Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

@diceui/shared

Package Overview
Dependencies
Maintainers
1
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@diceui/shared - npm Package Compare versions

Comparing version
0.4.0
to
0.5.0
+247
-40
dist/index.d.mts
import * as React from 'react';
import { VirtualElement, Boundary, Strategy, UseFloatingReturn, Placement, FloatingContext } from '@floating-ui/react';

@@ -14,2 +15,40 @@ type InputValue = string[] | string;

/**
* @see https://github.com/radix-ui/primitives/blob/main/packages/react/slot/src/Slot.tsx
*/
interface SlotProps extends React.HTMLAttributes<HTMLElement> {
children?: React.ReactNode;
}
declare const Slot: React.ForwardRefExoticComponent<SlotProps & React.RefAttributes<HTMLElement>>;
interface SlottableProps {
children: React.ReactNode;
}
declare const Slottable: React.NamedExoticComponent<SlottableProps>;
type CollectionItem<TItemElement extends HTMLElement, TItemData = {}> = {
ref: React.RefObject<TItemElement | null>;
} & TItemData;
type CollectionItemMap<TItemElement extends HTMLElement, TItemData = {}> = Map<React.RefObject<TItemElement | null>, CollectionItem<TItemElement, TItemData>>;
interface CollectionContextValue<TItemElement extends HTMLElement, TItemData = {}> {
collectionRef: React.RefObject<TItemElement | null>;
itemMap: CollectionItemMap<TItemElement, TItemData>;
}
interface CollectionProps extends SlotProps {
}
declare function createCollection<TItemElement extends HTMLElement, TItemData = {}>(name: string): readonly [{
readonly CollectionProvider: {
(props: CollectionContextValue<TItemElement, TItemData> & {
children: React.ReactNode;
}): React.JSX.Element;
displayName: string;
};
readonly CollectionSlot: React.NamedExoticComponent<CollectionProps & React.RefAttributes<HTMLElement>>;
readonly CollectionItemSlot: React.NamedExoticComponent<React.PropsWithoutRef<SlotProps & TItemData & {
children: React.ReactNode;
}> & React.RefAttributes<TItemElement>>;
}, <TItemElement_1 extends HTMLElement, TItemData_1 = {}>({ collectionRef, itemMap, }: CollectionContextValue<TItemElement_1, TItemData_1>) => {
getItems: () => CollectionItem<TItemElement_1, TItemData_1>[];
}];
/**
* @see https://github.com/radix-ui/primitives/blob/main/packages/react/context/src/createContext.tsx

@@ -32,2 +71,30 @@ */

/**
* @see https://github.com/radix-ui/primitives/blob/main/packages/react/primitive/src/Primitive.tsx
*/
type IntrinsicElementsKeys = keyof React.JSX.IntrinsicElements;
type PrimitivePropsWithRef<E extends IntrinsicElementsKeys> = Omit<React.JSX.IntrinsicElements[E], "ref"> & {
asChild?: boolean;
ref?: React.Ref<React.ElementRef<E>>;
};
type PrimitiveForwardRefComponent<E extends IntrinsicElementsKeys> = React.ForwardRefExoticComponent<PrimitivePropsWithRef<E>>;
type Primitives = {
[E in IntrinsicElementsKeys]: PrimitiveForwardRefComponent<E>;
};
declare const Primitive: Primitives;
/**
* Flush custom event dispatch for React 18 batching
*/
declare function dispatchDiscreteCustomEvent<E extends CustomEvent>(target: E["target"], event: E): void;
interface PortalProps extends React.ComponentPropsWithoutRef<typeof Primitive.div> {
/**
* The container to mount the portal into.
* @default globalThis.document?.body
*/
container?: HTMLElement | DocumentFragment | null;
}
declare const Portal: React.ForwardRefExoticComponent<PortalProps & React.RefAttributes<HTMLDivElement>>;
/**
* @see https://github.com/radix-ui/primitives/blob/main/packages/react/presence/src/Presence.tsx

@@ -63,2 +130,137 @@ */

type Direction = "ltr" | "rtl";
type Orientation = "horizontal" | "vertical";
type Side = "top" | "right" | "bottom" | "left";
type Align = "start" | "center" | "end";
type ProgressState = "indeterminate" | "complete" | "loading";
type HighlightingDirection = "next" | "prev" | "first" | "last" | "selected";
interface UseAnchorPositionerProps {
/** Whether the popover is open. */
open: boolean;
/** Event handler called when the popover is opened or closed. */
onOpenChange: (open: boolean) => void;
/**
* Reference to the anchor element.
* Can be either a VirtualElement or React ref to an HTMLElement element.
*/
anchorRef?: React.RefObject<HTMLElement | null> | VirtualElement | null;
/**
* The preferred placement of the popover relative to its anchor element.
* If there is not enough space, it will be adjusted automatically.
* - 'top': Position the popover above the anchor
* - 'right': Position the popover to the right of the anchor
* - 'bottom': Position the popover below the anchor
* - 'left': Position the popover to the left of the anchor
* @default "bottom"
*/
side?: Side;
/**
* The distance in pixels from the anchor element to the popover.
* This creates a gap between the anchor and popover.
* @default 4
*/
sideOffset?: number;
/**
* The alignment of the popover relative to its anchor element.
* - 'start': Align with the start edge of the anchor
* - 'center': Center align with the anchor
* - 'end': Align with the end edge of the anchor
* @default "start"
*/
align?: Align;
/**
* The distance in pixels from the aligned edge when using align.
* Allows the popover to be offset from its default aligned position.
* @default 0
*/
alignOffset?: number;
/**
* The element or elements that constrain where the popover can be positioned.
* By default, this is the viewport (browser window).
*/
collisionBoundary?: Boundary;
/**
* The amount of padding around the boundary edges for collision detection.
* This prevents the popover from touching the edges of its container.
* @default 0
*/
collisionPadding?: number | Partial<Record<Side, number>>;
/**
* The padding between the arrow element and the popover edges.
* Prevents the arrow from reaching the very edge of the popover.
* @default 0
*/
arrowPadding?: number;
/**
* Controls how the popover responds to scroll events.
* - 'partial': Allows partial visibility when scrolling
* - 'always': Maintains full visibility by shifting position
* @default "partial"
*/
sticky?: "partial" | "always";
/**
* The positioning strategy to use.
* - 'absolute': Position relative to closest positioned ancestor
* - 'fixed': Position relative to viewport
* @default "absolute"
*/
strategy?: Strategy;
/**
* Whether the popover should automatically adjust its placement to stay in view.
* When enabled, changes position when there's not enough space in the current placement.
* @default true
*/
avoidCollisions?: boolean;
/**
* Whether to disable the floating pointer/indicator.
* When true, the pointer will not be rendered and pointer middleware will not be added.
* @default false
*/
disableArrow?: boolean;
/**
* Whether the popover should be constrained to the viewport dimensions.
* When true, the popover will not exceed the browser window width/height.
* @default false
*/
fitViewport?: boolean;
/**
* Whether the popover should be mounted in the DOM even when closed.
* Useful for animations or when you need to measure the popover before displaying it.
* @default false
*/
forceMount?: boolean;
/**
* Whether the popover should be hidden when it would be positioned outside its boundary.
* Useful for preventing partially visible popovers.
* @default false
*/
hideWhenDetached?: boolean;
/**
* Whether the popover should track the anchor element's position changes.
* When true, updates position on scroll and resize events.
* @default true
*/
trackAnchor?: boolean;
}
type AnchorPositionerProps = Omit<UseAnchorPositionerProps, "open" | "onOpenChange" | "anchorRef" | "disableArrow">;
interface UseAnchorPositionerReturn {
refs: UseFloatingReturn["refs"];
floatingStyles: React.CSSProperties;
placement: Placement;
isPositioned: boolean;
middlewareData: UseFloatingReturn["middlewareData"];
elements: UseFloatingReturn["elements"];
update: () => void;
context: FloatingContext;
getFloatingProps: (floatingProps?: React.HTMLAttributes<HTMLElement>) => Record<string, unknown>;
arrowStyles: React.CSSProperties;
onArrowChange: (arrow: HTMLElement | null) => void;
side: Side;
align: Align;
arrowDisplaced: boolean;
anchorHidden: boolean;
}
declare function useAnchorPositioner({ open, onOpenChange, anchorRef, side, sideOffset, align, alignOffset, collisionBoundary, collisionPadding, arrowPadding, sticky, strategy, avoidCollisions, disableArrow, fitViewport, forceMount, hideWhenDetached, trackAnchor, }: UseAnchorPositionerProps): UseAnchorPositionerReturn;
/**

@@ -73,12 +275,2 @@ * @see https://github.com/radix-ui/primitives/blob/main/packages/react/use-callback-ref/src/useCallbackRef.tsx

interface CollectionItem<TElement extends HTMLElement> {
ref: TElement;
disabled: boolean;
value: string;
label?: string;
}
interface CollectionContextValue<TElement extends HTMLElement> {
collectionRef: React.RefObject<TElement | null>;
itemMap: Map<React.RefObject<TElement>, CollectionItem<TElement>>;
}
interface UseCollectionParams<TElement extends HTMLElement> {

@@ -92,4 +284,2 @@ ref: React.RefObject<TElement | null>;

};
declare function useCollectionItem<TElement extends HTMLElement>(ref: React.RefObject<TElement>, context: CollectionContextValue<TElement>, disabled: boolean, value: string, label?: string): void;
declare function getItem<TElement extends HTMLElement>(item: TElement, context: CollectionContextValue<TElement>): CollectionItem<TElement> | null;
declare function getSortedItems<TElement extends HTMLElement>(items: TElement[], value?: string[]): TElement[];

@@ -108,8 +298,2 @@

type Direction = "ltr" | "rtl";
type Orientation = "horizontal" | "vertical";
type Side = "top" | "right" | "bottom" | "left";
type Align = "start" | "center" | "end";
type ProgressState = "indeterminate" | "complete" | "loading";
declare function useDirection(dirProp?: Direction): Direction;

@@ -133,3 +317,3 @@

*/
onDismiss: (event?: Event) => void | Promise<void>;
onDismiss: (event?: FocusOutsideEvent | KeyboardEvent) => void | Promise<void>;
/** References to elements that should not trigger dismissal when clicked. */

@@ -178,3 +362,3 @@ refs: Array<React.RefObject<Element | null>>;

/**
* Delay in ms before adding the mouseup listener.
* Delay in ms before adding event listeners.
* @default 0

@@ -194,10 +378,13 @@ */

}
declare function useDismiss(params: UseDismissParameters): void;
declare function useDismiss(params: UseDismissParameters): {
onPointerDownCapture: () => void;
onPointerUpCapture: () => void;
};
interface UseEscapeKeydownParams {
ownerDocument: Document;
document: Document;
onEscapeKeyDown: (event: KeyboardEvent) => void;
enabled?: boolean;
}
declare function useEscapeKeydown({ ownerDocument, onEscapeKeyDown, enabled, }: UseEscapeKeydownParams): void;
declare function useEscapeKeydown({ document, onEscapeKeyDown, enabled, }: UseEscapeKeydownParams): void;

@@ -243,9 +430,20 @@ /**

interface Filter {
startsWith(string: string, substring: string): boolean;
endsWith(string: string, substring: string): boolean;
contains(string: string, substring: string): boolean;
fuzzy(string: string, substring: string): boolean;
interface UseFilterOptions extends Intl.CollatorOptions {
/**
* Whether to match strings with gaps between words.
* @default false
*/
gapMatch?: boolean;
/**
* The sensitivity of the collator.
* @default "base"
*/
sensitivity?: Intl.CollatorOptions["sensitivity"];
}
declare function useFilter(options?: Intl.CollatorOptions): Filter;
declare function useFilter(options?: UseFilterOptions): {
startsWith: (string: string, substring: string) => boolean;
endsWith: (string: string, substring: string) => boolean;
contains: (string: string, substring: string) => boolean;
fuzzy: (string: string, pattern: string) => boolean;
};

@@ -278,2 +476,3 @@ /**

* A hook to handle form reset events.
* Can be triggered by onReset callback or by form reset event.
*/

@@ -287,3 +486,3 @@ declare function useFormReset<T>({ form, defaultValue, onReset, }: UseFormResetParams<T>): void;

declare const useIsomorphicLayoutEffect: typeof React.useEffect;
declare const useIsomorphicLayoutEffect: typeof React.useLayoutEffect;

@@ -331,4 +530,13 @@ /**

interface ScrollLockOptions {
/** The element to lock the scroll of. */
referenceElement?: HTMLElement | null;
/**
* Whether to lock the scroll.
* @default false
*/
enabled?: boolean;
/**
* Whether to allow pinch zoom in Safari.
* @default window.visualViewport?.scale !== 1
*/
allowPinchZoom?: boolean;

@@ -346,10 +554,7 @@ }

type Machine<S> = {
[k: string]: {
[k: string]: S;
};
};
type MachineState<T> = keyof T;
type UnionToIntersection<T> = (T extends unknown ? (x: T) => unknown : never) extends (x: infer R) => unknown ? R : never;
declare function useStateMachine<M>(initialState: MachineState<M>, machine: M & Machine<MachineState<M>>): [keyof M, React.ActionDispatch<[event: keyof UnionToIntersection<M[keyof M]>]>];
interface StateMachineConfig<TState extends string, TEvent extends string> {
initial: TState;
states: Record<TState, Partial<Record<TEvent, TState>>>;
}
declare function useStateMachine<TState extends string, TEvent extends string>(config: StateMachineConfig<TState, TEvent>): readonly [TState, (event: TEvent) => void];

@@ -412,3 +617,3 @@ declare function wrapArray<T>(array: T[], startIndex: number): (T | undefined)[];

declare function isIOS(): boolean | undefined;
declare function isPinchZoomActive(): boolean;
declare function isPinchZoomActive(win?: Window): boolean;
declare function getPlatform(): string | undefined;

@@ -420,2 +625,4 @@ declare function testPlatform(re: RegExp): boolean | undefined;

export { type Align, BubbleInput, type CollectionContextValue, type CollectionItem, DATA_DISMISSABLE_LAYER_ATTR, DATA_DISMISSABLE_LAYER_STYLE_ATTR, DATA_ITEM_ATTR, DATA_VALUE_ATTR, type Direction, type Filter, type FocusOutsideEvent, type ForwardRefComponent, type Orientation, type PointerDownOutsideEvent, Presence, type PresenceProps, type ProgressState, type Side, VAR_ANCHOR_HEIGHT, VAR_ANCHOR_WIDTH, VAR_AVAILABLE_HEIGHT, VAR_AVAILABLE_WIDTH, VAR_TRANSFORM_ORIGIN, composeEventHandlers, composeRefs, createContext, findNextItem, forwardRef, getItem, getOwnerDocument, getOwnerWindow, getPlatform, getProgressState, getSortedItems, isFirefox, isIOS, isIPad, isIPhone, isMac, isMobileFirefox, isPinchZoomActive, isSafari, testPlatform, useAnchor, useCallbackRef, useCollection, useCollectionItem, useComposedRefs, useControllableState, useDirection, useDismiss, useEscapeKeydown, useEvent, useEventCallback, useFilter, useFormControl, useFormReset, useId, useIsomorphicLayoutEffect, useLayoutEffect, useMounted, usePrevious, useProgress, useScrollLock, useSize, useStateMachine, useTypeahead, wrapArray };
declare function compareNodePosition(a: Node, b: Node): 0 | 1 | -1;
export { type Align, type AnchorPositionerProps, BubbleInput, type CollectionItem, type CollectionItemMap, type CollectionProps, DATA_DISMISSABLE_LAYER_ATTR, DATA_DISMISSABLE_LAYER_STYLE_ATTR, DATA_ITEM_ATTR, DATA_VALUE_ATTR, type Direction, type FocusOutsideEvent, type ForwardRefComponent, type HighlightingDirection, type Orientation, type PointerDownOutsideEvent, Portal, type PortalProps, Presence, type PresenceProps, Primitive, type PrimitivePropsWithRef, type ProgressState, type Side, Slot, type SlotProps, Slottable, VAR_ANCHOR_HEIGHT, VAR_ANCHOR_WIDTH, VAR_AVAILABLE_HEIGHT, VAR_AVAILABLE_WIDTH, VAR_TRANSFORM_ORIGIN, compareNodePosition, composeEventHandlers, composeRefs, createCollection, createContext, dispatchDiscreteCustomEvent, findNextItem, forwardRef, getOwnerDocument, getOwnerWindow, getPlatform, getProgressState, getSortedItems, isFirefox, isIOS, isIPad, isIPhone, isMac, isMobileFirefox, isPinchZoomActive, isSafari, testPlatform, useAnchor, useAnchorPositioner, useCallbackRef, useCollection, useComposedRefs, useControllableState, useDirection, useDismiss, useEscapeKeydown, useEvent, useEventCallback, useFilter, useFormControl, useFormReset, useId, useIsomorphicLayoutEffect, useLayoutEffect, useMounted, usePrevious, useProgress, useScrollLock, useSize, useStateMachine, useTypeahead, wrapArray };
import * as React from 'react';
import { VirtualElement, Boundary, Strategy, UseFloatingReturn, Placement, FloatingContext } from '@floating-ui/react';

@@ -14,2 +15,40 @@ type InputValue = string[] | string;

/**
* @see https://github.com/radix-ui/primitives/blob/main/packages/react/slot/src/Slot.tsx
*/
interface SlotProps extends React.HTMLAttributes<HTMLElement> {
children?: React.ReactNode;
}
declare const Slot: React.ForwardRefExoticComponent<SlotProps & React.RefAttributes<HTMLElement>>;
interface SlottableProps {
children: React.ReactNode;
}
declare const Slottable: React.NamedExoticComponent<SlottableProps>;
type CollectionItem<TItemElement extends HTMLElement, TItemData = {}> = {
ref: React.RefObject<TItemElement | null>;
} & TItemData;
type CollectionItemMap<TItemElement extends HTMLElement, TItemData = {}> = Map<React.RefObject<TItemElement | null>, CollectionItem<TItemElement, TItemData>>;
interface CollectionContextValue<TItemElement extends HTMLElement, TItemData = {}> {
collectionRef: React.RefObject<TItemElement | null>;
itemMap: CollectionItemMap<TItemElement, TItemData>;
}
interface CollectionProps extends SlotProps {
}
declare function createCollection<TItemElement extends HTMLElement, TItemData = {}>(name: string): readonly [{
readonly CollectionProvider: {
(props: CollectionContextValue<TItemElement, TItemData> & {
children: React.ReactNode;
}): React.JSX.Element;
displayName: string;
};
readonly CollectionSlot: React.NamedExoticComponent<CollectionProps & React.RefAttributes<HTMLElement>>;
readonly CollectionItemSlot: React.NamedExoticComponent<React.PropsWithoutRef<SlotProps & TItemData & {
children: React.ReactNode;
}> & React.RefAttributes<TItemElement>>;
}, <TItemElement_1 extends HTMLElement, TItemData_1 = {}>({ collectionRef, itemMap, }: CollectionContextValue<TItemElement_1, TItemData_1>) => {
getItems: () => CollectionItem<TItemElement_1, TItemData_1>[];
}];
/**
* @see https://github.com/radix-ui/primitives/blob/main/packages/react/context/src/createContext.tsx

@@ -32,2 +71,30 @@ */

/**
* @see https://github.com/radix-ui/primitives/blob/main/packages/react/primitive/src/Primitive.tsx
*/
type IntrinsicElementsKeys = keyof React.JSX.IntrinsicElements;
type PrimitivePropsWithRef<E extends IntrinsicElementsKeys> = Omit<React.JSX.IntrinsicElements[E], "ref"> & {
asChild?: boolean;
ref?: React.Ref<React.ElementRef<E>>;
};
type PrimitiveForwardRefComponent<E extends IntrinsicElementsKeys> = React.ForwardRefExoticComponent<PrimitivePropsWithRef<E>>;
type Primitives = {
[E in IntrinsicElementsKeys]: PrimitiveForwardRefComponent<E>;
};
declare const Primitive: Primitives;
/**
* Flush custom event dispatch for React 18 batching
*/
declare function dispatchDiscreteCustomEvent<E extends CustomEvent>(target: E["target"], event: E): void;
interface PortalProps extends React.ComponentPropsWithoutRef<typeof Primitive.div> {
/**
* The container to mount the portal into.
* @default globalThis.document?.body
*/
container?: HTMLElement | DocumentFragment | null;
}
declare const Portal: React.ForwardRefExoticComponent<PortalProps & React.RefAttributes<HTMLDivElement>>;
/**
* @see https://github.com/radix-ui/primitives/blob/main/packages/react/presence/src/Presence.tsx

@@ -63,2 +130,137 @@ */

type Direction = "ltr" | "rtl";
type Orientation = "horizontal" | "vertical";
type Side = "top" | "right" | "bottom" | "left";
type Align = "start" | "center" | "end";
type ProgressState = "indeterminate" | "complete" | "loading";
type HighlightingDirection = "next" | "prev" | "first" | "last" | "selected";
interface UseAnchorPositionerProps {
/** Whether the popover is open. */
open: boolean;
/** Event handler called when the popover is opened or closed. */
onOpenChange: (open: boolean) => void;
/**
* Reference to the anchor element.
* Can be either a VirtualElement or React ref to an HTMLElement element.
*/
anchorRef?: React.RefObject<HTMLElement | null> | VirtualElement | null;
/**
* The preferred placement of the popover relative to its anchor element.
* If there is not enough space, it will be adjusted automatically.
* - 'top': Position the popover above the anchor
* - 'right': Position the popover to the right of the anchor
* - 'bottom': Position the popover below the anchor
* - 'left': Position the popover to the left of the anchor
* @default "bottom"
*/
side?: Side;
/**
* The distance in pixels from the anchor element to the popover.
* This creates a gap between the anchor and popover.
* @default 4
*/
sideOffset?: number;
/**
* The alignment of the popover relative to its anchor element.
* - 'start': Align with the start edge of the anchor
* - 'center': Center align with the anchor
* - 'end': Align with the end edge of the anchor
* @default "start"
*/
align?: Align;
/**
* The distance in pixels from the aligned edge when using align.
* Allows the popover to be offset from its default aligned position.
* @default 0
*/
alignOffset?: number;
/**
* The element or elements that constrain where the popover can be positioned.
* By default, this is the viewport (browser window).
*/
collisionBoundary?: Boundary;
/**
* The amount of padding around the boundary edges for collision detection.
* This prevents the popover from touching the edges of its container.
* @default 0
*/
collisionPadding?: number | Partial<Record<Side, number>>;
/**
* The padding between the arrow element and the popover edges.
* Prevents the arrow from reaching the very edge of the popover.
* @default 0
*/
arrowPadding?: number;
/**
* Controls how the popover responds to scroll events.
* - 'partial': Allows partial visibility when scrolling
* - 'always': Maintains full visibility by shifting position
* @default "partial"
*/
sticky?: "partial" | "always";
/**
* The positioning strategy to use.
* - 'absolute': Position relative to closest positioned ancestor
* - 'fixed': Position relative to viewport
* @default "absolute"
*/
strategy?: Strategy;
/**
* Whether the popover should automatically adjust its placement to stay in view.
* When enabled, changes position when there's not enough space in the current placement.
* @default true
*/
avoidCollisions?: boolean;
/**
* Whether to disable the floating pointer/indicator.
* When true, the pointer will not be rendered and pointer middleware will not be added.
* @default false
*/
disableArrow?: boolean;
/**
* Whether the popover should be constrained to the viewport dimensions.
* When true, the popover will not exceed the browser window width/height.
* @default false
*/
fitViewport?: boolean;
/**
* Whether the popover should be mounted in the DOM even when closed.
* Useful for animations or when you need to measure the popover before displaying it.
* @default false
*/
forceMount?: boolean;
/**
* Whether the popover should be hidden when it would be positioned outside its boundary.
* Useful for preventing partially visible popovers.
* @default false
*/
hideWhenDetached?: boolean;
/**
* Whether the popover should track the anchor element's position changes.
* When true, updates position on scroll and resize events.
* @default true
*/
trackAnchor?: boolean;
}
type AnchorPositionerProps = Omit<UseAnchorPositionerProps, "open" | "onOpenChange" | "anchorRef" | "disableArrow">;
interface UseAnchorPositionerReturn {
refs: UseFloatingReturn["refs"];
floatingStyles: React.CSSProperties;
placement: Placement;
isPositioned: boolean;
middlewareData: UseFloatingReturn["middlewareData"];
elements: UseFloatingReturn["elements"];
update: () => void;
context: FloatingContext;
getFloatingProps: (floatingProps?: React.HTMLAttributes<HTMLElement>) => Record<string, unknown>;
arrowStyles: React.CSSProperties;
onArrowChange: (arrow: HTMLElement | null) => void;
side: Side;
align: Align;
arrowDisplaced: boolean;
anchorHidden: boolean;
}
declare function useAnchorPositioner({ open, onOpenChange, anchorRef, side, sideOffset, align, alignOffset, collisionBoundary, collisionPadding, arrowPadding, sticky, strategy, avoidCollisions, disableArrow, fitViewport, forceMount, hideWhenDetached, trackAnchor, }: UseAnchorPositionerProps): UseAnchorPositionerReturn;
/**

@@ -73,12 +275,2 @@ * @see https://github.com/radix-ui/primitives/blob/main/packages/react/use-callback-ref/src/useCallbackRef.tsx

interface CollectionItem<TElement extends HTMLElement> {
ref: TElement;
disabled: boolean;
value: string;
label?: string;
}
interface CollectionContextValue<TElement extends HTMLElement> {
collectionRef: React.RefObject<TElement | null>;
itemMap: Map<React.RefObject<TElement>, CollectionItem<TElement>>;
}
interface UseCollectionParams<TElement extends HTMLElement> {

@@ -92,4 +284,2 @@ ref: React.RefObject<TElement | null>;

};
declare function useCollectionItem<TElement extends HTMLElement>(ref: React.RefObject<TElement>, context: CollectionContextValue<TElement>, disabled: boolean, value: string, label?: string): void;
declare function getItem<TElement extends HTMLElement>(item: TElement, context: CollectionContextValue<TElement>): CollectionItem<TElement> | null;
declare function getSortedItems<TElement extends HTMLElement>(items: TElement[], value?: string[]): TElement[];

@@ -108,8 +298,2 @@

type Direction = "ltr" | "rtl";
type Orientation = "horizontal" | "vertical";
type Side = "top" | "right" | "bottom" | "left";
type Align = "start" | "center" | "end";
type ProgressState = "indeterminate" | "complete" | "loading";
declare function useDirection(dirProp?: Direction): Direction;

@@ -133,3 +317,3 @@

*/
onDismiss: (event?: Event) => void | Promise<void>;
onDismiss: (event?: FocusOutsideEvent | KeyboardEvent) => void | Promise<void>;
/** References to elements that should not trigger dismissal when clicked. */

@@ -178,3 +362,3 @@ refs: Array<React.RefObject<Element | null>>;

/**
* Delay in ms before adding the mouseup listener.
* Delay in ms before adding event listeners.
* @default 0

@@ -194,10 +378,13 @@ */

}
declare function useDismiss(params: UseDismissParameters): void;
declare function useDismiss(params: UseDismissParameters): {
onPointerDownCapture: () => void;
onPointerUpCapture: () => void;
};
interface UseEscapeKeydownParams {
ownerDocument: Document;
document: Document;
onEscapeKeyDown: (event: KeyboardEvent) => void;
enabled?: boolean;
}
declare function useEscapeKeydown({ ownerDocument, onEscapeKeyDown, enabled, }: UseEscapeKeydownParams): void;
declare function useEscapeKeydown({ document, onEscapeKeyDown, enabled, }: UseEscapeKeydownParams): void;

@@ -243,9 +430,20 @@ /**

interface Filter {
startsWith(string: string, substring: string): boolean;
endsWith(string: string, substring: string): boolean;
contains(string: string, substring: string): boolean;
fuzzy(string: string, substring: string): boolean;
interface UseFilterOptions extends Intl.CollatorOptions {
/**
* Whether to match strings with gaps between words.
* @default false
*/
gapMatch?: boolean;
/**
* The sensitivity of the collator.
* @default "base"
*/
sensitivity?: Intl.CollatorOptions["sensitivity"];
}
declare function useFilter(options?: Intl.CollatorOptions): Filter;
declare function useFilter(options?: UseFilterOptions): {
startsWith: (string: string, substring: string) => boolean;
endsWith: (string: string, substring: string) => boolean;
contains: (string: string, substring: string) => boolean;
fuzzy: (string: string, pattern: string) => boolean;
};

@@ -278,2 +476,3 @@ /**

* A hook to handle form reset events.
* Can be triggered by onReset callback or by form reset event.
*/

@@ -287,3 +486,3 @@ declare function useFormReset<T>({ form, defaultValue, onReset, }: UseFormResetParams<T>): void;

declare const useIsomorphicLayoutEffect: typeof React.useEffect;
declare const useIsomorphicLayoutEffect: typeof React.useLayoutEffect;

@@ -331,4 +530,13 @@ /**

interface ScrollLockOptions {
/** The element to lock the scroll of. */
referenceElement?: HTMLElement | null;
/**
* Whether to lock the scroll.
* @default false
*/
enabled?: boolean;
/**
* Whether to allow pinch zoom in Safari.
* @default window.visualViewport?.scale !== 1
*/
allowPinchZoom?: boolean;

@@ -346,10 +554,7 @@ }

type Machine<S> = {
[k: string]: {
[k: string]: S;
};
};
type MachineState<T> = keyof T;
type UnionToIntersection<T> = (T extends unknown ? (x: T) => unknown : never) extends (x: infer R) => unknown ? R : never;
declare function useStateMachine<M>(initialState: MachineState<M>, machine: M & Machine<MachineState<M>>): [keyof M, React.ActionDispatch<[event: keyof UnionToIntersection<M[keyof M]>]>];
interface StateMachineConfig<TState extends string, TEvent extends string> {
initial: TState;
states: Record<TState, Partial<Record<TEvent, TState>>>;
}
declare function useStateMachine<TState extends string, TEvent extends string>(config: StateMachineConfig<TState, TEvent>): readonly [TState, (event: TEvent) => void];

@@ -412,3 +617,3 @@ declare function wrapArray<T>(array: T[], startIndex: number): (T | undefined)[];

declare function isIOS(): boolean | undefined;
declare function isPinchZoomActive(): boolean;
declare function isPinchZoomActive(win?: Window): boolean;
declare function getPlatform(): string | undefined;

@@ -420,2 +625,4 @@ declare function testPlatform(re: RegExp): boolean | undefined;

export { type Align, BubbleInput, type CollectionContextValue, type CollectionItem, DATA_DISMISSABLE_LAYER_ATTR, DATA_DISMISSABLE_LAYER_STYLE_ATTR, DATA_ITEM_ATTR, DATA_VALUE_ATTR, type Direction, type Filter, type FocusOutsideEvent, type ForwardRefComponent, type Orientation, type PointerDownOutsideEvent, Presence, type PresenceProps, type ProgressState, type Side, VAR_ANCHOR_HEIGHT, VAR_ANCHOR_WIDTH, VAR_AVAILABLE_HEIGHT, VAR_AVAILABLE_WIDTH, VAR_TRANSFORM_ORIGIN, composeEventHandlers, composeRefs, createContext, findNextItem, forwardRef, getItem, getOwnerDocument, getOwnerWindow, getPlatform, getProgressState, getSortedItems, isFirefox, isIOS, isIPad, isIPhone, isMac, isMobileFirefox, isPinchZoomActive, isSafari, testPlatform, useAnchor, useCallbackRef, useCollection, useCollectionItem, useComposedRefs, useControllableState, useDirection, useDismiss, useEscapeKeydown, useEvent, useEventCallback, useFilter, useFormControl, useFormReset, useId, useIsomorphicLayoutEffect, useLayoutEffect, useMounted, usePrevious, useProgress, useScrollLock, useSize, useStateMachine, useTypeahead, wrapArray };
declare function compareNodePosition(a: Node, b: Node): 0 | 1 | -1;
export { type Align, type AnchorPositionerProps, BubbleInput, type CollectionItem, type CollectionItemMap, type CollectionProps, DATA_DISMISSABLE_LAYER_ATTR, DATA_DISMISSABLE_LAYER_STYLE_ATTR, DATA_ITEM_ATTR, DATA_VALUE_ATTR, type Direction, type FocusOutsideEvent, type ForwardRefComponent, type HighlightingDirection, type Orientation, type PointerDownOutsideEvent, Portal, type PortalProps, Presence, type PresenceProps, Primitive, type PrimitivePropsWithRef, type ProgressState, type Side, Slot, type SlotProps, Slottable, VAR_ANCHOR_HEIGHT, VAR_ANCHOR_WIDTH, VAR_AVAILABLE_HEIGHT, VAR_AVAILABLE_WIDTH, VAR_TRANSFORM_ORIGIN, compareNodePosition, composeEventHandlers, composeRefs, createCollection, createContext, dispatchDiscreteCustomEvent, findNextItem, forwardRef, getOwnerDocument, getOwnerWindow, getPlatform, getProgressState, getSortedItems, isFirefox, isIOS, isIPad, isIPhone, isMac, isMobileFirefox, isPinchZoomActive, isSafari, testPlatform, useAnchor, useAnchorPositioner, useCallbackRef, useCollection, useComposedRefs, useControllableState, useDirection, useDismiss, useEscapeKeydown, useEvent, useEventCallback, useFilter, useFormControl, useFormReset, useId, useIsomorphicLayoutEffect, useLayoutEffect, useMounted, usePrevious, useProgress, useScrollLock, useSize, useStateMachine, useTypeahead, wrapArray };
+1013
-334
'use strict';
var React26 = require('react');
var React27 = require('react');
var react = require('@floating-ui/react');
var ReactDOM = require('react-dom');

@@ -23,18 +25,19 @@ function _interopNamespace(e) {

var React26__namespace = /*#__PURE__*/_interopNamespace(React26);
var React27__namespace = /*#__PURE__*/_interopNamespace(React27);
var ReactDOM__namespace = /*#__PURE__*/_interopNamespace(ReactDOM);
// src/components/bubble-input.tsx
function useAnchor() {
const anchorRef = React26__namespace.useRef(null);
const [hasAnchor, setHasAnchor] = React26__namespace.useState(false);
const onAnchorChange = React26__namespace.useCallback((node) => {
const anchorRef = React27__namespace.useRef(null);
const [hasAnchor, setHasAnchor] = React27__namespace.useState(false);
const onAnchorChange = React27__namespace.useCallback((node) => {
anchorRef.current = node;
}, []);
const onHasAnchorChange = React26__namespace.useCallback((value) => {
const onHasAnchorChange = React27__namespace.useCallback((value) => {
setHasAnchor(value);
}, []);
const onAnchorAdd = React26__namespace.useCallback(() => {
const onAnchorAdd = React27__namespace.useCallback(() => {
setHasAnchor(true);
}, []);
const onAnchorRemove = React26__namespace.useCallback(() => {
const onAnchorRemove = React27__namespace.useCallback(() => {
setHasAnchor(false);

@@ -51,12 +54,2 @@ }, []);

}
function useCallbackRef(callback) {
const callbackRef = React26__namespace.useRef(callback);
React26__namespace.useEffect(() => {
callbackRef.current = callback;
});
return React26__namespace.useMemo(
() => (...args) => callbackRef.current?.(...args),
[]
);
}

@@ -73,3 +66,281 @@ // src/constants.ts

var VAR_AVAILABLE_HEIGHT = "--dice-available-height";
var DirectionContext = React27__namespace.createContext(void 0);
function useDirection(dirProp) {
const contextDir = React27__namespace.useContext(DirectionContext);
return dirProp ?? contextDir ?? "ltr";
}
var useIsomorphicLayoutEffect = typeof window !== "undefined" ? React27__namespace.useLayoutEffect : React27__namespace.useEffect;
// src/hooks/use-anchor-positioner.ts
var LONGHAND_SIDES = {
top: "bottom",
right: "left",
bottom: "top",
left: "right"
};
var ARROW_TRANSFORMS = {
top: "translateY(100%)",
right: "translateY(50%) rotate(90deg) translateX(-50%)",
bottom: "rotate(180deg)",
left: "translateY(50%) rotate(-90deg) translateX(50%)"
};
function isValidNumber(value) {
return typeof value === "number" && !Number.isNaN(value) && Number.isFinite(value);
}
function useAnchorPositioner({
open,
onOpenChange,
anchorRef,
side = "bottom",
sideOffset = 4,
align = "start",
alignOffset = 0,
collisionBoundary,
collisionPadding = 0,
arrowPadding = 0,
sticky = "partial",
strategy = "absolute",
avoidCollisions = false,
disableArrow = false,
fitViewport = false,
forceMount = false,
hideWhenDetached = false,
trackAnchor = true
}) {
const direction = useDirection();
const [positionerArrow, setPositionerArrow] = React27__namespace.useState(null);
const rtlAlign = React27__namespace.useMemo(() => {
if (direction !== "rtl") return align;
return align === "start" ? "end" : align === "end" ? "start" : "center";
}, [align, direction]);
const placement = React27__namespace.useMemo(
() => `${side}-${rtlAlign}`,
[side, rtlAlign]
);
const baseMiddleware = React27__namespace.useMemo(
() => [
react.offset({
mainAxis: sideOffset,
alignmentAxis: alignOffset
}),
react.inline()
],
[sideOffset, alignOffset]
);
const collisionMiddleware = React27__namespace.useMemo(
() => avoidCollisions ? [
react.flip({
boundary: collisionBoundary,
padding: collisionPadding,
fallbackStrategy: sticky === "partial" ? "bestFit" : "initialPlacement"
}),
react.shift({
boundary: collisionBoundary,
padding: collisionPadding,
limiter: sticky === "partial" ? react.limitShift() : void 0
})
] : [],
[avoidCollisions, collisionBoundary, collisionPadding, sticky]
);
const sizeMiddleware = React27__namespace.useMemo(
() => [
react.size({
padding: collisionPadding,
apply({
elements: { floating },
rects: { reference },
availableWidth,
availableHeight
}) {
const styles = {
[VAR_AVAILABLE_WIDTH]: `${availableWidth}px`,
[VAR_AVAILABLE_HEIGHT]: `${availableHeight}px`,
[VAR_ANCHOR_WIDTH]: `${reference.width}px`,
[VAR_ANCHOR_HEIGHT]: `${reference.height}px`
};
for (const [key, value] of Object.entries(styles)) {
floating.style.setProperty(key, value);
}
if (fitViewport) {
Object.assign(floating.style, {
maxHeight: `${availableHeight}px`,
maxWidth: `${availableWidth}px`
});
}
}
})
],
[collisionPadding, fitViewport]
);
const arrowMiddleware = React27__namespace.useMemo(
() => !disableArrow && positionerArrow ? [
react.arrow({
element: positionerArrow,
padding: arrowPadding
})
] : [],
[disableArrow, positionerArrow, arrowPadding]
);
const middleware = React27__namespace.useMemo(
() => [
...baseMiddleware,
...collisionMiddleware,
...sizeMiddleware,
...hideWhenDetached ? [react.hide()] : [],
...arrowMiddleware
],
[
baseMiddleware,
collisionMiddleware,
sizeMiddleware,
hideWhenDetached,
arrowMiddleware
]
);
const autoUpdateOptions = React27__namespace.useMemo(
() => ({
ancestorScroll: trackAnchor,
ancestorResize: true,
elementResize: trackAnchor && typeof ResizeObserver !== "undefined",
layoutShift: trackAnchor && typeof IntersectionObserver !== "undefined"
}),
[trackAnchor]
);
const {
x,
y,
refs,
strategy: floatingStrategy,
context,
placement: floatingPlacement,
middlewareData,
isPositioned,
update,
elements
} = react.useFloating({
open,
onOpenChange,
placement,
middleware,
whileElementsMounted: forceMount ? void 0 : (...args) => react.autoUpdate(...args, autoUpdateOptions),
strategy
});
useIsomorphicLayoutEffect(() => {
if (!open) return;
const isVirtualAnchor = anchorRef && "getBoundingClientRect" in anchorRef;
const anchor = isVirtualAnchor ? anchorRef : anchorRef?.current;
if (!anchor) return;
isVirtualAnchor ? refs.setPositionReference(anchor) : refs.setReference(anchor);
update();
}, [open, anchorRef, refs, update]);
React27__namespace.useEffect(() => {
if (forceMount && open && elements.reference && elements.floating) {
return react.autoUpdate(
elements.reference,
elements.floating,
update,
autoUpdateOptions
);
}
return void 0;
}, [forceMount, open, elements, update, autoUpdateOptions]);
const [placementSide = "bottom", placementAlign = "start"] = floatingPlacement.split("-");
const transformOrigin = React27__namespace.useMemo(() => {
const oppositeSide = LONGHAND_SIDES[placementSide];
const oppositeAlign = placementAlign === "end" ? "start" : placementAlign === "start" ? "end" : "center";
return `${oppositeAlign} ${oppositeSide}`;
}, [placementSide, placementAlign]);
const getFloatingProps = React27__namespace.useCallback(
(floatingProps = {}) => ({
...floatingProps,
"data-side": placementSide,
"data-align": placementAlign
}),
[placementSide, placementAlign]
);
const floatingStyles = React27__namespace.useMemo(() => {
const validY = isValidNumber(y) ? y : 0;
const validX = isValidNumber(x) ? x : 0;
return {
position: floatingStrategy,
top: validY,
left: validX,
[VAR_TRANSFORM_ORIGIN]: transformOrigin
};
}, [floatingStrategy, x, y, transformOrigin]);
const anchorHidden = !!middlewareData.hide?.referenceHidden;
const arrowDisplaced = disableArrow ? false : middlewareData.arrow?.centerOffset !== 0;
const arrowStyles = React27__namespace.useMemo(() => {
if (disableArrow) return {};
return {
position: "absolute",
top: middlewareData.arrow?.y,
left: middlewareData.arrow?.x,
[placementSide]: 0,
transformOrigin,
transform: ARROW_TRANSFORMS[placementSide]
};
}, [middlewareData.arrow, placementSide, transformOrigin, disableArrow]);
const positionerContext = React27__namespace.useMemo(
() => ({
refs,
floatingStyles,
placement: floatingPlacement,
isPositioned,
middlewareData,
elements,
update,
context,
getFloatingProps,
arrowStyles,
onArrowChange: disableArrow ? () => {
} : setPositionerArrow,
side: placementSide,
align: placementAlign,
arrowDisplaced,
anchorHidden
}),
[
refs,
floatingStyles,
floatingPlacement,
isPositioned,
middlewareData,
elements,
update,
context,
getFloatingProps,
arrowStyles,
placementSide,
placementAlign,
arrowDisplaced,
anchorHidden,
disableArrow
]
);
return positionerContext;
}
function useCallbackRef(callback) {
const callbackRef = React27__namespace.useRef(callback);
React27__namespace.useEffect(() => {
callbackRef.current = callback;
});
return React27__namespace.useMemo(
() => (...args) => callbackRef.current?.(...args),
[]
);
}
// src/lib/node.ts
function compareNodePosition(a, b) {
const position = a.compareDocumentPosition(b);
if (position & Node.DOCUMENT_POSITION_FOLLOWING || position & Node.DOCUMENT_POSITION_CONTAINED_BY) {
return -1;
}
if (position & Node.DOCUMENT_POSITION_PRECEDING || position & Node.DOCUMENT_POSITION_CONTAINS) {
return 1;
}
return 0;
}
// src/hooks/use-collection.ts

@@ -80,3 +351,3 @@ function useCollection({

}) {
const getItems = React26__namespace.useCallback(() => {
const getItems = React27__namespace.useCallback(() => {
const collectionNode = ref.current;

@@ -87,10 +358,5 @@ if (!collectionNode) return [];

);
const orderedItems = items.sort((a, b) => {
const aIndex = Number(a.getAttribute(attr));
const bIndex = Number(b.getAttribute(attr));
return aIndex - bIndex;
});
return orderedItems;
return items.sort(compareNodePosition);
}, [ref, attr]);
const getEnabledItems = React26__namespace.useCallback(() => {
const getEnabledItems = React27__namespace.useCallback(() => {
const items = getItems();

@@ -103,16 +369,2 @@ return items.filter(

}
function useCollectionItem(ref, context, disabled, value, label) {
React26__namespace.useEffect(() => {
context.itemMap.set(ref, { ref: ref.current, label, value, disabled });
return () => {
context.itemMap.delete(ref);
};
}, [ref, label, value, disabled, context.itemMap]);
}
function getItem(item, context) {
for (const [ref, data] of context.itemMap.entries()) {
if (ref.current === item) return data;
}
return null;
}
function getSortedItems(items, value) {

@@ -125,6 +377,7 @@ if (!value?.length) return items;

const bIndex = value.indexOf(bValue ?? "");
if (aIndex === -1 && bIndex === -1) return 0;
if (aIndex === -1 && bIndex === -1) return compareNodePosition(a, b);
if (aIndex === -1) return 1;
if (bIndex === -1) return -1;
return aIndex - bIndex;
if (aIndex !== bIndex) return aIndex - bIndex;
return compareNodePosition(a, b);
});

@@ -145,3 +398,3 @@ }

const handleChange = useCallbackRef(onChange);
const setValue = React26__namespace.useCallback(
const setValue = React27__namespace.useCallback(
(nextValue) => {

@@ -164,7 +417,7 @@ if (isControlled) {

}) {
const uncontrolledState = React26__namespace.useState(defaultProp);
const uncontrolledState = React27__namespace.useState(defaultProp);
const [value] = uncontrolledState;
const prevValueRef = React26__namespace.useRef(value);
const prevValueRef = React27__namespace.useRef(value);
const handleChange = useCallbackRef(onChange);
React26__namespace.useEffect(() => {
React27__namespace.useEffect(() => {
if (prevValueRef.current !== value) {

@@ -177,18 +430,13 @@ handleChange(value);

}
var DirectionContext = React26__namespace.createContext(void 0);
function useDirection(dirProp) {
const contextDir = React26__namespace.useContext(DirectionContext);
return dirProp ?? contextDir ?? "ltr";
}
// src/lib/dock.ts
function getOwnerDocument(node) {
return node?.ownerDocument ?? document;
return node?.ownerDocument ?? globalThis.document;
}
function getOwnerWindow(node) {
const doc = getOwnerDocument(node);
return doc?.defaultView ?? window;
return doc?.defaultView ?? globalThis.window;
}
function useEscapeKeydown({
ownerDocument,
document: document2,
onEscapeKeyDown,

@@ -198,3 +446,3 @@ enabled

const onEscapeKeyDownCallback = useCallbackRef(onEscapeKeyDown);
React26__namespace.useEffect(() => {
React27__namespace.useEffect(() => {
if (!enabled) return;

@@ -206,11 +454,10 @@ function onKeyDown(event) {

}
ownerDocument.addEventListener("keydown", onKeyDown, { capture: true });
return () => ownerDocument.removeEventListener("keydown", onKeyDown, {
document2.addEventListener("keydown", onKeyDown, { capture: true });
return () => document2.removeEventListener("keydown", onKeyDown, {
capture: true
});
}, [enabled, onEscapeKeyDownCallback, ownerDocument]);
}, [enabled, onEscapeKeyDownCallback, document2]);
}
// src/hooks/use-dismiss.ts
var SCROLL_DISTANCE_THRESHOLD = 5;
function useDismiss(params) {

@@ -231,24 +478,11 @@ const {

} = params;
const ownerDocument = getOwnerDocument(refs[0]?.current) ?? document;
const shouldTriggerEvents = React26__namespace.useRef(true);
const touchStartY = React26__namespace.useRef(null);
const ownerDocument = getOwnerDocument(refs[0]?.current);
const isPointerInsideReactTreeRef = React27__namespace.useRef(false);
const onClickRef = React27__namespace.useRef(() => {
});
useEscapeKeydown({
ownerDocument,
document: ownerDocument,
onEscapeKeyDown: (event) => {
if (onEscapeKeyDown && !event.defaultPrevented) {
onEscapeKeyDown(event);
}
},
enabled: enabled && !!onEscapeKeyDown && !!onDismiss
});
React26__namespace.useEffect(() => {
if (!enabled) return;
function onKeyDown(event) {
if (event.key === "Escape") {
onInteractOutside?.({
currentTarget: event.currentTarget,
target: event.target,
preventDefault: () => event.preventDefault(),
defaultPrevented: event.defaultPrevented
});
if (!event.defaultPrevented) {

@@ -258,59 +492,59 @@ onDismiss(event);

}
}
function onDismissWithTarget(event, target) {
const missingElement = refs.some((ref) => !ref.current);
if (missingElement) return;
const clickedInside = refs.some((ref) => ref.current?.contains(target));
if (!clickedInside && shouldTriggerEvents.current) {
const outsideEvent = {
currentTarget: event.currentTarget,
target,
preventDefault: () => event.preventDefault(),
defaultPrevented: event.defaultPrevented,
detail: event.detail
};
onPointerDownOutside?.(outsideEvent);
onInteractOutside?.(outsideEvent);
if (!event.defaultPrevented && !outsideEvent.defaultPrevented) {
onDismiss(event);
}
},
enabled: enabled && !!onDismiss && !!onEscapeKeyDown
});
const onPointerDownOutsideCallback = useCallbackRef(
(event) => {
onPointerDownOutside?.(event);
onInteractOutside?.(event);
if (!event.defaultPrevented) {
onDismiss(event);
}
}
);
const onFocusOutsideCallback = useCallbackRef((event) => {
onFocusOutside?.(event);
onInteractOutside?.(event);
if (!event.defaultPrevented) {
onDismiss(event);
}
});
React27__namespace.useEffect(() => {
if (!enabled) return;
function onPointerDown(event) {
const target = event.target;
if (preventScrollDismiss && event.pointerType === "touch") {
touchStartY.current = event.clientY;
return;
if (!target || isPointerInsideReactTreeRef.current) return;
const isInsideRefs = refs.some((ref) => ref.current?.contains(target));
if (isInsideRefs) return;
const outsideEvent = {
currentTarget: event.currentTarget,
target,
preventDefault: () => event.preventDefault(),
defaultPrevented: event.defaultPrevented,
detail: event.detail
};
if (event.pointerType === "touch" && preventScrollDismiss) {
if (!ownerDocument) return;
ownerDocument.removeEventListener("click", onClickRef.current);
onClickRef.current = () => onPointerDownOutsideCallback(outsideEvent);
ownerDocument.addEventListener("click", onClickRef.current, {
once: true
});
} else {
onPointerDownOutsideCallback(outsideEvent);
}
if (event.pointerType !== "touch") {
onDismissWithTarget(event, target);
}
}
function onPointerUp(event) {
function onFocusIn(event) {
const target = event.target;
if (preventScrollDismiss && event.pointerType === "touch" && touchStartY.current !== null) {
const deltaY = Math.abs(event.clientY - touchStartY.current);
touchStartY.current = null;
if (deltaY <= SCROLL_DISTANCE_THRESHOLD) {
onDismissWithTarget(event, target);
}
}
if (!target) return;
const isInsideRefs = refs.some((ref) => ref.current?.contains(target));
if (isInsideRefs) return;
const outsideEvent = {
currentTarget: event.currentTarget,
target,
preventDefault: () => event.preventDefault(),
defaultPrevented: event.defaultPrevented
};
onFocusOutsideCallback(outsideEvent);
}
function onFocusOut(event) {
const target = event.target;
const focusedInside = refs.some((ref) => ref.current?.contains(target));
if (!focusedInside && shouldTriggerEvents.current) {
const outsideEvent = {
currentTarget: event.currentTarget,
target,
preventDefault: () => event.preventDefault(),
defaultPrevented: event.defaultPrevented
};
onFocusOutside?.(outsideEvent);
onInteractOutside?.(outsideEvent);
if (!event.defaultPrevented && !outsideEvent.defaultPrevented) {
onDismissWithTarget(event, target);
}
}
}
if (disableOutsidePointerEvents) {

@@ -329,13 +563,10 @@ const elements = refs.map((ref) => ref.current).filter(Boolean);

const timeoutId = window.setTimeout(() => {
ownerDocument.addEventListener("keydown", onKeyDown);
ownerDocument.addEventListener("pointerdown", onPointerDown);
ownerDocument.addEventListener("pointerup", onPointerUp);
ownerDocument.addEventListener("focusout", onFocusOut);
ownerDocument.addEventListener("focusin", onFocusIn);
}, delayMs);
return () => {
window.clearTimeout(timeoutId);
ownerDocument.removeEventListener("keydown", onKeyDown);
ownerDocument.removeEventListener("pointerdown", onPointerDown);
ownerDocument.removeEventListener("pointerup", onPointerUp);
ownerDocument.removeEventListener("focusout", onFocusOut);
ownerDocument.removeEventListener("focusin", onFocusIn);
ownerDocument.removeEventListener("click", onClickRef.current);
if (disableOutsidePointerEvents) {

@@ -353,6 +584,4 @@ for (const ref of refs) {

refs,
onDismiss,
onPointerDownOutside,
onFocusOutside,
onInteractOutside,
onPointerDownOutsideCallback,
onFocusOutsideCallback,
disableOutsidePointerEvents,

@@ -365,9 +594,19 @@ preventScrollDismiss,

]);
return {
onPointerDownCapture: () => {
isPointerInsideReactTreeRef.current = true;
},
onPointerUpCapture: () => {
window.setTimeout(() => {
isPointerInsideReactTreeRef.current = false;
}, 0);
}
};
}
function useEventCallback(callback) {
const callbackRef = React26__namespace.useRef(callback);
React26__namespace.useLayoutEffect(() => {
const callbackRef = React27__namespace.useRef(callback);
React27__namespace.useLayoutEffect(() => {
callbackRef.current = callback;
});
return React26__namespace.useCallback((event, ...args) => {
return React27__namespace.useCallback((event, ...args) => {
const fn = callbackRef.current;

@@ -378,7 +617,7 @@ return fn(event, ...args);

function useEvent(callback) {
const callbackRef = React26__namespace.useRef(callback);
React26__namespace.useLayoutEffect(() => {
const callbackRef = React27__namespace.useRef(callback);
React27__namespace.useLayoutEffect(() => {
callbackRef.current = callback;
});
return React26__namespace.useCallback((...args) => {
return React27__namespace.useCallback((...args) => {
const fn = callbackRef.current;

@@ -388,3 +627,66 @@ return fn(...args);

}
var collatorCache = /* @__PURE__ */ new Map();
var LRUCache = class {
cache;
maxSize;
keyOrder;
constructor(maxSize) {
this.cache = /* @__PURE__ */ new Map();
this.maxSize = maxSize;
this.keyOrder = [];
}
get(key) {
const value = this.cache.get(key);
if (value !== void 0) {
const index = this.keyOrder.indexOf(key);
if (index > -1) {
this.keyOrder.splice(index, 1);
this.keyOrder.push(key);
}
}
return value;
}
set(key, value) {
if (this.cache.has(key)) {
this.cache.set(key, value);
const index = this.keyOrder.indexOf(key);
if (index > -1) {
this.keyOrder.splice(index, 1);
}
} else {
if (this.keyOrder.length >= this.maxSize) {
const lruKey = this.keyOrder.shift();
if (lruKey !== void 0) {
this.cache.delete(lruKey);
}
}
this.cache.set(key, value);
}
this.keyOrder.push(key);
}
clear() {
this.cache.clear();
this.keyOrder.length = 0;
}
get size() {
return this.cache.size;
}
};
var collatorCache = new LRUCache(10);
var normalizedCache = new LRUCache(1e3);
var SEPARATORS_PATTERN = /[-_\s./\\|:;,]+/g;
var UNWANTED_CHARS = /[^\p{L}\p{N}\s]/gu;
function normalizeWithGaps(str) {
if (!str) return "";
if (typeof str !== "string") return "";
const cached = normalizedCache.get(str);
if (cached !== void 0) return cached;
let normalized;
try {
normalized = str.toLowerCase().normalize("NFC").replace(UNWANTED_CHARS, " ").replace(SEPARATORS_PATTERN, " ").trim().replace(/\s+/g, "");
} catch (_err) {
normalized = str.toLowerCase().normalize("NFC").replace(/[^a-z0-9\s]/g, " ").trim().replace(/\s+/g, "");
}
normalizedCache.set(str, normalized);
return normalized;
}
function useFilter(options) {

@@ -394,6 +696,9 @@ const cacheKey = options ? Object.entries(options).sort((a, b) => a[0] < b[0] ? -1 : 1).join() : "";

if (!collator) {
collator = new Intl.Collator("en", options);
collator = new Intl.Collator("en", {
...options,
sensitivity: "base"
});
collatorCache.set(cacheKey, collator);
}
const startsWith = React26__namespace.useCallback(
const startsWith = React27__namespace.useCallback(
(string, substring) => {

@@ -403,2 +708,7 @@ if (substring.length === 0) {

}
if (options?.gapMatch) {
const normalizedString2 = normalizeWithGaps(string);
const normalizedSubstring2 = normalizeWithGaps(substring);
return normalizedString2.startsWith(normalizedSubstring2);
}
const normalizedString = string.normalize("NFC");

@@ -411,5 +721,5 @@ const normalizedSubstring = substring.normalize("NFC");

},
[collator]
[collator, options?.gapMatch]
);
const endsWith = React26__namespace.useCallback(
const endsWith = React27__namespace.useCallback(
(string, substring) => {

@@ -419,2 +729,7 @@ if (substring.length === 0) {

}
if (options?.gapMatch) {
const normalizedString2 = normalizeWithGaps(string);
const normalizedSubstring2 = normalizeWithGaps(substring);
return normalizedString2.endsWith(normalizedSubstring2);
}
const normalizedString = string.normalize("NFC");

@@ -427,5 +742,5 @@ const normalizedSubstring = substring.normalize("NFC");

},
[collator]
[collator, options?.gapMatch]
);
const contains = React26__namespace.useCallback(
const contains = React27__namespace.useCallback(
(string, substring) => {

@@ -435,2 +750,7 @@ if (substring.length === 0) {

}
if (options?.gapMatch) {
const normalizedString2 = normalizeWithGaps(string);
const normalizedSubstring2 = normalizeWithGaps(substring);
return normalizedString2.includes(normalizedSubstring2);
}
const normalizedString = string.normalize("NFC");

@@ -448,10 +768,23 @@ const normalizedSubstring = substring.normalize("NFC");

},
[collator]
[collator, options?.gapMatch]
);
const fuzzy = React26__namespace.useCallback(
const fuzzy = React27__namespace.useCallback(
(string, pattern) => {
if (pattern.length === 0) return true;
if (string.length === 0) return false;
const normalizedString = string.normalize("NFC").toLowerCase();
const normalizedPattern = pattern.normalize("NFC").toLowerCase();
if (options?.gapMatch) {
const normalizedString2 = normalizeWithGaps(string);
const normalizedPattern2 = normalizeWithGaps(pattern);
let patternIdx2 = 0;
let stringIdx2 = 0;
while (stringIdx2 < normalizedString2.length && patternIdx2 < normalizedPattern2.length) {
if (normalizedString2[stringIdx2] === normalizedPattern2[patternIdx2]) {
patternIdx2++;
}
stringIdx2++;
}
return patternIdx2 === normalizedPattern2.length;
}
const normalizedString = string.normalize("NFC");
const normalizedPattern = pattern.normalize("NFC");
let patternIdx = 0;

@@ -470,5 +803,5 @@ let stringIdx = 0;

},
[collator]
[collator, options?.gapMatch]
);
const memoizedFilter = React26__namespace.useMemo(
return React27__namespace.useMemo(
() => ({

@@ -482,6 +815,5 @@ startsWith,

);
return memoizedFilter;
}
function useFormControl(form) {
const [trigger, setTrigger] = React26__namespace.useState(null);
const [trigger, setTrigger] = React27__namespace.useState(null);
const isFormControl = trigger ? form || !!trigger.closest("form") : true;

@@ -496,3 +828,3 @@ return { isFormControl, trigger, onTriggerChange: setTrigger };

const onResetCallback = useCallbackRef(onReset);
React26__namespace.useEffect(() => {
React27__namespace.useEffect(() => {
if (!form) return;

@@ -508,13 +840,13 @@ function onFormReset() {

}
var useLayoutEffect3 = globalThis?.document ? React26__namespace.useLayoutEffect : () => {
var useLayoutEffect4 = globalThis?.document ? React27__namespace.useLayoutEffect : () => {
};
// src/hooks/use-id.ts
var useReactId = React26__namespace[" useId ".trim().toString()] || (() => void 0);
var useReactId = React27__namespace[" useId ".trim().toString()] || (() => void 0);
var count = 0;
function useId(deterministicId) {
const [id, setId] = React26__namespace.useState(
const [id, setId] = React27__namespace.useState(
typeof useReactId === "function" ? useReactId() : void 0
);
useLayoutEffect3(() => {
useLayoutEffect4(() => {
if (!deterministicId) setId((reactId) => reactId ?? String(count++));

@@ -524,6 +856,5 @@ }, [deterministicId]);

}
var useIsomorphicLayoutEffect = typeof window !== "undefined" ? React26__namespace.useLayoutEffect : React26__namespace.useEffect;
function useMounted() {
const [mounted, setMounted] = React26__namespace.useState(false);
useLayoutEffect3(() => {
const [mounted, setMounted] = React27__namespace.useState(false);
useLayoutEffect4(() => {
setMounted(true);

@@ -534,4 +865,4 @@ }, []);

function usePrevious(value) {
const ref = React26__namespace.useRef({ value, previous: value });
return React26__namespace.useMemo(() => {
const ref = React27__namespace.useRef({ value, previous: value });
return React27__namespace.useMemo(() => {
if (ref.current.value !== value) {

@@ -560,15 +891,15 @@ ref.current.previous = ref.current.value;

}) {
const max = React26__namespace.useMemo(
const max = React27__namespace.useMemo(
() => isValidMaxNumber(maxProp) ? maxProp : 100,
[maxProp]
);
const value = React26__namespace.useMemo(
const value = React27__namespace.useMemo(
() => isValidValueNumber(valueProp, max) ? valueProp : null,
[valueProp, max]
);
const state = React26__namespace.useMemo(
const state = React27__namespace.useMemo(
() => getProgressState(value, max),
[value, max]
);
const progressProps = React26__namespace.useMemo(
const progressProps = React27__namespace.useMemo(
() => ({

@@ -618,4 +949,4 @@ role: "progressbar",

}
function isPinchZoomActive() {
return (window.visualViewport?.scale ?? 1) !== 1;
function isPinchZoomActive(win = globalThis.window) {
return (win.visualViewport?.scale ?? 1) !== 1;
}

@@ -630,25 +961,39 @@ function getPlatform() {

// src/hooks/use-scroll-lock.ts
function getScrollbarWidth() {
return Math.max(0, window.innerWidth - document.documentElement.clientWidth);
var nonTextInputTypes = /* @__PURE__ */ new Set([
"checkbox",
"radio",
"range",
"color",
"file",
"image",
"button",
"submit",
"reset"
]);
function getCanOpenKeyboard(target) {
return target instanceof HTMLInputElement && !nonTextInputTypes.has(target.type) || target instanceof HTMLTextAreaElement || target instanceof HTMLElement && target.isContentEditable;
}
function getScrollbarHeight() {
return Math.max(
0,
window.innerHeight - document.documentElement.clientHeight
function isNodeScrollable(node) {
if (!node) return false;
const style = window.getComputedStyle(node);
const hasScrollStyle = /(auto|scroll)/.test(
style.overflow + style.overflowX + style.overflowY
);
return hasScrollStyle && (node.scrollHeight !== node.clientHeight || node.scrollWidth !== node.clientWidth);
}
function getOriginalStyles(element) {
const computedStyle = window.getComputedStyle(element);
return {
overflow: element.style.overflow,
paddingRight: element.style.paddingRight,
paddingBottom: element.style.paddingBottom,
position: element.style.position,
height: element.style.height,
width: element.style.width,
top: element.style.top,
left: element.style.left,
marginTop: computedStyle.marginTop,
marginBottom: computedStyle.marginBottom
};
function scrollIntoView(target) {
const root = document.scrollingElement || document.documentElement;
let currentNode = target;
while (currentNode && currentNode !== root) {
while (currentNode && !isNodeScrollable(currentNode)) {
currentNode = currentNode.parentElement;
}
if (!currentNode || currentNode === root) break;
const { top: scrollableTop } = currentNode.getBoundingClientRect();
const { top: targetTop } = target.getBoundingClientRect();
if (targetTop > scrollableTop + target.clientHeight) {
currentNode.scrollTop += targetTop - scrollableTop;
}
currentNode = currentNode.parentElement;
}
}

@@ -658,10 +1003,10 @@ function getIsDvhSupported() {

}
function hasInsetScrollbars(referenceElement) {
function getIsInsetScroll(referenceElement) {
if (typeof document === "undefined") return false;
const doc = referenceElement ? referenceElement.ownerDocument : document;
const win = doc ? doc.defaultView : window;
if (!win) return false;
const doc = referenceElement?.ownerDocument ?? document;
const win = doc.defaultView ?? window;
return win.innerWidth - doc.documentElement.clientWidth > 0;
}
var preventScrollCount = 0;
var originalStyle = {};
function useScrollLock({

@@ -672,12 +1017,14 @@ referenceElement,

} = {}) {
const scrollPositionRef = React26__namespace.useRef(0);
const originalStylesRef = React26__namespace.useRef({});
const scrollPositionRef = React27__namespace.useRef({ top: 0, left: 0 });
const resizeRef = React27__namespace.useRef(-1);
const scrollableRef = React27__namespace.useRef(null);
const cleanupRef = React27__namespace.useRef(null);
useIsomorphicLayoutEffect(() => {
if (!enabled) return;
const targetElement = referenceElement ?? document.body;
const documentElement = document.documentElement;
const ios = isIOS();
const firefox = isFirefox();
const safari = isSafari();
if (safari && !allowPinchZoom && (window.visualViewport?.scale ?? 1) !== 1) {
const doc = referenceElement?.ownerDocument ?? globalThis.document;
const win = doc.defaultView ?? globalThis.window;
const html = doc.documentElement;
const body = doc.body;
const shouldAllowPinchZoom = allowPinchZoom ?? win.visualViewport?.scale !== 1;
if (isSafari() && !shouldAllowPinchZoom) {
return;

@@ -687,48 +1034,158 @@ }

if (preventScrollCount !== 1) return;
scrollPositionRef.current = window.scrollY;
originalStylesRef.current = getOriginalStyles(targetElement);
const scrollbarWidth = getScrollbarWidth();
const scrollbarHeight = getScrollbarHeight();
if (ios) {
const scrollableElements = Array.from(
document.querySelectorAll("[data-scroll-lock-scrollable]")
);
Object.assign(targetElement.style, {
position: "fixed",
width: "100%",
top: `-${scrollPositionRef.current}px`,
left: "0",
overflow: scrollableElements.length ? "auto" : "hidden",
height: "100%",
"-webkit-overflow-scrolling": "touch"
});
for (const elem of scrollableElements) {
elem.style.overflow = "auto";
}
} else {
const dvhSupported = getIsDvhSupported();
const hasInsetScroll = hasInsetScrollbars(targetElement);
Object.assign(targetElement.style, {
overflow: "hidden",
...scrollbarWidth > 0 && {
paddingRight: `${scrollbarWidth}px`,
// Prevent content shift in Firefox
...firefox && !hasInsetScroll && {
marginRight: `${scrollbarWidth}px`
scrollPositionRef.current = {
top: win.scrollY,
left: win.scrollX
};
const htmlStyle = win.getComputedStyle(html);
const bodyStyle = win.getComputedStyle(body);
originalStyle = {
htmlOverflowY: html.style.overflowY,
htmlOverflowX: html.style.overflowX,
bodyPosition: body.style.position,
bodyWidth: body.style.width,
bodyHeight: body.style.height,
bodyOverflow: body.style.overflow,
bodyBoxSizing: body.style.boxSizing
};
const scrollbarWidth = Math.max(
0,
win.innerWidth - doc.documentElement.clientWidth
);
const scrollbarHeight = Math.max(
0,
win.innerHeight - doc.documentElement.clientHeight
);
const dvhSupported = getIsDvhSupported();
const isInsetScroll = getIsInsetScroll(referenceElement);
function onScrollLock() {
const isScrollbarGutterStable = htmlStyle.scrollbarGutter?.includes("stable");
const isScrollableY = html.scrollHeight > html.clientHeight;
const isScrollableX = html.scrollWidth > html.clientWidth;
const isOverflowYScroll = htmlStyle.overflowY === "scroll" || bodyStyle.overflowY === "scroll";
const isOverflowXScroll = htmlStyle.overflowX === "scroll" || bodyStyle.overflowX === "scroll";
const marginY = Number.parseFloat(bodyStyle.marginTop) + Number.parseFloat(bodyStyle.marginBottom);
const marginX = Number.parseFloat(bodyStyle.marginLeft) + Number.parseFloat(bodyStyle.marginRight);
if (isIOS()) {
let onTouchStart2 = function(event) {
const target = event.target;
let currentNode = target;
while (currentNode && currentNode !== html) {
if (isNodeScrollable(currentNode) && currentNode instanceof HTMLElement) {
scrollableRef.current = currentNode;
const style = win.getComputedStyle(currentNode);
if (style.overscrollBehavior === "auto") {
currentNode.style.overscrollBehavior = "contain";
}
break;
}
currentNode = currentNode.parentElement;
}
},
...scrollbarHeight > 0 && {
paddingBottom: `${scrollbarHeight}px`
},
// Use dvh if supported for better mobile handling
...dvhSupported && {
height: "100dvh"
if (!currentNode || currentNode === html) {
scrollableRef.current = null;
}
}, onTouchMove2 = function(event) {
const scrollable = scrollableRef.current;
if (!scrollable || scrollable === html || scrollable === body) {
event.preventDefault();
return;
}
if (scrollable.scrollHeight === scrollable.clientHeight && scrollable.scrollWidth === scrollable.clientWidth) {
event.preventDefault();
}
}, onFocus2 = function(event) {
const target = event.target;
if (getCanOpenKeyboard(target)) {
target.style.transform = "translateY(-2000px)";
requestAnimationFrame(() => {
target.style.transform = "";
if (!win.visualViewport) return;
if (win.visualViewport.height < win.innerHeight) {
requestAnimationFrame(() => scrollIntoView(target));
return;
}
win.visualViewport.addEventListener(
"resize",
() => scrollIntoView(target),
{ once: true }
);
});
}
};
Object.assign(body.style, {
position: "fixed",
width: marginX || scrollbarWidth ? `calc(100vw - ${marginX + scrollbarWidth}px)` : "100vw",
height: marginY || scrollbarHeight ? `calc(100vh - ${marginY + scrollbarHeight}px)` : "100vh",
top: `-${scrollPositionRef.current.top}px`,
left: `-${scrollPositionRef.current.left}px`,
overflow: "hidden",
boxSizing: "border-box"
});
doc.addEventListener("touchstart", onTouchStart2, {
passive: false,
capture: true
});
doc.addEventListener("touchmove", onTouchMove2, {
passive: false,
capture: true
});
doc.addEventListener("focus", onFocus2, true);
cleanupRef.current = () => {
doc.removeEventListener("touchstart", onTouchStart2, {
capture: true
});
doc.removeEventListener("touchmove", onTouchMove2, {
capture: true
});
doc.removeEventListener("focus", onFocus2, true);
};
} else {
Object.assign(html.style, {
overflowY: !isScrollbarGutterStable && (isScrollableY || isOverflowYScroll) ? "scroll" : "hidden",
overflowX: !isScrollbarGutterStable && (isScrollableX || isOverflowXScroll) ? "scroll" : "hidden",
paddingRight: scrollbarWidth > 0 ? `${scrollbarWidth}px` : ""
});
Object.assign(body.style, {
position: "relative",
width: marginX || scrollbarWidth ? `calc(100vw - ${marginX + scrollbarWidth}px)` : "100vw",
height: dvhSupported ? marginY ? `calc(100dvh - ${marginY}px)` : "100dvh" : marginY ? `calc(100vh - ${marginY}px)` : "100vh",
boxSizing: "border-box",
overflow: "hidden"
});
if (isFirefox() && !isInsetScroll) {
body.style.marginRight = `${scrollbarWidth}px`;
}
body.scrollTop = scrollPositionRef.current.top;
body.scrollLeft = scrollPositionRef.current.left;
html.setAttribute("data-scroll-locked", "");
}
}
function onScrollUnlock() {
Object.assign(html.style, {
overflowY: originalStyle.htmlOverflowY,
overflowX: originalStyle.htmlOverflowX,
paddingRight: ""
});
Object.assign(documentElement.style, {
overflow: "hidden",
// Prevent iOS momentum scrolling
overscrollBehavior: "none"
Object.assign(body.style, {
overflow: originalStyle.bodyOverflow,
position: originalStyle.bodyPosition,
width: originalStyle.bodyWidth,
height: originalStyle.bodyHeight,
boxSizing: originalStyle.bodyBoxSizing,
marginRight: "",
top: "",
left: ""
});
html.removeAttribute("data-scroll-locked");
win.scrollTo(
scrollPositionRef.current.left,
scrollPositionRef.current.top
);
}
function onResize() {
cancelAnimationFrame(resizeRef.current);
resizeRef.current = requestAnimationFrame(() => {
onScrollUnlock();
onScrollLock();
});
}
function preventDefault(event) {

@@ -738,4 +1195,6 @@ if (event.touches.length > 1) return;

}
if (ios) {
document.addEventListener("touchmove", preventDefault, {
onScrollLock();
win.addEventListener("resize", onResize);
if (isIOS()) {
doc.addEventListener("touchmove", preventDefault, {
passive: false

@@ -747,10 +1206,8 @@ });

if (preventScrollCount !== 0) return;
Object.assign(targetElement.style, originalStylesRef.current);
Object.assign(documentElement.style, {
overflow: "",
overscrollBehavior: ""
});
if (ios) {
document.removeEventListener("touchmove", preventDefault);
window.scrollTo(0, scrollPositionRef.current);
cancelAnimationFrame(resizeRef.current);
onScrollUnlock();
win.removeEventListener("resize", onResize);
if (isIOS()) {
doc.removeEventListener("touchmove", preventDefault);
cleanupRef.current?.();
}

@@ -761,4 +1218,4 @@ };

function useSize(element) {
const [size, setSize] = React26__namespace.useState(void 0);
useLayoutEffect3(() => {
const [size2, setSize] = React27__namespace.useState(void 0);
useLayoutEffect4(() => {
if (element) {

@@ -792,12 +1249,16 @@ setSize({ width: element.offsetWidth, height: element.offsetHeight });

}, [element]);
return size;
return size2;
}
function useStateMachine(initialState, machine) {
return React26__namespace.useReducer(
(state, event) => {
const nextState = machine[state][event];
return nextState ?? state;
function useStateMachine(config) {
const [state, setState] = React27__namespace.useState(config.initial);
const send = React27__namespace.useCallback(
(event) => {
setState((currentState) => {
const transition = config.states[currentState]?.[event];
return transition ?? currentState;
});
},
initialState
[config.states]
);
return [state, send];
}

@@ -829,5 +1290,5 @@ function wrapArray(array, startIndex) {

const onSearchChangeCallback = useCallbackRef(onSearchChange);
const searchRef = React26__namespace.useRef("");
const timerRef = React26__namespace.useRef(0);
const onTypeaheadSearch = React26__namespace.useCallback(
const searchRef = React27__namespace.useRef("");
const timerRef = React27__namespace.useRef(0);
const onTypeaheadSearch = React27__namespace.useCallback(
(key) => {

@@ -854,7 +1315,7 @@ if (!enabled) return;

);
const onResetTypeahead = React26__namespace.useCallback(() => {
const onResetTypeahead = React27__namespace.useCallback(() => {
searchRef.current = "";
window.clearTimeout(timerRef.current);
}, []);
React26__namespace.useEffect(() => {
React27__namespace.useEffect(() => {
return () => window.clearTimeout(timerRef.current);

@@ -881,7 +1342,7 @@ }, []);

} = props;
const ref = React26__namespace.useRef(null);
const ref = React27__namespace.useRef(null);
const prevValue = usePrevious(type === "hidden" ? value : checked);
const controlSize = useSize(control);
const isCheckInput = type === "checkbox" || type === "radio" || type === "switch";
React26__namespace.useEffect(() => {
React27__namespace.useEffect(() => {
const input = ref.current;

@@ -911,3 +1372,3 @@ if (!input) return;

});
return /* @__PURE__ */ React26__namespace.createElement(
return /* @__PURE__ */ React27__namespace.createElement(
"input",

@@ -932,16 +1393,33 @@ {

}
function setRef(ref, value) {
if (typeof ref === "function") {
ref(value);
} else if (ref !== null && ref !== void 0) {
ref.current = value;
}
}
function composeRefs(...refs) {
return (node) => {
for (const ref of refs) {
setRef(ref, node);
}
};
}
function useComposedRefs(...refs) {
return React27__namespace.useCallback(composeRefs(...refs), refs);
}
function createContext3(rootComponentName, defaultValue) {
const Context = React26__namespace.createContext(defaultValue);
const Context = React27__namespace.createContext(defaultValue);
Context.displayName = rootComponentName;
function Provider(props) {
const { children, ...contextValue } = props;
const value = React26__namespace.useMemo(
const value = React27__namespace.useMemo(
() => contextValue,
Object.values(contextValue)
);
return /* @__PURE__ */ React26__namespace.createElement(Context.Provider, { value }, children);
return /* @__PURE__ */ React27__namespace.createElement(Context.Provider, { value }, children);
}
Provider.displayName = `${rootComponentName}Provider`;
function useContext3(consumerName, required) {
const context = React26__namespace.useContext(Context);
const context = React27__namespace.useContext(Context);
if (context) return context;

@@ -958,3 +1436,225 @@ if (defaultValue !== void 0) return defaultValue;

}
function getElementRef(element) {
if (!React27__namespace.isValidElement(element)) return void 0;
const propDescriptor = Object.getOwnPropertyDescriptor(element.props, "ref");
const elementDescriptor = Object.getOwnPropertyDescriptor(element, "ref");
if (propDescriptor?.get && "isReactWarning" in propDescriptor.get) {
return element.ref;
}
if (elementDescriptor?.get && "isReactWarning" in elementDescriptor.get) {
return element.props.ref;
}
return element.props.ref ?? element.ref;
}
// src/components/slot.tsx
var isSlottable = function isSlottable2(child) {
return React27__namespace.isValidElement(child) && child.type === Slottable;
};
function mergeProps(slotProps, childProps) {
const overrideProps = { ...childProps };
for (const propName in childProps) {
const slotPropValue = slotProps[propName];
const childPropValue = childProps[propName];
if (/^on[A-Z]/.test(propName)) {
if (typeof slotPropValue === "function" && typeof childPropValue === "function") {
overrideProps[propName] = (...args) => {
childPropValue(...args);
slotPropValue(...args);
};
} else if (typeof slotPropValue === "function") {
overrideProps[propName] = slotPropValue;
}
} else if (propName === "style" && slotPropValue && childPropValue) {
overrideProps[propName] = {
...slotPropValue,
...childPropValue
};
} else if (propName === "className") {
overrideProps[propName] = [slotPropValue, childPropValue].filter(Boolean).join(" ");
}
}
return { ...slotProps, ...overrideProps };
}
var SlotClone = React27__namespace.forwardRef(
(props, forwardedRef) => {
const { children, ...slotProps } = props;
if (!React27__namespace.isValidElement(children)) {
return React27__namespace.Children.count(children) > 1 ? React27__namespace.Children.only(null) : null;
}
const childrenRef = getElementRef(children);
const mergedProps = mergeProps(
slotProps,
children.props
);
if (typeof children.type === "string") {
return React27__namespace.cloneElement(children, {
...mergedProps,
ref: forwardedRef ? composeRefs(forwardedRef, childrenRef) : childrenRef
});
}
return React27__namespace.cloneElement(children, {
...mergedProps,
ref: forwardedRef ? composeRefs(forwardedRef, childrenRef) : childrenRef
});
}
);
SlotClone.displayName = "SlotClone";
var Slot = React27__namespace.forwardRef((props, forwardedRef) => {
const { children, ...slotProps } = props;
const childrenArray = React27__namespace.Children.toArray(children);
const slottable = childrenArray.find(isSlottable);
if (!slottable) {
return /* @__PURE__ */ React27__namespace.createElement(SlotClone, { ...slotProps, ref: forwardedRef }, children);
}
if (!React27__namespace.isValidElement(slottable)) {
return null;
}
const newElement = slottable.props.children;
const newChildren = childrenArray.map((child) => {
if (child === slottable) {
if (React27__namespace.Children.count(newElement) > 1) {
return React27__namespace.Children.only(null);
}
return React27__namespace.isValidElement(newElement) ? newElement.props.children : null;
}
return child;
});
return /* @__PURE__ */ React27__namespace.createElement(SlotClone, { ...slotProps, ref: forwardedRef }, React27__namespace.isValidElement(newElement) ? React27__namespace.cloneElement(newElement, void 0, newChildren) : null);
});
Slot.displayName = "Slot";
var Slottable = React27__namespace.memo(function Slottable2({ children }) {
return /* @__PURE__ */ React27__namespace.createElement(React27__namespace.Fragment, null, children);
});
Slottable.displayName = "Slottable";
// src/components/collection.tsx
function createCollection(name) {
const PROVIDER_NAME = `${name}CollectionProvider`;
const COLLECTION_SLOT_NAME = `${name}CollectionSlot`;
const ITEM_SLOT_NAME = `${name}CollectionItemSlot`;
const [CollectionProvider, useCollectionContext] = createContext3(
PROVIDER_NAME
);
const CollectionSlot = React27__namespace.memo(
React27__namespace.forwardRef((props, forwardedRef) => {
const context = useCollectionContext(COLLECTION_SLOT_NAME);
const composedRefs = React27__namespace.useMemo(
() => composeRefs(forwardedRef, context.collectionRef),
[forwardedRef, context.collectionRef]
);
return /* @__PURE__ */ React27__namespace.createElement(Slot, { ref: composedRefs, ...props });
})
);
CollectionSlot.displayName = COLLECTION_SLOT_NAME;
const CollectionItemSlot = React27__namespace.memo(
React27__namespace.forwardRef(
(props, forwardedRef) => {
const { children, ...itemProps } = props;
const context = useCollectionContext(ITEM_SLOT_NAME);
const itemRef = React27__namespace.useRef(null);
const itemPropsRef = React27__namespace.useRef(itemProps);
itemPropsRef.current = itemProps;
const composedRef = composeRefs(forwardedRef, itemRef);
React27__namespace.useEffect(() => {
const node = itemRef.current;
if (!node) return;
const item = {
ref: itemRef,
...itemPropsRef.current
};
context.itemMap.set(itemRef, item);
return () => void context.itemMap.delete(itemRef);
}, [context.itemMap]);
return /* @__PURE__ */ React27__namespace.createElement(Slot, { ...{ [DATA_ITEM_ATTR]: "" }, ref: composedRef }, children);
}
)
);
CollectionItemSlot.displayName = ITEM_SLOT_NAME;
function useCollection2({
collectionRef,
itemMap
}) {
const getItems = React27__namespace.useCallback(() => {
const collectionNode = collectionRef.current;
if (!collectionNode) return [];
try {
const items = Array.from(itemMap.values());
const fallbackDiv = globalThis.document?.createElement("div");
return items.sort((a, b) => {
const aNode = a?.ref.current ?? fallbackDiv;
const bNode = b?.ref.current ?? fallbackDiv;
return compareNodePosition(aNode, bNode);
});
} catch (_err) {
return [];
}
}, [collectionRef, itemMap]);
return React27__namespace.useMemo(() => ({ getItems }), [getItems]);
}
return [
{
CollectionProvider,
CollectionSlot,
CollectionItemSlot
},
useCollection2
];
}
function createPrimitive(element) {
const Primitive2 = React27__namespace.forwardRef((props, forwardedRef) => {
const { asChild, ...primitiveProps } = props;
if (asChild) {
return React27__namespace.createElement(Slot, {
...primitiveProps,
ref: forwardedRef
});
}
return React27__namespace.createElement(element, {
...primitiveProps,
ref: forwardedRef
});
});
Primitive2.displayName = `Primitive.${String(element)}`;
return Primitive2;
}
var cache = /* @__PURE__ */ new Map();
var Primitive = new Proxy(
{},
{
get: (_, element) => {
const key = element;
if (!cache.has(key)) {
cache.set(key, createPrimitive(key));
}
return cache.get(key);
}
}
);
function dispatchDiscreteCustomEvent(target, event) {
if (target) {
const evt = new CustomEvent(event.type, {
bubbles: true,
cancelable: true,
detail: event.detail
});
target.dispatchEvent(evt);
}
}
// src/components/portal.tsx
var Portal = React27__namespace.forwardRef(
(props, forwardedRef) => {
const { container, ...portalProps } = props;
const mounted = useMounted();
const dynamicContainer = container ?? (mounted ? globalThis.document?.body : null);
if (!dynamicContainer) return null;
return ReactDOM__namespace.createPortal(
/* @__PURE__ */ React27__namespace.createElement(Primitive.div, { ...portalProps, ref: forwardedRef }),
dynamicContainer
);
}
);
Portal.displayName = "Portal";
// src/lib/compose-event-handlers.ts

@@ -969,22 +1669,5 @@ function composeEventHandlers(originalEventHandler, ourEventHandler, { checkForDefaultPrevented = true } = {}) {

}
function setRef(ref, value) {
if (typeof ref === "function") {
ref(value);
} else if (ref !== null && ref !== void 0) {
ref.current = value;
}
function forwardRef6(render) {
return React27__namespace.forwardRef(render);
}
function composeRefs(...refs) {
return (node) => {
for (const ref of refs) {
setRef(ref, node);
}
};
}
function useComposedRefs(...refs) {
return React26__namespace.useCallback(composeRefs(...refs), refs);
}
function forwardRef2(render) {
return React26__namespace.forwardRef(render);
}

@@ -995,34 +1678,37 @@ // src/components/presence.tsx

const presence = usePresence(present);
const child = typeof children === "function" ? children({ present: presence.isPresent }) : React26__namespace.Children.only(children);
const child = typeof children === "function" ? children({ present: presence.isPresent }) : React27__namespace.Children.only(children);
const ref = useComposedRefs(presence.ref, getElementRef(child));
const forceMount = typeof children === "function";
return forceMount || presence.isPresent ? React26__namespace.cloneElement(child, { ref }) : null;
return forceMount || presence.isPresent ? React27__namespace.cloneElement(child, { ref }) : null;
};
Presence.displayName = "Presence";
function usePresence(present) {
const [node, setNode] = React26__namespace.useState();
const stylesRef = React26__namespace.useRef(
const [node, setNode] = React27__namespace.useState();
const stylesRef = React27__namespace.useRef(
{}
);
const prevPresentRef = React26__namespace.useRef(present);
const prevAnimationNameRef = React26__namespace.useRef("none");
const prevPresentRef = React27__namespace.useRef(present);
const prevAnimationNameRef = React27__namespace.useRef("none");
const initialState = present ? "mounted" : "unmounted";
const [state, send] = useStateMachine(initialState, {
mounted: {
UNMOUNT: "unmounted",
ANIMATION_OUT: "unmountSuspended"
},
unmountSuspended: {
MOUNT: "mounted",
ANIMATION_END: "unmounted"
},
unmounted: {
MOUNT: "mounted"
const [state, send] = useStateMachine({
initial: initialState,
states: {
mounted: {
UNMOUNT: "unmounted",
ANIMATION_OUT: "unmountSuspended"
},
unmountSuspended: {
MOUNT: "mounted",
ANIMATION_END: "unmounted"
},
unmounted: {
MOUNT: "mounted"
}
}
});
React26__namespace.useEffect(() => {
React27__namespace.useEffect(() => {
const currentAnimationName = getAnimationName(stylesRef.current);
prevAnimationNameRef.current = state === "mounted" ? currentAnimationName : "none";
}, [state]);
useLayoutEffect3(() => {
useLayoutEffect4(() => {
const styles = stylesRef.current;

@@ -1049,3 +1735,3 @@ const wasPresent = prevPresentRef.current;

}, [present, send]);
useLayoutEffect3(() => {
useLayoutEffect4(() => {
if (node) {

@@ -1090,3 +1776,3 @@ let onAnimationEnd2 = function(event) {

isPresent: ["mounted", "unmountSuspended"].includes(state),
ref: React26__namespace.useCallback((node2) => {
ref: React27__namespace.useCallback((node2) => {
if (node2) stylesRef.current = getComputedStyle(node2);

@@ -1100,15 +1786,2 @@ setNode(node2);

}
function getElementRef(element) {
let getter = Object.getOwnPropertyDescriptor(element.props, "ref")?.get;
let mayWarn = getter && "isReactWarning" in getter && getter.isReactWarning;
if (mayWarn) {
return element.ref;
}
getter = Object.getOwnPropertyDescriptor(element, "ref")?.get;
mayWarn = getter && "isReactWarning" in getter && getter.isReactWarning;
if (mayWarn) {
return element.props.ref;
}
return element.props.ref || element.ref;
}

@@ -1120,3 +1793,7 @@ exports.BubbleInput = BubbleInput;

exports.DATA_VALUE_ATTR = DATA_VALUE_ATTR;
exports.Portal = Portal;
exports.Presence = Presence;
exports.Primitive = Primitive;
exports.Slot = Slot;
exports.Slottable = Slottable;
exports.VAR_ANCHOR_HEIGHT = VAR_ANCHOR_HEIGHT;

@@ -1127,8 +1804,10 @@ exports.VAR_ANCHOR_WIDTH = VAR_ANCHOR_WIDTH;

exports.VAR_TRANSFORM_ORIGIN = VAR_TRANSFORM_ORIGIN;
exports.compareNodePosition = compareNodePosition;
exports.composeEventHandlers = composeEventHandlers;
exports.composeRefs = composeRefs;
exports.createCollection = createCollection;
exports.createContext = createContext3;
exports.dispatchDiscreteCustomEvent = dispatchDiscreteCustomEvent;
exports.findNextItem = findNextItem;
exports.forwardRef = forwardRef2;
exports.getItem = getItem;
exports.forwardRef = forwardRef6;
exports.getOwnerDocument = getOwnerDocument;

@@ -1149,5 +1828,5 @@ exports.getOwnerWindow = getOwnerWindow;

exports.useAnchor = useAnchor;
exports.useAnchorPositioner = useAnchorPositioner;
exports.useCallbackRef = useCallbackRef;
exports.useCollection = useCollection;
exports.useCollectionItem = useCollectionItem;
exports.useComposedRefs = useComposedRefs;

@@ -1165,3 +1844,3 @@ exports.useControllableState = useControllableState;

exports.useIsomorphicLayoutEffect = useIsomorphicLayoutEffect;
exports.useLayoutEffect = useLayoutEffect3;
exports.useLayoutEffect = useLayoutEffect4;
exports.useMounted = useMounted;

@@ -1168,0 +1847,0 @@ exports.usePrevious = usePrevious;

@@ -1,17 +0,19 @@

import * as React26 from 'react';
import * as React27 from 'react';
import { offset, inline, flip, shift, limitShift, size, arrow, hide, useFloating, autoUpdate } from '@floating-ui/react';
import * as ReactDOM from 'react-dom';
// src/components/bubble-input.tsx
function useAnchor() {
const anchorRef = React26.useRef(null);
const [hasAnchor, setHasAnchor] = React26.useState(false);
const onAnchorChange = React26.useCallback((node) => {
const anchorRef = React27.useRef(null);
const [hasAnchor, setHasAnchor] = React27.useState(false);
const onAnchorChange = React27.useCallback((node) => {
anchorRef.current = node;
}, []);
const onHasAnchorChange = React26.useCallback((value) => {
const onHasAnchorChange = React27.useCallback((value) => {
setHasAnchor(value);
}, []);
const onAnchorAdd = React26.useCallback(() => {
const onAnchorAdd = React27.useCallback(() => {
setHasAnchor(true);
}, []);
const onAnchorRemove = React26.useCallback(() => {
const onAnchorRemove = React27.useCallback(() => {
setHasAnchor(false);

@@ -28,12 +30,2 @@ }, []);

}
function useCallbackRef(callback) {
const callbackRef = React26.useRef(callback);
React26.useEffect(() => {
callbackRef.current = callback;
});
return React26.useMemo(
() => (...args) => callbackRef.current?.(...args),
[]
);
}

@@ -50,3 +42,281 @@ // src/constants.ts

var VAR_AVAILABLE_HEIGHT = "--dice-available-height";
var DirectionContext = React27.createContext(void 0);
function useDirection(dirProp) {
const contextDir = React27.useContext(DirectionContext);
return dirProp ?? contextDir ?? "ltr";
}
var useIsomorphicLayoutEffect = typeof window !== "undefined" ? React27.useLayoutEffect : React27.useEffect;
// src/hooks/use-anchor-positioner.ts
var LONGHAND_SIDES = {
top: "bottom",
right: "left",
bottom: "top",
left: "right"
};
var ARROW_TRANSFORMS = {
top: "translateY(100%)",
right: "translateY(50%) rotate(90deg) translateX(-50%)",
bottom: "rotate(180deg)",
left: "translateY(50%) rotate(-90deg) translateX(50%)"
};
function isValidNumber(value) {
return typeof value === "number" && !Number.isNaN(value) && Number.isFinite(value);
}
function useAnchorPositioner({
open,
onOpenChange,
anchorRef,
side = "bottom",
sideOffset = 4,
align = "start",
alignOffset = 0,
collisionBoundary,
collisionPadding = 0,
arrowPadding = 0,
sticky = "partial",
strategy = "absolute",
avoidCollisions = false,
disableArrow = false,
fitViewport = false,
forceMount = false,
hideWhenDetached = false,
trackAnchor = true
}) {
const direction = useDirection();
const [positionerArrow, setPositionerArrow] = React27.useState(null);
const rtlAlign = React27.useMemo(() => {
if (direction !== "rtl") return align;
return align === "start" ? "end" : align === "end" ? "start" : "center";
}, [align, direction]);
const placement = React27.useMemo(
() => `${side}-${rtlAlign}`,
[side, rtlAlign]
);
const baseMiddleware = React27.useMemo(
() => [
offset({
mainAxis: sideOffset,
alignmentAxis: alignOffset
}),
inline()
],
[sideOffset, alignOffset]
);
const collisionMiddleware = React27.useMemo(
() => avoidCollisions ? [
flip({
boundary: collisionBoundary,
padding: collisionPadding,
fallbackStrategy: sticky === "partial" ? "bestFit" : "initialPlacement"
}),
shift({
boundary: collisionBoundary,
padding: collisionPadding,
limiter: sticky === "partial" ? limitShift() : void 0
})
] : [],
[avoidCollisions, collisionBoundary, collisionPadding, sticky]
);
const sizeMiddleware = React27.useMemo(
() => [
size({
padding: collisionPadding,
apply({
elements: { floating },
rects: { reference },
availableWidth,
availableHeight
}) {
const styles = {
[VAR_AVAILABLE_WIDTH]: `${availableWidth}px`,
[VAR_AVAILABLE_HEIGHT]: `${availableHeight}px`,
[VAR_ANCHOR_WIDTH]: `${reference.width}px`,
[VAR_ANCHOR_HEIGHT]: `${reference.height}px`
};
for (const [key, value] of Object.entries(styles)) {
floating.style.setProperty(key, value);
}
if (fitViewport) {
Object.assign(floating.style, {
maxHeight: `${availableHeight}px`,
maxWidth: `${availableWidth}px`
});
}
}
})
],
[collisionPadding, fitViewport]
);
const arrowMiddleware = React27.useMemo(
() => !disableArrow && positionerArrow ? [
arrow({
element: positionerArrow,
padding: arrowPadding
})
] : [],
[disableArrow, positionerArrow, arrowPadding]
);
const middleware = React27.useMemo(
() => [
...baseMiddleware,
...collisionMiddleware,
...sizeMiddleware,
...hideWhenDetached ? [hide()] : [],
...arrowMiddleware
],
[
baseMiddleware,
collisionMiddleware,
sizeMiddleware,
hideWhenDetached,
arrowMiddleware
]
);
const autoUpdateOptions = React27.useMemo(
() => ({
ancestorScroll: trackAnchor,
ancestorResize: true,
elementResize: trackAnchor && typeof ResizeObserver !== "undefined",
layoutShift: trackAnchor && typeof IntersectionObserver !== "undefined"
}),
[trackAnchor]
);
const {
x,
y,
refs,
strategy: floatingStrategy,
context,
placement: floatingPlacement,
middlewareData,
isPositioned,
update,
elements
} = useFloating({
open,
onOpenChange,
placement,
middleware,
whileElementsMounted: forceMount ? void 0 : (...args) => autoUpdate(...args, autoUpdateOptions),
strategy
});
useIsomorphicLayoutEffect(() => {
if (!open) return;
const isVirtualAnchor = anchorRef && "getBoundingClientRect" in anchorRef;
const anchor = isVirtualAnchor ? anchorRef : anchorRef?.current;
if (!anchor) return;
isVirtualAnchor ? refs.setPositionReference(anchor) : refs.setReference(anchor);
update();
}, [open, anchorRef, refs, update]);
React27.useEffect(() => {
if (forceMount && open && elements.reference && elements.floating) {
return autoUpdate(
elements.reference,
elements.floating,
update,
autoUpdateOptions
);
}
return void 0;
}, [forceMount, open, elements, update, autoUpdateOptions]);
const [placementSide = "bottom", placementAlign = "start"] = floatingPlacement.split("-");
const transformOrigin = React27.useMemo(() => {
const oppositeSide = LONGHAND_SIDES[placementSide];
const oppositeAlign = placementAlign === "end" ? "start" : placementAlign === "start" ? "end" : "center";
return `${oppositeAlign} ${oppositeSide}`;
}, [placementSide, placementAlign]);
const getFloatingProps = React27.useCallback(
(floatingProps = {}) => ({
...floatingProps,
"data-side": placementSide,
"data-align": placementAlign
}),
[placementSide, placementAlign]
);
const floatingStyles = React27.useMemo(() => {
const validY = isValidNumber(y) ? y : 0;
const validX = isValidNumber(x) ? x : 0;
return {
position: floatingStrategy,
top: validY,
left: validX,
[VAR_TRANSFORM_ORIGIN]: transformOrigin
};
}, [floatingStrategy, x, y, transformOrigin]);
const anchorHidden = !!middlewareData.hide?.referenceHidden;
const arrowDisplaced = disableArrow ? false : middlewareData.arrow?.centerOffset !== 0;
const arrowStyles = React27.useMemo(() => {
if (disableArrow) return {};
return {
position: "absolute",
top: middlewareData.arrow?.y,
left: middlewareData.arrow?.x,
[placementSide]: 0,
transformOrigin,
transform: ARROW_TRANSFORMS[placementSide]
};
}, [middlewareData.arrow, placementSide, transformOrigin, disableArrow]);
const positionerContext = React27.useMemo(
() => ({
refs,
floatingStyles,
placement: floatingPlacement,
isPositioned,
middlewareData,
elements,
update,
context,
getFloatingProps,
arrowStyles,
onArrowChange: disableArrow ? () => {
} : setPositionerArrow,
side: placementSide,
align: placementAlign,
arrowDisplaced,
anchorHidden
}),
[
refs,
floatingStyles,
floatingPlacement,
isPositioned,
middlewareData,
elements,
update,
context,
getFloatingProps,
arrowStyles,
placementSide,
placementAlign,
arrowDisplaced,
anchorHidden,
disableArrow
]
);
return positionerContext;
}
function useCallbackRef(callback) {
const callbackRef = React27.useRef(callback);
React27.useEffect(() => {
callbackRef.current = callback;
});
return React27.useMemo(
() => (...args) => callbackRef.current?.(...args),
[]
);
}
// src/lib/node.ts
function compareNodePosition(a, b) {
const position = a.compareDocumentPosition(b);
if (position & Node.DOCUMENT_POSITION_FOLLOWING || position & Node.DOCUMENT_POSITION_CONTAINED_BY) {
return -1;
}
if (position & Node.DOCUMENT_POSITION_PRECEDING || position & Node.DOCUMENT_POSITION_CONTAINS) {
return 1;
}
return 0;
}
// src/hooks/use-collection.ts

@@ -57,3 +327,3 @@ function useCollection({

}) {
const getItems = React26.useCallback(() => {
const getItems = React27.useCallback(() => {
const collectionNode = ref.current;

@@ -64,10 +334,5 @@ if (!collectionNode) return [];

);
const orderedItems = items.sort((a, b) => {
const aIndex = Number(a.getAttribute(attr));
const bIndex = Number(b.getAttribute(attr));
return aIndex - bIndex;
});
return orderedItems;
return items.sort(compareNodePosition);
}, [ref, attr]);
const getEnabledItems = React26.useCallback(() => {
const getEnabledItems = React27.useCallback(() => {
const items = getItems();

@@ -80,16 +345,2 @@ return items.filter(

}
function useCollectionItem(ref, context, disabled, value, label) {
React26.useEffect(() => {
context.itemMap.set(ref, { ref: ref.current, label, value, disabled });
return () => {
context.itemMap.delete(ref);
};
}, [ref, label, value, disabled, context.itemMap]);
}
function getItem(item, context) {
for (const [ref, data] of context.itemMap.entries()) {
if (ref.current === item) return data;
}
return null;
}
function getSortedItems(items, value) {

@@ -102,6 +353,7 @@ if (!value?.length) return items;

const bIndex = value.indexOf(bValue ?? "");
if (aIndex === -1 && bIndex === -1) return 0;
if (aIndex === -1 && bIndex === -1) return compareNodePosition(a, b);
if (aIndex === -1) return 1;
if (bIndex === -1) return -1;
return aIndex - bIndex;
if (aIndex !== bIndex) return aIndex - bIndex;
return compareNodePosition(a, b);
});

@@ -122,3 +374,3 @@ }

const handleChange = useCallbackRef(onChange);
const setValue = React26.useCallback(
const setValue = React27.useCallback(
(nextValue) => {

@@ -141,7 +393,7 @@ if (isControlled) {

}) {
const uncontrolledState = React26.useState(defaultProp);
const uncontrolledState = React27.useState(defaultProp);
const [value] = uncontrolledState;
const prevValueRef = React26.useRef(value);
const prevValueRef = React27.useRef(value);
const handleChange = useCallbackRef(onChange);
React26.useEffect(() => {
React27.useEffect(() => {
if (prevValueRef.current !== value) {

@@ -154,18 +406,13 @@ handleChange(value);

}
var DirectionContext = React26.createContext(void 0);
function useDirection(dirProp) {
const contextDir = React26.useContext(DirectionContext);
return dirProp ?? contextDir ?? "ltr";
}
// src/lib/dock.ts
function getOwnerDocument(node) {
return node?.ownerDocument ?? document;
return node?.ownerDocument ?? globalThis.document;
}
function getOwnerWindow(node) {
const doc = getOwnerDocument(node);
return doc?.defaultView ?? window;
return doc?.defaultView ?? globalThis.window;
}
function useEscapeKeydown({
ownerDocument,
document: document2,
onEscapeKeyDown,

@@ -175,3 +422,3 @@ enabled

const onEscapeKeyDownCallback = useCallbackRef(onEscapeKeyDown);
React26.useEffect(() => {
React27.useEffect(() => {
if (!enabled) return;

@@ -183,11 +430,10 @@ function onKeyDown(event) {

}
ownerDocument.addEventListener("keydown", onKeyDown, { capture: true });
return () => ownerDocument.removeEventListener("keydown", onKeyDown, {
document2.addEventListener("keydown", onKeyDown, { capture: true });
return () => document2.removeEventListener("keydown", onKeyDown, {
capture: true
});
}, [enabled, onEscapeKeyDownCallback, ownerDocument]);
}, [enabled, onEscapeKeyDownCallback, document2]);
}
// src/hooks/use-dismiss.ts
var SCROLL_DISTANCE_THRESHOLD = 5;
function useDismiss(params) {

@@ -208,24 +454,11 @@ const {

} = params;
const ownerDocument = getOwnerDocument(refs[0]?.current) ?? document;
const shouldTriggerEvents = React26.useRef(true);
const touchStartY = React26.useRef(null);
const ownerDocument = getOwnerDocument(refs[0]?.current);
const isPointerInsideReactTreeRef = React27.useRef(false);
const onClickRef = React27.useRef(() => {
});
useEscapeKeydown({
ownerDocument,
document: ownerDocument,
onEscapeKeyDown: (event) => {
if (onEscapeKeyDown && !event.defaultPrevented) {
onEscapeKeyDown(event);
}
},
enabled: enabled && !!onEscapeKeyDown && !!onDismiss
});
React26.useEffect(() => {
if (!enabled) return;
function onKeyDown(event) {
if (event.key === "Escape") {
onInteractOutside?.({
currentTarget: event.currentTarget,
target: event.target,
preventDefault: () => event.preventDefault(),
defaultPrevented: event.defaultPrevented
});
if (!event.defaultPrevented) {

@@ -235,59 +468,59 @@ onDismiss(event);

}
}
function onDismissWithTarget(event, target) {
const missingElement = refs.some((ref) => !ref.current);
if (missingElement) return;
const clickedInside = refs.some((ref) => ref.current?.contains(target));
if (!clickedInside && shouldTriggerEvents.current) {
const outsideEvent = {
currentTarget: event.currentTarget,
target,
preventDefault: () => event.preventDefault(),
defaultPrevented: event.defaultPrevented,
detail: event.detail
};
onPointerDownOutside?.(outsideEvent);
onInteractOutside?.(outsideEvent);
if (!event.defaultPrevented && !outsideEvent.defaultPrevented) {
onDismiss(event);
}
},
enabled: enabled && !!onDismiss && !!onEscapeKeyDown
});
const onPointerDownOutsideCallback = useCallbackRef(
(event) => {
onPointerDownOutside?.(event);
onInteractOutside?.(event);
if (!event.defaultPrevented) {
onDismiss(event);
}
}
);
const onFocusOutsideCallback = useCallbackRef((event) => {
onFocusOutside?.(event);
onInteractOutside?.(event);
if (!event.defaultPrevented) {
onDismiss(event);
}
});
React27.useEffect(() => {
if (!enabled) return;
function onPointerDown(event) {
const target = event.target;
if (preventScrollDismiss && event.pointerType === "touch") {
touchStartY.current = event.clientY;
return;
if (!target || isPointerInsideReactTreeRef.current) return;
const isInsideRefs = refs.some((ref) => ref.current?.contains(target));
if (isInsideRefs) return;
const outsideEvent = {
currentTarget: event.currentTarget,
target,
preventDefault: () => event.preventDefault(),
defaultPrevented: event.defaultPrevented,
detail: event.detail
};
if (event.pointerType === "touch" && preventScrollDismiss) {
if (!ownerDocument) return;
ownerDocument.removeEventListener("click", onClickRef.current);
onClickRef.current = () => onPointerDownOutsideCallback(outsideEvent);
ownerDocument.addEventListener("click", onClickRef.current, {
once: true
});
} else {
onPointerDownOutsideCallback(outsideEvent);
}
if (event.pointerType !== "touch") {
onDismissWithTarget(event, target);
}
}
function onPointerUp(event) {
function onFocusIn(event) {
const target = event.target;
if (preventScrollDismiss && event.pointerType === "touch" && touchStartY.current !== null) {
const deltaY = Math.abs(event.clientY - touchStartY.current);
touchStartY.current = null;
if (deltaY <= SCROLL_DISTANCE_THRESHOLD) {
onDismissWithTarget(event, target);
}
}
if (!target) return;
const isInsideRefs = refs.some((ref) => ref.current?.contains(target));
if (isInsideRefs) return;
const outsideEvent = {
currentTarget: event.currentTarget,
target,
preventDefault: () => event.preventDefault(),
defaultPrevented: event.defaultPrevented
};
onFocusOutsideCallback(outsideEvent);
}
function onFocusOut(event) {
const target = event.target;
const focusedInside = refs.some((ref) => ref.current?.contains(target));
if (!focusedInside && shouldTriggerEvents.current) {
const outsideEvent = {
currentTarget: event.currentTarget,
target,
preventDefault: () => event.preventDefault(),
defaultPrevented: event.defaultPrevented
};
onFocusOutside?.(outsideEvent);
onInteractOutside?.(outsideEvent);
if (!event.defaultPrevented && !outsideEvent.defaultPrevented) {
onDismissWithTarget(event, target);
}
}
}
if (disableOutsidePointerEvents) {

@@ -306,13 +539,10 @@ const elements = refs.map((ref) => ref.current).filter(Boolean);

const timeoutId = window.setTimeout(() => {
ownerDocument.addEventListener("keydown", onKeyDown);
ownerDocument.addEventListener("pointerdown", onPointerDown);
ownerDocument.addEventListener("pointerup", onPointerUp);
ownerDocument.addEventListener("focusout", onFocusOut);
ownerDocument.addEventListener("focusin", onFocusIn);
}, delayMs);
return () => {
window.clearTimeout(timeoutId);
ownerDocument.removeEventListener("keydown", onKeyDown);
ownerDocument.removeEventListener("pointerdown", onPointerDown);
ownerDocument.removeEventListener("pointerup", onPointerUp);
ownerDocument.removeEventListener("focusout", onFocusOut);
ownerDocument.removeEventListener("focusin", onFocusIn);
ownerDocument.removeEventListener("click", onClickRef.current);
if (disableOutsidePointerEvents) {

@@ -330,6 +560,4 @@ for (const ref of refs) {

refs,
onDismiss,
onPointerDownOutside,
onFocusOutside,
onInteractOutside,
onPointerDownOutsideCallback,
onFocusOutsideCallback,
disableOutsidePointerEvents,

@@ -342,9 +570,19 @@ preventScrollDismiss,

]);
return {
onPointerDownCapture: () => {
isPointerInsideReactTreeRef.current = true;
},
onPointerUpCapture: () => {
window.setTimeout(() => {
isPointerInsideReactTreeRef.current = false;
}, 0);
}
};
}
function useEventCallback(callback) {
const callbackRef = React26.useRef(callback);
React26.useLayoutEffect(() => {
const callbackRef = React27.useRef(callback);
React27.useLayoutEffect(() => {
callbackRef.current = callback;
});
return React26.useCallback((event, ...args) => {
return React27.useCallback((event, ...args) => {
const fn = callbackRef.current;

@@ -355,7 +593,7 @@ return fn(event, ...args);

function useEvent(callback) {
const callbackRef = React26.useRef(callback);
React26.useLayoutEffect(() => {
const callbackRef = React27.useRef(callback);
React27.useLayoutEffect(() => {
callbackRef.current = callback;
});
return React26.useCallback((...args) => {
return React27.useCallback((...args) => {
const fn = callbackRef.current;

@@ -365,3 +603,66 @@ return fn(...args);

}
var collatorCache = /* @__PURE__ */ new Map();
var LRUCache = class {
cache;
maxSize;
keyOrder;
constructor(maxSize) {
this.cache = /* @__PURE__ */ new Map();
this.maxSize = maxSize;
this.keyOrder = [];
}
get(key) {
const value = this.cache.get(key);
if (value !== void 0) {
const index = this.keyOrder.indexOf(key);
if (index > -1) {
this.keyOrder.splice(index, 1);
this.keyOrder.push(key);
}
}
return value;
}
set(key, value) {
if (this.cache.has(key)) {
this.cache.set(key, value);
const index = this.keyOrder.indexOf(key);
if (index > -1) {
this.keyOrder.splice(index, 1);
}
} else {
if (this.keyOrder.length >= this.maxSize) {
const lruKey = this.keyOrder.shift();
if (lruKey !== void 0) {
this.cache.delete(lruKey);
}
}
this.cache.set(key, value);
}
this.keyOrder.push(key);
}
clear() {
this.cache.clear();
this.keyOrder.length = 0;
}
get size() {
return this.cache.size;
}
};
var collatorCache = new LRUCache(10);
var normalizedCache = new LRUCache(1e3);
var SEPARATORS_PATTERN = /[-_\s./\\|:;,]+/g;
var UNWANTED_CHARS = /[^\p{L}\p{N}\s]/gu;
function normalizeWithGaps(str) {
if (!str) return "";
if (typeof str !== "string") return "";
const cached = normalizedCache.get(str);
if (cached !== void 0) return cached;
let normalized;
try {
normalized = str.toLowerCase().normalize("NFC").replace(UNWANTED_CHARS, " ").replace(SEPARATORS_PATTERN, " ").trim().replace(/\s+/g, "");
} catch (_err) {
normalized = str.toLowerCase().normalize("NFC").replace(/[^a-z0-9\s]/g, " ").trim().replace(/\s+/g, "");
}
normalizedCache.set(str, normalized);
return normalized;
}
function useFilter(options) {

@@ -371,6 +672,9 @@ const cacheKey = options ? Object.entries(options).sort((a, b) => a[0] < b[0] ? -1 : 1).join() : "";

if (!collator) {
collator = new Intl.Collator("en", options);
collator = new Intl.Collator("en", {
...options,
sensitivity: "base"
});
collatorCache.set(cacheKey, collator);
}
const startsWith = React26.useCallback(
const startsWith = React27.useCallback(
(string, substring) => {

@@ -380,2 +684,7 @@ if (substring.length === 0) {

}
if (options?.gapMatch) {
const normalizedString2 = normalizeWithGaps(string);
const normalizedSubstring2 = normalizeWithGaps(substring);
return normalizedString2.startsWith(normalizedSubstring2);
}
const normalizedString = string.normalize("NFC");

@@ -388,5 +697,5 @@ const normalizedSubstring = substring.normalize("NFC");

},
[collator]
[collator, options?.gapMatch]
);
const endsWith = React26.useCallback(
const endsWith = React27.useCallback(
(string, substring) => {

@@ -396,2 +705,7 @@ if (substring.length === 0) {

}
if (options?.gapMatch) {
const normalizedString2 = normalizeWithGaps(string);
const normalizedSubstring2 = normalizeWithGaps(substring);
return normalizedString2.endsWith(normalizedSubstring2);
}
const normalizedString = string.normalize("NFC");

@@ -404,5 +718,5 @@ const normalizedSubstring = substring.normalize("NFC");

},
[collator]
[collator, options?.gapMatch]
);
const contains = React26.useCallback(
const contains = React27.useCallback(
(string, substring) => {

@@ -412,2 +726,7 @@ if (substring.length === 0) {

}
if (options?.gapMatch) {
const normalizedString2 = normalizeWithGaps(string);
const normalizedSubstring2 = normalizeWithGaps(substring);
return normalizedString2.includes(normalizedSubstring2);
}
const normalizedString = string.normalize("NFC");

@@ -425,10 +744,23 @@ const normalizedSubstring = substring.normalize("NFC");

},
[collator]
[collator, options?.gapMatch]
);
const fuzzy = React26.useCallback(
const fuzzy = React27.useCallback(
(string, pattern) => {
if (pattern.length === 0) return true;
if (string.length === 0) return false;
const normalizedString = string.normalize("NFC").toLowerCase();
const normalizedPattern = pattern.normalize("NFC").toLowerCase();
if (options?.gapMatch) {
const normalizedString2 = normalizeWithGaps(string);
const normalizedPattern2 = normalizeWithGaps(pattern);
let patternIdx2 = 0;
let stringIdx2 = 0;
while (stringIdx2 < normalizedString2.length && patternIdx2 < normalizedPattern2.length) {
if (normalizedString2[stringIdx2] === normalizedPattern2[patternIdx2]) {
patternIdx2++;
}
stringIdx2++;
}
return patternIdx2 === normalizedPattern2.length;
}
const normalizedString = string.normalize("NFC");
const normalizedPattern = pattern.normalize("NFC");
let patternIdx = 0;

@@ -447,5 +779,5 @@ let stringIdx = 0;

},
[collator]
[collator, options?.gapMatch]
);
const memoizedFilter = React26.useMemo(
return React27.useMemo(
() => ({

@@ -459,6 +791,5 @@ startsWith,

);
return memoizedFilter;
}
function useFormControl(form) {
const [trigger, setTrigger] = React26.useState(null);
const [trigger, setTrigger] = React27.useState(null);
const isFormControl = trigger ? form || !!trigger.closest("form") : true;

@@ -473,3 +804,3 @@ return { isFormControl, trigger, onTriggerChange: setTrigger };

const onResetCallback = useCallbackRef(onReset);
React26.useEffect(() => {
React27.useEffect(() => {
if (!form) return;

@@ -485,13 +816,13 @@ function onFormReset() {

}
var useLayoutEffect3 = globalThis?.document ? React26.useLayoutEffect : () => {
var useLayoutEffect4 = globalThis?.document ? React27.useLayoutEffect : () => {
};
// src/hooks/use-id.ts
var useReactId = React26[" useId ".trim().toString()] || (() => void 0);
var useReactId = React27[" useId ".trim().toString()] || (() => void 0);
var count = 0;
function useId(deterministicId) {
const [id, setId] = React26.useState(
const [id, setId] = React27.useState(
typeof useReactId === "function" ? useReactId() : void 0
);
useLayoutEffect3(() => {
useLayoutEffect4(() => {
if (!deterministicId) setId((reactId) => reactId ?? String(count++));

@@ -501,6 +832,5 @@ }, [deterministicId]);

}
var useIsomorphicLayoutEffect = typeof window !== "undefined" ? React26.useLayoutEffect : React26.useEffect;
function useMounted() {
const [mounted, setMounted] = React26.useState(false);
useLayoutEffect3(() => {
const [mounted, setMounted] = React27.useState(false);
useLayoutEffect4(() => {
setMounted(true);

@@ -511,4 +841,4 @@ }, []);

function usePrevious(value) {
const ref = React26.useRef({ value, previous: value });
return React26.useMemo(() => {
const ref = React27.useRef({ value, previous: value });
return React27.useMemo(() => {
if (ref.current.value !== value) {

@@ -537,15 +867,15 @@ ref.current.previous = ref.current.value;

}) {
const max = React26.useMemo(
const max = React27.useMemo(
() => isValidMaxNumber(maxProp) ? maxProp : 100,
[maxProp]
);
const value = React26.useMemo(
const value = React27.useMemo(
() => isValidValueNumber(valueProp, max) ? valueProp : null,
[valueProp, max]
);
const state = React26.useMemo(
const state = React27.useMemo(
() => getProgressState(value, max),
[value, max]
);
const progressProps = React26.useMemo(
const progressProps = React27.useMemo(
() => ({

@@ -595,4 +925,4 @@ role: "progressbar",

}
function isPinchZoomActive() {
return (window.visualViewport?.scale ?? 1) !== 1;
function isPinchZoomActive(win = globalThis.window) {
return (win.visualViewport?.scale ?? 1) !== 1;
}

@@ -607,25 +937,39 @@ function getPlatform() {

// src/hooks/use-scroll-lock.ts
function getScrollbarWidth() {
return Math.max(0, window.innerWidth - document.documentElement.clientWidth);
var nonTextInputTypes = /* @__PURE__ */ new Set([
"checkbox",
"radio",
"range",
"color",
"file",
"image",
"button",
"submit",
"reset"
]);
function getCanOpenKeyboard(target) {
return target instanceof HTMLInputElement && !nonTextInputTypes.has(target.type) || target instanceof HTMLTextAreaElement || target instanceof HTMLElement && target.isContentEditable;
}
function getScrollbarHeight() {
return Math.max(
0,
window.innerHeight - document.documentElement.clientHeight
function isNodeScrollable(node) {
if (!node) return false;
const style = window.getComputedStyle(node);
const hasScrollStyle = /(auto|scroll)/.test(
style.overflow + style.overflowX + style.overflowY
);
return hasScrollStyle && (node.scrollHeight !== node.clientHeight || node.scrollWidth !== node.clientWidth);
}
function getOriginalStyles(element) {
const computedStyle = window.getComputedStyle(element);
return {
overflow: element.style.overflow,
paddingRight: element.style.paddingRight,
paddingBottom: element.style.paddingBottom,
position: element.style.position,
height: element.style.height,
width: element.style.width,
top: element.style.top,
left: element.style.left,
marginTop: computedStyle.marginTop,
marginBottom: computedStyle.marginBottom
};
function scrollIntoView(target) {
const root = document.scrollingElement || document.documentElement;
let currentNode = target;
while (currentNode && currentNode !== root) {
while (currentNode && !isNodeScrollable(currentNode)) {
currentNode = currentNode.parentElement;
}
if (!currentNode || currentNode === root) break;
const { top: scrollableTop } = currentNode.getBoundingClientRect();
const { top: targetTop } = target.getBoundingClientRect();
if (targetTop > scrollableTop + target.clientHeight) {
currentNode.scrollTop += targetTop - scrollableTop;
}
currentNode = currentNode.parentElement;
}
}

@@ -635,10 +979,10 @@ function getIsDvhSupported() {

}
function hasInsetScrollbars(referenceElement) {
function getIsInsetScroll(referenceElement) {
if (typeof document === "undefined") return false;
const doc = referenceElement ? referenceElement.ownerDocument : document;
const win = doc ? doc.defaultView : window;
if (!win) return false;
const doc = referenceElement?.ownerDocument ?? document;
const win = doc.defaultView ?? window;
return win.innerWidth - doc.documentElement.clientWidth > 0;
}
var preventScrollCount = 0;
var originalStyle = {};
function useScrollLock({

@@ -649,12 +993,14 @@ referenceElement,

} = {}) {
const scrollPositionRef = React26.useRef(0);
const originalStylesRef = React26.useRef({});
const scrollPositionRef = React27.useRef({ top: 0, left: 0 });
const resizeRef = React27.useRef(-1);
const scrollableRef = React27.useRef(null);
const cleanupRef = React27.useRef(null);
useIsomorphicLayoutEffect(() => {
if (!enabled) return;
const targetElement = referenceElement ?? document.body;
const documentElement = document.documentElement;
const ios = isIOS();
const firefox = isFirefox();
const safari = isSafari();
if (safari && !allowPinchZoom && (window.visualViewport?.scale ?? 1) !== 1) {
const doc = referenceElement?.ownerDocument ?? globalThis.document;
const win = doc.defaultView ?? globalThis.window;
const html = doc.documentElement;
const body = doc.body;
const shouldAllowPinchZoom = allowPinchZoom ?? win.visualViewport?.scale !== 1;
if (isSafari() && !shouldAllowPinchZoom) {
return;

@@ -664,48 +1010,158 @@ }

if (preventScrollCount !== 1) return;
scrollPositionRef.current = window.scrollY;
originalStylesRef.current = getOriginalStyles(targetElement);
const scrollbarWidth = getScrollbarWidth();
const scrollbarHeight = getScrollbarHeight();
if (ios) {
const scrollableElements = Array.from(
document.querySelectorAll("[data-scroll-lock-scrollable]")
);
Object.assign(targetElement.style, {
position: "fixed",
width: "100%",
top: `-${scrollPositionRef.current}px`,
left: "0",
overflow: scrollableElements.length ? "auto" : "hidden",
height: "100%",
"-webkit-overflow-scrolling": "touch"
});
for (const elem of scrollableElements) {
elem.style.overflow = "auto";
}
} else {
const dvhSupported = getIsDvhSupported();
const hasInsetScroll = hasInsetScrollbars(targetElement);
Object.assign(targetElement.style, {
overflow: "hidden",
...scrollbarWidth > 0 && {
paddingRight: `${scrollbarWidth}px`,
// Prevent content shift in Firefox
...firefox && !hasInsetScroll && {
marginRight: `${scrollbarWidth}px`
scrollPositionRef.current = {
top: win.scrollY,
left: win.scrollX
};
const htmlStyle = win.getComputedStyle(html);
const bodyStyle = win.getComputedStyle(body);
originalStyle = {
htmlOverflowY: html.style.overflowY,
htmlOverflowX: html.style.overflowX,
bodyPosition: body.style.position,
bodyWidth: body.style.width,
bodyHeight: body.style.height,
bodyOverflow: body.style.overflow,
bodyBoxSizing: body.style.boxSizing
};
const scrollbarWidth = Math.max(
0,
win.innerWidth - doc.documentElement.clientWidth
);
const scrollbarHeight = Math.max(
0,
win.innerHeight - doc.documentElement.clientHeight
);
const dvhSupported = getIsDvhSupported();
const isInsetScroll = getIsInsetScroll(referenceElement);
function onScrollLock() {
const isScrollbarGutterStable = htmlStyle.scrollbarGutter?.includes("stable");
const isScrollableY = html.scrollHeight > html.clientHeight;
const isScrollableX = html.scrollWidth > html.clientWidth;
const isOverflowYScroll = htmlStyle.overflowY === "scroll" || bodyStyle.overflowY === "scroll";
const isOverflowXScroll = htmlStyle.overflowX === "scroll" || bodyStyle.overflowX === "scroll";
const marginY = Number.parseFloat(bodyStyle.marginTop) + Number.parseFloat(bodyStyle.marginBottom);
const marginX = Number.parseFloat(bodyStyle.marginLeft) + Number.parseFloat(bodyStyle.marginRight);
if (isIOS()) {
let onTouchStart2 = function(event) {
const target = event.target;
let currentNode = target;
while (currentNode && currentNode !== html) {
if (isNodeScrollable(currentNode) && currentNode instanceof HTMLElement) {
scrollableRef.current = currentNode;
const style = win.getComputedStyle(currentNode);
if (style.overscrollBehavior === "auto") {
currentNode.style.overscrollBehavior = "contain";
}
break;
}
currentNode = currentNode.parentElement;
}
},
...scrollbarHeight > 0 && {
paddingBottom: `${scrollbarHeight}px`
},
// Use dvh if supported for better mobile handling
...dvhSupported && {
height: "100dvh"
if (!currentNode || currentNode === html) {
scrollableRef.current = null;
}
}, onTouchMove2 = function(event) {
const scrollable = scrollableRef.current;
if (!scrollable || scrollable === html || scrollable === body) {
event.preventDefault();
return;
}
if (scrollable.scrollHeight === scrollable.clientHeight && scrollable.scrollWidth === scrollable.clientWidth) {
event.preventDefault();
}
}, onFocus2 = function(event) {
const target = event.target;
if (getCanOpenKeyboard(target)) {
target.style.transform = "translateY(-2000px)";
requestAnimationFrame(() => {
target.style.transform = "";
if (!win.visualViewport) return;
if (win.visualViewport.height < win.innerHeight) {
requestAnimationFrame(() => scrollIntoView(target));
return;
}
win.visualViewport.addEventListener(
"resize",
() => scrollIntoView(target),
{ once: true }
);
});
}
};
Object.assign(body.style, {
position: "fixed",
width: marginX || scrollbarWidth ? `calc(100vw - ${marginX + scrollbarWidth}px)` : "100vw",
height: marginY || scrollbarHeight ? `calc(100vh - ${marginY + scrollbarHeight}px)` : "100vh",
top: `-${scrollPositionRef.current.top}px`,
left: `-${scrollPositionRef.current.left}px`,
overflow: "hidden",
boxSizing: "border-box"
});
doc.addEventListener("touchstart", onTouchStart2, {
passive: false,
capture: true
});
doc.addEventListener("touchmove", onTouchMove2, {
passive: false,
capture: true
});
doc.addEventListener("focus", onFocus2, true);
cleanupRef.current = () => {
doc.removeEventListener("touchstart", onTouchStart2, {
capture: true
});
doc.removeEventListener("touchmove", onTouchMove2, {
capture: true
});
doc.removeEventListener("focus", onFocus2, true);
};
} else {
Object.assign(html.style, {
overflowY: !isScrollbarGutterStable && (isScrollableY || isOverflowYScroll) ? "scroll" : "hidden",
overflowX: !isScrollbarGutterStable && (isScrollableX || isOverflowXScroll) ? "scroll" : "hidden",
paddingRight: scrollbarWidth > 0 ? `${scrollbarWidth}px` : ""
});
Object.assign(body.style, {
position: "relative",
width: marginX || scrollbarWidth ? `calc(100vw - ${marginX + scrollbarWidth}px)` : "100vw",
height: dvhSupported ? marginY ? `calc(100dvh - ${marginY}px)` : "100dvh" : marginY ? `calc(100vh - ${marginY}px)` : "100vh",
boxSizing: "border-box",
overflow: "hidden"
});
if (isFirefox() && !isInsetScroll) {
body.style.marginRight = `${scrollbarWidth}px`;
}
body.scrollTop = scrollPositionRef.current.top;
body.scrollLeft = scrollPositionRef.current.left;
html.setAttribute("data-scroll-locked", "");
}
}
function onScrollUnlock() {
Object.assign(html.style, {
overflowY: originalStyle.htmlOverflowY,
overflowX: originalStyle.htmlOverflowX,
paddingRight: ""
});
Object.assign(documentElement.style, {
overflow: "hidden",
// Prevent iOS momentum scrolling
overscrollBehavior: "none"
Object.assign(body.style, {
overflow: originalStyle.bodyOverflow,
position: originalStyle.bodyPosition,
width: originalStyle.bodyWidth,
height: originalStyle.bodyHeight,
boxSizing: originalStyle.bodyBoxSizing,
marginRight: "",
top: "",
left: ""
});
html.removeAttribute("data-scroll-locked");
win.scrollTo(
scrollPositionRef.current.left,
scrollPositionRef.current.top
);
}
function onResize() {
cancelAnimationFrame(resizeRef.current);
resizeRef.current = requestAnimationFrame(() => {
onScrollUnlock();
onScrollLock();
});
}
function preventDefault(event) {

@@ -715,4 +1171,6 @@ if (event.touches.length > 1) return;

}
if (ios) {
document.addEventListener("touchmove", preventDefault, {
onScrollLock();
win.addEventListener("resize", onResize);
if (isIOS()) {
doc.addEventListener("touchmove", preventDefault, {
passive: false

@@ -724,10 +1182,8 @@ });

if (preventScrollCount !== 0) return;
Object.assign(targetElement.style, originalStylesRef.current);
Object.assign(documentElement.style, {
overflow: "",
overscrollBehavior: ""
});
if (ios) {
document.removeEventListener("touchmove", preventDefault);
window.scrollTo(0, scrollPositionRef.current);
cancelAnimationFrame(resizeRef.current);
onScrollUnlock();
win.removeEventListener("resize", onResize);
if (isIOS()) {
doc.removeEventListener("touchmove", preventDefault);
cleanupRef.current?.();
}

@@ -738,4 +1194,4 @@ };

function useSize(element) {
const [size, setSize] = React26.useState(void 0);
useLayoutEffect3(() => {
const [size2, setSize] = React27.useState(void 0);
useLayoutEffect4(() => {
if (element) {

@@ -769,12 +1225,16 @@ setSize({ width: element.offsetWidth, height: element.offsetHeight });

}, [element]);
return size;
return size2;
}
function useStateMachine(initialState, machine) {
return React26.useReducer(
(state, event) => {
const nextState = machine[state][event];
return nextState ?? state;
function useStateMachine(config) {
const [state, setState] = React27.useState(config.initial);
const send = React27.useCallback(
(event) => {
setState((currentState) => {
const transition = config.states[currentState]?.[event];
return transition ?? currentState;
});
},
initialState
[config.states]
);
return [state, send];
}

@@ -806,5 +1266,5 @@ function wrapArray(array, startIndex) {

const onSearchChangeCallback = useCallbackRef(onSearchChange);
const searchRef = React26.useRef("");
const timerRef = React26.useRef(0);
const onTypeaheadSearch = React26.useCallback(
const searchRef = React27.useRef("");
const timerRef = React27.useRef(0);
const onTypeaheadSearch = React27.useCallback(
(key) => {

@@ -831,7 +1291,7 @@ if (!enabled) return;

);
const onResetTypeahead = React26.useCallback(() => {
const onResetTypeahead = React27.useCallback(() => {
searchRef.current = "";
window.clearTimeout(timerRef.current);
}, []);
React26.useEffect(() => {
React27.useEffect(() => {
return () => window.clearTimeout(timerRef.current);

@@ -858,7 +1318,7 @@ }, []);

} = props;
const ref = React26.useRef(null);
const ref = React27.useRef(null);
const prevValue = usePrevious(type === "hidden" ? value : checked);
const controlSize = useSize(control);
const isCheckInput = type === "checkbox" || type === "radio" || type === "switch";
React26.useEffect(() => {
React27.useEffect(() => {
const input = ref.current;

@@ -888,3 +1348,3 @@ if (!input) return;

});
return /* @__PURE__ */ React26.createElement(
return /* @__PURE__ */ React27.createElement(
"input",

@@ -909,16 +1369,33 @@ {

}
function setRef(ref, value) {
if (typeof ref === "function") {
ref(value);
} else if (ref !== null && ref !== void 0) {
ref.current = value;
}
}
function composeRefs(...refs) {
return (node) => {
for (const ref of refs) {
setRef(ref, node);
}
};
}
function useComposedRefs(...refs) {
return React27.useCallback(composeRefs(...refs), refs);
}
function createContext3(rootComponentName, defaultValue) {
const Context = React26.createContext(defaultValue);
const Context = React27.createContext(defaultValue);
Context.displayName = rootComponentName;
function Provider(props) {
const { children, ...contextValue } = props;
const value = React26.useMemo(
const value = React27.useMemo(
() => contextValue,
Object.values(contextValue)
);
return /* @__PURE__ */ React26.createElement(Context.Provider, { value }, children);
return /* @__PURE__ */ React27.createElement(Context.Provider, { value }, children);
}
Provider.displayName = `${rootComponentName}Provider`;
function useContext3(consumerName, required) {
const context = React26.useContext(Context);
const context = React27.useContext(Context);
if (context) return context;

@@ -935,3 +1412,225 @@ if (defaultValue !== void 0) return defaultValue;

}
function getElementRef(element) {
if (!React27.isValidElement(element)) return void 0;
const propDescriptor = Object.getOwnPropertyDescriptor(element.props, "ref");
const elementDescriptor = Object.getOwnPropertyDescriptor(element, "ref");
if (propDescriptor?.get && "isReactWarning" in propDescriptor.get) {
return element.ref;
}
if (elementDescriptor?.get && "isReactWarning" in elementDescriptor.get) {
return element.props.ref;
}
return element.props.ref ?? element.ref;
}
// src/components/slot.tsx
var isSlottable = function isSlottable2(child) {
return React27.isValidElement(child) && child.type === Slottable;
};
function mergeProps(slotProps, childProps) {
const overrideProps = { ...childProps };
for (const propName in childProps) {
const slotPropValue = slotProps[propName];
const childPropValue = childProps[propName];
if (/^on[A-Z]/.test(propName)) {
if (typeof slotPropValue === "function" && typeof childPropValue === "function") {
overrideProps[propName] = (...args) => {
childPropValue(...args);
slotPropValue(...args);
};
} else if (typeof slotPropValue === "function") {
overrideProps[propName] = slotPropValue;
}
} else if (propName === "style" && slotPropValue && childPropValue) {
overrideProps[propName] = {
...slotPropValue,
...childPropValue
};
} else if (propName === "className") {
overrideProps[propName] = [slotPropValue, childPropValue].filter(Boolean).join(" ");
}
}
return { ...slotProps, ...overrideProps };
}
var SlotClone = React27.forwardRef(
(props, forwardedRef) => {
const { children, ...slotProps } = props;
if (!React27.isValidElement(children)) {
return React27.Children.count(children) > 1 ? React27.Children.only(null) : null;
}
const childrenRef = getElementRef(children);
const mergedProps = mergeProps(
slotProps,
children.props
);
if (typeof children.type === "string") {
return React27.cloneElement(children, {
...mergedProps,
ref: forwardedRef ? composeRefs(forwardedRef, childrenRef) : childrenRef
});
}
return React27.cloneElement(children, {
...mergedProps,
ref: forwardedRef ? composeRefs(forwardedRef, childrenRef) : childrenRef
});
}
);
SlotClone.displayName = "SlotClone";
var Slot = React27.forwardRef((props, forwardedRef) => {
const { children, ...slotProps } = props;
const childrenArray = React27.Children.toArray(children);
const slottable = childrenArray.find(isSlottable);
if (!slottable) {
return /* @__PURE__ */ React27.createElement(SlotClone, { ...slotProps, ref: forwardedRef }, children);
}
if (!React27.isValidElement(slottable)) {
return null;
}
const newElement = slottable.props.children;
const newChildren = childrenArray.map((child) => {
if (child === slottable) {
if (React27.Children.count(newElement) > 1) {
return React27.Children.only(null);
}
return React27.isValidElement(newElement) ? newElement.props.children : null;
}
return child;
});
return /* @__PURE__ */ React27.createElement(SlotClone, { ...slotProps, ref: forwardedRef }, React27.isValidElement(newElement) ? React27.cloneElement(newElement, void 0, newChildren) : null);
});
Slot.displayName = "Slot";
var Slottable = React27.memo(function Slottable2({ children }) {
return /* @__PURE__ */ React27.createElement(React27.Fragment, null, children);
});
Slottable.displayName = "Slottable";
// src/components/collection.tsx
function createCollection(name) {
const PROVIDER_NAME = `${name}CollectionProvider`;
const COLLECTION_SLOT_NAME = `${name}CollectionSlot`;
const ITEM_SLOT_NAME = `${name}CollectionItemSlot`;
const [CollectionProvider, useCollectionContext] = createContext3(
PROVIDER_NAME
);
const CollectionSlot = React27.memo(
React27.forwardRef((props, forwardedRef) => {
const context = useCollectionContext(COLLECTION_SLOT_NAME);
const composedRefs = React27.useMemo(
() => composeRefs(forwardedRef, context.collectionRef),
[forwardedRef, context.collectionRef]
);
return /* @__PURE__ */ React27.createElement(Slot, { ref: composedRefs, ...props });
})
);
CollectionSlot.displayName = COLLECTION_SLOT_NAME;
const CollectionItemSlot = React27.memo(
React27.forwardRef(
(props, forwardedRef) => {
const { children, ...itemProps } = props;
const context = useCollectionContext(ITEM_SLOT_NAME);
const itemRef = React27.useRef(null);
const itemPropsRef = React27.useRef(itemProps);
itemPropsRef.current = itemProps;
const composedRef = composeRefs(forwardedRef, itemRef);
React27.useEffect(() => {
const node = itemRef.current;
if (!node) return;
const item = {
ref: itemRef,
...itemPropsRef.current
};
context.itemMap.set(itemRef, item);
return () => void context.itemMap.delete(itemRef);
}, [context.itemMap]);
return /* @__PURE__ */ React27.createElement(Slot, { ...{ [DATA_ITEM_ATTR]: "" }, ref: composedRef }, children);
}
)
);
CollectionItemSlot.displayName = ITEM_SLOT_NAME;
function useCollection2({
collectionRef,
itemMap
}) {
const getItems = React27.useCallback(() => {
const collectionNode = collectionRef.current;
if (!collectionNode) return [];
try {
const items = Array.from(itemMap.values());
const fallbackDiv = globalThis.document?.createElement("div");
return items.sort((a, b) => {
const aNode = a?.ref.current ?? fallbackDiv;
const bNode = b?.ref.current ?? fallbackDiv;
return compareNodePosition(aNode, bNode);
});
} catch (_err) {
return [];
}
}, [collectionRef, itemMap]);
return React27.useMemo(() => ({ getItems }), [getItems]);
}
return [
{
CollectionProvider,
CollectionSlot,
CollectionItemSlot
},
useCollection2
];
}
function createPrimitive(element) {
const Primitive2 = React27.forwardRef((props, forwardedRef) => {
const { asChild, ...primitiveProps } = props;
if (asChild) {
return React27.createElement(Slot, {
...primitiveProps,
ref: forwardedRef
});
}
return React27.createElement(element, {
...primitiveProps,
ref: forwardedRef
});
});
Primitive2.displayName = `Primitive.${String(element)}`;
return Primitive2;
}
var cache = /* @__PURE__ */ new Map();
var Primitive = new Proxy(
{},
{
get: (_, element) => {
const key = element;
if (!cache.has(key)) {
cache.set(key, createPrimitive(key));
}
return cache.get(key);
}
}
);
function dispatchDiscreteCustomEvent(target, event) {
if (target) {
const evt = new CustomEvent(event.type, {
bubbles: true,
cancelable: true,
detail: event.detail
});
target.dispatchEvent(evt);
}
}
// src/components/portal.tsx
var Portal = React27.forwardRef(
(props, forwardedRef) => {
const { container, ...portalProps } = props;
const mounted = useMounted();
const dynamicContainer = container ?? (mounted ? globalThis.document?.body : null);
if (!dynamicContainer) return null;
return ReactDOM.createPortal(
/* @__PURE__ */ React27.createElement(Primitive.div, { ...portalProps, ref: forwardedRef }),
dynamicContainer
);
}
);
Portal.displayName = "Portal";
// src/lib/compose-event-handlers.ts

@@ -946,22 +1645,5 @@ function composeEventHandlers(originalEventHandler, ourEventHandler, { checkForDefaultPrevented = true } = {}) {

}
function setRef(ref, value) {
if (typeof ref === "function") {
ref(value);
} else if (ref !== null && ref !== void 0) {
ref.current = value;
}
function forwardRef6(render) {
return React27.forwardRef(render);
}
function composeRefs(...refs) {
return (node) => {
for (const ref of refs) {
setRef(ref, node);
}
};
}
function useComposedRefs(...refs) {
return React26.useCallback(composeRefs(...refs), refs);
}
function forwardRef2(render) {
return React26.forwardRef(render);
}

@@ -972,34 +1654,37 @@ // src/components/presence.tsx

const presence = usePresence(present);
const child = typeof children === "function" ? children({ present: presence.isPresent }) : React26.Children.only(children);
const child = typeof children === "function" ? children({ present: presence.isPresent }) : React27.Children.only(children);
const ref = useComposedRefs(presence.ref, getElementRef(child));
const forceMount = typeof children === "function";
return forceMount || presence.isPresent ? React26.cloneElement(child, { ref }) : null;
return forceMount || presence.isPresent ? React27.cloneElement(child, { ref }) : null;
};
Presence.displayName = "Presence";
function usePresence(present) {
const [node, setNode] = React26.useState();
const stylesRef = React26.useRef(
const [node, setNode] = React27.useState();
const stylesRef = React27.useRef(
{}
);
const prevPresentRef = React26.useRef(present);
const prevAnimationNameRef = React26.useRef("none");
const prevPresentRef = React27.useRef(present);
const prevAnimationNameRef = React27.useRef("none");
const initialState = present ? "mounted" : "unmounted";
const [state, send] = useStateMachine(initialState, {
mounted: {
UNMOUNT: "unmounted",
ANIMATION_OUT: "unmountSuspended"
},
unmountSuspended: {
MOUNT: "mounted",
ANIMATION_END: "unmounted"
},
unmounted: {
MOUNT: "mounted"
const [state, send] = useStateMachine({
initial: initialState,
states: {
mounted: {
UNMOUNT: "unmounted",
ANIMATION_OUT: "unmountSuspended"
},
unmountSuspended: {
MOUNT: "mounted",
ANIMATION_END: "unmounted"
},
unmounted: {
MOUNT: "mounted"
}
}
});
React26.useEffect(() => {
React27.useEffect(() => {
const currentAnimationName = getAnimationName(stylesRef.current);
prevAnimationNameRef.current = state === "mounted" ? currentAnimationName : "none";
}, [state]);
useLayoutEffect3(() => {
useLayoutEffect4(() => {
const styles = stylesRef.current;

@@ -1026,3 +1711,3 @@ const wasPresent = prevPresentRef.current;

}, [present, send]);
useLayoutEffect3(() => {
useLayoutEffect4(() => {
if (node) {

@@ -1067,3 +1752,3 @@ let onAnimationEnd2 = function(event) {

isPresent: ["mounted", "unmountSuspended"].includes(state),
ref: React26.useCallback((node2) => {
ref: React27.useCallback((node2) => {
if (node2) stylesRef.current = getComputedStyle(node2);

@@ -1077,16 +1762,3 @@ setNode(node2);

}
function getElementRef(element) {
let getter = Object.getOwnPropertyDescriptor(element.props, "ref")?.get;
let mayWarn = getter && "isReactWarning" in getter && getter.isReactWarning;
if (mayWarn) {
return element.ref;
}
getter = Object.getOwnPropertyDescriptor(element, "ref")?.get;
mayWarn = getter && "isReactWarning" in getter && getter.isReactWarning;
if (mayWarn) {
return element.props.ref;
}
return element.props.ref || element.ref;
}
export { BubbleInput, DATA_DISMISSABLE_LAYER_ATTR, DATA_DISMISSABLE_LAYER_STYLE_ATTR, DATA_ITEM_ATTR, DATA_VALUE_ATTR, Presence, VAR_ANCHOR_HEIGHT, VAR_ANCHOR_WIDTH, VAR_AVAILABLE_HEIGHT, VAR_AVAILABLE_WIDTH, VAR_TRANSFORM_ORIGIN, composeEventHandlers, composeRefs, createContext3 as createContext, findNextItem, forwardRef2 as forwardRef, getItem, getOwnerDocument, getOwnerWindow, getPlatform, getProgressState, getSortedItems, isFirefox, isIOS, isIPad, isIPhone, isMac, isMobileFirefox, isPinchZoomActive, isSafari, testPlatform, useAnchor, useCallbackRef, useCollection, useCollectionItem, useComposedRefs, useControllableState, useDirection, useDismiss, useEscapeKeydown, useEvent, useEventCallback, useFilter, useFormControl, useFormReset, useId, useIsomorphicLayoutEffect, useLayoutEffect3 as useLayoutEffect, useMounted, usePrevious, useProgress, useScrollLock, useSize, useStateMachine, useTypeahead, wrapArray };
export { BubbleInput, DATA_DISMISSABLE_LAYER_ATTR, DATA_DISMISSABLE_LAYER_STYLE_ATTR, DATA_ITEM_ATTR, DATA_VALUE_ATTR, Portal, Presence, Primitive, Slot, Slottable, VAR_ANCHOR_HEIGHT, VAR_ANCHOR_WIDTH, VAR_AVAILABLE_HEIGHT, VAR_AVAILABLE_WIDTH, VAR_TRANSFORM_ORIGIN, compareNodePosition, composeEventHandlers, composeRefs, createCollection, createContext3 as createContext, dispatchDiscreteCustomEvent, findNextItem, forwardRef6 as forwardRef, getOwnerDocument, getOwnerWindow, getPlatform, getProgressState, getSortedItems, isFirefox, isIOS, isIPad, isIPhone, isMac, isMobileFirefox, isPinchZoomActive, isSafari, testPlatform, useAnchor, useAnchorPositioner, useCallbackRef, useCollection, useComposedRefs, useControllableState, useDirection, useDismiss, useEscapeKeydown, useEvent, useEventCallback, useFilter, useFormControl, useFormReset, useId, useIsomorphicLayoutEffect, useLayoutEffect4 as useLayoutEffect, useMounted, usePrevious, useProgress, useScrollLock, useSize, useStateMachine, useTypeahead, wrapArray };
{
"name": "@diceui/shared",
"version": "0.4.0",
"version": "0.5.0",
"publishConfig": {
"access": "public"
},
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",

@@ -13,4 +13,4 @@ "exports": {

"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.js"
"import": "./dist/index.js",
"require": "./dist/index.cjs"
}

@@ -25,3 +25,6 @@ },

"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"@floating-ui/react": "^0.27.2"
},

@@ -31,2 +34,5 @@ "peerDependenciesMeta": {

"optional": true
},
"@types/react-dom": {
"optional": true
}

@@ -41,4 +47,5 @@ },

"build": "tsup --clean",
"typecheck": "tsc --noEmit"
"typecheck": "tsc --noEmit",
"test": "vitest run"
}
}