@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.
Files changed (185) hide show
  1. package/dist/EditorApp.js +1 -1
  2. package/dist/EditorRoutes.js +7 -5
  3. package/dist/changesets/screens/ChangeSetViewer.js +1 -1
  4. package/dist/changesets/screens/ChangeSetsExplorer.js +1 -2
  5. package/dist/collection/hooks/CollectionController.d.ts +5 -16
  6. package/dist/collection/hooks/CollectionController.js +18 -37
  7. package/dist/collection/hooks/ICollectionController.d.ts +24 -0
  8. package/dist/collection/hooks/ICollectionController.js +20 -0
  9. package/dist/collection/hooks/index.d.ts +1 -0
  10. package/dist/collection/hooks/index.js +1 -0
  11. package/dist/collection/hooks/useCollectionController.d.ts +3 -3
  12. package/dist/collection/screens/CollectionEditor.js +2 -2
  13. package/dist/components.d.ts +15 -3
  14. package/dist/components.js +18 -3
  15. package/dist/core/components/feedback/dialog/MinimalDialogLayout.js +1 -1
  16. package/dist/core/components/fields/BooleanField.d.ts +2 -1
  17. package/dist/core/components/fields/BooleanField.js +2 -2
  18. package/dist/core/components/fields/DateField.d.ts +2 -1
  19. package/dist/core/components/fields/DateField.js +2 -2
  20. package/dist/core/components/fields/DynamicPagesEditor.d.ts +2 -1
  21. package/dist/core/components/fields/DynamicPagesEditor.js +1 -1
  22. package/dist/core/components/fields/EnumField.d.ts +2 -1
  23. package/dist/core/components/fields/EnumField.js +2 -2
  24. package/dist/core/components/fields/FieldCard.d.ts +1 -0
  25. package/dist/core/components/fields/FieldCard.js +8 -1
  26. package/dist/core/components/fields/FieldEditor.d.ts +2 -1
  27. package/dist/core/components/fields/FieldEditor.js +11 -11
  28. package/dist/core/components/fields/FieldLayout.d.ts +2 -1
  29. package/dist/core/components/fields/FieldLayout.js +3 -3
  30. package/dist/core/components/fields/ListEditor.d.ts +2 -1
  31. package/dist/core/components/fields/ListEditor.js +5 -6
  32. package/dist/core/components/fields/OptInField.d.ts +2 -1
  33. package/dist/core/components/fields/OptInField.js +43 -3
  34. package/dist/core/components/fields/RichTextEditor.js +1 -1
  35. package/dist/core/components/fields/RichTextField.d.ts +2 -1
  36. package/dist/core/components/fields/RichTextField.js +3 -5
  37. package/dist/core/components/fields/TextField.d.ts +2 -0
  38. package/dist/core/components/fields/TextField.js +2 -2
  39. package/dist/core/components/fields/TimestampField.d.ts +2 -1
  40. package/dist/core/components/fields/TimestampField.js +3 -3
  41. package/dist/core/components/fields/asset/AssetEditor.d.ts +1 -2
  42. package/dist/core/components/fields/asset/AssetEditor.js +29 -49
  43. package/dist/core/components/fields/asset/AssetPicker.js +6 -6
  44. package/dist/core/components/fields/asset/AssetUploader.d.ts +1 -2
  45. package/dist/core/components/fields/asset/AssetUploader.js +39 -35
  46. package/dist/core/components/fields/asset/preview/VideoPreview.js +16 -11
  47. package/dist/core/components/fields/asset/useAssetFields.d.ts +2 -17
  48. package/dist/core/components/fields/asset/useAssetFields.js +0 -21
  49. package/dist/core/components/fields/collection/CollectionEditor.d.ts +2 -1
  50. package/dist/core/components/fields/collection/CollectionEditor.js +18 -4
  51. package/dist/core/components/fields/collection/CollectionPicker.d.ts +2 -2
  52. package/dist/core/components/fields/collection/CollectionPicker.js +3 -4
  53. package/dist/core/components/fields/dynamicPages/PagePriorityDialog.js +1 -1
  54. package/dist/core/components/fields/embed/EmbeddedVideoEditor.d.ts +2 -2
  55. package/dist/core/components/fields/embed/EmbeddedVideoEditor.js +50 -31
  56. package/dist/core/components/fields/factories/AssetFactory.d.ts +3 -3
  57. package/dist/core/components/fields/factories/AssetFactory.js +18 -13
  58. package/dist/core/components/fields/factories/CollectionFactory.d.ts +3 -3
  59. package/dist/core/components/fields/factories/CollectionFactory.js +20 -13
  60. package/dist/core/components/fields/factories/EmbeddedVideoFactory.d.ts +3 -3
  61. package/dist/core/components/fields/factories/EmbeddedVideoFactory.js +17 -8
  62. package/dist/core/components/fields/factories/FieldValueFactory.d.ts +7 -5
  63. package/dist/core/components/fields/factories/FieldValueFactory.js +57 -13
  64. package/dist/core/components/fields/factories/LinkFactory.d.ts +3 -3
  65. package/dist/core/components/fields/factories/LinkFactory.js +17 -8
  66. package/dist/core/components/fields/factories/MediaFactory.d.ts +13 -0
  67. package/dist/core/components/fields/factories/MediaFactory.js +212 -0
  68. package/dist/core/components/fields/factories/ObjectFactory.d.ts +3 -2
  69. package/dist/core/components/fields/factories/ObjectFactory.js +16 -2
  70. package/dist/core/components/fields/factories/TextFactory.d.ts +3 -3
  71. package/dist/core/components/fields/factories/TextFactory.js +16 -10
  72. package/dist/core/components/fields/link/LinkEditor.d.ts +2 -2
  73. package/dist/core/components/fields/link/LinkEditor.js +18 -6
  74. package/dist/core/components/fields/list/CreateFieldButton.js +1 -1
  75. package/dist/core/components/fields/media/MediaCard.d.ts +7 -0
  76. package/dist/core/components/fields/media/MediaCard.js +92 -0
  77. package/dist/core/components/fields/media/MediaEditor.d.ts +36 -0
  78. package/dist/core/components/fields/media/MediaEditor.js +264 -0
  79. package/dist/core/components/fields/media/index.d.ts +2 -0
  80. package/dist/core/components/fields/media/index.js +18 -0
  81. package/dist/core/components/fields/object/ObjectEditor.d.ts +2 -1
  82. package/dist/core/components/fields/object/ObjectEditor.js +16 -2
  83. package/dist/core/components/fields/page/PagePicker.js +1 -1
  84. package/dist/core/components/interaction/Combobox.js +1 -1
  85. package/dist/core/components/interaction/MultiSelectControls.js +2 -5
  86. package/dist/core/components/interaction/Popup.d.ts +11 -7
  87. package/dist/core/components/interaction/Popup.js +8 -6
  88. package/dist/core/components/interaction/QuickEditor.js +1 -1
  89. package/dist/core/components/interaction/QuickInput.d.ts +2 -4
  90. package/dist/core/components/interaction/QuickInput.js +6 -2
  91. package/dist/core/components/interaction/QuickPicker.js +1 -1
  92. package/dist/core/components/interaction/SideSheet.js +1 -1
  93. package/dist/core/components/interaction/centersheet/CenterSheet.js +7 -1
  94. package/dist/core/components/interaction/centersheet/CenterSheetContainer.js +3 -1
  95. package/dist/core/components/interaction/menu/Menu.d.ts +8 -19
  96. package/dist/core/components/interaction/menu/Menu.js +26 -60
  97. package/dist/core/components/interaction/menu/useMenuController.d.ts +4 -2
  98. package/dist/core/components/interaction/menu/useMenuController.js +4 -1
  99. package/dist/core/components/transitions/FadeIn.js +1 -1
  100. package/dist/core/components/visuals/Icon.d.ts +1 -1
  101. package/dist/core/components/visuals/Icon.js +3 -0
  102. package/dist/core/containers/AssetRepositoryContainer.d.ts +2 -0
  103. package/dist/core/containers/AssetRepositoryContainer.js +18 -0
  104. package/dist/core/containers/CollectionRepositoryContainer.d.ts +2 -0
  105. package/dist/core/containers/CollectionRepositoryContainer.js +18 -0
  106. package/dist/core/containers/PageRepositoryContainer.d.ts +2 -0
  107. package/dist/core/containers/PageRepositoryContainer.js +18 -0
  108. package/dist/core/containers/index.d.ts +3 -0
  109. package/dist/core/containers/index.js +19 -0
  110. package/dist/core/domain/Block.js +2 -1
  111. package/dist/core/domain/BlockConfiguration.d.ts +4 -1
  112. package/dist/core/domain/BlockConfiguration.js +59 -3
  113. package/dist/core/domain/Collection.d.ts +7 -25
  114. package/dist/core/domain/Collection.js +2 -16
  115. package/dist/core/domain/CollectionBrowser.d.ts +3 -2
  116. package/dist/core/domain/CollectionBrowser.js +3 -3
  117. package/dist/core/domain/CollectionFieldProxy.d.ts +12 -8
  118. package/dist/core/domain/CollectionFieldProxy.js +15 -9
  119. package/dist/core/domain/CollectionGroup.d.ts +0 -5
  120. package/dist/core/domain/CollectionGroup.js +0 -7
  121. package/dist/core/domain/CollectionSummary.d.ts +2 -2
  122. package/dist/core/domain/Collections.d.ts +3 -3
  123. package/dist/core/domain/Collections.js +4 -6
  124. package/dist/core/domain/ICollection.d.ts +72 -0
  125. package/dist/core/domain/ICollection.js +20 -0
  126. package/dist/core/domain/IPage.d.ts +16 -1
  127. package/dist/core/domain/Page.js +2 -2
  128. package/dist/core/domain/Pages.js +4 -6
  129. package/dist/core/domain/SectionBlock.js +2 -1
  130. package/dist/core/domain/Site.d.ts +4 -4
  131. package/dist/core/domain/Site.js +3 -5
  132. package/dist/core/domain/index.d.ts +1 -1
  133. package/dist/core/domain/index.js +1 -1
  134. package/dist/core/hooks/index.d.ts +4 -3
  135. package/dist/core/hooks/index.js +4 -3
  136. package/dist/core/hooks/useAssetRepository.d.ts +3 -0
  137. package/dist/core/hooks/useAssetRepository.js +11 -0
  138. package/dist/core/hooks/useCollection.d.ts +4 -4
  139. package/dist/core/hooks/useCollectionRepository.d.ts +3 -2
  140. package/dist/core/hooks/useCollectionRepository.js +4 -4
  141. package/dist/core/hooks/useCollections.js +4 -0
  142. package/dist/core/hooks/usePageRepository.d.ts +3 -2
  143. package/dist/core/hooks/usePageRepository.js +4 -4
  144. package/dist/core/hooks/useSite.js +4 -0
  145. package/dist/core/hooks/useTempFields.d.ts +2 -3
  146. package/dist/core/index.d.ts +1 -0
  147. package/dist/core/index.js +1 -0
  148. package/dist/core/repository/AssetRepository.d.ts +10 -0
  149. package/dist/core/repository/AssetRepository.js +22 -0
  150. package/dist/core/repository/CollectionRepository.d.ts +22 -21
  151. package/dist/core/repository/CollectionRepository.js +23 -161
  152. package/dist/core/repository/CollectionSerializer.d.ts +4 -1
  153. package/dist/core/repository/CollectionSerializer.js +3 -3
  154. package/dist/core/repository/IAssetRepository.d.ts +25 -0
  155. package/dist/core/repository/ICollectionRepository.d.ts +61 -0
  156. package/dist/core/repository/ICollectionRepository.js +2 -0
  157. package/dist/core/repository/IPageRepository.d.ts +40 -0
  158. package/dist/core/repository/IPageRepository.js +2 -0
  159. package/dist/core/repository/PageRepository.d.ts +5 -8
  160. package/dist/core/repository/PageRepository.js +7 -280
  161. package/dist/core/repository/SerializeCollectionUpdate.d.ts +8 -0
  162. package/dist/core/repository/SerializeCollectionUpdate.js +168 -0
  163. package/dist/core/repository/SerializePageUpdate.d.ts +10 -0
  164. package/dist/core/repository/SerializePageUpdate.js +292 -0
  165. package/dist/core/repository/index.d.ts +4 -0
  166. package/dist/core/repository/index.js +4 -0
  167. package/dist/core/splash/SplashContainer.d.ts +4 -2
  168. package/dist/core/splash/SplashContainer.js +3 -3
  169. package/dist/dashboard/screens/Dashboard.js +1 -1
  170. package/dist/devtools/screens/Devtools.js +1 -1
  171. package/dist/explore/components/CreatePageDialog.d.ts +2 -2
  172. package/dist/explore/screens/CollectionExplorer.js +1 -1
  173. package/dist/explore/screens/CollectionsExplorer.js +1 -1
  174. package/dist/explore/screens/PageExplorer.js +1 -1
  175. package/dist/explore/screens/SiteExplorer.js +1 -1
  176. package/dist/page/components/BlockEditor.js +1 -1
  177. package/dist/page/components/SettingsEditor.js +0 -7
  178. package/dist/page/components/config/BlockConfigButton.js +71 -14
  179. package/dist/page/screens/PageEditor.js +1 -1
  180. package/dist/styles/index.css +24 -20
  181. package/dist/styles/tailwind.js +1 -0
  182. package/dist/users/screens/UserExplorer.js +1 -1
  183. package/package.json +2 -2
  184. package/dist/core/domain/TranslateSchema.d.ts +0 -7
  185. /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: "sm", 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' &&
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: "sm", onClick: onDeleteSelected, disabled: selectedItemCount === 0, children: "Delete" }) })] }));
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
- console.debug('[ListEditor] rendering item', { itemId: item.id, selecting, selectedIds });
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
- field.optIn();
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, required, value: data } = field;
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: editor }));
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, required } = field;
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 [anchor, setAnchor] = (0, react_2.useState)();
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, anchorField, accessibleField, descriptionField } = (0, useAssetFields_1.useAssetFields)();
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, anchorField, accessibleField, descriptionField, shared });
48
+ const { valid, modified } = checkFields({ asset, nameField, descriptionField, shared });
38
49
  // export service
39
50
  (0, react_2.useImperativeHandle)(ref, () => ({
40
- edit: async ({ schema, asset, anchor }) => {
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
- setAnchor(anchor);
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
- if (funnel_core_1.Schema.AssetField.LinkedValue.Image.filter(asset)) {
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, anchorField, accessibleField });
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 || !anchor) {
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, placement: "right", anchor: anchor, anchorOffset: 4, canSave: onValidate, disableSave: !valid || !modified, renderSaveLabel: state => state === 'saving' ? 'Updating...' : 'Update', onSave: onUpdate, onClose: onCancel, onClosed: onPickerClosed, children: [(0, jsx_runtime_1.jsx)(feedback_1.ErrorMessage, { error: error }), schema.description && !error &&
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, anchorField, descriptionField, accessibleField, shared, setShared }) }) })] }));
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, anchorField, accessibleField }) {
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: funnel_core_1.Schema.EnumField.Value.fromData(anchorField.value) });
144
+ return Object.assign(Object.assign({}, metadata), { crop: 'center' });
148
145
  case 'video': {
149
- const accessible = (_a = funnel_core_1.Schema.EnumField.Value.fromData(accessibleField.value)) !== null && _a !== void 0 ? _a : 'system';
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, anchorField, accessibleField, descriptionField, shared }) {
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 = anchorField.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
- let modified = (asset.scope === 'global') !== shared
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, anchorField, descriptionField, accessibleField, shared, setShared }) {
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 editorApi = (0, client_1.useEditorApi)();
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
- editorApi
61
- .getAssets({
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
- }, [editorApi, assetStore, schema, fileTypes]);
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
  }