@nascentdigital/funnel-editor 4.6.7 → 5.0.2
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 +15 -3
- package/dist/components.js +18 -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 +43 -3
- 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.d.ts +1 -2
- package/dist/core/components/fields/asset/AssetEditor.js +29 -49
- package/dist/core/components/fields/asset/AssetPicker.js +6 -6
- package/dist/core/components/fields/asset/AssetUploader.d.ts +1 -2
- package/dist/core/components/fields/asset/AssetUploader.js +39 -35
- 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.d.ts +2 -1
- package/dist/core/components/fields/collection/CollectionEditor.js +18 -4
- 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.d.ts +2 -2
- package/dist/core/components/fields/embed/EmbeddedVideoEditor.js +50 -31
- package/dist/core/components/fields/factories/AssetFactory.d.ts +3 -3
- package/dist/core/components/fields/factories/AssetFactory.js +18 -13
- package/dist/core/components/fields/factories/CollectionFactory.d.ts +3 -3
- package/dist/core/components/fields/factories/CollectionFactory.js +20 -13
- package/dist/core/components/fields/factories/EmbeddedVideoFactory.d.ts +3 -3
- package/dist/core/components/fields/factories/EmbeddedVideoFactory.js +17 -8
- package/dist/core/components/fields/factories/FieldValueFactory.d.ts +7 -5
- package/dist/core/components/fields/factories/FieldValueFactory.js +57 -13
- package/dist/core/components/fields/factories/LinkFactory.d.ts +3 -3
- package/dist/core/components/fields/factories/LinkFactory.js +17 -8
- package/dist/core/components/fields/factories/MediaFactory.d.ts +13 -0
- package/dist/core/components/fields/factories/MediaFactory.js +212 -0
- package/dist/core/components/fields/factories/ObjectFactory.d.ts +3 -2
- package/dist/core/components/fields/factories/ObjectFactory.js +16 -2
- package/dist/core/components/fields/factories/TextFactory.d.ts +3 -3
- package/dist/core/components/fields/factories/TextFactory.js +16 -10
- package/dist/core/components/fields/link/LinkEditor.d.ts +2 -2
- package/dist/core/components/fields/link/LinkEditor.js +18 -6
- 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 +36 -0
- package/dist/core/components/fields/media/MediaEditor.js +264 -0
- package/dist/core/components/fields/media/index.d.ts +2 -0
- package/dist/core/components/fields/media/index.js +18 -0
- package/dist/core/components/fields/object/ObjectEditor.d.ts +2 -1
- package/dist/core/components/fields/object/ObjectEditor.js +16 -2
- 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/Popup.d.ts +11 -7
- package/dist/core/components/interaction/Popup.js +8 -6
- package/dist/core/components/interaction/QuickEditor.js +1 -1
- package/dist/core/components/interaction/QuickInput.d.ts +2 -4
- package/dist/core/components/interaction/QuickInput.js +6 -2
- 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/interaction/menu/Menu.d.ts +8 -19
- package/dist/core/components/interaction/menu/Menu.js +26 -60
- package/dist/core/components/interaction/menu/useMenuController.d.ts +4 -2
- package/dist/core/components/interaction/menu/useMenuController.js +4 -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 +15 -9
- 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 -6
- package/dist/core/domain/ICollection.d.ts +72 -0
- package/dist/core/domain/ICollection.js +20 -0
- package/dist/core/domain/IPage.d.ts +16 -1
- 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 -5
- 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/useCollections.js +4 -0
- package/dist/core/hooks/usePageRepository.d.ts +3 -2
- package/dist/core/hooks/usePageRepository.js +4 -4
- package/dist/core/hooks/useSite.js +4 -0
- 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 +22 -21
- 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 +61 -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 +10 -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/core/splash/SplashContainer.d.ts +4 -2
- package/dist/core/splash/SplashContainer.js +3 -3
- 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
|
@@ -17,7 +17,7 @@ const RichTextField_1 = require("./RichTextField");
|
|
|
17
17
|
const TextField_1 = require("./TextField");
|
|
18
18
|
const TimestampField_1 = require("./TimestampField");
|
|
19
19
|
// component
|
|
20
|
-
function FieldEditor({ className, field, variant, size = 'md', standalone = false, autoFocus: autoFocusRaw = false, disabled = false, secured = false, onValidChanged = funnel_core_1.Fn.NoOp }) {
|
|
20
|
+
function FieldEditor({ className, field, variant, size = 'md', standalone = false, autoFocus: autoFocusRaw = false, disabled = false, secured = false, disableDelete = false, onValidChanged = funnel_core_1.Fn.NoOp }) {
|
|
21
21
|
// bind state + hooks
|
|
22
22
|
const wasValidRef = (0, react_1.useRef)(field.valid);
|
|
23
23
|
const dialog = (0, feedback_1.useDialog)();
|
|
@@ -61,37 +61,37 @@ function FieldEditor({ className, field, variant, size = 'md', standalone = fals
|
|
|
61
61
|
if (field instanceof funnel_core_1.Field) {
|
|
62
62
|
switch (schema.type) {
|
|
63
63
|
case 'text':
|
|
64
|
-
return ((0, jsx_runtime_1.jsx)(TextField_1.TextField, { className: className, field: field, size: size, variant: variant, autoFocus: autoFocus, disabled: disabled, secured: secured }));
|
|
64
|
+
return ((0, jsx_runtime_1.jsx)(TextField_1.TextField, { className: className, field: field, size: size, variant: variant, autoFocus: autoFocus, disabled: disabled, secured: secured, disableDelete: disableDelete }));
|
|
65
65
|
case 'richtext':
|
|
66
|
-
return ((0, jsx_runtime_1.jsx)(RichTextField_1.RichTextField, { className: className, field: field, autoFocus: autoFocus, disabled: disabled }));
|
|
66
|
+
return ((0, jsx_runtime_1.jsx)(RichTextField_1.RichTextField, { className: className, field: field, autoFocus: autoFocus, disabled: disabled, disableDelete: disableDelete }));
|
|
67
67
|
case 'enum':
|
|
68
|
-
return ((0, jsx_runtime_1.jsx)(EnumField_1.EnumField, { className: className, field: field, size: size, variant: variant, disabled: disabled }));
|
|
68
|
+
return ((0, jsx_runtime_1.jsx)(EnumField_1.EnumField, { className: className, field: field, size: size, variant: variant, disabled: disabled, disableDelete: disableDelete }));
|
|
69
69
|
case 'boolean':
|
|
70
|
-
return ((0, jsx_runtime_1.jsx)(BooleanField_1.BooleanField, { className: className, field: field, size: size, variant: variant }));
|
|
70
|
+
return ((0, jsx_runtime_1.jsx)(BooleanField_1.BooleanField, { className: className, field: field, size: size, variant: variant, disableDelete: disableDelete }));
|
|
71
71
|
case 'date':
|
|
72
|
-
return ((0, jsx_runtime_1.jsx)(DateField_1.DateField, { className: className, field: field, size: size, variant: variant }));
|
|
72
|
+
return ((0, jsx_runtime_1.jsx)(DateField_1.DateField, { className: className, field: field, size: size, variant: variant, disableDelete: disableDelete }));
|
|
73
73
|
case 'timestamp':
|
|
74
|
-
return ((0, jsx_runtime_1.jsx)(TimestampField_1.TimestampField, { className: className, field: field, size: size, variant: variant, autoFocus: autoFocus, disabled: disabled, secured: secured }));
|
|
74
|
+
return ((0, jsx_runtime_1.jsx)(TimestampField_1.TimestampField, { className: className, field: field, size: size, variant: variant, autoFocus: autoFocus, disabled: disabled, disableDelete: disableDelete, secured: secured }));
|
|
75
75
|
case 'link':
|
|
76
76
|
case 'asset':
|
|
77
77
|
case 'embedded.video':
|
|
78
78
|
case 'collection':
|
|
79
79
|
case 'page':
|
|
80
|
-
return ((0, jsx_runtime_1.jsx)(FieldCard_1.FieldCard, { className: className, field: field, deletable: field.canOptOut, onDelete: onDelete }));
|
|
80
|
+
return ((0, jsx_runtime_1.jsx)(FieldCard_1.FieldCard, { className: className, field: field, deletable: field.canOptOut && !disableDelete, onDelete: onDelete }));
|
|
81
81
|
case 'form':
|
|
82
82
|
return ((0, jsx_runtime_1.jsx)(FormEditor_1.FormEditor, { form: field }));
|
|
83
83
|
case 'dynamic.pages':
|
|
84
|
-
return ((0, jsx_runtime_1.jsx)(DynamicPagesEditor_1.DynamicPagesEditor, { dynamicPages: field }));
|
|
84
|
+
return ((0, jsx_runtime_1.jsx)(DynamicPagesEditor_1.DynamicPagesEditor, { dynamicPages: field, disableDelete: disableDelete }));
|
|
85
85
|
default:
|
|
86
86
|
return ((0, jsx_runtime_1.jsxs)("b", { className: className, children: ["No support for: ", schema.type, "!"] }));
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
// or list
|
|
90
90
|
else if (field instanceof funnel_core_1.FieldList) {
|
|
91
|
-
return ((0, jsx_runtime_1.jsx)(ListEditor_1.ListEditor, { className: className, list: field }));
|
|
91
|
+
return ((0, jsx_runtime_1.jsx)(ListEditor_1.ListEditor, { className: className, list: field, disableDelete: disableDelete }));
|
|
92
92
|
}
|
|
93
93
|
// or object
|
|
94
94
|
else {
|
|
95
|
-
return ((0, jsx_runtime_1.jsx)(FieldCard_1.FieldCard, { className: className, field: field, deletable: field.canOptOut, onDelete: onDelete }));
|
|
95
|
+
return ((0, jsx_runtime_1.jsx)(FieldCard_1.FieldCard, { className: className, field: field, deletable: field.canOptOut && !disableDelete, onDelete: onDelete }));
|
|
96
96
|
}
|
|
97
97
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Callback, Field } from '@nascentdigital/funnel-core';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
import { FieldSize } from './FieldSize';
|
|
4
|
-
export declare function FieldLayout({ field, className, label: rawLabel, variant, size, onActiveChanged, children }: FieldLayout.Props): import("react/jsx-runtime").JSX.Element;
|
|
4
|
+
export declare function FieldLayout({ field, className, label: rawLabel, variant, size, disableDelete, onActiveChanged, children }: FieldLayout.Props): import("react/jsx-runtime").JSX.Element;
|
|
5
5
|
export declare namespace FieldLayout {
|
|
6
6
|
type Variant = 'default' | 'wide' | 'minimal';
|
|
7
7
|
type Props = {
|
|
@@ -12,6 +12,7 @@ export declare namespace FieldLayout {
|
|
|
12
12
|
label?: string;
|
|
13
13
|
secured?: boolean;
|
|
14
14
|
disabled?: boolean;
|
|
15
|
+
disableDelete?: boolean;
|
|
15
16
|
locked?: boolean;
|
|
16
17
|
onActiveChanged?: Callback<boolean>;
|
|
17
18
|
children: ReactNode;
|
|
@@ -6,15 +6,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.FieldLayout = FieldLayout;
|
|
7
7
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
8
|
const funnel_core_1 = require("@nascentdigital/funnel-core");
|
|
9
|
+
const classnames_1 = __importDefault(require("classnames"));
|
|
9
10
|
const react_1 = require("react");
|
|
10
11
|
const hooks_1 = require("../../hooks");
|
|
11
12
|
const feedback_1 = require("../feedback");
|
|
12
13
|
const visuals_1 = require("../visuals");
|
|
13
14
|
const FieldErrorController_1 = require("./FieldErrorController");
|
|
14
15
|
const FieldHeader_1 = require("./FieldHeader");
|
|
15
|
-
const classnames_1 = __importDefault(require("classnames"));
|
|
16
16
|
// component
|
|
17
|
-
function FieldLayout({ field, className, label: rawLabel, variant = 'default', size = 'md', onActiveChanged = funnel_core_1.Fn.NoOp, children }) {
|
|
17
|
+
function FieldLayout({ field, className, label: rawLabel, variant = 'default', size = 'md', disableDelete, onActiveChanged = funnel_core_1.Fn.NoOp, children }) {
|
|
18
18
|
var _a;
|
|
19
19
|
// bind props + hook
|
|
20
20
|
const { schema, name = 'Unknown', canOptOut = false } = field !== null && field !== void 0 ? field : {};
|
|
@@ -56,7 +56,7 @@ function FieldLayout({ field, className, label: rawLabel, variant = 'default', s
|
|
|
56
56
|
'flex flex-col gap-l2': variant !== 'wide',
|
|
57
57
|
'grid grid-cols-subgrid items-center': variant === 'wide'
|
|
58
58
|
}), onPointerEnter: onActive, onPointerLeave: onInactive, children: [!minimal &&
|
|
59
|
-
(0, jsx_runtime_1.jsx)(FieldHeader_1.FieldHeader, { fieldId: field === null || field === void 0 ? void 0 : field.id, size: size, label: label, tip: description, active: active || (field === null || field === void 0 ? void 0 : field.editing) === true, onDelete: canOptOut ? onOptOut : undefined }), (0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)({
|
|
59
|
+
(0, jsx_runtime_1.jsx)(FieldHeader_1.FieldHeader, { fieldId: field === null || field === void 0 ? void 0 : field.id, size: size, label: label, tip: description, active: active || (field === null || field === void 0 ? void 0 : field.editing) === true, onDelete: canOptOut && !disableDelete ? onOptOut : undefined }), (0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)({
|
|
60
60
|
'min-w-[200px]': size === 'md',
|
|
61
61
|
'min-w-[180px]': size !== 'sm',
|
|
62
62
|
'min-w-[120px]': size !== 'xs'
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { FieldList } from '@nascentdigital/funnel-core';
|
|
2
|
-
export declare function ListEditor({ className, list }: ListEditor.Props): import("react/jsx-runtime").JSX.Element;
|
|
2
|
+
export declare function ListEditor({ className, list, disableDelete }: ListEditor.Props): import("react/jsx-runtime").JSX.Element;
|
|
3
3
|
export declare namespace ListEditor {
|
|
4
4
|
type Props = {
|
|
5
5
|
className?: string;
|
|
6
6
|
list: FieldList;
|
|
7
|
+
disableDelete?: boolean;
|
|
7
8
|
};
|
|
8
9
|
}
|
|
@@ -14,7 +14,7 @@ const interaction_1 = require("../interaction");
|
|
|
14
14
|
const FieldCard_1 = require("./FieldCard");
|
|
15
15
|
const list_1 = require("./list");
|
|
16
16
|
// component
|
|
17
|
-
function ListEditor({ className, list }) {
|
|
17
|
+
function ListEditor({ className, list, disableDelete }) {
|
|
18
18
|
// bind props + memos
|
|
19
19
|
const { schema, composition, items } = list;
|
|
20
20
|
const { description, max } = schema;
|
|
@@ -68,7 +68,7 @@ function ListEditor({ className, list }) {
|
|
|
68
68
|
?
|
|
69
69
|
(0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)('flex justify-center items-center p-l6 select-none', 'label-md text-ix-disabled-content bg-ix-disabled rounded-md', {
|
|
70
70
|
'min-h-[200px]': composition !== 'simple'
|
|
71
|
-
}), children: schema.required
|
|
71
|
+
}), children: schema.required || disableDelete
|
|
72
72
|
?
|
|
73
73
|
(0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: "No items to display" })
|
|
74
74
|
:
|
|
@@ -109,14 +109,13 @@ function renderControls({ list, dialog, itemIds, multiSelectRef, multiSelect, se
|
|
|
109
109
|
multiSelect.setSelectedIds([]);
|
|
110
110
|
multiSelect.setSelecting(false);
|
|
111
111
|
};
|
|
112
|
-
console.debug('[ListEditor] no list to render', { itemIds, composition: list.composition });
|
|
113
112
|
// handle homogeneous list
|
|
114
113
|
const itemCount = items.length;
|
|
115
114
|
const { selecting = false, selectedIds = [] } = multiSelect !== null && multiSelect !== void 0 ? multiSelect : {};
|
|
116
115
|
const selectedItemCount = selectedIds.length;
|
|
117
116
|
const canAddMore = itemCount < schema.max;
|
|
118
|
-
return ((0, jsx_runtime_1.jsxs)("nav", { className: "w-full flex flex-wrap items-center gap-l5 my-l5", children: [itemTypes.map(([itemSchemaId, itemSchema]) => (0, jsx_runtime_1.jsxs)(list_1.CreateFieldButton, { size: "
|
|
119
|
-
(0, jsx_runtime_1.jsx)(interaction_1.MultiSelectControls, { ref: multiSelectRef, ids: itemIds, actions: (0, jsx_runtime_1.jsx)(interaction_1.Button, { variant: "destructive", size: "
|
|
117
|
+
return ((0, jsx_runtime_1.jsxs)("nav", { className: "w-full flex flex-wrap items-center gap-l5 my-l5", children: [itemTypes.map(([itemSchemaId, itemSchema]) => (0, jsx_runtime_1.jsxs)(list_1.CreateFieldButton, { size: "xs", schema: itemSchema, onCreated: data => onCreateItem(itemSchemaId, data), onEditing: setEditing, disabled: !canAddMore || selecting, children: ["Add ", funnel_core_1.StringUtils.articleFor(itemSchema.name), " ", itemSchema.name] }, itemSchemaId)), (0, jsx_runtime_1.jsx)("span", { className: "flex-1" }), itemIds.length > 0 && list.composition !== 'simple' &&
|
|
118
|
+
(0, jsx_runtime_1.jsx)(interaction_1.MultiSelectControls, { ref: multiSelectRef, ids: itemIds, actions: (0, jsx_runtime_1.jsx)(interaction_1.Button, { variant: "destructive", size: "xs", onClick: onDeleteSelected, disabled: selectedItemCount === 0, children: "Delete" }) })] }));
|
|
120
119
|
}
|
|
121
120
|
function renderItem({ list, item, multiSelect, selecting, selectedIds, onEditing }) {
|
|
122
121
|
var _a;
|
|
@@ -146,7 +145,7 @@ function renderItem({ list, item, multiSelect, selecting, selectedIds, onEditing
|
|
|
146
145
|
// just add
|
|
147
146
|
: [...ids, id]);
|
|
148
147
|
};
|
|
149
|
-
|
|
148
|
+
// render item
|
|
150
149
|
return ((0, jsx_runtime_1.jsxs)("div", { className: "FieldCard relative w-[212px] h-[170px] overflow-hidden", onClick: onToggleSelection, children: [(0, jsx_runtime_1.jsx)("div", { className: "absolute -inset-1 opacity-backdrop", children: content }), (0, jsx_runtime_1.jsx)(feedback_1.SelectionDecorator, { className: "absolute top-l4 right-l4 z-supersurface pointer-events-none", selected: selected })] }, id));
|
|
151
150
|
}
|
|
152
151
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { FieldModel } from '@nascentdigital/funnel-core';
|
|
2
|
-
export declare function OptInField({ className, field }: OptInField.Props): import("react/jsx-runtime").JSX.Element;
|
|
2
|
+
export declare function OptInField({ className, field, disabled }: OptInField.Props): import("react/jsx-runtime").JSX.Element;
|
|
3
3
|
export declare namespace OptInField {
|
|
4
4
|
type Props = {
|
|
5
5
|
className?: string;
|
|
6
6
|
field: FieldModel;
|
|
7
|
+
disabled?: boolean;
|
|
7
8
|
};
|
|
8
9
|
}
|
|
@@ -5,19 +5,59 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.OptInField = OptInField;
|
|
7
7
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
+
const funnel_core_1 = require("@nascentdigital/funnel-core");
|
|
8
9
|
const client_1 = require("@nascentdigital/funnel-ui/client");
|
|
9
10
|
const classnames_1 = __importDefault(require("classnames"));
|
|
11
|
+
const react_1 = require("react");
|
|
12
|
+
const interaction_1 = require("../interaction");
|
|
10
13
|
const visuals_1 = require("../visuals");
|
|
14
|
+
const factories_1 = require("./factories");
|
|
11
15
|
// component
|
|
12
|
-
function OptInField({ className, field }) {
|
|
16
|
+
function OptInField({ className, field, disabled = false }) {
|
|
17
|
+
// bind hooks
|
|
18
|
+
const id = (0, react_1.useId)();
|
|
19
|
+
const [factoryDeferral, setFactoryDeferral] = (0, react_1.useState)(undefined);
|
|
13
20
|
// helpers
|
|
14
21
|
const onOptIn = (e) => {
|
|
15
22
|
// consume event
|
|
16
23
|
e.preventDefault();
|
|
17
24
|
e.stopPropagation();
|
|
25
|
+
// stage add (if opting in)
|
|
26
|
+
if (factories_1.FieldValueFactory.isCompatibleField(field)) {
|
|
27
|
+
const create = async () => {
|
|
28
|
+
// try to create
|
|
29
|
+
try {
|
|
30
|
+
// create deferral
|
|
31
|
+
const deferral = new funnel_core_1.Deferral();
|
|
32
|
+
setFactoryDeferral(deferral);
|
|
33
|
+
// wait for completion
|
|
34
|
+
const result = await deferral.promise;
|
|
35
|
+
// create value on success
|
|
36
|
+
if (result) {
|
|
37
|
+
// opt-in field + bind data
|
|
38
|
+
field.optIn();
|
|
39
|
+
field.value = result;
|
|
40
|
+
// close factory
|
|
41
|
+
setFactoryDeferral(undefined);
|
|
42
|
+
}
|
|
43
|
+
// or cancel
|
|
44
|
+
else {
|
|
45
|
+
setFactoryDeferral(undefined);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// or cancel on failure
|
|
49
|
+
catch (e) {
|
|
50
|
+
setFactoryDeferral(undefined);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
create().catch(console.error);
|
|
54
|
+
}
|
|
18
55
|
// toggle opt-in
|
|
19
|
-
|
|
56
|
+
else {
|
|
57
|
+
field.optIn();
|
|
58
|
+
}
|
|
20
59
|
};
|
|
21
60
|
// render
|
|
22
|
-
return ((0, jsx_runtime_1.jsxs)("button", { className: (0, classnames_1.default)(className, 'flex items-center gap-l2 pl-l1 pr-l2 overflow-hidden select-none appearance-none cursor-pointer interpolate', 'border-2 border-solid border-transparent rounded-full', 'outline outline-offset-1 outline-transparent', 'hover:border-ix-primary', 'focus-visible:border-ix-primary focus-visible:outline-ix-primary', 'active:scale-[.95] active:interpolate-fast'), onClick: onOptIn, onKeyDown: client_1.OnKey.enter(onOptIn), children: [(0, jsx_runtime_1.jsx)(visuals_1.Icon, { className: "text-ix-primary", variant: "CirclePlus", size: "sm" }), (0, jsx_runtime_1.jsxs)("span", { className: "label-sm label-strong text-content-primary", children: ["Add ", field.name] })] }))
|
|
61
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(interaction_1.Popup.AnchorElement, { tag: "div", anchorId: id, children: (0, jsx_runtime_1.jsxs)("button", { className: (0, classnames_1.default)(className, 'flex items-center gap-l2 pl-l1 pr-l2 overflow-hidden select-none appearance-none cursor-pointer interpolate', 'border-2 border-solid border-transparent rounded-full', 'outline outline-offset-1 outline-transparent', 'hover:border-ix-primary', 'focus-visible:border-ix-primary focus-visible:outline-ix-primary', 'active:scale-[.95] active:interpolate-fast'), onClick: onOptIn, onKeyDown: client_1.OnKey.enter(onOptIn), disabled: disabled, children: [(0, jsx_runtime_1.jsx)(visuals_1.Icon, { className: "text-ix-primary", variant: "CirclePlus", size: "sm" }), (0, jsx_runtime_1.jsxs)("span", { className: "label-sm label-strong text-content-primary", children: ["Add ", field.name] })] }) }), factories_1.FieldValueFactory.isCompatibleField(field) && factoryDeferral &&
|
|
62
|
+
(0, jsx_runtime_1.jsx)(factories_1.FieldValueFactory, { itemSchema: field.schema, field: field, anchor: id, anchorOffset: 4, placement: "bottom", onCommit: result => factoryDeferral === null || factoryDeferral === void 0 ? void 0 : factoryDeferral.resolve(result), onCancel: () => factoryDeferral === null || factoryDeferral === void 0 ? void 0 : factoryDeferral.resolve(undefined) })] }));
|
|
23
63
|
}
|
|
@@ -178,7 +178,7 @@ function RichTextEditor({ id, variant = 'area', className, placeholder = DEFAULT
|
|
|
178
178
|
'bg-surface2 outline outline-1 outline-border-l1 rounded-md': isFixed,
|
|
179
179
|
'hover:outline-ix-primary/[.35] focus-within:outline-ix-primary hover:focus-within:outline-ix-primary': isFixed,
|
|
180
180
|
'focus-within:ring-2 focus-within:ring-ix-primary/[0.35] focus-within:ring-offset-1': isFixed
|
|
181
|
-
}), children: [(0, jsx_runtime_1.jsx)(LexicalRichTextPlugin_1.RichTextPlugin, { contentEditable: (0, jsx_runtime_1.jsx)(LexicalContentEditable_1.ContentEditable, { className: (0, classnames_1.default)('min-h-full body-sm text-content-primary cursor-text', {
|
|
181
|
+
}), tabIndex: -1, children: [(0, jsx_runtime_1.jsx)(LexicalRichTextPlugin_1.RichTextPlugin, { contentEditable: (0, jsx_runtime_1.jsx)(LexicalContentEditable_1.ContentEditable, { className: (0, classnames_1.default)('min-h-full body-sm text-content-primary cursor-text', {
|
|
182
182
|
'field focus-visible:field-focused text-nowrap overflow-x-scroll scrollbar-hide': isField,
|
|
183
183
|
'h-40 flex items-center px-l5': isField,
|
|
184
184
|
'[&>p]:text-nowrap [&:not(:focus-visible)>p]:ellipsis [&>p]:interpolate': isField,
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { Field, Schema } from '@nascentdigital/funnel-core';
|
|
2
2
|
import { RichTextEditor } from './RichTextEditor';
|
|
3
|
-
export declare function RichTextField({ id, className, field, minimal, autoFocus, disabled }: RichTextField.Props): import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
export declare function RichTextField({ id, className, field, minimal, autoFocus, disabled, disableDelete }: RichTextField.Props): import("react/jsx-runtime").JSX.Element;
|
|
4
4
|
export declare namespace RichTextField {
|
|
5
5
|
type Props = Pick<RichTextEditor.Props, 'id' | 'className' | 'autoFocus' | 'disabled'> & {
|
|
6
6
|
field: Field<Schema.RichTextField>;
|
|
7
7
|
minimal?: boolean;
|
|
8
|
+
disableDelete?: boolean;
|
|
8
9
|
};
|
|
9
10
|
}
|
|
@@ -7,9 +7,9 @@ const hooks_1 = require("../../hooks");
|
|
|
7
7
|
const FieldLayout_1 = require("./FieldLayout");
|
|
8
8
|
const RichTextEditor_1 = require("./RichTextEditor");
|
|
9
9
|
// component
|
|
10
|
-
function RichTextField({ id, className, field, minimal = false, autoFocus = false, disabled = false }) {
|
|
10
|
+
function RichTextField({ id, className, field, minimal = false, autoFocus = false, disabled = false, disableDelete = false }) {
|
|
11
11
|
// bind props + state + hooks
|
|
12
|
-
const { schema,
|
|
12
|
+
const { schema, value: data } = field;
|
|
13
13
|
const { capabilities, semantics } = schema;
|
|
14
14
|
// bind field
|
|
15
15
|
(0, hooks_1.useField)(field);
|
|
@@ -19,8 +19,6 @@ function RichTextField({ id, className, field, minimal = false, autoFocus = fals
|
|
|
19
19
|
// update field
|
|
20
20
|
field.value = funnel_core_1.Schema.RichTextField.Value.toData(change.getData());
|
|
21
21
|
};
|
|
22
|
-
// create editor
|
|
23
|
-
const editor = ((0, jsx_runtime_1.jsx)(RichTextEditor_1.RichTextEditor, { id: id, variant: semantics, placeholder: schema.hint, required: required, disabled: disabled, autoFocus: autoFocus, richText: data === null || data === void 0 ? void 0 : data.value, options: capabilities, onChange: onChange }));
|
|
24
22
|
// or within field
|
|
25
|
-
return ((0, jsx_runtime_1.jsx)(FieldLayout_1.FieldLayout, { className: className, field: field, variant: minimal ? 'minimal' : 'default', children:
|
|
23
|
+
return ((0, jsx_runtime_1.jsx)(FieldLayout_1.FieldLayout, { className: className, field: field, variant: minimal ? 'minimal' : 'default', disableDelete: disableDelete, children: (0, jsx_runtime_1.jsx)(RichTextEditor_1.RichTextEditor, { id: id, variant: semantics, placeholder: schema.hint, required: field.required, disabled: disabled, autoFocus: autoFocus, richText: data === null || data === void 0 ? void 0 : data.value, options: capabilities, onChange: onChange }) }));
|
|
26
24
|
}
|
|
@@ -7,6 +7,7 @@ export declare const TextField: import("react").ForwardRefExoticComponent<Omit<H
|
|
|
7
7
|
variant?: FieldLayout.Variant;
|
|
8
8
|
size?: FieldSize;
|
|
9
9
|
disabled?: boolean;
|
|
10
|
+
disableDelete?: boolean;
|
|
10
11
|
secured?: boolean;
|
|
11
12
|
controls?: ReactNode;
|
|
12
13
|
} & import("react").RefAttributes<TextField.Ref>>;
|
|
@@ -16,6 +17,7 @@ export declare namespace TextField {
|
|
|
16
17
|
variant?: FieldLayout.Variant;
|
|
17
18
|
size?: FieldSize;
|
|
18
19
|
disabled?: boolean;
|
|
20
|
+
disableDelete?: boolean;
|
|
19
21
|
secured?: boolean;
|
|
20
22
|
controls?: ReactNode;
|
|
21
23
|
};
|
|
@@ -28,7 +28,7 @@ const FieldLayout_1 = require("./FieldLayout");
|
|
|
28
28
|
// component
|
|
29
29
|
exports.TextField = (0, react_1.forwardRef)(function TextField(_a, ref) {
|
|
30
30
|
var _b, _c;
|
|
31
|
-
var { id: externalId, className, field, size = 'md', autoFocus = false, onKeyDown = funnel_core_1.Fn.NoOp, disabled = false, secured = false, variant, controls } = _a, props = __rest(_a, ["id", "className", "field", "size", "autoFocus", "onKeyDown", "disabled", "secured", "variant", "controls"]);
|
|
31
|
+
var { id: externalId, className, field, size = 'md', autoFocus = false, onKeyDown = funnel_core_1.Fn.NoOp, disabled = false, disableDelete = false, secured = false, variant, controls } = _a, props = __rest(_a, ["id", "className", "field", "size", "autoFocus", "onKeyDown", "disabled", "disableDelete", "secured", "variant", "controls"]);
|
|
32
32
|
// bind props + state + hooks
|
|
33
33
|
const { schema } = field;
|
|
34
34
|
const isPassword = schema.semantics === 'password' || schema.semantics === 'password-input';
|
|
@@ -106,7 +106,7 @@ exports.TextField = (0, react_1.forwardRef)(function TextField(_a, ref) {
|
|
|
106
106
|
// render
|
|
107
107
|
return ((0, jsx_runtime_1.jsx)(FieldLayout_1.FieldLayout, { className: (0, classnames_1.default)(className, {
|
|
108
108
|
'w-full': variant !== 'wide'
|
|
109
|
-
}), field: field, size: size, disabled: disabled, secured: secured, variant: variant, children: (0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)('w-full flex items-center gap-l5'), children: [(0, jsx_runtime_1.jsxs)("div", { className: inputClassNames, children: [mask
|
|
109
|
+
}), field: field, size: size, disabled: disabled, disableDelete: disableDelete, secured: secured, variant: variant, children: (0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)('w-full flex items-center gap-l5'), children: [(0, jsx_runtime_1.jsxs)("div", { className: inputClassNames, children: [mask
|
|
110
110
|
?
|
|
111
111
|
(0, jsx_runtime_1.jsx)(client_1.MaskedInput, Object.assign({ ref: maskRef, id: id, className: "flex-1", name: `field-${field.id}`, placeholder: schema.hint, autoComplete: autoComplete, mask: mask, initialValue: (_b = funnel_core_1.Schema.TextField.Value.fromData(field.value)) !== null && _b !== void 0 ? _b : '', onValueChanged: value => field.value = funnel_core_1.Schema.TextField.Value.toData(value), onFocus: () => field.editing = true, onBlur: () => field.editing = false, onKeyDown: onKeyDown, disabled: disabled || locked }, props, (schema.semantics === 'password'
|
|
112
112
|
?
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Field, Schema } from '@nascentdigital/funnel-core';
|
|
2
2
|
import { FieldLayout } from './FieldLayout';
|
|
3
3
|
import { FieldSize } from './FieldSize';
|
|
4
|
-
export declare function TimestampField({ className, field, variant, size, disabled, secured }: TimestampField.Props): import("react/jsx-runtime").JSX.Element;
|
|
4
|
+
export declare function TimestampField({ className, field, variant, size, disabled, disableDelete, secured }: TimestampField.Props): import("react/jsx-runtime").JSX.Element;
|
|
5
5
|
export declare namespace TimestampField {
|
|
6
6
|
type Props = {
|
|
7
7
|
className?: string;
|
|
@@ -10,6 +10,7 @@ export declare namespace TimestampField {
|
|
|
10
10
|
size?: FieldSize;
|
|
11
11
|
autoFocus?: boolean;
|
|
12
12
|
disabled?: boolean;
|
|
13
|
+
disableDelete?: boolean;
|
|
13
14
|
secured?: boolean;
|
|
14
15
|
};
|
|
15
16
|
}
|
|
@@ -11,9 +11,9 @@ const hooks_1 = require("../../hooks");
|
|
|
11
11
|
const interaction_1 = require("../interaction");
|
|
12
12
|
const FieldLayout_1 = require("./FieldLayout");
|
|
13
13
|
// component
|
|
14
|
-
function TimestampField({ className, field, variant, size = 'md', disabled = false, secured = false }) {
|
|
14
|
+
function TimestampField({ className, field, variant, size = 'md', disabled = false, disableDelete = false, secured = false }) {
|
|
15
15
|
// bind state + hooks
|
|
16
|
-
const { id, name, value: data, schema
|
|
16
|
+
const { id, name, value: data, schema } = field;
|
|
17
17
|
const { hint, minTime, maxTime, defaultHour } = schema;
|
|
18
18
|
const sandboxed = field.sandboxed;
|
|
19
19
|
const locked = secured && !sandboxed;
|
|
@@ -36,7 +36,7 @@ function TimestampField({ className, field, variant, size = 'md', disabled = fal
|
|
|
36
36
|
field.rollback();
|
|
37
37
|
};
|
|
38
38
|
// render
|
|
39
|
-
return ((0, jsx_runtime_1.jsx)(FieldLayout_1.FieldLayout, { className: (0, classnames_1.default)(className, 'TextField-root'), field: field, variant: variant, size: size, disabled: disabled, secured: secured, children: (0, jsx_runtime_1.jsxs)("div", { className: "FieldLayout-inputWrap TextField-inputWrap", children: [(0, jsx_runtime_1.jsx)(interaction_1.DateTimePicker, { className: "FieldLayout-input TextField-input", minTime: funnel_core_1.Timestamp.coerceToDate(minTime), maxTime: funnel_core_1.Timestamp.coerceToDate(maxTime), defaultHour: defaultHour, placeholder: hint !== null && hint !== void 0 ? hint : 'Please select a date', date: date, onChange: onDateChanged, disabled: disabled || locked }), !required &&
|
|
39
|
+
return ((0, jsx_runtime_1.jsx)(FieldLayout_1.FieldLayout, { className: (0, classnames_1.default)(className, 'TextField-root'), field: field, variant: variant, size: size, disabled: disabled, disableDelete: disableDelete, secured: secured, children: (0, jsx_runtime_1.jsxs)("div", { className: "FieldLayout-inputWrap TextField-inputWrap", children: [(0, jsx_runtime_1.jsx)(interaction_1.DateTimePicker, { className: "FieldLayout-input TextField-input", minTime: funnel_core_1.Timestamp.coerceToDate(minTime), maxTime: funnel_core_1.Timestamp.coerceToDate(maxTime), defaultHour: defaultHour, placeholder: hint !== null && hint !== void 0 ? hint : 'Please select a date', date: date, onChange: onDateChanged, disabled: disabled || locked }), !field.required &&
|
|
40
40
|
(0, jsx_runtime_1.jsx)(interaction_1.Button, { variant: "destructive", size: "sm", disabled: date === undefined || locked, onClick: () => field.value = undefined, children: "Clear" }), secured &&
|
|
41
41
|
(locked
|
|
42
42
|
// unlock
|
|
@@ -6,9 +6,8 @@ export declare namespace AssetEditor {
|
|
|
6
6
|
interface Ref {
|
|
7
7
|
edit(options: Options): Promise<Schema.AssetField.LinkedValue | undefined>;
|
|
8
8
|
}
|
|
9
|
-
type Options = {
|
|
9
|
+
type Options = Popup.Props.Delegated & {
|
|
10
10
|
schema: Schema.AssetField;
|
|
11
11
|
asset: Schema.AssetField.LinkedValue;
|
|
12
|
-
anchor: Popup.Anchor;
|
|
13
12
|
};
|
|
14
13
|
}
|
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
2
13
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
14
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
15
|
};
|
|
@@ -27,21 +38,22 @@ exports.AssetEditor = (0, react_2.forwardRef)(function AssetEditor(_, ref) {
|
|
|
27
38
|
const [result, setResult] = (0, react_2.useState)();
|
|
28
39
|
const [schema, setSchema] = (0, react_2.useState)();
|
|
29
40
|
const [asset, setAsset] = (0, react_2.useState)();
|
|
30
|
-
const [
|
|
41
|
+
const [popupProps, setPopupProps] = (0, react_2.useState)();
|
|
31
42
|
const [errorLevel, setErrorLevel] = (0, react_2.useState)('none');
|
|
32
43
|
const [error, setError] = (0, react_2.useState)();
|
|
33
|
-
const { nameField,
|
|
44
|
+
const { nameField, descriptionField } = (0, useAssetFields_1.useAssetFields)();
|
|
34
45
|
const [shared, setShared] = (0, react_2.useState)(false);
|
|
35
46
|
const editorApi = (0, client_1.useEditorApi)();
|
|
36
47
|
const assetStore = (0, hooks_1.useAssetStore)();
|
|
37
|
-
const { valid, modified } = checkFields({ asset, nameField,
|
|
48
|
+
const { valid, modified } = checkFields({ asset, nameField, descriptionField, shared });
|
|
38
49
|
// export service
|
|
39
50
|
(0, react_2.useImperativeHandle)(ref, () => ({
|
|
40
|
-
edit: async (
|
|
51
|
+
edit: async (_a) => {
|
|
52
|
+
var { schema, asset } = _a, popupProps = __rest(_a, ["schema", "asset"]);
|
|
41
53
|
// reset state
|
|
42
54
|
setSchema(schema);
|
|
43
55
|
setAsset(asset);
|
|
44
|
-
|
|
56
|
+
setPopupProps(popupProps);
|
|
45
57
|
setErrorLevel('none');
|
|
46
58
|
setError(undefined);
|
|
47
59
|
setShared(asset.scope === 'global');
|
|
@@ -62,19 +74,7 @@ exports.AssetEditor = (0, react_2.forwardRef)(function AssetEditor(_, ref) {
|
|
|
62
74
|
// bind fields to asset
|
|
63
75
|
nameField.reset(funnel_core_1.Schema.TextField.Value.toData(asset.name));
|
|
64
76
|
descriptionField.reset(asset.description ? funnel_core_1.Schema.TextField.Value.toData(asset.description) : null);
|
|
65
|
-
|
|
66
|
-
anchorField.reset(funnel_core_1.Schema.EnumField.Value.toData(asset.metadata.crop));
|
|
67
|
-
}
|
|
68
|
-
else if (funnel_core_1.Schema.AssetField.LinkedValue.Video.filter(asset)) {
|
|
69
|
-
anchorField.reset(funnel_core_1.Schema.EnumField.Value.toData(asset.metadata.crop));
|
|
70
|
-
const accessible = asset.metadata.accessible;
|
|
71
|
-
accessibleField.reset(funnel_core_1.Schema.EnumField.Value.toData(accessible === 'system'
|
|
72
|
-
? accessible
|
|
73
|
-
: accessible
|
|
74
|
-
? 'true'
|
|
75
|
-
: 'false'));
|
|
76
|
-
}
|
|
77
|
-
}, [asset, nameField, anchorField, accessibleField, descriptionField]);
|
|
77
|
+
}, [asset, nameField, descriptionField]);
|
|
78
78
|
// helpers
|
|
79
79
|
const onValidate = () => {
|
|
80
80
|
// update error level
|
|
@@ -92,8 +92,7 @@ exports.AssetEditor = (0, react_2.forwardRef)(function AssetEditor(_, ref) {
|
|
|
92
92
|
// handle update
|
|
93
93
|
try {
|
|
94
94
|
// create meta
|
|
95
|
-
const metadata = await getAssetMetadata({ asset
|
|
96
|
-
console.debug('[AssetEditor/onUpdate] updating asset', { asset, metadata });
|
|
95
|
+
const metadata = await getAssetMetadata({ asset });
|
|
97
96
|
// upload new file
|
|
98
97
|
const updatedAsset = await editorApi.updateAsset({
|
|
99
98
|
id: asset.id,
|
|
@@ -111,7 +110,6 @@ exports.AssetEditor = (0, react_2.forwardRef)(function AssetEditor(_, ref) {
|
|
|
111
110
|
assetStore.addAsset(updatedAsset);
|
|
112
111
|
// complete
|
|
113
112
|
setResult(updatedAsset.value);
|
|
114
|
-
console.debug('[AssetEditor/upload] completed upload');
|
|
115
113
|
}
|
|
116
114
|
// handle errors
|
|
117
115
|
catch (e) {
|
|
@@ -132,30 +130,26 @@ exports.AssetEditor = (0, react_2.forwardRef)(function AssetEditor(_, ref) {
|
|
|
132
130
|
deferral.resolve(result !== null && result !== void 0 ? result : undefined);
|
|
133
131
|
};
|
|
134
132
|
// skip if we don't have any params
|
|
135
|
-
if (!deferral || !schema || !
|
|
133
|
+
if (!deferral || !schema || !popupProps) {
|
|
136
134
|
return null;
|
|
137
135
|
}
|
|
138
136
|
// render
|
|
139
|
-
return ((0, jsx_runtime_1.jsxs)(interaction_1.MiniEditor, { className: "flex flex-col gap-l8", title: "Edit Asset", open: result === undefined,
|
|
140
|
-
(0, jsx_runtime_1.jsx)(feedback_1.Note, { variant: "tip", children: schema.description }), (0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)('relative h-[210px] overflow-hidden', 'border border-solid border-border-l2 rounded-md'), children: [(0, jsx_runtime_1.jsx)(AssetPreview_1.AssetPreview, { asset: asset }), (0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)('absolute inset-x-0 bottom-l5 z-overlay pointer-events-none', 'flex flex-col justify-center items-center px-l6'), children: (0, jsx_runtime_1.jsx)(AssetSpecs_1.AssetSpecs, { asset: asset }) })] }), (0, jsx_runtime_1.jsx)(react_1.AnimatePresence, { children: (0, jsx_runtime_1.jsx)(FieldErrorController_1.FieldErrorController, { errorLevel: errorLevel, children: renderFields({ asset, nameField,
|
|
137
|
+
return ((0, jsx_runtime_1.jsxs)(interaction_1.MiniEditor, Object.assign({ className: "flex flex-col gap-l8", title: "Edit Asset", open: result === undefined, canSave: onValidate, disableSave: !valid || !modified, renderSaveLabel: state => state === 'saving' ? 'Updating...' : 'Update', onSave: onUpdate, onClose: onCancel, onClosed: onPickerClosed }, popupProps, { children: [(0, jsx_runtime_1.jsx)(feedback_1.ErrorMessage, { error: error }), schema.description && !error &&
|
|
138
|
+
(0, jsx_runtime_1.jsx)(feedback_1.Note, { variant: "tip", children: schema.description }), (0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)('relative h-[210px] overflow-hidden', 'border border-solid border-border-l2 rounded-md'), children: [(0, jsx_runtime_1.jsx)(AssetPreview_1.AssetPreview, { asset: asset }), (0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)('absolute inset-x-0 bottom-l5 z-overlay pointer-events-none', 'flex flex-col justify-center items-center px-l6'), children: (0, jsx_runtime_1.jsx)(AssetSpecs_1.AssetSpecs, { asset: asset }) })] }), (0, jsx_runtime_1.jsx)(react_1.AnimatePresence, { children: (0, jsx_runtime_1.jsx)(FieldErrorController_1.FieldErrorController, { errorLevel: errorLevel, children: renderFields({ asset, nameField, descriptionField, shared, setShared }) }) })] })));
|
|
141
139
|
});
|
|
142
|
-
async function getAssetMetadata({ asset
|
|
143
|
-
var _a;
|
|
140
|
+
async function getAssetMetadata({ asset }) {
|
|
144
141
|
const { type, metadata } = asset;
|
|
145
142
|
switch (funnel_core_1.FileType.coerce(type)) {
|
|
146
143
|
case 'image':
|
|
147
|
-
return Object.assign(Object.assign({}, metadata), { crop:
|
|
144
|
+
return Object.assign(Object.assign({}, metadata), { crop: 'center' });
|
|
148
145
|
case 'video': {
|
|
149
|
-
|
|
150
|
-
return Object.assign(Object.assign({}, metadata), { crop: funnel_core_1.Schema.EnumField.Value.fromData(anchorField.value), accessible: accessible === 'system'
|
|
151
|
-
? 'system'
|
|
152
|
-
: accessible === 'true' });
|
|
146
|
+
return Object.assign(Object.assign({}, metadata), { crop: 'center', accessible: 'system' });
|
|
153
147
|
}
|
|
154
148
|
default:
|
|
155
149
|
return metadata;
|
|
156
150
|
}
|
|
157
151
|
}
|
|
158
|
-
function checkFields({ asset, nameField,
|
|
152
|
+
function checkFields({ asset, nameField, descriptionField, shared }) {
|
|
159
153
|
// skip if there's no asset
|
|
160
154
|
if (!asset) {
|
|
161
155
|
return { valid: false, modified: false };
|
|
@@ -165,26 +159,19 @@ function checkFields({ asset, nameField, anchorField, accessibleField, descripti
|
|
|
165
159
|
const isVisual = fieldType === 'image' || fieldType === 'icon' || fieldType === 'video';
|
|
166
160
|
let valid = nameField.valid;
|
|
167
161
|
if (valid && isVisual) {
|
|
168
|
-
valid =
|
|
169
|
-
(!descriptionField.exists || descriptionField.valid);
|
|
170
|
-
console.debug('[checkFields]', descriptionField);
|
|
162
|
+
valid = !descriptionField.exists || descriptionField.valid;
|
|
171
163
|
}
|
|
172
164
|
// check if modified
|
|
173
|
-
|
|
165
|
+
const modified = (asset.scope === 'global') !== shared
|
|
174
166
|
|| nameField.modified
|
|
175
167
|
|| descriptionField.modified;
|
|
176
|
-
if (!modified && isVisual) {
|
|
177
|
-
modified = anchorField.modified
|
|
178
|
-
|| (fieldType === 'video' && accessibleField.modified);
|
|
179
|
-
}
|
|
180
|
-
console.debug('[checkFields]', { valid, modified });
|
|
181
168
|
// return validity
|
|
182
169
|
return {
|
|
183
170
|
valid,
|
|
184
171
|
modified
|
|
185
172
|
};
|
|
186
173
|
}
|
|
187
|
-
function renderFields({ asset, nameField,
|
|
174
|
+
function renderFields({ asset, nameField, descriptionField, shared, setShared }) {
|
|
188
175
|
// skip if there's no asset
|
|
189
176
|
if (!asset) {
|
|
190
177
|
return null;
|
|
@@ -197,13 +184,6 @@ function renderFields({ asset, nameField, anchorField, descriptionField, accessi
|
|
|
197
184
|
const fieldType = funnel_core_1.FileType.coerce(asset.type);
|
|
198
185
|
const isVisual = fieldType === 'image' || fieldType === 'icon' || fieldType === 'video';
|
|
199
186
|
if (isVisual) {
|
|
200
|
-
// add anchor
|
|
201
|
-
fields.push((0, jsx_runtime_1.jsx)(FieldEditor_1.FieldEditor, { field: anchorField }, "anchor"));
|
|
202
|
-
// add accessible flag (for videos)
|
|
203
|
-
if (fieldType === 'video') {
|
|
204
|
-
fields.push((0, jsx_runtime_1.jsx)(FieldEditor_1.FieldEditor, { field: accessibleField }, "accessible"));
|
|
205
|
-
}
|
|
206
|
-
// get description
|
|
207
187
|
fields.push(descriptionField.exists
|
|
208
188
|
? (0, jsx_runtime_1.jsx)(FieldEditor_1.FieldEditor, { field: descriptionField }, "desc")
|
|
209
189
|
: (0, jsx_runtime_1.jsx)(OptInField_1.OptInField, { field: descriptionField }, "desc.option"));
|
|
@@ -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");
|
|
@@ -26,7 +25,7 @@ exports.AssetPicker = (0, react_1.forwardRef)(function AssetPicker(_, ref) {
|
|
|
26
25
|
const [tagFilters, setTagFilters] = (0, react_1.useState)([]);
|
|
27
26
|
const [globalFilter, setGlobalFilter] = (0, react_1.useState)(true);
|
|
28
27
|
const [error, setError] = (0, react_1.useState)();
|
|
29
|
-
const
|
|
28
|
+
const assetRepo = (0, hooks_1.useAssetRepository)();
|
|
30
29
|
const assetStore = (0, hooks_1.useAssetStore)();
|
|
31
30
|
const fileTypes = (0, react_1.useMemo)(() => getFileTypeOptions(schema), [schema]);
|
|
32
31
|
const tags = (0, react_1.useMemo)(() => getTagOptions(schema, assets), [schema, assets]);
|
|
@@ -57,8 +56,9 @@ exports.AssetPicker = (0, react_1.forwardRef)(function AssetPicker(_, ref) {
|
|
|
57
56
|
const scope = assetStore.getSearchScope();
|
|
58
57
|
console.debug('[AssetPicker] fetching files for', { fileTypes, tag: schema.tags, scope });
|
|
59
58
|
// fetch files
|
|
60
|
-
|
|
61
|
-
.
|
|
59
|
+
assetRepo
|
|
60
|
+
.search({
|
|
61
|
+
brand: funnel_core_1.AppConfig.brand(),
|
|
62
62
|
fileType: fileTypes,
|
|
63
63
|
scope: assetStore.getSearchScope(),
|
|
64
64
|
tags: schema.tags.map(funnel_core_1.Schema.Tag.toData),
|
|
@@ -70,7 +70,7 @@ exports.AssetPicker = (0, react_1.forwardRef)(function AssetPicker(_, ref) {
|
|
|
70
70
|
.catch(e => {
|
|
71
71
|
setError(feedback_1.ErrorMessage.coerce(e));
|
|
72
72
|
});
|
|
73
|
-
}, [
|
|
73
|
+
}, [assetRepo, assetStore, schema, fileTypes]);
|
|
74
74
|
// helpers
|
|
75
75
|
const onPick = (asset) => {
|
|
76
76
|
// store asset (if not switching to uploader)
|
|
@@ -99,7 +99,7 @@ exports.AssetPicker = (0, react_1.forwardRef)(function AssetPicker(_, ref) {
|
|
|
99
99
|
: filters.filter(filter => filter !== fileType)), onToggleAll: () => setFileTypeFilters([]), renderLabel: filter => funnel_core_1.StringUtils.capitalize(filter) }), tags.length > 1 &&
|
|
100
100
|
(0, jsx_runtime_1.jsx)(interaction_1.ChipFilters, { title: "Tags", multiselect: true, options: tags, selectedOptions: tagFilters, onToggle: (tag, selected) => setTagFilters(tags => selected
|
|
101
101
|
? [...tags, tag]
|
|
102
|
-
: tags.filter(t => t !== tag)), onToggleAll: () => setTagFilters([]), renderLabel: tag => VisualTag.getName(tag) }), (0, jsx_runtime_1.jsx)("div", { className: "flex-1" }), (0, jsx_runtime_1.jsx)(interaction_1.Checkbox, { className: "shrink-0", checked: globalFilter, onChange: setGlobalFilter, children: "Include Library Items" })] }), (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({ schema, error, assets, fileTypeFilters, tagFilters, onPick }) }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between items-center p-l8 border-t border-solid border-border-l1", children: [(0, jsx_runtime_1.jsx)(interaction_1.Button, { variant: "primary", size: "sm", iconLeft: "Upload", disabled: assets === undefined, onClick: () => onPick('upload'), children: "Upload new asset" }), (0, jsx_runtime_1.jsx)(interaction_1.Button, { variant: "secondary", size: "sm", onClick: onCancel, children: "Cancel" })] })] })] }));
|
|
102
|
+
: tags.filter(t => t !== tag)), onToggleAll: () => setTagFilters([]), renderLabel: tag => VisualTag.getName(tag) }), (0, jsx_runtime_1.jsx)("div", { className: "flex-1" }), (0, jsx_runtime_1.jsx)(interaction_1.Checkbox, { className: "shrink-0", checked: globalFilter, onChange: setGlobalFilter, children: "Include Library Items" })] }), (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({ schema, error, assets, fileTypeFilters, tagFilters, onPick }) }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between items-center p-l8 border-t border-solid border-border-l1", children: [(0, jsx_runtime_1.jsx)(interaction_1.Button, { variant: "primary", size: "sm", iconLeft: "Upload", disabled: assets === undefined, onClick: () => onPick('upload'), children: "Upload new asset" }), (0, jsx_runtime_1.jsx)(interaction_1.Button, { variant: "secondary", size: "sm", onClick: onCancel, children: "Cancel" })] })] })] }));
|
|
103
103
|
});
|
|
104
104
|
function getFileTypeOptions(schema) {
|
|
105
105
|
// skip if there's no schema
|
|
@@ -6,9 +6,8 @@ export declare namespace AssetUploader {
|
|
|
6
6
|
interface Ref {
|
|
7
7
|
upload(options: Options): Promise<Result>;
|
|
8
8
|
}
|
|
9
|
-
type Options = {
|
|
9
|
+
type Options = Popup.Props.Delegated & {
|
|
10
10
|
schema: Schema.AssetField;
|
|
11
|
-
anchor: Popup.Anchor;
|
|
12
11
|
};
|
|
13
12
|
type Result = Schema.Field.LinkedData<Schema.AssetField> | 'pick' | undefined;
|
|
14
13
|
}
|