@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.
Files changed (55) hide show
  1. package/README.md +253 -61
  2. package/dist/adapters-Bx_MyEX_.js +633 -0
  3. package/dist/adapters-Bx_MyEX_.js.map +1 -0
  4. package/dist/drawing-ByrcBbWB.js +50 -0
  5. package/dist/drawing-ByrcBbWB.js.map +1 -0
  6. package/dist/index.d.ts +84 -32
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +545 -323
  9. package/dist/index.js.map +1 -1
  10. package/dist/names.d.ts +8 -0
  11. package/dist/names.d.ts.map +1 -0
  12. package/dist/names.js +0 -0
  13. package/dist/next-loader.d.ts +64 -0
  14. package/dist/next-loader.d.ts.map +1 -0
  15. package/dist/next-loader.js +103 -0
  16. package/dist/next-loader.js.map +1 -0
  17. package/dist/next.d.ts +43 -0
  18. package/dist/next.d.ts.map +1 -0
  19. package/dist/next.js +52 -0
  20. package/dist/next.js.map +1 -0
  21. package/dist/nodes-DAzj56Xn.js +139 -0
  22. package/dist/nodes-DAzj56Xn.js.map +1 -0
  23. package/dist/read-worker.d.ts +1 -0
  24. package/dist/read-worker.js +23 -0
  25. package/dist/read-worker.js.map +1 -0
  26. package/dist/registry-B0Dxiwhh.js +68 -0
  27. package/dist/registry-B0Dxiwhh.js.map +1 -0
  28. package/dist/registry-BEEpqK3z.js +13 -0
  29. package/dist/registry-BEEpqK3z.js.map +1 -0
  30. package/dist/render.d.ts +4 -5
  31. package/dist/render.d.ts.map +1 -1
  32. package/dist/render.js +5 -5
  33. package/dist/render.js.map +1 -1
  34. package/dist/sets-D5_YGFll.js +258 -0
  35. package/dist/sets-D5_YGFll.js.map +1 -0
  36. package/dist/sets-kepuObH8.js +90 -0
  37. package/dist/sets-kepuObH8.js.map +1 -0
  38. package/dist/sets.d.ts +50 -0
  39. package/dist/sets.d.ts.map +1 -0
  40. package/dist/sets.js +14 -0
  41. package/dist/sets.js.map +1 -0
  42. package/dist/types-qlHEYDoN.d.ts +20 -0
  43. package/dist/types-qlHEYDoN.d.ts.map +1 -0
  44. package/dist/utils-COPacfAq.js +48 -0
  45. package/dist/utils-COPacfAq.js.map +1 -0
  46. package/dist/vite-ifICG8y9.d.ts +98 -0
  47. package/dist/vite-ifICG8y9.d.ts.map +1 -0
  48. package/dist/vite.d.ts +2 -0
  49. package/dist/vite.js +88 -0
  50. package/dist/vite.js.map +1 -0
  51. package/package.json +42 -5
  52. package/dist/drawing-BThiR2bN.js +0 -129
  53. package/dist/drawing-BThiR2bN.js.map +0 -1
  54. package/dist/types-_D2jGm25.d.ts +0 -16
  55. package/dist/types-_D2jGm25.d.ts.map +0 -1
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Options for the build step that converts icon libraries for the Studio.
3
+ *
4
+ * @public
5
+ */
6
+ interface SanityIconBuildOptions {
7
+ /** Folders of the project's own SVG icons, keyed by the identifier fields use, such as `{ acme: "./icons" }`. */
8
+ custom?: Record<string, string>;
9
+ }
10
+ /**
11
+ * A Vite plugin, limited to the hooks the build step uses, so the package doesn't depend on Vite's own types.
12
+ *
13
+ * @public
14
+ */
15
+ interface SanityIconVitePlugin {
16
+ /** Name Vite reports the plugin under. */
17
+ name: string;
18
+ /**
19
+ * Keeps the placeholder registry out of Vite's pre-bundling in development, which would fix it in place, while the
20
+ * rest of the plugin and its dependencies are pre-bundled as usual.
21
+ *
22
+ * @returns The configuration to merge.
23
+ */
24
+ config: () => {
25
+ optimizeDeps: {
26
+ exclude: string[];
27
+ };
28
+ };
29
+ /**
30
+ * Reads the project folder and cache folder once Vite has resolved its configuration.
31
+ *
32
+ * @param config - Vite's resolved configuration.
33
+ */
34
+ configResolved: (config: {
35
+ root: string;
36
+ cacheDir: string;
37
+ }) => Promise<void>;
38
+ /**
39
+ * Watches the project's own icon folders in development, reloading the Studio when an icon is added, changed, or
40
+ * removed.
41
+ *
42
+ * @param server - Vite's development server.
43
+ */
44
+ configureServer: (server: {
45
+ watcher: {
46
+ add: (paths: string[]) => void;
47
+ on: (event: "all", listener: (event: string, file: string) => void) => void;
48
+ };
49
+ moduleGraph: {
50
+ invalidateAll: () => void;
51
+ };
52
+ ws: {
53
+ send: (payload: {
54
+ type: "full-reload";
55
+ }) => void;
56
+ };
57
+ }) => void;
58
+ /** Lists the installed icon names in the plugin's types when a build or dev server starts. */
59
+ buildStart: () => Promise<void>;
60
+ /**
61
+ * Claims the modules each set is loaded from.
62
+ *
63
+ * @param id - The module requested.
64
+ * @returns The module's resolved id, or undefined when it isn't a set.
65
+ */
66
+ resolveId: (id: string) => string | undefined;
67
+ /**
68
+ * Generates the registry in place of the placeholder, and each set's module.
69
+ *
70
+ * @param this - Vite's plugin context, used to watch the files the registry depends on.
71
+ * @param id - The resolved module id.
72
+ * @returns The module's code, or undefined when it isn't the build step's.
73
+ */
74
+ load: (this: {
75
+ addWatchFile?: (file: string) => void;
76
+ }, id: string) => Promise<string | undefined>;
77
+ }
78
+ /**
79
+ * Creates the Vite plugin that converts the project's installed icon libraries when the Studio starts or builds.
80
+ *
81
+ * @param options - Options for the build step.
82
+ * @returns The Vite plugin.
83
+ * @public
84
+ */
85
+ declare function iconLibraries(options?: SanityIconBuildOptions): SanityIconVitePlugin;
86
+ /**
87
+ * Adds the icon build step to a Vite configuration, for the `vite` option in `sanity.cli.ts` or a framework's own
88
+ * Vite settings.
89
+ *
90
+ * @param options - Options for the build step.
91
+ * @returns A function that extends the Vite configuration.
92
+ * @public
93
+ */
94
+ declare function withIcons(options?: SanityIconBuildOptions): <Config extends {
95
+ plugins?: unknown[];
96
+ }>(config: Config) => Config;
97
+ export { withIcons as i, SanityIconVitePlugin as n, iconLibraries as r, SanityIconBuildOptions as t };
98
+ //# sourceMappingURL=vite-ifICG8y9.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vite-ifICG8y9.d.ts","names":["SanityIconBuildOptions","Record","SanityIconVitePlugin","Promise","iconLibraries","withIcons","Config"],"sources":["../src/build/vite.ts"],"mappings":"AAeA;;;;;UAAiBA;;EAEf,SAASC;;;;;;;UAQMC;;EAEf;;;;;;;EAOA;IAAgB;MAAgB;;;;;;;;EAMhC,iBAAiB;IAAU;IAAc;QAAuBC;;;;;;;EAOhE,kBAAkB;IAChB;MACE,MAAM;MACN,KAAK,cAAc,WAAW,eAAe;;IAE/C;MAAe;;IACf;MAAM,OAAO;QAAW;;;;;EAG1B,kBAAkBA;;;;;;;EAOlB,YAAY;;;;;;;;EAQZ,OAAO;IAAQ,gBAAgB;KAAyB,eAAeA;;;;;;;;;iBAazDC,cAAc,UAASJ,yBAA8BE;;;;;;;;;iBAkFrDG,UAAU,UAASL,0BACJ;EAAiB;GAAqB,QAAUM,WAASA"}
package/dist/vite.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ import { i as withIcons, n as SanityIconVitePlugin, r as iconLibraries } from "./vite-ifICG8y9.js";
2
+ export { type SanityIconVitePlugin, iconLibraries, withIcons };
package/dist/vite.js ADDED
@@ -0,0 +1,88 @@
1
+ import { n as logger, r as pluginName } from "./sets-kepuObH8.js";
2
+ import { n as isDefined } from "./utils-COPacfAq.js";
3
+ import { r as isRegistryModule, t as createRegistryModule } from "./registry-B0Dxiwhh.js";
4
+ import { a as writeIconNames, i as loadIconSet, n as detectLibraries, r as listRegistryDependencies, t as describeReport } from "./sets-D5_YGFll.js";
5
+ import path from "node:path";
6
+ /** Prefix of the module each set is loaded from, followed by its library and style. */
7
+ const setPrefix = `virtual:${pluginName}/set/`;
8
+ /**
9
+ * Creates the Vite plugin that converts the project's installed icon libraries when the Studio starts or builds.
10
+ *
11
+ * @param options - Options for the build step.
12
+ * @returns The Vite plugin.
13
+ * @public
14
+ */
15
+ function iconLibraries(options = {}) {
16
+ let root = process.cwd(), cacheDir, libraries = [];
17
+ return {
18
+ name: pluginName,
19
+ config() {
20
+ return { optimizeDeps: { exclude: [`${pluginName}/sets`] } };
21
+ },
22
+ async configResolved(config) {
23
+ ({root, cacheDir} = config), libraries = await detectLibraries(root, options.custom);
24
+ },
25
+ configureServer(server) {
26
+ let folders = Object.values(options.custom ?? {}).map((folder) => path.resolve(root, folder));
27
+ isDefined(folders) && (server.watcher.add(folders), server.watcher.on("all", (_event, file) => {
28
+ folders.some((folder) => file.startsWith(`${folder}${path.sep}`)) && (server.moduleGraph.invalidateAll(), server.ws.send({ type: "full-reload" }));
29
+ }));
30
+ },
31
+ async buildStart() {
32
+ let names = /* @__PURE__ */ new Map(), loaded = await Promise.all(libraries.flatMap((library) => library.styles.map(async ({ style }) => {
33
+ let { set } = await loadIconSet(library, style, {
34
+ root,
35
+ cacheDir
36
+ });
37
+ return {
38
+ library: library.adapter.library,
39
+ set
40
+ };
41
+ })));
42
+ for (let { library, set } of loaded) {
43
+ let libraryNames = names.get(library) ?? /* @__PURE__ */ new Set();
44
+ for (let icon of set.icons) libraryNames.add(icon.name);
45
+ names.set(library, libraryNames);
46
+ }
47
+ await writeIconNames(names);
48
+ },
49
+ resolveId(id) {
50
+ return id.startsWith(setPrefix) ? `\0${id}` : void 0;
51
+ },
52
+ async load(id) {
53
+ if (isRegistryModule(id)) {
54
+ libraries = await detectLibraries(root, options.custom);
55
+ let { files } = listRegistryDependencies(root, libraries);
56
+ for (let file of files) this.addWatchFile?.(file);
57
+ return createRegistryModule(libraries, (key) => `${setPrefix}${key}`);
58
+ }
59
+ if (!id.startsWith(`\0${setPrefix}`)) return;
60
+ let [libraryName, style] = id.slice(`\0${setPrefix}`.length).split("/"), library = libraries.find(({ adapter }) => adapter.library === libraryName);
61
+ if (!isDefined(library) || !isDefined(style)) return;
62
+ let { set, report } = await loadIconSet(library, style, {
63
+ root,
64
+ cacheDir
65
+ });
66
+ return logger.info(describeReport(library.adapter.label, style, report)), `export default JSON.parse(${JSON.stringify(JSON.stringify(set))});`;
67
+ }
68
+ };
69
+ }
70
+ /**
71
+ * Adds the icon build step to a Vite configuration, for the `vite` option in `sanity.cli.ts` or a framework's own
72
+ * Vite settings.
73
+ *
74
+ * @param options - Options for the build step.
75
+ * @returns A function that extends the Vite configuration.
76
+ * @public
77
+ */
78
+ function withIcons(options = {}) {
79
+ return function extendConfig(config) {
80
+ return {
81
+ ...config,
82
+ plugins: [...config.plugins ?? [], iconLibraries(options)]
83
+ };
84
+ };
85
+ }
86
+ export { iconLibraries, withIcons };
87
+
88
+ //# sourceMappingURL=vite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vite.js","names":["path","isDefined","writeIconNames","createRegistryModule","isRegistryModule","DetectedLibrary","describeReport","detectLibraries","listRegistryDependencies","loadIconSet","logger","pluginName","SanityIconBuildOptions","custom","Record","SanityIconVitePlugin","name","config","optimizeDeps","exclude","configResolved","root","cacheDir","Promise","configureServer","server","watcher","add","paths","on","event","listener","file","moduleGraph","invalidateAll","ws","send","payload","type","buildStart","resolveId","id","load","this","addWatchFile","setPrefix","iconLibraries","options","process","cwd","undefined","libraries","folders","Object","values","map","folder","resolve","_event","some","startsWith","sep","names","Map","Set","loaded","all","flatMap","library","styles","style","set","adapter","libraryNames","get","icon","icons","files","key","libraryName","slice","length","split","find","report","info","label","JSON","stringify","withIcons","extendConfig","plugins","Config"],"sources":["../src/build/vite.ts"],"sourcesContent":["import path from \"node:path\";\n\nimport { isDefined } from \"@repo/lib/utils\";\n\nimport { writeIconNames } from \"@/build/names\";\nimport { createRegistryModule, isRegistryModule } from \"@/build/registry\";\nimport type { DetectedLibrary } from \"@/build/sets\";\nimport { describeReport, detectLibraries, listRegistryDependencies, loadIconSet } from \"@/build/sets\";\nimport { logger, pluginName } from \"@/config/defaults\";\n\n/**\n * Options for the build step that converts icon libraries for the Studio.\n *\n * @public\n */\nexport interface SanityIconBuildOptions {\n /** Folders of the project's own SVG icons, keyed by the identifier fields use, such as `{ acme: \"./icons\" }`. */\n custom?: Record<string, string>;\n}\n\n/**\n * A Vite plugin, limited to the hooks the build step uses, so the package doesn't depend on Vite's own types.\n *\n * @public\n */\nexport interface SanityIconVitePlugin {\n /** Name Vite reports the plugin under. */\n name: string;\n /**\n * Keeps the placeholder registry out of Vite's pre-bundling in development, which would fix it in place, while the\n * rest of the plugin and its dependencies are pre-bundled as usual.\n *\n * @returns The configuration to merge.\n */\n config: () => { optimizeDeps: { exclude: string[] } };\n /**\n * Reads the project folder and cache folder once Vite has resolved its configuration.\n *\n * @param config - Vite's resolved configuration.\n */\n configResolved: (config: { root: string; cacheDir: string }) => Promise<void>;\n /**\n * Watches the project's own icon folders in development, reloading the Studio when an icon is added, changed, or\n * removed.\n *\n * @param server - Vite's development server.\n */\n configureServer: (server: {\n watcher: {\n add: (paths: string[]) => void;\n on: (event: \"all\", listener: (event: string, file: string) => void) => void;\n };\n moduleGraph: { invalidateAll: () => void };\n ws: { send: (payload: { type: \"full-reload\" }) => void };\n }) => void;\n /** Lists the installed icon names in the plugin's types when a build or dev server starts. */\n buildStart: () => Promise<void>;\n /**\n * Claims the modules each set is loaded from.\n *\n * @param id - The module requested.\n * @returns The module's resolved id, or undefined when it isn't a set.\n */\n resolveId: (id: string) => string | undefined;\n /**\n * Generates the registry in place of the placeholder, and each set's module.\n *\n * @param this - Vite's plugin context, used to watch the files the registry depends on.\n * @param id - The resolved module id.\n * @returns The module's code, or undefined when it isn't the build step's.\n */\n load: (this: { addWatchFile?: (file: string) => void }, id: string) => Promise<string | undefined>;\n}\n\n/** Prefix of the module each set is loaded from, followed by its library and style. */\nconst setPrefix = `virtual:${pluginName}/set/`;\n\n/**\n * Creates the Vite plugin that converts the project's installed icon libraries when the Studio starts or builds.\n *\n * @param options - Options for the build step.\n * @returns The Vite plugin.\n * @public\n */\nexport function iconLibraries(options: SanityIconBuildOptions = {}): SanityIconVitePlugin {\n let root = process.cwd();\n let cacheDir: string | undefined = undefined;\n let libraries: DetectedLibrary[] = [];\n\n return {\n name: pluginName,\n config() {\n return { optimizeDeps: { exclude: [`${pluginName}/sets`] } };\n },\n async configResolved(config) {\n ({ root, cacheDir } = config);\n libraries = await detectLibraries(root, options.custom);\n },\n configureServer(server) {\n const folders = Object.values(options.custom ?? {}).map((folder) => path.resolve(root, folder));\n if (!isDefined(folders)) return;\n\n server.watcher.add(folders);\n server.watcher.on(\"all\", (_event, file) => {\n if (!folders.some((folder) => file.startsWith(`${folder}${path.sep}`))) return;\n\n server.moduleGraph.invalidateAll();\n server.ws.send({ type: \"full-reload\" });\n });\n },\n async buildStart() {\n const names = new Map<string, Set<string>>();\n const loaded = await Promise.all(\n libraries.flatMap((library) =>\n library.styles.map(async ({ style }) => {\n const { set } = await loadIconSet(library, style, { root, cacheDir });\n\n return { library: library.adapter.library, set };\n }),\n ),\n );\n\n for (const { library, set } of loaded) {\n const libraryNames = names.get(library) ?? new Set<string>();\n\n for (const icon of set.icons) libraryNames.add(icon.name);\n names.set(library, libraryNames);\n }\n\n await writeIconNames(names);\n },\n resolveId(id) {\n return id.startsWith(setPrefix) ? `\\0${id}` : undefined;\n },\n async load(id) {\n if (isRegistryModule(id)) {\n libraries = await detectLibraries(root, options.custom);\n\n // Vite treats watched files as imports in development, so folders are watched by the server instead.\n const { files } = listRegistryDependencies(root, libraries);\n for (const file of files) this.addWatchFile?.(file);\n\n return createRegistryModule(libraries, (key) => `${setPrefix}${key}`);\n }\n if (!id.startsWith(`\\0${setPrefix}`)) return undefined;\n\n const [libraryName, style] = id.slice(`\\0${setPrefix}`.length).split(\"/\");\n const library = libraries.find(({ adapter }) => adapter.library === libraryName);\n if (!isDefined(library) || !isDefined(style)) return undefined;\n\n const { set, report } = await loadIconSet(library, style, { root, cacheDir });\n logger.info(describeReport(library.adapter.label, style, report));\n\n return `export default JSON.parse(${JSON.stringify(JSON.stringify(set))});`;\n },\n };\n}\n\n/**\n * Adds the icon build step to a Vite configuration, for the `vite` option in `sanity.cli.ts` or a framework's own\n * Vite settings.\n *\n * @param options - Options for the build step.\n * @returns A function that extends the Vite configuration.\n * @public\n */\nexport function withIcons(options: SanityIconBuildOptions = {}) {\n return function extendConfig<Config extends { plugins?: unknown[] }>(config: Config): Config {\n return { ...config, plugins: [...(config.plugins ?? []), iconLibraries(options)] };\n };\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,15 +1,22 @@
1
1
  {
2
2
  "name": "@driftime/sanity-plugin-icon",
3
- "version": "0.3.0",
4
- "description": "Lucide icons for Sanity Studio, stored as SVG and rendered without the library.",
3
+ "version": "0.4.1",
4
+ "description": "Icons for Sanity Studio, managed as content by the authors who use them.",
5
5
  "keywords": [
6
+ "central-icons",
7
+ "heroicons",
8
+ "hugeicons",
6
9
  "icon",
7
10
  "icon-picker",
11
+ "iconoir",
8
12
  "icons",
9
13
  "lucide",
14
+ "nucleo",
15
+ "phosphor-icons",
10
16
  "sanity",
11
17
  "sanity-plugin",
12
- "svg"
18
+ "svg",
19
+ "tabler-icons"
13
20
  ],
14
21
  "homepage": "https://github.com/driftime/sanity-plugins/tree/main/packages/icon#readme",
15
22
  "bugs": {
@@ -41,12 +48,42 @@
41
48
  "source": "./src/render.ts",
42
49
  "default": "./dist/render.js"
43
50
  },
51
+ "./vite": {
52
+ "source": "./src/vite.ts",
53
+ "default": "./dist/vite.js"
54
+ },
55
+ "./next": {
56
+ "source": "./src/next.ts",
57
+ "default": "./dist/next.js"
58
+ },
59
+ "./next-loader": {
60
+ "source": "./src/next-loader.ts",
61
+ "default": "./dist/next-loader.js"
62
+ },
63
+ "./read-worker": {
64
+ "source": "./src/read-worker.ts",
65
+ "default": "./dist/read-worker.js"
66
+ },
67
+ "./sets": {
68
+ "source": "./src/sets.ts",
69
+ "default": "./dist/sets.js"
70
+ },
71
+ "./names": {
72
+ "source": "./src/names.ts",
73
+ "default": "./dist/names.js"
74
+ },
44
75
  "./package.json": "./package.json"
45
76
  },
46
77
  "publishConfig": {
47
78
  "exports": {
48
79
  ".": "./dist/index.js",
49
80
  "./render": "./dist/render.js",
81
+ "./vite": "./dist/vite.js",
82
+ "./next": "./dist/next.js",
83
+ "./next-loader": "./dist/next-loader.js",
84
+ "./read-worker": "./dist/read-worker.js",
85
+ "./sets": "./dist/sets.js",
86
+ "./names": "./dist/names.js",
50
87
  "./package.json": "./package.json"
51
88
  },
52
89
  "access": "public"
@@ -54,7 +91,7 @@
54
91
  "scripts": {
55
92
  "typecheck": "tsc",
56
93
  "dev": "plugin-kit link-watch",
57
- "build": "bun run typecheck && plugin-kit verify-package --silent && pkg-utils build --strict --check --clean && node --check dist/index.js && node --check dist/render.js",
94
+ "build": "bun run typecheck && plugin-kit verify-package --silent && pkg-utils build --strict --check --clean && node --check dist/index.js && node --check dist/render.js && node --check dist/vite.js && node --check dist/next.js",
58
95
  "prepublishOnly": "bun run build",
59
96
  "push": "yalc push"
60
97
  },
@@ -62,7 +99,7 @@
62
99
  "@sanity/client": "^7.26.2 || ^8.0.0",
63
100
  "@sanity/icons": "^5.2.1",
64
101
  "@sanity/ui": "^4.0.3",
65
- "lucide-static": "^1.44.0"
102
+ "svgo": "^4.1.0"
66
103
  },
67
104
  "devDependencies": {
68
105
  "@repo/components": "workspace:*",
@@ -1,129 +0,0 @@
1
- import { createElement } from "react";
2
- import { jsx } from "react/jsx-runtime";
3
- import { stegaClean } from "@sanity/client/stega";
4
- /**
5
- * Checks whether a value is defined and non-empty, treating `false`, empty strings, and objects with
6
- * no keys as absent. An array is absent unless one of its elements is itself present, while anything
7
- * built from a class counts as present on existence alone. Not intended for boolean flags.
8
- *
9
- * @param value - The value to check.
10
- * @returns True if the value is defined and not empty.
11
- */
12
- function isDefined(value) {
13
- if (value == null || value === !1) return !1;
14
- if (typeof value == "string") return value.trim() !== "";
15
- if (Array.isArray(value)) return value.some((element) => isDefined(element));
16
- if (typeof value == "object") {
17
- let prototype = Reflect.getPrototypeOf(value);
18
- return prototype !== Object.prototype && prototype !== null || Object.keys(value).length > 0;
19
- }
20
- return !0;
21
- }
22
- /**
23
- * Converts a string between different casing formats.
24
- *
25
- * @param value - The string to convert.
26
- * @param format - The target casing format.
27
- * @returns The converted string.
28
- */
29
- function convertCase(value, format) {
30
- let words = value.replaceAll(/(?<lower>[a-z0-9])(?<upper>[A-Z])/gu, "$<lower> $<upper>").replaceAll(/[-_\s]+/gu, " ").trim().toLowerCase();
31
- switch (format) {
32
- case "kebab": return words.replaceAll(/\s+/gu, "-");
33
- case "snake": return words.replaceAll(/\s+/gu, "_");
34
- case "camel": return words.replaceAll(/\s+(?<character>.)/gu, (_match, character) => character.toUpperCase());
35
- case "pascal": return words.replaceAll(/(?:^|\s+)(?<character>.)/gu, (_match, character) => character.toUpperCase());
36
- case "title": return words.replaceAll(/\b\w/gu, (character) => character.toUpperCase());
37
- case "sentence": return words.replaceAll(/^(?<character>.)/gu, (character) => character.toUpperCase());
38
- default: return value;
39
- }
40
- }
41
- /**
42
- * Checks whether a value can be read by key, narrowing what arrives untyped from outside the plugin.
43
- *
44
- * @param value - The value to check.
45
- * @returns True if the value has keys to read.
46
- */
47
- function isRecord(value) {
48
- return typeof value == "object" && !!value;
49
- }
50
- /** Elements an icon's drawing may be built from, narrowed to those that describe a shape. */
51
- const iconElements = [
52
- "circle",
53
- "ellipse",
54
- "g",
55
- "line",
56
- "path",
57
- "polygon",
58
- "polyline",
59
- "rect"
60
- ], iconRootAttributes = {
61
- xmlns: "http://www.w3.org/2000/svg",
62
- width: 24,
63
- height: 24,
64
- viewBox: "0 0 24 24",
65
- fill: "none",
66
- stroke: "currentColor",
67
- strokeWidth: 2,
68
- strokeLinecap: "round",
69
- strokeLinejoin: "round"
70
- };
71
- /**
72
- * Checks whether a parsed value is an icon's drawing, since it arrives as whatever happened to be
73
- * stored. Shapes are matched against the known elements so nothing else reaches the renderer.
74
- *
75
- * @param value - The value to check.
76
- * @returns True if the value is a drawing.
77
- */
78
- function isIconNode(value) {
79
- return Array.isArray(value) ? value.every((element) => Array.isArray(element) && element.length === 2 && iconElements.some((name) => name === element[0]) && isRecord(element[1])) : !1;
80
- }
81
- /**
82
- * Reads an icon's drawing from an already-parsed value, for a library handing over its drawings as
83
- * data rather than as a document field.
84
- *
85
- * @param value - The value to read.
86
- * @returns The drawing, or undefined when the value is not one.
87
- */
88
- function parseIconNode(value) {
89
- return isIconNode(value) ? value : void 0;
90
- }
91
- /**
92
- * Reads an icon's drawing back from the form it is stored in, clearing the stega characters a Sanity
93
- * fetch leaves behind.
94
- *
95
- * @param value - The stored drawing.
96
- * @returns The drawing, or undefined when nothing readable was stored.
97
- */
98
- function resolveIconNode(value) {
99
- let cleaned = stegaClean(value);
100
- if (isDefined(cleaned)) try {
101
- return parseIconNode(JSON.parse(cleaned));
102
- } catch {
103
- return;
104
- }
105
- }
106
- /**
107
- * Writes an icon's drawing into the form it is stored in, so the shapes survive a round trip through
108
- * a document rather than a component reference that only resolves at build time.
109
- *
110
- * @param node - The drawing to store.
111
- * @returns The drawing ready to store.
112
- */
113
- function serializeIconNode(node) {
114
- return JSON.stringify(node);
115
- }
116
- function Drawing({ node, ...props }) {
117
- return isDefined(node) ? /* @__PURE__ */ jsx("svg", {
118
- ...iconRootAttributes,
119
- "aria-hidden": "true",
120
- ...props,
121
- children: node.map(([element, attributes], index) => createElement(element, {
122
- ...attributes,
123
- key: String(index)
124
- }))
125
- }) : null;
126
- }
127
- export { convertCase as a, serializeIconNode as i, parseIconNode as n, isDefined as o, resolveIconNode as r, Drawing as t };
128
-
129
- //# sourceMappingURL=drawing-BThiR2bN.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"drawing-BThiR2bN.js","names":["Nullable","T","isDefined","value","undefined","trim","Array","isArray","some","element","prototype","Reflect","getPrototypeOf","Object","keys","length","convertCase","format","words","replaceAll","toLowerCase","_match","character","toUpperCase","isRecord","Record","readPath","path","current","segment","isDefined","isRecord","stegaClean","iconElements","const","IconElement","element","attributes","Record","IconNode","iconRootAttributes","xmlns","width","height","viewBox","fill","stroke","strokeWidth","strokeLinecap","strokeLinejoin","isIconNode","value","Array","isArray","every","length","some","name","parseIconNode","undefined","resolveIconNode","cleaned","parsed","JSON","parse","serializeIconNode","node","stringify","isDefined","ComponentProps","createElement","IconNode","iconRootAttributes","DrawingProps","Omit","node","Drawing","props","map","element","attributes","index","key","String"],"sources":["../../@repo/lib/utils.ts","../src/lib/nodes.ts","../src/components/drawing.tsx"],"sourcesContent":["/** A value that may be absent, covering both null and undefined. */\ntype Nullable<T> = T | null | undefined;\n\n/**\n * Checks whether a value is defined and non-empty, treating `false`, empty strings, and objects with\n * no keys as absent. An array is absent unless one of its elements is itself present, while anything\n * built from a class counts as present on existence alone. Not intended for boolean flags.\n *\n * @param value - The value to check.\n * @returns True if the value is defined and not empty.\n */\nexport function isDefined<T>(value: Nullable<T> | false): value is T {\n if (value === undefined || value === null || value === false) return false;\n if (typeof value === \"string\") return value.trim() !== \"\";\n if (Array.isArray(value)) return value.some((element) => isDefined(element));\n\n if (typeof value === \"object\") {\n const prototype = Reflect.getPrototypeOf(value);\n if (prototype !== Object.prototype && prototype !== null) return true;\n\n return Object.keys(value).length > 0;\n }\n\n return true;\n}\n\n/**\n * Converts a string between different casing formats.\n *\n * @param value - The string to convert.\n * @param format - The target casing format.\n * @returns The converted string.\n */\nexport function convertCase(value: string, format: \"kebab\" | \"snake\" | \"camel\" | \"pascal\" | \"title\" | \"sentence\") {\n const words = value\n .replaceAll(/(?<lower>[a-z0-9])(?<upper>[A-Z])/gu, \"$<lower> $<upper>\")\n .replaceAll(/[-_\\s]+/gu, \" \")\n .trim()\n .toLowerCase();\n\n switch (format) {\n case \"kebab\": {\n return words.replaceAll(/\\s+/gu, \"-\");\n }\n case \"snake\": {\n return words.replaceAll(/\\s+/gu, \"_\");\n }\n case \"camel\": {\n return words.replaceAll(/\\s+(?<character>.)/gu, (_match, character: string) => character.toUpperCase());\n }\n case \"pascal\": {\n return words.replaceAll(/(?:^|\\s+)(?<character>.)/gu, (_match, character: string) => character.toUpperCase());\n }\n case \"title\": {\n return words.replaceAll(/\\b\\w/gu, (character) => character.toUpperCase());\n }\n case \"sentence\": {\n return words.replaceAll(/^(?<character>.)/gu, (character) => character.toUpperCase());\n }\n default: {\n return value;\n }\n }\n}\n\n/**\n * Checks whether a value can be read by key, narrowing what arrives untyped from outside the plugin.\n *\n * @param value - The value to check.\n * @returns True if the value has keys to read.\n */\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\n/**\n * Reads a value out of nested records by following a path of keys, so a caller can name something\n * inside a shape it does not otherwise know.\n *\n * @param value - The object to read from.\n * @param path - Keys leading to the value.\n * @returns The value at the path, or undefined when a key is missing or a step holds no keys to read.\n */\nexport function readPath(value: unknown, path: string[]) {\n let current: unknown = value;\n\n for (const segment of path) {\n if (!isRecord(current)) return undefined;\n\n current = current[segment];\n }\n\n return current;\n}\n","import { isDefined, isRecord } from \"@repo/lib/utils\";\nimport { stegaClean } from \"@sanity/client/stega\";\n\n/** Elements an icon's drawing may be built from, narrowed to those that describe a shape. */\nconst iconElements = [\"circle\", \"ellipse\", \"g\", \"line\", \"path\", \"polygon\", \"polyline\", \"rect\"] as const;\n\n/** Single shape in an icon's drawing, paired with the attributes it is drawn with. */\ntype IconElement = [element: (typeof iconElements)[number], attributes: Record<string, string>];\n\n/** An icon's drawing, held as the shapes it is built from rather than as a component. */\nexport type IconNode = IconElement[];\n\n/**\n * Attributes given to the SVG an icon's shapes are drawn inside, mirroring the grid and stroke Lucide\n * draws on. A library working to different conventions would need its own frame, which is why a\n * stored icon carries only what sits inside this one.\n */\nexport const iconRootAttributes = {\n xmlns: \"http://www.w3.org/2000/svg\",\n width: 24,\n height: 24,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 2,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n} as const;\n\n/**\n * Checks whether a parsed value is an icon's drawing, since it arrives as whatever happened to be\n * stored. Shapes are matched against the known elements so nothing else reaches the renderer.\n *\n * @param value - The value to check.\n * @returns True if the value is a drawing.\n */\nfunction isIconNode(value: unknown): value is IconNode {\n if (!Array.isArray(value)) return false;\n\n return value.every(\n (element: unknown) =>\n Array.isArray(element) &&\n element.length === 2 &&\n iconElements.some((name) => name === element[0]) &&\n isRecord(element[1]),\n );\n}\n\n/**\n * Reads an icon's drawing from an already-parsed value, for a library handing over its drawings as\n * data rather than as a document field.\n *\n * @param value - The value to read.\n * @returns The drawing, or undefined when the value is not one.\n */\nexport function parseIconNode(value: unknown) {\n return isIconNode(value) ? value : undefined;\n}\n\n/**\n * Reads an icon's drawing back from the form it is stored in, clearing the stega characters a Sanity\n * fetch leaves behind.\n *\n * @param value - The stored drawing.\n * @returns The drawing, or undefined when nothing readable was stored.\n */\nexport function resolveIconNode(value: string | undefined) {\n const cleaned = stegaClean(value);\n if (!isDefined(cleaned)) return undefined;\n\n try {\n const parsed: unknown = JSON.parse(cleaned);\n\n return parseIconNode(parsed);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Writes an icon's drawing into the form it is stored in, so the shapes survive a round trip through\n * a document rather than a component reference that only resolves at build time.\n *\n * @param node - The drawing to store.\n * @returns The drawing ready to store.\n */\nexport function serializeIconNode(node: IconNode) {\n return JSON.stringify(node);\n}\n","// Runs inside a consumer's server components, where the compiler's memo cache hook cannot.\n\"use no memo\";\n\nimport { isDefined } from \"@repo/lib/utils\";\nimport type { ComponentProps } from \"react\";\nimport { createElement } from \"react\";\n\nimport type { IconNode } from \"@/lib/nodes\";\nimport { iconRootAttributes } from \"@/lib/nodes\";\n\nexport type DrawingProps = Omit<ComponentProps<\"svg\">, \"children\"> & { node: IconNode | undefined };\n\nexport function Drawing({ node, ...props }: DrawingProps) {\n if (!isDefined(node)) return null;\n\n return (\n <svg {...iconRootAttributes} aria-hidden=\"true\" {...props}>\n {node.map(([element, attributes], index) => createElement(element, { ...attributes, key: String(index) }))}\n </svg>\n );\n}\n"],"mappings":";;;;;;;;;;;AAWA,SAAgBE,UAAaC,OAAwC;CACnE,IAAIA,SAAiC,QAAQA,UAAU,IAAO,OAAO;CACrE,IAAI,OAAOA,SAAU,UAAU,OAAOA,MAAME,KAAK,MAAM;CACvD,IAAIC,MAAMC,QAAQJ,KAAK,GAAG,OAAOA,MAAMK,MAAMC,YAAYP,UAAUO,OAAO,CAAC;CAE3E,IAAI,OAAON,SAAU,UAAU;EAC7B,IAAMO,YAAYC,QAAQC,eAAeT,KAAK;EAG9C,OAFIO,cAAcG,OAAOH,aAAaA,cAAc,QAE7CG,OAAOC,KAAKX,KAAK,CAAC,CAACY,SAAS;CACrC;CAEA,OAAO;AACT;;;;;;;;AASA,SAAgBC,YAAYb,OAAec,QAAuE;CAChH,IAAMC,QAAQf,MACXgB,WAAW,uCAAuC,mBAAmB,CAAC,CACtEA,WAAW,aAAa,GAAG,CAAC,CAC5Bd,KAAK,CAAC,CACNe,YAAY;CAEf,QAAQH,QAAR;EACE,KAAK,SACH,OAAOC,MAAMC,WAAW,SAAS,GAAG;EAEtC,KAAK,SACH,OAAOD,MAAMC,WAAW,SAAS,GAAG;EAEtC,KAAK,SACH,OAAOD,MAAMC,WAAW,yBAAyBE,QAAQC,cAAsBA,UAAUC,YAAY,CAAC;EAExG,KAAK,UACH,OAAOL,MAAMC,WAAW,+BAA+BE,QAAQC,cAAsBA,UAAUC,YAAY,CAAC;EAE9G,KAAK,SACH,OAAOL,MAAMC,WAAW,WAAWG,cAAcA,UAAUC,YAAY,CAAC;EAE1E,KAAK,YACH,OAAOL,MAAMC,WAAW,uBAAuBG,cAAcA,UAAUC,YAAY,CAAC;EAEtF,SACE,OAAOpB;CAEX;AACF;;;;;;;AAQA,SAAgBqB,SAASrB,OAAkD;CACzE,OAAO,OAAOA,SAAU,cAAYA;AACtC;;ACrEA,MAAM8B,eAAe;CAAC;CAAU;CAAW;CAAK;CAAQ;CAAQ;CAAW;CAAY;AAAM,GAahFO,qBAAqB;CAChCC,OAAO;CACPC,OAAO;CACPC,QAAQ;CACRC,SAAS;CACTC,MAAM;CACNC,QAAQ;CACRC,aAAa;CACbC,eAAe;CACfC,gBAAgB;AAClB;;;;;;;;AASA,SAASC,WAAWC,OAAmC;CAGrD,OAFKC,MAAMC,QAAQF,KAAK,IAEjBA,MAAMG,OACVlB,YACCgB,MAAMC,QAAQjB,OAAO,KACrBA,QAAQmB,WAAW,KACnBtB,aAAauB,MAAMC,SAASA,SAASrB,QAAQ,EAAE,KAC/CL,SAASK,QAAQ,EAAE,CACvB,IARkC;AASpC;;;;;;;;AASA,SAAgBsB,cAAcP,OAAgB;CAC5C,OAAOD,WAAWC,KAAK,IAAIA,QAAQQ,KAAAA;AACrC;;;;;;;;AASA,SAAgBC,gBAAgBT,OAA2B;CACzD,IAAMU,UAAU7B,WAAWmB,KAAK;CAC3BrB,cAAU+B,OAAO,GAEtB,IAAI;EAGF,OAAOH,cAFiBK,KAAKC,MAAMH,OAEdC,CAAM;CAC7B,QAAQ;EACN;CACF;AACF;;;;;;;;AASA,SAAgBG,kBAAkBC,MAAgB;CAChD,OAAOH,KAAKI,UAAUD,IAAI;AAC5B;AC5EA,SAAgBU,QAAQ,EAAED,MAAM,GAAGE,SAAuB;CAGxD,OAFKT,UAAUO,IAAI,IAGjB,oBAAC,OAAD;EAAK,GAAIH;EAAoB,eAAY;EAAO,GAAIK;EACjDF,UAAAA,KAAKG,KAAK,CAACC,SAASC,aAAaC,UAAUX,cAAcS,SAAS;GAAE,GAAGC;GAAYE,KAAKC,OAAOF,KAAK;EAAE,CAAC,CAAC;CACtG,CAAA,IALsB;AAO/B"}
@@ -1,16 +0,0 @@
1
- /** Type name of the icon object. */
2
- declare const iconTypeName = "icon";
3
- /**
4
- * An icon an author chose, stored as the name it was chosen by alongside the shapes it draws.
5
- *
6
- * @public
7
- */
8
- interface SanityIcon {
9
- _type: typeof iconTypeName;
10
- /** Name the icon goes by in the library it was taken from. */
11
- name?: string;
12
- /** Shapes the icon is drawn from, written when the icon is chosen. */
13
- node?: string;
14
- }
15
- export { iconTypeName as n, SanityIcon as t };
16
- //# sourceMappingURL=types-_D2jGm25.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types-_D2jGm25.d.ts","names":[],"sources":["../src/types.ts"],"mappings":"AACA;cAAa;;;;;;UAOI;EACf,cAAc;;EAEd;;EAEA"}