@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.
- package/package.json +1 -1
- package/src/components/Accordion.vmz +46 -63
- package/src/components/Alert.vmz +35 -38
- package/src/components/AppShell.vmz +92 -75
- package/src/components/Autocomplete.vmz +91 -119
- package/src/components/Avatar.vmz +37 -8
- package/src/components/Badge.vmz +29 -23
- package/src/components/Breadcrumb.vmz +36 -34
- package/src/components/BulkActions.vmz +22 -28
- package/src/components/Button.vmz +139 -121
- package/src/components/Callout.vmz +33 -36
- package/src/components/Card.vmz +68 -51
- package/src/components/Checkbox.vmz +28 -47
- package/src/components/CodeBlock.vmz +31 -25
- package/src/components/Collapse.vmz +34 -16
- package/src/components/ConsoleShell.vmz +107 -110
- package/src/components/Content.vmz +8 -4
- package/src/components/DataTable.vmz +124 -150
- package/src/components/DatePicker.vmz +526 -521
- package/src/components/Dialog.vmz +408 -327
- package/src/components/Divider.vmz +38 -11
- package/src/components/Drawer.vmz +325 -318
- package/src/components/Dropdown.vmz +53 -19
- package/src/components/Empty.vmz +23 -21
- package/src/components/Field.vmz +77 -83
- package/src/components/FilterBar.vmz +8 -10
- package/src/components/Flex.vmz +21 -6
- package/src/components/Footer.vmz +9 -4
- package/src/components/Form.vmz +35 -46
- package/src/components/FormItem.vmz +44 -43
- package/src/components/Grid.vmz +22 -6
- package/src/components/Header.vmz +11 -4
- package/src/components/Icon.vmz +43 -44
- package/src/components/Layout.vmz +9 -4
- package/src/components/Link.vmz +17 -25
- package/src/components/List.vmz +62 -75
- package/src/components/Menu.vmz +182 -197
- package/src/components/Notification.vmz +35 -38
- package/src/components/Pagination.vmz +37 -47
- package/src/components/Popover.vmz +157 -171
- package/src/components/Progress.vmz +36 -10
- package/src/components/Prose.vmz +29 -31
- package/src/components/QueryForm.vmz +14 -22
- package/src/components/RadioGroup.vmz +70 -84
- package/src/components/Result.vmz +36 -38
- package/src/components/Segmented.vmz +43 -22
- package/src/components/Select.vmz +404 -411
- package/src/components/Sider.vmz +21 -4
- package/src/components/Skeleton.vmz +34 -42
- package/src/components/Space.vmz +24 -9
- package/src/components/Spinner.vmz +17 -23
- package/src/components/Steps.vmz +48 -51
- package/src/components/Switch.vmz +50 -60
- package/src/components/Table.vmz +81 -84
- package/src/components/Tabs.vmz +66 -88
- package/src/components/Tag.vmz +36 -11
- package/src/components/TextArea.vmz +73 -77
- package/src/components/Timeline.vmz +36 -32
- package/src/components/Toc.vmz +31 -37
- package/src/components/Tooltip.vmz +25 -35
- package/src/components/Tree.vmz +127 -144
- package/src/components/Typography.vmz +33 -7
- package/src/components/Upload.vmz +1135 -1057
|
@@ -1,78 +1,79 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
2
|
+
<div data-vmz-ui="form-item" :data-required="requiredAttr" :data-invalid="invalidAttr" class="vmz-ui-form-item">
|
|
3
|
+
<label v-if="label" :for="controlId" class="vmz-ui-form-item__label">
|
|
4
|
+
<span>
|
|
5
|
+
{{ label }}
|
|
6
|
+
</span>
|
|
7
|
+
<span v-if="required" aria-hidden="true" class="vmz-ui-form-item__required">
|
|
8
|
+
*
|
|
9
|
+
</span>
|
|
10
|
+
</label>
|
|
11
|
+
<div class="vmz-ui-form-item__control">
|
|
12
|
+
<slot />
|
|
13
|
+
</div>
|
|
14
|
+
<p v-if="description" :id="descriptionId" class="vmz-ui-form-item__description">
|
|
15
|
+
{{ description }}
|
|
16
|
+
</p>
|
|
17
|
+
<p v-if="error" :id="errorId" role="alert" class="vmz-ui-form-item__error">
|
|
18
|
+
{{ error }}
|
|
19
|
+
</p>
|
|
17
20
|
</div>
|
|
18
21
|
</template>
|
|
19
|
-
|
|
20
22
|
<style>
|
|
21
|
-
|
|
23
|
+
.vmz-ui-form-item {
|
|
22
24
|
display: flex;
|
|
23
25
|
flex-direction: column;
|
|
24
26
|
gap: 0.35rem;
|
|
25
27
|
max-width: 28rem;
|
|
26
|
-
|
|
28
|
+
}
|
|
27
29
|
|
|
28
|
-
|
|
30
|
+
.vmz-ui-form-item__label {
|
|
29
31
|
display: inline-flex;
|
|
30
32
|
align-items: baseline;
|
|
31
33
|
gap: 0.25rem;
|
|
32
34
|
font: inherit;
|
|
33
35
|
font-weight: 600;
|
|
34
|
-
|
|
36
|
+
}
|
|
35
37
|
|
|
36
|
-
|
|
38
|
+
.vmz-ui-form-item__required {
|
|
37
39
|
color: var(--vmz-status-danger-accent);
|
|
38
40
|
font-weight: 700;
|
|
39
|
-
|
|
41
|
+
}
|
|
40
42
|
|
|
41
|
-
|
|
43
|
+
.vmz-ui-form-item__control {
|
|
42
44
|
min-width: 0;
|
|
43
|
-
|
|
45
|
+
}
|
|
44
46
|
|
|
45
|
-
|
|
47
|
+
.vmz-ui-form-item__description {
|
|
46
48
|
margin: 0;
|
|
47
49
|
opacity: 0.75;
|
|
48
50
|
font-size: 0.9em;
|
|
49
|
-
|
|
51
|
+
}
|
|
50
52
|
|
|
51
|
-
|
|
53
|
+
.vmz-ui-form-item__error {
|
|
52
54
|
margin: 0;
|
|
53
55
|
color: var(--vmz-status-danger-foreground);
|
|
54
56
|
font-size: 0.9em;
|
|
55
|
-
|
|
57
|
+
}
|
|
56
58
|
|
|
57
|
-
|
|
59
|
+
.vmz-ui-form-item[data-invalid="true"] .vmz-ui-form-item__control :where(input, select, textarea) {
|
|
58
60
|
border-color: var(--vmz-status-danger-accent);
|
|
59
|
-
|
|
61
|
+
}
|
|
60
62
|
</style>
|
|
61
|
-
|
|
62
63
|
<script client>
|
|
63
64
|
/**
|
|
64
|
-
* VMZ UI — FormItem.
|
|
65
|
-
* Label / description / error shell for slotted controls; parent owns validation strings.
|
|
66
|
-
*/
|
|
65
|
+
* VMZ UI — FormItem.
|
|
66
|
+
* Label / description / error shell for slotted controls; parent owns validation strings.
|
|
67
|
+
*/
|
|
67
68
|
export default class FormItem {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
69
|
+
public label: string = "";
|
|
70
|
+
public description: string = "";
|
|
71
|
+
public error: string = "";
|
|
72
|
+
public required: boolean = false;
|
|
73
|
+
public requiredAttr: string = "false";
|
|
74
|
+
public invalidAttr: string = "false";
|
|
75
|
+
public controlId: string = "vmz-form-item";
|
|
76
|
+
public descriptionId: string = "vmz-form-item-desc";
|
|
77
|
+
public errorId: string = "vmz-form-item-err";
|
|
77
78
|
}
|
|
78
79
|
</script>
|
package/src/components/Grid.vmz
CHANGED
|
@@ -1,12 +1,28 @@
|
|
|
1
|
-
<template
|
|
1
|
+
<template>
|
|
2
|
+
<div data-vmz-ui="grid" class="vmz-ui-grid" :style='"--ui-grid-columns:" + columns + ";--ui-grid-gap:" + gap'>
|
|
3
|
+
<slot />
|
|
4
|
+
</div>
|
|
5
|
+
</template>
|
|
2
6
|
<style>
|
|
3
|
-
.vmz-ui-grid{
|
|
4
|
-
|
|
5
|
-
|
|
7
|
+
.vmz-ui-grid {
|
|
8
|
+
display: grid;
|
|
9
|
+
grid-template-columns: repeat(var(--ui-grid-columns, 3), minmax(0, 1fr));
|
|
10
|
+
gap: var(--ui-grid-gap, 1rem);
|
|
11
|
+
}
|
|
12
|
+
@media (max-width: 900px) {
|
|
13
|
+
.vmz-ui-grid {
|
|
14
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
@media (max-width: 600px) {
|
|
18
|
+
.vmz-ui-grid {
|
|
19
|
+
grid-template-columns: 1fr;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
6
22
|
</style>
|
|
7
23
|
<script client>
|
|
8
24
|
export default class Grid {
|
|
9
|
-
|
|
10
|
-
|
|
25
|
+
public columns: number = 3;
|
|
26
|
+
public gap: string = "1rem";
|
|
11
27
|
}
|
|
12
28
|
</script>
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
2
|
+
<header data-vmz-ui="header" class="vmz-ui-header">
|
|
3
|
+
<slot />
|
|
4
|
+
</header>
|
|
3
5
|
</template>
|
|
4
|
-
|
|
5
6
|
<style>
|
|
6
|
-
|
|
7
|
+
.vmz-ui-header {
|
|
8
|
+
min-height: 4rem;
|
|
9
|
+
display: flex;
|
|
10
|
+
align-items: center;
|
|
11
|
+
padding: 0 1.5rem;
|
|
12
|
+
border-bottom: 1px solid var(--vmz-line-default, #d9d9d9);
|
|
13
|
+
background: var(--vmz-surface-paper, #fff);
|
|
14
|
+
}
|
|
7
15
|
</style>
|
|
8
|
-
|
|
9
16
|
<script client>
|
|
10
17
|
export default class Header {}
|
|
11
18
|
</script>
|
package/src/components/Icon.vmz
CHANGED
|
@@ -6,30 +6,30 @@
|
|
|
6
6
|
</span>
|
|
7
7
|
</template>
|
|
8
8
|
<style>
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
9
|
+
.vmz-ui-icon {
|
|
10
|
+
display: inline-flex;
|
|
11
|
+
align-items: center;
|
|
12
|
+
justify-content: center;
|
|
13
|
+
width: 1em;
|
|
14
|
+
height: 1em;
|
|
15
|
+
vertical-align: -0.125em;
|
|
16
|
+
color: inherit;
|
|
17
|
+
line-height: 1;
|
|
18
|
+
}
|
|
19
|
+
.vmz-ui-icon[data-size="sm"] {
|
|
20
|
+
font-size: 0.875rem;
|
|
21
|
+
}
|
|
22
|
+
.vmz-ui-icon[data-size="md"] {
|
|
23
|
+
font-size: 1rem;
|
|
24
|
+
}
|
|
25
|
+
.vmz-ui-icon[data-size="lg"] {
|
|
26
|
+
font-size: 1.25rem;
|
|
27
|
+
}
|
|
28
|
+
.vmz-ui-icon__svg {
|
|
29
|
+
width: 1em;
|
|
30
|
+
height: 1em;
|
|
31
|
+
display: block;
|
|
32
|
+
}
|
|
33
33
|
</style>
|
|
34
34
|
<script client>
|
|
35
35
|
/**
|
|
@@ -37,41 +37,40 @@
|
|
|
37
37
|
* Pass `pathD` for custom SVG paths, or `name` for the built-in chrome set.
|
|
38
38
|
* Full semantic registries live in optional `@vmz/ui-icons`.
|
|
39
39
|
*/
|
|
40
|
-
const FALLBACK_PATH =
|
|
41
|
-
'M12 2a10 10 0 1 1 0 20 10 10 0 0 1 0-20zm1 5h-2v2h2zm0 4h-2v7h2z';
|
|
40
|
+
const FALLBACK_PATH = "M12 2a10 10 0 1 1 0 20 10 10 0 0 1 0-20zm1 5h-2v2h2zm0 4h-2v7h2z";
|
|
42
41
|
|
|
43
42
|
const CHROME_PATHS = {
|
|
44
|
-
check:
|
|
45
|
-
close:
|
|
46
|
-
search:
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
info:
|
|
43
|
+
check: "M9.2 16.6 4.8 12.2l1.4-1.4 3 3 8-8 1.4 1.4z",
|
|
44
|
+
close: "M6.4 7.8 7.8 6.4 12 10.6 16.2 6.4 17.6 7.8 13.4 12 17.6 16.2 16.2 17.6 12 13.4 7.8 17.6 6.4 16.2 10.6 12z",
|
|
45
|
+
search: "M10.5 3a7.5 7.5 0 0 1 5.9 12.1l4 4-1.4 1.4-4-4A7.5 7.5 0 1 1 10.5 3zm0 2a5.5 5.5 0 1 0 0 11 5.5 5.5 0 0 0 0-11z",
|
|
46
|
+
"chevron-down": "M7.4 9.1 12 13.7l4.6-4.6 1.4 1.4L12 16.5 6 10.5z",
|
|
47
|
+
"chevron-right": "M9.1 6 15.1 12l-6 6-1.4-1.4L12.3 12 7.7 7.4z",
|
|
48
|
+
info: "M12 2a10 10 0 1 1 0 20 10 10 0 0 1 0-20zm0 8.2a1 1 0 0 0-1 1V17a1 1 0 1 0 2 0v-5.8a1 1 0 0 0-1-1zm0-3.7a1.2 1.2 0 1 0 0 2.4 1.2 1.2 0 0 0 0-2.4z",
|
|
50
49
|
warning:
|
|
51
|
-
|
|
52
|
-
success:
|
|
53
|
-
danger:
|
|
54
|
-
menu:
|
|
55
|
-
plus:
|
|
50
|
+
"M12 3.2 21 19H3L12 3.2zm0 5.3a1 1 0 0 0-1 1v4.2a1 1 0 1 0 2 0V9.5a1 1 0 0 0-1-1zm0 8.1a1.2 1.2 0 1 0 0 2.4 1.2 1.2 0 0 0 0-2.4z",
|
|
51
|
+
success: "M12 2a10 10 0 1 1 0 20 10 10 0 0 1 0-20zm-2.5 10.3-2-2 1.4-1.4 2 2 5-5 1.4 1.4z",
|
|
52
|
+
danger: "M12 2a10 10 0 1 1 0 20 10 10 0 0 1 0-20zm-1 5h2v6h-2zm0 8h2v2h-2z",
|
|
53
|
+
menu: "M4 7h16v2H4zm0 4h16v2H4zm0 4h16v2H4z",
|
|
54
|
+
plus: "M11 5h2v6h6v2h-6v6h-2v-6H5v-2h6z",
|
|
56
55
|
};
|
|
57
56
|
|
|
58
57
|
function resolveChromePath(name) {
|
|
59
|
-
const key = String(name ||
|
|
58
|
+
const key = String(name || "").trim();
|
|
60
59
|
if (!key) return FALLBACK_PATH;
|
|
61
60
|
return CHROME_PATHS[key] || FALLBACK_PATH;
|
|
62
61
|
}
|
|
63
62
|
|
|
64
63
|
export default class Icon {
|
|
65
|
-
static __vmzHostBox =
|
|
66
|
-
public name: string =
|
|
67
|
-
public size: string =
|
|
68
|
-
public label: string =
|
|
64
|
+
static __vmzHostBox = "contents";
|
|
65
|
+
public name: string = "info";
|
|
66
|
+
public size: string = "md";
|
|
67
|
+
public label: string = "";
|
|
69
68
|
public decorative: boolean = true;
|
|
70
69
|
/** Optional author SVG path override. When set, `name` is ignored for rendering. */
|
|
71
|
-
public pathD: string =
|
|
70
|
+
public pathD: string = "";
|
|
72
71
|
|
|
73
72
|
iconPath() {
|
|
74
|
-
const explicit = String(this.pathD ||
|
|
73
|
+
const explicit = String(this.pathD || "").trim();
|
|
75
74
|
return explicit || resolveChromePath(this.name);
|
|
76
75
|
}
|
|
77
76
|
}
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
2
|
+
<div data-vmz-ui="layout" class="vmz-ui-layout">
|
|
3
|
+
<slot />
|
|
4
|
+
</div>
|
|
3
5
|
</template>
|
|
4
|
-
|
|
5
6
|
<style>
|
|
6
|
-
|
|
7
|
+
.vmz-ui-layout {
|
|
8
|
+
display: flex;
|
|
9
|
+
flex-direction: column;
|
|
10
|
+
min-height: 100%;
|
|
11
|
+
background: var(--vmz-surface-page, var(--vmz-surface-mist, #f5f5f5));
|
|
12
|
+
}
|
|
7
13
|
</style>
|
|
8
|
-
|
|
9
14
|
<script client>
|
|
10
15
|
export default class Layout {}
|
|
11
16
|
</script>
|
package/src/components/Link.vmz
CHANGED
|
@@ -1,17 +1,10 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
data-vmz-ui="link"
|
|
5
|
-
:href="href"
|
|
6
|
-
:target="target"
|
|
7
|
-
:rel="rel"
|
|
8
|
-
>
|
|
9
|
-
<slot />
|
|
2
|
+
<a data-vmz-ui="link" :href="href" :target="target" :rel="rel" class="vmz-ui-link">
|
|
3
|
+
<slot />
|
|
10
4
|
</a>
|
|
11
5
|
</template>
|
|
12
|
-
|
|
13
6
|
<style>
|
|
14
|
-
|
|
7
|
+
.vmz-ui-link {
|
|
15
8
|
font: inherit;
|
|
16
9
|
font-weight: 600;
|
|
17
10
|
color: var(--vmz-action-primary-background);
|
|
@@ -19,31 +12,30 @@
|
|
|
19
12
|
text-underline-offset: 0.15em;
|
|
20
13
|
text-decoration-thickness: 1px;
|
|
21
14
|
outline: none;
|
|
22
|
-
|
|
15
|
+
}
|
|
23
16
|
|
|
24
|
-
|
|
17
|
+
.vmz-ui-link:hover {
|
|
25
18
|
color: var(--vmz-action-primary-hover);
|
|
26
|
-
|
|
19
|
+
}
|
|
27
20
|
|
|
28
|
-
|
|
21
|
+
.vmz-ui-link:active {
|
|
29
22
|
color: var(--vmz-action-primary-active);
|
|
30
|
-
|
|
23
|
+
}
|
|
31
24
|
|
|
32
|
-
|
|
25
|
+
.vmz-ui-link:focus-visible {
|
|
33
26
|
box-shadow: 0 0 0 2px var(--vmz-focus-ring);
|
|
34
27
|
border-radius: var(--vmz-radius-md, 6px);
|
|
35
|
-
|
|
28
|
+
}
|
|
36
29
|
</style>
|
|
37
|
-
|
|
38
30
|
<script client>
|
|
39
31
|
/**
|
|
40
|
-
* VMZ UI — Link (Foundation).
|
|
41
|
-
* Navigation / inline text link; tokens only, no brand hex.
|
|
42
|
-
*/
|
|
32
|
+
* VMZ UI — Link (Foundation).
|
|
33
|
+
* Navigation / inline text link; tokens only, no brand hex.
|
|
34
|
+
*/
|
|
43
35
|
export default class Link {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
36
|
+
static __vmzHostBox = "contents";
|
|
37
|
+
public href: string = "#";
|
|
38
|
+
public target: string = "";
|
|
39
|
+
public rel: string = "";
|
|
48
40
|
}
|
|
49
41
|
</script>
|
package/src/components/List.vmz
CHANGED
|
@@ -1,45 +1,30 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
role="listbox"
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
>
|
|
12
|
-
<li
|
|
13
|
-
v-for="item in items"
|
|
14
|
-
:key="item.id"
|
|
15
|
-
class="vmz-ui-list__item"
|
|
16
|
-
role="option"
|
|
17
|
-
:id="item.id"
|
|
18
|
-
:data-vmz-list-item="item.id"
|
|
19
|
-
:aria-selected="selected === item.id ? 'true' : 'false'"
|
|
20
|
-
:tabindex="selected === item.id ? 0 : -1"
|
|
21
|
-
>
|
|
22
|
-
{{ item.title }}
|
|
23
|
-
</li>
|
|
24
|
-
</ul>
|
|
2
|
+
<div data-vmz-ui="list" class="vmz-ui-list">
|
|
3
|
+
<p v-if="label" :id="labelId" class="vmz-ui-list__label">
|
|
4
|
+
{{ label }}
|
|
5
|
+
</p>
|
|
6
|
+
<ul role="listbox" :aria-labelledby="labelId" :aria-label="label" @click="onListClick" :onKeyDown="onListKeyDown" class="vmz-ui-list__items">
|
|
7
|
+
<li v-for="item in items" :key="item.id" role="option" :id="item.id" :data-vmz-list-item="item.id" :aria-selected='selected === item.id ? "true" : "false"' :tabindex="selected === item.id ? 0 : -1" class="vmz-ui-list__item">
|
|
8
|
+
{{ item.title }}
|
|
9
|
+
</li>
|
|
10
|
+
</ul>
|
|
25
11
|
</div>
|
|
26
12
|
</template>
|
|
27
|
-
|
|
28
13
|
<style>
|
|
29
|
-
|
|
14
|
+
.vmz-ui-list {
|
|
30
15
|
display: flex;
|
|
31
16
|
flex-direction: column;
|
|
32
17
|
gap: 0.35rem;
|
|
33
18
|
max-width: 28rem;
|
|
34
|
-
|
|
19
|
+
}
|
|
35
20
|
|
|
36
|
-
|
|
21
|
+
.vmz-ui-list__label {
|
|
37
22
|
margin: 0;
|
|
38
23
|
font-weight: 600;
|
|
39
24
|
color: var(--vmz-text-ink);
|
|
40
|
-
|
|
25
|
+
}
|
|
41
26
|
|
|
42
|
-
|
|
27
|
+
.vmz-ui-list__items {
|
|
43
28
|
margin: 0;
|
|
44
29
|
padding: 0.25rem;
|
|
45
30
|
list-style: none;
|
|
@@ -47,69 +32,71 @@
|
|
|
47
32
|
border-radius: var(--vmz-radius-md, 6px);
|
|
48
33
|
background: var(--vmz-surface-paper);
|
|
49
34
|
color: var(--vmz-text-ink);
|
|
50
|
-
|
|
35
|
+
}
|
|
51
36
|
|
|
52
|
-
|
|
37
|
+
.vmz-ui-list__item {
|
|
53
38
|
padding: var(--vmz-density-control-padding-y) var(--vmz-density-control-padding-x);
|
|
54
39
|
border-radius: var(--vmz-radius-md, 6px);
|
|
55
40
|
cursor: pointer;
|
|
56
41
|
outline: none;
|
|
57
|
-
|
|
42
|
+
}
|
|
58
43
|
|
|
59
|
-
|
|
44
|
+
.vmz-ui-list__item[aria-selected="true"] {
|
|
60
45
|
background: var(--vmz-action-primary-background);
|
|
61
46
|
color: var(--vmz-action-primary-foreground);
|
|
62
|
-
|
|
47
|
+
}
|
|
63
48
|
|
|
64
|
-
|
|
49
|
+
.vmz-ui-list__item:hover {
|
|
65
50
|
background: color-mix(in srgb, var(--vmz-action-primary-background) 14%, transparent);
|
|
66
|
-
|
|
51
|
+
}
|
|
67
52
|
|
|
68
|
-
|
|
53
|
+
.vmz-ui-list__item[aria-selected="true"]:hover {
|
|
69
54
|
background: var(--vmz-action-primary-hover);
|
|
70
|
-
|
|
55
|
+
}
|
|
71
56
|
|
|
72
|
-
|
|
57
|
+
.vmz-ui-list__item:focus-visible {
|
|
73
58
|
box-shadow: 0 0 0 2px var(--vmz-focus-ring);
|
|
74
|
-
|
|
59
|
+
}
|
|
75
60
|
</style>
|
|
76
|
-
|
|
77
61
|
<script client>
|
|
78
62
|
/**
|
|
79
|
-
* VMZ UI — List (ordinary selectable list).
|
|
80
|
-
* Parent owns `selected` id; click + Arrow/Home/End. Not a DataGrid.
|
|
81
|
-
*/
|
|
63
|
+
* VMZ UI — List (ordinary selectable list).
|
|
64
|
+
* Parent owns `selected` id; click + Arrow/Home/End. Not a DataGrid.
|
|
65
|
+
*/
|
|
82
66
|
export default class List {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
67
|
+
public label: string = "List";
|
|
68
|
+
public labelId: string = "vmz-list-label";
|
|
69
|
+
public selected: string = "";
|
|
70
|
+
/** @type {{ id: string, title: string }[]} */
|
|
71
|
+
public items: {
|
|
72
|
+
id: string;
|
|
73
|
+
title: string;
|
|
74
|
+
}[] = [];
|
|
75
|
+
public onSelect: ((id: string) => void) | null = null;
|
|
76
|
+
select(id) {
|
|
77
|
+
if (typeof this.onSelect === "function") this.onSelect(id);
|
|
78
|
+
}
|
|
79
|
+
onListClick(ev) {
|
|
80
|
+
const t = ev && ev.target;
|
|
81
|
+
const el = t && typeof t.closest === "function" ? t.closest("[data-vmz-list-item]") : null;
|
|
82
|
+
const id =
|
|
83
|
+
el && typeof el.getAttribute === "function"
|
|
84
|
+
? el.getAttribute("data-vmz-list-item")
|
|
85
|
+
: null;
|
|
86
|
+
if (id) this.select(id);
|
|
87
|
+
}
|
|
88
|
+
onListKeyDown(ev) {
|
|
89
|
+
if (!ev || !this.items?.length) return;
|
|
90
|
+
const ids = this.items.map((it) => it.id);
|
|
91
|
+
const idx = Math.max(0, ids.indexOf(this.selected));
|
|
92
|
+
let next = idx;
|
|
93
|
+
if (ev.key === "ArrowDown") next = (idx + 1) % ids.length;
|
|
94
|
+
else if (ev.key === "ArrowUp") next = (idx - 1 + ids.length) % ids.length;
|
|
95
|
+
else if (ev.key === "Home") next = 0;
|
|
96
|
+
else if (ev.key === "End") next = ids.length - 1;
|
|
97
|
+
else return;
|
|
98
|
+
ev.preventDefault();
|
|
99
|
+
this.select(ids[next]);
|
|
100
|
+
}
|
|
114
101
|
}
|
|
115
102
|
</script>
|