@nascentdigital/funnel-editor 4.6.1 → 5.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) 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 +20 -0
  14. package/dist/components.js +41 -0
  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 +2 -2
  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.js +12 -44
  42. package/dist/core/components/fields/asset/AssetPicker.js +6 -6
  43. package/dist/core/components/fields/asset/AssetUploader.js +23 -31
  44. package/dist/core/components/fields/asset/preview/VideoPreview.js +16 -11
  45. package/dist/core/components/fields/asset/useAssetFields.d.ts +2 -17
  46. package/dist/core/components/fields/asset/useAssetFields.js +0 -21
  47. package/dist/core/components/fields/collection/CollectionEditor.js +1 -1
  48. package/dist/core/components/fields/collection/CollectionPicker.d.ts +2 -2
  49. package/dist/core/components/fields/collection/CollectionPicker.js +3 -4
  50. package/dist/core/components/fields/dynamicPages/PagePriorityDialog.js +1 -1
  51. package/dist/core/components/fields/embed/EmbeddedVideoEditor.js +34 -27
  52. package/dist/core/components/fields/factories/FieldValueFactory.js +11 -4
  53. package/dist/core/components/fields/factories/MediaFactory.d.ts +13 -0
  54. package/dist/core/components/fields/factories/MediaFactory.js +256 -0
  55. package/dist/core/components/fields/list/CreateFieldButton.js +1 -1
  56. package/dist/core/components/fields/media/MediaCard.d.ts +7 -0
  57. package/dist/core/components/fields/media/MediaCard.js +92 -0
  58. package/dist/core/components/fields/media/MediaEditor.d.ts +37 -0
  59. package/dist/core/components/fields/media/MediaEditor.js +235 -0
  60. package/dist/core/components/fields/media/MediaPicker.d.ts +15 -0
  61. package/dist/core/components/fields/media/MediaPicker.js +251 -0
  62. package/dist/core/components/fields/media/index.d.ts +3 -0
  63. package/dist/core/components/fields/media/index.js +19 -0
  64. package/dist/core/components/fields/object/ObjectEditor.js +1 -1
  65. package/dist/core/components/fields/page/PagePicker.d.ts +2 -2
  66. package/dist/core/components/fields/page/PagePicker.js +1 -1
  67. package/dist/core/components/interaction/Combobox.js +1 -1
  68. package/dist/core/components/interaction/DateTimePicker.d.ts +0 -1
  69. package/dist/core/components/interaction/DateTimePicker.js +0 -2
  70. package/dist/core/components/interaction/MultiSelectControls.js +2 -5
  71. package/dist/core/components/interaction/Popup.js +1 -0
  72. package/dist/core/components/interaction/QuickEditor.js +1 -1
  73. package/dist/core/components/interaction/QuickPicker.js +1 -1
  74. package/dist/core/components/interaction/SideSheet.js +1 -1
  75. package/dist/core/components/interaction/centersheet/CenterSheet.js +7 -1
  76. package/dist/core/components/interaction/centersheet/CenterSheetContainer.js +3 -1
  77. package/dist/core/components/transitions/FadeIn.js +2 -14
  78. package/dist/core/components/visuals/Icon.d.ts +1 -1
  79. package/dist/core/components/visuals/Icon.js +3 -0
  80. package/dist/core/containers/AssetRepositoryContainer.d.ts +2 -0
  81. package/dist/core/containers/AssetRepositoryContainer.js +18 -0
  82. package/dist/core/containers/CollectionRepositoryContainer.d.ts +2 -0
  83. package/dist/core/containers/CollectionRepositoryContainer.js +18 -0
  84. package/dist/core/containers/PageRepositoryContainer.d.ts +2 -0
  85. package/dist/core/containers/PageRepositoryContainer.js +18 -0
  86. package/dist/core/containers/index.d.ts +3 -0
  87. package/dist/core/containers/index.js +19 -0
  88. package/dist/core/domain/Block.d.ts +1 -0
  89. package/dist/core/domain/Block.js +8 -5
  90. package/dist/core/domain/BlockConfiguration.d.ts +4 -1
  91. package/dist/core/domain/BlockConfiguration.js +64 -3
  92. package/dist/core/domain/Collection.d.ts +10 -28
  93. package/dist/core/domain/Collection.js +2 -16
  94. package/dist/core/domain/CollectionBrowser.d.ts +3 -2
  95. package/dist/core/domain/CollectionBrowser.js +3 -3
  96. package/dist/core/domain/CollectionFieldProxy.d.ts +12 -8
  97. package/dist/core/domain/CollectionFieldProxy.js +14 -8
  98. package/dist/core/domain/CollectionGroup.d.ts +0 -5
  99. package/dist/core/domain/CollectionGroup.js +0 -7
  100. package/dist/core/domain/CollectionSummary.d.ts +2 -2
  101. package/dist/core/domain/Collections.d.ts +3 -3
  102. package/dist/core/domain/Collections.js +4 -4
  103. package/dist/core/domain/ICollection.d.ts +71 -0
  104. package/dist/core/domain/ICollection.js +20 -0
  105. package/dist/core/domain/IPage.d.ts +72 -0
  106. package/dist/core/domain/IPage.js +20 -0
  107. package/dist/core/domain/IPageRefStore.d.ts +3 -3
  108. package/dist/core/domain/ItemBase.d.ts +6 -6
  109. package/dist/core/domain/ItemBase.js +5 -5
  110. package/dist/core/domain/Page.d.ts +9 -22
  111. package/dist/core/domain/Page.js +3 -18
  112. package/dist/core/domain/PageOverview.d.ts +2 -2
  113. package/dist/core/domain/PageRefStoreProxy.d.ts +4 -4
  114. package/dist/core/domain/PageSettings.d.ts +3 -3
  115. package/dist/core/domain/PageSummary.d.ts +2 -2
  116. package/dist/core/domain/Pages.js +4 -6
  117. package/dist/core/domain/SectionBlock.js +2 -1
  118. package/dist/core/domain/Site.d.ts +4 -4
  119. package/dist/core/domain/Site.js +3 -3
  120. package/dist/core/domain/index.d.ts +2 -1
  121. package/dist/core/domain/index.js +2 -1
  122. package/dist/core/hooks/index.d.ts +4 -3
  123. package/dist/core/hooks/index.js +4 -3
  124. package/dist/core/hooks/useAssetRepository.d.ts +3 -0
  125. package/dist/core/hooks/useAssetRepository.js +11 -0
  126. package/dist/core/hooks/useCollection.d.ts +4 -4
  127. package/dist/core/hooks/useCollectionRepository.d.ts +3 -2
  128. package/dist/core/hooks/useCollectionRepository.js +4 -4
  129. package/dist/core/hooks/usePage.d.ts +4 -4
  130. package/dist/core/hooks/usePageRef.d.ts +1 -1
  131. package/dist/core/hooks/usePageRepository.d.ts +3 -2
  132. package/dist/core/hooks/usePageRepository.js +4 -4
  133. package/dist/core/hooks/useTempFields.d.ts +2 -3
  134. package/dist/core/index.d.ts +1 -0
  135. package/dist/core/index.js +1 -0
  136. package/dist/core/repository/AssetRepository.d.ts +10 -0
  137. package/dist/core/repository/AssetRepository.js +22 -0
  138. package/dist/core/repository/CollectionRepository.d.ts +21 -20
  139. package/dist/core/repository/CollectionRepository.js +23 -161
  140. package/dist/core/repository/CollectionSerializer.d.ts +4 -1
  141. package/dist/core/repository/CollectionSerializer.js +3 -3
  142. package/dist/core/repository/IAssetRepository.d.ts +25 -0
  143. package/dist/core/repository/ICollectionRepository.d.ts +62 -0
  144. package/dist/core/repository/ICollectionRepository.js +2 -0
  145. package/dist/core/repository/IPageRepository.d.ts +40 -0
  146. package/dist/core/repository/IPageRepository.js +2 -0
  147. package/dist/core/repository/PageRepository.d.ts +6 -9
  148. package/dist/core/repository/PageRepository.js +7 -280
  149. package/dist/core/repository/PageSerializer.d.ts +34 -1
  150. package/dist/core/repository/PageSerializer.js +4 -0
  151. package/dist/core/repository/SerializeCollectionUpdate.d.ts +8 -0
  152. package/dist/core/repository/SerializeCollectionUpdate.js +168 -0
  153. package/dist/core/repository/SerializePageUpdate.d.ts +11 -0
  154. package/dist/core/repository/SerializePageUpdate.js +292 -0
  155. package/dist/core/repository/index.d.ts +4 -0
  156. package/dist/core/repository/index.js +4 -0
  157. package/dist/dashboard/screens/Dashboard.js +1 -1
  158. package/dist/devtools/screens/Devtools.js +1 -1
  159. package/dist/explore/components/CreatePageDialog.d.ts +2 -2
  160. package/dist/explore/screens/CollectionExplorer.js +1 -1
  161. package/dist/explore/screens/CollectionsExplorer.js +1 -1
  162. package/dist/explore/screens/PageExplorer.js +1 -1
  163. package/dist/explore/screens/SiteExplorer.js +1 -1
  164. package/dist/page/components/BlockEditor.js +1 -1
  165. package/dist/page/components/PageHeader.d.ts +2 -2
  166. package/dist/page/components/PageNotCreated.d.ts +2 -2
  167. package/dist/page/components/PageNotFound.d.ts +2 -2
  168. package/dist/page/components/SettingsEditor.js +0 -7
  169. package/dist/page/components/config/BlockConfigButton.d.ts +2 -1
  170. package/dist/page/components/config/BlockConfigButton.js +84 -24
  171. package/dist/page/components/config/BlockPreview.d.ts +8 -0
  172. package/dist/page/components/config/BlockPreview.js +53 -0
  173. package/dist/page/components/config/index.d.ts +1 -1
  174. package/dist/page/components/config/index.js +1 -1
  175. package/dist/page/components/config/preview/ColumnLayout.d.ts +10 -0
  176. package/dist/page/components/config/preview/ColumnLayout.js +15 -0
  177. package/dist/page/components/config/preview/ItemLayout.d.ts +12 -0
  178. package/dist/page/components/config/preview/ItemLayout.js +45 -0
  179. package/dist/page/components/config/preview/ListPanel.d.ts +12 -0
  180. package/dist/page/components/config/preview/ListPanel.js +14 -0
  181. package/dist/page/components/config/preview/MessagePanel.d.ts +12 -0
  182. package/dist/page/components/config/preview/MessagePanel.js +21 -0
  183. package/dist/page/components/config/preview/Panel.d.ts +15 -0
  184. package/dist/page/components/config/preview/Panel.js +74 -0
  185. package/dist/page/components/config/preview/RowLayout.d.ts +10 -0
  186. package/dist/page/components/config/preview/RowLayout.js +26 -0
  187. package/dist/page/components/config/preview/StackLayout.d.ts +10 -0
  188. package/dist/page/components/config/preview/StackLayout.js +15 -0
  189. package/dist/page/components/config/preview/VisualPanel.d.ts +12 -0
  190. package/dist/page/components/config/preview/VisualPanel.js +27 -0
  191. package/dist/page/components/config/preview/index.d.ts +3 -0
  192. package/dist/page/components/config/preview/index.js +19 -0
  193. package/dist/page/components/panels/BlockConfigPanel.js +4 -4
  194. package/dist/page/hooks/IPageController.d.ts +42 -0
  195. package/dist/page/hooks/IPageController.js +32 -0
  196. package/dist/page/hooks/PageController.d.ts +11 -36
  197. package/dist/page/hooks/PageController.js +7 -33
  198. package/dist/page/hooks/index.d.ts +1 -0
  199. package/dist/page/hooks/index.js +1 -0
  200. package/dist/page/hooks/usePageController.d.ts +3 -3
  201. package/dist/page/screens/PageEditor.js +1 -1
  202. package/dist/styles/index.css +809 -60
  203. package/dist/styles/tailwind.js +1 -0
  204. package/dist/users/screens/UserExplorer.js +1 -1
  205. package/package.json +3 -2
  206. package/dist/core/domain/TranslateSchema.d.ts +0 -7
  207. package/dist/page/components/config/LegacyBlockPreview.d.ts +0 -8
  208. package/dist/page/components/config/LegacyBlockPreview.js +0 -452
  209. /package/dist/core/{domain/TranslateSchema.js → repository/IAssetRepository.js} +0 -0
@@ -0,0 +1,251 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MediaPicker = void 0;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const funnel_core_1 = require("@nascentdigital/funnel-core");
9
+ const classnames_1 = __importDefault(require("classnames"));
10
+ const framer_motion_1 = require("framer-motion");
11
+ const react_1 = require("react");
12
+ const hooks_1 = require("../../../hooks");
13
+ const feedback_1 = require("../../feedback");
14
+ const interaction_1 = require("../../interaction");
15
+ const transitions_1 = require("../../transitions");
16
+ // component
17
+ exports.MediaPicker = (0, react_1.forwardRef)(function MediaPicker({ language }, ref) {
18
+ // bind props + hooks
19
+ const [deferral, setDeferral] = (0, react_1.useState)(undefined);
20
+ const [result, setResult] = (0, react_1.useState)();
21
+ const [schema, setSchema] = (0, react_1.useState)();
22
+ const [collectionGroups, setCollectionGroups] = (0, react_1.useState)();
23
+ const [collectionGroup, setCollectionGroup] = (0, react_1.useState)();
24
+ const [collections, setCollections] = (0, react_1.useState)();
25
+ const [tagOptions, setTagOptions] = (0, react_1.useState)();
26
+ const [tagFilters, setTagFilters] = (0, react_1.useState)([]);
27
+ const [tagTooltip, setTagTooltip] = (0, react_1.useState)();
28
+ const [fetching, setFetching] = (0, react_1.useState)(false);
29
+ const [error, setError] = (0, react_1.useState)();
30
+ const repo = (0, hooks_1.useCollectionRepository)();
31
+ const siteCollections = (0, hooks_1.useCollections)();
32
+ const collectionStore = (0, hooks_1.useCollectionStore)();
33
+ // export service
34
+ (0, react_1.useImperativeHandle)(ref, () => ({
35
+ pick: async ({ schema }) => {
36
+ // reset state
37
+ setSchema(schema);
38
+ setCollectionGroups(undefined);
39
+ setCollectionGroup(undefined);
40
+ setTagOptions(undefined);
41
+ setTagFilters([]);
42
+ setTagTooltip(undefined);
43
+ setCollections(undefined);
44
+ setError(undefined);
45
+ // create deferral
46
+ const deferral = new funnel_core_1.Deferral();
47
+ setDeferral(deferral);
48
+ setResult(undefined);
49
+ // wait until deferral is resolved
50
+ return deferral.promise;
51
+ }
52
+ }), []);
53
+ // fetch collection groups when schema changes
54
+ (0, react_1.useEffect)(() => {
55
+ // skip if there's no deferral
56
+ if (!schema || !deferral) {
57
+ return;
58
+ }
59
+ // reset error (if any)
60
+ setError(undefined);
61
+ // sync site
62
+ siteCollections.sync()
63
+ // bind groups, filtering out types that aren't part of the set
64
+ .then(() => {
65
+ // determine group list
66
+ const { collections } = schema;
67
+ const collectionGroups = collections.length === 0
68
+ ? siteCollections.items
69
+ : siteCollections.items
70
+ .filter(group => collections.some(collection => collection.type === group.type));
71
+ setCollectionGroups(collectionGroups);
72
+ // bind first group as in initial selection
73
+ const [collectionGroup] = collectionGroups;
74
+ setCollectionGroup(collectionGroup);
75
+ // short-circuit collections if none are present
76
+ if (!collectionGroup) {
77
+ setCollections([]);
78
+ setTagOptions([]);
79
+ setTagFilters([]);
80
+ }
81
+ })
82
+ // handle error
83
+ .catch(e => {
84
+ console.error('[MediaPicker/sync] sync failed', e);
85
+ setError(feedback_1.ErrorMessage.coerce(e));
86
+ });
87
+ }, [siteCollections, deferral, schema]);
88
+ // fetch collection items when group changes
89
+ (0, react_1.useEffect)(() => {
90
+ // ignore if not ready
91
+ if (!collectionGroup) {
92
+ return;
93
+ }
94
+ console.debug('[MediaPicker/sync] syncing group', collectionGroup);
95
+ // clear collections
96
+ setCollections(undefined);
97
+ setTagOptions(undefined);
98
+ setTagFilters([]);
99
+ // sync group
100
+ collectionGroup.sync()
101
+ // then update filters
102
+ .then(() => {
103
+ // transform items
104
+ const collections = collectionGroup.items
105
+ .map(summary => summary.getClosestCollectionRef(language, collectionGroup.defaultLanguage))
106
+ .filter(funnel_core_1.Value.isDefined);
107
+ // set collections
108
+ setCollections(collections);
109
+ // setup tags (if there are items in group)
110
+ if (collections.length > 0) {
111
+ const { tags: tagGroups } = collectionGroup.template;
112
+ const tagOptions = tagGroups
113
+ .map(tagGroup => {
114
+ // get all tags in group
115
+ const tags = Object.values(tagGroup.tags).reduce((tags, tag) => {
116
+ // add tag if it matches
117
+ if (collections.some(collection => collection.tags.includes(tag))) {
118
+ tags.add(tag);
119
+ }
120
+ // keep reducing
121
+ return tags;
122
+ }, new Set());
123
+ // create filter group (if there are items)
124
+ return tags.size > 0
125
+ ? { group: tagGroup, tags }
126
+ : undefined;
127
+ })
128
+ .filter(funnel_core_1.Value.isDefined);
129
+ // set options
130
+ setTagOptions(tagOptions);
131
+ }
132
+ // or clear tags
133
+ else {
134
+ setTagOptions([]);
135
+ }
136
+ })
137
+ // or capture error
138
+ .catch(e => setError(feedback_1.ErrorMessage.coerce(e)));
139
+ }, [language, collectionGroup]);
140
+ // helpers
141
+ const onPick = async (collectionRef) => {
142
+ // clear tooltips
143
+ setTagTooltip(undefined);
144
+ // fetch ref (or fail)
145
+ const { template, id, name } = collectionRef;
146
+ const collection = await repo.get({ id, version: 'draft' });
147
+ if (!collection) {
148
+ setFetching(false);
149
+ setError({
150
+ title: `Unable to find ${template.name}`,
151
+ message: `We ran into an issue while trying to fetch the "${name}" collection item. Please refresh your browser and try again.`
152
+ });
153
+ return;
154
+ }
155
+ // add collection
156
+ collectionStore.addCollection(collection.data);
157
+ // set result (triggers picker to close)
158
+ setResult(collectionRef);
159
+ };
160
+ const onCancel = () => {
161
+ // clear tooltips
162
+ setTagTooltip(undefined);
163
+ // set result (triggers picker to close)
164
+ setResult(null);
165
+ };
166
+ const onPickerClosed = () => {
167
+ // skip if missing or already completed
168
+ if (!deferral || deferral.isComplete) {
169
+ return;
170
+ }
171
+ // complete deferral
172
+ deferral.resolve(result !== null && result !== void 0 ? result : undefined);
173
+ };
174
+ // render
175
+ return ((0, jsx_runtime_1.jsxs)(interaction_1.Picker, { className: "flex", open: deferral && result === undefined, disableDismiss: fetching, onClose: onCancel, onClosed: onPickerClosed, children: [(0, jsx_runtime_1.jsxs)("section", { className: "shrink-0 w-[206px] flex flex-col gap-l8 p-l8 bg-modal-background", children: [(0, jsx_runtime_1.jsx)("h1", { className: "heading-md text-content-primary", children: "Select Collection" }), (0, jsx_runtime_1.jsx)(interaction_1.ChipFilters, { title: "Site Collections", options: collectionGroups, selectedOptions: collectionGroup && [collectionGroup], onToggle: (collectionGroup, selected) => selected && setCollectionGroup(collectionGroup), renderLabel: collectionGroup => collectionGroup.template.name, disabled: fetching })] }), (0, jsx_runtime_1.jsxs)("section", { className: "flex-1 flex flex-col", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex-1 p-l8 overflow-y-scroll", tabIndex: -1, children: (0, jsx_runtime_1.jsx)(framer_motion_1.AnimatePresence, { mode: "wait", initial: false, children: renderPicker({ language, error, collectionGroups, collectionGroup, collections, tagOptions, tagFilters, onPick, setTagTooltip, fetching }) }) }), (0, jsx_runtime_1.jsx)("div", { className: "flex justify-end items-center p-l8 border-t border-solid border-border-l1", children: (0, jsx_runtime_1.jsx)(interaction_1.Button, { variant: "secondary", size: "sm", onClick: onCancel, disabled: fetching, children: "Cancel" }) }), (0, jsx_runtime_1.jsx)(interaction_1.Popup, { className: (0, classnames_1.default)('max-w-[200px] bg-surface2 rounded-md p-l5', 'border border-solid border-border-l1 shadow-tooltip', 'flex flex-wrap items-center gap-l4'), open: !!tagTooltip, anchor: tagTooltip === null || tagTooltip === void 0 ? void 0 : tagTooltip.anchor, anchorOffset: 4, placement: "top", disableOverlay: true, onClose: () => setTagTooltip(undefined), children: tagTooltip === null || tagTooltip === void 0 ? void 0 : tagTooltip.tags.map(tag => (0, jsx_runtime_1.jsx)(feedback_1.Badge, { variant: "outlinedTiny", status: "draft", label: tag.name }, tag.data)) })] })] }));
176
+ });
177
+ function renderPicker({ language, schema, error, collectionGroups, collectionGroup, collections, tagOptions, tagFilters, onPick, setTagTooltip, fetching }) {
178
+ // show error if we have one
179
+ if (error) {
180
+ return ((0, jsx_runtime_1.jsx)(transitions_1.FadeIn, { className: "flex flex-col justify-center items-center", children: (0, jsx_runtime_1.jsx)(feedback_1.ErrorMessage, { error: error }) }, "error"));
181
+ }
182
+ // or show loader if filters aren't loaded (or if fetching)
183
+ else if (fetching || !collectionGroups || !collections || !tagOptions) {
184
+ return ((0, jsx_runtime_1.jsx)(transitions_1.FadeIn, { className: "w-full h-full flex flex-col justify-center items-center", children: (0, jsx_runtime_1.jsx)(interaction_1.Loader, { size: "lg" }) }, "loader"));
185
+ }
186
+ // show empty state if there are no pages
187
+ else if (!collectionGroup || collections.length === 0) {
188
+ return ((0, jsx_runtime_1.jsx)(transitions_1.FadeIn, { className: "h-full flex flex-wrap justify-center items-center", children: (0, jsx_runtime_1.jsxs)(feedback_1.EmptyState, { variant: "missing", size: "sm", children: [(0, jsx_runtime_1.jsx)("p", { className: "body-md text-content-secondary text-pretty", children: "There are no collections available that match your criteria." }), (0, jsx_runtime_1.jsx)("p", { className: "body-md text-content-secondary text-pretty", children: "Create a new collection." })] }) }, "pages.empty"));
189
+ }
190
+ // or show pages (filtered)
191
+ else {
192
+ // get tags that are available (no tags at all means "all" of the group is chosen)
193
+ const collectionSchema = collectionGroup.template;
194
+ const schemaTags = collectionSchema.tags.flatMap(tagGroup => Object.values(tagGroup.tags));
195
+ const activeTagFilters = tagFilters.filter(tag => schemaTags.includes(tag));
196
+ const tags = tagOptions
197
+ .filter(({ group }) => collectionSchema.tags.includes(group))
198
+ .flatMap(({ tags }) => {
199
+ const filteredTags = activeTagFilters.filter(tag => tags.has(tag));
200
+ return filteredTags.length > 0 ? filteredTags : tags.values().toArray();
201
+ });
202
+ const filteredCollections = activeTagFilters.length > 0
203
+ ? collections.filter(collection => collection.tags.some(tag => tags.includes(tag)))
204
+ : collections;
205
+ // render empty list if there are no items
206
+ if (filteredCollections.length === 0) {
207
+ return ((0, jsx_runtime_1.jsx)(transitions_1.FadeIn, { className: "h-full flex flex-col items-center justify-center gap-l5 px-l10", variant: "blur", children: (0, jsx_runtime_1.jsx)("p", { className: "body-md text-content-secondary text-pretty", children: "Sorry, but no collections match your filters." }) }, "pages.dyanmic.empty"));
208
+ }
209
+ // or render items
210
+ else {
211
+ return ((0, jsx_runtime_1.jsx)(transitions_1.FadeIn, { className: "flex flex-col gap-l3", children: filteredCollections.map(ref => renderCollectionRef({
212
+ language,
213
+ template: ref.template,
214
+ ref,
215
+ onPick,
216
+ setTagTooltip
217
+ })) }, "pages.dynamic"));
218
+ }
219
+ }
220
+ }
221
+ function renderCollectionRef({ language, template, ref, onPick, setTagTooltip }) {
222
+ var _a;
223
+ // resolve props
224
+ const title = (_a = ref.name) !== null && _a !== void 0 ? _a : template.name;
225
+ const tags = ref ? ref.tags : [];
226
+ const visibleTags = tags.slice(0, Math.min(tags.length, 2));
227
+ const tooltipTags = tags.length > 2
228
+ ? tags.slice(2)
229
+ : [];
230
+ const disabled = ref.language !== language;
231
+ // helpers
232
+ const onClick = () => {
233
+ // ignore if disabled
234
+ if (disabled) {
235
+ return;
236
+ }
237
+ // otherwise, pick
238
+ else {
239
+ onPick(ref);
240
+ }
241
+ };
242
+ // render
243
+ const anchorId = `col-pick-tip-${ref.id}`;
244
+ 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', {
245
+ 'hover:bg-modal-surface2/tint2 cursor-pointer': !disabled,
246
+ 'cursor-default': disabled
247
+ }), 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', {
248
+ 'opacity-disabled': disabled
249
+ }), onClick: onClick, children: [(0, jsx_runtime_1.jsx)("h3", { className: "flex-1 label-sm text-content-primary ellipsis", children: title }), tags.length > 0 &&
250
+ (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) }))] })] }) }, ref.id));
251
+ }
@@ -0,0 +1,3 @@
1
+ export * from './MediaCard';
2
+ export * from './MediaEditor';
3
+ export * from './MediaPicker';
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./MediaCard"), exports);
18
+ __exportStar(require("./MediaEditor"), exports);
19
+ __exportStar(require("./MediaPicker"), exports);
@@ -58,5 +58,5 @@ exports.ObjectEditor = (0, react_1.forwardRef)(function ObjectEditor(_, ref) {
58
58
  return null;
59
59
  }
60
60
  // render
61
- return ((0, jsx_runtime_1.jsxs)(interaction_1.CenterSheet, { className: "h-full flex flex-col gap-l6", name: field.name, open: !!deferral && result === undefined, onClose: onClose, onClosed: onClosed, children: [(0, jsx_runtime_1.jsxs)("div", { className: "h-48 flex items-center gap-l4 px-l7", children: [(0, jsx_runtime_1.jsx)(interaction_1.IconButton, { icon: "X", onClick: onClose }), (0, jsx_runtime_1.jsx)("h1", { className: "label-sm text-content-primary", children: field.name }), (0, jsx_runtime_1.jsx)("span", { className: "flex-1" }), (0, jsx_runtime_1.jsx)(interaction_1.Button, { variant: "primary", size: "sm", disabled: !field.modified, onClick: () => setResult(field.value), children: field.isNew ? 'Create' : 'Update' })] }), (0, jsx_runtime_1.jsx)(FieldsPanel_1.FieldsPanel, { className: "flex-1 px-l7", title: schema.name, fields: field.fields })] }));
61
+ return ((0, jsx_runtime_1.jsxs)(interaction_1.CenterSheet, { className: "h-full flex flex-col gap-l6", name: field.name, open: !!deferral && result === undefined, onClose: onClose, onClosed: onClosed, children: [(0, jsx_runtime_1.jsxs)("div", { className: "h-48 flex items-center gap-l8 px-l7", children: [(0, jsx_runtime_1.jsx)(interaction_1.IconButton, { icon: "X", onClick: onClose }), (0, jsx_runtime_1.jsx)("h1", { className: "label-sm text-content-primary", children: field.name }), (0, jsx_runtime_1.jsx)("span", { className: "flex-1" }), (0, jsx_runtime_1.jsx)(interaction_1.Button, { variant: "primary", size: "sm", disabled: !field.modified, onClick: () => setResult(field.value), children: field.isNew ? 'Create' : 'Update' })] }), (0, jsx_runtime_1.jsx)("div", { className: "flex-1 flex flex-col gap-l10 px-l6 py-l10 overflow-y-scroll scrollbar-thin bg-background", tabIndex: -1, children: (0, jsx_runtime_1.jsx)(FieldsPanel_1.FieldsPanel, { className: "flex-1", title: schema.name, fields: field.fields, autoFocus: true }) })] }));
62
62
  });
@@ -1,5 +1,5 @@
1
1
  import { Language, Schema } from '@nascentdigital/funnel-core';
2
- import { Page } from '../../../domain';
2
+ import { IPage } from '../../../domain';
3
3
  export declare const PagePicker: import("react").ForwardRefExoticComponent<PagePicker.Props & import("react").RefAttributes<PagePicker.Ref>>;
4
4
  export declare namespace PagePicker {
5
5
  type Props = {
@@ -14,5 +14,5 @@ export declare namespace PagePicker {
14
14
  tags?: ReadonlyArray<Schema.Tag>;
15
15
  disabledIds?: ReadonlyArray<Schema.Page.Id>;
16
16
  };
17
- type Result = Page.Ref | undefined;
17
+ type Result = IPage.Ref | undefined;
18
18
  }
@@ -205,7 +205,7 @@ exports.PagePicker = (0, react_1.forwardRef)(function PagePicker({ language }, r
205
205
  ? 'Primary'
206
206
  : filter.template.name }), tagOptions === null || tagOptions === void 0 ? void 0 : tagOptions.map(({ group, tags: groupTags }) => (0, jsx_runtime_1.jsx)(interaction_1.ChipFilters, { title: group.name, multiselect: true, options: groupTags.values().toArray(), selectedOptions: tagFilters.filter(tag => groupTags.has(tag)), onToggle: (tag, selected) => setTagFilters(tags => selected
207
207
  ? [...tags, tag]
208
- : tags.filter(t => t !== tag)), onToggleAll: () => setTagFilters(tags => tags.filter(tag => !groupTags.has(tag))), renderLabel: tag => tag.name }, group.id))] }), (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({ site, language, disabledIds, error, pageFilters, pageFilter, tagOptions, tagFilters, pagesSchema, pages, onPick, setTagTooltip }) }) }), (0, jsx_runtime_1.jsx)("div", { className: "flex justify-end items-center p-l8 border-t border-solid border-border-l1", children: (0, jsx_runtime_1.jsx)(interaction_1.Button, { variant: "secondary", size: "sm", onClick: onCancel, children: "Cancel" }) }), (0, jsx_runtime_1.jsx)(interaction_1.Popup, { className: (0, classnames_1.default)('max-w-[200px] bg-surface2 rounded-md p-l5', 'border border-solid border-border-l1 shadow-tooltip', 'flex flex-wrap items-center gap-l4'), open: !!tagTooltip, anchor: tagTooltip === null || tagTooltip === void 0 ? void 0 : tagTooltip.anchor, anchorOffset: 4, placement: "top", disableOverlay: true, onClose: () => setTagTooltip(undefined), children: tagTooltip === null || tagTooltip === void 0 ? void 0 : tagTooltip.tags.map(tag => (0, jsx_runtime_1.jsx)(feedback_1.Badge, { variant: "outlinedTiny", status: "draft", label: tag.name }, tag.data)) })] })] }));
208
+ : tags.filter(t => t !== tag)), onToggleAll: () => setTagFilters(tags => tags.filter(tag => !groupTags.has(tag))), renderLabel: tag => tag.name }, group.id))] }), (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({ site, language, disabledIds, error, pageFilters, pageFilter, tagOptions, tagFilters, pagesSchema, pages, onPick, setTagTooltip }) }) }), (0, jsx_runtime_1.jsx)("div", { className: "flex justify-end items-center p-l8 border-t border-solid border-border-l1", children: (0, jsx_runtime_1.jsx)(interaction_1.Button, { variant: "secondary", size: "sm", onClick: onCancel, children: "Cancel" }) }), (0, jsx_runtime_1.jsx)(interaction_1.Popup, { className: (0, classnames_1.default)('max-w-[200px] bg-surface2 rounded-md p-l5', 'border border-solid border-border-l1 shadow-tooltip', 'flex flex-wrap items-center gap-l4'), open: !!tagTooltip, anchor: tagTooltip === null || tagTooltip === void 0 ? void 0 : tagTooltip.anchor, anchorOffset: 4, placement: "top", disableOverlay: true, onClose: () => setTagTooltip(undefined), children: tagTooltip === null || tagTooltip === void 0 ? void 0 : tagTooltip.tags.map(tag => (0, jsx_runtime_1.jsx)(feedback_1.Badge, { variant: "outlinedTiny", status: "draft", label: tag.name }, tag.data)) })] })] }));
209
209
  });
210
210
  function renderPicker({ site, language, disabledIds, error, pageFilters, pageFilter, tagOptions, tagFilters, pagesSchema, pages, onPick, setTagTooltip }) {
211
211
  // show error if we have one
@@ -70,7 +70,7 @@ function Combobox({ id: externalId, className, size = 'md', maxRows = 6, rowHeig
70
70
  }), style: {
71
71
  minWidth: button ? `${button.offsetWidth}px` : 'auto',
72
72
  maxHeight: maxRows * rowHeight + (rowPaddingY * 2)
73
- }, role: "listbox", children: options.map((option, index) => {
73
+ }, role: "listbox", tabIndex: -1, children: options.map((option, index) => {
74
74
  // render
75
75
  const optionKey = getOptionId(id, option);
76
76
  const selected = option.id === selectedOptionId;
@@ -1,5 +1,4 @@
1
1
  import { Callback, Timestamp } from '@nascentdigital/funnel-core';
2
- import 'flatpickr/dist/themes/dark.css';
3
2
  export declare function DateTimePicker({ className, disabled, placeholder, date, onChange, ...optionsRaw }: DateTimePicker.Props): import("react/jsx-runtime").JSX.Element;
4
3
  export declare namespace DateTimePicker {
5
4
  type Props = {
@@ -19,8 +19,6 @@ const jsx_runtime_1 = require("react/jsx-runtime");
19
19
  const client_1 = require("@nascentdigital/funnel-ui/client");
20
20
  const flatpickr_1 = __importDefault(require("flatpickr"));
21
21
  const react_1 = require("react");
22
- // styles
23
- require("flatpickr/dist/themes/dark.css");
24
22
  // component
25
23
  function DateTimePicker(_a) {
26
24
  var { className, disabled = false, placeholder, date, onChange } = _a, optionsRaw = __rest(_a, ["className", "disabled", "placeholder", "date", "onChange"]);
@@ -57,11 +57,11 @@ exports.MultiSelectControls = (0, react_1.forwardRef)(function MultiSelectContro
57
57
  };
58
58
  // render controls when selecting
59
59
  if (selecting) {
60
- return ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)('flex flex-wrap items-center gap-l5', className), children: [(0, jsx_runtime_1.jsx)(Button_1.Button, { variant: "secondary", size: "sm", onClick: selectedIdCount < idCount ? onSelectAll : onDeselectAll, children: selectedIdCount < idCount ? selectAllLabel : deselectAllLabel }), actions, (0, jsx_runtime_1.jsx)(Button_1.Button, { variant: "text", size: "sm", onClick: onSelectCancel, children: cancelLabel })] }));
60
+ return ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)('flex flex-wrap items-center gap-l5', className), children: [(0, jsx_runtime_1.jsx)(Button_1.Button, { variant: "secondary", size: "xs", onClick: selectedIdCount < idCount ? onSelectAll : onDeselectAll, children: selectedIdCount < idCount ? selectAllLabel : deselectAllLabel }), actions, (0, jsx_runtime_1.jsx)(Button_1.Button, { variant: "text", size: "xs", onClick: onSelectCancel, children: cancelLabel })] }));
61
61
  }
62
62
  // or render control to enter selection
63
63
  else {
64
- return ((0, jsx_runtime_1.jsx)("div", { className: className, children: (0, jsx_runtime_1.jsx)(Button_1.Button, { variant: "text", size: "sm", onClick: onSelectStart, children: editLabel }) }));
64
+ return ((0, jsx_runtime_1.jsx)("div", { className: className, children: (0, jsx_runtime_1.jsx)(Button_1.Button, { variant: "secondary", size: "xs", onClick: onSelectStart, children: editLabel }) }));
65
65
  }
66
66
  });
67
67
  // hook
@@ -73,16 +73,13 @@ function useMultiSelectControls() {
73
73
  (0, react_1.useEffect)(() => {
74
74
  // skip if not bound
75
75
  if (!multiSelect) {
76
- console.debug('[useMultiSelectControls] controls not ready');
77
76
  return;
78
77
  }
79
- console.debug('[useMultiSelectControls] binding to controls');
80
78
  // touch on event
81
79
  const subscription = multiSelect.events$.subscribe(touch);
82
80
  // unsubscribe on unmount
83
81
  return () => subscription.unsubscribe();
84
82
  }, [touch, multiSelect]);
85
- console.debug('[useMultiSelectControls] updated', multiSelect);
86
83
  // return selector
87
84
  return [setMultiSelect, multiSelect];
88
85
  }
@@ -142,6 +142,7 @@ function getPopupClassNames({ anchor, placement }) {
142
142
  'anchored-top-span-right': placement === 'top-start',
143
143
  'anchored-bottom': placement === 'bottom',
144
144
  'anchored-left': placement === 'left',
145
+ 'anchored-left-span-bottom': placement === 'left-start',
145
146
  'anchored-right': placement === 'right',
146
147
  'anchored-bottom-span-left': placement === 'bottom-end'
147
148
  })
@@ -29,5 +29,5 @@ function QuickEditor(_a) {
29
29
  'w-[320px]': size === 'md',
30
30
  'w-[288px]': size === 'sm'
31
31
  }), open: open, onClose: onClose, children: [(0, jsx_runtime_1.jsxs)("div", { className: "text-content-primary flex justify-between items-center gap-l8 px-l8 pt-l8 pb-l4", children: [(0, jsx_runtime_1.jsx)("h2", { className: "heading-sm text-pretty", children: title }), (0, jsx_runtime_1.jsx)(IconButton_1.IconButton, { className: "shrink-0", icon: "X", size: "xs", onClick: onClose })] }), tip &&
32
- (0, jsx_runtime_1.jsx)(feedback_1.Note, { className: "mt-l2 mb-l4 mx-l8", variant: "tip", size: size === 'md' ? 'sm' : 'xs', children: (0, jsx_runtime_1.jsx)(funnel_ui_1.Markup, { markdown: `**Tip:** ${tip}` }) }), (0, jsx_runtime_1.jsx)("div", { className: "flex-1 px-l8 pt-l4 pb-l8 overflow-y-scroll", children: children })] })));
32
+ (0, jsx_runtime_1.jsx)(feedback_1.Note, { className: "mt-l2 mb-l4 mx-l8", variant: "tip", size: size === 'md' ? 'sm' : 'xs', children: (0, jsx_runtime_1.jsx)(funnel_ui_1.Markup, { markdown: `**Tip:** ${tip}` }) }), (0, jsx_runtime_1.jsx)("div", { className: "flex-1 px-l8 pt-l4 pb-l8 overflow-y-scroll", tabIndex: -1, children: children })] })));
33
33
  }
@@ -96,7 +96,7 @@ exports.QuickPicker = (0, react_1.forwardRef)(function QuickPicker({ variant, ti
96
96
  'flex flex-wrap gap-l5 items-center ': variant === 'card',
97
97
  'w-[288px]': variant === 'card' && items.length < 4,
98
98
  'w-[372px] max-h-[213px]': variant === 'card' && items.length >= 4
99
- }), children: items.map(item => renderCard({
99
+ }), tabIndex: -1, children: items.map(item => renderCard({
100
100
  item,
101
101
  content: renderItem(item),
102
102
  selected: item.id === selectedItem,
@@ -154,7 +154,7 @@ function SideSheet(_a) {
154
154
  'w-full md:w-screen-sm': size === 'lg'
155
155
  }), variants: breakpoint === 'xs' || breakpoint === 'sm'
156
156
  ? Animate_1.Animate.Variants.slideFromBottom
157
- : Animate_1.Animate.Variants.slideFromLeft, initial: "initial", animate: "animate", exit: "exit", onAnimationComplete: definition => onAnimationComplete(definition), onKeyDown: onKeyDown, tabIndex: -1, children: (0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(className, 'w-full h-full max-h-full pointer-events-auto', 'flex flex-col', 'bg-background border-solid border-border-l1', 'max-md:border-t max-md:rounded-tl-md max-md:rounded-tr-md', 'md:border-l md:rounded-tl-md md:rounded-bl-md'), children: [(0, jsx_runtime_1.jsx)("h2", { className: "heading-sm text-content-primary px-l8 pt-l8 pb-l4", children: title }), (0, jsx_runtime_1.jsx)("div", { className: "flex-1 px-l8 pt-l4 pb-l8 overflow-y-scroll", children: children }), (0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)('flex justify-end items-center gap-l4 p-l8', 'border-t border-solid border-border-l1'), children: [(0, jsx_runtime_1.jsx)(Button_1.Button, { variant: "text", size: "sm", disabled: locked, onClick: onClose, children: "Cancel" }), customActions &&
157
+ : Animate_1.Animate.Variants.slideFromLeft, initial: "initial", animate: "animate", exit: "exit", onAnimationComplete: definition => onAnimationComplete(definition), onKeyDown: onKeyDown, tabIndex: -1, children: (0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(className, 'w-full h-full max-h-full pointer-events-auto', 'flex flex-col', 'bg-background border-solid border-border-l1', 'max-md:border-t max-md:rounded-tl-md max-md:rounded-tr-md', 'md:border-l md:rounded-tl-md md:rounded-bl-md'), children: [(0, jsx_runtime_1.jsx)("h2", { className: "heading-sm text-content-primary px-l8 pt-l8 pb-l4", children: title }), (0, jsx_runtime_1.jsx)("div", { className: "flex-1 px-l8 pt-l4 pb-l8 overflow-y-scroll", tabIndex: -1, children: children }), (0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)('flex justify-end items-center gap-l4 p-l8', 'border-t border-solid border-border-l1'), children: [(0, jsx_runtime_1.jsx)(Button_1.Button, { variant: "text", size: "sm", disabled: locked, onClick: onClose, children: "Cancel" }), customActions &&
158
158
  (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) })] })] }) }))] }, id) }), document.body);
159
159
  }
160
160
  // helpers
@@ -34,8 +34,10 @@ exports.CenterSheet = (0, react_2.forwardRef)(function CenterSheet({ className,
34
34
  }), [open]);
35
35
  // handle open/close events
36
36
  (0, react_2.useEffect)(() => {
37
- // raise open event
37
+ // handle open change
38
+ let unlock = undefined;
38
39
  if (open) {
40
+ // raise open event
39
41
  eventBus.next({
40
42
  type: 'onOpen',
41
43
  sheetInfo: {
@@ -43,6 +45,8 @@ exports.CenterSheet = (0, react_2.forwardRef)(function CenterSheet({ className,
43
45
  name: nameRef.current
44
46
  }
45
47
  });
48
+ // lock tabbing
49
+ unlock = funnel_core_1.Browser.lockFocus(`#${CSS.escape(id)}`);
46
50
  }
47
51
  // or close event
48
52
  else {
@@ -51,6 +55,8 @@ exports.CenterSheet = (0, react_2.forwardRef)(function CenterSheet({ className,
51
55
  sheetId: id
52
56
  });
53
57
  }
58
+ // unlock tabbing on unmount (if locked)
59
+ return () => unlock && unlock();
54
60
  }, [id, eventBus, open]);
55
61
  // ensure close on unmount
56
62
  (0, react_2.useEffect)(() => {
@@ -58,7 +58,9 @@ function CenterSheetContainer({ children }) {
58
58
  // render
59
59
  const { sheets } = context;
60
60
  const active = sheets.length > 0;
61
- return ((0, jsx_runtime_1.jsxs)(CenterSheetContext_1.CenterSheetContext.Provider, { value: context, children: [children, (0, jsx_runtime_1.jsx)("div", { className: "fixed inset-0 pointer-events-none", children: (0, jsx_runtime_1.jsx)("div", { id: anchorId, className: "relative w-full h-full", children: (0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)('absolute inset-0 z-backdrop interpolate will-change-[backdrop-filter,opacity]', 'backdrop-blur-[9px] bg-glass-fill-l1', {
61
+ return ((0, jsx_runtime_1.jsxs)(CenterSheetContext_1.CenterSheetContext.Provider, { value: context, children: [(0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)('w-dvw h-dvh', {
62
+ 'pointer-events-none': active
63
+ }), children: children }), (0, jsx_runtime_1.jsx)("div", { className: "fixed inset-0 pointer-events-none", children: (0, jsx_runtime_1.jsx)("div", { id: anchorId, className: "relative w-full h-full", children: (0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)('absolute inset-0 z-backdrop interpolate will-change-[backdrop-filter,opacity]', 'backdrop-blur-[9px] bg-glass-fill-l1/tint3', {
62
64
  'pointer-events-none opacity-none': !active,
63
65
  'pointer-events-auto opacity-full': active
64
66
  }) }, "backdrop") }) })] }));
@@ -18,24 +18,12 @@ exports.FadeIn = FadeIn;
18
18
  const jsx_runtime_1 = require("react/jsx-runtime");
19
19
  const classnames_1 = __importDefault(require("classnames"));
20
20
  const react_1 = require("motion/react");
21
+ const interaction_1 = require("../interaction");
21
22
  // component
22
23
  function FadeIn(_a) {
23
24
  var { className, variant = 'default' } = _a, props = __rest(_a, ["className", "variant"]);
24
25
  // render
25
26
  return ((0, jsx_runtime_1.jsx)(react_1.motion.div, Object.assign({ className: (0, classnames_1.default)(className, {
26
27
  'will-change-[opacity,filter]': variant === 'blur'
27
- }), variants: Animations[variant], initial: "initial", animate: "animate", exit: "exit" }, props)));
28
+ }), variants: interaction_1.Animate.Variants.fade, initial: "initial", animate: "animate", exit: "exit" }, props, { tabIndex: -1 })));
28
29
  }
29
- // helper
30
- const Animations = {
31
- default: {
32
- initial: { opacity: 0 },
33
- animate: { opacity: 1, transition: { duration: 0.4, ease: 'easeIn' } },
34
- exit: { opacity: 0, transition: { duration: 0.2, ease: 'easeOut' } }
35
- },
36
- blur: {
37
- initial: { opacity: 0, filter: 'blur(5px)' },
38
- animate: { opacity: 1, filter: 'blur(0px)' },
39
- exit: { opacity: 0, filter: 'blur(5px)', transition: { duration: 0.2 } }
40
- }
41
- };
@@ -6,7 +6,7 @@ export declare namespace Icon {
6
6
  size?: Size;
7
7
  };
8
8
  type Size = 'xl' | 'lg' | 'md' | 'sm' | 'xs' | 'xxs' | 'nav' | 'card' | Sizing;
9
- type Variant = 'Archive' | 'ArrowLeft' | 'ArrowRight' | 'ArrowLeftRight' | 'Atom' | 'Blocks' | 'Bold' | 'Check' | 'ChevronDown' | 'ChevronRight' | 'ChevronUp' | 'Circle' | 'CircleAlert' | 'CircleCheck' | 'CircleCheckBig' | 'CirclePlus' | 'CircleQuestionMark' | 'CloudCheck' | 'CloudUpload' | 'CornerDownRight' | 'EllipsisVertical' | 'Eye' | 'EyeOff' | 'File' | 'FileDown' | 'FilePlusCorner' | 'FileSearchCorner' | 'Goal' | 'Globe' | 'GripVertical' | 'HatGlasses' | 'History' | 'Highlighter' | 'Image' | 'ImageDown' | 'Info' | 'Italic' | 'Layers' | 'LayoutTemplate' | 'Link' | 'Link2' | 'List' | 'ListChecks' | 'ListIndentDecrease' | 'ListIndentIncrease' | 'ListOrdered' | 'Lock' | 'LockOpen' | 'Mail' | 'MessageSquareQuote' | 'Minus' | 'Monitor' | 'MonitorCog' | 'Moon' | 'NotebookPen' | 'Pencil' | 'Pin' | 'Plus' | 'Redo' | 'RefreshCw' | 'RotateCcw' | 'RotateCw' | 'SearchCode' | 'Settings' | 'Smartphone' | 'SquarePlay' | 'Star' | 'Strikethrough' | 'Subscript' | 'Sun' | 'Superscript' | 'TextAlignStart' | 'Trash' | 'TriangleAlert' | 'Trophy' | 'Underline' | 'Undo' | 'Upload' | 'UserRound' | 'X';
9
+ type Variant = 'Archive' | 'ArrowLeft' | 'ArrowRight' | 'ArrowLeftRight' | 'Atom' | 'Blocks' | 'Bold' | 'Check' | 'ChevronDown' | 'ChevronRight' | 'ChevronUp' | 'Circle' | 'CircleAlert' | 'CircleCheck' | 'CircleCheckBig' | 'CirclePlus' | 'CircleQuestionMark' | 'CloudCheck' | 'CloudUpload' | 'CornerDownRight' | 'EllipsisVertical' | 'Eye' | 'EyeOff' | 'File' | 'FileDown' | 'FilePlusCorner' | 'FileSearchCorner' | 'Goal' | 'Globe' | 'GripVertical' | 'HatGlasses' | 'History' | 'Highlighter' | 'Image' | 'ImageDown' | 'Info' | 'Italic' | 'Layers' | 'LayoutTemplate' | 'Link' | 'Link2' | 'List' | 'ListChecks' | 'ListIndentDecrease' | 'ListIndentIncrease' | 'ListOrdered' | 'Lock' | 'LockOpen' | 'Mail' | 'MessageSquareQuote' | 'Minus' | 'Monitor' | 'MonitorCog' | 'Moon' | 'NotebookPen' | 'Pencil' | 'Pin' | 'Plus' | 'Redo' | 'RefreshCw' | 'RotateCcw' | 'RotateCw' | 'Search' | 'SearchCode' | 'Settings' | 'Smartphone' | 'SquarePlay' | 'Star' | 'Strikethrough' | 'Subscript' | 'Sun' | 'Superscript' | 'TextAlignStart' | 'Trash' | 'TriangleAlert' | 'Trophy' | 'Underline' | 'Undo' | 'Upload' | 'UserRound' | 'X';
10
10
  namespace Variant {
11
11
  function filter(value: any): value is Variant;
12
12
  }
@@ -80,6 +80,7 @@ function Icon({ className, variant, size: sizing = 'md' }) {
80
80
  'RefreshCw',
81
81
  'RotateCcw',
82
82
  'RotateCw',
83
+ 'Search',
83
84
  'SearchCode',
84
85
  'Settings',
85
86
  'Smartphone',
@@ -235,6 +236,8 @@ function getIcon(variant) {
235
236
  return lucide_react_1.RotateCcw;
236
237
  case 'RotateCw':
237
238
  return lucide_react_1.RotateCw;
239
+ case 'Search':
240
+ return lucide_react_1.Search;
238
241
  case 'SearchCode':
239
242
  return lucide_react_1.SearchCode;
240
243
  case 'Settings':
@@ -0,0 +1,2 @@
1
+ import { PropsWithChildren } from 'react';
2
+ export declare function AssetRepositoryContainer({ children }: PropsWithChildren): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AssetRepositoryContainer = AssetRepositoryContainer;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const client_1 = require("../client");
7
+ const hooks_1 = require("../hooks");
8
+ const repository_1 = require("../repository");
9
+ // container
10
+ function AssetRepositoryContainer({ children }) {
11
+ // bind to hooks
12
+ const client = (0, client_1.useEditorApi)();
13
+ const repository = (0, react_1.useMemo)(() => {
14
+ return new repository_1.AssetRepository(client);
15
+ }, [client]);
16
+ // render
17
+ return ((0, jsx_runtime_1.jsx)(hooks_1.AssetRepositoryContext.Provider, { value: repository, children: children }));
18
+ }
@@ -0,0 +1,2 @@
1
+ import { PropsWithChildren } from 'react';
2
+ export declare function CollectionRepositoryContainer({ children }: PropsWithChildren): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CollectionRepositoryContainer = CollectionRepositoryContainer;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const client_1 = require("../client");
7
+ const hooks_1 = require("../hooks");
8
+ const repository_1 = require("../repository");
9
+ // container
10
+ function CollectionRepositoryContainer({ children }) {
11
+ // bind to hooks
12
+ const client = (0, client_1.useEditorApi)();
13
+ const repository = (0, react_1.useMemo)(() => {
14
+ return new repository_1.CollectionRepository(client);
15
+ }, [client]);
16
+ // render
17
+ return ((0, jsx_runtime_1.jsx)(hooks_1.CollectionRepositoryContext.Provider, { value: repository, children: children }));
18
+ }
@@ -0,0 +1,2 @@
1
+ import { PropsWithChildren } from 'react';
2
+ export declare function PageRepositoryContainer({ children }: PropsWithChildren): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PageRepositoryContainer = PageRepositoryContainer;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const client_1 = require("../client");
7
+ const hooks_1 = require("../hooks");
8
+ const repository_1 = require("../repository");
9
+ // container
10
+ function PageRepositoryContainer({ children }) {
11
+ // bind to hooks
12
+ const client = (0, client_1.useEditorApi)();
13
+ const repository = (0, react_1.useMemo)(() => {
14
+ return new repository_1.PageRepository(client);
15
+ }, [client]);
16
+ // render
17
+ return ((0, jsx_runtime_1.jsx)(hooks_1.PageRepositoryContext.Provider, { value: repository, children: children }));
18
+ }
@@ -0,0 +1,3 @@
1
+ export * from './AssetRepositoryContainer';
2
+ export * from './CollectionRepositoryContainer';
3
+ export * from './PageRepositoryContainer';
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./AssetRepositoryContainer"), exports);
18
+ __exportStar(require("./CollectionRepositoryContainer"), exports);
19
+ __exportStar(require("./PageRepositoryContainer"), exports);