@wheelhouse/ui 0.2.9 → 0.2.11

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.
@@ -14,7 +14,7 @@ declare const buttonSizeStyles: {
14
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
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
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";
17
+ readonly icon: "size-8 text-sm";
18
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
19
  readonly 'icon-sm': "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg";
20
20
  readonly 'icon-lg': "size-9";
@@ -17,7 +17,7 @@ const buttonSizeStyles = {
17
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
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
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',
20
+ icon: 'size-8 text-sm',
21
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
22
  'icon-sm': 'size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg',
23
23
  'icon-lg': 'size-9',
@@ -25,7 +25,7 @@ function ComboboxInput({ className, children, disabled = false, showTrigger = tr
25
25
  return (_jsxs(InputGroup, { className: cn('w-auto', className), children: [_jsx(ComboboxPrimitive.Input, { render: _jsx(InputGroupInput, { disabled: disabled }), ...props }), _jsxs(InputGroupAddon, { align: "inline-end", children: [showTrigger && (_jsx(InputGroupButton, { size: "icon-xs", variant: "ghost", render: _jsx(ComboboxTrigger, {}), "data-slot": "input-group-button", className: "group-has-data-[slot=combobox-clear]/input-group:hidden data-pressed:bg-transparent", disabled: disabled })), showClear && _jsx(ComboboxClear, { disabled: disabled })] }), children] }));
26
26
  }
27
27
  function ComboboxContent({ className, side = 'bottom', sideOffset = 6, align = 'start', alignOffset = 0, anchor, ...props }) {
28
- return (_jsx(ComboboxPrimitive.Portal, { children: _jsx(ComboboxPrimitive.Positioner, { side: side, sideOffset: sideOffset, align: align, alignOffset: alignOffset, anchor: anchor, className: "isolate z-50", children: _jsx(ComboboxPrimitive.Popup, { "data-slot": "combobox-content", "data-chips": !!anchor, className: cn('group/combobox-content relative max-h-(--available-height) w-(--anchor-width) max-w-(--available-width) min-w-[calc(var(--anchor-width)+--spacing(7))] origin-(--transform-origin) overflow-hidden rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[chips=true]:min-w-(--anchor-width) data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 *:data-[slot=input-group]:m-1 *:data-[slot=input-group]:mb-0 *:data-[slot=input-group]:h-8 *:data-[slot=input-group]:border-input/30 *:data-[slot=input-group]:bg-input/30 *:data-[slot=input-group]:shadow-none 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 }) }) }));
28
+ return (_jsx(ComboboxPrimitive.Portal, { children: _jsx(ComboboxPrimitive.Positioner, { side: side, sideOffset: sideOffset, align: align, alignOffset: alignOffset, anchor: anchor, className: "isolate z-50", children: _jsx(ComboboxPrimitive.Popup, { "data-slot": "combobox-content", "data-chips": !!anchor, className: cn('group/combobox-content relative max-h-(--available-height) w-(--anchor-width) max-w-(--available-width) min-w-[calc(var(--anchor-width)+--spacing(7))] origin-(--transform-origin) overflow-hidden rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[chips=true]:min-w-(--anchor-width) data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 *:data-[slot=input-group]:m-1 *:data-[slot=input-group]:mb-0 *:data-[slot=input-group]:border-input/30 *:data-[slot=input-group]:bg-input/30 *:data-[slot=input-group]:shadow-none 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 }) }) }));
29
29
  }
30
30
  function ComboboxList({ className, ...props }) {
31
31
  return (_jsx(ComboboxPrimitive.List, { "data-slot": "combobox-list", className: cn('no-scrollbar max-h-[min(calc(--spacing(72)---spacing(9)),calc(var(--available-height)---spacing(9)))] scroll-py-1 overflow-y-auto overscroll-contain p-1 data-empty:p-0', className), ...props }));
@@ -13,7 +13,7 @@ function CommandDialog({ title = 'Command Palette', description = 'Search for a
13
13
  return (_jsxs(Dialog, { ...props, children: [_jsxs(DialogHeader, { className: "sr-only", children: [_jsx(DialogTitle, { children: title }), _jsx(DialogDescription, { children: description })] }), _jsx(DialogContent, { className: cn('top-1/3 translate-y-0 overflow-hidden rounded-xl! p-0', className), showCloseButton: showCloseButton, children: children })] }));
14
14
  }
15
15
  function CommandInput({ className, ...props }) {
16
- return (_jsx("div", { "data-slot": "command-input-wrapper", className: "p-1 pb-0", children: _jsxs(InputGroup, { className: "h-8! rounded-lg! border-input/30 bg-input/30 shadow-none! *:data-[slot=input-group-addon]:pl-2!", children: [_jsx(CommandPrimitive.Input, { "data-slot": "command-input", className: cn('w-full text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50', className), ...props }), _jsx(InputGroupAddon, { children: _jsx(Search, { className: "size-4 shrink-0 opacity-50" }) })] }) }));
16
+ return (_jsx("div", { "data-slot": "command-input-wrapper", className: "p-1 pb-0", children: _jsxs(InputGroup, { className: "rounded-lg! border-input/30 bg-input/30 shadow-none! *:data-[slot=input-group-addon]:pl-2!", children: [_jsx(CommandPrimitive.Input, { "data-slot": "command-input", className: cn('w-full text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50', className), ...props }), _jsx(InputGroupAddon, { children: _jsx(Search, { className: "size-4 shrink-0 opacity-50" }) })] }) }));
17
17
  }
18
18
  function CommandList({ className, ...props }) {
19
19
  return (_jsx(CommandPrimitive.List, { "data-slot": "command-list", className: cn('no-scrollbar max-h-72 scroll-py-1 overflow-x-hidden overflow-y-auto outline-none', className), ...props }));
@@ -117,7 +117,7 @@ function FilterInput({ field, onBlur, onKeyDown, className, ...props }) {
117
117
  // Call the original onKeyDown if provided
118
118
  onKeyDown?.(e);
119
119
  };
120
- return (_jsxs(InputGroup, { className: cn('w-36', context.size == 'sm' && 'h-7!', context.size == 'default' && 'h-8!', context.size == 'lg' && 'h-9!', className), children: [field?.prefix && (_jsx(InputGroupAddon, { children: _jsx(InputGroupText, { children: field.prefix }) })), _jsx(InputGroupInput, { ref: inputRef, size: context.size, "aria-invalid": !isValid, "aria-describedby": !isValid && validationMessage ? `${field?.key || 'input'}-error` : undefined, onBlur: handleBlur, onKeyDown: handleKeyDown, ...props }), !isValid && validationMessage && (_jsx(InputGroupAddon, { align: "inline-end", children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { render: _jsx(InputGroupButton, { size: "icon-xs" }), children: _jsx(AlertCircle, { className: "size-3.5 text-destructive" }) }), _jsx(TooltipContent, { children: _jsx("p", { className: "text-sm", children: validationMessage }) })] }) })), field?.suffix && (_jsx(InputGroupAddon, { align: "inline-end", children: _jsx(InputGroupText, { children: field.suffix }) }))] }));
120
+ return (_jsxs(InputGroup, { size: context.size, className: cn('w-36', className), children: [field?.prefix && (_jsx(InputGroupAddon, { children: _jsx(InputGroupText, { children: field.prefix }) })), _jsx(InputGroupInput, { ref: inputRef, size: context.size, "aria-invalid": !isValid, "aria-describedby": !isValid && validationMessage ? `${field?.key || 'input'}-error` : undefined, onBlur: handleBlur, onKeyDown: handleKeyDown, ...props }), !isValid && validationMessage && (_jsx(InputGroupAddon, { align: "inline-end", children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { render: _jsx(InputGroupButton, { size: "icon-xs" }), children: _jsx(AlertCircle, { className: "size-3.5 text-destructive" }) }), _jsx(TooltipContent, { children: _jsx("p", { className: "text-sm", children: validationMessage }) })] }) })), field?.suffix && (_jsx(InputGroupAddon, { align: "inline-end", children: _jsx(InputGroupText, { children: field.suffix }) }))] }));
121
121
  }
122
122
  function FilterRemoveButton({ className, icon = _jsx(X, {}), ...props }) {
123
123
  const context = useFilterContext();
@@ -1,3 +1,3 @@
1
- export { InputGroup, InputGroupAddon, InputGroupButton, InputGroupText, InputGroupInput, InputGroupTextarea, inputGroupAddonVariants, inputGroupButtonVariants, inputGroupAddonAlignKeys, inputGroupButtonSizeKeys, } from './input-group';
1
+ export { InputGroup, InputGroupAddon, InputGroupButton, InputGroupText, InputGroupInput, InputGroupTextarea, inputGroupAddonVariants, inputGroupButtonVariants, inputGroupAddonAlignKeys, inputGroupButtonSizeKeys, inputGroupSizeKeys, inputGroupVariants, } from './input-group';
2
2
  export type { InputGroupProps, InputGroupAddonProps, InputGroupButtonProps, InputGroupTextProps, InputGroupInputProps, InputGroupTextareaProps, } from './input-group';
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/input-group/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,uBAAuB,EACvB,wBAAwB,EACxB,wBAAwB,EACxB,wBAAwB,GAC3B,MAAM,eAAe,CAAC;AACvB,YAAY,EACR,eAAe,EACf,oBAAoB,EACpB,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,GAC1B,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/input-group/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,uBAAuB,EACvB,wBAAwB,EACxB,wBAAwB,EACxB,wBAAwB,EACxB,kBAAkB,EAClB,kBAAkB,GACrB,MAAM,eAAe,CAAC;AACvB,YAAY,EACR,eAAe,EACf,oBAAoB,EACpB,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,GAC1B,MAAM,eAAe,CAAC"}
@@ -1 +1 @@
1
- export { InputGroup, InputGroupAddon, InputGroupButton, InputGroupText, InputGroupInput, InputGroupTextarea, inputGroupAddonVariants, inputGroupButtonVariants, inputGroupAddonAlignKeys, inputGroupButtonSizeKeys, } from './input-group';
1
+ export { InputGroup, InputGroupAddon, InputGroupButton, InputGroupText, InputGroupInput, InputGroupTextarea, inputGroupAddonVariants, inputGroupButtonVariants, inputGroupAddonAlignKeys, inputGroupButtonSizeKeys, inputGroupSizeKeys, inputGroupVariants, } from './input-group';
@@ -3,8 +3,12 @@ import { type VariantProps } from 'class-variance-authority';
3
3
  import { Button } from '../button';
4
4
  import type { InputProps } from '../input';
5
5
  import type { TextareaProps } from '../textarea';
6
+ export declare const inputGroupSizeKeys: readonly ["sm", "default", "lg"];
7
+ declare const inputGroupVariants: (props?: ({
8
+ size?: "default" | "sm" | "lg" | null | undefined;
9
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
10
  /** Props for `InputGroup`. */
7
- export type InputGroupProps = React.ComponentProps<'div'>;
11
+ export type InputGroupProps = React.ComponentProps<'div'> & VariantProps<typeof inputGroupVariants>;
8
12
  declare const inputGroupAddonVariants: (props?: ({
9
13
  align?: "inline-end" | "inline-start" | "block-end" | "block-start" | null | undefined;
10
14
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
@@ -27,8 +31,9 @@ export type InputGroupInputProps = InputProps;
27
31
  export type InputGroupTextareaProps = TextareaProps;
28
32
  /**
29
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.
30
35
  */
31
- declare function InputGroup({ className, ...props }: InputGroupProps): import("react/jsx-runtime").JSX.Element;
36
+ declare function InputGroup({ className, size, ...props }: InputGroupProps): import("react/jsx-runtime").JSX.Element;
32
37
  /**
33
38
  * Static prefix or suffix (text, `Kbd`, icon, or `InputGroupButton`). Clicking the addon focuses the nested input unless the click target is a button.
34
39
  */
@@ -37,8 +42,8 @@ declare function InputGroupButton({ className, type, variant, size, ...props }:
37
42
  /** Muted inline label text inside an addon. */
38
43
  declare function InputGroupText({ className, ...props }: InputGroupTextProps): import("react/jsx-runtime").JSX.Element;
39
44
  /** Single-line control that shares the group border and focus ring. */
40
- declare function InputGroupInput({ className, ...props }: InputGroupInputProps): import("react/jsx-runtime").JSX.Element;
45
+ declare function InputGroupInput({ className, size: sizeProp, ...props }: InputGroupInputProps): import("react/jsx-runtime").JSX.Element;
41
46
  /** Multi-line control that shares the group border and focus ring. */
42
47
  declare function InputGroupTextarea({ className, ...props }: InputGroupTextareaProps): import("react/jsx-runtime").JSX.Element;
43
- export { InputGroup, InputGroupAddon, InputGroupButton, InputGroupText, InputGroupInput, InputGroupTextarea, inputGroupAddonVariants, inputGroupButtonVariants, };
48
+ export { InputGroup, InputGroupAddon, InputGroupButton, InputGroupText, InputGroupInput, InputGroupTextarea, inputGroupAddonVariants, inputGroupButtonVariants, inputGroupVariants, };
44
49
  //# sourceMappingURL=input-group.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"input-group.d.ts","sourceRoot":"","sources":["../../../src/components/input-group/input-group.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAGlE,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACnC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD,8BAA8B;AAC9B,MAAM,MAAM,eAAe,GAAG,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;AAE1D,QAAA,MAAM,uBAAuB;;8EAe5B,CAAC;AAEF,eAAO,MAAM,wBAAwB,qEAAsE,CAAC;AAE5G,mCAAmC;AACnC,MAAM,MAAM,oBAAoB,GAAG,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,YAAY,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAE9G,QAAA,MAAM,wBAAwB;;8EAY5B,CAAC;AAEH,eAAO,MAAM,wBAAwB,6CAA8C,CAAC;AAEpF,gFAAgF;AAChF,MAAM,MAAM,qBAAqB,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,GAC1F,YAAY,CAAC,OAAO,wBAAwB,CAAC,GAAG;IAC5C,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;CACxC,CAAC;AAEN,kCAAkC;AAClC,MAAM,MAAM,mBAAmB,GAAG,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;AAE/D,+EAA+E;AAC/E,MAAM,MAAM,oBAAoB,GAAG,UAAU,CAAC;AAE9C,mEAAmE;AACnE,MAAM,MAAM,uBAAuB,GAAG,aAAa,CAAC;AAEpD;;GAEG;AACH,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,2CAY3D;AAED;;GAEG;AACH,iBAAS,eAAe,CAAC,EAAE,SAAS,EAAE,KAAsB,EAAE,GAAG,KAAK,EAAE,EAAE,oBAAoB,2CAkB7F;AAED,iBAAS,gBAAgB,CAAC,EAAE,SAAS,EAAE,IAAe,EAAE,OAAiB,EAAE,IAAW,EAAE,GAAG,KAAK,EAAE,EAAE,qBAAqB,2CAExH;AAED,+CAA+C;AAC/C,iBAAS,cAAc,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,mBAAmB,2CAOnE;AAED,uEAAuE;AACvE,iBAAS,eAAe,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,oBAAoB,2CAWrE;AAED,sEAAsE;AACtE,iBAAS,kBAAkB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,uBAAuB,2CAW3E;AAED,OAAO,EACH,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,uBAAuB,EACvB,wBAAwB,GAC3B,CAAC"}
1
+ {"version":3,"file":"input-group.d.ts","sourceRoot":"","sources":["../../../src/components/input-group/input-group.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAGlE,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACnC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD,eAAO,MAAM,kBAAkB,kCAAgB,CAAC;AAMhD,QAAA,MAAM,kBAAkB;;8EAcvB,CAAC;AAEF,8BAA8B;AAC9B,MAAM,MAAM,eAAe,GAAG,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,YAAY,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEpG,QAAA,MAAM,uBAAuB;;8EAe5B,CAAC;AAEF,eAAO,MAAM,wBAAwB,qEAAsE,CAAC;AAE5G,mCAAmC;AACnC,MAAM,MAAM,oBAAoB,GAAG,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,YAAY,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAE9G,QAAA,MAAM,wBAAwB;;8EAY5B,CAAC;AAEH,eAAO,MAAM,wBAAwB,6CAA8C,CAAC;AAEpF,gFAAgF;AAChF,MAAM,MAAM,qBAAqB,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,GAC1F,YAAY,CAAC,OAAO,wBAAwB,CAAC,GAAG;IAC5C,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;CACxC,CAAC;AAEN,kCAAkC;AAClC,MAAM,MAAM,mBAAmB,GAAG,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;AAE/D,+EAA+E;AAC/E,MAAM,MAAM,oBAAoB,GAAG,UAAU,CAAC;AAE9C,mEAAmE;AACnE,MAAM,MAAM,uBAAuB,GAAG,aAAa,CAAC;AAEpD;;;GAGG;AACH,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,IAAgB,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,2CAc7E;AAED;;GAEG;AACH,iBAAS,eAAe,CAAC,EAAE,SAAS,EAAE,KAAsB,EAAE,GAAG,KAAK,EAAE,EAAE,oBAAoB,2CAkB7F;AAED,iBAAS,gBAAgB,CAAC,EAAE,SAAS,EAAE,IAAe,EAAE,OAAiB,EAAE,IAAW,EAAE,GAAG,KAAK,EAAE,EAAE,qBAAqB,2CAExH;AAED,+CAA+C;AAC/C,iBAAS,cAAc,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,mBAAmB,2CAOnE;AAED,uEAAuE;AACvE,iBAAS,eAAe,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,oBAAoB,2CAerF;AAED,sEAAsE;AACtE,iBAAS,kBAAkB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,uBAAuB,2CAW3E;AAED,OAAO,EACH,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,uBAAuB,EACvB,wBAAwB,EACxB,kBAAkB,GACrB,CAAC"}
@@ -4,9 +4,23 @@ import * as React from 'react';
4
4
  import { cva } from 'class-variance-authority';
5
5
  import { cn } from '../../lib/utils';
6
6
  import { Button } from '../button';
7
- import { Input } from '../input';
7
+ import { Input, inputSizeKeys } from '../input';
8
8
  import { Textarea } from '../textarea';
9
- 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 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4", {
9
+ export const inputGroupSizeKeys = inputSizeKeys;
10
+ const InputGroupSizeContext = React.createContext(undefined);
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
+ variants: {
13
+ size: {
14
+ sm: 'h-7 rounded-[min(var(--radius-md),12px)]',
15
+ default: 'h-8',
16
+ lg: 'h-9',
17
+ },
18
+ },
19
+ defaultVariants: {
20
+ size: 'default',
21
+ },
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", {
10
24
  variants: {
11
25
  align: {
12
26
  'inline-start': 'order-first pl-2 has-[>button]:ml-[-0.3rem] has-[>kbd]:ml-[-0.15rem]',
@@ -36,9 +50,11 @@ const inputGroupButtonVariants = cva('flex items-center gap-2 text-sm shadow-non
36
50
  export const inputGroupButtonSizeKeys = ['xs', 'sm', 'icon-xs', 'icon-sm'];
37
51
  /**
38
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.
39
54
  */
40
- function InputGroup({ className, ...props }) {
41
- return (_jsx("div", { "data-slot": "input-group", role: "group", className: cn('group/input-group relative flex h-8 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', className), ...props }));
55
+ function InputGroup({ className, size = 'default', ...props }) {
56
+ const resolvedSize = size ?? 'default';
57
+ return (_jsx(InputGroupSizeContext.Provider, { value: resolvedSize, children: _jsx("div", { "data-slot": "input-group", "data-size": resolvedSize, role: "group", className: cn(inputGroupVariants({ size: resolvedSize }), className), ...props }) }));
42
58
  }
43
59
  /**
44
60
  * Static prefix or suffix (text, `Kbd`, icon, or `InputGroupButton`). Clicking the addon focuses the nested input unless the click target is a button.
@@ -62,11 +78,13 @@ function InputGroupText({ className, ...props }) {
62
78
  return (_jsx("span", { className: cn("flex items-center gap-2 text-sm text-muted-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4", className), ...props }));
63
79
  }
64
80
  /** Single-line control that shares the group border and focus ring. */
65
- function InputGroupInput({ className, ...props }) {
66
- return (_jsx(Input, { "data-slot": "input-group-control", className: cn('flex-1 rounded-none border-0 bg-transparent shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent aria-invalid:ring-0 dark:bg-transparent dark:disabled:bg-transparent', className), ...props }));
81
+ function InputGroupInput({ className, size: sizeProp, ...props }) {
82
+ const groupSize = React.useContext(InputGroupSizeContext);
83
+ const size = sizeProp ?? groupSize ?? 'default';
84
+ return (_jsx(Input, { "data-slot": "input-group-control", size: size, className: cn('h-full min-h-0 flex-1 rounded-none border-0 bg-transparent shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent aria-invalid:ring-0 dark:bg-transparent dark:disabled:bg-transparent', className), ...props }));
67
85
  }
68
86
  /** Multi-line control that shares the group border and focus ring. */
69
87
  function InputGroupTextarea({ className, ...props }) {
70
88
  return (_jsx(Textarea, { "data-slot": "input-group-control", className: cn('flex-1 resize-none rounded-none border-0 bg-transparent py-2 shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent aria-invalid:ring-0 dark:bg-transparent dark:disabled:bg-transparent', className), ...props }));
71
89
  }
72
- export { InputGroup, InputGroupAddon, InputGroupButton, InputGroupText, InputGroupInput, InputGroupTextarea, inputGroupAddonVariants, inputGroupButtonVariants, };
90
+ export { InputGroup, InputGroupAddon, InputGroupButton, InputGroupText, InputGroupInput, InputGroupTextarea, inputGroupAddonVariants, inputGroupButtonVariants, inputGroupVariants, };
@@ -7,10 +7,23 @@ declare const meta: {
7
7
  parameters: {
8
8
  layout: string;
9
9
  };
10
+ args: {
11
+ size: "default";
12
+ };
13
+ argTypes: {
14
+ size: {
15
+ control: "select";
16
+ options: readonly ["sm", "default", "lg"];
17
+ };
18
+ className: {
19
+ control: false;
20
+ };
21
+ };
10
22
  };
11
23
  export default meta;
12
24
  type Story = StoryObj<typeof meta>;
13
25
  export declare const Default: Story;
26
+ export declare const Sizes: Story;
14
27
  export declare const WithTrailingButton: Story;
15
28
  export declare const WithKbd: Story;
16
29
  export declare const Textarea: Story;
@@ -1 +1 @@
1
- {"version":3,"file":"input-group.stories.d.ts","sourceRoot":"","sources":["../../../src/components/input-group/input-group.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAIvD,OAAO,EAAE,UAAU,EAA0F,MAAM,GAAG,CAAC;AAEvH,QAAA,MAAM,IAAI;;;;;;;CAOyB,CAAC;AAEpC,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,OAAO,EAAE,KAWrB,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,KAahC,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,KAYrB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAWtB,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,KAmCrB,CAAC"}
1
+ {"version":3,"file":"input-group.stories.d.ts","sourceRoot":"","sources":["../../../src/components/input-group/input-group.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAIvD,OAAO,EAAE,UAAU,EAA8G,MAAM,GAAG,CAAC;AAE3I,QAAA,MAAM,IAAI;;;;;;;;;;;;;;;;;;;CAcyB,CAAC;AAEpC,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,OAAO,EAAE,KAWrB,CAAC;AAEF,eAAO,MAAM,KAAK,EAAE,KAuBnB,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,KAahC,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,KAYrB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAWtB,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,KAmCrB,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Search } from 'lucide-react';
3
3
  import { Kbd } from '../kbd';
4
- import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea } from '.';
4
+ import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, inputGroupSizeKeys, InputGroupText, InputGroupTextarea } from '.';
5
5
  const meta = {
6
6
  title: 'Components/InputGroup',
7
7
  component: InputGroup,
@@ -9,13 +9,23 @@ const meta = {
9
9
  parameters: {
10
10
  layout: 'centered',
11
11
  },
12
+ args: {
13
+ size: 'default',
14
+ },
15
+ argTypes: {
16
+ size: { control: 'select', options: inputGroupSizeKeys },
17
+ className: { control: false },
18
+ },
12
19
  };
13
20
  export default meta;
14
21
  export const Default = {
15
22
  render: () => (_jsx("div", { className: "w-80", children: _jsxs(InputGroup, { children: [_jsx(InputGroupAddon, { children: _jsx(InputGroupText, { children: "https://" }) }), _jsx(InputGroupInput, { placeholder: "example.com" })] }) })),
16
23
  };
24
+ export const Sizes = {
25
+ render: () => (_jsxs("div", { className: "flex w-80 flex-col gap-2", children: [_jsxs(InputGroup, { size: "sm", children: [_jsx(InputGroupAddon, { children: _jsx(InputGroupText, { children: "https://" }) }), _jsx(InputGroupInput, { placeholder: "Small (h-7)" })] }), _jsxs(InputGroup, { size: "default", children: [_jsx(InputGroupAddon, { children: _jsx(InputGroupText, { children: "https://" }) }), _jsx(InputGroupInput, { placeholder: "Default (h-8)" })] }), _jsxs(InputGroup, { size: "lg", children: [_jsx(InputGroupAddon, { children: _jsx(InputGroupText, { children: "https://" }) }), _jsx(InputGroupInput, { placeholder: "Large (h-9)" })] })] })),
26
+ };
17
27
  export const WithTrailingButton = {
18
- render: () => (_jsx("div", { className: "w-80", children: _jsxs(InputGroup, { children: [_jsx(InputGroupInput, { placeholder: "Search\u2026" }), _jsx(InputGroupAddon, { align: "inline-end", children: _jsx(InputGroupButton, { type: "button", "aria-label": "Search", children: _jsx(Search, { className: "size-4" }) }) })] }) })),
28
+ render: () => (_jsx("div", { className: "w-80", children: _jsxs(InputGroup, { children: [_jsx(InputGroupInput, { placeholder: "Search it all\u2026" }), _jsx(InputGroupAddon, { align: "inline-end", children: _jsx(InputGroupButton, { type: "button", "aria-label": "Search", children: _jsx(Search, { className: "size-4" }) }) })] }) })),
19
29
  };
20
30
  export const WithKbd = {
21
31
  render: () => (_jsx("div", { className: "w-80", children: _jsxs(InputGroup, { children: [_jsx(InputGroupInput, { placeholder: "Command\u2026" }), _jsxs(InputGroupAddon, { align: "inline-end", children: [_jsx(Kbd, { children: "\u2318" }), _jsx(Kbd, { children: "K" })] })] }) })),
@@ -16,6 +16,6 @@ function TooltipTrigger({ ...props }) {
16
16
  return _jsx(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", ...props });
17
17
  }
18
18
  function TooltipContent({ className, side = 'top', sideOffset = 4, align = 'center', alignOffset = 0, showArrow = false, children, ...props }) {
19
- return (_jsx(TooltipPrimitive.Portal, { children: _jsx(TooltipPrimitive.Positioner, { align: align, alignOffset: alignOffset, side: side, sideOffset: sideOffset, className: "isolate z-50", children: _jsxs(TooltipPrimitive.Popup, { "data-slot": "tooltip-content", className: cn('z-50 inline-flex w-fit max-w-xs origin-(--transform-origin) items-center gap-1.5 rounded-md bg-foreground px-3 py-1.5 text-xs text-background has-data-[slot=kbd]:pr-1.5 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 **:data-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:rounded-sm data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 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, showArrow && (_jsx(TooltipPrimitive.Arrow, { className: "z-50 size-2.5 translate-y-[calc(-50%-2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground data-[side=bottom]:top-1 data-[side=inline-end]:top-1/2! data-[side=inline-end]:-left-1 data-[side=inline-end]:-translate-y-1/2 data-[side=inline-start]:top-1/2! data-[side=inline-start]:-right-1 data-[side=inline-start]:-translate-y-1/2 data-[side=left]:top-1/2! data-[side=left]:-right-1 data-[side=left]:-translate-y-1/2 data-[side=right]:top-1/2! data-[side=right]:-left-1 data-[side=right]:-translate-y-1/2 data-[side=top]:-bottom-2.5" }))] }) }) }));
19
+ return (_jsx(TooltipPrimitive.Portal, { children: _jsx(TooltipPrimitive.Positioner, { align: align, alignOffset: alignOffset, side: side, sideOffset: sideOffset, className: "isolate z-50", children: _jsxs(TooltipPrimitive.Popup, { "data-slot": "tooltip-content", className: cn('z-50 inline-flex w-fit max-w-xs origin-(--transform-origin) items-center gap-1.5 rounded-md bg-foreground px-2 py-1 text-xs text-background has-data-[slot=kbd]:pr-1.5 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 **:data-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:rounded-sm data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 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, showArrow && (_jsx(TooltipPrimitive.Arrow, { className: "z-50 size-2.5 translate-y-[calc(-50%-2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground data-[side=bottom]:top-1 data-[side=inline-end]:top-1/2! data-[side=inline-end]:-left-1 data-[side=inline-end]:-translate-y-1/2 data-[side=inline-start]:top-1/2! data-[side=inline-start]:-right-1 data-[side=inline-start]:-translate-y-1/2 data-[side=left]:top-1/2! data-[side=left]:-right-1 data-[side=left]:-translate-y-1/2 data-[side=right]:top-1/2! data-[side=right]:-left-1 data-[side=right]:-translate-y-1/2 data-[side=top]:-bottom-2.5" }))] }) }) }));
20
20
  }
21
21
  export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };
@@ -0,0 +1,3 @@
1
+ export { useIsMobile } from './use-mobile';
2
+ export { useMediaQuery, type MediaQueryInput } from './use-media-query';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { useIsMobile } from './use-mobile';
2
+ export { useMediaQuery } from './use-media-query';
@@ -0,0 +1,19 @@
1
+ /** Matches Tailwind v4 default breakpoints (see tailwindcss theme). */
2
+ declare const BREAKPOINTS: {
3
+ readonly sm: 640;
4
+ readonly md: 768;
5
+ readonly lg: 1024;
6
+ readonly xl: 1280;
7
+ readonly '2xl': 1536;
8
+ };
9
+ type Breakpoint = keyof typeof BREAKPOINTS;
10
+ type BreakpointQuery = Breakpoint | `max-${Breakpoint}` | `${Breakpoint}:max-${Breakpoint}`;
11
+ export type MediaQueryInput = {
12
+ min?: Breakpoint | number;
13
+ max?: Breakpoint | number;
14
+ /** Touch-like input (finger). Use `fine` for mouse/trackpad. */
15
+ pointer?: 'coarse' | 'fine';
16
+ };
17
+ export declare function useMediaQuery(query: BreakpointQuery | MediaQueryInput | (string & {})): boolean;
18
+ export {};
19
+ //# sourceMappingURL=use-media-query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-media-query.d.ts","sourceRoot":"","sources":["../../src/hooks/use-media-query.ts"],"names":[],"mappings":"AAIA,uEAAuE;AACvE,QAAA,MAAM,WAAW;;;;;;CAMP,CAAC;AAEX,KAAK,UAAU,GAAG,MAAM,OAAO,WAAW,CAAC;AAE3C,KAAK,eAAe,GAAG,UAAU,GAAG,OAAO,UAAU,EAAE,GAAG,GAAG,UAAU,QAAQ,UAAU,EAAE,CAAC;AAE5F,MAAM,MAAM,eAAe,GAAG;IAC1B,GAAG,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IAC1B,GAAG,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IAC1B,gEAAgE;IAChE,OAAO,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;CAC/B,CAAC;AAyCF,wBAAgB,aAAa,CAAC,KAAK,EAAE,eAAe,GAAG,eAAe,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,GAAG,OAAO,CAmB/F"}
@@ -0,0 +1,67 @@
1
+ 'use client';
2
+ import { useCallback, useSyncExternalStore } from 'react';
3
+ /** Matches Tailwind v4 default breakpoints (see tailwindcss theme). */
4
+ const BREAKPOINTS = {
5
+ sm: 640,
6
+ md: 768,
7
+ lg: 1024,
8
+ xl: 1280,
9
+ '2xl': 1536,
10
+ };
11
+ function resolveMin(value) {
12
+ const px = typeof value === 'number' ? value : BREAKPOINTS[value];
13
+ return `(min-width: ${px}px)`;
14
+ }
15
+ function resolveMax(value) {
16
+ const px = typeof value === 'number' ? value : BREAKPOINTS[value];
17
+ return `(max-width: ${px - 1}px)`;
18
+ }
19
+ function parseQuery(query) {
20
+ if (typeof query !== 'string') {
21
+ const parts = [];
22
+ if (query.min != null)
23
+ parts.push(resolveMin(query.min));
24
+ if (query.max != null)
25
+ parts.push(resolveMax(query.max));
26
+ if (query.pointer === 'coarse')
27
+ parts.push('(pointer: coarse)');
28
+ if (query.pointer === 'fine')
29
+ parts.push('(pointer: fine)');
30
+ if (parts.length === 0)
31
+ return '(min-width: 0px)';
32
+ return parts.join(' and ');
33
+ }
34
+ if (query.startsWith('('))
35
+ return query;
36
+ const parts = [];
37
+ for (const segment of query.split(':')) {
38
+ if (segment.startsWith('max-')) {
39
+ const bp = segment.slice(4);
40
+ if (bp in BREAKPOINTS)
41
+ parts.push(resolveMax(bp));
42
+ }
43
+ else if (segment in BREAKPOINTS) {
44
+ parts.push(resolveMin(segment));
45
+ }
46
+ }
47
+ return parts.length > 0 ? parts.join(' and ') : query;
48
+ }
49
+ function getServerSnapshot() {
50
+ return false;
51
+ }
52
+ export function useMediaQuery(query) {
53
+ const mediaQuery = parseQuery(query);
54
+ const subscribe = useCallback((callback) => {
55
+ if (typeof window === 'undefined')
56
+ return () => { };
57
+ const mql = window.matchMedia(mediaQuery);
58
+ mql.addEventListener('change', callback);
59
+ return () => mql.removeEventListener('change', callback);
60
+ }, [mediaQuery]);
61
+ const getSnapshot = useCallback(() => {
62
+ if (typeof window === 'undefined')
63
+ return false;
64
+ return window.matchMedia(mediaQuery).matches;
65
+ }, [mediaQuery]);
66
+ return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
67
+ }
@@ -1,2 +1,3 @@
1
+ /** True below the Tailwind `md` breakpoint (max-width 767px). */
1
2
  export declare function useIsMobile(): boolean;
2
3
  //# sourceMappingURL=use-mobile.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-mobile.d.ts","sourceRoot":"","sources":["../../src/hooks/use-mobile.ts"],"names":[],"mappings":"AAIA,wBAAgB,WAAW,YAc1B"}
1
+ {"version":3,"file":"use-mobile.d.ts","sourceRoot":"","sources":["../../src/hooks/use-mobile.ts"],"names":[],"mappings":"AAIA,iEAAiE;AACjE,wBAAgB,WAAW,IAAI,OAAO,CAErC"}
@@ -1,15 +1,6 @@
1
- import * as React from 'react';
2
- const MOBILE_BREAKPOINT = 768;
1
+ 'use client';
2
+ import { useMediaQuery } from './use-media-query';
3
+ /** True below the Tailwind `md` breakpoint (max-width 767px). */
3
4
  export function useIsMobile() {
4
- const [isMobile, setIsMobile] = React.useState(undefined);
5
- React.useEffect(() => {
6
- const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
7
- const onChange = () => {
8
- setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
9
- };
10
- mql.addEventListener('change', onChange);
11
- setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
12
- return () => mql.removeEventListener('change', onChange);
13
- }, []);
14
- return !!isMobile;
5
+ return useMediaQuery('max-md');
15
6
  }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from './components';
2
2
  export * from './blocks';
3
+ export * from './hooks';
3
4
  export { cn } from './lib/utils';
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './components';
2
2
  export * from './blocks';
3
+ export * from './hooks';
3
4
  export { cn } from './lib/utils';