efficient-web-builder 1.0.0 → 2.0.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 (340) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +2 -1
  3. package/dist/components/AddBlockRow.d.ts +1 -7
  4. package/dist/components/AddBlockRow.js +1 -1
  5. package/dist/components/AddChildRow.d.ts +1 -6
  6. package/dist/components/AddChildRow.js +1 -1
  7. package/dist/components/AddSidePanel.d.ts +2 -39
  8. package/dist/components/AddSidePanel.js +1 -1
  9. package/dist/components/BlockGapField.js +1 -1
  10. package/dist/components/BlogPostSource.js +1 -1
  11. package/dist/components/CardShadowField.js +1 -1
  12. package/dist/components/ChatSettingsPanel.js +1 -1
  13. package/dist/components/CornersField.d.ts +0 -1
  14. package/dist/components/CornersField.js +1 -1
  15. package/dist/components/DuplicateToPageMenu.js +1 -1
  16. package/dist/components/EditorScreenMount.d.ts +1 -0
  17. package/dist/components/EditorScreenMount.js +1 -0
  18. package/dist/components/EditorStoreProvider.d.ts +1 -0
  19. package/dist/components/EditorStoreProvider.js +1 -0
  20. package/dist/components/HeroImageField.js +1 -1
  21. package/dist/components/HeroSection.d.ts +2 -6
  22. package/dist/components/HeroSection.js +4 -4
  23. package/dist/components/HoverEffectField.js +1 -1
  24. package/dist/components/ImageFocusRow.js +1 -1
  25. package/dist/components/KeepHint.d.ts +5 -0
  26. package/dist/components/KeepHint.js +1 -0
  27. package/dist/components/LocationsGroupedField.js +1 -1
  28. package/dist/components/MediaSidePanel.d.ts +1 -6
  29. package/dist/components/MediaSidePanel.js +1 -1
  30. package/dist/components/MediaUploadField.js +1 -1
  31. package/dist/components/MultiSelectField.d.ts +4 -1
  32. package/dist/components/MultiSelectField.js +1 -1
  33. package/dist/components/NodeContextMenu.d.ts +2 -96
  34. package/dist/components/NodeContextMenu.js +1 -1
  35. package/dist/components/PageEditGuardNotices.d.ts +1 -1
  36. package/dist/components/PageEditGuardNotices.js +1 -1
  37. package/dist/components/PanelToggleIcon.d.ts +1 -3
  38. package/dist/components/PanelToggleIcon.js +1 -1
  39. package/dist/components/PartSettingsPanel.d.ts +5 -0
  40. package/dist/components/PartSettingsPanel.js +1 -1
  41. package/dist/components/PhotographyField.js +1 -1
  42. package/dist/components/PreviewDeviceContext.d.ts +2 -4
  43. package/dist/components/PreviewDeviceContext.js +1 -1
  44. package/dist/components/PreviewPartsContext.d.ts +1 -3
  45. package/dist/components/PreviewPartsContext.js +1 -1
  46. package/dist/components/SearchSelectField.d.ts +3 -1
  47. package/dist/components/SearchSelectField.js +1 -1
  48. package/dist/components/SectionEditor.d.ts +2 -5
  49. package/dist/components/SectionEditor.js +1 -1
  50. package/dist/components/SectionEditorShell.d.ts +1 -1
  51. package/dist/components/SectionEditorShell.js +1 -1
  52. package/dist/components/SectionThemePicker.d.ts +3 -1
  53. package/dist/components/SectionThemePicker.js +1 -1
  54. package/dist/components/ShadowColourField.js +1 -1
  55. package/dist/components/SidePanelHead.d.ts +1 -23
  56. package/dist/components/SidePanelHead.js +1 -1
  57. package/dist/components/SideSpaceField.d.ts +0 -1
  58. package/dist/components/SideSpaceField.js +1 -1
  59. package/dist/components/SiteEditorProvider.d.ts +3 -10
  60. package/dist/components/SiteEditorProvider.js +1 -1
  61. package/dist/components/SiteWidthField.d.ts +0 -1
  62. package/dist/components/SiteWidthField.js +1 -1
  63. package/dist/components/SlotChildActionsContext.d.ts +2 -13
  64. package/dist/components/SlotChildActionsContext.js +1 -1
  65. package/dist/components/SocialLinksPanel.js +1 -1
  66. package/dist/components/SourceStatus.js +1 -1
  67. package/dist/components/StandaloneSectionEditor.d.ts +1 -0
  68. package/dist/components/StandaloneSectionEditor.js +1 -1
  69. package/dist/components/StorefrontDocumentContext.d.ts +2 -67
  70. package/dist/components/StorefrontDocumentContext.js +1 -1
  71. package/dist/components/StorefrontEditor.d.ts +1 -0
  72. package/dist/components/StorefrontEditor.js +1 -1
  73. package/dist/components/StorefrontEditorChrome.d.ts +1 -1
  74. package/dist/components/StorefrontEditorChrome.js +1 -1
  75. package/dist/components/StorefrontLinkField.d.ts +9 -0
  76. package/dist/components/StorefrontLinkField.js +1 -1
  77. package/dist/components/ThemeField.js +1 -1
  78. package/dist/components/TickerSettingsPanel.js +1 -1
  79. package/dist/components/UiIcon.d.ts +2 -10
  80. package/dist/components/UiIcon.js +1 -1
  81. package/dist/components/WebsiteScreenParts.d.ts +2 -0
  82. package/dist/components/WebsiteScreenParts.js +1 -0
  83. package/dist/components/WidthFollowField.js +1 -1
  84. package/dist/components/panel-widths.d.ts +2 -12
  85. package/dist/components/panel-widths.js +1 -1
  86. package/dist/components/storefront-editor.css +125 -986
  87. package/dist/components/useFooterFocus.d.ts +2 -0
  88. package/dist/components/useFooterFocus.js +1 -0
  89. package/dist/components/useLocationsTree.d.ts +6 -0
  90. package/dist/components/useLocationsTree.js +1 -0
  91. package/dist/components/usePartBridge.d.ts +1 -9
  92. package/dist/components/usePartBridge.js +1 -1
  93. package/dist/components/usePinnedChromeSeed.d.ts +2 -0
  94. package/dist/components/usePinnedChromeSeed.js +1 -0
  95. package/dist/components/useSocialSettings.js +1 -1
  96. package/dist/components/useStorefrontBlogPosts.js +1 -1
  97. package/dist/lib/client-only.d.ts +1 -0
  98. package/dist/lib/client-only.js +1 -0
  99. package/dist/lib/content/view-tiers.d.ts +2 -6
  100. package/dist/lib/content/view-tiers.js +1 -1
  101. package/dist/lib/editor-admin-bridge.d.ts +2 -29
  102. package/dist/lib/editor-admin-bridge.js +1 -1
  103. package/dist/lib/editor-backend-error.d.ts +2 -0
  104. package/dist/lib/editor-backend-error.js +1 -0
  105. package/dist/lib/editor-blocks.d.ts +2 -2
  106. package/dist/lib/editor-chrome.d.ts +2 -52
  107. package/dist/lib/editor-chrome.js +1 -1
  108. package/dist/lib/editor-document-adapter.d.ts +3 -51
  109. package/dist/lib/editor-document-adapter.js +1 -1
  110. package/dist/lib/editor-document-addressing.d.ts +2 -0
  111. package/dist/lib/editor-document-addressing.js +1 -0
  112. package/dist/lib/editor-document-contract.d.ts +1 -0
  113. package/dist/lib/editor-document-contract.js +0 -0
  114. package/dist/lib/editor-document-hooks.d.ts +1 -15
  115. package/dist/lib/editor-document-switch.d.ts +2 -0
  116. package/dist/lib/editor-document-switch.js +1 -0
  117. package/dist/lib/editor-failure.d.ts +1 -4
  118. package/dist/lib/editor-failure.js +1 -1
  119. package/dist/lib/editor-host-inbound.d.ts +1 -1
  120. package/dist/lib/editor-host-inbound.js +1 -1
  121. package/dist/lib/editor-host.d.ts +2 -135
  122. package/dist/lib/editor-host.js +1 -1
  123. package/dist/lib/editor-key-scope.d.ts +1 -3
  124. package/dist/lib/editor-key-scope.js +1 -1
  125. package/dist/lib/editor-load-error.d.ts +1 -4
  126. package/dist/lib/editor-load-error.js +1 -1
  127. package/dist/lib/editor-media-panel.d.ts +2 -23
  128. package/dist/lib/editor-media-panel.js +1 -1
  129. package/dist/lib/editor-media-picker.d.ts +2 -12
  130. package/dist/lib/editor-media-picker.js +1 -1
  131. package/dist/lib/editor-page-lock.d.ts +1 -1
  132. package/dist/lib/editor-page-lock.js +1 -1
  133. package/dist/lib/editor-screen.d.ts +2 -0
  134. package/dist/lib/editor-screen.js +1 -0
  135. package/dist/lib/editor-section-templates.d.ts +1 -2
  136. package/dist/lib/editor-section-templates.js +1 -1
  137. package/dist/lib/editor-session-context.d.ts +1 -7
  138. package/dist/lib/editor-session-context.js +1 -1
  139. package/dist/lib/editor-session.d.ts +2 -45
  140. package/dist/lib/editor-session.js +1 -1
  141. package/dist/lib/editor-site-slug.js +1 -1
  142. package/dist/lib/editor-theme.d.ts +1 -1
  143. package/dist/lib/editor-theme.js +1 -1
  144. package/dist/lib/hero-arrows.d.ts +1 -1
  145. package/dist/lib/links/link-filters.d.ts +1 -0
  146. package/dist/lib/links/link-filters.js +0 -0
  147. package/dist/lib/links/link-picker-setup.d.ts +29 -0
  148. package/dist/lib/links/link-picker-setup.js +1 -0
  149. package/dist/lib/puck/ColourControl.d.ts +4 -1
  150. package/dist/lib/puck/ColourControl.js +1 -1
  151. package/dist/lib/puck/add-palette.d.ts +3 -9
  152. package/dist/lib/puck/add-palette.js +1 -1
  153. package/dist/lib/puck/add-target-types.d.ts +1 -0
  154. package/dist/lib/puck/add-target-types.js +0 -0
  155. package/dist/lib/puck/add-target.d.ts +2 -9
  156. package/dist/lib/puck/block-choice.d.ts +2 -0
  157. package/dist/lib/puck/block-choice.js +1 -0
  158. package/dist/lib/puck/block-offer.js +1 -1
  159. package/dist/lib/puck/block-types-in.d.ts +1 -1
  160. package/dist/lib/puck/block-types-in.js +1 -1
  161. package/dist/lib/puck/blocks/general/index.d.ts +2 -2
  162. package/dist/lib/puck/content-tree.d.ts +2 -43
  163. package/dist/lib/puck/content-tree.js +1 -1
  164. package/dist/lib/puck/controls.d.ts +11 -22
  165. package/dist/lib/puck/controls.js +1 -1
  166. package/dist/lib/puck/device-fields.d.ts +2 -24
  167. package/dist/lib/puck/device-fields.js +1 -1
  168. package/dist/lib/puck/field-buckets.d.ts +2 -0
  169. package/dist/lib/puck/field-buckets.js +1 -0
  170. package/dist/lib/puck/field-groups.d.ts +3 -3
  171. package/dist/lib/puck/field-groups.js +1 -1
  172. package/dist/lib/puck/field-markers.d.ts +2 -16
  173. package/dist/lib/puck/field-markers.js +1 -1
  174. package/dist/lib/puck/footer-block-row-name.d.ts +4 -0
  175. package/dist/lib/puck/footer-block-row-name.js +1 -0
  176. package/dist/lib/puck/footer-blocks.d.ts +2 -10
  177. package/dist/lib/puck/footer-blocks.js +1 -1
  178. package/dist/lib/puck/hidable.d.ts +2 -9
  179. package/dist/lib/puck/hidable.js +1 -1
  180. package/dist/lib/puck/palette-sections.d.ts +2 -0
  181. package/dist/lib/puck/palette-sections.js +1 -0
  182. package/dist/lib/puck/panel-fields.d.ts +2 -12
  183. package/dist/lib/puck/panel-fields.js +1 -1
  184. package/dist/lib/puck/panel-no-control-mark.d.ts +2 -7
  185. package/dist/lib/puck/panel-no-control-mark.js +1 -1
  186. package/dist/lib/puck/part-id.d.ts +1 -0
  187. package/dist/lib/puck/part-id.js +1 -0
  188. package/dist/lib/puck/pinned-seed-gate.d.ts +2 -12
  189. package/dist/lib/puck/pinned-seed-gate.js +1 -1
  190. package/dist/lib/puck/preview-click.d.ts +1 -2
  191. package/dist/lib/puck/preview-click.js +1 -1
  192. package/dist/lib/puck/preview-dom.d.ts +1 -6
  193. package/dist/lib/puck/preview-dom.js +1 -1
  194. package/dist/lib/puck/preview-events.d.ts +2 -0
  195. package/dist/lib/puck/preview-events.js +1 -0
  196. package/dist/lib/puck/preview-selection-context.d.ts +2 -19
  197. package/dist/lib/puck/preview-selection-context.js +1 -1
  198. package/dist/lib/puck/section-doc.d.ts +1 -5
  199. package/dist/lib/puck/section-doc.js +1 -1
  200. package/dist/lib/puck/section-groups.d.ts +1 -1
  201. package/dist/lib/puck/slot-child-name.d.ts +2 -8
  202. package/dist/lib/puck/slot-child-name.js +1 -1
  203. package/dist/lib/puck/slot-heal.d.ts +1 -2
  204. package/dist/lib/puck/slot-heal.js +1 -1
  205. package/dist/lib/puck/slot-section-spec.d.ts +1 -0
  206. package/dist/lib/puck/slot-section-spec.js +0 -0
  207. package/dist/lib/puck/slot-specs.d.ts +2 -13
  208. package/dist/lib/puck/style-clipboard.d.ts +1 -19
  209. package/dist/lib/puck/style-clipboard.js +1 -1
  210. package/dist/lib/puck/text-control-kinds.d.ts +2 -13
  211. package/dist/lib/puck/text-control-kinds.js +1 -1
  212. package/dist/lib/puck/text-parts.d.ts +2 -5
  213. package/dist/lib/puck/text-parts.js +1 -1
  214. package/dist/lib/puck/tree-reveal.d.ts +1 -11
  215. package/dist/lib/puck/tree-reveal.js +1 -1
  216. package/dist/lib/puck/use-section-ops.d.ts +2 -25
  217. package/dist/lib/puck/use-section-ops.js +1 -1
  218. package/dist/lib/reel.d.ts +1 -1
  219. package/dist/lib/section-template-types.d.ts +1 -21
  220. package/dist/lib/sections/new-section-node.d.ts +2 -0
  221. package/dist/lib/sections/new-section-node.js +1 -0
  222. package/dist/lib/source-rules/accent-token-name.d.ts +20 -0
  223. package/dist/lib/source-rules/accent-token-name.js +4 -0
  224. package/dist/lib/source-rules/button-corners.d.ts +13 -0
  225. package/dist/lib/source-rules/button-corners.js +2 -0
  226. package/dist/lib/source-rules/editor-chrome-note.d.ts +16 -0
  227. package/dist/lib/source-rules/editor-chrome-note.js +13 -0
  228. package/dist/lib/source-rules/editor-context-menu.d.ts +5 -0
  229. package/dist/lib/source-rules/editor-context-menu.js +4 -0
  230. package/dist/lib/source-rules/editor-puck-drag-off.d.ts +8 -0
  231. package/dist/lib/source-rules/editor-puck-drag-off.js +4 -0
  232. package/dist/lib/source-rules/efficient-easel-version.d.ts +9 -0
  233. package/dist/lib/source-rules/efficient-easel-version.js +2 -0
  234. package/dist/lib/source-rules/every-button-follows-the-button-colour.d.ts +12 -0
  235. package/dist/lib/source-rules/every-button-follows-the-button-colour.js +7 -0
  236. package/dist/lib/source-rules/flat-theme-palette.d.ts +10 -0
  237. package/dist/lib/source-rules/flat-theme-palette.js +8 -0
  238. package/dist/lib/source-rules/full-width-means-full.d.ts +8 -0
  239. package/dist/lib/source-rules/full-width-means-full.js +2 -0
  240. package/dist/lib/source-rules/heading-ceiling-sweep.d.ts +11 -0
  241. package/dist/lib/source-rules/heading-ceiling-sweep.js +8 -0
  242. package/dist/lib/source-rules/label-hints.d.ts +7 -0
  243. package/dist/lib/source-rules/label-hints.js +5 -0
  244. package/dist/lib/source-rules/label-vocabulary.d.ts +14 -0
  245. package/dist/lib/source-rules/label-vocabulary.js +5 -0
  246. package/dist/lib/source-rules/mirrored-rows-agree.d.ts +19 -0
  247. package/dist/lib/source-rules/mirrored-rows-agree.js +10 -0
  248. package/dist/lib/source-rules/no-comment-in-jsx.d.ts +9 -0
  249. package/dist/lib/source-rules/no-comment-in-jsx.js +7 -0
  250. package/dist/lib/source-rules/no-glyph-rows.d.ts +15 -0
  251. package/dist/lib/source-rules/no-glyph-rows.js +4 -0
  252. package/dist/lib/source-rules/one-colour-control.d.ts +7 -0
  253. package/dist/lib/source-rules/one-colour-control.js +2 -0
  254. package/dist/lib/source-rules/one-dropdown.d.ts +10 -0
  255. package/dist/lib/source-rules/one-dropdown.js +4 -0
  256. package/dist/lib/source-rules/one-editable-list.d.ts +16 -0
  257. package/dist/lib/source-rules/one-editable-list.js +6 -0
  258. package/dist/lib/source-rules/one-editor-list.d.ts +7 -0
  259. package/dist/lib/source-rules/one-editor-list.js +3 -0
  260. package/dist/lib/source-rules/one-right-click.d.ts +10 -0
  261. package/dist/lib/source-rules/one-right-click.js +2 -0
  262. package/dist/lib/source-rules/one-switch.d.ts +9 -0
  263. package/dist/lib/source-rules/one-switch.js +7 -0
  264. package/dist/lib/source-rules/one-up-level-link.d.ts +16 -0
  265. package/dist/lib/source-rules/one-up-level-link.js +18 -0
  266. package/dist/lib/source-rules/panel-colour-tokens.d.ts +48 -0
  267. package/dist/lib/source-rules/panel-colour-tokens.js +20 -0
  268. package/dist/lib/source-rules/panel-no-divider-lines.d.ts +14 -0
  269. package/dist/lib/source-rules/panel-no-divider-lines.js +10 -0
  270. package/dist/lib/source-rules/panel-one-arrow.d.ts +21 -0
  271. package/dist/lib/source-rules/panel-one-arrow.js +1 -0
  272. package/dist/lib/source-rules/panel-one-hover.d.ts +8 -0
  273. package/dist/lib/source-rules/panel-one-hover.js +2 -0
  274. package/dist/lib/source-rules/panel-rows-use-the-shared-row.d.ts +23 -0
  275. package/dist/lib/source-rules/panel-rows-use-the-shared-row.js +22 -0
  276. package/dist/lib/source-rules/part-slider-fills-row.d.ts +11 -0
  277. package/dist/lib/source-rules/part-slider-fills-row.js +29 -0
  278. package/dist/lib/source-rules/part-style-naming.d.ts +10 -0
  279. package/dist/lib/source-rules/part-style-naming.js +2 -0
  280. package/dist/lib/source-rules/puck-document-surfaces.d.ts +16 -0
  281. package/dist/lib/source-rules/puck-document-surfaces.js +8 -0
  282. package/dist/lib/source-rules/reduced-motion.d.ts +26 -0
  283. package/dist/lib/source-rules/reduced-motion.js +9 -0
  284. package/dist/lib/source-rules/route-content-width.d.ts +22 -0
  285. package/dist/lib/source-rules/route-content-width.js +5 -0
  286. package/dist/lib/source-rules/rule.d.ts +21 -0
  287. package/dist/lib/source-rules/rule.js +1 -0
  288. package/dist/lib/source-rules/section-theme-preview.d.ts +9 -0
  289. package/dist/lib/source-rules/section-theme-preview.js +8 -0
  290. package/dist/lib/source-rules/site-gutter.d.ts +6 -0
  291. package/dist/lib/source-rules/site-gutter.js +4 -0
  292. package/dist/lib/source-rules/site-square-by-default.d.ts +17 -0
  293. package/dist/lib/source-rules/site-square-by-default.js +3 -0
  294. package/dist/lib/source-rules/site-width.d.ts +11 -0
  295. package/dist/lib/source-rules/site-width.js +7 -0
  296. package/dist/lib/source-rules/size-token-paints.d.ts +8 -0
  297. package/dist/lib/source-rules/size-token-paints.js +11 -0
  298. package/dist/lib/source-rules/social-icons-import.d.ts +6 -0
  299. package/dist/lib/source-rules/social-icons-import.js +6 -0
  300. package/dist/lib/source-rules/source-status-is-shared.d.ts +7 -0
  301. package/dist/lib/source-rules/source-status-is-shared.js +1 -0
  302. package/dist/lib/source-rules/style-face-matches-size.d.ts +10 -0
  303. package/dist/lib/source-rules/style-face-matches-size.js +4 -0
  304. package/dist/lib/source-rules/support/accent-rename-bytes.d.ts +5 -0
  305. package/dist/lib/source-rules/support/accent-rename-bytes.js +1 -0
  306. package/dist/lib/source-rules/support/css-box-model.d.ts +5 -0
  307. package/dist/lib/source-rules/support/css-box-model.js +1 -0
  308. package/dist/lib/source-rules/support/css-length.d.ts +2 -0
  309. package/dist/lib/source-rules/support/css-length.js +1 -0
  310. package/dist/lib/source-rules/support/css-rules.d.ts +12 -0
  311. package/dist/lib/source-rules/support/css-rules.js +1 -0
  312. package/dist/lib/source-rules/support/css-source.d.ts +2 -0
  313. package/dist/lib/source-rules/support/css-source.js +3 -0
  314. package/dist/lib/source-rules/support/label-extraction.d.ts +14 -0
  315. package/dist/lib/source-rules/support/label-extraction.js +5 -0
  316. package/dist/lib/source-rules/support/panel-select-cascade.d.ts +72 -0
  317. package/dist/lib/source-rules/support/panel-select-cascade.js +2 -0
  318. package/dist/lib/source-rules/support/part-slider-call-sites.d.ts +9 -0
  319. package/dist/lib/source-rules/support/part-slider-call-sites.js +17 -0
  320. package/dist/lib/source-rules/support/registry-source.d.ts +14 -0
  321. package/dist/lib/source-rules/support/registry-source.js +3 -0
  322. package/dist/lib/source-rules/support/ts-source.d.ts +2 -0
  323. package/dist/lib/source-rules/support/ts-source.js +3 -0
  324. package/dist/lib/source-rules/theme-mode-controls-gone.d.ts +10 -0
  325. package/dist/lib/source-rules/theme-mode-controls-gone.js +5 -0
  326. package/dist/lib/source-rules/upload-intake-guard.d.ts +11 -0
  327. package/dist/lib/source-rules/upload-intake-guard.js +6 -0
  328. package/dist/lib/source-rules/word-styles.d.ts +8 -0
  329. package/dist/lib/source-rules/word-styles.js +4 -0
  330. package/dist/lib/theme-row-persist.js +1 -1
  331. package/dist/lib/theme-save-message.js +1 -1
  332. package/dist/lib/web-backend.d.ts +4 -59
  333. package/dist/lib/web-backend.js +1 -1
  334. package/dist/lib/website-document-addressing.d.ts +2 -0
  335. package/dist/lib/website-document-addressing.js +1 -0
  336. package/dist/lib/website-host-inbound.d.ts +1 -0
  337. package/dist/lib/website-host-inbound.js +1 -0
  338. package/dist/lib/website-session.d.ts +5 -0
  339. package/dist/lib/website-session.js +1 -0
  340. package/package.json +15 -5
package/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.0.0 - 2026-10-10
4
+
5
+ - **The editor's screen comes from `efficient-easel`.** The screen's 67
6
+ modules (the canvas, the side panels, the context menu, the toolbar, the
7
+ document context) live in `efficient-easel/screen` now. Each keeps its path
8
+ here as a re-export under its old names, so `efficient-web-builder/components/
9
+ AddSidePanel` and `.../StorefrontDocumentContext` still import as before. The
10
+ website hands the screen what is its own: its block rules, its panel wiring,
11
+ its toolbar and devices, its left views and rail, its pinned chrome, how a
12
+ block is named and drawn, and how a document is addressed. The screen's
13
+ stylesheet is `efficient-easel/screen.css`, loaded before
14
+ `components/storefront-editor.css`.
15
+ - **Settings rows are easel's.** Every settings row is one `SettingsField` with
16
+ one hint line; the part panel's and the Locations panel's backs are easel's
17
+ up-level link; the text region's Style row opens easel's `FieldSelect`; the
18
+ Link field is easel's shared `LinkPicker`; one Default / Reset part, drawn as
19
+ a revert icon with grey defaults.
20
+ - **Tree-wide rules ship with the package** (`lib/source-rules/`): 41 rules
21
+ over source text, and the N10 label vocabulary, written once here and run by
22
+ each repository over its own files. `typescript` is an optional peer
23
+ dependency, handed in by a repository that runs them.
24
+ - **Breaking.** `components/CornersField`, `components/SideSpaceField` and
25
+ `components/SiteWidthField` export `CORNERS_LABEL`, `SIDE_SPACE_LABEL` and
26
+ `SITE_WIDTH_LABEL` in place of their `*_UNSET_LABEL` constants, and
27
+ `lib/puck/controls` no longer exports `InheritBadge`, `SiteGapInheritBadge`,
28
+ `WidthInheritBadge` or `TypeGlyph` (the Default / Reset part replaced them).
29
+ No other module or export was removed; 81 modules were added.
30
+ - **Peer dependencies.** `efficient-easel` ^0.106.0 (was ^0.101.0), and
31
+ `typescript` ^5, optional.
32
+
3
33
  ## 1.0.0 - 2026-10-07
4
34
 
5
35
  - **`efficient-web-builder` is published from its own repository.** The
package/README.md CHANGED
@@ -111,7 +111,8 @@ pnpm install
111
111
  pnpm run verify
112
112
  ```
113
113
 
114
- `verify` is the typecheck, the boundary check, the build and
114
+ `verify` is the typecheck, the boundary check, the screen rule
115
+ (`scripts/test-screen-in-easel.mjs`, `doc/adr/0004`), the build and
115
116
  `scripts/verify-dist.mjs`, which reads `dist/` as a host would: every file
116
117
  there, every import resolving, every `"use client"` kept, no source in it.
117
118
 
@@ -1,7 +1 @@
1
- import { type BlockChoice } from "../lib/puck/footer-blocks.js";
2
- export default function AddBlockRow({ choices, onPick, open, onToggle, }: {
3
- choices: BlockChoice[];
4
- onPick: (type: string) => void;
5
- open?: boolean;
6
- onToggle?: () => void;
7
- }): import("react").JSX.Element;
1
+ export { default } from "efficient-easel/screen/components/AddBlockRow";
@@ -1 +1 @@
1
- "use client";import{jsx as s,jsxs as n,Fragment as p}from"react/jsx-runtime";import{Fragment as d,useState as u}from"react";import f from"./SectionIcon.js";import{blockRuns as g}from"../lib/puck/footer-blocks.js";function h({choices:o,onPick:m,open:c,onToggle:r}){const[i,a]=u(!1),t=c??i;return n(p,{children:[n("button",{type:"button",className:"sf-add-card","aria-expanded":t,onClick:r??(()=>a(e=>!e)),children:[s("span",{className:"sf-plus sf-plus--sm",children:"+"}),"Add block"]}),t&&s("div",{className:"sf-blockmenu",role:"menu",children:g(o).map(e=>n(d,{children:[e.group&&n("div",{className:"sf-menugroup-head",role:"presentation",children:[s("span",{className:"sf-menugroup-title",children:e.group}),s("span",{className:"sf-menugroup-count",children:e.items.length})]}),e.items.map(l=>n("button",{type:"button",className:"sf-blockmenu-item",role:"menuitem",onClick:()=>{a(!1),m(l.type)},children:[s("span",{className:"sf-chip",children:s(f,{type:l.type,size:13})}),s("span",{className:"sf-row-name",children:l.label})]},l.type))]},e.group??"all"))})]})}export{h as default};
1
+ "use client";import{default as f}from"efficient-easel/screen/components/AddBlockRow";export{f as default};
@@ -1,6 +1 @@
1
- export default function AddChildRow({ label, blocked, onAdd, small, }: {
2
- label: string;
3
- blocked: string | null;
4
- onAdd: () => void;
5
- small?: boolean;
6
- }): import("react").JSX.Element;
1
+ export { default } from "efficient-easel/screen/components/AddChildRow";
@@ -1 +1 @@
1
- "use client";import{jsx as t,jsxs as a}from"react/jsx-runtime";function d({label:l,blocked:s,onAdd:e,small:n=!1}){return a("button",{type:"button",className:"sf-add-card",disabled:s!==null,title:s??void 0,onClick:e,children:[t("span",{className:n?"sf-plus sf-plus--sm":"sf-plus",children:"+"}),l]})}export{d as default};
1
+ "use client";import{default as f}from"efficient-easel/screen/components/AddChildRow";export{f as default};
@@ -1,39 +1,2 @@
1
- import { type DragSession } from "efficient-easel/drag";
2
- import type { SectionTemplate } from "../lib/section-template-types.js";
3
- import { type BlockChoice } from "../lib/puck/footer-blocks.js";
4
- export type AddKey = {
5
- kind: "section";
6
- type: string;
7
- } | {
8
- kind: "template";
9
- template: SectionTemplate;
10
- } | {
11
- kind: "block";
12
- type: string;
13
- };
14
- export declare const sectionKey: (type: string) => string;
15
- export declare const blockKey: (type: string) => string;
16
- export declare const templateKey: (id: string) => string;
17
- export type AddSidePanelProps<I> = {
18
- blocks: {
19
- parentName: string;
20
- choices: BlockChoice[];
21
- } | null;
22
- blocksOnly: boolean;
23
- at?: {
24
- label: string;
25
- onClear: () => void;
26
- };
27
- onAdd: (key: AddKey) => void;
28
- itemFor: (key: AddKey) => I;
29
- session: DragSession<I>;
30
- siteWide?: {
31
- chatEnabled: boolean;
32
- onToggleChat: (on: boolean) => void;
33
- onOpenChat: () => void;
34
- };
35
- onClose: () => void;
36
- onHide?: () => void;
37
- readOnly?: boolean;
38
- };
39
- export default function AddSidePanel<I>({ blocks, blocksOnly, at, onAdd, itemFor, session, siteWide, onClose, onHide, readOnly, }: AddSidePanelProps<I>): import("react").JSX.Element;
1
+ export { blockKey, default, sectionKey, templateKey } from "efficient-easel/screen/components/AddSidePanel";
2
+ export type { AddKey, AddSidePanelProps } from "efficient-easel/screen/components/AddSidePanel";
@@ -1 +1 @@
1
- "use client";import{jsx as s,jsxs as m,Fragment as T}from"react/jsx-runtime";import{useEffect as L,useMemo as g,useState as P}from"react";import{useEasel as j}from"efficient-easel/easel";import{AddPanel as D}from"efficient-easel/drag";import y from"./SectionIcon.js";import _,{PanelModeExit as z}from"./SidePanelHead.js";import{AddIcon as F}from"efficient-easel/icons";import S from"./SectionThumbnail.js";import{sectionTemplates as K}from"../lib/editor-section-templates.js";import{useEditorSession as O}from"../lib/editor-session-context.js";import{buildPaletteSections as B,categoryLabel as H,paletteWithoutPinned as M,pinnedSection as R}from"../lib/puck/add-palette.js";import{blockOfferOf as Y}from"../lib/puck/block-offer.js";import{blockTypesIn as q}from"../lib/puck/block-types-in.js";import{SettingsSwitch as G}from"efficient-easel/panel";import{blockRuns as J}from"../lib/puck/footer-blocks.js";import{SECTION_DESCRIPTIONS as Q}from"../lib/puck/section-descriptions.js";import{labelAtLevel as U}from"../lib/puck/section-catalog.js";const V=o=>`section:${o}`,X=o=>`block:${o}`,Z=o=>`template:${o}`;function W({blocks:o,blocksOnly:l,at:k,onAdd:x,itemFor:w,session:$,siteWide:d,onClose:A,onHide:v,readOnly:C}){const a=j(e=>e.config),h=O(),[p,E]=P([]);L(()=>{let e=!1;const n=Y(h);return K.list().then(c=>{if(e)return;const t=a.components;E(c.filter(i=>i.node?.type&&t[i.node.type]&&(!n||q(i.node).every(n.offers))))}).catch(()=>{}),()=>{e=!0}},[a,h]);const f=g(()=>B(a,Q),[a]),I=e=>U(e,"section",a.components[e]?.label??e),u=e=>({type:V(e.type),label:e.name,cover:s(S,{type:e.type}),title:e.desc?`${e.name} \u2014 ${e.desc}`:`Add ${e.name}`,keywords:[e.alias??"",e.desc,e.type,e.catLabel].filter(Boolean)}),N=g(()=>{const e=[];if(o&&o.choices.length>0&&J(o.choices).forEach((t,i)=>{e.push({title:i===0?`Inside ${o.parentName}${t.group?` \xB7 ${t.group}`:""}`:t.group??"",tiles:t.items.map(r=>({type:X(r.type),label:r.label,icon:s(y,{type:r.type,size:18}),title:`Add ${r.label}`}))})}),l)return e;const n=R(f);n&&e.push({title:"Start blank",tiles:[u(n)]}),p.length>0&&e.push({title:"Your templates",tiles:p.map(t=>({type:Z(t.id),label:t.name,cover:s(S,{type:t.node.type}),keywords:[I(t.node.type),t.node.type]}))});const c=M(f);for(const t of Object.keys(a.categories??{})){const i=c.filter(r=>r.cat===t);i.length!==0&&e.push({title:H(a,t),tiles:i.map(u)})}return e},[o,l,p,f,a]),b=e=>{const n=e.indexOf(":"),c=e.slice(0,n),t=e.slice(n+1);if(c==="section")return{kind:"section",type:t};if(c==="block")return{kind:"block",type:t};if(c==="template"){const i=p.find(r=>r.id===t);return i?{kind:"template",template:i}:null}return null};return m(T,{children:[s(_,{icon:s(F,{size:15}),title:"Add",context:l?"Blocks for this place":"Sections and blocks",actions:s(z,{label:"Done",description:"Close Add and go back",onClick:A}),onHide:v}),m("div",{className:"sf-addside sf-scroll",children:[s(D,{groups:N,session:$,itemFor:e=>w(b(e)??{kind:"section",type:e}),onInsert:e=>{const n=b(e);n&&x(n)},at:k,hint:l?"Drag into the page, or click to add.":"Drag onto the page, or click to add.",searchLabel:l?"Search blocks":"Search sections",readOnly:C}),d&&!l?m("div",{className:"sf-addside-sitewide",children:[s("span",{className:"sf-addside-sitewide-glyph","aria-hidden":"true",children:s(y,{type:"chat",size:16})}),m("button",{type:"button",className:"sf-addside-sitewide-name",onClick:d.onOpenChat,children:["Live chat",s("span",{className:"sf-addside-sitewide-desc",children:"A chat bubble on every page"})]}),s(G,{checked:d.chatEnabled,onChange:d.onToggleChat,ariaLabel:"Show the chat bubble on the whole site"})]}):null]})]})}export{X as blockKey,W as default,V as sectionKey,Z as templateKey};
1
+ "use client";import{blockKey as l,default as o,sectionKey as c,templateKey as y}from"efficient-easel/screen/components/AddSidePanel";export{l as blockKey,o as default,c as sectionKey,y as templateKey};
@@ -1 +1 @@
1
- "use client";import{jsx as t}from"react/jsx-runtime";import{SettingsField as l}from"efficient-easel/panel";import{PartResetDot as s}from"./PartResetDot.js";import{AlignSeparateIcon as c}from"efficient-easel/icons";import{CONTAINER_GAP_BUILT_IN as m,SITE_BLOCK_GAP as a}from"../lib/content/container-gap.js";import{Slider as p}from"../lib/puck/controls.js";const d="The space between the blocks inside a row, a grid or a box. Not set means each one keeps the spacing it already has.",n="Block gap",f=m.Grid;function _({value:o,onChange:i,showHint:r=!0}){const e=o===null;return t(l,{label:n,labelId:"sf-block-gap",icon:t(c,{}),value:e?"Not set":`${o}px`,changed:!e,action:e?void 0:t(s,{label:n,what:"change",onClear:()=>i(null)}),hint:r?d:void 0,children:t(p,{min:a.min,max:a.max,step:a.step,value:e?f:o,readout:!1,ariaLabel:n,onChange:i})})}export{_ as default};
1
+ "use client";import{jsx as a}from"react/jsx-runtime";import{SettingsDefaultReset as s,SettingsField as r}from"efficient-easel/panel";import{AlignSeparateIcon as c}from"efficient-easel/icons";import{CONTAINER_GAP_BUILT_IN as d,SITE_BLOCK_GAP as t}from"../lib/content/container-gap.js";import{Slider as p}from"../lib/puck/controls.js";const m="The space between the blocks inside a row, a grid or a box. Default means each one keeps the spacing it already has.",o="Block gap",f=d.Grid;function u({value:n,onChange:i,showHint:l=!0}){const e=n===null;return a(r,{label:o,labelId:"sf-block-gap",icon:a(c,{}),value:e?void 0:`${n}px`,changed:!e,action:a(s,{label:o,changed:!e,detail:"each block's own spacing",onReset:()=>i(null)}),hint:l?m:void 0,children:a(p,{min:t.min,max:t.max,step:t.step,value:e?f:n,readout:!1,ariaLabel:o,onChange:i})})}export{u as default};
@@ -1 +1 @@
1
- "use client";import{jsx as e,Fragment as u,jsxs as c}from"react/jsx-runtime";import{useContext as B}from"react";import{SettingsField as g}from"efficient-easel/panel";import{FieldSelect as d}from"efficient-easel/fields";import{BlogPostIcon as f}from"efficient-easel/icons";import{StorefrontDocumentContext as x}from"./StorefrontDocumentContext.js";import{loadStorefrontBlogPosts as N}from"./useStorefrontBlogPosts.js";import{useSnapshotSource as L}from"./useSnapshotSource.js";import P from"./SourceStatus.js";function T(o){if(!o)return"";const t=new Date(o);return Number.isNaN(t.getTime())?"":t.toLocaleDateString("en-US",{year:"numeric",month:"short",day:"2-digit"})}function m(o){return{slug:o.slug,image:o.coverImage,title:o.title,dek:o.excerpt,date:T(o.publishedAt),href:o.href}}function C({value:o,onChange:t}){const r=B(x);return r&&!r.capabilities.hasBlog?o?.slug?e(D,{value:o,onChange:t}):e(u,{}):e(F,{value:o,onChange:t})}function D({value:o,onChange:t}){return c("div",{children:[e(g,{label:"Blog post source",icon:e(f,{}),children:e(d,{value:o.slug,ariaLabel:"Blog post source",onChange:r=>r?void 0:t(null),options:[{label:"None (manual)",value:""},{label:o.title||o.slug,value:o.slug}]})}),e("p",{className:"sf-blogsource-hint",style:{marginTop:7},children:"Linked to a blog post. This editor has no blog to pick another from; choose \u201CNone (manual)\u201D to author the section yourself."})]})}function F({value:o,onChange:t}){const{rows:r,loading:h,refreshing:l,errored:a,refresh:p}=L({load:N,resolve:(s,n)=>s.find(i=>i.slug===n.slug),snapshot:m,value:o,onChange:t}),b=s=>{if(!s){t(null);return}const n=(r??[]).find(i=>i.slug===s);n&&t(m(n))},S=o?.slug&&!(r??[]).some(s=>s.slug===o.slug),k=a?"error":l?"loading":"idle",y=a?"Couldn\u2019t reach Storefront \u2192 Blog.":l?"Syncing from Storefront \u2192 Blog\u2026":`Linked to \u201C${o?.title||o?.slug||""}\u201D`;return c("div",{children:[e(g,{label:"Blog post source",icon:e(f,{}),children:e(d,{value:o?.slug??"",ariaLabel:"Blog post source",onChange:b,readOnly:h,options:[{label:"None (manual)",value:""},...S?[{label:`${o.title||o.slug} (unavailable)`,value:o.slug}]:[],...(r??[]).map(s=>({label:s.title,value:s.slug}))]})}),o?.slug?e(P,{status:k,statusText:y,onRefresh:p,busy:l,hint:e(u,{children:"Auto-fills the cover image, headline, dek, date and link from this post each time you open the editor. Those fields are hidden while a post is linked; the remaining fields stay yours to set."})}):e("p",{className:"sf-blogsource-hint",style:{marginTop:7},children:"Pick a post from Storefront \u2192 Blog to auto-fill this section, or keep \u201CNone (manual)\u201D to author it yourself below."})]})}export{C as default};
1
+ "use client";import{jsx as t,Fragment as l,jsxs as B}from"react/jsx-runtime";import{useContext as y}from"react";import{SettingsField as c}from"efficient-easel/panel";import{FieldSelect as d}from"efficient-easel/fields";import{BlogPostIcon as g}from"efficient-easel/icons";import{StorefrontDocumentContext as x}from"./StorefrontDocumentContext.js";import{loadStorefrontBlogPosts as L}from"./useStorefrontBlogPosts.js";import{useSnapshotSource as N}from"./useSnapshotSource.js";import P from"./SourceStatus.js";function C(o){if(!o)return"";const e=new Date(o);return Number.isNaN(e.getTime())?"":e.toLocaleDateString("en-US",{year:"numeric",month:"short",day:"2-digit"})}function f(o){return{slug:o.slug,image:o.coverImage,title:o.title,dek:o.excerpt,date:C(o.publishedAt),href:o.href}}function D({value:o,onChange:e}){const r=y(x);return r&&!r.capabilities.hasBlog?o?.slug?t(F,{value:o,onChange:e}):t(l,{}):t(T,{value:o,onChange:e})}function F({value:o,onChange:e}){return t("div",{children:t(c,{label:"Blog post source",icon:t(g,{}),hint:t(l,{children:"Linked to a blog post. This editor has no blog to pick another from; choose \u201CNone (manual)\u201D to author the section yourself."}),children:t(d,{value:o.slug,ariaLabel:"Blog post source",onChange:r=>r?void 0:e(null),options:[{label:"None (manual)",value:""},{label:o.title||o.slug,value:o.slug}]})})})}function T({value:o,onChange:e}){const{rows:r,loading:h,refreshing:i,errored:u,refresh:m}=N({load:L,resolve:(n,s)=>n.find(a=>a.slug===s.slug),snapshot:f,value:o,onChange:e}),p=n=>{if(!n){e(null);return}const s=(r??[]).find(a=>a.slug===n);s&&e(f(s))},b=o?.slug&&!(r??[]).some(n=>n.slug===o.slug),S=u?"error":i?"loading":"idle",k=u?"Couldn\u2019t reach Storefront \u2192 Blog.":i?"Syncing from Storefront \u2192 Blog\u2026":`Linked to \u201C${o?.title||o?.slug||""}\u201D`;return B("div",{children:[t(c,{label:"Blog post source",icon:t(g,{}),hint:o?.slug?void 0:t(l,{children:"Pick a post from Storefront \u2192 Blog to auto-fill this section, or keep \u201CNone (manual)\u201D to author it yourself below."}),children:t(d,{value:o?.slug??"",ariaLabel:"Blog post source",onChange:p,readOnly:h,options:[{label:"None (manual)",value:""},...b?[{label:`${o.title||o.slug} (unavailable)`,value:o.slug}]:[],...(r??[]).map(n=>({label:n.title,value:n.slug}))]})}),o?.slug?t(P,{status:S,statusText:k,onRefresh:m,busy:i,hint:t(l,{children:"Auto-fills the cover image, headline, dek, date and link from this post each time you open the editor. Those fields are hidden while a post is linked; the remaining fields stay yours to set."})}):null]})}export{D as default};
@@ -1 +1 @@
1
- "use client";import{jsx as e}from"react/jsx-runtime";import{SettingsField as i,SettingsSegmented as l}from"efficient-easel/panel";import{ShadowIcon as p}from"efficient-easel/icons";import{CARD_SHADOWS as c,DEFAULT_CARD_SHADOW as f}from"../lib/theme.js";import{PartResetDot as S}from"./PartResetDot.js";import{SITE_STYLE_UNSET_LABEL as h}from"./SiteStyleUnset.js";const s={none:"None",soft:"Soft",lifted:"Lifted"},x="Applies to cards \u2014 products, brands, journal entries and filter cells. Round things like swatches and status dots are never shadowed.",m={none:"none",soft:"0 1px 1px rgba(20, 20, 22, 0.10), 0 2px 4px -1px rgba(20, 20, 22, 0.14)",lifted:"0 1px 2px rgba(20, 20, 22, 0.10), 0 4px 7px -2px rgba(20, 20, 22, 0.30)"},u={labelsPx:90.25,widestLabelPx:34.6};function A({value:t,onChange:a,showHint:r=!0}){const o=t===null,d=t??f;return e(i,{label:"Card shadow",icon:e(p,{}),value:o?h:s[t],changed:!o,action:o?void 0:e(S,{label:"Card shadow",what:"change",onClear:()=>a(null)}),hint:r?x:void 0,children:e(l,{options:c.map(n=>({id:n,label:s[n],icon:e("span",{className:"sf-shadow-chip",style:{boxShadow:m[n]}})})),value:d,ariaLabel:"Card shadow",fit:u,onChange:a})})}export{A as default};
1
+ "use client";import{jsx as e}from"react/jsx-runtime";import{SettingsDefaultReset as r,SettingsField as c,SettingsSegmented as p}from"efficient-easel/panel";import{ShadowIcon as f}from"efficient-easel/icons";import{CARD_SHADOWS as x,DEFAULT_CARD_SHADOW as i}from"../lib/theme.js";const n={none:"None",soft:"Soft",lifted:"Lifted"},h="Applies to cards \u2014 products, brands, journal entries and filter cells. Round things like swatches and status dots are never shadowed.",u={none:"none",soft:"0 1px 1px rgba(20, 20, 22, 0.10), 0 2px 4px -1px rgba(20, 20, 22, 0.14)",lifted:"0 1px 2px rgba(20, 20, 22, 0.10), 0 4px 7px -2px rgba(20, 20, 22, 0.30)"},S={labelsPx:90.25,widestLabelPx:34.6};function b({value:a,onChange:o,showHint:l=!0}){const s=a===null,d=a??i;return e(c,{label:"Card shadow",icon:e(f,{}),value:n[d],changed:!s,action:e(r,{label:"Card shadow",changed:!s,detail:n[i],onReset:()=>o(null)}),hint:l?h:void 0,children:e(p,{options:x.map(t=>({id:t,label:n[t],icon:e("span",{className:"sf-shadow-chip",style:{boxShadow:u[t]}})})),value:d,ariaLabel:"Card shadow",fit:S,onChange:o})})}export{b as default};
@@ -1 +1 @@
1
- "use client";import{jsx as e,jsxs as c,Fragment as d}from"react/jsx-runtime";import{useEffect as f,useId as m,useState as b}from"react";import{usePreviewChat as g}from"./PreviewChatContext.js";import{SettingsField as p,SettingsSwitch as w}from"efficient-easel/panel";import{TypeIcon as C}from"efficient-easel/icons";import{GroupLabel as L}from"../lib/puck/controls.js";const E="Chat with us",y="We usually reply within a few minutes",T="Hi! Ask us anything \u2014 about a wheel, an order, or fitment. Leave your details and we\u2019ll reply.";function s({label:t,value:l,placeholder:n,onCommit:a,multiline:u=!1}){const[r,o]=b(l);f(()=>o(l),[l]);const h=()=>{r!==l&&a(r)};return e(p,{label:t,icon:e(C,{}),children:u?e("textarea",{value:r,placeholder:n,rows:3,onChange:i=>o(i.target.value),onBlur:h,"aria-label":t}):e("input",{type:"text",value:r,placeholder:n,onChange:i=>o(i.target.value),onBlur:h,onKeyDown:i=>{i.key==="Enter"&&i.currentTarget.blur()},"aria-label":t,autoComplete:"off"})})}function v(){const{chat:t,setChat:l}=g(),n=m();return c(d,{children:[c("div",{className:"sf-field sf-field--row",children:[e("span",{id:n,className:"sf-field-label sf-field-label--inline",children:"Show the chat bubble"}),e(w,{checked:t.enabled,onChange:a=>l({enabled:a}),ariaLabelledBy:n})]}),e("p",{className:"sf-field-hint",children:t.enabled?"The floating chat bubble shows in the corner of every page.":"The chat bubble is hidden across the whole site."}),e(L,{label:"Wording"}),e(s,{label:"Title",value:t.title,placeholder:E,onCommit:a=>l({title:a})}),e(s,{label:"Subtitle",value:t.subtitle,placeholder:y,onCommit:a=>l({subtitle:a})}),e(s,{label:"Greeting message",value:t.greeting,placeholder:T,onCommit:a=>l({greeting:a}),multiline:!0}),e("p",{className:"sf-field-hint",children:"Leave a field blank to use the built-in wording."})]})}export{v as default};
1
+ "use client";import{jsx as e,Fragment as b,jsxs as d}from"react/jsx-runtime";import{useEffect as m,useId as f,useState as g}from"react";import{usePreviewChat as p}from"./PreviewChatContext.js";import{SettingsField as u,SettingsSwitch as w}from"efficient-easel/panel";import{EyeIcon as C,TypeIcon as E}from"efficient-easel/icons";import{GroupLabel as L}from"../lib/puck/controls.js";const y="Chat with us",T="We usually reply within a few minutes",v="Hi! Ask us anything \u2014 about a wheel, an order, or fitment. Leave your details and we\u2019ll reply.";function s({label:t,value:a,placeholder:i,onCommit:l,multiline:c=!1}){const[o,r]=g(a);m(()=>r(a),[a]);const h=()=>{o!==a&&l(o)};return e(u,{label:t,icon:e(E,{}),children:c?e("textarea",{value:o,placeholder:i,rows:3,onChange:n=>r(n.target.value),onBlur:h,"aria-label":t}):e("input",{type:"text",value:o,placeholder:i,onChange:n=>r(n.target.value),onBlur:h,onKeyDown:n=>{n.key==="Enter"&&n.currentTarget.blur()},"aria-label":t,autoComplete:"off"})})}function x(){const{chat:t,setChat:a}=p(),i=f();return d(b,{children:[e(u,{label:"Show the chat bubble",labelId:i,icon:e(C,{}),action:e(w,{checked:t.enabled,onChange:l=>a({enabled:l}),ariaLabelledBy:i}),hint:t.enabled?"The floating chat bubble shows in the corner of every page.":"The chat bubble is hidden across the whole site."}),e(L,{label:"Wording"}),e(s,{label:"Title",value:t.title,placeholder:y,onCommit:l=>a({title:l})}),e(s,{label:"Subtitle",value:t.subtitle,placeholder:T,onCommit:l=>a({subtitle:l})}),e(s,{label:"Greeting message",value:t.greeting,placeholder:v,onCommit:l=>a({greeting:l}),multiline:!0}),e("p",{className:"es-field-hint sf-hint-keep",children:"Leave a field blank to use the built-in wording."})]})}export{x as default};
@@ -1,5 +1,4 @@
1
1
  export declare const CORNERS_LABEL = "Corners";
2
- export declare const CORNERS_UNSET_LABEL = "Not set";
3
2
  export default function CornersField({ value, onChange, showHint, }: {
4
3
  value: number | null;
5
4
  onChange: (v: number | null) => void;
@@ -1 +1 @@
1
- "use client";import{jsx as t}from"react/jsx-runtime";import{SettingsField as i}from"efficient-easel/panel";import{SquareIcon as l}from"efficient-easel/icons";import{CORNER_RADIUS_MAX as u,CORNER_RADIUS_MIN as s}from"../lib/theme.js";import{Slider as c}from"../lib/puck/controls.js";import{PartResetDot as p}from"./PartSettingsPanel.js";const d="Applies to panels, cards, inputs and buttons. Round things \u2014 color swatches, switches, status dots \u2014 stay round.",n="Corners",m="Not set";function R({value:o,onChange:r,showHint:a=!0}){const e=o===null;return t(i,{label:n,icon:t(l,{}),value:e?m:`${o}px`,changed:!e,action:e?null:t(p,{label:n,what:"change",onClear:()=>r(null)}),hint:a?d:void 0,children:t(c,{min:s,max:u,step:1,value:o??s,readout:!1,ariaLabel:n,onChange:r})})}export{n as CORNERS_LABEL,m as CORNERS_UNSET_LABEL,R as default};
1
+ "use client";import{jsx as e}from"react/jsx-runtime";import{SettingsDefaultReset as a,SettingsField as l}from"efficient-easel/panel";import{SquareIcon as u}from"efficient-easel/icons";import{CORNER_RADIUS_MAX as d,CORNER_RADIUS_MIN as r}from"../lib/theme.js";import{Slider as c}from"../lib/puck/controls.js";const p="Applies to panels, cards, inputs and buttons. Round things \u2014 color swatches, switches, status dots \u2014 stay round.",o="Corners";function R({value:t,onChange:s,showHint:i=!0}){const n=t===null;return e(l,{label:o,icon:e(u,{}),value:n?void 0:`${t}px`,changed:!n,action:e(a,{label:o,changed:!n,detail:"the built-in corners",onReset:()=>s(null)}),hint:i?p:void 0,children:e(c,{min:r,max:d,step:1,value:t??r,readout:!1,ariaLabel:o,onChange:s})})}export{o as CORNERS_LABEL,R as default};
@@ -1 +1 @@
1
- "use client";import{jsx as t,jsxs as i,Fragment as C}from"react/jsx-runtime";import{useCallback as A,useEffect as H,useRef as z,useState as n}from"react";import{createPortal as W}from"react-dom";import{InspectorIconButton as $}from"efficient-easel/chrome";import{CopyToPageIcon as K}from"efficient-easel/icons";import{backendOf as P}from"../lib/editor-session.js";import{useEditorSession as Y}from"../lib/editor-session-context.js";import{cloneNodeWithFreshIds as q}from"../lib/puck/section-doc.js";import{FOOTER_TYPE as G}from"../lib/puck/content-tree.js";function J({node:T,currentSlug:j,siteId:c,tokenRef:g,runAuthed:B,onNotify:D}){const[s,o]=n(!1),[y,b]=n(null),r=Y(),[F,u]=n(!1),[d,w]=n(null),m=z(null),[f,I]=n(null),[v,L]=n(null),M=A(async()=>{if(r.usesBridgedToken&&!g.current){u(!0);return}try{b(await P(r).pages.list(c?{siteId:c}:void 0))}catch{u(!0)}},[g,c,r]),O=()=>{if(s){o(!1);return}const e=m.current?.getBoundingClientRect();e&&I({top:e.bottom+6,right:Math.max(8,window.innerWidth-e.right)}),L(m.current?.closest(".sf-editor")??document.body),b(null),u(!1),M(),o(!0)};H(()=>{if(!s)return;const e=a=>{a.key==="Escape"&&o(!1)};return window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)},[s]);const N=(y??[]).filter(e=>e.slug!==j),R=async e=>{if(d)return;w(e.slug);const a=q(T),S=r.documentHooks?.storedNode?.(a)??a,k=P(r).pages,E=await B(async()=>{const p=await k.load({id:e.id});if(!p)throw new Error(`Page "${e.slug}" no longer exists.`);const h=p.layout??{},l=Array.isArray(h.content)?[...h.content]:[],x=l.findIndex(_=>_?.type===G);l.splice(x===-1?l.length:x,0,S),await k.save(e.id,{layout:{root:{},zones:{},...h,content:l}},{version:p.version,clientId:""})});w(null),o(!1),D?.(E?`Duplicated to \u201C${e.label}\u201D`:"Couldn\u2019t duplicate the section \u2014 please retry",E?"success":"error")};return i(C,{children:[t($,{buttonRef:m,label:"Duplicate to another page",hasPopup:"menu",expanded:s,onClick:O,children:t(K,{size:15})}),s&&f&&v&&W(i(C,{children:[t("div",{className:"sf-dupmenu-backdrop",onClick:()=>o(!1)}),i("div",{className:"sf-dupmenu",role:"menu",style:{top:f.top,right:f.right},children:[t("div",{className:"sf-dupmenu-head",children:"Duplicate to page\u2026"}),F?t("div",{className:"sf-dupmenu-empty",children:"Couldn\u2019t load pages"}):y===null?t("div",{className:"sf-dupmenu-empty",children:"Loading\u2026"}):N.length===0?t("div",{className:"sf-dupmenu-empty",children:"No other pages"}):N.map(e=>i("button",{type:"button",role:"menuitem",className:"sf-dupmenu-item",disabled:d!==null,onClick:()=>R(e),children:[t("span",{className:"sf-dupmenu-name",children:e.label}),d===e.slug?t("span",{className:"sf-note",children:"Copying\u2026"}):e.draft&&t("span",{className:"sf-note",children:"draft"})]},e.id))]})]}),v)]})}export{J as default};
1
+ "use client";import{jsx as t,jsxs as i,Fragment as C}from"react/jsx-runtime";import{useCallback as A,useEffect as H,useRef as z,useState as n}from"react";import{createPortal as W}from"react-dom";import{InspectorIconButton as $}from"efficient-easel/chrome";import{CopyToPageIcon as K}from"efficient-easel/icons";import{backendOf as P}from"../lib/website-session.js";import{useEditorSession as Y}from"../lib/editor-session-context.js";import{cloneNodeWithFreshIds as q}from"../lib/puck/section-doc.js";import{FOOTER_TYPE as G}from"../lib/puck/content-tree.js";function J({node:T,currentSlug:j,siteId:c,tokenRef:g,runAuthed:B,onNotify:D}){const[s,o]=n(!1),[y,b]=n(null),r=Y(),[F,u]=n(!1),[d,w]=n(null),m=z(null),[f,I]=n(null),[v,L]=n(null),M=A(async()=>{if(r.usesBridgedToken&&!g.current){u(!0);return}try{b(await P(r).pages.list(c?{siteId:c}:void 0))}catch{u(!0)}},[g,c,r]),O=()=>{if(s){o(!1);return}const e=m.current?.getBoundingClientRect();e&&I({top:e.bottom+6,right:Math.max(8,window.innerWidth-e.right)}),L(m.current?.closest(".sf-editor")??document.body),b(null),u(!1),M(),o(!0)};H(()=>{if(!s)return;const e=a=>{a.key==="Escape"&&o(!1)};return window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)},[s]);const N=(y??[]).filter(e=>e.slug!==j),R=async e=>{if(d)return;w(e.slug);const a=q(T),S=r.documentHooks?.storedNode?.(a)??a,k=P(r).pages,E=await B(async()=>{const p=await k.load({id:e.id});if(!p)throw new Error(`Page "${e.slug}" no longer exists.`);const h=p.layout??{},l=Array.isArray(h.content)?[...h.content]:[],x=l.findIndex(_=>_?.type===G);l.splice(x===-1?l.length:x,0,S),await k.save(e.id,{layout:{root:{},zones:{},...h,content:l}},{version:p.version,clientId:""})});w(null),o(!1),D?.(E?`Duplicated to \u201C${e.label}\u201D`:"Couldn\u2019t duplicate the section \u2014 please retry",E?"success":"error")};return i(C,{children:[t($,{buttonRef:m,label:"Duplicate to another page",hasPopup:"menu",expanded:s,onClick:O,children:t(K,{size:15})}),s&&f&&v&&W(i(C,{children:[t("div",{className:"sf-dupmenu-backdrop",onClick:()=>o(!1)}),i("div",{className:"sf-dupmenu",role:"menu",style:{top:f.top,right:f.right},children:[t("div",{className:"sf-dupmenu-head",children:"Duplicate to page\u2026"}),F?t("div",{className:"sf-dupmenu-empty",children:"Couldn\u2019t load pages"}):y===null?t("div",{className:"sf-dupmenu-empty",children:"Loading\u2026"}):N.length===0?t("div",{className:"sf-dupmenu-empty",children:"No other pages"}):N.map(e=>i("button",{type:"button",role:"menuitem",className:"sf-dupmenu-item",disabled:d!==null,onClick:()=>R(e),children:[t("span",{className:"sf-dupmenu-name",children:e.label}),d===e.slug?t("span",{className:"sf-note",children:"Copying\u2026"}):e.draft&&t("span",{className:"sf-note",children:"draft"})]},e.id))]})]}),v)]})}export{J as default};
@@ -0,0 +1 @@
1
+ export { default, DocumentScreen } from "efficient-easel/screen/components/ScreenMount";
@@ -0,0 +1 @@
1
+ "use client";import{default as c,DocumentScreen as n}from"efficient-easel/screen/components/ScreenMount";export{n as DocumentScreen,c as default};
@@ -0,0 +1 @@
1
+ export { default } from "efficient-easel/screen/components/ScreenStoreProvider";
@@ -0,0 +1 @@
1
+ "use client";import{default as f}from"efficient-easel/screen/components/ScreenStoreProvider";export{f as default};
@@ -1 +1 @@
1
- "use client";import{jsx as t}from"react/jsx-runtime";import{SettingsField as f,SettingsSegmented as h}from"efficient-easel/panel";import{PartResetDot as m}from"./PartResetDot.js";import{SITE_STYLE_UNSET_LABEL as p}from"./SiteStyleUnset.js";import{WIDTH_CHOICE_LABEL as n}from"../lib/content/section-width.js";import{ImageIcon as c}from"efficient-easel/icons";const i="Hero image",r=[{followsWidth:!1,label:n.full},{followsWidth:!0,label:n.page}],g="Whether the big picture at the top of a page runs edge to edge, or sits inside the page width. The words follow the page width either way.";function u({value:o,onChange:a,showHint:s=!0}){const l=o===null,d=o??!1;return t(f,{label:i,icon:t(c,{}),value:l?p:r.find(e=>e.followsWidth===o).label,changed:!l,action:l?void 0:t(m,{label:i,what:"change",onClear:()=>a(null)}),hint:s?g:void 0,children:t(h,{options:r.map(e=>({id:e.followsWidth,label:e.label})),value:d,ariaLabel:i,onChange:a})})}export{i as HERO_IMAGE_LABEL,u as default};
1
+ "use client";import{jsx as t}from"react/jsx-runtime";import{SettingsDefaultReset as f,SettingsField as h,SettingsSegmented as g}from"efficient-easel/panel";import{WIDTH_CHOICE_LABEL as d}from"../lib/content/section-width.js";import{ImageIcon as c}from"efficient-easel/icons";const l="Hero image",o=[{followsWidth:!1,label:d.full},{followsWidth:!0,label:d.page}],u="Whether the big picture at the top of a page runs edge to edge, or sits inside the page width. The words follow the page width either way.";function p({value:i,onChange:a,showHint:r=!0}){const n=i===null,s=i??!1;return t(h,{label:l,icon:t(c,{}),value:o.find(e=>e.followsWidth===s).label,changed:!n,action:t(f,{label:l,changed:!n,detail:o.find(e=>!e.followsWidth).label,onReset:()=>a(null)}),hint:r?u:void 0,children:t(g,{options:o.map(e=>({id:e.followsWidth,label:e.label})),value:s,ariaLabel:l,onChange:a})})}export{l as HERO_IMAGE_LABEL,p as default};
@@ -2,14 +2,11 @@ import { type SlotComponent } from "efficient-easel/blocks";
2
2
  import { type HeroReelShape } from "../lib/reel.js";
3
3
  import { type HeroArrowShape } from "../lib/hero-arrows.js";
4
4
  import type { HeroCopyAlignment } from "../lib/hero-group-placement.js";
5
+ import { HERO_SLIDER_GOTO_EVENT, type HeroSliderGotoDetail } from "../lib/puck/preview-events.js";
5
6
  export declare const HERO_VIDEO_PLAY_LABEL = "Play video";
6
7
  export declare const HERO_VIDEO_HOLD_LABEL = "Hold video";
7
8
  export declare const DEFAULT_TICKER_ITEMS: string[];
8
- export declare const HERO_SLIDER_GOTO_EVENT = "hero-slider:goto";
9
- export interface HeroSliderGotoDetail {
10
- id?: string;
11
- index: number;
12
- }
9
+ export { HERO_SLIDER_GOTO_EVENT, type HeroSliderGotoDetail };
13
10
  export declare function subscribeSliderGoto(host: Element | null | undefined, handler: (event: Event) => void): (() => void) | undefined;
14
11
  interface Props {
15
12
  slides: SlotComponent;
@@ -36,4 +33,3 @@ interface Props {
36
33
  editing?: boolean;
37
34
  }
38
35
  export default function HeroSection({ slides: Slides, alignment, textureOpacity, showTexture, textureColor, phoneUpDown, phoneSideways, autoplay, autoplayInterval, showTicker, tickerItems, heightDesktop, heightMobile, showPicker, pickerShape, pickerPlacement, showArrows, arrowsShape, arrowsPlacement, editing, }: Props): import("react").JSX.Element;
39
- export {};
@@ -1,11 +1,11 @@
1
- "use client";import{jsx as c,jsxs as R}from"react/jsx-runtime";import{useCallback as p,useEffect as f,useId as Re,useRef as i,useState as b}from"react";import{markOverlayPortal as I}from"../lib/puck/overlay-portal.js";import Le from"./Ticker.js";import{HeroSlideStyleContext as Oe}from"./HeroSlide.js";import Te from"./HeroArrows.js";import He from"./Reel.js";import{usePreviewTicker as Ae}from"./PreviewTickerContext.js";import{useReducedMotion as Ce}from"./useReducedMotion.js";import{tk as W}from"./floating-editor/tokens.js";import{hasSectionHeight as Ie,resolveSectionHeight as Z}from"../lib/content/section-height.js";import{HEADER_HEIGHT_CSS as Ne}from"../lib/puck/header-clearance.js";import{nextReel as Me,normaliseHeroReelShape as Pe,reelShown as De}from"../lib/reel.js";import{arrowsShown as $e,arrowStep as Ve}from"../lib/hero-arrows.js";import{swipeEnabled as ze,swipeStep as Xe}from"../lib/hero-swipe.js";import{videoControlShown as qe,videoHeld as Ge}from"../lib/hero-video-control.js";const je=`
1
+ "use client";import{jsx as c,jsxs as R}from"react/jsx-runtime";import{useCallback as p,useEffect as f,useId as Re,useRef as i,useState as b}from"react";import{markOverlayPortal as I}from"../lib/puck/overlay-portal.js";import Le from"./Ticker.js";import{HeroSlideStyleContext as Oe}from"./HeroSlide.js";import Te from"./HeroArrows.js";import He from"./Reel.js";import{usePreviewTicker as Ae}from"./PreviewTickerContext.js";import{useReducedMotion as Ce}from"./useReducedMotion.js";import{tk as Z}from"./floating-editor/tokens.js";import{hasSectionHeight as Ie,resolveSectionHeight as ee}from"../lib/content/section-height.js";import{HEADER_HEIGHT_CSS as Ne}from"../lib/puck/header-clearance.js";import{nextReel as Me,normaliseHeroReelShape as Pe,reelShown as De}from"../lib/reel.js";import{arrowsShown as $e,arrowStep as Ve}from"../lib/hero-arrows.js";import{swipeEnabled as ze,swipeStep as Xe}from"../lib/hero-swipe.js";import{videoControlShown as qe,videoHeld as Ge}from"../lib/hero-video-control.js";import{HERO_SLIDER_GOTO_EVENT as N}from"../lib/puck/preview-events.js";const je=`
2
2
  .hero-ticker-pick { cursor: pointer; }
3
3
  .hero-ticker-pick:hover {
4
- outline: 2px solid color-mix(in srgb, ${W.accent} 45%, transparent);
4
+ outline: 2px solid color-mix(in srgb, ${Z.accent} 45%, transparent);
5
5
  outline-offset: -2px;
6
6
  }
7
7
  .hero-ticker-pick[data-selected] {
8
- outline: 2px solid ${W.accent};
8
+ outline: 2px solid ${Z.accent};
9
9
  outline-offset: -2px;
10
10
  }
11
- `,Be="Play video",Ke="Hold video",Ye="flex h-7 cursor-pointer items-center gap-1.5 rounded-full border border-overlay-chrome/25 bg-overlay-scrim/80 px-[11px] font-mono text-[11px] leading-none tracking-[0.05em] text-overlay-fg",Fe="item",Ue=["","","","","",""],ee=new Map,te="hero-slider:goto";function Je(L,w){const h=L?.ownerDocument?.defaultView;if(h)return h.addEventListener(te,w),()=>h.removeEventListener(te,w)}function Qe({slides:L,alignment:w,textureOpacity:h,showTexture:re,textureColor:oe,phoneUpDown:ne,phoneSideways:se,autoplay:N,autoplayInterval:O,showTicker:ce,tickerItems:ae,heightDesktop:M,heightMobile:P,showPicker:ie,pickerShape:le,pickerPlacement:ue,showArrows:de,arrowsShape:me,arrowsPlacement:pe,editing:n}){const D=Ie(M,P),fe=D?"h-[var(--sf-hero-h-m)] min-[720px]:h-[var(--sf-hero-h-d)]":"h-screen min-h-[680px]",he=D?{"--sf-hero-h-d":Z(M),"--sf-hero-h-m":Z(P)}:void 0,T=(ae??Ue.map(e=>({text:e}))).map(e=>e?.text?.trim()?e.text:n?Fe:"").filter(Boolean),$=ce!==!1,u=i(null),V=i(null),z=i(null),X=i(null),q=i(null),G=Re(),E=i(G),[y,ve]=b([]),[xe,j]=b(0),v=i(0),[B,K]=b(!1),[g,ke]=b(!1),[Y,be]=b(null),H=Ce(),{selectedHeroId:we,select:F}=Ae(),S=p(()=>u.current?.querySelector(".hero-track")??null,[]),l=p((e,t=!1)=>{j(e),v.current=e,ee.set(E.current,e);const r=u.current?.querySelector(".hero-track");if(r)if(t){const o=r.style.transition;r.style.transition="none",r.style.transform=`translateX(-${Math.max(0,e)*100}%)`,r.offsetHeight,r.style.transition=o}else r.style.transform=`translateX(-${Math.max(0,e)*100}%)`},[]);f(()=>{const e=u.current,t=e?.getAttribute("data-puck-component")||e?.closest("[data-puck-component]")?.getAttribute("data-puck-component")||G;E.current=t,be(t);const r=ee.get(t);typeof r=="number"&&(j(r),v.current=r)},[]),f(()=>{const e=S();if(!e)return;const t=()=>{ve(o=>Me(o,e.querySelectorAll("[data-slide-name]")))};t();const r=new MutationObserver(t);return r.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["data-slide-name","data-slide-process","data-slide-media"]}),()=>{r.disconnect()}},[S]),f(()=>{if(!n)return;const e=t=>{const r=t.detail;if(!r||typeof r.index!="number")return;const o=u.current,a=o?.getAttribute("data-puck-component")||o?.closest("[data-puck-component]")?.getAttribute("data-puck-component")||E.current;r.id&&r.id!==a||l(r.index,!0)};return Je(u.current,e)},[n,l]);const s=y.length,d=Math.min(Math.max(xe,0),Math.max(0,s-1)),A=De({shown:ie,count:s}),U=$e({shown:de,count:s}),J=qe({editing:n,shown:d,slides:y}),Ee=Ge({editing:n,playing:g,controlShown:J}),_=ze({count:s,editing:n}),m=i(null),x=i(null),ye=p(e=>{if(m.current=null,x.current=null,!_||e.touches.length!==1)return;const t=e.touches[0];m.current={x:t.clientX,y:t.clientY},x.current={x:t.clientX,y:t.clientY}},[_]),ge=p(e=>{if(!m.current)return;if(e.touches.length!==1){m.current=null;return}const t=e.touches[0];x.current={x:t.clientX,y:t.clientY}},[]),Se=p(()=>{const e=m.current,t=x.current;if(m.current=null,x.current=null,!_||!e||!t)return;const r=Xe(t.x-e.x,t.y-e.y,v.current,s);r!==v.current&&l(r)},[_,s,l]);f(()=>{if(n||!N||B||H||s<=1)return;const t=Math.max(1,typeof O=="number"?O:6)*1e3,r=window.setTimeout(()=>l((d+1)%s),t);return()=>window.clearTimeout(r)},[n,N,O,B,H,s,d,l]),f(()=>{const e=[V.current,z.current,X.current].filter(Boolean),t=e.map(o=>I(o)),r=o=>{const a=o.target,k=a.closest("[data-hero-nav]"),Q=k??a.closest("[data-idx]");if(!Q)return;o.stopPropagation(),o.preventDefault();const C=k?Ve(k.dataset.heroNav,v.current,s):Number(Q.dataset.idx);Number.isNaN(C)||(l(C,n),S()?.querySelectorAll("[data-slide-name]")[C]?.click())};return e.forEach(o=>o.addEventListener("click",r,{capture:!0})),()=>{t.forEach(o=>o?.()),e.forEach(o=>o.removeEventListener("click",r,{capture:!0}))}},[s,l,S,n]),f(()=>{if(!n)return;const e=q.current;if(!e)return;const t=I(e),r=o=>{o.stopPropagation(),o.preventDefault();const a=u.current,k=a?.getAttribute("data-puck-component")||a?.closest("[data-puck-component]")?.getAttribute("data-puck-component")||E.current;F(k)};return e.addEventListener("click",r,{capture:!0}),()=>{t?.(),e.removeEventListener("click",r,{capture:!0})}},[n,F,$,T.length]);const _e=p(e=>{if(!e)return;const t=I(e),r=o=>{o.stopPropagation(),o.preventDefault(),ke(a=>!a)};return e.addEventListener("click",r,{capture:!0}),()=>{t?.(),e.removeEventListener("click",r,{capture:!0})}},[]);return c(Oe.Provider,{value:{alignment:w,textureOpacity:h,textureOn:re,textureColor:oe,quietVideo:Ee,phoneUpDown:ne,phoneSideways:se},children:R("div",{ref:u,className:`relative mx-[var(--sf-hero-bleed-m,calc(50%_-_50vw))] w-[var(--sf-hero-bleed-w,100vw)] ${fe} max-w-[var(--sf-hero-cap,none)] overflow-hidden`,style:he,onMouseEnter:()=>K(!0),onMouseLeave:()=>K(!1),onTouchStart:ye,onTouchMove:ge,onTouchEnd:Se,children:[c(L,{className:"hero-track flex h-full [&>*]:h-full [&>*]:min-w-full [&>*]:shrink-0 [&>*]:basis-full",style:{transform:`translateX(-${d*100}%)`,transition:H?"none":"transform 600ms cubic-bezier(.22,.61,.36,1)"},minEmptyHeight:400}),J&&c("div",{ref:_e,"data-hero-video-control":g?"playing":"held",className:"sf-hero-video-control absolute left-6 z-[7]",style:{top:`calc(${Ne} + 16px)`},children:R("button",{type:"button",className:Ye,children:[c("span",{"aria-hidden":"true",children:g?"\u275A\u275A":"\u25B6"}),g?Ke:Be]})}),(A||U)&&R("div",{className:"pointer-events-none absolute inset-y-0 left-[var(--sf-hero-chrome-x,var(--sf-site-gutter,40px))] right-[var(--sf-hero-chrome-x,var(--sf-site-gutter,40px))] z-[6] mx-auto max-w-[var(--sf-hero-chrome-cap,calc(min(var(--sf-page-cap,var(--sf-site-width,1600px)),var(--sf-site-width,1600px))_-_var(--sf-site-gutter,40px)*2))]",children:[A&&c(He,{ref:V,slides:y,active:d,shape:Pe(le),placement:ue}),U&&c(Te,{ref:X,shape:me,placement:pe})]}),A&&c("div",{ref:z,className:"sf-hero-phone-dots absolute bottom-[80px] left-1/2 z-[6] hidden -translate-x-1/2 items-center gap-2",children:y.map((e,t)=>c("button",{type:"button","data-idx":t,"aria-label":`Go to slide ${t+1}`,className:`h-2 rounded-full transition-all motion-reduce:transition-none ${t===d?"w-5 bg-accent":"w-2 bg-white/45 hover:bg-white/70"}`},t))}),$&&T.length>0&&R("div",{ref:q,className:`sf-hero-ticker absolute inset-x-0 bottom-0 z-[5] border-t border-overlay-chrome/10 py-3.5${n?" hero-ticker-pick":""}`,"data-selected":n&&Y!=null&&we===Y?"":void 0,style:{background:"rgba(10,10,10,.55)"},children:[n&&c("style",{children:je}),c(Le,{items:T,backdrop:"dark-media"})]})]})})}export{Ue as DEFAULT_TICKER_ITEMS,te as HERO_SLIDER_GOTO_EVENT,Ke as HERO_VIDEO_HOLD_LABEL,Be as HERO_VIDEO_PLAY_LABEL,Qe as default,Je as subscribeSliderGoto};
11
+ `,Be="Play video",Ke="Hold video",Ye="flex h-7 cursor-pointer items-center gap-1.5 rounded-full border border-overlay-chrome/25 bg-overlay-scrim/80 px-[11px] font-mono text-[11px] leading-none tracking-[0.05em] text-overlay-fg",Fe="item",Ue=["","","","","",""],te=new Map;function Je(L,w){const h=L?.ownerDocument?.defaultView;if(h)return h.addEventListener(N,w),()=>h.removeEventListener(N,w)}function Qe({slides:L,alignment:w,textureOpacity:h,showTexture:re,textureColor:oe,phoneUpDown:ne,phoneSideways:se,autoplay:M,autoplayInterval:O,showTicker:ce,tickerItems:ae,heightDesktop:P,heightMobile:D,showPicker:ie,pickerShape:le,pickerPlacement:ue,showArrows:de,arrowsShape:me,arrowsPlacement:pe,editing:n}){const $=Ie(P,D),fe=$?"h-[var(--sf-hero-h-m)] min-[720px]:h-[var(--sf-hero-h-d)]":"h-screen min-h-[680px]",he=$?{"--sf-hero-h-d":ee(P),"--sf-hero-h-m":ee(D)}:void 0,T=(ae??Ue.map(e=>({text:e}))).map(e=>e?.text?.trim()?e.text:n?Fe:"").filter(Boolean),V=ce!==!1,u=i(null),z=i(null),X=i(null),q=i(null),G=i(null),j=Re(),E=i(j),[y,ve]=b([]),[xe,B]=b(0),v=i(0),[K,Y]=b(!1),[g,ke]=b(!1),[F,be]=b(null),H=Ce(),{selectedHeroId:we,select:U}=Ae(),S=p(()=>u.current?.querySelector(".hero-track")??null,[]),l=p((e,t=!1)=>{B(e),v.current=e,te.set(E.current,e);const r=u.current?.querySelector(".hero-track");if(r)if(t){const o=r.style.transition;r.style.transition="none",r.style.transform=`translateX(-${Math.max(0,e)*100}%)`,r.offsetHeight,r.style.transition=o}else r.style.transform=`translateX(-${Math.max(0,e)*100}%)`},[]);f(()=>{const e=u.current,t=e?.getAttribute("data-puck-component")||e?.closest("[data-puck-component]")?.getAttribute("data-puck-component")||j;E.current=t,be(t);const r=te.get(t);typeof r=="number"&&(B(r),v.current=r)},[]),f(()=>{const e=S();if(!e)return;const t=()=>{ve(o=>Me(o,e.querySelectorAll("[data-slide-name]")))};t();const r=new MutationObserver(t);return r.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["data-slide-name","data-slide-process","data-slide-media"]}),()=>{r.disconnect()}},[S]),f(()=>{if(!n)return;const e=t=>{const r=t.detail;if(!r||typeof r.index!="number")return;const o=u.current,a=o?.getAttribute("data-puck-component")||o?.closest("[data-puck-component]")?.getAttribute("data-puck-component")||E.current;r.id&&r.id!==a||l(r.index,!0)};return Je(u.current,e)},[n,l]);const s=y.length,d=Math.min(Math.max(xe,0),Math.max(0,s-1)),A=De({shown:ie,count:s}),J=$e({shown:de,count:s}),Q=qe({editing:n,shown:d,slides:y}),Ee=Ge({editing:n,playing:g,controlShown:Q}),_=ze({count:s,editing:n}),m=i(null),x=i(null),ye=p(e=>{if(m.current=null,x.current=null,!_||e.touches.length!==1)return;const t=e.touches[0];m.current={x:t.clientX,y:t.clientY},x.current={x:t.clientX,y:t.clientY}},[_]),ge=p(e=>{if(!m.current)return;if(e.touches.length!==1){m.current=null;return}const t=e.touches[0];x.current={x:t.clientX,y:t.clientY}},[]),Se=p(()=>{const e=m.current,t=x.current;if(m.current=null,x.current=null,!_||!e||!t)return;const r=Xe(t.x-e.x,t.y-e.y,v.current,s);r!==v.current&&l(r)},[_,s,l]);f(()=>{if(n||!M||K||H||s<=1)return;const t=Math.max(1,typeof O=="number"?O:6)*1e3,r=window.setTimeout(()=>l((d+1)%s),t);return()=>window.clearTimeout(r)},[n,M,O,K,H,s,d,l]),f(()=>{const e=[z.current,X.current,q.current].filter(Boolean),t=e.map(o=>I(o)),r=o=>{const a=o.target,k=a.closest("[data-hero-nav]"),W=k??a.closest("[data-idx]");if(!W)return;o.stopPropagation(),o.preventDefault();const C=k?Ve(k.dataset.heroNav,v.current,s):Number(W.dataset.idx);Number.isNaN(C)||(l(C,n),S()?.querySelectorAll("[data-slide-name]")[C]?.click())};return e.forEach(o=>o.addEventListener("click",r,{capture:!0})),()=>{t.forEach(o=>o?.()),e.forEach(o=>o.removeEventListener("click",r,{capture:!0}))}},[s,l,S,n]),f(()=>{if(!n)return;const e=G.current;if(!e)return;const t=I(e),r=o=>{o.stopPropagation(),o.preventDefault();const a=u.current,k=a?.getAttribute("data-puck-component")||a?.closest("[data-puck-component]")?.getAttribute("data-puck-component")||E.current;U(k)};return e.addEventListener("click",r,{capture:!0}),()=>{t?.(),e.removeEventListener("click",r,{capture:!0})}},[n,U,V,T.length]);const _e=p(e=>{if(!e)return;const t=I(e),r=o=>{o.stopPropagation(),o.preventDefault(),ke(a=>!a)};return e.addEventListener("click",r,{capture:!0}),()=>{t?.(),e.removeEventListener("click",r,{capture:!0})}},[]);return c(Oe.Provider,{value:{alignment:w,textureOpacity:h,textureOn:re,textureColor:oe,quietVideo:Ee,phoneUpDown:ne,phoneSideways:se},children:R("div",{ref:u,className:`relative mx-[var(--sf-hero-bleed-m,calc(50%_-_50vw))] w-[var(--sf-hero-bleed-w,100vw)] ${fe} max-w-[var(--sf-hero-cap,none)] overflow-hidden`,style:he,onMouseEnter:()=>Y(!0),onMouseLeave:()=>Y(!1),onTouchStart:ye,onTouchMove:ge,onTouchEnd:Se,children:[c(L,{className:"hero-track flex h-full [&>*]:h-full [&>*]:min-w-full [&>*]:shrink-0 [&>*]:basis-full",style:{transform:`translateX(-${d*100}%)`,transition:H?"none":"transform 600ms cubic-bezier(.22,.61,.36,1)"},minEmptyHeight:400}),Q&&c("div",{ref:_e,"data-hero-video-control":g?"playing":"held",className:"sf-hero-video-control absolute left-6 z-[7]",style:{top:`calc(${Ne} + 16px)`},children:R("button",{type:"button",className:Ye,children:[c("span",{"aria-hidden":"true",children:g?"\u275A\u275A":"\u25B6"}),g?Ke:Be]})}),(A||J)&&R("div",{className:"pointer-events-none absolute inset-y-0 left-[var(--sf-hero-chrome-x,var(--sf-site-gutter,40px))] right-[var(--sf-hero-chrome-x,var(--sf-site-gutter,40px))] z-[6] mx-auto max-w-[var(--sf-hero-chrome-cap,calc(min(var(--sf-page-cap,var(--sf-site-width,1600px)),var(--sf-site-width,1600px))_-_var(--sf-site-gutter,40px)*2))]",children:[A&&c(He,{ref:z,slides:y,active:d,shape:Pe(le),placement:ue}),J&&c(Te,{ref:q,shape:me,placement:pe})]}),A&&c("div",{ref:X,className:"sf-hero-phone-dots absolute bottom-[80px] left-1/2 z-[6] hidden -translate-x-1/2 items-center gap-2",children:y.map((e,t)=>c("button",{type:"button","data-idx":t,"aria-label":`Go to slide ${t+1}`,className:`h-2 rounded-full transition-all motion-reduce:transition-none ${t===d?"w-5 bg-accent":"w-2 bg-white/45 hover:bg-white/70"}`},t))}),V&&T.length>0&&R("div",{ref:G,className:`sf-hero-ticker absolute inset-x-0 bottom-0 z-[5] border-t border-overlay-chrome/10 py-3.5${n?" hero-ticker-pick":""}`,"data-selected":n&&F!=null&&we===F?"":void 0,style:{background:"rgba(10,10,10,.55)"},children:[n&&c("style",{children:je}),c(Le,{items:T,backdrop:"dark-media"})]})]})})}export{Ue as DEFAULT_TICKER_ITEMS,N as HERO_SLIDER_GOTO_EVENT,Ke as HERO_VIDEO_HOLD_LABEL,Be as HERO_VIDEO_PLAY_LABEL,Qe as default,Je as subscribeSliderGoto};
@@ -1 +1 @@
1
- "use client";import{jsx as e}from"react/jsx-runtime";import{SettingsField as l,SettingsSegmented as c}from"efficient-easel/panel";import{HoverIcon as s}from"efficient-easel/icons";import{HOVER_EFFECTS as h,DEFAULT_HOVER_EFFECT as E}from"../lib/theme.js";import{PartResetDot as d}from"./PartResetDot.js";import{SITE_STYLE_UNSET_LABEL as m}from"./SiteStyleUnset.js";const r={none:"None",lift:"Lift",highlight:"Highlight"},p="What a card does when a shopper points at it \u2014 or taps it, on a phone. Highlight is the effect your cards already use.";function u({value:t,onChange:i,showHint:a=!0}){const o=t===null,f=t??E;return e(l,{label:"Hover effect",icon:e(s,{}),value:o?m:r[t],changed:!o,action:o?void 0:e(d,{label:"Hover effect",what:"change",onClear:()=>i(null)}),hint:a?p:void 0,children:e(c,{options:h.map(n=>({id:n,label:r[n]})),value:f,ariaLabel:"Hover effect",onChange:i})})}export{u as default};
1
+ "use client";import{jsx as e}from"react/jsx-runtime";import{SettingsDefaultReset as s,SettingsField as c,SettingsSegmented as d}from"efficient-easel/panel";import{HoverIcon as h}from"efficient-easel/icons";import{HOVER_EFFECTS as u,DEFAULT_HOVER_EFFECT as l}from"../lib/theme.js";const t={none:"None",lift:"Lift",highlight:"Highlight"},g="What a card does when a shopper points at it \u2014 or taps it, on a phone. Highlight is the effect your cards already use.";function p({value:o,onChange:i,showHint:f=!0}){const n=o===null,a=o??l;return e(c,{label:"Hover effect",icon:e(h,{}),value:t[a],changed:!n,action:e(s,{label:"Hover effect",changed:!n,detail:t[l],onReset:()=>i(null)}),hint:f?g:void 0,children:e(d,{options:u.map(r=>({id:r,label:t[r]})),value:a,ariaLabel:"Hover effect",onChange:i})})}export{p as default};
@@ -1 +1 @@
1
- "use client";import{jsx as e,jsxs as a,Fragment as P}from"react/jsx-runtime";import{useRef as N,useState as F}from"react";import D from"./TextStyleRow.js";import{focalFromRect as k,formatFocal as $,nudgeFocal as C,parseFocal as R}from"../lib/image-focus.js";function j({label:c,value:t,onChange:l,image:i}){const[f,u]=F(!1),m=N(null),n=N(!1),{x:p,y:d}=R(t),g=(s,o)=>{const h=m.current?.getBoundingClientRect();if(!h)return;const y=k(h,s,o);l($(y.x,y.y))},b=s=>{const o=C(t,s.key,s.shiftKey);o!==null&&(s.preventDefault(),l(o))},x=s=>{s.currentTarget.setPointerCapture?.(s.pointerId),n.current=!0,g(s.clientX,s.clientY)},w=s=>{n.current&&g(s.clientX,s.clientY)},r=()=>{n.current=!1};return e(D,{styleKey:"imageFocal",label:c,value:t,sampleStyle:{fontSize:11,fontVariantNumeric:"tabular-nums"},open:f,onToggle:()=>u(s=>!s),children:f?e("div",{className:"sf-focus","data-sf-focusing":"",children:i?a(P,{children:[e("button",{type:"button",className:"sf-focus-canvas","aria-label":`${c}: ${t}. Use the arrow keys to move the point.`,onKeyDown:b,onPointerDown:x,onPointerMove:w,onPointerUp:r,onPointerCancel:r,onLostPointerCapture:r,children:a("span",{className:"sf-focus-pane",ref:m,children:[e("img",{className:"sf-focus-img",src:i,alt:"",draggable:!1}),e("span",{className:"sf-focus-cross sf-focus-cross--h",style:{top:`${d}%`}}),e("span",{className:"sf-focus-cross sf-focus-cross--v",style:{left:`${p}%`}}),e("span",{className:"sf-focus-marker",style:{left:`${p}%`,top:`${d}%`}})]})}),a("div",{className:"sf-focus-bar",children:[e("span",{className:"sf-focus-hint",children:"Press the picture, or nudge the point with the arrow keys."}),e("button",{type:"button",className:"sf-image-btn",onClick:()=>u(!1),children:"Done"})]})]}):e("p",{className:"sf-field-hint",children:"Choose a background image first \u2014 there\u2019s nothing to focus yet."})}):null})}export{j as default};
1
+ "use client";import{jsx as s,jsxs as a,Fragment as P}from"react/jsx-runtime";import{useRef as N,useState as F}from"react";import k from"./TextStyleRow.js";import{focalFromRect as D,formatFocal as $,nudgeFocal as C,parseFocal as R}from"../lib/image-focus.js";function j({label:c,value:t,onChange:l,image:i}){const[f,u]=F(!1),m=N(null),n=N(!1),{x:p,y:d}=R(t),g=(e,o)=>{const h=m.current?.getBoundingClientRect();if(!h)return;const y=D(h,e,o);l($(y.x,y.y))},b=e=>{const o=C(t,e.key,e.shiftKey);o!==null&&(e.preventDefault(),l(o))},x=e=>{e.currentTarget.setPointerCapture?.(e.pointerId),n.current=!0,g(e.clientX,e.clientY)},w=e=>{n.current&&g(e.clientX,e.clientY)},r=()=>{n.current=!1};return s(k,{styleKey:"imageFocal",label:c,value:t,sampleStyle:{fontSize:11,fontVariantNumeric:"tabular-nums"},open:f,onToggle:()=>u(e=>!e),children:f?s("div",{className:"sf-focus","data-sf-focusing":"",children:i?a(P,{children:[s("button",{type:"button",className:"sf-focus-canvas","aria-label":`${c}: ${t}. Use the arrow keys to move the point.`,onKeyDown:b,onPointerDown:x,onPointerMove:w,onPointerUp:r,onPointerCancel:r,onLostPointerCapture:r,children:a("span",{className:"sf-focus-pane",ref:m,children:[s("img",{className:"sf-focus-img",src:i,alt:"",draggable:!1}),s("span",{className:"sf-focus-cross sf-focus-cross--h",style:{top:`${d}%`}}),s("span",{className:"sf-focus-cross sf-focus-cross--v",style:{left:`${p}%`}}),s("span",{className:"sf-focus-marker",style:{left:`${p}%`,top:`${d}%`}})]})}),a("div",{className:"sf-focus-bar",children:[s("span",{className:"sf-focus-hint",children:"Press the picture, or nudge the point with the arrow keys."}),s("button",{type:"button",className:"sf-image-btn",onClick:()=>u(!1),children:"Done"})]})]}):s("p",{className:"es-field-hint sf-hint-keep",children:"Choose a background image first \u2014 there\u2019s nothing to focus yet."})}):null})}export{j as default};
@@ -0,0 +1,5 @@
1
+ import type { ReactNode } from "react";
2
+ export declare const KEEP_HINT_CLASS = "sf-hint-keep";
3
+ export default function KeepHint({ children }: {
4
+ children: ReactNode;
5
+ }): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ import{jsx as t}from"react/jsx-runtime";const n="sf-hint-keep";function s({children:e}){return t("span",{className:n,children:e})}export{n as KEEP_HINT_CLASS,s as default};
@@ -1 +1 @@
1
- "use client";import{jsx as e,jsxs as d,Fragment as z}from"react/jsx-runtime";import{useState as M}from"react";import{useEasel as j}from"efficient-easel/easel";import{ListField as E}from"efficient-easel/fields";import P from"./MediaUploadField.js";import{useLocationsHasTree as U}from"./LocationsTreeContext.js";import{CoordsField as $}from"../lib/puck/controls.js";import{useLocationsFocus as q,setLocationsFocus as f}from"../lib/puck/locations-focus.js";import{groupKeyOf as x,groupLabelOf as I,NEW_CITY as H,writeGroupCities as V,writeGroupOrder as Y}from"../lib/puck/locations-tree.js";import{useSectionOps as Z}from"../lib/puck/use-section-ops.js";import{ROOT_ZONE as J}from"../lib/puck/content-tree.js";import{CONTACT_LOCATIONS_DEFAULTS as F,parseLocationTileShape as Q}from"../lib/content/contact.js";function X(o){const t=[];return o.forEach((s,r)=>{const p=x(s);let l=t.find(a=>a.key===p);l||(l={key:p,name:String(s?.groupName??""),indices:[]},t.push(l)),l.indices.push(r)}),t}function S({children:o}){return e("div",{className:"sf-field-label",children:o})}function D({children:o}){return e("div",{style:{fontSize:11,fontWeight:600,letterSpacing:"0.06em",textTransform:"uppercase",color:"var(--fg-dim, #999)",margin:"14px 0 6px"},children:o})}const G={width:"100%",height:32,textAlign:"left",display:"flex",alignItems:"center",justifyContent:"space-between",gap:8,padding:"0 12px",fontSize:12,border:"1px solid var(--border-strong, #d0d0d0)",borderRadius:6,background:"transparent",color:"inherit",cursor:"inherit"},C={padding:0,border:"none",background:"none",font:"inherit",fontSize:12,color:"var(--sf-accent, #2563eb)",cursor:"pointer"},W={...C,color:"#d85a30"};function w({label:o,value:t,placeholder:s,textarea:r,onChange:p}){return d("div",{className:"sf-field",children:[e(S,{children:o}),r?e("textarea",{value:t,placeholder:s,onChange:l=>p(l.target.value)}):e("input",{type:"text",value:t,placeholder:s,onChange:l=>p(l.target.value)})]})}const K=[{label:"Auto",value:"auto"},{label:"Dark",value:"dark"},{label:"Light",value:"light"}],ee=[{label:"Tall (3:4)",value:"tall"},{label:"Square",value:"square"},{label:"Wide (2:1)",value:"wide"}];function _({label:o,options:t,value:s,onChange:r}){return d("div",{className:"sf-field",children:[e(S,{children:o}),e("div",{style:{display:"flex",gap:4},children:t.map(p=>{const l=s===p.value;return e("button",{type:"button","aria-pressed":l,onClick:()=>r(p.value),style:{flex:1,padding:"6px 8px",fontSize:12,borderRadius:6,cursor:"pointer",border:`1px solid ${l?"var(--sf-accent, #2563eb)":"var(--border-strong, #d0d0d0)"}`,background:l?"var(--sf-accent, #2563eb)":"transparent",color:l?"#fff":"inherit",fontWeight:l?500:400},children:p.label},p.value)})})]})}function R({props:o,setSection:t,headOnly:s}){const r=a=>String(o[a]??""),p=o.mapTheme||F.mapTheme,l=F;return d(z,{children:[!s&&e(D,{children:"Section"}),e(w,{label:"Section number",value:r("sectionNumber"),placeholder:l.sectionNumber,onChange:a=>t({sectionNumber:a})}),e(w,{label:"Heading",textarea:!0,value:r("heading"),placeholder:l.heading,onChange:a=>t({heading:a})}),e(w,{label:"Body",textarea:!0,value:r("tagline"),placeholder:l.tagline,onChange:a=>t({tagline:a})}),s?null:d(z,{children:[e(D,{children:"City strip"}),e(w,{label:"Eyebrow",value:r("galleryKicker"),placeholder:l.galleryKicker,onChange:a=>t({galleryKicker:a})}),e(w,{label:"Hint",value:r("galleryHint"),placeholder:l.galleryHint,onChange:a=>t({galleryHint:a})}),e(_,{label:"Shape",options:ee,value:Q(o.imageShape),onChange:a=>t({imageShape:a})}),e(D,{children:"Map & Theme"}),e(_,{label:"Map theme",options:K,value:p,onChange:a=>t({mapTheme:a})})]})]})}function ne({cards:o,groupKey:t,onChange:s,onBack:r,onOpenCity:p,onNavigate:l}){const a=o.map((i,h)=>x(i)===t?h:-1).filter(i=>i>=0),m=String(o[a[0]]?.groupName??""),L=new Set(o.map(x).filter(i=>i!==t)),[y,N]=M(t),k=i=>s(o.map(h=>x(h)===t?{...h,...i}:h)),O=()=>{const i=y;if(i!==t){if(L.has(i)){N(t);return}s(o.map(h=>x(h)===t?{...h,group:i}:h)),l(i)}};return d("div",{className:"sf-field",children:[e("button",{type:"button",style:C,onClick:r,children:"\u2190 Section"}),e("div",{style:{fontSize:14,fontWeight:500,margin:"6px 0 10px"},children:I(t,m)}),d("div",{className:"sf-field",children:[e(S,{children:"Group heading (optional)"}),e("input",{type:"text",value:y,placeholder:"e.g. Americas",onChange:i=>N(i.target.value),onBlur:O,onKeyDown:i=>{i.key==="Enter"&&i.target.blur()}}),L.has(y)&&y!==t&&e("div",{style:{marginTop:4,fontSize:11,color:"#d85a30"},children:"Another group already uses this heading \u2014 pick a different one."})]}),d("div",{className:"sf-field",children:[e(S,{children:"Group name (optional)"}),e("input",{type:"text",value:m,placeholder:"Shown beside the heading",onChange:i=>k({groupName:i.target.value})})]}),e(E,{label:"Cities in this group",noun:"city",items:a.map(i=>o[i]),onChange:i=>s(V(o,t,i)),newItem:()=>({...H,group:t,groupName:m}),open:null,onOpen:()=>{},renderItem:()=>null,removeOnRow:!1,canDuplicate:()=>!1,renderRow:(i,h)=>d("button",{type:"button",style:G,onClick:()=>p(a[h]),children:[e("span",{children:i?.name||"City"}),e("span",{"aria-hidden":"true",children:"\u203A"})]})}),e("div",{style:{marginTop:12},children:d("button",{type:"button",style:W,onClick:()=>{s(o.filter(i=>x(i)!==t)),r()},children:["Delete group (",a.length," ",a.length===1?"city":"cities",")"]})})]})}function te({value:o,onChange:t}){const s=Array.isArray(o)?o:[],r=q(),p=U(),l=X(s),{appState:a,selectedItem:m}=j(n=>n),L=Z(),y=m?.props??{},N=n=>{if(!m)return;const u=(a.data.content??[]).findIndex(g=>g.props.id===m.props.id);u<0||L.replaceComponent(J,u,{type:m.type,props:{...m.props,...n}})},k=(n,c)=>t(s.map((u,g)=>g===n?{...u,...c}:u)),O=()=>{const n=new Set(l.map(g=>g.key));let c=l.length+1,u=`Group ${c}`;for(;n.has(u);)u=`Group ${++c}`;return u};if(r.level==="texts")return d("div",{className:"sf-field",children:[e("button",{type:"button",style:C,onClick:()=>f({level:"groups"}),children:"\u2190 Locations"}),e("div",{style:{fontSize:14,fontWeight:500,margin:"6px 0 10px"},children:"Texts"}),e(R,{props:y,setSection:N,headOnly:!0})]});if(r.level==="image"){const n=s[r.index];return n?d("div",{className:"sf-field",children:[d("button",{type:"button",style:C,onClick:()=>f({level:"city",index:r.index}),children:["\u2190 ",String(n.name??"")||"City"]}),e("div",{style:{fontSize:14,fontWeight:500,margin:"6px 0 10px"},children:"Image"}),e(P,{value:n.photo||"",onChange:c=>k(r.index,{photo:c}),label:"Image",accept:"image/*"})]}):i()}if(r.level==="map"){const n=s[r.index];return n?d("div",{className:"sf-field",children:[d("button",{type:"button",style:C,onClick:()=>f({level:"city",index:r.index}),children:["\u2190 ",String(n.name??"")||"City"]}),e("div",{style:{fontSize:14,fontWeight:500,margin:"6px 0 10px"},children:"Map"}),e($,{value:n.geocode,onChange:c=>k(r.index,{geocode:c}),label:"Coordinates"}),d("div",{className:"sf-field",children:[e(S,{children:"Directions link"}),e("input",{type:"text",value:String(n.mapsUrl??""),onChange:c=>k(r.index,{mapsUrl:c.target.value})})]})]}):i()}if(r.level==="city"){const n=r.index,c=s[n];if(!c)return i();const u=x(c),g=(b,T)=>k(n,{[b]:T}),v=(b,T,B=!1)=>d("div",{className:"sf-field",children:[e(S,{children:T}),B?e("textarea",{value:String(c[b]??""),onChange:A=>g(b,A.target.value)}):e("input",{type:"text",value:String(c[b]??""),onChange:A=>g(b,A.target.value)})]});return d("div",{className:"sf-field",children:[d("button",{type:"button",style:C,onClick:()=>f({level:"group",key:u}),children:["\u2190 ",I(u,String(c.groupName??""))]}),e("div",{style:{fontSize:14,fontWeight:500,margin:"6px 0 10px"},children:c.name||"City"}),v("name","Location name"),v("state","State / Province"),v("country","Country"),v("address","Address",!0),v("phone","Phone"),v("hours","Opening hours"),v("timezone","Timezone chip"),e("div",{style:{marginTop:12},children:e("button",{type:"button",style:W,onClick:()=>{t(s.filter((b,T)=>T!==n)),f({level:"group",key:u})},children:"Delete city"})})]})}if(r.level==="group")return l.some(n=>n.key===r.key)?e(ne,{cards:s,groupKey:r.key,onChange:t,onBack:()=>f({level:"groups"}),onOpenCity:n=>f({level:"city",index:n}),onNavigate:n=>f({level:"group",key:n})},r.key):i();function i(){return d("div",{className:"sf-field",children:[e(R,{props:y,setSection:N}),!p&&e(z,{children:h()})]})}function h(){return e(E,{label:"Locations",noun:"group",items:l,onChange:n=>{const c=n.find(u=>!l.some(g=>g.key===u.key));t(Y(s,n.map(u=>u.key),u=>[{...H,group:u,groupName:""}])),c&&f({level:"group",key:c.key})},newItem:()=>({key:O(),name:"",indices:[]}),open:null,onOpen:()=>{},renderItem:()=>null,removeOnRow:!1,canDuplicate:()=>!1,above:l.length===0?e("div",{style:{fontSize:12,color:"var(--fg-dim, #999)",padding:"4px 0"},children:"No locations yet."}):void 0,renderRow:n=>d("button",{type:"button",style:G,onClick:()=>f({level:"group",key:n.key}),children:[e("span",{style:{fontWeight:500},children:I(n.key,n.name)}),d("span",{style:{color:"var(--fg-dim, #999)"},children:[n.indices.length," ",n.indices.length===1?"city":"cities"," \u203A"]})]})})}return i()}export{te as default};
1
+ "use client";import{jsx as e,Fragment as L,jsxs as m}from"react/jsx-runtime";import{useId as U,useState as q}from"react";import{InspectorUpLevel as N}from"efficient-easel/chrome";import{useEasel as $}from"efficient-easel/easel";import{ListField as D}from"efficient-easel/fields";import{SettingsField as E}from"efficient-easel/panel";import{ClockIcon as F,ContrastIcon as V,GlobeIcon as Y,LinkIcon as Z,LocationIcon as J,PhoneIcon as Q,SquareIcon as X,TypeIcon as O}from"efficient-easel/icons";import K from"./MediaUploadField.js";import{useLocationsHasTree as ee}from"./LocationsTreeContext.js";import{CoordsField as ne}from"../lib/puck/controls.js";import{useLocationsFocus as te,setLocationsFocus as f}from"../lib/puck/locations-focus.js";import{groupKeyOf as S,groupLabelOf as A,NEW_CITY as G,writeGroupCities as ie,writeGroupOrder as oe}from"../lib/puck/locations-tree.js";import{useSectionOps as re}from"../lib/puck/use-section-ops.js";import{ROOT_ZONE as le}from"../lib/puck/content-tree.js";import{CONTACT_LOCATIONS_DEFAULTS as H,parseLocationTileShape as ae}from"../lib/content/contact.js";function se(a){const t=[];return a.forEach((s,o)=>{const u=S(s);let l=t.find(i=>i.key===u);l||(l={key:u,name:String(s?.groupName??""),indices:[]},t.push(l)),l.indices.push(o)}),t}function z({children:a}){return e("div",{style:{fontSize:11,fontWeight:600,letterSpacing:"0.06em",textTransform:"uppercase",color:"var(--fg-dim, #999)",margin:"14px 0 6px"},children:a})}const W={width:"100%",height:32,textAlign:"left",display:"flex",alignItems:"center",justifyContent:"space-between",gap:8,padding:"0 12px",fontSize:12,border:"1px solid var(--border-strong, #d0d0d0)",borderRadius:6,background:"transparent",color:"inherit",cursor:"inherit"},ce={padding:0,border:"none",background:"none",font:"inherit",fontSize:12,color:"var(--sf-accent, #2563eb)",cursor:"pointer"},_={...ce,color:"#d85a30"};function y({label:a,value:t,placeholder:s,textarea:o,icon:u,onChange:l,onBlur:i,onKeyDown:h}){const b=U();return e(E,{label:a,icon:u??e(O,{}),htmlFor:b,children:o?e("textarea",{id:b,value:t,placeholder:s,onChange:g=>l(g.target.value)}):e("input",{id:b,type:"text",value:t,placeholder:s,onChange:g=>l(g.target.value),onBlur:i,onKeyDown:h})})}const de=[{label:"Auto",value:"auto"},{label:"Dark",value:"dark"},{label:"Light",value:"light"}],pe=[{label:"Tall (3:4)",value:"tall"},{label:"Square",value:"square"},{label:"Wide (2:1)",value:"wide"}];function R({label:a,icon:t,options:s,value:o,onChange:u}){return e(E,{label:a,icon:t,children:e("div",{role:"group","aria-label":a,style:{display:"flex",gap:4,flex:1},children:s.map(l=>{const i=o===l.value;return e("button",{type:"button","aria-pressed":i,onClick:()=>u(l.value),style:{flex:1,padding:"6px 8px",fontSize:12,borderRadius:6,cursor:"pointer",border:`1px solid ${i?"var(--sf-accent, #2563eb)":"var(--border-strong, #d0d0d0)"}`,background:i?"var(--sf-accent, #2563eb)":"transparent",color:i?"#fff":"inherit",fontWeight:i?500:400},children:l.label},l.value)})})})}function B({props:a,setSection:t,headOnly:s}){const o=i=>String(a[i]??""),u=a.mapTheme||H.mapTheme,l=H;return m(L,{children:[!s&&e(z,{children:"Section"}),e(y,{label:"Section number",value:o("sectionNumber"),placeholder:l.sectionNumber,onChange:i=>t({sectionNumber:i})}),e(y,{label:"Heading",textarea:!0,value:o("heading"),placeholder:l.heading,onChange:i=>t({heading:i})}),e(y,{label:"Body",textarea:!0,value:o("tagline"),placeholder:l.tagline,onChange:i=>t({tagline:i})}),s?null:m(L,{children:[e(z,{children:"City strip"}),e(y,{label:"Eyebrow",value:o("galleryKicker"),placeholder:l.galleryKicker,onChange:i=>t({galleryKicker:i})}),e(y,{label:"Hint",value:o("galleryHint"),placeholder:l.galleryHint,onChange:i=>t({galleryHint:i})}),e(R,{label:"Shape",icon:e(X,{}),options:pe,value:ae(a.imageShape),onChange:i=>t({imageShape:i})}),e(z,{children:"Map & Theme"}),e(R,{label:"Map theme",icon:e(V,{}),options:de,value:u,onChange:i=>t({mapTheme:i})})]})]})}function ue({cards:a,groupKey:t,onChange:s,onBack:o,onOpenCity:u,onNavigate:l}){const i=a.map((r,p)=>S(r)===t?p:-1).filter(r=>r>=0),h=String(a[i[0]]?.groupName??""),b=new Set(a.map(S).filter(r=>r!==t)),[g,C]=q(t),k=r=>s(a.map(p=>S(p)===t?{...p,...r}:p)),I=()=>{const r=g;if(r!==t){if(b.has(r)){C(t);return}s(a.map(p=>S(p)===t?{...p,group:r}:p)),l(r)}};return m("div",{className:"sf-locations-view",children:[e(N,{inline:!0,name:"Section",onSelect:o}),e("div",{style:{fontSize:14,fontWeight:500,margin:"6px 0 10px"},children:A(t,h)}),e(y,{label:"Group heading",value:g,placeholder:"e.g. Americas",onChange:C,onBlur:I,onKeyDown:r=>{r.key==="Enter"&&r.currentTarget.blur()}}),b.has(g)&&g!==t&&e("p",{className:"sf-note sf-note--error",role:"alert",children:"Another group already uses this heading \u2014 pick a different one."}),e(y,{label:"Group name",value:h,placeholder:"Shown beside the heading",onChange:r=>k({groupName:r})}),e(D,{label:"Cities in this group",noun:"city",items:i.map(r=>a[r]),onChange:r=>s(ie(a,t,r)),newItem:()=>({...G,group:t,groupName:h}),open:null,onOpen:()=>{},renderItem:()=>null,removeOnRow:!1,canDuplicate:()=>!1,renderRow:(r,p)=>m("button",{type:"button",style:W,onClick:()=>u(i[p]),children:[e("span",{children:r?.name||"City"}),e("span",{"aria-hidden":"true",children:"\u203A"})]})}),e("div",{style:{marginTop:12},children:m("button",{type:"button",style:_,onClick:()=>{s(a.filter(r=>S(r)!==t)),o()},children:["Delete group (",i.length," ",i.length===1?"city":"cities",")"]})})]})}function me({value:a,onChange:t}){const s=Array.isArray(a)?a:[],o=te(),u=ee(),l=se(s),{appState:i,selectedItem:h}=$(n=>n),b=re(),g=h?.props??{},C=n=>{if(!h)return;const d=(i.data.content??[]).findIndex(v=>v.props.id===h.props.id);d<0||b.replaceComponent(le,d,{type:h.type,props:{...h.props,...n}})},k=(n,c)=>t(s.map((d,v)=>v===n?{...d,...c}:d)),I=()=>{const n=new Set(l.map(v=>v.key));let c=l.length+1,d=`Group ${c}`;for(;n.has(d);)d=`Group ${++c}`;return d};if(o.level==="texts")return m("div",{className:"sf-locations-view",children:[e(N,{inline:!0,name:"Locations",onSelect:()=>f({level:"groups"})}),e("div",{style:{fontSize:14,fontWeight:500,margin:"6px 0 10px"},children:"Texts"}),e(B,{props:g,setSection:C,headOnly:!0})]});if(o.level==="image"){const n=s[o.index];return n?m("div",{className:"sf-locations-view",children:[e(N,{inline:!0,name:String(n.name??"")||"City",onSelect:()=>f({level:"city",index:o.index})}),e("div",{style:{fontSize:14,fontWeight:500,margin:"6px 0 10px"},children:"Image"}),e(K,{value:n.photo||"",onChange:c=>k(o.index,{photo:c}),label:"Image",accept:"image/*"})]}):r()}if(o.level==="map"){const n=s[o.index];return n?m("div",{className:"sf-locations-view",children:[e(N,{inline:!0,name:String(n.name??"")||"City",onSelect:()=>f({level:"city",index:o.index})}),e("div",{style:{fontSize:14,fontWeight:500,margin:"6px 0 10px"},children:"Map"}),e(ne,{value:n.geocode,onChange:c=>k(o.index,{geocode:c}),label:"Coordinates"}),e(y,{label:"Directions link",icon:e(Z,{}),value:String(n.mapsUrl??""),onChange:c=>k(o.index,{mapsUrl:c})})]}):r()}if(o.level==="city"){const n=o.index,c=s[n];if(!c)return r();const d=S(c),v=(w,T)=>k(n,{[w]:T}),x=(w,T,M,P=!1)=>e(y,{label:T,icon:M,textarea:P,value:String(c[w]??""),onChange:j=>v(w,j)});return m("div",{className:"sf-locations-view",children:[e(N,{inline:!0,name:A(d,String(c.groupName??"")),onSelect:()=>f({level:"group",key:d})}),e("div",{style:{fontSize:14,fontWeight:500,margin:"6px 0 10px"},children:c.name||"City"}),x("name","Location name",e(O,{})),x("state","State / Province",e(O,{})),x("country","Country",e(Y,{})),x("address","Address",e(J,{}),!0),x("phone","Phone",e(Q,{})),x("hours","Opening hours",e(F,{})),x("timezone","Timezone chip",e(F,{})),e("div",{style:{marginTop:12},children:e("button",{type:"button",style:_,onClick:()=>{t(s.filter((w,T)=>T!==n)),f({level:"group",key:d})},children:"Delete city"})})]})}if(o.level==="group")return l.some(n=>n.key===o.key)?e(ue,{cards:s,groupKey:o.key,onChange:t,onBack:()=>f({level:"groups"}),onOpenCity:n=>f({level:"city",index:n}),onNavigate:n=>f({level:"group",key:n})},o.key):r();function r(){return m("div",{className:"sf-locations-view",children:[e(B,{props:g,setSection:C}),!u&&e(L,{children:p()})]})}function p(){return e(D,{label:"Locations",noun:"group",items:l,onChange:n=>{const c=n.find(d=>!l.some(v=>v.key===d.key));t(oe(s,n.map(d=>d.key),d=>[{...G,group:d,groupName:""}])),c&&f({level:"group",key:c.key})},newItem:()=>({key:I(),name:"",indices:[]}),open:null,onOpen:()=>{},renderItem:()=>null,removeOnRow:!1,canDuplicate:()=>!1,above:l.length===0?e("div",{style:{fontSize:12,color:"var(--fg-dim, #999)",padding:"4px 0"},children:"No locations yet."}):void 0,renderRow:n=>m("button",{type:"button",style:W,onClick:()=>f({level:"group",key:n.key}),children:[e("span",{style:{fontWeight:500},children:A(n.key,n.name)}),m("span",{style:{color:"var(--fg-dim, #999)"},children:[n.indices.length," ",n.indices.length===1?"city":"cities"," \u203A"]})]})})}return r()}export{me as default};
@@ -1,6 +1 @@
1
- import { type MediaPanelComponent, type MediaPickRequest } from "../lib/editor-media-panel.js";
2
- export default function MediaSidePanel({ panel: Panel, pick, onHide, }: {
3
- panel: MediaPanelComponent;
4
- pick: MediaPickRequest | null;
5
- onHide?: () => void;
6
- }): import("react").JSX.Element;
1
+ export { default } from "efficient-easel/screen/components/MediaSidePanel";
@@ -1 +1 @@
1
- "use client";import{jsx as n,Fragment as l,jsxs as r}from"react/jsx-runtime";import{MediaPanelHead as m,mediaPickKind as o}from"efficient-easel/chrome";import{useWebsiteName as u}from"./WebsiteSettingsPanel.js";import{settlePanelPick as t}from"../lib/editor-media-panel.js";function f({panel:a,pick:e,onHide:i}){const s=u();return r(l,{children:[n(m,{context:s,pick:e?{kind:o(e.accept),field:e.title||void 0}:null,onCancel:()=>e&&t(e.requestId,null),onHide:i}),n("div",{className:"sf-media-panel",children:n(a,{pick:e,onPick:d=>e&&t(e.requestId,d)})})]})}export{f as default};
1
+ "use client";import{default as f}from"efficient-easel/screen/components/MediaSidePanel";export{f as default};
@@ -1 +1 @@
1
- "use client";import{jsxs as p,jsx as e}from"react/jsx-runtime";import{SettingsField as g}from"efficient-easel/panel";import{ImageIcon as h,PlayIcon as v}from"efficient-easel/icons";import{ImageBox as E}from"efficient-easel/pick";import{useContext as N,useState as y}from"react";import{FileIntakeAlert as S,useFileIntake as B}from"efficient-shell/file-intake";import{StorefrontDocumentContext as F}from"./StorefrontDocumentContext.js";import{requestMediaPick as x}from"../lib/editor-media-picker.js";import{useEditorHost as C}from"../lib/editor-host.js";import{backendOf as O}from"../lib/editor-session.js";import{useEditorSession as P}from"../lib/editor-session-context.js";function w({value:k,onChange:l,label:t,accept:i,placeholder:j}){const m=C(),b=P(),[r,d]=y(!1),[c,a]=y(null),s=i.startsWith("video"),u=N(F),o=B({accept:i,maxSizeBytes:O(b).media.maxUploadBytes,acceptHint:s?"videos only":"images only",multiple:!1,disabled:r,onAccept:([n])=>{a(null),d(!0),x(m,{accept:i,title:t,file:n}).then(f=>{f&&l(f.url)}).catch(()=>a("Couldn\u2019t open the media picker \u2014 please try again.")).finally(()=>d(!1))}}),I=()=>(o.clearRejections(),a(null),x(m,{accept:i,title:t}).then(n=>n?.url??null));return u&&!u.capabilities.mediaEditing?e(g,{label:t,icon:s?e(v,{}):e(h,{}),children:p("div",{className:"sf-image-slot-inert",children:["Templates don\u2019t store ",s?"videos":"images"," \u2014 this slot stays a placeholder. Each website picks its own after it\u2019s created."]})}):p("div",{children:[e(g,{label:t,icon:s?e(v,{}):e(h,{}),children:e("div",{className:`sf-image-drop${o.dragOver?" is-dragover":""}`,...o.zoneProps,children:e(E,{value:k,onChange:l,label:t,kind:s?"video":"image",placeholder:j,openLibrary:r?void 0:I})})}),r&&e("div",{className:"sf-image-status",role:"status",children:"Opening the picker\u2026"}),c&&e("div",{className:"sf-image-status sf-image-status--error",role:"alert",children:c}),e(S,{rejections:o.rejections,className:"sf-image-status sf-image-status--error"})]})}export{w as default};
1
+ "use client";import{jsxs as p,jsx as e}from"react/jsx-runtime";import{SettingsField as g}from"efficient-easel/panel";import{ImageIcon as h,PlayIcon as v}from"efficient-easel/icons";import{ImageBox as E}from"efficient-easel/pick";import{useContext as N,useState as y}from"react";import{FileIntakeAlert as S,useFileIntake as B}from"efficient-shell/file-intake";import{StorefrontDocumentContext as F}from"./StorefrontDocumentContext.js";import{requestMediaPick as x}from"../lib/editor-media-picker.js";import{useEditorHost as C}from"../lib/editor-host.js";import{backendOf as O}from"../lib/website-session.js";import{useEditorSession as P}from"../lib/editor-session-context.js";function w({value:k,onChange:l,label:t,accept:i,placeholder:j}){const m=C(),b=P(),[r,d]=y(!1),[c,a]=y(null),s=i.startsWith("video"),u=N(F),o=B({accept:i,maxSizeBytes:O(b).media.maxUploadBytes,acceptHint:s?"videos only":"images only",multiple:!1,disabled:r,onAccept:([n])=>{a(null),d(!0),x(m,{accept:i,title:t,file:n}).then(f=>{f&&l(f.url)}).catch(()=>a("Couldn\u2019t open the media picker \u2014 please try again.")).finally(()=>d(!1))}}),I=()=>(o.clearRejections(),a(null),x(m,{accept:i,title:t}).then(n=>n?.url??null));return u&&!u.capabilities.mediaEditing?e(g,{label:t,icon:s?e(v,{}):e(h,{}),children:p("div",{className:"sf-image-slot-inert",children:["Templates don\u2019t store ",s?"videos":"images"," \u2014 this slot stays a placeholder. Each website picks its own after it\u2019s created."]})}):p("div",{children:[e(g,{label:t,icon:s?e(v,{}):e(h,{}),children:e("div",{className:`sf-image-drop${o.dragOver?" is-dragover":""}`,...o.zoneProps,children:e(E,{value:k,onChange:l,label:t,kind:s?"video":"image",placeholder:j,openLibrary:r?void 0:I})})}),r&&e("div",{className:"sf-image-status",role:"status",children:"Opening the picker\u2026"}),c&&e("div",{className:"sf-image-status sf-image-status--error",role:"alert",children:c}),e(S,{rejections:o.rejections,className:"sf-image-status sf-image-status--error"})]})}export{w as default};
@@ -1,3 +1,4 @@
1
+ import { type ReactNode } from "react";
1
2
  import { type FieldOption } from "efficient-easel/fields";
2
3
  interface Option {
3
4
  value: string;
@@ -11,6 +12,8 @@ interface Props {
11
12
  value: string[];
12
13
  onChange: (value: string[]) => void;
13
14
  emptyLabel?: string;
15
+ icon?: ReactNode;
16
+ hint?: ReactNode;
14
17
  }
15
- export default function MultiSelectField({ label, options, value, onChange, emptyLabel, }: Props): import("react").JSX.Element;
18
+ export default function MultiSelectField({ label, options, value, onChange, emptyLabel, icon, hint, }: Props): import("react").JSX.Element;
16
19
  export {};
@@ -1 +1 @@
1
- "use client";import{jsx as o,jsxs as c}from"react/jsx-runtime";import{useId as u}from"react";import{FieldSelect as m}from"efficient-easel/fields";function f(l){return l.map(({value:i,label:e,note:t})=>({value:i,label:e,...t?{meta:t}:{}}))}function p({label:l,options:i,value:e,onChange:t,emptyLabel:a="None"}){const s=u(),r=`${s}-label`,n=`${s}-button`,d=Array.isArray(e)?e:[];return c("div",{className:"sf-field sf-multi",children:[o("div",{className:"sf-field-label",id:r,children:l}),o(m,{id:n,multiple:!0,value:d,options:f(i),onChange:t,placeholder:a,ariaLabelledBy:`${r} ${n}`,inline:!0})]})}export{p as default,f as multiSelectOptions};
1
+ "use client";import{jsx as a}from"react/jsx-runtime";import{useId as m}from"react";import{FieldSelect as p}from"efficient-easel/fields";import{SettingsField as b}from"efficient-easel/panel";function f(i){return i.map(({value:l,label:e,note:t})=>({value:l,label:e,...t?{meta:t}:{}}))}function h({label:i,options:l,value:e,onChange:t,emptyLabel:c="None",icon:d,hint:u}){const o=m(),n=`${o}-label`,r=`${o}-button`,s=Array.isArray(e)?e:[];return a(b,{label:i,labelId:n,icon:d,hint:u,children:a(p,{id:r,multiple:!0,value:s,options:f(l),onChange:t,placeholder:c,ariaLabelledBy:`${n} ${r}`,inline:!0})})}export{h as default,f as multiSelectOptions};
@@ -1,96 +1,2 @@
1
- import { type EaselContextMenuItem } from "efficient-easel/menu";
2
- import { type NodeOps } from "efficient-easel/node-ops";
3
- import { type StyleSnapshot } from "efficient-easel/style-clipboard";
4
- import { type CanvasTarget } from "efficient-easel/canvas";
5
- export type NodeMenuTarget = {
6
- kind: "node";
7
- x: number;
8
- y: number;
9
- zone: string;
10
- index: number;
11
- } | {
12
- kind: "empty";
13
- x: number;
14
- y: number;
15
- } | {
16
- kind: "input";
17
- x: number;
18
- y: number;
19
- el: TextEl;
20
- };
21
- type TextEl = {
22
- value: string;
23
- selectionStart: number | null;
24
- selectionEnd: number | null;
25
- setRangeText: (t: string, s: number, e: number, m?: string) => void;
26
- select: () => void;
27
- focus: () => void;
28
- dispatchEvent: (e: Event) => boolean;
29
- };
30
- type NodeLike = {
31
- type: string;
32
- props: {
33
- [key: string]: unknown;
34
- id: string;
35
- };
36
- };
37
- export type NodeMenuHost = {
38
- nodesIn: (zone: string) => NodeLike[];
39
- nodeAt: (zone: string, index: number) => NodeLike | null;
40
- labelOf: (type: string, zone: string) => string;
41
- rowNameOf: (node: NodeLike, zone: string) => string;
42
- renamePropOf: (node: NodeLike, zone: string) => string | null;
43
- beginRename: (zone: string, index: number) => void;
44
- history: {
45
- hasPast: boolean;
46
- hasFuture: boolean;
47
- back: () => void;
48
- forward: () => void;
49
- };
50
- openAddSection: () => void;
51
- openPageSettings: () => void;
52
- collapseAll: () => void;
53
- onPasteRefused: () => void;
54
- document: unknown;
55
- nodeOps: Pick<NodeOps, "held" | "remove" | "duplicate" | "step" | "canStep" | "setProps" | "copy" | "cut" | "paste">;
56
- isPinned: (node: NodeLike, zone: string) => boolean;
57
- sectionBand: () => {
58
- floor: number;
59
- cap: number;
60
- };
61
- selectAt: (zone: string, index: number, id: string, parentType: string | null) => void;
62
- openAddInside: (zone: string, index: number) => void;
63
- locate: (id: string) => {
64
- zone: string;
65
- index: number;
66
- } | null;
67
- style?: {
68
- held: () => StyleSnapshot | null;
69
- canCopy: (node: NodeLike, zone: string) => boolean;
70
- copy: (node: NodeLike, zone: string) => void;
71
- paste: (zone: string, index: number, node: NodeLike) => void;
72
- };
73
- };
74
- export type ChainRung = {
75
- zone: string;
76
- index: number;
77
- node: NodeLike;
78
- parentType: string | null;
79
- };
80
- export declare function ancestorChain(host: NodeMenuHost, target: {
81
- zone: string;
82
- index: number;
83
- }): ChainRung[];
84
- export declare const EDITOR_NODE_CLIPBOARD: import("efficient-easel/node-ops").NodeClipboard;
85
- export declare function nodeMenuItems(host: NodeMenuHost, target: {
86
- zone: string;
87
- index: number;
88
- }): EaselContextMenuItem[];
89
- export declare function pageMenuItems(host: NodeMenuHost): EaselContextMenuItem[];
90
- export declare function textMenuItems(host: NodeMenuHost, el: TextEl): EaselContextMenuItem[];
91
- export declare function useNodeContextMenu(host: NodeMenuHost, canvas: CanvasTarget | null): {
92
- onEditorContextMenu: (e: React.MouseEvent) => void;
93
- menu: import("react").JSX.Element | null;
94
- closeMenu: () => void;
95
- };
96
- export {};
1
+ export { ancestorChain, EASEL_NODE_CLIPBOARD as EDITOR_NODE_CLIPBOARD, nodeMenuItems, pageMenuItems, textMenuItems, useNodeContextMenu } from "efficient-easel/screen/components/NodeContextMenu";
2
+ export type { ChainRung, NodeMenuHost, NodeMenuTarget } from "efficient-easel/screen/components/NodeContextMenu";