@scenetest/dashboard 0.11.0 → 0.12.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.
Files changed (77) hide show
  1. package/README.md +87 -35
  2. package/dist/app.d.ts +10 -7
  3. package/dist/app.d.ts.map +1 -1
  4. package/dist/app.js +12 -130
  5. package/dist/app.js.map +1 -1
  6. package/dist/collections/index.d.ts +19 -0
  7. package/dist/collections/index.d.ts.map +1 -0
  8. package/dist/collections/index.js +18 -0
  9. package/dist/collections/index.js.map +1 -0
  10. package/dist/collections/options.d.ts +29 -0
  11. package/dist/collections/options.d.ts.map +1 -0
  12. package/dist/collections/options.js +68 -0
  13. package/dist/collections/options.js.map +1 -0
  14. package/dist/collections/projections.d.ts +117 -0
  15. package/dist/collections/projections.d.ts.map +1 -0
  16. package/dist/collections/projections.js +228 -0
  17. package/dist/collections/projections.js.map +1 -0
  18. package/dist/collections/source.d.ts +32 -0
  19. package/dist/collections/source.d.ts.map +1 -0
  20. package/dist/collections/source.js +84 -0
  21. package/dist/collections/source.js.map +1 -0
  22. package/dist/collections/types.d.ts +87 -0
  23. package/dist/collections/types.d.ts.map +1 -0
  24. package/dist/collections/types.js +2 -0
  25. package/dist/collections/types.js.map +1 -0
  26. package/dist/dashboard.d.ts +20 -0
  27. package/dist/dashboard.d.ts.map +1 -0
  28. package/dist/dashboard.js +114 -0
  29. package/dist/dashboard.js.map +1 -0
  30. package/dist/dev-transport.d.ts +3 -3
  31. package/dist/dev-transport.d.ts.map +1 -1
  32. package/dist/dev-transport.js +3 -7
  33. package/dist/dev-transport.js.map +1 -1
  34. package/dist/index.d.ts +6 -3
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +4 -2
  37. package/dist/index.js.map +1 -1
  38. package/dist/runner.d.ts +8 -0
  39. package/dist/runner.d.ts.map +1 -0
  40. package/dist/runner.js +249 -0
  41. package/dist/runner.js.map +1 -0
  42. package/dist/select-helpers.d.ts +50 -0
  43. package/dist/select-helpers.d.ts.map +1 -0
  44. package/dist/select-helpers.js +48 -0
  45. package/dist/select-helpers.js.map +1 -0
  46. package/dist/select-runner.d.ts +55 -0
  47. package/dist/select-runner.d.ts.map +1 -0
  48. package/dist/select-runner.js +108 -0
  49. package/dist/select-runner.js.map +1 -0
  50. package/dist/select-waterfall.d.ts +12 -0
  51. package/dist/select-waterfall.d.ts.map +1 -0
  52. package/dist/select-waterfall.js +79 -0
  53. package/dist/select-waterfall.js.map +1 -0
  54. package/dist/style.css +878 -0
  55. package/dist/types.d.ts +6 -20
  56. package/dist/types.d.ts.map +1 -1
  57. package/dist/use-live-query.d.ts +28 -0
  58. package/dist/use-live-query.d.ts.map +1 -0
  59. package/dist/use-live-query.js +25 -0
  60. package/dist/use-live-query.js.map +1 -0
  61. package/dist/use-run-slice.d.ts +25 -0
  62. package/dist/use-run-slice.d.ts.map +1 -0
  63. package/dist/use-run-slice.js +48 -0
  64. package/dist/use-run-slice.js.map +1 -0
  65. package/package.json +10 -5
  66. package/dist/mount.d.ts +0 -14
  67. package/dist/mount.d.ts.map +0 -1
  68. package/dist/mount.js +0 -50
  69. package/dist/mount.js.map +0 -1
  70. package/dist/store.d.ts +0 -19
  71. package/dist/store.d.ts.map +0 -1
  72. package/dist/store.js +0 -164
  73. package/dist/store.js.map +0 -1
  74. package/dist/styles.d.ts +0 -10
  75. package/dist/styles.d.ts.map +0 -1
  76. package/dist/styles.js +0 -152
  77. package/dist/styles.js.map +0 -1
@@ -0,0 +1,114 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
2
+ import { useState, useEffect, useMemo } from 'preact/hooks';
3
+ import { createCollection } from '@tanstack/db';
4
+ import { createRunSource, runCollectionOptions, scenesProjection, assertionsProjection, actionsProjection, runsProjection, } from './collections/index.js';
5
+ import { Waterfall } from './app.js';
6
+ import { selectWaterfall } from './select-waterfall.js';
7
+ import { RunnerView } from './runner.js';
8
+ import { useRunSlice } from './use-run-slice.js';
9
+ /** Build the inline `--st-*` custom properties for the theming surface. */
10
+ function themeVars(theme) {
11
+ const vars = {};
12
+ if (theme?.bg)
13
+ vars['--st-bg'] = theme.bg;
14
+ if (theme?.accent)
15
+ vars['--st-accent'] = theme.accent;
16
+ if (theme?.font)
17
+ vars['--st-font'] = theme.font;
18
+ if (theme?.fontSize)
19
+ vars['--st-font-size'] = theme.fontSize;
20
+ return vars;
21
+ }
22
+ function useDashboardStore(transport) {
23
+ const store = useMemo(() => {
24
+ const source = createRunSource(transport);
25
+ return {
26
+ source,
27
+ scenes: createCollection(runCollectionOptions({ source, projection: scenesProjection() })),
28
+ assertions: createCollection(runCollectionOptions({ source, projection: assertionsProjection() })),
29
+ actions: createCollection(runCollectionOptions({ source, projection: actionsProjection() })),
30
+ runs: createCollection(runCollectionOptions({ source, projection: runsProjection() })),
31
+ };
32
+ }, [transport]);
33
+ const [connection, setConnection] = useState('connecting');
34
+ useEffect(() => {
35
+ const stopStatus = store.source.subscribe(() => { }, setConnection);
36
+ return () => {
37
+ stopStatus();
38
+ store.source.close();
39
+ };
40
+ }, [store]);
41
+ return { store, connection };
42
+ }
43
+ // Both hosts mount the dashboard (and its dev middleware endpoints) here. It's
44
+ // a single constant rather than a prop: the routing and the Runner's data
45
+ // fetches must agree, and nothing in-tree mounts it anywhere else.
46
+ const BASE = '/__scenetest';
47
+ function tabForPath(pathname) {
48
+ if (pathname.startsWith(`${BASE}/runner`))
49
+ return 'runner';
50
+ if (pathname.startsWith(`${BASE}/waterfall`))
51
+ return 'waterfall';
52
+ return 'home';
53
+ }
54
+ const PATH_FOR_TAB = {
55
+ home: BASE,
56
+ runner: `${BASE}/runner`,
57
+ waterfall: `${BASE}/waterfall`,
58
+ };
59
+ /**
60
+ * The Dashboard app — Home / Runner / Waterfall views over one read-only
61
+ * `@tanstack/db` read model, routed on `location.pathname`. A plain Preact
62
+ * component rendering into the light DOM under a single `.scenetest-dashboard`
63
+ * root class; the shipped stylesheet scopes everything to it. Dev and cloud
64
+ * render the same component — only the injected `transport` differs.
65
+ *
66
+ * /__scenetest → Home
67
+ * /__scenetest/runner → Runner (filterable scene log)
68
+ * /__scenetest/waterfall → Waterfall (live timeline)
69
+ *
70
+ * The collections are the single store: the component builds them from the run
71
+ * stream and every view reads from them (`selectWaterfall`, `selectSnapshot`).
72
+ */
73
+ export function Dashboard({ transport, theme, }) {
74
+ const { store, connection } = useDashboardStore(transport);
75
+ const [tab, setTab] = useState(() => tabForPath(location.pathname));
76
+ useEffect(() => {
77
+ const onPop = () => setTab(tabForPath(location.pathname));
78
+ window.addEventListener('popstate', onPop);
79
+ return () => window.removeEventListener('popstate', onPop);
80
+ }, []);
81
+ // Client-side navigation via real <a> links, delegated on the app root.
82
+ // Modifier-clicks fall through to the browser as normal links.
83
+ const onNavigate = (e) => {
84
+ const a = e.target?.closest('a');
85
+ const href = a?.getAttribute('href');
86
+ if (!href || !href.startsWith(BASE))
87
+ return;
88
+ if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || e.button !== 0)
89
+ return;
90
+ e.preventDefault();
91
+ history.pushState(null, '', href + location.search);
92
+ setTab(tabForPath(href));
93
+ };
94
+ const send = (command) => {
95
+ void transport.sendCommand(command);
96
+ };
97
+ const tabClass = (t) => 'tab' + (tab === t ? ' active' : '');
98
+ return (_jsxs("div", { class: "scenetest-dashboard", style: themeVars(theme), onClick: onNavigate, children: [_jsxs("nav", { class: "dashboard-nav", children: [_jsxs("h1", { children: [_jsx("span", { class: "logo", children: "\uD83C\uDFAC" }), " Scenetest"] }), _jsxs("div", { class: "tabs", children: [_jsx("a", { class: tabClass('home'), href: PATH_FOR_TAB.home, children: "Home" }), _jsx("a", { class: tabClass('runner'), href: PATH_FOR_TAB.runner, children: "Runner" }), _jsx("a", { class: tabClass('waterfall'), href: PATH_FOR_TAB.waterfall, children: "Waterfall" })] })] }), _jsx("div", { class: "view", children: tab === 'home' ? (_jsx(Home, {})) : tab === 'runner' ? (_jsx(RunnerView, { collections: store, connection: connection, base: BASE })) : (_jsx(WaterfallHost, { collections: store, connection: connection, send: send })) })] }));
99
+ }
100
+ // ── Home ──────────────────────────────────────────────────────────
101
+ function Home() {
102
+ return (_jsxs("div", { class: "index", children: [_jsxs("h1", { children: [_jsx("span", { class: "logo", children: "\uD83C\uDFAC" }), " Scenetest"] }), _jsx("p", { class: "lede", children: "Pick a view." }), _jsxs("div", { class: "cards", children: [_jsxs("a", { class: "card", href: PATH_FOR_TAB.runner, children: [_jsx("div", { class: "name", children: "Scene runner \u2192" }), _jsx("div", { class: "desc", children: "Live and past runs: scene tree, status, failure log, spec snippets." })] }), _jsxs("a", { class: "card", href: PATH_FOR_TAB.waterfall, children: [_jsx("div", { class: "name", children: "Waterfall \u2192" }), _jsx("div", { class: "desc", children: "Live timeline of actors and inline check() / should() assertions." })] })] })] }));
103
+ }
104
+ // ── Waterfall view ─────────────────────────────────────────────────
105
+ // A pure Preact subtree now — its widget styles are scoped to `.waterfall-host`
106
+ // by the stylesheet, so it no longer needs a nested shadow root. Reads the
107
+ // shared store reactively; `selectWaterfall` folds it into the Waterfall shape.
108
+ function WaterfallHost({ collections, connection, send, }) {
109
+ const slice = useRunSlice(collections);
110
+ const view = useMemo(() => selectWaterfall(slice), [slice.runId, slice.run, slice.scenes, slice.assertions, slice.actions]);
111
+ const state = { ...view, connection };
112
+ return (_jsx("div", { class: "waterfall-host", children: _jsx(Waterfall, { state: state, send: send }) }));
113
+ }
114
+ //# sourceMappingURL=dashboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../src/dashboard.tsx"],"names":[],"mappings":"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"}
@@ -10,9 +10,9 @@ export interface DevTransportOptions {
10
10
  /**
11
11
  * Transport adapter for dev mode: the Vite middleware, same-origin.
12
12
  *
13
- * - Live events arrive over the SSE stream at `<base>/events`, which also
14
- * replays the buffered events for the current run on connect so history
15
- * comes through `subscribe`, and `fetchState` returns empty.
13
+ * - History + live events both arrive over the SSE stream at `<base>/events`,
14
+ * which replays the buffered events for the current run on connect and then
15
+ * streams live ones all through `subscribe`.
16
16
  * - Commands map onto the middleware's existing endpoints:
17
17
  * `run:replay` → POST `<base>/replay` (`{ file?, team? }`),
18
18
  * `run:stop` → POST `<base>/stop`,
@@ -1 +1 @@
1
- {"version":3,"file":"dev-transport.d.ts","sourceRoot":"","sources":["../src/dev-transport.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAoB,SAAS,EAAE,MAAM,YAAY,CAAA;AAE7D,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,mBAAwB,GAAG,SAAS,CA0D/E"}
1
+ {"version":3,"file":"dev-transport.d.ts","sourceRoot":"","sources":["../src/dev-transport.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAoB,SAAS,EAAE,MAAM,YAAY,CAAA;AAE7D,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,mBAAwB,GAAG,SAAS,CAqD/E"}
@@ -2,9 +2,9 @@ import { isEventShaped } from '@scenetest/protocol';
2
2
  /**
3
3
  * Transport adapter for dev mode: the Vite middleware, same-origin.
4
4
  *
5
- * - Live events arrive over the SSE stream at `<base>/events`, which also
6
- * replays the buffered events for the current run on connect so history
7
- * comes through `subscribe`, and `fetchState` returns empty.
5
+ * - History + live events both arrive over the SSE stream at `<base>/events`,
6
+ * which replays the buffered events for the current run on connect and then
7
+ * streams live ones all through `subscribe`.
8
8
  * - Commands map onto the middleware's existing endpoints:
9
9
  * `run:replay` → POST `<base>/replay` (`{ file?, team? }`),
10
10
  * `run:stop` → POST `<base>/stop`,
@@ -13,10 +13,6 @@ import { isEventShaped } from '@scenetest/protocol';
13
13
  export function createDevTransport(options = {}) {
14
14
  const base = (options.base ?? '/__scenetest').replace(/\/+$/, '');
15
15
  return {
16
- // SSE replays the run buffer on connect, so there is no separate snapshot.
17
- async fetchState() {
18
- return [];
19
- },
20
16
  subscribe(onEvent, onStatus) {
21
17
  const source = new EventSource(`${base}/events`);
22
18
  const status = (s) => onStatus?.(s);
@@ -1 +1 @@
1
- {"version":3,"file":"dev-transport.js","sourceRoot":"","sources":["../src/dev-transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAanD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,kBAAkB,CAAC,UAA+B,EAAE;IAClE,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,cAAc,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;IAEjE,OAAO;QACL,2EAA2E;QAC3E,KAAK,CAAC,UAAU;YACd,OAAO,EAAE,CAAA;QACX,CAAC;QAED,SAAS,CAAC,OAAO,EAAE,QAAQ;YACzB,MAAM,MAAM,GAAG,IAAI,WAAW,CAAC,GAAG,IAAI,SAAS,CAAC,CAAA;YAChD,MAAM,MAAM,GAAG,CAAC,CAAmB,EAAE,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAA;YACrD,MAAM,CAAC,YAAY,CAAC,CAAA;YAEpB,MAAM,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;YACzC,MAAM,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,CAAA;YAC7C,MAAM,CAAC,SAAS,GAAG,CAAC,CAAe,EAAE,EAAE;gBACrC,IAAI,MAAe,CAAA;gBACnB,IAAI,CAAC;oBACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;gBAC7B,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAM;gBACR,CAAC;gBACD,kEAAkE;gBAClE,sDAAsD;gBACtD,IAAI,aAAa,CAAC,MAAM,CAAC;oBAAE,OAAO,CAAC,MAAkB,CAAC,CAAA;YACxD,CAAC,CAAA;YAED,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QAC7B,CAAC;QAED,KAAK,CAAC,WAAW,CAAC,OAAgB;YAChC,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,IAAc,EAAE,EAAE,CAC5C,KAAK,CAAC,GAAG,IAAI,GAAG,IAAI,EAAE,EAAE;gBACtB,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;aAC5D,CAAC,CAAA;YAEJ,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;gBACrB,KAAK,YAAY,CAAC,CAAC,CAAC;oBAClB,MAAM,IAAI,GAAqC,EAAE,CAAA;oBACjD,IAAI,OAAO,CAAC,IAAI;wBAAE,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAA;oBAC1C,IAAI,OAAO,CAAC,IAAI;wBAAE,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAA;oBAC1C,MAAM,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;oBAC3B,OAAM;gBACR,CAAC;gBACD,KAAK,UAAU;oBACb,MAAM,IAAI,CAAC,OAAO,CAAC,CAAA;oBACnB,OAAM;gBACR,mEAAmE;gBACnE,KAAK,WAAW,CAAC;gBACjB,KAAK,YAAY;oBACf,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAA;oBACpB,OAAM;YACV,CAAC;QACH,CAAC;KACF,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"dev-transport.js","sourceRoot":"","sources":["../src/dev-transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAanD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,kBAAkB,CAAC,UAA+B,EAAE;IAClE,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,cAAc,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;IAEjE,OAAO;QACL,SAAS,CAAC,OAAO,EAAE,QAAQ;YACzB,MAAM,MAAM,GAAG,IAAI,WAAW,CAAC,GAAG,IAAI,SAAS,CAAC,CAAA;YAChD,MAAM,MAAM,GAAG,CAAC,CAAmB,EAAE,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAA;YACrD,MAAM,CAAC,YAAY,CAAC,CAAA;YAEpB,MAAM,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;YACzC,MAAM,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,CAAA;YAC7C,MAAM,CAAC,SAAS,GAAG,CAAC,CAAe,EAAE,EAAE;gBACrC,IAAI,MAAe,CAAA;gBACnB,IAAI,CAAC;oBACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;gBAC7B,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAM;gBACR,CAAC;gBACD,kEAAkE;gBAClE,sDAAsD;gBACtD,IAAI,aAAa,CAAC,MAAM,CAAC;oBAAE,OAAO,CAAC,MAAkB,CAAC,CAAA;YACxD,CAAC,CAAA;YAED,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QAC7B,CAAC;QAED,KAAK,CAAC,WAAW,CAAC,OAAgB;YAChC,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,IAAc,EAAE,EAAE,CAC5C,KAAK,CAAC,GAAG,IAAI,GAAG,IAAI,EAAE,EAAE;gBACtB,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;aAC5D,CAAC,CAAA;YAEJ,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;gBACrB,KAAK,YAAY,CAAC,CAAC,CAAC;oBAClB,MAAM,IAAI,GAAqC,EAAE,CAAA;oBACjD,IAAI,OAAO,CAAC,IAAI;wBAAE,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAA;oBAC1C,IAAI,OAAO,CAAC,IAAI;wBAAE,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAA;oBAC1C,MAAM,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;oBAC3B,OAAM;gBACR,CAAC;gBACD,KAAK,UAAU;oBACb,MAAM,IAAI,CAAC,OAAO,CAAC,CAAA;oBACnB,OAAM;gBACR,mEAAmE;gBACnE,KAAK,WAAW,CAAC;gBACjB,KAAK,YAAY;oBACf,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAA;oBACpB,OAAM;YACV,CAAC;QACH,CAAC;KACF,CAAA;AACH,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,9 @@
1
- export { mountDashboard } from './mount.js';
1
+ export { Dashboard } from './dashboard.js';
2
2
  export { createDevTransport, type DevTransportOptions } from './dev-transport.js';
3
- export { applyEvent, foldEvents, initialState, withConnection, completedSceneCount, } from './store.js';
3
+ export { selectWaterfall, completedSceneCount } from './select-waterfall.js';
4
+ export { selectSnapshot, mapReportToSnapshot } from './select-runner.js';
4
5
  export { sceneSummary } from './app.js';
5
- export type { Transport, ConnectionStatus, DashboardState, DashboardTheme, DashboardHandle, MountOptions, Scene, Lane, ActionItem, AssertionRow, } from './types.js';
6
+ export { useLiveQuery, type ObservableRows } from './use-live-query.js';
7
+ export type { DashboardCollections } from './select-helpers.js';
8
+ export type { Transport, ConnectionStatus, DashboardState, DashboardTheme, Scene, Lane, ActionItem, AssertionRow, } from './types.js';
6
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,EAAE,kBAAkB,EAAE,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACjF,OAAO,EACL,UAAU,EACV,UAAU,EACV,YAAY,EACZ,cAAc,EACd,mBAAmB,GACpB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AACvC,YAAY,EACV,SAAS,EACT,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,eAAe,EACf,YAAY,EACZ,KAAK,EACL,IAAI,EACJ,UAAU,EACV,YAAY,GACb,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,kBAAkB,EAAE,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACjF,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAC5E,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AACvC,OAAO,EAAE,YAAY,EAAE,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACvE,YAAY,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC/D,YAAY,EACV,SAAS,EACT,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,KAAK,EACL,IAAI,EACJ,UAAU,EACV,YAAY,GACb,MAAM,YAAY,CAAA"}
package/dist/index.js CHANGED
@@ -1,5 +1,7 @@
1
- export { mountDashboard } from './mount.js';
1
+ export { Dashboard } from './dashboard.js';
2
2
  export { createDevTransport } from './dev-transport.js';
3
- export { applyEvent, foldEvents, initialState, withConnection, completedSceneCount, } from './store.js';
3
+ export { selectWaterfall, completedSceneCount } from './select-waterfall.js';
4
+ export { selectSnapshot, mapReportToSnapshot } from './select-runner.js';
4
5
  export { sceneSummary } from './app.js';
6
+ export { useLiveQuery } from './use-live-query.js';
5
7
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,EAAE,kBAAkB,EAA4B,MAAM,oBAAoB,CAAA;AACjF,OAAO,EACL,UAAU,EACV,UAAU,EACV,YAAY,EACZ,cAAc,EACd,mBAAmB,GACpB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,kBAAkB,EAA4B,MAAM,oBAAoB,CAAA;AACjF,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAC5E,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AACvC,OAAO,EAAE,YAAY,EAAuB,MAAM,qBAAqB,CAAA"}
@@ -0,0 +1,8 @@
1
+ import type { DashboardCollections } from './select-helpers.js';
2
+ import type { ConnectionStatus } from './types.js';
3
+ export declare function RunnerView({ collections, connection: liveConnection, base, }: {
4
+ collections: DashboardCollections;
5
+ connection: ConnectionStatus;
6
+ base: string;
7
+ }): import("preact").JSX.Element;
8
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC/D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAmElD,wBAAgB,UAAU,CAAC,EACzB,WAAW,EACX,UAAU,EAAE,cAAc,EAC1B,IAAI,GACL,EAAE;IACD,WAAW,EAAE,oBAAoB,CAAA;IACjC,UAAU,EAAE,gBAAgB,CAAA;IAC5B,IAAI,EAAE,MAAM,CAAA;CACb,gCAkDA"}
package/dist/runner.js ADDED
@@ -0,0 +1,249 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
2
+ import { useState, useEffect, useMemo, useCallback, useRef } from 'preact/hooks';
3
+ import { selectSnapshot, mapReportToSnapshot, EMPTY_SNAPSHOT, } from './select-runner.js';
4
+ import { useRunSlice } from './use-run-slice.js';
5
+ const STATUSES = ['failed', 'timeout', 'running', 'completed'];
6
+ // ── Helpers ───────────────────────────────────────────────────────
7
+ function shortFile(f) {
8
+ if (!f)
9
+ return '';
10
+ const parts = f.replace(/\\/g, '/').split('/');
11
+ return parts.length > 2 ? '…/' + parts.slice(-2).join('/') : f;
12
+ }
13
+ function statusIcon(s) {
14
+ return s === 'completed' ? '✓' : s === 'running' ? '◐' : s === 'timeout' ? '⏱' : '✗';
15
+ }
16
+ function teamLabel(s) {
17
+ return s.team?.name || 'team ' + s.teamIndex;
18
+ }
19
+ // ── Data: live reads the shared read model; past fetches a report ──
20
+ function useRunner(collections, liveConnection, runId, base) {
21
+ // Read the store reactively (live mode): the latest-run slice is maintained
22
+ // by live-query collections (`where runId = latest`, ordered); the selector
23
+ // attributes assertions/actions to scenes and rolls up the summary.
24
+ const slice = useRunSlice(collections);
25
+ const live = useMemo(() => selectSnapshot(slice), [slice.runId, slice.run, slice.scenes, slice.assertions, slice.actions]);
26
+ const [past, setPast] = useState(EMPTY_SNAPSHOT);
27
+ useEffect(() => {
28
+ if (runId === 'live')
29
+ return;
30
+ setPast(EMPTY_SNAPSHOT);
31
+ let alive = true;
32
+ fetch(`${base}/runs/${encodeURIComponent(runId)}`)
33
+ .then((r) => (r.ok ? r.json() : null))
34
+ .then((data) => {
35
+ if (alive && data)
36
+ setPast(mapReportToSnapshot(data));
37
+ })
38
+ .catch(() => { });
39
+ return () => {
40
+ alive = false;
41
+ };
42
+ }, [runId, base]);
43
+ if (runId === 'live')
44
+ return { snap: live, connection: liveConnection };
45
+ return { snap: past, connection: 'idle' };
46
+ }
47
+ // ── Runner view root ──────────────────────────────────────────────
48
+ export function RunnerView({ collections, connection: liveConnection, base, }) {
49
+ const [runId, setRunId] = useState(() => new URLSearchParams(location.search).get('run') || 'live');
50
+ const [runs, setRuns] = useState([]);
51
+ const [filters, setFilters] = useState({ text: '', statuses: new Set(STATUSES), groupBy: 'status' });
52
+ const [selected, setSelected] = useState(null);
53
+ const { snap, connection } = useRunner(collections, liveConnection, runId, base);
54
+ useEffect(() => {
55
+ fetch(`${base}/runs`)
56
+ .then((r) => (r.ok ? r.json() : null))
57
+ .then((data) => {
58
+ if (data)
59
+ setRuns(data.runs || []);
60
+ })
61
+ .catch(() => { });
62
+ }, [base]);
63
+ // Reflect the chosen run in the URL, preserving the route path.
64
+ useEffect(() => {
65
+ const p = new URLSearchParams(location.search);
66
+ p.set('run', runId);
67
+ history.replaceState(null, '', location.pathname + '?' + p.toString());
68
+ setSelected(null);
69
+ }, [runId]);
70
+ const scene = snap.scenes.find((s) => s.id === selected);
71
+ return (_jsxs("div", { class: "runner", children: [_jsx(RunnerHeader, { runs: runs, runId: runId, onRunChange: setRunId, connection: connection, summary: snap.summary, scenes: snap.scenes }), _jsxs("main", { children: [_jsx(Tree, { scenes: snap.scenes, selected: selected, onSelect: setSelected }), _jsx(ListPane, { scenes: snap.scenes, filters: filters, onFilters: setFilters, selected: selected, onSelect: setSelected, runId: runId }), _jsx(Detail, { scene: scene, base: base })] })] }));
72
+ }
73
+ // ── Header (run picker + status) ──────────────────────────────────
74
+ function RunnerHeader({ runs, runId, onRunChange, connection, summary, scenes, }) {
75
+ const completed = scenes.filter((s) => s.status === 'completed').length;
76
+ const a = summary.assertions;
77
+ return (_jsxs("div", { class: "runner-bar", children: [_jsxs("div", { class: "run-picker", children: [_jsx("label", { for: "run-select", children: "Run" }), _jsxs("select", { id: "run-select", value: runId, onChange: (e) => onRunChange(e.target.value), children: [_jsx("option", { value: "live", children: "Live (current run)" }), runs.map((r) => (_jsxs("option", { value: r.id, children: [new Date(r.mtime).toLocaleString(), " \u2014 ", r.id] }, r.id)))] }), _jsx("span", { class: 'conn ' + connection, title: connection })] }), _jsxs("div", { class: "status-bar", children: [_jsxs("span", { children: ["scenes ", completed, "/", summary.scenes || scenes.length] }), _jsxs("span", { class: "ok", children: ["\u2713 ", a.passed] }), _jsxs("span", { class: "fail", children: ["\u2717 ", a.failed] })] })] }));
78
+ }
79
+ // ── Tree (scenes grouped by file) ─────────────────────────────────
80
+ function Tree({ scenes, selected, onSelect, }) {
81
+ const byFile = useMemo(() => {
82
+ const m = new Map();
83
+ for (const s of scenes) {
84
+ const f = s.file || '(no file)';
85
+ if (!m.has(f))
86
+ m.set(f, []);
87
+ m.get(f).push(s);
88
+ }
89
+ return m;
90
+ }, [scenes]);
91
+ return (_jsx("aside", { class: "tree", children: [...byFile.entries()].map(([file, group]) => {
92
+ const fails = group.filter((s) => s.status !== 'completed' && s.status !== 'running').length;
93
+ return (_jsxs("div", { children: [_jsxs("div", { class: "tree-file", title: file, children: [_jsx("span", { children: shortFile(file) }), fails ? _jsx("span", { class: "fail", children: fails }) : null] }), group.map((s) => (_jsx("div", { class: 'tree-scene ' + s.status + (s.id === selected ? ' selected' : ''), onClick: () => onSelect(s.id), children: s.name }, s.id)))] }, file));
94
+ }) }));
95
+ }
96
+ // ── List pane (filters + grouped list) ────────────────────────────
97
+ function ListPane({ scenes, filters, onFilters, selected, onSelect, runId, }) {
98
+ const filtered = useMemo(() => {
99
+ const text = filters.text.toLowerCase();
100
+ return scenes.filter((s) => {
101
+ if (!filters.statuses.has(s.status))
102
+ return false;
103
+ if (!text)
104
+ return true;
105
+ const hay = [s.name, s.file, ...s.assertions.map((a) => a.description), s.error || ''].join(' ').toLowerCase();
106
+ return hay.includes(text);
107
+ });
108
+ }, [scenes, filters]);
109
+ const groups = useMemo(() => groupScenes(filtered, filters.groupBy), [filtered, filters.groupBy]);
110
+ const toggleStatus = useCallback((s) => {
111
+ const next = new Set(filters.statuses);
112
+ next.has(s) ? next.delete(s) : next.add(s);
113
+ onFilters({ ...filters, statuses: next });
114
+ }, [filters, onFilters]);
115
+ return (_jsxs("section", { class: "list-pane", children: [_jsxs("div", { class: "filters", children: [_jsx("input", { type: "search", placeholder: "Filter by scene, file, or assertion\u2026", value: filters.text, onInput: (e) => onFilters({ ...filters, text: e.target.value }) }), _jsx("div", { class: "chips", children: STATUSES.map((s) => (_jsx("button", { class: 'chip' + (filters.statuses.has(s) ? ' on' : ''), "data-status": s, onClick: () => toggleStatus(s), children: s[0].toUpperCase() + s.slice(1) }, s))) }), _jsxs("select", { class: "group-by", value: filters.groupBy, onChange: (e) => onFilters({ ...filters, groupBy: e.target.value }), children: [_jsx("option", { value: "none", children: "No grouping" }), _jsx("option", { value: "file", children: "Group by file" }), _jsx("option", { value: "status", children: "Group by status" }), _jsx("option", { value: "team", children: "Group by team" })] }), _jsx(CopyButton, { label: "Copy all failures", getText: () => formatFailureReport(scenes, runId) }), _jsx(CopyButton, { label: "Copy all", subtle: true, getText: () => formatReport(scenes, runId) })] }), _jsx("div", { class: "list", children: groups.length === 0 ? (_jsx("div", { class: "group-header", children: "No scenes match the current filters." })) : (groups.map((g) => (_jsxs("div", { children: [filters.groupBy !== 'none' ? (_jsxs("div", { class: "group-header", children: [g.key || '', " \u00B7 ", g.items.length] })) : null, g.items.map((s) => (_jsxs("div", { class: 'row' + (s.id === selected ? ' selected' : ''), onClick: () => onSelect(s.id), children: [_jsx("span", { class: 'icon ' + s.status, children: statusIcon(s.status) }), _jsx("span", { class: "name", children: s.name }), _jsx("span", { class: "row-team", title: "Team running this scene", children: teamLabel(s) }), _jsxs("span", { class: "meta", children: [s.assertions.filter((a) => !a.result).length > 0 ? _jsx("span", { class: "icon failed", children: "\u2717" }) : null, ' ', s.assertions.length, " check", s.assertions.length === 1 ? '' : 's', s.duration ? ' · ' + s.duration + 'ms' : ''] }), _jsx("span", { class: "file", children: shortFile(s.file) })] }, s.id)))] }, g.key)))) })] }));
116
+ }
117
+ function groupScenes(scenes, groupBy) {
118
+ if (groupBy === 'none')
119
+ return [{ key: '', items: scenes }];
120
+ const m = new Map();
121
+ for (const s of scenes) {
122
+ let key = '';
123
+ if (groupBy === 'file')
124
+ key = s.file || '(no file)';
125
+ else if (groupBy === 'status')
126
+ key = s.status;
127
+ else if (groupBy === 'team')
128
+ key = teamLabel(s);
129
+ if (!m.has(key))
130
+ m.set(key, []);
131
+ m.get(key).push(s);
132
+ }
133
+ const keys = [...m.keys()];
134
+ if (groupBy === 'status') {
135
+ const order = { failed: 0, timeout: 1, running: 2, completed: 3 };
136
+ keys.sort((a, b) => (order[a] ?? 99) - (order[b] ?? 99));
137
+ }
138
+ else {
139
+ keys.sort();
140
+ }
141
+ return keys.map((k) => ({ key: k, items: m.get(k) }));
142
+ }
143
+ // ── Detail pane (scene + spec snippet) ────────────────────────────
144
+ function Detail({ scene, base }) {
145
+ if (!scene) {
146
+ return (_jsx("aside", { class: "detail", children: _jsx("div", { class: "empty", children: "Select a scene on the left to see error details, timeline, and the spec snippet for reproducing it manually." }) }));
147
+ }
148
+ const failed = scene.status !== 'completed' && scene.status !== 'running';
149
+ const pills = ['team ' + teamLabel(scene), scene.duration ? scene.duration + 'ms' : '', scene.status].filter(Boolean);
150
+ const editorHref = `${base.replace(/__scenetest$/, '')}__open-in-editor?file=` +
151
+ encodeURIComponent(scene.file) +
152
+ (scene.line ? '&line=' + scene.line : '');
153
+ return (_jsxs("aside", { class: "detail", children: [_jsxs("div", { class: "actions", children: [_jsx(CopyButton, { label: "Copy", getText: () => formatScene(scene) }), scene.file ? (_jsx("a", { class: "btn subtle", href: editorHref, children: "Open in editor" })) : null] }), _jsxs("h3", { children: [failed ? _jsx("span", { class: "icon failed", children: "\u2717" }) : null, " ", scene.name] }), _jsxs("div", { class: "meta-row", children: [pills.map((t, i) => (_jsx("span", { class: "pill", children: t }, i))), scene.file ? (_jsxs("span", { class: "pill", title: scene.file, children: [shortFile(scene.file), scene.line ? ':' + scene.line : ''] })) : null] }), scene.error ? _jsx("div", { class: "err", children: scene.error }) : null, _jsx("h4", { children: "Assertions" }), _jsx("ul", { class: "alist", children: scene.assertions.length === 0 ? (_jsx("li", { children: "No assertions recorded." })) : (scene.assertions.map((a, i) => (_jsxs("li", { class: a.result ? 'pass' : 'fail', children: [a.result ? '✓' : '✗', " ", a.description] }, i)))) }), _jsx("h4", { children: "Timeline" }), _jsx("ul", { class: "timeline", children: scene.timeline.length === 0 ? (_jsx("li", { children: "(no timeline)" })) : (scene.timeline.map((t, i) => (_jsxs("li", { class: t.error ? 'err-step' : '', children: [t.actor, ": ", t.action, t.target ? ' ' + t.target : '', t.duration != null ? ' (' + t.duration + 'ms)' : '', t.error ? ' — ' + t.error : ''] }, i)))) }), _jsx("h4", { children: "Spec snippet" }), _jsx(SpecSnippet, { file: scene.file, line: scene.line, base: base })] }));
154
+ }
155
+ function SpecSnippet({ file, line, base }) {
156
+ const [state, setState] = useState({ status: 'idle' });
157
+ useEffect(() => {
158
+ if (!file) {
159
+ setState({ status: 'no-file' });
160
+ return;
161
+ }
162
+ const ctrl = new AbortController();
163
+ setState({ status: 'loading' });
164
+ const url = `${base}/source?file=` + encodeURIComponent(file) + '&line=' + (line || 1) + '&context=20';
165
+ fetch(url, { signal: ctrl.signal })
166
+ .then(async (r) => {
167
+ if (r.ok)
168
+ return { status: 'loaded', data: await r.json() };
169
+ return { status: 'missing', code: r.status };
170
+ })
171
+ .then((next) => setState(next))
172
+ .catch((err) => {
173
+ if (err.name !== 'AbortError')
174
+ setState({ status: 'error' });
175
+ });
176
+ return () => ctrl.abort();
177
+ }, [file, line, base]);
178
+ if (state.status === 'no-file')
179
+ return _jsx("div", { class: "empty", children: "No source file recorded." });
180
+ if (state.status === 'loading')
181
+ return _jsx("div", { class: "empty", children: "Loading\u2026" });
182
+ if (state.status === 'missing')
183
+ return _jsxs("div", { class: "empty", children: ["Source not available (", state.code, ")."] });
184
+ if (state.status === 'error')
185
+ return _jsx("div", { class: "empty", children: "Could not load source." });
186
+ if (state.status !== 'loaded')
187
+ return null;
188
+ const { start, lines } = state.data;
189
+ const target = line || start;
190
+ return (_jsx("pre", { class: "snippet", children: lines.map((ln, i) => {
191
+ const n = start + i;
192
+ return (_jsxs("div", { class: 'row-line' + (n === target ? ' hl' : ''), children: [_jsx("span", { class: "ln", children: n }), ln] }, n));
193
+ }) }));
194
+ }
195
+ // ── Copy button ───────────────────────────────────────────────────
196
+ function CopyButton({ label, getText, subtle }) {
197
+ const [copied, setCopied] = useState(false);
198
+ const tRef = useRef(null);
199
+ useEffect(() => () => {
200
+ if (tRef.current)
201
+ clearTimeout(tRef.current);
202
+ }, []);
203
+ const onClick = () => {
204
+ navigator.clipboard.writeText(getText()).then(() => {
205
+ setCopied(true);
206
+ tRef.current = setTimeout(() => setCopied(false), 1500);
207
+ });
208
+ };
209
+ const cls = 'btn' + (subtle ? ' subtle' : '') + (copied ? ' copied' : '');
210
+ return (_jsx("button", { class: cls, onClick: onClick, children: copied ? 'Copied!' : label }));
211
+ }
212
+ // ── Plain-text formatters (clipboard payload) ─────────────────────
213
+ function formatScene(s) {
214
+ const status = s.status === 'completed' ? 'PASSED' : s.status === 'timeout' ? 'TIMEOUT' : s.status === 'running' ? 'RUNNING' : 'FAILED';
215
+ const lines = [];
216
+ lines.push(statusIcon(s.status) + ' ' + s.name + ' — ' + status);
217
+ lines.push(' File: ' + s.file + (s.line ? ':' + s.line : ''));
218
+ lines.push(' Team: ' + teamLabel(s) + (s.duration ? ' · ' + s.duration + 'ms' : ''));
219
+ if (s.error)
220
+ lines.push(' Error: ' + s.error);
221
+ if (s.assertions.length) {
222
+ lines.push(' Assertions:');
223
+ for (const a of s.assertions)
224
+ lines.push(' ' + (a.result ? '✓' : '✗') + ' ' + a.description);
225
+ }
226
+ if (s.timeline.length) {
227
+ lines.push(' Timeline:');
228
+ for (const t of s.timeline) {
229
+ lines.push(' ' +
230
+ t.actor +
231
+ ': ' +
232
+ t.action +
233
+ (t.target ? ' ' + t.target : '') +
234
+ (t.duration != null ? ' (' + t.duration + 'ms)' : '') +
235
+ (t.error ? ' — ' + t.error : ''));
236
+ }
237
+ }
238
+ return lines.join('\n');
239
+ }
240
+ function formatReport(scenes, runId) {
241
+ const failures = scenes.filter((s) => s.status !== 'completed' && s.status !== 'running');
242
+ const header = ['Scenetest — ' + (runId || 'live'), failures.length + ' failing scene(s)', ''];
243
+ return header.join('\n') + '\n' + scenes.map((s) => formatScene(s)).join('\n\n');
244
+ }
245
+ function formatFailureReport(scenes, runId) {
246
+ const failures = scenes.filter((s) => s.status !== 'completed' && s.status !== 'running');
247
+ return formatReport(failures.length ? failures : scenes, runId);
248
+ }
249
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAChF,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,cAAc,GAGf,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAIhD,MAAM,QAAQ,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,CAAU,CAAA;AAavE,qEAAqE;AACrE,SAAS,SAAS,CAAC,CAAS;IAC1B,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAA;IACjB,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC9C,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAChE,CAAC;AAED,SAAS,UAAU,CAAC,CAAS;IAC3B,OAAO,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAA;AACtF,CAAC;AAED,SAAS,SAAS,CAAC,CAAc;IAC/B,OAAO,CAAC,CAAC,IAAI,EAAE,IAAI,IAAI,OAAO,GAAG,CAAC,CAAC,SAAS,CAAA;AAC9C,CAAC;AAED,sEAAsE;AACtE,SAAS,SAAS,CAChB,WAAiC,EACjC,cAAgC,EAChC,KAAa,EACb,IAAY;IAEZ,4EAA4E;IAC5E,4EAA4E;IAC5E,oEAAoE;IACpE,MAAM,KAAK,GAAG,WAAW,CAAC,WAAW,CAAC,CAAA;IACtC,MAAM,IAAI,GAAG,OAAO,CAClB,GAAG,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,EAC3B,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,OAAO,CAAC,CACxE,CAAA;IAED,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAiB,cAAc,CAAC,CAAA;IAChE,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,KAAK,KAAK,MAAM;YAAE,OAAM;QAC5B,OAAO,CAAC,cAAc,CAAC,CAAA;QACvB,IAAI,KAAK,GAAG,IAAI,CAAA;QAChB,KAAK,CAAC,GAAG,IAAI,SAAS,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;aAC/C,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;aACrC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;YACb,IAAI,KAAK,IAAI,IAAI;gBAAE,OAAO,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAA;QACvD,CAAC,CAAC;aACD,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QAClB,OAAO,GAAG,EAAE;YACV,KAAK,GAAG,KAAK,CAAA;QACf,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAA;IAEjB,IAAI,KAAK,KAAK,MAAM;QAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,cAAc,EAAE,CAAA;IACvE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,CAAA;AAC3C,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,UAAU,CAAC,EACzB,WAAW,EACX,UAAU,EAAE,cAAc,EAC1B,IAAI,GAKL;IACC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,CAAA;IACnG,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAY,EAAE,CAAC,CAAA;IAC/C,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAU,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,GAAG,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAA;IAC7G,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAA;IAC7D,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,SAAS,CAAC,WAAW,EAAE,cAAc,EAAE,KAAK,EAAE,IAAI,CAAC,CAAA;IAEhF,SAAS,CAAC,GAAG,EAAE;QACb,KAAK,CAAC,GAAG,IAAI,OAAO,CAAC;aAClB,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;aACrC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;YACb,IAAI,IAAI;gBAAE,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAA;QACpC,CAAC,CAAC;aACD,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;IACpB,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;IAEV,gEAAgE;IAChE,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,CAAC,GAAG,IAAI,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;QAC9C,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;QACnB,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,GAAG,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAA;QACtE,WAAW,CAAC,IAAI,CAAC,CAAA;IACnB,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAA;IAEX,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAA;IAExD,OAAO,CACL,eAAK,KAAK,EAAC,QAAQ,aACjB,KAAC,YAAY,IACX,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,KAAK,EACZ,WAAW,EAAE,QAAQ,EACrB,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,IAAI,CAAC,OAAO,EACrB,MAAM,EAAE,IAAI,CAAC,MAAM,GACnB,EACF,2BACE,KAAC,IAAI,IAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,GAAI,EACxE,KAAC,QAAQ,IACP,MAAM,EAAE,IAAI,CAAC,MAAM,EACnB,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,UAAU,EACrB,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,WAAW,EACrB,KAAK,EAAE,KAAK,GACZ,EACF,KAAC,MAAM,IAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,GAAI,IAC/B,IACH,CACP,CAAA;AACH,CAAC;AAED,qEAAqE;AACrE,SAAS,YAAY,CAAC,EACpB,IAAI,EACJ,KAAK,EACL,WAAW,EACX,UAAU,EACV,OAAO,EACP,MAAM,GAQP;IACC,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,MAAM,CAAA;IACvE,MAAM,CAAC,GAAG,OAAO,CAAC,UAAU,CAAA;IAC5B,OAAO,CACL,eAAK,KAAK,EAAC,YAAY,aACrB,eAAK,KAAK,EAAC,YAAY,aACrB,gBAAO,GAAG,EAAC,YAAY,oBAAY,EACnC,kBAAQ,EAAE,EAAC,YAAY,EAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAE,CAAC,CAAC,MAA4B,CAAC,KAAK,CAAC,aACvG,iBAAQ,KAAK,EAAC,MAAM,mCAA4B,EAC/C,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CACf,kBAAmB,KAAK,EAAE,CAAC,CAAC,EAAE,aAC3B,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,cAAc,EAAE,cAAK,CAAC,CAAC,EAAE,KADjC,CAAC,CAAC,EAAE,CAER,CACV,CAAC,IACK,EACT,eAAM,KAAK,EAAE,OAAO,GAAG,UAAU,EAAE,KAAK,EAAE,UAAU,GAAS,IACzD,EACN,eAAK,KAAK,EAAC,YAAY,aACrB,sCACU,SAAS,OAAG,OAAO,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,IAC9C,EACP,gBAAM,KAAK,EAAC,IAAI,wBAAI,CAAC,CAAC,MAAM,IAAQ,EACpC,gBAAM,KAAK,EAAC,MAAM,wBAAI,CAAC,CAAC,MAAM,IAAQ,IAClC,IACF,CACP,CAAA;AACH,CAAC;AAED,qEAAqE;AACrE,SAAS,IAAI,CAAC,EACZ,MAAM,EACN,QAAQ,EACR,QAAQ,GAKT;IACC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE;QAC1B,MAAM,CAAC,GAAG,IAAI,GAAG,EAAyB,CAAA;QAC1C,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;YACvB,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,WAAW,CAAA;YAC/B,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;YAC3B,CAAC,CAAC,GAAG,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACnB,CAAC;QACD,OAAO,CAAC,CAAA;IACV,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA;IAEZ,OAAO,CACL,gBAAO,KAAK,EAAC,MAAM,YAChB,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE;YAC3C,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,MAAM,CAAA;YAC5F,OAAO,CACL,0BACE,eAAK,KAAK,EAAC,WAAW,EAAC,KAAK,EAAE,IAAI,aAChC,yBAAO,SAAS,CAAC,IAAI,CAAC,GAAQ,EAC7B,KAAK,CAAC,CAAC,CAAC,eAAM,KAAK,EAAC,MAAM,YAAE,KAAK,GAAQ,CAAC,CAAC,CAAC,IAAI,IAC7C,EACL,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAChB,cAEE,KAAK,EAAE,aAAa,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EACxE,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,YAE5B,CAAC,CAAC,IAAI,IAJF,CAAC,CAAC,EAAE,CAKL,CACP,CAAC,KAbM,IAAI,CAcR,CACP,CAAA;QACH,CAAC,CAAC,GACI,CACT,CAAA;AACH,CAAC;AAED,qEAAqE;AACrE,SAAS,QAAQ,CAAC,EAChB,MAAM,EACN,OAAO,EACP,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,KAAK,GAQN;IACC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,EAAE;QAC5B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,CAAA;QACvC,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;YACzB,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;gBAAE,OAAO,KAAK,CAAA;YACjD,IAAI,CAAC,IAAI;gBAAE,OAAO,IAAI,CAAA;YACtB,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAA;YAC9G,OAAO,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;QAC3B,CAAC,CAAC,CAAA;IACJ,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;IAErB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAA;IAEjG,MAAM,YAAY,GAAG,WAAW,CAC9B,CAAC,CAAS,EAAE,EAAE;QACZ,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QACtC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;QAC1C,SAAS,CAAC,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;IAC3C,CAAC,EACD,CAAC,OAAO,EAAE,SAAS,CAAC,CACrB,CAAA;IAED,OAAO,CACL,mBAAS,KAAK,EAAC,WAAW,aACxB,eAAK,KAAK,EAAC,SAAS,aAClB,gBACE,IAAI,EAAC,QAAQ,EACb,WAAW,EAAC,2CAAsC,EAClD,KAAK,EAAE,OAAO,CAAC,IAAI,EACnB,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,GAAG,OAAO,EAAE,IAAI,EAAG,CAAC,CAAC,MAA2B,CAAC,KAAK,EAAE,CAAC,GACrF,EACF,cAAK,KAAK,EAAC,OAAO,YACf,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CACnB,iBAEE,KAAK,EAAE,MAAM,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,iBACzC,CAAC,EACd,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,YAE7B,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAL3B,CAAC,CAMC,CACV,CAAC,GACE,EACN,kBACE,KAAK,EAAC,UAAU,EAChB,KAAK,EAAE,OAAO,CAAC,OAAO,EACtB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,GAAG,OAAO,EAAE,OAAO,EAAG,CAAC,CAAC,MAA4B,CAAC,KAAgB,EAAE,CAAC,aAErG,iBAAQ,KAAK,EAAC,MAAM,4BAAqB,EACzC,iBAAQ,KAAK,EAAC,MAAM,8BAAuB,EAC3C,iBAAQ,KAAK,EAAC,QAAQ,gCAAyB,EAC/C,iBAAQ,KAAK,EAAC,MAAM,8BAAuB,IACpC,EACT,KAAC,UAAU,IAAC,KAAK,EAAC,mBAAmB,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,mBAAmB,CAAC,MAAM,EAAE,KAAK,CAAC,GAAI,EAC3F,KAAC,UAAU,IAAC,KAAK,EAAC,UAAU,EAAC,MAAM,QAAC,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC,GAAI,IAC9E,EACN,cAAK,KAAK,EAAC,MAAM,YACd,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CACrB,cAAK,KAAK,EAAC,cAAc,qDAA2C,CACrE,CAAC,CAAC,CAAC,CACF,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAChB,0BACG,OAAO,CAAC,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC,CAC5B,eAAK,KAAK,EAAC,cAAc,aACtB,CAAC,CAAC,GAAG,IAAI,EAAE,cAAK,CAAC,CAAC,KAAK,CAAC,MAAM,IAC3B,CACP,CAAC,CAAC,CAAC,IAAI,EACP,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAClB,eAAgB,KAAK,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,aAClG,eAAM,KAAK,EAAE,OAAO,GAAG,CAAC,CAAC,MAAM,YAAG,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,GAAQ,EAC9D,eAAM,KAAK,EAAC,MAAM,YAAE,CAAC,CAAC,IAAI,GAAQ,EAClC,eAAM,KAAK,EAAC,UAAU,EAAC,KAAK,EAAC,yBAAyB,YACnD,SAAS,CAAC,CAAC,CAAC,GACR,EACP,gBAAM,KAAK,EAAC,MAAM,aACf,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,eAAM,KAAK,EAAC,aAAa,uBAAS,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,EACjG,CAAC,CAAC,UAAU,CAAC,MAAM,YAAQ,CAAC,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAC/D,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,IACvC,EACP,eAAM,KAAK,EAAC,MAAM,YAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAQ,KAXrC,CAAC,CAAC,EAAE,CAYR,CACP,CAAC,KApBM,CAAC,CAAC,GAAG,CAqBT,CACP,CAAC,CACH,GACG,IACE,CACX,CAAA;AACH,CAAC;AAED,SAAS,WAAW,CAAC,MAAqB,EAAE,OAAgB;IAC1D,IAAI,OAAO,KAAK,MAAM;QAAE,OAAO,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;IAC3D,MAAM,CAAC,GAAG,IAAI,GAAG,EAAyB,CAAA;IAC1C,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,GAAG,GAAG,EAAE,CAAA;QACZ,IAAI,OAAO,KAAK,MAAM;YAAE,GAAG,GAAG,CAAC,CAAC,IAAI,IAAI,WAAW,CAAA;aAC9C,IAAI,OAAO,KAAK,QAAQ;YAAE,GAAG,GAAG,CAAC,CAAC,MAAM,CAAA;aACxC,IAAI,OAAO,KAAK,MAAM;YAAE,GAAG,GAAG,SAAS,CAAC,CAAC,CAAC,CAAA;QAC/C,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;QAC/B,CAAC,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACrB,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;IAC1B,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;QACzB,MAAM,KAAK,GAA2B,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAA;QACzF,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;IAC1D,CAAC;SAAM,CAAC;QACN,IAAI,CAAC,IAAI,EAAE,CAAA;IACb,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAE,EAAE,CAAC,CAAC,CAAA;AACxD,CAAC;AAED,qEAAqE;AACrE,SAAS,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,EAAoD;IAC/E,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CACL,gBAAO,KAAK,EAAC,QAAQ,YACnB,cAAK,KAAK,EAAC,OAAO,6HAEZ,GACA,CACT,CAAA;IACH,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,KAAK,WAAW,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,CAAA;IACzE,MAAM,KAAK,GAAG,CAAC,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IACrH,MAAM,UAAU,GACd,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,wBAAwB;QAC3D,kBAAkB,CAAC,KAAK,CAAC,IAAI,CAAC;QAC9B,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;IAE3C,OAAO,CACL,iBAAO,KAAK,EAAC,QAAQ,aACnB,eAAK,KAAK,EAAC,SAAS,aAClB,KAAC,UAAU,IAAC,KAAK,EAAC,MAAM,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,GAAI,EAC7D,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CACZ,YAAG,KAAK,EAAC,YAAY,EAAC,IAAI,EAAE,UAAU,+BAElC,CACL,CAAC,CAAC,CAAC,IAAI,IACJ,EACN,yBACG,MAAM,CAAC,CAAC,CAAC,eAAM,KAAK,EAAC,aAAa,uBAAS,CAAC,CAAC,CAAC,IAAI,OAAG,KAAK,CAAC,IAAI,IAC7D,EACL,eAAK,KAAK,EAAC,UAAU,aAClB,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CACnB,eAAM,KAAK,EAAC,MAAM,YACf,CAAC,IADoB,CAAC,CAElB,CACR,CAAC,EACD,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CACZ,gBAAM,KAAK,EAAC,MAAM,EAAC,KAAK,EAAE,KAAK,CAAC,IAAI,aACjC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,EACrB,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAC9B,CACR,CAAC,CAAC,CAAC,IAAI,IACJ,EACL,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,cAAK,KAAK,EAAC,KAAK,YAAE,KAAK,CAAC,KAAK,GAAO,CAAC,CAAC,CAAC,IAAI,EAC1D,sCAAmB,EACnB,aAAI,KAAK,EAAC,OAAO,YACd,KAAK,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAC/B,mDAAgC,CACjC,CAAC,CAAC,CAAC,CACF,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAC7B,cAAI,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,aAClC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,OAAG,CAAC,CAAC,WAAW,KADK,CAAC,CAExC,CACN,CAAC,CACH,GACE,EACL,oCAAiB,EACjB,aAAI,KAAK,EAAC,UAAU,YACjB,KAAK,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAC7B,yCAAsB,CACvB,CAAC,CAAC,CAAC,CACF,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAC3B,cAAI,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,aACjC,CAAC,CAAC,KAAK,QAAI,CAAC,CAAC,MAAM,EACnB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAC9B,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,EACnD,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAJU,CAAC,CAKvC,CACN,CAAC,CACH,GACE,EACL,wCAAqB,EACrB,KAAC,WAAW,IAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,GAAI,IACzD,CACT,CAAA;AACH,CAAC;AAQD,SAAS,WAAW,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAiD;IACtF,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAe,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;IACpE,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,QAAQ,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAA;YAC/B,OAAM;QACR,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,eAAe,EAAE,CAAA;QAClC,QAAQ,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAA;QAC/B,MAAM,GAAG,GAAG,GAAG,IAAI,eAAe,GAAG,kBAAkB,CAAC,IAAI,CAAC,GAAG,QAAQ,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,aAAa,CAAA;QACtG,KAAK,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;aAChC,IAAI,CAAC,KAAK,EAAE,CAAC,EAAyB,EAAE;YACvC,IAAI,CAAC,CAAC,EAAE;gBAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAA;YAC3D,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAA;QAC9C,CAAC,CAAC;aACD,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;aAC9B,KAAK,CAAC,CAAC,GAAU,EAAE,EAAE;YACpB,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY;gBAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAA;QAC9D,CAAC,CAAC,CAAA;QACJ,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,CAAA;IAC3B,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAA;IAEtB,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO,cAAK,KAAK,EAAC,OAAO,yCAA+B,CAAA;IACxF,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO,cAAK,KAAK,EAAC,OAAO,8BAAe,CAAA;IACxE,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO,eAAK,KAAK,EAAC,OAAO,uCAAwB,KAAK,CAAC,IAAI,UAAS,CAAA;IACpG,IAAI,KAAK,CAAC,MAAM,KAAK,OAAO;QAAE,OAAO,cAAK,KAAK,EAAC,OAAO,uCAA6B,CAAA;IACpF,IAAI,KAAK,CAAC,MAAM,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAA;IAE1C,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC,IAAI,CAAA;IACnC,MAAM,MAAM,GAAG,IAAI,IAAI,KAAK,CAAA;IAC5B,OAAO,CACL,cAAK,KAAK,EAAC,SAAS,YACjB,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE;YACnB,MAAM,CAAC,GAAG,KAAK,GAAG,CAAC,CAAA;YACnB,OAAO,CACL,eAAK,KAAK,EAAE,UAAU,GAAG,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,aAClD,eAAM,KAAK,EAAC,IAAI,YAAE,CAAC,GAAQ,EAC1B,EAAE,KAFsD,CAAC,CAGtD,CACP,CAAA;QACH,CAAC,CAAC,GACE,CACP,CAAA;AACH,CAAC;AAED,qEAAqE;AACrE,SAAS,UAAU,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAA8D;IACxG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC3C,MAAM,IAAI,GAAG,MAAM,CAAuC,IAAI,CAAC,CAAA;IAC/D,SAAS,CACP,GAAG,EAAE,CAAC,GAAG,EAAE;QACT,IAAI,IAAI,CAAC,OAAO;YAAE,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAC9C,CAAC,EACD,EAAE,CACH,CAAA;IACD,MAAM,OAAO,GAAG,GAAG,EAAE;QACnB,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;YACjD,SAAS,CAAC,IAAI,CAAC,CAAA;YACf,IAAI,CAAC,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAA;QACzD,CAAC,CAAC,CAAA;IACJ,CAAC,CAAA;IACD,MAAM,GAAG,GAAG,KAAK,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;IACzE,OAAO,CACL,iBAAQ,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,YACjC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,GACpB,CACV,CAAA;AACH,CAAC;AAED,qEAAqE;AACrE,SAAS,WAAW,CAAC,CAAc;IACjC,MAAM,MAAM,GACV,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAA;IAC1H,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,IAAI,GAAG,KAAK,GAAG,MAAM,CAAC,CAAA;IAChE,KAAK,CAAC,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAC9D,KAAK,CAAC,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IACrF,IAAI,CAAC,CAAC,KAAK;QAAE,KAAK,CAAC,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,CAAA;IAC9C,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;QAC3B,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,UAAU;YAAE,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,WAAW,CAAC,CAAA;IACjG,CAAC;IACD,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;QACtB,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;QACzB,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;YAC3B,KAAK,CAAC,IAAI,CACR,MAAM;gBACJ,CAAC,CAAC,KAAK;gBACP,IAAI;gBACJ,CAAC,CAAC,MAAM;gBACR,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;gBAChC,CAAC,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;gBACrD,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CACnC,CAAA;QACH,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC;AAED,SAAS,YAAY,CAAC,MAAqB,EAAE,KAAa;IACxD,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAA;IACzF,MAAM,MAAM,GAAG,CAAC,cAAc,GAAG,CAAC,KAAK,IAAI,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,GAAG,mBAAmB,EAAE,EAAE,CAAC,CAAA;IAC9F,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;AAClF,CAAC;AAED,SAAS,mBAAmB,CAAC,MAAqB,EAAE,KAAa;IAC/D,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAA;IACzF,OAAO,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;AACjE,CAAC"}
@@ -0,0 +1,50 @@
1
+ import type { SceneRow, AssertionRecord, ActionRecord, RunRow } from './collections/projections.js';
2
+ import type { ObservableRows } from './use-live-query.js';
3
+ /**
4
+ * The read model's collections, created once at the Dashboard root and passed
5
+ * to every view. Each view reads the tables it needs reactively with
6
+ * `useLiveQuery`, then selects (`selectWaterfall`, `selectSnapshot`). Typed
7
+ * structurally ({@link ObservableRows}) so the concrete `@tanstack/db`
8
+ * `Collection`s satisfy it without leaking their generics.
9
+ */
10
+ export interface DashboardCollections {
11
+ scenes: ObservableRows<SceneRow>;
12
+ assertions: ObservableRows<AssertionRecord>;
13
+ actions: ObservableRows<ActionRecord>;
14
+ runs: ObservableRows<RunRow>;
15
+ }
16
+ /**
17
+ * The read model is multi-run — the collections accumulate every run of the
18
+ * session — so the live views (Waterfall, Runner) render the **latest** run:
19
+ * the `where runId = latest` slice. `RunSlice` is that slice, shared by both
20
+ * selectors so they agree on the "current run". Built incrementally by
21
+ * `useRunSlice` (live), or by `latestRunSlice` (the pure reference, for tests).
22
+ */
23
+ export interface RunSlice {
24
+ runId: string | undefined;
25
+ run: RunRow | undefined;
26
+ scenes: SceneRow[];
27
+ assertions: AssertionRecord[];
28
+ actions: ActionRecord[];
29
+ }
30
+ /**
31
+ * The latest run's id — the newest `run:start` (max `startTime`). Falls back to
32
+ * the most-recent scene's `runId` only when no run row exists yet (a window that
33
+ * doesn't occur in practice, since `run:start` precedes the first scene).
34
+ */
35
+ export declare function latestRunId(runs: RunRow[], scenes?: SceneRow[]): string | undefined;
36
+ /**
37
+ * Bucket assertion/action rows by the scene they attribute to, in **one pass**
38
+ * over the rows. Both selectors then read each scene's rows by id instead of
39
+ * re-filtering the whole list per scene through `attributeToScene` (which itself
40
+ * scans the scenes) — turning the O(scenes² × rows) per-scene filter into one
41
+ * O(rows × scenes) pass. Rows that attribute to no scene are dropped.
42
+ */
43
+ export declare function groupByScene<T extends {
44
+ sceneId: string | null;
45
+ runId: string;
46
+ actor: string | null;
47
+ timestamp: number;
48
+ }>(rows: T[], scenes: SceneRow[]): Map<string, T[]>;
49
+ export declare function latestRunSlice(scenes: SceneRow[], assertions: AssertionRecord[], actions: ActionRecord[], runs: RunRow[]): RunSlice;
50
+ //# sourceMappingURL=select-helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select-helpers.d.ts","sourceRoot":"","sources":["../src/select-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAA;AAEnG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAEzD;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAA;IAChC,UAAU,EAAE,cAAc,CAAC,eAAe,CAAC,CAAA;IAC3C,OAAO,EAAE,cAAc,CAAC,YAAY,CAAC,CAAA;IACrC,IAAI,EAAE,cAAc,CAAC,MAAM,CAAC,CAAA;CAC7B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;IACzB,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;IACvB,MAAM,EAAE,QAAQ,EAAE,CAAA;IAClB,UAAU,EAAE,eAAe,EAAE,CAAA;IAC7B,OAAO,EAAE,YAAY,EAAE,CAAA;CACxB;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,MAAM,GAAE,QAAQ,EAAO,GAAG,MAAM,GAAG,SAAS,CAKvF;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS;IAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,EACvH,IAAI,EAAE,CAAC,EAAE,EACT,MAAM,EAAE,QAAQ,EAAE,GACjB,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAUlB;AAED,wBAAgB,cAAc,CAC5B,MAAM,EAAE,QAAQ,EAAE,EAClB,UAAU,EAAE,eAAe,EAAE,EAC7B,OAAO,EAAE,YAAY,EAAE,EACvB,IAAI,EAAE,MAAM,EAAE,GACb,QAAQ,CAWV"}