@ahrowe/ui 0.23.0 → 0.24.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/esm/common/alert/alert.types.mjs.map +1 -1
- package/dist/esm/common/badge/badge.types.mjs.map +1 -1
- package/dist/esm/common/button/button.mjs +1 -1
- package/dist/esm/common/button/button.mjs.map +1 -1
- package/dist/esm/common/button/button.module.mjs +1 -1
- package/dist/esm/common/button/button.module.mjs.map +1 -1
- package/dist/esm/common/button/button.types.mjs +1 -1
- package/dist/esm/common/button/button.types.mjs.map +1 -1
- package/dist/esm/common/card/Card.mjs +1 -1
- package/dist/esm/common/card/Card.mjs.map +1 -1
- package/dist/esm/common/card/card.types.mjs.map +1 -1
- package/dist/esm/common/chip/chip.mjs +1 -1
- package/dist/esm/common/chip/chip.mjs.map +1 -1
- package/dist/esm/common/chip/chip.types.mjs.map +1 -1
- package/dist/esm/common/dropZone/dropZone.types.mjs.map +1 -1
- package/dist/esm/common/floatingMenu/floatingMenu.types.mjs.map +1 -1
- package/dist/esm/common/hooks/useCoarsePointer.mjs +2 -0
- package/dist/esm/common/hooks/useCoarsePointer.mjs.map +1 -0
- package/dist/esm/common/hooks/useSwipeDismiss.mjs +1 -1
- package/dist/esm/common/hooks/useSwipeDismiss.mjs.map +1 -1
- package/dist/esm/common/iconPicker/iconPicker.mjs +1 -1
- package/dist/esm/common/iconPicker/iconPicker.mjs.map +1 -1
- package/dist/esm/common/input/input.types.mjs.map +1 -1
- package/dist/esm/common/interactableDiv/interactableDiv.mjs +1 -1
- package/dist/esm/common/interactableDiv/interactableDiv.mjs.map +1 -1
- package/dist/esm/common/numberInput/index.mjs.map +1 -1
- package/dist/esm/common/numberInput/numberInput.mjs +1 -1
- package/dist/esm/common/numberInput/numberInput.mjs.map +1 -1
- package/dist/esm/common/numberInput/numberInput.module.mjs +1 -1
- package/dist/esm/common/numberInput/numberInput.module.mjs.map +1 -1
- package/dist/esm/common/numberInput/useStepRepeat.mjs +2 -0
- package/dist/esm/common/numberInput/useStepRepeat.mjs.map +1 -0
- package/dist/esm/common/otpInput/otpInput.types.mjs.map +1 -1
- package/dist/esm/common/popover/popover.types.mjs.map +1 -1
- package/dist/esm/common/radioGroup/radioGroup.types.mjs.map +1 -1
- package/dist/esm/common/sectionHeader/sectionHeader.types.mjs.map +1 -1
- package/dist/index.cjs +6 -6
- package/dist/index.cjs.map +1 -1
- package/dist/style.css +1 -1
- package/dist/types/package/common/alert/alert.types.d.ts +1 -1
- package/dist/types/package/common/animatedLogo/animatedLogo.types.d.ts +11 -3
- package/dist/types/package/common/avatar/avatar.types.d.ts +1 -1
- package/dist/types/package/common/badge/badge.types.d.ts +1 -1
- package/dist/types/package/common/button/button.types.d.ts +10 -4
- package/dist/types/package/common/card/card.types.d.ts +1 -1
- package/dist/types/package/common/carousel/carousel.types.d.ts +1 -1
- package/dist/types/package/common/checkbox/checkbox.types.d.ts +1 -1
- package/dist/types/package/common/chip/chip.types.d.ts +2 -0
- package/dist/types/package/common/colorPicker/colorPicker.types.d.ts +1 -1
- package/dist/types/package/common/configProvider/configProvider.types.d.ts +1 -1
- package/dist/types/package/common/dropZone/dropZone.types.d.ts +1 -1
- package/dist/types/package/common/dropdown/dropdown.types.d.ts +1 -1
- package/dist/types/package/common/errorBoundary/errorBoundary.types.d.ts +1 -1
- package/dist/types/package/common/floatingMenu/floatingMenu.types.d.ts +1 -1
- package/dist/types/package/common/hooks/useCoarsePointer.d.ts +10 -0
- package/dist/types/package/common/iconPicker/iconPicker.types.d.ts +1 -1
- package/dist/types/package/common/input/input.types.d.ts +2 -2
- package/dist/types/package/common/inputDropdown/inputDropdown.types.d.ts +1 -1
- package/dist/types/package/common/interactableDiv/interactableDiv.d.ts +2 -2
- package/dist/types/package/common/kanbanBoard/kanbanBoard.types.d.ts +1 -1
- package/dist/types/package/common/numberInput/index.d.ts +1 -0
- package/dist/types/package/common/numberInput/numberInput.d.ts +3 -32
- package/dist/types/package/common/numberInput/numberInput.types.d.ts +61 -0
- package/dist/types/package/common/numberInput/useStepRepeat.d.ts +17 -0
- package/dist/types/package/common/optionPicker/optionPicker.types.d.ts +1 -1
- package/dist/types/package/common/otpInput/otpInput.types.d.ts +1 -1
- package/dist/types/package/common/popover/popover.types.d.ts +1 -1
- package/dist/types/package/common/radioGroup/radioGroup.types.d.ts +1 -1
- package/dist/types/package/common/rating/rating.types.d.ts +1 -1
- package/dist/types/package/common/searchInput/searchInput.types.d.ts +1 -1
- package/dist/types/package/common/sectionHeader/sectionHeader.types.d.ts +1 -1
- package/dist/types/package/common/slider/slider.types.d.ts +1 -1
- package/dist/types/package/common/switch/switch.types.d.ts +1 -1
- package/dist/types/package/common/tabHeader/tabHeader.types.d.ts +1 -1
- package/dist/types/package/common/timeInput/timeInput.types.d.ts +1 -1
- package/dist/types/package/common/types/baseProps.types.d.ts +20 -5
- package/dist/types/package/common/types/slots.types.d.ts +1 -1
- package/docs/Button.md +23 -2
- package/docs/Chip.md +1 -0
- package/docs/NumberInput.md +66 -2
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { CSSProperties } from 'react';
|
|
1
|
+
import { default as React, CSSProperties } from 'react';
|
|
2
2
|
import { IconContent } from '../types/icon.types';
|
|
3
|
-
import { SlotClassNames, SlotStyles,
|
|
3
|
+
import { SlotClassNames, SlotStyles, DataProps } from '../types/slots.types';
|
|
4
4
|
export declare enum ButtonStyleType {
|
|
5
5
|
Primary = "primary",
|
|
6
6
|
Default = "default",
|
|
@@ -10,7 +10,9 @@ export declare enum ButtonSize {
|
|
|
10
10
|
Default = "default",
|
|
11
11
|
Small = "small",
|
|
12
12
|
Medium = "medium",
|
|
13
|
-
Large = "large"
|
|
13
|
+
Large = "large",
|
|
14
|
+
/** Square, padding-free button for a lone icon. Give it its own width/height. */
|
|
15
|
+
Icon = "icon"
|
|
14
16
|
}
|
|
15
17
|
export declare enum ButtonType {
|
|
16
18
|
Button = "button",
|
|
@@ -18,7 +20,11 @@ export declare enum ButtonType {
|
|
|
18
20
|
Submit = "submit"
|
|
19
21
|
}
|
|
20
22
|
export type ButtonSlots = 'background' | 'content' | 'loadingContainer' | 'label';
|
|
21
|
-
|
|
23
|
+
/**
|
|
24
|
+
* `DataProps` supplies the `data-*` index signature, which `ButtonHTMLAttributes` doesn't cover.
|
|
25
|
+
* `type` and `onClick` below deliberately narrow their inherited counterparts.
|
|
26
|
+
*/
|
|
27
|
+
export interface ButtonProps extends DataProps, React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
22
28
|
className?: string;
|
|
23
29
|
style?: CSSProperties;
|
|
24
30
|
type?: ButtonType;
|
|
@@ -7,7 +7,7 @@ export declare enum CardStyleType {
|
|
|
7
7
|
Outlined = "outlined",
|
|
8
8
|
Filled = "filled"
|
|
9
9
|
}
|
|
10
|
-
export interface CardProps extends HtmlProps {
|
|
10
|
+
export interface CardProps extends Omit<HtmlProps, 'tabIndex'> {
|
|
11
11
|
className?: string | undefined;
|
|
12
12
|
children?: ReactNode;
|
|
13
13
|
styleType?: CardStyleType;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CSSProperties, ReactNode } from 'react';
|
|
2
2
|
import { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';
|
|
3
3
|
export type CarouselSlots = 'root' | 'track' | 'slide' | 'prevButton' | 'nextButton' | 'dots' | 'dot';
|
|
4
|
-
export interface CarouselProps extends HtmlProps {
|
|
4
|
+
export interface CarouselProps extends Omit<HtmlProps, 'onChange'> {
|
|
5
5
|
children?: ReactNode;
|
|
6
6
|
currentIndex?: number;
|
|
7
7
|
defaultIndex?: number;
|
|
@@ -2,7 +2,7 @@ import { CSSProperties, ReactNode } from 'react';
|
|
|
2
2
|
import { FormValidator } from '../../services/formValidation';
|
|
3
3
|
import { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';
|
|
4
4
|
export type CheckboxSlots = 'icon' | 'checkmark' | 'label';
|
|
5
|
-
export interface CheckboxProps extends HtmlProps {
|
|
5
|
+
export interface CheckboxProps extends Omit<HtmlProps, 'onToggle'> {
|
|
6
6
|
label?: string;
|
|
7
7
|
selected?: boolean;
|
|
8
8
|
onToggle?: (isToggled: boolean, event?: React.MouseEvent | React.KeyboardEvent) => void;
|
|
@@ -12,6 +12,8 @@ export interface ChipProps extends HtmlProps {
|
|
|
12
12
|
thumbnail?: React.ReactNode;
|
|
13
13
|
styleType?: ChipStyleType;
|
|
14
14
|
showRemoveIcon?: boolean;
|
|
15
|
+
/** Accessible name for the remove button. Default `'Remove'`. */
|
|
16
|
+
removeLabel?: string;
|
|
15
17
|
onClick?: () => void;
|
|
16
18
|
onRemove?: () => void;
|
|
17
19
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
import { InputProps } from '../input/input.types';
|
|
3
3
|
import { TextareaProps } from '../textarea/textarea.types';
|
|
4
|
-
import { NumberInputProps } from '../numberInput/numberInput';
|
|
4
|
+
import { NumberInputProps } from '../numberInput/numberInput.types';
|
|
5
5
|
import { DropdownProps } from '../dropdown/dropdown.types';
|
|
6
6
|
import { InputDropdownProps } from '../inputDropdown/inputDropdown.types';
|
|
7
7
|
import { CheckboxProps } from '../checkbox/checkbox.types';
|
|
@@ -48,7 +48,7 @@ export interface DropZoneRenderState {
|
|
|
48
48
|
disabled: boolean;
|
|
49
49
|
}
|
|
50
50
|
export type DropZoneSlots = 'root' | 'content' | 'fileList' | 'fileItem' | 'input';
|
|
51
|
-
export interface DropZoneProps extends HtmlProps {
|
|
51
|
+
export interface DropZoneProps extends Omit<HtmlProps, 'children'> {
|
|
52
52
|
/** Static content, or a render function that receives the live drop state. */
|
|
53
53
|
children?: React.ReactNode | ((state: DropZoneRenderState) => React.ReactNode);
|
|
54
54
|
/**
|
|
@@ -6,7 +6,7 @@ export interface DropdownItem {
|
|
|
6
6
|
label: ReactNode;
|
|
7
7
|
disabled?: boolean;
|
|
8
8
|
}
|
|
9
|
-
export interface DropdownProps extends HtmlProps {
|
|
9
|
+
export interface DropdownProps extends Omit<HtmlProps, 'onFocus' | 'onBlur' | 'onMouseEnter' | 'onMouseLeave'> {
|
|
10
10
|
formValidator?: FormValidator | null;
|
|
11
11
|
onMouseEnter?: ((event: React.MouseEvent) => void) | null;
|
|
12
12
|
onMouseLeave?: ((event: React.MouseEvent) => void) | null;
|
|
@@ -24,7 +24,7 @@ export interface ErrorBoundaryLabels {
|
|
|
24
24
|
/** Toast shown if the copy fails (only visible if `ToastProvider` is mounted). */
|
|
25
25
|
copyErrorToast?: string;
|
|
26
26
|
}
|
|
27
|
-
export interface ErrorBoundaryProps extends HtmlProps {
|
|
27
|
+
export interface ErrorBoundaryProps extends Omit<HtmlProps, 'title' | 'onError'> {
|
|
28
28
|
children?: ReactNode;
|
|
29
29
|
/** Heading shown above the error message. Default: "Something went wrong". */
|
|
30
30
|
title?: ReactNode;
|
|
@@ -6,7 +6,7 @@ export declare enum Align {
|
|
|
6
6
|
Center = "center"
|
|
7
7
|
}
|
|
8
8
|
export type FloatingMenuSlots = 'root' | 'trigger' | 'menu' | 'menuContainer';
|
|
9
|
-
export interface FloatingMenuProps extends HtmlProps {
|
|
9
|
+
export interface FloatingMenuProps extends Omit<HtmlProps, 'content'> {
|
|
10
10
|
align?: Align;
|
|
11
11
|
children?: ReactNode;
|
|
12
12
|
content?: ReactNode;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `true` when the primary pointing device is coarse (touch), kept current so a device that
|
|
3
|
+
* switches input modes re-renders.
|
|
4
|
+
*
|
|
5
|
+
* `useSyncExternalStore` rather than `useState` + `useEffect`: callers pick *markup* with this,
|
|
6
|
+
* so hydration has to start from the server's answer. Reading `matchMedia` in a `useState`
|
|
7
|
+
* initialiser makes the client's first render disagree with the server's HTML.
|
|
8
|
+
*/
|
|
9
|
+
export declare function useCoarsePointer(): boolean;
|
|
10
|
+
export default useCoarsePointer;
|
|
@@ -9,7 +9,7 @@ export interface IconPickerItem {
|
|
|
9
9
|
icon?: IconDefinition;
|
|
10
10
|
customIcon?: React.ReactNode;
|
|
11
11
|
}
|
|
12
|
-
export interface IconPickerProps extends HtmlProps {
|
|
12
|
+
export interface IconPickerProps extends Omit<HtmlProps, 'onChange'> {
|
|
13
13
|
data?: IconPickerItem[];
|
|
14
14
|
selectedId?: string | null;
|
|
15
15
|
label?: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
import { FormValidator } from '../../services/formValidation';
|
|
3
|
-
import { SlotClassNames, SlotStyles,
|
|
3
|
+
import { SlotClassNames, SlotStyles, DataProps } from '../types/slots.types';
|
|
4
4
|
export declare enum InputType {
|
|
5
5
|
Edit = "edit",
|
|
6
6
|
Phone = "phone",
|
|
@@ -17,7 +17,7 @@ export declare enum InputIconPosition {
|
|
|
17
17
|
}
|
|
18
18
|
export type InputSlots = 'label' | 'container' | 'input' | 'suffix' | 'upperRightLabel' | 'fieldset';
|
|
19
19
|
type OverriddenInputAttributes = 'onChange' | 'onFocus' | 'onBlur' | 'onMouseEnter' | 'onMouseLeave' | 'onClick' | 'type' | 'value' | 'min' | 'max' | 'autoComplete';
|
|
20
|
-
export interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, OverriddenInputAttributes>,
|
|
20
|
+
export interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, OverriddenInputAttributes>, DataProps {
|
|
21
21
|
onMouseEnter?: ((event: React.MouseEvent) => void) | null;
|
|
22
22
|
onMouseLeave?: ((event: React.MouseEvent) => void) | null;
|
|
23
23
|
onFocus?: ((event: React.FocusEvent) => void) | null;
|
|
@@ -6,7 +6,7 @@ export interface InputDropdownItem {
|
|
|
6
6
|
label?: string;
|
|
7
7
|
value: string;
|
|
8
8
|
}
|
|
9
|
-
export interface InputDropdownProps extends HtmlProps {
|
|
9
|
+
export interface InputDropdownProps extends Omit<HtmlProps, 'onSelect'> {
|
|
10
10
|
label?: string;
|
|
11
11
|
value?: string;
|
|
12
12
|
formValidator?: FormValidator | null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
interface Properties extends
|
|
2
|
+
import { DataProps } from '../types/baseProps.types';
|
|
3
|
+
interface Properties extends DataProps, Omit<React.HTMLAttributes<HTMLDivElement>, 'tabIndex'> {
|
|
4
4
|
tabIndex?: number | null;
|
|
5
5
|
}
|
|
6
6
|
declare const InteractableDiv: React.ForwardRefExoticComponent<Properties & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -25,7 +25,7 @@ export interface KanbanColumnDef {
|
|
|
25
25
|
hasMore?: boolean;
|
|
26
26
|
}
|
|
27
27
|
export type KanbanBoardSlots = 'dragOverlay';
|
|
28
|
-
export interface KanbanBoardProps<T = unknown> extends HtmlProps {
|
|
28
|
+
export interface KanbanBoardProps<T = unknown> extends Omit<HtmlProps, 'onChange'> {
|
|
29
29
|
/** Ordered list of column definitions. Each column owns its itemIds. */
|
|
30
30
|
columns: KanbanColumnDef[];
|
|
31
31
|
/** Flat map of all items keyed by their id. */
|
|
@@ -1,34 +1,5 @@
|
|
|
1
|
-
import { ReactElement
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
export interface NumberInputProps extends Omit<NumericFormatProps, 'onValueChange' | 'value' | 'customInput' | 'onChange' | 'step' | 'onKeyDown'> {
|
|
5
|
-
value?: number | string;
|
|
6
|
-
onChange?: (value: number | undefined) => void;
|
|
7
|
-
formValidator?: FormValidator | null;
|
|
8
|
-
label?: string;
|
|
9
|
-
error?: string;
|
|
10
|
-
className?: string;
|
|
11
|
-
allowNegative?: boolean;
|
|
12
|
-
decimalSeparator?: string;
|
|
13
|
-
thousandSeparator?: string | boolean;
|
|
14
|
-
prefix?: string;
|
|
15
|
-
suffix?: string;
|
|
16
|
-
decimalScale?: number;
|
|
17
|
-
/**
|
|
18
|
-
* Whether to pad the value to exactly `decimalScale` decimals. Default `true`
|
|
19
|
-
* (e.g. with `decimalScale={2}`, `12` displays as `12.00`). Set `false` to make
|
|
20
|
-
* `decimalScale` an upper limit only — the user may type fewer decimals and they
|
|
21
|
-
* are kept as-is (`12` stays `12`, `12.1` stays `12.1`), while anything beyond
|
|
22
|
-
* `decimalScale` is still truncated.
|
|
23
|
-
*/
|
|
24
|
-
fixedDecimalScale?: boolean;
|
|
25
|
-
placeholder?: string;
|
|
26
|
-
sign?: '+' | '-';
|
|
27
|
-
showArrows?: boolean;
|
|
28
|
-
step?: number;
|
|
29
|
-
readOnly?: boolean;
|
|
30
|
-
isRequired?: boolean;
|
|
31
|
-
onKeyDown?: (e: React.KeyboardEvent<HTMLInputElement>) => void;
|
|
32
|
-
}
|
|
1
|
+
import { ReactElement } from 'react';
|
|
2
|
+
import { NumberInputProps } from './numberInput.types';
|
|
3
|
+
export type { NumberInputProps, NumberInputArrowsLayout } from './numberInput.types';
|
|
33
4
|
declare function NumberInput(props: NumberInputProps): ReactElement;
|
|
34
5
|
export default NumberInput;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { NumericFormatProps } from 'react-number-format';
|
|
3
|
+
import { FormValidator } from '../../services/formValidation';
|
|
4
|
+
/**
|
|
5
|
+
* How the stepper buttons are laid out.
|
|
6
|
+
*
|
|
7
|
+
* - `stacked` — chevrons stacked inside the field's right edge. Compact; suits a mouse.
|
|
8
|
+
* - `split` — square `−` / `+` buttons flanking the field, each as tall and wide as the field.
|
|
9
|
+
* Far apart with the field between them, so a mis-tap can't step the value the wrong way.
|
|
10
|
+
* - `auto` — `split` on a coarse (touch) pointer, `stacked` otherwise.
|
|
11
|
+
*/
|
|
12
|
+
export type NumberInputArrowsLayout = 'auto' | 'stacked' | 'split';
|
|
13
|
+
export interface NumberInputProps extends Omit<NumericFormatProps, 'onValueChange' | 'value' | 'customInput' | 'onChange' | 'step' | 'onKeyDown' | 'min' | 'max'> {
|
|
14
|
+
value?: number | string;
|
|
15
|
+
onChange?: (value: number | undefined) => void;
|
|
16
|
+
formValidator?: FormValidator | null;
|
|
17
|
+
label?: string;
|
|
18
|
+
error?: string;
|
|
19
|
+
className?: string;
|
|
20
|
+
allowNegative?: boolean;
|
|
21
|
+
decimalSeparator?: string;
|
|
22
|
+
thousandSeparator?: string | boolean;
|
|
23
|
+
prefix?: string;
|
|
24
|
+
suffix?: string;
|
|
25
|
+
decimalScale?: number;
|
|
26
|
+
/**
|
|
27
|
+
* Whether to pad the value to exactly `decimalScale` decimals. Default `true`
|
|
28
|
+
* (e.g. with `decimalScale={2}`, `12` displays as `12.00`). Set `false` to make
|
|
29
|
+
* `decimalScale` an upper limit only — the user may type fewer decimals and they
|
|
30
|
+
* are kept as-is (`12` stays `12`, `12.1` stays `12.1`), while anything beyond
|
|
31
|
+
* `decimalScale` is still truncated.
|
|
32
|
+
*/
|
|
33
|
+
fixedDecimalScale?: boolean;
|
|
34
|
+
placeholder?: string;
|
|
35
|
+
sign?: '+' | '-';
|
|
36
|
+
showArrows?: boolean;
|
|
37
|
+
step?: number;
|
|
38
|
+
/**
|
|
39
|
+
* Lower bound. Constrains the steppers and the ArrowDown key, disables the decrease button
|
|
40
|
+
* once reached, and clamps a typed value on blur and on Enter — the two moments it stops
|
|
41
|
+
* being mid-edit. Typing is never blocked; see {@link NumberInputProps.max}.
|
|
42
|
+
*/
|
|
43
|
+
min?: number;
|
|
44
|
+
/**
|
|
45
|
+
* Upper bound. Behaves exactly like {@link NumberInputProps.min} in the other direction.
|
|
46
|
+
*
|
|
47
|
+
* Neither bound rejects a keystroke as it is typed — an edit passes through out-of-range
|
|
48
|
+
* states on its way somewhere valid — and an empty field is never clamped. Use a
|
|
49
|
+
* `formValidator` if out-of-range input must be *rejected* rather than corrected.
|
|
50
|
+
*/
|
|
51
|
+
max?: number;
|
|
52
|
+
/** Stepper layout. Default `'auto'`. */
|
|
53
|
+
arrowsLayout?: NumberInputArrowsLayout;
|
|
54
|
+
/** Accessible name for the increase button. Default `'Increase'`. */
|
|
55
|
+
increaseLabel?: string;
|
|
56
|
+
/** Accessible name for the decrease button. Default `'Decrease'`. */
|
|
57
|
+
decreaseLabel?: string;
|
|
58
|
+
readOnly?: boolean;
|
|
59
|
+
isRequired?: boolean;
|
|
60
|
+
onKeyDown?: (e: React.KeyboardEvent<HTMLInputElement>) => void;
|
|
61
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface UseStepRepeatResult {
|
|
2
|
+
/** Fires one step immediately, then starts the hold-to-repeat timer. */
|
|
3
|
+
start: (direction: 1 | -1, multiplier: number) => void;
|
|
4
|
+
/** Cancels a running repeat. Safe to call when nothing is running. */
|
|
5
|
+
stop: () => void;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Hold-to-repeat for the stepper buttons: one step on press, then an accelerating repeat.
|
|
9
|
+
*
|
|
10
|
+
* The release is watched on `window` rather than by capturing the pointer, which would retarget
|
|
11
|
+
* the following click past the node Button's ripple listens on. Capture would have guaranteed a
|
|
12
|
+
* `pointerup`, so the extra listeners cover the ways a press can end without one.
|
|
13
|
+
*
|
|
14
|
+
* `onStep` returns whether anything changed; `false` ends the repeat, so a hold at a bound stops.
|
|
15
|
+
*/
|
|
16
|
+
export declare function useStepRepeat(onStep: (delta: number) => boolean): UseStepRepeatResult;
|
|
17
|
+
export default useStepRepeat;
|
|
@@ -5,7 +5,7 @@ export interface Option {
|
|
|
5
5
|
key: string;
|
|
6
6
|
}
|
|
7
7
|
export type OptionPickerSlots = 'root' | 'chip' | 'option';
|
|
8
|
-
export interface OptionPickerProps extends HtmlProps {
|
|
8
|
+
export interface OptionPickerProps extends Omit<HtmlProps, 'onChange'> {
|
|
9
9
|
className?: string;
|
|
10
10
|
style?: React.CSSProperties;
|
|
11
11
|
classNames?: SlotClassNames<OptionPickerSlots>;
|
|
@@ -8,7 +8,7 @@ export declare enum OtpInputCharset {
|
|
|
8
8
|
/** Letters and digits. */
|
|
9
9
|
Alphanumeric = "alphanumeric"
|
|
10
10
|
}
|
|
11
|
-
export interface OtpInputProps extends HtmlProps {
|
|
11
|
+
export interface OtpInputProps extends Omit<HtmlProps, 'onChange'> {
|
|
12
12
|
/** Number of character boxes. Default 6. */
|
|
13
13
|
length?: number;
|
|
14
14
|
/** Current code as a plain string, e.g. "123456". */
|
|
@@ -20,7 +20,7 @@ export declare enum PopoverTrigger {
|
|
|
20
20
|
Focus = "focus"
|
|
21
21
|
}
|
|
22
22
|
export type PopoverSlots = 'root' | 'trigger' | 'floating' | 'panel' | 'arrow';
|
|
23
|
-
export interface PopoverProps extends HtmlProps {
|
|
23
|
+
export interface PopoverProps extends Omit<HtmlProps, 'content'> {
|
|
24
24
|
/** The trigger element. */
|
|
25
25
|
children?: ReactNode;
|
|
26
26
|
/** The popover body. */
|
|
@@ -16,7 +16,7 @@ export interface RadioOption {
|
|
|
16
16
|
disabled?: boolean;
|
|
17
17
|
}
|
|
18
18
|
export type RadioGroupSlots = 'root' | 'option' | 'radio' | 'dot' | 'label' | 'description';
|
|
19
|
-
export interface RadioGroupProps extends HtmlProps {
|
|
19
|
+
export interface RadioGroupProps extends Omit<HtmlProps, 'onChange'> {
|
|
20
20
|
/** The selectable options. */
|
|
21
21
|
options: RadioOption[];
|
|
22
22
|
/** Controlled selected value. Omit for uncontrolled. */
|
|
@@ -2,7 +2,7 @@ import { CSSProperties } from 'react';
|
|
|
2
2
|
import { IconContent } from '../types/icon.types';
|
|
3
3
|
import { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';
|
|
4
4
|
export type RatingSlots = 'root' | 'item' | 'iconEmpty' | 'iconFilled';
|
|
5
|
-
export interface RatingProps extends HtmlProps {
|
|
5
|
+
export interface RatingProps extends Omit<HtmlProps, 'onChange'> {
|
|
6
6
|
value?: number;
|
|
7
7
|
defaultValue?: number;
|
|
8
8
|
onChange?: (value: number) => void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HtmlProps } from '../types/slots.types';
|
|
2
|
-
export interface SearchInputProps extends HtmlProps {
|
|
2
|
+
export interface SearchInputProps extends Omit<HtmlProps, 'onChange'> {
|
|
3
3
|
value: string;
|
|
4
4
|
onChange: (value: string) => void;
|
|
5
5
|
onDebounce?: (value: string) => void;
|
|
@@ -9,7 +9,7 @@ export declare enum SectionHeaderSize {
|
|
|
9
9
|
}
|
|
10
10
|
export type SectionHeaderAction = IconAction;
|
|
11
11
|
export type SectionHeaderSlots = 'root' | 'identity' | 'leading' | 'titles' | 'title' | 'subtitle' | 'trailing' | 'left' | 'center' | 'actions';
|
|
12
|
-
export interface SectionHeaderProps extends HtmlProps {
|
|
12
|
+
export interface SectionHeaderProps extends Omit<HtmlProps, 'title'> {
|
|
13
13
|
title?: ReactNode;
|
|
14
14
|
subtitle?: ReactNode;
|
|
15
15
|
icon?: IconContent;
|
|
@@ -7,7 +7,7 @@ export interface SliderMark {
|
|
|
7
7
|
label?: ReactNode;
|
|
8
8
|
}
|
|
9
9
|
export type SliderSlots = 'root' | 'track' | 'range' | 'thumb' | 'mark' | 'markLabel' | 'value';
|
|
10
|
-
export interface SliderProps extends HtmlProps {
|
|
10
|
+
export interface SliderProps extends Omit<HtmlProps, 'onChange'> {
|
|
11
11
|
/** Controlled value. Omit for uncontrolled. */
|
|
12
12
|
value?: number;
|
|
13
13
|
/** Initial value when uncontrolled (default `min`). */
|
|
@@ -2,7 +2,7 @@ import { CSSProperties, ReactNode } from 'react';
|
|
|
2
2
|
import { FormValidator } from '../../services/formValidation';
|
|
3
3
|
import { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';
|
|
4
4
|
export type SwitchSlots = 'track' | 'thumb' | 'label';
|
|
5
|
-
export interface SwitchProps extends HtmlProps {
|
|
5
|
+
export interface SwitchProps extends Omit<HtmlProps, 'onToggle'> {
|
|
6
6
|
label?: string;
|
|
7
7
|
selected?: boolean;
|
|
8
8
|
onToggle?: (isToggled: boolean, event?: React.MouseEvent | React.KeyboardEvent) => void;
|
|
@@ -9,7 +9,7 @@ export interface TabHeaderTab {
|
|
|
9
9
|
subtitle?: string;
|
|
10
10
|
disabled?: boolean;
|
|
11
11
|
}
|
|
12
|
-
export interface TabHeaderProps extends HtmlProps {
|
|
12
|
+
export interface TabHeaderProps extends Omit<HtmlProps, 'onChange'> {
|
|
13
13
|
tabs: TabHeaderTab[];
|
|
14
14
|
currentTab: string;
|
|
15
15
|
onChange: (id: string) => void;
|
|
@@ -2,7 +2,7 @@ import { default as React } from 'react';
|
|
|
2
2
|
import { FormValidator } from '../../services/formValidation';
|
|
3
3
|
import { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';
|
|
4
4
|
export type TimeInputSlots = 'root' | 'clock' | 'clockHeader' | 'headerSegment' | 'meridiem' | 'clockFace' | 'clockHand' | 'clockNumber' | 'footer';
|
|
5
|
-
export interface TimeInputProps extends HtmlProps {
|
|
5
|
+
export interface TimeInputProps extends Omit<HtmlProps, 'onChange' | 'onSelect'> {
|
|
6
6
|
/** Current time as a "HH:MM" (24-hour) string. */
|
|
7
7
|
value?: string | null;
|
|
8
8
|
/** Alias for `value`, to mirror DatePicker. */
|
|
@@ -1,8 +1,23 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
|
-
/**
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
/**
|
|
3
|
+
* TypeScript allows hyphenated attributes on *intrinsic* elements only, so a component's props
|
|
4
|
+
* interface has to declare these itself — no React attribute type provides them.
|
|
5
|
+
*/
|
|
6
|
+
type DataAttributes = {
|
|
7
7
|
[K in `data-${string}`]?: string;
|
|
8
8
|
};
|
|
9
|
+
/**
|
|
10
|
+
* HTML pass-through props accepted on the root element of every component: the full native
|
|
11
|
+
* attribute set for that element, plus `data-*`.
|
|
12
|
+
*
|
|
13
|
+
* Pass the root's element type for correctly-typed event handlers (`HtmlProps<HTMLDivElement>`);
|
|
14
|
+
* the default is the loose `HTMLElement`. Where the root is not a plain container, extend the
|
|
15
|
+
* matching React type instead and add `DataProps` for the `data-*` half — `Button` does this
|
|
16
|
+
* with `React.ButtonHTMLAttributes<HTMLButtonElement>`.
|
|
17
|
+
*
|
|
18
|
+
* A component prop that collides with a native one of the same name must `Omit` the native one.
|
|
19
|
+
*/
|
|
20
|
+
export type HtmlProps<E extends HTMLElement = HTMLElement> = React.HTMLAttributes<E> & DataAttributes;
|
|
21
|
+
/** The `data-*` half of {@link HtmlProps}, for components that source attributes elsewhere. */
|
|
22
|
+
export type DataProps = DataAttributes;
|
|
23
|
+
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { CSSProperties } from 'react';
|
|
2
2
|
export type SlotClassNames<Keys extends string> = Partial<Record<Keys, string>>;
|
|
3
3
|
export type SlotStyles<Keys extends string> = Partial<Record<Keys, CSSProperties>>;
|
|
4
|
-
export type { HtmlProps } from './baseProps.types';
|
|
4
|
+
export type { HtmlProps, DataProps } from './baseProps.types';
|
package/docs/Button.md
CHANGED
|
@@ -29,6 +29,18 @@ import { faSave } from '@fortawesome/free-solid-svg-icons';
|
|
|
29
29
|
// Small
|
|
30
30
|
<Button size={ButtonSize.Small}>Cancel</Button>
|
|
31
31
|
|
|
32
|
+
// Icon-only — padding-free and square; give it the box size you want
|
|
33
|
+
<Button size={ButtonSize.Icon} icon={faPlus} aria-label="Add" style={{ width: 44, height: 44 }} />
|
|
34
|
+
|
|
35
|
+
// Press-and-hold: act on press rather than release
|
|
36
|
+
<Button
|
|
37
|
+
icon={faPlus}
|
|
38
|
+
aria-label="Increase"
|
|
39
|
+
onPointerDown={startRepeat}
|
|
40
|
+
onPointerUp={stopRepeat}
|
|
41
|
+
onPointerCancel={stopRepeat}
|
|
42
|
+
/>
|
|
43
|
+
|
|
32
44
|
// Submit button in a form
|
|
33
45
|
<Button type={ButtonType.Submit} styleType={ButtonStyleType.Primary}>Submit</Button>
|
|
34
46
|
```
|
|
@@ -36,7 +48,7 @@ import { faSave } from '@fortawesome/free-solid-svg-icons';
|
|
|
36
48
|
**Enums:**
|
|
37
49
|
|
|
38
50
|
- `ButtonStyleType`: `Primary` | `Default` | `Delete`
|
|
39
|
-
- `ButtonSize`: `Default` | `Small` | `Medium` | `Large`
|
|
51
|
+
- `ButtonSize`: `Default` | `Small` | `Medium` | `Large` | `Icon`
|
|
40
52
|
- `ButtonType`: `Button` | `Reset` | `Submit`
|
|
41
53
|
|
|
42
54
|
**Key props:**
|
|
@@ -44,13 +56,19 @@ import { faSave } from '@fortawesome/free-solid-svg-icons';
|
|
|
44
56
|
| Prop | Type | Description |
|
|
45
57
|
|------|------|-------------|
|
|
46
58
|
| `styleType` | `ButtonStyleType` | Visual variant |
|
|
47
|
-
| `size` | `ButtonSize` | Size variant |
|
|
59
|
+
| `size` | `ButtonSize` | Size variant. `Icon` strips all padding, inherits the surrounding text size, and centres a lone icon — set the width/height yourself |
|
|
48
60
|
| `type` | `ButtonType` | HTML button type |
|
|
49
61
|
| `icon` | `IconDefinition \| ReactElement` | FontAwesome icon or any React element, shown before label |
|
|
50
62
|
| `isLoading` | `boolean` | Replaces content with a spinner |
|
|
51
63
|
| `disabled` | `boolean` | |
|
|
52
64
|
| `onClick` | `(e: MouseEvent) => void \| Promise<void>` | |
|
|
53
65
|
|
|
66
|
+
`ButtonProps` extends `React.ButtonHTMLAttributes<HTMLButtonElement>`, so every native `<button>`
|
|
67
|
+
attribute is accepted and forwarded — pointer handlers (`onPointerDown` and friends, for
|
|
68
|
+
press-and-hold controls that act on press rather than release), `onContextMenu`, `tabIndex`,
|
|
69
|
+
`name`, `value`, `form`, `autoFocus`, and the rest. `type` and `onClick` are narrowed: `type`
|
|
70
|
+
takes the `ButtonType` enum, and `onClick` may return a promise.
|
|
71
|
+
|
|
54
72
|
**Theming (default style):** the `Default` style is transparent text-coloured by default. Override it theme-wide (or per button via `style`) without touching `Primary`/`Delete`:
|
|
55
73
|
|
|
56
74
|
- `--button-default-background` — fill (default transparent)
|
|
@@ -73,3 +91,6 @@ const theme: Theme = {
|
|
|
73
91
|
```
|
|
74
92
|
|
|
75
93
|
**Slots:** `background` `content` `loadingContainer` `label`
|
|
94
|
+
|
|
95
|
+
**Sizing in a flex row:** a Button never shrinks below its own content (`min-width: min-content`),
|
|
96
|
+
so an icon is never cut off by a flexible sibling. A multi-word label still wraps above that floor.
|
package/docs/Chip.md
CHANGED
|
@@ -56,6 +56,7 @@ import { Chip, ChipContainer, ChipStyleType } from '@ahrowe/ui';
|
|
|
56
56
|
| `text` | `string` | Chip label |
|
|
57
57
|
| `styleType` | `ChipStyleType` | Colour variant (default `Default`) |
|
|
58
58
|
| `thumbnail` | `string` | Avatar image URL |
|
|
59
|
+
| `removeLabel` | `string` | Accessible name for the remove button. Default: `'Remove'` |
|
|
59
60
|
| `showRemoveIcon` | `boolean` | Show × icon |
|
|
60
61
|
| `onRemove` | `() => void` | Remove button handler |
|
|
61
62
|
| `onClick` | `() => void` | Makes chip clickable |
|
package/docs/NumberInput.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**When to use:** Numeric input with formatting — prices, quantities, percentages, phone numbers with separators. Wraps `react-number-format` with the same floating-label style as `Input`.
|
|
4
4
|
|
|
5
|
-
**Keywords:** currency input, quantity field, numeric field
|
|
5
|
+
**Keywords:** currency input, quantity field, numeric field, spinner, stepper, up down arrows, increment, decrement, plus minus, range, bounds, disabled
|
|
6
6
|
|
|
7
7
|
**Import:** `import { NumberInput } from '@ahrowe/ui'`
|
|
8
8
|
|
|
@@ -32,7 +32,18 @@ const priceValidator = new FormValidator<number | undefined>(undefined, [Validat
|
|
|
32
32
|
<NumberInput label="Price" formValidator={priceValidator} prefix="€" decimalScale={2} />
|
|
33
33
|
|
|
34
34
|
// Percentage
|
|
35
|
-
<NumberInput label="Discount" suffix="%" decimalScale={1}
|
|
35
|
+
<NumberInput label="Discount" suffix="%" decimalScale={1} />
|
|
36
|
+
|
|
37
|
+
// Stepper buttons — hold to repeat, shift for ±10, clamped to min/max
|
|
38
|
+
<NumberInput
|
|
39
|
+
label="Guests"
|
|
40
|
+
value={guests}
|
|
41
|
+
onChange={setGuests}
|
|
42
|
+
decimalScale={0}
|
|
43
|
+
showArrows
|
|
44
|
+
min={0}
|
|
45
|
+
max={10}
|
|
46
|
+
/>
|
|
36
47
|
|
|
37
48
|
// Max decimals without padding — cap at 2 decimals, but keep what the user typed
|
|
38
49
|
// (12 stays "12", 12.1 stays "12.1"; 12.111 is truncated to "12.11")
|
|
@@ -58,5 +69,58 @@ const priceValidator = new FormValidator<number | undefined>(undefined, [Validat
|
|
|
58
69
|
| `isRequired` | `boolean` | Shows the required mark (`*`) next to the label. Also inferred automatically when `formValidator` has a `required` validator. Default: `false` |
|
|
59
70
|
| `placeholder` | `string` | |
|
|
60
71
|
| `error` | `string` | Manual error message |
|
|
72
|
+
| `showArrows` | `boolean` | Show stepper buttons. Default: `false` |
|
|
73
|
+
| `step` | `number` | Amount one step changes the value by. Default: `1` (hold shift for ×10) |
|
|
74
|
+
| `min` | `number` | Lower bound — see the note below |
|
|
75
|
+
| `max` | `number` | Upper bound — see the note below |
|
|
76
|
+
| `arrowsLayout` | `'auto' \| 'stacked' \| 'split'` | Stepper layout. Default: `'auto'` |
|
|
77
|
+
| `increaseLabel` | `string` | Accessible name for the increase button. Default: `'Increase'` |
|
|
78
|
+
| `decreaseLabel` | `string` | Accessible name for the decrease button. Default: `'Decrease'` |
|
|
79
|
+
|
|
80
|
+
**Steppers (`showArrows`):** two layouts, picked by `arrowsLayout`:
|
|
81
|
+
|
|
82
|
+
- `'stacked'` — chevrons inside the field's right edge, each roughly 27x17 at the default text
|
|
83
|
+
size. Compact and mouse-oriented: two targets stacked inside a 34px field cannot reach the 24px
|
|
84
|
+
minimum that WCAG 2.5.8 asks for, which is why `'auto'` prefers `'split'` on touch.
|
|
85
|
+
- `'split'` — full-height `−` / `+` buttons flanking the field, each a 44px touch target. The two
|
|
86
|
+
are far apart, so a mis-tap can't step the value the wrong way.
|
|
87
|
+
- `'auto'` (default) — `split` on a coarse (touch) pointer, `stacked` otherwise, detected with
|
|
88
|
+
`matchMedia('(pointer: coarse)')` and re-evaluated when the pointer type changes.
|
|
89
|
+
|
|
90
|
+
The split buttons are the shared `Button` component, so press feedback is the same ripple as everywhere else in the library.
|
|
91
|
+
|
|
92
|
+
Press and hold a button to repeat: one step immediately, then a repeat after 400ms that accelerates
|
|
93
|
+
after about a second. Hold shift for ×10. The field itself carries `role="spinbutton"` with
|
|
94
|
+
`aria-valuenow` / `aria-valuemin` / `aria-valuemax`, so ↑/↓ stepping is announced; the buttons stay
|
|
95
|
+
out of the tab order rather than adding two tab stops per field.
|
|
96
|
+
|
|
97
|
+
**`min` / `max` clamp, they do not block typing.** Both bounds constrain the steppers and the
|
|
98
|
+
↑/↓ keys, disable the corresponding button once reached, and pull a typed value back into range
|
|
99
|
+
when it stops being mid-edit: on blur, and on Enter (which submits a surrounding form without ever
|
|
100
|
+
blurring the field). An empty field is never clamped, so blurring an untouched field does not fill
|
|
101
|
+
in `min`.
|
|
102
|
+
|
|
103
|
+
Nothing is rejected as it is typed, deliberately. Editing inserts digits into an existing value, so
|
|
104
|
+
the intermediate state routinely leaves the range even when the destination is inside it — with
|
|
105
|
+
`max={10}`, putting the caret in front of `8` and typing `1` on the way to `18` would simply do
|
|
106
|
+
nothing, with no feedback. Blocking input suits *format* rules (digits only, a fixed length), where
|
|
107
|
+
every rejected keystroke is unambiguously wrong; a value range is not one of those.
|
|
108
|
+
|
|
109
|
+
The Enter clamp is exact for a `formValidator`-driven field, because `formValidator.set` is
|
|
110
|
+
imperative and lands before the submit handler runs. For a plain `value`/`onChange` field it is
|
|
111
|
+
best-effort: the consumer's own state update may not have flushed by the time their `onSubmit`
|
|
112
|
+
reads it. If an out-of-range value must be *impossible* to submit rather than merely corrected, add
|
|
113
|
+
a validator — `@ahrowe/form-validation` has no numeric range validator (`minLength`/`maxLength` are
|
|
114
|
+
string length), so write one:
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
const inRange = (min: number, max: number): ValidatorFunction => (value) =>
|
|
118
|
+
typeof value === 'number' && (value < min || value > max)
|
|
119
|
+
? { id: 'range', message: `Must be between ${min} and ${max}` }
|
|
120
|
+
: null;
|
|
121
|
+
|
|
122
|
+
const qty = new FormValidator<number | undefined>(undefined, [inRange(10, 100)]);
|
|
123
|
+
<NumberInput label="Quantity" formValidator={qty} min={10} max={100} showArrows decimalScale={0} />
|
|
124
|
+
```
|
|
61
125
|
|
|
62
126
|
**Mobile keyboard layout:** shows the numeric on-screen keyboard automatically (`inputMode="numeric"` when `decimalScale={0}`, `"decimal"` otherwise, so a decimal separator key is available whenever fractional values are allowed). Pass `inputMode` directly to override.
|