@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,6 @@
1
+ <template><aside class="vmz-ui-sider" data-vmz-ui="sider"><slot /></aside></template>
2
+ <style>
3
+ .vmz-ui-sider{width:16rem;padding:1rem;border-right:1px solid var(--vmz-line-default);background:var(--vmz-surface-paper)}
4
+ @media(max-width:720px){.vmz-ui-sider{width:100%;border-right:0;border-bottom:1px solid var(--vmz-line-default)}}
5
+ </style>
6
+ <script client>export default class Sider {}</script>
@@ -1,80 +1,80 @@
1
1
  <template>
2
2
  <div
3
- class="vmz-ui-skeleton"
4
- data-vmz-ui="skeleton"
5
- data-loading={loadingAttr}
6
- role="status"
7
- aria-live="polite"
8
- aria-busy={loadingAttr}
9
- >
10
- <div if={loading} class="vmz-ui-skeleton__block" data-vmz-skeleton="block"></div>
11
- <div if={loading} class="vmz-ui-skeleton__line" data-vmz-skeleton="line"></div>
12
- <div if={loading} class="vmz-ui-skeleton__line" data-vmz-skeleton="line"></div>
13
- <div if={!loading} class="vmz-ui-skeleton__content">
14
- <slot />
3
+ class="vmz-ui-skeleton"
4
+ data-vmz-ui="skeleton"
5
+ data-loading={loadingAttr}
6
+ role="status"
7
+ aria-live="polite"
8
+ aria-busy={loadingAttr}
9
+ >
10
+ <div if={loading} class="vmz-ui-skeleton__block" data-vmz-skeleton="block"></div>
11
+ <div if={loading} class="vmz-ui-skeleton__line" data-vmz-skeleton="line"></div>
12
+ <div if={loading} class="vmz-ui-skeleton__line" data-vmz-skeleton="line"></div>
13
+ <div if={!loading} class="vmz-ui-skeleton__content">
14
+ <slot />
15
+ </div>
15
16
  </div>
16
- </div>
17
17
  </template>
18
18
 
19
19
  <style>
20
- .vmz-ui-skeleton {
21
- display: flex;
22
- flex-direction: column;
23
- gap: var(--vmz-density-compact-gap);
24
- min-height: 4.5rem;
25
- }
26
-
27
- .vmz-ui-skeleton__block,
28
- .vmz-ui-skeleton__line {
29
- border-radius: 2px;
30
- background: color-mix(in srgb, var(--vmz-action-primary-background) 18%, transparent);
31
- animation: vmz-ui-skeleton-pulse var(--vmz-motion-overlay-duration) var(--vmz-motion-overlay-easing) infinite alternate;
32
- }
20
+ .vmz-ui-skeleton {
21
+ display: flex;
22
+ flex-direction: column;
23
+ gap: var(--vmz-density-compact-gap);
24
+ min-height: 4.5rem;
25
+ }
33
26
 
34
- .vmz-ui-skeleton__block {
35
- width: 100%;
36
- height: 2.5rem;
37
- }
27
+ .vmz-ui-skeleton__block,
28
+ .vmz-ui-skeleton__line {
29
+ border-radius: var(--vmz-radius-md, 6px);
30
+ background: color-mix(in srgb, var(--vmz-action-primary-background) 18%, transparent);
31
+ animation: vmz-ui-skeleton-pulse var(--vmz-motion-overlay-duration) var(--vmz-motion-overlay-easing) infinite alternate;
32
+ }
38
33
 
39
- .vmz-ui-skeleton__line {
40
- width: 72%;
41
- height: 0.75rem;
42
- }
34
+ .vmz-ui-skeleton__block {
35
+ width: 100%;
36
+ height: 2.5rem;
37
+ }
43
38
 
44
- .vmz-ui-skeleton__line + .vmz-ui-skeleton__line {
45
- width: 48%;
46
- }
39
+ .vmz-ui-skeleton__line {
40
+ width: 72%;
41
+ height: 0.75rem;
42
+ }
47
43
 
48
- .vmz-ui-skeleton__content {
49
- display: flex;
50
- flex-direction: column;
51
- gap: inherit;
52
- }
44
+ .vmz-ui-skeleton__line + .vmz-ui-skeleton__line {
45
+ width: 48%;
46
+ }
53
47
 
54
- @keyframes vmz-ui-skeleton-pulse {
55
- from {
56
- opacity: 0.55;
48
+ .vmz-ui-skeleton__content {
49
+ display: flex;
50
+ flex-direction: column;
51
+ gap: inherit;
57
52
  }
58
- to {
59
- opacity: 1;
53
+
54
+ @keyframes vmz-ui-skeleton-pulse {
55
+ from {
56
+ opacity: 0.55;
57
+ }
58
+ to {
59
+ opacity: 1;
60
+ }
60
61
  }
61
- }
62
62
 
63
- @media (prefers-reduced-motion: reduce) {
64
- .vmz-ui-skeleton__block,
65
- .vmz-ui-skeleton__line {
66
- animation: none;
63
+ @media (prefers-reduced-motion: reduce) {
64
+ .vmz-ui-skeleton__block,
65
+ .vmz-ui-skeleton__line {
66
+ animation: none;
67
+ }
67
68
  }
68
- }
69
69
  </style>
70
70
 
71
71
  <script client>
72
72
  /**
73
- * VMZ UI — Skeleton (UI5 Console Surface).
74
- * Loading placeholder with stable min-height (CLS guard); parent owns loading.
75
- */
73
+ * VMZ UI — Skeleton (UI5 Console Surface).
74
+ * Loading placeholder with stable min-height (CLS guard); parent owns loading.
75
+ */
76
76
  export default class Skeleton {
77
- public loading: boolean = true;
78
- public loadingAttr: string = 'true';
77
+ public loading: boolean = true;
78
+ public loadingAttr: string = "true";
79
79
  }
80
80
  </script>
@@ -0,0 +1,15 @@
1
+ <template><div class="vmz-ui-space" data-vmz-ui="space" data-direction={direction} data-size={size} data-wrap={wrap?'true':'false'}><slot /></div></template>
2
+ <style>
3
+ .vmz-ui-space{display:flex;gap:var(--vmz-density-control-gap,.75rem)}
4
+ .vmz-ui-space[data-direction='vertical']{flex-direction:column}
5
+ .vmz-ui-space[data-wrap='true']{flex-wrap:wrap}
6
+ .vmz-ui-space[data-size='small']{gap:.5rem}
7
+ .vmz-ui-space[data-size='large']{gap:1.5rem}
8
+ </style>
9
+ <script client>
10
+ export default class Space {
11
+ public direction: string = 'horizontal';
12
+ public size: string = 'middle';
13
+ public wrap: boolean = false;
14
+ }
15
+ </script>
@@ -1,45 +1,45 @@
1
1
  <template>
2
2
  <span
3
- class="vmz-ui-spinner"
4
- data-vmz-ui="spinner"
5
- role="status"
6
- aria-label={label}
7
- ></span>
3
+ class="vmz-ui-spinner"
4
+ data-vmz-ui="spinner"
5
+ role="status"
6
+ aria-label={label}
7
+ ></span>
8
8
  </template>
9
9
 
10
10
  <style>
11
- .vmz-ui-spinner {
12
- display: inline-block;
13
- width: 1rem;
14
- height: 1rem;
15
- border: 2px solid color-mix(in srgb, var(--vmz-action-primary-background) 25%, transparent);
16
- border-top-color: var(--vmz-action-primary-background);
17
- border-radius: 50%;
18
- vertical-align: -0.15em;
19
- animation: vmz-ui-spin var(--vmz-motion-overlay-duration) var(--vmz-motion-overlay-easing) infinite;
20
- }
11
+ .vmz-ui-spinner {
12
+ display: inline-block;
13
+ width: 1rem;
14
+ height: 1rem;
15
+ border: 2px solid color-mix(in srgb, var(--vmz-action-primary-background) 25%, transparent);
16
+ border-top-color: var(--vmz-action-primary-background);
17
+ border-radius: 50%;
18
+ vertical-align: -0.15em;
19
+ animation: vmz-ui-spin var(--vmz-motion-overlay-duration) var(--vmz-motion-overlay-easing) infinite;
20
+ }
21
21
 
22
- @keyframes vmz-ui-spin {
23
- to {
24
- transform: rotate(360deg);
22
+ @keyframes vmz-ui-spin {
23
+ to {
24
+ transform: rotate(360deg);
25
+ }
25
26
  }
26
- }
27
27
 
28
- @media (prefers-reduced-motion: reduce) {
29
- .vmz-ui-spinner {
30
- animation: none;
31
- border-color: var(--vmz-action-primary-background);
32
- opacity: 0.55;
28
+ @media (prefers-reduced-motion: reduce) {
29
+ .vmz-ui-spinner {
30
+ animation: none;
31
+ border-color: var(--vmz-action-primary-background);
32
+ opacity: 0.55;
33
+ }
33
34
  }
34
- }
35
35
  </style>
36
36
 
37
37
  <script client>
38
38
  /**
39
- * VMZ UI — Spinner (Foundation).
40
- * Loading indicator; reduced-motion keeps static feedback.
41
- */
39
+ * VMZ UI — Spinner (Foundation).
40
+ * Loading indicator; reduced-motion keeps static feedback.
41
+ */
42
42
  export default class Spinner {
43
- public label: string = 'Loading';
43
+ public label: string = "Loading";
44
44
  }
45
45
  </script>
@@ -1,107 +1,107 @@
1
1
  <template>
2
2
  <ol class="vmz-ui-steps" data-vmz-ui="steps" aria-label={label}>
3
- <li
4
- each={items}
5
- as="item"
6
- key={item.id}
7
- class="vmz-ui-steps__item"
8
- data-vmz-step={item.id}
9
- data-status={item.status}
10
- aria-current={current === item.id ? 'step' : 'false'}
11
- >
12
- <span class="vmz-ui-steps__index" data-vmz-step-index={item.id}>{item.index}</span>
13
- <span class="vmz-ui-steps__body">
14
- <span class="vmz-ui-steps__title">{item.title}</span>
15
- <span if={item.description} class="vmz-ui-steps__description">{item.description}</span>
16
- </span>
17
- </li>
18
- </ol>
3
+ <li
4
+ each={items}
5
+ as="item"
6
+ key={item.id}
7
+ class="vmz-ui-steps__item"
8
+ data-vmz-step={item.id}
9
+ data-status={item.status}
10
+ aria-current={current === item.id ? 'step' : 'false'}
11
+ >
12
+ <span class="vmz-ui-steps__index" data-vmz-step-index={item.id}>{item.index}</span>
13
+ <span class="vmz-ui-steps__body">
14
+ <span class="vmz-ui-steps__title">{item.title}</span>
15
+ <span if={item.description} class="vmz-ui-steps__description">{item.description}</span>
16
+ </span>
17
+ </li>
18
+ </ol>
19
19
  </template>
20
20
 
21
21
  <style>
22
- .vmz-ui-steps {
23
- margin: 0;
24
- padding: 0;
25
- list-style: none;
26
- display: flex;
27
- flex-direction: column;
28
- gap: var(--vmz-density-control-gap);
29
- max-width: 36rem;
30
- }
22
+ .vmz-ui-steps {
23
+ margin: 0;
24
+ padding: 0;
25
+ list-style: none;
26
+ display: flex;
27
+ flex-direction: column;
28
+ gap: var(--vmz-density-control-gap);
29
+ max-width: 36rem;
30
+ }
31
31
 
32
- .vmz-ui-steps__item {
33
- display: flex;
34
- align-items: flex-start;
35
- gap: 0.75rem;
36
- color: var(--vmz-text-steel);
37
- }
32
+ .vmz-ui-steps__item {
33
+ display: flex;
34
+ align-items: flex-start;
35
+ gap: 0.75rem;
36
+ color: var(--vmz-text-steel);
37
+ }
38
38
 
39
- .vmz-ui-steps__item[data-status='done'] {
40
- color: var(--vmz-status-success-foreground);
41
- }
39
+ .vmz-ui-steps__item[data-status='done'] {
40
+ color: var(--vmz-status-success-foreground);
41
+ }
42
42
 
43
- .vmz-ui-steps__item[data-status='current'] {
44
- color: var(--vmz-action-primary-active);
45
- }
43
+ .vmz-ui-steps__item[data-status='current'] {
44
+ color: var(--vmz-action-primary-active);
45
+ }
46
46
 
47
- .vmz-ui-steps__index {
48
- flex: 0 0 auto;
49
- min-width: 1.75rem;
50
- height: 1.75rem;
51
- display: inline-flex;
52
- align-items: center;
53
- justify-content: center;
54
- border: 1px solid var(--vmz-line-default);
55
- border-radius: 999px;
56
- font-weight: 700;
57
- font-size: 0.85rem;
58
- color: inherit;
59
- }
47
+ .vmz-ui-steps__index {
48
+ flex: 0 0 auto;
49
+ min-width: 1.75rem;
50
+ height: 1.75rem;
51
+ display: inline-flex;
52
+ align-items: center;
53
+ justify-content: center;
54
+ border: 1px solid var(--vmz-line-default);
55
+ border-radius: 999px;
56
+ font-weight: 700;
57
+ font-size: 0.85rem;
58
+ color: inherit;
59
+ }
60
60
 
61
- .vmz-ui-steps__item[data-status='current'] .vmz-ui-steps__index {
62
- border-color: var(--vmz-action-primary-background);
63
- background: var(--vmz-action-primary-background);
64
- color: var(--vmz-action-primary-foreground);
65
- }
61
+ .vmz-ui-steps__item[data-status='current'] .vmz-ui-steps__index {
62
+ border-color: var(--vmz-action-primary-background);
63
+ background: var(--vmz-action-primary-background);
64
+ color: var(--vmz-action-primary-foreground);
65
+ }
66
66
 
67
- .vmz-ui-steps__item[data-status='done'] .vmz-ui-steps__index {
68
- border-color: var(--vmz-status-success-accent);
69
- background: color-mix(in srgb, var(--vmz-status-success-accent) 18%, transparent);
70
- }
67
+ .vmz-ui-steps__item[data-status='done'] .vmz-ui-steps__index {
68
+ border-color: var(--vmz-status-success-accent);
69
+ background: color-mix(in srgb, var(--vmz-status-success-accent) 18%, transparent);
70
+ }
71
71
 
72
- .vmz-ui-steps__body {
73
- display: flex;
74
- flex-direction: column;
75
- gap: 0.2rem;
76
- padding-top: 0.15rem;
77
- }
72
+ .vmz-ui-steps__body {
73
+ display: flex;
74
+ flex-direction: column;
75
+ gap: 0.2rem;
76
+ padding-top: 0.15rem;
77
+ }
78
78
 
79
- .vmz-ui-steps__title {
80
- font-weight: 700;
81
- }
79
+ .vmz-ui-steps__title {
80
+ font-weight: 700;
81
+ }
82
82
 
83
- .vmz-ui-steps__description {
84
- font-size: 0.9em;
85
- opacity: 0.9;
86
- }
83
+ .vmz-ui-steps__description {
84
+ font-size: 0.9em;
85
+ opacity: 0.9;
86
+ }
87
87
  </style>
88
88
 
89
89
  <script client>
90
90
  /**
91
- * VMZ UI — Steps.
92
- * Parent owns `current` id and item `status` (upcoming|current|done).
93
- * Navigation actions stay on the page (no private wizard store).
94
- */
91
+ * VMZ UI — Steps.
92
+ * Parent owns `current` id and item `status` (upcoming|current|done).
93
+ * Navigation actions stay on the page (no private wizard store).
94
+ */
95
95
  export default class Steps {
96
- public label: string = 'Steps';
97
- public current: string = '';
98
- /** @type {{ id: string, index: string, title: string, description?: string, status: string }[]} */
99
- public items: {
100
- id: string;
101
- index: string;
102
- title: string;
103
- description?: string;
104
- status: string;
105
- }[] = [];
96
+ public label: string = "Steps";
97
+ public current: string = "";
98
+ /** @type {{ id: string, index: string, title: string, description?: string, status: string }[]} */
99
+ public items: {
100
+ id: string;
101
+ index: string;
102
+ title: string;
103
+ description?: string;
104
+ status: string;
105
+ }[] = [];
106
106
  }
107
107
  </script>
@@ -1,109 +1,107 @@
1
1
  <template>
2
2
  <label class="vmz-ui-switch" data-vmz-ui="switch" for={controlId}>
3
- <button
4
- id={controlId}
5
- type="button"
6
- class="vmz-ui-switch__control"
7
- role="switch"
8
- aria-checked={checked}
9
- aria-describedby={describedBy}
10
- disabled={disabled}
11
- onClick={toggle}
12
- onKeyDown={onKeyDown}
13
- >
14
- <span class="vmz-ui-switch__thumb" aria-hidden="true"></span>
15
- </button>
16
- <span class="vmz-ui-switch__label">{label}</span>
17
- </label>
3
+ <button
4
+ id={controlId}
5
+ type="button"
6
+ class="vmz-ui-switch__control"
7
+ role="switch"
8
+ aria-checked={checked}
9
+ aria-describedby={describedBy}
10
+ disabled={disabled}
11
+ onClick={toggle}
12
+ onKeyDown={onKeyDown}
13
+ >
14
+ <span class="vmz-ui-switch__thumb" aria-hidden="true"></span>
15
+ </button>
16
+ <span class="vmz-ui-switch__label">{label}</span>
17
+ </label>
18
18
  </template>
19
19
 
20
20
  <style>
21
- .vmz-ui-switch {
22
- display: inline-flex;
23
- align-items: center;
24
- gap: 0.55rem;
25
- font: inherit;
26
- cursor: pointer;
27
- }
21
+ .vmz-ui-switch {
22
+ display: inline-flex;
23
+ align-items: center;
24
+ gap: 0.55rem;
25
+ font: inherit;
26
+ cursor: pointer;
27
+ }
28
28
 
29
- .vmz-ui-switch__control {
30
- position: relative;
31
- width: 2.4rem;
32
- height: 1.35rem;
33
- padding: 0;
34
- border: 1px solid var(--vmz-action-primary-background);
35
- border-radius: 999px;
36
- background: transparent;
37
- cursor: pointer;
38
- outline: none;
39
- }
29
+ .vmz-ui-switch__control {
30
+ position: relative;
31
+ width: 2.4rem;
32
+ height: 1.35rem;
33
+ padding: 0;
34
+ border: 1px solid var(--vmz-line-default);
35
+ border-radius: 999px;
36
+ background: transparent;
37
+ cursor: pointer;
38
+ outline: none;
39
+ }
40
40
 
41
- .vmz-ui-switch__control[aria-checked='true'],
42
- .vmz-ui-switch__control[aria-checked=''] {
43
- background: var(--vmz-action-primary-background);
44
- }
41
+ .vmz-ui-switch__control[aria-checked='true'],
42
+ .vmz-ui-switch__control[aria-checked=''] {
43
+ background: var(--vmz-action-primary-background);
44
+ }
45
45
 
46
- .vmz-ui-switch__control:focus-visible {
47
- box-shadow: 0 0 0 2px var(--vmz-focus-ring);
48
- }
46
+ .vmz-ui-switch__control:focus-visible {
47
+ box-shadow: 0 0 0 2px var(--vmz-focus-ring);
48
+ }
49
49
 
50
- .vmz-ui-switch__control:disabled {
51
- opacity: 0.55;
52
- cursor: not-allowed;
53
- }
50
+ .vmz-ui-switch__control:disabled {
51
+ opacity: 0.55;
52
+ cursor: not-allowed;
53
+ }
54
54
 
55
- .vmz-ui-switch__thumb {
56
- position: absolute;
57
- top: 0.12rem;
58
- left: 0.12rem;
59
- width: 1rem;
60
- height: 1rem;
61
- border-radius: 999px;
62
- background: var(--vmz-action-primary-foreground);
63
- transition: transform var(--vmz-motion-control-duration) var(--vmz-motion-control-easing);
64
- }
55
+ .vmz-ui-switch__thumb {
56
+ position: absolute;
57
+ top: 0.12rem;
58
+ left: 0.12rem;
59
+ width: 1rem;
60
+ height: 1rem;
61
+ border-radius: 999px;
62
+ background: var(--vmz-action-primary-foreground);
63
+ transition: transform var(--vmz-motion-control-duration) var(--vmz-motion-control-easing);
64
+ }
65
65
 
66
- .vmz-ui-switch__control[aria-checked='true'] .vmz-ui-switch__thumb,
67
- .vmz-ui-switch__control[aria-checked=''] .vmz-ui-switch__thumb {
68
- transform: translateX(1.05rem);
69
- }
66
+ .vmz-ui-switch__control[aria-checked='true'] .vmz-ui-switch__thumb,
67
+ .vmz-ui-switch__control[aria-checked=''] .vmz-ui-switch__thumb {
68
+ transform: translateX(1.05rem);
69
+ }
70
70
 
71
- .vmz-ui-switch__label {
72
- font-weight: 600;
73
- }
71
+ .vmz-ui-switch__label {
72
+ font-weight: 600;
73
+ }
74
74
 
75
- @media (prefers-reduced-motion: reduce) {
76
- .vmz-ui-switch__thumb {
77
- transition: none;
75
+ @media (prefers-reduced-motion: reduce) {
76
+ .vmz-ui-switch__thumb {
77
+ transition: none;
78
+ }
78
79
  }
79
- }
80
80
  </style>
81
81
 
82
82
  <script client>
83
83
  /**
84
- * VMZ UI — Switch (UI2).
85
- * role=switch + aria-checked; parent owns checked (no parallel form store).
86
- */
84
+ * VMZ UI — Switch (UI2).
85
+ * role=switch + aria-checked; parent owns checked (no parallel form store).
86
+ */
87
87
  export default class Switch {
88
- public label: string = '';
89
- public checked: boolean = false;
90
- public disabled: boolean = false;
91
- public controlId: string = 'vmz-switch';
92
- public describedBy: string = '';
93
- public onChange: ((checked: boolean) => void) | null = null;
94
-
95
- toggle() {
96
- if (this.disabled) return;
97
- const next = !this.checked;
98
- if (typeof this.onChange === 'function') this.onChange(next);
99
- }
100
-
101
- onKeyDown(ev) {
102
- if (!ev) return;
103
- if (ev.key === ' ' || ev.key === 'Enter') {
104
- ev.preventDefault();
105
- this.toggle();
106
- }
107
- }
88
+ public label: string = "";
89
+ public checked: boolean = false;
90
+ public disabled: boolean = false;
91
+ public controlId: string = "vmz-switch";
92
+ public describedBy: string = "";
93
+ public onChange: ((checked: boolean) => void) | null = null;
94
+ toggle() {
95
+ if (this.disabled) return;
96
+ const next = !this.checked;
97
+ if (typeof this.onChange === "function") this.onChange(next);
98
+ }
99
+ onKeyDown(ev) {
100
+ if (!ev) return;
101
+ if (ev.key === " " || ev.key === "Enter") {
102
+ ev.preventDefault();
103
+ this.toggle();
104
+ }
105
+ }
108
106
  }
109
107
  </script>