@wildwinter/app-shell 0.56.0 → 0.57.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 CHANGED
@@ -327,6 +327,26 @@ fold.sweep(); // after each redraw, beside the rows' own sweep
327
327
 
328
328
  Project Settings shouldn't fold: it's where an author goes to set things.
329
329
 
330
+ ## v0.57 (a map of records as a grid)
331
+
332
+ **`@wildwinter/app-shell/value-rows`**, for a map whose values are records (an
333
+ extension's per-character performance, say), too big for an inspector's column:
334
+
335
+ - `isRecordMap(decl)`: which fields these are, from the declaration alone.
336
+ - `recordMapSummary(decl, value, adapter)`: a line per key, "TAM: smile, nod",
337
+ the record's set values as their controls show them (`valueText`); for the
338
+ inspector, beside an Edit button.
339
+ - `recordMapGrid({ decl, value, adapter, onCommit, disabled })`: the grid a
340
+ helper window draws, a row per key and a column per record field, each cell
341
+ the row value-rows draws for that field (picks, checks and problems
342
+ included), a remove button per row and the key adder under it. `onCommit`
343
+ gets the whole map. Cells keep their elements across `update`. Styles in
344
+ `controls.css`.
345
+
346
+ **`selectionFollowButton`** (tool-window kit): "Follow selection", for a helper
347
+ window that shows whatever the editor has selected. The other direction from
348
+ `followButton` ("Follow in the editor"), so it has its own words.
349
+
330
350
  ## Roadmap
331
351
 
332
352
  Later slices lift the rest of the common shell from Patterpad (canonical),
package/dist/controls.css CHANGED
@@ -377,4 +377,56 @@ kbd {
377
377
  .shell-fold-body:empty {
378
378
  display: none;
379
379
  }
380
+ .shell-recordgrid-table {
381
+ width: 100%;
382
+ border-collapse: collapse;
383
+ }
384
+ .shell-recordgrid-table th {
385
+ font: 600 12px/1.3 var(--font-ui);
386
+ color: var(--muted);
387
+ text-align: left;
388
+ padding: 4px 6px;
389
+ vertical-align: top;
390
+ }
391
+ .shell-recordgrid-table td {
392
+ padding: 3px 6px;
393
+ vertical-align: top;
394
+ }
395
+ .shell-recordgrid-table tbody tr {
396
+ border-top: 1px solid var(--line);
397
+ }
398
+ .shell-recordgrid-table th.shell-recordgrid-key {
399
+ color: var(--ink);
400
+ padding-top: 9px;
401
+ white-space: nowrap;
402
+ }
403
+ .shell-recordgrid-gone {
404
+ color: var(--danger);
405
+ font-weight: 400;
406
+ }
407
+ .shell-recordgrid-tools {
408
+ width: 1%;
409
+ white-space: nowrap;
410
+ }
411
+ .shell-recordgrid-cell {
412
+ display: block;
413
+ }
414
+ .shell-recordgrid-cell > .shell-fieldrow-label,
415
+ .shell-recordgrid-cell .shell-fieldrow-purpose,
416
+ .shell-recordgrid-cell .shell-fieldrow-valuehelp {
417
+ display: none;
418
+ }
419
+ .shell-recordgrid-cell select,
420
+ .shell-recordgrid-cell input {
421
+ width: 100%;
422
+ min-width: 7em;
423
+ }
424
+ .shell-recordgrid-empty {
425
+ margin: 6px 0;
426
+ font: 12.5px/1.4 var(--font-ui);
427
+ color: var(--muted);
428
+ }
429
+ .shell-recordgrid-add {
430
+ margin-top: 8px;
431
+ }
380
432
  /*# sourceMappingURL=controls.css.map */
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/controls.css"],"sourcesContent":["/* ============================================================================\n The family's control grammar: one button, one field, one segmented control,\n one pill, one empty-state line, one keycap. Class-scoped throughout, never\n an element reset: a stylesheet that restyles every <button> in a window is a\n blast radius, and the two apps had five spellings of \"primary button\" using\n four foreground tokens between them (ui-review-2026-09, finding 20).\n\n Reads the token grammar (tokens.css) and the app's palette (--surface,\n --card, --ink, --muted, --line, --accent, --danger, --on-accent; optional\n --accent-soft, --line-soft, --font-mono). The keyboard focus ring is the\n family's one rule in tokens.css, so nothing here draws another.\n\n \"Controls have edges\" (design-language.md, 2026-09-16): a button has a\n border or a fill at rest, and text a person can read without hovering.\n Ghost styling is ONLY for icon-only toolbar buttons in a bar that is itself\n the affordance. And \"Motion is interpolation\", as amended: the only thing\n that transitions on hover is colour, at --dur-quick. No lift, no shadow\n change, no scale.\n ============================================================================ */\n\n/* --- buttons ---------------------------------------------------------------- */\n.btn {\n display: inline-flex; align-items: center; justify-content: center; gap: 0.35em;\n padding: 5px 11px;\n border: 1px solid var(--line); border-radius: var(--radius-sm);\n background: var(--surface); color: var(--ink);\n font: 600 12.5px var(--font-ui); letter-spacing: 0.02em; line-height: 1.2;\n cursor: pointer; white-space: nowrap;\n -webkit-user-select: none; user-select: none;\n transition: color var(--dur-quick) var(--ease-standard),\n background var(--dur-quick) var(--ease-standard),\n border-color var(--dur-quick) var(--ease-standard);\n}\n.btn:hover:not(:disabled) {\n border-color: var(--accent);\n background: var(--accent-soft, color-mix(in oklab, var(--accent) 10%, transparent));\n}\n.btn:disabled { opacity: 0.45; cursor: default; }\n\n/* The one action a dialog or a bar is for: accent fill, the palette's own ink\n on it (never a raw white, which read white-on-tan on the dark palettes). */\n.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }\n.btn.primary:hover:not(:disabled) {\n background: color-mix(in oklab, var(--accent) 88%, var(--ink));\n border-color: color-mix(in oklab, var(--accent) 88%, var(--ink));\n color: var(--on-accent);\n}\n\n/* The destructive action, and it names its object (\"Delete scene\"). */\n.btn.danger { background: var(--danger); border-color: var(--danger); color: var(--surface); }\n.btn.danger:hover:not(:disabled) {\n background: color-mix(in oklab, var(--danger) 88%, var(--ink));\n border-color: color-mix(in oklab, var(--danger) 88%, var(--ink));\n color: var(--surface);\n}\n\n/* ONLY for an icon-only button in a toolbar: borderless, muted, a wash on\n hover. A text action drawn this way is the \"bare muted text on the ground\"\n the design language rules out. */\n.btn.ghost { border-color: transparent; background: none; color: var(--muted); }\n.btn.ghost:hover:not(:disabled) {\n border-color: transparent; color: var(--ink);\n background: var(--accent-soft, color-mix(in oklab, var(--accent) 10%, transparent));\n}\n\n/* A square button holding one glyph, centred explicitly: a bare <button>\n centres by the font's metrics plus UA padding, which parks an arrow up-left\n of the square's visual centre. */\n.btn.icon { width: 28px; height: 28px; padding: 0; line-height: 1; font-size: 13.5px; }\n\n/* --- fields ----------------------------------------------------------------- */\n.field {\n font: inherit; font-size: 13.5px; line-height: 1.4;\n padding: 6px 9px;\n border: 1px solid var(--line); border-radius: var(--radius-sm);\n background: var(--card); color: var(--ink);\n -webkit-user-select: text; user-select: text;\n transition: border-color var(--dur-quick) var(--ease-standard);\n}\n.field:focus-visible { border-color: var(--accent); outline-offset: 0; }\n/* A placeholder is a hint, not content: lighter and italic, its opacity\n pinned so no engine fades an already-muted colour a second time. */\n.field::placeholder { color: var(--muted); font-style: italic; opacity: 1; }\n/* `.invalid` is the dup guard's (a value that clashes with another row);\n `.illegal` is a value that breaks a rule. Both can be true at once, so they\n are separate classes that draw the same. */\n.field.invalid, .field.illegal { border-color: var(--danger); }\n.field:disabled { opacity: 0.55; cursor: default; }\ntextarea.field { resize: vertical; }\n\n/* --- segmented control ------------------------------------------------------ */\n/* One bordered strip, options divided by hairlines, the chosen one washed. Seven\n hand-rolled copies across the two apps agreed on everything but the radius\n (finding 21); this is the one they converge on. */\n.seg { display: inline-flex; border: 1px solid var(--line); border-radius: var(--radius-sm); overflow: hidden; }\n.seg-opt {\n background: none; border: 0; cursor: pointer;\n color: var(--muted); font: 600 12px var(--font-ui); padding: 3px 9.5px; white-space: nowrap;\n transition: color var(--dur-quick) var(--ease-standard), background var(--dur-quick) var(--ease-standard);\n}\n.seg-opt + .seg-opt { border-left: 1px solid var(--line); }\n.seg-opt:hover:not(.on) { color: var(--ink); }\n.seg-opt.on {\n color: var(--accent); cursor: default;\n background: var(--accent-soft, color-mix(in oklab, var(--accent) 14%, transparent));\n}\n\n/* A quality's value as its ladder (value-control.ts rungStrip): the rungs in order, the current one marked.\n Stage names keep the mono voice values use. An unset value's fallback rung is marked quietly; a value that\n is no longer a stage is shown after the ladder, in the warning colour, until a rung is picked. */\n.shell-rungs { flex-wrap: wrap; }\n.shell-rung { font-family: var(--font-mono); font-weight: 400; padding: 2px 7px; }\n.shell-rung.on { font-weight: 600; }\n.shell-rung.fallback { color: var(--ink); text-decoration: underline dotted; text-underline-offset: 3px; }\n.shell-rung-default { font-family: var(--font-ui); }\n.shell-rung.stray { color: var(--warn, var(--danger, var(--accent))); text-decoration: line-through; cursor: default; }\nspan.shell-rung { cursor: default; }\n\n/* A declared field's value as a row (value-control.ts fieldRow): the caption, then the control with the\n purpose and any message under it. The grid is the app's (it passes its own row class); these are the\n parts both apps share. A flags value is a picker of the declared values: chips, the set ones washed. */\n.shell-fieldrow-body { display: flex; flex-direction: column; align-items: flex-start; gap: 3px; min-width: 0; }\n.shell-fieldrow-textual .shell-fieldrow-body { align-items: stretch; }\n.shell-fieldrow-text { min-width: 0; }\ntextarea.shell-fieldrow-text { min-height: 3.6em; font-family: inherit; line-height: 1.4; }\n.shell-fieldrow-purpose { margin: 0; font: 12px/1.4 var(--font-ui); color: var(--muted); max-width: 60ch; }\n.shell-fieldrow-problem { margin: 0; font: 12px/1.4 var(--font-ui); color: var(--warn, var(--danger, var(--accent))); }\n.shell-fieldrow.has-problem .shell-fieldrow-text { border-color: var(--warn, var(--danger)); }\n.shell-flags { display: inline-flex; flex-wrap: wrap; gap: 4px; }\n.shell-flag {\n display: inline-flex; align-items: center; border: 1px solid var(--line); border-radius: var(--radius-pill);\n background: none; color: var(--muted); font: 12px var(--font-mono); padding: 1px 8px; cursor: pointer;\n}\n.shell-flag:hover:not(.on):not(span) { color: var(--ink); }\n.shell-flag.on { color: var(--accent); border-color: var(--accent); background: var(--accent-soft, color-mix(in oklab, var(--accent) 14%, transparent)); }\n.shell-flag.fallback { color: var(--ink); border-style: dashed; background: none; }\n.shell-flag-default { font-family: var(--font-ui); }\n.shell-flag-default.on { cursor: default; }\n.shell-flag.stray { color: var(--warn, var(--danger, var(--accent))); border-color: currentColor; background: none; text-decoration: line-through; }\nspan.shell-flag { cursor: default; }\n\n/* --- small things ----------------------------------------------------------- */\n/* A pill: a small bordered label (a class, a count, a state). */\n.pill {\n display: inline-flex; align-items: center; gap: 4px;\n font: 11.5px/1.3 var(--font-ui); color: var(--muted);\n border: 1px solid var(--line-soft, var(--line)); border-radius: var(--radius-pill);\n padding: 1px 7px; white-space: nowrap;\n}\n\n/* The inline empty state: one muted italic sentence where a list would be. */\n.empty { margin: 0; color: var(--muted); font: italic 13px/1.45 var(--font-ui); }\n\n/* A keycap. A key hint is an element, never a typed \"↑↓ move\" string. The\n element rule is the floor for a hand-written <kbd>; the shell's own hint\n helpers (keys.ts) stamp `.shell-kbd`, drawn in keys.css. */\nkbd {\n display: inline-block;\n font: 11px/1.3 var(--font-mono, ui-monospace, monospace);\n color: var(--muted);\n border: 1px solid var(--line); border-bottom-width: 2px; border-radius: var(--radius-sm);\n padding: 1px 5px; vertical-align: baseline;\n}\n\n/* --- metadata and breadcrumbs ---------------------------------------------- */\n/* A metadata line (`metaLine` in dom.ts): parts in a row, each after the first\n led by a DRAWN 3px disc. Never a \"·\" character: that is a typed separator,\n and it renders at whatever weight and height the symbol font has. The disc\n is the muted ink, the row inherits its size from wherever it sits. */\n.shell-meta { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 2px 8px; min-width: 0; }\n.shell-meta-part { display: inline-flex; align-items: center; gap: 8px; min-width: 0; white-space: nowrap; }\n.shell-meta-part + .shell-meta-part::before {\n content: \"\"; flex: none; width: 3px; height: 3px;\n border-radius: var(--radius-pill); background: var(--muted);\n}\n\n/* A breadcrumb trail (`breadcrumb` in dom.ts): crumbs with the vocabulary's\n `forward` chevron drawn between them. A crumb that goes somewhere is a\n button coloured as a link (it reads as a control with the pointer parked);\n the last crumb is where the reader is, in the ink. */\n.shell-crumbs { display: inline-flex; align-items: center; gap: 2px; min-width: 0; font: 12.5px/1.3 var(--font-ui); }\n.shell-crumb { color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }\n.shell-crumb[aria-current] { color: var(--ink); }\n.shell-crumb-sep { flex: none; color: var(--muted); opacity: 0.7; }\n.shell-crumb-link {\n font: inherit; background: none; border: 0; padding: 0 2px; margin: 0;\n border-radius: var(--radius-sm); color: var(--accent); cursor: pointer;\n transition: color var(--dur-quick) var(--ease-standard);\n}\n.shell-crumb-link:hover { color: var(--ink); text-decoration: underline; }\n\n/* Structured values (record, map, list): the parts, each a field row of its own, indented under the\n caption, with a map's and a list's own controls beside each part. */\n.shell-valuerow-parts { gap: 6px; padding-left: 10px; border-left: 1px solid var(--line, color-mix(in oklab, var(--ink) 14%, transparent)); }\n.shell-valuerow-part { display: flex; align-items: flex-start; gap: 6px; width: 100%; }\n.shell-valuerow-part > .shell-fieldrow { flex: 1; min-width: 0; }\n.shell-valuerow-controls { display: inline-flex; gap: 2px; padding-top: 2px; }\n.shell-valuerow-controls:empty { display: none; }\n.shell-valuerow-add { display: inline-flex; align-items: center; gap: 4px; }\n.shell-valuerow-key { min-width: 10em; }\n/* The chosen value's own help (a manifest's valueHelp): a line per chosen flag. */\n.shell-fieldrow-valuehelp { white-space: pre-line; }\n\n/* An extension's section, folded to the fields a node sets (value-rows' extensionFold). The caption is the\n disclosure: a quiet full-width button, the chevron then the name and its count. */\n.shell-fold-cap {\n display: flex; align-items: center; gap: 4px; width: 100%;\n padding: 0; border: 0; background: none; color: inherit; font: inherit; text-align: left; cursor: pointer;\n}\n.shell-fold-cap svg { flex: none; color: var(--muted); }\n.shell-fold-cap:hover svg, .shell-fold-cap:focus-visible svg { color: var(--ink); }\n.shell-fold-cap:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-sm); }\n.shell-fold-body:empty { display: none; }\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/controls.css"],"sourcesContent":["/* ============================================================================\n The family's control grammar: one button, one field, one segmented control,\n one pill, one empty-state line, one keycap. Class-scoped throughout, never\n an element reset: a stylesheet that restyles every <button> in a window is a\n blast radius, and the two apps had five spellings of \"primary button\" using\n four foreground tokens between them (ui-review-2026-09, finding 20).\n\n Reads the token grammar (tokens.css) and the app's palette (--surface,\n --card, --ink, --muted, --line, --accent, --danger, --on-accent; optional\n --accent-soft, --line-soft, --font-mono). The keyboard focus ring is the\n family's one rule in tokens.css, so nothing here draws another.\n\n \"Controls have edges\" (design-language.md, 2026-09-16): a button has a\n border or a fill at rest, and text a person can read without hovering.\n Ghost styling is ONLY for icon-only toolbar buttons in a bar that is itself\n the affordance. And \"Motion is interpolation\", as amended: the only thing\n that transitions on hover is colour, at --dur-quick. No lift, no shadow\n change, no scale.\n ============================================================================ */\n\n/* --- buttons ---------------------------------------------------------------- */\n.btn {\n display: inline-flex; align-items: center; justify-content: center; gap: 0.35em;\n padding: 5px 11px;\n border: 1px solid var(--line); border-radius: var(--radius-sm);\n background: var(--surface); color: var(--ink);\n font: 600 12.5px var(--font-ui); letter-spacing: 0.02em; line-height: 1.2;\n cursor: pointer; white-space: nowrap;\n -webkit-user-select: none; user-select: none;\n transition: color var(--dur-quick) var(--ease-standard),\n background var(--dur-quick) var(--ease-standard),\n border-color var(--dur-quick) var(--ease-standard);\n}\n.btn:hover:not(:disabled) {\n border-color: var(--accent);\n background: var(--accent-soft, color-mix(in oklab, var(--accent) 10%, transparent));\n}\n.btn:disabled { opacity: 0.45; cursor: default; }\n\n/* The one action a dialog or a bar is for: accent fill, the palette's own ink\n on it (never a raw white, which read white-on-tan on the dark palettes). */\n.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }\n.btn.primary:hover:not(:disabled) {\n background: color-mix(in oklab, var(--accent) 88%, var(--ink));\n border-color: color-mix(in oklab, var(--accent) 88%, var(--ink));\n color: var(--on-accent);\n}\n\n/* The destructive action, and it names its object (\"Delete scene\"). */\n.btn.danger { background: var(--danger); border-color: var(--danger); color: var(--surface); }\n.btn.danger:hover:not(:disabled) {\n background: color-mix(in oklab, var(--danger) 88%, var(--ink));\n border-color: color-mix(in oklab, var(--danger) 88%, var(--ink));\n color: var(--surface);\n}\n\n/* ONLY for an icon-only button in a toolbar: borderless, muted, a wash on\n hover. A text action drawn this way is the \"bare muted text on the ground\"\n the design language rules out. */\n.btn.ghost { border-color: transparent; background: none; color: var(--muted); }\n.btn.ghost:hover:not(:disabled) {\n border-color: transparent; color: var(--ink);\n background: var(--accent-soft, color-mix(in oklab, var(--accent) 10%, transparent));\n}\n\n/* A square button holding one glyph, centred explicitly: a bare <button>\n centres by the font's metrics plus UA padding, which parks an arrow up-left\n of the square's visual centre. */\n.btn.icon { width: 28px; height: 28px; padding: 0; line-height: 1; font-size: 13.5px; }\n\n/* --- fields ----------------------------------------------------------------- */\n.field {\n font: inherit; font-size: 13.5px; line-height: 1.4;\n padding: 6px 9px;\n border: 1px solid var(--line); border-radius: var(--radius-sm);\n background: var(--card); color: var(--ink);\n -webkit-user-select: text; user-select: text;\n transition: border-color var(--dur-quick) var(--ease-standard);\n}\n.field:focus-visible { border-color: var(--accent); outline-offset: 0; }\n/* A placeholder is a hint, not content: lighter and italic, its opacity\n pinned so no engine fades an already-muted colour a second time. */\n.field::placeholder { color: var(--muted); font-style: italic; opacity: 1; }\n/* `.invalid` is the dup guard's (a value that clashes with another row);\n `.illegal` is a value that breaks a rule. Both can be true at once, so they\n are separate classes that draw the same. */\n.field.invalid, .field.illegal { border-color: var(--danger); }\n.field:disabled { opacity: 0.55; cursor: default; }\ntextarea.field { resize: vertical; }\n\n/* --- segmented control ------------------------------------------------------ */\n/* One bordered strip, options divided by hairlines, the chosen one washed. Seven\n hand-rolled copies across the two apps agreed on everything but the radius\n (finding 21); this is the one they converge on. */\n.seg { display: inline-flex; border: 1px solid var(--line); border-radius: var(--radius-sm); overflow: hidden; }\n.seg-opt {\n background: none; border: 0; cursor: pointer;\n color: var(--muted); font: 600 12px var(--font-ui); padding: 3px 9.5px; white-space: nowrap;\n transition: color var(--dur-quick) var(--ease-standard), background var(--dur-quick) var(--ease-standard);\n}\n.seg-opt + .seg-opt { border-left: 1px solid var(--line); }\n.seg-opt:hover:not(.on) { color: var(--ink); }\n.seg-opt.on {\n color: var(--accent); cursor: default;\n background: var(--accent-soft, color-mix(in oklab, var(--accent) 14%, transparent));\n}\n\n/* A quality's value as its ladder (value-control.ts rungStrip): the rungs in order, the current one marked.\n Stage names keep the mono voice values use. An unset value's fallback rung is marked quietly; a value that\n is no longer a stage is shown after the ladder, in the warning colour, until a rung is picked. */\n.shell-rungs { flex-wrap: wrap; }\n.shell-rung { font-family: var(--font-mono); font-weight: 400; padding: 2px 7px; }\n.shell-rung.on { font-weight: 600; }\n.shell-rung.fallback { color: var(--ink); text-decoration: underline dotted; text-underline-offset: 3px; }\n.shell-rung-default { font-family: var(--font-ui); }\n.shell-rung.stray { color: var(--warn, var(--danger, var(--accent))); text-decoration: line-through; cursor: default; }\nspan.shell-rung { cursor: default; }\n\n/* A declared field's value as a row (value-control.ts fieldRow): the caption, then the control with the\n purpose and any message under it. The grid is the app's (it passes its own row class); these are the\n parts both apps share. A flags value is a picker of the declared values: chips, the set ones washed. */\n.shell-fieldrow-body { display: flex; flex-direction: column; align-items: flex-start; gap: 3px; min-width: 0; }\n.shell-fieldrow-textual .shell-fieldrow-body { align-items: stretch; }\n.shell-fieldrow-text { min-width: 0; }\ntextarea.shell-fieldrow-text { min-height: 3.6em; font-family: inherit; line-height: 1.4; }\n.shell-fieldrow-purpose { margin: 0; font: 12px/1.4 var(--font-ui); color: var(--muted); max-width: 60ch; }\n.shell-fieldrow-problem { margin: 0; font: 12px/1.4 var(--font-ui); color: var(--warn, var(--danger, var(--accent))); }\n.shell-fieldrow.has-problem .shell-fieldrow-text { border-color: var(--warn, var(--danger)); }\n.shell-flags { display: inline-flex; flex-wrap: wrap; gap: 4px; }\n.shell-flag {\n display: inline-flex; align-items: center; border: 1px solid var(--line); border-radius: var(--radius-pill);\n background: none; color: var(--muted); font: 12px var(--font-mono); padding: 1px 8px; cursor: pointer;\n}\n.shell-flag:hover:not(.on):not(span) { color: var(--ink); }\n.shell-flag.on { color: var(--accent); border-color: var(--accent); background: var(--accent-soft, color-mix(in oklab, var(--accent) 14%, transparent)); }\n.shell-flag.fallback { color: var(--ink); border-style: dashed; background: none; }\n.shell-flag-default { font-family: var(--font-ui); }\n.shell-flag-default.on { cursor: default; }\n.shell-flag.stray { color: var(--warn, var(--danger, var(--accent))); border-color: currentColor; background: none; text-decoration: line-through; }\nspan.shell-flag { cursor: default; }\n\n/* --- small things ----------------------------------------------------------- */\n/* A pill: a small bordered label (a class, a count, a state). */\n.pill {\n display: inline-flex; align-items: center; gap: 4px;\n font: 11.5px/1.3 var(--font-ui); color: var(--muted);\n border: 1px solid var(--line-soft, var(--line)); border-radius: var(--radius-pill);\n padding: 1px 7px; white-space: nowrap;\n}\n\n/* The inline empty state: one muted italic sentence where a list would be. */\n.empty { margin: 0; color: var(--muted); font: italic 13px/1.45 var(--font-ui); }\n\n/* A keycap. A key hint is an element, never a typed \"↑↓ move\" string. The\n element rule is the floor for a hand-written <kbd>; the shell's own hint\n helpers (keys.ts) stamp `.shell-kbd`, drawn in keys.css. */\nkbd {\n display: inline-block;\n font: 11px/1.3 var(--font-mono, ui-monospace, monospace);\n color: var(--muted);\n border: 1px solid var(--line); border-bottom-width: 2px; border-radius: var(--radius-sm);\n padding: 1px 5px; vertical-align: baseline;\n}\n\n/* --- metadata and breadcrumbs ---------------------------------------------- */\n/* A metadata line (`metaLine` in dom.ts): parts in a row, each after the first\n led by a DRAWN 3px disc. Never a \"·\" character: that is a typed separator,\n and it renders at whatever weight and height the symbol font has. The disc\n is the muted ink, the row inherits its size from wherever it sits. */\n.shell-meta { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 2px 8px; min-width: 0; }\n.shell-meta-part { display: inline-flex; align-items: center; gap: 8px; min-width: 0; white-space: nowrap; }\n.shell-meta-part + .shell-meta-part::before {\n content: \"\"; flex: none; width: 3px; height: 3px;\n border-radius: var(--radius-pill); background: var(--muted);\n}\n\n/* A breadcrumb trail (`breadcrumb` in dom.ts): crumbs with the vocabulary's\n `forward` chevron drawn between them. A crumb that goes somewhere is a\n button coloured as a link (it reads as a control with the pointer parked);\n the last crumb is where the reader is, in the ink. */\n.shell-crumbs { display: inline-flex; align-items: center; gap: 2px; min-width: 0; font: 12.5px/1.3 var(--font-ui); }\n.shell-crumb { color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }\n.shell-crumb[aria-current] { color: var(--ink); }\n.shell-crumb-sep { flex: none; color: var(--muted); opacity: 0.7; }\n.shell-crumb-link {\n font: inherit; background: none; border: 0; padding: 0 2px; margin: 0;\n border-radius: var(--radius-sm); color: var(--accent); cursor: pointer;\n transition: color var(--dur-quick) var(--ease-standard);\n}\n.shell-crumb-link:hover { color: var(--ink); text-decoration: underline; }\n\n/* Structured values (record, map, list): the parts, each a field row of its own, indented under the\n caption, with a map's and a list's own controls beside each part. */\n.shell-valuerow-parts { gap: 6px; padding-left: 10px; border-left: 1px solid var(--line, color-mix(in oklab, var(--ink) 14%, transparent)); }\n.shell-valuerow-part { display: flex; align-items: flex-start; gap: 6px; width: 100%; }\n.shell-valuerow-part > .shell-fieldrow { flex: 1; min-width: 0; }\n.shell-valuerow-controls { display: inline-flex; gap: 2px; padding-top: 2px; }\n.shell-valuerow-controls:empty { display: none; }\n.shell-valuerow-add { display: inline-flex; align-items: center; gap: 4px; }\n.shell-valuerow-key { min-width: 10em; }\n/* The chosen value's own help (a manifest's valueHelp): a line per chosen flag. */\n.shell-fieldrow-valuehelp { white-space: pre-line; }\n\n/* An extension's section, folded to the fields a node sets (value-rows' extensionFold). The caption is the\n disclosure: a quiet full-width button, the chevron then the name and its count. */\n.shell-fold-cap {\n display: flex; align-items: center; gap: 4px; width: 100%;\n padding: 0; border: 0; background: none; color: inherit; font: inherit; text-align: left; cursor: pointer;\n}\n.shell-fold-cap svg { flex: none; color: var(--muted); }\n.shell-fold-cap:hover svg, .shell-fold-cap:focus-visible svg { color: var(--ink); }\n.shell-fold-cap:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-sm); }\n.shell-fold-body:empty { display: none; }\n\n/* A map of records as a grid (value-rows' recordMapGrid): a row per key, a column per record field, each\n cell the field's own row with its caption and help left to the column head. */\n.shell-recordgrid-table { width: 100%; border-collapse: collapse; }\n.shell-recordgrid-table th { font: 600 12px/1.3 var(--font-ui); color: var(--muted); text-align: left; padding: 4px 6px; vertical-align: top; }\n.shell-recordgrid-table td { padding: 3px 6px; vertical-align: top; }\n.shell-recordgrid-table tbody tr { border-top: 1px solid var(--line); }\n.shell-recordgrid-table th.shell-recordgrid-key { color: var(--ink); padding-top: 9px; white-space: nowrap; }\n.shell-recordgrid-gone { color: var(--danger); font-weight: 400; }\n.shell-recordgrid-tools { width: 1%; white-space: nowrap; }\n.shell-recordgrid-cell { display: block; }\n.shell-recordgrid-cell > .shell-fieldrow-label,\n.shell-recordgrid-cell .shell-fieldrow-purpose,\n.shell-recordgrid-cell .shell-fieldrow-valuehelp { display: none; }\n.shell-recordgrid-cell select, .shell-recordgrid-cell input { width: 100%; min-width: 7em; }\n.shell-recordgrid-empty { margin: 6px 0; font: 12.5px/1.4 var(--font-ui); color: var(--muted); }\n.shell-recordgrid-add { margin-top: 8px; }\n"],"mappings":"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","names":[]}
package/dist/index.cjs CHANGED
@@ -1460,6 +1460,27 @@ function followButton(opts) {
1460
1460
  reflect();
1461
1461
  } };
1462
1462
  }
1463
+ function selectionFollowButton(opts) {
1464
+ const what = opts.what ?? "line";
1465
+ const b = el("button", "btn swin-follow", "Follow selection");
1466
+ b.type = "button";
1467
+ let on = opts.on;
1468
+ const reflect = () => {
1469
+ b.classList.toggle("on", on);
1470
+ b.setAttribute("aria-pressed", String(on));
1471
+ b.dataset["tip"] = on ? `Shows whatever is selected in the editor. Click to stay on this ${what}.` : `Stays on this ${what}. Click to follow the selection.`;
1472
+ };
1473
+ reflect();
1474
+ b.addEventListener("click", () => {
1475
+ on = !on;
1476
+ reflect();
1477
+ opts.onToggle(on);
1478
+ });
1479
+ return { el: b, set: (next) => {
1480
+ on = next;
1481
+ reflect();
1482
+ } };
1483
+ }
1463
1484
 
1464
1485
  // src/exit.ts
1465
1486
  function closeWithExit(element, done) {
@@ -3927,6 +3948,7 @@ exports.revealRow = revealRow;
3927
3948
  exports.revealRowWhenReady = revealRowWhenReady;
3928
3949
  exports.rungStrip = rungStrip;
3929
3950
  exports.saveIndicator = saveIndicator;
3951
+ exports.selectionFollowButton = selectionFollowButton;
3930
3952
  exports.setKeyPlatform = setKeyPlatform;
3931
3953
  exports.showAbout = showAbout;
3932
3954
  exports.showUpdaterDialog = showUpdaterDialog;