@workflow/web-shared 5.0.0-beta.2 → 5.0.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +2 -0
- package/dist/components/index.js.map +1 -1
- package/dist/components/new-trace-viewer/components/copy-button.d.ts +9 -0
- package/dist/components/new-trace-viewer/components/copy-button.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/copy-button.js +27 -0
- package/dist/components/new-trace-viewer/components/copy-button.js.map +1 -0
- package/dist/components/new-trace-viewer/components/event-list.d.ts +8 -0
- package/dist/components/new-trace-viewer/components/event-list.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/event-list.js +38 -0
- package/dist/components/new-trace-viewer/components/event-list.js.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.d.ts +18 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.js +54 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.js.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.d.ts +20 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.js +81 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.js.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/truncate.d.ts +25 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/truncate.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/truncate.js +101 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/truncate.js.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.d.ts +20 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.js +114 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.js.map +1 -0
- package/dist/components/new-trace-viewer/components/split-pane.d.ts +14 -0
- package/dist/components/new-trace-viewer/components/split-pane.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/split-pane.js +99 -0
- package/dist/components/new-trace-viewer/components/split-pane.js.map +1 -0
- package/dist/components/new-trace-viewer/components/timeline.d.ts +31 -0
- package/dist/components/new-trace-viewer/components/timeline.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/timeline.js +138 -0
- package/dist/components/new-trace-viewer/components/timeline.js.map +1 -0
- package/dist/components/new-trace-viewer/context.d.ts +15 -0
- package/dist/components/new-trace-viewer/context.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/context.js +47 -0
- package/dist/components/new-trace-viewer/context.js.map +1 -0
- package/dist/components/new-trace-viewer/detail-panel.d.ts +10 -0
- package/dist/components/new-trace-viewer/detail-panel.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/detail-panel.js +12 -0
- package/dist/components/new-trace-viewer/detail-panel.js.map +1 -0
- package/dist/components/new-trace-viewer/icons.d.ts +6 -0
- package/dist/components/new-trace-viewer/icons.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/icons.js +15 -0
- package/dist/components/new-trace-viewer/icons.js.map +1 -0
- package/dist/components/new-trace-viewer/trace-viewer.d.ts +8 -0
- package/dist/components/new-trace-viewer/trace-viewer.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/trace-viewer.js +349 -0
- package/dist/components/new-trace-viewer/trace-viewer.js.map +1 -0
- package/dist/components/new-trace-viewer/types.d.ts +1 -0
- package/dist/components/new-trace-viewer/types.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/types.js +2 -0
- package/dist/components/new-trace-viewer/types.js.map +1 -0
- package/dist/components/new-trace-viewer/util/constants.d.ts +1 -0
- package/dist/components/new-trace-viewer/util/constants.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/util/constants.js +2 -0
- package/dist/components/new-trace-viewer/util/constants.js.map +1 -0
- package/dist/components/new-trace-viewer/utils.d.ts +42 -0
- package/dist/components/new-trace-viewer/utils.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/utils.js +305 -0
- package/dist/components/new-trace-viewer/utils.js.map +1 -0
- package/dist/components/sidebar/attribute-panel.d.ts.map +1 -1
- package/dist/components/sidebar/attribute-panel.js +42 -23
- package/dist/components/sidebar/attribute-panel.js.map +1 -1
- package/dist/components/sidebar/copyable-data-block.js +1 -1
- package/dist/components/sidebar/copyable-data-block.js.map +1 -1
- package/dist/components/sidebar/detail-card.d.ts.map +1 -1
- package/dist/components/sidebar/detail-card.js +1 -1
- package/dist/components/sidebar/detail-card.js.map +1 -1
- package/dist/components/sidebar/entity-detail-panel.d.ts +1 -3
- package/dist/components/sidebar/entity-detail-panel.d.ts.map +1 -1
- package/dist/components/sidebar/entity-detail-panel.js +3 -25
- package/dist/components/sidebar/entity-detail-panel.js.map +1 -1
- package/dist/components/sidebar/events-list.d.ts.map +1 -1
- package/dist/components/sidebar/events-list.js +2 -2
- package/dist/components/sidebar/events-list.js.map +1 -1
- package/dist/components/sidebar/sidebar-data-context.d.ts +29 -0
- package/dist/components/sidebar/sidebar-data-context.d.ts.map +1 -0
- package/dist/components/sidebar/sidebar-data-context.js +19 -0
- package/dist/components/sidebar/sidebar-data-context.js.map +1 -0
- package/dist/components/stream-viewer.d.ts +1 -1
- package/dist/components/stream-viewer.d.ts.map +1 -1
- package/dist/components/stream-viewer.js +2 -26
- package/dist/components/stream-viewer.js.map +1 -1
- package/dist/components/trace-viewer/util/timing.d.ts +1 -1
- package/dist/components/trace-viewer/util/timing.d.ts.map +1 -1
- package/dist/components/trace-viewer/util/timing.js +5 -8
- package/dist/components/trace-viewer/util/timing.js.map +1 -1
- package/dist/components/trace-viewer-new.d.ts +10 -0
- package/dist/components/trace-viewer-new.d.ts.map +1 -0
- package/dist/components/trace-viewer-new.js +23 -0
- package/dist/components/trace-viewer-new.js.map +1 -0
- package/dist/components/ui/data-inspector.d.ts +21 -0
- package/dist/components/ui/data-inspector.d.ts.map +1 -1
- package/dist/components/ui/data-inspector.js +99 -4
- package/dist/components/ui/data-inspector.js.map +1 -1
- package/dist/components/ui/inspector-theme.d.ts +9 -10
- package/dist/components/ui/inspector-theme.d.ts.map +1 -1
- package/dist/components/ui/inspector-theme.js +38 -71
- package/dist/components/ui/inspector-theme.js.map +1 -1
- package/dist/components/workflow-trace-view.d.ts +1 -3
- package/dist/components/workflow-trace-view.d.ts.map +1 -1
- package/dist/components/workflow-trace-view.js +4 -4
- package/dist/components/workflow-trace-view.js.map +1 -1
- package/dist/components/workflow-traces/trace-span-construction.d.ts +2 -2
- package/dist/components/workflow-traces/trace-span-construction.d.ts.map +1 -1
- package/dist/components/workflow-traces/trace-span-construction.js +16 -3
- package/dist/components/workflow-traces/trace-span-construction.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/stream-display.d.ts +18 -0
- package/dist/lib/stream-display.d.ts.map +1 -0
- package/dist/lib/stream-display.js +30 -0
- package/dist/lib/stream-display.js.map +1 -0
- package/dist/lib/trace-builder.d.ts.map +1 -1
- package/dist/lib/trace-builder.js +2 -1
- package/dist/lib/trace-builder.js.map +1 -1
- package/dist/lib/utils.d.ts +9 -9
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +26 -31
- package/dist/lib/utils.js.map +1 -1
- package/dist/styles.css +470 -1
- package/package.json +3 -2
- package/src/components/index.ts +5 -0
- package/src/components/new-trace-viewer/components/copy-button.tsx +68 -0
- package/src/components/new-trace-viewer/components/event-list.tsx +116 -0
- package/src/components/new-trace-viewer/components/middle-truncate/copy-selection.ts +114 -0
- package/src/components/new-trace-viewer/components/middle-truncate/middle-truncate.tsx +157 -0
- package/src/components/new-trace-viewer/components/middle-truncate/truncate.ts +132 -0
- package/src/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.ts +167 -0
- package/src/components/new-trace-viewer/components/split-pane.tsx +185 -0
- package/src/components/new-trace-viewer/components/timeline.tsx +382 -0
- package/src/components/new-trace-viewer/context.tsx +92 -0
- package/src/components/new-trace-viewer/detail-panel.tsx +58 -0
- package/src/components/new-trace-viewer/icons.tsx +79 -0
- package/src/components/new-trace-viewer/trace-viewer.tsx +645 -0
- package/src/components/new-trace-viewer/types.ts +0 -0
- package/src/components/new-trace-viewer/util/constants.ts +0 -0
- package/src/components/new-trace-viewer/utils.ts +450 -0
- package/src/components/sidebar/attribute-panel.tsx +43 -32
- package/src/components/sidebar/copyable-data-block.tsx +1 -1
- package/src/components/sidebar/detail-card.tsx +1 -19
- package/src/components/sidebar/entity-detail-panel.tsx +0 -71
- package/src/components/sidebar/events-list.tsx +9 -6
- package/src/components/sidebar/sidebar-data-context.tsx +62 -0
- package/src/components/stream-viewer.tsx +18 -40
- package/src/components/trace-viewer/util/timing.ts +5 -9
- package/src/components/trace-viewer-new.tsx +49 -0
- package/src/components/ui/data-inspector.tsx +235 -4
- package/src/components/ui/inspector-theme.ts +39 -81
- package/src/components/workflow-trace-view.tsx +2 -6
- package/src/components/workflow-traces/trace-span-construction.ts +22 -4
- package/src/index.ts +1 -0
- package/src/lib/stream-display.ts +48 -0
- package/src/lib/trace-builder.ts +2 -1
- package/src/lib/utils.ts +27 -32
- package/src/styles.css +470 -1
|
@@ -4,6 +4,7 @@ export type { HookActionCallbacks, HookActionsDropdownItemProps, HookResolveModa
|
|
|
4
4
|
export { HookResolveModalWrapper, ResolveHookDropdownItem, ResolveHookModal, useHookActions, } from './hook-actions';
|
|
5
5
|
export { RunTraceView } from './run-trace-view';
|
|
6
6
|
export { ConversationView } from './sidebar/conversation-view';
|
|
7
|
+
export { SidebarDataProvider, type SidebarDataContextValue, } from './sidebar/sidebar-data-context';
|
|
7
8
|
export type { SelectedSpanInfo, SpanSelectionInfo, } from './sidebar/entity-detail-panel';
|
|
8
9
|
export { type StreamChunk, StreamViewer } from './stream-viewer';
|
|
9
10
|
export type { Span, SpanEvent } from './trace-viewer/types';
|
|
@@ -13,4 +14,5 @@ export { LoadMoreButton } from './ui/load-more-button';
|
|
|
13
14
|
export { MenuDropdown, type MenuDropdownOption } from './ui/menu-dropdown';
|
|
14
15
|
export { Spinner } from './ui/spinner';
|
|
15
16
|
export { WorkflowTraceViewer } from './workflow-trace-view';
|
|
17
|
+
export { NewTraceViewer } from './trace-viewer-new';
|
|
16
18
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,YAAY,EACV,mBAAmB,EACnB,4BAA4B,EAC5B,qBAAqB,EACrB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,gBAAgB,EAChB,cAAc,GACf,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,YAAY,EACV,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,KAAK,WAAW,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACjE,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EACL,aAAa,EACb,KAAK,kBAAkB,EACvB,mBAAmB,EACnB,KAAK,wBAAwB,GAC9B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,YAAY,EACV,mBAAmB,EACnB,4BAA4B,EAC5B,qBAAqB,EACrB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,gBAAgB,EAChB,cAAc,GACf,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EACL,mBAAmB,EACnB,KAAK,uBAAuB,GAC7B,MAAM,gCAAgC,CAAC;AACxC,YAAY,EACV,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,KAAK,WAAW,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACjE,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EACL,aAAa,EACb,KAAK,kBAAkB,EACvB,mBAAmB,EACnB,KAAK,wBAAwB,GAC9B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/components/index.js
CHANGED
|
@@ -3,6 +3,7 @@ export { EventListView } from './event-list-view';
|
|
|
3
3
|
export { HookResolveModalWrapper, ResolveHookDropdownItem, ResolveHookModal, useHookActions, } from './hook-actions';
|
|
4
4
|
export { RunTraceView } from './run-trace-view';
|
|
5
5
|
export { ConversationView } from './sidebar/conversation-view';
|
|
6
|
+
export { SidebarDataProvider, } from './sidebar/sidebar-data-context';
|
|
6
7
|
export { StreamViewer } from './stream-viewer';
|
|
7
8
|
export { DataInspector, DecryptClickContext, } from './ui/data-inspector';
|
|
8
9
|
export { DecryptButton } from './ui/decrypt-button';
|
|
@@ -10,4 +11,5 @@ export { LoadMoreButton } from './ui/load-more-button';
|
|
|
10
11
|
export { MenuDropdown } from './ui/menu-dropdown';
|
|
11
12
|
export { Spinner } from './ui/spinner';
|
|
12
13
|
export { WorkflowTraceViewer } from './workflow-trace-view';
|
|
14
|
+
export { NewTraceViewer } from './trace-viewer-new';
|
|
13
15
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAQlD,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,gBAAgB,EAChB,cAAc,GACf,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAQlD,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,gBAAgB,EAChB,cAAc,GACf,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EACL,mBAAmB,GAEpB,MAAM,gCAAgC,CAAC;AAKxC,OAAO,EAAoB,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEjE,OAAO,EACL,aAAa,EAEb,mBAAmB,GAEpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAA2B,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC","sourcesContent":["export { ErrorBoundary } from './error-boundary';\nexport { EventListView } from './event-list-view';\nexport type {\n HookActionCallbacks,\n HookActionsDropdownItemProps,\n HookResolveModalProps,\n UseHookActionsOptions,\n UseHookActionsReturn,\n} from './hook-actions';\nexport {\n HookResolveModalWrapper,\n ResolveHookDropdownItem,\n ResolveHookModal,\n useHookActions,\n} from './hook-actions';\nexport { RunTraceView } from './run-trace-view';\nexport { ConversationView } from './sidebar/conversation-view';\nexport {\n SidebarDataProvider,\n type SidebarDataContextValue,\n} from './sidebar/sidebar-data-context';\nexport type {\n SelectedSpanInfo,\n SpanSelectionInfo,\n} from './sidebar/entity-detail-panel';\nexport { type StreamChunk, StreamViewer } from './stream-viewer';\nexport type { Span, SpanEvent } from './trace-viewer/types';\nexport {\n DataInspector,\n type DataInspectorProps,\n DecryptClickContext,\n type DecryptClickContextValue,\n} from './ui/data-inspector';\nexport { DecryptButton } from './ui/decrypt-button';\nexport { LoadMoreButton } from './ui/load-more-button';\nexport { MenuDropdown, type MenuDropdownOption } from './ui/menu-dropdown';\nexport { Spinner } from './ui/spinner';\nexport { WorkflowTraceViewer } from './workflow-trace-view';\nexport { NewTraceViewer } from './trace-viewer-new';\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type JSX } from 'react';
|
|
2
|
+
interface CopyButtonProps {
|
|
3
|
+
copyText: string;
|
|
4
|
+
ariaLabel: string;
|
|
5
|
+
className?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function CopyButton({ copyText, ariaLabel, className, }: CopyButtonProps): JSX.Element;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=copy-button.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copy-button.d.ts","sourceRoot":"","sources":["../../../../src/components/new-trace-viewer/components/copy-button.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,GAAG,EAA+B,MAAM,OAAO,CAAC;AAG9D,UAAU,eAAe;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,SAAS,EACT,SAAS,GACV,EAAE,eAAe,GAAG,GAAG,CAAC,OAAO,CAmD/B"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Check, Copy } from 'lucide-react';
|
|
4
|
+
import { useEffect, useRef, useState } from 'react';
|
|
5
|
+
import { cn } from '../../../lib/utils';
|
|
6
|
+
export function CopyButton({ copyText, ariaLabel, className, }) {
|
|
7
|
+
const [copied, setCopied] = useState(false);
|
|
8
|
+
const timeoutRef = useRef(null);
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
return () => {
|
|
11
|
+
if (timeoutRef.current) {
|
|
12
|
+
clearTimeout(timeoutRef.current);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
}, []);
|
|
16
|
+
return (_jsx("button", { type: "button", "aria-label": ariaLabel, className: cn('cursor-pointer text-gray-800 hover:text-gray-1000 bg-transparent border-none p-1 m-0', className), onClick: (e) => {
|
|
17
|
+
e.stopPropagation();
|
|
18
|
+
if (timeoutRef.current) {
|
|
19
|
+
clearTimeout(timeoutRef.current);
|
|
20
|
+
}
|
|
21
|
+
void navigator.clipboard.writeText(copyText).then(() => {
|
|
22
|
+
setCopied(true);
|
|
23
|
+
timeoutRef.current = setTimeout(() => setCopied(false), 1000);
|
|
24
|
+
});
|
|
25
|
+
}, children: _jsxs("div", { className: "relative w-3 h-3", children: [_jsx("div", { className: cn('absolute inset-0 flex items-center justify-center transition-all duration-150 ease-out', copied ? 'scale-100 opacity-100' : 'scale-0 opacity-0'), children: _jsx(Check, { className: "w-3 h-3" }) }), _jsx("div", { className: cn('absolute inset-0 flex items-center justify-center transition-all duration-150 ease-out', copied ? 'scale-0 opacity-0' : 'scale-100 opacity-100'), children: _jsx(Copy, { className: "w-3 h-3" }) })] }) }));
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=copy-button.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copy-button.js","sourceRoot":"","sources":["../../../../src/components/new-trace-viewer/components/copy-button.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAY,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC9D,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAC;AAQxC,MAAM,UAAU,UAAU,CAAC,EACzB,QAAQ,EACR,SAAS,EACT,SAAS,GACO;IAChB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC5C,MAAM,UAAU,GAAG,MAAM,CAAuC,IAAI,CAAC,CAAC;IAEtE,SAAS,CAAC,GAAG,EAAE;QACb,OAAO,GAAG,EAAE;YACV,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;gBACvB,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YACnC,CAAC;QACH,CAAC,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,CACL,iBACE,IAAI,EAAC,QAAQ,gBACD,SAAS,EACrB,SAAS,EAAE,EAAE,CACX,sFAAsF,EACtF,SAAS,CACV,EACD,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;YACb,CAAC,CAAC,eAAe,EAAE,CAAC;YACpB,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;gBACvB,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YACnC,CAAC;YACD,KAAK,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;gBACrD,SAAS,CAAC,IAAI,CAAC,CAAC;gBAChB,UAAU,CAAC,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;YAChE,CAAC,CAAC,CAAC;QACL,CAAC,YAED,eAAK,SAAS,EAAC,kBAAkB,aAC/B,cACE,SAAS,EAAE,EAAE,CACX,wFAAwF,EACxF,MAAM,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,mBAAmB,CACvD,YAED,KAAC,KAAK,IAAC,SAAS,EAAC,SAAS,GAAG,GACzB,EACN,cACE,SAAS,EAAE,EAAE,CACX,wFAAwF,EACxF,MAAM,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,uBAAuB,CACvD,YAED,KAAC,IAAI,IAAC,SAAS,EAAC,SAAS,GAAG,GACxB,IACF,GACC,CACV,CAAC;AACJ,CAAC","sourcesContent":["'use client';\n\nimport { Check, Copy } from 'lucide-react';\nimport { type JSX, useEffect, useRef, useState } from 'react';\nimport { cn } from '../../../lib/utils';\n\ninterface CopyButtonProps {\n copyText: string;\n ariaLabel: string;\n className?: string;\n}\n\nexport function CopyButton({\n copyText,\n ariaLabel,\n className,\n}: CopyButtonProps): JSX.Element {\n const [copied, setCopied] = useState(false);\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(() => {\n return () => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n };\n }, []);\n\n return (\n <button\n type=\"button\"\n aria-label={ariaLabel}\n className={cn(\n 'cursor-pointer text-gray-800 hover:text-gray-1000 bg-transparent border-none p-1 m-0',\n className\n )}\n onClick={(e) => {\n e.stopPropagation();\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n void navigator.clipboard.writeText(copyText).then(() => {\n setCopied(true);\n timeoutRef.current = setTimeout(() => setCopied(false), 1000);\n });\n }}\n >\n <div className=\"relative w-3 h-3\">\n <div\n className={cn(\n 'absolute inset-0 flex items-center justify-center transition-all duration-150 ease-out',\n copied ? 'scale-100 opacity-100' : 'scale-0 opacity-0'\n )}\n >\n <Check className=\"w-3 h-3\" />\n </div>\n <div\n className={cn(\n 'absolute inset-0 flex items-center justify-center transition-all duration-150 ease-out',\n copied ? 'scale-0 opacity-0' : 'scale-100 opacity-100'\n )}\n >\n <Copy className=\"w-3 h-3\" />\n </div>\n </div>\n </button>\n );\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Span } from '../../trace-viewer/types';
|
|
2
|
+
declare const EventList: ({ spans, activeSpanId, onSelectSpan, }: {
|
|
3
|
+
spans: Span[];
|
|
4
|
+
activeSpanId: string | null;
|
|
5
|
+
onSelectSpan: (spanId: string) => void;
|
|
6
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export default EventList;
|
|
8
|
+
//# sourceMappingURL=event-list.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-list.d.ts","sourceRoot":"","sources":["../../../../src/components/new-trace-viewer/components/event-list.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAwFrD,QAAA,MAAM,SAAS,GAAI,wCAIhB;IACD,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC,4CAeA,CAAC;AAEF,eAAe,SAAS,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Circle } from 'lucide-react';
|
|
3
|
+
import { cn } from '../../../lib/utils';
|
|
4
|
+
import { formatDuration } from '../../trace-viewer/util/timing';
|
|
5
|
+
import { WorkflowIcon, WebhookIcon, SleepIcon, StepForwardIcon, } from '../icons';
|
|
6
|
+
import { getSpanDurationMs } from '../utils';
|
|
7
|
+
import { MiddleTruncate } from './middle-truncate/middle-truncate';
|
|
8
|
+
const eventStyles = {
|
|
9
|
+
run: { icon: WorkflowIcon, className: 'text-blue-900' },
|
|
10
|
+
step: { icon: StepForwardIcon, className: 'text-green-900' },
|
|
11
|
+
hook: { icon: WebhookIcon, className: 'text-yellow-900' },
|
|
12
|
+
sleep: { icon: SleepIcon, className: 'text-gray-900' },
|
|
13
|
+
};
|
|
14
|
+
const defaultStyle = {
|
|
15
|
+
icon: Circle,
|
|
16
|
+
className: 'text-gray-900',
|
|
17
|
+
};
|
|
18
|
+
const ROW_HEIGHT_CLASS = 'h-10';
|
|
19
|
+
function getEventStyle(resource, isErrored) {
|
|
20
|
+
const style = eventStyles[resource] ?? defaultStyle;
|
|
21
|
+
return {
|
|
22
|
+
icon: style.icon,
|
|
23
|
+
className: cn(isErrored ? 'text-red-900' : style.className),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
const EventRow = ({ span, isSelected, onSelectSpan, }) => {
|
|
27
|
+
const durationMs = getSpanDurationMs(span);
|
|
28
|
+
const isErrored = span.attributes.data.status === 'failed';
|
|
29
|
+
const { icon: Icon, className: tagClassName } = getEventStyle(span.resource, isErrored);
|
|
30
|
+
return (_jsx("li", { className: cn('relative overflow-clip group after:absolute after:inset-x-0 after:bottom-0 after:h-px after:bg-gray-alpha-400', ROW_HEIGHT_CLASS), role: 'treeitem', "aria-selected": isSelected, "aria-expanded": isSelected, "aria-level": 1, onClick: () => onSelectSpan(span.spanId), children: _jsx("div", { className: 'h-full hover:bg-gray-100 group-aria-selected:bg-gray-100 group-aria-selected:hover:bg-gray-200', children: _jsxs("div", { className: 'flex h-full min-w-0 items-center px-2', children: [_jsxs("div", { className: 'flex min-w-0 flex-1 items-center gap-2', children: [_jsx("span", { className: cn('shrink-0', tagClassName), children: _jsx(Icon, { className: 'w-4 h-4' }) }), _jsx("span", { className: 'min-w-0 text-label-14', children: _jsx(MiddleTruncate, { value: span.name }) })] }), _jsx("div", { className: 'ml-2 shrink-0', children: _jsx("span", { className: 'text-label-14 text-gray-900 tabular-nums', children: formatDuration(durationMs) }) })] }) }) }));
|
|
31
|
+
};
|
|
32
|
+
const EventList = ({ spans, activeSpanId, onSelectSpan, }) => {
|
|
33
|
+
return (_jsx("ul", { id: 'event-list', role: 'tree', className: 'block min-h-0 overflow-visible', children: spans.map((span) => {
|
|
34
|
+
return (_jsx(EventRow, { span: span, isSelected: span.spanId === activeSpanId, onSelectSpan: onSelectSpan }, span.spanId));
|
|
35
|
+
}) }));
|
|
36
|
+
};
|
|
37
|
+
export default EventList;
|
|
38
|
+
//# sourceMappingURL=event-list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-list.js","sourceRoot":"","sources":["../../../../src/components/new-trace-viewer/components/event-list.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Circle } from 'lucide-react';\nimport { cn } from '../../../lib/utils';\nimport type { Span } from '../../trace-viewer/types';\nimport { formatDuration } from '../../trace-viewer/util/timing';\nimport {\n WorkflowIcon,\n WebhookIcon,\n SleepIcon,\n StepForwardIcon,\n} from '../icons';\nimport { getSpanDurationMs } from '../utils';\nimport { MiddleTruncate } from './middle-truncate/middle-truncate';\n\ninterface EventStyle {\n icon: React.ComponentType<{ className?: string }>;\n className: string;\n}\n\nconst eventStyles: Record<string, EventStyle> = {\n run: { icon: WorkflowIcon, className: 'text-blue-900' },\n step: { icon: StepForwardIcon, className: 'text-green-900' },\n hook: { icon: WebhookIcon, className: 'text-yellow-900' },\n sleep: { icon: SleepIcon, className: 'text-gray-900' },\n};\n\nconst defaultStyle: EventStyle = {\n icon: Circle,\n className: 'text-gray-900',\n};\n\nconst ROW_HEIGHT_CLASS = 'h-10';\n\nfunction getEventStyle(resource: string, isErrored: boolean): EventStyle {\n const style = eventStyles[resource] ?? defaultStyle;\n return {\n icon: style.icon,\n className: cn(isErrored ? 'text-red-900' : style.className),\n };\n}\n\nconst EventRow = ({\n span,\n isSelected,\n onSelectSpan,\n}: {\n span: Span;\n isSelected: boolean;\n onSelectSpan: (spanId: string) => void;\n}) => {\n const durationMs = getSpanDurationMs(span);\n const isErrored =\n (span.attributes.data as Record<string, unknown>).status === 'failed';\n const { icon: Icon, className: tagClassName } = getEventStyle(\n span.resource,\n isErrored\n );\n\n return (\n <li\n className={cn(\n 'relative overflow-clip group after:absolute after:inset-x-0 after:bottom-0 after:h-px after:bg-gray-alpha-400',\n ROW_HEIGHT_CLASS\n )}\n role='treeitem'\n aria-selected={isSelected}\n aria-expanded={isSelected}\n aria-level={1}\n onClick={() => onSelectSpan(span.spanId)}\n >\n <div className='h-full hover:bg-gray-100 group-aria-selected:bg-gray-100 group-aria-selected:hover:bg-gray-200'>\n <div className='flex h-full min-w-0 items-center px-2'>\n <div className='flex min-w-0 flex-1 items-center gap-2'>\n <span className={cn('shrink-0', tagClassName)}>\n <Icon className='w-4 h-4' />\n </span>\n <span className='min-w-0 text-label-14'>\n <MiddleTruncate value={span.name} />\n </span>\n </div>\n <div className='ml-2 shrink-0'>\n <span className='text-label-14 text-gray-900 tabular-nums'>\n {formatDuration(durationMs)}\n </span>\n </div>\n </div>\n </div>\n </li>\n );\n};\n\nconst EventList = ({\n spans,\n activeSpanId,\n onSelectSpan,\n}: {\n spans: Span[];\n activeSpanId: string | null;\n onSelectSpan: (spanId: string) => void;\n}) => {\n return (\n <ul id='event-list' role='tree' className='block min-h-0 overflow-visible'>\n {spans.map((span) => {\n return (\n <EventRow\n key={span.spanId}\n span={span}\n isSelected={span.spanId === activeSpanId}\n onSelectSpan={onSelectSpan}\n />\n );\n })}\n </ul>\n );\n};\n\nexport default EventList;\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
interface GetMiddleTruncateCopyTextOptions {
|
|
2
|
+
prefixText: string;
|
|
3
|
+
selectionEnd: number;
|
|
4
|
+
selectionStart: number;
|
|
5
|
+
suffixText: string;
|
|
6
|
+
value: string;
|
|
7
|
+
}
|
|
8
|
+
interface GetMiddleTruncateCopyTextFromSelectionTextOptions {
|
|
9
|
+
prefixText: string;
|
|
10
|
+
selectionText: string;
|
|
11
|
+
suffixText: string;
|
|
12
|
+
value: string;
|
|
13
|
+
}
|
|
14
|
+
declare function getMiddleTruncateCopyText({ prefixText, selectionEnd, selectionStart, suffixText, value, }: GetMiddleTruncateCopyTextOptions): string | null;
|
|
15
|
+
declare function getMiddleTruncateCopyTextFromSelectionText({ prefixText, selectionText, suffixText, value, }: GetMiddleTruncateCopyTextFromSelectionTextOptions): string | null;
|
|
16
|
+
export { getMiddleTruncateCopyText, getMiddleTruncateCopyTextFromSelectionText, };
|
|
17
|
+
export type { GetMiddleTruncateCopyTextFromSelectionTextOptions, GetMiddleTruncateCopyTextOptions, };
|
|
18
|
+
//# sourceMappingURL=copy-selection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copy-selection.d.ts","sourceRoot":"","sources":["../../../../../src/components/new-trace-viewer/components/middle-truncate/copy-selection.ts"],"names":[],"mappings":"AAEA,UAAU,gCAAgC;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,UAAU,iDAAiD;IACzD,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,iBAAS,yBAAyB,CAAC,EACjC,UAAU,EACV,YAAY,EACZ,cAAc,EACd,UAAU,EACV,KAAK,GACN,EAAE,gCAAgC,GAAG,MAAM,GAAG,IAAI,CAqClD;AAED,iBAAS,0CAA0C,CAAC,EAClD,UAAU,EACV,aAAa,EACb,UAAU,EACV,KAAK,GACN,EAAE,iDAAiD,GAAG,MAAM,GAAG,IAAI,CAqCnE;AAED,OAAO,EACL,yBAAyB,EACzB,0CAA0C,GAC3C,CAAC;AACF,YAAY,EACV,iDAAiD,EACjD,gCAAgC,GACjC,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { ELLIPSIS, toGraphemes } from './truncate';
|
|
2
|
+
function getMiddleTruncateCopyText({ prefixText, selectionEnd, selectionStart, suffixText, value, }) {
|
|
3
|
+
const visibleText = prefixText + ELLIPSIS + suffixText;
|
|
4
|
+
if (selectionStart < 0 ||
|
|
5
|
+
selectionEnd > visibleText.length ||
|
|
6
|
+
selectionStart >= selectionEnd) {
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
if (selectionStart === 0 && selectionEnd === visibleText.length) {
|
|
10
|
+
return value;
|
|
11
|
+
}
|
|
12
|
+
const ellipsisStart = prefixText.length;
|
|
13
|
+
const ellipsisEnd = ellipsisStart + ELLIPSIS.length;
|
|
14
|
+
if (selectionStart > ellipsisStart || selectionEnd < ellipsisEnd) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
const originalGraphemes = toGraphemes(value);
|
|
18
|
+
const selectedPrefixGraphemeCount = toGraphemes(visibleText.slice(0, selectionStart)).length;
|
|
19
|
+
const selectedSuffixGraphemeCount = toGraphemes(visibleText.slice(ellipsisEnd, selectionEnd)).length;
|
|
20
|
+
const suffixStart = originalGraphemes.length - toGraphemes(suffixText).length;
|
|
21
|
+
return originalGraphemes
|
|
22
|
+
.slice(selectedPrefixGraphemeCount, suffixStart + selectedSuffixGraphemeCount)
|
|
23
|
+
.join('');
|
|
24
|
+
}
|
|
25
|
+
function getMiddleTruncateCopyTextFromSelectionText({ prefixText, selectionText, suffixText, value, }) {
|
|
26
|
+
const visibleText = prefixText + ELLIPSIS + suffixText;
|
|
27
|
+
const trimmedSelectionText = selectionText.trim();
|
|
28
|
+
if (!trimmedSelectionText) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
const leading = selectionText.slice(0, selectionText.length - selectionText.trimStart().length);
|
|
32
|
+
const trailing = selectionText.slice(selectionText.trimEnd().length);
|
|
33
|
+
if (trimmedSelectionText === visibleText) {
|
|
34
|
+
return leading + value + trailing;
|
|
35
|
+
}
|
|
36
|
+
if (!trimmedSelectionText.includes(ELLIPSIS)) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
const selectionStart = visibleText.indexOf(trimmedSelectionText);
|
|
40
|
+
if (selectionStart === -1) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
const selectionEnd = selectionStart + trimmedSelectionText.length;
|
|
44
|
+
const mappedText = getMiddleTruncateCopyText({
|
|
45
|
+
prefixText,
|
|
46
|
+
selectionEnd,
|
|
47
|
+
selectionStart,
|
|
48
|
+
suffixText,
|
|
49
|
+
value,
|
|
50
|
+
});
|
|
51
|
+
return mappedText === null ? null : leading + mappedText + trailing;
|
|
52
|
+
}
|
|
53
|
+
export { getMiddleTruncateCopyText, getMiddleTruncateCopyTextFromSelectionText, };
|
|
54
|
+
//# sourceMappingURL=copy-selection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copy-selection.js","sourceRoot":"","sources":["../../../../../src/components/new-trace-viewer/components/middle-truncate/copy-selection.ts"],"names":[],"mappings":"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","sourcesContent":["import { ELLIPSIS, toGraphemes } from './truncate';\n\ninterface GetMiddleTruncateCopyTextOptions {\n prefixText: string;\n selectionEnd: number;\n selectionStart: number;\n suffixText: string;\n value: string;\n}\n\ninterface GetMiddleTruncateCopyTextFromSelectionTextOptions {\n prefixText: string;\n selectionText: string;\n suffixText: string;\n value: string;\n}\n\nfunction getMiddleTruncateCopyText({\n prefixText,\n selectionEnd,\n selectionStart,\n suffixText,\n value,\n}: GetMiddleTruncateCopyTextOptions): string | null {\n const visibleText = prefixText + ELLIPSIS + suffixText;\n\n if (\n selectionStart < 0 ||\n selectionEnd > visibleText.length ||\n selectionStart >= selectionEnd\n ) {\n return null;\n }\n\n if (selectionStart === 0 && selectionEnd === visibleText.length) {\n return value;\n }\n\n const ellipsisStart = prefixText.length;\n const ellipsisEnd = ellipsisStart + ELLIPSIS.length;\n\n if (selectionStart > ellipsisStart || selectionEnd < ellipsisEnd) {\n return null;\n }\n\n const originalGraphemes = toGraphemes(value);\n const selectedPrefixGraphemeCount = toGraphemes(\n visibleText.slice(0, selectionStart)\n ).length;\n const selectedSuffixGraphemeCount = toGraphemes(\n visibleText.slice(ellipsisEnd, selectionEnd)\n ).length;\n const suffixStart = originalGraphemes.length - toGraphemes(suffixText).length;\n\n return originalGraphemes\n .slice(\n selectedPrefixGraphemeCount,\n suffixStart + selectedSuffixGraphemeCount\n )\n .join('');\n}\n\nfunction getMiddleTruncateCopyTextFromSelectionText({\n prefixText,\n selectionText,\n suffixText,\n value,\n}: GetMiddleTruncateCopyTextFromSelectionTextOptions): string | null {\n const visibleText = prefixText + ELLIPSIS + suffixText;\n const trimmedSelectionText = selectionText.trim();\n\n if (!trimmedSelectionText) {\n return null;\n }\n\n const leading = selectionText.slice(\n 0,\n selectionText.length - selectionText.trimStart().length\n );\n const trailing = selectionText.slice(selectionText.trimEnd().length);\n\n if (trimmedSelectionText === visibleText) {\n return leading + value + trailing;\n }\n\n if (!trimmedSelectionText.includes(ELLIPSIS)) {\n return null;\n }\n\n const selectionStart = visibleText.indexOf(trimmedSelectionText);\n if (selectionStart === -1) {\n return null;\n }\n\n const selectionEnd = selectionStart + trimmedSelectionText.length;\n const mappedText = getMiddleTruncateCopyText({\n prefixText,\n selectionEnd,\n selectionStart,\n suffixText,\n value,\n });\n\n return mappedText === null ? null : leading + mappedText + trailing;\n}\n\nexport {\n getMiddleTruncateCopyText,\n getMiddleTruncateCopyTextFromSelectionText,\n};\nexport type {\n GetMiddleTruncateCopyTextFromSelectionTextOptions,\n GetMiddleTruncateCopyTextOptions,\n};\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ComponentPropsWithoutRef, JSX } from 'react';
|
|
2
|
+
/** Props for the {@link MiddleTruncate} component. */
|
|
3
|
+
interface MiddleTruncateProps extends Omit<ComponentPropsWithoutRef<'span'>, 'children'> {
|
|
4
|
+
/** The full text string to display, truncated from the middle when it overflows. */
|
|
5
|
+
value: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* @gdoc
|
|
9
|
+
*
|
|
10
|
+
* Truncates text from the middle with an ellipsis when it overflows, preserving the beginning and end (e.g. file paths, URLs). Copy behavior restores the full untruncated text to the clipboard.
|
|
11
|
+
* Renders a `<span>` element.
|
|
12
|
+
*
|
|
13
|
+
* Documentation: [Geist Middle Truncate](https://vercel.com/geist/middle-truncate)
|
|
14
|
+
*
|
|
15
|
+
* @param value - Full text string to display.
|
|
16
|
+
*/
|
|
17
|
+
declare function MiddleTruncate({ value, className, onCopy: onCopyProp, ...props }: MiddleTruncateProps): JSX.Element;
|
|
18
|
+
export { MiddleTruncate };
|
|
19
|
+
export type { MiddleTruncateProps };
|
|
20
|
+
//# sourceMappingURL=middle-truncate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middle-truncate.d.ts","sourceRoot":"","sources":["../../../../../src/components/new-trace-viewer/components/middle-truncate/middle-truncate.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAkB,wBAAwB,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAS3E,sDAAsD;AACtD,UAAU,mBACR,SAAQ,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC;IAC1D,oFAAoF;IACpF,KAAK,EAAE,MAAM,CAAC;CACf;AA2BD;;;;;;;;;GASG;AACH,iBAAS,cAAc,CAAC,EACtB,KAAK,EACL,SAAS,EACT,MAAM,EAAE,UAAU,EAClB,GAAG,KAAK,EACT,EAAE,mBAAmB,GAAG,GAAG,CAAC,OAAO,CA8FnC;AAED,OAAO,EAAE,cAAc,EAAE,CAAC;AAC1B,YAAY,EAAE,mBAAmB,EAAE,CAAC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useRef } from 'react';
|
|
4
|
+
import { cn } from '../../../../lib/utils';
|
|
5
|
+
import { getMiddleTruncateCopyText, getMiddleTruncateCopyTextFromSelectionText, } from './copy-selection';
|
|
6
|
+
import { ELLIPSIS } from './truncate';
|
|
7
|
+
import { useMiddleTruncate } from './use-middle-truncate';
|
|
8
|
+
function getRangeOffsets(container, range) {
|
|
9
|
+
if (!container.contains(range.startContainer) ||
|
|
10
|
+
!container.contains(range.endContainer)) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
const startRange = document.createRange();
|
|
14
|
+
startRange.selectNodeContents(container);
|
|
15
|
+
startRange.setEnd(range.startContainer, range.startOffset);
|
|
16
|
+
const endRange = document.createRange();
|
|
17
|
+
endRange.selectNodeContents(container);
|
|
18
|
+
endRange.setEnd(range.endContainer, range.endOffset);
|
|
19
|
+
return {
|
|
20
|
+
end: endRange.toString().length,
|
|
21
|
+
start: startRange.toString().length,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* @gdoc
|
|
26
|
+
*
|
|
27
|
+
* Truncates text from the middle with an ellipsis when it overflows, preserving the beginning and end (e.g. file paths, URLs). Copy behavior restores the full untruncated text to the clipboard.
|
|
28
|
+
* Renders a `<span>` element.
|
|
29
|
+
*
|
|
30
|
+
* Documentation: [Geist Middle Truncate](https://vercel.com/geist/middle-truncate)
|
|
31
|
+
*
|
|
32
|
+
* @param value - Full text string to display.
|
|
33
|
+
*/
|
|
34
|
+
function MiddleTruncate({ value, className, onCopy: onCopyProp, ...props }) {
|
|
35
|
+
const { ref, measureRef, displayText, isTruncated, prefixText, suffixText } = useMiddleTruncate(value);
|
|
36
|
+
const visibleRef = useRef(null);
|
|
37
|
+
const handleCopy = useCallback((e) => {
|
|
38
|
+
onCopyProp?.(e);
|
|
39
|
+
if (e.defaultPrevented || !isTruncated)
|
|
40
|
+
return;
|
|
41
|
+
const selection = window.getSelection();
|
|
42
|
+
if (!selection || selection.rangeCount === 0)
|
|
43
|
+
return;
|
|
44
|
+
const selectionText = selection.toString();
|
|
45
|
+
if (!selectionText)
|
|
46
|
+
return;
|
|
47
|
+
// Only intercept when the selection is fully within this element.
|
|
48
|
+
// If the user selected across elements (e.g. a table row), let
|
|
49
|
+
// the browser's default behavior preserve surrounding context.
|
|
50
|
+
const range = selection.getRangeAt(0);
|
|
51
|
+
const visibleEl = visibleRef.current;
|
|
52
|
+
let copyText = null;
|
|
53
|
+
if (e.currentTarget.contains(range.startContainer) &&
|
|
54
|
+
e.currentTarget.contains(range.endContainer) &&
|
|
55
|
+
visibleEl) {
|
|
56
|
+
const offsets = getRangeOffsets(visibleEl, range);
|
|
57
|
+
if (offsets) {
|
|
58
|
+
copyText = getMiddleTruncateCopyText({
|
|
59
|
+
prefixText,
|
|
60
|
+
selectionEnd: offsets.end,
|
|
61
|
+
selectionStart: offsets.start,
|
|
62
|
+
suffixText,
|
|
63
|
+
value,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
copyText ??= getMiddleTruncateCopyTextFromSelectionText({
|
|
68
|
+
prefixText,
|
|
69
|
+
selectionText,
|
|
70
|
+
suffixText,
|
|
71
|
+
value,
|
|
72
|
+
});
|
|
73
|
+
if (copyText === null)
|
|
74
|
+
return;
|
|
75
|
+
e.preventDefault();
|
|
76
|
+
e.clipboardData.setData('text/plain', copyText);
|
|
77
|
+
}, [onCopyProp, isTruncated, prefixText, suffixText, value]);
|
|
78
|
+
return (_jsxs("span", { title: isTruncated ? value : undefined, ...props, ref: ref, className: cn('relative inline-grid min-w-0 max-w-full overflow-hidden whitespace-nowrap', className), onCopy: handleCopy, children: [isTruncated && _jsx("span", { className: 'sr-only select-none', children: value }), _jsx("span", { "aria-hidden": 'true', className: 'pointer-events-none col-start-1 row-start-1 invisible select-none whitespace-nowrap', children: value }), _jsx("span", { "aria-hidden": isTruncated || undefined, className: 'col-start-1 row-start-1 min-w-0 overflow-hidden', ref: visibleRef, children: isTruncated ? (_jsxs(_Fragment, { children: [_jsx("span", { children: prefixText }), _jsx("span", { children: ELLIPSIS }), _jsx("span", { children: suffixText })] })) : (displayText) }), _jsx("span", { "aria-hidden": 'true', className: 'pointer-events-none absolute left-0 top-0 inline-block invisible select-none whitespace-nowrap', ref: measureRef })] }));
|
|
79
|
+
}
|
|
80
|
+
export { MiddleTruncate };
|
|
81
|
+
//# sourceMappingURL=middle-truncate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middle-truncate.js","sourceRoot":"","sources":["../../../../../src/components/new-trace-viewer/components/middle-truncate/middle-truncate.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\nimport { useCallback, useRef } from 'react';\nimport type { ClipboardEvent, ComponentPropsWithoutRef, JSX } from 'react';\nimport { cn } from '../../../../lib/utils';\nimport {\n getMiddleTruncateCopyText,\n getMiddleTruncateCopyTextFromSelectionText,\n} from './copy-selection';\nimport { ELLIPSIS } from './truncate';\nimport { useMiddleTruncate } from './use-middle-truncate';\n\n/** Props for the {@link MiddleTruncate} component. */\ninterface MiddleTruncateProps\n extends Omit<ComponentPropsWithoutRef<'span'>, 'children'> {\n /** The full text string to display, truncated from the middle when it overflows. */\n value: string;\n}\n\nfunction getRangeOffsets(\n container: HTMLElement,\n range: Range\n): { end: number; start: number } | null {\n if (\n !container.contains(range.startContainer) ||\n !container.contains(range.endContainer)\n ) {\n return null;\n }\n\n const startRange = document.createRange();\n startRange.selectNodeContents(container);\n startRange.setEnd(range.startContainer, range.startOffset);\n\n const endRange = document.createRange();\n endRange.selectNodeContents(container);\n endRange.setEnd(range.endContainer, range.endOffset);\n\n return {\n end: endRange.toString().length,\n start: startRange.toString().length,\n };\n}\n\n/**\n * @gdoc\n *\n * Truncates text from the middle with an ellipsis when it overflows, preserving the beginning and end (e.g. file paths, URLs). Copy behavior restores the full untruncated text to the clipboard.\n * Renders a `<span>` element.\n *\n * Documentation: [Geist Middle Truncate](https://vercel.com/geist/middle-truncate)\n *\n * @param value - Full text string to display.\n */\nfunction MiddleTruncate({\n value,\n className,\n onCopy: onCopyProp,\n ...props\n}: MiddleTruncateProps): JSX.Element {\n const { ref, measureRef, displayText, isTruncated, prefixText, suffixText } =\n useMiddleTruncate(value);\n const visibleRef = useRef<HTMLSpanElement | null>(null);\n\n const handleCopy = useCallback(\n (e: ClipboardEvent<HTMLSpanElement>) => {\n onCopyProp?.(e);\n if (e.defaultPrevented || !isTruncated) return;\n\n const selection = window.getSelection();\n if (!selection || selection.rangeCount === 0) return;\n const selectionText = selection.toString();\n if (!selectionText) return;\n\n // Only intercept when the selection is fully within this element.\n // If the user selected across elements (e.g. a table row), let\n // the browser's default behavior preserve surrounding context.\n const range = selection.getRangeAt(0);\n const visibleEl = visibleRef.current;\n let copyText: string | null = null;\n\n if (\n e.currentTarget.contains(range.startContainer) &&\n e.currentTarget.contains(range.endContainer) &&\n visibleEl\n ) {\n const offsets = getRangeOffsets(visibleEl, range);\n if (offsets) {\n copyText = getMiddleTruncateCopyText({\n prefixText,\n selectionEnd: offsets.end,\n selectionStart: offsets.start,\n suffixText,\n value,\n });\n }\n }\n\n copyText ??= getMiddleTruncateCopyTextFromSelectionText({\n prefixText,\n selectionText,\n suffixText,\n value,\n });\n\n if (copyText === null) return;\n\n e.preventDefault();\n e.clipboardData.setData('text/plain', copyText);\n },\n [onCopyProp, isTruncated, prefixText, suffixText, value]\n );\n\n return (\n <span\n title={isTruncated ? value : undefined}\n {...props}\n ref={ref}\n className={cn(\n 'relative inline-grid min-w-0 max-w-full overflow-hidden whitespace-nowrap',\n className\n )}\n onCopy={handleCopy}\n >\n {isTruncated && <span className='sr-only select-none'>{value}</span>}\n <span\n aria-hidden='true'\n className='pointer-events-none col-start-1 row-start-1 invisible select-none whitespace-nowrap'\n >\n {value}\n </span>\n <span\n aria-hidden={isTruncated || undefined}\n className='col-start-1 row-start-1 min-w-0 overflow-hidden'\n ref={visibleRef}\n >\n {isTruncated ? (\n <>\n <span>{prefixText}</span>\n <span>{ELLIPSIS}</span>\n <span>{suffixText}</span>\n </>\n ) : (\n displayText\n )}\n </span>\n <span\n aria-hidden='true'\n className='pointer-events-none absolute left-0 top-0 inline-block invisible select-none whitespace-nowrap'\n ref={measureRef}\n />\n </span>\n );\n}\n\nexport { MiddleTruncate };\nexport type { MiddleTruncateProps };\n"]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
declare const ELLIPSIS = "...";
|
|
2
|
+
declare const MIN_START = 3;
|
|
3
|
+
declare const MIN_END = 3;
|
|
4
|
+
type MeasureFn = (text: string) => number;
|
|
5
|
+
/**
|
|
6
|
+
* Splits a string into grapheme clusters using Intl.Segmenter.
|
|
7
|
+
* Falls back to Array.from for environments without Intl.Segmenter.
|
|
8
|
+
*/
|
|
9
|
+
declare function toGraphemes(text: string): string[];
|
|
10
|
+
interface TruncateResult {
|
|
11
|
+
prefixText: string;
|
|
12
|
+
prefixGraphemeCount: number;
|
|
13
|
+
suffixText: string;
|
|
14
|
+
suffixGraphemeCount: number;
|
|
15
|
+
text: string;
|
|
16
|
+
truncated: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Middle-truncates a string so `prefix...suffix` fits within `availableWidth`.
|
|
20
|
+
* Uses binary search over grapheme clusters with an injectable measure function.
|
|
21
|
+
*/
|
|
22
|
+
declare function middleTruncate(graphemes: string[], availableWidth: number, measure: MeasureFn, fullWidth?: number): TruncateResult;
|
|
23
|
+
export { middleTruncate, toGraphemes, ELLIPSIS, MIN_START, MIN_END };
|
|
24
|
+
export type { MeasureFn, TruncateResult };
|
|
25
|
+
//# sourceMappingURL=truncate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"truncate.d.ts","sourceRoot":"","sources":["../../../../../src/components/new-trace-viewer/components/middle-truncate/truncate.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,QAAQ,QAAQ,CAAC;AACvB,QAAA,MAAM,SAAS,IAAI,CAAC;AACpB,QAAA,MAAM,OAAO,IAAI,CAAC;AAOlB,KAAK,SAAS,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;AAE1C;;;GAGG;AACH,iBAAS,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAK3C;AAED,UAAU,cAAc;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;CACpB;AAmCD;;;GAGG;AACH,iBAAS,cAAc,CACrB,SAAS,EAAE,MAAM,EAAE,EACnB,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,SAAS,EAClB,SAAS,CAAC,EAAE,MAAM,GACjB,cAAc,CAuDhB;AAED,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC;AACrE,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
const ELLIPSIS = '...';
|
|
2
|
+
const MIN_START = 3;
|
|
3
|
+
const MIN_END = 3;
|
|
4
|
+
const MIN_KEPT = MIN_START + MIN_END;
|
|
5
|
+
const graphemeSegmenter = typeof Intl !== 'undefined' && 'Segmenter' in Intl
|
|
6
|
+
? new Intl.Segmenter(undefined, { granularity: 'grapheme' })
|
|
7
|
+
: null;
|
|
8
|
+
/**
|
|
9
|
+
* Splits a string into grapheme clusters using Intl.Segmenter.
|
|
10
|
+
* Falls back to Array.from for environments without Intl.Segmenter.
|
|
11
|
+
*/
|
|
12
|
+
function toGraphemes(text) {
|
|
13
|
+
if (graphemeSegmenter) {
|
|
14
|
+
return [...graphemeSegmenter.segment(text)].map((s) => s.segment);
|
|
15
|
+
}
|
|
16
|
+
return Array.from(text);
|
|
17
|
+
}
|
|
18
|
+
function buildCandidate(graphemes, kept) {
|
|
19
|
+
if (kept <= 0) {
|
|
20
|
+
return {
|
|
21
|
+
prefixText: '',
|
|
22
|
+
prefixGraphemeCount: 0,
|
|
23
|
+
suffixText: '',
|
|
24
|
+
suffixGraphemeCount: 0,
|
|
25
|
+
text: ELLIPSIS,
|
|
26
|
+
truncated: true,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
const suffixGraphemeCount = kept >= MIN_KEPT
|
|
30
|
+
? Math.max(MIN_END, Math.floor(kept / 2))
|
|
31
|
+
: Math.floor(kept / 2);
|
|
32
|
+
const prefixGraphemeCount = kept - suffixGraphemeCount;
|
|
33
|
+
const prefixText = graphemes.slice(0, prefixGraphemeCount).join('');
|
|
34
|
+
const suffixText = suffixGraphemeCount > 0
|
|
35
|
+
? graphemes.slice(-suffixGraphemeCount).join('')
|
|
36
|
+
: '';
|
|
37
|
+
return {
|
|
38
|
+
prefixText,
|
|
39
|
+
prefixGraphemeCount,
|
|
40
|
+
suffixText,
|
|
41
|
+
suffixGraphemeCount,
|
|
42
|
+
text: prefixText + ELLIPSIS + suffixText,
|
|
43
|
+
truncated: true,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Middle-truncates a string so `prefix...suffix` fits within `availableWidth`.
|
|
48
|
+
* Uses binary search over grapheme clusters with an injectable measure function.
|
|
49
|
+
*/
|
|
50
|
+
function middleTruncate(graphemes, availableWidth, measure, fullWidth) {
|
|
51
|
+
const fullText = graphemes.join('');
|
|
52
|
+
const resolvedFullWidth = fullWidth ?? measure(fullText);
|
|
53
|
+
if (availableWidth <= 0 || graphemes.length === 0) {
|
|
54
|
+
return {
|
|
55
|
+
prefixText: fullText,
|
|
56
|
+
prefixGraphemeCount: graphemes.length,
|
|
57
|
+
suffixText: '',
|
|
58
|
+
suffixGraphemeCount: 0,
|
|
59
|
+
text: fullText,
|
|
60
|
+
truncated: false,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
if (resolvedFullWidth <= availableWidth) {
|
|
64
|
+
return {
|
|
65
|
+
prefixText: fullText,
|
|
66
|
+
prefixGraphemeCount: graphemes.length,
|
|
67
|
+
suffixText: '',
|
|
68
|
+
suffixGraphemeCount: 0,
|
|
69
|
+
text: fullText,
|
|
70
|
+
truncated: false,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
// Binary search for the maximum number of kept graphemes
|
|
74
|
+
let lo = 0;
|
|
75
|
+
let hi = graphemes.length - 1;
|
|
76
|
+
let best = -1;
|
|
77
|
+
while (lo <= hi) {
|
|
78
|
+
const mid = (lo + hi) >>> 1;
|
|
79
|
+
const candidate = buildCandidate(graphemes, mid);
|
|
80
|
+
if (measure(candidate.text) <= availableWidth) {
|
|
81
|
+
best = mid;
|
|
82
|
+
lo = mid + 1;
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
hi = mid - 1;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (best === -1) {
|
|
89
|
+
return {
|
|
90
|
+
prefixText: '',
|
|
91
|
+
prefixGraphemeCount: 0,
|
|
92
|
+
suffixText: '',
|
|
93
|
+
suffixGraphemeCount: 0,
|
|
94
|
+
text: '',
|
|
95
|
+
truncated: true,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
return buildCandidate(graphemes, best);
|
|
99
|
+
}
|
|
100
|
+
export { middleTruncate, toGraphemes, ELLIPSIS, MIN_START, MIN_END };
|
|
101
|
+
//# sourceMappingURL=truncate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"truncate.js","sourceRoot":"","sources":["../../../../../src/components/new-trace-viewer/components/middle-truncate/truncate.ts"],"names":[],"mappings":"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","sourcesContent":["const ELLIPSIS = '...';\nconst MIN_START = 3;\nconst MIN_END = 3;\nconst MIN_KEPT = MIN_START + MIN_END;\nconst graphemeSegmenter =\n typeof Intl !== 'undefined' && 'Segmenter' in Intl\n ? new Intl.Segmenter(undefined, { granularity: 'grapheme' })\n : null;\n\ntype MeasureFn = (text: string) => number;\n\n/**\n * Splits a string into grapheme clusters using Intl.Segmenter.\n * Falls back to Array.from for environments without Intl.Segmenter.\n */\nfunction toGraphemes(text: string): string[] {\n if (graphemeSegmenter) {\n return [...graphemeSegmenter.segment(text)].map((s) => s.segment);\n }\n return Array.from(text);\n}\n\ninterface TruncateResult {\n prefixText: string;\n prefixGraphemeCount: number;\n suffixText: string;\n suffixGraphemeCount: number;\n text: string;\n truncated: boolean;\n}\n\nfunction buildCandidate(graphemes: string[], kept: number): TruncateResult {\n if (kept <= 0) {\n return {\n prefixText: '',\n prefixGraphemeCount: 0,\n suffixText: '',\n suffixGraphemeCount: 0,\n text: ELLIPSIS,\n truncated: true,\n };\n }\n\n const suffixGraphemeCount =\n kept >= MIN_KEPT\n ? Math.max(MIN_END, Math.floor(kept / 2))\n : Math.floor(kept / 2);\n const prefixGraphemeCount = kept - suffixGraphemeCount;\n const prefixText = graphemes.slice(0, prefixGraphemeCount).join('');\n const suffixText =\n suffixGraphemeCount > 0\n ? graphemes.slice(-suffixGraphemeCount).join('')\n : '';\n\n return {\n prefixText,\n prefixGraphemeCount,\n suffixText,\n suffixGraphemeCount,\n text: prefixText + ELLIPSIS + suffixText,\n truncated: true,\n };\n}\n\n/**\n * Middle-truncates a string so `prefix...suffix` fits within `availableWidth`.\n * Uses binary search over grapheme clusters with an injectable measure function.\n */\nfunction middleTruncate(\n graphemes: string[],\n availableWidth: number,\n measure: MeasureFn,\n fullWidth?: number\n): TruncateResult {\n const fullText = graphemes.join('');\n const resolvedFullWidth = fullWidth ?? measure(fullText);\n\n if (availableWidth <= 0 || graphemes.length === 0) {\n return {\n prefixText: fullText,\n prefixGraphemeCount: graphemes.length,\n suffixText: '',\n suffixGraphemeCount: 0,\n text: fullText,\n truncated: false,\n };\n }\n\n if (resolvedFullWidth <= availableWidth) {\n return {\n prefixText: fullText,\n prefixGraphemeCount: graphemes.length,\n suffixText: '',\n suffixGraphemeCount: 0,\n text: fullText,\n truncated: false,\n };\n }\n\n // Binary search for the maximum number of kept graphemes\n let lo = 0;\n let hi = graphemes.length - 1;\n let best = -1;\n\n while (lo <= hi) {\n const mid = (lo + hi) >>> 1;\n const candidate = buildCandidate(graphemes, mid);\n\n if (measure(candidate.text) <= availableWidth) {\n best = mid;\n lo = mid + 1;\n } else {\n hi = mid - 1;\n }\n }\n\n if (best === -1) {\n return {\n prefixText: '',\n prefixGraphemeCount: 0,\n suffixText: '',\n suffixGraphemeCount: 0,\n text: '',\n truncated: true,\n };\n }\n\n return buildCandidate(graphemes, best);\n}\n\nexport { middleTruncate, toGraphemes, ELLIPSIS, MIN_START, MIN_END };\nexport type { MeasureFn, TruncateResult };\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Middle-truncation logic. Returns refs to attach to the container and measurement elements, plus the truncated display text. Recalculates on resize, font loading, and value changes.
|
|
3
|
+
* Powers the `<MiddleTruncate>` (`<span>`) component.
|
|
4
|
+
*
|
|
5
|
+
* Documentation: [Geist Middle Truncate](https://vercel.com/geist/middle-truncate)
|
|
6
|
+
*
|
|
7
|
+
* @param value - Full text string to truncate.
|
|
8
|
+
*/
|
|
9
|
+
declare function useMiddleTruncate(value: string): {
|
|
10
|
+
ref: React.RefObject<HTMLSpanElement | null>;
|
|
11
|
+
measureRef: React.RefObject<HTMLSpanElement | null>;
|
|
12
|
+
displayText: string;
|
|
13
|
+
isTruncated: boolean;
|
|
14
|
+
prefixGraphemeCount: number;
|
|
15
|
+
prefixText: string;
|
|
16
|
+
suffixGraphemeCount: number;
|
|
17
|
+
suffixText: string;
|
|
18
|
+
};
|
|
19
|
+
export { useMiddleTruncate };
|
|
20
|
+
//# sourceMappingURL=use-middle-truncate.d.ts.map
|
package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-middle-truncate.d.ts","sourceRoot":"","sources":["../../../../../src/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.ts"],"names":[],"mappings":"AAsCA;;;;;;;GAOG;AACH,iBAAS,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG;IACzC,GAAG,EAAE,KAAK,CAAC,SAAS,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IAC7C,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IACpD,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;CACpB,CA6GA;AAED,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
|