@dragunio/fe-libs 0.1.8 → 0.1.9

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/README.md CHANGED
@@ -56,6 +56,8 @@ Available review routes:
56
56
  - `http://127.0.0.1:3000/#/datetime` — DateTimePicker
57
57
  - `http://127.0.0.1:3000/#/currency` — CurrencyInput
58
58
  - `http://127.0.0.1:3000/#/number` — NumberInput
59
+ - `http://127.0.0.1:3000/#/file-upload` — FileUpload
60
+ - `http://127.0.0.1:3000/#/file-preview` — FilePreview
59
61
  - `http://127.0.0.1:3000/#/tooltip` — Tooltip
60
62
  - `http://127.0.0.1:3000/#/expandable` — ExpandableSection
61
63
  - `http://127.0.0.1:3000/#/loading` — Loading
@@ -65,6 +67,7 @@ Available review routes:
65
67
  - `http://127.0.0.1:3000/#/chip` — Chip
66
68
  - `http://127.0.0.1:3000/#/avatar` — Avatar
67
69
  - `http://127.0.0.1:3000/#/text-input` — TextInput & TextArea
70
+ - `http://127.0.0.1:3000/#/validated-inputs` — EmailInput, PasswordInput & PhoneNumberInput
68
71
  - `http://127.0.0.1:3000/#/pagination` — Pagination
69
72
  - `http://127.0.0.1:3000/#/message` — Message
70
73
  - `http://127.0.0.1:3000/#/snackbar` — Snackbar
@@ -191,14 +194,17 @@ The library exposes ESM, CommonJS, TypeScript declarations, and keeps React as a
191
194
 
192
195
  ### New form and overlay primitives
193
196
 
194
- - `Drawer` is a portal-based modal panel with `left`, `right`, `top`, and `bottom` slide-in animations. Use `fullScreen` for a full-viewport panel and `footer` for fixed actions below the scrollable body.
197
+ - `Drawer` is a portal-based modal panel with `left`, `right`, `top`, and `bottom` slide-in animations. Use `DrawerWidths.small`, `.medium`, or `.large` (360px, 400px, 480px) with `width`, or provide any custom CSS width. Use `fullScreen` for a full-viewport panel and `footer` for fixed actions below the scrollable body. It automatically adapts to smaller screens: side drawers use the available viewport width, while top and bottom drawers become sheet-style panels.
195
198
  - `Selection` is a rounded custom dropdown inspired by DropdownCustom, with single/multiple modes, optional search, clear action, tags, form-field values, and keyboard navigation.
196
199
  - `DateTimePicker` supports `mode="single"` and `mode="range"`; its default format is `dd/MM/yyyy HH:mm`.
197
200
  - `NumberInput` and `CurrencyInput` format values immediately while typing (`1000` → `1,000`) and keep up to two fractional digits by default. Both include accessible up/down controls (and arrow-key support); use `step` or `showStepper` to configure them. `NumberInput` also accepts `prefix`/`suffix` adornments. Use `allowDecimal`, `decimals`, `min`, and `max` to control decimal input and numeric limits. Both support `error` and `errorMessage` with the same red border/message treatment as `TextInput`. `CurrencyInput` adds a `VND` suffix by default, or a currency dropdown through `currencies`.
201
+ - `FileUpload` accepts browser `File` objects from selecting or dropping files. Choose its preset `accept` groups—such as `image`, `pdf`, `document`, `audio`, and `video`—instead of manually assembling MIME patterns; it validates them with `maxSize`, `maxFiles`, and duplicate checks locally, then emits `onChange`, `onAccept`, `onReject`, and `onRemove` synchronously. It deliberately contains no endpoint, request, `async`, or upload-progress behavior.
202
+ - `FilePreview` is a local, portal-based File viewer. It displays the current file count in its backdrop header, supports buttons and ArrowLeft/ArrowRight navigation, calls `onEscape` then `onClose('escape')`, and reports `onDelete`/`onDownload` with the active `File`. Its Download action starts a direct local browser download—there is no endpoint or transport behavior.
198
203
  - `Tooltip` shows accessible content on hover and focus.
199
204
  - `ExpandableSection` provides controlled and uncontrolled expand/collapse behavior.
200
205
  - `TextInput` and `TextArea` support `error`/`errorMessage`, `helperText`, `clearable`, `onClear`, and `onValueChange`. `TextArea` also accepts `autosize` (default `false`) to grow with its content. `TextInput` also accepts `label`, `isRequired`, and `prefix`/`suffix` adornments. Passing a string to `error` shows it below the field and applies the error border.
201
- - `Modal` is a centered portal dialog in `small`, `medium`, `large`, `xlarge`, and `full` sizes. Its close control and `actions` are library `Button` instances.
206
+ - `EmailInput`, `PasswordInput`, and `PhoneNumberInput` add their standard mailbox, show/hide password, and phone adornments. They validate their formats on blur by default; use `validateOn="change"` for immediate feedback and `validate={(value) => ...}` for an additional rule. Passwords require at least eight characters including uppercase, lowercase, and a number; phone numbers accept digits, spaces, parentheses, and plus signs, and require 7–15 digits.
207
+ - `Modal` is a centered portal dialog in `small`, `medium`, `large`, `xlarge`, and `full` sizes. Its close control and `actions` are library `Button` instances. Modal and Drawer trap keyboard focus, lock background scrolling, return focus to their opener, and respect reduced-motion preferences. Use `initialFocusRef`, `restoreFocus`, `closeOnEscape`, and `closeOnBackdropClick` to customize that behavior.
202
208
  - `Loading` provides `small`, `medium`, and `large` circular indicators (or a custom pixel `size`); use `Skeleton.Circle` and `Skeleton.Square` with `size`, or `Skeleton.Box` and `Skeleton.Line` with `width` and `height`.
203
209
  - `ProgressBar` is determinate when `value` is supplied and renders an indeterminate back-and-forth animation when it is omitted.
204
210
  - `Chip` supports the standard `default`, `success`, `error`, `info`, and `warning` palettes, plus `color` for any CSS color and `subtle`, `solid`, or `outline` variants.
@@ -219,6 +225,17 @@ The library exposes ESM, CommonJS, TypeScript declarations, and keeps React as a
219
225
  clearable
220
226
  />
221
227
 
228
+ <EmailInput
229
+ label="Work email"
230
+ value={email}
231
+ onValueChange={setEmail}
232
+ validate={(value) =>
233
+ value.endsWith('@dragunio.com') || 'Use your work email.'
234
+ }
235
+ />
236
+ <PasswordInput label="Password" />
237
+ <PhoneNumberInput label="Phone number" placeholder="+84 (123) 456 789" />
238
+
222
239
  <ProgressBar label="Upload" value={72} />
223
240
  <ProgressBar label="Synchronising" />
224
241
  <Chip status="success" dot>Complete</Chip>
@@ -169,6 +169,82 @@ function SearchIcon(props) {
169
169
  )
170
170
  ] });
171
171
  }
172
+ function MailboxIcon(props) {
173
+ return /* @__PURE__ */ jsxs("svg", { ...iconProps4(props), children: [
174
+ /* @__PURE__ */ jsx4(
175
+ "rect",
176
+ {
177
+ x: "3.5",
178
+ y: "5.5",
179
+ width: "17",
180
+ height: "13",
181
+ rx: "2",
182
+ stroke: "currentColor",
183
+ strokeWidth: "1.8"
184
+ }
185
+ ),
186
+ /* @__PURE__ */ jsx4(
187
+ "path",
188
+ {
189
+ d: "m4.5 7 6.04 4.53a2.4 2.4 0 0 0 2.92 0L19.5 7",
190
+ stroke: "currentColor",
191
+ strokeWidth: "1.8",
192
+ strokeLinecap: "round",
193
+ strokeLinejoin: "round"
194
+ }
195
+ )
196
+ ] });
197
+ }
198
+ function PhoneIcon(props) {
199
+ return /* @__PURE__ */ jsx4("svg", { ...iconProps4(props), children: /* @__PURE__ */ jsx4(
200
+ "path",
201
+ {
202
+ d: "M8.05 3.75 5.84 4.8c-.76.36-1.15 1.2-.94 2.02 1.55 6.14 6.34 10.93 12.48 12.48.82.21 1.66-.18 2.02-.94l1.05-2.21a1.5 1.5 0 0 0-.57-1.91l-2.41-1.48a1.5 1.5 0 0 0-1.8.18l-1.23 1.06a10.38 10.38 0 0 1-4.45-4.45l1.06-1.23a1.5 1.5 0 0 0 .18-1.8L9.96 4.32a1.5 1.5 0 0 0-1.91-.57Z",
203
+ stroke: "currentColor",
204
+ strokeWidth: "1.8",
205
+ strokeLinecap: "round",
206
+ strokeLinejoin: "round"
207
+ }
208
+ ) });
209
+ }
210
+ function EyeIcon(props) {
211
+ return /* @__PURE__ */ jsxs("svg", { ...iconProps4(props), children: [
212
+ /* @__PURE__ */ jsx4(
213
+ "path",
214
+ {
215
+ d: "M2.9 12s3.1-5 9.1-5 9.1 5 9.1 5-3.1 5-9.1 5-9.1-5-9.1-5Z",
216
+ stroke: "currentColor",
217
+ strokeWidth: "1.8",
218
+ strokeLinecap: "round",
219
+ strokeLinejoin: "round"
220
+ }
221
+ ),
222
+ /* @__PURE__ */ jsx4("circle", { cx: "12", cy: "12", r: "2.4", stroke: "currentColor", strokeWidth: "1.8" })
223
+ ] });
224
+ }
225
+ function EyeOffIcon(props) {
226
+ return /* @__PURE__ */ jsxs("svg", { ...iconProps4(props), children: [
227
+ /* @__PURE__ */ jsx4(
228
+ "path",
229
+ {
230
+ d: "M10.58 7.16A6.1 6.1 0 0 1 12 7c6 0 9.1 5 9.1 5a16.1 16.1 0 0 1-2.54 2.84M13.28 16.83A6.1 6.1 0 0 1 12 17c-6 0-9.1-5-9.1-5a16.1 16.1 0 0 1 2.59-2.87",
231
+ stroke: "currentColor",
232
+ strokeWidth: "1.8",
233
+ strokeLinecap: "round",
234
+ strokeLinejoin: "round"
235
+ }
236
+ ),
237
+ /* @__PURE__ */ jsx4(
238
+ "path",
239
+ {
240
+ d: "m3.5 3.5 17 17M10.1 10.1a2.7 2.7 0 0 0 3.8 3.8",
241
+ stroke: "currentColor",
242
+ strokeWidth: "1.8",
243
+ strokeLinecap: "round"
244
+ }
245
+ )
246
+ ] });
247
+ }
172
248
 
173
249
  export {
174
250
  plus,
@@ -194,5 +270,9 @@ export {
194
270
  CloseIcon,
195
271
  MoreHorizontalIcon,
196
272
  MoreVerticalIcon,
197
- SearchIcon
273
+ SearchIcon,
274
+ MailboxIcon,
275
+ PhoneIcon,
276
+ EyeIcon,
277
+ EyeOffIcon
198
278
  };
package/dist/icons.d.mts CHANGED
@@ -31,5 +31,9 @@ declare function CloseIcon(props: IconProps): react.JSX.Element;
31
31
  declare function MoreHorizontalIcon(props: IconProps): react.JSX.Element;
32
32
  declare function MoreVerticalIcon(props: IconProps): react.JSX.Element;
33
33
  declare function SearchIcon(props: IconProps): react.JSX.Element;
34
+ declare function MailboxIcon(props: IconProps): react.JSX.Element;
35
+ declare function PhoneIcon(props: IconProps): react.JSX.Element;
36
+ declare function EyeIcon(props: IconProps): react.JSX.Element;
37
+ declare function EyeOffIcon(props: IconProps): react.JSX.Element;
34
38
 
35
- export { ChevronDownIcon, ChevronUpIcon, CloseIcon, type IconProps, MoreHorizontalIcon, MoreVerticalIcon, PlusIcon, SearchIcon, arrow_left, check_square_fill, chevron_down, chevron_left, chevron_right, chevron_up, copy, key, lock, lock_unlocked, log_out, minus_square, plus, plus_square, search, trash, x_close };
39
+ export { ChevronDownIcon, ChevronUpIcon, CloseIcon, EyeIcon, EyeOffIcon, type IconProps, MailboxIcon, MoreHorizontalIcon, MoreVerticalIcon, PhoneIcon, PlusIcon, SearchIcon, arrow_left, check_square_fill, chevron_down, chevron_left, chevron_right, chevron_up, copy, key, lock, lock_unlocked, log_out, minus_square, plus, plus_square, search, trash, x_close };
package/dist/icons.d.ts CHANGED
@@ -31,5 +31,9 @@ declare function CloseIcon(props: IconProps): react.JSX.Element;
31
31
  declare function MoreHorizontalIcon(props: IconProps): react.JSX.Element;
32
32
  declare function MoreVerticalIcon(props: IconProps): react.JSX.Element;
33
33
  declare function SearchIcon(props: IconProps): react.JSX.Element;
34
+ declare function MailboxIcon(props: IconProps): react.JSX.Element;
35
+ declare function PhoneIcon(props: IconProps): react.JSX.Element;
36
+ declare function EyeIcon(props: IconProps): react.JSX.Element;
37
+ declare function EyeOffIcon(props: IconProps): react.JSX.Element;
34
38
 
35
- export { ChevronDownIcon, ChevronUpIcon, CloseIcon, type IconProps, MoreHorizontalIcon, MoreVerticalIcon, PlusIcon, SearchIcon, arrow_left, check_square_fill, chevron_down, chevron_left, chevron_right, chevron_up, copy, key, lock, lock_unlocked, log_out, minus_square, plus, plus_square, search, trash, x_close };
39
+ export { ChevronDownIcon, ChevronUpIcon, CloseIcon, EyeIcon, EyeOffIcon, type IconProps, MailboxIcon, MoreHorizontalIcon, MoreVerticalIcon, PhoneIcon, PlusIcon, SearchIcon, arrow_left, check_square_fill, chevron_down, chevron_left, chevron_right, chevron_up, copy, key, lock, lock_unlocked, log_out, minus_square, plus, plus_square, search, trash, x_close };
package/dist/icons.js CHANGED
@@ -23,8 +23,12 @@ __export(icons_exports, {
23
23
  ChevronDownIcon: () => ChevronDownIcon,
24
24
  ChevronUpIcon: () => ChevronUpIcon,
25
25
  CloseIcon: () => CloseIcon,
26
+ EyeIcon: () => EyeIcon,
27
+ EyeOffIcon: () => EyeOffIcon,
28
+ MailboxIcon: () => MailboxIcon,
26
29
  MoreHorizontalIcon: () => MoreHorizontalIcon,
27
30
  MoreVerticalIcon: () => MoreVerticalIcon,
31
+ PhoneIcon: () => PhoneIcon,
28
32
  PlusIcon: () => PlusIcon,
29
33
  SearchIcon: () => SearchIcon,
30
34
  arrow_left: () => arrow_left,
@@ -218,13 +222,93 @@ function SearchIcon(props) {
218
222
  )
219
223
  ] });
220
224
  }
225
+ function MailboxIcon(props) {
226
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { ...iconProps4(props), children: [
227
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
228
+ "rect",
229
+ {
230
+ x: "3.5",
231
+ y: "5.5",
232
+ width: "17",
233
+ height: "13",
234
+ rx: "2",
235
+ stroke: "currentColor",
236
+ strokeWidth: "1.8"
237
+ }
238
+ ),
239
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
240
+ "path",
241
+ {
242
+ d: "m4.5 7 6.04 4.53a2.4 2.4 0 0 0 2.92 0L19.5 7",
243
+ stroke: "currentColor",
244
+ strokeWidth: "1.8",
245
+ strokeLinecap: "round",
246
+ strokeLinejoin: "round"
247
+ }
248
+ )
249
+ ] });
250
+ }
251
+ function PhoneIcon(props) {
252
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { ...iconProps4(props), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
253
+ "path",
254
+ {
255
+ d: "M8.05 3.75 5.84 4.8c-.76.36-1.15 1.2-.94 2.02 1.55 6.14 6.34 10.93 12.48 12.48.82.21 1.66-.18 2.02-.94l1.05-2.21a1.5 1.5 0 0 0-.57-1.91l-2.41-1.48a1.5 1.5 0 0 0-1.8.18l-1.23 1.06a10.38 10.38 0 0 1-4.45-4.45l1.06-1.23a1.5 1.5 0 0 0 .18-1.8L9.96 4.32a1.5 1.5 0 0 0-1.91-.57Z",
256
+ stroke: "currentColor",
257
+ strokeWidth: "1.8",
258
+ strokeLinecap: "round",
259
+ strokeLinejoin: "round"
260
+ }
261
+ ) });
262
+ }
263
+ function EyeIcon(props) {
264
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { ...iconProps4(props), children: [
265
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
266
+ "path",
267
+ {
268
+ d: "M2.9 12s3.1-5 9.1-5 9.1 5 9.1 5-3.1 5-9.1 5-9.1-5-9.1-5Z",
269
+ stroke: "currentColor",
270
+ strokeWidth: "1.8",
271
+ strokeLinecap: "round",
272
+ strokeLinejoin: "round"
273
+ }
274
+ ),
275
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "12", cy: "12", r: "2.4", stroke: "currentColor", strokeWidth: "1.8" })
276
+ ] });
277
+ }
278
+ function EyeOffIcon(props) {
279
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { ...iconProps4(props), children: [
280
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
281
+ "path",
282
+ {
283
+ d: "M10.58 7.16A6.1 6.1 0 0 1 12 7c6 0 9.1 5 9.1 5a16.1 16.1 0 0 1-2.54 2.84M13.28 16.83A6.1 6.1 0 0 1 12 17c-6 0-9.1-5-9.1-5a16.1 16.1 0 0 1 2.59-2.87",
284
+ stroke: "currentColor",
285
+ strokeWidth: "1.8",
286
+ strokeLinecap: "round",
287
+ strokeLinejoin: "round"
288
+ }
289
+ ),
290
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
291
+ "path",
292
+ {
293
+ d: "m3.5 3.5 17 17M10.1 10.1a2.7 2.7 0 0 0 3.8 3.8",
294
+ stroke: "currentColor",
295
+ strokeWidth: "1.8",
296
+ strokeLinecap: "round"
297
+ }
298
+ )
299
+ ] });
300
+ }
221
301
  // Annotate the CommonJS export names for ESM import in node:
222
302
  0 && (module.exports = {
223
303
  ChevronDownIcon,
224
304
  ChevronUpIcon,
225
305
  CloseIcon,
306
+ EyeIcon,
307
+ EyeOffIcon,
308
+ MailboxIcon,
226
309
  MoreHorizontalIcon,
227
310
  MoreVerticalIcon,
311
+ PhoneIcon,
228
312
  PlusIcon,
229
313
  SearchIcon,
230
314
  arrow_left,
package/dist/icons.mjs CHANGED
@@ -2,8 +2,12 @@ import {
2
2
  ChevronDownIcon,
3
3
  ChevronUpIcon,
4
4
  CloseIcon,
5
+ EyeIcon,
6
+ EyeOffIcon,
7
+ MailboxIcon,
5
8
  MoreHorizontalIcon,
6
9
  MoreVerticalIcon,
10
+ PhoneIcon,
7
11
  PlusIcon,
8
12
  SearchIcon,
9
13
  arrow_left,
@@ -23,13 +27,17 @@ import {
23
27
  search,
24
28
  trash,
25
29
  x_close
26
- } from "./chunk-HM3V3DVO.mjs";
30
+ } from "./chunk-BAZJ5UJ5.mjs";
27
31
  export {
28
32
  ChevronDownIcon,
29
33
  ChevronUpIcon,
30
34
  CloseIcon,
35
+ EyeIcon,
36
+ EyeOffIcon,
37
+ MailboxIcon,
31
38
  MoreHorizontalIcon,
32
39
  MoreVerticalIcon,
40
+ PhoneIcon,
33
41
  PlusIcon,
34
42
  SearchIcon,
35
43
  arrow_left,
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react from 'react';
2
- import { ButtonHTMLAttributes, ReactNode, HTMLAttributes, MouseEvent, KeyboardEvent, TableHTMLAttributes, InputHTMLAttributes, TextareaHTMLAttributes, KeyboardEventHandler, ChangeEvent, ReactElement } from 'react';
3
- export { ChevronDownIcon, ChevronUpIcon, CloseIcon, IconProps, MoreHorizontalIcon, MoreVerticalIcon, PlusIcon, SearchIcon, arrow_left, check_square_fill, chevron_down, chevron_left, chevron_right, chevron_up, copy, key, lock, lock_unlocked, log_out, minus_square, plus, plus_square, search, trash, x_close } from './icons.mjs';
2
+ import { ButtonHTMLAttributes, ReactNode, HTMLAttributes, MouseEvent, KeyboardEvent, TableHTMLAttributes, InputHTMLAttributes, RefObject, TextareaHTMLAttributes, KeyboardEventHandler, ChangeEvent, ReactElement } from 'react';
3
+ export { ChevronDownIcon, ChevronUpIcon, CloseIcon, EyeIcon, EyeOffIcon, IconProps, MailboxIcon, MoreHorizontalIcon, MoreVerticalIcon, PhoneIcon, PlusIcon, SearchIcon, arrow_left, check_square_fill, chevron_down, chevron_left, chevron_right, chevron_up, copy, key, lock, lock_unlocked, log_out, minus_square, plus, plus_square, search, trash, x_close } from './icons.mjs';
4
4
 
5
5
  type ButtonHierarchy = 'primary' | 'secondary-gray' | 'secondary-color' | 'tertiary-gray' | 'tertiary-color';
6
6
  type ButtonSize = '24' | '32' | '40';
@@ -183,22 +183,39 @@ declare const Toggle: react.ForwardRefExoticComponent<Omit<InputHTMLAttributes<H
183
183
  labelPosition?: "top" | "right";
184
184
  } & react.RefAttributes<HTMLInputElement>>;
185
185
 
186
+ type DrawerSide = 'left' | 'right' | 'top' | 'bottom';
187
+ /** Named width presets for left and right drawers. */
188
+ declare const DrawerWidths: {
189
+ readonly small: 360;
190
+ readonly medium: 400;
191
+ readonly large: 480;
192
+ };
193
+ type DrawerWidthPreset = (typeof DrawerWidths)[keyof typeof DrawerWidths];
194
+ type DrawerWidth = DrawerWidthPreset | number | string;
186
195
  type DrawerProps = Omit<HTMLAttributes<HTMLElement>, 'title'> & {
187
196
  open: boolean;
188
197
  onClose: () => void;
189
198
  title?: ReactNode;
199
+ description?: ReactNode;
190
200
  /** Optional content pinned below the scrollable body. */
191
201
  footer?: ReactNode;
192
- side?: 'left' | 'right' | 'top' | 'bottom';
193
- /** Width of a left/right drawer. Defaults to 400px. */
194
- width?: number | string;
202
+ side?: DrawerSide;
203
+ /** Width of a left/right drawer. Use DrawerWidths presets or any CSS width. Defaults to DrawerWidths.medium (400px). */
204
+ width?: DrawerWidth;
195
205
  /** Makes the panel fill the entire viewport while retaining the chosen entrance direction. */
196
206
  fullScreen?: boolean;
197
207
  children?: ReactNode;
198
208
  closeOnBackdropClick?: boolean;
209
+ /** Allows Escape to request closing the drawer. Defaults to true. */
210
+ closeOnEscape?: boolean;
211
+ closeLabel?: string;
212
+ /** Element that receives focus when the drawer opens. The dialog itself is focused by default. */
213
+ initialFocusRef?: RefObject<HTMLElement | null>;
214
+ /** Restores focus to the opener after closing. Defaults to true. */
215
+ restoreFocus?: boolean;
199
216
  };
200
217
  /** A modal panel with fixed header/footer regions and a scrollable body. */
201
- declare function Drawer({ open, onClose, title, footer, side, width, fullScreen, children, closeOnBackdropClick, className, style, ...props }: DrawerProps): react.ReactPortal | null;
218
+ declare function Drawer({ open, onClose, title, description, footer, side, width, fullScreen, children, closeOnBackdropClick, closeOnEscape, closeLabel, initialFocusRef, restoreFocus, className, style, 'aria-label': ariaLabel, 'aria-describedby': ariaDescribedBy, ...props }: DrawerProps): react.ReactPortal | null;
202
219
 
203
220
  type FieldError = boolean | ReactNode;
204
221
  type DescriptionDisplay = 'inline' | 'tooltip';
@@ -251,6 +268,63 @@ type TextInputProps = Omit<InputHTMLAttributes<HTMLInputElement>, 'size' | 'valu
251
268
  Suffix?: ReactNode;
252
269
  };
253
270
 
271
+ /**
272
+ * Return a message (or `false`) to mark a value invalid. Return `undefined`,
273
+ * `null`, or `true` when the value is valid.
274
+ */
275
+ type InputValidator = (value: string) => string | boolean | null | undefined;
276
+ type ValidationTiming = 'blur' | 'change';
277
+ /** Shared public props for inputs with built-in format validation. */
278
+ type ValidatedTextInputProps = Omit<TextInputProps, 'type' | 'prefix' | 'suffix' | 'Prefix' | 'Suffix'> & {
279
+ /**
280
+ * Extra validation run after the built-in format check. Return an error
281
+ * message (or `false`) when invalid.
282
+ */
283
+ validate?: InputValidator;
284
+ /** When validation runs. It runs on blur by default. */
285
+ validateOn?: ValidationTiming;
286
+ };
287
+
288
+ declare function validateEmail(value: string, required?: boolean): string | undefined;
289
+ declare function validatePassword(value: string, required?: boolean): string | undefined;
290
+ declare function validatePhoneNumber(value: string, required?: boolean): string | undefined;
291
+ declare function normalizePhoneNumber(value: string): string;
292
+
293
+ /** An email field with a mailbox prefix and built-in format validation. */
294
+ declare const EmailInput: react.ForwardRefExoticComponent<Omit<TextInputProps, "prefix" | "type" | "suffix" | "Prefix" | "Suffix"> & {
295
+ validate?: InputValidator;
296
+ validateOn?: ValidationTiming;
297
+ } & react.RefAttributes<HTMLInputElement>>;
298
+
299
+ type EmailInputProps = ValidatedTextInputProps;
300
+
301
+ /** A password field with reveal/hide control and built-in strength validation. */
302
+ declare const PasswordInput: react.ForwardRefExoticComponent<Omit<TextInputProps, "prefix" | "type" | "suffix" | "Prefix" | "Suffix"> & {
303
+ validate?: InputValidator;
304
+ validateOn?: ValidationTiming;
305
+ } & {
306
+ showPasswordLabel?: string;
307
+ hidePasswordLabel?: string;
308
+ } & react.RefAttributes<HTMLInputElement>>;
309
+
310
+ type PasswordInputProps = ValidatedTextInputProps & {
311
+ /** Accessible label for the control that reveals the password. */
312
+ showPasswordLabel?: string;
313
+ /** Accessible label for the control that hides the password. */
314
+ hidePasswordLabel?: string;
315
+ };
316
+
317
+ /**
318
+ * A phone field that accepts digits, spaces, parentheses, and plus signs,
319
+ * with built-in digit-count validation.
320
+ */
321
+ declare const PhoneNumberInput: react.ForwardRefExoticComponent<Omit<TextInputProps, "prefix" | "type" | "suffix" | "Prefix" | "Suffix"> & {
322
+ validate?: InputValidator;
323
+ validateOn?: ValidationTiming;
324
+ } & react.RefAttributes<HTMLInputElement>>;
325
+
326
+ type PhoneNumberInputProps = ValidatedTextInputProps;
327
+
254
328
  /** A multi-line text field with helper/error text and a Button-powered clear action. */
255
329
  declare const TextArea: react.ForwardRefExoticComponent<Omit<react.TextareaHTMLAttributes<HTMLTextAreaElement>, "value" | "defaultValue"> & FieldBaseProps & {
256
330
  clearable?: boolean;
@@ -571,11 +645,17 @@ type ModalProps = Omit<HTMLAttributes<HTMLDivElement>, 'title'> & {
571
645
  actions?: ModalAction[];
572
646
  size?: ModalSize;
573
647
  closeOnBackdropClick?: boolean;
648
+ /** Allows Escape to request closing the modal. Defaults to true. */
649
+ closeOnEscape?: boolean;
574
650
  closeButton?: boolean;
575
651
  closeLabel?: string;
652
+ /** Element that receives focus when the modal opens. The dialog itself is focused by default. */
653
+ initialFocusRef?: RefObject<HTMLElement | null>;
654
+ /** Restores focus to the opener after closing. Defaults to true. */
655
+ restoreFocus?: boolean;
576
656
  };
577
657
  /** A centered, portal-based dialog with Button-powered close and footer actions. */
578
- declare function Modal({ open, onClose, title, description, children, footer, actions, size, closeOnBackdropClick, closeButton, closeLabel, className, ...props }: ModalProps): react.ReactPortal | null;
658
+ declare function Modal({ open, onClose, title, description, children, footer, actions, size, closeOnBackdropClick, closeOnEscape, closeButton, closeLabel, initialFocusRef, restoreFocus, className, 'aria-label': ariaLabel, 'aria-describedby': ariaDescribedBy, ...props }: ModalProps): react.ReactPortal | null;
579
659
 
580
660
  type ProgressBarSize = 'small' | 'medium' | 'large';
581
661
  type ProgressBarProps = HTMLAttributes<HTMLDivElement> & {
@@ -718,4 +798,143 @@ declare function Avatar({ src, content, alt, size, shape, fallbackIndex, classNa
718
798
  */
719
799
  declare function AvatarGroup({ children, maxCount, className, style, role, ...props }: AvatarGroupProps): react.JSX.Element;
720
800
 
721
- export { Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, type AvatarShape, type AvatarSize, Button, ButtonBar, type ButtonBarAction, type ButtonBarItem, type ButtonBarProps, type ButtonColor, type ButtonHierarchy, type ButtonProps, type ButtonSize, type ButtonVariant, Checkbox, type CheckboxProps, Chip, type ChipProps, type ChipStatus, type ChipVariant, type ColumnResizeHandler, type ControlLabelPosition, type Currency, CurrencyInput, type CurrencyInputProps, type DateRange, DateTimePicker, type DateTimePickerProps, type DateTimePickerRangeProps, type DateTimePickerSingleProps, type DescriptionDisplay, Drawer, type DrawerProps, ExpandableSection, type ExpandableSectionProps, type FieldError, Loading, type LoadingProps, type LoadingSize, Message, type MessageOptions, type MessageProps, type MessageSeverity, Modal, type ModalAction, type ModalProps, type ModalSize, NumberInput, type NumberInputProps, Pagination, type PaginationProps, ProgressBar, type ProgressBarProps, type ProgressBarSize, RadioButton, type RadioButtonProps, RadioGroup, type RadioGroupOption, type RadioGroupProps, type RadioValue, Selection, type SelectionOption, type SelectionProps, type SelectionValue, Skeleton, SkeletonBox, type SkeletonBoxProps, SkeletonCircle, SkeletonLine, type SkeletonProps, type SkeletonSizeProps, SkeletonSquare, type SkeletonVariant, Snackbar, type SnackbarAnchorOrigin, type SnackbarProps, type TabChangeEvent, type TabItem, Table, TableBody, TableCaption, TableCell, type TableData, TableHead, TableHeader, type TablePaginationPosition, type TableProps, TableRow, Tabs, type TabsProps, type TabsScrollButtons, type TabsVariant, TextArea, type TextAreaProps, TextInput, type TextInputProps, Toggle, type ToggleProps, Tooltip, type TooltipProps, formatNumber, getIconSize, message };
801
+ type FileUploadRejectionCode = 'accept' | 'max-files' | 'max-size' | 'duplicate';
802
+ type FileUploadRejection = {
803
+ file: File;
804
+ code: FileUploadRejectionCode;
805
+ message: string;
806
+ };
807
+ /**
808
+ * Predefined file groups that FileUpload maps to native accept patterns and
809
+ * validates locally. Use `all` to leave the file picker unrestricted.
810
+ */
811
+ declare const FILE_UPLOAD_ACCEPTS: {
812
+ readonly all: readonly [];
813
+ readonly image: readonly ["image/*", ".avif", ".bmp", ".gif", ".heic", ".heif", ".ico", ".jpeg", ".jpg", ".png", ".svg", ".tif", ".tiff", ".webp"];
814
+ readonly pdf: readonly [".pdf"];
815
+ readonly word: readonly [".doc", ".docm", ".docx", ".dot", ".dotx", ".odt", ".rtf"];
816
+ readonly spreadsheet: readonly [".csv", ".ods", ".xls", ".xlsb", ".xlsm", ".xlsx"];
817
+ readonly presentation: readonly [".odp", ".pot", ".potx", ".pps", ".ppsx", ".ppt", ".pptx"];
818
+ readonly document: readonly [".pdf", ".doc", ".docm", ".docx", ".dot", ".dotx", ".odt", ".rtf", ".csv", ".xls", ".xlsb", ".xlsx", ".xlsm", ".ods", ".pot", ".potx", ".pps", ".ppsx", ".ppt", ".pptx", ".odp"];
819
+ readonly text: readonly [".log", ".md", ".rtf", ".text", ".txt"];
820
+ readonly csv: readonly [".csv"];
821
+ readonly json: readonly [".json"];
822
+ readonly xml: readonly [".xml"];
823
+ readonly code: readonly [".c", ".cpp", ".cs", ".css", ".go", ".html", ".java", ".js", ".jsx", ".php", ".py", ".rb", ".rs", ".scss", ".sh", ".sql", ".swift", ".ts", ".tsx", ".vue", ".yml", ".yaml"];
824
+ readonly archive: readonly [".7z", ".bz2", ".gz", ".rar", ".tar", ".tgz", ".xz", ".zip"];
825
+ readonly audio: readonly ["audio/*", ".aac", ".aiff", ".flac", ".m4a", ".mp3", ".ogg", ".opus", ".wav", ".wma"];
826
+ readonly video: readonly ["video/*", ".avi", ".mkv", ".mov", ".mp4", ".mpeg", ".mpg", ".webm", ".wmv"];
827
+ readonly font: readonly [".ttf", ".otf", ".woff", ".woff2"];
828
+ readonly email: readonly [".eml", ".msg"];
829
+ };
830
+ /** A predefined FileUpload group name. */
831
+ type FileUploadFileType = keyof typeof FILE_UPLOAD_ACCEPTS;
832
+ /** One or more predefined FileUpload file groups. */
833
+ type FileUploadAccept = FileUploadFileType | readonly FileUploadFileType[];
834
+ type FileUploadProps = Omit<HTMLAttributes<HTMLDivElement>, 'children' | 'onChange'> & {
835
+ /** Controlled files currently shown by the component. */
836
+ value?: readonly File[];
837
+ /** Initial files for uncontrolled use. */
838
+ defaultValue?: readonly File[];
839
+ /** Called synchronously whenever the accepted file list changes. */
840
+ onChange?: (files: File[]) => void;
841
+ /** Called with only the files accepted during one selection or drop. */
842
+ onAccept?: (files: File[]) => void;
843
+ /** Called with validation failures; no upload or API request is made. */
844
+ onReject?: (rejections: FileUploadRejection[]) => void;
845
+ /** Called before a file is removed from the list. */
846
+ onRemove?: (file: File, index: number) => void;
847
+ /** Predefined file group(s) used to select and validate files. */
848
+ accept?: FileUploadAccept;
849
+ /** Maximum bytes allowed for one file. Defaults to no limit. */
850
+ maxSize?: number;
851
+ /** Maximum files in the list. Defaults to no limit. */
852
+ maxFiles?: number;
853
+ multiple?: boolean;
854
+ disabled?: boolean;
855
+ /** Rejects files with the same name, size, and last-modified timestamp. */
856
+ preventDuplicate?: boolean;
857
+ label?: ReactNode;
858
+ description?: ReactNode;
859
+ dropLabel?: ReactNode;
860
+ browseLabel?: ReactNode;
861
+ removeLabel?: (file: File) => string;
862
+ /** Shows local image previews and file metadata below the drop zone. */
863
+ showFileList?: boolean;
864
+ inputProps?: Omit<InputHTMLAttributes<HTMLInputElement>, 'accept' | 'disabled' | 'multiple' | 'onChange' | 'type' | 'value'>;
865
+ };
866
+ declare function formatFileSize(bytes: number): string;
867
+ /**
868
+ * A local file picker and drop zone. It validates and emits browser File
869
+ * objects only; callers own all persistence, uploads, progress, and API work.
870
+ */
871
+ declare const FileUpload: react.ForwardRefExoticComponent<Omit<HTMLAttributes<HTMLDivElement>, "children" | "onChange"> & {
872
+ /** Controlled files currently shown by the component. */
873
+ value?: readonly File[];
874
+ /** Initial files for uncontrolled use. */
875
+ defaultValue?: readonly File[];
876
+ /** Called synchronously whenever the accepted file list changes. */
877
+ onChange?: (files: File[]) => void;
878
+ /** Called with only the files accepted during one selection or drop. */
879
+ onAccept?: (files: File[]) => void;
880
+ /** Called with validation failures; no upload or API request is made. */
881
+ onReject?: (rejections: FileUploadRejection[]) => void;
882
+ /** Called before a file is removed from the list. */
883
+ onRemove?: (file: File, index: number) => void;
884
+ /** Predefined file group(s) used to select and validate files. */
885
+ accept?: FileUploadAccept;
886
+ /** Maximum bytes allowed for one file. Defaults to no limit. */
887
+ maxSize?: number;
888
+ /** Maximum files in the list. Defaults to no limit. */
889
+ maxFiles?: number;
890
+ multiple?: boolean;
891
+ disabled?: boolean;
892
+ /** Rejects files with the same name, size, and last-modified timestamp. */
893
+ preventDuplicate?: boolean;
894
+ label?: ReactNode;
895
+ description?: ReactNode;
896
+ dropLabel?: ReactNode;
897
+ browseLabel?: ReactNode;
898
+ removeLabel?: (file: File) => string;
899
+ /** Shows local image previews and file metadata below the drop zone. */
900
+ showFileList?: boolean;
901
+ inputProps?: Omit<InputHTMLAttributes<HTMLInputElement>, "accept" | "disabled" | "multiple" | "onChange" | "type" | "value">;
902
+ } & react.RefAttributes<HTMLInputElement>>;
903
+
904
+ type FilePreviewKind = 'audio' | 'image' | 'pdf' | 'unsupported' | 'video';
905
+ type FilePreviewCloseReason = 'backdrop' | 'close' | 'escape';
906
+ type FilePreviewActionHandler = (file: File, index: number) => void;
907
+ type FilePreviewProps = Omit<HTMLAttributes<HTMLDivElement>, 'children' | 'onChange' | 'onClose'> & {
908
+ open: boolean;
909
+ files: readonly File[];
910
+ /** Controlled zero-based index of the file currently shown. */
911
+ activeIndex?: number;
912
+ /** Initial zero-based file index for uncontrolled use. */
913
+ defaultActiveIndex?: number;
914
+ /** Called after a previous/next control or Arrow key changes the active file. */
915
+ onActiveIndexChange?: (index: number, file: File) => void;
916
+ /** Called when the preview requests closing, including the reason. */
917
+ onClose: (reason: FilePreviewCloseReason) => void;
918
+ /** Called immediately before `onClose('escape')`. */
919
+ onEscape?: () => void;
920
+ /** Called when the Delete action is pressed. The owner removes files. */
921
+ onDelete?: FilePreviewActionHandler;
922
+ /** Called when the Download action is pressed, before the local browser download starts. */
923
+ onDownload?: FilePreviewActionHandler;
924
+ closeOnBackdropClick?: boolean;
925
+ closeOnEscape?: boolean;
926
+ closeLabel?: string;
927
+ downloadLabel?: ReactNode;
928
+ deleteLabel?: ReactNode;
929
+ /** Hides the local browser Download action. Defaults to false. */
930
+ hideDownload?: boolean;
931
+ };
932
+ /** Identifies browser-native previews supported by FilePreview. */
933
+ declare function getFilePreviewKind(file: File): FilePreviewKind;
934
+ /**
935
+ * A local File viewer with click and keyboard navigation. It makes no network
936
+ * request: deletion and download notifications always carry the active File.
937
+ */
938
+ declare function FilePreview({ open, files, activeIndex, defaultActiveIndex, onActiveIndexChange, onClose, onEscape, onDelete, onDownload, closeOnBackdropClick, closeOnEscape, closeLabel, downloadLabel, deleteLabel, hideDownload, className, 'aria-label': ariaLabel, ...props }: FilePreviewProps): react.ReactPortal | null;
939
+
940
+ export { Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, type AvatarShape, type AvatarSize, Button, ButtonBar, type ButtonBarAction, type ButtonBarItem, type ButtonBarProps, type ButtonColor, type ButtonHierarchy, type ButtonProps, type ButtonSize, type ButtonVariant, Checkbox, type CheckboxProps, Chip, type ChipProps, type ChipStatus, type ChipVariant, type ColumnResizeHandler, type ControlLabelPosition, type Currency, CurrencyInput, type CurrencyInputProps, type DateRange, DateTimePicker, type DateTimePickerProps, type DateTimePickerRangeProps, type DateTimePickerSingleProps, type DescriptionDisplay, Drawer, type DrawerProps, type DrawerSide, type DrawerWidth, type DrawerWidthPreset, DrawerWidths, EmailInput, type EmailInputProps, ExpandableSection, type ExpandableSectionProps, FILE_UPLOAD_ACCEPTS, type FieldError, FilePreview, type FilePreviewActionHandler, type FilePreviewCloseReason, type FilePreviewKind, type FilePreviewProps, FileUpload, type FileUploadAccept, type FileUploadFileType, type FileUploadProps, type FileUploadRejection, type FileUploadRejectionCode, type InputValidator, Loading, type LoadingProps, type LoadingSize, Message, type MessageOptions, type MessageProps, type MessageSeverity, Modal, type ModalAction, type ModalProps, type ModalSize, NumberInput, type NumberInputProps, Pagination, type PaginationProps, PasswordInput, type PasswordInputProps, PhoneNumberInput, type PhoneNumberInputProps, ProgressBar, type ProgressBarProps, type ProgressBarSize, RadioButton, type RadioButtonProps, RadioGroup, type RadioGroupOption, type RadioGroupProps, type RadioValue, Selection, type SelectionOption, type SelectionProps, type SelectionValue, Skeleton, SkeletonBox, type SkeletonBoxProps, SkeletonCircle, SkeletonLine, type SkeletonProps, type SkeletonSizeProps, SkeletonSquare, type SkeletonVariant, Snackbar, type SnackbarAnchorOrigin, type SnackbarProps, type TabChangeEvent, type TabItem, Table, TableBody, TableCaption, TableCell, type TableData, TableHead, TableHeader, type TablePaginationPosition, type TableProps, TableRow, Tabs, type TabsProps, type TabsScrollButtons, type TabsVariant, TextArea, type TextAreaProps, TextInput, type TextInputProps, Toggle, type ToggleProps, Tooltip, type TooltipProps, type ValidatedTextInputProps, type ValidationTiming, formatFileSize, formatNumber, getFilePreviewKind, getIconSize, message, normalizePhoneNumber, validateEmail, validatePassword, validatePhoneNumber };