@cosmic-labs/sanity-schema 0.1.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.
@@ -0,0 +1,20 @@
1
+ import { SchemaTypeDefinition } from '@sanity/types';
2
+ import { BlockRegistryEntry } from '@cosmic-labs/content-contract';
3
+
4
+ declare const sourceLink: SchemaTypeDefinition;
5
+ declare const statCallout: SchemaTypeDefinition;
6
+ declare const comparisonTable: SchemaTypeDefinition;
7
+ declare const editorialQuote: SchemaTypeDefinition;
8
+ declare const definitionBox: SchemaTypeDefinition;
9
+ declare const checklistBox: SchemaTypeDefinition;
10
+ declare const captionedImage: SchemaTypeDefinition;
11
+ declare const botanicalDivider: SchemaTypeDefinition;
12
+ declare const videoEmbed: SchemaTypeDefinition;
13
+ /** A site-neutral sourced assertion. Sites may extend it with their own subject reference. */
14
+ declare const fact: SchemaTypeDefinition;
15
+ /** The schemas sites opt into when they need these shared editorial blocks. */
16
+ declare const editorialBlocks: SchemaTypeDefinition[];
17
+ /** Keeps the schema package's block names tied to the shared contract vocabulary. */
18
+ declare const editorialBlockTypes: readonly BlockRegistryEntry['type'][];
19
+
20
+ export { botanicalDivider, captionedImage, checklistBox, comparisonTable, definitionBox, editorialBlockTypes, editorialBlocks, editorialQuote, fact, sourceLink, statCallout, videoEmbed };
package/dist/index.js ADDED
@@ -0,0 +1,223 @@
1
+ // src/index.ts
2
+ import { defineArrayMember, defineField, defineType } from "sanity";
3
+ var sourceLink = defineType({
4
+ name: "sourceLink",
5
+ title: "Source link",
6
+ type: "object",
7
+ fields: [
8
+ defineField({ name: "label", title: "Label", type: "string", validation: (rule) => rule.required() }),
9
+ defineField({ name: "url", title: "URL", type: "url", validation: (rule) => rule.required() })
10
+ ]
11
+ });
12
+ var statCallout = defineType({
13
+ name: "statCallout",
14
+ title: "Stat callout",
15
+ type: "object",
16
+ fields: [
17
+ defineField({ name: "title", title: "Title", type: "string" }),
18
+ defineField({
19
+ name: "stats",
20
+ title: "Stats",
21
+ type: "array",
22
+ of: [
23
+ defineArrayMember({
24
+ name: "stat",
25
+ type: "object",
26
+ fields: [
27
+ defineField({ name: "value", title: "Value", type: "string", validation: (rule) => rule.required() }),
28
+ defineField({ name: "label", title: "Label", type: "string", validation: (rule) => rule.required() }),
29
+ defineField({ name: "detail", title: "Detail", type: "string" })
30
+ ]
31
+ })
32
+ ],
33
+ validation: (rule) => rule.required().min(1).max(4)
34
+ }),
35
+ defineField({ name: "source", title: "Source", type: "sourceLink" })
36
+ ],
37
+ preview: {
38
+ prepare: () => ({ title: "Stat callout" })
39
+ }
40
+ });
41
+ var comparisonTable = defineType({
42
+ name: "comparisonTable",
43
+ title: "Comparison table",
44
+ type: "object",
45
+ fields: [
46
+ defineField({ name: "caption", title: "Caption", type: "string" }),
47
+ defineField({ name: "rowHeader", title: "Row header", type: "string", initialValue: "Item" }),
48
+ defineField({
49
+ name: "columns",
50
+ title: "Columns",
51
+ type: "array",
52
+ of: [defineArrayMember({ type: "string" })],
53
+ validation: (rule) => rule.required().min(2)
54
+ }),
55
+ defineField({
56
+ name: "rows",
57
+ title: "Rows",
58
+ type: "array",
59
+ of: [
60
+ defineArrayMember({
61
+ name: "comparisonRow",
62
+ type: "object",
63
+ fields: [
64
+ defineField({ name: "label", title: "Label", type: "string", validation: (rule) => rule.required() }),
65
+ defineField({
66
+ name: "values",
67
+ title: "Values",
68
+ type: "array",
69
+ of: [defineArrayMember({ type: "string" })],
70
+ validation: (rule) => rule.required().min(1)
71
+ })
72
+ ]
73
+ })
74
+ ],
75
+ validation: (rule) => rule.required().min(1)
76
+ })
77
+ ]
78
+ });
79
+ var editorialQuote = defineType({
80
+ name: "editorialQuote",
81
+ title: "Editorial quote",
82
+ type: "object",
83
+ fields: [
84
+ defineField({ name: "quote", title: "Quote", type: "text", validation: (rule) => rule.required() }),
85
+ defineField({ name: "attribution", title: "Attribution", type: "string" })
86
+ ]
87
+ });
88
+ var definitionBox = defineType({
89
+ name: "definitionBox",
90
+ title: "Definition box",
91
+ type: "object",
92
+ fields: [
93
+ defineField({ name: "term", title: "Term", type: "string", validation: (rule) => rule.required() }),
94
+ defineField({ name: "definition", title: "Definition", type: "text", validation: (rule) => rule.required() }),
95
+ defineField({
96
+ name: "icon",
97
+ title: "Icon",
98
+ type: "string",
99
+ options: {
100
+ list: ["olive", "lemon", "herb", "vase", "teacup"]
101
+ },
102
+ initialValue: "olive"
103
+ })
104
+ ]
105
+ });
106
+ var checklistBox = defineType({
107
+ name: "checklistBox",
108
+ title: "Checklist box",
109
+ type: "object",
110
+ fields: [
111
+ defineField({ name: "title", title: "Title", type: "string" }),
112
+ defineField({
113
+ name: "items",
114
+ title: "Items",
115
+ type: "array",
116
+ of: [defineArrayMember({ type: "string" })],
117
+ validation: (rule) => rule.required().min(1)
118
+ })
119
+ ]
120
+ });
121
+ var captionedImage = defineType({
122
+ name: "captionedImage",
123
+ title: "Captioned image",
124
+ type: "object",
125
+ fields: [
126
+ defineField({
127
+ name: "image",
128
+ title: "Image",
129
+ type: "image",
130
+ options: { hotspot: true },
131
+ fields: [
132
+ defineField({ name: "alt", title: "Alternative text", type: "string", validation: (rule) => rule.required() })
133
+ ],
134
+ validation: (rule) => rule.required()
135
+ }),
136
+ defineField({ name: "caption", title: "Caption", type: "string" }),
137
+ defineField({ name: "credit", title: "Credit", type: "string" })
138
+ ]
139
+ });
140
+ var botanicalDivider = defineType({
141
+ name: "botanicalDivider",
142
+ title: "Botanical divider",
143
+ type: "object",
144
+ fields: [
145
+ defineField({ name: "note", title: "Note", type: "string", readOnly: true })
146
+ ],
147
+ preview: {
148
+ prepare: () => ({ title: "Botanical divider" })
149
+ }
150
+ });
151
+ var youtubeUrlPattern = /^(?:https?:\/\/)?(?:www\.)?(?:youtube\.com\/(?:watch\?(?:[^#]*&)?v=|embed\/|shorts\/)|youtu\.be\/)[A-Za-z0-9_-]{11}(?:[?&#/].*)?$/i;
152
+ var videoEmbed = defineType({
153
+ name: "videoEmbed",
154
+ title: "Video embed",
155
+ type: "object",
156
+ fields: [
157
+ defineField({
158
+ name: "url",
159
+ title: "YouTube URL",
160
+ type: "url",
161
+ validation: (rule) => rule.required().custom((url) => typeof url === "string" && youtubeUrlPattern.test(url) ? true : "Enter a YouTube video URL.")
162
+ }),
163
+ defineField({ name: "caption", title: "Caption", type: "string" })
164
+ ]
165
+ });
166
+ var fact = defineType({
167
+ name: "fact",
168
+ title: "Fact",
169
+ type: "document",
170
+ fields: [
171
+ defineField({ name: "subject", title: "Subject", type: "string", validation: (rule) => rule.required() }),
172
+ defineField({ name: "claim", title: "Claim", type: "string", validation: (rule) => rule.required() }),
173
+ defineField({ name: "value", title: "Value", type: "text", validation: (rule) => rule.required() }),
174
+ defineField({ name: "source", title: "Source", type: "sourceLink", validation: (rule) => rule.required() }),
175
+ defineField({ name: "sourceDate", title: "Source date", type: "date" }),
176
+ defineField({ name: "geography", title: "Geography", type: "string" }),
177
+ defineField({
178
+ name: "confidence",
179
+ title: "Confidence",
180
+ type: "string",
181
+ options: { list: ["high", "medium", "low"] },
182
+ initialValue: "high",
183
+ validation: (rule) => rule.required()
184
+ }),
185
+ defineField({ name: "reviewedBy", title: "Reviewed by", type: "string" }),
186
+ defineField({ name: "lastReviewed", title: "Last reviewed", type: "date" })
187
+ ]
188
+ });
189
+ var editorialBlocks = [
190
+ sourceLink,
191
+ statCallout,
192
+ comparisonTable,
193
+ editorialQuote,
194
+ definitionBox,
195
+ checklistBox,
196
+ captionedImage,
197
+ botanicalDivider,
198
+ videoEmbed
199
+ ];
200
+ var editorialBlockTypes = [
201
+ "statCallout",
202
+ "comparisonTable",
203
+ "editorialQuote",
204
+ "definitionBox",
205
+ "checklistBox",
206
+ "captionedImage",
207
+ "botanicalDivider",
208
+ "videoEmbed"
209
+ ];
210
+ export {
211
+ botanicalDivider,
212
+ captionedImage,
213
+ checklistBox,
214
+ comparisonTable,
215
+ definitionBox,
216
+ editorialBlockTypes,
217
+ editorialBlocks,
218
+ editorialQuote,
219
+ fact,
220
+ sourceLink,
221
+ statCallout,
222
+ videoEmbed
223
+ };
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@cosmic-labs/sanity-schema",
3
+ "version": "0.1.0",
4
+ "description": "Composable Sanity editorial block schemas for Cosmic Atlas sites.",
5
+ "license": "UNLICENSED",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "publishConfig": {
19
+ "access": "restricted"
20
+ },
21
+ "dependencies": {
22
+ "@cosmic-labs/content-contract": "0.1.0"
23
+ },
24
+ "peerDependencies": {
25
+ "@sanity/types": "^3.0.0 || ^4.0.0",
26
+ "sanity": "^3.0.0 || ^4.0.0"
27
+ },
28
+ "devDependencies": {
29
+ "tsup": "^8.3.5",
30
+ "typescript": "^5.7.2",
31
+ "vitest": "^3.0.0"
32
+ },
33
+ "engines": {
34
+ "node": ">=22.14"
35
+ },
36
+ "scripts": {
37
+ "build": "tsup src/index.ts --format esm --dts --clean --target es2022 --external sanity --external @sanity/types",
38
+ "test": "vitest run --root ../.. --project sanity-schema --passWithNoTests",
39
+ "lint": "tsc --noEmit"
40
+ }
41
+ }