@vmz/ui 0.1.0 → 0.1.2

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 (66) hide show
  1. package/README.md +8 -0
  2. package/contracts/token-requirements.v0.json +2 -6
  3. package/package.json +18 -2
  4. package/presets/web-surface.v0.json +24 -10
  5. package/src/components/Accordion.vmz +88 -89
  6. package/src/components/Alert.vmz +64 -63
  7. package/src/components/AppShell.vmz +64 -45
  8. package/src/components/Autocomplete.vmz +152 -151
  9. package/src/components/Avatar.vmz +16 -0
  10. package/src/components/Badge.vmz +46 -46
  11. package/src/components/Breadcrumb.vmz +52 -48
  12. package/src/components/BulkActions.vmz +37 -37
  13. package/src/components/Button.vmz +90 -75
  14. package/src/components/Callout.vmz +61 -61
  15. package/src/components/Card.vmz +58 -51
  16. package/src/components/Checkbox.vmz +56 -53
  17. package/src/components/CodeBlock.vmz +51 -51
  18. package/src/components/Collapse.vmz +20 -0
  19. package/src/components/ConsoleShell.vmz +134 -99
  20. package/src/components/Content.vmz +11 -0
  21. package/src/components/DataTable.vmz +197 -196
  22. package/src/components/DatePicker.vmz +613 -536
  23. package/src/components/Dialog.vmz +365 -384
  24. package/src/components/Divider.vmz +19 -0
  25. package/src/components/Drawer.vmz +361 -378
  26. package/src/components/Dropdown.vmz +22 -0
  27. package/src/components/Empty.vmz +36 -36
  28. package/src/components/Field.vmz +69 -40
  29. package/src/components/FilterBar.vmz +15 -15
  30. package/src/components/Flex.vmz +12 -0
  31. package/src/components/Footer.vmz +11 -0
  32. package/src/components/Form.vmz +56 -58
  33. package/src/components/FormItem.vmz +59 -59
  34. package/src/components/Grid.vmz +12 -0
  35. package/src/components/Header.vmz +11 -0
  36. package/src/components/Icon.vmz +86 -0
  37. package/src/components/Layout.vmz +11 -0
  38. package/src/components/Link.vmz +33 -33
  39. package/src/components/List.vmz +96 -96
  40. package/src/components/Menu.vmz +229 -240
  41. package/src/components/Notification.vmz +62 -62
  42. package/src/components/Pagination.vmz +63 -65
  43. package/src/components/Popover.vmz +202 -219
  44. package/src/components/Progress.vmz +18 -0
  45. package/src/components/Prose.vmz +61 -61
  46. package/src/components/QueryForm.vmz +26 -27
  47. package/src/components/RadioGroup.vmz +116 -113
  48. package/src/components/Result.vmz +63 -63
  49. package/src/components/Segmented.vmz +29 -0
  50. package/src/components/Select.vmz +462 -290
  51. package/src/components/Sider.vmz +6 -0
  52. package/src/components/Skeleton.vmz +58 -58
  53. package/src/components/Space.vmz +15 -0
  54. package/src/components/Spinner.vmz +29 -29
  55. package/src/components/Steps.vmz +86 -86
  56. package/src/components/Switch.vmz +86 -88
  57. package/src/components/Table.vmz +116 -114
  58. package/src/components/Tabs.vmz +113 -112
  59. package/src/components/Tag.vmz +8 -0
  60. package/src/components/TextArea.vmz +76 -49
  61. package/src/components/Timeline.vmz +55 -50
  62. package/src/components/Toc.vmz +64 -60
  63. package/src/components/Tooltip.vmz +51 -51
  64. package/src/components/Tree.vmz +184 -190
  65. package/src/components/Typography.vmz +9 -0
  66. package/src/components/Upload.vmz +1130 -1151
@@ -0,0 +1,22 @@
1
+ <template>
2
+ <details class="vmz-ui-dropdown" data-vmz-ui="dropdown">
3
+ <summary>{label}</summary>
4
+ <div class="vmz-ui-dropdown__menu">
5
+ <a each={items} as="item" key={item.id} href={item.href}>{item.title}</a>
6
+ </div>
7
+ </details>
8
+ </template>
9
+ <style>
10
+ .vmz-ui-dropdown{position:relative;display:inline-block}
11
+ .vmz-ui-dropdown summary{list-style:none;min-height:2.5rem;display:inline-flex;align-items:center;padding:0 .85rem;border:1px solid var(--vmz-line-default);border-radius:var(--vmz-radius-md,6px);background:var(--vmz-surface-paper);cursor:pointer;font-weight:550}
12
+ .vmz-ui-dropdown summary::-webkit-details-marker{display:none}
13
+ .vmz-ui-dropdown__menu{position:absolute;top:calc(100% + .35rem);right:0;z-index:50;min-width:11rem;padding:.3rem;border:1px solid var(--vmz-line-default);border-radius:var(--vmz-radius-lg,8px);background:var(--vmz-surface-paper);box-shadow:var(--vmz-shadow-popup)}
14
+ .vmz-ui-dropdown__menu a{display:block;padding:.55rem .7rem;border-radius:var(--vmz-radius-sm,2px);color:var(--vmz-text-ink);text-decoration:none}
15
+ .vmz-ui-dropdown__menu a:hover{background:var(--vmz-surface-mist)}
16
+ </style>
17
+ <script client>
18
+ export default class Dropdown {
19
+ public label: string = 'Menu';
20
+ public items: Array<{ id: string; title: string; href: string }> = [];
21
+ }
22
+ </script>
@@ -1,52 +1,52 @@
1
1
  <template>
2
2
  <div class="vmz-ui-empty" data-vmz-ui="empty">
3
- <h2 class="vmz-ui-empty__title">{title}</h2>
4
- <p if={description} class="vmz-ui-empty__description">{description}</p>
5
- <div class="vmz-ui-empty__actions">
6
- <slot />
3
+ <h2 class="vmz-ui-empty__title">{title}</h2>
4
+ <p if={description} class="vmz-ui-empty__description">{description}</p>
5
+ <div class="vmz-ui-empty__actions">
6
+ <slot />
7
+ </div>
7
8
  </div>
8
- </div>
9
9
  </template>
10
10
 
11
11
  <style>
12
- .vmz-ui-empty {
13
- display: flex;
14
- flex-direction: column;
15
- align-items: flex-start;
16
- gap: 0.65rem;
17
- padding: 1.5rem 1.15rem;
18
- border: 1px dashed var(--vmz-line-default);
19
- border-radius: 2px;
20
- background: color-mix(in srgb, var(--vmz-surface-mist) 70%, var(--vmz-surface-paper));
21
- color: var(--vmz-text-ink);
22
- }
12
+ .vmz-ui-empty {
13
+ display: flex;
14
+ flex-direction: column;
15
+ align-items: flex-start;
16
+ gap: 0.65rem;
17
+ padding: 1.5rem 1.15rem;
18
+ border: 1px dashed var(--vmz-line-default);
19
+ border-radius: var(--vmz-radius-md, 6px);
20
+ background: color-mix(in srgb, var(--vmz-surface-mist) 70%, var(--vmz-surface-paper));
21
+ color: var(--vmz-text-ink);
22
+ }
23
23
 
24
- .vmz-ui-empty__title {
25
- margin: 0;
26
- font-family: var(--vmz-font-display);
27
- font-size: 1.1rem;
28
- font-weight: 700;
29
- }
24
+ .vmz-ui-empty__title {
25
+ margin: 0;
26
+ font-family: var(--vmz-font-display);
27
+ font-size: 1.1rem;
28
+ font-weight: 700;
29
+ }
30
30
 
31
- .vmz-ui-empty__description {
32
- margin: 0;
33
- color: var(--vmz-text-steel);
34
- max-width: 36rem;
35
- line-height: 1.45;
36
- }
31
+ .vmz-ui-empty__description {
32
+ margin: 0;
33
+ color: var(--vmz-text-steel);
34
+ max-width: 36rem;
35
+ line-height: 1.45;
36
+ }
37
37
 
38
- .vmz-ui-empty__actions:empty {
39
- display: none;
40
- }
38
+ .vmz-ui-empty__actions:empty {
39
+ display: none;
40
+ }
41
41
  </style>
42
42
 
43
43
  <script client>
44
44
  /**
45
- * VMZ UI — Empty (Commercial composition).
46
- * Empty / zero-state surface with optional action slot.
47
- */
45
+ * VMZ UI — Empty (Commercial composition).
46
+ * Empty / zero-state surface with optional action slot.
47
+ */
48
48
  export default class Empty {
49
- public title: string = 'Nothing here yet';
50
- public description: string = '';
49
+ public title: string = "Nothing here yet";
50
+ public description: string = "";
51
51
  }
52
52
  </script>
@@ -1,19 +1,22 @@
1
1
  <template>
2
2
  <div class="vmz-ui-field" data-vmz-ui="field" data-invalid={invalidAttr}>
3
- <label if={label} class="vmz-ui-field__label" for={controlId}>{label}</label>
4
- <input
5
- id={controlId}
6
- class="vmz-ui-field__control"
7
- type={type}
8
- value={value}
9
- disabled={disabled}
10
- aria-invalid={error ? 'true' : 'false'}
11
- aria-describedby={describedBy}
12
- onInput={onInput}
13
- />
14
- <p if={description} id={descriptionId} class="vmz-ui-field__description">{description}</p>
15
- <p if={error} id={errorId} class="vmz-ui-field__error" role="alert">{error}</p>
16
- </div>
3
+ <label if={label} class="vmz-ui-field__label" for={controlId}>{label}</label>
4
+ <input
5
+ id={controlId}
6
+ class="vmz-ui-field__control"
7
+ type={type}
8
+ value={value}
9
+ min={min}
10
+ max={max}
11
+ step={step}
12
+ disabled={disabled}
13
+ aria-invalid={error ? 'true' : 'false'}
14
+ aria-describedby={describedBy}
15
+ onInput={onInput}
16
+ />
17
+ <p if={description} id={descriptionId} class="vmz-ui-field__description">{description}</p>
18
+ <p if={error} id={errorId} class="vmz-ui-field__error" role="alert">{error}</p>
19
+ </div>
17
20
  </template>
18
21
 
19
22
  <style>
@@ -26,63 +29,89 @@
26
29
 
27
30
  .vmz-ui-field__label {
28
31
  font: inherit;
29
- font-weight: 600;
32
+ font-weight: 500;
33
+ font-size: 0.875rem;
34
+ color: var(--vmz-text-ink, inherit);
30
35
  }
31
36
 
32
37
  .vmz-ui-field__control {
33
- font: inherit;
34
- padding: var(--vmz-density-control-padding-y) var(--vmz-density-control-padding-x);
35
- border: 1px solid var(--vmz-action-primary-background);
36
- border-radius: 2px;
37
- background: transparent;
38
- color: inherit;
38
+ box-sizing: border-box;
39
+ width: 100%;
40
+ min-height: var(--vmz-control-height, 2rem);
41
+ font-family: var(--vmz-font-sans, inherit);
42
+ font-size: 0.875rem;
43
+ line-height: 1.5715;
44
+ padding: var(--vmz-density-control-padding-y, 0.25rem)
45
+ var(--vmz-density-control-padding-x, 0.75rem);
46
+ border: 1px solid var(--vmz-line-default, #d9d9d9);
47
+ border-radius: var(--vmz-radius-md, 6px);
48
+ background: var(--vmz-surface-paper, #fff);
49
+ color: var(--vmz-text-ink, inherit);
39
50
  outline: none;
51
+ transition:
52
+ border-color var(--vmz-motion-control-duration, 120ms) var(--vmz-motion-control-easing, linear),
53
+ box-shadow var(--vmz-motion-control-duration, 120ms) var(--vmz-motion-control-easing, linear);
54
+ }
55
+
56
+ .vmz-ui-field__control::placeholder {
57
+ color: var(--vmz-text-steel, #8c8c8c);
58
+ opacity: 1;
40
59
  }
41
60
 
42
61
  .vmz-ui-field[data-invalid='true'] .vmz-ui-field__control {
43
62
  border-color: var(--vmz-status-danger-accent);
44
63
  }
45
64
 
65
+ .vmz-ui-field__control:hover:not(:disabled):not(:focus-visible) {
66
+ border-color: var(--vmz-action-primary-background);
67
+ }
68
+
46
69
  .vmz-ui-field__control:focus-visible {
70
+ border-color: var(--vmz-action-primary-background);
47
71
  box-shadow: 0 0 0 2px var(--vmz-focus-ring);
48
72
  }
49
73
 
50
74
  .vmz-ui-field__control:disabled {
51
75
  opacity: 0.55;
52
76
  cursor: not-allowed;
77
+ background: var(--vmz-surface-mist, #fafafa);
53
78
  }
54
79
 
55
80
  .vmz-ui-field__description {
56
81
  margin: 0;
57
- opacity: 0.75;
58
- font-size: 0.9em;
82
+ color: var(--vmz-text-steel, #8c8c8c);
83
+ font-size: 0.875rem;
84
+ line-height: 1.4;
59
85
  }
60
86
 
61
87
  .vmz-ui-field__error {
62
88
  margin: 0;
63
89
  color: var(--vmz-status-danger-foreground);
64
- font-size: 0.9em;
90
+ font-size: 0.875rem;
65
91
  }
66
92
  </style>
67
93
 
68
94
  <script client>
69
95
  /**
70
- * VMZ UI — Field (UI1).
71
- * Label / description / error association via for + aria-describedby.
72
- * Colors only from Style Theme semantic tokens.
73
- */
96
+ * VMZ UI — Field (UI1).
97
+ * Label / description / error association via for + aria-describedby.
98
+ * Colors only from Style Theme semantic tokens.
99
+ */
74
100
  export default class Field {
75
- public label: string = '';
76
- public description: string = '';
77
- public error: string = '';
78
- public value: string = '';
79
- public type: string = 'text';
80
- public disabled: boolean = false;
81
- public invalidAttr: string = 'false';
82
- public controlId: string = 'vmz-field';
83
- public descriptionId: string = 'vmz-field-desc';
84
- public errorId: string = 'vmz-field-err';
85
- public describedBy: string = '';
86
- public onInput: ((e: Event) => void) | null = null;
101
+ public label: string = "";
102
+ public description: string = "";
103
+ public error: string = "";
104
+ public value: string = "";
105
+ public type: string = "text";
106
+ public min: string = "";
107
+ public max: string = "";
108
+ public step: string = "";
109
+ public disabled: boolean = false;
110
+ public invalidAttr: string = "false";
111
+ public controlId: string = "vmz-field";
112
+ public descriptionId: string = "vmz-field-desc";
113
+ public errorId: string = "vmz-field-err";
114
+ public describedBy: string = "";
115
+ public onInput: ((e: Event) => void) | null = null;
87
116
  }
88
117
  </script>
@@ -1,27 +1,27 @@
1
1
  <template>
2
2
  <section class="vmz-ui-filter-bar" data-vmz-ui="filter-bar" aria-label={label}>
3
- <slot />
4
- </section>
3
+ <slot />
4
+ </section>
5
5
  </template>
6
6
 
7
7
  <style>
8
- .vmz-ui-filter-bar {
9
- display: flex;
10
- flex-wrap: wrap;
11
- align-items: flex-end;
12
- gap: 0.75rem 1rem;
13
- padding: 0.75rem 0.85rem;
14
- border: 1px solid var(--vmz-action-primary-background);
15
- border-radius: 2px;
16
- }
8
+ .vmz-ui-filter-bar {
9
+ display: flex;
10
+ flex-wrap: wrap;
11
+ align-items: flex-end;
12
+ gap: 0.75rem 1rem;
13
+ padding: 0.75rem 0.85rem;
14
+ border: 1px solid var(--vmz-line-default);
15
+ border-radius: var(--vmz-radius-md, 6px);
16
+ }
17
17
  </style>
18
18
 
19
19
  <script client>
20
20
  /**
21
- * VMZ UI — FilterBar (Console composition).
22
- * Dense filter/query landmark; parent projects Field + action controls.
23
- */
21
+ * VMZ UI — FilterBar (Console composition).
22
+ * Dense filter/query landmark; parent projects Field + action controls.
23
+ */
24
24
  export default class FilterBar {
25
- public label: string = 'Filters';
25
+ public label: string = "Filters";
26
26
  }
27
27
  </script>
@@ -0,0 +1,12 @@
1
+ <template><div class="vmz-ui-flex" data-vmz-ui="flex" data-vertical={vertical?'true':'false'} data-wrap={wrap?'true':'false'}><slot /></div></template>
2
+ <style>
3
+ .vmz-ui-flex{display:flex;align-items:center;justify-content:flex-start;gap:.75rem;min-width:0}
4
+ .vmz-ui-flex[data-vertical='true']{flex-direction:column;align-items:stretch}
5
+ .vmz-ui-flex[data-wrap='true']{flex-wrap:wrap}
6
+ </style>
7
+ <script client>
8
+ export default class Flex {
9
+ public vertical: boolean = false;
10
+ public wrap: boolean = false;
11
+ }
12
+ </script>
@@ -0,0 +1,11 @@
1
+ <template>
2
+ <footer class="vmz-ui-footer" data-vmz-ui="footer"><slot /></footer>
3
+ </template>
4
+
5
+ <style>
6
+ .vmz-ui-footer{padding:1.5rem;color:var(--vmz-text-steel,#646a73);font-size:.875rem;text-align:center}
7
+ </style>
8
+
9
+ <script client>
10
+ export default class Footer {}
11
+ </script>
@@ -1,72 +1,70 @@
1
1
  <template>
2
2
  <form
3
- class="vmz-ui-form"
4
- data-vmz-ui="form"
5
- data-disabled={disabledAttr}
6
- data-novalidate="true"
7
- aria-label={label}
8
- aria-describedby={describedBy}
9
- onSubmit={onSubmitGuard}
10
- onReset={onResetGuard}
11
- >
12
- <div if={errorSummary} id={summaryId} class="vmz-ui-form__summary" role="alert" data-vmz-form="summary">
13
- {errorSummary}
14
- </div>
15
- <slot />
16
- </form>
3
+ class="vmz-ui-form"
4
+ data-vmz-ui="form"
5
+ data-disabled={disabledAttr}
6
+ data-novalidate="true"
7
+ aria-label={label}
8
+ aria-describedby={describedBy}
9
+ onSubmit={onSubmitGuard}
10
+ onReset={onResetGuard}
11
+ >
12
+ <div if={errorSummary} id={summaryId} class="vmz-ui-form__summary" role="alert" data-vmz-form="summary">
13
+ {errorSummary}
14
+ </div>
15
+ <slot />
16
+ </form>
17
17
  </template>
18
18
 
19
19
  <style>
20
- .vmz-ui-form {
21
- display: flex;
22
- flex-direction: column;
23
- gap: var(--vmz-density-control-gap);
24
- max-width: 36rem;
25
- }
20
+ .vmz-ui-form {
21
+ display: flex;
22
+ flex-direction: column;
23
+ gap: var(--vmz-density-control-gap);
24
+ max-width: 36rem;
25
+ }
26
26
 
27
- .vmz-ui-form[data-disabled='true'] {
28
- opacity: 0.72;
29
- pointer-events: none;
30
- }
27
+ .vmz-ui-form[data-disabled='true'] {
28
+ opacity: 0.72;
29
+ pointer-events: none;
30
+ }
31
31
 
32
- .vmz-ui-form__summary {
33
- margin: 0;
34
- padding: var(--vmz-density-control-padding-y) var(--vmz-density-control-padding-x);
35
- border: 1px solid var(--vmz-status-danger-accent);
36
- border-left-width: 4px;
37
- border-radius: 2px;
38
- background: color-mix(in srgb, var(--vmz-status-danger-accent) 12%, transparent);
39
- color: var(--vmz-status-danger-foreground);
40
- font-weight: 600;
41
- }
32
+ .vmz-ui-form__summary {
33
+ margin: 0;
34
+ padding: var(--vmz-density-control-padding-y) var(--vmz-density-control-padding-x);
35
+ border: 1px solid var(--vmz-status-danger-accent);
36
+ border-left-width: 1px;
37
+ border-radius: var(--vmz-radius-md, 6px);
38
+ background: color-mix(in srgb, var(--vmz-status-danger-accent) 12%, transparent);
39
+ color: var(--vmz-status-danger-foreground);
40
+ font-weight: 600;
41
+ }
42
42
  </style>
43
43
 
44
44
  <script client>
45
45
  /**
46
- * VMZ UI — Form (hand-written commercial form shell).
47
- * Parent owns field values + validation presentation; no parallel form store.
48
- * Native submit/reset guarded; browser HTML5 validation left off (data-novalidate + preventDefault).
49
- */
46
+ * VMZ UI — Form (hand-written commercial form shell).
47
+ * Parent owns field values + validation presentation; no parallel form store.
48
+ * Native submit/reset guarded; browser HTML5 validation left off (data-novalidate + preventDefault).
49
+ */
50
50
  export default class Form {
51
- public label: string = 'Form';
52
- public errorSummary: string = '';
53
- public summaryId: string = 'vmz-form-summary';
54
- public describedBy: string = '';
55
- public disabled: boolean = false;
56
- public disabledAttr: string = 'false';
57
- public onSubmit: (() => void) | null = null;
58
- public onReset: (() => void) | null = null;
59
-
60
- onSubmitGuard(ev) {
61
- if (ev && typeof ev.preventDefault === 'function') ev.preventDefault();
62
- if (this.disabled) return;
63
- if (typeof this.onSubmit === 'function') this.onSubmit();
64
- }
65
-
66
- onResetGuard(ev) {
67
- if (ev && typeof ev.preventDefault === 'function') ev.preventDefault();
68
- if (this.disabled) return;
69
- if (typeof this.onReset === 'function') this.onReset();
70
- }
51
+ public label: string = "Form";
52
+ public errorSummary: string = "";
53
+ public summaryId: string = "vmz-form-summary";
54
+ public describedBy: string = "";
55
+ public disabled: boolean = false;
56
+ public disabledAttr: string = "false";
57
+ public onSubmit: (() => void) | null = null;
58
+ public onReset: (() => void) | null = null;
59
+ onSubmitGuard(ev) {
60
+ if (ev && typeof ev.preventDefault === "function") ev.preventDefault();
61
+ if (this.disabled) return;
62
+ if (typeof this.onSubmit === "function") this.onSubmit();
63
+ }
64
+ onResetGuard(ev) {
65
+ if (ev && typeof ev.preventDefault === "function") ev.preventDefault();
66
+ if (this.disabled) return;
67
+ if (typeof this.onReset === "function") this.onReset();
68
+ }
71
69
  }
72
70
  </script>
@@ -1,78 +1,78 @@
1
1
  <template>
2
2
  <div
3
- class="vmz-ui-form-item"
4
- data-vmz-ui="form-item"
5
- data-required={requiredAttr}
6
- data-invalid={invalidAttr}
7
- >
8
- <label if={label} class="vmz-ui-form-item__label" for={controlId}>
9
- <span>{label}</span>
10
- <span if={required} class="vmz-ui-form-item__required" aria-hidden="true">*</span>
11
- </label>
12
- <div class="vmz-ui-form-item__control">
13
- <slot />
3
+ class="vmz-ui-form-item"
4
+ data-vmz-ui="form-item"
5
+ data-required={requiredAttr}
6
+ data-invalid={invalidAttr}
7
+ >
8
+ <label if={label} class="vmz-ui-form-item__label" for={controlId}>
9
+ <span>{label}</span>
10
+ <span if={required} class="vmz-ui-form-item__required" aria-hidden="true">*</span>
11
+ </label>
12
+ <div class="vmz-ui-form-item__control">
13
+ <slot />
14
+ </div>
15
+ <p if={description} id={descriptionId} class="vmz-ui-form-item__description">{description}</p>
16
+ <p if={error} id={errorId} class="vmz-ui-form-item__error" role="alert">{error}</p>
14
17
  </div>
15
- <p if={description} id={descriptionId} class="vmz-ui-form-item__description">{description}</p>
16
- <p if={error} id={errorId} class="vmz-ui-form-item__error" role="alert">{error}</p>
17
- </div>
18
18
  </template>
19
19
 
20
20
  <style>
21
- .vmz-ui-form-item {
22
- display: flex;
23
- flex-direction: column;
24
- gap: 0.35rem;
25
- max-width: 28rem;
26
- }
21
+ .vmz-ui-form-item {
22
+ display: flex;
23
+ flex-direction: column;
24
+ gap: 0.35rem;
25
+ max-width: 28rem;
26
+ }
27
27
 
28
- .vmz-ui-form-item__label {
29
- display: inline-flex;
30
- align-items: baseline;
31
- gap: 0.25rem;
32
- font: inherit;
33
- font-weight: 600;
34
- }
28
+ .vmz-ui-form-item__label {
29
+ display: inline-flex;
30
+ align-items: baseline;
31
+ gap: 0.25rem;
32
+ font: inherit;
33
+ font-weight: 600;
34
+ }
35
35
 
36
- .vmz-ui-form-item__required {
37
- color: var(--vmz-status-danger-accent);
38
- font-weight: 700;
39
- }
36
+ .vmz-ui-form-item__required {
37
+ color: var(--vmz-status-danger-accent);
38
+ font-weight: 700;
39
+ }
40
40
 
41
- .vmz-ui-form-item__control {
42
- min-width: 0;
43
- }
41
+ .vmz-ui-form-item__control {
42
+ min-width: 0;
43
+ }
44
44
 
45
- .vmz-ui-form-item__description {
46
- margin: 0;
47
- opacity: 0.75;
48
- font-size: 0.9em;
49
- }
45
+ .vmz-ui-form-item__description {
46
+ margin: 0;
47
+ opacity: 0.75;
48
+ font-size: 0.9em;
49
+ }
50
50
 
51
- .vmz-ui-form-item__error {
52
- margin: 0;
53
- color: var(--vmz-status-danger-foreground);
54
- font-size: 0.9em;
55
- }
51
+ .vmz-ui-form-item__error {
52
+ margin: 0;
53
+ color: var(--vmz-status-danger-foreground);
54
+ font-size: 0.9em;
55
+ }
56
56
 
57
- .vmz-ui-form-item[data-invalid='true'] .vmz-ui-form-item__control :where(input, select, textarea) {
58
- border-color: var(--vmz-status-danger-accent);
59
- }
57
+ .vmz-ui-form-item[data-invalid='true'] .vmz-ui-form-item__control :where(input, select, textarea) {
58
+ border-color: var(--vmz-status-danger-accent);
59
+ }
60
60
  </style>
61
61
 
62
62
  <script client>
63
63
  /**
64
- * VMZ UI — FormItem.
65
- * Label / description / error shell for slotted controls; parent owns validation strings.
66
- */
64
+ * VMZ UI — FormItem.
65
+ * Label / description / error shell for slotted controls; parent owns validation strings.
66
+ */
67
67
  export default class FormItem {
68
- public label: string = '';
69
- public description: string = '';
70
- public error: string = '';
71
- public required: boolean = false;
72
- public requiredAttr: string = 'false';
73
- public invalidAttr: string = 'false';
74
- public controlId: string = 'vmz-form-item';
75
- public descriptionId: string = 'vmz-form-item-desc';
76
- public errorId: string = 'vmz-form-item-err';
68
+ public label: string = "";
69
+ public description: string = "";
70
+ public error: string = "";
71
+ public required: boolean = false;
72
+ public requiredAttr: string = "false";
73
+ public invalidAttr: string = "false";
74
+ public controlId: string = "vmz-form-item";
75
+ public descriptionId: string = "vmz-form-item-desc";
76
+ public errorId: string = "vmz-form-item-err";
77
77
  }
78
78
  </script>
@@ -0,0 +1,12 @@
1
+ <template><div class="vmz-ui-grid" data-vmz-ui="grid" style={'--ui-grid-columns:' + columns + ';--ui-grid-gap:' + gap}><slot /></div></template>
2
+ <style>
3
+ .vmz-ui-grid{display:grid;grid-template-columns:repeat(var(--ui-grid-columns,3),minmax(0,1fr));gap:var(--ui-grid-gap,1rem)}
4
+ @media(max-width:900px){.vmz-ui-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
5
+ @media(max-width:600px){.vmz-ui-grid{grid-template-columns:1fr}}
6
+ </style>
7
+ <script client>
8
+ export default class Grid {
9
+ public columns: number = 3;
10
+ public gap: string = '1rem';
11
+ }
12
+ </script>
@@ -0,0 +1,11 @@
1
+ <template>
2
+ <header class="vmz-ui-header" data-vmz-ui="header"><slot /></header>
3
+ </template>
4
+
5
+ <style>
6
+ .vmz-ui-header{min-height:4rem;display:flex;align-items:center;padding:0 1.5rem;border-bottom:1px solid var(--vmz-line-default,#d9d9d9);background:var(--vmz-surface-paper,#fff)}
7
+ </style>
8
+
9
+ <script client>
10
+ export default class Header {}
11
+ </script>