You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

179 lines
3.9 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. <script lang="ts" context="module">
  2. const COLORS = [
  3. "none",
  4. "bronze",
  5. "silver",
  6. "gold",
  7. "emerald",
  8. "diamond"
  9. ]
  10. </script>
  11. <script lang="ts">
  12. export let target = 1;
  13. export let count = 0;
  14. export let green = false;
  15. export let thin = false;
  16. export let thinner = false;
  17. export let gray = false;
  18. export let titlePercentageOnly = false;
  19. export let titleTime = false;
  20. export let contextColor = false;
  21. let offClass = COLORS[0];
  22. let onClass = COLORS[1];
  23. let ons = 0;
  24. let offs = 1;
  25. let nonSegmented = false;
  26. let title = "";
  27. $: {
  28. if (target > 0) {
  29. let level = Math.floor(count / target);
  30. if (level >= COLORS.length - 1 || (level > 1 && green)) {
  31. offs = 0;
  32. ons = target;
  33. offClass = "gold";
  34. onClass = "diamond";
  35. } else {
  36. if (count > 0 && count == (level * target)) {
  37. level -= 1;
  38. }
  39. ons = count - (level * target);
  40. offs = target - ons;
  41. offClass = COLORS[level];
  42. onClass = COLORS[level + 1];
  43. }
  44. if (green) {
  45. onClass = "green"
  46. offClass = "none"
  47. }
  48. if (gray) {
  49. onClass = "gray"
  50. offClass = "none"
  51. }
  52. if (contextColor) {
  53. onClass = "sccpb"
  54. offClass = "none"
  55. }
  56. // Mark it non-segmented if the target is too high. This prevents a clunky progress bar,
  57. // or a browser freeze if you set the target very high.
  58. nonSegmented = (target >= 60);
  59. } else {
  60. offClass = "none";
  61. nonSegmented = false;
  62. ons = 0;
  63. offs = 1;
  64. }
  65. }
  66. $: {
  67. const percentage = ((count / target) * 100).toFixed(0);
  68. if (titlePercentageOnly) {
  69. title = `${percentage}%`;
  70. } else if (titleTime) {
  71. let unit = "days";
  72. let progressTime = (count / 86400000);
  73. let totaltTime = (target / 86400000);
  74. if (totaltTime < 1) {
  75. unit = "hours";
  76. totaltTime *= 24;
  77. progressTime *= 24;
  78. }
  79. title = `${progressTime.toFixed(1)} / ${totaltTime.toFixed(1)} ${unit} (${percentage}%)`;
  80. } else {
  81. title = `${count} / ${target} (${percentage}%)`
  82. }
  83. }
  84. </script>
  85. <div class="bar" title="{title}" class:thin class:thinner>
  86. {#if nonSegmented}
  87. {#if ons > 0}
  88. <div style="flex: {ons}" class={"non-segmented on " + onClass}></div>
  89. {/if}
  90. {#if offs > 0}
  91. <div style="flex: {offs}" class={"non-segmented off " + offClass}></div>
  92. {/if}
  93. {:else}
  94. {#each {length: Math.max(ons, 0)} as _}
  95. <div class={"on " + onClass}></div>
  96. {/each}
  97. {#each {length: Math.max(offs, 0)} as _}
  98. <div class={"off " + offClass}></div>
  99. {/each}
  100. {/if}
  101. </div>
  102. <style>
  103. div.bar {
  104. display: flex;
  105. flex-direction: row;
  106. margin: 0;
  107. box-sizing: border-box;
  108. width: 100%;
  109. height: 16px;
  110. margin: 0.5px 0;
  111. }
  112. div.bar > div {
  113. flex-grow: 1;
  114. flex-basis: 0;
  115. display: inline-block;
  116. box-sizing: border-box;
  117. margin: 0 0.5px;
  118. border: 0.25px solid #111;
  119. }
  120. div.non-segmented {
  121. flex-grow: inherit;
  122. flex-basis: inherit;
  123. }
  124. div.on {
  125. opacity: 0.75;
  126. }
  127. div.none { background-color: #555555; }
  128. div.bronze { background-color: #f4b083; }
  129. div.silver { background-color: #d8dce4; opacity: 0.8; }
  130. div.gold { background-color: #ffd966; opacity: 0.8; }
  131. div.diamond { background-color: #84f5ff; opacity: 0.9; }
  132. div.emerald, div.green { background-color: #8ef88e; opacity: 0.8; }
  133. div.gray { background-color: #777777; }
  134. div.off {
  135. opacity: 0.50;
  136. }
  137. div.bar.thin {
  138. height: 3px;
  139. }
  140. div.bar.thinner {
  141. height: 1px;
  142. }
  143. div.bar.thinner div {
  144. border-bottom: none;
  145. border-top: none;
  146. }
  147. div.bar.thinner div.none {
  148. background-color: #111111;
  149. }
  150. @media screen and (min-width: 1200) {
  151. div.bar div {
  152. margin: 1px 1px;
  153. }
  154. div.bar.thin {
  155. height: 4px;
  156. }
  157. div.bar.thinner {
  158. height: 4px;
  159. }
  160. }
  161. </style>