@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.
- package/README.md +53 -51
- package/contracts/token-requirements.v0.json +58 -1
- package/package.json +5 -2
- package/presets/web-surface.v0.json +14 -12
- package/src/components/Accordion.vmz +127 -94
- package/src/components/Alert.vmz +125 -28
- package/src/components/AppShell.vmz +125 -57
- package/src/components/Autocomplete.vmz +261 -154
- package/src/components/Avatar.vmz +20 -12
- package/src/components/Badge.vmz +62 -70
- package/src/components/Breadcrumb.vmz +86 -72
- package/src/components/BulkActions.vmz +56 -51
- package/src/components/Button.vmz +237 -211
- package/src/components/Callout.vmz +178 -77
- package/src/components/Card.vmz +141 -120
- package/src/components/Checkbox.vmz +131 -55
- package/src/components/CodeBlock.vmz +77 -30
- package/src/components/Collapse.vmz +64 -11
- package/src/components/ConsoleShell.vmz +405 -251
- package/src/components/Content.vmz +15 -1
- package/src/components/DataTable.vmz +294 -194
- package/src/components/DatePicker.vmz +766 -674
- package/src/components/Descriptions.vmz +90 -0
- package/src/components/Dialog.vmz +137 -38
- package/src/components/Divider.vmz +8 -1
- package/src/components/Drawer.vmz +518 -427
- package/src/components/Dropdown.vmz +195 -51
- package/src/components/Empty.vmz +96 -54
- package/src/components/Field.vmz +170 -115
- package/src/components/FilterBar.vmz +34 -4
- package/src/components/Flex.vmz +3 -1
- package/src/components/Footer.vmz +6 -3
- package/src/components/Form.vmz +41 -0
- package/src/components/FormItem.vmz +78 -79
- package/src/components/Grid.vmz +6 -3
- package/src/components/Header.vmz +193 -6
- package/src/components/Layout.vmz +3 -1
- package/src/components/Link.vmz +25 -10
- package/src/components/List.vmz +124 -102
- package/src/components/Menu.vmz +416 -243
- package/src/components/Message.vmz +167 -0
- package/src/components/Notification.vmz +132 -37
- package/src/components/Pagination.vmz +237 -69
- package/src/components/Popconfirm.vmz +287 -0
- package/src/components/Popover.vmz +341 -223
- package/src/components/Progress.vmz +16 -5
- package/src/components/Prose.vmz +180 -81
- package/src/components/QueryForm.vmz +31 -9
- package/src/components/RadioGroup.vmz +204 -124
- package/src/components/Result.vmz +60 -27
- package/src/components/Segmented.vmz +86 -51
- package/src/components/Select.vmz +620 -533
- package/src/components/Sider.vmz +120 -7
- package/src/components/Skeleton.vmz +9 -7
- package/src/components/Space.vmz +9 -3
- package/src/components/Spinner.vmz +5 -4
- package/src/components/Steps.vmz +118 -103
- package/src/components/Switch.vmz +131 -98
- package/src/components/Table.vmz +270 -165
- package/src/components/Tabs.vmz +125 -110
- package/src/components/Tag.vmz +60 -43
- package/src/components/TextArea.vmz +125 -118
- package/src/components/Timeline.vmz +111 -76
- package/src/components/Toc.vmz +90 -74
- package/src/components/Tooltip.vmz +107 -58
- package/src/components/Tree.vmz +214 -191
- package/src/components/Typography.vmz +23 -8
- package/src/components/Upload.vmz +1394 -1289
|
@@ -1,12 +1,42 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<details data-vmz-ui="dropdown" data-vmz-motion="overlay" data-vmz-motion-token="motion.overlay" class="vmz-ui-dropdown">
|
|
3
3
|
<summary data-vmz-dropdown-trigger="1" class="vmz-ui-dropdown__trigger">
|
|
4
|
-
|
|
4
|
+
<span class="vmz-ui-dropdown__trigger-label">
|
|
5
|
+
{{ label }}
|
|
6
|
+
</span>
|
|
7
|
+
<Icon name="action.chevron-down" size="sm" decorative />
|
|
5
8
|
</summary>
|
|
6
9
|
<div data-vmz-dropdown-menu="1" role="menu" class="vmz-ui-dropdown__menu">
|
|
7
10
|
<div v-for="item in items" :key="item.id" class="vmz-ui-dropdown__row">
|
|
8
|
-
<div v-if="item.divider" role="separator" class="vmz-ui-dropdown__divider"
|
|
9
|
-
<
|
|
11
|
+
<div v-if="item.divider" role="separator" class="vmz-ui-dropdown__divider" />
|
|
12
|
+
<div v-else-if="item.kind === 'group'" role="presentation" class="vmz-ui-dropdown__group">
|
|
13
|
+
{{ item.title }}
|
|
14
|
+
</div>
|
|
15
|
+
<details v-else-if="item.children && item.children.length" class="vmz-ui-dropdown__sub">
|
|
16
|
+
<summary :data-danger="item.danger ? 'true' : 'false'" class="vmz-ui-dropdown__item vmz-ui-dropdown__item--sub">
|
|
17
|
+
<span class="vmz-ui-dropdown__label">
|
|
18
|
+
{{ item.title }}
|
|
19
|
+
</span>
|
|
20
|
+
<Icon name="action.chevron-right" size="sm" decorative />
|
|
21
|
+
</summary>
|
|
22
|
+
<div role="menu" class="vmz-ui-dropdown__subpanel">
|
|
23
|
+
<div v-for="child in item.children" :key="child.id" class="vmz-ui-dropdown__row">
|
|
24
|
+
<div v-if="child.divider" role="separator" class="vmz-ui-dropdown__divider" />
|
|
25
|
+
<a v-else-if="hasHref(child)" :href="child.href" role="menuitem" :data-vmz-dropdown-item="child.id" :data-danger="child.danger ? 'true' : 'false'" :data-active="child.active ? 'true' : 'false'" :data-disabled="child.disabled ? 'true' : 'false'" :aria-disabled="child.disabled ? 'true' : null" :tabindex="child.disabled ? -1 : null" class="vmz-ui-dropdown__item">
|
|
26
|
+
{{ child.title }}
|
|
27
|
+
</a>
|
|
28
|
+
<button v-else type="button" role="menuitem" :data-vmz-dropdown-item="child.id" :data-danger="child.danger ? 'true' : 'false'" :data-active="child.active ? 'true' : 'false'" :data-disabled="child.disabled ? 'true' : 'false'" :aria-disabled="child.disabled ? 'true' : null" :tabindex="child.disabled ? -1 : null" @click="onItemClick" class="vmz-ui-dropdown__item">
|
|
29
|
+
{{ child.title }}
|
|
30
|
+
</button>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
</details>
|
|
34
|
+
<a v-else-if="hasHref(item)" :href="item.href" role="menuitem" :data-vmz-dropdown-item="item.id" :data-danger="item.danger ? 'true' : 'false'" :data-active="item.active ? 'true' : 'false'" :data-disabled="item.disabled ? 'true' : 'false'" :aria-disabled="item.disabled ? 'true' : null" :tabindex="item.disabled ? -1 : null" class="vmz-ui-dropdown__item">
|
|
35
|
+
{{ item.title }}
|
|
36
|
+
</a>
|
|
37
|
+
<button v-else type="button" role="menuitem" :data-vmz-dropdown-item="item.id" :data-danger="item.danger ? 'true' : 'false'" :data-active="item.active ? 'true' : 'false'" :data-disabled="item.disabled ? 'true' : 'false'" :aria-disabled="item.disabled ? 'true' : null" :tabindex="item.disabled ? -1 : null" @click="onItemClick" class="vmz-ui-dropdown__item">
|
|
38
|
+
{{ item.title }}
|
|
39
|
+
</button>
|
|
10
40
|
</div>
|
|
11
41
|
</div>
|
|
12
42
|
</details>
|
|
@@ -19,41 +49,41 @@
|
|
|
19
49
|
|
|
20
50
|
.vmz-ui-dropdown__trigger {
|
|
21
51
|
list-style: none;
|
|
22
|
-
min-height:
|
|
52
|
+
min-height: 40px;
|
|
53
|
+
box-sizing: border-box;
|
|
23
54
|
display: inline-flex;
|
|
24
55
|
align-items: center;
|
|
25
|
-
gap:
|
|
26
|
-
padding: 0
|
|
56
|
+
gap: 6px;
|
|
57
|
+
padding: 0 15px;
|
|
27
58
|
border: 1px solid var(--vmz-line-default);
|
|
28
|
-
border-radius: var(--vmz-radius-md
|
|
59
|
+
border-radius: var(--vmz-radius-md);
|
|
29
60
|
background: var(--vmz-surface-paper);
|
|
30
61
|
color: var(--vmz-text-ink);
|
|
31
62
|
cursor: pointer;
|
|
32
|
-
font
|
|
63
|
+
font: inherit;
|
|
64
|
+
font-size: 14px;
|
|
65
|
+
font-weight: 500;
|
|
66
|
+
line-height: 22px;
|
|
33
67
|
outline: none;
|
|
34
68
|
transition:
|
|
35
|
-
border-color var(--vmz-motion-control-duration
|
|
36
|
-
background-color var(--vmz-motion-control-duration
|
|
37
|
-
box-shadow var(--vmz-motion-control-duration, 150ms) var(--vmz-motion-control-easing, cubic-bezier(0.4, 0, 0.2, 1));
|
|
69
|
+
border-color var(--vmz-motion-control-duration) var(--vmz-motion-control-easing),
|
|
70
|
+
background-color var(--vmz-motion-control-duration) var(--vmz-motion-control-easing);
|
|
38
71
|
}
|
|
39
72
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
content: "";
|
|
43
|
-
width: 0.4375rem;
|
|
44
|
-
height: 0.4375rem;
|
|
45
|
-
margin-top: -0.1875rem;
|
|
46
|
-
border-right: 1.5px solid currentColor;
|
|
47
|
-
border-bottom: 1.5px solid currentColor;
|
|
48
|
-
opacity: 0.55;
|
|
49
|
-
transform: rotate(45deg);
|
|
50
|
-
transition: transform var(--vmz-motion-control-duration, 150ms) var(--vmz-motion-control-easing, cubic-bezier(0.4, 0, 0.2, 1));
|
|
73
|
+
.vmz-ui-dropdown summary::-webkit-details-marker {
|
|
74
|
+
display: none;
|
|
51
75
|
}
|
|
52
76
|
|
|
53
|
-
.vmz-ui-
|
|
77
|
+
.vmz-ui-dropdown__trigger-label:empty {
|
|
54
78
|
display: none;
|
|
55
79
|
}
|
|
56
80
|
|
|
81
|
+
.vmz-ui-dropdown__trigger .vmz-ui-icon {
|
|
82
|
+
flex: 0 0 auto;
|
|
83
|
+
color: var(--vmz-text-tertiary);
|
|
84
|
+
transition: transform var(--vmz-motion-control-duration) var(--vmz-motion-control-easing);
|
|
85
|
+
}
|
|
86
|
+
|
|
57
87
|
.vmz-ui-dropdown__trigger:hover {
|
|
58
88
|
border-color: var(--vmz-action-primary-hover);
|
|
59
89
|
background: var(--vmz-surface-mist);
|
|
@@ -67,34 +97,40 @@
|
|
|
67
97
|
border-color: var(--vmz-action-primary-background);
|
|
68
98
|
}
|
|
69
99
|
|
|
70
|
-
.vmz-ui-dropdown[open] > .vmz-ui-dropdown__trigger
|
|
71
|
-
|
|
72
|
-
transform: rotate(-135deg);
|
|
100
|
+
.vmz-ui-dropdown[open] > .vmz-ui-dropdown__trigger .vmz-ui-icon {
|
|
101
|
+
transform: rotate(180deg);
|
|
73
102
|
}
|
|
74
103
|
|
|
75
104
|
.vmz-ui-dropdown__menu {
|
|
76
105
|
position: absolute;
|
|
77
|
-
top: calc(100% +
|
|
106
|
+
top: calc(100% + 6px);
|
|
78
107
|
right: 0;
|
|
79
108
|
z-index: 50;
|
|
80
|
-
min-width:
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
border
|
|
109
|
+
min-width: 176px;
|
|
110
|
+
box-sizing: border-box;
|
|
111
|
+
padding: 4px;
|
|
112
|
+
border: 1px solid var(--vmz-line-subtle);
|
|
113
|
+
border-radius: var(--vmz-radius-lg);
|
|
84
114
|
background: var(--vmz-surface-paper);
|
|
115
|
+
color: var(--vmz-text-ink);
|
|
85
116
|
box-shadow: var(--vmz-shadow-popup);
|
|
86
117
|
transform-origin: top right;
|
|
87
|
-
animation: vmz-dropdown-in var(--vmz-motion-overlay-duration
|
|
118
|
+
animation: vmz-dropdown-in var(--vmz-motion-overlay-duration)
|
|
119
|
+
var(--vmz-motion-overlay-easing);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.vmz-ui-dropdown__item--sub {
|
|
123
|
+
list-style: none;
|
|
88
124
|
}
|
|
89
125
|
|
|
90
126
|
@keyframes vmz-dropdown-in {
|
|
91
127
|
from {
|
|
92
128
|
opacity: 0;
|
|
93
|
-
transform: translateY(-
|
|
129
|
+
transform: translateY(-4px) scale(0.98);
|
|
94
130
|
}
|
|
95
131
|
to {
|
|
96
132
|
opacity: 1;
|
|
97
|
-
transform:
|
|
133
|
+
transform: none;
|
|
98
134
|
}
|
|
99
135
|
}
|
|
100
136
|
|
|
@@ -103,7 +139,7 @@
|
|
|
103
139
|
animation: none;
|
|
104
140
|
}
|
|
105
141
|
.vmz-ui-dropdown__trigger,
|
|
106
|
-
.vmz-ui-dropdown__trigger
|
|
142
|
+
.vmz-ui-dropdown__trigger .vmz-ui-icon {
|
|
107
143
|
transition: none;
|
|
108
144
|
}
|
|
109
145
|
}
|
|
@@ -113,17 +149,27 @@
|
|
|
113
149
|
}
|
|
114
150
|
|
|
115
151
|
.vmz-ui-dropdown__item {
|
|
116
|
-
display:
|
|
117
|
-
|
|
118
|
-
|
|
152
|
+
display: flex;
|
|
153
|
+
align-items: center;
|
|
154
|
+
gap: 8px;
|
|
155
|
+
width: 100%;
|
|
156
|
+
min-height: 32px;
|
|
157
|
+
box-sizing: border-box;
|
|
158
|
+
padding: 0 12px;
|
|
159
|
+
border: 0;
|
|
160
|
+
border-radius: var(--vmz-radius-md);
|
|
161
|
+
background: transparent;
|
|
119
162
|
color: var(--vmz-text-ink);
|
|
120
|
-
|
|
121
|
-
|
|
163
|
+
cursor: pointer;
|
|
164
|
+
font: inherit;
|
|
165
|
+
font-size: 14px;
|
|
166
|
+
line-height: 22px;
|
|
167
|
+
text-align: left;
|
|
122
168
|
text-decoration: none;
|
|
123
169
|
outline: none;
|
|
124
170
|
transition:
|
|
125
|
-
background-color var(--vmz-motion-control-duration
|
|
126
|
-
color var(--vmz-motion-control-duration
|
|
171
|
+
background-color var(--vmz-motion-control-duration) var(--vmz-motion-control-easing),
|
|
172
|
+
color var(--vmz-motion-control-duration) var(--vmz-motion-control-easing);
|
|
127
173
|
}
|
|
128
174
|
|
|
129
175
|
.vmz-ui-dropdown__item:hover {
|
|
@@ -132,49 +178,147 @@
|
|
|
132
178
|
|
|
133
179
|
.vmz-ui-dropdown__item:focus-visible {
|
|
134
180
|
background: var(--vmz-surface-mist);
|
|
135
|
-
box-shadow: inset 0 0 0
|
|
181
|
+
box-shadow: inset 0 0 0 2px var(--vmz-focus-ring);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.vmz-ui-dropdown__item[data-active="true"] {
|
|
185
|
+
background: color-mix(in srgb, var(--vmz-action-primary-background) 10%, transparent);
|
|
186
|
+
box-shadow: inset 2px 0 0 var(--vmz-action-primary-background);
|
|
136
187
|
}
|
|
137
188
|
|
|
138
189
|
.vmz-ui-dropdown__item[data-danger="true"] {
|
|
139
190
|
color: var(--vmz-status-danger-foreground);
|
|
140
191
|
}
|
|
141
192
|
|
|
142
|
-
.vmz-ui-dropdown__item[data-danger="true"]:hover
|
|
193
|
+
.vmz-ui-dropdown__item[data-danger="true"]:hover,
|
|
194
|
+
.vmz-ui-dropdown__item[data-danger="true"]:focus-visible {
|
|
143
195
|
background: color-mix(in srgb, var(--vmz-status-danger-accent) 12%, transparent);
|
|
144
196
|
}
|
|
145
197
|
|
|
146
198
|
.vmz-ui-dropdown__item[data-disabled="true"] {
|
|
147
|
-
color: var(--vmz-text-
|
|
199
|
+
color: var(--vmz-text-tertiary);
|
|
148
200
|
cursor: not-allowed;
|
|
149
201
|
pointer-events: none;
|
|
150
202
|
}
|
|
151
203
|
|
|
152
204
|
.vmz-ui-dropdown__divider {
|
|
153
205
|
height: 1px;
|
|
154
|
-
margin:
|
|
155
|
-
background: var(--vmz-line-subtle
|
|
206
|
+
margin: 4px 8px;
|
|
207
|
+
background: var(--vmz-line-subtle);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.vmz-ui-dropdown__group {
|
|
211
|
+
padding: 8px 12px 4px;
|
|
212
|
+
font-size: 12px;
|
|
213
|
+
font-weight: 600;
|
|
214
|
+
line-height: 20px;
|
|
215
|
+
color: var(--vmz-text-tertiary);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.vmz-ui-dropdown__label {
|
|
219
|
+
flex: 1 1 auto;
|
|
220
|
+
min-width: 0;
|
|
221
|
+
overflow: hidden;
|
|
222
|
+
text-overflow: ellipsis;
|
|
223
|
+
white-space: nowrap;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.vmz-ui-dropdown__item--sub .vmz-ui-icon {
|
|
227
|
+
flex: 0 0 auto;
|
|
228
|
+
color: var(--vmz-text-tertiary);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.vmz-ui-dropdown__sub {
|
|
232
|
+
position: relative;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
.vmz-ui-dropdown__sub[open] > .vmz-ui-dropdown__item--sub {
|
|
236
|
+
background: var(--vmz-surface-mist);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.vmz-ui-dropdown__subpanel {
|
|
240
|
+
display: flex;
|
|
241
|
+
flex-direction: column;
|
|
242
|
+
margin: 2px 0 4px;
|
|
243
|
+
padding: 4px 0 4px 12px;
|
|
244
|
+
border-left: 1px solid var(--vmz-line-subtle);
|
|
156
245
|
}
|
|
157
246
|
</style>
|
|
158
247
|
<script client>
|
|
159
248
|
/**
|
|
160
249
|
* VMZ UI — Dropdown (Menu).
|
|
161
|
-
* Native `<details>` disclosure: works without JS
|
|
162
|
-
*
|
|
250
|
+
* Native `<details>` disclosure: works without JS. An item with a non-empty
|
|
251
|
+
* `href` is a plain link; an item without `href` is an action button that
|
|
252
|
+
* notifies via `onSelect(id)`. Selection handlers never navigate.
|
|
253
|
+
*
|
|
254
|
+
* Item model adds `kind: "group"` headers, `active` styling and one level of
|
|
255
|
+
* nested `children` rendered inside a nested `<details>` submenu.
|
|
163
256
|
*/
|
|
164
257
|
export type DropdownItem = {
|
|
165
258
|
id: string;
|
|
166
259
|
title: string;
|
|
260
|
+
/** Non-empty → link item (native navigation). Empty/absent → action item. */
|
|
167
261
|
href?: string;
|
|
168
262
|
/** Destructive action styling. */
|
|
169
263
|
danger?: boolean;
|
|
170
|
-
/** Non-interactive state. */
|
|
264
|
+
/** Non-interactive state: neither navigates nor selects. */
|
|
171
265
|
disabled?: boolean;
|
|
172
266
|
/** Render a separator instead of a row (title/href are ignored). */
|
|
173
267
|
divider?: boolean;
|
|
268
|
+
/** `"group"` renders a 12px tertiary section title. */
|
|
269
|
+
kind?: string;
|
|
270
|
+
/** Current selection — light primary fill plus a 2px leading bar. */
|
|
271
|
+
active?: boolean;
|
|
272
|
+
/** One level of nested items rendered as a submenu. */
|
|
273
|
+
children?: DropdownItem[];
|
|
174
274
|
};
|
|
175
275
|
|
|
176
276
|
export default class Dropdown {
|
|
177
|
-
public label: string = "
|
|
277
|
+
public label: string = "";
|
|
178
278
|
public items: DropdownItem[] = [];
|
|
279
|
+
/** Action-item selection callback (`:on-select`). Link items bypass it. */
|
|
280
|
+
public onSelect: ((id: string) => void) | null = null;
|
|
281
|
+
|
|
282
|
+
hasHref(item) {
|
|
283
|
+
return typeof item?.href === "string" && item.href.length > 0;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
onItemClick(ev) {
|
|
287
|
+
const el = ev && ev.currentTarget;
|
|
288
|
+
const id =
|
|
289
|
+
el && typeof el.getAttribute === "function"
|
|
290
|
+
? el.getAttribute("data-vmz-dropdown-item")
|
|
291
|
+
: null;
|
|
292
|
+
if (!id) return;
|
|
293
|
+
const item = this._findItem(id);
|
|
294
|
+
if (!item || item.disabled || this.hasHref(item)) return;
|
|
295
|
+
this.close();
|
|
296
|
+
if (typeof this.onSelect === "function") this.onSelect(id);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
_findItem(id) {
|
|
300
|
+
for (const item of this.items || []) {
|
|
301
|
+
if (item.id === id) return item;
|
|
302
|
+
if (Array.isArray(item.children)) {
|
|
303
|
+
const child = item.children.find((candidate) => candidate.id === id);
|
|
304
|
+
if (child) return child;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
return null;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
close() {
|
|
311
|
+
const root = this.__vmzDomRoot;
|
|
312
|
+
if (!root) return;
|
|
313
|
+
const details =
|
|
314
|
+
root.tagName === "DETAILS"
|
|
315
|
+
? root
|
|
316
|
+
: typeof root.closest === "function"
|
|
317
|
+
? root.closest("details")
|
|
318
|
+
: null;
|
|
319
|
+
if (details && typeof details.removeAttribute === "function") {
|
|
320
|
+
details.removeAttribute("open");
|
|
321
|
+
}
|
|
322
|
+
}
|
|
179
323
|
}
|
|
180
324
|
</script>
|
package/src/components/Empty.vmz
CHANGED
|
@@ -1,54 +1,96 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div data-vmz-ui="empty" class="vmz-ui-empty">
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
</
|
|
6
|
-
<
|
|
7
|
-
{{
|
|
8
|
-
</
|
|
9
|
-
<
|
|
10
|
-
|
|
11
|
-
</
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
1
|
+
<template>
|
|
2
|
+
<div data-vmz-ui="empty" class="vmz-ui-empty">
|
|
3
|
+
<span aria-hidden="true" class="vmz-ui-empty__illustration">
|
|
4
|
+
<Icon :name="icon" size="lg" decorative />
|
|
5
|
+
</span>
|
|
6
|
+
<h2 v-if="title" class="vmz-ui-empty__title">
|
|
7
|
+
{{ title }}
|
|
8
|
+
</h2>
|
|
9
|
+
<p v-if="description" class="vmz-ui-empty__description">
|
|
10
|
+
{{ description }}
|
|
11
|
+
</p>
|
|
12
|
+
<div class="vmz-ui-empty__actions">
|
|
13
|
+
<slot />
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
</template>
|
|
17
|
+
<style>
|
|
18
|
+
.vmz-ui-empty {
|
|
19
|
+
display: flex;
|
|
20
|
+
flex-direction: column;
|
|
21
|
+
align-items: center;
|
|
22
|
+
justify-content: center;
|
|
23
|
+
gap: var(--vmz-space-2, 0.5rem);
|
|
24
|
+
padding: var(--vmz-space-6, 2rem);
|
|
25
|
+
text-align: center;
|
|
26
|
+
background: transparent;
|
|
27
|
+
color: var(--vmz-text-ink);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.vmz-ui-empty__illustration {
|
|
31
|
+
display: inline-flex;
|
|
32
|
+
align-items: center;
|
|
33
|
+
justify-content: center;
|
|
34
|
+
width: 4rem;
|
|
35
|
+
height: 4rem;
|
|
36
|
+
margin-bottom: var(--vmz-space-1, 0.25rem);
|
|
37
|
+
border: 1px solid var(--vmz-line-default, var(--vmz-line-strong));
|
|
38
|
+
border-radius: var(--vmz-radius-pill, 999px);
|
|
39
|
+
background: var(--vmz-surface-mist);
|
|
40
|
+
color: var(--vmz-text-muted);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.vmz-ui-empty__illustration .vmz-ui-icon[data-size] {
|
|
44
|
+
font-size: 2rem;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.vmz-ui-empty__title {
|
|
48
|
+
margin: 0;
|
|
49
|
+
font-family: var(--vmz-font-display, var(--vmz-font-sans, inherit));
|
|
50
|
+
font-size: 1rem;
|
|
51
|
+
font-weight: 600;
|
|
52
|
+
line-height: 1.4;
|
|
53
|
+
color: var(--vmz-text-ink);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.vmz-ui-empty__description {
|
|
57
|
+
margin: 0;
|
|
58
|
+
max-width: 36rem;
|
|
59
|
+
font-size: 0.875rem;
|
|
60
|
+
line-height: 1.55;
|
|
61
|
+
color: var(--vmz-text-tertiary);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.vmz-ui-empty__actions {
|
|
65
|
+
display: flex;
|
|
66
|
+
flex-wrap: wrap;
|
|
67
|
+
justify-content: center;
|
|
68
|
+
gap: var(--vmz-space-2, 0.5rem);
|
|
69
|
+
margin-top: var(--vmz-space-2, 0.5rem);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.vmz-ui-empty__actions:empty {
|
|
73
|
+
display: none;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
:where([data-density="compact"]) .vmz-ui-empty {
|
|
77
|
+
gap: var(--vmz-density-compact-gap);
|
|
78
|
+
padding: var(--vmz-space-5, 1.5rem);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
:where([data-density="dense"]) .vmz-ui-empty {
|
|
82
|
+
gap: var(--vmz-density-dense-gap);
|
|
83
|
+
padding: var(--vmz-space-4, 1rem);
|
|
84
|
+
}
|
|
85
|
+
</style>
|
|
86
|
+
<script client>
|
|
87
|
+
/**
|
|
88
|
+
* VMZ UI — Empty (Commercial composition).
|
|
89
|
+
* Empty / zero-state surface with neutral registry icon and optional action slot.
|
|
90
|
+
*/
|
|
91
|
+
export default class Empty {
|
|
92
|
+
public title: string = "";
|
|
93
|
+
public description: string = "";
|
|
94
|
+
public icon: string = "feature.runtime";
|
|
95
|
+
}
|
|
96
|
+
</script>
|