efficient-easel 0.99.2 → 0.101.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 +233 -17
- package/dist/autosave/index.d.ts +11 -5
- package/dist/blocks/index.d.ts +1 -1
- package/dist/canvas/index.d.ts +2 -2
- package/dist/canvas/index.js +1 -1
- package/dist/chrome/chrome.css +96 -29
- package/dist/chrome/index.d.ts +67 -18
- package/dist/chrome/index.js +25 -21
- package/dist/{chunk-JYPOOHII.js → chunk-2FZJWH24.js} +3 -3
- package/dist/chunk-3EDSDPIP.js +1 -0
- package/dist/chunk-546BBOPE.js +1 -0
- package/dist/chunk-67GNT6PF.js +1 -0
- package/dist/chunk-EOJNJCMJ.js +16 -0
- package/dist/chunk-EWVJSRRY.js +6 -0
- package/dist/chunk-FPOKPNO4.js +1 -0
- package/dist/chunk-H24N5TMZ.js +11 -0
- package/dist/chunk-IG3U5NWJ.js +1 -0
- package/dist/chunk-JUQ6YJCG.js +1 -0
- package/dist/chunk-KTVH2ZRL.js +15 -0
- package/dist/{chunk-PI26YXYD.js → chunk-L5KW4HG5.js} +16 -8
- package/dist/chunk-M6F6LS3H.js +1 -0
- package/dist/chunk-P6O363EE.js +6 -0
- package/dist/chunk-PAELDYYS.js +1 -0
- package/dist/chunk-QTLAVDJE.js +1 -0
- package/dist/chunk-UH7IGZKF.js +1 -0
- package/dist/chunk-WZ7TGAAT.js +3 -0
- package/dist/chunk-ZFDCDJNZ.js +16 -0
- package/dist/chunk-ZJEBF4NB.js +1 -0
- package/dist/chunk-ZNS7727Y.js +12 -0
- package/dist/copy/copy.css +442 -5
- package/dist/copy/index.d.ts +302 -5
- package/dist/copy/index.js +32 -10
- package/dist/drag/drag.css +10 -1
- package/dist/drag/index.d.ts +99 -8
- package/dist/drag/index.js +18 -17
- package/dist/easel/easel.css +15 -0
- package/dist/easel/index.d.ts +104 -33
- package/dist/easel/index.js +9 -1
- package/dist/edit-lock/index.d.ts +1 -3
- package/dist/edit-lock/index.js +1 -1
- package/dist/fields/fields.css +270 -38
- package/dist/fields/index.d.ts +209 -26
- package/dist/fields/index.js +22 -53
- package/dist/gold/index.js +1 -1
- package/dist/icons/index.d.ts +13 -1
- package/dist/icons/index.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/markup/index.d.ts +111 -10
- package/dist/markup/index.js +1 -1
- package/dist/menu/index.d.ts +58 -5
- package/dist/menu/index.js +1 -15
- package/dist/menu/menu.css +17 -6
- package/dist/node-ops/index.d.ts +1 -1
- package/dist/node-ops/index.js +1 -1
- package/dist/panel/index.d.ts +83 -4
- package/dist/panel/index.js +18 -16
- package/dist/panel/panel.css +135 -62
- package/dist/pick/index.d.ts +78 -2
- package/dist/pick/index.js +7 -14
- package/dist/pick/pick.css +197 -10
- package/dist/rail/index.d.ts +3 -7
- package/dist/rail/index.js +1 -1
- package/dist/strings/catalogue.d.ts +13 -35
- package/dist/strings/catalogue.js +1 -1
- package/dist/strings/index.d.ts +12 -18
- package/dist/strings/index.js +2 -2
- package/dist/style-clipboard/index.d.ts +1 -1
- package/dist/style-clipboard/index.js +1 -1
- package/dist/text-styles/index.d.ts +328 -0
- package/dist/text-styles/index.js +38 -0
- package/dist/text-styles/text-styles.css +309 -0
- package/dist/tree/index.d.ts +43 -2
- package/dist/tree/index.js +1 -1
- package/dist/tree/tree.css +71 -0
- package/dist/{types-p9j2Fac7.d.ts → types-DGcCsxs8.d.ts} +72 -7
- package/dist/{types-Bs_gVkVI.d.ts → types-DWS-s9z-.d.ts} +1 -9
- package/dist/{types-DO-b0LNj.d.ts → types-Djdq6Xkd.d.ts} +9 -8
- package/dist/{types-BOSGNvil.d.ts → types-E3HrTPg2.d.ts} +7 -13
- package/dist/{types-C7HFvdtk.d.ts → types-VqL6t5HH.d.ts} +82 -5
- package/dist/{watch-B5RTR-WX.d.ts → watch-BTYOJpQU.d.ts} +18 -1
- package/dist/{words-DagJdwIA.d.ts → words-AHHfiaRY.d.ts} +31 -2
- package/dist/words-BGrHZAJJ.d.ts +46 -0
- package/dist/{words-c-3h9xQQ.d.ts → words-BMzV04b1.d.ts} +1 -1
- package/dist/words-CRYvAiHX.d.ts +105 -0
- package/dist/words-D8kf071T.d.ts +93 -0
- package/dist/{words-N4ebT88_.d.ts → words-DgHcY5qB.d.ts} +9 -3
- package/dist/{words-C74EUpFr.d.ts → words-XH0TvZPg.d.ts} +60 -4
- package/package.json +8 -8
- package/dist/chunk-66CKSTXP.js +0 -14
- package/dist/chunk-672FAEKU.js +0 -1
- package/dist/chunk-67VZRQLG.js +0 -13
- package/dist/chunk-6PS6STGA.js +0 -1
- package/dist/chunk-7A7O2JWQ.js +0 -1
- package/dist/chunk-7JTL3P6P.js +0 -1
- package/dist/chunk-F2PIG3AA.js +0 -10
- package/dist/chunk-H4B72XCJ.js +0 -1
- package/dist/chunk-KDIVA6WD.js +0 -1
- package/dist/chunk-MCLBHENY.js +0 -1
- package/dist/chunk-QB3BZIRA.js +0 -5
- package/dist/chunk-SJQG5ENJ.js +0 -1
- package/dist/chunk-SUO5627P.js +0 -1
- package/dist/chunk-XUE5O62R.js +0 -3
- package/dist/chunk-ZT7M24XD.js +0 -1
- package/dist/editor/index.d.ts +0 -10
- package/dist/editor/index.js +0 -1
- package/dist/words-CD3WADyb.d.ts +0 -51
- /package/dist/{chunk-2PHD4L6A.js → chunk-OWBO4WKA.js} +0 -0
package/dist/fields/fields.css
CHANGED
|
@@ -35,8 +35,13 @@
|
|
|
35
35
|
border-color: var(--es-accent);
|
|
36
36
|
box-shadow: 0 0 0 3px var(--es-accent-ring);
|
|
37
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. */
|
|
38
43
|
.es-fin[readonly],
|
|
39
|
-
.es-fin:disabled { background: var(--es-track-bg); color: var(--es-
|
|
44
|
+
.es-fin:disabled { background: var(--es-track-bg); color: var(--es-text-secondary); }
|
|
40
45
|
|
|
41
46
|
.es-fin--area {
|
|
42
47
|
height: auto;
|
|
@@ -75,7 +80,7 @@
|
|
|
75
80
|
border-color: var(--es-focus-line, #60a5fa);
|
|
76
81
|
box-shadow: 0 0 0 2px var(--es-focus-ring, rgba(96, 165, 250, 0.3));
|
|
77
82
|
}
|
|
78
|
-
.es-fnum.is-readonly { background: var(--es-track-bg); color: var(--es-
|
|
83
|
+
.es-fnum.is-readonly { background: var(--es-track-bg); color: var(--es-text-secondary); }
|
|
79
84
|
|
|
80
85
|
.es-fnum-icon { display: flex; align-items: center; flex: none; color: var(--es-field-placeholder); }
|
|
81
86
|
.es-fnum-icon svg { width: 14px; height: 14px; }
|
|
@@ -239,6 +244,90 @@
|
|
|
239
244
|
.es-fsel-option.is-active { background: var(--es-hover); }
|
|
240
245
|
.es-fsel-option.is-chosen { color: var(--es-accent-text); font-weight: 600; }
|
|
241
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; }
|
|
265
|
+
.es-fsel-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
266
|
+
.es-fsel-meta { flex: none; font-size: 11px; font-weight: 400; color: var(--es-muted); }
|
|
267
|
+
.es-fsel-thumb {
|
|
268
|
+
flex: none;
|
|
269
|
+
width: 26px;
|
|
270
|
+
height: 26px;
|
|
271
|
+
overflow: hidden;
|
|
272
|
+
border-radius: var(--es-field-radius);
|
|
273
|
+
background: var(--es-track-bg);
|
|
274
|
+
}
|
|
275
|
+
.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; }
|
|
242
331
|
|
|
243
332
|
/* ── the panel body: the tab strip and the rows (Inspector) ───────────────── */
|
|
244
333
|
|
|
@@ -260,9 +349,13 @@
|
|
|
260
349
|
.es-insp-row:empty,
|
|
261
350
|
.es-insp-row[hidden] { display: none; }
|
|
262
351
|
|
|
263
|
-
/* ── a list (ListField
|
|
352
|
+
/* ── a list (ListField): ONE look in both editors (owner, 2026-10-06) ────────
|
|
353
|
+
The website ticker's rows: one row per item, a × at its end, "+ Add <noun>"
|
|
354
|
+
under the last. The whole row drags (no grip); a many-field item opens under
|
|
355
|
+
its own row. Sizes from the ticker (.sf-textlist): a 32px row, a 28 × 32 ×.
|
|
356
|
+
Gaps are the spacing scale: 8 between rows (the seam IS the gap), 4 inside. */
|
|
264
357
|
|
|
265
|
-
.es-list { display: flex; flex-direction: column; gap: 8px; min-width: 0; margin-top: max(var(--es-row-gap), var(--es-rhythm-between)); }
|
|
358
|
+
.es-list { position: relative; display: flex; flex-direction: column; gap: 8px; min-width: 0; margin-top: max(var(--es-row-gap), var(--es-rhythm-between)); }
|
|
266
359
|
.es-list-head {
|
|
267
360
|
display: flex;
|
|
268
361
|
align-items: baseline;
|
|
@@ -270,52 +363,191 @@
|
|
|
270
363
|
gap: 8px;
|
|
271
364
|
}
|
|
272
365
|
.es-list-label { display: inline-flex; align-items: center; gap: 8px; font-size: 12px; font-weight: 600; color: var(--es-text); }
|
|
273
|
-
.es-list-count { font-size: 11px; color: var(--es-muted); }
|
|
274
|
-
/* The rows are Layers' rows (tree.css); the list lets them reach the panel's
|
|
275
|
-
edges the way Layers' do, so a row's hover reads as the same row. */
|
|
276
|
-
.es-list-tree { margin: 0 -8px; }
|
|
366
|
+
.es-list-count { font-size: 11px; color: var(--es-muted); font-variant-numeric: tabular-nums; }
|
|
277
367
|
|
|
278
|
-
.
|
|
368
|
+
/* A host's bar for the row in use, between the name and the rows. */
|
|
369
|
+
.es-list-above { min-width: 0; }
|
|
370
|
+
|
|
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,
|
|
373
|
+
and not Layers' `.es-tree` (which is one): the panel around the list scrolls.
|
|
374
|
+
Inside a scroll box of its own the drag hint under the last row was clipped
|
|
375
|
+
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; }
|
|
378
|
+
.es-list-entry { display: flex; flex-direction: column; min-width: 0; }
|
|
379
|
+
|
|
380
|
+
.es-list-row {
|
|
381
|
+
position: relative;
|
|
382
|
+
display: flex;
|
|
383
|
+
align-items: center;
|
|
384
|
+
gap: 4px;
|
|
385
|
+
min-width: 0;
|
|
386
|
+
min-height: 32px;
|
|
387
|
+
border-radius: var(--es-row-radius);
|
|
388
|
+
--es-row-scrim: var(--es-panel);
|
|
389
|
+
}
|
|
390
|
+
.es-list-row.is-draggable { cursor: grab; }
|
|
391
|
+
.es-list-row.is-item { padding-left: 8px; }
|
|
392
|
+
/* A row whose own control is not a text box (a name, a picture) reads as a row. */
|
|
393
|
+
.es-list-row.is-inline:not(:has(input, textarea, [contenteditable])) { padding-left: 8px; }
|
|
394
|
+
.es-list-row.is-inline:not(:has(input, textarea, [contenteditable])):hover { --es-row-scrim: var(--es-hover); background: var(--es-row-scrim); }
|
|
395
|
+
.es-list-row.is-item:hover,
|
|
396
|
+
.es-list-row.is-open { --es-row-scrim: var(--es-hover); background: var(--es-row-scrim); }
|
|
397
|
+
.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); }
|
|
399
|
+
.es-list-row:focus-visible { outline: 2px solid var(--es-accent); outline-offset: 1px; }
|
|
400
|
+
/* The one drop line, in the middle of the 8px gap — where a seam draws its own. */
|
|
401
|
+
.es-list-row.is-drop-before::before,
|
|
402
|
+
.es-list-row.is-drop-after::after {
|
|
403
|
+
content: "";
|
|
404
|
+
position: absolute;
|
|
405
|
+
left: 8px;
|
|
406
|
+
right: 8px;
|
|
407
|
+
height: 2px;
|
|
408
|
+
border-radius: 2px;
|
|
409
|
+
background: var(--es-accent);
|
|
410
|
+
pointer-events: none;
|
|
411
|
+
}
|
|
412
|
+
.es-list-row.is-drop-before::before { top: -5px; }
|
|
413
|
+
.es-list-row.is-drop-after::after { bottom: -5px; }
|
|
414
|
+
|
|
415
|
+
/* The row's own control (renderRow): it fills the row up to the ×. */
|
|
416
|
+
.es-list-row-main { flex: 1 1 auto; min-width: 0; min-height: 32px; display: flex; align-items: center; font-size: 12px; color: var(--es-text); }
|
|
417
|
+
.es-list-row-main > * { flex: 1 1 auto; min-width: 0; }
|
|
418
|
+
|
|
419
|
+
/* A many-field item: its name, its summary, a chevron that turns when open. */
|
|
420
|
+
.es-list-open {
|
|
421
|
+
flex: 1 1 auto;
|
|
422
|
+
min-width: 0;
|
|
423
|
+
display: flex;
|
|
424
|
+
align-items: center;
|
|
425
|
+
gap: 4px;
|
|
279
426
|
height: 32px;
|
|
280
|
-
|
|
281
|
-
border
|
|
427
|
+
padding: 0;
|
|
428
|
+
border: 0;
|
|
282
429
|
background: none;
|
|
283
|
-
color: var(--es-text
|
|
430
|
+
color: var(--es-text);
|
|
284
431
|
font: inherit;
|
|
285
432
|
font-size: 12px;
|
|
286
|
-
|
|
433
|
+
text-align: left;
|
|
434
|
+
cursor: inherit;
|
|
287
435
|
}
|
|
288
|
-
.es-list-
|
|
289
|
-
.es-list-
|
|
290
|
-
.es-list-
|
|
436
|
+
.es-list-open:focus-visible { outline: 2px solid var(--es-accent); outline-offset: 1px; border-radius: 4px; }
|
|
437
|
+
.es-list-thumb { flex: none; display: inline-flex; align-items: center; }
|
|
438
|
+
.es-list-row-name { flex: none; font-weight: 600; white-space: nowrap; }
|
|
439
|
+
.es-list-row-summary { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--es-muted); }
|
|
440
|
+
.es-list-chev { flex: none; color: var(--es-icon); transition: transform 0.12s; }
|
|
441
|
+
.es-list-row.is-open .es-list-chev { transform: rotate(90deg); }
|
|
291
442
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
443
|
+
.es-list-x {
|
|
444
|
+
flex: none;
|
|
445
|
+
width: 28px;
|
|
446
|
+
height: 32px;
|
|
447
|
+
border: 0;
|
|
448
|
+
border-radius: var(--es-row-radius);
|
|
449
|
+
background: transparent;
|
|
450
|
+
color: var(--es-muted);
|
|
451
|
+
font: inherit;
|
|
452
|
+
font-size: 16px;
|
|
453
|
+
line-height: 1;
|
|
454
|
+
cursor: pointer;
|
|
455
|
+
}
|
|
456
|
+
.es-list-x:hover:not(:disabled) { background: var(--es-danger-tint); color: var(--es-danger); }
|
|
457
|
+
.es-list-x:disabled { color: var(--es-disabled); cursor: default; }
|
|
458
|
+
.es-list-x:focus-visible { outline: 2px solid var(--es-accent); outline-offset: 2px; }
|
|
459
|
+
.es-list-lock {
|
|
460
|
+
flex: none;
|
|
461
|
+
width: 28px;
|
|
462
|
+
height: 32px;
|
|
296
463
|
display: inline-flex;
|
|
297
464
|
align-items: center;
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
465
|
+
justify-content: center;
|
|
466
|
+
color: var(--es-disabled);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/* What a draggable row says after 0.7 s on it — Layers' hint, never over a text box. */
|
|
470
|
+
.es-list-hint {
|
|
471
|
+
position: absolute;
|
|
472
|
+
left: 8px;
|
|
473
|
+
top: calc(100% + 4px);
|
|
474
|
+
z-index: 5;
|
|
475
|
+
padding: 4px 8px;
|
|
476
|
+
border-radius: 6px;
|
|
477
|
+
background: var(--es-toast-bg);
|
|
478
|
+
color: var(--es-on-accent);
|
|
479
|
+
font-size: 11px;
|
|
480
|
+
line-height: 1.3;
|
|
481
|
+
white-space: nowrap;
|
|
482
|
+
pointer-events: none;
|
|
483
|
+
opacity: 0;
|
|
484
|
+
transition: opacity 0.1s;
|
|
485
|
+
}
|
|
486
|
+
.es-list-row.is-draggable:hover:not(:has(input:hover, textarea:hover, [contenteditable]:hover)) .es-list-hint {
|
|
487
|
+
opacity: 1;
|
|
488
|
+
transition-delay: 0.7s;
|
|
489
|
+
}
|
|
490
|
+
.es-list-row.is-dragging .es-list-hint,
|
|
491
|
+
.es-list-row.is-lifting .es-list-hint { display: none; }
|
|
492
|
+
|
|
493
|
+
/* The open item, under its row: its own settings, indented on a hairline. */
|
|
494
|
+
.es-list-item {
|
|
495
|
+
display: flex;
|
|
496
|
+
flex-direction: column;
|
|
497
|
+
min-width: 0;
|
|
498
|
+
margin: 4px 0 8px 8px;
|
|
499
|
+
padding: 0 8px 4px 12px;
|
|
500
|
+
border-left: 2px solid var(--es-line);
|
|
501
|
+
}
|
|
502
|
+
.es-list-item > :first-child { margin-top: 0; }
|
|
503
|
+
|
|
504
|
+
.es-list-add {
|
|
505
|
+
align-self: flex-start;
|
|
506
|
+
padding: 4px 2px;
|
|
301
507
|
border: 0;
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
color: var(--es-text-secondary);
|
|
508
|
+
background: none;
|
|
509
|
+
color: var(--es-accent);
|
|
305
510
|
font: inherit;
|
|
306
511
|
font-size: 12px;
|
|
512
|
+
font-weight: 500;
|
|
307
513
|
cursor: pointer;
|
|
308
514
|
}
|
|
309
|
-
.es-list-
|
|
310
|
-
.es-list-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
}
|
|
317
|
-
.es-list-title { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
|
|
318
|
-
.es-list-name { font-size: 14px; font-weight: 600; color: var(--es-text); }
|
|
319
|
-
.es-list-item { min-width: 0; }
|
|
320
|
-
.es-list-item-actions { display: flex; gap: 8px; margin-top: 8px; }
|
|
515
|
+
.es-list-add:hover:not(:disabled) { text-decoration: underline; }
|
|
516
|
+
.es-list-add:disabled { color: var(--es-disabled); cursor: default; }
|
|
517
|
+
.es-list-add:focus-visible { outline: 2px solid var(--es-accent); outline-offset: 2px; }
|
|
518
|
+
|
|
519
|
+
/* Read out after a move; never seen. */
|
|
520
|
+
.es-list-said { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
|
|
521
|
+
|
|
321
522
|
.es-fbtn--danger { color: var(--es-danger); }
|
|
523
|
+
|
|
524
|
+
/* ── the link picker (LinkPicker, [MERGE] One Link Picker For Both Editors) ──
|
|
525
|
+
The mockup's stack (owner, 2026-10-06): Link type, the target, and on the
|
|
526
|
+
listing Filter and Value — one box under the next, the whole width of the
|
|
527
|
+
row, 8px apart (the spacing scale). The same stack at 320px and at 220px:
|
|
528
|
+
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. */
|
|
531
|
+
.es-flink {
|
|
532
|
+
display: flex;
|
|
533
|
+
flex-direction: column;
|
|
534
|
+
gap: 8px;
|
|
535
|
+
min-width: 0;
|
|
536
|
+
}
|
|
537
|
+
/* Inside a SettingsField the slot is a flex ROW, and a column box written for
|
|
538
|
+
a block row sizes to its own content there (291px became 117px in the shop
|
|
539
|
+
when its link stack sat in the slot). Fill the slot instead. */
|
|
540
|
+
.es-field-ctl > .es-flink {
|
|
541
|
+
flex: 1 1 auto;
|
|
542
|
+
}
|
|
543
|
+
.es-flink > .es-fin[aria-invalid='true'] {
|
|
544
|
+
border-color: var(--es-danger);
|
|
545
|
+
}
|
|
546
|
+
.es-flink-error,
|
|
547
|
+
.es-flink-hint {
|
|
548
|
+
margin: 0;
|
|
549
|
+
font-size: 11px;
|
|
550
|
+
line-height: 1.45;
|
|
551
|
+
}
|
|
552
|
+
.es-flink-error { color: var(--es-danger); }
|
|
553
|
+
.es-flink-hint { color: var(--es-muted); }
|
package/dist/fields/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode, KeyboardEvent } from 'react';
|
|
3
3
|
import { S as SettingsBucket } from '../buckets-CuLM47h9.js';
|
|
4
|
-
import { I as InspectorFields, a as InspectorFieldDef, F as FieldRenderer, b as FieldTextProps, c as FieldNumberProps, d as FieldSliderProps, e as
|
|
5
|
-
export { A as ArrayFieldDef, C as CustomFieldDef,
|
|
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
|
+
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
|
-
export { F as FieldsWords } from '../words-
|
|
7
|
+
export { F as FieldsWords } from '../words-D8kf071T.js';
|
|
8
8
|
import '../types-41704JE4.js';
|
|
9
9
|
|
|
10
10
|
interface InspectorProps {
|
|
@@ -98,7 +98,14 @@ interface PlannedRow {
|
|
|
98
98
|
bucket: SettingsBucket;
|
|
99
99
|
}
|
|
100
100
|
interface FieldPlan {
|
|
101
|
-
/**
|
|
101
|
+
/**
|
|
102
|
+
* Every field that is not a marker and not hidden, in the order declared.
|
|
103
|
+
*
|
|
104
|
+
* ⚠️ A `slot` field is among them and draws NOTHING: it is here so its name
|
|
105
|
+
* has a bucket (`bucketsOf`), and `Inspector` leaves it mounted but empty.
|
|
106
|
+
* A host that draws rows of its own, or counts them ("3 settings"), filters
|
|
107
|
+
* `row.field.type !== 'slot'` first. `buckets` already leaves slots out.
|
|
108
|
+
*/
|
|
102
109
|
rows: PlannedRow[];
|
|
103
110
|
/** The tabs to offer: the buckets that hold a row, in the owner's order. */
|
|
104
111
|
buckets: SettingsBucket[];
|
|
@@ -171,26 +178,37 @@ declare function useResolvedFields({ id, node, block, parent, appState }: Resolv
|
|
|
171
178
|
};
|
|
172
179
|
|
|
173
180
|
/**
|
|
174
|
-
* A LIST VALUE
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
*
|
|
178
|
-
*
|
|
181
|
+
* A LIST VALUE — slides, buttons, links, lines of copy, any `array` field —
|
|
182
|
+
* drawn ONE way in both editors (owner, 2026-10-06: "the ticker look"). One row
|
|
183
|
+
* per item with a × at its end, and "+ Add <noun>" under the last row.
|
|
184
|
+
*
|
|
185
|
+
* one field `renderRow` puts the host's own control IN the row (the
|
|
186
|
+
* ticker's text box): nothing to open, the item is edited where
|
|
187
|
+
* it stands;
|
|
188
|
+
* many fields the row is the item's name and summary; pressing it opens the
|
|
189
|
+
* item IN PLACE, under its row, one at a time (the owner's pick
|
|
190
|
+
* A of the 2026-10-06 mockup — the drill-in page is gone).
|
|
179
191
|
*
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
192
|
+
* REORDER IS NEVER CUT TO FIT THE LOOK. The WHOLE ROW drags — no grip (owner,
|
|
193
|
+
* 2026-09-29) — a text box in it too, until the caret is in that box: from
|
|
194
|
+
* then on a press there selects text. Alt+↑ /
|
|
195
|
+
* Alt+↓ move it from the keyboard, the caret in the text box included, and the
|
|
196
|
+
* caret goes with the item. The right-click menu (or Shift+F10) offers Move up,
|
|
197
|
+
* Move down, Duplicate and Delete, and only what the row can do. The count, the
|
|
198
|
+
* "+" between two rows and Duplicate stay, as Layers keeps them.
|
|
185
199
|
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
200
|
+
* THE DATA DOES NOT CHANGE: a list is the array the document stored, and every
|
|
201
|
+
* write is that array with an item added, moved, copied, changed or taken out.
|
|
202
|
+
* No id is added to an item; a row's key is its position.
|
|
188
203
|
*
|
|
189
|
-
*
|
|
190
|
-
*
|
|
204
|
+
* CONTROLLED, the list and which item is open: the Inspector holds them, so an
|
|
205
|
+
* editor can keep the open item across a re-render of the panel.
|
|
206
|
+
*
|
|
207
|
+
* Its words are the strings provider's — `EaselStrings.fields.list` and
|
|
208
|
+
* `.tree` — English with none.
|
|
191
209
|
*/
|
|
192
210
|
interface ListFieldProps<T> {
|
|
193
|
-
/** The list's name, e.g. "Slides".
|
|
211
|
+
/** The list's name, e.g. "Slides". */
|
|
194
212
|
label: string;
|
|
195
213
|
/** A glyph before the name, as a settings row wears one. */
|
|
196
214
|
icon?: ReactNode;
|
|
@@ -209,11 +227,37 @@ interface ListFieldProps<T> {
|
|
|
209
227
|
min?: number;
|
|
210
228
|
max?: number;
|
|
211
229
|
readOnly?: boolean;
|
|
212
|
-
/** The item open
|
|
230
|
+
/** The item open under its row, by position, or null. */
|
|
213
231
|
open: number | null;
|
|
214
232
|
onOpen: (index: number | null) => void;
|
|
215
|
-
/** The open item's own settings. `change` writes the item. */
|
|
233
|
+
/** The open item's own settings, drawn under its row. `change` writes the item. */
|
|
216
234
|
renderItem: (item: T, index: number, change: (next: T) => void) => ReactNode;
|
|
235
|
+
/**
|
|
236
|
+
* The row's own control, for an item that is ONE value (a line of copy): the
|
|
237
|
+
* row holds it, and nothing opens. `change` writes the item.
|
|
238
|
+
*/
|
|
239
|
+
renderRow?: (item: T, index: number, change: (next: T) => void) => ReactNode;
|
|
240
|
+
/** May this item be taken out? False: no ×, a lock, no Delete — it still moves (the email's Unsubscribe). */
|
|
241
|
+
canRemove?: (item: T, index: number) => boolean;
|
|
242
|
+
/** Why a locked item cannot be taken out — the lock's tooltip. Default `fields.list.locked`. */
|
|
243
|
+
lockedReason?: (item: T, index: number) => string;
|
|
244
|
+
/** A set that is never added to or taken from (the phone column order): it only moves. */
|
|
245
|
+
fixed?: boolean;
|
|
246
|
+
/**
|
|
247
|
+
* False: an item is deleted INSIDE (its own page, as a Locations group is),
|
|
248
|
+
* never from its row — no ×, no lock, no Delete in the menu. Default true.
|
|
249
|
+
*/
|
|
250
|
+
removeOnRow?: boolean;
|
|
251
|
+
/** May this item be copied? False: no Duplicate in the menu (a copy that would merge with its original). Default: yes. */
|
|
252
|
+
canDuplicate?: (item: T, index: number) => boolean;
|
|
253
|
+
/** Drawn once, under the list's name and above its rows — a bar that acts on the row in use (the ticker's formatting bar). */
|
|
254
|
+
above?: ReactNode;
|
|
255
|
+
/**
|
|
256
|
+
* False: no head of the list's own — the host draws the list inside a
|
|
257
|
+
* settings row that already names it (a `SettingsField` with its glyph and
|
|
258
|
+
* hint), and shows the count in that row's `value`. Default true.
|
|
259
|
+
*/
|
|
260
|
+
head?: boolean;
|
|
217
261
|
}
|
|
218
262
|
/** The list with `item` put at `index`. */
|
|
219
263
|
declare function insertAt<T>(items: readonly T[], index: number, item: T): T[];
|
|
@@ -226,7 +270,7 @@ declare function removeAt<T>(items: readonly T[], index: number): T[];
|
|
|
226
270
|
* writes through to the original (a list item is JSON — Puck stored it so).
|
|
227
271
|
*/
|
|
228
272
|
declare function copyItem<T>(item: T): T;
|
|
229
|
-
declare function ListField<T>({ label, icon, noun: ownNoun, items, onChange, newItem, summary, itemName, thumb, min, max, readOnly, open, onOpen, renderItem, }: ListFieldProps<T>): react.JSX.Element;
|
|
273
|
+
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;
|
|
230
274
|
|
|
231
275
|
/**
|
|
232
276
|
* A text value: the shell's own box, one line or several (blueprint step 4.1,
|
|
@@ -290,7 +334,7 @@ declare function useNumberEntry({ value, onChange, min, max, step, shiftStep, st
|
|
|
290
334
|
* small stacked arrows. What the typing, the keys and the arrows do is
|
|
291
335
|
* {@link useNumberEntry}'s.
|
|
292
336
|
*/
|
|
293
|
-
declare function FieldNumber({ id, value, onChange, min, max, step, shiftStep, styleValue, icon, unit, steppers, placeholder, readOnly, ariaLabel, ariaLabelledBy, }: FieldNumberProps): react.JSX.Element;
|
|
337
|
+
declare function FieldNumber({ id, value, onChange, min, max, step, shiftStep, styleValue, icon, unit, steppers, placeholder, readOnly, ariaLabel, ariaLabelledBy, title, }: FieldNumberProps): react.JSX.Element;
|
|
294
338
|
|
|
295
339
|
/**
|
|
296
340
|
* A slider row (plan step E4), for Site styles and Email styles: the name on
|
|
@@ -300,8 +344,14 @@ declare function FieldNumber({ id, value, onChange, min, max, step, shiftStep, s
|
|
|
300
344
|
* cell does — it is the same {@link useNumberEntry} — and may go past the
|
|
301
345
|
* slider's own travel (`sliderMin` / `sliderMax`); only `min` / `max` hold it.
|
|
302
346
|
* The slider then rests at its end. A grey value follows the style.
|
|
347
|
+
*
|
|
348
|
+
* `auto` (plan step E6, Site styles) is the word for "no number: each section
|
|
349
|
+
* draws its own". The design puts it ON the slider: one spot left of its
|
|
350
|
+
* travel is Auto, and the value reads the word, grey, with no unit. Dragged there, the row
|
|
351
|
+
* writes `undefined`; ↑ from Auto starts at `sliderMin` (one more than Auto is
|
|
352
|
+
* the slider's first number, not `min`), ↓ stays; an emptied box is Auto too.
|
|
303
353
|
*/
|
|
304
|
-
declare function FieldSlider({ id, label, value, onChange, min, max, step, shiftStep, styleValue, unit, sliderMin, sliderMax, readOnly, }: FieldSliderProps): react.JSX.Element;
|
|
354
|
+
declare function FieldSlider({ id, label, value, onChange, min, max, step, shiftStep, styleValue, unit, sliderMin, sliderMax, auto, readOnly, }: FieldSliderProps): react.JSX.Element;
|
|
305
355
|
|
|
306
356
|
/** The option a stored value names: equal by `Object.is`, so `0`, `false` and `''` are values too. */
|
|
307
357
|
declare function optionFor<V>(options: readonly FieldOption<V>[], value: V | undefined): FieldOption<V> | undefined;
|
|
@@ -315,7 +365,140 @@ declare function optionFor<V>(options: readonly FieldOption<V>[], value: V | und
|
|
|
315
365
|
* button its focus back, a letter jumps to the next option that starts with it.
|
|
316
366
|
* A click outside closes it (a CLICK, not a pointerdown: closing early moves the
|
|
317
367
|
* row and loses the press — the colour row learned that in 4.6).
|
|
368
|
+
*
|
|
369
|
+
* Options may sit under headings (`FieldOption.group`, `<optgroup>`'s job): a
|
|
370
|
+
* heading is a `role="group"`'s name, never an option, so the keys and a click
|
|
371
|
+
* pass it by. Without groups the list is exactly the flat one it always was.
|
|
372
|
+
*
|
|
373
|
+
* THE EDITOR'S ONE POP-UP LIST (card [MERGE] One Pop-up List For Editor And One
|
|
374
|
+
* For Shoppers, 2026-10-06). What the website editor's own lists did is here,
|
|
375
|
+
* each optional, and a list that asks for none draws what it always drew:
|
|
376
|
+
*
|
|
377
|
+
* searchable a search box at the top of the open list. It has the focus;
|
|
378
|
+
* letters go into it (no letter jump), ↓ ↑ walk what is left,
|
|
379
|
+
* Enter chooses, Escape closes. Home and End stay the box's.
|
|
380
|
+
* multiple several values. Enter, Space or a click ticks one and the list
|
|
381
|
+
* STAYS open; the save is in the options' order.
|
|
382
|
+
* thumb, meta a picture column and a quiet fact on the option.
|
|
383
|
+
* groupCount a heading says how many of its options are showing.
|
|
384
|
+
* renderOption / renderValue the host draws a row's or the button's content.
|
|
385
|
+
* inline the list opens in flow, for a panel that scrolls.
|
|
386
|
+
*
|
|
387
|
+
* THE OPEN LIST ALWAYS HAS A NAME (second host, 2026-10-07): the host's
|
|
388
|
+
* `ariaLabelledBy`, else its `ariaLabel`, else the BUTTON that opened it —
|
|
389
|
+
* which the row's `<label for>` names. Until then a list given neither was a
|
|
390
|
+
* `role="listbox"` with no accessible name (axe `aria-input-field-name`), and
|
|
391
|
+
* the engine's own settings row gave neither.
|
|
392
|
+
*/
|
|
393
|
+
declare function FieldSelect<V>(props: FieldSelectManyProps<V>): ReactNode;
|
|
394
|
+
declare function FieldSelect<V>(props: FieldSelectOneProps<V>): ReactNode;
|
|
395
|
+
|
|
396
|
+
/** One thing a link can point at: the URL it writes and the name it shows. */
|
|
397
|
+
type LinkOption = {
|
|
398
|
+
value: string;
|
|
399
|
+
label: string;
|
|
400
|
+
};
|
|
401
|
+
/** Options under one heading — the anchors of one page. */
|
|
402
|
+
type LinkOptionGroup = {
|
|
403
|
+
label: string;
|
|
404
|
+
options: readonly LinkOption[];
|
|
405
|
+
};
|
|
406
|
+
/** One filter on a link onto the product listing, or none. */
|
|
407
|
+
type LinkFilter = {
|
|
408
|
+
param: string;
|
|
409
|
+
value: string;
|
|
410
|
+
} | null;
|
|
411
|
+
/** A filter a listing link may offer, with the values it may take. */
|
|
412
|
+
type LinkFilterField = {
|
|
413
|
+
param: string;
|
|
414
|
+
label: string;
|
|
415
|
+
values: readonly LinkOption[];
|
|
416
|
+
};
|
|
417
|
+
/** What a kind's target box is: a list, a list in groups, or a typed address. */
|
|
418
|
+
type LinkTarget = {
|
|
419
|
+
type: 'select';
|
|
420
|
+
options: readonly LinkOption[];
|
|
421
|
+
placeholder: string;
|
|
422
|
+
} | {
|
|
423
|
+
type: 'groups';
|
|
424
|
+
groups: readonly LinkOptionGroup[];
|
|
425
|
+
placeholder: string;
|
|
426
|
+
} | {
|
|
427
|
+
type: 'text';
|
|
428
|
+
};
|
|
429
|
+
/** One entry of the Link type list, with everything its target box offers. */
|
|
430
|
+
type LinkKindChoice = {
|
|
431
|
+
/** The kind's key — what `rules.kindOf` answers. */
|
|
432
|
+
value: string;
|
|
433
|
+
/** Its name in the list ("Page", "Blog post"), and its target box's name. */
|
|
434
|
+
label: string;
|
|
435
|
+
target: LinkTarget;
|
|
436
|
+
/** A quiet line under the boxes while this kind is chosen. */
|
|
437
|
+
hint?: string;
|
|
438
|
+
/** Left out of the list while its target has nothing to pick — unless the
|
|
439
|
+
* saved link is this kind, so a link is never shown as something it is not. */
|
|
440
|
+
hideWhenEmpty?: boolean;
|
|
441
|
+
};
|
|
442
|
+
/**
|
|
443
|
+
* Everything the picker needs to know about a URL — and it knows nothing else.
|
|
444
|
+
* A host hands in its own rules (the storefront's come from
|
|
445
|
+
* `efficient-web-builder/links`), so a new kind or a new filter never changes
|
|
446
|
+
* this file.
|
|
447
|
+
*/
|
|
448
|
+
type LinkRules = {
|
|
449
|
+
/** Which kind a saved URL is. */
|
|
450
|
+
kindOf: (url: string) => string;
|
|
451
|
+
/** The target a URL points at, with any listing filter taken off. */
|
|
452
|
+
targetOf: (url: string) => string;
|
|
453
|
+
/** The filter a URL carries onto the listing, or null. */
|
|
454
|
+
readFilter: (url: string) => LinkFilter;
|
|
455
|
+
/** The URL of a target with this filter written on (or cleared). */
|
|
456
|
+
withFilter: (url: string, filter: LinkFilter) => string;
|
|
457
|
+
/** May this typed address be saved? */
|
|
458
|
+
isSafe: (url: string) => boolean;
|
|
459
|
+
};
|
|
460
|
+
type LinkPickerProps = {
|
|
461
|
+
/** The saved link, or `''`. */
|
|
462
|
+
value: string;
|
|
463
|
+
/**
|
|
464
|
+
* The new link, and — when a thing was PICKED — its name, so a host can fill
|
|
465
|
+
* its own label with it (the admin's menu item does). No name when the link
|
|
466
|
+
* was typed or cleared.
|
|
467
|
+
*/
|
|
468
|
+
onChange: (url: string, name?: string) => void;
|
|
469
|
+
/** The Link type list, in order, each with what its target box offers. */
|
|
470
|
+
kinds: readonly LinkKindChoice[];
|
|
471
|
+
rules: LinkRules;
|
|
472
|
+
/**
|
|
473
|
+
* The filters a link onto this target may carry, or null when the target is
|
|
474
|
+
* not the product listing. Asked only for a kind whose target is a list.
|
|
475
|
+
*/
|
|
476
|
+
filtersFor?: (target: string) => readonly LinkFilterField[] | null;
|
|
477
|
+
/** The whole control's accessible name — "Button link", "Where “Wheels” goes". */
|
|
478
|
+
label?: string;
|
|
479
|
+
readOnly?: boolean;
|
|
480
|
+
};
|
|
481
|
+
/**
|
|
482
|
+
* ONE LINK PICKER ([MERGE] One Link Picker For Both Editors, owner
|
|
483
|
+
* 2026-10-06; mockup https://claude.ai/artifact/6mVmY5787gnXdSWP3syqhu v4): a
|
|
484
|
+
* type — Page / Anchor / Blog post / Product / Custom URL — then which one; on
|
|
485
|
+
* the product listing a Filter and then a Value. The website editor's Link
|
|
486
|
+
* field and the admin's menu item draw this same control.
|
|
487
|
+
*
|
|
488
|
+
* IT HOLDS NO URL RULE. Which kind a link is, which page it points at, what
|
|
489
|
+
* filter it carries and how one is written, which typed address is unsafe —
|
|
490
|
+
* all of it is `rules`, and every option and every name is the host's. Only
|
|
491
|
+
* the order of the boxes and how they answer each other is decided here.
|
|
492
|
+
*
|
|
493
|
+
* It never writes on its own. Opening a saved link writes nothing; a target,
|
|
494
|
+
* filter or value the host no longer offers is shown as "(unavailable)" and
|
|
495
|
+
* kept, never silently replaced.
|
|
496
|
+
*
|
|
497
|
+
* Every list is `FieldSelect`, the editor's one pop-up list — the anchors
|
|
498
|
+
* under one heading per page (`FieldOption.group`), a long list with a search
|
|
499
|
+
* box — never the browser's `<select>`. The boxes stack, one under the next,
|
|
500
|
+
* at every panel width.
|
|
318
501
|
*/
|
|
319
|
-
declare function
|
|
502
|
+
declare function LinkPicker({ value, onChange, kinds, rules, filtersFor, label, readOnly }: LinkPickerProps): react.JSX.Element | null;
|
|
320
503
|
|
|
321
|
-
export { FieldNumber, FieldNumberProps, FieldOption, type FieldPlan, FieldRenderer, FieldSelect,
|
|
504
|
+
export { FieldNumber, FieldNumberProps, FieldOption, type FieldPlan, FieldRenderer, FieldSelect, FieldSelectManyProps, FieldSelectOneProps, FieldSlider, FieldSliderProps, FieldText, FieldTextProps, type FieldsBlock, Inspector, InspectorField, InspectorFieldDef, type InspectorFieldProps, InspectorFields, type InspectorProps, type LinkFilter, type LinkFilterField, type LinkKindChoice, type LinkOption, type LinkOptionGroup, LinkPicker, type LinkPickerProps, type LinkRules, type LinkTarget, ListField, type ListFieldProps, type NumberEntryOptions, type PlannedRow, type ResolvedFieldsInput, SettingsBucket, bucketsOf, clampNumber, copyItem, insertAt, labelOf, moveTo, optionFor, parseTyped, planFields, removeAt, useNumberEntry, useResolvedFields };
|