@fils/sanity-components 0.0.8 → 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,205 @@
1
+ import { LinkIcon, PlayIcon, VideoIcon } from "@sanity/icons";
2
+ import { defineField, defineType } from "sanity";
3
+ import { createVideoInput } from "./CreateVideoInput";
4
+
5
+ /**
6
+ * Video File Schema
7
+ * Document type for uploaded video files with thumbnail generation
8
+ */
9
+ export const VideoFile = defineType({
10
+ name: 'videoFile',
11
+ type: 'document',
12
+ title: 'Video File',
13
+ description: 'Video File + Thumbnail',
14
+ icon: VideoIcon,
15
+ fields: [
16
+ defineField({
17
+ name: 'video',
18
+ type: 'file',
19
+ options: {
20
+ accept: "video/mp4, video/webm"
21
+ },
22
+ icon: PlayIcon,
23
+ description: 'Video File. Supported formats: MP4 & WebM',
24
+ validation: Rule => Rule.required()
25
+ }),
26
+ defineField({
27
+ name: 'image',
28
+ title: 'Video Thumbnail',
29
+ type: 'image',
30
+ validation: Rule => Rule.required()
31
+ })
32
+ ],
33
+ components: {
34
+ input: createVideoInput({
35
+ inputType: 'file',
36
+ enableThumbnailGeneration: true
37
+ })
38
+ },
39
+ preview: {
40
+ select: {
41
+ video: 'video',
42
+ media: 'image'
43
+ },
44
+ prepare(selected) {
45
+ const { video, media } = selected;
46
+
47
+ // Just use the original filename from the asset if available
48
+ const filename = video?.asset?._ref
49
+ ? video.asset._ref.split('-').slice(1, -1).join('-')
50
+ : 'No video';
51
+
52
+ return {
53
+ title: filename,
54
+ media
55
+ }
56
+ }
57
+ }
58
+ });
59
+
60
+ /**
61
+ * Video URL Schema
62
+ * Document type for external video URLs (e.g., Vimeo, YouTube)
63
+ */
64
+ export const VideoURL = defineType({
65
+ name: 'videoUrl',
66
+ type: 'document',
67
+ title: 'Video URL',
68
+ description: 'External video URL + Thumbnail',
69
+ icon: VideoIcon,
70
+ fields: [
71
+ defineField({
72
+ name: 'video',
73
+ type: 'url',
74
+ icon: LinkIcon,
75
+ description: 'Video URL (e.g., Vimeo, YouTube)',
76
+ validation: Rule => Rule.required().uri({
77
+ scheme: ['http', 'https']
78
+ })
79
+ }),
80
+ defineField({
81
+ name: 'image',
82
+ title: 'Video Thumbnail',
83
+ type: 'image',
84
+ validation: Rule => Rule.required()
85
+ })
86
+ ],
87
+ components: {
88
+ input: createVideoInput({
89
+ inputType: 'url',
90
+ enableThumbnailGeneration: false // Can't generate from external URLs
91
+ })
92
+ },
93
+ preview: {
94
+ select: {
95
+ video: 'video',
96
+ media: 'image'
97
+ },
98
+ prepare(selected) {
99
+ const { video, media } = selected;
100
+ return {
101
+ title: video || 'No URL',
102
+ media
103
+ }
104
+ }
105
+ }
106
+ });
107
+
108
+ /**
109
+ * Video File Object Schema
110
+ * Object type for use as a field in other schemas
111
+ */
112
+ export const VideoFileObject = defineType({
113
+ name: 'videoFileObject',
114
+ type: 'object',
115
+ title: 'Video with Thumbnail',
116
+ fields: [
117
+ defineField({
118
+ name: 'video',
119
+ type: 'file',
120
+ options: {
121
+ accept: "video/mp4, video/webm"
122
+ }
123
+ }),
124
+ defineField({
125
+ name: 'image',
126
+ title: 'Thumbnail',
127
+ type: 'image'
128
+ })
129
+ ],
130
+ components: {
131
+ input: createVideoInput({
132
+ inputType: 'file',
133
+ enableThumbnailGeneration: true
134
+ })
135
+ }
136
+ });
137
+
138
+ /**
139
+ * Video URL Object Schema
140
+ * Object type for use as a field in other schemas (URL version)
141
+ */
142
+ export const VideoURLObject = defineType({
143
+ name: 'videoUrlObject',
144
+ type: 'object',
145
+ title: 'Video URL with Thumbnail',
146
+ fields: [
147
+ defineField({
148
+ name: 'video',
149
+ type: 'url'
150
+ }),
151
+ defineField({
152
+ name: 'image',
153
+ title: 'Thumbnail',
154
+ type: 'image'
155
+ })
156
+ ],
157
+ components: {
158
+ input: createVideoInput({
159
+ inputType: 'url',
160
+ enableThumbnailGeneration: false
161
+ })
162
+ }
163
+ });
164
+
165
+ export const VideoFileNoThumb = defineType({
166
+ name: 'videoFileNoThumb',
167
+ type: 'object',
168
+ title: 'Video File',
169
+ fields: [
170
+ defineField({
171
+ name: 'video',
172
+ type: 'file',
173
+ options: {
174
+ accept: 'video/mp4, video/webm'
175
+ }
176
+ })
177
+ ],
178
+ components: {
179
+ input: createVideoInput({
180
+ inputType: 'file',
181
+ enableThumbnailGeneration: false
182
+ })
183
+ }
184
+ });
185
+
186
+ export const VideoURLNoThumb = defineType({
187
+ name: 'videoFileNoThumb',
188
+ type: 'object',
189
+ title: 'Video URL',
190
+ fields: [
191
+ defineField({
192
+ name: 'video',
193
+ type: 'file',
194
+ options: {
195
+ accept: 'video/mp4, video/webm'
196
+ }
197
+ })
198
+ ],
199
+ components: {
200
+ input: createVideoInput({
201
+ inputType: 'url',
202
+ enableThumbnailGeneration: false
203
+ })
204
+ }
205
+ });
@@ -0,0 +1,86 @@
1
+ import { defineConfig, DocumentActionComponent, DocumentActionsContext } from "sanity"
2
+ import {StructureResolver, structureTool} from 'sanity/structure'
3
+ import { netlifyWidget, SiteWidgetOption } from "sanity-plugin-dashboard-widget-netlify";
4
+ import { dashboardTool } from '@sanity/dashboard';
5
+
6
+ // Define the actions that should be available for singleton documents
7
+ const singletonActions = new Set(["publish", "discardChanges", "restore"])
8
+
9
+ export function getActions(singletonTypes:Set<string>) {
10
+ return (input: DocumentActionComponent[], context: DocumentActionsContext) =>
11
+ singletonTypes.has(context.schemaType)
12
+ ? input.filter(({ action }) => action && singletonActions.has(action))
13
+ : input;
14
+ }
15
+
16
+ export function getDefaultConfig(projectId:string, title:string, structure:StructureResolver, schemaTypes:any, singletonTypes:Set<string>) {
17
+ return defineConfig({
18
+ name: 'default',
19
+ title,
20
+
21
+ projectId,
22
+ dataset: 'production',
23
+
24
+ scheduledPublishing: {
25
+ enabled: false
26
+ },
27
+
28
+ plugins: [structureTool({
29
+ structure
30
+ })],
31
+
32
+ schema: {
33
+ types: schemaTypes,
34
+ // Filter out singleton types from the global “New document” menu options
35
+ templates: (templates) =>
36
+ templates.filter(({ schemaType }) => !singletonTypes.has(schemaType)),
37
+ },
38
+
39
+ document: {
40
+ // For singleton types, filter out actions that are not explicitly included
41
+ // in the `singletonActions` list defined above
42
+ actions: getActions(singletonTypes),
43
+ },
44
+ });
45
+ }
46
+
47
+ export function getConfigWithNetlify(projectId:string, title:string, structure:StructureResolver, schemaTypes:any, singletonTypes:Set<string>, sites:SiteWidgetOption[]) {
48
+ return defineConfig({
49
+ name: 'default',
50
+ title,
51
+
52
+ projectId,
53
+ dataset: 'production',
54
+
55
+ scheduledPublishing: {
56
+ enabled: false
57
+ },
58
+
59
+ plugins: [
60
+ structureTool({
61
+ structure
62
+ }),
63
+ dashboardTool({
64
+ widgets: [
65
+ netlifyWidget({
66
+ title: 'Deploy Site',
67
+ sites
68
+ })
69
+ ]
70
+ })
71
+ ],
72
+
73
+ schema: {
74
+ types: schemaTypes,
75
+ // Filter out singleton types from the global “New document” menu options
76
+ templates: (templates) =>
77
+ templates.filter(({ schemaType }) => !singletonTypes.has(schemaType)),
78
+ },
79
+
80
+ document: {
81
+ // For singleton types, filter out actions that are not explicitly included
82
+ // in the `singletonActions` list defined above
83
+ actions: getActions(singletonTypes),
84
+ },
85
+ });
86
+ }
package/src/main.ts ADDED
@@ -0,0 +1,6 @@
1
+ export * from './components/core/SEOImage';
2
+ export * from './components/core/SEO';
3
+ // export * from './config/utils';
4
+ export * from './validators/utils';
5
+ export * from './components/ui/DeployButton';
6
+ export * from './components/video/VideoSchemas';
@@ -0,0 +1,17 @@
1
+ import { Rule } from "sanity";
2
+
3
+ /**
4
+ * Deprecated use Sanity's Rule.uri instead!!
5
+ * @returns regexp url validator
6
+ */
7
+ export function urlValidation() {
8
+ return (rule:Rule) =>
9
+ rule.custom((url:string) => {
10
+ if (typeof url === 'undefined' || url === null) {
11
+ return true; // Allow undefined values
12
+ }
13
+
14
+ const regex = /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)$/;
15
+ return regex.test(url) ? true : 'Not a valid URL';
16
+ });
17
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "lib": ["DOM", "DOM.Iterable", "ESNext"],
5
+ "module": "ESNext",
6
+ "declaration": true,
7
+ "outDir": "./lib",
8
+ "strict": true,
9
+ "skipLibCheck": true,
10
+ "resolveJsonModule": true,
11
+ "moduleResolution": "node",
12
+ "jsx": "react-jsx"
13
+ },
14
+ "include": [
15
+ "src",
16
+ ],
17
+ "exclude": [
18
+ "node_modules"
19
+ ]
20
+ }