@vmz/ui 0.3.6 → 0.3.7

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 (42) hide show
  1. package/README.md +51 -51
  2. package/package.json +2 -2
  3. package/src/components/Accordion.vmz +94 -94
  4. package/src/components/AppShell.vmz +5 -2
  5. package/src/components/Autocomplete.vmz +154 -154
  6. package/src/components/Badge.vmz +70 -70
  7. package/src/components/Breadcrumb.vmz +72 -72
  8. package/src/components/BulkActions.vmz +51 -51
  9. package/src/components/Button.vmz +213 -211
  10. package/src/components/Callout.vmz +77 -77
  11. package/src/components/Card.vmz +120 -120
  12. package/src/components/Checkbox.vmz +55 -55
  13. package/src/components/CodeBlock.vmz +21 -6
  14. package/src/components/ConsoleShell.vmz +251 -251
  15. package/src/components/DataTable.vmz +194 -194
  16. package/src/components/DatePicker.vmz +674 -674
  17. package/src/components/Dialog.vmz +17 -1
  18. package/src/components/Drawer.vmz +427 -427
  19. package/src/components/Dropdown.vmz +51 -5
  20. package/src/components/Empty.vmz +54 -54
  21. package/src/components/Field.vmz +115 -115
  22. package/src/components/FormItem.vmz +79 -79
  23. package/src/components/Link.vmz +5 -1
  24. package/src/components/List.vmz +102 -102
  25. package/src/components/Menu.vmz +243 -243
  26. package/src/components/Pagination.vmz +71 -69
  27. package/src/components/Popover.vmz +223 -223
  28. package/src/components/Prose.vmz +81 -81
  29. package/src/components/RadioGroup.vmz +124 -124
  30. package/src/components/Segmented.vmz +51 -51
  31. package/src/components/Select.vmz +533 -533
  32. package/src/components/Steps.vmz +103 -103
  33. package/src/components/Switch.vmz +98 -98
  34. package/src/components/Table.vmz +165 -165
  35. package/src/components/Tabs.vmz +110 -110
  36. package/src/components/Tag.vmz +43 -43
  37. package/src/components/TextArea.vmz +118 -118
  38. package/src/components/Timeline.vmz +76 -76
  39. package/src/components/Toc.vmz +74 -74
  40. package/src/components/Tooltip.vmz +58 -58
  41. package/src/components/Tree.vmz +191 -191
  42. package/src/components/Upload.vmz +1299 -1289
@@ -1,120 +1,120 @@
1
- <template>
2
- <section data-vmz-ui="card" :data-size="size" :data-bordered="bordered ? 'true' : 'false'" :data-hoverable="hoverable ? 'true' : 'false'" class="vmz-ui-card">
3
- <header v-if="title" class="vmz-ui-card__header">
4
- <h2 class="vmz-ui-card__title">
5
- {{ title }}
6
- </h2>
7
- <p v-if="description" class="vmz-ui-card__description">
8
- {{ description }}
9
- </p>
10
- </header>
11
- <div class="vmz-ui-card__body">
12
- <slot />
13
- </div>
14
- </section>
15
- </template>
16
- <style>
17
- .vmz-ui-card {
18
- display: flex;
19
- flex-direction: column;
20
- gap: 0.75rem;
21
- padding: 1.25rem 1.5rem;
22
- border: 1px solid var(--vmz-line-subtle, var(--vmz-line-default));
23
- border-radius: var(--vmz-radius-lg, 8px);
24
- background: var(--vmz-surface-paper);
25
- color: var(--vmz-text-ink);
26
- box-shadow: var(--vmz-shadow-card, none);
27
- }
28
- .vmz-ui-card[data-bordered="false"] {
29
- border-color: transparent;
30
- }
31
- .vmz-ui-card[data-hoverable="true"] {
32
- transition:
33
- border-color var(--vmz-motion-emphasis-duration, 240ms) var(--vmz-motion-emphasis-easing, cubic-bezier(0.16, 1, 0.3, 1)),
34
- box-shadow var(--vmz-motion-emphasis-duration, 240ms) var(--vmz-motion-emphasis-easing, cubic-bezier(0.16, 1, 0.3, 1)),
35
- transform var(--vmz-motion-emphasis-duration, 240ms) var(--vmz-motion-emphasis-easing, cubic-bezier(0.16, 1, 0.3, 1));
36
- }
37
- .vmz-ui-card[data-hoverable="true"]:hover {
38
- border-color: var(--vmz-line-default);
39
- box-shadow: var(
40
- --vmz-shadow-card-hover,
41
- 0 1px 2px -2px rgba(0, 0, 0, 0.08),
42
- 0 3px 6px 0 rgba(0, 0, 0, 0.06)
43
- );
44
- transform: translateY(-1px);
45
- }
46
- .vmz-ui-card[data-hoverable="true"]:focus-within {
47
- border-color: var(--vmz-action-primary-background);
48
- }
49
- @media (prefers-reduced-motion: reduce) {
50
- .vmz-ui-card[data-hoverable="true"] {
51
- transition: none;
52
- }
53
- .vmz-ui-card[data-hoverable="true"]:hover {
54
- transform: none;
55
- }
56
- }
57
- .vmz-ui-card[data-size="small"] {
58
- gap: 0.5rem;
59
- padding: 0.875rem 1rem;
60
- }
61
-
62
- :where([data-density="compact"]) .vmz-ui-card {
63
- gap: var(--vmz-density-compact-gap);
64
- padding: var(--vmz-density-compact-padding-y) var(--vmz-density-compact-padding-x);
65
- }
66
-
67
- :where([data-density="dense"]) .vmz-ui-card {
68
- gap: var(--vmz-density-dense-gap);
69
- padding: var(--vmz-density-dense-padding-y) var(--vmz-density-dense-padding-x);
70
- }
71
-
72
- .vmz-ui-card__header {
73
- display: flex;
74
- flex-direction: column;
75
- gap: 0.375rem;
76
- }
77
-
78
- .vmz-ui-card__title {
79
- margin: 0;
80
- font-family: var(--vmz-font-sans, inherit);
81
- font-size: 1rem;
82
- font-weight: 600;
83
- color: var(--vmz-text-ink);
84
- }
85
-
86
- .vmz-ui-card__description {
87
- margin: 0;
88
- color: var(--vmz-text-steel);
89
- line-height: 1.45;
90
- }
91
-
92
- .vmz-ui-card__body {
93
- display: flex;
94
- flex-direction: column;
95
- gap: var(--vmz-density-control-gap);
96
- }
97
-
98
- /* Direct host default is display:contents (runtime); Badge-only CSS special-case removed. */
99
-
100
- :where([data-density="compact"]) .vmz-ui-card__body {
101
- gap: var(--vmz-density-compact-gap);
102
- }
103
-
104
- :where([data-density="dense"]) .vmz-ui-card__body {
105
- gap: var(--vmz-density-dense-gap);
106
- }
107
- </style>
108
- <script client>
109
- /**
110
- * VMZ UI — Card (Commercial Surface).
111
- * Surface container; spacing from density.*; chrome from surface/line/text.
112
- */
113
- export default class Card {
114
- public title: string = "";
115
- public description: string = "";
116
- public size: string = "middle";
117
- public bordered: boolean = true;
118
- public hoverable: boolean = false;
119
- }
120
- </script>
1
+ <template>
2
+ <section data-vmz-ui="card" :data-size="size" :data-bordered="bordered ? 'true' : 'false'" :data-hoverable="hoverable ? 'true' : 'false'" class="vmz-ui-card">
3
+ <header v-if="title" class="vmz-ui-card__header">
4
+ <h2 class="vmz-ui-card__title">
5
+ {{ title }}
6
+ </h2>
7
+ <p v-if="description" class="vmz-ui-card__description">
8
+ {{ description }}
9
+ </p>
10
+ </header>
11
+ <div class="vmz-ui-card__body">
12
+ <slot />
13
+ </div>
14
+ </section>
15
+ </template>
16
+ <style>
17
+ .vmz-ui-card {
18
+ display: flex;
19
+ flex-direction: column;
20
+ gap: 0.75rem;
21
+ padding: 1.25rem 1.5rem;
22
+ border: 1px solid var(--vmz-line-subtle, var(--vmz-line-default));
23
+ border-radius: var(--vmz-radius-lg, 8px);
24
+ background: var(--vmz-surface-paper);
25
+ color: var(--vmz-text-ink);
26
+ box-shadow: var(--vmz-shadow-card, none);
27
+ }
28
+ .vmz-ui-card[data-bordered="false"] {
29
+ border-color: transparent;
30
+ }
31
+ .vmz-ui-card[data-hoverable="true"] {
32
+ transition:
33
+ border-color var(--vmz-motion-emphasis-duration, 240ms) var(--vmz-motion-emphasis-easing, cubic-bezier(0.16, 1, 0.3, 1)),
34
+ box-shadow var(--vmz-motion-emphasis-duration, 240ms) var(--vmz-motion-emphasis-easing, cubic-bezier(0.16, 1, 0.3, 1)),
35
+ transform var(--vmz-motion-emphasis-duration, 240ms) var(--vmz-motion-emphasis-easing, cubic-bezier(0.16, 1, 0.3, 1));
36
+ }
37
+ .vmz-ui-card[data-hoverable="true"]:hover {
38
+ border-color: var(--vmz-line-default);
39
+ box-shadow: var(
40
+ --vmz-shadow-card-hover,
41
+ 0 1px 2px -2px rgba(0, 0, 0, 0.08),
42
+ 0 3px 6px 0 rgba(0, 0, 0, 0.06)
43
+ );
44
+ transform: translateY(-1px);
45
+ }
46
+ .vmz-ui-card[data-hoverable="true"]:focus-within {
47
+ border-color: var(--vmz-action-primary-background);
48
+ }
49
+ @media (prefers-reduced-motion: reduce) {
50
+ .vmz-ui-card[data-hoverable="true"] {
51
+ transition: none;
52
+ }
53
+ .vmz-ui-card[data-hoverable="true"]:hover {
54
+ transform: none;
55
+ }
56
+ }
57
+ .vmz-ui-card[data-size="small"] {
58
+ gap: 0.5rem;
59
+ padding: 0.875rem 1rem;
60
+ }
61
+
62
+ :where([data-density="compact"]) .vmz-ui-card {
63
+ gap: var(--vmz-density-compact-gap);
64
+ padding: var(--vmz-density-compact-padding-y) var(--vmz-density-compact-padding-x);
65
+ }
66
+
67
+ :where([data-density="dense"]) .vmz-ui-card {
68
+ gap: var(--vmz-density-dense-gap);
69
+ padding: var(--vmz-density-dense-padding-y) var(--vmz-density-dense-padding-x);
70
+ }
71
+
72
+ .vmz-ui-card__header {
73
+ display: flex;
74
+ flex-direction: column;
75
+ gap: 0.375rem;
76
+ }
77
+
78
+ .vmz-ui-card__title {
79
+ margin: 0;
80
+ font-family: var(--vmz-font-sans, inherit);
81
+ font-size: 1rem;
82
+ font-weight: 600;
83
+ color: var(--vmz-text-ink);
84
+ }
85
+
86
+ .vmz-ui-card__description {
87
+ margin: 0;
88
+ color: var(--vmz-text-steel);
89
+ line-height: 1.45;
90
+ }
91
+
92
+ .vmz-ui-card__body {
93
+ display: flex;
94
+ flex-direction: column;
95
+ gap: var(--vmz-density-control-gap);
96
+ }
97
+
98
+ /* Direct host default is display:contents (runtime); Badge-only CSS special-case removed. */
99
+
100
+ :where([data-density="compact"]) .vmz-ui-card__body {
101
+ gap: var(--vmz-density-compact-gap);
102
+ }
103
+
104
+ :where([data-density="dense"]) .vmz-ui-card__body {
105
+ gap: var(--vmz-density-dense-gap);
106
+ }
107
+ </style>
108
+ <script client>
109
+ /**
110
+ * VMZ UI — Card (Commercial Surface).
111
+ * Surface container; spacing from density.*; chrome from surface/line/text.
112
+ */
113
+ export default class Card {
114
+ public title: string = "";
115
+ public description: string = "";
116
+ public size: string = "middle";
117
+ public bordered: boolean = true;
118
+ public hoverable: boolean = false;
119
+ }
120
+ </script>
@@ -1,55 +1,55 @@
1
- <template>
2
- <label data-vmz-ui="checkbox" :for="controlId" class="vmz-ui-checkbox">
3
- <input :id="controlId" type="checkbox" :checked="checked" :disabled="disabled" :aria-describedby="describedBy" @change="onToggle" class="vmz-ui-checkbox__input" />
4
- <span class="vmz-ui-checkbox__label">
5
- {{ label }}
6
- </span>
7
- </label>
8
- </template>
9
- <style>
10
- .vmz-ui-checkbox {
11
- display: inline-flex;
12
- align-items: center;
13
- gap: 0.5rem;
14
- font: inherit;
15
- cursor: pointer;
16
- }
17
-
18
- .vmz-ui-checkbox__input {
19
- width: 1rem;
20
- height: 1rem;
21
- accent-color: var(--vmz-action-primary-background);
22
- outline: none;
23
- }
24
-
25
- .vmz-ui-checkbox__input:focus-visible {
26
- box-shadow: 0 0 0 3px var(--vmz-focus-ring);
27
- }
28
-
29
- .vmz-ui-checkbox__input:disabled {
30
- opacity: 0.55;
31
- cursor: not-allowed;
32
- }
33
-
34
- .vmz-ui-checkbox__label {
35
- font-weight: 600;
36
- }
37
- </style>
38
- <script client>
39
- /**
40
- * VMZ UI — Checkbox (UI2).
41
- * Label association via wrapping label + for/id; parent owns checked (no parallel form store).
42
- * Native change reports the committed checked state to the parent.
43
- */
44
- export default class Checkbox {
45
- public label: string = "";
46
- public checked: boolean = false;
47
- public disabled: boolean = false;
48
- public controlId: string = "vmz-checkbox";
49
- public describedBy: string = "";
50
- onToggle(ev) {
51
- if (this.disabled) return;
52
- this.emit("change", !!ev?.target?.checked);
53
- }
54
- }
55
- </script>
1
+ <template>
2
+ <label data-vmz-ui="checkbox" :for="controlId" class="vmz-ui-checkbox">
3
+ <input :id="controlId" type="checkbox" :checked="checked" :disabled="disabled" :aria-describedby="describedBy" @change="onToggle" class="vmz-ui-checkbox__input" />
4
+ <span class="vmz-ui-checkbox__label">
5
+ {{ label }}
6
+ </span>
7
+ </label>
8
+ </template>
9
+ <style>
10
+ .vmz-ui-checkbox {
11
+ display: inline-flex;
12
+ align-items: center;
13
+ gap: 0.5rem;
14
+ font: inherit;
15
+ cursor: pointer;
16
+ }
17
+
18
+ .vmz-ui-checkbox__input {
19
+ width: 1rem;
20
+ height: 1rem;
21
+ accent-color: var(--vmz-action-primary-background);
22
+ outline: none;
23
+ }
24
+
25
+ .vmz-ui-checkbox__input:focus-visible {
26
+ box-shadow: 0 0 0 3px var(--vmz-focus-ring);
27
+ }
28
+
29
+ .vmz-ui-checkbox__input:disabled {
30
+ opacity: 0.55;
31
+ cursor: not-allowed;
32
+ }
33
+
34
+ .vmz-ui-checkbox__label {
35
+ font-weight: 600;
36
+ }
37
+ </style>
38
+ <script client>
39
+ /**
40
+ * VMZ UI — Checkbox (UI2).
41
+ * Label association via wrapping label + for/id; parent owns checked (no parallel form store).
42
+ * Native change reports the committed checked state to the parent.
43
+ */
44
+ export default class Checkbox {
45
+ public label: string = "";
46
+ public checked: boolean = false;
47
+ public disabled: boolean = false;
48
+ public controlId: string = "vmz-checkbox";
49
+ public describedBy: string = "";
50
+ onToggle(ev) {
51
+ if (this.disabled) return;
52
+ this.emit("change", !!ev?.target?.checked);
53
+ }
54
+ }
55
+ </script>
@@ -2,11 +2,17 @@
2
2
  <figure data-vmz-ui="code-block" class="vmz-ui-code-block">
3
3
  <div v-if="barVisible()" class="vmz-ui-code-block__bar">
4
4
  <div class="vmz-ui-code-block__heading">
5
- <span v-if="language" class="vmz-ui-code-block__lang">{{ language }}</span>
6
- <span v-if="title" class="vmz-ui-code-block__caption">{{ title }}</span>
7
- <span v-else-if="caption" class="vmz-ui-code-block__caption">{{ caption }}</span>
5
+ <span v-if="language" class="vmz-ui-code-block__lang">
6
+ {{ language }}
7
+ </span>
8
+ <span v-if="title" class="vmz-ui-code-block__caption">
9
+ {{ title }}
10
+ </span>
11
+ <span v-else-if="caption" class="vmz-ui-code-block__caption">
12
+ {{ caption }}
13
+ </span>
8
14
  </div>
9
- <Button type="button" variant="text" size="sm" class="vmz-ui-code-block__copy" @click="onCopy">
15
+ <Button v-if="canCopy()" type="button" variant="text" size="sm" @click="onCopy" class="vmz-ui-code-block__copy">
10
16
  {{ copyLabel }}
11
17
  </Button>
12
18
  </div>
@@ -112,21 +118,30 @@
112
118
  <script client>
113
119
  /**
114
120
  * VMZ UI — CodeBlock (Document/Product composition).
115
- * Source is readable in SSR HTML; copy is progressive enhancement via onCopy.
121
+ * Readable `<pre><code>` shell: no syntax highlighting (use `<Shiki>` / `<Code>`).
122
+ * `title` wins over legacy `caption`; `language` is a display-only chip.
123
+ * Source and bar are server-rendered; copy is progressive enhancement via onCopy.
116
124
  */
117
125
  export default class CodeBlock {
118
126
  public code: string = "";
127
+ /** Legacy heading text; kept for existing callers and used when `title` is empty. */
119
128
  public caption: string = "";
120
129
  /** Preferred heading text; falls back to `caption` when absent. */
121
130
  public title: string = "";
122
131
  /** Optional syntax label rendered as a chip in the bar (e.g. `ts`, `bash`). */
123
132
  public language: string = "";
133
+ /** Visible label of the copy control. */
124
134
  public copyLabel: string = "Copy";
125
135
  public onCopy: ((e: Event) => void) | null = null;
126
136
 
127
137
  /** The bar renders when there is anything to show in it. */
128
138
  public barVisible(): boolean {
129
- return !!(this.title || this.caption || this.language || this.onCopy);
139
+ return !!(this.title || this.caption || this.language || this.canCopy());
140
+ }
141
+
142
+ /** Copy is a real control only when a handler exists; no dead button. */
143
+ public canCopy(): boolean {
144
+ return typeof this.onCopy === "function";
130
145
  }
131
146
  }
132
147
  </script>