@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
@@ -0,0 +1,287 @@
1
+ <template>
2
+ <span data-vmz-ui="popconfirm" :data-tone="tone" class="vmz-ui-popconfirm-root">
3
+ <span class="vmz-ui-popconfirm__trigger">
4
+ <slot />
5
+ </span>
6
+ <span v-if="open" data-vmz-overlay="popconfirm" data-vmz-overlay-owner="popconfirm" :data-vmz-overlay-stack="stackLevel" class="vmz-ui-popconfirm">
7
+ <button type="button" data-vmz-overlay-layer="backdrop" :aria-label="cancelLabel || title" @click="cancel" class="vmz-ui-popconfirm__backdrop" />
8
+ <span role="dialog" aria-modal="false" :aria-labelledby="title ? titleId : null" tabindex="-1" data-vmz-overlay-layer="panel" data-vmz-focus="enter" :onKeyDown="onPanelKeyDown" class="vmz-ui-popconfirm__panel">
9
+ <span aria-hidden="true" class="vmz-ui-popconfirm__icon">
10
+ <Icon :name="toneIcon()" size="md" decorative />
11
+ </span>
12
+ <span class="vmz-ui-popconfirm__content">
13
+ <span v-if="title" :id="titleId" class="vmz-ui-popconfirm__title">
14
+ {{ title }}
15
+ </span>
16
+ <span v-if="description" class="vmz-ui-popconfirm__description">
17
+ {{ description }}
18
+ </span>
19
+ <span class="vmz-ui-popconfirm__actions">
20
+ <Button type="button" variant="secondary" size="small" @click="cancel">
21
+ {{ cancelLabel }}
22
+ </Button>
23
+ <Button type="button" :variant="tone === 'danger' ? 'danger' : 'primary'" size="small" @click="confirm">
24
+ {{ confirmLabel }}
25
+ </Button>
26
+ </span>
27
+ </span>
28
+ </span>
29
+ </span>
30
+ </span>
31
+ </template>
32
+ <style>
33
+ .vmz-ui-popconfirm-root {
34
+ display: inline-flex;
35
+ }
36
+
37
+ .vmz-ui-popconfirm {
38
+ position: fixed;
39
+ inset: 0;
40
+ z-index: 35;
41
+ pointer-events: none;
42
+ }
43
+
44
+ .vmz-ui-popconfirm[data-vmz-overlay-stack="1"] {
45
+ z-index: 50;
46
+ }
47
+
48
+ .vmz-ui-popconfirm[data-vmz-overlay-stack="2"] {
49
+ z-index: 60;
50
+ }
51
+
52
+ .vmz-ui-popconfirm[data-vmz-overlay-stack="3"] {
53
+ z-index: 70;
54
+ }
55
+
56
+ .vmz-ui-popconfirm__backdrop {
57
+ position: absolute;
58
+ inset: 0;
59
+ border: 0;
60
+ padding: 0;
61
+ margin: 0;
62
+ cursor: default;
63
+ background: transparent;
64
+ pointer-events: auto;
65
+ }
66
+
67
+ .vmz-ui-popconfirm__panel {
68
+ position: absolute;
69
+ z-index: 1;
70
+ top: 30%;
71
+ left: 50%;
72
+ transform: translateX(-50%);
73
+ box-sizing: border-box;
74
+ display: flex;
75
+ align-items: flex-start;
76
+ gap: 0.5rem;
77
+ width: min(340px, calc(100vw - 32px));
78
+ padding: 12px;
79
+ border: 1px solid var(--vmz-line-subtle);
80
+ border-radius: var(--vmz-radius-lg);
81
+ background: var(--vmz-surface-paper);
82
+ color: var(--vmz-text-ink);
83
+ box-shadow: var(--vmz-shadow-popup);
84
+ outline: none;
85
+ pointer-events: auto;
86
+ animation: vmz-ui-popconfirm-in var(--vmz-motion-overlay-duration) var(--vmz-motion-overlay-easing);
87
+ }
88
+
89
+ .vmz-ui-popconfirm__panel:focus-visible {
90
+ box-shadow: 0 0 0 3px var(--vmz-focus-ring), var(--vmz-shadow-popup);
91
+ }
92
+
93
+ .vmz-ui-popconfirm__icon {
94
+ flex: 0 0 auto;
95
+ display: inline-flex;
96
+ align-items: center;
97
+ justify-content: center;
98
+ height: 1.5rem;
99
+ color: var(--vmz-status-warning-accent);
100
+ }
101
+
102
+ .vmz-ui-popconfirm[data-tone="danger"] .vmz-ui-popconfirm__icon {
103
+ color: var(--vmz-status-danger-accent);
104
+ }
105
+
106
+ .vmz-ui-popconfirm[data-tone="info"] .vmz-ui-popconfirm__icon {
107
+ color: var(--vmz-status-info-accent);
108
+ }
109
+
110
+ .vmz-ui-popconfirm__content {
111
+ flex: 1 1 auto;
112
+ display: block;
113
+ min-width: 0;
114
+ }
115
+
116
+ .vmz-ui-popconfirm__title {
117
+ display: block;
118
+ font-size: 0.875rem;
119
+ font-weight: 600;
120
+ line-height: 1.5;
121
+ color: var(--vmz-text-ink);
122
+ }
123
+
124
+ .vmz-ui-popconfirm__description {
125
+ display: block;
126
+ margin-top: 2px;
127
+ font-size: 0.875rem;
128
+ line-height: 1.5;
129
+ color: var(--vmz-text-steel);
130
+ }
131
+
132
+ .vmz-ui-popconfirm__actions {
133
+ display: flex;
134
+ flex-wrap: wrap;
135
+ align-items: center;
136
+ justify-content: flex-end;
137
+ gap: 8px;
138
+ margin-top: 10px;
139
+ }
140
+
141
+ @keyframes vmz-ui-popconfirm-in {
142
+ from {
143
+ opacity: 0;
144
+ transform: translateX(-50%) translateY(-6px) scale(0.98);
145
+ }
146
+ to {
147
+ opacity: 1;
148
+ transform: translateX(-50%) translateY(0) scale(1);
149
+ }
150
+ }
151
+
152
+ @media (prefers-reduced-motion: reduce) {
153
+ .vmz-ui-popconfirm__panel {
154
+ animation: none;
155
+ }
156
+ }
157
+ </style>
158
+ <script client>
159
+ /**
160
+ * VMZ UI — Popconfirm.
161
+ * Destructive-action confirmation. Same overlay contract as Popover: Escape,
162
+ * outside dismiss, focus enter/restore, stack-aware z-index.
163
+ * Parent owns `open`; confirm/cancel are emitted, the caller performs the action.
164
+ */
165
+ export default class Popconfirm {
166
+ public open: boolean = false;
167
+ public title: string = "";
168
+ public description: string = "";
169
+ public tone: string = "danger";
170
+ public confirmLabel: string = "";
171
+ public cancelLabel: string = "";
172
+ public titleId: string = "vmz-popconfirm-title";
173
+ public stackLevel: string = "0";
174
+ public onConfirm: (() => void) | null = null;
175
+ public onCancel: (() => void) | null = null;
176
+ _restoreFocus = null;
177
+ _panel = null;
178
+ _docKeyHandler = null;
179
+ _observer = null;
180
+ onMount() {
181
+ if (typeof document === "undefined" || typeof MutationObserver === "undefined") return;
182
+ const root = this.__vmzDomRoot;
183
+ if (!root || typeof root.querySelector !== "function") return;
184
+ this._observer = new MutationObserver(() => this._syncFromDom());
185
+ this._observer.observe(root, {
186
+ childList: true,
187
+ subtree: true,
188
+ });
189
+ this._syncFromDom();
190
+ }
191
+ onDestroy() {
192
+ if (this._observer) {
193
+ this._observer.disconnect();
194
+ this._observer = null;
195
+ }
196
+ this._teardownDocKey();
197
+ this._panel = null;
198
+ this._restoreFocus = null;
199
+ }
200
+ confirm() {
201
+ this.emit("confirm");
202
+ if (typeof this.onConfirm === "function") this.onConfirm();
203
+ }
204
+ cancel() {
205
+ this.emit("cancel");
206
+ if (typeof this.onCancel === "function") this.onCancel();
207
+ }
208
+ toneIcon() {
209
+ const tone = String(this.tone || "").toLowerCase();
210
+ if (tone === "danger" || tone === "info" || tone === "success") return `status.${tone}`;
211
+ return "status.warning";
212
+ }
213
+ _isTopmostStack() {
214
+ if (typeof document === "undefined") return true;
215
+ const root = this.__vmzDomRoot;
216
+ const mine =
217
+ root && typeof root.querySelector === "function"
218
+ ? root.querySelector("[data-vmz-overlay][data-vmz-overlay-stack]")
219
+ : null;
220
+ const myStack = Number(mine?.getAttribute("data-vmz-overlay-stack") || this.stackLevel || "0");
221
+ const open = document.querySelectorAll("[data-vmz-overlay][data-vmz-overlay-stack]");
222
+ let max = -Infinity;
223
+ for (const el of open) {
224
+ const n = Number(el.getAttribute("data-vmz-overlay-stack") || "0");
225
+ if (Number.isFinite(n) && n > max) max = n;
226
+ }
227
+ if (!Number.isFinite(max)) return true;
228
+ return (Number.isFinite(myStack) ? myStack : 0) >= max;
229
+ }
230
+ onPanelKeyDown(ev) {
231
+ if (!ev || ev.key !== "Escape") return;
232
+ if (!this._isTopmostStack()) return;
233
+ ev.preventDefault();
234
+ ev.stopPropagation();
235
+ this.cancel();
236
+ }
237
+ _syncFromDom() {
238
+ const root = this.__vmzDomRoot;
239
+ const panel =
240
+ root && typeof root.querySelector === "function"
241
+ ? root.querySelector('[data-vmz-overlay="popconfirm"] [data-vmz-focus="enter"]')
242
+ : null;
243
+ if (panel && !this._panel) this._enterFocus(panel);
244
+ else if (!panel && this._panel) this._exitFocus();
245
+ }
246
+ _enterFocus(panel) {
247
+ if (typeof document === "undefined") return;
248
+ const active = document.activeElement;
249
+ if (!this._restoreFocus) {
250
+ const root = this.__vmzDomRoot;
251
+ const outside =
252
+ active instanceof HTMLElement &&
253
+ active !== document.body &&
254
+ !(root && typeof root.contains === "function" && root.contains(active));
255
+ if (outside) this._restoreFocus = active;
256
+ }
257
+ this._panel = panel instanceof HTMLElement ? panel : null;
258
+ if (this._panel && typeof this._panel.focus === "function") this._panel.focus();
259
+ if (!this._docKeyHandler) {
260
+ this._docKeyHandler = (ev) => {
261
+ if (ev.key !== "Escape") return;
262
+ if (ev.defaultPrevented) return;
263
+ if (!this._isTopmostStack()) return;
264
+ ev.preventDefault();
265
+ ev.stopPropagation();
266
+ this.cancel();
267
+ };
268
+ document.addEventListener("keydown", this._docKeyHandler);
269
+ }
270
+ }
271
+ _exitFocus() {
272
+ this._teardownDocKey();
273
+ this._panel = null;
274
+ const restore = this._restoreFocus;
275
+ this._restoreFocus = null;
276
+ if (restore && typeof restore.focus === "function" && document.contains(restore)) {
277
+ restore.focus();
278
+ }
279
+ }
280
+ _teardownDocKey() {
281
+ if (typeof document !== "undefined" && this._docKeyHandler) {
282
+ document.removeEventListener("keydown", this._docKeyHandler);
283
+ }
284
+ this._docKeyHandler = null;
285
+ }
286
+ }
287
+ </script>