efficient-easel 0.0.0 → 0.96.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/LICENSE +10 -0
- package/README.md +723 -4
- package/dist/autosave/index.d.ts +101 -0
- package/dist/autosave/index.js +1 -0
- package/dist/blocks/index.d.ts +295 -0
- package/dist/blocks/index.js +0 -0
- package/dist/buckets-1vRlQceY.d.ts +13 -0
- package/dist/canvas/index.d.ts +194 -0
- package/dist/canvas/index.js +1 -0
- package/dist/chrome/chrome.css +570 -0
- package/dist/chrome/index.d.ts +219 -0
- package/dist/chrome/index.js +21 -0
- package/dist/chunk-2LUSK32B.js +1 -0
- package/dist/chunk-2OAZYSWJ.js +1 -0
- package/dist/chunk-67VZRQLG.js +13 -0
- package/dist/chunk-6JDII7N3.js +1 -0
- package/dist/chunk-6OPSJGAI.js +1 -0
- package/dist/chunk-6WY6ZXJG.js +1 -0
- package/dist/chunk-7A7O2JWQ.js +1 -0
- package/dist/chunk-BZ5ASXOL.js +1 -0
- package/dist/chunk-CERTFXCV.js +13 -0
- package/dist/chunk-EFTTSIMK.js +1 -0
- package/dist/chunk-FI23ALVJ.js +1 -0
- package/dist/chunk-FJE4IDBQ.js +1 -0
- package/dist/chunk-GGTPNGFJ.js +1 -0
- package/dist/chunk-H4B72XCJ.js +1 -0
- package/dist/chunk-H6DDIBQ4.js +1 -0
- package/dist/chunk-KDIVA6WD.js +1 -0
- package/dist/chunk-LPRQDDQO.js +1 -0
- package/dist/chunk-MCLBHENY.js +1 -0
- package/dist/chunk-MFIRYGHW.js +1 -0
- package/dist/chunk-NKB3KVAB.js +1 -0
- package/dist/chunk-O2NLQBFX.js +1 -0
- package/dist/chunk-OGZFDJ6G.js +1 -0
- package/dist/chunk-OWBO4WKA.js +0 -0
- package/dist/chunk-QB3BZIRA.js +5 -0
- package/dist/chunk-RE4LP46F.js +1 -0
- package/dist/chunk-STFMZJKU.js +14 -0
- package/dist/chunk-SUO5627P.js +1 -0
- package/dist/chunk-TDA4HH54.js +1 -0
- package/dist/chunk-WK3AFPXY.js +1 -0
- package/dist/chunk-YIMRTIBN.js +3 -0
- package/dist/chunk-YNZZYHA4.js +450 -0
- package/dist/chunk-ZAOM6PFH.js +1 -0
- package/dist/chunk-ZNCEOSXO.js +1 -0
- package/dist/copy/copy.css +282 -0
- package/dist/copy/index.d.ts +336 -0
- package/dist/copy/index.js +10 -0
- package/dist/data/index.d.ts +208 -0
- package/dist/data/index.js +1 -0
- package/dist/drag/drag.css +360 -0
- package/dist/drag/index.d.ts +379 -0
- package/dist/drag/index.js +18 -0
- package/dist/edit-lock/index.d.ts +354 -0
- package/dist/edit-lock/index.js +1 -0
- package/dist/editor/editor.css +58 -0
- package/dist/editor/index.d.ts +361 -0
- package/dist/editor/index.js +9 -0
- package/dist/fields/fields.css +207 -0
- package/dist/fields/index.d.ts +273 -0
- package/dist/fields/index.js +46 -0
- package/dist/gold/gold.css +196 -0
- package/dist/gold/index.d.ts +280 -0
- package/dist/gold/index.js +1 -0
- package/dist/icons/index.d.ts +474 -0
- package/dist/icons/index.js +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +1 -0
- package/dist/markup/index.d.ts +452 -0
- package/dist/markup/index.js +1 -0
- package/dist/menu/index.d.ts +49 -0
- package/dist/menu/index.js +15 -0
- package/dist/menu/menu.css +254 -0
- package/dist/node-ops/index.d.ts +91 -0
- package/dist/node-ops/index.js +1 -0
- package/dist/panel/index.d.ts +1088 -0
- package/dist/panel/index.js +16 -0
- package/dist/panel/panel.css +1460 -0
- package/dist/pick/index.d.ts +153 -0
- package/dist/pick/index.js +14 -0
- package/dist/pick/pick.css +235 -0
- package/dist/plan-DtNw2VuI.d.ts +88 -0
- package/dist/rail/index.d.ts +145 -0
- package/dist/rail/index.js +1 -0
- package/dist/rail/rail.css +175 -0
- package/dist/render/index.d.ts +117 -0
- package/dist/render/index.js +5 -0
- package/dist/resolve-DpH8YQOA.d.ts +57 -0
- package/dist/shell/index.d.ts +159 -0
- package/dist/shell/index.js +1 -0
- package/dist/shell/shell.css +122 -0
- package/dist/strings/catalogue.d.ts +141 -0
- package/dist/strings/catalogue.js +1 -0
- package/dist/strings/index.d.ts +56 -0
- package/dist/strings/index.js +2 -0
- package/dist/style-clipboard/index.d.ts +184 -0
- package/dist/style-clipboard/index.js +1 -0
- package/dist/tree/index.d.ts +173 -0
- package/dist/tree/index.js +1 -0
- package/dist/tree/tree.css +618 -0
- package/dist/types-CEqUFH2j.d.ts +129 -0
- package/dist/types-CuNiSnX6.d.ts +204 -0
- package/dist/types-DNrn_w4V.d.ts +88 -0
- package/dist/types-DziKCwsN.d.ts +105 -0
- package/dist/types-_Vayx8ov.d.ts +153 -0
- package/dist/types-pGBXevBU.d.ts +131 -0
- package/dist/useNodeOps-6IAej9jy.d.ts +68 -0
- package/dist/watch-DmasQA61.d.ts +60 -0
- package/dist/wordFit-9B9nqyf3.d.ts +35 -0
- package/dist/words-B2YLaKEr.d.ts +30 -0
- package/dist/words-B87GIFWH.d.ts +86 -0
- package/dist/words-BK-npta-.d.ts +27 -0
- package/dist/words-CD3WADyb.d.ts +51 -0
- package/dist/words-CsRWXkY4.d.ts +129 -0
- package/dist/words-D9ChvbNC.d.ts +52 -0
- package/dist/words-DOhF-4D4.d.ts +35 -0
- package/dist/words-DagJdwIA.d.ts +78 -0
- package/dist/words-DfxEp_RH.d.ts +142 -0
- package/package.json +202 -3
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* efficient-easel — rail styles.
|
|
3
|
+
*
|
|
4
|
+
* The values here mirror `railTokens` in tokens.ts one-for-one (both trace back
|
|
5
|
+
* to the storefront editor's `.sf-rail` rules — the visual reference). They are
|
|
6
|
+
* declared as custom properties ON `.es-rail`, not on `:root`, so importing this
|
|
7
|
+
* stylesheet themes ONLY the rail and never leaks variables into the host page.
|
|
8
|
+
* Re-theme by overriding any `--es-rail-*` var on or above the rail element.
|
|
9
|
+
*
|
|
10
|
+
* Import once from a client entry / global stylesheet:
|
|
11
|
+
* import 'efficient-easel/rail.css';
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
.es-rail {
|
|
15
|
+
/* — tokens (see tokens.ts / railCssVars) — */
|
|
16
|
+
--es-rail-w: 46px;
|
|
17
|
+
--es-rail-pad-y: 8px;
|
|
18
|
+
--es-rail-gap: 4px;
|
|
19
|
+
--es-rail-radius: 12px;
|
|
20
|
+
--es-rail-btn-size: 34px;
|
|
21
|
+
--es-rail-btn-radius: 9px;
|
|
22
|
+
--es-rail-icon-size: 18px;
|
|
23
|
+
--es-rail-word-pad-x: 8px;
|
|
24
|
+
--es-rail-word-gap: 6px;
|
|
25
|
+
--es-rail-word-size: 12px;
|
|
26
|
+
--es-rail-word-weight: 500;
|
|
27
|
+
--es-rail-bg: #ffffff;
|
|
28
|
+
--es-rail-shadow: 0 1px 2px rgba(0, 0, 0, 0.05), 0 10px 30px rgba(0, 0, 0, 0.06);
|
|
29
|
+
--es-rail-fg: #6b7280;
|
|
30
|
+
--es-rail-hover-bg: #f3f4f6;
|
|
31
|
+
--es-rail-hover-fg: #111827;
|
|
32
|
+
--es-rail-accent: #2563eb;
|
|
33
|
+
--es-rail-accent-tint: #eff6ff;
|
|
34
|
+
|
|
35
|
+
flex: none;
|
|
36
|
+
width: var(--es-rail-w);
|
|
37
|
+
display: flex;
|
|
38
|
+
flex-direction: column;
|
|
39
|
+
align-items: center;
|
|
40
|
+
gap: var(--es-rail-gap);
|
|
41
|
+
padding: var(--es-rail-pad-y) 0;
|
|
42
|
+
background: var(--es-rail-bg);
|
|
43
|
+
border-radius: var(--es-rail-radius);
|
|
44
|
+
box-shadow: var(--es-rail-shadow);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/*
|
|
48
|
+
* The ROW variant (card 66160) — the same rail laid into a top bar.
|
|
49
|
+
*
|
|
50
|
+
* The column costs a 1280px laptop 56px of website preview (a 46px rail plus
|
|
51
|
+
* the 10px panel gap) that the top bar has going spare, so the icons move up
|
|
52
|
+
* there. `.es-rail` above is UNTOUCHED: this rule only overrides, so a consumer
|
|
53
|
+
* who never passes `orientation` gets exactly the stylesheet they had.
|
|
54
|
+
*
|
|
55
|
+
* THE CARD LOOK GOES, THROUGH THE TOKENS THAT ALREADY EXIST. The bar has its
|
|
56
|
+
* own surface and shadow; a second white card floating inside it is the bug.
|
|
57
|
+
* These re-point the THREE custom properties the base rule already reads rather
|
|
58
|
+
* than re-stating `background` / `box-shadow` / `border-radius` here — so the
|
|
59
|
+
* card look stays declared in exactly one place, and a host re-theming the rail
|
|
60
|
+
* still only has the `--es-rail-*` names to learn.
|
|
61
|
+
*
|
|
62
|
+
* WHAT DELIBERATELY DOES NOT CHANGE: the button size, the button radius, the
|
|
63
|
+
* icon size, the gap and every colour. The icons must not resize when they move
|
|
64
|
+
* into the bar, so no `--es-rail-btn-*`, `--es-rail-icon-size` or colour token
|
|
65
|
+
* appears below, and there is no `.es-rail-row .es-rail-btn` rule anywhere.
|
|
66
|
+
* `align-items: center` is inherited from the base rule and does the right
|
|
67
|
+
* thing here too — in a row it centres the buttons vertically.
|
|
68
|
+
*/
|
|
69
|
+
.es-rail.es-rail-row {
|
|
70
|
+
--es-rail-bg: transparent;
|
|
71
|
+
--es-rail-shadow: none;
|
|
72
|
+
--es-rail-radius: 0;
|
|
73
|
+
|
|
74
|
+
flex-direction: row;
|
|
75
|
+
/* No fixed width: the row is as wide as its buttons. `flex: none` from the
|
|
76
|
+
base rule keeps flex-basis on `auto`, so this sizes to content. */
|
|
77
|
+
width: auto;
|
|
78
|
+
/* The column pads `--es-rail-pad-y 0`: the one step goes on the MAIN axis —
|
|
79
|
+
the run of buttons — and the cross axis is handled by the fixed width.
|
|
80
|
+
Rotate the axes and the same step goes on the ENDS of the row. The cross
|
|
81
|
+
axis is 0 on purpose, so the row is exactly one button tall (34px) and the
|
|
82
|
+
52px bar centres it, instead of the rail imposing a height on the bar. */
|
|
83
|
+
padding: 0 var(--es-rail-pad-y);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.es-rail-btn {
|
|
87
|
+
width: var(--es-rail-btn-size);
|
|
88
|
+
height: var(--es-rail-btn-size);
|
|
89
|
+
border: none;
|
|
90
|
+
background: transparent;
|
|
91
|
+
border-radius: var(--es-rail-btn-radius);
|
|
92
|
+
color: var(--es-rail-fg);
|
|
93
|
+
display: flex;
|
|
94
|
+
align-items: center;
|
|
95
|
+
justify-content: center;
|
|
96
|
+
cursor: pointer;
|
|
97
|
+
transition: background 0.12s, color 0.12s;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.es-rail-btn svg {
|
|
101
|
+
width: var(--es-rail-icon-size);
|
|
102
|
+
height: var(--es-rail-icon-size);
|
|
103
|
+
display: block;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.es-rail-btn:hover:not(:disabled) {
|
|
107
|
+
background: var(--es-rail-hover-bg);
|
|
108
|
+
color: var(--es-rail-hover-fg);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.es-rail-btn.is-active {
|
|
112
|
+
background: var(--es-rail-accent-tint);
|
|
113
|
+
color: var(--es-rail-accent);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.es-rail-btn:disabled {
|
|
117
|
+
opacity: 0.35;
|
|
118
|
+
cursor: default;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/* ── Words beside the icons (a row rail only) ────────────────────────────────
|
|
122
|
+
THE SETTINGS TABS' RULE (owner, 2026-09-18: "the rule must be the same as the
|
|
123
|
+
top tabs of the right settings panel"). Three states, picked by the width of
|
|
124
|
+
the rail's column and nothing else:
|
|
125
|
+
|
|
126
|
+
every word when every button fits with its word;
|
|
127
|
+
chosen word otherwise the glyphs, plus the word of the button whose
|
|
128
|
+
panel is open;
|
|
129
|
+
glyphs only when even that does not fit.
|
|
130
|
+
|
|
131
|
+
BOTH parts are always in the markup once the words are measured; the widths
|
|
132
|
+
decide which are drawn, in CSS, against the column's own width (`100cqi`) —
|
|
133
|
+
the tab strip's way, not a script's. The thresholds come from ONE rule, the
|
|
134
|
+
"word fit" block in `panel.css`, which the segmented control reads too. This
|
|
135
|
+
sheet only names the rail's chrome for it — the four inputs below — so a
|
|
136
|
+
re-padded rail button moves its thresholds with it.
|
|
137
|
+
|
|
138
|
+
`is-measured` is set by `EditorRail` when it was handed the words' widths
|
|
139
|
+
(`TopBarRail` measures them). Without it, and without `panel.css`, the word
|
|
140
|
+
stays clipped to nothing: an icon-only rail always fits. */
|
|
141
|
+
.es-rail.es-rail-row.is-measured {
|
|
142
|
+
--es-fit-chip: var(--es-rail-btn-size);
|
|
143
|
+
--es-fit-word-gap: var(--es-rail-word-gap);
|
|
144
|
+
--es-fit-gap: var(--es-rail-gap);
|
|
145
|
+
--es-fit-ends: var(--es-rail-pad-y);
|
|
146
|
+
}
|
|
147
|
+
/* The button keeps its 34px height, its radius and its idle / hover / active
|
|
148
|
+
colours; only its width follows the word. Wordless it is 34px wide exactly
|
|
149
|
+
as before — the padding plus the 18px glyph is 34. The icon-to-word gap is
|
|
150
|
+
the WORD's margin (see `panel.css`), so the button's own `gap` stays 0 and
|
|
151
|
+
goes with the word.
|
|
152
|
+
|
|
153
|
+
`min-width: 0` KEEPS THE ICON-ONLY RAIL'S GIVE. Six glyph buttons need 240px
|
|
154
|
+
and the 220px panel floor gives the column 219: the icon-only rail has
|
|
155
|
+
always shrunk its buttons a few px there rather than run past the column,
|
|
156
|
+
and padding would otherwise make the button's own content its floor.
|
|
157
|
+
The glyph keeps its square instead (the rule after), which is also what
|
|
158
|
+
holds a narrower glyph — the shop's text "+" — to a 34px button. */
|
|
159
|
+
.es-rail.es-rail-row.is-measured .es-rail-btn {
|
|
160
|
+
width: auto;
|
|
161
|
+
min-width: 0;
|
|
162
|
+
padding: 0 var(--es-rail-word-pad-x);
|
|
163
|
+
}
|
|
164
|
+
.es-rail.es-rail-row.is-measured .es-rail-btn > :first-child {
|
|
165
|
+
min-width: var(--es-rail-icon-size);
|
|
166
|
+
text-align: center;
|
|
167
|
+
}
|
|
168
|
+
.es-rail-word {
|
|
169
|
+
font-size: var(--es-rail-word-size);
|
|
170
|
+
font-weight: var(--es-rail-word-weight);
|
|
171
|
+
line-height: 1;
|
|
172
|
+
white-space: nowrap;
|
|
173
|
+
overflow: hidden;
|
|
174
|
+
max-width: 0;
|
|
175
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { CSSProperties, ReactNode, ReactElement } from 'react';
|
|
2
|
+
import { B as BlockShape, D as Data } from '../types-DziKCwsN.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* efficient-easel/render — draw a saved document, the published way.
|
|
6
|
+
*
|
|
7
|
+
* Step 1.2 of the engine that replaces Puck (blueprint "Puck From The Ground
|
|
8
|
+
* Up For Efficient Editor", 2026-09-29). The published storefront draws every
|
|
9
|
+
* page through Puck's `<Render>` today (efficient-shop `lib/puck/render-client.tsx`
|
|
10
|
+
* and `components/PublishedFooter.tsx`); this is the drop-in for it: the same
|
|
11
|
+
* config, the same document, THE SAME HTML — `tests/render-puck-parity.test.tsx`
|
|
12
|
+
* renders both and compares the markup byte for byte.
|
|
13
|
+
*
|
|
14
|
+
* WHAT IS DIFFERENT IS WHAT IT IS MADE OF. Puck's `<Render>` reaches the
|
|
15
|
+
* document through a React context and builds each block's props in hooks, so
|
|
16
|
+
* it can only run as a client component. This is a plain function: no hook, no
|
|
17
|
+
* context, no state, no browser global. It runs in a server component, in a
|
|
18
|
+
* client component, in a Node script, or called directly — `Render(props)`
|
|
19
|
+
* returns the element tree. Whether the BLOCKS can run on the server is up to
|
|
20
|
+
* the blocks (the storefront's are client components today; blueprint default
|
|
21
|
+
* #4 keeps that wrapper until they are moved one by one).
|
|
22
|
+
*
|
|
23
|
+
* THE BLOCK AUTHORING SHAPE IS PUCK'S (blueprint default #3), so an app hands
|
|
24
|
+
* in the config it has:
|
|
25
|
+
*
|
|
26
|
+
* - a block's `render` receives its props, plus `puck`, plus each SLOT as a
|
|
27
|
+
* component: `render: ({ content: Content }) => <Content className="…" />`.
|
|
28
|
+
* A slot draws `<div className style>` around its blocks, as Puck's does;
|
|
29
|
+
* - the root's `render` receives the root props, `puck`, `title` (`''` when
|
|
30
|
+
* unset), `editMode: false`, `id: 'puck-root'`, and the page as `children`;
|
|
31
|
+
* - a block type the config does not know draws nothing.
|
|
32
|
+
*
|
|
33
|
+
* Three details are copied exactly because a block can observe them, not
|
|
34
|
+
* because they are good design:
|
|
35
|
+
*
|
|
36
|
+
* 1. The top-level list is wrapped in one plain `<div>`, root render or not.
|
|
37
|
+
* (Puck's own SERVER `<Render>` uses a fragment there instead, so Puck's
|
|
38
|
+
* two renderers disagree; the client one is what is published.) A host
|
|
39
|
+
* that needs to reach that wrapper from its stylesheet passes `className`
|
|
40
|
+
* (0.95.0); left out, the `<div>` is as bare as Puck's.
|
|
41
|
+
* 2. `puck` differs by level. The root gets
|
|
42
|
+
* `{ renderDropZone, isEditing: false, dragRef: null, metadata }`; a
|
|
43
|
+
* top-level block gets `{ renderDropZone, metadata: { ...metadata,
|
|
44
|
+
* ...block.metadata } }`; a block inside a slot gets `{ metadata }` only.
|
|
45
|
+
* 3. A missing top-level slot draws as an empty slot; a slot is found by its
|
|
46
|
+
* field, including inside `object` and `array` fields.
|
|
47
|
+
*
|
|
48
|
+
* `renderDropZone` draws a legacy `zones` entry. Neither editor writes zones,
|
|
49
|
+
* so it draws an empty `<div>` in practice; it exists so a block that still
|
|
50
|
+
* calls it gets what Puck gave it.
|
|
51
|
+
*
|
|
52
|
+
* LEAF DISCIPLINE: imports React's JSX runtime and this package's own data
|
|
53
|
+
* layer, nothing else (`tests/render-leaf-safety.test.ts`).
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
type Metadata = Record<string, unknown>;
|
|
57
|
+
/** What a slot component accepts. Only `className` and `style` draw anything. */
|
|
58
|
+
interface SlotProps {
|
|
59
|
+
className?: string;
|
|
60
|
+
style?: CSSProperties;
|
|
61
|
+
allow?: string[];
|
|
62
|
+
disallow?: string[];
|
|
63
|
+
minEmptyHeight?: number;
|
|
64
|
+
collisionAxis?: unknown;
|
|
65
|
+
}
|
|
66
|
+
/** A slot, as a block's `render` receives it. */
|
|
67
|
+
type SlotComponent = (props?: SlotProps) => ReactElement;
|
|
68
|
+
interface DropZoneProps extends SlotProps {
|
|
69
|
+
zone: string;
|
|
70
|
+
}
|
|
71
|
+
/** The `puck` prop. Which keys are present depends on the level (see above). */
|
|
72
|
+
interface RenderContext {
|
|
73
|
+
renderDropZone?: (props: DropZoneProps) => ReactElement;
|
|
74
|
+
isEditing?: boolean;
|
|
75
|
+
dragRef?: null;
|
|
76
|
+
metadata: Metadata;
|
|
77
|
+
}
|
|
78
|
+
type BlockRender = (props: any) => ReactNode;
|
|
79
|
+
interface RenderBlock extends BlockShape {
|
|
80
|
+
render: BlockRender;
|
|
81
|
+
metadata?: Metadata;
|
|
82
|
+
}
|
|
83
|
+
interface RenderConfig {
|
|
84
|
+
root?: BlockShape & {
|
|
85
|
+
render?: BlockRender;
|
|
86
|
+
};
|
|
87
|
+
components: Record<string, RenderBlock | undefined>;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* What `Render` draws: a saved document, as loosely as the renderer reads it.
|
|
91
|
+
* `root.props` is OPTIONAL here, as it is in Puck's own `Data` type — a root
|
|
92
|
+
* that holds its props directly (the older format) is drawn the way Puck draws
|
|
93
|
+
* it, and a document with no root or no content draws an empty page. So a
|
|
94
|
+
* Puck-typed document is passed as it is, with no cast.
|
|
95
|
+
*/
|
|
96
|
+
interface RenderData {
|
|
97
|
+
root?: {
|
|
98
|
+
props?: Record<string, unknown>;
|
|
99
|
+
[key: string]: unknown;
|
|
100
|
+
};
|
|
101
|
+
content?: unknown[];
|
|
102
|
+
zones?: Record<string, unknown[]>;
|
|
103
|
+
}
|
|
104
|
+
interface RenderProps {
|
|
105
|
+
config: RenderConfig;
|
|
106
|
+
data: RenderData | Partial<Data>;
|
|
107
|
+
metadata?: Metadata;
|
|
108
|
+
/**
|
|
109
|
+
* A class for the `<div>` around the top-level list — that wrapper, and
|
|
110
|
+
* nothing else. OPT-IN: left out (or empty) the wrapper carries no attribute
|
|
111
|
+
* at all, and the markup is Puck's, byte for byte.
|
|
112
|
+
*/
|
|
113
|
+
className?: string;
|
|
114
|
+
}
|
|
115
|
+
declare function Render({ config, data, metadata, className }: RenderProps): ReactElement;
|
|
116
|
+
|
|
117
|
+
export { type DropZoneProps, type Metadata, Render, type RenderBlock, type RenderConfig, type RenderContext, type RenderData, type RenderProps, type SlotComponent, type SlotProps };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{isRecord as t,fieldsFrom as n,slotLocations as e,setIn as r,isNode as o}from"../chunk-NKB3KVAB.js";import{jsx as a}from"react/jsx-runtime";function c({config:e,data:r,metadata:o={},className:c}){const s=Array.isArray(r?.content)?r.content:[],l=t(r?.root)?r.root:{},p="props"in l?l.props:l,m={config:e,content:s,zones:t(r?.zones)?r.zones:{},metadata:o},f={...p,puck:{renderDropZone:d(m,"root"),isEditing:!1,dragRef:null,metadata:o},title:p?.title||"",editMode:!1,id:"puck-root"},y=i(m,n(e.root),f),g=s.map(t=>u(m,t)),k=/* @__PURE__ */a("div",c?{className:c,children:g}:{children:g}),N=e.root?.render;return N?/* @__PURE__ */a(N,{...y,children:k}):k}function i(t,n,o){let a=o;for(const c of e(o,n))a=r(a,c.segments,s(t,c.content));return a}function s(t,e){return function(r={}){/* @__PURE__ */
|
|
2
|
+
return a("div",{className:r.className,style:r.style,children:e.map(e=>function(t,e){if(!o(e))return null;const r=t.config.components[e.type];if(!r)return null;const c=i(t,n(r),e.props),s=r.render,u={...c.puck,metadata:t.metadata||{}};/* @__PURE__ */
|
|
3
|
+
return a(s,{...c,puck:u},c.id)}(t,e))})}}function u(t,e){if(!o(e))return null;const r=t.config.components[e.type];if(!r)return null;const c=i(t,n(r),e.props),s=r.render,u={...c.puck,renderDropZone:d(t,c.id),metadata:{...t.metadata,...r.metadata}};/* @__PURE__ */
|
|
4
|
+
return a(s,{...c,puck:u},c.id)}function d(t,n){return function({zone:e,className:r,style:o}){const c=`${n}:${e}`,i="root:default-zone"===c?t.content:t.zones[c],s=Array.isArray(i)?i:[];/* @__PURE__ */
|
|
5
|
+
return a("div",{className:r,style:o,children:s.map(n=>u(t,n))})}}export{c as Render};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { a as DataConfig } from './types-DziKCwsN.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A BLOCK'S `resolveData`, RUN AS PUCK RUNS IT — `resolveComponentData` in Puck
|
|
5
|
+
* 0.20 (`lib/resolve-component-data.ts`), because the documents both editors
|
|
6
|
+
* hold were resolved by it and must go on resolving the same way.
|
|
7
|
+
*
|
|
8
|
+
* - It runs only when the item differs from the last one resolved for that id
|
|
9
|
+
* (deep-equal), unless the trigger is "force"; the last answer is reused.
|
|
10
|
+
* - `changed` names every prop of the new item with whether it differs from
|
|
11
|
+
* the last one resolved (`changedProps`, Puck's `getChanged`).
|
|
12
|
+
* - The block's own `metadata` is spread over the host's.
|
|
13
|
+
* - The answer's `props` are spread OVER the item's, and its `readOnly` kept
|
|
14
|
+
* when it has any key.
|
|
15
|
+
* - Then every slot's children are resolved the same way, in order.
|
|
16
|
+
*
|
|
17
|
+
* What differs from Puck is only where the memory lives: Puck kept the last
|
|
18
|
+
* change per id in a module-level object shared by every editor on the page;
|
|
19
|
+
* here the host hands in its own (`createResolveCache`), one per editor.
|
|
20
|
+
*
|
|
21
|
+
* Pure apart from the resolvers it calls: no React, no browser global.
|
|
22
|
+
*/
|
|
23
|
+
type ResolveTrigger = 'insert' | 'replace' | 'load' | 'force' | 'move';
|
|
24
|
+
/** An item to resolve: a node, or the root (`{ props }`, no type). */
|
|
25
|
+
interface ResolvableItem {
|
|
26
|
+
type?: string;
|
|
27
|
+
props: Record<string, unknown>;
|
|
28
|
+
readOnly?: Record<string, boolean>;
|
|
29
|
+
}
|
|
30
|
+
interface ResolveCache {
|
|
31
|
+
lastChange: Record<string, {
|
|
32
|
+
item: ResolvableItem;
|
|
33
|
+
resolved: ResolvableItem;
|
|
34
|
+
}>;
|
|
35
|
+
}
|
|
36
|
+
declare const createResolveCache: () => ResolveCache;
|
|
37
|
+
interface ResolveOptions {
|
|
38
|
+
metadata?: Record<string, unknown>;
|
|
39
|
+
trigger?: ResolveTrigger;
|
|
40
|
+
cache?: ResolveCache;
|
|
41
|
+
onResolveStart?: (item: ResolvableItem) => void;
|
|
42
|
+
onResolveEnd?: (item: ResolvableItem) => void;
|
|
43
|
+
}
|
|
44
|
+
/** Deep equality of JSON-shaped values, as `fast-deep-equal` answers it for them. */
|
|
45
|
+
declare function deepEqual(a: unknown, b: unknown): boolean;
|
|
46
|
+
/** Every prop of `next`, and whether it differs from `last` (Puck's `getChanged`). */
|
|
47
|
+
declare function changedProps(next: ResolvableItem | null | undefined, last: ResolvableItem | null | undefined): Record<string, boolean>;
|
|
48
|
+
/**
|
|
49
|
+
* Resolve one item and everything in its slots. `didChange` says whether the
|
|
50
|
+
* answer differs from the item handed in.
|
|
51
|
+
*/
|
|
52
|
+
declare function resolveNodeData<T extends ResolvableItem>(item: T, config: DataConfig, options?: ResolveOptions): Promise<{
|
|
53
|
+
node: T;
|
|
54
|
+
didChange: boolean;
|
|
55
|
+
}>;
|
|
56
|
+
|
|
57
|
+
export { type ResolvableItem as R, type ResolveCache as a, type ResolveOptions as b, type ResolveTrigger as c, changedProps as d, createResolveCache as e, deepEqual as f, resolveNodeData as r };
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Editor SHELL design tokens — the ONE source both editors' chrome converge on.
|
|
3
|
+
*
|
|
4
|
+
* Where `rail/tokens.ts` owns the slim icon-rail, this owns the rest of the
|
|
5
|
+
* editor chrome theme: accent, surfaces, fields, text, lines, chips, named
|
|
6
|
+
* chrome literals, danger/warning/success, radii, gap, shadows and font. Every
|
|
7
|
+
* value bar one is taken verbatim from the storefront editor's `--sf-*` block
|
|
8
|
+
* (`efficient-shop/components/storefront-editor.css`), the visual reference the
|
|
9
|
+
* campaign designer (`--cd-*`) and the storefront's own TS mirror (`tk`) had
|
|
10
|
+
* each re-copied. After card 66024 they all resolve to these values instead.
|
|
11
|
+
* The one exception is `success`, which that block has no counterpart for; see
|
|
12
|
+
* its own note below.
|
|
13
|
+
*
|
|
14
|
+
* Exposed BOTH ways, per the same value (mirrors the rail):
|
|
15
|
+
* - `shellTokens` — this JS object, for code that needs the numbers/colours
|
|
16
|
+
* (e.g. the storefront's `floating-editor/tokens.ts` inline-style mirror);
|
|
17
|
+
* - `shell.css` — the stylesheet, which declares the identical values as CSS
|
|
18
|
+
* custom properties on `.es-editor` (names listed in `shellCssVars`).
|
|
19
|
+
*
|
|
20
|
+
* Numeric fields are pixel magnitudes (unitless) so they compose in code; the
|
|
21
|
+
* CSS applies the `px`. Both editing surfaces are LIGHT only (no dark mode), so
|
|
22
|
+
* there is a single palette here — no dark counterpart.
|
|
23
|
+
*/
|
|
24
|
+
declare const shellTokens: {
|
|
25
|
+
/** `--es-accent` — blue-600. */
|
|
26
|
+
readonly accent: "#2563eb";
|
|
27
|
+
/** `--es-accent-tint` — blue-50. */
|
|
28
|
+
readonly accentTint: "#eff6ff";
|
|
29
|
+
/** `--es-accent-tint-strong` — blue-100. */
|
|
30
|
+
readonly accentTintStrong: "#dbeafe";
|
|
31
|
+
/** `--es-accent-line` — blue-200: a quiet accent hairline (an empty slot's outline). */
|
|
32
|
+
readonly accentLine: "#bfdbfe";
|
|
33
|
+
/** `--es-accent-text` — blue-700. */
|
|
34
|
+
readonly accentText: "#1d4ed8";
|
|
35
|
+
/** `--es-accent-ring` — focus ring wash. */
|
|
36
|
+
readonly accentRing: "rgba(37, 99, 235, 0.25)";
|
|
37
|
+
/** `--es-accent-shadow` — accent button shadow. */
|
|
38
|
+
readonly accentShadow: "rgba(37, 99, 235, 0.35)";
|
|
39
|
+
/** `--es-on-accent` — text/icon over the solid accent. */
|
|
40
|
+
readonly onAccent: "#ffffff";
|
|
41
|
+
/** `--es-app-bg` — gray-50, sunken canvas. */
|
|
42
|
+
readonly appBg: "#f9fafb";
|
|
43
|
+
/** `--es-preview-bg` — gray-100, preview well. */
|
|
44
|
+
readonly previewBg: "#f3f4f6";
|
|
45
|
+
/** `--es-panel` — raised cards / panels. */
|
|
46
|
+
readonly panel: "#ffffff";
|
|
47
|
+
/** `--es-raised` — a lifted surface. NOT the active chip since card 66302. */
|
|
48
|
+
readonly raised: "#ffffff";
|
|
49
|
+
/** `--es-topbar-bg`. */
|
|
50
|
+
readonly topbarBg: "#ffffff";
|
|
51
|
+
/** `--es-frame-bg` — device "paper" behind the preview iframe. */
|
|
52
|
+
readonly frameBg: "#ffffff";
|
|
53
|
+
/** `--es-hover` — gray-100 row / icon hover. */
|
|
54
|
+
readonly hover: "#f3f4f6";
|
|
55
|
+
/** `--es-hatch` — 45° upload-slot texture. */
|
|
56
|
+
readonly hatch: "rgba(0, 0, 0, 0.018)";
|
|
57
|
+
/** `--es-addcard-veil` — add-section card hover wash. */
|
|
58
|
+
readonly addcardVeil: "rgba(248, 249, 250, 0.66)";
|
|
59
|
+
/** `--es-field-bg`. */
|
|
60
|
+
readonly fieldBg: "#ffffff";
|
|
61
|
+
/** `--es-track-bg` — gray-100 segmented / search track. */
|
|
62
|
+
readonly trackBg: "#f3f4f6";
|
|
63
|
+
/** `--es-input-border` — gray-300. */
|
|
64
|
+
readonly inputBorder: "#d1d5db";
|
|
65
|
+
/** `--es-field-text` — gray-800. */
|
|
66
|
+
readonly fieldText: "#1f2937";
|
|
67
|
+
/** `--es-field-placeholder` — gray-400. */
|
|
68
|
+
readonly fieldPlaceholder: "#9ca3af";
|
|
69
|
+
/** `--es-knob` — toggle knob. */
|
|
70
|
+
readonly knob: "#ffffff";
|
|
71
|
+
/** `--es-text` — gray-900. */
|
|
72
|
+
readonly text: "#111827";
|
|
73
|
+
/** `--es-text-strong` — gray-950 active labels. */
|
|
74
|
+
readonly textStrong: "#030712";
|
|
75
|
+
/** `--es-text-secondary` — gray-700. */
|
|
76
|
+
readonly textSecondary: "#374151";
|
|
77
|
+
/** `--es-muted` — gray-500. */
|
|
78
|
+
readonly muted: "#6b7280";
|
|
79
|
+
/** `--es-icon` — gray-500 icon buttons. */
|
|
80
|
+
readonly icon: "#6b7280";
|
|
81
|
+
/** `--es-disabled` — gray-400 disabled / faint glyphs. */
|
|
82
|
+
readonly disabled: "#9ca3af";
|
|
83
|
+
/** `--es-divider` — gray-200. */
|
|
84
|
+
readonly divider: "#e5e7eb";
|
|
85
|
+
/** `--es-line` — gray-200 hairlines. */
|
|
86
|
+
readonly line: "#e5e7eb";
|
|
87
|
+
/** `--es-btn-border` — gray-300. */
|
|
88
|
+
readonly btnBorder: "#d1d5db";
|
|
89
|
+
/** `--es-btn-text` — gray-700. */
|
|
90
|
+
readonly btnText: "#374151";
|
|
91
|
+
/** `--es-chip-bg` — gray-100. */
|
|
92
|
+
readonly chipBg: "#f3f4f6";
|
|
93
|
+
/** `--es-chip-fg` — gray-500. */
|
|
94
|
+
readonly chipFg: "#6b7280";
|
|
95
|
+
/** `--es-brand-square` — gray-900 wordmark square. */
|
|
96
|
+
readonly brandSquare: "#111827";
|
|
97
|
+
/** `--es-device-border` — gray-200 tablet/mobile frame. */
|
|
98
|
+
readonly deviceBorder: "#e5e7eb";
|
|
99
|
+
/** `--es-toast-bg` — gray-900 dark chip / seam pill. */
|
|
100
|
+
readonly toastBg: "#111827";
|
|
101
|
+
/** `--es-toggle-off` — gray-300 toggle track. */
|
|
102
|
+
readonly toggleOff: "#d1d5db";
|
|
103
|
+
/** `--es-scrollbar` — gray-300. */
|
|
104
|
+
readonly scrollbar: "#d1d5db";
|
|
105
|
+
/** `--es-scrollbar-hover` — gray-400. */
|
|
106
|
+
readonly scrollbarHover: "#9ca3af";
|
|
107
|
+
/** `--es-danger` — red-600. */
|
|
108
|
+
readonly danger: "#dc2626";
|
|
109
|
+
/** `--es-danger-strong` — red-700. */
|
|
110
|
+
readonly dangerStrong: "#b91c1c";
|
|
111
|
+
/** `--es-danger-tint` — red-50. */
|
|
112
|
+
readonly dangerTint: "#fef2f2";
|
|
113
|
+
/** `--es-warning` — amber-700. */
|
|
114
|
+
readonly warning: "#b45309";
|
|
115
|
+
/** `--es-preview-tint` — amber-100 "Preview" pill. */
|
|
116
|
+
readonly previewTint: "#fef3c7";
|
|
117
|
+
/**
|
|
118
|
+
* `--es-success` — green-700. THE ONE VALUE HERE WITH NO `--sf-*` BEHIND IT:
|
|
119
|
+
* the storefront editor's block has a red and an amber and no green, and card
|
|
120
|
+
* 8802.g needs one for a green tick. So it is picked to sit with the block
|
|
121
|
+
* rather than invented next to it — the same Tailwind ramp every other colour
|
|
122
|
+
* in this file comes from, at the 700 step `--es-warning` already sits on.
|
|
123
|
+
* 700 and not 600 for the reason amber went there: it is the darkest step
|
|
124
|
+
* still plainly the hue, and it clears WCAG AA (5.0:1) on the shell's white
|
|
125
|
+
* panels, so a tick may carry a label without needing a second token.
|
|
126
|
+
*/
|
|
127
|
+
readonly success: "#15803d";
|
|
128
|
+
/** `--es-panel-radius`. */
|
|
129
|
+
readonly panelRadius: 12;
|
|
130
|
+
/** `--es-row-radius`. */
|
|
131
|
+
readonly rowRadius: 8;
|
|
132
|
+
/** `--es-field-radius`. */
|
|
133
|
+
readonly fieldRadius: 6;
|
|
134
|
+
/** `--es-panel-gap` — inter-pane gutter + outer frame padding, ONE token. */
|
|
135
|
+
readonly panelGap: 10;
|
|
136
|
+
/** `--es-panel-shadow`. */
|
|
137
|
+
readonly panelShadow: "0 1px 2px rgba(0, 0, 0, 0.05), 0 10px 30px rgba(0, 0, 0, 0.06)";
|
|
138
|
+
/** `--es-topbar-shadow`. */
|
|
139
|
+
readonly topbarShadow: "0 1px 3px rgba(0, 0, 0, 0.06)";
|
|
140
|
+
/**
|
|
141
|
+
* `--es-raised-shadow` — what a small surface sitting ON another one casts:
|
|
142
|
+
* the chip in the settings tab strip's track (card 66138). Tighter and darker
|
|
143
|
+
* than `panelShadow`, which is a whole panel floating over the app; this one
|
|
144
|
+
* has to read across 3px of track without looking like a second panel.
|
|
145
|
+
*/
|
|
146
|
+
readonly raisedShadow: "0 1px 2px rgba(16, 24, 40, 0.1)";
|
|
147
|
+
/** `--es-font` — system sans stack. */
|
|
148
|
+
readonly font: "-apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif";
|
|
149
|
+
};
|
|
150
|
+
type ShellTokens = typeof shellTokens;
|
|
151
|
+
/**
|
|
152
|
+
* The CSS custom-property name behind each `shellTokens` key. `shell.css` sets
|
|
153
|
+
* these on `.es-editor`; override any of them on (or above) the editor root to
|
|
154
|
+
* re-theme without shipping new CSS. The `shell-tokens.test.ts` parity gate
|
|
155
|
+
* proves this map, `shellTokens` and `shell.css` never drift apart.
|
|
156
|
+
*/
|
|
157
|
+
declare const shellCssVars: Record<keyof ShellTokens, string>;
|
|
158
|
+
|
|
159
|
+
export { type ShellTokens, shellCssVars, shellTokens };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{shellCssVars,shellTokens}from"../chunk-FI23ALVJ.js";
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* efficient-easel — shell chrome tokens.
|
|
3
|
+
*
|
|
4
|
+
* The values here mirror `shellTokens` in tokens.ts one-for-one (both trace back
|
|
5
|
+
* to the storefront editor's `--sf-*` block — the visual reference). They are
|
|
6
|
+
* declared as custom properties ON `.es-editor`, not on `:root`, so importing
|
|
7
|
+
* this stylesheet themes ONLY an editor root and never leaks variables into the
|
|
8
|
+
* host page (the campaign designer renders INSIDE the admin DOM, so this must
|
|
9
|
+
* not touch the surrounding app).
|
|
10
|
+
*
|
|
11
|
+
* Both editors add the `es-editor` class to their chrome root and alias their
|
|
12
|
+
* own `--sf-*` / `--cd-*` names onto these — e.g. `--sf-accent: var(--es-accent)`
|
|
13
|
+
* — so the light values live ONCE, here. Re-theme by overriding any `--es-*` var
|
|
14
|
+
* on or above the editor root.
|
|
15
|
+
*
|
|
16
|
+
* LIGHT only: both editing surfaces always render light (no dark mode), so there
|
|
17
|
+
* is no dark counterpart block — do not add one.
|
|
18
|
+
*
|
|
19
|
+
*
|
|
20
|
+
* ⛔ CUSTOM PROPERTIES ONLY IN THIS BLOCK. Never a paint property.
|
|
21
|
+
*
|
|
22
|
+
* `.es-editor` is not this package's own element — it is the class each editor
|
|
23
|
+
* puts on ITS OWN chrome root, and the campaign designer puts it on a root that
|
|
24
|
+
* lives INSIDE the admin portal's DOM (card 66024 made that the mechanism:
|
|
25
|
+
* `CampaignDesigner.tsx` adds the class and `campaignBlocks.css` aliases its
|
|
26
|
+
* `--cd-*` onto these values). A custom property here is inert until something
|
|
27
|
+
* reads it. A `background`, a `padding`, a `font` — anything that PAINTS — is
|
|
28
|
+
* not: it applies to that root the moment this sheet is imported, in every
|
|
29
|
+
* editor that imports it, and in the admin portal's own document.
|
|
30
|
+
*
|
|
31
|
+
* ⚠️ This sheet is the one that matters most for that, because it is the one the
|
|
32
|
+
* admin portal actually imports (`CampaignDesigner.tsx`, since card 66024).
|
|
33
|
+
*
|
|
34
|
+
* Audited 2026-09-02 across every sheet here that opens an `.es-editor` block,
|
|
35
|
+
* and the honest number is zero:
|
|
36
|
+
*
|
|
37
|
+
* shell.css 67 declarations, 67 custom, 0 paint
|
|
38
|
+
* panel.css 11 declarations, 11 custom, 0 paint
|
|
39
|
+
* menu.css 7 declarations, 7 custom, 0 paint
|
|
40
|
+
*
|
|
41
|
+
* ⚠️ Nothing enforces this — a rule with no test behind it. If you are adding a
|
|
42
|
+
* declaration here, you are the check.
|
|
43
|
+
* Import once from a client entry / global stylesheet:
|
|
44
|
+
* import 'efficient-easel/shell.css';
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
.es-editor {
|
|
48
|
+
/* — accent (efficient-shell blue) — */
|
|
49
|
+
--es-accent: #2563eb;
|
|
50
|
+
--es-accent-tint: #eff6ff;
|
|
51
|
+
--es-accent-tint-strong: #dbeafe;
|
|
52
|
+
--es-accent-line: #bfdbfe;
|
|
53
|
+
--es-accent-text: #1d4ed8;
|
|
54
|
+
--es-accent-ring: rgba(37, 99, 235, 0.25);
|
|
55
|
+
--es-accent-shadow: rgba(37, 99, 235, 0.35);
|
|
56
|
+
--es-on-accent: #ffffff;
|
|
57
|
+
|
|
58
|
+
/* — surfaces (cool gray ramp) — */
|
|
59
|
+
--es-app-bg: #f9fafb;
|
|
60
|
+
--es-preview-bg: #f3f4f6;
|
|
61
|
+
--es-panel: #ffffff;
|
|
62
|
+
--es-raised: #ffffff;
|
|
63
|
+
--es-topbar-bg: #ffffff;
|
|
64
|
+
--es-frame-bg: #ffffff;
|
|
65
|
+
--es-hover: #f3f4f6;
|
|
66
|
+
--es-hatch: rgba(0, 0, 0, 0.018);
|
|
67
|
+
--es-addcard-veil: rgba(248, 249, 250, 0.66);
|
|
68
|
+
|
|
69
|
+
/* — fields — */
|
|
70
|
+
--es-field-bg: #ffffff;
|
|
71
|
+
--es-track-bg: #f3f4f6;
|
|
72
|
+
--es-input-border: #d1d5db;
|
|
73
|
+
--es-field-text: #1f2937;
|
|
74
|
+
--es-field-placeholder: #9ca3af;
|
|
75
|
+
--es-knob: #ffffff;
|
|
76
|
+
|
|
77
|
+
/* — text — */
|
|
78
|
+
--es-text: #111827;
|
|
79
|
+
--es-text-strong: #030712;
|
|
80
|
+
--es-text-secondary: #374151;
|
|
81
|
+
--es-muted: #6b7280;
|
|
82
|
+
--es-icon: #6b7280;
|
|
83
|
+
--es-disabled: #9ca3af;
|
|
84
|
+
|
|
85
|
+
/* — lines / chips / buttons — */
|
|
86
|
+
--es-divider: #e5e7eb;
|
|
87
|
+
--es-line: #e5e7eb;
|
|
88
|
+
--es-btn-border: #d1d5db;
|
|
89
|
+
--es-btn-text: #374151;
|
|
90
|
+
--es-chip-bg: #f3f4f6;
|
|
91
|
+
--es-chip-fg: #6b7280;
|
|
92
|
+
|
|
93
|
+
/* — named chrome literals — */
|
|
94
|
+
--es-brand-square: #111827;
|
|
95
|
+
--es-device-border: #e5e7eb;
|
|
96
|
+
--es-toast-bg: #111827;
|
|
97
|
+
--es-toggle-off: #d1d5db;
|
|
98
|
+
--es-scrollbar: #d1d5db;
|
|
99
|
+
--es-scrollbar-hover: #9ca3af;
|
|
100
|
+
|
|
101
|
+
/* — danger / warning / success (shell red / amber / green) — */
|
|
102
|
+
--es-danger: #dc2626;
|
|
103
|
+
--es-danger-strong: #b91c1c;
|
|
104
|
+
--es-danger-tint: #fef2f2;
|
|
105
|
+
--es-warning: #b45309;
|
|
106
|
+
--es-preview-tint: #fef3c7;
|
|
107
|
+
--es-success: #15803d;
|
|
108
|
+
|
|
109
|
+
/* — radii / shape / gap — */
|
|
110
|
+
--es-panel-radius: 12px;
|
|
111
|
+
--es-row-radius: 8px;
|
|
112
|
+
--es-field-radius: 6px;
|
|
113
|
+
--es-panel-gap: 10px;
|
|
114
|
+
|
|
115
|
+
/* — shadows — */
|
|
116
|
+
--es-panel-shadow: 0 1px 2px rgba(0, 0, 0, 0.05), 0 10px 30px rgba(0, 0, 0, 0.06);
|
|
117
|
+
--es-topbar-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
|
|
118
|
+
--es-raised-shadow: 0 1px 2px rgba(16, 24, 40, 0.1);
|
|
119
|
+
|
|
120
|
+
/* — type — */
|
|
121
|
+
--es-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
|
|
122
|
+
}
|