@hello-better/sanity-media 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,14 @@
1
+ import type { MediaOptions } from './types.js';
2
+ export type { MediaOptions, MediaType } from './types.js';
3
+ export declare const createMediaBlock: (options?: MediaOptions) => {
4
+ type: "object";
5
+ name: string;
6
+ } & Omit<import("sanity").ObjectDefinition, "preview"> & {
7
+ preview?: import("sanity").PreviewConfig<{
8
+ title: string;
9
+ titlePrefix: string;
10
+ mediaType: string;
11
+ image: string;
12
+ }, Record<"image" | "title" | "mediaType" | "titlePrefix", any>> | undefined;
13
+ };
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,YAAY,CAAA;AAE5C,YAAY,EAAC,YAAY,EAAE,SAAS,EAAC,MAAM,YAAY,CAAA;AAEvD,eAAO,MAAM,gBAAgB,GAAI,UAAS,YAAiB;;;;;;;;;;CAO1D,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ import { createMediaBlockType } from './schema/mediaBlock.js';
2
+ export const createMediaBlock = (options = {}) => {
3
+ const mediaBlockTypeName = options.typeNames?.mediaBlock ?? 'mediaBlock';
4
+ return createMediaBlockType({
5
+ typeName: mediaBlockTypeName,
6
+ options,
7
+ });
8
+ };
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,oBAAoB,EAAC,MAAM,wBAAwB,CAAA;AAK3D,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,UAAwB,EAAE,EAAE,EAAE;IAC7D,MAAM,kBAAkB,GAAG,OAAO,CAAC,SAAS,EAAE,UAAU,IAAI,YAAY,CAAA;IAExE,OAAO,oBAAoB,CAAC;QAC1B,QAAQ,EAAE,kBAAkB;QAC5B,OAAO;KACR,CAAC,CAAA;AACJ,CAAC,CAAA"}
@@ -0,0 +1,18 @@
1
+ import type { MediaOptions } from '../types.js';
2
+ type CreateMediaBlockTypeParams = {
3
+ typeName?: string;
4
+ options?: MediaOptions;
5
+ };
6
+ export declare const createMediaBlockType: ({ typeName, options, }?: CreateMediaBlockTypeParams) => {
7
+ type: "object";
8
+ name: string;
9
+ } & Omit<import("sanity").ObjectDefinition, "preview"> & {
10
+ preview?: import("sanity").PreviewConfig<{
11
+ title: string;
12
+ titlePrefix: string;
13
+ mediaType: string;
14
+ image: string;
15
+ }, Record<"image" | "title" | "mediaType" | "titlePrefix", any>> | undefined;
16
+ };
17
+ export {};
18
+ //# sourceMappingURL=mediaBlock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mediaBlock.d.ts","sourceRoot":"","sources":["../../src/schema/mediaBlock.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,aAAa,CAAA;AAE7C,KAAK,0BAA0B,GAAG;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,YAAY,CAAA;CACvB,CAAA;AAED,eAAO,MAAM,oBAAoB,GAAI,yBAGlC,0BAA+B;;;;;;;;;;CAqFjC,CAAA"}
@@ -0,0 +1,82 @@
1
+ import { defineArrayMember, defineField, defineType } from 'sanity';
2
+ import { createMediaItemFields } from './mediaItemFields.js';
3
+ export const createMediaBlockType = ({ typeName = 'mediaBlock', options = {}, } = {}) => {
4
+ return defineType({
5
+ name: typeName,
6
+ title: 'Media Block',
7
+ type: 'object',
8
+ fields: [
9
+ defineField({
10
+ name: 'titlePrefix',
11
+ title: 'Title Prefix',
12
+ type: 'string',
13
+ }),
14
+ defineField({
15
+ name: 'title',
16
+ title: 'Title',
17
+ type: 'string',
18
+ }),
19
+ defineField({
20
+ name: 'html',
21
+ title: 'HTML',
22
+ type: 'array',
23
+ of: [
24
+ defineArrayMember({
25
+ type: 'block',
26
+ }),
27
+ ],
28
+ }),
29
+ defineField({
30
+ name: 'mediaItems',
31
+ title: 'Media Items',
32
+ type: 'array',
33
+ of: [
34
+ defineArrayMember({
35
+ name: 'mediaItem',
36
+ title: 'Media Item',
37
+ type: 'object',
38
+ fields: createMediaItemFields(options),
39
+ }),
40
+ ],
41
+ validation: (Rule) => {
42
+ let rule = Rule.min(options.minItems ?? 1);
43
+ if (options.maxItems) {
44
+ rule = rule.max(options.maxItems);
45
+ }
46
+ return rule;
47
+ },
48
+ }),
49
+ ...(options.blockSettingsFields?.length
50
+ ? [
51
+ defineField({
52
+ name: 'settings',
53
+ title: 'Settings',
54
+ type: 'object',
55
+ options: {
56
+ collapsible: true,
57
+ collapsed: true,
58
+ },
59
+ fields: options.blockSettingsFields,
60
+ }),
61
+ ]
62
+ : []),
63
+ ...(options.blockFields ?? []),
64
+ ],
65
+ preview: {
66
+ select: {
67
+ title: 'title',
68
+ titlePrefix: 'titlePrefix',
69
+ mediaType: 'mediaItems.0.mediaType',
70
+ image: 'mediaItems.0.image',
71
+ },
72
+ prepare: ({ title, titlePrefix, mediaType, image }) => {
73
+ return {
74
+ title: [titlePrefix, title].filter(Boolean).join(' ') || 'Media Block',
75
+ subtitle: mediaType ? `First item: ${mediaType}` : 'No media items',
76
+ media: image,
77
+ };
78
+ },
79
+ },
80
+ });
81
+ };
82
+ //# sourceMappingURL=mediaBlock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mediaBlock.js","sourceRoot":"","sources":["../../src/schema/mediaBlock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,iBAAiB,EAAE,WAAW,EAAE,UAAU,EAAC,MAAM,QAAQ,CAAA;AACjE,OAAO,EAAC,qBAAqB,EAAC,MAAM,sBAAsB,CAAA;AAQ1D,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,EACnC,QAAQ,GAAG,YAAY,EACvB,OAAO,GAAG,EAAE,MACkB,EAAE,EAAE,EAAE;IACpC,OAAO,UAAU,CAAC;QAChB,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,aAAa;QACpB,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE;YACN,WAAW,CAAC;gBACV,IAAI,EAAE,aAAa;gBACnB,KAAK,EAAE,cAAc;gBACrB,IAAI,EAAE,QAAQ;aACf,CAAC;YAEF,WAAW,CAAC;gBACV,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,OAAO;gBACd,IAAI,EAAE,QAAQ;aACf,CAAC;YAEF,WAAW,CAAC;gBACV,IAAI,EAAE,MAAM;gBACZ,KAAK,EAAE,MAAM;gBACb,IAAI,EAAE,OAAO;gBACb,EAAE,EAAE;oBACF,iBAAiB,CAAC;wBAChB,IAAI,EAAE,OAAO;qBACd,CAAC;iBACH;aACF,CAAC;YAEF,WAAW,CAAC;gBACV,IAAI,EAAE,YAAY;gBAClB,KAAK,EAAE,aAAa;gBACpB,IAAI,EAAE,OAAO;gBACb,EAAE,EAAE;oBACF,iBAAiB,CAAC;wBAChB,IAAI,EAAE,WAAW;wBACjB,KAAK,EAAE,YAAY;wBACnB,IAAI,EAAE,QAAQ;wBACd,MAAM,EAAE,qBAAqB,CAAC,OAAO,CAAC;qBACvC,CAAC;iBACH;gBACD,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE;oBACnB,IAAI,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAA;oBAE1C,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;wBACrB,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;oBACnC,CAAC;oBAED,OAAO,IAAI,CAAA;gBACb,CAAC;aACF,CAAC;YAEF,GAAG,CAAC,OAAO,CAAC,mBAAmB,EAAE,MAAM;gBACrC,CAAC,CAAC;oBACE,WAAW,CAAC;wBACV,IAAI,EAAE,UAAU;wBAChB,KAAK,EAAE,UAAU;wBACjB,IAAI,EAAE,QAAQ;wBACd,OAAO,EAAE;4BACP,WAAW,EAAE,IAAI;4BACjB,SAAS,EAAE,IAAI;yBAChB;wBACD,MAAM,EAAE,OAAO,CAAC,mBAAmB;qBACpC,CAAC;iBACH;gBACH,CAAC,CAAC,EAAE,CAAC;YAEP,GAAG,CAAC,OAAO,CAAC,WAAW,IAAI,EAAE,CAAC;SAC/B;QACD,OAAO,EAAE;YACP,MAAM,EAAE;gBACN,KAAK,EAAE,OAAO;gBACd,WAAW,EAAE,aAAa;gBAC1B,SAAS,EAAE,wBAAwB;gBACnC,KAAK,EAAE,oBAAoB;aAC5B;YACD,OAAO,EAAE,CAAC,EAAC,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,EAAC,EAAE,EAAE;gBAClD,OAAO;oBACL,KAAK,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,aAAa;oBACtE,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,eAAe,SAAS,EAAE,CAAC,CAAC,CAAC,gBAAgB;oBACnE,KAAK,EAAE,KAAK;iBACb,CAAA;YACH,CAAC;SACF;KACF,CAAC,CAAA;AACJ,CAAC,CAAA"}
@@ -0,0 +1,19 @@
1
+ import { MediaOptions } from '../types.js';
2
+ type CreateMediaItemTypeParams = {
3
+ typeName: string;
4
+ options: MediaOptions;
5
+ };
6
+ export declare const createMediaItemType: ({ typeName, options, }: CreateMediaItemTypeParams) => {
7
+ type: "object";
8
+ name: string;
9
+ } & Omit<import("sanity").ObjectDefinition, "preview"> & {
10
+ preview?: import("sanity").PreviewConfig<{
11
+ mediaType: string;
12
+ caption: string;
13
+ image: string;
14
+ videoFile: string;
15
+ embedUrl: string;
16
+ }, Record<"image" | "videoFile" | "mediaType" | "embedUrl" | "caption", any>> | undefined;
17
+ };
18
+ export {};
19
+ //# sourceMappingURL=mediaItem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mediaItem.d.ts","sourceRoot":"","sources":["../../src/schema/mediaItem.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAa,MAAM,aAAa,CAAA;AAIrD,KAAK,yBAAyB,GAAG;IAC/B,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,YAAY,CAAA;CACtB,CAAA;AAED,eAAO,MAAM,mBAAmB,GAAI,wBAGjC,yBAAyB;;;;;;;;;;;CAkJ3B,CAAA"}
@@ -0,0 +1,131 @@
1
+ import { defineField, defineType } from 'sanity';
2
+ import { appendFields } from './utils.js';
3
+ const defaultMediaTypes = ['image', 'videoFile', 'embed'];
4
+ export const createMediaItemType = ({ typeName, options, }) => {
5
+ const enabledMediaTypes = options.mediaTypes ?? defaultMediaTypes;
6
+ const mediaTypeOptions = [
7
+ { title: 'Image', value: 'image' },
8
+ { title: 'Video - File', value: 'videoFile' },
9
+ { title: 'Video - Embed', value: 'embed' },
10
+ ].filter((item) => enabledMediaTypes.includes(item.value));
11
+ const defaultFields = [
12
+ defineField({
13
+ name: 'mediaType',
14
+ title: 'Type',
15
+ type: 'string',
16
+ initialValue: mediaTypeOptions[0]?.value,
17
+ options: {
18
+ layout: 'radio',
19
+ list: mediaTypeOptions,
20
+ },
21
+ validation: (Rule) => Rule.required(),
22
+ }),
23
+ defineField({
24
+ name: 'image',
25
+ title: 'Image',
26
+ type: 'image',
27
+ hidden: ({ parent }) => parent?.mediaType !== 'image',
28
+ options: {
29
+ hotspot: options.imageOptions?.hotspot ?? true,
30
+ metadata: options.imageOptions?.metadata ?? ['blurhash', 'lqip', 'palette'],
31
+ },
32
+ fields: [
33
+ defineField({
34
+ name: 'alt',
35
+ title: 'Alt text',
36
+ type: 'string',
37
+ description: 'Short description for accessibility and SEO.',
38
+ }),
39
+ ],
40
+ validation: (Rule) => Rule.custom((value, context) => {
41
+ const parent = context.parent;
42
+ if (parent?.mediaType === 'image' && !value?.asset?._ref) {
43
+ return 'Image is required.';
44
+ }
45
+ return true;
46
+ }),
47
+ }),
48
+ defineField({
49
+ name: 'videoFile',
50
+ title: 'Video file',
51
+ type: 'file',
52
+ hidden: ({ parent }) => parent?.mediaType !== 'videoFile',
53
+ options: {
54
+ accept: options.videoFileOptions?.accept ?? 'video/*',
55
+ storeOriginalFilename: options.videoFileOptions?.storeOriginalFilename ?? false,
56
+ },
57
+ validation: (Rule) => Rule.custom((value, context) => {
58
+ const parent = context.parent;
59
+ if (parent?.mediaType === 'videoFile' && !value?.asset?._ref) {
60
+ return 'Video file is required.';
61
+ }
62
+ return true;
63
+ }),
64
+ }),
65
+ defineField({
66
+ name: 'embedUrl',
67
+ title: 'Video URL',
68
+ type: 'url',
69
+ hidden: ({ parent }) => parent?.mediaType !== 'embed',
70
+ validation: (Rule) => Rule.uri({
71
+ scheme: ['http', 'https'],
72
+ }).custom((value, context) => {
73
+ const parent = context.parent;
74
+ if (parent?.mediaType === 'embed' && !value) {
75
+ return 'Video URL is required.';
76
+ }
77
+ return true;
78
+ }),
79
+ }),
80
+ defineField({
81
+ name: 'caption',
82
+ title: 'Caption',
83
+ type: 'text',
84
+ rows: 2,
85
+ }),
86
+ ...(options.itemSettingsFields?.length
87
+ ? [
88
+ defineField({
89
+ name: 'settings',
90
+ title: 'Settings',
91
+ type: 'object',
92
+ options: {
93
+ collapsible: true,
94
+ collapsed: true,
95
+ },
96
+ fields: options.itemSettingsFields,
97
+ }),
98
+ ]
99
+ : []),
100
+ ];
101
+ return defineType({
102
+ name: typeName,
103
+ title: 'Media Item',
104
+ type: 'object',
105
+ fields: appendFields(defaultFields, options.itemFields),
106
+ preview: {
107
+ select: {
108
+ mediaType: 'mediaType',
109
+ caption: 'caption',
110
+ image: 'image',
111
+ videoFile: 'videoFile.asset.originalFilename',
112
+ embedUrl: 'embedUrl',
113
+ },
114
+ prepare: ({ mediaType, caption, image, videoFile, embedUrl }) => {
115
+ const mediaLabel = mediaType === 'image'
116
+ ? 'Image'
117
+ : mediaType === 'videoFile'
118
+ ? 'Video file'
119
+ : mediaType === 'embed'
120
+ ? 'Embedded video'
121
+ : 'Media item';
122
+ return {
123
+ title: caption || mediaLabel,
124
+ subtitle: videoFile || embedUrl || mediaLabel,
125
+ media: image,
126
+ };
127
+ },
128
+ },
129
+ });
130
+ };
131
+ //# sourceMappingURL=mediaItem.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mediaItem.js","sourceRoot":"","sources":["../../src/schema/mediaItem.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { MediaOptions } from '../types.js';
2
+ export declare const createMediaItemFields: (options?: MediaOptions) => import("sanity").FieldDefinition[];
3
+ //# sourceMappingURL=mediaItemFields.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mediaItemFields.d.ts","sourceRoot":"","sources":["../../src/schema/mediaItemFields.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,YAAY,EAAY,MAAM,aAAa,CAAA;AAUxD,eAAO,MAAM,qBAAqB,GAAI,UAAS,YAAiB,uCAkG/D,CAAA"}
@@ -0,0 +1,90 @@
1
+ import { defineField } from 'sanity';
2
+ const defaultMediaTypes = ['image', 'videoFile', 'embed'];
3
+ const defaultImageMetadata = [
4
+ 'blurhash',
5
+ 'lqip',
6
+ 'palette',
7
+ ];
8
+ export const createMediaItemFields = (options = {}) => {
9
+ const enabledMediaTypes = options.mediaTypes ?? defaultMediaTypes;
10
+ const mediaTypeOptions = [
11
+ { title: 'Image', value: 'image' },
12
+ { title: 'Video - File', value: 'videoFile' },
13
+ { title: 'Video - Embed', value: 'embed' },
14
+ ].filter((item) => enabledMediaTypes.includes(item.value));
15
+ return [
16
+ defineField({
17
+ name: 'mediaType',
18
+ title: 'Type',
19
+ type: 'string',
20
+ initialValue: mediaTypeOptions[0]?.value,
21
+ options: {
22
+ layout: 'dropdown',
23
+ list: mediaTypeOptions,
24
+ },
25
+ validation: (Rule) => Rule.required(),
26
+ }),
27
+ defineField({
28
+ name: 'image',
29
+ title: 'Image',
30
+ type: 'image',
31
+ hidden: ({ parent }) => parent?.mediaType !== 'image',
32
+ options: {
33
+ hotspot: options.imageOptions?.hotspot ?? true,
34
+ metadata: options.imageOptions?.metadata ?? defaultImageMetadata,
35
+ },
36
+ fields: [
37
+ defineField({
38
+ name: 'alt',
39
+ title: 'Alt text',
40
+ type: 'string',
41
+ }),
42
+ ],
43
+ validation: (Rule) => Rule.custom((value, context) => {
44
+ const parent = context.parent;
45
+ if (parent?.mediaType === 'image' && !value?.asset?._ref) {
46
+ return 'Image is required.';
47
+ }
48
+ return true;
49
+ }),
50
+ }),
51
+ defineField({
52
+ name: 'videoFile',
53
+ title: 'Video file',
54
+ type: 'file',
55
+ hidden: ({ parent }) => parent?.mediaType !== 'videoFile',
56
+ options: {
57
+ accept: options.videoFileOptions?.accept ?? 'video/*',
58
+ storeOriginalFilename: options.videoFileOptions?.storeOriginalFilename ?? false,
59
+ },
60
+ validation: (Rule) => Rule.custom((value, context) => {
61
+ const parent = context.parent;
62
+ if (parent?.mediaType === 'videoFile' && !value?.asset?._ref) {
63
+ return 'Video file is required.';
64
+ }
65
+ return true;
66
+ }),
67
+ }),
68
+ defineField({
69
+ name: 'embedUrl',
70
+ title: 'Video URL',
71
+ type: 'url',
72
+ hidden: ({ parent }) => parent?.mediaType !== 'embed',
73
+ validation: (Rule) => Rule.uri({ scheme: ['http', 'https'] }).custom((value, context) => {
74
+ const parent = context.parent;
75
+ if (parent?.mediaType === 'embed' && !value) {
76
+ return 'Video URL is required.';
77
+ }
78
+ return true;
79
+ }),
80
+ }),
81
+ defineField({
82
+ name: 'caption',
83
+ title: 'Caption',
84
+ type: 'text',
85
+ rows: 2,
86
+ }),
87
+ ...(options.itemFields ?? []),
88
+ ];
89
+ };
90
+ //# sourceMappingURL=mediaItemFields.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mediaItemFields.js","sourceRoot":"","sources":["../../src/schema/mediaItemFields.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { FieldDefinition } from 'sanity';
2
+ export declare const appendFields: (defaultFields: FieldDefinition[], extraFields?: FieldDefinition[]) => FieldDefinition[];
3
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/schema/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,QAAQ,CAAA;AAE3C,eAAO,MAAM,YAAY,GACvB,eAAe,eAAe,EAAE,EAChC,cAAa,eAAe,EAAO,sBAIpC,CAAA"}
@@ -0,0 +1,5 @@
1
+ export const appendFields = (defaultFields, extraFields = []) => {
2
+ // Allows project users to add custom fields
3
+ return [...defaultFields, ...extraFields];
4
+ };
5
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/schema/utils.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,aAAgC,EAChC,cAAiC,EAAE,EACnC,EAAE;IACF,4CAA4C;IAC5C,OAAO,CAAC,GAAG,aAAa,EAAE,GAAG,WAAW,CAAC,CAAA;AAC3C,CAAC,CAAA"}
@@ -0,0 +1,24 @@
1
+ import type { FieldDefinition, ImageMetadataType } from 'sanity';
2
+ export type MediaType = 'image' | 'videoFile' | 'embed';
3
+ export type MediaOptions = {
4
+ typeNames?: {
5
+ mediaBlock?: string;
6
+ mediaItem?: string;
7
+ };
8
+ mediaTypes?: MediaType[];
9
+ minItems?: number;
10
+ maxItems?: number;
11
+ blockFields?: FieldDefinition[];
12
+ itemFields?: FieldDefinition[];
13
+ blockSettingsFields?: FieldDefinition[];
14
+ itemSettingsFields?: FieldDefinition[];
15
+ imageOptions?: {
16
+ hotspot?: boolean;
17
+ metadata?: ImageMetadataType[];
18
+ };
19
+ videoFileOptions?: {
20
+ accept?: string;
21
+ storeOriginalFilename?: boolean;
22
+ };
23
+ };
24
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,eAAe,EAAE,iBAAiB,EAAC,MAAM,QAAQ,CAAA;AAE9D,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,WAAW,GAAG,OAAO,CAAA;AAEvD,MAAM,MAAM,YAAY,GAAG;IACzB,SAAS,CAAC,EAAE;QACV,UAAU,CAAC,EAAE,MAAM,CAAA;QACnB,SAAS,CAAC,EAAE,MAAM,CAAA;KACnB,CAAA;IAED,UAAU,CAAC,EAAE,SAAS,EAAE,CAAA;IAExB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB,WAAW,CAAC,EAAE,eAAe,EAAE,CAAA;IAC/B,UAAU,CAAC,EAAE,eAAe,EAAE,CAAA;IAE9B,mBAAmB,CAAC,EAAE,eAAe,EAAE,CAAA;IACvC,kBAAkB,CAAC,EAAE,eAAe,EAAE,CAAA;IAEtC,YAAY,CAAC,EAAE;QACb,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB,QAAQ,CAAC,EAAE,iBAAiB,EAAE,CAAA;KAC/B,CAAA;IAED,gBAAgB,CAAC,EAAE;QACjB,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,qBAAqB,CAAC,EAAE,OAAO,CAAA;KAChC,CAAA;CACF,CAAA"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@hello-better/sanity-media",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": ["dist", "README.md"],
15
+ "scripts": {
16
+ "clean": "rimraf dist",
17
+ "build": "yarn clean && tsc",
18
+ "prepublishOnly": "yarn build"
19
+ },
20
+ "peerDependencies": {
21
+ "@hello-better/sanity-core": "^0.1.1",
22
+ "sanity": ">=5.24.0",
23
+ "react": ">=18 <20",
24
+ "react-dom": ">=18 <20"
25
+ },
26
+ "devDependencies": {
27
+ "typescript": "^6.0.3",
28
+ "rimraf": "^6.0.1"
29
+ },
30
+ "publishConfig": {
31
+ "access": "restricted"
32
+ }
33
+ }