@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.
- package/CHANGELOG.md +58 -0
- package/LICENSE.md +6 -4
- package/dist/components/DataCodeSection.cjs.js +1 -1
- package/dist/components/DataCodeSection.es.js +1 -1
- package/dist/components/DataPanel.cjs.js +1 -1
- package/dist/components/DataPanel.es.js +1 -1
- package/dist/components/FormFieldBlocks.cjs.js +1 -1
- package/dist/components/FormFieldBlocks.es.js +1 -1
- package/dist/components/ListSearch.cjs.js +13 -2
- package/dist/components/ListSearch.cjs.js.map +1 -1
- package/dist/components/ListSearch.es.js +14 -3
- package/dist/components/ListSearch.es.js.map +1 -1
- package/dist/components/LogsDataList.cjs.js +0 -1
- package/dist/components/LogsDataList.cjs.js.map +1 -1
- package/dist/components/LogsDataList.es.js +0 -1
- package/dist/components/LogsDataList.es.js.map +1 -1
- package/dist/components/MarkdownRenderer.cjs.js +3 -65
- package/dist/components/MarkdownRenderer.cjs.js.map +1 -1
- package/dist/components/MarkdownRenderer.es.js +1 -67
- package/dist/components/MarkdownRenderer.es.js.map +1 -1
- package/dist/components/ai/message-reveal.cjs.js +50 -0
- package/dist/components/ai/message-reveal.cjs.js.map +1 -0
- package/dist/components/ai/message-reveal.d.ts +2 -0
- package/dist/components/ai/message-reveal.es.js +44 -0
- package/dist/components/ai/message-reveal.es.js.map +1 -0
- package/dist/{data-code-section-sK4cZuA-.cjs → data-code-section-C3ZRkULz.cjs} +2 -2
- package/dist/{data-code-section-sK4cZuA-.cjs.map → data-code-section-C3ZRkULz.cjs.map} +1 -1
- package/dist/{data-code-section-g1jBtzwR.js → data-code-section-CSt_ZuUP.js} +2 -2
- package/dist/{data-code-section-g1jBtzwR.js.map → data-code-section-CSt_ZuUP.js.map} +1 -1
- package/dist/{data-panel-B3AECYLW.cjs → data-panel-DHNc5Y4L.cjs} +2 -2
- package/dist/{data-panel-B3AECYLW.cjs.map → data-panel-DHNc5Y4L.cjs.map} +1 -1
- package/dist/{data-panel-B527Q_Zh.js → data-panel-DJpAfEsG.js} +2 -2
- package/dist/{data-panel-B527Q_Zh.js.map → data-panel-DJpAfEsG.js.map} +1 -1
- package/dist/domains/traces/components/span-data-panel-view.cjs.js +1 -1
- package/dist/domains/traces/components/span-data-panel-view.es.js +1 -1
- package/dist/domains/traces/components/timeline-name-col.cjs.js +1 -1
- package/dist/domains/traces/components/timeline-name-col.cjs.js.map +1 -1
- package/dist/domains/traces/components/timeline-name-col.es.js +1 -1
- package/dist/domains/traces/components/timeline-name-col.es.js.map +1 -1
- package/dist/domains/traces/components/trace-data-panel-view.cjs.js +44 -9
- package/dist/domains/traces/components/trace-data-panel-view.cjs.js.map +1 -1
- package/dist/domains/traces/components/trace-data-panel-view.es.js +45 -10
- package/dist/domains/traces/components/trace-data-panel-view.es.js.map +1 -1
- package/dist/domains/traces/components/trace-timeline.cjs.js +18 -14
- package/dist/domains/traces/components/trace-timeline.cjs.js.map +1 -1
- package/dist/domains/traces/components/trace-timeline.es.js +18 -14
- package/dist/domains/traces/components/trace-timeline.es.js.map +1 -1
- package/dist/domains/traces/hooks/use-branch.cjs.js +4 -0
- package/dist/domains/traces/hooks/use-branch.cjs.js.map +1 -1
- package/dist/domains/traces/hooks/use-branch.es.js +4 -0
- package/dist/domains/traces/hooks/use-branch.es.js.map +1 -1
- package/dist/domains/traces/hooks/use-trace-light-spans.cjs.js +4 -0
- package/dist/domains/traces/hooks/use-trace-light-spans.cjs.js.map +1 -1
- package/dist/domains/traces/hooks/use-trace-light-spans.es.js +4 -0
- package/dist/domains/traces/hooks/use-trace-light-spans.es.js.map +1 -1
- package/dist/domains/traces/hooks/use-trace-or-branch-spans.cjs.js +2 -2
- package/dist/domains/traces/hooks/use-trace-or-branch-spans.cjs.js.map +1 -1
- package/dist/domains/traces/hooks/use-trace-or-branch-spans.es.js +2 -2
- package/dist/domains/traces/hooks/use-trace-or-branch-spans.es.js.map +1 -1
- package/dist/domains/traces/hooks/use-trace-search.cjs.js +21 -0
- package/dist/domains/traces/hooks/use-trace-search.cjs.js.map +1 -0
- package/dist/domains/traces/hooks/use-trace-search.d.ts +2 -0
- package/dist/domains/traces/hooks/use-trace-search.es.js +17 -0
- package/dist/domains/traces/hooks/use-trace-search.es.js.map +1 -0
- package/dist/domains/traces/hooks/use-trace-spans.cjs.js +11 -1
- package/dist/domains/traces/hooks/use-trace-spans.cjs.js.map +1 -1
- package/dist/domains/traces/hooks/use-trace-spans.es.js +11 -1
- package/dist/domains/traces/hooks/use-trace-spans.es.js.map +1 -1
- package/dist/domains/traces/hooks.cjs.js +2 -0
- package/dist/domains/traces/hooks.cjs.js.map +1 -1
- package/dist/domains/traces/hooks.es.js +1 -0
- package/dist/domains/traces/hooks.es.js.map +1 -1
- package/dist/domains/traces/types.cjs.js.map +1 -1
- package/dist/domains/traces/types.es.js.map +1 -1
- package/dist/domains/traces/utils/filter-spans-keeping-ancestors.cjs.js +47 -0
- package/dist/domains/traces/utils/filter-spans-keeping-ancestors.cjs.js.map +1 -0
- package/dist/domains/traces/utils/filter-spans-keeping-ancestors.d.ts +2 -0
- package/dist/domains/traces/utils/filter-spans-keeping-ancestors.es.js +43 -0
- package/dist/domains/traces/utils/filter-spans-keeping-ancestors.es.js.map +1 -0
- package/dist/domains/traces/utils/flatten-to-search-text.cjs.js +78 -0
- package/dist/domains/traces/utils/flatten-to-search-text.cjs.js.map +1 -0
- package/dist/domains/traces/utils/flatten-to-search-text.d.ts +2 -0
- package/dist/domains/traces/utils/flatten-to-search-text.es.js +74 -0
- package/dist/domains/traces/utils/flatten-to-search-text.es.js.map +1 -0
- package/dist/domains/traces/utils/to-searchable-spans.cjs.js +22 -0
- package/dist/domains/traces/utils/to-searchable-spans.cjs.js.map +1 -0
- package/dist/domains/traces/utils/to-searchable-spans.d.ts +2 -0
- package/dist/domains/traces/utils/to-searchable-spans.es.js +17 -0
- package/dist/domains/traces/utils/to-searchable-spans.es.js.map +1 -0
- package/dist/domains/traces/utils.cjs.js +7 -0
- package/dist/domains/traces/utils.cjs.js.map +1 -1
- package/dist/domains/traces/utils.es.js +3 -0
- package/dist/domains/traces/utils.es.js.map +1 -1
- package/dist/domains/traces.cjs.js +9 -0
- package/dist/domains/traces.cjs.js.map +1 -1
- package/dist/domains/traces.es.js +4 -0
- package/dist/domains/traces.es.js.map +1 -1
- package/dist/ee/topics/components/topic-trace-details-panel.cjs.js +2 -2
- package/dist/ee/topics/components/topic-trace-details-panel.cjs.js.map +1 -1
- package/dist/ee/topics/components/topic-trace-details-panel.es.js +2 -2
- package/dist/ee/topics/components/topic-trace-details-panel.es.js.map +1 -1
- package/dist/hooks/use-text-highlight.cjs.js +68 -0
- package/dist/hooks/use-text-highlight.cjs.js.map +1 -0
- package/dist/hooks/use-text-highlight.d.ts +2 -0
- package/dist/hooks/use-text-highlight.es.js +64 -0
- package/dist/hooks/use-text-highlight.es.js.map +1 -0
- package/dist/{search-field-block-BqRM53jf.cjs → search-field-block-CjCIzUhN.cjs} +8 -3
- package/dist/search-field-block-CjCIzUhN.cjs.map +1 -0
- package/dist/{search-field-block-CgrC6f9t.js → search-field-block-DoNywsJC.js} +8 -3
- package/dist/search-field-block-DoNywsJC.js.map +1 -0
- package/dist/src/domains/traces/components/trace-data-panel-view.d.ts +2 -2
- package/dist/src/domains/traces/components/trace-timeline.d.ts +4 -2
- package/dist/src/domains/traces/hooks/index.d.ts +1 -0
- package/dist/src/domains/traces/hooks/use-branch.d.ts +2 -2
- package/dist/src/domains/traces/hooks/use-trace-light-spans.d.ts +2 -2
- package/dist/src/domains/traces/hooks/use-trace-or-branch-spans.d.ts +5 -2
- package/dist/src/domains/traces/hooks/use-trace-search.d.ts +27 -0
- package/dist/src/domains/traces/hooks/use-trace-spans.d.ts +11 -2
- package/dist/src/domains/traces/types.d.ts +16 -0
- package/dist/src/domains/traces/utils/filter-spans-keeping-ancestors.d.ts +19 -0
- package/dist/src/domains/traces/utils/flatten-to-search-text.d.ts +25 -0
- package/dist/src/domains/traces/utils/index.d.ts +3 -0
- package/dist/src/domains/traces/utils/to-searchable-spans.d.ts +41 -0
- package/dist/src/ds/components/Arrival/arrival.stories.d.ts +6 -0
- package/dist/src/ds/components/Card/card.stories.d.ts +8 -0
- package/dist/src/ds/components/Columns/columns.stories.d.ts +7 -0
- package/dist/src/ds/components/DataDetailsPanel/data-details-panel.stories.d.ts +9 -0
- package/dist/src/ds/components/DataFilter/select-data-filter.stories.d.ts +8 -0
- package/dist/src/ds/components/DateRangeTimeline/date-range-timeline.stories.d.ts +8 -0
- package/dist/src/ds/components/ErrorState/error-state.stories.d.ts +7 -0
- package/dist/src/ds/components/FormFieldBlocks/fields/search-field-block.d.ts +4 -1
- package/dist/src/ds/components/ListSearch/list-search.d.ts +6 -1
- package/dist/src/ds/components/ListSearch/list-search.stories.d.ts +7 -0
- package/dist/src/ds/components/LogsDataList/logs-data-list.stories.d.ts +8 -0
- package/dist/src/ds/components/MessageScroller/message-scroller.stories.d.ts +7 -0
- package/dist/src/ds/components/MetricsLineChart/metrics-line-chart.stories.d.ts +8 -0
- package/dist/src/ds/components/PageHeader/page-header.stories.d.ts +8 -0
- package/dist/src/ds/components/PageLayout/page-layout.stories.d.ts +8 -0
- package/dist/src/ds/components/PendingIndicator/pending-indicator.stories.d.ts +7 -0
- package/dist/src/ds/components/PermissionDenied/permission-denied.stories.d.ts +8 -0
- package/dist/src/ds/components/PrevNextNav/prev-next-nav.stories.d.ts +8 -0
- package/dist/src/ds/components/SessionExpired/session-expired.stories.d.ts +7 -0
- package/dist/src/ds/components/Shimmer/shimmer.stories.d.ts +7 -0
- package/dist/src/ds/components/StatusBadge/status-badge.stories.d.ts +8 -0
- package/dist/src/ds/components/ThreadList/thread-list.stories.d.ts +8 -0
- package/dist/src/ds/components/ThreadRail/thread-rail.stories.d.ts +7 -0
- package/dist/src/ds/components/TokenBudget/token-budget.stories.d.ts +8 -0
- package/dist/src/ds/components/ai/message-reveal/index.d.ts +1 -0
- package/dist/src/ds/components/ai/message-reveal/message-reveal.d.ts +22 -0
- package/dist/src/hooks/use-text-highlight.d.ts +18 -0
- package/dist/src/test/highlight-api.d.ts +28 -0
- package/dist/style.css +80 -0
- package/dist/use-reveal-Sa456jZb.cjs +70 -0
- package/dist/use-reveal-Sa456jZb.cjs.map +1 -0
- package/dist/use-reveal-d77hxHz9.js +68 -0
- package/dist/use-reveal-d77hxHz9.js.map +1 -0
- package/dist/use-text-highlight.css +8 -0
- package/package.json +8 -8
- package/dist/search-field-block-BqRM53jf.cjs.map +0 -1
- package/dist/search-field-block-CgrC6f9t.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flatten-to-search-text.es.js","sources":["../../../../src/domains/traces/utils/flatten-to-search-text.ts"],"sourcesContent":["/**\n * Flatten an arbitrary value into a single space-separated string containing\n * every searchable token it holds, however deeply nested.\n *\n * Built for span payloads whose shape is not known ahead of time (`attributes`,\n * `output`, `errorInfo`): the caller cannot enumerate fields, so this walks\n * whatever it is handed.\n *\n * **Keys are emitted alongside their values**, so a field name is searchable\n * even when its value is not — `{ error: null }` still answers a search for\n * `error`. The cost is that structural names present on every span (`traceId`,\n * `usage`, …) are searchable too, which makes short generic terms match widely.\n *\n * Values that no one can usefully search for are dropped rather than\n * stringified: `null`, `undefined`, `NaN`, infinities, functions, symbols,\n * invalid dates and whitespace-only strings. Dropping them keeps the output\n * free of noise words like `\"Invalid Date\"` that would produce false hits.\n * Array indices are dropped for the same reason — `0 1 2` is not content.\n *\n * Cycles are detected along the current path, so a self-referencing object\n * terminates while a value referenced twice as a sibling is emitted twice.\n * Only own, string-keyed properties are read, and a getter that throws is\n * skipped instead of taking the whole trace down.\n */\nexport function flattenToSearchText(value: unknown): string {\n const parts: string[] = [];\n const path = new Set<object>();\n\n collect(value, parts, path);\n\n return parts.join(' ');\n}\n\nfunction collect(value: unknown, parts: string[], path: Set<object>): void {\n if (value === null || value === undefined) return;\n\n switch (typeof value) {\n case 'string': {\n const trimmed = value.trim();\n if (trimmed) parts.push(trimmed);\n return;\n }\n case 'number': {\n // NaN and infinities have no useful search form.\n if (Number.isFinite(value)) parts.push(String(value));\n return;\n }\n case 'boolean':\n case 'bigint':\n parts.push(String(value));\n return;\n case 'function':\n case 'symbol':\n return;\n }\n\n const object = value as object;\n\n // Guard the current path only: a cycle must terminate, but the same object\n // referenced twice side by side is legitimately worth emitting twice.\n if (path.has(object)) return;\n path.add(object);\n\n try {\n collectFromObject(object, parts, path);\n } finally {\n path.delete(object);\n }\n}\n\nfunction collectFromObject(object: object, parts: string[], path: Set<object>): void {\n if (object instanceof Date) {\n const time = object.getTime();\n if (!Number.isNaN(time)) parts.push(object.toISOString());\n return;\n }\n\n if (object instanceof Error) {\n collect(object.message, parts, path);\n return;\n }\n\n // Indices carry no meaning, so an array contributes only its items.\n if (Array.isArray(object)) {\n for (const item of object) collect(item, parts, path);\n return;\n }\n\n if (object instanceof Map) {\n for (const [key, item] of object) {\n collect(key, parts, path);\n collect(item, parts, path);\n }\n return;\n }\n\n // A Set has members, not fields.\n if (object instanceof Set) {\n for (const item of object) collect(item, parts, path);\n return;\n }\n\n // Own string keys only: skips the prototype chain and symbol-keyed entries.\n for (const key of Object.keys(object)) {\n // The key is emitted even when the value turns out to be unsearchable, so\n // the presence of a field is itself findable.\n collect(key, parts, path);\n\n let item: unknown;\n try {\n item = (object as Record<string, unknown>)[key];\n } catch {\n // A getter that throws is not a reason to lose the rest of the payload.\n continue;\n }\n collect(item, parts, path);\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
|
+
|
|
5
|
+
const domains_traces_utils_flattenToSearchText = require('./flatten-to-search-text.cjs.js');
|
|
6
|
+
|
|
7
|
+
function toSearchableSpans(spans) {
|
|
8
|
+
return spans.map((span) => ({
|
|
9
|
+
...span,
|
|
10
|
+
// Computed from `span`, so a stale `searchText` on the input is overwritten
|
|
11
|
+
// rather than carried through by the spread.
|
|
12
|
+
searchText: domains_traces_utils_flattenToSearchText.flattenToSearchText(span).toLowerCase()
|
|
13
|
+
}));
|
|
14
|
+
}
|
|
15
|
+
function selectSearchableSpans(data) {
|
|
16
|
+
if (!data) return null;
|
|
17
|
+
return { ...data, spans: toSearchableSpans(data.spans) };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
exports.selectSearchableSpans = selectSearchableSpans;
|
|
21
|
+
exports.toSearchableSpans = toSearchableSpans;
|
|
22
|
+
//# sourceMappingURL=to-searchable-spans.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"to-searchable-spans.cjs.js","sources":["../../../../src/domains/traces/utils/to-searchable-spans.ts"],"sourcesContent":["import type { LightSpanRecord } from '@mastra/core/storage';\nimport type { SearchableSpan } from '../types';\nimport { flattenToSearchText } from './flatten-to-search-text';\n\n/**\n * Attach a precomputed search haystack to each span.\n *\n * Run this once, where the span list is resolved — not per keystroke. Flattening\n * walks every nested payload, so doing it inside a filter would repeat the whole\n * walk for every character typed.\n *\n * The whole record is flattened, which is what reaches `metadata` and `error`:\n * their shapes are open-ended, so no fixed list of fields can read them. The\n * text is lowercased here so matching is a bare `includes` with no per-span\n * `toLowerCase` on every keystroke.\n *\n * Inputs are left untouched; each result is a new object.\n */\nexport function toSearchableSpans(spans: LightSpanRecord[]): SearchableSpan[] {\n return spans.map(span => ({\n ...span,\n // Computed from `span`, so a stale `searchText` on the input is overwritten\n // rather than carried through by the spread.\n searchText: flattenToSearchText(span).toLowerCase(),\n }));\n}\n\n/**\n * React Query `select` for the `{ traceId, spans }` payload returned by\n * `getTraceLight` and `getBranch`.\n *\n * Enriching here rather than in a component means the flattening runs once per\n * fetch and is cached with the query, so it survives the panel unmounting and\n * remounting. Keep this a module-level reference: React Query re-runs `select`\n * whenever its identity changes, and an inline arrow would re-flatten the whole\n * trace on every render.\n *\n * Deliberately not generic: TypeScript cannot infer a query's `TData` from a\n * generic function passed as `select`, and silently falls back to the unselected\n * type — which would leave `searchText` missing at the call sites.\n *\n * `null` is passed through because a query may resolve to it. `undefined` is not\n * in the signature: React Query only runs `select` once data exists.\n */\nexport function selectSearchableSpans(\n data: { traceId: string; spans: LightSpanRecord[] } | null,\n): { traceId: string; spans: SearchableSpan[] } | null {\n if (!data) return null;\n\n return { ...data, spans: toSearchableSpans(data.spans) };\n}\n"],"names":["flattenToSearchText"],"mappings":";;;;;;AAkBO,SAAS,kBAAkB,KAAA,EAA4C;AAC5E,EAAA,OAAO,KAAA,CAAM,IAAI,CAAA,IAAA,MAAS;AAAA,IACxB,GAAG,IAAA;AAAA;AAAA;AAAA,IAGH,UAAA,EAAYA,4DAAA,CAAoB,IAAI,CAAA,CAAE,WAAA;AAAY,GACpD,CAAE,CAAA;AACJ;AAmBO,SAAS,sBACd,IAAA,EACqD;AACrD,EAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAElB,EAAA,OAAO,EAAE,GAAG,IAAA,EAAM,OAAO,iBAAA,CAAkB,IAAA,CAAK,KAAK,CAAA,EAAE;AACzD;;;;;"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { flattenToSearchText } from './flatten-to-search-text.es.js';
|
|
2
|
+
|
|
3
|
+
function toSearchableSpans(spans) {
|
|
4
|
+
return spans.map((span) => ({
|
|
5
|
+
...span,
|
|
6
|
+
// Computed from `span`, so a stale `searchText` on the input is overwritten
|
|
7
|
+
// rather than carried through by the spread.
|
|
8
|
+
searchText: flattenToSearchText(span).toLowerCase()
|
|
9
|
+
}));
|
|
10
|
+
}
|
|
11
|
+
function selectSearchableSpans(data) {
|
|
12
|
+
if (!data) return null;
|
|
13
|
+
return { ...data, spans: toSearchableSpans(data.spans) };
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export { selectSearchableSpans, toSearchableSpans };
|
|
17
|
+
//# sourceMappingURL=to-searchable-spans.es.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"to-searchable-spans.es.js","sources":["../../../../src/domains/traces/utils/to-searchable-spans.ts"],"sourcesContent":["import type { LightSpanRecord } from '@mastra/core/storage';\nimport type { SearchableSpan } from '../types';\nimport { flattenToSearchText } from './flatten-to-search-text';\n\n/**\n * Attach a precomputed search haystack to each span.\n *\n * Run this once, where the span list is resolved — not per keystroke. Flattening\n * walks every nested payload, so doing it inside a filter would repeat the whole\n * walk for every character typed.\n *\n * The whole record is flattened, which is what reaches `metadata` and `error`:\n * their shapes are open-ended, so no fixed list of fields can read them. The\n * text is lowercased here so matching is a bare `includes` with no per-span\n * `toLowerCase` on every keystroke.\n *\n * Inputs are left untouched; each result is a new object.\n */\nexport function toSearchableSpans(spans: LightSpanRecord[]): SearchableSpan[] {\n return spans.map(span => ({\n ...span,\n // Computed from `span`, so a stale `searchText` on the input is overwritten\n // rather than carried through by the spread.\n searchText: flattenToSearchText(span).toLowerCase(),\n }));\n}\n\n/**\n * React Query `select` for the `{ traceId, spans }` payload returned by\n * `getTraceLight` and `getBranch`.\n *\n * Enriching here rather than in a component means the flattening runs once per\n * fetch and is cached with the query, so it survives the panel unmounting and\n * remounting. Keep this a module-level reference: React Query re-runs `select`\n * whenever its identity changes, and an inline arrow would re-flatten the whole\n * trace on every render.\n *\n * Deliberately not generic: TypeScript cannot infer a query's `TData` from a\n * generic function passed as `select`, and silently falls back to the unselected\n * type — which would leave `searchText` missing at the call sites.\n *\n * `null` is passed through because a query may resolve to it. `undefined` is not\n * in the signature: React Query only runs `select` once data exists.\n */\nexport function selectSearchableSpans(\n data: { traceId: string; spans: LightSpanRecord[] } | null,\n): { traceId: string; spans: SearchableSpan[] } | null {\n if (!data) return null;\n\n return { ...data, spans: toSearchableSpans(data.spans) };\n}\n"],"names":[],"mappings":";;AAkBO,SAAS,kBAAkB,KAAA,EAA4C;AAC5E,EAAA,OAAO,KAAA,CAAM,IAAI,CAAA,IAAA,MAAS;AAAA,IACxB,GAAG,IAAA;AAAA;AAAA;AAAA,IAGH,UAAA,EAAY,mBAAA,CAAoB,IAAI,CAAA,CAAE,WAAA;AAAY,GACpD,CAAE,CAAA;AACJ;AAmBO,SAAS,sBACd,IAAA,EACqD;AACrD,EAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAElB,EAAA,OAAO,EAAE,GAAG,IAAA,EAAM,OAAO,iBAAA,CAAkB,IAAA,CAAK,KAAK,CAAA,EAAE;AACzD;;;;"}
|
|
@@ -2,10 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
4
|
|
|
5
|
+
const domains_traces_utils_filterSpansKeepingAncestors = require('./utils/filter-spans-keeping-ancestors.cjs.js');
|
|
6
|
+
const domains_traces_utils_flattenToSearchText = require('./utils/flatten-to-search-text.cjs.js');
|
|
7
|
+
const domains_traces_utils_toSearchableSpans = require('./utils/to-searchable-spans.cjs.js');
|
|
5
8
|
const domains_traces_utils_spanUtils = require('./utils/span-utils.cjs.js');
|
|
6
9
|
|
|
7
10
|
|
|
8
11
|
|
|
12
|
+
exports.filterSpansKeepingAncestors = domains_traces_utils_filterSpansKeepingAncestors.filterSpansKeepingAncestors;
|
|
13
|
+
exports.flattenToSearchText = domains_traces_utils_flattenToSearchText.flattenToSearchText;
|
|
14
|
+
exports.selectSearchableSpans = domains_traces_utils_toSearchableSpans.selectSearchableSpans;
|
|
15
|
+
exports.toSearchableSpans = domains_traces_utils_toSearchableSpans.toSearchableSpans;
|
|
9
16
|
exports.formatSpanDuration = domains_traces_utils_spanUtils.formatSpanDuration;
|
|
10
17
|
exports.getInputPreview = domains_traces_utils_spanUtils.getInputPreview;
|
|
11
18
|
exports.getTokenLimitMessage = domains_traces_utils_spanUtils.getTokenLimitMessage;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;"}
|
|
@@ -1,2 +1,5 @@
|
|
|
1
|
+
export { filterSpansKeepingAncestors } from './utils/filter-spans-keeping-ancestors.es.js';
|
|
2
|
+
export { flattenToSearchText } from './utils/flatten-to-search-text.es.js';
|
|
3
|
+
export { selectSearchableSpans, toSearchableSpans } from './utils/to-searchable-spans.es.js';
|
|
1
4
|
export { formatSpanDuration, getInputPreview, getTokenLimitMessage, isTokenLimitExceeded } from './utils/span-utils.es.js';
|
|
2
5
|
//# sourceMappingURL=utils.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.es.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"utils.es.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
|
|
@@ -28,6 +28,7 @@ const domains_traces_hooks_useDownloadTraceJson = require('./traces/hooks/use-do
|
|
|
28
28
|
const domains_traces_hooks_useSpanDetail = require('./traces/hooks/use-span-detail.cjs.js');
|
|
29
29
|
const domains_traces_hooks_useTraceLightSpans = require('./traces/hooks/use-trace-light-spans.cjs.js');
|
|
30
30
|
const domains_traces_hooks_useTraceOrBranchSpans = require('./traces/hooks/use-trace-or-branch-spans.cjs.js');
|
|
31
|
+
const domains_traces_hooks_useTraceSearch = require('./traces/hooks/use-trace-search.cjs.js');
|
|
31
32
|
const domains_traces_hooks_useTraceSpans = require('./traces/hooks/use-trace-spans.cjs.js');
|
|
32
33
|
const domains_traces_hooks_useTraces = require('./traces/hooks/use-traces.cjs.js');
|
|
33
34
|
const domains_traces_hooks_useTags = require('./traces/hooks/use-tags.cjs.js');
|
|
@@ -38,6 +39,9 @@ const domains_traces_hooks_useTraceSpanNavigation = require('./traces/hooks/use-
|
|
|
38
39
|
const domains_traces_hooks_useTraceListNavigation = require('./traces/hooks/use-trace-list-navigation.cjs.js');
|
|
39
40
|
const domains_traces_hooks_useTraceUrlState = require('./traces/hooks/use-trace-url-state.cjs.js');
|
|
40
41
|
const domains_traces_hooks_useTraceFilterPersistence = require('./traces/hooks/use-trace-filter-persistence.cjs.js');
|
|
42
|
+
const domains_traces_utils_filterSpansKeepingAncestors = require('./traces/utils/filter-spans-keeping-ancestors.cjs.js');
|
|
43
|
+
const domains_traces_utils_flattenToSearchText = require('./traces/utils/flatten-to-search-text.cjs.js');
|
|
44
|
+
const domains_traces_utils_toSearchableSpans = require('./traces/utils/to-searchable-spans.cjs.js');
|
|
41
45
|
const domains_traces_utils_spanUtils = require('./traces/utils/span-utils.cjs.js');
|
|
42
46
|
const domains_traces_traceFilters = require('./traces/trace-filters.cjs.js');
|
|
43
47
|
const domains_traces_types = require('./traces/types.cjs.js');
|
|
@@ -72,6 +76,7 @@ exports.useDownloadTraceJson = domains_traces_hooks_useDownloadTraceJson.useDown
|
|
|
72
76
|
exports.useSpanDetail = domains_traces_hooks_useSpanDetail.useSpanDetail;
|
|
73
77
|
exports.useTraceLightSpans = domains_traces_hooks_useTraceLightSpans.useTraceLightSpans;
|
|
74
78
|
exports.useTraceOrBranchSpans = domains_traces_hooks_useTraceOrBranchSpans.useTraceOrBranchSpans;
|
|
79
|
+
exports.useTraceSearch = domains_traces_hooks_useTraceSearch.useTraceSearch;
|
|
75
80
|
exports.useTraceSpans = domains_traces_hooks_useTraceSpans.useTraceSpans;
|
|
76
81
|
exports.useTraces = domains_traces_hooks_useTraces.useTraces;
|
|
77
82
|
exports.useTags = domains_traces_hooks_useTags.useTags;
|
|
@@ -82,6 +87,10 @@ exports.useTraceSpanNavigation = domains_traces_hooks_useTraceSpanNavigation.use
|
|
|
82
87
|
exports.useTraceListNavigation = domains_traces_hooks_useTraceListNavigation.useTraceListNavigation;
|
|
83
88
|
exports.useTraceUrlState = domains_traces_hooks_useTraceUrlState.useTraceUrlState;
|
|
84
89
|
exports.useTraceFilterPersistence = domains_traces_hooks_useTraceFilterPersistence.useTraceFilterPersistence;
|
|
90
|
+
exports.filterSpansKeepingAncestors = domains_traces_utils_filterSpansKeepingAncestors.filterSpansKeepingAncestors;
|
|
91
|
+
exports.flattenToSearchText = domains_traces_utils_flattenToSearchText.flattenToSearchText;
|
|
92
|
+
exports.selectSearchableSpans = domains_traces_utils_toSearchableSpans.selectSearchableSpans;
|
|
93
|
+
exports.toSearchableSpans = domains_traces_utils_toSearchableSpans.toSearchableSpans;
|
|
85
94
|
exports.formatSpanDuration = domains_traces_utils_spanUtils.formatSpanDuration;
|
|
86
95
|
exports.getInputPreview = domains_traces_utils_spanUtils.getInputPreview;
|
|
87
96
|
exports.getTokenLimitMessage = domains_traces_utils_spanUtils.getTokenLimitMessage;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"traces.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"traces.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -24,6 +24,7 @@ export { useDownloadTraceJson } from './traces/hooks/use-download-trace-json.es.
|
|
|
24
24
|
export { useSpanDetail } from './traces/hooks/use-span-detail.es.js';
|
|
25
25
|
export { useTraceLightSpans } from './traces/hooks/use-trace-light-spans.es.js';
|
|
26
26
|
export { useTraceOrBranchSpans } from './traces/hooks/use-trace-or-branch-spans.es.js';
|
|
27
|
+
export { useTraceSearch } from './traces/hooks/use-trace-search.es.js';
|
|
27
28
|
export { useTraceSpans } from './traces/hooks/use-trace-spans.es.js';
|
|
28
29
|
export { useTraces } from './traces/hooks/use-traces.es.js';
|
|
29
30
|
export { useTags } from './traces/hooks/use-tags.es.js';
|
|
@@ -34,6 +35,9 @@ export { useTraceSpanNavigation } from './traces/hooks/use-trace-span-navigation
|
|
|
34
35
|
export { useTraceListNavigation } from './traces/hooks/use-trace-list-navigation.es.js';
|
|
35
36
|
export { useTraceUrlState } from './traces/hooks/use-trace-url-state.es.js';
|
|
36
37
|
export { useTraceFilterPersistence } from './traces/hooks/use-trace-filter-persistence.es.js';
|
|
38
|
+
export { filterSpansKeepingAncestors } from './traces/utils/filter-spans-keeping-ancestors.es.js';
|
|
39
|
+
export { flattenToSearchText } from './traces/utils/flatten-to-search-text.es.js';
|
|
40
|
+
export { selectSearchableSpans, toSearchableSpans } from './traces/utils/to-searchable-spans.es.js';
|
|
37
41
|
export { formatSpanDuration, getInputPreview, getTokenLimitMessage, isTokenLimitExceeded } from './traces/utils/span-utils.es.js';
|
|
38
42
|
export { DEFAULT_TRACE_FILTERS_STORAGE_KEY, ROOT_ENTITY_TYPES, ROOT_ENTITY_TYPE_OPTIONS, TRACE_ANCHOR_SPAN_ID_PARAM, TRACE_DATE_FROM_PARAM, TRACE_DATE_PRESET_PARAM, TRACE_DATE_PRESET_VALUES, TRACE_DATE_TO_PARAM, TRACE_LIST_MODE_OPTIONS, TRACE_LIST_MODE_PARAM, TRACE_LIST_MODE_VALUES, TRACE_PROPERTY_FILTER_FIELD_IDS, TRACE_PROPERTY_FILTER_PARAM_BY_FIELD, TRACE_ROOT_ENTITY_TYPE_PARAM, TRACE_STATUS_OPTIONS, TRACE_STATUS_PARAM, TRACE_STATUS_VALUES, TRACE_SYNTHETIC_FILTER_FIELD_IDS, applyTracePropertyFilterTokens, buildTraceListFilters, clearSavedTraceFilters, createTracePropertyFilterFields, getPreservedTraceFilterParams, getTracePropertyFilterTokens, hasAnyTraceFilterParams, loadTraceFiltersFromStorage, neutralizeFilterTokens, saveTraceFiltersToStorage } from './traces/trace-filters.es.js';
|
|
39
43
|
export { CONTEXT_FIELD_IDS } from './traces/types.es.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"traces.es.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"traces.es.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -6,8 +6,8 @@ const jsxRuntime = require('react/jsx-runtime');
|
|
|
6
6
|
const domains_traces_components_spanDataPanelView = require('../../../domains/traces/components/span-data-panel-view.cjs.js');
|
|
7
7
|
const domains_traces_components_traceDetailsView = require('../../../domains/traces/components/trace-details-view.cjs.js');
|
|
8
8
|
const domains_traces_hooks_useSpanDetail = require('../../../domains/traces/hooks/use-span-detail.cjs.js');
|
|
9
|
-
const domains_traces_hooks_useTraceLightSpans = require('../../../domains/traces/hooks/use-trace-light-spans.cjs.js');
|
|
10
9
|
const domains_traces_hooks_useTraceSpanNavigation = require('../../../domains/traces/hooks/use-trace-span-navigation.cjs.js');
|
|
10
|
+
const domains_traces_hooks_useTraceSpans = require('../../../domains/traces/hooks/use-trace-spans.cjs.js');
|
|
11
11
|
const utils_cn = require('../../../cn-vA5sWo9W.cjs');
|
|
12
12
|
|
|
13
13
|
function TopicTraceDetailsPanel({
|
|
@@ -16,7 +16,7 @@ function TopicTraceDetailsPanel({
|
|
|
16
16
|
onSpanSelect,
|
|
17
17
|
onClose
|
|
18
18
|
}) {
|
|
19
|
-
const traceSpans =
|
|
19
|
+
const traceSpans = domains_traces_hooks_useTraceSpans.useTraceSpans(traceId);
|
|
20
20
|
const spanDetail = domains_traces_hooks_useSpanDetail.useSpanDetail(traceId, selectedSpanId);
|
|
21
21
|
const { handlePreviousSpan, handleNextSpan } = domains_traces_hooks_useTraceSpanNavigation.useTraceSpanNavigation(
|
|
22
22
|
traceSpans.data?.spans,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"topic-trace-details-panel.cjs.js","sources":["../../../../src/ee/topics/components/topic-trace-details-panel.tsx"],"sourcesContent":["import { SpanDataPanelView } from '@/domains/traces/components/span-data-panel-view';\nimport { TraceDetailsView } from '@/domains/traces/components/trace-details-view';\nimport { useSpanDetail } from '@/domains/traces/hooks/use-span-detail';\nimport {
|
|
1
|
+
{"version":3,"file":"topic-trace-details-panel.cjs.js","sources":["../../../../src/ee/topics/components/topic-trace-details-panel.tsx"],"sourcesContent":["import { SpanDataPanelView } from '@/domains/traces/components/span-data-panel-view';\nimport { TraceDetailsView } from '@/domains/traces/components/trace-details-view';\nimport { useSpanDetail } from '@/domains/traces/hooks/use-span-detail';\nimport { useTraceSpanNavigation } from '@/domains/traces/hooks/use-trace-span-navigation';\nimport { useTraceSpans } from '@/domains/traces/hooks/use-trace-spans';\nimport { cn } from '@/lib/utils';\n\nexport interface TopicTraceDetailsPanelProps {\n traceId: string | null;\n selectedSpanId?: string | null;\n onSpanSelect?: (spanId: string | undefined) => void;\n onClose: () => void;\n}\n\nexport function TopicTraceDetailsPanel({\n traceId,\n selectedSpanId,\n onSpanSelect,\n onClose,\n}: TopicTraceDetailsPanelProps) {\n const traceSpans = useTraceSpans(traceId);\n const spanDetail = useSpanDetail(traceId, selectedSpanId);\n const { handlePreviousSpan, handleNextSpan } = useTraceSpanNavigation(\n traceSpans.data?.spans,\n selectedSpanId,\n spanId => onSpanSelect?.(spanId),\n );\n\n if (!traceId) return null;\n\n return (\n <div\n className={cn(\n 'grid h-full min-h-0 overflow-auto',\n selectedSpanId ? 'grid-rows-[minmax(0,1fr)_minmax(0,1fr)] gap-4' : 'grid-rows-[minmax(0,1fr)]',\n )}\n >\n <TraceDetailsView\n traceId={traceId}\n spans={traceSpans.data?.spans}\n isLoading={traceSpans.isLoading}\n selectedSpanId={selectedSpanId}\n onSpanSelect={onSpanSelect}\n onClose={onClose}\n />\n {selectedSpanId ? (\n <SpanDataPanelView\n traceId={traceId}\n spanId={selectedSpanId}\n span={spanDetail.data?.span}\n isLoading={spanDetail.isLoading}\n onClose={() => onSpanSelect?.(undefined)}\n onPrevious={handlePreviousSpan}\n onNext={handleNextSpan}\n />\n ) : null}\n </div>\n );\n}\n"],"names":["useTraceSpans","useSpanDetail","useTraceSpanNavigation","jsxs","cn","jsx","TraceDetailsView","SpanDataPanelView"],"mappings":";;;;;;;;;;;;AAcO,SAAS,sBAAA,CAAuB;AAAA,EACrC,OAAA;AAAA,EACA,cAAA;AAAA,EACA,YAAA;AAAA,EACA;AACF,CAAA,EAAgC;AAC9B,EAAA,MAAM,UAAA,GAAaA,iDAAc,OAAO,CAAA;AACxC,EAAA,MAAM,UAAA,GAAaC,gDAAA,CAAc,OAAA,EAAS,cAAc,CAAA;AACxD,EAAA,MAAM,EAAE,kBAAA,EAAoB,cAAA,EAAe,GAAIC,kEAAA;AAAA,IAC7C,WAAW,IAAA,EAAM,KAAA;AAAA,IACjB,cAAA;AAAA,IACA,CAAA,MAAA,KAAU,eAAe,MAAM;AAAA,GACjC;AAEA,EAAA,IAAI,CAAC,SAAS,OAAO,IAAA;AAErB,EAAA,uBACEC,eAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAWC,WAAA;AAAA,QACT,mCAAA;AAAA,QACA,iBAAiB,+CAAA,GAAkD;AAAA,OACrE;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAAC,cAAA;AAAA,UAACC,2DAAA;AAAA,UAAA;AAAA,YACC,OAAA;AAAA,YACA,KAAA,EAAO,WAAW,IAAA,EAAM,KAAA;AAAA,YACxB,WAAW,UAAA,CAAW,SAAA;AAAA,YACtB,cAAA;AAAA,YACA,YAAA;AAAA,YACA;AAAA;AAAA,SACF;AAAA,QACC,cAAA,mBACCD,cAAA;AAAA,UAACE,6DAAA;AAAA,UAAA;AAAA,YACC,OAAA;AAAA,YACA,MAAA,EAAQ,cAAA;AAAA,YACR,IAAA,EAAM,WAAW,IAAA,EAAM,IAAA;AAAA,YACvB,WAAW,UAAA,CAAW,SAAA;AAAA,YACtB,OAAA,EAAS,MAAM,YAAA,GAAe,MAAS,CAAA;AAAA,YACvC,UAAA,EAAY,kBAAA;AAAA,YACZ,MAAA,EAAQ;AAAA;AAAA,SACV,GACE;AAAA;AAAA;AAAA,GACN;AAEJ;;;;"}
|
|
@@ -2,8 +2,8 @@ import { jsxs, jsx } from 'react/jsx-runtime';
|
|
|
2
2
|
import { SpanDataPanelView } from '../../../domains/traces/components/span-data-panel-view.es.js';
|
|
3
3
|
import { TraceDetailsView } from '../../../domains/traces/components/trace-details-view.es.js';
|
|
4
4
|
import { useSpanDetail } from '../../../domains/traces/hooks/use-span-detail.es.js';
|
|
5
|
-
import { useTraceLightSpans } from '../../../domains/traces/hooks/use-trace-light-spans.es.js';
|
|
6
5
|
import { useTraceSpanNavigation } from '../../../domains/traces/hooks/use-trace-span-navigation.es.js';
|
|
6
|
+
import { useTraceSpans } from '../../../domains/traces/hooks/use-trace-spans.es.js';
|
|
7
7
|
import { c as cn } from '../../../cn-BakJzhuv.js';
|
|
8
8
|
|
|
9
9
|
function TopicTraceDetailsPanel({
|
|
@@ -12,7 +12,7 @@ function TopicTraceDetailsPanel({
|
|
|
12
12
|
onSpanSelect,
|
|
13
13
|
onClose
|
|
14
14
|
}) {
|
|
15
|
-
const traceSpans =
|
|
15
|
+
const traceSpans = useTraceSpans(traceId);
|
|
16
16
|
const spanDetail = useSpanDetail(traceId, selectedSpanId);
|
|
17
17
|
const { handlePreviousSpan, handleNextSpan } = useTraceSpanNavigation(
|
|
18
18
|
traceSpans.data?.spans,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"topic-trace-details-panel.es.js","sources":["../../../../src/ee/topics/components/topic-trace-details-panel.tsx"],"sourcesContent":["import { SpanDataPanelView } from '@/domains/traces/components/span-data-panel-view';\nimport { TraceDetailsView } from '@/domains/traces/components/trace-details-view';\nimport { useSpanDetail } from '@/domains/traces/hooks/use-span-detail';\nimport {
|
|
1
|
+
{"version":3,"file":"topic-trace-details-panel.es.js","sources":["../../../../src/ee/topics/components/topic-trace-details-panel.tsx"],"sourcesContent":["import { SpanDataPanelView } from '@/domains/traces/components/span-data-panel-view';\nimport { TraceDetailsView } from '@/domains/traces/components/trace-details-view';\nimport { useSpanDetail } from '@/domains/traces/hooks/use-span-detail';\nimport { useTraceSpanNavigation } from '@/domains/traces/hooks/use-trace-span-navigation';\nimport { useTraceSpans } from '@/domains/traces/hooks/use-trace-spans';\nimport { cn } from '@/lib/utils';\n\nexport interface TopicTraceDetailsPanelProps {\n traceId: string | null;\n selectedSpanId?: string | null;\n onSpanSelect?: (spanId: string | undefined) => void;\n onClose: () => void;\n}\n\nexport function TopicTraceDetailsPanel({\n traceId,\n selectedSpanId,\n onSpanSelect,\n onClose,\n}: TopicTraceDetailsPanelProps) {\n const traceSpans = useTraceSpans(traceId);\n const spanDetail = useSpanDetail(traceId, selectedSpanId);\n const { handlePreviousSpan, handleNextSpan } = useTraceSpanNavigation(\n traceSpans.data?.spans,\n selectedSpanId,\n spanId => onSpanSelect?.(spanId),\n );\n\n if (!traceId) return null;\n\n return (\n <div\n className={cn(\n 'grid h-full min-h-0 overflow-auto',\n selectedSpanId ? 'grid-rows-[minmax(0,1fr)_minmax(0,1fr)] gap-4' : 'grid-rows-[minmax(0,1fr)]',\n )}\n >\n <TraceDetailsView\n traceId={traceId}\n spans={traceSpans.data?.spans}\n isLoading={traceSpans.isLoading}\n selectedSpanId={selectedSpanId}\n onSpanSelect={onSpanSelect}\n onClose={onClose}\n />\n {selectedSpanId ? (\n <SpanDataPanelView\n traceId={traceId}\n spanId={selectedSpanId}\n span={spanDetail.data?.span}\n isLoading={spanDetail.isLoading}\n onClose={() => onSpanSelect?.(undefined)}\n onPrevious={handlePreviousSpan}\n onNext={handleNextSpan}\n />\n ) : null}\n </div>\n );\n}\n"],"names":[],"mappings":";;;;;;;;AAcO,SAAS,sBAAA,CAAuB;AAAA,EACrC,OAAA;AAAA,EACA,cAAA;AAAA,EACA,YAAA;AAAA,EACA;AACF,CAAA,EAAgC;AAC9B,EAAA,MAAM,UAAA,GAAa,cAAc,OAAO,CAAA;AACxC,EAAA,MAAM,UAAA,GAAa,aAAA,CAAc,OAAA,EAAS,cAAc,CAAA;AACxD,EAAA,MAAM,EAAE,kBAAA,EAAoB,cAAA,EAAe,GAAI,sBAAA;AAAA,IAC7C,WAAW,IAAA,EAAM,KAAA;AAAA,IACjB,cAAA;AAAA,IACA,CAAA,MAAA,KAAU,eAAe,MAAM;AAAA,GACjC;AAEA,EAAA,IAAI,CAAC,SAAS,OAAO,IAAA;AAErB,EAAA,uBACE,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA;AAAA,QACT,mCAAA;AAAA,QACA,iBAAiB,+CAAA,GAAkD;AAAA,OACrE;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAA,GAAA;AAAA,UAAC,gBAAA;AAAA,UAAA;AAAA,YACC,OAAA;AAAA,YACA,KAAA,EAAO,WAAW,IAAA,EAAM,KAAA;AAAA,YACxB,WAAW,UAAA,CAAW,SAAA;AAAA,YACtB,cAAA;AAAA,YACA,YAAA;AAAA,YACA;AAAA;AAAA,SACF;AAAA,QACC,cAAA,mBACC,GAAA;AAAA,UAAC,iBAAA;AAAA,UAAA;AAAA,YACC,OAAA;AAAA,YACA,MAAA,EAAQ,cAAA;AAAA,YACR,IAAA,EAAM,WAAW,IAAA,EAAM,IAAA;AAAA,YACvB,WAAW,UAAA,CAAW,SAAA;AAAA,YACtB,OAAA,EAAS,MAAM,YAAA,GAAe,MAAS,CAAA;AAAA,YACvC,UAAA,EAAY,kBAAA;AAAA,YACZ,MAAA,EAAQ;AAAA;AAAA,SACV,GACE;AAAA;AAAA;AAAA,GACN;AAEJ;;;;"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
|
+
|
|
5
|
+
require('../use-text-highlight.css');const React = require('react');
|
|
6
|
+
const hooks_useIsomorphicLayoutEffect = require('./use-isomorphic-layout-effect.cjs.js');
|
|
7
|
+
|
|
8
|
+
const HIGHLIGHT_NAME = "search-result";
|
|
9
|
+
const MIN_SEARCH_LENGTH = 2;
|
|
10
|
+
const INCLUDED_SELECTOR = "[data-highlight]";
|
|
11
|
+
function escapeRegExp(value) {
|
|
12
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
13
|
+
}
|
|
14
|
+
function useTextHighlight(search) {
|
|
15
|
+
const [root, setRoot] = React.useState(null);
|
|
16
|
+
hooks_useIsomorphicLayoutEffect.useIsomorphicLayoutEffect(() => {
|
|
17
|
+
if (!root || search.trim().length < MIN_SEARCH_LENGTH || typeof CSS === "undefined" || !("highlights" in CSS) || typeof StaticRange === "undefined") {
|
|
18
|
+
CSS?.highlights?.delete(HIGHLIGHT_NAME);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
let animationFrame = null;
|
|
22
|
+
const updateHighlight = () => {
|
|
23
|
+
const ranges = [];
|
|
24
|
+
const regex = new RegExp(escapeRegExp(search), "giu");
|
|
25
|
+
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
|
|
26
|
+
acceptNode(node) {
|
|
27
|
+
const parent = node.parentElement;
|
|
28
|
+
return parent.closest(INCLUDED_SELECTOR) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
while (walker.nextNode()) {
|
|
32
|
+
const textNode = walker.currentNode;
|
|
33
|
+
regex.lastIndex = 0;
|
|
34
|
+
let match;
|
|
35
|
+
while ((match = regex.exec(textNode.data)) !== null) {
|
|
36
|
+
ranges.push(
|
|
37
|
+
new StaticRange({
|
|
38
|
+
startContainer: textNode,
|
|
39
|
+
startOffset: match.index,
|
|
40
|
+
endContainer: textNode,
|
|
41
|
+
endOffset: match.index + match[0].length
|
|
42
|
+
})
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
CSS.highlights.set(HIGHLIGHT_NAME, new Highlight(...ranges));
|
|
47
|
+
};
|
|
48
|
+
const scheduleUpdate = () => {
|
|
49
|
+
if (animationFrame !== null) cancelAnimationFrame(animationFrame);
|
|
50
|
+
animationFrame = requestAnimationFrame(() => {
|
|
51
|
+
animationFrame = null;
|
|
52
|
+
updateHighlight();
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
updateHighlight();
|
|
56
|
+
const observer = new MutationObserver(scheduleUpdate);
|
|
57
|
+
observer.observe(root, { subtree: true, childList: true, characterData: true });
|
|
58
|
+
return () => {
|
|
59
|
+
observer.disconnect();
|
|
60
|
+
if (animationFrame !== null) cancelAnimationFrame(animationFrame);
|
|
61
|
+
CSS.highlights.delete(HIGHLIGHT_NAME);
|
|
62
|
+
};
|
|
63
|
+
}, [root, search]);
|
|
64
|
+
return { ref: setRoot };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
exports.useTextHighlight = useTextHighlight;
|
|
68
|
+
//# sourceMappingURL=use-text-highlight.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-text-highlight.cjs.js","sources":["../../src/hooks/use-text-highlight.ts"],"sourcesContent":["import { useState } from 'react';\nimport type { RefCallback } from 'react';\n\nimport { useIsomorphicLayoutEffect } from './use-isomorphic-layout-effect';\nimport './use-text-highlight.css';\n\n/** Single registry entry, so only one search surface can be highlighted at a time. */\nconst HIGHLIGHT_NAME = 'search-result';\n\n/**\n * A single character matches almost everywhere, which paints noise instead of results.\n * Highlighting only starts once the term is discriminating enough.\n */\nconst MIN_SEARCH_LENGTH = 2;\n\n/**\n * Opt-in marker: only text inside a `data-highlight` subtree can be painted. Highlighting\n * is a claim about which text is searchable, so surfaces state it explicitly rather than\n * having every piece of surrounding chrome remember to opt out.\n */\nconst INCLUDED_SELECTOR = '[data-highlight]';\n\nfunction escapeRegExp(value: string) {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nexport interface UseTextHighlightResult<TElement extends HTMLElement> {\n ref: RefCallback<TElement>;\n}\n\n/**\n * Paints every occurrence of `search` inside the referenced subtree using the CSS Custom\n * Highlight API. Only text under an element carrying `data-highlight` is painted, so a\n * surface names its searchable regions and everything else — headers, labels, metadata —\n * is left alone by default. The DOM is never mutated — no wrapper elements are injected — so text\n * selection, copy/paste and virtualised renderers are unaffected. Styling lives in\n * `use-text-highlight.css` (`::highlight(search-result)`).\n *\n * Terms shorter than two characters are ignored — they match too much to be useful.\n * Matching is case-insensitive and literal (the term is escaped, not a pattern). The\n * subtree is re-scanned on content changes, coalesced to one scan per frame. Browsers\n * without the API simply render nothing highlighted.\n */\nexport function useTextHighlight<TElement extends HTMLElement = HTMLElement>(\n search: string,\n): UseTextHighlightResult<TElement> {\n const [root, setRoot] = useState<TElement | null>(null);\n\n useIsomorphicLayoutEffect(() => {\n if (\n !root ||\n search.trim().length < MIN_SEARCH_LENGTH ||\n typeof CSS === 'undefined' ||\n !('highlights' in CSS) ||\n typeof StaticRange === 'undefined'\n ) {\n CSS?.highlights?.delete(HIGHLIGHT_NAME);\n return;\n }\n\n let animationFrame: number | null = null;\n\n const updateHighlight = () => {\n const ranges: StaticRange[] = [];\n const regex = new RegExp(escapeRegExp(search), 'giu');\n\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {\n acceptNode(node) {\n // Inside a rooted walker every text node has a parent element.\n const parent = node.parentElement as HTMLElement;\n return parent.closest(INCLUDED_SELECTOR) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;\n },\n });\n\n while (walker.nextNode()) {\n const textNode = walker.currentNode as Text;\n regex.lastIndex = 0;\n\n let match: RegExpExecArray | null;\n while ((match = regex.exec(textNode.data)) !== null) {\n ranges.push(\n new StaticRange({\n startContainer: textNode,\n startOffset: match.index,\n endContainer: textNode,\n endOffset: match.index + match[0].length,\n }),\n );\n }\n }\n\n CSS.highlights.set(HIGHLIGHT_NAME, new Highlight(...ranges));\n };\n\n const scheduleUpdate = () => {\n if (animationFrame !== null) cancelAnimationFrame(animationFrame);\n\n animationFrame = requestAnimationFrame(() => {\n animationFrame = null;\n updateHighlight();\n });\n };\n\n updateHighlight();\n\n const observer = new MutationObserver(scheduleUpdate);\n observer.observe(root, { subtree: true, childList: true, characterData: true });\n\n return () => {\n observer.disconnect();\n if (animationFrame !== null) cancelAnimationFrame(animationFrame);\n CSS.highlights.delete(HIGHLIGHT_NAME);\n };\n }, [root, search]);\n\n return { ref: setRoot };\n}\n"],"names":["useState","useIsomorphicLayoutEffect"],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { useIsomorphicLayoutEffect } from './use-isomorphic-layout-effect.es.js';
|
|
3
|
+
|
|
4
|
+
import '../use-text-highlight.css';const HIGHLIGHT_NAME = "search-result";
|
|
5
|
+
const MIN_SEARCH_LENGTH = 2;
|
|
6
|
+
const INCLUDED_SELECTOR = "[data-highlight]";
|
|
7
|
+
function escapeRegExp(value) {
|
|
8
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
9
|
+
}
|
|
10
|
+
function useTextHighlight(search) {
|
|
11
|
+
const [root, setRoot] = useState(null);
|
|
12
|
+
useIsomorphicLayoutEffect(() => {
|
|
13
|
+
if (!root || search.trim().length < MIN_SEARCH_LENGTH || typeof CSS === "undefined" || !("highlights" in CSS) || typeof StaticRange === "undefined") {
|
|
14
|
+
CSS?.highlights?.delete(HIGHLIGHT_NAME);
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
let animationFrame = null;
|
|
18
|
+
const updateHighlight = () => {
|
|
19
|
+
const ranges = [];
|
|
20
|
+
const regex = new RegExp(escapeRegExp(search), "giu");
|
|
21
|
+
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
|
|
22
|
+
acceptNode(node) {
|
|
23
|
+
const parent = node.parentElement;
|
|
24
|
+
return parent.closest(INCLUDED_SELECTOR) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
while (walker.nextNode()) {
|
|
28
|
+
const textNode = walker.currentNode;
|
|
29
|
+
regex.lastIndex = 0;
|
|
30
|
+
let match;
|
|
31
|
+
while ((match = regex.exec(textNode.data)) !== null) {
|
|
32
|
+
ranges.push(
|
|
33
|
+
new StaticRange({
|
|
34
|
+
startContainer: textNode,
|
|
35
|
+
startOffset: match.index,
|
|
36
|
+
endContainer: textNode,
|
|
37
|
+
endOffset: match.index + match[0].length
|
|
38
|
+
})
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
CSS.highlights.set(HIGHLIGHT_NAME, new Highlight(...ranges));
|
|
43
|
+
};
|
|
44
|
+
const scheduleUpdate = () => {
|
|
45
|
+
if (animationFrame !== null) cancelAnimationFrame(animationFrame);
|
|
46
|
+
animationFrame = requestAnimationFrame(() => {
|
|
47
|
+
animationFrame = null;
|
|
48
|
+
updateHighlight();
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
updateHighlight();
|
|
52
|
+
const observer = new MutationObserver(scheduleUpdate);
|
|
53
|
+
observer.observe(root, { subtree: true, childList: true, characterData: true });
|
|
54
|
+
return () => {
|
|
55
|
+
observer.disconnect();
|
|
56
|
+
if (animationFrame !== null) cancelAnimationFrame(animationFrame);
|
|
57
|
+
CSS.highlights.delete(HIGHLIGHT_NAME);
|
|
58
|
+
};
|
|
59
|
+
}, [root, search]);
|
|
60
|
+
return { ref: setRoot };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export { useTextHighlight };
|
|
64
|
+
//# sourceMappingURL=use-text-highlight.es.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-text-highlight.es.js","sources":["../../src/hooks/use-text-highlight.ts"],"sourcesContent":["import { useState } from 'react';\nimport type { RefCallback } from 'react';\n\nimport { useIsomorphicLayoutEffect } from './use-isomorphic-layout-effect';\nimport './use-text-highlight.css';\n\n/** Single registry entry, so only one search surface can be highlighted at a time. */\nconst HIGHLIGHT_NAME = 'search-result';\n\n/**\n * A single character matches almost everywhere, which paints noise instead of results.\n * Highlighting only starts once the term is discriminating enough.\n */\nconst MIN_SEARCH_LENGTH = 2;\n\n/**\n * Opt-in marker: only text inside a `data-highlight` subtree can be painted. Highlighting\n * is a claim about which text is searchable, so surfaces state it explicitly rather than\n * having every piece of surrounding chrome remember to opt out.\n */\nconst INCLUDED_SELECTOR = '[data-highlight]';\n\nfunction escapeRegExp(value: string) {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nexport interface UseTextHighlightResult<TElement extends HTMLElement> {\n ref: RefCallback<TElement>;\n}\n\n/**\n * Paints every occurrence of `search` inside the referenced subtree using the CSS Custom\n * Highlight API. Only text under an element carrying `data-highlight` is painted, so a\n * surface names its searchable regions and everything else — headers, labels, metadata —\n * is left alone by default. The DOM is never mutated — no wrapper elements are injected — so text\n * selection, copy/paste and virtualised renderers are unaffected. Styling lives in\n * `use-text-highlight.css` (`::highlight(search-result)`).\n *\n * Terms shorter than two characters are ignored — they match too much to be useful.\n * Matching is case-insensitive and literal (the term is escaped, not a pattern). The\n * subtree is re-scanned on content changes, coalesced to one scan per frame. Browsers\n * without the API simply render nothing highlighted.\n */\nexport function useTextHighlight<TElement extends HTMLElement = HTMLElement>(\n search: string,\n): UseTextHighlightResult<TElement> {\n const [root, setRoot] = useState<TElement | null>(null);\n\n useIsomorphicLayoutEffect(() => {\n if (\n !root ||\n search.trim().length < MIN_SEARCH_LENGTH ||\n typeof CSS === 'undefined' ||\n !('highlights' in CSS) ||\n typeof StaticRange === 'undefined'\n ) {\n CSS?.highlights?.delete(HIGHLIGHT_NAME);\n return;\n }\n\n let animationFrame: number | null = null;\n\n const updateHighlight = () => {\n const ranges: StaticRange[] = [];\n const regex = new RegExp(escapeRegExp(search), 'giu');\n\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {\n acceptNode(node) {\n // Inside a rooted walker every text node has a parent element.\n const parent = node.parentElement as HTMLElement;\n return parent.closest(INCLUDED_SELECTOR) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;\n },\n });\n\n while (walker.nextNode()) {\n const textNode = walker.currentNode as Text;\n regex.lastIndex = 0;\n\n let match: RegExpExecArray | null;\n while ((match = regex.exec(textNode.data)) !== null) {\n ranges.push(\n new StaticRange({\n startContainer: textNode,\n startOffset: match.index,\n endContainer: textNode,\n endOffset: match.index + match[0].length,\n }),\n );\n }\n }\n\n CSS.highlights.set(HIGHLIGHT_NAME, new Highlight(...ranges));\n };\n\n const scheduleUpdate = () => {\n if (animationFrame !== null) cancelAnimationFrame(animationFrame);\n\n animationFrame = requestAnimationFrame(() => {\n animationFrame = null;\n updateHighlight();\n });\n };\n\n updateHighlight();\n\n const observer = new MutationObserver(scheduleUpdate);\n observer.observe(root, { subtree: true, childList: true, characterData: true });\n\n return () => {\n observer.disconnect();\n if (animationFrame !== null) cancelAnimationFrame(animationFrame);\n CSS.highlights.delete(HIGHLIGHT_NAME);\n };\n }, [root, search]);\n\n return { ref: setRoot };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -26,9 +26,14 @@ function SearchFieldBlock({
|
|
|
26
26
|
size,
|
|
27
27
|
variant,
|
|
28
28
|
isMinimized,
|
|
29
|
-
onMinimizedChange
|
|
29
|
+
onMinimizedChange,
|
|
30
|
+
inputRef: externalInputRef
|
|
30
31
|
}) {
|
|
31
32
|
const inputRef = React.useRef(null);
|
|
33
|
+
const setInputRef = (element) => {
|
|
34
|
+
inputRef.current = element;
|
|
35
|
+
if (externalInputRef) externalInputRef.current = element;
|
|
36
|
+
};
|
|
32
37
|
const buttonSize = size === "default" ? "lg" : size;
|
|
33
38
|
React.useEffect(() => {
|
|
34
39
|
if (isMinimized === false) {
|
|
@@ -58,7 +63,7 @@ function SearchFieldBlock({
|
|
|
58
63
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
59
64
|
input.Input,
|
|
60
65
|
{
|
|
61
|
-
ref:
|
|
66
|
+
ref: setInputRef,
|
|
62
67
|
id: `input-${name}`,
|
|
63
68
|
name,
|
|
64
69
|
disabled,
|
|
@@ -114,4 +119,4 @@ function SearchFieldBlock({
|
|
|
114
119
|
}
|
|
115
120
|
|
|
116
121
|
exports.SearchFieldBlock = SearchFieldBlock;
|
|
117
|
-
//# sourceMappingURL=search-field-block-
|
|
122
|
+
//# sourceMappingURL=search-field-block-CjCIzUhN.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-field-block-CjCIzUhN.cjs","sources":["../src/ds/components/FormFieldBlocks/fields/search-field-block.tsx"],"sourcesContent":["import { SearchIcon, XIcon } from 'lucide-react';\nimport { useEffect, useRef, type RefObject } from 'react';\nimport { Button } from '../../Button';\nimport { Input } from '../../Input';\nimport type { InputProps } from '../../Input';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '../../Tooltip';\nimport { FieldBlock } from '../block/field-block';\nimport { cn } from '@/lib/utils';\n\nexport type SearchFieldBlockProps = {\n name: string;\n testId?: string;\n label?: string;\n labelIsHidden?: boolean;\n required?: boolean;\n disabled?: boolean;\n value?: string;\n placeholder?: string;\n onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;\n onReset?: () => void;\n helpText?: string;\n error?: boolean;\n errorMsg?: string;\n layout?: 'horizontal' | 'vertical';\n className?: string;\n size?: InputProps['size'];\n variant?: InputProps['variant'];\n isMinimized?: boolean;\n onMinimizedChange?: (minimized: boolean) => void;\n /** Gives the caller access to the underlying input, e.g. to focus it from a keyboard shortcut. */\n inputRef?: RefObject<HTMLInputElement | null>;\n};\n\nexport function SearchFieldBlock({\n name,\n helpText,\n errorMsg,\n required = false,\n disabled = false,\n value,\n label,\n labelIsHidden = false,\n layout = 'vertical',\n placeholder = 'Search...',\n onChange,\n onReset,\n className,\n size,\n variant,\n isMinimized,\n onMinimizedChange,\n inputRef: externalInputRef,\n}: SearchFieldBlockProps) {\n const inputRef = useRef<HTMLInputElement>(null);\n\n const setInputRef = (element: HTMLInputElement | null) => {\n inputRef.current = element;\n if (externalInputRef) externalInputRef.current = element;\n };\n const buttonSize = size === 'default' ? 'lg' : size;\n\n useEffect(() => {\n if (isMinimized === false) {\n inputRef.current?.focus();\n }\n }, [isMinimized]);\n\n if (isMinimized) {\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n size={buttonSize || 'sm'}\n aria-label={label || 'Search'}\n disabled={disabled}\n onClick={() => onMinimizedChange?.(false)}\n >\n <SearchIcon />\n </Button>\n </TooltipTrigger>\n <TooltipContent>{label || 'Search'}</TooltipContent>\n </Tooltip>\n );\n }\n\n return (\n <FieldBlock.Layout layout={layout} className={className}>\n {layout === 'horizontal' ? (\n <FieldBlock.Column className={labelIsHidden ? 'sr-only' : undefined}>\n <FieldBlock.Label name={name} required={required}>\n {label}\n </FieldBlock.Label>\n </FieldBlock.Column>\n ) : null}\n <FieldBlock.Column className={layout === 'horizontal' && labelIsHidden ? 'col-span-full' : undefined}>\n {layout === 'vertical' && label ? (\n <FieldBlock.Label name={name} required={required} className={labelIsHidden ? 'sr-only' : undefined}>\n {label}\n </FieldBlock.Label>\n ) : null}\n <div className=\"group relative\">\n <Input\n ref={setInputRef}\n id={`input-${name}`}\n name={name}\n disabled={disabled}\n value={value}\n placeholder={placeholder}\n onChange={onChange}\n size={size}\n variant={variant}\n className={cn(\n size === 'sm' && 'px-8',\n size === 'md' && 'px-9',\n (!size || size === 'default') && 'px-10',\n size === 'lg' && 'px-11',\n )}\n />\n <SearchIcon\n aria-hidden=\"true\"\n className={cn(\n 'absolute top-1/2 left-3 -translate-y-1/2 text-neutral4 opacity-50 group-has-focus:opacity-100',\n size === 'sm' && 'size-3.5',\n size === 'md' && 'size-4',\n (!size || size === 'default') && 'size-[1.125rem]',\n size === 'lg' && 'size-5',\n )}\n />\n {onReset && (value || isMinimized === false) && (\n <Button\n variant=\"ghost\"\n size={buttonSize || 'lg'}\n aria-label=\"Clear search\"\n onClick={() => {\n if (value) {\n onReset();\n }\n if (isMinimized === false) {\n onMinimizedChange?.(true);\n }\n }}\n className=\"absolute top-1/2 right-0 -translate-y-1/2\"\n >\n <XIcon />\n </Button>\n )}\n </div>\n {helpText && <FieldBlock.HelpText>{helpText}</FieldBlock.HelpText>}\n {errorMsg && <FieldBlock.ErrorMsg>{errorMsg}</FieldBlock.ErrorMsg>}\n </FieldBlock.Column>\n </FieldBlock.Layout>\n );\n}\n"],"names":["useRef","useEffect","Tooltip","jsx","TooltipTrigger","Button","SearchIcon","TooltipContent","jsxs","FieldBlock","Input","cn","XIcon"],"mappings":"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"}
|
|
@@ -24,9 +24,14 @@ function SearchFieldBlock({
|
|
|
24
24
|
size,
|
|
25
25
|
variant,
|
|
26
26
|
isMinimized,
|
|
27
|
-
onMinimizedChange
|
|
27
|
+
onMinimizedChange,
|
|
28
|
+
inputRef: externalInputRef
|
|
28
29
|
}) {
|
|
29
30
|
const inputRef = useRef(null);
|
|
31
|
+
const setInputRef = (element) => {
|
|
32
|
+
inputRef.current = element;
|
|
33
|
+
if (externalInputRef) externalInputRef.current = element;
|
|
34
|
+
};
|
|
30
35
|
const buttonSize = size === "default" ? "lg" : size;
|
|
31
36
|
useEffect(() => {
|
|
32
37
|
if (isMinimized === false) {
|
|
@@ -56,7 +61,7 @@ function SearchFieldBlock({
|
|
|
56
61
|
/* @__PURE__ */ jsx(
|
|
57
62
|
Input,
|
|
58
63
|
{
|
|
59
|
-
ref:
|
|
64
|
+
ref: setInputRef,
|
|
60
65
|
id: `input-${name}`,
|
|
61
66
|
name,
|
|
62
67
|
disabled,
|
|
@@ -112,4 +117,4 @@ function SearchFieldBlock({
|
|
|
112
117
|
}
|
|
113
118
|
|
|
114
119
|
export { SearchFieldBlock as S };
|
|
115
|
-
//# sourceMappingURL=search-field-block-
|
|
120
|
+
//# sourceMappingURL=search-field-block-DoNywsJC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-field-block-DoNywsJC.js","sources":["../src/ds/components/FormFieldBlocks/fields/search-field-block.tsx"],"sourcesContent":["import { SearchIcon, XIcon } from 'lucide-react';\nimport { useEffect, useRef, type RefObject } from 'react';\nimport { Button } from '../../Button';\nimport { Input } from '../../Input';\nimport type { InputProps } from '../../Input';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '../../Tooltip';\nimport { FieldBlock } from '../block/field-block';\nimport { cn } from '@/lib/utils';\n\nexport type SearchFieldBlockProps = {\n name: string;\n testId?: string;\n label?: string;\n labelIsHidden?: boolean;\n required?: boolean;\n disabled?: boolean;\n value?: string;\n placeholder?: string;\n onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;\n onReset?: () => void;\n helpText?: string;\n error?: boolean;\n errorMsg?: string;\n layout?: 'horizontal' | 'vertical';\n className?: string;\n size?: InputProps['size'];\n variant?: InputProps['variant'];\n isMinimized?: boolean;\n onMinimizedChange?: (minimized: boolean) => void;\n /** Gives the caller access to the underlying input, e.g. to focus it from a keyboard shortcut. */\n inputRef?: RefObject<HTMLInputElement | null>;\n};\n\nexport function SearchFieldBlock({\n name,\n helpText,\n errorMsg,\n required = false,\n disabled = false,\n value,\n label,\n labelIsHidden = false,\n layout = 'vertical',\n placeholder = 'Search...',\n onChange,\n onReset,\n className,\n size,\n variant,\n isMinimized,\n onMinimizedChange,\n inputRef: externalInputRef,\n}: SearchFieldBlockProps) {\n const inputRef = useRef<HTMLInputElement>(null);\n\n const setInputRef = (element: HTMLInputElement | null) => {\n inputRef.current = element;\n if (externalInputRef) externalInputRef.current = element;\n };\n const buttonSize = size === 'default' ? 'lg' : size;\n\n useEffect(() => {\n if (isMinimized === false) {\n inputRef.current?.focus();\n }\n }, [isMinimized]);\n\n if (isMinimized) {\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n size={buttonSize || 'sm'}\n aria-label={label || 'Search'}\n disabled={disabled}\n onClick={() => onMinimizedChange?.(false)}\n >\n <SearchIcon />\n </Button>\n </TooltipTrigger>\n <TooltipContent>{label || 'Search'}</TooltipContent>\n </Tooltip>\n );\n }\n\n return (\n <FieldBlock.Layout layout={layout} className={className}>\n {layout === 'horizontal' ? (\n <FieldBlock.Column className={labelIsHidden ? 'sr-only' : undefined}>\n <FieldBlock.Label name={name} required={required}>\n {label}\n </FieldBlock.Label>\n </FieldBlock.Column>\n ) : null}\n <FieldBlock.Column className={layout === 'horizontal' && labelIsHidden ? 'col-span-full' : undefined}>\n {layout === 'vertical' && label ? (\n <FieldBlock.Label name={name} required={required} className={labelIsHidden ? 'sr-only' : undefined}>\n {label}\n </FieldBlock.Label>\n ) : null}\n <div className=\"group relative\">\n <Input\n ref={setInputRef}\n id={`input-${name}`}\n name={name}\n disabled={disabled}\n value={value}\n placeholder={placeholder}\n onChange={onChange}\n size={size}\n variant={variant}\n className={cn(\n size === 'sm' && 'px-8',\n size === 'md' && 'px-9',\n (!size || size === 'default') && 'px-10',\n size === 'lg' && 'px-11',\n )}\n />\n <SearchIcon\n aria-hidden=\"true\"\n className={cn(\n 'absolute top-1/2 left-3 -translate-y-1/2 text-neutral4 opacity-50 group-has-focus:opacity-100',\n size === 'sm' && 'size-3.5',\n size === 'md' && 'size-4',\n (!size || size === 'default') && 'size-[1.125rem]',\n size === 'lg' && 'size-5',\n )}\n />\n {onReset && (value || isMinimized === false) && (\n <Button\n variant=\"ghost\"\n size={buttonSize || 'lg'}\n aria-label=\"Clear search\"\n onClick={() => {\n if (value) {\n onReset();\n }\n if (isMinimized === false) {\n onMinimizedChange?.(true);\n }\n }}\n className=\"absolute top-1/2 right-0 -translate-y-1/2\"\n >\n <XIcon />\n </Button>\n )}\n </div>\n {helpText && <FieldBlock.HelpText>{helpText}</FieldBlock.HelpText>}\n {errorMsg && <FieldBlock.ErrorMsg>{errorMsg}</FieldBlock.ErrorMsg>}\n </FieldBlock.Column>\n </FieldBlock.Layout>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { LightSpanRecord } from '@mastra/core/storage';
|
|
2
1
|
import { ReactNode } from 'react';
|
|
3
2
|
import { TraceUsageSummary } from '../trace-list-columns';
|
|
3
|
+
import { SearchableSpan } from '../types';
|
|
4
4
|
import { LinkComponent } from '../../../ds/types/link-component';
|
|
5
5
|
export type TraceDataPanelPlacement = 'traces-list' | 'trace-page';
|
|
6
6
|
export type TraceDataPanelTab = 'details' | 'scores' | 'feedback';
|
|
7
7
|
export interface TraceDataPanelViewProps {
|
|
8
8
|
traceId: string;
|
|
9
9
|
/** Lightweight spans for the trace. Caller fetches via useTraceLightSpans. */
|
|
10
|
-
spans:
|
|
10
|
+
spans: SearchableSpan[] | undefined;
|
|
11
11
|
/**
|
|
12
12
|
* Token and estimated-cost totals for the trace (from `useTraceUsage`).
|
|
13
13
|
* Rendered in the trace summary when the panel is in the list side-panel
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Dispatch, SetStateAction } from 'react';
|
|
1
|
+
import { Dispatch, ReactNode, SetStateAction } from 'react';
|
|
2
2
|
import { UISpan } from '../types';
|
|
3
3
|
type TraceTimelineProps = {
|
|
4
4
|
hierarchicalSpans: UISpan[];
|
|
@@ -10,6 +10,8 @@ type TraceTimelineProps = {
|
|
|
10
10
|
setExpandedSpanIds?: Dispatch<SetStateAction<string[]>>;
|
|
11
11
|
featuredSpanIds?: string[];
|
|
12
12
|
chartWidth?: 'wide' | 'default';
|
|
13
|
+
/** Rendered on the left of the span type legend row. */
|
|
14
|
+
leadingSlot?: ReactNode;
|
|
13
15
|
};
|
|
14
|
-
export declare function TraceTimeline({ hierarchicalSpans, onSpanClick, selectedSpanId, isLoading, fadedTypes, expandedSpanIds, setExpandedSpanIds, featuredSpanIds, chartWidth, }: TraceTimelineProps): import("react").JSX.Element;
|
|
16
|
+
export declare function TraceTimeline({ hierarchicalSpans, onSpanClick, selectedSpanId, isLoading, fadedTypes, expandedSpanIds, setExpandedSpanIds, featuredSpanIds, chartWidth, leadingSlot, }: TraceTimelineProps): import("react").JSX.Element;
|
|
15
17
|
export {};
|
|
@@ -4,6 +4,7 @@ export { useDownloadTraceJson } from './use-download-trace-json';
|
|
|
4
4
|
export { useSpanDetail } from './use-span-detail';
|
|
5
5
|
export { useTraceLightSpans } from './use-trace-light-spans';
|
|
6
6
|
export { useTraceOrBranchSpans, type UseTraceOrBranchSpansArgs, type UseTraceOrBranchSpansResult, } from './use-trace-or-branch-spans';
|
|
7
|
+
export { useTraceSearch, type UseTraceSearchResult } from './use-trace-search';
|
|
7
8
|
export { useTraceSpans } from './use-trace-spans';
|
|
8
9
|
export { useTraces } from './use-traces';
|
|
9
10
|
export { useTags } from './use-tags';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { LightSpanRecord } from '@mastra/core/storage';
|
|
2
1
|
import { UseQueryResult } from '@tanstack/react-query';
|
|
2
|
+
import { SearchableSpan } from '../types';
|
|
3
3
|
export interface UseBranchArgs {
|
|
4
4
|
traceId: string | null | undefined;
|
|
5
5
|
spanId: string | null | undefined;
|
|
@@ -7,5 +7,5 @@ export interface UseBranchArgs {
|
|
|
7
7
|
}
|
|
8
8
|
export declare function useBranch({ traceId, spanId, depth, }: UseBranchArgs): UseQueryResult<{
|
|
9
9
|
traceId: string;
|
|
10
|
-
spans:
|
|
10
|
+
spans: SearchableSpan[];
|
|
11
11
|
} | null>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { LightSpanRecord } from '@mastra/core/storage';
|
|
2
1
|
import { UseQueryResult } from '@tanstack/react-query';
|
|
2
|
+
import { SearchableSpan } from '../types';
|
|
3
3
|
export declare function useTraceLightSpans(traceId: string | null | undefined): UseQueryResult<{
|
|
4
4
|
traceId: string;
|
|
5
|
-
spans:
|
|
5
|
+
spans: SearchableSpan[];
|
|
6
6
|
} | null>;
|