@driftime/sanity-plugin-icon 0.3.0 → 0.4.1
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/README.md +253 -61
- package/dist/adapters-Bx_MyEX_.js +633 -0
- package/dist/adapters-Bx_MyEX_.js.map +1 -0
- package/dist/drawing-ByrcBbWB.js +50 -0
- package/dist/drawing-ByrcBbWB.js.map +1 -0
- package/dist/index.d.ts +84 -32
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +545 -323
- package/dist/index.js.map +1 -1
- package/dist/names.d.ts +8 -0
- package/dist/names.d.ts.map +1 -0
- package/dist/names.js +0 -0
- package/dist/next-loader.d.ts +64 -0
- package/dist/next-loader.d.ts.map +1 -0
- package/dist/next-loader.js +103 -0
- package/dist/next-loader.js.map +1 -0
- package/dist/next.d.ts +43 -0
- package/dist/next.d.ts.map +1 -0
- package/dist/next.js +52 -0
- package/dist/next.js.map +1 -0
- package/dist/nodes-DAzj56Xn.js +139 -0
- package/dist/nodes-DAzj56Xn.js.map +1 -0
- package/dist/read-worker.d.ts +1 -0
- package/dist/read-worker.js +23 -0
- package/dist/read-worker.js.map +1 -0
- package/dist/registry-B0Dxiwhh.js +68 -0
- package/dist/registry-B0Dxiwhh.js.map +1 -0
- package/dist/registry-BEEpqK3z.js +13 -0
- package/dist/registry-BEEpqK3z.js.map +1 -0
- package/dist/render.d.ts +4 -5
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +5 -5
- package/dist/render.js.map +1 -1
- package/dist/sets-D5_YGFll.js +258 -0
- package/dist/sets-D5_YGFll.js.map +1 -0
- package/dist/sets-kepuObH8.js +90 -0
- package/dist/sets-kepuObH8.js.map +1 -0
- package/dist/sets.d.ts +50 -0
- package/dist/sets.d.ts.map +1 -0
- package/dist/sets.js +14 -0
- package/dist/sets.js.map +1 -0
- package/dist/types-qlHEYDoN.d.ts +20 -0
- package/dist/types-qlHEYDoN.d.ts.map +1 -0
- package/dist/utils-COPacfAq.js +48 -0
- package/dist/utils-COPacfAq.js.map +1 -0
- package/dist/vite-ifICG8y9.d.ts +98 -0
- package/dist/vite-ifICG8y9.d.ts.map +1 -0
- package/dist/vite.d.ts +2 -0
- package/dist/vite.js +88 -0
- package/dist/vite.js.map +1 -0
- package/package.json +42 -5
- package/dist/drawing-BThiR2bN.js +0 -129
- package/dist/drawing-BThiR2bN.js.map +0 -1
- package/dist/types-_D2jGm25.d.ts +0 -16
- package/dist/types-_D2jGm25.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,37 +1,42 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { r as pluginName, t as parseIconSet } from "./sets-kepuObH8.js";
|
|
2
|
+
import { n as isDefined, t as convertCase } from "./utils-COPacfAq.js";
|
|
3
|
+
import { a as resolveIconDrawing, o as serializeIconDrawing } from "./nodes-DAzj56Xn.js";
|
|
4
|
+
import { t as Drawing } from "./drawing-ByrcBbWB.js";
|
|
5
|
+
import { t as getIconSetKey } from "./registry-BEEpqK3z.js";
|
|
2
6
|
import { ChangeIndicator, FieldActionsProvider, FieldActionsResolver, FormField, defineField, definePlugin, defineType, getPublishedId, set, setIfMissing, unset, useFormValue } from "sanity";
|
|
3
7
|
import { c } from "react/compiler-runtime";
|
|
4
8
|
import { createElement, useEffect, useRef, useState } from "react";
|
|
5
9
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
10
|
import { CloseIcon } from "@sanity/icons/Close";
|
|
7
|
-
import { Box, Button, Dialog, Flex, Grid, Spinner, Stack, Text, TextInput } from "@sanity/ui";
|
|
11
|
+
import { Box, Button, Card, Dialog, Flex, Grid, Spinner, Stack, Text, TextInput } from "@sanity/ui";
|
|
8
12
|
import { SearchIcon } from "@sanity/icons/Search";
|
|
13
|
+
import { WarningOutlineIcon } from "@sanity/icons/WarningOutline";
|
|
9
14
|
import { Popover } from "@sanity/ui/popover";
|
|
15
|
+
import { iconRegistry } from "@driftime/sanity-plugin-icon/sets";
|
|
10
16
|
/**
|
|
11
|
-
* Checks whether a form node
|
|
17
|
+
* Checks whether a form node has members, as objects and arrays of objects do.
|
|
12
18
|
*
|
|
13
19
|
* @param node - The form node to check.
|
|
14
|
-
* @returns True if the node
|
|
20
|
+
* @returns True if the node has members.
|
|
15
21
|
*/
|
|
16
22
|
function hasMembers(node) {
|
|
17
23
|
return "members" in node;
|
|
18
24
|
}
|
|
19
25
|
/**
|
|
20
|
-
*
|
|
26
|
+
* Collects the validation on a form node and everything inside it.
|
|
21
27
|
*
|
|
22
|
-
* @param node - The form node
|
|
23
|
-
* @returns Every validation
|
|
28
|
+
* @param node - The form node.
|
|
29
|
+
* @returns Every validation result on the node or inside it.
|
|
24
30
|
*/
|
|
25
31
|
function collectNodeValidation(node) {
|
|
26
32
|
return [...node.validation, ...hasMembers(node) ? collectMemberValidation(node.members) : []];
|
|
27
33
|
}
|
|
28
34
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* hides them showing nothing they report.
|
|
35
|
+
* Collects the validation anywhere inside a field's members. The form only passes a field the
|
|
36
|
+
* validation at its own path, so a field that hides its members would otherwise show none of theirs.
|
|
32
37
|
*
|
|
33
|
-
* @param members - The members
|
|
34
|
-
* @returns Every validation
|
|
38
|
+
* @param members - The members.
|
|
39
|
+
* @returns Every validation result on the members or inside them.
|
|
35
40
|
*/
|
|
36
41
|
function collectMemberValidation(members) {
|
|
37
42
|
return members.flatMap((member) => member.kind === "field" ? collectNodeValidation(member.field) : member.kind === "fieldSet" ? collectMemberValidation(member.fieldSet.members) : member.kind === "item" ? collectNodeValidation(member.item) : []);
|
|
@@ -86,21 +91,18 @@ function Field(t0) {
|
|
|
86
91
|
let t7;
|
|
87
92
|
return $[37] !== t3 || $[38] !== t6 ? (t7 = /* @__PURE__ */ jsxs(Fragment, { children: [t3, t6] }), $[37] = t3, $[38] = t6, $[39] = t7) : t7 = $[39], t7;
|
|
88
93
|
}
|
|
89
|
-
/**
|
|
90
|
-
* Properties the plugin's own icons are drawn with. Icons taken from `@sanity/icons` are left alone,
|
|
91
|
-
* since they already carry the sizing and stroke the rest of the Studio uses.
|
|
92
|
-
*/
|
|
94
|
+
/** Default props for the plugin's own icons. Icons from `@sanity/icons` already match the Studio. */
|
|
93
95
|
const defaultIconProps = {
|
|
94
96
|
width: "1em",
|
|
95
97
|
height: "1em",
|
|
96
98
|
strokeWidth: 1.5
|
|
97
99
|
};
|
|
98
100
|
/**
|
|
99
|
-
*
|
|
101
|
+
* Wraps an SVG icon component for use in the Studio.
|
|
100
102
|
*
|
|
101
|
-
* @param icon - The icon
|
|
102
|
-
* @param props -
|
|
103
|
-
* @returns
|
|
103
|
+
* @param icon - The icon to wrap.
|
|
104
|
+
* @param props - Props that override the Studio icon defaults.
|
|
105
|
+
* @returns An icon component.
|
|
104
106
|
*/
|
|
105
107
|
function createSanityIcon(icon, props) {
|
|
106
108
|
let Icon = icon;
|
|
@@ -112,7 +114,7 @@ function createSanityIcon(icon, props) {
|
|
|
112
114
|
}
|
|
113
115
|
return SanityIcon;
|
|
114
116
|
}
|
|
115
|
-
/**
|
|
117
|
+
/** Gap between rows in pixels. */
|
|
116
118
|
const gridLayoutStyle = {
|
|
117
119
|
justifyItems: "center",
|
|
118
120
|
rowGap: 4
|
|
@@ -126,12 +128,11 @@ function Cell(t0) {
|
|
|
126
128
|
height: 40
|
|
127
129
|
}, $[9] = t2) : t2 = $[9];
|
|
128
130
|
let t3;
|
|
129
|
-
$[10] === icon.
|
|
130
|
-
|
|
131
|
+
$[10] === icon.drawing ? t3 = $[11] : (t3 = /* @__PURE__ */ jsx(Drawing, {
|
|
132
|
+
drawing: icon.drawing,
|
|
131
133
|
width: "1.25em",
|
|
132
|
-
height: "1.25em"
|
|
133
|
-
|
|
134
|
-
}), $[10] = icon.node, $[11] = t3);
|
|
134
|
+
height: "1.25em"
|
|
135
|
+
}), $[10] = icon.drawing, $[11] = t3);
|
|
135
136
|
let t4;
|
|
136
137
|
$[12] !== icon || $[13] !== onSelect ? (t4 = () => {
|
|
137
138
|
onSelect(icon);
|
|
@@ -160,22 +161,21 @@ function Cell(t0) {
|
|
|
160
161
|
}), $[18] = icon.label, $[19] = position, $[20] = props, $[21] = selected, $[22] = t1, $[23] = t3, $[24] = t4, $[25] = t5, $[26] = total, $[27] = t6) : t6 = $[27], t6;
|
|
161
162
|
}
|
|
162
163
|
function Library(t0) {
|
|
163
|
-
let $ = c(
|
|
164
|
+
let $ = c(44), activeCell, activeIndex, icons, onClearSearch, onHover, onSelect, props, rows, search, selected;
|
|
164
165
|
$[0] === t0 ? (activeCell = $[1], activeIndex = $[2], icons = $[3], onClearSearch = $[4], onHover = $[5], onSelect = $[6], props = $[7], rows = $[8], search = $[9], selected = $[10]) : ({icons, rows, selected, activeIndex, activeCell, search, onSelect, onHover, onClearSearch, ...props} = t0, $[0] = t0, $[1] = activeCell, $[2] = activeIndex, $[3] = icons, $[4] = onClearSearch, $[5] = onHover, $[6] = onSelect, $[7] = props, $[8] = rows, $[9] = search, $[10] = selected);
|
|
165
|
-
let { totalRows, firstRow, lastRow } = rows, t1;
|
|
166
|
+
let { totalRows, firstRow, lastRow } = rows, T0, t1, t2, t3, t4, t5, t6;
|
|
166
167
|
if ($[11] !== activeCell || $[12] !== activeIndex || $[13] !== firstRow || $[14] !== icons || $[15] !== lastRow || $[16] !== onClearSearch || $[17] !== onHover || $[18] !== onSelect || $[19] !== props || $[20] !== search || $[21] !== selected || $[22] !== totalRows) {
|
|
167
|
-
let visible = icons.slice(firstRow * 8, lastRow * 8)
|
|
168
|
-
$[
|
|
168
|
+
let visible = icons.slice(firstRow * 8, lastRow * 8);
|
|
169
|
+
T0 = Box, t1 = "listbox", t2 = "Icon library", $[30] === icons ? t3 = $[31] : (t3 = isDefined(icons) ? {
|
|
169
170
|
height: 348,
|
|
170
171
|
overflowY: "auto"
|
|
171
|
-
}, $[
|
|
172
|
-
let t3;
|
|
173
|
-
$[25] !== icons.length || $[26] !== onClearSearch || $[27] !== search ? (t3 = icons.length === 0 && /* @__PURE__ */ jsxs(Flex, {
|
|
172
|
+
} : void 0, $[30] = icons, $[31] = t3), t4 = props, $[32] !== icons || $[33] !== onClearSearch || $[34] !== search ? (t5 = !isDefined(icons) && /* @__PURE__ */ jsxs(Flex, {
|
|
174
173
|
align: "center",
|
|
175
174
|
justify: "center",
|
|
176
175
|
direction: "column",
|
|
177
176
|
gap: 3,
|
|
178
|
-
|
|
177
|
+
paddingTop: 5,
|
|
178
|
+
paddingBottom: 6,
|
|
179
179
|
children: [/* @__PURE__ */ jsx(Text, {
|
|
180
180
|
size: 1,
|
|
181
181
|
muted: !0,
|
|
@@ -186,35 +186,91 @@ function Library(t0) {
|
|
|
186
186
|
text: "Clear search",
|
|
187
187
|
onClick: onClearSearch
|
|
188
188
|
})]
|
|
189
|
-
}), $[
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
189
|
+
}), $[32] = icons, $[33] = onClearSearch, $[34] = search, $[35] = t5) : t5 = $[35], t6 = isDefined(icons) && /* @__PURE__ */ jsx(Grid, {
|
|
190
|
+
gridTemplateColumns: 8,
|
|
191
|
+
style: {
|
|
192
|
+
...gridLayoutStyle,
|
|
193
|
+
paddingTop: firstRow * 44,
|
|
194
|
+
paddingBottom: (totalRows - lastRow) * 44
|
|
195
|
+
},
|
|
196
|
+
children: visible.map((icon, offset) => {
|
|
197
|
+
let index = firstRow * 8 + offset;
|
|
198
|
+
return /* @__PURE__ */ jsx(Cell, {
|
|
199
|
+
ref: index === activeIndex ? activeCell : void 0,
|
|
200
|
+
icon,
|
|
201
|
+
selected: icon.name === selected,
|
|
202
|
+
focusable: index === activeIndex,
|
|
203
|
+
position: index + 1,
|
|
204
|
+
total: icons.length,
|
|
205
|
+
onSelect,
|
|
206
|
+
onHover
|
|
207
|
+
}, icon.name);
|
|
208
|
+
})
|
|
209
|
+
}), $[11] = activeCell, $[12] = activeIndex, $[13] = firstRow, $[14] = icons, $[15] = lastRow, $[16] = onClearSearch, $[17] = onHover, $[18] = onSelect, $[19] = props, $[20] = search, $[21] = selected, $[22] = totalRows, $[23] = T0, $[24] = t1, $[25] = t2, $[26] = t3, $[27] = t4, $[28] = t5, $[29] = t6;
|
|
210
|
+
} else T0 = $[23], t1 = $[24], t2 = $[25], t3 = $[26], t4 = $[27], t5 = $[28], t6 = $[29];
|
|
211
|
+
let t7;
|
|
212
|
+
return $[36] !== T0 || $[37] !== t1 || $[38] !== t2 || $[39] !== t3 || $[40] !== t4 || $[41] !== t5 || $[42] !== t6 ? (t7 = /* @__PURE__ */ jsxs(T0, {
|
|
213
|
+
role: t1,
|
|
214
|
+
"aria-label": t2,
|
|
215
|
+
style: t3,
|
|
216
|
+
...t4,
|
|
217
|
+
children: [t5, t6]
|
|
218
|
+
}), $[36] = T0, $[37] = t1, $[38] = t2, $[39] = t3, $[40] = t4, $[41] = t5, $[42] = t6, $[43] = t7) : t7 = $[43], t7;
|
|
219
|
+
}
|
|
220
|
+
function CodeText(t0) {
|
|
221
|
+
let $ = c(10), props, text;
|
|
222
|
+
$[0] === t0 ? (props = $[1], text = $[2]) : ({text, ...props} = t0, $[0] = t0, $[1] = props, $[2] = text);
|
|
223
|
+
let t1, t2;
|
|
224
|
+
if ($[3] !== props || $[4] !== text) {
|
|
225
|
+
let parts = text.split("`");
|
|
226
|
+
t1 = props, t2 = parts.map((part, index) => {
|
|
227
|
+
let start = parts.slice(0, index).join("`").length;
|
|
228
|
+
return index % 2 == 1 ? /* @__PURE__ */ jsx("code", { children: part }, start) : part;
|
|
229
|
+
}), $[3] = props, $[4] = text, $[5] = t1, $[6] = t2;
|
|
230
|
+
} else t1 = $[5], t2 = $[6];
|
|
231
|
+
let t3;
|
|
232
|
+
return $[7] !== t1 || $[8] !== t2 ? (t3 = /* @__PURE__ */ jsx("span", {
|
|
233
|
+
...t1,
|
|
234
|
+
children: t2
|
|
235
|
+
}), $[7] = t1, $[8] = t2, $[9] = t3) : t3 = $[9], t3;
|
|
236
|
+
}
|
|
237
|
+
function Problem(t0) {
|
|
238
|
+
let $ = c(14), problem, props;
|
|
239
|
+
$[0] === t0 ? (problem = $[1], props = $[2]) : ({problem, ...props} = t0, $[0] = t0, $[1] = problem, $[2] = props);
|
|
240
|
+
let t1;
|
|
241
|
+
$[3] === Symbol.for("react.memo_cache_sentinel") ? (t1 = /* @__PURE__ */ jsx(Text, {
|
|
242
|
+
size: 1,
|
|
243
|
+
children: /* @__PURE__ */ jsx(WarningOutlineIcon, {})
|
|
244
|
+
}), $[3] = t1) : t1 = $[3];
|
|
245
|
+
let t2;
|
|
246
|
+
$[4] === problem.title ? t2 = $[5] : (t2 = /* @__PURE__ */ jsx(Text, {
|
|
247
|
+
size: 1,
|
|
248
|
+
weight: "medium",
|
|
249
|
+
children: /* @__PURE__ */ jsx(CodeText, { text: problem.title })
|
|
250
|
+
}), $[4] = problem.title, $[5] = t2);
|
|
251
|
+
let t3;
|
|
252
|
+
$[6] === problem.description ? t3 = $[7] : (t3 = /* @__PURE__ */ jsx(Text, {
|
|
253
|
+
size: 1,
|
|
254
|
+
muted: !0,
|
|
255
|
+
children: /* @__PURE__ */ jsx(CodeText, { text: problem.description })
|
|
256
|
+
}), $[6] = problem.description, $[7] = t3);
|
|
257
|
+
let t4;
|
|
258
|
+
$[8] !== t2 || $[9] !== t3 ? (t4 = /* @__PURE__ */ jsxs(Flex, {
|
|
259
|
+
gap: 3,
|
|
260
|
+
children: [t1, /* @__PURE__ */ jsxs(Stack, {
|
|
261
|
+
gap: 3,
|
|
262
|
+
children: [t2, t3]
|
|
263
|
+
})]
|
|
264
|
+
}), $[8] = t2, $[9] = t3, $[10] = t4) : t4 = $[10];
|
|
265
|
+
let t5;
|
|
266
|
+
return $[11] !== props || $[12] !== t4 ? (t5 = /* @__PURE__ */ jsx(Card, {
|
|
267
|
+
tone: "caution",
|
|
268
|
+
padding: 4,
|
|
269
|
+
radius: 2,
|
|
270
|
+
border: !0,
|
|
271
|
+
...props,
|
|
272
|
+
children: t4
|
|
273
|
+
}), $[11] = props, $[12] = t4, $[13] = t5) : t5 = $[13], t5;
|
|
218
274
|
}
|
|
219
275
|
function Recent(t0) {
|
|
220
276
|
let $ = c(26), icons, onForget, onHover, onSelect, props, selected;
|
|
@@ -238,7 +294,7 @@ function Recent(t0) {
|
|
|
238
294
|
padding: 2,
|
|
239
295
|
text: "Clear",
|
|
240
296
|
onClick: onForget,
|
|
241
|
-
"aria-label": "
|
|
297
|
+
"aria-label": "Clear recent icons"
|
|
242
298
|
})]
|
|
243
299
|
}), $[8] = onForget, $[9] = t2);
|
|
244
300
|
let t3;
|
|
@@ -270,38 +326,202 @@ function Recent(t0) {
|
|
|
270
326
|
}), $[22] = props, $[23] = t2, $[24] = t4, $[25] = t5) : t5 = $[25], t5;
|
|
271
327
|
}
|
|
272
328
|
/**
|
|
273
|
-
*
|
|
274
|
-
*
|
|
329
|
+
* Normalises text for search, so hyphenated names and multi-word keywords match the same way.
|
|
330
|
+
*
|
|
331
|
+
* @param value - The text.
|
|
332
|
+
* @returns The normalised text.
|
|
333
|
+
*/
|
|
334
|
+
function normalizeTerms(value) {
|
|
335
|
+
return value.toLowerCase().replaceAll(/[\s-]+/gu, " ").trim();
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Splits text into the parts a search matches and the parts it doesn't, matching the way search does: ignoring case,
|
|
339
|
+
* and treating spaces and hyphens alike.
|
|
340
|
+
*
|
|
341
|
+
* @param text - The text to split.
|
|
342
|
+
* @param query - The normalised search.
|
|
343
|
+
* @returns The parts in order, each with where it starts in the text and whether it matches.
|
|
344
|
+
*/
|
|
345
|
+
function splitMatches(text, query) {
|
|
346
|
+
if (!isDefined(query)) return [{
|
|
347
|
+
text,
|
|
348
|
+
start: 0,
|
|
349
|
+
match: !1
|
|
350
|
+
}];
|
|
351
|
+
let pattern = query.split(" ").map((word) => word.replaceAll(/[$()*+.?[\\\]^{|}]/gu, String.raw`\$&`)).join(String.raw`[\s-]+`), parts = text.split(RegExp(`(${pattern})`, "giu"));
|
|
352
|
+
return parts.map((part, index) => ({
|
|
353
|
+
text: part,
|
|
354
|
+
start: parts.slice(0, index).join("").length,
|
|
355
|
+
match: index % 2 == 1
|
|
356
|
+
}));
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Narrows the library to the named icons, in the order given. Unknown names are skipped, so a list keeps working
|
|
360
|
+
* across library releases.
|
|
361
|
+
*
|
|
362
|
+
* @param library - Every icon in the library.
|
|
363
|
+
* @param names - The icons to offer, or undefined for all of them.
|
|
364
|
+
* @returns The icons to offer.
|
|
365
|
+
*/
|
|
366
|
+
function selectIcons(library, names) {
|
|
367
|
+
if (!isDefined(names)) return library;
|
|
368
|
+
let byName = new Map(library.map((icon) => [icon.name, icon]));
|
|
369
|
+
return [...new Set(names)].flatMap((name) => {
|
|
370
|
+
let icon = byName.get(name);
|
|
371
|
+
return isDefined(icon) ? [icon] : [];
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Lists identifiers as inline code, separated by commas.
|
|
376
|
+
*
|
|
377
|
+
* @param identifiers - The identifiers.
|
|
378
|
+
* @returns The list.
|
|
379
|
+
*/
|
|
380
|
+
function formatList(identifiers) {
|
|
381
|
+
return identifiers.map((identifier) => `\`${identifier}\``).join(", ");
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Describes why a library the project hasn't installed can't be shown, and what to add.
|
|
385
|
+
*
|
|
386
|
+
* @param label - Readable name of the library.
|
|
387
|
+
* @param packageName - Package the library is read from, or an example of one for a family of packages.
|
|
388
|
+
* @param family - Whether the library is a family of packages, one per style.
|
|
389
|
+
* @param listed - Whether the project's `package.json` lists the package.
|
|
390
|
+
* @param sitePackage - Another package of the library the project lists, or undefined when there's none.
|
|
391
|
+
* @returns The problem.
|
|
392
|
+
*/
|
|
393
|
+
function describeMissingLibrary(label, packageName, family, listed, sitePackage) {
|
|
394
|
+
return listed ? {
|
|
395
|
+
title: `${label} isn't installed yet`,
|
|
396
|
+
description: `\`${packageName}\` is in \`package.json\` but not in \`node_modules\`. Reinstall the project's dependencies.`
|
|
397
|
+
} : isDefined(sitePackage) ? {
|
|
398
|
+
title: `${label} needs \`${packageName}\``,
|
|
399
|
+
description: `The Studio reads ${label} from \`${packageName}\`, not \`${sitePackage}\`. Add it as a dev dependency.`
|
|
400
|
+
} : {
|
|
401
|
+
title: `${label} isn't installed`,
|
|
402
|
+
description: family ? `Install a ${label} style package, such as \`${packageName}\`.` : `Install \`${packageName}\` in the project.`
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Loads one library style from the sets the build step converted.
|
|
407
|
+
*
|
|
408
|
+
* @param library - Identifier of the library, or undefined when none is set.
|
|
409
|
+
* @param style - Identifier of the style, or undefined for the library's default.
|
|
410
|
+
* @returns The icons, or why they can't be shown.
|
|
411
|
+
*/
|
|
412
|
+
async function readLibrary(library, style) {
|
|
413
|
+
if (!isDefined(library)) return { problem: {
|
|
414
|
+
title: "No icon library set",
|
|
415
|
+
description: "Set `library` in the icon plugin's configuration or in the field's options."
|
|
416
|
+
} };
|
|
417
|
+
if (!iconRegistry.ready) return { problem: {
|
|
418
|
+
title: "Icons aren't set up",
|
|
419
|
+
description: "Add `withIcons()` to the Studio's build configuration, then restart the Studio."
|
|
420
|
+
} };
|
|
421
|
+
let info = iconRegistry.libraries[library];
|
|
422
|
+
if (!isDefined(info)) return { problem: {
|
|
423
|
+
title: "Unknown icon library",
|
|
424
|
+
description: `There's no icon library called \`${library}\`. Use one of: ${formatList(Object.keys(iconRegistry.libraries))}.`
|
|
425
|
+
} };
|
|
426
|
+
let { label, packageName, packagePrefix, styles, listed, installed, sitePackage } = info;
|
|
427
|
+
if (!installed) return { problem: describeMissingLibrary(label, packageName, isDefined(packagePrefix), listed, sitePackage) };
|
|
428
|
+
let resolvedStyle = style ?? styles[0] ?? "", loader = iconRegistry.sets[getIconSetKey(library, resolvedStyle)];
|
|
429
|
+
if (!isDefined(loader)) return { problem: isDefined(packagePrefix) ? {
|
|
430
|
+
title: `${label} style \`${resolvedStyle}\` isn't installed`,
|
|
431
|
+
description: `Install \`${packagePrefix}${resolvedStyle}\` in the project.`
|
|
432
|
+
} : {
|
|
433
|
+
title: `Unknown ${label} style`,
|
|
434
|
+
description: `${label} has no \`${resolvedStyle}\` style. Use one of: ${formatList(styles)}.`
|
|
435
|
+
} };
|
|
436
|
+
let module = await loader(), set = parseIconSet(module.default);
|
|
437
|
+
return isDefined(set) ? { icons: set.icons.map(({ name, keywords, node, root }) => ({
|
|
438
|
+
name,
|
|
439
|
+
label: convertCase(name, "title"),
|
|
440
|
+
tags: keywords.join(", "),
|
|
441
|
+
drawing: {
|
|
442
|
+
root: root ?? set.root,
|
|
443
|
+
node
|
|
444
|
+
},
|
|
445
|
+
terms: normalizeTerms([name, ...keywords].join(" "))
|
|
446
|
+
})) } : { problem: {
|
|
447
|
+
title: `Couldn't load ${label}`,
|
|
448
|
+
description: "Restart the Studio and try again."
|
|
449
|
+
} };
|
|
450
|
+
}
|
|
451
|
+
/** Library requests shared by every field in the session, keyed by library and style, since the data never changes. */
|
|
452
|
+
const libraryRequests = /* @__PURE__ */ new Map();
|
|
453
|
+
/**
|
|
454
|
+
* Loads a library style, reusing a request already in progress.
|
|
455
|
+
*
|
|
456
|
+
* @param library - Identifier of the library, or undefined when none is set.
|
|
457
|
+
* @param style - Identifier of the style, or undefined for the library's default.
|
|
458
|
+
* @returns The icons, or why they can't be shown.
|
|
459
|
+
*/
|
|
460
|
+
async function requestLibrary(library, style) {
|
|
461
|
+
let key = getIconSetKey(library ?? "", style ?? ""), request = libraryRequests.get(key);
|
|
462
|
+
return isDefined(request) || (request = readLibrary(library, style), libraryRequests.set(key, request)), await request;
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Gap between the tooltip and its cell, set through margins because `@sanity/ui` offers no other way.
|
|
466
|
+
* Only the top is set, since the tooltip always appears above the cell.
|
|
275
467
|
*/
|
|
276
468
|
const tooltipMargins = [
|
|
277
469
|
-4,
|
|
278
470
|
0,
|
|
279
471
|
0,
|
|
280
472
|
0
|
|
281
|
-
]
|
|
473
|
+
], matchStyle = {
|
|
474
|
+
background: "none",
|
|
475
|
+
color: "inherit",
|
|
476
|
+
textDecorationLine: "underline",
|
|
477
|
+
textUnderlineOffset: "0.2em"
|
|
478
|
+
};
|
|
479
|
+
function Highlight(t0) {
|
|
480
|
+
let $ = c(10), props, query, text;
|
|
481
|
+
$[0] === t0 ? (props = $[1], query = $[2], text = $[3]) : ({text, query, ...props} = t0, $[0] = t0, $[1] = props, $[2] = query, $[3] = text);
|
|
482
|
+
let t1;
|
|
483
|
+
$[4] !== query || $[5] !== text ? (t1 = splitMatches(text, query).map(_temp$1), $[4] = query, $[5] = text, $[6] = t1) : t1 = $[6];
|
|
484
|
+
let t2;
|
|
485
|
+
return $[7] !== props || $[8] !== t1 ? (t2 = /* @__PURE__ */ jsx("span", {
|
|
486
|
+
...props,
|
|
487
|
+
children: t1
|
|
488
|
+
}), $[7] = props, $[8] = t1, $[9] = t2) : t2 = $[9], t2;
|
|
489
|
+
}
|
|
490
|
+
function _temp$1(part) {
|
|
491
|
+
return part.match ? /* @__PURE__ */ jsx("mark", {
|
|
492
|
+
style: matchStyle,
|
|
493
|
+
children: part.text
|
|
494
|
+
}, part.start) : part.text;
|
|
495
|
+
}
|
|
282
496
|
function Tooltip(t0) {
|
|
283
|
-
let $ = c(
|
|
284
|
-
$[0] === t0 ? (hovered = $[1], props = $[2]) : ({hovered, ...props} = t0, $[0] = t0, $[1] = hovered, $[2] = props);
|
|
497
|
+
let $ = c(15), hovered, props, query;
|
|
498
|
+
$[0] === t0 ? (hovered = $[1], props = $[2], query = $[3]) : ({hovered, query, ...props} = t0, $[0] = t0, $[1] = hovered, $[2] = props, $[3] = query);
|
|
285
499
|
let t1;
|
|
286
|
-
$[
|
|
500
|
+
$[4] === hovered ? t1 = $[5] : (t1 = isDefined(hovered), $[4] = hovered, $[5] = t1);
|
|
287
501
|
let t2 = hovered?.element ?? null, t3;
|
|
288
|
-
$[
|
|
502
|
+
$[6] === Symbol.for("react.memo_cache_sentinel") ? (t3 = { pointerEvents: "none" }, $[6] = t3) : t3 = $[6];
|
|
289
503
|
let t4;
|
|
290
|
-
$[
|
|
504
|
+
$[7] !== hovered || $[8] !== query ? (t4 = isDefined(hovered) && /* @__PURE__ */ jsxs(Stack, {
|
|
291
505
|
gap: 3,
|
|
292
506
|
style: { maxWidth: "16rem" },
|
|
293
507
|
children: [/* @__PURE__ */ jsx(Text, {
|
|
294
508
|
size: 1,
|
|
295
509
|
weight: "medium",
|
|
296
|
-
children:
|
|
510
|
+
children: /* @__PURE__ */ jsx(Highlight, {
|
|
511
|
+
text: hovered.icon.label,
|
|
512
|
+
query
|
|
513
|
+
})
|
|
297
514
|
}), isDefined(hovered.icon.tags) && /* @__PURE__ */ jsx(Text, {
|
|
298
515
|
size: 1,
|
|
299
516
|
muted: !0,
|
|
300
|
-
children:
|
|
517
|
+
children: /* @__PURE__ */ jsx(Highlight, {
|
|
518
|
+
text: hovered.icon.tags,
|
|
519
|
+
query
|
|
520
|
+
})
|
|
301
521
|
})]
|
|
302
|
-
}), $[
|
|
522
|
+
}), $[7] = hovered, $[8] = query, $[9] = t4) : t4 = $[9];
|
|
303
523
|
let t5;
|
|
304
|
-
return $[
|
|
524
|
+
return $[10] !== props || $[11] !== t1 || $[12] !== t2 || $[13] !== t4 ? (t5 = /* @__PURE__ */ jsx(Popover, {
|
|
305
525
|
open: t1,
|
|
306
526
|
referenceElement: t2,
|
|
307
527
|
placement: "top",
|
|
@@ -311,104 +531,60 @@ function Tooltip(t0) {
|
|
|
311
531
|
style: t3,
|
|
312
532
|
content: t4,
|
|
313
533
|
...props
|
|
314
|
-
}), $[
|
|
315
|
-
}
|
|
316
|
-
/**
|
|
317
|
-
* Flattens text into the form a search compares against, so a hyphenated icon name and a multi-word
|
|
318
|
-
* tag are matched the same way.
|
|
319
|
-
*
|
|
320
|
-
* @param value - The text to flatten.
|
|
321
|
-
* @returns The text in comparable form.
|
|
322
|
-
*/
|
|
323
|
-
function normalizeTerms(value) {
|
|
324
|
-
return value.toLowerCase().replaceAll(/[\s-]+/gu, " ").trim();
|
|
325
|
-
}
|
|
326
|
-
/**
|
|
327
|
-
* Narrows the library to a chosen set of icons, in the order they were named. A name the library does
|
|
328
|
-
* not recognise is skipped, so a set outlives the release it was written against.
|
|
329
|
-
*
|
|
330
|
-
* @param library - Every icon the library offers.
|
|
331
|
-
* @param names - Names of the icons to offer, or nothing to offer them all.
|
|
332
|
-
* @returns The icons on offer.
|
|
333
|
-
*/
|
|
334
|
-
function selectIcons(library, names) {
|
|
335
|
-
if (!isDefined(names)) return library;
|
|
336
|
-
let byName = new Map(library.map((icon) => [icon.name, icon]));
|
|
337
|
-
return [...new Set(names)].flatMap((name) => {
|
|
338
|
-
let icon = byName.get(name);
|
|
339
|
-
return isDefined(icon) ? [icon] : [];
|
|
340
|
-
});
|
|
534
|
+
}), $[10] = props, $[11] = t1, $[12] = t2, $[13] = t4, $[14] = t5) : t5 = $[14], t5;
|
|
341
535
|
}
|
|
342
536
|
/**
|
|
343
|
-
*
|
|
344
|
-
* from the same release as the icons themselves, so the drawings and their terms never disagree.
|
|
537
|
+
* Loads an icon library style. Only an open picker calls this, so a Studio that never opens one never loads it.
|
|
345
538
|
*
|
|
346
|
-
* @
|
|
539
|
+
* @param library - Identifier of the library, or undefined when none is set.
|
|
540
|
+
* @param style - Identifier of the style, or undefined for the library's default.
|
|
541
|
+
* @returns The icons or why they can't be shown, or undefined while loading.
|
|
347
542
|
*/
|
|
348
|
-
|
|
349
|
-
let
|
|
350
|
-
return
|
|
351
|
-
let node = parseIconNode(nodes[name]);
|
|
352
|
-
if (!isDefined(node)) return [];
|
|
353
|
-
let iconTags = terms[name] ?? [];
|
|
354
|
-
return [{
|
|
355
|
-
name,
|
|
356
|
-
label: convertCase(name, "sentence"),
|
|
357
|
-
tags: iconTags.join(", "),
|
|
358
|
-
node,
|
|
359
|
-
terms: normalizeTerms([name, ...iconTags].join(" "))
|
|
360
|
-
}];
|
|
361
|
-
});
|
|
362
|
-
}
|
|
363
|
-
/**
|
|
364
|
-
* The library once asked for, held so every field in a Studio session shares the one request. It is a
|
|
365
|
-
* megabyte of data that never changes within a release, so asking twice only ever costs.
|
|
366
|
-
*/
|
|
367
|
-
let libraryRequest;
|
|
368
|
-
/**
|
|
369
|
-
* Reads the icon library, waiting on whatever request is already under way.
|
|
370
|
-
*
|
|
371
|
-
* @returns Every icon the library offers.
|
|
372
|
-
*/
|
|
373
|
-
async function requestLibrary() {
|
|
374
|
-
return libraryRequest ??= readLibrary(), await libraryRequest;
|
|
375
|
-
}
|
|
376
|
-
/**
|
|
377
|
-
* Reads the icon library. Callers mount only while a picker is open, so a Studio that never opens one
|
|
378
|
-
* never pays what it costs to read.
|
|
379
|
-
*
|
|
380
|
-
* @returns Every icon the library offers, or undefined while it is still being read.
|
|
381
|
-
*/
|
|
382
|
-
function useIconLibrary() {
|
|
383
|
-
let $ = c(2), [library, setLibrary] = useState(), t0, t1;
|
|
384
|
-
return $[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = () => {
|
|
543
|
+
function useIconLibrary(library, style) {
|
|
544
|
+
let $ = c(4), [result, setResult] = useState(), t0, t1;
|
|
545
|
+
return $[0] !== library || $[1] !== style ? (t0 = () => {
|
|
385
546
|
let active = !0;
|
|
386
547
|
return (async function load() {
|
|
387
|
-
let loaded = await requestLibrary();
|
|
388
|
-
active &&
|
|
548
|
+
let loaded = await requestLibrary(library, style);
|
|
549
|
+
active && setResult(loaded);
|
|
389
550
|
})(), () => {
|
|
390
551
|
active = !1;
|
|
391
552
|
};
|
|
392
|
-
}, t1 = [], $[0] =
|
|
553
|
+
}, t1 = [library, style], $[0] = library, $[1] = style, $[2] = t0, $[3] = t1) : (t0 = $[2], t1 = $[3]), useEffect(t0, t1), result;
|
|
393
554
|
}
|
|
394
555
|
/**
|
|
395
|
-
* Tracks
|
|
556
|
+
* Tracks the icon under the cursor, showing its tooltip after a short delay. Tooltips are held back while the grid
|
|
557
|
+
* scrolls, and the icon left under the cursor gets its tooltip once scrolling stops.
|
|
396
558
|
*
|
|
397
|
-
* @param scrolling - Whether the grid is
|
|
398
|
-
* @returns The icon
|
|
559
|
+
* @param scrolling - Whether the grid is scrolling.
|
|
560
|
+
* @returns The hovered icon, and functions to update and clear it.
|
|
399
561
|
*/
|
|
400
562
|
function useIconTooltip(scrolling) {
|
|
401
|
-
let $ = c(
|
|
563
|
+
let $ = c(14), [hovered, setHovered] = useState(), hoverStart = useRef(void 0), scrolledOnto = useRef(void 0), t0, t1;
|
|
402
564
|
$[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = () => () => {
|
|
403
565
|
isDefined(hoverStart.current) && clearTimeout(hoverStart.current);
|
|
404
566
|
}, t1 = [], $[0] = t0, $[1] = t1) : (t0 = $[0], t1 = $[1]), useEffect(t0, t1);
|
|
405
|
-
let t2;
|
|
406
|
-
$[2] ===
|
|
567
|
+
let t2, t3;
|
|
568
|
+
$[2] === scrolling ? (t2 = $[3], t3 = $[4]) : (t2 = () => {
|
|
569
|
+
let landed = scrolledOnto.current;
|
|
570
|
+
!scrolling && isDefined(landed) && (scrolledOnto.current = void 0, landed.element.isConnected && landed.element.matches(":hover") && (hoverStart.current = setTimeout(() => {
|
|
571
|
+
setHovered(landed);
|
|
572
|
+
}, 200)));
|
|
573
|
+
}, t3 = [scrolling], $[2] = scrolling, $[3] = t2, $[4] = t3), useEffect(t2, t3);
|
|
574
|
+
let t4;
|
|
575
|
+
$[5] === hovered ? t4 = $[6] : (t4 = function clearHover() {
|
|
407
576
|
isDefined(hoverStart.current) && clearTimeout(hoverStart.current), isDefined(hovered) && setHovered(void 0);
|
|
408
|
-
}, $[
|
|
409
|
-
let clearHover =
|
|
410
|
-
$[
|
|
411
|
-
if (
|
|
577
|
+
}, $[5] = hovered, $[6] = t4);
|
|
578
|
+
let clearHover = t4, t5;
|
|
579
|
+
$[7] !== hovered || $[8] !== scrolling ? (t5 = function handleHover(icon, element) {
|
|
580
|
+
if (scrolling) {
|
|
581
|
+
scrolledOnto.current = {
|
|
582
|
+
icon,
|
|
583
|
+
element
|
|
584
|
+
};
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
if (element !== hovered?.element) {
|
|
412
588
|
if (isDefined(hoverStart.current) && clearTimeout(hoverStart.current), isDefined(hovered)) {
|
|
413
589
|
setHovered({
|
|
414
590
|
icon,
|
|
@@ -423,77 +599,93 @@ function useIconTooltip(scrolling) {
|
|
|
423
599
|
});
|
|
424
600
|
}, 200);
|
|
425
601
|
}
|
|
426
|
-
}, $[
|
|
427
|
-
let handleHover =
|
|
428
|
-
return $[
|
|
602
|
+
}, $[7] = hovered, $[8] = scrolling, $[9] = t5) : t5 = $[9];
|
|
603
|
+
let handleHover = t5, t6;
|
|
604
|
+
return $[10] !== clearHover || $[11] !== handleHover || $[12] !== hovered ? (t6 = {
|
|
429
605
|
hovered,
|
|
430
606
|
handleHover,
|
|
431
607
|
clearHover
|
|
432
|
-
}, $[
|
|
608
|
+
}, $[10] = clearHover, $[11] = handleHover, $[12] = hovered, $[13] = t6) : t6 = $[13], t6;
|
|
433
609
|
}
|
|
434
|
-
/** Where the icons an author reached for last are kept, in the browser rather than the dataset. */
|
|
435
|
-
const storageKey = "driftime:sanity-plugin-icon:recent";
|
|
436
610
|
/**
|
|
437
|
-
*
|
|
611
|
+
* Builds the storage key for one library style.
|
|
438
612
|
*
|
|
439
|
-
* @
|
|
613
|
+
* @param scope - The library and style, such as `phosphor/bold`.
|
|
614
|
+
* @returns The storage key.
|
|
440
615
|
*/
|
|
441
|
-
function
|
|
616
|
+
function getStorageKey(scope) {
|
|
617
|
+
return `driftime:sanity-plugin-icon:recent:${scope}`;
|
|
618
|
+
}
|
|
619
|
+
/**
|
|
620
|
+
* Reads the recently chosen icons.
|
|
621
|
+
*
|
|
622
|
+
* @param scope - The library and style, such as `phosphor/bold`.
|
|
623
|
+
* @returns The icon names, most recent first.
|
|
624
|
+
*/
|
|
625
|
+
function readRecent(scope) {
|
|
442
626
|
try {
|
|
443
|
-
let stored = JSON.parse(globalThis.localStorage.getItem(
|
|
627
|
+
let stored = JSON.parse(globalThis.localStorage.getItem(getStorageKey(scope)) ?? "[]");
|
|
444
628
|
return Array.isArray(stored) ? stored.filter((entry) => typeof entry == "string") : [];
|
|
445
629
|
} catch {
|
|
446
630
|
return [];
|
|
447
631
|
}
|
|
448
632
|
}
|
|
449
633
|
/**
|
|
450
|
-
*
|
|
634
|
+
* Adds an icon to the front of the recent list.
|
|
451
635
|
*
|
|
452
|
-
* @param
|
|
453
|
-
* @
|
|
636
|
+
* @param scope - The library and style, such as `phosphor/bold`.
|
|
637
|
+
* @param name - The chosen icon's name.
|
|
638
|
+
* @returns The updated icon names, most recent first.
|
|
454
639
|
*/
|
|
455
|
-
function writeRecent(name) {
|
|
456
|
-
let updated = [name, ...readRecent().filter((entry) => entry !== name)].slice(0, 8);
|
|
640
|
+
function writeRecent(scope, name) {
|
|
641
|
+
let updated = [name, ...readRecent(scope).filter((entry) => entry !== name)].slice(0, 8);
|
|
457
642
|
try {
|
|
458
|
-
globalThis.localStorage.setItem(
|
|
643
|
+
globalThis.localStorage.setItem(getStorageKey(scope), JSON.stringify(updated));
|
|
459
644
|
} catch {}
|
|
460
645
|
return updated;
|
|
461
646
|
}
|
|
462
|
-
/**
|
|
463
|
-
|
|
647
|
+
/**
|
|
648
|
+
* Clears the recent icons.
|
|
649
|
+
*
|
|
650
|
+
* @param scope - The library and style, such as `phosphor/bold`.
|
|
651
|
+
*/
|
|
652
|
+
function clearRecent(scope) {
|
|
464
653
|
try {
|
|
465
|
-
globalThis.localStorage.removeItem(
|
|
654
|
+
globalThis.localStorage.removeItem(getStorageKey(scope));
|
|
466
655
|
} catch {}
|
|
467
656
|
}
|
|
468
657
|
/**
|
|
469
|
-
* Tracks the icons an author
|
|
470
|
-
*
|
|
658
|
+
* Tracks the icons an author chose most recently from one library style. The list is read when the picker opens, so
|
|
659
|
+
* choices made in another tab are included.
|
|
471
660
|
*
|
|
472
|
-
* @
|
|
661
|
+
* @param scope - The library and style, such as `phosphor/bold`.
|
|
662
|
+
* @returns The recent icon names, most recent first, and functions to add to and clear them.
|
|
473
663
|
*/
|
|
474
|
-
function useRecentIcons() {
|
|
475
|
-
let $ = c(
|
|
476
|
-
$[0] ===
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
$[
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
664
|
+
function useRecentIcons(scope) {
|
|
665
|
+
let $ = c(10), t0;
|
|
666
|
+
$[0] === scope ? t0 = $[1] : (t0 = () => readRecent(scope), $[0] = scope, $[1] = t0);
|
|
667
|
+
let [recent, setRecent] = useState(t0), t1;
|
|
668
|
+
$[2] === scope ? t1 = $[3] : (t1 = function remember(name) {
|
|
669
|
+
setRecent(writeRecent(scope, name));
|
|
670
|
+
}, $[2] = scope, $[3] = t1);
|
|
671
|
+
let remember = t1, t2;
|
|
672
|
+
$[4] === scope ? t2 = $[5] : (t2 = function forget() {
|
|
673
|
+
clearRecent(scope), setRecent([]);
|
|
674
|
+
}, $[4] = scope, $[5] = t2);
|
|
675
|
+
let forget = t2, t3;
|
|
676
|
+
return $[6] !== forget || $[7] !== recent || $[8] !== remember ? (t3 = {
|
|
485
677
|
recent,
|
|
486
678
|
remember,
|
|
487
679
|
forget
|
|
488
|
-
}, $[
|
|
680
|
+
}, $[6] = forget, $[7] = recent, $[8] = remember, $[9] = t3) : t3 = $[9], t3;
|
|
489
681
|
}
|
|
490
682
|
/**
|
|
491
|
-
* Works out which icon a key press moves to
|
|
683
|
+
* Works out which icon a key press moves to.
|
|
492
684
|
*
|
|
493
685
|
* @param key - The key pressed.
|
|
494
|
-
* @param current - Index of the icon
|
|
495
|
-
* @param last - Index of the
|
|
496
|
-
* @returns The index
|
|
686
|
+
* @param current - Index of the current icon.
|
|
687
|
+
* @param last - Index of the last icon.
|
|
688
|
+
* @returns The new index, or undefined when the key doesn't move.
|
|
497
689
|
*/
|
|
498
690
|
function getNextIndex(key, current, last) {
|
|
499
691
|
if (key === "ArrowRight") return current + 1;
|
|
@@ -504,12 +696,12 @@ function getNextIndex(key, current, last) {
|
|
|
504
696
|
if (key === "End") return last;
|
|
505
697
|
}
|
|
506
698
|
/**
|
|
507
|
-
* Works out which rows
|
|
508
|
-
*
|
|
699
|
+
* Works out which rows to render at a scroll position, so only icons near the viewport are mounted.
|
|
700
|
+
* Padding replaces the other rows, so the scrollbar stays the right size.
|
|
509
701
|
*
|
|
510
|
-
* @param scrollRow -
|
|
702
|
+
* @param scrollRow - The row scrolled to.
|
|
511
703
|
* @param count - Number of icons in the results.
|
|
512
|
-
* @returns The
|
|
704
|
+
* @returns The first and last rows to render, and the total number of rows.
|
|
513
705
|
*/
|
|
514
706
|
function getVisibleRows(scrollRow, count) {
|
|
515
707
|
let totalRows = Math.ceil(count / 8), firstRow = Math.max(0, scrollRow - 8);
|
|
@@ -520,32 +712,32 @@ function getVisibleRows(scrollRow, count) {
|
|
|
520
712
|
};
|
|
521
713
|
}
|
|
522
714
|
/**
|
|
523
|
-
* Works out
|
|
524
|
-
* icon already chosen.
|
|
715
|
+
* Works out the scroll position that centres an icon, for opening on the selected icon.
|
|
525
716
|
*
|
|
526
|
-
* @param index - Index of the icon
|
|
527
|
-
* @returns The
|
|
717
|
+
* @param index - Index of the icon.
|
|
718
|
+
* @returns The scroll position.
|
|
528
719
|
*/
|
|
529
720
|
function getCenteredScrollTop(index) {
|
|
530
721
|
return Math.max(0, Math.floor(index / 8) * 44 - 174);
|
|
531
722
|
}
|
|
532
723
|
/**
|
|
533
|
-
* Works out
|
|
534
|
-
*
|
|
535
|
-
* land outside the rows that are mounted.
|
|
724
|
+
* Works out the scroll position that brings an icon into view, keeping the current one if it's
|
|
725
|
+
* already visible. It uses the index because Home and End can move to rows that aren't mounted.
|
|
536
726
|
*
|
|
537
|
-
* @param index - Index of the icon
|
|
538
|
-
* @param scrollTop -
|
|
539
|
-
* @returns The
|
|
727
|
+
* @param index - Index of the icon.
|
|
728
|
+
* @param scrollTop - The current scroll position.
|
|
729
|
+
* @returns The scroll position.
|
|
540
730
|
*/
|
|
541
731
|
function getRevealedScrollTop(index, scrollTop) {
|
|
542
732
|
let top = Math.floor(index / 8) * 44;
|
|
543
733
|
return top < scrollTop ? top : top + 44 > scrollTop + 348 ? top + 44 - 348 : scrollTop;
|
|
544
734
|
}
|
|
545
735
|
function Picker(t0) {
|
|
546
|
-
let $ = c(
|
|
547
|
-
$[0] === t0 ? (allowed = $[1],
|
|
548
|
-
let
|
|
736
|
+
let $ = c(39), allowed, iconStyle, libraryName, onSelect, props, selected;
|
|
737
|
+
$[0] === t0 ? (allowed = $[1], iconStyle = $[2], libraryName = $[3], onSelect = $[4], props = $[5], selected = $[6]) : ({library: libraryName, iconStyle, allowed, selected, onSelect, ...props} = t0, $[0] = t0, $[1] = allowed, $[2] = iconStyle, $[3] = libraryName, $[4] = onSelect, $[5] = props, $[6] = selected);
|
|
738
|
+
let result = useIconLibrary(libraryName, iconStyle), library = result?.icons, icons = selectIcons(library ?? [], allowed), t1 = libraryName ?? "", t2 = iconStyle ?? "default", t3;
|
|
739
|
+
$[7] !== t1 || $[8] !== t2 ? (t3 = getIconSetKey(t1, t2), $[7] = t1, $[8] = t2, $[9] = t3) : t3 = $[9];
|
|
740
|
+
let { recent, remember, forget } = useRecentIcons(t3), [search, setSearch] = useState(""), [scrollRow, setScrollRow] = useState(0), [movedIndex, setMovedIndex] = useState(), [scrolling, setScrolling] = useState(!1), scroller = useRef(null), activeCell = useRef(null), focusIndex = useRef(void 0), scrollFrame = useRef(void 0), scrollStop = useRef(void 0), query = normalizeTerms(search), searching = isDefined(query), results = icons.filter((icon) => !searching || icon.terms.includes(query)), byName = new Map(icons.map(_temp)), recentIcons = searching ? [] : recent.flatMap((entry) => {
|
|
549
741
|
let icon_1 = byName.get(entry);
|
|
550
742
|
return isDefined(icon_1) ? [icon_1] : [];
|
|
551
743
|
}), { hovered, handleHover, clearHover } = useIconTooltip(scrolling), rows = getVisibleRows(scrollRow, results.length), selectedIndex = searching || !isDefined(selected) ? -1 : icons.findIndex((icon_2) => icon_2.name === selected), activeIndex = movedIndex ?? Math.max(0, selectedIndex);
|
|
@@ -553,23 +745,23 @@ function Picker(t0) {
|
|
|
553
745
|
let element = scroller.current;
|
|
554
746
|
isDefined(element) && selectedIndex !== -1 && (element.scrollTop = getCenteredScrollTop(selectedIndex));
|
|
555
747
|
}, [scroller, selectedIndex]);
|
|
556
|
-
let
|
|
557
|
-
$[
|
|
748
|
+
let t4, t5;
|
|
749
|
+
$[10] === Symbol.for("react.memo_cache_sentinel") ? (t4 = () => () => {
|
|
558
750
|
isDefined(scrollFrame.current) && cancelAnimationFrame(scrollFrame.current), isDefined(scrollStop.current) && clearTimeout(scrollStop.current);
|
|
559
|
-
},
|
|
560
|
-
let
|
|
561
|
-
$[
|
|
751
|
+
}, t5 = [], $[10] = t4, $[11] = t5) : (t4 = $[10], t5 = $[11]), useEffect(t4, t5);
|
|
752
|
+
let t6, t7;
|
|
753
|
+
$[12] === activeIndex ? (t6 = $[13], t7 = $[14]) : (t6 = () => {
|
|
562
754
|
focusIndex.current === activeIndex && (focusIndex.current = void 0, isDefined(activeCell.current) && activeCell.current.focus());
|
|
563
|
-
},
|
|
564
|
-
let
|
|
565
|
-
$[
|
|
755
|
+
}, t7 = [activeIndex], $[12] = activeIndex, $[13] = t6, $[14] = t7), useEffect(t6, t7);
|
|
756
|
+
let t8;
|
|
757
|
+
$[15] !== onSelect || $[16] !== remember ? (t8 = function handleSelect(icon_3) {
|
|
566
758
|
remember(icon_3.name), onSelect(icon_3);
|
|
567
|
-
}, $[
|
|
568
|
-
let handleSelect =
|
|
569
|
-
$[
|
|
759
|
+
}, $[15] = onSelect, $[16] = remember, $[17] = t8) : t8 = $[17];
|
|
760
|
+
let handleSelect = t8, t9;
|
|
761
|
+
$[18] === Symbol.for("react.memo_cache_sentinel") ? (t9 = function clearSearch() {
|
|
570
762
|
setSearch(""), setMovedIndex(void 0);
|
|
571
|
-
}, $[
|
|
572
|
-
let clearSearch =
|
|
763
|
+
}, $[18] = t9) : t9 = $[18];
|
|
764
|
+
let clearSearch = t9, handleSearch = function handleSearch(event) {
|
|
573
765
|
setSearch(event.currentTarget.value), setMovedIndex(void 0), isDefined(scroller.current) && (scroller.current.scrollTop = 0);
|
|
574
766
|
}, selectActive = function selectActive() {
|
|
575
767
|
let icon_4 = results[activeIndex];
|
|
@@ -602,17 +794,32 @@ function Picker(t0) {
|
|
|
602
794
|
focusIndex.current = index, setMovedIndex(index);
|
|
603
795
|
let element_1 = scroller.current;
|
|
604
796
|
isDefined(element_1) && (element_1.scrollTop = getRevealedScrollTop(index, element_1.scrollTop));
|
|
605
|
-
},
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
797
|
+
}, T0 = Dialog, T1 = Stack, t14 = !isDefined(result?.problem) && /* @__PURE__ */ jsx(TextInput, {
|
|
798
|
+
type: "search",
|
|
799
|
+
icon: /* @__PURE__ */ jsx(SearchIcon, {}),
|
|
800
|
+
placeholder: "Search by name or keyword",
|
|
801
|
+
value: search,
|
|
802
|
+
onChange: handleSearch,
|
|
803
|
+
onKeyDown: handleSearchKeyDown,
|
|
804
|
+
disabled: !isDefined(library) || !isDefined(icons),
|
|
805
|
+
"aria-label": "Search the icon library"
|
|
806
|
+
}), t15;
|
|
807
|
+
$[19] === result ? t15 = $[20] : (t15 = !isDefined(result) && /* @__PURE__ */ jsx(Flex, {
|
|
609
808
|
align: "center",
|
|
610
809
|
justify: "center",
|
|
611
810
|
style: { height: 348 },
|
|
612
811
|
children: /* @__PURE__ */ jsx(Spinner, { muted: !0 })
|
|
613
|
-
}), $[
|
|
614
|
-
let
|
|
615
|
-
$[
|
|
812
|
+
}), $[19] = result, $[20] = t15);
|
|
813
|
+
let t16;
|
|
814
|
+
$[21] === result ? t16 = $[22] : (t16 = isDefined(result?.problem) && /* @__PURE__ */ jsx(Problem, { problem: result.problem }), $[21] = result, $[22] = t16);
|
|
815
|
+
let t17 = isDefined(recentIcons) && /* @__PURE__ */ jsx(Recent, {
|
|
816
|
+
icons: recentIcons,
|
|
817
|
+
selected,
|
|
818
|
+
onSelect: handleSelect,
|
|
819
|
+
onHover: handleHover,
|
|
820
|
+
onForget: forget,
|
|
821
|
+
onMouseLeave: clearHover
|
|
822
|
+
}), t18 = isDefined(library) && /* @__PURE__ */ jsxs(Stack, {
|
|
616
823
|
gap: 3,
|
|
617
824
|
children: [
|
|
618
825
|
/* @__PURE__ */ jsx(Box, {
|
|
@@ -628,17 +835,18 @@ function Picker(t0) {
|
|
|
628
835
|
]
|
|
629
836
|
})
|
|
630
837
|
}),
|
|
631
|
-
icons
|
|
838
|
+
!isDefined(icons) && /* @__PURE__ */ jsx(Flex, {
|
|
632
839
|
align: "center",
|
|
633
840
|
justify: "center",
|
|
634
|
-
|
|
841
|
+
paddingTop: 5,
|
|
842
|
+
paddingBottom: 6,
|
|
635
843
|
children: /* @__PURE__ */ jsx(Text, {
|
|
636
844
|
size: 1,
|
|
637
845
|
muted: !0,
|
|
638
|
-
children: "No icons
|
|
846
|
+
children: "No icons available."
|
|
639
847
|
})
|
|
640
848
|
}),
|
|
641
|
-
icons
|
|
849
|
+
isDefined(icons) && /* @__PURE__ */ jsx(Library, {
|
|
642
850
|
ref: scroller,
|
|
643
851
|
icons: results,
|
|
644
852
|
rows,
|
|
@@ -654,39 +862,31 @@ function Picker(t0) {
|
|
|
654
862
|
onKeyDown: handleGridKeyDown
|
|
655
863
|
})
|
|
656
864
|
]
|
|
657
|
-
}),
|
|
658
|
-
|
|
659
|
-
|
|
865
|
+
}), t19 = hovered?.icon.name, t20;
|
|
866
|
+
$[23] !== hovered || $[24] !== query || $[25] !== t19 ? (t20 = /* @__PURE__ */ jsx(Tooltip, {
|
|
867
|
+
hovered,
|
|
868
|
+
query
|
|
869
|
+
}, t19), $[23] = hovered, $[24] = query, $[25] = t19, $[26] = t20) : t20 = $[26];
|
|
870
|
+
let t21;
|
|
871
|
+
$[27] !== T1 || $[28] !== t14 || $[29] !== t15 || $[30] !== t16 || $[31] !== t17 || $[32] !== t18 || $[33] !== t20 ? (t21 = /* @__PURE__ */ jsxs(T1, {
|
|
872
|
+
gap: 4,
|
|
873
|
+
padding: 4,
|
|
874
|
+
children: [
|
|
875
|
+
t14,
|
|
876
|
+
t15,
|
|
877
|
+
t16,
|
|
878
|
+
t17,
|
|
879
|
+
t18,
|
|
880
|
+
t20
|
|
881
|
+
]
|
|
882
|
+
}), $[27] = T1, $[28] = t14, $[29] = t15, $[30] = t16, $[31] = t17, $[32] = t18, $[33] = t20, $[34] = t21) : t21 = $[34];
|
|
883
|
+
let t22;
|
|
884
|
+
return $[35] !== T0 || $[36] !== props || $[37] !== t21 ? (t22 = /* @__PURE__ */ jsx(T0, {
|
|
660
885
|
header: "Select icon",
|
|
661
886
|
width: 1,
|
|
662
887
|
...props,
|
|
663
|
-
children:
|
|
664
|
-
|
|
665
|
-
padding: 4,
|
|
666
|
-
children: [
|
|
667
|
-
/* @__PURE__ */ jsx(TextInput, {
|
|
668
|
-
icon: t7,
|
|
669
|
-
placeholder: "Search by name or by what the icon depicts",
|
|
670
|
-
value: search,
|
|
671
|
-
onChange: handleSearch,
|
|
672
|
-
onKeyDown: handleSearchKeyDown,
|
|
673
|
-
disabled: !isDefined(library) || icons.length === 0,
|
|
674
|
-
"aria-label": "Search the icon library"
|
|
675
|
-
}),
|
|
676
|
-
t8,
|
|
677
|
-
isDefined(recentIcons) && /* @__PURE__ */ jsx(Recent, {
|
|
678
|
-
icons: recentIcons,
|
|
679
|
-
selected,
|
|
680
|
-
onSelect: handleSelect,
|
|
681
|
-
onHover: handleHover,
|
|
682
|
-
onForget: forget,
|
|
683
|
-
onMouseLeave: clearHover
|
|
684
|
-
}),
|
|
685
|
-
t9,
|
|
686
|
-
t11
|
|
687
|
-
]
|
|
688
|
-
})
|
|
689
|
-
});
|
|
888
|
+
children: t21
|
|
889
|
+
}), $[35] = T0, $[36] = props, $[37] = t21, $[38] = t22) : t22 = $[38], t22;
|
|
690
890
|
}
|
|
691
891
|
function _temp(icon_0) {
|
|
692
892
|
return [icon_0.name, icon_0];
|
|
@@ -723,46 +923,54 @@ function SquareDashedIcon(props) {
|
|
|
723
923
|
}), $[12] = props, $[13] = t12), t12;
|
|
724
924
|
}
|
|
725
925
|
/**
|
|
726
|
-
*
|
|
727
|
-
*
|
|
926
|
+
* Resolves the library, style, and icons a field offers. A field that names a library replaces all three of the
|
|
927
|
+
* plugin's, and one that doesn't uses the plugin's.
|
|
728
928
|
*
|
|
729
|
-
* @param options -
|
|
730
|
-
* @param config -
|
|
731
|
-
* @returns The settings the field
|
|
929
|
+
* @param options - The field's options.
|
|
930
|
+
* @param config - The plugin configuration.
|
|
931
|
+
* @returns The field's settings, whose library is undefined when neither the field nor the plugin names one.
|
|
732
932
|
*/
|
|
733
933
|
function resolveIconOptions(options, config) {
|
|
734
|
-
|
|
934
|
+
let { library, style, icons } = (isDefined(options?.library) ? options : config) ?? {};
|
|
935
|
+
return {
|
|
936
|
+
library,
|
|
937
|
+
style,
|
|
938
|
+
icons
|
|
939
|
+
};
|
|
735
940
|
}
|
|
736
|
-
/**
|
|
941
|
+
/** Schema type name of the icon object. */
|
|
737
942
|
const iconTypeName = "icon";
|
|
738
943
|
/**
|
|
739
|
-
* Creates the
|
|
740
|
-
*
|
|
944
|
+
* Creates the icon field input, bound to the plugin's configuration. A field's own icons replace the
|
|
945
|
+
* plugin's rather than adding to them.
|
|
741
946
|
*
|
|
742
|
-
* @param config -
|
|
947
|
+
* @param config - The plugin configuration.
|
|
743
948
|
* @returns The input component.
|
|
744
949
|
*/
|
|
745
950
|
function createInput(config) {
|
|
746
951
|
function Input(t0) {
|
|
747
|
-
let $ = c(
|
|
952
|
+
let $ = c(35), { id, schemaType, value, onChange, readOnly } = t0, { library: storedLibrary, name, node } = value ?? {}, [open, setOpen] = useState(!1), t1;
|
|
748
953
|
$[0] === schemaType.options ? t1 = $[1] : (t1 = resolveIconOptions(schemaType.options, config), $[0] = schemaType.options, $[1] = t1);
|
|
749
|
-
let { icons } = t1,
|
|
750
|
-
$[2] !==
|
|
954
|
+
let { library, style, icons } = t1, selectedDrawing = resolveIconDrawing(node), selectedName = storedLibrary === library ? name : void 0, selectedLabel = isDefined(name) ? convertCase(name, "title") : void 0, t2;
|
|
955
|
+
$[2] !== library || $[3] !== onChange || $[4] !== setOpen || $[5] !== style ? (t2 = function handleSelect(icon) {
|
|
751
956
|
onChange([
|
|
752
957
|
setIfMissing({ _type: iconTypeName }),
|
|
958
|
+
isDefined(library) ? set(library, ["library"]) : unset(["library"]),
|
|
959
|
+
isDefined(style) ? set(style, ["style"]) : unset(["style"]),
|
|
753
960
|
set(icon.name, ["name"]),
|
|
754
|
-
set(
|
|
961
|
+
set(serializeIconDrawing(icon.drawing), ["node"])
|
|
755
962
|
]), setOpen(!1);
|
|
756
|
-
}, $[2] =
|
|
757
|
-
let handleSelect = t2, T0 = Flex, T1 = Button, t6 = isDefined(
|
|
758
|
-
|
|
759
|
-
|
|
963
|
+
}, $[2] = library, $[3] = onChange, $[4] = setOpen, $[5] = style, $[6] = t2) : t2 = $[6];
|
|
964
|
+
let handleSelect = t2, T0 = Flex, T1 = Button, t6 = isDefined(selectedDrawing) ? /* @__PURE__ */ jsx(Drawing, {
|
|
965
|
+
drawing: selectedDrawing,
|
|
966
|
+
width: "1em",
|
|
967
|
+
height: "1em"
|
|
760
968
|
}) : /* @__PURE__ */ jsx(SquareDashedIcon, { ...defaultIconProps }), t7 = selectedLabel ?? "Select icon", t8;
|
|
761
|
-
$[
|
|
969
|
+
$[7] === setOpen ? t8 = $[8] : (t8 = () => {
|
|
762
970
|
setOpen(!0);
|
|
763
|
-
}, $[
|
|
971
|
+
}, $[7] = setOpen, $[8] = t8);
|
|
764
972
|
let t9 = isDefined(selectedLabel) ? `${selectedLabel} currently selected` : "Select icon", t10;
|
|
765
|
-
$[
|
|
973
|
+
$[9] !== T1 || $[10] !== id || $[11] !== readOnly || $[12] !== t6 || $[13] !== t7 || $[14] !== t8 || $[15] !== t9 ? (t10 = /* @__PURE__ */ jsx(T1, {
|
|
766
974
|
id,
|
|
767
975
|
type: "button",
|
|
768
976
|
mode: "ghost",
|
|
@@ -771,9 +979,9 @@ function createInput(config) {
|
|
|
771
979
|
disabled: readOnly,
|
|
772
980
|
onClick: t8,
|
|
773
981
|
"aria-label": t9
|
|
774
|
-
}), $[
|
|
982
|
+
}), $[9] = T1, $[10] = id, $[11] = readOnly, $[12] = t6, $[13] = t7, $[14] = t8, $[15] = t9, $[16] = t10) : t10 = $[16];
|
|
775
983
|
let t11;
|
|
776
|
-
$[
|
|
984
|
+
$[17] !== onChange || $[18] !== readOnly || $[19] !== value ? (t11 = isDefined(value) && /* @__PURE__ */ jsx(Button, {
|
|
777
985
|
type: "button",
|
|
778
986
|
mode: "ghost",
|
|
779
987
|
tone: "critical",
|
|
@@ -783,13 +991,15 @@ function createInput(config) {
|
|
|
783
991
|
onClick: () => {
|
|
784
992
|
onChange(unset());
|
|
785
993
|
},
|
|
786
|
-
"aria-label": "Clear the
|
|
787
|
-
}), $[
|
|
994
|
+
"aria-label": "Clear the selected icon"
|
|
995
|
+
}), $[17] = onChange, $[18] = readOnly, $[19] = value, $[20] = t11) : t11 = $[20];
|
|
788
996
|
let t12;
|
|
789
|
-
$[
|
|
997
|
+
$[21] !== handleSelect || $[22] !== icons || $[23] !== id || $[24] !== library || $[25] !== open || $[26] !== selectedName || $[27] !== setOpen || $[28] !== style ? (t12 = open && /* @__PURE__ */ jsx(Picker, {
|
|
790
998
|
id: `${id}-library`,
|
|
999
|
+
library,
|
|
1000
|
+
iconStyle: style,
|
|
791
1001
|
allowed: icons,
|
|
792
|
-
selected:
|
|
1002
|
+
selected: selectedName,
|
|
793
1003
|
onSelect: handleSelect,
|
|
794
1004
|
onClose: () => {
|
|
795
1005
|
setOpen(!1);
|
|
@@ -797,54 +1007,53 @@ function createInput(config) {
|
|
|
797
1007
|
onClickOutside: () => {
|
|
798
1008
|
setOpen(!1);
|
|
799
1009
|
}
|
|
800
|
-
}), $[
|
|
1010
|
+
}), $[21] = handleSelect, $[22] = icons, $[23] = id, $[24] = library, $[25] = open, $[26] = selectedName, $[27] = setOpen, $[28] = style, $[29] = t12) : t12 = $[29];
|
|
801
1011
|
let t13;
|
|
802
|
-
return $[
|
|
1012
|
+
return $[30] !== T0 || $[31] !== t10 || $[32] !== t11 || $[33] !== t12 ? (t13 = /* @__PURE__ */ jsxs(T0, {
|
|
803
1013
|
gap: 2,
|
|
804
1014
|
children: [
|
|
805
1015
|
t10,
|
|
806
1016
|
t11,
|
|
807
1017
|
t12
|
|
808
1018
|
]
|
|
809
|
-
}), $[
|
|
1019
|
+
}), $[30] = T0, $[31] = t10, $[32] = t11, $[33] = t12, $[34] = t13) : t13 = $[34], t13;
|
|
810
1020
|
}
|
|
811
1021
|
return Input;
|
|
812
1022
|
}
|
|
813
1023
|
/**
|
|
814
|
-
*
|
|
815
|
-
* rather than one placeholder standing in for every icon alike.
|
|
1024
|
+
* Creates preview media for a stored icon, so each document shows its own icon instead of a placeholder.
|
|
816
1025
|
*
|
|
817
1026
|
* @param value - The stored icon.
|
|
818
1027
|
* @returns The media component, or undefined when nothing readable was stored.
|
|
819
1028
|
* @public
|
|
820
1029
|
*/
|
|
821
1030
|
function createIconPreview(value) {
|
|
822
|
-
let
|
|
823
|
-
if (isDefined(
|
|
1031
|
+
let drawing = resolveIconDrawing(value?.node);
|
|
1032
|
+
if (isDefined(drawing)) return function IconPreview() {
|
|
824
1033
|
return createElement(Drawing, {
|
|
825
|
-
|
|
826
|
-
|
|
1034
|
+
drawing,
|
|
1035
|
+
width: "1em",
|
|
1036
|
+
height: "1em"
|
|
827
1037
|
});
|
|
828
1038
|
};
|
|
829
1039
|
}
|
|
830
1040
|
/**
|
|
831
|
-
* Creates the object type
|
|
832
|
-
* does not name its own.
|
|
1041
|
+
* Creates the icon object type, offering the plugin's icons to fields that don't set their own.
|
|
833
1042
|
*
|
|
834
|
-
* @param config -
|
|
835
|
-
* @returns
|
|
1043
|
+
* @param config - The plugin configuration.
|
|
1044
|
+
* @returns The icon type.
|
|
836
1045
|
*/
|
|
837
1046
|
function createIconType(config) {
|
|
838
1047
|
return defineType({
|
|
839
1048
|
name: iconTypeName,
|
|
840
1049
|
type: "object",
|
|
841
1050
|
icon: createSanityIcon(SquareDashedIcon),
|
|
842
|
-
description: "Icon chosen from
|
|
1051
|
+
description: "Icon chosen from an icon library.",
|
|
843
1052
|
components: {
|
|
844
1053
|
field: Field,
|
|
845
1054
|
input: createInput(config)
|
|
846
1055
|
},
|
|
847
|
-
validation: (rule) => rule.custom((value) => !isDefined(value?.name) || isDefined(value.node) ? !0 : "Select the icon again
|
|
1056
|
+
validation: (rule) => rule.custom((value) => !isDefined(value?.name) || isDefined(value.node) ? !0 : "Select the icon again to save its drawing."),
|
|
848
1057
|
preview: {
|
|
849
1058
|
select: {
|
|
850
1059
|
name: "name",
|
|
@@ -853,7 +1062,7 @@ function createIconType(config) {
|
|
|
853
1062
|
prepare(selection) {
|
|
854
1063
|
let { name, node } = selection;
|
|
855
1064
|
return {
|
|
856
|
-
title: isDefined(name) ? convertCase(name, "
|
|
1065
|
+
title: isDefined(name) ? convertCase(name, "title") : "No icon",
|
|
857
1066
|
media: createIconPreview({
|
|
858
1067
|
_type: iconTypeName,
|
|
859
1068
|
name,
|
|
@@ -862,30 +1071,43 @@ function createIconType(config) {
|
|
|
862
1071
|
};
|
|
863
1072
|
}
|
|
864
1073
|
},
|
|
865
|
-
fields: [
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
1074
|
+
fields: [
|
|
1075
|
+
defineField({
|
|
1076
|
+
name: "library",
|
|
1077
|
+
type: "string",
|
|
1078
|
+
description: "Identifier of the library the icon came from."
|
|
1079
|
+
}),
|
|
1080
|
+
defineField({
|
|
1081
|
+
name: "style",
|
|
1082
|
+
type: "string",
|
|
1083
|
+
description: "Identifier of the library style the icon came from."
|
|
1084
|
+
}),
|
|
1085
|
+
defineField({
|
|
1086
|
+
name: "name",
|
|
1087
|
+
type: "string",
|
|
1088
|
+
description: "Name of the icon in its library."
|
|
1089
|
+
}),
|
|
1090
|
+
defineField({
|
|
1091
|
+
name: "node",
|
|
1092
|
+
type: "text",
|
|
1093
|
+
description: "Shapes the icon is drawn from, saved when it's chosen."
|
|
1094
|
+
})
|
|
1095
|
+
]
|
|
874
1096
|
});
|
|
875
1097
|
}
|
|
876
1098
|
const plugin = definePlugin((config) => ({
|
|
877
|
-
name:
|
|
1099
|
+
name: pluginName,
|
|
878
1100
|
schema: { types: [createIconType(config)] }
|
|
879
1101
|
}));
|
|
880
1102
|
/**
|
|
881
|
-
*
|
|
882
|
-
*
|
|
1103
|
+
* Adds an icon field type to Sanity Studio, with a searchable picker for the installed icon libraries that
|
|
1104
|
+
* stores the chosen icon's drawing.
|
|
883
1105
|
*
|
|
884
|
-
* @param config -
|
|
885
|
-
* @returns
|
|
1106
|
+
* @param config - The plugin configuration.
|
|
1107
|
+
* @returns The plugin.
|
|
886
1108
|
* @public
|
|
887
1109
|
*/
|
|
888
|
-
function iconPlugin(config
|
|
1110
|
+
function iconPlugin(config) {
|
|
889
1111
|
return plugin(config);
|
|
890
1112
|
}
|
|
891
1113
|
export { createIconPreview, iconPlugin };
|