efficient-easel 0.101.0 → 0.102.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.
- package/README.md +37 -0
- package/dist/LinkPicker-W2Rtxetz.d.ts +111 -0
- package/dist/autosave/index.d.ts +6 -3
- package/dist/autosave/index.js +1 -1
- package/dist/chrome/index.d.ts +3 -2
- package/dist/chrome/index.js +1 -25
- package/dist/chunk-26OOWIJJ.js +1 -0
- package/dist/chunk-2LK54I4E.js +1 -0
- package/dist/chunk-3QVB4AG2.js +3 -0
- package/dist/chunk-3U4GP5VA.js +10 -0
- package/dist/chunk-3WSPDAK2.js +1 -0
- package/dist/chunk-4ES5JGGX.js +1 -0
- package/dist/chunk-5464H65G.js +4 -0
- package/dist/chunk-57DJOKXT.js +1 -0
- package/dist/chunk-5MZ3RNQQ.js +13 -0
- package/dist/chunk-5ZBY24K7.js +1 -0
- package/dist/chunk-6DJHRLCU.js +25 -0
- package/dist/chunk-6FY3PZS3.js +1 -0
- package/dist/chunk-6TZTKAB5.js +1 -0
- package/dist/chunk-6W7WLPZH.js +1 -0
- package/dist/chunk-7F52SZOI.js +2 -0
- package/dist/chunk-7MU3RJ6S.js +1 -0
- package/dist/chunk-7RNTMJER.js +5 -0
- package/dist/chunk-A7ZJII7O.js +1 -0
- package/dist/chunk-AJBJ74ME.js +1 -0
- package/dist/chunk-AKFJK65Z.js +1 -0
- package/dist/chunk-AKZWUV5Z.js +1 -0
- package/dist/chunk-BDTITTMW.js +1 -0
- package/dist/chunk-BSPCSC45.js +1 -0
- package/dist/chunk-BXZ6WLHC.js +22 -0
- package/dist/chunk-D7M6IRPJ.js +8 -0
- package/dist/chunk-DUVRZ456.js +1 -0
- package/dist/chunk-E7GGVILG.js +1 -0
- package/dist/chunk-F2FPZIZV.js +62 -0
- package/dist/chunk-F6CCTEIX.js +1 -0
- package/dist/chunk-FGNR22NY.js +1 -0
- package/dist/chunk-FT35FX7D.js +2 -0
- package/dist/chunk-FUDHI5I4.js +1 -0
- package/dist/chunk-GENAF3P6.js +1 -0
- package/dist/chunk-GOTN2KY4.js +2 -0
- package/dist/chunk-GXQCZJOP.js +1 -0
- package/dist/chunk-GZO72N3Q.js +0 -0
- package/dist/chunk-HMX55DYT.js +1 -0
- package/dist/chunk-HQ4VVRIC.js +1 -0
- package/dist/chunk-HWW4XJOH.js +1 -0
- package/dist/chunk-I54UCYOU.js +1 -0
- package/dist/chunk-IQ5TA7AM.js +1 -0
- package/dist/chunk-IWAPPEL4.js +6 -0
- package/dist/chunk-IYT6NN2J.js +1 -0
- package/dist/chunk-J4RAY75C.js +1 -0
- package/dist/chunk-KCBEE2MC.js +2 -0
- package/dist/chunk-KDYIMJTZ.js +1 -0
- package/dist/chunk-KQMML6JM.js +4 -0
- package/dist/chunk-OM67AJQC.js +1 -0
- package/dist/chunk-OYX47SL7.js +1 -0
- package/dist/chunk-P67FP7PG.js +9 -0
- package/dist/chunk-PP44LCJM.js +1 -0
- package/dist/chunk-PWZOS45R.js +2 -0
- package/dist/chunk-Q3SQBNJB.js +1 -0
- package/dist/chunk-R2HLPNQF.js +1 -0
- package/dist/chunk-R5L2E7JX.js +1 -0
- package/dist/chunk-R5ZVNJLJ.js +2 -0
- package/dist/chunk-RLBXE4EU.js +1 -0
- package/dist/chunk-RW4XBUUW.js +1 -0
- package/dist/chunk-SERF2FAU.js +1 -0
- package/dist/chunk-TEZ6V6PA.js +4 -0
- package/dist/chunk-TTJ54QGG.js +18 -0
- package/dist/chunk-UH7TGWHR.js +1 -0
- package/dist/chunk-UVWVYMMZ.js +1 -0
- package/dist/chunk-VLSTGOVD.js +2 -0
- package/dist/chunk-VV5ADNBR.js +1 -0
- package/dist/chunk-ZE7I3PLX.js +1 -0
- package/dist/chunk-ZZ7VLIHQ.js +1 -0
- package/dist/drag/index.d.ts +3 -41
- package/dist/drag/index.js +1 -18
- package/dist/easel/index.js +1 -9
- package/dist/{words-BMzV04b1.d.ts → engine-DBxp_v6B.d.ts} +1 -58
- package/dist/fields/index.d.ts +2 -109
- package/dist/fields/index.js +1 -22
- package/dist/gold/index.d.ts +4 -2
- package/dist/host-B-byaQxg.d.ts +480 -0
- package/dist/menu/index.js +1 -1
- package/dist/node-ops/index.js +1 -1
- package/dist/panel/index.js +16 -16
- package/dist/panelWidths-D9hTLR25.d.ts +66 -0
- package/dist/screen/components/AddBlockRow.d.ts +14 -0
- package/dist/screen/components/AddBlockRow.js +1 -0
- package/dist/screen/components/AddChildRow.d.ts +39 -0
- package/dist/screen/components/AddChildRow.js +1 -0
- package/dist/screen/components/AddSidePanel.d.ts +54 -0
- package/dist/screen/components/AddSidePanel.js +1 -0
- package/dist/screen/components/MediaSidePanel.d.ts +47 -0
- package/dist/screen/components/MediaSidePanel.js +1 -0
- package/dist/screen/components/NodeContextMenu.d.ts +364 -0
- package/dist/screen/components/NodeContextMenu.js +1 -0
- package/dist/screen/components/PageEditGuardNotices.d.ts +5 -0
- package/dist/screen/components/PageEditGuardNotices.js +1 -0
- package/dist/screen/components/PanelToggleIcon.d.ts +14 -0
- package/dist/screen/components/PanelToggleIcon.js +1 -0
- package/dist/screen/components/PreviewDeviceContext.d.ts +28 -0
- package/dist/screen/components/PreviewDeviceContext.js +1 -0
- package/dist/screen/components/PreviewPartsContext.d.ts +33 -0
- package/dist/screen/components/PreviewPartsContext.js +1 -0
- package/dist/screen/components/ScreenChrome.d.ts +5 -0
- package/dist/screen/components/ScreenChrome.js +1 -0
- package/dist/screen/components/ScreenDocumentContext.d.ts +20 -0
- package/dist/screen/components/ScreenDocumentContext.js +1 -0
- package/dist/screen/components/ScreenMount.d.ts +75 -0
- package/dist/screen/components/ScreenMount.js +1 -0
- package/dist/screen/components/ScreenStoreProvider.d.ts +63 -0
- package/dist/screen/components/ScreenStoreProvider.js +1 -0
- package/dist/screen/components/SectionScreenShell.d.ts +5 -0
- package/dist/screen/components/SectionScreenShell.js +16 -0
- package/dist/screen/components/SidePanelHead.d.ts +81 -0
- package/dist/screen/components/SidePanelHead.js +1 -0
- package/dist/screen/components/SlotChildActionsContext.d.ts +41 -0
- package/dist/screen/components/SlotChildActionsContext.js +1 -0
- package/dist/screen/components/UiIcon.d.ts +52 -0
- package/dist/screen/components/UiIcon.js +1 -0
- package/dist/screen/components/panel-widths.d.ts +37 -0
- package/dist/screen/components/panel-widths.js +1 -0
- package/dist/screen/components/usePartBridge.d.ts +66 -0
- package/dist/screen/components/usePartBridge.js +1 -0
- package/dist/screen/index.d.ts +31 -0
- package/dist/screen/index.js +1 -0
- package/dist/screen/lib/admin-bridge.d.ts +105 -0
- package/dist/screen/lib/admin-bridge.js +1 -0
- package/dist/screen/lib/backend-error.d.ts +106 -0
- package/dist/screen/lib/backend-error.js +1 -0
- package/dist/screen/lib/chrome-theme.d.ts +21 -0
- package/dist/screen/lib/chrome-theme.js +1 -0
- package/dist/screen/lib/client-only.d.ts +24 -0
- package/dist/screen/lib/client-only.js +1 -0
- package/dist/screen/lib/content/view-tiers.d.ts +25 -0
- package/dist/screen/lib/content/view-tiers.js +1 -0
- package/dist/screen/lib/document-addressing.d.ts +20 -0
- package/dist/screen/lib/document-addressing.js +1 -0
- package/dist/screen/lib/document-contract.d.ts +230 -0
- package/dist/screen/lib/document-contract.js +1 -0
- package/dist/screen/lib/document-hooks.d.ts +71 -0
- package/dist/screen/lib/document-hooks.js +0 -0
- package/dist/screen/lib/document-switch.d.ts +74 -0
- package/dist/screen/lib/document-switch.js +1 -0
- package/dist/screen/lib/failure.d.ts +54 -0
- package/dist/screen/lib/failure.js +1 -0
- package/dist/screen/lib/host-chrome.d.ts +181 -0
- package/dist/screen/lib/host-chrome.js +1 -0
- package/dist/screen/lib/host-inbound.d.ts +20 -0
- package/dist/screen/lib/host-inbound.js +1 -0
- package/dist/screen/lib/host.d.ts +20 -0
- package/dist/screen/lib/host.js +1 -0
- package/dist/screen/lib/key-scope.d.ts +23 -0
- package/dist/screen/lib/key-scope.js +1 -0
- package/dist/screen/lib/links/link-filters.d.ts +41 -0
- package/dist/screen/lib/links/link-filters.js +0 -0
- package/dist/screen/lib/load-error.d.ts +29 -0
- package/dist/screen/lib/load-error.js +1 -0
- package/dist/screen/lib/media-panel.d.ts +94 -0
- package/dist/screen/lib/media-panel.js +1 -0
- package/dist/screen/lib/media-picker.d.ts +68 -0
- package/dist/screen/lib/media-picker.js +1 -0
- package/dist/screen/lib/page-lock.d.ts +5 -0
- package/dist/screen/lib/page-lock.js +1 -0
- package/dist/screen/lib/puck/add-target-types.d.ts +55 -0
- package/dist/screen/lib/puck/add-target-types.js +0 -0
- package/dist/screen/lib/puck/block-choice.d.ts +52 -0
- package/dist/screen/lib/puck/block-choice.js +1 -0
- package/dist/screen/lib/puck/block-types-in.d.ts +39 -0
- package/dist/screen/lib/puck/block-types-in.js +1 -0
- package/dist/screen/lib/puck/content-tree.d.ts +196 -0
- package/dist/screen/lib/puck/content-tree.js +1 -0
- package/dist/screen/lib/puck/device-fields.d.ts +126 -0
- package/dist/screen/lib/puck/device-fields.js +1 -0
- package/dist/screen/lib/puck/field-buckets.d.ts +22 -0
- package/dist/screen/lib/puck/field-buckets.js +1 -0
- package/dist/screen/lib/puck/field-markers.d.ts +205 -0
- package/dist/screen/lib/puck/field-markers.js +1 -0
- package/dist/screen/lib/puck/hidable.d.ts +44 -0
- package/dist/screen/lib/puck/hidable.js +1 -0
- package/dist/screen/lib/puck/palette-sections.d.ts +96 -0
- package/dist/screen/lib/puck/palette-sections.js +1 -0
- package/dist/screen/lib/puck/panel-fields.d.ts +47 -0
- package/dist/screen/lib/puck/panel-fields.js +1 -0
- package/dist/screen/lib/puck/panel-no-control-mark.d.ts +74 -0
- package/dist/screen/lib/puck/panel-no-control-mark.js +1 -0
- package/dist/screen/lib/puck/part-id.d.ts +23 -0
- package/dist/screen/lib/puck/part-id.js +1 -0
- package/dist/screen/lib/puck/preview-click.d.ts +49 -0
- package/dist/screen/lib/puck/preview-click.js +1 -0
- package/dist/screen/lib/puck/preview-dom.d.ts +8 -0
- package/dist/screen/lib/puck/preview-dom.js +1 -0
- package/dist/screen/lib/puck/preview-events.d.ts +25 -0
- package/dist/screen/lib/puck/preview-events.js +1 -0
- package/dist/screen/lib/puck/preview-selection-context.d.ts +72 -0
- package/dist/screen/lib/puck/preview-selection-context.js +1 -0
- package/dist/screen/lib/puck/section-doc.d.ts +20 -0
- package/dist/screen/lib/puck/section-doc.js +1 -0
- package/dist/screen/lib/puck/slot-child-name.d.ts +186 -0
- package/dist/screen/lib/puck/slot-child-name.js +1 -0
- package/dist/screen/lib/puck/slot-heal.d.ts +5 -0
- package/dist/screen/lib/puck/slot-heal.js +1 -0
- package/dist/screen/lib/puck/slot-section-spec.d.ts +96 -0
- package/dist/screen/lib/puck/slot-section-spec.js +0 -0
- package/dist/screen/lib/puck/style-clipboard.d.ts +78 -0
- package/dist/screen/lib/puck/style-clipboard.js +1 -0
- package/dist/screen/lib/puck/text-control-kinds.d.ts +71 -0
- package/dist/screen/lib/puck/text-control-kinds.js +1 -0
- package/dist/screen/lib/puck/tree-reveal.d.ts +62 -0
- package/dist/screen/lib/puck/tree-reveal.js +1 -0
- package/dist/screen/lib/puck/use-section-ops.d.ts +86 -0
- package/dist/screen/lib/puck/use-section-ops.js +1 -0
- package/dist/screen/lib/screen-parts.d.ts +727 -0
- package/dist/screen/lib/screen-parts.js +1 -0
- package/dist/screen/lib/section-template-types.d.ts +49 -0
- package/dist/screen/lib/section-template-types.js +0 -0
- package/dist/screen/lib/section-templates.d.ts +23 -0
- package/dist/screen/lib/section-templates.js +1 -0
- package/dist/screen/lib/session-context.d.ts +30 -0
- package/dist/screen/lib/session-context.js +1 -0
- package/dist/screen/lib/session.d.ts +255 -0
- package/dist/screen/lib/session.js +1 -0
- package/dist/screen/screen.css +1088 -0
- package/dist/session-DSQFmIvx.d.ts +43 -0
- package/dist/strings/catalogue.d.ts +4 -2
- package/dist/strings/catalogue.js +1 -1
- package/dist/strings/index.d.ts +4 -2
- package/dist/strings/index.js +1 -1
- package/dist/style-clipboard/index.js +1 -1
- package/dist/{types-DGcCsxs8.d.ts → types-CqY85foL.d.ts} +3 -65
- package/dist/words-D_Lnw1Gr.d.ts +59 -0
- package/package.json +343 -2
- package/dist/chunk-IG3U5NWJ.js +0 -1
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Shared machinery for the editor preview's "selection bridges" — the click-to-
|
|
6
|
+
* select plumbing every piece of site CHROME needs because it is NOT a Puck node
|
|
7
|
+
* and so can't route through Puck's own selection. The header, the chat bubble,
|
|
8
|
+
* and a Hero's ticker / background / text overlay each expose the SAME two-way
|
|
9
|
+
* bridge, and all built it by hand until this file:
|
|
10
|
+
*
|
|
11
|
+
* - `select(…)` / `setSelectHandler(fn)` — a ref-backed handler the chrome
|
|
12
|
+
* registers (it opens the matching inspector panel), invoked from inside the
|
|
13
|
+
* portaled preview iframe when the element is clicked. It lives behind a ref so
|
|
14
|
+
* the chrome can re-register without re-rendering the preview; `select` itself
|
|
15
|
+
* stays stable. See {@link useSelectHandler}.
|
|
16
|
+
* - a mirrored SELECTION the preview reads to draw its own "selected" outline.
|
|
17
|
+
*
|
|
18
|
+
* Two entry points reuse the bridge:
|
|
19
|
+
* - {@link useSelectHandler} — just the ref-backed `select` / `setSelectHandler`
|
|
20
|
+
* pair, for the header + chat bridges. They keep a plain boolean `selected` and
|
|
21
|
+
* layer their own live-config state around it, so they compose this hook rather
|
|
22
|
+
* than the whole context factory.
|
|
23
|
+
* - {@link createPreviewSelectionContext} — a whole context + provider + hook for
|
|
24
|
+
* an ID-SCOPED bridge (a Hero's ticker / background / text), where the mirrored
|
|
25
|
+
* selection is "which sibling id is selected" (`selected<Thing>Id`), scoped by
|
|
26
|
+
* id so sibling heroes never cross-select. The three such contexts differ ONLY
|
|
27
|
+
* in that field's name, so they are each one call to this factory.
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* The ref-backed `select` / `setSelectHandler` pair shared by every selection
|
|
31
|
+
* bridge. `Args` is the click payload the chrome's handler receives — `[]` for a
|
|
32
|
+
* lone toggle (header / chat) or `[id: string]` for an id-scoped bridge (ticker /
|
|
33
|
+
* hero media / hero text). `select` is stable across renders; registering a new
|
|
34
|
+
* handler never re-renders the portaled preview.
|
|
35
|
+
*/
|
|
36
|
+
declare function useSelectHandler<Args extends unknown[]>(): {
|
|
37
|
+
select: (...args: Args) => void;
|
|
38
|
+
setSelectHandler: (fn: (...args: Args) => void) => void;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* The context value of an id-scoped selection bridge, keyed by the id field's
|
|
42
|
+
* name `Key` (e.g. `"selectedHeroId"`): the mirrored id + its `set…` setter, plus
|
|
43
|
+
* the shared `select(id)` / `setSelectHandler` pair. Keeping the field name in the
|
|
44
|
+
* type is what lets one factory reproduce each context's exact public API.
|
|
45
|
+
*/
|
|
46
|
+
type PreviewIdSelection<Key extends string> = {
|
|
47
|
+
[P in Key]: string | null;
|
|
48
|
+
} & {
|
|
49
|
+
[P in Key as `set${Capitalize<P>}`]: (id: string | null) => void;
|
|
50
|
+
} & {
|
|
51
|
+
select: (id: string) => void;
|
|
52
|
+
setSelectHandler: (fn: (id: string) => void) => void;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Build a complete id-scoped selection-bridge context — the shared body of
|
|
56
|
+
* PreviewTickerContext / PreviewHeroMediaContext / PreviewHeroTextContext, which
|
|
57
|
+
* differ only in the id field's NAME. Pass that field name and the returned
|
|
58
|
+
* `Provider` + `useSelection` expose exactly `{ [idKey], set<IdKey>, select,
|
|
59
|
+
* setSelectHandler }`, so each context's existing consumers read unchanged.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* export const { Provider: PreviewTickerProvider, useSelection: usePreviewTicker } =
|
|
63
|
+
* createPreviewSelectionContext("selectedHeroId");
|
|
64
|
+
*/
|
|
65
|
+
declare function createPreviewSelectionContext<Key extends string>(idKey: Key): {
|
|
66
|
+
Provider: ({ children }: {
|
|
67
|
+
children: ReactNode;
|
|
68
|
+
}) => react.JSX.Element;
|
|
69
|
+
useSelection: () => PreviewIdSelection<Key>;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export { type PreviewIdSelection, createPreviewSelectionContext, useSelectHandler };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{createPreviewSelectionContext,useSelectHandler}from"../../../chunk-GOTN2KY4.js";import"../../../chunk-R5L2E7JX.js";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Data } from '../../../blocks/index.js';
|
|
2
|
+
import { TreeItem } from './content-tree.js';
|
|
3
|
+
import 'react';
|
|
4
|
+
import '../../../types-E3HrTPg2.js';
|
|
5
|
+
import '../../../data/index.js';
|
|
6
|
+
import '../../../types-41704JE4.js';
|
|
7
|
+
import '../../../resolve-D68pb3Bx.js';
|
|
8
|
+
import '../../../plan-DChbUXdS.js';
|
|
9
|
+
|
|
10
|
+
declare function nodeToDoc(node: TreeItem): Data;
|
|
11
|
+
declare function docToNode(data: Data): TreeItem | null;
|
|
12
|
+
/**
|
|
13
|
+
* Deep-copy a stored section node with FRESH ids — the node's own and every
|
|
14
|
+
* inline slot child's, recursively — so inserting the same template twice never
|
|
15
|
+
* lands two nodes with colliding ids (Puck keys selection/replace on id, and
|
|
16
|
+
* React keys render on it).
|
|
17
|
+
*/
|
|
18
|
+
declare function cloneNodeWithFreshIds(node: TreeItem): TreeItem;
|
|
19
|
+
|
|
20
|
+
export { cloneNodeWithFreshIds, docToNode, nodeToDoc };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{cloneNodeWithFreshIds,docToNode,nodeToDoc}from"../../../chunk-AKFJK65Z.js";import"../../../chunk-FUDHI5I4.js";
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a slot child is CALLED — the ONE rule, and the only place it is written
|
|
3
|
+
* (card 66194).
|
|
4
|
+
*
|
|
5
|
+
* A slot-backed section (Hero Slideshow, Collections, Product Grid, Customer
|
|
6
|
+
* Photo Grid, Gallery) keeps its children on its own props, and three surfaces
|
|
7
|
+
* have to put a word on each of them: the page editor's Sections tree
|
|
8
|
+
* (`ScreenChrome`), the standalone section editor's tree
|
|
9
|
+
* (`SectionScreenShell`) — which also feeds the list drawn inside the section's
|
|
10
|
+
* own settings panel through `SlotChildActionsContext` — and `CollectionCard`'s
|
|
11
|
+
* own render, which puts the SAME word on the published card.
|
|
12
|
+
*
|
|
13
|
+
* Before this card the rule was written out three times. Card 66186 wrote the
|
|
14
|
+
* second copy, card 66190 had to edit both to add the Collection Card step and
|
|
15
|
+
* discovered the third while doing it. Three copies of a five-rung precedence is
|
|
16
|
+
* a rule that looks right until the day two of them disagree — and a merchant
|
|
17
|
+
* would meet that as a tree row and a card that name the same thing differently.
|
|
18
|
+
*
|
|
19
|
+
* ── THE PRECEDENCE, most specific first ──────────────────────────────────────
|
|
20
|
+
* 1. `props.name` an explicit identifier the author typed (Hero Slide's
|
|
21
|
+
* "Slide name", Gallery Item's "Heading").
|
|
22
|
+
* 2. `props.altName` a card-local override of the name below it
|
|
23
|
+
* (Collection Card's "Alt name").
|
|
24
|
+
* 3. `props.collection` the LINKED category's snapshot name — the source the
|
|
25
|
+
* override above overrides.
|
|
26
|
+
* 3b. `props.source` the LINKED post's snapshot headline (Post card). The
|
|
27
|
+
* SAME rung as `collection` and deliberately beside it:
|
|
28
|
+
* both are "the thing this block is linked to, named by
|
|
29
|
+
* its own snapshot", and both are overridable by the two
|
|
30
|
+
* rungs above. A Post card is the first slot child that
|
|
31
|
+
* links to a post — Featured cover and Long read link to
|
|
32
|
+
* one too, but they are top-level sections and never
|
|
33
|
+
* reach this rule — so without it four cards in a Box
|
|
34
|
+
* all read "Post card" and a merchant cannot tell which
|
|
35
|
+
* one they are dragging.
|
|
36
|
+
* 4. `props.code` a catalog slug (Product Ref stores only this), resolved
|
|
37
|
+
* through `wheelName` when a caller supplies one.
|
|
38
|
+
* 5. the caller's own fallback — see {@link slotChildRowName}.
|
|
39
|
+
*
|
|
40
|
+
* `name` and `altName` may be hidable values (`{text,hidden}`) rather than bare
|
|
41
|
+
* strings, so both read through `hidableText`: an object reaching a tree row
|
|
42
|
+
* crashes it ("Objects are not valid as a React child").
|
|
43
|
+
*
|
|
44
|
+
* Rungs 1–3 are authored copy and may carry the shop's editorial marks. A TREE
|
|
45
|
+
* ROW unwraps them ({@link slotChildRowName}); the published card does not, and
|
|
46
|
+
* must not — that rung's own comment carries the reasoning (card 66202). How a
|
|
47
|
+
* mark is unwrapped is the grammar's, so the row is handed the function that
|
|
48
|
+
* does it, as it is handed the catalog: this module goes into efficient-easel
|
|
49
|
+
* with the screen (doc/adr/0004), and the grammar is the layer's.
|
|
50
|
+
*
|
|
51
|
+
* ── WHY THE CATALOG RESOLVER IS AN ARGUMENT ──────────────────────────────────
|
|
52
|
+
* The two trees genuinely differ at rung 4, and always have: the page editor has
|
|
53
|
+
* the product catalog loaded and shows a Product Ref as "Turbine II", while the
|
|
54
|
+
* standalone shell has no catalog and shows the raw slug `turbine-ii`. That
|
|
55
|
+
* asymmetry shipped with card 66186 and is real behaviour, NOT a defect this
|
|
56
|
+
* module quietly repairs. Taking the resolver as a parameter makes it an
|
|
57
|
+
* explicit argument instead of an accident: the shell passes none, so it shows
|
|
58
|
+
* the slug, and a reader sees that on the call line rather than discovering it.
|
|
59
|
+
* (Same reasoning as `content-tree.ts`, which takes the config as an argument
|
|
60
|
+
* rather than importing it.)
|
|
61
|
+
*
|
|
62
|
+
* `scripts/test-slot-child-name.tsx` pins the behaviour — the precedence, the
|
|
63
|
+
* resolver contract, and that every existing row name is unchanged.
|
|
64
|
+
* `scripts/test-slot-child-lists.tsx` §5 pins that this stays the ONE home.
|
|
65
|
+
*/
|
|
66
|
+
/**
|
|
67
|
+
* A Puck content node as this rule reads it. Deliberately looser than
|
|
68
|
+
* `TreeItem` (no required `id`): `CollectionCard.render` names itself from the
|
|
69
|
+
* props it was handed, and never has a node in hand.
|
|
70
|
+
*/
|
|
71
|
+
type SlotChild = {
|
|
72
|
+
type: string;
|
|
73
|
+
props: Record<string, unknown>;
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* The name a slot child carries in its OWN data — rungs 1–4 above — or `""` when
|
|
77
|
+
* it carries none.
|
|
78
|
+
*
|
|
79
|
+
* `wheelName` resolves a `props.code` catalog slug to a wheel's design name; a
|
|
80
|
+
* caller with no catalog omits it and the slug stands.
|
|
81
|
+
*
|
|
82
|
+
* Callers that need a word for an unnamed child add their own last rung; they do
|
|
83
|
+
* not agree on what it should be, which is exactly why it is not in here. The
|
|
84
|
+
* two trees fall back to the component's label ({@link slotChildRowName}), while
|
|
85
|
+
* `CollectionCard.render` falls back to an editor-only placeholder — an unlinked
|
|
86
|
+
* card must not publish the words "Collection Card".
|
|
87
|
+
*/
|
|
88
|
+
declare function slotChildName(child: SlotChild, wheelName?: (code: string) => string | undefined): string;
|
|
89
|
+
/**
|
|
90
|
+
* The full five-rung rule as a TREE ROW reads it: {@link slotChildName} with its
|
|
91
|
+
* markup unwrapped, else the component's friendly label. `compLabel` is the
|
|
92
|
+
* host's own config-backed lookup (`config.components[type].label ?? type`) —
|
|
93
|
+
* passed in, because this module has no config and importing one would make the
|
|
94
|
+
* editor's naming rule a dependency of the config that describes it.
|
|
95
|
+
*
|
|
96
|
+
* `plainText` unwraps the markup: the plain words of authored copy in the
|
|
97
|
+
* layer's grammar, which the screen holds as `ScreenBlockLook.plainText`
|
|
98
|
+
* (lib/screen-parts). The website's is lib/markup `stripMarkup`. Passed in for
|
|
99
|
+
* the reason `compLabel` is: the grammar is the layer's, and an email's is not
|
|
100
|
+
* a website's.
|
|
101
|
+
*
|
|
102
|
+
* ── WHY THE STRIP IS HERE AND NOT ONE RUNG DOWN (card 66202) ─────────────────
|
|
103
|
+
* A slot child's name is AUTHORED COPY. Rungs 1–3 are boxes a merchant types
|
|
104
|
+
* into, so they may carry any mark in the shop's grammar, and a tree row printed
|
|
105
|
+
* them verbatim: `Precision== Forged==` in a list that is plain text end to end.
|
|
106
|
+
* It reads as broken, and it is expensive — `.sf-subtree` costs 25px a nesting
|
|
107
|
+
* level, so a depth-2 row has roughly 172px of a 288px panel to spell a name in
|
|
108
|
+
* and truncates. Four delimiters come out of that budget before a word does.
|
|
109
|
+
*
|
|
110
|
+
* `slotChildName` deliberately does NOT strip, and that asymmetry is the whole
|
|
111
|
+
* point of putting this on the row rung instead. Its third caller is
|
|
112
|
+
* `CollectionCard.render`, which puts the word on a customer's LIVE page, where
|
|
113
|
+
* `<CollectionCard/>` routes `name` through `renderHeadline` — so `==phrase==`
|
|
114
|
+
* there is the merchant's accent colour, not noise. Stripping one rung lower
|
|
115
|
+
* would have flattened it on every published card that uses one. A tree row is
|
|
116
|
+
* the surface that cannot draw a mark; it is the surface that drops it.
|
|
117
|
+
*
|
|
118
|
+
* Through the grammar's own stripper (the website's `stripMarkup`), never by
|
|
119
|
+
* deleting delimiter characters: that unwraps a PAIR and leaves a lone
|
|
120
|
+
* delimiter exactly where the renderer leaves it, so a half-typed name — which
|
|
121
|
+
* is what mid-edit data actually looks like — keeps its whole line. It also
|
|
122
|
+
* means a mark the grammar grows is handled here with no edit, because this
|
|
123
|
+
* file names no delimiter of its own.
|
|
124
|
+
*
|
|
125
|
+
* The fallback still fires only for a genuinely nameless child: the grammar
|
|
126
|
+
* needs at least one character between a pair, so a name that is non-empty
|
|
127
|
+
* cannot strip to nothing and be renamed into its component's label.
|
|
128
|
+
*/
|
|
129
|
+
declare function slotChildRowName(child: SlotChild, compLabel: (type: string) => string, plainText: (copy: string) => string, wheelName?: (code: string) => string | undefined): string;
|
|
130
|
+
/**
|
|
131
|
+
* WHICH PROP A RENAME WRITES — the write side of the rule above, and here for
|
|
132
|
+
* the reason the read side is: naming a slot child has ONE home (card 66194).
|
|
133
|
+
* A rename that picked its own prop would be a sixth opinion about what a child
|
|
134
|
+
* is called, and the day it disagreed a merchant would rename a row and watch
|
|
135
|
+
* the row not change.
|
|
136
|
+
*
|
|
137
|
+
* Returns the prop key, or `null` when this component has no name to write —
|
|
138
|
+
* and a `null` is what takes `Rename` out of the menu, rather than a menu item
|
|
139
|
+
* that does nothing.
|
|
140
|
+
*
|
|
141
|
+
* ── ONLY A DECLARED IDENTIFIER, AND THIS IS THE WHOLE TRAP ───────────────────
|
|
142
|
+
* `GalleryItem.name` is keyed `name`, it IS what its Layers row says, and it is
|
|
143
|
+
* an ordinary `Heading` a merchant writes — copy, printed on the page. A rename
|
|
144
|
+
* keyed on the prop NAME would quietly rewrite that heading from a menu item
|
|
145
|
+
* called "Rename". So the field must DECLARE itself an identifier
|
|
146
|
+
* (`withIdentifier`, see `lib/puck/controls`), which is the same declaration the
|
|
147
|
+
* settings panel reads to keep these rows out of the copy list.
|
|
148
|
+
*
|
|
149
|
+
* `fields` is taken as an argument rather than imported, exactly like the
|
|
150
|
+
* `wheelName` resolver above: this module has no config, and importing one would
|
|
151
|
+
* make the editor's naming rule a dependency of the config that describes it.
|
|
152
|
+
*
|
|
153
|
+
* The order matches {@link slotChildName}'s precedence, so the prop a rename
|
|
154
|
+
* writes is the prop the row then reads. `altName` before `name` cannot happen
|
|
155
|
+
* in today's config — no component declares both — and the order is written out
|
|
156
|
+
* anyway so the answer does not depend on that staying true.
|
|
157
|
+
*/
|
|
158
|
+
declare function slotChildRenameProp(fields: Record<string, unknown> | undefined): "name" | "altName" | null;
|
|
159
|
+
/**
|
|
160
|
+
* What a ROOT-level node is called in the trees — rung 1 of the same precedence
|
|
161
|
+
* above, and nothing below it.
|
|
162
|
+
*
|
|
163
|
+
* A root node is not a slot child: it has no linked collection, no card-local
|
|
164
|
+
* override and no catalog slug, so four of the five rungs have nothing to say
|
|
165
|
+
* about it. What it CAN carry is rung 1 — an explicit name the author (or the
|
|
166
|
+
* seeding) wrote — and before this function nothing at the root read it.
|
|
167
|
+
*
|
|
168
|
+
* ⚠️ THE DEFECT THAT PUT THIS HERE. `addSection` seeds a split pair as a Box
|
|
169
|
+
* carrying `name: "<Section> section"`, and the comment beside that line says
|
|
170
|
+
* the rename seam reads `name`. At the root both trees named a node by its TYPE
|
|
171
|
+
* alone, and a Box's type name at section level is the literal "Blank section" —
|
|
172
|
+
* so every pair a merchant added arrived in Layers as "Blank section", with the
|
|
173
|
+
* stored name read by nobody. A value written and never read is the same defect
|
|
174
|
+
* as a control that reaches nothing.
|
|
175
|
+
*
|
|
176
|
+
* It lives HERE, beside the rule it is a rung of, rather than in the chrome that
|
|
177
|
+
* calls it: two files deciding what a node is called is exactly what card 66194
|
|
178
|
+
* collapsed into this module, and a root rule written in the component would be
|
|
179
|
+
* the fourth copy.
|
|
180
|
+
*
|
|
181
|
+
* `fallback` is the caller's type-level label (`sectionLabel(type)`), which is
|
|
182
|
+
* what every published page reads today and what an unnamed node keeps reading.
|
|
183
|
+
*/
|
|
184
|
+
declare function rootRowName(node: SlotChild, fallback: string): string;
|
|
185
|
+
|
|
186
|
+
export { type SlotChild, rootRowName, slotChildName, slotChildRenameProp, slotChildRowName };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{rootRowName,slotChildName,slotChildRenameProp,slotChildRowName}from"../../../chunk-HWW4XJOH.js";import"../../../chunk-DUVRZ456.js";import"../../../chunk-6W7WLPZH.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{dedupeSlotChildren}from"../../../chunk-26OOWIJJ.js";
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A component type's own `defaultProps`, looked up in the Puck config.
|
|
3
|
+
*
|
|
4
|
+
* Handed IN rather than imported: `lib/puck/config` imports the seed
|
|
5
|
+
* registry's neighbours, and a seed registry that reached back into the config
|
|
6
|
+
* would close the loop. Both callers of `seeds()` already hold the config
|
|
7
|
+
* (`components/ScreenChrome`, `components/StandaloneSectionEditor`),
|
|
8
|
+
* so the lookup travels the short way.
|
|
9
|
+
*
|
|
10
|
+
* ⚠️ IT IS OPTIONAL, AND THE FIVE SPECS THAT PREDATE IT IGNORE IT. They
|
|
11
|
+
* seed ONE flat child whose every field is content, so a missing default changes
|
|
12
|
+
* nothing they draw. Image & Text Columns seeds a Box holding blocks, and a Box
|
|
13
|
+
* without its `direction` / `justify` / `align` / `wrap` is a different shape on
|
|
14
|
+
* the page — see `boxColumnSeed` in lib/puck/slot-specs.
|
|
15
|
+
*/
|
|
16
|
+
type NodeDefaults = (type: string) => Record<string, unknown>;
|
|
17
|
+
interface SlotSectionSpec {
|
|
18
|
+
/** The primary slot field on the section (e.g. Hero's `slides`). */
|
|
19
|
+
slot: string;
|
|
20
|
+
/** The child component type the slot holds. */
|
|
21
|
+
childType: string;
|
|
22
|
+
/** The "Add …" affordance label. */
|
|
23
|
+
addLabel: string;
|
|
24
|
+
/**
|
|
25
|
+
* The children ARE the section, and no surface offers to add one.
|
|
26
|
+
*
|
|
27
|
+
* ⚠️ NOT THE SAME THING AS `addBlocked`, AND THE DIFFERENCE IS WHY IT EXISTS.
|
|
28
|
+
* `addBlocked` is a reason adding is impossible RIGHT NOW — a hero anchor
|
|
29
|
+
* already holds four — so the row stays, greyed, with the sentence on it, and
|
|
30
|
+
* the merchant can act on it (re-place a group and Add comes back). A fixed
|
|
31
|
+
* set has no such state: the row would be permanently dead furniture, and
|
|
32
|
+
* `NodeContextMenu`'s own rule says it plainest — a row must never be a button
|
|
33
|
+
* that does nothing.
|
|
34
|
+
*
|
|
35
|
+
* Both surfaces that draw an Add row read this. `addBlocked` is still declared
|
|
36
|
+
* beside it, because the DROP path asks that one and never this.
|
|
37
|
+
*/
|
|
38
|
+
fixed?: boolean;
|
|
39
|
+
/** Children render as a HORIZONTAL slider (selection must advance it). */
|
|
40
|
+
slider?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Prop bags for the default children a fresh section is seeded with.
|
|
43
|
+
*
|
|
44
|
+
* `defaultsFor` is {@link NodeDefaults} — present when the caller holds the
|
|
45
|
+
* config, absent otherwise, and every spec that seeds a plain content child
|
|
46
|
+
* simply declines it.
|
|
47
|
+
*/
|
|
48
|
+
seeds: (defaultsFor?: NodeDefaults) => Record<string, unknown>[];
|
|
49
|
+
/**
|
|
50
|
+
* Convert a section's LEGACY props (an older inline-array field) into slot
|
|
51
|
+
* children at load-time — the chrome-only migration for pages saved before the
|
|
52
|
+
* field became a slot. Returns [] when there's nothing to migrate, in which
|
|
53
|
+
* case the seeder falls back to `seeds()`.
|
|
54
|
+
*/
|
|
55
|
+
legacy?: (props: Record<string, unknown>) => Record<string, unknown>[];
|
|
56
|
+
/**
|
|
57
|
+
* Why this section cannot take another child right now — a sentence the
|
|
58
|
+
* merchant reads — or `null` when it can (card 66189).
|
|
59
|
+
*
|
|
60
|
+
* Optional, and only the Hero slide answers it today: a group is placed on one
|
|
61
|
+
* of nine anchors, an anchor stacks at most four, and a fifth would be drawn
|
|
62
|
+
* ON TOP of the fourth. The rule lives on the SPEC rather than inside
|
|
63
|
+
* `SlotChildRows` because the list is shared by five sections and this is one
|
|
64
|
+
* section's arithmetic — the list asks, the spec answers.
|
|
65
|
+
*/
|
|
66
|
+
addBlocked?: (children: readonly unknown[], incoming?: unknown) => string | null;
|
|
67
|
+
/**
|
|
68
|
+
* Why this section must NOT be seeded at all, read off its OWN stored props.
|
|
69
|
+
*
|
|
70
|
+
* The seeder's existing guard is "the slot already has children" — right for a
|
|
71
|
+
* section whose only shape is the slot, and blind to a section that still
|
|
72
|
+
* carries an OLDER one. Image & Text Columns is the first of those: its
|
|
73
|
+
* columns used to be a `steps` ARRAY, the owner ruled on 2026-09-05 that
|
|
74
|
+
* nothing is migrated, and a stored page therefore has a full `steps` and an
|
|
75
|
+
* empty `boxes`. Without this the seeder would drop three fresh Boxes into a
|
|
76
|
+
* published page that already draws three columns, and the merchant would find
|
|
77
|
+
* six.
|
|
78
|
+
*
|
|
79
|
+
* Deliberately a question about the PARENT'S props, not about the slot — the
|
|
80
|
+
* slot is what the existing guard already reads, and answering "is there an
|
|
81
|
+
* older shape here" from the same place is what makes this a second question
|
|
82
|
+
* rather than a second opinion on the first.
|
|
83
|
+
*/
|
|
84
|
+
skipSeed?: (props: Record<string, unknown>) => boolean;
|
|
85
|
+
/**
|
|
86
|
+
* What the list says about the children it ALREADY holds, or `null`.
|
|
87
|
+
*
|
|
88
|
+
* The counterpart to `addBlocked`, and deliberately a second question rather
|
|
89
|
+
* than a second answer from the first: `addBlocked` is about a group that has
|
|
90
|
+
* not arrived yet, this is about the ones that are already here and cannot all
|
|
91
|
+
* be drawn. A section that cannot get into that state simply declares neither.
|
|
92
|
+
*/
|
|
93
|
+
notice?: (children: readonly unknown[]) => string | null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export type { NodeDefaults, SlotSectionSpec };
|
|
File without changes
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { StyleRow } from '../../../style-clipboard/index.js';
|
|
2
|
+
import { panelFieldsOf } from './panel-fields.js';
|
|
3
|
+
import '../../../types-Djdq6Xkd.js';
|
|
4
|
+
import 'react';
|
|
5
|
+
import '../../../words-CnnHb9jo.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* lib/puck/style-clipboard.ts — COPY STYLE / PASTE STYLE in the website editor
|
|
9
|
+
* (card [ADD] Copy Style And Paste Style, owner 2026-09-19).
|
|
10
|
+
*
|
|
11
|
+
* The clipboard, the matching rule, the menu rows, the words and the shortcut
|
|
12
|
+
* test are `efficient-easel/style-clipboard`'s — written once for both editors;
|
|
13
|
+
* the campaign designer draws the same two rows from the same module. This file
|
|
14
|
+
* answers only the two questions that are the website editor's own:
|
|
15
|
+
*
|
|
16
|
+
* 1. WHICH ROWS of a node are its look — {@link nodeStyleRows};
|
|
17
|
+
* 2. WHAT KIND each row is — {@link shopFieldKind}.
|
|
18
|
+
*
|
|
19
|
+
* ── WHICH ROWS ──────────────────────────────────────────────────────────────
|
|
20
|
+
* Owner's rule 3: the Style and Layout tabs, never Content. The panel after
|
|
21
|
+
* `assignSectionGroups` is a flat list in which each bucket header
|
|
22
|
+
* (`BUCKET_KEY`) opens its run — the same reading the tab strip hides rows by —
|
|
23
|
+
* so a row belongs to the header above it. Animation is not copied.
|
|
24
|
+
*
|
|
25
|
+
* Left out even on those tabs (the list GG approved on 2026-09-19):
|
|
26
|
+
* · every picture (`__media`) — Media folded into Style on 2026-09-14, and a
|
|
27
|
+
* picture is Content;
|
|
28
|
+
* · words and links (`__text`, `__link`);
|
|
29
|
+
* · headings, bucket headers and notes — `__fold`, and every `_`-key (the
|
|
30
|
+
* panel's own furniture, as in the campaign designer) — which store nothing;
|
|
31
|
+
* · the Anchor rows — a deep-link id must be unique on the page;
|
|
32
|
+
* · slots (Boxes, children) — structure, not a look;
|
|
33
|
+
* · a picture's focal point (`focal`, `imageFocal`) — a point ON ONE picture,
|
|
34
|
+
* meaningless on another, like the campaign logo's colour map.
|
|
35
|
+
* A text part's own look (`partStyles`) is no row at all, so it is never read.
|
|
36
|
+
*
|
|
37
|
+
* ── THE PHONE VALUE ─────────────────────────────────────────────────────────
|
|
38
|
+
* Stored as its own row (`<key>Phone`, ./phone-override), on the same tab, so it
|
|
39
|
+
* travels like any row. It is not COUNTED: the merchant sees one row per
|
|
40
|
+
* device, and the number is the rows they see.
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
type Props = Record<string, unknown>;
|
|
44
|
+
type NodeLike = {
|
|
45
|
+
type: string;
|
|
46
|
+
props: Props;
|
|
47
|
+
};
|
|
48
|
+
type ConfigLike = Parameters<typeof panelFieldsOf>[0];
|
|
49
|
+
/** The clipboard's scope: one site (GG, 2026-09-19) — across its pages. */
|
|
50
|
+
declare function siteStyleScope(siteId: string | null | undefined): string;
|
|
51
|
+
/**
|
|
52
|
+
* The kind of one website-editor row.
|
|
53
|
+
*
|
|
54
|
+
* · a tag (a shared builder's `section:<key>`, ../controls `sharedStyleKinds`)
|
|
55
|
+
* wins, on the gate or on the control it wraps;
|
|
56
|
+
* · a CHOICE row (it declares `options`) is `choice:` plus its sorted values;
|
|
57
|
+
* · anything else is the shell's reading, which answers `null` for an
|
|
58
|
+
* untagged custom control: it pastes only onto the same section type.
|
|
59
|
+
*/
|
|
60
|
+
declare function shopFieldKind(field: unknown): string | null;
|
|
61
|
+
/** A node's look, as rows the shell's clipboard can hold and match. */
|
|
62
|
+
declare function nodeStyleRows(config: ConfigLike, node: NodeLike): StyleRow[];
|
|
63
|
+
/** Copy one node's look into the site's clipboard. */
|
|
64
|
+
declare function copyNodeStyle(config: ConfigLike, scope: string, node: NodeLike, label: string): void;
|
|
65
|
+
/**
|
|
66
|
+
* What a paste onto this node would do: the new props, and the words the
|
|
67
|
+
* merchant reads. Null when nothing is held for this site. The caller writes
|
|
68
|
+
* `props` through its one replace op only when `changed`, and always shows
|
|
69
|
+
* `message` — "nothing matched" is an answer, not a silence.
|
|
70
|
+
*/
|
|
71
|
+
declare function planNodePaste(config: ConfigLike, scope: string, node: NodeLike, label: string): {
|
|
72
|
+
props: Props;
|
|
73
|
+
changed: boolean;
|
|
74
|
+
pasted: number;
|
|
75
|
+
message: string;
|
|
76
|
+
} | null;
|
|
77
|
+
|
|
78
|
+
export { copyNodeStyle, nodeStyleRows, planNodePaste, shopFieldKind, siteStyleScope };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{copyNodeStyle,nodeStyleRows,planNodePaste,shopFieldKind,siteStyleScope}from"../../../chunk-PP44LCJM.js";import"../../../chunk-PWZOS45R.js";import"../../../chunk-7F52SZOI.js";import"../../../chunk-R2HLPNQF.js";import"../../../chunk-ZE7I3PLX.js";import"../../../chunk-DUVRZ456.js";import"../../../chunk-BSPCSC45.js";import"../../../chunk-57DJOKXT.js";import"../../../chunk-6WY6ZXJG.js";import"../../../chunk-L5KW4HG5.js";
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* text-control-kinds — the authored-text control kinds, and the ONE fact about
|
|
3
|
+
* each that three separate lists used to hold by hand (card 66286).
|
|
4
|
+
*
|
|
5
|
+
* A LEAF ON PURPOSE: it imports nothing. `lib/puck/controls` is nine hops deep in
|
|
6
|
+
* a require cycle back to `lib/puck/part-text`
|
|
7
|
+
* (controls → MediaUploadField → ScreenDocumentContext →
|
|
8
|
+
* catalog-default-layout → ProductGridSection → goldPhrases → PartStyledText →
|
|
9
|
+
* part-styles → part-rows → part-text), so a list defined in `controls` and read
|
|
10
|
+
* at another module's INIT time throws "Cannot access before initialization".
|
|
11
|
+
* The cycle never bit before because the values `part-text` takes from `controls`
|
|
12
|
+
* — `TEXT_FIELD_MARKER`, `readHidable` — are only read inside functions. A
|
|
13
|
+
* single source has to be readable at init, so it lives here, on its own, where
|
|
14
|
+
* nothing can be in flight ahead of it.
|
|
15
|
+
*
|
|
16
|
+
* `lib/puck/controls` re-exports every name below, because that is where the rest
|
|
17
|
+
* of the text-field vocabulary lives (`TEXT_FIELD_MARKER`, `TextFieldMeta`, the
|
|
18
|
+
* builders) and every existing caller already reads it from there. The
|
|
19
|
+
* definitions are here and only here.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Every authored-text control kind, as recorded on `TEXT_FIELD_MARKER`
|
|
23
|
+
* (`lib/puck/controls`),
|
|
24
|
+
* and the one fact three separate lists used to hold by hand (card 66286):
|
|
25
|
+
* whether the kind's value is ONE string a merchant edits as a single box
|
|
26
|
+
* (`"scalar"`), or N of them a control adds, removes and reorders (`"list"`).
|
|
27
|
+
*
|
|
28
|
+
* ⚠️ THIS IS THE SOURCE. {@link TextControlKind} and {@link SCALAR_TEXT_CONTROLS}
|
|
29
|
+
* are both read off it, so a sixth kind cannot be added without answering the
|
|
30
|
+
* scalar/list question once, here, where the answer is. Until this card it was
|
|
31
|
+
* answered THREE times in three files, kept in step by a comment asking the next
|
|
32
|
+
* reader to remember: which parts get an entry row on the section screen
|
|
33
|
+
* (`ENTRY_CONTROLS`), which copy boxes move to the drill (`DRILL_TEXT_CONTROLS`),
|
|
34
|
+
* and which parts a caret may be opened in (`TYPE_IN_PLACE_KINDS`). All three
|
|
35
|
+
* were the same question and nothing went red when they disagreed — card 66282
|
|
36
|
+
* added `copyText` to one of them first and the drift surfaced afterwards as
|
|
37
|
+
* `1 unreachable: altName`.
|
|
38
|
+
*
|
|
39
|
+
* `control` also fixes the STORED VALUE SHAPE the neutralizer must preserve, so
|
|
40
|
+
* each kind names its own shape beside it.
|
|
41
|
+
*/
|
|
42
|
+
declare const TEXT_CONTROL_KINDS: {
|
|
43
|
+
readonly text: "scalar";
|
|
44
|
+
readonly textarea: "scalar";
|
|
45
|
+
readonly plainText: "scalar";
|
|
46
|
+
readonly copyText: "scalar";
|
|
47
|
+
readonly plainTextarea: "scalar";
|
|
48
|
+
readonly textList: "list";
|
|
49
|
+
};
|
|
50
|
+
/** The authored-text control kinds — the keys of {@link TEXT_CONTROL_KINDS}. */
|
|
51
|
+
type TextControlKind = keyof typeof TEXT_CONTROL_KINDS;
|
|
52
|
+
/** The kinds whose value is ONE string, as a type — so a caller may hold one of
|
|
53
|
+
* those and not the list kind, which the compiler then keeps it to. */
|
|
54
|
+
type ScalarTextControlKind = {
|
|
55
|
+
[K in TextControlKind]: (typeof TEXT_CONTROL_KINDS)[K] extends "scalar" ? K : never;
|
|
56
|
+
}[TextControlKind];
|
|
57
|
+
/**
|
|
58
|
+
* THE SCALAR CONTROLS, derived — one string each, so one box, so one row.
|
|
59
|
+
*
|
|
60
|
+
* The three lists this replaces all named exactly these and each stated the same
|
|
61
|
+
* reason for leaving `textList` out: its control manages ROW STRUCTURE (add,
|
|
62
|
+
* remove, reorder), which a per-row box cannot, so it keeps its place on the
|
|
63
|
+
* section screen. That reason is now the `"list"` beside it above, stated once.
|
|
64
|
+
*
|
|
65
|
+
* Order is declaration order, and the section screen's rows are built by walking
|
|
66
|
+
* a section's FIELDS rather than this list, so nothing merchant-facing reads it
|
|
67
|
+
* as an ordering.
|
|
68
|
+
*/
|
|
69
|
+
declare const SCALAR_TEXT_CONTROLS: readonly ScalarTextControlKind[];
|
|
70
|
+
|
|
71
|
+
export { SCALAR_TEXT_CONTROLS, type ScalarTextControlKind, TEXT_CONTROL_KINDS, type TextControlKind };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var a={text:"scalar",textarea:"scalar",plainText:"scalar",copyText:"scalar",plainTextarea:"scalar",textList:"list"},t=Object.entries(a).filter(([,a])=>"scalar"===a).map(([a])=>a);export{t as SCALAR_TEXT_CONTROLS,a as TEXT_CONTROL_KINDS};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/** Puck's index-based address, as `use-section-ops` spells it (zone omitted at root). */
|
|
2
|
+
type Selector = {
|
|
3
|
+
index: number;
|
|
4
|
+
zone?: string;
|
|
5
|
+
} | null;
|
|
6
|
+
/**
|
|
7
|
+
* Do these two addresses name the same node?
|
|
8
|
+
*
|
|
9
|
+
* `ops.select` omits the zone for a top-level node (Puck's reducer falls back to
|
|
10
|
+
* the root zone), while `getSelectorForId` always fills it in — so the two
|
|
11
|
+
* spellings of one top-level node differ, and the comparison has to normalise
|
|
12
|
+
* before it can answer. Exported for `scripts/test-tree-reveal.ts`.
|
|
13
|
+
*/
|
|
14
|
+
declare function sameSelector(a: Selector, b: Selector, rootZone: string): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Bring the selected Layers row into view. Returns whether a row was found —
|
|
17
|
+
* false whenever the panel is collapsed or on another view, which is a no-op and
|
|
18
|
+
* not a failure. A row that is already fully visible is found and left alone:
|
|
19
|
+
* the return says "there is a row", not "the panel moved".
|
|
20
|
+
*/
|
|
21
|
+
declare function revealSelectedTreeRow(doc?: Document | undefined): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Which node's Layers row is the MARKED one — the row that draws `is-selected`,
|
|
24
|
+
* and so the row {@link revealSelectedTreeRow} scrolls to.
|
|
25
|
+
*
|
|
26
|
+
* TWO SOURCES, ONE ANSWER. Normally it is the Puck selection. While a PART
|
|
27
|
+
* panel is open it is that part's OWNER, because `usePartBridge` deliberately
|
|
28
|
+
* leaves the Puck selection where it was — "the Layers tree, undo, redo and
|
|
29
|
+
* autosave therefore see nothing at all", which is that bridge's own cheapest
|
|
30
|
+
* proof that they still behave. The chrome asked `isPuckMode && selectedItem`
|
|
31
|
+
* instead, and `isPuckMode` is false in part mode, so opening a part put the
|
|
32
|
+
* mark out on EVERY row at once: a merchant who clicked a run of text in the
|
|
33
|
+
* canvas was left looking at a Layers list with nothing lit, which had also not
|
|
34
|
+
* moved (owner, 2026-09-09 — the "SHOP" tag on a Collections card). The bridge
|
|
35
|
+
* has returned `openPartId` for exactly this since card 66268 and no shell ever
|
|
36
|
+
* read it.
|
|
37
|
+
*
|
|
38
|
+
* EVERY OTHER OVERRIDE STILL ANSWERS `null` — Header, Website, Live chat and the
|
|
39
|
+
* ticker. Those panels are not about a node in this tree at all, and the rows
|
|
40
|
+
* that DO mark them (`inspectorMode.kind === "header"`, `tickerHeroId === secId`,
|
|
41
|
+
* …) read their own state, which is why widening this to them would light two
|
|
42
|
+
* rows for one panel.
|
|
43
|
+
*
|
|
44
|
+
* ⚠️ THE HERO'S `Text` / `Background` WERE ON THIS LIST AND ARE GONE
|
|
45
|
+
* ([ADD] The Hero Takes Boxes). They were two SYNTHETIC rows standing for the
|
|
46
|
+
* section's own copy and media; the owner put the background back in the hero's
|
|
47
|
+
* settings on 2026-09-09 and deleted the built-in copy, so both panels and both
|
|
48
|
+
* `…SectionId` derivations went with them. The example above named
|
|
49
|
+
* `heroTextSectionId`, a variable that no longer exists — corrected to the ticker
|
|
50
|
+
* rather than dropped, because the RULE it illustrates is unchanged and this is
|
|
51
|
+
* the only place that states it.
|
|
52
|
+
*
|
|
53
|
+
* The mode is taken structurally rather than as `InspectorMode`: that union
|
|
54
|
+
* lives in a component (SectionEditor) and this is `lib`, so a named import
|
|
55
|
+
* here would point the dependency the wrong way for one field.
|
|
56
|
+
*/
|
|
57
|
+
declare function markedTreeNodeId(mode: {
|
|
58
|
+
kind: string;
|
|
59
|
+
nodeId?: string;
|
|
60
|
+
}, selectedId: string | null | undefined): string | null;
|
|
61
|
+
|
|
62
|
+
export { markedTreeNodeId, revealSelectedTreeRow, sameSelector };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{markedTreeNodeId,revealSelectedTreeRow,sameSelector}from"../../../chunk-FGNR22NY.js";
|