@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
package/dist/types.d.ts CHANGED
@@ -15,16 +15,12 @@ export type ConnectionStatus = 'connecting' | 'connected' | 'disconnected';
15
15
  */
16
16
  export interface Transport {
17
17
  /**
18
- * A snapshot of the run so far, as an ordered list of protocol events the
19
- * widget folds into its initial state. Transports that deliver history
20
- * through the initial `subscribe` burst instead (e.g. SSE replay) may
21
- * return an empty array the store folds both the same way.
22
- */
23
- fetchState(): Promise<RunEvent[]>;
24
- /**
25
- * Subscribe to live events. `onEvent` receives every event after the
26
- * snapshot; `onStatus`, if given, receives connection-liveness changes.
27
- * Returns an unsubscribe function that tears down the underlying stream.
18
+ * Subscribe to the run stream. The transport replays the run history so far
19
+ * (SSE replays the buffer on connect; the cloud WebSocket replays from a
20
+ * `sinceSeq`) and then delivers live events through the same `onEvent`, so
21
+ * the read model folds history and live the same way. `onStatus`, if given,
22
+ * receives connection-liveness changes. Returns an unsubscribe function that
23
+ * tears down the underlying stream.
28
24
  */
29
25
  subscribe(onEvent: (event: RunEvent) => void, onStatus?: (status: ConnectionStatus) => void): () => void;
30
26
  /** Send a command toward the runner (replay, stop, pause, resume). */
@@ -99,14 +95,4 @@ export interface DashboardTheme {
99
95
  /** Base font size (e.g. `'13px'`). */
100
96
  fontSize?: string;
101
97
  }
102
- export interface MountOptions {
103
- transport: Transport;
104
- /** Optional theme overrides applied as `--st-*` custom properties. */
105
- theme?: DashboardTheme;
106
- }
107
- /** Handle returned by `mountDashboard`. */
108
- export interface DashboardHandle {
109
- /** Tear down the widget, its subscription, and its shadow root contents. */
110
- unmount(): void;
111
- }
112
98
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAEtE;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,YAAY,GAAG,WAAW,GAAG,cAAc,CAAA;AAE1E;;;;;;;GAOG;AACH,MAAM,WAAW,SAAS;IACxB;;;;;;;OAOG;IACH,SAAS,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,GAAG,MAAM,IAAI,CAAA;IAExG,sEAAsE;IACtE,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC7C;AAED,+CAA+C;AAC/C,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAA;CACjD;AAED,kDAAkD;AAClD,MAAM,WAAW,IAAI;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,UAAU,EAAE,CAAA;CACpB;AAED,0DAA0D;AAC1D,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,OAAO,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,gDAAgD;AAChD,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,KAAK,EAAE,IAAI,EAAE,CAAA;IACb,UAAU,EAAE,YAAY,EAAE,CAAA;IAC1B,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAA;IAC/D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,QAAQ,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,4EAA4E;AAC5E,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,KAAK,EAAE,CAAA;IACf,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,wEAAwE;IACxE,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,OAAO,EAAE,OAAO,CAAA;IAChB,4DAA4D;IAC5D,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,iEAAiE;IACjE,QAAQ,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IAC1D,UAAU,EAAE,gBAAgB,CAAA;CAC7B;AAED,kFAAkF;AAClF,MAAM,WAAW,cAAc;IAC7B,uCAAuC;IACvC,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,gCAAgC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,sCAAsC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * The minimal shape this hook needs from a TanStack DB collection: read its
3
+ * rows and subscribe to changes. Both base collections (`createCollection`) and
4
+ * derived ones (`createLiveQueryCollection`) satisfy it, so a view can read a
5
+ * raw table or a `.where(...).orderBy(...)` query through the same hook.
6
+ */
7
+ export interface ObservableRows<T> {
8
+ readonly toArray: T[];
9
+ subscribeChanges(callback: (changes: unknown) => void): {
10
+ unsubscribe: () => void;
11
+ };
12
+ }
13
+ /**
14
+ * Read a TanStack DB collection reactively: subscribe to its changes, re-render
15
+ * on each, and return the current rows. This is the Preact analogue of
16
+ * `@tanstack/react-db`'s `useLiveQuery` — the pattern to reach for, rather than
17
+ * a hand-rolled `subscribeChanges` + force-update in every component. Pass a
18
+ * stable collection (created once, e.g. via `useMemo` or at the app root); a
19
+ * fresh collection each render would resubscribe every time.
20
+ *
21
+ * The returned array keeps a **stable identity between changes** (`collection.toArray`
22
+ * builds a fresh array on every access, so we snapshot it only when a change
23
+ * actually fires). That's what lets downstream `useMemo`s over these rows
24
+ * (`selectSnapshot`, the Runner's filter/group memos) hit instead of recomputing
25
+ * every render.
26
+ */
27
+ export declare function useLiveQuery<T>(collection: ObservableRows<T>): T[];
28
+ //# sourceMappingURL=use-live-query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-live-query.d.ts","sourceRoot":"","sources":["../src/use-live-query.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,CAAC,EAAE,CAAA;IACrB,gBAAgB,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG;QAAE,WAAW,EAAE,MAAM,IAAI,CAAA;KAAE,CAAA;CACpF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,UAAU,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAQlE"}
@@ -0,0 +1,25 @@
1
+ import { useEffect, useState } from 'preact/hooks';
2
+ /**
3
+ * Read a TanStack DB collection reactively: subscribe to its changes, re-render
4
+ * on each, and return the current rows. This is the Preact analogue of
5
+ * `@tanstack/react-db`'s `useLiveQuery` — the pattern to reach for, rather than
6
+ * a hand-rolled `subscribeChanges` + force-update in every component. Pass a
7
+ * stable collection (created once, e.g. via `useMemo` or at the app root); a
8
+ * fresh collection each render would resubscribe every time.
9
+ *
10
+ * The returned array keeps a **stable identity between changes** (`collection.toArray`
11
+ * builds a fresh array on every access, so we snapshot it only when a change
12
+ * actually fires). That's what lets downstream `useMemo`s over these rows
13
+ * (`selectSnapshot`, the Runner's filter/group memos) hit instead of recomputing
14
+ * every render.
15
+ */
16
+ export function useLiveQuery(collection) {
17
+ const [rows, setRows] = useState(() => collection.toArray);
18
+ useEffect(() => {
19
+ setRows(collection.toArray); // resync in case it changed before we subscribed
20
+ const sub = collection.subscribeChanges(() => setRows(collection.toArray));
21
+ return () => sub.unsubscribe();
22
+ }, [collection]);
23
+ return rows;
24
+ }
25
+ //# sourceMappingURL=use-live-query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-live-query.js","sourceRoot":"","sources":["../src/use-live-query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAalD;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,YAAY,CAAI,UAA6B;IAC3D,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAM,GAAG,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;IAC/D,SAAS,CAAC,GAAG,EAAE;QACb,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA,CAAC,iDAAiD;QAC7E,MAAM,GAAG,GAAG,UAAU,CAAC,gBAAgB,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAA;QAC1E,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,CAAA;IAChC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAA;IAChB,OAAO,IAAI,CAAA;AACb,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { type ObservableRows } from './use-live-query.js';
2
+ import { type DashboardCollections, type RunSlice } from './select-helpers.js';
3
+ import type { SceneRow, AssertionRecord, ActionRecord } from './collections/projections.js';
4
+ /** The live-query collections of one run's rows, the heart of {@link useRunSlice}. */
5
+ export interface RunSliceCollections {
6
+ scenes: ObservableRows<SceneRow>;
7
+ assertions: ObservableRows<AssertionRecord>;
8
+ actions: ObservableRows<ActionRecord>;
9
+ }
10
+ /**
11
+ * Build the three derived live-query collections for `runId` (`where runId = …`,
12
+ * scenes/actions `orderBy startTime`). A pure builder (no hooks) so it can be
13
+ * tested against `latestRunSlice` directly. Before the first run `runId` is
14
+ * undefined, so we filter on a sentinel that matches no real row (ids are
15
+ * timestamps) and the slice comes back empty.
16
+ */
17
+ export declare function runSliceCollections(collections: DashboardCollections, runId: string | undefined): RunSliceCollections;
18
+ /**
19
+ * The latest-run slice the live views render, maintained incrementally by
20
+ * `@tanstack/db` rather than re-scanned in JS each render. Picks the latest run
21
+ * from the small `runs` table and rebuilds the derived collections only when a
22
+ * new run starts; the views hand the result to the pure selectors.
23
+ */
24
+ export declare function useRunSlice(collections: DashboardCollections): RunSlice;
25
+ //# sourceMappingURL=use-run-slice.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-run-slice.d.ts","sourceRoot":"","sources":["../src/use-run-slice.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACvE,OAAO,EAAe,KAAK,oBAAoB,EAAE,KAAK,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAC3F,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAE3F,sFAAsF;AACtF,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAA;IAChC,UAAU,EAAE,cAAc,CAAC,eAAe,CAAC,CAAA;IAC3C,OAAO,EAAE,cAAc,CAAC,YAAY,CAAC,CAAA;CACtC;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,oBAAoB,EACjC,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB,mBAAmB,CAsBrB;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,oBAAoB,GAAG,QAAQ,CAiBvE"}
@@ -0,0 +1,48 @@
1
+ import { useMemo } from 'preact/hooks';
2
+ import { createLiveQueryCollection, eq } from '@tanstack/db';
3
+ import { useLiveQuery } from './use-live-query.js';
4
+ import { latestRunId } from './select-helpers.js';
5
+ /**
6
+ * Build the three derived live-query collections for `runId` (`where runId = …`,
7
+ * scenes/actions `orderBy startTime`). A pure builder (no hooks) so it can be
8
+ * tested against `latestRunSlice` directly. Before the first run `runId` is
9
+ * undefined, so we filter on a sentinel that matches no real row (ids are
10
+ * timestamps) and the slice comes back empty.
11
+ */
12
+ export function runSliceCollections(collections, runId) {
13
+ const key = runId ?? ' no-run';
14
+ const scenes = collections.scenes;
15
+ const assertions = collections.assertions;
16
+ const actions = collections.actions;
17
+ return {
18
+ scenes: createLiveQueryCollection((q) => q
19
+ .from({ scene: scenes })
20
+ .where(({ scene }) => eq(scene.runId, key))
21
+ .orderBy(({ scene }) => scene.startTime)),
22
+ assertions: createLiveQueryCollection((q) => q.from({ assertion: assertions }).where(({ assertion }) => eq(assertion.runId, key))),
23
+ actions: createLiveQueryCollection((q) => q
24
+ .from({ action: actions })
25
+ .where(({ action }) => eq(action.runId, key))
26
+ .orderBy(({ action }) => action.startTime)),
27
+ };
28
+ }
29
+ /**
30
+ * The latest-run slice the live views render, maintained incrementally by
31
+ * `@tanstack/db` rather than re-scanned in JS each render. Picks the latest run
32
+ * from the small `runs` table and rebuilds the derived collections only when a
33
+ * new run starts; the views hand the result to the pure selectors.
34
+ */
35
+ export function useRunSlice(collections) {
36
+ const runs = useLiveQuery(collections.runs);
37
+ const runId = latestRunId(runs);
38
+ const run = runId ? runs.find((r) => r.id === runId) : undefined;
39
+ // Rebuild only when a new run starts (runId changes), not on every event.
40
+ const queries = useMemo(() => runSliceCollections(collections, runId),
41
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- collections are stable; rebuild only when the run changes
42
+ [collections.scenes, collections.assertions, collections.actions, runId]);
43
+ const scenes = useLiveQuery(queries.scenes);
44
+ const assertions = useLiveQuery(queries.assertions);
45
+ const actions = useLiveQuery(queries.actions);
46
+ return { runId, run, scenes, assertions, actions };
47
+ }
48
+ //# sourceMappingURL=use-run-slice.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-run-slice.js","sourceRoot":"","sources":["../src/use-run-slice.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,yBAAyB,EAAE,EAAE,EAAmB,MAAM,cAAc,CAAA;AAC7E,OAAO,EAAE,YAAY,EAAuB,MAAM,qBAAqB,CAAA;AACvE,OAAO,EAAE,WAAW,EAA4C,MAAM,qBAAqB,CAAA;AAU3F;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CACjC,WAAiC,EACjC,KAAyB;IAEzB,MAAM,GAAG,GAAG,KAAK,IAAI,SAAS,CAAA;IAC9B,MAAM,MAAM,GAAG,WAAW,CAAC,MAAyC,CAAA;IACpE,MAAM,UAAU,GAAG,WAAW,CAAC,UAAoD,CAAA;IACnF,MAAM,OAAO,GAAG,WAAW,CAAC,OAA8C,CAAA;IAC1E,OAAO;QACL,MAAM,EAAE,yBAAyB,CAAC,CAAC,CAAC,EAAE,EAAE,CACtC,CAAC;aACE,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;aACvB,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;aAC1C,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAC3C;QACD,UAAU,EAAE,yBAAyB,CAAC,CAAC,CAAC,EAAE,EAAE,CAC1C,CAAC,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CACrF;QACD,OAAO,EAAE,yBAAyB,CAAC,CAAC,CAAC,EAAE,EAAE,CACvC,CAAC;aACE,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;aACzB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;aAC5C,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAC7C;KACF,CAAA;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,WAAiC;IAC3D,MAAM,IAAI,GAAG,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;IAC3C,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,CAAA;IAC/B,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IAEhE,0EAA0E;IAC1E,MAAM,OAAO,GAAG,OAAO,CACrB,GAAG,EAAE,CAAC,mBAAmB,CAAC,WAAW,EAAE,KAAK,CAAC;IAC7C,oHAAoH;IACpH,CAAC,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,UAAU,EAAE,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,CACzE,CAAA;IAED,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IAC3C,MAAM,UAAU,GAAG,YAAY,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;IACnD,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;IAE7C,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,CAAA;AACpD,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@scenetest/dashboard",
3
- "version": "0.11.0",
4
- "description": "Mountable Preact dashboard widget for scenetest — renders a live run into a shadow root, fed by a pluggable transport adapter",
3
+ "version": "0.12.0",
4
+ "description": "Embeddable Preact dashboard component for scenetest — Home/Runner/Waterfall views over a read-only read model, fed by a pluggable transport adapter",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -15,7 +15,7 @@
15
15
  "playwright",
16
16
  "dashboard",
17
17
  "preact",
18
- "widget"
18
+ "component"
19
19
  ],
20
20
  "main": "./dist/index.js",
21
21
  "types": "./dist/index.d.ts",
@@ -24,6 +24,11 @@
24
24
  "types": "./dist/index.d.ts",
25
25
  "import": "./dist/index.js"
26
26
  },
27
+ "./collections": {
28
+ "types": "./dist/collections/index.d.ts",
29
+ "import": "./dist/collections/index.js"
30
+ },
31
+ "./style.css": "./dist/style.css",
27
32
  "./package.json": "./package.json"
28
33
  },
29
34
  "files": [
@@ -33,7 +38,7 @@
33
38
  "access": "public"
34
39
  },
35
40
  "dependencies": {
36
- "htm": "^3.1.1",
41
+ "@tanstack/db": "^0.6.0",
37
42
  "preact": "^10.22.0",
38
43
  "@scenetest/protocol": "0.11.0"
39
44
  },
@@ -43,7 +48,7 @@
43
48
  "vitest": "^4.1.4"
44
49
  },
45
50
  "scripts": {
46
- "build": "tsc",
51
+ "build": "tsc && cp src/style.css dist/style.css",
47
52
  "typecheck": "tsc --noEmit",
48
53
  "test": "vitest run",
49
54
  "test:watch": "vitest"
package/dist/mount.d.ts DELETED
@@ -1,14 +0,0 @@
1
- import type { DashboardHandle, MountOptions } from './types.js';
2
- /**
3
- * Mount the dashboard widget into `element`. The widget renders into a shadow
4
- * root with its own styles and fonts, so it can drop into any host — the
5
- * `/__scenetest` page, a worker-served page, a docs island — without leaking
6
- * styles in either direction and without the host needing to use Preact.
7
- *
8
- * The host supplies only a transport adapter (the dev/cloud seam) and an
9
- * optional theme; everything else is internal. Returns a handle whose
10
- * `unmount()` tears down Preact, the transport subscription, and the shadow
11
- * content.
12
- */
13
- export declare function mountDashboard(element: HTMLElement, options: MountOptions): DashboardHandle;
14
- //# sourceMappingURL=mount.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../src/mount.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAkB,YAAY,EAAE,MAAM,YAAY,CAAA;AAE/E;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,GAAG,eAAe,CAqB3F"}
package/dist/mount.js DELETED
@@ -1,50 +0,0 @@
1
- import { h, render } from 'preact';
2
- import { Dashboard } from './app.js';
3
- import { STYLES } from './styles.js';
4
- /**
5
- * Mount the dashboard widget into `element`. The widget renders into a shadow
6
- * root with its own styles and fonts, so it can drop into any host — the
7
- * `/__scenetest` page, a worker-served page, a docs island — without leaking
8
- * styles in either direction and without the host needing to use Preact.
9
- *
10
- * The host supplies only a transport adapter (the dev/cloud seam) and an
11
- * optional theme; everything else is internal. Returns a handle whose
12
- * `unmount()` tears down Preact, the transport subscription, and the shadow
13
- * content.
14
- */
15
- export function mountDashboard(element, options) {
16
- const root = element.shadowRoot ?? element.attachShadow({ mode: 'open' });
17
- root.innerHTML = '';
18
- const style = document.createElement('style');
19
- style.textContent = STYLES;
20
- root.appendChild(style);
21
- if (options.theme)
22
- applyTheme(root, options.theme);
23
- const container = document.createElement('div');
24
- root.appendChild(container);
25
- render(h(Dashboard, { transport: options.transport }), container);
26
- return {
27
- unmount() {
28
- render(null, container);
29
- root.innerHTML = '';
30
- },
31
- };
32
- }
33
- /**
34
- * Apply the small `--st-*` theming surface to the shadow host. A
35
- * `:host { ... }` block can't be set imperatively, so the custom properties
36
- * are written onto the host element's inline style, where `:host` rules in the
37
- * stylesheet pick them up as overrides.
38
- */
39
- function applyTheme(root, theme) {
40
- const host = root.host;
41
- if (theme.bg)
42
- host.style.setProperty('--st-bg', theme.bg);
43
- if (theme.accent)
44
- host.style.setProperty('--st-accent', theme.accent);
45
- if (theme.font)
46
- host.style.setProperty('--st-font', theme.font);
47
- if (theme.fontSize)
48
- host.style.setProperty('--st-font-size', theme.fontSize);
49
- }
50
- //# sourceMappingURL=mount.js.map
package/dist/mount.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"mount.js","sourceRoot":"","sources":["../src/mount.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAGpC;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAAC,OAAoB,EAAE,OAAqB;IACxE,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAA;IACzE,IAAI,CAAC,SAAS,GAAG,EAAE,CAAA;IAEnB,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAA;IAC7C,KAAK,CAAC,WAAW,GAAG,MAAM,CAAA;IAC1B,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;IAEvB,IAAI,OAAO,CAAC,KAAK;QAAE,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,CAAA;IAElD,MAAM,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;IAC/C,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAA;IAE3B,MAAM,CAAC,CAAC,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,EAAE,SAAS,CAAC,CAAA;IAEjE,OAAO;QACL,OAAO;YACL,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;YACvB,IAAI,CAAC,SAAS,GAAG,EAAE,CAAA;QACrB,CAAC;KACF,CAAA;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,UAAU,CAAC,IAAgB,EAAE,KAAqB;IACzD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAmB,CAAA;IACrC,IAAI,KAAK,CAAC,EAAE;QAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,CAAA;IACzD,IAAI,KAAK,CAAC,MAAM;QAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IACrE,IAAI,KAAK,CAAC,IAAI;QAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,CAAA;IAC/D,IAAI,KAAK,CAAC,QAAQ;QAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAA;AAC9E,CAAC"}
package/dist/store.d.ts DELETED
@@ -1,19 +0,0 @@
1
- import type { RunEvent } from '@scenetest/protocol';
2
- import type { ConnectionStatus, DashboardState } from './types.js';
3
- /** The empty state, before any events. */
4
- export declare function initialState(): DashboardState;
5
- /**
6
- * Fold one protocol event into the state, returning a new state object (and
7
- * new objects for the scenes/scene that changed) so Preact re-renders. This
8
- * is the same reduction the original inline dashboard did imperatively, made
9
- * pure. Unknown event types are ignored — a newer producer can add events
10
- * without breaking an older widget.
11
- */
12
- export declare function applyEvent(state: DashboardState, event: RunEvent): DashboardState;
13
- /** Fold a snapshot of events into a fresh state, in order. */
14
- export declare function foldEvents(events: RunEvent[]): DashboardState;
15
- /** Return a new state with the connection liveness updated. */
16
- export declare function withConnection(state: DashboardState, connection: ConnectionStatus): DashboardState;
17
- /** Number of scenes that have finished (not currently running). */
18
- export declare function completedSceneCount(state: DashboardState): number;
19
- //# sourceMappingURL=store.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAe,MAAM,YAAY,CAAA;AAE/E,0CAA0C;AAC1C,wBAAgB,YAAY,IAAI,cAAc,CAa7C;AAqBD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,QAAQ,GAAG,cAAc,CA2GjF;AAYD,8DAA8D;AAC9D,wBAAgB,UAAU,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,cAAc,CAE7D;AAED,+DAA+D;AAC/D,wBAAgB,cAAc,CAAC,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,gBAAgB,GAAG,cAAc,CAElG;AAED,mEAAmE;AACnE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAEjE"}
package/dist/store.js DELETED
@@ -1,164 +0,0 @@
1
- /** The empty state, before any events. */
2
- export function initialState() {
3
- return {
4
- scenes: [],
5
- currentSceneIndex: null,
6
- runStartTime: null,
7
- passCount: 0,
8
- failCount: 0,
9
- sceneCount: 0,
10
- teams: [],
11
- running: false,
12
- endDurationMs: null,
13
- connection: 'connecting',
14
- };
15
- }
16
- function cloneScene(scene) {
17
- return {
18
- ...scene,
19
- actors: scene.actors.slice(),
20
- lanes: scene.lanes.map((lane) => ({ actor: lane.actor, items: lane.items.slice() })),
21
- assertions: scene.assertions.slice(),
22
- };
23
- }
24
- function laneFor(scene, actor) {
25
- let lane = scene.lanes.find((l) => l.actor === actor);
26
- if (!lane) {
27
- lane = { actor, items: [] };
28
- scene.lanes.push(lane);
29
- if (!scene.actors.includes(actor))
30
- scene.actors.push(actor);
31
- }
32
- return lane;
33
- }
34
- /**
35
- * Fold one protocol event into the state, returning a new state object (and
36
- * new objects for the scenes/scene that changed) so Preact re-renders. This
37
- * is the same reduction the original inline dashboard did imperatively, made
38
- * pure. Unknown event types are ignored — a newer producer can add events
39
- * without breaking an older widget.
40
- */
41
- export function applyEvent(state, event) {
42
- switch (event.type) {
43
- case 'run:start':
44
- return {
45
- ...initialState(),
46
- connection: state.connection,
47
- runStartTime: event.timestamp,
48
- sceneCount: event.sceneCount,
49
- running: true,
50
- };
51
- case 'scene:start': {
52
- const scene = {
53
- name: event.name,
54
- file: event.file,
55
- actors: (event.actors ?? []).slice(),
56
- lanes: (event.actors ?? []).map((actor) => ({ actor, items: [] })),
57
- assertions: [],
58
- startTime: event.timestamp,
59
- endTime: null,
60
- status: 'running',
61
- team: event.team ?? {},
62
- teamIndex: event.teamIndex ?? 0,
63
- };
64
- const scenes = state.scenes.concat(scene);
65
- const teamName = scene.team?.name;
66
- const teams = teamName && !state.teams.includes(teamName) ? state.teams.concat(teamName) : state.teams;
67
- return { ...state, scenes, currentSceneIndex: scenes.length - 1, teams };
68
- }
69
- case 'action:start': {
70
- return updateCurrentScene(state, (scene) => {
71
- const lane = laneFor(scene, event.actor);
72
- lane.items.push({
73
- action: event.action,
74
- target: event.target,
75
- startTime: event.timestamp,
76
- endTime: null,
77
- duration: null,
78
- error: null,
79
- status: 'running',
80
- });
81
- });
82
- }
83
- case 'action:end': {
84
- return updateCurrentScene(state, (scene) => {
85
- const lane = scene.lanes.find((l) => l.actor === event.actor);
86
- if (!lane)
87
- return;
88
- for (let i = lane.items.length - 1; i >= 0; i--) {
89
- const item = lane.items[i];
90
- if (item.status === 'running' && item.action === event.action) {
91
- item.endTime = event.timestamp;
92
- item.duration = event.duration;
93
- item.error = event.error ?? null;
94
- item.status = event.error ? 'error' : event.duration > 500 ? 'slow' : 'success';
95
- break;
96
- }
97
- }
98
- });
99
- }
100
- case 'assertion': {
101
- return updateCurrentScene(state, (scene) => {
102
- scene.assertions.push({
103
- actor: event.actor,
104
- description: event.description,
105
- result: event.result,
106
- timestamp: event.timestamp,
107
- });
108
- });
109
- }
110
- case 'scene:end': {
111
- if (state.currentSceneIndex == null)
112
- return state;
113
- const next = updateCurrentScene(state, (scene) => {
114
- scene.endTime = event.timestamp;
115
- scene.status = event.status;
116
- scene.duration = event.duration;
117
- scene.error = event.error;
118
- });
119
- const passed = event.status === 'completed';
120
- return {
121
- ...next,
122
- currentSceneIndex: null,
123
- passCount: next.passCount + (passed ? 1 : 0),
124
- failCount: next.failCount + (passed ? 0 : 1),
125
- };
126
- }
127
- case 'run:progress':
128
- return { ...state, progress: { pct: event.pct, failing: event.failing, flaky: event.flaky } };
129
- case 'run:end':
130
- return {
131
- ...state,
132
- running: false,
133
- sceneCount: event.summary?.scenes ?? state.sceneCount,
134
- passCount: event.summary?.completed ?? state.passCount,
135
- failCount: event.summary?.failed ?? state.failCount,
136
- endDurationMs: event.duration,
137
- };
138
- default:
139
- return state;
140
- }
141
- }
142
- function updateCurrentScene(state, mutate) {
143
- const idx = state.currentSceneIndex;
144
- if (idx == null || idx < 0 || idx >= state.scenes.length)
145
- return state;
146
- const scene = cloneScene(state.scenes[idx]);
147
- mutate(scene);
148
- const scenes = state.scenes.slice();
149
- scenes[idx] = scene;
150
- return { ...state, scenes };
151
- }
152
- /** Fold a snapshot of events into a fresh state, in order. */
153
- export function foldEvents(events) {
154
- return events.reduce(applyEvent, initialState());
155
- }
156
- /** Return a new state with the connection liveness updated. */
157
- export function withConnection(state, connection) {
158
- return { ...state, connection };
159
- }
160
- /** Number of scenes that have finished (not currently running). */
161
- export function completedSceneCount(state) {
162
- return state.scenes.filter((s) => s.status !== 'running').length;
163
- }
164
- //# sourceMappingURL=store.js.map
package/dist/store.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
package/dist/styles.d.ts DELETED
@@ -1,10 +0,0 @@
1
- /**
2
- * The widget's stylesheet, injected into its shadow root. The only theming
3
- * surface is the small set of `--st-*` custom properties on `:host`; every
4
- * internal color derives from them or from a fixed terminal palette. A host
5
- * may set `--st-bg`, `--st-accent`, `--st-font`, `--st-font-size` (and nothing
6
- * else) to retheme the pane. These are versioned with the widget, like the
7
- * wire protocol.
8
- */
9
- export declare const STYLES = "\n:host {\n /* \u2500\u2500 Theming surface (host may override these four) \u2500\u2500 */\n --st-bg: #0f1117;\n --st-accent: #3b82f6;\n --st-font: 'SF Mono', 'Cascadia Code', 'Fira Code', ui-monospace, monospace;\n --st-font-size: 13px;\n\n /* \u2500\u2500 Internal palette (derived; not a public surface) \u2500\u2500 */\n --bg: var(--st-bg);\n --bg2: #1a1d27;\n --bg3: #252833;\n --border: #2e3140;\n --text: #e1e4ed;\n --text2: #8b8fa3;\n --green: #22c55e;\n --red: #ef4444;\n --amber: #f59e0b;\n --blue: var(--st-accent);\n\n display: block;\n font-family: var(--st-font);\n font-size: var(--st-font-size);\n color: var(--text);\n background: var(--bg);\n}\n\n* { margin: 0; padding: 0; box-sizing: border-box; }\n\n.root { min-height: 100%; background: var(--bg); }\n\nheader {\n position: sticky;\n top: 0;\n z-index: 10;\n padding: 12px 20px;\n border-bottom: 1px solid var(--border);\n background: var(--bg2);\n display: flex;\n align-items: center;\n gap: 14px;\n flex-wrap: wrap;\n}\nheader.running .logo { animation: pulse 1.2s ease-in-out infinite; }\n\nh1 { font-size: 15px; font-weight: 600; display: flex; align-items: center; gap: 8px; }\n.logo {\n display: inline-flex; align-items: center; justify-content: center;\n width: 22px; height: 22px; border-radius: 5px;\n background: var(--blue); color: #fff; font-weight: 700;\n}\n\nbutton {\n font-family: inherit; font-size: 12px; cursor: pointer;\n border: 1px solid var(--border); background: var(--bg3); color: var(--text);\n padding: 5px 10px; border-radius: 5px; display: inline-flex; align-items: center; gap: 6px;\n}\nbutton:hover:not(:disabled) { border-color: var(--blue); }\nbutton:disabled { opacity: 0.5; cursor: default; }\n.replay-all-btn { color: var(--green); }\n.stop-btn { color: var(--red); }\n\n.team-select-wrap { font-size: 12px; color: var(--text2); display: flex; align-items: center; gap: 6px; }\nselect {\n font-family: inherit; font-size: 12px; background: var(--bg3); color: var(--text);\n border: 1px solid var(--border); border-radius: 5px; padding: 4px 6px;\n}\n\n.spacer { flex: 1; }\n\n.stats { display: flex; align-items: center; gap: 14px; font-size: 12px; }\n.stat { display: flex; align-items: center; gap: 5px; }\n.stat .label { color: var(--text2); }\n.stat .value { font-weight: 600; }\n.stat.pass .value { color: var(--green); }\n.stat.fail .value { color: var(--red); }\n\n.conn { width: 9px; height: 9px; border-radius: 50%; background: var(--text2); }\n.conn.connected { background: var(--green); }\n.conn.disconnected { background: var(--red); }\n\n.progress { flex-basis: 100%; height: 3px; background: var(--bg3); border-radius: 2px; overflow: hidden; }\n.progress-fill { height: 100%; width: 0; background: var(--blue); transition: width 0.2s ease; }\n.progress.done .progress-fill { background: var(--green); }\n.progress.has-failures .progress-fill { background: var(--red); }\n\nmain { padding: 16px 20px; }\n.waiting { text-align: center; color: var(--text2); padding: 60px 20px; }\n.waiting h2 { font-size: 16px; font-weight: 500; margin-bottom: 8px; color: var(--text); }\n.waiting code { background: var(--bg3); padding: 2px 6px; border-radius: 4px; }\n\n.scene {\n border: 1px solid var(--border); border-radius: 8px; background: var(--bg2);\n margin-bottom: 14px; overflow: hidden;\n}\n.scene.failed { border-color: var(--red); }\n.scene-head {\n display: flex; align-items: center; gap: 10px; padding: 10px 14px;\n border-bottom: 1px solid var(--border); background: var(--bg3);\n}\n.scene-status { font-weight: 700; }\n.scene-status.completed { color: var(--green); }\n.scene-status.failed, .scene-status.timeout { color: var(--red); }\n.scene-status.running { color: var(--amber); }\n.scene-name { font-weight: 600; }\n.scene-file { color: var(--text2); font-size: 11px; }\n.scene-team {\n font-size: 11px; color: var(--blue); border: 1px solid var(--border);\n padding: 1px 6px; border-radius: 10px;\n}\n.scene-dur { color: var(--text2); font-size: 11px; margin-left: auto; }\n.copy-btn { padding: 3px 7px; font-size: 11px; }\n.copy-btn.copied { color: var(--green); border-color: var(--green); }\n\n.lanes { padding: 8px 14px; display: flex; flex-direction: column; gap: 6px; }\n.lane { display: flex; align-items: flex-start; gap: 8px; }\n.lane-actor { color: var(--text2); min-width: 90px; font-size: 11px; padding-top: 3px; }\n.lane-items { display: flex; flex-wrap: wrap; gap: 4px; }\n.pill {\n font-size: 11px; padding: 2px 7px; border-radius: 4px;\n border: 1px solid var(--border); background: var(--bg3); color: var(--text);\n}\n.pill.running { border-color: var(--amber); color: var(--amber); }\n.pill.success { border-color: var(--green); }\n.pill.slow { border-color: var(--amber); }\n.pill.error { border-color: var(--red); color: var(--red); }\n.pill .tgt { color: var(--text2); }\n\n.assertions { padding: 0 14px 10px; display: flex; flex-direction: column; gap: 3px; }\n.assert { font-size: 12px; display: flex; gap: 6px; align-items: baseline; }\n.assert .mark { font-weight: 700; }\n.assert.ok .mark { color: var(--green); }\n.assert.bad .mark { color: var(--red); }\n.assert .who { color: var(--text2); }\n\n.scene-error {\n margin: 0 14px 12px; padding: 8px 10px; border-radius: 6px;\n background: rgba(239, 68, 68, 0.1); border: 1px solid var(--red);\n color: var(--red); font-size: 12px; white-space: pre-wrap; cursor: pointer;\n}\n\n@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.55; } }\n";
10
- //# sourceMappingURL=styles.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../src/styles.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM,o4KA8IlB,CAAA"}