foldkit 0.91.0 → 0.93.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/dist/devTools/overlay-styles.d.ts +1 -1
- package/dist/devTools/overlay-styles.d.ts.map +1 -1
- package/dist/devTools/overlay-styles.js +65 -0
- package/dist/devTools/overlay.d.ts +1 -0
- package/dist/devTools/overlay.d.ts.map +1 -1
- package/dist/devTools/overlay.js +154 -41
- package/dist/devTools/store.d.ts +12 -1
- package/dist/devTools/store.d.ts.map +1 -1
- package/dist/devTools/store.js +23 -7
- package/dist/route/parser.js +1 -1
- package/dist/runtime/public.d.ts +1 -1
- package/dist/runtime/public.d.ts.map +1 -1
- package/dist/runtime/runtime.d.ts +15 -2
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +50 -7
- package/dist/ui/dragAndDrop/index.d.ts +3 -3
- package/dist/ui/slider/index.d.ts +70 -12
- package/dist/ui/slider/index.d.ts.map +1 -1
- package/dist/ui/slider/index.js +34 -15
- package/dist/ui/slider/public.d.ts +1 -1
- package/dist/ui/slider/public.d.ts.map +1 -1
- package/dist/ui/slider/public.js +1 -1
- package/package.json +6 -6
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
declare const overlayStyles = ":host {\n position: relative;\n z-index: 2147483647;\n\n --dt-bg: #1e1e2e;\n --dt-surface-selected: #282839;\n --dt-border: #45475a;\n --dt-text: #cdd6f4;\n --dt-text-muted: #9399b2;\n --dt-accent: #cba6f7;\n --dt-live: #a6e3a1;\n --dt-paused: #fab387;\n --dt-json-string: #a6e3a1;\n --dt-json-number: #89b4fa;\n --dt-json-boolean: #fab387;\n --dt-json-null: #9399b2;\n --dt-json-key: #89dceb;\n --dt-json-tag: #cba6f7;\n --dt-json-preview: #9399b2;\n --dt-json-arrow: #9399b2;\n --dt-tree-hover: #313244;\n --dt-diff-changed: #74c7ec;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n}\nbutton {\n font: inherit;\n color: inherit;\n}\nul {\n list-style: none;\n}\n\n.fixed {\n position: fixed;\n}\n.flex {\n display: flex;\n}\n.flex-col {\n flex-direction: column;\n}\n.flex-1 {\n flex: 1 1 0%;\n}\n.items-center {\n align-items: center;\n}\n.justify-center {\n justify-content: center;\n}\n.justify-between {\n justify-content: space-between;\n}\n.shrink-0 {\n flex-shrink: 0;\n}\n.inline-block {\n display: inline-block;\n}\n.gap-0\\.5 {\n gap: 2px;\n}\n.gap-1\\.5 {\n gap: 6px;\n}\n.gap-2 {\n gap: 8px;\n}\n.gap-px {\n gap: 1px;\n}\n.px-1 {\n padding-left: 4px;\n padding-right: 4px;\n}\n.px-2 {\n padding-left: 8px;\n padding-right: 8px;\n}\n.px-2\\.5 {\n padding-left: 10px;\n padding-right: 10px;\n}\n.p-3 {\n padding: 12px;\n}\n.px-3 {\n padding-left: 12px;\n padding-right: 12px;\n}\n.py-0\\.5 {\n padding-top: 2px;\n padding-bottom: 2px;\n}\n.pt-1 {\n padding-top: 4px;\n}\n.pl-1 {\n padding-left: 4px;\n}\n.py-1 {\n padding-top: 4px;\n padding-bottom: 4px;\n}\n.py-1\\.5 {\n padding-top: 6px;\n padding-bottom: 6px;\n}\n.py-2 {\n padding-top: 8px;\n padding-bottom: 8px;\n}\n.py-px {\n padding-top: 1px;\n padding-bottom: 1px;\n}\n.w-1\\.5 {\n width: 6px;\n}\n.h-1\\.5 {\n height: 6px;\n}\n.w-3 {\n width: 12px;\n}\n.w-5 {\n width: 20px;\n}\n.h-5 {\n height: 20px;\n}\n.w-14 {\n width: 56px;\n}\n.h-14 {\n height: 56px;\n}\n.min-w-0 {\n min-width: 0;\n}\n.min-w-5 {\n min-width: 20px;\n}\n.min-h-0 {\n min-height: 0;\n}\n/* Badge positions \u2014 flush against side edge */\n.dt-pos-br {\n bottom: 16px;\n right: 0;\n border-radius: 6px 0 0 6px;\n}\n.dt-pos-bl {\n bottom: 16px;\n left: 0;\n border-radius: 0 6px 6px 0;\n}\n.dt-pos-tr {\n top: 16px;\n right: 0;\n border-radius: 6px 0 0 6px;\n}\n.dt-pos-tl {\n top: 16px;\n left: 0;\n border-radius: 0 6px 6px 0;\n}\n.overflow-hidden {\n overflow: hidden;\n}\n.overflow-auto {\n overflow: auto;\n}\n.overflow-y-auto {\n overflow-y: auto;\n}\n.overscroll-none {\n overscroll-behavior: none;\n}\n\n.truncate {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.rounded {\n border-radius: 4px;\n}\n.rounded-lg {\n border-radius: 8px;\n}\n.rounded-full {\n border-radius: 9999px;\n}\n.border {\n border-width: 1px;\n border-style: solid;\n border-color: var(--dt-border);\n}\n.border-b {\n border-bottom: 1px solid var(--dt-border);\n}\n.border-t {\n border-top: 1px solid var(--dt-border);\n}\n.border-r {\n border-right: 1px solid var(--dt-border);\n}\n.border-l {\n border-left: 1px solid var(--dt-border);\n}\n.border-none {\n border: none;\n}\n.selected {\n background-color: var(--dt-surface-selected);\n}\n.dt-row:hover:not(.selected) {\n background-color: var(--dt-tree-hover);\n}\n.dt-header-button:hover {\n color: var(--dt-text);\n}\n.dt-resume-button:hover {\n opacity: 0.7;\n}\n.dt-filter-wrapper {\n position: relative;\n flex-shrink: 0;\n border-bottom: 1px solid var(--dt-border);\n}\n.dt-filter-button {\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 6px 12px;\n background: transparent;\n border: none;\n color: var(--dt-text-muted);\n font-family:\n ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;\n font-size: 13px;\n cursor: pointer;\n text-align: left;\n}\n.dt-filter-button:hover {\n color: var(--dt-text);\n background-color: var(--dt-tree-hover);\n}\n.dt-filter-button:focus-visible {\n outline: 1px solid var(--dt-accent);\n outline-offset: -1px;\n}\n.dt-filter-button[data-open] {\n color: var(--dt-text);\n background-color: var(--dt-surface-selected);\n}\n.dt-filter-button[data-open]:hover {\n background-color: var(--dt-tree-hover);\n}\n.dt-filter-button[data-open] .json-arrow {\n transform: rotate(180deg);\n}\n.dt-filter-items {\n position: absolute;\n top: 100%;\n left: 0;\n right: 0;\n background-color: var(--dt-bg);\n border-top: 1px solid var(--dt-border);\n border-bottom: 1px solid var(--dt-border);\n z-index: 10;\n max-height: 200px;\n overflow-y: auto;\n outline: none;\n}\n.dt-filter-item {\n padding: 6px 12px;\n color: var(--dt-text-muted);\n cursor: pointer;\n font-family:\n ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;\n font-size: 13px;\n border-bottom: 1px solid var(--dt-border);\n}\n.dt-filter-item:last-child {\n border-bottom: none;\n}\n.dt-filter-item[data-active] {\n background-color: var(--dt-tree-hover);\n color: var(--dt-text);\n}\n.dt-filter-item[data-selected] {\n color: var(--dt-accent);\n}\n.dt-filter-check {\n width: 12px;\n height: 12px;\n visibility: hidden;\n}\n.dt-filter-item[data-selected] .dt-filter-check {\n visibility: visible;\n color: var(--dt-accent);\n}\n.dt-filter-backdrop {\n position: fixed;\n inset: 0;\n pointer-events: none;\n}\n.dt-tab-button {\n position: relative;\n background: transparent;\n border: none;\n border-right: 1px solid var(--dt-border);\n outline: none;\n flex: 1;\n}\n.dt-tab-button:last-child {\n border-right: none;\n}\n.dt-tab-active {\n background-color: var(--dt-surface-selected);\n}\n.dt-tab-button:not(.dt-tab-active):hover {\n color: var(--dt-text);\n background-color: rgba(49, 50, 68, 0.3);\n}\n.font-sans {\n font-family:\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n 'Segoe UI',\n Roboto,\n sans-serif;\n}\n.font-mono {\n font-family:\n ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;\n}\n.font-medium {\n font-weight: 500;\n}\n.font-semibold {\n font-weight: 600;\n}\n.text-xs {\n font-size: 12px;\n}\n.text-2xs {\n font-size: 10px;\n}\n.text-sm {\n font-size: 11px;\n}\n.text-base {\n font-size: 13px;\n}\n.text-md {\n font-size: 15px;\n}\n.text-lg {\n font-size: 20px;\n}\n.text-xl {\n font-size: 26px;\n}\n.italic {\n font-style: italic;\n}\n.text-right {\n text-align: right;\n}\n.tracking-wide {\n letter-spacing: 0.025em;\n}\n.tracking-wider {\n letter-spacing: 0.05em;\n}\n.leading-none {\n line-height: 1;\n}\n.leading-snug {\n line-height: 1.35;\n}\n.bg-dt-bg {\n background-color: var(--dt-bg);\n}\n.bg-dt-live {\n background-color: var(--dt-live);\n}\n.bg-transparent {\n background-color: transparent;\n}\n.text-dt {\n color: var(--dt-text);\n}\n.text-dt-bg {\n color: var(--dt-bg);\n}\n.text-dt-muted {\n color: var(--dt-text-muted);\n}\n.text-dt-accent {\n color: var(--dt-accent);\n}\n.text-dt-live {\n color: var(--dt-live);\n}\n.text-dt-paused {\n color: var(--dt-paused);\n}\n.cursor-pointer {\n cursor: pointer;\n}\n.outline-none {\n outline: none;\n}\n.transition-colors {\n transition-property: color, background-color, border-color;\n transition-duration: 100ms;\n transition-timing-function: ease;\n}\n\n/* Panel */\n.dt-panel {\n width: 360px;\n height: 480px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);\n z-index: 99998;\n}\n/* Panel positions */\n.dt-panel-br {\n bottom: 16px;\n right: 28px;\n}\n.dt-panel-bl {\n bottom: 16px;\n left: 28px;\n}\n.dt-panel-tr {\n top: 16px;\n right: 28px;\n}\n.dt-panel-tl {\n top: 16px;\n left: 28px;\n}\n.dt-panel-wide {\n width: 720px;\n}\n.dt-message-pane {\n width: 320px;\n flex-shrink: 0;\n}\n.dt-badge {\n z-index: 99999;\n box-shadow: -2px 0 8px rgba(0, 0, 0, 0.3);\n transition: background-color 150ms ease;\n border: 1px solid var(--dt-border);\n}\n.dt-badge-accent:hover {\n background-color: #252538;\n}\n.dt-badge-paused {\n background-color: var(--dt-paused);\n color: var(--dt-bg);\n border: none;\n}\n.dt-badge-paused:hover {\n background-color: #e0a070;\n}\n.dt-badge.dt-pos-br,\n.dt-badge.dt-pos-tr {\n border-right: none;\n}\n.dt-badge.dt-pos-bl,\n.dt-badge.dt-pos-tl {\n border-left: none;\n}\n\n/* JSON tree */\n.tree-row {\n position: relative;\n white-space: nowrap;\n line-height: 18px;\n padding-right: 8px;\n}\n.tree-row-expandable:hover {\n background-color: var(--dt-tree-hover);\n}\n.inspector-tree {\n font-family:\n ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;\n}\n.json-key {\n color: var(--dt-json-key);\n}\n.json-string {\n color: var(--dt-json-string);\n}\n.json-number {\n color: var(--dt-json-number);\n}\n.json-boolean {\n color: var(--dt-json-boolean);\n}\n.json-null {\n color: var(--dt-json-null);\n}\n.json-tag {\n color: var(--dt-json-tag);\n margin-right: 4px;\n}\n.json-preview {\n color: var(--dt-json-preview);\n}\n.json-arrow {\n color: var(--dt-json-arrow);\n width: 10px;\n height: 10px;\n user-select: none;\n}\n\n/* Diff */\n.diff-changed {\n background-color: rgba(116, 199, 236, 0.06);\n}\n.diff-dot {\n position: absolute;\n left: 3px;\n width: 5px;\n height: 5px;\n border-radius: 9999px;\n background-color: var(--dt-diff-changed);\n}\n.diff-dot-inline {\n width: 5px;\n height: 5px;\n border-radius: 9999px;\n background-color: var(--dt-diff-changed);\n flex-shrink: 0;\n}\n.dot-column {\n width: 5px;\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.pause-column {\n width: 8px;\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.dt-pause-icon {\n width: 8px;\n height: 8px;\n color: var(--dt-paused);\n}\n\n/* Interaction blocker \u2014 covers the app while time-travelling */\n.dt-interaction-blocker {\n position: fixed;\n inset: 0;\n z-index: 99997;\n cursor: not-allowed;\n}\n\n/* Mobile */\n@media (max-width: 767px) {\n .dt-panel {\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n width: 100%;\n height: 100%;\n border-radius: 0;\n border: none;\n }\n .dt-panel-wide {\n width: 100%;\n }\n .dt-content {\n flex-direction: column;\n }\n .dt-message-pane {\n width: 100%;\n max-height: 40%;\n border-bottom: 1px solid var(--dt-border);\n }\n .message-list > :last-child {\n border-bottom: none;\n }\n .dt-inspector-pane {\n border-left: none;\n }\n}\n";
|
|
1
|
+
declare const overlayStyles = ":host {\n position: relative;\n z-index: 2147483647;\n\n --dt-bg: #1e1e2e;\n --dt-surface-selected: #282839;\n --dt-border: #45475a;\n --dt-text: #cdd6f4;\n --dt-text-muted: #9399b2;\n --dt-accent: #cba6f7;\n --dt-live: #a6e3a1;\n --dt-paused: #fab387;\n --dt-json-string: #a6e3a1;\n --dt-json-number: #89b4fa;\n --dt-json-boolean: #fab387;\n --dt-json-null: #9399b2;\n --dt-json-key: #89dceb;\n --dt-json-tag: #cba6f7;\n --dt-json-preview: #9399b2;\n --dt-json-arrow: #9399b2;\n --dt-tree-hover: #313244;\n --dt-diff-changed: #74c7ec;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n}\nbutton {\n font: inherit;\n color: inherit;\n}\nul {\n list-style: none;\n}\n\n.fixed {\n position: fixed;\n}\n.flex {\n display: flex;\n}\n.flex-col {\n flex-direction: column;\n}\n.flex-1 {\n flex: 1 1 0%;\n}\n.items-center {\n align-items: center;\n}\n.justify-center {\n justify-content: center;\n}\n.justify-between {\n justify-content: space-between;\n}\n.shrink-0 {\n flex-shrink: 0;\n}\n.inline-block {\n display: inline-block;\n}\n.gap-0\\.5 {\n gap: 2px;\n}\n.gap-1\\.5 {\n gap: 6px;\n}\n.gap-2 {\n gap: 8px;\n}\n.gap-3 {\n gap: 12px;\n}\n.gap-px {\n gap: 1px;\n}\n.px-1 {\n padding-left: 4px;\n padding-right: 4px;\n}\n.px-2 {\n padding-left: 8px;\n padding-right: 8px;\n}\n.px-2\\.5 {\n padding-left: 10px;\n padding-right: 10px;\n}\n.p-3 {\n padding: 12px;\n}\n.px-3 {\n padding-left: 12px;\n padding-right: 12px;\n}\n.py-0\\.5 {\n padding-top: 2px;\n padding-bottom: 2px;\n}\n.pt-1 {\n padding-top: 4px;\n}\n.pl-1 {\n padding-left: 4px;\n}\n.py-1 {\n padding-top: 4px;\n padding-bottom: 4px;\n}\n.py-1\\.5 {\n padding-top: 6px;\n padding-bottom: 6px;\n}\n.py-2 {\n padding-top: 8px;\n padding-bottom: 8px;\n}\n.py-px {\n padding-top: 1px;\n padding-bottom: 1px;\n}\n.w-1\\.5 {\n width: 6px;\n}\n.h-1\\.5 {\n height: 6px;\n}\n.w-3 {\n width: 12px;\n}\n.w-5 {\n width: 20px;\n}\n.h-5 {\n height: 20px;\n}\n.w-14 {\n width: 56px;\n}\n.h-14 {\n height: 56px;\n}\n.min-w-0 {\n min-width: 0;\n}\n.min-w-5 {\n min-width: 20px;\n}\n.min-h-0 {\n min-height: 0;\n}\n/* Badge positions \u2014 flush against side edge */\n.dt-pos-br {\n bottom: 16px;\n right: 0;\n border-radius: 6px 0 0 6px;\n}\n.dt-pos-bl {\n bottom: 16px;\n left: 0;\n border-radius: 0 6px 6px 0;\n}\n.dt-pos-tr {\n top: 16px;\n right: 0;\n border-radius: 6px 0 0 6px;\n}\n.dt-pos-tl {\n top: 16px;\n left: 0;\n border-radius: 0 6px 6px 0;\n}\n.overflow-hidden {\n overflow: hidden;\n}\n.overflow-auto {\n overflow: auto;\n}\n.overflow-y-auto {\n overflow-y: auto;\n}\n.overscroll-none {\n overscroll-behavior: none;\n}\n\n.truncate {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.rounded {\n border-radius: 4px;\n}\n.rounded-lg {\n border-radius: 8px;\n}\n.rounded-full {\n border-radius: 9999px;\n}\n.border {\n border-width: 1px;\n border-style: solid;\n border-color: var(--dt-border);\n}\n.border-b {\n border-bottom: 1px solid var(--dt-border);\n}\n.border-t {\n border-top: 1px solid var(--dt-border);\n}\n.border-r {\n border-right: 1px solid var(--dt-border);\n}\n.border-l {\n border-left: 1px solid var(--dt-border);\n}\n.border-none {\n border: none;\n}\n.selected {\n background-color: var(--dt-surface-selected);\n}\n.dt-row:hover:not(.selected) {\n background-color: var(--dt-tree-hover);\n}\n.dt-header-button:hover {\n color: var(--dt-text);\n}\n.dt-resume-button:hover {\n opacity: 0.7;\n}\n.dt-filter-wrapper {\n position: relative;\n flex-shrink: 0;\n border-bottom: 1px solid var(--dt-border);\n}\n.dt-filter-button {\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 6px 12px;\n background: transparent;\n border: none;\n color: var(--dt-text-muted);\n font-family:\n ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;\n font-size: 13px;\n cursor: pointer;\n text-align: left;\n}\n.dt-filter-button:hover {\n color: var(--dt-text);\n background-color: var(--dt-tree-hover);\n}\n.dt-filter-button:focus-visible {\n outline: 1px solid var(--dt-accent);\n outline-offset: -1px;\n}\n.dt-filter-button[data-open] {\n color: var(--dt-text);\n background-color: var(--dt-surface-selected);\n}\n.dt-filter-button[data-open]:hover {\n background-color: var(--dt-tree-hover);\n}\n.dt-filter-button[data-open] .json-arrow {\n transform: rotate(180deg);\n}\n.dt-filter-items {\n position: absolute;\n top: 100%;\n left: 0;\n right: 0;\n background-color: var(--dt-bg);\n border-top: 1px solid var(--dt-border);\n border-bottom: 1px solid var(--dt-border);\n z-index: 10;\n max-height: 200px;\n overflow-y: auto;\n outline: none;\n}\n.dt-filter-item {\n padding: 6px 12px;\n color: var(--dt-text-muted);\n cursor: pointer;\n font-family:\n ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;\n font-size: 13px;\n border-bottom: 1px solid var(--dt-border);\n}\n.dt-filter-item:last-child {\n border-bottom: none;\n}\n.dt-filter-item[data-active] {\n background-color: var(--dt-tree-hover);\n color: var(--dt-text);\n}\n.dt-filter-item[data-selected] {\n color: var(--dt-accent);\n}\n.dt-filter-check {\n width: 12px;\n height: 12px;\n visibility: hidden;\n}\n.dt-filter-item[data-selected] .dt-filter-check {\n visibility: visible;\n color: var(--dt-accent);\n}\n.dt-filter-backdrop {\n position: fixed;\n inset: 0;\n pointer-events: none;\n}\n.dt-tab-button {\n position: relative;\n background: transparent;\n border: none;\n border-right: 1px solid var(--dt-border);\n outline: none;\n flex: 1;\n}\n.dt-tab-button:last-child {\n border-right: none;\n}\n.dt-tab-active {\n background-color: var(--dt-surface-selected);\n}\n.dt-tab-button:not(.dt-tab-active):hover {\n color: var(--dt-text);\n background-color: rgba(49, 50, 68, 0.3);\n}\n.font-sans {\n font-family:\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n 'Segoe UI',\n Roboto,\n sans-serif;\n}\n.font-mono {\n font-family:\n ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;\n}\n.font-medium {\n font-weight: 500;\n}\n.font-semibold {\n font-weight: 600;\n}\n.text-xs {\n font-size: 12px;\n}\n.text-2xs {\n font-size: 10px;\n}\n.text-sm {\n font-size: 11px;\n}\n.text-base {\n font-size: 13px;\n}\n.text-md {\n font-size: 15px;\n}\n.text-lg {\n font-size: 20px;\n}\n.text-xl {\n font-size: 26px;\n}\n.italic {\n font-style: italic;\n}\n.text-right {\n text-align: right;\n}\n.tracking-wide {\n letter-spacing: 0.025em;\n}\n.tracking-wider {\n letter-spacing: 0.05em;\n}\n.leading-none {\n line-height: 1;\n}\n.leading-snug {\n line-height: 1.35;\n}\n.bg-dt-bg {\n background-color: var(--dt-bg);\n}\n.bg-dt-live {\n background-color: var(--dt-live);\n}\n.bg-transparent {\n background-color: transparent;\n}\n.text-dt {\n color: var(--dt-text);\n}\n.text-dt-bg {\n color: var(--dt-bg);\n}\n.text-dt-muted {\n color: var(--dt-text-muted);\n}\n.text-dt-accent {\n color: var(--dt-accent);\n}\n.text-dt-live {\n color: var(--dt-live);\n}\n.text-dt-paused {\n color: var(--dt-paused);\n}\n.cursor-pointer {\n cursor: pointer;\n}\n.outline-none {\n outline: none;\n}\n.transition-colors {\n transition-property: color, background-color, border-color;\n transition-duration: 100ms;\n transition-timing-function: ease;\n}\n\n/* Panel */\n.dt-panel {\n width: 360px;\n height: 480px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);\n z-index: 99998;\n}\n/* Panel positions */\n.dt-panel-br {\n bottom: 16px;\n right: 28px;\n}\n.dt-panel-bl {\n bottom: 16px;\n left: 28px;\n}\n.dt-panel-tr {\n top: 16px;\n right: 28px;\n}\n.dt-panel-tl {\n top: 16px;\n left: 28px;\n}\n.dt-panel-wide {\n width: 720px;\n}\n.dt-message-pane {\n width: 320px;\n flex-shrink: 0;\n}\n.dt-badge {\n z-index: 99999;\n box-shadow: -2px 0 8px rgba(0, 0, 0, 0.3);\n transition: background-color 150ms ease;\n border: 1px solid var(--dt-border);\n}\n.dt-badge-accent:hover {\n background-color: #252538;\n}\n.dt-badge-paused {\n background-color: var(--dt-paused);\n color: var(--dt-bg);\n border: none;\n}\n.dt-badge-paused:hover {\n background-color: #e0a070;\n}\n.dt-badge.dt-pos-br,\n.dt-badge.dt-pos-tr {\n border-right: none;\n}\n.dt-badge.dt-pos-bl,\n.dt-badge.dt-pos-tl {\n border-left: none;\n}\n\n/* JSON tree */\n.tree-row {\n position: relative;\n white-space: nowrap;\n line-height: 18px;\n padding-right: 8px;\n}\n.tree-row-expandable:hover {\n background-color: var(--dt-tree-hover);\n}\n.inspector-tree {\n font-family:\n ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;\n}\n.json-key {\n color: var(--dt-json-key);\n}\n.json-string {\n color: var(--dt-json-string);\n}\n.json-number {\n color: var(--dt-json-number);\n}\n.json-boolean {\n color: var(--dt-json-boolean);\n}\n.json-null {\n color: var(--dt-json-null);\n}\n.json-tag {\n color: var(--dt-json-tag);\n margin-right: 4px;\n}\n.json-preview {\n color: var(--dt-json-preview);\n}\n.json-arrow {\n color: var(--dt-json-arrow);\n width: 10px;\n height: 10px;\n user-select: none;\n}\n\n/* Diff */\n.diff-changed {\n background-color: rgba(116, 199, 236, 0.06);\n}\n.diff-dot {\n position: absolute;\n left: 3px;\n width: 5px;\n height: 5px;\n border-radius: 9999px;\n background-color: var(--dt-diff-changed);\n}\n.diff-dot-inline {\n width: 5px;\n height: 5px;\n border-radius: 9999px;\n background-color: var(--dt-diff-changed);\n flex-shrink: 0;\n}\n.dot-column {\n width: 5px;\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.pause-column {\n width: 8px;\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.dt-pause-icon {\n width: 8px;\n height: 8px;\n color: var(--dt-paused);\n}\n\n/* Interaction blocker \u2014 covers the app while time-travelling */\n.dt-interaction-blocker {\n position: fixed;\n inset: 0;\n z-index: 99997;\n cursor: not-allowed;\n}\n\n/* Scrubber */\n.dt-scrubber-row {\n background-color: var(--dt-bg);\n}\n.dt-scrubber-control {\n position: relative;\n height: 16px;\n width: 100%;\n padding: 0 7px;\n display: flex;\n align-items: center;\n}\n.dt-scrubber-track {\n width: 100%;\n height: 4px;\n background-color: var(--dt-border);\n border-radius: 9999px;\n cursor: pointer;\n}\n.dt-scrubber-track[data-disabled] {\n cursor: not-allowed;\n}\n.dt-scrubber-fill {\n height: 100%;\n background-color: var(--dt-accent);\n border-radius: 9999px;\n}\n.dt-scrubber-thumb {\n width: 14px;\n height: 14px;\n border-radius: 9999px;\n background-color: var(--dt-accent);\n border: 2px solid var(--dt-bg);\n cursor: grab;\n outline: none;\n top: 50%;\n margin-top: -7px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);\n}\n.dt-scrubber-thumb:focus-visible {\n outline: 2px solid var(--dt-text);\n outline-offset: 2px;\n}\n.dt-scrubber-thumb[data-dragging] {\n cursor: grabbing;\n}\n.dt-scrubber-position {\n width: 72px;\n padding-left: 12px;\n border-left: 1px solid var(--dt-border);\n align-self: stretch;\n margin-top: -8px;\n margin-bottom: -8px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n/* Mobile */\n@media (max-width: 767px) {\n .dt-panel {\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n width: 100%;\n height: 100%;\n border-radius: 0;\n border: none;\n }\n .dt-panel-wide {\n width: 100%;\n }\n .dt-content {\n flex-direction: column;\n }\n .dt-message-pane {\n width: 100%;\n max-height: 40%;\n border-bottom: 1px solid var(--dt-border);\n }\n .message-list > :last-child {\n border-bottom: none;\n }\n .dt-inspector-pane {\n border-left: none;\n }\n .dt-badge.dt-pos-br,\n .dt-badge.dt-pos-bl {\n bottom: 44px;\n }\n}\n";
|
|
2
2
|
export { overlayStyles };
|
|
3
3
|
//# sourceMappingURL=overlay-styles.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"overlay-styles.d.ts","sourceRoot":"","sources":["../../src/devTools/overlay-styles.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,aAAa,
|
|
1
|
+
{"version":3,"file":"overlay-styles.d.ts","sourceRoot":"","sources":["../../src/devTools/overlay-styles.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,aAAa,ypXAkqBlB,CAAA;AAED,OAAO,EAAE,aAAa,EAAE,CAAA"}
|
|
@@ -73,6 +73,9 @@ ul {
|
|
|
73
73
|
.gap-2 {
|
|
74
74
|
gap: 8px;
|
|
75
75
|
}
|
|
76
|
+
.gap-3 {
|
|
77
|
+
gap: 12px;
|
|
78
|
+
}
|
|
76
79
|
.gap-px {
|
|
77
80
|
gap: 1px;
|
|
78
81
|
}
|
|
@@ -577,6 +580,64 @@ ul {
|
|
|
577
580
|
cursor: not-allowed;
|
|
578
581
|
}
|
|
579
582
|
|
|
583
|
+
/* Scrubber */
|
|
584
|
+
.dt-scrubber-row {
|
|
585
|
+
background-color: var(--dt-bg);
|
|
586
|
+
}
|
|
587
|
+
.dt-scrubber-control {
|
|
588
|
+
position: relative;
|
|
589
|
+
height: 16px;
|
|
590
|
+
width: 100%;
|
|
591
|
+
padding: 0 7px;
|
|
592
|
+
display: flex;
|
|
593
|
+
align-items: center;
|
|
594
|
+
}
|
|
595
|
+
.dt-scrubber-track {
|
|
596
|
+
width: 100%;
|
|
597
|
+
height: 4px;
|
|
598
|
+
background-color: var(--dt-border);
|
|
599
|
+
border-radius: 9999px;
|
|
600
|
+
cursor: pointer;
|
|
601
|
+
}
|
|
602
|
+
.dt-scrubber-track[data-disabled] {
|
|
603
|
+
cursor: not-allowed;
|
|
604
|
+
}
|
|
605
|
+
.dt-scrubber-fill {
|
|
606
|
+
height: 100%;
|
|
607
|
+
background-color: var(--dt-accent);
|
|
608
|
+
border-radius: 9999px;
|
|
609
|
+
}
|
|
610
|
+
.dt-scrubber-thumb {
|
|
611
|
+
width: 14px;
|
|
612
|
+
height: 14px;
|
|
613
|
+
border-radius: 9999px;
|
|
614
|
+
background-color: var(--dt-accent);
|
|
615
|
+
border: 2px solid var(--dt-bg);
|
|
616
|
+
cursor: grab;
|
|
617
|
+
outline: none;
|
|
618
|
+
top: 50%;
|
|
619
|
+
margin-top: -7px;
|
|
620
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
|
|
621
|
+
}
|
|
622
|
+
.dt-scrubber-thumb:focus-visible {
|
|
623
|
+
outline: 2px solid var(--dt-text);
|
|
624
|
+
outline-offset: 2px;
|
|
625
|
+
}
|
|
626
|
+
.dt-scrubber-thumb[data-dragging] {
|
|
627
|
+
cursor: grabbing;
|
|
628
|
+
}
|
|
629
|
+
.dt-scrubber-position {
|
|
630
|
+
width: 72px;
|
|
631
|
+
padding-left: 12px;
|
|
632
|
+
border-left: 1px solid var(--dt-border);
|
|
633
|
+
align-self: stretch;
|
|
634
|
+
margin-top: -8px;
|
|
635
|
+
margin-bottom: -8px;
|
|
636
|
+
display: flex;
|
|
637
|
+
align-items: center;
|
|
638
|
+
justify-content: center;
|
|
639
|
+
}
|
|
640
|
+
|
|
580
641
|
/* Mobile */
|
|
581
642
|
@media (max-width: 767px) {
|
|
582
643
|
.dt-panel {
|
|
@@ -606,6 +667,10 @@ ul {
|
|
|
606
667
|
.dt-inspector-pane {
|
|
607
668
|
border-left: none;
|
|
608
669
|
}
|
|
670
|
+
.dt-badge.dt-pos-br,
|
|
671
|
+
.dt-badge.dt-pos-bl {
|
|
672
|
+
bottom: 44px;
|
|
673
|
+
}
|
|
609
674
|
}
|
|
610
675
|
`;
|
|
611
676
|
export { overlayStyles };
|
|
@@ -7,6 +7,7 @@ declare const StoreService_base: Context.ServiceClass<StoreService, "foldkit/Dev
|
|
|
7
7
|
recordMessage: (message: Readonly<{
|
|
8
8
|
_tag: string;
|
|
9
9
|
}>, modelBeforeUpdate: unknown, modelAfterUpdate: unknown, commands: ReadonlyArray<CommandRecord>, isModelChanged: boolean) => Effect.Effect<void>;
|
|
10
|
+
updateLatestModel: (model: unknown) => Effect.Effect<void>;
|
|
10
11
|
attachRenderedMounts: (mountStarts: ReadonlyArray<MountRecord>, mountEnds: ReadonlyArray<MountRecord>) => Effect.Effect<void>;
|
|
11
12
|
getModelAtIndex: (index: number) => Effect.Effect<unknown>;
|
|
12
13
|
getMessageAtIndex: (index: number) => Effect.Effect<Option.Option<unknown>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../../src/devTools/overlay.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,OAAO,EACP,MAAM,EAGN,OAAO,EAGP,MAAM,EAKN,MAAM,IAAI,CAAC,EAGX,eAAe,EAEhB,MAAM,QAAQ,CAAA;AAEf,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAA;AAa9C,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../../src/devTools/overlay.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,OAAO,EACP,MAAM,EAGN,OAAO,EAGP,MAAM,EAKN,MAAM,IAAI,CAAC,EAGX,eAAe,EAEhB,MAAM,QAAQ,CAAA;AAEf,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAA;AAa9C,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAQ3E,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,aAAa,EAElB,KAAK,WAAW,EAChB,KAAK,UAAU,EAChB,MAAM,YAAY,CAAA;;oFA8ZQ,CAAC;;;;;;;;;;;;;;AApI5B,cAAM,YAAa,SAAQ,iBAE1B;CAAG;;AAEJ,cAAM,iBAAkB,SAAQ,sBAGC;CAAG;AAEpC,eAAO,MAAM,UAAU;;iBAGsB,CAAA;AAE7C,eAAO,MAAM,YAAY;;iBAGwB,CAAA;AAWjD,eAAO,MAAM,MAAM;;;;wBAUlB,CAAA;AAED,eAAO,MAAM,YAAY;;;;;;;;wBAIqB,CAAA;AAE9C,eAAO,MAAM,aAAa;;;;;;wBAYzB,CAAA;AAED,eAAO,MAAM,MAAM;;wBASlB,CAAA;AAED,eAAO,MAAM,KAAK;;wBASjB,CAAA;AAED,eAAO,MAAM,WAAW;;6BAYvB,CAAA;AA0oDD,eAAO,MAAM,aAAa,GACxB,OAAO,aAAa,EACpB,UAAU,gBAAgB,EAC1B,MAAM,YAAY,EAClB,aAAa,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,sCAkEhC,CAAA"}
|
package/dist/devTools/overlay.js
CHANGED
|
@@ -9,6 +9,7 @@ import { makeProgram } from '../runtime/runtime.js';
|
|
|
9
9
|
import { makeSubscriptions } from '../runtime/subscription.js';
|
|
10
10
|
import { evo } from '../struct/index.js';
|
|
11
11
|
import * as Listbox from '../ui/listbox/public.js';
|
|
12
|
+
import * as Slider from '../ui/slider/public.js';
|
|
12
13
|
import * as Tabs from '../ui/tabs/public.js';
|
|
13
14
|
import { overlayStyles } from './overlay-styles.js';
|
|
14
15
|
import { toInspectableValue } from './serialize.js';
|
|
@@ -35,6 +36,7 @@ const DisplayEntry = S.Struct({
|
|
|
35
36
|
});
|
|
36
37
|
const INSPECTOR_TABS_ID = 'dt-inspector';
|
|
37
38
|
const SUBMODEL_FILTER_ID = 'dt-submodel-filter';
|
|
39
|
+
const SCRUBBER_SLIDER_ID = 'dt-scrubber';
|
|
38
40
|
const InspectorTabsModel = S.Struct({
|
|
39
41
|
id: S.String,
|
|
40
42
|
activeIndex: S.Number,
|
|
@@ -73,6 +75,15 @@ const Model = S.Struct({
|
|
|
73
75
|
changedPaths: S.HashSet(S.String),
|
|
74
76
|
affectedPaths: S.HashSet(S.String),
|
|
75
77
|
inspectorTabs: InspectorTabsModel,
|
|
78
|
+
// NOTE: empirically, inlining `Slider.Model` here throws
|
|
79
|
+
// "Cannot read properties of undefined (reading 'ast')" when running slider
|
|
80
|
+
// tests, because slider imports html → runtime → overlay, and overlay
|
|
81
|
+
// references Slider.Model mid-cycle. S.suspend defers the read until after
|
|
82
|
+
// the cycle resolves. Inlining Listbox.Model works in practice but goes
|
|
83
|
+
// through the same import chain; the exact cause of the asymmetry isn't
|
|
84
|
+
// pinned down. Suspend is the conservative fix until the runtime ↔ overlay
|
|
85
|
+
// cycle is broken at the source.
|
|
86
|
+
scrubberSlider: S.suspend(() => Slider.Model),
|
|
76
87
|
});
|
|
77
88
|
const Flags = S.Struct({
|
|
78
89
|
isMobile: S.Boolean,
|
|
@@ -122,6 +133,10 @@ const GotSubmodelFilterMessage = m('GotSubmodelFilterMessage', {
|
|
|
122
133
|
const SelectedSubmodelFilter = m('SelectedSubmodelFilter', {
|
|
123
134
|
tag: S.String,
|
|
124
135
|
});
|
|
136
|
+
// NOTE: suspend for the same init-order reason as scrubberSlider above.
|
|
137
|
+
const GotScrubberSliderMessage = m('GotScrubberSliderMessage', {
|
|
138
|
+
message: S.suspend(() => Slider.Message),
|
|
139
|
+
});
|
|
125
140
|
const Message = S.Union([
|
|
126
141
|
ClickedToggle,
|
|
127
142
|
ClickedRow,
|
|
@@ -141,6 +156,7 @@ const Message = S.Union([
|
|
|
141
156
|
ReceivedStoreUpdate,
|
|
142
157
|
GotSubmodelFilterMessage,
|
|
143
158
|
SelectedSubmodelFilter,
|
|
159
|
+
GotScrubberSliderMessage,
|
|
144
160
|
]);
|
|
145
161
|
// HELPERS
|
|
146
162
|
const MILLIS_PER_SECOND = 1000;
|
|
@@ -153,6 +169,14 @@ const NO_COMMANDS = [];
|
|
|
153
169
|
const NO_MOUNTS = [];
|
|
154
170
|
const formatTimeDelta = (deltaMs) => M.value(deltaMs).pipe(M.when(0, () => '0ms'), M.when(Number_.isLessThan(MILLIS_PER_SECOND), ms => `+${Math.round(ms)}ms`), M.orElse(ms => `+${(ms / MILLIS_PER_SECOND).toFixed(1)}s`));
|
|
155
171
|
const MESSAGE_LIST_SELECTOR = '.message-list';
|
|
172
|
+
// NOTE: scrubber slider value space is independent of the store's host
|
|
173
|
+
// indices. Slider value 0 represents init; 1..entries.length represents
|
|
174
|
+
// positions after each buffered message. Passing pausedAtIndex (a host
|
|
175
|
+
// index) straight into setValue, or treating ChangedValue.value as a host
|
|
176
|
+
// index in jumpTo, will silently produce wrong navigation. Translate at
|
|
177
|
+
// the boundaries via the helpers below.
|
|
178
|
+
const hostIndexToSliderValue = (hostIndex, startIndex) => (hostIndex === INIT_INDEX ? 0 : hostIndex - startIndex + 1);
|
|
179
|
+
const sliderValueToHostIndex = (sliderValue, startIndex) => (sliderValue === 0 ? INIT_INDEX : startIndex + sliderValue - 1);
|
|
156
180
|
const computeSubmodelTags = (entries) => pipe(entries, Array_.flatMap(({ submodelPath }) => submodelPath), Array_.dedupe, Array_.sort(Order.String));
|
|
157
181
|
const toDisplayCommand = (command) => ({
|
|
158
182
|
name: command.name,
|
|
@@ -358,6 +382,13 @@ const makeUpdate = (store, shadow, mode) => {
|
|
|
358
382
|
})
|
|
359
383
|
: current,
|
|
360
384
|
selectedIndex: current => shouldFollowLatest ? latestIndex : current,
|
|
385
|
+
scrubberSlider: current => {
|
|
386
|
+
const sliderMax = entries.length;
|
|
387
|
+
const targetSliderValue = isPaused
|
|
388
|
+
? hostIndexToSliderValue(pausedAtIndex, startIndex)
|
|
389
|
+
: sliderMax;
|
|
390
|
+
return Slider.setValue(Slider.setRange(current, { min: 0, max: sliderMax }), targetSliderValue);
|
|
391
|
+
},
|
|
361
392
|
}),
|
|
362
393
|
shouldFollowLatest ? [scrollToTop, inspectLatest] : [],
|
|
363
394
|
];
|
|
@@ -381,30 +412,68 @@ const makeUpdate = (store, shadow, mode) => {
|
|
|
381
412
|
listboxCommands.map(Command.mapEffect(Effect.map(innerMessage => GotSubmodelFilterMessage({ message: innerMessage })))),
|
|
382
413
|
];
|
|
383
414
|
},
|
|
415
|
+
GotScrubberSliderMessage: ({ message: sliderMessage }) => {
|
|
416
|
+
const [nextSlider, sliderCommands, maybeOutMessage] = Slider.update(model.scrubberSlider, sliderMessage);
|
|
417
|
+
const mappedSliderCommands = sliderCommands.map(Command.mapEffect(Effect.map(innerMessage => GotScrubberSliderMessage({ message: innerMessage }))));
|
|
418
|
+
const additionalCommands = Option.match(maybeOutMessage, {
|
|
419
|
+
onNone: () => [],
|
|
420
|
+
onSome: outMessage => M.value(outMessage).pipe(M.tagsExhaustive({
|
|
421
|
+
ChangedValue: ({ value }) => {
|
|
422
|
+
const hostIndex = sliderValueToHostIndex(value, model.startIndex);
|
|
423
|
+
return [jumpTo(hostIndex), inspectState(hostIndex)];
|
|
424
|
+
},
|
|
425
|
+
})),
|
|
426
|
+
});
|
|
427
|
+
return [
|
|
428
|
+
evo(model, { scrubberSlider: () => nextSlider }),
|
|
429
|
+
[...mappedSliderCommands, ...additionalCommands],
|
|
430
|
+
];
|
|
431
|
+
},
|
|
384
432
|
}), M.tag('CompletedJump', 'CompletedResume', 'CompletedClear', 'LockedScroll', 'UnlockedScroll', 'ScrolledToTop', () => [model, []]), M.exhaustive);
|
|
385
433
|
};
|
|
386
434
|
// SUBSCRIPTION
|
|
435
|
+
const ScrubberDragActivity = S.Literals(['Idle', 'Active']);
|
|
387
436
|
const SubscriptionDeps = S.Struct({
|
|
388
437
|
storeUpdates: S.Boolean,
|
|
389
438
|
mobileBreakpoint: S.Null,
|
|
439
|
+
scrubberPointer: S.Struct({
|
|
440
|
+
dragActivity: ScrubberDragActivity,
|
|
441
|
+
id: S.String,
|
|
442
|
+
min: S.Number,
|
|
443
|
+
max: S.Number,
|
|
444
|
+
}),
|
|
445
|
+
scrubberEscape: S.Struct({
|
|
446
|
+
dragActivity: ScrubberDragActivity,
|
|
447
|
+
}),
|
|
390
448
|
});
|
|
391
|
-
const makeOverlaySubscriptions = (store) =>
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
})
|
|
449
|
+
const makeOverlaySubscriptions = (store, shadow) => {
|
|
450
|
+
const sliderSubscriptions = Slider.subscriptionsForRoot(() => shadow);
|
|
451
|
+
return makeSubscriptions(SubscriptionDeps)({
|
|
452
|
+
storeUpdates: {
|
|
453
|
+
modelToDependencies: () => true,
|
|
454
|
+
dependenciesToStream: () => Stream.concat(Stream.fromEffect(SubscriptionRef.get(store.stateRef).pipe(Effect.map(state => ReceivedStoreUpdate(toDisplayState(state))))), Stream.map(SubscriptionRef.changes(store.stateRef), state => ReceivedStoreUpdate(toDisplayState(state)))),
|
|
455
|
+
},
|
|
456
|
+
mobileBreakpoint: {
|
|
457
|
+
modelToDependencies: () => null,
|
|
458
|
+
dependenciesToStream: () => Stream.callback(queue => Effect.acquireRelease(Effect.sync(() => {
|
|
459
|
+
const mediaQuery = window.matchMedia(MOBILE_BREAKPOINT_QUERY);
|
|
460
|
+
const handler = (event) => {
|
|
461
|
+
Queue.offerUnsafe(queue, CrossedMobileBreakpoint({ isMobile: event.matches }));
|
|
462
|
+
};
|
|
463
|
+
mediaQuery.addEventListener('change', handler);
|
|
464
|
+
return { mediaQuery, handler };
|
|
465
|
+
}), ({ mediaQuery, handler }) => Effect.sync(() => mediaQuery.removeEventListener('change', handler))).pipe(Effect.flatMap(() => Effect.never))),
|
|
466
|
+
},
|
|
467
|
+
scrubberPointer: {
|
|
468
|
+
modelToDependencies: model => sliderSubscriptions.dragPointer.modelToDependencies(model.scrubberSlider),
|
|
469
|
+
dependenciesToStream: (deps, readDeps) => Stream.map(sliderSubscriptions.dragPointer.dependenciesToStream(deps, readDeps), message => GotScrubberSliderMessage({ message })),
|
|
470
|
+
},
|
|
471
|
+
scrubberEscape: {
|
|
472
|
+
modelToDependencies: model => sliderSubscriptions.dragEscape.modelToDependencies(model.scrubberSlider),
|
|
473
|
+
dependenciesToStream: (deps, readDeps) => Stream.map(sliderSubscriptions.dragEscape.dependenciesToStream(deps, readDeps), message => GotScrubberSliderMessage({ message })),
|
|
474
|
+
},
|
|
475
|
+
});
|
|
476
|
+
};
|
|
408
477
|
// VIEW
|
|
409
478
|
const indexClass = 'text-2xs text-dt-muted font-mono min-w-5';
|
|
410
479
|
const headerButtonClass = 'dt-header-button bg-transparent border-none text-dt-muted cursor-pointer text-base font-mono transition-colors';
|
|
@@ -421,7 +490,7 @@ const PANEL_POSITION_CLASS = {
|
|
|
421
490
|
TopRight: 'dt-panel-tr',
|
|
422
491
|
TopLeft: 'dt-panel-tl',
|
|
423
492
|
};
|
|
424
|
-
const makeView = (position, mode, maybeBanner) => {
|
|
493
|
+
const makeView = (position, mode, shadow, maybeBanner) => {
|
|
425
494
|
const h = html();
|
|
426
495
|
const lazyTreeNode = createKeyedLazy();
|
|
427
496
|
const lazyMessageRow = createKeyedLazy();
|
|
@@ -971,7 +1040,37 @@ const makeView = (position, mode, maybeBanner) => {
|
|
|
971
1040
|
model.maybeSubmodelFilter,
|
|
972
1041
|
]);
|
|
973
1042
|
};
|
|
1043
|
+
// SCRUBBER
|
|
1044
|
+
const scrubberPositionLabel = (model) => {
|
|
1045
|
+
const total = String(model.entries.length).padStart(3, '0');
|
|
1046
|
+
const current = String(model.scrubberSlider.value).padStart(3, '0');
|
|
1047
|
+
return `${current} / ${total}`;
|
|
1048
|
+
};
|
|
1049
|
+
const scrubberView = (model) => Slider.view({
|
|
1050
|
+
model: model.scrubberSlider,
|
|
1051
|
+
toParentMessage: message => GotScrubberSliderMessage({ message }),
|
|
1052
|
+
ariaLabel: 'Session scrubber',
|
|
1053
|
+
getTrackRoot: () => shadow,
|
|
1054
|
+
formatValue: value => (value === 0 ? 'init' : `Message ${String(value)}`),
|
|
1055
|
+
toView: attributes => h.div([
|
|
1056
|
+
h.Class('dt-scrubber-row flex items-center gap-3 px-3 py-2 border-t shrink-0'),
|
|
1057
|
+
], [
|
|
1058
|
+
h.div([
|
|
1059
|
+
...attributes.root,
|
|
1060
|
+
h.Class('dt-scrubber-control flex-1 flex items-center'),
|
|
1061
|
+
], [
|
|
1062
|
+
h.div([...attributes.track, h.Class('dt-scrubber-track')], [
|
|
1063
|
+
h.div([...attributes.filledTrack, h.Class('dt-scrubber-fill')], []),
|
|
1064
|
+
h.div([...attributes.thumb, h.Class('dt-scrubber-thumb')], []),
|
|
1065
|
+
]),
|
|
1066
|
+
]),
|
|
1067
|
+
h.span([
|
|
1068
|
+
h.Class('dt-scrubber-position text-2xs text-dt-muted font-mono shrink-0 tabular-nums'),
|
|
1069
|
+
], [scrubberPositionLabel(model)]),
|
|
1070
|
+
]),
|
|
1071
|
+
});
|
|
974
1072
|
// PANEL
|
|
1073
|
+
const isScrubberVisible = mode === 'TimeTravel';
|
|
975
1074
|
const panelView = (model) => h.keyed('div')('dt-panel', [
|
|
976
1075
|
h.Class(clsx('fixed dt-panel dt-panel-wide bg-dt-bg border rounded-lg flex flex-col overflow-hidden font-mono text-dt', PANEL_POSITION_CLASS[position])),
|
|
977
1076
|
], [
|
|
@@ -989,6 +1088,7 @@ const makeView = (position, mode, maybeBanner) => {
|
|
|
989
1088
|
]),
|
|
990
1089
|
inspectorPaneView(model),
|
|
991
1090
|
]),
|
|
1091
|
+
...OptionExt.when(isScrubberVisible, scrubberView(model)).pipe(Option.toArray),
|
|
992
1092
|
]);
|
|
993
1093
|
const interactionBlocker = h.div([h.Class('dt-interaction-blocker')], []);
|
|
994
1094
|
return (model) => ({
|
|
@@ -1035,36 +1135,49 @@ export const createOverlay = (store, position, mode, maybeBanner) => Effect.gen(
|
|
|
1035
1135
|
...toDisplayState(storeState),
|
|
1036
1136
|
};
|
|
1037
1137
|
});
|
|
1038
|
-
const init = (flags) =>
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1138
|
+
const init = (flags) => {
|
|
1139
|
+
const sliderMax = flags.entries.length;
|
|
1140
|
+
const initialSliderValue = flags.isPaused
|
|
1141
|
+
? hostIndexToSliderValue(flags.pausedAtIndex, flags.startIndex)
|
|
1142
|
+
: sliderMax;
|
|
1143
|
+
return [
|
|
1144
|
+
{
|
|
1145
|
+
isOpen: false,
|
|
1146
|
+
...flags,
|
|
1147
|
+
selectedIndex: INIT_INDEX,
|
|
1148
|
+
isFollowingLatest: true,
|
|
1149
|
+
submodelTags: computeSubmodelTags(flags.entries),
|
|
1150
|
+
maybeSubmodelFilter: Option.none(),
|
|
1151
|
+
submodelFilterListbox: Listbox.init({
|
|
1152
|
+
id: SUBMODEL_FILTER_ID,
|
|
1153
|
+
selectedItem: ALL_MESSAGES_VALUE,
|
|
1154
|
+
}),
|
|
1155
|
+
maybeInspectedModel: Option.none(),
|
|
1156
|
+
maybeInspectedMessage: Option.none(),
|
|
1157
|
+
expandedPaths: HashSet.empty(),
|
|
1158
|
+
changedPaths: HashSet.empty(),
|
|
1159
|
+
affectedPaths: HashSet.empty(),
|
|
1160
|
+
inspectorTabs: Tabs.init({ id: INSPECTOR_TABS_ID }),
|
|
1161
|
+
scrubberSlider: Slider.init({
|
|
1162
|
+
id: SCRUBBER_SLIDER_ID,
|
|
1163
|
+
min: 0,
|
|
1164
|
+
max: sliderMax,
|
|
1165
|
+
step: 1,
|
|
1166
|
+
initialValue: initialSliderValue,
|
|
1167
|
+
}),
|
|
1168
|
+
},
|
|
1169
|
+
[],
|
|
1170
|
+
];
|
|
1171
|
+
};
|
|
1059
1172
|
const overlayRuntime = makeProgram({
|
|
1060
1173
|
Model,
|
|
1061
1174
|
Flags,
|
|
1062
1175
|
flags,
|
|
1063
1176
|
init,
|
|
1064
1177
|
update: makeUpdate(store, shadow, mode),
|
|
1065
|
-
view: makeView(position, mode, maybeBanner),
|
|
1178
|
+
view: makeView(position, mode, shadow, maybeBanner),
|
|
1066
1179
|
container,
|
|
1067
|
-
subscriptions: makeOverlaySubscriptions(store),
|
|
1180
|
+
subscriptions: makeOverlaySubscriptions(store, shadow),
|
|
1068
1181
|
devTools: false,
|
|
1069
1182
|
freezeModel: false,
|
|
1070
1183
|
});
|
package/dist/devTools/store.d.ts
CHANGED
|
@@ -40,12 +40,23 @@ export type Bridge = Readonly<{
|
|
|
40
40
|
render: (model: unknown) => Effect.Effect<void>;
|
|
41
41
|
markRenderPending: Effect.Effect<void>;
|
|
42
42
|
}>;
|
|
43
|
-
|
|
43
|
+
/**
|
|
44
|
+
* Options for `createDevToolsStore`.
|
|
45
|
+
*
|
|
46
|
+
* - `maxEntries`: Maximum number of history entries to retain before evicting the oldest segment. Defaults to 100.
|
|
47
|
+
* - `keyframeInterval`: Number of recorded entries between full model snapshots. Smaller values use more memory but make time-travel a constant-time lookup instead of a replay. Set to `1` to snapshot every entry, which keeps time-travel correct under exclusion-from-history (since excluded Messages are never replayed). Defaults to 31.
|
|
48
|
+
*/
|
|
49
|
+
export type CreateDevToolsStoreOptions = Readonly<{
|
|
50
|
+
maxEntries?: number;
|
|
51
|
+
keyframeInterval?: number;
|
|
52
|
+
}>;
|
|
53
|
+
export declare const createDevToolsStore: (bridge: Bridge, options?: CreateDevToolsStoreOptions) => Effect.Effect<DevToolsStore>;
|
|
44
54
|
export type DevToolsStore = Readonly<{
|
|
45
55
|
recordInit: (model: unknown, commands: ReadonlyArray<CommandRecord>, mountStarts?: ReadonlyArray<MountRecord>) => Effect.Effect<void>;
|
|
46
56
|
recordMessage: (message: Readonly<{
|
|
47
57
|
_tag: string;
|
|
48
58
|
}>, modelBeforeUpdate: unknown, modelAfterUpdate: unknown, commands: ReadonlyArray<CommandRecord>, isModelChanged: boolean) => Effect.Effect<void>;
|
|
59
|
+
updateLatestModel: (model: unknown) => Effect.Effect<void>;
|
|
49
60
|
attachRenderedMounts: (mountStarts: ReadonlyArray<MountRecord>, mountEnds: ReadonlyArray<MountRecord>) => Effect.Effect<void>;
|
|
50
61
|
getModelAtIndex: (index: number) => Effect.Effect<unknown>;
|
|
51
62
|
getMessageAtIndex: (index: number) => Effect.Effect<Option.Option<unknown>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/devTools/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,MAAM,EACN,OAAO,EACP,OAAO,EAEP,MAAM,EAIN,eAAe,EAEhB,MAAM,QAAQ,CAAA;
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/devTools/store.ts"],"names":[],"mappings":"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"}
|
package/dist/devTools/store.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Array, Effect, HashMap, HashSet, Match, Option, Predicate, Record, String as String_, SubscriptionRef, pipe, } from 'effect';
|
|
2
|
+
import { evo } from '../struct/index.js';
|
|
2
3
|
export const INIT_INDEX = -1;
|
|
3
|
-
const
|
|
4
|
-
const DEFAULT_MAX_ENTRIES =
|
|
4
|
+
const DEFAULT_KEYFRAME_INTERVAL = 31;
|
|
5
|
+
const DEFAULT_MAX_ENTRIES = 100;
|
|
5
6
|
export const emptyDiff = {
|
|
6
7
|
changedPaths: HashSet.empty(),
|
|
7
8
|
affectedPaths: HashSet.empty(),
|
|
@@ -74,25 +75,38 @@ const emptyState = {
|
|
|
74
75
|
pausedAtIndex: 0,
|
|
75
76
|
maybeLatestModel: Option.none(),
|
|
76
77
|
};
|
|
77
|
-
export const createDevToolsStore = (bridge,
|
|
78
|
+
export const createDevToolsStore = (bridge, options = {}) => Effect.gen(function* () {
|
|
79
|
+
const maxEntries = options.maxEntries ?? DEFAULT_MAX_ENTRIES;
|
|
80
|
+
const keyframeInterval = options.keyframeInterval ?? DEFAULT_KEYFRAME_INTERVAL;
|
|
78
81
|
const stateRef = yield* SubscriptionRef.make(emptyState);
|
|
79
82
|
const replayToIndex = (state, index) => {
|
|
80
|
-
|
|
83
|
+
// NOTE: the keyframe stored at `index + 1` represents the model
|
|
84
|
+
// state immediately after entry `index` was processed, per the
|
|
85
|
+
// convention `recordMessage` uses. Looking it up first short-circuits
|
|
86
|
+
// replay entirely; this hits on every index when keyframeInterval is
|
|
87
|
+
// 1 and at segment boundaries otherwise. Don't "simplify" to
|
|
88
|
+
// `keyframes[index]` — that's the model BEFORE entry `index`, which
|
|
89
|
+
// would require replaying the entry to land at the right state.
|
|
90
|
+
const directSnapshot = HashMap.get(state.keyframes, index + 1);
|
|
91
|
+
if (Option.isSome(directSnapshot)) {
|
|
92
|
+
return directSnapshot.value;
|
|
93
|
+
}
|
|
94
|
+
const segmentStart = Math.floor(index / keyframeInterval) * keyframeInterval;
|
|
81
95
|
const keyframeIndex = HashMap.has(state.keyframes, segmentStart)
|
|
82
96
|
? segmentStart
|
|
83
97
|
: state.startIndex;
|
|
84
98
|
return pipe(state.keyframes, HashMap.get(keyframeIndex), Option.map(keyframeModel => pipe(state.entries, Array.drop(keyframeIndex - state.startIndex), Array.take(index - keyframeIndex + 1), Array.reduce(keyframeModel, (model, entry) => bridge.replay(model, entry.message)))), Option.getOrThrow);
|
|
85
99
|
};
|
|
86
|
-
const addKeyframeIfNeeded = (keyframes, nextAbsoluteIndex, modelAfterUpdate) => nextAbsoluteIndex %
|
|
100
|
+
const addKeyframeIfNeeded = (keyframes, nextAbsoluteIndex, modelAfterUpdate) => nextAbsoluteIndex % keyframeInterval === 0
|
|
87
101
|
? HashMap.set(keyframes, nextAbsoluteIndex, modelAfterUpdate)
|
|
88
102
|
: keyframes;
|
|
89
103
|
const evictOldestSegment = (state) => {
|
|
90
|
-
const nextStartIndex = state.startIndex +
|
|
104
|
+
const nextStartIndex = state.startIndex + keyframeInterval;
|
|
91
105
|
const isPausedAtRetainedIndex = state.pausedAtIndex >= nextStartIndex ||
|
|
92
106
|
state.pausedAtIndex === INIT_INDEX;
|
|
93
107
|
return {
|
|
94
108
|
...state,
|
|
95
|
-
entries: Array.drop(state.entries,
|
|
109
|
+
entries: Array.drop(state.entries, keyframeInterval),
|
|
96
110
|
keyframes: HashMap.remove(state.keyframes, state.startIndex),
|
|
97
111
|
startIndex: nextStartIndex,
|
|
98
112
|
isPaused: state.isPaused && isPausedAtRetainedIndex,
|
|
@@ -214,9 +228,11 @@ export const createDevToolsStore = (bridge, maxEntries = DEFAULT_MAX_ENTRIES) =>
|
|
|
214
228
|
onSome: ({ diff }) => diff,
|
|
215
229
|
}));
|
|
216
230
|
});
|
|
231
|
+
const updateLatestModel = (model) => SubscriptionRef.update(stateRef, evo({ maybeLatestModel: () => Option.some(model) }));
|
|
217
232
|
return {
|
|
218
233
|
recordInit,
|
|
219
234
|
recordMessage,
|
|
235
|
+
updateLatestModel,
|
|
220
236
|
attachRenderedMounts,
|
|
221
237
|
getModelAtIndex,
|
|
222
238
|
getMessageAtIndex,
|
package/dist/route/parser.js
CHANGED
|
@@ -121,7 +121,7 @@ export const oneOf = (...parsers) => ({
|
|
|
121
121
|
onEmpty: () => Effect.fail(new ParseError({
|
|
122
122
|
message: `No parsers provided for path: /${Array.join(segments, '/')}`,
|
|
123
123
|
})),
|
|
124
|
-
onNonEmpty: (
|
|
124
|
+
onNonEmpty: () => Effect.firstSuccessOf(Array.map(parsers, parser => parser.parse(segments, search))),
|
|
125
125
|
}),
|
|
126
126
|
});
|
|
127
127
|
/**
|
package/dist/runtime/public.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { makeProgram, run } from './runtime.js';
|
|
2
|
-
export type { RoutingConfig, CrashConfig, CrashContext, RoutingProgramConfigWithFlags, RoutingProgramConfig, ProgramConfigWithFlags, ProgramConfig, ProgramInit, RoutingProgramInit, MakeRuntimeReturn, Visibility, SlowViewContext, SlowViewConfig, DevToolsConfig, } from './runtime.js';
|
|
2
|
+
export type { RoutingConfig, CrashConfig, CrashContext, RoutingProgramConfigWithFlags, RoutingProgramConfig, ProgramConfigWithFlags, ProgramConfig, ProgramInit, RoutingProgramInit, MakeRuntimeReturn, Visibility, SlowViewContext, SlowViewConfig, DevToolsConfig, DevToolsMode, DevToolsModeConfig, } from './runtime.js';
|
|
3
3
|
export { UrlRequest } from './urlRequest.js';
|
|
4
4
|
export type { Internal, External } from './urlRequest.js';
|
|
5
5
|
//# sourceMappingURL=public.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/runtime/public.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,cAAc,CAAA;AAE/C,YAAY,EACV,aAAa,EACb,WAAW,EACX,YAAY,EACZ,6BAA6B,EAC7B,oBAAoB,EACpB,sBAAsB,EACtB,aAAa,EACb,WAAW,EACX,kBAAkB,EAClB,iBAAiB,EACjB,UAAU,EACV,eAAe,EACf,cAAc,EACd,cAAc,
|
|
1
|
+
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/runtime/public.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,cAAc,CAAA;AAE/C,YAAY,EACV,aAAa,EACb,WAAW,EACX,YAAY,EACZ,6BAA6B,EAC7B,oBAAoB,EACpB,sBAAsB,EACtB,aAAa,EACb,WAAW,EACX,kBAAkB,EAClB,iBAAiB,EACjB,UAAU,EACV,eAAe,EACf,cAAc,EACd,cAAc,EACd,YAAY,EACZ,kBAAkB,GACnB,MAAM,cAAc,CAAA;AAErB,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE5C,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA"}
|
|
@@ -15,6 +15,15 @@ export type Visibility = 'Development' | 'Always';
|
|
|
15
15
|
* - `'TimeTravel'`: Clicking a row pauses the app at that historical state. Resume to continue.
|
|
16
16
|
*/
|
|
17
17
|
export type DevToolsMode = 'Inspect' | 'TimeTravel';
|
|
18
|
+
/** Mode value for the DevTools panel. Either a single mode used in every
|
|
19
|
+
* environment, or an object selecting different modes for development and
|
|
20
|
+
* production. Use the object form to keep `'TimeTravel'` for local debugging
|
|
21
|
+
* while shipping the safer `'Inspect'` mode to users. `'TimeTravel'` in
|
|
22
|
+
* production pauses the user's app when a history row is clicked. */
|
|
23
|
+
export type DevToolsModeConfig = DevToolsMode | Readonly<{
|
|
24
|
+
development: DevToolsMode;
|
|
25
|
+
production: DevToolsMode;
|
|
26
|
+
}>;
|
|
18
27
|
/**
|
|
19
28
|
* DevTools configuration.
|
|
20
29
|
*
|
|
@@ -22,14 +31,18 @@ export type DevToolsMode = 'Inspect' | 'TimeTravel';
|
|
|
22
31
|
*
|
|
23
32
|
* - `show`: `'Development'` (default) enables in dev mode only, `'Always'` enables in all environments including production.
|
|
24
33
|
* - `position`: Where the badge and panel appear. Defaults to `'BottomRight'`.
|
|
25
|
-
* - `mode`: `'TimeTravel'` (default) enables full time-travel debugging. `'Inspect'` allows browsing state snapshots without pausing the app.
|
|
34
|
+
* - `mode`: `'TimeTravel'` (default) enables full time-travel debugging. `'Inspect'` allows browsing state snapshots without pausing the app. Pass `{ development, production }` to use different modes per environment. Useful when DevTools is shown in production (`show: 'Always'`) and you want `'TimeTravel'` only in local development.
|
|
26
35
|
* - `banner`: Optional text shown as a banner at the top of the panel.
|
|
36
|
+
* - `excludeFromHistory`: Message `_tag` values whose dispatches should not be recorded in DevTools history. The Messages still drive `update` and the runtime as usual; they just don't appear in the history panel and don't pay the per-Message diff cost. Use for high-frequency Messages (animation frames, pointer moves, scroll events) that would flood history without adding insight.
|
|
37
|
+
* - `maxEntries`: Maximum number of recorded Messages retained in history before the oldest is evicted. Defaults to 100. Clamped to the range 20-500: smaller values keep the panel snappy under high message rates, larger values give you more scroll-back. Each retained entry stores a full Model snapshot, so memory cost scales linearly with both `maxEntries` and your Model size.
|
|
27
38
|
*/
|
|
28
39
|
export type DevToolsConfig = false | Readonly<{
|
|
29
40
|
show?: Visibility;
|
|
30
41
|
position?: DevToolsPosition;
|
|
31
|
-
mode?:
|
|
42
|
+
mode?: DevToolsModeConfig;
|
|
32
43
|
banner?: string;
|
|
44
|
+
excludeFromHistory?: ReadonlyArray<string>;
|
|
45
|
+
maxEntries?: number;
|
|
33
46
|
/**
|
|
34
47
|
* The application's `Message` Schema. When provided and the running app
|
|
35
48
|
* is connected to the Foldkit DevTools MCP server, AI agents can dispatch
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/runtime/runtime.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,OAAO,EAEP,MAAM,EAGN,KAAK,EAEL,MAAM,EAON,MAAM,EAIP,MAAM,QAAQ,CAAA;AAGf,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AASlD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAE3C,OAAO,EAAE,GAAG,EAA+B,MAAM,iBAAiB,CAAA;AAalE,OAAO,KAAK,EAEV,gBAAgB,EACjB,MAAM,sBAAsB,CAAA;AAI7B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAe5C,0DAA0D;AAC1D,MAAM,MAAM,gBAAgB,GACxB,aAAa,GACb,YAAY,GACZ,UAAU,GACV,SAAS,CAAA;AAEb,wCAAwC;AACxC,MAAM,MAAM,UAAU,GAAG,aAAa,GAAG,QAAQ,CAAA;AAEjD;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,YAAY,CAAA;AAEnD
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/runtime/runtime.ts"],"names":[],"mappings":"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"}
|
package/dist/runtime/runtime.js
CHANGED
|
@@ -20,6 +20,16 @@ const toCommandRecord = (command) => command.args !== undefined
|
|
|
20
20
|
const DEFAULT_DEV_TOOLS_SHOW = 'Development';
|
|
21
21
|
const DEFAULT_DEV_TOOLS_POSITION = 'BottomRight';
|
|
22
22
|
const DEFAULT_DEV_TOOLS_MODE = 'TimeTravel';
|
|
23
|
+
const resolveDevToolsMode = (config) => {
|
|
24
|
+
if (typeof config === 'string') {
|
|
25
|
+
return config;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
return import.meta.hot ? config.development : config.production;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
const DEV_TOOLS_MAX_ENTRIES_MIN = 20;
|
|
32
|
+
const DEV_TOOLS_MAX_ENTRIES_MAX = 500;
|
|
23
33
|
const DEFAULT_SLOW_VIEW_SHOW = 'Development';
|
|
24
34
|
const DEFAULT_SLOW_VIEW_THRESHOLD_MS = 16;
|
|
25
35
|
const defaultSlowViewCallback = (context) => {
|
|
@@ -43,6 +53,11 @@ const makeRuntime = ({ Model, flags: resolveFlags, init, update, view, subscript
|
|
|
43
53
|
onSlowView: config.onSlowView ?? defaultSlowViewCallback,
|
|
44
54
|
})));
|
|
45
55
|
const isFreezeModelActive = freezeModel !== false && !!import.meta.hot;
|
|
56
|
+
const excludeFromHistoryTags = pipe(devTools ?? {}, Option.liftPredicate(config => config !== false), Option.flatMapNullishOr(config => config.excludeFromHistory), Option.match({
|
|
57
|
+
onNone: () => new Set(),
|
|
58
|
+
onSome: tags => new Set(tags),
|
|
59
|
+
}));
|
|
60
|
+
const devToolsMaxEntries = pipe(devTools ?? {}, Option.liftPredicate(config => config !== false), Option.flatMapNullishOr(config => config.maxEntries), Option.map(value => Math.max(DEV_TOOLS_MAX_ENTRIES_MIN, Math.min(DEV_TOOLS_MAX_ENTRIES_MAX, value))), Option.getOrUndefined);
|
|
46
61
|
const maybeFreezeModel = (model) => isFreezeModelActive ? deepFreeze(model) : model;
|
|
47
62
|
const runtimeId = container?.id ?? '';
|
|
48
63
|
// NOTE: When the message queue drains a chain of dispatches (e.g. recursive
|
|
@@ -221,13 +236,25 @@ const makeRuntime = ({ Model, flags: resolveFlags, init, update, view, subscript
|
|
|
221
236
|
attributes: command.args ?? {},
|
|
222
237
|
}), provideAllResources, Effect.flatMap(enqueueNormal))));
|
|
223
238
|
const maybeDevToolsStore = yield* Ref.get(maybeDevToolsStoreRef);
|
|
239
|
+
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */
|
|
240
|
+
const messageTag = message._tag;
|
|
241
|
+
const isModelChanged = currentModel !== nextModel;
|
|
242
|
+
const isExcludedFromHistory = excludeFromHistoryTags.has(messageTag);
|
|
224
243
|
yield* Option.match(maybeDevToolsStore, {
|
|
225
244
|
onNone: () => Effect.void,
|
|
226
|
-
onSome: store =>
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
245
|
+
onSome: store => {
|
|
246
|
+
if (!isExcludedFromHistory) {
|
|
247
|
+
return store.recordMessage(
|
|
248
|
+
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */
|
|
249
|
+
message, currentModel, nextModel, Array.map(
|
|
250
|
+
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */
|
|
251
|
+
commands, toCommandRecord), isModelChanged);
|
|
252
|
+
}
|
|
253
|
+
if (isModelChanged) {
|
|
254
|
+
return store.updateLatestModel(nextModel);
|
|
255
|
+
}
|
|
256
|
+
return Effect.void;
|
|
257
|
+
},
|
|
231
258
|
});
|
|
232
259
|
});
|
|
233
260
|
// NOTE: `dispatchService` defaults to the live dispatch but is
|
|
@@ -264,17 +291,28 @@ const makeRuntime = ({ Model, flags: resolveFlags, init, update, view, subscript
|
|
|
264
291
|
const isInIframe = window.self !== window.top;
|
|
265
292
|
const resolvedDevTools = pipe(devTools ?? {}, Option.liftPredicate(config => config !== false), Option.filter(config => Match.value(config.show ?? DEFAULT_DEV_TOOLS_SHOW).pipe(Match.when('Always', () => true), Match.when('Development', () => !!import.meta.hot && !isInIframe), Match.exhaustive)), Option.map(config => ({
|
|
266
293
|
position: config.position ?? DEFAULT_DEV_TOOLS_POSITION,
|
|
267
|
-
mode: config.mode ?? DEFAULT_DEV_TOOLS_MODE,
|
|
294
|
+
mode: resolveDevToolsMode(config.mode ?? DEFAULT_DEV_TOOLS_MODE),
|
|
268
295
|
maybeBanner: Option.fromNullishOr(config.banner),
|
|
269
296
|
})));
|
|
270
297
|
if (Option.isSome(resolvedDevTools)) {
|
|
271
298
|
const { position, mode, maybeBanner } = resolvedDevTools.value;
|
|
299
|
+
// NOTE: when excludeFromHistory is active, the runtime drops
|
|
300
|
+
// excluded Messages from the recorded history. Replay walks the
|
|
301
|
+
// recorded entries forward from the nearest keyframe — but with
|
|
302
|
+
// exclusion, the dropped Messages aren't in that walk, so any
|
|
303
|
+
// cumulative state they would have produced is missing from the
|
|
304
|
+
// replayed model. Setting keyframeInterval to 1 stores a full
|
|
305
|
+
// snapshot on every recorded entry, so time-travel becomes a
|
|
306
|
+
// direct lookup that reflects the real live state at the moment
|
|
307
|
+
// the entry was recorded.
|
|
308
|
+
const isExcludingMessages = excludeFromHistoryTags.size > 0;
|
|
272
309
|
const devToolsStore = yield* createDevToolsStore({
|
|
310
|
+
/* eslint-disable @typescript-eslint/consistent-type-assertions */
|
|
273
311
|
replay: (model, message) => {
|
|
274
|
-
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */
|
|
275
312
|
const [updatedModel] = update(model, message);
|
|
276
313
|
return maybeFreezeModel(updatedModel);
|
|
277
314
|
},
|
|
315
|
+
/* eslint-enable @typescript-eslint/consistent-type-assertions */
|
|
278
316
|
// NOTE: clears the dirty bit on the jumpTo render so the
|
|
279
317
|
// renderLoop's Stream.changes sees the next dispatch as a real
|
|
280
318
|
// false-to-true transition rather than a deduped no-op. Passes
|
|
@@ -295,6 +333,11 @@ const makeRuntime = ({ Model, flags: resolveFlags, init, update, view, subscript
|
|
|
295
333
|
// animation frame, which renders the live model with live
|
|
296
334
|
// dispatch and rebinds listeners.
|
|
297
335
|
markRenderPending: SubscriptionRef.set(isRenderPendingRef, true),
|
|
336
|
+
}, {
|
|
337
|
+
...(isExcludingMessages && { keyframeInterval: 1 }),
|
|
338
|
+
...(devToolsMaxEntries !== undefined && {
|
|
339
|
+
maxEntries: devToolsMaxEntries,
|
|
340
|
+
}),
|
|
298
341
|
});
|
|
299
342
|
yield* Ref.set(maybeDevToolsStoreRef, Option.some(devToolsStore));
|
|
300
343
|
// The init render runs below; capture the events it produces. We
|
|
@@ -172,7 +172,6 @@ export declare const SubscriptionDeps: S.Struct<{
|
|
|
172
172
|
export declare const subscriptions: import("../../runtime/subscription.js").Subscriptions<{
|
|
173
173
|
readonly id: string;
|
|
174
174
|
readonly orientation: "Vertical" | "Horizontal";
|
|
175
|
-
readonly activationThreshold: number;
|
|
176
175
|
readonly dragState: {
|
|
177
176
|
readonly _tag: "Idle";
|
|
178
177
|
} | {
|
|
@@ -209,7 +208,10 @@ export declare const subscriptions: import("../../runtime/subscription.js").Subs
|
|
|
209
208
|
readonly targetContainerId: string;
|
|
210
209
|
readonly targetIndex: number;
|
|
211
210
|
};
|
|
211
|
+
readonly activationThreshold: number;
|
|
212
212
|
}, {
|
|
213
|
+
readonly _tag: "CancelledDrag";
|
|
214
|
+
} | {
|
|
213
215
|
readonly _tag: "PressedDraggable";
|
|
214
216
|
readonly screenX: number;
|
|
215
217
|
readonly screenY: number;
|
|
@@ -228,8 +230,6 @@ export declare const subscriptions: import("../../runtime/subscription.js").Subs
|
|
|
228
230
|
}>;
|
|
229
231
|
} | {
|
|
230
232
|
readonly _tag: "ReleasedPointer";
|
|
231
|
-
} | {
|
|
232
|
-
readonly _tag: "CancelledDrag";
|
|
233
233
|
} | {
|
|
234
234
|
readonly _tag: "ActivatedKeyboardDrag";
|
|
235
235
|
readonly index: number;
|
|
@@ -83,26 +83,41 @@ type UpdateReturn = readonly [
|
|
|
83
83
|
/** Processes a slider message and returns the next model, commands, and an
|
|
84
84
|
* optional out-message for the parent. */
|
|
85
85
|
export declare const update: (model: Model, message: Message) => UpdateReturn;
|
|
86
|
-
/**
|
|
87
|
-
*
|
|
86
|
+
/** Updates the slider's range. Snaps and clamps the current value into the
|
|
87
|
+
* new range. Use this when min/max derive from external state (e.g. a
|
|
88
|
+
* bounded buffer whose first/last index shifts over time). Unlike `setValue`,
|
|
89
|
+
* this runs even while the user is Dragging: a structural range change
|
|
90
|
+
* cannot leave the value out of bounds. */
|
|
91
|
+
export declare const setRange: (model: Model, range: Readonly<{
|
|
92
|
+
min: number;
|
|
93
|
+
max: number;
|
|
94
|
+
}>) => Model;
|
|
95
|
+
/** Sets the slider's value, snapped and clamped into the current range.
|
|
96
|
+
* No-op while the user is actively dragging. drag state owns the value.
|
|
97
|
+
* Does not emit `ChangedValue`; use when the value is being driven by
|
|
98
|
+
* external state rather than user input. */
|
|
99
|
+
export declare const setValue: (model: Model, value: number) => Model;
|
|
100
|
+
/** Schema describing the subscription dependencies for slider drag. */
|
|
88
101
|
export declare const SubscriptionDeps: S.Struct<{
|
|
89
|
-
readonly
|
|
102
|
+
readonly dragPointer: S.Struct<{
|
|
90
103
|
readonly dragActivity: S.Literals<readonly ["Idle", "Active"]>;
|
|
91
104
|
readonly id: S.String;
|
|
92
105
|
readonly min: S.Number;
|
|
93
106
|
readonly max: S.Number;
|
|
94
107
|
}>;
|
|
95
|
-
readonly
|
|
108
|
+
readonly dragEscape: S.Struct<{
|
|
96
109
|
readonly dragActivity: S.Literals<readonly ["Idle", "Active"]>;
|
|
97
110
|
}>;
|
|
98
111
|
}>;
|
|
99
|
-
/**
|
|
100
|
-
*
|
|
101
|
-
|
|
112
|
+
/** Builds slider drag subscriptions, looking up the track
|
|
113
|
+
* element through the supplied root resolver. Use this when the slider is
|
|
114
|
+
* rendered inside a Shadow DOM. The root is read lazily so consumers can
|
|
115
|
+
* resolve it at subscription time. */
|
|
116
|
+
export declare const subscriptionsForRoot: (getTrackRoot: () => Document | ShadowRoot) => import("../../runtime/subscription.js").Subscriptions<{
|
|
102
117
|
readonly value: number;
|
|
103
118
|
readonly id: string;
|
|
104
|
-
readonly max: number;
|
|
105
119
|
readonly min: number;
|
|
120
|
+
readonly max: number;
|
|
106
121
|
readonly step: number;
|
|
107
122
|
readonly dragState: {
|
|
108
123
|
readonly _tag: "Idle";
|
|
@@ -111,8 +126,45 @@ export declare const subscriptions: import("../../runtime/subscription.js").Subs
|
|
|
111
126
|
readonly originValue: number;
|
|
112
127
|
};
|
|
113
128
|
}, {
|
|
129
|
+
readonly _tag: "PressedThumb";
|
|
130
|
+
} | {
|
|
131
|
+
readonly _tag: "PressedPointer";
|
|
132
|
+
readonly value: number;
|
|
133
|
+
} | {
|
|
134
|
+
readonly _tag: "MovedDragPointer";
|
|
135
|
+
readonly value: number;
|
|
136
|
+
} | {
|
|
137
|
+
readonly _tag: "ReleasedDragPointer";
|
|
138
|
+
} | {
|
|
114
139
|
readonly _tag: "CancelledDrag";
|
|
115
140
|
} | {
|
|
141
|
+
readonly _tag: "PressedKeyboardNavigation";
|
|
142
|
+
readonly direction: "Max" | "Min" | "StepDecrement" | "StepIncrement" | "PageDecrement" | "PageIncrement";
|
|
143
|
+
}, S.Struct<{
|
|
144
|
+
readonly dragPointer: S.Struct<{
|
|
145
|
+
readonly dragActivity: S.Literals<readonly ["Idle", "Active"]>;
|
|
146
|
+
readonly id: S.String;
|
|
147
|
+
readonly min: S.Number;
|
|
148
|
+
readonly max: S.Number;
|
|
149
|
+
}>;
|
|
150
|
+
readonly dragEscape: S.Struct<{
|
|
151
|
+
readonly dragActivity: S.Literals<readonly ["Idle", "Active"]>;
|
|
152
|
+
}>;
|
|
153
|
+
}>, never>;
|
|
154
|
+
/** Default drag subscriptions, with the track looked up via `document`. */
|
|
155
|
+
export declare const subscriptions: import("../../runtime/subscription.js").Subscriptions<{
|
|
156
|
+
readonly value: number;
|
|
157
|
+
readonly id: string;
|
|
158
|
+
readonly min: number;
|
|
159
|
+
readonly max: number;
|
|
160
|
+
readonly step: number;
|
|
161
|
+
readonly dragState: {
|
|
162
|
+
readonly _tag: "Idle";
|
|
163
|
+
} | {
|
|
164
|
+
readonly _tag: "Dragging";
|
|
165
|
+
readonly originValue: number;
|
|
166
|
+
};
|
|
167
|
+
}, {
|
|
116
168
|
readonly _tag: "PressedThumb";
|
|
117
169
|
} | {
|
|
118
170
|
readonly _tag: "PressedPointer";
|
|
@@ -122,17 +174,19 @@ export declare const subscriptions: import("../../runtime/subscription.js").Subs
|
|
|
122
174
|
readonly value: number;
|
|
123
175
|
} | {
|
|
124
176
|
readonly _tag: "ReleasedDragPointer";
|
|
177
|
+
} | {
|
|
178
|
+
readonly _tag: "CancelledDrag";
|
|
125
179
|
} | {
|
|
126
180
|
readonly _tag: "PressedKeyboardNavigation";
|
|
127
181
|
readonly direction: "Max" | "Min" | "StepDecrement" | "StepIncrement" | "PageDecrement" | "PageIncrement";
|
|
128
182
|
}, S.Struct<{
|
|
129
|
-
readonly
|
|
183
|
+
readonly dragPointer: S.Struct<{
|
|
130
184
|
readonly dragActivity: S.Literals<readonly ["Idle", "Active"]>;
|
|
131
185
|
readonly id: S.String;
|
|
132
186
|
readonly min: S.Number;
|
|
133
187
|
readonly max: S.Number;
|
|
134
188
|
}>;
|
|
135
|
-
readonly
|
|
189
|
+
readonly dragEscape: S.Struct<{
|
|
136
190
|
readonly dragActivity: S.Literals<readonly ["Idle", "Active"]>;
|
|
137
191
|
}>;
|
|
138
192
|
}>, never>;
|
|
@@ -156,13 +210,17 @@ export type ViewConfig<ParentMessage> = Readonly<{
|
|
|
156
210
|
formatValue?: (value: number) => string;
|
|
157
211
|
isDisabled?: boolean;
|
|
158
212
|
name?: string;
|
|
213
|
+
/** Resolves the root that holds the slider track when looking it up by its
|
|
214
|
+
* `data-slider-track-id` attribute. Defaults to `document`. Provide a
|
|
215
|
+
* ShadowRoot when rendering the slider inside a shadow tree so pointer
|
|
216
|
+
* events on the track can map clientX into a value. */
|
|
217
|
+
getTrackRoot?: () => Document | ShadowRoot;
|
|
159
218
|
}>;
|
|
160
219
|
/** Renders an accessible slider by building ARIA attribute groups and
|
|
161
220
|
* delegating layout to the consumer's `toView` callback. Follows the
|
|
162
221
|
* WAI-ARIA slider pattern — role="slider" on the thumb, aria-valuemin /
|
|
163
222
|
* aria-valuemax / aria-valuenow, keyboard navigation by step / page / home /
|
|
164
|
-
* end. Pointer drag is handled by the component's
|
|
165
|
-
* subscriptions. */
|
|
223
|
+
* end. Pointer drag is handled by the component's drag subscriptions. */
|
|
166
224
|
export declare const view: <ParentMessage>(config: ViewConfig<ParentMessage>) => Html;
|
|
167
225
|
/** Creates a memoized slider view. Static config is captured in a closure;
|
|
168
226
|
* only `model` and `toParentMessage` are compared per render via `createLazy`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/slider/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,MAAM,EACN,MAAM,IAAI,CAAC,EAIZ,MAAM,QAAQ,CAAA;AAEf,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAA;AACrD,OAAO,EACL,KAAK,SAAS,EACd,KAAK,IAAI,EAGV,MAAM,qBAAqB,CAAA;AAa5B;uDACuD;AACvD,eAAO,MAAM,KAAK;;;;;;;;;EAOhB,CAAA;AAEF,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAIrC,4EAA4E;AAC5E,eAAO,MAAM,YAAY,0EAAoB,CAAA;AAC7C;;sDAEsD;AACtD,eAAO,MAAM,cAAc;;EAA2C,CAAA;AACtE;wCACwC;AACxC,eAAO,MAAM,gBAAgB;;EAA6C,CAAA;AAC1E,yEAAyE;AACzE,eAAO,MAAM,mBAAmB,iFAA2B,CAAA;AAC3D,iFAAiF;AACjF,eAAO,MAAM,aAAa,2EAAqB,CAAA;AAC/C,uEAAuE;AACvE,eAAO,MAAM,yBAAyB;;EASpC,CAAA;AAEF,8DAA8D;AAC9D,eAAO,MAAM,OAAO,EAAE,CAAC,CAAC,KAAK,CAC3B;IACE,OAAO,YAAY;IACnB,OAAO,cAAc;IACrB,OAAO,gBAAgB;IACvB,OAAO,mBAAmB;IAC1B,OAAO,aAAa;IACpB,OAAO,yBAAyB;CACjC,CAQD,CAAA;AAEF,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAEzC,MAAM,MAAM,YAAY,GAAG,OAAO,YAAY,CAAC,IAAI,CAAA;AACnD,MAAM,MAAM,cAAc,GAAG,OAAO,cAAc,CAAC,IAAI,CAAA;AACvD,MAAM,MAAM,gBAAgB,GAAG,OAAO,gBAAgB,CAAC,IAAI,CAAA;AAC3D,MAAM,MAAM,mBAAmB,GAAG,OAAO,mBAAmB,CAAC,IAAI,CAAA;AACjE,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC,IAAI,CAAA;AACrD,MAAM,MAAM,yBAAyB,GAAG,OAAO,yBAAyB,CAAC,IAAI,CAAA;AAI7E;uEACuE;AACvE,eAAO,MAAM,YAAY;;EAA0C,CAAA;AAEnE,6EAA6E;AAC7E,eAAO,MAAM,UAAU;;EAAe,CAAA;AACtC,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,CAAC,IAAI,CAAA;AAI/C,6DAA6D;AAC7D,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAChC,EAAE,EAAE,MAAM,CAAA;IACV,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,YAAY,EAAE,MAAM,CAAA;CACrB,CAAC,CAAA;AAEF;kDACkD;AAClD,eAAO,MAAM,IAAI,GAAI,QAAQ,UAAU,KAAG,KAOxC,CAAA;AAkCF;gCACgC;AAChC,eAAO,MAAM,eAAe,GAAI,OAAO,KAAK,KAAG,MAO9C,CAAA;AAuCD,KAAK,YAAY,GAAG,SAAS;IAC3B,KAAK;IACL,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/B,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC;CAC1B,CAAA;AAmBD;2CAC2C;AAC3C,eAAO,MAAM,MAAM,GAAI,OAAO,KAAK,EAAE,SAAS,OAAO,KAAG,YAwFrD,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/slider/index.ts"],"names":[],"mappings":"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"}
|
package/dist/ui/slider/index.js
CHANGED
|
@@ -152,10 +152,27 @@ export const update = (model, message) => M.value(message).pipe(withUpdateReturn
|
|
|
152
152
|
}), M.orElse(() => [model, [], Option.none()])),
|
|
153
153
|
PressedKeyboardNavigation: ({ direction }) => withValue(model, nextValueForDirection(model, direction), []),
|
|
154
154
|
}));
|
|
155
|
+
/** Updates the slider's range. Snaps and clamps the current value into the
|
|
156
|
+
* new range. Use this when min/max derive from external state (e.g. a
|
|
157
|
+
* bounded buffer whose first/last index shifts over time). Unlike `setValue`,
|
|
158
|
+
* this runs even while the user is Dragging: a structural range change
|
|
159
|
+
* cannot leave the value out of bounds. */
|
|
160
|
+
export const setRange = (model, range) => evo(model, {
|
|
161
|
+
min: () => range.min,
|
|
162
|
+
max: () => range.max,
|
|
163
|
+
value: current => snapAndClamp(current, range.min, range.max, model.step),
|
|
164
|
+
});
|
|
165
|
+
/** Sets the slider's value, snapped and clamped into the current range.
|
|
166
|
+
* No-op while the user is actively dragging. drag state owns the value.
|
|
167
|
+
* Does not emit `ChangedValue`; use when the value is being driven by
|
|
168
|
+
* external state rather than user input. */
|
|
169
|
+
export const setValue = (model, value) => M.value(model.dragState).pipe(M.withReturnType(), M.tag('Dragging', () => model), M.orElse(() => evo(model, {
|
|
170
|
+
value: () => snapAndClamp(value, model.min, model.max, model.step),
|
|
171
|
+
})));
|
|
155
172
|
// SUBSCRIPTION
|
|
156
173
|
const DragActivity = S.Literals(['Idle', 'Active']);
|
|
157
174
|
const dragActivityFromModel = (model) => M.value(model.dragState).pipe(M.withReturnType(), M.tag('Dragging', () => 'Active'), M.orElse(() => 'Idle'));
|
|
158
|
-
const trackElement = (id) => Option.fromNullishOr(
|
|
175
|
+
const trackElement = (id, root) => Option.fromNullishOr(root.querySelector(`[data-slider-track-id="${id}"]`));
|
|
159
176
|
const valueFromClientX = (clientX, trackElement_, min, max) => {
|
|
160
177
|
const rect = trackElement_.getBoundingClientRect();
|
|
161
178
|
if (rect.width === 0) {
|
|
@@ -166,23 +183,24 @@ const valueFromClientX = (clientX, trackElement_, min, max) => {
|
|
|
166
183
|
return min + fraction * (max - min);
|
|
167
184
|
}
|
|
168
185
|
};
|
|
169
|
-
/** Schema describing the subscription dependencies for
|
|
170
|
-
* tracking. */
|
|
186
|
+
/** Schema describing the subscription dependencies for slider drag. */
|
|
171
187
|
export const SubscriptionDeps = S.Struct({
|
|
172
|
-
|
|
188
|
+
dragPointer: S.Struct({
|
|
173
189
|
dragActivity: DragActivity,
|
|
174
190
|
id: S.String,
|
|
175
191
|
min: S.Number,
|
|
176
192
|
max: S.Number,
|
|
177
193
|
}),
|
|
178
|
-
|
|
194
|
+
dragEscape: S.Struct({
|
|
179
195
|
dragActivity: DragActivity,
|
|
180
196
|
}),
|
|
181
197
|
});
|
|
182
|
-
/**
|
|
183
|
-
*
|
|
184
|
-
|
|
185
|
-
|
|
198
|
+
/** Builds slider drag subscriptions, looking up the track
|
|
199
|
+
* element through the supplied root resolver. Use this when the slider is
|
|
200
|
+
* rendered inside a Shadow DOM. The root is read lazily so consumers can
|
|
201
|
+
* resolve it at subscription time. */
|
|
202
|
+
export const subscriptionsForRoot = (getTrackRoot) => makeSubscriptions(SubscriptionDeps)({
|
|
203
|
+
dragPointer: {
|
|
186
204
|
modelToDependencies: model => ({
|
|
187
205
|
dragActivity: dragActivityFromModel(model),
|
|
188
206
|
id: model.id,
|
|
@@ -190,7 +208,7 @@ export const subscriptions = makeSubscriptions(SubscriptionDeps)({
|
|
|
190
208
|
max: model.max,
|
|
191
209
|
}),
|
|
192
210
|
dependenciesToStream: ({ dragActivity, id, min, max }) => {
|
|
193
|
-
const pointerEvents = Stream.merge(Stream.fromEventListener(document, 'pointermove').pipe(Stream.mapEffect(event => Effect.sync(() => Option.map(trackElement(id), element => MovedDragPointer({
|
|
211
|
+
const pointerEvents = Stream.merge(Stream.fromEventListener(document, 'pointermove').pipe(Stream.mapEffect(event => Effect.sync(() => Option.map(trackElement(id, getTrackRoot()), element => MovedDragPointer({
|
|
194
212
|
value: valueFromClientX(event.clientX, element, min, max),
|
|
195
213
|
})))), Stream.filter(Option.isSome), Stream.map(option => option.value)), Stream.fromEventListener(document, 'pointerup').pipe(Stream.map(() => ReleasedDragPointer())));
|
|
196
214
|
// NOTE: prevents text selection and locks cursor to grabbing while the
|
|
@@ -210,13 +228,15 @@ export const subscriptions = makeSubscriptions(SubscriptionDeps)({
|
|
|
210
228
|
return Stream.when(Stream.merge(pointerEvents, documentDragStyles), Effect.sync(() => dragActivity === 'Active'));
|
|
211
229
|
},
|
|
212
230
|
},
|
|
213
|
-
|
|
231
|
+
dragEscape: {
|
|
214
232
|
modelToDependencies: model => ({
|
|
215
233
|
dragActivity: dragActivityFromModel(model),
|
|
216
234
|
}),
|
|
217
235
|
dependenciesToStream: ({ dragActivity }) => Stream.when(Stream.fromEventListener(document, 'keydown').pipe(Stream.filter(({ key }) => key === 'Escape'), Stream.map(() => CancelledDrag())), Effect.sync(() => dragActivity === 'Active')),
|
|
218
236
|
},
|
|
219
237
|
});
|
|
238
|
+
/** Default drag subscriptions, with the track looked up via `document`. */
|
|
239
|
+
export const subscriptions = subscriptionsForRoot(() => document);
|
|
220
240
|
// VIEW
|
|
221
241
|
const LEFT_MOUSE_BUTTON = 0;
|
|
222
242
|
const labelId = (id) => `${id}-label`;
|
|
@@ -226,16 +246,15 @@ const percentString = (fraction) => `${Math.round(fraction * 10000) / 100}%`;
|
|
|
226
246
|
* delegating layout to the consumer's `toView` callback. Follows the
|
|
227
247
|
* WAI-ARIA slider pattern — role="slider" on the thumb, aria-valuemin /
|
|
228
248
|
* aria-valuemax / aria-valuenow, keyboard navigation by step / page / home /
|
|
229
|
-
* end. Pointer drag is handled by the component's
|
|
230
|
-
* subscriptions. */
|
|
249
|
+
* end. Pointer drag is handled by the component's drag subscriptions. */
|
|
231
250
|
export const view = (config) => {
|
|
232
251
|
const h = html();
|
|
233
|
-
const { model, toParentMessage, formatValue, isDisabled = false, name, } = config;
|
|
252
|
+
const { model, toParentMessage, formatValue, isDisabled = false, name, getTrackRoot = () => document, } = config;
|
|
234
253
|
const { id, value, min, max } = model;
|
|
235
254
|
const isDragging = model.dragState._tag === 'Dragging';
|
|
236
255
|
const fraction = fractionOfValue(model);
|
|
237
256
|
const handleKeyDown = (key) => Option.map(keyToDirection(key), direction => toParentMessage(PressedKeyboardNavigation({ direction })));
|
|
238
|
-
const pointerAtClientX = (clientX) => Option.map(trackElement(id), element => toParentMessage(PressedPointer({
|
|
257
|
+
const pointerAtClientX = (clientX) => Option.map(trackElement(id, getTrackRoot()), element => toParentMessage(PressedPointer({
|
|
239
258
|
value: valueFromClientX(clientX, element, min, max),
|
|
240
259
|
})));
|
|
241
260
|
const trackPointerHandler = (_pointerType, button, _screenX, _screenY, _timeStamp, clientX) => pipe(button, Option.liftPredicate(Equal.equals(LEFT_MOUSE_BUTTON)), Option.flatMap(() => pointerAtClientX(clientX)));
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { init, update, view, lazy, subscriptions, fractionOfValue, Model, Message, OutMessage, SubscriptionDeps, } from './index.js';
|
|
1
|
+
export { init, update, setRange, setValue, view, lazy, subscriptions, subscriptionsForRoot, fractionOfValue, Model, Message, OutMessage, SubscriptionDeps, } from './index.js';
|
|
2
2
|
export type { InitConfig, ViewConfig, SliderAttributes, PressedThumb, PressedPointer, MovedDragPointer, ReleasedDragPointer, CancelledDrag, PressedKeyboardNavigation, } from './index.js';
|
|
3
3
|
//# sourceMappingURL=public.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../src/ui/slider/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EACJ,MAAM,EACN,IAAI,EACJ,IAAI,EACJ,aAAa,EACb,eAAe,EACf,KAAK,EACL,OAAO,EACP,UAAU,EACV,gBAAgB,GACjB,MAAM,YAAY,CAAA;AAEnB,YAAY,EACV,UAAU,EACV,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,mBAAmB,EACnB,aAAa,EACb,yBAAyB,GAC1B,MAAM,YAAY,CAAA"}
|
|
1
|
+
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../src/ui/slider/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EACJ,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,IAAI,EACJ,IAAI,EACJ,aAAa,EACb,oBAAoB,EACpB,eAAe,EACf,KAAK,EACL,OAAO,EACP,UAAU,EACV,gBAAgB,GACjB,MAAM,YAAY,CAAA;AAEnB,YAAY,EACV,UAAU,EACV,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,mBAAmB,EACnB,aAAa,EACb,yBAAyB,GAC1B,MAAM,YAAY,CAAA"}
|
package/dist/ui/slider/public.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { init, update, view, lazy, subscriptions, fractionOfValue, Model, Message, OutMessage, SubscriptionDeps, } from './index.js';
|
|
1
|
+
export { init, update, setRange, setValue, view, lazy, subscriptions, subscriptionsForRoot, fractionOfValue, Model, Message, OutMessage, SubscriptionDeps, } from './index.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "foldkit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.93.0",
|
|
4
4
|
"description": "A TypeScript frontend framework, built on Effect and architected like Elm",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -200,13 +200,13 @@
|
|
|
200
200
|
"dist"
|
|
201
201
|
],
|
|
202
202
|
"peerDependencies": {
|
|
203
|
-
"@effect/platform-browser": "4.0.0-beta.
|
|
204
|
-
"effect": "4.0.0-beta.
|
|
203
|
+
"@effect/platform-browser": "4.0.0-beta.64",
|
|
204
|
+
"effect": "4.0.0-beta.64"
|
|
205
205
|
},
|
|
206
206
|
"devDependencies": {
|
|
207
|
-
"@effect/platform-browser": "4.0.0-beta.
|
|
208
|
-
"@effect/vitest": "4.0.0-beta.
|
|
209
|
-
"effect": "4.0.0-beta.
|
|
207
|
+
"@effect/platform-browser": "4.0.0-beta.64",
|
|
208
|
+
"@effect/vitest": "4.0.0-beta.64",
|
|
209
|
+
"effect": "4.0.0-beta.64",
|
|
210
210
|
"happy-dom": "^20.9.0",
|
|
211
211
|
"rimraf": "^6.1.3",
|
|
212
212
|
"typedoc": "^0.28.19",
|