@mptw/skylens-ui 1.4.109 → 1.5.1

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