@nice2dev/icons 1.3.15 → 1.3.17
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/CHANGELOG.md +26 -0
- package/README.md +1 -1
- package/dist/cjs/NiceDesktopIconExporter.js +688 -599
- package/dist/cjs/NiceFaviconGenerator.js +603 -417
- package/dist/cjs/NiceIconPicker.js +788 -508
- package/dist/cjs/NiceIconPreview.js +246 -188
- package/dist/cjs/NiceIconSetCreator.js +683 -552
- package/dist/cjs/NiceIconStacker.js +547 -171
- package/dist/cjs/NiceIconValue.js +27 -35
- package/dist/cjs/NtdIconBadge.js +384 -360
- package/dist/cjs/NtdIconMorph.js +419 -354
- package/dist/cjs/NtdStateMorph.js +150 -147
- package/dist/cjs/advancedIconSearch.js +373 -510
- package/dist/cjs/animationControls.js +518 -642
- package/dist/cjs/animationSpeed.js +69 -0
- package/dist/cjs/client.js +12 -15
- package/dist/cjs/createIcon.js +374 -252
- package/dist/cjs/design-tokens.js +324 -390
- package/dist/cjs/figmaExport.js +162 -257
- package/dist/cjs/figmaSync.js +234 -316
- package/dist/cjs/headless-ui.js +240 -368
- package/dist/cjs/iconAnalytics.js +337 -393
- package/dist/cjs/iconHtml.js +64 -86
- package/dist/cjs/iconMetadata.js +392 -472
- package/dist/cjs/iconParts.js +120 -90
- package/dist/cjs/iconStack.js +136 -155
- package/dist/cjs/iconStyles.js +1670 -509
- package/dist/cjs/iconValue.js +359 -430
- package/dist/cjs/icons/accessibility.js +1119 -134
- package/dist/cjs/icons/actions.js +1290 -330
- package/dist/cjs/icons/ai.js +1424 -144
- package/dist/cjs/icons/brand.js +613 -184
- package/dist/cjs/icons/business.js +938 -192
- package/dist/cjs/icons/devtech.js +1656 -227
- package/dist/cjs/icons/ecommerce.js +802 -111
- package/dist/cjs/icons/education.js +1345 -199
- package/dist/cjs/icons/files.js +1597 -328
- package/dist/cjs/icons/fintech.js +793 -104
- package/dist/cjs/icons/food.js +1028 -156
- package/dist/cjs/icons/fun.js +804 -109
- package/dist/cjs/icons/gaming.js +916 -170
- package/dist/cjs/icons/health.js +623 -112
- package/dist/cjs/icons/index.js +32 -42
- package/dist/cjs/icons/input.js +282 -83
- package/dist/cjs/icons/legal.js +1065 -122
- package/dist/cjs/icons/media.js +1061 -267
- package/dist/cjs/icons/navigation.js +407 -123
- package/dist/cjs/icons/omniverk.js +523 -93
- package/dist/cjs/icons/realestate.js +1520 -193
- package/dist/cjs/icons/saas.js +867 -98
- package/dist/cjs/icons/science.js +1344 -202
- package/dist/cjs/icons/shapes.js +1316 -308
- package/dist/cjs/icons/smarthome.js +786 -90
- package/dist/cjs/icons/social.js +591 -59
- package/dist/cjs/icons/sports.js +1133 -133
- package/dist/cjs/icons/sustainability.js +1211 -139
- package/dist/cjs/icons/travel.js +1470 -148
- package/dist/cjs/icons/ui.js +1508 -315
- package/dist/cjs/icons/weather.js +1160 -173
- package/dist/cjs/index.js +559 -568
- package/dist/cjs/lottieIntegration.js +261 -266
- package/dist/cjs/nicetodev-icons.css +1 -1
- package/dist/cjs/particleEffects.js +270 -251
- package/dist/cjs/resolver.js +229 -284
- package/dist/cjs/rsc.js +175 -193
- package/dist/cjs/sharpen.js +73 -130
- package/dist/cjs/smilAnimations.js +380 -165
- package/dist/cjs/stacking.js +87 -122
- package/dist/cjs/tailwind-plugin.js +280 -320
- package/dist/cjs/types.js +46 -72
- package/dist/cjs/utilities.js +163 -324
- package/dist/cjs/variantProps.js +12 -52
- package/dist/esm/NiceDesktopIconExporter.js +671 -598
- package/dist/esm/NiceFaviconGenerator.js +583 -416
- package/dist/esm/NiceIconPicker.js +789 -507
- package/dist/esm/NiceIconPreview.js +247 -187
- package/dist/esm/NiceIconSetCreator.js +685 -551
- package/dist/esm/NiceIconStacker.js +549 -170
- package/dist/esm/NiceIconValue.js +29 -34
- package/dist/esm/NtdIconBadge.js +388 -359
- package/dist/esm/NtdIconMorph.js +423 -353
- package/dist/esm/NtdStateMorph.js +152 -146
- package/dist/esm/advancedIconSearch.js +391 -509
- package/dist/esm/animationControls.js +527 -641
- package/dist/esm/animationSpeed.js +69 -0
- package/dist/esm/client.js +48 -10
- package/dist/esm/createIcon.js +375 -251
- package/dist/esm/design-tokens.js +334 -387
- package/dist/esm/figmaExport.js +170 -256
- package/dist/esm/figmaSync.js +237 -315
- package/dist/esm/headless-ui.js +254 -365
- package/dist/esm/iconAnalytics.js +342 -392
- package/dist/esm/iconHtml.js +67 -85
- package/dist/esm/iconMetadata.js +404 -471
- package/dist/esm/iconParts.js +125 -89
- package/dist/esm/iconStack.js +145 -154
- package/dist/esm/iconStyles.js +1681 -508
- package/dist/esm/iconValue.js +361 -429
- package/dist/esm/icons/accessibility.js +1133 -133
- package/dist/esm/icons/actions.js +1320 -329
- package/dist/esm/icons/ai.js +1441 -143
- package/dist/esm/icons/brand.js +616 -179
- package/dist/esm/icons/business.js +957 -191
- package/dist/esm/icons/devtech.js +1687 -226
- package/dist/esm/icons/ecommerce.js +816 -110
- package/dist/esm/icons/education.js +1364 -198
- package/dist/esm/icons/files.js +1628 -327
- package/dist/esm/icons/fintech.js +807 -103
- package/dist/esm/icons/food.js +1043 -153
- package/dist/esm/icons/fun.js +819 -108
- package/dist/esm/icons/gaming.js +933 -169
- package/dist/esm/icons/health.js +636 -111
- package/dist/esm/icons/index.js +589 -32
- package/dist/esm/icons/input.js +326 -82
- package/dist/esm/icons/legal.js +1079 -121
- package/dist/esm/icons/media.js +1086 -266
- package/dist/esm/icons/navigation.js +421 -122
- package/dist/esm/icons/omniverk.js +534 -91
- package/dist/esm/icons/realestate.js +1544 -198
- package/dist/esm/icons/saas.js +880 -97
- package/dist/esm/icons/science.js +1370 -208
- package/dist/esm/icons/shapes.js +1343 -307
- package/dist/esm/icons/smarthome.js +799 -89
- package/dist/esm/icons/social.js +599 -58
- package/dist/esm/icons/sports.js +1148 -132
- package/dist/esm/icons/sustainability.js +1226 -138
- package/dist/esm/icons/travel.js +1486 -147
- package/dist/esm/icons/ui.js +1540 -314
- package/dist/esm/icons/weather.js +1181 -172
- package/dist/esm/index.js +749 -58
- package/dist/esm/lottieIntegration.js +264 -265
- package/dist/esm/nicetodev-icons.css +1 -1
- package/dist/esm/particleEffects.js +271 -250
- package/dist/esm/resolver.js +231 -283
- package/dist/esm/rsc.js +182 -192
- package/dist/esm/sharpen.js +78 -129
- package/dist/esm/smilAnimations.js +385 -164
- package/dist/esm/stacking.js +99 -121
- package/dist/esm/tailwind-plugin.js +282 -319
- package/dist/esm/types.js +50 -71
- package/dist/esm/utilities.js +177 -321
- package/dist/esm/variantProps.js +23 -52
- package/dist/types/animationSpeed.d.ts +19 -0
- package/dist/types/createIcon.d.ts +6 -0
- package/dist/types/iconStyles.d.ts +6 -1
- package/dist/types/icons/brand.d.ts +0 -4
- package/dist/types/icons/food.d.ts +0 -3
- package/dist/types/icons/index.d.ts +3 -3
- package/dist/types/icons/omniverk.d.ts +0 -3
- package/dist/types/icons/science.d.ts +1 -1
- package/dist/types/smilAnimations.d.ts +4 -2
- package/dist/types/types.d.ts +7 -0
- package/package.json +15 -22
package/dist/esm/iconValue.js
CHANGED
|
@@ -1,470 +1,402 @@
|
|
|
1
|
-
import { parseIconHtml } from
|
|
2
|
-
import { iconDisplayName, stackChildrenOf } from
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* An icon — or a stack of icons — kept as short text (1.3.10): what NiceIconPicker stores with
|
|
6
|
-
* `valueFormat="name"` (the default) or `"json"`, as short as a database value can be and still be
|
|
7
|
-
* read by people.
|
|
8
|
-
*
|
|
9
|
-
* **The code** (`'name'`) — a plain icon is its name (`NtdFolder`); a stack nests like a function
|
|
10
|
-
* call, the parent first, each setting behind a sign of its own:
|
|
11
|
-
*
|
|
12
|
-
* ```
|
|
13
|
-
* Folder(Star@tr) a star in the folder's top-right corner
|
|
14
|
-
* Bell(Circle@tr'3') a circle with "3" in the bell's corner
|
|
15
|
-
* Folder(Star@tr%40^15,Lock@bl) two icons in the folder: 40 %, turned 15°; a lock
|
|
16
|
-
* User:o(Circle@br#2a2{count}'5'#fff) an outline user, a green circle bound to `count`
|
|
17
|
-
* ```
|
|
18
|
-
*
|
|
19
|
-
* | sign | meaning | example |
|
|
20
|
-
* |---|---|---|
|
|
21
|
-
* | `( , )` | what sits in the icon, side by side | `Folder(Star,Lock)` |
|
|
22
|
-
* | `:` | variant — `so` solid, `sh` sharp, `o` outline, `w` wireframe, `d` duotone, `c` cutout, `r` rounded, `m` mini, `3d`, `v` vivid | `:o` |
|
|
23
|
-
* | `@` | position in the parent — `c t b l r tl tr bl br`, `h…` halfway (`ht`, `hbr`…); the parent's own spot when absent | `@tr` |
|
|
24
|
-
* | `%` | size, percent of the parent | `%40` |
|
|
25
|
-
* | `^` | turn, degrees clockwise | `^-30` |
|
|
26
|
-
* | `~` | nudge right / down, percent of the parent | `~5/-3` |
|
|
27
|
-
* | `#` | colours: primary, secondary, accent (`##0f0` — secondary only) | `#2a2` |
|
|
28
|
-
* | `'…'` | text; `#` and `%` after it are the text's colour and size | `'3'#fff%60` |
|
|
29
|
-
* | `{…}` | the value the text is bound to (the text after it is a sample) | `{count}'5'` |
|
|
30
|
-
*
|
|
31
|
-
* Names drop `Ntd` inside a stack. A name or colour holding any of the signs goes in backticks
|
|
32
|
-
* (`` `fa:home` ``); `\` escapes inside quotes.
|
|
33
|
-
*
|
|
34
|
-
* **JSON** (`'json'`) — the same tree as JsonML: `["Folder",["Star",{"a":"tr"}]]`, a node being
|
|
35
|
-
* `[name, {settings}?, ...nodes, "text"?]` with the settings `v a s r x y p sc ac b tc ts` written
|
|
36
|
-
* as in the code; a plain icon is its name as a JSON string.
|
|
37
|
-
*/
|
|
1
|
+
import { parseIconHtml } from "./iconHtml.js";
|
|
2
|
+
import { iconDisplayName, stackChildrenOf } from "./iconStack.js";
|
|
38
3
|
const VARIANT_CODE = {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
4
|
+
solid: "so",
|
|
5
|
+
sharp: "sh",
|
|
6
|
+
outline: "o",
|
|
7
|
+
wireframe: "w",
|
|
8
|
+
duotone: "d",
|
|
9
|
+
cutout: "c",
|
|
10
|
+
rounded: "r",
|
|
11
|
+
mini: "m",
|
|
12
|
+
"3d": "3d",
|
|
13
|
+
vivid: "v"
|
|
49
14
|
};
|
|
50
15
|
const ALIGN_CODE = {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
16
|
+
center: "c",
|
|
17
|
+
top: "t",
|
|
18
|
+
bottom: "b",
|
|
19
|
+
left: "l",
|
|
20
|
+
right: "r",
|
|
21
|
+
"top-left": "tl",
|
|
22
|
+
"top-right": "tr",
|
|
23
|
+
"bottom-left": "bl",
|
|
24
|
+
"bottom-right": "br",
|
|
25
|
+
"half-top": "ht",
|
|
26
|
+
"half-bottom": "hb",
|
|
27
|
+
"half-left": "hl",
|
|
28
|
+
"half-right": "hr",
|
|
29
|
+
"half-top-left": "htl",
|
|
30
|
+
"half-top-right": "htr",
|
|
31
|
+
"half-bottom-left": "hbl",
|
|
32
|
+
"half-bottom-right": "hbr"
|
|
68
33
|
};
|
|
69
|
-
/** A code or a full name → the value; an unknown one (a newer writer's) reads as unset. */
|
|
70
34
|
function reverse(codes) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
35
|
+
const map = /* @__PURE__ */ new Map();
|
|
36
|
+
for (const [full, code] of Object.entries(codes)) {
|
|
37
|
+
map.set(code, full);
|
|
38
|
+
map.set(full, full);
|
|
39
|
+
}
|
|
40
|
+
return map;
|
|
77
41
|
}
|
|
78
42
|
const VARIANTS = reverse(VARIANT_CODE);
|
|
79
|
-
const ALIGNS = reverse({ ...ALIGN_CODE, perfect:
|
|
80
|
-
|
|
81
|
-
const SIGNS = new Set(['(', ')', ',', ':', '@', '%', '^', '~', '#', "'", '{', '}', '`', '\\']);
|
|
82
|
-
/** A plain icon: one layer and nothing set on it but its name. */
|
|
43
|
+
const ALIGNS = reverse({ ...ALIGN_CODE, perfect: "p" });
|
|
44
|
+
const SIGNS = /* @__PURE__ */ new Set(["(", ")", ",", ":", "@", "%", "^", "~", "#", "'", "{", "}", "`", "\\"]);
|
|
83
45
|
function isPlain(layers) {
|
|
84
|
-
|
|
85
|
-
|
|
46
|
+
return layers.length === 1 && Object.entries(layers[0]).every(
|
|
47
|
+
([key, value]) => key === "id" || key === "icon" || value === void 0
|
|
48
|
+
);
|
|
86
49
|
}
|
|
87
50
|
function quote(text, mark) {
|
|
88
|
-
|
|
51
|
+
return mark + text.replace(/[\\`']/g, (c) => c === mark || c === "\\" ? `\\${c}` : c) + mark;
|
|
89
52
|
}
|
|
90
53
|
function writeName(name) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
[...name].some((c) => SIGNS.has(c)) ||
|
|
94
|
-
/^["[<]/.test(name);
|
|
95
|
-
return needsQuotes ? quote(name, '`') : name;
|
|
54
|
+
const needsQuotes = name === "" || name !== name.trim() || [...name].some((c) => SIGNS.has(c)) || /^["[<]/.test(name);
|
|
55
|
+
return needsQuotes ? quote(name, "`") : name;
|
|
96
56
|
}
|
|
97
57
|
function writeNumber(n) {
|
|
98
|
-
|
|
58
|
+
return String(Math.round(n * 1e3) / 1e3);
|
|
99
59
|
}
|
|
100
|
-
/** `#22aa22` → `2a2`, any other hex as is; another colour (`var(--x)`) in backticks. */
|
|
101
60
|
function writeColor(color) {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
61
|
+
if (!color) {
|
|
62
|
+
return "";
|
|
63
|
+
}
|
|
64
|
+
const hex = /^#([0-9a-f]{3,8})$/i.exec(color);
|
|
65
|
+
if (!hex) {
|
|
66
|
+
return quote(color, "`");
|
|
67
|
+
}
|
|
68
|
+
const h = hex[1].toLowerCase();
|
|
69
|
+
return h.length === 6 && h[0] === h[1] && h[2] === h[3] && h[4] === h[5] ? h[0] + h[2] + h[4] : h;
|
|
111
70
|
}
|
|
112
71
|
function writeCode(layers, shortName) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
};
|
|
158
|
-
return write(layers[0], true);
|
|
72
|
+
const write = (layer, isBase) => {
|
|
73
|
+
let out = writeName(shortName(layer.icon));
|
|
74
|
+
if (layer.variant) {
|
|
75
|
+
out += `:${VARIANT_CODE[layer.variant] ?? layer.variant}`;
|
|
76
|
+
}
|
|
77
|
+
if (!isBase) {
|
|
78
|
+
if (layer.align && layer.align !== "perfect") {
|
|
79
|
+
out += `@${ALIGN_CODE[layer.align] ?? layer.align}`;
|
|
80
|
+
}
|
|
81
|
+
if (layer.size !== void 0) {
|
|
82
|
+
out += `%${writeNumber(layer.size * 100)}`;
|
|
83
|
+
}
|
|
84
|
+
if (layer.rotation !== void 0) {
|
|
85
|
+
out += `^${writeNumber(layer.rotation)}`;
|
|
86
|
+
}
|
|
87
|
+
if (layer.offsetX || layer.offsetY) {
|
|
88
|
+
out += `~${writeNumber(layer.offsetX ?? 0)}`;
|
|
89
|
+
if (layer.offsetY) {
|
|
90
|
+
out += `/${writeNumber(layer.offsetY)}`;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const colors = [layer.primaryColor, layer.secondaryColor, layer.accentColor];
|
|
95
|
+
const lastColor = colors.reduce((last, c, i) => c ? i : last, -1);
|
|
96
|
+
for (let i = 0; i <= lastColor; i++) {
|
|
97
|
+
out += `#${writeColor(colors[i])}`;
|
|
98
|
+
}
|
|
99
|
+
const bound = !!layer.textBinding && /^[A-Za-z_$][\w$]*$/.test(layer.textBinding);
|
|
100
|
+
if (bound) {
|
|
101
|
+
out += `{${layer.textBinding}}`;
|
|
102
|
+
}
|
|
103
|
+
if (layer.text || !bound && (layer.textColor || layer.textSize !== void 0)) {
|
|
104
|
+
out += quote(layer.text ?? "", "'");
|
|
105
|
+
}
|
|
106
|
+
if (layer.textColor) {
|
|
107
|
+
out += `#${writeColor(layer.textColor)}`;
|
|
108
|
+
}
|
|
109
|
+
if (layer.textSize !== void 0) {
|
|
110
|
+
out += `%${writeNumber(layer.textSize)}`;
|
|
111
|
+
}
|
|
112
|
+
const inner = stackChildrenOf(layers, layer.id);
|
|
113
|
+
return inner.length > 0 ? `${out}(${inner.map((l) => write(l, false)).join(",")})` : out;
|
|
114
|
+
};
|
|
115
|
+
return write(layers[0], true);
|
|
159
116
|
}
|
|
160
117
|
function writeJson(layers, shortName) {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}
|
|
168
|
-
};
|
|
169
|
-
set('v', layer.variant && ((_a = VARIANT_CODE[layer.variant]) !== null && _a !== void 0 ? _a : layer.variant));
|
|
170
|
-
if (!isBase) {
|
|
171
|
-
if (layer.align && layer.align !== 'perfect') {
|
|
172
|
-
set('a', (_b = ALIGN_CODE[layer.align]) !== null && _b !== void 0 ? _b : layer.align);
|
|
173
|
-
}
|
|
174
|
-
if (layer.size !== undefined) {
|
|
175
|
-
s.s = Math.round(layer.size * 100000) / 1000;
|
|
176
|
-
}
|
|
177
|
-
if (layer.rotation !== undefined) {
|
|
178
|
-
s.r = layer.rotation;
|
|
179
|
-
}
|
|
180
|
-
set('x', layer.offsetX);
|
|
181
|
-
set('y', layer.offsetY);
|
|
182
|
-
}
|
|
183
|
-
set('p', layer.primaryColor);
|
|
184
|
-
set('sc', layer.secondaryColor);
|
|
185
|
-
set('ac', layer.accentColor);
|
|
186
|
-
set('b', layer.textBinding);
|
|
187
|
-
set('tc', layer.textColor);
|
|
188
|
-
if (layer.textSize !== undefined) {
|
|
189
|
-
s.ts = layer.textSize;
|
|
190
|
-
}
|
|
191
|
-
const node = [shortName(layer.icon)];
|
|
192
|
-
if (Object.keys(s).length > 0) {
|
|
193
|
-
node.push(s);
|
|
194
|
-
}
|
|
195
|
-
for (const child of stackChildrenOf(layers, layer.id)) {
|
|
196
|
-
node.push(write(child, false));
|
|
197
|
-
}
|
|
198
|
-
if (layer.text) {
|
|
199
|
-
node.push(layer.text);
|
|
200
|
-
}
|
|
201
|
-
return node;
|
|
118
|
+
const write = (layer, isBase) => {
|
|
119
|
+
const s = {};
|
|
120
|
+
const set = (key, value) => {
|
|
121
|
+
if (value !== void 0 && value !== "" && value !== 0) {
|
|
122
|
+
s[key] = value;
|
|
123
|
+
}
|
|
202
124
|
};
|
|
203
|
-
|
|
125
|
+
set("v", layer.variant && (VARIANT_CODE[layer.variant] ?? layer.variant));
|
|
126
|
+
if (!isBase) {
|
|
127
|
+
if (layer.align && layer.align !== "perfect") {
|
|
128
|
+
set("a", ALIGN_CODE[layer.align] ?? layer.align);
|
|
129
|
+
}
|
|
130
|
+
if (layer.size !== void 0) {
|
|
131
|
+
s.s = Math.round(layer.size * 1e5) / 1e3;
|
|
132
|
+
}
|
|
133
|
+
if (layer.rotation !== void 0) {
|
|
134
|
+
s.r = layer.rotation;
|
|
135
|
+
}
|
|
136
|
+
set("x", layer.offsetX);
|
|
137
|
+
set("y", layer.offsetY);
|
|
138
|
+
}
|
|
139
|
+
set("p", layer.primaryColor);
|
|
140
|
+
set("sc", layer.secondaryColor);
|
|
141
|
+
set("ac", layer.accentColor);
|
|
142
|
+
set("b", layer.textBinding);
|
|
143
|
+
set("tc", layer.textColor);
|
|
144
|
+
if (layer.textSize !== void 0) {
|
|
145
|
+
s.ts = layer.textSize;
|
|
146
|
+
}
|
|
147
|
+
const node = [shortName(layer.icon)];
|
|
148
|
+
if (Object.keys(s).length > 0) {
|
|
149
|
+
node.push(s);
|
|
150
|
+
}
|
|
151
|
+
for (const child of stackChildrenOf(layers, layer.id)) {
|
|
152
|
+
node.push(write(child, false));
|
|
153
|
+
}
|
|
154
|
+
if (layer.text) {
|
|
155
|
+
node.push(layer.text);
|
|
156
|
+
}
|
|
157
|
+
return node;
|
|
158
|
+
};
|
|
159
|
+
return write(layers[0], true);
|
|
204
160
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
}
|
|
214
|
-
if (isPlain(layers)) {
|
|
215
|
-
return format === 'json' ? JSON.stringify(layers[0].icon) : layers[0].icon;
|
|
216
|
-
}
|
|
217
|
-
return format === 'json'
|
|
218
|
-
? JSON.stringify(writeJson(layers, shortName))
|
|
219
|
-
: writeCode(layers, shortName);
|
|
161
|
+
function formatIconValue(layers, format = "name", { shortName = iconDisplayName } = {}) {
|
|
162
|
+
if (layers.length === 0) {
|
|
163
|
+
return "";
|
|
164
|
+
}
|
|
165
|
+
if (isPlain(layers)) {
|
|
166
|
+
return format === "json" ? JSON.stringify(layers[0].icon) : layers[0].icon;
|
|
167
|
+
}
|
|
168
|
+
return format === "json" ? JSON.stringify(writeJson(layers, shortName)) : writeCode(layers, shortName);
|
|
220
169
|
}
|
|
221
|
-
/* ─── Reading ─── */
|
|
222
170
|
class IconValueError extends Error {
|
|
223
171
|
}
|
|
224
|
-
/** Collects the layers in document order, ids `'1'`, `'2'`…; what sits in the base has no parent. */
|
|
225
172
|
class LayerSink {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
}
|
|
243
|
-
const id = String(this.layers.length + 1);
|
|
244
|
-
const clean = Object.fromEntries(Object.entries(data).filter(([, v]) => v !== undefined && v !== ''));
|
|
245
|
-
this.layers.push({ id, ...clean, ...(parent && parent !== '1' ? { parent } : {}) });
|
|
246
|
-
return id;
|
|
173
|
+
constructor() {
|
|
174
|
+
this.layers = [];
|
|
175
|
+
}
|
|
176
|
+
add(layer, parent, isBase) {
|
|
177
|
+
const data = isBase ? (
|
|
178
|
+
// where a layer sits means nothing for the base
|
|
179
|
+
{ ...layer, align: void 0, size: void 0, rotation: void 0 }
|
|
180
|
+
) : layer;
|
|
181
|
+
if (isBase || !data.offsetX) {
|
|
182
|
+
data.offsetX = void 0;
|
|
183
|
+
}
|
|
184
|
+
if (isBase || !data.offsetY) {
|
|
185
|
+
data.offsetY = void 0;
|
|
186
|
+
}
|
|
187
|
+
if (data.align === "perfect") {
|
|
188
|
+
data.align = void 0;
|
|
247
189
|
}
|
|
190
|
+
const id = String(this.layers.length + 1);
|
|
191
|
+
const clean = Object.fromEntries(
|
|
192
|
+
Object.entries(data).filter(([, v]) => v !== void 0 && v !== "")
|
|
193
|
+
);
|
|
194
|
+
this.layers.push({ id, ...clean, ...parent && parent !== "1" ? { parent } : {} });
|
|
195
|
+
return id;
|
|
196
|
+
}
|
|
248
197
|
}
|
|
249
198
|
function readCode(code) {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
199
|
+
const sink = new LayerSink();
|
|
200
|
+
let i = 0;
|
|
201
|
+
const peek = () => code[i];
|
|
202
|
+
const skipSpaces = () => {
|
|
203
|
+
while (i < code.length && /\s/.test(code[i])) {
|
|
204
|
+
i++;
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
const quoted = (mark) => {
|
|
208
|
+
i++;
|
|
209
|
+
let out = "";
|
|
210
|
+
while (i < code.length && code[i] !== mark) {
|
|
211
|
+
if (code[i] === "\\" && i + 1 < code.length) {
|
|
259
212
|
i++;
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
213
|
+
}
|
|
214
|
+
out += code[i];
|
|
215
|
+
i++;
|
|
216
|
+
}
|
|
217
|
+
if (code[i] !== mark) {
|
|
218
|
+
throw new IconValueError("unclosed quote");
|
|
219
|
+
}
|
|
220
|
+
i++;
|
|
221
|
+
return out;
|
|
222
|
+
};
|
|
223
|
+
const name = () => {
|
|
224
|
+
skipSpaces();
|
|
225
|
+
if (peek() === "`") {
|
|
226
|
+
return quoted("`");
|
|
227
|
+
}
|
|
228
|
+
const start = i;
|
|
229
|
+
while (i < code.length && !SIGNS.has(code[i])) {
|
|
230
|
+
i++;
|
|
231
|
+
}
|
|
232
|
+
const out = code.slice(start, i).trim();
|
|
233
|
+
if (!out) {
|
|
234
|
+
throw new IconValueError("name expected");
|
|
235
|
+
}
|
|
236
|
+
return out;
|
|
237
|
+
};
|
|
238
|
+
const word = () => {
|
|
239
|
+
const hit = /^[A-Za-z0-9-]*/.exec(code.slice(i))?.[0] ?? "";
|
|
240
|
+
i += hit.length;
|
|
241
|
+
return hit;
|
|
242
|
+
};
|
|
243
|
+
const number = () => {
|
|
244
|
+
const hit = /^-?(?:\d+(?:\.\d*)?|\.\d+)/.exec(code.slice(i))?.[0];
|
|
245
|
+
if (!hit) {
|
|
246
|
+
throw new IconValueError("number expected");
|
|
247
|
+
}
|
|
248
|
+
i += hit.length;
|
|
249
|
+
return Number(hit);
|
|
250
|
+
};
|
|
251
|
+
const color = () => {
|
|
252
|
+
if (peek() === "`") {
|
|
253
|
+
return quoted("`");
|
|
254
|
+
}
|
|
255
|
+
const hit = /^[0-9a-fA-F]{0,8}/.exec(code.slice(i))?.[0] ?? "";
|
|
256
|
+
i += hit.length;
|
|
257
|
+
return hit ? `#${hit.toLowerCase()}` : void 0;
|
|
258
|
+
};
|
|
259
|
+
const node = (parent, isBase) => {
|
|
260
|
+
const layer = { icon: name() };
|
|
261
|
+
const colors = [];
|
|
262
|
+
let settings = true;
|
|
263
|
+
while (settings) {
|
|
264
|
+
const sign = peek();
|
|
265
|
+
if (sign === ":" || sign === "@" || sign === "%" || sign === "^" || sign === "~" || sign === "#") {
|
|
271
266
|
i++;
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
};
|
|
313
|
-
const node = (parent, isBase) => {
|
|
314
|
-
const layer = { icon: name() };
|
|
315
|
-
const colors = [];
|
|
316
|
-
let settings = true;
|
|
317
|
-
while (settings) {
|
|
318
|
-
const sign = peek();
|
|
319
|
-
if (sign === ':' ||
|
|
320
|
-
sign === '@' ||
|
|
321
|
-
sign === '%' ||
|
|
322
|
-
sign === '^' ||
|
|
323
|
-
sign === '~' ||
|
|
324
|
-
sign === '#') {
|
|
325
|
-
i++;
|
|
326
|
-
}
|
|
327
|
-
if (sign === ':') {
|
|
328
|
-
layer.variant = VARIANTS.get(word());
|
|
329
|
-
}
|
|
330
|
-
else if (sign === '@') {
|
|
331
|
-
layer.align = ALIGNS.get(word());
|
|
332
|
-
}
|
|
333
|
-
else if (sign === '%') {
|
|
334
|
-
layer.size = Math.round(number() * 1000) / 100000;
|
|
335
|
-
}
|
|
336
|
-
else if (sign === '^') {
|
|
337
|
-
layer.rotation = number();
|
|
338
|
-
}
|
|
339
|
-
else if (sign === '~') {
|
|
340
|
-
layer.offsetX = number();
|
|
341
|
-
if (peek() === '/') {
|
|
342
|
-
i++;
|
|
343
|
-
layer.offsetY = number();
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
else if (sign === '#') {
|
|
347
|
-
colors.push(color());
|
|
348
|
-
}
|
|
349
|
-
else {
|
|
350
|
-
settings = false;
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
[layer.primaryColor, layer.secondaryColor, layer.accentColor] = colors;
|
|
354
|
-
if (peek() === '{') {
|
|
355
|
-
const end = code.indexOf('}', i);
|
|
356
|
-
if (end < 0) {
|
|
357
|
-
throw new IconValueError('unclosed binding');
|
|
358
|
-
}
|
|
359
|
-
layer.textBinding = code.slice(i + 1, end).trim();
|
|
360
|
-
i = end + 1;
|
|
361
|
-
}
|
|
362
|
-
if (peek() === "'") {
|
|
363
|
-
layer.text = quoted("'");
|
|
364
|
-
}
|
|
365
|
-
if (layer.text !== undefined || layer.textBinding) {
|
|
366
|
-
for (let sign = peek(); sign === '#' || sign === '%'; sign = peek()) {
|
|
367
|
-
i++;
|
|
368
|
-
if (sign === '#') {
|
|
369
|
-
layer.textColor = color();
|
|
370
|
-
}
|
|
371
|
-
else {
|
|
372
|
-
layer.textSize = number();
|
|
373
|
-
}
|
|
374
|
-
}
|
|
267
|
+
}
|
|
268
|
+
if (sign === ":") {
|
|
269
|
+
layer.variant = VARIANTS.get(word());
|
|
270
|
+
} else if (sign === "@") {
|
|
271
|
+
layer.align = ALIGNS.get(word());
|
|
272
|
+
} else if (sign === "%") {
|
|
273
|
+
layer.size = Math.round(number() * 1e3) / 1e5;
|
|
274
|
+
} else if (sign === "^") {
|
|
275
|
+
layer.rotation = number();
|
|
276
|
+
} else if (sign === "~") {
|
|
277
|
+
layer.offsetX = number();
|
|
278
|
+
if (peek() === "/") {
|
|
279
|
+
i++;
|
|
280
|
+
layer.offsetY = number();
|
|
281
|
+
}
|
|
282
|
+
} else if (sign === "#") {
|
|
283
|
+
colors.push(color());
|
|
284
|
+
} else {
|
|
285
|
+
settings = false;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
[layer.primaryColor, layer.secondaryColor, layer.accentColor] = colors;
|
|
289
|
+
if (peek() === "{") {
|
|
290
|
+
const end = code.indexOf("}", i);
|
|
291
|
+
if (end < 0) {
|
|
292
|
+
throw new IconValueError("unclosed binding");
|
|
293
|
+
}
|
|
294
|
+
layer.textBinding = code.slice(i + 1, end).trim();
|
|
295
|
+
i = end + 1;
|
|
296
|
+
}
|
|
297
|
+
if (peek() === "'") {
|
|
298
|
+
layer.text = quoted("'");
|
|
299
|
+
}
|
|
300
|
+
if (layer.text !== void 0 || layer.textBinding) {
|
|
301
|
+
for (let sign = peek(); sign === "#" || sign === "%"; sign = peek()) {
|
|
302
|
+
i++;
|
|
303
|
+
if (sign === "#") {
|
|
304
|
+
layer.textColor = color();
|
|
305
|
+
} else {
|
|
306
|
+
layer.textSize = number();
|
|
375
307
|
}
|
|
376
|
-
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
const id = sink.add(layer, parent, isBase);
|
|
311
|
+
skipSpaces();
|
|
312
|
+
if (peek() === "(") {
|
|
313
|
+
i++;
|
|
314
|
+
let more = true;
|
|
315
|
+
while (more) {
|
|
316
|
+
node(id, false);
|
|
377
317
|
skipSpaces();
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
}
|
|
389
|
-
if (peek() !== ')') {
|
|
390
|
-
throw new IconValueError(') expected');
|
|
391
|
-
}
|
|
392
|
-
i++;
|
|
393
|
-
skipSpaces();
|
|
394
|
-
}
|
|
395
|
-
};
|
|
396
|
-
node(undefined, true);
|
|
397
|
-
if (i < code.length) {
|
|
398
|
-
throw new IconValueError('unexpected text');
|
|
318
|
+
more = peek() === ",";
|
|
319
|
+
if (more) {
|
|
320
|
+
i++;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
if (peek() !== ")") {
|
|
324
|
+
throw new IconValueError(") expected");
|
|
325
|
+
}
|
|
326
|
+
i++;
|
|
327
|
+
skipSpaces();
|
|
399
328
|
}
|
|
400
|
-
|
|
329
|
+
};
|
|
330
|
+
node(void 0, true);
|
|
331
|
+
if (i < code.length) {
|
|
332
|
+
throw new IconValueError("unexpected text");
|
|
333
|
+
}
|
|
334
|
+
return sink.layers;
|
|
401
335
|
}
|
|
402
336
|
function readJson(json) {
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
337
|
+
const parsed = JSON.parse(json);
|
|
338
|
+
if (typeof parsed === "string") {
|
|
339
|
+
return parsed.trim() ? [{ id: "1", icon: parsed }] : null;
|
|
340
|
+
}
|
|
341
|
+
const sink = new LayerSink();
|
|
342
|
+
const str = (v) => typeof v === "string" ? v : void 0;
|
|
343
|
+
const num = (v) => typeof v === "number" && Number.isFinite(v) ? v : void 0;
|
|
344
|
+
const node = (value, parent, isBase) => {
|
|
345
|
+
if (!Array.isArray(value) || typeof value[0] !== "string" || !value[0]) {
|
|
346
|
+
throw new IconValueError("node expected");
|
|
347
|
+
}
|
|
348
|
+
const [icon, ...rest] = value;
|
|
349
|
+
const first = rest[0];
|
|
350
|
+
const s = first && typeof first === "object" && !Array.isArray(first) ? rest.shift() : {};
|
|
351
|
+
const text = rest.filter((v) => typeof v === "string").join("");
|
|
352
|
+
const size = num(s.s);
|
|
353
|
+
const id = sink.add(
|
|
354
|
+
{
|
|
355
|
+
icon,
|
|
356
|
+
variant: VARIANTS.get(str(s.v) ?? ""),
|
|
357
|
+
align: ALIGNS.get(str(s.a) ?? ""),
|
|
358
|
+
size: size === void 0 ? void 0 : Math.round(size * 1e3) / 1e5,
|
|
359
|
+
rotation: num(s.r),
|
|
360
|
+
offsetX: num(s.x),
|
|
361
|
+
offsetY: num(s.y),
|
|
362
|
+
primaryColor: str(s.p),
|
|
363
|
+
secondaryColor: str(s.sc),
|
|
364
|
+
accentColor: str(s.ac),
|
|
365
|
+
text: text || void 0,
|
|
366
|
+
textBinding: str(s.b),
|
|
367
|
+
textColor: str(s.tc),
|
|
368
|
+
textSize: num(s.ts)
|
|
369
|
+
},
|
|
370
|
+
parent,
|
|
371
|
+
isBase
|
|
372
|
+
);
|
|
373
|
+
for (const child of rest) {
|
|
374
|
+
if (Array.isArray(child)) {
|
|
375
|
+
node(child, id, false);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
node(parsed, void 0, true);
|
|
380
|
+
return sink.layers;
|
|
444
381
|
}
|
|
445
|
-
/**
|
|
446
|
-
* Reads an icon kept as text (1.3.10) — a name, the code (`Folder(Star@tr)`), JSON or the HTML of
|
|
447
|
-
* NiceIconPicker 1.3.9 — into stack layers (ids `'1'`, `'2'`… in document order). `null` for empty
|
|
448
|
-
* or unreadable text. Names stay as written: `renderIconStack` resolves `Star` to `NtdStar`.
|
|
449
|
-
*/
|
|
450
382
|
function parseIconValue(value) {
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
return (_b = (_a = parseIconHtml(text)) === null || _a === void 0 ? void 0 : _a.layers) !== null && _b !== void 0 ? _b : null;
|
|
459
|
-
}
|
|
460
|
-
if (text.startsWith('[') || text.startsWith('"')) {
|
|
461
|
-
return readJson(text);
|
|
462
|
-
}
|
|
463
|
-
return readCode(text);
|
|
383
|
+
const text = value?.trim();
|
|
384
|
+
if (!text) {
|
|
385
|
+
return null;
|
|
386
|
+
}
|
|
387
|
+
try {
|
|
388
|
+
if (text.startsWith("<")) {
|
|
389
|
+
return parseIconHtml(text)?.layers ?? null;
|
|
464
390
|
}
|
|
465
|
-
|
|
466
|
-
|
|
391
|
+
if (text.startsWith("[") || text.startsWith('"')) {
|
|
392
|
+
return readJson(text);
|
|
467
393
|
}
|
|
394
|
+
return readCode(text);
|
|
395
|
+
} catch {
|
|
396
|
+
return null;
|
|
397
|
+
}
|
|
468
398
|
}
|
|
469
|
-
|
|
470
|
-
|
|
399
|
+
export {
|
|
400
|
+
formatIconValue,
|
|
401
|
+
parseIconValue
|
|
402
|
+
};
|