@wheelhouse/ui 0.2.14 → 0.3.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 (42) hide show
  1. package/dist/blocks/floating-menu-widget/floating-menu-widget.d.ts +4 -1
  2. package/dist/blocks/floating-menu-widget/floating-menu-widget.d.ts.map +1 -1
  3. package/dist/blocks/floating-menu-widget/floating-menu-widget.js +70 -22
  4. package/dist/blocks/floating-menu-widget/floating-menu-widget.stories.d.ts +1 -0
  5. package/dist/blocks/floating-menu-widget/floating-menu-widget.stories.d.ts.map +1 -1
  6. package/dist/blocks/floating-menu-widget/floating-menu-widget.stories.js +3 -0
  7. package/dist/blocks/floating-menu-widget/index.d.ts +1 -1
  8. package/dist/blocks/floating-menu-widget/index.d.ts.map +1 -1
  9. package/dist/components/avatar/avatar.js +1 -1
  10. package/dist/components/badge/badge.d.ts +3 -3
  11. package/dist/components/badge/badge.js +3 -3
  12. package/dist/components/button/button.d.ts +8 -8
  13. package/dist/components/button/button.js +15 -15
  14. package/dist/components/button-group/button-group.js +3 -3
  15. package/dist/components/combobox/combobox.js +1 -1
  16. package/dist/components/data-grid/data-grid-column-filter.js +1 -1
  17. package/dist/components/data-grid/data-grid-column-header.js +1 -1
  18. package/dist/components/data-grid/data-grid-pagination.js +4 -4
  19. package/dist/components/data-grid/data-grid-table-dnd-rows.js +2 -2
  20. package/dist/components/data-grid/data-grid-table-dnd.js +1 -1
  21. package/dist/components/dialog/dialog.js +1 -1
  22. package/dist/components/filters/filter-date-metric-value.js +1 -1
  23. package/dist/components/input/input.js +4 -4
  24. package/dist/components/input-group/input-group.d.ts +1 -1
  25. package/dist/components/input-group/input-group.js +7 -7
  26. package/dist/components/native-select/native-select.js +1 -1
  27. package/dist/components/number-field/number-field.js +4 -4
  28. package/dist/components/select/select.js +1 -1
  29. package/dist/components/sheet/sheet.js +1 -1
  30. package/dist/components/sidebar/sidebar.js +6 -6
  31. package/dist/components/text/index.d.ts +1 -1
  32. package/dist/components/text/index.d.ts.map +1 -1
  33. package/dist/components/text/text.d.ts +4 -5
  34. package/dist/components/text/text.d.ts.map +1 -1
  35. package/dist/components/text/text.js +8 -4
  36. package/dist/components/textarea/textarea.js +1 -1
  37. package/dist/components/toggle/toggle.d.ts +3 -3
  38. package/dist/components/toggle/toggle.d.ts.map +1 -1
  39. package/dist/components/toggle/toggle.js +3 -3
  40. package/dist/tsconfig.tsbuildinfo +1 -1
  41. package/package.json +1 -1
  42. package/src/styles/globals.css +5 -2
@@ -5,6 +5,7 @@ export type FloatingMenuWidgetInset = {
5
5
  right: number;
6
6
  bottom: number;
7
7
  };
8
+ export type FloatingMenuWidgetCorner = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
8
9
  export type FloatingMenuWidgetProps = Omit<React.ComponentProps<'div'>, 'children'> & {
9
10
  children: React.ReactNode;
10
11
  menuTitle: string;
@@ -18,9 +19,11 @@ export type FloatingMenuWidgetProps = Omit<React.ComponentProps<'div'>, 'childre
18
19
  positionStorageKey?: string;
19
20
  /** Long-press to drag. */
20
21
  draggable?: boolean;
22
+ /** After a drag, glide to the nearest viewport corner (resting at `defaultInset` from its edges) and stay pinned there on resize. */
23
+ snapToCorners?: boolean;
21
24
  open?: boolean;
22
25
  onOpenChange?: (open: boolean) => void;
23
26
  };
24
- declare function FloatingMenuWidget({ children, menuTitle, menuDescription, triggerIcon, renderTrigger, triggerNativeButton, defaultInset, positionStorageKey, draggable, open: openControlled, onOpenChange: onOpenChangeControlled, className, ...rest }: FloatingMenuWidgetProps): import("react/jsx-runtime").JSX.Element;
27
+ declare function FloatingMenuWidget({ children, menuTitle, menuDescription, triggerIcon, renderTrigger, triggerNativeButton, defaultInset, positionStorageKey, draggable, snapToCorners, open: openControlled, onOpenChange: onOpenChangeControlled, className, ...rest }: FloatingMenuWidgetProps): import("react/jsx-runtime").JSX.Element;
25
28
  export { FloatingMenuWidget };
26
29
  //# sourceMappingURL=floating-menu-widget.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"floating-menu-widget.d.ts","sourceRoot":"","sources":["../../../src/blocks/floating-menu-widget/floating-menu-widget.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,OAAO,EAA2C,KAAK,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAS7G,MAAM,MAAM,+BAA+B,GAAG,WAAW,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC,CAAC;AAEzF,MAAM,MAAM,uBAAuB,GAAG;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC,GAAG;IAClF,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,aAAa,CAAC,EAAE,+BAA+B,CAAC;IAChD,mEAAmE;IACnE,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,YAAY,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAChD,4DAA4D;IAC5D,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,0BAA0B;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CAC1C,CAAC;AA0BF,iBAAS,kBAAkB,CAAC,EACxB,QAAQ,EACR,SAAS,EACT,eAAe,EACf,WAAyC,EACzC,aAAa,EACb,mBAA0B,EAC1B,YAAY,EACZ,kBAAkB,EAClB,SAAgB,EAChB,IAAI,EAAE,cAAc,EACpB,YAAY,EAAE,sBAAsB,EACpC,SAAS,EACT,GAAG,IAAI,EACV,EAAE,uBAAuB,2CAwOzB;AAED,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
1
+ {"version":3,"file":"floating-menu-widget.d.ts","sourceRoot":"","sources":["../../../src/blocks/floating-menu-widget/floating-menu-widget.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,OAAO,EAA2C,KAAK,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAS7G,MAAM,MAAM,+BAA+B,GAAG,WAAW,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC,CAAC;AAEzF,MAAM,MAAM,uBAAuB,GAAG;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG,UAAU,GAAG,WAAW,GAAG,aAAa,GAAG,cAAc,CAAC;AAIjG,MAAM,MAAM,uBAAuB,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC,GAAG;IAClF,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,aAAa,CAAC,EAAE,+BAA+B,CAAC;IAChD,mEAAmE;IACnE,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,YAAY,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAChD,4DAA4D;IAC5D,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,0BAA0B;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,qIAAqI;IACrI,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CAC1C,CAAC;AA2CF,iBAAS,kBAAkB,CAAC,EACxB,QAAQ,EACR,SAAS,EACT,eAAe,EACf,WAAyC,EACzC,aAAa,EACb,mBAA0B,EAC1B,YAAY,EACZ,kBAAkB,EAClB,SAAgB,EAChB,aAAqB,EACrB,IAAI,EAAE,cAAc,EACpB,YAAY,EAAE,sBAAsB,EACpC,SAAS,EACT,GAAG,IAAI,EACV,EAAE,uBAAuB,2CAwQzB;AAED,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
@@ -10,10 +10,11 @@ import { cn } from '../../lib/utils';
10
10
  const DEFAULT_INSET = 24;
11
11
  const LONG_PRESS_MS = 160;
12
12
  const LONG_PRESS_MOVE_CANCEL_PX = 22;
13
+ const CORNERS = ['top-left', 'top-right', 'bottom-left', 'bottom-right'];
13
14
  function clamp(n, min, max) {
14
15
  return Math.min(max, Math.max(min, n));
15
16
  }
16
- function readStoredInset(key) {
17
+ function readStoredPosition(key) {
17
18
  if (typeof window === 'undefined')
18
19
  return null;
19
20
  try {
@@ -23,29 +24,48 @@ function readStoredInset(key) {
23
24
  const parsed = JSON.parse(raw);
24
25
  if (!parsed || typeof parsed !== 'object')
25
26
  return null;
26
- const { right, bottom } = parsed;
27
+ const { right, bottom, corner } = parsed;
27
28
  if (typeof right !== 'number' || typeof bottom !== 'number')
28
29
  return null;
29
- return { right, bottom };
30
+ return { right, bottom, corner: corner && CORNERS.includes(corner) ? corner : undefined };
30
31
  }
31
32
  catch {
32
33
  return null;
33
34
  }
34
35
  }
35
- function FloatingMenuWidget({ children, menuTitle, menuDescription, triggerIcon = _jsx(Menu, { className: "size-4" }), renderTrigger, triggerNativeButton = true, defaultInset, positionStorageKey, draggable = true, open: openControlled, onOpenChange: onOpenChangeControlled, className, ...rest }) {
36
+ function nearestCorner(rect) {
37
+ const vertical = rect.top + rect.height / 2 < window.innerHeight / 2 ? 'top' : 'bottom';
38
+ const horizontal = rect.left + rect.width / 2 < window.innerWidth / 2 ? 'left' : 'right';
39
+ return `${vertical}-${horizontal}`;
40
+ }
41
+ /** Resting `right`/`bottom` inset for a corner, given the widget size and the per-edge resting distance. */
42
+ function cornerInset(corner, width, height, rest) {
43
+ const margin = 8;
44
+ return {
45
+ right: corner.endsWith('right') ? rest.right : Math.max(margin, window.innerWidth - width - rest.right),
46
+ bottom: corner.startsWith('bottom') ? rest.bottom : Math.max(margin, window.innerHeight - height - rest.bottom),
47
+ };
48
+ }
49
+ function FloatingMenuWidget({ children, menuTitle, menuDescription, triggerIcon = _jsx(Menu, { className: "size-4" }), renderTrigger, triggerNativeButton = true, defaultInset, positionStorageKey, draggable = true, snapToCorners = false, open: openControlled, onOpenChange: onOpenChangeControlled, className, ...rest }) {
36
50
  const isMobile = useIsMobile();
37
51
  const anchorRef = React.useRef(null);
38
52
  const planRef = React.useRef(null);
39
53
  const longPressTimerRef = React.useRef(null);
40
54
  const storageKeyFull = positionStorageKey ? `wheelhouse:floating-menu-widget:${positionStorageKey}` : null;
55
+ const restRight = defaultInset?.right ?? DEFAULT_INSET;
56
+ const restBottom = defaultInset?.bottom ?? DEFAULT_INSET;
41
57
  const [inset, setInset] = React.useState(() => {
42
- const stored = storageKeyFull ? readStoredInset(storageKeyFull) : null;
58
+ const stored = storageKeyFull ? readStoredPosition(storageKeyFull) : null;
43
59
  if (stored)
44
- return stored;
45
- return {
46
- right: defaultInset?.right ?? DEFAULT_INSET,
47
- bottom: defaultInset?.bottom ?? DEFAULT_INSET,
48
- };
60
+ return { right: stored.right, bottom: stored.bottom };
61
+ return { right: restRight, bottom: restBottom };
62
+ });
63
+ const [corner, setCorner] = React.useState(() => {
64
+ if (!snapToCorners)
65
+ return null;
66
+ const stored = storageKeyFull ? readStoredPosition(storageKeyFull) : null;
67
+ // A stored inset without a corner predates snapping — leave it free until the next drag.
68
+ return stored ? (stored.corner ?? null) : 'bottom-right';
49
69
  });
50
70
  const insetRef = React.useRef(inset);
51
71
  React.useEffect(() => {
@@ -74,6 +94,21 @@ function FloatingMenuWidget({ children, menuTitle, menuDescription, triggerIcon
74
94
  }
75
95
  };
76
96
  }, []);
97
+ // While pinned to a corner, keep the resting inset exact across mounts and window resizes
98
+ // (top/left corners are expressed via right/bottom, so they drift without this).
99
+ React.useLayoutEffect(() => {
100
+ if (!snapToCorners || !corner)
101
+ return;
102
+ const reposition = () => {
103
+ const shell = anchorRef.current;
104
+ if (!shell)
105
+ return;
106
+ setInset(cornerInset(corner, shell.offsetWidth, shell.offsetHeight, { right: restRight, bottom: restBottom }));
107
+ };
108
+ reposition();
109
+ window.addEventListener('resize', reposition);
110
+ return () => window.removeEventListener('resize', reposition);
111
+ }, [snapToCorners, corner, restRight, restBottom]);
77
112
  React.useEffect(() => {
78
113
  if (!isDragging || typeof document === 'undefined')
79
114
  return;
@@ -101,6 +136,7 @@ function FloatingMenuWidget({ children, menuTitle, menuDescription, triggerIcon
101
136
  }
102
137
  const { right, bottom } = insetRef.current;
103
138
  planRef.current = { kind: 'drag', pointerId, startX, startY, originRight: right, originBottom: bottom };
139
+ setCorner(null);
104
140
  setIsDragging(true);
105
141
  }, []);
106
142
  const onShellPointerDown = React.useCallback((event) => {
@@ -160,18 +196,30 @@ function FloatingMenuWidget({ children, menuTitle, menuDescription, triggerIcon
160
196
  catch {
161
197
  /* released */
162
198
  }
163
- setInset((cur) => {
164
- if (storageKeyFull && typeof window !== 'undefined') {
165
- try {
166
- window.localStorage.setItem(storageKeyFull, JSON.stringify(cur));
167
- }
168
- catch {
169
- /* quota / private mode */
170
- }
199
+ const persist = (value) => {
200
+ if (!storageKeyFull || typeof window === 'undefined')
201
+ return;
202
+ try {
203
+ window.localStorage.setItem(storageKeyFull, JSON.stringify(value));
171
204
  }
172
- return cur;
173
- });
205
+ catch {
206
+ /* quota / private mode */
207
+ }
208
+ };
174
209
  const shell = anchorRef.current;
210
+ if (snapToCorners && shell) {
211
+ const target = nearestCorner(shell.getBoundingClientRect());
212
+ const targetInset = cornerInset(target, shell.offsetWidth, shell.offsetHeight, { right: restRight, bottom: restBottom });
213
+ setCorner(target);
214
+ setInset(targetInset);
215
+ persist({ ...targetInset, corner: target });
216
+ }
217
+ else {
218
+ setInset((cur) => {
219
+ persist(cur);
220
+ return cur;
221
+ });
222
+ }
175
223
  if (shell) {
176
224
  shell.style.pointerEvents = 'none';
177
225
  requestAnimationFrame(() => {
@@ -183,8 +231,8 @@ function FloatingMenuWidget({ children, menuTitle, menuDescription, triggerIcon
183
231
  return;
184
232
  }
185
233
  planRef.current = null;
186
- }, [clearLongPressTimer, storageKeyFull]);
187
- const shellClass = cn('fixed z-50 flex touch-none items-center justify-center overflow-hidden rounded-full bg-background shadow-lg ring-1 ring-foreground/5', isDragging && 'cursor-grabbing', className);
234
+ }, [clearLongPressTimer, storageKeyFull, snapToCorners, restRight, restBottom]);
235
+ const shellClass = cn('fixed z-50 flex touch-none items-center justify-center overflow-hidden rounded-full bg-background shadow-lg ring-1 ring-foreground/5', snapToCorners && !isDragging && 'transition-[right,bottom] duration-300 ease-out', isDragging && 'cursor-grabbing', className);
188
236
  const shellPointer = draggable
189
237
  ? {
190
238
  onPointerDown: onShellPointerDown,
@@ -11,5 +11,6 @@ declare const meta: {
11
11
  export default meta;
12
12
  type Story = StoryObj<typeof FloatingMenuWidget>;
13
13
  export declare const Default: Story;
14
+ export declare const SnapToCorners: Story;
14
15
  export declare const NotDraggable: Story;
15
16
  //# sourceMappingURL=floating-menu-widget.stories.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"floating-menu-widget.stories.d.ts","sourceRoot":"","sources":["../../../src/blocks/floating-menu-widget/floating-menu-widget.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAKvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAE5D,QAAA,MAAM,IAAI;;;;;;;CAOiC,CAAC;AAE5C,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAqBjD,eAAO,MAAM,OAAO,EAAE,KAYrB,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAQ1B,CAAC"}
1
+ {"version":3,"file":"floating-menu-widget.stories.d.ts","sourceRoot":"","sources":["../../../src/blocks/floating-menu-widget/floating-menu-widget.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAKvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAE5D,QAAA,MAAM,IAAI;;;;;;;CAOiC,CAAC;AAE5C,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAqBjD,eAAO,MAAM,OAAO,EAAE,KAYrB,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,KAY3B,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAQ1B,CAAC"}
@@ -17,6 +17,9 @@ function DemoLinks() {
17
17
  export const Default = {
18
18
  render: () => (_jsxs("div", { className: "relative min-h-[100dvh] bg-muted/30 p-8", children: [_jsx("p", { className: "max-w-md text-sm text-muted-foreground", children: "Click the circular control to open a popover on wide viewports (bottom sheet on narrow ones). Press and hold the control to drag it. Resize the preview to compare." }), _jsx(FloatingMenuWidget, { menuTitle: "Quick actions", menuDescription: "Shortcuts for this preview", positionStorageKey: "storybook-demo", children: _jsx(DemoLinks, {}) })] })),
19
19
  };
20
+ export const SnapToCorners = {
21
+ render: () => (_jsxs("div", { className: "relative min-h-[100dvh] bg-muted/30 p-8", children: [_jsx("p", { className: "max-w-md text-sm text-muted-foreground", children: "Press and hold the control, drag it anywhere, and release \u2014 it glides to the nearest viewport corner and stays pinned there when the window resizes." }), _jsx(FloatingMenuWidget, { menuTitle: "Quick actions", snapToCorners: true, positionStorageKey: "storybook-snap-demo", children: _jsx(DemoLinks, {}) })] })),
22
+ };
20
23
  export const NotDraggable = {
21
24
  render: () => (_jsx("div", { className: "relative min-h-[100dvh] bg-muted/30 p-8", children: _jsx(FloatingMenuWidget, { menuTitle: "Menu", draggable: false, defaultInset: { right: 32, bottom: 32 }, children: _jsx(DemoLinks, {}) }) })),
22
25
  };
@@ -1,3 +1,3 @@
1
1
  export { FloatingMenuWidget } from './floating-menu-widget';
2
- export type { FloatingMenuWidgetInset, FloatingMenuWidgetProps, FloatingMenuWidgetRenderTrigger } from './floating-menu-widget';
2
+ export type { FloatingMenuWidgetCorner, FloatingMenuWidgetInset, FloatingMenuWidgetProps, FloatingMenuWidgetRenderTrigger } from './floating-menu-widget';
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/blocks/floating-menu-widget/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,YAAY,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,+BAA+B,EAAE,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/blocks/floating-menu-widget/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,YAAY,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,+BAA+B,EAAE,MAAM,wBAAwB,CAAC"}
@@ -11,7 +11,7 @@ function AvatarImage({ className, ...props }) {
11
11
  return _jsx(AvatarPrimitive.Image, { "data-slot": "avatar-image", className: cn('aspect-square size-full rounded-full object-cover', className), ...props });
12
12
  }
13
13
  function AvatarFallback({ className, ...props }) {
14
- return (_jsx(AvatarPrimitive.Fallback, { "data-slot": "avatar-fallback", className: cn('flex size-full items-center justify-center rounded-full bg-muted text-xs font-medium text-muted-foreground group-data-[size=sm]/avatar:text-xxs', className), ...props }));
14
+ return (_jsx(AvatarPrimitive.Fallback, { "data-slot": "avatar-fallback", className: cn('group-data-[size=sm]/avatar:text-xxs flex size-full items-center justify-center rounded-full bg-muted text-xs font-medium text-muted-foreground', className), ...props }));
15
15
  }
16
16
  function AvatarBadge({ className, ...props }) {
17
17
  return (_jsx("span", { "data-slot": "avatar-badge", className: cn('absolute right-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full bg-primary text-primary-foreground bg-blend-color ring-2 ring-background select-none', 'group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden', 'group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2', 'group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2', className), ...props }));
@@ -19,9 +19,9 @@ declare const badgeVariantStyles: {
19
19
  readonly 'destructive-outline': "border-border bg-background text-destructive-foreground dark:bg-input/30";
20
20
  };
21
21
  declare const badgeSizeStyles: {
22
- readonly default: "h-5.5 min-w-5.5 px-[calc(--spacing(1)-0px)] text-sm sm:h-4.5 sm:min-w-4.5 sm:text-xs";
23
- readonly lg: "h-6.5 min-w-6.5 px-[calc(--spacing(1.5)-1px)] text-base sm:h-5.5 sm:min-w-5.5 sm:text-sm";
24
- readonly sm: "h-5 min-w-5 rounded-[.25rem] px-[calc(--spacing(1)-1px)] text-xs sm:h-4 sm:min-w-4 sm:text-[.625rem]";
22
+ readonly default: "h-5 min-w-5 rounded-[.25rem] px-[calc(--spacing(1)-1px)] text-xs sm:h-4 sm:min-w-4 sm:text-[.625rem]";
23
+ readonly lg: "h-5.5 min-w-5.5 px-[calc(--spacing(1)-0px)] text-sm sm:h-4.5 sm:min-w-4.5 sm:text-xs";
24
+ readonly sm: "h-4.5 min-w-4.5 rounded-[.25rem] px-[calc(--spacing(1)-1px)] text-xs sm:h-3.5 sm:min-w-3.5 sm:text-[.625rem]";
25
25
  };
26
26
  export declare const badgeVariantKeys: (keyof typeof badgeVariantStyles)[];
27
27
  export declare const badgeSizeKeys: (keyof typeof badgeSizeStyles)[];
@@ -21,9 +21,9 @@ const badgeVariantStyles = {
21
21
  'destructive-outline': 'border-border bg-background text-destructive-foreground dark:bg-input/30',
22
22
  };
23
23
  const badgeSizeStyles = {
24
- default: 'h-5.5 min-w-5.5 px-[calc(--spacing(1)-0px)] text-sm sm:h-4.5 sm:min-w-4.5 sm:text-xs',
25
- lg: 'h-6.5 min-w-6.5 px-[calc(--spacing(1.5)-1px)] text-base sm:h-5.5 sm:min-w-5.5 sm:text-sm',
26
- sm: 'h-5 min-w-5 rounded-[.25rem] px-[calc(--spacing(1)-1px)] text-xs sm:h-4 sm:min-w-4 sm:text-[.625rem]',
24
+ default: 'h-5 min-w-5 rounded-[.25rem] px-[calc(--spacing(1)-1px)] text-xs sm:h-4 sm:min-w-4 sm:text-[.625rem]',
25
+ lg: 'h-5.5 min-w-5.5 px-[calc(--spacing(1)-0px)] text-sm sm:h-4.5 sm:min-w-4.5 sm:text-xs',
26
+ sm: 'h-4.5 min-w-4.5 rounded-[.25rem] px-[calc(--spacing(1)-1px)] text-xs sm:h-3.5 sm:min-w-3.5 sm:text-[.625rem]',
27
27
  };
28
28
  export const badgeVariantKeys = Object.keys(badgeVariantStyles);
29
29
  export const badgeSizeKeys = Object.keys(badgeSizeStyles);
@@ -10,14 +10,14 @@ declare const buttonVariantStyles: {
10
10
  readonly link: "text-primary underline-offset-4 hover:underline [&_[data-slot=button-loading-indicator]]:text-primary";
11
11
  };
12
12
  declare const buttonSizeStyles: {
13
- readonly default: "h-8 gap-2 px-[calc(--spacing(3)-1px)] text-sm has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3";
14
- readonly xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3";
15
- readonly sm: "h-7 gap-1.5 rounded-[min(var(--radius-md),12px)] px-[calc(--spacing(2.5)-1px)] text-sm in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3.5";
16
- readonly lg: "h-9 gap-1.5 px-[calc(--spacing(3.5)-1px)] text-base has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3 [&_svg:not([class*='size-'])]:size-3.5";
17
- readonly icon: "size-8 text-sm";
18
- readonly 'icon-xs': "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3";
19
- readonly 'icon-sm': "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg";
20
- readonly 'icon-lg': "size-9";
13
+ readonly default: "h-7 gap-1.5 rounded-[min(var(--radius-md),12px)] px-[calc(--spacing(2.5)-1px)] text-sm in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3.5";
14
+ readonly xs: "h-5 gap-1 rounded-[min(var(--radius-md),8px)] px-1.5 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1 has-data-[icon=inline-start]:pl-1 [&_svg:not([class*='size-'])]:size-2.5";
15
+ readonly sm: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3";
16
+ readonly lg: "h-8 gap-2 px-[calc(--spacing(3)-1px)] text-sm has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3";
17
+ readonly icon: "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg";
18
+ readonly 'icon-xs': "size-5 rounded-[min(var(--radius-md),8px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-2.5";
19
+ readonly 'icon-sm': "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3";
20
+ readonly 'icon-lg': "size-8 text-sm";
21
21
  };
22
22
  export declare const buttonVariantKeys: (keyof typeof buttonVariantStyles)[];
23
23
  export declare const buttonSizeKeys: (keyof typeof buttonSizeStyles)[];
@@ -13,14 +13,14 @@ const buttonVariantStyles = {
13
13
  link: 'text-primary underline-offset-4 hover:underline [&_[data-slot=button-loading-indicator]]:text-primary',
14
14
  };
15
15
  const buttonSizeStyles = {
16
- default: "h-8 gap-2 px-[calc(--spacing(3)-1px)] text-sm has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3",
17
- xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
18
- sm: "h-7 gap-1.5 rounded-[min(var(--radius-md),12px)] px-[calc(--spacing(2.5)-1px)] text-sm in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3.5",
19
- lg: "h-9 gap-1.5 px-[calc(--spacing(3.5)-1px)] text-base has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3 [&_svg:not([class*='size-'])]:size-3.5",
20
- icon: 'size-8 text-sm',
21
- 'icon-xs': "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
22
- 'icon-sm': 'size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg',
23
- 'icon-lg': 'size-9',
16
+ default: "h-7 gap-1.5 rounded-[min(var(--radius-md),12px)] px-[calc(--spacing(2.5)-1px)] text-sm in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3.5",
17
+ xs: "h-5 gap-1 rounded-[min(var(--radius-md),8px)] px-1.5 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1 has-data-[icon=inline-start]:pl-1 [&_svg:not([class*='size-'])]:size-2.5",
18
+ sm: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
19
+ lg: "h-8 gap-2 px-[calc(--spacing(3)-1px)] text-sm has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3",
20
+ icon: 'size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg',
21
+ 'icon-xs': "size-5 rounded-[min(var(--radius-md),8px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-2.5",
22
+ 'icon-sm': "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
23
+ 'icon-lg': 'size-8 text-sm',
24
24
  };
25
25
  export const buttonVariantKeys = Object.keys(buttonVariantStyles);
26
26
  export const buttonSizeKeys = Object.keys(buttonSizeStyles);
@@ -35,13 +35,13 @@ const buttonVariants = cva("group/button relative inline-flex shrink-0 cursor-po
35
35
  },
36
36
  });
37
37
  const spinnerSizeByButtonSize = {
38
- default: 'size-3',
39
- xs: 'size-3',
40
- sm: 'size-3.5',
41
- lg: 'size-3.5',
42
- icon: 'size-4',
43
- 'icon-xs': 'size-3',
44
- 'icon-sm': 'size-3.5',
38
+ default: 'size-3.5',
39
+ xs: 'size-2.5',
40
+ sm: 'size-3',
41
+ lg: 'size-3',
42
+ icon: 'size-3.5',
43
+ 'icon-xs': 'size-2.5',
44
+ 'icon-sm': 'size-3',
45
45
  'icon-lg': 'size-4',
46
46
  };
47
47
  function Button({ className, variant = 'default', size = 'default', loading = false, disabled, children, ...props }) {
@@ -7,9 +7,9 @@ import { Separator } from '../separator';
7
7
  const buttonGroupTextVariants = cva('flex shrink-0 items-center gap-2 rounded-lg border bg-muted font-medium [&_svg]:pointer-events-none', {
8
8
  variants: {
9
9
  size: {
10
- sm: "h-7 px-2 text-sm leading-none [&_svg:not([class*='size-'])]:size-3.5",
11
- default: "min-h-8 px-2.5 text-base [&_svg:not([class*='size-'])]:size-4",
12
- lg: "h-9 px-3 text-base [&_svg:not([class*='size-'])]:size-4",
10
+ sm: "h-6 px-1.5 text-xs leading-none [&_svg:not([class*='size-'])]:size-3",
11
+ default: "min-h-7 px-2 text-sm leading-none [&_svg:not([class*='size-'])]:size-3.5",
12
+ lg: "min-h-8 px-2.5 text-base [&_svg:not([class*='size-'])]:size-4",
13
13
  },
14
14
  },
15
15
  defaultVariants: {
@@ -52,7 +52,7 @@ function ComboboxChips({ className, ...props }) {
52
52
  return (_jsx(ComboboxPrimitive.Chips, { "data-slot": "combobox-chips", className: cn('flex min-h-8 flex-wrap items-center gap-1 rounded-lg border border-input bg-transparent bg-clip-padding px-2.5 py-1 text-sm transition-colors focus-within:border-ring focus-within:ring-3 focus-within:ring-ring/50 has-aria-invalid:border-destructive has-aria-invalid:ring-3 has-aria-invalid:ring-destructive/20 has-data-[slot=combobox-chip]:px-1 dark:bg-input/30 dark:has-aria-invalid:border-destructive/50 dark:has-aria-invalid:ring-destructive/40', className), ...props }));
53
53
  }
54
54
  function ComboboxChip({ className, children, showRemove = true, ...props }) {
55
- return (_jsxs(ComboboxPrimitive.Chip, { "data-slot": "combobox-chip", className: cn('flex h-[calc(--spacing(5.25))] w-fit items-center justify-center gap-1 rounded-sm bg-muted px-1.5 text-xs font-medium whitespace-nowrap text-foreground has-disabled:pointer-events-none has-disabled:cursor-not-allowed has-disabled:opacity-50 has-data-[slot=combobox-chip-remove]:pr-0', className), ...props, children: [children, showRemove && (_jsx(ComboboxPrimitive.ChipRemove, { render: _jsx(Button, { variant: "ghost", size: "icon-xs" }), className: "-ml-1 opacity-50 hover:opacity-100", "data-slot": "combobox-chip-remove", children: _jsx(X, { className: "pointer-events-none" }) }))] }));
55
+ return (_jsxs(ComboboxPrimitive.Chip, { "data-slot": "combobox-chip", className: cn('flex h-[calc(--spacing(5.25))] w-fit items-center justify-center gap-1 rounded-sm bg-muted px-1.5 text-xs font-medium whitespace-nowrap text-foreground has-disabled:pointer-events-none has-disabled:cursor-not-allowed has-disabled:opacity-50 has-data-[slot=combobox-chip-remove]:pr-0', className), ...props, children: [children, showRemove && (_jsx(ComboboxPrimitive.ChipRemove, { render: _jsx(Button, { variant: "ghost", size: "icon-sm" }), className: "-ml-1 opacity-50 hover:opacity-100", "data-slot": "combobox-chip-remove", children: _jsx(X, { className: "pointer-events-none" }) }))] }));
56
56
  }
57
57
  function ComboboxChipsInput({ className, ...props }) {
58
58
  return _jsx(ComboboxPrimitive.Input, { "data-slot": "combobox-chip-input", className: cn('min-w-16 flex-1 outline-none', className), ...props });
@@ -17,7 +17,7 @@ function DataGridColumnFilter({ column, title, options }) {
17
17
  return options;
18
18
  return options.filter((option) => option.label.toLowerCase().includes(searchQuery.toLowerCase()));
19
19
  }, [options, searchQuery]);
20
- return (_jsxs(Popover, { children: [_jsx(PopoverTrigger, { render: _jsxs(Button, { variant: "outline", size: "sm", children: [_jsx(CirclePlusIcon, { className: "size-4" }), title, selectedValues?.size > 0 && (_jsxs(_Fragment, { children: [_jsx(Separator, { orientation: "vertical", className: "mx-2 h-4" }), _jsx(Badge, { variant: "secondary", className: "rounded-sm px-1 font-normal lg:hidden", children: selectedValues.size }), _jsx("div", { className: "hidden space-x-1 lg:flex", children: selectedValues.size > 2 ? (_jsxs(Badge, { variant: "secondary", className: "rounded-sm px-1 font-normal", children: [selectedValues.size, " selected"] })) : (options
20
+ return (_jsxs(Popover, { children: [_jsx(PopoverTrigger, { render: _jsxs(Button, { variant: "outline", children: [_jsx(CirclePlusIcon, { className: "size-4" }), title, selectedValues?.size > 0 && (_jsxs(_Fragment, { children: [_jsx(Separator, { orientation: "vertical", className: "mx-2 h-4" }), _jsx(Badge, { variant: "secondary", className: "rounded-sm px-1 font-normal lg:hidden", children: selectedValues.size }), _jsx("div", { className: "hidden space-x-1 lg:flex", children: selectedValues.size > 2 ? (_jsxs(Badge, { variant: "secondary", className: "rounded-sm px-1 font-normal", children: [selectedValues.size, " selected"] })) : (options
21
21
  .filter((option) => selectedValues.has(option.value))
22
22
  .map((option) => (_jsx(Badge, { variant: "secondary", className: "rounded-sm px-1 font-normal", children: option.label }, option.value)))) })] }))] }) }), _jsxs(PopoverContent, { className: "w-[200px] p-0", align: "start", children: [_jsx("div", { className: "p-2", children: _jsx(Input, { placeholder: title, value: searchQuery, onChange: (e) => setSearchQuery(e.target.value) }) }), _jsxs("div", { className: "max-h-[300px] overflow-y-auto", children: [filteredOptions.length === 0 ? (_jsx("div", { className: "py-6 text-center text-sm text-muted-foreground", children: "No results found." })) : (_jsx("div", { className: "p-1", children: filteredOptions.map((option) => {
23
23
  const isSelected = selectedValues.has(option.value);
@@ -126,7 +126,7 @@ function DataGridColumnHeaderInner({ column, title, icon, className, filter, vis
126
126
  columnVisibilityKey, // Needed to update checkbox states when visibility changes
127
127
  ]);
128
128
  if (hasControls) {
129
- return (_jsxs("div", { className: "flex h-full items-center justify-between gap-1.5", children: [_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { render: _jsxs(Button, { variant: "ghost", className: headerButtonClassName, disabled: isLoading || recordCount === 0, children: [icon && icon, resolvedTitle, sortIcon] }) }), _jsx(DropdownMenuContent, { className: "w-40", align: "start", children: menuItems })] }), props.tableLayout?.columnsPinnable && canPin && isPinned && (_jsx(Button, { size: "icon-sm", variant: "ghost", className: "-me-1 size-7 rounded-md", onClick: () => column.pin(false), "aria-label": `Unpin ${resolvedTitle} column`, title: `Unpin ${resolvedTitle} column`, children: _jsx(PinOffIcon, { className: "size-3.5! opacity-50!", "aria-hidden": "true" }) }))] }));
129
+ return (_jsxs("div", { className: "flex h-full items-center justify-between gap-1.5", children: [_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { render: _jsxs(Button, { variant: "ghost", className: headerButtonClassName, disabled: isLoading || recordCount === 0, children: [icon && icon, resolvedTitle, sortIcon] }) }), _jsx(DropdownMenuContent, { className: "w-40", align: "start", children: menuItems })] }), props.tableLayout?.columnsPinnable && canPin && isPinned && (_jsx(Button, { size: "icon", variant: "ghost", className: "-me-1 size-7 rounded-md", onClick: () => column.pin(false), "aria-label": `Unpin ${resolvedTitle} column`, title: `Unpin ${resolvedTitle} column`, children: _jsx(PinOffIcon, { className: "size-3.5! opacity-50!", "aria-hidden": "true" }) }))] }));
130
130
  }
131
131
  if (canSort || (props.tableLayout?.columnsResizable && canResize)) {
132
132
  return (_jsx("div", { className: "flex h-full items-center", children: _jsxs(Button, { variant: "ghost", className: headerButtonClassName, disabled: isLoading || recordCount === 0, onClick: handleSort, children: [icon && icon, resolvedTitle, sortIcon] }) }));
@@ -44,7 +44,7 @@ function DataGridPagination(props) {
44
44
  const renderPageButtons = () => {
45
45
  const buttons = [];
46
46
  for (let i = currentGroupStart; i < currentGroupEnd; i++) {
47
- buttons.push(_jsx(Button, { size: "icon-sm", variant: "ghost", className: cn(btnBaseClasses, 'text-muted-foreground', {
47
+ buttons.push(_jsx(Button, { size: "icon", variant: "ghost", className: cn(btnBaseClasses, 'text-muted-foreground', {
48
48
  'bg-accent text-accent-foreground': pageIndex === i,
49
49
  }), onClick: () => {
50
50
  if (pageIndex !== i) {
@@ -57,20 +57,20 @@ function DataGridPagination(props) {
57
57
  // Render a "previous" ellipsis button if there are previous pages to show
58
58
  const renderEllipsisPrevButton = () => {
59
59
  if (currentGroupStart > 0) {
60
- return (_jsx(Button, { size: "icon-sm", className: btnBaseClasses, variant: "ghost", onClick: () => table.setPageIndex(currentGroupStart - 1), children: mergedProps.ellipsisText }));
60
+ return (_jsx(Button, { size: "icon", className: btnBaseClasses, variant: "ghost", onClick: () => table.setPageIndex(currentGroupStart - 1), children: mergedProps.ellipsisText }));
61
61
  }
62
62
  return null;
63
63
  };
64
64
  // Render a "next" ellipsis button if there are more pages to show after the current group
65
65
  const renderEllipsisNextButton = () => {
66
66
  if (currentGroupEnd < pageCount) {
67
- return (_jsx(Button, { className: btnBaseClasses, variant: "ghost", size: "icon-sm", onClick: () => table.setPageIndex(currentGroupEnd), children: mergedProps.ellipsisText }));
67
+ return (_jsx(Button, { className: btnBaseClasses, variant: "ghost", size: "icon", onClick: () => table.setPageIndex(currentGroupEnd), children: mergedProps.ellipsisText }));
68
68
  }
69
69
  return null;
70
70
  };
71
71
  return (_jsxs("div", { "data-slot": "data-grid-pagination", className: cn('flex grow flex-col flex-wrap items-center justify-between gap-2.5 py-2.5 sm:flex-row sm:py-0', mergedProps?.className), children: [_jsx("div", { className: "order-2 flex flex-wrap items-center space-x-2.5 pb-2.5 sm:order-1 sm:pb-0", children: isLoading ? (mergedProps?.sizesSkeleton) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-sm text-muted-foreground", children: mergedProps.rowsPerPageLabel }), _jsxs(Select, { value: `${pageSize}`, onValueChange: (value) => {
72
72
  const newPageSize = Number(value);
73
73
  table.setPageSize(newPageSize);
74
- }, children: [_jsx(SelectTrigger, { className: "w-14", size: "sm", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { side: "top", className: "min-w-18", children: mergedProps?.sizes?.map((size) => (_jsx(SelectItem, { value: `${size}`, children: size }, size))) })] })] })) }), _jsx("div", { className: "order-1 flex flex-col items-center justify-center gap-2.5 pt-2.5 sm:order-2 sm:flex-row sm:justify-end sm:pt-0", children: isLoading ? (mergedProps?.infoSkeleton) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "order-2 text-sm text-nowrap text-muted-foreground sm:order-1", children: paginationInfo }), pageCount > 1 && (_jsxs("div", { className: "order-1 flex items-center space-x-1 sm:order-2", children: [_jsxs(Button, { size: "icon-sm", variant: "ghost", className: btnArrowClasses, onClick: () => table.previousPage(), disabled: !table.getCanPreviousPage(), children: [_jsx("span", { className: "sr-only", children: mergedProps.previousPageLabel }), _jsx(ChevronLeftIcon, { className: "size-4" })] }), renderEllipsisPrevButton(), renderPageButtons(), renderEllipsisNextButton(), _jsxs(Button, { size: "icon-sm", variant: "ghost", className: btnArrowClasses, onClick: () => table.nextPage(), disabled: !table.getCanNextPage(), children: [_jsx("span", { className: "sr-only", children: mergedProps.nextPageLabel }), _jsx(ChevronRightIcon, { className: "size-4" })] })] }))] })) })] }));
74
+ }, children: [_jsx(SelectTrigger, { className: "w-14", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { side: "top", className: "min-w-18", children: mergedProps?.sizes?.map((size) => (_jsx(SelectItem, { value: `${size}`, children: size }, size))) })] })] })) }), _jsx("div", { className: "order-1 flex flex-col items-center justify-center gap-2.5 pt-2.5 sm:order-2 sm:flex-row sm:justify-end sm:pt-0", children: isLoading ? (mergedProps?.infoSkeleton) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "order-2 text-sm text-nowrap text-muted-foreground sm:order-1", children: paginationInfo }), pageCount > 1 && (_jsxs("div", { className: "order-1 flex items-center space-x-1 sm:order-2", children: [_jsxs(Button, { size: "icon", variant: "ghost", className: btnArrowClasses, onClick: () => table.previousPage(), disabled: !table.getCanPreviousPage(), children: [_jsx("span", { className: "sr-only", children: mergedProps.previousPageLabel }), _jsx(ChevronLeftIcon, { className: "size-4" })] }), renderEllipsisPrevButton(), renderPageButtons(), renderEllipsisNextButton(), _jsxs(Button, { size: "icon", variant: "ghost", className: btnArrowClasses, onClick: () => table.nextPage(), disabled: !table.getCanNextPage(), children: [_jsx("span", { className: "sr-only", children: mergedProps.nextPageLabel }), _jsx(ChevronRightIcon, { className: "size-4" })] })] }))] })) })] }));
75
75
  }
76
76
  export { DataGridPagination };
@@ -16,9 +16,9 @@ function DataGridTableDndRowHandle({ className }) {
16
16
  const context = useContext(SortableRowContext);
17
17
  if (!context) {
18
18
  // Fallback if context is not available (shouldn't happen in normal usage)
19
- return (_jsx(Button, { variant: "ghost", size: "icon-sm", className: cn('size-7 cursor-grab opacity-70 hover:bg-transparent hover:opacity-100 active:cursor-grabbing', className), disabled: true, children: _jsx(GripHorizontalIcon, {}) }));
19
+ return (_jsx(Button, { variant: "ghost", size: "icon", className: cn('size-7 cursor-grab opacity-70 hover:bg-transparent hover:opacity-100 active:cursor-grabbing', className), disabled: true, children: _jsx(GripHorizontalIcon, {}) }));
20
20
  }
21
- return (_jsx(Button, { variant: "ghost", size: "icon-sm", className: cn('size-7 cursor-grab opacity-70 hover:bg-transparent hover:opacity-100 active:cursor-grabbing', className), ...context.attributes, ...context.listeners, children: _jsx(GripHorizontalIcon, {}) }));
21
+ return (_jsx(Button, { variant: "ghost", size: "icon", className: cn('size-7 cursor-grab opacity-70 hover:bg-transparent hover:opacity-100 active:cursor-grabbing', className), ...context.attributes, ...context.listeners, children: _jsx(GripHorizontalIcon, {}) }));
22
22
  }
23
23
  function DataGridTableDndRow({ row }) {
24
24
  const { transform, transition, setNodeRef, isDragging, attributes, listeners } = useSortable({
@@ -27,7 +27,7 @@ function DataGridTableDndHeader({ header }) {
27
27
  width: props.tableLayout?.columnsResizable ? `calc(var(--header-${header.id}-size) * 1px)` : header.column.getSize(),
28
28
  zIndex: isDragging ? 1 : 0,
29
29
  };
30
- return (_jsx(DataGridTableHeadRowCell, { header: header, dndStyle: style, dndRef: setNodeRef, children: _jsxs("div", { className: "flex items-center justify-start gap-0.5", children: [canOrder && (_jsx(Button, { size: "icon-sm", variant: "ghost", className: `-ms-2 size-6 ${isDragging ? 'cursor-grabbing' : 'cursor-grab active:cursor-grabbing'}`, ...attributes, ...listeners, "aria-label": "Drag to reorder", children: _jsx(GripVerticalIcon, { className: "opacity-60 hover:opacity-100", "aria-hidden": "true" }) })), _jsx("span", { className: "grow truncate", children: header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext()) }), props.tableLayout?.columnsResizable && column.getCanResize() && _jsx(DataGridTableHeadRowCellResize, { header: header })] }) }));
30
+ return (_jsx(DataGridTableHeadRowCell, { header: header, dndStyle: style, dndRef: setNodeRef, children: _jsxs("div", { className: "flex items-center justify-start gap-0.5", children: [canOrder && (_jsx(Button, { size: "icon", variant: "ghost", className: `-ms-2 size-6 ${isDragging ? 'cursor-grabbing' : 'cursor-grab active:cursor-grabbing'}`, ...attributes, ...listeners, "aria-label": "Drag to reorder", children: _jsx(GripVerticalIcon, { className: "opacity-60 hover:opacity-100", "aria-hidden": "true" }) })), _jsx("span", { className: "grow truncate", children: header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext()) }), props.tableLayout?.columnsResizable && column.getCanResize() && _jsx(DataGridTableHeadRowCellResize, { header: header })] }) }));
31
31
  }
32
32
  function DataGridTableDndCell({ cell }) {
33
33
  const { props } = useDataGrid();
@@ -21,7 +21,7 @@ function DialogOverlay({ className, ...props }) {
21
21
  return (_jsx(DialogPrimitive.Backdrop, { "data-slot": "dialog-overlay", className: cn('fixed inset-0 isolate z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0', className), ...props }));
22
22
  }
23
23
  function DialogContent({ className, children, showCloseButton = true, ...props }) {
24
- return (_jsxs(DialogPortal, { children: [_jsx(DialogOverlay, {}), _jsxs(DialogPrimitive.Popup, { "data-slot": "dialog-content", className: cn('fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-sm text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95', className), ...props, children: [children, showCloseButton && (_jsxs(DialogPrimitive.Close, { "data-slot": "dialog-close", render: _jsx(Button, { variant: "ghost", className: "absolute top-2 right-2", size: "icon-sm" }), children: [_jsx(X, {}), _jsx("span", { className: "sr-only", children: "Close" })] }))] })] }));
24
+ return (_jsxs(DialogPortal, { children: [_jsx(DialogOverlay, {}), _jsxs(DialogPrimitive.Popup, { "data-slot": "dialog-content", className: cn('fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-sm text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95', className), ...props, children: [children, showCloseButton && (_jsxs(DialogPrimitive.Close, { "data-slot": "dialog-close", render: _jsx(Button, { variant: "ghost", className: "absolute top-2 right-2", size: "icon" }), children: [_jsx(X, {}), _jsx("span", { className: "sr-only", children: "Close" })] }))] })] }));
25
25
  }
26
26
  function DialogHeader({ className, ...props }) {
27
27
  return _jsx("div", { "data-slot": "dialog-header", className: cn('flex flex-col gap-2', className), ...props });
@@ -176,7 +176,7 @@ export function FilterDateMetricBarPeriodSegments({ field, values, onChange, i18
176
176
  if (!open) {
177
177
  setCustomDraft(null);
178
178
  }
179
- }, children: _jsxs(DialogContent, { className: "max-h-[min(90vh,32rem)] w-[min(calc(100vw-2rem),28rem)] gap-0 overflow-y-auto p-4 sm:max-w-none", children: [_jsx(DialogHeader, { className: "pb-2", children: _jsx(DialogTitle, { children: mergedDateI18n.selectDate }) }), _jsx("div", { className: "flex flex-col gap-6 py-2", children: _jsx("section", { className: "flex flex-col gap-2", children: _jsx(DateSelector, { ...field.dateMetricProps, className: cn('max-w-none space-y-3', field.dateMetricProps?.className), value: customDraft ?? dateMetricValueForCustomEditor(payload.date), onChange: setCustomDraft, showOperators: field.dateMetricProps?.showOperators !== false, showInput: field.dateMetricProps?.showInput ?? false, dayDateFormat: dayFormat, showRollingPresets: false }) }) }), _jsx(DialogFooter, { className: "mt-2 border-t pt-4 sm:justify-end", children: _jsx(Button, { type: "button", size: "sm", variant: "default", onClick: commitCustomDialog, children: i18n.dateMetricDialogDone }) })] }) })] }));
179
+ }, children: _jsxs(DialogContent, { className: "max-h-[min(90vh,32rem)] w-[min(calc(100vw-2rem),28rem)] gap-0 overflow-y-auto p-4 sm:max-w-none", children: [_jsx(DialogHeader, { className: "pb-2", children: _jsx(DialogTitle, { children: mergedDateI18n.selectDate }) }), _jsx("div", { className: "flex flex-col gap-6 py-2", children: _jsx("section", { className: "flex flex-col gap-2", children: _jsx(DateSelector, { ...field.dateMetricProps, className: cn('max-w-none space-y-3', field.dateMetricProps?.className), value: customDraft ?? dateMetricValueForCustomEditor(payload.date), onChange: setCustomDraft, showOperators: field.dateMetricProps?.showOperators !== false, showInput: field.dateMetricProps?.showInput ?? false, dayDateFormat: dayFormat, showRollingPresets: false }) }) }), _jsx(DialogFooter, { className: "mt-2 border-t pt-4 sm:justify-end", children: _jsx(Button, { type: "button", variant: "default", onClick: commitCustomDialog, children: i18n.dateMetricDialogDone }) })] }) })] }));
180
180
  }
181
181
  /** Typographic en dash (–) for “no amount” on the bar trigger. */
182
182
  const METRIC_EMPTY_AMOUNT = '\u2013';
@@ -4,12 +4,12 @@ import * as React from 'react';
4
4
  import { Input as InputPrimitive } from '@base-ui/react/input';
5
5
  import { cva } from 'class-variance-authority';
6
6
  import { cn } from '../../lib/utils';
7
- const inputVariants = cva('flex w-full min-w-0 rounded-md border border-input bg-background shadow-xs transition-[color,box-shadow] outline-none group-has-disabled/field:opacity-50 file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-invalid:border-destructive data-invalid:ring-3 data-invalid:ring-destructive/20 dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 dark:data-invalid:border-destructive/50 dark:data-invalid:ring-destructive/40', {
7
+ const inputVariants = cva('flex w-full min-w-0 rounded-md border border-input bg-background shadow-xs transition-[color,box-shadow] outline-none group-has-disabled/field:opacity-50 file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-invalid:border-destructive data-invalid:ring-3 data-invalid:ring-destructive/20 dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 dark:data-invalid:border-destructive/50 dark:data-invalid:ring-destructive/40', {
8
8
  variants: {
9
9
  size: {
10
- sm: 'h-7 rounded-[min(var(--radius-md),12px)] px-[calc(--spacing(2.5)-1px)] text-sm',
11
- default: 'h-8 px-[calc(--spacing(3)-1px)] text-sm',
12
- lg: 'h-9 px-[calc(--spacing(3.5)-1px)] text-base',
10
+ sm: 'h-6 rounded-[min(var(--radius-md),10px)] px-[calc(--spacing(2)-1px)] text-xs',
11
+ default: 'h-7 rounded-[min(var(--radius-md),12px)] px-[calc(--spacing(2.5)-1px)] text-sm',
12
+ lg: 'h-8 px-[calc(--spacing(3)-1px)] text-sm',
13
13
  },
14
14
  },
15
15
  defaultVariants: {
@@ -31,7 +31,7 @@ export type InputGroupInputProps = InputProps;
31
31
  export type InputGroupTextareaProps = TextareaProps;
32
32
  /**
33
33
  * Wraps a control and addons in a single bordered, focus-styled shell. Set `data-disabled` on the root when the field is disabled.
34
- * `size` sets shell height (`sm` = 28px, `default` = 32px, `lg` = 36px) and is inherited by `InputGroupInput` unless overridden there.
34
+ * `size` sets shell height (`sm` = 24px, `default` = 28px, `lg` = 32px) and is inherited by `InputGroupInput` unless overridden there.
35
35
  */
36
36
  declare function InputGroup({ className, size, ...props }: InputGroupProps): import("react/jsx-runtime").JSX.Element;
37
37
  /**
@@ -11,16 +11,16 @@ const InputGroupSizeContext = React.createContext(undefined);
11
11
  const inputGroupVariants = cva('group/input-group relative flex w-full min-w-0 items-center rounded-lg border border-input transition-colors outline-none in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-disabled:bg-input/50 has-disabled:opacity-50 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-3 has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot][aria-invalid=true]]:border-destructive has-[[data-slot][aria-invalid=true]]:ring-3 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto dark:bg-input/30 dark:has-disabled:bg-input/80 dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5', {
12
12
  variants: {
13
13
  size: {
14
- sm: 'h-7 rounded-[min(var(--radius-md),12px)]',
15
- default: 'h-8',
16
- lg: 'h-9',
14
+ sm: 'h-6 rounded-[min(var(--radius-md),10px)]',
15
+ default: 'h-7 rounded-[min(var(--radius-md),12px)]',
16
+ lg: 'h-8',
17
17
  },
18
18
  },
19
19
  defaultVariants: {
20
20
  size: 'default',
21
21
  },
22
22
  });
23
- const inputGroupAddonVariants = cva("flex h-auto cursor-text items-center justify-center gap-2 py-1.5 text-sm font-medium text-muted-foreground select-none group-data-[disabled=true]/input-group:opacity-50 group-data-[size=lg]/input-group:py-2 group-data-[size=sm]/input-group:py-1 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4 group-data-[size=sm]/input-group:[&>svg:not([class*='size-'])]:size-3.5", {
23
+ const inputGroupAddonVariants = cva("flex h-auto cursor-text items-center justify-center gap-2 py-1 text-sm font-medium text-muted-foreground select-none group-data-[disabled=true]/input-group:opacity-50 group-data-[size=lg]/input-group:py-1.5 group-data-[size=sm]/input-group:py-0.5 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-3.5 group-data-[size=lg]/input-group:[&>svg:not([class*='size-'])]:size-4 group-data-[size=sm]/input-group:[&>svg:not([class*='size-'])]:size-3", {
24
24
  variants: {
25
25
  align: {
26
26
  'inline-start': 'order-first pl-2 has-[>button]:ml-[-0.3rem] has-[>kbd]:ml-[-0.15rem]',
@@ -37,10 +37,10 @@ export const inputGroupAddonAlignKeys = ['inline-start', 'inline-end', 'block-st
37
37
  const inputGroupButtonVariants = cva('flex items-center gap-2 text-sm shadow-none', {
38
38
  variants: {
39
39
  size: {
40
- xs: "h-6 gap-1 rounded-[calc(var(--radius)-3px)] px-1.5 [&>svg:not([class*='size-'])]:size-3.5",
40
+ xs: "h-5 gap-1 rounded-[calc(var(--radius)-3px)] px-1 [&>svg:not([class*='size-'])]:size-3",
41
41
  sm: '',
42
42
  'icon-xs': 'size-6 rounded-[calc(var(--radius)-3px)] p-0 has-[>svg]:p-0',
43
- 'icon-sm': 'size-8 p-0 has-[>svg]:p-0',
43
+ 'icon-sm': 'size-7 p-0 has-[>svg]:p-0',
44
44
  },
45
45
  },
46
46
  defaultVariants: {
@@ -50,7 +50,7 @@ const inputGroupButtonVariants = cva('flex items-center gap-2 text-sm shadow-non
50
50
  export const inputGroupButtonSizeKeys = ['xs', 'sm', 'icon-xs', 'icon-sm'];
51
51
  /**
52
52
  * Wraps a control and addons in a single bordered, focus-styled shell. Set `data-disabled` on the root when the field is disabled.
53
- * `size` sets shell height (`sm` = 28px, `default` = 32px, `lg` = 36px) and is inherited by `InputGroupInput` unless overridden there.
53
+ * `size` sets shell height (`sm` = 24px, `default` = 28px, `lg` = 32px) and is inherited by `InputGroupInput` unless overridden there.
54
54
  */
55
55
  function InputGroup({ className, size = 'default', ...props }) {
56
56
  const resolvedSize = size ?? 'default';
@@ -3,7 +3,7 @@ import * as React from 'react';
3
3
  import { ChevronDown } from 'lucide-react';
4
4
  import { cn } from '../../lib/utils';
5
5
  function NativeSelect({ className, size = 'default', ...props }) {
6
- return (_jsxs("div", { className: cn('group/native-select relative w-fit has-[select:disabled]:opacity-50', className), "data-slot": "native-select-wrapper", "data-size": size, children: [_jsx("select", { "data-slot": "native-select", "data-size": size, className: "h-8 w-full min-w-0 appearance-none rounded-lg border border-input bg-transparent py-1 pr-8 pl-2.5 text-sm transition-colors outline-none select-none selection:bg-primary selection:text-primary-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-[size=sm]:h-7 data-[size=sm]:rounded-[min(var(--radius-md),10px)] data-[size=sm]:py-0.5 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40", ...props }), _jsx(ChevronDown, { className: "pointer-events-none absolute top-1/2 right-2.5 size-4 -translate-y-1/2 text-muted-foreground select-none", "aria-hidden": "true", "data-slot": "native-select-icon" })] }));
6
+ return (_jsxs("div", { className: cn('group/native-select relative w-fit has-[select:disabled]:opacity-50', className), "data-slot": "native-select-wrapper", "data-size": size, children: [_jsx("select", { "data-slot": "native-select", "data-size": size, className: "h-7 w-full min-w-0 appearance-none rounded-[min(var(--radius-md),10px)] border border-input bg-transparent py-0.5 pr-8 pl-2.5 text-sm transition-colors outline-none select-none selection:bg-primary selection:text-primary-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-[size=sm]:h-6 data-[size=sm]:text-xs dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40", ...props }), _jsx(ChevronDown, { className: "pointer-events-none absolute top-1/2 right-2.5 size-4 -translate-y-1/2 text-muted-foreground select-none", "aria-hidden": "true", "data-slot": "native-select-icon" })] }));
7
7
  }
8
8
  function NativeSelectOption({ className, ...props }) {
9
9
  return _jsx("option", { "data-slot": "native-select-option", className: cn('bg-[Canvas] text-[CanvasText]', className), ...props });