@enigmax/primitives 0.17.0 → 0.18.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 (89) hide show
  1. package/dist/button-CaXaqG_K.d.ts +63 -0
  2. package/dist/chunk-2QFTRNAZ.js +88 -0
  3. package/dist/chunk-6BGBYUSZ.js +114 -0
  4. package/dist/chunk-AU3H5WIY.js +107 -0
  5. package/dist/chunk-F25CGNQC.js +19 -0
  6. package/dist/chunk-HC2ME5PU.js +168 -0
  7. package/dist/chunk-HS3X3XCW.js +43 -0
  8. package/dist/chunk-IIT6U7LM.js +249 -0
  9. package/dist/chunk-IXVMRVD4.js +96 -0
  10. package/dist/chunk-KJINGUQN.js +188 -0
  11. package/dist/chunk-LKA2UG4P.js +542 -0
  12. package/dist/chunk-MMQPZGSU.js +161 -0
  13. package/dist/chunk-OCMI7R6H.js +79 -0
  14. package/dist/chunk-QYMUIW5I.js +28 -0
  15. package/dist/chunk-S653GLSF.js +17 -0
  16. package/dist/chunk-SNYUBXWQ.js +149 -0
  17. package/dist/chunk-U3V4EHOB.js +41 -0
  18. package/dist/chunk-UOSSNUSC.js +309 -0
  19. package/dist/chunk-WSB655JB.js +47 -0
  20. package/dist/chunk-XNNQRA35.js +31 -0
  21. package/dist/chunk-XQHCZAPJ.js +102 -0
  22. package/dist/chunk-ZCUFYBPB.js +154 -0
  23. package/dist/chunk-ZWR2EXHQ.js +55 -0
  24. package/dist/flags-BBJc9unY.d.ts +133 -0
  25. package/dist/index-D-ARvWpQ.d.ts +306 -0
  26. package/dist/index-DNXPtY9X.d.ts +144 -0
  27. package/dist/index.d.ts +16 -602
  28. package/dist/index.js +9 -1
  29. package/dist/input-BwXjFenq.d.ts +77 -0
  30. package/dist/marquee-CJ3Uwy3E.d.ts +81 -0
  31. package/dist/network-D2LsBG_k.d.ts +39 -0
  32. package/dist/next/index.d.ts +20 -3
  33. package/dist/next/index.js +23 -3
  34. package/dist/notifications-BpVV6sel.d.ts +70 -0
  35. package/dist/password-3DRQYAYQ.js +2 -0
  36. package/dist/password-C8lG4Zm9.d.ts +71 -0
  37. package/dist/password-FB2CUEKJ.js +1 -0
  38. package/dist/react/button.d.ts +75 -0
  39. package/dist/react/button.js +4 -0
  40. package/dist/react/flag.d.ts +37 -0
  41. package/dist/react/flag.js +3 -0
  42. package/dist/react/index.d.ts +28 -312
  43. package/dist/react/index.js +22 -2
  44. package/dist/react/input.d.ts +4 -0
  45. package/dist/react/input.js +3 -0
  46. package/dist/react/marquee.d.ts +44 -0
  47. package/dist/react/marquee.js +3 -0
  48. package/dist/react/network.d.ts +20 -0
  49. package/dist/react/network.js +3 -0
  50. package/dist/react/notifications.d.ts +17 -0
  51. package/dist/react/notifications.js +3 -0
  52. package/dist/react/palette.d.ts +3 -0
  53. package/dist/react/palette.js +4 -0
  54. package/dist/react/relative-time.d.ts +21 -0
  55. package/dist/react/relative-time.js +3 -0
  56. package/dist/react/search.d.ts +30 -0
  57. package/dist/react/search.js +3 -0
  58. package/dist/react/slot.d.ts +47 -0
  59. package/dist/react/slot.js +2 -0
  60. package/dist/react/toast.d.ts +40 -0
  61. package/dist/react/toast.js +4 -0
  62. package/dist/react-router/index.d.ts +20 -3
  63. package/dist/react-router/index.js +23 -3
  64. package/dist/relative-time-YpRTG7YH.d.ts +106 -0
  65. package/dist/search-P4OHCRXD.js +50 -0
  66. package/package.json +52 -2
  67. package/registry.json +175 -18
  68. package/src/core/flags.ts +88 -42
  69. package/src/core/input-icons.ts +34 -0
  70. package/src/core/input.ts +5 -21
  71. package/src/core/palette.ts +0 -0
  72. package/src/index.ts +2 -2
  73. package/src/react/button.tsx +70 -4
  74. package/src/react/flag.tsx +18 -6
  75. package/src/react/index.ts +40 -5
  76. package/src/react/input/icon.tsx +17 -0
  77. package/src/react/input/index.tsx +307 -0
  78. package/src/react/input/password.tsx +174 -0
  79. package/src/react/input/search.tsx +82 -0
  80. package/src/react/input/types.ts +146 -0
  81. package/src/react/input/write-value.ts +18 -0
  82. package/src/react/palette/context.ts +60 -0
  83. package/src/react/palette/index.tsx +66 -0
  84. package/src/react/palette/root.tsx +621 -0
  85. package/src/react/slot.tsx +91 -0
  86. package/src/react/use-button.ts +3 -1
  87. package/dist/chunk-4GLYRF4B.js +0 -1259
  88. package/dist/chunk-JFNND6P4.js +0 -749
  89. package/src/react/input.tsx +0 -429
@@ -0,0 +1,306 @@
1
+ import { ComponentPropsWithoutRef, ReactNode } from 'react';
2
+ import { b as SearchMatch, c as SearchOptions } from './search-CsO3L1Lw.js';
3
+
4
+ /**
5
+ * The parts of a command palette that are not rendering: what was searched before, how a
6
+ * flat list becomes groups, and where the highlight goes when a key is pressed.
7
+ *
8
+ * Pure functions and one storage wrapper, so all three are testable without a browser and
9
+ * reusable by a renderer that is not React. The palette's React parts are a thin layer over
10
+ * this file.
11
+ */
12
+ interface RecentEntry {
13
+ /** What was typed. The palette puts it back in the field when the row is chosen. */
14
+ term: string;
15
+ /** A result that was opened, rather than a query that was run. */
16
+ label?: string;
17
+ /** Where that result was. */
18
+ href?: string;
19
+ /** Which scope it was searched in, when the palette has scopes. */
20
+ scope?: string | null;
21
+ /** Epoch ms. Used only for ordering. */
22
+ at: number;
23
+ }
24
+ interface RecentStoreOptions {
25
+ /** Storage key. One per palette, so two palettes on a site do not share a history. */
26
+ key?: string;
27
+ /** How many entries to keep. */
28
+ limit?: number;
29
+ /** `local` outlives the tab, `session` does not. Default local. */
30
+ storage?: "local" | "session";
31
+ }
32
+ interface RecentStore {
33
+ list(): RecentEntry[];
34
+ remember(entry: Omit<RecentEntry, "at"> & {
35
+ at?: number;
36
+ }): RecentEntry[];
37
+ forget(entry: RecentEntry): RecentEntry[];
38
+ clear(): void;
39
+ }
40
+ /** Two entries are the same memory when they point at the same thing in the same scope. */
41
+ declare function recentKey(entry: Pick<RecentEntry, "term" | "href" | "scope">): string;
42
+ /**
43
+ * What was searched before, in this browser.
44
+ *
45
+ * Every read and write is guarded: storage throws in a private window, when the quota is
46
+ * full, and whenever a page is opened from a file URL - and a palette that cannot remember
47
+ * is still a working palette, so none of that is allowed to reach the renderer. Reads also
48
+ * survive a corrupted value, because the key is shared with whatever else the site stores.
49
+ */
50
+ declare function createRecentStore(options?: RecentStoreOptions): RecentStore;
51
+ /** A row after grouping: its own index in the FLAT list is what the keyboard moves through. */
52
+ interface PositionedRow<Row> {
53
+ row: Row;
54
+ position: number;
55
+ }
56
+ interface RowGroup<Row> {
57
+ label: string;
58
+ rows: PositionedRow<Row>[];
59
+ }
60
+ /**
61
+ * Group a flat list while keeping every row's flat position.
62
+ *
63
+ * The flat position is the whole point: the highlight moves through ONE sequence, so a
64
+ * group boundary is invisible to the arrow keys - and a renderer that grouped rows into
65
+ * separate arrays would have to reconstruct that sequence, which is where an off-by-one
66
+ * makes Enter open the row above the highlighted one. Groups keep first-seen order.
67
+ */
68
+ declare function groupRows<Row>(rows: Row[], labelOf: (row: Row) => string): RowGroup<Row>[];
69
+ /** Keys the list responds to. Anything else belongs to the field. */
70
+ type PaletteKey = "ArrowDown" | "ArrowUp" | "Home" | "End" | "PageDown" | "PageUp";
71
+ /**
72
+ * Where the highlight lands.
73
+ *
74
+ * It WRAPS, because a palette is a short list and the row after the last one is the first:
75
+ * clamping instead leaves the arrow key doing nothing at the end, which reads as the panel
76
+ * having frozen. An empty list stays at 0 rather than going negative.
77
+ */
78
+ declare function moveActive(current: number, length: number, key: PaletteKey, page?: number): number;
79
+ /**
80
+ * The shortcut label for this platform: `Cmd K` on a Mac, `Ctrl K` everywhere else.
81
+ *
82
+ * Read from the platform rather than hardcoded, because the wrong modifier in the trigger
83
+ * is a hint that actively misleads - and it is the first thing anyone tries.
84
+ */
85
+ declare function shortcutLabel(key?: string): string;
86
+ /** Whether an event is the palette's open shortcut. Meta on a Mac, Control elsewhere. */
87
+ declare function isPaletteShortcut(event: KeyboardEvent, key?: string): boolean;
88
+
89
+ /** One line in the palette, whatever it came from. */
90
+ interface PaletteRow<Item> {
91
+ /** Stable within a render. Used for React keys and for `aria-activedescendant`. */
92
+ id: string;
93
+ /** Which group it appears under. */
94
+ group: string;
95
+ /** `item` for a result, `recent` for a memory, `action` for a row the app declared. */
96
+ kind: "item" | "recent" | "action";
97
+ item?: Item;
98
+ recent?: RecentEntry;
99
+ /** Set for a result that came from the engine, so a renderer can show the score. */
100
+ match?: SearchMatch<Item>;
101
+ /** What running this row does. The palette closes afterwards unless this returns false. */
102
+ onSelect?: () => void | boolean;
103
+ label: string;
104
+ description?: string;
105
+ }
106
+ interface PaletteContextValue<Item = unknown> {
107
+ open: boolean;
108
+ setOpen: (open: boolean) => void;
109
+ query: string;
110
+ setQuery: (query: string) => void;
111
+ rows: PaletteRow<Item>[];
112
+ active: number;
113
+ setActive: (index: number) => void;
114
+ /** Run a row: its own action, or the palette's `onSelect`, then remember it. */
115
+ select: (row: PaletteRow<Item> | undefined) => void;
116
+ /** Wipe the remembered searches. */
117
+ clearRecents: () => void;
118
+ forgetRecent: (entry: RecentEntry) => void;
119
+ /** True while the engine is loading or an async source is in flight. */
120
+ busy: boolean;
121
+ /** ids the parts need to point at each other. */
122
+ ids: {
123
+ field: string;
124
+ list: string;
125
+ title: string;
126
+ };
127
+ /** `Ctrl K` or `⌘ K`, whichever this platform uses. */
128
+ shortcutLabel: string;
129
+ triggerRef: {
130
+ current: HTMLElement | null;
131
+ };
132
+ fieldRef: {
133
+ current: HTMLInputElement | null;
134
+ };
135
+ rowId: (row: PaletteRow<Item>) => string;
136
+ }
137
+ declare function usePaletteContext<Item = unknown>(part: string): PaletteContextValue<Item>;
138
+
139
+ /**
140
+ * The command palette: the panel that opens on Ctrl/Cmd+K, searches as you type, remembers
141
+ * what was searched before, and is driven entirely from the keyboard.
142
+ *
143
+ * It is a DIALOG, which is why it is its own component rather than a prop on `<Input>`: a
144
+ * palette is a trigger, an overlay, a focus trap, a listbox and a footer, and the thing that
145
+ * makes those usable together is composition. Radix draws the line in the same place, and
146
+ * for the same reason - one `<input>` is a component, a widget made of parts is an anatomy:
147
+ *
148
+ * ```tsx
149
+ * <SearchPalette.Root items={docs} keys={["title"]} onSelect={open}>
150
+ * <SearchPalette.Trigger />
151
+ * <SearchPalette.Content>
152
+ * <SearchPalette.Field placeholder="Search the docs" />
153
+ * <SearchPalette.List />
154
+ * <SearchPalette.Footer />
155
+ * </SearchPalette.Content>
156
+ * </SearchPalette.Root>
157
+ * ```
158
+ *
159
+ * `<SearchPalette>` on its own renders exactly that, for the case that needs no arguing
160
+ * with. Every part takes `asChild`, so any of them can be your own element instead.
161
+ *
162
+ * The keyboard sequence is ONE flat list across every group - a group boundary is invisible
163
+ * to the arrow keys - and the highlight wraps, because in a short list the row after the
164
+ * last one is the first, and a key that does nothing at the end reads as a frozen panel.
165
+ */
166
+ interface PaletteSection<Item> {
167
+ label: string;
168
+ items: Item[];
169
+ /** Shown whatever the query, e.g. a list of commands. Off by default. */
170
+ always?: boolean;
171
+ }
172
+ interface PaletteRootProps<Item> {
173
+ /** What to search. */
174
+ items?: Item[];
175
+ /** Fields to read. Dotted paths work. */
176
+ keys?: SearchOptions<Item>["keys"];
177
+ /** Fuse.js's constructor, for fuzzy matching. Without it, a substring matcher runs. */
178
+ fuse?: SearchOptions<Item>["fuse"];
179
+ fuseOptions?: SearchOptions<Item>["fuseOptions"];
180
+ /** Replaces the engine outright. */
181
+ matcher?: SearchOptions<Item>["matcher"];
182
+ /** ms after the last keystroke. Default 120: a palette should feel immediate. */
183
+ delay?: number;
184
+ limit?: number;
185
+ /** Which group a result belongs under. One group when this is left out. */
186
+ groupBy?: (item: Item) => string;
187
+ /** The row's text. Falls back to the first string field. */
188
+ labelOf?: (item: Item) => string;
189
+ descriptionOf?: (item: Item) => string | undefined;
190
+ /** Rows the app always offers - commands, shortcuts, "create new". */
191
+ sections?: PaletteSection<Item>[];
192
+ /** What running a row does. Closing afterwards is the default; return false to stay. */
193
+ onSelect?: (item: Item) => void | boolean;
194
+ /** Remember what was searched, in this browser. On by default. */
195
+ recents?: boolean;
196
+ recentsKey?: string;
197
+ recentsLimit?: number;
198
+ /** The key that opens it, with Ctrl or Cmd. `null` binds nothing. Default "k". */
199
+ shortcut?: string | null;
200
+ /** Controlled open state. Leave both out for an uncontrolled palette. */
201
+ open?: boolean;
202
+ onOpenChange?: (open: boolean) => void;
203
+ defaultOpen?: boolean;
204
+ /** Wording for the empty group heading of ungrouped results. Default "Results". */
205
+ resultsLabel?: string;
206
+ recentsLabel?: string;
207
+ children?: ReactNode;
208
+ }
209
+ declare function PaletteRoot<Item>({ items, keys, fuse, fuseOptions, matcher, delay, limit, groupBy, labelOf, descriptionOf, sections, onSelect, recents, recentsKey, recentsLimit, shortcut, open: openProp, onOpenChange, defaultOpen, resultsLabel, recentsLabel, children }: PaletteRootProps<Item>): ReactNode;
210
+ interface PaletteTriggerProps extends ComponentPropsWithoutRef<"button"> {
211
+ asChild?: boolean;
212
+ }
213
+ /** Opens the palette. Carries the shortcut in `aria-keyshortcuts`, so it is announced. */
214
+ declare function PaletteTrigger({ asChild, children, onClick, ...props }: PaletteTriggerProps): ReactNode;
215
+ interface PaletteContentProps extends ComponentPropsWithoutRef<"div"> {
216
+ /** Accessible name for the dialog. Rendered for screen readers only. */
217
+ title?: string;
218
+ /** Render into `document.body`. On by default: a palette inside a clipped or
219
+ * transformed ancestor is a panel nobody can see. */
220
+ portal?: boolean;
221
+ /** Rendered behind the panel. Pass null for no overlay of ours. */
222
+ overlayProps?: ComponentPropsWithoutRef<"div"> | null;
223
+ }
224
+ /**
225
+ * The panel: overlay, focus trap, Escape, scroll lock, and focus handed back to the trigger.
226
+ *
227
+ * Mounted only while open, so nothing of the palette is in the document (or in the tab
228
+ * order) the rest of the time.
229
+ */
230
+ declare function PaletteContent({ title, portal, overlayProps, children, ...props }: PaletteContentProps): ReactNode;
231
+ interface PaletteFieldProps extends Omit<ComponentPropsWithoutRef<"input">, "value" | "onChange"> {
232
+ asChild?: boolean;
233
+ }
234
+ /**
235
+ * The query field.
236
+ *
237
+ * A `combobox` that keeps the caret while the arrows move a highlight somewhere else -
238
+ * which is exactly what `aria-activedescendant` is for. Without it a screen reader hears
239
+ * nothing move, because focus never leaves the field.
240
+ */
241
+ declare function PaletteField({ asChild, onKeyDown, ...props }: PaletteFieldProps): ReactNode;
242
+ interface PaletteListProps<Item> extends Omit<ComponentPropsWithoutRef<"div">, "children"> {
243
+ /** Render one row. The default prints its label, which is enough to be usable. */
244
+ children?: (row: PaletteRow<Item>, state: {
245
+ active: boolean;
246
+ index: number;
247
+ }) => ReactNode;
248
+ /** Rendered when there is nothing to show. */
249
+ empty?: ReactNode;
250
+ /** The group heading. Pass null for a flat list with no headings. */
251
+ heading?: ((label: string) => ReactNode) | null;
252
+ }
253
+ /** The results, grouped, with one flat keyboard sequence running through them. */
254
+ declare function PaletteList<Item>({ children, empty, heading, ...props }: PaletteListProps<Item>): ReactNode;
255
+ interface PaletteItemProps<Item> extends Omit<ComponentPropsWithoutRef<"div">, "children"> {
256
+ row: PaletteRow<Item>;
257
+ index: number;
258
+ children?: ReactNode;
259
+ }
260
+ /**
261
+ * One row.
262
+ *
263
+ * The pointer MOVES the highlight rather than running a second one of its own: two
264
+ * highlights on screen is the thing that makes a palette feel unpredictable, because Enter
265
+ * then opens the row the mouse is not on.
266
+ */
267
+ declare function PaletteItem<Item>({ row, index, children, ...props }: PaletteItemProps<Item>): ReactNode;
268
+ interface PaletteFooterProps extends ComponentPropsWithoutRef<"div"> {
269
+ /** Replace the hints. The default names the three keys that actually matter. */
270
+ hints?: ReactNode;
271
+ }
272
+ /** The strip along the bottom that says which keys do what. */
273
+ declare function PaletteFooter({ hints, children, ...props }: PaletteFooterProps): ReactNode;
274
+
275
+ interface SearchPaletteProps<Item> extends PaletteRootProps<Item> {
276
+ placeholder?: string;
277
+ /** The trigger's own content. Pass null for a palette that only opens on the shortcut. */
278
+ trigger?: ReactNode | null;
279
+ /** Render one row, same signature as `SearchPalette.List`. */
280
+ renderItem?: PaletteListProps<Item>["children"];
281
+ empty?: ReactNode;
282
+ footer?: ReactNode;
283
+ }
284
+ /**
285
+ * The palette, assembled.
286
+ *
287
+ * ```tsx
288
+ * <SearchPalette items={docs} keys={["title", "body"]} onSelect={(doc) => go(doc.href)} />
289
+ * ```
290
+ *
291
+ * Everything it renders is a part you can render yourself instead - see `SearchPalette.Root`
292
+ * for the anatomy. This is the composition that covers the common case, not a different
293
+ * component: it is those parts, in the order they belong in.
294
+ */
295
+ declare function SearchPalette<Item>({ placeholder, trigger, renderItem, empty, footer, children, ...root }: SearchPaletteProps<Item>): ReactNode;
296
+ declare namespace SearchPalette {
297
+ var Root: typeof PaletteRoot;
298
+ var Trigger: typeof PaletteTrigger;
299
+ var Content: typeof PaletteContent;
300
+ var Field: typeof PaletteField;
301
+ var List: typeof PaletteList;
302
+ var Item: typeof PaletteItem;
303
+ var Footer: typeof PaletteFooter;
304
+ }
305
+
306
+ export { PaletteContent as P, type RecentEntry as R, SearchPalette as S, type PaletteContextValue as a, PaletteField as b, PaletteFooter as c, PaletteItem as d, PaletteList as e, type PaletteListProps as f, PaletteRoot as g, type PaletteRootProps as h, type PaletteRow as i, type PaletteSection as j, PaletteTrigger as k, type RecentStore as l, type SearchPaletteProps as m, createRecentStore as n, groupRows as o, isPaletteShortcut as p, moveActive as q, recentKey as r, shortcutLabel as s, usePaletteContext as u };
@@ -0,0 +1,144 @@
1
+ import { ReactNode, ComponentPropsWithoutRef } from 'react';
2
+ import { c as SearchOptions, F as FuseConstructor, b as SearchMatch } from './search-CsO3L1Lw.js';
3
+ import { G as GeneratePasswordOptions, E as EstimateOptions, b as PasswordStrengthReport } from './password-C8lG4Zm9.js';
4
+
5
+ /**
6
+ * The prop shapes for `<Input>`, split from the component so the per-type chunks can import
7
+ * them without importing the component - and so every type in here is erased at build,
8
+ * which is what keeps a `type="text"` field from pulling the password estimator or a search
9
+ * engine into the bundle.
10
+ *
11
+ * The API is ONE component keyed on `type`, the way HTML itself is: `type` is an attribute
12
+ * of one element, not a different element. Radix splits Select, Checkbox and Slider into
13
+ * their own primitives because those are composed widgets rather than an `<input>` - that
14
+ * split is about the DOM, not about the props. What varies here is which props EXIST, and
15
+ * that is a discriminated union: `strength` on a text field and `items` on a password field
16
+ * are compile errors rather than props that quietly do nothing.
17
+ */
18
+
19
+ /** An extra button inside the field. The built-ins are the same shape. */
20
+ interface FieldAction {
21
+ /** Stable id. Lands on `data-enigma-input-action`, and replaces a built-in of the same name. */
22
+ name: string;
23
+ /** Accessible name. Becomes `aria-label` and `title`. */
24
+ label: string;
25
+ icon: ReactNode;
26
+ onSelect: () => void;
27
+ /** Renders `aria-pressed`. Omit for actions that are not toggles. */
28
+ pressed?: boolean;
29
+ /** Default true. A false action is not rendered at all. */
30
+ visible?: boolean;
31
+ }
32
+ type BreachStatus = "idle" | "checking" | "safe" | "breached" | "error";
33
+ interface BreachState {
34
+ status: BreachStatus;
35
+ /** How many breaches the password appears in. 0 unless `status` is "breached". */
36
+ count: number;
37
+ /** Whatever the checker threw. The form decides whether that is worth showing. */
38
+ error: unknown;
39
+ }
40
+ type BreachChecker = (password: string, options: {
41
+ signal: AbortSignal;
42
+ }) => Promise<{
43
+ breached: boolean;
44
+ count: number;
45
+ }>;
46
+ /** Every `type` a single `<input>` element takes, plus the two this component teaches. */
47
+ type InputType = "text" | "email" | "password" | "search" | "tel" | "url" | "number" | "date" | "datetime-local" | "month" | "week" | "time" | "color" | "file" | "range" | "hidden" | "checkbox" | "radio";
48
+ interface PasswordStrengthClassNames {
49
+ track?: string;
50
+ segment?: string;
51
+ label?: string;
52
+ warning?: string;
53
+ }
54
+ /** What every type has, whatever it is. */
55
+ interface InputBaseProps extends Omit<ComponentPropsWithoutRef<"input">, "children" | "type"> {
56
+ /** The reveal toggle. Defaults to on for `type="password"` and off for everything else. */
57
+ reveal?: boolean;
58
+ revealLabels?: {
59
+ show?: string;
60
+ hide?: string;
61
+ };
62
+ /** Extra buttons, or a replacement for a built-in by name. */
63
+ actions?: FieldAction[];
64
+ /** Which end the buttons sit at. Position them yourself; this only orders the markup. */
65
+ position?: "start" | "end";
66
+ /** Props for the element wrapping the field, its buttons and anything under them. */
67
+ wrapperProps?: ComponentPropsWithoutRef<"div">;
68
+ /** Props for the row holding the field and its buttons - this is what you position. */
69
+ fieldProps?: ComponentPropsWithoutRef<"div">;
70
+ /**
71
+ * Classes for the parts you cannot reach with a ref, which is what Tailwind needs.
72
+ * `className` still goes to the `<input>` itself, where you would expect it.
73
+ */
74
+ classNames?: {
75
+ actions?: string;
76
+ action?: string;
77
+ strength?: PasswordStrengthClassNames;
78
+ results?: string;
79
+ result?: string;
80
+ };
81
+ /** Rendered inside the wrapper, after everything the type adds. Your error goes here. */
82
+ children?: ReactNode;
83
+ }
84
+ /** The half only a password field has. */
85
+ interface PasswordOnlyProps {
86
+ type: "password";
87
+ /** Offer to generate a password. `true` for the defaults, or the generator's options. */
88
+ generate?: boolean | GeneratePasswordOptions;
89
+ generateLabel?: string;
90
+ /** Show what was generated. On by default - a password nobody can read is not usable. */
91
+ revealOnGenerate?: boolean;
92
+ /**
93
+ * Also copy it to the clipboard. OFF by default and worth leaving off: the clipboard is
94
+ * shared with every other app on the machine and is not cleared.
95
+ */
96
+ copyOnGenerate?: boolean;
97
+ onGenerate?: (password: string) => void;
98
+ /** Score the password as it is typed, and render the meter under the field. */
99
+ strength?: boolean | EstimateOptions;
100
+ onStrengthChange?: (report: PasswordStrengthReport) => void;
101
+ /**
102
+ * Check the password against a breach corpus - pass `checkPasswordBreach` from
103
+ * @enigmax/utils, or your own. It is a prop rather than a built-in because it makes a
104
+ * network request, and that is not a decision a field should take on its own.
105
+ */
106
+ breach?: BreachChecker;
107
+ /** Quiet time before a check fires, in ms. Default 500. */
108
+ breachDelay?: number;
109
+ onBreachChange?: (state: BreachState) => void;
110
+ }
111
+ /** The half only a search field has. The palette is its own component, not a prop. */
112
+ interface SearchOnlyProps<Item = unknown> {
113
+ type: "search";
114
+ /** What to search. Leave it out for a field that only reports the query. */
115
+ items?: Item[];
116
+ /** Which fields to read. `["title", "body"]`, or leave it out for every string field. */
117
+ keys?: SearchOptions<Item>["keys"];
118
+ /** Quiet time before a search runs, in ms. Default 150. */
119
+ delay?: number;
120
+ /** Cap the result list. Applies to the empty query too. */
121
+ limit?: number;
122
+ /** Fuse.js's constructor, for fuzzy matching. Without it, a substring matcher is used. */
123
+ fuse?: FuseConstructor;
124
+ fuseOptions?: SearchOptions<Item>["fuseOptions"];
125
+ /** Replaces the engine outright, and wins over `fuse`. */
126
+ matcher?: SearchOptions<Item>["matcher"];
127
+ onResults?: (matches: SearchMatch<Item>[], query: string) => void;
128
+ /** Render the results under the field. Without it, the field only reports them. */
129
+ renderResults?: (matches: SearchMatch<Item>[], query: string) => ReactNode;
130
+ /** Clear button. On by default for a search field, because the platform's own is not. */
131
+ clearable?: boolean;
132
+ clearLabel?: string;
133
+ }
134
+ /** Everything else: one `<input>`, its native props, and no extras to bundle. */
135
+ interface PlainOnlyProps {
136
+ type?: Exclude<InputType, "password" | "search">;
137
+ }
138
+ type InputProps<Item = unknown> = InputBaseProps & (PasswordOnlyProps | SearchOnlyProps<Item> | PlainOnlyProps);
139
+
140
+ declare const Input: <Item = unknown>(props: InputProps<Item> & {
141
+ ref?: React.Ref<HTMLInputElement>;
142
+ }) => ReactNode;
143
+
144
+ export { type BreachChecker as B, type FieldAction as F, Input as I, type PasswordOnlyProps as P, type SearchOnlyProps as S, type BreachState as a, type BreachStatus as b, type InputBaseProps as c, type InputProps as d, type InputType as e, type PasswordStrengthClassNames as f, type PlainOnlyProps as g };