@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/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
</picture>
|
|
7
7
|
<h1>Icon</h1>
|
|
8
8
|
<p><strong>A Sanity Studio plugin by Driftime®</strong></p>
|
|
9
|
-
<p>
|
|
9
|
+
<p>Icons for Sanity Studio, managed as content by the authors who use them.</p>
|
|
10
10
|
<p>
|
|
11
11
|
<a href="https://www.npmjs.com/package/@driftime/sanity-plugin-icon"><img src="https://img.shields.io/npm/v/@driftime/sanity-plugin-icon?style=flat-square&labelColor=1a1a1a&color=666666" alt="npm version" /></a>
|
|
12
12
|
<a href="https://github.com/driftime/sanity-plugins/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/@driftime/sanity-plugin-icon?style=flat-square&labelColor=1a1a1a&color=666666" alt="License: MIT" /></a>
|
|
@@ -17,9 +17,11 @@
|
|
|
17
17
|
|
|
18
18
|
## Overview
|
|
19
19
|
|
|
20
|
-
Icons are part of a site's visual language, chosen with the same care as its typography and its colors, and Icon makes them part of
|
|
20
|
+
Icons are part of a site's visual language, chosen with the same care as its typography and its colors, and Icon makes them part of the content. It works with the icon library a project installs, such as Lucide, Phosphor, or Central Icon System, or with custom iconography drawn for a brand or a product. In the Studio, that library becomes a field that feels native, and authors search every icon in it to find the one they need.
|
|
21
21
|
|
|
22
|
-
When an
|
|
22
|
+
The real difference is on the site. When an author picks an icon, its drawing is stored on the document, so the front end needs no icon library at all. There's no package of icon components to import and no icons to bundle, only one small component that draws whatever the CMS sends, on the server or in the browser.
|
|
23
|
+
|
|
24
|
+
The Studio is just as light. The plugin ships no icons of its own and reads the icon library while the Studio builds, so a picker stays fast with a hundred icons or several thousand.
|
|
23
25
|
|
|
24
26
|
<br />
|
|
25
27
|
|
|
@@ -27,32 +29,140 @@ When an icon is chosen, its drawing is stored on the document alongside its name
|
|
|
27
29
|
<picture>
|
|
28
30
|
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/driftime/sanity-plugins/HEAD/packages/icon/assets/icon-selector-dark.png" />
|
|
29
31
|
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/driftime/sanity-plugins/HEAD/packages/icon/assets/icon-selector-light.png" />
|
|
30
|
-
<img src="https://raw.githubusercontent.com/driftime/sanity-plugins/HEAD/packages/icon/assets/icon-selector-light.png" alt="The icon picker open in Sanity Studio, showing a search field above a scrolling grid of
|
|
32
|
+
<img src="https://raw.githubusercontent.com/driftime/sanity-plugins/HEAD/packages/icon/assets/icon-selector-light.png" alt="The icon picker open in Sanity Studio, showing a search field above a scrolling grid of Lucide icons" />
|
|
31
33
|
</picture>
|
|
32
|
-
<p align="center"><sub><em>The icon picker, with
|
|
34
|
+
<p align="center"><sub><em>The icon picker, with all 1,854 Lucide icons in one searchable grid.</em></sub></p>
|
|
33
35
|
</figure>
|
|
34
36
|
|
|
35
37
|
<br />
|
|
36
38
|
|
|
37
39
|
## Installation
|
|
38
40
|
|
|
39
|
-
Icon is built for Sanity Studio 6.10 and React 19 and declares both as peer dependencies, so the Studio needs to be on those versions already. Node
|
|
41
|
+
Icon is built for Sanity Studio 6.10 and React 19 and declares both as peer dependencies, so the Studio needs to be on those versions already. Node 20.19 or later is required, or 22.12 or later on Node 22.
|
|
40
42
|
|
|
41
43
|
```bash
|
|
42
44
|
bun add -E @driftime/sanity-plugin-icon
|
|
43
45
|
```
|
|
44
46
|
|
|
47
|
+
Each icon library a field uses is installed alongside it, as described in [Installing an Icon Library](#installing-an-icon-library).
|
|
48
|
+
|
|
45
49
|
<br />
|
|
46
50
|
|
|
47
51
|
## Studio
|
|
48
52
|
|
|
49
|
-
In the Studio, the plugin registers an `icon` type
|
|
53
|
+
In the Studio, the plugin registers an `icon` type, takes the icon library every field offers, and adds a step to the Studio's build that reads the installed icon libraries.
|
|
54
|
+
|
|
55
|
+
<br />
|
|
56
|
+
|
|
57
|
+
### Adding the Build Step
|
|
58
|
+
|
|
59
|
+
The build step reads every installed icon library when the Studio starts or builds, and converts each one into the form the picker and the site use. It runs inside the bundler that builds the Studio, so it's added to that bundler's configuration. The icon libraries never become part of the Studio's own code.
|
|
60
|
+
|
|
61
|
+
Each conversion is cached inside `node_modules`, so an icon library is only converted again when its version changes. Changes to icon libraries and to the project's own icons apply while the Studio runs, with no restart.
|
|
62
|
+
|
|
63
|
+
The build step also writes the names of the installed icons into the plugin's own type declarations, so options are checked against them. Nothing is written to the project itself.
|
|
64
|
+
|
|
65
|
+
<br />
|
|
66
|
+
|
|
67
|
+
#### Standalone Studio
|
|
68
|
+
|
|
69
|
+
A standalone Studio is built with Vite. `withIcons` extends its `vite` option in `sanity.cli.ts`.
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
import { withIcons } from "@driftime/sanity-plugin-icon/vite";
|
|
73
|
+
import { defineCliConfig } from "sanity/cli";
|
|
74
|
+
|
|
75
|
+
export default defineCliConfig({
|
|
76
|
+
// ...
|
|
77
|
+
vite: withIcons(),
|
|
78
|
+
});
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
<br />
|
|
82
|
+
|
|
83
|
+
#### Next.js
|
|
84
|
+
|
|
85
|
+
A Studio embedded in a Next.js app is built by Next.js, with Turbopack or webpack. `withIcons` wraps the app's configuration in `next.config.ts`.
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
import { withIcons } from "@driftime/sanity-plugin-icon/next";
|
|
89
|
+
import type { NextConfig } from "next";
|
|
90
|
+
|
|
91
|
+
const config: NextConfig = {
|
|
92
|
+
// ...
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export default withIcons()(config);
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
<br />
|
|
99
|
+
|
|
100
|
+
#### Other Vite Frameworks
|
|
101
|
+
|
|
102
|
+
A Studio embedded in another Vite-based framework, such as React Router, TanStack Start, or Astro, adds `iconLibraries` to that framework's Vite plugins.
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
import { iconLibraries } from "@driftime/sanity-plugin-icon/vite";
|
|
106
|
+
|
|
107
|
+
export default defineConfig({
|
|
108
|
+
// ...
|
|
109
|
+
plugins: [
|
|
110
|
+
// ...
|
|
111
|
+
iconLibraries(),
|
|
112
|
+
],
|
|
113
|
+
});
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
<br />
|
|
117
|
+
|
|
118
|
+
#### Build Options
|
|
119
|
+
|
|
120
|
+
`withIcons` and `iconLibraries` accept the same options.
|
|
121
|
+
|
|
122
|
+
| Option | Type | Default | Purpose |
|
|
123
|
+
| -------- | ------------------------ | ------- | --------------------------------------------------------------------------------------------------------------------------------- |
|
|
124
|
+
| `custom` | `Record<string, string>` | none | Folders of the project's own SVG icons, keyed by icon library identifier. See [The Project's Own Icons](#the-projects-own-icons). |
|
|
125
|
+
|
|
126
|
+
<br />
|
|
127
|
+
|
|
128
|
+
### Choosing an Icon Library
|
|
129
|
+
|
|
130
|
+
The plugin reads eight published icon libraries. Each has an identifier, which the plugin and its fields use to name it, and one or more styles.
|
|
131
|
+
|
|
132
|
+
| Icon library | Identifier | Package | Styles | Keywords |
|
|
133
|
+
| -------------------------------------------------- | ----------- | ------------------------------ | ------------------------------------------------------------------- | -------- |
|
|
134
|
+
| [Central Icon System](https://iconists.co/central) | `central` | `@central-icons-react/<style>` | One package per style, such as `round-outlined-radius-2-stroke-1.5` | yes |
|
|
135
|
+
| [Heroicons](https://heroicons.com) | `heroicons` | `heroicons` | `outline`, `solid`, `mini`, `micro` | no |
|
|
136
|
+
| [Hugeicons](https://hugeicons.com) | `hugeicons` | `@hugeicons/core-free-icons` | `stroke-rounded` | no |
|
|
137
|
+
| [Iconoir](https://iconoir.com) | `iconoir` | `iconoir` | `regular`, `solid` | no |
|
|
138
|
+
| [Lucide](https://lucide.dev) | `lucide` | `lucide-static` | `default` | yes |
|
|
139
|
+
| [Nucleo](https://nucleoapp.com) | `nucleo` | `nucleo-<style>` | One package per style, such as `ui-outline-18` | no |
|
|
140
|
+
| [Phosphor Icons](https://phosphoricons.com) | `phosphor` | `@phosphor-icons/core` | `regular`, `thin`, `light`, `bold`, `fill`, `duotone` | yes |
|
|
141
|
+
| [Tabler Icons](https://tabler.io/icons) | `tabler` | `@tabler/icons` | `outline`, `filled` | yes |
|
|
142
|
+
|
|
143
|
+
Search always matches an icon's name. Some icon libraries also publish keywords for their icons, which is how a search for "next" finds an arrow. The Keywords column shows which ones do, and the others match by name alone.
|
|
144
|
+
|
|
145
|
+
Central Icon System and Nucleo are commercial icon libraries, installed under the license their own documentation describes. Both publish one package per style, and each package the project installs becomes one of the icon library's styles.
|
|
146
|
+
|
|
147
|
+
<br />
|
|
148
|
+
|
|
149
|
+
### Installing an Icon Library
|
|
150
|
+
|
|
151
|
+
Each icon library is installed from the package listed for it in [Choosing an Icon Library](#choosing-an-icon-library). Only the build step reads the package, so it can be a dev dependency and never reaches the site.
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
bun add -D -E lucide-static
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
It has to be that exact package, even in a project that already uses the icon library some other way. Framework packages such as `lucide-react` or `@phosphor-icons/vue` contain components rather than SVG files, so the plugin can't read icons from them.
|
|
158
|
+
|
|
159
|
+
The package also has to be listed in the project's own `package.json`. A copy that another dependency happens to install is ignored, so the icons in the Studio always come from the version the project chose.
|
|
50
160
|
|
|
51
161
|
<br />
|
|
52
162
|
|
|
53
163
|
### Registering the Plugin
|
|
54
164
|
|
|
55
|
-
|
|
165
|
+
The plugin needs to know which icon library its fields offer. Register it with that icon library's identifier.
|
|
56
166
|
|
|
57
167
|
```typescript
|
|
58
168
|
import { defineConfig } from "sanity";
|
|
@@ -62,20 +172,22 @@ export default defineConfig({
|
|
|
62
172
|
// ...
|
|
63
173
|
plugins: [
|
|
64
174
|
// ...
|
|
65
|
-
iconPlugin(),
|
|
175
|
+
iconPlugin({ library: "lucide" }),
|
|
66
176
|
],
|
|
67
177
|
});
|
|
68
178
|
```
|
|
69
179
|
|
|
70
|
-
| Option
|
|
71
|
-
|
|
|
72
|
-
| `
|
|
180
|
+
| Option | Type | Default | Purpose |
|
|
181
|
+
| --------- | ------------------- | ------------------- | --------------------------------------------------------------------------------------------------- |
|
|
182
|
+
| `library` | `SanityIconLibrary` | required | The icon library every field offers, unless a field names its own. |
|
|
183
|
+
| `style` | `SanityIconStyle` | the library's first | The icon library's style. See [Choosing a Style](#choosing-a-style). |
|
|
184
|
+
| `icons` | `SanityIconName[]` | all | Icons every field offers, in the order listed. See [Restricting the Icons](#restricting-the-icons). |
|
|
73
185
|
|
|
74
186
|
<br />
|
|
75
187
|
|
|
76
188
|
### Adding an Icon Field
|
|
77
189
|
|
|
78
|
-
A field of type `icon` is defined like any other.
|
|
190
|
+
A field of type `icon` is defined like any other, and offers the plugin's icon library.
|
|
79
191
|
|
|
80
192
|
```typescript
|
|
81
193
|
defineField({
|
|
@@ -85,43 +197,72 @@ defineField({
|
|
|
85
197
|
});
|
|
86
198
|
```
|
|
87
199
|
|
|
88
|
-
| Option
|
|
89
|
-
|
|
|
90
|
-
| `
|
|
200
|
+
| Option | Type | Default | Purpose |
|
|
201
|
+
| --------- | ------------------- | ------------------- | ----------------------------------------------------------- |
|
|
202
|
+
| `library` | `SanityIconLibrary` | the plugin's | The icon library this field offers. |
|
|
203
|
+
| `style` | `SanityIconStyle` | the library's first | The icon library's style. Only set together with `library`. |
|
|
204
|
+
| `icons` | `SanityIconName[]` | all | Icons this field offers. Only set together with `library`. |
|
|
205
|
+
|
|
206
|
+
A field that names an icon library **replaces** the plugin's icon library, style, and icons, and a field that doesn't uses all three of the plugin's. So a field can offer a different icon library from the rest of the Studio, for example one of the project's own.
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
defineField({
|
|
210
|
+
name: "badge",
|
|
211
|
+
type: "icon",
|
|
212
|
+
description: "Badge shown on the product card.",
|
|
213
|
+
options: { library: "phosphor", style: "duotone" },
|
|
214
|
+
});
|
|
215
|
+
```
|
|
91
216
|
|
|
92
217
|
The type name is always `icon`, so a Studio that already has a type by that name needs to rename it before installing.
|
|
93
218
|
|
|
94
219
|
<br />
|
|
95
220
|
|
|
221
|
+
### Choosing a Style
|
|
222
|
+
|
|
223
|
+
An icon library that draws its icons in several ways, such as Phosphor's weights or Heroicons' sizes, offers each as a style. A style is chosen with the icon library, and without one the icon library's first style is used.
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
iconPlugin({
|
|
227
|
+
library: "phosphor",
|
|
228
|
+
style: "bold",
|
|
229
|
+
});
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Styles are typed against the icon library, so `style: "bold"` is accepted for Phosphor and rejected for Lucide. Each style is its own set, with its own search results and its own recent icons.
|
|
233
|
+
|
|
234
|
+
<br />
|
|
235
|
+
|
|
96
236
|
### Restricting the Icons
|
|
97
237
|
|
|
98
|
-
A field offers the whole library unless restricted, and most sites want a smaller set. Pass the icons the site uses to the plugin, and every field offers those, in the order they
|
|
238
|
+
A field offers the whole icon library unless restricted, and most sites want a smaller set. Pass the icons the site uses to the plugin, and every field offers those, in the order they're listed.
|
|
99
239
|
|
|
100
240
|
```typescript
|
|
101
241
|
iconPlugin({
|
|
242
|
+
library: "lucide",
|
|
102
243
|
icons: ["sun", "wind", "droplets", "leaf", "sprout", "mountain", "tent", "compass"],
|
|
103
244
|
});
|
|
104
245
|
```
|
|
105
246
|
|
|
106
|
-
A single field sometimes needs a list of its own, for example a contact card whose icon should only ever be a mail, phone, or globe symbol. Pass `icons` in the field's `options
|
|
247
|
+
A single field sometimes needs a list of its own, for example a contact card whose icon should only ever be a mail, phone, or globe symbol. Pass `icons` in the field's `options`, with its icon library.
|
|
107
248
|
|
|
108
249
|
```typescript
|
|
109
250
|
defineField({
|
|
110
251
|
name: "icon",
|
|
111
252
|
type: "icon",
|
|
112
253
|
description: "Icon shown beside the contact method.",
|
|
113
|
-
options: { icons: ["mail", "phone", "globe"] },
|
|
254
|
+
options: { library: "lucide", icons: ["mail", "phone", "globe"] },
|
|
114
255
|
});
|
|
115
256
|
```
|
|
116
257
|
|
|
117
|
-
A
|
|
258
|
+
A name the installed release doesn't have is skipped, and restricting a field later is safe, because a stored icon carries its own drawing and still renders when the picker no longer offers it.
|
|
118
259
|
|
|
119
|
-
Names are typed against the
|
|
260
|
+
Names are typed against the release installed in the project, so they complete as they're typed, once the build step has run. A list shared between the plugin and a field, or between several fields, is typed with `SanityIconName` and the icon library's identifier.
|
|
120
261
|
|
|
121
262
|
```typescript
|
|
122
263
|
import type { SanityIconName } from "@driftime/sanity-plugin-icon";
|
|
123
264
|
|
|
124
|
-
export const contactIcons: SanityIconName[] = ["mail", "phone", "globe"];
|
|
265
|
+
export const contactIcons: SanityIconName<"lucide">[] = ["mail", "phone", "globe"];
|
|
125
266
|
```
|
|
126
267
|
|
|
127
268
|
<br />
|
|
@@ -130,13 +271,60 @@ export const contactIcons: SanityIconName[] = ["mail", "phone", "globe"];
|
|
|
130
271
|
<picture>
|
|
131
272
|
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/driftime/sanity-plugins/HEAD/packages/icon/assets/icon-search-dark.png" />
|
|
132
273
|
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/driftime/sanity-plugins/HEAD/packages/icon/assets/icon-search-light.png" />
|
|
133
|
-
<img src="https://raw.githubusercontent.com/driftime/sanity-plugins/HEAD/packages/icon/assets/icon-search-light.png" alt="The icon picker filtered by the search term next, showing
|
|
274
|
+
<img src="https://raw.githubusercontent.com/driftime/sanity-plugins/HEAD/packages/icon/assets/icon-search-light.png" alt="The icon picker filtered by the search term next, showing the icons whose names or tags match it" />
|
|
134
275
|
</picture>
|
|
135
|
-
<p align="center"><sub><em>Search matches an icon's name and the terms Lucide tags it with, so "next" finds
|
|
276
|
+
<p align="center"><sub><em>Search matches an icon's name and the terms Lucide tags it with, so "next" also finds arrow and skip icons.</em></sub></p>
|
|
136
277
|
</figure>
|
|
137
278
|
|
|
138
279
|
<br />
|
|
139
280
|
|
|
281
|
+
### The Project's Own Icons
|
|
282
|
+
|
|
283
|
+
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.
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
export default defineCliConfig({
|
|
287
|
+
// ...
|
|
288
|
+
vite: withIcons({ custom: { acme: "./icons" } }),
|
|
289
|
+
});
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
defineField({
|
|
294
|
+
name: "mark",
|
|
295
|
+
type: "icon",
|
|
296
|
+
description: "Brand mark shown in the footer.",
|
|
297
|
+
options: { library: "acme" },
|
|
298
|
+
});
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
Each SVG file directly inside the folder becomes an icon named after the file, so `Rocket_Launch.svg` is `rocket-launch`. Subfolders aren't read, and the icon library has one style, `default`.
|
|
302
|
+
|
|
303
|
+
Each file is cleaned the same way as an icon from a published icon library: minified, with its identifiers made unique to the icon, and with scripts, event handlers, and titles removed. A file that can't be read, or that embeds or loads something an icon can't safely hold, such as an image, is skipped, and the build log names it and says why.
|
|
304
|
+
|
|
305
|
+
<br />
|
|
306
|
+
|
|
307
|
+
#### Keywords
|
|
308
|
+
|
|
309
|
+
Keywords for search go in a `keywords.json` file inside the same folder, next to the SVG files.
|
|
310
|
+
|
|
311
|
+
```text
|
|
312
|
+
icons/
|
|
313
|
+
├── keywords.json
|
|
314
|
+
├── Rocket_Launch.svg
|
|
315
|
+
└── ...
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
The file maps each icon's name to its keywords. It's optional, and an icon it doesn't list is still found by its name.
|
|
319
|
+
|
|
320
|
+
```json
|
|
321
|
+
{
|
|
322
|
+
"rocket-launch": ["start", "space", "launch"]
|
|
323
|
+
}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
<br />
|
|
327
|
+
|
|
140
328
|
### Document Previews
|
|
141
329
|
|
|
142
330
|
A document's preview shows the icon its type was given in the schema, which is the same for every document of that type. `createIconPreview` shows the icon the author chose instead. Pass it the stored value in `prepare`.
|
|
@@ -159,28 +347,15 @@ When nothing readable is stored, it returns `undefined` and the preview falls ba
|
|
|
159
347
|
|
|
160
348
|
<br />
|
|
161
349
|
|
|
162
|
-
### Keeping the Library Current
|
|
163
|
-
|
|
164
|
-
The plugin depends on Lucide with a caret range, so a newer release installs without a plugin release. The project's lockfile pins whichever release was installed, and there are two ways to move it forward. Removing and re-adding the plugin resolves the range again.
|
|
165
|
-
|
|
166
|
-
```bash
|
|
167
|
-
bun remove @driftime/sanity-plugin-icon
|
|
168
|
-
bun add -E @driftime/sanity-plugin-icon
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
Adding `lucide-static` to the project's own dependencies puts the release under the project's control, and the plugin resolves to that copy from then on.
|
|
172
|
-
|
|
173
|
-
<br />
|
|
174
|
-
|
|
175
350
|
## Site
|
|
176
351
|
|
|
177
|
-
On the site, one component draws a stored icon, and it
|
|
352
|
+
On the site, one component draws a stored icon, and it's 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.
|
|
178
353
|
|
|
179
354
|
<br />
|
|
180
355
|
|
|
181
356
|
### Rendering Icons
|
|
182
357
|
|
|
183
|
-
`Icon` draws the
|
|
358
|
+
`Icon` draws the drawing held in the stored value, and it's the only icon code the site ships, whichever icon library the icon came from. The markup is a plain `svg` element, rendered on the server or the client alike, and the component renders nothing when the value is missing or unreadable.
|
|
184
359
|
|
|
185
360
|
```tsx
|
|
186
361
|
import { Icon } from "@driftime/sanity-plugin-icon/render";
|
|
@@ -205,12 +380,14 @@ export function Feature({ icon, title }: FeatureProps) {
|
|
|
205
380
|
| ------- | ------------------------- | ------------------------------------------------------ |
|
|
206
381
|
| `value` | `SanityIcon \| undefined` | The stored icon. Required, though it may hold nothing. |
|
|
207
382
|
|
|
208
|
-
Every other prop is an `svg` element's and is spread onto the root element after the
|
|
383
|
+
Every other prop is an `svg` element's and is spread onto the root element after the icon's own attributes, so `className` and `style` apply. The icon keeps the frame and paint its icon library drew it with, so an icon drawn in `currentColor` takes the surrounding text color, and a full-color icon keeps its own colors. It's `aria-hidden`, so assistive technology treats it as decoration beside its text, and an icon that carries meaning on its own takes `aria-hidden={false}` and an `aria-label`.
|
|
209
384
|
|
|
210
385
|
```tsx
|
|
211
386
|
<Icon value={link.icon} aria-hidden={false} aria-label="Opens in a new tab" />
|
|
212
387
|
```
|
|
213
388
|
|
|
389
|
+
A stored drawing is checked before it's drawn, and one holding anything that could run code or load something from outside the icon renders nothing.
|
|
390
|
+
|
|
214
391
|
<br />
|
|
215
392
|
|
|
216
393
|
### Querying
|
|
@@ -244,41 +421,56 @@ export interface SanityFeature {
|
|
|
244
421
|
```json
|
|
245
422
|
{
|
|
246
423
|
"_type": "icon",
|
|
424
|
+
"library": "lucide",
|
|
425
|
+
"style": "default",
|
|
247
426
|
"name": "house",
|
|
248
|
-
"node": "[[\"path\",{\"d\":\"M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8\"}],[\"path\",{\"d\":\"M3 10a2 2 0 0 1 .709-1.528l7-6a2 2 0 0 1 2.582 0l7 6A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z\"}]]"
|
|
427
|
+
"node": "{\"root\":{\"fill\":\"none\",\"stroke\":\"currentColor\",\"strokeLinecap\":\"round\",\"strokeLinejoin\":\"round\",\"strokeWidth\":\"2\",\"viewBox\":\"0 0 24 24\"},\"node\":[[\"path\",{\"d\":\"M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8\"}],[\"path\",{\"d\":\"M3 10a2 2 0 0 1 .709-1.528l7-6a2 2 0 0 1 2.582 0l7 6A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z\"}]]}"
|
|
249
428
|
}
|
|
250
429
|
```
|
|
251
430
|
|
|
252
|
-
| Field
|
|
253
|
-
|
|
|
254
|
-
| `_type`
|
|
255
|
-
| `
|
|
256
|
-
| `
|
|
431
|
+
| Field | Type | Purpose |
|
|
432
|
+
| --------- | -------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
|
433
|
+
| `_type` | `string` | Always `icon`. |
|
|
434
|
+
| `library` | `string` | The identifier of the icon library the icon was chosen from. |
|
|
435
|
+
| `style` | `string` | The style it was chosen from. Absent when the field didn't name one, so the icon library's first style was used. |
|
|
436
|
+
| `name` | `string` | The icon's name in its icon library. |
|
|
437
|
+
| `node` | `string` | The icon's drawing as JSON: the attributes of its `svg` element and the elements inside it. Written when the icon is chosen. |
|
|
257
438
|
|
|
258
|
-
|
|
439
|
+
The drawing is written with the name, which is what lets an icon render without its icon library. A stored icon with a name but no drawing fails validation with a prompt to select it again, so a document can't be published with an icon that renders as nothing.
|
|
259
440
|
|
|
260
441
|
<br />
|
|
261
442
|
|
|
262
443
|
### API
|
|
263
444
|
|
|
264
|
-
| Export | Import from | Purpose
|
|
265
|
-
| -------------------------- | ------------------------------------- |
|
|
266
|
-
| `iconPlugin(config
|
|
267
|
-
| `createIconPreview(value)` | `@driftime/sanity-plugin-icon` | Builds preview media from a stored icon.
|
|
268
|
-
| `
|
|
445
|
+
| Export | Import from | Purpose |
|
|
446
|
+
| -------------------------- | ------------------------------------- | -------------------------------------------------------- |
|
|
447
|
+
| `iconPlugin(config)` | `@driftime/sanity-plugin-icon` | Registers the `icon` type. |
|
|
448
|
+
| `createIconPreview(value)` | `@driftime/sanity-plugin-icon` | Builds preview media from a stored icon. |
|
|
449
|
+
| `withIcons(options?)` | `@driftime/sanity-plugin-icon/vite` | Adds the build step to the `vite` option of a Studio. |
|
|
450
|
+
| `iconLibraries(options?)` | `@driftime/sanity-plugin-icon/vite` | The build step as a Vite plugin, for a framework's list. |
|
|
451
|
+
| `withIcons(options?)` | `@driftime/sanity-plugin-icon/next` | Adds the build step to a Next.js configuration. |
|
|
452
|
+
| `Icon` | `@driftime/sanity-plugin-icon/render` | Draws a stored icon. |
|
|
269
453
|
|
|
270
454
|
<br />
|
|
271
455
|
|
|
272
456
|
### Types
|
|
273
457
|
|
|
274
|
-
| Type
|
|
275
|
-
|
|
|
276
|
-
| `SanityIconConfig`
|
|
277
|
-
| `SanityIconOptions`
|
|
278
|
-
| `SanityIconDefinition`
|
|
279
|
-
| `
|
|
280
|
-
| `
|
|
281
|
-
| `
|
|
458
|
+
| Type | Import from | Purpose |
|
|
459
|
+
| ----------------------------- | ------------------------------------- | --------------------------------------------------------------------- |
|
|
460
|
+
| `SanityIconConfig` | `@driftime/sanity-plugin-icon` | Everything `iconPlugin` accepts. |
|
|
461
|
+
| `SanityIconOptions` | `@driftime/sanity-plugin-icon` | The `options` an icon field accepts. |
|
|
462
|
+
| `SanityIconDefinition` | `@driftime/sanity-plugin-icon` | A field or array member of type `icon`. |
|
|
463
|
+
| `SanityIconSelection` | `@driftime/sanity-plugin-icon` | An icon library with a style and icons checked against it. |
|
|
464
|
+
| `SanityIconLibrary` | `@driftime/sanity-plugin-icon` | The identifier of a supported icon library. |
|
|
465
|
+
| `SanityIconStyle` | `@driftime/sanity-plugin-icon` | The styles of an icon library, given its identifier. |
|
|
466
|
+
| `SanityIconName` | `@driftime/sanity-plugin-icon` | The names of an icon library's installed icons, given its identifier. |
|
|
467
|
+
| `SanityIconBuildOptions` | `@driftime/sanity-plugin-icon` | Everything the build step accepts. |
|
|
468
|
+
| `SanityIconVitePlugin` | `@driftime/sanity-plugin-icon/vite` | What `iconLibraries` returns. |
|
|
469
|
+
| `SanityIconNextConfig` | `@driftime/sanity-plugin-icon/next` | The parts of a Next.js configuration the build step extends. |
|
|
470
|
+
| `SanityIconWebpackConfig` | `@driftime/sanity-plugin-icon/next` | The parts of a webpack configuration the build step extends. |
|
|
471
|
+
| `SanityIconWebpackCustomizer` | `@driftime/sanity-plugin-icon/next` | A Next.js `webpack` option the build step runs first. |
|
|
472
|
+
| `SanityIconProps` | `@driftime/sanity-plugin-icon/render` | Everything `Icon` accepts: an `svg` element's props and `value`. |
|
|
473
|
+
| `SanityIcon` | `@driftime/sanity-plugin-icon/render` | A stored icon, with its icon library, its name, and its drawing. |
|
|
282
474
|
|
|
283
475
|
<br />
|
|
284
476
|
|
|
@@ -290,7 +482,7 @@ MIT © [Driftime®](https://driftime.com). See [LICENSE](https://github.com/drif
|
|
|
290
482
|
|
|
291
483
|
## Acknowledgements
|
|
292
484
|
|
|
293
|
-
|
|
485
|
+
The plugin ships no icons. Each icon library is installed by the project under its own license: [Lucide](https://lucide.dev) under the ISC License, [Heroicons](https://heroicons.com), [Hugeicons](https://hugeicons.com)' free set, [Iconoir](https://iconoir.com), [Phosphor Icons](https://phosphoricons.com), and [Tabler Icons](https://tabler.io/icons) under the MIT License, and [Central Icon System](https://iconists.co/central) and [Nucleo](https://nucleoapp.com) under their commercial licenses. Icons for the Studio's own controls come from `@sanity/icons`, so they match the rest of the Studio.
|
|
294
486
|
|
|
295
487
|
<br />
|
|
296
488
|
<br />
|