@timmbr/ui 1.15.1 → 1.16.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.
Files changed (41) hide show
  1. package/dist/components/Card/Card.styles.d.ts +1 -1
  2. package/dist/components/Panel/Panel.context.d.ts +17 -0
  3. package/dist/components/Panel/Panel.context.d.ts.map +1 -0
  4. package/dist/components/Panel/Panel.context.js +17 -0
  5. package/dist/components/Panel/Panel.d.ts +4 -0
  6. package/dist/components/Panel/Panel.d.ts.map +1 -0
  7. package/dist/components/Panel/Panel.helpers.d.ts +103 -0
  8. package/dist/components/Panel/Panel.helpers.d.ts.map +1 -0
  9. package/dist/components/Panel/Panel.helpers.js +179 -0
  10. package/dist/components/Panel/Panel.js +174 -0
  11. package/dist/components/Panel/Panel.styles.d.ts +42 -0
  12. package/dist/components/Panel/Panel.styles.d.ts.map +1 -0
  13. package/dist/components/Panel/Panel.styles.js +118 -0
  14. package/dist/components/Panel/Panel.types.d.ts +59 -0
  15. package/dist/components/Panel/Panel.types.d.ts.map +1 -0
  16. package/dist/components/Panel/index.d.ts +7 -0
  17. package/dist/components/Panel/index.d.ts.map +1 -0
  18. package/dist/components/Panel/subcomponents/PanelBody.d.ts +4 -0
  19. package/dist/components/Panel/subcomponents/PanelBody.d.ts.map +1 -0
  20. package/dist/components/Panel/subcomponents/PanelBody.js +58 -0
  21. package/dist/components/Panel/subcomponents/PanelDescription.d.ts +4 -0
  22. package/dist/components/Panel/subcomponents/PanelDescription.d.ts.map +1 -0
  23. package/dist/components/Panel/subcomponents/PanelDescription.js +24 -0
  24. package/dist/components/Panel/subcomponents/PanelFooter.d.ts +4 -0
  25. package/dist/components/Panel/subcomponents/PanelFooter.d.ts.map +1 -0
  26. package/dist/components/Panel/subcomponents/PanelFooter.js +27 -0
  27. package/dist/components/Panel/subcomponents/PanelHeader.d.ts +4 -0
  28. package/dist/components/Panel/subcomponents/PanelHeader.d.ts.map +1 -0
  29. package/dist/components/Panel/subcomponents/PanelHeader.js +101 -0
  30. package/dist/components/Panel/subcomponents/PanelResizeHandle.d.ts +11 -0
  31. package/dist/components/Panel/subcomponents/PanelResizeHandle.d.ts.map +1 -0
  32. package/dist/components/Panel/subcomponents/PanelResizeHandle.js +29 -0
  33. package/dist/components/Panel/subcomponents/PanelTitle.d.ts +4 -0
  34. package/dist/components/Panel/subcomponents/PanelTitle.d.ts.map +1 -0
  35. package/dist/components/Panel/subcomponents/PanelTitle.js +24 -0
  36. package/dist/components/Panel/subcomponents/index.d.ts +6 -0
  37. package/dist/components/Panel/subcomponents/index.d.ts.map +1 -0
  38. package/dist/index.d.ts +1 -0
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +9 -0
  41. package/package.json +5 -5
@@ -1,6 +1,6 @@
1
1
  import { type VariantProps } from 'class-variance-authority';
2
2
  export declare const cardVariants: (props?: ({
3
- variant?: "inset" | "outline" | "subtle" | "elevated" | "interactive" | null | undefined;
3
+ variant?: "inset" | "outline" | "elevated" | "subtle" | "interactive" | null | undefined;
4
4
  padding?: "none" | "sm" | "md" | "lg" | "default" | null | undefined;
5
5
  selected?: boolean | null | undefined;
6
6
  sectioned?: boolean | null | undefined;
@@ -0,0 +1,17 @@
1
+ import * as React from 'react';
2
+ import type { panelSectionPadding } from './Panel.styles';
3
+ export type PanelPadding = keyof typeof panelSectionPadding;
4
+ export type PanelPlacement = 'inline' | 'left' | 'right';
5
+ export interface PanelContextValue {
6
+ sectioned: boolean;
7
+ padding: PanelPadding;
8
+ collapsed: boolean;
9
+ collapsible: boolean;
10
+ shouldAnimate: boolean;
11
+ panelId: string;
12
+ placement: PanelPlacement;
13
+ onToggleCollapse: () => void;
14
+ }
15
+ export declare const PanelContext: React.Context<PanelContextValue>;
16
+ export declare const usePanelContext: () => PanelContextValue;
17
+ //# sourceMappingURL=Panel.context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Panel.context.d.ts","sourceRoot":"","sources":["../../../src/components/Panel/Panel.context.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE1D,MAAM,MAAM,YAAY,GAAG,MAAM,OAAO,mBAAmB,CAAC;AAC5D,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAEzD,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,YAAY,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,aAAa,EAAE,OAAO,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,cAAc,CAAC;IAC1B,gBAAgB,EAAE,MAAM,IAAI,CAAC;CAC9B;AAED,eAAO,MAAM,YAAY,kCASvB,CAAC;AAEH,eAAO,MAAM,eAAe,yBAAuC,CAAC"}
@@ -0,0 +1,17 @@
1
+ "use client";
2
+ import * as React from 'react';
3
+
4
+ const PanelContext = React.createContext({
5
+ sectioned: false,
6
+ padding: "default",
7
+ collapsed: false,
8
+ collapsible: false,
9
+ shouldAnimate: true,
10
+ panelId: "",
11
+ placement: "inline",
12
+ onToggleCollapse: () => {
13
+ }
14
+ });
15
+ const usePanelContext = () => React.useContext(PanelContext);
16
+
17
+ export { PanelContext, usePanelContext };
@@ -0,0 +1,4 @@
1
+ import * as React from 'react';
2
+ import type { PanelProps } from './Panel.types';
3
+ export declare const Panel: React.ForwardRefExoticComponent<PanelProps & React.RefAttributes<HTMLDivElement>>;
4
+ //# sourceMappingURL=Panel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Panel.d.ts","sourceRoot":"","sources":["../../../src/components/Panel/Panel.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAkB/B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,eAAO,MAAM,KAAK,mFAqMjB,CAAC"}
@@ -0,0 +1,103 @@
1
+ import * as React from 'react';
2
+ import { useMotionValue } from '@timmbr/motion';
3
+ export declare const DEFAULT_H_MIN = 120;
4
+ export declare const DEFAULT_H_MAX = 640;
5
+ export declare const DEFAULT_H_SIZE = 320;
6
+ export declare const DEFAULT_H_COLLAPSED = 40;
7
+ export declare const DEFAULT_V_MIN = 80;
8
+ export declare const DEFAULT_V_MAX = 480;
9
+ export declare const DEFAULT_V_SIZE = 240;
10
+ export declare const DEFAULT_V_COLLAPSED = 40;
11
+ export interface PanelSizes {
12
+ isH: boolean;
13
+ resolvedMin: number;
14
+ resolvedMax: number;
15
+ resolvedDefault: number;
16
+ resolvedCollapsedSize: number;
17
+ }
18
+ /**
19
+ * Derives the concrete px values for min/max/default/collapsed from the
20
+ * raw props, falling back to axis-specific defaults.
21
+ *
22
+ * Side panels (left/right) always collapse along the horizontal axis;
23
+ * only inline panels with resizable='vertical' use the vertical axis.
24
+ */
25
+ export declare function resolvePanelSizes(resizable: false | 'horizontal' | 'vertical', placement: 'inline' | 'left' | 'right', minSize?: number, maxSize?: number, defaultSize?: number, collapsedSize?: number): PanelSizes;
26
+ export interface UsePanelResizeOptions {
27
+ containerRef: React.RefObject<HTMLElement | null>;
28
+ resizable: false | 'horizontal' | 'vertical';
29
+ /** Which edge the panel is docked to — determines whether delta should be inverted. */
30
+ placement?: 'inline' | 'left' | 'right';
31
+ minSize: number;
32
+ maxSize: number;
33
+ defaultSize: number;
34
+ /** Starting size for the motion value — may differ from defaultSize when initially collapsed. */
35
+ initialValue?: number;
36
+ onResize?: (size: number) => void;
37
+ }
38
+ export interface UsePanelResizeReturn {
39
+ size: number;
40
+ isResizing: boolean;
41
+ /** Live motion value driving the panel's inline width/height — also used by the collapse spring. */
42
+ sizeMotionValue: ReturnType<typeof useMotionValue<number>>;
43
+ handleProps: React.HTMLAttributes<HTMLDivElement> & {
44
+ 'data-resizing'?: string;
45
+ };
46
+ }
47
+ export interface UsePanelCollapseOptions {
48
+ collapsible: boolean;
49
+ collapsed?: boolean;
50
+ defaultCollapsed?: boolean;
51
+ onCollapsedChange?: (collapsed: boolean) => void;
52
+ }
53
+ export interface UsePanelCollapseReturn {
54
+ collapsed: boolean;
55
+ toggle: () => void;
56
+ }
57
+ /**
58
+ * Manages drag-to-resize behaviour for the Panel.
59
+ *
60
+ * During drag, `sizeMotionValue` is updated directly for zero-stutter 60fps
61
+ * tracking. The collapse spring in Panel.tsx reuses the same motion value so
62
+ * both interactions drive the element through a single binding.
63
+ *
64
+ * When animations are disabled, the same code path runs — motion values still
65
+ * work as plain reactive values; only the spring in the collapse path is skipped.
66
+ */
67
+ export declare function usePanelResize({ containerRef: _containerRef, resizable, placement, minSize, maxSize, defaultSize, initialValue, onResize, }: UsePanelResizeOptions): UsePanelResizeReturn;
68
+ /**
69
+ * Imperatively spring-animates the panel size motion value to a target.
70
+ * Called from Panel.tsx when the collapse state changes.
71
+ */
72
+ export declare function animatePanelSize(motionValue: ReturnType<typeof useMotionValue<number>>, target: number, shouldAnimate: boolean): void;
73
+ /**
74
+ * Manages controlled/uncontrolled collapse state for the Panel toggle button.
75
+ */
76
+ export declare function usePanelCollapse({ collapsible, collapsed, defaultCollapsed, onCollapsedChange, }: UsePanelCollapseOptions): UsePanelCollapseReturn;
77
+ export interface UsePanelSnapCoordinationOptions {
78
+ /** Whether snap-to-collapse coordination is active (requires collapsible + resizable + snapToCollapse). */
79
+ activelySnapping: boolean;
80
+ handleProps: UsePanelResizeReturn['handleProps'];
81
+ collapsed: boolean;
82
+ sizeMotionValue: ReturnType<typeof useMotionValue<number>>;
83
+ resolvedMin: number;
84
+ resolvedCollapsedSize: number;
85
+ toggle: () => void;
86
+ isH: boolean;
87
+ placement: 'inline' | 'left' | 'right';
88
+ /** Mutable ref tracking the last expanded size — owned by Panel root, shared here. */
89
+ expandedSizeRef: React.MutableRefObject<number>;
90
+ }
91
+ /**
92
+ * Wraps the resize handle props to coordinate snap-to-collapse behaviour:
93
+ *
94
+ * EXPANDING (panel is collapsed):
95
+ * - A bare click must NOT expand. Panel stays at collapsedSize until drag crosses minSize.
96
+ * - Once the threshold is crossed the panel expands and normal resize takes over.
97
+ *
98
+ * COLLAPSING (panel is expanded):
99
+ * - When the user releases at minSize (the clamped floor), they wanted to go smaller —
100
+ * the panel smooth-animates to collapsedSize.
101
+ */
102
+ export declare function usePanelSnapCoordination({ activelySnapping, handleProps, collapsed, sizeMotionValue, resolvedMin, resolvedCollapsedSize, toggle, isH, placement, expandedSizeRef, }: UsePanelSnapCoordinationOptions): UsePanelResizeReturn['handleProps'];
103
+ //# sourceMappingURL=Panel.helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Panel.helpers.d.ts","sourceRoot":"","sources":["../../../src/components/Panel/Panel.helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,cAAc,EAAW,MAAM,gBAAgB,CAAC;AAIzD,eAAO,MAAM,aAAa,MAAM,CAAC;AACjC,eAAO,MAAM,aAAa,MAAM,CAAC;AACjC,eAAO,MAAM,cAAc,MAAM,CAAC;AAClC,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAEtC,eAAO,MAAM,aAAa,KAAK,CAAC;AAChC,eAAO,MAAM,aAAa,MAAM,CAAC;AACjC,eAAO,MAAM,cAAc,MAAM,CAAC;AAClC,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAItC,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,OAAO,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,qBAAqB,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,KAAK,GAAG,YAAY,GAAG,UAAU,EAC5C,SAAS,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,EACtC,OAAO,CAAC,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,MAAM,EACpB,aAAa,CAAC,EAAE,MAAM,GACrB,UAAU,CASZ;AAID,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAClD,SAAS,EAAE,KAAK,GAAG,YAAY,GAAG,UAAU,CAAC;IAC7C,uFAAuF;IACvF,SAAS,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,iGAAiG;IACjG,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,OAAO,CAAC;IACpB,oGAAoG;IACpG,eAAe,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;IAC3D,WAAW,EAAE,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG;QAAE,eAAe,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAClF;AAED,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;CAClD;AAED,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB;AAID;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,EAC7B,YAAY,EAAE,aAAa,EAC3B,SAAS,EACT,SAAoB,EACpB,OAAO,EACP,OAAO,EACP,WAAW,EACX,YAAY,EACZ,QAAQ,GACT,EAAE,qBAAqB,GAAG,oBAAoB,CAyD9C;AAID;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,MAAM,CAAC,CAAC,EACtD,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,OAAO,GACrB,IAAI,CAUN;AAID;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,WAAW,EACX,SAAS,EACT,gBAAwB,EACxB,iBAAiB,GAClB,EAAE,uBAAuB,GAAG,sBAAsB,CAalD;AAID,MAAM,WAAW,+BAA+B;IAC9C,2GAA2G;IAC3G,gBAAgB,EAAE,OAAO,CAAC;IAC1B,WAAW,EAAE,oBAAoB,CAAC,aAAa,CAAC,CAAC;IACjD,SAAS,EAAE,OAAO,CAAC;IACnB,eAAe,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;IAC3D,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,GAAG,EAAE,OAAO,CAAC;IACb,SAAS,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IACvC,sFAAsF;IACtF,eAAe,EAAE,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;CACjD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAAC,EACvC,gBAAgB,EAChB,WAAW,EACX,SAAS,EACT,eAAe,EACf,WAAW,EACX,qBAAqB,EACrB,MAAM,EACN,GAAG,EACH,SAAS,EACT,eAAe,GAChB,EAAE,+BAA+B,GAAG,oBAAoB,CAAC,aAAa,CAAC,CAsFvE"}
@@ -0,0 +1,179 @@
1
+ import * as React from 'react';
2
+ import { useControllableState } from '@timmbr/hooks';
3
+ import { animate, useMotionValue } from '@timmbr/motion';
4
+
5
+ const DEFAULT_H_MIN = 120;
6
+ const DEFAULT_H_MAX = 640;
7
+ const DEFAULT_H_SIZE = 320;
8
+ const DEFAULT_H_COLLAPSED = 40;
9
+ const DEFAULT_V_MIN = 80;
10
+ const DEFAULT_V_MAX = 480;
11
+ const DEFAULT_V_SIZE = 240;
12
+ const DEFAULT_V_COLLAPSED = 40;
13
+ function resolvePanelSizes(resizable, placement, minSize, maxSize, defaultSize, collapsedSize) {
14
+ const isH = resizable === "horizontal" || placement === "right" || placement === "left";
15
+ return {
16
+ isH,
17
+ resolvedMin: minSize ?? (isH ? DEFAULT_H_MIN : DEFAULT_V_MIN),
18
+ resolvedMax: maxSize ?? (isH ? DEFAULT_H_MAX : DEFAULT_V_MAX),
19
+ resolvedDefault: defaultSize ?? (isH ? DEFAULT_H_SIZE : DEFAULT_V_SIZE),
20
+ resolvedCollapsedSize: collapsedSize ?? (isH ? DEFAULT_H_COLLAPSED : DEFAULT_V_COLLAPSED)
21
+ };
22
+ }
23
+ function usePanelResize({
24
+ containerRef: _containerRef,
25
+ resizable,
26
+ placement = "inline",
27
+ minSize,
28
+ maxSize,
29
+ defaultSize,
30
+ initialValue,
31
+ onResize
32
+ }) {
33
+ const [size, setSize] = React.useState(defaultSize);
34
+ const [isResizing, setIsResizing] = React.useState(false);
35
+ const sizeMotionValue = useMotionValue(initialValue ?? defaultSize);
36
+ const dragStartPos = React.useRef(0);
37
+ const dragStartSize = React.useRef(defaultSize);
38
+ const clamp = React.useCallback(
39
+ (v) => Math.min(maxSize, Math.max(minSize, v)),
40
+ [minSize, maxSize]
41
+ );
42
+ const handlePointerDown = React.useCallback(
43
+ (e) => {
44
+ if (resizable === false) return;
45
+ e.preventDefault();
46
+ e.target.setPointerCapture(e.pointerId);
47
+ dragStartPos.current = resizable === "horizontal" ? e.clientX : e.clientY;
48
+ dragStartSize.current = sizeMotionValue.get();
49
+ setIsResizing(true);
50
+ },
51
+ [resizable, sizeMotionValue]
52
+ );
53
+ const handlePointerMove = React.useCallback(
54
+ (e) => {
55
+ if (!e.buttons || resizable === false) return;
56
+ const rawDelta = (resizable === "horizontal" ? e.clientX : e.clientY) - dragStartPos.current;
57
+ const delta = placement === "right" ? -rawDelta : rawDelta;
58
+ const next = clamp(dragStartSize.current + delta);
59
+ sizeMotionValue.set(next);
60
+ },
61
+ [resizable, placement, clamp, sizeMotionValue]
62
+ );
63
+ const handlePointerUp = React.useCallback(() => {
64
+ if (!isResizing) return;
65
+ const final = sizeMotionValue.get();
66
+ setIsResizing(false);
67
+ setSize(final);
68
+ onResize?.(final);
69
+ }, [isResizing, sizeMotionValue, onResize]);
70
+ const handleProps = {
71
+ role: "separator",
72
+ "aria-label": resizable === "horizontal" ? "Resize panel width" : "Resize panel height",
73
+ onPointerDown: handlePointerDown,
74
+ onPointerMove: handlePointerMove,
75
+ onPointerUp: handlePointerUp,
76
+ ...isResizing ? { "data-resizing": "true" } : {}
77
+ };
78
+ return { size, isResizing, sizeMotionValue, handleProps };
79
+ }
80
+ function animatePanelSize(motionValue, target, shouldAnimate) {
81
+ if (shouldAnimate) {
82
+ animate(motionValue, target, {
83
+ type: "tween",
84
+ duration: 0.2,
85
+ ease: [0.25, 1, 0.5, 1]
86
+ });
87
+ } else {
88
+ motionValue.set(target);
89
+ }
90
+ }
91
+ function usePanelCollapse({
92
+ collapsible,
93
+ collapsed,
94
+ defaultCollapsed = false,
95
+ onCollapsedChange
96
+ }) {
97
+ const [isCollapsed, setIsCollapsed] = useControllableState({
98
+ value: collapsed,
99
+ defaultValue: defaultCollapsed,
100
+ onChange: onCollapsedChange
101
+ });
102
+ const toggle = React.useCallback(() => {
103
+ if (!collapsible) return;
104
+ setIsCollapsed((prev) => !prev);
105
+ }, [collapsible, setIsCollapsed]);
106
+ return { collapsed: isCollapsed ?? false, toggle };
107
+ }
108
+ function usePanelSnapCoordination({
109
+ activelySnapping,
110
+ handleProps,
111
+ collapsed,
112
+ sizeMotionValue,
113
+ resolvedMin,
114
+ resolvedCollapsedSize,
115
+ toggle,
116
+ isH,
117
+ placement,
118
+ expandedSizeRef
119
+ }) {
120
+ const dragFromCollapsedRef = React.useRef(false);
121
+ const pendingExpandRef = React.useRef(false);
122
+ const pendingDragStartPos = React.useRef(0);
123
+ return React.useMemo(() => {
124
+ if (!activelySnapping) return handleProps;
125
+ const origDown = handleProps.onPointerDown;
126
+ const origMove = handleProps.onPointerMove;
127
+ const origUp = handleProps.onPointerUp;
128
+ return {
129
+ ...handleProps,
130
+ onPointerDown: (e) => {
131
+ if (collapsed) {
132
+ pendingExpandRef.current = true;
133
+ dragFromCollapsedRef.current = true;
134
+ pendingDragStartPos.current = isH ? e.clientX : e.clientY;
135
+ } else {
136
+ pendingExpandRef.current = false;
137
+ dragFromCollapsedRef.current = false;
138
+ }
139
+ origDown?.(e);
140
+ },
141
+ onPointerMove: (e) => {
142
+ if (!pendingExpandRef.current) {
143
+ origMove?.(e);
144
+ return;
145
+ }
146
+ const curPos = isH ? e.clientX : e.clientY;
147
+ const rawDelta = curPos - pendingDragStartPos.current;
148
+ const delta = placement === "right" ? -rawDelta : rawDelta;
149
+ const wouldBe = resolvedCollapsedSize + delta;
150
+ if (wouldBe >= resolvedMin) {
151
+ pendingExpandRef.current = false;
152
+ expandedSizeRef.current = resolvedMin;
153
+ toggle();
154
+ origMove?.(e);
155
+ }
156
+ },
157
+ onPointerUp: (e) => {
158
+ const wasPending = pendingExpandRef.current;
159
+ pendingExpandRef.current = false;
160
+ origUp?.(e);
161
+ if (wasPending) {
162
+ expandedSizeRef.current = resolvedMin;
163
+ dragFromCollapsedRef.current = false;
164
+ return;
165
+ }
166
+ if (dragFromCollapsedRef.current) {
167
+ dragFromCollapsedRef.current = false;
168
+ return;
169
+ }
170
+ if (!collapsed && sizeMotionValue.get() <= resolvedMin) {
171
+ expandedSizeRef.current = resolvedMin;
172
+ toggle();
173
+ }
174
+ }
175
+ };
176
+ }, [activelySnapping, handleProps, collapsed, sizeMotionValue, resolvedMin, resolvedCollapsedSize, toggle, isH, placement]);
177
+ }
178
+
179
+ export { DEFAULT_H_COLLAPSED, DEFAULT_H_MAX, DEFAULT_H_MIN, DEFAULT_H_SIZE, DEFAULT_V_COLLAPSED, DEFAULT_V_MAX, DEFAULT_V_MIN, DEFAULT_V_SIZE, animatePanelSize, resolvePanelSizes, usePanelCollapse, usePanelResize, usePanelSnapCoordination };
@@ -0,0 +1,174 @@
1
+ "use client";
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+ import * as React from 'react';
4
+ import { Slot } from '@radix-ui/react-slot';
5
+ import { cn } from '@timmbr/utils';
6
+ import { motion } from '@timmbr/motion';
7
+ import { usePrevious } from '@timmbr/hooks';
8
+ import { resolveMotion } from '../../types/motion.js';
9
+ import { panelVariants } from './Panel.styles.js';
10
+ import { resolvePanelSizes, usePanelResize, usePanelCollapse, animatePanelSize, usePanelSnapCoordination } from './Panel.helpers.js';
11
+ import { PanelContext } from './Panel.context.js';
12
+ import { PanelResizeHandle } from './subcomponents/PanelResizeHandle.js';
13
+ import { useGlobalAnimation } from '../../providers/AnimationProvider.js';
14
+
15
+ const Panel = React.forwardRef(
16
+ ({
17
+ className,
18
+ variant,
19
+ padding,
20
+ placement = "inline",
21
+ sectioned = false,
22
+ asChild = false,
23
+ resizable = false,
24
+ minSize,
25
+ maxSize,
26
+ defaultSize,
27
+ onResize,
28
+ collapsible = false,
29
+ collapsed: controlledCollapsed,
30
+ defaultCollapsed = false,
31
+ collapsedSize,
32
+ onCollapsedChange,
33
+ snapToCollapse = true,
34
+ motion: motionProp,
35
+ children,
36
+ ...props
37
+ }, ref) => {
38
+ const globalMotion = useGlobalAnimation();
39
+ const { shouldAnimate, motionClass } = resolveMotion(motionProp, globalMotion);
40
+ const rawId = React.useId();
41
+ const panelId = rawId.replace(/[^a-zA-Z0-9_-]/g, "");
42
+ const containerRef = React.useRef(null);
43
+ const resolvedPlacement = placement ?? "inline";
44
+ const { isH, resolvedMin, resolvedMax, resolvedDefault, resolvedCollapsedSize } = resolvePanelSizes(resizable, resolvedPlacement, minSize, maxSize, defaultSize, collapsedSize);
45
+ const isInitiallyCollapsed = collapsible && (defaultCollapsed || controlledCollapsed === true);
46
+ const initialMotionValue = isInitiallyCollapsed ? resolvedCollapsedSize : resolvedDefault;
47
+ const expandedSizeRef = React.useRef(isInitiallyCollapsed ? resolvedDefault : initialMotionValue);
48
+ const { isResizing, sizeMotionValue, handleProps } = usePanelResize({
49
+ containerRef,
50
+ resizable,
51
+ placement: resolvedPlacement,
52
+ minSize: resolvedMin,
53
+ maxSize: resolvedMax,
54
+ defaultSize: resolvedDefault,
55
+ initialValue: initialMotionValue,
56
+ onResize: (newSize) => {
57
+ expandedSizeRef.current = newSize;
58
+ onResize?.(newSize);
59
+ }
60
+ });
61
+ const { collapsed, toggle } = usePanelCollapse({
62
+ collapsible,
63
+ collapsed: controlledCollapsed,
64
+ defaultCollapsed,
65
+ onCollapsedChange
66
+ });
67
+ const prevCollapsed = usePrevious(collapsed);
68
+ React.useEffect(() => {
69
+ if (!collapsible || prevCollapsed === void 0 || prevCollapsed === collapsed) return;
70
+ animatePanelSize(
71
+ sizeMotionValue,
72
+ collapsed ? resolvedCollapsedSize : expandedSizeRef.current,
73
+ shouldAnimate
74
+ );
75
+ }, [collapsed, collapsible, resolvedCollapsedSize, sizeMotionValue, shouldAnimate]);
76
+ const coordHandleProps = usePanelSnapCoordination({
77
+ activelySnapping: collapsible && resizable !== false && snapToCollapse,
78
+ handleProps,
79
+ collapsed,
80
+ sizeMotionValue,
81
+ resolvedMin,
82
+ resolvedCollapsedSize,
83
+ toggle,
84
+ isH,
85
+ placement: resolvedPlacement,
86
+ expandedSizeRef
87
+ });
88
+ const context = React.useMemo(
89
+ () => ({
90
+ sectioned,
91
+ padding: padding ?? "default",
92
+ collapsed,
93
+ collapsible,
94
+ shouldAnimate,
95
+ panelId,
96
+ placement: resolvedPlacement,
97
+ onToggleCollapse: toggle
98
+ }),
99
+ [sectioned, padding, collapsed, collapsible, shouldAnimate, panelId, resolvedPlacement, toggle]
100
+ );
101
+ const needsSizeControl = resizable !== false || collapsible;
102
+ const dimension = isH ? "width" : "height";
103
+ const handleEdge = resizable === "horizontal" ? resolvedPlacement === "right" ? "left" : "right" : "bottom";
104
+ const rootClasses = cn(
105
+ panelVariants({ variant, padding, sectioned, placement }),
106
+ needsSizeControl && "overflow-hidden",
107
+ !shouldAnimate && "transition-none animate-none",
108
+ motionClass,
109
+ className
110
+ );
111
+ const combinedRef = React.useCallback(
112
+ (node) => {
113
+ containerRef.current = node;
114
+ if (typeof ref === "function") ref(node);
115
+ else if (ref) ref.current = node;
116
+ },
117
+ [ref]
118
+ );
119
+ const rootContent = /* @__PURE__ */ jsxs(PanelContext.Provider, { value: context, children: [
120
+ children,
121
+ resizable !== false && /* @__PURE__ */ jsx(
122
+ PanelResizeHandle,
123
+ {
124
+ direction: handleEdge,
125
+ isResizing,
126
+ handleProps: coordHandleProps
127
+ }
128
+ )
129
+ ] });
130
+ if (asChild) {
131
+ return /* @__PURE__ */ jsx(
132
+ Slot,
133
+ {
134
+ ref,
135
+ "data-slot": "panel",
136
+ "data-collapsed": collapsed || void 0,
137
+ className: rootClasses,
138
+ ...props,
139
+ children: rootContent
140
+ }
141
+ );
142
+ }
143
+ if (needsSizeControl && shouldAnimate) {
144
+ return /* @__PURE__ */ jsx(
145
+ motion.div,
146
+ {
147
+ ref: combinedRef,
148
+ "data-slot": "panel",
149
+ "data-collapsed": collapsed || void 0,
150
+ className: rootClasses,
151
+ style: { [dimension]: sizeMotionValue },
152
+ ...props,
153
+ children: rootContent
154
+ }
155
+ );
156
+ }
157
+ const staticStyle = needsSizeControl ? { [dimension]: collapsed ? resolvedCollapsedSize : sizeMotionValue.get(), ...props.style ?? {} } : props.style ?? void 0;
158
+ return /* @__PURE__ */ jsx(
159
+ "div",
160
+ {
161
+ ref: combinedRef,
162
+ "data-slot": "panel",
163
+ "data-collapsed": collapsed || void 0,
164
+ className: rootClasses,
165
+ style: staticStyle,
166
+ ...props,
167
+ children: rootContent
168
+ }
169
+ );
170
+ }
171
+ );
172
+ Panel.displayName = "Panel";
173
+
174
+ export { Panel };
@@ -0,0 +1,42 @@
1
+ import { type VariantProps } from 'class-variance-authority';
2
+ export declare const panelVariants: (props?: ({
3
+ variant?: "outline" | "ghost" | "elevated" | "subtle" | null | undefined;
4
+ padding?: "none" | "sm" | "lg" | "default" | null | undefined;
5
+ sectioned?: boolean | null | undefined;
6
+ placement?: "left" | "right" | "inline" | null | undefined;
7
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
8
+ export declare const panelSectionPadding: {
9
+ readonly none: "";
10
+ readonly sm: "p-4";
11
+ readonly default: "p-6";
12
+ readonly lg: "p-8";
13
+ };
14
+ export declare const panelSectionFooterPadding: {
15
+ readonly none: "";
16
+ readonly sm: "px-4 py-2";
17
+ readonly default: "px-6 py-3";
18
+ readonly lg: "px-8 py-4";
19
+ };
20
+ export declare const panelHeaderVariants: (props?: ({
21
+ sectioned?: boolean | null | undefined;
22
+ divider?: boolean | null | undefined;
23
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
24
+ export declare const panelTitleVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
25
+ export declare const panelDescriptionVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
26
+ export declare const panelBodyVariants: (props?: ({
27
+ overflow?: "auto" | "hidden" | "visible" | null | undefined;
28
+ sectioned?: boolean | null | undefined;
29
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
30
+ export declare const panelFooterVariants: (props?: ({
31
+ sectioned?: boolean | null | undefined;
32
+ justify?: "start" | "end" | "between" | null | undefined;
33
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
34
+ export declare const panelResizeHandleVariants: (props?: ({
35
+ direction?: "left" | "right" | "bottom" | null | undefined;
36
+ resizing?: boolean | null | undefined;
37
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
38
+ export type PanelVariants = VariantProps<typeof panelVariants>;
39
+ export type PanelBodyVariants = VariantProps<typeof panelBodyVariants>;
40
+ export type PanelFooterVariants = VariantProps<typeof panelFooterVariants>;
41
+ export type PanelResizeHandleVariants = VariantProps<typeof panelResizeHandleVariants>;
42
+ //# sourceMappingURL=Panel.styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Panel.styles.d.ts","sourceRoot":"","sources":["../../../src/components/Panel/Panel.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAElE,eAAO,MAAM,aAAa;;;;;8EAiCzB,CAAC;AAEF,eAAO,MAAM,mBAAmB;;;;;CAKtB,CAAC;AAEX,eAAO,MAAM,yBAAyB;;;;;CAK5B,CAAC;AAEX,eAAO,MAAM,mBAAmB;;;8EAa9B,CAAC;AAEH,eAAO,MAAM,kBAAkB,oFAE9B,CAAC;AAEF,eAAO,MAAM,wBAAwB,oFAEpC,CAAC;AAEF,eAAO,MAAM,iBAAiB;;;8EAa5B,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;8EAgB/B,CAAC;AAEF,eAAO,MAAM,yBAAyB;;;8EAgBrC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,YAAY,CAAC,OAAO,aAAa,CAAC,CAAC;AAC/D,MAAM,MAAM,iBAAiB,GAAG,YAAY,CAAC,OAAO,iBAAiB,CAAC,CAAC;AACvE,MAAM,MAAM,mBAAmB,GAAG,YAAY,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAC3E,MAAM,MAAM,yBAAyB,GAAG,YAAY,CAAC,OAAO,yBAAyB,CAAC,CAAC"}
@@ -0,0 +1,118 @@
1
+ import { cva } from 'class-variance-authority';
2
+
3
+ const panelVariants = cva(
4
+ "relative flex flex-col text-foreground font-sans",
5
+ {
6
+ variants: {
7
+ variant: {
8
+ outline: "border border-grey-200 dark:border-grey-800 bg-card shadow-sm",
9
+ elevated: "border border-transparent bg-card shadow-md",
10
+ subtle: "border border-transparent bg-card",
11
+ ghost: "bg-transparent"
12
+ },
13
+ padding: {
14
+ none: "p-0",
15
+ sm: "p-4",
16
+ default: "p-6",
17
+ lg: "p-8"
18
+ },
19
+ sectioned: {
20
+ true: "p-0",
21
+ false: ""
22
+ },
23
+ placement: {
24
+ inline: "rounded-[4px]",
25
+ left: "rounded-r-[4px] h-full shrink-0",
26
+ right: "rounded-l-[4px] h-full shrink-0"
27
+ }
28
+ },
29
+ defaultVariants: {
30
+ variant: "outline",
31
+ padding: "default",
32
+ sectioned: false,
33
+ placement: "inline"
34
+ }
35
+ }
36
+ );
37
+ const panelSectionPadding = {
38
+ none: "",
39
+ sm: "p-4",
40
+ default: "p-6",
41
+ lg: "p-8"
42
+ };
43
+ const panelSectionFooterPadding = {
44
+ none: "",
45
+ sm: "px-4 py-2",
46
+ default: "px-6 py-3",
47
+ lg: "px-8 py-4"
48
+ };
49
+ const panelHeaderVariants = cva("flex flex-col gap-1.5", {
50
+ variants: {
51
+ sectioned: {
52
+ true: "",
53
+ false: "mb-4"
54
+ },
55
+ divider: {
56
+ true: "border-b border-border",
57
+ false: ""
58
+ }
59
+ },
60
+ compoundVariants: [{ sectioned: false, divider: true, className: "pb-4" }],
61
+ defaultVariants: { sectioned: false, divider: false }
62
+ });
63
+ const panelTitleVariants = cva(
64
+ "text-h6 font-bold text-foreground leading-tight tracking-tight"
65
+ );
66
+ const panelDescriptionVariants = cva(
67
+ "text-body-2 text-muted-foreground leading-relaxed"
68
+ );
69
+ const panelBodyVariants = cva("flex-1 min-h-0", {
70
+ variants: {
71
+ overflow: {
72
+ auto: "overflow-auto",
73
+ hidden: "overflow-hidden",
74
+ visible: "overflow-visible"
75
+ },
76
+ sectioned: {
77
+ true: "",
78
+ false: ""
79
+ }
80
+ },
81
+ defaultVariants: { overflow: "auto", sectioned: false }
82
+ });
83
+ const panelFooterVariants = cva(
84
+ "flex items-center gap-2 border-t border-border",
85
+ {
86
+ variants: {
87
+ sectioned: {
88
+ true: "",
89
+ false: "pt-4 mt-4"
90
+ },
91
+ justify: {
92
+ start: "justify-start",
93
+ between: "justify-between",
94
+ end: "justify-end"
95
+ }
96
+ },
97
+ defaultVariants: { sectioned: false, justify: "between" }
98
+ }
99
+ );
100
+ const panelResizeHandleVariants = cva(
101
+ "absolute z-10 flex items-center justify-center select-none touch-none group transition-colors duration-100 hover:bg-primary/10 active:bg-primary/15",
102
+ {
103
+ variants: {
104
+ direction: {
105
+ left: "left-0 inset-y-0 w-2 cursor-ew-resize",
106
+ right: "right-0 inset-y-0 w-2 cursor-ew-resize",
107
+ bottom: "bottom-0 inset-x-0 h-2 cursor-ns-resize"
108
+ },
109
+ resizing: {
110
+ true: "bg-primary/15",
111
+ false: ""
112
+ }
113
+ },
114
+ defaultVariants: { direction: "left", resizing: false }
115
+ }
116
+ );
117
+
118
+ export { panelBodyVariants, panelDescriptionVariants, panelFooterVariants, panelHeaderVariants, panelResizeHandleVariants, panelSectionFooterPadding, panelSectionPadding, panelTitleVariants, panelVariants };
@@ -0,0 +1,59 @@
1
+ import type * as React from 'react';
2
+ import type { MotionProp } from '../../types/motion';
3
+ import type { PanelVariants, PanelBodyVariants, PanelFooterVariants } from './Panel.styles';
4
+ export interface PanelProps extends React.HTMLAttributes<HTMLDivElement>, Omit<PanelVariants, 'sectioned'> {
5
+ asChild?: boolean;
6
+ /**
7
+ * Distributes padding to PanelHeader / PanelBody / PanelFooter instead of
8
+ * the root, so header and footer dividers run edge to edge.
9
+ */
10
+ sectioned?: boolean;
11
+ /** Enables a drag handle at the panel edge for continuous resize. */
12
+ resizable?: false | 'horizontal' | 'vertical';
13
+ /** Minimum size in px. Defaults: 120 (horizontal) / 80 (vertical). */
14
+ minSize?: number;
15
+ /** Maximum size in px. Defaults: 640 (horizontal) / 480 (vertical). */
16
+ maxSize?: number;
17
+ /** Initial size in px. Defaults: 320 (horizontal) / 240 (vertical). */
18
+ defaultSize?: number;
19
+ /** Called when a drag-resize interaction commits a new size. */
20
+ onResize?: (size: number) => void;
21
+ /** Shows a chevron toggle button in the header to collapse/expand the panel. */
22
+ collapsible?: boolean;
23
+ /** Controlled collapsed state. */
24
+ collapsed?: boolean;
25
+ /** Uncontrolled initial collapsed state. */
26
+ defaultCollapsed?: boolean;
27
+ /** Size in px when collapsed. Defaults to 40 (narrow icon bar). */
28
+ collapsedSize?: number;
29
+ /** Called when the collapsed state changes. */
30
+ onCollapsedChange?: (collapsed: boolean) => void;
31
+ /**
32
+ * When both `resizable` and `collapsible` are set:
33
+ * - Dragging the handle while collapsed auto-expands to `minSize`.
34
+ * - Dragging below `(collapsedSize + minSize) / 2` auto-collapses.
35
+ * Default: `true`.
36
+ */
37
+ snapToCollapse?: boolean;
38
+ motion?: MotionProp;
39
+ }
40
+ export interface PanelHeaderProps extends React.HTMLAttributes<HTMLDivElement> {
41
+ asChild?: boolean;
42
+ /** Renders a divider line below the header (full width in sectioned panels). */
43
+ divider?: boolean;
44
+ /** Content rendered at the trailing end of the header row. */
45
+ actions?: React.ReactNode;
46
+ }
47
+ export interface PanelTitleProps extends React.HTMLAttributes<HTMLHeadingElement> {
48
+ asChild?: boolean;
49
+ }
50
+ export interface PanelDescriptionProps extends React.HTMLAttributes<HTMLParagraphElement> {
51
+ asChild?: boolean;
52
+ }
53
+ export interface PanelBodyProps extends React.HTMLAttributes<HTMLDivElement>, Omit<PanelBodyVariants, 'sectioned'> {
54
+ asChild?: boolean;
55
+ }
56
+ export interface PanelFooterProps extends React.HTMLAttributes<HTMLDivElement>, Omit<PanelFooterVariants, 'sectioned'> {
57
+ asChild?: boolean;
58
+ }
59
+ //# sourceMappingURL=Panel.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Panel.types.d.ts","sourceRoot":"","sources":["../../../src/components/Panel/Panel.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AACpC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EACV,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACpB,MAAM,gBAAgB,CAAC;AAExB,MAAM,WAAW,UACf,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAC1C,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAGpB,qEAAqE;IACrE,SAAS,CAAC,EAAE,KAAK,GAAG,YAAY,GAAG,UAAU,CAAC;IAC9C,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAGlC,gFAAgF;IAChF,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kCAAkC;IAClC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,4CAA4C;IAC5C,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,mEAAmE;IACnE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,+CAA+C;IAC/C,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;IAGjD;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAGzB,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED,MAAM,WAAW,gBAAiB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IAC5E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,gFAAgF;IAChF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,8DAA8D;IAC9D,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,MAAM,WAAW,eACf,SAAQ,KAAK,CAAC,cAAc,CAAC,kBAAkB,CAAC;IAChD,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,qBACf,SAAQ,KAAK,CAAC,cAAc,CAAC,oBAAoB,CAAC;IAClD,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,cACf,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAC1C,IAAI,CAAC,iBAAiB,EAAE,WAAW,CAAC;IACtC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,gBACf,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAC1C,IAAI,CAAC,mBAAmB,EAAE,WAAW,CAAC;IACxC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB"}
@@ -0,0 +1,7 @@
1
+ export * from './Panel';
2
+ export * from './Panel.context';
3
+ export * from './Panel.types';
4
+ export * from './Panel.styles';
5
+ export * from './Panel.helpers';
6
+ export * from './subcomponents';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Panel/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import * as React from 'react';
2
+ import type { PanelBodyProps } from '../Panel.types';
3
+ export declare const PanelBody: React.ForwardRefExoticComponent<PanelBodyProps & React.RefAttributes<HTMLDivElement>>;
4
+ //# sourceMappingURL=PanelBody.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PanelBody.d.ts","sourceRoot":"","sources":["../../../../src/components/Panel/subcomponents/PanelBody.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAM/B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,eAAO,MAAM,SAAS,uFAuDrB,CAAC"}
@@ -0,0 +1,58 @@
1
+ "use client";
2
+ import { jsx } from 'react/jsx-runtime';
3
+ import * as React from 'react';
4
+ import { Slot } from '@radix-ui/react-slot';
5
+ import { cn } from '@timmbr/utils';
6
+ import { AnimatePresence, motion, panelContentFadeVariants } from '@timmbr/motion';
7
+ import { panelBodyVariants, panelSectionPadding } from '../Panel.styles.js';
8
+ import { usePanelContext } from '../Panel.context.js';
9
+
10
+ const PanelBody = React.forwardRef(
11
+ ({ className, asChild = false, overflow = "auto", children, ...props }, ref) => {
12
+ const { sectioned, padding, collapsed, collapsible, shouldAnimate, panelId } = usePanelContext();
13
+ const Comp = asChild ? Slot : "div";
14
+ const bodyClasses = cn(
15
+ panelBodyVariants({ overflow, sectioned }),
16
+ sectioned && panelSectionPadding[padding],
17
+ className
18
+ );
19
+ if (!collapsible) {
20
+ return /* @__PURE__ */ jsx(
21
+ Comp,
22
+ {
23
+ ref,
24
+ id: `panel-body-${panelId}`,
25
+ "data-slot": "panel-body",
26
+ className: bodyClasses,
27
+ ...props,
28
+ children
29
+ }
30
+ );
31
+ }
32
+ return /* @__PURE__ */ jsx(
33
+ Comp,
34
+ {
35
+ ref,
36
+ id: `panel-body-${panelId}`,
37
+ "data-slot": "panel-body",
38
+ className: cn(bodyClasses, "overflow-hidden"),
39
+ ...props,
40
+ children: shouldAnimate ? /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: !collapsed && /* @__PURE__ */ jsx(
41
+ motion.div,
42
+ {
43
+ variants: panelContentFadeVariants,
44
+ initial: "hidden",
45
+ animate: "visible",
46
+ exit: "exit",
47
+ className: "h-full",
48
+ children
49
+ },
50
+ "panel-body-content"
51
+ ) }) : !collapsed && children
52
+ }
53
+ );
54
+ }
55
+ );
56
+ PanelBody.displayName = "PanelBody";
57
+
58
+ export { PanelBody };
@@ -0,0 +1,4 @@
1
+ import * as React from 'react';
2
+ import type { PanelDescriptionProps } from '../Panel.types';
3
+ export declare const PanelDescription: React.ForwardRefExoticComponent<PanelDescriptionProps & React.RefAttributes<HTMLParagraphElement>>;
4
+ //# sourceMappingURL=PanelDescription.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PanelDescription.d.ts","sourceRoot":"","sources":["../../../../src/components/Panel/subcomponents/PanelDescription.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAE5D,eAAO,MAAM,gBAAgB,oGAY5B,CAAC"}
@@ -0,0 +1,24 @@
1
+ "use client";
2
+ import { jsx } from 'react/jsx-runtime';
3
+ import * as React from 'react';
4
+ import { Slot } from '@radix-ui/react-slot';
5
+ import { cn } from '@timmbr/utils';
6
+ import { panelDescriptionVariants } from '../Panel.styles.js';
7
+
8
+ const PanelDescription = React.forwardRef(
9
+ ({ className, asChild = false, ...props }, ref) => {
10
+ const Comp = asChild ? Slot : "p";
11
+ return /* @__PURE__ */ jsx(
12
+ Comp,
13
+ {
14
+ ref,
15
+ "data-slot": "panel-description",
16
+ className: cn(panelDescriptionVariants(), className),
17
+ ...props
18
+ }
19
+ );
20
+ }
21
+ );
22
+ PanelDescription.displayName = "PanelDescription";
23
+
24
+ export { PanelDescription };
@@ -0,0 +1,4 @@
1
+ import * as React from 'react';
2
+ import type { PanelFooterProps } from '../Panel.types';
3
+ export declare const PanelFooter: React.ForwardRefExoticComponent<PanelFooterProps & React.RefAttributes<HTMLDivElement>>;
4
+ //# sourceMappingURL=PanelFooter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PanelFooter.d.ts","sourceRoot":"","sources":["../../../../src/components/Panel/subcomponents/PanelFooter.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,eAAO,MAAM,WAAW,yFA4BvB,CAAC"}
@@ -0,0 +1,27 @@
1
+ "use client";
2
+ import { jsx } from 'react/jsx-runtime';
3
+ import * as React from 'react';
4
+ import { Slot } from '@radix-ui/react-slot';
5
+ import { cn } from '@timmbr/utils';
6
+ import { panelFooterVariants, panelSectionFooterPadding } from '../Panel.styles.js';
7
+ import { usePanelContext } from '../Panel.context.js';
8
+
9
+ const PanelFooter = React.forwardRef(
10
+ ({ className, asChild = false, justify, children, ...props }, ref) => {
11
+ const { sectioned, padding, collapsed, collapsible } = usePanelContext();
12
+ const Comp = asChild ? Slot : "div";
13
+ const footerClasses = cn(
14
+ panelFooterVariants({ sectioned, justify }),
15
+ sectioned && panelSectionFooterPadding[padding],
16
+ className
17
+ );
18
+ if (!collapsible) {
19
+ return /* @__PURE__ */ jsx(Comp, { ref, "data-slot": "panel-footer", className: footerClasses, ...props, children });
20
+ }
21
+ if (collapsed) return null;
22
+ return /* @__PURE__ */ jsx(Comp, { ref, "data-slot": "panel-footer", className: footerClasses, ...props, children });
23
+ }
24
+ );
25
+ PanelFooter.displayName = "PanelFooter";
26
+
27
+ export { PanelFooter };
@@ -0,0 +1,4 @@
1
+ import * as React from 'react';
2
+ import type { PanelHeaderProps } from '../Panel.types';
3
+ export declare const PanelHeader: React.ForwardRefExoticComponent<PanelHeaderProps & React.RefAttributes<HTMLDivElement>>;
4
+ //# sourceMappingURL=PanelHeader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PanelHeader.d.ts","sourceRoot":"","sources":["../../../../src/components/Panel/subcomponents/PanelHeader.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAO/B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,eAAO,MAAM,WAAW,yFAqGvB,CAAC"}
@@ -0,0 +1,101 @@
1
+ "use client";
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+ import * as React from 'react';
4
+ import { Slot } from '@radix-ui/react-slot';
5
+ import { cn } from '@timmbr/utils';
6
+ import { motion, transitions } from '@timmbr/motion';
7
+ import { ChevronRight } from '@timmbr/icons';
8
+ import { panelHeaderVariants, panelSectionPadding } from '../Panel.styles.js';
9
+ import { usePanelContext } from '../Panel.context.js';
10
+
11
+ const PanelHeader = React.forwardRef(
12
+ ({ className, asChild = false, divider = false, actions, children, ...props }, ref) => {
13
+ const {
14
+ sectioned,
15
+ padding,
16
+ collapsed,
17
+ collapsible,
18
+ shouldAnimate,
19
+ panelId,
20
+ placement,
21
+ onToggleCollapse
22
+ } = usePanelContext();
23
+ const Comp = asChild ? Slot : "div";
24
+ const rotationDeg = placement === "right" ? collapsed ? 180 : 0 : collapsed ? 0 : 180;
25
+ const collapseButton = collapsible && /* @__PURE__ */ jsxs(
26
+ "button",
27
+ {
28
+ type: "button",
29
+ "aria-expanded": !collapsed,
30
+ "aria-controls": `panel-body-${panelId}`,
31
+ onClick: onToggleCollapse,
32
+ className: "flex size-7 shrink-0 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-primary",
33
+ "data-slot": "panel-collapse-toggle",
34
+ children: [
35
+ shouldAnimate ? /* @__PURE__ */ jsx(
36
+ motion.span,
37
+ {
38
+ animate: { rotate: rotationDeg },
39
+ transition: transitions.fast,
40
+ style: { display: "flex", alignItems: "center", justifyContent: "center" },
41
+ children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-3.5 w-3.5" })
42
+ }
43
+ ) : /* @__PURE__ */ jsx(
44
+ "span",
45
+ {
46
+ style: {
47
+ display: "flex",
48
+ alignItems: "center",
49
+ justifyContent: "center",
50
+ transform: `rotate(${rotationDeg}deg)`
51
+ },
52
+ children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-3.5 w-3.5" })
53
+ }
54
+ ),
55
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: collapsed ? "Expand panel" : "Collapse panel" })
56
+ ]
57
+ }
58
+ );
59
+ const headerClasses = cn(
60
+ panelHeaderVariants({ sectioned, divider }),
61
+ sectioned && panelSectionPadding[padding],
62
+ sectioned && !divider && "pb-0",
63
+ className
64
+ );
65
+ if (collapsible && collapsed) {
66
+ return /* @__PURE__ */ jsx(
67
+ Comp,
68
+ {
69
+ ref,
70
+ "data-slot": "panel-header",
71
+ className: cn("flex items-center justify-center py-2", className),
72
+ ...props,
73
+ children: collapseButton
74
+ }
75
+ );
76
+ }
77
+ const hasTrailingContent = actions !== void 0 || collapsible;
78
+ if (!hasTrailingContent) {
79
+ return /* @__PURE__ */ jsx(Comp, { ref, "data-slot": "panel-header", className: headerClasses, ...props, children });
80
+ }
81
+ return /* @__PURE__ */ jsxs(
82
+ Comp,
83
+ {
84
+ ref,
85
+ "data-slot": "panel-header",
86
+ className: cn(headerClasses, "flex-row items-start justify-between gap-2"),
87
+ ...props,
88
+ children: [
89
+ /* @__PURE__ */ jsx("div", { className: "flex min-w-0 flex-col gap-1", "data-slot": "panel-header-text", children }),
90
+ /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-1 -mt-0.5", "data-slot": "panel-header-actions", children: [
91
+ actions,
92
+ collapseButton
93
+ ] })
94
+ ]
95
+ }
96
+ );
97
+ }
98
+ );
99
+ PanelHeader.displayName = "PanelHeader";
100
+
101
+ export { PanelHeader };
@@ -0,0 +1,11 @@
1
+ import * as React from 'react';
2
+ interface PanelResizeHandleProps {
3
+ direction: 'left' | 'right' | 'bottom';
4
+ isResizing: boolean;
5
+ handleProps: React.HTMLAttributes<HTMLDivElement> & {
6
+ 'data-resizing'?: string;
7
+ };
8
+ }
9
+ export declare function PanelResizeHandle({ direction, isResizing, handleProps }: PanelResizeHandleProps): React.JSX.Element;
10
+ export {};
11
+ //# sourceMappingURL=PanelResizeHandle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PanelResizeHandle.d.ts","sourceRoot":"","sources":["../../../../src/components/Panel/subcomponents/PanelResizeHandle.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,UAAU,sBAAsB;IAC9B,SAAS,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;IACvC,UAAU,EAAE,OAAO,CAAC;IACpB,WAAW,EAAE,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG;QAAE,eAAe,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAClF;AAED,wBAAgB,iBAAiB,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,EAAE,sBAAsB,qBAqB/F"}
@@ -0,0 +1,29 @@
1
+ "use client";
2
+ import { jsx } from 'react/jsx-runtime';
3
+ import { cn } from '@timmbr/utils';
4
+ import { panelResizeHandleVariants } from '../Panel.styles.js';
5
+
6
+ function PanelResizeHandle({ direction, isResizing, handleProps }) {
7
+ const isVertical = direction === "bottom";
8
+ return /* @__PURE__ */ jsx(
9
+ "div",
10
+ {
11
+ "data-slot": "panel-resize-handle",
12
+ className: cn(panelResizeHandleVariants({ direction, resizing: isResizing })),
13
+ ...handleProps,
14
+ children: /* @__PURE__ */ jsx(
15
+ "div",
16
+ {
17
+ "aria-hidden": "true",
18
+ className: cn(
19
+ "flex shrink-0 items-center justify-center gap-0.5 rounded-full opacity-0 group-hover:opacity-100 transition-opacity duration-150",
20
+ isVertical ? "h-1.5 w-10 flex-row" : "h-10 w-1.5 flex-col"
21
+ ),
22
+ children: [0, 1, 2].map((i) => /* @__PURE__ */ jsx("div", { className: "h-1 w-1 shrink-0 rounded-full bg-muted-foreground/50" }, i))
23
+ }
24
+ )
25
+ }
26
+ );
27
+ }
28
+
29
+ export { PanelResizeHandle };
@@ -0,0 +1,4 @@
1
+ import * as React from 'react';
2
+ import type { PanelTitleProps } from '../Panel.types';
3
+ export declare const PanelTitle: React.ForwardRefExoticComponent<PanelTitleProps & React.RefAttributes<HTMLHeadingElement>>;
4
+ //# sourceMappingURL=PanelTitle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PanelTitle.d.ts","sourceRoot":"","sources":["../../../../src/components/Panel/subcomponents/PanelTitle.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEtD,eAAO,MAAM,UAAU,4FAYtB,CAAC"}
@@ -0,0 +1,24 @@
1
+ "use client";
2
+ import { jsx } from 'react/jsx-runtime';
3
+ import * as React from 'react';
4
+ import { Slot } from '@radix-ui/react-slot';
5
+ import { cn } from '@timmbr/utils';
6
+ import { panelTitleVariants } from '../Panel.styles.js';
7
+
8
+ const PanelTitle = React.forwardRef(
9
+ ({ className, asChild = false, ...props }, ref) => {
10
+ const Comp = asChild ? Slot : "h3";
11
+ return /* @__PURE__ */ jsx(
12
+ Comp,
13
+ {
14
+ ref,
15
+ "data-slot": "panel-title",
16
+ className: cn(panelTitleVariants(), className),
17
+ ...props
18
+ }
19
+ );
20
+ }
21
+ );
22
+ PanelTitle.displayName = "PanelTitle";
23
+
24
+ export { PanelTitle };
@@ -0,0 +1,6 @@
1
+ export { PanelHeader } from './PanelHeader';
2
+ export { PanelTitle } from './PanelTitle';
3
+ export { PanelDescription } from './PanelDescription';
4
+ export { PanelBody } from './PanelBody';
5
+ export { PanelFooter } from './PanelFooter';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/Panel/subcomponents/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
package/dist/index.d.ts CHANGED
@@ -7,6 +7,7 @@ export * from './components/Center';
7
7
  export * from './components/Stack';
8
8
  export * from './components/Inline';
9
9
  export * from './components/ScrollRail';
10
+ export * from './components/Panel';
10
11
  export * from './components/Input';
11
12
  export * from './components/Textarea';
12
13
  export * from './components/Select';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,gBAAgB,CAAC;AAC/B,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG3D,cAAc,aAAa,CAAC;AAG5B,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AAGxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,kCAAkC,CAAC;AACjD,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAG5C,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AAGxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,gBAAgB,CAAC;AAC/B,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG3D,cAAc,aAAa,CAAC;AAG5B,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AAGnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,kCAAkC,CAAC;AACjD,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAG5C,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AAGxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC"}
package/dist/index.js CHANGED
@@ -27,6 +27,7 @@ export { DEFAULT_AUTH_MODAL_LABELS } from './components/AuthModal/AuthModal.labe
27
27
  export { DEFAULT_FILTER_DRAWER_LABELS, FilterDrawer } from './components/FilterDrawer/FilterDrawer.js';
28
28
  export { DEFAULT_FILTER_LABELS, FilterOptionList, FilterPanel, FilterPriceSlider, FilterToggleRow, isOptionDisabled } from './components/FilterPanel/FilterPanel.js';
29
29
  export { DEFAULT_FOOTER_LEGAL_LINKS, DEFAULT_FOOTER_SECTIONS, DEFAULT_FOOTER_SOCIAL_LINKS, isCrossZoneNavigation, resolveNavDestination } from './components/NavFooter/NavFooter.helpers.js';
30
+ export { DEFAULT_H_COLLAPSED, DEFAULT_H_MAX, DEFAULT_H_MIN, DEFAULT_H_SIZE, DEFAULT_V_COLLAPSED, DEFAULT_V_MAX, DEFAULT_V_MIN, DEFAULT_V_SIZE, animatePanelSize, resolvePanelSizes, usePanelCollapse, usePanelResize, usePanelSnapCoordination } from './components/Panel/Panel.helpers.js';
30
31
  export { DEFAULT_STORAGE_KEY, isNavItemActive, isRouteActive, readStoredCollapsed, writeStoredCollapsed } from './components/SideBarNavigation/SideBarNavigation.helpers.js';
31
32
  export { DataList, DataListAction, DataListItem, DataListLabel, DataListValue } from './components/DataList/DataList.js';
32
33
  export { DataTable } from './components/DataTable/DataTable.js';
@@ -72,6 +73,13 @@ export { PRICE_GROUP_KEY } from './components/FilterPanel/FilterPanel.types.js';
72
73
  export { PageHeader } from './components/PageHeader/PageHeader.js';
73
74
  export { PageProgress } from './components/PageProgress/PageProgress.js';
74
75
  export { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, PaginationSummary } from './components/Pagination/Pagination.js';
76
+ export { Panel } from './components/Panel/Panel.js';
77
+ export { PanelBody } from './components/Panel/subcomponents/PanelBody.js';
78
+ export { PanelContext, usePanelContext } from './components/Panel/Panel.context.js';
79
+ export { PanelDescription } from './components/Panel/subcomponents/PanelDescription.js';
80
+ export { PanelFooter } from './components/Panel/subcomponents/PanelFooter.js';
81
+ export { PanelHeader } from './components/Panel/subcomponents/PanelHeader.js';
82
+ export { PanelTitle } from './components/Panel/subcomponents/PanelTitle.js';
75
83
  export { Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverTrigger } from './components/Popover/Popover.js';
76
84
  export { Price, discountPercent } from './components/Price/Price.js';
77
85
  export { ProductGallery } from './components/ProductGallery/ProductGallery.js';
@@ -171,6 +179,7 @@ export { optionImageVariants, optionPickerLegendVariants, optionPickerVariants,
171
179
  export { otpContainerVariants, otpSlotVariants } from './components/OtpInput/OtpInput.styles.js';
172
180
  export { pageHeaderTitleVariants, pageHeaderVariants } from './components/PageHeader/PageHeader.styles.js';
173
181
  export { paginationLinkVariants } from './components/Pagination/Pagination.styles.js';
182
+ export { panelBodyVariants, panelDescriptionVariants, panelFooterVariants, panelHeaderVariants, panelResizeHandleVariants, panelSectionFooterPadding, panelSectionPadding, panelTitleVariants, panelVariants } from './components/Panel/Panel.styles.js';
174
183
  export { popoverContentVariants } from './components/Popover/Popover.styles.js';
175
184
  export { priceAmountVariants, priceCompareVariants, priceDiscountVariants, priceVariants } from './components/Price/Price.styles.js';
176
185
  export { productGalleryArrowVariants, productGalleryCounterVariants, productGalleryFrameVariants, productGalleryLensVariants, productGalleryLightboxButtonVariants, productGalleryLightboxVariants, productGallerySlideVariants, productGalleryStageVariants, productGalleryThumbListVariants, productGalleryThumbVariants, productGalleryThumbsVariants, productGalleryTrackVariants, productGalleryVariants, productGalleryZoomPaneVariants } from './components/ProductGallery/ProductGallery.styles.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@timmbr/ui",
3
- "version": "1.15.1",
3
+ "version": "1.16.0",
4
4
  "description": "High-performance, Next.js App Router-compatible UI design system components for Timmbr",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -51,11 +51,11 @@
51
51
  "@tiptap/extension-text-align": "^2.11.0",
52
52
  "@tiptap/extension-placeholder": "^2.11.0",
53
53
  "@tiptap/extension-character-count": "^2.11.0",
54
- "@timmbr/hooks": "1.2.0",
55
- "@timmbr/icons": "1.6.0",
54
+ "@timmbr/hooks": "1.3.0",
56
55
  "@timmbr/motion": "1.2.5",
57
- "@timmbr/theme": "1.3.0",
58
- "@timmbr/utils": "1.6.0"
56
+ "@timmbr/utils": "1.6.0",
57
+ "@timmbr/icons": "1.6.0",
58
+ "@timmbr/theme": "1.3.0"
59
59
  },
60
60
  "peerDependencies": {
61
61
  "next": ">=13.0.0 || >=14.0.0 || >=15.0.0 || >=16.0.0",