@elvora/core 1.0.0-rc.1

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.
@@ -0,0 +1,346 @@
1
+ export { F as FocusTrap, a as FocusTrapOptions, c as createFocusTrap } from './focusTrap-Bko1L5FG.js';
2
+ import { Tokens } from '@elvora/tokens';
3
+
4
+ /**
5
+ * Shared semantic types used across every Elvora component on every framework.
6
+ * Keeping these in core means every adapter (React, RN, Angular, Vue) speaks
7
+ * the same vocabulary for sizes, variants, and statuses.
8
+ */
9
+ type ElvoraSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
10
+ type ElvoraVariant = 'primary' | 'secondary' | 'tertiary' | 'ghost' | 'outline' | 'destructive' | 'link';
11
+ type ElvoraStatus = 'info' | 'success' | 'warning' | 'error' | 'neutral';
12
+ type ElvoraRadius = 'none' | 'sm' | 'md' | 'lg' | 'full';
13
+ type ElvoraTone = 'solid' | 'subtle' | 'outline';
14
+ type Orientation = 'horizontal' | 'vertical';
15
+ type Placement = 'top' | 'top-start' | 'top-end' | 'right' | 'right-start' | 'right-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'left' | 'left-start' | 'left-end';
16
+ type Direction = 'ltr' | 'rtl';
17
+ type Booleanish = boolean | 'true' | 'false';
18
+ /** Helper to type a generic event handler that may be controlled or uncontrolled. */
19
+ type ChangeHandler<T> = (value: T) => void;
20
+ /** Helper for components that accept either a value or a callback to derive it. */
21
+ type ValueOrCallback<T, Args extends unknown[] = []> = T | ((...args: Args) => T);
22
+
23
+ /**
24
+ * Compose multiple refs into a single ref callback. Useful when a component
25
+ * needs both an internal ref (e.g. for focus management) and a forwarded ref
26
+ * from the caller.
27
+ *
28
+ * Framework-agnostic: works with any ref shape (callback or object with `.current`).
29
+ */
30
+ type PossibleRef<T> = ((instance: T | null) => void) | {
31
+ current: T | null;
32
+ } | null | undefined;
33
+ declare function setRef<T>(ref: PossibleRef<T>, value: T | null): void;
34
+ declare function composeRefs<T>(...refs: PossibleRef<T>[]): (node: T | null) => void;
35
+
36
+ /**
37
+ * Compose two event handlers so the consumer's handler runs first; if it
38
+ * calls `event.preventDefault()` (or passes `checkForDefaultPrevented` and the
39
+ * synthetic event reports `defaultPrevented`), the internal handler is skipped.
40
+ *
41
+ * This pattern lets internal handlers do "after" work (e.g. close a popover)
42
+ * while still letting the consumer opt out.
43
+ */
44
+ type AnyEvent = {
45
+ defaultPrevented?: boolean;
46
+ };
47
+ declare function composeEventHandlers<E extends AnyEvent>(originalEventHandler: ((event: E) => void) | undefined, ourEventHandler: ((event: E) => void) | undefined, { checkForDefaultPrevented }?: {
48
+ checkForDefaultPrevented?: boolean;
49
+ }): (event: E) => void;
50
+
51
+ type AnyProps = Record<string, unknown>;
52
+ declare function mergeProps<A extends AnyProps, B extends AnyProps>(a: A, b: B): A & B;
53
+
54
+ /**
55
+ * Helpers for conditionally emitting ARIA + data attributes. Returning
56
+ * `undefined` (instead of `false`) keeps DOM clean: the attribute is omitted
57
+ * entirely when the state isn't active.
58
+ */
59
+ declare function dataAttr(condition: boolean | undefined): '' | undefined;
60
+ declare function ariaAttr(condition: boolean | undefined): boolean | undefined;
61
+
62
+ /**
63
+ * Minimal QR Code generator (byte mode only, error-correction levels L/M/Q/H,
64
+ * versions 1–10). Adapted from Nayuki's QR Code generator algorithm; this is a
65
+ * lean self-contained TypeScript port small enough to ship in a UI library
66
+ * without pulling in an external dependency.
67
+ *
68
+ * Returns a square boolean matrix (true = dark module, false = light) plus the
69
+ * chosen version. The caller is responsible for rendering it (SVG, canvas,
70
+ * native paths, …).
71
+ */
72
+ type ErrorCorrection = 'L' | 'M' | 'Q' | 'H';
73
+ interface QRMatrix {
74
+ size: number;
75
+ modules: boolean[][];
76
+ version: number;
77
+ }
78
+ /** Generate a QR matrix for the given text. */
79
+ declare function generateQrMatrix(text: string, ecl?: ErrorCorrection): QRMatrix;
80
+
81
+ /**
82
+ * Discover and walk focusable elements within a container. Used by focus traps,
83
+ * roving-tabindex managers, and keyboard-navigable lists/menus.
84
+ *
85
+ * Selectors are based on the WAI-ARIA Authoring Practices and the live
86
+ * `tabindex`/`disabled`/`inert` semantics of HTML.
87
+ */
88
+ declare const FOCUSABLE_SELECTOR: string;
89
+ declare function isElementVisible(el: HTMLElement): boolean;
90
+ declare function isFocusable(el: HTMLElement): boolean;
91
+ declare function getFocusableElements(container: HTMLElement): HTMLElement[];
92
+ declare function getFirstFocusable(container: HTMLElement): HTMLElement | null;
93
+ declare function getLastFocusable(container: HTMLElement): HTMLElement | null;
94
+
95
+ /**
96
+ * Named keyboard constants. Adapters use these instead of magic strings so
97
+ * keyboard logic is consistent across frameworks.
98
+ */
99
+ declare const Keys: {
100
+ readonly Enter: "Enter";
101
+ readonly Space: " ";
102
+ readonly Escape: "Escape";
103
+ readonly Tab: "Tab";
104
+ readonly ArrowUp: "ArrowUp";
105
+ readonly ArrowDown: "ArrowDown";
106
+ readonly ArrowLeft: "ArrowLeft";
107
+ readonly ArrowRight: "ArrowRight";
108
+ readonly Home: "Home";
109
+ readonly End: "End";
110
+ readonly PageUp: "PageUp";
111
+ readonly PageDown: "PageDown";
112
+ readonly Backspace: "Backspace";
113
+ readonly Delete: "Delete";
114
+ };
115
+ type KeyName = (typeof Keys)[keyof typeof Keys];
116
+ /** True when the event represents an activation (Enter or Space). */
117
+ declare function isActivationKey(key: string): boolean;
118
+
119
+ /**
120
+ * Tiny, SSR-safe id generator. Prefer crypto.randomUUID when available, fall
121
+ * back to a monotonic counter otherwise so generated ids are stable across
122
+ * server/client when adapters seed them once.
123
+ */
124
+ declare function generateId(prefix?: string): string;
125
+
126
+ /**
127
+ * The shape of a Elvora theme. This is the contract every adapter depends on.
128
+ * The concrete `defaultTheme` / `darkTheme` values live in `@elvora/themes`,
129
+ * but the shape lives here so headless style descriptors don't need to import
130
+ * theme values — only the type.
131
+ */
132
+
133
+ interface ElvoraTheme {
134
+ name: string;
135
+ mode: 'light' | 'dark';
136
+ tokens: Tokens;
137
+ colors: ThemeColors;
138
+ radii: {
139
+ sm: string;
140
+ md: string;
141
+ lg: string;
142
+ full: string;
143
+ };
144
+ shadows: {
145
+ sm: string;
146
+ md: string;
147
+ lg: string;
148
+ focus: string;
149
+ };
150
+ durations: {
151
+ fast: string;
152
+ normal: string;
153
+ slow: string;
154
+ };
155
+ easings: {
156
+ standard: string;
157
+ emphasized: string;
158
+ };
159
+ }
160
+ interface ThemeColors {
161
+ background: string;
162
+ surface: string;
163
+ surfaceElevated: string;
164
+ fg: string;
165
+ fgMuted: string;
166
+ fgSubtle: string;
167
+ border: string;
168
+ borderStrong: string;
169
+ intent: {
170
+ primary: IntentScale;
171
+ neutral: IntentScale;
172
+ success: IntentScale;
173
+ warning: IntentScale;
174
+ danger: IntentScale;
175
+ info: IntentScale;
176
+ };
177
+ }
178
+ interface IntentScale {
179
+ solid: string;
180
+ solidHover: string;
181
+ solidActive: string;
182
+ solidFg: string;
183
+ subtle: string;
184
+ subtleHover: string;
185
+ fg: string;
186
+ border: string;
187
+ ring: string;
188
+ }
189
+
190
+ /**
191
+ * Headless style descriptor for the Button component. Given a theme and the
192
+ * Button's variant/size/state, returns a flat style object usable by both web
193
+ * adapters (inline styles or vanilla-extract recipes) and React Native.
194
+ *
195
+ * Keeping this here means every framework adapter looks identical visually
196
+ * without re-implementing variant logic per framework.
197
+ */
198
+
199
+ interface ButtonStyleInputs {
200
+ theme: ElvoraTheme;
201
+ variant: ElvoraVariant;
202
+ size: ElvoraSize;
203
+ fullWidth: boolean;
204
+ isLoading: boolean;
205
+ isDisabled: boolean;
206
+ isPressed: boolean;
207
+ isHovered: boolean;
208
+ isFocusVisible: boolean;
209
+ /** Intent overrides the variant's default color scheme (defaults to primary). */
210
+ intent?: keyof ElvoraTheme['colors']['intent'];
211
+ }
212
+ interface ButtonStyle {
213
+ /** Root style object — keys are camelCase so the same shape works in RN + web. */
214
+ root: Record<string, string | number | undefined>;
215
+ /** Label/text style. */
216
+ label: Record<string, string | number | undefined>;
217
+ /** Loading spinner color. */
218
+ spinnerColor: string;
219
+ }
220
+ declare function getButtonStyle(input: ButtonStyleInputs): ButtonStyle;
221
+
222
+ interface InputStyleInputs {
223
+ theme: ElvoraTheme;
224
+ size: ElvoraSize;
225
+ status: ElvoraStatus;
226
+ isDisabled: boolean;
227
+ isReadOnly: boolean;
228
+ isInvalid: boolean;
229
+ isFocused: boolean;
230
+ isHovered: boolean;
231
+ }
232
+ declare function getInputStyle(input: InputStyleInputs): Record<string, string | number | undefined>;
233
+
234
+ type FloatingLabelVariant = 'outlined' | 'filled';
235
+ interface FloatingLabelStyleInputs {
236
+ theme: ElvoraTheme;
237
+ size: ElvoraSize;
238
+ variant: FloatingLabelVariant;
239
+ floated: boolean;
240
+ focused: boolean;
241
+ invalid: boolean;
242
+ /**
243
+ * Vertical resting position of the label when the field is empty. `center`
244
+ * suits single-line controls; `top` suits multi-line controls (textarea)
245
+ * where the text starts at the top.
246
+ */
247
+ restAlign?: 'center' | 'top';
248
+ }
249
+ interface FloatingLabelStyle {
250
+ wrapper: Record<string, string | number | undefined>;
251
+ label: Record<string, string | number | undefined>;
252
+ }
253
+ /**
254
+ * Headless style descriptor for a floating label. Drives the `outlined`
255
+ * (label notches the top border) and `filled` (label floats inside the field)
256
+ * variants. The float is React-state driven via `floated` because the library
257
+ * styles with inline CSS and cannot rely on `:focus`/`:placeholder-shown`.
258
+ */
259
+ declare function getFloatingLabelStyle(input: FloatingLabelStyleInputs): FloatingLabelStyle;
260
+
261
+ /**
262
+ * Framework-agnostic Button contract. Each adapter extends/maps this to its
263
+ * framework-idiomatic event names (onPress vs press vs @press) but the
264
+ * semantics are identical: same variants, same sizes, same states.
265
+ */
266
+
267
+ interface ButtonOwnProps {
268
+ /** Visual variant. Defaults to `'primary'`. */
269
+ variant?: ElvoraVariant;
270
+ /** Size. Defaults to `'md'`. */
271
+ size?: ElvoraSize;
272
+ /** Override the intent (color scheme) for this button. */
273
+ intent?: keyof ElvoraTheme['colors']['intent'];
274
+ /** When true, stretches the button to fill its container. */
275
+ fullWidth?: boolean;
276
+ /** When true, shows a spinner and prevents activation. */
277
+ isLoading?: boolean;
278
+ /** Disabled state. */
279
+ isDisabled?: boolean;
280
+ /** Loading-state announcement for assistive tech. Defaults to "Loading". */
281
+ loadingText?: string;
282
+ /** Type attribute for HTML buttons. Defaults to `'button'`. */
283
+ type?: 'button' | 'submit' | 'reset';
284
+ }
285
+ declare const defaultButtonProps: {
286
+ variant: ElvoraVariant;
287
+ size: ElvoraSize;
288
+ type: "button";
289
+ fullWidth: boolean;
290
+ isLoading: boolean;
291
+ isDisabled: boolean;
292
+ loadingText: string;
293
+ };
294
+
295
+ interface InputOwnProps {
296
+ size?: ElvoraSize;
297
+ /** Validation status (changes border color and icon). */
298
+ status?: ElvoraStatus;
299
+ /** When true, renders a read-only input. */
300
+ isReadOnly?: boolean;
301
+ /** When true, disables the input. */
302
+ isDisabled?: boolean;
303
+ /** When true, the field is required for form submission. */
304
+ isRequired?: boolean;
305
+ /** When true, marks the input as invalid (`aria-invalid`). */
306
+ isInvalid?: boolean;
307
+ }
308
+ declare const defaultInputProps: {
309
+ size: ElvoraSize;
310
+ status: ElvoraStatus;
311
+ isReadOnly: boolean;
312
+ isDisabled: boolean;
313
+ isRequired: boolean;
314
+ isInvalid: boolean;
315
+ };
316
+
317
+ /**
318
+ * Headless Tabs contract. Each adapter renders tab buttons + panels and wires
319
+ * keyboard navigation per WAI-ARIA Tabs pattern.
320
+ */
321
+
322
+ interface TabDescriptor<V extends string = string> {
323
+ /** Stable identifier for this tab; becomes the selected value. */
324
+ value: V;
325
+ /** Visible label. */
326
+ label: string;
327
+ /** Disable this tab. */
328
+ isDisabled?: boolean;
329
+ }
330
+ type TabsActivation = 'automatic' | 'manual';
331
+ interface TabsKeyboardOptions {
332
+ orientation?: Orientation;
333
+ /** When `automatic` (default) arrow keys also select; `manual` only moves focus. */
334
+ activation?: TabsActivation;
335
+ }
336
+ /**
337
+ * Compute the next focusable tab index for a keyboard event. Returns the
338
+ * current index if the key shouldn't move focus.
339
+ */
340
+ declare function getNextTabIndex(event: {
341
+ key: string;
342
+ }, currentIndex: number, tabs: ReadonlyArray<{
343
+ isDisabled?: boolean;
344
+ }>, options?: TabsKeyboardOptions): number;
345
+
346
+ export { type Booleanish, type ButtonOwnProps, type ButtonStyle, type ButtonStyleInputs, type ChangeHandler, type Direction, type ElvoraRadius, type ElvoraSize, type ElvoraStatus, type ElvoraTheme, type ElvoraTone, type ElvoraVariant, type ErrorCorrection, FOCUSABLE_SELECTOR, type FloatingLabelStyle, type FloatingLabelStyleInputs, type FloatingLabelVariant, type InputOwnProps, type InputStyleInputs, type IntentScale, type KeyName, Keys, type Orientation, type Placement, type PossibleRef, type QRMatrix, type TabDescriptor, type TabsActivation, type TabsKeyboardOptions, type ThemeColors, type ValueOrCallback, ariaAttr, composeEventHandlers, composeRefs, dataAttr, defaultButtonProps, defaultInputProps, generateId, generateQrMatrix, getButtonStyle, getFirstFocusable, getFloatingLabelStyle, getFocusableElements, getInputStyle, getLastFocusable, getNextTabIndex, isActivationKey, isElementVisible, isFocusable, mergeProps, setRef };