@sanity/presets 0.1.0 → 0.2.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/dist/index.d.ts CHANGED
@@ -1,12 +1,30 @@
1
1
  import { PluginOptions, SchemaTypeDefinition } from "sanity";
2
+ import * as _____0 from "../..";
3
+ /**
4
+ * @internal
5
+ */
6
+ declare const presetProvider: unique symbol;
7
+ declare const visitedFactories: unique symbol;
8
+ type PresetProvider = 'user' | 'system';
9
+ interface BaseContext {
10
+ [presetProvider]?: PresetProvider;
11
+ [visitedFactories]?: WeakSet<WeakKey>;
12
+ }
2
13
  interface PresetResult {
3
- types: SchemaTypeDefinition[];
14
+ type: SchemaTypeDefinition;
15
+ [presetProvider]: PresetProvider;
4
16
  }
5
- declare function presets(...types: PresetResult[]): PluginOptions;
17
+ declare function presets(...types: PresetResult[][]): PluginOptions;
6
18
  declare const LINK_TYPE_NAME = "core.presets.link";
7
19
  interface LinkTypeConfig {
8
- internalTypes: string[];
20
+ internalTypes?: string[];
21
+ }
22
+ declare const linkType: (context?: (BaseContext & LinkTypeConfig) | undefined) => _____0.PresetResult[];
23
+ declare const ctaType: (context?: (BaseContext & void) | undefined) => _____0.PresetResult[];
24
+ interface PageTypeConfig {
25
+ pageBuilderBlocks: string[];
9
26
  }
10
- declare function linkType(config: LinkTypeConfig): PresetResult;
11
- export { LINK_TYPE_NAME, type LinkTypeConfig, type PresetResult, linkType, presets };
27
+ declare const pageType: (context?: (BaseContext & PageTypeConfig) | undefined) => _____0.PresetResult[];
28
+ declare const seoType: (context?: (BaseContext & void) | undefined) => _____0.PresetResult[];
29
+ export { LINK_TYPE_NAME, type LinkTypeConfig, type PresetResult, ctaType, linkType, pageType, presets, seoType };
12
30
  //# 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/definePresetType.ts","../src/types.ts","../src/composer.ts","../src/presets/link-type/constants.ts","../src/presets/link-type/index.ts","../src/presets/cta-type/index.ts","../src/presets/page-type/index.ts","../src/presets/seo-type/index.ts"],"mappings":";;;AAOA;;cAAa,cAAA;AAAA,cAEP,gBAAA;AAAA,KAEM,cAAA;AAAA,UAIK,WAAA;EAAA,CACd,cAAA,IAAkB,cAAA;EAAA,CAClB,gBAAA,IAAoB,OAAA,CAAQ,OAAA;AAAA;AAAA,UCbd,YAAA;EACf,IAAA,EAAM,oBAAA;EAAA,CACL,cAAA,GAAiB,cAAA;AAAA;AAAA,iBCoCJ,OAAA,CAAA,GAAW,KAAA,EAAO,YAAA,OAAmB,aAAA;AAAA,cC1CxC,cAAA;AAAA,UCOI,cAAA;EACf,aAAA;AAAA;AAAA,cAGW,QAAA,GAAQ,OAAA,IAiEnB,WAAA,GAjEmB,cAAA,kBAAA,MAAA,CAAA,YAAA;AAAA,cCNR,OAAA,GAAO,OAAA,IAyBlB,WAAA,yBAzBkB,MAAA,CAAA,YAAA;AAAA,UCAH,cAAA;EACf,iBAAA;AAAA;AAAA,cAGW,QAAA,GAAQ,OAAA,IA6DnB,WAAA,GA7DmB,cAAA,kBAAA,MAAA,CAAA,YAAA;AAAA,cCJR,OAAA,GAAO,OAAA,IAoDlB,WAAA,yBApDkB,MAAA,CAAA,YAAA"}
package/dist/index.js CHANGED
@@ -1,7 +1,33 @@
1
- import { defineType, defineField } from "sanity";
1
+ import { defineType, defineField, ALL_FIELDS_GROUP, defineArrayMember } from "sanity";
2
+ import { getImageDimensions } from "@sanity/asset-utils";
3
+ const presetProvider = /* @__PURE__ */ Symbol("presetProvider"), visitedFactories = /* @__PURE__ */ Symbol("visitedFactories");
4
+ function definePresetType(factory) {
5
+ return function(context) {
6
+ const {
7
+ schemaType,
8
+ composes = []
9
+ } = factory(context), visited = context?.[visitedFactories] ?? /* @__PURE__ */ new WeakSet();
10
+ if (visited.has(factory))
11
+ throw new Error(`Found circular dependency resolving preset \`${schemaType.name}\`.`);
12
+ return visited.add(factory), composes.flatMap((composedFactory) => composedFactory({
13
+ [presetProvider]: "system",
14
+ [visitedFactories]: visited
15
+ })).concat({
16
+ type: schemaType,
17
+ [presetProvider]: context?.[presetProvider] ?? "user"
18
+ });
19
+ };
20
+ }
2
21
  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)));
22
+ const userSeen = /* @__PURE__ */ new Set(), systemSeen = /* @__PURE__ */ new Set();
23
+ return presets2.flat().toSorted(sortUserPrecedence).filter((preset) => {
24
+ const {
25
+ type
26
+ } = preset, provider = preset[presetProvider];
27
+ return userSeen.has(type.name) ? (provider === "user" && console.warn(`[@sanity/presets] Dropped duplicate type "${type.name}". Keeping first definition.`), !1) : systemSeen.has(type.name) ? !1 : (provider === "user" && userSeen.add(type.name), provider === "system" && systemSeen.add(type.name), !0);
28
+ }).map(({
29
+ type
30
+ }) => type);
5
31
  }
6
32
  function presets(...types) {
7
33
  return {
@@ -11,86 +37,194 @@ function presets(...types) {
11
37
  }
12
38
  };
13
39
  }
14
- const LINK_TYPE_NAME = "core.presets.link";
15
- function createLinkType(internalTypes) {
16
- const referenceTargets = internalTypes.map((typeName) => ({
40
+ function sortUserPrecedence(a, b) {
41
+ return a[presetProvider] === "user" && b[presetProvider] === "system" ? -1 : a[presetProvider] === "system" && b[presetProvider] === "user" ? 1 : 0;
42
+ }
43
+ const LINK_TYPE_NAME = "core.presets.link", linkType = definePresetType((context) => {
44
+ const referenceTargets = (context?.internalTypes ?? [] ?? []).map((typeName) => ({
17
45
  type: typeName
18
46
  }));
19
- return defineType({
20
- name: LINK_TYPE_NAME,
47
+ return {
48
+ schemaType: defineType({
49
+ name: LINK_TYPE_NAME,
50
+ type: "object",
51
+ title: "Link",
52
+ fields: [defineField({
53
+ name: "linkType",
54
+ type: "string",
55
+ title: "Link Type",
56
+ initialValue: "internal",
57
+ options: {
58
+ layout: "radio",
59
+ list: [{
60
+ title: "Internal",
61
+ value: "internal"
62
+ }, {
63
+ title: "External",
64
+ value: "external"
65
+ }]
66
+ }
67
+ }), defineField({
68
+ name: "reference",
69
+ type: "reference",
70
+ title: "Internal Link",
71
+ to: referenceTargets,
72
+ hidden: ({
73
+ parent
74
+ }) => parent?.linkType === "external"
75
+ }), defineField({
76
+ name: "url",
77
+ type: "url",
78
+ title: "URL",
79
+ hidden: ({
80
+ parent
81
+ }) => parent?.linkType === "internal",
82
+ validation: (rule) => rule.uri({
83
+ scheme: ["http", "https", "mailto", "tel"]
84
+ })
85
+ }), defineField({
86
+ name: "openInNewTab",
87
+ type: "boolean",
88
+ title: "Open in New Tab",
89
+ initialValue: !1,
90
+ hidden: ({
91
+ parent
92
+ }) => parent?.linkType === "internal"
93
+ })],
94
+ preview: {
95
+ select: {
96
+ linkType: "linkType",
97
+ url: "url",
98
+ referenceTitle: "reference.title"
99
+ },
100
+ prepare({
101
+ linkType: linkType2,
102
+ url,
103
+ referenceTitle
104
+ }) {
105
+ return {
106
+ title: linkType2 === "external" ? url || "No URL" : referenceTitle || "No reference",
107
+ subtitle: linkType2 === "external" ? "External link" : "Internal link"
108
+ };
109
+ }
110
+ }
111
+ })
112
+ };
113
+ }), ctaType = definePresetType(() => ({
114
+ composes: [linkType],
115
+ schemaType: defineType({
116
+ name: "core.presets.cta",
21
117
  type: "object",
22
- title: "Link",
118
+ title: "Call to action",
23
119
  fields: [defineField({
24
- name: "linkType",
25
- type: "string",
26
- title: "Link Type",
27
- initialValue: "internal",
120
+ name: "link",
121
+ title: "Link",
122
+ type: LINK_TYPE_NAME
123
+ }), defineField({
124
+ name: "level",
125
+ title: "Level",
126
+ type: "number",
28
127
  options: {
29
128
  layout: "radio",
30
- list: [{
31
- title: "Internal",
32
- value: "internal"
33
- }, {
34
- title: "External",
35
- value: "external"
36
- }]
129
+ list: [1, 2, 3]
37
130
  }
131
+ })]
132
+ })
133
+ })), seoType = definePresetType(() => ({
134
+ schemaType: defineType({
135
+ name: "core.presets.seo",
136
+ type: "object",
137
+ title: "Web page metadata (SEO)",
138
+ fields: [defineField({
139
+ name: "title",
140
+ title: "Title",
141
+ type: "string",
142
+ validation: (rule) => rule.max(70).info("Search engines may truncate this title.")
38
143
  }), 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
- })
144
+ name: "description",
145
+ title: "Description",
146
+ type: "text",
147
+ validation: (rule) => rule.max(150).info("Search engines may truncate this description.")
56
148
  }), 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"
149
+ name: "ogImage",
150
+ title: "Open Graph image",
151
+ type: "image",
152
+ description: "Landscape 1200x630 (1.91:1)",
153
+ options: {
154
+ hotspot: {
155
+ previews: [{
156
+ title: "Landscape (1.91:1)",
157
+ aspectRatio: 1.91 / 1
158
+ }]
159
+ }
70
160
  },
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
- };
80
- }
81
- }
82
- });
83
- }
84
- function linkType(config) {
85
- if (config.internalTypes.length === 0)
86
- throw new Error("[@sanity/presets] linkType requires at least one internalTypes entry.");
161
+ validation: (Rule) => Rule.custom((value) => {
162
+ if (!value?.asset?._ref)
163
+ return !0;
164
+ const {
165
+ height,
166
+ width
167
+ } = getImageDimensions(value.asset?._ref);
168
+ return height !== 630 || width !== 1200 ? "Open Graph image must be 1200x630" : !0;
169
+ })
170
+ })]
171
+ })
172
+ })), pageType = definePresetType((context) => {
173
+ const pageBuilderBlocks = context?.pageBuilderBlocks ?? [];
87
174
  return {
88
- types: [createLinkType(config.internalTypes)]
175
+ composes: [seoType],
176
+ schemaType: defineType({
177
+ name: "core.presets.page",
178
+ type: "document",
179
+ title: "Page",
180
+ groups: [{
181
+ ...ALL_FIELDS_GROUP,
182
+ hidden: !0
183
+ }, {
184
+ name: "main",
185
+ title: "Main",
186
+ default: !0
187
+ }, {
188
+ name: "metadata",
189
+ title: "Metadata"
190
+ }],
191
+ fields: [defineField({
192
+ name: "name",
193
+ title: "Name",
194
+ type: "string",
195
+ group: "main",
196
+ validation: (rule) => rule.required()
197
+ }), defineField({
198
+ name: "slug",
199
+ title: "Slug",
200
+ type: "slug",
201
+ group: "main",
202
+ options: {
203
+ source: "name"
204
+ }
205
+ }), defineField({
206
+ name: "content",
207
+ title: "Content",
208
+ group: "main",
209
+ type: "array",
210
+ of: pageBuilderBlocks.map((typeName) => defineArrayMember({
211
+ type: typeName
212
+ }))
213
+ }), defineField({
214
+ name: "seo",
215
+ title: "SEO",
216
+ type: "core.presets.seo",
217
+ group: "metadata"
218
+ })]
219
+ })
89
220
  };
90
- }
221
+ });
91
222
  export {
92
223
  LINK_TYPE_NAME,
224
+ ctaType,
93
225
  linkType,
94
- presets
226
+ pageType,
227
+ presets,
228
+ seoType
95
229
  };
96
230
  //# 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/definePresetType.ts","../src/composer.ts","../src/presets/link-type/constants.ts","../src/presets/link-type/index.ts","../src/presets/cta-type/index.ts","../src/presets/seo-type/index.ts","../src/presets/page-type/index.ts"],"sourcesContent":["import type {SchemaTypeDefinition} from 'sanity'\n\nimport type {PresetResult} from './types'\n\n/**\n * @internal\n */\nexport const presetProvider: unique symbol = Symbol('presetProvider')\n\nconst visitedFactories: unique symbol = Symbol('visitedFactories')\n\nexport type PresetProvider = 'user' | 'system'\n\nexport type PresetResultFactory = (...args: any[]) => PresetResult[]\n\nexport interface BaseContext {\n [presetProvider]?: PresetProvider\n [visitedFactories]?: WeakSet<WeakKey>\n}\n\nexport interface PresetTypeContext {\n [presetProvider]?: PresetProvider\n schemaType: SchemaTypeDefinition\n composes?: PresetResultFactory[]\n}\n\nexport function definePresetType<Context = void>(\n factory: (context?: Context) => PresetTypeContext,\n): (context?: BaseContext & Context) => PresetResult[] {\n return function define(context) {\n const {schemaType, composes = []} = factory(context)\n const visited = context?.[visitedFactories] ?? new WeakSet()\n\n if (visited.has(factory)) {\n throw new Error(`Found circular dependency resolving preset \\`${schemaType.name}\\`.`)\n }\n\n visited.add(factory)\n\n const dependencies = composes.flatMap<PresetResult>((composedFactory) =>\n composedFactory({\n [presetProvider]: 'system',\n [visitedFactories]: visited,\n }),\n )\n\n return dependencies.concat({\n type: schemaType,\n [presetProvider]: context?.[presetProvider] ?? 'user',\n })\n }\n}\n","import {type PluginOptions, type SchemaTypeDefinition} from 'sanity'\n\nimport {presetProvider} from './definePresetType'\nimport type {PresetResult} from './types'\n\nexport function collectTypes(presets: PresetResult[][]): SchemaTypeDefinition[] {\n const userSeen = new Set<string>()\n const systemSeen = new Set<string>()\n\n return presets\n .flat()\n .toSorted(sortUserPrecedence)\n .filter((preset) => {\n const {type} = preset\n const provider = preset[presetProvider]\n\n if (userSeen.has(type.name)) {\n if (provider === 'user') {\n console.warn(\n `[@sanity/presets] Dropped duplicate type \"${type.name}\". Keeping first definition.`,\n )\n }\n return false\n }\n\n if (systemSeen.has(type.name)) {\n return false\n }\n\n if (provider === 'user') {\n userSeen.add(type.name)\n }\n\n if (provider === 'system') {\n systemSeen.add(type.name)\n }\n\n return true\n })\n .map(({type}) => type)\n}\n\nexport function presets(...types: PresetResult[][]): PluginOptions {\n return {\n name: '@sanity/presets',\n schema: {types: collectTypes(types)},\n }\n}\n\nfunction sortUserPrecedence(a: PresetResult, b: PresetResult): number {\n if (a[presetProvider] === 'user' && b[presetProvider] === 'system') {\n return -1\n }\n\n if (a[presetProvider] === 'system' && b[presetProvider] === 'user') {\n return 1\n }\n\n return 0\n}\n","export const LINK_TYPE_NAME = 'core.presets.link'\n","import {defineField, defineType} from 'sanity'\n\nimport {definePresetType} from '../../definePresetType'\nimport {LINK_TYPE_NAME} from './constants'\n\nexport {LINK_TYPE_NAME} from './constants'\n\nexport interface LinkTypeConfig {\n internalTypes?: string[]\n}\n\nexport const linkType = definePresetType<LinkTypeConfig>((context) => {\n const internalTypes = context?.internalTypes ?? []\n const referenceTargets = (internalTypes ?? []).map((typeName) => ({type: typeName}))\n\n return {\n schemaType: 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})\n","import {defineField, defineType} from 'sanity'\n\nimport {definePresetType} from '../../definePresetType'\nimport {LINK_TYPE_NAME, linkType} from '../link-type'\n\nexport const ctaType = definePresetType(() => {\n return {\n composes: [linkType],\n schemaType: defineType({\n name: 'core.presets.cta',\n type: 'object',\n title: 'Call to action',\n fields: [\n defineField({\n name: 'link',\n title: 'Link',\n type: LINK_TYPE_NAME,\n }),\n defineField({\n name: 'level',\n title: 'Level',\n type: 'number',\n options: {\n layout: 'radio',\n list: [1, 2, 3],\n },\n }),\n ],\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(() => {\n return {\n schemaType: defineType({\n name: 'core.presets.seo',\n type: 'object',\n title: 'Web page metadata (SEO)',\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 ],\n }),\n }\n})\n","import {ALL_FIELDS_GROUP, defineArrayMember, defineField, defineType} from 'sanity'\n\nimport {definePresetType} from '../../definePresetType'\nimport {seoType} from '../seo-type'\n\nexport interface PageTypeConfig {\n pageBuilderBlocks: string[]\n}\n\nexport const pageType = definePresetType<PageTypeConfig>((context) => {\n const pageBuilderBlocks = context?.pageBuilderBlocks ?? []\n\n return {\n composes: [seoType],\n schemaType: defineType({\n name: 'core.presets.page',\n type: 'document',\n title: 'Page',\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 ],\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 defineField({\n name: 'seo',\n title: 'SEO',\n type: 'core.presets.seo',\n group: 'metadata',\n }),\n ],\n }),\n }\n})\n"],"names":["presetProvider","visitedFactories","definePresetType","factory","context","schemaType","composes","visited","WeakSet","has","Error","name","add","flatMap","composedFactory","concat","type","collectTypes","presets","userSeen","Set","systemSeen","flat","toSorted","sortUserPrecedence","filter","preset","provider","console","warn","map","types","schema","a","b","LINK_TYPE_NAME","linkType","referenceTargets","internalTypes","typeName","defineType","title","fields","defineField","initialValue","options","layout","list","value","to","hidden","parent","validation","rule","uri","scheme","preview","select","url","referenceTitle","prepare","subtitle","ctaType","seoType","max","info","description","hotspot","previews","aspectRatio","Rule","custom","asset","_ref","height","width","getImageDimensions","pageType","pageBuilderBlocks","groups","ALL_FIELDS_GROUP","default","group","required","source","of","defineArrayMember"],"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.2.0",
4
4
  "description": "Production ready preset patterns for Sanity Studio",
5
5
  "keywords": [
6
6
  "sanity",
@@ -26,6 +26,9 @@
26
26
  ".": "./dist/index.js",
27
27
  "./package.json": "./package.json"
28
28
  },
29
+ "dependencies": {
30
+ "@sanity/asset-utils": "^2.3.0"
31
+ },
29
32
  "devDependencies": {
30
33
  "@sanity/pkg-utils": "^10.4.11",
31
34
  "sanity": "^5.17.1",