quasar-ui-sellmate-ui-kit 3.11.1 → 3.11.2

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 (84) hide show
  1. package/.eslintrc.cjs +104 -104
  2. package/.prettierrc +25 -25
  3. package/README.md +156 -156
  4. package/dist/index.common.js +2 -2
  5. package/dist/index.css +1 -1
  6. package/dist/index.esm.js +2 -2
  7. package/dist/index.min.css +1 -1
  8. package/dist/index.rtl.css +1 -1
  9. package/dist/index.rtl.min.css +1 -1
  10. package/dist/index.umd.js +4417 -4405
  11. package/dist/index.umd.min.js +2 -2
  12. package/html/assets/index-iPSQW1bz.css +1 -1
  13. package/html/assets/index-pzCGhZhc.js +35 -35
  14. package/html/favicon.svg +5 -5
  15. package/html/index.html +26 -26
  16. package/package.json +95 -95
  17. package/src/assets/icons.js +63 -63
  18. package/src/components/SBadge.vue +75 -75
  19. package/src/components/SButton.vue +206 -206
  20. package/src/components/SButtonGroup.vue +41 -41
  21. package/src/components/SButtonToggle.vue +200 -200
  22. package/src/components/SCaution.vue +143 -143
  23. package/src/components/SCheckbox.vue +123 -123
  24. package/src/components/SChip.vue +99 -99
  25. package/src/components/SDate.vue +664 -664
  26. package/src/components/SDateAutoRangePicker.vue +311 -311
  27. package/src/components/SDatePicker.vue +465 -465
  28. package/src/components/SDateRange.vue +382 -382
  29. package/src/components/SDateRangePicker.vue +582 -582
  30. package/src/components/SDateTimePicker.vue +259 -259
  31. package/src/components/SDialog.vue +250 -250
  32. package/src/components/SDropdown.vue +273 -273
  33. package/src/components/SEditor.vue +590 -590
  34. package/src/components/SFilePicker.vue +207 -207
  35. package/src/components/SHelp.vue +126 -126
  36. package/src/components/SHelpMessage.vue +57 -57
  37. package/src/components/SInput.vue +379 -379
  38. package/src/components/SInputCounter.vue +46 -46
  39. package/src/components/SInputNumber.vue +194 -194
  40. package/src/components/SList.vue +29 -29
  41. package/src/components/SMarkupTable.vue +142 -142
  42. package/src/components/SPagination.vue +345 -345
  43. package/src/components/SRadio.vue +78 -78
  44. package/src/components/SRouteTab.vue +67 -67
  45. package/src/components/SSelect.vue +299 -299
  46. package/src/components/SSelectCheckbox.vue +238 -238
  47. package/src/components/SSelectCustom.vue +189 -189
  48. package/src/components/SSelectGroupCheckbox.vue +372 -372
  49. package/src/components/SSelectSearchAutoComplete.vue +172 -172
  50. package/src/components/SSelectSearchCheckbox.vue +360 -360
  51. package/src/components/SStringToInput.vue +66 -66
  52. package/src/components/STab.vue +147 -147
  53. package/src/components/STable.vue +21 -9
  54. package/src/components/STableTree.vue +502 -502
  55. package/src/components/STabs.vue +32 -32
  56. package/src/components/STag.vue +152 -152
  57. package/src/components/STimePicker.vue +186 -186
  58. package/src/components/SToggle.vue +68 -68
  59. package/src/components/STooltip.vue +209 -209
  60. package/src/components/SYearMonthPicker.vue +211 -211
  61. package/src/components/SelelctItem.vue +21 -21
  62. package/src/components/TableTreeNode.vue +177 -177
  63. package/src/components/TimePickerCard.vue +393 -393
  64. package/src/components/__tests__/SButton.test.js +18 -18
  65. package/src/components/__tests__/SInput.test.js +42 -42
  66. package/src/components/__tests__/SInputCounter.test.js +30 -30
  67. package/src/components/__tests__/SInputNumber.test.js +32 -32
  68. package/src/components/__tests__/STimePicker.spec.js +78 -78
  69. package/src/composables/date.js +11 -11
  70. package/src/composables/modelBinder.js +13 -13
  71. package/src/composables/resizable.js +55 -55
  72. package/src/composables/table/use-navigator.js +110 -110
  73. package/src/composables/table/use-resizable-tree.js +96 -96
  74. package/src/composables/table/use-resizable.js +187 -187
  75. package/src/constants/locale.js +102 -102
  76. package/src/css/app.scss +106 -106
  77. package/src/css/default.scss +393 -393
  78. package/src/css/extends.scss +177 -177
  79. package/src/css/quasar.variables.scss +187 -187
  80. package/src/directives/Directive.js +7 -7
  81. package/src/index.scss +3 -3
  82. package/src/vue-plugin.js +93 -93
  83. package/tsconfig.json +35 -35
  84. package/vitest.config.ts +31 -31
@@ -1,502 +1,502 @@
1
- <template>
2
- <div
3
- class="s-table-tree bg-white"
4
- :class="{
5
- 'sticky-table-tree': isStickyFirstColumn,
6
- 'loading-table-tree': loading,
7
- 'no-data-table-tree': !rows.length,
8
- }"
9
- ref="sTableTreeRef"
10
- >
11
- <slot name="loading" v-if="loading">
12
- <q-inner-loading showing color="positive" size="72px" />
13
- </slot>
14
-
15
- <div class="s-table-tree__inner" ref="scrollLocationRef" @scroll="handleScroll">
16
- <table>
17
- <thead>
18
- <tr>
19
- <th
20
- v-for="(column, idx) in columns"
21
- :key="column.name"
22
- :class="`td-${idx + 1} text-${column.align}`"
23
- :style="`width: ${column.width}px`"
24
- >
25
- <slot :name="`header-cell-${column.name}`">
26
- {{ column.label }}
27
- </slot>
28
- </th>
29
- </tr>
30
- </thead>
31
-
32
- <tbody v-if="!rows.length">
33
- <tr>
34
- <td :colspan="columns.length">
35
- <div>
36
- <slot name="no-data">
37
- {{ noDataLabel }}
38
- </slot>
39
- </div>
40
- </td>
41
- </tr>
42
- </tbody>
43
-
44
- <tbody v-else>
45
- <slot name="body">
46
- <tr v-if="rows.length > 0">
47
- <td :colspan="columns.length" class="body-td">
48
- <table-tree-node
49
- v-for="(row, i) in treeDataSource"
50
- :key="i"
51
- :nodeName="`root_node_${i}`"
52
- :row="row"
53
- :columns="columns"
54
- :colspan="columns.length"
55
- :resizedWidths="resizedWidths"
56
- ref="childTableNode"
57
- @handleExpand="node => handleExpand(row, node)"
58
- >
59
- <template
60
- v-for="column in columns"
61
- :key="column.name"
62
- #[`body-cell-${column.name}`]="row"
63
- >
64
- <slot :name="`body-cell-${column.name}`" v-bind="row"></slot>
65
- </template>
66
- </table-tree-node>
67
- </td>
68
- </tr>
69
- </slot>
70
- </tbody>
71
-
72
- <tfoot v-if="foots.length > 0 && rows.length > 0">
73
- <slot name="tfoot">
74
- <tr v-for="(f, i) in foots" :key="i" :class="`tr-${i + 1}`">
75
- <td
76
- v-for="(col, colIdx) in columns"
77
- :key="col.name"
78
- :class="`td-${colIdx + 1} text-${col.align}`"
79
- >
80
- <slot :name="`body-cell-${col.name}`">
81
- <span v-if="col.prefix" class="q-mr-xs">{{ col.prefix }}</span>
82
- {{ f[col.name] }}
83
- <span v-if="col.suffix" class="q-ml-xs">{{ col.suffix }}</span>
84
- </slot>
85
- </td>
86
- </tr>
87
- </slot>
88
- </tfoot>
89
- </table>
90
- </div>
91
- </div>
92
- </template>
93
-
94
- <script>
95
- import { defineComponent, ref, onMounted, nextTick, watch } from 'vue';
96
- import { QInnerLoading } from 'quasar';
97
- import TableTreeNode from './TableTreeNode.vue';
98
- import { useResizableTree } from '../composables/table/use-resizable-tree';
99
-
100
- function setWidthForExpand(tableNodeRef, resizedWidths) {
101
- const tableElements = tableNodeRef.querySelectorAll('table');
102
-
103
- tableElements.forEach(tableElement => {
104
- const rows = tableElement.querySelectorAll('tr');
105
- rows.forEach(row => {
106
- const cols = row.children;
107
- for (let i = 0; i < cols.length; i++) {
108
- if (resizedWidths[i] !== undefined) {
109
- cols[i].style.minWidth = `${resizedWidths[i]}px`;
110
- cols[i].style.width = `${resizedWidths[i]}px`;
111
- }
112
- }
113
- });
114
- });
115
- }
116
-
117
- export default defineComponent({
118
- name: 'STableTree',
119
- components: { TableTreeNode, QInnerLoading },
120
- props: {
121
- columns: {
122
- type: Array,
123
- default: () => [],
124
- },
125
- rows: {
126
- type: Array,
127
- default: () => [],
128
- },
129
- foots: {
130
- type: Array,
131
- default: () => [],
132
- },
133
- noDataLabel: {
134
- type: String,
135
- default: '데이터 조회가 필요합니다',
136
- },
137
- loading: {
138
- type: Boolean,
139
- default: false,
140
- },
141
- isStickyFirstColumn: {
142
- tpye: Boolean,
143
- default: true,
144
- },
145
- resizable: {
146
- type: Boolean,
147
- default: false,
148
- },
149
- stickyResizable: {
150
- type: [Array, Number],
151
- required: false,
152
- },
153
- },
154
- setup(props, { emit }) {
155
- const treeDataSource = ref([]);
156
- const sTableTreeRef = ref(null);
157
- const resizedWidths = ref({});
158
- const scrollLocationRef = ref(null);
159
-
160
- function handleScroll() {
161
- const { scrollLeft } = scrollLocationRef.value;
162
-
163
- if (scrollLeft === 0) {
164
- scrollLocationRef.value.classList.add('no-before');
165
- } else {
166
- scrollLocationRef.value.classList.remove('no-before');
167
- }
168
- }
169
-
170
- function initTreeData() {
171
- const tempData = props.rows;
172
- const reduceDataFunc = (data, level) => {
173
- data.forEach(m => {
174
- m.isExpand = m.isExpand || false;
175
- m.children = m.children || [];
176
- m.level = level;
177
- m.leftPadding = level === 1 ? 20 : (level - 1) * 28 + 20;
178
- m.meta = {
179
- isLastDepth: m.meta.isLastDepth || false,
180
- };
181
- if (m.children.length > 0) {
182
- reduceDataFunc(m.children, level + 1);
183
- }
184
-
185
- nextTick(() => {
186
- setWidthForExpand(sTableTreeRef.value, resizedWidths.value);
187
- });
188
- });
189
- };
190
- reduceDataFunc(tempData, 1);
191
- treeDataSource.value = tempData;
192
- }
193
- initTreeData();
194
-
195
- function handleExpand(parentRow, row) {
196
- row.isExpand = !row.isExpand;
197
- if (row.isExpand) emit('handleExpand', parentRow, row);
198
-
199
- nextTick(() => {
200
- setWidthForExpand(sTableTreeRef.value, resizedWidths.value);
201
- });
202
- }
203
-
204
- const { addResizable } = useResizableTree();
205
- function handleColumnResizable() {
206
- if (props.resizable || props.isStickyFirstColumn) {
207
- resizedWidths.value = addResizable(sTableTreeRef.value, props.columns);
208
- }
209
- }
210
-
211
- onMounted(() => {
212
- handleColumnResizable();
213
- scrollLocationRef.value.classList.add('no-before');
214
- });
215
-
216
- watch(
217
- () => props.columns,
218
- () => {
219
- nextTick(() => {
220
- handleColumnResizable();
221
- });
222
- },
223
- { deep: true },
224
- );
225
-
226
- watch(
227
- () => props.rows,
228
- () => {
229
- initTreeData();
230
- },
231
- { deep: true },
232
- );
233
-
234
- watch(
235
- () => treeDataSource.value,
236
- () => {
237
- emit('update:model-value', treeDataSource.value);
238
- },
239
- { deep: true },
240
- );
241
-
242
- return {
243
- treeDataSource,
244
- handleExpand,
245
- handleScroll,
246
- sTableTreeRef,
247
- scrollLocationRef,
248
- resizedWidths,
249
- };
250
- },
251
- });
252
- </script>
253
-
254
- <style scoped lang="scss">
255
- @import '../css/quasar.variables.scss';
256
- @import '../css/extends.scss';
257
-
258
- .s-table-tree {
259
- border: 1px solid $Grey_Lighten-2;
260
- border-radius: 8px !important;
261
- overflow: hidden;
262
- position: relative;
263
- box-sizing: border-box;
264
- color: $Grey_Darken-5;
265
- .q-inner-loading {
266
- z-index: 1;
267
- }
268
- .s-table-tree__inner {
269
- overflow: auto;
270
- td,
271
- th {
272
- width: 100%;
273
- &:not(:first-of-type) {
274
- word-break: keep-all;
275
- white-space: nowrap;
276
- text-overflow: ellipsis;
277
- overflow: hidden;
278
- }
279
- }
280
- table {
281
- width: 100%;
282
- border-collapse: collapse;
283
- border-spacing: 0;
284
- table-layout: fixed;
285
- thead {
286
- background: $th-bg;
287
- tr {
288
- height: 36px;
289
- th {
290
- border-bottom: 1px solid $Grey-Lighten-3;
291
- padding: 0 16px;
292
- font-weight: 500;
293
- color: rgba(34, 34, 34, 1);
294
- }
295
- }
296
- }
297
- tbody {
298
- > tr {
299
- td {
300
- height: 44px;
301
- }
302
- > .body-td {
303
- padding: 0;
304
- }
305
- }
306
- }
307
- tfoot {
308
- border-top: 2px solid $Grey_Lighten-3 !important;
309
- tr {
310
- &:last-of-type {
311
- background: rgba(245, 250, 255, 1);
312
- .td-1 {
313
- color: $Blue_B_Lighten-2;
314
- }
315
- }
316
- td {
317
- border-top: 1px solid $Grey_Lighten-3 !important;
318
- height: 52px;
319
- padding: 0 16px;
320
- &.td-1 {
321
- padding: 0 20px;
322
- font-weight: 700;
323
- color: $Blue_C_Darken-1;
324
- }
325
- }
326
- }
327
- }
328
- }
329
- }
330
-
331
- &.sticky-table-tree {
332
- .s-table-tree__inner {
333
- td,
334
- th {
335
- width: 100%;
336
- &:not(:first-of-type) {
337
- word-break: keep-all;
338
- white-space: nowrap;
339
- text-overflow: ellipsis;
340
- overflow: hidden;
341
- }
342
- }
343
- table {
344
- border-collapse: collapse !important;
345
- thead {
346
- tr {
347
- th {
348
- &:first-of-type {
349
- position: sticky;
350
- left: 0;
351
- background: $th-bg;
352
- z-index: 10;
353
- &:before {
354
- content: '';
355
- position: absolute;
356
- width: 20px;
357
- height: 100%;
358
- right: -20px;
359
- top: 0;
360
- box-shadow: inset 17px 0 26px -29px rgba(0, 0, 0, 0.2);
361
- background: none !important;
362
- }
363
- }
364
- }
365
- }
366
- }
367
- > tbody {
368
- > tr {
369
- > td {
370
- :deep(.table-tree-node) {
371
- table {
372
- tr {
373
- td {
374
- &:first-of-type {
375
- position: sticky;
376
- left: 0;
377
- &:before {
378
- content: '';
379
- position: absolute;
380
- width: 20px;
381
- height: 100%;
382
- right: -20px;
383
- top: 0;
384
- box-shadow: inset 17px 0 26px -29px rgba(0, 0, 0, 0.3);
385
- background: none !important;
386
- }
387
- }
388
- }
389
- }
390
- }
391
- }
392
- }
393
- }
394
- }
395
- tfoot {
396
- border-top: 2px solid $Grey_Lighten-3 !important;
397
- tr {
398
- td {
399
- &:first-of-type {
400
- position: sticky;
401
- left: 0;
402
- background: white;
403
- &:before {
404
- content: '';
405
- position: absolute;
406
- width: 20px;
407
- height: 100%;
408
- right: -20px;
409
- top: 0;
410
- box-shadow: inset 17px 0 26px -29px rgba(0, 0, 0, 0.3);
411
- background: none !important;
412
- }
413
- }
414
- }
415
- &:last-of-type {
416
- background: rgba(245, 250, 255, 1);
417
- .td-1 {
418
- color: $Blue_B_Lighten-2;
419
- background: rgba(245, 250, 255, 1);
420
- }
421
- }
422
- }
423
- }
424
- }
425
- &.no-before {
426
- table {
427
- thead {
428
- tr {
429
- th {
430
- &:first-of-type {
431
- &::before {
432
- display: none;
433
- }
434
- }
435
- }
436
- }
437
- }
438
- > tbody {
439
- > tr {
440
- > td {
441
- :deep(.table-tree-node) {
442
- table {
443
- tr {
444
- td {
445
- &:first-of-type {
446
- &::before {
447
- display: none;
448
- }
449
- }
450
- }
451
- }
452
- }
453
- }
454
- }
455
- }
456
- }
457
- tfoot {
458
- tr {
459
- td {
460
- &:first-of-type {
461
- &::before {
462
- display: none;
463
- }
464
- }
465
- }
466
- }
467
- }
468
- }
469
- }
470
- }
471
- }
472
-
473
- &.no-data-table-tree {
474
- .s-table-tree__inner {
475
- overflow: hidden;
476
- table {
477
- thead {
478
- opacity: 0.4;
479
- }
480
- tbody {
481
- tr {
482
- td {
483
- height: 240px;
484
- padding: 0;
485
- > div {
486
- padding-top: 80px;
487
- height: 240px;
488
- text-align: center;
489
- position: absolute;
490
- width: 100%;
491
- top: 36px;
492
- left: 0;
493
- color: $Grey_Default;
494
- }
495
- }
496
- }
497
- }
498
- }
499
- }
500
- }
501
- }
502
- </style>
1
+ <template>
2
+ <div
3
+ class="s-table-tree bg-white"
4
+ :class="{
5
+ 'sticky-table-tree': isStickyFirstColumn,
6
+ 'loading-table-tree': loading,
7
+ 'no-data-table-tree': !rows.length,
8
+ }"
9
+ ref="sTableTreeRef"
10
+ >
11
+ <slot name="loading" v-if="loading">
12
+ <q-inner-loading showing color="positive" size="72px" />
13
+ </slot>
14
+
15
+ <div class="s-table-tree__inner" ref="scrollLocationRef" @scroll="handleScroll">
16
+ <table>
17
+ <thead>
18
+ <tr>
19
+ <th
20
+ v-for="(column, idx) in columns"
21
+ :key="column.name"
22
+ :class="`td-${idx + 1} text-${column.align}`"
23
+ :style="`width: ${column.width}px`"
24
+ >
25
+ <slot :name="`header-cell-${column.name}`">
26
+ {{ column.label }}
27
+ </slot>
28
+ </th>
29
+ </tr>
30
+ </thead>
31
+
32
+ <tbody v-if="!rows.length">
33
+ <tr>
34
+ <td :colspan="columns.length">
35
+ <div>
36
+ <slot name="no-data">
37
+ {{ noDataLabel }}
38
+ </slot>
39
+ </div>
40
+ </td>
41
+ </tr>
42
+ </tbody>
43
+
44
+ <tbody v-else>
45
+ <slot name="body">
46
+ <tr v-if="rows.length > 0">
47
+ <td :colspan="columns.length" class="body-td">
48
+ <table-tree-node
49
+ v-for="(row, i) in treeDataSource"
50
+ :key="i"
51
+ :nodeName="`root_node_${i}`"
52
+ :row="row"
53
+ :columns="columns"
54
+ :colspan="columns.length"
55
+ :resizedWidths="resizedWidths"
56
+ ref="childTableNode"
57
+ @handleExpand="node => handleExpand(row, node)"
58
+ >
59
+ <template
60
+ v-for="column in columns"
61
+ :key="column.name"
62
+ #[`body-cell-${column.name}`]="row"
63
+ >
64
+ <slot :name="`body-cell-${column.name}`" v-bind="row"></slot>
65
+ </template>
66
+ </table-tree-node>
67
+ </td>
68
+ </tr>
69
+ </slot>
70
+ </tbody>
71
+
72
+ <tfoot v-if="foots.length > 0 && rows.length > 0">
73
+ <slot name="tfoot">
74
+ <tr v-for="(f, i) in foots" :key="i" :class="`tr-${i + 1}`">
75
+ <td
76
+ v-for="(col, colIdx) in columns"
77
+ :key="col.name"
78
+ :class="`td-${colIdx + 1} text-${col.align}`"
79
+ >
80
+ <slot :name="`body-cell-${col.name}`">
81
+ <span v-if="col.prefix" class="q-mr-xs">{{ col.prefix }}</span>
82
+ {{ f[col.name] }}
83
+ <span v-if="col.suffix" class="q-ml-xs">{{ col.suffix }}</span>
84
+ </slot>
85
+ </td>
86
+ </tr>
87
+ </slot>
88
+ </tfoot>
89
+ </table>
90
+ </div>
91
+ </div>
92
+ </template>
93
+
94
+ <script>
95
+ import { defineComponent, ref, onMounted, nextTick, watch } from 'vue';
96
+ import { QInnerLoading } from 'quasar';
97
+ import TableTreeNode from './TableTreeNode.vue';
98
+ import { useResizableTree } from '../composables/table/use-resizable-tree';
99
+
100
+ function setWidthForExpand(tableNodeRef, resizedWidths) {
101
+ const tableElements = tableNodeRef.querySelectorAll('table');
102
+
103
+ tableElements.forEach(tableElement => {
104
+ const rows = tableElement.querySelectorAll('tr');
105
+ rows.forEach(row => {
106
+ const cols = row.children;
107
+ for (let i = 0; i < cols.length; i++) {
108
+ if (resizedWidths[i] !== undefined) {
109
+ cols[i].style.minWidth = `${resizedWidths[i]}px`;
110
+ cols[i].style.width = `${resizedWidths[i]}px`;
111
+ }
112
+ }
113
+ });
114
+ });
115
+ }
116
+
117
+ export default defineComponent({
118
+ name: 'STableTree',
119
+ components: { TableTreeNode, QInnerLoading },
120
+ props: {
121
+ columns: {
122
+ type: Array,
123
+ default: () => [],
124
+ },
125
+ rows: {
126
+ type: Array,
127
+ default: () => [],
128
+ },
129
+ foots: {
130
+ type: Array,
131
+ default: () => [],
132
+ },
133
+ noDataLabel: {
134
+ type: String,
135
+ default: '데이터 조회가 필요합니다',
136
+ },
137
+ loading: {
138
+ type: Boolean,
139
+ default: false,
140
+ },
141
+ isStickyFirstColumn: {
142
+ tpye: Boolean,
143
+ default: true,
144
+ },
145
+ resizable: {
146
+ type: Boolean,
147
+ default: false,
148
+ },
149
+ stickyResizable: {
150
+ type: [Array, Number],
151
+ required: false,
152
+ },
153
+ },
154
+ setup(props, { emit }) {
155
+ const treeDataSource = ref([]);
156
+ const sTableTreeRef = ref(null);
157
+ const resizedWidths = ref({});
158
+ const scrollLocationRef = ref(null);
159
+
160
+ function handleScroll() {
161
+ const { scrollLeft } = scrollLocationRef.value;
162
+
163
+ if (scrollLeft === 0) {
164
+ scrollLocationRef.value.classList.add('no-before');
165
+ } else {
166
+ scrollLocationRef.value.classList.remove('no-before');
167
+ }
168
+ }
169
+
170
+ function initTreeData() {
171
+ const tempData = props.rows;
172
+ const reduceDataFunc = (data, level) => {
173
+ data.forEach(m => {
174
+ m.isExpand = m.isExpand || false;
175
+ m.children = m.children || [];
176
+ m.level = level;
177
+ m.leftPadding = level === 1 ? 20 : (level - 1) * 28 + 20;
178
+ m.meta = {
179
+ isLastDepth: m.meta.isLastDepth || false,
180
+ };
181
+ if (m.children.length > 0) {
182
+ reduceDataFunc(m.children, level + 1);
183
+ }
184
+
185
+ nextTick(() => {
186
+ setWidthForExpand(sTableTreeRef.value, resizedWidths.value);
187
+ });
188
+ });
189
+ };
190
+ reduceDataFunc(tempData, 1);
191
+ treeDataSource.value = tempData;
192
+ }
193
+ initTreeData();
194
+
195
+ function handleExpand(parentRow, row) {
196
+ row.isExpand = !row.isExpand;
197
+ if (row.isExpand) emit('handleExpand', parentRow, row);
198
+
199
+ nextTick(() => {
200
+ setWidthForExpand(sTableTreeRef.value, resizedWidths.value);
201
+ });
202
+ }
203
+
204
+ const { addResizable } = useResizableTree();
205
+ function handleColumnResizable() {
206
+ if (props.resizable || props.isStickyFirstColumn) {
207
+ resizedWidths.value = addResizable(sTableTreeRef.value, props.columns);
208
+ }
209
+ }
210
+
211
+ onMounted(() => {
212
+ handleColumnResizable();
213
+ scrollLocationRef.value.classList.add('no-before');
214
+ });
215
+
216
+ watch(
217
+ () => props.columns,
218
+ () => {
219
+ nextTick(() => {
220
+ handleColumnResizable();
221
+ });
222
+ },
223
+ { deep: true },
224
+ );
225
+
226
+ watch(
227
+ () => props.rows,
228
+ () => {
229
+ initTreeData();
230
+ },
231
+ { deep: true },
232
+ );
233
+
234
+ watch(
235
+ () => treeDataSource.value,
236
+ () => {
237
+ emit('update:model-value', treeDataSource.value);
238
+ },
239
+ { deep: true },
240
+ );
241
+
242
+ return {
243
+ treeDataSource,
244
+ handleExpand,
245
+ handleScroll,
246
+ sTableTreeRef,
247
+ scrollLocationRef,
248
+ resizedWidths,
249
+ };
250
+ },
251
+ });
252
+ </script>
253
+
254
+ <style scoped lang="scss">
255
+ @import '../css/quasar.variables.scss';
256
+ @import '../css/extends.scss';
257
+
258
+ .s-table-tree {
259
+ border: 1px solid $Grey_Lighten-2;
260
+ border-radius: 8px !important;
261
+ overflow: hidden;
262
+ position: relative;
263
+ box-sizing: border-box;
264
+ color: $Grey_Darken-5;
265
+ .q-inner-loading {
266
+ z-index: 1;
267
+ }
268
+ .s-table-tree__inner {
269
+ overflow: auto;
270
+ td,
271
+ th {
272
+ width: 100%;
273
+ &:not(:first-of-type) {
274
+ word-break: keep-all;
275
+ white-space: nowrap;
276
+ text-overflow: ellipsis;
277
+ overflow: hidden;
278
+ }
279
+ }
280
+ table {
281
+ width: 100%;
282
+ border-collapse: collapse;
283
+ border-spacing: 0;
284
+ table-layout: fixed;
285
+ thead {
286
+ background: $th-bg;
287
+ tr {
288
+ height: 36px;
289
+ th {
290
+ border-bottom: 1px solid $Grey-Lighten-3;
291
+ padding: 0 16px;
292
+ font-weight: 500;
293
+ color: rgba(34, 34, 34, 1);
294
+ }
295
+ }
296
+ }
297
+ tbody {
298
+ > tr {
299
+ td {
300
+ height: 44px;
301
+ }
302
+ > .body-td {
303
+ padding: 0;
304
+ }
305
+ }
306
+ }
307
+ tfoot {
308
+ border-top: 2px solid $Grey_Lighten-3 !important;
309
+ tr {
310
+ &:last-of-type {
311
+ background: rgba(245, 250, 255, 1);
312
+ .td-1 {
313
+ color: $Blue_B_Lighten-2;
314
+ }
315
+ }
316
+ td {
317
+ border-top: 1px solid $Grey_Lighten-3 !important;
318
+ height: 52px;
319
+ padding: 0 16px;
320
+ &.td-1 {
321
+ padding: 0 20px;
322
+ font-weight: 700;
323
+ color: $Blue_C_Darken-1;
324
+ }
325
+ }
326
+ }
327
+ }
328
+ }
329
+ }
330
+
331
+ &.sticky-table-tree {
332
+ .s-table-tree__inner {
333
+ td,
334
+ th {
335
+ width: 100%;
336
+ &:not(:first-of-type) {
337
+ word-break: keep-all;
338
+ white-space: nowrap;
339
+ text-overflow: ellipsis;
340
+ overflow: hidden;
341
+ }
342
+ }
343
+ table {
344
+ border-collapse: collapse !important;
345
+ thead {
346
+ tr {
347
+ th {
348
+ &:first-of-type {
349
+ position: sticky;
350
+ left: 0;
351
+ background: $th-bg;
352
+ z-index: 10;
353
+ &:before {
354
+ content: '';
355
+ position: absolute;
356
+ width: 20px;
357
+ height: 100%;
358
+ right: -20px;
359
+ top: 0;
360
+ box-shadow: inset 17px 0 26px -29px rgba(0, 0, 0, 0.2);
361
+ background: none !important;
362
+ }
363
+ }
364
+ }
365
+ }
366
+ }
367
+ > tbody {
368
+ > tr {
369
+ > td {
370
+ :deep(.table-tree-node) {
371
+ table {
372
+ tr {
373
+ td {
374
+ &:first-of-type {
375
+ position: sticky;
376
+ left: 0;
377
+ &:before {
378
+ content: '';
379
+ position: absolute;
380
+ width: 20px;
381
+ height: 100%;
382
+ right: -20px;
383
+ top: 0;
384
+ box-shadow: inset 17px 0 26px -29px rgba(0, 0, 0, 0.3);
385
+ background: none !important;
386
+ }
387
+ }
388
+ }
389
+ }
390
+ }
391
+ }
392
+ }
393
+ }
394
+ }
395
+ tfoot {
396
+ border-top: 2px solid $Grey_Lighten-3 !important;
397
+ tr {
398
+ td {
399
+ &:first-of-type {
400
+ position: sticky;
401
+ left: 0;
402
+ background: white;
403
+ &:before {
404
+ content: '';
405
+ position: absolute;
406
+ width: 20px;
407
+ height: 100%;
408
+ right: -20px;
409
+ top: 0;
410
+ box-shadow: inset 17px 0 26px -29px rgba(0, 0, 0, 0.3);
411
+ background: none !important;
412
+ }
413
+ }
414
+ }
415
+ &:last-of-type {
416
+ background: rgba(245, 250, 255, 1);
417
+ .td-1 {
418
+ color: $Blue_B_Lighten-2;
419
+ background: rgba(245, 250, 255, 1);
420
+ }
421
+ }
422
+ }
423
+ }
424
+ }
425
+ &.no-before {
426
+ table {
427
+ thead {
428
+ tr {
429
+ th {
430
+ &:first-of-type {
431
+ &::before {
432
+ display: none;
433
+ }
434
+ }
435
+ }
436
+ }
437
+ }
438
+ > tbody {
439
+ > tr {
440
+ > td {
441
+ :deep(.table-tree-node) {
442
+ table {
443
+ tr {
444
+ td {
445
+ &:first-of-type {
446
+ &::before {
447
+ display: none;
448
+ }
449
+ }
450
+ }
451
+ }
452
+ }
453
+ }
454
+ }
455
+ }
456
+ }
457
+ tfoot {
458
+ tr {
459
+ td {
460
+ &:first-of-type {
461
+ &::before {
462
+ display: none;
463
+ }
464
+ }
465
+ }
466
+ }
467
+ }
468
+ }
469
+ }
470
+ }
471
+ }
472
+
473
+ &.no-data-table-tree {
474
+ .s-table-tree__inner {
475
+ overflow: hidden;
476
+ table {
477
+ thead {
478
+ opacity: 0.4;
479
+ }
480
+ tbody {
481
+ tr {
482
+ td {
483
+ height: 240px;
484
+ padding: 0;
485
+ > div {
486
+ padding-top: 80px;
487
+ height: 240px;
488
+ text-align: center;
489
+ position: absolute;
490
+ width: 100%;
491
+ top: 36px;
492
+ left: 0;
493
+ color: $Grey_Default;
494
+ }
495
+ }
496
+ }
497
+ }
498
+ }
499
+ }
500
+ }
501
+ }
502
+ </style>