@driftime/sanity-plugin-icon 0.4.1 → 0.4.3
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 +70 -1
- package/dist/{sets-kepuObH8.js → defaults-BEzCWZtH.js} +2 -39
- package/dist/defaults-BEzCWZtH.js.map +1 -0
- package/dist/index.d.ts +16 -44
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +69 -176
- package/dist/index.js.map +1 -1
- package/dist/next-loader.js +2 -2
- package/dist/render.d.ts +24 -2
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +22 -3
- package/dist/render.js.map +1 -1
- package/dist/{sets-D5_YGFll.js → sets-B2lHNI7c.js} +3 -2
- package/dist/{sets-D5_YGFll.js.map → sets-B2lHNI7c.js.map} +1 -1
- package/dist/sets-BFcRq7dc.js +40 -0
- package/dist/sets-BFcRq7dc.js.map +1 -0
- package/dist/types-D9GjPlhU.d.ts +59 -0
- package/dist/types-D9GjPlhU.d.ts.map +1 -0
- package/dist/types-v7Qz7ogk.js +191 -0
- package/dist/types-v7Qz7ogk.js.map +1 -0
- package/dist/vite.js +2 -2
- package/package.json +1 -1
- package/dist/drawing-ByrcBbWB.js +0 -50
- package/dist/drawing-ByrcBbWB.js.map +0 -1
- package/dist/sets-kepuObH8.js.map +0 -1
- package/dist/types-qlHEYDoN.d.ts +0 -20
- package/dist/types-qlHEYDoN.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -278,6 +278,37 @@ export const contactIcons: SanityIconName<"lucide">[] = ["mail", "phone", "globe
|
|
|
278
278
|
|
|
279
279
|
<br />
|
|
280
280
|
|
|
281
|
+
### Initial Values
|
|
282
|
+
|
|
283
|
+
A field's `initialValue` names the icon a new document starts with. Once the build step has run, the name completes as it's typed.
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
defineField({
|
|
287
|
+
name: "icon",
|
|
288
|
+
type: "icon",
|
|
289
|
+
description: "Icon shown beside the contact method.",
|
|
290
|
+
options: { library: "lucide", icons: ["mail", "phone", "globe"] },
|
|
291
|
+
initialValue: { name: "mail" },
|
|
292
|
+
});
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
The initial value holds only the name. The first time the field is shown, the Studio finds the icon in the field's icon library and stores it with its icon library, style, and drawing. Until then, the stored icon has a name but no drawing, and it fails validation like any other icon in that state. A name the field doesn't offer is left as it is, and during development a message in the console names the field.
|
|
296
|
+
|
|
297
|
+
Names complete from every icon library the build step listed, not only the field's. A function that returns the initial value needs `SanityIconInitialValue` as its return type, so the name is checked rather than widened to a string.
|
|
298
|
+
|
|
299
|
+
```typescript
|
|
300
|
+
import type { SanityIconInitialValue } from "@driftime/sanity-plugin-icon";
|
|
301
|
+
|
|
302
|
+
defineField({
|
|
303
|
+
name: "icon",
|
|
304
|
+
type: "icon",
|
|
305
|
+
description: "Icon shown beside the contact method.",
|
|
306
|
+
initialValue: (): SanityIconInitialValue => ({ name: "mail" }),
|
|
307
|
+
});
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
<br />
|
|
311
|
+
|
|
281
312
|
### The Project's Own Icons
|
|
282
313
|
|
|
283
314
|
A folder of SVG files becomes an icon library of its own. It might hold a brand's marks, or a complete icon set drawn for a brand or a product. Pass the folder's path, relative to the project, to the build step under an identifier. Fields then name that identifier as their icon library.
|
|
@@ -349,7 +380,7 @@ When nothing readable is stored, it returns `undefined` and the preview falls ba
|
|
|
349
380
|
|
|
350
381
|
## Site
|
|
351
382
|
|
|
352
|
-
On the site,
|
|
383
|
+
On the site, `Icon` draws a stored icon, and `getIcon` finds an icon the site chooses itself. Both are imported from `@driftime/sanity-plugin-icon/render`. That path carries no Studio code, so it's safe in server components and anywhere else on the site.
|
|
353
384
|
|
|
354
385
|
<br />
|
|
355
386
|
|
|
@@ -400,6 +431,41 @@ An icon needs nothing special in a query. It comes back as a plain object with t
|
|
|
400
431
|
|
|
401
432
|
<br />
|
|
402
433
|
|
|
434
|
+
### Looking Up Icons
|
|
435
|
+
|
|
436
|
+
Some icons are chosen by the site rather than by an author, such as a default for an icon field left empty. `getIcon` finds an icon by name in an installed icon library and returns it as the Studio stores it, so `Icon` draws it the same way as an icon an author chose.
|
|
437
|
+
|
|
438
|
+
```tsx
|
|
439
|
+
import { getIcon, Icon } from "@driftime/sanity-plugin-icon/render";
|
|
440
|
+
import type { SanityIcon } from "@driftime/sanity-plugin-icon/render";
|
|
441
|
+
|
|
442
|
+
interface FeatureProps {
|
|
443
|
+
icon: SanityIcon | undefined;
|
|
444
|
+
title: string;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
export async function Feature({ icon, title }: FeatureProps) {
|
|
448
|
+
const value = icon ?? (await getIcon({ library: "lucide", name: "house" }));
|
|
449
|
+
|
|
450
|
+
return (
|
|
451
|
+
<article>
|
|
452
|
+
<Icon value={value} className="size-8" />
|
|
453
|
+
<h3>{title}</h3>
|
|
454
|
+
</article>
|
|
455
|
+
);
|
|
456
|
+
}
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
| Input | Type | Default | Purpose |
|
|
460
|
+
| --------- | ------------------- | ------------------- | --------------------------------------------------------------------------- |
|
|
461
|
+
| `library` | `SanityIconLibrary` | required | The identifier of the icon library. |
|
|
462
|
+
| `style` | `SanityIconStyle` | the library's first | The style the icon is drawn in. |
|
|
463
|
+
| `name` | `SanityIconName` | required | The icon's name, which completes as it's typed once the build step has run. |
|
|
464
|
+
|
|
465
|
+
It reads the icon libraries the build step converts, so the site's own build needs the build step, as [Adding the Build Step](#adding-the-build-step) describes. It returns `undefined` when the build step hasn't run, or when the icon library, style, or name isn't installed. The first call for a style loads every icon in that style, so it suits server components and images rendered on the server better than the browser.
|
|
466
|
+
|
|
467
|
+
<br />
|
|
468
|
+
|
|
403
469
|
## Reference
|
|
404
470
|
|
|
405
471
|
The rest of this document covers the shape of a stored icon and everything the package exports.
|
|
@@ -450,6 +516,7 @@ The drawing is written with the name, which is what lets an icon render without
|
|
|
450
516
|
| `iconLibraries(options?)` | `@driftime/sanity-plugin-icon/vite` | The build step as a Vite plugin, for a framework's list. |
|
|
451
517
|
| `withIcons(options?)` | `@driftime/sanity-plugin-icon/next` | Adds the build step to a Next.js configuration. |
|
|
452
518
|
| `Icon` | `@driftime/sanity-plugin-icon/render` | Draws a stored icon. |
|
|
519
|
+
| `getIcon(lookup)` | `@driftime/sanity-plugin-icon/render` | Finds an icon by name in an installed icon library. |
|
|
453
520
|
|
|
454
521
|
<br />
|
|
455
522
|
|
|
@@ -460,6 +527,7 @@ The drawing is written with the name, which is what lets an icon render without
|
|
|
460
527
|
| `SanityIconConfig` | `@driftime/sanity-plugin-icon` | Everything `iconPlugin` accepts. |
|
|
461
528
|
| `SanityIconOptions` | `@driftime/sanity-plugin-icon` | The `options` an icon field accepts. |
|
|
462
529
|
| `SanityIconDefinition` | `@driftime/sanity-plugin-icon` | A field or array member of type `icon`. |
|
|
530
|
+
| `SanityIconInitialValue` | `@driftime/sanity-plugin-icon` | The icon a field starts with. |
|
|
463
531
|
| `SanityIconSelection` | `@driftime/sanity-plugin-icon` | An icon library with a style and icons checked against it. |
|
|
464
532
|
| `SanityIconLibrary` | `@driftime/sanity-plugin-icon` | The identifier of a supported icon library. |
|
|
465
533
|
| `SanityIconStyle` | `@driftime/sanity-plugin-icon` | The styles of an icon library, given its identifier. |
|
|
@@ -471,6 +539,7 @@ The drawing is written with the name, which is what lets an icon render without
|
|
|
471
539
|
| `SanityIconWebpackCustomizer` | `@driftime/sanity-plugin-icon/next` | A Next.js `webpack` option the build step runs first. |
|
|
472
540
|
| `SanityIconProps` | `@driftime/sanity-plugin-icon/render` | Everything `Icon` accepts: an `svg` element's props and `value`. |
|
|
473
541
|
| `SanityIcon` | `@driftime/sanity-plugin-icon/render` | A stored icon, with its icon library, its name, and its drawing. |
|
|
542
|
+
| `SanityIconLookup` | `@driftime/sanity-plugin-icon/render` | Everything `getIcon` accepts: an icon library, a style, and a name. |
|
|
474
543
|
|
|
475
544
|
<br />
|
|
476
545
|
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { n as isDefined, r as isRecord } from "./utils-COPacfAq.js";
|
|
2
|
-
import { i as parseIconRoot, r as parseIconNode } from "./nodes-DAzj56Xn.js";
|
|
3
1
|
/** Whether this is a development build, the only kind in which the plugin logs. */
|
|
4
2
|
const isDevelopment = process.env.NODE_ENV === "development", prefixStyle = "color: #2276fc";
|
|
5
3
|
/**
|
|
@@ -50,41 +48,6 @@ function createLogger(name) {
|
|
|
50
48
|
}
|
|
51
49
|
/** Package name, used as the prefix on every logged message. */
|
|
52
50
|
const pluginName = "@driftime/sanity-plugin-icon", logger = createLogger(pluginName);
|
|
53
|
-
|
|
54
|
-
* Reads one icon of a converted set, skipping it when its data isn't usable.
|
|
55
|
-
*
|
|
56
|
-
* @param value - The value to read.
|
|
57
|
-
* @returns The icon, or undefined when the value isn't one.
|
|
58
|
-
*/
|
|
59
|
-
function parseIconSetIcon(value) {
|
|
60
|
-
if (!isRecord(value)) return;
|
|
61
|
-
let { name, keywords, node, root } = value, parsedNode = parseIconNode(node), parsedRoot = isDefined(root) ? parseIconRoot(root) : void 0;
|
|
62
|
-
if (typeof name == "string" && Array.isArray(keywords) && isDefined(parsedNode) && (!isDefined(root) || isDefined(parsedRoot))) return {
|
|
63
|
-
name,
|
|
64
|
-
keywords: keywords.filter((keyword) => typeof keyword == "string"),
|
|
65
|
-
node: parsedNode,
|
|
66
|
-
...isDefined(parsedRoot) && { root: parsedRoot }
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Reads a converted set, keeping only the icons whose data is usable.
|
|
71
|
-
*
|
|
72
|
-
* @param value - The value to read.
|
|
73
|
-
* @returns The set, or undefined when the value isn't one.
|
|
74
|
-
*/
|
|
75
|
-
function parseIconSet(value) {
|
|
76
|
-
if (!isRecord(value)) return;
|
|
77
|
-
let { library, style, root, icons } = value, parsedRoot = parseIconRoot(root);
|
|
78
|
-
if (typeof library == "string" && typeof style == "string" && isDefined(parsedRoot) && Array.isArray(icons)) return {
|
|
79
|
-
library,
|
|
80
|
-
style,
|
|
81
|
-
root: parsedRoot,
|
|
82
|
-
icons: icons.flatMap((icon) => {
|
|
83
|
-
let parsed = parseIconSetIcon(icon);
|
|
84
|
-
return isDefined(parsed) ? [parsed] : [];
|
|
85
|
-
})
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
export { logger as n, pluginName as r, parseIconSet as t };
|
|
51
|
+
export { pluginName as n, logger as t };
|
|
89
52
|
|
|
90
|
-
//# sourceMappingURL=
|
|
53
|
+
//# sourceMappingURL=defaults-BEzCWZtH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults-BEzCWZtH.js","names":["isDevelopment","process","env","isDevelopment","prefixStyle","createLogger","name","prefix","format","message","info","console","warn","error","createLogger","pluginName","logger","\"NODE_ENV\""],"sources":["../../@repo/lib/environment.ts","../../@repo/lib/logger.ts","../src/config/defaults.ts"],"sourcesContent":["/** Whether this is a development build, the only kind in which the plugin logs. */\nexport const isDevelopment = process.env[\"NODE_ENV\"] === \"development\";\n","import { isDevelopment } from \"./environment\";\n\n/** Console style for the prefix, in the blue the Studio uses for its own messages. */\nconst prefixStyle = \"color: #2276fc\";\n\n/**\n * Creates a logger that prefixes messages with the plugin's name and only logs in development builds.\n * Browser consoles show the prefix in blue.\n *\n * @param name - The package name to prefix messages with.\n * @returns Functions that log progress, a warning, or an error, or format a message to throw.\n */\nexport function createLogger(name: string) {\n const prefix = `[${name}]`;\n\n /**\n * Prefixes a message with the package name.\n *\n * @param message - The message.\n * @returns The prefixed message.\n */\n function format(message: string) {\n return `${prefix} ${message}`;\n }\n\n return {\n /**\n * Logs progress worth seeing, such as what a build step did, in development builds only.\n *\n * @param message - What happened.\n */\n info(message: string) {\n if (isDevelopment) console.info(`%c${prefix}%c ${message}`, prefixStyle, \"\");\n },\n /**\n * Logs a warning about something the plugin recovered from, in development builds only.\n *\n * @param message - What happened and what to do about it.\n */\n warn(message: string) {\n if (isDevelopment) console.warn(`%c${prefix}%c ${message}`, prefixStyle, \"\");\n },\n /**\n * Logs an error the plugin couldn't recover from, in development builds only.\n *\n * @param message - What went wrong and what to do about it.\n */\n error(message: string) {\n if (isDevelopment) console.error(`%c${prefix}%c ${message}`, prefixStyle, \"\");\n },\n format,\n };\n}\n","import { createLogger } from \"@repo/lib/logger\";\n\n/** Package name, used as the prefix on every logged message. */\nexport const pluginName = \"@driftime/sanity-plugin-icon\";\n\n/** The package's logger. */\nexport const logger = createLogger(pluginName);\n"],"mappings":";AACA,MAAaA,gBAAgBC,QAAQC,IAAIe,aAAgB,eCEnDb,cAAc;;;;;;;;AASpB,SAAgBC,aAAaC,MAAc;CACzC,IAAMC,SAAS,IAAID,KAAI;;;;;;;CAQvB,SAASE,OAAOC,SAAiB;EAC/B,OAAO,GAAGF,OAAM,GAAIE;CACtB;CAEA,OAAO;;;;;;EAMLC,KAAKD,SAAiB;GACpB,AAAIN,iBAAeQ,QAAQD,KAAK,KAAKH,OAAM,KAAME,WAAWL,aAAa,EAAE;EAC7E;;;;;;EAMAQ,KAAKH,SAAiB;GACpB,AAAIN,iBAAeQ,QAAQC,KAAK,KAAKL,OAAM,KAAME,WAAWL,aAAa,EAAE;EAC7E;;;;;;EAMAS,MAAMJ,SAAiB;GACrB,AAAIN,iBAAeQ,QAAQE,MAAM,KAAKN,OAAM,KAAME,WAAWL,aAAa,EAAE;EAC9E;EACAI;CACF;AACF;;ACjDA,MAAaO,aAAa,gCAGbC,SAASF,aAAaC,UAAU"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,52 +1,13 @@
|
|
|
1
|
-
import { n as iconTypeName, t as
|
|
1
|
+
import { a as SanityIconName, i as SanityIconLibrary, n as ListedLibraryId, o as SanityIconStyle, r as SanityIcon, s as iconTypeName, t as IconLibraryId } from "./types-D9GjPlhU.js";
|
|
2
2
|
import { t as SanityIconBuildOptions } from "./vite-ifICG8y9.js";
|
|
3
|
-
import { BaseSchemaTypeOptions, TypeAliasDefinition } from "sanity";
|
|
3
|
+
import { BaseSchemaTypeOptions, InitialValueProperty, TypeAliasDefinition } from "sanity";
|
|
4
4
|
import { ComponentProps } from "react";
|
|
5
|
-
import { SanityIconNames } from "@driftime/sanity-plugin-icon/names";
|
|
6
|
-
/**
|
|
7
|
-
* Styles of each library the plugin supports, the first being the default. For a library published as a family of
|
|
8
|
-
* packages, its styles are the packages it publishes, and the installed ones are used.
|
|
9
|
-
*/
|
|
10
|
-
declare const iconLibraryStyles: {
|
|
11
|
-
readonly central: ("round-filled-radius-0-stroke-1" | "round-filled-radius-0-stroke-1.5" | "round-filled-radius-0-stroke-2" | "round-filled-radius-1-stroke-1" | "round-filled-radius-1-stroke-1.5" | "round-filled-radius-1-stroke-2" | "round-filled-radius-2-stroke-1" | "round-filled-radius-2-stroke-1.5" | "round-filled-radius-2-stroke-2" | "round-filled-radius-3-stroke-1" | "round-filled-radius-3-stroke-1.5" | "round-filled-radius-3-stroke-2" | "round-outlined-radius-0-stroke-1" | "round-outlined-radius-0-stroke-1.5" | "round-outlined-radius-0-stroke-2" | "round-outlined-radius-1-stroke-1" | "round-outlined-radius-1-stroke-1.5" | "round-outlined-radius-1-stroke-2" | "round-outlined-radius-2-stroke-1" | "round-outlined-radius-2-stroke-1.5" | "round-outlined-radius-2-stroke-2" | "round-outlined-radius-3-stroke-1" | "round-outlined-radius-3-stroke-1.5" | "round-outlined-radius-3-stroke-2" | "square-filled-radius-0-stroke-1" | "square-filled-radius-0-stroke-1.5" | "square-filled-radius-0-stroke-2" | "square-outlined-radius-0-stroke-1" | "square-outlined-radius-0-stroke-1.5" | "square-outlined-radius-0-stroke-2")[];
|
|
12
|
-
readonly heroicons: readonly ["outline", "solid", "mini", "micro"];
|
|
13
|
-
readonly hugeicons: readonly ["stroke-rounded"];
|
|
14
|
-
readonly iconoir: readonly ["regular", "solid"];
|
|
15
|
-
readonly lucide: readonly ["default"];
|
|
16
|
-
readonly nucleo: readonly ["arcade", "core-essential-fill-24", "core-essential-fill-32", "core-essential-fill-48", "core-essential-outline-24", "core-essential-outline-32", "core-essential-outline-48", "core-fill-24", "core-fill-32", "core-fill-48", "core-outline-24", "core-outline-32", "core-outline-48", "credit-cards", "flags", "glass", "isometric", "micro-bold", "micro-bold-essential", "pixel", "pixel-essential", "sharp", "sharp-essential", "social-media", "ui-essential-fill-12", "ui-essential-fill-18", "ui-essential-fill-duo-18", "ui-essential-outline-12", "ui-essential-outline-18", "ui-essential-outline-duo-18", "ui-fill-12", "ui-fill-18", "ui-fill-duo-18", "ui-outline-12", "ui-outline-18", "ui-outline-duo-18"];
|
|
17
|
-
readonly phosphor: readonly ["regular", "thin", "light", "bold", "fill", "duotone"];
|
|
18
|
-
readonly tabler: readonly ["outline", "filled"];
|
|
19
|
-
};
|
|
20
5
|
declare module "@sanity/types" {
|
|
21
6
|
interface IntrinsicDefinitions {
|
|
22
7
|
/** Definition of a field of type `icon`. */
|
|
23
8
|
icon: SanityIconDefinition;
|
|
24
9
|
}
|
|
25
10
|
}
|
|
26
|
-
/** Styles of each supported library, from the plugin's own list. */
|
|
27
|
-
type IconLibraryStyles = typeof iconLibraryStyles;
|
|
28
|
-
/**
|
|
29
|
-
* Identifier of a library the plugin supports.
|
|
30
|
-
*
|
|
31
|
-
* @public
|
|
32
|
-
*/
|
|
33
|
-
type SanityIconLibrary = keyof IconLibraryStyles;
|
|
34
|
-
/**
|
|
35
|
-
* Styles a library offers. The project's own icon folders have one style, `default`.
|
|
36
|
-
*
|
|
37
|
-
* @public
|
|
38
|
-
*/
|
|
39
|
-
type SanityIconStyle<Library extends string> = Library extends SanityIconLibrary ? IconLibraryStyles[Library][number] : "default";
|
|
40
|
-
/**
|
|
41
|
-
* Names of a library's icons, once the build step has listed the installed version's, or any name before then.
|
|
42
|
-
*
|
|
43
|
-
* @public
|
|
44
|
-
*/
|
|
45
|
-
type SanityIconName<Library extends string> = Library extends keyof SanityIconNames ? SanityIconNames[Library] : string;
|
|
46
|
-
/** Libraries the build step has listed, or any identifier before it has, so the project's own folders can be named. */
|
|
47
|
-
type ListedLibraryId = [keyof SanityIconNames] extends [never] ? string & NonNullable<unknown> : Extract<keyof SanityIconNames, string>;
|
|
48
|
-
/** Libraries a field can name: the supported ones, plus the project's own folders. */
|
|
49
|
-
type IconLibraryId = SanityIconLibrary | ListedLibraryId;
|
|
50
11
|
/**
|
|
51
12
|
* A choice of library, style, and icons, where the style and icons are checked against the library.
|
|
52
13
|
*
|
|
@@ -72,14 +33,25 @@ type SanityIconOptions = BaseSchemaTypeOptions & (SanityIconSelection | {
|
|
|
72
33
|
icons?: undefined;
|
|
73
34
|
});
|
|
74
35
|
/**
|
|
75
|
-
*
|
|
36
|
+
* Icon a field starts with. The Studio saves its drawing from the field's library the first time the field is shown.
|
|
37
|
+
*
|
|
38
|
+
* @public
|
|
39
|
+
*/
|
|
40
|
+
interface SanityIconInitialValue {
|
|
41
|
+
/** Name of the icon, from any library the build step has listed. */
|
|
42
|
+
name: SanityIconName<ListedLibraryId>;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Definition of a field or array member holding an icon, so its options and initial value are type-checked like a
|
|
76
46
|
* built-in type's.
|
|
77
47
|
*
|
|
78
48
|
* @public
|
|
79
49
|
*/
|
|
80
|
-
interface SanityIconDefinition extends Omit<TypeAliasDefinition<typeof iconTypeName, undefined>, "options"> {
|
|
50
|
+
interface SanityIconDefinition extends Omit<TypeAliasDefinition<typeof iconTypeName, undefined>, "options" | "initialValue"> {
|
|
81
51
|
/** Options for the field. */
|
|
82
52
|
options?: SanityIconOptions;
|
|
53
|
+
/** Icon the field starts with, or a function that returns one. */
|
|
54
|
+
initialValue?: InitialValueProperty<unknown, SanityIconInitialValue>;
|
|
83
55
|
}
|
|
84
56
|
/**
|
|
85
57
|
* Plugin configuration, naming the library every icon field uses unless it names its own.
|
|
@@ -120,5 +92,5 @@ type DrawingProps = Omit<ComponentProps<"svg">, "children"> & {
|
|
|
120
92
|
* @public
|
|
121
93
|
*/
|
|
122
94
|
export declare function createIconPreview(value: SanityIcon | undefined): (() => import("react").FunctionComponentElement<DrawingProps>) | undefined;
|
|
123
|
-
export type { SanityIconBuildOptions, SanityIconConfig, SanityIconDefinition, SanityIconLibrary, SanityIconName, SanityIconOptions, SanityIconSelection, SanityIconStyle };
|
|
95
|
+
export type { SanityIconBuildOptions, SanityIconConfig, SanityIconDefinition, SanityIconInitialValue, SanityIconLibrary, SanityIconName, SanityIconOptions, SanityIconSelection, SanityIconStyle };
|
|
124
96
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":["
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":["BaseSchemaTypeOptions","InitialValueProperty","TypeAliasDefinition","IconLibraryId","ListedLibraryId","SanityIconName","SanityIconStyle","iconTypeName","_0","SanityIconDefinition","sideEffect","SanityIconSelection","Library","SanityIconOptions","SanityIconInitialValue","Omit","SanityIconConfig","iconPlugin","IconElement","Record","IconNode","IconRoot","IconDrawing","iconSvgAttributes","findDrawingProblem","root","node","parseIconNode","parseIconRoot","resolveIconDrawing","serializeIconDrawing","ComponentProps","IconDrawing","DrawingProps","Omit","Drawing","drawing","JSX","_$__components_drawing0","SanityIcon","createIconPreview","DrawingProps","_$__components_drawing0.DrawingProps"],"sources":["../src/plugin.ts","../src/lib/nodes.ts","../src/components/drawing.tsx","../src/lib/preview.ts"],"mappings":";;;;;YAQY;;IAER,MAAMS;;;;;;;;KASEE,yBACT,WAAWR;;EAEV,SAASS;;EAET,QAAQN,gBAAgBM;;EAExB,QAAQP,eAAeO;KAEzBT;;;;;;;KAQUU,oBAAoBb,yBAC7BW;EAAwB;EAAqB;EAAmB;;;;;;;UAOlDG;;EAEf,MAAMT,eAAeD;;;;;;;;UASNK,6BAA6BM,KAC5Cb,2BAA2BK;;EAI3B,UAAUM;;EAEV,eAAeZ,8BAA8Ba;;;;;;;KAQnCE,mBAAmBL;;;;;;;;;wBAiBfM,WAAW,QAAQD,oCAAgB;;KCnFvCE,eAAe,iBAAiB,YAAYC,wBAAwB,YAAYD;;KAGhFE,WAAWF;;KAGXG,WAAWF;;UAGNG;;EAEf,MAAMD;;EAEN,MAAMD;;KCuCIa,eAAeC,KAAKH;EAAuC,SAASC;;;;;;;;;wBC1ChEQ,kBAAkB,OAAOD,gDAAsB,yBAAtBD"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as pluginName, t as logger } from "./defaults-BEzCWZtH.js";
|
|
2
2
|
import { n as isDefined, t as convertCase } from "./utils-COPacfAq.js";
|
|
3
3
|
import { a as resolveIconDrawing, o as serializeIconDrawing } from "./nodes-DAzj56Xn.js";
|
|
4
|
-
import {
|
|
4
|
+
import { a as splitMatches, i as selectIcons, n as normalizeTerms, o as Drawing, r as requestLibrary, t as iconTypeName } from "./types-v7Qz7ogk.js";
|
|
5
5
|
import { t as getIconSetKey } from "./registry-BEEpqK3z.js";
|
|
6
6
|
import { ChangeIndicator, FieldActionsProvider, FieldActionsResolver, FormField, defineField, definePlugin, defineType, getPublishedId, set, setIfMissing, unset, useFormValue } from "sanity";
|
|
7
7
|
import { c } from "react/compiler-runtime";
|
|
@@ -12,7 +12,6 @@ import { Box, Button, Card, Dialog, Flex, Grid, Spinner, Stack, Text, TextInput
|
|
|
12
12
|
import { SearchIcon } from "@sanity/icons/Search";
|
|
13
13
|
import { WarningOutlineIcon } from "@sanity/icons/WarningOutline";
|
|
14
14
|
import { Popover } from "@sanity/ui/popover";
|
|
15
|
-
import { iconRegistry } from "@driftime/sanity-plugin-icon/sets";
|
|
16
15
|
/**
|
|
17
16
|
* Checks whether a form node has members, as objects and arrays of objects do.
|
|
18
17
|
*
|
|
@@ -326,142 +325,6 @@ function Recent(t0) {
|
|
|
326
325
|
}), $[22] = props, $[23] = t2, $[24] = t4, $[25] = t5) : t5 = $[25], t5;
|
|
327
326
|
}
|
|
328
327
|
/**
|
|
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
328
|
* Gap between the tooltip and its cell, set through margins because `@sanity/ui` offers no other way.
|
|
466
329
|
* Only the top is set, since the tooltip always appears above the cell.
|
|
467
330
|
*/
|
|
@@ -938,8 +801,23 @@ function resolveIconOptions(options, config) {
|
|
|
938
801
|
icons
|
|
939
802
|
};
|
|
940
803
|
}
|
|
941
|
-
/**
|
|
942
|
-
|
|
804
|
+
/**
|
|
805
|
+
* Creates the patches that store an icon, with the library and style it was chosen from.
|
|
806
|
+
*
|
|
807
|
+
* @param icon - The icon.
|
|
808
|
+
* @param library - Identifier of the library, or undefined when none is set.
|
|
809
|
+
* @param style - Identifier of the style, or undefined for the library's default.
|
|
810
|
+
* @returns The patches.
|
|
811
|
+
*/
|
|
812
|
+
function createSelectionPatches(icon, library, style) {
|
|
813
|
+
return [
|
|
814
|
+
setIfMissing({ _type: iconTypeName }),
|
|
815
|
+
isDefined(library) ? set(library, ["library"]) : unset(["library"]),
|
|
816
|
+
isDefined(style) ? set(style, ["style"]) : unset(["style"]),
|
|
817
|
+
set(icon.name, ["name"]),
|
|
818
|
+
set(serializeIconDrawing(icon.drawing), ["node"])
|
|
819
|
+
];
|
|
820
|
+
}
|
|
943
821
|
/**
|
|
944
822
|
* Creates the icon field input, bound to the plugin's configuration. A field's own icons replace the
|
|
945
823
|
* plugin's rather than adding to them.
|
|
@@ -949,39 +827,54 @@ const iconTypeName = "icon";
|
|
|
949
827
|
*/
|
|
950
828
|
function createInput(config) {
|
|
951
829
|
function Input(t0) {
|
|
952
|
-
let $ = c(
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
830
|
+
let $ = c(28), { id, schemaType, value, onChange, readOnly } = t0, { library: storedLibrary, name, node } = value ?? {}, [open, setOpen] = useState(!1), { library, style, icons } = resolveIconOptions(schemaType.options, config), selectedDrawing = resolveIconDrawing(node), selectedName = storedLibrary === library ? name : void 0, selectedLabel = isDefined(name) ? convertCase(name, "title") : void 0, undrawnName = isDefined(node) ? void 0 : name;
|
|
831
|
+
useEffect(() => {
|
|
832
|
+
let active = !0;
|
|
833
|
+
return (async function saveDrawing() {
|
|
834
|
+
if (!isDefined(undrawnName) || readOnly === !0) return;
|
|
835
|
+
let { icons: libraryIcons } = await requestLibrary(library, style);
|
|
836
|
+
if (!active || !isDefined(libraryIcons)) return;
|
|
837
|
+
let icon = selectIcons(libraryIcons, icons).find((candidate) => candidate.name === undrawnName);
|
|
838
|
+
if (!isDefined(icon)) {
|
|
839
|
+
logger.warn(`The icon field "${id}" starts with "${undrawnName}", which isn't one of its icons. Change its initialValue.`);
|
|
840
|
+
return;
|
|
841
|
+
}
|
|
842
|
+
onChange(createSelectionPatches(icon, library, style));
|
|
843
|
+
})(), () => {
|
|
844
|
+
active = !1;
|
|
845
|
+
};
|
|
846
|
+
}, [
|
|
847
|
+
id,
|
|
848
|
+
undrawnName,
|
|
849
|
+
readOnly,
|
|
850
|
+
library,
|
|
851
|
+
style,
|
|
852
|
+
icons,
|
|
853
|
+
onChange
|
|
854
|
+
]);
|
|
855
|
+
let handleSelect = function handleSelect(icon_0) {
|
|
856
|
+
onChange(createSelectionPatches(icon_0, library, style)), setOpen(!1);
|
|
857
|
+
}, T0 = Flex, T1 = Button, t4 = isDefined(selectedDrawing) ? /* @__PURE__ */ jsx(Drawing, {
|
|
965
858
|
drawing: selectedDrawing,
|
|
966
859
|
width: "1em",
|
|
967
860
|
height: "1em"
|
|
968
|
-
}) : /* @__PURE__ */ jsx(SquareDashedIcon, { ...defaultIconProps }),
|
|
969
|
-
$[
|
|
861
|
+
}) : /* @__PURE__ */ jsx(SquareDashedIcon, { ...defaultIconProps }), t5 = selectedLabel ?? "Select icon", t6;
|
|
862
|
+
$[0] === setOpen ? t6 = $[1] : (t6 = () => {
|
|
970
863
|
setOpen(!0);
|
|
971
|
-
}, $[
|
|
972
|
-
let
|
|
973
|
-
$[
|
|
864
|
+
}, $[0] = setOpen, $[1] = t6);
|
|
865
|
+
let t7 = isDefined(selectedLabel) ? `${selectedLabel} currently selected` : "Select icon", t8;
|
|
866
|
+
$[2] !== T1 || $[3] !== id || $[4] !== readOnly || $[5] !== t4 || $[6] !== t5 || $[7] !== t6 || $[8] !== t7 ? (t8 = /* @__PURE__ */ jsx(T1, {
|
|
974
867
|
id,
|
|
975
868
|
type: "button",
|
|
976
869
|
mode: "ghost",
|
|
977
|
-
icon:
|
|
978
|
-
text:
|
|
870
|
+
icon: t4,
|
|
871
|
+
text: t5,
|
|
979
872
|
disabled: readOnly,
|
|
980
|
-
onClick:
|
|
981
|
-
"aria-label":
|
|
982
|
-
}), $[
|
|
983
|
-
let
|
|
984
|
-
$[
|
|
873
|
+
onClick: t6,
|
|
874
|
+
"aria-label": t7
|
|
875
|
+
}), $[2] = T1, $[3] = id, $[4] = readOnly, $[5] = t4, $[6] = t5, $[7] = t6, $[8] = t7, $[9] = t8) : t8 = $[9];
|
|
876
|
+
let t9;
|
|
877
|
+
$[10] !== onChange || $[11] !== readOnly || $[12] !== value ? (t9 = isDefined(value) && /* @__PURE__ */ jsx(Button, {
|
|
985
878
|
type: "button",
|
|
986
879
|
mode: "ghost",
|
|
987
880
|
tone: "critical",
|
|
@@ -992,9 +885,9 @@ function createInput(config) {
|
|
|
992
885
|
onChange(unset());
|
|
993
886
|
},
|
|
994
887
|
"aria-label": "Clear the selected icon"
|
|
995
|
-
}), $[
|
|
996
|
-
let
|
|
997
|
-
$[
|
|
888
|
+
}), $[10] = onChange, $[11] = readOnly, $[12] = value, $[13] = t9) : t9 = $[13];
|
|
889
|
+
let t10;
|
|
890
|
+
$[14] !== handleSelect || $[15] !== icons || $[16] !== id || $[17] !== library || $[18] !== open || $[19] !== selectedName || $[20] !== setOpen || $[21] !== style ? (t10 = open && /* @__PURE__ */ jsx(Picker, {
|
|
998
891
|
id: `${id}-library`,
|
|
999
892
|
library,
|
|
1000
893
|
iconStyle: style,
|
|
@@ -1007,16 +900,16 @@ function createInput(config) {
|
|
|
1007
900
|
onClickOutside: () => {
|
|
1008
901
|
setOpen(!1);
|
|
1009
902
|
}
|
|
1010
|
-
}), $[
|
|
1011
|
-
let
|
|
1012
|
-
return $[
|
|
903
|
+
}), $[14] = handleSelect, $[15] = icons, $[16] = id, $[17] = library, $[18] = open, $[19] = selectedName, $[20] = setOpen, $[21] = style, $[22] = t10) : t10 = $[22];
|
|
904
|
+
let t11;
|
|
905
|
+
return $[23] !== T0 || $[24] !== t10 || $[25] !== t8 || $[26] !== t9 ? (t11 = /* @__PURE__ */ jsxs(T0, {
|
|
1013
906
|
gap: 2,
|
|
1014
907
|
children: [
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
908
|
+
t8,
|
|
909
|
+
t9,
|
|
910
|
+
t10
|
|
1018
911
|
]
|
|
1019
|
-
}), $[
|
|
912
|
+
}), $[23] = T0, $[24] = t10, $[25] = t8, $[26] = t9, $[27] = t11) : t11 = $[27], t11;
|
|
1020
913
|
}
|
|
1021
914
|
return Input;
|
|
1022
915
|
}
|