@mastra/playground-ui 51.2.0 → 51.3.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/LICENSE.md +6 -4
  3. package/dist/components/DataCodeSection.cjs.js +1 -1
  4. package/dist/components/DataCodeSection.es.js +1 -1
  5. package/dist/components/DataPanel.cjs.js +1 -1
  6. package/dist/components/DataPanel.es.js +1 -1
  7. package/dist/components/FormFieldBlocks.cjs.js +1 -1
  8. package/dist/components/FormFieldBlocks.es.js +1 -1
  9. package/dist/components/ListSearch.cjs.js +13 -2
  10. package/dist/components/ListSearch.cjs.js.map +1 -1
  11. package/dist/components/ListSearch.es.js +14 -3
  12. package/dist/components/ListSearch.es.js.map +1 -1
  13. package/dist/components/LogsDataList.cjs.js +0 -1
  14. package/dist/components/LogsDataList.cjs.js.map +1 -1
  15. package/dist/components/LogsDataList.es.js +0 -1
  16. package/dist/components/LogsDataList.es.js.map +1 -1
  17. package/dist/components/MarkdownRenderer.cjs.js +3 -65
  18. package/dist/components/MarkdownRenderer.cjs.js.map +1 -1
  19. package/dist/components/MarkdownRenderer.es.js +1 -67
  20. package/dist/components/MarkdownRenderer.es.js.map +1 -1
  21. package/dist/components/ai/message-reveal.cjs.js +50 -0
  22. package/dist/components/ai/message-reveal.cjs.js.map +1 -0
  23. package/dist/components/ai/message-reveal.d.ts +2 -0
  24. package/dist/components/ai/message-reveal.es.js +44 -0
  25. package/dist/components/ai/message-reveal.es.js.map +1 -0
  26. package/dist/{data-code-section-sK4cZuA-.cjs → data-code-section-C3ZRkULz.cjs} +2 -2
  27. package/dist/{data-code-section-sK4cZuA-.cjs.map → data-code-section-C3ZRkULz.cjs.map} +1 -1
  28. package/dist/{data-code-section-g1jBtzwR.js → data-code-section-CSt_ZuUP.js} +2 -2
  29. package/dist/{data-code-section-g1jBtzwR.js.map → data-code-section-CSt_ZuUP.js.map} +1 -1
  30. package/dist/{data-panel-B3AECYLW.cjs → data-panel-DHNc5Y4L.cjs} +2 -2
  31. package/dist/{data-panel-B3AECYLW.cjs.map → data-panel-DHNc5Y4L.cjs.map} +1 -1
  32. package/dist/{data-panel-B527Q_Zh.js → data-panel-DJpAfEsG.js} +2 -2
  33. package/dist/{data-panel-B527Q_Zh.js.map → data-panel-DJpAfEsG.js.map} +1 -1
  34. package/dist/domains/traces/components/span-data-panel-view.cjs.js +1 -1
  35. package/dist/domains/traces/components/span-data-panel-view.es.js +1 -1
  36. package/dist/domains/traces/components/timeline-name-col.cjs.js +1 -1
  37. package/dist/domains/traces/components/timeline-name-col.cjs.js.map +1 -1
  38. package/dist/domains/traces/components/timeline-name-col.es.js +1 -1
  39. package/dist/domains/traces/components/timeline-name-col.es.js.map +1 -1
  40. package/dist/domains/traces/components/trace-data-panel-view.cjs.js +44 -9
  41. package/dist/domains/traces/components/trace-data-panel-view.cjs.js.map +1 -1
  42. package/dist/domains/traces/components/trace-data-panel-view.es.js +45 -10
  43. package/dist/domains/traces/components/trace-data-panel-view.es.js.map +1 -1
  44. package/dist/domains/traces/components/trace-timeline.cjs.js +18 -14
  45. package/dist/domains/traces/components/trace-timeline.cjs.js.map +1 -1
  46. package/dist/domains/traces/components/trace-timeline.es.js +18 -14
  47. package/dist/domains/traces/components/trace-timeline.es.js.map +1 -1
  48. package/dist/domains/traces/hooks/use-branch.cjs.js +4 -0
  49. package/dist/domains/traces/hooks/use-branch.cjs.js.map +1 -1
  50. package/dist/domains/traces/hooks/use-branch.es.js +4 -0
  51. package/dist/domains/traces/hooks/use-branch.es.js.map +1 -1
  52. package/dist/domains/traces/hooks/use-trace-light-spans.cjs.js +4 -0
  53. package/dist/domains/traces/hooks/use-trace-light-spans.cjs.js.map +1 -1
  54. package/dist/domains/traces/hooks/use-trace-light-spans.es.js +4 -0
  55. package/dist/domains/traces/hooks/use-trace-light-spans.es.js.map +1 -1
  56. package/dist/domains/traces/hooks/use-trace-or-branch-spans.cjs.js +2 -2
  57. package/dist/domains/traces/hooks/use-trace-or-branch-spans.cjs.js.map +1 -1
  58. package/dist/domains/traces/hooks/use-trace-or-branch-spans.es.js +2 -2
  59. package/dist/domains/traces/hooks/use-trace-or-branch-spans.es.js.map +1 -1
  60. package/dist/domains/traces/hooks/use-trace-search.cjs.js +21 -0
  61. package/dist/domains/traces/hooks/use-trace-search.cjs.js.map +1 -0
  62. package/dist/domains/traces/hooks/use-trace-search.d.ts +2 -0
  63. package/dist/domains/traces/hooks/use-trace-search.es.js +17 -0
  64. package/dist/domains/traces/hooks/use-trace-search.es.js.map +1 -0
  65. package/dist/domains/traces/hooks/use-trace-spans.cjs.js +11 -1
  66. package/dist/domains/traces/hooks/use-trace-spans.cjs.js.map +1 -1
  67. package/dist/domains/traces/hooks/use-trace-spans.es.js +11 -1
  68. package/dist/domains/traces/hooks/use-trace-spans.es.js.map +1 -1
  69. package/dist/domains/traces/hooks.cjs.js +2 -0
  70. package/dist/domains/traces/hooks.cjs.js.map +1 -1
  71. package/dist/domains/traces/hooks.es.js +1 -0
  72. package/dist/domains/traces/hooks.es.js.map +1 -1
  73. package/dist/domains/traces/types.cjs.js.map +1 -1
  74. package/dist/domains/traces/types.es.js.map +1 -1
  75. package/dist/domains/traces/utils/filter-spans-keeping-ancestors.cjs.js +47 -0
  76. package/dist/domains/traces/utils/filter-spans-keeping-ancestors.cjs.js.map +1 -0
  77. package/dist/domains/traces/utils/filter-spans-keeping-ancestors.d.ts +2 -0
  78. package/dist/domains/traces/utils/filter-spans-keeping-ancestors.es.js +43 -0
  79. package/dist/domains/traces/utils/filter-spans-keeping-ancestors.es.js.map +1 -0
  80. package/dist/domains/traces/utils/flatten-to-search-text.cjs.js +78 -0
  81. package/dist/domains/traces/utils/flatten-to-search-text.cjs.js.map +1 -0
  82. package/dist/domains/traces/utils/flatten-to-search-text.d.ts +2 -0
  83. package/dist/domains/traces/utils/flatten-to-search-text.es.js +74 -0
  84. package/dist/domains/traces/utils/flatten-to-search-text.es.js.map +1 -0
  85. package/dist/domains/traces/utils/to-searchable-spans.cjs.js +22 -0
  86. package/dist/domains/traces/utils/to-searchable-spans.cjs.js.map +1 -0
  87. package/dist/domains/traces/utils/to-searchable-spans.d.ts +2 -0
  88. package/dist/domains/traces/utils/to-searchable-spans.es.js +17 -0
  89. package/dist/domains/traces/utils/to-searchable-spans.es.js.map +1 -0
  90. package/dist/domains/traces/utils.cjs.js +7 -0
  91. package/dist/domains/traces/utils.cjs.js.map +1 -1
  92. package/dist/domains/traces/utils.es.js +3 -0
  93. package/dist/domains/traces/utils.es.js.map +1 -1
  94. package/dist/domains/traces.cjs.js +9 -0
  95. package/dist/domains/traces.cjs.js.map +1 -1
  96. package/dist/domains/traces.es.js +4 -0
  97. package/dist/domains/traces.es.js.map +1 -1
  98. package/dist/ee/topics/components/topic-trace-details-panel.cjs.js +2 -2
  99. package/dist/ee/topics/components/topic-trace-details-panel.cjs.js.map +1 -1
  100. package/dist/ee/topics/components/topic-trace-details-panel.es.js +2 -2
  101. package/dist/ee/topics/components/topic-trace-details-panel.es.js.map +1 -1
  102. package/dist/hooks/use-text-highlight.cjs.js +68 -0
  103. package/dist/hooks/use-text-highlight.cjs.js.map +1 -0
  104. package/dist/hooks/use-text-highlight.d.ts +2 -0
  105. package/dist/hooks/use-text-highlight.es.js +64 -0
  106. package/dist/hooks/use-text-highlight.es.js.map +1 -0
  107. package/dist/{search-field-block-BqRM53jf.cjs → search-field-block-CjCIzUhN.cjs} +8 -3
  108. package/dist/search-field-block-CjCIzUhN.cjs.map +1 -0
  109. package/dist/{search-field-block-CgrC6f9t.js → search-field-block-DoNywsJC.js} +8 -3
  110. package/dist/search-field-block-DoNywsJC.js.map +1 -0
  111. package/dist/src/domains/traces/components/trace-data-panel-view.d.ts +2 -2
  112. package/dist/src/domains/traces/components/trace-timeline.d.ts +4 -2
  113. package/dist/src/domains/traces/hooks/index.d.ts +1 -0
  114. package/dist/src/domains/traces/hooks/use-branch.d.ts +2 -2
  115. package/dist/src/domains/traces/hooks/use-trace-light-spans.d.ts +2 -2
  116. package/dist/src/domains/traces/hooks/use-trace-or-branch-spans.d.ts +5 -2
  117. package/dist/src/domains/traces/hooks/use-trace-search.d.ts +27 -0
  118. package/dist/src/domains/traces/hooks/use-trace-spans.d.ts +11 -2
  119. package/dist/src/domains/traces/types.d.ts +16 -0
  120. package/dist/src/domains/traces/utils/filter-spans-keeping-ancestors.d.ts +19 -0
  121. package/dist/src/domains/traces/utils/flatten-to-search-text.d.ts +25 -0
  122. package/dist/src/domains/traces/utils/index.d.ts +3 -0
  123. package/dist/src/domains/traces/utils/to-searchable-spans.d.ts +41 -0
  124. package/dist/src/ds/components/Arrival/arrival.stories.d.ts +6 -0
  125. package/dist/src/ds/components/Card/card.stories.d.ts +8 -0
  126. package/dist/src/ds/components/Columns/columns.stories.d.ts +7 -0
  127. package/dist/src/ds/components/DataDetailsPanel/data-details-panel.stories.d.ts +9 -0
  128. package/dist/src/ds/components/DataFilter/select-data-filter.stories.d.ts +8 -0
  129. package/dist/src/ds/components/DateRangeTimeline/date-range-timeline.stories.d.ts +8 -0
  130. package/dist/src/ds/components/ErrorState/error-state.stories.d.ts +7 -0
  131. package/dist/src/ds/components/FormFieldBlocks/fields/search-field-block.d.ts +4 -1
  132. package/dist/src/ds/components/ListSearch/list-search.d.ts +6 -1
  133. package/dist/src/ds/components/ListSearch/list-search.stories.d.ts +7 -0
  134. package/dist/src/ds/components/LogsDataList/logs-data-list.stories.d.ts +8 -0
  135. package/dist/src/ds/components/MessageScroller/message-scroller.stories.d.ts +7 -0
  136. package/dist/src/ds/components/MetricsLineChart/metrics-line-chart.stories.d.ts +8 -0
  137. package/dist/src/ds/components/PageHeader/page-header.stories.d.ts +8 -0
  138. package/dist/src/ds/components/PageLayout/page-layout.stories.d.ts +8 -0
  139. package/dist/src/ds/components/PendingIndicator/pending-indicator.stories.d.ts +7 -0
  140. package/dist/src/ds/components/PermissionDenied/permission-denied.stories.d.ts +8 -0
  141. package/dist/src/ds/components/PrevNextNav/prev-next-nav.stories.d.ts +8 -0
  142. package/dist/src/ds/components/SessionExpired/session-expired.stories.d.ts +7 -0
  143. package/dist/src/ds/components/Shimmer/shimmer.stories.d.ts +7 -0
  144. package/dist/src/ds/components/StatusBadge/status-badge.stories.d.ts +8 -0
  145. package/dist/src/ds/components/ThreadList/thread-list.stories.d.ts +8 -0
  146. package/dist/src/ds/components/ThreadRail/thread-rail.stories.d.ts +7 -0
  147. package/dist/src/ds/components/TokenBudget/token-budget.stories.d.ts +8 -0
  148. package/dist/src/ds/components/ai/message-reveal/index.d.ts +1 -0
  149. package/dist/src/ds/components/ai/message-reveal/message-reveal.d.ts +22 -0
  150. package/dist/src/hooks/use-text-highlight.d.ts +18 -0
  151. package/dist/src/test/highlight-api.d.ts +28 -0
  152. package/dist/style.css +80 -0
  153. package/dist/use-reveal-Sa456jZb.cjs +70 -0
  154. package/dist/use-reveal-Sa456jZb.cjs.map +1 -0
  155. package/dist/use-reveal-d77hxHz9.js +68 -0
  156. package/dist/use-reveal-d77hxHz9.js.map +1 -0
  157. package/dist/use-text-highlight.css +8 -0
  158. package/package.json +8 -8
  159. package/dist/search-field-block-BqRM53jf.cjs.map +0 -1
  160. package/dist/search-field-block-CgrC6f9t.js.map +0 -1
@@ -1,5 +1,5 @@
1
- import { LightSpanRecord } from '@mastra/core/storage';
2
1
  import { TraceListMode } from '../trace-filters';
2
+ import { SearchableSpan } from '../types';
3
3
  export interface UseTraceOrBranchSpansArgs {
4
4
  traceId: string | null | undefined;
5
5
  /** Required when `listMode === 'branches'` — the anchor span identifying the displayed
@@ -10,7 +10,7 @@ export interface UseTraceOrBranchSpansArgs {
10
10
  depth?: number;
11
11
  }
12
12
  export interface UseTraceOrBranchSpansResult {
13
- spans: LightSpanRecord[] | undefined;
13
+ spans: SearchableSpan[] | undefined;
14
14
  /** Set in branches mode; undefined in traces mode (which uses parentSpanId == null). */
15
15
  anchorSpanId: string | undefined;
16
16
  isLoading: boolean;
@@ -21,5 +21,8 @@ export interface UseTraceOrBranchSpansResult {
21
21
  * Unified data source for the trace/span detail panel. Returns trace spans (full tree from the
22
22
  * root) in traces mode, or branch spans (subtree rooted at `anchorSpanId`) in branches mode.
23
23
  * Only the active query fires; the inactive one is disabled via its `enabled` flag.
24
+ *
25
+ * Both modes carry full span payloads: the panel renders and searches them, so a lightweight
26
+ * projection here would hide content from the reader looking straight at it.
24
27
  */
25
28
  export declare function useTraceOrBranchSpans({ traceId, anchorSpanId, listMode, depth, }: UseTraceOrBranchSpansArgs): UseTraceOrBranchSpansResult;
@@ -0,0 +1,27 @@
1
+ import { SearchableSpan } from '../types';
2
+ export interface UseTraceSearchResult {
3
+ /** The immediate, user-facing input value. Bind this to the search field. */
4
+ query: string;
5
+ setQuery: (query: string) => void;
6
+ /** Rows matching the deferred query. An empty query returns the input array reference. */
7
+ results: SearchableSpan[];
8
+ /** True while the deferred value is behind `query` (the list is still catching up). */
9
+ isPending: boolean;
10
+ }
11
+ /**
12
+ * Client-side search over a flat span list.
13
+ *
14
+ * Matching is a substring test against `searchText`, the haystack built once per span when
15
+ * the query resolved (see `toSearchableSpans`). That is what makes the open-ended `metadata`
16
+ * and `error` payloads searchable: their shapes are unknown, so no fixed list of fields can
17
+ * read them. Both sides are already lowercased, so the test is a bare `includes`.
18
+ *
19
+ * Filtering is keyed on a deferred copy of the query, so typing stays responsive while a
20
+ * large list re-filters at lower priority — bind the input to `query`, not to the deferred
21
+ * value. A matching span keeps its ancestors and its whole subtree, so the hierarchy stays
22
+ * intact.
23
+ *
24
+ * `spans` is required. Resolving the loading/empty state is the caller's job — a component
25
+ * holding a query result passes `data?.spans ?? []`.
26
+ */
27
+ export declare function useTraceSearch(spans: SearchableSpan[]): UseTraceSearchResult;
@@ -1,6 +1,15 @@
1
- import { LightSpanRecord } from '@mastra/core/storage';
2
1
  import { UseQueryResult } from '@tanstack/react-query';
2
+ import { SearchableSpan } from '../types';
3
+ /**
4
+ * Every span of a single trace, with its full payload.
5
+ *
6
+ * The lightweight projection exists to keep blob columns off the read path of a
7
+ * *list*, where the cost is paid once per trace on screen. A trace that is open
8
+ * has already narrowed that to one, and the panel both renders and searches
9
+ * these spans -- `input`, `output` and `attributes` included -- so the
10
+ * projection would only hide content the reader is looking at.
11
+ */
3
12
  export declare function useTraceSpans(traceId: string | null | undefined): UseQueryResult<{
4
13
  traceId: string;
5
- spans: LightSpanRecord[];
14
+ spans: SearchableSpan[];
6
15
  } | null>;
@@ -1,5 +1,21 @@
1
1
  import { EntityType } from '@mastra/core/observability';
2
+ import { LightSpanRecord } from '@mastra/core/storage';
2
3
  import { ReactNode } from 'react';
4
+ /**
5
+ * A light span carrying a precomputed haystack of everything it holds.
6
+ *
7
+ * `LightSpanRecord` exposes searchable content across a fixed set of columns
8
+ * plus open-ended payloads whose shape is unknown, so a search cannot read it
9
+ * field by field. `searchText` is that content flattened once — see
10
+ * `flattenToSearchText` — so filtering is a substring test per span instead of
11
+ * a re-walk of every payload on every keystroke.
12
+ *
13
+ * It holds field names as well as values, so a span is findable by the shape of
14
+ * its payload and not only by its content.
15
+ */
16
+ export type SearchableSpan = LightSpanRecord & {
17
+ searchText: string;
18
+ };
3
19
  export type UISpan = {
4
20
  id: string;
5
21
  name: string;
@@ -0,0 +1,19 @@
1
+ import { LightSpanRecord } from '@mastra/core/storage';
2
+ /**
3
+ * Filter a flat span list down to the spans matching `predicate`, plus every
4
+ * ancestor needed to keep those spans connected to their root, plus the whole
5
+ * subtree below each match — a matching span is shown intact, not truncated.
6
+ *
7
+ * `spans` may arrive in any order. Trace payloads are flat lists sorted by
8
+ * `startedAt` (and the list API defaults to `direction: 'DESC'`), so children
9
+ * routinely precede their parents; the traversal below indexes the list up
10
+ * front rather than assuming a topological order.
11
+ *
12
+ * The output preserves the input's relative order, so it can be fed straight
13
+ * into `formatHierarchicalSpans`. `predicate` is called exactly once per span.
14
+ *
15
+ * Generic over the span type: only `spanId` and `parentSpanId` are read, and the
16
+ * exact input type comes back out, so enriched spans such as `SearchableSpan`
17
+ * survive the filter instead of being widened to `LightSpanRecord`.
18
+ */
19
+ export declare function filterSpansKeepingAncestors<T extends Pick<LightSpanRecord, 'spanId' | 'parentSpanId'>>(spans: T[], predicate: (span: T) => boolean): T[];
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Flatten an arbitrary value into a single space-separated string containing
3
+ * every searchable token it holds, however deeply nested.
4
+ *
5
+ * Built for span payloads whose shape is not known ahead of time (`attributes`,
6
+ * `output`, `errorInfo`): the caller cannot enumerate fields, so this walks
7
+ * whatever it is handed.
8
+ *
9
+ * **Keys are emitted alongside their values**, so a field name is searchable
10
+ * even when its value is not — `{ error: null }` still answers a search for
11
+ * `error`. The cost is that structural names present on every span (`traceId`,
12
+ * `usage`, …) are searchable too, which makes short generic terms match widely.
13
+ *
14
+ * Values that no one can usefully search for are dropped rather than
15
+ * stringified: `null`, `undefined`, `NaN`, infinities, functions, symbols,
16
+ * invalid dates and whitespace-only strings. Dropping them keeps the output
17
+ * free of noise words like `"Invalid Date"` that would produce false hits.
18
+ * Array indices are dropped for the same reason — `0 1 2` is not content.
19
+ *
20
+ * Cycles are detected along the current path, so a self-referencing object
21
+ * terminates while a value referenced twice as a sibling is emitted twice.
22
+ * Only own, string-keyed properties are read, and a getter that throws is
23
+ * skipped instead of taking the whole trace down.
24
+ */
25
+ export declare function flattenToSearchText(value: unknown): string;
@@ -1 +1,4 @@
1
+ export { filterSpansKeepingAncestors } from './filter-spans-keeping-ancestors';
2
+ export { flattenToSearchText } from './flatten-to-search-text';
3
+ export { selectSearchableSpans, toSearchableSpans } from './to-searchable-spans';
1
4
  export { formatSpanDuration, getInputPreview, isTokenLimitExceeded, getTokenLimitMessage } from './span-utils';
@@ -0,0 +1,41 @@
1
+ import { LightSpanRecord } from '@mastra/core/storage';
2
+ import { SearchableSpan } from '../types';
3
+ /**
4
+ * Attach a precomputed search haystack to each span.
5
+ *
6
+ * Run this once, where the span list is resolved — not per keystroke. Flattening
7
+ * walks every nested payload, so doing it inside a filter would repeat the whole
8
+ * walk for every character typed.
9
+ *
10
+ * The whole record is flattened, which is what reaches `metadata` and `error`:
11
+ * their shapes are open-ended, so no fixed list of fields can read them. The
12
+ * text is lowercased here so matching is a bare `includes` with no per-span
13
+ * `toLowerCase` on every keystroke.
14
+ *
15
+ * Inputs are left untouched; each result is a new object.
16
+ */
17
+ export declare function toSearchableSpans(spans: LightSpanRecord[]): SearchableSpan[];
18
+ /**
19
+ * React Query `select` for the `{ traceId, spans }` payload returned by
20
+ * `getTraceLight` and `getBranch`.
21
+ *
22
+ * Enriching here rather than in a component means the flattening runs once per
23
+ * fetch and is cached with the query, so it survives the panel unmounting and
24
+ * remounting. Keep this a module-level reference: React Query re-runs `select`
25
+ * whenever its identity changes, and an inline arrow would re-flatten the whole
26
+ * trace on every render.
27
+ *
28
+ * Deliberately not generic: TypeScript cannot infer a query's `TData` from a
29
+ * generic function passed as `select`, and silently falls back to the unselected
30
+ * type — which would leave `searchText` missing at the call sites.
31
+ *
32
+ * `null` is passed through because a query may resolve to it. `undefined` is not
33
+ * in the signature: React Query only runs `select` once data exists.
34
+ */
35
+ export declare function selectSearchableSpans(data: {
36
+ traceId: string;
37
+ spans: LightSpanRecord[];
38
+ } | null): {
39
+ traceId: string;
40
+ spans: SearchableSpan[];
41
+ } | null;
@@ -0,0 +1,6 @@
1
+ import { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { ArrivalScope } from './arrival';
3
+ declare const meta: Meta<typeof ArrivalScope>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof ArrivalScope>;
6
+ export declare const ExistingAndNewContent: Story;
@@ -0,0 +1,8 @@
1
+ import { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { Card } from './Card';
3
+ declare const meta: Meta<typeof Card>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof Card>;
6
+ export declare const Default: Story;
7
+ export declare const AppearancesAndElevation: Story;
8
+ export declare const InteractiveLinks: Story;
@@ -0,0 +1,7 @@
1
+ import { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { Columns } from './index';
3
+ declare const meta: Meta<typeof Columns>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof Columns>;
6
+ export declare const ResponsiveGrid: Story;
7
+ export declare const HorizontallyScrollable: Story;
@@ -0,0 +1,9 @@
1
+ import { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { DataDetailsPanel } from './index';
3
+ declare const meta: Meta<typeof DataDetailsPanel>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof DataDetailsPanel>;
6
+ export declare const Populated: Story;
7
+ export declare const Loading: Story;
8
+ export declare const Empty: Story;
9
+ export declare const Collapsed: Story;
@@ -0,0 +1,8 @@
1
+ import { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { SelectDataFilter } from './select-data-filter';
3
+ declare const meta: Meta<typeof SelectDataFilter>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof SelectDataFilter>;
6
+ export declare const Default: Story;
7
+ export declare const WithActiveFilters: Story;
8
+ export declare const Disabled: Story;
@@ -0,0 +1,8 @@
1
+ import { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { DateRangeTimeline } from './DateRangeTimeline';
3
+ declare const meta: Meta<typeof DateRangeTimeline>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof DateRangeTimeline>;
6
+ export declare const Default: Story;
7
+ export declare const SingleDay: Story;
8
+ export declare const MultiYear: Story;
@@ -0,0 +1,7 @@
1
+ import { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { ErrorState } from './ErrorState';
3
+ declare const meta: Meta<typeof ErrorState>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof ErrorState>;
6
+ export declare const Default: Story;
7
+ export declare const WithRecoveryAction: Story;
@@ -1,3 +1,4 @@
1
+ import { RefObject } from 'react';
1
2
  import { InputProps } from '../../Input';
2
3
  export type SearchFieldBlockProps = {
3
4
  name: string;
@@ -19,5 +20,7 @@ export type SearchFieldBlockProps = {
19
20
  variant?: InputProps['variant'];
20
21
  isMinimized?: boolean;
21
22
  onMinimizedChange?: (minimized: boolean) => void;
23
+ /** Gives the caller access to the underlying input, e.g. to focus it from a keyboard shortcut. */
24
+ inputRef?: RefObject<HTMLInputElement | null>;
22
25
  };
23
- export declare function SearchFieldBlock({ name, helpText, errorMsg, required, disabled, value, label, labelIsHidden, layout, placeholder, onChange, onReset, className, size, variant, isMinimized, onMinimizedChange, }: SearchFieldBlockProps): import("react").JSX.Element;
26
+ export declare function SearchFieldBlock({ name, helpText, errorMsg, required, disabled, value, label, labelIsHidden, layout, placeholder, onChange, onReset, className, size, variant, isMinimized, onMinimizedChange, inputRef: externalInputRef, }: SearchFieldBlockProps): import("react").JSX.Element;
@@ -12,5 +12,10 @@ export type ListSearchProps = {
12
12
  */
13
13
  value?: string;
14
14
  variant?: InputProps['variant'];
15
+ /**
16
+ * Opts out of the Cmd/Ctrl+Shift+F focus shortcut. Pass this on secondary
17
+ * instances so two search fields on the same page don't fight over focus.
18
+ */
19
+ shortcutDisabled?: boolean;
15
20
  };
16
- export declare const ListSearch: ({ onSearch, label, placeholder, debounceMs, size, value: controlledValue, variant, }: ListSearchProps) => import("react").JSX.Element;
21
+ export declare const ListSearch: ({ onSearch, label, placeholder, debounceMs, size, value: controlledValue, variant, shortcutDisabled, }: ListSearchProps) => import("react").JSX.Element;
@@ -0,0 +1,7 @@
1
+ import { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { ListSearch } from './list-search';
3
+ declare const meta: Meta<typeof ListSearch>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof ListSearch>;
6
+ export declare const Default: Story;
7
+ export declare const PresetValue: Story;
@@ -0,0 +1,8 @@
1
+ import { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { LogsDataList } from './index';
3
+ declare const meta: Meta<typeof LogsDataList>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof LogsDataList>;
6
+ export declare const Populated: Story;
7
+ export declare const NoMatches: Story;
8
+ export declare const Loading: Story;
@@ -0,0 +1,7 @@
1
+ import { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { MessageScroller } from './message-scroller';
3
+ declare const meta: Meta<typeof MessageScroller>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof MessageScroller>;
6
+ export declare const Conversation: Story;
7
+ export declare const AutoFollow: Story;
@@ -0,0 +1,8 @@
1
+ import { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { MetricsLineChart } from './metrics-line-chart';
3
+ declare const meta: Meta<typeof MetricsLineChart>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof MetricsLineChart>;
6
+ export declare const MultipleSeries: Story;
7
+ export declare const SinglePoint: Story;
8
+ export declare const FixedDomain: Story;
@@ -0,0 +1,8 @@
1
+ import { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { PageHeader } from './page-header';
3
+ declare const meta: Meta<typeof PageHeader>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof PageHeader>;
6
+ export declare const Default: Story;
7
+ export declare const Loading: Story;
8
+ export declare const SmallerTitle: Story;
@@ -0,0 +1,8 @@
1
+ import { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { PageLayout } from './index';
3
+ declare const meta: Meta<typeof PageLayout>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof PageLayout>;
6
+ export declare const FullPage: Story;
7
+ export declare const NarrowSettings: Story;
8
+ export declare const CenteredEmptyState: Story;
@@ -0,0 +1,7 @@
1
+ import { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { PendingIndicator } from './pending-indicator';
3
+ declare const meta: Meta<typeof PendingIndicator>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof PendingIndicator>;
6
+ export declare const Default: Story;
7
+ export declare const InConversation: Story;
@@ -0,0 +1,8 @@
1
+ import { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { PermissionDenied } from './PermissionDenied';
3
+ declare const meta: Meta<typeof PermissionDenied>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof PermissionDenied>;
6
+ export declare const Default: Story;
7
+ export declare const ResourceSpecific: Story;
8
+ export declare const CustomRecovery: Story;
@@ -0,0 +1,8 @@
1
+ import { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { PrevNextNav } from './prev-next-nav';
3
+ declare const meta: Meta<typeof PrevNextNav>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof PrevNextNav>;
6
+ export declare const BetweenItems: Story;
7
+ export declare const FirstItem: Story;
8
+ export declare const LastItem: Story;
@@ -0,0 +1,7 @@
1
+ import { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { SessionExpired } from './SessionExpired';
3
+ declare const meta: Meta<typeof SessionExpired>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof SessionExpired>;
6
+ export declare const Default: Story;
7
+ export declare const CustomCopy: Story;
@@ -0,0 +1,7 @@
1
+ import { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { Shimmer } from './shimmer';
3
+ declare const meta: Meta<typeof Shimmer>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof Shimmer>;
6
+ export declare const Default: Story;
7
+ export declare const ActiveToSettled: Story;
@@ -0,0 +1,8 @@
1
+ import { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { StatusBadge } from './StatusBadge';
3
+ declare const meta: Meta<typeof StatusBadge>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof StatusBadge>;
6
+ export declare const Default: Story;
7
+ export declare const Variants: Story;
8
+ export declare const SizesAndPulse: Story;
@@ -0,0 +1,8 @@
1
+ import { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { ThreadList } from './thread-list';
3
+ declare const meta: Meta<typeof ThreadList>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof ThreadList>;
6
+ export declare const Default: Story;
7
+ export declare const Embedded: Story;
8
+ export declare const Empty: Story;
@@ -0,0 +1,7 @@
1
+ import { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { ThreadRail } from './thread-rail';
3
+ declare const meta: Meta<typeof ThreadRail>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof ThreadRail>;
6
+ export declare const ConversationTimeline: Story;
7
+ export declare const Empty: Story;
@@ -0,0 +1,8 @@
1
+ import { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { TokenBudget } from './token-budget';
3
+ declare const meta: Meta<typeof TokenBudget>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof TokenBudget>;
6
+ export declare const Default: Story;
7
+ export declare const Budgets: Story;
8
+ export declare const Details: Story;
@@ -0,0 +1 @@
1
+ export * from './message-reveal';
@@ -0,0 +1,22 @@
1
+ import { MastraDBMessage } from '@mastra/core/agent/message-list';
2
+ type MessagePart = MastraDBMessage['content']['parts'][number];
3
+ /** What the reveal paces: the whole message, rows and cards written in as beats between the prose. */
4
+ export declare function messageScript(parts: MessagePart[]): string;
5
+ /**
6
+ * The parts of a message a reveal has reached, `shown` being a prefix of the script.
7
+ *
8
+ * A reply is not only prose: a tool row, a card, a reasoning block sit between its
9
+ * passages, and they were written in that order. Pacing the prose alone would lay a
10
+ * sentence down word by word while the row that follows it is already on screen — so
11
+ * every part waits its turn on the one clock, and the reader is handed the answer in
12
+ * the order it was written.
13
+ */
14
+ export declare function revealedParts(parts: MessagePart[], shown: string): MessagePart[];
15
+ /**
16
+ * A message's parts as far as the reveal has laid them down. Hand the result to
17
+ * `MessageFactory` in place of the message's own parts and the whole reply — prose,
18
+ * reasoning, tool rows, cards — arrives at the pace it was written, from one clock,
19
+ * without a renderer having to know a reveal is running.
20
+ */
21
+ export declare function useRevealedParts(parts: MessagePart[], streaming: boolean): MessagePart[];
22
+ export {};
@@ -0,0 +1,18 @@
1
+ import { RefCallback } from 'react';
2
+ export interface UseTextHighlightResult<TElement extends HTMLElement> {
3
+ ref: RefCallback<TElement>;
4
+ }
5
+ /**
6
+ * Paints every occurrence of `search` inside the referenced subtree using the CSS Custom
7
+ * Highlight API. Only text under an element carrying `data-highlight` is painted, so a
8
+ * surface names its searchable regions and everything else — headers, labels, metadata —
9
+ * is left alone by default. The DOM is never mutated — no wrapper elements are injected — so text
10
+ * selection, copy/paste and virtualised renderers are unaffected. Styling lives in
11
+ * `use-text-highlight.css` (`::highlight(search-result)`).
12
+ *
13
+ * Terms shorter than two characters are ignored — they match too much to be useful.
14
+ * Matching is case-insensitive and literal (the term is escaped, not a pattern). The
15
+ * subtree is re-scanned on content changes, coalesced to one scan per frame. Browsers
16
+ * without the API simply render nothing highlighted.
17
+ */
18
+ export declare function useTextHighlight<TElement extends HTMLElement = HTMLElement>(search: string): UseTextHighlightResult<TElement>;
@@ -0,0 +1,28 @@
1
+ import { vi } from 'vitest';
2
+ /**
3
+ * Minimal fakes for the CSS Custom Highlight API, which jsdom does not implement.
4
+ * Install with `installHighlightApi()` in `beforeEach` and undo with the returned
5
+ * `restore` in `afterEach`.
6
+ */
7
+ export interface FakeStaticRange {
8
+ startContainer: Node;
9
+ startOffset: number;
10
+ endContainer: Node;
11
+ endOffset: number;
12
+ }
13
+ export declare class FakeHighlight {
14
+ readonly ranges: FakeStaticRange[];
15
+ constructor(...ranges: FakeStaticRange[]);
16
+ }
17
+ export interface HighlightApiHarness {
18
+ highlights: {
19
+ set: ReturnType<typeof vi.fn>;
20
+ delete: ReturnType<typeof vi.fn>;
21
+ };
22
+ /** The text covered by the ranges of the most recent registration. */
23
+ highlightedText: () => string[] | undefined;
24
+ /** The elements owning the highlighted text of the most recent registration. */
25
+ highlightedIn: () => (HTMLElement | null)[];
26
+ restore: () => void;
27
+ }
28
+ export declare function installHighlightApi(): HighlightApiHarness;
package/dist/style.css CHANGED
@@ -1621,6 +1621,10 @@
1621
1621
  margin-right: var(--spacing-8);
1622
1622
  }
1623
1623
 
1624
+ .mr-12 {
1625
+ margin-right: var(--spacing-12);
1626
+ }
1627
+
1624
1628
  .-mb-12 {
1625
1629
  margin-bottom: calc(var(--spacing-12) * -1);
1626
1630
  }
@@ -1706,6 +1710,14 @@
1706
1710
  margin-left: var(--spacing-8);
1707
1711
  }
1708
1712
 
1713
+ .ml-10 {
1714
+ margin-left: var(--spacing-10);
1715
+ }
1716
+
1717
+ .ml-12 {
1718
+ margin-left: var(--spacing-12);
1719
+ }
1720
+
1709
1721
  .ml-\[14px\] {
1710
1722
  margin-left: 14px;
1711
1723
  }
@@ -1988,6 +2000,10 @@
1988
2000
  height: var(--spacing-40);
1989
2001
  }
1990
2002
 
2003
+ .h-56 {
2004
+ height: var(--spacing-56);
2005
+ }
2006
+
1991
2007
  .h-60 {
1992
2008
  height: var(--spacing-60);
1993
2009
  }
@@ -1996,10 +2012,18 @@
1996
2012
  height: var(--spacing-64);
1997
2013
  }
1998
2014
 
2015
+ .h-72 {
2016
+ height: var(--spacing-72);
2017
+ }
2018
+
1999
2019
  .h-80 {
2000
2020
  height: var(--spacing-80);
2001
2021
  }
2002
2022
 
2023
+ .h-96 {
2024
+ height: var(--spacing-96);
2025
+ }
2026
+
2003
2027
  .h-\[1\.8rem\] {
2004
2028
  height: 1.8rem;
2005
2029
  }
@@ -2012,6 +2036,22 @@
2012
2036
  height: 30vh;
2013
2037
  }
2014
2038
 
2039
+ .h-\[32rem\] {
2040
+ height: 32rem;
2041
+ }
2042
+
2043
+ .h-\[34rem\] {
2044
+ height: 34rem;
2045
+ }
2046
+
2047
+ .h-\[36rem\] {
2048
+ height: 36rem;
2049
+ }
2050
+
2051
+ .h-\[38rem\] {
2052
+ height: 38rem;
2053
+ }
2054
+
2015
2055
  .h-\[160px\] {
2016
2056
  height: 160px;
2017
2057
  }
@@ -2241,10 +2281,18 @@
2241
2281
  min-height: var(--spacing-60);
2242
2282
  }
2243
2283
 
2284
+ .min-h-64 {
2285
+ min-height: var(--spacing-64);
2286
+ }
2287
+
2244
2288
  .min-h-72 {
2245
2289
  min-height: var(--spacing-72);
2246
2290
  }
2247
2291
 
2292
+ .min-h-\[34rem\] {
2293
+ min-height: 34rem;
2294
+ }
2295
+
2248
2296
  .min-h-\[70cqh\] {
2249
2297
  min-height: 70cqh;
2250
2298
  }
@@ -2501,6 +2549,30 @@
2501
2549
  width: calc(100vw - 2rem);
2502
2550
  }
2503
2551
 
2552
+ .w-\[min\(24rem\,calc\(100vw-2rem\)\)\] {
2553
+ width: min(24rem, 100vw - 2rem);
2554
+ }
2555
+
2556
+ .w-\[min\(34rem\,calc\(100vw-3rem\)\)\] {
2557
+ width: min(34rem, 100vw - 3rem);
2558
+ }
2559
+
2560
+ .w-\[min\(42rem\,calc\(100vw-3rem\)\)\] {
2561
+ width: min(42rem, 100vw - 3rem);
2562
+ }
2563
+
2564
+ .w-\[min\(44rem\,calc\(100vw-2rem\)\)\] {
2565
+ width: min(44rem, 100vw - 2rem);
2566
+ }
2567
+
2568
+ .w-\[min\(48rem\,calc\(100vw-3rem\)\)\] {
2569
+ width: min(48rem, 100vw - 3rem);
2570
+ }
2571
+
2572
+ .w-\[min\(52rem\,calc\(100vw-3rem\)\)\] {
2573
+ width: min(52rem, 100vw - 3rem);
2574
+ }
2575
+
2504
2576
  .w-\[var\(--active-tab-width\)\] {
2505
2577
  width: var(--active-tab-width);
2506
2578
  }
@@ -9268,6 +9340,14 @@
9268
9340
  max-height: none;
9269
9341
  }
9270
9342
 
9343
+ .md\:grid-cols-2 {
9344
+ grid-template-columns: repeat(2, minmax(0, 1fr));
9345
+ }
9346
+
9347
+ .md\:grid-cols-3 {
9348
+ grid-template-columns: repeat(3, minmax(0, 1fr));
9349
+ }
9350
+
9271
9351
  .md\:grid-cols-\[13rem_minmax\(0\,1fr\)\] {
9272
9352
  grid-template-columns: 13rem minmax(0, 1fr);
9273
9353
  }