@mptw/skylens-ui 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/.editorconfig +12 -0
  2. package/.eslintrc.cjs +4 -0
  3. package/.nuxtrc +1 -0
  4. package/.playground/app.config.ts +5 -0
  5. package/.playground/nuxt.config.ts +3 -0
  6. package/README.md +73 -0
  7. package/app.config.ts +5 -0
  8. package/app.vue +3 -0
  9. package/assets/css/fonts/MEShPlus-font-icon.eot +0 -0
  10. package/assets/css/fonts/MEShPlus-font-icon.svg +186 -0
  11. package/assets/css/fonts/MEShPlus-font-icon.ttf +0 -0
  12. package/assets/css/fonts/MEShPlus-font-icon.woff +0 -0
  13. package/assets/css/icons.css +555 -0
  14. package/assets/css/layout.styl +98 -0
  15. package/assets/css/tailwind.css +3 -0
  16. package/assets/images/commons/app-logo-white.png +0 -0
  17. package/assets/images/commons/app-logo.png +0 -0
  18. package/assets/images/commons/empty-box.png +0 -0
  19. package/assets/images/commons/watermark.svg +15 -0
  20. package/components/SLAlertModal.vue +99 -0
  21. package/components/SLBreadcrumbs.vue +42 -0
  22. package/components/SLButton.vue +301 -0
  23. package/components/SLCalendarButton.vue +259 -0
  24. package/components/SLCalendarPopup.vue +832 -0
  25. package/components/SLCard.vue +118 -0
  26. package/components/SLChart.vue +181 -0
  27. package/components/SLCheckbox.vue +179 -0
  28. package/components/SLCircleButton.vue +95 -0
  29. package/components/SLCollapsableBlock.vue +116 -0
  30. package/components/SLCollapsableMulitPillSelect.vue +92 -0
  31. package/components/SLConfirmModal.vue +122 -0
  32. package/components/SLDateInput.vue +460 -0
  33. package/components/SLDatePicker.vue +143 -0
  34. package/components/SLDistributor.vue +30 -0
  35. package/components/SLDownloadButton.vue +410 -0
  36. package/components/SLDraggable.vue +151 -0
  37. package/components/SLDropdown.vue +277 -0
  38. package/components/SLDropdownItem.vue +31 -0
  39. package/components/SLElementWithTitle.vue +181 -0
  40. package/components/SLEyeCheckbox.vue +162 -0
  41. package/components/SLFileInput.vue +101 -0
  42. package/components/SLGenderAgeSelect.vue +279 -0
  43. package/components/SLHeatMap.vue +151 -0
  44. package/components/SLHourRangeInput.vue +211 -0
  45. package/components/SLIOSSwitch.vue +235 -0
  46. package/components/SLIcon.vue +35 -0
  47. package/components/SLIconButton.vue +130 -0
  48. package/components/SLInfoTip.vue +221 -0
  49. package/components/SLInsightSitePage.vue +27 -0
  50. package/components/SLLegend.vue +76 -0
  51. package/components/SLLinearProgressBar.vue +35 -0
  52. package/components/SLLink.vue +162 -0
  53. package/components/SLLoading.vue +127 -0
  54. package/components/SLMapChart.vue +151 -0
  55. package/components/SLModal.vue +377 -0
  56. package/components/SLMonthCalendarButton.vue +378 -0
  57. package/components/SLMonthPicker.vue +151 -0
  58. package/components/SLMultiSelect.vue +121 -0
  59. package/components/SLNoData.vue +43 -0
  60. package/components/SLPageModal.vue +64 -0
  61. package/components/SLPagination.vue +192 -0
  62. package/components/SLPillCheckbox.vue +207 -0
  63. package/components/SLPillLabel.vue +101 -0
  64. package/components/SLPopupMenuButton.vue +158 -0
  65. package/components/SLProfileButton.vue +186 -0
  66. package/components/SLRadioButton.vue +97 -0
  67. package/components/SLRadioButtonGroup.vue +113 -0
  68. package/components/SLRadioGroup.vue +201 -0
  69. package/components/SLRangeInput.vue +209 -0
  70. package/components/SLRegionsMapChart.vue +151 -0
  71. package/components/SLRightSider.vue +242 -0
  72. package/components/SLSearchInput.vue +87 -0
  73. package/components/SLSelect.vue +545 -0
  74. package/components/SLSelectAllToggle.vue +118 -0
  75. package/components/SLSiderbarNav.vue +394 -0
  76. package/components/SLSiderbarNavItem.vue +204 -0
  77. package/components/SLSitePage.vue +96 -0
  78. package/components/SLSkyInsightSitePage.vue +27 -0
  79. package/components/SLSortByDropdown.vue +189 -0
  80. package/components/SLSpinIcon.vue +24 -0
  81. package/components/SLStayRangeInput.vue +306 -0
  82. package/components/SLTab.vue +159 -0
  83. package/components/SLTable.vue +409 -0
  84. package/components/SLTableTooltip.vue +111 -0
  85. package/components/SLTabs.vue +388 -0
  86. package/components/SLTextInput.vue +362 -0
  87. package/components/SLTextarea.vue +134 -0
  88. package/components/SLToast.vue +71 -0
  89. package/components/SLToggleButton.vue +78 -0
  90. package/components/SLTwoLayerMultiSelect.vue +428 -0
  91. package/components/SLTwoLayerSelect.vue +265 -0
  92. package/components/SLWarnModal.vue +75 -0
  93. package/interface/IDateRange.ts +5 -0
  94. package/interface/IHourRange.ts +4 -0
  95. package/interface/IInputOption.ts +6 -0
  96. package/interface/ILegendItem.ts +7 -0
  97. package/interface/IPopupMenuButton.ts +5 -0
  98. package/interface/IStayRange.ts +15 -0
  99. package/interface/ITableField.ts +19 -0
  100. package/interface/IWeb.ts +5 -0
  101. package/interface/NavConfigType.ts +14 -0
  102. package/interface/commons.ts +7 -0
  103. package/models/DateRange.ts +21 -0
  104. package/nuxt.config.ts +22 -0
  105. package/package.json +52 -0
  106. package/plugins/googlemaps.ts +17 -0
  107. package/plugins/v-calendar.ts +5 -0
  108. package/public/assets/files/taiwan-regions.json +7 -0
  109. package/public/assets/files/taiwan.json +24 -0
  110. package/public/assets/images/commons/default-favico.png +0 -0
  111. package/public/assets/images/dashboard/closure-button-icon.png +0 -0
  112. package/public/assets/images/dashboard/dashboard-widget-bar-chart-icon-disabled.png +0 -0
  113. package/public/assets/images/dashboard/dashboard-widget-bar-chart-icon-poi.png +0 -0
  114. package/public/assets/images/dashboard/dashboard-widget-bar-chart-icon-web.png +0 -0
  115. package/public/assets/images/dashboard/dashboard-widget-country-heatmap-chart-icon-disabled.png +0 -0
  116. package/public/assets/images/dashboard/dashboard-widget-country-heatmap-chart-icon.png +0 -0
  117. package/public/assets/images/dashboard/dashboard-widget-geo-list-icon-disabled.png +0 -0
  118. package/public/assets/images/dashboard/dashboard-widget-geo-list-icon-poi.png +0 -0
  119. package/public/assets/images/dashboard/dashboard-widget-geo-list-icon-web.png +0 -0
  120. package/public/assets/images/dashboard/dashboard-widget-heatmap-chart-icon-disabled.png +0 -0
  121. package/public/assets/images/dashboard/dashboard-widget-heatmap-chart-icon-web.png +0 -0
  122. package/public/assets/images/dashboard/dashboard-widget-line-chart-icon-disabled.png +0 -0
  123. package/public/assets/images/dashboard/dashboard-widget-line-chart-icon-poi.png +0 -0
  124. package/public/assets/images/dashboard/dashboard-widget-list-icon-disabled.png +0 -0
  125. package/public/assets/images/dashboard/dashboard-widget-list-icon-poi.png +0 -0
  126. package/public/assets/images/dashboard/dashboard-widget-list-icon-web.png +0 -0
  127. package/public/assets/images/dashboard/dashboard-widget-pie-chart-icon-disabled.png +0 -0
  128. package/public/assets/images/dashboard/dashboard-widget-pie-chart-icon-poi.png +0 -0
  129. package/public/assets/images/dashboard/dashboard-widget-pie-chart-icon-web.png +0 -0
  130. package/public/assets/images/dashboard/drag-hint-icon.svg +3 -0
  131. package/public/assets/images/dashboard/extend-button-icon.png +0 -0
  132. package/public/assets/images/dashboard/map-list-chart-icon.svg +17 -0
  133. package/public/assets/images/dashboard/map-marker-chart-icon.svg +32 -0
  134. package/public/assets/images/dashboard/pie-chart-icon.svg +4 -0
  135. package/public/assets/images/dashboard/poi-gender-age-chart-icon.svg +20 -0
  136. package/public/assets/images/dashboard/poi-nav-icon.png +0 -0
  137. package/public/assets/images/dashboard/web-gender-age-chart-icon.svg +20 -0
  138. package/public/assets/images/dashboard/web-nav-icon.png +0 -0
  139. package/tailwind.config.js +300 -0
  140. package/tsconfig.json +8 -0
  141. package/utils/constants.ts +160 -0
  142. package/utils/generateSheet.ts +36 -0
  143. package/utils/index.ts +539 -0
@@ -0,0 +1,409 @@
1
+ <template lang="pug">
2
+ div(ref="el")
3
+ .table(
4
+ :class="{ 'table-responsive': responsive }"
5
+ @mousemove="onMousemoved"
6
+ )
7
+ table
8
+ thead
9
+ slot(name="thead")
10
+ tr
11
+ template(v-for="field, index in fields")
12
+ slot(
13
+ v-if="$slots[`${field.key}-header`]"
14
+ :name="`${field.key}-header`"
15
+ :field="field"
16
+ :index="index"
17
+ )
18
+ th(
19
+ v-else
20
+ :style="field._style"
21
+ :class="[field._class, { sortable: field.sortable, sorting: field.key === sortBy, filterable: field.filterable, filtering: filterBy !== '' }]"
22
+ :colspan="headerColumnSpans[index]"
23
+ @click.prevent="onClickedHeaderCol(field.key)"
24
+ :key="field.key"
25
+ :name="`${field.key}-header`"
26
+ )
27
+ .inline-flex.items-center
28
+ SLElementWithTitle(:title="field.tooltip")
29
+ span {{ field.label ? field.label : '&nbsp;' }}
30
+ SLIcon.sort-icon(
31
+ v-if="field.sortable"
32
+ class="ml-0.5"
33
+ :icon="sortDesc ? 'descending' : 'ascending'"
34
+ )
35
+ SLIcon.filter-icon(
36
+ v-if="field.filterable"
37
+ class="ml-0.5"
38
+ :icon="filterBy !== '' ? 'filter-on' : 'filter'"
39
+ )
40
+ tbody(:class="{ 'hoverable': hoverableRows, 'clickable': clickableRows }")
41
+ template(v-for="(item, itemIndex) in items" :key="itemIndex")
42
+ tr(
43
+ @click="rowClicked(item, itemIndex, $event)"
44
+ @mouseenter="rowMouseEntered(item, itemIndex, $event)"
45
+ @mouseleave="rowMouseLeaved(item, itemIndex, $event)"
46
+ :tabindex="clickableRows ? 0 : undefined"
47
+ :class="[hoverableRows ? `hover:${tdHoverColor}` : '', `${hoverRowIndex === itemIndex ? tdHoverColor : ''}`, { hover: hoverRowIndex === itemIndex }]"
48
+ )
49
+ template(v-for="(field, index) in fields")
50
+ slot(
51
+ v-if="$slots[field.key]"
52
+ :name="field.key"
53
+ :item="item"
54
+ :index="itemIndex"
55
+ ).border-border
56
+ td(
57
+ v-else
58
+ :colspan="columnSpans[index]"
59
+ :key="`${itemIndex}-${field.key}`"
60
+ :class='tdBorderColor'
61
+ ) {{ item[field.key] }}
62
+ tr(v-if="items.length === 0")
63
+ td(:colspan="fields.length")
64
+ div(v-if="loading", style="min-height: 200px")
65
+ .flex.flex-col.items-center.py-8.px-4.space-y-3(v-else)
66
+ img(src="images/commons/empty-box.png")
67
+ .text-lg.text-primary-light {{ noItems }}
68
+ .text-sm.text-gray-3(v-if="reason") 可能的原因:{{ reason }}
69
+ SLLoading(
70
+ v-if="loading"
71
+ :boundaries="[{ sides: ['top'], query: 'td' }, { sides: ['bottom'], query: 'tbody' }]"
72
+ )
73
+ .table-header-filter-popup(ref="popupEl")
74
+ .table-header-filter-popup-content
75
+ a.table-header-filter-item(
76
+ v-for="option in filterOptions"
77
+ href="javascript:;"
78
+ :class="{ active: filterBy === option.key }"
79
+ :key="option.key"
80
+ @click="onClickedFilter(option.key)"
81
+ )
82
+ .inline-flex.items-center.space-x-1
83
+ SLIcon(
84
+ v-if="option.icon"
85
+ :icon="option.icon"
86
+ :class="option._iconClass"
87
+ )
88
+ span(v-if="option.label") {{ option.label }}
89
+ </template>
90
+
91
+ <script lang="ts">
92
+ import type { PropType } from "vue";
93
+ import { fromEvent, Subscription } from "rxjs";
94
+ import { createPopper } from "@popperjs/core";
95
+ import type { Instance as PopperInstance } from "@popperjs/core";
96
+ import type ITableField from "~ui/interface/ITableField";
97
+
98
+ export default defineComponent({
99
+ name: "SLTable",
100
+ components: {},
101
+ props: {
102
+ items: {
103
+ type: Array,
104
+ default: () => [],
105
+ },
106
+ fields: {
107
+ type: Array as PropType<Array<ITableField>>,
108
+ default: () => [],
109
+ },
110
+ sortBy: {
111
+ type: String,
112
+ default: "",
113
+ },
114
+ sortDesc: {
115
+ type: Boolean,
116
+ default: false,
117
+ },
118
+ filterBy: {
119
+ type: String,
120
+ default: "",
121
+ },
122
+ hoverableRows: {
123
+ type: Boolean,
124
+ default: false,
125
+ },
126
+ clickableRows: {
127
+ type: Boolean,
128
+ default: false,
129
+ },
130
+ loading: {
131
+ type: Boolean,
132
+ default: false,
133
+ },
134
+ responsive: {
135
+ type: Boolean,
136
+ default: true,
137
+ },
138
+ tdBorderColor: {
139
+ type: String,
140
+ default: "border-border",
141
+ },
142
+ tdHoverColor: {
143
+ type: String,
144
+ default: "bg-bg",
145
+ },
146
+ noItems: {
147
+ type: String,
148
+ default: "無資料",
149
+ },
150
+ reason: {
151
+ type: String,
152
+ default: "",
153
+ },
154
+ },
155
+ emits: [
156
+ "update:sortDesc",
157
+ "update:sortBy",
158
+ "update:filterBy",
159
+ "row-clicked",
160
+ "row-mouseentered",
161
+ "row-mouseleaved",
162
+ "table-mousemoved",
163
+ ],
164
+ setup(props, { emit }) {
165
+ const { fields, sortBy, sortDesc, clickableRows, hoverableRows } =
166
+ toRefs(props);
167
+
168
+ const el = shallowRef<HTMLElement | null>(null);
169
+ const popupEl = shallowRef<HTMLElement | null>(null);
170
+ const hoverRowIndex = ref(-1);
171
+ const filterOptions = ref<
172
+ {
173
+ key: string;
174
+ label?: string;
175
+ icon?: string;
176
+ }[]
177
+ >([]);
178
+
179
+ let popperInstance: PopperInstance | null = null;
180
+ let clickSubscriber: Subscription | null = null;
181
+ let filterHeaderCol: HTMLElement | null = null;
182
+
183
+ const headerColumnSpans = computed(() => {
184
+ return fields.value.map((field) => {
185
+ if (!field.colspan) return 1;
186
+ return field.colspan;
187
+ });
188
+ });
189
+ const columnSpans = computed(() => {
190
+ return fields.value.map((field) => {
191
+ if (!field.col) return 1;
192
+ if (!field.col.span) return 1;
193
+ return field.col.span;
194
+ });
195
+ });
196
+
197
+ function sort(fieldKey: string) {
198
+ if (fieldKey === sortBy.value) {
199
+ emit("update:sortDesc", !sortDesc.value);
200
+ } else {
201
+ emit("update:sortBy", fieldKey);
202
+ }
203
+ }
204
+
205
+ function onClickedHeaderCol(fieldKey: string) {
206
+ const field = fields.value.find((f) => f.key === fieldKey);
207
+ if (!field || (!field.sortable && !field.filterable)) return;
208
+
209
+ if (field.sortable) {
210
+ sort(field.key);
211
+ }
212
+
213
+ if (field.filterable) {
214
+ filterOptions.value = [...field.filterOptions];
215
+ filterHeaderCol = el.value.querySelector(`th[name=${field.key}-header]`)
216
+ .children[0] as HTMLElement;
217
+ show();
218
+ }
219
+ }
220
+
221
+ function rowClicked(item: any, index: number, e: Event) {
222
+ if (!clickableRows.value) return;
223
+
224
+ emit("row-clicked", item, index, e);
225
+ e.preventDefault();
226
+ }
227
+
228
+ function rowMouseEntered(item: any, index: number, e: Event) {
229
+ if (!hoverableRows.value) return;
230
+
231
+ hoverRowIndex.value = index;
232
+ emit("row-mouseentered", item, index, e);
233
+ }
234
+
235
+ function rowMouseLeaved(item: any, index: number, e: Event) {
236
+ if (!hoverableRows.value) return;
237
+
238
+ hoverRowIndex.value = -1;
239
+ emit("row-mouseleaved", item, index, e);
240
+ }
241
+
242
+ function onMousemoved(e: Event) {
243
+ if (!hoverableRows.value) return;
244
+
245
+ emit("table-mousemoved", e);
246
+ }
247
+
248
+ function subscribeClick() {
249
+ clickSubscriber = fromEvent(window, "click").subscribe((e) => {
250
+ const { target } = e;
251
+ if (
252
+ filterHeaderCol &&
253
+ popupEl.value &&
254
+ !filterHeaderCol.contains(target as HTMLElement) &&
255
+ !popupEl.value.contains(target as HTMLElement)
256
+ ) {
257
+ hide();
258
+ }
259
+ });
260
+ }
261
+
262
+ function unsubscribeClick() {
263
+ if (clickSubscriber) {
264
+ clickSubscriber.unsubscribe();
265
+ }
266
+ clickSubscriber = null;
267
+ }
268
+
269
+ function show() {
270
+ if (!popupEl.value || !filterHeaderCol || !popperInstance) return;
271
+
272
+ popupEl.value.setAttribute("data-show", "");
273
+
274
+ subscribeClick();
275
+ popperInstance.state.elements.reference = filterHeaderCol;
276
+ popperInstance.setOptions({
277
+ modifiers: [
278
+ {
279
+ name: "offset",
280
+ options: {
281
+ offset: [0, 4],
282
+ },
283
+ },
284
+ { name: "eventListeners", enabled: true },
285
+ ],
286
+ });
287
+ popperInstance.update();
288
+ }
289
+
290
+ function hide() {
291
+ if (
292
+ !popupEl.value ||
293
+ popupEl.value.getAttribute("data-show") === null ||
294
+ !popperInstance
295
+ )
296
+ return;
297
+
298
+ unsubscribeClick();
299
+
300
+ if (popupEl.value) {
301
+ popupEl.value.removeAttribute("data-show");
302
+ }
303
+
304
+ popperInstance.setOptions({
305
+ modifiers: [{ name: "eventListeners", enabled: false }],
306
+ });
307
+ }
308
+
309
+ function onClickedFilter(filterKey: string) {
310
+ emit("update:filterBy", filterKey);
311
+ hide();
312
+ }
313
+
314
+ onMounted(() => {
315
+ if (el.value && popupEl.value) {
316
+ popperInstance = createPopper(el.value, popupEl.value, {
317
+ placement: "bottom-end",
318
+ modifiers: [{ name: "eventListeners", enabled: false }],
319
+ });
320
+ }
321
+ });
322
+
323
+ onBeforeUnmount(() => {
324
+ if (popperInstance) {
325
+ popperInstance.destroy();
326
+ }
327
+ popperInstance = null;
328
+ });
329
+
330
+ return {
331
+ el,
332
+ popupEl,
333
+ hoverRowIndex,
334
+ filterOptions,
335
+ headerColumnSpans,
336
+ columnSpans,
337
+ onClickedHeaderCol,
338
+ rowClicked,
339
+ rowMouseEntered,
340
+ rowMouseLeaved,
341
+ onMousemoved,
342
+ onClickedFilter,
343
+ };
344
+ },
345
+ });
346
+ </script>
347
+
348
+ <style lang="stylus">
349
+ .table
350
+ @apply block relative w-full overflow-hidden
351
+
352
+ &.table-responsive
353
+ @apply overflow-auto
354
+
355
+ table
356
+ @apply table-auto
357
+
358
+ table
359
+ @apply w-full table-fixed
360
+
361
+ thead
362
+ tr
363
+ @apply border-b border-primary-light bg-white
364
+
365
+ th
366
+ @apply px-2 pb-2 text-sm font-normal text-primary whitespace-nowrap
367
+ &.sortable, &.filterable
368
+ @apply cursor-pointer
369
+ .sort-icon, .filter-icon
370
+ @apply opacity-0
371
+ &:hover,
372
+ &.sorting
373
+ .sort-icon
374
+ @apply opacity-100
375
+ &.filterable
376
+ .filter-icon
377
+ @apply opacity-100
378
+
379
+ tbody
380
+ &.clickable
381
+ tr
382
+ @apply cursor-pointer
383
+
384
+ tr
385
+ td
386
+ @apply p-2 border-b text-sm text-gray-2
387
+
388
+ .table-header-filter-popup
389
+ @apply z-10 flex border border-primary-light rounded overflow-hidden invisible pointer-events-none
390
+
391
+ &[data-show]
392
+ @apply visible pointer-events-auto
393
+
394
+ &-content
395
+ @apply flex flex-col
396
+
397
+ .table-header-filter-item
398
+ @apply inline-flex justify-center p-2 bg-white text-sm text-gray-3
399
+ @apply s('hover:bg-bg-middle')
400
+
401
+ &.active
402
+ @apply bg-bg text-primary
403
+
404
+ .icon
405
+ @apply text-primary
406
+
407
+ .icon
408
+ @apply text-base leading-none
409
+ </style>
@@ -0,0 +1,111 @@
1
+ <template lang="pug">
2
+ .table-tooltip
3
+ .table-tooltip-header
4
+ .table-tooltip-title {{ title }}
5
+ .table-tooltip-caption(v-if="caption && caption !== ''") {{ caption }}
6
+ .table-tooltip-body
7
+ .table-toottip-table
8
+ table
9
+ tbody
10
+ template(v-for="item, index in items")
11
+ tr(v-if="formatedDateRanges[index]").date-row
12
+ td(
13
+ colspan="3"
14
+ :class="{'text-gray-3': index + 1 < 2, 'text-primary': index + 1 > 1}"
15
+ ) {{ formatedDateRanges[index] }}
16
+ tr.header-row(:class='headerBorderColor')
17
+ th(v-for="field in fields" :key="field.key") {{ field.label }}
18
+ tr
19
+ td(v-for="field in fields" :key="field.key") {{ item[field.key] }}
20
+ </template>
21
+
22
+ <script lang="ts">
23
+ import type { PropType } from "vue";
24
+ import { formatDateRange } from "~ui/utils";
25
+ import type IDateRange from "~ui/interface/IDateRange";
26
+ import type ITableField from "~ui/interface/ITableField";
27
+
28
+ export default defineComponent({
29
+ name: "SLTableTooltip",
30
+ components: {},
31
+ props: {
32
+ title: {
33
+ type: String,
34
+ default: "",
35
+ },
36
+ caption: {
37
+ type: String,
38
+ default: "",
39
+ },
40
+ dateRanges: {
41
+ type: Array as PropType<Array<IDateRange | null>>,
42
+ default: () => [],
43
+ },
44
+ items: {
45
+ type: Array as PropType<{ [key: string]: any }[]>,
46
+ default: () => [],
47
+ },
48
+ fields: {
49
+ type: Array as PropType<Array<ITableField>>,
50
+ default: () => [],
51
+ },
52
+ headerBorderColor: {
53
+ type: String,
54
+ default: "border-primary-light",
55
+ },
56
+ },
57
+ setup(props) {
58
+ const { dateRanges } = toRefs(props);
59
+
60
+ const formatedDateRanges = computed(() => {
61
+ if (dateRanges.value.length < 2) return [];
62
+
63
+ return dateRanges.value.map((dateRange) => formatDateRange(dateRange));
64
+ });
65
+
66
+ return {
67
+ formatedDateRanges,
68
+ };
69
+ },
70
+ });
71
+ </script>
72
+
73
+ <style lang="stylus">
74
+ .table-tooltip
75
+ @apply inline-block p-4 border border-border rounded bg-white shadow-popup-sm pointer-events-none
76
+
77
+ &-title
78
+ @apply mb-4 text-base text-gray-2 font-bold
79
+
80
+ &:not(:last-child)
81
+ @apply mb-1
82
+
83
+ &-caption
84
+ @apply mb-2 text-sm text-gray-2
85
+
86
+ table
87
+ @apply w-full text-base text-gray-2
88
+
89
+ tbody
90
+ tr
91
+ &.date-row
92
+ @apply text-gray-3
93
+
94
+ td
95
+ @apply pt-4
96
+
97
+ &:first-child
98
+ @apply text-primary
99
+
100
+ td
101
+ @apply pt-0
102
+
103
+ td, th
104
+ @apply text-left
105
+
106
+ &.header-row
107
+ @apply border-b
108
+
109
+ td, th
110
+ @apply py-1 px-3 text-center
111
+ </style>