ionbase-ui 0.51.0 → 0.69.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/components/Accordion.d.ts +54 -0
- package/dist/components/Accordion.d.ts.map +1 -0
- package/dist/components/Accordion.js +68 -0
- package/dist/components/Accordion.js.map +1 -0
- package/dist/components/AgentActivity.d.ts +2 -1
- package/dist/components/AgentActivity.d.ts.map +1 -1
- package/dist/components/AgentActivity.js +4 -17
- package/dist/components/AgentActivity.js.map +1 -1
- package/dist/components/Breadcrumb.d.ts +45 -0
- package/dist/components/Breadcrumb.d.ts.map +1 -0
- package/dist/components/Breadcrumb.js +31 -0
- package/dist/components/Breadcrumb.js.map +1 -0
- package/dist/components/Calendar.d.ts +20 -0
- package/dist/components/Calendar.d.ts.map +1 -0
- package/dist/components/Calendar.js +151 -0
- package/dist/components/Calendar.js.map +1 -0
- package/dist/components/CalendarPopover.d.ts +26 -0
- package/dist/components/CalendarPopover.d.ts.map +1 -0
- package/dist/components/CalendarPopover.js +45 -0
- package/dist/components/CalendarPopover.js.map +1 -0
- package/dist/components/Checkbox.d.ts +2 -1
- package/dist/components/Checkbox.d.ts.map +1 -1
- package/dist/components/Checkbox.js +4 -2
- package/dist/components/Checkbox.js.map +1 -1
- package/dist/components/Combobox.d.ts +86 -0
- package/dist/components/Combobox.d.ts.map +1 -0
- package/dist/components/Combobox.js +261 -0
- package/dist/components/Combobox.js.map +1 -0
- package/dist/components/DateField.d.ts +15 -0
- package/dist/components/DateField.d.ts.map +1 -0
- package/dist/components/DateField.js +74 -0
- package/dist/components/DateField.js.map +1 -0
- package/dist/components/DatePicker.d.ts +81 -0
- package/dist/components/DatePicker.d.ts.map +1 -0
- package/dist/components/DatePicker.js +102 -0
- package/dist/components/DatePicker.js.map +1 -0
- package/dist/components/DateRangePicker.d.ts +117 -0
- package/dist/components/DateRangePicker.d.ts.map +1 -0
- package/dist/components/DateRangePicker.js +152 -0
- package/dist/components/DateRangePicker.js.map +1 -0
- package/dist/components/Drawer.d.ts +52 -0
- package/dist/components/Drawer.d.ts.map +1 -0
- package/dist/components/Drawer.js +66 -0
- package/dist/components/Drawer.js.map +1 -0
- package/dist/components/FileUpload.d.ts +79 -0
- package/dist/components/FileUpload.d.ts.map +1 -0
- package/dist/components/FileUpload.js +218 -0
- package/dist/components/FileUpload.js.map +1 -0
- package/dist/components/Header.d.ts +10 -0
- package/dist/components/Header.d.ts.map +1 -1
- package/dist/components/Header.js +18 -3
- package/dist/components/Header.js.map +1 -1
- package/dist/components/NumberInput.d.ts +63 -0
- package/dist/components/NumberInput.d.ts.map +1 -0
- package/dist/components/NumberInput.js +102 -0
- package/dist/components/NumberInput.js.map +1 -0
- package/dist/components/ProgressBar.d.ts +46 -0
- package/dist/components/ProgressBar.d.ts.map +1 -0
- package/dist/components/ProgressBar.js +52 -0
- package/dist/components/ProgressBar.js.map +1 -0
- package/dist/components/PromptInput.d.ts +89 -0
- package/dist/components/PromptInput.d.ts.map +1 -0
- package/dist/components/PromptInput.js +130 -0
- package/dist/components/PromptInput.js.map +1 -0
- package/dist/components/SegmentedControl.d.ts +63 -0
- package/dist/components/SegmentedControl.d.ts.map +1 -0
- package/dist/components/SegmentedControl.js +79 -0
- package/dist/components/SegmentedControl.js.map +1 -0
- package/dist/components/Select.d.ts +9 -2
- package/dist/components/Select.d.ts.map +1 -1
- package/dist/components/Select.js.map +1 -1
- package/dist/components/Sidebar.d.ts +109 -0
- package/dist/components/Sidebar.d.ts.map +1 -0
- package/dist/components/Sidebar.js +106 -0
- package/dist/components/Sidebar.js.map +1 -0
- package/dist/components/Skeleton.d.ts +39 -0
- package/dist/components/Skeleton.d.ts.map +1 -0
- package/dist/components/Skeleton.js +50 -0
- package/dist/components/Skeleton.js.map +1 -0
- package/dist/components/Spinner.d.ts +45 -0
- package/dist/components/Spinner.d.ts.map +1 -0
- package/dist/components/Spinner.js +44 -0
- package/dist/components/Spinner.js.map +1 -0
- package/dist/components/Stepper.d.ts +73 -0
- package/dist/components/Stepper.d.ts.map +1 -0
- package/dist/components/Stepper.js +82 -0
- package/dist/components/Stepper.js.map +1 -0
- package/dist/components/Toggle.d.ts +2 -1
- package/dist/components/Toggle.d.ts.map +1 -1
- package/dist/components/Toggle.js +4 -2
- package/dist/components/Toggle.js.map +1 -1
- package/dist/components/ToolCall.d.ts +66 -0
- package/dist/components/ToolCall.d.ts.map +1 -0
- package/dist/components/ToolCall.js +78 -0
- package/dist/components/ToolCall.js.map +1 -0
- package/dist/components/agent-status.d.ts +14 -0
- package/dist/components/agent-status.d.ts.map +1 -0
- package/dist/components/agent-status.js +16 -0
- package/dist/components/agent-status.js.map +1 -0
- package/dist/components/index.d.ts +33 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +16 -0
- package/dist/components/index.js.map +1 -1
- package/dist/components/iso-date.d.ts +53 -0
- package/dist/components/iso-date.d.ts.map +1 -0
- package/dist/components/iso-date.js +102 -0
- package/dist/components/iso-date.js.map +1 -0
- package/dist/components/resolve-selection.d.ts +36 -0
- package/dist/components/resolve-selection.d.ts.map +1 -0
- package/dist/components/resolve-selection.js +14 -0
- package/dist/components/resolve-selection.js.map +1 -0
- package/dist/figma-descriptions.json +255 -145
- package/dist/figma-map.json +3205 -1860
- package/dist/meta/Accordion.json +123 -0
- package/dist/meta/AccordionItem.json +90 -0
- package/dist/meta/AgentActivityStep.json +2 -2
- package/dist/meta/Breadcrumb.json +87 -0
- package/dist/meta/BreadcrumbItem.json +78 -0
- package/dist/meta/Checkbox.json +18 -1
- package/dist/meta/Combobox.json +265 -0
- package/dist/meta/DatePicker.json +270 -0
- package/dist/meta/DateRangePicker.json +284 -0
- package/dist/meta/Drawer.json +234 -0
- package/dist/meta/EmptyState.json +1 -1
- package/dist/meta/FileUpload.json +246 -0
- package/dist/meta/Header.json +32 -2
- package/dist/meta/NumberInput.json +407 -0
- package/dist/meta/PhoneInput.json +39 -39
- package/dist/meta/Popover.json +3 -3
- package/dist/meta/ProgressBar.json +166 -0
- package/dist/meta/PromptInput.json +212 -0
- package/dist/meta/SegmentedControl.json +217 -0
- package/dist/meta/SegmentedControlItem.json +122 -0
- package/dist/meta/Select.json +4 -3
- package/dist/meta/Sidebar.json +150 -0
- package/dist/meta/SidebarItem.json +184 -0
- package/dist/meta/SidebarSection.json +131 -0
- package/dist/meta/Skeleton.json +120 -0
- package/dist/meta/Spinner.json +123 -0
- package/dist/meta/Stepper.json +135 -0
- package/dist/meta/StepperStep.json +148 -0
- package/dist/meta/Tabs.json +5 -0
- package/dist/meta/Toggle.json +18 -1
- package/dist/meta/ToolCall.json +192 -0
- package/dist/meta/Tooltip.json +3 -3
- package/dist/meta/components.json +6759 -2705
- package/dist/meta/contrast.json +11075 -3098
- package/dist/meta/index.json +266 -8
- package/dist/meta/patterns/AgentRun.json +27 -0
- package/dist/meta/patterns/Form.json +9 -0
- package/dist/meta/patterns/PageShell.json +43 -3
- package/dist/meta/patterns/Wizard.json +20 -1
- package/dist/meta/patterns/index.json +10 -1
- package/dist/styles/accordion.css +102 -0
- package/dist/styles/breadcrumb.css +72 -0
- package/dist/styles/combobox.css +154 -0
- package/dist/styles/date-picker.css +420 -0
- package/dist/styles/date-range-picker.css +280 -0
- package/dist/styles/drawer.css +181 -0
- package/dist/styles/empty-state.css +16 -4
- package/dist/styles/file-upload.css +236 -0
- package/dist/styles/header.css +26 -0
- package/dist/styles/index.css +23 -0
- package/dist/styles/number-input.css +83 -0
- package/dist/styles/progress-bar.css +107 -0
- package/dist/styles/prompt-input.css +127 -0
- package/dist/styles/segmented-control.css +182 -0
- package/dist/styles/sidebar.css +307 -0
- package/dist/styles/skeleton.css +76 -0
- package/dist/styles/spinner.css +70 -0
- package/dist/styles/stepper.css +250 -0
- package/dist/styles/tool-call.css +202 -0
- package/llms.txt +2 -2
- package/package.json +2 -1
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import React, { forwardRef, useId, useState } from 'react';
|
|
4
|
+
const Chevron = () => (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", focusable: "false", children: _jsx("path", { d: "m9 6 6 6-6 6", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
5
|
+
/** Does any SidebarItem below these children carry `isCurrent`? */
|
|
6
|
+
function containsCurrent(children) {
|
|
7
|
+
return React.Children.toArray(children).some((child) => {
|
|
8
|
+
if (!React.isValidElement(child))
|
|
9
|
+
return false;
|
|
10
|
+
return (child.props.isCurrent === true || containsCurrent(child.props.children));
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
function useDisclosure(controlled, initial, onChange) {
|
|
14
|
+
const [internal, setInternal] = useState(initial);
|
|
15
|
+
const isOpen = controlled ?? internal;
|
|
16
|
+
const toggle = () => {
|
|
17
|
+
const next = !isOpen;
|
|
18
|
+
if (controlled === undefined)
|
|
19
|
+
setInternal(next);
|
|
20
|
+
onChange?.(next);
|
|
21
|
+
};
|
|
22
|
+
return [isOpen, toggle];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Sidebar — an application's navigation, as a column.
|
|
26
|
+
*
|
|
27
|
+
* DISCLOSURE NAVIGATION, NOT `role="tree"`
|
|
28
|
+
*
|
|
29
|
+
* A file-tree look invites the tree role, and the tree role is wrong here.
|
|
30
|
+
* A treeview takes the arrow keys, allows one tab stop for the whole widget,
|
|
31
|
+
* and does not permit interactive content inside an item — so the `…` and `+`
|
|
32
|
+
* buttons on a row, which are half the point of a workspace sidebar, could not
|
|
33
|
+
* exist in it. This is the WAI-ARIA disclosure navigation pattern instead:
|
|
34
|
+
* nested lists of links, each expandable level behind a real button with
|
|
35
|
+
* `aria-expanded`, and everything reachable with Tab.
|
|
36
|
+
*
|
|
37
|
+
* AN ITEM THAT IS A LINK AND HAS CHILDREN GETS TWO CONTROLS
|
|
38
|
+
*
|
|
39
|
+
* A button cannot sit inside a link. So a row that navigates AND expands
|
|
40
|
+
* renders the link and a separate chevron button beside it; a row with no
|
|
41
|
+
* `href` is one button that expands. The actions slot is a sibling of both,
|
|
42
|
+
* never nested inside either.
|
|
43
|
+
*
|
|
44
|
+
* THE CURRENT PAGE IS NEVER FOLDED AWAY
|
|
45
|
+
*
|
|
46
|
+
* An item whose subtree contains the current page starts open. A sidebar that
|
|
47
|
+
* loads with the user's location collapsed inside a closed group tells a
|
|
48
|
+
* sighted user nothing and a screen-reader user less.
|
|
49
|
+
*
|
|
50
|
+
* Expansion is per item, controlled or not. Remembering it across visits is the
|
|
51
|
+
* caller's job — this component cannot know where that state should live.
|
|
52
|
+
*/
|
|
53
|
+
export const Sidebar = forwardRef(({ label, header, footer, children, className, ...rest }, ref) => (_jsxs("nav", { ...rest, ref: ref, "aria-label": label, className: ['ion-sidebar', className || ''].filter(Boolean).join(' '), children: [header && _jsx("div", { className: "ion-sidebar__header", children: header }), _jsx("div", { className: "ion-sidebar__body", children: children }), footer && _jsx("div", { className: "ion-sidebar__footer", children: footer })] })));
|
|
54
|
+
Sidebar.displayName = 'Sidebar';
|
|
55
|
+
export const SidebarSection = forwardRef(({ title, isCollapsible = false, defaultExpanded = true, isExpanded: isExpandedProp, onExpandedChange, actions, children, className, ...rest }, ref) => {
|
|
56
|
+
const titleId = useId();
|
|
57
|
+
const listId = useId();
|
|
58
|
+
const collapsible = isCollapsible && !!title;
|
|
59
|
+
const [isOpen, toggle] = useDisclosure(collapsible ? isExpandedProp : true, collapsible ? defaultExpanded : true, onExpandedChange);
|
|
60
|
+
return (_jsxs("div", { ...rest, ref: ref, className: ['ion-sidebar__section', className || '']
|
|
61
|
+
.filter(Boolean)
|
|
62
|
+
.join(' '), children: [title && (_jsxs("div", { className: "ion-sidebar__section-header", children: [collapsible ? (_jsxs("button", { type: "button", id: titleId, className: [
|
|
63
|
+
'ion-sidebar__section-title',
|
|
64
|
+
isOpen ? 'ion-sidebar__section-title--expanded' : '',
|
|
65
|
+
]
|
|
66
|
+
.filter(Boolean)
|
|
67
|
+
.join(' '), "aria-expanded": isOpen, "aria-controls": listId, onClick: toggle, children: [title, _jsx("span", { className: "ion-sidebar__chevron", "aria-hidden": "true", children: _jsx(Chevron, {}) })] })) : (_jsx("span", { id: titleId, className: "ion-sidebar__section-title", children: title })), actions && (_jsx("span", { className: "ion-sidebar__section-actions", children: actions }))] })), _jsx("ul", { id: listId, className: "ion-sidebar__list", "aria-labelledby": title ? titleId : undefined, hidden: !isOpen, children: children })] }));
|
|
68
|
+
});
|
|
69
|
+
SidebarSection.displayName = 'SidebarSection';
|
|
70
|
+
export const SidebarItem = forwardRef(({ label, icon, href, onPress, isCurrent = false, isDisabled = false, badge, actions, defaultExpanded, isExpanded: isExpandedProp, onExpandedChange, children, className, ...rest }, ref) => {
|
|
71
|
+
const listId = useId();
|
|
72
|
+
const hasChildren = React.Children.toArray(children).some((c) => React.isValidElement(c));
|
|
73
|
+
const [isOpen, toggle] = useDisclosure(isExpandedProp, defaultExpanded ?? containsCurrent(children), onExpandedChange);
|
|
74
|
+
const content = (_jsxs(_Fragment, { children: [icon && (_jsx("span", { className: "ion-sidebar__icon", "aria-hidden": "true", children: icon })), _jsx("span", { className: "ion-sidebar__label", children: label }), badge !== undefined && badge !== null && (_jsx("span", { className: "ion-sidebar__badge", children: badge }))] }));
|
|
75
|
+
const chevron = (_jsx("span", { className: [
|
|
76
|
+
'ion-sidebar__chevron',
|
|
77
|
+
isOpen ? 'ion-sidebar__chevron--expanded' : '',
|
|
78
|
+
]
|
|
79
|
+
.filter(Boolean)
|
|
80
|
+
.join(' '), "aria-hidden": "true", children: _jsx(Chevron, {}) }));
|
|
81
|
+
let main;
|
|
82
|
+
if (href !== undefined && !isDisabled) {
|
|
83
|
+
main = (_jsx("a", { href: href, className: "ion-sidebar__link", "aria-current": isCurrent ? 'page' : undefined, children: content }));
|
|
84
|
+
}
|
|
85
|
+
else if (hasChildren && href === undefined) {
|
|
86
|
+
// No destination: the whole row is the disclosure.
|
|
87
|
+
main = (_jsxs("button", { type: "button", className: "ion-sidebar__link", "aria-expanded": isOpen, "aria-controls": listId, disabled: isDisabled, onClick: toggle, children: [content, chevron] }));
|
|
88
|
+
}
|
|
89
|
+
else if (onPress && !isDisabled) {
|
|
90
|
+
main = (_jsx("button", { type: "button", className: "ion-sidebar__link", onClick: onPress, children: content }));
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
main = (_jsx("span", { className: "ion-sidebar__link", "aria-current": isCurrent ? 'page' : undefined, "aria-disabled": isDisabled || undefined, children: content }));
|
|
94
|
+
}
|
|
95
|
+
return (_jsxs("li", { ...rest, ref: ref, className: ['ion-sidebar__item', className || '']
|
|
96
|
+
.filter(Boolean)
|
|
97
|
+
.join(' '), children: [_jsxs("div", { className: [
|
|
98
|
+
'ion-sidebar__row',
|
|
99
|
+
isCurrent ? 'ion-sidebar__row--current' : '',
|
|
100
|
+
isDisabled ? 'ion-sidebar__row--disabled' : '',
|
|
101
|
+
]
|
|
102
|
+
.filter(Boolean)
|
|
103
|
+
.join(' '), children: [main, actions && _jsx("span", { className: "ion-sidebar__actions", children: actions }), hasChildren && href !== undefined && (_jsx("button", { type: "button", className: "ion-sidebar__toggle", "aria-label": label, "aria-expanded": isOpen, "aria-controls": listId, disabled: isDisabled, onClick: toggle, children: chevron }))] }), hasChildren && (_jsx("ul", { id: listId, className: "ion-sidebar__list ion-sidebar__list--nested", hidden: !isOpen, children: children }))] }));
|
|
104
|
+
});
|
|
105
|
+
SidebarItem.displayName = 'SidebarItem';
|
|
106
|
+
//# sourceMappingURL=Sidebar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Sidebar.js","sourceRoot":"","sources":["../../src/components/Sidebar.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type SkeletonVariant = 'text' | 'circle' | 'rect';
|
|
3
|
+
export interface SkeletonProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {
|
|
4
|
+
variant?: SkeletonVariant;
|
|
5
|
+
/** Any CSS length. Defaults to filling the width available. */
|
|
6
|
+
width?: string;
|
|
7
|
+
/** Any CSS length. `text` derives its height from the line box instead. */
|
|
8
|
+
height?: string;
|
|
9
|
+
/** `text` only: how many lines to draw. The last is drawn short. */
|
|
10
|
+
lines?: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Skeleton — the shape of content that has not arrived.
|
|
14
|
+
*
|
|
15
|
+
* IT IS HIDDEN FROM ASSISTIVE TECHNOLOGY, ALWAYS, AND THAT IS THE WHOLE POINT
|
|
16
|
+
*
|
|
17
|
+
* A skeleton is a picture of content, and a screen reader cannot use a picture
|
|
18
|
+
* of content. Announcing it produces a stream of empty boxes between the user
|
|
19
|
+
* and the thing they asked for. So every skeleton is `aria-hidden`, with no way
|
|
20
|
+
* to opt out — a prop for that would only ever be used by mistake.
|
|
21
|
+
*
|
|
22
|
+
* WHICH MEANS THE CALLER OWES THE ANNOUNCEMENT, AND THIS COMPONENT CANNOT DO IT
|
|
23
|
+
*
|
|
24
|
+
* Hiding the placeholder is only half an answer: something still has to tell a
|
|
25
|
+
* screen-reader user that the region is loading. That belongs on the region
|
|
26
|
+
* being replaced — `aria-busy="true"` while it loads — because only the caller
|
|
27
|
+
* knows where that region starts and ends. `Spinner` is the other half when the
|
|
28
|
+
* wait deserves an announcement of its own.
|
|
29
|
+
*
|
|
30
|
+
* <section aria-busy={isLoading}>
|
|
31
|
+
* {isLoading ? <Skeleton lines={3} /> : <Rows data={data} />}
|
|
32
|
+
* </section>
|
|
33
|
+
*
|
|
34
|
+
* This is the one component in the system whose correct use REQUIRES something
|
|
35
|
+
* of the caller that the type system cannot check, which is why it is stated
|
|
36
|
+
* here, in the contract, and in the story.
|
|
37
|
+
*/
|
|
38
|
+
export declare const Skeleton: React.ForwardRefExoticComponent<SkeletonProps & React.RefAttributes<HTMLDivElement>>;
|
|
39
|
+
//# sourceMappingURL=Skeleton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Skeleton.d.ts","sourceRoot":"","sources":["../../src/components/Skeleton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAqB,MAAM,OAAO,CAAC;AAE1C,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEzD,MAAM,WAAW,aAAc,SAAQ,IAAI,CACzC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EACpC,UAAU,CACX;IACC,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,+DAA+D;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,QAAQ,sFAiDpB,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* Skeleton — the shape of content that has not arrived.
|
|
5
|
+
*
|
|
6
|
+
* IT IS HIDDEN FROM ASSISTIVE TECHNOLOGY, ALWAYS, AND THAT IS THE WHOLE POINT
|
|
7
|
+
*
|
|
8
|
+
* A skeleton is a picture of content, and a screen reader cannot use a picture
|
|
9
|
+
* of content. Announcing it produces a stream of empty boxes between the user
|
|
10
|
+
* and the thing they asked for. So every skeleton is `aria-hidden`, with no way
|
|
11
|
+
* to opt out — a prop for that would only ever be used by mistake.
|
|
12
|
+
*
|
|
13
|
+
* WHICH MEANS THE CALLER OWES THE ANNOUNCEMENT, AND THIS COMPONENT CANNOT DO IT
|
|
14
|
+
*
|
|
15
|
+
* Hiding the placeholder is only half an answer: something still has to tell a
|
|
16
|
+
* screen-reader user that the region is loading. That belongs on the region
|
|
17
|
+
* being replaced — `aria-busy="true"` while it loads — because only the caller
|
|
18
|
+
* knows where that region starts and ends. `Spinner` is the other half when the
|
|
19
|
+
* wait deserves an announcement of its own.
|
|
20
|
+
*
|
|
21
|
+
* <section aria-busy={isLoading}>
|
|
22
|
+
* {isLoading ? <Skeleton lines={3} /> : <Rows data={data} />}
|
|
23
|
+
* </section>
|
|
24
|
+
*
|
|
25
|
+
* This is the one component in the system whose correct use REQUIRES something
|
|
26
|
+
* of the caller that the type system cannot check, which is why it is stated
|
|
27
|
+
* here, in the contract, and in the story.
|
|
28
|
+
*/
|
|
29
|
+
export const Skeleton = forwardRef(({ variant = 'text', width, height, lines = 1, className, ...rest }, ref) => {
|
|
30
|
+
const classNames = [
|
|
31
|
+
'ion-skeleton',
|
|
32
|
+
`ion-skeleton--${variant}`,
|
|
33
|
+
className || '',
|
|
34
|
+
]
|
|
35
|
+
.filter(Boolean)
|
|
36
|
+
.join(' ');
|
|
37
|
+
// Lengths travel as custom properties rather than inline width/height, so a
|
|
38
|
+
// caller never writes a raw value into a style attribute the lint rules
|
|
39
|
+
// read. See ProgressBar for the same trade.
|
|
40
|
+
const style = {
|
|
41
|
+
...(width ? { '--ion-skeleton-width': width } : {}),
|
|
42
|
+
...(height ? { '--ion-skeleton-height': height } : {}),
|
|
43
|
+
};
|
|
44
|
+
if (variant === 'text' && lines > 1) {
|
|
45
|
+
return (_jsx("div", { ...rest, ref: ref, "aria-hidden": "true", className: "ion-skeleton-group", style: style, children: Array.from({ length: lines }, (_, i) => (_jsx("div", { className: `${classNames}${i === lines - 1 ? ' ion-skeleton--last' : ''}` }, i))) }));
|
|
46
|
+
}
|
|
47
|
+
return (_jsx("div", { ...rest, ref: ref, "aria-hidden": "true", className: classNames, style: style }));
|
|
48
|
+
});
|
|
49
|
+
Skeleton.displayName = 'Skeleton';
|
|
50
|
+
//# sourceMappingURL=Skeleton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Skeleton.js","sourceRoot":"","sources":["../../src/components/Skeleton.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAiB1C;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,UAAU,CAChC,CAAC,EAAE,OAAO,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,GAAG,CAAC,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,EAAE,GAAG,EAAE,EAAE;IAC1E,MAAM,UAAU,GAAG;QACjB,cAAc;QACd,iBAAiB,OAAO,EAAE;QAC1B,SAAS,IAAI,EAAE;KAChB;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;IAEb,4EAA4E;IAC5E,wEAAwE;IACxE,4CAA4C;IAC5C,MAAM,KAAK,GAAG;QACZ,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,sBAAsB,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnD,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,uBAAuB,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAChC,CAAC;IAEzB,IAAI,OAAO,KAAK,MAAM,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACpC,OAAO,CACL,iBACM,IAAI,EACR,GAAG,EAAE,GAAG,iBACI,MAAM,EAClB,SAAS,EAAC,oBAAoB,EAC9B,KAAK,EAAE,KAAK,YAEX,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CACvC,cAEE,SAAS,EAAE,GAAG,UAAU,GACtB,CAAC,KAAK,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,EAC5C,EAAE,IAHG,CAAC,CAIN,CACH,CAAC,GACE,CACP,CAAC;IACJ,CAAC;IAED,OAAO,CACL,iBACM,IAAI,EACR,GAAG,EAAE,GAAG,iBACI,MAAM,EAClB,SAAS,EAAE,UAAU,EACrB,KAAK,EAAE,KAAK,GACZ,CACH,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,QAAQ,CAAC,WAAW,GAAG,UAAU,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type SpinnerSize = 'sm' | 'md' | 'lg';
|
|
3
|
+
export interface SpinnerProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, 'children'> {
|
|
4
|
+
/** Matches the icon size ramp: sm, md, lg. */
|
|
5
|
+
size?: SpinnerSize;
|
|
6
|
+
/** What is loading. Announced politely; visible only with `isLabelVisible`. */
|
|
7
|
+
label?: string;
|
|
8
|
+
/** Render the label as text beside the ring as well as announcing it. */
|
|
9
|
+
isLabelVisible?: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* The spinner conveys nothing on its own — something else already says the
|
|
12
|
+
* region is busy. Renders inert: no role, no live region, hidden from AT.
|
|
13
|
+
*/
|
|
14
|
+
isDecorative?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Spinner — an indeterminate wait, announced once.
|
|
18
|
+
*
|
|
19
|
+
* WHY THIS IS NOT A DIV WITH A CSS ANIMATION
|
|
20
|
+
*
|
|
21
|
+
* The obvious implementation is inaccessible in a specific and common way: a
|
|
22
|
+
* spinning graphic with no text is silence to a screen reader, so the user is
|
|
23
|
+
* told nothing happened. Generated code in this repo's own eval corpus reached
|
|
24
|
+
* for a bare `role="status"` in 48 files, which is the right instinct and only
|
|
25
|
+
* half the job — the role creates a live region, but an empty one announces
|
|
26
|
+
* nothing at all.
|
|
27
|
+
*
|
|
28
|
+
* So the default carries a label. It is visually hidden, it lives inside the
|
|
29
|
+
* live region, and it is what makes "Loading" reach the user who cannot see the
|
|
30
|
+
* ring.
|
|
31
|
+
*
|
|
32
|
+
* `isDecorative` exists because the opposite mistake is just as easy. A spinner
|
|
33
|
+
* inside a button whose label already changed to "Saving…" would announce
|
|
34
|
+
* twice, and two live regions racing is worse than one. Decorative renders no
|
|
35
|
+
* role at all rather than `aria-hidden` on a live region, which browsers treat
|
|
36
|
+
* inconsistently.
|
|
37
|
+
*
|
|
38
|
+
* MOTION
|
|
39
|
+
*
|
|
40
|
+
* `prefers-reduced-motion` slows the rotation rather than stopping it. A
|
|
41
|
+
* stationary spinner is not a calmer spinner — it is a broken one, and it
|
|
42
|
+
* removes the only signal a sighted user has that the wait is still live.
|
|
43
|
+
*/
|
|
44
|
+
export declare const Spinner: React.ForwardRefExoticComponent<SpinnerProps & React.RefAttributes<HTMLSpanElement>>;
|
|
45
|
+
//# sourceMappingURL=Spinner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Spinner.d.ts","sourceRoot":"","sources":["../../src/components/Spinner.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAqB,MAAM,OAAO,CAAC;AAE1C,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAE7C,MAAM,WAAW,YAAa,SAAQ,IAAI,CACxC,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC,EACrC,UAAU,CACX;IACC,8CAA8C;IAC9C,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,OAAO,sFA0CnB,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* Spinner — an indeterminate wait, announced once.
|
|
5
|
+
*
|
|
6
|
+
* WHY THIS IS NOT A DIV WITH A CSS ANIMATION
|
|
7
|
+
*
|
|
8
|
+
* The obvious implementation is inaccessible in a specific and common way: a
|
|
9
|
+
* spinning graphic with no text is silence to a screen reader, so the user is
|
|
10
|
+
* told nothing happened. Generated code in this repo's own eval corpus reached
|
|
11
|
+
* for a bare `role="status"` in 48 files, which is the right instinct and only
|
|
12
|
+
* half the job — the role creates a live region, but an empty one announces
|
|
13
|
+
* nothing at all.
|
|
14
|
+
*
|
|
15
|
+
* So the default carries a label. It is visually hidden, it lives inside the
|
|
16
|
+
* live region, and it is what makes "Loading" reach the user who cannot see the
|
|
17
|
+
* ring.
|
|
18
|
+
*
|
|
19
|
+
* `isDecorative` exists because the opposite mistake is just as easy. A spinner
|
|
20
|
+
* inside a button whose label already changed to "Saving…" would announce
|
|
21
|
+
* twice, and two live regions racing is worse than one. Decorative renders no
|
|
22
|
+
* role at all rather than `aria-hidden` on a live region, which browsers treat
|
|
23
|
+
* inconsistently.
|
|
24
|
+
*
|
|
25
|
+
* MOTION
|
|
26
|
+
*
|
|
27
|
+
* `prefers-reduced-motion` slows the rotation rather than stopping it. A
|
|
28
|
+
* stationary spinner is not a calmer spinner — it is a broken one, and it
|
|
29
|
+
* removes the only signal a sighted user has that the wait is still live.
|
|
30
|
+
*/
|
|
31
|
+
export const Spinner = forwardRef(({ size = 'md', label = 'Loading', isLabelVisible = false, isDecorative = false, className, ...rest }, ref) => {
|
|
32
|
+
const classNames = [
|
|
33
|
+
'ion-spinner',
|
|
34
|
+
size !== 'md' ? `ion-spinner--${size}` : '',
|
|
35
|
+
className || '',
|
|
36
|
+
]
|
|
37
|
+
.filter(Boolean)
|
|
38
|
+
.join(' ');
|
|
39
|
+
return (_jsxs("span", { ...rest, ref: ref, className: classNames, ...(isDecorative
|
|
40
|
+
? { 'aria-hidden': true }
|
|
41
|
+
: { role: 'status', 'aria-live': 'polite' }), children: [_jsx("span", { className: "ion-spinner__ring", "aria-hidden": "true" }), !isDecorative && (_jsx("span", { className: isLabelVisible ? 'ion-spinner__label' : 'ion-visually-hidden', children: label }))] }));
|
|
42
|
+
});
|
|
43
|
+
Spinner.displayName = 'Spinner';
|
|
44
|
+
//# sourceMappingURL=Spinner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Spinner.js","sourceRoot":"","sources":["../../src/components/Spinner.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAqB1C;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,UAAU,CAC/B,CACE,EACE,IAAI,GAAG,IAAI,EACX,KAAK,GAAG,SAAS,EACjB,cAAc,GAAG,KAAK,EACtB,YAAY,GAAG,KAAK,EACpB,SAAS,EACT,GAAG,IAAI,EACR,EACD,GAAG,EACH,EAAE;IACF,MAAM,UAAU,GAAG;QACjB,aAAa;QACb,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE;QAC3C,SAAS,IAAI,EAAE;KAChB;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;IAEb,OAAO,CACL,mBACM,IAAI,EACR,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,UAAU,KACjB,CAAC,YAAY;YACf,CAAC,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE;YACzB,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC,aAE9C,eAAM,SAAS,EAAC,mBAAmB,iBAAa,MAAM,GAAG,EACxD,CAAC,YAAY,IAAI,CAChB,eACE,SAAS,EACP,cAAc,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,qBAAqB,YAG9D,KAAK,GACD,CACR,IACI,CACR,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type StepperOrientation = 'horizontal' | 'vertical';
|
|
3
|
+
export type StepperStepStatus = 'incomplete' | 'complete' | 'error';
|
|
4
|
+
export interface StepperProps extends React.HTMLAttributes<HTMLOListElement> {
|
|
5
|
+
/**
|
|
6
|
+
* Names the list. Defaults to "Progress"; give it the task's name when a page
|
|
7
|
+
* carries more than one — "Checkout progress".
|
|
8
|
+
*/
|
|
9
|
+
label?: string;
|
|
10
|
+
/**
|
|
11
|
+
* `horizontal` for a page-width header above the form, `vertical` for a side
|
|
12
|
+
* rail. Below 40rem a horizontal stepper hides every label but the current
|
|
13
|
+
* one, so it does not need a second variant for mobile.
|
|
14
|
+
*/
|
|
15
|
+
orientation?: StepperOrientation;
|
|
16
|
+
/** `StepperStep` elements, first step first. */
|
|
17
|
+
children?: React.ReactNode;
|
|
18
|
+
}
|
|
19
|
+
export interface StepperStepProps extends Omit<React.LiHTMLAttributes<HTMLLIElement>, 'onClick'> {
|
|
20
|
+
/** The step's name, in the user's language. */
|
|
21
|
+
children?: React.ReactNode;
|
|
22
|
+
/** A short second line — what the step asks for, or a summary of the answer. */
|
|
23
|
+
description?: React.ReactNode;
|
|
24
|
+
/**
|
|
25
|
+
* Whether the step's answers have been accepted. Orthogonal to `isCurrent`:
|
|
26
|
+
* a user who goes Back to step 1 is on a step that is both current and
|
|
27
|
+
* complete.
|
|
28
|
+
*/
|
|
29
|
+
status?: StepperStepStatus;
|
|
30
|
+
/** The step the user is on. Marked `aria-current="step"`. */
|
|
31
|
+
isCurrent?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Makes a visited step a link back to it. Ignored on the current step and on
|
|
34
|
+
* `incomplete` steps — see the component's comment for why.
|
|
35
|
+
*/
|
|
36
|
+
href?: string;
|
|
37
|
+
/** As `href`, for a wizard that changes step without a route. */
|
|
38
|
+
onPress?: () => void;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Stepper — where the user is in a task that has an order.
|
|
42
|
+
*
|
|
43
|
+
* WHY NOT TABS
|
|
44
|
+
*
|
|
45
|
+
* The `tablist` role announces peers that can be visited in any order, which is
|
|
46
|
+
* the opposite of a wizard. This is an ordered list: the steps are a sequence,
|
|
47
|
+
* and `ol` says so. Nothing here is a tab, and arrow keys do nothing.
|
|
48
|
+
*
|
|
49
|
+
* POSITION AND STATUS ARE TEXT, NOT ONLY DRAWING
|
|
50
|
+
*
|
|
51
|
+
* Every step renders "Step 2 of 5" and its status as visually hidden text. The
|
|
52
|
+
* number in the circle is for the eye; a screen reader cannot be relied on to
|
|
53
|
+
* announce list position, and a coloured ring carries nothing in forced-colours
|
|
54
|
+
* mode. The complete and error glyphs also differ in SHAPE — a check and an
|
|
55
|
+
* exclamation — so the states survive greyscale, which WCAG 1.4.1 requires.
|
|
56
|
+
*
|
|
57
|
+
* ONLY VISITED STEPS ARE LINKS
|
|
58
|
+
*
|
|
59
|
+
* `href` / `onPress` are honoured on `complete` and `error` steps that are not
|
|
60
|
+
* current. An `incomplete` step renders as text even when given one, because
|
|
61
|
+
* jumping forward past unanswered steps is exactly what a wizard exists to
|
|
62
|
+
* prevent — and a link that is there but should not be followed is worse than
|
|
63
|
+
* no link. The current step is text for the same reason Breadcrumb's is: a link
|
|
64
|
+
* to where you already are is a dead control.
|
|
65
|
+
*
|
|
66
|
+
* IT DOES NOT ANNOUNCE STEP CHANGES
|
|
67
|
+
*
|
|
68
|
+
* The Wizard pattern moves focus to the new step's heading, which announces it.
|
|
69
|
+
* A live region here as well would say the same thing twice, on every step.
|
|
70
|
+
*/
|
|
71
|
+
export declare const Stepper: React.ForwardRefExoticComponent<StepperProps & React.RefAttributes<HTMLOListElement>>;
|
|
72
|
+
export declare const StepperStep: React.ForwardRefExoticComponent<StepperStepProps & React.RefAttributes<HTMLLIElement>>;
|
|
73
|
+
//# sourceMappingURL=Stepper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Stepper.d.ts","sourceRoot":"","sources":["../../src/components/Stepper.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAgD,MAAM,OAAO,CAAC;AAErE,MAAM,MAAM,kBAAkB,GAAG,YAAY,GAAG,UAAU,CAAC;AAC3D,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG,UAAU,GAAG,OAAO,CAAC;AASpE,MAAM,WAAW,YAAa,SAAQ,KAAK,CAAC,cAAc,CAAC,gBAAgB,CAAC;IAC1E;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,gDAAgD;IAChD,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAED,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAC5C,KAAK,CAAC,gBAAgB,CAAC,aAAa,CAAC,EACrC,SAAS,CACV;IACC,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,gFAAgF;IAChF,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B;;;;OAIG;IACH,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,6DAA6D;IAC7D,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAgCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,OAAO,uFA0CnB,CAAC;AAIF,eAAO,MAAM,WAAW,wFAoFvB,CAAC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import React, { createContext, forwardRef, useContext } from 'react';
|
|
4
|
+
const StepContext = createContext(null);
|
|
5
|
+
const STATUS_TEXT = {
|
|
6
|
+
incomplete: 'Not started',
|
|
7
|
+
complete: 'Completed',
|
|
8
|
+
error: 'Has errors',
|
|
9
|
+
};
|
|
10
|
+
const Check = () => (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", focusable: "false", children: _jsx("path", { d: "m6 12.5 4 4 8-9", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
11
|
+
const Exclamation = () => (_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", focusable: "false", children: [_jsx("path", { d: "M12 6.5v7", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round" }), _jsx("circle", { cx: "12", cy: "17.5", r: "1.5", fill: "currentColor" })] }));
|
|
12
|
+
/**
|
|
13
|
+
* Stepper — where the user is in a task that has an order.
|
|
14
|
+
*
|
|
15
|
+
* WHY NOT TABS
|
|
16
|
+
*
|
|
17
|
+
* The `tablist` role announces peers that can be visited in any order, which is
|
|
18
|
+
* the opposite of a wizard. This is an ordered list: the steps are a sequence,
|
|
19
|
+
* and `ol` says so. Nothing here is a tab, and arrow keys do nothing.
|
|
20
|
+
*
|
|
21
|
+
* POSITION AND STATUS ARE TEXT, NOT ONLY DRAWING
|
|
22
|
+
*
|
|
23
|
+
* Every step renders "Step 2 of 5" and its status as visually hidden text. The
|
|
24
|
+
* number in the circle is for the eye; a screen reader cannot be relied on to
|
|
25
|
+
* announce list position, and a coloured ring carries nothing in forced-colours
|
|
26
|
+
* mode. The complete and error glyphs also differ in SHAPE — a check and an
|
|
27
|
+
* exclamation — so the states survive greyscale, which WCAG 1.4.1 requires.
|
|
28
|
+
*
|
|
29
|
+
* ONLY VISITED STEPS ARE LINKS
|
|
30
|
+
*
|
|
31
|
+
* `href` / `onPress` are honoured on `complete` and `error` steps that are not
|
|
32
|
+
* current. An `incomplete` step renders as text even when given one, because
|
|
33
|
+
* jumping forward past unanswered steps is exactly what a wizard exists to
|
|
34
|
+
* prevent — and a link that is there but should not be followed is worse than
|
|
35
|
+
* no link. The current step is text for the same reason Breadcrumb's is: a link
|
|
36
|
+
* to where you already are is a dead control.
|
|
37
|
+
*
|
|
38
|
+
* IT DOES NOT ANNOUNCE STEP CHANGES
|
|
39
|
+
*
|
|
40
|
+
* The Wizard pattern moves focus to the new step's heading, which announces it.
|
|
41
|
+
* A live region here as well would say the same thing twice, on every step.
|
|
42
|
+
*/
|
|
43
|
+
export const Stepper = forwardRef(({ label = 'Progress', orientation = 'horizontal', children, className, ...rest }, ref) => {
|
|
44
|
+
/*
|
|
45
|
+
* Position comes from the children rather than from props on each step.
|
|
46
|
+
* Asking the caller to pass `index` and `total` five times is five chances
|
|
47
|
+
* for "Step 3 of 4" to appear twice.
|
|
48
|
+
*/
|
|
49
|
+
const steps = React.Children.toArray(children).filter(React.isValidElement);
|
|
50
|
+
return (_jsx("ol", { ...rest, ref: ref, "aria-label": label, "data-orientation": orientation, className: [
|
|
51
|
+
'ion-stepper',
|
|
52
|
+
`ion-stepper--${orientation}`,
|
|
53
|
+
className || '',
|
|
54
|
+
]
|
|
55
|
+
.filter(Boolean)
|
|
56
|
+
.join(' '), children: steps.map((step, index) => (_jsx(StepContext.Provider, { value: { index, total: steps.length }, children: step }, step.key ?? index))) }));
|
|
57
|
+
});
|
|
58
|
+
Stepper.displayName = 'Stepper';
|
|
59
|
+
export const StepperStep = forwardRef(({ children, description, status = 'incomplete', isCurrent = false, href, onPress, className, ...rest }, ref) => {
|
|
60
|
+
const position = useContext(StepContext);
|
|
61
|
+
if (!position) {
|
|
62
|
+
throw new Error('StepperStep must be rendered inside a Stepper');
|
|
63
|
+
}
|
|
64
|
+
const number = position.index + 1;
|
|
65
|
+
const isInteractive = !isCurrent && status !== 'incomplete' && (!!href || !!onPress);
|
|
66
|
+
const statusText = isCurrent
|
|
67
|
+
? status === 'error'
|
|
68
|
+
? 'Current step, has errors'
|
|
69
|
+
: 'Current step'
|
|
70
|
+
: STATUS_TEXT[status];
|
|
71
|
+
const content = (_jsxs(_Fragment, { children: [_jsx("span", { className: "ion-stepper__indicator", "aria-hidden": "true", children: status === 'complete' ? (_jsx(Check, {})) : status === 'error' ? (_jsx(Exclamation, {})) : (number) }), _jsxs("span", { className: "ion-stepper__text", children: [_jsx("span", { className: "ion-visually-hidden", children: `Step ${number} of ${position.total}: ` }), _jsx("span", { className: "ion-stepper__label", children: children }), description && (_jsx("span", { className: "ion-stepper__description", children: description })), _jsx("span", { className: "ion-visually-hidden", children: `, ${statusText}` })] })] }));
|
|
72
|
+
return (_jsx("li", { ...rest, ref: ref, "aria-current": isCurrent ? 'step' : undefined, className: [
|
|
73
|
+
'ion-stepper__step',
|
|
74
|
+
status !== 'incomplete' ? `ion-stepper__step--${status}` : '',
|
|
75
|
+
isCurrent ? 'ion-stepper__step--current' : '',
|
|
76
|
+
className || '',
|
|
77
|
+
]
|
|
78
|
+
.filter(Boolean)
|
|
79
|
+
.join(' '), children: isInteractive && href ? (_jsx("a", { href: href, className: "ion-stepper__trigger", children: content })) : isInteractive ? (_jsx("button", { type: "button", className: "ion-stepper__trigger", onClick: onPress, children: content })) : (_jsx("span", { className: "ion-stepper__trigger", children: content })) }));
|
|
80
|
+
});
|
|
81
|
+
StepperStep.displayName = 'StepperStep';
|
|
82
|
+
//# sourceMappingURL=Stepper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Stepper.js","sourceRoot":"","sources":["../../src/components/Stepper.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { type SelectionProps } from './resolve-selection.js';
|
|
2
3
|
export type ToggleSize = 'sm' | 'md' | 'lg';
|
|
3
4
|
export type ToggleIntent = 'brand' | 'neutral' | 'danger';
|
|
4
|
-
export interface ToggleProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size' | 'type'
|
|
5
|
+
export interface ToggleProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size' | 'type'>, SelectionProps {
|
|
5
6
|
/** Matches the Figma `Size` variant: Small, Medium, Large. */
|
|
6
7
|
size?: ToggleSize;
|
|
7
8
|
/** Matches the Figma `Color` variant: Brand, Neutral, Danger. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toggle.d.ts","sourceRoot":"","sources":["../../src/components/Toggle.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAkD,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"Toggle.d.ts","sourceRoot":"","sources":["../../src/components/Toggle.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAkD,MAAM,OAAO,CAAC;AAEvE,OAAO,EAAoB,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE/E,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAC5C,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE1D,MAAM,WAAW,WACf,SACE,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,EAClE,cAAc;IAChB,8DAA8D;IAC9D,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,iEAAiE;IACjE,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,sCAAsC;IACtC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,MAAM,sFAwDlB,CAAC"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { forwardRef, useRef, useImperativeHandle } from 'react';
|
|
4
4
|
import { resolveDisabled } from './resolve-disabled.js';
|
|
5
|
+
import { resolveSelection } from './resolve-selection.js';
|
|
5
6
|
/**
|
|
6
7
|
* Toggle is a checkbox with `role="switch"`.
|
|
7
8
|
*
|
|
@@ -16,8 +17,9 @@ import { resolveDisabled } from './resolve-disabled.js';
|
|
|
16
17
|
* ramps.
|
|
17
18
|
*/
|
|
18
19
|
export const Toggle = forwardRef((props, forwardedRef) => {
|
|
19
|
-
const { size = 'md', intent = 'brand', className, children, isDisabled, disabled, ...rest } = props;
|
|
20
|
+
const { size = 'md', intent = 'brand', className, children, isDisabled, disabled, isSelected, checked, onChange, onSelectionChange, ...rest } = props;
|
|
20
21
|
const resolvedDisabled = resolveDisabled(isDisabled, disabled);
|
|
22
|
+
const selection = resolveSelection(isSelected, checked, onChange, onSelectionChange);
|
|
21
23
|
const domRef = useRef(null);
|
|
22
24
|
useImperativeHandle(forwardedRef, () => domRef.current);
|
|
23
25
|
const classNames = [
|
|
@@ -29,7 +31,7 @@ export const Toggle = forwardRef((props, forwardedRef) => {
|
|
|
29
31
|
]
|
|
30
32
|
.filter(Boolean)
|
|
31
33
|
.join(' ');
|
|
32
|
-
return (_jsxs("label", { className: classNames, children: [_jsx("input", { ...rest, ref: domRef, type: "checkbox", role: "switch", disabled: resolvedDisabled, className: "ion-toggle__input" }), _jsx("span", { className: "ion-toggle__track", "aria-hidden": "true", children: _jsx("span", { className: "ion-toggle__thumb" }) }), children && _jsx("span", { className: "ion-toggle__label", children: children })] }));
|
|
34
|
+
return (_jsxs("label", { className: classNames, children: [_jsx("input", { ...rest, ref: domRef, type: "checkbox", checked: selection.checked, onChange: selection.onChange, role: "switch", disabled: resolvedDisabled, className: "ion-toggle__input" }), _jsx("span", { className: "ion-toggle__track", "aria-hidden": "true", children: _jsx("span", { className: "ion-toggle__thumb" }) }), children && _jsx("span", { className: "ion-toggle__label", children: children })] }));
|
|
33
35
|
});
|
|
34
36
|
Toggle.displayName = 'Toggle';
|
|
35
37
|
//# sourceMappingURL=Toggle.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toggle.js","sourceRoot":"","sources":["../../src/components/Toggle.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAc,EAAE,UAAU,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,OAAO,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"Toggle.js","sourceRoot":"","sources":["../../src/components/Toggle.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAc,EAAE,UAAU,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,OAAO,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAuB,MAAM,wBAAwB,CAAC;AAsB/E;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,UAAU,CAC9B,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE;IACtB,MAAM,EACJ,IAAI,GAAG,IAAI,EACX,MAAM,GAAG,OAAO,EAChB,SAAS,EACT,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,UAAU,EACV,OAAO,EACP,QAAQ,EACR,iBAAiB,EACjB,GAAG,IAAI,EACR,GAAG,KAAK,CAAC;IAEV,MAAM,gBAAgB,GAAG,eAAe,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IAC/D,MAAM,SAAS,GAAG,gBAAgB,CAChC,UAAU,EACV,OAAO,EACP,QAAQ,EACR,iBAAiB,CAClB,CAAC;IAEF,MAAM,MAAM,GAAG,MAAM,CAAmB,IAAI,CAAC,CAAC;IAC9C,mBAAmB,CAAC,YAAY,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAQ,CAAC,CAAC;IAEzD,MAAM,UAAU,GAAG;QACjB,YAAY;QACZ,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE;QAC1C,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,eAAe,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE;QACjD,gBAAgB,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE;QAC9C,SAAS,IAAI,EAAE;KAChB;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;IAEb,OAAO,CACL,iBAAO,SAAS,EAAE,UAAU,aAC1B,mBACM,IAAI,EACR,GAAG,EAAE,MAAM,EACX,IAAI,EAAC,UAAU,EACf,OAAO,EAAE,SAAS,CAAC,OAAO,EAC1B,QAAQ,EAAE,SAAS,CAAC,QAAQ,EAC5B,IAAI,EAAC,QAAQ,EACb,QAAQ,EAAE,gBAAgB,EAC1B,SAAS,EAAC,mBAAmB,GAC7B,EACF,eAAM,SAAS,EAAC,mBAAmB,iBAAa,MAAM,YACpD,eAAM,SAAS,EAAC,mBAAmB,GAAG,GACjC,EACN,QAAQ,IAAI,eAAM,SAAS,EAAC,mBAAmB,YAAE,QAAQ,GAAQ,IAC5D,CACT,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,WAAW,GAAG,QAAQ,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { AgentActivityStatus } from './agent-status.js';
|
|
3
|
+
export interface ToolCallProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {
|
|
4
|
+
/**
|
|
5
|
+
* What the call did, in the user's language — "Searched the invoice archive".
|
|
6
|
+
* Required: the tool's function name is not a description of the work.
|
|
7
|
+
*/
|
|
8
|
+
title: string;
|
|
9
|
+
/** The tool's technical name, shown in monospace beside the title. */
|
|
10
|
+
name?: string;
|
|
11
|
+
/** The same vocabulary as AgentActivityStep, so the two never disagree. */
|
|
12
|
+
status?: AgentActivityStatus;
|
|
13
|
+
/**
|
|
14
|
+
* What the agent passed in. Objects and arrays render as formatted JSON,
|
|
15
|
+
* strings as they are. Redact secrets before passing it — this renders
|
|
16
|
+
* exactly what it is given.
|
|
17
|
+
*/
|
|
18
|
+
input?: unknown;
|
|
19
|
+
/** What came back. Rendered as `input` is. */
|
|
20
|
+
output?: unknown;
|
|
21
|
+
/**
|
|
22
|
+
* Why a `failed` call failed. Shown under the header whether or not the
|
|
23
|
+
* details are expanded — a failure that takes a click to read is not read.
|
|
24
|
+
*/
|
|
25
|
+
errorMessage?: React.ReactNode;
|
|
26
|
+
/** How long the call took, in milliseconds. */
|
|
27
|
+
durationMs?: number;
|
|
28
|
+
/** Uncontrolled: whether the details start open. */
|
|
29
|
+
defaultExpanded?: boolean;
|
|
30
|
+
/** Controlled: whether the details are open. Pass `onExpandedChange` with it. */
|
|
31
|
+
isExpanded?: boolean;
|
|
32
|
+
onExpandedChange?: (isExpanded: boolean) => void;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* ToolCall — the evidence behind one step of an agent run.
|
|
36
|
+
*
|
|
37
|
+
* AgentActivityStep says what the agent did in the user's language. ToolCall
|
|
38
|
+
* is where the person checking that account goes next: which tool, with what
|
|
39
|
+
* arguments, and what came back. The title is still plain language and still
|
|
40
|
+
* required, so the technical detail supplements the account rather than
|
|
41
|
+
* replacing it.
|
|
42
|
+
*
|
|
43
|
+
* COLLAPSED BY DEFAULT, EXCEPT THE FAILURE
|
|
44
|
+
*
|
|
45
|
+
* A run makes dozens of calls, and a thread of expanded JSON is unreadable.
|
|
46
|
+
* But `errorMessage` renders outside the disclosure: evidence that takes a
|
|
47
|
+
* click to reach is evidence nobody reads, and a failure is the one thing in
|
|
48
|
+
* the call a reader must not miss.
|
|
49
|
+
*
|
|
50
|
+
* THE DETAILS ARE UNMOUNTED WHEN CLOSED — unlike Accordion, deliberately.
|
|
51
|
+
* Accordion keeps collapsed panels for the form state inside them; a tool call
|
|
52
|
+
* holds no user state, and its payloads can be megabytes of JSON multiplied by
|
|
53
|
+
* every call in the thread.
|
|
54
|
+
*
|
|
55
|
+
* A CALL WITH NOTHING TO SHOW IS NOT A BUTTON. With no input and no output the
|
|
56
|
+
* header renders as text: a disclosure that discloses nothing announces as
|
|
57
|
+
* expandable and does nothing.
|
|
58
|
+
*
|
|
59
|
+
* THE PAYLOADS ARE FOCUSABLE. Each is a scroll container capped in height, and
|
|
60
|
+
* a scroll container a keyboard user cannot focus is one they cannot scroll.
|
|
61
|
+
*
|
|
62
|
+
* It does not announce status changes. AgentActivity owns the run's live
|
|
63
|
+
* region; a second one here would talk over it.
|
|
64
|
+
*/
|
|
65
|
+
export declare const ToolCall: React.ForwardRefExoticComponent<ToolCallProps & React.RefAttributes<HTMLDivElement>>;
|
|
66
|
+
//# sourceMappingURL=ToolCall.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToolCall.d.ts","sourceRoot":"","sources":["../../src/components/ToolCall.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAE3D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE7D,MAAM,WAAW,aAAc,SAAQ,IAAI,CACzC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EACpC,OAAO,CACR;IACC;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,8CAA8C;IAC9C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,iFAAiF;IACjF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,OAAO,KAAK,IAAI,CAAC;CAClD;AA6BD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,QAAQ,sFAwHpB,CAAC"}
|