@mercury-fx/core 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +32 -0
  3. package/dist/cx.d.ts +3 -0
  4. package/dist/date.d.ts +7 -0
  5. package/dist/index.d.ts +32 -0
  6. package/dist/internal/arrays.d.ts +95 -0
  7. package/dist/internal/attrs.d.ts +33 -0
  8. package/dist/internal/clamp.d.ts +4 -0
  9. package/dist/internal/create-id.d.ts +8 -0
  10. package/dist/internal/css-escape.d.ts +7 -0
  11. package/dist/internal/date-time/calendar/use-calendar.d.ts +63 -0
  12. package/dist/internal/date-time/field/helpers.d.ts +86 -0
  13. package/dist/internal/date-time/field/parts.d.ts +8 -0
  14. package/dist/internal/date-time/field/segments.d.ts +60 -0
  15. package/dist/internal/date-time/field/time-helpers.d.ts +82 -0
  16. package/dist/internal/date-time/field/types.d.ts +25 -0
  17. package/dist/internal/date-time/field/use-date-field.d.ts +61 -0
  18. package/dist/internal/date-time/formatter.d.ts +114 -0
  19. package/dist/internal/date-time/placeholders.d.ts +8 -0
  20. package/dist/internal/date-time/time-value.d.ts +11 -0
  21. package/dist/internal/date-time/utils.d.ts +76 -0
  22. package/dist/internal/debounce.d.ts +4 -0
  23. package/dist/internal/dom.d.ts +7 -0
  24. package/dist/internal/elements.d.ts +2 -0
  25. package/dist/internal/focus.d.ts +5 -0
  26. package/dist/internal/get-directional-keys.d.ts +21 -0
  27. package/dist/internal/is.d.ts +25 -0
  28. package/dist/internal/kbd-constants.d.ts +42 -0
  29. package/dist/internal/kbd.d.ts +1 -0
  30. package/dist/internal/locale.d.ts +6 -0
  31. package/dist/internal/math.d.ts +1 -0
  32. package/dist/internal/noop.d.ts +4 -0
  33. package/dist/internal/should-enable-focus-trap.d.ts +4 -0
  34. package/dist/internal/types.d.ts +14 -0
  35. package/dist/internal/use-anchored-position.d.ts +45 -0
  36. package/dist/internal/use-arrow-navigation.d.ts +62 -0
  37. package/dist/internal/use-dismiss.d.ts +31 -0
  38. package/dist/internal/use-focus-trap.d.ts +31 -0
  39. package/dist/internal/use-id.d.ts +6 -0
  40. package/dist/internal/warn.d.ts +1 -0
  41. package/dist/mercury-core.js +865 -0
  42. package/dist/mercury-core.js.map +1 -0
  43. package/dist/shared/date/types.d.ts +100 -0
  44. package/dist/shared/index.d.ts +36 -0
  45. package/dist/shared/types.d.ts +13 -0
  46. package/dist/types.d.ts +31 -0
  47. package/dist/utils/after-sleep.d.ts +4 -0
  48. package/dist/utils/clsx.d.ts +7 -0
  49. package/dist/utils/dom.d.ts +14 -0
  50. package/dist/utils/event-list.d.ts +1 -0
  51. package/dist/utils/events.d.ts +13 -0
  52. package/dist/utils/execute-callbacks.d.ts +7 -0
  53. package/dist/utils/is.d.ts +4 -0
  54. package/dist/utils/merge-props.d.ts +22 -0
  55. package/dist/utils/strings.d.ts +3 -0
  56. package/dist/utils/style-to-css.d.ts +9 -0
  57. package/dist/utils/style.d.ts +2 -0
  58. package/package.json +51 -0
@@ -0,0 +1,114 @@
1
+ import { DateValue } from '@internationalized/date';
2
+ import { HourCycle, TimeValue } from '../..shared/date/types.js';
3
+ /**
4
+ * A read-only, *live* value source — anything that exposes its current value
5
+ * behind a `current` getter. A Svelte `box`, a signal wrapper, or the Effector
6
+ * adapter from `@mercury-fx/effector` (`createFormatterModel`) all satisfy it. The
7
+ * formatter reads `.current` on every call, so changes to the source are picked
8
+ * up immediately with no rebuild and no framework coupling in this package.
9
+ */
10
+ export interface Readable<T> {
11
+ readonly current: T;
12
+ }
13
+ /** A formatter input that may be a plain value or a live {@link Readable}. */
14
+ export type MaybeReadable<T> = T | Readable<T>;
15
+ /**
16
+ * How the month renders in {@link Formatter.fullMonthAndYear}: an `Intl` month
17
+ * style (`"long"`, `"short"`, `"narrow"`, `"numeric"`, `"2-digit"`) or a custom
18
+ * mapper from the 1-based month number to a string.
19
+ */
20
+ export type MonthFormat = NonNullable<Intl.DateTimeFormatOptions["month"]> | ((month: number) => string);
21
+ /**
22
+ * How the year renders in {@link Formatter.fullMonthAndYear}: an `Intl` year
23
+ * style (`"numeric"`, `"2-digit"`) or a custom mapper from the full year.
24
+ */
25
+ export type YearFormat = NonNullable<Intl.DateTimeFormatOptions["year"]> | ((year: number) => string);
26
+ /** The resolved day period. */
27
+ export type DayPeriodValue = "AM" | "PM";
28
+ /** Options for {@link createFormatter}. Only `locale` is required. */
29
+ export interface FormatterOptions {
30
+ /** BCP-47 locale tag. Static, or a live source to follow a locale store. */
31
+ locale: MaybeReadable<string>;
32
+ /** Month rendering for `fullMonthAndYear`. Defaults to `"long"`. */
33
+ monthFormat?: MaybeReadable<MonthFormat>;
34
+ /** Year rendering for `fullMonthAndYear`. Defaults to `"numeric"`. */
35
+ yearFormat?: MaybeReadable<YearFormat>;
36
+ }
37
+ /**
38
+ * The locale-aware date-formatting surface used across the date builders. Every
39
+ * method goes through `Intl`'s {@link DateFormatter} at the *current* locale, so
40
+ * output stays consistent and updates when a live `locale` source changes.
41
+ */
42
+ export interface Formatter {
43
+ /** Imperatively override the active locale (wins over a live `locale` source). */
44
+ setLocale(newLocale: string): void;
45
+ /** The active locale — the override if one was set, else the (possibly live) source. */
46
+ getLocale(): string;
47
+ /** Format a native `Date` with arbitrary `Intl` options. */
48
+ custom(date: Date, options: Intl.DateTimeFormatOptions): string;
49
+ /** A human "selected date" string, with time included when the value carries one. */
50
+ selectedDate(date: DateValue, includeTime?: boolean): string;
51
+ /** The full month + year, honoring `monthFormat` / `yearFormat`. */
52
+ fullMonthAndYear(date: Date): string;
53
+ /** The full ("long") month name. */
54
+ fullMonth(date: Date): string;
55
+ /** The numeric year. */
56
+ fullYear(date: Date): string;
57
+ /** The `Intl` parts of a date value, timezone-aware for zoned values. */
58
+ toParts(date: DateValue, options?: Intl.DateTimeFormatOptions): Intl.DateTimeFormatPart[];
59
+ /** A single weekday label at the given width (default `"narrow"`). */
60
+ dayOfWeek(date: Date, length?: Intl.DateTimeFormatOptions["weekday"]): string;
61
+ /** "AM" / "PM" for the given instant under the (optional) hour cycle. */
62
+ dayPeriod(date: Date, hourCycle?: HourCycle): DayPeriodValue;
63
+ /** The string value of one `Intl` part of a date value (`""` if absent). */
64
+ part(dateObj: DateValue, type: Intl.DateTimeFormatPartTypes, options?: Intl.DateTimeFormatOptions): string;
65
+ }
66
+ /** Options for {@link createTimeFormatter}. */
67
+ export interface TimeFormatterOptions {
68
+ /** BCP-47 locale tag. Static, or a live source to follow a locale store. */
69
+ locale: MaybeReadable<string>;
70
+ }
71
+ /** The locale-aware time-formatting surface (the time-only counterpart to {@link Formatter}). */
72
+ export interface TimeFormatter {
73
+ /** Imperatively override the active locale (wins over a live `locale` source). */
74
+ setLocale(newLocale: string): void;
75
+ /** The active locale — the override if one was set, else the (possibly live) source. */
76
+ getLocale(): string;
77
+ /** Format a native `Date` with arbitrary `Intl` options. */
78
+ custom(date: Date, options: Intl.DateTimeFormatOptions): string;
79
+ /** A human "selected time" string (long time style). */
80
+ selectedTime(date: TimeValue): string;
81
+ /** The `Intl` parts of a time value, timezone-aware for zoned values. */
82
+ toParts(timeValue: TimeValue, options?: Intl.DateTimeFormatOptions): Intl.DateTimeFormatPart[];
83
+ /** "AM" / "PM" for the given instant under the (optional) hour cycle. */
84
+ dayPeriod(date: Date, hourCycle?: HourCycle): DayPeriodValue;
85
+ /** The string value of one `Intl` part of a time value (`""` if absent). */
86
+ part(dateObj: TimeValue, type: Intl.DateTimeFormatPartTypes, options?: Intl.DateTimeFormatOptions): string;
87
+ }
88
+ /**
89
+ * Creates a typed wrapper around `@internationalized/date`'s {@link DateFormatter}
90
+ * — itself an improved {@link Intl.DateTimeFormat} — used by the date builders to
91
+ * format dates consistently.
92
+ *
93
+ * The wrapper is framework-agnostic: pass plain values for a static formatter, or
94
+ * {@link Readable} sources (Svelte boxes, signals, the `@mercury-fx/effector` store
95
+ * adapter) for one that tracks live locale / format changes.
96
+ *
97
+ * @example Static
98
+ * ```ts
99
+ * const fmt = createFormatter({ locale: "en-GB" });
100
+ * fmt.fullMonthAndYear(new Date()); // "December 2025"
101
+ * ```
102
+ * @example Live (Effector — see `@mercury-fx/effector` `createFormatterModel`)
103
+ * ```ts
104
+ * const fmt = createFormatter({ locale: { get current() { return $locale.getState(); } } });
105
+ * ```
106
+ *
107
+ * @see [DateFormatter](https://react-spectrum.adobe.com/internationalized/date/DateFormatter.html)
108
+ */
109
+ export declare function createFormatter(opts: FormatterOptions): Formatter;
110
+ /**
111
+ * The time-only counterpart to {@link createFormatter}. Accepts a plain locale
112
+ * string or a live {@link Readable} source, the same way.
113
+ */
114
+ export declare function createTimeFormatter(locale: MaybeReadable<string>): TimeFormatter;
@@ -0,0 +1,8 @@
1
+ declare const supportedLocales: readonly ["ach", "af", "am", "an", "ar", "ast", "az", "be", "bg", "bn", "br", "bs", "ca", "cak", "ckb", "cs", "cy", "da", "de", "dsb", "el", "en", "eo", "es", "et", "eu", "fa", "ff", "fi", "fr", "fy", "ga", "gd", "gl", "he", "hr", "hsb", "hu", "ia", "id", "it", "ja", "ka", "kk", "kn", "ko", "lb", "lo", "lt", "lv", "meh", "ml", "ms", "nl", "nn", "no", "oc", "pl", "pt", "rm", "ro", "ru", "sc", "scn", "sk", "sl", "sr", "sv", "szl", "tg", "th", "tr", "uk", "zh-CN", "zh-TW"];
2
+ declare const placeholderFields: readonly ["year", "month", "day"];
3
+ type SupportedLocale = (typeof supportedLocales)[number];
4
+ type PlaceholderField = (typeof placeholderFields)[number];
5
+ export type PlaceholderMap = Record<SupportedLocale, Record<PlaceholderField, string>>;
6
+ type Field = "era" | "year" | "month" | "day" | "hour" | "minute" | "second" | "dayPeriod";
7
+ export declare function getPlaceholder(field: Field, value: string, locale: SupportedLocale | (string & {})): string;
8
+ export {};
@@ -0,0 +1,11 @@
1
+ import { CalendarDateTime, ZonedDateTime } from '@internationalized/date';
2
+ import { TimeValue } from '../..shared/date/types.js';
3
+ /**
4
+ * Normalize a {@link TimeValue} to a date-bearing value the `Intl` formatters
5
+ * can consume. A bare `Time` has no date, so it is anchored to a fixed sentinel
6
+ * day (2020-01-01) — only the time parts are ever read back out.
7
+ *
8
+ * This lives as a standalone leaf (rather than in `field/time-helpers`) so the
9
+ * formatter can depend on it without pulling in the whole date-field surface.
10
+ */
11
+ export declare function convertTimeValueToDateValue(time: TimeValue): CalendarDateTime | ZonedDateTime;
@@ -0,0 +1,76 @@
1
+ import { CalendarDateTime, DateValue, ZonedDateTime } from '@internationalized/date';
2
+ import { DateMatcher, Granularity, TimeGranularity, TimeValue } from '../..shared/date/types.js';
3
+ type GetDefaultDateProps = {
4
+ defaultValue?: DateValue | DateValue[] | undefined;
5
+ minValue?: DateValue;
6
+ maxValue?: DateValue;
7
+ granularity?: Granularity;
8
+ };
9
+ type GetDefaultTimeProps = {
10
+ defaultValue?: TimeValue | undefined;
11
+ granularity?: TimeGranularity;
12
+ };
13
+ /**
14
+ * A helper function used throughout the various date builders
15
+ * to generate a default `DateValue` using the `defaultValue`,
16
+ * `defaultPlaceholder`, `minValue`, `maxValue`, and `granularity` props.
17
+ *
18
+ * It's important to match the `DateValue` type being used
19
+ * elsewhere in the builder, so they behave according to the
20
+ * behavior the user expects based on the props they've provided.
21
+ *
22
+ */
23
+ export declare function getDefaultDate(opts: GetDefaultDateProps): DateValue;
24
+ export declare function getDefaultTime(opts: GetDefaultTimeProps): TimeValue;
25
+ /**
26
+ * Given a date string and a reference `DateValue` object, parse the
27
+ * string to the same type as the reference object.
28
+ *
29
+ * Useful for parsing strings from data attributes, which are always
30
+ * strings, to the same type being used by the date component.
31
+ */
32
+ export declare function parseStringToDateValue(dateStr: string, referenceVal: DateValue): DateValue;
33
+ /**
34
+ * Given a `DateValue` object, convert it to a native `Date` object.
35
+ * If a timezone is provided, the date will be converted to that timezone.
36
+ * If no timezone is provided, the date will be converted to the local timezone.
37
+ */
38
+ export declare function toDate(dateValue: DateValue, tz?: string): Date;
39
+ export declare function getDateValueType(date: DateValue): string;
40
+ export declare function parseAnyDateValue(value: string, type: string): DateValue;
41
+ export declare function isZonedDateTime(dateValue: DateValue | TimeValue): dateValue is ZonedDateTime;
42
+ export declare function hasTime(dateValue: DateValue): dateValue is CalendarDateTime | ZonedDateTime;
43
+ /**
44
+ * Given a date, return the number of days in the month.
45
+ */
46
+ export declare function getDaysInMonth(date: Date | DateValue): number;
47
+ /**
48
+ * Determine if a date is before the reference date.
49
+ * @param dateToCompare - is this date before the `referenceDate`
50
+ * @param referenceDate - is the `dateToCompare` before this date
51
+ *
52
+ * @see {@link isBeforeOrSame} for inclusive
53
+ */
54
+ export declare function isBefore(dateToCompare: DateValue, referenceDate: DateValue): boolean;
55
+ /**
56
+ * Determine if a date is after the reference date.
57
+ * @param dateToCompare - is this date after the `referenceDate`
58
+ * @param referenceDate - is the `dateToCompare` after this date
59
+ *
60
+ * @see {@link isAfterOrSame} for inclusive
61
+ */
62
+ export declare function isAfter(dateToCompare: DateValue, referenceDate: DateValue): boolean;
63
+ /**
64
+ * Determine if a date is inclusively between a start and end reference date.
65
+ *
66
+ * @param date - is this date inclusively between the `start` and `end` dates
67
+ * @param start - the start reference date to make the comparison against
68
+ * @param end - the end reference date to make the comparison against
69
+ *
70
+ * @see {@link isBetween} for non-inclusive
71
+ */
72
+ export declare function isBetweenInclusive(date: DateValue, start: DateValue, end: DateValue): boolean;
73
+ export declare function getLastFirstDayOfWeek<T extends DateValue = DateValue>(date: T, firstDayOfWeek: number, locale: string): T;
74
+ export declare function getNextLastDayOfWeek<T extends DateValue = DateValue>(date: T, firstDayOfWeek: number, locale: string): T;
75
+ export declare function areAllDaysBetweenValid(start: DateValue, end: DateValue, isUnavailable: DateMatcher | undefined, isDisabled: DateMatcher | undefined): boolean;
76
+ export {};
@@ -0,0 +1,4 @@
1
+ export declare function debounce<T extends (...args: any[]) => any>(fn: T, wait?: number): {
2
+ (...args: Parameters<T>): void;
3
+ destroy(): void;
4
+ };
@@ -0,0 +1,7 @@
1
+ export declare function getFirstNonCommentChild(element: HTMLElement | null): ChildNode | null;
2
+ /**
3
+ * Determines if the click event truly occurred outside the content node.
4
+ * This was added to handle password managers and other elements that may be injected
5
+ * into the DOM but visually appear inside the content.
6
+ */
7
+ export declare function isClickTrulyOutside(event: PointerEvent, contentNode: HTMLElement): boolean;
@@ -0,0 +1,2 @@
1
+ export declare function isOrContainsTarget(node: HTMLElement, target: Element): boolean;
2
+ export declare function getOwnerDocument(el: Element | null | undefined): Document;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * A target that can receive DOM focus. Mirrors the elements `HTMLElement.focus`
3
+ * / `SVGElement.focus` accept, used by the focus-management helpers.
4
+ */
5
+ export type FocusableTarget = HTMLElement | SVGElement;
@@ -0,0 +1,21 @@
1
+ import { Direction, Orientation } from '..shared/index.js';
2
+ export declare const FIRST_KEYS: string[];
3
+ export declare const LAST_KEYS: string[];
4
+ export declare const FIRST_LAST_KEYS: string[];
5
+ export declare const SELECTION_KEYS: string[];
6
+ /**
7
+ * A utility function that returns the next key based on the direction and orientation.
8
+ */
9
+ export declare function getNextKey(dir?: Direction, orientation?: Orientation): string;
10
+ /**
11
+ * A utility function that returns the previous key based on the direction and orientation.
12
+ */
13
+ export declare function getPrevKey(dir?: Direction, orientation?: Orientation): string;
14
+ /**
15
+ * A utility function that returns the next and previous keys based on the direction
16
+ * and orientation.
17
+ */
18
+ export declare function getDirectionalKeys(dir?: Direction, orientation?: Orientation): {
19
+ nextKey: string;
20
+ prevKey: string;
21
+ };
@@ -0,0 +1,25 @@
1
+ import { FocusableTarget } from './focus.js';
2
+ export declare const isBrowser: boolean;
3
+ export declare const isIOS: boolean | "";
4
+ export declare function isFunction(value: unknown): value is (...args: unknown[]) => unknown;
5
+ export declare function isHTMLElement(element: unknown): element is HTMLElement;
6
+ export declare function isElement(element: unknown): element is Element;
7
+ export declare function isElementOrSVGElement(element: unknown): element is Element | SVGElement;
8
+ export declare function isNumberString(value: string): boolean;
9
+ export declare function isNull(value: unknown): value is null;
10
+ export declare function isTouch(e: PointerEvent): boolean;
11
+ export declare function isFocusVisible(element: Element): boolean;
12
+ export declare function isNotNull<T>(value: T | null): value is T;
13
+ /**
14
+ * Determines if the provided object is a valid `HTMLInputElement` with
15
+ * a `select` method available.
16
+ */
17
+ export declare function isSelectableInput(element: unknown): element is FocusableTarget & {
18
+ select: () => void;
19
+ };
20
+ /**
21
+ * Given a node, determine if it is hidden by walking up the
22
+ * DOM tree until we hit the `stopAt` node (exclusive), if provided)
23
+ * otherwise we stop at the document root.
24
+ */
25
+ export declare function isElementHidden(node: HTMLElement, stopAt?: HTMLElement): boolean;
@@ -0,0 +1,42 @@
1
+ export declare const ALT = "Alt";
2
+ export declare const ARROW_DOWN = "ArrowDown";
3
+ export declare const ARROW_LEFT = "ArrowLeft";
4
+ export declare const ARROW_RIGHT = "ArrowRight";
5
+ export declare const ARROW_UP = "ArrowUp";
6
+ export declare const BACKSPACE = "Backspace";
7
+ export declare const CAPS_LOCK = "CapsLock";
8
+ export declare const CONTROL = "Control";
9
+ export declare const DELETE = "Delete";
10
+ export declare const END = "End";
11
+ export declare const ENTER = "Enter";
12
+ export declare const ESCAPE = "Escape";
13
+ export declare const F1 = "F1";
14
+ export declare const F10 = "F10";
15
+ export declare const F11 = "F11";
16
+ export declare const F12 = "F12";
17
+ export declare const F2 = "F2";
18
+ export declare const F3 = "F3";
19
+ export declare const F4 = "F4";
20
+ export declare const F5 = "F5";
21
+ export declare const F6 = "F6";
22
+ export declare const F7 = "F7";
23
+ export declare const F8 = "F8";
24
+ export declare const F9 = "F9";
25
+ export declare const HOME = "Home";
26
+ export declare const META = "Meta";
27
+ export declare const PAGE_DOWN = "PageDown";
28
+ export declare const PAGE_UP = "PageUp";
29
+ export declare const SHIFT = "Shift";
30
+ export declare const SPACE = " ";
31
+ export declare const TAB = "Tab";
32
+ export declare const CTRL = "Control";
33
+ export declare const ASTERISK = "*";
34
+ export declare const a = "a";
35
+ export declare const P = "P";
36
+ export declare const A = "A";
37
+ export declare const p = "p";
38
+ export declare const n = "n";
39
+ export declare const j = "j";
40
+ export declare const k = "k";
41
+ export declare const h = "h";
42
+ export declare const l = "l";
@@ -0,0 +1 @@
1
+ export * as kbd from './kbd-constants.js';
@@ -0,0 +1,6 @@
1
+ import { Direction } from '..shared/index.js';
2
+ /**
3
+ * Detects the text direction in the element.
4
+ * @returns {Direction} The text direction ('ltr' for left-to-right or 'rtl' for right-to-left).
5
+ */
6
+ export declare function getElemDirection(elem: HTMLElement): Direction;
@@ -0,0 +1 @@
1
+ export declare function linearScale(domain: [number, number], range: [number, number], clamp?: boolean): (x: number) => number;
@@ -0,0 +1,4 @@
1
+ /**
2
+ * A no operation function (does nothing)
3
+ */
4
+ export declare function noop(): void;
@@ -0,0 +1,4 @@
1
+ export declare function shouldEnableFocusTrap({ forceMount, open, }: {
2
+ forceMount: boolean;
3
+ open: boolean;
4
+ }): boolean;
@@ -0,0 +1,14 @@
1
+ import { ReactNode } from 'react';
2
+ /** Any function — used where the signature is irrelevant. */
3
+ export type { AnyFn, Without } from '..types.js';
4
+ /** A component's props plus the standard React `children`. */
5
+ export type WithChildren<T = Record<never, never>> = T & {
6
+ children?: ReactNode;
7
+ };
8
+ /**
9
+ * A component's props plus an optional `child` render slot — the React analogue
10
+ * of the bits-ui `child` snippet, for headless "render your own element" APIs.
11
+ */
12
+ export type WithChild<T = Record<never, never>> = T & {
13
+ child?: (props: Record<string, unknown>) => ReactNode;
14
+ };
@@ -0,0 +1,45 @@
1
+ import { CSSProperties, RefObject } from 'react';
2
+ /** A side, optionally refined by a cross-axis alignment (`bottom-start` …). */
3
+ export type AnchoredPlacement = "top" | "bottom" | "left" | "right" | "top-start" | "top-end" | "bottom-start" | "bottom-end" | "left-start" | "left-end" | "right-start" | "right-end";
4
+ /** Cross-axis alignment for a bare side (`placement: "bottom"` + `align: "end"`). */
5
+ export type AnchoredAlign = "start" | "center" | "end";
6
+ /** A pointer anchor (e.g. a context menu) — overrides the anchor element's rect. */
7
+ export interface AnchoredPoint {
8
+ x: number;
9
+ y: number;
10
+ }
11
+ /**
12
+ * Options for {@link useAnchoredPosition}.
13
+ */
14
+ export interface UseAnchoredPositionOptions {
15
+ /** The placed side (+ optional compound alignment). Default `"bottom-start"`. */
16
+ placement?: AnchoredPlacement;
17
+ /** Cross-axis alignment when `placement` is a bare side. Default `"center"`. */
18
+ align?: AnchoredAlign;
19
+ /** A fixed float width (px). When set, overrides the measured width. */
20
+ width?: number;
21
+ /** Offset between the anchor and the float (px). Default `8`. */
22
+ gap?: number;
23
+ /** Viewport-edge clamp padding (px). Default `8`. */
24
+ padding?: number;
25
+ /** Recompute while open and track scroll/resize. Default open when omitted. */
26
+ open?: boolean;
27
+ /** Pointer anchor — overrides the anchor rect (context-menu case). */
28
+ point?: AnchoredPoint | null;
29
+ }
30
+ /** The return of {@link useAnchoredPosition}. */
31
+ export interface UseAnchoredPositionReturn {
32
+ /** A `position: fixed` style to spread onto the float element. */
33
+ style: CSSProperties;
34
+ /** Force a recompute (e.g. after the float's content resizes). */
35
+ update: () => void;
36
+ }
37
+ /**
38
+ * Hand-rolled anchored positioning (no positioning dependency — §D). Places
39
+ * `floatRef` relative to `anchorRef` (or a pointer `point`) using `position:
40
+ * fixed` + `getBoundingClientRect`, so it escapes overflow/stacking contexts and
41
+ * pairs with the `<Portal>`. Recomputes on scroll/resize while open and clamps to
42
+ * the viewport. Supports every enum placement + the pointer case the overlay
43
+ * family needs. Guards the React-19 nullable refs.
44
+ */
45
+ export declare function useAnchoredPosition(anchorRef: RefObject<HTMLElement | null>, floatRef: RefObject<HTMLElement | null>, options?: UseAnchoredPositionOptions): UseAnchoredPositionReturn;
@@ -0,0 +1,62 @@
1
+ import { Direction } from '..shared/index.js';
2
+ type ArrowKeyOptions = "horizontal" | "vertical" | "both";
3
+ interface ArrowNavigationOptions {
4
+ /**
5
+ * The arrow key options to allow navigation
6
+ *
7
+ * @defaultValue "both"
8
+ */
9
+ arrowKeyOptions?: ArrowKeyOptions;
10
+ /**
11
+ * The selector to find the collection items in the parent element.
12
+ */
13
+ candidateSelector: string;
14
+ /**
15
+ * The parent element where contains all the collection items, this will collect every item to be used when nav
16
+ * It will be ignored if attributeName is provided
17
+ *
18
+ * @defaultValue []
19
+ */
20
+ itemsArray?: HTMLElement[];
21
+ /**
22
+ * Allow loop navigation. If false, it will stop at the first and last element
23
+ *
24
+ * @defaultValue true
25
+ */
26
+ loop?: boolean;
27
+ /**
28
+ * The orientation of the collection
29
+ *
30
+ * @defaultValue "ltr"
31
+ */
32
+ dir?: Direction;
33
+ /**
34
+ * Prevent the scroll when navigating. This happens when the direction of the
35
+ * key matches the scroll direction of any ancestor scrollable elements.
36
+ *
37
+ * @defaultValue true
38
+ */
39
+ preventScroll?: boolean;
40
+ /**
41
+ * By default all currentElement would trigger navigation. If `true`, currentElement nodeName in the ignore list will return null
42
+ *
43
+ * @defaultValue false
44
+ */
45
+ enableIgnoredElement?: boolean;
46
+ /**
47
+ * Focus the element after navigation
48
+ *
49
+ * @defaultValue false
50
+ */
51
+ focus?: boolean;
52
+ }
53
+ /**
54
+ *
55
+ * @param e Keyboard event
56
+ * @param currentElement Event initiator element or any element that wants to handle the navigation
57
+ * @param parentElement Parent element where contains all the collection items, this will collect every item to be used when nav
58
+ * @param options further options
59
+ * @returns the navigated html element or null if none
60
+ */
61
+ export declare function useArrowNavigation(e: KeyboardEvent, currentElement: HTMLElement, parentElement: HTMLElement | undefined, options: ArrowNavigationOptions): HTMLElement | null;
62
+ export {};
@@ -0,0 +1,31 @@
1
+ import { RefObject } from 'react';
2
+ /**
3
+ * Options for {@link useDismiss}.
4
+ */
5
+ export interface UseDismissOptions {
6
+ /** Called when an outside press or `Escape` requests dismissal. */
7
+ onDismiss: () => void;
8
+ /** Dismiss on a press outside `ref`. Default `true`. `AlertDialog` opts out. */
9
+ outsideClick?: boolean;
10
+ /** Dismiss on `Escape`. Default `true`. */
11
+ escapeKey?: boolean;
12
+ /**
13
+ * Elements whose presses do NOT count as outside — typically the trigger /
14
+ * anchor, so re-pressing it toggles rather than double-firing dismiss + open.
15
+ */
16
+ ignore?: ReadonlyArray<RefObject<HTMLElement | null> | null>;
17
+ /** Gate the whole hook — a closed overlay ignores `Escape`/outside. Default `true`. */
18
+ enabled?: boolean;
19
+ }
20
+ /**
21
+ * The one true outside-press + `Escape` dismiss effect, replacing the overlays'
22
+ * inline copies. Subscribes once while `enabled` and reads the latest options at
23
+ * event time, so `outsideClick`/`escapeKey`/`onDismiss` may change without churn.
24
+ *
25
+ * Uses `pointerdown` (mouse + touch + pen, before `click`) and composes
26
+ * `dom.isClickTrulyOutside`: a press dismisses only when it lands outside the
27
+ * DOM subtree AND outside the content's box (the latter guards password-manager
28
+ * overlays injected outside the tree but visually within). Guards the React-19
29
+ * nullable `ref.current`.
30
+ */
31
+ export declare function useDismiss(ref: RefObject<HTMLElement | null>, options: UseDismissOptions): void;
@@ -0,0 +1,31 @@
1
+ import { RefObject } from 'react';
2
+ import { FocusableTarget } from './focus.js';
3
+ /**
4
+ * Options for {@link useFocusTrap}.
5
+ */
6
+ export interface UseFocusTrapOptions {
7
+ /** While `true`, `Tab`/`Shift+Tab` cycle within `ref`'s focusable descendants. */
8
+ active: boolean;
9
+ /**
10
+ * Where focus returns on deactivate — the trigger. Accepts a ref or a direct
11
+ * element. When omitted, focus returns to whatever held it when the trap engaged.
12
+ */
13
+ returnFocusTo?: RefObject<FocusableTarget | null> | FocusableTarget | null;
14
+ /**
15
+ * The element to focus first on engage (e.g. an alert dialog's confirm action).
16
+ * When omitted, focus moves to the first focusable descendant, else the container.
17
+ */
18
+ initialFocus?: RefObject<FocusableTarget | null> | null;
19
+ /** Composes `shouldEnableFocusTrap` — a portal that stays mounted while closed. */
20
+ forceMount?: boolean;
21
+ }
22
+ /**
23
+ * Headless focus trap + focus return. While `active`, keyboard focus is confined
24
+ * to `ref`'s focusable descendants (Tab wraps last→first, Shift+Tab first→last,
25
+ * and focus that escapes is pulled back); on deactivate, focus returns to
26
+ * `returnFocusTo` (or the element that held focus when the trap engaged).
27
+ *
28
+ * JSX/portal-free — the `<Portal>` wrapper lives in `@mercury-fx/ui`. Guards the
29
+ * React-19 nullable `ref.current`.
30
+ */
31
+ export declare function useFocusTrap(ref: RefObject<HTMLElement | null>, { active, returnFocusTo, initialFocus, forceMount }: UseFocusTrapOptions): void;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Generates a process-unique id with the given prefix. Despite the name this is
3
+ * NOT a React hook — it's a plain monotonic counter (base36), safe to call from
4
+ * anywhere a stable, collision-free id is needed.
5
+ */
6
+ export declare function useId(prefix?: string): string;
@@ -0,0 +1 @@
1
+ export declare function warn(...messages: string[]): void;