@wildwinter/app-shell 0.55.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 +64 -0
- package/dist/controls.css +81 -0
- package/dist/controls.css.map +1 -1
- package/dist/index.cjs +24 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -2
- package/dist/index.d.ts +17 -2
- package/dist/index.js +24 -2
- package/dist/index.js.map +1 -1
- package/dist/tokens.css +1 -1
- package/dist/tokens.css.map +1 -1
- package/dist/value-rows.cjs +279 -10
- package/dist/value-rows.cjs.map +1 -1
- package/dist/value-rows.d.cts +85 -1
- package/dist/value-rows.d.ts +85 -1
- package/dist/value-rows.js +276 -13
- package/dist/value-rows.js.map +1 -1
- package/package.json +1 -1
package/dist/tokens.css
CHANGED
package/dist/tokens.css.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/tokens.css"],"sourcesContent":["/* ============================================================================\n Design-token GRAMMAR - the app-agnostic layer (design-language.md section 4).\n\n The shared half of \"two palettes, one grammar\": the scales that are IDENTICAL\n across the editor family - elevation, motion, radius, scrollbar chrome. Each\n app supplies its own colour + font VALUES (its palette) over this grammar in\n its own theme.css. Do not add app-specific colours here.\n\n SCALE. Chrome is sized in px off a 14px base; the reading surface alone\n scales with the root (\"Chrome has its own scale\", design-language.md\n section 4, 2026-09-16). Every size in the shell's stylesheets (font-size,\n padding, gap, margin, width, height) is a pixel value: the navigator, the\n inspector, the bars, the dialogs and the controls in them read the same in\n every app of the family whatever the reading size is. `em` survives only\n where a rule deliberately scales with its own font; line-heights stay\n unitless. The values are what Storyletter rendered at 0.39.0 (rem x 16, to\n the nearest half pixel), so the conversion moved nothing there and brought\n Patterpad, whose chrome had grown 7 to 10 percent with its reading root,\n back to the same size. No `rem` in a chrome rule; the test suite greps.\n ============================================================================ */\n\n:root {\n color-scheme: light dark;\n\n /* The semantic set's third member, and the only COLOUR in this file.\n\n It is here because it kept not being anywhere. An app's palette owns\n --danger and --warn; neither owned \"all is well\", so a real need - the live\n debug link, an in-sync shard, a saved document - was met with a raw green\n literal that could not theme-shift (surface-audit-shell.md F2). A default\n in the grammar layer means the shell's own widgets may say it, and an app\n that has not thought about green yet still gets a green that works on both\n grounds. Every palette should override it in its theme.css, as it does the\n other two: this is a floor, not a decision. */\n --ok: light-dark(#3f7d49, #79bd80);\n\n /* The ink that sits ON the accent: a primary button's label, a selected\n row's text. Every palette overrides it (a light tan accent on a dark\n palette wants dark ink, not white); this floor only stops the shell's own\n primary buttons from falling back to a raw #fff literal, which is what\n they did until 0.39.0 and which read white-on-tan on Night and Slate. */\n --on-accent: light-dark(#ffffff, #1b1916);\n\n /* The chrome base. `.shell-dialog`, `.pane-shell` and `.swin-head` set it as\n their font-size, so unstyled text inside them lands at 14px regardless of\n the app's root; a rule that wants the base by name reads it here. Not a\n scale factor: the sizes below it are literal px, on purpose. */\n --chrome-size: 14px;\n\n /* The one scrim behind every modal in the family (confirm, settings,\n identity, about, notes). Four recipes had grown across five files. */\n --scrim: color-mix(in oklab, var(--ink) 28%, transparent);\n\n /* Elevation: three tiers by how far a surface floats (resting cards,\n floating menus/popovers, full overlays). Theme-agnostic black so it\n deepens naturally on the dark palettes. */\n --shadow-1: 0 1px 3px rgba(0, 0, 0, 0.05);\n --shadow-2: 0 6px 20px rgba(0, 0, 0, 0.14);\n --shadow-3: 0 16px 48px rgba(0, 0, 0, 0.28);\n\n /* Motion: one easing curve + a small duration scale, plus the shared\n panel/backdrop/screen enter-exit vocabulary. Nothing pops. */\n --ease-standard: cubic-bezier(0.2, 0, 0, 1);\n --dur-quick: 120ms;\n --dur-base: 150ms;\n --dur-settle: 200ms;\n --dur-slow: 1s;\n --dur-panel: 260ms;\n --dur-exit: 170ms;\n --anim-panel-in: panel-in var(--dur-panel) var(--ease-standard);\n --anim-backdrop-in: backdrop-in var(--dur-settle) var(--ease-standard);\n --anim-screen-in: screen-in var(--dur-panel) var(--ease-standard);\n --anim-panel-out: panel-out var(--dur-exit) var(--ease-standard) forwards;\n --anim-backdrop-out: backdrop-out var(--dur-exit) var(--ease-standard) forwards;\n /* The long-job strip's indeterminate band (job.css draws the keyframes). */\n --anim-job-band: job-band 1.4s var(--ease-standard) infinite;\n\n /* Corner radius: four steps cover every surface. */\n --radius-sm: 6px;\n --radius-md: 10px;\n --radius-lg: 14px;\n --radius-pill: 999px;\n\n /* Scrollbar thumb: a translucent ink, so it adapts per palette. */\n --scroll-thumb: color-mix(in oklab, var(--ink) 20%, transparent);\n --scroll-thumb-hover: color-mix(in oklab, var(--ink) 40%, transparent);\n}\n\n/* A drawn icon (`iconNode` / `iconHtml` in icons.ts stamp `data-icon`). A\n block, so it never sits on a text baseline with descender space under it;\n no flex shrink, so a crowded row squeezes the text and not the picture; and\n no pointer events, so a click lands on the button and never on the drawing\n (a handler comparing `event.target` to its button would otherwise miss).\n Colour is inherited: every drawing is currentColor. */\n[data-icon] { display: block; flex: none; pointer-events: none; }\n\n/* The family's keyboard focus ring: one rule, zero specificity (:where), so a\n component may draw its own and win without !important. Until 0.39.0\n Patterpad's main window had no ring at all and Storyletter carried five\n copies of this line. Mouse focus stays quiet; only :focus-visible draws. */\n:where(button, [role=\"button\"], input, select, textarea, summary, a[href], [tabindex]):focus-visible {\n outline: 2px solid var(--accent);\n outline-offset: 1px;\n}\n\n/* The tracked uppercase caption, kept for exactly two jobs: table column heads\n and screenplay character cues, where uppercase is the domain's own\n convention (design-language.md, \"Captions are words, not overlines\"). A\n section caption anywhere else is sentence-case text at label size, weight\n 600, in the UI face, which is what the shell's own captions now are. */\n.overline { font: 600 10.5px/1 var(--font-ui); text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }\n\n* { scrollbar-width: thin; scrollbar-color: var(--scroll-thumb) transparent; }\n::-webkit-scrollbar { width: 11px; height: 11px; }\n::-webkit-scrollbar-track { background: transparent; }\n::-webkit-scrollbar-corner { background: transparent; }\n::-webkit-scrollbar-thumb { background: var(--scroll-thumb); border-radius: var(--radius-sm); border: 3px solid transparent; background-clip: padding-box; }\n::-webkit-scrollbar-thumb:hover { background: var(--scroll-thumb-hover); background-clip: padding-box; }\n\n@keyframes panel-in { from { opacity: 0; transform: translateY(-9px) scale(0.965); } to { opacity: 1; transform: none; } }\n@keyframes backdrop-in { from { opacity: 0; } to { opacity: 1; } }\n@keyframes screen-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }\n@keyframes panel-out { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateY(-6px) scale(0.97); } }\n@keyframes backdrop-out { from { opacity: 1; } to { opacity: 0; } }\n\n@media (prefers-reduced-motion: reduce) {\n :root {\n --anim-panel-in: none; --anim-backdrop-in: none; --anim-screen-in: none;\n --anim-panel-out: none; --anim-backdrop-out: none; --anim-job-band: none;\n }\n}\n\n/* A floating layer from createFloating (floating.ts) carries this attribute, because its class is\n the caller's. Never a window-drag region, even over one: Electron gives a click in a drag area to\n the OS before the page sees it (dialog.css has the whole story, 2026-09-28). */\n[data-shell-layer], [data-shell-layer] * { -webkit-app-region: no-drag; }\n"],"mappings":";AAqBA;AACE,gBAAc,MAAM;AAYpB,QAAM,WAAW,OAAO,EAAE;AAO1B,eAAa,WAAW,OAAO,EAAE;AAMjC,iBAAe;AAIf,WAAS,UAAU,GAAG,KAAK,EAAE,IAAI,OAAO,GAAG,EAAE;AAK7C,cAAY,EAAE,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;AACpC,cAAY,EAAE,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;AACrC,cAAY,EAAE,KAAK,KAAK,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;AAItC,mBAAiB,aAAa,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE;AACzC,eAAa;AACb,cAAY;AACZ,gBAAc;AACd,cAAY;AACZ,eAAa;AACb,cAAY;AACZ,mBAAiB,SAAS,IAAI,aAAa,IAAI;AAC/C,sBAAoB,YAAY,IAAI,cAAc,IAAI;AACtD,oBAAkB,UAAU,IAAI,aAAa,IAAI;AACjD,oBAAkB,UAAU,IAAI,YAAY,IAAI,iBAAiB;AACjE,uBAAqB,aAAa,IAAI,YAAY,IAAI,iBAAiB;AAEvE,mBAAiB,SAAS,KAAK,IAAI,iBAAiB;AAGpD,eAAa;AACb,eAAa;AACb,eAAa;AACb,iBAAe;AAGf,kBAAgB,UAAU,GAAG,KAAK,EAAE,IAAI,OAAO,GAAG,EAAE;AACpD,wBAAsB,UAAU,GAAG,KAAK,EAAE,IAAI,OAAO,GAAG,EAAE;AAC5D;AAQA,CAAC;AAAa,WAAS;AAAO,QAAM;AAAM,kBAAgB;AAAM;AAMhE,OAAO,QAAQ,CAAC,cAAgB,OAAO,QAAQ,UAAU,SAAS,CAAC,CAAC,OAAO,CAAC,UAAU;AACpF,WAAS,IAAI,MAAM,IAAI;AACvB,kBAAgB;AAClB;AAOA,CAAC;AAAW,QAAM,IAAI,MAAM,CAAC,EAAE,IAAI;AAAY,kBAAgB;AAAW,kBAAgB;AAAQ,SAAO,IAAI;AAAU;AAEvH;AAAI,mBAAiB;AAAM,mBAAiB,IAAI,gBAAgB;AAAa;AAC7E;AAAsB,SAAO;AAAM,UAAQ;AAAM;AACjD;AAA4B,cAAY;AAAa;AACrD;AAA6B,cAAY;AAAa;AACtD;AAA4B,cAAY,IAAI;AAAiB,iBAAe,IAAI;AAAc,UAAQ,IAAI,MAAM;AAAa,mBAAiB;AAAa;AAC3J,yBAAyB;AAAS,cAAY,IAAI;AAAuB,mBAAiB;AAAa;AAEvG,WAAW;AAAW;AAAO,aAAS;AAAG,eAAW,WAAW,MAAM,MAAM;AAAQ;AAAE;AAAK,aAAS;AAAG,eAAW;AAAM;AAAE;AACzH,WAAW;AAAc;AAAO,aAAS;AAAG;AAAE;AAAK,aAAS;AAAG;AAAE;AACjE,WAAW;AAAY;AAAO,aAAS;AAAG,eAAW,WAAW;AAAM;AAAE;AAAK,aAAS;AAAG,eAAW;AAAM;AAAE;AAC5G,WAAW;AAAY;AAAO,aAAS;AAAG,eAAW;AAAM;AAAE;AAAK,aAAS;AAAG,eAAW,WAAW,MAAM,MAAM;AAAO;AAAE;AACzH,WAAW;AAAe;AAAO,aAAS;AAAG;AAAE;AAAK,aAAS;AAAG;AAAE;AAElE,QAAO,wBAAyB;AAC9B;AACE,qBAAiB;AAAM,wBAAoB;AAAM,sBAAkB;AACnE,sBAAkB;AAAM,yBAAqB;AAAM,qBAAiB;AACtE;AACF;AAKA,CAAC;AAAmB,CAAC,kBAAkB;AAAI,sBAAoB;AAAS;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/tokens.css"],"sourcesContent":["/* ============================================================================\n Design-token GRAMMAR - the app-agnostic layer (design-language.md section 4).\n\n The shared half of \"two palettes, one grammar\": the scales that are IDENTICAL\n across the editor family - elevation, motion, radius, scrollbar chrome. Each\n app supplies its own colour + font VALUES (its palette) over this grammar in\n its own theme.css. Do not add app-specific colours here.\n\n SCALE. Chrome is sized in px off a 14px base; the reading surface alone\n scales with the root (\"Chrome has its own scale\", design-language.md\n section 4, 2026-09-16). Every size in the shell's stylesheets (font-size,\n padding, gap, margin, width, height) is a pixel value: the navigator, the\n inspector, the bars, the dialogs and the controls in them read the same in\n every app of the family whatever the reading size is. `em` survives only\n where a rule deliberately scales with its own font; line-heights stay\n unitless. The values are what Storyletter rendered at 0.39.0 (rem x 16, to\n the nearest half pixel), so the conversion moved nothing there and brought\n Patterpad, whose chrome had grown 7 to 10 percent with its reading root,\n back to the same size. No `rem` in a chrome rule; the test suite greps.\n ============================================================================ */\n\n:root {\n /* Native controls (an unticked checkbox, a radio, a scrollbar, a select's\n pop-up, a date field) and every light-dark() below follow this, so it must\n follow the palette the author chose, not the OS: a light palette under a\n dark OS drew every unticked checkbox as a dark filled square. Every palette\n block in an app's theme.css declares `--color-scheme: light` or `dark`;\n with no palette chosen the fallback follows the OS, as before. */\n color-scheme: var(--color-scheme, light dark);\n\n /* The semantic set's third member, and the only COLOUR in this file.\n\n It is here because it kept not being anywhere. An app's palette owns\n --danger and --warn; neither owned \"all is well\", so a real need - the live\n debug link, an in-sync shard, a saved document - was met with a raw green\n literal that could not theme-shift (surface-audit-shell.md F2). A default\n in the grammar layer means the shell's own widgets may say it, and an app\n that has not thought about green yet still gets a green that works on both\n grounds. Every palette should override it in its theme.css, as it does the\n other two: this is a floor, not a decision. */\n --ok: light-dark(#3f7d49, #79bd80);\n\n /* The ink that sits ON the accent: a primary button's label, a selected\n row's text. Every palette overrides it (a light tan accent on a dark\n palette wants dark ink, not white); this floor only stops the shell's own\n primary buttons from falling back to a raw #fff literal, which is what\n they did until 0.39.0 and which read white-on-tan on Night and Slate. */\n --on-accent: light-dark(#ffffff, #1b1916);\n\n /* The chrome base. `.shell-dialog`, `.pane-shell` and `.swin-head` set it as\n their font-size, so unstyled text inside them lands at 14px regardless of\n the app's root; a rule that wants the base by name reads it here. Not a\n scale factor: the sizes below it are literal px, on purpose. */\n --chrome-size: 14px;\n\n /* The one scrim behind every modal in the family (confirm, settings,\n identity, about, notes). Four recipes had grown across five files. */\n --scrim: color-mix(in oklab, var(--ink) 28%, transparent);\n\n /* Elevation: three tiers by how far a surface floats (resting cards,\n floating menus/popovers, full overlays). Theme-agnostic black so it\n deepens naturally on the dark palettes. */\n --shadow-1: 0 1px 3px rgba(0, 0, 0, 0.05);\n --shadow-2: 0 6px 20px rgba(0, 0, 0, 0.14);\n --shadow-3: 0 16px 48px rgba(0, 0, 0, 0.28);\n\n /* Motion: one easing curve + a small duration scale, plus the shared\n panel/backdrop/screen enter-exit vocabulary. Nothing pops. */\n --ease-standard: cubic-bezier(0.2, 0, 0, 1);\n --dur-quick: 120ms;\n --dur-base: 150ms;\n --dur-settle: 200ms;\n --dur-slow: 1s;\n --dur-panel: 260ms;\n --dur-exit: 170ms;\n --anim-panel-in: panel-in var(--dur-panel) var(--ease-standard);\n --anim-backdrop-in: backdrop-in var(--dur-settle) var(--ease-standard);\n --anim-screen-in: screen-in var(--dur-panel) var(--ease-standard);\n --anim-panel-out: panel-out var(--dur-exit) var(--ease-standard) forwards;\n --anim-backdrop-out: backdrop-out var(--dur-exit) var(--ease-standard) forwards;\n /* The long-job strip's indeterminate band (job.css draws the keyframes). */\n --anim-job-band: job-band 1.4s var(--ease-standard) infinite;\n\n /* Corner radius: four steps cover every surface. */\n --radius-sm: 6px;\n --radius-md: 10px;\n --radius-lg: 14px;\n --radius-pill: 999px;\n\n /* Scrollbar thumb: a translucent ink, so it adapts per palette. */\n --scroll-thumb: color-mix(in oklab, var(--ink) 20%, transparent);\n --scroll-thumb-hover: color-mix(in oklab, var(--ink) 40%, transparent);\n}\n\n/* A drawn icon (`iconNode` / `iconHtml` in icons.ts stamp `data-icon`). A\n block, so it never sits on a text baseline with descender space under it;\n no flex shrink, so a crowded row squeezes the text and not the picture; and\n no pointer events, so a click lands on the button and never on the drawing\n (a handler comparing `event.target` to its button would otherwise miss).\n Colour is inherited: every drawing is currentColor. */\n[data-icon] { display: block; flex: none; pointer-events: none; }\n\n/* The family's keyboard focus ring: one rule, zero specificity (:where), so a\n component may draw its own and win without !important. Until 0.39.0\n Patterpad's main window had no ring at all and Storyletter carried five\n copies of this line. Mouse focus stays quiet; only :focus-visible draws. */\n:where(button, [role=\"button\"], input, select, textarea, summary, a[href], [tabindex]):focus-visible {\n outline: 2px solid var(--accent);\n outline-offset: 1px;\n}\n\n/* The tracked uppercase caption, kept for exactly two jobs: table column heads\n and screenplay character cues, where uppercase is the domain's own\n convention (design-language.md, \"Captions are words, not overlines\"). A\n section caption anywhere else is sentence-case text at label size, weight\n 600, in the UI face, which is what the shell's own captions now are. */\n.overline { font: 600 10.5px/1 var(--font-ui); text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }\n\n* { scrollbar-width: thin; scrollbar-color: var(--scroll-thumb) transparent; }\n::-webkit-scrollbar { width: 11px; height: 11px; }\n::-webkit-scrollbar-track { background: transparent; }\n::-webkit-scrollbar-corner { background: transparent; }\n::-webkit-scrollbar-thumb { background: var(--scroll-thumb); border-radius: var(--radius-sm); border: 3px solid transparent; background-clip: padding-box; }\n::-webkit-scrollbar-thumb:hover { background: var(--scroll-thumb-hover); background-clip: padding-box; }\n\n@keyframes panel-in { from { opacity: 0; transform: translateY(-9px) scale(0.965); } to { opacity: 1; transform: none; } }\n@keyframes backdrop-in { from { opacity: 0; } to { opacity: 1; } }\n@keyframes screen-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }\n@keyframes panel-out { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateY(-6px) scale(0.97); } }\n@keyframes backdrop-out { from { opacity: 1; } to { opacity: 0; } }\n\n@media (prefers-reduced-motion: reduce) {\n :root {\n --anim-panel-in: none; --anim-backdrop-in: none; --anim-screen-in: none;\n --anim-panel-out: none; --anim-backdrop-out: none; --anim-job-band: none;\n }\n}\n\n/* A floating layer from createFloating (floating.ts) carries this attribute, because its class is\n the caller's. Never a window-drag region, even over one: Electron gives a click in a drag area to\n the OS before the page sees it (dialog.css has the whole story, 2026-09-28). */\n[data-shell-layer], [data-shell-layer] * { -webkit-app-region: no-drag; }\n"],"mappings":";AAqBA;AAOE,gBAAc,IAAI,cAAc,EAAE,MAAM;AAYxC,QAAM,WAAW,OAAO,EAAE;AAO1B,eAAa,WAAW,OAAO,EAAE;AAMjC,iBAAe;AAIf,WAAS,UAAU,GAAG,KAAK,EAAE,IAAI,OAAO,GAAG,EAAE;AAK7C,cAAY,EAAE,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;AACpC,cAAY,EAAE,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;AACrC,cAAY,EAAE,KAAK,KAAK,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;AAItC,mBAAiB,aAAa,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE;AACzC,eAAa;AACb,cAAY;AACZ,gBAAc;AACd,cAAY;AACZ,eAAa;AACb,cAAY;AACZ,mBAAiB,SAAS,IAAI,aAAa,IAAI;AAC/C,sBAAoB,YAAY,IAAI,cAAc,IAAI;AACtD,oBAAkB,UAAU,IAAI,aAAa,IAAI;AACjD,oBAAkB,UAAU,IAAI,YAAY,IAAI,iBAAiB;AACjE,uBAAqB,aAAa,IAAI,YAAY,IAAI,iBAAiB;AAEvE,mBAAiB,SAAS,KAAK,IAAI,iBAAiB;AAGpD,eAAa;AACb,eAAa;AACb,eAAa;AACb,iBAAe;AAGf,kBAAgB,UAAU,GAAG,KAAK,EAAE,IAAI,OAAO,GAAG,EAAE;AACpD,wBAAsB,UAAU,GAAG,KAAK,EAAE,IAAI,OAAO,GAAG,EAAE;AAC5D;AAQA,CAAC;AAAa,WAAS;AAAO,QAAM;AAAM,kBAAgB;AAAM;AAMhE,OAAO,QAAQ,CAAC,cAAgB,OAAO,QAAQ,UAAU,SAAS,CAAC,CAAC,OAAO,CAAC,UAAU;AACpF,WAAS,IAAI,MAAM,IAAI;AACvB,kBAAgB;AAClB;AAOA,CAAC;AAAW,QAAM,IAAI,MAAM,CAAC,EAAE,IAAI;AAAY,kBAAgB;AAAW,kBAAgB;AAAQ,SAAO,IAAI;AAAU;AAEvH;AAAI,mBAAiB;AAAM,mBAAiB,IAAI,gBAAgB;AAAa;AAC7E;AAAsB,SAAO;AAAM,UAAQ;AAAM;AACjD;AAA4B,cAAY;AAAa;AACrD;AAA6B,cAAY;AAAa;AACtD;AAA4B,cAAY,IAAI;AAAiB,iBAAe,IAAI;AAAc,UAAQ,IAAI,MAAM;AAAa,mBAAiB;AAAa;AAC3J,yBAAyB;AAAS,cAAY,IAAI;AAAuB,mBAAiB;AAAa;AAEvG,WAAW;AAAW;AAAO,aAAS;AAAG,eAAW,WAAW,MAAM,MAAM;AAAQ;AAAE;AAAK,aAAS;AAAG,eAAW;AAAM;AAAE;AACzH,WAAW;AAAc;AAAO,aAAS;AAAG;AAAE;AAAK,aAAS;AAAG;AAAE;AACjE,WAAW;AAAY;AAAO,aAAS;AAAG,eAAW,WAAW;AAAM;AAAE;AAAK,aAAS;AAAG,eAAW;AAAM;AAAE;AAC5G,WAAW;AAAY;AAAO,aAAS;AAAG,eAAW;AAAM;AAAE;AAAK,aAAS;AAAG,eAAW,WAAW,MAAM,MAAM;AAAO;AAAE;AACzH,WAAW;AAAe;AAAO,aAAS;AAAG;AAAE;AAAK,aAAS;AAAG;AAAE;AAElE,QAAO,wBAAyB;AAC9B;AACE,qBAAiB;AAAM,wBAAoB;AAAM,sBAAkB;AACnE,sBAAkB;AAAM,yBAAqB;AAAM,qBAAiB;AACtE;AACF;AAKA,CAAC;AAAmB,CAAC,kBAAkB;AAAI,sBAAoB;AAAS;","names":[]}
|
package/dist/value-rows.cjs
CHANGED
|
@@ -826,13 +826,274 @@ var fieldRowFocus = {
|
|
|
826
826
|
settle: (row) => keeper.settle(row),
|
|
827
827
|
restore: (row) => keeper.restore(row)
|
|
828
828
|
};
|
|
829
|
+
var isObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
830
|
+
function isSet(decl, value) {
|
|
831
|
+
if (value === void 0) return false;
|
|
832
|
+
if (decl.type === "record" && decl.default === void 0 && isObject(value)) {
|
|
833
|
+
const fields = decl.fields ?? [];
|
|
834
|
+
const declared = new Set(fields.map((f) => f.name));
|
|
835
|
+
if (Object.entries(value).some(([k, v]) => !declared.has(k) && v !== void 0)) return true;
|
|
836
|
+
return fields.some((f) => isSet(f, value[f.name]));
|
|
837
|
+
}
|
|
838
|
+
return extensions.stableStringify(value) !== extensions.stableStringify(extensions.defaultOf(decl));
|
|
839
|
+
}
|
|
840
|
+
function foldCaption(name, set) {
|
|
841
|
+
return set > 0 ? `${name} (${set} set)` : name;
|
|
842
|
+
}
|
|
843
|
+
function extensionFold() {
|
|
844
|
+
const open = /* @__PURE__ */ new Set();
|
|
845
|
+
const shown = /* @__PURE__ */ new Map();
|
|
846
|
+
const keyOf = (o) => `${o.extension}\0${o.node}`;
|
|
847
|
+
const visible = (o, setNames) => {
|
|
848
|
+
const was = shown.get(keyOf(o));
|
|
849
|
+
const fields = was ? /* @__PURE__ */ new Set([...was.fields, ...setNames]) : new Set(setNames);
|
|
850
|
+
shown.set(keyOf(o), { fields, used: true });
|
|
851
|
+
return fields;
|
|
852
|
+
};
|
|
853
|
+
const fold = {
|
|
854
|
+
isOpen: (extension) => open.has(extension),
|
|
855
|
+
setOpen(extension, on) {
|
|
856
|
+
if (on) open.add(extension);
|
|
857
|
+
else open.delete(extension);
|
|
858
|
+
for (const key of shown.keys()) if (key.startsWith(`${extension}\0`)) shown.delete(key);
|
|
859
|
+
},
|
|
860
|
+
sweep() {
|
|
861
|
+
for (const [key, entry] of shown) {
|
|
862
|
+
if (!entry.used) shown.delete(key);
|
|
863
|
+
else entry.used = false;
|
|
864
|
+
}
|
|
865
|
+
},
|
|
866
|
+
section(o) {
|
|
867
|
+
const sec = el("div", `shell-fold${o.className ? ` ${o.className}` : ""}`);
|
|
868
|
+
sec.dataset["extension"] = o.extension;
|
|
869
|
+
const cap = el("button", `shell-fold-cap${o.captionClassName ? ` ${o.captionClassName}` : ""}`);
|
|
870
|
+
cap.type = "button";
|
|
871
|
+
const body = el("div", "shell-fold-body");
|
|
872
|
+
sec.append(cap, body);
|
|
873
|
+
const draw = () => {
|
|
874
|
+
const isOpen = open.has(o.extension);
|
|
875
|
+
const setNames = new Set(o.fields.filter((f) => isSet(f, o.entry?.[f.name])).map((f) => f.name));
|
|
876
|
+
const show2 = isOpen ? void 0 : visible(o, setNames);
|
|
877
|
+
cap.replaceChildren(iconNode(isOpen ? "expanded" : "collapsed"), el("span", "shell-fold-name", foldCaption(o.caption, setNames.size)));
|
|
878
|
+
cap.setAttribute("aria-expanded", String(isOpen));
|
|
879
|
+
cap.dataset["tip"] = isOpen ? `Show only the fields set here` : `Show every ${o.caption} field`;
|
|
880
|
+
sec.classList.toggle("shell-fold-open", isOpen);
|
|
881
|
+
const rows = [...o.lead ?? []];
|
|
882
|
+
let group;
|
|
883
|
+
for (const decl of o.fields) {
|
|
884
|
+
if (show2 && !show2.has(decl.name)) continue;
|
|
885
|
+
const g = decl.group;
|
|
886
|
+
if (g !== void 0 && g !== group) {
|
|
887
|
+
group = g;
|
|
888
|
+
rows.push(o.group(g));
|
|
889
|
+
}
|
|
890
|
+
rows.push(o.row(decl));
|
|
891
|
+
}
|
|
892
|
+
rows.push(...o.tail ?? []);
|
|
893
|
+
body.replaceChildren(...rows);
|
|
894
|
+
};
|
|
895
|
+
cap.addEventListener("click", () => {
|
|
896
|
+
fold.setOpen(o.extension, !open.has(o.extension));
|
|
897
|
+
draw();
|
|
898
|
+
});
|
|
899
|
+
draw();
|
|
900
|
+
return sec;
|
|
901
|
+
}
|
|
902
|
+
};
|
|
903
|
+
return fold;
|
|
904
|
+
}
|
|
905
|
+
var isObject2 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
906
|
+
function isRecordMap(decl) {
|
|
907
|
+
return decl.type === "map" && decl.of?.type === "record";
|
|
908
|
+
}
|
|
909
|
+
function recordMapKeyLabel(decl, key, adapter) {
|
|
910
|
+
const kind = decl.key?.type === "reference" ? decl.key.to ?? "" : void 0;
|
|
911
|
+
if (kind === void 0 || !adapter) return key;
|
|
912
|
+
return adapter.nodes(kind).find((n) => n.id === key)?.label ?? adapter.label?.(kind, key) ?? key;
|
|
913
|
+
}
|
|
914
|
+
function valueText(decl, value, adapter) {
|
|
915
|
+
if (!isSet(decl, value)) return "";
|
|
916
|
+
if (decl.type === "pick" && typeof value === "string") {
|
|
917
|
+
const choice = extensions.pickChoices(decl, {
|
|
918
|
+
...adapter ? { nodes: (kind) => adapter.nodes(kind) } : {},
|
|
919
|
+
...adapter?.list ? { list: (name) => adapter.list(name) } : {}
|
|
920
|
+
}).find((c) => c.value === value);
|
|
921
|
+
return choice?.label ?? value;
|
|
922
|
+
}
|
|
923
|
+
if (decl.type === "reference" && typeof value === "string" && decl.to !== void 0 && adapter) {
|
|
924
|
+
return adapter.nodes(decl.to).find((n) => n.id === value)?.label ?? adapter.label?.(decl.to, value) ?? value;
|
|
925
|
+
}
|
|
926
|
+
if (decl.type === "boolean") return value === true ? decl.label ?? decl.name : "";
|
|
927
|
+
if (Array.isArray(value)) return value.map(String).join(", ");
|
|
928
|
+
if (isObject2(value)) return JSON.stringify(value);
|
|
929
|
+
return String(value);
|
|
930
|
+
}
|
|
931
|
+
function recordMapSummary(decl, value, adapter) {
|
|
932
|
+
if (!isObject2(value)) return [];
|
|
933
|
+
const fields = decl.of?.fields ?? [];
|
|
934
|
+
return Object.entries(value).map(([key, record]) => {
|
|
935
|
+
const name = recordMapKeyLabel(decl, key, adapter);
|
|
936
|
+
const words = isObject2(record) ? fields.map((f) => valueText(f, record[f.name], adapter)).filter((w) => w !== "") : [];
|
|
937
|
+
return words.length > 0 ? `${name}: ${words.join(", ")}` : name;
|
|
938
|
+
});
|
|
939
|
+
}
|
|
940
|
+
function recordMapGrid(initial) {
|
|
941
|
+
let opts = initial;
|
|
942
|
+
const root = el("div", "shell-recordgrid");
|
|
943
|
+
const table = el("table", "shell-recordgrid-table");
|
|
944
|
+
const head = el("thead");
|
|
945
|
+
const body = el("tbody");
|
|
946
|
+
table.append(head, body);
|
|
947
|
+
const adder = el("div", "shell-recordgrid-add");
|
|
948
|
+
const empty = el("p", "shell-recordgrid-empty");
|
|
949
|
+
root.append(table, empty, adder);
|
|
950
|
+
const cells = /* @__PURE__ */ new Map();
|
|
951
|
+
let addKey = "";
|
|
952
|
+
const editable = () => opts.onCommit !== void 0 && opts.disabled !== true;
|
|
953
|
+
const held = () => isObject2(opts.value) ? opts.value : {};
|
|
954
|
+
const commit = (next) => {
|
|
955
|
+
const v = Object.keys(next).length > 0 ? next : void 0;
|
|
956
|
+
opts = { ...opts, value: v };
|
|
957
|
+
draw();
|
|
958
|
+
opts.onCommit?.(v);
|
|
959
|
+
};
|
|
960
|
+
const cell = (key, field, record) => {
|
|
961
|
+
const id = `${key}\0${field.name}`;
|
|
962
|
+
const o = {
|
|
963
|
+
decl: field,
|
|
964
|
+
value: record[field.name],
|
|
965
|
+
...opts.adapter ? { adapter: opts.adapter } : {},
|
|
966
|
+
...opts.disabled !== void 0 ? { disabled: opts.disabled } : {},
|
|
967
|
+
...opts.controlClassName !== void 0 ? { controlClassName: opts.controlClassName } : {},
|
|
968
|
+
...editable() ? {
|
|
969
|
+
onCommit: (v) => {
|
|
970
|
+
const map = held();
|
|
971
|
+
const rec = { ...isObject2(map[key]) ? map[key] : {} };
|
|
972
|
+
if (v === void 0) delete rec[field.name];
|
|
973
|
+
else rec[field.name] = v;
|
|
974
|
+
commit({ ...map, [key]: rec });
|
|
975
|
+
}
|
|
976
|
+
} : {},
|
|
977
|
+
className: "shell-recordgrid-cell"
|
|
978
|
+
};
|
|
979
|
+
const had = cells.get(id);
|
|
980
|
+
if (had && had.el.dataset["type"] === field.type) {
|
|
981
|
+
fieldRowFocus.settle(had.el);
|
|
982
|
+
had.update(o);
|
|
983
|
+
fieldRowFocus.restore(had.el);
|
|
984
|
+
return had.el;
|
|
985
|
+
}
|
|
986
|
+
const handle = valueRow(o);
|
|
987
|
+
handle.el.dataset["type"] = field.type;
|
|
988
|
+
cells.set(id, handle);
|
|
989
|
+
return handle.el;
|
|
990
|
+
};
|
|
991
|
+
const draw = () => {
|
|
992
|
+
const decl = opts.decl;
|
|
993
|
+
const fields = decl.of?.fields ?? [];
|
|
994
|
+
const map = held();
|
|
995
|
+
const keys = Object.keys(map);
|
|
996
|
+
const adapter = opts.adapter;
|
|
997
|
+
const keyKind = decl.key?.type === "reference" ? decl.key.to ?? "" : void 0;
|
|
998
|
+
const keyNodes = keyKind !== void 0 && adapter ? adapter.nodes(keyKind) : void 0;
|
|
999
|
+
const hr = el("tr");
|
|
1000
|
+
hr.append(el("th", "shell-recordgrid-keyhead", recordMapKeyHeading(decl)));
|
|
1001
|
+
for (const f of fields) {
|
|
1002
|
+
const th = el("th", void 0, f.label ?? f.name);
|
|
1003
|
+
const help = f.help ?? f.purpose;
|
|
1004
|
+
if (help) th.dataset["tip"] = help;
|
|
1005
|
+
hr.append(th);
|
|
1006
|
+
}
|
|
1007
|
+
hr.append(el("th", "shell-recordgrid-tools"));
|
|
1008
|
+
head.replaceChildren(hr);
|
|
1009
|
+
const used = /* @__PURE__ */ new Set();
|
|
1010
|
+
const rows = [];
|
|
1011
|
+
for (const key of keys) {
|
|
1012
|
+
const record = isObject2(map[key]) ? map[key] : {};
|
|
1013
|
+
const tr = el("tr");
|
|
1014
|
+
tr.dataset["key"] = key;
|
|
1015
|
+
const name = recordMapKeyLabel(decl, key, adapter);
|
|
1016
|
+
const keyCell = el("th", "shell-recordgrid-key", name);
|
|
1017
|
+
keyCell.setAttribute("scope", "row");
|
|
1018
|
+
if (keyNodes !== void 0 && adapter && keyNodes.every((n) => n.id !== key) && adapter.label?.(keyKind, key) === void 0) {
|
|
1019
|
+
keyCell.append(el("span", "shell-recordgrid-gone", " (not here any more)"));
|
|
1020
|
+
}
|
|
1021
|
+
tr.append(keyCell);
|
|
1022
|
+
for (const f of fields) {
|
|
1023
|
+
used.add(`${key}\0${f.name}`);
|
|
1024
|
+
const td = el("td");
|
|
1025
|
+
td.append(cell(key, f, record));
|
|
1026
|
+
tr.append(td);
|
|
1027
|
+
}
|
|
1028
|
+
const tools = el("td", "shell-recordgrid-tools");
|
|
1029
|
+
if (editable()) tools.append(iconBtn("close", `Remove ${name}`, () => {
|
|
1030
|
+
const next = { ...held() };
|
|
1031
|
+
delete next[key];
|
|
1032
|
+
commit(next);
|
|
1033
|
+
}));
|
|
1034
|
+
tr.append(tools);
|
|
1035
|
+
rows.push(tr);
|
|
1036
|
+
}
|
|
1037
|
+
for (const id of [...cells.keys()]) if (!used.has(id)) cells.delete(id);
|
|
1038
|
+
body.replaceChildren(...rows);
|
|
1039
|
+
table.hidden = keys.length === 0;
|
|
1040
|
+
empty.textContent = keys.length === 0 ? "None yet." : "";
|
|
1041
|
+
empty.hidden = keys.length !== 0;
|
|
1042
|
+
adder.replaceChildren();
|
|
1043
|
+
if (!editable()) return;
|
|
1044
|
+
const add = (k) => {
|
|
1045
|
+
if (k === "" || Object.prototype.hasOwnProperty.call(held(), k)) return;
|
|
1046
|
+
commit({ ...held(), [k]: extensions.defaultOf(decl.of) });
|
|
1047
|
+
};
|
|
1048
|
+
if (keyNodes !== void 0) {
|
|
1049
|
+
const pick = el("select", `field shell-valuerow-key${opts.controlClassName ? ` ${opts.controlClassName}` : ""}`);
|
|
1050
|
+
const first = el("option", void 0, "Add...");
|
|
1051
|
+
first.value = "";
|
|
1052
|
+
pick.append(first);
|
|
1053
|
+
for (const n of keyNodes.filter((n2) => !Object.prototype.hasOwnProperty.call(map, n2.id))) {
|
|
1054
|
+
const opt = el("option", void 0, n.label);
|
|
1055
|
+
opt.value = n.id;
|
|
1056
|
+
pick.append(opt);
|
|
1057
|
+
}
|
|
1058
|
+
pick.disabled = pick.options.length === 1;
|
|
1059
|
+
pick.addEventListener("change", () => add(pick.value));
|
|
1060
|
+
adder.append(pick);
|
|
1061
|
+
} else {
|
|
1062
|
+
const input = el("input", "field shell-valuerow-key");
|
|
1063
|
+
input.type = "text";
|
|
1064
|
+
input.placeholder = "New key";
|
|
1065
|
+
input.value = addKey;
|
|
1066
|
+
input.addEventListener("input", () => {
|
|
1067
|
+
addKey = input.value;
|
|
1068
|
+
});
|
|
1069
|
+
const go = () => {
|
|
1070
|
+
const k = input.value.trim();
|
|
1071
|
+
addKey = "";
|
|
1072
|
+
add(k);
|
|
1073
|
+
};
|
|
1074
|
+
input.addEventListener("keydown", (e) => {
|
|
1075
|
+
if (e.key === "Enter") go();
|
|
1076
|
+
});
|
|
1077
|
+
adder.append(input, iconBtn("add", "Add", go));
|
|
1078
|
+
}
|
|
1079
|
+
};
|
|
1080
|
+
draw();
|
|
1081
|
+
return { el: root, update: (o) => {
|
|
1082
|
+
opts = o;
|
|
1083
|
+
draw();
|
|
1084
|
+
} };
|
|
1085
|
+
}
|
|
1086
|
+
function recordMapKeyHeading(decl) {
|
|
1087
|
+
const to = decl.key?.type === "reference" ? decl.key.to : void 0;
|
|
1088
|
+
return to ? to.charAt(0).toUpperCase() + to.slice(1) : "Key";
|
|
1089
|
+
}
|
|
829
1090
|
|
|
830
1091
|
// src/value-rows.ts
|
|
831
1092
|
function nodeLabel(adapter, kind, id) {
|
|
832
1093
|
return adapter.nodes(kind).find((n) => n.id === id)?.label ?? adapter.label?.(kind, id);
|
|
833
1094
|
}
|
|
834
1095
|
var SCALARS = /* @__PURE__ */ new Set(["text", "multiline", "number", "boolean", "enum", "flags", "quality", "string"]);
|
|
835
|
-
var
|
|
1096
|
+
var isObject3 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
836
1097
|
var nameOf = (decl) => decl.label ?? decl.name;
|
|
837
1098
|
var asDecl = (d, name) => ({ ...d, name: d.name ?? name });
|
|
838
1099
|
function ownProblems(decl, value, adapter) {
|
|
@@ -1071,31 +1332,31 @@ function structuredRow(initial) {
|
|
|
1071
1332
|
}, controls));
|
|
1072
1333
|
};
|
|
1073
1334
|
if (decl.type === "record") {
|
|
1074
|
-
const value =
|
|
1335
|
+
const value = isObject3(o.value) ? o.value : void 0;
|
|
1075
1336
|
const required = value === void 0 ? [] : extensions.valueProblems(decl, value).filter((p) => p.code === "required");
|
|
1076
1337
|
for (const f of decl.fields ?? []) {
|
|
1077
1338
|
const missing = required.find((p) => p.path === f.name);
|
|
1078
1339
|
child(`f:${f.name}`, f, value?.[f.name], (v) => {
|
|
1079
|
-
const next = { ...
|
|
1340
|
+
const next = { ...isObject3(opts.value) ? opts.value : {} };
|
|
1080
1341
|
if (v === void 0) delete next[f.name];
|
|
1081
1342
|
else next[f.name] = v;
|
|
1082
1343
|
commit(Object.keys(next).length > 0 ? next : void 0);
|
|
1083
1344
|
}, void 0, void 0, missing ? "Required." : void 0);
|
|
1084
1345
|
}
|
|
1085
1346
|
} else if (decl.type === "map" && decl.of) {
|
|
1086
|
-
const value =
|
|
1347
|
+
const value = isObject3(o.value) ? o.value : {};
|
|
1087
1348
|
const keyNodes = decl.key?.type === "reference" && o.adapter ? o.adapter.nodes(decl.key.to ?? "") : void 0;
|
|
1088
1349
|
const keyKind = decl.key?.to ?? "";
|
|
1089
1350
|
const keyLabel = (k) => (o.adapter && keyNodes !== void 0 ? nodeLabel(o.adapter, keyKind, k) : void 0) ?? k;
|
|
1090
1351
|
for (const k of Object.keys(value)) {
|
|
1091
1352
|
const remove = editable() ? [iconBtn("close", `Remove ${keyLabel(k)}`, () => {
|
|
1092
|
-
const next = { ...
|
|
1353
|
+
const next = { ...isObject3(opts.value) ? opts.value : {} };
|
|
1093
1354
|
delete next[k];
|
|
1094
1355
|
commit(Object.keys(next).length > 0 ? next : void 0);
|
|
1095
1356
|
})] : [];
|
|
1096
1357
|
const gone = keyNodes !== void 0 && o.adapter && nodeLabel(o.adapter, keyKind, k) === void 0 ? `${k} is not here any more.` : void 0;
|
|
1097
1358
|
child(`k:${k}`, asDecl(decl.of, k), value[k], (v) => {
|
|
1098
|
-
const next = { ...
|
|
1359
|
+
const next = { ...isObject3(opts.value) ? opts.value : {} };
|
|
1099
1360
|
next[k] = v === void 0 ? extensions.defaultOf(decl.of) : v;
|
|
1100
1361
|
commit(next);
|
|
1101
1362
|
}, remove, keyLabel(k), gone);
|
|
@@ -1139,7 +1400,7 @@ function structuredRow(initial) {
|
|
|
1139
1400
|
}
|
|
1140
1401
|
} else if (decl.type === "list" && decl.of) {
|
|
1141
1402
|
const value = Array.isArray(o.value) ? o.value : [];
|
|
1142
|
-
const idOf = (item, i) => decl.id !== void 0 &&
|
|
1403
|
+
const idOf = (item, i) => decl.id !== void 0 && isObject3(item) && typeof item[decl.id] === "string" ? `id:${item[decl.id]}` : `i:${i}`;
|
|
1143
1404
|
value.forEach((item, i) => {
|
|
1144
1405
|
const set = (next) => commit(next.length > 0 ? next : void 0);
|
|
1145
1406
|
const controls = editable() ? [
|
|
@@ -1153,7 +1414,7 @@ function structuredRow(initial) {
|
|
|
1153
1414
|
}, i === value.length - 1),
|
|
1154
1415
|
iconBtn("close", "Remove", () => set(value.filter((_, j) => j !== i)), false, true)
|
|
1155
1416
|
] : [];
|
|
1156
|
-
const itemLabel = decl.id !== void 0 &&
|
|
1417
|
+
const itemLabel = decl.id !== void 0 && isObject3(item) && typeof item[decl.id] === "string" ? item[decl.id] : `${i + 1}`;
|
|
1157
1418
|
child(idOf(item, i), asDecl(decl.of, itemLabel), item, (v) => {
|
|
1158
1419
|
const next = [...Array.isArray(opts.value) ? opts.value : []];
|
|
1159
1420
|
next[i] = v === void 0 ? extensions.defaultOf(decl.of) : v;
|
|
@@ -1164,8 +1425,8 @@ function structuredRow(initial) {
|
|
|
1164
1425
|
if (editable()) {
|
|
1165
1426
|
adder.append(iconBtn("add", "Add", () => {
|
|
1166
1427
|
const fresh = extensions.defaultOf(decl.of);
|
|
1167
|
-
if (decl.id !== void 0 &&
|
|
1168
|
-
const taken = new Set(value.map((x) =>
|
|
1428
|
+
if (decl.id !== void 0 && isObject3(fresh)) {
|
|
1429
|
+
const taken = new Set(value.map((x) => isObject3(x) ? x[decl.id] : void 0));
|
|
1169
1430
|
let n = value.length + 1;
|
|
1170
1431
|
while (taken.has(`item-${n}`)) n++;
|
|
1171
1432
|
fresh[decl.id] = `item-${n}`;
|
|
@@ -1214,7 +1475,15 @@ function valueRows() {
|
|
|
1214
1475
|
};
|
|
1215
1476
|
}
|
|
1216
1477
|
|
|
1478
|
+
exports.extensionFold = extensionFold;
|
|
1479
|
+
exports.foldCaption = foldCaption;
|
|
1480
|
+
exports.isRecordMap = isRecordMap;
|
|
1481
|
+
exports.isSet = isSet;
|
|
1482
|
+
exports.recordMapGrid = recordMapGrid;
|
|
1483
|
+
exports.recordMapKeyLabel = recordMapKeyLabel;
|
|
1484
|
+
exports.recordMapSummary = recordMapSummary;
|
|
1217
1485
|
exports.valueRow = valueRow;
|
|
1218
1486
|
exports.valueRows = valueRows;
|
|
1487
|
+
exports.valueText = valueText;
|
|
1219
1488
|
//# sourceMappingURL=value-rows.cjs.map
|
|
1220
1489
|
//# sourceMappingURL=value-rows.cjs.map
|