@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.
- package/dist/button-CaXaqG_K.d.ts +63 -0
- package/dist/chunk-2QFTRNAZ.js +88 -0
- package/dist/chunk-6BGBYUSZ.js +114 -0
- package/dist/chunk-AU3H5WIY.js +107 -0
- package/dist/chunk-F25CGNQC.js +19 -0
- package/dist/chunk-HC2ME5PU.js +168 -0
- package/dist/chunk-HS3X3XCW.js +43 -0
- package/dist/chunk-IIT6U7LM.js +249 -0
- package/dist/chunk-IXVMRVD4.js +96 -0
- package/dist/chunk-KJINGUQN.js +188 -0
- package/dist/chunk-LKA2UG4P.js +542 -0
- package/dist/chunk-MMQPZGSU.js +161 -0
- package/dist/chunk-OCMI7R6H.js +79 -0
- package/dist/chunk-QYMUIW5I.js +28 -0
- package/dist/chunk-S653GLSF.js +17 -0
- package/dist/chunk-SNYUBXWQ.js +149 -0
- package/dist/chunk-U3V4EHOB.js +41 -0
- package/dist/chunk-UOSSNUSC.js +309 -0
- package/dist/chunk-WSB655JB.js +47 -0
- package/dist/chunk-XNNQRA35.js +31 -0
- package/dist/chunk-XQHCZAPJ.js +102 -0
- package/dist/chunk-ZCUFYBPB.js +154 -0
- package/dist/chunk-ZWR2EXHQ.js +55 -0
- package/dist/flags-BBJc9unY.d.ts +133 -0
- package/dist/index-D-ARvWpQ.d.ts +306 -0
- package/dist/index-DNXPtY9X.d.ts +144 -0
- package/dist/index.d.ts +16 -602
- package/dist/index.js +9 -1
- package/dist/input-BwXjFenq.d.ts +77 -0
- package/dist/marquee-CJ3Uwy3E.d.ts +81 -0
- package/dist/network-D2LsBG_k.d.ts +39 -0
- package/dist/next/index.d.ts +20 -3
- package/dist/next/index.js +23 -3
- package/dist/notifications-BpVV6sel.d.ts +70 -0
- package/dist/password-3DRQYAYQ.js +2 -0
- package/dist/password-C8lG4Zm9.d.ts +71 -0
- package/dist/password-FB2CUEKJ.js +1 -0
- package/dist/react/button.d.ts +75 -0
- package/dist/react/button.js +4 -0
- package/dist/react/flag.d.ts +37 -0
- package/dist/react/flag.js +3 -0
- package/dist/react/index.d.ts +28 -312
- package/dist/react/index.js +22 -2
- package/dist/react/input.d.ts +4 -0
- package/dist/react/input.js +3 -0
- package/dist/react/marquee.d.ts +44 -0
- package/dist/react/marquee.js +3 -0
- package/dist/react/network.d.ts +20 -0
- package/dist/react/network.js +3 -0
- package/dist/react/notifications.d.ts +17 -0
- package/dist/react/notifications.js +3 -0
- package/dist/react/palette.d.ts +3 -0
- package/dist/react/palette.js +4 -0
- package/dist/react/relative-time.d.ts +21 -0
- package/dist/react/relative-time.js +3 -0
- package/dist/react/search.d.ts +30 -0
- package/dist/react/search.js +3 -0
- package/dist/react/slot.d.ts +47 -0
- package/dist/react/slot.js +2 -0
- package/dist/react/toast.d.ts +40 -0
- package/dist/react/toast.js +4 -0
- package/dist/react-router/index.d.ts +20 -3
- package/dist/react-router/index.js +23 -3
- package/dist/relative-time-YpRTG7YH.d.ts +106 -0
- package/dist/search-P4OHCRXD.js +50 -0
- package/package.json +52 -2
- package/registry.json +175 -18
- package/src/core/flags.ts +88 -42
- package/src/core/input-icons.ts +34 -0
- package/src/core/input.ts +5 -21
- package/src/core/palette.ts +0 -0
- package/src/index.ts +2 -2
- package/src/react/button.tsx +70 -4
- package/src/react/flag.tsx +18 -6
- package/src/react/index.ts +40 -5
- package/src/react/input/icon.tsx +17 -0
- package/src/react/input/index.tsx +307 -0
- package/src/react/input/password.tsx +174 -0
- package/src/react/input/search.tsx +82 -0
- package/src/react/input/types.ts +146 -0
- package/src/react/input/write-value.ts +18 -0
- package/src/react/palette/context.ts +60 -0
- package/src/react/palette/index.tsx +66 -0
- package/src/react/palette/root.tsx +621 -0
- package/src/react/slot.tsx +91 -0
- package/src/react/use-button.ts +3 -1
- package/dist/chunk-4GLYRF4B.js +0 -1259
- package/dist/chunk-JFNND6P4.js +0 -749
- package/src/react/input.tsx +0 -429
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input affordances: the buttons that live inside a field, with no styling of their own.
|
|
3
|
+
*
|
|
4
|
+
* A password field gets its reveal toggle automatically, because a field the visitor
|
|
5
|
+
* cannot read back is the single most common cause of a failed sign-in. Everything about
|
|
6
|
+
* it is replaceable - the icon, the label, the position, the container, whether it exists
|
|
7
|
+
* at all - and the same mechanism takes any other action you want in there.
|
|
8
|
+
*
|
|
9
|
+
* The details below are the ones the hand-rolled version gets wrong; each is commented
|
|
10
|
+
* with the failure it prevents.
|
|
11
|
+
*/
|
|
12
|
+
/** What an action renders. A string is parsed as HTML, so an inline SVG works. */
|
|
13
|
+
type InputIcon = string | Node;
|
|
14
|
+
interface InputActionState {
|
|
15
|
+
/** The field the action belongs to. */
|
|
16
|
+
input: HTMLInputElement;
|
|
17
|
+
/** True while the password is readable. Always false for a non-password field. */
|
|
18
|
+
revealed: boolean;
|
|
19
|
+
/** The field cannot be acted on: disabled or read-only. */
|
|
20
|
+
locked: boolean;
|
|
21
|
+
}
|
|
22
|
+
interface InputAction {
|
|
23
|
+
/** Stable id. Used for `data-action` and to replace a built-in (e.g. "reveal"). */
|
|
24
|
+
name: string;
|
|
25
|
+
/** Accessible name. Becomes both `aria-label` and `title`. */
|
|
26
|
+
label: string | ((state: InputActionState) => string);
|
|
27
|
+
icon: InputIcon | ((state: InputActionState) => InputIcon);
|
|
28
|
+
/** Runs on click and on Enter/Space, because it is a real button. */
|
|
29
|
+
onSelect: (state: InputActionState) => void;
|
|
30
|
+
/** Renders `aria-pressed`. Omit for actions that are not a toggle. */
|
|
31
|
+
pressed?: (state: InputActionState) => boolean;
|
|
32
|
+
/** Hide the action without removing it, e.g. a clear button on an empty field. */
|
|
33
|
+
visible?: (state: InputActionState) => boolean;
|
|
34
|
+
}
|
|
35
|
+
interface InputOptions {
|
|
36
|
+
/**
|
|
37
|
+
* The password reveal. `false` removes it. An object overrides parts of it - the
|
|
38
|
+
* icons, the labels - without giving up the caret and focus handling.
|
|
39
|
+
*/
|
|
40
|
+
reveal?: boolean | {
|
|
41
|
+
/** Shown while the password is hidden; selecting it reveals. */
|
|
42
|
+
showIcon?: InputIcon;
|
|
43
|
+
/** Shown while the password is readable. */
|
|
44
|
+
hideIcon?: InputIcon;
|
|
45
|
+
showLabel?: string;
|
|
46
|
+
hideLabel?: string;
|
|
47
|
+
};
|
|
48
|
+
/** Extra actions, or a replacement for a built-in when `name` matches. */
|
|
49
|
+
actions?: InputAction[];
|
|
50
|
+
/** Which side the actions mount on. Position them yourself with CSS. */
|
|
51
|
+
position?: "start" | "end";
|
|
52
|
+
/**
|
|
53
|
+
* Mount the actions here instead of in a container created next to the input.
|
|
54
|
+
* Use it when your markup already has a slot for them.
|
|
55
|
+
*/
|
|
56
|
+
container?: HTMLElement;
|
|
57
|
+
/** Called whenever the password's visibility changes. */
|
|
58
|
+
onRevealChange?: (revealed: boolean) => void;
|
|
59
|
+
}
|
|
60
|
+
interface InputInstance {
|
|
61
|
+
readonly revealed: boolean;
|
|
62
|
+
/** Show or hide the password. Toggles when the argument is omitted. */
|
|
63
|
+
reveal(next?: boolean): void;
|
|
64
|
+
/** Re-read the field and re-render the actions. Call after changing it yourself. */
|
|
65
|
+
refresh(): void;
|
|
66
|
+
update(options: Partial<InputOptions>): void;
|
|
67
|
+
destroy(): void;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Wire a field's in-field actions.
|
|
72
|
+
*
|
|
73
|
+
* @param input The field itself. A `type="password"` field gets the reveal for free.
|
|
74
|
+
*/
|
|
75
|
+
declare function createInput(input: HTMLInputElement, options?: InputOptions): InputInstance;
|
|
76
|
+
|
|
77
|
+
export { type InputAction as I, type InputActionState as a, type InputIcon as b, type InputInstance as c, type InputOptions as d, createInput as e };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Draggable infinite marquee: the behaviour engine, with no styling of its own.
|
|
3
|
+
*
|
|
4
|
+
* The contract is a SPEED in pixels per second, never a duration. A lap of a
|
|
5
|
+
* looping row is as long as its content, so a duration makes the row run faster
|
|
6
|
+
* every time an item is added to it. See the package README.
|
|
7
|
+
*
|
|
8
|
+
* Every rule encoded here was measured in a browser, not reasoned about. The
|
|
9
|
+
* comments marked "non-negotiable" name the bug that the obvious implementation
|
|
10
|
+
* shipped with.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* What a MOUSE resting on the row does to its speed. One option covers every case, so
|
|
14
|
+
* there is no pile of booleans to reconcile:
|
|
15
|
+
*
|
|
16
|
+
* - `"off"` ignore hover entirely (the default)
|
|
17
|
+
* - `"pause"` stop while the pointer is on it
|
|
18
|
+
* - a number multiply the cruise speed: `0.15` crawls, `1` changes nothing, `2` doubles
|
|
19
|
+
* - `{ speed }` an ABSOLUTE speed in px/s, whatever the cruise is; direction still
|
|
20
|
+
* follows `reverse`, so you give a magnitude and not a sign
|
|
21
|
+
*
|
|
22
|
+
* Touch never triggers any of it - see the pointerType note on the hover handler.
|
|
23
|
+
*/
|
|
24
|
+
type MarqueeHover = number | "off" | "pause" | {
|
|
25
|
+
speed: number;
|
|
26
|
+
};
|
|
27
|
+
interface MarqueeOptions {
|
|
28
|
+
/**
|
|
29
|
+
* Pixels per second. NOT a duration: a duration ties the speed to the item
|
|
30
|
+
* count and the row silently accelerates as content grows.
|
|
31
|
+
*/
|
|
32
|
+
speed?: number;
|
|
33
|
+
/** Scroll towards the start instead of the end. */
|
|
34
|
+
reverse?: boolean;
|
|
35
|
+
/** Scroll on the Y axis instead of the X axis. */
|
|
36
|
+
vertical?: boolean;
|
|
37
|
+
/** Allow grabbing and throwing the row. */
|
|
38
|
+
draggable?: boolean;
|
|
39
|
+
/** What a mouse resting on the row does to its speed. See {@link MarqueeHover}. */
|
|
40
|
+
hover?: MarqueeHover;
|
|
41
|
+
/** Fraction of the remaining velocity gap left after one second. */
|
|
42
|
+
decay?: number;
|
|
43
|
+
/**
|
|
44
|
+
* Apply the styles the behaviour needs (overflow, touch-action, user-select,
|
|
45
|
+
* will-change, transform). Never theme styles. Turn off to own them yourself.
|
|
46
|
+
*/
|
|
47
|
+
manageStyles?: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* How the repeated copies get into the DOM.
|
|
50
|
+
* - "clone": the engine clones the first child of the track (vanilla, Astro).
|
|
51
|
+
* - "external": the consumer renders them and is told the count (React, Vue).
|
|
52
|
+
*/
|
|
53
|
+
copies?: "clone" | "external";
|
|
54
|
+
/** Called when the required copy count changes. Required for "external". */
|
|
55
|
+
onCopyCountChange?: (count: number) => void;
|
|
56
|
+
/** Called on a click that was not the end of a drag. */
|
|
57
|
+
onItemClick?: (event: MouseEvent) => void;
|
|
58
|
+
/** Called whenever the measured lap period changes. */
|
|
59
|
+
onMeasure?: (period: number, copyCount: number) => void;
|
|
60
|
+
}
|
|
61
|
+
interface MarqueeInstance {
|
|
62
|
+
/** Current offset in px, normalized to [0, period). */
|
|
63
|
+
readonly offset: number;
|
|
64
|
+
/** Measured distance between two copies of the content, in px. */
|
|
65
|
+
readonly period: number;
|
|
66
|
+
/** Copies currently required to cover the lane plus one whole period. */
|
|
67
|
+
readonly copyCount: number;
|
|
68
|
+
/** True between pointerdown and pointerup while the row is being grabbed. */
|
|
69
|
+
readonly dragging: boolean;
|
|
70
|
+
/** True while the OS asks for reduced motion. Autoplay stops, drag does not. */
|
|
71
|
+
readonly reducedMotion: boolean;
|
|
72
|
+
update(options: Partial<MarqueeOptions>): void;
|
|
73
|
+
/** Re-read the lap from the DOM. Called for you on resize and on font load. */
|
|
74
|
+
measure(): void;
|
|
75
|
+
pause(): void;
|
|
76
|
+
resume(): void;
|
|
77
|
+
destroy(): void;
|
|
78
|
+
}
|
|
79
|
+
declare function createMarquee(lane: HTMLElement, track: HTMLElement, options?: MarqueeOptions): MarqueeInstance;
|
|
80
|
+
|
|
81
|
+
export { type MarqueeHover as M, type MarqueeInstance as a, type MarqueeOptions as b, createMarquee as c };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connection state: online/offline plus whatever the Network Information API will say.
|
|
3
|
+
*
|
|
4
|
+
* The part worth not rewriting is the TRANSITION. "You are back online" needs to know the
|
|
5
|
+
* connection had dropped, and every implementation of that ends up as a stray `wasOffline`
|
|
6
|
+
* boolean next to the effect, re-derived per screen and wrong the first time the page
|
|
7
|
+
* loads offline. It is tracked here instead.
|
|
8
|
+
*/
|
|
9
|
+
interface NetworkState {
|
|
10
|
+
online: boolean;
|
|
11
|
+
/** Estimated downlink in Mbps. Null where the browser does not report it. */
|
|
12
|
+
downlink: number | null;
|
|
13
|
+
downlinkMax: number | null;
|
|
14
|
+
/** "slow-2g" | "2g" | "3g" | "4g", or null. */
|
|
15
|
+
effectiveType: string | null;
|
|
16
|
+
/** Estimated round-trip time in ms. */
|
|
17
|
+
rtt: number | null;
|
|
18
|
+
/** The visitor asked for reduced data use. */
|
|
19
|
+
saveData: boolean | null;
|
|
20
|
+
/** "wifi" | "cellular" | "ethernet" | ..., or null. */
|
|
21
|
+
type: string | null;
|
|
22
|
+
/**
|
|
23
|
+
* The connection dropped earlier and is back. False on a first load, so a page that
|
|
24
|
+
* opens online never announces a recovery that did not happen.
|
|
25
|
+
*/
|
|
26
|
+
recovered: boolean;
|
|
27
|
+
/** On a connection worth degrading for: 2g or slower, or data saver on. */
|
|
28
|
+
slow: boolean;
|
|
29
|
+
}
|
|
30
|
+
interface NetworkMonitor {
|
|
31
|
+
readonly state: NetworkState;
|
|
32
|
+
subscribe(listener: (state: NetworkState) => void): () => void;
|
|
33
|
+
destroy(): void;
|
|
34
|
+
}
|
|
35
|
+
/** What a server render sees. Assuming offline would flash a warning on every page. */
|
|
36
|
+
declare const SERVER_NETWORK_STATE: NetworkState;
|
|
37
|
+
declare function createNetworkMonitor(): NetworkMonitor;
|
|
38
|
+
|
|
39
|
+
export { type NetworkMonitor as N, SERVER_NETWORK_STATE as S, type NetworkState as a, createNetworkMonitor as c };
|
package/dist/next/index.d.ts
CHANGED
|
@@ -1,8 +1,25 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { ButtonProps } from '../react/
|
|
3
|
-
export {
|
|
4
|
-
export {
|
|
2
|
+
import { ButtonProps } from '../react/button.js';
|
|
3
|
+
export { UseMarqueeResult, useMarquee } from '../react/marquee.js';
|
|
4
|
+
export { M as MarqueeHover, a as MarqueeInstance, b as MarqueeOptions } from '../marquee-CJ3Uwy3E.js';
|
|
5
|
+
export { PasswordStrength, PasswordStrengthProps, UseButtonResult, UseInputResult, getLinkComponent, setLinkComponent, useButton, useInput } from '../react/index.js';
|
|
6
|
+
export { UseSearchResult, useSearch } from '../react/search.js';
|
|
7
|
+
export { I as InputAction, b as InputIcon, d as InputOptions } from '../input-BwXjFenq.js';
|
|
5
8
|
export { F as FuseConstructor, b as SearchMatch, c as SearchOptions } from '../search-CsO3L1Lw.js';
|
|
9
|
+
export { c as ButtonOptions, d as ButtonState } from '../button-CaXaqG_K.js';
|
|
10
|
+
export { B as BreachChecker, a as BreachState, b as BreachStatus, F as FieldAction, I as Input, c as InputBaseProps, d as InputProps, e as InputType, P as PasswordOnlyProps, g as PlainOnlyProps, S as SearchOnlyProps } from '../index-DNXPtY9X.js';
|
|
11
|
+
export { Slot, SlotProps, mergeSlotProps } from '../react/slot.js';
|
|
12
|
+
export { E as EstimateOptions, G as GeneratePasswordOptions, a as PasswordScore, b as PasswordStrengthReport, e as estimatePasswordStrength, g as generatePassword } from '../password-C8lG4Zm9.js';
|
|
13
|
+
export { UseNotificationsResult, createNotificationQueue, defaultQueue, useNotifications } from '../react/notifications.js';
|
|
14
|
+
export { ToastControls, ToastPosition, Toaster, ToasterProps } from '../react/toast.js';
|
|
15
|
+
export { useNetworkState } from '../react/network.js';
|
|
16
|
+
export { a as NetworkState } from '../network-D2LsBG_k.js';
|
|
17
|
+
export { RelativeTime, RelativeTimeProps } from '../react/relative-time.js';
|
|
18
|
+
export { Flag, FlagProps } from '../react/flag.js';
|
|
19
|
+
export { c as FlagFormat, d as FlagOptions, e as FlagShape, f as FlagSource, h as configureFlags, i as flagAttributes, k as flagName, l as flagSrc, m as flagView, n as normalizeFlagCode } from '../flags-BBJc9unY.js';
|
|
20
|
+
export { P as PaletteContent, a as PaletteContextValue, b as PaletteField, c as PaletteFooter, d as PaletteItem, e as PaletteList, f as PaletteListProps, g as PaletteRoot, h as PaletteRootProps, i as PaletteRow, j as PaletteSection, k as PaletteTrigger, R as RecentEntry, l as RecentStore, S as SearchPalette, m as SearchPaletteProps, n as createRecentStore, o as groupRows, p as isPaletteShortcut, q as moveActive, r as recentKey, s as shortcutLabel, u as usePaletteContext } from '../index-D-ARvWpQ.js';
|
|
21
|
+
import '../notifications-BpVV6sel.js';
|
|
22
|
+
import '../relative-time-YpRTG7YH.js';
|
|
6
23
|
|
|
7
24
|
/**
|
|
8
25
|
* The Next.js entry. Same components, wired to `next/link`.
|
package/dist/next/index.js
CHANGED
|
@@ -1,8 +1,28 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
|
|
3
|
-
export {
|
|
4
|
-
export {
|
|
2
|
+
export { useInput } from '../chunk-U3V4EHOB.js';
|
|
3
|
+
export { PasswordStrength } from '../chunk-XQHCZAPJ.js';
|
|
4
|
+
export { Flag } from '../chunk-XNNQRA35.js';
|
|
5
|
+
export { Toaster } from '../chunk-ZCUFYBPB.js';
|
|
6
|
+
export { useMarquee } from '../chunk-ZWR2EXHQ.js';
|
|
7
|
+
export { useSearch } from '../chunk-WSB655JB.js';
|
|
8
|
+
export { useNetworkState } from '../chunk-S653GLSF.js';
|
|
9
|
+
export { createNotificationQueue, defaultQueue, useNotifications } from '../chunk-QYMUIW5I.js';
|
|
10
|
+
export { RelativeTime } from '../chunk-OCMI7R6H.js';
|
|
11
|
+
import '../chunk-KJINGUQN.js';
|
|
12
|
+
export { estimatePasswordStrength, generatePassword } from '../chunk-HC2ME5PU.js';
|
|
13
|
+
export { configureFlags, flagAttributes, flagName, flagSrc, flagView, normalizeFlagCode } from '../chunk-AU3H5WIY.js';
|
|
14
|
+
import '../chunk-UOSSNUSC.js';
|
|
15
|
+
import '../chunk-2QFTRNAZ.js';
|
|
16
|
+
import '../chunk-SNYUBXWQ.js';
|
|
17
|
+
import '../chunk-IXVMRVD4.js';
|
|
18
|
+
export { Input } from '../chunk-IIT6U7LM.js';
|
|
19
|
+
import '../chunk-F25CGNQC.js';
|
|
20
|
+
export { PaletteContent, PaletteField, PaletteFooter, PaletteItem, PaletteList, PaletteRoot, PaletteTrigger, SearchPalette, createRecentStore, groupRows, isPaletteShortcut, moveActive, recentKey, shortcutLabel, usePaletteContext } from '../chunk-LKA2UG4P.js';
|
|
5
21
|
import '../chunk-UZFEEFMF.js';
|
|
22
|
+
import { Button } from '../chunk-6BGBYUSZ.js';
|
|
23
|
+
export { getLinkComponent, setLinkComponent, useButton } from '../chunk-6BGBYUSZ.js';
|
|
24
|
+
import '../chunk-MMQPZGSU.js';
|
|
25
|
+
export { Slot, mergeSlotProps } from '../chunk-HS3X3XCW.js';
|
|
6
26
|
import Link from 'next/link';
|
|
7
27
|
import { forwardRef, createElement } from 'react';
|
|
8
28
|
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Notification queue: ordering, timers, dedupe and pause. No rendering, no styles.
|
|
3
|
+
*
|
|
4
|
+
* The timer is the part that is always wrong when hand-rolled. A dismiss timer
|
|
5
|
+
* that keeps counting while the tab is hidden fires the moment the visitor comes
|
|
6
|
+
* back and they never see the message, so the remaining time is held, not run.
|
|
7
|
+
*/
|
|
8
|
+
type NotificationTone = "info" | "success" | "warning" | "error" | "loading";
|
|
9
|
+
/** One button on a notification. Anything more belongs on the page, not in a toast. */
|
|
10
|
+
interface NotificationAction {
|
|
11
|
+
label: string;
|
|
12
|
+
onSelect: () => void;
|
|
13
|
+
/** Dismiss once it has been pressed. On by default. */
|
|
14
|
+
dismiss?: boolean;
|
|
15
|
+
}
|
|
16
|
+
interface NotificationInput {
|
|
17
|
+
/** Reuses the slot of a live notification with the same key instead of stacking. */
|
|
18
|
+
key?: string;
|
|
19
|
+
title: string;
|
|
20
|
+
body?: string;
|
|
21
|
+
tone?: NotificationTone;
|
|
22
|
+
/** ms before it dismisses itself. 0 or Infinity keeps it until dismissed. */
|
|
23
|
+
duration?: number;
|
|
24
|
+
action?: NotificationAction;
|
|
25
|
+
/** Arbitrary payload for the renderer: an href, an icon name. */
|
|
26
|
+
data?: unknown;
|
|
27
|
+
}
|
|
28
|
+
interface Notification extends Required<Omit<NotificationInput, "body" | "data" | "key" | "action">> {
|
|
29
|
+
id: string;
|
|
30
|
+
key?: string;
|
|
31
|
+
body?: string;
|
|
32
|
+
action?: NotificationAction;
|
|
33
|
+
data?: unknown;
|
|
34
|
+
createdAt: number;
|
|
35
|
+
}
|
|
36
|
+
/** What `promise()` shows at each stage. A function receives the resolved value or the error. */
|
|
37
|
+
interface PromiseMessages<T> {
|
|
38
|
+
loading: string | NotificationInput;
|
|
39
|
+
success: string | ((value: T) => string | NotificationInput);
|
|
40
|
+
error: string | ((error: unknown) => string | NotificationInput);
|
|
41
|
+
}
|
|
42
|
+
interface NotificationsOptions {
|
|
43
|
+
/** Live notifications kept at once. The oldest dismissable one makes room. */
|
|
44
|
+
max?: number;
|
|
45
|
+
/** Default ms before self-dismissal. */
|
|
46
|
+
duration?: number;
|
|
47
|
+
/** Errors default to staying until dismissed. */
|
|
48
|
+
stickyTones?: NotificationTone[];
|
|
49
|
+
}
|
|
50
|
+
interface Notifications {
|
|
51
|
+
readonly items: readonly Notification[];
|
|
52
|
+
notify(input: NotificationInput): string;
|
|
53
|
+
/** Change a live notification in place, keeping its slot and restarting its timer. */
|
|
54
|
+
update(id: string, patch: Partial<NotificationInput>): void;
|
|
55
|
+
/**
|
|
56
|
+
* One notification that follows an async operation from loading to its outcome, in the
|
|
57
|
+
* same slot. The alternative is three toasts stacking up for one action.
|
|
58
|
+
*/
|
|
59
|
+
promise<T>(work: Promise<T>, messages: PromiseMessages<T>): Promise<T>;
|
|
60
|
+
dismiss(id: string): void;
|
|
61
|
+
dismissAll(): void;
|
|
62
|
+
/** Hold every timer, e.g. while a pointer rests on the stack. */
|
|
63
|
+
pause(): void;
|
|
64
|
+
resume(): void;
|
|
65
|
+
subscribe(listener: (items: readonly Notification[]) => void): () => void;
|
|
66
|
+
destroy(): void;
|
|
67
|
+
}
|
|
68
|
+
declare function createNotifications(options?: NotificationsOptions): Notifications;
|
|
69
|
+
|
|
70
|
+
export { type Notification as N, type PromiseMessages as P, type NotificationAction as a, type NotificationInput as b, type NotificationTone as c, type Notifications as d, type NotificationsOptions as e, createNotifications as f };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Making a password, and judging one.
|
|
3
|
+
*
|
|
4
|
+
* Both are opt-in. A sign-in form wants neither: offering to generate a password where one
|
|
5
|
+
* already exists is noise, and scoring one the visitor cannot change is worse. They belong
|
|
6
|
+
* on a registration form and a change-password form, which is where an agent should switch
|
|
7
|
+
* them on.
|
|
8
|
+
*/
|
|
9
|
+
/** Character classes a generated password can draw from. */
|
|
10
|
+
interface PasswordAlphabet {
|
|
11
|
+
lowercase?: boolean;
|
|
12
|
+
uppercase?: boolean;
|
|
13
|
+
digits?: boolean;
|
|
14
|
+
symbols?: boolean;
|
|
15
|
+
}
|
|
16
|
+
interface GeneratePasswordOptions extends PasswordAlphabet {
|
|
17
|
+
/** Default 20. Long beats clever: length is the only term that scales. */
|
|
18
|
+
length?: number;
|
|
19
|
+
/**
|
|
20
|
+
* Drop the characters that are read wrong off a screen or off paper - I l 1 O 0.
|
|
21
|
+
* Worth it when the password will be typed by hand, not worth the entropy otherwise.
|
|
22
|
+
*/
|
|
23
|
+
excludeAmbiguous?: boolean;
|
|
24
|
+
/** Characters to remove from every class, e.g. ones your backend rejects. */
|
|
25
|
+
exclude?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Guarantee at least one character from every class asked for. Most password policies
|
|
28
|
+
* demand it; it costs a little entropy, because it removes every password that happens
|
|
29
|
+
* to lack one.
|
|
30
|
+
*/
|
|
31
|
+
requireEachClass?: boolean;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* A random password from the classes asked for.
|
|
35
|
+
*
|
|
36
|
+
* @throws when the runtime has no CSPRNG, or when the options ask for something impossible
|
|
37
|
+
* (every class excluded, or a length too short to hold one of each).
|
|
38
|
+
*/
|
|
39
|
+
declare function generatePassword(options?: GeneratePasswordOptions): string;
|
|
40
|
+
type PasswordScore = 0 | 1 | 2 | 3 | 4;
|
|
41
|
+
interface PasswordStrengthReport {
|
|
42
|
+
/** 0 worst, 4 best. What the bars under the field render. */
|
|
43
|
+
score: PasswordScore;
|
|
44
|
+
/** Estimated bits of entropy after the penalties below. */
|
|
45
|
+
bits: number;
|
|
46
|
+
/**
|
|
47
|
+
* Why it scored what it scored, worst first. Show the first one; showing all of them
|
|
48
|
+
* turns a hint into a lecture.
|
|
49
|
+
*/
|
|
50
|
+
warnings: string[];
|
|
51
|
+
/** Empty field. Render nothing rather than a zero score, which reads as a failure. */
|
|
52
|
+
empty: boolean;
|
|
53
|
+
}
|
|
54
|
+
interface EstimateOptions {
|
|
55
|
+
/**
|
|
56
|
+
* Values the visitor has already typed elsewhere - email, name, company. A password
|
|
57
|
+
* containing one of them is guessable by anyone who has the sign-up form in front of
|
|
58
|
+
* them, and no character-class rule catches it.
|
|
59
|
+
*/
|
|
60
|
+
userInputs?: string[];
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Score a password.
|
|
64
|
+
*
|
|
65
|
+
* The bits are an estimate and the bands are a convention, not a measurement - they exist
|
|
66
|
+
* to move a bar, not to certify anything. Swap this out for zxcvbn where the number has to
|
|
67
|
+
* mean something, and check the breach corpus for the cases no estimator can see.
|
|
68
|
+
*/
|
|
69
|
+
declare function estimatePasswordStrength(password: string, options?: EstimateOptions): PasswordStrengthReport;
|
|
70
|
+
|
|
71
|
+
export { type EstimateOptions as E, type GeneratePasswordOptions as G, type PasswordAlphabet as P, type PasswordScore as a, type PasswordStrengthReport as b, estimatePasswordStrength as e, generatePassword as g };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { estimatePasswordStrength, generatePassword } from './chunk-HC2ME5PU.js';
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ComponentPropsWithoutRef, ElementType, ReactNode } from 'react';
|
|
3
|
+
import { c as ButtonOptions, d as ButtonState } from '../button-CaXaqG_K.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `<Button>` - the component, for the ninety percent.
|
|
7
|
+
*
|
|
8
|
+
* ```tsx
|
|
9
|
+
* <Button onPress={save}>Save</Button>
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* That is the whole thing: disabled while the work runs, `aria-busy`, `data-loading`, and a
|
|
13
|
+
* cooldown afterwards if you asked for one. `useButton` is still there for a button whose
|
|
14
|
+
* markup is nothing like a button - a card, a table row - but reaching for it to render an
|
|
15
|
+
* ordinary one means writing the same six lines at every call site, which is how they drift.
|
|
16
|
+
*/
|
|
17
|
+
interface ButtonProps extends ButtonOptions, Omit<ComponentPropsWithoutRef<"button">, "onClick" | "onChange" | "children" | "type"> {
|
|
18
|
+
/**
|
|
19
|
+
* What to run when it is pressed. The same thing as `onPress`, under the name React
|
|
20
|
+
* already uses - write whichever reads better.
|
|
21
|
+
*
|
|
22
|
+
* It is an ALIAS, not a second handler: the component owns the element's real onClick,
|
|
23
|
+
* because that is where a press is refused while the button is loading, disabled or
|
|
24
|
+
* cooling down. Passing one through would replace that and silently take the behaviour
|
|
25
|
+
* with it. Returning a promise drives `loading` for its duration, same as `onPress`.
|
|
26
|
+
*/
|
|
27
|
+
onClick?: ButtonOptions["onPress"];
|
|
28
|
+
/**
|
|
29
|
+
* Override what to render. You rarely need it: an href already renders whatever
|
|
30
|
+
* `setLinkComponent` registered - your router's Link - and a button otherwise.
|
|
31
|
+
*/
|
|
32
|
+
as?: ElementType;
|
|
33
|
+
/**
|
|
34
|
+
* The label, or a function of the state for one that changes with it.
|
|
35
|
+
*
|
|
36
|
+
* ```tsx
|
|
37
|
+
* <Button onPress={send} cooldown={30_000}>
|
|
38
|
+
* {({ loading, cooldown }) => loading ? "Sending" : cooldown ? `Wait ${Math.ceil(cooldown / 1000)}s` : "Resend"}
|
|
39
|
+
* </Button>
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
children?: ReactNode | ((state: ButtonState) => ReactNode);
|
|
43
|
+
/** Replaces the label while async work runs - a spinner, or just different words. */
|
|
44
|
+
pending?: ReactNode;
|
|
45
|
+
/** `type` on a real button. Ignored on a link, which has none. */
|
|
46
|
+
type?: "button" | "submit" | "reset";
|
|
47
|
+
/**
|
|
48
|
+
* Show the shortcut as a key badge after the label, the way Stripe writes
|
|
49
|
+
* "Create invoice n".
|
|
50
|
+
*
|
|
51
|
+
* `"auto"` (the default) shows it when there is a shortcut AND the label renders text:
|
|
52
|
+
* beside a lone glyph on an icon-only button the badge is noise, and it would double the
|
|
53
|
+
* width of the smallest control on the screen. `true` and `false` decide it outright.
|
|
54
|
+
*/
|
|
55
|
+
shortcutHint?: boolean | "auto";
|
|
56
|
+
/** Render the badge yourself. Return null to drop it for one button. */
|
|
57
|
+
renderShortcut?: (key: string) => ReactNode;
|
|
58
|
+
/**
|
|
59
|
+
* Put the behaviour on YOUR element instead of ours - a `motion.button`, your design
|
|
60
|
+
* system's button, a router Link, anything.
|
|
61
|
+
*
|
|
62
|
+
* ```tsx
|
|
63
|
+
* <Button asChild cooldown={30_000} onPress={resend}>
|
|
64
|
+
* <motion.button whileTap={{ scale: 0.98 }}>Resend</motion.button>
|
|
65
|
+
* </Button>
|
|
66
|
+
* ```
|
|
67
|
+
*
|
|
68
|
+
* The child owns its own markup, so the shortcut badge is not injected - the child is
|
|
69
|
+
* rendered exactly as written. Read `state.shortcut` from `useButton` to place your own.
|
|
70
|
+
*/
|
|
71
|
+
asChild?: boolean;
|
|
72
|
+
}
|
|
73
|
+
declare const Button: react.ForwardRefExoticComponent<ButtonProps & react.RefAttributes<HTMLElement>>;
|
|
74
|
+
|
|
75
|
+
export { Button, type ButtonProps };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { ImgHTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
import { e as FlagShape, c as FlagFormat, f as FlagSource } from '../flags-BBJc9unY.js';
|
|
3
|
+
|
|
4
|
+
interface FlagProps extends Omit<ImgHTMLAttributes<HTMLImageElement>, "src" | "alt" | "width" | "height"> {
|
|
5
|
+
/** `es`, `ES`, `en-GB`, `gb-eng`, or the emoji flag you are replacing. */
|
|
6
|
+
code: string | null | undefined;
|
|
7
|
+
/**
|
|
8
|
+
* Your own accessible name. Left out, the country's own name is used, in the reader's
|
|
9
|
+
* language - so a flag standing on its own is never a silent image.
|
|
10
|
+
*/
|
|
11
|
+
label?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Beside a country name that is already on screen the flag is decoration, and repeating
|
|
14
|
+
* the name only makes a screen reader say it twice.
|
|
15
|
+
*/
|
|
16
|
+
decorative?: boolean;
|
|
17
|
+
/** Language the automatic name is written in. Follows the document's `lang` otherwise. */
|
|
18
|
+
locale?: string;
|
|
19
|
+
shape?: FlagShape;
|
|
20
|
+
format?: FlagFormat;
|
|
21
|
+
source?: FlagSource;
|
|
22
|
+
basePath?: string;
|
|
23
|
+
/** Rendered height in px. The width follows the shape. Default 16. */
|
|
24
|
+
size?: number;
|
|
25
|
+
/** Rendered when the code resolves to nothing. Nothing, by default. */
|
|
26
|
+
fallback?: ReactNode;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* `<Flag code="es" />` - a country flag as an image, at the size you asked for, from the
|
|
30
|
+
* source the app configured once.
|
|
31
|
+
*
|
|
32
|
+
* The defaults come from `configureFlags`, so moving the whole application from the CDN to
|
|
33
|
+
* a downloaded set is one line at startup and no change at any call site.
|
|
34
|
+
*/
|
|
35
|
+
declare function Flag({ code, label, decorative, locale, shape, format, source, basePath, size, fallback, ...rest }: FlagProps): ReactNode;
|
|
36
|
+
|
|
37
|
+
export { Flag, type FlagProps };
|