@retailcrm/embed-ui-v1-components 0.9.26 → 0.9.27
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.
package/dist/remote.cjs
CHANGED
|
@@ -2466,6 +2466,12 @@ const slotNeedsBodyCellWrapper = (children) => {
|
|
|
2466
2466
|
}
|
|
2467
2467
|
return !nodes.every(isCellVNode);
|
|
2468
2468
|
};
|
|
2469
|
+
const hasSlotContent = (children) => {
|
|
2470
|
+
if (!children) {
|
|
2471
|
+
return false;
|
|
2472
|
+
}
|
|
2473
|
+
return normalizeNodes(children).length > 0;
|
|
2474
|
+
};
|
|
2469
2475
|
const renderGroupHead = (slot, props) => {
|
|
2470
2476
|
return slot?.(props) ?? [String(props.group.key)];
|
|
2471
2477
|
};
|
|
@@ -2692,17 +2698,25 @@ const _sfc_main$6 = vue.defineComponent({
|
|
|
2692
2698
|
const pageSize = slots["footer-page-size"]?.(footerData);
|
|
2693
2699
|
const exportControl = slots["footer-export"]?.(footerData);
|
|
2694
2700
|
const pagination = slots["footer-pagination"]?.(footerData);
|
|
2701
|
+
const hasSummary = hasSlotContent(summary);
|
|
2702
|
+
const hasPageSize = hasSlotContent(pageSize);
|
|
2703
|
+
const hasExportControl = hasSlotContent(exportControl);
|
|
2704
|
+
const hasPagination = hasSlotContent(pagination);
|
|
2705
|
+
const hasAnyStructuredFooterContent = hasSummary || hasPageSize || hasExportControl || hasPagination;
|
|
2706
|
+
if (!hasAnyStructuredFooterContent) {
|
|
2707
|
+
return null;
|
|
2708
|
+
}
|
|
2695
2709
|
return vue.h(UiTableSection, { kind: "foot", key: "footer" }, () => vue.h(UiTableRow, () => vue.h(UiTableBodyCell, {
|
|
2696
2710
|
colspan: columnsCount,
|
|
2697
2711
|
class: "ui-v1-table__footer-cell"
|
|
2698
2712
|
}, () => vue.h("div", { class: "ui-v1-table__footer" }, [
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2713
|
+
hasSummary ? vue.h("div", { class: "ui-v1-table__footer-meta" }, [summary]) : null,
|
|
2714
|
+
hasPageSize || hasExportControl || hasPagination ? vue.h("div", { class: "ui-v1-table__footer-controls" }, [
|
|
2715
|
+
hasPageSize || hasExportControl ? vue.h("div", { class: "ui-v1-table__footer-main" }, [
|
|
2702
2716
|
pageSize,
|
|
2703
2717
|
exportControl
|
|
2704
2718
|
]) : null,
|
|
2705
|
-
|
|
2719
|
+
hasPagination ? vue.h("div", { class: "ui-v1-table__footer-side" }, [pagination]) : null
|
|
2706
2720
|
]) : null
|
|
2707
2721
|
]))));
|
|
2708
2722
|
}
|
package/dist/remote.js
CHANGED
|
@@ -2464,6 +2464,12 @@ const slotNeedsBodyCellWrapper = (children) => {
|
|
|
2464
2464
|
}
|
|
2465
2465
|
return !nodes.every(isCellVNode);
|
|
2466
2466
|
};
|
|
2467
|
+
const hasSlotContent = (children) => {
|
|
2468
|
+
if (!children) {
|
|
2469
|
+
return false;
|
|
2470
|
+
}
|
|
2471
|
+
return normalizeNodes(children).length > 0;
|
|
2472
|
+
};
|
|
2467
2473
|
const renderGroupHead = (slot, props) => {
|
|
2468
2474
|
return slot?.(props) ?? [String(props.group.key)];
|
|
2469
2475
|
};
|
|
@@ -2690,17 +2696,25 @@ const _sfc_main$6 = defineComponent({
|
|
|
2690
2696
|
const pageSize = slots["footer-page-size"]?.(footerData);
|
|
2691
2697
|
const exportControl = slots["footer-export"]?.(footerData);
|
|
2692
2698
|
const pagination = slots["footer-pagination"]?.(footerData);
|
|
2699
|
+
const hasSummary = hasSlotContent(summary);
|
|
2700
|
+
const hasPageSize = hasSlotContent(pageSize);
|
|
2701
|
+
const hasExportControl = hasSlotContent(exportControl);
|
|
2702
|
+
const hasPagination = hasSlotContent(pagination);
|
|
2703
|
+
const hasAnyStructuredFooterContent = hasSummary || hasPageSize || hasExportControl || hasPagination;
|
|
2704
|
+
if (!hasAnyStructuredFooterContent) {
|
|
2705
|
+
return null;
|
|
2706
|
+
}
|
|
2693
2707
|
return h(UiTableSection, { kind: "foot", key: "footer" }, () => h(UiTableRow, () => h(UiTableBodyCell, {
|
|
2694
2708
|
colspan: columnsCount,
|
|
2695
2709
|
class: "ui-v1-table__footer-cell"
|
|
2696
2710
|
}, () => h("div", { class: "ui-v1-table__footer" }, [
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2711
|
+
hasSummary ? h("div", { class: "ui-v1-table__footer-meta" }, [summary]) : null,
|
|
2712
|
+
hasPageSize || hasExportControl || hasPagination ? h("div", { class: "ui-v1-table__footer-controls" }, [
|
|
2713
|
+
hasPageSize || hasExportControl ? h("div", { class: "ui-v1-table__footer-main" }, [
|
|
2700
2714
|
pageSize,
|
|
2701
2715
|
exportControl
|
|
2702
2716
|
]) : null,
|
|
2703
|
-
|
|
2717
|
+
hasPagination ? h("div", { class: "ui-v1-table__footer-side" }, [pagination]) : null
|
|
2704
2718
|
]) : null
|
|
2705
2719
|
]))));
|
|
2706
2720
|
}
|
package/docs/AI.md
CHANGED
|
@@ -126,6 +126,10 @@ screen where users scan and refine datasets:
|
|
|
126
126
|
- reset `page` to `1` when filters or sorting change;
|
|
127
127
|
- debounce free-text search before writing query or fetching data;
|
|
128
128
|
- use `UiTableSorter` for sortable headers;
|
|
129
|
+
- for ordinary `UiTableColumn` cell customization, set header metadata through props such as `label`, `width`,
|
|
130
|
+
and `trim`, then use `v-slot` on `UiTableColumn` instead of `<template #cell>`;
|
|
131
|
+
- use the `#cell` slot only when the column also needs another named slot such as `#label`, or when explicit
|
|
132
|
+
slot naming makes a complex column easier to read;
|
|
129
133
|
- use `UiTable` footer slots for summary, page-size controls, export, and pagination;
|
|
130
134
|
- compose table footer controls with `UiTableFooterSection` and `UiTableFooterButton`, not regular `UiButton`;
|
|
131
135
|
- use chevron icon assets for table footer previous/next controls instead of text glyphs;
|
|
@@ -32,24 +32,18 @@ examples:
|
|
|
32
32
|
:rows="rows"
|
|
33
33
|
row-key="id"
|
|
34
34
|
>
|
|
35
|
-
<UiTableColumn label="Title">
|
|
36
|
-
<
|
|
37
|
-
<strong>{{ row.title }}</strong>
|
|
38
|
-
</template>
|
|
35
|
+
<UiTableColumn v-slot="{ row }" label="Title">
|
|
36
|
+
<strong>{{ row.title }}</strong>
|
|
39
37
|
</UiTableColumn>
|
|
40
38
|
|
|
41
|
-
<UiTableColumn label="Customer" width="180">
|
|
42
|
-
|
|
43
|
-
{{ row.customer }}
|
|
44
|
-
</template>
|
|
39
|
+
<UiTableColumn v-slot="{ row }" label="Customer" width="180">
|
|
40
|
+
{{ row.customer }}
|
|
45
41
|
</UiTableColumn>
|
|
46
42
|
|
|
47
|
-
<UiTableColumn label="Status" width="160">
|
|
48
|
-
<
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
</UiTag>
|
|
52
|
-
</template>
|
|
43
|
+
<UiTableColumn v-slot="{ row }" label="Status" width="160">
|
|
44
|
+
<UiTag :background="statusBackgroundByName[row.status]" size="md" saturated :ticker="false">
|
|
45
|
+
{{ row.status }}
|
|
46
|
+
</UiTag>
|
|
53
47
|
</UiTableColumn>
|
|
54
48
|
</UiTable>
|
|
55
49
|
</template>
|
|
@@ -78,29 +72,25 @@ examples:
|
|
|
78
72
|
:rows="rows"
|
|
79
73
|
row-key="id"
|
|
80
74
|
>
|
|
81
|
-
<UiTableColumn label="Name">
|
|
82
|
-
|
|
83
|
-
{{ row.name }}
|
|
84
|
-
</template>
|
|
75
|
+
<UiTableColumn v-slot="{ row }" label="Name">
|
|
76
|
+
{{ row.name }}
|
|
85
77
|
</UiTableColumn>
|
|
86
78
|
|
|
87
|
-
<UiTableColumn :width="48" label="" trim>
|
|
88
|
-
<
|
|
89
|
-
<
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
</UiPopperConnector>
|
|
103
|
-
</template>
|
|
79
|
+
<UiTableColumn v-slot="{ row }" :width="48" label="" trim>
|
|
80
|
+
<UiPopperConnector>
|
|
81
|
+
<UiButton
|
|
82
|
+
:aria-label="`Edit ${row.name}`"
|
|
83
|
+
appearance="tertiary"
|
|
84
|
+
size="sm"
|
|
85
|
+
@click="edit(row)"
|
|
86
|
+
>
|
|
87
|
+
<IconEdit aria-hidden="true" />
|
|
88
|
+
</UiButton>
|
|
89
|
+
|
|
90
|
+
<UiTooltip>
|
|
91
|
+
Edit {{ row.name }}
|
|
92
|
+
</UiTooltip>
|
|
93
|
+
</UiPopperConnector>
|
|
104
94
|
</UiTableColumn>
|
|
105
95
|
</UiTable>
|
|
106
96
|
</template>
|
|
@@ -139,18 +129,14 @@ examples:
|
|
|
139
129
|
:rows="rows"
|
|
140
130
|
row-key="id"
|
|
141
131
|
>
|
|
142
|
-
<UiTableColumn :width="44" label="" trim>
|
|
143
|
-
<
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
</button>
|
|
147
|
-
</template>
|
|
132
|
+
<UiTableColumn v-slot="{ expanded, toggle }" :width="44" label="" trim>
|
|
133
|
+
<button class="table-expand" type="button" @click="toggle">
|
|
134
|
+
{{ expanded ? '-' : '+' }}
|
|
135
|
+
</button>
|
|
148
136
|
</UiTableColumn>
|
|
149
137
|
|
|
150
|
-
<UiTableColumn label="Title">
|
|
151
|
-
|
|
152
|
-
{{ row.title }}
|
|
153
|
-
</template>
|
|
138
|
+
<UiTableColumn v-slot="{ row }" label="Title">
|
|
139
|
+
{{ row.title }}
|
|
154
140
|
</UiTableColumn>
|
|
155
141
|
|
|
156
142
|
<template #expand="{ row }">
|
|
@@ -186,16 +172,12 @@ examples:
|
|
|
186
172
|
row-key="id"
|
|
187
173
|
:group-by="groupByStatus"
|
|
188
174
|
>
|
|
189
|
-
<UiTableColumn label="Title">
|
|
190
|
-
|
|
191
|
-
{{ row.title }}
|
|
192
|
-
</template>
|
|
175
|
+
<UiTableColumn v-slot="{ row }" label="Title">
|
|
176
|
+
{{ row.title }}
|
|
193
177
|
</UiTableColumn>
|
|
194
178
|
|
|
195
|
-
<UiTableColumn label="Status" width="160">
|
|
196
|
-
|
|
197
|
-
{{ row.status }}
|
|
198
|
-
</template>
|
|
179
|
+
<UiTableColumn v-slot="{ row }" label="Status" width="160">
|
|
180
|
+
{{ row.status }}
|
|
199
181
|
</UiTableColumn>
|
|
200
182
|
|
|
201
183
|
<template #group-head="{ group }">
|
|
@@ -241,10 +223,8 @@ examples:
|
|
|
241
223
|
:rows="rows"
|
|
242
224
|
row-key="id"
|
|
243
225
|
>
|
|
244
|
-
<UiTableColumn label="Title">
|
|
245
|
-
|
|
246
|
-
{{ row.title }}
|
|
247
|
-
</template>
|
|
226
|
+
<UiTableColumn v-slot="{ row }" label="Title">
|
|
227
|
+
{{ row.title }}
|
|
248
228
|
</UiTableColumn>
|
|
249
229
|
|
|
250
230
|
<template #footer-summary="{ rowsCount }">
|
|
@@ -440,16 +420,12 @@ examples:
|
|
|
440
420
|
:rows="rows"
|
|
441
421
|
row-key="id"
|
|
442
422
|
>
|
|
443
|
-
<UiTableColumn label="Title">
|
|
444
|
-
|
|
445
|
-
{{ row.title }}
|
|
446
|
-
</template>
|
|
423
|
+
<UiTableColumn v-slot="{ row }" label="Title">
|
|
424
|
+
{{ row.title }}
|
|
447
425
|
</UiTableColumn>
|
|
448
426
|
|
|
449
|
-
<UiTableColumn label="Status" width="160">
|
|
450
|
-
|
|
451
|
-
{{ row.status }}
|
|
452
|
-
</template>
|
|
427
|
+
<UiTableColumn v-slot="{ row }" label="Status" width="160">
|
|
428
|
+
{{ row.status }}
|
|
453
429
|
</UiTableColumn>
|
|
454
430
|
</UiTable>
|
|
455
431
|
</template>
|
|
@@ -649,6 +625,11 @@ composition:
|
|
|
649
625
|
- Use UiTableSorter inside a UiTableColumn label slot for sortable columns.
|
|
650
626
|
- Reset pagination to the first page when sorting changes.
|
|
651
627
|
- Persist sort key and direction in URL query parameters when routing is available.
|
|
628
|
+
columns:
|
|
629
|
+
notes:
|
|
630
|
+
- Configure header metadata with UiTableColumn props such as label, width, align, valign, and trim.
|
|
631
|
+
- Prefer `v-slot` on UiTableColumn for ordinary cell content when the header is configured through props.
|
|
632
|
+
- Use `#cell` only when the column also needs another named slot such as `#label`, or when explicit naming improves readability.
|
|
652
633
|
pagination:
|
|
653
634
|
notes:
|
|
654
635
|
- Use footer-summary, footer-page-size, footer-export, and footer-pagination slots for structured footer controls.
|
|
@@ -676,6 +657,7 @@ ai_notes:
|
|
|
676
657
|
- Compose footer controls with UiTableFooterSection and UiTableFooterButton.
|
|
677
658
|
- Copy the Entity list table footer example when building a realistic entity-list footer.
|
|
678
659
|
- Use UiTableSorter for sortable headers.
|
|
660
|
+
- Prefer UiTableColumn `v-slot` for ordinary custom cells when label and sizing are configured through props.
|
|
679
661
|
- Use icon-only row action buttons with aria-label and UiTooltip in action columns.
|
|
680
662
|
avoid:
|
|
681
663
|
- Do not hide table filters in page header actions.
|
|
@@ -684,6 +666,7 @@ ai_notes:
|
|
|
684
666
|
- Do not put visible text buttons in dense table action columns.
|
|
685
667
|
- Do not put pagination only in local state when the screen has routable result sets.
|
|
686
668
|
- Do not import table internals from host or src paths.
|
|
669
|
+
- Do not use `<template #cell>` for every column when the default slot would be simpler.
|
|
687
670
|
|
|
688
671
|
behavior:
|
|
689
672
|
notes:
|
|
@@ -11,6 +11,35 @@ public_import:
|
|
|
11
11
|
related_components:
|
|
12
12
|
- UiTable
|
|
13
13
|
|
|
14
|
+
examples:
|
|
15
|
+
- title: Prop label with default cell slot
|
|
16
|
+
notes:
|
|
17
|
+
- Use this shape when header metadata is covered by props and only the cell body is custom.
|
|
18
|
+
code: |
|
|
19
|
+
<UiTableColumn v-slot="{ row }" label="Name" min-width="180">
|
|
20
|
+
<UiLink size="small">{{ row.name }}</UiLink>
|
|
21
|
+
</UiTableColumn>
|
|
22
|
+
- title: Custom label and explicit cell slot
|
|
23
|
+
notes:
|
|
24
|
+
- Use named slots when the column uses a custom label, for example a sorter.
|
|
25
|
+
- Keeping `#cell` explicit makes the two slot zones easier to scan.
|
|
26
|
+
code: |
|
|
27
|
+
<UiTableColumn min-width="180">
|
|
28
|
+
<template #label>
|
|
29
|
+
<UiTableSorter
|
|
30
|
+
:direction="sort.direction"
|
|
31
|
+
:active="sort.field === 'name'"
|
|
32
|
+
@click="setSort('name')"
|
|
33
|
+
>
|
|
34
|
+
Name
|
|
35
|
+
</UiTableSorter>
|
|
36
|
+
</template>
|
|
37
|
+
|
|
38
|
+
<template #cell="{ row }">
|
|
39
|
+
<UiLink size="small">{{ row.name }}</UiLink>
|
|
40
|
+
</template>
|
|
41
|
+
</UiTableColumn>
|
|
42
|
+
|
|
14
43
|
use_when:
|
|
15
44
|
- You define columns for UiTable.
|
|
16
45
|
|
|
@@ -30,12 +59,19 @@ api:
|
|
|
30
59
|
- name: default
|
|
31
60
|
zone: cell
|
|
32
61
|
creates: Cell content.
|
|
62
|
+
notes: >
|
|
63
|
+
Prefer `v-slot` on UiTableColumn when the header label is already supplied by the `label`
|
|
64
|
+
prop and only the cell body is customized.
|
|
33
65
|
- name: cell
|
|
34
66
|
zone: cell
|
|
35
67
|
creates: Explicit cell content.
|
|
68
|
+
notes: >
|
|
69
|
+
Use `#cell` when the column also needs another named slot such as `#label`, or when explicit
|
|
70
|
+
naming makes a complex column easier to read.
|
|
36
71
|
- name: label
|
|
37
72
|
zone: header-label
|
|
38
73
|
creates: Header label content.
|
|
74
|
+
notes: Use only when the header label needs custom markup, for example UiTableSorter.
|
|
39
75
|
|
|
40
76
|
rendered_structure:
|
|
41
77
|
descriptive_only: true
|
|
@@ -60,6 +96,10 @@ composition:
|
|
|
60
96
|
notes: Put the row's main UiLink in the first meaningful text column and set link size to small.
|
|
61
97
|
- title: Sortable header
|
|
62
98
|
notes: Use the label slot with UiTableSorter when the column supports sorting.
|
|
99
|
+
- title: Prop label plus custom cell
|
|
100
|
+
notes: Use `<UiTableColumn v-slot="{ row }" label="Name">` instead of `<template #cell>` when `label` prop is enough for the header.
|
|
101
|
+
- title: Custom label plus custom cell
|
|
102
|
+
notes: Use separate `<template #label>` and `<template #cell>` blocks when the header is built with a slot.
|
|
63
103
|
- title: Status column
|
|
64
104
|
notes: Use UiTag for categorical statuses instead of raw colored text.
|
|
65
105
|
|
|
@@ -68,8 +108,12 @@ ai_notes:
|
|
|
68
108
|
- Set minWidth for important text columns so generated tables remain scannable.
|
|
69
109
|
- Use align="right" for numbers, money, and percentages.
|
|
70
110
|
- Use trim only for narrow checkbox, icon, or action columns.
|
|
111
|
+
- Prefer `v-slot` on UiTableColumn for ordinary custom cell content when the header is configured through props.
|
|
112
|
+
- Use the label slot only when the header itself needs custom markup.
|
|
113
|
+
- Use explicit `#cell` together with `#label` when both header and cell content are custom.
|
|
71
114
|
avoid:
|
|
72
115
|
- Do not place filters inside column labels; filters belong above the table.
|
|
116
|
+
- Do not wrap every cell body in `<template #cell>` when the default slot would express the same thing more simply.
|
|
73
117
|
|
|
74
118
|
behavior:
|
|
75
119
|
notes:
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@retailcrm/embed-ui-v1-components",
|
|
3
3
|
"bin": "bin/embed-ui-v1-components.mjs",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "0.9.
|
|
5
|
+
"version": "0.9.27",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "RetailDriverLLC <integration@retailcrm.ru>",
|
|
8
8
|
"repository": {
|
|
@@ -82,8 +82,8 @@
|
|
|
82
82
|
"@storybook/vue3": "^10.3.5",
|
|
83
83
|
"@storybook/vue3-vite": "^10.3.5",
|
|
84
84
|
"@vitejs/plugin-vue": "^6.0.2",
|
|
85
|
-
"@vitest/browser": "4.1.
|
|
86
|
-
"@vitest/browser-playwright": "4.1.
|
|
85
|
+
"@vitest/browser": "4.1.8",
|
|
86
|
+
"@vitest/browser-playwright": "4.1.8",
|
|
87
87
|
"@vue/compiler-sfc": "^3.5.25",
|
|
88
88
|
"@vue/test-utils": "^2.4.6",
|
|
89
89
|
"@yandex/ymaps3-types": "^1.0.19072130",
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
"vite": "^7.3.2",
|
|
101
101
|
"vite-plugin-dts": "^4.5.4",
|
|
102
102
|
"vite-svg-loader": "^5.1.0",
|
|
103
|
-
"vitest": "
|
|
103
|
+
"vitest": "4.1.8",
|
|
104
104
|
"vue": "^3.5.32",
|
|
105
105
|
"vue-i18n": "10.0.8"
|
|
106
106
|
}
|
|
@@ -32,6 +32,7 @@ Use this skill before changing frontend UI built with `@retailcrm/embed-ui-v1-co
|
|
|
32
32
|
## High-signal checks
|
|
33
33
|
|
|
34
34
|
- For entity lists, use `UiTable`, `UiTableColumn`, and table footer slots.
|
|
35
|
+
- For ordinary table cells, configure `UiTableColumn` headers through props and use `v-slot` on the column; reserve `#cell` for columns that also need another named slot or extra clarity.
|
|
35
36
|
- For table pagination, follow the reference example in `UiTable.yml`: button sizes, active state, dividers, arrow assets, and scoped selector pattern.
|
|
36
37
|
- For form fields, use `UiField` with the matching control and forward slot props such as `id` when the control accepts them.
|
|
37
38
|
- Put validation errors inside the relevant field composition, not as unrelated sibling blocks.
|