@mastra/playground-ui 53.1.0-alpha.3 → 54.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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":"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"}
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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"}
@@ -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;
package/dist/style.css CHANGED
@@ -811,10 +811,6 @@
811
811
  right: var(--spacing-0);
812
812
  }
813
813
 
814
- .right-0\.5 {
815
- right: var(--spacing-0_5);
816
- }
817
-
818
814
  .right-1 {
819
815
  right: var(--spacing-1);
820
816
  }
@@ -2980,11 +2976,6 @@
2980
2976
  translate: var(--tw-translate-x) var(--tw-translate-y);
2981
2977
  }
2982
2978
 
2983
- .-translate-x-1 {
2984
- --tw-translate-x: calc(var(--spacing-1) * -1);
2985
- translate: var(--tw-translate-x) var(--tw-translate-y);
2986
- }
2987
-
2988
2979
  .-translate-x-1\/2 {
2989
2980
  --tw-translate-x: calc(calc(1 / 2 * 100%) * -1);
2990
2981
  translate: var(--tw-translate-x) var(--tw-translate-y);
@@ -2995,11 +2986,6 @@
2995
2986
  translate: var(--tw-translate-x) var(--tw-translate-y);
2996
2987
  }
2997
2988
 
2998
- .translate-x-1 {
2999
- --tw-translate-x: var(--spacing-1);
3000
- translate: var(--tw-translate-x) var(--tw-translate-y);
3001
- }
3002
-
3003
2989
  .translate-x-1\/2 {
3004
2990
  --tw-translate-x: calc(1 / 2 * 100%);
3005
2991
  translate: var(--tw-translate-x) var(--tw-translate-y);
@@ -6464,12 +6450,6 @@
6464
6450
  transition-duration: var(--tw-duration, var(--default-transition-duration));
6465
6451
  }
6466
6452
 
6467
- .transition-\[opacity\,translate\,top\] {
6468
- transition-property: opacity, translate, top;
6469
- transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
6470
- transition-duration: var(--tw-duration, var(--default-transition-duration));
6471
- }
6472
-
6473
6453
  .transition-\[padding\] {
6474
6454
  transition-property: padding;
6475
6455
  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
@@ -6799,16 +6779,7 @@
6799
6779
  background-color: var(--color-surface4);
6800
6780
  }
6801
6781
 
6802
- .group-hover\/expand\:pointer-events-auto:is(:where(.group\/expand):hover *) {
6803
- pointer-events: auto;
6804
- }
6805
-
6806
- .group-hover\/expand\:translate-x-0:is(:where(.group\/expand):hover *) {
6807
- --tw-translate-x: var(--spacing-0);
6808
- translate: var(--tw-translate-x) var(--tw-translate-y);
6809
- }
6810
-
6811
- .group-hover\/expand\:opacity-100:is(:where(.group\/expand):hover *), .group-hover\/row\:opacity-100:is(:where(.group\/row):hover *) {
6782
+ .group-hover\/row\:opacity-100:is(:where(.group\/row):hover *) {
6812
6783
  opacity: 1;
6813
6784
  }
6814
6785
 
@@ -6882,16 +6853,6 @@
6882
6853
  background-color: var(--color-surface4);
6883
6854
  }
6884
6855
 
6885
- .group-active\/expand\:bg-neutral6\/80:is(:where(.group\/expand):active *) {
6886
- background-color: var(--color-neutral6);
6887
- }
6888
-
6889
- @supports (color: color-mix(in lab, red, red)) {
6890
- .group-active\/expand\:bg-neutral6\/80:is(:where(.group\/expand):active *) {
6891
- background-color: color-mix(in oklab, var(--color-neutral6) 80%, transparent);
6892
- }
6893
- }
6894
-
6895
6856
  .group-active\/switch\:w-6:is(:where(.group\/switch):active *) {
6896
6857
  width: var(--spacing-6);
6897
6858
  }
@@ -8789,23 +8750,6 @@
8789
8750
  opacity: .5;
8790
8751
  }
8791
8752
 
8792
- .data-\[edge-hovered\=true\]\:pointer-events-auto[data-edge-hovered="true"] {
8793
- pointer-events: auto;
8794
- }
8795
-
8796
- .data-\[edge-hovered\=true\]\:translate-x-0[data-edge-hovered="true"] {
8797
- --tw-translate-x: var(--spacing-0);
8798
- translate: var(--tw-translate-x) var(--tw-translate-y);
8799
- }
8800
-
8801
- .data-\[edge-hovered\=true\]\:text-neutral6[data-edge-hovered="true"] {
8802
- color: var(--color-neutral6);
8803
- }
8804
-
8805
- .data-\[edge-hovered\=true\]\:opacity-100[data-edge-hovered="true"] {
8806
- opacity: 1;
8807
- }
8808
-
8809
8753
  .data-\[ending-style\]\:h-0[data-ending-style] {
8810
8754
  height: var(--spacing-0);
8811
8755
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mastra/playground-ui",
3
3
  "type": "module",
4
- "version": "53.1.0-alpha.3",
4
+ "version": "54.0.0",
5
5
  "description": "Mastra Playground components",
6
6
  "sideEffects": [
7
7
  "**/*.css"
@@ -160,8 +160,8 @@
160
160
  "react": ">=19.0.0",
161
161
  "react-dom": ">=19.0.0",
162
162
  "tailwindcss": "^4.0.0",
163
- "@mastra/react": "1.4.12-alpha.3",
164
- "@mastra/client-js": "^1.44.1-alpha.3"
163
+ "@mastra/client-js": "^1.45.0",
164
+ "@mastra/react": "1.4.12"
165
165
  },
166
166
  "devDependencies": {
167
167
  "@storybook/addon-a11y": "^10.4.1",
@@ -202,11 +202,11 @@
202
202
  "vite-plugin-dts": "^4.5.4",
203
203
  "vite-plugin-lib-inject-css": "^2.2.2",
204
204
  "vitest": "4.1.10",
205
- "@mastra/client-js": "^1.44.1-alpha.3",
206
- "@internal/lint": "0.0.131",
207
- "@mastra/core": "1.66.0-alpha.3",
208
- "@mastra/memory": "1.29.0-alpha.2",
209
- "@mastra/react": "1.4.12-alpha.3"
205
+ "@internal/lint": "0.0.132",
206
+ "@mastra/client-js": "^1.45.0",
207
+ "@mastra/core": "1.66.0",
208
+ "@mastra/memory": "1.29.0",
209
+ "@mastra/react": "1.4.12"
210
210
  },
211
211
  "homepage": "https://mastra.ai",
212
212
  "repository": {
@@ -1,56 +0,0 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
-
5
- const React = require('react');
6
-
7
- const clamp = (value, min, max) => Math.min(max, Math.max(min, value));
8
- const readAxis = (point, rect, axis) => {
9
- if (axis === "x") {
10
- return { client: point.clientX, start: rect.left, size: rect.width };
11
- }
12
- return { client: point.clientY, start: rect.top, size: rect.height };
13
- };
14
- const getClampedElementCursorOffset = (point, rect, axis, margin = 0) => {
15
- const { client, start, size } = readAxis(point, rect, axis);
16
- return clamp(client - start, margin, Math.max(margin, size - margin));
17
- };
18
- const useClampedElementCursor = ({
19
- axis,
20
- margin = 0,
21
- variableName
22
- }) => {
23
- const elementRef = React.useRef(null);
24
- const rectRef = React.useRef(null);
25
- const writePosition = React.useCallback(
26
- (point, refreshRect = false) => {
27
- const element = elementRef.current;
28
- if (!element) return;
29
- const rect = refreshRect || !rectRef.current ? element.getBoundingClientRect() : rectRef.current;
30
- rectRef.current = rect;
31
- const offset = getClampedElementCursorOffset(point, rect, axis, margin);
32
- element.style.setProperty(variableName, `${offset}px`);
33
- },
34
- [axis, margin, variableName]
35
- );
36
- const beginTracking = React.useCallback(
37
- (point) => {
38
- writePosition(point, true);
39
- },
40
- [writePosition]
41
- );
42
- const updateTracking = React.useCallback(
43
- (point) => {
44
- writePosition(point);
45
- },
46
- [writePosition]
47
- );
48
- const endTracking = React.useCallback(() => {
49
- rectRef.current = null;
50
- }, []);
51
- return { beginTracking, elementRef, endTracking, updateTracking };
52
- };
53
-
54
- exports.getClampedElementCursorOffset = getClampedElementCursorOffset;
55
- exports.useClampedElementCursor = useClampedElementCursor;
56
- //# sourceMappingURL=use-clamped-element-cursor.cjs.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-clamped-element-cursor.cjs.js","sources":["../../src/lib/resize/use-clamped-element-cursor.ts"],"sourcesContent":["import { useCallback, useRef } from 'react';\n\nexport interface ClientPoint {\n clientX: number;\n clientY: number;\n}\n\nexport interface UseClampedElementCursorOptions {\n axis: 'x' | 'y';\n margin?: number;\n variableName: `--${string}`;\n}\n\nconst clamp = (value: number, min: number, max: number) => Math.min(max, Math.max(min, value));\n\nconst readAxis = (point: ClientPoint, rect: DOMRect, axis: 'x' | 'y') => {\n if (axis === 'x') {\n return { client: point.clientX, start: rect.left, size: rect.width };\n }\n\n return { client: point.clientY, start: rect.top, size: rect.height };\n};\n\nexport const getClampedElementCursorOffset = (point: ClientPoint, rect: DOMRect, axis: 'x' | 'y', margin = 0) => {\n const { client, start, size } = readAxis(point, rect, axis);\n return clamp(client - start, margin, Math.max(margin, size - margin));\n};\n\nexport const useClampedElementCursor = <TElement extends HTMLElement>({\n axis,\n margin = 0,\n variableName,\n}: UseClampedElementCursorOptions) => {\n const elementRef = useRef<TElement | null>(null);\n const rectRef = useRef<DOMRect | null>(null);\n\n const writePosition = useCallback(\n (point: ClientPoint, refreshRect = false) => {\n const element = elementRef.current;\n if (!element) return;\n\n const rect = refreshRect || !rectRef.current ? element.getBoundingClientRect() : rectRef.current;\n rectRef.current = rect;\n\n const offset = getClampedElementCursorOffset(point, rect, axis, margin);\n element.style.setProperty(variableName, `${offset}px`);\n },\n [axis, margin, variableName],\n );\n\n const beginTracking = useCallback(\n (point: ClientPoint) => {\n writePosition(point, true);\n },\n [writePosition],\n );\n\n const updateTracking = useCallback(\n (point: ClientPoint) => {\n writePosition(point);\n },\n [writePosition],\n );\n\n const endTracking = useCallback(() => {\n rectRef.current = null;\n }, []);\n\n return { beginTracking, elementRef, endTracking, updateTracking };\n};\n"],"names":["useRef","useCallback"],"mappings":";;;;;;AAaA,MAAM,KAAA,GAAQ,CAAC,KAAA,EAAe,GAAA,EAAa,GAAA,KAAgB,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,KAAK,CAAC,CAAA;AAE7F,MAAM,QAAA,GAAW,CAAC,KAAA,EAAoB,IAAA,EAAe,IAAA,KAAoB;AACvE,EAAA,IAAI,SAAS,GAAA,EAAK;AAChB,IAAA,OAAO,EAAE,QAAQ,KAAA,CAAM,OAAA,EAAS,OAAO,IAAA,CAAK,IAAA,EAAM,IAAA,EAAM,IAAA,CAAK,KAAA,EAAM;AAAA,EACrE;AAEA,EAAA,OAAO,EAAE,QAAQ,KAAA,CAAM,OAAA,EAAS,OAAO,IAAA,CAAK,GAAA,EAAK,IAAA,EAAM,IAAA,CAAK,MAAA,EAAO;AACrE,CAAA;AAEO,MAAM,gCAAgC,CAAC,KAAA,EAAoB,IAAA,EAAe,IAAA,EAAiB,SAAS,CAAA,KAAM;AAC/G,EAAA,MAAM,EAAE,QAAQ,KAAA,EAAO,IAAA,KAAS,QAAA,CAAS,KAAA,EAAO,MAAM,IAAI,CAAA;AAC1D,EAAA,OAAO,KAAA,CAAM,SAAS,KAAA,EAAO,MAAA,EAAQ,KAAK,GAAA,CAAI,MAAA,EAAQ,IAAA,GAAO,MAAM,CAAC,CAAA;AACtE;AAEO,MAAM,0BAA0B,CAA+B;AAAA,EACpE,IAAA;AAAA,EACA,MAAA,GAAS,CAAA;AAAA,EACT;AACF,CAAA,KAAsC;AACpC,EAAA,MAAM,UAAA,GAAaA,aAAwB,IAAI,CAAA;AAC/C,EAAA,MAAM,OAAA,GAAUA,aAAuB,IAAI,CAAA;AAE3C,EAAA,MAAM,aAAA,GAAgBC,iBAAA;AAAA,IACpB,CAAC,KAAA,EAAoB,WAAA,GAAc,KAAA,KAAU;AAC3C,MAAA,MAAM,UAAU,UAAA,CAAW,OAAA;AAC3B,MAAA,IAAI,CAAC,OAAA,EAAS;AAEd,MAAA,MAAM,IAAA,GAAO,eAAe,CAAC,OAAA,CAAQ,UAAU,OAAA,CAAQ,qBAAA,KAA0B,OAAA,CAAQ,OAAA;AACzF,MAAA,OAAA,CAAQ,OAAA,GAAU,IAAA;AAElB,MAAA,MAAM,MAAA,GAAS,6BAAA,CAA8B,KAAA,EAAO,IAAA,EAAM,MAAM,MAAM,CAAA;AACtE,MAAA,OAAA,CAAQ,KAAA,CAAM,WAAA,CAAY,YAAA,EAAc,CAAA,EAAG,MAAM,CAAA,EAAA,CAAI,CAAA;AAAA,IACvD,CAAA;AAAA,IACA,CAAC,IAAA,EAAM,MAAA,EAAQ,YAAY;AAAA,GAC7B;AAEA,EAAA,MAAM,aAAA,GAAgBA,iBAAA;AAAA,IACpB,CAAC,KAAA,KAAuB;AACtB,MAAA,aAAA,CAAc,OAAO,IAAI,CAAA;AAAA,IAC3B,CAAA;AAAA,IACA,CAAC,aAAa;AAAA,GAChB;AAEA,EAAA,MAAM,cAAA,GAAiBA,iBAAA;AAAA,IACrB,CAAC,KAAA,KAAuB;AACtB,MAAA,aAAA,CAAc,KAAK,CAAA;AAAA,IACrB,CAAA;AAAA,IACA,CAAC,aAAa;AAAA,GAChB;AAEA,EAAA,MAAM,WAAA,GAAcA,kBAAY,MAAM;AACpC,IAAA,OAAA,CAAQ,OAAA,GAAU,IAAA;AAAA,EACpB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,OAAO,EAAE,aAAA,EAAe,UAAA,EAAY,WAAA,EAAa,cAAA,EAAe;AAClE;;;;;"}
@@ -1,2 +0,0 @@
1
- export * from '../src/lib/resize/use-clamped-element-cursor'
2
- export {}
@@ -1,51 +0,0 @@
1
- import { useRef, useCallback } from 'react';
2
-
3
- const clamp = (value, min, max) => Math.min(max, Math.max(min, value));
4
- const readAxis = (point, rect, axis) => {
5
- if (axis === "x") {
6
- return { client: point.clientX, start: rect.left, size: rect.width };
7
- }
8
- return { client: point.clientY, start: rect.top, size: rect.height };
9
- };
10
- const getClampedElementCursorOffset = (point, rect, axis, margin = 0) => {
11
- const { client, start, size } = readAxis(point, rect, axis);
12
- return clamp(client - start, margin, Math.max(margin, size - margin));
13
- };
14
- const useClampedElementCursor = ({
15
- axis,
16
- margin = 0,
17
- variableName
18
- }) => {
19
- const elementRef = useRef(null);
20
- const rectRef = useRef(null);
21
- const writePosition = useCallback(
22
- (point, refreshRect = false) => {
23
- const element = elementRef.current;
24
- if (!element) return;
25
- const rect = refreshRect || !rectRef.current ? element.getBoundingClientRect() : rectRef.current;
26
- rectRef.current = rect;
27
- const offset = getClampedElementCursorOffset(point, rect, axis, margin);
28
- element.style.setProperty(variableName, `${offset}px`);
29
- },
30
- [axis, margin, variableName]
31
- );
32
- const beginTracking = useCallback(
33
- (point) => {
34
- writePosition(point, true);
35
- },
36
- [writePosition]
37
- );
38
- const updateTracking = useCallback(
39
- (point) => {
40
- writePosition(point);
41
- },
42
- [writePosition]
43
- );
44
- const endTracking = useCallback(() => {
45
- rectRef.current = null;
46
- }, []);
47
- return { beginTracking, elementRef, endTracking, updateTracking };
48
- };
49
-
50
- export { getClampedElementCursorOffset, useClampedElementCursor };
51
- //# sourceMappingURL=use-clamped-element-cursor.es.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-clamped-element-cursor.es.js","sources":["../../src/lib/resize/use-clamped-element-cursor.ts"],"sourcesContent":["import { useCallback, useRef } from 'react';\n\nexport interface ClientPoint {\n clientX: number;\n clientY: number;\n}\n\nexport interface UseClampedElementCursorOptions {\n axis: 'x' | 'y';\n margin?: number;\n variableName: `--${string}`;\n}\n\nconst clamp = (value: number, min: number, max: number) => Math.min(max, Math.max(min, value));\n\nconst readAxis = (point: ClientPoint, rect: DOMRect, axis: 'x' | 'y') => {\n if (axis === 'x') {\n return { client: point.clientX, start: rect.left, size: rect.width };\n }\n\n return { client: point.clientY, start: rect.top, size: rect.height };\n};\n\nexport const getClampedElementCursorOffset = (point: ClientPoint, rect: DOMRect, axis: 'x' | 'y', margin = 0) => {\n const { client, start, size } = readAxis(point, rect, axis);\n return clamp(client - start, margin, Math.max(margin, size - margin));\n};\n\nexport const useClampedElementCursor = <TElement extends HTMLElement>({\n axis,\n margin = 0,\n variableName,\n}: UseClampedElementCursorOptions) => {\n const elementRef = useRef<TElement | null>(null);\n const rectRef = useRef<DOMRect | null>(null);\n\n const writePosition = useCallback(\n (point: ClientPoint, refreshRect = false) => {\n const element = elementRef.current;\n if (!element) return;\n\n const rect = refreshRect || !rectRef.current ? element.getBoundingClientRect() : rectRef.current;\n rectRef.current = rect;\n\n const offset = getClampedElementCursorOffset(point, rect, axis, margin);\n element.style.setProperty(variableName, `${offset}px`);\n },\n [axis, margin, variableName],\n );\n\n const beginTracking = useCallback(\n (point: ClientPoint) => {\n writePosition(point, true);\n },\n [writePosition],\n );\n\n const updateTracking = useCallback(\n (point: ClientPoint) => {\n writePosition(point);\n },\n [writePosition],\n );\n\n const endTracking = useCallback(() => {\n rectRef.current = null;\n }, []);\n\n return { beginTracking, elementRef, endTracking, updateTracking };\n};\n"],"names":[],"mappings":";;AAaA,MAAM,KAAA,GAAQ,CAAC,KAAA,EAAe,GAAA,EAAa,GAAA,KAAgB,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,KAAK,CAAC,CAAA;AAE7F,MAAM,QAAA,GAAW,CAAC,KAAA,EAAoB,IAAA,EAAe,IAAA,KAAoB;AACvE,EAAA,IAAI,SAAS,GAAA,EAAK;AAChB,IAAA,OAAO,EAAE,QAAQ,KAAA,CAAM,OAAA,EAAS,OAAO,IAAA,CAAK,IAAA,EAAM,IAAA,EAAM,IAAA,CAAK,KAAA,EAAM;AAAA,EACrE;AAEA,EAAA,OAAO,EAAE,QAAQ,KAAA,CAAM,OAAA,EAAS,OAAO,IAAA,CAAK,GAAA,EAAK,IAAA,EAAM,IAAA,CAAK,MAAA,EAAO;AACrE,CAAA;AAEO,MAAM,gCAAgC,CAAC,KAAA,EAAoB,IAAA,EAAe,IAAA,EAAiB,SAAS,CAAA,KAAM;AAC/G,EAAA,MAAM,EAAE,QAAQ,KAAA,EAAO,IAAA,KAAS,QAAA,CAAS,KAAA,EAAO,MAAM,IAAI,CAAA;AAC1D,EAAA,OAAO,KAAA,CAAM,SAAS,KAAA,EAAO,MAAA,EAAQ,KAAK,GAAA,CAAI,MAAA,EAAQ,IAAA,GAAO,MAAM,CAAC,CAAA;AACtE;AAEO,MAAM,0BAA0B,CAA+B;AAAA,EACpE,IAAA;AAAA,EACA,MAAA,GAAS,CAAA;AAAA,EACT;AACF,CAAA,KAAsC;AACpC,EAAA,MAAM,UAAA,GAAa,OAAwB,IAAI,CAAA;AAC/C,EAAA,MAAM,OAAA,GAAU,OAAuB,IAAI,CAAA;AAE3C,EAAA,MAAM,aAAA,GAAgB,WAAA;AAAA,IACpB,CAAC,KAAA,EAAoB,WAAA,GAAc,KAAA,KAAU;AAC3C,MAAA,MAAM,UAAU,UAAA,CAAW,OAAA;AAC3B,MAAA,IAAI,CAAC,OAAA,EAAS;AAEd,MAAA,MAAM,IAAA,GAAO,eAAe,CAAC,OAAA,CAAQ,UAAU,OAAA,CAAQ,qBAAA,KAA0B,OAAA,CAAQ,OAAA;AACzF,MAAA,OAAA,CAAQ,OAAA,GAAU,IAAA;AAElB,MAAA,MAAM,MAAA,GAAS,6BAAA,CAA8B,KAAA,EAAO,IAAA,EAAM,MAAM,MAAM,CAAA;AACtE,MAAA,OAAA,CAAQ,KAAA,CAAM,WAAA,CAAY,YAAA,EAAc,CAAA,EAAG,MAAM,CAAA,EAAA,CAAI,CAAA;AAAA,IACvD,CAAA;AAAA,IACA,CAAC,IAAA,EAAM,MAAA,EAAQ,YAAY;AAAA,GAC7B;AAEA,EAAA,MAAM,aAAA,GAAgB,WAAA;AAAA,IACpB,CAAC,KAAA,KAAuB;AACtB,MAAA,aAAA,CAAc,OAAO,IAAI,CAAA;AAAA,IAC3B,CAAA;AAAA,IACA,CAAC,aAAa;AAAA,GAChB;AAEA,EAAA,MAAM,cAAA,GAAiB,WAAA;AAAA,IACrB,CAAC,KAAA,KAAuB;AACtB,MAAA,aAAA,CAAc,KAAK,CAAA;AAAA,IACrB,CAAA;AAAA,IACA,CAAC,aAAa;AAAA,GAChB;AAEA,EAAA,MAAM,WAAA,GAAc,YAAY,MAAM;AACpC,IAAA,OAAA,CAAQ,OAAA,GAAU,IAAA;AAAA,EACpB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,OAAO,EAAE,aAAA,EAAe,UAAA,EAAY,WAAA,EAAa,cAAA,EAAe;AAClE;;;;"}
@@ -1,16 +0,0 @@
1
- export interface ClientPoint {
2
- clientX: number;
3
- clientY: number;
4
- }
5
- export interface UseClampedElementCursorOptions {
6
- axis: 'x' | 'y';
7
- margin?: number;
8
- variableName: `--${string}`;
9
- }
10
- export declare const getClampedElementCursorOffset: (point: ClientPoint, rect: DOMRect, axis: "x" | "y", margin?: number) => number;
11
- export declare const useClampedElementCursor: <TElement extends HTMLElement>({ axis, margin, variableName, }: UseClampedElementCursorOptions) => {
12
- beginTracking: (point: ClientPoint) => void;
13
- elementRef: import('react').RefObject<TElement | null>;
14
- endTracking: () => void;
15
- updateTracking: (point: ClientPoint) => void;
16
- };