@webority/ui-react 0.17.3 → 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.
@@ -0,0 +1,23 @@
1
+ @webority/ui-react includes a port (src/lib/qrCode.js, bundled into dist) of the following third-party software.
2
+
3
+ QR Code generator library
4
+ https://www.nayuki.io/page/qr-code-generator-library
5
+ https://github.com/nayuki/QR-Code-generator
6
+
7
+ Copyright (c) Project Nayuki. (MIT License)
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
10
+ this software and associated documentation files (the "Software"), to deal in
11
+ the Software without restriction, including without limitation the rights to
12
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
13
+ the Software, and to permit persons to whom the Software is furnished to do so,
14
+ subject to the following conditions:
15
+ - The above copyright notice and this permission notice shall be included in
16
+ all copies or substantial portions of the Software.
17
+ - The Software is provided "as is", without warranty of any kind, express or
18
+ implied, including but not limited to the warranties of merchantability,
19
+ fitness for a particular purpose and noninfringement. In no event shall the
20
+ authors or copyright holders be liable for any claim, damages or other
21
+ liability, whether in an action of contract, tort or otherwise, arising from,
22
+ out of or in connection with the Software or the use or other dealings in the
23
+ Software.
@@ -0,0 +1,23 @@
1
+ /**
2
+ * A "Columns" menu that hides and shows a table's columns: one checkbox per column marked
3
+ * `hideable`. Put it in the table toolbar's actions and feed it from `useTableView`, which also
4
+ * hands the same `hiddenColumns` to `AppDataTable`. Razor counterpart: `<app-column-menu for="…" view-key="…">`.
5
+ *
6
+ * @param {object} props
7
+ * @param {{ key: string, label: import('react').ReactNode, hideable?: boolean }[]} props.columns The table's columns.
8
+ * @param {string[]} [props.hiddenColumns] Keys of the columns currently hidden.
9
+ * @param {(key: string) => void} props.onToggle Called with a column's key when its box changes.
10
+ * @param {string} [props.label="Columns"] Accessible name and tooltip of the button, and the menu heading.
11
+ * @param {string} [props.className] Extra classes on the menu panel.
12
+ */
13
+ export default function AppColumnMenu({ columns, hiddenColumns, onToggle, label, className, ...rest }: {
14
+ columns: {
15
+ key: string;
16
+ label: import('react').ReactNode;
17
+ hideable?: boolean;
18
+ }[];
19
+ hiddenColumns?: string[];
20
+ onToggle: (key: string) => void;
21
+ label?: string;
22
+ className?: string;
23
+ }): import("react").JSX.Element;
@@ -29,8 +29,17 @@
29
29
  * @param {boolean} [props.striped=false] Alternate-row shading in place of divider lines.
30
30
  * @param {string|number} [props.maxHeight] Caps the table's height; the body scrolls inside it with
31
31
  * the header pinned. Without it there is no scroll box for the header to stick to.
32
+ * @param {string[]} [props.hiddenColumns] Keys of `hideable` columns to leave out (from useTableView).
33
+ * A column that is not hideable always shows.
34
+ * @param {boolean} [props.stackOnMobile=false] Below 576px, shows each row as a card: the first
35
+ * column on top, then "label: value" lines from the column labels, actions at the bottom.
32
36
  * @param {boolean} [props.stickyFirstColumn=false] Pins the first column (and the select/expand
33
37
  * column before it) while a wide table scrolls sideways.
38
+ * @param {(row: object) => string} [props.rowHref] Makes the whole row open this URL on click or Enter
39
+ * (Ctrl/Cmd or middle click opens a new tab). Checkboxes, buttons, links and menus in the row keep
40
+ * their own behaviour. Razor: `data-href` on the <tr>.
41
+ * @param {(row: object) => void} [props.onRowClick] Called when the row is clicked or Enter is pressed
42
+ * on it, for in-page actions (open a drawer). Same nested-control rule as rowHref.
34
43
  * @param {(row: object) => 'success'|'warning'|'danger'|'info'|undefined} [props.rowStatus] A coloured
35
44
  * bar on the row's leading edge, e.g. danger for an overdue invoice. Undefined draws none.
36
45
  * @param {boolean} [props.selectable=false] Render a leading checkbox column.
@@ -40,7 +49,7 @@
40
49
  * @param {(row: object) => import('react').ReactNode} [props.renderExpanded] When given, each row
41
50
  * gets a leading expand toggle; the returned content renders in a full-width row beneath it.
42
51
  */
43
- export default function AppDataTable({ columns, rows, rowKey, sort, onSort, loading, skeletonRows, empty, emptyFiltered, sourceCount, rowActions, rowActionsLabel, pagination, ariaLabel, className, wrapperClassName, selectable, selectedIds, onToggleRow, onToggleAll, renderExpanded, density, striped, maxHeight, stickyFirstColumn, rowStatus, ...rest }: {
52
+ export default function AppDataTable({ columns, rows, rowKey, sort, onSort, loading, skeletonRows, empty, emptyFiltered, sourceCount, rowActions, rowActionsLabel, pagination, ariaLabel, className, wrapperClassName, selectable, selectedIds, onToggleRow, onToggleAll, renderExpanded, density, striped, maxHeight, stickyFirstColumn, stackOnMobile, hiddenColumns, rowStatus, rowHref, onRowClick, ...rest }: {
44
53
  columns: object[];
45
54
  rows: object[];
46
55
  rowKey?: (row: object, index: number) => string | number;
@@ -63,7 +72,11 @@ export default function AppDataTable({ columns, rows, rowKey, sort, onSort, load
63
72
  density?: 'comfortable' | 'cozy' | 'compact';
64
73
  striped?: boolean;
65
74
  maxHeight?: string | number;
75
+ hiddenColumns?: string[];
76
+ stackOnMobile?: boolean;
66
77
  stickyFirstColumn?: boolean;
78
+ rowHref?: (row: object) => string;
79
+ onRowClick?: (row: object) => void;
67
80
  rowStatus?: (row: object) => 'success' | 'warning' | 'danger' | 'info' | undefined;
68
81
  selectable?: boolean;
69
82
  selectedIds?: Set<string | number>;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * The list of a form's errors after a failed submit, each a link that moves focus to its field.
3
+ *
4
+ * Renders nothing while `errors` is empty. When errors appear it takes the focus itself, so a
5
+ * screen reader announces the title and the count, and a keyboard user starts from the list
6
+ * rather than from the Save button.
7
+ *
8
+ * @param {object} props
9
+ * @param {{ field: string, message: string }[]} [props.errors] `field` is the input's id or name.
10
+ * @param {import('react').ReactNode} [props.title] Heading. Defaults to "Fix N field(s) to continue".
11
+ * @param {boolean} [props.autoFocus=true] Take focus when errors appear. Turn off only where the
12
+ * summary is shown for reference, such as documentation, never on a form.
13
+ * @param {string} [props.id]
14
+ * @param {string} [props.className]
15
+ */
16
+ export default function AppErrorSummary({ errors, title, autoFocus, id, className, ...rest }: {
17
+ errors?: {
18
+ field: string;
19
+ message: string;
20
+ }[];
21
+ title?: import('react').ReactNode;
22
+ autoFocus?: boolean;
23
+ id?: string;
24
+ className?: string;
25
+ }): import("react").JSX.Element;
@@ -4,16 +4,26 @@
4
4
  * Wraps a set of related fields with a section heading and intro text. Useful for
5
5
  * breaking large forms into digestible chunks. The body receives the fields; the
6
6
  * heading is outside so it stacks above the first field without wrapping it.
7
+ * Consecutive sections are set apart by space and a light rule.
7
8
  *
8
9
  * @param {object} props
9
10
  * @param {import('react').ReactNode} props.children The form fields.
10
11
  * @param {import('react').ReactNode} [props.title] Section heading (h3).
11
12
  * @param {import('react').ReactNode} [props.description] Intro text below the title (optional).
13
+ * @param {'stacked'|'side'} [props.layout='stacked'] `side` puts the title and description in a
14
+ * column beside the fields from lg up; below that it stacks.
15
+ * @param {'top'|'start'} [props.labels='top'] `start` puts each field's label beside its control
16
+ * (one field per row) from md up; below that labels sit on top.
17
+ * @param {'comfortable'|'compact'} [props.density='comfortable'] `compact` uses 36px controls and
18
+ * tighter gaps, for admin screens and dialogs.
12
19
  * @param {string} [props.className]
13
20
  */
14
- export default function AppFormSection({ children, title, description, className, ...rest }: {
21
+ export default function AppFormSection({ children, title, description, layout, labels, density, className, ...rest }: {
15
22
  children: import('react').ReactNode;
16
23
  title?: import('react').ReactNode;
17
24
  description?: import('react').ReactNode;
25
+ layout?: 'stacked' | 'side';
26
+ labels?: 'top' | 'start';
27
+ density?: 'comfortable' | 'compact';
18
28
  className?: string;
19
29
  }): import("react").JSX.Element;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * A scannable QR code, drawn as inline SVG. The React counterpart of `<app-qr-code>`.
3
+ *
4
+ * Drawn on a whole-module grid as ONE path, then scaled by a whole number of pixels per module. A
5
+ * fractional module size (a 200px box over 41 modules) lets the browser round each square
6
+ * differently, which leaves uneven modules and hairline seams between neighbours, and scanners
7
+ * refuse the result. `size` is therefore the largest the code may be, not its exact width.
8
+ *
9
+ * Black on white is a scan-reliability requirement, not a styling choice, so it ignores the theme
10
+ * and dark mode. Byte mode (UTF-8), medium error correction or higher, versions 1 to 40; text too
11
+ * long for a version 40 symbol throws.
12
+ *
13
+ * @param {object} props
14
+ * @param {string} props.value The text to encode, such as a URL, an otpauth:// URI or a signed token.
15
+ * Nothing renders while it is empty.
16
+ * @param {number} [props.size=240] Largest width and height in px. The code renders at the biggest
17
+ * whole number of pixels per module that fits.
18
+ * @param {string} [props.title='QR code'] Accessible name. Say what scanning it does.
19
+ * @param {string} [props.className]
20
+ * @param {import('react').CSSProperties} [props.style]
21
+ */
22
+ export default function AppQrCode({ value, size, title, className, style, ...rest }: {
23
+ value: string;
24
+ size?: number;
25
+ title?: string;
26
+ className?: string;
27
+ style?: import('react').CSSProperties;
28
+ }): import("react").JSX.Element;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * A labelled set of radio buttons, laid out like every other field: the group's label sits
3
+ * where a text field's label does (above, or beside it under `AppFormSection labels="start"`),
4
+ * with the hint or error below.
5
+ *
6
+ * The group is a `role="radiogroup"` named by its label rather than a fieldset/legend: a
7
+ * legend renders at heading size and cannot take part in the field grid, so the label would
8
+ * sit apart from every other field on the form.
9
+ *
10
+ * @param {object} props
11
+ * @param {import('react').ReactNode} props.label Visible group label; also the group's accessible name.
12
+ * @param {{ value: string, label: import('react').ReactNode, disabled?: boolean }[]} props.options
13
+ * @param {string} [props.name] Shared name of the radios. Defaults to a generated one.
14
+ * @param {string} [props.value] Selected value (controlled).
15
+ * @param {string} [props.defaultValue] Initially selected value (uncontrolled).
16
+ * @param {(value: string) => void} [props.onChange]
17
+ * @param {boolean} [props.inline=false] Options in a row (wrapping) instead of a column.
18
+ * @param {boolean} [props.required=false]
19
+ * @param {boolean} [props.disabled=false] Disables every option.
20
+ * @param {string} [props.error] Error message below the group. Replaces the hint.
21
+ * @param {string} [props.hint] Helper text below the group.
22
+ * @param {import('react').ReactNode} [props.help] Content for the label info-tip.
23
+ * @param {string} [props.helpLabel="More information"] aria-label for the info-tip button.
24
+ * @param {string} [props.id]
25
+ * @param {string} [props.className] Class on the group (the control).
26
+ * @param {import('react').CSSProperties} [props.style] Inline style; lands on the group with `className`.
27
+ * @param {string} [props.fieldClassName] Class on the `.field` wrapper.
28
+ */
29
+ export default function AppRadioGroup({ label, options, name, value, defaultValue, onChange, inline, required, disabled, error, hint, help, helpLabel, id, className, fieldClassName, style, ...rest }: {
30
+ label: import('react').ReactNode;
31
+ options: {
32
+ value: string;
33
+ label: import('react').ReactNode;
34
+ disabled?: boolean;
35
+ }[];
36
+ name?: string;
37
+ value?: string;
38
+ defaultValue?: string;
39
+ onChange?: (value: string) => void;
40
+ inline?: boolean;
41
+ required?: boolean;
42
+ disabled?: boolean;
43
+ error?: string;
44
+ hint?: string;
45
+ help?: import('react').ReactNode;
46
+ helpLabel?: string;
47
+ id?: string;
48
+ className?: string;
49
+ style?: import('react').CSSProperties;
50
+ fieldClassName?: string;
51
+ }): import("react").JSX.Element;
@@ -15,6 +15,7 @@ export { default as AppChip } from "./components/AppChip.jsx";
15
15
  export { default as AppChoiceCard } from "./components/AppChoiceCard.jsx";
16
16
  export { default as AppChoiceChip } from "./components/AppChoiceChip.jsx";
17
17
  export { default as AppColorField } from "./components/AppColorField.jsx";
18
+ export { default as AppColumnMenu } from "./components/AppColumnMenu.jsx";
18
19
  export { default as AppCommandPalette } from "./components/AppCommandPalette.jsx";
19
20
  export { default as AppCompareTable } from "./components/AppCompareTable.jsx";
20
21
  export { default as AppConfirmDialog } from "./components/AppConfirmDialog.jsx";
@@ -27,6 +28,7 @@ export { default as AppDateRangePicker } from "./components/AppDateRangePicker.j
27
28
  export { default as AppDescriptions } from "./components/AppDescriptions.jsx";
28
29
  export { default as AppDropdown } from "./components/AppDropdown.jsx";
29
30
  export { default as AppEmptyState } from "./components/AppEmptyState.jsx";
31
+ export { default as AppErrorSummary } from "./components/AppErrorSummary.jsx";
30
32
  export { default as AppFileAttachment } from "./components/AppFileAttachment.jsx";
31
33
  export { default as AppFilePicker } from "./components/AppFilePicker.jsx";
32
34
  export { default as AppFloatingDock } from "./components/AppFloatingDock.jsx";
@@ -51,7 +53,9 @@ export { default as AppPhoneNumberInput } from "./components/AppPhoneNumberInput
51
53
  export { default as AppPopover } from "./components/AppPopover.jsx";
52
54
  export { default as AppPricingCard } from "./components/AppPricingCard.jsx";
53
55
  export { default as AppProgress } from "./components/AppProgress.jsx";
56
+ export { default as AppQrCode } from "./components/AppQrCode.jsx";
54
57
  export { default as AppRadio } from "./components/AppRadio.jsx";
58
+ export { default as AppRadioGroup } from "./components/AppRadioGroup.jsx";
55
59
  export { default as AppRepeater } from "./components/AppRepeater.jsx";
56
60
  export { default as AppRequiredMark } from "./components/AppRequiredMark.jsx";
57
61
  export { default as AppResourceCard } from "./components/AppResourceCard.jsx";
@@ -87,3 +91,4 @@ export { MODAL_ICONS } from "./components/ModalIcons.jsx";
87
91
  export { dismissAll, errorToast, toast } from "./components/toast.js";
88
92
  export { useCommandPaletteShortcut } from "./lib/useCommandPaletteShortcut.js";
89
93
  export { usePagination } from "./lib/usePagination.js";
94
+ export { useTableView } from "./lib/useTableView.js";
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Moves focus to a form field named by its id or its `name`, scrolling it to the middle of the
3
+ * view so its label shows too. A custom-element field (a select, a date picker) carries the id or
4
+ * name on its host, so the first focusable element inside the match takes the focus. A hidden
5
+ * form mirror shares the name and is skipped.
6
+ *
7
+ * @param {string} field The field's id or name.
8
+ * @returns {boolean} Whether a field took the focus.
9
+ * @internal shared by AppErrorSummary; Razor's webority-ui.js carries the same lookup.
10
+ */
11
+ export default function focusField(field: string): boolean;
@@ -0,0 +1,72 @@
1
+ /*! @license
2
+ * QR Code encoder, ported from the QR Code generator library by Project Nayuki.
3
+ * https://www.nayuki.io/page/qr-code-generator-library
4
+ *
5
+ * Copyright (c) Project Nayuki. (MIT License)
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
8
+ * this software and associated documentation files (the "Software"), to deal in
9
+ * the Software without restriction, including without limitation the rights to
10
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11
+ * the Software, and to permit persons to whom the Software is furnished to do so,
12
+ * subject to the following conditions:
13
+ * - The above copyright notice and this permission notice shall be included in
14
+ * all copies or substantial portions of the Software.
15
+ * - The Software is provided "as is", without warranty of any kind, express or
16
+ * implied, including but not limited to the warranties of merchantability,
17
+ * fitness for a particular purpose and noninfringement. In no event shall the
18
+ * authors or copyright holders be liable for any claim, damages or other
19
+ * liability, whether in an action of contract, tort or otherwise, arising from,
20
+ * out of or in connection with the Software or the use or other dealings in the
21
+ * Software.
22
+ */
23
+ export type QrMatrix = {
24
+ /**
25
+ * Modules per side, 21 to 177.
26
+ */
27
+ size: number;
28
+ /**
29
+ * 1 to 40.
30
+ */
31
+ version: number;
32
+ /**
33
+ * The level actually used, which can be above the one asked for.
34
+ */
35
+ ecc: 'L' | 'M' | 'Q' | 'H';
36
+ /**
37
+ * 0 to 7.
38
+ */
39
+ mask: number;
40
+ isDark: (row: number, col: number) => boolean;
41
+ };
42
+ /**
43
+ * An encoded QR symbol: a square grid of dark and light modules, without the quiet zone.
44
+ * @typedef {object} QrMatrix
45
+ * @property {number} size Modules per side, 21 to 177.
46
+ * @property {number} version 1 to 40.
47
+ * @property {'L'|'M'|'Q'|'H'} ecc The level actually used, which can be above the one asked for.
48
+ * @property {number} mask 0 to 7.
49
+ * @property {(row: number, col: number) => boolean} isDark
50
+ */
51
+ /**
52
+ * Encodes text as a QR symbol in byte mode (UTF-8), choosing the smallest version that fits.
53
+ * The error correction level is a minimum: it is raised while the data still fits the same version.
54
+ *
55
+ * @param {string} text
56
+ * @param {'L'|'M'|'Q'|'H'} [ecc='M']
57
+ * @param {{ mask?: number, boostEcc?: boolean }} [options] mask -1 chooses the best of the eight.
58
+ * @returns {QrMatrix}
59
+ */
60
+ export declare function encodeQr(text: string, ecc?: 'L' | 'M' | 'Q' | 'H', { mask, boostEcc }?: {
61
+ mask?: number;
62
+ boostEcc?: boolean;
63
+ }): QrMatrix;
64
+ /**
65
+ * The dark modules as ONE SVG path on a whole-module grid: one rectangle per horizontal run,
66
+ * offset by the quiet zone. The viewBox is `size + 2 * quietZone` modules square.
67
+ *
68
+ * @param {QrMatrix} matrix
69
+ * @param {number} [quietZone=4]
70
+ * @returns {string}
71
+ */
72
+ export declare function qrSvgPath(matrix: QrMatrix, quietZone?: number): string;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Hidden columns and sort for one table, remembered per browser.
3
+ *
4
+ * @param {string} viewKey Names the view, e.g. "invoices". Two tables sharing a key share a view.
5
+ * @param {{ sort?: { key: string, dir: "asc"|"desc" } }} [options] The sort to start from.
6
+ * @returns {{ hiddenColumns: string[], toggleColumn: (key: string) => void,
7
+ * sort: { key: string, dir: "asc"|"desc" }|undefined, setSort: (next: object|((prev: object) => object)) => void }}
8
+ */
9
+ export declare function useTableView(viewKey: string, { sort: initialSort }?: {
10
+ sort?: {
11
+ key: string;
12
+ dir: "asc" | "desc";
13
+ };
14
+ }): {
15
+ hiddenColumns: string[];
16
+ toggleColumn: (key: string) => void;
17
+ sort: {
18
+ key: string;
19
+ dir: "asc" | "desc";
20
+ } | undefined;
21
+ setSort: (next: object | ((prev: object) => object)) => void;
22
+ };