@electrolux-oss/sanity-plugin-media 5.0.1 → 5.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.
- package/README.md +63 -14
- package/dist/index.d.ts +141 -204
- package/dist/index.js +5657 -5965
- package/dist/index.js.map +1 -1
- package/package.json +51 -52
package/README.md
CHANGED
|
@@ -223,7 +223,18 @@ The plugin adds an **Edit Media** option to the asset menu of image and file fie
|
|
|
223
223
|
|
|
224
224
|
### Link the plugin to a local studio
|
|
225
225
|
|
|
226
|
-
**Step 1:
|
|
226
|
+
**Step 1: Install the studio's dependencies**
|
|
227
|
+
|
|
228
|
+
In your studio project directory, run:
|
|
229
|
+
|
|
230
|
+
```zsh
|
|
231
|
+
npm install
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
This installs the published version of the plugin, so its own dependencies end up in the
|
|
235
|
+
studio's `node_modules`.
|
|
236
|
+
|
|
237
|
+
**Step 2: Publish the plugin to yalc and watch for changes**
|
|
227
238
|
|
|
228
239
|
In the plugin directory, run:
|
|
229
240
|
|
|
@@ -234,29 +245,33 @@ npm run link-watch
|
|
|
234
245
|
This will:
|
|
235
246
|
|
|
236
247
|
- Build your plugin automatically whenever code changes
|
|
237
|
-
- Publish the package to a local yalc repository
|
|
248
|
+
- Publish the package to a local yalc repository and push it to linked studios
|
|
238
249
|
|
|
239
|
-
**Step
|
|
250
|
+
**Step 3: Link the plugin to your studio**
|
|
240
251
|
|
|
241
252
|
In your studio project directory, run:
|
|
242
253
|
|
|
243
254
|
```zsh
|
|
244
|
-
npx yalc
|
|
255
|
+
npx yalc link @electrolux-oss/sanity-plugin-media
|
|
245
256
|
```
|
|
246
257
|
|
|
247
|
-
**Step
|
|
258
|
+
**Step 4: Verify the setup**
|
|
248
259
|
|
|
249
|
-
|
|
260
|
+
`node_modules/@electrolux-oss/sanity-plugin-media` is now a symlink to
|
|
261
|
+
`.yalc/@electrolux-oss/sanity-plugin-media`, and the studio's `package.json` is unchanged:
|
|
250
262
|
|
|
251
|
-
```
|
|
252
|
-
|
|
263
|
+
```zsh
|
|
264
|
+
ls -l node_modules/@electrolux-oss/
|
|
265
|
+
git diff package.json # no change
|
|
253
266
|
```
|
|
254
267
|
|
|
255
|
-
|
|
268
|
+
Don't run `npm install` in the studio while linked: it replaces the link with the published
|
|
269
|
+
version. Run `npx yalc link @electrolux-oss/sanity-plugin-media` again if you did. To stop,
|
|
270
|
+
run `npx yalc remove @electrolux-oss/sanity-plugin-media && npm install`.
|
|
256
271
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
272
|
+
Avoid `yalc add` here. It writes `file:.yalc/…` into the studio's `package.json`, and with
|
|
273
|
+
`link-watch` every rebuild replaces the plugin with a copy that can't resolve the plugin's own
|
|
274
|
+
dependencies.
|
|
260
275
|
|
|
261
276
|
### Making changes
|
|
262
277
|
|
|
@@ -268,12 +283,46 @@ serves the old build.
|
|
|
268
283
|
|
|
269
284
|
```zsh
|
|
270
285
|
npm run typecheck # tsc --noEmit
|
|
271
|
-
npm run lint #
|
|
272
|
-
npm run
|
|
286
|
+
npm run lint # oxlint, type-aware; warnings count as errors
|
|
287
|
+
npm run format # oxfmt
|
|
288
|
+
npm run build # plugin-kit verify-package, then pkg-utils
|
|
273
289
|
```
|
|
274
290
|
|
|
275
291
|
This plugin has no automated tests yet.
|
|
276
292
|
|
|
293
|
+
`npm run build` doesn't type-check (pkg-utils 13 generates types without checking them), so
|
|
294
|
+
run `typecheck` or `lint` to catch type errors.
|
|
295
|
+
|
|
296
|
+
### Formatting
|
|
297
|
+
|
|
298
|
+
The plugin is formatted with [oxfmt](https://oxc.rs/docs/guide/usage/formatter.html), using
|
|
299
|
+
plugin-kit's preset with the repository's previous Prettier settings on top (see
|
|
300
|
+
`oxfmt.config.ts`). To format on save in VS Code, install the
|
|
301
|
+
[Oxc extension](https://marketplace.visualstudio.com/items?itemName=oxc.oxc-vscode) and make it
|
|
302
|
+
the default formatter for this workspace; a global Prettier formatter would undo oxfmt's
|
|
303
|
+
import and `package.json` sorting.
|
|
304
|
+
|
|
305
|
+
### Publishing
|
|
306
|
+
|
|
307
|
+
Releases are published with pnpm, while development uses npm:
|
|
308
|
+
|
|
309
|
+
```zsh
|
|
310
|
+
npm run publish:next:dry-run # what would ship
|
|
311
|
+
npm run publish:next # publish behind the next tag
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
pnpm is a pinned devDependency, so `npm ci` installs it. Don't use `npm publish`.
|
|
315
|
+
|
|
316
|
+
pkg-utils writes a `source` condition into `exports` for local development and a
|
|
317
|
+
`source`-less `publishConfig.exports` for the published package. pnpm applies
|
|
318
|
+
`publishConfig` when it packs the package; npm doesn't, and would publish an export that points
|
|
319
|
+
at `src/`, which isn't shipped. To check what the packed `package.json` exports:
|
|
320
|
+
|
|
321
|
+
```zsh
|
|
322
|
+
D=$(mktemp -d) && npx pnpm pack --pack-destination "$D" >/dev/null && tar xzf "$D"/*.tgz -C "$D" && node -p "JSON.stringify(require('$D/package/package.json').exports)"
|
|
323
|
+
# -> {".":"./dist/index.js","./package.json":"./package.json"}, no "source"
|
|
324
|
+
```
|
|
325
|
+
|
|
277
326
|
## Breaking changes
|
|
278
327
|
|
|
279
328
|
### **v4 → v5**
|
package/dist/index.d.ts
CHANGED
|
@@ -1,221 +1,158 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
declare const createAssetFormSchema: (
|
|
41
|
-
languages: MediaToolOptions['languages'],
|
|
42
|
-
validateAltTexts?: boolean
|
|
43
|
-
) => z.ZodObject<
|
|
44
|
-
{
|
|
45
|
-
altText: z.ZodOptional<z.ZodString>
|
|
46
|
-
altTexts: z.ZodRecord<z.ZodString, z.ZodOptional<z.ZodNullable<z.ZodString>>>
|
|
47
|
-
creditLine: z.ZodOptional<z.ZodString>
|
|
48
|
-
description: z.ZodOptional<z.ZodString>
|
|
49
|
-
opt: z.ZodObject<
|
|
50
|
-
{
|
|
51
|
-
media: z.ZodObject<
|
|
52
|
-
{
|
|
53
|
-
tags: z.ZodNullable<
|
|
54
|
-
z.ZodArray<
|
|
55
|
-
z.ZodObject<
|
|
56
|
-
{
|
|
57
|
-
label: z.ZodString
|
|
58
|
-
value: z.ZodString
|
|
59
|
-
},
|
|
60
|
-
z.core.$strip
|
|
61
|
-
>
|
|
62
|
-
>
|
|
63
|
-
>
|
|
64
|
-
},
|
|
65
|
-
z.core.$strip
|
|
66
|
-
>
|
|
67
|
-
},
|
|
68
|
-
z.core.$strip
|
|
69
|
-
>
|
|
70
|
-
originalFilename: z.ZodString
|
|
71
|
-
title: z.ZodOptional<z.ZodString>
|
|
72
|
-
},
|
|
73
|
-
z.core.$strip
|
|
74
|
-
>
|
|
75
|
-
|
|
76
|
-
declare type CustomFields = {
|
|
77
|
-
altText?: string
|
|
78
|
-
altTexts?: Record<string, string>
|
|
79
|
-
description?: string
|
|
80
|
-
opt?: {
|
|
81
|
-
media?: {
|
|
82
|
-
tags?: SanityReference[]
|
|
83
|
-
uploadedBy?: Uploader | string
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
title?: string
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
declare type DetailsProps = {
|
|
90
|
-
formUpdating: boolean
|
|
91
|
-
handleCreateTag: (title: string) => void
|
|
92
|
-
control: Control<AssetFormData>
|
|
93
|
-
errors: FieldErrors<AssetFormData>
|
|
94
|
-
register: UseFormRegister<AssetFormData>
|
|
95
|
-
allTagOptions: TagSelectOption[]
|
|
96
|
-
assetTagOptions: TagSelectOption[] | null
|
|
97
|
-
currentAsset: Asset
|
|
1
|
+
import { ComponentType, JSX } from "react";
|
|
2
|
+
import { FieldDefinitionBase, FileDefinition, ImageDefinition, InputProps, WidenInitialValue, WidenValidation } from "sanity";
|
|
3
|
+
import * as z from "zod";
|
|
4
|
+
import "react-redux";
|
|
5
|
+
import "@reduxjs/toolkit";
|
|
6
|
+
import "redux-observable";
|
|
7
|
+
import { Control, FieldErrors, UseFormRegister } from "react-hook-form";
|
|
8
|
+
import { SanityAssetDocument, SanityImageAssetDocument } from "@sanity/client";
|
|
9
|
+
declare const tagOptionSchema: z.ZodObject<{
|
|
10
|
+
label: z.ZodString;
|
|
11
|
+
value: z.ZodString;
|
|
12
|
+
}, z.core.$strip>;
|
|
13
|
+
declare const createAssetFormSchema: (languages: MediaToolOptions["languages"], validateAltTexts?: boolean) => z.ZodObject<{
|
|
14
|
+
altText: z.ZodOptional<z.ZodString>;
|
|
15
|
+
altTexts: z.ZodRecord<z.ZodString, z.ZodOptional<z.ZodNullable<z.ZodString>>>;
|
|
16
|
+
creditLine: z.ZodOptional<z.ZodString>;
|
|
17
|
+
description: z.ZodOptional<z.ZodString>;
|
|
18
|
+
opt: z.ZodObject<{
|
|
19
|
+
media: z.ZodObject<{
|
|
20
|
+
tags: z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
21
|
+
label: z.ZodString;
|
|
22
|
+
value: z.ZodString;
|
|
23
|
+
}, z.core.$strip>>>;
|
|
24
|
+
}, z.core.$strip>;
|
|
25
|
+
}, z.core.$strip>;
|
|
26
|
+
originalFilename: z.ZodString;
|
|
27
|
+
title: z.ZodOptional<z.ZodString>;
|
|
28
|
+
}, z.core.$strip>;
|
|
29
|
+
type AssetFormSchemaObject = ReturnType<typeof createAssetFormSchema>;
|
|
30
|
+
type DetailsProps = {
|
|
31
|
+
formUpdating: boolean;
|
|
32
|
+
handleCreateTag: (title: string) => void;
|
|
33
|
+
control: Control<AssetFormData>;
|
|
34
|
+
errors: FieldErrors<AssetFormData>;
|
|
35
|
+
register: UseFormRegister<AssetFormData>;
|
|
36
|
+
allTagOptions: TagSelectOption[];
|
|
37
|
+
assetTagOptions: TagSelectOption[] | null;
|
|
38
|
+
currentAsset: Asset;
|
|
98
39
|
creditLine?: {
|
|
99
|
-
enabled: boolean
|
|
100
|
-
excludeSources?: string | string[] | undefined
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
_type: 'sanity.fileAsset'
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
declare type ImageAsset = SanityImageAssetDocument &
|
|
110
|
-
CustomFields & {
|
|
111
|
-
_type: 'sanity.imageAsset'
|
|
112
|
-
creditLine?: string
|
|
40
|
+
enabled: boolean;
|
|
41
|
+
excludeSources?: string | string[] | undefined;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
declare global {
|
|
45
|
+
interface SymbolConstructor {
|
|
46
|
+
readonly observable: symbol;
|
|
113
47
|
}
|
|
114
|
-
|
|
115
|
-
export declare const media: Plugin_2<void | MediaToolOptions>
|
|
116
|
-
|
|
117
|
-
export declare const mediaAssetSource: {
|
|
118
|
-
component: (props: AssetSourceComponentProps) => JSX
|
|
119
|
-
uploadMode: 'component'
|
|
120
|
-
icon: ForwardRefExoticComponent<
|
|
121
|
-
Omit<SVGProps<SVGSVGElement>, 'ref'> & RefAttributes<SVGSVGElement>
|
|
122
|
-
>
|
|
123
|
-
name: string
|
|
124
|
-
title: string
|
|
125
48
|
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Defines an image or file field whose selected / uploaded assets are tagged with `mediaTags`.
|
|
129
|
-
*
|
|
130
|
-
* `mediaTags` is copied to `options.mediaTags` (which pre-filters the media browser) and
|
|
131
|
-
* {@link AutoTagInput} is set as the input component.
|
|
132
|
-
*
|
|
133
|
-
* ```ts
|
|
134
|
-
* mediaField({ name: 'image', type: 'image', mediaTags: ['product'] })
|
|
135
|
-
* ```
|
|
136
|
-
*/
|
|
137
|
-
export declare function mediaField(
|
|
138
|
-
config: MediaFieldConfig<ImageDefinition>
|
|
139
|
-
): MediaFieldResult<ImageDefinition>
|
|
140
|
-
|
|
141
|
-
export declare function mediaField(
|
|
142
|
-
config: MediaFieldConfig<FileDefinition>
|
|
143
|
-
): MediaFieldResult<FileDefinition>
|
|
144
|
-
|
|
145
|
-
declare type MediaFieldConfig<T extends ImageDefinition | FileDefinition> = Omit<T, 'options'> &
|
|
146
|
-
FieldDefinitionBase & {
|
|
147
|
-
name: string
|
|
148
|
-
mediaTags: string[]
|
|
149
|
-
options?: T['options']
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
declare type MediaFieldResult<T extends ImageDefinition | FileDefinition> = Omit<T, 'options'> &
|
|
153
|
-
FieldDefinitionBase & {
|
|
154
|
-
options?: T['options'] & {
|
|
155
|
-
mediaTags: string[]
|
|
156
|
-
}
|
|
157
|
-
components: {
|
|
158
|
-
input: typeof AutoTagInput
|
|
159
|
-
}
|
|
160
|
-
} & WidenValidation &
|
|
161
|
-
WidenInitialValue
|
|
162
|
-
|
|
163
|
-
export declare type MediaToolOptions = {
|
|
49
|
+
type MediaToolOptions = {
|
|
164
50
|
languages: {
|
|
165
|
-
code: string
|
|
166
|
-
title: string
|
|
167
|
-
default?: boolean
|
|
168
|
-
}[]
|
|
169
|
-
maximumUploadSize?: number
|
|
170
|
-
createTagsOnUpload?: boolean
|
|
51
|
+
code: string;
|
|
52
|
+
title: string;
|
|
53
|
+
default?: boolean;
|
|
54
|
+
}[];
|
|
55
|
+
maximumUploadSize?: number;
|
|
56
|
+
createTagsOnUpload?: boolean;
|
|
171
57
|
components?: {
|
|
172
|
-
details?: ComponentType<
|
|
173
|
-
DetailsProps
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
>
|
|
177
|
-
}
|
|
58
|
+
details?: ComponentType<DetailsProps & {
|
|
59
|
+
renderDefaultDetails: (props: DetailsProps) => JSX.Element;
|
|
60
|
+
}>;
|
|
61
|
+
};
|
|
178
62
|
creditLine: {
|
|
179
|
-
enabled: boolean
|
|
180
|
-
excludeSources?: string | string[]
|
|
181
|
-
}
|
|
182
|
-
directUploads?: boolean
|
|
183
|
-
uploadMenu?: boolean
|
|
63
|
+
enabled: boolean;
|
|
64
|
+
excludeSources?: string | string[];
|
|
65
|
+
};
|
|
66
|
+
directUploads?: boolean;
|
|
67
|
+
uploadMenu?: boolean;
|
|
184
68
|
/**
|
|
185
69
|
* Tag slugs (`media.tag` `name.current`) whose assets are hidden from the Media browser and
|
|
186
70
|
* asset picker, along with the tags themselves in the tag panel and tag search facet.
|
|
187
71
|
* The asset edit dialog still lists every tag.
|
|
188
72
|
*/
|
|
189
|
-
excludeTags?: string[]
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
_ref: string
|
|
194
|
-
_type: 'reference'
|
|
195
|
-
_weak?: boolean
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
declare const tagOptionSchema: z.ZodObject<
|
|
199
|
-
{
|
|
200
|
-
label: z.ZodString
|
|
201
|
-
value: z.ZodString
|
|
202
|
-
},
|
|
203
|
-
z.core.$strip
|
|
204
|
-
>
|
|
205
|
-
|
|
206
|
-
declare type TagSelectOption = z.infer<typeof tagOptionSchema>
|
|
207
|
-
|
|
208
|
-
declare type Uploader = {
|
|
209
|
-
id: string
|
|
73
|
+
excludeTags?: string[];
|
|
74
|
+
};
|
|
75
|
+
type Uploader = {
|
|
76
|
+
id: string;
|
|
210
77
|
/** Only set by earlier builds; the name is now looked up on demand. */
|
|
211
|
-
name?: string
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
78
|
+
name?: string;
|
|
79
|
+
};
|
|
80
|
+
type CustomFields = {
|
|
81
|
+
altText?: string;
|
|
82
|
+
altTexts?: Record<string, string>;
|
|
83
|
+
description?: string;
|
|
84
|
+
opt?: {
|
|
85
|
+
media?: {
|
|
86
|
+
tags?: SanityReference[];
|
|
87
|
+
uploadedBy?: Uploader | string;
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
title?: string;
|
|
91
|
+
};
|
|
92
|
+
type Asset = FileAsset | ImageAsset;
|
|
93
|
+
type AssetFormData = z.infer<AssetFormSchemaObject>;
|
|
94
|
+
type FileAsset = SanityAssetDocument & CustomFields & {
|
|
95
|
+
_type: 'sanity.fileAsset';
|
|
96
|
+
};
|
|
97
|
+
type ImageAsset = SanityImageAssetDocument & CustomFields & {
|
|
98
|
+
_type: 'sanity.imageAsset';
|
|
99
|
+
creditLine?: string;
|
|
100
|
+
};
|
|
101
|
+
type SanityReference = {
|
|
102
|
+
_ref: string;
|
|
103
|
+
_type: 'reference';
|
|
104
|
+
_weak?: boolean;
|
|
105
|
+
};
|
|
106
|
+
type TagSelectOption = z.infer<typeof tagOptionSchema>;
|
|
216
107
|
declare module 'sanity' {
|
|
217
108
|
interface FileOptions {
|
|
218
109
|
/** Tags applied by `AutoTagInput` / `mediaField`, also used to pre-filter the media browser. */
|
|
219
|
-
mediaTags?: string[]
|
|
110
|
+
mediaTags?: string[];
|
|
220
111
|
}
|
|
221
112
|
}
|
|
113
|
+
export declare const mediaAssetSource: {
|
|
114
|
+
component: (props: import("sanity").AssetSourceComponentProps) => import("react/jsx-runtime").JSX.Element;
|
|
115
|
+
uploadMode: "component";
|
|
116
|
+
icon: import("react").ForwardRefExoticComponent<Omit<import("react").SVGProps<SVGSVGElement>, "ref"> & import("react").RefAttributes<SVGSVGElement>>;
|
|
117
|
+
name: string;
|
|
118
|
+
title: string;
|
|
119
|
+
};
|
|
120
|
+
export declare const media: import("sanity").Plugin<void | MediaToolOptions>;
|
|
121
|
+
type AutoTagInputProps = InputProps & {
|
|
122
|
+
mediaTags?: string[];
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* Image / file input that tags the selected or uploaded asset with `mediaTags`.
|
|
126
|
+
*
|
|
127
|
+
* Tags come from the `mediaTags` prop, falling back to `options.mediaTags` on the field
|
|
128
|
+
* (which also pre-filters the media browser). Only changes made after mount are tagged,
|
|
129
|
+
* so opening a document never patches its existing assets.
|
|
130
|
+
*/
|
|
131
|
+
export declare function AutoTagInput(props: AutoTagInputProps): import("react").JSX.Element;
|
|
132
|
+
type MediaFieldConfig<T extends ImageDefinition | FileDefinition> = Omit<T, 'options'> & FieldDefinitionBase & {
|
|
133
|
+
name: string;
|
|
134
|
+
mediaTags: string[];
|
|
135
|
+
options?: T['options'];
|
|
136
|
+
};
|
|
137
|
+
type MediaFieldResult<T extends ImageDefinition | FileDefinition> = Omit<T, 'options'> & FieldDefinitionBase & {
|
|
138
|
+
options?: T['options'] & {
|
|
139
|
+
mediaTags: string[];
|
|
140
|
+
};
|
|
141
|
+
components: {
|
|
142
|
+
input: typeof AutoTagInput;
|
|
143
|
+
};
|
|
144
|
+
} & WidenValidation & WidenInitialValue;
|
|
145
|
+
/**
|
|
146
|
+
* Defines an image or file field whose selected / uploaded assets are tagged with `mediaTags`.
|
|
147
|
+
*
|
|
148
|
+
* `mediaTags` is copied to `options.mediaTags` (which pre-filters the media browser) and
|
|
149
|
+
* {@link AutoTagInput} is set as the input component.
|
|
150
|
+
*
|
|
151
|
+
* ```ts
|
|
152
|
+
* mediaField({ name: 'image', type: 'image', mediaTags: ['product'] })
|
|
153
|
+
* ```
|
|
154
|
+
*/
|
|
155
|
+
export declare function mediaField(config: MediaFieldConfig<ImageDefinition>): MediaFieldResult<ImageDefinition>;
|
|
156
|
+
export declare function mediaField(config: MediaFieldConfig<FileDefinition>): MediaFieldResult<FileDefinition>;
|
|
157
|
+
export type { AutoTagInputProps, MediaToolOptions };
|
|
158
|
+
//# sourceMappingURL=index.d.ts.map
|