@vmz/ui 0.3.6 → 0.3.8

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 (68) hide show
  1. package/README.md +53 -51
  2. package/contracts/token-requirements.v0.json +58 -1
  3. package/package.json +5 -2
  4. package/presets/web-surface.v0.json +14 -12
  5. package/src/components/Accordion.vmz +127 -94
  6. package/src/components/Alert.vmz +125 -28
  7. package/src/components/AppShell.vmz +125 -57
  8. package/src/components/Autocomplete.vmz +261 -154
  9. package/src/components/Avatar.vmz +20 -12
  10. package/src/components/Badge.vmz +62 -70
  11. package/src/components/Breadcrumb.vmz +86 -72
  12. package/src/components/BulkActions.vmz +56 -51
  13. package/src/components/Button.vmz +237 -211
  14. package/src/components/Callout.vmz +178 -77
  15. package/src/components/Card.vmz +141 -120
  16. package/src/components/Checkbox.vmz +131 -55
  17. package/src/components/CodeBlock.vmz +77 -30
  18. package/src/components/Collapse.vmz +64 -11
  19. package/src/components/ConsoleShell.vmz +405 -251
  20. package/src/components/Content.vmz +15 -1
  21. package/src/components/DataTable.vmz +294 -194
  22. package/src/components/DatePicker.vmz +766 -674
  23. package/src/components/Descriptions.vmz +90 -0
  24. package/src/components/Dialog.vmz +137 -38
  25. package/src/components/Divider.vmz +8 -1
  26. package/src/components/Drawer.vmz +518 -427
  27. package/src/components/Dropdown.vmz +195 -51
  28. package/src/components/Empty.vmz +96 -54
  29. package/src/components/Field.vmz +170 -115
  30. package/src/components/FilterBar.vmz +34 -4
  31. package/src/components/Flex.vmz +3 -1
  32. package/src/components/Footer.vmz +6 -3
  33. package/src/components/Form.vmz +41 -0
  34. package/src/components/FormItem.vmz +78 -79
  35. package/src/components/Grid.vmz +6 -3
  36. package/src/components/Header.vmz +193 -6
  37. package/src/components/Layout.vmz +3 -1
  38. package/src/components/Link.vmz +25 -10
  39. package/src/components/List.vmz +124 -102
  40. package/src/components/Menu.vmz +416 -243
  41. package/src/components/Message.vmz +167 -0
  42. package/src/components/Notification.vmz +132 -37
  43. package/src/components/Pagination.vmz +237 -69
  44. package/src/components/Popconfirm.vmz +287 -0
  45. package/src/components/Popover.vmz +341 -223
  46. package/src/components/Progress.vmz +16 -5
  47. package/src/components/Prose.vmz +180 -81
  48. package/src/components/QueryForm.vmz +31 -9
  49. package/src/components/RadioGroup.vmz +204 -124
  50. package/src/components/Result.vmz +60 -27
  51. package/src/components/Segmented.vmz +86 -51
  52. package/src/components/Select.vmz +620 -533
  53. package/src/components/Sider.vmz +120 -7
  54. package/src/components/Skeleton.vmz +9 -7
  55. package/src/components/Space.vmz +9 -3
  56. package/src/components/Spinner.vmz +5 -4
  57. package/src/components/Steps.vmz +118 -103
  58. package/src/components/Switch.vmz +131 -98
  59. package/src/components/Table.vmz +270 -165
  60. package/src/components/Tabs.vmz +125 -110
  61. package/src/components/Tag.vmz +60 -43
  62. package/src/components/TextArea.vmz +125 -118
  63. package/src/components/Timeline.vmz +111 -76
  64. package/src/components/Toc.vmz +90 -74
  65. package/src/components/Tooltip.vmz +107 -58
  66. package/src/components/Tree.vmz +214 -191
  67. package/src/components/Typography.vmz +23 -8
  68. package/src/components/Upload.vmz +1394 -1289
@@ -1,165 +1,270 @@
1
- <template>
2
- <div data-vmz-ui="table" :data-sort-key="sortKey" :data-sort-dir="sortDir" class="vmz-ui-table-wrap">
3
- <table class="vmz-ui-table">
4
- <thead @click="onHeadClick">
5
- <tr>
6
- <th v-for="col in columns" :key="col.id" scope="col" :data-vmz-col="col.id">
7
- <button type="button" :data-vmz-sort="col.id" class="vmz-ui-table__sort">
8
- {{ col.title }}
9
- </button>
10
- </th>
11
- <th v-if="hasRowAction" scope="col">
12
- {{ actionTitle }}
13
- </th>
14
- </tr>
15
- </thead>
16
- <tbody @click="onBodyClick">
17
- <tr v-for="row in rows" :key="row.id" :data-vmz-row="row.id">
18
- <td v-for="cell in row.cells">
19
- {{ cell }}
20
- </td>
21
- <td v-if="hasRowAction">
22
- <button type="button" :data-vmz-row-action="row.id" :disabled="rowActionDisabled" class="vmz-ui-table__row-action">
23
- {{ actionLabel }}
24
- </button>
25
- </td>
26
- </tr>
27
- </tbody>
28
- </table>
29
- </div>
30
- </template>
31
- <style>
32
- .vmz-ui-table-wrap {
33
- overflow-x: auto;
34
- border: 1px solid var(--vmz-line-subtle, var(--vmz-line-default));
35
- border-radius: var(--vmz-radius-lg, 8px);
36
- background: var(--vmz-surface-paper);
37
- }
38
-
39
- .vmz-ui-table {
40
- width: 100%;
41
- border-collapse: collapse;
42
- font: inherit;
43
- font-size: 0.875rem;
44
- }
45
-
46
- .vmz-ui-table th,
47
- .vmz-ui-table td {
48
- padding: 0.75rem 1rem;
49
- text-align: left;
50
- border-bottom: 1px solid var(--vmz-line-subtle, var(--vmz-line-default));
51
- vertical-align: middle;
52
- }
53
-
54
- /* Header is structure, not brand: quiet ink on a tinted band. */
55
- .vmz-ui-table th {
56
- font-weight: 600;
57
- font-size: 0.8125rem;
58
- letter-spacing: 0.01em;
59
- color: var(--vmz-text-steel);
60
- background: var(--vmz-surface-mist);
61
- white-space: nowrap;
62
- }
63
-
64
- .vmz-ui-table tbody tr {
65
- transition: background-color var(--vmz-motion-control-duration, 150ms)
66
- var(--vmz-motion-control-easing, cubic-bezier(0.4, 0, 0.2, 1));
67
- }
68
-
69
- .vmz-ui-table tbody tr:hover {
70
- background: var(--vmz-surface-mist);
71
- }
72
-
73
- .vmz-ui-table tbody tr:last-child td {
74
- border-bottom: 0;
75
- }
76
-
77
- .vmz-ui-table__sort {
78
- display: inline-flex;
79
- align-items: center;
80
- gap: 0.25rem;
81
- font: inherit;
82
- font-weight: 600;
83
- padding: 0;
84
- border: 0;
85
- background: transparent;
86
- color: inherit;
87
- cursor: pointer;
88
- outline: none;
89
- border-radius: var(--vmz-radius-xs, 2px);
90
- }
91
-
92
- .vmz-ui-table__sort:focus-visible {
93
- box-shadow: 0 0 0 3px var(--vmz-focus-ring);
94
- }
95
-
96
- .vmz-ui-table__row-action {
97
- font: inherit;
98
- font-weight: 500;
99
- padding: 0.25rem 0.625rem;
100
- border: 1px solid var(--vmz-line-default);
101
- border-radius: var(--vmz-radius-md, 6px);
102
- background: var(--vmz-surface-paper);
103
- color: var(--vmz-action-primary-background);
104
- cursor: pointer;
105
- outline: none;
106
- transition:
107
- color var(--vmz-motion-control-duration, 150ms) var(--vmz-motion-control-easing, cubic-bezier(0.4, 0, 0.2, 1)),
108
- border-color var(--vmz-motion-control-duration, 150ms) var(--vmz-motion-control-easing, cubic-bezier(0.4, 0, 0.2, 1)),
109
- background-color var(--vmz-motion-control-duration, 150ms) var(--vmz-motion-control-easing, cubic-bezier(0.4, 0, 0.2, 1));
110
- }
111
-
112
- .vmz-ui-table__row-action:hover:not(:disabled) {
113
- color: var(--vmz-action-primary-hover);
114
- border-color: var(--vmz-action-primary-hover);
115
- }
116
-
117
- .vmz-ui-table__row-action:focus-visible {
118
- box-shadow: 0 0 0 3px var(--vmz-focus-ring);
119
- }
120
-
121
- .vmz-ui-table__row-action:disabled {
122
- opacity: 0.55;
123
- cursor: not-allowed;
124
- }
125
- </style>
126
- <script client>
127
- /**
128
- * VMZ UI — Table (UI5 Console Surface).
129
- * Column header click → onSort; row action → onRowAction; permission via rowActionDisabled.
130
- */
131
- export default class Table {
132
- /** @type {{ id: string, title: string }[]} */
133
- public columns: {
134
- id: string;
135
- title: string;
136
- }[] = [];
137
- /** @type {{ id: string, cells: string[] }[]} */
138
- public rows: {
139
- id: string;
140
- cells: string[];
141
- }[] = [];
142
- public hasRowAction: boolean = false;
143
- public rowActionDisabled: boolean = false;
144
- public actionTitle: string = "Action";
145
- public actionLabel: string = "Open";
146
- public sortKey: string = "";
147
- public sortDir: string = "asc";
148
- public onRowAction: ((rowId: string) => void) | null = null;
149
- public onSort: ((columnId: string) => void) | null = null;
150
- onBodyClick(ev) {
151
- const t = ev && ev.target;
152
- const el = t && typeof t.closest === "function" ? t.closest("[data-vmz-row-action]") : null;
153
- if (!el || el.disabled) return;
154
- const id = el.getAttribute("data-vmz-row-action");
155
- if (id && typeof this.onRowAction === "function") this.onRowAction(id);
156
- }
157
- onHeadClick(ev) {
158
- const t = ev && ev.target;
159
- const el = t && typeof t.closest === "function" ? t.closest("[data-vmz-sort]") : null;
160
- if (!el) return;
161
- const id = el.getAttribute("data-vmz-sort");
162
- if (id && typeof this.onSort === "function") this.onSort(id);
163
- }
164
- }
165
- </script>
1
+ <template>
2
+ <div data-vmz-ui="table" :data-sort-key="sortKey" :data-sort-dir="sortDir" class="vmz-ui-table-wrap">
3
+ <table class="vmz-ui-table">
4
+ <thead @click="onHeadClick">
5
+ <tr>
6
+ <th v-for="col in columns" :key="col.id" scope="col" :data-vmz-col="col.id" :data-align="columnAlign(col)" :aria-sort="sortAria(col.id)">
7
+ <button type="button" :data-vmz-sort="col.id" :data-active="col.id === sortKey ? 'true' : 'false'" class="vmz-ui-table__sort">
8
+ <span class="vmz-ui-table__title">
9
+ {{ col.title }}
10
+ </span>
11
+ <span class="vmz-ui-table__sort-icon">
12
+ <Icon v-if="col.id === sortKey && sortDir === 'asc'" name="action.sort-asc" size="sm" decorative />
13
+ <Icon v-else-if="col.id === sortKey && sortDir === 'desc'" name="action.sort-desc" size="sm" decorative />
14
+ <Icon v-else name="action.sort" size="sm" decorative />
15
+ </span>
16
+ </button>
17
+ </th>
18
+ <th v-if="hasRowAction" scope="col">
19
+ {{ actionTitle }}
20
+ </th>
21
+ </tr>
22
+ </thead>
23
+ <tbody @click="onBodyClick">
24
+ <tr v-for="row in rows" :key="row.id" :data-vmz-row="row.id">
25
+ <td v-for="(cell, index) in row.cells" :key="index" :data-align="cellAlign(index, cell)">
26
+ {{ cell }}
27
+ </td>
28
+ <td v-if="hasRowAction">
29
+ <button type="button" :data-vmz-row-action="row.id" :disabled="rowActionDisabled" class="vmz-ui-table__row-action">
30
+ {{ actionLabel }}
31
+ </button>
32
+ </td>
33
+ </tr>
34
+ <tr v-if="loading" class="vmz-ui-table__state-row">
35
+ <td :colspan="columnSpan()" class="vmz-ui-table__state">
36
+ <Spinner :label="loadingLabel" />
37
+ <span v-if="loadingText" class="vmz-ui-table__state-text">
38
+ {{ loadingText }}
39
+ </span>
40
+ </td>
41
+ </tr>
42
+ <tr v-else-if="rows.length === 0" class="vmz-ui-table__state-row">
43
+ <td :colspan="columnSpan()" class="vmz-ui-table__state">
44
+ <span class="vmz-ui-table__state-text">
45
+ {{ emptyText }}
46
+ </span>
47
+ </td>
48
+ </tr>
49
+ </tbody>
50
+ </table>
51
+ </div>
52
+ </template>
53
+ <style>
54
+ .vmz-ui-table-wrap {
55
+ width: 100%;
56
+ overflow: auto;
57
+ border: 1px solid var(--vmz-line-default);
58
+ border-radius: var(--vmz-radius-lg, 8px);
59
+ background: var(--vmz-surface-paper);
60
+ }
61
+
62
+ .vmz-ui-table {
63
+ width: 100%;
64
+ border-collapse: collapse;
65
+ font: inherit;
66
+ font-size: 0.875rem;
67
+ color: var(--vmz-text-ink);
68
+ }
69
+
70
+ .vmz-ui-table th,
71
+ .vmz-ui-table td {
72
+ height: 3rem;
73
+ padding: 0 1rem;
74
+ text-align: left;
75
+ vertical-align: middle;
76
+ border: 0;
77
+ border-bottom: 1px solid var(--vmz-line-subtle);
78
+ white-space: nowrap;
79
+ }
80
+
81
+ .vmz-ui-table th {
82
+ height: 2.75rem;
83
+ font-size: 0.75rem;
84
+ font-weight: 600;
85
+ color: var(--vmz-text-tertiary);
86
+ background: var(--vmz-surface-mist);
87
+ }
88
+
89
+ .vmz-ui-table td[data-align="right"],
90
+ .vmz-ui-table th[data-align="right"] {
91
+ text-align: right;
92
+ font-variant-numeric: tabular-nums;
93
+ }
94
+
95
+ .vmz-ui-table td[data-align="center"],
96
+ .vmz-ui-table th[data-align="center"] {
97
+ text-align: center;
98
+ }
99
+
100
+ .vmz-ui-table tbody tr {
101
+ transition: background-color var(--vmz-motion-control-duration, 150ms)
102
+ var(--vmz-motion-control-easing, cubic-bezier(0.4, 0, 0.2, 1));
103
+ }
104
+
105
+ .vmz-ui-table tbody tr:hover {
106
+ background: var(--vmz-surface-fill);
107
+ }
108
+
109
+ .vmz-ui-table tbody tr:last-child td {
110
+ border-bottom: 0;
111
+ }
112
+
113
+ .vmz-ui-table__sort {
114
+ display: inline-flex;
115
+ align-items: center;
116
+ justify-content: flex-start;
117
+ gap: 0.25rem;
118
+ width: 100%;
119
+ padding: 0;
120
+ border: 0;
121
+ background: transparent;
122
+ color: inherit;
123
+ font: inherit;
124
+ font-size: 0.75rem;
125
+ font-weight: 600;
126
+ cursor: pointer;
127
+ outline: none;
128
+ border-radius: var(--vmz-radius-xs, 2px);
129
+ }
130
+
131
+ .vmz-ui-table th[data-align="right"] .vmz-ui-table__sort {
132
+ justify-content: flex-end;
133
+ }
134
+
135
+ .vmz-ui-table th[data-align="center"] .vmz-ui-table__sort {
136
+ justify-content: center;
137
+ }
138
+
139
+ .vmz-ui-table__sort:hover {
140
+ color: var(--vmz-action-primary-background);
141
+ }
142
+
143
+ .vmz-ui-table__sort:focus-visible {
144
+ box-shadow: 0 0 0 3px var(--vmz-focus-ring);
145
+ }
146
+
147
+ .vmz-ui-table__sort-icon {
148
+ display: inline-flex;
149
+ align-items: center;
150
+ color: var(--vmz-text-tertiary);
151
+ font-size: 0.875rem;
152
+ }
153
+
154
+ .vmz-ui-table__sort:hover .vmz-ui-table__sort-icon,
155
+ .vmz-ui-table__sort[data-active="true"] .vmz-ui-table__sort-icon {
156
+ color: var(--vmz-action-primary-background);
157
+ }
158
+
159
+ .vmz-ui-table__row-action {
160
+ height: 2rem;
161
+ padding: 0 0.5rem;
162
+ font: inherit;
163
+ font-size: 0.875rem;
164
+ font-weight: 500;
165
+ border: 0;
166
+ border-radius: var(--vmz-radius-md, 6px);
167
+ background: transparent;
168
+ color: var(--vmz-action-primary-background);
169
+ cursor: pointer;
170
+ outline: none;
171
+ transition:
172
+ color var(--vmz-motion-control-duration, 150ms) var(--vmz-motion-control-easing, cubic-bezier(0.4, 0, 0.2, 1)),
173
+ background-color var(--vmz-motion-control-duration, 150ms) var(--vmz-motion-control-easing, cubic-bezier(0.4, 0, 0.2, 1));
174
+ }
175
+
176
+ .vmz-ui-table__row-action:hover:not(:disabled) {
177
+ background: var(--vmz-action-primary-soft);
178
+ color: var(--vmz-action-primary-hover);
179
+ }
180
+
181
+ .vmz-ui-table__row-action:focus-visible {
182
+ box-shadow: 0 0 0 3px var(--vmz-focus-ring);
183
+ }
184
+
185
+ .vmz-ui-table__row-action:disabled {
186
+ opacity: 0.55;
187
+ cursor: not-allowed;
188
+ color: var(--vmz-text-tertiary);
189
+ }
190
+
191
+ .vmz-ui-table tbody tr.vmz-ui-table__state-row:hover {
192
+ background: transparent;
193
+ }
194
+
195
+ .vmz-ui-table__state {
196
+ height: 3rem;
197
+ text-align: center;
198
+ color: var(--vmz-text-tertiary);
199
+ white-space: normal;
200
+ }
201
+
202
+ .vmz-ui-table__state-text {
203
+ margin-left: 0.5rem;
204
+ font-size: 0.875rem;
205
+ }
206
+ </style>
207
+ <script client>
208
+ /**
209
+ * VMZ UI — Table (commercial data surface).
210
+ * Column header click → onSort; row action → onRowAction; permission via rowActionDisabled.
211
+ * Numeric cells right-align automatically; column `align` overrides.
212
+ */
213
+ export default class Table {
214
+ /** @type {{ id: string, title: string, align?: string }[]} */
215
+ public columns: {
216
+ id: string;
217
+ title: string;
218
+ align?: string;
219
+ }[] = [];
220
+ /** @type {{ id: string, cells: string[] }[]} */
221
+ public rows: {
222
+ id: string;
223
+ cells: string[];
224
+ }[] = [];
225
+ public hasRowAction: boolean = false;
226
+ public rowActionDisabled: boolean = false;
227
+ public actionTitle: string = "";
228
+ public actionLabel: string = "";
229
+ public sortKey: string = "";
230
+ public sortDir: string = "asc";
231
+ public loading: boolean = false;
232
+ public loadingLabel: string = "";
233
+ public loadingText: string = "";
234
+ public emptyText: string = "";
235
+ public onRowAction: ((rowId: string) => void) | null = null;
236
+ public onSort: ((columnId: string) => void) | null = null;
237
+ columnAlign(col) {
238
+ return col && col.align ? col.align : "left";
239
+ }
240
+ cellAlign(index, cell) {
241
+ const col = (this.columns || [])[index];
242
+ if (col && col.align) return col.align;
243
+ const text = String(cell == null ? "" : cell).trim();
244
+ if (!text) return "left";
245
+ return /^[-+]?[\d.,%]+$/.test(text) ? "right" : "left";
246
+ }
247
+ columnSpan() {
248
+ const count = (this.columns || []).length + (this.hasRowAction ? 1 : 0);
249
+ return Math.max(1, count);
250
+ }
251
+ sortAria(id) {
252
+ if (id !== this.sortKey) return null;
253
+ return this.sortDir === "desc" ? "descending" : "ascending";
254
+ }
255
+ onBodyClick(ev) {
256
+ const t = ev && ev.target;
257
+ const el = t && typeof t.closest === "function" ? t.closest("[data-vmz-row-action]") : null;
258
+ if (!el || el.disabled) return;
259
+ const id = el.getAttribute("data-vmz-row-action");
260
+ if (id && typeof this.onRowAction === "function") this.onRowAction(id);
261
+ }
262
+ onHeadClick(ev) {
263
+ const t = ev && ev.target;
264
+ const el = t && typeof t.closest === "function" ? t.closest("[data-vmz-sort]") : null;
265
+ if (!el) return;
266
+ const id = el.getAttribute("data-vmz-sort");
267
+ if (id && typeof this.onSort === "function") this.onSort(id);
268
+ }
269
+ }
270
+ </script>