@sanity/presets 0.5.2 → 1.0.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/dist/index.js CHANGED
@@ -1,489 +1,446 @@
1
- import { jsx } from "react/jsx-runtime";
2
1
  import { uuid } from "@sanity/uuid";
2
+ import { useEffect } from "react";
3
3
  import { c } from "react/compiler-runtime";
4
4
  import { useTelemetry } from "@sanity/telemetry/react";
5
- import { useEffect } from "react";
6
5
  import { defineEvent } from "@sanity/telemetry";
7
- import { defineType, defineField, ALL_FIELDS_GROUP, defineArrayMember } from "sanity";
6
+ import { jsx } from "react/jsx-runtime";
7
+ import { ALL_FIELDS_GROUP, defineArrayMember, defineField, defineType } from "sanity";
8
8
  import { getImageDimensions } from "@sanity/asset-utils";
9
9
  const PresetsAdded = defineEvent({
10
- name: "Presets Added",
11
- version: 1,
12
- description: "Workspace using presets was accessed"
10
+ name: "Presets Added",
11
+ version: 1,
12
+ description: "Workspace using presets was accessed"
13
13
  }), registries = /* @__PURE__ */ new Map();
14
14
  function registerRegistry(id) {
15
- registries.set(id, {
16
- id,
17
- presets: /* @__PURE__ */ new Set(),
18
- logged: !1
19
- });
15
+ registries.set(id, {
16
+ id,
17
+ presets: /* @__PURE__ */ new Set(),
18
+ logged: !1
19
+ });
20
20
  }
21
21
  function recordPresetUsage(registryId, identifier) {
22
- registries.get(registryId)?.presets.add(identifier);
22
+ registries.get(registryId)?.presets.add(identifier);
23
23
  }
24
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]
28
- }));
25
+ let record = registries.get(registryId);
26
+ !record || record.logged || (record.logged = !0, record.presets.size > 0 && telemetry.log(PresetsAdded, { presetNames: [...record.presets] }));
29
27
  }
28
+ /**
29
+ * A transparent input component wrapper that triggers telemetry collection
30
+ * for the presets registry. Renders the user-provided input component if
31
+ * supplied, otherwise the default input component unchanged.
32
+ *
33
+ * Attached to every schema type produced by a define<Type> function via
34
+ * components.input. The first instance to render for a given registry id
35
+ * submits the PresetsAdded telemetry event; subsequent renders are no-ops.
36
+ */
30
37
  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
- ...objectConfig,
51
- type: "object",
52
- fields: [registry.getPreset("link", {
53
- name: "link",
54
- title: "Link"
55
- }), defineField({
56
- name: "level",
57
- title: "Level",
58
- description: "The importance of the action relative to its siblings: level 1 being the primary action, 2 the secondary action, and so on.",
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
- ...imageConfig
96
- } = config;
97
- return defineType({
98
- ...imageConfig,
99
- type: "image",
100
- // hotspot is the curated default; callers override other image options (accept, sources, storeOriginalFilename) via the map.options hook
101
- options: {
102
- hotspot
103
- },
104
- fields: [...altText ? [defineField({
105
- name: "altText",
106
- title: "Alt text",
107
- description: "Describes the image for screen readers and search engines. Important for accessibility.",
108
- type: "string",
109
- validation: (rule) => rule.warning("Alt text improves accessibility.")
110
- })] : [], ...caption ? [defineField({
111
- name: "caption",
112
- title: "Caption",
113
- type: "text"
114
- })] : [], ...fields ?? []],
115
- preview: {
116
- select: {
117
- title: altText ? "altText" : caption ? "caption" : "asset.originalFilename"
118
- }
119
- }
120
- });
121
- }
38
+ let $ = c(4), { registryId, userInput: UserInput, ...props } = t0, telemetry = useTelemetry(), t1, t2;
39
+ return $[0] !== registryId || $[1] !== telemetry ? (t1 = () => {
40
+ collectPresetsRegistryTelemetry(registryId, telemetry);
41
+ }, 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);
122
42
  };
43
+ /**
44
+ * A typed passthrough for defining a preset. Given a `PresetDefinition`, it
45
+ * returns the same value, narrowed to its concrete generic parameters so
46
+ * downstream code can infer the preset's config type from it.
47
+ *
48
+ * This is intentionally lightweight: it performs no work at call time. The
49
+ * registry is responsible for invoking `schemaType` when a preset is
50
+ * instantiated, and for applying `map` hooks to the produced schema type.
51
+ */
52
+ function definePresetType(preset) {
53
+ return preset;
54
+ }
55
+ const ctaType = definePresetType({
56
+ name: "cta",
57
+ identifier: "core.cta",
58
+ schemaType: (config, registry) => {
59
+ let { fields, ...objectConfig } = config;
60
+ return defineType({
61
+ ...objectConfig,
62
+ type: "object",
63
+ fields: [
64
+ registry.getPreset("link", {
65
+ name: "link",
66
+ title: "Link"
67
+ }),
68
+ defineField({
69
+ name: "level",
70
+ title: "Level",
71
+ description: "The importance of the action relative to its siblings: level 1 being the primary action, 2 the secondary action, and so on.",
72
+ type: "number",
73
+ options: {
74
+ layout: "radio",
75
+ list: [
76
+ 1,
77
+ 2,
78
+ 3
79
+ ]
80
+ }
81
+ }),
82
+ ...fields ?? []
83
+ ],
84
+ preview: {
85
+ select: {
86
+ linkType: "link.linkType",
87
+ url: "link.url",
88
+ referenceTitle: "link.reference.title",
89
+ referenceName: "link.reference.name"
90
+ },
91
+ prepare({ linkType, url, referenceTitle, referenceName }) {
92
+ return {
93
+ title: linkType === "external" ? url || "No URL" : referenceTitle || referenceName || "No reference",
94
+ subtitle: "Button"
95
+ };
96
+ }
97
+ }
98
+ });
99
+ }
100
+ }), imageType = definePresetType({
101
+ name: "image",
102
+ identifier: "core.image",
103
+ schemaType: (config) => {
104
+ let { altText = !0, caption = !0, hotspot = !0, fields, ...imageConfig } = config;
105
+ return defineType({
106
+ ...imageConfig,
107
+ type: "image",
108
+ options: { hotspot },
109
+ fields: [
110
+ ...altText ? [defineField({
111
+ name: "altText",
112
+ title: "Alt text",
113
+ description: "Describes the image for screen readers and search engines. Important for accessibility.",
114
+ type: "string",
115
+ validation: (rule) => rule.warning("Alt text improves accessibility.")
116
+ })] : [],
117
+ ...caption ? [defineField({
118
+ name: "caption",
119
+ title: "Caption",
120
+ type: "text"
121
+ })] : [],
122
+ ...fields ?? []
123
+ ],
124
+ preview: { select: { title: altText ? "altText" : caption ? "caption" : "asset.originalFilename" } }
125
+ });
126
+ }
127
+ });
123
128
  function normalizeToTargets(entries) {
124
- return entries.map((entry) => typeof entry == "string" ? {
125
- type: entry
126
- } : entry);
129
+ return entries.map((entry) => typeof entry == "string" ? { type: entry } : entry);
127
130
  }
128
- const linkType = {
129
- name: "link",
130
- identifier: "core.link",
131
- schemaType: ({
132
- to,
133
- fields,
134
- ...objectConfig
135
- }) => {
136
- const referenceTargets = normalizeToTargets(to ?? []);
137
- return defineType({
138
- ...objectConfig,
139
- type: "object",
140
- fields: [defineField({
141
- name: "linkType",
142
- type: "string",
143
- title: "Link Type",
144
- description: "Internal links point to a page in this project. External links point to a full URL.",
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
- description: "Full URL including protocol, e.g. https://example.com. Supports http, https, mailto, and tel.",
169
- hidden: ({
170
- parent
171
- }) => parent?.linkType === "internal",
172
- validation: (rule) => rule.uri({
173
- scheme: ["http", "https", "mailto", "tel"]
174
- })
175
- }), defineField({
176
- name: "openInNewTab",
177
- type: "boolean",
178
- title: "Open in New Tab",
179
- initialValue: !1,
180
- hidden: ({
181
- parent
182
- }) => parent?.linkType === "internal"
183
- }), ...fields ?? []],
184
- preview: {
185
- select: {
186
- linkType: "linkType",
187
- url: "url",
188
- referenceTitle: "reference.title",
189
- referenceName: "reference.name"
190
- },
191
- prepare({
192
- linkType: linkType2,
193
- url,
194
- referenceTitle,
195
- referenceName
196
- }) {
197
- return {
198
- title: linkType2 === "external" ? url || "No URL" : referenceTitle || referenceName || "No reference",
199
- subtitle: linkType2 === "external" ? "External link" : "Internal link"
200
- };
201
- }
202
- }
203
- });
204
- }
205
- };
131
+ const linkType = definePresetType({
132
+ name: "link",
133
+ identifier: "core.link",
134
+ schemaType: ({ to, fields, ...objectConfig }) => {
135
+ let referenceTargets = normalizeToTargets(to ?? []);
136
+ return defineType({
137
+ ...objectConfig,
138
+ type: "object",
139
+ fields: [
140
+ defineField({
141
+ name: "linkType",
142
+ type: "string",
143
+ title: "Link Type",
144
+ description: "Internal links point to a page in this project. External links point to a full URL.",
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
+ }),
157
+ defineField({
158
+ name: "reference",
159
+ type: "reference",
160
+ title: "Internal Link",
161
+ to: referenceTargets,
162
+ hidden: ({ parent }) => parent?.linkType === "external"
163
+ }),
164
+ defineField({
165
+ name: "url",
166
+ type: "url",
167
+ title: "URL",
168
+ description: "Full URL including protocol, e.g. https://example.com. Supports http, https, mailto, and tel.",
169
+ hidden: ({ parent }) => parent?.linkType === "internal",
170
+ validation: (rule) => rule.uri({ scheme: [
171
+ "http",
172
+ "https",
173
+ "mailto",
174
+ "tel"
175
+ ] })
176
+ }),
177
+ defineField({
178
+ name: "openInNewTab",
179
+ type: "boolean",
180
+ title: "Open in New Tab",
181
+ initialValue: !1,
182
+ hidden: ({ parent }) => parent?.linkType === "internal"
183
+ }),
184
+ ...fields ?? []
185
+ ],
186
+ preview: {
187
+ select: {
188
+ linkType: "linkType",
189
+ url: "url",
190
+ referenceTitle: "reference.title",
191
+ referenceName: "reference.name"
192
+ },
193
+ prepare({ linkType, url, referenceTitle, referenceName }) {
194
+ return {
195
+ title: linkType === "external" ? url || "No URL" : referenceTitle || referenceName || "No reference",
196
+ subtitle: linkType === "external" ? "External link" : "Internal link"
197
+ };
198
+ }
199
+ }
200
+ });
201
+ }
202
+ });
206
203
  function wrapArrayAsPageBuilderBlock(arraySchema) {
207
- const components = "components" in arraySchema ? arraySchema.components : void 0;
208
- return defineArrayMember({
209
- name: arraySchema.name,
210
- title: arraySchema.title,
211
- type: "object",
212
- fields: [defineField({
213
- name: "content",
214
- type: "array",
215
- of: arraySchema.of,
216
- components
217
- })]
218
- });
204
+ let components = "components" in arraySchema ? arraySchema.components : void 0;
205
+ return defineArrayMember({
206
+ name: arraySchema.name,
207
+ title: arraySchema.title,
208
+ type: "object",
209
+ fields: [defineField({
210
+ name: "content",
211
+ type: "array",
212
+ of: arraySchema.of,
213
+ components
214
+ })]
215
+ });
219
216
  }
220
217
  function toPageBuilderArrayMember(block, lookupArrayPreset) {
221
- if (typeof block == "string") {
222
- const arrayPreset = lookupArrayPreset(block);
223
- return arrayPreset ? wrapArrayAsPageBuilderBlock(arrayPreset) : defineArrayMember({
224
- type: block
225
- });
226
- }
227
- return block.type === "array" ? wrapArrayAsPageBuilderBlock(block) : defineArrayMember(block);
218
+ if (typeof block == "string") {
219
+ let arrayPreset = lookupArrayPreset(block);
220
+ return arrayPreset ? wrapArrayAsPageBuilderBlock(arrayPreset) : defineArrayMember({ type: block });
221
+ }
222
+ return block.type === "array" ? wrapArrayAsPageBuilderBlock(block) : defineArrayMember(block);
228
223
  }
229
224
  function defineLazyContentField(blocks, lookupArrayPreset) {
230
- let cached;
231
- return defineField({
232
- name: "content",
233
- title: "Content",
234
- description: "Page sections rendered in order. Add, remove, or reorder blocks to build the page.",
235
- group: "main",
236
- type: "array",
237
- get of() {
238
- return cached ??= blocks.map((block) => toPageBuilderArrayMember(block, lookupArrayPreset)), cached;
239
- }
240
- });
225
+ let cached;
226
+ return defineField({
227
+ name: "content",
228
+ title: "Content",
229
+ description: "Page sections rendered in order. Add, remove, or reorder blocks to build the page.",
230
+ group: "main",
231
+ type: "array",
232
+ get of() {
233
+ return cached ??= blocks.map((block) => toPageBuilderArrayMember(block, lookupArrayPreset)), cached;
234
+ }
235
+ });
241
236
  }
242
- function createPageType({
243
- lookupArrayPreset
244
- }) {
245
- return {
246
- name: "page",
247
- identifier: "core.page",
248
- schemaType: (config, registry) => {
249
- const {
250
- pageBuilderBlocks,
251
- groups,
252
- fields,
253
- ...documentConfig
254
- } = config;
255
- return defineType({
256
- ...documentConfig,
257
- type: "document",
258
- groups: [{
259
- ...ALL_FIELDS_GROUP,
260
- hidden: !0
261
- }, {
262
- name: "main",
263
- title: "Main",
264
- default: !0
265
- }, {
266
- name: "metadata",
267
- title: "Metadata"
268
- }, ...groups ?? []],
269
- fields: [defineField({
270
- name: "name",
271
- title: "Name",
272
- description: "Used as the page title and as the source for the auto-generated slug.",
273
- type: "string",
274
- group: "main",
275
- validation: (rule) => rule.required()
276
- }), defineField({
277
- name: "slug",
278
- title: "Slug",
279
- type: "slug",
280
- group: "main",
281
- options: {
282
- source: "name"
283
- }
284
- }), defineLazyContentField(pageBuilderBlocks ?? [], lookupArrayPreset), registry.getPreset("seo", {
285
- name: "seo",
286
- title: "SEO",
287
- group: "metadata"
288
- }), ...fields ?? []]
289
- });
290
- }
291
- };
237
+ function createPageType({ lookupArrayPreset }) {
238
+ return definePresetType({
239
+ name: "page",
240
+ identifier: "core.page",
241
+ schemaType: (config, registry) => {
242
+ let { pageBuilderBlocks, groups, fields, ...documentConfig } = config;
243
+ return defineType({
244
+ ...documentConfig,
245
+ type: "document",
246
+ groups: [
247
+ {
248
+ ...ALL_FIELDS_GROUP,
249
+ hidden: !0
250
+ },
251
+ {
252
+ name: "main",
253
+ title: "Main",
254
+ default: !0
255
+ },
256
+ {
257
+ name: "metadata",
258
+ title: "Metadata"
259
+ },
260
+ ...groups ?? []
261
+ ],
262
+ fields: [
263
+ defineField({
264
+ name: "name",
265
+ title: "Name",
266
+ description: "Used as the page title and as the source for the auto-generated slug.",
267
+ type: "string",
268
+ group: "main",
269
+ validation: (rule) => rule.required()
270
+ }),
271
+ defineField({
272
+ name: "slug",
273
+ title: "Slug",
274
+ type: "slug",
275
+ group: "main",
276
+ options: { source: "name" }
277
+ }),
278
+ defineLazyContentField(pageBuilderBlocks ?? [], lookupArrayPreset),
279
+ registry.getPreset("seo", {
280
+ name: "seo",
281
+ title: "SEO",
282
+ group: "metadata"
283
+ }),
284
+ ...fields ?? []
285
+ ]
286
+ });
287
+ }
288
+ });
292
289
  }
290
+ createPageType({ lookupArrayPreset: () => void 0 });
293
291
  function resolveObjects(objects) {
294
- if (objects === !1) return {
295
- link: !1,
296
- image: !1,
297
- cta: !1
298
- };
299
- if (objects === !0 || objects === void 0) return {
300
- link: !0,
301
- image: !0,
302
- cta: !0
303
- };
304
- const {
305
- link = !0,
306
- image = !0,
307
- cta = !0
308
- } = objects;
309
- return {
310
- link,
311
- image,
312
- cta
313
- };
292
+ if (objects === !1) return {
293
+ link: !1,
294
+ image: !1,
295
+ cta: !1
296
+ };
297
+ if (objects === !0 || objects === void 0) return {
298
+ link: !0,
299
+ image: !0,
300
+ cta: !0
301
+ };
302
+ let { link = !0, image = !0, cta = !0 } = objects;
303
+ return {
304
+ link,
305
+ image,
306
+ cta
307
+ };
314
308
  }
315
- const richTextType = {
316
- name: "richText",
317
- identifier: "core.richText",
318
- schemaType: (config, registry) => {
319
- const {
320
- objects,
321
- ...arrayConfig
322
- } = config, {
323
- link,
324
- image,
325
- cta
326
- } = resolveObjects(objects), linkAnnotation = link ? registry.getPreset("link", {
327
- name: "link",
328
- title: "Link"
329
- }) : void 0, ctaInline = cta ? registry.getPreset("cta", {
330
- name: "cta",
331
- title: "CTA"
332
- }) : void 0, imageMember = image ? registry.getPreset("image", {
333
- name: "richTextImage",
334
- title: "Image"
335
- }) : void 0, blockMember = defineArrayMember({
336
- type: "block",
337
- marks: {
338
- annotations: linkAnnotation ? [linkAnnotation] : []
339
- },
340
- ...ctaInline && {
341
- of: [ctaInline]
342
- }
343
- });
344
- return defineType({
345
- ...arrayConfig,
346
- type: "array",
347
- of: imageMember ? [blockMember, imageMember] : [blockMember]
348
- });
349
- }
350
- }, seoType = {
351
- name: "seo",
352
- identifier: "core.seo",
353
- schemaType: (config) => {
354
- const {
355
- fields,
356
- ...objectConfig
357
- } = config;
358
- return defineType({
359
- ...objectConfig,
360
- type: "object",
361
- fields: [defineField({
362
- name: "title",
363
- title: "Title",
364
- type: "string",
365
- validation: (rule) => rule.max(70).info("Search engines may truncate this title.")
366
- }), defineField({
367
- name: "description",
368
- title: "Description",
369
- type: "text",
370
- validation: (rule) => rule.max(150).info("Search engines may truncate this description.")
371
- }), defineField({
372
- name: "ogImage",
373
- title: "Open Graph image",
374
- type: "image",
375
- description: "Landscape 1200x630 (1.91:1)",
376
- options: {
377
- hotspot: {
378
- previews: [{
379
- title: "Landscape (1.91:1)",
380
- aspectRatio: 1.91 / 1
381
- }]
382
- }
383
- },
384
- validation: (Rule) => Rule.custom((value) => {
385
- if (!value?.asset?._ref)
386
- return !0;
387
- const {
388
- height,
389
- width
390
- } = getImageDimensions(value.asset?._ref);
391
- return height !== 630 || width !== 1200 ? "Open Graph images are recommended to be exactly 1200x630 (1.91:1) for the best social sharing previews." : !0;
392
- }).warning()
393
- }), ...fields ?? []]
394
- });
395
- }
396
- };
309
+ const richTextType = definePresetType({
310
+ name: "richText",
311
+ identifier: "core.richText",
312
+ schemaType: (config, registry) => {
313
+ let { objects, ...arrayConfig } = config, { link, image, cta } = resolveObjects(objects), linkAnnotation = link ? registry.getPreset("link", {
314
+ name: "link",
315
+ title: "Link"
316
+ }) : void 0, ctaInline = cta ? registry.getPreset("cta", {
317
+ name: "cta",
318
+ title: "CTA"
319
+ }) : void 0, imageMember = image ? registry.getPreset("image", {
320
+ name: "richTextImage",
321
+ title: "Image"
322
+ }) : void 0, blockMember = defineArrayMember({
323
+ type: "block",
324
+ marks: { annotations: linkAnnotation ? [linkAnnotation] : [] },
325
+ ...ctaInline && { of: [ctaInline] }
326
+ });
327
+ return defineType({
328
+ ...arrayConfig,
329
+ type: "array",
330
+ of: imageMember ? [blockMember, imageMember] : [blockMember]
331
+ });
332
+ }
333
+ }), seoType = definePresetType({
334
+ name: "seo",
335
+ identifier: "core.seo",
336
+ schemaType: (config) => {
337
+ let { fields, ...objectConfig } = config;
338
+ return defineType({
339
+ ...objectConfig,
340
+ type: "object",
341
+ fields: [
342
+ defineField({
343
+ name: "title",
344
+ title: "Title",
345
+ type: "string",
346
+ validation: (rule) => rule.max(70).info("Search engines may truncate this title.")
347
+ }),
348
+ defineField({
349
+ name: "description",
350
+ title: "Description",
351
+ type: "text",
352
+ validation: (rule) => rule.max(150).info("Search engines may truncate this description.")
353
+ }),
354
+ defineField({
355
+ name: "ogImage",
356
+ title: "Open Graph image",
357
+ type: "image",
358
+ description: "Landscape 1200x630 (1.91:1)",
359
+ options: { hotspot: { previews: [{
360
+ title: "Landscape (1.91:1)",
361
+ aspectRatio: 1.91 / 1
362
+ }] } },
363
+ validation: (Rule) => Rule.custom((value) => {
364
+ if (!value?.asset?._ref) return !0;
365
+ let { height, width } = getImageDimensions(value.asset?._ref);
366
+ return height !== 630 || width !== 1200 ? "Open Graph images are recommended to be exactly 1200x630 (1.91:1) for the best social sharing previews." : !0;
367
+ }).warning()
368
+ }),
369
+ ...fields ?? []
370
+ ]
371
+ });
372
+ }
373
+ });
397
374
  function createPresetsRegistry(config = {}) {
398
- const registryId = uuid();
399
- registerRegistry(registryId);
400
- const seed = {}, registeredSchemas = /* @__PURE__ */ new Map(), pageTypeWithLookup = createPageType({
401
- lookupArrayPreset: (name) => {
402
- const registered = registeredSchemas.get(name);
403
- return registered?.type === "array" ? registered : void 0;
404
- }
405
- });
406
- return [linkType, ctaType, seoType, imageType, pageTypeWithLookup, richTextType].reduce((registry, preset) => {
407
- const key = getPresetKey(preset.name);
408
- return registry[key] = createDefiner({
409
- registryId,
410
- preset,
411
- config,
412
- registry,
413
- registeredSchemas
414
- }), registry;
415
- }, seed);
375
+ let registryId = uuid();
376
+ registerRegistry(registryId);
377
+ let seed = {}, registeredSchemas = /* @__PURE__ */ new Map();
378
+ return [
379
+ linkType,
380
+ ctaType,
381
+ seoType,
382
+ imageType,
383
+ createPageType({ lookupArrayPreset: (name) => {
384
+ let registered = registeredSchemas.get(name);
385
+ return registered?.type === "array" ? registered : void 0;
386
+ } }),
387
+ richTextType
388
+ ].reduce((registry, preset) => {
389
+ let key = getPresetKey(preset.name);
390
+ return registry[key] = createDefiner({
391
+ registryId,
392
+ preset,
393
+ config,
394
+ registry,
395
+ registeredSchemas
396
+ }), registry;
397
+ }, seed);
416
398
  }
417
399
  function getPresetKey(name) {
418
- return `define${name.charAt(0).toUpperCase()}${name.slice(1)}`;
400
+ return `define${name.charAt(0).toUpperCase()}${name.slice(1)}`;
419
401
  }
420
- function createRegistryContext({
421
- registry
422
- }) {
423
- return {
424
- getPreset: (name, presetConfig) => {
425
- const key = getPresetKey(name), definer = registry[key];
426
- if (!definer)
427
- throw new Error(`Cannot resolve preset "${name}". No such preset in this registry.`);
428
- return definer(presetConfig);
429
- }
430
- };
402
+ function createRegistryContext({ registry }) {
403
+ return { getPreset: (name, presetConfig) => {
404
+ let definer = registry[getPresetKey(name)];
405
+ if (!definer) throw Error(`Cannot resolve preset "${name}". No such preset in this registry.`);
406
+ return definer(presetConfig);
407
+ } };
431
408
  }
432
- function createDefiner({
433
- registryId,
434
- preset,
435
- config,
436
- registry,
437
- registeredSchemas
438
- }) {
439
- return function(userConfig = {}) {
440
- const name = userConfig.name;
441
- if (typeof name != "string" || name.length === 0)
442
- throw new Error(`${getPresetKey(preset.name)}: "name" is required. Pass {name: "yourTypeName"}.`);
443
- recordPresetUsage(registryId, preset.identifier ?? "unnamed");
444
- const registryContext = createRegistryContext({
445
- registry
446
- }), registryDefaults = config[preset.name], mergedConfig = {
447
- ...typeof registryDefaults == "object" && registryDefaults !== null ? registryDefaults : {},
448
- ...userConfig
449
- }, {
450
- map,
451
- ...factoryConfig
452
- } = mergedConfig, schemaType = preset.schemaType(
453
- // 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
454
- factoryConfig,
455
- registryContext
456
- );
457
- return registeredSchemas.set(name, schemaType), applyMapHooks(addTelemetryComponent(schemaType, registryId), map);
458
- };
409
+ function createDefiner({ registryId, preset, config, registry, registeredSchemas }) {
410
+ return function(userConfig = {}) {
411
+ let name = userConfig.name;
412
+ if (typeof name != "string" || name.length === 0) throw Error(`${getPresetKey(preset.name)}: "name" is required. Pass {name: "yourTypeName"}.`);
413
+ recordPresetUsage(registryId, preset.identifier ?? "unnamed");
414
+ let registryContext = createRegistryContext({ registry }), registryDefaults = config[preset.name], { map, ...factoryConfig } = {
415
+ ...typeof registryDefaults == "object" && registryDefaults ? registryDefaults : {},
416
+ ...userConfig
417
+ }, schemaType = preset.schemaType(factoryConfig, registryContext);
418
+ return registeredSchemas.set(name, schemaType), applyMapHooks(addTelemetryComponent(schemaType, registryId), map);
419
+ };
459
420
  }
460
421
  function applyMapHooks(schemaType, map) {
461
- if (!map || typeof map != "object") return schemaType;
462
- const mappedSchemaType = {};
463
- for (const [configName, configValue] of Object.entries(map))
464
- typeof configValue == "function" && (mappedSchemaType[configName] = configValue(
465
- // oxlint-disable-next-line no-unsafe-type-assertion -- map hooks operate on arbitrary schema type properties
466
- schemaType[configName]
467
- ));
468
- return {
469
- ...schemaType,
470
- ...mappedSchemaType
471
- };
422
+ if (!map || typeof map != "object") return schemaType;
423
+ let mappedSchemaType = {};
424
+ for (let [configName, configValue] of Object.entries(map)) typeof configValue == "function" && (mappedSchemaType[configName] = configValue(schemaType[configName]));
425
+ return {
426
+ ...schemaType,
427
+ ...mappedSchemaType
428
+ };
472
429
  }
473
430
  function addTelemetryComponent(schemaType, registryId) {
474
- const existing = "components" in schemaType ? schemaType.components : void 0, existingInput = existing && "input" in existing && typeof existing.input == "function" ? (
475
- // oxlint-disable-next-line no-unsafe-type-assertion -- presets only produce object/document schema types, whose input components are assignable to ComponentType<InputProps>
476
- existing.input
477
- ) : void 0;
478
- return {
479
- ...schemaType,
480
- components: {
481
- ...existing,
482
- input: (props) => /* @__PURE__ */ jsx(PresetsTelemetryCollector, { ...props, registryId, userInput: existingInput })
483
- }
484
- };
431
+ let existing = "components" in schemaType ? schemaType.components : void 0, existingInput = existing && "input" in existing && typeof existing.input == "function" ? existing.input : void 0;
432
+ return {
433
+ ...schemaType,
434
+ components: {
435
+ ...existing,
436
+ input: (props) => /* @__PURE__ */ jsx(PresetsTelemetryCollector, {
437
+ ...props,
438
+ registryId,
439
+ userInput: existingInput
440
+ })
441
+ }
442
+ };
485
443
  }
486
- export {
487
- createPresetsRegistry
488
- };
489
- //# sourceMappingURL=index.js.map
444
+ export { createPresetsRegistry };
445
+
446
+ //# sourceMappingURL=index.js.map