@vmz/ui 0.2.3 → 0.2.4

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 (63) hide show
  1. package/package.json +1 -1
  2. package/src/components/Accordion.vmz +46 -63
  3. package/src/components/Alert.vmz +35 -38
  4. package/src/components/AppShell.vmz +92 -75
  5. package/src/components/Autocomplete.vmz +91 -119
  6. package/src/components/Avatar.vmz +37 -8
  7. package/src/components/Badge.vmz +29 -23
  8. package/src/components/Breadcrumb.vmz +36 -34
  9. package/src/components/BulkActions.vmz +22 -28
  10. package/src/components/Button.vmz +139 -121
  11. package/src/components/Callout.vmz +33 -36
  12. package/src/components/Card.vmz +68 -51
  13. package/src/components/Checkbox.vmz +28 -47
  14. package/src/components/CodeBlock.vmz +31 -25
  15. package/src/components/Collapse.vmz +34 -16
  16. package/src/components/ConsoleShell.vmz +107 -110
  17. package/src/components/Content.vmz +8 -4
  18. package/src/components/DataTable.vmz +124 -150
  19. package/src/components/DatePicker.vmz +526 -521
  20. package/src/components/Dialog.vmz +408 -327
  21. package/src/components/Divider.vmz +38 -11
  22. package/src/components/Drawer.vmz +325 -318
  23. package/src/components/Dropdown.vmz +53 -19
  24. package/src/components/Empty.vmz +23 -21
  25. package/src/components/Field.vmz +77 -83
  26. package/src/components/FilterBar.vmz +8 -10
  27. package/src/components/Flex.vmz +21 -6
  28. package/src/components/Footer.vmz +9 -4
  29. package/src/components/Form.vmz +35 -46
  30. package/src/components/FormItem.vmz +44 -43
  31. package/src/components/Grid.vmz +22 -6
  32. package/src/components/Header.vmz +11 -4
  33. package/src/components/Icon.vmz +43 -44
  34. package/src/components/Layout.vmz +9 -4
  35. package/src/components/Link.vmz +17 -25
  36. package/src/components/List.vmz +62 -75
  37. package/src/components/Menu.vmz +182 -197
  38. package/src/components/Notification.vmz +35 -38
  39. package/src/components/Pagination.vmz +37 -47
  40. package/src/components/Popover.vmz +157 -171
  41. package/src/components/Progress.vmz +36 -10
  42. package/src/components/Prose.vmz +29 -31
  43. package/src/components/QueryForm.vmz +14 -22
  44. package/src/components/RadioGroup.vmz +70 -84
  45. package/src/components/Result.vmz +36 -38
  46. package/src/components/Segmented.vmz +43 -22
  47. package/src/components/Select.vmz +404 -411
  48. package/src/components/Sider.vmz +21 -4
  49. package/src/components/Skeleton.vmz +34 -42
  50. package/src/components/Space.vmz +24 -9
  51. package/src/components/Spinner.vmz +17 -23
  52. package/src/components/Steps.vmz +48 -51
  53. package/src/components/Switch.vmz +50 -60
  54. package/src/components/Table.vmz +81 -84
  55. package/src/components/Tabs.vmz +66 -88
  56. package/src/components/Tag.vmz +36 -11
  57. package/src/components/TextArea.vmz +73 -77
  58. package/src/components/Timeline.vmz +36 -32
  59. package/src/components/Toc.vmz +31 -37
  60. package/src/components/Tooltip.vmz +25 -35
  61. package/src/components/Tree.vmz +127 -144
  62. package/src/components/Typography.vmz +33 -7
  63. package/src/components/Upload.vmz +1135 -1057
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vmz/ui",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "type": "module",
5
5
  "description": "VMZ UI — official UI framework (component contracts + semantic token requirements). Not a theme. Not a plugin.",
6
6
  "license": "MIT",
@@ -1,35 +1,19 @@
1
1
  <template>
2
- <div class="vmz-ui-accordion" data-vmz-ui="accordion" :aria-label="label">
3
- <div v-for="item in items" :key="item.id" class="vmz-ui-accordion__item" :data-vmz-accordion="item.id">
4
- <h3 class="vmz-ui-accordion__heading">
5
- <button
6
- type="button"
7
- class="vmz-ui-accordion__trigger"
8
- :id="item.triggerId"
9
- :data-vmz-accordion-trigger="item.id"
10
- :aria-expanded="openId === item.id ? 'true' : 'false'"
11
- :aria-controls="item.panelId"
12
- @click="() => toggle(item.id)"
13
- >
14
- {{ item.title }}
15
- </button>
16
- </h3>
17
- <div
18
- v-if="openId === item.id"
19
- :id="item.panelId"
20
- class="vmz-ui-accordion__panel"
21
- role="region"
22
- :data-vmz-accordion-panel="item.id"
23
- :aria-labelledby="item.triggerId"
24
- >
25
- {{ item.body }}
2
+ <div data-vmz-ui="accordion" :aria-label="label" class="vmz-ui-accordion">
3
+ <div v-for="item in items" :key="item.id" :data-vmz-accordion="item.id" class="vmz-ui-accordion__item">
4
+ <h3 class="vmz-ui-accordion__heading">
5
+ <button type="button" :id="item.triggerId" :data-vmz-accordion-trigger="item.id" :aria-expanded='openId === item.id ? "true" : "false"' :aria-controls="item.panelId" @click="(() => toggle(item.id))" class="vmz-ui-accordion__trigger">
6
+ {{ item.title }}
7
+ </button>
8
+ </h3>
9
+ <div v-if="openId === item.id" :id="item.panelId" role="region" :data-vmz-accordion-panel="item.id" :aria-labelledby="item.triggerId" class="vmz-ui-accordion__panel">
10
+ {{ item.body }}
11
+ </div>
26
12
  </div>
27
- </div>
28
13
  </div>
29
14
  </template>
30
-
31
15
  <style>
32
- .vmz-ui-accordion {
16
+ .vmz-ui-accordion {
33
17
  display: flex;
34
18
  flex-direction: column;
35
19
  gap: 0.35rem;
@@ -38,22 +22,22 @@
38
22
  border-radius: var(--vmz-radius-md, 6px);
39
23
  background: var(--vmz-surface-paper);
40
24
  color: var(--vmz-text-ink);
41
- }
25
+ }
42
26
 
43
- .vmz-ui-accordion__item {
27
+ .vmz-ui-accordion__item {
44
28
  border-bottom: 1px solid var(--vmz-line-default);
45
- }
29
+ }
46
30
 
47
- .vmz-ui-accordion__item:last-child {
31
+ .vmz-ui-accordion__item:last-child {
48
32
  border-bottom: none;
49
- }
33
+ }
50
34
 
51
- .vmz-ui-accordion__heading {
35
+ .vmz-ui-accordion__heading {
52
36
  margin: 0;
53
37
  font: inherit;
54
- }
38
+ }
55
39
 
56
- .vmz-ui-accordion__trigger {
40
+ .vmz-ui-accordion__trigger {
57
41
  display: block;
58
42
  width: 100%;
59
43
  text-align: start;
@@ -65,47 +49,46 @@
65
49
  color: inherit;
66
50
  cursor: pointer;
67
51
  outline: none;
68
- }
52
+ }
69
53
 
70
- .vmz-ui-accordion__trigger:hover {
54
+ .vmz-ui-accordion__trigger:hover {
71
55
  background: color-mix(in srgb, var(--vmz-surface-mist) 85%, transparent);
72
- }
56
+ }
73
57
 
74
- .vmz-ui-accordion__trigger:focus-visible {
58
+ .vmz-ui-accordion__trigger:focus-visible {
75
59
  box-shadow: inset 0 0 0 2px var(--vmz-focus-ring);
76
- }
60
+ }
77
61
 
78
- .vmz-ui-accordion__trigger[aria-expanded='true'] {
62
+ .vmz-ui-accordion__trigger[aria-expanded="true"] {
79
63
  color: var(--vmz-action-primary-active);
80
- }
64
+ }
81
65
 
82
- .vmz-ui-accordion__panel {
66
+ .vmz-ui-accordion__panel {
83
67
  padding: 0 var(--vmz-density-control-padding-x) var(--vmz-density-control-padding-y);
84
68
  color: var(--vmz-text-steel);
85
69
  line-height: 1.5;
86
- }
70
+ }
87
71
  </style>
88
-
89
72
  <script client>
90
73
  /**
91
- * VMZ UI — Accordion.
92
- * Exclusive open: parent owns `openId`. Toggle same id closes.
93
- * Panel body lives on items (no per-panel slot runtime).
94
- */
74
+ * VMZ UI — Accordion.
75
+ * Exclusive open: parent owns `openId`. Toggle same id closes.
76
+ * Panel body lives on items (no per-panel slot runtime).
77
+ */
95
78
  export default class Accordion {
96
- public label: string = "Accordion";
97
- public openId: string = "";
98
- /** @type {{ id: string, title: string, body: string, triggerId: string, panelId: string }[]} */
99
- public items: {
100
- id: string;
101
- title: string;
102
- body: string;
103
- triggerId: string;
104
- panelId: string;
105
- }[] = [];
106
- public onToggle: ((id: string) => void) | null = null;
107
- toggle(id) {
108
- if (typeof this.onToggle === "function") this.onToggle(id);
109
- }
79
+ public label: string = "Accordion";
80
+ public openId: string = "";
81
+ /** @type {{ id: string, title: string, body: string, triggerId: string, panelId: string }[]} */
82
+ public items: {
83
+ id: string;
84
+ title: string;
85
+ body: string;
86
+ triggerId: string;
87
+ panelId: string;
88
+ }[] = [];
89
+ public onToggle: ((id: string) => void) | null = null;
90
+ toggle(id) {
91
+ if (typeof this.onToggle === "function") this.onToggle(id);
92
+ }
110
93
  }
111
94
  </script>
@@ -1,20 +1,18 @@
1
1
  <template>
2
- <div
3
- class="vmz-ui-alert"
4
- data-vmz-ui="alert"
5
- :data-tone="tone"
6
- :role="roleName"
7
- >
8
- <p v-if="title" class="vmz-ui-alert__title">{{ title }}</p>
9
- <p v-if="description" class="vmz-ui-alert__description">{{ description }}</p>
10
- <div class="vmz-ui-alert__actions">
11
- <slot />
12
- </div>
2
+ <div data-vmz-ui="alert" :data-tone="tone" :role="roleName" class="vmz-ui-alert">
3
+ <p v-if="title" class="vmz-ui-alert__title">
4
+ {{ title }}
5
+ </p>
6
+ <p v-if="description" class="vmz-ui-alert__description">
7
+ {{ description }}
8
+ </p>
9
+ <div class="vmz-ui-alert__actions">
10
+ <slot />
11
+ </div>
13
12
  </div>
14
13
  </template>
15
-
16
14
  <style>
17
- .vmz-ui-alert {
15
+ .vmz-ui-alert {
18
16
  display: flex;
19
17
  flex-direction: column;
20
18
  gap: var(--vmz-density-control-gap);
@@ -24,62 +22,61 @@
24
22
  border-radius: var(--vmz-radius-md, 6px);
25
23
  background: color-mix(in srgb, var(--vmz-status-info-accent) 12%, transparent);
26
24
  color: var(--vmz-status-info-foreground);
27
- }
25
+ }
28
26
 
29
- .vmz-ui-alert[data-tone='info'] {
27
+ .vmz-ui-alert[data-tone="info"] {
30
28
  border-color: var(--vmz-status-info-accent);
31
29
  background: color-mix(in srgb, var(--vmz-status-info-accent) 12%, transparent);
32
30
  color: var(--vmz-status-info-foreground);
33
- }
31
+ }
34
32
 
35
- .vmz-ui-alert[data-tone='success'] {
33
+ .vmz-ui-alert[data-tone="success"] {
36
34
  border-color: var(--vmz-status-success-accent);
37
35
  background: color-mix(in srgb, var(--vmz-status-success-accent) 12%, transparent);
38
36
  color: var(--vmz-status-success-foreground);
39
- }
37
+ }
40
38
 
41
- .vmz-ui-alert[data-tone='warning'] {
39
+ .vmz-ui-alert[data-tone="warning"] {
42
40
  border-color: var(--vmz-status-warning-accent);
43
41
  background: color-mix(in srgb, var(--vmz-status-warning-accent) 12%, transparent);
44
42
  color: var(--vmz-status-warning-foreground);
45
- }
43
+ }
46
44
 
47
- .vmz-ui-alert[data-tone='danger'] {
45
+ .vmz-ui-alert[data-tone="danger"] {
48
46
  border-color: var(--vmz-status-danger-accent);
49
47
  background: color-mix(in srgb, var(--vmz-status-danger-accent) 12%, transparent);
50
48
  color: var(--vmz-status-danger-foreground);
51
- }
49
+ }
52
50
 
53
- :where([data-density='compact']) .vmz-ui-alert {
51
+ :where([data-density="compact"]) .vmz-ui-alert {
54
52
  gap: var(--vmz-density-compact-gap);
55
53
  padding: var(--vmz-density-compact-padding-y) var(--vmz-density-compact-padding-x);
56
- }
54
+ }
57
55
 
58
- .vmz-ui-alert__title {
56
+ .vmz-ui-alert__title {
59
57
  margin: 0;
60
58
  font-size: 0.875rem;
61
59
  font-weight: 600;
62
- }
60
+ }
63
61
 
64
- .vmz-ui-alert__description {
62
+ .vmz-ui-alert__description {
65
63
  margin: 0;
66
64
  opacity: 0.9;
67
- }
65
+ }
68
66
 
69
- .vmz-ui-alert__actions:empty {
67
+ .vmz-ui-alert__actions:empty {
70
68
  display: none;
71
- }
69
+ }
72
70
  </style>
73
-
74
71
  <script client>
75
72
  /**
76
- * VMZ UI — Alert (UI4 status tone matrix).
77
- * tone → status.{info|success|warning|danger}.* tokens from Style Theme.
78
- */
73
+ * VMZ UI — Alert (UI4 status tone matrix).
74
+ * tone → status.{info|success|warning|danger}.* tokens from Style Theme.
75
+ */
79
76
  export default class Alert {
80
- public title: string = "";
81
- public description: string = "";
82
- public tone: string = "info";
83
- public roleName: string = "status";
77
+ public title: string = "";
78
+ public description: string = "";
79
+ public tone: string = "info";
80
+ public roleName: string = "status";
84
81
  }
85
82
  </script>
@@ -1,116 +1,133 @@
1
1
  <template>
2
- <div class="vmz-ui-app-shell" data-vmz-ui="app-shell">
3
- <header class="vmz-ui-app-shell__header" data-vmz-shell="header"><div class="vmz-ui-app-shell__header-inner">
4
- <a class="vmz-ui-app-shell__brand" :href="homeHref">{{ brand }}</a>
5
- <nav class="vmz-ui-app-shell__nav" :aria-label="navLabel">
6
- <a v-for="item in nav" :key="item.id" :href="item.href" :data-vmz-nav="item.id">
7
- {{ item.title }}
8
- </a>
9
- </nav>
10
- </div></header>
11
- <main class="vmz-ui-app-shell__main" data-vmz-shell="main">
12
- <slot />
13
- </main>
2
+ <div data-vmz-ui="app-shell" class="vmz-ui-app-shell">
3
+ <header data-vmz-shell="header" class="vmz-ui-app-shell__header">
4
+ <div class="vmz-ui-app-shell__header-inner">
5
+ <a :href="homeHref" class="vmz-ui-app-shell__brand">
6
+ {{ brand }}
7
+ </a>
8
+ <nav :aria-label="navLabel" class="vmz-ui-app-shell__nav">
9
+ <a v-for="item in nav" :key="item.id" :href="item.href" :data-vmz-nav="item.id">
10
+ {{ item.title }}
11
+ </a>
12
+ </nav>
13
+ </div>
14
+ </header>
15
+ <main data-vmz-shell="main" class="vmz-ui-app-shell__main">
16
+ <slot />
17
+ </main>
14
18
  </div>
15
19
  </template>
16
-
17
20
  <style>
18
- .vmz-ui-app-shell {
21
+ .vmz-ui-app-shell {
19
22
  display: flex;
20
23
  flex-direction: column;
21
24
  min-height: 100%;
22
25
  color: var(--vmz-text-ink);
23
26
  background: transparent;
24
- }
27
+ }
25
28
 
26
29
  .vmz-ui-app-shell__header {
27
- position: sticky;
28
- top: 0;
29
- z-index: 30;
30
- border-bottom: 1px solid var(--vmz-line-subtle, var(--vmz-line-default));
31
- background: var(--vmz-surface-paper);
30
+ position: sticky;
31
+ top: 0;
32
+ z-index: 30;
33
+ border-bottom: 1px solid var(--vmz-line-subtle, var(--vmz-line-default));
34
+ background: var(--vmz-surface-paper);
32
35
  }
33
36
  .vmz-ui-app-shell__header-inner {
34
- width: min(var(--vmz-layout-max-width, 75rem), calc(100% - 2rem));
35
- min-height: 3rem;
36
- margin: 0 auto;
37
- display: flex;
38
- align-items: center;
39
- justify-content: space-between;
40
- gap: 1.5rem;
37
+ width: min(var(--vmz-layout-max-width, 75rem), calc(100% - 2rem));
38
+ min-height: 3rem;
39
+ margin: 0 auto;
40
+ display: flex;
41
+ align-items: center;
42
+ justify-content: space-between;
43
+ gap: 1.5rem;
41
44
  }
42
45
 
43
46
  .vmz-ui-app-shell__brand {
44
- font-family: var(--vmz-font-sans);
45
- font-weight: 600;
46
- font-size: 1.125rem;
47
- letter-spacing: 0;
48
- text-decoration: none;
49
- color: var(--vmz-text-ink);
47
+ font-family: var(--vmz-font-sans);
48
+ font-weight: 600;
49
+ font-size: 1.125rem;
50
+ letter-spacing: 0;
51
+ text-decoration: none;
52
+ color: var(--vmz-text-ink);
50
53
  }
51
54
 
52
55
  .vmz-ui-app-shell__brand:focus-visible {
53
- outline: none;
54
- box-shadow: 0 0 0 2px var(--vmz-focus-ring);
56
+ outline: none;
57
+ box-shadow: 0 0 0 2px var(--vmz-focus-ring);
55
58
  }
56
59
 
57
60
  .vmz-ui-app-shell__nav {
58
- display: flex;
59
- flex-wrap: wrap;
60
- gap: 0.25rem 0.15rem;
61
+ display: flex;
62
+ flex-wrap: wrap;
63
+ gap: 0.25rem 0.15rem;
61
64
  }
62
65
 
63
66
  .vmz-ui-app-shell__nav a {
64
- font: inherit;
65
- font-size: 0.875rem;
66
- font-weight: 400;
67
- text-decoration: none;
68
- color: var(--vmz-text-ink);
69
- padding: 0.25rem 0.75rem;
70
- border-radius: var(--vmz-radius-md, 6px);
67
+ font: inherit;
68
+ font-size: 0.875rem;
69
+ font-weight: 400;
70
+ text-decoration: none;
71
+ color: var(--vmz-text-ink);
72
+ padding: 0.25rem 0.75rem;
73
+ border-radius: var(--vmz-radius-md, 6px);
71
74
  }
72
75
 
73
76
  .vmz-ui-app-shell__nav a:hover {
74
- color: var(--vmz-action-primary-background);
75
- background: var(--vmz-surface-mist, #fafafa);
77
+ color: var(--vmz-action-primary-background);
78
+ background: var(--vmz-surface-mist, #fafafa);
76
79
  }
77
80
 
78
81
  .vmz-ui-app-shell__nav a:focus-visible {
79
- outline: none;
80
- box-shadow: 0 0 0 2px var(--vmz-focus-ring);
82
+ outline: none;
83
+ box-shadow: 0 0 0 2px var(--vmz-focus-ring);
81
84
  }
82
85
 
83
86
  .vmz-ui-app-shell__main {
84
- flex: 1;
85
- width: min(var(--vmz-layout-max-width, 75rem), calc(100% - 2rem));
86
- margin: 0 auto;
87
- padding: 1.5rem 0 2.5rem;
88
- display: flex;
89
- flex-direction: column;
90
- gap: 1rem;
87
+ flex: 1;
88
+ width: min(var(--vmz-layout-max-width, 75rem), calc(100% - 2rem));
89
+ margin: 0 auto;
90
+ padding: 1.5rem 0 2.5rem;
91
+ display: flex;
92
+ flex-direction: column;
93
+ gap: 1rem;
94
+ }
95
+ @media (max-width: 720px) {
96
+ .vmz-ui-app-shell__header-inner {
97
+ min-height: 3.5rem;
98
+ align-items: flex-start;
99
+ flex-direction: column;
100
+ gap: 0.35rem;
101
+ padding: 0.7rem 0;
102
+ }
103
+ .vmz-ui-app-shell__nav {
104
+ width: 100%;
105
+ overflow-x: auto;
106
+ flex-wrap: nowrap;
107
+ padding-bottom: 0.2rem;
108
+ }
109
+ .vmz-ui-app-shell__nav a {
110
+ white-space: nowrap;
111
+ }
112
+ .vmz-ui-app-shell__main {
113
+ padding-top: 1.25rem;
114
+ }
91
115
  }
92
- @media (max-width: 720px) {
93
- .vmz-ui-app-shell__header-inner { min-height: 3.5rem; align-items: flex-start; flex-direction: column; gap: .35rem; padding: .7rem 0; }
94
- .vmz-ui-app-shell__nav { width: 100%; overflow-x: auto; flex-wrap: nowrap; padding-bottom: .2rem; }
95
- .vmz-ui-app-shell__nav a { white-space: nowrap; }
96
- .vmz-ui-app-shell__main { padding-top: 1.25rem; }
97
- }
98
116
  </style>
99
-
100
117
  <script client>
101
118
  /**
102
- * VMZ UI — AppShell (Commercial composition).
103
- * Landmark header/nav + main slot. Parent supplies nav items; no private theme.
104
- */
119
+ * VMZ UI — AppShell (Commercial composition).
120
+ * Landmark header/nav + main slot. Parent supplies nav items; no private theme.
121
+ */
105
122
  export default class AppShell {
106
- public brand: string = "VMZ";
107
- public homeHref: string = "/";
108
- public navLabel: string = "Primary";
109
- /** @type {{ id: string, title: string, href: string }[]} */
110
- public nav: {
111
- id: string;
112
- title: string;
113
- href: string;
114
- }[] = [];
123
+ public brand: string = "VMZ";
124
+ public homeHref: string = "/";
125
+ public navLabel: string = "Primary";
126
+ /** @type {{ id: string, title: string, href: string }[]} */
127
+ public nav: {
128
+ id: string;
129
+ title: string;
130
+ href: string;
131
+ }[] = [];
115
132
  }
116
133
  </script>