efficient-easel 0.106.0 → 1.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 (168) hide show
  1. package/README.md +70 -29
  2. package/dist/{LinkPicker-W2Rtxetz.d.ts → LinkPicker-hPEr1MJx.d.ts} +6 -4
  3. package/dist/autosave/index.d.ts +5 -5
  4. package/dist/chrome/chrome.css +50 -273
  5. package/dist/chrome/index.d.ts +61 -56
  6. package/dist/chrome/index.js +1 -1
  7. package/dist/chunk-4GNPKHV4.js +64 -0
  8. package/dist/chunk-5545A3PC.js +4 -0
  9. package/dist/chunk-7SQF6LZL.js +1 -0
  10. package/dist/chunk-BXMXTO36.js +1 -0
  11. package/dist/{chunk-JWMNPRTT.js → chunk-CKEPQNSQ.js} +1 -1
  12. package/dist/{chunk-LY4K2ECT.js → chunk-DJMMTWFP.js} +1 -1
  13. package/dist/chunk-EA2HTX37.js +5 -0
  14. package/dist/{chunk-VINYARYJ.js → chunk-FEK3S6HN.js} +1 -1
  15. package/dist/chunk-FPAVNX3Y.js +6 -0
  16. package/dist/chunk-HMJS344F.js +1 -0
  17. package/dist/chunk-JLTZQ4US.js +1 -0
  18. package/dist/chunk-JMGPPXNQ.js +24 -0
  19. package/dist/chunk-K56YDHYQ.js +1 -0
  20. package/dist/chunk-LOMEH6DG.js +1 -0
  21. package/dist/{chunk-FS5BLARH.js → chunk-MAEXP3KE.js} +1 -1
  22. package/dist/chunk-MJM6SFD3.js +3 -0
  23. package/dist/chunk-NLRW4BGG.js +8 -0
  24. package/dist/chunk-OJAJVH7S.js +5 -0
  25. package/dist/chunk-ONRYLR2D.js +2 -0
  26. package/dist/{chunk-WTMHT7BI.js → chunk-ORR3Q4WV.js} +1 -1
  27. package/dist/chunk-OTEXGJDU.js +5 -0
  28. package/dist/chunk-P2VEMZH5.js +1 -0
  29. package/dist/{chunk-MHKBLPQ2.js → chunk-PT6V53OO.js} +1 -1
  30. package/dist/{chunk-6WH7FA2M.js → chunk-PYCLHOSA.js} +2 -2
  31. package/dist/chunk-Q27BB5ZC.js +14 -0
  32. package/dist/chunk-QLD57GBB.js +6 -0
  33. package/dist/{chunk-PBSEUZD6.js → chunk-QMNML7XH.js} +1 -1
  34. package/dist/chunk-QR4DLZ3P.js +5 -0
  35. package/dist/chunk-TJ7YIRWQ.js +21 -0
  36. package/dist/{chunk-3P6AMTOS.js → chunk-VPFNZ7TB.js} +1 -1
  37. package/dist/chunk-W3XX2CNW.js +16 -0
  38. package/dist/chunk-X6DQWK2C.js +1 -0
  39. package/dist/chunk-XWR5YVA7.js +9 -0
  40. package/dist/chunk-YABL4EWX.js +7 -0
  41. package/dist/chunk-ZNNATBDC.js +1 -0
  42. package/dist/chunk-ZP4G3X44.js +4 -0
  43. package/dist/copy/copy.css +66 -177
  44. package/dist/copy/index.d.ts +0 -2
  45. package/dist/copy/index.js +31 -32
  46. package/dist/drag/drag.css +31 -11
  47. package/dist/drag/index.js +1 -1
  48. package/dist/easel/index.js +1 -1
  49. package/dist/fields/fields.css +35 -304
  50. package/dist/fields/index.d.ts +87 -95
  51. package/dist/fields/index.js +1 -1
  52. package/dist/gold/gold.css +3 -3
  53. package/dist/gold/index.d.ts +6 -5
  54. package/dist/gold/index.js +1 -1
  55. package/dist/index.d.ts +3 -3
  56. package/dist/index.js +1 -1
  57. package/dist/menu/index.d.ts +49 -93
  58. package/dist/menu/index.js +1 -1
  59. package/dist/menu/menu.css +37 -246
  60. package/dist/node-ops/index.d.ts +1 -1
  61. package/dist/panel/index.d.ts +46 -72
  62. package/dist/panel/index.js +17 -18
  63. package/dist/panel/panel.css +143 -372
  64. package/dist/pick/index.d.ts +52 -33
  65. package/dist/pick/index.js +7 -7
  66. package/dist/pick/pick.css +19 -150
  67. package/dist/rail/index.d.ts +48 -90
  68. package/dist/rail/index.js +1 -1
  69. package/dist/rail/rail.css +21 -108
  70. package/dist/screen/components/AddBlockRow.d.ts +8 -2
  71. package/dist/screen/components/AddBlockRow.js +1 -1
  72. package/dist/screen/components/AddChildRow.d.ts +4 -3
  73. package/dist/screen/components/AddChildRow.js +1 -1
  74. package/dist/screen/components/AddSidePanel.js +1 -1
  75. package/dist/screen/components/MediaSidePanel.d.ts +1 -1
  76. package/dist/screen/components/MediaSidePanel.js +1 -1
  77. package/dist/screen/components/NodeContextMenu.d.ts +12 -8
  78. package/dist/screen/components/NodeContextMenu.js +1 -1
  79. package/dist/screen/components/PageEditGuardNotices.js +1 -1
  80. package/dist/screen/components/ScreenChrome.js +1 -1
  81. package/dist/screen/components/ScreenDocumentContext.d.ts +1 -1
  82. package/dist/screen/components/ScreenDocumentContext.js +1 -1
  83. package/dist/screen/components/ScreenMount.d.ts +7 -7
  84. package/dist/screen/components/ScreenMount.js +1 -1
  85. package/dist/screen/components/ScreenStoreProvider.d.ts +7 -7
  86. package/dist/screen/components/ScreenStoreProvider.js +1 -1
  87. package/dist/screen/components/SectionScreenShell.js +16 -16
  88. package/dist/screen/components/SidePanelHead.d.ts +4 -2
  89. package/dist/screen/components/SidePanelHead.js +1 -1
  90. package/dist/screen/components/UiIcon.d.ts +10 -26
  91. package/dist/screen/components/UiIcon.js +2 -1
  92. package/dist/screen/components/panel-widths.js +1 -1
  93. package/dist/screen/components/usePartBridge.d.ts +7 -7
  94. package/dist/screen/components/usePartBridge.js +1 -1
  95. package/dist/screen/index.d.ts +7 -7
  96. package/dist/screen/index.js +1 -1
  97. package/dist/screen/lib/admin-bridge.d.ts +1 -1
  98. package/dist/screen/lib/admin-bridge.js +1 -1
  99. package/dist/screen/lib/chrome-theme.d.ts +20 -12
  100. package/dist/screen/lib/chrome-theme.js +1 -1
  101. package/dist/screen/lib/document-addressing.d.ts +1 -1
  102. package/dist/screen/lib/host-chrome.d.ts +1 -1
  103. package/dist/screen/lib/host.d.ts +1 -1
  104. package/dist/screen/lib/key-scope.js +1 -1
  105. package/dist/screen/lib/links/link-filters.d.ts +1 -1
  106. package/dist/screen/lib/media-panel.d.ts +1 -1
  107. package/dist/screen/lib/media-picker.d.ts +1 -1
  108. package/dist/screen/lib/page-lock.d.ts +1 -1
  109. package/dist/screen/lib/puck/style-clipboard.d.ts +7 -7
  110. package/dist/screen/lib/puck/use-section-ops.js +1 -1
  111. package/dist/screen/lib/screen-parts.d.ts +9 -8
  112. package/dist/screen/lib/screen-parts.js +1 -1
  113. package/dist/screen/lib/section-templates.d.ts +1 -1
  114. package/dist/screen/lib/session-context.d.ts +1 -1
  115. package/dist/screen/lib/session.d.ts +1 -1
  116. package/dist/screen/screen.css +33 -206
  117. package/dist/shell/index.d.ts +134 -118
  118. package/dist/shell/index.js +1 -1
  119. package/dist/shell/shell.css +130 -88
  120. package/dist/strings/catalogue.d.ts +5 -5
  121. package/dist/strings/catalogue.js +1 -1
  122. package/dist/strings/index.d.ts +5 -5
  123. package/dist/strings/index.js +1 -1
  124. package/dist/style-clipboard/index.d.ts +1 -1
  125. package/dist/text-styles/index.d.ts +12 -3
  126. package/dist/text-styles/index.js +33 -38
  127. package/dist/text-styles/text-styles.css +39 -71
  128. package/dist/tree/index.d.ts +49 -44
  129. package/dist/tree/index.js +1 -1
  130. package/dist/tree/tree.css +31 -653
  131. package/dist/{types-DJDBtdB2.d.ts → types-BqGnUVX5.d.ts} +32 -32
  132. package/dist/types-BsyPh6EW.d.ts +99 -0
  133. package/dist/{types-DWS-s9z-.d.ts → types-CsgMwHHa.d.ts} +14 -11
  134. package/dist/{types-CqY85foL.d.ts → types-Dt1CFR1S.d.ts} +4 -2
  135. package/dist/{wordFit-D4S36PvB.d.ts → wordFit-7XpmhcaW.d.ts} +3 -5
  136. package/dist/words-Cl9xMUYY.d.ts +41 -0
  137. package/dist/{words-D_Lnw1Gr.d.ts → words-CvFnwGSr.d.ts} +1 -1
  138. package/package.json +5 -1
  139. package/dist/chunk-2UX75JDP.js +0 -1
  140. package/dist/chunk-37OCQYNX.js +0 -65
  141. package/dist/chunk-3EDSDPIP.js +0 -1
  142. package/dist/chunk-3QVB4AG2.js +0 -3
  143. package/dist/chunk-3WSPDAK2.js +0 -1
  144. package/dist/chunk-5MZ3RNQQ.js +0 -13
  145. package/dist/chunk-5ZBBXZPV.js +0 -6
  146. package/dist/chunk-BZ5ASXOL.js +0 -1
  147. package/dist/chunk-C6BJB5AC.js +0 -2
  148. package/dist/chunk-DX4XELD6.js +0 -18
  149. package/dist/chunk-EOJNJCMJ.js +0 -16
  150. package/dist/chunk-EWVJSRRY.js +0 -6
  151. package/dist/chunk-H24N5TMZ.js +0 -11
  152. package/dist/chunk-I6T4TZ5Q.js +0 -8
  153. package/dist/chunk-KTVH2ZRL.js +0 -15
  154. package/dist/chunk-M7N2V4TG.js +0 -2
  155. package/dist/chunk-MS4QRBJ6.js +0 -5
  156. package/dist/chunk-ND55LTCA.js +0 -5
  157. package/dist/chunk-OWBO4WKA.js +0 -0
  158. package/dist/chunk-P6O363EE.js +0 -6
  159. package/dist/chunk-RW4XBUUW.js +0 -1
  160. package/dist/chunk-UEVTQBM7.js +0 -10
  161. package/dist/chunk-VCQVNPTG.js +0 -22
  162. package/dist/chunk-WZ7TGAAT.js +0 -3
  163. package/dist/chunk-YC4TB3CJ.js +0 -25
  164. package/dist/chunk-Z6SOLDWV.js +0 -1
  165. package/dist/chunk-ZFDCDJNZ.js +0 -16
  166. package/dist/chunk-ZNS7727Y.js +0 -12
  167. package/dist/types-Djdq6Xkd.d.ts +0 -138
  168. package/dist/words-DgHcY5qB.d.ts +0 -33
@@ -11,140 +11,24 @@
11
11
  * file.
12
12
  */
13
13
 
14
- /* ── the box: one line, several lines, the dropdown's button ──────────────── */
15
-
16
- .es-fin {
17
- box-sizing: border-box;
18
- width: 100%;
19
- min-width: 0;
20
- height: 32px;
21
- padding: 0 12px;
22
- border: 1px solid var(--es-input-border);
23
- border-radius: var(--es-field-radius);
24
- background: var(--es-field-bg);
25
- color: var(--es-field-text);
26
- font: inherit;
27
- font-size: 12px;
28
- line-height: 1.4;
29
- }
30
- .es-fin::placeholder { color: var(--es-field-placeholder); }
31
- .es-fin:hover:not(:disabled):not([readonly]) { border-color: var(--es-muted); }
32
- .es-fin:focus-visible,
33
- .es-fin:focus {
34
- outline: none;
35
- border-color: var(--es-accent);
36
- box-shadow: 0 0 0 3px var(--es-accent-ring);
37
- }
38
- /* A value nobody may change is still a value somebody has to READ: the grey
39
- ground says the state, and the ink stays legible on it. It was `--es-muted`,
40
- 4.39:1 on this ground at 12px — a hair under the 4.5:1 WCAG AA asks (second
41
- host, axe-core, 2026-10-07). The number cell's read-only state below is the
42
- same rule. Held by ratio in tests/contrast-small-text.test.ts. */
43
- .es-fin[readonly],
44
- .es-fin:disabled { background: var(--es-track-bg); color: var(--es-text-secondary); }
45
-
46
- .es-fin--area {
47
- height: auto;
48
- min-height: 64px;
49
- padding: 8px 12px;
50
- resize: vertical;
51
- }
52
-
53
- /* ── a number: the cell (plan step E4) ─────────────────────────────────────
54
- icon · number · unit · two stacked arrows, in ONE box with react-os-shell's
55
- Input look (32px tall, the shell's border and radius, 14px text). The ring
56
- is on the whole cell while the number inside has focus, as the design draws
57
- it: react-os-shell's blue-400 line and a 2px ring at 30%.
58
-
59
- SPACING IS THE SCALE ONLY (2 / 4 / 8 / 12 / 16 / 32), read from the
60
- `--es-space-*` tokens. The fallback after each is the same step, for a host
61
- whose sheet is older than the scale. */
62
-
63
- .es-fnum {
64
- box-sizing: border-box;
65
- display: flex;
66
- align-items: stretch;
67
- gap: var(--es-space-4, 4px);
68
- width: 100%;
69
- min-width: 0;
70
- height: 32px;
71
- padding-inline: var(--es-space-8, 8px);
72
- border: 1px solid var(--es-input-border);
73
- border-radius: var(--es-field-radius);
74
- background: var(--es-field-bg);
75
- color: var(--es-field-text);
76
- }
77
- .es-fnum--arrows { padding-inline-end: 0; }
78
- .es-fnum:hover:not(.is-readonly):not(:focus-within) { border-color: var(--es-muted); }
79
- .es-fnum:focus-within {
80
- border-color: var(--es-focus-line, #60a5fa);
81
- box-shadow: 0 0 0 2px var(--es-focus-ring, rgba(96, 165, 250, 0.3));
82
- }
83
- .es-fnum.is-readonly { background: var(--es-track-bg); color: var(--es-text-secondary); }
84
-
85
- .es-fnum-icon { display: flex; align-items: center; flex: none; color: var(--es-field-placeholder); }
14
+ /* ── the box: one line, several lines, a number ─────────────────────────────
15
+ The shell's Input / Textarea / InputNumber (harness UI-24): their border,
16
+ ground, ink, focus ring, read-only look, arrows and the grey of a number
17
+ that follows the style are the kit's, at its small rung, since
18
+ efficient-shell 4.164.0 — the read-only ground this sheet painted as a
19
+ SHELL GAP is gone. What stays is how a cell sits in its row. */
20
+
21
+ /* A NUMBER (the cell, plan step E4): fills its share of the row; a cell with a
22
+ `title` stands in the shell Tooltip's wrapper, and fills that. */
23
+ .es-fnum { flex: 1 1 auto; min-width: 0; }
24
+ span:has(> .es-fnum) { display: flex; min-width: 0; }
25
+ .es-fnum-icon { display: flex; align-items: center; }
86
26
  .es-fnum-icon svg { width: 14px; height: 14px; }
87
27
 
88
- .es-fnum-box {
89
- flex: 1 1 auto;
90
- min-width: 0;
91
- width: 100%;
92
- padding: 0;
93
- border: 0;
94
- outline: none;
95
- background: none;
96
- color: inherit;
97
- font: inherit;
98
- font-size: 14px;
99
- font-variant-numeric: tabular-nums;
100
- }
101
- .es-fnum-box::placeholder { color: var(--es-field-placeholder); opacity: 1; }
102
- /* A grey number follows the style: what shows is the style's, not the cell's. */
103
- .es-fnum.is-style .es-fnum-box { color: var(--es-field-placeholder); }
104
-
105
- .es-fnum-unit { align-self: center; flex: none; font-size: 12px; color: var(--es-muted); white-space: nowrap; }
106
-
107
- .es-fnum-arrows {
108
- display: flex;
109
- flex-direction: column;
110
- flex: none;
111
- width: 18px;
112
- border-left: 1px solid var(--es-line);
113
- }
114
- .es-fnum-arrow {
115
- flex: 1 1 0;
116
- display: flex;
117
- align-items: center;
118
- justify-content: center;
119
- min-height: 0;
120
- padding: 0;
121
- border: 0;
122
- background: none;
123
- color: var(--es-icon);
124
- cursor: pointer;
125
- touch-action: none;
126
- }
127
- .es-fnum-arrow--up {
128
- border-bottom: 1px solid var(--es-line);
129
- border-top-right-radius: calc(var(--es-field-radius) - 1px);
130
- }
131
- .es-fnum-arrow--down { border-bottom-right-radius: calc(var(--es-field-radius) - 1px); }
132
- .es-fnum-arrow:hover:not(:disabled) { background: var(--es-hover); color: var(--es-text); }
133
- .es-fnum-arrow:disabled { color: var(--es-disabled); cursor: default; }
134
- .es-fnum-arrow svg { width: 10px; height: 10px; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
135
-
136
28
  /* ── a slider row (Site styles, Email styles; plan step E4) ────────────────
137
- The name left and the value right on one line, the slider under them. The
138
- value is a quiet box until it is hovered or has focus. */
29
+ The name over the shell's `Slider` (its range and its typed box, UI-24). */
139
30
 
140
31
  .es-fslider { display: flex; flex-direction: column; gap: var(--es-space-4, 4px); min-width: 0; }
141
- .es-fslider-top {
142
- display: flex;
143
- align-items: baseline;
144
- justify-content: space-between;
145
- gap: var(--es-space-8, 8px);
146
- min-width: 0;
147
- }
148
32
  .es-fslider-name {
149
33
  min-width: 0;
150
34
  overflow: hidden;
@@ -154,114 +38,16 @@
154
38
  font-weight: 500;
155
39
  color: var(--es-text-secondary);
156
40
  }
157
- .es-fslider-read { display: inline-flex; align-items: baseline; gap: var(--es-space-2, 2px); flex: none; }
158
- .es-fslider-value {
159
- box-sizing: content-box;
160
- width: 5ch;
161
- padding: var(--es-space-2, 2px) var(--es-space-4, 4px);
162
- border: 0;
163
- border-radius: 4px;
164
- outline: none;
165
- background: none;
166
- color: var(--es-field-text);
167
- font: inherit;
168
- font-size: 12.5px;
169
- font-variant-numeric: tabular-nums;
170
- text-align: right;
171
- cursor: text;
172
- }
173
- .es-fslider-value:hover { background: var(--es-hover); }
174
- .es-fslider-value:focus { background: var(--es-field-bg); box-shadow: inset 0 0 0 1px var(--es-focus-line, #60a5fa); }
175
- .es-fslider-value::placeholder { color: var(--es-field-placeholder); opacity: 1; }
176
- .es-fslider.is-style .es-fslider-value { color: var(--es-field-placeholder); }
177
- .es-fslider-unit { font-size: 12px; color: var(--es-field-placeholder); }
178
- .es-fslider-range { width: 100%; height: 18px; margin: 0; accent-color: var(--es-accent); }
41
+ /* A row with no number of its own (Auto, or the style's number) is the shell's
42
+ empty box: the word or the number is its placeholder, grey. */
179
43
 
180
- .es-fbtn {
181
- height: 28px;
182
- min-width: 28px;
183
- padding: 0 8px;
184
- border: 1px solid var(--es-btn-border);
185
- border-radius: var(--es-field-radius);
186
- background: var(--es-raised);
187
- color: var(--es-btn-text);
188
- font: inherit;
189
- font-size: 12px;
190
- cursor: pointer;
191
- }
192
- .es-fbtn:hover:not(:disabled) { background: var(--es-hover); }
193
- .es-fbtn:disabled { color: var(--es-disabled); cursor: default; }
194
- .es-fbtn:focus-visible { outline: 2px solid var(--es-accent); outline-offset: 1px; }
195
-
196
- /* ── one of a set: the button and its list ────────────────────────────────── */
44
+ /* ── one of a set: the shell's Select / SearchableSelect ────────────────────
45
+ The box, the list, its groups, its ticks and its search are the shell's
46
+ (harness UI-24, efficient-shell 4.164.0). What stays is the row a host's
47
+ options draw inside the shell's row: a picture column and a quiet fact. */
197
48
 
198
49
  .es-fsel { position: relative; width: 100%; min-width: 0; }
199
- .es-fsel-button {
200
- display: flex;
201
- align-items: center;
202
- justify-content: space-between;
203
- gap: 8px;
204
- text-align: left;
205
- cursor: pointer;
206
- }
207
- .es-fsel-value { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
208
- .es-fsel-value.is-empty { color: var(--es-field-placeholder); }
209
- /* The chevron is drawn, not a glyph, so it sits on the same stroke as the
210
- panel's other chevrons whatever the font. */
211
- .es-fsel-chev {
212
- flex: none;
213
- width: 7px;
214
- height: 7px;
215
- margin: -3px 2px 0 0;
216
- border-right: 1.6px solid var(--es-icon);
217
- border-bottom: 1.6px solid var(--es-icon);
218
- transform: rotate(45deg);
219
- }
220
- .es-fsel-list {
221
- position: absolute;
222
- z-index: 20;
223
- top: calc(100% + 4px);
224
- left: 0;
225
- right: 0;
226
- max-height: 240px;
227
- overflow-y: auto;
228
- margin: 0;
229
- padding: 4px;
230
- list-style: none;
231
- border: 1px solid var(--es-line);
232
- border-radius: var(--es-row-radius);
233
- background: var(--es-raised);
234
- box-shadow: var(--es-panel-shadow);
235
- }
236
- .es-fsel-list:focus { outline: none; }
237
- .es-fsel-option {
238
- padding: 8px;
239
- border-radius: var(--es-field-radius);
240
- font-size: 12px;
241
- color: var(--es-text);
242
- cursor: pointer;
243
- }
244
- .es-fsel-option.is-active { background: var(--es-hover); }
245
- .es-fsel-option.is-chosen { color: var(--es-accent-text); font-weight: 600; }
246
- .es-fsel-option[aria-disabled='true'] { color: var(--es-disabled); cursor: default; }
247
- /* A heading over a run of options (`FieldOption.group`): a quiet label above
248
- its options, and not an option itself — no hover, no pointer. */
249
- .es-fsel-group-list { margin: 0; padding: 0; list-style: none; }
250
- .es-fsel-group + .es-fsel-group,
251
- .es-fsel-option + .es-fsel-group { margin-top: 4px; }
252
- .es-fsel-group-head {
253
- padding: 8px 8px 4px;
254
- font-size: 11px;
255
- font-weight: 600;
256
- color: var(--es-muted);
257
- cursor: default;
258
- }
259
- .es-fsel-group-count { margin-left: 4px; font-weight: 400; }
260
-
261
- /* The editor's one pop-up list (card [MERGE] One Pop-up List For Editor And
262
- One For Shoppers): what the website editor's own lists drew, here once.
263
- A row with more than its label lays its parts out in a line. */
264
- .es-fsel-option--rich { display: flex; align-items: center; gap: 8px; }
50
+ .es-fsel-row { display: flex; align-items: center; gap: 8px; min-width: 0; }
265
51
  .es-fsel-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
266
52
  .es-fsel-meta { flex: none; font-size: 11px; font-weight: 400; color: var(--es-muted); }
267
53
  .es-fsel-thumb {
@@ -273,61 +59,6 @@
273
59
  background: var(--es-track-bg);
274
60
  }
275
61
  .es-fsel-thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
276
- /* `multiple`: a tick box per row, drawn (the row is the option, not an <input>). */
277
- .es-fsel-tick {
278
- flex: none;
279
- position: relative;
280
- box-sizing: border-box;
281
- width: 14px;
282
- height: 14px;
283
- border: 1.5px solid var(--es-input-border);
284
- border-radius: 3px;
285
- background: var(--es-field-bg);
286
- }
287
- .es-fsel-tick.is-on { border-color: var(--es-accent); background: var(--es-accent); }
288
- .es-fsel-tick.is-on::after {
289
- content: '';
290
- position: absolute;
291
- left: 3.5px;
292
- top: 0.5px;
293
- width: 3.5px;
294
- height: 7px;
295
- border-right: 1.6px solid var(--es-on-accent);
296
- border-bottom: 1.6px solid var(--es-on-accent);
297
- transform: rotate(45deg);
298
- }
299
- /* A tick box says "on" itself, so a ticked row keeps the ordinary ink. */
300
- .es-fsel-option--rich.is-chosen:has(.es-fsel-tick) { color: var(--es-text); font-weight: 400; }
301
- /* `searchable`: the box and the list float together; the list inside is plain. */
302
- .es-fsel-pop {
303
- position: absolute;
304
- z-index: 20;
305
- top: calc(100% + 4px);
306
- left: 0;
307
- right: 0;
308
- display: flex;
309
- flex-direction: column;
310
- gap: 4px;
311
- padding: 4px;
312
- border: 1px solid var(--es-line);
313
- border-radius: var(--es-row-radius);
314
- background: var(--es-raised);
315
- box-shadow: var(--es-panel-shadow);
316
- }
317
- .es-fsel-pop .es-fsel-list {
318
- position: static;
319
- padding: 0;
320
- border: 0;
321
- border-radius: 0;
322
- background: none;
323
- box-shadow: none;
324
- }
325
- .es-fsel-empty { padding: 8px; font-size: 12px; color: var(--es-muted); }
326
- /* `inline`: the list opens in flow and pushes the rows below it down, so a
327
- panel that scrolls never clips it. */
328
- .es-fsel--inline .es-fsel-list { position: static; margin-top: 4px; }
329
- .es-fsel--inline .es-fsel-pop { position: static; margin-top: 4px; }
330
- .es-fsel--inline .es-fsel-pop .es-fsel-list { margin-top: 0; }
331
62
 
332
63
  /* ── the panel body: the tab strip and the rows (Inspector) ───────────────── */
333
64
 
@@ -368,13 +99,18 @@
368
99
  /* A host's bar for the row in use, between the name and the rows. */
369
100
  .es-list-above { min-width: 0; }
370
101
 
371
- /* The rows: a column with no gap of its own, because the seams between rows
372
- are the gap (tree.css `.es-tree-seam`, one rule for both). NOT a scroll box,
102
+ /* The rows: 8px apart, and the gap between two is a place — the shell's
103
+ `TreeSeam` (efficient-shell 4.165.0) in an `.es-list-gap`. NOT a scroll box,
373
104
  and not Layers' `.es-tree` (which is one): the panel around the list scrolls.
374
105
  Inside a scroll box of its own the drag hint under the last row was clipped
375
106
  and the list scrolled by itself under a wheel (second host, 2026-10-07). */
376
- .es-list-rows { display: flex; flex-direction: column; min-width: 0; --es-rhythm-between: 8px; }
377
- .es-list-rows > .es-tree-seam:last-child { margin-top: -8px; }
107
+ .es-list-rows { display: flex; flex-direction: column; min-width: 0; }
108
+ /* The 8px between two rows, holding the shell's seam centred in it: the seam
109
+ hands back its own height, so a column that centres it puts its 4px line
110
+ box in the middle of the 8. */
111
+ .es-list-gap { display: flex; flex-direction: column; justify-content: center; height: 8px; flex: none; }
112
+ /* The place after the last row takes no room: it lies over the row's end. */
113
+ .es-list-rows > .es-list-gap:last-child { margin-top: -8px; }
378
114
  .es-list-entry { display: flex; flex-direction: column; min-width: 0; }
379
115
 
380
116
  .es-list-row {
@@ -395,7 +131,7 @@
395
131
  .es-list-row.is-item:hover,
396
132
  .es-list-row.is-open { --es-row-scrim: var(--es-hover); background: var(--es-row-scrim); }
397
133
  .es-list-row.is-dragging { opacity: 0.4; }
398
- .es-list-row.is-lifting { background: var(--es-raised); box-shadow: 0 8px 20px rgba(16, 24, 40, 0.16), 0 2px 6px rgba(16, 24, 40, 0.1); }
134
+ .es-list-row.is-lifting { background: var(--es-raised); box-shadow: var(--rosh-glass-solid-shadow); }
399
135
  .es-list-row:focus-visible { outline: 2px solid var(--es-accent); outline-offset: 1px; }
400
136
  /* The one drop line, in the middle of the 8px gap — where a seam draws its own. */
401
137
  .es-list-row.is-drop-before::before,
@@ -405,7 +141,7 @@
405
141
  left: 8px;
406
142
  right: 8px;
407
143
  height: 2px;
408
- border-radius: 2px;
144
+ border-radius: var(--radius-sm);
409
145
  background: var(--es-accent);
410
146
  pointer-events: none;
411
147
  }
@@ -433,7 +169,7 @@
433
169
  text-align: left;
434
170
  cursor: inherit;
435
171
  }
436
- .es-list-open:focus-visible { outline: 2px solid var(--es-accent); outline-offset: 1px; border-radius: 4px; }
172
+ .es-list-open:focus-visible { outline: 2px solid var(--es-accent); outline-offset: 1px; border-radius: var(--radius-sm); }
437
173
  .es-list-thumb { flex: none; display: inline-flex; align-items: center; }
438
174
  .es-list-row-name { flex: none; font-weight: 600; white-space: nowrap; }
439
175
  .es-list-row-summary { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--es-muted); }
@@ -473,7 +209,7 @@
473
209
  top: calc(100% + 4px);
474
210
  z-index: 5;
475
211
  padding: 4px 8px;
476
- border-radius: 6px;
212
+ border-radius: var(--radius-md);
477
213
  background: var(--es-toast-bg);
478
214
  color: var(--es-on-accent);
479
215
  font-size: 11px;
@@ -519,15 +255,13 @@
519
255
  /* Read out after a move; never seen. */
520
256
  .es-list-said { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
521
257
 
522
- .es-fbtn--danger { color: var(--es-danger); }
523
-
524
258
  /* ── the link picker (LinkPicker, [MERGE] One Link Picker For Both Editors) ──
525
259
  The mockup's stack (owner, 2026-10-06): Link type, the target, and on the
526
260
  listing Filter and Value — one box under the next, the whole width of the
527
261
  row, 8px apart (the spacing scale). The same stack at 320px and at 220px:
528
262
  nothing beside anything, so nothing is cut off mid-word in the narrow
529
- panel. Every box is `FieldSelect` or `.es-fin`; this adds only the stack and
530
- the two quiet lines under it. */
263
+ panel. Every box is the shell's Select, SearchableSelect or Input; this adds
264
+ only the stack and the two quiet lines under it. */
531
265
  .es-flink {
532
266
  display: flex;
533
267
  flex-direction: column;
@@ -540,9 +274,6 @@
540
274
  .es-field-ctl > .es-flink {
541
275
  flex: 1 1 auto;
542
276
  }
543
- .es-flink > .es-fin[aria-invalid='true'] {
544
- border-color: var(--es-danger);
545
- }
546
277
  .es-flink-error,
547
278
  .es-flink-hint {
548
279
  margin: 0;
@@ -1,11 +1,11 @@
1
1
  import * as react from 'react';
2
- import { ReactNode, KeyboardEvent } from 'react';
2
+ import { ReactNode } from 'react';
3
3
  import { S as SettingsBucket } from '../buckets-CuLM47h9.js';
4
4
  import { I as InspectorFields, a as InspectorFieldDef, F as FieldRenderer, b as FieldTextProps, c as FieldNumberProps, d as FieldSliderProps, e as FieldSelectManyProps, f as FieldSelectOneProps, g as FieldOption } from '../types-VqL6t5HH.js';
5
5
  export { A as ArrayFieldDef, C as CustomFieldDef, h as CustomFieldRenderProps, i as FieldSelectProps, N as NumberFieldDef, O as ObjectFieldDef, R as RadioFieldDef, S as SelectFieldDef, j as SlotFieldDef, T as TextFieldDef, k as TextareaFieldDef } from '../types-VqL6t5HH.js';
6
6
  import { R as ResolvableItem } from '../resolve-D68pb3Bx.js';
7
7
  export { F as FieldsWords } from '../words-D8kf071T.js';
8
- export { b as LinkFilter, a as LinkFilterField, c as LinkKindChoice, L as LinkOption, d as LinkOptionGroup, e as LinkPicker, f as LinkPickerProps, g as LinkRules, h as LinkTarget } from '../LinkPicker-W2Rtxetz.js';
8
+ export { b as LinkFilter, a as LinkFilterField, c as LinkKindChoice, L as LinkOption, d as LinkOptionGroup, e as LinkPicker, f as LinkPickerProps, g as LinkRules, h as LinkTarget } from '../LinkPicker-hPEr1MJx.js';
9
9
  import '../types-41704JE4.js';
10
10
 
11
11
  interface InspectorProps {
@@ -274,124 +274,116 @@ declare function copyItem<T>(item: T): T;
274
274
  declare function ListField<T>({ label, icon, noun: ownNoun, items, onChange, newItem, summary, itemName, thumb, min, max, readOnly, open, onOpen, renderItem, renderRow, canRemove: removable, lockedReason, fixed, removeOnRow, canDuplicate, above, head, }: ListFieldProps<T>): react.JSX.Element;
275
275
 
276
276
  /**
277
- * A text value: the shell's own box, one line or several (blueprint step 4.1,
278
- * "native inputs become shell controls"). The look is `fields.css`
279
- * (`.es-fin`), so a row in the email designer and a row in the website editor
280
- * are the same box instead of Puck's input under two sets of overrides.
277
+ * A text value, one line or several (blueprint step 4.1, "native inputs become
278
+ * shell controls"): the shell's `Input` / `Textarea` (harness UI-24,
279
+ * efficient-easel#199 step 4), at the kit's small rung, so a row in the email
280
+ * designer and a row in the website editor are the portal's own box.
281
281
  *
282
282
  * CONTROLLED: every keystroke goes to `onChange`; the host decides what a
283
283
  * keystroke costs (the editors write a draft and save on their own clock).
284
284
  */
285
285
  declare function FieldText({ id, value, onChange, placeholder, multiline, rows, readOnly, ariaLabel, ariaLabelledBy, }: FieldTextProps): react.JSX.Element;
286
286
 
287
- /** A number held to its bounds and, when a step is given, to the step's grid. */
288
- declare function clampNumber(n: number, min?: number, max?: number): number;
289
- /** What a typed string means as a number: null for nothing or not-a-number. */
290
- declare function parseTyped(text: string): number | null;
291
- interface NumberEntryOptions {
292
- value: number | undefined;
293
- onChange: (value: number | undefined) => void;
294
- min?: number;
295
- max?: number;
296
- step?: number;
297
- shiftStep?: number;
298
- styleValue?: number;
299
- readOnly?: boolean;
300
- }
301
287
  /**
302
- * What a typed number box does, shared by the number cell and the slider
303
- * row's value, so the two cannot drift.
288
+ * A number value (blueprint step 4.1; the cell, plan step E4): the shell's
289
+ * `InputNumber` (harness UI-24, efficient-easel#199), at its small rung, with
290
+ * an optional glyph in front, an optional unit and, with `steppers`, the
291
+ * shell's two arrows inside its end. A `title` is the shell's `Tooltip`.
304
292
  *
305
- * It keeps the TYPED TEXT while you type, so "1." and "-" are allowed on the way
306
- * to a number, and writes only when the text is a number. It writes as you type
307
- * (the canvas follows). Enter or leaving the box clamps to `min` / `max`; Esc
308
- * puts back the value the box had when you came in. ↑↓ move by `step`, Shift
309
- * by `shiftStep` (ten steps unless the host says). An empty box writes
310
- * `undefined`: the setting goes back to the style, whose number `styleValue`
311
- * then shows, grey, and is where a step starts from.
312
- */
313
- declare function useNumberEntry({ value, onChange, min, max, step, shiftStep, styleValue, readOnly }: NumberEntryOptions): {
314
- inputProps: {
315
- value: string;
316
- readOnly: boolean;
317
- placeholder: string | undefined;
318
- onFocus: () => void;
319
- onChange: (e: {
320
- target: {
321
- value: string;
322
- };
323
- }) => void;
324
- onBlur: () => void;
325
- onKeyDown: (e: KeyboardEvent<HTMLInputElement>) => void;
326
- };
327
- nudge: (dir: 1 | -1, big?: boolean) => void;
328
- set: (n: number | undefined) => void;
329
- /** Nothing of its own: the style's number shows, grey. */
330
- isStyle: boolean;
331
- };
332
- /**
333
- * A number value (blueprint step 4.1; the cell, plan step E4): one box holding
334
- * an optional icon, the number, an optional unit and, with `steppers`, two
335
- * small stacked arrows. What the typing, the keys and the arrows do is
336
- * {@link useNumberEntry}'s.
293
+ * Everything a key, a typed character or an arrow does is the shell's since
294
+ * efficient-shell 4.164.0, which took in what this cell used to do itself:
295
+ * the half-typed text kept while it reports numbers, a comma read as the
296
+ * decimal point, ↑↓ by `step` and Shift by `shiftStep` (ten steps unless the
297
+ * host says), Enter and leaving the box settling the number — onto the
298
+ * `step` grid counted from `min` (`snap`), then held to `min` / `max` — Escape
299
+ * putting back the value the box had when it was entered, and the arrows'
300
+ * hold-to-repeat. The cell no longer keeps any of that logic.
301
+ *
302
+ * FOLLOWING THE STYLE. The cell's value is `undefined` while the setting
303
+ * follows the style: the shell's `null`, with the style's number as the
304
+ * `placeholder`, which the shell shows grey, announces (`aria-valuetext`) and
305
+ * steps from. Emptying the box writes `undefined`, back to the style
306
+ * (`allowEmpty`, the shell's default).
307
+ *
308
+ * THE ARROWS' NAMES are still the catalogue's (`fields.more` / `fields.less`),
309
+ * handed to the shell's `InputNumber` through its own strings provider round
310
+ * the box, so a host's `EaselStringsProvider` keeps naming them in its
311
+ * language.
337
312
  */
338
313
  declare function FieldNumber({ id, value, onChange, min, max, step, shiftStep, styleValue, icon, unit, steppers, placeholder, readOnly, ariaLabel, ariaLabelledBy, title, }: FieldNumberProps): react.JSX.Element;
339
314
 
340
315
  /**
341
- * A slider row (plan step E4), for Site styles and Email styles: the name on
342
- * the left and the value on the right on one line, the slider under them.
316
+ * A slider row (plan step E4), for Site styles and Email styles: the name over
317
+ * the shell's `Slider` — its range and its typed box beside it (harness UI-24;
318
+ * efficient-easel#199).
319
+ *
320
+ * The typed value may go past the slider's own travel (`sliderMin` /
321
+ * `sliderMax`); only `min` / `max` hold it, and the slider then rests at its
322
+ * end — the shell's `inputMin` / `inputMax`. A row that follows the style
323
+ * has no number of its own: the shell's `null`, with the style's number as
324
+ * the box's grey placeholder (`emptyLabel`), which the box steps from;
325
+ * emptying the box writes `undefined`, back to the style, and Escape after
326
+ * typing goes back to following it.
343
327
  *
344
- * The value is typed and takes ↑↓ (Shift = ten steps), exactly as the number
345
- * cell does — it is the same {@link useNumberEntry} — and may go past the
346
- * slider's own travel (`sliderMin` / `sliderMax`); only `min` / `max` hold it.
347
- * The slider then rests at its end. A grey value follows the style.
328
+ * SHELL GAP (named in efficient-easel#199 part C): the shell's Slider rests
329
+ * its range at `min` while the value is `null`, and has no "inherited" number
330
+ * for it to sit on, so a row that follows the style shows its number in the
331
+ * box but not on the range. Handing the shell the style's number AS the value
332
+ * would put the range right and make Escape write that number as the row's
333
+ * own — a document change nobody asked for — so the range waits for the
334
+ * shell.
348
335
  *
349
336
  * `auto` (plan step E6, Site styles) is the word for "no number: each section
350
337
  * draws its own". The design puts it ON the slider: one spot left of its
351
- * travel is Auto, and the value reads the word, grey, with no unit. Dragged there, the row
352
- * writes `undefined`; ↑ from Auto starts at `sliderMin` (one more than Auto is
353
- * the slider's first number, not `min`), ↓ stays; an emptied box is Auto too.
338
+ * travel is Auto, the box reads the word, grey, with no unit, and the slider
339
+ * announces the word. Dragged there, the row writes `undefined`; an emptied
340
+ * box is Auto too.
341
+ *
342
+ * THE BOX'S KEYS ARE THE SHELL'S (efficient-shell 4.164.0): ↑↓ step from the
343
+ * number shown, Shift by ten steps, Enter commits — snapped to `step` and held
344
+ * to `min` / `max` — and Escape puts back the value the box had when it was
345
+ * entered. The key-capture wrapper this row kept round the shell's box until
346
+ * then is gone; what differs from it is listed in the 1.0.0 notes.
354
347
  */
355
- declare function FieldSlider({ id, label, value, onChange, min, max, step, shiftStep, styleValue, unit, sliderMin, sliderMax, auto, readOnly, }: FieldSliderProps): react.JSX.Element;
348
+ declare function FieldSlider({ id, label, value, onChange, min, max, step, styleValue, unit, sliderMin, sliderMax, auto, readOnly, }: FieldSliderProps): react.JSX.Element;
356
349
 
357
350
  /** The option a stored value names: equal by `Object.is`, so `0`, `false` and `''` are values too. */
358
351
  declare function optionFor<V>(options: readonly FieldOption<V>[], value: V | undefined): FieldOption<V> | undefined;
359
352
  /**
360
- * One of a fixed set (blueprint step 4.1): a button that shows the choice and
361
- * opens a list under it. The shell's control, not the browser's `<select>`, so
362
- * it is the same box and the same list in both editors and on every system.
363
- *
364
- * Keyboard as a listbox: ↓ / ↑ / Enter / Space open it on the button; in the
365
- * list ↓ ↑ Home End move, Enter or Space choose, Escape closes and gives the
366
- * button its focus back, a letter jumps to the next option that starts with it.
367
- * A click outside closes it (a CLICK, not a pointerdown: closing early moves the
368
- * row and loses the press — the colour row learned that in 4.6).
369
- *
370
- * Options may sit under headings (`FieldOption.group`, `<optgroup>`'s job): a
371
- * heading is a `role="group"`'s name, never an option, so the keys and a click
372
- * pass it by. Without groups the list is exactly the flat one it always was.
353
+ * One of a fixed set (blueprint step 4.1) — or several (`multiple`), or one of
354
+ * a long list with a search box (`searchable`). It is the SHELL's list
355
+ * (harness UI-24, efficient-easel#199): `Select` for a set, `SearchableSelect`
356
+ * for a searchable one. Since efficient-shell 4.164.0 `Select` takes option
357
+ * groups, several values and a drawn row, and names its open list, and
358
+ * `SearchableSelect` is named and walked as a listbox — the gaps this field
359
+ * drew its own list for until then. What is left here is the mapping from the
360
+ * editors' options to the shell's:
373
361
  *
374
- * THE EDITOR'S ONE POP-UP LIST (card [MERGE] One Pop-up List For Editor And One
375
- * For Shoppers, 2026-10-06). What the website editor's own lists did is here,
376
- * each optional, and a list that asks for none draws what it always drew:
362
+ * group each RUN of options with the same `group` is one
363
+ * `SelectOptionGroup`, in the order the options come — what
364
+ * `<optgroup>` did. `groupCount` puts the run's size after its
365
+ * heading.
366
+ * thumb, meta drawn into the row by the shell's `renderOption`: a picture
367
+ * column (one option with a `thumb` key gives every row one)
368
+ * and a quiet fact at the end that a screen reader skips.
369
+ * renderOption the host's drawing of a row (each style in its own face),
370
+ * inside the same row.
371
+ * readOnly the shell's `disabled`: the list cannot open.
377
372
  *
378
- * searchable a search box at the top of the open list. It has the focus;
379
- * letters go into it (no letter jump), ↓ ↑ walk what is left,
380
- * Enter chooses, Escape closes. Home and End stay the box's.
381
- * multiple several values. Enter, Space or a click ticks one and the list
382
- * STAYS open; the save is in the options' order.
383
- * thumb, meta a picture column and a quiet fact on the option.
384
- * groupCount a heading says how many of its options are showing.
385
- * renderOption / renderValue the host draws a row's or the button's content.
386
- * inline the list opens in flow, for a panel that scrolls.
373
+ * NAMES. `ariaLabelledBy`, else `ariaLabel`, names the control and its open
374
+ * list; with neither, the shell names the list by its trigger, which the row's
375
+ * `<label for>` names.
387
376
  *
388
- * THE OPEN LIST ALWAYS HAS A NAME (second host, 2026-10-07): the host's
389
- * `ariaLabelledBy`, else its `ariaLabel`, else the BUTTON that opened it —
390
- * which the row's `<label for>` names. Until then a list given neither was a
391
- * `role="listbox"` with no accessible name (axe `aria-input-field-name`), and
392
- * the engine's own settings row gave neither.
377
+ * WHAT THE SHELL'S LISTS DO NOT TAKE (named for efficient-shell, not drawn
378
+ * here): `SearchableSelect` has no option groups, no several values and no
379
+ * disabled options — a searchable list shows a group as its option's quiet
380
+ * second line, ticks are a plain `Select`'s, and a disabled option is left out
381
+ * of a searchable list; `Select` draws no closed value of the host's
382
+ * (`renderValue` is ignored: the chosen label shows); and neither list opens
383
+ * in the panel's flow (`inline` is ignored — the shell's list is placed over
384
+ * the page, so a panel that scrolls no longer clips it).
393
385
  */
394
386
  declare function FieldSelect<V>(props: FieldSelectManyProps<V>): ReactNode;
395
387
  declare function FieldSelect<V>(props: FieldSelectOneProps<V>): ReactNode;
396
388
 
397
- export { FieldNumber, FieldNumberProps, FieldOption, type FieldPlan, FieldRenderer, FieldSelect, FieldSelectManyProps, FieldSelectOneProps, FieldSlider, FieldSliderProps, FieldText, FieldTextProps, type FieldsBlock, Inspector, InspectorField, InspectorFieldDef, type InspectorFieldProps, InspectorFields, type InspectorProps, ListField, type ListFieldProps, type NumberEntryOptions, type PlannedRow, type ResolvedFieldsInput, SettingsBucket, bucketsOf, clampNumber, copyItem, insertAt, labelOf, moveTo, optionFor, parseTyped, planFields, removeAt, useNumberEntry, useResolvedFields };
389
+ export { FieldNumber, FieldNumberProps, FieldOption, type FieldPlan, FieldRenderer, FieldSelect, FieldSelectManyProps, FieldSelectOneProps, FieldSlider, FieldSliderProps, FieldText, FieldTextProps, type FieldsBlock, Inspector, InspectorField, InspectorFieldDef, type InspectorFieldProps, InspectorFields, type InspectorProps, ListField, type ListFieldProps, type PlannedRow, type ResolvedFieldsInput, SettingsBucket, bucketsOf, copyItem, insertAt, labelOf, moveTo, optionFor, planFields, removeAt, useResolvedFields };