@enigmax/primitives 0.16.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 -496
- 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 -286
- 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 +53 -1
- package/registry.json +235 -16
- package/src/core/flags.ts +266 -0
- 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 +18 -0
- package/src/react/button.tsx +70 -4
- package/src/react/flag.tsx +70 -0
- package/src/react/index.ts +52 -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-53DQY6LP.js +0 -1164
- package/dist/chunk-U2KYYMBJ.js +0 -724
- package/src/react/input.tsx +0 -429
package/dist/index.d.ts
CHANGED
|
@@ -1,153 +1,20 @@
|
|
|
1
|
+
export { M as MarqueeHover, a as MarqueeInstance, b as MarqueeOptions, c as createMarquee } from './marquee-CJ3Uwy3E.js';
|
|
2
|
+
export { I as InputAction, a as InputActionState, b as InputIcon, c as InputInstance, d as InputOptions, e as createInput } from './input-BwXjFenq.js';
|
|
1
3
|
export { F as FuseConstructor, a as FuseLike, S as SearchInstance, b as SearchMatch, c as SearchOptions, d as createSearch } from './search-CsO3L1Lw.js';
|
|
4
|
+
export { B as ButtonCooldown, a as ButtonElement, b as ButtonInstance, c as ButtonOptions, d as ButtonState, e as createButton } from './button-CaXaqG_K.js';
|
|
5
|
+
export { E as EstimateOptions, G as GeneratePasswordOptions, P as PasswordAlphabet, a as PasswordScore, b as PasswordStrengthReport, e as estimatePasswordStrength, g as generatePassword } from './password-C8lG4Zm9.js';
|
|
6
|
+
export { N as Notification, a as NotificationAction, b as NotificationInput, c as NotificationTone, d as Notifications, e as NotificationsOptions, P as PromiseMessages, f as createNotifications } from './notifications-BpVV6sel.js';
|
|
7
|
+
export { N as NetworkMonitor, a as NetworkState, S as SERVER_NETWORK_STATE, c as createNetworkMonitor } from './network-D2LsBG_k.js';
|
|
8
|
+
export { R as RelativeTimeFormat, a as RelativeTimeOptions, b as RelativeTimePrecision, c as RelativeTimeStyle, d as RelativeTimeTense, e as RelativeTimeView, f as ensureZone, n as normalizeDate, p as parseDuration, r as relativeTimeAttributes, g as relativeTimeView } from './relative-time-YpRTG7YH.js';
|
|
9
|
+
export { F as FLAG_CDN, a as FLAG_RATIO, b as FlagConfig, c as FlagFormat, d as FlagOptions, e as FlagShape, f as FlagSource, g as FlagView, h as configureFlags, i as flagAttributes, j as flagConfig, k as flagName, l as flagSrc, m as flagView, n as normalizeFlagCode, r as resetFlagConfig } from './flags-BBJc9unY.js';
|
|
2
10
|
|
|
3
11
|
/**
|
|
4
|
-
*
|
|
12
|
+
* The icon shapes both renderers draw.
|
|
5
13
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* every
|
|
9
|
-
*
|
|
10
|
-
* Every rule encoded here was measured in a browser, not reasoned about. The
|
|
11
|
-
* comments marked "non-negotiable" name the bug that the obvious implementation
|
|
12
|
-
* shipped with.
|
|
13
|
-
*/
|
|
14
|
-
/**
|
|
15
|
-
* What a MOUSE resting on the row does to its speed. One option covers every case, so
|
|
16
|
-
* there is no pile of booleans to reconcile:
|
|
17
|
-
*
|
|
18
|
-
* - `"off"` ignore hover entirely (the default)
|
|
19
|
-
* - `"pause"` stop while the pointer is on it
|
|
20
|
-
* - a number multiply the cruise speed: `0.15` crawls, `1` changes nothing, `2` doubles
|
|
21
|
-
* - `{ speed }` an ABSOLUTE speed in px/s, whatever the cruise is; direction still
|
|
22
|
-
* follows `reverse`, so you give a magnitude and not a sign
|
|
23
|
-
*
|
|
24
|
-
* Touch never triggers any of it - see the pointerType note on the hover handler.
|
|
25
|
-
*/
|
|
26
|
-
type MarqueeHover = number | "off" | "pause" | {
|
|
27
|
-
speed: number;
|
|
28
|
-
};
|
|
29
|
-
interface MarqueeOptions {
|
|
30
|
-
/**
|
|
31
|
-
* Pixels per second. NOT a duration: a duration ties the speed to the item
|
|
32
|
-
* count and the row silently accelerates as content grows.
|
|
33
|
-
*/
|
|
34
|
-
speed?: number;
|
|
35
|
-
/** Scroll towards the start instead of the end. */
|
|
36
|
-
reverse?: boolean;
|
|
37
|
-
/** Scroll on the Y axis instead of the X axis. */
|
|
38
|
-
vertical?: boolean;
|
|
39
|
-
/** Allow grabbing and throwing the row. */
|
|
40
|
-
draggable?: boolean;
|
|
41
|
-
/** What a mouse resting on the row does to its speed. See {@link MarqueeHover}. */
|
|
42
|
-
hover?: MarqueeHover;
|
|
43
|
-
/** Fraction of the remaining velocity gap left after one second. */
|
|
44
|
-
decay?: number;
|
|
45
|
-
/**
|
|
46
|
-
* Apply the styles the behaviour needs (overflow, touch-action, user-select,
|
|
47
|
-
* will-change, transform). Never theme styles. Turn off to own them yourself.
|
|
48
|
-
*/
|
|
49
|
-
manageStyles?: boolean;
|
|
50
|
-
/**
|
|
51
|
-
* How the repeated copies get into the DOM.
|
|
52
|
-
* - "clone": the engine clones the first child of the track (vanilla, Astro).
|
|
53
|
-
* - "external": the consumer renders them and is told the count (React, Vue).
|
|
54
|
-
*/
|
|
55
|
-
copies?: "clone" | "external";
|
|
56
|
-
/** Called when the required copy count changes. Required for "external". */
|
|
57
|
-
onCopyCountChange?: (count: number) => void;
|
|
58
|
-
/** Called on a click that was not the end of a drag. */
|
|
59
|
-
onItemClick?: (event: MouseEvent) => void;
|
|
60
|
-
/** Called whenever the measured lap period changes. */
|
|
61
|
-
onMeasure?: (period: number, copyCount: number) => void;
|
|
62
|
-
}
|
|
63
|
-
interface MarqueeInstance {
|
|
64
|
-
/** Current offset in px, normalized to [0, period). */
|
|
65
|
-
readonly offset: number;
|
|
66
|
-
/** Measured distance between two copies of the content, in px. */
|
|
67
|
-
readonly period: number;
|
|
68
|
-
/** Copies currently required to cover the lane plus one whole period. */
|
|
69
|
-
readonly copyCount: number;
|
|
70
|
-
/** True between pointerdown and pointerup while the row is being grabbed. */
|
|
71
|
-
readonly dragging: boolean;
|
|
72
|
-
/** True while the OS asks for reduced motion. Autoplay stops, drag does not. */
|
|
73
|
-
readonly reducedMotion: boolean;
|
|
74
|
-
update(options: Partial<MarqueeOptions>): void;
|
|
75
|
-
/** Re-read the lap from the DOM. Called for you on resize and on font load. */
|
|
76
|
-
measure(): void;
|
|
77
|
-
pause(): void;
|
|
78
|
-
resume(): void;
|
|
79
|
-
destroy(): void;
|
|
80
|
-
}
|
|
81
|
-
declare function createMarquee(lane: HTMLElement, track: HTMLElement, options?: MarqueeOptions): MarqueeInstance;
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Input affordances: the buttons that live inside a field, with no styling of their own.
|
|
85
|
-
*
|
|
86
|
-
* A password field gets its reveal toggle automatically, because a field the visitor
|
|
87
|
-
* cannot read back is the single most common cause of a failed sign-in. Everything about
|
|
88
|
-
* it is replaceable - the icon, the label, the position, the container, whether it exists
|
|
89
|
-
* at all - and the same mechanism takes any other action you want in there.
|
|
90
|
-
*
|
|
91
|
-
* The details below are the ones the hand-rolled version gets wrong; each is commented
|
|
92
|
-
* with the failure it prevents.
|
|
14
|
+
* Their own module because the React field imports NOTHING else from the vanilla adapter:
|
|
15
|
+
* pulling `createInput` in for two arrays of path data put the whole imperative renderer
|
|
16
|
+
* into every React bundle, for a component that never calls it.
|
|
93
17
|
*/
|
|
94
|
-
/** What an action renders. A string is parsed as HTML, so an inline SVG works. */
|
|
95
|
-
type InputIcon = string | Node;
|
|
96
|
-
interface InputActionState {
|
|
97
|
-
/** The field the action belongs to. */
|
|
98
|
-
input: HTMLInputElement;
|
|
99
|
-
/** True while the password is readable. Always false for a non-password field. */
|
|
100
|
-
revealed: boolean;
|
|
101
|
-
/** The field cannot be acted on: disabled or read-only. */
|
|
102
|
-
locked: boolean;
|
|
103
|
-
}
|
|
104
|
-
interface InputAction {
|
|
105
|
-
/** Stable id. Used for `data-action` and to replace a built-in (e.g. "reveal"). */
|
|
106
|
-
name: string;
|
|
107
|
-
/** Accessible name. Becomes both `aria-label` and `title`. */
|
|
108
|
-
label: string | ((state: InputActionState) => string);
|
|
109
|
-
icon: InputIcon | ((state: InputActionState) => InputIcon);
|
|
110
|
-
/** Runs on click and on Enter/Space, because it is a real button. */
|
|
111
|
-
onSelect: (state: InputActionState) => void;
|
|
112
|
-
/** Renders `aria-pressed`. Omit for actions that are not a toggle. */
|
|
113
|
-
pressed?: (state: InputActionState) => boolean;
|
|
114
|
-
/** Hide the action without removing it, e.g. a clear button on an empty field. */
|
|
115
|
-
visible?: (state: InputActionState) => boolean;
|
|
116
|
-
}
|
|
117
|
-
interface InputOptions {
|
|
118
|
-
/**
|
|
119
|
-
* The password reveal. `false` removes it. An object overrides parts of it - the
|
|
120
|
-
* icons, the labels - without giving up the caret and focus handling.
|
|
121
|
-
*/
|
|
122
|
-
reveal?: boolean | {
|
|
123
|
-
/** Shown while the password is hidden; selecting it reveals. */
|
|
124
|
-
showIcon?: InputIcon;
|
|
125
|
-
/** Shown while the password is readable. */
|
|
126
|
-
hideIcon?: InputIcon;
|
|
127
|
-
showLabel?: string;
|
|
128
|
-
hideLabel?: string;
|
|
129
|
-
};
|
|
130
|
-
/** Extra actions, or a replacement for a built-in when `name` matches. */
|
|
131
|
-
actions?: InputAction[];
|
|
132
|
-
/** Which side the actions mount on. Position them yourself with CSS. */
|
|
133
|
-
position?: "start" | "end";
|
|
134
|
-
/**
|
|
135
|
-
* Mount the actions here instead of in a container created next to the input.
|
|
136
|
-
* Use it when your markup already has a slot for them.
|
|
137
|
-
*/
|
|
138
|
-
container?: HTMLElement;
|
|
139
|
-
/** Called whenever the password's visibility changes. */
|
|
140
|
-
onRevealChange?: (revealed: boolean) => void;
|
|
141
|
-
}
|
|
142
|
-
interface InputInstance {
|
|
143
|
-
readonly revealed: boolean;
|
|
144
|
-
/** Show or hide the password. Toggles when the argument is omitted. */
|
|
145
|
-
reveal(next?: boolean): void;
|
|
146
|
-
/** Re-read the field and re-render the actions. Call after changing it yourself. */
|
|
147
|
-
refresh(): void;
|
|
148
|
-
update(options: Partial<InputOptions>): void;
|
|
149
|
-
destroy(): void;
|
|
150
|
-
}
|
|
151
18
|
/**
|
|
152
19
|
* The built-in glyphs, as path data.
|
|
153
20
|
*
|
|
@@ -160,358 +27,11 @@ declare const INPUT_ICON_PATHS: {
|
|
|
160
27
|
readonly eye: readonly ["M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7Z", "M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"];
|
|
161
28
|
readonly eyeOff: readonly ["M10.6 5.2A9.8 9.8 0 0 1 12 5c6.5 0 10 7 10 7a17.6 17.6 0 0 1-3.2 4.2M6.2 6.2A17.7 17.7 0 0 0 2 12s3.5 7 10 7a9.6 9.6 0 0 0 4.2-.9", "m2 2 20 20", "M9.9 9.9a3 3 0 0 0 4.2 4.2"];
|
|
162
29
|
readonly generate: readonly ["m12 3 1.9 4.6L18.5 9.5 13.9 11.4 12 16l-1.9-4.6L5.5 9.5l4.6-1.9Z", "M19 15l.8 2.2 2.2.8-2.2.8-.8 2.2-.8-2.2-2.2-.8 2.2-.8Z"];
|
|
30
|
+
/** Clears a search field. The platform draws one only in WebKit, and not on mobile. */
|
|
31
|
+
readonly clear: readonly ["m6 6 12 12", "m18 6-12 12"];
|
|
32
|
+
readonly search: readonly ["M11 4a7 7 0 1 0 0 14 7 7 0 0 0 0-14Z", "m20 20-4.2-4.2"];
|
|
163
33
|
};
|
|
164
34
|
/** The same shapes as a standalone SVG string, for the DOM renderer below. */
|
|
165
35
|
declare function iconMarkup(paths: readonly string[]): string;
|
|
166
|
-
/**
|
|
167
|
-
* Wire a field's in-field actions.
|
|
168
|
-
*
|
|
169
|
-
* @param input The field itself. A `type="password"` field gets the reveal for free.
|
|
170
|
-
*/
|
|
171
|
-
declare function createInput(input: HTMLInputElement, options?: InputOptions): InputInstance;
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* Button behaviour: what makes it unavailable, and everything that follows from that.
|
|
175
|
-
*
|
|
176
|
-
* Disabled, loading and a cooldown are three reasons for the same state, so they collapse
|
|
177
|
-
* into one `available` the renderer reads, instead of three flags every call site has to
|
|
178
|
-
* combine correctly. The element to render is reported rather than chosen, because a
|
|
179
|
-
* framework-agnostic package cannot import next/link.
|
|
180
|
-
*/
|
|
181
|
-
/** Which tag the consumer should render. An href makes it a link, and a link is not a button. */
|
|
182
|
-
type ButtonElement = "button" | "a";
|
|
183
|
-
interface ButtonCooldown {
|
|
184
|
-
/** How long the button stays unavailable after a press, in ms. */
|
|
185
|
-
ms: number;
|
|
186
|
-
/**
|
|
187
|
-
* Survive a reload under this key. Without it the cooldown is in memory only, and a
|
|
188
|
-
* refresh is a free retry - which is the whole thing a cooldown exists to prevent.
|
|
189
|
-
*/
|
|
190
|
-
key?: string;
|
|
191
|
-
storage?: "local" | "session";
|
|
192
|
-
}
|
|
193
|
-
interface ButtonOptions {
|
|
194
|
-
/** Turns into an `a`, and a link cannot be `disabled` - only `aria-disabled`. */
|
|
195
|
-
href?: string;
|
|
196
|
-
disabled?: boolean;
|
|
197
|
-
/** Unavailable and busy. Set it yourself, or let an async `onPress` manage it. */
|
|
198
|
-
loading?: boolean;
|
|
199
|
-
/** ms, or the full shape for a cooldown that outlives a reload. */
|
|
200
|
-
cooldown?: number | ButtonCooldown;
|
|
201
|
-
/**
|
|
202
|
-
* A single key that presses the button. Ignored while the visitor is typing, and
|
|
203
|
-
* while any modifier is held, so it never steals a real shortcut.
|
|
204
|
-
*/
|
|
205
|
-
shortcut?: string;
|
|
206
|
-
/** Async work flips `loading` for its duration and only then starts the cooldown. */
|
|
207
|
-
onPress?: (event?: Event) => void | Promise<void>;
|
|
208
|
-
/** Called whenever anything below changes. */
|
|
209
|
-
onChange?: (state: ButtonState) => void;
|
|
210
|
-
}
|
|
211
|
-
interface ButtonState {
|
|
212
|
-
/** The tag to render. */
|
|
213
|
-
element: ButtonElement;
|
|
214
|
-
/** Pressable: not disabled, not loading, not cooling down. */
|
|
215
|
-
available: boolean;
|
|
216
|
-
loading: boolean;
|
|
217
|
-
disabled: boolean;
|
|
218
|
-
/** ms left on the cooldown, 0 when there is none. */
|
|
219
|
-
cooldown: number;
|
|
220
|
-
/** The accessible name for the shortcut, when there is one. */
|
|
221
|
-
shortcut: string | null;
|
|
222
|
-
}
|
|
223
|
-
interface ButtonInstance {
|
|
224
|
-
readonly state: ButtonState;
|
|
225
|
-
/** Run the press as if it had been clicked. Ignored while unavailable. */
|
|
226
|
-
press(event?: Event): Promise<void>;
|
|
227
|
-
update(options: Partial<ButtonOptions>): void;
|
|
228
|
-
/** Clear a cooldown early, including its stored entry. */
|
|
229
|
-
reset(): void;
|
|
230
|
-
subscribe(listener: (state: ButtonState) => void): () => void;
|
|
231
|
-
destroy(): void;
|
|
232
|
-
}
|
|
233
|
-
declare function createButton(options?: ButtonOptions): ButtonInstance;
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Making a password, and judging one.
|
|
237
|
-
*
|
|
238
|
-
* Both are opt-in. A sign-in form wants neither: offering to generate a password where one
|
|
239
|
-
* already exists is noise, and scoring one the visitor cannot change is worse. They belong
|
|
240
|
-
* on a registration form and a change-password form, which is where an agent should switch
|
|
241
|
-
* them on.
|
|
242
|
-
*/
|
|
243
|
-
/** Character classes a generated password can draw from. */
|
|
244
|
-
interface PasswordAlphabet {
|
|
245
|
-
lowercase?: boolean;
|
|
246
|
-
uppercase?: boolean;
|
|
247
|
-
digits?: boolean;
|
|
248
|
-
symbols?: boolean;
|
|
249
|
-
}
|
|
250
|
-
interface GeneratePasswordOptions extends PasswordAlphabet {
|
|
251
|
-
/** Default 20. Long beats clever: length is the only term that scales. */
|
|
252
|
-
length?: number;
|
|
253
|
-
/**
|
|
254
|
-
* Drop the characters that are read wrong off a screen or off paper - I l 1 O 0.
|
|
255
|
-
* Worth it when the password will be typed by hand, not worth the entropy otherwise.
|
|
256
|
-
*/
|
|
257
|
-
excludeAmbiguous?: boolean;
|
|
258
|
-
/** Characters to remove from every class, e.g. ones your backend rejects. */
|
|
259
|
-
exclude?: string;
|
|
260
|
-
/**
|
|
261
|
-
* Guarantee at least one character from every class asked for. Most password policies
|
|
262
|
-
* demand it; it costs a little entropy, because it removes every password that happens
|
|
263
|
-
* to lack one.
|
|
264
|
-
*/
|
|
265
|
-
requireEachClass?: boolean;
|
|
266
|
-
}
|
|
267
|
-
/**
|
|
268
|
-
* A random password from the classes asked for.
|
|
269
|
-
*
|
|
270
|
-
* @throws when the runtime has no CSPRNG, or when the options ask for something impossible
|
|
271
|
-
* (every class excluded, or a length too short to hold one of each).
|
|
272
|
-
*/
|
|
273
|
-
declare function generatePassword(options?: GeneratePasswordOptions): string;
|
|
274
|
-
type PasswordScore = 0 | 1 | 2 | 3 | 4;
|
|
275
|
-
interface PasswordStrengthReport {
|
|
276
|
-
/** 0 worst, 4 best. What the bars under the field render. */
|
|
277
|
-
score: PasswordScore;
|
|
278
|
-
/** Estimated bits of entropy after the penalties below. */
|
|
279
|
-
bits: number;
|
|
280
|
-
/**
|
|
281
|
-
* Why it scored what it scored, worst first. Show the first one; showing all of them
|
|
282
|
-
* turns a hint into a lecture.
|
|
283
|
-
*/
|
|
284
|
-
warnings: string[];
|
|
285
|
-
/** Empty field. Render nothing rather than a zero score, which reads as a failure. */
|
|
286
|
-
empty: boolean;
|
|
287
|
-
}
|
|
288
|
-
interface EstimateOptions {
|
|
289
|
-
/**
|
|
290
|
-
* Values the visitor has already typed elsewhere - email, name, company. A password
|
|
291
|
-
* containing one of them is guessable by anyone who has the sign-up form in front of
|
|
292
|
-
* them, and no character-class rule catches it.
|
|
293
|
-
*/
|
|
294
|
-
userInputs?: string[];
|
|
295
|
-
}
|
|
296
|
-
/**
|
|
297
|
-
* Score a password.
|
|
298
|
-
*
|
|
299
|
-
* The bits are an estimate and the bands are a convention, not a measurement - they exist
|
|
300
|
-
* to move a bar, not to certify anything. Swap this out for zxcvbn where the number has to
|
|
301
|
-
* mean something, and check the breach corpus for the cases no estimator can see.
|
|
302
|
-
*/
|
|
303
|
-
declare function estimatePasswordStrength(password: string, options?: EstimateOptions): PasswordStrengthReport;
|
|
304
|
-
|
|
305
|
-
/**
|
|
306
|
-
* Notification queue: ordering, timers, dedupe and pause. No rendering, no styles.
|
|
307
|
-
*
|
|
308
|
-
* The timer is the part that is always wrong when hand-rolled. A dismiss timer
|
|
309
|
-
* that keeps counting while the tab is hidden fires the moment the visitor comes
|
|
310
|
-
* back and they never see the message, so the remaining time is held, not run.
|
|
311
|
-
*/
|
|
312
|
-
type NotificationTone = "info" | "success" | "warning" | "error" | "loading";
|
|
313
|
-
/** One button on a notification. Anything more belongs on the page, not in a toast. */
|
|
314
|
-
interface NotificationAction {
|
|
315
|
-
label: string;
|
|
316
|
-
onSelect: () => void;
|
|
317
|
-
/** Dismiss once it has been pressed. On by default. */
|
|
318
|
-
dismiss?: boolean;
|
|
319
|
-
}
|
|
320
|
-
interface NotificationInput {
|
|
321
|
-
/** Reuses the slot of a live notification with the same key instead of stacking. */
|
|
322
|
-
key?: string;
|
|
323
|
-
title: string;
|
|
324
|
-
body?: string;
|
|
325
|
-
tone?: NotificationTone;
|
|
326
|
-
/** ms before it dismisses itself. 0 or Infinity keeps it until dismissed. */
|
|
327
|
-
duration?: number;
|
|
328
|
-
action?: NotificationAction;
|
|
329
|
-
/** Arbitrary payload for the renderer: an href, an icon name. */
|
|
330
|
-
data?: unknown;
|
|
331
|
-
}
|
|
332
|
-
interface Notification extends Required<Omit<NotificationInput, "body" | "data" | "key" | "action">> {
|
|
333
|
-
id: string;
|
|
334
|
-
key?: string;
|
|
335
|
-
body?: string;
|
|
336
|
-
action?: NotificationAction;
|
|
337
|
-
data?: unknown;
|
|
338
|
-
createdAt: number;
|
|
339
|
-
}
|
|
340
|
-
/** What `promise()` shows at each stage. A function receives the resolved value or the error. */
|
|
341
|
-
interface PromiseMessages<T> {
|
|
342
|
-
loading: string | NotificationInput;
|
|
343
|
-
success: string | ((value: T) => string | NotificationInput);
|
|
344
|
-
error: string | ((error: unknown) => string | NotificationInput);
|
|
345
|
-
}
|
|
346
|
-
interface NotificationsOptions {
|
|
347
|
-
/** Live notifications kept at once. The oldest dismissable one makes room. */
|
|
348
|
-
max?: number;
|
|
349
|
-
/** Default ms before self-dismissal. */
|
|
350
|
-
duration?: number;
|
|
351
|
-
/** Errors default to staying until dismissed. */
|
|
352
|
-
stickyTones?: NotificationTone[];
|
|
353
|
-
}
|
|
354
|
-
interface Notifications {
|
|
355
|
-
readonly items: readonly Notification[];
|
|
356
|
-
notify(input: NotificationInput): string;
|
|
357
|
-
/** Change a live notification in place, keeping its slot and restarting its timer. */
|
|
358
|
-
update(id: string, patch: Partial<NotificationInput>): void;
|
|
359
|
-
/**
|
|
360
|
-
* One notification that follows an async operation from loading to its outcome, in the
|
|
361
|
-
* same slot. The alternative is three toasts stacking up for one action.
|
|
362
|
-
*/
|
|
363
|
-
promise<T>(work: Promise<T>, messages: PromiseMessages<T>): Promise<T>;
|
|
364
|
-
dismiss(id: string): void;
|
|
365
|
-
dismissAll(): void;
|
|
366
|
-
/** Hold every timer, e.g. while a pointer rests on the stack. */
|
|
367
|
-
pause(): void;
|
|
368
|
-
resume(): void;
|
|
369
|
-
subscribe(listener: (items: readonly Notification[]) => void): () => void;
|
|
370
|
-
destroy(): void;
|
|
371
|
-
}
|
|
372
|
-
declare function createNotifications(options?: NotificationsOptions): Notifications;
|
|
373
|
-
|
|
374
|
-
/**
|
|
375
|
-
* Connection state: online/offline plus whatever the Network Information API will say.
|
|
376
|
-
*
|
|
377
|
-
* The part worth not rewriting is the TRANSITION. "You are back online" needs to know the
|
|
378
|
-
* connection had dropped, and every implementation of that ends up as a stray `wasOffline`
|
|
379
|
-
* boolean next to the effect, re-derived per screen and wrong the first time the page
|
|
380
|
-
* loads offline. It is tracked here instead.
|
|
381
|
-
*/
|
|
382
|
-
interface NetworkState {
|
|
383
|
-
online: boolean;
|
|
384
|
-
/** Estimated downlink in Mbps. Null where the browser does not report it. */
|
|
385
|
-
downlink: number | null;
|
|
386
|
-
downlinkMax: number | null;
|
|
387
|
-
/** "slow-2g" | "2g" | "3g" | "4g", or null. */
|
|
388
|
-
effectiveType: string | null;
|
|
389
|
-
/** Estimated round-trip time in ms. */
|
|
390
|
-
rtt: number | null;
|
|
391
|
-
/** The visitor asked for reduced data use. */
|
|
392
|
-
saveData: boolean | null;
|
|
393
|
-
/** "wifi" | "cellular" | "ethernet" | ..., or null. */
|
|
394
|
-
type: string | null;
|
|
395
|
-
/**
|
|
396
|
-
* The connection dropped earlier and is back. False on a first load, so a page that
|
|
397
|
-
* opens online never announces a recovery that did not happen.
|
|
398
|
-
*/
|
|
399
|
-
recovered: boolean;
|
|
400
|
-
/** On a connection worth degrading for: 2g or slower, or data saver on. */
|
|
401
|
-
slow: boolean;
|
|
402
|
-
}
|
|
403
|
-
interface NetworkMonitor {
|
|
404
|
-
readonly state: NetworkState;
|
|
405
|
-
subscribe(listener: (state: NetworkState) => void): () => void;
|
|
406
|
-
destroy(): void;
|
|
407
|
-
}
|
|
408
|
-
/** What a server render sees. Assuming offline would flash a warning on every page. */
|
|
409
|
-
declare const SERVER_NETWORK_STATE: NetworkState;
|
|
410
|
-
declare function createNetworkMonitor(): NetworkMonitor;
|
|
411
|
-
|
|
412
|
-
/**
|
|
413
|
-
* Relative time: "3 hours ago", and everything that has to be right around it.
|
|
414
|
-
*
|
|
415
|
-
* The rendering itself is `<relative-time>` (@github/relative-time-element), which already
|
|
416
|
-
* owns the hard parts - Intl.RelativeTimeFormat per locale, and re-rendering on a schedule
|
|
417
|
-
* that gets slower as the date gets older. What is here is the part every wrapper
|
|
418
|
-
* re-implements and usually gets wrong: parsing a timestamp that does not declare its zone,
|
|
419
|
-
* knowing when the date has aged past the relative threshold, and producing an absolute
|
|
420
|
-
* label to show while the element is still loading, or forever if scripting is off.
|
|
421
|
-
*
|
|
422
|
-
* Nothing in this file touches the DOM, so it renders on a server.
|
|
423
|
-
*/
|
|
424
|
-
/** How the element should phrase it. `auto` is relative until the threshold, then a date. */
|
|
425
|
-
type RelativeTimeFormat = "auto" | "relative" | "duration" | "datetime" | "micro" | "elapsed";
|
|
426
|
-
type RelativeTimeTense = "auto" | "past" | "future";
|
|
427
|
-
type RelativeTimePrecision = "year" | "month" | "day" | "hour" | "minute" | "second";
|
|
428
|
-
type RelativeTimeStyle = "long" | "short" | "narrow";
|
|
429
|
-
type NumericStyle = "numeric" | "2-digit";
|
|
430
|
-
interface RelativeTimeOptions {
|
|
431
|
-
format?: RelativeTimeFormat;
|
|
432
|
-
tense?: RelativeTimeTense;
|
|
433
|
-
precision?: RelativeTimePrecision;
|
|
434
|
-
/** ISO 8601 duration. Past this age `auto` stops being relative. Default `P30D`. */
|
|
435
|
-
threshold?: string;
|
|
436
|
-
/** Word before an absolute date, e.g. "on 5 May". Empty string removes it. */
|
|
437
|
-
prefix?: string;
|
|
438
|
-
formatStyle?: RelativeTimeStyle;
|
|
439
|
-
/**
|
|
440
|
-
* BCP 47 tag. Left undefined the element reads the closest `lang` in the document,
|
|
441
|
-
* which is what a translated page wants - hardcoding one is how a Spanish page ends
|
|
442
|
-
* up saying "3 hours ago".
|
|
443
|
-
*/
|
|
444
|
-
locale?: string;
|
|
445
|
-
/** IANA zone for the absolute rendering. Undefined means the reader's own. */
|
|
446
|
-
timeZone?: string;
|
|
447
|
-
second?: NumericStyle;
|
|
448
|
-
minute?: NumericStyle;
|
|
449
|
-
hour?: NumericStyle;
|
|
450
|
-
weekday?: RelativeTimeStyle;
|
|
451
|
-
day?: NumericStyle;
|
|
452
|
-
month?: NumericStyle | "short" | "long" | "narrow";
|
|
453
|
-
year?: NumericStyle;
|
|
454
|
-
timeZoneName?: "long" | "short" | "shortOffset" | "longOffset" | "shortGeneric" | "longGeneric";
|
|
455
|
-
/** Drop the exact timestamp the element otherwise puts in `title`. */
|
|
456
|
-
noTitle?: boolean;
|
|
457
|
-
/**
|
|
458
|
-
* Once the date is older than `threshold`, render it as digits (05/05/2026) instead of
|
|
459
|
-
* a prefixed month name. The cutoff is the threshold itself, not a guess at it.
|
|
460
|
-
*/
|
|
461
|
-
numericBeyondThreshold?: boolean;
|
|
462
|
-
}
|
|
463
|
-
/** Everything derived from a date, in one pass, for whichever adapter is rendering it. */
|
|
464
|
-
interface RelativeTimeView {
|
|
465
|
-
/** Null when the input could not be parsed - nothing else here is meaningful then. */
|
|
466
|
-
date: Date | null;
|
|
467
|
-
/** `datetime` attribute value: always UTC, always ISO. */
|
|
468
|
-
iso: string;
|
|
469
|
-
/** Absolute text. Shown until the element upgrades, and forever without scripting. */
|
|
470
|
-
label: string;
|
|
471
|
-
/** Full timestamp for `title` / `aria-label`. */
|
|
472
|
-
exact: string;
|
|
473
|
-
/** The date is older (or further ahead) than `threshold`. */
|
|
474
|
-
beyondThreshold: boolean;
|
|
475
|
-
/** Render `label` in a plain `<time>` and skip the element entirely. */
|
|
476
|
-
absoluteOnly: boolean;
|
|
477
|
-
}
|
|
478
|
-
/**
|
|
479
|
-
* A timestamp with no zone is UTC.
|
|
480
|
-
*
|
|
481
|
-
* This is the single most common defect in a date column: `2026-08-13 22:41:00` comes back
|
|
482
|
-
* from the database with no offset, `new Date()` reads it as LOCAL time, and every reader
|
|
483
|
-
* east or west of the server sees a time that is hours out - silently, because the wrong
|
|
484
|
-
* time is still a valid one.
|
|
485
|
-
*
|
|
486
|
-
* A date with no clock is left exactly as it is. The spec already reads a bare `YYYY-MM-DD`
|
|
487
|
-
* as UTC, so there is nothing to add - and `YYYY-MM-DDZ` is not in the spec's grammar at
|
|
488
|
-
* all, which drops it into each engine's own legacy parser. That is a portability coin
|
|
489
|
-
* flip on a value that was already correct.
|
|
490
|
-
*/
|
|
491
|
-
declare function ensureZone(text: string): string;
|
|
492
|
-
/** Parse anything a date column or an API hands over. Null rather than an Invalid Date. */
|
|
493
|
-
declare function normalizeDate(value: string | number | Date | null | undefined): Date | null;
|
|
494
|
-
/**
|
|
495
|
-
* ISO 8601 duration to milliseconds, for comparing an age against `threshold`.
|
|
496
|
-
*
|
|
497
|
-
* Years and months are approximated the way the element approximates them, because the
|
|
498
|
-
* threshold is a rough "old enough to stop counting", not an anniversary.
|
|
499
|
-
*/
|
|
500
|
-
declare function parseDuration(value: string): number;
|
|
501
|
-
/**
|
|
502
|
-
* Everything an adapter needs to render one date.
|
|
503
|
-
*
|
|
504
|
-
* `now` is a parameter so a test can pin it, and so a server render can pass the same
|
|
505
|
-
* instant it used elsewhere on the page.
|
|
506
|
-
*/
|
|
507
|
-
declare function relativeTimeView(value: string | number | Date | null | undefined, options?: RelativeTimeOptions, now?: Date): RelativeTimeView;
|
|
508
|
-
/**
|
|
509
|
-
* The element's attributes, kebab-cased, with anything undefined left out.
|
|
510
|
-
*
|
|
511
|
-
* Written as attributes rather than properties because that is the half of a custom
|
|
512
|
-
* element's API that works before it is defined - the markup is already correct when the
|
|
513
|
-
* definition arrives late, or never.
|
|
514
|
-
*/
|
|
515
|
-
declare function relativeTimeAttributes(view: RelativeTimeView, options?: RelativeTimeOptions): Record<string, string>;
|
|
516
36
|
|
|
517
|
-
export {
|
|
37
|
+
export { INPUT_ICON_PATHS, iconMarkup };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,10 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { createInput } from './chunk-KJINGUQN.js';
|
|
2
|
+
export { estimatePasswordStrength, generatePassword } from './chunk-HC2ME5PU.js';
|
|
3
|
+
export { FLAG_CDN, FLAG_RATIO, configureFlags, flagAttributes, flagConfig, flagName, flagSrc, flagView, normalizeFlagCode, resetFlagConfig } from './chunk-AU3H5WIY.js';
|
|
4
|
+
export { createMarquee } from './chunk-UOSSNUSC.js';
|
|
5
|
+
export { SERVER_NETWORK_STATE, createNetworkMonitor } from './chunk-2QFTRNAZ.js';
|
|
6
|
+
export { createNotifications } from './chunk-SNYUBXWQ.js';
|
|
7
|
+
export { ensureZone, normalizeDate, parseDuration, relativeTimeAttributes, relativeTimeView } from './chunk-IXVMRVD4.js';
|
|
8
|
+
export { INPUT_ICON_PATHS, iconMarkup } from './chunk-F25CGNQC.js';
|
|
2
9
|
export { createSearch } from './chunk-UZFEEFMF.js';
|
|
10
|
+
export { createButton } from './chunk-MMQPZGSU.js';
|
|
@@ -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 };
|