@digilogiclabs/saas-factory-ui 1.28.1 → 1.29.1
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/dist/index.d.mts +15 -2
- package/dist/index.d.ts +15 -2
- package/dist/index.js +154 -36
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +167 -49
- package/dist/index.mjs.map +1 -1
- package/dist/web/index.d.mts +15 -2
- package/dist/web/index.d.ts +15 -2
- package/dist/web/index.js +154 -36
- package/dist/web/index.js.map +1 -1
- package/dist/web/index.mjs +165 -47
- package/dist/web/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -5257,15 +5257,28 @@ interface FlowTreeProps {
|
|
|
5257
5257
|
hideControls?: boolean;
|
|
5258
5258
|
/** Hide the breadcrumb legend at the bottom-left. */
|
|
5259
5259
|
hideLegend?: boolean;
|
|
5260
|
+
/**
|
|
5261
|
+
* When > 0, cycles the focused path through the root's direct children
|
|
5262
|
+
* every N milliseconds until the user interacts with the tree (clicks a
|
|
5263
|
+
* card, pans, zooms, toggles a detail, or clicks a legend chip). Honors
|
|
5264
|
+
* `prefers-reduced-motion` (disabled if reduced motion is requested).
|
|
5265
|
+
* Default: 0 (disabled).
|
|
5266
|
+
*/
|
|
5267
|
+
autoCycleMs?: number;
|
|
5268
|
+
/**
|
|
5269
|
+
* Explicit paths to cycle through when `autoCycleMs` is set. If omitted,
|
|
5270
|
+
* the tree auto-cycles through the root's direct children.
|
|
5271
|
+
*/
|
|
5272
|
+
autoCyclePaths?: string[][];
|
|
5260
5273
|
}
|
|
5261
|
-
declare function FlowTree({ data, title, eyebrow, tagline, renderIcon: renderIconProp, tierColors: tierColorsProp, resolveHref: resolveHrefProp, layoutOptions, onNodeOpen, defaultFocusedPath, focusedPath: controlledPath, onFocusedPathChange, className, style, hideHeader, hideControls, hideLegend, }: FlowTreeProps): react_jsx_runtime.JSX.Element;
|
|
5274
|
+
declare function FlowTree({ data, title, eyebrow, tagline, renderIcon: renderIconProp, tierColors: tierColorsProp, resolveHref: resolveHrefProp, layoutOptions, onNodeOpen, defaultFocusedPath, focusedPath: controlledPath, onFocusedPathChange, className, style, hideHeader, hideControls, hideLegend, autoCycleMs, autoCyclePaths, }: FlowTreeProps): react_jsx_runtime.JSX.Element;
|
|
5262
5275
|
|
|
5263
5276
|
/**
|
|
5264
5277
|
* FlowTree CSS — injected once per page at runtime on the first mount.
|
|
5265
5278
|
* Self-themed via `--ft-*` CSS variables, all with sensible fallbacks so the
|
|
5266
5279
|
* component works standalone in any light or dark design system.
|
|
5267
5280
|
*/
|
|
5268
|
-
declare const FLOW_TREE_CSS = "\n.ft-shell {\n --ft-bg: var(--ft-bg, oklch(0.185 0.008 80));\n --ft-fg: var(--ft-fg, oklch(0.96 0.005 85));\n --ft-muted-fg: var(--ft-muted-fg, oklch(0.68 0.008 80));\n --ft-dim-fg: var(--ft-dim-fg, oklch(0.5 0.008 80));\n --ft-line: var(--ft-line, oklch(0.28 0.008 80));\n --ft-line-strong: var(--ft-line-strong, oklch(0.4 0.008 80));\n --ft-grid-strong: var(--ft-grid-strong, oklch(0.24 0.008 80));\n --ft-card-bg: var(--ft-card-bg, oklch(0.21 0.008 80));\n --ft-card-active-bg: var(--ft-card-active-bg, oklch(0.25 0.015 60));\n --ft-card-hover-bg: var(--ft-card-hover-bg, oklch(0.23 0.01 80 / 0.6));\n --ft-rail-bg: var(--ft-rail-bg, oklch(0.19 0.008 80));\n --ft-icon-bg: var(--ft-icon-bg, oklch(0.17 0.008 80));\n --ft-detail-bg: var(--ft-detail-bg, oklch(0.16 0.008 80));\n --ft-header-bg: var(--ft-header-bg, linear-gradient(180deg, oklch(0.21 0.01 60) 0%, oklch(0.19 0.008 70) 100%));\n --ft-tier-orange: var(--ft-tier-orange, #f16c25);\n --ft-tier-teal: var(--ft-tier-teal, #5fb7b8);\n --ft-tier-blue: var(--ft-tier-blue, oklch(0.72 0.12 240));\n --ft-tier-amber: var(--ft-tier-amber, oklch(0.8 0.14 75));\n --ft-tier-green: var(--ft-tier-green, oklch(0.74 0.14 155));\n --ft-accent: var(--ft-accent, var(--ft-tier-orange));\n --ft-serif: var(--ft-serif, \"Instrument Serif\", Georgia, serif);\n --ft-sans: var(--ft-sans, \"Inter\", system-ui, sans-serif);\n --ft-mono: var(--ft-mono, \"JetBrains Mono\", ui-monospace, Menlo, monospace);\n\n display: flex;\n flex-direction: column;\n min-height: 0;\n background: var(--ft-bg);\n border: 1px solid var(--ft-line);\n border-radius: 2px;\n overflow: hidden;\n color: var(--ft-fg);\n font-family: var(--ft-sans);\n font-size: 14px;\n line-height: 1.5;\n -webkit-font-smoothing: antialiased;\n box-shadow: 0 30px 60px -30px oklch(0 0 0 / 0.5);\n}\n.ft-shell * { box-sizing: border-box; }\n.ft-shell .ft-mono {\n font-family: var(--ft-mono);\n font-size: 11px;\n letter-spacing: 0.02em;\n}\n\n.ft-header {\n padding: 22px 28px 20px;\n border-bottom: 1px solid var(--ft-line);\n background: var(--ft-header-bg);\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.ft-header__eyebrow {\n font-family: var(--ft-mono);\n font-size: 10.5px;\n letter-spacing: 0.22em;\n text-transform: uppercase;\n color: var(--ft-accent);\n}\n.ft-header__title {\n margin: 0;\n font-family: var(--ft-serif);\n font-weight: 400;\n font-size: 44px;\n line-height: 1;\n letter-spacing: -0.015em;\n color: var(--ft-fg);\n}\n.ft-header__tagline {\n margin: 6px 0 0;\n max-width: 76ch;\n color: var(--ft-muted-fg);\n font-size: 13px;\n}\n\n.ft-stage {\n position: relative;\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n\n.ft-svg {\n display: block;\n width: 100%;\n height: 100%;\n background: transparent;\n cursor: grab;\n touch-action: none;\n user-select: none;\n}\n.ft-svg.is-dragging { cursor: grabbing; }\n\n.ft-controls {\n position: absolute;\n top: 14px;\n right: 14px;\n z-index: 5;\n display: flex;\n align-items: center;\n gap: 6px;\n background: oklch(0.2 0.008 80 / 0.94);\n border: 1px solid var(--ft-line-strong);\n padding: 5px 8px;\n backdrop-filter: blur(8px);\n border-radius: 2px;\n}\n.ft-controls button {\n font-family: var(--ft-mono);\n font-size: 12px;\n width: 26px;\n height: 26px;\n background: transparent;\n border: 1px solid var(--ft-line);\n color: var(--ft-fg);\n cursor: pointer;\n padding: 0;\n}\n.ft-controls button:hover { border-color: var(--ft-accent); }\n.ft-controls__reset {\n width: auto !important;\n padding: 0 10px !important;\n font-size: 9.5px !important;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n}\n.ft-controls__hint {\n font-family: var(--ft-mono);\n font-size: 9.5px;\n color: var(--ft-muted-fg);\n letter-spacing: 0.04em;\n padding-left: 8px;\n margin-left: 2px;\n border-left: 1px solid var(--ft-line);\n}\n\n.ft-legend {\n position: absolute;\n left: 18px;\n bottom: 14px;\n z-index: 5;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n font-family: var(--ft-mono);\n font-size: 10px;\n color: var(--ft-muted-fg);\n background: oklch(0.2 0.008 80 / 0.88);\n border: 1px solid var(--ft-line);\n padding: 6px 10px;\n backdrop-filter: blur(6px);\n max-width: calc(100% - 220px);\n}\n.ft-legend__chip { display: inline-flex; align-items: center; gap: 6px; }\n.ft-legend__dot {\n width: 5px;\n height: 5px;\n border-radius: 50%;\n background: var(--ft-accent);\n}\n.ft-legend__sep { color: var(--ft-line-strong); margin: 0 2px; }\n\n.ft-edge { fill: none; transition: stroke 260ms, opacity 260ms; }\n.ft-edge--off {\n stroke: var(--ft-line);\n stroke-width: 1;\n opacity: 0.55;\n}\n.ft-edge--on {\n stroke: var(--ft-accent);\n stroke-width: 1.6;\n stroke-dasharray: 4 5;\n opacity: 1;\n animation: ftDashFlow 1.4s linear infinite;\n}\n@keyframes ftDashFlow { to { stroke-dashoffset: -36; } }\n\n.ft-card {\n --tier-local: var(--tier, var(--ft-line-strong));\n width: 100%;\n height: 100%;\n display: grid;\n grid-template-columns: 1fr auto;\n align-items: stretch;\n background: var(--ft-card-bg);\n border: 1px solid var(--ft-line);\n border-left: 3px solid var(--tier-local);\n border-radius: 2px;\n transition:\n background 260ms cubic-bezier(.2,.8,.2,1),\n border-color 260ms, box-shadow 260ms,\n transform 260ms cubic-bezier(.2,.8,.2,1),\n filter 260ms, opacity 260ms, color 260ms;\n overflow: visible;\n animation: ftCardIn 320ms cubic-bezier(.2,.8,.2,1) backwards;\n}\n@keyframes ftCardIn {\n from { opacity: 0; transform: translateX(-6px); }\n to { opacity: 1; transform: translateX(0); }\n}\n.ft-card__main {\n display: grid;\n grid-template-columns: auto 1fr auto;\n gap: 10px;\n align-items: center;\n padding: 0 10px 0 12px;\n background: transparent;\n border: none;\n color: inherit;\n font-family: var(--ft-sans);\n font-size: 13px;\n text-align: left;\n cursor: pointer;\n min-width: 0;\n}\n.ft-card__main:hover { background: var(--ft-card-hover-bg); }\n.ft-card__icon {\n width: 24px;\n height: 24px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: var(--tier-local);\n border: 1px solid var(--ft-line-strong);\n background: var(--ft-icon-bg);\n flex-shrink: 0;\n}\n.ft-card__body { display: flex; flex-direction: column; min-width: 0; gap: 1px; }\n.ft-card__label {\n font-family: var(--ft-serif);\n font-size: 15px;\n line-height: 1.15;\n color: var(--ft-fg);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n display: flex;\n align-items: center;\n gap: 5px;\n}\n.ft-card__sub {\n font-family: var(--ft-mono);\n font-size: 9.5px;\n letter-spacing: 0.02em;\n color: var(--ft-muted-fg);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ft-card__lock { color: var(--ft-muted-fg); display: inline-flex; }\n.ft-card__caret {\n width: 18px;\n height: 18px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-family: var(--ft-mono);\n font-size: 12px;\n color: var(--ft-muted-fg);\n border: 1px solid var(--ft-line);\n}\n.ft-card--active .ft-card__caret {\n color: var(--tier-local);\n border-color: var(--tier-local);\n}\n\n.ft-card__rail {\n display: flex;\n flex-direction: column;\n border-left: 1px solid var(--ft-line);\n background: var(--ft-rail-bg);\n}\n.ft-card__mini {\n flex: 1;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n min-height: 20px;\n background: transparent;\n border: none;\n color: var(--ft-muted-fg);\n cursor: pointer;\n transition: background 150ms, color 150ms;\n border-bottom: 1px solid var(--ft-line);\n padding: 0;\n text-decoration: none;\n}\n.ft-card__mini:last-child { border-bottom: none; }\n.ft-card__mini:hover {\n background: oklch(0.23 0.01 80);\n color: var(--tier-local);\n}\n.ft-card__mini.is-on {\n color: var(--tier-local);\n background: oklch(0.23 0.01 80);\n}\n\n.ft-card--active {\n background: var(--ft-card-active-bg);\n box-shadow: 0 0 0 1px var(--tier-local), 0 14px 34px -16px oklch(0.5 0.18 50 / 0.55);\n transform: scale(1.02);\n}\n.ft-card--dim {\n filter: grayscale(0.85) brightness(0.82);\n opacity: 0.7;\n transform: scale(0.88);\n transform-origin: center left;\n}\n.ft-card--dim .ft-card__label { color: var(--ft-dim-fg); }\n.ft-card--dim:hover {\n filter: grayscale(0.3) brightness(0.96);\n opacity: 1;\n transform: scale(0.94);\n}\n.ft-card--cta {\n border-left-color: var(--ft-accent);\n background: linear-gradient(180deg, oklch(0.23 0.02 55) 0%, oklch(0.2 0.015 60) 100%);\n}\n.ft-card--root {\n border-left-color: var(--ft-accent);\n background: oklch(0.26 0.015 55);\n}\n.ft-card--root .ft-card__icon {\n color: var(--ft-accent);\n border-color: var(--ft-accent);\n}\n\n.ft-detail {\n position: relative;\n margin-top: 0;\n padding: 16px 18px 14px;\n background: var(--ft-detail-bg);\n border: 1px solid var(--ft-line-strong);\n border-left: 2px solid var(--ft-accent);\n border-radius: 3px;\n animation: ftDetailIn 220ms cubic-bezier(.2,.8,.2,1) backwards;\n color: var(--ft-fg);\n width: 320px;\n box-shadow: 0 18px 40px -8px rgba(0,0,0,0.6), 0 2px 8px rgba(0,0,0,0.4);\n}\n.ft-detail__head {\n display: flex;\n align-items: center;\n margin: -2px 28px 10px 0;\n}\n.ft-detail__title {\n font-family: var(--ft-mono);\n font-size: 10px;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: var(--ft-muted-fg);\n}\n.ft-detail__close {\n position: absolute;\n top: 8px;\n right: 8px;\n width: 22px;\n height: 22px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: 1px solid var(--ft-line);\n border-radius: 2px;\n color: var(--ft-muted-fg);\n cursor: pointer;\n padding: 0;\n transition: color 120ms, border-color 120ms, background 120ms;\n}\n.ft-detail__close:hover {\n color: var(--ft-fg);\n border-color: var(--ft-line-strong);\n background: oklch(0.22 0.008 80);\n}\n@keyframes ftDetailIn {\n from { opacity: 0; transform: translateY(-4px); }\n to { opacity: 1; transform: translateY(0); }\n}\n.ft-detail__lead {\n font-family: var(--ft-serif);\n font-size: 15px;\n line-height: 1.35;\n font-style: italic;\n padding-left: 10px;\n border-left: 2px solid var(--ft-accent);\n margin-bottom: 10px;\n}\n.ft-detail__body {\n margin: 0 0 10px;\n font-size: 12px;\n color: var(--ft-muted-fg);\n line-height: 1.5;\n}\n.ft-detail__bullets {\n margin: 0 0 10px;\n padding-left: 16px;\n font-size: 12px;\n color: var(--ft-fg);\n}\n.ft-detail__bullets li { margin-bottom: 3px; }\n.ft-detail__meta {\n margin: 0 0 10px;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n.ft-detail__meta-row {\n display: grid;\n grid-template-columns: 96px 1fr;\n gap: 8px;\n font-size: 11px;\n}\n.ft-detail__meta-row dt {\n font-family: var(--ft-mono);\n font-size: 9.5px;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n color: var(--ft-muted-fg);\n padding-top: 1px;\n}\n.ft-detail__meta-row dd { margin: 0; color: var(--ft-fg); }\n.ft-detail__actions {\n display: flex;\n gap: 6px;\n flex-wrap: wrap;\n margin-top: 8px;\n}\n\n.ft-btn {\n font-family: var(--ft-mono);\n font-size: 10px;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n padding: 7px 10px;\n background: transparent;\n color: var(--ft-fg);\n border: 1px solid var(--ft-line-strong);\n text-decoration: none;\n cursor: pointer;\n display: inline-flex;\n gap: 5px;\n align-items: center;\n transition: border-color 150ms, background 150ms;\n}\n.ft-btn:hover { border-color: var(--ft-accent); }\n.ft-btn--primary {\n background: var(--ft-accent);\n color: oklch(0.18 0.01 50);\n border-color: var(--ft-accent);\n}\n\n@media (max-width: 760px) {\n .ft-header { padding: 16px 18px 14px; }\n .ft-header__title { font-size: 32px; }\n .ft-controls__hint { display: none; }\n .ft-legend { max-width: calc(100% - 24px); left: 10px; bottom: 10px; }\n}\n";
|
|
5281
|
+
declare const FLOW_TREE_CSS = "\n.ft-shell {\n --ft-bg: var(--ft-bg, oklch(0.185 0.008 80));\n --ft-fg: var(--ft-fg, oklch(0.96 0.005 85));\n --ft-muted-fg: var(--ft-muted-fg, oklch(0.68 0.008 80));\n --ft-dim-fg: var(--ft-dim-fg, oklch(0.5 0.008 80));\n --ft-line: var(--ft-line, oklch(0.28 0.008 80));\n --ft-line-strong: var(--ft-line-strong, oklch(0.4 0.008 80));\n --ft-grid-strong: var(--ft-grid-strong, oklch(0.24 0.008 80));\n --ft-card-bg: var(--ft-card-bg, oklch(0.21 0.008 80));\n --ft-card-active-bg: var(--ft-card-active-bg, oklch(0.25 0.015 60));\n --ft-card-hover-bg: var(--ft-card-hover-bg, oklch(0.23 0.01 80 / 0.6));\n --ft-rail-bg: var(--ft-rail-bg, oklch(0.19 0.008 80));\n --ft-icon-bg: var(--ft-icon-bg, oklch(0.17 0.008 80));\n --ft-detail-bg: var(--ft-detail-bg, oklch(0.16 0.008 80));\n --ft-header-bg: var(--ft-header-bg, linear-gradient(180deg, oklch(0.21 0.01 60) 0%, oklch(0.19 0.008 70) 100%));\n --ft-tier-orange: var(--ft-tier-orange, #f16c25);\n --ft-tier-teal: var(--ft-tier-teal, #5fb7b8);\n --ft-tier-blue: var(--ft-tier-blue, oklch(0.72 0.12 240));\n --ft-tier-amber: var(--ft-tier-amber, oklch(0.8 0.14 75));\n --ft-tier-green: var(--ft-tier-green, oklch(0.74 0.14 155));\n --ft-accent: var(--ft-accent, var(--ft-tier-orange));\n --ft-serif: var(--ft-serif, \"Instrument Serif\", Georgia, serif);\n --ft-sans: var(--ft-sans, \"Inter\", system-ui, sans-serif);\n --ft-mono: var(--ft-mono, \"JetBrains Mono\", ui-monospace, Menlo, monospace);\n\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n min-height: 420px;\n background: var(--ft-bg);\n border: 1px solid var(--ft-line);\n border-radius: 2px;\n overflow: hidden;\n color: var(--ft-fg);\n font-family: var(--ft-sans);\n font-size: 14px;\n line-height: 1.5;\n -webkit-font-smoothing: antialiased;\n box-shadow: 0 30px 60px -30px oklch(0 0 0 / 0.5);\n}\n.ft-shell * { box-sizing: border-box; }\n.ft-shell .ft-mono {\n font-family: var(--ft-mono);\n font-size: 11px;\n letter-spacing: 0.02em;\n}\n\n.ft-header {\n padding: 22px 28px 20px;\n border-bottom: 1px solid var(--ft-line);\n background: var(--ft-header-bg);\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.ft-header__eyebrow {\n font-family: var(--ft-mono);\n font-size: 10.5px;\n letter-spacing: 0.22em;\n text-transform: uppercase;\n color: var(--ft-accent);\n}\n.ft-header__title {\n margin: 0;\n font-family: var(--ft-serif);\n font-weight: 400;\n font-size: 44px;\n line-height: 1;\n letter-spacing: -0.015em;\n color: var(--ft-fg);\n}\n.ft-header__tagline {\n margin: 6px 0 0;\n max-width: 76ch;\n color: var(--ft-muted-fg);\n font-size: 13px;\n}\n\n.ft-stage {\n position: relative;\n flex: 1;\n min-height: 0;\n overflow: hidden;\n background:\n radial-gradient(1000px 600px at 15% -10%, oklch(0.22 0.012 60 / 0.7), transparent 60%),\n radial-gradient(800px 500px at 110% 110%, oklch(0.2 0.02 200 / 0.35), transparent 65%);\n}\n\n.ft-svg {\n display: block;\n width: 100%;\n height: 100%;\n background: transparent;\n cursor: grab;\n touch-action: none;\n user-select: none;\n}\n.ft-svg.is-dragging { cursor: grabbing; }\n\n.ft-controls {\n position: absolute;\n top: 14px;\n right: 14px;\n z-index: 5;\n display: flex;\n align-items: center;\n gap: 6px;\n background: oklch(0.2 0.008 80 / 0.94);\n border: 1px solid var(--ft-line-strong);\n padding: 5px 8px;\n backdrop-filter: blur(8px);\n border-radius: 2px;\n}\n.ft-controls button {\n font-family: var(--ft-mono);\n font-size: 12px;\n width: 26px;\n height: 26px;\n background: transparent;\n border: 1px solid var(--ft-line);\n color: var(--ft-fg);\n cursor: pointer;\n padding: 0;\n}\n.ft-controls button:hover { border-color: var(--ft-accent); }\n.ft-controls__reset {\n width: auto !important;\n padding: 0 10px !important;\n font-size: 9.5px !important;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n}\n.ft-controls__hint {\n font-family: var(--ft-mono);\n font-size: 9.5px;\n color: var(--ft-muted-fg);\n letter-spacing: 0.04em;\n padding-left: 8px;\n margin-left: 2px;\n border-left: 1px solid var(--ft-line);\n}\n\n.ft-legend {\n position: absolute;\n left: 18px;\n bottom: 14px;\n z-index: 5;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n font-family: var(--ft-mono);\n font-size: 10px;\n color: var(--ft-muted-fg);\n background: oklch(0.2 0.008 80 / 0.88);\n border: 1px solid var(--ft-line);\n padding: 6px 10px;\n backdrop-filter: blur(6px);\n max-width: calc(100% - 220px);\n}\n.ft-legend__chip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 2px 6px;\n margin: -2px 0;\n background: transparent;\n border: none;\n color: inherit;\n font: inherit;\n letter-spacing: inherit;\n cursor: pointer;\n border-radius: 2px;\n transition: background 120ms, color 120ms;\n}\n.ft-legend__chip:hover {\n background: oklch(0.24 0.01 80);\n color: var(--ft-fg);\n}\n.ft-legend__chip:disabled {\n cursor: default;\n color: var(--ft-fg);\n}\n.ft-legend__chip:disabled:hover { background: transparent; }\n.ft-legend__dot {\n width: 5px;\n height: 5px;\n border-radius: 50%;\n background: var(--ft-accent);\n flex-shrink: 0;\n}\n.ft-legend__sep {\n color: var(--ft-line-strong);\n margin: 0 2px;\n pointer-events: none;\n user-select: none;\n}\n\n.ft-edge {\n fill: none;\n /* Critical: keep strokes the same screen size regardless of the tree's\n scale transform. Without this, fit-to-viewport (z \u2248 0.6-0.9) makes\n the edges sub-pixel wide and they visually disappear. */\n vector-effect: non-scaling-stroke;\n transition: stroke 260ms, opacity 260ms, stroke-width 260ms;\n}\n.ft-edge--off {\n /* Use the accent color at low opacity instead of the dim line color \u2014\n the accent (orange by default) reads far better on a dark stage. */\n stroke: var(--ft-accent);\n stroke-width: 1.5;\n stroke-dasharray: 3 5;\n opacity: 0.35;\n}\n.ft-edge--on {\n stroke: var(--ft-accent);\n stroke-width: 2.2;\n stroke-dasharray: 6 5;\n opacity: 1;\n filter: drop-shadow(0 0 6px var(--ft-accent));\n animation: ftDashFlow 1.4s linear infinite;\n}\n@keyframes ftDashFlow { to { stroke-dashoffset: -44; } }\n@media (prefers-reduced-motion: reduce) {\n .ft-edge--on { animation: none; }\n}\n\n.ft-card {\n --tier-local: var(--tier, var(--ft-line-strong));\n width: 100%;\n height: 100%;\n display: grid;\n grid-template-columns: 1fr auto;\n align-items: stretch;\n background: var(--ft-card-bg);\n border: 1px solid var(--ft-line);\n border-left: 3px solid var(--tier-local);\n border-radius: 2px;\n transition:\n background 260ms cubic-bezier(.2,.8,.2,1),\n border-color 260ms, box-shadow 260ms,\n transform 260ms cubic-bezier(.2,.8,.2,1),\n filter 260ms, opacity 260ms, color 260ms;\n overflow: visible;\n animation: ftCardIn 320ms cubic-bezier(.2,.8,.2,1) backwards;\n}\n@keyframes ftCardIn {\n from { opacity: 0; transform: translateX(-6px); }\n to { opacity: 1; transform: translateX(0); }\n}\n.ft-card__main {\n display: grid;\n grid-template-columns: auto 1fr auto;\n gap: 10px;\n align-items: center;\n padding: 0 10px 0 12px;\n background: transparent;\n border: none;\n color: inherit;\n font-family: var(--ft-sans);\n font-size: 13px;\n text-align: left;\n cursor: pointer;\n min-width: 0;\n}\n.ft-card__main:hover { background: var(--ft-card-hover-bg); }\n.ft-card__icon {\n width: 24px;\n height: 24px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: var(--tier-local);\n border: 1px solid var(--ft-line-strong);\n background: var(--ft-icon-bg);\n flex-shrink: 0;\n}\n.ft-card__body { display: flex; flex-direction: column; min-width: 0; gap: 1px; }\n.ft-card__label {\n font-family: var(--ft-serif);\n font-size: 15px;\n line-height: 1.15;\n color: var(--ft-fg);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n display: flex;\n align-items: center;\n gap: 5px;\n}\n.ft-card__sub {\n font-family: var(--ft-mono);\n font-size: 9.5px;\n letter-spacing: 0.02em;\n color: var(--ft-muted-fg);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ft-card__lock { color: var(--ft-muted-fg); display: inline-flex; }\n.ft-card__caret {\n width: 18px;\n height: 18px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-family: var(--ft-mono);\n font-size: 12px;\n color: var(--ft-muted-fg);\n border: 1px solid var(--ft-line);\n}\n.ft-card--active .ft-card__caret {\n color: var(--tier-local);\n border-color: var(--tier-local);\n}\n\n.ft-card__rail {\n display: flex;\n flex-direction: column;\n border-left: 1px solid var(--ft-line);\n background: var(--ft-rail-bg);\n}\n.ft-card__mini {\n flex: 1;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n min-height: 20px;\n background: transparent;\n border: none;\n color: var(--ft-muted-fg);\n cursor: pointer;\n transition: background 150ms, color 150ms;\n border-bottom: 1px solid var(--ft-line);\n padding: 0;\n text-decoration: none;\n}\n.ft-card__mini:last-child { border-bottom: none; }\n.ft-card__mini:hover {\n background: oklch(0.23 0.01 80);\n color: var(--tier-local);\n}\n.ft-card__mini.is-on {\n color: var(--tier-local);\n background: oklch(0.23 0.01 80);\n}\n\n.ft-card--active {\n background: var(--ft-card-active-bg);\n box-shadow: 0 0 0 1px var(--tier-local), 0 14px 34px -16px oklch(0.5 0.18 50 / 0.55);\n transform: scale(1.02);\n}\n.ft-card--dim {\n filter: grayscale(0.85) brightness(0.82);\n opacity: 0.7;\n transform: scale(0.88);\n transform-origin: center left;\n}\n.ft-card--dim .ft-card__label { color: var(--ft-dim-fg); }\n.ft-card--dim:hover {\n filter: grayscale(0.3) brightness(0.96);\n opacity: 1;\n transform: scale(0.94);\n}\n.ft-card--cta {\n border-left-color: var(--ft-accent);\n background: linear-gradient(180deg, oklch(0.23 0.02 55) 0%, oklch(0.2 0.015 60) 100%);\n}\n.ft-card--root {\n border-left-color: var(--ft-accent);\n background: oklch(0.26 0.015 55);\n}\n.ft-card--root .ft-card__icon {\n color: var(--ft-accent);\n border-color: var(--ft-accent);\n}\n\n.ft-detail {\n position: relative;\n margin-top: 0;\n padding: 16px 18px 14px;\n background: var(--ft-detail-bg);\n border: 1px solid var(--ft-line-strong);\n border-left: 2px solid var(--ft-accent);\n border-radius: 3px;\n animation: ftDetailIn 220ms cubic-bezier(.2,.8,.2,1) backwards;\n color: var(--ft-fg);\n width: 320px;\n box-shadow: 0 18px 40px -8px rgba(0,0,0,0.6), 0 2px 8px rgba(0,0,0,0.4);\n}\n.ft-detail__head {\n display: flex;\n align-items: center;\n margin: -2px 28px 10px 0;\n}\n.ft-detail__title {\n font-family: var(--ft-mono);\n font-size: 10px;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: var(--ft-muted-fg);\n}\n.ft-detail__close {\n position: absolute;\n top: 8px;\n right: 8px;\n width: 22px;\n height: 22px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: 1px solid var(--ft-line);\n border-radius: 2px;\n color: var(--ft-muted-fg);\n cursor: pointer;\n padding: 0;\n transition: color 120ms, border-color 120ms, background 120ms;\n}\n.ft-detail__close:hover {\n color: var(--ft-fg);\n border-color: var(--ft-line-strong);\n background: oklch(0.22 0.008 80);\n}\n@keyframes ftDetailIn {\n from { opacity: 0; transform: translateY(-4px); }\n to { opacity: 1; transform: translateY(0); }\n}\n.ft-detail__lead {\n font-family: var(--ft-serif);\n font-size: 15px;\n line-height: 1.35;\n font-style: italic;\n padding-left: 10px;\n border-left: 2px solid var(--ft-accent);\n margin-bottom: 10px;\n}\n.ft-detail__body {\n margin: 0 0 10px;\n font-size: 12px;\n color: var(--ft-muted-fg);\n line-height: 1.5;\n}\n.ft-detail__bullets {\n margin: 0 0 10px;\n padding-left: 16px;\n font-size: 12px;\n color: var(--ft-fg);\n}\n.ft-detail__bullets li { margin-bottom: 3px; }\n.ft-detail__meta {\n margin: 0 0 10px;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n.ft-detail__meta-row {\n display: grid;\n grid-template-columns: 96px 1fr;\n gap: 8px;\n font-size: 11px;\n}\n.ft-detail__meta-row dt {\n font-family: var(--ft-mono);\n font-size: 9.5px;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n color: var(--ft-muted-fg);\n padding-top: 1px;\n}\n.ft-detail__meta-row dd { margin: 0; color: var(--ft-fg); }\n.ft-detail__actions {\n display: flex;\n gap: 6px;\n flex-wrap: wrap;\n margin-top: 8px;\n}\n\n.ft-btn {\n font-family: var(--ft-mono);\n font-size: 10px;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n padding: 7px 10px;\n background: transparent;\n color: var(--ft-fg);\n border: 1px solid var(--ft-line-strong);\n text-decoration: none;\n cursor: pointer;\n display: inline-flex;\n gap: 5px;\n align-items: center;\n transition: border-color 150ms, background 150ms;\n}\n.ft-btn:hover { border-color: var(--ft-accent); }\n.ft-btn--primary {\n background: var(--ft-accent);\n color: oklch(0.18 0.01 50);\n border-color: var(--ft-accent);\n}\n\n@media (max-width: 760px) {\n .ft-header { padding: 16px 18px 14px; }\n .ft-header__title { font-size: 32px; }\n .ft-controls__hint { display: none; }\n .ft-legend { max-width: calc(100% - 24px); left: 10px; bottom: 10px; }\n}\n";
|
|
5269
5282
|
|
|
5270
5283
|
type GameTimerMode = "countdown" | "countup";
|
|
5271
5284
|
type GameTimerThemePreset = "green" | "red" | "blue" | "amber" | "purple" | "pink" | "teal";
|
package/dist/index.d.ts
CHANGED
|
@@ -5257,15 +5257,28 @@ interface FlowTreeProps {
|
|
|
5257
5257
|
hideControls?: boolean;
|
|
5258
5258
|
/** Hide the breadcrumb legend at the bottom-left. */
|
|
5259
5259
|
hideLegend?: boolean;
|
|
5260
|
+
/**
|
|
5261
|
+
* When > 0, cycles the focused path through the root's direct children
|
|
5262
|
+
* every N milliseconds until the user interacts with the tree (clicks a
|
|
5263
|
+
* card, pans, zooms, toggles a detail, or clicks a legend chip). Honors
|
|
5264
|
+
* `prefers-reduced-motion` (disabled if reduced motion is requested).
|
|
5265
|
+
* Default: 0 (disabled).
|
|
5266
|
+
*/
|
|
5267
|
+
autoCycleMs?: number;
|
|
5268
|
+
/**
|
|
5269
|
+
* Explicit paths to cycle through when `autoCycleMs` is set. If omitted,
|
|
5270
|
+
* the tree auto-cycles through the root's direct children.
|
|
5271
|
+
*/
|
|
5272
|
+
autoCyclePaths?: string[][];
|
|
5260
5273
|
}
|
|
5261
|
-
declare function FlowTree({ data, title, eyebrow, tagline, renderIcon: renderIconProp, tierColors: tierColorsProp, resolveHref: resolveHrefProp, layoutOptions, onNodeOpen, defaultFocusedPath, focusedPath: controlledPath, onFocusedPathChange, className, style, hideHeader, hideControls, hideLegend, }: FlowTreeProps): react_jsx_runtime.JSX.Element;
|
|
5274
|
+
declare function FlowTree({ data, title, eyebrow, tagline, renderIcon: renderIconProp, tierColors: tierColorsProp, resolveHref: resolveHrefProp, layoutOptions, onNodeOpen, defaultFocusedPath, focusedPath: controlledPath, onFocusedPathChange, className, style, hideHeader, hideControls, hideLegend, autoCycleMs, autoCyclePaths, }: FlowTreeProps): react_jsx_runtime.JSX.Element;
|
|
5262
5275
|
|
|
5263
5276
|
/**
|
|
5264
5277
|
* FlowTree CSS — injected once per page at runtime on the first mount.
|
|
5265
5278
|
* Self-themed via `--ft-*` CSS variables, all with sensible fallbacks so the
|
|
5266
5279
|
* component works standalone in any light or dark design system.
|
|
5267
5280
|
*/
|
|
5268
|
-
declare const FLOW_TREE_CSS = "\n.ft-shell {\n --ft-bg: var(--ft-bg, oklch(0.185 0.008 80));\n --ft-fg: var(--ft-fg, oklch(0.96 0.005 85));\n --ft-muted-fg: var(--ft-muted-fg, oklch(0.68 0.008 80));\n --ft-dim-fg: var(--ft-dim-fg, oklch(0.5 0.008 80));\n --ft-line: var(--ft-line, oklch(0.28 0.008 80));\n --ft-line-strong: var(--ft-line-strong, oklch(0.4 0.008 80));\n --ft-grid-strong: var(--ft-grid-strong, oklch(0.24 0.008 80));\n --ft-card-bg: var(--ft-card-bg, oklch(0.21 0.008 80));\n --ft-card-active-bg: var(--ft-card-active-bg, oklch(0.25 0.015 60));\n --ft-card-hover-bg: var(--ft-card-hover-bg, oklch(0.23 0.01 80 / 0.6));\n --ft-rail-bg: var(--ft-rail-bg, oklch(0.19 0.008 80));\n --ft-icon-bg: var(--ft-icon-bg, oklch(0.17 0.008 80));\n --ft-detail-bg: var(--ft-detail-bg, oklch(0.16 0.008 80));\n --ft-header-bg: var(--ft-header-bg, linear-gradient(180deg, oklch(0.21 0.01 60) 0%, oklch(0.19 0.008 70) 100%));\n --ft-tier-orange: var(--ft-tier-orange, #f16c25);\n --ft-tier-teal: var(--ft-tier-teal, #5fb7b8);\n --ft-tier-blue: var(--ft-tier-blue, oklch(0.72 0.12 240));\n --ft-tier-amber: var(--ft-tier-amber, oklch(0.8 0.14 75));\n --ft-tier-green: var(--ft-tier-green, oklch(0.74 0.14 155));\n --ft-accent: var(--ft-accent, var(--ft-tier-orange));\n --ft-serif: var(--ft-serif, \"Instrument Serif\", Georgia, serif);\n --ft-sans: var(--ft-sans, \"Inter\", system-ui, sans-serif);\n --ft-mono: var(--ft-mono, \"JetBrains Mono\", ui-monospace, Menlo, monospace);\n\n display: flex;\n flex-direction: column;\n min-height: 0;\n background: var(--ft-bg);\n border: 1px solid var(--ft-line);\n border-radius: 2px;\n overflow: hidden;\n color: var(--ft-fg);\n font-family: var(--ft-sans);\n font-size: 14px;\n line-height: 1.5;\n -webkit-font-smoothing: antialiased;\n box-shadow: 0 30px 60px -30px oklch(0 0 0 / 0.5);\n}\n.ft-shell * { box-sizing: border-box; }\n.ft-shell .ft-mono {\n font-family: var(--ft-mono);\n font-size: 11px;\n letter-spacing: 0.02em;\n}\n\n.ft-header {\n padding: 22px 28px 20px;\n border-bottom: 1px solid var(--ft-line);\n background: var(--ft-header-bg);\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.ft-header__eyebrow {\n font-family: var(--ft-mono);\n font-size: 10.5px;\n letter-spacing: 0.22em;\n text-transform: uppercase;\n color: var(--ft-accent);\n}\n.ft-header__title {\n margin: 0;\n font-family: var(--ft-serif);\n font-weight: 400;\n font-size: 44px;\n line-height: 1;\n letter-spacing: -0.015em;\n color: var(--ft-fg);\n}\n.ft-header__tagline {\n margin: 6px 0 0;\n max-width: 76ch;\n color: var(--ft-muted-fg);\n font-size: 13px;\n}\n\n.ft-stage {\n position: relative;\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n\n.ft-svg {\n display: block;\n width: 100%;\n height: 100%;\n background: transparent;\n cursor: grab;\n touch-action: none;\n user-select: none;\n}\n.ft-svg.is-dragging { cursor: grabbing; }\n\n.ft-controls {\n position: absolute;\n top: 14px;\n right: 14px;\n z-index: 5;\n display: flex;\n align-items: center;\n gap: 6px;\n background: oklch(0.2 0.008 80 / 0.94);\n border: 1px solid var(--ft-line-strong);\n padding: 5px 8px;\n backdrop-filter: blur(8px);\n border-radius: 2px;\n}\n.ft-controls button {\n font-family: var(--ft-mono);\n font-size: 12px;\n width: 26px;\n height: 26px;\n background: transparent;\n border: 1px solid var(--ft-line);\n color: var(--ft-fg);\n cursor: pointer;\n padding: 0;\n}\n.ft-controls button:hover { border-color: var(--ft-accent); }\n.ft-controls__reset {\n width: auto !important;\n padding: 0 10px !important;\n font-size: 9.5px !important;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n}\n.ft-controls__hint {\n font-family: var(--ft-mono);\n font-size: 9.5px;\n color: var(--ft-muted-fg);\n letter-spacing: 0.04em;\n padding-left: 8px;\n margin-left: 2px;\n border-left: 1px solid var(--ft-line);\n}\n\n.ft-legend {\n position: absolute;\n left: 18px;\n bottom: 14px;\n z-index: 5;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n font-family: var(--ft-mono);\n font-size: 10px;\n color: var(--ft-muted-fg);\n background: oklch(0.2 0.008 80 / 0.88);\n border: 1px solid var(--ft-line);\n padding: 6px 10px;\n backdrop-filter: blur(6px);\n max-width: calc(100% - 220px);\n}\n.ft-legend__chip { display: inline-flex; align-items: center; gap: 6px; }\n.ft-legend__dot {\n width: 5px;\n height: 5px;\n border-radius: 50%;\n background: var(--ft-accent);\n}\n.ft-legend__sep { color: var(--ft-line-strong); margin: 0 2px; }\n\n.ft-edge { fill: none; transition: stroke 260ms, opacity 260ms; }\n.ft-edge--off {\n stroke: var(--ft-line);\n stroke-width: 1;\n opacity: 0.55;\n}\n.ft-edge--on {\n stroke: var(--ft-accent);\n stroke-width: 1.6;\n stroke-dasharray: 4 5;\n opacity: 1;\n animation: ftDashFlow 1.4s linear infinite;\n}\n@keyframes ftDashFlow { to { stroke-dashoffset: -36; } }\n\n.ft-card {\n --tier-local: var(--tier, var(--ft-line-strong));\n width: 100%;\n height: 100%;\n display: grid;\n grid-template-columns: 1fr auto;\n align-items: stretch;\n background: var(--ft-card-bg);\n border: 1px solid var(--ft-line);\n border-left: 3px solid var(--tier-local);\n border-radius: 2px;\n transition:\n background 260ms cubic-bezier(.2,.8,.2,1),\n border-color 260ms, box-shadow 260ms,\n transform 260ms cubic-bezier(.2,.8,.2,1),\n filter 260ms, opacity 260ms, color 260ms;\n overflow: visible;\n animation: ftCardIn 320ms cubic-bezier(.2,.8,.2,1) backwards;\n}\n@keyframes ftCardIn {\n from { opacity: 0; transform: translateX(-6px); }\n to { opacity: 1; transform: translateX(0); }\n}\n.ft-card__main {\n display: grid;\n grid-template-columns: auto 1fr auto;\n gap: 10px;\n align-items: center;\n padding: 0 10px 0 12px;\n background: transparent;\n border: none;\n color: inherit;\n font-family: var(--ft-sans);\n font-size: 13px;\n text-align: left;\n cursor: pointer;\n min-width: 0;\n}\n.ft-card__main:hover { background: var(--ft-card-hover-bg); }\n.ft-card__icon {\n width: 24px;\n height: 24px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: var(--tier-local);\n border: 1px solid var(--ft-line-strong);\n background: var(--ft-icon-bg);\n flex-shrink: 0;\n}\n.ft-card__body { display: flex; flex-direction: column; min-width: 0; gap: 1px; }\n.ft-card__label {\n font-family: var(--ft-serif);\n font-size: 15px;\n line-height: 1.15;\n color: var(--ft-fg);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n display: flex;\n align-items: center;\n gap: 5px;\n}\n.ft-card__sub {\n font-family: var(--ft-mono);\n font-size: 9.5px;\n letter-spacing: 0.02em;\n color: var(--ft-muted-fg);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ft-card__lock { color: var(--ft-muted-fg); display: inline-flex; }\n.ft-card__caret {\n width: 18px;\n height: 18px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-family: var(--ft-mono);\n font-size: 12px;\n color: var(--ft-muted-fg);\n border: 1px solid var(--ft-line);\n}\n.ft-card--active .ft-card__caret {\n color: var(--tier-local);\n border-color: var(--tier-local);\n}\n\n.ft-card__rail {\n display: flex;\n flex-direction: column;\n border-left: 1px solid var(--ft-line);\n background: var(--ft-rail-bg);\n}\n.ft-card__mini {\n flex: 1;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n min-height: 20px;\n background: transparent;\n border: none;\n color: var(--ft-muted-fg);\n cursor: pointer;\n transition: background 150ms, color 150ms;\n border-bottom: 1px solid var(--ft-line);\n padding: 0;\n text-decoration: none;\n}\n.ft-card__mini:last-child { border-bottom: none; }\n.ft-card__mini:hover {\n background: oklch(0.23 0.01 80);\n color: var(--tier-local);\n}\n.ft-card__mini.is-on {\n color: var(--tier-local);\n background: oklch(0.23 0.01 80);\n}\n\n.ft-card--active {\n background: var(--ft-card-active-bg);\n box-shadow: 0 0 0 1px var(--tier-local), 0 14px 34px -16px oklch(0.5 0.18 50 / 0.55);\n transform: scale(1.02);\n}\n.ft-card--dim {\n filter: grayscale(0.85) brightness(0.82);\n opacity: 0.7;\n transform: scale(0.88);\n transform-origin: center left;\n}\n.ft-card--dim .ft-card__label { color: var(--ft-dim-fg); }\n.ft-card--dim:hover {\n filter: grayscale(0.3) brightness(0.96);\n opacity: 1;\n transform: scale(0.94);\n}\n.ft-card--cta {\n border-left-color: var(--ft-accent);\n background: linear-gradient(180deg, oklch(0.23 0.02 55) 0%, oklch(0.2 0.015 60) 100%);\n}\n.ft-card--root {\n border-left-color: var(--ft-accent);\n background: oklch(0.26 0.015 55);\n}\n.ft-card--root .ft-card__icon {\n color: var(--ft-accent);\n border-color: var(--ft-accent);\n}\n\n.ft-detail {\n position: relative;\n margin-top: 0;\n padding: 16px 18px 14px;\n background: var(--ft-detail-bg);\n border: 1px solid var(--ft-line-strong);\n border-left: 2px solid var(--ft-accent);\n border-radius: 3px;\n animation: ftDetailIn 220ms cubic-bezier(.2,.8,.2,1) backwards;\n color: var(--ft-fg);\n width: 320px;\n box-shadow: 0 18px 40px -8px rgba(0,0,0,0.6), 0 2px 8px rgba(0,0,0,0.4);\n}\n.ft-detail__head {\n display: flex;\n align-items: center;\n margin: -2px 28px 10px 0;\n}\n.ft-detail__title {\n font-family: var(--ft-mono);\n font-size: 10px;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: var(--ft-muted-fg);\n}\n.ft-detail__close {\n position: absolute;\n top: 8px;\n right: 8px;\n width: 22px;\n height: 22px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: 1px solid var(--ft-line);\n border-radius: 2px;\n color: var(--ft-muted-fg);\n cursor: pointer;\n padding: 0;\n transition: color 120ms, border-color 120ms, background 120ms;\n}\n.ft-detail__close:hover {\n color: var(--ft-fg);\n border-color: var(--ft-line-strong);\n background: oklch(0.22 0.008 80);\n}\n@keyframes ftDetailIn {\n from { opacity: 0; transform: translateY(-4px); }\n to { opacity: 1; transform: translateY(0); }\n}\n.ft-detail__lead {\n font-family: var(--ft-serif);\n font-size: 15px;\n line-height: 1.35;\n font-style: italic;\n padding-left: 10px;\n border-left: 2px solid var(--ft-accent);\n margin-bottom: 10px;\n}\n.ft-detail__body {\n margin: 0 0 10px;\n font-size: 12px;\n color: var(--ft-muted-fg);\n line-height: 1.5;\n}\n.ft-detail__bullets {\n margin: 0 0 10px;\n padding-left: 16px;\n font-size: 12px;\n color: var(--ft-fg);\n}\n.ft-detail__bullets li { margin-bottom: 3px; }\n.ft-detail__meta {\n margin: 0 0 10px;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n.ft-detail__meta-row {\n display: grid;\n grid-template-columns: 96px 1fr;\n gap: 8px;\n font-size: 11px;\n}\n.ft-detail__meta-row dt {\n font-family: var(--ft-mono);\n font-size: 9.5px;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n color: var(--ft-muted-fg);\n padding-top: 1px;\n}\n.ft-detail__meta-row dd { margin: 0; color: var(--ft-fg); }\n.ft-detail__actions {\n display: flex;\n gap: 6px;\n flex-wrap: wrap;\n margin-top: 8px;\n}\n\n.ft-btn {\n font-family: var(--ft-mono);\n font-size: 10px;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n padding: 7px 10px;\n background: transparent;\n color: var(--ft-fg);\n border: 1px solid var(--ft-line-strong);\n text-decoration: none;\n cursor: pointer;\n display: inline-flex;\n gap: 5px;\n align-items: center;\n transition: border-color 150ms, background 150ms;\n}\n.ft-btn:hover { border-color: var(--ft-accent); }\n.ft-btn--primary {\n background: var(--ft-accent);\n color: oklch(0.18 0.01 50);\n border-color: var(--ft-accent);\n}\n\n@media (max-width: 760px) {\n .ft-header { padding: 16px 18px 14px; }\n .ft-header__title { font-size: 32px; }\n .ft-controls__hint { display: none; }\n .ft-legend { max-width: calc(100% - 24px); left: 10px; bottom: 10px; }\n}\n";
|
|
5281
|
+
declare const FLOW_TREE_CSS = "\n.ft-shell {\n --ft-bg: var(--ft-bg, oklch(0.185 0.008 80));\n --ft-fg: var(--ft-fg, oklch(0.96 0.005 85));\n --ft-muted-fg: var(--ft-muted-fg, oklch(0.68 0.008 80));\n --ft-dim-fg: var(--ft-dim-fg, oklch(0.5 0.008 80));\n --ft-line: var(--ft-line, oklch(0.28 0.008 80));\n --ft-line-strong: var(--ft-line-strong, oklch(0.4 0.008 80));\n --ft-grid-strong: var(--ft-grid-strong, oklch(0.24 0.008 80));\n --ft-card-bg: var(--ft-card-bg, oklch(0.21 0.008 80));\n --ft-card-active-bg: var(--ft-card-active-bg, oklch(0.25 0.015 60));\n --ft-card-hover-bg: var(--ft-card-hover-bg, oklch(0.23 0.01 80 / 0.6));\n --ft-rail-bg: var(--ft-rail-bg, oklch(0.19 0.008 80));\n --ft-icon-bg: var(--ft-icon-bg, oklch(0.17 0.008 80));\n --ft-detail-bg: var(--ft-detail-bg, oklch(0.16 0.008 80));\n --ft-header-bg: var(--ft-header-bg, linear-gradient(180deg, oklch(0.21 0.01 60) 0%, oklch(0.19 0.008 70) 100%));\n --ft-tier-orange: var(--ft-tier-orange, #f16c25);\n --ft-tier-teal: var(--ft-tier-teal, #5fb7b8);\n --ft-tier-blue: var(--ft-tier-blue, oklch(0.72 0.12 240));\n --ft-tier-amber: var(--ft-tier-amber, oklch(0.8 0.14 75));\n --ft-tier-green: var(--ft-tier-green, oklch(0.74 0.14 155));\n --ft-accent: var(--ft-accent, var(--ft-tier-orange));\n --ft-serif: var(--ft-serif, \"Instrument Serif\", Georgia, serif);\n --ft-sans: var(--ft-sans, \"Inter\", system-ui, sans-serif);\n --ft-mono: var(--ft-mono, \"JetBrains Mono\", ui-monospace, Menlo, monospace);\n\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n min-height: 420px;\n background: var(--ft-bg);\n border: 1px solid var(--ft-line);\n border-radius: 2px;\n overflow: hidden;\n color: var(--ft-fg);\n font-family: var(--ft-sans);\n font-size: 14px;\n line-height: 1.5;\n -webkit-font-smoothing: antialiased;\n box-shadow: 0 30px 60px -30px oklch(0 0 0 / 0.5);\n}\n.ft-shell * { box-sizing: border-box; }\n.ft-shell .ft-mono {\n font-family: var(--ft-mono);\n font-size: 11px;\n letter-spacing: 0.02em;\n}\n\n.ft-header {\n padding: 22px 28px 20px;\n border-bottom: 1px solid var(--ft-line);\n background: var(--ft-header-bg);\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.ft-header__eyebrow {\n font-family: var(--ft-mono);\n font-size: 10.5px;\n letter-spacing: 0.22em;\n text-transform: uppercase;\n color: var(--ft-accent);\n}\n.ft-header__title {\n margin: 0;\n font-family: var(--ft-serif);\n font-weight: 400;\n font-size: 44px;\n line-height: 1;\n letter-spacing: -0.015em;\n color: var(--ft-fg);\n}\n.ft-header__tagline {\n margin: 6px 0 0;\n max-width: 76ch;\n color: var(--ft-muted-fg);\n font-size: 13px;\n}\n\n.ft-stage {\n position: relative;\n flex: 1;\n min-height: 0;\n overflow: hidden;\n background:\n radial-gradient(1000px 600px at 15% -10%, oklch(0.22 0.012 60 / 0.7), transparent 60%),\n radial-gradient(800px 500px at 110% 110%, oklch(0.2 0.02 200 / 0.35), transparent 65%);\n}\n\n.ft-svg {\n display: block;\n width: 100%;\n height: 100%;\n background: transparent;\n cursor: grab;\n touch-action: none;\n user-select: none;\n}\n.ft-svg.is-dragging { cursor: grabbing; }\n\n.ft-controls {\n position: absolute;\n top: 14px;\n right: 14px;\n z-index: 5;\n display: flex;\n align-items: center;\n gap: 6px;\n background: oklch(0.2 0.008 80 / 0.94);\n border: 1px solid var(--ft-line-strong);\n padding: 5px 8px;\n backdrop-filter: blur(8px);\n border-radius: 2px;\n}\n.ft-controls button {\n font-family: var(--ft-mono);\n font-size: 12px;\n width: 26px;\n height: 26px;\n background: transparent;\n border: 1px solid var(--ft-line);\n color: var(--ft-fg);\n cursor: pointer;\n padding: 0;\n}\n.ft-controls button:hover { border-color: var(--ft-accent); }\n.ft-controls__reset {\n width: auto !important;\n padding: 0 10px !important;\n font-size: 9.5px !important;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n}\n.ft-controls__hint {\n font-family: var(--ft-mono);\n font-size: 9.5px;\n color: var(--ft-muted-fg);\n letter-spacing: 0.04em;\n padding-left: 8px;\n margin-left: 2px;\n border-left: 1px solid var(--ft-line);\n}\n\n.ft-legend {\n position: absolute;\n left: 18px;\n bottom: 14px;\n z-index: 5;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n font-family: var(--ft-mono);\n font-size: 10px;\n color: var(--ft-muted-fg);\n background: oklch(0.2 0.008 80 / 0.88);\n border: 1px solid var(--ft-line);\n padding: 6px 10px;\n backdrop-filter: blur(6px);\n max-width: calc(100% - 220px);\n}\n.ft-legend__chip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 2px 6px;\n margin: -2px 0;\n background: transparent;\n border: none;\n color: inherit;\n font: inherit;\n letter-spacing: inherit;\n cursor: pointer;\n border-radius: 2px;\n transition: background 120ms, color 120ms;\n}\n.ft-legend__chip:hover {\n background: oklch(0.24 0.01 80);\n color: var(--ft-fg);\n}\n.ft-legend__chip:disabled {\n cursor: default;\n color: var(--ft-fg);\n}\n.ft-legend__chip:disabled:hover { background: transparent; }\n.ft-legend__dot {\n width: 5px;\n height: 5px;\n border-radius: 50%;\n background: var(--ft-accent);\n flex-shrink: 0;\n}\n.ft-legend__sep {\n color: var(--ft-line-strong);\n margin: 0 2px;\n pointer-events: none;\n user-select: none;\n}\n\n.ft-edge {\n fill: none;\n /* Critical: keep strokes the same screen size regardless of the tree's\n scale transform. Without this, fit-to-viewport (z \u2248 0.6-0.9) makes\n the edges sub-pixel wide and they visually disappear. */\n vector-effect: non-scaling-stroke;\n transition: stroke 260ms, opacity 260ms, stroke-width 260ms;\n}\n.ft-edge--off {\n /* Use the accent color at low opacity instead of the dim line color \u2014\n the accent (orange by default) reads far better on a dark stage. */\n stroke: var(--ft-accent);\n stroke-width: 1.5;\n stroke-dasharray: 3 5;\n opacity: 0.35;\n}\n.ft-edge--on {\n stroke: var(--ft-accent);\n stroke-width: 2.2;\n stroke-dasharray: 6 5;\n opacity: 1;\n filter: drop-shadow(0 0 6px var(--ft-accent));\n animation: ftDashFlow 1.4s linear infinite;\n}\n@keyframes ftDashFlow { to { stroke-dashoffset: -44; } }\n@media (prefers-reduced-motion: reduce) {\n .ft-edge--on { animation: none; }\n}\n\n.ft-card {\n --tier-local: var(--tier, var(--ft-line-strong));\n width: 100%;\n height: 100%;\n display: grid;\n grid-template-columns: 1fr auto;\n align-items: stretch;\n background: var(--ft-card-bg);\n border: 1px solid var(--ft-line);\n border-left: 3px solid var(--tier-local);\n border-radius: 2px;\n transition:\n background 260ms cubic-bezier(.2,.8,.2,1),\n border-color 260ms, box-shadow 260ms,\n transform 260ms cubic-bezier(.2,.8,.2,1),\n filter 260ms, opacity 260ms, color 260ms;\n overflow: visible;\n animation: ftCardIn 320ms cubic-bezier(.2,.8,.2,1) backwards;\n}\n@keyframes ftCardIn {\n from { opacity: 0; transform: translateX(-6px); }\n to { opacity: 1; transform: translateX(0); }\n}\n.ft-card__main {\n display: grid;\n grid-template-columns: auto 1fr auto;\n gap: 10px;\n align-items: center;\n padding: 0 10px 0 12px;\n background: transparent;\n border: none;\n color: inherit;\n font-family: var(--ft-sans);\n font-size: 13px;\n text-align: left;\n cursor: pointer;\n min-width: 0;\n}\n.ft-card__main:hover { background: var(--ft-card-hover-bg); }\n.ft-card__icon {\n width: 24px;\n height: 24px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: var(--tier-local);\n border: 1px solid var(--ft-line-strong);\n background: var(--ft-icon-bg);\n flex-shrink: 0;\n}\n.ft-card__body { display: flex; flex-direction: column; min-width: 0; gap: 1px; }\n.ft-card__label {\n font-family: var(--ft-serif);\n font-size: 15px;\n line-height: 1.15;\n color: var(--ft-fg);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n display: flex;\n align-items: center;\n gap: 5px;\n}\n.ft-card__sub {\n font-family: var(--ft-mono);\n font-size: 9.5px;\n letter-spacing: 0.02em;\n color: var(--ft-muted-fg);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.ft-card__lock { color: var(--ft-muted-fg); display: inline-flex; }\n.ft-card__caret {\n width: 18px;\n height: 18px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-family: var(--ft-mono);\n font-size: 12px;\n color: var(--ft-muted-fg);\n border: 1px solid var(--ft-line);\n}\n.ft-card--active .ft-card__caret {\n color: var(--tier-local);\n border-color: var(--tier-local);\n}\n\n.ft-card__rail {\n display: flex;\n flex-direction: column;\n border-left: 1px solid var(--ft-line);\n background: var(--ft-rail-bg);\n}\n.ft-card__mini {\n flex: 1;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n min-height: 20px;\n background: transparent;\n border: none;\n color: var(--ft-muted-fg);\n cursor: pointer;\n transition: background 150ms, color 150ms;\n border-bottom: 1px solid var(--ft-line);\n padding: 0;\n text-decoration: none;\n}\n.ft-card__mini:last-child { border-bottom: none; }\n.ft-card__mini:hover {\n background: oklch(0.23 0.01 80);\n color: var(--tier-local);\n}\n.ft-card__mini.is-on {\n color: var(--tier-local);\n background: oklch(0.23 0.01 80);\n}\n\n.ft-card--active {\n background: var(--ft-card-active-bg);\n box-shadow: 0 0 0 1px var(--tier-local), 0 14px 34px -16px oklch(0.5 0.18 50 / 0.55);\n transform: scale(1.02);\n}\n.ft-card--dim {\n filter: grayscale(0.85) brightness(0.82);\n opacity: 0.7;\n transform: scale(0.88);\n transform-origin: center left;\n}\n.ft-card--dim .ft-card__label { color: var(--ft-dim-fg); }\n.ft-card--dim:hover {\n filter: grayscale(0.3) brightness(0.96);\n opacity: 1;\n transform: scale(0.94);\n}\n.ft-card--cta {\n border-left-color: var(--ft-accent);\n background: linear-gradient(180deg, oklch(0.23 0.02 55) 0%, oklch(0.2 0.015 60) 100%);\n}\n.ft-card--root {\n border-left-color: var(--ft-accent);\n background: oklch(0.26 0.015 55);\n}\n.ft-card--root .ft-card__icon {\n color: var(--ft-accent);\n border-color: var(--ft-accent);\n}\n\n.ft-detail {\n position: relative;\n margin-top: 0;\n padding: 16px 18px 14px;\n background: var(--ft-detail-bg);\n border: 1px solid var(--ft-line-strong);\n border-left: 2px solid var(--ft-accent);\n border-radius: 3px;\n animation: ftDetailIn 220ms cubic-bezier(.2,.8,.2,1) backwards;\n color: var(--ft-fg);\n width: 320px;\n box-shadow: 0 18px 40px -8px rgba(0,0,0,0.6), 0 2px 8px rgba(0,0,0,0.4);\n}\n.ft-detail__head {\n display: flex;\n align-items: center;\n margin: -2px 28px 10px 0;\n}\n.ft-detail__title {\n font-family: var(--ft-mono);\n font-size: 10px;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: var(--ft-muted-fg);\n}\n.ft-detail__close {\n position: absolute;\n top: 8px;\n right: 8px;\n width: 22px;\n height: 22px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: 1px solid var(--ft-line);\n border-radius: 2px;\n color: var(--ft-muted-fg);\n cursor: pointer;\n padding: 0;\n transition: color 120ms, border-color 120ms, background 120ms;\n}\n.ft-detail__close:hover {\n color: var(--ft-fg);\n border-color: var(--ft-line-strong);\n background: oklch(0.22 0.008 80);\n}\n@keyframes ftDetailIn {\n from { opacity: 0; transform: translateY(-4px); }\n to { opacity: 1; transform: translateY(0); }\n}\n.ft-detail__lead {\n font-family: var(--ft-serif);\n font-size: 15px;\n line-height: 1.35;\n font-style: italic;\n padding-left: 10px;\n border-left: 2px solid var(--ft-accent);\n margin-bottom: 10px;\n}\n.ft-detail__body {\n margin: 0 0 10px;\n font-size: 12px;\n color: var(--ft-muted-fg);\n line-height: 1.5;\n}\n.ft-detail__bullets {\n margin: 0 0 10px;\n padding-left: 16px;\n font-size: 12px;\n color: var(--ft-fg);\n}\n.ft-detail__bullets li { margin-bottom: 3px; }\n.ft-detail__meta {\n margin: 0 0 10px;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n.ft-detail__meta-row {\n display: grid;\n grid-template-columns: 96px 1fr;\n gap: 8px;\n font-size: 11px;\n}\n.ft-detail__meta-row dt {\n font-family: var(--ft-mono);\n font-size: 9.5px;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n color: var(--ft-muted-fg);\n padding-top: 1px;\n}\n.ft-detail__meta-row dd { margin: 0; color: var(--ft-fg); }\n.ft-detail__actions {\n display: flex;\n gap: 6px;\n flex-wrap: wrap;\n margin-top: 8px;\n}\n\n.ft-btn {\n font-family: var(--ft-mono);\n font-size: 10px;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n padding: 7px 10px;\n background: transparent;\n color: var(--ft-fg);\n border: 1px solid var(--ft-line-strong);\n text-decoration: none;\n cursor: pointer;\n display: inline-flex;\n gap: 5px;\n align-items: center;\n transition: border-color 150ms, background 150ms;\n}\n.ft-btn:hover { border-color: var(--ft-accent); }\n.ft-btn--primary {\n background: var(--ft-accent);\n color: oklch(0.18 0.01 50);\n border-color: var(--ft-accent);\n}\n\n@media (max-width: 760px) {\n .ft-header { padding: 16px 18px 14px; }\n .ft-header__title { font-size: 32px; }\n .ft-controls__hint { display: none; }\n .ft-legend { max-width: calc(100% - 24px); left: 10px; bottom: 10px; }\n}\n";
|
|
5269
5282
|
|
|
5270
5283
|
type GameTimerMode = "countdown" | "countup";
|
|
5271
5284
|
type GameTimerThemePreset = "green" | "red" | "blue" | "amber" | "purple" | "pink" | "teal";
|
package/dist/index.js
CHANGED
|
@@ -35940,7 +35940,9 @@ var FLOW_TREE_CSS = `
|
|
|
35940
35940
|
|
|
35941
35941
|
display: flex;
|
|
35942
35942
|
flex-direction: column;
|
|
35943
|
-
|
|
35943
|
+
width: 100%;
|
|
35944
|
+
height: 100%;
|
|
35945
|
+
min-height: 420px;
|
|
35944
35946
|
background: var(--ft-bg);
|
|
35945
35947
|
border: 1px solid var(--ft-line);
|
|
35946
35948
|
border-radius: 2px;
|
|
@@ -35995,6 +35997,9 @@ var FLOW_TREE_CSS = `
|
|
|
35995
35997
|
flex: 1;
|
|
35996
35998
|
min-height: 0;
|
|
35997
35999
|
overflow: hidden;
|
|
36000
|
+
background:
|
|
36001
|
+
radial-gradient(1000px 600px at 15% -10%, oklch(0.22 0.012 60 / 0.7), transparent 60%),
|
|
36002
|
+
radial-gradient(800px 500px at 110% 110%, oklch(0.2 0.02 200 / 0.35), transparent 65%);
|
|
35998
36003
|
}
|
|
35999
36004
|
|
|
36000
36005
|
.ft-svg {
|
|
@@ -36069,29 +36074,72 @@ var FLOW_TREE_CSS = `
|
|
|
36069
36074
|
backdrop-filter: blur(6px);
|
|
36070
36075
|
max-width: calc(100% - 220px);
|
|
36071
36076
|
}
|
|
36072
|
-
.ft-legend__chip {
|
|
36077
|
+
.ft-legend__chip {
|
|
36078
|
+
display: inline-flex;
|
|
36079
|
+
align-items: center;
|
|
36080
|
+
gap: 6px;
|
|
36081
|
+
padding: 2px 6px;
|
|
36082
|
+
margin: -2px 0;
|
|
36083
|
+
background: transparent;
|
|
36084
|
+
border: none;
|
|
36085
|
+
color: inherit;
|
|
36086
|
+
font: inherit;
|
|
36087
|
+
letter-spacing: inherit;
|
|
36088
|
+
cursor: pointer;
|
|
36089
|
+
border-radius: 2px;
|
|
36090
|
+
transition: background 120ms, color 120ms;
|
|
36091
|
+
}
|
|
36092
|
+
.ft-legend__chip:hover {
|
|
36093
|
+
background: oklch(0.24 0.01 80);
|
|
36094
|
+
color: var(--ft-fg);
|
|
36095
|
+
}
|
|
36096
|
+
.ft-legend__chip:disabled {
|
|
36097
|
+
cursor: default;
|
|
36098
|
+
color: var(--ft-fg);
|
|
36099
|
+
}
|
|
36100
|
+
.ft-legend__chip:disabled:hover { background: transparent; }
|
|
36073
36101
|
.ft-legend__dot {
|
|
36074
36102
|
width: 5px;
|
|
36075
36103
|
height: 5px;
|
|
36076
36104
|
border-radius: 50%;
|
|
36077
36105
|
background: var(--ft-accent);
|
|
36106
|
+
flex-shrink: 0;
|
|
36107
|
+
}
|
|
36108
|
+
.ft-legend__sep {
|
|
36109
|
+
color: var(--ft-line-strong);
|
|
36110
|
+
margin: 0 2px;
|
|
36111
|
+
pointer-events: none;
|
|
36112
|
+
user-select: none;
|
|
36078
36113
|
}
|
|
36079
|
-
.ft-legend__sep { color: var(--ft-line-strong); margin: 0 2px; }
|
|
36080
36114
|
|
|
36081
|
-
.ft-edge {
|
|
36115
|
+
.ft-edge {
|
|
36116
|
+
fill: none;
|
|
36117
|
+
/* Critical: keep strokes the same screen size regardless of the tree's
|
|
36118
|
+
scale transform. Without this, fit-to-viewport (z \u2248 0.6-0.9) makes
|
|
36119
|
+
the edges sub-pixel wide and they visually disappear. */
|
|
36120
|
+
vector-effect: non-scaling-stroke;
|
|
36121
|
+
transition: stroke 260ms, opacity 260ms, stroke-width 260ms;
|
|
36122
|
+
}
|
|
36082
36123
|
.ft-edge--off {
|
|
36083
|
-
|
|
36084
|
-
|
|
36085
|
-
|
|
36124
|
+
/* Use the accent color at low opacity instead of the dim line color \u2014
|
|
36125
|
+
the accent (orange by default) reads far better on a dark stage. */
|
|
36126
|
+
stroke: var(--ft-accent);
|
|
36127
|
+
stroke-width: 1.5;
|
|
36128
|
+
stroke-dasharray: 3 5;
|
|
36129
|
+
opacity: 0.35;
|
|
36086
36130
|
}
|
|
36087
36131
|
.ft-edge--on {
|
|
36088
36132
|
stroke: var(--ft-accent);
|
|
36089
|
-
stroke-width:
|
|
36090
|
-
stroke-dasharray:
|
|
36133
|
+
stroke-width: 2.2;
|
|
36134
|
+
stroke-dasharray: 6 5;
|
|
36091
36135
|
opacity: 1;
|
|
36136
|
+
filter: drop-shadow(0 0 6px var(--ft-accent));
|
|
36092
36137
|
animation: ftDashFlow 1.4s linear infinite;
|
|
36093
36138
|
}
|
|
36094
|
-
@keyframes ftDashFlow { to { stroke-dashoffset: -
|
|
36139
|
+
@keyframes ftDashFlow { to { stroke-dashoffset: -44; } }
|
|
36140
|
+
@media (prefers-reduced-motion: reduce) {
|
|
36141
|
+
.ft-edge--on { animation: none; }
|
|
36142
|
+
}
|
|
36095
36143
|
|
|
36096
36144
|
.ft-card {
|
|
36097
36145
|
--tier-local: var(--tier, var(--ft-line-strong));
|
|
@@ -36388,11 +36436,11 @@ var DEFAULT_TIER_COLORS = {
|
|
|
36388
36436
|
gray: "var(--ft-line-strong)"
|
|
36389
36437
|
};
|
|
36390
36438
|
var DEFAULT_LAYOUT = {
|
|
36391
|
-
col:
|
|
36392
|
-
row:
|
|
36393
|
-
compactRow:
|
|
36394
|
-
cardW:
|
|
36395
|
-
cardH:
|
|
36439
|
+
col: 290,
|
|
36440
|
+
row: 76,
|
|
36441
|
+
compactRow: 48,
|
|
36442
|
+
cardW: 248,
|
|
36443
|
+
cardH: 60,
|
|
36396
36444
|
detailMaxW: 320
|
|
36397
36445
|
};
|
|
36398
36446
|
var STYLE_ID4 = "dll-flow-tree-styles";
|
|
@@ -36745,7 +36793,9 @@ function FlowTree({
|
|
|
36745
36793
|
style,
|
|
36746
36794
|
hideHeader = false,
|
|
36747
36795
|
hideControls = false,
|
|
36748
|
-
hideLegend = false
|
|
36796
|
+
hideLegend = false,
|
|
36797
|
+
autoCycleMs = 0,
|
|
36798
|
+
autoCyclePaths
|
|
36749
36799
|
}) {
|
|
36750
36800
|
React87.useEffect(() => {
|
|
36751
36801
|
ensureStylesInjected4();
|
|
@@ -36789,31 +36839,84 @@ function FlowTree({
|
|
|
36789
36839
|
},
|
|
36790
36840
|
[controlledPath, onFocusedPathChange]
|
|
36791
36841
|
);
|
|
36842
|
+
const [hasUserInteracted, setHasUserInteracted] = React87.useState(false);
|
|
36843
|
+
const markInteracted = React87.useCallback(() => {
|
|
36844
|
+
setHasUserInteracted(true);
|
|
36845
|
+
}, []);
|
|
36792
36846
|
const [expandedDetails, setExpandedDetails] = React87.useState(
|
|
36793
36847
|
() => /* @__PURE__ */ new Set()
|
|
36794
36848
|
);
|
|
36795
|
-
const toggleDetail = React87.useCallback(
|
|
36796
|
-
|
|
36797
|
-
|
|
36798
|
-
|
|
36799
|
-
|
|
36800
|
-
|
|
36801
|
-
|
|
36802
|
-
|
|
36803
|
-
|
|
36804
|
-
|
|
36805
|
-
|
|
36806
|
-
|
|
36807
|
-
|
|
36808
|
-
|
|
36809
|
-
|
|
36849
|
+
const toggleDetail = React87.useCallback(
|
|
36850
|
+
(n) => {
|
|
36851
|
+
markInteracted();
|
|
36852
|
+
setExpandedDetails((prev) => {
|
|
36853
|
+
const next = new Set(prev);
|
|
36854
|
+
if (next.has(n.data.id)) next.delete(n.data.id);
|
|
36855
|
+
else next.add(n.data.id);
|
|
36856
|
+
return next;
|
|
36857
|
+
});
|
|
36858
|
+
},
|
|
36859
|
+
[markInteracted]
|
|
36860
|
+
);
|
|
36861
|
+
const closeDetail = React87.useCallback(
|
|
36862
|
+
(id) => {
|
|
36863
|
+
markInteracted();
|
|
36864
|
+
setExpandedDetails((prev) => {
|
|
36865
|
+
const next = new Set(prev);
|
|
36866
|
+
next.delete(id);
|
|
36867
|
+
return next;
|
|
36868
|
+
});
|
|
36869
|
+
},
|
|
36870
|
+
[markInteracted]
|
|
36871
|
+
);
|
|
36810
36872
|
const activate = React87.useCallback(
|
|
36811
36873
|
(n) => {
|
|
36874
|
+
markInteracted();
|
|
36812
36875
|
setFocusedPath(n.pathArr);
|
|
36813
36876
|
setExpandedDetails(/* @__PURE__ */ new Set());
|
|
36814
36877
|
},
|
|
36815
|
-
[setFocusedPath]
|
|
36878
|
+
[setFocusedPath, markInteracted]
|
|
36879
|
+
);
|
|
36880
|
+
const focusPathPrefix = React87.useCallback(
|
|
36881
|
+
(prefixLen) => {
|
|
36882
|
+
if (prefixLen < 1 || prefixLen >= focusedPath.length) return;
|
|
36883
|
+
markInteracted();
|
|
36884
|
+
setFocusedPath(focusedPath.slice(0, prefixLen));
|
|
36885
|
+
setExpandedDetails(/* @__PURE__ */ new Set());
|
|
36886
|
+
},
|
|
36887
|
+
[focusedPath, setFocusedPath, markInteracted]
|
|
36816
36888
|
);
|
|
36889
|
+
const resolvedCyclePaths = React87.useMemo(() => {
|
|
36890
|
+
if (!autoCycleMs || autoCycleMs <= 0) return [];
|
|
36891
|
+
if (autoCyclePaths && autoCyclePaths.length) return autoCyclePaths;
|
|
36892
|
+
return (data.children ?? []).map((c) => [data.id, c.id]);
|
|
36893
|
+
}, [autoCycleMs, autoCyclePaths, data]);
|
|
36894
|
+
React87.useEffect(() => {
|
|
36895
|
+
if (!autoCycleMs || autoCycleMs <= 0) return;
|
|
36896
|
+
if (hasUserInteracted) return;
|
|
36897
|
+
if (controlledPath) return;
|
|
36898
|
+
if (resolvedCyclePaths.length === 0) return;
|
|
36899
|
+
if (typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
|
|
36900
|
+
return;
|
|
36901
|
+
}
|
|
36902
|
+
const currentKey = focusedPath.join("/");
|
|
36903
|
+
let i = Math.max(
|
|
36904
|
+
0,
|
|
36905
|
+
resolvedCyclePaths.findIndex((p) => p.join("/") === currentKey)
|
|
36906
|
+
);
|
|
36907
|
+
const id = window.setInterval(() => {
|
|
36908
|
+
i = (i + 1) % resolvedCyclePaths.length;
|
|
36909
|
+
const next = resolvedCyclePaths[i];
|
|
36910
|
+
if (next) setFocusedPath(next);
|
|
36911
|
+
}, autoCycleMs);
|
|
36912
|
+
return () => window.clearInterval(id);
|
|
36913
|
+
}, [
|
|
36914
|
+
autoCycleMs,
|
|
36915
|
+
hasUserInteracted,
|
|
36916
|
+
controlledPath,
|
|
36917
|
+
resolvedCyclePaths,
|
|
36918
|
+
setFocusedPath
|
|
36919
|
+
]);
|
|
36817
36920
|
const { nodes, edges, width, height } = React87.useMemo(
|
|
36818
36921
|
() => layoutTree(data, focusedPath, opts, expandedDetails),
|
|
36819
36922
|
[data, focusedPath.join("/"), opts, expandedDetails]
|
|
@@ -36873,6 +36976,7 @@ function FlowTree({
|
|
|
36873
36976
|
const onPointerDown = (e) => {
|
|
36874
36977
|
if (e.target.closest("button, a")) return;
|
|
36875
36978
|
userInteractedRef.current = true;
|
|
36979
|
+
markInteracted();
|
|
36876
36980
|
dragRef.current = { sx: e.clientX, sy: e.clientY, px: pan.x, py: pan.y };
|
|
36877
36981
|
e.currentTarget.setPointerCapture?.(e.pointerId);
|
|
36878
36982
|
e.currentTarget.classList.add("is-dragging");
|
|
@@ -36892,6 +36996,7 @@ function FlowTree({
|
|
|
36892
36996
|
if (!e.ctrlKey && !e.metaKey) return;
|
|
36893
36997
|
e.preventDefault();
|
|
36894
36998
|
userInteractedRef.current = true;
|
|
36999
|
+
markInteracted();
|
|
36895
37000
|
setZoom((z) => Math.max(0.35, Math.min(2, z + -e.deltaY * 15e-4)));
|
|
36896
37001
|
};
|
|
36897
37002
|
const resetView = () => {
|
|
@@ -37067,10 +37172,23 @@ function FlowTree({
|
|
|
37067
37172
|
),
|
|
37068
37173
|
!hideLegend ? /* @__PURE__ */ (0, import_jsx_runtime120.jsx)("div", { className: "ft-legend ft-mono", children: focusedPath.map((id, i) => {
|
|
37069
37174
|
const n = nodeById[id];
|
|
37070
|
-
|
|
37071
|
-
|
|
37072
|
-
|
|
37073
|
-
|
|
37175
|
+
const isLast = i === focusedPath.length - 1;
|
|
37176
|
+
return /* @__PURE__ */ (0, import_jsx_runtime120.jsxs)(React87.Fragment, { children: [
|
|
37177
|
+
/* @__PURE__ */ (0, import_jsx_runtime120.jsxs)(
|
|
37178
|
+
"button",
|
|
37179
|
+
{
|
|
37180
|
+
type: "button",
|
|
37181
|
+
className: "ft-legend__chip",
|
|
37182
|
+
onClick: () => focusPathPrefix(i + 1),
|
|
37183
|
+
disabled: isLast,
|
|
37184
|
+
title: isLast ? "Current focus" : `Jump back to ${n ? n.data.label : id}`,
|
|
37185
|
+
children: [
|
|
37186
|
+
/* @__PURE__ */ (0, import_jsx_runtime120.jsx)("span", { className: "ft-legend__dot" }),
|
|
37187
|
+
n ? n.data.label : id
|
|
37188
|
+
]
|
|
37189
|
+
}
|
|
37190
|
+
),
|
|
37191
|
+
!isLast ? /* @__PURE__ */ (0, import_jsx_runtime120.jsx)("span", { className: "ft-legend__sep", "aria-hidden": true, children: "\u203A" }) : null
|
|
37074
37192
|
] }, id);
|
|
37075
37193
|
}) }) : null
|
|
37076
37194
|
] })
|