@vmz/ui 0.2.4 → 0.2.6
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 +9 -1
- package/src/components/Icon.vmz +108 -31
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vmz/ui",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.6",
|
|
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",
|
|
@@ -83,6 +83,14 @@
|
|
|
83
83
|
"ui",
|
|
84
84
|
"components"
|
|
85
85
|
],
|
|
86
|
+
"peerDependencies": {
|
|
87
|
+
"@vmz/ui-icons": "0.2.6"
|
|
88
|
+
},
|
|
89
|
+
"peerDependenciesMeta": {
|
|
90
|
+
"@vmz/ui-icons": {
|
|
91
|
+
"optional": true
|
|
92
|
+
}
|
|
93
|
+
},
|
|
86
94
|
"publishConfig": {
|
|
87
95
|
"access": "public"
|
|
88
96
|
},
|
package/src/components/Icon.vmz
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<span data-vmz-ui="icon" :data-name="name" :data-size="size" :role='decorative ? "presentation" : "img"' :aria-hidden='decorative ? "true" : "false"' :aria-label='decorative ? "" : label' class="vmz-ui-icon">
|
|
3
|
-
<
|
|
4
|
-
|
|
3
|
+
<span v-if="isTextBadge()" class="vmz-ui-icon__badge">
|
|
4
|
+
{{ badgeLabel() }}
|
|
5
|
+
</span>
|
|
6
|
+
<svg v-else viewBox="0 0 24 24" focusable="false" aria-hidden="true" class="vmz-ui-icon__svg">
|
|
7
|
+
<path v-if="hasExplicitPath()" fill="currentColor" :d="explicitPath()" />
|
|
8
|
+
<g v-else-if="isStroke()" fill="none" stroke="currentColor" :stroke-width="strokeWidth()" stroke-linecap="round" stroke-linejoin="round">
|
|
9
|
+
<path v-for="d in strokePaths()" :key="d" :d="d" />
|
|
10
|
+
<circle v-for="c in strokeCircles()" :key="circleKey(c)" :cx="c.cx" :cy="c.cy" :r="c.r" />
|
|
11
|
+
<circle v-for="dot in strokeDots()" :key="dotKey(dot)" :cx="dot.cx" :cy="dot.cy" :r="dot.r" fill="currentColor" stroke="none" />
|
|
12
|
+
</g>
|
|
13
|
+
<path v-else-if="isFill()" fill="currentColor" :fill-rule="fillRule()" :d="fillD()" />
|
|
5
14
|
</svg>
|
|
6
15
|
</span>
|
|
7
16
|
</template>
|
|
@@ -30,36 +39,31 @@
|
|
|
30
39
|
height: 1em;
|
|
31
40
|
display: block;
|
|
32
41
|
}
|
|
42
|
+
.vmz-ui-icon__badge {
|
|
43
|
+
display: inline-flex;
|
|
44
|
+
align-items: center;
|
|
45
|
+
justify-content: center;
|
|
46
|
+
box-sizing: border-box;
|
|
47
|
+
min-width: 1.65em;
|
|
48
|
+
padding: 0.12em 0.22em;
|
|
49
|
+
border: 1.5px solid currentColor;
|
|
50
|
+
border-radius: 0.2em;
|
|
51
|
+
font-family: var(--vmz-font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
|
|
52
|
+
font-size: 0.52em;
|
|
53
|
+
font-weight: 600;
|
|
54
|
+
letter-spacing: -0.03em;
|
|
55
|
+
line-height: 1.1;
|
|
56
|
+
text-align: center;
|
|
57
|
+
text-transform: uppercase;
|
|
58
|
+
}
|
|
33
59
|
</style>
|
|
34
60
|
<script client>
|
|
61
|
+
import { DEFAULT_STROKE_WIDTH, resolveIconDef } from "@vmz/ui-icons/registry";
|
|
62
|
+
|
|
35
63
|
/**
|
|
36
|
-
* VMZ UI Icon — shell
|
|
37
|
-
* Pass `pathD` for
|
|
38
|
-
* Full semantic registries live in optional `@vmz/ui-icons`.
|
|
64
|
+
* VMZ UI Icon — chrome shell backed by `@vmz/ui-icons` registry.
|
|
65
|
+
* Pass `pathD` for author SVG path overrides; otherwise resolves `name` from registry.
|
|
39
66
|
*/
|
|
40
|
-
const FALLBACK_PATH = "M12 2a10 10 0 1 1 0 20 10 10 0 0 1 0-20zm1 5h-2v2h2zm0 4h-2v7h2z";
|
|
41
|
-
|
|
42
|
-
const CHROME_PATHS = {
|
|
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",
|
|
49
|
-
warning:
|
|
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",
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
function resolveChromePath(name) {
|
|
58
|
-
const key = String(name || "").trim();
|
|
59
|
-
if (!key) return FALLBACK_PATH;
|
|
60
|
-
return CHROME_PATHS[key] || FALLBACK_PATH;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
67
|
export default class Icon {
|
|
64
68
|
static __vmzHostBox = "contents";
|
|
65
69
|
public name: string = "info";
|
|
@@ -69,9 +73,82 @@ export default class Icon {
|
|
|
69
73
|
/** Optional author SVG path override. When set, `name` is ignored for rendering. */
|
|
70
74
|
public pathD: string = "";
|
|
71
75
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
76
|
+
hasExplicitPath() {
|
|
77
|
+
return Boolean(String(this.pathD || "").trim());
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
explicitPath() {
|
|
81
|
+
return String(this.pathD || "").trim();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
iconDef() {
|
|
85
|
+
if (this.hasExplicitPath()) return null;
|
|
86
|
+
return resolveIconDef(this.name);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
isStroke() {
|
|
90
|
+
const def = this.iconDef();
|
|
91
|
+
return def?.kind === "stroke";
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
isFill() {
|
|
95
|
+
const def = this.iconDef();
|
|
96
|
+
return def?.kind === "fill";
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
isTextBadge() {
|
|
100
|
+
const def = this.iconDef();
|
|
101
|
+
return def?.kind === "text-badge";
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
badgeLabel() {
|
|
105
|
+
const def = this.iconDef();
|
|
106
|
+
if (def?.kind !== "text-badge") return "";
|
|
107
|
+
return def.label;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
strokeWidth() {
|
|
111
|
+
const def = this.iconDef();
|
|
112
|
+
if (def?.kind !== "stroke") return DEFAULT_STROKE_WIDTH;
|
|
113
|
+
return def.strokeWidth ?? DEFAULT_STROKE_WIDTH;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
strokePaths() {
|
|
117
|
+
const def = this.iconDef();
|
|
118
|
+
if (def?.kind !== "stroke") return [];
|
|
119
|
+
return def.paths ?? [];
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
strokeCircles() {
|
|
123
|
+
const def = this.iconDef();
|
|
124
|
+
if (def?.kind !== "stroke") return [];
|
|
125
|
+
return def.circles ?? [];
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
strokeDots() {
|
|
129
|
+
const def = this.iconDef();
|
|
130
|
+
if (def?.kind !== "stroke") return [];
|
|
131
|
+
return def.dots ?? [];
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
circleKey(c) {
|
|
135
|
+
return `c-${c.cx}-${c.cy}-${c.r}`;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
dotKey(dot) {
|
|
139
|
+
return `d-${dot.cx}-${dot.cy}-${dot.r}`;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
fillD() {
|
|
143
|
+
const def = this.iconDef();
|
|
144
|
+
if (def?.kind !== "fill") return "";
|
|
145
|
+
return def.d;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
fillRule() {
|
|
149
|
+
const def = this.iconDef();
|
|
150
|
+
if (def?.kind !== "fill" || !def.fillRule) return "";
|
|
151
|
+
return def.fillRule;
|
|
75
152
|
}
|
|
76
153
|
}
|
|
77
154
|
</script>
|