sanity-plugin-media 4.1.1 → 4.3.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/LICENSE +1 -1
- package/README.md +107 -3
- package/dist/index.d.mts +227 -56
- package/dist/index.d.ts +227 -56
- package/dist/index.js +473 -184
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +476 -187
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -2
- package/src/__tests__/fixtures/createEpicTestStore.ts +27 -0
- package/src/__tests__/fixtures/listenMock.ts +9 -0
- package/src/__tests__/fixtures/mockSanityClient.ts +84 -0
- package/src/__tests__/fixtures/renderWithProviders.tsx +54 -0
- package/src/__tests__/fixtures/rootState.ts +27 -0
- package/src/__tests__/fixtures/withinDialog.ts +28 -0
- package/src/components/AutoTagInputWrapper/index.tsx +82 -0
- package/src/components/Browser/Browser.test.tsx +44 -0
- package/src/components/Browser/index.tsx +12 -69
- package/src/components/Browser/useBrowserInit.ts +126 -0
- package/src/components/CardAsset/CardAsset.test.tsx +322 -0
- package/src/components/DialogAssetEdit/Details.tsx +123 -44
- package/src/components/DialogAssetEdit/DialogAssetEdit.test.tsx +215 -0
- package/src/components/DialogAssetEdit/index.tsx +138 -30
- package/src/components/DialogTagCreate/DialogTagCreate.test.tsx +120 -0
- package/src/components/DialogTagEdit/DialogTagEdit.test.tsx +164 -0
- package/src/components/FormBuilderTool/FormBuilderTool.test.tsx +62 -0
- package/src/components/FormBuilderTool/index.tsx +1 -1
- package/src/components/UploadDropzone/UploadDropzone.test.tsx +39 -0
- package/src/contexts/ToolOptionsContext.tsx +9 -3
- package/src/formSchema/index.test.ts +55 -0
- package/src/formSchema/index.ts +28 -12
- package/src/hooks/useVersionedClient.ts +1 -1
- package/src/index.ts +4 -1
- package/src/modules/assets/deleteAndUpdateEpics.test.ts +86 -0
- package/src/modules/assets/fetchEpic.test.ts +72 -0
- package/src/modules/assets/reducer.test.ts +90 -0
- package/src/modules/assets/tagsAndListenerEpics.test.ts +205 -0
- package/src/modules/dialog/epics.test.ts +167 -0
- package/src/modules/dialog/reducer.test.ts +184 -0
- package/src/modules/notifications/epics.test.ts +373 -0
- package/src/modules/notifications/index.ts +24 -4
- package/src/modules/notifications/reducer.test.ts +53 -0
- package/src/modules/search/index.test.ts +35 -0
- package/src/modules/selectors.test.ts +20 -0
- package/src/modules/tags/epics.test.ts +95 -0
- package/src/modules/tags/index.test.ts +41 -0
- package/src/modules/uploads/epics.test.ts +108 -0
- package/src/modules/uploads/index.test.ts +58 -0
- package/src/operators/checkTagName.test.ts +28 -0
- package/src/types/index.ts +25 -7
- package/src/utils/applyMediaTags.ts +86 -0
- package/src/utils/blocksToText.test.ts +42 -0
- package/src/utils/constructFilter.test.ts +119 -0
- package/src/utils/generatePreviewBlobUrl.test.ts +69 -0
- package/src/utils/getAssetResolution.test.ts +12 -0
- package/src/utils/getDocumentAssetIds.test.ts +49 -0
- package/src/utils/getSchemeColor.test.ts +11 -0
- package/src/utils/getTagSelectOptions.test.ts +43 -0
- package/src/utils/getUniqueDocuments.test.ts +25 -0
- package/src/utils/imageDprUrl.test.ts +45 -0
- package/src/utils/isSupportedAssetType.test.ts +15 -0
- package/src/utils/mediaField.ts +72 -0
- package/src/utils/sanitizeFormData.test.ts +58 -0
- package/src/utils/typeGuards.test.ts +17 -0
- package/src/utils/uploadSanityAsset.test.ts +28 -0
- package/src/utils/withMaxConcurrency.test.ts +42 -0
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: !0 });
|
|
3
|
-
var jsxRuntime = require("react/jsx-runtime"), sanity = require("sanity"), icons = require("@sanity/icons"), ui = require("@sanity/ui"), react = require("react"),
|
|
3
|
+
var jsxRuntime = require("react/jsx-runtime"), sanity = require("sanity"), icons = require("@sanity/icons"), ui = require("@sanity/ui"), react = require("react"), styledComponents = require("styled-components"), reactRedux = require("react-redux"), toolkit = require("@reduxjs/toolkit"), pluralize = require("pluralize"), reduxObservable = require("redux-observable"), rxjs = require("rxjs"), operators$1 = require("rxjs/operators"), groq = require("groq"), nanoid = require("nanoid"), uuid = require("@sanity/uuid"), reactNprogress = require("@tanem/react-nprogress"), color = require("@sanity/color"), Select = require("react-select"), reactVirtuoso = require("react-virtuoso"), zod = require("@hookform/resolvers/zod"), reactHookForm = require("react-hook-form"), z = require("zod"), dateFns = require("date-fns"), filesize = require("filesize"), copy = require("copy-to-clipboard"), router = require("sanity/router"), reactFileIcon = require("react-file-icon"), CreatableSelect = require("react-select/creatable"), reactDropzone = require("react-dropzone");
|
|
4
4
|
function _interopDefaultCompat(e) {
|
|
5
5
|
return e && typeof e == "object" && "default" in e ? e : { default: e };
|
|
6
6
|
}
|
|
@@ -19,7 +19,7 @@ function _interopNamespaceCompat(e) {
|
|
|
19
19
|
}
|
|
20
20
|
}), n.default = e, Object.freeze(n);
|
|
21
21
|
}
|
|
22
|
-
var
|
|
22
|
+
var pluralize__default = /* @__PURE__ */ _interopDefaultCompat(pluralize), groq__default = /* @__PURE__ */ _interopDefaultCompat(groq), Select__default = /* @__PURE__ */ _interopDefaultCompat(Select), z__namespace = /* @__PURE__ */ _interopNamespaceCompat(z), filesize__default = /* @__PURE__ */ _interopDefaultCompat(filesize), copy__default = /* @__PURE__ */ _interopDefaultCompat(copy), CreatableSelect__default = /* @__PURE__ */ _interopDefaultCompat(CreatableSelect);
|
|
23
23
|
function getDefaultExportFromCjs(x) {
|
|
24
24
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x.default : x;
|
|
25
25
|
}
|
|
@@ -169,7 +169,71 @@ const useKeyPress = (hotkey, onPress) => {
|
|
|
169
169
|
return react.useEffect(() => (window.addEventListener("keydown", downHandler), window.addEventListener("keyup", upHandler), () => {
|
|
170
170
|
window.removeEventListener("keydown", downHandler), window.removeEventListener("keyup", upHandler);
|
|
171
171
|
}), [downHandler, upHandler]), keyPressed;
|
|
172
|
-
},
|
|
172
|
+
}, AssetSourceDispatchContext = react.createContext(void 0), AssetBrowserDispatchProvider = (props) => {
|
|
173
|
+
const { children, onSelect } = props, contextValue = {
|
|
174
|
+
onSelect
|
|
175
|
+
};
|
|
176
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AssetSourceDispatchContext.Provider, { value: contextValue, children });
|
|
177
|
+
}, useAssetSourceActions = () => {
|
|
178
|
+
const context = react.useContext(AssetSourceDispatchContext);
|
|
179
|
+
if (context === void 0)
|
|
180
|
+
throw new Error("useAssetSourceActions must be used within an AssetSourceDispatchProvider");
|
|
181
|
+
return context;
|
|
182
|
+
}, useVersionedClient = () => sanity.useClient({ apiVersion: "2025-10-02" }), customScrollbar = styledComponents.css`
|
|
183
|
+
::-webkit-scrollbar {
|
|
184
|
+
width: 14px;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
::-webkit-scrollbar-thumb {
|
|
188
|
+
border-radius: 10px;
|
|
189
|
+
border: 4px solid rgba(0, 0, 0, 0);
|
|
190
|
+
background: var(--card-border-color);
|
|
191
|
+
background-clip: padding-box;
|
|
192
|
+
|
|
193
|
+
&:hover {
|
|
194
|
+
background: var(--card-muted-fg-color);
|
|
195
|
+
background-clip: padding-box;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
`, GlobalStyle = styledComponents.createGlobalStyle`
|
|
199
|
+
.media__custom-scrollbar {
|
|
200
|
+
${customScrollbar}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// @sanity/ui overrides
|
|
204
|
+
|
|
205
|
+
// Custom scrollbar on Box (used in Dialogs)
|
|
206
|
+
div[data-ui="Box"] {
|
|
207
|
+
${customScrollbar}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Dialog background color
|
|
211
|
+
div[data-ui="Dialog"] {
|
|
212
|
+
background-color: rgba(15, 17, 18, 0.9);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
`, useTypedSelector = reactRedux.useSelector, ORDER_DICTIONARY = {
|
|
216
|
+
_createdAt: {
|
|
217
|
+
asc: "Last created: Oldest first",
|
|
218
|
+
desc: "Last created: Newest first"
|
|
219
|
+
},
|
|
220
|
+
_updatedAt: {
|
|
221
|
+
asc: "Last updated: Oldest first",
|
|
222
|
+
desc: "Last updated: Newest first"
|
|
223
|
+
},
|
|
224
|
+
mimeType: {
|
|
225
|
+
asc: "MIME type: A to Z",
|
|
226
|
+
desc: "MIME type: Z to A"
|
|
227
|
+
},
|
|
228
|
+
originalFilename: {
|
|
229
|
+
asc: "File name: A to Z",
|
|
230
|
+
desc: "File name: Z to A"
|
|
231
|
+
},
|
|
232
|
+
size: {
|
|
233
|
+
asc: "File size: Smallest first",
|
|
234
|
+
desc: "File size: Largest first"
|
|
235
|
+
}
|
|
236
|
+
}, getOrderTitle = (field, direction) => ORDER_DICTIONARY[field][direction], divider = { type: "divider" }, inputs = {
|
|
173
237
|
altText: {
|
|
174
238
|
assetTypes: ["file", "image"],
|
|
175
239
|
field: "altText",
|
|
@@ -532,38 +596,7 @@ const useKeyPress = (hotkey, onPress) => {
|
|
|
532
596
|
], GRID_TEMPLATE_COLUMNS = {
|
|
533
597
|
SMALL: "3rem 100px auto 1.5rem",
|
|
534
598
|
LARGE: "3rem 100px auto 5.5rem 5.5rem 3.5rem 8.5rem 4.75rem 2rem"
|
|
535
|
-
}, PANEL_HEIGHT = 32, TAG_DOCUMENT_NAME = "media.tag", TAGS_PANEL_WIDTH = 250,
|
|
536
|
-
const { children, onSelect } = props, contextValue = {
|
|
537
|
-
onSelect
|
|
538
|
-
};
|
|
539
|
-
return /* @__PURE__ */ jsxRuntime.jsx(AssetSourceDispatchContext.Provider, { value: contextValue, children });
|
|
540
|
-
}, useAssetSourceActions = () => {
|
|
541
|
-
const context = react.useContext(AssetSourceDispatchContext);
|
|
542
|
-
if (context === void 0)
|
|
543
|
-
throw new Error("useAssetSourceActions must be used within an AssetSourceDispatchProvider");
|
|
544
|
-
return context;
|
|
545
|
-
}, useVersionedClient = () => sanity.useClient({ apiVersion: "2022-10-01" }), ORDER_DICTIONARY = {
|
|
546
|
-
_createdAt: {
|
|
547
|
-
asc: "Last created: Oldest first",
|
|
548
|
-
desc: "Last created: Newest first"
|
|
549
|
-
},
|
|
550
|
-
_updatedAt: {
|
|
551
|
-
asc: "Last updated: Oldest first",
|
|
552
|
-
desc: "Last updated: Newest first"
|
|
553
|
-
},
|
|
554
|
-
mimeType: {
|
|
555
|
-
asc: "MIME type: A to Z",
|
|
556
|
-
desc: "MIME type: Z to A"
|
|
557
|
-
},
|
|
558
|
-
originalFilename: {
|
|
559
|
-
asc: "File name: A to Z",
|
|
560
|
-
desc: "File name: Z to A"
|
|
561
|
-
},
|
|
562
|
-
size: {
|
|
563
|
-
asc: "File size: Smallest first",
|
|
564
|
-
desc: "File size: Largest first"
|
|
565
|
-
}
|
|
566
|
-
}, getOrderTitle = (field, direction) => ORDER_DICTIONARY[field][direction], debugThrottle = (throttled) => function(source) {
|
|
599
|
+
}, PANEL_HEIGHT = 32, TAG_DOCUMENT_NAME = "media.tag", TAGS_PANEL_WIDTH = 250, debugThrottle = (throttled) => function(source) {
|
|
567
600
|
return rxjs.iif(
|
|
568
601
|
() => !!throttled,
|
|
569
602
|
source.pipe(
|
|
@@ -1607,40 +1640,7 @@ const UPLOADS_ACTIONS = {
|
|
|
1607
1640
|
(assetsPicked) => assetsPicked.length
|
|
1608
1641
|
), assetsActions = { ...assetsSlice.actions };
|
|
1609
1642
|
var assetsReducer = assetsSlice.reducer;
|
|
1610
|
-
const
|
|
1611
|
-
::-webkit-scrollbar {
|
|
1612
|
-
width: 14px;
|
|
1613
|
-
}
|
|
1614
|
-
|
|
1615
|
-
::-webkit-scrollbar-thumb {
|
|
1616
|
-
border-radius: 10px;
|
|
1617
|
-
border: 4px solid rgba(0, 0, 0, 0);
|
|
1618
|
-
background: var(--card-border-color);
|
|
1619
|
-
background-clip: padding-box;
|
|
1620
|
-
|
|
1621
|
-
&:hover {
|
|
1622
|
-
background: var(--card-muted-fg-color);
|
|
1623
|
-
background-clip: padding-box;
|
|
1624
|
-
}
|
|
1625
|
-
}
|
|
1626
|
-
`, GlobalStyle = styledComponents.createGlobalStyle`
|
|
1627
|
-
.media__custom-scrollbar {
|
|
1628
|
-
${customScrollbar}
|
|
1629
|
-
}
|
|
1630
|
-
|
|
1631
|
-
// @sanity/ui overrides
|
|
1632
|
-
|
|
1633
|
-
// Custom scrollbar on Box (used in Dialogs)
|
|
1634
|
-
div[data-ui="Box"] {
|
|
1635
|
-
${customScrollbar}
|
|
1636
|
-
}
|
|
1637
|
-
|
|
1638
|
-
// Dialog background color
|
|
1639
|
-
div[data-ui="Dialog"] {
|
|
1640
|
-
background-color: rgba(15, 17, 18, 0.9);
|
|
1641
|
-
}
|
|
1642
|
-
|
|
1643
|
-
`, useTypedSelector = reactRedux.useSelector, initialState$4 = {
|
|
1643
|
+
const initialState$4 = {
|
|
1644
1644
|
items: []
|
|
1645
1645
|
}, dialogSlice = toolkit.createSlice({
|
|
1646
1646
|
name: "dialog",
|
|
@@ -2361,18 +2361,22 @@ const Container$1 = styledComponents.styled(ui.Box)(({ $scheme, theme }) => styl
|
|
|
2361
2361
|
components: {
|
|
2362
2362
|
details: options?.components?.details
|
|
2363
2363
|
},
|
|
2364
|
+
createTagsOnUpload: options?.createTagsOnUpload ?? !0,
|
|
2364
2365
|
creditLine: {
|
|
2365
2366
|
enabled: options?.creditLine?.enabled || !1,
|
|
2366
2367
|
excludeSources: creditLineExcludeSources
|
|
2367
2368
|
},
|
|
2368
|
-
directUploads: options?.directUploads ?? !0
|
|
2369
|
+
directUploads: options?.directUploads ?? !0,
|
|
2370
|
+
locales: options?.locales
|
|
2369
2371
|
};
|
|
2370
2372
|
}, [
|
|
2371
2373
|
options?.creditLine?.enabled,
|
|
2372
2374
|
options?.components,
|
|
2375
|
+
options?.createTagsOnUpload,
|
|
2373
2376
|
options?.creditLine?.excludeSources,
|
|
2374
2377
|
options?.maximumUploadSize,
|
|
2375
|
-
options?.directUploads
|
|
2378
|
+
options?.directUploads,
|
|
2379
|
+
options?.locales
|
|
2376
2380
|
]);
|
|
2377
2381
|
return /* @__PURE__ */ jsxRuntime.jsx(ToolOptionsContext.Provider, { value, children });
|
|
2378
2382
|
}, useToolOptions = () => {
|
|
@@ -2651,21 +2655,35 @@ const DebugControls = () => {
|
|
|
2651
2655
|
] })
|
|
2652
2656
|
}
|
|
2653
2657
|
) : null;
|
|
2654
|
-
}
|
|
2658
|
+
};
|
|
2659
|
+
function localizedStringSchema(locales) {
|
|
2660
|
+
if (!locales || locales.length === 0)
|
|
2661
|
+
return z__namespace.string().trim().optional();
|
|
2662
|
+
const shape = {};
|
|
2663
|
+
for (const locale of locales)
|
|
2664
|
+
shape[locale.id] = z__namespace.string().trim().optional();
|
|
2665
|
+
return z__namespace.object(shape).passthrough();
|
|
2666
|
+
}
|
|
2667
|
+
const tagOptionSchema = z__namespace.object({
|
|
2655
2668
|
label: z__namespace.string().trim().min(1, { message: "Label cannot be empty" }),
|
|
2656
2669
|
value: z__namespace.string().trim().min(1, { message: "Value cannot be empty" })
|
|
2657
|
-
})
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2670
|
+
});
|
|
2671
|
+
function getAssetFormSchema(locales) {
|
|
2672
|
+
return z__namespace.object({
|
|
2673
|
+
altText: localizedStringSchema(locales),
|
|
2674
|
+
creditLine: localizedStringSchema(locales),
|
|
2675
|
+
description: localizedStringSchema(locales),
|
|
2676
|
+
opt: z__namespace.object({
|
|
2677
|
+
media: z__namespace.object({
|
|
2678
|
+
tags: z__namespace.array(tagOptionSchema).nullable()
|
|
2679
|
+
})
|
|
2680
|
+
}),
|
|
2681
|
+
originalFilename: z__namespace.string().trim().min(1, { message: "Filename cannot be empty" }),
|
|
2682
|
+
title: localizedStringSchema(locales)
|
|
2683
|
+
});
|
|
2684
|
+
}
|
|
2685
|
+
getAssetFormSchema();
|
|
2686
|
+
const tagFormSchema = z__namespace.object({
|
|
2669
2687
|
name: z__namespace.string().min(1, { message: "Name cannot be empty" })
|
|
2670
2688
|
});
|
|
2671
2689
|
function getUniqueDocuments(documents) {
|
|
@@ -3100,6 +3118,11 @@ const imageDprUrl = (asset, options) => {
|
|
|
3100
3118
|
)
|
|
3101
3119
|
] });
|
|
3102
3120
|
});
|
|
3121
|
+
function toStringField(value) {
|
|
3122
|
+
if (typeof value == "string") return value;
|
|
3123
|
+
if (typeof value == "object" && value !== null)
|
|
3124
|
+
return Object.values(value).find((v) => v) || void 0;
|
|
3125
|
+
}
|
|
3103
3126
|
function Details({
|
|
3104
3127
|
formUpdating,
|
|
3105
3128
|
handleCreateTag,
|
|
@@ -3109,8 +3132,10 @@ function Details({
|
|
|
3109
3132
|
allTagOptions,
|
|
3110
3133
|
assetTagOptions,
|
|
3111
3134
|
currentAsset,
|
|
3112
|
-
creditLine
|
|
3135
|
+
creditLine,
|
|
3136
|
+
locales
|
|
3113
3137
|
}) {
|
|
3138
|
+
const hasLocales = locales && locales.length > 0, [activeLocaleTab, setActiveLocaleTab] = react.useState(0);
|
|
3114
3139
|
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
|
|
3115
3140
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3116
3141
|
FormFieldInputTags,
|
|
@@ -3137,51 +3162,117 @@ function Details({
|
|
|
3137
3162
|
value: currentAsset?.originalFilename
|
|
3138
3163
|
}
|
|
3139
3164
|
),
|
|
3140
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3165
|
+
hasLocales ? /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { marginTop: 2, shadow: 1, padding: 3, radius: 1, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 2, children: [
|
|
3166
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.TabList, { space: 2, children: locales.map((locale, idx) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3167
|
+
ui.Tab,
|
|
3168
|
+
{
|
|
3169
|
+
id: `locale-tab-${locale.id}`,
|
|
3170
|
+
"aria-controls": `locale-panel-${locale.id}`,
|
|
3171
|
+
selected: activeLocaleTab === idx,
|
|
3172
|
+
onClick: () => setActiveLocaleTab(idx),
|
|
3173
|
+
label: locale.title
|
|
3174
|
+
},
|
|
3175
|
+
locale.id
|
|
3176
|
+
)) }),
|
|
3177
|
+
locales.map((locale, idx) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3178
|
+
ui.TabPanel,
|
|
3179
|
+
{
|
|
3180
|
+
id: `locale-panel-${locale.id}`,
|
|
3181
|
+
"aria-labelledby": `locale-tab-${locale.id}`,
|
|
3182
|
+
hidden: activeLocaleTab !== idx,
|
|
3183
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
|
|
3184
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3185
|
+
FormFieldInputText,
|
|
3186
|
+
{
|
|
3187
|
+
...register(`title.${locale.id}`),
|
|
3188
|
+
disabled: formUpdating,
|
|
3189
|
+
error: errors?.title?.[locale.id]?.message,
|
|
3190
|
+
label: "Title",
|
|
3191
|
+
name: `title.${locale.id}`
|
|
3192
|
+
}
|
|
3193
|
+
),
|
|
3194
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3195
|
+
FormFieldInputText,
|
|
3196
|
+
{
|
|
3197
|
+
...register(`altText.${locale.id}`),
|
|
3198
|
+
disabled: formUpdating,
|
|
3199
|
+
error: errors?.altText?.[locale.id]?.message,
|
|
3200
|
+
label: "Alt Text",
|
|
3201
|
+
name: `altText.${locale.id}`
|
|
3202
|
+
}
|
|
3203
|
+
),
|
|
3204
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3205
|
+
FormFieldInputTextarea,
|
|
3206
|
+
{
|
|
3207
|
+
...register(`description.${locale.id}`),
|
|
3208
|
+
disabled: formUpdating,
|
|
3209
|
+
error: errors?.description?.[locale.id]?.message,
|
|
3210
|
+
label: "Description",
|
|
3211
|
+
name: `description.${locale.id}`,
|
|
3212
|
+
rows: 5
|
|
3213
|
+
}
|
|
3214
|
+
),
|
|
3215
|
+
creditLine?.enabled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3216
|
+
FormFieldInputText,
|
|
3217
|
+
{
|
|
3218
|
+
...register(`creditLine.${locale.id}`),
|
|
3219
|
+
error: errors?.creditLine?.[locale.id]?.message,
|
|
3220
|
+
label: "Credit",
|
|
3221
|
+
name: `creditLine.${locale.id}`,
|
|
3222
|
+
disabled: formUpdating || creditLine?.excludeSources?.includes(currentAsset?.source?.name)
|
|
3223
|
+
}
|
|
3224
|
+
)
|
|
3225
|
+
] })
|
|
3226
|
+
},
|
|
3227
|
+
locale.id
|
|
3228
|
+
))
|
|
3229
|
+
] }) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3230
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3231
|
+
FormFieldInputText,
|
|
3232
|
+
{
|
|
3233
|
+
...register("title"),
|
|
3234
|
+
disabled: formUpdating,
|
|
3235
|
+
error: errors?.title?.message,
|
|
3236
|
+
label: "Title",
|
|
3237
|
+
name: "title",
|
|
3238
|
+
value: toStringField(currentAsset?.title)
|
|
3239
|
+
}
|
|
3240
|
+
),
|
|
3241
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3242
|
+
FormFieldInputText,
|
|
3243
|
+
{
|
|
3244
|
+
...register("altText"),
|
|
3245
|
+
disabled: formUpdating,
|
|
3246
|
+
error: errors?.altText?.message,
|
|
3247
|
+
label: "Alt Text",
|
|
3248
|
+
name: "altText",
|
|
3249
|
+
value: toStringField(currentAsset?.altText)
|
|
3250
|
+
}
|
|
3251
|
+
),
|
|
3252
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3253
|
+
FormFieldInputTextarea,
|
|
3254
|
+
{
|
|
3255
|
+
...register("description"),
|
|
3256
|
+
disabled: formUpdating,
|
|
3257
|
+
error: errors?.description?.message,
|
|
3258
|
+
label: "Description",
|
|
3259
|
+
name: "description",
|
|
3260
|
+
rows: 5,
|
|
3261
|
+
value: toStringField(currentAsset?.description)
|
|
3262
|
+
}
|
|
3263
|
+
),
|
|
3264
|
+
creditLine?.enabled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3265
|
+
FormFieldInputText,
|
|
3266
|
+
{
|
|
3267
|
+
...register("creditLine"),
|
|
3268
|
+
error: errors?.creditLine?.message,
|
|
3269
|
+
label: "Credit",
|
|
3270
|
+
name: "creditLine",
|
|
3271
|
+
value: toStringField(currentAsset?.creditLine),
|
|
3272
|
+
disabled: formUpdating || creditLine?.excludeSources?.includes(currentAsset?.source?.name)
|
|
3273
|
+
}
|
|
3274
|
+
)
|
|
3275
|
+
] })
|
|
3185
3276
|
] });
|
|
3186
3277
|
}
|
|
3187
3278
|
function renderDefaultDetails(props) {
|
|
@@ -3191,16 +3282,37 @@ const DialogAssetEdit = (props) => {
|
|
|
3191
3282
|
const {
|
|
3192
3283
|
children,
|
|
3193
3284
|
dialog: { assetId, id, lastCreatedTag, lastRemovedTagIds }
|
|
3194
|
-
} = props, client = useVersionedClient(), scheme = sanity.useColorSchemeValue(), documentStore = sanity.useDocumentStore(), dispatch = reactRedux.useDispatch(), assetItem = useTypedSelector((state) => selectAssetById(state, String(assetId))), tags = useTypedSelector(selectTags), assetUpdatedPrev = react.useRef(void 0), [assetSnapshot, setAssetSnapshot] = react.useState(assetItem?.asset), [tabSection, setTabSection] = react.useState("details"), currentAsset = assetItem ? assetItem?.asset : assetSnapshot, allTagOptions = getTagSelectOptions(tags), assetTagOptions = useTypedSelector(selectTagSelectOptions(currentAsset)), { creditLine, components: { details: CustomDetails } = {} } = useToolOptions(), generateDefaultValues = react.useCallback(
|
|
3195
|
-
(asset) =>
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3285
|
+
} = props, client = useVersionedClient(), scheme = sanity.useColorSchemeValue(), documentStore = sanity.useDocumentStore(), dispatch = reactRedux.useDispatch(), assetItem = useTypedSelector((state) => selectAssetById(state, String(assetId))), tags = useTypedSelector(selectTags), assetUpdatedPrev = react.useRef(void 0), [assetSnapshot, setAssetSnapshot] = react.useState(assetItem?.asset), [tabSection, setTabSection] = react.useState("details"), currentAsset = assetItem ? assetItem?.asset : assetSnapshot, allTagOptions = getTagSelectOptions(tags), assetTagOptions = useTypedSelector(selectTagSelectOptions(currentAsset)), { creditLine, components: { details: CustomDetails } = {}, locales } = useToolOptions(), generateDefaultValues = react.useCallback(
|
|
3286
|
+
(asset) => {
|
|
3287
|
+
if (locales && locales.length > 0) {
|
|
3288
|
+
const makeLocaleObj = (field) => {
|
|
3289
|
+
const obj = {};
|
|
3290
|
+
for (let i = 0; i < locales.length; i++) {
|
|
3291
|
+
const locale = locales[i];
|
|
3292
|
+
typeof field == "object" && field && field[locale.id] ? obj[locale.id] = field[locale.id] : typeof field == "string" ? obj[locale.id] = i === 0 ? field : "" : obj[locale.id] = "";
|
|
3293
|
+
}
|
|
3294
|
+
return obj;
|
|
3295
|
+
};
|
|
3296
|
+
return {
|
|
3297
|
+
altText: makeLocaleObj(asset?.altText),
|
|
3298
|
+
creditLine: makeLocaleObj(asset?.creditLine),
|
|
3299
|
+
description: makeLocaleObj(asset?.description),
|
|
3300
|
+
originalFilename: asset?.originalFilename || "",
|
|
3301
|
+
opt: { media: { tags: assetTagOptions } },
|
|
3302
|
+
title: makeLocaleObj(asset?.title)
|
|
3303
|
+
};
|
|
3304
|
+
}
|
|
3305
|
+
const flattenField = (field) => typeof field == "string" ? field : typeof field == "object" && field !== null && Object.values(field).find((v) => v) || "";
|
|
3306
|
+
return {
|
|
3307
|
+
altText: flattenField(asset?.altText),
|
|
3308
|
+
creditLine: flattenField(asset?.creditLine),
|
|
3309
|
+
description: flattenField(asset?.description),
|
|
3310
|
+
originalFilename: asset?.originalFilename || "",
|
|
3311
|
+
opt: { media: { tags: assetTagOptions } },
|
|
3312
|
+
title: flattenField(asset?.title)
|
|
3313
|
+
};
|
|
3314
|
+
},
|
|
3315
|
+
[assetTagOptions, locales]
|
|
3204
3316
|
), {
|
|
3205
3317
|
control,
|
|
3206
3318
|
// Read the formState before render to subscribe the form state through Proxy
|
|
@@ -3213,7 +3325,7 @@ const DialogAssetEdit = (props) => {
|
|
|
3213
3325
|
} = reactHookForm.useForm({
|
|
3214
3326
|
defaultValues: generateDefaultValues(assetItem?.asset),
|
|
3215
3327
|
mode: "onChange",
|
|
3216
|
-
resolver: zod.zodResolver(
|
|
3328
|
+
resolver: zod.zodResolver(getAssetFormSchema(locales))
|
|
3217
3329
|
}), formUpdating = !assetItem || assetItem?.updating, handleClose = react.useCallback(() => {
|
|
3218
3330
|
dispatch(dialogActions.remove({ id }));
|
|
3219
3331
|
}, [dispatch, id]), handleDelete = react.useCallback(() => {
|
|
@@ -3236,7 +3348,39 @@ const DialogAssetEdit = (props) => {
|
|
|
3236
3348
|
);
|
|
3237
3349
|
},
|
|
3238
3350
|
[currentAsset?._id, dispatch]
|
|
3239
|
-
),
|
|
3351
|
+
), hasOrphanedLocales = react.useMemo(() => {
|
|
3352
|
+
if (!currentAsset) return !1;
|
|
3353
|
+
const isLocaleObj = (v) => typeof v == "object" && v !== null && !Array.isArray(v), fields = [
|
|
3354
|
+
currentAsset.title,
|
|
3355
|
+
currentAsset.altText,
|
|
3356
|
+
currentAsset.description,
|
|
3357
|
+
...currentAsset._type === "sanity.imageAsset" ? [currentAsset.creditLine] : []
|
|
3358
|
+
];
|
|
3359
|
+
if (!fields.some((f) => isLocaleObj(f))) return !1;
|
|
3360
|
+
if (!locales || locales.length === 0) return !0;
|
|
3361
|
+
const configuredIds = new Set(locales.map((l) => l.id));
|
|
3362
|
+
return fields.some((f) => isLocaleObj(f) ? Object.keys(f).some((k) => !configuredIds.has(k)) : !1);
|
|
3363
|
+
}, [currentAsset, locales]), handleCleanupLocales = react.useCallback(async () => {
|
|
3364
|
+
if (!currentAsset) return;
|
|
3365
|
+
const cleanField = (field) => {
|
|
3366
|
+
if (typeof field != "object" || field === null || Array.isArray(field)) return field;
|
|
3367
|
+
const obj = field;
|
|
3368
|
+
if (!locales || locales.length === 0)
|
|
3369
|
+
return Object.keys(obj).sort().map((k) => obj[k]).find((v) => v) || "";
|
|
3370
|
+
const configuredIds = new Set(locales.map((l) => l.id)), cleaned = {};
|
|
3371
|
+
for (const [key, val] of Object.entries(obj))
|
|
3372
|
+
configuredIds.has(key) && (cleaned[key] = val);
|
|
3373
|
+
return cleaned;
|
|
3374
|
+
};
|
|
3375
|
+
await client.patch(currentAsset._id).set({
|
|
3376
|
+
title: cleanField(currentAsset.title),
|
|
3377
|
+
altText: cleanField(currentAsset.altText),
|
|
3378
|
+
description: cleanField(currentAsset.description),
|
|
3379
|
+
...currentAsset._type === "sanity.imageAsset" && {
|
|
3380
|
+
creditLine: cleanField(currentAsset.creditLine)
|
|
3381
|
+
}
|
|
3382
|
+
}).commit();
|
|
3383
|
+
}, [client, currentAsset, locales]), onSubmit = react.useCallback(
|
|
3240
3384
|
(formData) => {
|
|
3241
3385
|
if (!assetItem?.asset)
|
|
3242
3386
|
return;
|
|
@@ -3284,27 +3428,42 @@ const DialogAssetEdit = (props) => {
|
|
|
3284
3428
|
}, [getValues, lastRemovedTagIds, setValue]), react.useEffect(() => {
|
|
3285
3429
|
assetUpdatedPrev.current !== assetItem?.asset._updatedAt && reset(generateDefaultValues(assetItem?.asset)), assetUpdatedPrev.current = assetItem?.asset._updatedAt;
|
|
3286
3430
|
}, [assetItem?.asset, generateDefaultValues, reset]);
|
|
3287
|
-
const Footer = () => /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { padding: 3, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.
|
|
3288
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3289
|
-
ui.
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3431
|
+
const Footer = () => /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { padding: 3, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
|
|
3432
|
+
hasOrphanedLocales && /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { padding: 3, radius: 2, shadow: 1, tone: "caution", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { align: "center", justify: "space-between", gap: 3, children: [
|
|
3433
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, children: "This asset has localized fields that are no longer configured. Clean them up to avoid validation errors." }),
|
|
3434
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3435
|
+
ui.Button,
|
|
3436
|
+
{
|
|
3437
|
+
fontSize: 1,
|
|
3438
|
+
mode: "ghost",
|
|
3439
|
+
onClick: handleCleanupLocales,
|
|
3440
|
+
text: "Cleanup localized fields",
|
|
3441
|
+
tone: "caution"
|
|
3442
|
+
}
|
|
3443
|
+
)
|
|
3444
|
+
] }) }),
|
|
3445
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { justify: "space-between", children: [
|
|
3446
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3447
|
+
ui.Button,
|
|
3448
|
+
{
|
|
3449
|
+
disabled: formUpdating,
|
|
3450
|
+
fontSize: 1,
|
|
3451
|
+
mode: "bleed",
|
|
3452
|
+
onClick: handleDelete,
|
|
3453
|
+
text: "Delete",
|
|
3454
|
+
tone: "critical"
|
|
3455
|
+
}
|
|
3456
|
+
),
|
|
3457
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3458
|
+
FormSubmitButton,
|
|
3459
|
+
{
|
|
3460
|
+
disabled: formUpdating || !isDirty || !isValid || hasOrphanedLocales,
|
|
3461
|
+
isValid,
|
|
3462
|
+
lastUpdated: currentAsset?._updatedAt,
|
|
3463
|
+
onClick: handleSubmit(onSubmit)
|
|
3464
|
+
}
|
|
3465
|
+
)
|
|
3466
|
+
] })
|
|
3308
3467
|
] }) });
|
|
3309
3468
|
if (!currentAsset)
|
|
3310
3469
|
return null;
|
|
@@ -3318,7 +3477,8 @@ const DialogAssetEdit = (props) => {
|
|
|
3318
3477
|
allTagOptions,
|
|
3319
3478
|
handleCreateTag,
|
|
3320
3479
|
currentAsset,
|
|
3321
|
-
creditLine
|
|
3480
|
+
creditLine,
|
|
3481
|
+
locales
|
|
3322
3482
|
};
|
|
3323
3483
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3324
3484
|
Dialog,
|
|
@@ -5104,6 +5264,9 @@ const TableRowUpload = (props) => {
|
|
|
5104
5264
|
reducers: {}
|
|
5105
5265
|
});
|
|
5106
5266
|
var selectedReducer = selectedSlice.reducer;
|
|
5267
|
+
function messageFromGenericErrorPayload(payload) {
|
|
5268
|
+
return !payload || typeof payload != "object" ? "Unknown error" : "error" in payload && payload.error && typeof payload.error == "object" && payload.error !== null && "message" in payload.error ? String(payload.error.message) : "message" in payload && typeof payload.message == "string" ? String(payload.message) : "Unknown error";
|
|
5269
|
+
}
|
|
5107
5270
|
const initialState = {
|
|
5108
5271
|
items: []
|
|
5109
5272
|
}, notificationsSlice = toolkit.createSlice({
|
|
@@ -5190,11 +5353,11 @@ const initialState = {
|
|
|
5190
5353
|
uploadsActions.uploadError.type
|
|
5191
5354
|
),
|
|
5192
5355
|
operators$1.mergeMap((action) => {
|
|
5193
|
-
const
|
|
5356
|
+
const title = `An error occurred: ${messageFromGenericErrorPayload(action.payload)}`;
|
|
5194
5357
|
return rxjs.of(
|
|
5195
5358
|
notificationsSlice.actions.add({
|
|
5196
5359
|
status: "error",
|
|
5197
|
-
title
|
|
5360
|
+
title
|
|
5198
5361
|
})
|
|
5199
5362
|
);
|
|
5200
5363
|
})
|
|
@@ -5442,24 +5605,81 @@ const UploadDropzone = (props) => {
|
|
|
5442
5605
|
isDragActive && /* @__PURE__ */ jsxRuntime.jsx(DragActiveContainer, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, { direction: "column", justify: "center", style: { color: color.white.hex }, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 3, style: { color: "inherit" }, children: "Drop files to upload" }) }) }),
|
|
5443
5606
|
children
|
|
5444
5607
|
] }) });
|
|
5445
|
-
}
|
|
5446
|
-
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
|
|
5450
|
-
|
|
5451
|
-
|
|
5452
|
-
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
|
|
5456
|
-
const
|
|
5608
|
+
};
|
|
5609
|
+
function getMediaTagNames(schemaType) {
|
|
5610
|
+
const mediaTags = schemaType?.options?.mediaTags;
|
|
5611
|
+
if (!mediaTags?.length) return [];
|
|
5612
|
+
const unique = new Set(
|
|
5613
|
+
mediaTags.map((t) => t?.trim()).filter((t) => !!t?.length)
|
|
5614
|
+
);
|
|
5615
|
+
return Array.from(unique);
|
|
5616
|
+
}
|
|
5617
|
+
function createAssetHandler(dispatch) {
|
|
5618
|
+
return (update) => {
|
|
5619
|
+
const { documentId, result, transition } = update;
|
|
5620
|
+
switch (transition) {
|
|
5621
|
+
case "appear":
|
|
5622
|
+
dispatch(assetsActions.listenerCreateQueue({ asset: result }));
|
|
5623
|
+
break;
|
|
5624
|
+
case "disappear":
|
|
5625
|
+
dispatch(assetsActions.listenerDeleteQueue({ assetId: documentId }));
|
|
5626
|
+
break;
|
|
5627
|
+
case "update":
|
|
5628
|
+
dispatch(assetsActions.listenerUpdateQueue({ asset: result }));
|
|
5629
|
+
break;
|
|
5630
|
+
}
|
|
5631
|
+
};
|
|
5632
|
+
}
|
|
5633
|
+
function createTagHandler(dispatch) {
|
|
5634
|
+
return (update) => {
|
|
5635
|
+
const { documentId, result, transition } = update;
|
|
5636
|
+
switch (transition) {
|
|
5637
|
+
case "appear":
|
|
5638
|
+
dispatch(tagsActions.listenerCreateQueue({ tag: result }));
|
|
5639
|
+
break;
|
|
5640
|
+
case "disappear":
|
|
5641
|
+
dispatch(tagsActions.listenerDeleteQueue({ tagId: documentId }));
|
|
5642
|
+
break;
|
|
5643
|
+
case "update":
|
|
5644
|
+
dispatch(tagsActions.listenerUpdateQueue({ tag: result }));
|
|
5645
|
+
break;
|
|
5646
|
+
}
|
|
5647
|
+
};
|
|
5648
|
+
}
|
|
5649
|
+
function useBrowserInit(client, schemaType) {
|
|
5650
|
+
const dispatch = reactRedux.useDispatch(), tagsByIds = reactRedux.useSelector((state) => state.tags.byIds), tagsFetchCount = reactRedux.useSelector((state) => state.tags.fetchCount), tagNames = getMediaTagNames(schemaType), hasMediaTags = tagNames.length > 0;
|
|
5651
|
+
react.useEffect(() => {
|
|
5652
|
+
hasMediaTags || dispatch(searchActions.facetsClear()), dispatch(tagsActions.fetchRequest());
|
|
5653
|
+
const assetSubscription = client.listen(
|
|
5457
5654
|
groq__default.default`*[_type in ["sanity.fileAsset", "sanity.imageAsset"] && !(_id in path("drafts.**"))]`
|
|
5458
|
-
).subscribe(
|
|
5655
|
+
).subscribe(createAssetHandler(dispatch)), tagSubscription = client.listen(groq__default.default`*[_type == "${TAG_DOCUMENT_NAME}" && !(_id in path("drafts.**"))]`).subscribe(createTagHandler(dispatch));
|
|
5459
5656
|
return () => {
|
|
5460
|
-
|
|
5657
|
+
assetSubscription.unsubscribe(), tagSubscription.unsubscribe();
|
|
5461
5658
|
};
|
|
5462
|
-
}, [client, dispatch]),
|
|
5659
|
+
}, [client, dispatch, hasMediaTags]), react.useEffect(() => {
|
|
5660
|
+
if (!hasMediaTags || tagsFetchCount < 0) return;
|
|
5661
|
+
const tagFacetInput = inputs.tag;
|
|
5662
|
+
if (tagFacetInput.type !== "searchable") return;
|
|
5663
|
+
const resolvedTags = tagNames.map((name) => Object.values(tagsByIds).find((item) => item.tag.name.current === name)).filter((item) => !!item);
|
|
5664
|
+
dispatch(searchActions.facetsClear());
|
|
5665
|
+
for (const tagItem of resolvedTags)
|
|
5666
|
+
dispatch(
|
|
5667
|
+
searchActions.facetsAdd({
|
|
5668
|
+
facet: {
|
|
5669
|
+
...tagFacetInput,
|
|
5670
|
+
operatorType: "references",
|
|
5671
|
+
value: { label: tagItem.tag.name.current, value: tagItem.tag._id }
|
|
5672
|
+
}
|
|
5673
|
+
})
|
|
5674
|
+
);
|
|
5675
|
+
}, [tagsFetchCount, hasMediaTags]);
|
|
5676
|
+
}
|
|
5677
|
+
const BrowserContent = ({
|
|
5678
|
+
onClose,
|
|
5679
|
+
schemaType
|
|
5680
|
+
}) => {
|
|
5681
|
+
const client = useVersionedClient(), [portalElement, setPortalElement] = react.useState(null);
|
|
5682
|
+
return useBrowserInit(client, schemaType), /* @__PURE__ */ jsxRuntime.jsx(ui.PortalProvider, { element: portalElement, children: /* @__PURE__ */ jsxRuntime.jsxs(UploadDropzone, { children: [
|
|
5463
5683
|
/* @__PURE__ */ jsxRuntime.jsx(Dialogs, {}),
|
|
5464
5684
|
/* @__PURE__ */ jsxRuntime.jsx(Notifications, {}),
|
|
5465
5685
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Card, { display: "flex", height: "fill", ref: setPortalElement, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { direction: "column", flex: 1, children: [
|
|
@@ -5486,7 +5706,7 @@ const UploadDropzone = (props) => {
|
|
|
5486
5706
|
selectedAssets: props?.selectedAssets,
|
|
5487
5707
|
children: /* @__PURE__ */ jsxRuntime.jsxs(AssetBrowserDispatchProvider, { onSelect: props?.onSelect, children: [
|
|
5488
5708
|
/* @__PURE__ */ jsxRuntime.jsx(GlobalStyle, {}),
|
|
5489
|
-
/* @__PURE__ */ jsxRuntime.jsx(BrowserContent, { onClose: props?.onClose })
|
|
5709
|
+
/* @__PURE__ */ jsxRuntime.jsx(BrowserContent, { onClose: props?.onClose, schemaType: props?.schemaType })
|
|
5490
5710
|
] })
|
|
5491
5711
|
}
|
|
5492
5712
|
);
|
|
@@ -5513,7 +5733,7 @@ const UploadDropzone = (props) => {
|
|
|
5513
5733
|
width: "100%",
|
|
5514
5734
|
zIndex
|
|
5515
5735
|
},
|
|
5516
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(Browser, { document: currentDocument, ...props })
|
|
5736
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Browser, { document: currentDocument, schemaType: props.schemaType, ...props })
|
|
5517
5737
|
}
|
|
5518
5738
|
) }) });
|
|
5519
5739
|
}, useRootPortalElement = () => {
|
|
@@ -5578,7 +5798,76 @@ const plugin = {
|
|
|
5578
5798
|
types: [mediaTag]
|
|
5579
5799
|
},
|
|
5580
5800
|
tools: (prev) => [...prev, tool]
|
|
5581
|
-
}));
|
|
5801
|
+
})), pendingByAsset = /* @__PURE__ */ new Map();
|
|
5802
|
+
function applyMediaTags(options) {
|
|
5803
|
+
const { assetId } = options, chain = (pendingByAsset.get(assetId) ?? Promise.resolve()).then(
|
|
5804
|
+
() => doApplyMediaTags(options)
|
|
5805
|
+
), cleanup = chain.catch(() => {
|
|
5806
|
+
}).finally(() => {
|
|
5807
|
+
pendingByAsset.get(assetId) === cleanup && pendingByAsset.delete(assetId);
|
|
5808
|
+
});
|
|
5809
|
+
return pendingByAsset.set(assetId, cleanup), chain;
|
|
5810
|
+
}
|
|
5811
|
+
async function doApplyMediaTags({
|
|
5812
|
+
client,
|
|
5813
|
+
assetId,
|
|
5814
|
+
mediaTags,
|
|
5815
|
+
createTagsOnUpload = !0
|
|
5816
|
+
}) {
|
|
5817
|
+
if (!mediaTags || mediaTags.length === 0) return;
|
|
5818
|
+
const validTags = (await Promise.all(
|
|
5819
|
+
mediaTags.map(async (tagName) => await client.fetch(
|
|
5820
|
+
groq__default.default`*[_type == "${TAG_DOCUMENT_NAME}" && name.current == $tagName][0]`,
|
|
5821
|
+
{ tagName }
|
|
5822
|
+
) || (createTagsOnUpload ? await client.create({
|
|
5823
|
+
_type: TAG_DOCUMENT_NAME,
|
|
5824
|
+
name: { _type: "slug", current: tagName }
|
|
5825
|
+
}) : null))
|
|
5826
|
+
)).filter((tag) => tag !== null);
|
|
5827
|
+
if (validTags.length === 0) return;
|
|
5828
|
+
const existing = await client.fetch(
|
|
5829
|
+
groq__default.default`*[_id == $assetId][0]{'tagIds': opt.media.tags[]._ref}`,
|
|
5830
|
+
{ assetId },
|
|
5831
|
+
{ useCdn: !1 }
|
|
5832
|
+
// bypass CDN cache so we see the latest committed tag refs
|
|
5833
|
+
), existingIds = new Set(existing?.tagIds ?? []), tagReferences = validTags.filter((tag) => !existingIds.has(tag._id)).map((tag) => ({
|
|
5834
|
+
_key: nanoid.nanoid(),
|
|
5835
|
+
_ref: tag._id,
|
|
5836
|
+
_type: "reference",
|
|
5837
|
+
_weak: !0
|
|
5838
|
+
}));
|
|
5839
|
+
tagReferences.length !== 0 && await client.patch(assetId).setIfMissing({ opt: {} }).setIfMissing({ "opt.media": {} }).setIfMissing({ "opt.media.tags": [] }).append("opt.media.tags", tagReferences).commit();
|
|
5840
|
+
}
|
|
5841
|
+
function AutoTagInput(props) {
|
|
5842
|
+
const { renderDefault, schemaType, value, mediaTags: mediaTagsProp } = props, toast = ui.useToast(), mediaTags = mediaTagsProp ?? schemaType?.options?.mediaTags, client = useVersionedClient(), { createTagsOnUpload } = useToolOptions(), prevAssetRef = react.useRef(void 0), isInitialMount = react.useRef(!0), currentAssetRef = value?.asset?._ref;
|
|
5843
|
+
return react.useEffect(() => {
|
|
5844
|
+
if (isInitialMount.current) {
|
|
5845
|
+
isInitialMount.current = !1, prevAssetRef.current = currentAssetRef;
|
|
5846
|
+
return;
|
|
5847
|
+
}
|
|
5848
|
+
const previousRef = prevAssetRef.current;
|
|
5849
|
+
prevAssetRef.current = currentAssetRef, !(!mediaTags?.length || !currentAssetRef || currentAssetRef === previousRef) && applyMediaTags({
|
|
5850
|
+
client,
|
|
5851
|
+
assetId: currentAssetRef,
|
|
5852
|
+
mediaTags,
|
|
5853
|
+
createTagsOnUpload
|
|
5854
|
+
}).catch((err) => {
|
|
5855
|
+
console.error("[sanity-plugin-media] Failed to apply auto-tags:", err);
|
|
5856
|
+
const label = mediaTags.length === 1 ? "tag" : "tags";
|
|
5857
|
+
toast.push({ closable: !0, status: "error", title: `Failed to apply the media ${label} ${mediaTags.join(", ")}` });
|
|
5858
|
+
});
|
|
5859
|
+
}, [currentAssetRef, mediaTags, client, createTagsOnUpload]), renderDefault(props);
|
|
5860
|
+
}
|
|
5861
|
+
function mediaField(config) {
|
|
5862
|
+
const { mediaTags, options, components, ...rest } = config;
|
|
5863
|
+
return {
|
|
5864
|
+
...rest,
|
|
5865
|
+
options: { ...options, mediaTags },
|
|
5866
|
+
components: { ...components, input: AutoTagInput }
|
|
5867
|
+
};
|
|
5868
|
+
}
|
|
5869
|
+
exports.AutoTagInput = AutoTagInput;
|
|
5582
5870
|
exports.media = media;
|
|
5583
5871
|
exports.mediaAssetSource = mediaAssetSource;
|
|
5872
|
+
exports.mediaField = mediaField;
|
|
5584
5873
|
//# sourceMappingURL=index.js.map
|