@nascentdigital/funnel-editor 5.0.1 → 5.0.3

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 (86) hide show
  1. package/dist/components.d.ts +3 -1
  2. package/dist/components.js +3 -1
  3. package/dist/core/client/EditorApiClient.js +1 -1
  4. package/dist/core/components/fields/OptInField.js +42 -2
  5. package/dist/core/components/fields/asset/AssetEditor.d.ts +1 -2
  6. package/dist/core/components/fields/asset/AssetEditor.js +18 -6
  7. package/dist/core/components/fields/asset/AssetUploader.d.ts +1 -2
  8. package/dist/core/components/fields/asset/AssetUploader.js +18 -6
  9. package/dist/core/components/fields/collection/CollectionEditor.d.ts +2 -1
  10. package/dist/core/components/fields/collection/CollectionEditor.js +17 -3
  11. package/dist/core/components/fields/embed/EmbeddedVideoEditor.d.ts +2 -2
  12. package/dist/core/components/fields/embed/EmbeddedVideoEditor.js +17 -5
  13. package/dist/core/components/fields/factories/AssetFactory.d.ts +3 -3
  14. package/dist/core/components/fields/factories/AssetFactory.js +18 -13
  15. package/dist/core/components/fields/factories/CollectionFactory.d.ts +3 -3
  16. package/dist/core/components/fields/factories/CollectionFactory.js +20 -13
  17. package/dist/core/components/fields/factories/EmbeddedVideoFactory.d.ts +3 -3
  18. package/dist/core/components/fields/factories/EmbeddedVideoFactory.js +17 -8
  19. package/dist/core/components/fields/factories/FieldValueFactory.d.ts +7 -5
  20. package/dist/core/components/fields/factories/FieldValueFactory.js +49 -12
  21. package/dist/core/components/fields/factories/LinkFactory.d.ts +3 -3
  22. package/dist/core/components/fields/factories/LinkFactory.js +17 -8
  23. package/dist/core/components/fields/factories/MediaFactory.d.ts +3 -3
  24. package/dist/core/components/fields/factories/MediaFactory.js +105 -149
  25. package/dist/core/components/fields/factories/ObjectFactory.d.ts +3 -2
  26. package/dist/core/components/fields/factories/ObjectFactory.js +16 -2
  27. package/dist/core/components/fields/factories/TextFactory.d.ts +3 -3
  28. package/dist/core/components/fields/factories/TextFactory.js +16 -10
  29. package/dist/core/components/fields/link/LinkEditor.d.ts +2 -2
  30. package/dist/core/components/fields/link/LinkEditor.js +18 -6
  31. package/dist/core/components/fields/media/MediaEditor.d.ts +2 -3
  32. package/dist/core/components/fields/media/MediaEditor.js +40 -11
  33. package/dist/core/components/fields/media/index.d.ts +0 -1
  34. package/dist/core/components/fields/media/index.js +0 -1
  35. package/dist/core/components/fields/object/ObjectEditor.d.ts +2 -1
  36. package/dist/core/components/fields/object/ObjectEditor.js +15 -1
  37. package/dist/core/components/fields/page/PagePicker.js +1 -1
  38. package/dist/core/components/interaction/Popup.d.ts +11 -7
  39. package/dist/core/components/interaction/Popup.js +8 -6
  40. package/dist/core/components/interaction/QuickInput.d.ts +2 -4
  41. package/dist/core/components/interaction/QuickInput.js +6 -2
  42. package/dist/core/components/interaction/menu/Menu.d.ts +8 -19
  43. package/dist/core/components/interaction/menu/Menu.js +26 -60
  44. package/dist/core/components/interaction/menu/useMenuController.d.ts +4 -2
  45. package/dist/core/components/interaction/menu/useMenuController.js +4 -1
  46. package/dist/core/domain/CollectionFieldProxy.js +1 -1
  47. package/dist/core/domain/Collections.js +0 -2
  48. package/dist/core/domain/ICollection.d.ts +1 -0
  49. package/dist/core/domain/IPage.d.ts +6 -1
  50. package/dist/core/domain/IPage.js +30 -0
  51. package/dist/core/domain/PageOverview.d.ts +6 -0
  52. package/dist/core/domain/PageOverview.js +17 -0
  53. package/dist/core/domain/PageSummary.d.ts +9 -7
  54. package/dist/core/domain/PageSummary.js +12 -16
  55. package/dist/core/domain/Pages.js +1 -2
  56. package/dist/core/domain/Site.js +0 -2
  57. package/dist/core/hooks/useCollectionRepository.d.ts +1 -1
  58. package/dist/core/hooks/useCollections.js +4 -0
  59. package/dist/core/hooks/usePageRepository.d.ts +1 -1
  60. package/dist/core/hooks/useSite.js +4 -0
  61. package/dist/core/repository/CollectionRepository.d.ts +2 -2
  62. package/dist/core/repository/ICollectionRepository.d.ts +2 -3
  63. package/dist/core/repository/IPageRepository.d.ts +0 -1
  64. package/dist/core/repository/PageRepository.js +1 -1
  65. package/dist/core/repository/SerializeCollectionUpdate.d.ts +5 -5
  66. package/dist/core/repository/SerializePageUpdate.d.ts +7 -8
  67. package/dist/core/splash/SplashContainer.d.ts +4 -2
  68. package/dist/core/splash/SplashContainer.js +3 -3
  69. package/dist/explore/screens/PageExplorer.js +2 -1
  70. package/dist/page/components/BlockEditor.d.ts +3 -1
  71. package/dist/page/components/BlockEditor.js +4 -3
  72. package/dist/page/components/config/BlockConfigurationProvider.d.ts +10 -2
  73. package/dist/page/components/config/BlockConfigurationProvider.js +11 -3
  74. package/dist/page/components/config/BlockPreview.d.ts +4 -2
  75. package/dist/page/components/config/BlockPreview.js +5 -11
  76. package/dist/page/components/config/index.d.ts +1 -0
  77. package/dist/page/components/config/index.js +1 -0
  78. package/dist/page/components/config/useBlockConfiguration$.d.ts +3 -0
  79. package/dist/page/components/config/useBlockConfiguration$.js +22 -0
  80. package/dist/page/components/panels/BlockConfigPanel.js +3 -3
  81. package/dist/page/hooks/PageController.js +2 -1
  82. package/dist/styles/index.css +34 -9
  83. package/dist/styles/tailwind.js +1 -0
  84. package/package.json +3 -3
  85. package/dist/core/components/fields/media/MediaPicker.d.ts +0 -15
  86. package/dist/core/components/fields/media/MediaPicker.js +0 -251
@@ -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
  };
@@ -25,7 +36,7 @@ exports.LinkEditor = (0, react_1.forwardRef)(function LinkEditor({ region, langu
25
36
  const [deferral, setDeferral] = (0, react_1.useState)(undefined);
26
37
  const [schema, setSchema] = (0, react_1.useState)();
27
38
  const [initialValue, setInitialValue] = (0, react_1.useState)();
28
- const [anchor, setAnchor] = (0, react_1.useState)();
39
+ const [popupProps, setPopupProps] = (0, react_1.useState)();
29
40
  const [pickedPage, setPickedPage] = (0, react_1.useState)();
30
41
  const [pickingPage, setPickingPage] = (0, react_1.useState)(false);
31
42
  const [errorLevel, setErrorLevel] = (0, react_1.useState)('none');
@@ -48,11 +59,12 @@ exports.LinkEditor = (0, react_1.forwardRef)(function LinkEditor({ region, langu
48
59
  const pagesAvailable = allowInternal && pageStore !== undefined;
49
60
  // export service
50
61
  (0, react_1.useImperativeHandle)(ref, () => ({
51
- edit: async ({ schema, initialValue, anchor }) => {
62
+ edit: async (_a) => {
63
+ var { schema, initialValue } = _a, popupProps = __rest(_a, ["schema", "initialValue"]);
52
64
  // reset state
53
65
  setSchema(schema);
54
66
  setInitialValue(initialValue);
55
- setAnchor(anchor);
67
+ setPopupProps(popupProps);
56
68
  setPickedPage(undefined);
57
69
  setPickingPage(false);
58
70
  setErrorLevel('none');
@@ -217,11 +229,11 @@ exports.LinkEditor = (0, react_1.forwardRef)(function LinkEditor({ region, langu
217
229
  touch();
218
230
  };
219
231
  // skip if params are missing
220
- if (!anchor) {
232
+ if (!popupProps) {
221
233
  return null;
222
234
  }
223
235
  // render
224
- return ((0, jsx_runtime_1.jsxs)(interaction_1.MiniEditor, { title: `${initialValue ? 'Edit' : 'Create'} ${name}`, open: !!deferral && !deferral.isComplete, anchor: anchor, anchorOffset: 4, canSave: canSave, onSave: onSave, onClose: onCancel, disabled: pickingPage, children: [description &&
236
+ return ((0, jsx_runtime_1.jsxs)(interaction_1.MiniEditor, Object.assign({ title: `${initialValue ? 'Edit' : 'Create'} ${name}`, open: !!deferral && !deferral.isComplete, canSave: canSave, onSave: onSave, onClose: onCancel, disabled: pickingPage }, popupProps, { children: [description &&
225
237
  (0, jsx_runtime_1.jsx)(feedback_1.Note, { variant: "tip", children: description }), (0, jsx_runtime_1.jsxs)(FieldErrorController_1.FieldErrorController, { errorLevel: errorLevel, children: [(0, jsx_runtime_1.jsx)(FieldEditor_1.FieldEditor, { field: labelField, autoFocus: true }), pickedPage
226
238
  // show picked page (if selected)
227
239
  ?
@@ -232,5 +244,5 @@ exports.LinkEditor = (0, react_1.forwardRef)(function LinkEditor({ region, langu
232
244
  ?
233
245
  (0, jsx_runtime_1.jsx)(interaction_1.IconButton, { icon: "Globe", onClick: onPickPage })
234
246
  : undefined }) }, "field.input")] }), allowInternal &&
235
- (0, jsx_runtime_1.jsx)(page_1.PagePicker, { ref: pagePickerRef, language: language })] }));
247
+ (0, jsx_runtime_1.jsx)(page_1.PagePicker, { ref: pagePickerRef, language: language })] })));
236
248
  });
@@ -28,10 +28,9 @@ export declare namespace MediaEditor {
28
28
  interface Ref {
29
29
  edit(options: Options): Promise<Result>;
30
30
  }
31
- type Options = {
31
+ type Options = Popup.Props.Delegated & {
32
32
  schema: Media.Schema;
33
33
  target: Target;
34
- anchor: Popup.Anchor;
35
34
  };
36
- type Result = Media.Value | 'pick' | undefined;
35
+ type Result = Media.Value | undefined;
37
36
  }
@@ -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
  Object.defineProperty(exports, "__esModule", { value: true });
3
14
  exports.MediaEditor = void 0;
4
15
  const jsx_runtime_1 = require("react/jsx-runtime");
@@ -20,7 +31,7 @@ exports.MediaEditor = (0, react_1.forwardRef)(function MediaEditor({ language },
20
31
  const [deferral, setDeferral] = (0, react_1.useState)(undefined);
21
32
  const [result, setResult] = (0, react_1.useState)();
22
33
  const [target, setTarget] = (0, react_1.useState)();
23
- const [anchor, setAnchor] = (0, react_1.useState)();
34
+ const [popupProps, setPopupProps] = (0, react_1.useState)();
24
35
  const [fieldSchema, setFieldSchema] = (0, react_1.useState)();
25
36
  const [mediaSchema, setMediaSchema] = (0, react_1.useState)();
26
37
  const [shared, setShared] = (0, react_1.useState)(false);
@@ -39,7 +50,8 @@ exports.MediaEditor = (0, react_1.forwardRef)(function MediaEditor({ language },
39
50
  (0, hooks_1.useCollectionFieldProxy)(field);
40
51
  // export service
41
52
  (0, react_1.useImperativeHandle)(ref, () => ({
42
- edit: async ({ schema, target, anchor }) => {
53
+ edit: async (_a) => {
54
+ var { schema, target } = _a, popupProps = __rest(_a, ["schema", "target"]);
43
55
  // reset state
44
56
  setFieldSchema(schema);
45
57
  setMediaSchema(target.type === 'image' || (target.type === 'media' && funnel_ui_1.Media.Value.isImage(target.media))
@@ -48,7 +60,7 @@ exports.MediaEditor = (0, react_1.forwardRef)(function MediaEditor({ language },
48
60
  setTarget(target);
49
61
  setField(undefined);
50
62
  setShared(false);
51
- setAnchor(anchor);
63
+ setPopupProps(popupProps);
52
64
  setErrorLevel('none');
53
65
  setError(undefined);
54
66
  // create deferral
@@ -189,31 +201,41 @@ exports.MediaEditor = (0, react_1.forwardRef)(function MediaEditor({ language },
189
201
  // complete deferral
190
202
  deferral.resolve(result !== null && result !== void 0 ? result : undefined);
191
203
  };
204
+ // skip if not ready
205
+ if (!popupProps) {
206
+ return null;
207
+ }
192
208
  // render
193
- return ((0, jsx_runtime_1.jsx)(interaction_1.MiniEditor, { className: "flex flex-col gap-l8", title: `Edit Media`, open: !!deferral && result === undefined, placement: "right", anchor: anchor, anchorOffset: 4, disableSave: !modified, canSave: onValidate, onSave: onSave, renderSaveLabel: state => state === 'saving' ? 'Updating...' : 'Update', customActions: (0, jsx_runtime_1.jsx)(interaction_1.Button, { variant: "secondary", size: "sm", onClick: () => setResult('pick'), children: "Use existing media" }), onClose: onCancel, onClosed: onClosed, children: (0, jsx_runtime_1.jsx)(hooks_1.CollectionStoreContext.Provider, { value: collectionStore, children: (0, jsx_runtime_1.jsxs)(hooks_1.AssetStoreContext.Provider, { value: assetStore, children: [mediaSchema.description && !error &&
194
- (0, jsx_runtime_1.jsx)(feedback_1.Note, { variant: "tip", children: mediaSchema.description }), (0, jsx_runtime_1.jsx)(framer_motion_1.AnimatePresence, { children: (0, jsx_runtime_1.jsxs)(FieldErrorController_1.FieldErrorController, { errorLevel: errorLevel, children: [(0, jsx_runtime_1.jsx)(FieldEditor_1.FieldEditor, { field: field.nameField, autoFocus: true }), renderFields({ field })] }) })] }) }) }));
209
+ return ((0, jsx_runtime_1.jsx)(interaction_1.MiniEditor, Object.assign({ className: "flex flex-col gap-l8", title: `Edit Media`, open: !!deferral && result === undefined, disableSave: !modified, canSave: onValidate, onSave: onSave, renderSaveLabel: state => state === 'saving' ? 'Updating...' : 'Update', onClose: onCancel, onClosed: onClosed }, popupProps, { children: (0, jsx_runtime_1.jsx)(hooks_1.CollectionStoreContext.Provider, { value: collectionStore, children: (0, jsx_runtime_1.jsx)(hooks_1.AssetStoreContext.Provider, { value: assetStore, children: renderFields({ field, error, errorLevel }) }) }) })));
195
210
  });
196
211
  function renderFields(args) {
197
212
  // render image fields
213
+ let content;
198
214
  const value = args.field.value;
199
215
  if (funnel_ui_1.Media.Value.isImage(value)) {
200
- return renderImageFields(args);
216
+ content = renderImageFields(args);
201
217
  }
202
218
  // or video fields
203
219
  else {
204
- return renderVideoFields(args);
220
+ content = renderVideoFields(args);
205
221
  }
222
+ // render
223
+ return ((0, jsx_runtime_1.jsx)(framer_motion_1.AnimatePresence, { children: (0, jsx_runtime_1.jsx)(FieldErrorController_1.FieldErrorController, { errorLevel: args.errorLevel, children: content }) }));
206
224
  }
207
- function renderImageFields({ field }) {
225
+ function renderImageFields({ field, error }) {
208
226
  // resolve fields
209
227
  const desktopImageField = field.getField('image');
210
228
  const mobileImageField = field.getField('mobileImage');
229
+ const hasMobileImage = mobileImageField.exists;
211
230
  // render
212
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(FieldEditor_1.FieldEditor, { field: desktopImageField, disableDelete: true }), mobileImageField.exists
231
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [!error &&
232
+ (0, jsx_runtime_1.jsx)(feedback_1.Note, { variant: "tip", children: hasMobileImage
233
+ ? 'The mobile version on phones and smaller displays.'
234
+ : 'Without a mobile version, this image is used at every screen size.' }), (0, jsx_runtime_1.jsx)(FieldEditor_1.FieldEditor, { field: desktopImageField, disableDelete: true }), hasMobileImage
213
235
  ? (0, jsx_runtime_1.jsx)(FieldEditor_1.FieldEditor, { field: mobileImageField })
214
236
  : (0, jsx_runtime_1.jsx)(OptInField_1.OptInField, { className: "self-start", field: mobileImageField })] }));
215
237
  }
216
- function renderVideoFields({ field }) {
238
+ function renderVideoFields({ field, error }) {
217
239
  var _a, _b;
218
240
  // resolve fields
219
241
  const sourceField = field.getField('video');
@@ -222,12 +244,19 @@ function renderVideoFields({ field }) {
222
244
  const remoteVideoField = sourceField.getField('remote');
223
245
  const remoteVideo = (_b = remoteVideoField.value) === null || _b === void 0 ? void 0 : _b.value;
224
246
  const coverField = field.getField('cover');
247
+ const hasCover = coverField.exists;
248
+ const isRemote = !localVideo;
225
249
  // TODO render error if there's no video source
226
250
  if (!localVideo && !remoteVideo) {
227
251
  return null;
228
252
  }
229
253
  // render
230
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(FieldEditor_1.FieldEditor, { field: localVideo
254
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [!error &&
255
+ (0, jsx_runtime_1.jsx)(feedback_1.Note, { variant: "tip", children: hasCover
256
+ ? 'Your cover image will be shown before the video plays, replacing the default first frame.'
257
+ : isRemote
258
+ ? 'You can customize the video cover image.'
259
+ : 'Without a cover image, a blurhash will be displayed before it plays.' }), (0, jsx_runtime_1.jsx)(FieldEditor_1.FieldEditor, { field: localVideo
231
260
  ? localVideoField
232
261
  : remoteVideoField, disableDelete: true }), coverField.exists
233
262
  ? (0, jsx_runtime_1.jsx)(FieldEditor_1.FieldEditor, { field: coverField })
@@ -1,3 +1,2 @@
1
1
  export * from './MediaCard';
2
2
  export * from './MediaEditor';
3
- export * from './MediaPicker';
@@ -16,4 +16,3 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./MediaCard"), exports);
18
18
  __exportStar(require("./MediaEditor"), exports);
19
- __exportStar(require("./MediaPicker"), exports);
@@ -1,11 +1,12 @@
1
1
  import { ObjectField, Schema } from '@nascentdigital/funnel-core';
2
+ import { Popup } from '../../interaction';
2
3
  export declare const ObjectEditor: import("react").ForwardRefExoticComponent<import("react").RefAttributes<ObjectEditor.Ref>>;
3
4
  export declare namespace ObjectEditor {
4
5
  type Props = {};
5
6
  interface Ref {
6
7
  edit(options: Options): Promise<Schema.Field.Data<Schema.ObjectField> | undefined>;
7
8
  }
8
- type Options = {
9
+ type Options = Popup.Props.Delegated & {
9
10
  schema: Schema.ObjectField;
10
11
  field?: ObjectField;
11
12
  };
@@ -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
  Object.defineProperty(exports, "__esModule", { value: true });
3
14
  exports.ObjectEditor = void 0;
4
15
  const jsx_runtime_1 = require("react/jsx-runtime");
@@ -14,13 +25,16 @@ exports.ObjectEditor = (0, react_1.forwardRef)(function ObjectEditor(_, ref) {
14
25
  const [result, setResult] = (0, react_1.useState)();
15
26
  const [schema, setSchema] = (0, react_1.useState)();
16
27
  const [field, setField] = (0, react_1.useState)();
28
+ const [popupProps, setPopupProps] = (0, react_1.useState)();
17
29
  // sync field
18
30
  (0, hooks_1.useField)(field);
19
31
  // export service
20
32
  (0, react_1.useImperativeHandle)(ref, () => ({
21
- edit: async ({ schema, field: existingField }) => {
33
+ edit: async (_a) => {
34
+ var { schema, field: existingField } = _a, popupProps = __rest(_a, ["schema", "field"]);
22
35
  // reset state
23
36
  setSchema(schema);
37
+ setPopupProps(popupProps);
24
38
  // create new field (clone data from existing field if provided)
25
39
  const clonedField = funnel_core_1.ObjectField.forSchema(schema);
26
40
  if (existingField) {
@@ -138,7 +138,7 @@ exports.PagePicker = (0, react_1.forwardRef)(function PagePicker({ language }, r
138
138
  pages.sync()
139
139
  .then(() => {
140
140
  setPagesSchema(pages.template);
141
- setPages(pages.items.map(page => page.getClosestPageRef(language, site.defaultLanguage)));
141
+ setPages(pages.items.map(page => page.getClosestPageRef({ region: site.region.id, language, fallbackLanguage: site.defaultLanguage })));
142
142
  })
143
143
  .catch(e => setError(feedback_1.ErrorMessage.coerce(e)));
144
144
  }
@@ -1,13 +1,15 @@
1
1
  import { Callback, Placement, Rect } from '@nascentdigital/funnel-core';
2
2
  import { HTMLContainer } from '@nascentdigital/funnel-ui';
3
- import { HTMLAttributes, ReactNode, CSSProperties } from 'react';
4
- export declare function Popup({ className, style, anchor, anchorOffset, placement, viewportPadding, animation, backdrop, disabled, disableDismiss, disableOverlay, open, onOpened: onOpenedRaw, onClose, onClosed: onClosedRaw, onKeyDown: onKeyDownRaw, children, ...props }: Popup.Props): import("react/jsx-runtime").JSX.Element | null;
3
+ import { CSSProperties, HTMLAttributes, ReactNode } from 'react';
4
+ export declare function Popup({ className, style, anchor, anchorOffset, placement, animation, backdrop, disabled, disableDismiss, disableOverlay, open, onOpened: onOpenedRaw, onClose, onClosed: onClosedRaw, onKeyDown: onKeyDownRaw, children, ...props }: Popup.Props): import("react/jsx-runtime").JSX.Element | null;
5
5
  export declare namespace Popup {
6
+ type Anchor = string;
7
+ type Animation = 'in' | 'out' | 'in-out';
8
+ type Backdrop = 'none' | 'glass';
6
9
  type Props = HTMLAttributes<HTMLDivElement> & {
7
- anchor?: Anchor;
10
+ anchor?: Anchor | ReactNode;
8
11
  anchorOffset?: number;
9
12
  placement?: Placement;
10
- viewportPadding?: number;
11
13
  animation?: Animation;
12
14
  backdrop?: Backdrop;
13
15
  disabled?: boolean;
@@ -18,9 +20,11 @@ export declare namespace Popup {
18
20
  onClose?: Callback.Void;
19
21
  onClosed?: Callback.Void;
20
22
  };
21
- type Anchor = string | ReactNode;
22
- type Animation = 'in' | 'out' | 'in-out';
23
- type Backdrop = 'none' | 'glass';
23
+ namespace Props {
24
+ type Delegated = Pick<Props, 'anchorOffset' | 'placement'> & {
25
+ anchor?: Popup.Anchor;
26
+ };
27
+ }
24
28
  const anchorClassName: "anchor/[--nd-popup-anchor]";
25
29
  function getAnchorStyle(anchorId: string, styles?: CSSProperties): CSSProperties;
26
30
  type Frame = {
@@ -26,7 +26,7 @@ const react_dom_1 = require("react-dom");
26
26
  const Animate_1 = require("./Animate");
27
27
  // component
28
28
  function Popup(_a) {
29
- var { className, style = {}, anchor, anchorOffset, placement = 'bottom', viewportPadding, animation = 'in-out', backdrop = 'none', disabled = false, disableDismiss = false, disableOverlay = false, open = false, onOpened: onOpenedRaw = funnel_core_1.Fn.NoOp, onClose = funnel_core_1.Fn.NoOp, onClosed: onClosedRaw = funnel_core_1.Fn.NoOp, onKeyDown: onKeyDownRaw, children } = _a, props = __rest(_a, ["className", "style", "anchor", "anchorOffset", "placement", "viewportPadding", "animation", "backdrop", "disabled", "disableDismiss", "disableOverlay", "open", "onOpened", "onClose", "onClosed", "onKeyDown", "children"]);
29
+ var { className, style = {}, anchor, anchorOffset = 4, placement = 'bottom', animation = 'in-out', backdrop = 'none', disabled = false, disableDismiss = false, disableOverlay = false, open = false, onOpened: onOpenedRaw = funnel_core_1.Fn.NoOp, onClose = funnel_core_1.Fn.NoOp, onClosed: onClosedRaw = funnel_core_1.Fn.NoOp, onKeyDown: onKeyDownRaw, children } = _a, props = __rest(_a, ["className", "style", "anchor", "anchorOffset", "placement", "animation", "backdrop", "disabled", "disableDismiss", "disableOverlay", "open", "onOpened", "onClose", "onClosed", "onKeyDown", "children"]);
30
30
  // bind context
31
31
  const id = (0, react_1.useId)();
32
32
  const anchorId = typeof anchor === 'string'
@@ -89,7 +89,7 @@ function Popup(_a) {
89
89
  }
90
90
  };
91
91
  // render
92
- const { popupContainerClassName, popupClassName } = getPopupClassNames({ anchor, anchorId, anchorOffset, placement });
92
+ const { popupContainerClassName, popupClassName, popupStyles } = getPopupClassNames({ anchor, anchorId, anchorOffset, placement });
93
93
  return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [anchor && typeof anchor !== 'string' &&
94
94
  (0, jsx_runtime_1.jsx)(Popup.AnchorElement, { tag: "div", anchorId: anchorId, children: anchor }), (0, react_dom_1.createPortal)((0, jsx_runtime_1.jsx)(framer_motion_1.AnimatePresence, { mode: "wait", children: open &&
95
95
  (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsxs)(framer_motion_1.motion.div, { id: id, className: (0, classnames_1.default)(popupContainerClassName, 'fixed inset-0 z-popup', {
@@ -98,8 +98,8 @@ function Popup(_a) {
98
98
  (0, jsx_runtime_1.jsx)(framer_motion_1.motion.div, { className: (0, classnames_1.default)('fixed inset-0 z-backdrop', {
99
99
  'backdrop-blur-[9px] bg-glass/backdrop will-change-[backdrop-filter]': backdrop === 'glass'
100
100
  }) }, "backdrop"), (0, jsx_runtime_1.jsx)("div", Object.assign({}, props, { ref: contentRef, className: (0, classnames_1.default)(className, popupClassName, 'pointer-events-auto'), style: anchor
101
- ? Popup.getAnchorStyle(anchorId, { margin: `${anchorOffset !== null && anchorOffset !== void 0 ? anchorOffset : 0}px` })
102
- : undefined, onKeyDown: onKeyDown, children: children }))] }, id) }) }), document.body)] }));
101
+ ? Popup.getAnchorStyle(anchorId, Object.assign({ margin: `${anchorOffset !== null && anchorOffset !== void 0 ? anchorOffset : 0}px` }, popupStyles))
102
+ : popupStyles, onKeyDown: onKeyDown, children: children }))] }, id) }) }), document.body)] }));
103
103
  }
104
104
  // extension
105
105
  (function (Popup) {
@@ -145,14 +145,16 @@ function getPopupClassNames({ anchor, placement }) {
145
145
  'anchored-left-span-bottom': placement === 'left-start',
146
146
  'anchored-right': placement === 'right',
147
147
  'anchored-bottom-span-left': placement === 'bottom-end'
148
- })
148
+ }),
149
+ popupStyles: { positionTryFallbacks: 'flip-y, flip-x' }
149
150
  };
150
151
  }
151
152
  // or treat as modal if there's no anchor
152
153
  else {
153
154
  return {
154
155
  popupContainerClassName: 'flex flex-col justify-end items-center sm:justify-center',
155
- popupClassName: 'z-dialog'
156
+ popupClassName: 'z-dialog',
157
+ popupStyles: {}
156
158
  };
157
159
  }
158
160
  }
@@ -1,4 +1,4 @@
1
- import { RequiredBy, Schema } from '@nascentdigital/funnel-core';
1
+ import { Schema } from '@nascentdigital/funnel-core';
2
2
  import { Popup } from './Popup';
3
3
  export declare const QuickInput: import("react").ForwardRefExoticComponent<import("react").RefAttributes<QuickInput.Ref<Schema.Field.Type.Simple.NonRef>>>;
4
4
  export declare namespace QuickInput {
@@ -8,10 +8,8 @@ export declare namespace QuickInput {
8
8
  open(args: CaptureArgs<TSchema>): Promise<Schema.Field.Value.ForSimpleType<TSchema> | undefined>;
9
9
  close(): void;
10
10
  }
11
- type CaptureArgs<TSchema extends Schema.Field.Type.Simple.NonRef = Schema.Field.Type.Simple.NonRef> = PopupProps & {
11
+ type CaptureArgs<TSchema extends Schema.Field.Type.Simple.NonRef = Schema.Field.Type.Simple.NonRef> = Popup.Props.Delegated & {
12
12
  schema: TSchema;
13
13
  initialValue?: Schema.Field.Value.ForSimpleType<TSchema>;
14
14
  };
15
15
  }
16
- type PopupProps = RequiredBy<Omit<Popup.Props, 'className' | 'animation' | 'disableClickDismiss' | 'open' | 'onOpened' | 'onClose' | 'onClosed' | 'children'>, 'anchor' | 'placement'>;
17
- export {};
@@ -127,11 +127,15 @@ exports.QuickInput = (0, react_1.forwardRef)(function QuickInput(_, ref) {
127
127
  break;
128
128
  }
129
129
  };
130
+ // skip if not ready
131
+ if (!popupProps) {
132
+ return null;
133
+ }
130
134
  // render
131
- return ((0, jsx_runtime_1.jsxs)(Popup_1.Popup, Object.assign({}, (popupProps !== null && popupProps !== void 0 ? popupProps : {}), { className: (0, classnames_1.default)('glass-overlay w-[330px] flex items-center gap-l5 p-l5 interpolate', 'border-t border-solid border-glass-stroke-l1 rounded-full', {
135
+ return ((0, jsx_runtime_1.jsxs)(Popup_1.Popup, Object.assign({ className: (0, classnames_1.default)('glass-overlay w-[330px] flex items-center gap-l5 p-l5 interpolate', 'border-t border-solid border-glass-stroke-l1 rounded-full', {
132
136
  'opacity-none': !opened,
133
137
  'opacity-full': opened
134
- }), animation: "out", open: deferral && ready, onOpened: () => setOpened(true), onClose: onClose, onClosed: () => setOpened(false), children: [(0, jsx_runtime_1.jsx)(FieldErrorController_1.FieldErrorController, { errorLevel: errorLevel, children: renderInput({ field, onKeyDown }) }), (0, jsx_runtime_1.jsx)(Button_1.Button, { variant: "secondary", size: "sm", onClick: onSave, children: "Save" })] })));
138
+ }), animation: "out", open: deferral && ready, onOpened: () => setOpened(true), onClose: onClose, onClosed: () => setOpened(false) }, popupProps, { children: [(0, jsx_runtime_1.jsx)(FieldErrorController_1.FieldErrorController, { errorLevel: errorLevel, children: renderInput({ field, onKeyDown }) }), (0, jsx_runtime_1.jsx)(Button_1.Button, { variant: "secondary", size: "sm", onClick: onSave, children: "Save" })] })));
135
139
  });
136
140
  function renderInput({ field, onKeyDown }) {
137
141
  // skip if there's no field
@@ -1,25 +1,14 @@
1
1
  import { Callback } from '@nascentdigital/funnel-core';
2
2
  import { Popup } from '../Popup';
3
- import { MenuItem } from './MenuItem';
4
3
  import { MenuController } from './useMenuController';
5
4
  export declare function Menu<TItemId extends string>(props: Menu.Props<TItemId>): import("react/jsx-runtime").JSX.Element;
6
5
  export declare namespace Menu {
7
- type Props<TItemId extends string> = Props.Static<TItemId> | Props.Controlled<TItemId>;
8
- namespace Props {
9
- type Base<TItemId extends string> = {
10
- label?: string;
11
- title?: string;
12
- onItemClick?: Callback<TItemId>;
13
- };
14
- export type Static<TItemId extends string> = Omit<Popup.Props, 'children'> & Base<TItemId> & {
15
- items: ReadonlyArray<MenuItem<TItemId>>;
16
- controller?: never;
17
- selectedItem?: TItemId;
18
- };
19
- export type Controlled<TItemId extends string> = Omit<Popup.Props, 'anchor' | 'open' | 'children'> & Base<TItemId> & {
20
- items?: never;
21
- controller: MenuController<TItemId>;
22
- };
23
- export {};
24
- }
6
+ type Props<TItemId extends string> = Omit<Popup.Props.Delegated, 'anchor'> & {
7
+ className?: string;
8
+ label?: string;
9
+ title?: string;
10
+ controller: MenuController<TItemId>;
11
+ onItemClick?: Callback<TItemId>;
12
+ onClose?: Callback.Void;
13
+ };
25
14
  }
@@ -15,74 +15,40 @@ function Menu(props) {
15
15
  const { className, label, title } = props;
16
16
  const { popupProps, menuListProps } = getPopupMenuProps(props);
17
17
  // render
18
- return ((0, jsx_runtime_1.jsxs)(Popup_1.Popup, Object.assign({}, popupProps, { className: (0, classnames_1.default)(className, 'min-w-[200px] glass-overlay rounded-lg overflow-hidden'), children: [(label || title) &&
18
+ return ((0, jsx_runtime_1.jsxs)(Popup_1.Popup, Object.assign({ className: (0, classnames_1.default)(className, 'min-w-[200px] glass-overlay rounded-lg overflow-hidden') }, popupProps, { children: [(label || title) &&
19
19
  (0, jsx_runtime_1.jsxs)("div", { className: "border-b border-solid border-border-l1 px-l6 pt-l4 pb-l5", children: [label &&
20
20
  (0, jsx_runtime_1.jsx)("span", { className: "block body-xs text-content-secondary", children: label }), title &&
21
21
  (0, jsx_runtime_1.jsx)("h3", { className: "heading-xs text-content-primary ", children: title })] }), (0, jsx_runtime_1.jsx)(MenuList_1.MenuList, Object.assign({}, menuListProps))] })));
22
22
  }
23
23
  function getPopupMenuProps(props) {
24
- var _a, _b, _c, _d;
24
+ var _a;
25
25
  // handle controlled menu
26
26
  const anchorOffset = 4;
27
- const viewportPadding = 6;
28
- if (isMenuControlled(props)) {
29
- const { controller, onClose = funnel_core_1.Fn.NoOp } = props;
30
- return {
31
- popupProps: {
32
- placement: props.placement,
33
- anchorOffset: (_a = props.anchorOffset) !== null && _a !== void 0 ? _a : anchorOffset,
34
- viewportPadding: (_b = props.viewportPadding) !== null && _b !== void 0 ? _b : viewportPadding,
35
- anchor: controller.anchor,
36
- open: controller.isOpen,
37
- onClose: () => {
38
- controller.close();
39
- onClose();
40
- }
41
- },
42
- menuListProps: {
43
- items: controller.items,
44
- selectedItem: controller.selectedItem,
45
- onItemClick: (id) => {
46
- // close menu
47
- controller.close();
48
- // update selected item
49
- controller.selectedItem = id;
50
- // raise click
51
- if (props.onItemClick) {
52
- props.onItemClick(id);
53
- }
54
- }
27
+ const { controller, onClose = funnel_core_1.Fn.NoOp } = props;
28
+ return {
29
+ popupProps: {
30
+ anchor: controller.anchor,
31
+ anchorOffset: (_a = props.anchorOffset) !== null && _a !== void 0 ? _a : anchorOffset,
32
+ placement: props.placement,
33
+ open: controller.isOpen,
34
+ onClose: () => {
35
+ controller.close();
36
+ onClose();
55
37
  }
56
- };
57
- }
58
- // or uncontrolled
59
- else {
60
- return {
61
- popupProps: {
62
- placement: props.placement,
63
- anchorOffset: (_c = props.anchorOffset) !== null && _c !== void 0 ? _c : anchorOffset,
64
- viewportPadding: (_d = props.viewportPadding) !== null && _d !== void 0 ? _d : viewportPadding,
65
- anchor: props.anchor,
66
- open: props.open,
67
- onClose: props.onClose
68
- },
69
- menuListProps: {
70
- items: props.items,
71
- selectedItem: props.selectedItem,
72
- onItemClick: (id) => {
73
- // close menu
74
- if (props.onClose) {
75
- props.onClose();
76
- }
77
- // raise click
78
- if (props.onItemClick) {
79
- props.onItemClick(id);
80
- }
38
+ },
39
+ menuListProps: {
40
+ items: controller.items,
41
+ selectedItem: controller.selectedItem,
42
+ onItemClick: (id) => {
43
+ // close menu
44
+ controller.close();
45
+ // update selected item
46
+ controller.selectedItem = id;
47
+ // raise click
48
+ if (props.onItemClick) {
49
+ props.onItemClick(id);
81
50
  }
82
51
  }
83
- };
84
- }
85
- }
86
- function isMenuControlled(props) {
87
- return 'controller' in props;
52
+ }
53
+ };
88
54
  }
@@ -1,4 +1,5 @@
1
1
  import { Observable } from 'rxjs';
2
+ import { Popup } from '../Popup';
2
3
  import { MenuItem } from './MenuItem';
3
4
  export declare function useMenuController<TItemId extends string = string, TContext = any>(items?: ReadonlyArray<MenuItem<TItemId>>): MenuController<TItemId, TContext>;
4
5
  export declare class MenuController<TItemId extends string, TContext = any> {
@@ -6,17 +7,18 @@ export declare class MenuController<TItemId extends string, TContext = any> {
6
7
  private _items?;
7
8
  private _selectedItem?;
8
9
  private _anchor?;
10
+ private _open;
9
11
  constructor(items?: ReadonlyArray<MenuItem<TItemId>>);
10
12
  get items(): ReadonlyArray<MenuItem<TItemId>>;
11
13
  set items(items: ReadonlyArray<MenuItem<TItemId>> | undefined);
12
14
  get selectedItem(): TItemId | undefined;
13
15
  set selectedItem(item: TItemId | undefined);
14
- get anchor(): string | undefined;
16
+ get anchor(): Popup.Anchor | undefined;
15
17
  private _context?;
16
18
  get context(): TContext | undefined;
17
19
  get changed$(): Observable<Date>;
18
20
  get isOpen(): boolean;
19
- open(anchor: string, context?: TContext): void;
21
+ open(anchor?: Popup.Anchor, context?: TContext): void;
20
22
  close(): void;
21
23
  private raiseChange;
22
24
  }
@@ -26,6 +26,7 @@ class MenuController {
26
26
  // initialize instance variables
27
27
  this._changed$ = new rxjs_1.Subject();
28
28
  this._items = items;
29
+ this._open = false;
29
30
  }
30
31
  get items() {
31
32
  var _a;
@@ -52,15 +53,17 @@ class MenuController {
52
53
  return this._changed$;
53
54
  }
54
55
  get isOpen() {
55
- return !!this._anchor;
56
+ return this._open;
56
57
  }
57
58
  open(anchor, context) {
58
59
  this._anchor = anchor;
59
60
  this._context = context;
61
+ this._open = true;
60
62
  this.raiseChange();
61
63
  }
62
64
  close() {
63
65
  delete this._anchor;
66
+ this._open = false;
64
67
  this.raiseChange();
65
68
  }
66
69
  raiseChange() {
@@ -23,7 +23,7 @@ class CollectionFieldProxy {
23
23
  this._syncing = false;
24
24
  // initialize name
25
25
  const data = this.dataFrom(initialData);
26
- const name = (data === null || data === void 0 ? void 0 : data.name) || '';
26
+ const name = (data === null || data === void 0 ? void 0 : data.name) || this.schema.name;
27
27
  this.nameField = new funnel_core_1.Field({
28
28
  id: 'name',
29
29
  name: 'Name',
@@ -12,8 +12,6 @@ class Collections {
12
12
  this.schemas = funnel_core_1.Schema.Site.current().collections;
13
13
  this._eventBus = new funnel_core_1.EventBus();
14
14
  this._state = 'uninitialized';
15
- // start initial loading of data
16
- this.sync().catch(console.error);
17
15
  // listen to app state for page changes
18
16
  this._subscription = this.appState.collectionEvents$.subscribe(e => this.onCollectionEvent(e));
19
17
  }
@@ -43,6 +43,7 @@ export declare namespace ICollection {
43
43
  updatedOn: number;
44
44
  publishedOn?: number;
45
45
  };
46
+ type Savable = FieldModel;
46
47
  type References = {
47
48
  collections: Schema.Collection.Data.AsLink[];
48
49
  assets: Asset[];
@@ -1,4 +1,4 @@
1
- import { EventBus, Field, FieldList, Language, ObjectField, Schema } from '@nascentdigital/funnel-core';
1
+ import { EventBus, Field, FieldList, FieldModel, Language, ObjectField, Schema } from '@nascentdigital/funnel-core';
2
2
  import type { Observable } from 'rxjs';
3
3
  import type { Asset } from './Asset';
4
4
  import type { Block } from './Block';
@@ -34,6 +34,7 @@ export interface IPage extends IAssetStore, ICollectionStore, IPageRefStore, ITa
34
34
  export declare namespace IPage {
35
35
  type Content = ReadonlyArray<Block | Section>;
36
36
  type Area = 'discover' | 'content';
37
+ type Savable = Section | Block | FieldModel;
37
38
  type Ref = {
38
39
  template: Schema.Page;
39
40
  id: Schema.Page.Id;
@@ -51,6 +52,9 @@ export declare namespace IPage {
51
52
  updatedOn: number;
52
53
  publishedOn?: number;
53
54
  };
55
+ namespace Ref {
56
+ function fromData({ tags, ...data }: Schema.Page.Data.AsLink): Ref;
57
+ }
54
58
  type References = {
55
59
  pages: Ref[];
56
60
  collections: Schema.Collection.Data.AsLink[];
@@ -69,4 +73,5 @@ export declare namespace IPage {
69
73
  function filter(event: EventBus.Event): event is Event;
70
74
  function create(event: EventBus.Args<Event>): Event;
71
75
  }
76
+ function getPreviewUrl(path: string): URL;
72
77
  }