@sanity/presets 0.1.0 → 0.3.0

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 CHANGED
@@ -1,18 +1,446 @@
1
1
  # @sanity/presets
2
2
 
3
- > **This package is under active development and is not ready for use.**
4
- > The API is unstable and will change without notice. Do not install it as a dependency.
3
+ ## Overview
5
4
 
6
- ## Status
5
+ `@sanity/presets` provides ready-made helpers for creating schema types for common content patterns in Sanity Studio. Instead of modelling pages, links, images, and metadata from scratch, call a `define<Type>` function and get a working schema type with sensible defaults.
7
6
 
8
- This plugin is a work in progress. There are no stable APIs, no published releases intended for production, and no guarantees of backward compatibility.
7
+ **Included presets:**
9
8
 
10
- When the package is ready, this README will be updated with installation and usage instructions.
9
+ - `definePage` document type for page building (content blocks, slug, SEO metadata)
10
+ - `defineLink` — internal and external links with conditional fields
11
+ - `defineCta` — call-to-action with an inline link and semantic importance level
12
+ - `defineSeo` — search engine metadata (title, description, Open Graph image)
13
+ - `defineImage` — image with optional alt text, caption, and hotspot
14
+ - `defineRichText` — Portable Text with link annotations, image blocks, and CTA inline objects; embedded objects default on, opt out with `objects: false` or `objects: {link: false}`
11
15
 
12
- ## Do not use this package
16
+ **When to use presets:**
13
17
 
14
- - It is not published to npm as a usable release
15
- - It contains no stable public API
16
- - It will change without notice
18
+ - You want opinionated defaults to get started quickly.
19
+ - You don't yet have a need for highly custom content modelling.
20
+ - You have not chosen to use LLMs for schema generation.
17
21
 
18
- Check back later, or watch the repository for updates.
22
+ Presets are designed to be extended — add fields, groups, and map hooks as your needs evolve. When a preset no longer fits, replace it with your own schema type using `defineType` directly.
23
+
24
+ ## Installation
25
+
26
+ **Prerequisites:** A Sanity Studio project with `sanity` installed. See the [getting started guide](https://www.sanity.io/docs/getting-started) if you're starting from scratch.
27
+
28
+ ```sh
29
+ npm install @sanity/presets
30
+ ```
31
+
32
+ ```sh
33
+ pnpm add @sanity/presets
34
+ ```
35
+
36
+ ```sh
37
+ yarn add @sanity/presets
38
+ ```
39
+
40
+ Import `createPresetsRegistry` and create a registry instance. The registry returns `define<Type>` functions that produce schema types:
41
+
42
+ ```ts
43
+ import {createPresetsRegistry} from '@sanity/presets'
44
+
45
+ const {defineLink, defineCta, defineSeo, defineImage, definePage} = createPresetsRegistry({
46
+ link: {
47
+ internalTypes: ['page', 'post'],
48
+ },
49
+ })
50
+ ```
51
+
52
+ The `define<Type>` functions are used directly in your `schema.types` configuration, alongside standard `defineType` and `defineField` calls:
53
+
54
+ ```ts
55
+ import {defineConfig} from 'sanity'
56
+
57
+ export default defineConfig({
58
+ // ...
59
+ schema: {
60
+ types: [
61
+ definePage({
62
+ name: 'marketingPage',
63
+ title: 'Marketing Page',
64
+ // Each page builder block must be a type you've defined in your
65
+ // schema. See "Use presets alongside custom types" for more.
66
+ pageBuilderBlocks: ['hero', 'featureGrid'],
67
+ }),
68
+ // your other types...
69
+ ],
70
+ },
71
+ })
72
+ ```
73
+
74
+ ## Concepts
75
+
76
+ ### Registry
77
+
78
+ The **presets registry** is the entry point to `@sanity/presets`. Call `createPresetsRegistry()` to get a set of `define<Type>` functions that produce schema types.
79
+
80
+ The registry serves two purposes:
81
+
82
+ 1. **Global configuration.** Presets can be configured at the registry level, providing defaults that apply everywhere a preset is used. For example, configuring `link.internalTypes` once means every link — whether standalone, inside a CTA, or inside rich text — knows which document types are available for internal links.
83
+
84
+ 2. **Composition.** Some presets compose other presets internally. The CTA preset includes a link field; the page preset includes SEO fields. The registry ensures these composed presets share the same global configuration.
85
+
86
+ ```ts
87
+ const {defineLink, defineCta, definePage} = createPresetsRegistry({
88
+ link: {
89
+ // Every link in this registry — standalone, inside CTAs,
90
+ // inside rich text — will offer these types for internal links.
91
+ internalTypes: ['marketingPage', 'blogPost'],
92
+ },
93
+ })
94
+ ```
95
+
96
+ Global configuration can be overridden at the call site. If a specific link instance needs different internal types, pass them directly:
97
+
98
+ ```ts
99
+ defineLink({
100
+ name: 'specialLink',
101
+ // Overrides the registry-level internalTypes for this instance only.
102
+ internalTypes: ['product'],
103
+ })
104
+ ```
105
+
106
+ ### Composition
107
+
108
+ Presets can compose other presets. This means configuring one preset can affect others that depend on it.
109
+
110
+ The **link** preset is the clearest example. When you configure `link.internalTypes` at the registry level, that configuration cascades to:
111
+
112
+ - **CTA (call to action)** — the CTA preset includes an inline link field. The link field automatically uses the registry-level `internalTypes` configuration.
113
+ - **Rich text** — the rich text preset includes link annotations. Those annotations also use the registry-level `internalTypes` configuration.
114
+
115
+ This means you configure link behaviour once, and every preset that uses links inherits that configuration automatically.
116
+
117
+ ### Map hooks
118
+
119
+ Every preset accepts a `map` option containing **map hooks** — functions that receive the produced schema type and return a modified version.
120
+
121
+ Map hooks exist as an escape hatch. They give you full control over the schema type a preset produces, including the ability to reorder, rename, or remove fields.
122
+
123
+ ```ts
124
+ import {defineField} from 'sanity'
125
+
126
+ definePage({
127
+ name: 'marketingPage',
128
+ title: 'Marketing Page',
129
+ map: {
130
+ // Prepend a "Subtitle" field before all other fields.
131
+ fields: (fields = []) => [
132
+ defineField({
133
+ name: 'subtitle',
134
+ title: 'Subtitle',
135
+ type: 'string',
136
+ group: 'main',
137
+ }),
138
+ ...fields,
139
+ ],
140
+ },
141
+ })
142
+ ```
143
+
144
+ Each hook receives the value from the produced schema type (after any `fields`, `groups`, or other options have been applied) and must return a compatible value.
145
+
146
+ **Use map hooks carefully.** They have the final say in the produced schema type, which means they can unintentionally break a preset's intended functionality. A few guidelines:
147
+
148
+ - If you find yourself heavily rewriting the produced schema type with map hooks, it may be a sign that you should model the content type yourself using `defineType` and `defineField` directly. See the [schema type documentation](https://www.sanity.io/docs/apis-and-sdks/introduction-to-schemas) for more.
149
+ - If you use map hooks to rename fields, existing documents may need to be migrated. See the [schema and content migrations documentation](https://www.sanity.io/docs/content-lake/schema-and-content-migrations).
150
+
151
+ ## Usage
152
+
153
+ ### Page
154
+
155
+ The page preset produces a document type designed for page building. It includes fields for a page name, slug, content (an array of page-builder blocks), and SEO metadata.
156
+
157
+ ```ts
158
+ definePage({
159
+ name: 'marketingPage',
160
+ title: 'Marketing Page',
161
+ // Each page builder block must be a type you've defined in your schema.
162
+ // See "Use presets alongside custom types" for more.
163
+ pageBuilderBlocks: ['hero', 'featureGrid', 'testimonial'],
164
+ })
165
+ ```
166
+
167
+ **Fields:**
168
+
169
+ | Field | Type | Group | Description |
170
+ | --------- | -------- | -------- | -------------------------------------------------------------------------------- |
171
+ | `name` | `string` | Main | The page's display name. Required. |
172
+ | `slug` | `slug` | Main | URL-friendly slug, sourced from `name`. |
173
+ | `content` | `array` | Main | Page builder blocks. Types are specified via `pageBuilderBlocks`. |
174
+ | `seo` | `object` | Metadata | SEO fields (title, description, Open Graph image). Composed from the SEO preset. |
175
+
176
+ **Groups:** Main (default), Metadata.
177
+
178
+ **Options:**
179
+
180
+ | Option | Type | Description |
181
+ | ------------------- | ------------------------ | ----------------------------------------------- |
182
+ | `pageBuilderBlocks` | `string[]` | Type names to include in the content array. |
183
+ | `fields` | `FieldDefinition[]` | Additional fields to append. |
184
+ | `groups` | `FieldGroupDefinition[]` | Additional groups to append after the defaults. |
185
+
186
+ The page preset is not the only way to create page documents. It provides opinionated defaults to get started quickly. For specialised page types, use `defineType` directly. See the [document type documentation](https://www.sanity.io/docs/studio/document-type).
187
+
188
+ ### Link
189
+
190
+ The link preset produces an object type for internal and external links. It includes fields for the link type (internal or external), a reference field for internal links, a URL field for external links, and an "open in new tab" option.
191
+
192
+ ```ts
193
+ defineLink({
194
+ name: 'primaryLink',
195
+ title: 'Primary Link',
196
+ // Document types available for internal links. Falls back to
197
+ // the registry-level link.internalTypes if not provided here.
198
+ internalTypes: ['page', 'post'],
199
+ })
200
+ ```
201
+
202
+ **Fields:**
203
+
204
+ | Field | Type | Description |
205
+ | -------------- | ----------- | -------------------------------------------------------------------------------------------------------- |
206
+ | `linkType` | `string` | "Internal" or "External". Defaults to "Internal". |
207
+ | `reference` | `reference` | Internal link. Hidden when link type is external. Targets configured via `internalTypes`. |
208
+ | `url` | `url` | External URL. Hidden when link type is internal. Validates `http`, `https`, `mailto`, and `tel` schemes. |
209
+ | `openInNewTab` | `boolean` | Whether to open in a new tab. Hidden for internal links. |
210
+
211
+ **Options:**
212
+
213
+ | Option | Type | Description |
214
+ | --------------- | ---------- | --------------------------------------------------------------------------------------------------- |
215
+ | `internalTypes` | `string[]` | Document types available for internal links. Falls back to the registry-level `link.internalTypes`. |
216
+
217
+ ### CTA (call to action)
218
+
219
+ The CTA preset produces an object type for call-to-action elements. It includes an inline link field (composed from the link preset) and a level selector for semantic importance.
220
+
221
+ ```ts
222
+ defineCta({
223
+ name: 'heroCta',
224
+ title: 'Hero CTA',
225
+ })
226
+ ```
227
+
228
+ **Fields:**
229
+
230
+ | Field | Type | Description |
231
+ | ------- | -------- | ------------------------------------------------------------------------------------------ |
232
+ | `link` | `object` | An inline link, composed from the link preset. Inherits `internalTypes` from the registry. |
233
+ | `level` | `number` | Semantic importance level (1, 2, or 3). |
234
+
235
+ ### SEO (search engine optimization)
236
+
237
+ The SEO preset produces an object type for search engine metadata. It includes fields for a title, description, and Open Graph image with dimension validation.
238
+
239
+ ```ts
240
+ defineSeo({
241
+ name: 'metadata',
242
+ title: 'Metadata',
243
+ group: 'metadata',
244
+ })
245
+ ```
246
+
247
+ **Fields:**
248
+
249
+ | Field | Type | Description |
250
+ | ------------- | -------- | ------------------------------------------------------------------ |
251
+ | `title` | `string` | Page title for search engines. Warns when exceeding 70 characters. |
252
+ | `description` | `text` | Meta description. Warns when exceeding 150 characters. |
253
+ | `ogImage` | `image` | Open Graph image. Validates dimensions are exactly 1200×630. |
254
+
255
+ The SEO preset is also composed into the page preset, where it appears as an inline object field in the Metadata group.
256
+
257
+ ### Image
258
+
259
+ The image preset produces an object type for images with optional alt text and caption fields. It includes built-in preview configuration.
260
+
261
+ ```ts
262
+ defineImage({
263
+ name: 'heroImage',
264
+ title: 'Hero Image',
265
+ altText: true,
266
+ caption: false,
267
+ hotspot: true,
268
+ })
269
+ ```
270
+
271
+ **Fields:**
272
+
273
+ | Field | Type | Description |
274
+ | --------- | -------- | -------------------------------------------------------------------------------------- |
275
+ | `image` | `image` | The image asset. Hotspot is enabled by default. |
276
+ | `altText` | `string` | Alt text for accessibility. Enabled by default. Shows a validation warning when empty. |
277
+ | `caption` | `text` | Image caption. Enabled by default. |
278
+
279
+ **Options:**
280
+
281
+ | Option | Type | Default | Description |
282
+ | --------- | --------- | ------- | --------------------------- |
283
+ | `altText` | `boolean` | `true` | Include the alt text field. |
284
+ | `caption` | `boolean` | `true` | Include the caption field. |
285
+ | `hotspot` | `boolean` | `true` | Enable image hotspot. |
286
+
287
+ ### Rich text
288
+
289
+ The rich text preset produces a Portable Text array type with link annotations, image blocks, and inline call-to-action (CTA) objects. All three embedded objects are on by default.
290
+
291
+ ```ts
292
+ defineRichText({
293
+ name: 'body',
294
+ title: 'Body',
295
+ })
296
+ ```
297
+
298
+ **Embedded objects:**
299
+
300
+ | Object | Type | Description |
301
+ | ------- | ------------------------ | ----------------------------------------------------------- |
302
+ | `link` | Portable Text annotation | Adds the link preset as an inline annotation on blocks. |
303
+ | `image` | Array member | Adds the image preset as a block-level member of the array. |
304
+ | `cta` | Inline object | Adds the CTA preset as an inline object within blocks. |
305
+
306
+ **Options:**
307
+
308
+ | Option | Type | Default | Description |
309
+ | --------- | ------------------------------------------------------------- | ------- | ---------------------------------------------------------------------------------------- |
310
+ | `objects` | `boolean \| {link?: boolean, image?: boolean, cta?: boolean}` | `true` | Toggles embedded objects on or off. Pass `false` to disable all, or an object per entry. |
311
+
312
+ To disable all embedded objects for a plain Portable Text field:
313
+
314
+ ```ts
315
+ defineRichText({
316
+ name: 'plainBody',
317
+ objects: false,
318
+ })
319
+ ```
320
+
321
+ To disable individual embedded objects:
322
+
323
+ ```ts
324
+ defineRichText({
325
+ name: 'body',
326
+ objects: {cta: false},
327
+ })
328
+ ```
329
+
330
+ #### Configuring the embedded presets
331
+
332
+ Configure each object's options (link `internalTypes`, image `altText`, and so on) at the registry level. Those options cascade into every rich text field:
333
+
334
+ ```ts
335
+ const {defineRichText} = createPresetsRegistry({
336
+ link: {
337
+ internalTypes: ['page', 'post'],
338
+ },
339
+ image: {
340
+ altText: true,
341
+ caption: false,
342
+ },
343
+ })
344
+ ```
345
+
346
+ The `objects` option only toggles embedded objects on or off. To reshape the array members on a specific rich text field, use the [map hooks escape hatch](#reserve-map-hooks-for-when-you-need-full-control).
347
+
348
+ ## Recommended patterns
349
+
350
+ ### Use presets alongside custom types
351
+
352
+ Presets are not intended to replace all content modelling. They provide opinionated defaults for common patterns — pages, links, images, metadata — but your schema will likely include custom types that are specific to your project.
353
+
354
+ Custom types and presets work well together. You can use presets inside custom types, and reference custom types from presets:
355
+
356
+ ```ts
357
+ import {defineType, defineField} from 'sanity'
358
+
359
+ // A custom "blockquote" type that includes a link preset.
360
+ // This type must be added to schema.types alongside your presets.
361
+ defineType({
362
+ name: 'blockquote',
363
+ title: 'Blockquote',
364
+ type: 'object',
365
+ fields: [
366
+ defineField({name: 'quote', title: 'Quote', type: 'text'}),
367
+ defineField({name: 'author', title: 'Author', type: 'string'}),
368
+ defineLink({name: 'source', title: 'Source'}),
369
+ ],
370
+ })
371
+ ```
372
+
373
+ When a preset references a custom type — for example, passing `pageBuilderBlocks: ["blockquote"]` to `definePage` — that type must be defined in your schema. Presets don't create these types for you.
374
+
375
+ ### Extend presets with fields and groups
376
+
377
+ Rather than reaching for [map hooks](#map-hooks), use the `fields` and `groups` options to extend a preset. Fields and groups added this way are appended after the preset's own fields and groups:
378
+
379
+ ```ts
380
+ definePage({
381
+ name: 'blogPost',
382
+ title: 'Blog Post',
383
+ // These types must be defined in your schema.
384
+ // See "Use presets alongside custom types" for more.
385
+ pageBuilderBlocks: ['richText', 'image'],
386
+ groups: [{name: 'settings', title: 'Settings'}],
387
+ fields: [
388
+ defineField({
389
+ name: 'publishedAt',
390
+ title: 'Published at',
391
+ type: 'datetime',
392
+ group: 'metadata',
393
+ }),
394
+ defineField({
395
+ name: 'featured',
396
+ title: 'Featured',
397
+ type: 'boolean',
398
+ group: 'settings',
399
+ }),
400
+ ],
401
+ })
402
+ ```
403
+
404
+ ### Reserve map hooks for when you need full control
405
+
406
+ The [`fields` option](#extend-presets-with-fields-and-groups) is sufficient for adding new fields to a preset. Use map hooks when you need full control over the produced schema type — for example, reordering or wrapping existing fields:
407
+
408
+ ```ts
409
+ import {defineField} from 'sanity'
410
+
411
+ definePage({
412
+ name: 'marketingPage',
413
+ title: 'Marketing Page',
414
+ map: {
415
+ // Prepend a "Subtitle" field before all other fields.
416
+ fields: (fields = []) => [
417
+ defineField({
418
+ name: 'subtitle',
419
+ title: 'Subtitle',
420
+ type: 'string',
421
+ group: 'main',
422
+ }),
423
+ ...fields,
424
+ ],
425
+ },
426
+ })
427
+ ```
428
+
429
+ A few guidelines for using map hooks:
430
+
431
+ - If you find yourself heavily rewriting the produced schema type with map hooks, it may be a sign that you should model the content type yourself. See the [schema type documentation](https://www.sanity.io/docs/apis-and-sdks/introduction-to-schemas) for more.
432
+ - If you use map hooks to rename fields, existing documents may need to be migrated to reflect the new field names. See the [schema and content migrations documentation](https://www.sanity.io/docs/content-lake/schema-and-content-migrations).
433
+
434
+ ### Configure links globally
435
+
436
+ The [link preset](#link) is used by multiple other presets ([CTA](#cta-call-to-action), [rich text](#rich-text)). Configure `internalTypes` at the registry level so all links share the same set of linkable document types:
437
+
438
+ ```ts
439
+ const {defineLink, defineCta, definePage} = createPresetsRegistry({
440
+ link: {
441
+ internalTypes: ['page', 'post', 'product'],
442
+ },
443
+ })
444
+ ```
445
+
446
+ This single configuration flows into every `defineLink`, `defineCta`, and `defineRichText` call from this registry. Override at the call site only when a specific instance needs different behaviour.
package/dist/index.d.ts CHANGED
@@ -1,12 +1,93 @@
1
- import { PluginOptions, SchemaTypeDefinition } from "sanity";
2
- interface PresetResult {
3
- types: SchemaTypeDefinition[];
1
+ import { DefineSchemaBase, FieldDefinition, FieldDefinitionBase, IntrinsicTypeName, PreviewConfig, SchemaTypeDefinition } from "sanity";
2
+ type PartialSchemaDefinition<TypeName extends IntrinsicTypeName> = Partial<DefineSchemaBase<TypeName, TypeName> & {
3
+ preview: PreviewConfig;
4
+ }>;
5
+ interface RegistryContext {
6
+ getPreset: (presetName: string, config?: Record<string, unknown>) => FieldDefinition;
4
7
  }
5
- declare function presets(...types: PresetResult[]): PluginOptions;
6
- declare const LINK_TYPE_NAME = "core.presets.link";
8
+ type ProhibitedProperties = 'type';
9
+ type SanitizeProperties<Properties, ExcludedProperties extends string | undefined> = [ExcludedProperties] extends [PropertyKey] ? Omit<Properties, ExcludedProperties> : Properties;
10
+ type DerivedConfig<Context, AliasedType extends IntrinsicTypeName | undefined = undefined, LockedProperties extends string | undefined = undefined> = Context & FieldDefinitionBase & (AliasedType extends string ? SanitizeProperties<PartialSchemaDefinition<AliasedType>, ProhibitedProperties | LockedProperties> : {}) & {
11
+ map?: AliasedType extends string ? { [Key in keyof PartialSchemaDefinition<AliasedType>]?: (input: PartialSchemaDefinition<AliasedType>[Key]) => PartialSchemaDefinition<AliasedType>[Key] } : {};
12
+ };
13
+ /**
14
+ * The public-facing config shape that a registry's `define<Name>` function
15
+ * accepts at the call site. Includes the full `DerivedConfig` (with optional
16
+ * `map` and optional `name` — the registry falls back to the preset's default
17
+ * name when `name` is omitted).
18
+ */
19
+ type UserConfig<Context = {}, AliasedType extends IntrinsicTypeName | undefined = undefined, LockedProperties extends string | undefined = undefined> = DerivedConfig<Context, AliasedType, LockedProperties>;
20
+ /**
21
+ * A preset definition describes how to produce a Sanity schema type.
22
+ *
23
+ * - `name` is the default schema type name. Consumers can override this at the
24
+ * call site (e.g. `defineLink({name: 'myLink'})`); the registry will make
25
+ * sure the override reaches the `schemaType` factory via its config.
26
+ * - `identifier` is an optional stable identifier used for telemetry.
27
+ * - `schemaType` is the factory that produces the Sanity schema type. It
28
+ * receives the merged config (minus `map`, with `name` guaranteed by the
29
+ * registry) and the registry context, and returns a `SchemaTypeDefinition`.
30
+ */
31
+ interface PresetDefinition<Context = {}, AliasedType extends IntrinsicTypeName | undefined = undefined, LockedProperties extends string | undefined = undefined> {
32
+ name: string;
33
+ identifier?: string;
34
+ schemaType: (config: Omit<DerivedConfig<Context, AliasedType, LockedProperties>, 'map' | 'name'> & {
35
+ name: string;
36
+ }, registry: RegistryContext) => SchemaTypeDefinition;
37
+ }
38
+ /**
39
+ * A preset definition with its generic parameters erased, for use in code
40
+ * that handles presets generically (e.g. the registry).
41
+ */
42
+ type AnyPresetDefinition = PresetDefinition<any, any, any>;
43
+ declare const ctaType: PresetDefinition<{}, "object", "preview">;
44
+ interface ImageTypeConfig {
45
+ altText?: boolean;
46
+ caption?: boolean;
47
+ hotspot?: boolean;
48
+ }
49
+ declare const imageType: PresetDefinition<ImageTypeConfig, "object", "preview">;
7
50
  interface LinkTypeConfig {
8
- internalTypes: string[];
51
+ internalTypes?: string[];
52
+ }
53
+ declare const linkType: PresetDefinition<LinkTypeConfig, "object", "preview">;
54
+ interface PageTypeConfig {
55
+ pageBuilderBlocks?: string[];
56
+ }
57
+ declare const pageType: PresetDefinition<PageTypeConfig, "document", undefined>;
58
+ interface RichTextObjectsConfig {
59
+ link?: boolean;
60
+ image?: boolean;
61
+ cta?: boolean;
62
+ }
63
+ interface RichTextTypeConfig {
64
+ /**
65
+ * Toggle the embedded objects (link annotations, image blocks, inline CTAs).
66
+ * Defaults to all enabled. Pass `false` to disable every object, or an
67
+ * object to toggle individual ones (e.g. `{link: false}`).
68
+ *
69
+ * Each object's options (link `internalTypes`, image `altText`, …) are
70
+ * configured on `createPresetsRegistry` and cascade into every rich text
71
+ * field. Use `map.of` for per-field structural changes.
72
+ */
73
+ objects?: boolean | RichTextObjectsConfig;
74
+ }
75
+ declare const richTextType: PresetDefinition<RichTextTypeConfig, "array", "of">;
76
+ declare const seoType: PresetDefinition<{}, "object", undefined>;
77
+ interface PresetsRegistryConfig {
78
+ link?: LinkTypeConfig;
79
+ image?: ImageTypeConfig;
80
+ page?: PageTypeConfig;
81
+ }
82
+ type DefineFunction<Preset extends AnyPresetDefinition> = Preset extends PresetDefinition<infer Context, infer AliasedType, infer LockedProperties> ? (config?: UserConfig<Context, AliasedType, LockedProperties>) => SchemaTypeDefinition & FieldDefinition : never;
83
+ interface PresetsRegistry {
84
+ defineLink: DefineFunction<typeof linkType>;
85
+ defineCta: DefineFunction<typeof ctaType>;
86
+ defineSeo: DefineFunction<typeof seoType>;
87
+ defineImage: DefineFunction<typeof imageType>;
88
+ definePage: DefineFunction<typeof pageType>;
89
+ defineRichText: DefineFunction<typeof richTextType>;
9
90
  }
10
- declare function linkType(config: LinkTypeConfig): PresetResult;
11
- export { LINK_TYPE_NAME, type LinkTypeConfig, type PresetResult, linkType, presets };
91
+ declare function createPresetsRegistry(config?: PresetsRegistryConfig): PresetsRegistry;
92
+ export { type PresetsRegistry, type PresetsRegistryConfig, createPresetsRegistry };
12
93
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/composer.ts","../src/presets/link-type/constants.ts","../src/presets/link-type/index.ts"],"mappings":";UAEiB,YAAA;EACf,KAAA,EAAO,oBAAA;AAAA;AAAA,iBCkBO,OAAA,CAAA,GAAW,KAAA,EAAO,YAAA,KAAiB,aAAA;AAAA,cCrBtC,cAAA;AAAA,UCKI,cAAA;EACf,aAAA;AAAA;AAAA,iBAGc,QAAA,CAAS,MAAA,EAAQ,cAAA,GAAiB,YAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/definePresetType.ts","../src/presets/cta-type/index.ts","../src/presets/image-type/index.ts","../src/presets/link-type/index.ts","../src/presets/page-type/index.ts","../src/presets/rich-text-type/index.ts","../src/presets/seo-type/index.ts","../src/registry.tsx"],"mappings":";KAEY,uBAAA,kBAAyC,iBAAA,IAAqB,OAAA,CACxE,gBAAA,CAAiB,QAAA,EAAU,QAAA;EAAa,OAAA,EAAS,aAAA;AAAA;AAAA,UCMlC,eAAA;EACf,SAAA,GAAY,UAAA,UAAoB,MAAA,GAAS,MAAA,sBAA4B,eAAA;AAAA;AAAA,KAGlE,oBAAA;AAAA,KAEA,kBAAA,+DACH,kBAAA,WACS,WAAA,IACP,IAAA,CAAK,UAAA,EAAY,kBAAA,IACjB,UAAA;AAAA,KAEQ,aAAA,8BAEU,iBAAA,qFAElB,OAAA,GACF,mBAAA,IACC,WAAA,kBACG,kBAAA,CACE,uBAAA,CAAwB,WAAA,GACxB,oBAAA,GAAuB,gBAAA;EAG3B,GAAA,GAAM,WAAA,kCAEc,uBAAA,CAAwB,WAAA,MACpC,KAAA,EAAO,uBAAA,CAAwB,WAAA,EAAa,GAAA,MACzC,uBAAA,CAAwB,WAAA,EAAa,GAAA;AAAA;;;;;;;KAWxC,UAAA,mCAEU,iBAAA,qFAElB,aAAA,CAAc,OAAA,EAAS,WAAA,EAAa,gBAAA;;;;AA3CxC;;;;;;;;UAwDiB,gBAAA,mCAEK,iBAAA;EAGpB,IAAA;EACA,UAAA;EACA,UAAA,GACE,MAAA,EAAQ,IAAA,CAAK,aAAA,CAAc,OAAA,EAAS,WAAA,EAAa,gBAAA;IAC/C,IAAA;EAAA,GAEF,QAAA,EAAU,eAAA,KACP,oBAAA;AAAA;;;;;KA0BK,mBAAA,GAAsB,gBAAA;AAAA,cCnGrB,OAAA,EAsCX,gBAAA;AAAA,UCtCe,eAAA;EACf,OAAA;EACA,OAAA;EACA,OAAA;AAAA;AAAA,cAGW,SAAA,EAAS,gBAAA,CAAA,eAAA;AAAA,UCNL,cAAA;EACf,aAAA;AAAA;AAAA,cAGW,QAAA,EAAQ,gBAAA,CAAA,cAAA;AAAA,UCJJ,cAAA;EACf,iBAAA;AAAA;AAAA,cAGW,QAAA,EAAQ,gBAAA,CAAA,cAAA;AAAA,UCJJ,qBAAA;EACf,IAAA;EACA,KAAA;EACA,GAAA;AAAA;AAAA,UAGe,kBAAA;ENPE;;;;;;;;;EMiBjB,OAAA,aAAoB,qBAAA;AAAA;AAAA,cAUT,YAAA,EAAY,gBAAA,CAAA,kBAAA;AAAA,cCzBZ,OAAA,EAyDX,gBAAA;AAAA,UCzCe,qBAAA;EACf,IAAA,GAAO,cAAA;EACP,KAAA,GAAQ,eAAA;EACR,IAAA,GAAO,cAAA;AAAA;AAAA,KAGJ,cAAA,gBAA8B,mBAAA,IACjC,MAAA,SAAe,gBAAA,8DAET,MAAA,GAAS,UAAA,CAAW,OAAA,EAAS,WAAA,EAAa,gBAAA,MACvC,oBAAA,GAAuB,eAAA;AAAA,UAGjB,eAAA;EACf,UAAA,EAAY,cAAA,QAAsB,QAAA;EAClC,SAAA,EAAW,cAAA,QAAsB,OAAA;EACjC,SAAA,EAAW,cAAA,QAAsB,OAAA;EACjC,WAAA,EAAa,cAAA,QAAsB,SAAA;EACnC,UAAA,EAAY,cAAA,QAAsB,QAAA;EAClC,cAAA,EAAgB,cAAA,QAAsB,YAAA;AAAA;AAAA,iBAGxB,qBAAA,CAAsB,MAAA,GAAQ,qBAAA,GAA6B,eAAA"}
package/dist/index.js CHANGED
@@ -1,96 +1,448 @@
1
- import { defineType, defineField } from "sanity";
2
- function collectTypes(presets2) {
3
- const seen = /* @__PURE__ */ new Set();
4
- return presets2.flatMap((preset) => preset.types.filter((typeDef) => seen.has(typeDef.name) ? (console.warn(`[@sanity/presets] Dropped duplicate type "${typeDef.name}". Keeping first definition.`), !1) : (seen.add(typeDef.name), !0)));
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { uuid } from "@sanity/uuid";
3
+ import { c } from "react/compiler-runtime";
4
+ import { useTelemetry } from "@sanity/telemetry/react";
5
+ import { useEffect } from "react";
6
+ import { defineEvent } from "@sanity/telemetry";
7
+ import { defineType, defineField, ALL_FIELDS_GROUP, defineArrayMember } from "sanity";
8
+ import { getImageDimensions } from "@sanity/asset-utils";
9
+ const PresetsAdded = defineEvent({
10
+ name: "Presets Added",
11
+ version: 1,
12
+ description: "Workspace using presets was accessed"
13
+ }), registries = /* @__PURE__ */ new Map();
14
+ function registerRegistry(id) {
15
+ registries.set(id, {
16
+ id,
17
+ presets: /* @__PURE__ */ new Set(),
18
+ logged: !1
19
+ });
5
20
  }
6
- function presets(...types) {
7
- return {
8
- name: "@sanity/presets",
9
- schema: {
10
- types: collectTypes(types)
11
- }
12
- };
21
+ function recordPresetUsage(registryId, identifier) {
22
+ registries.get(registryId)?.presets.add(identifier);
13
23
  }
14
- const LINK_TYPE_NAME = "core.presets.link";
15
- function createLinkType(internalTypes) {
16
- const referenceTargets = internalTypes.map((typeName) => ({
17
- type: typeName
24
+ function collectPresetsRegistryTelemetry(registryId, telemetry) {
25
+ const record = registries.get(registryId);
26
+ !record || record.logged || (record.logged = !0, record.presets.size > 0 && telemetry.log(PresetsAdded, {
27
+ presetNames: [...record.presets]
18
28
  }));
19
- return defineType({
20
- name: LINK_TYPE_NAME,
21
- type: "object",
22
- title: "Link",
23
- fields: [defineField({
24
- name: "linkType",
25
- type: "string",
26
- title: "Link Type",
27
- initialValue: "internal",
28
- options: {
29
- layout: "radio",
30
- list: [{
31
- title: "Internal",
32
- value: "internal"
33
- }, {
34
- title: "External",
35
- value: "external"
36
- }]
29
+ }
30
+ const PresetsTelemetryCollector = (t0) => {
31
+ const $ = c(4), {
32
+ registryId,
33
+ userInput: UserInput,
34
+ ...props
35
+ } = t0, telemetry = useTelemetry();
36
+ let t1, t2;
37
+ return $[0] !== registryId || $[1] !== telemetry ? (t1 = () => {
38
+ collectPresetsRegistryTelemetry(registryId, telemetry);
39
+ }, t2 = [registryId, telemetry], $[0] = registryId, $[1] = telemetry, $[2] = t1, $[3] = t2) : (t1 = $[2], t2 = $[3]), useEffect(t1, t2), UserInput ? /* @__PURE__ */ jsx(UserInput, { ...props }) : props.renderDefault(props);
40
+ };
41
+ const ctaType = {
42
+ name: "cta",
43
+ identifier: "core.cta",
44
+ schemaType: (config, registry) => {
45
+ const {
46
+ fields,
47
+ ...objectConfig
48
+ } = config;
49
+ return defineType({
50
+ title: "Call to action",
51
+ ...objectConfig,
52
+ type: "object",
53
+ fields: [registry.getPreset("link", {
54
+ name: "link",
55
+ title: "Link"
56
+ }), defineField({
57
+ name: "level",
58
+ title: "Level",
59
+ type: "number",
60
+ options: {
61
+ layout: "radio",
62
+ list: [1, 2, 3]
63
+ }
64
+ }), ...fields ?? []],
65
+ preview: {
66
+ select: {
67
+ linkType: "link.linkType",
68
+ url: "link.url",
69
+ referenceTitle: "link.reference.title",
70
+ referenceName: "link.reference.name"
71
+ },
72
+ prepare({
73
+ linkType: linkType2,
74
+ url,
75
+ referenceTitle,
76
+ referenceName
77
+ }) {
78
+ return {
79
+ title: linkType2 === "external" ? url || "No URL" : referenceTitle || referenceName || "No reference",
80
+ subtitle: "Button"
81
+ };
82
+ }
83
+ }
84
+ });
85
+ }
86
+ }, imageType = {
87
+ name: "image",
88
+ identifier: "core.image",
89
+ schemaType: (config) => {
90
+ const {
91
+ altText = !0,
92
+ caption = !0,
93
+ hotspot = !0,
94
+ fields,
95
+ ...objectConfig
96
+ } = config;
97
+ return defineType({
98
+ title: "Image",
99
+ ...objectConfig,
100
+ type: "object",
101
+ fields: [defineField({
102
+ name: "image",
103
+ title: "Image",
104
+ type: "image",
105
+ options: {
106
+ hotspot
107
+ }
108
+ }), ...altText ? [defineField({
109
+ name: "altText",
110
+ title: "Alt text",
111
+ type: "string",
112
+ validation: (rule) => rule.warning("Alt text improves accessibility.")
113
+ })] : [], ...caption ? [defineField({
114
+ name: "caption",
115
+ title: "Caption",
116
+ type: "text"
117
+ })] : [], ...fields ?? []],
118
+ preview: {
119
+ select: {
120
+ title: altText ? "altText" : caption ? "caption" : "image.asset.originalFilename",
121
+ media: "image"
122
+ }
37
123
  }
38
- }), defineField({
39
- name: "reference",
40
- type: "reference",
41
- title: "Internal Link",
42
- to: referenceTargets,
43
- hidden: ({
44
- parent
45
- }) => parent?.linkType === "external"
46
- }), defineField({
47
- name: "url",
48
- type: "url",
49
- title: "URL",
50
- hidden: ({
51
- parent
52
- }) => parent?.linkType === "internal",
53
- validation: (rule) => rule.uri({
54
- scheme: ["http", "https", "mailto", "tel"]
55
- })
56
- }), defineField({
57
- name: "openInNewTab",
58
- type: "boolean",
59
- title: "Open in New Tab",
60
- initialValue: !1,
61
- hidden: ({
62
- parent
63
- }) => parent?.linkType === "internal"
64
- })],
65
- preview: {
66
- select: {
67
- linkType: "linkType",
68
- url: "url",
69
- referenceTitle: "reference.title"
124
+ });
125
+ }
126
+ }, linkType = {
127
+ name: "link",
128
+ identifier: "core.link",
129
+ schemaType: ({
130
+ internalTypes,
131
+ fields,
132
+ ...objectConfig
133
+ }) => {
134
+ const referenceTargets = (internalTypes ?? []).map((type) => ({
135
+ type
136
+ }));
137
+ return defineType({
138
+ title: "Link",
139
+ ...objectConfig,
140
+ type: "object",
141
+ fields: [defineField({
142
+ name: "linkType",
143
+ type: "string",
144
+ title: "Link Type",
145
+ initialValue: "internal",
146
+ options: {
147
+ layout: "radio",
148
+ list: [{
149
+ title: "Internal",
150
+ value: "internal"
151
+ }, {
152
+ title: "External",
153
+ value: "external"
154
+ }]
155
+ }
156
+ }), defineField({
157
+ name: "reference",
158
+ type: "reference",
159
+ title: "Internal Link",
160
+ to: referenceTargets,
161
+ hidden: ({
162
+ parent
163
+ }) => parent?.linkType === "external"
164
+ }), defineField({
165
+ name: "url",
166
+ type: "url",
167
+ title: "URL",
168
+ hidden: ({
169
+ parent
170
+ }) => parent?.linkType === "internal",
171
+ validation: (rule) => rule.uri({
172
+ scheme: ["http", "https", "mailto", "tel"]
173
+ })
174
+ }), defineField({
175
+ name: "openInNewTab",
176
+ type: "boolean",
177
+ title: "Open in New Tab",
178
+ initialValue: !1,
179
+ hidden: ({
180
+ parent
181
+ }) => parent?.linkType === "internal"
182
+ }), ...fields ?? []],
183
+ preview: {
184
+ select: {
185
+ linkType: "linkType",
186
+ url: "url",
187
+ referenceTitle: "reference.title",
188
+ referenceName: "reference.name"
189
+ },
190
+ prepare({
191
+ linkType: linkType2,
192
+ url,
193
+ referenceTitle,
194
+ referenceName
195
+ }) {
196
+ return {
197
+ title: linkType2 === "external" ? url || "No URL" : referenceTitle || referenceName || "No reference",
198
+ subtitle: linkType2 === "external" ? "External link" : "Internal link"
199
+ };
200
+ }
201
+ }
202
+ });
203
+ }
204
+ }, pageType = {
205
+ name: "page",
206
+ identifier: "core.page",
207
+ schemaType: (config, registry) => {
208
+ const {
209
+ pageBuilderBlocks,
210
+ groups,
211
+ fields,
212
+ ...documentConfig
213
+ } = config;
214
+ return defineType({
215
+ title: "Page",
216
+ ...documentConfig,
217
+ type: "document",
218
+ groups: [{
219
+ ...ALL_FIELDS_GROUP,
220
+ hidden: !0
221
+ }, {
222
+ name: "main",
223
+ title: "Main",
224
+ default: !0
225
+ }, {
226
+ name: "metadata",
227
+ title: "Metadata"
228
+ }, ...groups ?? []],
229
+ fields: [defineField({
230
+ name: "name",
231
+ title: "Name",
232
+ type: "string",
233
+ group: "main",
234
+ validation: (rule) => rule.required()
235
+ }), defineField({
236
+ name: "slug",
237
+ title: "Slug",
238
+ type: "slug",
239
+ group: "main",
240
+ options: {
241
+ source: "name"
242
+ }
243
+ }), defineField({
244
+ name: "content",
245
+ title: "Content",
246
+ group: "main",
247
+ type: "array",
248
+ of: (pageBuilderBlocks ?? []).map((typeName) => defineArrayMember({
249
+ type: typeName
250
+ }))
251
+ }), registry.getPreset("seo", {
252
+ name: "seo",
253
+ title: "SEO",
254
+ group: "metadata"
255
+ }), ...fields ?? []]
256
+ });
257
+ }
258
+ };
259
+ function resolveObjects(objects) {
260
+ if (objects === !1) return {
261
+ link: !1,
262
+ image: !1,
263
+ cta: !1
264
+ };
265
+ if (objects === !0 || objects === void 0) return {
266
+ link: !0,
267
+ image: !0,
268
+ cta: !0
269
+ };
270
+ const {
271
+ link = !0,
272
+ image = !0,
273
+ cta = !0
274
+ } = objects;
275
+ return {
276
+ link,
277
+ image,
278
+ cta
279
+ };
280
+ }
281
+ const richTextType = {
282
+ name: "richText",
283
+ identifier: "core.richText",
284
+ schemaType: (config, registry) => {
285
+ const {
286
+ objects,
287
+ ...arrayConfig
288
+ } = config, {
289
+ link,
290
+ image,
291
+ cta
292
+ } = resolveObjects(objects), linkAnnotation = link ? registry.getPreset("link", {
293
+ name: "link",
294
+ title: "Link"
295
+ }) : void 0, ctaInline = cta ? registry.getPreset("cta", {
296
+ name: "cta",
297
+ title: "CTA"
298
+ }) : void 0, imageMember = image ? registry.getPreset("image", {
299
+ name: "richTextImage",
300
+ title: "Image"
301
+ }) : void 0, blockMember = defineArrayMember({
302
+ type: "block",
303
+ marks: {
304
+ annotations: linkAnnotation ? [linkAnnotation] : []
70
305
  },
71
- prepare({
72
- linkType: linkType2,
73
- url,
74
- referenceTitle
75
- }) {
76
- return {
77
- title: linkType2 === "external" ? url || "No URL" : referenceTitle || "No reference",
78
- subtitle: linkType2 === "external" ? "External link" : "Internal link"
79
- };
306
+ ...ctaInline && {
307
+ of: [ctaInline]
80
308
  }
309
+ });
310
+ return defineType({
311
+ title: "Rich text",
312
+ ...arrayConfig,
313
+ type: "array",
314
+ of: imageMember ? [blockMember, imageMember] : [blockMember]
315
+ });
316
+ }
317
+ }, seoType = {
318
+ name: "seo",
319
+ identifier: "core.seo",
320
+ schemaType: (config) => {
321
+ const {
322
+ fields,
323
+ ...objectConfig
324
+ } = config;
325
+ return defineType({
326
+ title: "Web page metadata (SEO)",
327
+ ...objectConfig,
328
+ type: "object",
329
+ fields: [defineField({
330
+ name: "title",
331
+ title: "Title",
332
+ type: "string",
333
+ validation: (rule) => rule.max(70).info("Search engines may truncate this title.")
334
+ }), defineField({
335
+ name: "description",
336
+ title: "Description",
337
+ type: "text",
338
+ validation: (rule) => rule.max(150).info("Search engines may truncate this description.")
339
+ }), defineField({
340
+ name: "ogImage",
341
+ title: "Open Graph image",
342
+ type: "image",
343
+ description: "Landscape 1200x630 (1.91:1)",
344
+ options: {
345
+ hotspot: {
346
+ previews: [{
347
+ title: "Landscape (1.91:1)",
348
+ aspectRatio: 1.91 / 1
349
+ }]
350
+ }
351
+ },
352
+ validation: (Rule) => Rule.custom((value) => {
353
+ if (!value?.asset?._ref)
354
+ return !0;
355
+ const {
356
+ height,
357
+ width
358
+ } = getImageDimensions(value.asset?._ref);
359
+ return height !== 630 || width !== 1200 ? "Open Graph image must be 1200x630" : !0;
360
+ })
361
+ }), ...fields ?? []]
362
+ });
363
+ }
364
+ }, systemPresets = [linkType, ctaType, seoType, imageType, pageType, richTextType];
365
+ function createPresetsRegistry(config = {}) {
366
+ const registryId = uuid();
367
+ registerRegistry(registryId);
368
+ const seed = {};
369
+ return systemPresets.reduce((registry, preset) => {
370
+ const key = getPresetKey(preset.name);
371
+ return registry[key] = createDefiner({
372
+ registryId,
373
+ preset,
374
+ config,
375
+ registry
376
+ }), registry;
377
+ }, seed);
378
+ }
379
+ function getPresetKey(name) {
380
+ return `define${name.charAt(0).toUpperCase()}${name.slice(1)}`;
381
+ }
382
+ function createRegistryContext({
383
+ registry
384
+ }) {
385
+ return {
386
+ getPreset: (name, presetConfig) => {
387
+ const key = getPresetKey(name), definer = registry[key];
388
+ if (!definer)
389
+ throw new Error(`Cannot resolve preset "${name}". No such preset in this registry.`);
390
+ return definer(presetConfig);
81
391
  }
82
- });
392
+ };
83
393
  }
84
- function linkType(config) {
85
- if (config.internalTypes.length === 0)
86
- throw new Error("[@sanity/presets] linkType requires at least one internalTypes entry.");
394
+ function createDefiner({
395
+ registryId,
396
+ preset,
397
+ config,
398
+ registry
399
+ }) {
400
+ return function(userConfig = {}) {
401
+ recordPresetUsage(registryId, preset.identifier ?? "unnamed");
402
+ const registryContext = createRegistryContext({
403
+ registry
404
+ }), registryDefaults = config[preset.name], mergedConfig = {
405
+ name: preset.name,
406
+ ...typeof registryDefaults == "object" && registryDefaults !== null ? registryDefaults : {},
407
+ ...userConfig
408
+ }, {
409
+ map,
410
+ ...factoryConfig
411
+ } = mergedConfig, schemaType = preset.schemaType(
412
+ // oxlint-disable-next-line no-unsafe-type-assertion -- factoryConfig is the merged user config (minus `map`, with `name` injected); its shape matches the factory's expected parameter at runtime
413
+ factoryConfig,
414
+ registryContext
415
+ );
416
+ return applyMapHooks(addTelemetryComponent(schemaType, registryId), map);
417
+ };
418
+ }
419
+ function applyMapHooks(schemaType, map) {
420
+ if (!map || typeof map != "object") return schemaType;
421
+ const mappedSchemaType = {};
422
+ for (const [configName, configValue] of Object.entries(map))
423
+ typeof configValue == "function" && (mappedSchemaType[configName] = configValue(
424
+ // oxlint-disable-next-line no-unsafe-type-assertion -- map hooks operate on arbitrary schema type properties
425
+ schemaType[configName]
426
+ ));
427
+ return {
428
+ ...schemaType,
429
+ ...mappedSchemaType
430
+ };
431
+ }
432
+ function addTelemetryComponent(schemaType, registryId) {
433
+ const existing = "components" in schemaType ? schemaType.components : void 0, existingInput = existing && "input" in existing && typeof existing.input == "function" ? (
434
+ // oxlint-disable-next-line no-unsafe-type-assertion -- presets only produce object/document schema types, whose input components are assignable to ComponentType<InputProps>
435
+ existing.input
436
+ ) : void 0;
87
437
  return {
88
- types: [createLinkType(config.internalTypes)]
438
+ ...schemaType,
439
+ components: {
440
+ ...existing,
441
+ input: (props) => /* @__PURE__ */ jsx(PresetsTelemetryCollector, { ...props, registryId, userInput: existingInput })
442
+ }
89
443
  };
90
444
  }
91
445
  export {
92
- LINK_TYPE_NAME,
93
- linkType,
94
- presets
446
+ createPresetsRegistry
95
447
  };
96
448
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/composer.ts","../src/presets/link-type/constants.ts","../src/presets/link-type/schema.ts","../src/presets/link-type/index.ts"],"sourcesContent":["import {type PluginOptions, type SchemaTypeDefinition} from 'sanity'\n\nimport type {PresetResult} from './types'\n\nexport function collectTypes(presets: PresetResult[]): SchemaTypeDefinition[] {\n const seen = new Set<string>()\n\n return presets.flatMap((preset) =>\n preset.types.filter((typeDef) => {\n if (seen.has(typeDef.name)) {\n console.warn(\n `[@sanity/presets] Dropped duplicate type \"${typeDef.name}\". Keeping first definition.`,\n )\n return false\n }\n seen.add(typeDef.name)\n return true\n }),\n )\n}\n\nexport function presets(...types: PresetResult[]): PluginOptions {\n return {\n name: '@sanity/presets',\n schema: {types: collectTypes(types)},\n }\n}\n","export const LINK_TYPE_NAME = 'core.presets.link'\n","import {defineField, defineType, type SchemaTypeDefinition} from 'sanity'\n\nimport {LINK_TYPE_NAME} from './constants'\n\nexport function createLinkType(internalTypes: string[]): SchemaTypeDefinition {\n const referenceTargets = internalTypes.map((typeName) => ({type: typeName}))\n\n return defineType({\n name: LINK_TYPE_NAME,\n type: 'object',\n title: 'Link',\n fields: [\n defineField({\n name: 'linkType',\n type: 'string',\n title: 'Link Type',\n initialValue: 'internal',\n options: {\n layout: 'radio',\n list: [\n {title: 'Internal', value: 'internal'},\n {title: 'External', value: 'external'},\n ],\n },\n }),\n defineField({\n name: 'reference',\n type: 'reference',\n title: 'Internal Link',\n to: referenceTargets,\n hidden: ({parent}) => parent?.linkType === 'external',\n }),\n defineField({\n name: 'url',\n type: 'url',\n title: 'URL',\n hidden: ({parent}) => parent?.linkType === 'internal',\n validation: (rule) =>\n rule.uri({\n scheme: ['http', 'https', 'mailto', 'tel'],\n }),\n }),\n defineField({\n name: 'openInNewTab',\n type: 'boolean',\n title: 'Open in New Tab',\n initialValue: false,\n hidden: ({parent}) => parent?.linkType === 'internal',\n }),\n ],\n preview: {\n select: {\n linkType: 'linkType',\n url: 'url',\n referenceTitle: 'reference.title',\n },\n prepare({linkType, url, referenceTitle}) {\n const title = linkType === 'external' ? url || 'No URL' : referenceTitle || 'No reference'\n\n return {\n title,\n subtitle: linkType === 'external' ? 'External link' : 'Internal link',\n }\n },\n },\n })\n}\n","import type {PresetResult} from '../../types'\nimport {createLinkType} from './schema'\n\nexport {LINK_TYPE_NAME} from './constants'\n\nexport interface LinkTypeConfig {\n internalTypes: string[]\n}\n\nexport function linkType(config: LinkTypeConfig): PresetResult {\n if (config.internalTypes.length === 0) {\n throw new Error('[@sanity/presets] linkType requires at least one internalTypes entry.')\n }\n\n return {\n types: [createLinkType(config.internalTypes)],\n }\n}\n"],"names":["collectTypes","presets","seen","Set","flatMap","preset","types","filter","typeDef","has","name","console","warn","add","schema","LINK_TYPE_NAME","createLinkType","internalTypes","referenceTargets","map","typeName","type","defineType","title","fields","defineField","initialValue","options","layout","list","value","to","hidden","parent","linkType","validation","rule","uri","scheme","preview","select","url","referenceTitle","prepare","subtitle","config","length","Error"],"mappings":";AAIO,SAASA,aAAaC,UAAiD;AAC5E,QAAMC,2BAAWC,IAAAA;AAEjB,SAAOF,SAAQG,QAASC,CAAAA,WACtBA,OAAOC,MAAMC,OAAQC,CAAAA,YACfN,KAAKO,IAAID,QAAQE,IAAI,KACvBC,QAAQC,KACN,6CAA6CJ,QAAQE,IAAI,8BAC3D,GACO,OAETR,KAAKW,IAAIL,QAAQE,IAAI,GACd,GACR,CACH;AACF;AAEO,SAAST,WAAWK,OAAsC;AAC/D,SAAO;AAAA,IACLI,MAAM;AAAA,IACNI,QAAQ;AAAA,MAACR,OAAON,aAAaM,KAAK;AAAA,IAAA;AAAA,EAAC;AAEvC;AC1BO,MAAMS,iBAAiB;ACIvB,SAASC,eAAeC,eAA+C;AAC5E,QAAMC,mBAAmBD,cAAcE,IAAKC,CAAAA,cAAc;AAAA,IAACC,MAAMD;AAAAA,EAAAA,EAAU;AAE3E,SAAOE,WAAW;AAAA,IAChBZ,MAAMK;AAAAA,IACNM,MAAM;AAAA,IACNE,OAAO;AAAA,IACPC,QAAQ,CACNC,YAAY;AAAA,MACVf,MAAM;AAAA,MACNW,MAAM;AAAA,MACNE,OAAO;AAAA,MACPG,cAAc;AAAA,MACdC,SAAS;AAAA,QACPC,QAAQ;AAAA,QACRC,MAAM,CACJ;AAAA,UAACN,OAAO;AAAA,UAAYO,OAAO;AAAA,QAAA,GAC3B;AAAA,UAACP,OAAO;AAAA,UAAYO,OAAO;AAAA,QAAA,CAAW;AAAA,MAAA;AAAA,IAE1C,CACD,GACDL,YAAY;AAAA,MACVf,MAAM;AAAA,MACNW,MAAM;AAAA,MACNE,OAAO;AAAA,MACPQ,IAAIb;AAAAA,MACJc,QAAQA,CAAC;AAAA,QAACC;AAAAA,MAAAA,MAAYA,QAAQC,aAAa;AAAA,IAAA,CAC5C,GACDT,YAAY;AAAA,MACVf,MAAM;AAAA,MACNW,MAAM;AAAA,MACNE,OAAO;AAAA,MACPS,QAAQA,CAAC;AAAA,QAACC;AAAAA,MAAAA,MAAYA,QAAQC,aAAa;AAAA,MAC3CC,YAAaC,CAAAA,SACXA,KAAKC,IAAI;AAAA,QACPC,QAAQ,CAAC,QAAQ,SAAS,UAAU,KAAK;AAAA,MAAA,CAC1C;AAAA,IAAA,CACJ,GACDb,YAAY;AAAA,MACVf,MAAM;AAAA,MACNW,MAAM;AAAA,MACNE,OAAO;AAAA,MACPG,cAAc;AAAA,MACdM,QAAQA,CAAC;AAAA,QAACC;AAAAA,MAAAA,MAAYA,QAAQC,aAAa;AAAA,IAAA,CAC5C,CAAC;AAAA,IAEJK,SAAS;AAAA,MACPC,QAAQ;AAAA,QACNN,UAAU;AAAA,QACVO,KAAK;AAAA,QACLC,gBAAgB;AAAA,MAAA;AAAA,MAElBC,QAAQ;AAAA,QAACT,UAAAA;AAAAA,QAAUO;AAAAA,QAAKC;AAAAA,MAAAA,GAAiB;AAGvC,eAAO;AAAA,UACLnB,OAHYW,cAAa,aAAaO,OAAO,WAAWC,kBAAkB;AAAA,UAI1EE,UAAUV,cAAa,aAAa,kBAAkB;AAAA,QAAA;AAAA,MAE1D;AAAA,IAAA;AAAA,EACF,CACD;AACH;ACzDO,SAASA,SAASW,QAAsC;AAC7D,MAAIA,OAAO5B,cAAc6B,WAAW;AAClC,UAAM,IAAIC,MAAM,uEAAuE;AAGzF,SAAO;AAAA,IACLzC,OAAO,CAACU,eAAe6B,OAAO5B,aAAa,CAAC;AAAA,EAAA;AAEhD;"}
1
+ {"version":3,"file":"index.js","sources":["../src/__telemetry__/presets.telemetry.ts","../src/telemetry.ts","../src/components/PresetsTelemetryCollector.tsx","../src/presets/cta-type/index.ts","../src/presets/image-type/index.ts","../src/presets/link-type/index.ts","../src/presets/page-type/index.ts","../src/presets/rich-text-type/index.ts","../src/presets/seo-type/index.ts","../src/registry.tsx"],"sourcesContent":["import {defineEvent} from '@sanity/telemetry'\n\ninterface PresetsAddedInfo {\n presetNames: string[]\n}\n\nexport const PresetsAdded = defineEvent<PresetsAddedInfo>({\n name: 'Presets Added',\n version: 1,\n description: 'Workspace using presets was accessed',\n})\n","import {PresetsAdded} from './__telemetry__/presets.telemetry'\n\n/**\n * Minimal interface for the subset of TelemetryLogger we need.\n * Avoids forcing callers to satisfy the full generic TelemetryLogger type.\n */\nexport interface TelemetryLog {\n log(event: unknown, data: unknown): void\n}\n\ninterface RegistryRecord {\n id: string\n presets: Set<string>\n logged: boolean\n}\n\nconst registries = new Map<string, RegistryRecord>()\n\nexport function registerRegistry(id: string): void {\n registries.set(id, {id, presets: new Set(), logged: false})\n}\n\nexport function recordPresetUsage(registryId: string, identifier: string): void {\n registries.get(registryId)?.presets.add(identifier)\n}\n\nexport function collectPresetsRegistryTelemetry(registryId: string, telemetry: TelemetryLog): void {\n const record = registries.get(registryId)\n if (!record || record.logged) return\n record.logged = true\n if (record.presets.size > 0) {\n telemetry.log(PresetsAdded, {presetNames: [...record.presets]})\n }\n}\n\n/** @internal */\nexport function resetRegistries(): void {\n registries.clear()\n}\n","import {useTelemetry} from '@sanity/telemetry/react'\nimport {useEffect, type ComponentType} from 'react'\nimport type {InputProps} from 'sanity'\n\nimport {collectPresetsRegistryTelemetry} from '../telemetry'\n\ntype Props = InputProps & {\n registryId: string\n userInput?: ComponentType<InputProps>\n}\n\n/**\n * A transparent input component wrapper that triggers telemetry collection\n * for the presets registry. Renders the user-provided input component if\n * supplied, otherwise the default input component unchanged.\n *\n * Attached to every schema type produced by a define<Type> function via\n * components.input. The first instance to render for a given registry id\n * submits the PresetsAdded telemetry event; subsequent renders are no-ops.\n */\nexport const PresetsTelemetryCollector: ComponentType<Props> = ({\n registryId,\n userInput: UserInput,\n ...props\n}) => {\n const telemetry = useTelemetry()\n\n useEffect(() => {\n collectPresetsRegistryTelemetry(registryId, telemetry)\n }, [registryId, telemetry])\n\n if (UserInput) {\n return <UserInput {...props} />\n }\n\n return props.renderDefault(props)\n}\n","import {defineField, defineType} from 'sanity'\n\nimport {definePresetType} from '../../definePresetType'\n\nexport const ctaType = definePresetType<{}, 'object', 'preview'>({\n name: 'cta',\n identifier: 'core.cta',\n schemaType: (config, registry) => {\n const {fields, ...objectConfig} = config\n\n return defineType({\n title: 'Call to action',\n ...objectConfig,\n type: 'object',\n fields: [\n registry.getPreset('link', {name: 'link', title: 'Link'}),\n defineField({\n name: 'level',\n title: 'Level',\n type: 'number',\n options: {\n layout: 'radio',\n list: [1, 2, 3],\n },\n }),\n ...(fields ?? []),\n ],\n preview: {\n select: {\n linkType: 'link.linkType',\n url: 'link.url',\n referenceTitle: 'link.reference.title',\n referenceName: 'link.reference.name',\n },\n prepare({linkType, url, referenceTitle, referenceName}) {\n const referenceLabel = referenceTitle || referenceName || 'No reference'\n const title = linkType === 'external' ? url || 'No URL' : referenceLabel\n return {title, subtitle: 'Button'}\n },\n },\n })\n },\n})\n","import {defineField, defineType} from 'sanity'\n\nimport {definePresetType} from '../../definePresetType'\n\nexport interface ImageTypeConfig {\n altText?: boolean\n caption?: boolean\n hotspot?: boolean\n}\n\nexport const imageType = definePresetType<ImageTypeConfig, 'object', 'preview'>({\n name: 'image',\n identifier: 'core.image',\n schemaType: (config) => {\n const {altText = true, caption = true, hotspot = true, fields, ...objectConfig} = config\n\n return defineType({\n title: 'Image',\n ...objectConfig,\n type: 'object',\n fields: [\n defineField({\n name: 'image',\n title: 'Image',\n type: 'image',\n options: {\n hotspot,\n },\n }),\n ...(altText\n ? [\n defineField({\n name: 'altText',\n title: 'Alt text',\n type: 'string',\n validation: (rule) => rule.warning('Alt text improves accessibility.'),\n }),\n ]\n : []),\n ...(caption\n ? [\n defineField({\n name: 'caption',\n title: 'Caption',\n type: 'text',\n }),\n ]\n : []),\n ...(fields ?? []),\n ],\n preview: {\n select: {\n title: altText ? 'altText' : caption ? 'caption' : 'image.asset.originalFilename',\n media: 'image',\n },\n },\n })\n },\n})\n","import {defineField, defineType} from 'sanity'\n\nimport {definePresetType} from '../../definePresetType'\n\nexport interface LinkTypeConfig {\n internalTypes?: string[]\n}\n\nexport const linkType = definePresetType<LinkTypeConfig, 'object', 'preview'>({\n name: 'link',\n identifier: 'core.link',\n schemaType: ({internalTypes, fields, ...objectConfig}) => {\n const resolvedInternalTypes = internalTypes ?? []\n const referenceTargets = resolvedInternalTypes.map((type) => ({type}))\n\n return defineType({\n title: 'Link',\n ...objectConfig,\n type: 'object',\n fields: [\n defineField({\n name: 'linkType',\n type: 'string',\n title: 'Link Type',\n initialValue: 'internal',\n options: {\n layout: 'radio',\n list: [\n {title: 'Internal', value: 'internal'},\n {title: 'External', value: 'external'},\n ],\n },\n }),\n defineField({\n name: 'reference',\n type: 'reference',\n title: 'Internal Link',\n to: referenceTargets,\n hidden: ({parent}) => parent?.linkType === 'external',\n }),\n defineField({\n name: 'url',\n type: 'url',\n title: 'URL',\n hidden: ({parent}) => parent?.linkType === 'internal',\n validation: (rule) =>\n rule.uri({\n scheme: ['http', 'https', 'mailto', 'tel'],\n }),\n }),\n defineField({\n name: 'openInNewTab',\n type: 'boolean',\n title: 'Open in New Tab',\n initialValue: false,\n hidden: ({parent}) => parent?.linkType === 'internal',\n }),\n ...(fields ?? []),\n ],\n preview: {\n select: {\n linkType: 'linkType',\n url: 'url',\n referenceTitle: 'reference.title',\n referenceName: 'reference.name',\n },\n prepare({linkType, url, referenceTitle, referenceName}) {\n const referenceLabel = referenceTitle || referenceName || 'No reference'\n const title = linkType === 'external' ? url || 'No URL' : referenceLabel\n\n return {\n title,\n subtitle: linkType === 'external' ? 'External link' : 'Internal link',\n }\n },\n },\n })\n },\n})\n","import {ALL_FIELDS_GROUP, defineArrayMember, defineField, defineType} from 'sanity'\n\nimport {definePresetType} from '../../definePresetType'\n\nexport interface PageTypeConfig {\n pageBuilderBlocks?: string[]\n}\n\nexport const pageType = definePresetType<PageTypeConfig, 'document'>({\n name: 'page',\n identifier: 'core.page',\n schemaType: (config, registry) => {\n const {pageBuilderBlocks, groups, fields, ...documentConfig} = config\n\n return defineType({\n title: 'Page',\n ...documentConfig,\n type: 'document',\n groups: [\n {\n ...ALL_FIELDS_GROUP,\n hidden: true,\n },\n {\n name: 'main',\n title: 'Main',\n default: true,\n },\n {\n name: 'metadata',\n title: 'Metadata',\n },\n ...(groups ?? []),\n ],\n fields: [\n defineField({\n name: 'name',\n title: 'Name',\n type: 'string',\n group: 'main',\n validation: (rule) => rule.required(),\n }),\n defineField({\n name: 'slug',\n title: 'Slug',\n type: 'slug',\n group: 'main',\n options: {\n source: 'name',\n },\n }),\n defineField({\n name: 'content',\n title: 'Content',\n group: 'main',\n type: 'array',\n of: (pageBuilderBlocks ?? []).map((typeName) =>\n defineArrayMember({\n type: typeName,\n }),\n ),\n }),\n registry.getPreset('seo', {\n name: 'seo',\n title: 'SEO',\n group: 'metadata',\n }),\n ...(fields ?? []),\n ],\n })\n },\n})\n","import {defineArrayMember, defineType} from 'sanity'\n\nimport {definePresetType} from '../../definePresetType'\n\nexport interface RichTextObjectsConfig {\n link?: boolean\n image?: boolean\n cta?: boolean\n}\n\nexport interface RichTextTypeConfig {\n /**\n * Toggle the embedded objects (link annotations, image blocks, inline CTAs).\n * Defaults to all enabled. Pass `false` to disable every object, or an\n * object to toggle individual ones (e.g. `{link: false}`).\n *\n * Each object's options (link `internalTypes`, image `altText`, …) are\n * configured on `createPresetsRegistry` and cascade into every rich text\n * field. Use `map.of` for per-field structural changes.\n */\n objects?: boolean | RichTextObjectsConfig\n}\n\nfunction resolveObjects(objects: RichTextTypeConfig['objects']): Required<RichTextObjectsConfig> {\n if (objects === false) return {link: false, image: false, cta: false}\n if (objects === true || objects === undefined) return {link: true, image: true, cta: true}\n const {link = true, image = true, cta = true} = objects\n return {link, image, cta}\n}\n\nexport const richTextType = definePresetType<RichTextTypeConfig, 'array', 'of'>({\n name: 'richText',\n identifier: 'core.richText',\n schemaType: (config, registry) => {\n const {objects, ...arrayConfig} = config\n const {link, image, cta} = resolveObjects(objects)\n\n // The annotation name must be 'link' — Portable Text Editor's built-in link UI keys off this name.\n const linkAnnotation = link\n ? registry.getPreset('link', {name: 'link', title: 'Link'})\n : undefined\n const ctaInline = cta ? registry.getPreset('cta', {name: 'cta', title: 'CTA'}) : undefined\n const imageMember = image\n ? registry.getPreset('image', {name: 'richTextImage', title: 'Image'})\n : undefined\n\n const blockMember = defineArrayMember({\n type: 'block',\n marks: {annotations: linkAnnotation ? [linkAnnotation] : []},\n ...(ctaInline && {of: [ctaInline]}),\n })\n\n return defineType({\n title: 'Rich text',\n ...arrayConfig,\n type: 'array',\n of: imageMember ? [blockMember, imageMember] : [blockMember],\n })\n },\n})\n","import {getImageDimensions} from '@sanity/asset-utils'\nimport {defineField, defineType} from 'sanity'\n\nimport {definePresetType} from '../../definePresetType'\n\nexport const seoType = definePresetType<{}, 'object'>({\n name: 'seo',\n identifier: 'core.seo',\n schemaType: (config) => {\n const {fields, ...objectConfig} = config\n\n return defineType({\n title: 'Web page metadata (SEO)',\n ...objectConfig,\n type: 'object',\n fields: [\n defineField({\n name: 'title',\n title: 'Title',\n type: 'string',\n validation: (rule) => rule.max(70).info('Search engines may truncate this title.'),\n }),\n defineField({\n name: 'description',\n title: 'Description',\n type: 'text',\n validation: (rule) => rule.max(150).info('Search engines may truncate this description.'),\n }),\n defineField({\n name: 'ogImage',\n title: 'Open Graph image',\n type: 'image',\n description: 'Landscape 1200x630 (1.91:1)',\n options: {\n hotspot: {\n previews: [\n {\n title: 'Landscape (1.91:1)',\n aspectRatio: 1.91 / 1,\n },\n ],\n },\n },\n validation: (Rule) =>\n Rule.custom((value) => {\n if (!value?.asset?._ref) {\n return true\n }\n\n const {height, width} = getImageDimensions(value.asset?._ref)\n\n if (height !== 630 || width !== 1200) {\n return 'Open Graph image must be 1200x630'\n }\n\n return true\n }),\n }),\n ...(fields ?? []),\n ],\n })\n },\n})\n","import {uuid} from '@sanity/uuid'\nimport {type ComponentType} from 'react'\nimport type {FieldDefinition, InputProps, SchemaTypeDefinition} from 'sanity'\n\nimport {PresetsTelemetryCollector} from './components/PresetsTelemetryCollector'\nimport type {\n AnyPresetDefinition,\n PresetDefinition,\n RegistryContext,\n UserConfig,\n} from './definePresetType'\nimport {ctaType} from './presets/cta-type'\nimport {imageType, type ImageTypeConfig} from './presets/image-type'\nimport {linkType, type LinkTypeConfig} from './presets/link-type'\nimport {pageType, type PageTypeConfig} from './presets/page-type'\nimport {richTextType} from './presets/rich-text-type'\nimport {seoType} from './presets/seo-type'\nimport {recordPresetUsage, registerRegistry} from './telemetry'\n\nconst systemPresets = [linkType, ctaType, seoType, imageType, pageType, richTextType] as const\n\nexport interface PresetsRegistryConfig {\n link?: LinkTypeConfig\n image?: ImageTypeConfig\n page?: PageTypeConfig\n}\n\ntype DefineFunction<Preset extends AnyPresetDefinition> =\n Preset extends PresetDefinition<infer Context, infer AliasedType, infer LockedProperties>\n ? (\n config?: UserConfig<Context, AliasedType, LockedProperties>,\n ) => SchemaTypeDefinition & FieldDefinition\n : never\n\nexport interface PresetsRegistry {\n defineLink: DefineFunction<typeof linkType>\n defineCta: DefineFunction<typeof ctaType>\n defineSeo: DefineFunction<typeof seoType>\n defineImage: DefineFunction<typeof imageType>\n definePage: DefineFunction<typeof pageType>\n defineRichText: DefineFunction<typeof richTextType>\n}\n\nexport function createPresetsRegistry(config: PresetsRegistryConfig = {}): PresetsRegistry {\n const registryId = uuid()\n registerRegistry(registryId)\n\n // oxlint-disable-next-line no-unsafe-type-assertion -- seeding reduce with an empty object that is populated by each iteration\n const seed = {} as DefinerRecord & PresetsRegistry\n\n return systemPresets.reduce((registry, preset) => {\n const key = getPresetKey(preset.name)\n registry[key] = createDefiner({registryId, preset, config, registry})\n return registry\n }, seed)\n}\n\nexport function getPresetKey(name: string): string {\n return `define${name.charAt(0).toUpperCase()}${name.slice(1)}`\n}\n\ntype Definer = (config?: Record<string, unknown>) => SchemaTypeDefinition & FieldDefinition\ntype DefinerRecord = Record<string, Definer>\n\nfunction createRegistryContext({registry}: {registry: DefinerRecord}): RegistryContext {\n return {\n getPreset: (name, presetConfig) => {\n const key = getPresetKey(name)\n const definer = registry[key]\n if (!definer) {\n throw new Error(`Cannot resolve preset \"${name}\". No such preset in this registry.`)\n }\n return definer(presetConfig)\n },\n }\n}\n\ninterface CreateDefinerOptions {\n registryId: string\n preset: AnyPresetDefinition\n config: PresetsRegistryConfig\n registry: DefinerRecord\n}\n\nfunction createDefiner({registryId, preset, config, registry}: CreateDefinerOptions): Definer {\n return function define(userConfig = {}) {\n recordPresetUsage(registryId, preset.identifier ?? 'unnamed')\n\n const registryContext = createRegistryContext({registry})\n\n // oxlint-disable-next-line no-unsafe-type-assertion -- PresetsRegistryConfig is keyed by preset name; dynamic lookup is safe\n const registryDefaults = (config as Record<string, unknown>)[preset.name]\n const mergedConfig: Record<string, unknown> = {\n name: preset.name,\n ...(typeof registryDefaults === 'object' && registryDefaults !== null\n ? registryDefaults\n : {}),\n ...userConfig,\n }\n\n const {map, ...factoryConfig} = mergedConfig\n\n const schemaType = preset.schemaType(\n // oxlint-disable-next-line no-unsafe-type-assertion -- factoryConfig is the merged user config (minus `map`, with `name` injected); its shape matches the factory's expected parameter at runtime\n factoryConfig as unknown as Parameters<AnyPresetDefinition['schemaType']>[0],\n registryContext,\n )\n\n // oxlint-disable-next-line no-unsafe-type-assertion -- runtime value is a valid field definition\n return applyMapHooks(\n addTelemetryComponent(schemaType, registryId),\n map,\n ) as SchemaTypeDefinition & FieldDefinition\n }\n}\n\nfunction applyMapHooks(schemaType: SchemaTypeDefinition, map: unknown): SchemaTypeDefinition {\n if (!map || typeof map !== 'object') return schemaType\n\n const mappedSchemaType: Record<string, unknown> = {}\n\n for (const [configName, configValue] of Object.entries(map)) {\n if (typeof configValue !== 'function') {\n continue\n }\n\n mappedSchemaType[configName] = configValue(\n // oxlint-disable-next-line no-unsafe-type-assertion -- map hooks operate on arbitrary schema type properties\n schemaType[configName as keyof typeof schemaType],\n )\n }\n\n return {...schemaType, ...mappedSchemaType}\n}\n\nfunction addTelemetryComponent(\n schemaType: SchemaTypeDefinition,\n registryId: string,\n): SchemaTypeDefinition {\n const existing = 'components' in schemaType ? schemaType.components : undefined\n const existingInput =\n existing && 'input' in existing && typeof existing.input === 'function'\n ? // oxlint-disable-next-line no-unsafe-type-assertion -- presets only produce object/document schema types, whose input components are assignable to ComponentType<InputProps>\n (existing.input as ComponentType<InputProps>)\n : undefined\n // oxlint-disable-next-line no-unsafe-type-assertion -- spreading a discriminated union loses the discriminant; the runtime shape is still a valid SchemaTypeDefinition\n return {\n ...schemaType,\n components: {\n ...existing,\n input: (props: InputProps) => (\n <PresetsTelemetryCollector {...props} registryId={registryId} userInput={existingInput} />\n ),\n },\n } as SchemaTypeDefinition\n}\n\n// Re-export for consumers that previously used these types.\nexport type {PresetDefinition, AnyPresetDefinition}\n"],"names":["PresetsAdded","defineEvent","name","version","description","registries","Map","registerRegistry","id","set","presets","Set","logged","recordPresetUsage","registryId","identifier","get","add","collectPresetsRegistryTelemetry","telemetry","record","size","log","presetNames","PresetsTelemetryCollector","t0","$","_c","userInput","UserInput","props","useTelemetry","t1","t2","useEffect","renderDefault","ctaType","schemaType","config","registry","fields","objectConfig","defineType","title","type","getPreset","defineField","options","layout","list","preview","select","linkType","url","referenceTitle","referenceName","prepare","subtitle","imageType","altText","caption","hotspot","validation","rule","warning","media","internalTypes","referenceTargets","map","initialValue","value","to","hidden","parent","uri","scheme","pageType","pageBuilderBlocks","groups","documentConfig","ALL_FIELDS_GROUP","default","group","required","source","of","typeName","defineArrayMember","resolveObjects","objects","link","image","cta","undefined","richTextType","arrayConfig","linkAnnotation","ctaInline","imageMember","blockMember","marks","annotations","seoType","max","info","previews","aspectRatio","Rule","custom","asset","_ref","height","width","getImageDimensions","systemPresets","createPresetsRegistry","uuid","seed","reduce","preset","key","getPresetKey","createDefiner","charAt","toUpperCase","slice","createRegistryContext","presetConfig","definer","Error","userConfig","registryContext","registryDefaults","mergedConfig","factoryConfig","applyMapHooks","addTelemetryComponent","mappedSchemaType","configName","configValue","Object","entries","existing","components","existingInput","input"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/presets",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "Production ready preset patterns for Sanity Studio",
5
5
  "keywords": [
6
6
  "sanity",
@@ -26,13 +26,29 @@
26
26
  ".": "./dist/index.js",
27
27
  "./package.json": "./package.json"
28
28
  },
29
+ "dependencies": {
30
+ "@sanity/asset-utils": "^2.3.0",
31
+ "@sanity/telemetry": "^1.1.0",
32
+ "@sanity/uuid": "^3.0.2"
33
+ },
29
34
  "devDependencies": {
30
- "@sanity/pkg-utils": "^10.4.11",
31
- "sanity": "^5.17.1",
35
+ "@sanity/pkg-utils": "^10.4.17",
36
+ "@testing-library/jest-dom": "^6.9.1",
37
+ "@testing-library/react": "^16.3.2",
38
+ "@types/node": "^24.12.2",
39
+ "@types/react": "^19.2.14",
40
+ "@types/react-dom": "^19.2.3",
41
+ "jsdom": "^29.0.1",
42
+ "react": "^19.2.5",
43
+ "react-dom": "^19.2.5",
44
+ "sanity": "^5.21.0",
45
+ "styled-components": "^6.4.1",
32
46
  "@repo/package.config": "0.0.0",
33
47
  "@repo/tsconfig": "0.0.0"
34
48
  },
35
49
  "peerDependencies": {
50
+ "react": "^19.2",
51
+ "react-dom": "^19.2",
36
52
  "sanity": "^5"
37
53
  },
38
54
  "engines": {