@vmz/ui 0.3.7 → 0.3.9
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 +2 -0
- 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 +49 -16
- package/src/components/Alert.vmz +125 -28
- package/src/components/AppShell.vmz +121 -56
- package/src/components/Autocomplete.vmz +136 -29
- package/src/components/Avatar.vmz +20 -12
- package/src/components/Badge.vmz +18 -26
- package/src/components/Breadcrumb.vmz +28 -14
- package/src/components/BulkActions.vmz +13 -8
- package/src/components/Button.vmz +68 -44
- package/src/components/Callout.vmz +128 -27
- package/src/components/Card.vmz +67 -46
- package/src/components/Checkbox.vmz +81 -5
- package/src/components/CodeBlock.vmz +59 -27
- package/src/components/Collapse.vmz +64 -11
- package/src/components/ConsoleShell.vmz +249 -69
- package/src/components/Content.vmz +15 -1
- package/src/components/DataTable.vmz +123 -23
- package/src/components/DatePicker.vmz +171 -79
- package/src/components/Descriptions.vmz +90 -0
- package/src/components/Dialog.vmz +133 -50
- package/src/components/Divider.vmz +8 -1
- package/src/components/Drawer.vmz +131 -40
- package/src/components/Dropdown.vmz +147 -49
- package/src/components/Empty.vmz +56 -14
- package/src/components/Field.vmz +78 -23
- 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 +2 -3
- 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 +20 -9
- package/src/components/List.vmz +35 -13
- package/src/components/Menu.vmz +198 -25
- package/src/components/Message.vmz +167 -0
- package/src/components/Notification.vmz +132 -37
- package/src/components/Pagination.vmz +186 -20
- package/src/components/Popconfirm.vmz +287 -0
- package/src/components/Popover.vmz +152 -34
- package/src/components/Progress.vmz +16 -5
- package/src/components/Prose.vmz +131 -32
- package/src/components/QueryForm.vmz +31 -9
- package/src/components/RadioGroup.vmz +91 -11
- package/src/components/Result.vmz +60 -27
- package/src/components/Segmented.vmz +46 -11
- package/src/components/Select.vmz +174 -87
- 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 +40 -25
- package/src/components/Switch.vmz +48 -15
- package/src/components/Table.vmz +130 -25
- package/src/components/Tabs.vmz +28 -13
- package/src/components/Tag.vmz +29 -12
- package/src/components/TextArea.vmz +32 -25
- package/src/components/Timeline.vmz +65 -30
- package/src/components/Toc.vmz +45 -29
- package/src/components/Tooltip.vmz +70 -21
- package/src/components/Tree.vmz +48 -25
- package/src/components/Typography.vmz +23 -8
- package/src/components/Upload.vmz +191 -96
|
@@ -1,15 +1,40 @@
|
|
|
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
11
|
<div v-if="item.divider" role="separator" class="vmz-ui-dropdown__divider" />
|
|
9
|
-
<
|
|
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">
|
|
10
35
|
{{ item.title }}
|
|
11
36
|
</a>
|
|
12
|
-
<button v-else type="button" role="menuitem" :data-vmz-dropdown-item="item.id" :data-danger="item.danger ? '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">
|
|
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">
|
|
13
38
|
{{ item.title }}
|
|
14
39
|
</button>
|
|
15
40
|
</div>
|
|
@@ -24,41 +49,41 @@
|
|
|
24
49
|
|
|
25
50
|
.vmz-ui-dropdown__trigger {
|
|
26
51
|
list-style: none;
|
|
27
|
-
min-height:
|
|
52
|
+
min-height: 40px;
|
|
53
|
+
box-sizing: border-box;
|
|
28
54
|
display: inline-flex;
|
|
29
55
|
align-items: center;
|
|
30
|
-
gap:
|
|
31
|
-
padding: 0
|
|
56
|
+
gap: 6px;
|
|
57
|
+
padding: 0 15px;
|
|
32
58
|
border: 1px solid var(--vmz-line-default);
|
|
33
|
-
border-radius: var(--vmz-radius-md
|
|
59
|
+
border-radius: var(--vmz-radius-md);
|
|
34
60
|
background: var(--vmz-surface-paper);
|
|
35
61
|
color: var(--vmz-text-ink);
|
|
36
62
|
cursor: pointer;
|
|
37
|
-
font
|
|
63
|
+
font: inherit;
|
|
64
|
+
font-size: 14px;
|
|
65
|
+
font-weight: 500;
|
|
66
|
+
line-height: 22px;
|
|
38
67
|
outline: none;
|
|
39
68
|
transition:
|
|
40
|
-
border-color var(--vmz-motion-control-duration
|
|
41
|
-
background-color var(--vmz-motion-control-duration
|
|
42
|
-
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);
|
|
43
71
|
}
|
|
44
72
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
content: "";
|
|
48
|
-
width: 0.4375rem;
|
|
49
|
-
height: 0.4375rem;
|
|
50
|
-
margin-top: -0.1875rem;
|
|
51
|
-
border-right: 1.5px solid currentColor;
|
|
52
|
-
border-bottom: 1.5px solid currentColor;
|
|
53
|
-
opacity: 0.55;
|
|
54
|
-
transform: rotate(45deg);
|
|
55
|
-
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;
|
|
56
75
|
}
|
|
57
76
|
|
|
58
|
-
.vmz-ui-
|
|
77
|
+
.vmz-ui-dropdown__trigger-label:empty {
|
|
59
78
|
display: none;
|
|
60
79
|
}
|
|
61
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
|
+
|
|
62
87
|
.vmz-ui-dropdown__trigger:hover {
|
|
63
88
|
border-color: var(--vmz-action-primary-hover);
|
|
64
89
|
background: var(--vmz-surface-mist);
|
|
@@ -72,34 +97,40 @@
|
|
|
72
97
|
border-color: var(--vmz-action-primary-background);
|
|
73
98
|
}
|
|
74
99
|
|
|
75
|
-
.vmz-ui-dropdown[open] > .vmz-ui-dropdown__trigger
|
|
76
|
-
|
|
77
|
-
transform: rotate(-135deg);
|
|
100
|
+
.vmz-ui-dropdown[open] > .vmz-ui-dropdown__trigger .vmz-ui-icon {
|
|
101
|
+
transform: rotate(180deg);
|
|
78
102
|
}
|
|
79
103
|
|
|
80
104
|
.vmz-ui-dropdown__menu {
|
|
81
105
|
position: absolute;
|
|
82
|
-
top: calc(100% +
|
|
106
|
+
top: calc(100% + 6px);
|
|
83
107
|
right: 0;
|
|
84
108
|
z-index: 50;
|
|
85
|
-
min-width:
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
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);
|
|
89
114
|
background: var(--vmz-surface-paper);
|
|
115
|
+
color: var(--vmz-text-ink);
|
|
90
116
|
box-shadow: var(--vmz-shadow-popup);
|
|
91
117
|
transform-origin: top right;
|
|
92
|
-
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;
|
|
93
124
|
}
|
|
94
125
|
|
|
95
126
|
@keyframes vmz-dropdown-in {
|
|
96
127
|
from {
|
|
97
128
|
opacity: 0;
|
|
98
|
-
transform: translateY(-
|
|
129
|
+
transform: translateY(-4px) scale(0.98);
|
|
99
130
|
}
|
|
100
131
|
to {
|
|
101
132
|
opacity: 1;
|
|
102
|
-
transform:
|
|
133
|
+
transform: none;
|
|
103
134
|
}
|
|
104
135
|
}
|
|
105
136
|
|
|
@@ -108,7 +139,7 @@
|
|
|
108
139
|
animation: none;
|
|
109
140
|
}
|
|
110
141
|
.vmz-ui-dropdown__trigger,
|
|
111
|
-
.vmz-ui-dropdown__trigger
|
|
142
|
+
.vmz-ui-dropdown__trigger .vmz-ui-icon {
|
|
112
143
|
transition: none;
|
|
113
144
|
}
|
|
114
145
|
}
|
|
@@ -118,23 +149,27 @@
|
|
|
118
149
|
}
|
|
119
150
|
|
|
120
151
|
.vmz-ui-dropdown__item {
|
|
121
|
-
display:
|
|
152
|
+
display: flex;
|
|
153
|
+
align-items: center;
|
|
154
|
+
gap: 8px;
|
|
122
155
|
width: 100%;
|
|
123
|
-
|
|
156
|
+
min-height: 32px;
|
|
157
|
+
box-sizing: border-box;
|
|
158
|
+
padding: 0 12px;
|
|
124
159
|
border: 0;
|
|
125
|
-
border-radius: var(--vmz-radius-
|
|
160
|
+
border-radius: var(--vmz-radius-md);
|
|
126
161
|
background: transparent;
|
|
127
162
|
color: var(--vmz-text-ink);
|
|
128
163
|
cursor: pointer;
|
|
129
164
|
font: inherit;
|
|
130
|
-
font-size:
|
|
131
|
-
line-height:
|
|
165
|
+
font-size: 14px;
|
|
166
|
+
line-height: 22px;
|
|
132
167
|
text-align: left;
|
|
133
168
|
text-decoration: none;
|
|
134
169
|
outline: none;
|
|
135
170
|
transition:
|
|
136
|
-
background-color var(--vmz-motion-control-duration
|
|
137
|
-
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);
|
|
138
173
|
}
|
|
139
174
|
|
|
140
175
|
.vmz-ui-dropdown__item:hover {
|
|
@@ -143,27 +178,70 @@
|
|
|
143
178
|
|
|
144
179
|
.vmz-ui-dropdown__item:focus-visible {
|
|
145
180
|
background: var(--vmz-surface-mist);
|
|
146
|
-
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);
|
|
147
187
|
}
|
|
148
188
|
|
|
149
189
|
.vmz-ui-dropdown__item[data-danger="true"] {
|
|
150
190
|
color: var(--vmz-status-danger-foreground);
|
|
151
191
|
}
|
|
152
192
|
|
|
153
|
-
.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 {
|
|
154
195
|
background: color-mix(in srgb, var(--vmz-status-danger-accent) 12%, transparent);
|
|
155
196
|
}
|
|
156
197
|
|
|
157
198
|
.vmz-ui-dropdown__item[data-disabled="true"] {
|
|
158
|
-
color: var(--vmz-text-
|
|
199
|
+
color: var(--vmz-text-tertiary);
|
|
159
200
|
cursor: not-allowed;
|
|
160
201
|
pointer-events: none;
|
|
161
202
|
}
|
|
162
203
|
|
|
163
204
|
.vmz-ui-dropdown__divider {
|
|
164
205
|
height: 1px;
|
|
165
|
-
margin:
|
|
166
|
-
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);
|
|
167
245
|
}
|
|
168
246
|
</style>
|
|
169
247
|
<script client>
|
|
@@ -172,6 +250,9 @@
|
|
|
172
250
|
* Native `<details>` disclosure: works without JS. An item with a non-empty
|
|
173
251
|
* `href` is a plain link; an item without `href` is an action button that
|
|
174
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.
|
|
175
256
|
*/
|
|
176
257
|
export type DropdownItem = {
|
|
177
258
|
id: string;
|
|
@@ -184,10 +265,16 @@ export type DropdownItem = {
|
|
|
184
265
|
disabled?: boolean;
|
|
185
266
|
/** Render a separator instead of a row (title/href are ignored). */
|
|
186
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[];
|
|
187
274
|
};
|
|
188
275
|
|
|
189
276
|
export default class Dropdown {
|
|
190
|
-
public label: string = "
|
|
277
|
+
public label: string = "";
|
|
191
278
|
public items: DropdownItem[] = [];
|
|
192
279
|
/** Action-item selection callback (`:on-select`). Link items bypass it. */
|
|
193
280
|
public onSelect: ((id: string) => void) | null = null;
|
|
@@ -203,12 +290,23 @@ export default class Dropdown {
|
|
|
203
290
|
? el.getAttribute("data-vmz-dropdown-item")
|
|
204
291
|
: null;
|
|
205
292
|
if (!id) return;
|
|
206
|
-
const item = this.
|
|
293
|
+
const item = this._findItem(id);
|
|
207
294
|
if (!item || item.disabled || this.hasHref(item)) return;
|
|
208
295
|
this.close();
|
|
209
296
|
if (typeof this.onSelect === "function") this.onSelect(id);
|
|
210
297
|
}
|
|
211
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
|
+
|
|
212
310
|
close() {
|
|
213
311
|
const root = this.__vmzDomRoot;
|
|
214
312
|
if (!root) return;
|
package/src/components/Empty.vmz
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div data-vmz-ui="empty" class="vmz-ui-empty">
|
|
3
|
-
<
|
|
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">
|
|
4
7
|
{{ title }}
|
|
5
8
|
</h2>
|
|
6
9
|
<p v-if="description" class="vmz-ui-empty__description">
|
|
@@ -15,40 +18,79 @@
|
|
|
15
18
|
.vmz-ui-empty {
|
|
16
19
|
display: flex;
|
|
17
20
|
flex-direction: column;
|
|
18
|
-
align-items:
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
background:
|
|
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;
|
|
24
27
|
color: var(--vmz-text-ink);
|
|
25
28
|
}
|
|
26
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
|
+
|
|
27
47
|
.vmz-ui-empty__title {
|
|
28
48
|
margin: 0;
|
|
29
|
-
font-family: var(--vmz-font-display);
|
|
30
|
-
font-size:
|
|
31
|
-
font-weight:
|
|
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);
|
|
32
54
|
}
|
|
33
55
|
|
|
34
56
|
.vmz-ui-empty__description {
|
|
35
57
|
margin: 0;
|
|
36
|
-
color: var(--vmz-text-steel);
|
|
37
58
|
max-width: 36rem;
|
|
38
|
-
|
|
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);
|
|
39
70
|
}
|
|
40
71
|
|
|
41
72
|
.vmz-ui-empty__actions:empty {
|
|
42
73
|
display: none;
|
|
43
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
|
+
}
|
|
44
85
|
</style>
|
|
45
86
|
<script client>
|
|
46
87
|
/**
|
|
47
88
|
* VMZ UI — Empty (Commercial composition).
|
|
48
|
-
* Empty / zero-state surface with optional action slot.
|
|
89
|
+
* Empty / zero-state surface with neutral registry icon and optional action slot.
|
|
49
90
|
*/
|
|
50
91
|
export default class Empty {
|
|
51
|
-
public title: string = "
|
|
92
|
+
public title: string = "";
|
|
52
93
|
public description: string = "";
|
|
94
|
+
public icon: string = "feature.runtime";
|
|
53
95
|
}
|
|
54
96
|
</script>
|
package/src/components/Field.vmz
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div data-vmz-ui="field" :data-invalid="
|
|
2
|
+
<div data-vmz-ui="field" :data-invalid="error ? 'true' : 'false'" class="vmz-ui-field">
|
|
3
3
|
<label v-if="label" :for="controlId" class="vmz-ui-field__label">
|
|
4
4
|
{{ label }}
|
|
5
5
|
</label>
|
|
6
|
-
<
|
|
6
|
+
<div :data-prefix="prefix ? 'true' : 'false'" :data-suffix="suffix ? 'true' : 'false'" class="vmz-ui-field__control-wrap">
|
|
7
|
+
<Icon v-if="prefix" :name="prefix" size="md" decorative class="vmz-ui-field__icon vmz-ui-field__icon--prefix" />
|
|
8
|
+
<input :id="controlId" :type="type" :value="value" :min="min" :max="max" :step="step" :placeholder="placeholder" :disabled="disabled" :readonly="readonly" :aria-invalid="error ? 'true' : 'false'" :aria-describedby="describedBy" @input="onDomInput" class="vmz-ui-field__control" />
|
|
9
|
+
<Icon v-if="suffix" :name="suffix" size="md" decorative class="vmz-ui-field__icon vmz-ui-field__icon--suffix" />
|
|
10
|
+
</div>
|
|
7
11
|
<p v-if="description" :id="descriptionId" class="vmz-ui-field__description">
|
|
8
12
|
{{ description }}
|
|
9
13
|
</p>
|
|
@@ -16,7 +20,8 @@
|
|
|
16
20
|
.vmz-ui-field {
|
|
17
21
|
display: flex;
|
|
18
22
|
flex-direction: column;
|
|
19
|
-
gap:
|
|
23
|
+
gap: var(--vmz-space-2);
|
|
24
|
+
width: 100%;
|
|
20
25
|
max-width: 28rem;
|
|
21
26
|
}
|
|
22
27
|
|
|
@@ -24,32 +29,67 @@
|
|
|
24
29
|
font: inherit;
|
|
25
30
|
font-weight: 500;
|
|
26
31
|
font-size: 0.875rem;
|
|
27
|
-
|
|
32
|
+
line-height: 1.5715;
|
|
33
|
+
color: var(--vmz-text-ink);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.vmz-ui-field__control-wrap {
|
|
37
|
+
position: relative;
|
|
38
|
+
display: flex;
|
|
39
|
+
align-items: center;
|
|
40
|
+
width: 100%;
|
|
28
41
|
}
|
|
29
42
|
|
|
30
43
|
.vmz-ui-field__control {
|
|
31
44
|
box-sizing: border-box;
|
|
32
45
|
width: 100%;
|
|
33
|
-
min-height: var(--vmz-control-height
|
|
34
|
-
font-family:
|
|
46
|
+
min-height: var(--vmz-control-height);
|
|
47
|
+
font-family: inherit;
|
|
35
48
|
font-size: 0.875rem;
|
|
36
49
|
line-height: 1.5715;
|
|
37
|
-
padding: var(--vmz-density-control-padding-y
|
|
38
|
-
|
|
39
|
-
border:
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
color: var(--vmz-text-ink, inherit);
|
|
50
|
+
padding: var(--vmz-density-control-padding-y) var(--vmz-density-control-padding-x);
|
|
51
|
+
border: 1px solid var(--vmz-line-default);
|
|
52
|
+
border-radius: var(--vmz-radius-lg);
|
|
53
|
+
background: var(--vmz-surface-paper);
|
|
54
|
+
color: var(--vmz-text-ink);
|
|
43
55
|
outline: none;
|
|
44
56
|
transition:
|
|
45
|
-
border-color var(--vmz-motion-control-duration
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
57
|
+
border-color var(--vmz-motion-control-duration) var(--vmz-motion-control-easing),
|
|
58
|
+
box-shadow var(--vmz-motion-control-duration) var(--vmz-motion-control-easing),
|
|
59
|
+
background-color var(--vmz-motion-control-duration) var(--vmz-motion-control-easing);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.vmz-ui-field__control-wrap[data-prefix="true"] .vmz-ui-field__control {
|
|
63
|
+
padding-left: calc(
|
|
64
|
+
var(--vmz-density-control-padding-x) + var(--vmz-space-4) + var(--vmz-space-1)
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.vmz-ui-field__control-wrap[data-suffix="true"] .vmz-ui-field__control {
|
|
69
|
+
padding-right: calc(
|
|
70
|
+
var(--vmz-density-control-padding-x) + var(--vmz-space-4) + var(--vmz-space-1)
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.vmz-ui-field__icon {
|
|
75
|
+
position: absolute;
|
|
76
|
+
top: 50%;
|
|
77
|
+
z-index: 1;
|
|
78
|
+
color: var(--vmz-text-tertiary);
|
|
79
|
+
transform: translateY(-50%);
|
|
80
|
+
pointer-events: none;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.vmz-ui-field__icon--prefix {
|
|
84
|
+
left: var(--vmz-density-control-padding-x);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.vmz-ui-field__icon--suffix {
|
|
88
|
+
right: var(--vmz-density-control-padding-x);
|
|
49
89
|
}
|
|
50
90
|
|
|
51
91
|
.vmz-ui-field__control::placeholder {
|
|
52
|
-
color: var(--vmz-text-
|
|
92
|
+
color: var(--vmz-text-tertiary);
|
|
53
93
|
opacity: 1;
|
|
54
94
|
}
|
|
55
95
|
|
|
@@ -57,8 +97,13 @@
|
|
|
57
97
|
border-color: var(--vmz-status-danger-accent);
|
|
58
98
|
}
|
|
59
99
|
|
|
100
|
+
.vmz-ui-field[data-invalid="true"] .vmz-ui-field__control:hover:not(:disabled),
|
|
101
|
+
.vmz-ui-field[data-invalid="true"] .vmz-ui-field__control:focus-visible {
|
|
102
|
+
border-color: var(--vmz-status-danger-foreground);
|
|
103
|
+
}
|
|
104
|
+
|
|
60
105
|
.vmz-ui-field__control:hover:not(:disabled):not(:focus-visible) {
|
|
61
|
-
border-color: var(--vmz-action-primary-
|
|
106
|
+
border-color: var(--vmz-action-primary-hover);
|
|
62
107
|
}
|
|
63
108
|
|
|
64
109
|
.vmz-ui-field__control:focus-visible {
|
|
@@ -67,22 +112,29 @@
|
|
|
67
112
|
}
|
|
68
113
|
|
|
69
114
|
.vmz-ui-field__control:disabled {
|
|
70
|
-
opacity: 0.
|
|
115
|
+
opacity: 0.6;
|
|
116
|
+
color: var(--vmz-text-muted);
|
|
71
117
|
cursor: not-allowed;
|
|
72
|
-
background: var(--vmz-surface-mist
|
|
118
|
+
background: var(--vmz-surface-mist);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.vmz-ui-field__control:read-only {
|
|
122
|
+
cursor: default;
|
|
123
|
+
background: var(--vmz-surface-mist);
|
|
73
124
|
}
|
|
74
125
|
|
|
75
126
|
.vmz-ui-field__description {
|
|
76
127
|
margin: 0;
|
|
77
|
-
color: var(--vmz-text-steel
|
|
128
|
+
color: var(--vmz-text-steel);
|
|
78
129
|
font-size: 0.875rem;
|
|
79
|
-
line-height: 1.
|
|
130
|
+
line-height: 1.5715;
|
|
80
131
|
}
|
|
81
132
|
|
|
82
133
|
.vmz-ui-field__error {
|
|
83
134
|
margin: 0;
|
|
84
135
|
color: var(--vmz-status-danger-foreground);
|
|
85
136
|
font-size: 0.875rem;
|
|
137
|
+
line-height: 1.5715;
|
|
86
138
|
}
|
|
87
139
|
</style>
|
|
88
140
|
<script client>
|
|
@@ -97,11 +149,14 @@ export default class Field {
|
|
|
97
149
|
public error: string = "";
|
|
98
150
|
public value: string = "";
|
|
99
151
|
public type: string = "text";
|
|
152
|
+
public placeholder: string = "";
|
|
153
|
+
public prefix: string = "";
|
|
154
|
+
public suffix: string = "";
|
|
100
155
|
public min: string = "";
|
|
101
156
|
public max: string = "";
|
|
102
157
|
public step: string = "";
|
|
103
158
|
public disabled: boolean = false;
|
|
104
|
-
public
|
|
159
|
+
public readonly: boolean = false;
|
|
105
160
|
public controlId: string = "vmz-field";
|
|
106
161
|
public descriptionId: string = "vmz-field-desc";
|
|
107
162
|
public errorId: string = "vmz-field-err";
|
|
@@ -8,10 +8,40 @@
|
|
|
8
8
|
display: flex;
|
|
9
9
|
flex-wrap: wrap;
|
|
10
10
|
align-items: flex-end;
|
|
11
|
-
gap: 0.75rem
|
|
12
|
-
padding:
|
|
11
|
+
gap: 0.75rem;
|
|
12
|
+
padding: 1rem;
|
|
13
13
|
border: 1px solid var(--vmz-line-default);
|
|
14
|
-
border-radius: var(--vmz-radius-
|
|
14
|
+
border-radius: var(--vmz-radius-lg, 8px);
|
|
15
|
+
background: var(--vmz-surface-paper);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/* Action controls (Field + buttons) keep 32px height and hug the right edge. */
|
|
19
|
+
.vmz-ui-filter-bar .vmz-ui-field__control,
|
|
20
|
+
.vmz-ui-filter-bar .vmz-ui-select__control,
|
|
21
|
+
.vmz-ui-filter-bar .vmz-ui-btn {
|
|
22
|
+
min-height: 2rem;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.vmz-ui-filter-bar > :has(.vmz-ui-btn),
|
|
26
|
+
.vmz-ui-filter-bar > button.vmz-ui-btn {
|
|
27
|
+
margin-left: auto;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@media (max-width: 40rem) {
|
|
31
|
+
.vmz-ui-filter-bar {
|
|
32
|
+
flex-direction: column;
|
|
33
|
+
align-items: flex-start;
|
|
34
|
+
gap: 0.5rem;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.vmz-ui-filter-bar > * {
|
|
38
|
+
width: 100%;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.vmz-ui-filter-bar > :has(.vmz-ui-btn),
|
|
42
|
+
.vmz-ui-filter-bar > button.vmz-ui-btn {
|
|
43
|
+
margin-left: 0;
|
|
44
|
+
}
|
|
15
45
|
}
|
|
16
46
|
</style>
|
|
17
47
|
<script client>
|
|
@@ -20,6 +50,6 @@
|
|
|
20
50
|
* Dense filter/query landmark; parent projects Field + action controls.
|
|
21
51
|
*/
|
|
22
52
|
export default class FilterBar {
|
|
23
|
-
public label: string = "
|
|
53
|
+
public label: string = "";
|
|
24
54
|
}
|
|
25
55
|
</script>
|
package/src/components/Flex.vmz
CHANGED
|
@@ -8,13 +8,15 @@
|
|
|
8
8
|
display: flex;
|
|
9
9
|
align-items: center;
|
|
10
10
|
justify-content: flex-start;
|
|
11
|
-
gap:
|
|
11
|
+
gap: var(--vmz-space-3);
|
|
12
12
|
min-width: 0;
|
|
13
13
|
}
|
|
14
|
+
|
|
14
15
|
.vmz-ui-flex[data-vertical="true"] {
|
|
15
16
|
flex-direction: column;
|
|
16
17
|
align-items: stretch;
|
|
17
18
|
}
|
|
19
|
+
|
|
18
20
|
.vmz-ui-flex[data-wrap="true"] {
|
|
19
21
|
flex-wrap: wrap;
|
|
20
22
|
}
|