@uniflowed/ui 0.2.0 → 0.4.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/accordion.js +22 -9
- package/alert-dialog.js +41 -19
- package/alert.js +14 -8
- package/avatar.js +14 -8
- package/breadcrumb.js +24 -6
- package/calendar.js +22 -5
- package/carousel.js +24 -6
- package/collapsible.js +14 -3
- package/color-picker.js +22 -5
- package/combobox.js +30 -21
- package/context-menu.js +31 -2
- package/date-picker.js +37 -11
- package/date-range-picker.js +25 -8
- package/dialog.js +31 -10
- package/drawer.js +47 -34
- package/field.js +24 -6
- package/hover-card.js +14 -3
- package/index.js +89 -740
- package/input-otp.js +20 -4
- package/interactions.js +0 -1
- package/internal/focus.js +13 -4
- package/internal/roving-focus.js +12 -3
- package/menu.js +36 -13
- package/menubar.js +32 -5
- package/navigation-menu.js +24 -6
- package/number-field.js +20 -12
- package/package.json +5 -5
- package/pagination.js +22 -5
- package/popover.js +14 -4
- package/radio-group.js +15 -4
- package/range-calendar.js +20 -2
- package/resizable.js +14 -3
- package/scroll-area.js +14 -3
- package/select.js +30 -13
- package/sheet.js +39 -18
- package/sidebar.js +31 -16
- package/skeleton.js +13 -3
- package/slider.js +15 -4
- package/table.js +32 -10
- package/tabs.js +15 -9
- package/toast.js +24 -6
- package/toggle-group.js +14 -3
- package/tooltip.js +21 -5
package/range-calendar.js
CHANGED
|
@@ -7,11 +7,11 @@ import { useControlled } from "./internal/controlled-state.js";
|
|
|
7
7
|
import type { Rest } from "./internal/merge-props.js";
|
|
8
8
|
import type { DateRange } from "./internal/date-range.js";
|
|
9
9
|
import { validateRange, unavailableInRange } from "./internal/date-range.js";
|
|
10
|
-
import { CalendarRoot, CalendarMonth } from "./calendar.js";
|
|
10
|
+
import { Root as CalendarRoot, Month as CalendarMonth } from "./calendar.js";
|
|
11
11
|
import { visuallyHiddenStyle } from "./internal/visually-hidden-style.js";
|
|
12
12
|
export type { DateRange } from "./internal/date-range.js";
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
component RangeCalendarRoot(
|
|
15
15
|
children?: React.Node = <CalendarMonth />,
|
|
16
16
|
value?: DateRange | null,
|
|
17
17
|
defaultValue?: DateRange | null = null,
|
|
@@ -77,3 +77,21 @@ export component RangeCalendarRoot(
|
|
|
77
77
|
</div>
|
|
78
78
|
);
|
|
79
79
|
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* The parts, under the names the `RangeCalendar` namespace gives them.
|
|
83
|
+
*
|
|
84
|
+
* `index.js` re-exports this module whole — `export * as RangeCalendar from "./range-calendar.js"` —
|
|
85
|
+
* so a caller writes `<RangeCalendar.Root>`, and the namespace is the prefix. Each
|
|
86
|
+
* part is still *declared* as `RangeCalendarRoot`, so React DevTools, a component
|
|
87
|
+
* stack and an error name the part a reader can find rather than one of forty
|
|
88
|
+
* `Root`s.
|
|
89
|
+
*/
|
|
90
|
+
export { RangeCalendarRoot as Root };
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* The parts `RangeCalendar` shares with `Calendar`, re-exported so the `RangeCalendar`
|
|
94
|
+
* namespace is complete on its own: `<RangeCalendar.Month>` is `Calendar`'s part,
|
|
95
|
+
* not a copy of it.
|
|
96
|
+
*/
|
|
97
|
+
export { Month, Day, Previous, Next } from "./calendar.js";
|
package/resizable.js
CHANGED
|
@@ -165,7 +165,7 @@ hook useResizable(part: string): ResizableState {
|
|
|
165
165
|
* `Enter` collapses the pane entirely; a group whose primary pane should never
|
|
166
166
|
* disappear gives it a floor.
|
|
167
167
|
*/
|
|
168
|
-
|
|
168
|
+
component ResizablePanelGroup(
|
|
169
169
|
children: React.Node,
|
|
170
170
|
value?: number,
|
|
171
171
|
defaultValue?: number = 50,
|
|
@@ -225,7 +225,7 @@ export component ResizablePanelGroup(
|
|
|
225
225
|
* caller renders a pane conditionally, and a handle pointing at the wrong pane
|
|
226
226
|
* is a handle that announces someone else's size.
|
|
227
227
|
*/
|
|
228
|
-
|
|
228
|
+
component ResizablePanel(children: React.Node, primary?: boolean = false, ...rest: Rest) {
|
|
229
229
|
const group = useResizable("Resizable.Panel");
|
|
230
230
|
const passed = withoutComposed(rest, ["style"]);
|
|
231
231
|
const register = group.registerPrimary;
|
|
@@ -260,7 +260,7 @@ export component ResizablePanel(children: React.Node, primary?: boolean = false,
|
|
|
260
260
|
* name is announced as "separator", which tells a reader there is a control
|
|
261
261
|
* here and nothing about what it does.
|
|
262
262
|
*/
|
|
263
|
-
|
|
263
|
+
component ResizableHandle(label?: string = "Resize", ...rest: Rest) {
|
|
264
264
|
const group = useResizable("Resizable.Handle");
|
|
265
265
|
const passed = withoutComposed(rest, [
|
|
266
266
|
"onKeyDown",
|
|
@@ -451,3 +451,14 @@ function stepFor(
|
|
|
451
451
|
_ => null,
|
|
452
452
|
};
|
|
453
453
|
}
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* The parts, under the names the `Resizable` namespace gives them.
|
|
457
|
+
*
|
|
458
|
+
* `index.js` re-exports this module whole — `export * as Resizable from "./resizable.js"` —
|
|
459
|
+
* so a caller writes `<Resizable.PanelGroup>`, and the namespace is the prefix. Each
|
|
460
|
+
* part is still *declared* as `ResizablePanelGroup`, so React DevTools, a component
|
|
461
|
+
* stack and an error name the part a reader can find rather than one of forty
|
|
462
|
+
* `PanelGroup`s.
|
|
463
|
+
*/
|
|
464
|
+
export { ResizablePanelGroup as PanelGroup, ResizablePanel as Panel, ResizableHandle as Handle };
|
package/scroll-area.js
CHANGED
|
@@ -103,7 +103,7 @@ hook useScrollArea(part: string): ScrollAreaState {
|
|
|
103
103
|
* lands them in it, and a scroll area that has to be scrolled to be read and is
|
|
104
104
|
* announced as "region" has told them nothing.
|
|
105
105
|
*/
|
|
106
|
-
|
|
106
|
+
component ScrollAreaRoot(children: React.Node, label: string, ...rest: Rest) {
|
|
107
107
|
const base = useId();
|
|
108
108
|
const viewportRef = useRef<HTMLElement | null>(null);
|
|
109
109
|
const rememberedRef = useRef<Offset>({ x: 0, y: 0 });
|
|
@@ -143,7 +143,7 @@ export component ScrollAreaRoot(children: React.Node, label: string, ...rest: Re
|
|
|
143
143
|
* scrolls a native overflow container scrolls this one because it is one, and
|
|
144
144
|
* the component's contribution is the tab stop that lets those keys arrive.
|
|
145
145
|
*/
|
|
146
|
-
|
|
146
|
+
component ScrollAreaViewport(children: React.Node, ...rest: Rest) {
|
|
147
147
|
const area = useScrollArea("ScrollArea.Viewport");
|
|
148
148
|
const { rememberedRef, report, viewportRef } = area;
|
|
149
149
|
const passed = withoutComposed(rest, ["ref"]);
|
|
@@ -207,7 +207,7 @@ export component ScrollAreaViewport(children: React.Node, ...rest: Rest) {
|
|
|
207
207
|
* measure nothing. `aria-hidden`, because the region it belongs to is already
|
|
208
208
|
* the thing a reader operates.
|
|
209
209
|
*/
|
|
210
|
-
|
|
210
|
+
component ScrollAreaScrollbar(
|
|
211
211
|
children?: React.Node,
|
|
212
212
|
orientation?: Orientation = "vertical",
|
|
213
213
|
...rest: Rest
|
|
@@ -281,3 +281,14 @@ function fraction(part: number, whole: number): number {
|
|
|
281
281
|
}
|
|
282
282
|
return Math.min(1, Math.max(0, part / whole));
|
|
283
283
|
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* The parts, under the names the `ScrollArea` namespace gives them.
|
|
287
|
+
*
|
|
288
|
+
* `index.js` re-exports this module whole — `export * as ScrollArea from "./scroll-area.js"` —
|
|
289
|
+
* so a caller writes `<ScrollArea.Root>`, and the namespace is the prefix. Each
|
|
290
|
+
* part is still *declared* as `ScrollAreaRoot`, so React DevTools, a component
|
|
291
|
+
* stack and an error name the part a reader can find rather than one of forty
|
|
292
|
+
* `Root`s.
|
|
293
|
+
*/
|
|
294
|
+
export { ScrollAreaRoot as Root, ScrollAreaViewport as Viewport, ScrollAreaScrollbar as Scrollbar };
|
package/select.js
CHANGED
|
@@ -252,7 +252,7 @@ const SelectGroupContext: React.Context<SelectGroupState | null> = createContext
|
|
|
252
252
|
* `onValueChange`, which is exactly the pair of props below. Neither package
|
|
253
253
|
* imports the other and neither needs to.
|
|
254
254
|
*/
|
|
255
|
-
|
|
255
|
+
component SelectRoot(
|
|
256
256
|
children: React.Node,
|
|
257
257
|
value?: string | null,
|
|
258
258
|
defaultValue?: string | null = null,
|
|
@@ -365,7 +365,7 @@ export component SelectRoot(
|
|
|
365
365
|
* shadcn's single `SelectLabel`, which is the group's, has no name for the
|
|
366
366
|
* field's.
|
|
367
367
|
*/
|
|
368
|
-
|
|
368
|
+
component SelectLabel(children: React.Node, ...rest: Rest) {
|
|
369
369
|
const select = useSelect("Select.Label");
|
|
370
370
|
const register = select.registerFieldLabel;
|
|
371
371
|
useEffect(() => {
|
|
@@ -392,7 +392,7 @@ export component SelectLabel(children: React.Node, ...rest: Rest) {
|
|
|
392
392
|
* forms, and a `<button>` inside a `<form>` submits it by default. A select
|
|
393
393
|
* that posted the form every time it was opened would be a memorable bug.
|
|
394
394
|
*/
|
|
395
|
-
|
|
395
|
+
component SelectTrigger(children: React.Node, ...rest: Rest) {
|
|
396
396
|
const select = useSelect("Select.Trigger");
|
|
397
397
|
const passed = withoutComposed(rest, ["onClick", "onKeyDown", "ref"]);
|
|
398
398
|
|
|
@@ -550,7 +550,6 @@ export component SelectTrigger(children: React.Node, ...rest: Rest) {
|
|
|
550
550
|
event.preventDefault();
|
|
551
551
|
// The options are not in the document yet, so the keystroke travels
|
|
552
552
|
// to the commit that renders them.
|
|
553
|
-
// uf-lint-disable-next-line react-compiler/immutability
|
|
554
553
|
select.pendingLandingRef.current = { kind: "typed", key: event.key };
|
|
555
554
|
select.setOpen(true);
|
|
556
555
|
return;
|
|
@@ -603,7 +602,7 @@ export component SelectTrigger(children: React.Node, ...rest: Rest) {
|
|
|
603
602
|
*
|
|
604
603
|
* Case 3 is a real edge and the way out of it is case 1.
|
|
605
604
|
*/
|
|
606
|
-
|
|
605
|
+
component SelectValue(children?: React.Node, placeholder?: React.Node, ...rest: Rest) {
|
|
607
606
|
const select = useSelect("Select.Value");
|
|
608
607
|
const chosen = select.value;
|
|
609
608
|
|
|
@@ -626,7 +625,7 @@ export component SelectValue(children?: React.Node, placeholder?: React.Node, ..
|
|
|
626
625
|
* The effect below keeps the one invariant this pattern rests on:
|
|
627
626
|
* `aria-activedescendant` never names an option that is not in the document.
|
|
628
627
|
*/
|
|
629
|
-
|
|
628
|
+
component SelectList(
|
|
630
629
|
children: renders* (SelectOption | SelectGroup | SelectSeparator),
|
|
631
630
|
align?: Align = "start",
|
|
632
631
|
alignOffset?: number = 0,
|
|
@@ -666,8 +665,6 @@ export component SelectList(
|
|
|
666
665
|
// render — a change to `children` that no dependency list can describe. Every
|
|
667
666
|
// write is guarded by a comparison, so it settles after one extra pass rather
|
|
668
667
|
// than looping.
|
|
669
|
-
// This effect measures caller-rendered options after commit.
|
|
670
|
-
// uf-lint-disable-next-line react-compiler/immutability
|
|
671
668
|
useEffect(() => {
|
|
672
669
|
const list = listRef.current;
|
|
673
670
|
if (list == null) {
|
|
@@ -677,7 +674,6 @@ export component SelectList(
|
|
|
677
674
|
|
|
678
675
|
const wanted = pendingLandingRef.current;
|
|
679
676
|
if (wanted != null) {
|
|
680
|
-
// uf-lint-disable-next-line react-compiler/immutability
|
|
681
677
|
pendingLandingRef.current = null;
|
|
682
678
|
// An `if` rather than a `match` on `wanted.kind`, because matching on a
|
|
683
679
|
// property does not refine the object that property came from: inside
|
|
@@ -751,7 +747,7 @@ export component SelectList(
|
|
|
751
747
|
* finds the option in the document rather than in a registry that could
|
|
752
748
|
* disagree with the page — the reason `internal/roving-focus.js` gives.
|
|
753
749
|
*/
|
|
754
|
-
|
|
750
|
+
component SelectOption(
|
|
755
751
|
value: string,
|
|
756
752
|
children: React.Node,
|
|
757
753
|
label?: string,
|
|
@@ -840,7 +836,7 @@ export component SelectOption(
|
|
|
840
836
|
* fix is to hand the options to the group directly; a wrapper had no effect on
|
|
841
837
|
* what this renders, because the group's element is the one below.
|
|
842
838
|
*/
|
|
843
|
-
|
|
839
|
+
component SelectGroup(children: renders* (SelectOption | SelectGroupLabel), ...rest: Rest) {
|
|
844
840
|
const base = useId();
|
|
845
841
|
const [labelled, setLabelled] = useState(false);
|
|
846
842
|
|
|
@@ -862,7 +858,7 @@ export component SelectGroup(children: renders* (SelectOption | SelectGroupLabel
|
|
|
862
858
|
* ordinary content a reader would hear the heading once as the group's name and
|
|
863
859
|
* again as a stray line of text among the options.
|
|
864
860
|
*/
|
|
865
|
-
|
|
861
|
+
component SelectGroupLabel(children: React.Node, ...rest: Rest) {
|
|
866
862
|
const group = useContext(SelectGroupContext);
|
|
867
863
|
const register = group?.registerLabel;
|
|
868
864
|
|
|
@@ -891,7 +887,7 @@ export component SelectGroupLabel(children: React.Node, ...rest: Rest) {
|
|
|
891
887
|
* the software rather than the specification. The rule between two groups is
|
|
892
888
|
* decoration, so it says so and stays out of the tree.
|
|
893
889
|
*/
|
|
894
|
-
|
|
890
|
+
component SelectSeparator(...rest: Rest) {
|
|
895
891
|
return <div {...rest} aria-hidden="true" />;
|
|
896
892
|
}
|
|
897
893
|
|
|
@@ -899,3 +895,24 @@ export component SelectSeparator(...rest: Rest) {
|
|
|
899
895
|
function textOf(element: HTMLElement | null): string {
|
|
900
896
|
return (element?.textContent ?? "").replace(/\s+/g, " ").trim();
|
|
901
897
|
}
|
|
898
|
+
|
|
899
|
+
/**
|
|
900
|
+
* The parts, under the names the `Select` namespace gives them.
|
|
901
|
+
*
|
|
902
|
+
* `index.js` re-exports this module whole — `export * as Select from "./select.js"` —
|
|
903
|
+
* so a caller writes `<Select.Root>`, and the namespace is the prefix. Each
|
|
904
|
+
* part is still *declared* as `SelectRoot`, so React DevTools, a component
|
|
905
|
+
* stack and an error name the part a reader can find rather than one of forty
|
|
906
|
+
* `Root`s.
|
|
907
|
+
*/
|
|
908
|
+
export {
|
|
909
|
+
SelectRoot as Root,
|
|
910
|
+
SelectLabel as Label,
|
|
911
|
+
SelectTrigger as Trigger,
|
|
912
|
+
SelectValue as Value,
|
|
913
|
+
SelectList as List,
|
|
914
|
+
SelectOption as Option,
|
|
915
|
+
SelectGroup as Group,
|
|
916
|
+
SelectGroupLabel as GroupLabel,
|
|
917
|
+
SelectSeparator as Separator,
|
|
918
|
+
};
|
package/sheet.js
CHANGED
|
@@ -46,15 +46,15 @@ import { createContext, useContext, useMemo } from "@uniflowed/react";
|
|
|
46
46
|
import type { RenderProp, Rest } from "./internal/merge-props.js";
|
|
47
47
|
import { forwarded } from "./internal/merge-props.js";
|
|
48
48
|
import {
|
|
49
|
-
DialogBody,
|
|
50
|
-
DialogClose,
|
|
51
|
-
DialogDescription,
|
|
52
|
-
DialogFooter,
|
|
53
|
-
DialogHeader,
|
|
54
|
-
DialogOverlay,
|
|
55
|
-
DialogRoot,
|
|
56
|
-
DialogTitle,
|
|
57
|
-
DialogTrigger,
|
|
49
|
+
Body as DialogBody,
|
|
50
|
+
Close as DialogClose,
|
|
51
|
+
Description as DialogDescription,
|
|
52
|
+
Footer as DialogFooter,
|
|
53
|
+
Header as DialogHeader,
|
|
54
|
+
Overlay as DialogOverlay,
|
|
55
|
+
Root as DialogRoot,
|
|
56
|
+
Title as DialogTitle,
|
|
57
|
+
Trigger as DialogTrigger,
|
|
58
58
|
} from "./dialog.js";
|
|
59
59
|
|
|
60
60
|
/**
|
|
@@ -91,7 +91,7 @@ hook useSheet(part: string): SheetState {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
/** The sheet, open or closed. Uncontrolled unless `open` is given. */
|
|
94
|
-
|
|
94
|
+
component SheetRoot(
|
|
95
95
|
children: React.Node,
|
|
96
96
|
defaultOpen?: boolean = false,
|
|
97
97
|
onOpenChange?: (open: boolean) => void,
|
|
@@ -110,7 +110,7 @@ export component SheetRoot(
|
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
/** What opens it, and what focus comes back to when it closes. */
|
|
113
|
-
|
|
113
|
+
component SheetTrigger(children: React.Node, render?: RenderProp, ...rest: Rest) {
|
|
114
114
|
return (
|
|
115
115
|
<DialogTrigger {...forwarded(rest)} render={render}>
|
|
116
116
|
{children}
|
|
@@ -122,7 +122,7 @@ export component SheetTrigger(children: React.Node, render?: RenderProp, ...rest
|
|
|
122
122
|
* The backdrop, which knows the edge so a stylesheet does not have to be told
|
|
123
123
|
* twice.
|
|
124
124
|
*/
|
|
125
|
-
|
|
125
|
+
component SheetOverlay(render?: RenderProp, ...rest: Rest) {
|
|
126
126
|
const sheet = useSheet("Sheet.Overlay");
|
|
127
127
|
return <DialogOverlay {...forwarded(rest)} data-side={sheet.side} render={render} />;
|
|
128
128
|
}
|
|
@@ -133,7 +133,7 @@ export component SheetOverlay(render?: RenderProp, ...rest: Rest) {
|
|
|
133
133
|
* Every modal promise `dialog.js` makes is made here, unchanged. This part adds
|
|
134
134
|
* `data-side` and nothing else, which is the honest size of the difference.
|
|
135
135
|
*/
|
|
136
|
-
|
|
136
|
+
component SheetBody(children: React.Node, render?: RenderProp, ...rest: Rest) {
|
|
137
137
|
const sheet = useSheet("Sheet.Body");
|
|
138
138
|
|
|
139
139
|
return (
|
|
@@ -144,7 +144,7 @@ export component SheetBody(children: React.Node, render?: RenderProp, ...rest: R
|
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
/** The top of the sheet. See `Dialog.Header` for why it is not a `<header>`. */
|
|
147
|
-
|
|
147
|
+
component SheetHeader(children: React.Node, render?: RenderProp, ...rest: Rest) {
|
|
148
148
|
return (
|
|
149
149
|
<DialogHeader {...forwarded(rest)} render={render}>
|
|
150
150
|
{children}
|
|
@@ -153,7 +153,7 @@ export component SheetHeader(children: React.Node, render?: RenderProp, ...rest:
|
|
|
153
153
|
}
|
|
154
154
|
|
|
155
155
|
/** The bottom of the sheet, where the actions go. */
|
|
156
|
-
|
|
156
|
+
component SheetFooter(children: React.Node, render?: RenderProp, ...rest: Rest) {
|
|
157
157
|
return (
|
|
158
158
|
<DialogFooter {...forwarded(rest)} render={render}>
|
|
159
159
|
{children}
|
|
@@ -162,7 +162,7 @@ export component SheetFooter(children: React.Node, render?: RenderProp, ...rest:
|
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
/** The sheet's accessible name. A modal without one is announced as "dialog". */
|
|
165
|
-
|
|
165
|
+
component SheetTitle(children: React.Node, render?: RenderProp, ...rest: Rest) {
|
|
166
166
|
return (
|
|
167
167
|
<DialogTitle {...forwarded(rest)} render={render}>
|
|
168
168
|
{children}
|
|
@@ -171,7 +171,7 @@ export component SheetTitle(children: React.Node, render?: RenderProp, ...rest:
|
|
|
171
171
|
}
|
|
172
172
|
|
|
173
173
|
/** What the sheet is for, announced after its name. */
|
|
174
|
-
|
|
174
|
+
component SheetDescription(children: React.Node, render?: RenderProp, ...rest: Rest) {
|
|
175
175
|
return (
|
|
176
176
|
<DialogDescription {...forwarded(rest)} render={render}>
|
|
177
177
|
{children}
|
|
@@ -180,10 +180,31 @@ export component SheetDescription(children: React.Node, render?: RenderProp, ...
|
|
|
180
180
|
}
|
|
181
181
|
|
|
182
182
|
/** A button that closes the sheet. */
|
|
183
|
-
|
|
183
|
+
component SheetClose(children: React.Node, render?: RenderProp, ...rest: Rest) {
|
|
184
184
|
return (
|
|
185
185
|
<DialogClose {...forwarded(rest)} render={render}>
|
|
186
186
|
{children}
|
|
187
187
|
</DialogClose>
|
|
188
188
|
);
|
|
189
189
|
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* The parts, under the names the `Sheet` namespace gives them.
|
|
193
|
+
*
|
|
194
|
+
* `index.js` re-exports this module whole — `export * as Sheet from "./sheet.js"` —
|
|
195
|
+
* so a caller writes `<Sheet.Root>`, and the namespace is the prefix. Each
|
|
196
|
+
* part is still *declared* as `SheetRoot`, so React DevTools, a component
|
|
197
|
+
* stack and an error name the part a reader can find rather than one of forty
|
|
198
|
+
* `Root`s.
|
|
199
|
+
*/
|
|
200
|
+
export {
|
|
201
|
+
SheetRoot as Root,
|
|
202
|
+
SheetTrigger as Trigger,
|
|
203
|
+
SheetOverlay as Overlay,
|
|
204
|
+
SheetBody as Body,
|
|
205
|
+
SheetHeader as Header,
|
|
206
|
+
SheetFooter as Footer,
|
|
207
|
+
SheetTitle as Title,
|
|
208
|
+
SheetDescription as Description,
|
|
209
|
+
SheetClose as Close,
|
|
210
|
+
};
|
package/sidebar.js
CHANGED
|
@@ -57,8 +57,13 @@ import { useMediaQuery } from "@uniflowed/hooks/browser";
|
|
|
57
57
|
|
|
58
58
|
import type { RenderProp, Rest } from "./internal/merge-props.js";
|
|
59
59
|
import { composeHandlers, forwarded, withProps, withoutComposed } from "./internal/merge-props.js";
|
|
60
|
-
import {
|
|
61
|
-
|
|
60
|
+
import {
|
|
61
|
+
Body as SheetBody,
|
|
62
|
+
Overlay as SheetOverlay,
|
|
63
|
+
Root as SheetRoot,
|
|
64
|
+
Trigger as SheetTrigger,
|
|
65
|
+
} from "./sheet.js";
|
|
66
|
+
import { Body as TooltipBody, Root as TooltipRoot, Trigger as TooltipTrigger } from "./tooltip.js";
|
|
62
67
|
import { useControlled } from "./internal/controlled-state.js";
|
|
63
68
|
|
|
64
69
|
/**
|
|
@@ -115,7 +120,7 @@ hook useSidebar(part: string): SidebarState {
|
|
|
115
120
|
* is the sheet's trigger and focus goes back to it — which is the half of the
|
|
116
121
|
* transition a wrapper around only the navigation could not do.
|
|
117
122
|
*/
|
|
118
|
-
|
|
123
|
+
component SidebarRoot(
|
|
119
124
|
children: React.Node,
|
|
120
125
|
defaultOpen?: boolean = true,
|
|
121
126
|
narrowQuery?: string = NARROW,
|
|
@@ -167,7 +172,7 @@ export component SidebarRoot(
|
|
|
167
172
|
* id nothing has tells a reader there is somewhere to go and has nowhere to
|
|
168
173
|
* send them.
|
|
169
174
|
*/
|
|
170
|
-
|
|
175
|
+
component SidebarTrigger(children: React.Node, ...rest: Rest) {
|
|
171
176
|
const sidebar = useSidebar("Sidebar.Trigger");
|
|
172
177
|
const passed = withoutComposed(rest, ["onClick"]);
|
|
173
178
|
const named = sidebar.present ? `${sidebar.base}-nav` : undefined;
|
|
@@ -208,12 +213,7 @@ export component SidebarTrigger(children: React.Node, ...rest: Rest) {
|
|
|
208
213
|
* announced as "navigation" — and a page with two of those has told the reader
|
|
209
214
|
* there are two and which is which is a guess.
|
|
210
215
|
*/
|
|
211
|
-
|
|
212
|
-
children: React.Node,
|
|
213
|
-
label: string,
|
|
214
|
-
sheetProps?: Rest,
|
|
215
|
-
...rest: Rest
|
|
216
|
-
) {
|
|
216
|
+
component SidebarBody(children: React.Node, label: string, sheetProps?: Rest, ...rest: Rest) {
|
|
217
217
|
const sidebar = useSidebar("Sidebar.Body");
|
|
218
218
|
const nav = (
|
|
219
219
|
<nav
|
|
@@ -243,12 +243,12 @@ export component SidebarBody(
|
|
|
243
243
|
}
|
|
244
244
|
|
|
245
245
|
/** The top of the sidebar, as a place to put styles. See `Dialog.Header`. */
|
|
246
|
-
|
|
246
|
+
component SidebarHeader(children: React.Node, ...rest: Rest) {
|
|
247
247
|
return <div {...rest}>{children}</div>;
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
/** The bottom of the sidebar. See `Sidebar.Header`. */
|
|
251
|
-
|
|
251
|
+
component SidebarFooter(children: React.Node, ...rest: Rest) {
|
|
252
252
|
return <div {...rest}>{children}</div>;
|
|
253
253
|
}
|
|
254
254
|
|
|
@@ -267,7 +267,7 @@ export component SidebarFooter(children: React.Node, ...rest: Rest) {
|
|
|
267
267
|
* `navigation-menu.js`, which is the same argument at the scale of a whole
|
|
268
268
|
* menu.
|
|
269
269
|
*/
|
|
270
|
-
|
|
270
|
+
component SidebarItem(
|
|
271
271
|
children: React.Node,
|
|
272
272
|
label: string,
|
|
273
273
|
render?: RenderProp,
|
|
@@ -275,11 +275,8 @@ export component SidebarItem(
|
|
|
275
275
|
...rest: Rest
|
|
276
276
|
) {
|
|
277
277
|
const sidebar = useSidebar("Sidebar.Item");
|
|
278
|
-
// This removes the caller's ref from rest props; it does not read a ref value.
|
|
279
|
-
// uf-lint-disable-next-line react-compiler/refs
|
|
280
278
|
const passed = withoutComposed(rest, ["ref"]);
|
|
281
279
|
// The forwarded ref is passed through to whichever entry wrapper renders.
|
|
282
|
-
// uf-lint-disable-next-line react-compiler/refs
|
|
283
280
|
const forwardedRef = rest.ref;
|
|
284
281
|
const mine: Rest = {
|
|
285
282
|
"aria-label": sidebar.collapsed ? label : undefined,
|
|
@@ -318,3 +315,21 @@ export component SidebarItem(
|
|
|
318
315
|
</TooltipRoot>
|
|
319
316
|
);
|
|
320
317
|
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* The parts, under the names the `Sidebar` namespace gives them.
|
|
321
|
+
*
|
|
322
|
+
* `index.js` re-exports this module whole — `export * as Sidebar from "./sidebar.js"` —
|
|
323
|
+
* so a caller writes `<Sidebar.Root>`, and the namespace is the prefix. Each
|
|
324
|
+
* part is still *declared* as `SidebarRoot`, so React DevTools, a component
|
|
325
|
+
* stack and an error name the part a reader can find rather than one of forty
|
|
326
|
+
* `Root`s.
|
|
327
|
+
*/
|
|
328
|
+
export {
|
|
329
|
+
SidebarRoot as Root,
|
|
330
|
+
SidebarTrigger as Trigger,
|
|
331
|
+
SidebarHeader as Header,
|
|
332
|
+
SidebarBody as Body,
|
|
333
|
+
SidebarFooter as Footer,
|
|
334
|
+
SidebarItem as Item,
|
|
335
|
+
};
|
package/skeleton.js
CHANGED
|
@@ -92,7 +92,7 @@ import { withProps } from "./internal/merge-props.js";
|
|
|
92
92
|
* beside it, mounted by this component, because that timing is the accessibility
|
|
93
93
|
* contract rather than markup the caller can safely recreate by sight.
|
|
94
94
|
*/
|
|
95
|
-
|
|
95
|
+
component SkeletonRoot(
|
|
96
96
|
children: React.Node,
|
|
97
97
|
busy?: boolean = true,
|
|
98
98
|
label?: string = "Loading…",
|
|
@@ -114,7 +114,6 @@ export component SkeletonRoot(
|
|
|
114
114
|
return;
|
|
115
115
|
}
|
|
116
116
|
// The live-region text changes after commit so assistive tech can announce it.
|
|
117
|
-
// uf-lint-disable-next-line react-compiler/set-state-in-effect
|
|
118
117
|
setMessage(waited.current ? doneLabel : "");
|
|
119
118
|
}, [busy, doneLabel, label]);
|
|
120
119
|
|
|
@@ -154,10 +153,21 @@ export component SkeletonRoot(
|
|
|
154
153
|
* `render` changes the placeholder element, not the fact that it is hidden
|
|
155
154
|
* from the accessibility tree.
|
|
156
155
|
*/
|
|
157
|
-
|
|
156
|
+
component SkeletonBox(children?: React.Node, render?: RenderProp, ...rest: Rest) {
|
|
158
157
|
const props = withProps(rest, { "aria-hidden": "true", children });
|
|
159
158
|
if (render != null) {
|
|
160
159
|
return render(props);
|
|
161
160
|
}
|
|
162
161
|
return <div {...props} />;
|
|
163
162
|
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* The parts, under the names the `Skeleton` namespace gives them.
|
|
166
|
+
*
|
|
167
|
+
* `index.js` re-exports this module whole — `export * as Skeleton from "./skeleton.js"` —
|
|
168
|
+
* so a caller writes `<Skeleton.Root>`, and the namespace is the prefix. Each
|
|
169
|
+
* part is still *declared* as `SkeletonRoot`, so React DevTools, a component
|
|
170
|
+
* stack and an error name the part a reader can find rather than one of forty
|
|
171
|
+
* `Root`s.
|
|
172
|
+
*/
|
|
173
|
+
export { SkeletonRoot as Root, SkeletonBox as Box };
|
package/slider.js
CHANGED
|
@@ -121,7 +121,7 @@ hook useSlider(part: string): SliderState {
|
|
|
121
121
|
* with two thumbs, and a `number | [number, number]` prop would make every
|
|
122
122
|
* caller narrow a union to read their own value back.
|
|
123
123
|
*/
|
|
124
|
-
|
|
124
|
+
component SliderRoot(
|
|
125
125
|
children: React.Node,
|
|
126
126
|
value?: $ReadOnlyArray<number>,
|
|
127
127
|
defaultValue?: $ReadOnlyArray<number> = [0],
|
|
@@ -209,7 +209,7 @@ export component SliderRoot(
|
|
|
209
209
|
* wanders off the track — which every drag does — keeps arriving here instead
|
|
210
210
|
* of being lost to whatever it wandered over.
|
|
211
211
|
*/
|
|
212
|
-
|
|
212
|
+
component SliderTrack(children: React.Node, render?: RenderProp, ...rest: Rest) {
|
|
213
213
|
const slider = useSlider("Slider.Track");
|
|
214
214
|
const passed = withoutComposed(rest, ["onPointerDown", "onPointerMove", "onPointerUp", "ref"]);
|
|
215
215
|
const dragging = useRef<number | null>(null);
|
|
@@ -291,7 +291,7 @@ export component SliderTrack(children: React.Node, render?: RenderProp, ...rest:
|
|
|
291
291
|
* is told the value by the thumb and telling them again here would be telling
|
|
292
292
|
* them twice.
|
|
293
293
|
*/
|
|
294
|
-
|
|
294
|
+
component SliderRange(render?: RenderProp, ...rest: Rest) {
|
|
295
295
|
const slider = useSlider("Slider.Range");
|
|
296
296
|
const passed = withoutComposed(rest, ["style"]);
|
|
297
297
|
const ends = [...slider.values].sort((first, second) => first - second);
|
|
@@ -323,7 +323,7 @@ export component SliderRange(render?: RenderProp, ...rest: Rest) {
|
|
|
323
323
|
* "Maximum" told apart is the whole difference between a control a reader can
|
|
324
324
|
* operate and two identical "slider"s.
|
|
325
325
|
*/
|
|
326
|
-
|
|
326
|
+
component SliderThumb(index?: number = 0, render?: RenderProp, ...rest: Rest) {
|
|
327
327
|
const slider = useSlider("Slider.Thumb");
|
|
328
328
|
const passed = withoutComposed(rest, ["onKeyDown", "style"]);
|
|
329
329
|
const value = slider.values[index] ?? slider.min;
|
|
@@ -409,3 +409,14 @@ function boundsOf(
|
|
|
409
409
|
const above = index < values.length - 1 ? values[index + 1] : undefined;
|
|
410
410
|
return [below ?? min, above ?? max];
|
|
411
411
|
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* The parts, under the names the `Slider` namespace gives them.
|
|
415
|
+
*
|
|
416
|
+
* `index.js` re-exports this module whole — `export * as Slider from "./slider.js"` —
|
|
417
|
+
* so a caller writes `<Slider.Root>`, and the namespace is the prefix. Each
|
|
418
|
+
* part is still *declared* as `SliderRoot`, so React DevTools, a component
|
|
419
|
+
* stack and an error name the part a reader can find rather than one of forty
|
|
420
|
+
* `Root`s.
|
|
421
|
+
*/
|
|
422
|
+
export { SliderRoot as Root, SliderTrack as Track, SliderRange as Range, SliderThumb as Thumb };
|