@nascentdigital/funnel-editor 4.5.7 → 4.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/dist/collection/hooks/CollectionController.d.ts +1 -1
  2. package/dist/core/components/ColorModeToggle.js +6 -4
  3. package/dist/core/components/Header.js +3 -2
  4. package/dist/core/components/UserEditor.d.ts +2 -2
  5. package/dist/core/components/feedback/Badge.d.ts +2 -1
  6. package/dist/core/components/feedback/Badge.js +4 -3
  7. package/dist/core/components/fields/DynamicPagesEditor.js +7 -6
  8. package/dist/core/components/fields/EmptyFieldCard.js +4 -4
  9. package/dist/core/components/fields/FieldCardLayout.js +5 -5
  10. package/dist/core/components/fields/FieldHeader.js +3 -2
  11. package/dist/core/components/fields/FieldsPanel.js +4 -4
  12. package/dist/core/components/fields/FormEditor.js +5 -4
  13. package/dist/core/components/fields/asset/AssetEditor.d.ts +3 -2
  14. package/dist/core/components/fields/asset/AssetEditor.js +1 -1
  15. package/dist/core/components/fields/asset/AssetUploader.d.ts +3 -2
  16. package/dist/core/components/fields/asset/AssetUploader.js +1 -1
  17. package/dist/core/components/fields/collection/CollectionCard.js +1 -11
  18. package/dist/core/components/fields/collection/CollectionPicker.js +3 -2
  19. package/dist/core/components/fields/collection/previews/index.d.ts +0 -1
  20. package/dist/core/components/fields/collection/previews/index.js +0 -1
  21. package/dist/core/components/fields/embed/EmbeddedVideoEditor.d.ts +2 -2
  22. package/dist/core/components/fields/factories/AssetFactory.d.ts +1 -1
  23. package/dist/core/components/fields/factories/CollectionFactory.d.ts +1 -1
  24. package/dist/core/components/fields/factories/EmbeddedVideoFactory.d.ts +2 -2
  25. package/dist/core/components/fields/factories/FieldValueFactory.d.ts +1 -1
  26. package/dist/core/components/fields/factories/FieldValueFactory.js +1 -1
  27. package/dist/core/components/fields/factories/LinkFactory.d.ts +2 -2
  28. package/dist/core/components/fields/factories/TextFactory.d.ts +2 -2
  29. package/dist/core/components/fields/form/FormFieldEditor.d.ts +3 -2
  30. package/dist/core/components/fields/index.d.ts +1 -0
  31. package/dist/core/components/fields/index.js +1 -0
  32. package/dist/core/components/fields/link/LinkEditor.d.ts +2 -2
  33. package/dist/core/components/fields/link/LinkEditor.js +4 -0
  34. package/dist/core/components/fields/list/CreateFieldButton.d.ts +1 -1
  35. package/dist/core/components/fields/list/CreateFieldButton.js +4 -5
  36. package/dist/core/components/fields/list/CreateFieldCard.js +4 -4
  37. package/dist/core/components/fields/page/PagePicker.js +4 -2
  38. package/dist/core/components/fields/richtext/FloatingToolbarPlugin.js +3 -2
  39. package/dist/core/components/fields/richtext/LinkEditor.js +17 -4
  40. package/dist/core/components/fields/richtext/LinkPopup.js +11 -7
  41. package/dist/core/components/interaction/AvatarButton.d.ts +2 -1
  42. package/dist/core/components/interaction/AvatarButton.js +3 -2
  43. package/dist/core/components/interaction/Button.d.ts +2 -0
  44. package/dist/core/components/interaction/Button.js +3 -2
  45. package/dist/core/components/interaction/Combobox.js +2 -2
  46. package/dist/core/components/interaction/IconButton.d.ts +2 -0
  47. package/dist/core/components/interaction/IconButton.js +3 -2
  48. package/dist/core/components/interaction/IconLink.d.ts +1 -1
  49. package/dist/core/components/interaction/MiniEditor.d.ts +3 -2
  50. package/dist/core/components/interaction/MiniEditor.js +7 -5
  51. package/dist/core/components/interaction/Popup.d.ts +20 -15
  52. package/dist/core/components/interaction/Popup.js +63 -66
  53. package/dist/core/components/interaction/QuickInput.js +2 -0
  54. package/dist/core/components/interaction/QuickPicker.js +4 -4
  55. package/dist/core/components/interaction/Tabs.d.ts +5 -1
  56. package/dist/core/components/interaction/Tabs.js +18 -8
  57. package/dist/core/components/interaction/menu/useMenuController.d.ts +2 -2
  58. package/dist/core/components/interaction/table/TableItem.d.ts +2 -1
  59. package/dist/core/components/interaction/table/TableItem.js +5 -3
  60. package/dist/core/components/layout/InfoPanel.js +4 -2
  61. package/dist/core/components/visuals/Icon.d.ts +1 -1
  62. package/dist/core/components/visuals/Icon.js +6 -0
  63. package/dist/core/components/visuals/index.d.ts +0 -1
  64. package/dist/core/components/visuals/index.js +0 -1
  65. package/dist/core/domain/Block.d.ts +4 -0
  66. package/dist/core/domain/Block.js +7 -0
  67. package/dist/core/domain/BlockConfiguration.d.ts +9 -2
  68. package/dist/core/domain/BlockConfiguration.js +49 -12
  69. package/dist/core/domain/CollectionBrowser.d.ts +2 -2
  70. package/dist/core/domain/CollectionFieldProxy.d.ts +7 -2
  71. package/dist/core/domain/CollectionFieldProxy.js +55 -66
  72. package/dist/core/domain/SectionBlock.d.ts +5 -0
  73. package/dist/core/domain/SectionBlock.js +15 -0
  74. package/dist/core/hooks/useBlockConfiguration.d.ts +7 -1
  75. package/dist/core/hooks/useBlockConfiguration.js +8 -1
  76. package/dist/core/hooks/usePage.d.ts +2 -2
  77. package/dist/core/hooks/usePage.js +5 -4
  78. package/dist/core/repository/CollectionRepository.js +1 -1
  79. package/dist/core/repository/CollectionSerializer.d.ts +3 -2
  80. package/dist/core/repository/CollectionSerializer.js +12 -7
  81. package/dist/core/repository/PageRepository.js +2 -2
  82. package/dist/core/repository/PageSerializer.d.ts +5 -3
  83. package/dist/core/repository/PageSerializer.js +10 -11
  84. package/dist/explore/components/CreateCollectionDialog.d.ts +2 -3
  85. package/dist/explore/components/CreateCollectionDialog.js +1 -1
  86. package/dist/explore/components/CreatePageDialog.d.ts +3 -3
  87. package/dist/explore/components/CreatePageDialog.js +2 -2
  88. package/dist/explore/screens/CollectionExplorer.js +4 -4
  89. package/dist/explore/screens/PageExplorer.js +4 -4
  90. package/dist/page/components/BlockEditor.js +10 -2
  91. package/dist/page/components/config/BlockConfigButton.d.ts +8 -0
  92. package/dist/page/components/config/BlockConfigButton.js +320 -0
  93. package/dist/page/components/config/BlockConfigurationProvider.d.ts +8 -0
  94. package/dist/page/components/config/BlockConfigurationProvider.js +17 -0
  95. package/dist/page/components/config/LegacyBlockPreview.d.ts +8 -0
  96. package/dist/page/components/config/{BlockPreview.js → LegacyBlockPreview.js} +30 -40
  97. package/dist/page/components/config/index.d.ts +3 -1
  98. package/dist/page/components/config/index.js +3 -1
  99. package/dist/page/components/index.d.ts +1 -1
  100. package/dist/page/components/index.js +1 -1
  101. package/dist/page/components/nav/NavSection.js +4 -3
  102. package/dist/page/components/panels/BlockConfigPanel.d.ts +1 -0
  103. package/dist/page/components/panels/BlockConfigPanel.js +25 -0
  104. package/dist/page/components/{PageStatus.d.ts → panels/PageStatus.d.ts} +3 -3
  105. package/dist/page/components/{PageStatus.js → panels/PageStatus.js} +10 -14
  106. package/dist/page/components/panels/index.d.ts +2 -0
  107. package/dist/page/components/{status → panels}/index.js +2 -1
  108. package/dist/page/hooks/PageController.d.ts +2 -2
  109. package/dist/page/screens/PageEditor.js +8 -1
  110. package/dist/styles/index.css +153 -48
  111. package/dist/styles/tailwind.js +7 -3
  112. package/dist/users/screens/UserExplorer.js +7 -6
  113. package/package.json +3 -2
  114. package/dist/core/components/fields/collection/previews/ClientPreview.d.ts +0 -10
  115. package/dist/core/components/fields/collection/previews/ClientPreview.js +0 -29
  116. package/dist/core/components/visuals/SkeletonLayout.d.ts +0 -9
  117. package/dist/core/components/visuals/SkeletonLayout.js +0 -429
  118. package/dist/page/components/config/BlockConfig.d.ts +0 -8
  119. package/dist/page/components/config/BlockConfig.js +0 -28
  120. package/dist/page/components/config/BlockConfigEditor.d.ts +0 -9
  121. package/dist/page/components/config/BlockConfigEditor.js +0 -129
  122. package/dist/page/components/config/BlockPreview.d.ts +0 -10
  123. package/dist/page/components/config/BlockView.d.ts +0 -4
  124. package/dist/page/components/config/BlockView.js +0 -9
  125. package/dist/page/components/config/LegacyBlockConfigEditor.d.ts +0 -9
  126. package/dist/page/components/config/LegacyBlockConfigEditor.js +0 -27
  127. package/dist/page/components/config/ListPanelEditor.d.ts +0 -8
  128. package/dist/page/components/config/ListPanelEditor.js +0 -102
  129. package/dist/page/components/config/MessagePanelEditor.d.ts +0 -8
  130. package/dist/page/components/config/MessagePanelEditor.js +0 -17
  131. package/dist/page/components/config/VisualPanelEditor.d.ts +0 -8
  132. package/dist/page/components/config/VisualPanelEditor.js +0 -76
  133. package/dist/page/components/status/index.d.ts +0 -1
  134. /package/dist/page/components/{status → panels}/AutoSave.d.ts +0 -0
  135. /package/dist/page/components/{status → panels}/AutoSave.js +0 -0
@@ -18,6 +18,7 @@ __exportStar(require("./asset/AssetPreview"), exports);
18
18
  __exportStar(require("./DateField"), exports);
19
19
  __exportStar(require("./FieldEditor"), exports);
20
20
  __exportStar(require("./FieldErrorController"), exports);
21
+ __exportStar(require("./FieldHeader"), exports);
21
22
  __exportStar(require("./FieldSize"), exports);
22
23
  __exportStar(require("./FieldsPanel"), exports);
23
24
  __exportStar(require("./RichTextEditor"), exports);
@@ -1,4 +1,4 @@
1
- import { Language, Rect, Schema } from '@nascentdigital/funnel-core';
1
+ import { Language, Schema } from '@nascentdigital/funnel-core';
2
2
  export declare const LinkEditor: import("react").ForwardRefExoticComponent<LinkEditor.Props & import("react").RefAttributes<LinkEditor.Ref>>;
3
3
  export declare namespace LinkEditor {
4
4
  type Props = {
@@ -11,6 +11,6 @@ export declare namespace LinkEditor {
11
11
  type Options = {
12
12
  schema: Schema.LinkField;
13
13
  initialValue?: Schema.Field.Data<Schema.LinkField>;
14
- anchor: HTMLElement | Rect;
14
+ anchor: string;
15
15
  };
16
16
  }
@@ -216,6 +216,10 @@ exports.LinkEditor = (0, react_1.forwardRef)(function LinkEditor({ region, langu
216
216
  // touch
217
217
  touch();
218
218
  };
219
+ // skip if params are missing
220
+ if (!anchor) {
221
+ return null;
222
+ }
219
223
  // render
220
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 &&
221
225
  (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
@@ -1,6 +1,6 @@
1
1
  import { Callback, Schema } from '@nascentdigital/funnel-core';
2
2
  import { Button } from '../../interaction';
3
- export declare function CreateFieldButton({ schema, onCreated, onEditing, children, ...props }: CreateFieldButton.Props): import("react/jsx-runtime").JSX.Element;
3
+ export declare function CreateFieldButton({ schema, className, onCreated, onEditing, children, ...props }: CreateFieldButton.Props): import("react/jsx-runtime").JSX.Element;
4
4
  export declare namespace CreateFieldButton {
5
5
  type Props = Omit<Button.Props, 'onClick' | 'variant' | 'iconLeft' | 'iconRight'> & {
6
6
  schema: Schema.Field.Type;
@@ -19,11 +19,10 @@ const interaction_1 = require("../../interaction");
19
19
  const factories_1 = require("../factories");
20
20
  // component
21
21
  function CreateFieldButton(_a) {
22
- var { schema, onCreated, onEditing = funnel_core_1.Fn.NoOp, children } = _a, props = __rest(_a, ["schema", "onCreated", "onEditing", "children"]);
22
+ var { schema, className, onCreated, onEditing = funnel_core_1.Fn.NoOp, children } = _a, props = __rest(_a, ["schema", "className", "onCreated", "onEditing", "children"]);
23
23
  // bind props + state
24
24
  const [creating, setCreating] = (0, react_1.useState)(false);
25
- const rootElementRef = (0, react_1.useRef)(null);
26
- const rootElement = rootElementRef.current;
25
+ const id = (0, react_1.useId)();
27
26
  const onCreatedRef = (0, react_1.useRef)(onCreated);
28
27
  onCreatedRef.current = onCreated;
29
28
  // helpers
@@ -40,6 +39,6 @@ function CreateFieldButton(_a) {
40
39
  setCreating(false);
41
40
  };
42
41
  // render
43
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(interaction_1.Button, Object.assign({}, props, { ref: rootElementRef, onClick: onCreateStart, variant: "text", iconLeft: "Plus", children: children })), creating && rootElement &&
44
- (0, jsx_runtime_1.jsx)(factories_1.FieldValueFactory, { itemSchema: schema, anchor: rootElement, onCommit: onCreate, onCancel: onCreateCancel })] }));
42
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(interaction_1.Button, Object.assign({}, props, { anchorId: id, onClick: onCreateStart, variant: "text", iconLeft: "Plus", children: children })), creating &&
43
+ (0, jsx_runtime_1.jsx)(factories_1.FieldValueFactory, { itemSchema: schema, anchor: id, onCommit: onCreate, onCancel: onCreateCancel })] }));
45
44
  }
@@ -9,6 +9,7 @@ const funnel_core_1 = require("@nascentdigital/funnel-core");
9
9
  const client_1 = require("@nascentdigital/funnel-ui/client");
10
10
  const classnames_1 = __importDefault(require("classnames"));
11
11
  const react_1 = require("react");
12
+ const interaction_1 = require("../../interaction");
12
13
  const visuals_1 = require("../../visuals");
13
14
  const factories_1 = require("../factories");
14
15
  // component
@@ -16,8 +17,7 @@ function CreateFieldCard({ className, schema, field, onClick, onCreated = funnel
16
17
  // bind props + state
17
18
  const { name } = schema;
18
19
  const [creating, setCreating] = (0, react_1.useState)(false);
19
- const rootElementRef = (0, react_1.useRef)(null);
20
- const rootElement = rootElementRef.current;
20
+ const id = (0, react_1.useId)();
21
21
  const onCreatedRef = (0, react_1.useRef)(onCreated);
22
22
  onCreatedRef.current = onCreated;
23
23
  // helpers
@@ -47,6 +47,6 @@ function CreateFieldCard({ className, schema, field, onClick, onCreated = funnel
47
47
  onCreatedRef.current(data);
48
48
  };
49
49
  // render
50
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("section", { ref: rootElementRef, className: (0, classnames_1.default)(className, 'h-full outline outline-1 outline-transparent overflow-hidden cursor-pointer interpolate', 'bg-surface1 border border-dashed border-border-l1 rounded-md', 'hover:bg-ix-primary-hover/tint0 hover:border-ix-primary hover:border-solid', 'focus-visible:bg-ix-primary-hover/tint0 focus-visible:border-ix-primary focus-visible:border-solid focus-visible:outline-ix-primary', 'active:scale-[.97] active:interpolate-fast'), onClick: onCreateStart, onKeyDown: client_1.OnKey.enter(onCreateStart), tabIndex: 0, children: (0, jsx_runtime_1.jsx)("div", { className: "h-full flex flex-col justify-center items-center pointer-events-none interpolate", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-center gap-l5 p-l5", children: [(0, jsx_runtime_1.jsx)("div", { className: "p-l5 text-ix-secondary bg-ix-primary rounded-full", children: (0, jsx_runtime_1.jsx)(visuals_1.Icon, { variant: "Plus", size: "sm" }) }), (0, jsx_runtime_1.jsxs)("span", { className: "block label-md text-content-primary text-center", children: ["Add ", name] })] }) }) }), !onClick && creating && rootElement &&
51
- (0, jsx_runtime_1.jsx)(factories_1.FieldValueFactory, { anchor: rootElement, itemSchema: schema, field: field, onCommit: onCreateComplete, onCancel: onCreateCancel })] }));
50
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(interaction_1.Popup.AnchorElement, { tag: "div", anchorId: id, className: (0, classnames_1.default)(className, 'h-full outline outline-1 outline-transparent overflow-hidden cursor-pointer interpolate', 'bg-surface1 border border-dashed border-border-l1 rounded-md', 'hover:bg-ix-primary-hover/tint0 hover:border-ix-primary hover:border-solid', 'focus-visible:bg-ix-primary-hover/tint0 focus-visible:border-ix-primary focus-visible:border-solid focus-visible:outline-ix-primary', 'active:scale-[.97] active:interpolate-fast'), onClick: onCreateStart, onKeyDown: client_1.OnKey.enter(onCreateStart), tabIndex: 0, children: (0, jsx_runtime_1.jsx)("div", { className: "h-full flex flex-col justify-center items-center pointer-events-none interpolate", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-center gap-l5 p-l5", children: [(0, jsx_runtime_1.jsx)("div", { className: "p-l5 text-ix-secondary bg-ix-primary rounded-full", children: (0, jsx_runtime_1.jsx)(visuals_1.Icon, { variant: "Plus", size: "sm" }) }), (0, jsx_runtime_1.jsxs)("span", { className: "block label-md text-content-primary text-center", children: ["Add ", name] })] }) }) }), !onClick && creating &&
51
+ (0, jsx_runtime_1.jsx)(factories_1.FieldValueFactory, { anchor: id, itemSchema: schema, field: field, onCommit: onCreateComplete, onCancel: onCreateCancel })] }));
52
52
  }
@@ -256,7 +256,7 @@ function renderPicker({ site, language, disabledIds, error, pageFilters, pageFil
256
256
  }
257
257
  }
258
258
  function renderPageRef({ language, template, disabledIds, ref, onPick, setTagTooltip }) {
259
- var _a, _b;
259
+ var _a, _b, _c;
260
260
  // resolve props
261
261
  const title = (_a = ref === null || ref === void 0 ? void 0 : ref.name) !== null && _a !== void 0 ? _a : template.name;
262
262
  const path = (ref === null || ref === void 0 ? void 0 : ref.slug) ? `/${ref.slug}` : funnel_core_1.Localized.Maybe.get(template.route, language);
@@ -278,11 +278,13 @@ function renderPageRef({ language, template, disabledIds, ref, onPick, setTagToo
278
278
  }
279
279
  };
280
280
  // render
281
+ const id = (_b = ref === null || ref === void 0 ? void 0 : ref.id) !== null && _b !== void 0 ? _b : template.type;
282
+ const anchorId = `page-picker-tip-${id}`;
281
283
  return ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)('flex items-center px-l7 py-l4 select-none interpolate', 'even:bg-modal-background rounded-md', {
282
284
  'hover:bg-modal-surface2/tint2 cursor-pointer': !disabled,
283
285
  'cursor-default': disabled
284
286
  }), onClick: onClick, tabIndex: disabled ? undefined : 0, children: (0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)('w-full flex items-center gap-l8 select-none interpolate', {
285
287
  'opacity-disabled': disabled
286
288
  }), onClick: onClick, children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex-1 shrink-0 flex flex-col", children: [(0, jsx_runtime_1.jsx)("h3", { className: "label-sm text-content-primary ellipsis", children: title }), (0, jsx_runtime_1.jsx)("span", { className: "label-xs text-content-tertiary ellipsis", children: path })] }), tags.length > 0 &&
287
- (0, jsx_runtime_1.jsxs)("div", { className: "shrink-0 flex items-center gap-l4", children: [visibleTags.map(tag => (0, jsx_runtime_1.jsx)(feedback_1.Badge, { variant: "outlinedTiny", status: "draft", label: tag.name }, tag.data)), tooltipTags.length > 0 && ((0, jsx_runtime_1.jsx)(feedback_1.Badge, { variant: "outlinedTiny", status: "draft", label: `+${tooltipTags.length}`, onPointerEnter: e => setTagTooltip({ anchor: e.currentTarget, tags: tooltipTags }), onPointerLeave: () => setTagTooltip(undefined) }))] })] }) }, (_b = ref === null || ref === void 0 ? void 0 : ref.id) !== null && _b !== void 0 ? _b : template.type));
289
+ (0, jsx_runtime_1.jsxs)("div", { className: "shrink-0 flex items-center gap-l4", children: [visibleTags.map(tag => (0, jsx_runtime_1.jsx)(feedback_1.Badge, { variant: "outlinedTiny", status: "draft", label: tag.name }, tag.data)), tooltipTags.length > 0 && ((0, jsx_runtime_1.jsx)(feedback_1.Badge, { anchorId: anchorId, variant: "outlinedTiny", status: "draft", label: `+${tooltipTags.length}`, onPointerEnter: e => setTagTooltip({ anchor: anchorId, tags: tooltipTags }), onPointerLeave: () => setTagTooltip(undefined) }))] })] }) }, (_c = ref === null || ref === void 0 ? void 0 : ref.id) !== null && _c !== void 0 ? _c : template.type));
288
290
  }
@@ -16,6 +16,7 @@ function FloatingToolbarPlugin({ options }) {
16
16
  const [open, setOpen] = (0, react_1.useState)(false);
17
17
  const [anchorRect, setAnchorRect] = (0, react_1.useState)();
18
18
  const [editor] = (0, LexicalComposerContext_1.useLexicalComposerContext)();
19
+ const id = (0, react_1.useId)();
19
20
  const toolbarActiveRef = (0, react_1.useRef)(false);
20
21
  // register commands
21
22
  (0, react_1.useEffect)(() => {
@@ -56,7 +57,7 @@ function FloatingToolbarPlugin({ options }) {
56
57
  .pipe((0, rxjs_1.debounce)(({ open }) => open ? (0, rxjs_1.interval)(200) : (0, rxjs_1.interval)(0)))
57
58
  .subscribe(({ open, anchor }) => {
58
59
  // update open state
59
- setAnchorRect(anchor);
60
+ setAnchorRect(prevAnchor => anchor !== null && anchor !== void 0 ? anchor : prevAnchor);
60
61
  setOpen(open);
61
62
  // ignore command if unchanged
62
63
  if (wasOpen !== open) {
@@ -75,7 +76,7 @@ function FloatingToolbarPlugin({ options }) {
75
76
  return () => subscription.unsubscribe();
76
77
  }, [editor, openEvent$]);
77
78
  // render nothing
78
- return ((0, jsx_runtime_1.jsx)(interaction_1.Popup, { className: "bg-surface2 p-l5 border border-solid border-border-l2 rounded-full shadow-popup", open: open, anchor: anchorRect, anchorOffset: 8, placement: "top", disableOverlay: true, onClose: () => openEvent$.next({ open: false }), children: (0, jsx_runtime_1.jsx)(Toolbar_1.Toolbar, { options: options, onInteractionChange: state => toolbarActiveRef.current = state !== 'none' }) }));
79
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(interaction_1.Popup.AnchorElement, { tag: "div", anchorId: id, className: "fixed pointer-events-none opacity-none", style: interaction_1.Popup.getAnchorFrame(anchorRect) }), (0, jsx_runtime_1.jsx)(interaction_1.Popup, { className: "bg-surface2 p-l5 border border-solid border-border-l2 rounded-full shadow-popup", open: open, anchor: id, anchorOffset: 8, placement: "top", disableOverlay: true, onClose: () => openEvent$.next({ open: false }), children: (0, jsx_runtime_1.jsx)(Toolbar_1.Toolbar, { options: options, onInteractionChange: state => toolbarActiveRef.current = state !== 'none' }) })] }));
79
80
  }
80
81
  // extension
81
82
  (function (FloatingToolbarPlugin) {
@@ -1,4 +1,7 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.LinkEditor = LinkEditor;
4
7
  const jsx_runtime_1 = require("react/jsx-runtime");
@@ -6,6 +9,7 @@ const link_1 = require("@lexical/link");
6
9
  const LexicalComposerContext_1 = require("@lexical/react/LexicalComposerContext");
7
10
  const utils_1 = require("@lexical/utils");
8
11
  const funnel_core_1 = require("@nascentdigital/funnel-core");
12
+ const classnames_1 = __importDefault(require("classnames"));
9
13
  const lexical_1 = require("lexical");
10
14
  const react_1 = require("react");
11
15
  const interaction_1 = require("../../interaction");
@@ -13,6 +17,8 @@ const interaction_1 = require("../../interaction");
13
17
  function LinkEditor() {
14
18
  // bind state + hooks
15
19
  const [editor] = (0, LexicalComposerContext_1.useLexicalComposerContext)();
20
+ const id = (0, react_1.useId)();
21
+ const anchorRef = (0, react_1.useRef)(null);
16
22
  const linkInputRef = (0, react_1.useRef)(null);
17
23
  // handle listener
18
24
  (0, react_1.useEffect)(() => {
@@ -28,17 +34,24 @@ function LinkEditor() {
28
34
  const [selectedNode] = (_a = selection === null || selection === void 0 ? void 0 : selection.getNodes()) !== null && _a !== void 0 ? _a : [];
29
35
  let anchorNode = selectedNode && funnel_core_1.LexicalUtils.findContainer(selectedNode, [link_1.LinkNode]);
30
36
  const anchorUrl = anchorNode === null || anchorNode === void 0 ? void 0 : anchorNode.getURL();
31
- const anchor = funnel_core_1.LexicalUtils.getSelectionRect({ editor, selection, coerce: true, allowEmpty: true });
32
- if (!anchor) {
37
+ const anchorRect = funnel_core_1.LexicalUtils.getSelectionRect({ editor, selection, coerce: true, allowEmpty: true });
38
+ const anchorFrame = interaction_1.Popup.getAnchorFrame(anchorRect);
39
+ const anchor = anchorRef.current;
40
+ if (!anchorFrame || !anchor) {
33
41
  return true;
34
42
  }
35
43
  // raise opened
36
44
  editor.dispatchCommand(LinkEditor.OPENED_COMMAND, undefined);
45
+ // reposition anchor
46
+ anchor.style.left = anchorFrame.left;
47
+ anchor.style.top = anchorFrame.top;
48
+ anchor.style.width = anchorFrame.width;
49
+ anchor.style.height = anchorFrame.height;
37
50
  // open link input
38
51
  linkInput
39
52
  .open({
40
53
  schema: linkSchema,
41
- anchor,
54
+ anchor: id,
42
55
  initialValue: anchorUrl,
43
56
  placement: 'top',
44
57
  anchorOffset: 2
@@ -93,7 +106,7 @@ function LinkEditor() {
93
106
  }, lexical_1.COMMAND_PRIORITY_EDITOR));
94
107
  }, [editor]);
95
108
  // render
96
- return ((0, jsx_runtime_1.jsx)(interaction_1.QuickInput, { ref: linkInputRef }));
109
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { ref: anchorRef, className: (0, classnames_1.default)(interaction_1.Popup.anchorClassName, 'fixed pointer-events-none opacity-none'), style: interaction_1.Popup.getAnchorStyle(id) }), (0, jsx_runtime_1.jsx)(interaction_1.QuickInput, { ref: linkInputRef })] }));
97
110
  }
98
111
  // extension
99
112
  (function (LinkEditor) {
@@ -23,9 +23,11 @@ function LinkPopup() {
23
23
  var _a, _b;
24
24
  // bind state + hooks
25
25
  const [linkContext, setLinkContext] = (0, react_1.useState)();
26
+ const [linkAnchorRect, setLinkAnchorRect] = (0, react_1.useState)();
26
27
  const [editingLink, setEditingLink] = (0, react_1.useState)(false);
27
28
  const [toolbarVisible, setToolbarVisible] = (0, react_1.useState)(false);
28
29
  const [ready, setReady] = (0, react_1.useState)(false);
30
+ const id = (0, react_1.useId)();
29
31
  const { activeRef, active } = (0, useEditorActive_1.useEditorActive)();
30
32
  const linkContextRef = (0, react_1.useRef)(linkContext);
31
33
  linkContextRef.current = linkContext;
@@ -65,13 +67,15 @@ function LinkPopup() {
65
67
  const linkContext = linkContextRef.current;
66
68
  if (linkKey !== lastLinkKeyRef.current || !!linkContext) {
67
69
  setLastLinkKey(linkKey);
70
+ const anchorRect = linkKey === lastLinkKeyRef.current
71
+ ? (_a = linkContext === null || linkContext === void 0 ? void 0 : linkContext.anchor) !== null && _a !== void 0 ? _a : anchor
72
+ : anchor;
68
73
  setLinkContext({
69
- anchor: linkKey === lastLinkKeyRef.current
70
- ? (_a = linkContext === null || linkContext === void 0 ? void 0 : linkContext.anchor) !== null && _a !== void 0 ? _a : anchor
71
- : anchor,
74
+ anchor: anchorRect,
72
75
  url: linkNode.getURL(),
73
76
  label: linkNode.getTextContent()
74
77
  });
78
+ setLinkAnchorRect(anchorRect);
75
79
  }
76
80
  }
77
81
  // or close/clear
@@ -155,10 +159,10 @@ function LinkPopup() {
155
159
  editor.dispatchCommand(LinkPopup.CLOSED_COMMAND, undefined);
156
160
  };
157
161
  // render
158
- return ((0, jsx_runtime_1.jsxs)(interaction_1.Popup, { className: (0, classnames_1.default)('glass-overlay h-36 w-[330px] flex items-center gap-l5 px-l5 interpolate', 'border-t border-solid border-glass-stroke-l1 rounded-full', {
159
- 'opacity-none': !ready,
160
- 'opacity-full': ready
161
- }), open: !!linkContext && !editingLink && !toolbarVisible, anchor: linkContext === null || linkContext === void 0 ? void 0 : linkContext.anchor, anchorOffset: 4, placement: "top", animation: "out", disableOverlay: true, onOpened: onOpened, onClosed: onClosed, children: [(0, jsx_runtime_1.jsx)(link_2.default, { className: (0, classnames_1.default)('flex-1 self-stretch flex items-center cursor-pointer', 'body-sm text-content-tertiary align-middle ellipsis'), href: (_a = linkContext === null || linkContext === void 0 ? void 0 : linkContext.url) !== null && _a !== void 0 ? _a : '#', target: "_blank", children: (_b = linkContext === null || linkContext === void 0 ? void 0 : linkContext.url) !== null && _b !== void 0 ? _b : '' }), (0, jsx_runtime_1.jsx)("div", { className: "h-20 divider-y" }), (0, jsx_runtime_1.jsx)(interaction_1.IconButton, { icon: "Pencil", size: "xs", onClick: onEdit }), (0, jsx_runtime_1.jsx)(interaction_1.IconButton, { icon: "Trash", size: "xs", onClick: onDelete })] }));
162
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(interaction_1.Popup.AnchorElement, { tag: "div", anchorId: id, className: "fixed pointer-events-none opacity-none", style: interaction_1.Popup.getAnchorFrame(linkAnchorRect) }), (0, jsx_runtime_1.jsxs)(interaction_1.Popup, { className: (0, classnames_1.default)('glass-overlay h-36 w-[330px] flex items-center gap-l5 px-l5 interpolate', 'border-t border-solid border-glass-stroke-l1 rounded-full', {
163
+ 'opacity-none': !ready,
164
+ 'opacity-full': ready
165
+ }), open: !!linkContext && !editingLink && !toolbarVisible, anchor: id, anchorOffset: 4, placement: "top", animation: "out", disableOverlay: true, onOpened: onOpened, onClosed: onClosed, children: [(0, jsx_runtime_1.jsx)(link_2.default, { className: (0, classnames_1.default)('flex-1 self-stretch flex items-center cursor-pointer', 'body-sm text-content-tertiary align-middle ellipsis'), href: (_a = linkContext === null || linkContext === void 0 ? void 0 : linkContext.url) !== null && _a !== void 0 ? _a : '#', target: "_blank", children: (_b = linkContext === null || linkContext === void 0 ? void 0 : linkContext.url) !== null && _b !== void 0 ? _b : '' }), (0, jsx_runtime_1.jsx)("div", { className: "h-20 divider-y" }), (0, jsx_runtime_1.jsx)(interaction_1.IconButton, { icon: "Pencil", size: "xs", onClick: onEdit }), (0, jsx_runtime_1.jsx)(interaction_1.IconButton, { icon: "Trash", size: "xs", onClick: onDelete })] })] }));
162
166
  }
163
167
  // extension
164
168
  (function (LinkPopup) {
@@ -1,9 +1,10 @@
1
1
  import { User } from '@nascentdigital/funnel-cms';
2
2
  import { HTMLAttributes } from 'react';
3
- export declare function AvatarButton({ className, user, disabled, ...props }: AvatarButton.Props): import("react/jsx-runtime").JSX.Element;
3
+ export declare function AvatarButton({ anchorId, className, style, user, disabled, ...props }: AvatarButton.Props): import("react/jsx-runtime").JSX.Element;
4
4
  export declare namespace AvatarButton {
5
5
  type Props = Omit<HTMLAttributes<HTMLButtonElement>, 'children'> & {
6
6
  user: User;
7
+ anchorId?: string;
7
8
  disabled?: boolean;
8
9
  };
9
10
  }
@@ -18,11 +18,12 @@ exports.AvatarButton = AvatarButton;
18
18
  const jsx_runtime_1 = require("react/jsx-runtime");
19
19
  const classnames_1 = __importDefault(require("classnames"));
20
20
  const react_1 = require("react");
21
+ const Popup_1 = require("./Popup");
21
22
  // component
22
23
  function AvatarButton(_a) {
23
- var { className, user, disabled = false } = _a, props = __rest(_a, ["className", "user", "disabled"]);
24
+ var { anchorId, className, style, user, disabled = false } = _a, props = __rest(_a, ["anchorId", "className", "style", "user", "disabled"]);
24
25
  // bind memos
25
26
  const initials = (0, react_1.useMemo)(() => user.username.substring(0, 1).toUpperCase() || '?', [user]);
26
27
  // render
27
- return ((0, jsx_runtime_1.jsx)("button", Object.assign({ className: (0, classnames_1.default)(className, 'iconbutton iconbutton-avatar iconbutton-sm'), disabled: disabled }, props, { children: (0, jsx_runtime_1.jsx)("span", { className: "heading-xs", children: initials }) })));
28
+ return ((0, jsx_runtime_1.jsx)("button", Object.assign({ className: (0, classnames_1.default)(className, anchorId ? Popup_1.Popup.anchorClassName : undefined, 'iconbutton iconbutton-avatar iconbutton-sm'), style: anchorId ? Popup_1.Popup.getAnchorStyle(anchorId, style) : style, disabled: disabled }, props, { children: (0, jsx_runtime_1.jsx)("span", { className: "heading-xs", children: initials }) })));
28
29
  }
@@ -1,6 +1,7 @@
1
1
  import { HTMLAttributes } from 'react';
2
2
  import { Icon } from '../visuals';
3
3
  export declare const Button: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLButtonElement> & {
4
+ anchorId?: string;
4
5
  variant?: Button.Variant;
5
6
  size?: Button.Size;
6
7
  iconLeft?: Icon.Variant;
@@ -10,6 +11,7 @@ export declare const Button: import("react").ForwardRefExoticComponent<HTMLAttri
10
11
  } & import("react").RefAttributes<HTMLButtonElement>>;
11
12
  export declare namespace Button {
12
13
  type Props = HTMLAttributes<HTMLButtonElement> & {
14
+ anchorId?: string;
13
15
  variant?: Variant;
14
16
  size?: Size;
15
17
  iconLeft?: Icon.Variant;
@@ -21,11 +21,12 @@ const classnames_1 = __importDefault(require("classnames"));
21
21
  const react_1 = require("react");
22
22
  const visuals_1 = require("../visuals");
23
23
  const Loader_1 = require("./Loader");
24
+ const Popup_1 = require("./Popup");
24
25
  // component
25
26
  exports.Button = (0, react_1.forwardRef)(function Button(_a, ref) {
26
- var { className, variant = 'primary', size = 'md', iconLeft, iconRight, loading = false, disabled = false, children } = _a, props = __rest(_a, ["className", "variant", "size", "iconLeft", "iconRight", "loading", "disabled", "children"]);
27
+ var { anchorId, className, style, variant = 'primary', size = 'md', iconLeft, iconRight, loading = false, disabled = false, children } = _a, props = __rest(_a, ["anchorId", "className", "style", "variant", "size", "iconLeft", "iconRight", "loading", "disabled", "children"]);
27
28
  // render
28
- return ((0, jsx_runtime_1.jsxs)("button", Object.assign({ ref: ref, className: (0, classnames_1.default)(className, getButtonClassnames({ variant, size, loading, disabled })), type: "button", disabled: disabled || loading }, props, { children: [loading &&
29
+ return ((0, jsx_runtime_1.jsxs)("button", Object.assign({ ref: ref, className: (0, classnames_1.default)(className, anchorId ? Popup_1.Popup.anchorClassName : undefined, getButtonClassnames({ variant, size, loading, disabled })), style: anchorId ? Popup_1.Popup.getAnchorStyle(anchorId, style) : style, type: "button", disabled: disabled || loading }, props, { children: [loading &&
29
30
  (0, jsx_runtime_1.jsx)(Loader_1.Loader, { size: "sm" }), iconLeft && !loading &&
30
31
  (0, jsx_runtime_1.jsx)(visuals_1.Icon, { variant: iconLeft, size: size }), children, iconRight &&
31
32
  (0, jsx_runtime_1.jsx)(visuals_1.Icon, { variant: iconRight, size: size })] })));
@@ -59,12 +59,12 @@ function Combobox({ id: externalId, className, size = 'md', maxRows = 6, rowHeig
59
59
  setOpen(false);
60
60
  };
61
61
  // render
62
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("button", { ref: buttonRef, id: id, className: (0, classnames_1.default)(className, 'flex items-center justify-between gap-l5 px-l5', 'bg-surface1 border border-solid border-border-l1 rounded-full select-none appearance-none', 'disabled:opacity-disabled', {
62
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("button", { ref: buttonRef, id: id, className: (0, classnames_1.default)(className, Popup_1.Popup.anchorClassName, 'flex items-center justify-between gap-l5 px-l5', 'bg-surface1 border border-solid border-border-l1 rounded-full select-none appearance-none', 'disabled:opacity-disabled', {
63
63
  'min-w-[200px] h-40': size === 'md',
64
64
  'min-w-[180px] h-32': size === 'sm',
65
65
  'min-w-[120px] h-24': size === 'xs',
66
66
  'pointer-events-none': open
67
- }), type: "button", disabled: disabled, role: "combobox", "aria-expanded": open, "aria-controls": popupId, "aria-owns": popupId, onClick: onOpen, onKeyDown: client_1.OnKey.enter(onOpen), children: [renderSelection(selectedOption), (0, jsx_runtime_1.jsx)(visuals_1.Icon, { className: "text-content-primary", variant: "ChevronDown" })] }), (0, jsx_runtime_1.jsx)(Popup_1.Popup, { open: open, anchor: button, anchorOffset: 2, placement: "bottom", onClose: onOptionsClose, children: (0, jsx_runtime_1.jsx)("div", { id: popupId, className: (0, classnames_1.default)('flex flex-col bg-surface2 shadow-popup overflow-y-scroll', {
67
+ }), style: Popup_1.Popup.getAnchorStyle(id), type: "button", disabled: disabled, role: "combobox", "aria-expanded": open, "aria-controls": popupId, "aria-owns": popupId, onClick: onOpen, onKeyDown: client_1.OnKey.enter(onOpen), children: [renderSelection(selectedOption), (0, jsx_runtime_1.jsx)(visuals_1.Icon, { className: "text-content-primary", variant: "ChevronDown" })] }), (0, jsx_runtime_1.jsx)(Popup_1.Popup, { open: open, anchor: id, anchorOffset: 2, placement: "bottom", onClose: onOptionsClose, children: (0, jsx_runtime_1.jsx)("div", { id: popupId, className: (0, classnames_1.default)('flex flex-col bg-surface2 shadow-popup overflow-y-scroll', {
68
68
  'py-l4 rounded-lg': size === 'md',
69
69
  'py-l3 rounded-md': size !== 'md'
70
70
  }), style: {
@@ -1,6 +1,7 @@
1
1
  import { HTMLAttributes } from 'react';
2
2
  import { Icon } from '../visuals';
3
3
  export declare const IconButton: import("react").ForwardRefExoticComponent<Omit<HTMLAttributes<HTMLButtonElement>, "children"> & {
4
+ anchorId?: string;
4
5
  variant?: IconButton.Variant;
5
6
  icon: Icon.Variant;
6
7
  size?: Extract<Icon.Size, "md" | "sm" | "xs" | "xxs">;
@@ -9,6 +10,7 @@ export declare const IconButton: import("react").ForwardRefExoticComponent<Omit<
9
10
  } & import("react").RefAttributes<HTMLButtonElement>>;
10
11
  export declare namespace IconButton {
11
12
  type Props = Omit<HTMLAttributes<HTMLButtonElement>, 'children'> & {
13
+ anchorId?: string;
12
14
  variant?: Variant;
13
15
  icon: Icon.Variant;
14
16
  size?: Extract<Icon.Size, 'md' | 'sm' | 'xs' | 'xxs'>;
@@ -20,11 +20,12 @@ const jsx_runtime_1 = require("react/jsx-runtime");
20
20
  const classnames_1 = __importDefault(require("classnames"));
21
21
  const react_1 = require("react");
22
22
  const visuals_1 = require("../visuals");
23
+ const Popup_1 = require("./Popup");
23
24
  // component
24
25
  exports.IconButton = (0, react_1.forwardRef)(function IconButton(_a, ref) {
25
- var { className, variant = 'util', icon, size = 'md', active = false, disabled = false } = _a, props = __rest(_a, ["className", "variant", "icon", "size", "active", "disabled"]);
26
+ var { anchorId, className, style, variant = 'util', icon, size = 'md', active = false, disabled = false } = _a, props = __rest(_a, ["anchorId", "className", "style", "variant", "icon", "size", "active", "disabled"]);
26
27
  // render
27
- return ((0, jsx_runtime_1.jsx)("button", Object.assign({ ref: ref, className: (0, classnames_1.default)(className, getIconButtonClassnames({ variant, size, active, disabled })), disabled: disabled }, props, { children: (0, jsx_runtime_1.jsx)(visuals_1.Icon, { variant: icon, size: size }) })));
28
+ return ((0, jsx_runtime_1.jsx)("button", Object.assign({ ref: ref, className: (0, classnames_1.default)(className, anchorId ? Popup_1.Popup.anchorClassName : undefined, getIconButtonClassnames({ variant, size, active, disabled })), style: anchorId ? Popup_1.Popup.getAnchorStyle(anchorId, style) : style, disabled: disabled }, props, { children: (0, jsx_runtime_1.jsx)(visuals_1.Icon, { variant: icon, size: size }) })));
28
29
  });
29
30
  function getIconButtonClassnames({ variant, size, active, disabled }) {
30
31
  return (0, classnames_1.default)('iconbutton', {
@@ -1,6 +1,6 @@
1
1
  import { AnchorHTMLAttributes } from 'react';
2
2
  import { IconButton } from './IconButton';
3
- export declare const IconLink: import("react").ForwardRefExoticComponent<Omit<AnchorHTMLAttributes<HTMLAnchorElement>, "children"> & Pick<IconButton.Props, "disabled" | "size" | "icon" | "variant"> & import("react").RefAttributes<HTMLAnchorElement>>;
3
+ export declare const IconLink: import("react").ForwardRefExoticComponent<Omit<AnchorHTMLAttributes<HTMLAnchorElement>, "children"> & Pick<IconButton.Props, "size" | "disabled" | "icon" | "variant"> & import("react").RefAttributes<HTMLAnchorElement>>;
4
4
  export declare namespace IconLink {
5
5
  type Props = Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'children'> & Pick<IconButton.Props, 'variant' | 'icon' | 'size' | 'disabled'>;
6
6
  }
@@ -1,11 +1,11 @@
1
1
  import { Callback, Provider, Transform } from '@nascentdigital/funnel-core';
2
2
  import { ReactNode } from 'react';
3
3
  import { Popup } from './Popup';
4
- export declare function MiniEditor({ className, title, open, wide, disabled, renderSaveLabel, canSave, disableSave, onSave: onSaveRaw, onClose: onCloseRaw, customActions, children, ...popupProps }: MiniEditor.Props): import("react/jsx-runtime").JSX.Element;
4
+ export declare function MiniEditor({ className, title, open, size, disabled, renderSaveLabel, canSave, disableSave, onSave: onSaveRaw, onClose: onCloseRaw, customActions, children, ...popupProps }: MiniEditor.Props): import("react/jsx-runtime").JSX.Element;
5
5
  export declare namespace MiniEditor {
6
6
  type Props = PopupProps & {
7
7
  title: string;
8
- wide?: boolean;
8
+ size?: Size;
9
9
  disabled?: boolean;
10
10
  renderSaveLabel?: Transform<State, string>;
11
11
  canSave?: Provider<boolean> | Provider.Async<boolean>;
@@ -13,6 +13,7 @@ export declare namespace MiniEditor {
13
13
  onSave?: Callback.Void | Callback.AsyncVoid;
14
14
  customActions?: ReactNode;
15
15
  };
16
+ type Size = 'md' | 'sm' | 'xs';
16
17
  type State = 'editing' | 'validating' | 'saving' | 'error' | 'saved';
17
18
  }
18
19
  type PopupProps = Pick<Popup.Props, 'className' | 'open' | 'anchor' | 'anchorOffset' | 'placement' | 'onOpened' | 'onClose' | 'onClosed' | 'children'>;
@@ -23,7 +23,7 @@ const Button_1 = require("./Button");
23
23
  const Popup_1 = require("./Popup");
24
24
  // component
25
25
  function MiniEditor(_a) {
26
- var { className, title, open, wide, disabled = false, renderSaveLabel = onRenderSaveLabel, canSave = funnel_core_1.Fn.True, disableSave = false, onSave: onSaveRaw = funnel_core_1.Fn.NoOp, onClose: onCloseRaw = funnel_core_1.Fn.NoOp, customActions, children } = _a, popupProps = __rest(_a, ["className", "title", "open", "wide", "disabled", "renderSaveLabel", "canSave", "disableSave", "onSave", "onClose", "customActions", "children"]);
26
+ var { className, title, open, size = 'md', disabled = false, renderSaveLabel = onRenderSaveLabel, canSave = funnel_core_1.Fn.True, disableSave = false, onSave: onSaveRaw = funnel_core_1.Fn.NoOp, onClose: onCloseRaw = funnel_core_1.Fn.NoOp, customActions, children } = _a, popupProps = __rest(_a, ["className", "title", "open", "size", "disabled", "renderSaveLabel", "canSave", "disableSave", "onSave", "onClose", "customActions", "children"]);
27
27
  // bind state + refs
28
28
  const [state, setState] = (0, react_1.useState)('editing');
29
29
  // reset state on open
@@ -94,10 +94,12 @@ function MiniEditor(_a) {
94
94
  };
95
95
  // render
96
96
  const locked = disabled || state === 'validating' || state === 'saving' || state === 'saved';
97
- return ((0, jsx_runtime_1.jsxs)(Popup_1.Popup, Object.assign({}, popupProps, { className: (0, classnames_1.default)(className, 'max-h-[90dvh]', 'flex flex-col gap-l8 p-l8 shadow-miniEditor interpolate', 'bg-background border border-solid border-border-l1 rounded-md', {
98
- 'w-[420px] max-w-[420px]': !wide
99
- }), open: open, disabled: disabled, disableDismiss: locked, onKeyDown: onKeyDown, onClose: onClose, tabIndex: -1, children: [(0, jsx_runtime_1.jsx)("h2", { className: "heading-md text-content-primary", children: title }), children, (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-end items-center gap-l4 pt-l6", children: [(0, jsx_runtime_1.jsx)(Button_1.Button, { variant: "text", size: "sm", disabled: locked, onClick: onClose, children: "Cancel" }), customActions &&
100
- (0, jsx_runtime_1.jsx)("div", { className: "flex-1 flex justify-end items-center gap-l4", children: customActions }), (0, jsx_runtime_1.jsx)(Button_1.Button, { variant: "primary", size: "sm", loading: state === 'saving', disabled: disableSave || locked, onClick: onSave, children: renderSaveLabel(state) })] })] })));
97
+ return ((0, jsx_runtime_1.jsxs)(Popup_1.Popup, Object.assign({}, popupProps, { className: (0, classnames_1.default)(className, 'max-h-[90dvh]', 'flex flex-col p-l8 shadow-miniEditor interpolate', 'bg-background border border-solid border-border-l1 rounded-md', {
98
+ 'w-[420px] max-w-[420px] gap-l8': size === 'md',
99
+ 'w-[320px] gap-l6': size === 'sm',
100
+ 'w-[288px] gap-l6': size === 'xs'
101
+ }), open: open, disabled: disabled, disableDismiss: locked, onKeyDown: onKeyDown, onClose: onClose, tabIndex: -1, children: [(0, jsx_runtime_1.jsx)("h2", { className: "heading-md text-content-primary", children: title }), children, (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-end items-center gap-l4 pt-l6", children: [(0, jsx_runtime_1.jsx)(Button_1.Button, { variant: "text", size: size === 'md' ? 'sm' : 'xs', disabled: locked, onClick: onClose, children: "Cancel" }), customActions &&
102
+ (0, jsx_runtime_1.jsx)("div", { className: "flex-1 flex justify-end items-center gap-l4", children: customActions }), (0, jsx_runtime_1.jsx)(Button_1.Button, { variant: "primary", size: size === 'md' ? 'sm' : 'xs', loading: state === 'saving', disabled: disableSave || locked, onClick: onSave, children: renderSaveLabel(state) })] })] })));
101
103
  }
102
104
  function onRenderSaveLabel(state) {
103
105
  switch (state) {
@@ -1,10 +1,10 @@
1
1
  import { Callback, Placement, Rect } from '@nascentdigital/funnel-core';
2
- import { Variants } from 'framer-motion';
3
- import { CSSProperties, HTMLAttributes } from 'react';
4
- export declare function Popup({ className, style, anchor, placement, anchorOffset, 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;
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;
5
5
  export declare namespace Popup {
6
6
  type Props = HTMLAttributes<HTMLDivElement> & {
7
- anchor?: Rect | Element | string | null | undefined;
7
+ anchor?: Anchor;
8
8
  anchorOffset?: number;
9
9
  placement?: Placement;
10
10
  viewportPadding?: number;
@@ -18,17 +18,22 @@ export declare namespace Popup {
18
18
  onClose?: Callback.Void;
19
19
  onClosed?: Callback.Void;
20
20
  };
21
+ type Anchor = string | ReactNode;
21
22
  type Animation = 'in' | 'out' | 'in-out';
22
23
  type Backdrop = 'none' | 'glass';
24
+ const anchorClassName: "anchor/[--nd-popup-anchor]";
25
+ function getAnchorStyle(anchorId: string, styles?: CSSProperties): CSSProperties;
26
+ type Frame = {
27
+ left: string;
28
+ top: string;
29
+ width: string;
30
+ height: string;
31
+ };
32
+ function getAnchorFrame(frame?: Rect): Frame | undefined;
33
+ function AnchorElement<TTag extends HTMLContainer.Tag>({ anchorId, tag, className, style, ...props }: AnchorElement.Props<TTag>): import("react/jsx-runtime").JSX.Element;
34
+ namespace AnchorElement {
35
+ type Props<TTag extends HTMLContainer.Tag = 'div'> = HTMLContainer.Props<TTag> & {
36
+ anchorId: string;
37
+ };
38
+ }
23
39
  }
24
- export declare const animations: Variants;
25
- type GetPopupPlacementStyleArgs = Pick<Popup.Props, 'anchor' | 'anchorOffset' | 'placement' | 'viewportPadding'> & {
26
- contentElement: HTMLDivElement | null;
27
- };
28
- type PopupPlacement = {
29
- containerClassName?: string;
30
- className?: string;
31
- style?: CSSProperties;
32
- };
33
- export declare function getPopupPlacement({ anchor, anchorOffset, placement, viewportPadding, contentElement }: GetPopupPlacementStyleArgs): PopupPlacement;
34
- export {};