@nascentdigital/funnel-editor 4.6.7 → 5.0.1
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/dist/EditorApp.js +1 -1
- package/dist/EditorRoutes.js +7 -5
- package/dist/changesets/screens/ChangeSetViewer.js +1 -1
- package/dist/changesets/screens/ChangeSetsExplorer.js +1 -2
- package/dist/collection/hooks/CollectionController.d.ts +5 -16
- package/dist/collection/hooks/CollectionController.js +18 -37
- package/dist/collection/hooks/ICollectionController.d.ts +24 -0
- package/dist/collection/hooks/ICollectionController.js +20 -0
- package/dist/collection/hooks/index.d.ts +1 -0
- package/dist/collection/hooks/index.js +1 -0
- package/dist/collection/hooks/useCollectionController.d.ts +3 -3
- package/dist/collection/screens/CollectionEditor.js +2 -2
- package/dist/components.d.ts +14 -3
- package/dist/components.js +17 -3
- package/dist/core/components/feedback/dialog/MinimalDialogLayout.js +1 -1
- package/dist/core/components/fields/BooleanField.d.ts +2 -1
- package/dist/core/components/fields/BooleanField.js +2 -2
- package/dist/core/components/fields/DateField.d.ts +2 -1
- package/dist/core/components/fields/DateField.js +2 -2
- package/dist/core/components/fields/DynamicPagesEditor.d.ts +2 -1
- package/dist/core/components/fields/DynamicPagesEditor.js +1 -1
- package/dist/core/components/fields/EnumField.d.ts +2 -1
- package/dist/core/components/fields/EnumField.js +2 -2
- package/dist/core/components/fields/FieldCard.d.ts +1 -0
- package/dist/core/components/fields/FieldCard.js +8 -1
- package/dist/core/components/fields/FieldEditor.d.ts +2 -1
- package/dist/core/components/fields/FieldEditor.js +11 -11
- package/dist/core/components/fields/FieldLayout.d.ts +2 -1
- package/dist/core/components/fields/FieldLayout.js +3 -3
- package/dist/core/components/fields/ListEditor.d.ts +2 -1
- package/dist/core/components/fields/ListEditor.js +5 -6
- package/dist/core/components/fields/OptInField.d.ts +2 -1
- package/dist/core/components/fields/OptInField.js +2 -2
- package/dist/core/components/fields/RichTextEditor.js +1 -1
- package/dist/core/components/fields/RichTextField.d.ts +2 -1
- package/dist/core/components/fields/RichTextField.js +3 -5
- package/dist/core/components/fields/TextField.d.ts +2 -0
- package/dist/core/components/fields/TextField.js +2 -2
- package/dist/core/components/fields/TimestampField.d.ts +2 -1
- package/dist/core/components/fields/TimestampField.js +3 -3
- package/dist/core/components/fields/asset/AssetEditor.js +12 -44
- package/dist/core/components/fields/asset/AssetPicker.js +6 -6
- package/dist/core/components/fields/asset/AssetUploader.js +23 -31
- package/dist/core/components/fields/asset/preview/VideoPreview.js +16 -11
- package/dist/core/components/fields/asset/useAssetFields.d.ts +2 -17
- package/dist/core/components/fields/asset/useAssetFields.js +0 -21
- package/dist/core/components/fields/collection/CollectionEditor.js +1 -1
- package/dist/core/components/fields/collection/CollectionPicker.d.ts +2 -2
- package/dist/core/components/fields/collection/CollectionPicker.js +3 -4
- package/dist/core/components/fields/dynamicPages/PagePriorityDialog.js +1 -1
- package/dist/core/components/fields/embed/EmbeddedVideoEditor.js +34 -27
- package/dist/core/components/fields/factories/FieldValueFactory.js +11 -4
- package/dist/core/components/fields/factories/MediaFactory.d.ts +13 -0
- package/dist/core/components/fields/factories/MediaFactory.js +256 -0
- package/dist/core/components/fields/list/CreateFieldButton.js +1 -1
- package/dist/core/components/fields/media/MediaCard.d.ts +7 -0
- package/dist/core/components/fields/media/MediaCard.js +92 -0
- package/dist/core/components/fields/media/MediaEditor.d.ts +37 -0
- package/dist/core/components/fields/media/MediaEditor.js +235 -0
- package/dist/core/components/fields/media/MediaPicker.d.ts +15 -0
- package/dist/core/components/fields/media/MediaPicker.js +251 -0
- package/dist/core/components/fields/media/index.d.ts +3 -0
- package/dist/core/components/fields/media/index.js +19 -0
- package/dist/core/components/fields/object/ObjectEditor.js +1 -1
- package/dist/core/components/fields/page/PagePicker.js +1 -1
- package/dist/core/components/interaction/Combobox.js +1 -1
- package/dist/core/components/interaction/MultiSelectControls.js +2 -5
- package/dist/core/components/interaction/QuickEditor.js +1 -1
- package/dist/core/components/interaction/QuickPicker.js +1 -1
- package/dist/core/components/interaction/SideSheet.js +1 -1
- package/dist/core/components/interaction/centersheet/CenterSheet.js +7 -1
- package/dist/core/components/interaction/centersheet/CenterSheetContainer.js +3 -1
- package/dist/core/components/transitions/FadeIn.js +1 -1
- package/dist/core/components/visuals/Icon.d.ts +1 -1
- package/dist/core/components/visuals/Icon.js +3 -0
- package/dist/core/containers/AssetRepositoryContainer.d.ts +2 -0
- package/dist/core/containers/AssetRepositoryContainer.js +18 -0
- package/dist/core/containers/CollectionRepositoryContainer.d.ts +2 -0
- package/dist/core/containers/CollectionRepositoryContainer.js +18 -0
- package/dist/core/containers/PageRepositoryContainer.d.ts +2 -0
- package/dist/core/containers/PageRepositoryContainer.js +18 -0
- package/dist/core/containers/index.d.ts +3 -0
- package/dist/core/containers/index.js +19 -0
- package/dist/core/domain/Block.js +2 -1
- package/dist/core/domain/BlockConfiguration.d.ts +4 -1
- package/dist/core/domain/BlockConfiguration.js +59 -3
- package/dist/core/domain/Collection.d.ts +7 -25
- package/dist/core/domain/Collection.js +2 -16
- package/dist/core/domain/CollectionBrowser.d.ts +3 -2
- package/dist/core/domain/CollectionBrowser.js +3 -3
- package/dist/core/domain/CollectionFieldProxy.d.ts +12 -8
- package/dist/core/domain/CollectionFieldProxy.js +14 -8
- package/dist/core/domain/CollectionGroup.d.ts +0 -5
- package/dist/core/domain/CollectionGroup.js +0 -7
- package/dist/core/domain/CollectionSummary.d.ts +2 -2
- package/dist/core/domain/Collections.d.ts +3 -3
- package/dist/core/domain/Collections.js +4 -4
- package/dist/core/domain/ICollection.d.ts +71 -0
- package/dist/core/domain/ICollection.js +20 -0
- package/dist/core/domain/IPage.d.ts +14 -0
- package/dist/core/domain/Page.js +2 -2
- package/dist/core/domain/Pages.js +4 -6
- package/dist/core/domain/SectionBlock.js +2 -1
- package/dist/core/domain/Site.d.ts +4 -4
- package/dist/core/domain/Site.js +3 -3
- package/dist/core/domain/index.d.ts +1 -1
- package/dist/core/domain/index.js +1 -1
- package/dist/core/hooks/index.d.ts +4 -3
- package/dist/core/hooks/index.js +4 -3
- package/dist/core/hooks/useAssetRepository.d.ts +3 -0
- package/dist/core/hooks/useAssetRepository.js +11 -0
- package/dist/core/hooks/useCollection.d.ts +4 -4
- package/dist/core/hooks/useCollectionRepository.d.ts +3 -2
- package/dist/core/hooks/useCollectionRepository.js +4 -4
- package/dist/core/hooks/usePageRepository.d.ts +3 -2
- package/dist/core/hooks/usePageRepository.js +4 -4
- package/dist/core/hooks/useTempFields.d.ts +2 -3
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.js +1 -0
- package/dist/core/repository/AssetRepository.d.ts +10 -0
- package/dist/core/repository/AssetRepository.js +22 -0
- package/dist/core/repository/CollectionRepository.d.ts +21 -20
- package/dist/core/repository/CollectionRepository.js +23 -161
- package/dist/core/repository/CollectionSerializer.d.ts +4 -1
- package/dist/core/repository/CollectionSerializer.js +3 -3
- package/dist/core/repository/IAssetRepository.d.ts +25 -0
- package/dist/core/repository/ICollectionRepository.d.ts +62 -0
- package/dist/core/repository/ICollectionRepository.js +2 -0
- package/dist/core/repository/IPageRepository.d.ts +40 -0
- package/dist/core/repository/IPageRepository.js +2 -0
- package/dist/core/repository/PageRepository.d.ts +5 -8
- package/dist/core/repository/PageRepository.js +7 -280
- package/dist/core/repository/SerializeCollectionUpdate.d.ts +8 -0
- package/dist/core/repository/SerializeCollectionUpdate.js +168 -0
- package/dist/core/repository/SerializePageUpdate.d.ts +11 -0
- package/dist/core/repository/SerializePageUpdate.js +292 -0
- package/dist/core/repository/index.d.ts +4 -0
- package/dist/core/repository/index.js +4 -0
- package/dist/dashboard/screens/Dashboard.js +1 -1
- package/dist/devtools/screens/Devtools.js +1 -1
- package/dist/explore/components/CreatePageDialog.d.ts +2 -2
- package/dist/explore/screens/CollectionExplorer.js +1 -1
- package/dist/explore/screens/CollectionsExplorer.js +1 -1
- package/dist/explore/screens/PageExplorer.js +1 -1
- package/dist/explore/screens/SiteExplorer.js +1 -1
- package/dist/page/components/BlockEditor.js +1 -1
- package/dist/page/components/SettingsEditor.js +0 -7
- package/dist/page/components/config/BlockConfigButton.js +71 -14
- package/dist/page/screens/PageEditor.js +1 -1
- package/dist/styles/index.css +24 -20
- package/dist/styles/tailwind.js +1 -0
- package/dist/users/screens/UserExplorer.js +1 -1
- package/package.json +2 -2
- package/dist/core/domain/TranslateSchema.d.ts +0 -7
- /package/dist/core/{domain/TranslateSchema.js → repository/IAssetRepository.js} +0 -0
|
@@ -5,7 +5,6 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
5
5
|
const funnel_core_1 = require("@nascentdigital/funnel-core");
|
|
6
6
|
const react_1 = require("motion/react");
|
|
7
7
|
const react_2 = require("react");
|
|
8
|
-
const client_1 = require("../../../client");
|
|
9
8
|
const hooks_1 = require("../../../hooks");
|
|
10
9
|
const feedback_1 = require("../../feedback");
|
|
11
10
|
const interaction_1 = require("../../interaction");
|
|
@@ -21,14 +20,15 @@ exports.AssetUploader = (0, react_2.forwardRef)(function AssetUploader(_, ref) {
|
|
|
21
20
|
// bind props + hooks
|
|
22
21
|
const [deferral, setDeferral] = (0, react_2.useState)(undefined);
|
|
23
22
|
const [result, setResult] = (0, react_2.useState)();
|
|
23
|
+
const [uploading, setUploading] = (0, react_2.useState)(false);
|
|
24
24
|
const [schema, setSchema] = (0, react_2.useState)();
|
|
25
25
|
const [anchor, setAnchor] = (0, react_2.useState)();
|
|
26
26
|
const [errorLevel, setErrorLevel] = (0, react_2.useState)('none');
|
|
27
27
|
const [error, setError] = (0, react_2.useState)();
|
|
28
28
|
const [assetInfo, setAssetInfo] = (0, react_2.useState)();
|
|
29
|
-
const { nameField,
|
|
29
|
+
const { nameField, descriptionField } = (0, useAssetFields_1.useAssetFields)();
|
|
30
30
|
const [shared, setShared] = (0, react_2.useState)(false);
|
|
31
|
-
const
|
|
31
|
+
const assetRepo = (0, hooks_1.useAssetRepository)();
|
|
32
32
|
const assetStore = (0, hooks_1.useAssetStore)();
|
|
33
33
|
const assetOptions = (0, react_2.useMemo)(() => getAssetOptions(schema), [schema]);
|
|
34
34
|
// export service
|
|
@@ -56,9 +56,7 @@ exports.AssetUploader = (0, react_2.forwardRef)(function AssetUploader(_, ref) {
|
|
|
56
56
|
// update fields if there's a file
|
|
57
57
|
if (assetInfo) {
|
|
58
58
|
nameField.reset(funnel_core_1.Schema.TextField.Value.toData(assetInfo.fileName));
|
|
59
|
-
anchorField.reset(funnel_core_1.Schema.EnumField.Value.toData('center'));
|
|
60
59
|
descriptionField.reset(null);
|
|
61
|
-
accessibleField.reset(funnel_core_1.Schema.EnumField.Value.toData('system'));
|
|
62
60
|
}
|
|
63
61
|
};
|
|
64
62
|
const onValidate = () => {
|
|
@@ -69,8 +67,7 @@ exports.AssetUploader = (0, react_2.forwardRef)(function AssetUploader(_, ref) {
|
|
|
69
67
|
// check if level
|
|
70
68
|
let valid = nameField.valid;
|
|
71
69
|
if (valid && assetInfo.isVisual) {
|
|
72
|
-
valid =
|
|
73
|
-
(!descriptionField.exists || descriptionField.valid);
|
|
70
|
+
valid = !descriptionField.exists || descriptionField.valid;
|
|
74
71
|
}
|
|
75
72
|
// update error level
|
|
76
73
|
setErrorLevel('all');
|
|
@@ -86,11 +83,13 @@ exports.AssetUploader = (0, react_2.forwardRef)(function AssetUploader(_, ref) {
|
|
|
86
83
|
}
|
|
87
84
|
// handle upload
|
|
88
85
|
try {
|
|
86
|
+
// start upload
|
|
87
|
+
setUploading(true);
|
|
89
88
|
// create meta
|
|
90
|
-
const metadata = await getAssetMetadata({ assetInfo
|
|
89
|
+
const metadata = await getAssetMetadata({ assetInfo });
|
|
91
90
|
console.debug('[AssetUploader/onUpload] uploading asset', { assetInfo, metadata });
|
|
92
91
|
// upload new file
|
|
93
|
-
const uploadedFile = await
|
|
92
|
+
const uploadedFile = await assetRepo.uploadFile({
|
|
94
93
|
file: assetInfo.file,
|
|
95
94
|
type: assetInfo.mimeType,
|
|
96
95
|
size: assetInfo.size,
|
|
@@ -115,6 +114,10 @@ exports.AssetUploader = (0, react_2.forwardRef)(function AssetUploader(_, ref) {
|
|
|
115
114
|
console.error('[AssetUploader/upload] file upload failure', e);
|
|
116
115
|
setError(feedback_1.ErrorMessage.getGenericError((e instanceof Error) ? e : new funnel_core_1.ServerError()));
|
|
117
116
|
}
|
|
117
|
+
// clear uploading flag
|
|
118
|
+
finally {
|
|
119
|
+
setUploading(false);
|
|
120
|
+
}
|
|
118
121
|
};
|
|
119
122
|
const onCancel = () => {
|
|
120
123
|
// set result (triggers uploader to close)
|
|
@@ -133,8 +136,8 @@ exports.AssetUploader = (0, react_2.forwardRef)(function AssetUploader(_, ref) {
|
|
|
133
136
|
return null;
|
|
134
137
|
}
|
|
135
138
|
// render
|
|
136
|
-
return ((0, jsx_runtime_1.jsxs)(interaction_1.MiniEditor, { className: "flex flex-col gap-l8", title: "Upload Asset", open: result === undefined, placement: "right", anchor: anchor, anchorOffset: 4, canSave: onValidate, disableSave: !(assetInfo === null || assetInfo === void 0 ? void 0 : assetInfo.isValid), renderSaveLabel: () => 'Upload', onSave: onUpload, onClose: onCancel, onClosed: onPickerClosed, children: [schema.description &&
|
|
137
|
-
(0, jsx_runtime_1.jsx)(feedback_1.Note, { variant: "tip", children: schema.description }), (0, jsx_runtime_1.jsx)(AssetSelectorPane_1.AssetSelectorPane, { options: assetOptions, onAssetChanged: onAssetChanged }), (0, jsx_runtime_1.jsx)(react_1.AnimatePresence, { children: (0, jsx_runtime_1.jsx)(FieldErrorController_1.FieldErrorController, { errorLevel: errorLevel, children: renderAssetInfo({ assetInfo, nameField,
|
|
139
|
+
return ((0, jsx_runtime_1.jsxs)(interaction_1.MiniEditor, { className: "flex flex-col gap-l8", title: "Upload Asset", open: result === undefined, placement: "right", anchor: anchor, anchorOffset: 4, canSave: onValidate, disableSave: !(assetInfo === null || assetInfo === void 0 ? void 0 : assetInfo.isValid), renderSaveLabel: () => 'Upload', customActions: (0, jsx_runtime_1.jsx)(interaction_1.Button, { variant: "secondary", size: "sm", iconLeft: "ImageDown", disabled: uploading, onClick: () => setResult('pick'), children: "Open Library" }), onSave: onUpload, onClose: onCancel, onClosed: onPickerClosed, children: [schema.description &&
|
|
140
|
+
(0, jsx_runtime_1.jsx)(feedback_1.Note, { variant: "tip", children: schema.description }), (0, jsx_runtime_1.jsx)(AssetSelectorPane_1.AssetSelectorPane, { options: assetOptions, onAssetChanged: onAssetChanged }), (0, jsx_runtime_1.jsx)(react_1.AnimatePresence, { children: (0, jsx_runtime_1.jsx)(FieldErrorController_1.FieldErrorController, { errorLevel: errorLevel, children: renderAssetInfo({ assetInfo, nameField, descriptionField, shared, setShared, uploading }) }) })] }));
|
|
138
141
|
});
|
|
139
142
|
function getAssetOptions(schema) {
|
|
140
143
|
// return empty options if there's no schema
|
|
@@ -158,52 +161,41 @@ function getAssetOptions(schema) {
|
|
|
158
161
|
// normalize options
|
|
159
162
|
return AssetInfo_1.AssetInfo.Options.normalize(options);
|
|
160
163
|
}
|
|
161
|
-
function renderAssetInfo({ assetInfo, nameField,
|
|
164
|
+
function renderAssetInfo({ assetInfo, nameField, descriptionField, shared, setShared, uploading }) {
|
|
162
165
|
// skip if there's no asset info
|
|
163
166
|
if (!assetInfo || !assetInfo.isValid) {
|
|
164
167
|
return null;
|
|
165
168
|
}
|
|
166
169
|
// build fields
|
|
167
170
|
const fields = [
|
|
168
|
-
(0, jsx_runtime_1.jsx)(FieldEditor_1.FieldEditor, { field: nameField }, "name")
|
|
171
|
+
(0, jsx_runtime_1.jsx)(FieldEditor_1.FieldEditor, { field: nameField, disabled: uploading }, "name")
|
|
169
172
|
];
|
|
170
173
|
// add fields related to visuals
|
|
171
174
|
if (assetInfo.isVisual) {
|
|
172
|
-
// add anchor
|
|
173
|
-
fields.push((0, jsx_runtime_1.jsx)(FieldEditor_1.FieldEditor, { field: anchorField }, "anchor"));
|
|
174
|
-
// add accessible flag (for videos)
|
|
175
|
-
if (assetInfo.isVideo) {
|
|
176
|
-
fields.push((0, jsx_runtime_1.jsx)(FieldEditor_1.FieldEditor, { field: accessibleField }, "accessible"));
|
|
177
|
-
}
|
|
178
|
-
// get description
|
|
179
175
|
fields.push(descriptionField.exists
|
|
180
|
-
? (0, jsx_runtime_1.jsx)(FieldEditor_1.FieldEditor, { field: descriptionField }, "desc")
|
|
181
|
-
: (0, jsx_runtime_1.jsx)(OptInField_1.OptInField, { field: descriptionField }, "desc.option"));
|
|
176
|
+
? (0, jsx_runtime_1.jsx)(FieldEditor_1.FieldEditor, { field: descriptionField, disabled: uploading }, "desc")
|
|
177
|
+
: (0, jsx_runtime_1.jsx)(OptInField_1.OptInField, { field: descriptionField, disabled: uploading }, "desc.option"));
|
|
182
178
|
}
|
|
183
179
|
// render editing fields
|
|
184
|
-
return ((0, jsx_runtime_1.jsxs)(transitions_1.FadeIn, { className: "flex flex-col gap-l8", children: [fields, (0, jsx_runtime_1.jsx)(interaction_1.Checkbox, { checked: shared, onChange: setShared, children: "Store in global media library" })] }, "fields"));
|
|
180
|
+
return ((0, jsx_runtime_1.jsxs)(transitions_1.FadeIn, { className: "flex flex-col gap-l8", children: [fields, (0, jsx_runtime_1.jsx)(interaction_1.Checkbox, { checked: shared, onChange: setShared, disabled: uploading, children: "Store in global media library" })] }, "fields"));
|
|
185
181
|
}
|
|
186
|
-
async function getAssetMetadata({ assetInfo
|
|
187
|
-
var _a;
|
|
182
|
+
async function getAssetMetadata({ assetInfo }) {
|
|
188
183
|
const { fileType, dimensions, blurHash } = assetInfo;
|
|
189
184
|
switch (fileType) {
|
|
190
185
|
case 'image':
|
|
191
186
|
return {
|
|
192
|
-
crop:
|
|
187
|
+
crop: 'center',
|
|
193
188
|
dimensions,
|
|
194
189
|
blurHash
|
|
195
190
|
};
|
|
196
191
|
case 'icon':
|
|
197
192
|
return { dimensions };
|
|
198
193
|
case 'video': {
|
|
199
|
-
const accessible = (_a = funnel_core_1.Schema.EnumField.Value.fromData(accessibleField.value)) !== null && _a !== void 0 ? _a : 'system';
|
|
200
194
|
return {
|
|
201
|
-
crop:
|
|
195
|
+
crop: 'center',
|
|
202
196
|
dimensions,
|
|
203
197
|
blurHash,
|
|
204
|
-
accessible:
|
|
205
|
-
? 'system'
|
|
206
|
-
: accessible === 'true'
|
|
198
|
+
accessible: 'system'
|
|
207
199
|
};
|
|
208
200
|
}
|
|
209
201
|
default:
|
|
@@ -11,11 +11,13 @@ const classnames_1 = __importDefault(require("classnames"));
|
|
|
11
11
|
const react_1 = require("react");
|
|
12
12
|
// component
|
|
13
13
|
function VideoPreview({ className, asset, active }) {
|
|
14
|
+
var _a;
|
|
14
15
|
// bind state + refs
|
|
15
16
|
const { url, metadata } = asset;
|
|
16
17
|
const { blurHash } = metadata;
|
|
17
18
|
const [videoRef, video] = (0, client_1.useRefElement)();
|
|
18
19
|
const videoProxy = (0, client_1.useVideoProxy)(video);
|
|
20
|
+
const videoState = (_a = videoProxy === null || videoProxy === void 0 ? void 0 : videoProxy.state) !== null && _a !== void 0 ? _a : 'uninitialized';
|
|
19
21
|
const blurCanvasRef = (0, react_1.useRef)(null);
|
|
20
22
|
// decode blurhash (if any)
|
|
21
23
|
(0, react_1.useEffect)(() => {
|
|
@@ -44,7 +46,10 @@ function VideoPreview({ className, asset, active }) {
|
|
|
44
46
|
});
|
|
45
47
|
// cancel on unmount
|
|
46
48
|
return () => {
|
|
49
|
+
// mark cancelled
|
|
47
50
|
cancelled = true;
|
|
51
|
+
// stop video (if required)
|
|
52
|
+
videoProxy.pause().catch(console.error);
|
|
48
53
|
};
|
|
49
54
|
}, [videoProxy]);
|
|
50
55
|
// start/stop video when active
|
|
@@ -53,22 +58,22 @@ function VideoPreview({ className, asset, active }) {
|
|
|
53
58
|
if (!videoProxy) {
|
|
54
59
|
return;
|
|
55
60
|
}
|
|
56
|
-
//
|
|
57
|
-
if (
|
|
61
|
+
// or ignore if it's not ready (playing or paused)
|
|
62
|
+
else if (videoState !== 'ready' && videoState !== 'playing') {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
// start video if not playing
|
|
66
|
+
const playbackRate = active ? 1 : 0.33;
|
|
67
|
+
if (videoProxy.state !== 'playing') {
|
|
58
68
|
videoProxy
|
|
59
|
-
.play({ playbackRate
|
|
69
|
+
.play({ playbackRate, loop: true })
|
|
60
70
|
.catch(console.error);
|
|
61
71
|
}
|
|
72
|
+
// or adjust speed
|
|
62
73
|
else {
|
|
63
|
-
videoProxy
|
|
64
|
-
.pause()
|
|
65
|
-
.catch(console.error);
|
|
74
|
+
videoProxy.video.playbackRate = playbackRate;
|
|
66
75
|
}
|
|
67
|
-
|
|
68
|
-
return () => {
|
|
69
|
-
videoProxy.pause().catch(console.error);
|
|
70
|
-
};
|
|
71
|
-
}, [videoProxy, active]);
|
|
76
|
+
}, [videoProxy, videoState, active]);
|
|
72
77
|
// render
|
|
73
78
|
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(className, 'relative w-full h-full'), children: [blurHash &&
|
|
74
79
|
(0, jsx_runtime_1.jsx)("canvas", { ref: blurCanvasRef, className: "absolute inset-0 w-full h-full", width: 32, height: 32, draggable: false }), (0, jsx_runtime_1.jsx)("video", { ref: videoRef, className: (0, classnames_1.default)('absolute inset-0 w-full h-full object-cover cursor-pointer interpolate', {
|
|
@@ -1,20 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare function useAssetFields(): import("
|
|
1
|
+
import { Schema } from '@nascentdigital/funnel-core';
|
|
2
|
+
export declare function useAssetFields(): import("@nascentdigital/funnel-core").SchemaToFields<{
|
|
3
3
|
nameField: Schema.TextField;
|
|
4
|
-
anchorField: Schema.EnumField<Schema.EnumField.Options<Position>>;
|
|
5
|
-
accessibleField: Schema.EnumField<{
|
|
6
|
-
system: {
|
|
7
|
-
name: string;
|
|
8
|
-
hint: string;
|
|
9
|
-
};
|
|
10
|
-
true: {
|
|
11
|
-
name: string;
|
|
12
|
-
hint: string;
|
|
13
|
-
};
|
|
14
|
-
false: {
|
|
15
|
-
name: string;
|
|
16
|
-
hint: string;
|
|
17
|
-
};
|
|
18
|
-
}>;
|
|
19
4
|
descriptionField: Schema.TextField;
|
|
20
5
|
}>;
|
|
@@ -9,27 +9,6 @@ function useAssetFields() {
|
|
|
9
9
|
nameField: funnel_core_1.Schema.TextField.slug({
|
|
10
10
|
name: 'Name'
|
|
11
11
|
}),
|
|
12
|
-
anchorField: funnel_core_1.Schema.Field.enumeration({
|
|
13
|
-
name: 'Cropping',
|
|
14
|
-
options: funnel_core_1.Position.values.reduce((options, position) => {
|
|
15
|
-
// bind position
|
|
16
|
-
options[position] = {
|
|
17
|
-
name: funnel_core_1.Position.getName(position)
|
|
18
|
-
};
|
|
19
|
-
// keep reducing
|
|
20
|
-
return options;
|
|
21
|
-
}, {}),
|
|
22
|
-
defaultOption: 'center',
|
|
23
|
-
required: true
|
|
24
|
-
}),
|
|
25
|
-
accessibleField: funnel_core_1.Schema.Field.enumeration({
|
|
26
|
-
name: 'Pause Button',
|
|
27
|
-
options: {
|
|
28
|
-
system: { name: 'Site Default', hint: `Use the default for the site (${funnel_core_1.AppConfig.get().accessible ? 'enabled' : 'disabled'})` },
|
|
29
|
-
true: { name: 'Enable', hint: 'A pause button will be included' },
|
|
30
|
-
false: { name: 'Disable', hint: 'There will be no way to pause the video' }
|
|
31
|
-
}
|
|
32
|
-
}),
|
|
33
12
|
descriptionField: funnel_core_1.Schema.TextField.text({
|
|
34
13
|
name: 'Alt Text',
|
|
35
14
|
hint: 'What\'s happening in this visual?',
|
|
@@ -147,7 +147,7 @@ exports.CollectionEditor = (0, react_1.forwardRef)(function CollectionEditor({ l
|
|
|
147
147
|
? () => setShared(!shared)
|
|
148
148
|
: undefined, children: shared ? 'Shared' : 'Unshared' }), (0, jsx_runtime_1.jsx)(interaction_1.Button, { variant: "primary", size: "sm", disabled: !field || !field.nameField.valid || !field.modified, onClick: onSave, children: !initialValue ? 'Create' : 'Update' })] }), (0, jsx_runtime_1.jsx)(framer_motion_1.AnimatePresence, { mode: "wait", initial: false, children: field
|
|
149
149
|
?
|
|
150
|
-
(0, jsx_runtime_1.jsxs)(transitions_1.FadeIn, { className: "flex flex-col gap-
|
|
150
|
+
(0, jsx_runtime_1.jsxs)(transitions_1.FadeIn, { className: "flex-1 flex flex-col gap-l10 px-l6 py-l10 overflow-y-scroll scrollbar-thin bg-background", children: [(0, jsx_runtime_1.jsx)(FieldsPanel_1.FieldsPanel, { className: "flex-1", fields: field.allFields, autoFocus: true }), field.tagGroups.length > 0 &&
|
|
151
151
|
(0, jsx_runtime_1.jsx)("div", { className: "px-l7", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-l8 p-l8 bg-surface1 rounded-md", children: [(0, jsx_runtime_1.jsx)("h2", { className: "display-xxs flex-1", children: "Tags" }), (0, jsx_runtime_1.jsx)(TagEditor_1.TagEditor, { className: "bg-surface2 p-l6 rounded-sm", tagged: field })] }) })] }, "fields")
|
|
152
152
|
:
|
|
153
153
|
(0, jsx_runtime_1.jsx)(transitions_1.FadeIn, { className: "w-full h-full flex flex-col justify-center items-center", children: (0, jsx_runtime_1.jsx)(interaction_1.Loader, { size: "lg" }) }, "loader") })] }) }) }));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Language, Schema } from '@nascentdigital/funnel-core';
|
|
2
|
-
import {
|
|
2
|
+
import { ICollection } from '../../../domain';
|
|
3
3
|
export declare const CollectionPicker: import("react").ForwardRefExoticComponent<CollectionPicker.Props & import("react").RefAttributes<CollectionPicker.Ref>>;
|
|
4
4
|
export declare namespace CollectionPicker {
|
|
5
5
|
type Props = {
|
|
@@ -11,5 +11,5 @@ export declare namespace CollectionPicker {
|
|
|
11
11
|
type Options = {
|
|
12
12
|
schema: Schema.CollectionField;
|
|
13
13
|
};
|
|
14
|
-
type Result =
|
|
14
|
+
type Result = ICollection.Ref | undefined;
|
|
15
15
|
}
|
|
@@ -9,7 +9,6 @@ const funnel_core_1 = require("@nascentdigital/funnel-core");
|
|
|
9
9
|
const classnames_1 = __importDefault(require("classnames"));
|
|
10
10
|
const framer_motion_1 = require("framer-motion");
|
|
11
11
|
const react_1 = require("react");
|
|
12
|
-
const client_1 = require("../../../client");
|
|
13
12
|
const hooks_1 = require("../../../hooks");
|
|
14
13
|
const feedback_1 = require("../../feedback");
|
|
15
14
|
const interaction_1 = require("../../interaction");
|
|
@@ -28,7 +27,7 @@ exports.CollectionPicker = (0, react_1.forwardRef)(function CollectionPicker({ l
|
|
|
28
27
|
const [tagTooltip, setTagTooltip] = (0, react_1.useState)();
|
|
29
28
|
const [fetching, setFetching] = (0, react_1.useState)(false);
|
|
30
29
|
const [error, setError] = (0, react_1.useState)();
|
|
31
|
-
const
|
|
30
|
+
const collectionRepo = (0, hooks_1.useCollectionRepository)();
|
|
32
31
|
const siteCollections = (0, hooks_1.useCollections)();
|
|
33
32
|
const collectionStore = (0, hooks_1.useCollectionStore)();
|
|
34
33
|
// export service
|
|
@@ -144,7 +143,7 @@ exports.CollectionPicker = (0, react_1.forwardRef)(function CollectionPicker({ l
|
|
|
144
143
|
setTagTooltip(undefined);
|
|
145
144
|
// fetch ref (or fail)
|
|
146
145
|
const { template, id, name } = collectionRef;
|
|
147
|
-
const collection = await
|
|
146
|
+
const collection = await collectionRepo.get({ id, version: 'draft' });
|
|
148
147
|
if (!collection) {
|
|
149
148
|
setFetching(false);
|
|
150
149
|
setError({
|
|
@@ -173,7 +172,7 @@ exports.CollectionPicker = (0, react_1.forwardRef)(function CollectionPicker({ l
|
|
|
173
172
|
deferral.resolve(result !== null && result !== void 0 ? result : undefined);
|
|
174
173
|
};
|
|
175
174
|
// render
|
|
176
|
-
return ((0, jsx_runtime_1.jsxs)(interaction_1.Picker, { className: "flex", open: deferral && result === undefined, disableDismiss: fetching, onClose: onCancel, onClosed: onPickerClosed, children: [(0, jsx_runtime_1.jsxs)("section", { className: "shrink-0 w-[206px] flex flex-col gap-l8 p-l8 bg-modal-background", children: [(0, jsx_runtime_1.jsx)("h1", { className: "heading-md text-content-primary", children: "Select Collection" }), (0, jsx_runtime_1.jsx)(interaction_1.ChipFilters, { title: "Site Collections", options: collectionGroups, selectedOptions: collectionGroup && [collectionGroup], onToggle: (collectionGroup, selected) => selected && setCollectionGroup(collectionGroup), renderLabel: collectionGroup => collectionGroup.template.name, disabled: fetching })] }), (0, jsx_runtime_1.jsxs)("section", { className: "flex-1 flex flex-col", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex-1 p-l8 overflow-y-scroll", children: (0, jsx_runtime_1.jsx)(framer_motion_1.AnimatePresence, { mode: "wait", initial: false, children: renderPicker({ language, error, collectionGroups, collectionGroup, collections, tagOptions, tagFilters, onPick, setTagTooltip, fetching }) }) }), (0, jsx_runtime_1.jsx)("div", { className: "flex justify-end items-center p-l8 border-t border-solid border-border-l1", children: (0, jsx_runtime_1.jsx)(interaction_1.Button, { variant: "secondary", size: "sm", onClick: onCancel, disabled: fetching, children: "Cancel" }) }), (0, jsx_runtime_1.jsx)(interaction_1.Popup, { className: (0, classnames_1.default)('max-w-[200px] bg-surface2 rounded-md p-l5', 'border border-solid border-border-l1 shadow-tooltip', 'flex flex-wrap items-center gap-l4'), open: !!tagTooltip, anchor: tagTooltip === null || tagTooltip === void 0 ? void 0 : tagTooltip.anchor, anchorOffset: 4, placement: "top", disableOverlay: true, onClose: () => setTagTooltip(undefined), children: tagTooltip === null || tagTooltip === void 0 ? void 0 : tagTooltip.tags.map(tag => (0, jsx_runtime_1.jsx)(feedback_1.Badge, { variant: "outlinedTiny", status: "draft", label: tag.name }, tag.data)) })] })] }));
|
|
175
|
+
return ((0, jsx_runtime_1.jsxs)(interaction_1.Picker, { className: "flex", open: deferral && result === undefined, disableDismiss: fetching, onClose: onCancel, onClosed: onPickerClosed, children: [(0, jsx_runtime_1.jsxs)("section", { className: "shrink-0 w-[206px] flex flex-col gap-l8 p-l8 bg-modal-background", children: [(0, jsx_runtime_1.jsx)("h1", { className: "heading-md text-content-primary", children: "Select Collection" }), (0, jsx_runtime_1.jsx)(interaction_1.ChipFilters, { title: "Site Collections", options: collectionGroups, selectedOptions: collectionGroup && [collectionGroup], onToggle: (collectionGroup, selected) => selected && setCollectionGroup(collectionGroup), renderLabel: collectionGroup => collectionGroup.template.name, disabled: fetching })] }), (0, jsx_runtime_1.jsxs)("section", { className: "flex-1 flex flex-col", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex-1 p-l8 overflow-y-scroll", tabIndex: -1, children: (0, jsx_runtime_1.jsx)(framer_motion_1.AnimatePresence, { mode: "wait", initial: false, children: renderPicker({ language, error, collectionGroups, collectionGroup, collections, tagOptions, tagFilters, onPick, setTagTooltip, fetching }) }) }), (0, jsx_runtime_1.jsx)("div", { className: "flex justify-end items-center p-l8 border-t border-solid border-border-l1", children: (0, jsx_runtime_1.jsx)(interaction_1.Button, { variant: "secondary", size: "sm", onClick: onCancel, disabled: fetching, children: "Cancel" }) }), (0, jsx_runtime_1.jsx)(interaction_1.Popup, { className: (0, classnames_1.default)('max-w-[200px] bg-surface2 rounded-md p-l5', 'border border-solid border-border-l1 shadow-tooltip', 'flex flex-wrap items-center gap-l4'), open: !!tagTooltip, anchor: tagTooltip === null || tagTooltip === void 0 ? void 0 : tagTooltip.anchor, anchorOffset: 4, placement: "top", disableOverlay: true, onClose: () => setTagTooltip(undefined), children: tagTooltip === null || tagTooltip === void 0 ? void 0 : tagTooltip.tags.map(tag => (0, jsx_runtime_1.jsx)(feedback_1.Badge, { variant: "outlinedTiny", status: "draft", label: tag.name }, tag.data)) })] })] }));
|
|
177
176
|
});
|
|
178
177
|
function renderPicker({ language, schema, error, collectionGroups, collectionGroup, collections, tagOptions, tagFilters, onPick, setTagTooltip, fetching }) {
|
|
179
178
|
// show error if we have one
|
|
@@ -50,7 +50,7 @@ exports.PagePriorityDialog = (0, react_1.forwardRef)(function CreatePageDialog({
|
|
|
50
50
|
return;
|
|
51
51
|
}
|
|
52
52
|
// render
|
|
53
|
-
return ((0, jsx_runtime_1.jsxs)(interaction_1.Picker, { open: !!deferral, onClose: onClose, className: "flex", children: [(0, jsx_runtime_1.jsxs)("section", { className: "shrink-0 w-[206px] flex flex-col gap-l8 p-l8 bg-modal-background", children: [(0, jsx_runtime_1.jsx)("h1", { className: "heading-md text-content-primary", children: "Priority Settings" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-l6", children: [(0, jsx_runtime_1.jsx)("h2", { className: "label-sm label-strong text-content-tertiary", children: "Site Pages" }), (0, jsx_runtime_1.jsx)(feedback_1.Badge, { label: currentPage.name })] })] }), (0, jsx_runtime_1.jsxs)("section", { className: "flex-1 flex flex-col", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex-1 p-l8 overflow-y-scroll", children: currentPage.tags.map(group => (0, jsx_runtime_1.jsx)(TagGroup, { page: currentPage, group: group, state: pageTagState }, group.id)) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-end gap-l4 items-center p-l8 border-t border-solid border-border-l1", children: [(0, jsx_runtime_1.jsx)(interaction_1.Button, { variant: "secondary", size: "sm", onClick: onClose, children: "Cancel" }), (0, jsx_runtime_1.jsx)(interaction_1.Button, { variant: "secondary", size: "sm", onClick: onReset, children: "Reset" }), (0, jsx_runtime_1.jsx)(interaction_1.Button, { variant: "primary", size: "sm", onClick: onSave, children: "Save" })] })] })] }));
|
|
53
|
+
return ((0, jsx_runtime_1.jsxs)(interaction_1.Picker, { open: !!deferral, onClose: onClose, className: "flex", children: [(0, jsx_runtime_1.jsxs)("section", { className: "shrink-0 w-[206px] flex flex-col gap-l8 p-l8 bg-modal-background", children: [(0, jsx_runtime_1.jsx)("h1", { className: "heading-md text-content-primary", children: "Priority Settings" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-l6", children: [(0, jsx_runtime_1.jsx)("h2", { className: "label-sm label-strong text-content-tertiary", children: "Site Pages" }), (0, jsx_runtime_1.jsx)(feedback_1.Badge, { label: currentPage.name })] })] }), (0, jsx_runtime_1.jsxs)("section", { className: "flex-1 flex flex-col", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex-1 p-l8 overflow-y-scroll", tabIndex: -1, children: currentPage.tags.map(group => (0, jsx_runtime_1.jsx)(TagGroup, { page: currentPage, group: group, state: pageTagState }, group.id)) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-end gap-l4 items-center p-l8 border-t border-solid border-border-l1", children: [(0, jsx_runtime_1.jsx)(interaction_1.Button, { variant: "secondary", size: "sm", onClick: onClose, children: "Cancel" }), (0, jsx_runtime_1.jsx)(interaction_1.Button, { variant: "secondary", size: "sm", onClick: onReset, children: "Reset" }), (0, jsx_runtime_1.jsx)(interaction_1.Button, { variant: "primary", size: "sm", onClick: onSave, children: "Save" })] })] })] }));
|
|
54
54
|
});
|
|
55
55
|
var PageTagState;
|
|
56
56
|
(function (PageTagState) {
|
|
@@ -14,7 +14,6 @@ const hooks_1 = require("../../../hooks");
|
|
|
14
14
|
const feedback_1 = require("../../feedback");
|
|
15
15
|
const interaction_1 = require("../../interaction");
|
|
16
16
|
const visuals_1 = require("../../visuals");
|
|
17
|
-
const FieldEditor_1 = require("../FieldEditor");
|
|
18
17
|
const FieldErrorController_1 = require("../FieldErrorController");
|
|
19
18
|
const TextField_1 = require("../TextField");
|
|
20
19
|
// component
|
|
@@ -26,19 +25,12 @@ exports.EmbeddedVideoEditor = (0, react_1.forwardRef)(function EmbeddedVideoEdit
|
|
|
26
25
|
const [anchor, setAnchor] = (0, react_1.useState)();
|
|
27
26
|
const [state, setState] = (0, react_1.useState)('initializing');
|
|
28
27
|
const touch = (0, client_1.useTouch)();
|
|
29
|
-
const { uriField
|
|
28
|
+
const { uriField } = (0, hooks_1.useTempFields)({
|
|
30
29
|
uriField: funnel_core_1.Schema.Field.uri({
|
|
31
30
|
name: 'YouTube or Vimeo URL',
|
|
32
31
|
hint: 'Enter video link',
|
|
33
32
|
required: true
|
|
34
33
|
}),
|
|
35
|
-
mutedField: funnel_core_1.Schema.Field.boolean({
|
|
36
|
-
name: 'Muted',
|
|
37
|
-
hint: 'Video starts off on mute',
|
|
38
|
-
semantics: 'toggle',
|
|
39
|
-
required: true,
|
|
40
|
-
defaultValue: true
|
|
41
|
-
})
|
|
42
34
|
});
|
|
43
35
|
const uri = uriField.valid
|
|
44
36
|
? funnel_core_1.Schema.TextField.Value.fromData(uriField.value)
|
|
@@ -49,7 +41,6 @@ exports.EmbeddedVideoEditor = (0, react_1.forwardRef)(function EmbeddedVideoEdit
|
|
|
49
41
|
// export service
|
|
50
42
|
(0, react_1.useImperativeHandle)(ref, () => ({
|
|
51
43
|
edit: async ({ schema, initialValue, anchor }) => {
|
|
52
|
-
var _a;
|
|
53
44
|
// reset state
|
|
54
45
|
setSchema(schema);
|
|
55
46
|
setInitialValue(initialValue);
|
|
@@ -61,14 +52,13 @@ exports.EmbeddedVideoEditor = (0, react_1.forwardRef)(function EmbeddedVideoEdit
|
|
|
61
52
|
uriField.reset(video
|
|
62
53
|
? funnel_core_1.Schema.TextField.Value.toData(funnel_core_1.Schema.EmbeddedVideoField.Value.toUrl(video).href)
|
|
63
54
|
: null);
|
|
64
|
-
mutedField.reset(funnel_core_1.Schema.BooleanField.Value.toData(schema.allowMuting ? (_a = video === null || video === void 0 ? void 0 : video.muted) !== null && _a !== void 0 ? _a : true : true));
|
|
65
55
|
// create deferral
|
|
66
56
|
const deferral = new funnel_core_1.Deferral();
|
|
67
57
|
setDeferral(deferral);
|
|
68
58
|
// wait until deferral is resolved
|
|
69
59
|
return deferral.promise;
|
|
70
60
|
}
|
|
71
|
-
}), [uriField,
|
|
61
|
+
}), [uriField, video$]);
|
|
72
62
|
// sync uri on change
|
|
73
63
|
(0, react_1.useEffect)(() => {
|
|
74
64
|
var _a;
|
|
@@ -100,7 +90,7 @@ exports.EmbeddedVideoEditor = (0, react_1.forwardRef)(function EmbeddedVideoEdit
|
|
|
100
90
|
return;
|
|
101
91
|
}
|
|
102
92
|
// or if there's already a thumb
|
|
103
|
-
else if (video.thumbUrl) {
|
|
93
|
+
else if (video.thumbUrl && video.dimensions.width && video.dimensions.height) {
|
|
104
94
|
setState('valid');
|
|
105
95
|
return;
|
|
106
96
|
}
|
|
@@ -113,18 +103,28 @@ exports.EmbeddedVideoEditor = (0, react_1.forwardRef)(function EmbeddedVideoEdit
|
|
|
113
103
|
return;
|
|
114
104
|
}
|
|
115
105
|
// or fail if we couldn't get a thumbnail (means no video)
|
|
116
|
-
if (!thumbUrl) {
|
|
106
|
+
else if (!thumbUrl) {
|
|
117
107
|
setState('error');
|
|
108
|
+
return;
|
|
118
109
|
}
|
|
119
|
-
//
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
110
|
+
// get video dimensions
|
|
111
|
+
const dimensions = await getVideoThumbnailSize(thumbUrl.href);
|
|
112
|
+
console.debug('[EmbeddedVideoEditor] got video size as ', dimensions);
|
|
113
|
+
// skip if video has changed (debounced)
|
|
114
|
+
if (video$.value !== video) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
// or fail if we couldn't get dimensions (means no thumbnail)
|
|
118
|
+
else if (!dimensions || !dimensions.width || !dimensions.height) {
|
|
119
|
+
setState('error');
|
|
120
|
+
return;
|
|
127
121
|
}
|
|
122
|
+
// update video
|
|
123
|
+
video$.next(Object.assign(Object.assign({}, video), { dimensions, thumbUrl: thumbUrl.href }));
|
|
124
|
+
// update state
|
|
125
|
+
setState('valid');
|
|
126
|
+
// touch (just in case we were already valid)
|
|
127
|
+
touch();
|
|
128
128
|
});
|
|
129
129
|
// unsubscribe on unmount
|
|
130
130
|
return () => subscription.unsubscribe();
|
|
@@ -134,14 +134,12 @@ exports.EmbeddedVideoEditor = (0, react_1.forwardRef)(function EmbeddedVideoEdit
|
|
|
134
134
|
return state === 'valid';
|
|
135
135
|
};
|
|
136
136
|
const onSave = async () => {
|
|
137
|
-
var _a;
|
|
138
137
|
// blow up if missing uri (should never happen)
|
|
139
138
|
if (!video || state !== 'valid') {
|
|
140
139
|
throw new funnel_core_1.IllegalStateError('Missing URI');
|
|
141
140
|
}
|
|
142
141
|
// resolve embed (we're done)
|
|
143
|
-
|
|
144
|
-
deferral === null || deferral === void 0 ? void 0 : deferral.resolve(funnel_core_1.Schema.EmbeddedVideoField.Value.toData(Object.assign(Object.assign({}, video), { muted })));
|
|
142
|
+
deferral === null || deferral === void 0 ? void 0 : deferral.resolve(funnel_core_1.Schema.EmbeddedVideoField.Value.toData(Object.assign({}, video)));
|
|
145
143
|
// refresh
|
|
146
144
|
touch();
|
|
147
145
|
};
|
|
@@ -157,8 +155,7 @@ exports.EmbeddedVideoEditor = (0, react_1.forwardRef)(function EmbeddedVideoEdit
|
|
|
157
155
|
};
|
|
158
156
|
// render
|
|
159
157
|
return ((0, jsx_runtime_1.jsxs)(interaction_1.MiniEditor, { title: `${initialValue ? 'Edit' : 'Add'} ${name}`, open: !!deferral && !deferral.isComplete, placement: "right", anchor: anchor, anchorOffset: 4, canSave: canSave, onSave: onSave, onClose: onCancel, disabled: false, children: [description &&
|
|
160
|
-
(0, jsx_runtime_1.jsx)(feedback_1.Note, { variant: "tip", children: description }), renderPreview({ state, video }), (0, jsx_runtime_1.
|
|
161
|
-
(0, jsx_runtime_1.jsx)(FieldEditor_1.FieldEditor, { field: mutedField })] })] }));
|
|
158
|
+
(0, jsx_runtime_1.jsx)(feedback_1.Note, { variant: "tip", children: description }), renderPreview({ state, video }), (0, jsx_runtime_1.jsx)(FieldErrorController_1.FieldErrorController, { errorLevel: "none", children: (0, jsx_runtime_1.jsx)(TextField_1.TextField, { field: uriField }) })] }));
|
|
162
159
|
});
|
|
163
160
|
async function getVideoThumbnailUrl(video) {
|
|
164
161
|
// skip if there's no video
|
|
@@ -207,6 +204,16 @@ async function getVideoThumbnailUrl(video) {
|
|
|
207
204
|
return null;
|
|
208
205
|
}
|
|
209
206
|
}
|
|
207
|
+
async function getVideoThumbnailSize(url) {
|
|
208
|
+
// get blob
|
|
209
|
+
const response = await fetch(url);
|
|
210
|
+
const blob = await response.blob();
|
|
211
|
+
// get image
|
|
212
|
+
const imageProxy = new funnel_core_1.BlobImageProxy(blob);
|
|
213
|
+
await imageProxy.waitUntilReady();
|
|
214
|
+
// return dimensions
|
|
215
|
+
return imageProxy.intrinsicSize;
|
|
216
|
+
}
|
|
210
217
|
function renderPreview({ state, video }) {
|
|
211
218
|
// show loader if checking
|
|
212
219
|
let content;
|
|
@@ -3,17 +3,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.FieldValueFactory = FieldValueFactory;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const funnel_core_1 = require("@nascentdigital/funnel-core");
|
|
6
|
+
const funnel_ui_1 = require("@nascentdigital/funnel-ui");
|
|
6
7
|
const hooks_1 = require("../../../hooks");
|
|
7
8
|
const AssetFactory_1 = require("./AssetFactory");
|
|
8
9
|
const CollectionFactory_1 = require("./CollectionFactory");
|
|
9
10
|
const EmbeddedVideoFactory_1 = require("./EmbeddedVideoFactory");
|
|
10
11
|
const LinkFactory_1 = require("./LinkFactory");
|
|
12
|
+
const MediaFactory_1 = require("./MediaFactory");
|
|
11
13
|
const ObjectFactory_1 = require("./ObjectFactory");
|
|
12
14
|
const PageFactory_1 = require("./PageFactory");
|
|
13
15
|
const TextFactory_1 = require("./TextFactory");
|
|
14
16
|
// factory
|
|
15
17
|
function FieldValueFactory({ anchor, itemSchema, field, onCommit = funnel_core_1.Fn.NoOp, onCancel = funnel_core_1.Fn.NoOp }) {
|
|
16
|
-
var _a, _b, _c, _d, _e, _f;
|
|
18
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
17
19
|
// bind language
|
|
18
20
|
const brandConfig = funnel_core_1.AppConfig.brandConfig();
|
|
19
21
|
const page = (0, hooks_1.usePossiblePage)();
|
|
@@ -21,11 +23,9 @@ function FieldValueFactory({ anchor, itemSchema, field, onCommit = funnel_core_1
|
|
|
21
23
|
const region = (_a = page === null || page === void 0 ? void 0 : page.region) !== null && _a !== void 0 ? _a : funnel_core_1.RegionsConfig.getDefaultRegion(brandConfig.regionalization);
|
|
22
24
|
const language = (_c = (_b = page === null || page === void 0 ? void 0 : page.language) !== null && _b !== void 0 ? _b : collection === null || collection === void 0 ? void 0 : collection.language) !== null && _c !== void 0 ? _c : funnel_core_1.RegionsConfig.getDefaultLanguage(brandConfig.regionalization);
|
|
23
25
|
const commit = (item) => {
|
|
24
|
-
console.debug(`[FieldValueFactory/commit] creating value for "${itemSchema.name}"`, item);
|
|
25
26
|
onCommit(item);
|
|
26
27
|
};
|
|
27
28
|
const cancel = () => {
|
|
28
|
-
console.debug(`[FieldValueFactory/cancel] cancelling "${itemSchema.name}"`);
|
|
29
29
|
onCancel();
|
|
30
30
|
};
|
|
31
31
|
// handle based on item type
|
|
@@ -42,7 +42,14 @@ function FieldValueFactory({ anchor, itemSchema, field, onCommit = funnel_core_1
|
|
|
42
42
|
case 'page':
|
|
43
43
|
return ((0, jsx_runtime_1.jsx)(PageFactory_1.PageFactory, { schema: itemSchema, region: region, language: language, onCommit: item => commit(item), onCancel: cancel }));
|
|
44
44
|
case 'collection':
|
|
45
|
-
|
|
45
|
+
// custom handling for media
|
|
46
|
+
if (funnel_ui_1.Media.Schema.filter(itemSchema)) {
|
|
47
|
+
return ((0, jsx_runtime_1.jsx)(MediaFactory_1.MediaFactory, { schema: itemSchema, language: language, media: (_f = field === null || field === void 0 ? void 0 : field.value) === null || _f === void 0 ? void 0 : _f.value, anchor: anchor, onCommit: item => commit(funnel_core_1.Schema.CollectionField.Value.toData(item)), onCancel: cancel }));
|
|
48
|
+
}
|
|
49
|
+
// or generic collection
|
|
50
|
+
else {
|
|
51
|
+
return ((0, jsx_runtime_1.jsx)(CollectionFactory_1.CollectionFactory, { schema: itemSchema, language: language, collection: (_g = field === null || field === void 0 ? void 0 : field.value) === null || _g === void 0 ? void 0 : _g.value, anchor: anchor, onCommit: item => commit(item), onCancel: cancel }));
|
|
52
|
+
}
|
|
46
53
|
case 'object':
|
|
47
54
|
return ((0, jsx_runtime_1.jsx)(ObjectFactory_1.ObjectFactory, { schema: itemSchema, field: field, onCommit: item => commit(item), onCancel: cancel }));
|
|
48
55
|
default:
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Callback, Language } from '@nascentdigital/funnel-core';
|
|
2
|
+
import { Media } from '@nascentdigital/funnel-ui';
|
|
3
|
+
export declare function MediaFactory({ schema, language, media: initialValue, anchor, onCommit: onCommitRaw, onCancel: onCancelRaw }: MediaFactory.Props): import("react/jsx-runtime").JSX.Element;
|
|
4
|
+
export declare namespace MediaFactory {
|
|
5
|
+
type Props = {
|
|
6
|
+
schema: Media.Schema;
|
|
7
|
+
language: Language;
|
|
8
|
+
media?: Media.Value;
|
|
9
|
+
anchor: string;
|
|
10
|
+
onCommit: Callback<Media.Value>;
|
|
11
|
+
onCancel: Callback.Void;
|
|
12
|
+
};
|
|
13
|
+
}
|