@ahrowe/ui 0.44.0 → 0.46.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/CHANGELOG.md +40 -0
- package/README.md +1 -1
- package/dist/cjs-types/common/button/button.types.d.ts +1 -1
- package/dist/cjs-types/common/configProvider/configProvider.types.d.ts +2 -0
- package/dist/cjs-types/common/kanbanBoard/KanbanBoard.d.ts +1 -1
- package/dist/cjs-types/common/kanbanBoard/KanbanColumn.d.ts +21 -12
- package/dist/cjs-types/common/kanbanBoard/KanbanItem.d.ts +1 -1
- package/dist/cjs-types/common/kanbanBoard/kanbanBoard.types.d.ts +23 -17
- package/dist/cjs-types/common/kanbanBoard/kanbanBoard.utils.d.ts +47 -1
- package/dist/cjs-types/common/stepper/stepper.d.ts +1 -1
- package/dist/cjs-types/common/stepper/stepper.types.d.ts +28 -12
- package/dist/cjs-types/common/themeProvider/theme.types.d.ts +0 -12
- 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/kanbanBoard/KanbanBoard.mjs +3 -2
- package/dist/esm/common/kanbanBoard/KanbanBoard.mjs.map +1 -1
- package/dist/esm/common/kanbanBoard/KanbanColumn.mjs +1 -1
- package/dist/esm/common/kanbanBoard/KanbanColumn.mjs.map +1 -1
- package/dist/esm/common/kanbanBoard/KanbanItem.mjs +1 -1
- package/dist/esm/common/kanbanBoard/KanbanItem.mjs.map +1 -1
- package/dist/esm/common/kanbanBoard/kanbanBoard.module.mjs +1 -1
- package/dist/esm/common/kanbanBoard/kanbanBoard.module.mjs.map +1 -1
- package/dist/esm/common/kanbanBoard/kanbanBoard.utils.mjs +1 -1
- package/dist/esm/common/kanbanBoard/kanbanBoard.utils.mjs.map +1 -1
- package/dist/esm/common/splitButton/splitButton.mjs +1 -1
- package/dist/esm/common/splitButton/splitButton.mjs.map +1 -1
- package/dist/esm/common/stepper/stepper.mjs +1 -1
- package/dist/esm/common/stepper/stepper.mjs.map +1 -1
- package/dist/esm/common/stepper/stepper.module.mjs +1 -1
- package/dist/esm/common/stepper/stepper.module.mjs.map +1 -1
- package/dist/esm/common/stepper/stepper.types.mjs +1 -1
- package/dist/esm/common/stepper/stepper.types.mjs.map +1 -1
- package/dist/esm/index.mjs +1 -1
- package/dist/index.cjs +4 -3
- package/dist/index.cjs.map +1 -1
- package/dist/style.css +1 -1
- package/dist/types/common/button/button.types.d.ts +1 -1
- package/dist/types/common/configProvider/configProvider.types.d.ts +2 -0
- package/dist/types/common/kanbanBoard/KanbanBoard.d.ts +1 -1
- package/dist/types/common/kanbanBoard/KanbanColumn.d.ts +21 -12
- package/dist/types/common/kanbanBoard/KanbanItem.d.ts +1 -1
- package/dist/types/common/kanbanBoard/kanbanBoard.types.d.ts +23 -17
- package/dist/types/common/kanbanBoard/kanbanBoard.utils.d.ts +47 -1
- package/dist/types/common/stepper/stepper.d.ts +1 -1
- package/dist/types/common/stepper/stepper.types.d.ts +28 -12
- package/dist/types/common/themeProvider/theme.types.d.ts +0 -12
- package/docs/Button.md +8 -2
- package/docs/CLAUDE.md +1 -1
- package/docs/ConfigProvider.md +1 -1
- package/docs/KanbanBoard.md +36 -18
- package/docs/SplitButton.md +1 -1
- package/docs/Stepper.md +57 -29
- package/package.json +1 -1
|
@@ -14,8 +14,8 @@ export declare enum ButtonStyleType {
|
|
|
14
14
|
Plain = "plain"
|
|
15
15
|
}
|
|
16
16
|
export declare enum ButtonSize {
|
|
17
|
-
Default = "default",
|
|
18
17
|
Small = "small",
|
|
18
|
+
/** The default. */
|
|
19
19
|
Medium = "medium",
|
|
20
20
|
Large = "large",
|
|
21
21
|
/** Square, padding-free button for a lone icon. Give it its own width/height. */
|
|
@@ -48,6 +48,7 @@ import { RoomDrawerProps } from '../roomDrawer/roomDrawer.types.js';
|
|
|
48
48
|
import { RoomViewerProps } from '../roomViewer/roomViewer.types.js';
|
|
49
49
|
import { PopoverProps } from '../popover/popover.types.js';
|
|
50
50
|
import { ModalProps } from '../modal/modal.types.js';
|
|
51
|
+
import { StepperProps } from '../stepper/stepper.types.js';
|
|
51
52
|
import { Presentation } from '../configProvider/presentation.types.js';
|
|
52
53
|
/**
|
|
53
54
|
* Global default props keyed by component name.
|
|
@@ -131,6 +132,7 @@ export interface ComponentDefaults {
|
|
|
131
132
|
Modal?: Partial<ModalProps>;
|
|
132
133
|
CommandPalette?: Partial<CommandPaletteProps>;
|
|
133
134
|
WeatherIcon?: Partial<WeatherIconProps>;
|
|
135
|
+
Stepper?: Partial<StepperProps>;
|
|
134
136
|
}
|
|
135
137
|
export interface ConfigProviderProps {
|
|
136
138
|
children: React.ReactNode;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { KanbanBoardProps } from './kanbanBoard.types.js';
|
|
2
|
-
declare function KanbanBoard<T = unknown>({ columns, items, renderItem, onChange, dragHandle, getItemLabel, getItemDisabled, renderEmptyColumn, renderColumnActions, reorderableColumns, collapseEmptyColumns, columnMaxHeight, onLoadMore, loadMoreThreshold, className, style, classNames, styles: slotStyles, ...rest }: KanbanBoardProps<T>): import("react").JSX.Element;
|
|
2
|
+
declare function KanbanBoard<T = unknown>({ columns, items, renderItem, onChange, dragHandle, getItemLabel, getItemDisabled, renderEmptyColumn, renderColumnActions, reorderableColumns, collapseEmptyColumns, columnMaxHeight, onLoadMore, loadMoreThreshold, onKeyDown, className, style, classNames, styles: slotStyles, ...rest }: KanbanBoardProps<T>): import("react").JSX.Element;
|
|
3
3
|
export default KanbanBoard;
|
|
@@ -1,25 +1,21 @@
|
|
|
1
|
-
import { ReactNode } from 'react';
|
|
2
|
-
import {
|
|
1
|
+
import { HTMLAttributes, ReactNode, Ref } from 'react';
|
|
2
|
+
import { DataProps, SlotClassNames, SlotStyles } from '../types/slots.types.js';
|
|
3
|
+
import { KanbanColumnProps, KanbanColumnSlots } from './kanbanBoard.types.js';
|
|
3
4
|
interface KanbanColumnInternalProps<T> extends KanbanColumnProps {
|
|
4
5
|
itemIds: string[];
|
|
5
6
|
items: Record<string, T>;
|
|
6
7
|
renderItem: (item: T, id: string) => ReactNode;
|
|
7
8
|
dragHandle?: boolean;
|
|
8
|
-
/**
|
|
9
|
-
|
|
10
|
-
* is in progress: the empty-column collapse is driven by transient shadow state during a
|
|
11
|
-
* drag, and letting the column shrink mid-drag shifts every column's layout underneath the
|
|
12
|
-
* pointer, which can flip the collision target back and forth forever.
|
|
13
|
-
*/
|
|
14
|
-
preserveSizeWhileEmpty?: boolean;
|
|
15
|
-
/** Shrink to a narrow strip when empty — see `KanbanBoardProps.collapseEmptyColumns`. Defaults to `true`. */
|
|
16
|
-
collapseEmptyColumns?: boolean;
|
|
9
|
+
/** Shrink to a narrow strip. The board decides when, see `KanbanBoardProps.collapseEmptyColumns`. */
|
|
10
|
+
collapsed?: boolean;
|
|
17
11
|
/** Work-in-progress limit — see `KanbanColumnDef.maxItems`. Display-only. */
|
|
18
12
|
maxItems?: number;
|
|
19
13
|
/** Freezes the column — see `KanbanColumnDef.disabled`. */
|
|
20
14
|
disabled?: boolean;
|
|
21
15
|
/** Returns whether a specific card can't be picked up — see `KanbanBoardProps.getItemDisabled`. */
|
|
22
16
|
getItemDisabled?: (item: T, id: string) => boolean;
|
|
17
|
+
/** Names a card's drag handle — see `KanbanBoardProps.getItemLabel`. */
|
|
18
|
+
getItemLabel?: (item: T, id: string) => string;
|
|
23
19
|
/** Custom content shown when the column has no cards — see `KanbanBoardProps.renderEmptyColumn`. */
|
|
24
20
|
emptyPlaceholder?: ReactNode;
|
|
25
21
|
/** Custom header actions — see `KanbanBoardProps.renderColumnActions`. */
|
|
@@ -41,5 +37,18 @@ interface KanbanColumnInternalProps<T> extends KanbanColumnProps {
|
|
|
41
37
|
/** Scroll distance from the bottom that triggers `onLoadMore` — see `KanbanBoardProps.loadMoreThreshold`. */
|
|
42
38
|
loadMoreThreshold?: number;
|
|
43
39
|
}
|
|
44
|
-
|
|
40
|
+
interface ColumnHeaderContentProps {
|
|
41
|
+
title: string;
|
|
42
|
+
count: number;
|
|
43
|
+
maxItems?: number;
|
|
44
|
+
actions?: ReactNode;
|
|
45
|
+
/** Makes the title the column's keyboard drag handle. */
|
|
46
|
+
titleProps?: HTMLAttributes<HTMLSpanElement> & DataProps & {
|
|
47
|
+
ref?: Ref<HTMLSpanElement>;
|
|
48
|
+
};
|
|
49
|
+
classNames?: SlotClassNames<KanbanColumnSlots>;
|
|
50
|
+
styles?: SlotStyles<KanbanColumnSlots>;
|
|
51
|
+
}
|
|
52
|
+
export declare function ColumnHeaderContent({ title, count, maxItems, actions, titleProps, classNames, styles: slotStyles, }: ColumnHeaderContentProps): import("react").JSX.Element;
|
|
53
|
+
declare function KanbanColumn<T>({ id, title, itemIds, items, renderItem, dragHandle, collapsed, maxItems, disabled, getItemDisabled, getItemLabel, emptyPlaceholder, actions, reorderable, activeIsColumn, columnMaxHeight, hasMore, onLoadMore, loadMoreThreshold, className, style, classNames, styles: slotStyles, ...rest }: KanbanColumnInternalProps<T>): import("react").JSX.Element;
|
|
45
54
|
export default KanbanColumn;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { KanbanItemProps } from './kanbanBoard.types.js';
|
|
2
|
-
declare function KanbanItem({ id, dragHandle, disabled, preventAsDropTarget, children }: KanbanItemProps): import("react").JSX.Element;
|
|
2
|
+
declare function KanbanItem({ id, label, dragHandle, disabled, preventAsDropTarget, children }: KanbanItemProps): import("react").JSX.Element;
|
|
3
3
|
export default KanbanItem;
|
|
@@ -38,14 +38,17 @@ export interface KanbanBoardProps<T = unknown> extends Omit<HtmlProps, 'onChange
|
|
|
38
38
|
*/
|
|
39
39
|
onChange: (columns: KanbanColumnDef[]) => void;
|
|
40
40
|
/**
|
|
41
|
-
*
|
|
42
|
-
* instead of the whole card.
|
|
43
|
-
*
|
|
41
|
+
* Drag a card only by the element marked `data-drag-handle` inside it, with the mouse, touch
|
|
42
|
+
* and the keyboard, instead of by the whole card. The handle is made focusable and named with
|
|
43
|
+
* `getItemLabel` unless it has a name, and the card stops being a button. Use when `renderItem`
|
|
44
|
+
* includes controls (buttons, inputs): inside a card that is itself the button, a screen reader
|
|
45
|
+
* reads them as plain text.
|
|
44
46
|
*/
|
|
45
47
|
dragHandle?: boolean;
|
|
46
48
|
/**
|
|
47
49
|
* Produce an accessible label for a card, announced to screen-reader users while dragging
|
|
48
|
-
* (e.g. "Picked up <label>.")
|
|
50
|
+
* (e.g. "Picked up <label>."), and naming a `dragHandle` handle that has no name of its own.
|
|
51
|
+
* Defaults to the card's id when omitted.
|
|
49
52
|
*/
|
|
50
53
|
getItemLabel?: (item: T, id: string) => string;
|
|
51
54
|
/**
|
|
@@ -70,27 +73,28 @@ export interface KanbanBoardProps<T = unknown> extends Omit<HtmlProps, 'onChange
|
|
|
70
73
|
*/
|
|
71
74
|
reorderableColumns?: boolean;
|
|
72
75
|
/**
|
|
73
|
-
* Shrink a column to a narrow strip
|
|
74
|
-
*
|
|
75
|
-
* width
|
|
76
|
-
*
|
|
77
|
-
* via `ThemeProvider`'s `variables`, or per board via `style`.
|
|
76
|
+
* Shrink a column to a narrow strip while it has no cards. Defaults to `false`. Widths hold
|
|
77
|
+
* still during a drag: a column the drag empties or fills changes width after the drop. The
|
|
78
|
+
* collapsed width is set via the `--kanban-empty-column-width` CSS variable (falls back to
|
|
79
|
+
* `140px`): override it theme-wide via `ThemeProvider`'s `variables`, or per board via `style`.
|
|
78
80
|
*/
|
|
79
81
|
collapseEmptyColumns?: boolean;
|
|
80
82
|
/**
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
83
|
+
* Caps each column's card list at a length (any CSS length, e.g. `'70vh'`, `'600px'`), so a
|
|
84
|
+
* long column scrolls on its own instead of growing the page. To fill the space your layout
|
|
85
|
+
* gives the board instead, give the board a height (`style={{ height: '100%' }}` in a parent
|
|
86
|
+
* with one): its columns then scroll the same way.
|
|
85
87
|
*/
|
|
86
88
|
columnMaxHeight?: string;
|
|
87
89
|
/**
|
|
88
90
|
* Called with a column's `id` when that column has `hasMore` set and its card list is scrolled
|
|
89
|
-
* within `loadMoreThreshold` of the bottom
|
|
91
|
+
* within `loadMoreThreshold` of the bottom: fetch and append the next page of items for it.
|
|
90
92
|
* `KanbanColumn` tracks its own in-flight state per column (shown as a spinner at the bottom of
|
|
91
|
-
* the list), so overlapping calls for the same column are never made concurrently. Also
|
|
92
|
-
*
|
|
93
|
-
*
|
|
93
|
+
* the list), so overlapping calls for the same column are never made concurrently. Also called
|
|
94
|
+
* while the column's cards leave empty space below them, since a column that doesn't overflow
|
|
95
|
+
* can't be scrolled. Paging all the way needs a column that scrolls: `columnMaxHeight`, or a
|
|
96
|
+
* board with a height. On a board that grows with its cards, a short column only fills up to
|
|
97
|
+
* the tallest one.
|
|
94
98
|
*/
|
|
95
99
|
onLoadMore?: (columnId: string) => void | Promise<void>;
|
|
96
100
|
/**
|
|
@@ -115,6 +119,8 @@ export interface KanbanColumnProps extends HtmlProps {
|
|
|
115
119
|
}
|
|
116
120
|
export interface KanbanItemProps {
|
|
117
121
|
id: string;
|
|
122
|
+
/** Names the card's `[data-drag-handle]` when it has no `aria-label` of its own. */
|
|
123
|
+
label?: string;
|
|
118
124
|
dragHandle?: boolean;
|
|
119
125
|
/** Whether this card can't be picked up (column frozen, or the card itself is pinned). */
|
|
120
126
|
disabled?: boolean;
|
|
@@ -20,8 +20,28 @@ export declare function moveColumn(columns: KanbanColumnDef[], activeColumnId: s
|
|
|
20
20
|
* which reads as needing to "wiggle it around" before the right drop target lights up. This
|
|
21
21
|
* restricts the candidates to only the same kind as whatever is being dragged: a column drag only
|
|
22
22
|
* considers other columns, a card drag only considers cards and card lists.
|
|
23
|
+
*
|
|
24
|
+
* A card drag also lets the pointer pick the column, and `closestCorners` only the position within
|
|
25
|
+
* it. Corners alone compare the dragged card's whole rect, so a wide card over a collapsed column
|
|
26
|
+
* had its corners nearer the neighbours' cards, and landed beside the column under the pointer.
|
|
27
|
+
* Without a pointer (the keyboard) or between columns, every column is a candidate as before.
|
|
23
28
|
*/
|
|
24
29
|
export declare const kanbanCollisionDetection: CollisionDetection;
|
|
30
|
+
/**
|
|
31
|
+
* Whether the auto-scroll may move `scroller`, an ancestor of the board such as the page, while
|
|
32
|
+
* something is dragged: only toward a part of the board that is out of view. Nothing beyond the
|
|
33
|
+
* board takes a drop, and a page left free to scroll carried the whole board off screen.
|
|
34
|
+
*/
|
|
35
|
+
export declare function scrollsTowardBoard(scroller: {
|
|
36
|
+
top: number;
|
|
37
|
+
bottom: number;
|
|
38
|
+
}, board: {
|
|
39
|
+
top: number;
|
|
40
|
+
bottom: number;
|
|
41
|
+
}, dragged: {
|
|
42
|
+
top: number;
|
|
43
|
+
height: number;
|
|
44
|
+
}): boolean;
|
|
25
45
|
/** Extracts the column id from a column droppable's `column-<id>` identifier, or `null` for a card id. */
|
|
26
46
|
export declare function resolveColumnDropId(overId: string): string | null;
|
|
27
47
|
export interface DragGeometry {
|
|
@@ -40,9 +60,35 @@ export interface DragGeometry {
|
|
|
40
60
|
* position (see the two branches below for what each one decides).
|
|
41
61
|
*/
|
|
42
62
|
export declare function moveItem(columns: KanbanColumnDef[], activeItemId: string, overId: string, geometry: DragGeometry): KanbanColumnDef[];
|
|
63
|
+
/**
|
|
64
|
+
* Where a drag has put the dragged card or column so far. The board keeps this rather than a copy
|
|
65
|
+
* of `columns`, so a change the consumer makes mid-drag (a page appended by `onLoadMore`) still
|
|
66
|
+
* shows, and is still there in what `onChange` receives on drop.
|
|
67
|
+
*/
|
|
68
|
+
export interface DragPlacement {
|
|
69
|
+
/** The dragged card's or column's id. */
|
|
70
|
+
id: string;
|
|
71
|
+
/** The column the card sits in, or `null` while a whole column is dragged. */
|
|
72
|
+
columnId: string | null;
|
|
73
|
+
index: number;
|
|
74
|
+
}
|
|
75
|
+
/** The position `id` holds in `columns`, as a placement to lay over a later `columns`. */
|
|
76
|
+
export declare function findPlacement(columns: KanbanColumnDef[], id: string, isColumn: boolean): DragPlacement | null;
|
|
77
|
+
/**
|
|
78
|
+
* Moves the dragged card or column to its placement in `columns`. Returns `columns` itself when
|
|
79
|
+
* there is no placement, or when the card, the column, or its destination is no longer there.
|
|
80
|
+
*/
|
|
81
|
+
export declare function applyPlacement(columns: KanbanColumnDef[], placement: DragPlacement | null): KanbanColumnDef[];
|
|
82
|
+
/**
|
|
83
|
+
* Where an arrow key moves focus from a focused card or column handle while nothing is picked up.
|
|
84
|
+
* It mirrors what the same keys do to a picked-up card: Up/Down within the column, Left/Right to
|
|
85
|
+
* the nearest card in the next column with anything to focus, or from a handle to the next handle.
|
|
86
|
+
* Returns `null` when `from` is not a card or handle, or there is nowhere to go.
|
|
87
|
+
*/
|
|
88
|
+
export declare function findArrowFocusTarget(board: HTMLElement, from: HTMLElement, key: string): HTMLElement | null;
|
|
43
89
|
/**
|
|
44
90
|
* Builds screen-reader drag announcements against the columns layout as currently understood
|
|
45
|
-
* (the live
|
|
91
|
+
* (the live layout while a drag is in progress, or the settled `columns` prop otherwise).
|
|
46
92
|
*/
|
|
47
93
|
export declare function buildAnnouncements<T>(columns: KanbanColumnDef[], items: Record<string, T>, getItemLabel: (item: T, id: string) => string): Announcements;
|
|
48
94
|
/**
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
import { StepperProps } from './stepper.types.js';
|
|
3
|
-
export default function Stepper(
|
|
3
|
+
export default function Stepper(props: StepperProps): React.JSX.Element;
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
import { IconContent } from '../types/icon.types.js';
|
|
3
3
|
import { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types.js';
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
import { ColorValue } from '../themeProvider/color.types.js';
|
|
5
|
+
/** Direction the steps run in. */
|
|
6
|
+
export declare enum StepperOrientation {
|
|
6
7
|
Horizontal = "horizontal",
|
|
7
8
|
Vertical = "vertical"
|
|
8
9
|
}
|
|
9
|
-
/**
|
|
10
|
+
/** How the step markers are drawn. */
|
|
10
11
|
export declare enum StepperStyleType {
|
|
11
|
-
/** Numbered markers, filled solid on completion
|
|
12
|
-
|
|
13
|
-
/** Numbered markers that stay ringed when completed
|
|
12
|
+
/** Numbered markers, filled solid on completion. The default. */
|
|
13
|
+
Filled = "filled",
|
|
14
|
+
/** Numbered markers that stay ringed when completed, with a check in the colour. */
|
|
14
15
|
Outlined = "outlined",
|
|
15
16
|
/** Minimal dots without numbers, for a compact onboarding or carousel style. */
|
|
16
17
|
Dots = "dots"
|
|
@@ -39,6 +40,16 @@ export declare enum StepperLabelPlacement {
|
|
|
39
40
|
Right = "right"
|
|
40
41
|
}
|
|
41
42
|
export type StepperSlots = 'root' | 'entry' | 'entryNumber' | 'entryLabel' | 'connector' | 'description' | 'content' | 'optional' | 'icon';
|
|
43
|
+
export interface StepperLabels {
|
|
44
|
+
/** Hint under the label of a step with `optional: true`. */
|
|
45
|
+
optional?: string;
|
|
46
|
+
/** Status of a completed step, read out by screen readers. */
|
|
47
|
+
completed?: string;
|
|
48
|
+
/** Status of a step not reached yet, read out by screen readers. */
|
|
49
|
+
notCompleted?: string;
|
|
50
|
+
/** Status of a step with `error`, read out by screen readers. */
|
|
51
|
+
error?: string;
|
|
52
|
+
}
|
|
42
53
|
export interface StepperStep {
|
|
43
54
|
/** Primary label for the step. */
|
|
44
55
|
label: React.ReactNode;
|
|
@@ -48,28 +59,33 @@ export interface StepperStep {
|
|
|
48
59
|
content?: React.ReactNode;
|
|
49
60
|
/** Icon shown in the marker instead of the step number — a FontAwesome icon or any node. */
|
|
50
61
|
icon?: IconContent;
|
|
51
|
-
/** Marks the step as errored,
|
|
62
|
+
/** Marks the step as errored, drawing its marker in the theme's `--error-color`. */
|
|
52
63
|
error?: boolean;
|
|
53
|
-
/** `true` renders
|
|
64
|
+
/** `true` renders the `optional` label as a hint; a node renders custom hint text. */
|
|
54
65
|
optional?: boolean | React.ReactNode;
|
|
55
66
|
/** Disables this step: never clickable, dimmed. */
|
|
56
67
|
disabled?: boolean;
|
|
57
68
|
}
|
|
58
|
-
export interface StepperProps extends HtmlProps {
|
|
69
|
+
export interface StepperProps extends HtmlProps<HTMLOListElement> {
|
|
59
70
|
steps?: StepperStep[];
|
|
71
|
+
/** Zero-based index of the current step. `steps.length` marks every step completed. */
|
|
60
72
|
currentStep?: number;
|
|
61
|
-
|
|
73
|
+
/** Direction the steps run in (default `Horizontal`). */
|
|
74
|
+
orientation?: StepperOrientation;
|
|
62
75
|
onStepClicked?: ((index: number) => void) | null;
|
|
63
76
|
/** Allow clicking any step, not just completed ones. */
|
|
64
77
|
nonLinear?: boolean;
|
|
65
|
-
/** Hide
|
|
78
|
+
/** Hide each step's label, description and hint visually. Screen readers still read them. */
|
|
66
79
|
hideLabels?: boolean;
|
|
67
|
-
/**
|
|
80
|
+
/** How the markers are drawn (default `Filled`). */
|
|
68
81
|
styleType?: StepperStyleType;
|
|
82
|
+
/** A `ThemeColor` (default `Primary`) or any CSS colour, such as `'var(--brand)'`. */
|
|
83
|
+
color?: ColorValue;
|
|
69
84
|
/** Which step bodies are expanded. Vertical `content` only (default `None`). */
|
|
70
85
|
collapse?: StepperCollapse;
|
|
71
86
|
/** Label position relative to the marker (default: horizontal `Bottom`, vertical `Right`). */
|
|
72
87
|
labelPlacement?: StepperLabelPlacement;
|
|
88
|
+
labels?: StepperLabels;
|
|
73
89
|
className?: string;
|
|
74
90
|
style?: React.CSSProperties;
|
|
75
91
|
classNames?: SlotClassNames<StepperSlots>;
|
|
@@ -125,24 +125,12 @@ export interface ThemeVariables {
|
|
|
125
125
|
'--stepper-marker-size'?: string;
|
|
126
126
|
/** Step marker corner radius. Falls back to --default-border-radius. */
|
|
127
127
|
'--stepper-marker-radius'?: string;
|
|
128
|
-
/** Idle (upcoming) marker/connector colour. Falls back to --primary-lighter. */
|
|
129
|
-
'--stepper-idle-color'?: string;
|
|
130
|
-
/** Current-step marker colour. Falls back to --primary-color. */
|
|
131
|
-
'--stepper-active-color'?: string;
|
|
132
|
-
/** Completed-step marker fill/colour. Falls back to --primary-color. */
|
|
133
|
-
'--stepper-done-color'?: string;
|
|
134
|
-
/** Errored-step marker colour. Falls back to --error-color. */
|
|
135
|
-
'--stepper-error-color'?: string;
|
|
136
|
-
/** Completed connector colour. Falls back to --primary-color. */
|
|
137
|
-
'--stepper-connector-color'?: string;
|
|
138
128
|
/** Completed connector thickness. Falls back to 3px. */
|
|
139
129
|
'--stepper-connector-thickness'?: string;
|
|
140
130
|
/** Not-yet-reached connector thickness. Falls back to 1px. */
|
|
141
131
|
'--stepper-connector-idle-thickness'?: string;
|
|
142
132
|
/** Gap between marker and label, and grid column gap. Falls back to 12px. */
|
|
143
133
|
'--stepper-gap'?: string;
|
|
144
|
-
/** Text/check colour on a filled marker. Falls back to --text-on-primary. */
|
|
145
|
-
'--stepper-text-on-marker'?: string;
|
|
146
134
|
/** Timer ring track (unfilled) colour. Falls back to --background-accent-light. */
|
|
147
135
|
'--timer-track-color'?: string;
|
|
148
136
|
/** Timer ring progress (remaining time) colour. Falls back to --primary-color. */
|
package/docs/Button.md
CHANGED
|
@@ -69,7 +69,7 @@ import { faPlus, faSave, faTrash, faXmark } from '@fortawesome/free-solid-svg-ic
|
|
|
69
69
|
|
|
70
70
|
- `ButtonStyleType`: `Filled` | `Light` | `Outlined` (default) | `Plain`
|
|
71
71
|
- `ThemeColor`: `Primary` (default) | `Neutral` | `Success` | `Info` | `Warn` | `Error`
|
|
72
|
-
- `ButtonSize`: `
|
|
72
|
+
- `ButtonSize`: `Small` | `Medium` (default) | `Large` | `Icon`
|
|
73
73
|
- `ButtonType`: `Button` | `Reset` | `Submit`
|
|
74
74
|
|
|
75
75
|
**Key props:**
|
|
@@ -119,10 +119,16 @@ so an icon is never cut off by a flexible sibling. A multi-word label still wrap
|
|
|
119
119
|
|
|
120
120
|
## Sizing
|
|
121
121
|
|
|
122
|
-
A Button is sized by its font. `--default-font-size` is the base, and `Small` and `Large` are multiples of it (0.75x and 1.25x), so a theme with a smaller base font gets proportionally smaller controls everywhere. Padding and the icon gap are in `em`, so the whole box grows with the label rather than a large button wearing a
|
|
122
|
+
A Button is sized by its font. `--default-font-size` is the base, `Medium` is that size, and `Small` and `Large` are multiples of it (0.75x and 1.25x), so a theme with a smaller base font gets proportionally smaller controls everywhere. Padding and the icon gap are in `em`, so the whole box grows with the label rather than a large button wearing a medium button's padding.
|
|
123
123
|
|
|
124
124
|
`ButtonSize.Icon` is the exception: it inherits the surrounding text size and has no padding at all, because the caller sets the box.
|
|
125
125
|
|
|
126
|
+
## Migration from `ButtonSize.Default`
|
|
127
|
+
|
|
128
|
+
Before 0.45, `ButtonSize.Default` was a second name for `Medium`, which is now the default. Replace
|
|
129
|
+
`size={ButtonSize.Default}` with `size={ButtonSize.Medium}`, or leave the prop out. The look does
|
|
130
|
+
not change.
|
|
131
|
+
|
|
126
132
|
## Migration from `Primary`, `Default` and `Delete`
|
|
127
133
|
|
|
128
134
|
Before 0.43, `styleType` set emphasis and colour in one value. `Primary`, `Default` and `Delete` no
|
package/docs/CLAUDE.md
CHANGED
|
@@ -128,7 +128,7 @@ enums and slot names. Do not infer props from a component's name.
|
|
|
128
128
|
| Skeleton.md | Skeleton, SkeletonVariant, SkeletonAnimation | Content-shaped loading placeholder, shown while real content is being fetched — more polished than a Loader for content-heavy pages (lists, cards, profile headers) |
|
|
129
129
|
| Slider.md | Slider | Let the user pick a number from a continuous or stepped range by dragging a thumb: volume, brightness, price ranges, zoom, quality presets |
|
|
130
130
|
| SplitButton.md | SplitButton | A primary action button with a small attached dropdown for closely related secondary actions, e.g. "Save ▾" opening "Save as draft" / "Save and close" |
|
|
131
|
-
| Stepper.md | Stepper | Step progress indicator for multi-step forms, onboarding flows, and checkout wizards |
|
|
131
|
+
| Stepper.md | Stepper, StepperOrientation, StepperStyleType, StepperCollapse, StepperLabelPlacement, ThemeColor | Step progress indicator for multi-step forms, onboarding flows, and checkout wizards |
|
|
132
132
|
| Sticky.md | Sticky | Pin a piece of content to the top of the viewport once the page scrolls past it — section headers, toolbars, filter bars, table headers |
|
|
133
133
|
| Switch.md | Switch | Sliding boolean toggle — settings panels, feature flags, preference lists |
|
|
134
134
|
| TabHeader.md | TabHeader | A horizontal row of tabs to switch between sibling views or sections — settings panels, dashboards, detail pages |
|
package/docs/ConfigProvider.md
CHANGED
|
@@ -95,7 +95,7 @@ A nested provider inherits it unless it sets its own, the same way `defaultProps
|
|
|
95
95
|
Each entry is a `Partial<...Props>`, so any of that component's props can be defaulted:
|
|
96
96
|
|
|
97
97
|
- **Form inputs:** `Input` · `Textarea` · `NumberInput` · `Dropdown` · `InputDropdown` · `Checkbox` · `Switch` · `RadioGroup` · `DatePicker` · `OptionPicker` · `OtpInput`
|
|
98
|
-
- **Display:** `Button` · `CopyButton` · `ActionButtons` · `Badge` · `Chip` · `Card` · `SectionHeader` · `Skeleton` · `Loader` · `LoadingOverlay` · `Accordion` · `Divider` · `Timer` · `WeatherIcon`
|
|
98
|
+
- **Display:** `Button` · `CopyButton` · `ActionButtons` · `Badge` · `Chip` · `Card` · `SectionHeader` · `Skeleton` · `Loader` · `LoadingOverlay` · `Accordion` · `Divider` · `Timer` · `WeatherIcon` · `Stepper`
|
|
99
99
|
- **Overlays:** `ConfirmModal` · `Modal` · `CommandPalette` · `Popover`
|
|
100
100
|
- **Editors:** `RoomDrawer`, `RoomViewer`
|
|
101
101
|
- **Scheduling:** `Calendar`, for `labels`, `locale`, `weekStartsOn`, `slotMinutes`, `views`, `hiddenDays`, `scrollToHour`, `workingHours` and `showWeekNumbers` only (see below)
|
package/docs/KanbanBoard.md
CHANGED
|
@@ -37,13 +37,14 @@ const items: Record<string, Task> = {
|
|
|
37
37
|
onChange={(updatedColumns) => setColumns(updatedColumns)}
|
|
38
38
|
/>
|
|
39
39
|
|
|
40
|
-
//
|
|
41
|
-
//
|
|
42
|
-
//
|
|
40
|
+
// Drag by a handle instead of the whole card: needed when a card contains its own
|
|
41
|
+
// controls (buttons, inputs). The handle is also the card's keyboard handle, named
|
|
42
|
+
// with getItemLabel, so the card is not one button wrapped around the Delete button
|
|
43
43
|
<KanbanBoard
|
|
44
44
|
columns={columns}
|
|
45
45
|
items={items}
|
|
46
46
|
dragHandle
|
|
47
|
+
getItemLabel={(task) => task.title}
|
|
47
48
|
renderItem={(task, id) => (
|
|
48
49
|
<div className="task-card">
|
|
49
50
|
<span data-drag-handle>⠿</span>
|
|
@@ -128,18 +129,33 @@ const columnsWithLock: KanbanColumnDef[] = [
|
|
|
128
129
|
onChange={(updatedColumns) => setColumns(updatedColumns)}
|
|
129
130
|
/>
|
|
130
131
|
|
|
131
|
-
//
|
|
132
|
-
//
|
|
132
|
+
// Shrink a column with no cards to a narrow strip. Widths hold still during a drag,
|
|
133
|
+
// so a column the drag empties or fills changes width once the card is dropped
|
|
133
134
|
<KanbanBoard
|
|
134
135
|
columns={columns}
|
|
135
136
|
items={items}
|
|
136
137
|
renderItem={(task) => <div className="task-card"><strong>{task.title}</strong></div>}
|
|
137
|
-
collapseEmptyColumns
|
|
138
|
+
collapseEmptyColumns
|
|
138
139
|
onChange={(updatedColumns) => setColumns(updatedColumns)}
|
|
139
140
|
/>
|
|
140
141
|
|
|
141
|
-
//
|
|
142
|
-
//
|
|
142
|
+
// Fill the height your layout gives the board, like a full-screen board app: give the
|
|
143
|
+
// board a height and each column scrolls on its own inside it. Here the board takes
|
|
144
|
+
// what the header leaves of the window (minHeight: 0 lets a flex child shrink below
|
|
145
|
+
// its content)
|
|
146
|
+
<div style={{ display: 'flex', flexDirection: 'column', height: '100vh' }}>
|
|
147
|
+
<AppHeader />
|
|
148
|
+
<KanbanBoard
|
|
149
|
+
columns={columns}
|
|
150
|
+
items={items}
|
|
151
|
+
renderItem={(task) => <div className="task-card"><strong>{task.title}</strong></div>}
|
|
152
|
+
style={{ flex: 1, minHeight: 0 }}
|
|
153
|
+
onChange={(updatedColumns) => setColumns(updatedColumns)}
|
|
154
|
+
/>
|
|
155
|
+
</div>
|
|
156
|
+
|
|
157
|
+
// Or cap each column at a length, so a long column scrolls on its own instead of
|
|
158
|
+
// growing the page, while a board of short columns stays short
|
|
143
159
|
<KanbanBoard
|
|
144
160
|
columns={columns}
|
|
145
161
|
items={items}
|
|
@@ -148,12 +164,12 @@ const columnsWithLock: KanbanColumnDef[] = [
|
|
|
148
164
|
onChange={(updatedColumns) => setColumns(updatedColumns)}
|
|
149
165
|
/>
|
|
150
166
|
|
|
151
|
-
// Paginate a column instead of loading everything up front
|
|
167
|
+
// Paginate a column instead of loading everything up front: mark it `hasMore`
|
|
152
168
|
// and fetch/append the next page in `onLoadMore` once it's scrolled near the
|
|
153
|
-
// bottom.
|
|
169
|
+
// bottom. Needs a column that scrolls: `columnMaxHeight` or a board with a height.
|
|
154
170
|
// KanbanBoard tracks its own in-flight state per column (shown as a spinner at
|
|
155
|
-
// the bottom of the list) and
|
|
156
|
-
//
|
|
171
|
+
// the bottom of the list) and asks again while a column's cards leave empty space
|
|
172
|
+
// below them, so pagination doesn't dead-end on a short first batch.
|
|
157
173
|
const columnsPaged: KanbanColumnDef[] = [
|
|
158
174
|
{ id: 'done', title: 'Done', itemIds: doneTaskIds, hasMore: doneHasMore },
|
|
159
175
|
];
|
|
@@ -171,10 +187,12 @@ const columnsPaged: KanbanColumnDef[] = [
|
|
|
171
187
|
/>
|
|
172
188
|
```
|
|
173
189
|
|
|
174
|
-
**Keyboard support:** cards are focusable and
|
|
190
|
+
**Keyboard support:** cards are focusable, and the arrow keys move focus between them while nothing is picked up: Up/Down within a column, Left/Right to the nearest card in the next column. Space or Enter picks a card up, Space or Enter again drops it, and Escape cancels (reverts to the original position). While a card is picked up, the same arrow keys move the card instead: Up/Down reorders it within its column; Left/Right moves it into the adjacent column, landing on the nearest card there (or the column itself, if it's empty). This uses a board-aware coordinate getter rather than `dnd-kit`'s generic `sortableKeyboardCoordinates`, which, across multiple per-column `SortableContext`s, can't reliably tell "next card in this column" from "some other column's droppable" and ends up mixing up Up/Down and Left/Right. With `reorderableColumns`, each column's title is focusable too and joins the arrow-key navigation (Left/Right goes title to title, Up/Down between the title and the column's cards): Space/Enter picks the column up and Left/Right moves it. Keys pressed in a control inside a card or header, such as a `renderColumnActions` button or an input in a card, go to that control and never start a drag.
|
|
175
191
|
|
|
176
192
|
**Column reordering (`reorderableColumns`):** a column's header becomes its drag handle for moving the whole column — dragging the cards area still only moves cards. This shares the same `DndContext` as card dragging (mouse, touch, and keyboard all work the same way), and commits through the same `onChange` — a column move is just a reordering of the `columns` array, same as any other change.
|
|
177
193
|
|
|
194
|
+
**Scrolling while dragging:** holding a card near the edge of a column's card list scrolls that list. The page scrolls only toward a part of the board that is out of view, and stops once the board's edge is on screen, since nothing outside the board takes a drop.
|
|
195
|
+
|
|
178
196
|
**Screen-reader announcements:** every pick-up, hover, drop, and cancel is announced (e.g. "Picked up card Design mockup.", "Card Design mockup is over the In Progress column."). By default cards are announced by their id — pass `getItemLabel` to announce something meaningful instead (a title, a short description).
|
|
179
197
|
|
|
180
198
|
**KanbanBoardProps:**
|
|
@@ -185,15 +203,15 @@ const columnsPaged: KanbanColumnDef[] = [
|
|
|
185
203
|
| `items` | `Record<string, T>` | Flat map of all items keyed by id |
|
|
186
204
|
| `renderItem` | `(item: T, id: string) => ReactNode` | Render function for each item |
|
|
187
205
|
| `onChange` | `(columns: KanbanColumnDef[]) => void` | Called after a drop that actually changes column or order — replace state with this value |
|
|
188
|
-
| `dragHandle` | `boolean` |
|
|
189
|
-
| `getItemLabel` | `(item: T, id: string) => string` | Accessible label for a card, used in screen-reader drag announcements. Defaults to the card's id |
|
|
206
|
+
| `dragHandle` | `boolean` | Drag a card only by the element marked `data-drag-handle` inside it (mouse, touch and keyboard), instead of by the whole card. The board makes the handle focusable and names it with `getItemLabel` unless it has an `aria-label`, and the card stops being a button. Use when `renderItem` includes controls: without it the whole card is one button, its text can't be selected, and a screen reader reads controls inside it as plain text |
|
|
207
|
+
| `getItemLabel` | `(item: T, id: string) => string` | Accessible label for a card, used in screen-reader drag announcements and as the name of a `dragHandle` handle without one. Defaults to the card's id |
|
|
190
208
|
| `getItemDisabled` | `(item: T, id: string) => boolean` | Returns whether a specific card can't be picked up. Defaults to every card being draggable; independent of a column's own `disabled`. A pinned card stays a valid drop target — other cards can still be reordered before/after it, unlike a card inside a fully frozen (`disabled`) column |
|
|
191
209
|
| `renderEmptyColumn` | `(column: KanbanColumnDef) => ReactNode` | Custom content shown inside a column when it has no cards, instead of leaving it blank |
|
|
192
210
|
| `renderColumnActions` | `(column: KanbanColumnDef) => ReactNode` | Custom actions rendered in a column's header, next to its title (e.g. an "add card" button, a column menu) |
|
|
193
211
|
| `reorderableColumns` | `boolean` | Allow whole columns to be reordered by dragging their header, alongside card dragging (default `false`) |
|
|
194
|
-
| `collapseEmptyColumns` | `boolean` | Shrink a column to a narrow strip
|
|
195
|
-
| `columnMaxHeight` | `string` |
|
|
196
|
-
| `onLoadMore` | `(columnId: string) => void \| Promise<void>` | Called when a column with `hasMore` is scrolled within `loadMoreThreshold` of the bottom
|
|
212
|
+
| `collapseEmptyColumns` | `boolean` | Shrink a column to a narrow strip while it has no cards (default `false`). Widths hold still during a drag: a column the drag empties or fills changes width after the drop. The collapsed width is set via `--kanban-empty-column-width` (falls back to `140px`); override it theme-wide via `ThemeProvider`, or per board via `style` |
|
|
213
|
+
| `columnMaxHeight` | `string` | Caps each column's card list at a length (any CSS length, e.g. `'70vh'`), so a long column scrolls on its own instead of growing the page. Unset by default. To fill the space your layout gives the board instead, give the board a height (`style={{ height: '100%' }}` in a parent with one, or `flex: 1; min-height: 0` in a flex column): its columns then scroll the same way |
|
|
214
|
+
| `onLoadMore` | `(columnId: string) => void \| Promise<void>` | Called when a column with `hasMore` is scrolled within `loadMoreThreshold` of the bottom: fetch and append the next page for that column. Tracked per column, so overlapping calls for the same column are never made concurrently. Also called while the column's cards leave empty space below them. Paging all the way needs a column that scrolls (`columnMaxHeight` or a board with a height); on a board that grows with its cards, a short column only fills up to the tallest one |
|
|
197
215
|
| `loadMoreThreshold` | `number` | Distance in px from the bottom of a column's scroll area that triggers `onLoadMore` (default `100`, matching `VirtualList`) |
|
|
198
216
|
| `id` / `role` / `aria-*` / `data-*` | | Passed through to the root element |
|
|
199
217
|
|
package/docs/SplitButton.md
CHANGED
|
@@ -70,7 +70,7 @@ import { ButtonStyleType } from '@ahrowe/ui';
|
|
|
70
70
|
| `actions` | `SplitButtonAction[]` | Secondary actions shown in the dropdown |
|
|
71
71
|
| `styleType` | `ButtonStyleType` | Shared by both the primary and trigger button (default `Filled`) |
|
|
72
72
|
| `color` | `ColorValue` | Shared by both buttons (default `Primary`); or any CSS colour, as on Button |
|
|
73
|
-
| `size` | `ButtonSize` | Size variant, shared by both buttons |
|
|
73
|
+
| `size` | `ButtonSize` | Size variant, shared by both buttons (default `Medium`) |
|
|
74
74
|
| `disabled` | `boolean` | Disables both the primary and trigger button |
|
|
75
75
|
| `isLoading` | `boolean` | Shows a spinner on the primary button (same as `Button`'s own `isLoading`) |
|
|
76
76
|
| `align` | `PopoverAlign` | Which edge of the group the menu lines up with (default `End`, the chevron's side). The menu is a [Menu](Menu.md), hence `Popover`'s enum |
|