@mastra/playground-ui 53.1.0-alpha.2 → 54.0.0-alpha.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.
Files changed (36) hide show
  1. package/dist/components/LogsDataList.cjs.js +0 -1
  2. package/dist/components/LogsDataList.cjs.js.map +1 -1
  3. package/dist/components/LogsDataList.es.js +0 -1
  4. package/dist/components/LogsDataList.es.js.map +1 -1
  5. package/dist/domains/traces/components/timeline-name-col.cjs.js +9 -4
  6. package/dist/domains/traces/components/timeline-name-col.cjs.js.map +1 -1
  7. package/dist/domains/traces/components/timeline-name-col.es.js +9 -4
  8. package/dist/domains/traces/components/timeline-name-col.es.js.map +1 -1
  9. package/dist/domains/traces/components/trace-timeline-span.cjs.js +3 -0
  10. package/dist/domains/traces/components/trace-timeline-span.cjs.js.map +1 -1
  11. package/dist/domains/traces/components/trace-timeline-span.es.js +3 -0
  12. package/dist/domains/traces/components/trace-timeline-span.es.js.map +1 -1
  13. package/dist/domains/traces/components/trace-timeline.cjs.js +2 -0
  14. package/dist/domains/traces/components/trace-timeline.cjs.js.map +1 -1
  15. package/dist/domains/traces/components/trace-timeline.es.js +2 -0
  16. package/dist/domains/traces/components/trace-timeline.es.js.map +1 -1
  17. package/dist/ee/signals/components/entity-index-list.cjs.js +0 -1
  18. package/dist/ee/signals/components/entity-index-list.cjs.js.map +1 -1
  19. package/dist/ee/signals/components/entity-index-list.es.js +0 -1
  20. package/dist/ee/signals/components/entity-index-list.es.js.map +1 -1
  21. package/dist/resize/collapsible-panel.cjs.js +36 -124
  22. package/dist/resize/collapsible-panel.cjs.js.map +1 -1
  23. package/dist/resize/collapsible-panel.es.js +38 -126
  24. package/dist/resize/collapsible-panel.es.js.map +1 -1
  25. package/dist/src/domains/traces/components/timeline-name-col.d.ts +2 -1
  26. package/dist/src/domains/traces/components/trace-timeline-span.d.ts +2 -1
  27. package/dist/src/domains/traces/components/trace-timeline.d.ts +3 -1
  28. package/dist/src/lib/resize/collapsible-panel.d.ts +9 -1
  29. package/dist/style.css +1 -57
  30. package/package.json +8 -8
  31. package/dist/resize/use-clamped-element-cursor.cjs.js +0 -56
  32. package/dist/resize/use-clamped-element-cursor.cjs.js.map +0 -1
  33. package/dist/resize/use-clamped-element-cursor.d.ts +0 -2
  34. package/dist/resize/use-clamped-element-cursor.es.js +0 -51
  35. package/dist/resize/use-clamped-element-cursor.es.js.map +0 -1
  36. package/dist/src/lib/resize/use-clamped-element-cursor.d.ts +0 -16
@@ -3,84 +3,15 @@
3
3
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
4
 
5
5
  const jsxRuntime = require('react/jsx-runtime');
6
- const lucideReact = require('lucide-react');
7
6
  const React = require('react');
8
7
  const reactResizablePanels = require('react-resizable-panels');
9
8
  const resize_panelEdgeIcon = require('./panel-edge-icon.cjs.js');
10
9
  const resize_panelIconButton = require('./panel-icon-button.cjs.js');
11
- const resize_useClampedElementCursor = require('./use-clamped-element-cursor.cjs.js');
10
+ const tooltip = require('../tooltip-DIi_oOxO.cjs');
12
11
  const icons_Icon = require('../icons/Icon.cjs.js');
12
+ require('lucide-react');
13
13
  const utils_cn = require('../cn-DCPcv4xv.cjs');
14
14
 
15
- const PILL_EDGE_MARGIN = 22;
16
- const useCollapsedEdgePill = ({
17
- collapsed,
18
- direction,
19
- elementRef
20
- }) => {
21
- const expandButtonRef = React.useRef(null);
22
- const pillRef = React.useRef(null);
23
- const {
24
- beginTracking: beginPillTracking,
25
- elementRef: stripRef,
26
- endTracking: endPillTracking,
27
- updateTracking: updatePillTracking
28
- } = resize_useClampedElementCursor.useClampedElementCursor({
29
- axis: "y",
30
- margin: PILL_EDGE_MARGIN,
31
- variableName: "--pill-y"
32
- });
33
- const setEdgeHovered = React.useCallback((hovered) => {
34
- const expandButton = expandButtonRef.current;
35
- const pill = pillRef.current;
36
- if (expandButton) expandButton.dataset.edgeHovered = hovered ? "true" : "false";
37
- if (pill) pill.dataset.edgeHovered = hovered ? "true" : "false";
38
- }, []);
39
- const spawnPill = React.useCallback(
40
- (point) => {
41
- const pill = pillRef.current;
42
- if (!pill) return;
43
- beginPillTracking(point);
44
- pill.style.transitionProperty = "opacity, translate";
45
- requestAnimationFrame(() => {
46
- pill.style.transitionProperty = "";
47
- });
48
- },
49
- [beginPillTracking]
50
- );
51
- const trackPillPosition = React.useCallback(
52
- (point) => {
53
- updatePillTracking(point);
54
- },
55
- [updatePillTracking]
56
- );
57
- React.useEffect(() => {
58
- if (!collapsed) return;
59
- const panelElement = elementRef.current;
60
- const separator = direction === "left" ? panelElement?.nextElementSibling : panelElement?.previousElementSibling;
61
- if (!(separator instanceof HTMLElement) || !separator.hasAttribute("data-separator")) return;
62
- const show = (event) => {
63
- setEdgeHovered(true);
64
- spawnPill(event);
65
- };
66
- const hide = () => {
67
- setEdgeHovered(false);
68
- endPillTracking();
69
- };
70
- const follow = (event) => trackPillPosition(event);
71
- separator.addEventListener("pointerenter", show);
72
- separator.addEventListener("pointerleave", hide);
73
- separator.addEventListener("pointermove", follow);
74
- return () => {
75
- separator.removeEventListener("pointerenter", show);
76
- separator.removeEventListener("pointerleave", hide);
77
- separator.removeEventListener("pointermove", follow);
78
- setEdgeHovered(false);
79
- endPillTracking();
80
- };
81
- }, [collapsed, direction, elementRef, endPillTracking, setEdgeHovered, spawnPill, trackPillPosition]);
82
- return { endPillTracking, expandButtonRef, stripRef, pillRef, spawnPill, trackPillPosition };
83
- };
84
15
  const CollapsiblePanel = ({
85
16
  collapsedSize,
86
17
  children,
@@ -89,28 +20,44 @@ const CollapsiblePanel = ({
89
20
  onResize,
90
21
  style,
91
22
  minSize,
23
+ defaultSize,
24
+ panelRef: externalPanelRef,
25
+ ref,
92
26
  ...props
93
27
  }) => {
94
- const [collapsed, setCollapsed] = React.useState(false);
95
- const panelRef = reactResizablePanels.usePanelRef();
96
- const elementRef = React.useRef(null);
97
- const { endPillTracking, expandButtonRef, stripRef, pillRef, spawnPill, trackPillPosition } = useCollapsedEdgePill({
98
- collapsed,
99
- direction,
100
- elementRef
101
- });
102
- const expand = () => panelRef.current?.expand();
28
+ const [isCollapsed, setIsCollapsed] = React.useState(false);
29
+ const sizeBeforeCollapseRef = React.useRef(null);
30
+ const internalPanelRef = reactResizablePanels.usePanelRef();
31
+ const panelRef = externalPanelRef ?? internalPanelRef;
32
+ const collapse = () => {
33
+ const panel = panelRef.current;
34
+ if (!panel) return;
35
+ sizeBeforeCollapseRef.current = panel.getSize().inPixels;
36
+ panel.collapse();
37
+ };
38
+ const expand = () => {
39
+ const panel = panelRef.current;
40
+ if (!panel) return;
41
+ const target = sizeBeforeCollapseRef.current ?? defaultSize;
42
+ if (target === void 0) {
43
+ panel.expand();
44
+ return;
45
+ }
46
+ panel.resize(target);
47
+ };
48
+ React.useImperativeHandle(ref, () => ({ collapse, expand }));
103
49
  const numericMinSize = typeof minSize === "number" ? minSize : null;
104
50
  return /* @__PURE__ */ jsxRuntime.jsxs(
105
51
  reactResizablePanels.Panel,
106
52
  {
107
53
  panelRef,
108
- elementRef,
109
54
  collapsedSize,
110
55
  minSize,
56
+ defaultSize,
111
57
  className: utils_cn.cn("relative", className),
112
58
  style: {
113
- overflow: collapsed ? "visible" : "hidden",
59
+ // The expand button must remain visible once the panel is at zero width.
60
+ overflow: isCollapsed ? "visible" : "hidden",
114
61
  "--panel-min-w": numericMinSize ? `${numericMinSize}px` : void 0,
115
62
  ...style
116
63
  },
@@ -118,23 +65,22 @@ const CollapsiblePanel = ({
118
65
  onResize: (size, id, previousSize) => {
119
66
  onResize?.(size, id, previousSize);
120
67
  if (typeof collapsedSize !== "number") return;
121
- setCollapsed(size.inPixels <= collapsedSize);
68
+ setIsCollapsed(size.inPixels <= collapsedSize);
122
69
  },
123
70
  children: [
124
71
  /* @__PURE__ */ jsxRuntime.jsx(
125
72
  "div",
126
73
  {
127
- hidden: collapsed,
74
+ hidden: isCollapsed,
128
75
  style: { minWidth: "var(--panel-min-w)" },
129
76
  className: utils_cn.cn("absolute inset-y-0 w-full overflow-hidden", direction === "left" ? "left-0" : "right-0"),
130
77
  children
131
78
  }
132
79
  ),
133
- collapsed && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
134
- /* @__PURE__ */ jsxRuntime.jsx(
80
+ isCollapsed && /* @__PURE__ */ jsxRuntime.jsxs(tooltip.Tooltip, { children: [
81
+ /* @__PURE__ */ jsxRuntime.jsx(tooltip.TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
135
82
  "button",
136
83
  {
137
- ref: expandButtonRef,
138
84
  type: "button",
139
85
  "aria-label": "Expand panel",
140
86
  onClick: expand,
@@ -142,46 +88,12 @@ const CollapsiblePanel = ({
142
88
  resize_panelIconButton.panelIconButtonClass,
143
89
  "absolute top-2 z-10",
144
90
  "transition-[color,background-color,opacity] duration-300 starting:opacity-0",
145
- direction === "left" ? "left-2" : "right-2",
146
- "data-[edge-hovered=true]:text-neutral6"
91
+ direction === "left" ? "left-2" : "right-2"
147
92
  ),
148
93
  children: /* @__PURE__ */ jsxRuntime.jsx(icons_Icon.Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(resize_panelEdgeIcon.PanelEdgeIcon, { side: direction }) })
149
94
  }
150
- ),
151
- /* @__PURE__ */ jsxRuntime.jsx(
152
- "button",
153
- {
154
- ref: stripRef,
155
- type: "button",
156
- tabIndex: -1,
157
- "aria-hidden": "true",
158
- onClick: expand,
159
- onPointerEnter: (event) => spawnPill(event),
160
- onPointerLeave: endPillTracking,
161
- onPointerMove: (event) => trackPillPosition(event),
162
- style: { "--pill-y": "50%" },
163
- className: utils_cn.cn(
164
- "group/expand absolute inset-y-0 z-10 w-4 cursor-pointer focus-visible:outline-hidden",
165
- direction === "left" ? "left-1" : "right-1"
166
- ),
167
- children: /* @__PURE__ */ jsxRuntime.jsx(
168
- "span",
169
- {
170
- ref: pillRef,
171
- style: { top: "var(--pill-y)" },
172
- className: utils_cn.cn(
173
- "absolute flex size-7 -translate-y-1/2 items-center justify-center rounded-full bg-neutral6 text-surface1 shadow-dialog",
174
- "pointer-events-none opacity-0 transition-[opacity,translate,top] duration-150 ease-out-custom motion-reduce:transition-none",
175
- direction === "left" ? "left-0.5 -translate-x-1" : "right-0.5 translate-x-1",
176
- "group-hover/expand:pointer-events-auto group-hover/expand:translate-x-0 group-hover/expand:opacity-100",
177
- "group-active/expand:bg-neutral6/80",
178
- "data-[edge-hovered=true]:pointer-events-auto data-[edge-hovered=true]:translate-x-0 data-[edge-hovered=true]:opacity-100"
179
- ),
180
- children: /* @__PURE__ */ jsxRuntime.jsx(icons_Icon.Icon, { children: direction === "left" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, {}) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, {}) })
181
- }
182
- )
183
- }
184
- )
95
+ ) }),
96
+ /* @__PURE__ */ jsxRuntime.jsx(tooltip.TooltipContent, { side: direction === "left" ? "right" : "left", children: "Expand panel" })
185
97
  ] })
186
98
  ]
187
99
  }
@@ -1 +1 @@
1
- {"version":3,"file":"collapsible-panel.cjs.js","sources":["../../src/lib/resize/collapsible-panel.tsx"],"sourcesContent":["import { ChevronLeft, ChevronRight } from 'lucide-react';\nimport type { CSSProperties, RefObject } from 'react';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport type { PanelProps } from 'react-resizable-panels';\nimport { Panel, usePanelRef } from 'react-resizable-panels';\nimport { PanelEdgeIcon } from './panel-edge-icon';\nimport { panelIconButtonClass } from './panel-icon-button';\nimport { useClampedElementCursor } from './use-clamped-element-cursor';\nimport { Icon } from '@/ds/icons';\nimport { cn } from '@/lib/utils';\n\nexport interface CollapsiblePanelProps extends PanelProps {\n direction: 'left' | 'right';\n}\n\n// The expand pill follows the pointer vertically along the edge, clamped so\n// it never bleeds past the strip's ends.\nconst PILL_EDGE_MARGIN = 22;\n\ntype PanelElementRef = RefObject<HTMLDivElement | null>;\n\nconst useCollapsedEdgePill = ({\n collapsed,\n direction,\n elementRef,\n}: {\n collapsed: boolean;\n direction: CollapsiblePanelProps['direction'];\n elementRef: PanelElementRef;\n}) => {\n const expandButtonRef = useRef<HTMLButtonElement | null>(null);\n const pillRef = useRef<HTMLSpanElement | null>(null);\n const {\n beginTracking: beginPillTracking,\n elementRef: stripRef,\n endTracking: endPillTracking,\n updateTracking: updatePillTracking,\n } = useClampedElementCursor<HTMLButtonElement>({\n axis: 'y',\n margin: PILL_EDGE_MARGIN,\n variableName: '--pill-y',\n });\n\n const setEdgeHovered = useCallback((hovered: boolean) => {\n const expandButton = expandButtonRef.current;\n const pill = pillRef.current;\n if (expandButton) expandButton.dataset.edgeHovered = hovered ? 'true' : 'false';\n if (pill) pill.dataset.edgeHovered = hovered ? 'true' : 'false';\n }, []);\n\n const spawnPill = useCallback(\n (point: { clientX: number; clientY: number }) => {\n const pill = pillRef.current;\n if (!pill) return;\n beginPillTracking(point);\n pill.style.transitionProperty = 'opacity, translate';\n // Re-enable top transitions after the browser commits the pill's new\n // starting position; otherwise it travels in from its previous position.\n requestAnimationFrame(() => {\n pill.style.transitionProperty = '';\n });\n },\n [beginPillTracking],\n );\n\n const trackPillPosition = useCallback(\n (point: { clientX: number; clientY: number }) => {\n updatePillTracking(point);\n },\n [updatePillTracking],\n );\n\n useEffect(() => {\n if (!collapsed) return;\n const panelElement = elementRef.current;\n const separator = direction === 'left' ? panelElement?.nextElementSibling : panelElement?.previousElementSibling;\n if (!(separator instanceof HTMLElement) || !separator.hasAttribute('data-separator')) return;\n\n const show = (event: PointerEvent) => {\n setEdgeHovered(true);\n spawnPill(event);\n };\n const hide = () => {\n setEdgeHovered(false);\n endPillTracking();\n };\n const follow = (event: PointerEvent) => trackPillPosition(event);\n separator.addEventListener('pointerenter', show);\n separator.addEventListener('pointerleave', hide);\n separator.addEventListener('pointermove', follow);\n return () => {\n separator.removeEventListener('pointerenter', show);\n separator.removeEventListener('pointerleave', hide);\n separator.removeEventListener('pointermove', follow);\n setEdgeHovered(false);\n endPillTracking();\n };\n }, [collapsed, direction, elementRef, endPillTracking, setEdgeHovered, spawnPill, trackPillPosition]);\n\n return { endPillTracking, expandButtonRef, stripRef, pillRef, spawnPill, trackPillPosition };\n};\n\nexport const CollapsiblePanel = ({\n collapsedSize,\n children,\n direction,\n className,\n onResize,\n style,\n minSize,\n ...props\n}: CollapsiblePanelProps) => {\n const [collapsed, setCollapsed] = useState(false);\n const panelRef = usePanelRef();\n const elementRef = useRef<HTMLDivElement | null>(null);\n const { endPillTracking, expandButtonRef, stripRef, pillRef, spawnPill, trackPillPosition } = useCollapsedEdgePill({\n collapsed,\n direction,\n elementRef,\n });\n\n const expand = () => panelRef.current?.expand();\n\n const numericMinSize = typeof minSize === 'number' ? minSize : null;\n\n return (\n <Panel\n panelRef={panelRef}\n elementRef={elementRef}\n collapsedSize={collapsedSize}\n minSize={minSize}\n className={cn('relative', className)}\n style={\n {\n overflow: collapsed ? 'visible' : 'hidden',\n '--panel-min-w': numericMinSize ? `${numericMinSize}px` : undefined,\n ...style,\n } as CSSProperties\n }\n {...props}\n onResize={(size, id, previousSize) => {\n onResize?.(size, id, previousSize);\n if (typeof collapsedSize !== 'number') return;\n setCollapsed(size.inPixels <= collapsedSize);\n }}\n >\n <div\n hidden={collapsed}\n style={{ minWidth: 'var(--panel-min-w)' }}\n className={cn('absolute inset-y-0 w-full overflow-hidden', direction === 'left' ? 'left-0' : 'right-0')}\n >\n {children}\n </div>\n\n {collapsed && (\n <>\n <button\n ref={expandButtonRef}\n type=\"button\"\n aria-label=\"Expand panel\"\n onClick={expand}\n className={cn(\n panelIconButtonClass,\n 'absolute top-2 z-10',\n 'transition-[color,background-color,opacity] duration-300 starting:opacity-0',\n direction === 'left' ? 'left-2' : 'right-2',\n 'data-[edge-hovered=true]:text-neutral6',\n )}\n >\n <Icon>\n <PanelEdgeIcon side={direction} />\n </Icon>\n </button>\n\n <button\n ref={stripRef}\n type=\"button\"\n tabIndex={-1}\n aria-hidden=\"true\"\n onClick={expand}\n onPointerEnter={event => spawnPill(event)}\n onPointerLeave={endPillTracking}\n onPointerMove={event => trackPillPosition(event)}\n style={{ '--pill-y': '50%' } as CSSProperties}\n className={cn(\n 'group/expand absolute inset-y-0 z-10 w-4 cursor-pointer focus-visible:outline-hidden',\n direction === 'left' ? 'left-1' : 'right-1',\n )}\n >\n <span\n ref={pillRef}\n style={{ top: 'var(--pill-y)' }}\n className={cn(\n 'absolute flex size-7 -translate-y-1/2 items-center justify-center rounded-full bg-neutral6 text-surface1 shadow-dialog',\n 'pointer-events-none opacity-0 transition-[opacity,translate,top] duration-150 ease-out-custom motion-reduce:transition-none',\n direction === 'left' ? 'left-0.5 -translate-x-1' : 'right-0.5 translate-x-1',\n 'group-hover/expand:pointer-events-auto group-hover/expand:translate-x-0 group-hover/expand:opacity-100',\n 'group-active/expand:bg-neutral6/80',\n 'data-[edge-hovered=true]:pointer-events-auto data-[edge-hovered=true]:translate-x-0 data-[edge-hovered=true]:opacity-100',\n )}\n >\n <Icon>{direction === 'left' ? <ChevronRight /> : <ChevronLeft />}</Icon>\n </span>\n </button>\n </>\n )}\n </Panel>\n );\n};\n"],"names":["useRef","useClampedElementCursor","useCallback","useEffect","useState","usePanelRef","jsxs","Panel","cn","jsx","Fragment","panelIconButtonClass","Icon","PanelEdgeIcon","ChevronRight","ChevronLeft"],"mappings":"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"}
1
+ {"version":3,"file":"collapsible-panel.cjs.js","sources":["../../src/lib/resize/collapsible-panel.tsx"],"sourcesContent":["import type { CSSProperties, Ref } from 'react';\nimport { useImperativeHandle, useRef, useState } from 'react';\nimport type { PanelProps } from 'react-resizable-panels';\nimport { Panel, usePanelRef } from 'react-resizable-panels';\nimport { PanelEdgeIcon } from './panel-edge-icon';\nimport { panelIconButtonClass } from './panel-icon-button';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/ds/components/Tooltip';\nimport { Icon } from '@/ds/icons';\nimport { cn } from '@/lib/utils';\n\n/** Programmatic control over a CollapsiblePanel (distinct from the library's panel handle). */\nexport interface CollapsiblePanelHandle {\n collapse: () => void;\n /** Reopens at the width the panel had when `collapse()` was called, else at `defaultSize`. */\n expand: () => void;\n}\n\nexport interface CollapsiblePanelProps extends PanelProps {\n direction: 'left' | 'right';\n ref?: Ref<CollapsiblePanelHandle>;\n}\n\nexport const CollapsiblePanel = ({\n collapsedSize,\n children,\n direction,\n className,\n onResize,\n style,\n minSize,\n defaultSize,\n panelRef: externalPanelRef,\n ref,\n ...props\n}: CollapsiblePanelProps) => {\n // Physical state of the panel, as reported by onResize. It drives what is rendered.\n const [isCollapsed, setIsCollapsed] = useState(false);\n // Width the panel had right before we collapsed it. The library's `expand()`\n // relies on its own \"most recent size\", which is unreliable when the panel\n // mounts already collapsed from a persisted layout (it opens at `minSize`).\n const sizeBeforeCollapseRef = useRef<number | null>(null);\n const internalPanelRef = usePanelRef();\n const panelRef = externalPanelRef ?? internalPanelRef;\n\n const collapse = () => {\n const panel = panelRef.current;\n if (!panel) return;\n sizeBeforeCollapseRef.current = panel.getSize().inPixels;\n panel.collapse();\n };\n\n const expand = () => {\n const panel = panelRef.current;\n if (!panel) return;\n const target = sizeBeforeCollapseRef.current ?? defaultSize;\n if (target === undefined) {\n panel.expand();\n return;\n }\n panel.resize(target);\n };\n\n useImperativeHandle(ref, () => ({ collapse, expand }));\n\n const numericMinSize = typeof minSize === 'number' ? minSize : null;\n\n return (\n <Panel\n panelRef={panelRef}\n collapsedSize={collapsedSize}\n minSize={minSize}\n defaultSize={defaultSize}\n className={cn('relative', className)}\n style={\n {\n // The expand button must remain visible once the panel is at zero width.\n overflow: isCollapsed ? 'visible' : 'hidden',\n '--panel-min-w': numericMinSize ? `${numericMinSize}px` : undefined,\n ...style,\n } as CSSProperties\n }\n {...props}\n onResize={(size, id, previousSize) => {\n onResize?.(size, id, previousSize);\n if (typeof collapsedSize !== 'number') return;\n setIsCollapsed(size.inPixels <= collapsedSize);\n }}\n >\n <div\n hidden={isCollapsed}\n style={{ minWidth: 'var(--panel-min-w)' }}\n className={cn('absolute inset-y-0 w-full overflow-hidden', direction === 'left' ? 'left-0' : 'right-0')}\n >\n {children}\n </div>\n\n {isCollapsed && (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n aria-label=\"Expand panel\"\n onClick={expand}\n className={cn(\n panelIconButtonClass,\n 'absolute top-2 z-10',\n 'transition-[color,background-color,opacity] duration-300 starting:opacity-0',\n direction === 'left' ? 'left-2' : 'right-2',\n )}\n >\n <Icon>\n <PanelEdgeIcon side={direction} />\n </Icon>\n </button>\n </TooltipTrigger>\n <TooltipContent side={direction === 'left' ? 'right' : 'left'}>Expand panel</TooltipContent>\n </Tooltip>\n )}\n </Panel>\n );\n};\n"],"names":["useState","useRef","usePanelRef","useImperativeHandle","jsxs","Panel","cn","jsx","Tooltip","TooltipTrigger","panelIconButtonClass","Icon","PanelEdgeIcon","TooltipContent"],"mappings":"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"}
@@ -1,82 +1,13 @@
1
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
- import { ChevronRight, ChevronLeft } from 'lucide-react';
3
- import { useState, useRef, useCallback, useEffect } from 'react';
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { useState, useRef, useImperativeHandle } from 'react';
4
3
  import { usePanelRef, Panel } from 'react-resizable-panels';
5
4
  import { PanelEdgeIcon } from './panel-edge-icon.es.js';
6
5
  import { panelIconButtonClass } from './panel-icon-button.es.js';
7
- import { useClampedElementCursor } from './use-clamped-element-cursor.es.js';
6
+ import { T as Tooltip, c as TooltipTrigger, a as TooltipContent } from '../tooltip-Bi0pDO5P.js';
8
7
  import { Icon } from '../icons/Icon.es.js';
8
+ import 'lucide-react';
9
9
  import { c as cn } from '../cn-B4oPhFx9.js';
10
10
 
11
- const PILL_EDGE_MARGIN = 22;
12
- const useCollapsedEdgePill = ({
13
- collapsed,
14
- direction,
15
- elementRef
16
- }) => {
17
- const expandButtonRef = useRef(null);
18
- const pillRef = useRef(null);
19
- const {
20
- beginTracking: beginPillTracking,
21
- elementRef: stripRef,
22
- endTracking: endPillTracking,
23
- updateTracking: updatePillTracking
24
- } = useClampedElementCursor({
25
- axis: "y",
26
- margin: PILL_EDGE_MARGIN,
27
- variableName: "--pill-y"
28
- });
29
- const setEdgeHovered = useCallback((hovered) => {
30
- const expandButton = expandButtonRef.current;
31
- const pill = pillRef.current;
32
- if (expandButton) expandButton.dataset.edgeHovered = hovered ? "true" : "false";
33
- if (pill) pill.dataset.edgeHovered = hovered ? "true" : "false";
34
- }, []);
35
- const spawnPill = useCallback(
36
- (point) => {
37
- const pill = pillRef.current;
38
- if (!pill) return;
39
- beginPillTracking(point);
40
- pill.style.transitionProperty = "opacity, translate";
41
- requestAnimationFrame(() => {
42
- pill.style.transitionProperty = "";
43
- });
44
- },
45
- [beginPillTracking]
46
- );
47
- const trackPillPosition = useCallback(
48
- (point) => {
49
- updatePillTracking(point);
50
- },
51
- [updatePillTracking]
52
- );
53
- useEffect(() => {
54
- if (!collapsed) return;
55
- const panelElement = elementRef.current;
56
- const separator = direction === "left" ? panelElement?.nextElementSibling : panelElement?.previousElementSibling;
57
- if (!(separator instanceof HTMLElement) || !separator.hasAttribute("data-separator")) return;
58
- const show = (event) => {
59
- setEdgeHovered(true);
60
- spawnPill(event);
61
- };
62
- const hide = () => {
63
- setEdgeHovered(false);
64
- endPillTracking();
65
- };
66
- const follow = (event) => trackPillPosition(event);
67
- separator.addEventListener("pointerenter", show);
68
- separator.addEventListener("pointerleave", hide);
69
- separator.addEventListener("pointermove", follow);
70
- return () => {
71
- separator.removeEventListener("pointerenter", show);
72
- separator.removeEventListener("pointerleave", hide);
73
- separator.removeEventListener("pointermove", follow);
74
- setEdgeHovered(false);
75
- endPillTracking();
76
- };
77
- }, [collapsed, direction, elementRef, endPillTracking, setEdgeHovered, spawnPill, trackPillPosition]);
78
- return { endPillTracking, expandButtonRef, stripRef, pillRef, spawnPill, trackPillPosition };
79
- };
80
11
  const CollapsiblePanel = ({
81
12
  collapsedSize,
82
13
  children,
@@ -85,28 +16,44 @@ const CollapsiblePanel = ({
85
16
  onResize,
86
17
  style,
87
18
  minSize,
19
+ defaultSize,
20
+ panelRef: externalPanelRef,
21
+ ref,
88
22
  ...props
89
23
  }) => {
90
- const [collapsed, setCollapsed] = useState(false);
91
- const panelRef = usePanelRef();
92
- const elementRef = useRef(null);
93
- const { endPillTracking, expandButtonRef, stripRef, pillRef, spawnPill, trackPillPosition } = useCollapsedEdgePill({
94
- collapsed,
95
- direction,
96
- elementRef
97
- });
98
- const expand = () => panelRef.current?.expand();
24
+ const [isCollapsed, setIsCollapsed] = useState(false);
25
+ const sizeBeforeCollapseRef = useRef(null);
26
+ const internalPanelRef = usePanelRef();
27
+ const panelRef = externalPanelRef ?? internalPanelRef;
28
+ const collapse = () => {
29
+ const panel = panelRef.current;
30
+ if (!panel) return;
31
+ sizeBeforeCollapseRef.current = panel.getSize().inPixels;
32
+ panel.collapse();
33
+ };
34
+ const expand = () => {
35
+ const panel = panelRef.current;
36
+ if (!panel) return;
37
+ const target = sizeBeforeCollapseRef.current ?? defaultSize;
38
+ if (target === void 0) {
39
+ panel.expand();
40
+ return;
41
+ }
42
+ panel.resize(target);
43
+ };
44
+ useImperativeHandle(ref, () => ({ collapse, expand }));
99
45
  const numericMinSize = typeof minSize === "number" ? minSize : null;
100
46
  return /* @__PURE__ */ jsxs(
101
47
  Panel,
102
48
  {
103
49
  panelRef,
104
- elementRef,
105
50
  collapsedSize,
106
51
  minSize,
52
+ defaultSize,
107
53
  className: cn("relative", className),
108
54
  style: {
109
- overflow: collapsed ? "visible" : "hidden",
55
+ // The expand button must remain visible once the panel is at zero width.
56
+ overflow: isCollapsed ? "visible" : "hidden",
110
57
  "--panel-min-w": numericMinSize ? `${numericMinSize}px` : void 0,
111
58
  ...style
112
59
  },
@@ -114,23 +61,22 @@ const CollapsiblePanel = ({
114
61
  onResize: (size, id, previousSize) => {
115
62
  onResize?.(size, id, previousSize);
116
63
  if (typeof collapsedSize !== "number") return;
117
- setCollapsed(size.inPixels <= collapsedSize);
64
+ setIsCollapsed(size.inPixels <= collapsedSize);
118
65
  },
119
66
  children: [
120
67
  /* @__PURE__ */ jsx(
121
68
  "div",
122
69
  {
123
- hidden: collapsed,
70
+ hidden: isCollapsed,
124
71
  style: { minWidth: "var(--panel-min-w)" },
125
72
  className: cn("absolute inset-y-0 w-full overflow-hidden", direction === "left" ? "left-0" : "right-0"),
126
73
  children
127
74
  }
128
75
  ),
129
- collapsed && /* @__PURE__ */ jsxs(Fragment, { children: [
130
- /* @__PURE__ */ jsx(
76
+ isCollapsed && /* @__PURE__ */ jsxs(Tooltip, { children: [
77
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
131
78
  "button",
132
79
  {
133
- ref: expandButtonRef,
134
80
  type: "button",
135
81
  "aria-label": "Expand panel",
136
82
  onClick: expand,
@@ -138,46 +84,12 @@ const CollapsiblePanel = ({
138
84
  panelIconButtonClass,
139
85
  "absolute top-2 z-10",
140
86
  "transition-[color,background-color,opacity] duration-300 starting:opacity-0",
141
- direction === "left" ? "left-2" : "right-2",
142
- "data-[edge-hovered=true]:text-neutral6"
87
+ direction === "left" ? "left-2" : "right-2"
143
88
  ),
144
89
  children: /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(PanelEdgeIcon, { side: direction }) })
145
90
  }
146
- ),
147
- /* @__PURE__ */ jsx(
148
- "button",
149
- {
150
- ref: stripRef,
151
- type: "button",
152
- tabIndex: -1,
153
- "aria-hidden": "true",
154
- onClick: expand,
155
- onPointerEnter: (event) => spawnPill(event),
156
- onPointerLeave: endPillTracking,
157
- onPointerMove: (event) => trackPillPosition(event),
158
- style: { "--pill-y": "50%" },
159
- className: cn(
160
- "group/expand absolute inset-y-0 z-10 w-4 cursor-pointer focus-visible:outline-hidden",
161
- direction === "left" ? "left-1" : "right-1"
162
- ),
163
- children: /* @__PURE__ */ jsx(
164
- "span",
165
- {
166
- ref: pillRef,
167
- style: { top: "var(--pill-y)" },
168
- className: cn(
169
- "absolute flex size-7 -translate-y-1/2 items-center justify-center rounded-full bg-neutral6 text-surface1 shadow-dialog",
170
- "pointer-events-none opacity-0 transition-[opacity,translate,top] duration-150 ease-out-custom motion-reduce:transition-none",
171
- direction === "left" ? "left-0.5 -translate-x-1" : "right-0.5 translate-x-1",
172
- "group-hover/expand:pointer-events-auto group-hover/expand:translate-x-0 group-hover/expand:opacity-100",
173
- "group-active/expand:bg-neutral6/80",
174
- "data-[edge-hovered=true]:pointer-events-auto data-[edge-hovered=true]:translate-x-0 data-[edge-hovered=true]:opacity-100"
175
- ),
176
- children: /* @__PURE__ */ jsx(Icon, { children: direction === "left" ? /* @__PURE__ */ jsx(ChevronRight, {}) : /* @__PURE__ */ jsx(ChevronLeft, {}) })
177
- }
178
- )
179
- }
180
- )
91
+ ) }),
92
+ /* @__PURE__ */ jsx(TooltipContent, { side: direction === "left" ? "right" : "left", children: "Expand panel" })
181
93
  ] })
182
94
  ]
183
95
  }
@@ -1 +1 @@
1
- {"version":3,"file":"collapsible-panel.es.js","sources":["../../src/lib/resize/collapsible-panel.tsx"],"sourcesContent":["import { ChevronLeft, ChevronRight } from 'lucide-react';\nimport type { CSSProperties, RefObject } from 'react';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport type { PanelProps } from 'react-resizable-panels';\nimport { Panel, usePanelRef } from 'react-resizable-panels';\nimport { PanelEdgeIcon } from './panel-edge-icon';\nimport { panelIconButtonClass } from './panel-icon-button';\nimport { useClampedElementCursor } from './use-clamped-element-cursor';\nimport { Icon } from '@/ds/icons';\nimport { cn } from '@/lib/utils';\n\nexport interface CollapsiblePanelProps extends PanelProps {\n direction: 'left' | 'right';\n}\n\n// The expand pill follows the pointer vertically along the edge, clamped so\n// it never bleeds past the strip's ends.\nconst PILL_EDGE_MARGIN = 22;\n\ntype PanelElementRef = RefObject<HTMLDivElement | null>;\n\nconst useCollapsedEdgePill = ({\n collapsed,\n direction,\n elementRef,\n}: {\n collapsed: boolean;\n direction: CollapsiblePanelProps['direction'];\n elementRef: PanelElementRef;\n}) => {\n const expandButtonRef = useRef<HTMLButtonElement | null>(null);\n const pillRef = useRef<HTMLSpanElement | null>(null);\n const {\n beginTracking: beginPillTracking,\n elementRef: stripRef,\n endTracking: endPillTracking,\n updateTracking: updatePillTracking,\n } = useClampedElementCursor<HTMLButtonElement>({\n axis: 'y',\n margin: PILL_EDGE_MARGIN,\n variableName: '--pill-y',\n });\n\n const setEdgeHovered = useCallback((hovered: boolean) => {\n const expandButton = expandButtonRef.current;\n const pill = pillRef.current;\n if (expandButton) expandButton.dataset.edgeHovered = hovered ? 'true' : 'false';\n if (pill) pill.dataset.edgeHovered = hovered ? 'true' : 'false';\n }, []);\n\n const spawnPill = useCallback(\n (point: { clientX: number; clientY: number }) => {\n const pill = pillRef.current;\n if (!pill) return;\n beginPillTracking(point);\n pill.style.transitionProperty = 'opacity, translate';\n // Re-enable top transitions after the browser commits the pill's new\n // starting position; otherwise it travels in from its previous position.\n requestAnimationFrame(() => {\n pill.style.transitionProperty = '';\n });\n },\n [beginPillTracking],\n );\n\n const trackPillPosition = useCallback(\n (point: { clientX: number; clientY: number }) => {\n updatePillTracking(point);\n },\n [updatePillTracking],\n );\n\n useEffect(() => {\n if (!collapsed) return;\n const panelElement = elementRef.current;\n const separator = direction === 'left' ? panelElement?.nextElementSibling : panelElement?.previousElementSibling;\n if (!(separator instanceof HTMLElement) || !separator.hasAttribute('data-separator')) return;\n\n const show = (event: PointerEvent) => {\n setEdgeHovered(true);\n spawnPill(event);\n };\n const hide = () => {\n setEdgeHovered(false);\n endPillTracking();\n };\n const follow = (event: PointerEvent) => trackPillPosition(event);\n separator.addEventListener('pointerenter', show);\n separator.addEventListener('pointerleave', hide);\n separator.addEventListener('pointermove', follow);\n return () => {\n separator.removeEventListener('pointerenter', show);\n separator.removeEventListener('pointerleave', hide);\n separator.removeEventListener('pointermove', follow);\n setEdgeHovered(false);\n endPillTracking();\n };\n }, [collapsed, direction, elementRef, endPillTracking, setEdgeHovered, spawnPill, trackPillPosition]);\n\n return { endPillTracking, expandButtonRef, stripRef, pillRef, spawnPill, trackPillPosition };\n};\n\nexport const CollapsiblePanel = ({\n collapsedSize,\n children,\n direction,\n className,\n onResize,\n style,\n minSize,\n ...props\n}: CollapsiblePanelProps) => {\n const [collapsed, setCollapsed] = useState(false);\n const panelRef = usePanelRef();\n const elementRef = useRef<HTMLDivElement | null>(null);\n const { endPillTracking, expandButtonRef, stripRef, pillRef, spawnPill, trackPillPosition } = useCollapsedEdgePill({\n collapsed,\n direction,\n elementRef,\n });\n\n const expand = () => panelRef.current?.expand();\n\n const numericMinSize = typeof minSize === 'number' ? minSize : null;\n\n return (\n <Panel\n panelRef={panelRef}\n elementRef={elementRef}\n collapsedSize={collapsedSize}\n minSize={minSize}\n className={cn('relative', className)}\n style={\n {\n overflow: collapsed ? 'visible' : 'hidden',\n '--panel-min-w': numericMinSize ? `${numericMinSize}px` : undefined,\n ...style,\n } as CSSProperties\n }\n {...props}\n onResize={(size, id, previousSize) => {\n onResize?.(size, id, previousSize);\n if (typeof collapsedSize !== 'number') return;\n setCollapsed(size.inPixels <= collapsedSize);\n }}\n >\n <div\n hidden={collapsed}\n style={{ minWidth: 'var(--panel-min-w)' }}\n className={cn('absolute inset-y-0 w-full overflow-hidden', direction === 'left' ? 'left-0' : 'right-0')}\n >\n {children}\n </div>\n\n {collapsed && (\n <>\n <button\n ref={expandButtonRef}\n type=\"button\"\n aria-label=\"Expand panel\"\n onClick={expand}\n className={cn(\n panelIconButtonClass,\n 'absolute top-2 z-10',\n 'transition-[color,background-color,opacity] duration-300 starting:opacity-0',\n direction === 'left' ? 'left-2' : 'right-2',\n 'data-[edge-hovered=true]:text-neutral6',\n )}\n >\n <Icon>\n <PanelEdgeIcon side={direction} />\n </Icon>\n </button>\n\n <button\n ref={stripRef}\n type=\"button\"\n tabIndex={-1}\n aria-hidden=\"true\"\n onClick={expand}\n onPointerEnter={event => spawnPill(event)}\n onPointerLeave={endPillTracking}\n onPointerMove={event => trackPillPosition(event)}\n style={{ '--pill-y': '50%' } as CSSProperties}\n className={cn(\n 'group/expand absolute inset-y-0 z-10 w-4 cursor-pointer focus-visible:outline-hidden',\n direction === 'left' ? 'left-1' : 'right-1',\n )}\n >\n <span\n ref={pillRef}\n style={{ top: 'var(--pill-y)' }}\n className={cn(\n 'absolute flex size-7 -translate-y-1/2 items-center justify-center rounded-full bg-neutral6 text-surface1 shadow-dialog',\n 'pointer-events-none opacity-0 transition-[opacity,translate,top] duration-150 ease-out-custom motion-reduce:transition-none',\n direction === 'left' ? 'left-0.5 -translate-x-1' : 'right-0.5 translate-x-1',\n 'group-hover/expand:pointer-events-auto group-hover/expand:translate-x-0 group-hover/expand:opacity-100',\n 'group-active/expand:bg-neutral6/80',\n 'data-[edge-hovered=true]:pointer-events-auto data-[edge-hovered=true]:translate-x-0 data-[edge-hovered=true]:opacity-100',\n )}\n >\n <Icon>{direction === 'left' ? <ChevronRight /> : <ChevronLeft />}</Icon>\n </span>\n </button>\n </>\n )}\n </Panel>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;AAiBA,MAAM,gBAAA,GAAmB,EAAA;AAIzB,MAAM,uBAAuB,CAAC;AAAA,EAC5B,SAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAA,KAIM;AACJ,EAAA,MAAM,eAAA,GAAkB,OAAiC,IAAI,CAAA;AAC7D,EAAA,MAAM,OAAA,GAAU,OAA+B,IAAI,CAAA;AACnD,EAAA,MAAM;AAAA,IACJ,aAAA,EAAe,iBAAA;AAAA,IACf,UAAA,EAAY,QAAA;AAAA,IACZ,WAAA,EAAa,eAAA;AAAA,IACb,cAAA,EAAgB;AAAA,MACd,uBAAA,CAA2C;AAAA,IAC7C,IAAA,EAAM,GAAA;AAAA,IACN,MAAA,EAAQ,gBAAA;AAAA,IACR,YAAA,EAAc;AAAA,GACf,CAAA;AAED,EAAA,MAAM,cAAA,GAAiB,WAAA,CAAY,CAAC,OAAA,KAAqB;AACvD,IAAA,MAAM,eAAe,eAAA,CAAgB,OAAA;AACrC,IAAA,MAAM,OAAO,OAAA,CAAQ,OAAA;AACrB,IAAA,IAAI,YAAA,EAAc,YAAA,CAAa,OAAA,CAAQ,WAAA,GAAc,UAAU,MAAA,GAAS,OAAA;AACxE,IAAA,IAAI,IAAA,EAAM,IAAA,CAAK,OAAA,CAAQ,WAAA,GAAc,UAAU,MAAA,GAAS,OAAA;AAAA,EAC1D,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,SAAA,GAAY,WAAA;AAAA,IAChB,CAAC,KAAA,KAAgD;AAC/C,MAAA,MAAM,OAAO,OAAA,CAAQ,OAAA;AACrB,MAAA,IAAI,CAAC,IAAA,EAAM;AACX,MAAA,iBAAA,CAAkB,KAAK,CAAA;AACvB,MAAA,IAAA,CAAK,MAAM,kBAAA,GAAqB,oBAAA;AAGhC,MAAA,qBAAA,CAAsB,MAAM;AAC1B,QAAA,IAAA,CAAK,MAAM,kBAAA,GAAqB,EAAA;AAAA,MAClC,CAAC,CAAA;AAAA,IACH,CAAA;AAAA,IACA,CAAC,iBAAiB;AAAA,GACpB;AAEA,EAAA,MAAM,iBAAA,GAAoB,WAAA;AAAA,IACxB,CAAC,KAAA,KAAgD;AAC/C,MAAA,kBAAA,CAAmB,KAAK,CAAA;AAAA,IAC1B,CAAA;AAAA,IACA,CAAC,kBAAkB;AAAA,GACrB;AAEA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,SAAA,EAAW;AAChB,IAAA,MAAM,eAAe,UAAA,CAAW,OAAA;AAChC,IAAA,MAAM,SAAA,GAAY,SAAA,KAAc,MAAA,GAAS,YAAA,EAAc,qBAAqB,YAAA,EAAc,sBAAA;AAC1F,IAAA,IAAI,EAAE,SAAA,YAAqB,WAAA,CAAA,IAAgB,CAAC,SAAA,CAAU,YAAA,CAAa,gBAAgB,CAAA,EAAG;AAEtF,IAAA,MAAM,IAAA,GAAO,CAAC,KAAA,KAAwB;AACpC,MAAA,cAAA,CAAe,IAAI,CAAA;AACnB,MAAA,SAAA,CAAU,KAAK,CAAA;AAAA,IACjB,CAAA;AACA,IAAA,MAAM,OAAO,MAAM;AACjB,MAAA,cAAA,CAAe,KAAK,CAAA;AACpB,MAAA,eAAA,EAAgB;AAAA,IAClB,CAAA;AACA,IAAA,MAAM,MAAA,GAAS,CAAC,KAAA,KAAwB,iBAAA,CAAkB,KAAK,CAAA;AAC/D,IAAA,SAAA,CAAU,gBAAA,CAAiB,gBAAgB,IAAI,CAAA;AAC/C,IAAA,SAAA,CAAU,gBAAA,CAAiB,gBAAgB,IAAI,CAAA;AAC/C,IAAA,SAAA,CAAU,gBAAA,CAAiB,eAAe,MAAM,CAAA;AAChD,IAAA,OAAO,MAAM;AACX,MAAA,SAAA,CAAU,mBAAA,CAAoB,gBAAgB,IAAI,CAAA;AAClD,MAAA,SAAA,CAAU,mBAAA,CAAoB,gBAAgB,IAAI,CAAA;AAClD,MAAA,SAAA,CAAU,mBAAA,CAAoB,eAAe,MAAM,CAAA;AACnD,MAAA,cAAA,CAAe,KAAK,CAAA;AACpB,MAAA,eAAA,EAAgB;AAAA,IAClB,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,SAAA,EAAW,SAAA,EAAW,YAAY,eAAA,EAAiB,cAAA,EAAgB,SAAA,EAAW,iBAAiB,CAAC,CAAA;AAEpG,EAAA,OAAO,EAAE,eAAA,EAAiB,eAAA,EAAiB,QAAA,EAAU,OAAA,EAAS,WAAW,iBAAA,EAAkB;AAC7F,CAAA;AAEO,MAAM,mBAAmB,CAAC;AAAA,EAC/B,aAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA;AAAA,EACA,KAAA;AAAA,EACA,OAAA;AAAA,EACA,GAAG;AACL,CAAA,KAA6B;AAC3B,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,SAAS,KAAK,CAAA;AAChD,EAAA,MAAM,WAAW,WAAA,EAAY;AAC7B,EAAA,MAAM,UAAA,GAAa,OAA8B,IAAI,CAAA;AACrD,EAAA,MAAM,EAAE,iBAAiB,eAAA,EAAiB,QAAA,EAAU,SAAS,SAAA,EAAW,iBAAA,KAAsB,oBAAA,CAAqB;AAAA,IACjH,SAAA;AAAA,IACA,SAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS,OAAA,EAAS,MAAA,EAAO;AAE9C,EAAA,MAAM,cAAA,GAAiB,OAAO,OAAA,KAAY,QAAA,GAAW,OAAA,GAAU,IAAA;AAE/D,EAAA,uBACE,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,QAAA;AAAA,MACA,UAAA;AAAA,MACA,aAAA;AAAA,MACA,OAAA;AAAA,MACA,SAAA,EAAW,EAAA,CAAG,UAAA,EAAY,SAAS,CAAA;AAAA,MACnC,KAAA,EACE;AAAA,QACE,QAAA,EAAU,YAAY,SAAA,GAAY,QAAA;AAAA,QAClC,eAAA,EAAiB,cAAA,GAAiB,CAAA,EAAG,cAAc,CAAA,EAAA,CAAA,GAAO,MAAA;AAAA,QAC1D,GAAG;AAAA,OACL;AAAA,MAED,GAAG,KAAA;AAAA,MACJ,QAAA,EAAU,CAAC,IAAA,EAAM,EAAA,EAAI,YAAA,KAAiB;AACpC,QAAA,QAAA,GAAW,IAAA,EAAM,IAAI,YAAY,CAAA;AACjC,QAAA,IAAI,OAAO,kBAAkB,QAAA,EAAU;AACvC,QAAA,YAAA,CAAa,IAAA,CAAK,YAAY,aAAa,CAAA;AAAA,MAC7C,CAAA;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAA,GAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,MAAA,EAAQ,SAAA;AAAA,YACR,KAAA,EAAO,EAAE,QAAA,EAAU,oBAAA,EAAqB;AAAA,YACxC,WAAW,EAAA,CAAG,2CAAA,EAA6C,SAAA,KAAc,MAAA,GAAS,WAAW,SAAS,CAAA;AAAA,YAErG;AAAA;AAAA,SACH;AAAA,QAEC,6BACC,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,0BAAA,GAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,GAAA,EAAK,eAAA;AAAA,cACL,IAAA,EAAK,QAAA;AAAA,cACL,YAAA,EAAW,cAAA;AAAA,cACX,OAAA,EAAS,MAAA;AAAA,cACT,SAAA,EAAW,EAAA;AAAA,gBACT,oBAAA;AAAA,gBACA,qBAAA;AAAA,gBACA,6EAAA;AAAA,gBACA,SAAA,KAAc,SAAS,QAAA,GAAW,SAAA;AAAA,gBAClC;AAAA,eACF;AAAA,cAEA,8BAAC,IAAA,EAAA,EACC,QAAA,kBAAA,GAAA,CAAC,aAAA,EAAA,EAAc,IAAA,EAAM,WAAW,CAAA,EAClC;AAAA;AAAA,WACF;AAAA,0BAEA,GAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,GAAA,EAAK,QAAA;AAAA,cACL,IAAA,EAAK,QAAA;AAAA,cACL,QAAA,EAAU,EAAA;AAAA,cACV,aAAA,EAAY,MAAA;AAAA,cACZ,OAAA,EAAS,MAAA;AAAA,cACT,cAAA,EAAgB,CAAA,KAAA,KAAS,SAAA,CAAU,KAAK,CAAA;AAAA,cACxC,cAAA,EAAgB,eAAA;AAAA,cAChB,aAAA,EAAe,CAAA,KAAA,KAAS,iBAAA,CAAkB,KAAK,CAAA;AAAA,cAC/C,KAAA,EAAO,EAAE,UAAA,EAAY,KAAA,EAAM;AAAA,cAC3B,SAAA,EAAW,EAAA;AAAA,gBACT,sFAAA;AAAA,gBACA,SAAA,KAAc,SAAS,QAAA,GAAW;AAAA,eACpC;AAAA,cAEA,QAAA,kBAAA,GAAA;AAAA,gBAAC,MAAA;AAAA,gBAAA;AAAA,kBACC,GAAA,EAAK,OAAA;AAAA,kBACL,KAAA,EAAO,EAAE,GAAA,EAAK,eAAA,EAAgB;AAAA,kBAC9B,SAAA,EAAW,EAAA;AAAA,oBACT,wHAAA;AAAA,oBACA,6HAAA;AAAA,oBACA,SAAA,KAAc,SAAS,yBAAA,GAA4B,yBAAA;AAAA,oBACnD,wGAAA;AAAA,oBACA,oCAAA;AAAA,oBACA;AAAA,mBACF;AAAA,kBAEA,QAAA,kBAAA,GAAA,CAAC,QAAM,QAAA,EAAA,SAAA,KAAc,MAAA,uBAAU,YAAA,EAAA,EAAa,CAAA,mBAAK,GAAA,CAAC,WAAA,EAAA,EAAY,CAAA,EAAG;AAAA;AAAA;AACnE;AAAA;AACF,SAAA,EACF;AAAA;AAAA;AAAA,GAEJ;AAEJ;;;;"}
1
+ {"version":3,"file":"collapsible-panel.es.js","sources":["../../src/lib/resize/collapsible-panel.tsx"],"sourcesContent":["import type { CSSProperties, Ref } from 'react';\nimport { useImperativeHandle, useRef, useState } from 'react';\nimport type { PanelProps } from 'react-resizable-panels';\nimport { Panel, usePanelRef } from 'react-resizable-panels';\nimport { PanelEdgeIcon } from './panel-edge-icon';\nimport { panelIconButtonClass } from './panel-icon-button';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/ds/components/Tooltip';\nimport { Icon } from '@/ds/icons';\nimport { cn } from '@/lib/utils';\n\n/** Programmatic control over a CollapsiblePanel (distinct from the library's panel handle). */\nexport interface CollapsiblePanelHandle {\n collapse: () => void;\n /** Reopens at the width the panel had when `collapse()` was called, else at `defaultSize`. */\n expand: () => void;\n}\n\nexport interface CollapsiblePanelProps extends PanelProps {\n direction: 'left' | 'right';\n ref?: Ref<CollapsiblePanelHandle>;\n}\n\nexport const CollapsiblePanel = ({\n collapsedSize,\n children,\n direction,\n className,\n onResize,\n style,\n minSize,\n defaultSize,\n panelRef: externalPanelRef,\n ref,\n ...props\n}: CollapsiblePanelProps) => {\n // Physical state of the panel, as reported by onResize. It drives what is rendered.\n const [isCollapsed, setIsCollapsed] = useState(false);\n // Width the panel had right before we collapsed it. The library's `expand()`\n // relies on its own \"most recent size\", which is unreliable when the panel\n // mounts already collapsed from a persisted layout (it opens at `minSize`).\n const sizeBeforeCollapseRef = useRef<number | null>(null);\n const internalPanelRef = usePanelRef();\n const panelRef = externalPanelRef ?? internalPanelRef;\n\n const collapse = () => {\n const panel = panelRef.current;\n if (!panel) return;\n sizeBeforeCollapseRef.current = panel.getSize().inPixels;\n panel.collapse();\n };\n\n const expand = () => {\n const panel = panelRef.current;\n if (!panel) return;\n const target = sizeBeforeCollapseRef.current ?? defaultSize;\n if (target === undefined) {\n panel.expand();\n return;\n }\n panel.resize(target);\n };\n\n useImperativeHandle(ref, () => ({ collapse, expand }));\n\n const numericMinSize = typeof minSize === 'number' ? minSize : null;\n\n return (\n <Panel\n panelRef={panelRef}\n collapsedSize={collapsedSize}\n minSize={minSize}\n defaultSize={defaultSize}\n className={cn('relative', className)}\n style={\n {\n // The expand button must remain visible once the panel is at zero width.\n overflow: isCollapsed ? 'visible' : 'hidden',\n '--panel-min-w': numericMinSize ? `${numericMinSize}px` : undefined,\n ...style,\n } as CSSProperties\n }\n {...props}\n onResize={(size, id, previousSize) => {\n onResize?.(size, id, previousSize);\n if (typeof collapsedSize !== 'number') return;\n setIsCollapsed(size.inPixels <= collapsedSize);\n }}\n >\n <div\n hidden={isCollapsed}\n style={{ minWidth: 'var(--panel-min-w)' }}\n className={cn('absolute inset-y-0 w-full overflow-hidden', direction === 'left' ? 'left-0' : 'right-0')}\n >\n {children}\n </div>\n\n {isCollapsed && (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n aria-label=\"Expand panel\"\n onClick={expand}\n className={cn(\n panelIconButtonClass,\n 'absolute top-2 z-10',\n 'transition-[color,background-color,opacity] duration-300 starting:opacity-0',\n direction === 'left' ? 'left-2' : 'right-2',\n )}\n >\n <Icon>\n <PanelEdgeIcon side={direction} />\n </Icon>\n </button>\n </TooltipTrigger>\n <TooltipContent side={direction === 'left' ? 'right' : 'left'}>Expand panel</TooltipContent>\n </Tooltip>\n )}\n </Panel>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -6,10 +6,11 @@ type TimelineNameColProps = {
6
6
  depth?: number;
7
7
  onSpanClick?: (id: string) => void;
8
8
  selectedSpanId?: string;
9
+ revealSpanId?: string;
9
10
  isLastChild?: boolean;
10
11
  hasChildren?: boolean;
11
12
  isRootSpan?: boolean;
12
13
  isExpanded?: boolean;
13
14
  };
14
- export declare function TimelineNameCol({ span, spanUI, isFaded, depth, onSpanClick, selectedSpanId, isLastChild, hasChildren: _hasChildren, isRootSpan, isExpanded: _isExpanded, }: TimelineNameColProps): import("react").JSX.Element;
15
+ export declare function TimelineNameCol({ span, spanUI, isFaded, depth, onSpanClick, selectedSpanId, revealSpanId, isLastChild, hasChildren: _hasChildren, isRootSpan, isExpanded: _isExpanded, }: TimelineNameColProps): import("react").JSX.Element;
15
16
  export {};
@@ -5,6 +5,7 @@ type TraceTimelineSpanProps = {
5
5
  depth?: number;
6
6
  onSpanClick?: (id: string) => void;
7
7
  selectedSpanId?: string;
8
+ revealSpanId?: string;
8
9
  isLastChild?: boolean;
9
10
  overallLatency?: number;
10
11
  overallStartTime?: string;
@@ -15,5 +16,5 @@ type TraceTimelineSpanProps = {
15
16
  setExpandedSpanIds?: React.Dispatch<React.SetStateAction<string[]>>;
16
17
  chartWidth?: 'wide' | 'default';
17
18
  };
18
- export declare function TraceTimelineSpan({ span, siblings, depth, onSpanClick, selectedSpanId, isLastChild, overallLatency, overallStartTime, fadedTypes, searchPhrase, featuredSpanIds, expandedSpanIds, setExpandedSpanIds, chartWidth, }: TraceTimelineSpanProps): import("react").JSX.Element;
19
+ export declare function TraceTimelineSpan({ span, siblings, depth, onSpanClick, selectedSpanId, revealSpanId, isLastChild, overallLatency, overallStartTime, fadedTypes, searchPhrase, featuredSpanIds, expandedSpanIds, setExpandedSpanIds, chartWidth, }: TraceTimelineSpanProps): import("react").JSX.Element;
19
20
  export {};
@@ -9,9 +9,11 @@ type TraceTimelineProps = {
9
9
  expandedSpanIds?: string[];
10
10
  setExpandedSpanIds?: Dispatch<SetStateAction<string[]>>;
11
11
  featuredSpanIds?: string[];
12
+ /** Row scrolled into view once it is mounted (ancestors auto-expand when the span is featured). */
13
+ revealSpanId?: string;
12
14
  chartWidth?: 'wide' | 'default';
13
15
  /** Rendered full-width above the span type legend row. */
14
16
  leadingSlot?: ReactNode;
15
17
  };
16
- export declare function TraceTimeline({ hierarchicalSpans, onSpanClick, selectedSpanId, isLoading, fadedTypes, expandedSpanIds, setExpandedSpanIds, featuredSpanIds, chartWidth, leadingSlot, }: TraceTimelineProps): import("react").JSX.Element;
18
+ export declare function TraceTimeline({ hierarchicalSpans, onSpanClick, selectedSpanId, isLoading, fadedTypes, expandedSpanIds, setExpandedSpanIds, featuredSpanIds, revealSpanId, chartWidth, leadingSlot, }: TraceTimelineProps): import("react").JSX.Element;
17
19
  export {};
@@ -1,5 +1,13 @@
1
+ import { Ref } from 'react';
1
2
  import { PanelProps } from 'react-resizable-panels';
3
+ /** Programmatic control over a CollapsiblePanel (distinct from the library's panel handle). */
4
+ export interface CollapsiblePanelHandle {
5
+ collapse: () => void;
6
+ /** Reopens at the width the panel had when `collapse()` was called, else at `defaultSize`. */
7
+ expand: () => void;
8
+ }
2
9
  export interface CollapsiblePanelProps extends PanelProps {
3
10
  direction: 'left' | 'right';
11
+ ref?: Ref<CollapsiblePanelHandle>;
4
12
  }
5
- export declare const CollapsiblePanel: ({ collapsedSize, children, direction, className, onResize, style, minSize, ...props }: CollapsiblePanelProps) => import("react").JSX.Element;
13
+ export declare const CollapsiblePanel: ({ collapsedSize, children, direction, className, onResize, style, minSize, defaultSize, panelRef: externalPanelRef, ref, ...props }: CollapsiblePanelProps) => import("react").JSX.Element;