@phreshos/react-ui 0.1.48 → 0.1.50
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/app-layout.d.ts +17 -2
- package/dist/app-layout.js +7 -6
- package/dist/button.d.ts +4 -1
- package/dist/button.js +5 -4
- package/dist/context-menu.d.ts +3 -0
- package/dist/context-menu.js +3 -0
- package/dist/control/control.d.ts +0 -1
- package/dist/control/control.js +0 -1
- package/dist/control/item.d.ts +5 -0
- package/dist/control/item.js +8 -1
- package/dist/control/selection.js +12 -2
- package/dist/document-theme.d.ts +7 -2
- package/dist/document-theme.js +38 -3
- package/dist/drag-and-drop.d.ts +7 -0
- package/dist/drag-and-drop.js +7 -0
- package/dist/drawer.d.ts +21 -0
- package/dist/drawer.js +53 -0
- package/dist/dropdown-menu.d.ts +3 -0
- package/dist/foundation/motion-style.js +16 -0
- package/dist/grid-list.js +8 -5
- package/dist/loading.d.ts +13 -10
- package/dist/loading.js +25 -16
- package/dist/main.d.ts +5 -3
- package/dist/main.js +2 -0
- package/dist/menu.d.ts +13 -0
- package/dist/menu.js +18 -4
- package/dist/spinner.js +4 -4
- package/dist/table.js +6 -4
- package/dist/tooltip.d.ts +5 -1
- package/dist/tooltip.js +5 -3
- package/dist/tree.d.ts +10 -0
- package/dist/tree.js +17 -6
- package/dist/use-window-move-handle.d.ts +2 -2
- package/dist/window.d.ts +2 -2
- package/package.json +2 -2
package/dist/app-layout.d.ts
CHANGED
|
@@ -1,15 +1,30 @@
|
|
|
1
1
|
import type { CSSProperties, HTMLAttributes, ReactNode } from "react";
|
|
2
|
+
import { type SurfaceDepth } from "./surface/surface.js";
|
|
2
3
|
export interface AppLayoutProps extends HTMLAttributes<HTMLDivElement> {
|
|
3
4
|
readonly children: ReactNode;
|
|
4
5
|
/** The sidebar's width; eighteen times the Appearance spacing by default. */
|
|
5
6
|
readonly sidebarWidth?: CSSProperties["width"];
|
|
6
7
|
}
|
|
7
8
|
export type AppLayoutRegionProps = HTMLAttributes<HTMLElement>;
|
|
9
|
+
export type AppLayoutContentProps = AppLayoutRegionProps & Readonly<{
|
|
10
|
+
/** How the content's Surface stands in the layout: recessed into it by default, or raised. */
|
|
11
|
+
depth?: SurfaceDepth;
|
|
12
|
+
}>;
|
|
13
|
+
export type AppLayoutSidebarProps = AppLayoutRegionProps & Readonly<{
|
|
14
|
+
/** What stays at the foot of the sidebar while the rest scrolls, such as work in progress. */
|
|
15
|
+
footer?: ReactNode;
|
|
16
|
+
}>;
|
|
8
17
|
export type AppLayoutTitleProps = HTMLAttributes<HTMLHeadingElement>;
|
|
9
18
|
export declare const AppLayout: import("react").ForwardRefExoticComponent<AppLayoutProps & import("react").RefAttributes<HTMLDivElement>> & {
|
|
10
19
|
Title: import("react").ForwardRefExoticComponent<AppLayoutTitleProps & import("react").RefAttributes<HTMLHeadingElement>>;
|
|
11
|
-
Sidebar: import("react").ForwardRefExoticComponent<AppLayoutRegionProps &
|
|
20
|
+
Sidebar: import("react").ForwardRefExoticComponent<AppLayoutRegionProps & Readonly<{
|
|
21
|
+
/** What stays at the foot of the sidebar while the rest scrolls, such as work in progress. */
|
|
22
|
+
footer?: ReactNode;
|
|
23
|
+
}> & import("react").RefAttributes<HTMLElement>>;
|
|
12
24
|
Header: import("react").ForwardRefExoticComponent<AppLayoutRegionProps & import("react").RefAttributes<HTMLElement>>;
|
|
13
|
-
Content: import("react").ForwardRefExoticComponent<AppLayoutRegionProps &
|
|
25
|
+
Content: import("react").ForwardRefExoticComponent<AppLayoutRegionProps & Readonly<{
|
|
26
|
+
/** How the content's Surface stands in the layout: recessed into it by default, or raised. */
|
|
27
|
+
depth?: SurfaceDepth;
|
|
28
|
+
}> & import("react").RefAttributes<HTMLElement>>;
|
|
14
29
|
Footer: import("react").ForwardRefExoticComponent<AppLayoutRegionProps & import("react").RefAttributes<HTMLElement>>;
|
|
15
30
|
};
|
package/dist/app-layout.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { createContext, forwardRef, useContext } from "react";
|
|
3
3
|
import { controlFontSizes, controlFontWeight } from "./control/control.js";
|
|
4
4
|
import { headerHeight } from "./foundation/layout.js";
|
|
@@ -54,10 +54,11 @@ const AppLayoutTitle = forwardRef(function AppLayoutTitle({ style, ...properties
|
|
|
54
54
|
...style
|
|
55
55
|
} });
|
|
56
56
|
});
|
|
57
|
-
/** The sidebar, such as a program's navigation. It scrolls on its own. */
|
|
58
|
-
const AppLayoutSidebar = forwardRef(function AppLayoutSidebar({ children, style, ...properties }, ref) {
|
|
57
|
+
/** The sidebar, such as a program's navigation. It scrolls on its own, above its footer. */
|
|
58
|
+
const AppLayoutSidebar = forwardRef(function AppLayoutSidebar({ children, footer, style, ...properties }, ref) {
|
|
59
59
|
const { spacing } = useLayout();
|
|
60
|
-
|
|
60
|
+
const padding = scale(spacing, "small");
|
|
61
|
+
return _jsxs("aside", { ...properties, ref: ref, style: { gridArea: "sidebar", minHeight: 0, display: "flex", flexDirection: "column", ...style }, children: [_jsx(ScrollArea, { style: { flex: "1 1 auto", minHeight: 0 }, children: _jsx("div", { style: { padding }, children: children }) }), footer != null && _jsx("div", { style: { flex: "none", paddingInline: padding, paddingBottom: padding }, children: footer })] });
|
|
61
62
|
});
|
|
62
63
|
/** The header row above the content, as tall as a Window or Panel header. */
|
|
63
64
|
const AppLayoutHeader = forwardRef(function AppLayoutHeader({ style, ...properties }, ref) {
|
|
@@ -73,9 +74,9 @@ const AppLayoutHeader = forwardRef(function AppLayoutHeader({ style, ...properti
|
|
|
73
74
|
} });
|
|
74
75
|
});
|
|
75
76
|
/** The content, on its Surface. It scrolls on its own, padded by the Appearance spacing. */
|
|
76
|
-
const AppLayoutContent = forwardRef(function AppLayoutContent({ children, style, ...properties }, ref) {
|
|
77
|
+
const AppLayoutContent = forwardRef(function AppLayoutContent({ children, depth = "recessed", style, ...properties }, ref) {
|
|
77
78
|
const { spacing, radius } = useLayout();
|
|
78
|
-
return _jsx(Surface, { as: "main", ...properties, ref: ref, material: "extended", radius: resolveRadius("medium", radius), style: {
|
|
79
|
+
return _jsx(Surface, { as: "main", ...properties, ref: ref, depth: depth, material: "extended", radius: resolveRadius("medium", radius), style: {
|
|
79
80
|
gridArea: "content",
|
|
80
81
|
minWidth: 0,
|
|
81
82
|
minHeight: 0,
|
package/dist/button.d.ts
CHANGED
|
@@ -25,7 +25,10 @@ interface ButtonOwnProps extends ControlProps, RadiusProps, MaterialOverrides, S
|
|
|
25
25
|
/** A Button that acts: a native `<button>`. */
|
|
26
26
|
export interface ButtonActionProps extends NativeButtonProps, ButtonOwnProps {
|
|
27
27
|
readonly href?: undefined;
|
|
28
|
-
/**
|
|
28
|
+
/**
|
|
29
|
+
* Work the Button started is under way: a Spinner shows in its place, the Button keeps its size
|
|
30
|
+
* and its name, and it stays focusable without activating.
|
|
31
|
+
*/
|
|
29
32
|
readonly pending?: boolean;
|
|
30
33
|
}
|
|
31
34
|
/**
|
package/dist/button.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef } from "react";
|
|
3
3
|
import { Button as AriaButton, Link as AriaLink } from "react-aria-components";
|
|
4
|
-
import {
|
|
4
|
+
import { transition, useControlMetrics } from "./control/control.js";
|
|
5
5
|
import { surfaceRender } from "./control/surface-render.js";
|
|
6
|
+
import { Spinner } from "./spinner.js";
|
|
6
7
|
/** A raised Surface you act on, or follow when it has an `href`. */
|
|
7
8
|
export const Button = forwardRef(function Button(properties, ref) {
|
|
8
9
|
const { children, color = "default", depth, disabled, iconOnly = false, radius, size, style, className, material, shadow, ...rest } = properties;
|
|
@@ -33,7 +34,7 @@ export const Button = forwardRef(function Button(properties, ref) {
|
|
|
33
34
|
const { pending = false, type = "button", ...action } = rest;
|
|
34
35
|
// Disabled state is read from React Aria, so a Button placed in a slot, such
|
|
35
36
|
// as a calendar's month buttons, follows the owner that disables it.
|
|
36
|
-
return _jsx(AriaButton, { ...action, ref: ref, type: type, className: className, isDisabled: disabled, isPending: pending, render: surfaceRender("button", state => surface(state, pending)), style: state => buttonStyle(metrics, iconOnly, !state.isDisabled && !pending && state.isPressed, state.isDisabled, pending, style), children: children });
|
|
37
|
+
return _jsx(AriaButton, { ...action, ref: ref, type: type, className: className, isDisabled: disabled, isPending: pending, render: surfaceRender("button", state => surface(state, pending)), style: state => buttonStyle(metrics, iconOnly, !state.isDisabled && !pending && state.isPressed, state.isDisabled, pending, style), children: pending ? _jsxs(_Fragment, { children: [_jsx("span", { style: { display: "inline-flex", alignItems: "center", gap: metrics.gap, opacity: 0 }, children: children }), _jsx("span", { style: { position: "absolute", inset: 0, display: "grid", placeItems: "center" }, children: _jsx(Spinner, { decorative: true, color: "currentColor", style: { width: metrics.indicator, height: metrics.indicator } }) })] }) : children });
|
|
37
38
|
});
|
|
38
39
|
function buttonStyle(metrics, iconOnly, pressed, disabled, pending, style) {
|
|
39
40
|
return {
|
|
@@ -62,7 +63,7 @@ function buttonStyle(metrics, iconOnly, pressed, disabled, pending, style) {
|
|
|
62
63
|
WebkitTapHighlightColor: "transparent",
|
|
63
64
|
cursor: disabled ? "not-allowed" : pending ? "progress" : "pointer",
|
|
64
65
|
scale: pressed ? "0.97" : "1",
|
|
65
|
-
...(pending ? {
|
|
66
|
+
...(pending ? { position: "relative" } : {}),
|
|
66
67
|
...style
|
|
67
68
|
};
|
|
68
69
|
}
|
package/dist/context-menu.d.ts
CHANGED
|
@@ -21,6 +21,9 @@ export declare const ContextMenu: typeof ContextMenuRoot & {
|
|
|
21
21
|
Section: <T extends object = object>(properties: import("./menu.js").MenuSectionProps<T>) => import("react").ReactElement | null;
|
|
22
22
|
Header: import("react").ForwardRefExoticComponent<import("react-aria-components").HeaderProps & import("react").RefAttributes<HTMLElement>>;
|
|
23
23
|
Separator: import("react").ForwardRefExoticComponent<import("react-aria-components").SeparatorProps & import("react").RefAttributes<HTMLElement>>;
|
|
24
|
+
Submenu: (({ children, delay }: import("./menu.js").MenuSubmenuProps) => import("react").JSX.Element) & {
|
|
25
|
+
Content: import("react").ForwardRefExoticComponent<import("./menu.js").MenuSubmenuContentProps & import("react").RefAttributes<HTMLElement>>;
|
|
26
|
+
};
|
|
24
27
|
};
|
|
25
28
|
};
|
|
26
29
|
export type ContextMenuProps = ComponentProps<typeof ContextMenuRoot>;
|
package/dist/context-menu.js
CHANGED
|
@@ -36,6 +36,9 @@ export const ContextMenuContent = forwardRef(function ContextMenuContent(propert
|
|
|
36
36
|
const target = event.target;
|
|
37
37
|
if (target instanceof Node && contentRef.current?.contains(target))
|
|
38
38
|
return;
|
|
39
|
+
// A Submenu opens in its own overlay; a press inside it is still inside this menu.
|
|
40
|
+
if (target instanceof Element && target.closest('[data-trigger="SubmenuTrigger"]'))
|
|
41
|
+
return;
|
|
39
42
|
state?.close();
|
|
40
43
|
}
|
|
41
44
|
document.addEventListener("pointerdown", dismiss, true);
|
|
@@ -36,7 +36,6 @@ export declare const controlLineHeight = 1.45;
|
|
|
36
36
|
export declare const controlFontWeight = 600;
|
|
37
37
|
/** Attenuation shared by every control family. */
|
|
38
38
|
export declare const controlOpacity: Readonly<{
|
|
39
|
-
pending: 0.68;
|
|
40
39
|
secondary: 0.66;
|
|
41
40
|
placeholder: 0.55;
|
|
42
41
|
}>;
|
package/dist/control/control.js
CHANGED
package/dist/control/item.d.ts
CHANGED
|
@@ -35,3 +35,8 @@ export declare function itemStyle(metrics: ControlMetrics, disabled: boolean): C
|
|
|
35
35
|
export declare function SelectionMark({ visible }: Readonly<{
|
|
36
36
|
visible: boolean;
|
|
37
37
|
}>): import("react").JSX.Element;
|
|
38
|
+
/**
|
|
39
|
+
* A collection that a drag would drop into as a whole, outlined as focus is, so it reads as the place
|
|
40
|
+
* that takes the drop.
|
|
41
|
+
*/
|
|
42
|
+
export declare function dropTargetOutline(metrics: ControlMetrics, dropTarget: boolean | undefined): CSSProperties;
|
package/dist/control/item.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { colorLevel, mixColor, resolveColor } from "../foundation/color.js";
|
|
2
|
+
import { colorLevel, colorOpacity, mixColor, resolveColor } from "../foundation/color.js";
|
|
3
3
|
import { clearVeil, interactionShift, surfacePaint } from "../surface/surface.js";
|
|
4
4
|
import { transition } from "./control.js";
|
|
5
5
|
import { Check } from "lucide-react";
|
|
@@ -55,3 +55,10 @@ export function itemStyle(metrics, disabled) {
|
|
|
55
55
|
export function SelectionMark({ visible }) {
|
|
56
56
|
return _jsx(Check, { ...iconProps(14), style: { flexShrink: 0, marginInlineStart: "auto", opacity: visible ? 1 : 0 } });
|
|
57
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* A collection that a drag would drop into as a whole, outlined as focus is, so it reads as the place
|
|
60
|
+
* that takes the drop.
|
|
61
|
+
*/
|
|
62
|
+
export function dropTargetOutline(metrics, dropTarget) {
|
|
63
|
+
return dropTarget ? { outline: `3px solid ${colorOpacity(metrics.visual.colors.primary, 0.34)}`, outlineOffset: -3 } : {};
|
|
64
|
+
}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The selection React Aria reported for each value handed out. It also remembers where a range
|
|
3
|
+
* started, which the strings alone lose; when the same value comes back, React Aria gets its own
|
|
4
|
+
* selection again, so Shift extends from the entry chosen last.
|
|
5
|
+
*/
|
|
6
|
+
const reported = new WeakMap();
|
|
1
7
|
export function toAriaSelection(value) {
|
|
2
8
|
if (value === undefined)
|
|
3
9
|
return undefined;
|
|
@@ -7,7 +13,7 @@ export function toAriaSelection(value) {
|
|
|
7
13
|
return new Set();
|
|
8
14
|
if (typeof value === "string")
|
|
9
15
|
return new Set([value]);
|
|
10
|
-
return new Set(value);
|
|
16
|
+
return reported.get(value) ?? new Set(value);
|
|
11
17
|
}
|
|
12
18
|
export function stringKey(value) {
|
|
13
19
|
if (typeof value !== "string")
|
|
@@ -21,7 +27,11 @@ export function singleSelection(selection) {
|
|
|
21
27
|
return selection === "all" ? null : optionalStringKey(selection.values().next().value ?? null);
|
|
22
28
|
}
|
|
23
29
|
export function multipleSelection(selection) {
|
|
24
|
-
|
|
30
|
+
if (selection === "all")
|
|
31
|
+
return "all";
|
|
32
|
+
const value = [...selection].map(stringKey);
|
|
33
|
+
reported.set(value, selection);
|
|
34
|
+
return value;
|
|
25
35
|
}
|
|
26
36
|
export function stringKeys(values) {
|
|
27
37
|
return [...values].map(stringKey);
|
package/dist/document-theme.d.ts
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
|
+
import { type ReactElement } from "react";
|
|
1
2
|
/**
|
|
2
3
|
* Keeps the document's color scheme on the Theme of the nearest UIProvider,
|
|
3
4
|
* or on the browser's without one. It writes the Theme into the document's
|
|
4
5
|
* `<meta name="color-scheme">`, creating the element when the document has
|
|
5
6
|
* none, before the browser paints, and follows every change. It renders
|
|
6
|
-
* nothing; place it once, where the Theme that owns the page is
|
|
7
|
+
* nothing in place; place it once, where the Theme that owns the page is
|
|
8
|
+
* provided.
|
|
7
9
|
*
|
|
8
10
|
* A page embedded in a frame needs its color scheme to match the frame's, or
|
|
9
11
|
* the browser paints the frame opaque instead of letting what is behind it
|
|
10
12
|
* show.
|
|
13
|
+
*
|
|
14
|
+
* A change of Theme takes the page there in one step; the Desktop around the
|
|
15
|
+
* page carries the movement from one Theme to the other.
|
|
11
16
|
*/
|
|
12
|
-
export declare function DocumentTheme():
|
|
17
|
+
export declare function DocumentTheme(): ReactElement;
|
package/dist/document-theme.js
CHANGED
|
@@ -1,18 +1,53 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useLayoutEffect, useRef } from "react";
|
|
2
3
|
import { usePreferences } from "./foundation/visual.js";
|
|
4
|
+
/** Marks the document while its Theme changes, so what it paints changes in one step. */
|
|
5
|
+
const changing = "data-phreshos-theme-change";
|
|
6
|
+
/**
|
|
7
|
+
* While the Theme changes, nothing in the document eases toward the new colors: the Desktop that
|
|
8
|
+
* holds the page moves from one Theme to the other as a whole, and a page easing on its own would
|
|
9
|
+
* keep changing after the Desktop has finished. Pseudo-elements carry Surface paint, so they
|
|
10
|
+
* change at once too.
|
|
11
|
+
*/
|
|
12
|
+
const instantThemeRule = `
|
|
13
|
+
html[${changing}] *,
|
|
14
|
+
html[${changing}] *::before,
|
|
15
|
+
html[${changing}] *::after {
|
|
16
|
+
transition-delay: 0s !important;
|
|
17
|
+
transition-duration: 0s !important;
|
|
18
|
+
}
|
|
19
|
+
`;
|
|
3
20
|
/**
|
|
4
21
|
* Keeps the document's color scheme on the Theme of the nearest UIProvider,
|
|
5
22
|
* or on the browser's without one. It writes the Theme into the document's
|
|
6
23
|
* `<meta name="color-scheme">`, creating the element when the document has
|
|
7
24
|
* none, before the browser paints, and follows every change. It renders
|
|
8
|
-
* nothing; place it once, where the Theme that owns the page is
|
|
25
|
+
* nothing in place; place it once, where the Theme that owns the page is
|
|
26
|
+
* provided.
|
|
9
27
|
*
|
|
10
28
|
* A page embedded in a frame needs its color scheme to match the frame's, or
|
|
11
29
|
* the browser paints the frame opaque instead of letting what is behind it
|
|
12
30
|
* show.
|
|
31
|
+
*
|
|
32
|
+
* A change of Theme takes the page there in one step; the Desktop around the
|
|
33
|
+
* page carries the movement from one Theme to the other.
|
|
13
34
|
*/
|
|
14
35
|
export function DocumentTheme() {
|
|
15
36
|
const { theme } = usePreferences();
|
|
37
|
+
const shown = useRef(theme);
|
|
38
|
+
useLayoutEffect(() => {
|
|
39
|
+
if (shown.current === theme)
|
|
40
|
+
return;
|
|
41
|
+
shown.current = theme;
|
|
42
|
+
// Set before the browser paints the new colors, and kept until they have been painted.
|
|
43
|
+
const root = document.documentElement;
|
|
44
|
+
root.setAttribute(changing, "");
|
|
45
|
+
let frame = requestAnimationFrame(() => { frame = requestAnimationFrame(() => root.removeAttribute(changing)); });
|
|
46
|
+
return () => {
|
|
47
|
+
cancelAnimationFrame(frame);
|
|
48
|
+
root.removeAttribute(changing);
|
|
49
|
+
};
|
|
50
|
+
}, [theme]);
|
|
16
51
|
useLayoutEffect(() => {
|
|
17
52
|
const existing = document.head.querySelector('meta[name="color-scheme" i]');
|
|
18
53
|
const meta = existing ?? document.head.appendChild(Object.assign(document.createElement("meta"), { name: "color-scheme" }));
|
|
@@ -25,5 +60,5 @@ export function DocumentTheme() {
|
|
|
25
60
|
meta.remove();
|
|
26
61
|
};
|
|
27
62
|
}, [theme]);
|
|
28
|
-
return
|
|
63
|
+
return _jsx("style", { href: "phreshos-document-theme", precedence: "phreshos", children: instantThemeRule });
|
|
29
64
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dragging entries out of a collection and dropping onto it, for Table, GridList, and Tree: pass what
|
|
3
|
+
* `useDragAndDrop` returns as the collection's `dragAndDropHooks`. Drags are the browser's own, so
|
|
4
|
+
* they reach other frames and other applications, and files dragged in from the machine arrive as
|
|
5
|
+
* drop items of kind `file` or `directory`. What a drag would drop into shows as chosen.
|
|
6
|
+
*/
|
|
7
|
+
export { useDragAndDrop, type DragAndDropHooks, type DragAndDropOptions, type DropItem, type DropOperation, type DirectoryDropItem, type FileDropItem, type TextDropItem } from "react-aria-components";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dragging entries out of a collection and dropping onto it, for Table, GridList, and Tree: pass what
|
|
3
|
+
* `useDragAndDrop` returns as the collection's `dragAndDropHooks`. Drags are the browser's own, so
|
|
4
|
+
* they reach other frames and other applications, and files dragged in from the machine arrive as
|
|
5
|
+
* drop items of kind `file` or `directory`. What a drag would drop into shows as chosen.
|
|
6
|
+
*/
|
|
7
|
+
export { useDragAndDrop } from "react-aria-components";
|
package/dist/drawer.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type CSSProperties, type ReactNode } from "react";
|
|
2
|
+
export interface DrawerProps {
|
|
3
|
+
readonly open: boolean;
|
|
4
|
+
/** Called for a press outside the Drawer or for Escape. */
|
|
5
|
+
readonly onClose: () => void;
|
|
6
|
+
/** Shown at its top, such as the name of what it belongs to. */
|
|
7
|
+
readonly title?: ReactNode;
|
|
8
|
+
readonly "aria-label"?: string;
|
|
9
|
+
readonly className?: string;
|
|
10
|
+
readonly style?: CSSProperties;
|
|
11
|
+
readonly children: ReactNode;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A narrow layout's sidebar, over its content from the start side, such as the navigation a narrow
|
|
15
|
+
* window gives up to its content. It is placed in its nearest positioned container. A press
|
|
16
|
+
* outside or Escape closes it. It slides in and back out along the same path, timed by the
|
|
17
|
+
* Appearance transaction, the way out its own animation so its end is seen; without motion it
|
|
18
|
+
* simply shows and goes. Only its position moves:
|
|
19
|
+
* fading it would switch off the blur it draws of what is behind it.
|
|
20
|
+
*/
|
|
21
|
+
export declare function Drawer({ open, onClose, title, className, style, children, ...properties }: DrawerProps): import("react").JSX.Element | null;
|
package/dist/drawer.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
import { controlFontSizes, controlFontWeight } from "./control/control.js";
|
|
4
|
+
import MotionStyle, { overlayTransition } from "./foundation/motion-style.js";
|
|
5
|
+
import { scale } from "./foundation/scale.js";
|
|
6
|
+
import { useVisual } from "./foundation/visual.js";
|
|
7
|
+
import { Surface } from "./surface/surface.js";
|
|
8
|
+
/**
|
|
9
|
+
* A narrow layout's sidebar, over its content from the start side, such as the navigation a narrow
|
|
10
|
+
* window gives up to its content. It is placed in its nearest positioned container. A press
|
|
11
|
+
* outside or Escape closes it. It slides in and back out along the same path, timed by the
|
|
12
|
+
* Appearance transaction, the way out its own animation so its end is seen; without motion it
|
|
13
|
+
* simply shows and goes. Only its position moves:
|
|
14
|
+
* fading it would switch off the blur it draws of what is behind it.
|
|
15
|
+
*/
|
|
16
|
+
export function Drawer({ open, onClose, title, className, style, children, ...properties }) {
|
|
17
|
+
const visual = useVisual();
|
|
18
|
+
const animated = visual.duration > 0;
|
|
19
|
+
const inset = scale(visual.spacing, "small");
|
|
20
|
+
// It stays while it slides out, and leaves once the slide ends.
|
|
21
|
+
const [present, setPresent] = useState(open);
|
|
22
|
+
useEffect(() => { if (open)
|
|
23
|
+
setPresent(true);
|
|
24
|
+
else if (!animated)
|
|
25
|
+
setPresent(false); }, [open, animated]);
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
if (!open)
|
|
28
|
+
return;
|
|
29
|
+
// Escape closes the Drawer alone, not a surface that holds it.
|
|
30
|
+
const close = (event) => { if (event.key === "Escape") {
|
|
31
|
+
event.preventDefault();
|
|
32
|
+
event.stopPropagation();
|
|
33
|
+
onClose();
|
|
34
|
+
} };
|
|
35
|
+
addEventListener("keydown", close, true);
|
|
36
|
+
return () => removeEventListener("keydown", close, true);
|
|
37
|
+
}, [open, onClose]);
|
|
38
|
+
if (!present)
|
|
39
|
+
return null;
|
|
40
|
+
return _jsxs(_Fragment, { children: [_jsx(MotionStyle, {}), open && _jsx("div", { "data-drawer-scrim": "", style: { position: "absolute", inset: 0, zIndex: 10 }, onPointerDown: onClose }), _jsxs(Surface, { ...properties, "data-drawer": "", "data-state": animated ? open ? "opening" : "closing" : undefined, material: "full", className: ["phreshos-ui-drawer", className].filter(Boolean).join(" "), onAnimationEnd: () => { if (!open)
|
|
41
|
+
setPresent(false); }, style: {
|
|
42
|
+
...overlayTransition(visual),
|
|
43
|
+
position: "absolute",
|
|
44
|
+
insetBlock: inset,
|
|
45
|
+
insetInlineStart: inset,
|
|
46
|
+
zIndex: 11,
|
|
47
|
+
boxSizing: "border-box",
|
|
48
|
+
width: `min(${visual.spacing * 20}px, calc(100% - ${visual.spacing * 4}px))`,
|
|
49
|
+
padding: inset,
|
|
50
|
+
overflow: "auto",
|
|
51
|
+
...style
|
|
52
|
+
}, children: [title != null && _jsx("div", { style: { padding: `${inset}px ${inset}px ${visual.spacing}px`, fontSize: controlFontSizes.xlarge, fontWeight: controlFontWeight }, children: title }), children] })] });
|
|
53
|
+
}
|
package/dist/dropdown-menu.d.ts
CHANGED
|
@@ -17,6 +17,9 @@ export declare const DropdownMenu: typeof DropdownMenuRoot & {
|
|
|
17
17
|
Section: <T extends object = object>(properties: import("./menu.js").MenuSectionProps<T>) => import("react").ReactElement | null;
|
|
18
18
|
Header: import("react").ForwardRefExoticComponent<import("react-aria-components").HeaderProps & import("react").RefAttributes<HTMLElement>>;
|
|
19
19
|
Separator: import("react").ForwardRefExoticComponent<import("react-aria-components").SeparatorProps & import("react").RefAttributes<HTMLElement>>;
|
|
20
|
+
Submenu: (({ children, delay }: import("./menu.js").MenuSubmenuProps) => import("react").JSX.Element) & {
|
|
21
|
+
Content: import("react").ForwardRefExoticComponent<import("./menu.js").MenuSubmenuContentProps & import("react").RefAttributes<HTMLElement>>;
|
|
22
|
+
};
|
|
20
23
|
};
|
|
21
24
|
};
|
|
22
25
|
export type DropdownMenuProps = ComponentProps<typeof DropdownMenuRoot>;
|
|
@@ -45,6 +45,22 @@ const stylesheet = `
|
|
|
45
45
|
color: inherit;
|
|
46
46
|
opacity: 0.55;
|
|
47
47
|
}
|
|
48
|
+
.phreshos-ui-text-control::-webkit-search-cancel-button,
|
|
49
|
+
.phreshos-ui-text-control::-webkit-search-decoration {
|
|
50
|
+
display: none;
|
|
51
|
+
}
|
|
52
|
+
.phreshos-ui-drawer[data-state="opening"] {
|
|
53
|
+
animation: phreshos-ui-drawer-in var(--phreshos-ui-motion-duration) var(--phreshos-ui-motion-easing);
|
|
54
|
+
}
|
|
55
|
+
.phreshos-ui-drawer[data-state="closing"] {
|
|
56
|
+
animation: phreshos-ui-drawer-out var(--phreshos-ui-motion-duration) var(--phreshos-ui-motion-easing) forwards;
|
|
57
|
+
}
|
|
58
|
+
:dir(rtl).phreshos-ui-drawer[data-state="opening"] { animation-name: phreshos-ui-drawer-in-rtl; }
|
|
59
|
+
:dir(rtl).phreshos-ui-drawer[data-state="closing"] { animation-name: phreshos-ui-drawer-out-rtl; }
|
|
60
|
+
@keyframes phreshos-ui-drawer-in { from { translate: calc(-100% - 1rem) 0; } }
|
|
61
|
+
@keyframes phreshos-ui-drawer-out { to { translate: calc(-100% - 1rem) 0; } }
|
|
62
|
+
@keyframes phreshos-ui-drawer-in-rtl { from { translate: calc(100% + 1rem) 0; } }
|
|
63
|
+
@keyframes phreshos-ui-drawer-out-rtl { to { translate: calc(100% + 1rem) 0; } }
|
|
48
64
|
@keyframes phreshos-ui-spin {
|
|
49
65
|
to { rotate: 360deg; }
|
|
50
66
|
}
|
package/dist/grid-list.js
CHANGED
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
2
2
|
import { createContext, forwardRef, useContext, useMemo } from "react";
|
|
3
3
|
import { GridList as AriaGridList, GridListHeader as AriaGridListHeader, GridListItem as AriaGridListItem, GridListSection as AriaGridListSection } from "react-aria-components";
|
|
4
4
|
import { useControlMetrics } from "./control/control.js";
|
|
5
|
-
import { itemSurface, SelectionMark } from "./control/item.js";
|
|
5
|
+
import { dropTargetOutline, itemSurface, SelectionMark } from "./control/item.js";
|
|
6
6
|
import { ariaSelection } from "./control/selection.js";
|
|
7
7
|
import { surfaceRender } from "./control/surface-render.js";
|
|
8
8
|
import { AriaDirectionBoundary } from "./foundation/aria-direction.js";
|
|
@@ -17,7 +17,7 @@ const GridListRootImplementation = forwardRef(function GridList(properties, ref)
|
|
|
17
17
|
const columns = `repeat(auto-fill, minmax(min(${typeof width === "number" ? `${width}px` : width}, 100%), 1fr))`;
|
|
18
18
|
const context = useMemo(() => ({ color, metrics, columns }), [color, metrics, columns]);
|
|
19
19
|
const direction = resolveDirection(native.dir, useDirection());
|
|
20
|
-
return _jsx(GridListStyleContext.Provider, { value: context, children: _jsx(AriaDirectionBoundary, { direction: direction, children: _jsx(AriaGridList, { ...native, ...ariaSelection(properties, "single"), ref: ref, dir: direction, layout: "grid", className: className, style: {
|
|
20
|
+
return _jsx(GridListStyleContext.Provider, { value: context, children: _jsx(AriaDirectionBoundary, { direction: direction, children: _jsx(AriaGridList, { ...native, ...ariaSelection(properties, "single"), ref: ref, dir: direction, layout: "grid", className: className, style: state => ({
|
|
21
21
|
display: "grid",
|
|
22
22
|
gridTemplateColumns: columns,
|
|
23
23
|
gap: metrics.gap * 2,
|
|
@@ -27,8 +27,10 @@ const GridListRootImplementation = forwardRef(function GridList(properties, ref)
|
|
|
27
27
|
outline: "none",
|
|
28
28
|
fontFamily: "inherit",
|
|
29
29
|
fontSize: metrics.fontSize,
|
|
30
|
+
borderRadius: metrics.radius,
|
|
31
|
+
...dropTargetOutline(metrics, state.isDropTarget),
|
|
30
32
|
...style
|
|
31
|
-
} }) }) });
|
|
33
|
+
}) }) }) });
|
|
32
34
|
});
|
|
33
35
|
/** One card. It holds whatever it is given, and shows a check in its corner when selected. */
|
|
34
36
|
const GridListItemImplementation = forwardRef(function GridListItem({ children, className, color, disabled = false, style, textValue, ...properties }, ref) {
|
|
@@ -37,7 +39,8 @@ const GridListItemImplementation = forwardRef(function GridListItem({ children,
|
|
|
37
39
|
const { metrics } = inherited;
|
|
38
40
|
return _jsx(AriaGridListItem, { ...properties, ref: ref, textValue: textValue ?? (typeof children === "string" ? children : undefined), className: className, isDisabled: disabled, render: surfaceRender("div", state => ({
|
|
39
41
|
...itemSurface(metrics.visual, itemColor, {
|
|
40
|
-
|
|
42
|
+
// What a drag would drop into shows as chosen.
|
|
43
|
+
selected: state.isSelected || state.isDropTarget === true,
|
|
41
44
|
hovered: state.isHovered,
|
|
42
45
|
pressed: state.isPressed,
|
|
43
46
|
focusVisible: state.isFocusVisible,
|
|
@@ -45,7 +48,7 @@ const GridListItemImplementation = forwardRef(function GridListItem({ children,
|
|
|
45
48
|
}, metrics.radius),
|
|
46
49
|
// Unlike a list row, a card is a whole Surface: flat, in the default color at rest, in its
|
|
47
50
|
// selection color once selected, with the default material in both.
|
|
48
|
-
...(state.isSelected ? {} : { color: "default" }),
|
|
51
|
+
...(state.isSelected || state.isDropTarget === true ? {} : { color: "default" }),
|
|
49
52
|
material: undefined
|
|
50
53
|
})), style: {
|
|
51
54
|
position: "relative",
|
package/dist/loading.d.ts
CHANGED
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
import type { CSSProperties } from "react";
|
|
2
2
|
import { type ReadinessProps } from "./readiness.js";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
export interface LoadingProps extends Pick<ReadinessProps, "children" | "delay">, SurfaceOwnProps {
|
|
3
|
+
export interface LoadingProps extends Pick<ReadinessProps, "children" | "delay"> {
|
|
4
|
+
/** Class of the layer that shows the loading. */
|
|
6
5
|
readonly className?: string;
|
|
6
|
+
/** Style of the layer that shows the loading, such as where it stands. */
|
|
7
7
|
readonly style?: CSSProperties;
|
|
8
8
|
/** Lists every requirement with a message, each with its own progress, instead of one message. */
|
|
9
9
|
readonly steps?: boolean;
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
12
|
-
* A Readiness boundary drawn the way the System draws loading:
|
|
13
|
-
*
|
|
14
|
-
* waiting requirement, or every step
|
|
15
|
-
*
|
|
12
|
+
* A Readiness boundary drawn the way the System draws loading: the waiting
|
|
13
|
+
* interface is hidden, not covered, and a Spinner with the message of the
|
|
14
|
+
* first waiting requirement, or every step, stands where it will be. Nothing
|
|
15
|
+
* is painted behind the Spinner, so the Surface the interface sits on shows
|
|
16
|
+
* through. A requirement's detail is its message when it is a string; other
|
|
17
|
+
* requirements are waited for without being shown.
|
|
16
18
|
*
|
|
17
|
-
* The
|
|
18
|
-
* fades out with the Appearance transaction
|
|
19
|
+
* The loading fills the nearest positioned ancestor. It appears at once; when
|
|
20
|
+
* everything is ready it fades out with the Appearance transaction and the
|
|
21
|
+
* interface appears whole at once.
|
|
19
22
|
*/
|
|
20
|
-
export declare function Loading({ children, delay, steps,
|
|
23
|
+
export declare function Loading({ children, delay, steps, className, style }: LoadingProps): import("react").JSX.Element;
|
package/dist/loading.js
CHANGED
|
@@ -3,23 +3,34 @@ import { useEffect, useRef, useState } from "react";
|
|
|
3
3
|
import { Check } from "lucide-react";
|
|
4
4
|
import { useControlMetrics } from "./control/control.js";
|
|
5
5
|
import { iconProps } from "./control/icon.js";
|
|
6
|
-
import { Readiness } from "./readiness.js";
|
|
6
|
+
import { Readiness, useReadiness } from "./readiness.js";
|
|
7
7
|
import { Spinner, spinnerDiameter } from "./spinner.js";
|
|
8
|
-
import { Surface } from "./surface/surface.js";
|
|
9
8
|
import { Text } from "./typography.js";
|
|
10
9
|
/**
|
|
11
|
-
* A Readiness boundary drawn the way the System draws loading:
|
|
12
|
-
*
|
|
13
|
-
* waiting requirement, or every step
|
|
14
|
-
*
|
|
10
|
+
* A Readiness boundary drawn the way the System draws loading: the waiting
|
|
11
|
+
* interface is hidden, not covered, and a Spinner with the message of the
|
|
12
|
+
* first waiting requirement, or every step, stands where it will be. Nothing
|
|
13
|
+
* is painted behind the Spinner, so the Surface the interface sits on shows
|
|
14
|
+
* through. A requirement's detail is its message when it is a string; other
|
|
15
|
+
* requirements are waited for without being shown.
|
|
15
16
|
*
|
|
16
|
-
* The
|
|
17
|
-
* fades out with the Appearance transaction
|
|
17
|
+
* The loading fills the nearest positioned ancestor. It appears at once; when
|
|
18
|
+
* everything is ready it fades out with the Appearance transaction and the
|
|
19
|
+
* interface appears whole at once.
|
|
18
20
|
*/
|
|
19
|
-
export function Loading({ children, delay, steps = false,
|
|
20
|
-
return _jsx(Readiness, { delay: delay, status: state => _jsx(
|
|
21
|
+
export function Loading({ children, delay, steps = false, className, style }) {
|
|
22
|
+
return _jsx(Readiness, { delay: delay, status: state => _jsx(LoadingStatus, { state: state, steps: steps, className: className, style: style }), children: _jsx(Hidden, { children: children }) });
|
|
21
23
|
}
|
|
22
|
-
|
|
24
|
+
/**
|
|
25
|
+
* Hides the waiting interface while it keeps its layout, so it appears whole and in place. It
|
|
26
|
+
* draws no box of its own, so the interface stays a direct part of the layout around it; such a
|
|
27
|
+
* box cannot fade, which is why the interface appears at once.
|
|
28
|
+
*/
|
|
29
|
+
function Hidden({ children }) {
|
|
30
|
+
const { ready } = useReadiness();
|
|
31
|
+
return _jsx("div", { "data-loading-content": "", style: { display: "contents", visibility: ready ? undefined : "hidden" }, children: children });
|
|
32
|
+
}
|
|
33
|
+
function LoadingStatus({ state, steps, className, style }) {
|
|
23
34
|
const metrics = useControlMetrics();
|
|
24
35
|
const { duration, easing } = metrics.visual;
|
|
25
36
|
const { ready } = state;
|
|
@@ -39,21 +50,19 @@ function LoadingCover({ state, steps, surface }) {
|
|
|
39
50
|
shown.current = state.requirements.flatMap(requirement => typeof requirement.detail === "string" ? [{ message: requirement.detail, ready: requirement.ready }] : []);
|
|
40
51
|
if (gone)
|
|
41
52
|
return null;
|
|
42
|
-
const
|
|
43
|
-
const cover = {
|
|
53
|
+
const layer = {
|
|
44
54
|
position: "absolute",
|
|
45
55
|
inset: 0,
|
|
46
56
|
display: "grid",
|
|
47
57
|
placeItems: "center",
|
|
48
58
|
opacity: ready ? 0 : 1,
|
|
49
|
-
// New waiting
|
|
59
|
+
// New waiting shows at once; only readiness fades.
|
|
50
60
|
transition: ready ? `opacity ${duration}ms ${easing}` : "none",
|
|
51
61
|
pointerEvents: ready ? "none" : undefined,
|
|
52
62
|
...style
|
|
53
63
|
};
|
|
54
64
|
const progress = steps ? _jsx(StepList, { steps: shown.current }) : _jsx(Message, { message: shown.current.find(step => !step.ready)?.message });
|
|
55
|
-
|
|
56
|
-
return _jsx(Surface, { ...paint, depth: depth, radius: radius, role: "status", "aria-hidden": ready || undefined, style: cover, children: progress });
|
|
65
|
+
return _jsx("div", { className: className, role: "status", "aria-hidden": ready || undefined, style: layer, children: progress });
|
|
57
66
|
}
|
|
58
67
|
function Message({ message }) {
|
|
59
68
|
const metrics = useControlMetrics();
|
package/dist/main.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export { resolveColor, useColor, useContrastingColor, type Color, type ColorLeve
|
|
|
17
17
|
export { Panel, type PanelProps, type PanelHeaderProps, type PanelContentProps } from "./panel.js";
|
|
18
18
|
export { Window, type WindowProps, type WindowContentProps, type WindowHeaderProps, type WindowIdentityProps, type WindowCenterProps, type WindowActionsProps, type WindowActionProps, type WindowControlProps, type WindowMaximizeProps, type WindowCloseProps, type WindowMoveCaptureProps } from "./window.js";
|
|
19
19
|
export { default as useWindowMoveHandle, type WindowMoveHandle } from "./use-window-move-handle.js";
|
|
20
|
+
export { Drawer, type DrawerProps } from "./drawer.js";
|
|
20
21
|
export { Button, type ButtonActionProps, type ButtonColor, type ButtonLinkProps, type ButtonProps } from "./button.js";
|
|
21
22
|
export { Input, type InputProps } from "./input.js";
|
|
22
23
|
export { Textarea, type TextareaProps } from "./textarea.js";
|
|
@@ -36,7 +37,7 @@ export { ListBox, type ListBoxProps, type ListBoxSingleSelectionProps, type List
|
|
|
36
37
|
export { GridList, type GridListProps, type GridListNoSelectionProps, type GridListSingleSelectionProps, type GridListMultipleSelectionProps, type GridListMultipleValue, type GridListItemProps, type GridListSectionProps, type GridListHeaderProps } from "./grid-list.js";
|
|
37
38
|
export { Tabs, type TabsProps, type TabsListProps, type TabsTabProps, type TabsPanelsProps, type TabsPanelProps } from "./tabs.js";
|
|
38
39
|
export { Table, type TableProps, type TableNoSelectionProps, type TableSingleSelectionProps, type TableMultipleSelectionProps, type TableMultipleValue, type TableSort, type TableSortDirection, type TableHeaderProps, type TableColumnProps, type TableBodyProps, type TableRowProps, type TableCellProps } from "./table.js";
|
|
39
|
-
export { Tree, type TreeProps, type TreeNoSelectionProps, type TreeSingleSelectionProps, type TreeMultipleSelectionProps, type TreeMultipleValue, type TreeItemProps, type TreeContentProps, type TreeCollectionProps } from "./tree.js";
|
|
40
|
+
export { Tree, type TreeProps, type TreeNoSelectionProps, type TreeSingleSelectionProps, type TreeMultipleSelectionProps, type TreeMultipleValue, type TreeItemProps, type TreeContentProps, type TreeCollectionProps, type TreeLoadMoreProps } from "./tree.js";
|
|
40
41
|
export { Slider, type SliderProps } from "./slider.js";
|
|
41
42
|
export { ProgressBar, type ProgressBarProps } from "./progress-bar.js";
|
|
42
43
|
export { Spinner, type SpinnerProps } from "./spinner.js";
|
|
@@ -53,13 +54,14 @@ export { Avatar, type AvatarProps } from "./avatar.js";
|
|
|
53
54
|
export { TagGroup, type TagGroupProps, type TagGroupTagProps } from "./tag-group.js";
|
|
54
55
|
export { Skeleton, type SkeletonProps } from "./skeleton.js";
|
|
55
56
|
export { Snippet, copyText, type SnippetProps } from "./snippet.js";
|
|
57
|
+
export { useDragAndDrop, type DragAndDropHooks, type DragAndDropOptions, type DropItem, type DropOperation, type DirectoryDropItem, type FileDropItem, type TextDropItem } from "./drag-and-drop.js";
|
|
56
58
|
export { toast, ToastRegion, type ToastContent, type ToastOptions, type ToastRegionProps } from "./toast.js";
|
|
57
59
|
export { Readiness, useReadiness, useRequirement, type ReadinessProps, type ReadinessState, type Requirement } from "./readiness.js";
|
|
58
60
|
export { Loading, type LoadingProps } from "./loading.js";
|
|
59
61
|
export { FileTrigger, type FileTriggerProps } from "./file-trigger.js";
|
|
60
62
|
export { DropZone, type DropZoneProps } from "./drop-zone.js";
|
|
61
63
|
export { Fieldset, type FieldsetProps } from "./fieldset.js";
|
|
62
|
-
export { AppLayout, type AppLayoutProps, type AppLayoutRegionProps, type AppLayoutTitleProps } from "./app-layout.js";
|
|
64
|
+
export { AppLayout, type AppLayoutContentProps, type AppLayoutProps, type AppLayoutRegionProps, type AppLayoutSidebarProps, type AppLayoutTitleProps } from "./app-layout.js";
|
|
63
65
|
export { ColorSwatch, type ColorSwatchProps } from "./color-swatch.js";
|
|
64
66
|
export { ColorSwatchPicker, type ColorSwatchPickerProps, type ColorSwatchPickerItemProps } from "./color-swatch-picker.js";
|
|
65
67
|
export { ColorSlider, type ColorSliderProps } from "./color-slider.js";
|
|
@@ -71,7 +73,7 @@ export { Toolbar, type ToolbarProps, type ToolbarGroupProps, type ToolbarSeparat
|
|
|
71
73
|
export { Disclosure, type DisclosureProps, type DisclosureTriggerProps, type DisclosureContentProps } from "./disclosure.js";
|
|
72
74
|
export { Accordion, type AccordionProps, type AccordionSingleExpansionProps, type AccordionMultipleExpansionProps, type AccordionItemProps } from "./accordion.js";
|
|
73
75
|
export { Popover, type PopoverProps, type PopoverTriggerProps, type PopoverContentProps, type PopoverDialogProps, type PopoverTitleProps, type PopoverCloseProps } from "./popover.js";
|
|
74
|
-
export { Menu, type MenuProps, type MenuNoSelectionProps, type MenuSingleSelectionProps, type MenuMultipleSelectionProps, type MenuMultipleValue, type MenuItemProps, type MenuSectionProps, type MenuHeaderProps, type MenuSeparatorProps } from "./menu.js";
|
|
76
|
+
export { Menu, type MenuProps, type MenuNoSelectionProps, type MenuSingleSelectionProps, type MenuMultipleSelectionProps, type MenuMultipleValue, type MenuItemProps, type MenuSectionProps, type MenuHeaderProps, type MenuSeparatorProps, type MenuSubmenuProps, type MenuSubmenuContentProps } from "./menu.js";
|
|
75
77
|
export { DropdownMenu, type DropdownMenuProps, type DropdownMenuTriggerProps } from "./dropdown-menu.js";
|
|
76
78
|
export { ContextMenu, type ContextMenuProps, type ContextMenuTriggerProps, type ContextMenuContentProps } from "./context-menu.js";
|
|
77
79
|
export { Dialog, type DialogProps, type DialogTriggerProps, type DialogBackdropProps, type DialogBackdropVariant, type DialogContentProps, type DialogHeaderProps, type DialogTitleProps, type DialogDescriptionProps, type DialogBodyProps, type DialogFooterProps, type DialogCloseProps } from "./dialog.js";
|
package/dist/main.js
CHANGED
|
@@ -17,6 +17,7 @@ export { resolveColor, useColor, useContrastingColor } from "./foundation/color.
|
|
|
17
17
|
export { Panel } from "./panel.js";
|
|
18
18
|
export { Window } from "./window.js";
|
|
19
19
|
export { default as useWindowMoveHandle } from "./use-window-move-handle.js";
|
|
20
|
+
export { Drawer } from "./drawer.js";
|
|
20
21
|
export { Button } from "./button.js";
|
|
21
22
|
export { Input } from "./input.js";
|
|
22
23
|
export { Textarea } from "./textarea.js";
|
|
@@ -52,6 +53,7 @@ export { Avatar } from "./avatar.js";
|
|
|
52
53
|
export { TagGroup } from "./tag-group.js";
|
|
53
54
|
export { Skeleton } from "./skeleton.js";
|
|
54
55
|
export { Snippet, copyText } from "./snippet.js";
|
|
56
|
+
export { useDragAndDrop } from "./drag-and-drop.js";
|
|
55
57
|
export { toast, ToastRegion } from "./toast.js";
|
|
56
58
|
export { Readiness, useReadiness, useRequirement } from "./readiness.js";
|
|
57
59
|
export { Loading } from "./loading.js";
|
package/dist/menu.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { type MultipleSelectionProps, type MultipleStringSelection, type NoSelec
|
|
|
4
4
|
import type { Color } from "./foundation/color.js";
|
|
5
5
|
import type { RadiusProps } from "./foundation/radius.js";
|
|
6
6
|
import type { ScaleLevel } from "./foundation/scale.js";
|
|
7
|
+
import { type PopoverContentProps } from "./popover.js";
|
|
7
8
|
type MenuRootBaseProps<T extends object> = Omit<AriaMenuProps<T>, "className" | "defaultSelectedKeys" | "disabledKeys" | "onAction" | "onSelectionChange" | "selectedKeys" | "selectionMode" | "style" | "shouldFocusWrap" | "shouldCloseOnSelect"> & RadiusProps & Readonly<{
|
|
8
9
|
className?: string;
|
|
9
10
|
/** Whether activating an Item closes the menu. Defaults to `true`. */
|
|
@@ -38,12 +39,24 @@ export type MenuItemComponent = <T = object>(properties: MenuItemProps<T> & RefA
|
|
|
38
39
|
export type MenuSectionProps<T extends object = object> = Omit<AriaMenuSectionProps<T>, "defaultSelectedKeys" | "selectedKeys" | "onSelectionChange" | "selectionMode" | "disallowEmptySelection" | "shouldCloseOnSelect">;
|
|
39
40
|
export type MenuHeaderProps = AriaHeaderProps;
|
|
40
41
|
export type MenuSeparatorProps = AriaSeparatorProps;
|
|
42
|
+
export interface MenuSubmenuProps {
|
|
43
|
+
/** The Item that opens the Submenu, then its `Menu.Submenu.Content`. */
|
|
44
|
+
readonly children: [ReactElement, ReactElement];
|
|
45
|
+
/** Milliseconds the pointer rests on the Item before the Submenu opens. */
|
|
46
|
+
readonly delay?: number;
|
|
47
|
+
}
|
|
48
|
+
/** An Item that opens another Menu beside it. */
|
|
49
|
+
declare function MenuSubmenu({ children, delay }: MenuSubmenuProps): import("react").JSX.Element;
|
|
50
|
+
export type MenuSubmenuContentProps = Omit<PopoverContentProps, "placement">;
|
|
41
51
|
/** A keyboard-navigable collection of commands or selectable options. */
|
|
42
52
|
export declare const Menu: MenuRootComponent & {
|
|
43
53
|
Item: MenuItemComponent;
|
|
44
54
|
Section: <T extends object = object>(properties: MenuSectionProps<T>) => ReactElement | null;
|
|
45
55
|
Header: import("react").ForwardRefExoticComponent<AriaHeaderProps & RefAttributes<HTMLElement>>;
|
|
46
56
|
Separator: import("react").ForwardRefExoticComponent<AriaSeparatorProps & RefAttributes<HTMLElement>>;
|
|
57
|
+
Submenu: typeof MenuSubmenu & {
|
|
58
|
+
Content: import("react").ForwardRefExoticComponent<MenuSubmenuContentProps & RefAttributes<HTMLElement>>;
|
|
59
|
+
};
|
|
47
60
|
};
|
|
48
61
|
export type MenuProps<T extends object = object> = MenuRootProps<T>;
|
|
49
62
|
export {};
|
package/dist/menu.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { createContext, forwardRef, useContext, useMemo } from "react";
|
|
3
|
-
import { Header as AriaHeader, Menu as AriaMenu, MenuItem as AriaMenuItem, MenuSection as AriaMenuSection, Separator as AriaSeparator } from "react-aria-components";
|
|
4
|
-
import {
|
|
3
|
+
import { Header as AriaHeader, Menu as AriaMenu, MenuItem as AriaMenuItem, MenuSection as AriaMenuSection, Separator as AriaSeparator, SubmenuTrigger as AriaSubmenuTrigger } from "react-aria-components";
|
|
4
|
+
import { ChevronRight } from "lucide-react";
|
|
5
|
+
import { controlOpacity, useControlMetrics } from "./control/control.js";
|
|
5
6
|
import { separatorColor } from "./control/field.js";
|
|
6
7
|
import { itemStyle, itemSurface, SelectionMark } from "./control/item.js";
|
|
7
8
|
import { ariaSelection, stringKey } from "./control/selection.js";
|
|
8
9
|
import { surfaceRender } from "./control/surface-render.js";
|
|
9
10
|
import { collectionHeaderStyle } from "./list-box.js";
|
|
11
|
+
import { resolveDirection, useDirection } from "./foundation/direction.js";
|
|
12
|
+
import { iconProps } from "./control/icon.js";
|
|
13
|
+
import { MenuContent } from "./popover.js";
|
|
10
14
|
const MenuStyleContext = createContext(null);
|
|
11
15
|
const MenuRootImplementation = forwardRef(function Menu(properties, ref) {
|
|
12
16
|
const { className, closeOnSelect, color = "primary", defaultValue: _defaultValue, focusWrap, onAction, onChange: _onChange, radius, selectionMode = "none", size, style, value: _value, ...native } = properties;
|
|
@@ -30,6 +34,7 @@ const MenuRootImplementation = forwardRef(function Menu(properties, ref) {
|
|
|
30
34
|
const MenuItemImplementation = forwardRef(function MenuItem({ children, className, closeOnSelect, color, disabled = false, style, textValue, ...properties }, ref) {
|
|
31
35
|
const { color: inherited, metrics, itemRadius, selecting } = useMenuStyle();
|
|
32
36
|
const itemColor = color ?? inherited;
|
|
37
|
+
const direction = resolveDirection(properties.dir, useDirection());
|
|
33
38
|
return _jsx(AriaMenuItem, { ...properties, shouldCloseOnSelect: closeOnSelect, ref: ref, textValue: textValue ?? (typeof children === "string" ? children : undefined), className: className, isDisabled: disabled, render: surfaceRender("div", state => itemSurface(metrics.visual, itemColor, {
|
|
34
39
|
selected: state.isSelected,
|
|
35
40
|
// Keyboard focus moves the highlight through a menu the way the pointer does;
|
|
@@ -38,7 +43,7 @@ const MenuItemImplementation = forwardRef(function MenuItem({ children, classNam
|
|
|
38
43
|
pressed: state.isPressed,
|
|
39
44
|
focusVisible: false,
|
|
40
45
|
disabled: state.isDisabled
|
|
41
|
-
}, itemRadius)), style: { ...itemStyle(metrics, disabled), ...style }, children: state => _jsxs(_Fragment, { children: [typeof children === "function" ? children(state) : children, selecting && _jsx(SelectionMark, { visible: state.isSelected })] }) });
|
|
46
|
+
}, itemRadius)), style: { ...itemStyle(metrics, disabled), ...style }, children: state => _jsxs(_Fragment, { children: [typeof children === "function" ? children(state) : children, selecting && _jsx(SelectionMark, { visible: state.isSelected }), state.hasSubmenu && _jsx(ChevronRight, { ...iconProps(14), style: { marginInlineStart: "auto", opacity: controlOpacity.secondary, rotate: direction === "rtl" ? "180deg" : undefined } })] }) });
|
|
42
47
|
});
|
|
43
48
|
const MenuHeader = forwardRef(function MenuHeader({ style, ...properties }, ref) {
|
|
44
49
|
const { metrics } = useMenuStyle();
|
|
@@ -55,6 +60,14 @@ const MenuSeparator = forwardRef(function MenuSeparator({ style, ...properties }
|
|
|
55
60
|
...style
|
|
56
61
|
} });
|
|
57
62
|
});
|
|
63
|
+
/** An Item that opens another Menu beside it. */
|
|
64
|
+
function MenuSubmenu({ children, delay }) {
|
|
65
|
+
return _jsx(AriaSubmenuTrigger, { delay: delay, children: children });
|
|
66
|
+
}
|
|
67
|
+
/** The Submenu's own Menu, opening beside its Item toward the reading direction's end. */
|
|
68
|
+
const MenuSubmenuContent = forwardRef(function MenuSubmenuContent(properties, ref) {
|
|
69
|
+
return _jsx(MenuContent, { ...properties, ref: ref, placement: "end top" });
|
|
70
|
+
});
|
|
58
71
|
function useMenuStyle() {
|
|
59
72
|
const context = useContext(MenuStyleContext);
|
|
60
73
|
if (context == null)
|
|
@@ -66,5 +79,6 @@ export const Menu = Object.assign(MenuRootImplementation, {
|
|
|
66
79
|
Item: MenuItemImplementation,
|
|
67
80
|
Section: AriaMenuSection,
|
|
68
81
|
Header: MenuHeader,
|
|
69
|
-
Separator: MenuSeparator
|
|
82
|
+
Separator: MenuSeparator,
|
|
83
|
+
Submenu: Object.assign(MenuSubmenu, { Content: MenuSubmenuContent })
|
|
70
84
|
});
|
package/dist/spinner.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { jsx as _jsx,
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef } from "react";
|
|
3
3
|
import { ProgressBar as AriaProgressBar } from "react-aria-components";
|
|
4
4
|
import { useControlMetrics } from "./control/control.js";
|
|
5
|
-
import {
|
|
6
|
-
import MotionStyle from "./foundation/motion-style.js";
|
|
5
|
+
import { resolveColor } from "./foundation/color.js";
|
|
6
|
+
import MotionStyle, { loopDuration } from "./foundation/motion-style.js";
|
|
7
7
|
import { scale } from "./foundation/scale.js";
|
|
8
8
|
/** A standalone status stays visibly distinct from the compact control indicator. */
|
|
9
9
|
export function spinnerDiameter(spacing, size) {
|
|
@@ -25,7 +25,7 @@ export const Spinner = forwardRef(function Spinner({ className, color = "primary
|
|
|
25
25
|
verticalAlign: "middle",
|
|
26
26
|
...style
|
|
27
27
|
};
|
|
28
|
-
const indicator = _jsxs(_Fragment, { children: [_jsx(MotionStyle, {}),
|
|
28
|
+
const indicator = _jsxs(_Fragment, { children: [_jsx(MotionStyle, {}), _jsx("svg", { "data-spinner-indicator": "", "aria-hidden": "true", focusable: "false", viewBox: "0 0 24 24", width: "100%", height: "100%", fill: "none", style: { display: "block", animation: metrics.visual.duration > 0 ? `phreshos-ui-spin ${loopDuration(metrics.visual)}ms linear infinite` : undefined }, children: _jsx("circle", { "data-spinner-fill": "", cx: "12", cy: "12", r: "11", pathLength: "100", stroke: arc, strokeWidth: "2", strokeDasharray: "75 25", transform: "rotate(-90 12 12)" }) })] });
|
|
29
29
|
if (decorative)
|
|
30
30
|
return _jsx("div", { ...properties, ref: ref, "aria-hidden": "true", className: className, style: rootStyle, children: indicator });
|
|
31
31
|
return _jsx(AriaProgressBar, { ...properties, ref: ref, "aria-label": label, className: className, isIndeterminate: true, style: rootStyle, children: indicator });
|
package/dist/table.js
CHANGED
|
@@ -3,7 +3,7 @@ import { createContext, forwardRef, useContext, useMemo } from "react";
|
|
|
3
3
|
import { Cell as AriaCell, Column as AriaColumn, Row as AriaRow, Table as AriaTable, TableBody as AriaTableBody, TableHeader as AriaTableHeader } from "react-aria-components";
|
|
4
4
|
import { controlFontWeight, controlOpacity, transition, useControlMetrics, secondaryFontSize } from "./control/control.js";
|
|
5
5
|
import { separatorColor } from "./control/field.js";
|
|
6
|
-
import { itemPaint } from "./control/item.js";
|
|
6
|
+
import { dropTargetOutline, itemPaint } from "./control/item.js";
|
|
7
7
|
import { ariaSelection, stringKey } from "./control/selection.js";
|
|
8
8
|
import { AriaDirectionBoundary } from "./foundation/aria-direction.js";
|
|
9
9
|
import { colorOpacity } from "./foundation/color.js";
|
|
@@ -18,7 +18,7 @@ const TableRoot = forwardRef(function Table(properties, ref) {
|
|
|
18
18
|
const metrics = useControlMetrics(size, radius);
|
|
19
19
|
const context = useMemo(() => ({ color, interactive: selectionMode !== "none" || onAction != null, metrics }), [color, metrics, onAction, selectionMode]);
|
|
20
20
|
const direction = resolveDirection(native.dir, useDirection());
|
|
21
|
-
return _jsx(TableStyleContext.Provider, { value: context, children: _jsx(AriaDirectionBoundary, { direction: direction, children: _jsx(AriaTable, { ...native, shouldSelectOnPressUp: selectOnPressUp, ...ariaSelection(properties, "none"), ...(sort === undefined ? {} : { sortDescriptor: sort }), ref: ref, dir: direction, className: className, onRowAction: onAction == null ? undefined : key => onAction(stringKey(key)), onSortChange: onSortChange == null ? undefined : descriptor => onSortChange(tableSort(descriptor)), style: {
|
|
21
|
+
return _jsx(TableStyleContext.Provider, { value: context, children: _jsx(AriaDirectionBoundary, { direction: direction, children: _jsx(AriaTable, { ...native, shouldSelectOnPressUp: selectOnPressUp, ...ariaSelection(properties, "none"), ...(sort === undefined ? {} : { sortDescriptor: sort }), ref: ref, dir: direction, className: className, onRowAction: onAction == null ? undefined : key => onAction(stringKey(key)), onSortChange: onSortChange == null ? undefined : descriptor => onSortChange(tableSort(descriptor)), style: state => ({
|
|
22
22
|
width: "100%",
|
|
23
23
|
minWidth: "max-content",
|
|
24
24
|
borderCollapse: "separate",
|
|
@@ -29,8 +29,9 @@ const TableRoot = forwardRef(function Table(properties, ref) {
|
|
|
29
29
|
overflow: "hidden",
|
|
30
30
|
fontFamily: "inherit",
|
|
31
31
|
fontSize: metrics.fontSize,
|
|
32
|
+
...dropTargetOutline(metrics, state.isDropTarget),
|
|
32
33
|
...style
|
|
33
|
-
} }) }) });
|
|
34
|
+
}) }) }) });
|
|
34
35
|
});
|
|
35
36
|
function tableSort(descriptor) {
|
|
36
37
|
return { column: stringKey(descriptor.column), direction: descriptor.direction };
|
|
@@ -68,7 +69,8 @@ const TableRowImplementation = forwardRef(function TableRow({ className, disable
|
|
|
68
69
|
return _jsx(AriaRow, { ...properties, ref: ref, className: state => dimmedClass(state.isDisabled, className ?? state.defaultClassName) ?? "", isDisabled: disabled, onAction: onAction, style: state => ({
|
|
69
70
|
...transition(metrics.visual, "background-color, color, outline-color"),
|
|
70
71
|
...itemPaint(metrics.visual, color, {
|
|
71
|
-
|
|
72
|
+
// What a drag would drop into shows as chosen.
|
|
73
|
+
selected: state.isSelected || state.isDropTarget === true,
|
|
72
74
|
hovered: responds && state.isHovered,
|
|
73
75
|
pressed: responds && state.isPressed,
|
|
74
76
|
focusVisible: false,
|
package/dist/tooltip.d.ts
CHANGED
|
@@ -4,7 +4,9 @@ import { type ButtonActionProps } from "./button.js";
|
|
|
4
4
|
import { type AriaOverlayInternals, type OverlayRootProps } from "./control/open-state.js";
|
|
5
5
|
import { type Direction } from "./foundation/direction.js";
|
|
6
6
|
import { type SurfaceOwnProps } from "./surface/surface.js";
|
|
7
|
-
export type TooltipRootProps = OverlayRootProps & Readonly<Pick<AriaTooltipTriggerProps, "
|
|
7
|
+
export type TooltipRootProps = OverlayRootProps & Readonly<Pick<AriaTooltipTriggerProps, "closeDelay" | "trigger">> & Readonly<{
|
|
8
|
+
/** Milliseconds the pointer rests on the trigger before the Tooltip opens: four Appearance transactions by default. */
|
|
9
|
+
delay?: number;
|
|
8
10
|
/** Whether the Tooltip is prevented from opening. */
|
|
9
11
|
disabled?: boolean;
|
|
10
12
|
/** Whether pressing the trigger closes the Tooltip. Defaults to `true`. */
|
|
@@ -18,6 +20,8 @@ export interface TooltipContentProps extends Omit<AriaTooltipProps, AriaOverlayI
|
|
|
18
20
|
readonly children?: ReactNode;
|
|
19
21
|
readonly className?: string;
|
|
20
22
|
readonly dir?: Direction;
|
|
23
|
+
/** DOM container that owns the positioned overlay's coordinate space. */
|
|
24
|
+
readonly portalContainer?: Element;
|
|
21
25
|
readonly style?: CSSProperties;
|
|
22
26
|
}
|
|
23
27
|
export declare const TooltipContent: import("react").ForwardRefExoticComponent<TooltipContentProps & import("react").RefAttributes<HTMLDivElement>>;
|
package/dist/tooltip.js
CHANGED
|
@@ -12,17 +12,19 @@ import { useVisual } from "./foundation/visual.js";
|
|
|
12
12
|
import { floatingShadow } from "./surface/shadow-options.js";
|
|
13
13
|
import { Surface } from "./surface/surface.js";
|
|
14
14
|
export function TooltipRoot({ children, delay, closeDelay, trigger, disabled, closeOnPress, ...state }) {
|
|
15
|
-
|
|
15
|
+
// A pointer resting on a trigger for four Appearance transactions is asking what it is.
|
|
16
|
+
const rest = useVisual().appearance.transaction.duration * 4;
|
|
17
|
+
return _jsx(AriaTooltipTrigger, { ...ariaOpenState(state), delay: delay ?? rest, closeDelay: closeDelay, trigger: trigger, isDisabled: disabled, shouldCloseOnPress: closeOnPress, children: children });
|
|
16
18
|
}
|
|
17
19
|
export const TooltipTrigger = forwardRef(function TooltipTrigger(properties, ref) {
|
|
18
20
|
return _jsx(Button, { ...properties, ref: ref });
|
|
19
21
|
});
|
|
20
|
-
export const TooltipContent = forwardRef(function TooltipContent({ children, className, color, material, radius, shadow, style, offset, placement = "top", dir, ...attributes }, ref) {
|
|
22
|
+
export const TooltipContent = forwardRef(function TooltipContent({ children, className, color, material, radius, shadow, style, offset, placement = "top", dir, portalContainer, ...attributes }, ref) {
|
|
21
23
|
const visual = useVisual();
|
|
22
24
|
const inset = scale(visual.spacing, "small");
|
|
23
25
|
const transition = overlayTransition(visual);
|
|
24
26
|
const direction = resolveDirection(dir, useDirection());
|
|
25
|
-
return _jsxs(_Fragment, { children: [_jsx(MotionStyle, {}), _jsx(AriaTooltip, { ...attributes, ref: ref, dir: direction, offset: offset ?? inset, placement: resolveDirectionalPlacement(placement, direction), className: overlayMotionClass, style: transition, children: _jsx(Surface, { dir: direction, className: className, color: color ?? "foreground", material: material, radius: radius, shadow: shadow ?? floatingShadow(visual.shadow), style: {
|
|
27
|
+
return _jsxs(_Fragment, { children: [_jsx(MotionStyle, {}), _jsx(AriaTooltip, { ...attributes, ref: ref, dir: direction, offset: offset ?? inset, placement: resolveDirectionalPlacement(placement, direction), UNSTABLE_portalContainer: portalContainer, className: overlayMotionClass, style: transition, children: _jsx(Surface, { dir: direction, className: className, color: color ?? "foreground", material: material, radius: radius, shadow: shadow ?? floatingShadow(visual.shadow), style: {
|
|
26
28
|
boxSizing: "border-box",
|
|
27
29
|
maxWidth: "28em",
|
|
28
30
|
paddingBlock: inset,
|
package/dist/tree.d.ts
CHANGED
|
@@ -41,11 +41,21 @@ export interface TreeContentProps extends AriaTreeItemContentProps {
|
|
|
41
41
|
readonly children: AriaTreeItemContentProps["children"];
|
|
42
42
|
}
|
|
43
43
|
export type TreeCollectionProps<T extends object = object> = AriaCollectionProps<T>;
|
|
44
|
+
export type TreeLoadMoreProps = Readonly<{
|
|
45
|
+
/** Asks for more Items once the end of the list comes near while scrolling. */
|
|
46
|
+
onLoadMore: () => void;
|
|
47
|
+
}>;
|
|
48
|
+
/**
|
|
49
|
+
* The end of a list shown in parts, such as a long folder: when scrolling brings it near, the
|
|
50
|
+
* list is asked for more. It is placed after the Items it follows, at their level, and draws nothing.
|
|
51
|
+
*/
|
|
52
|
+
declare function TreeLoadMore({ onLoadMore }: TreeLoadMoreProps): import("react").JSX.Element;
|
|
44
53
|
/** Hierarchical navigation with independently controlled expansion, selection, and actions. */
|
|
45
54
|
export declare const Tree: TreeRootComponent & {
|
|
46
55
|
Item: TreeItemComponent;
|
|
47
56
|
Content: import("react").ForwardRefExoticComponent<TreeContentProps & RefAttributes<Element>>;
|
|
48
57
|
Collection: typeof AriaCollection;
|
|
58
|
+
LoadMore: typeof TreeLoadMore;
|
|
49
59
|
};
|
|
50
60
|
export type TreeProps<T extends object = object> = TreeRootProps<T>;
|
|
51
61
|
export {};
|
package/dist/tree.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { createContext, forwardRef, useContext, useMemo } from "react";
|
|
3
|
-
import { Button as AriaButton, Collection as AriaCollection, Tree as AriaTree, TreeItem as AriaTreeItem, TreeItemContent as AriaTreeItemContent } from "react-aria-components";
|
|
3
|
+
import { Button as AriaButton, Collection as AriaCollection, Tree as AriaTree, TreeItem as AriaTreeItem, TreeItemContent as AriaTreeItemContent, TreeLoadMoreItem as AriaTreeLoadMoreItem } from "react-aria-components";
|
|
4
4
|
import { proportionalRadius, transition, useControlMetrics } from "./control/control.js";
|
|
5
|
-
import { itemPaint, itemStyle } from "./control/item.js";
|
|
5
|
+
import { dropTargetOutline, itemPaint, itemStyle } from "./control/item.js";
|
|
6
6
|
import { ariaSelection, stringKey, stringKeys } from "./control/selection.js";
|
|
7
7
|
import { AriaDirectionBoundary } from "./foundation/aria-direction.js";
|
|
8
8
|
import { colorOpacity } from "./foundation/color.js";
|
|
@@ -18,7 +18,7 @@ const TreeRootImplementation = forwardRef(function Tree(properties, ref) {
|
|
|
18
18
|
const itemRadius = metrics.radius;
|
|
19
19
|
const direction = resolveDirection(native.dir, useDirection());
|
|
20
20
|
const context = useMemo(() => ({ color, direction, interactive: selectionMode !== "none" || onAction != null, metrics, itemRadius }), [color, direction, metrics, itemRadius, onAction, selectionMode]);
|
|
21
|
-
return _jsx(TreeStyleContext.Provider, { value: context, children: _jsx(AriaDirectionBoundary, { direction: direction, children: _jsx(AriaTree, { ...native, shouldSelectOnPressUp: selectOnPressUp, ...ariaSelection(properties, "none"), ...(expanded !== undefined ? { expandedKeys: new Set(expanded) } : {}), ...(defaultExpanded !== undefined ? { defaultExpandedKeys: new Set(defaultExpanded) } : {}), ...(onExpandedChange !== undefined ? { onExpandedChange: (keys) => onExpandedChange(stringKeys(keys)) } : {}), ref: ref, dir: direction, className: className, onAction: onAction == null ? undefined : key => onAction(stringKey(key)), style: {
|
|
21
|
+
return _jsx(TreeStyleContext.Provider, { value: context, children: _jsx(AriaDirectionBoundary, { direction: direction, children: _jsx(AriaTree, { ...native, shouldSelectOnPressUp: selectOnPressUp, ...ariaSelection(properties, "none"), ...(expanded !== undefined ? { expandedKeys: new Set(expanded) } : {}), ...(defaultExpanded !== undefined ? { defaultExpandedKeys: new Set(defaultExpanded) } : {}), ...(onExpandedChange !== undefined ? { onExpandedChange: (keys) => onExpandedChange(stringKeys(keys)) } : {}), ref: ref, dir: direction, className: className, onAction: onAction == null ? undefined : key => onAction(stringKey(key)), style: state => ({
|
|
22
22
|
display: "grid",
|
|
23
23
|
alignContent: "start",
|
|
24
24
|
gap: 2,
|
|
@@ -28,8 +28,10 @@ const TreeRootImplementation = forwardRef(function Tree(properties, ref) {
|
|
|
28
28
|
outline: "none",
|
|
29
29
|
fontFamily: "inherit",
|
|
30
30
|
fontSize: metrics.fontSize,
|
|
31
|
+
borderRadius: metrics.radius,
|
|
32
|
+
...dropTargetOutline(metrics, state.isDropTarget),
|
|
31
33
|
...style
|
|
32
|
-
} }) }) });
|
|
34
|
+
}) }) }) });
|
|
33
35
|
});
|
|
34
36
|
/** Tree entries use the collection Item treatment as their own paint. */
|
|
35
37
|
const TreeItemImplementation = forwardRef(function TreeItem({ arrowNavigation, className, disabled = false, expandable, onAction, style, ...properties }, ref) {
|
|
@@ -39,7 +41,8 @@ const TreeItemImplementation = forwardRef(function TreeItem({ arrowNavigation, c
|
|
|
39
41
|
return {
|
|
40
42
|
...itemStyle(metrics, state.isDisabled),
|
|
41
43
|
...itemPaint(metrics.visual, color, {
|
|
42
|
-
|
|
44
|
+
// What a drag would drop into shows as chosen.
|
|
45
|
+
selected: state.isSelected || state.isDropTarget === true,
|
|
43
46
|
hovered: responds && state.isHovered,
|
|
44
47
|
pressed: responds && state.isPressed,
|
|
45
48
|
focusVisible: false,
|
|
@@ -75,6 +78,13 @@ const TreeContent = forwardRef(function TreeContent({ children }, ref) {
|
|
|
75
78
|
}), children: _jsx(ChevronRight, { ...iconProps(14), style: { ...transition(metrics.visual, "rotate"), rotate: state.isExpanded ? "90deg" : direction === "rtl" ? "180deg" : "0deg" } }) })
|
|
76
79
|
: _jsx("span", { "aria-hidden": "true", style: { flex: `0 0 ${box}px` } }), _jsx("span", { style: { flex: "1 1 auto", minWidth: 0, display: "flex", alignItems: "center", gap: metrics.gap }, children: typeof children === "function" ? children(state) : children })] }) });
|
|
77
80
|
});
|
|
81
|
+
/**
|
|
82
|
+
* The end of a list shown in parts, such as a long folder: when scrolling brings it near, the
|
|
83
|
+
* list is asked for more. It is placed after the Items it follows, at their level, and draws nothing.
|
|
84
|
+
*/
|
|
85
|
+
function TreeLoadMore({ onLoadMore }) {
|
|
86
|
+
return _jsx(AriaTreeLoadMoreItem, { onLoadMore: onLoadMore });
|
|
87
|
+
}
|
|
78
88
|
function useTreeStyle() {
|
|
79
89
|
const context = useContext(TreeStyleContext);
|
|
80
90
|
if (context == null)
|
|
@@ -85,5 +95,6 @@ function useTreeStyle() {
|
|
|
85
95
|
export const Tree = Object.assign(TreeRootImplementation, {
|
|
86
96
|
Item: TreeItemImplementation,
|
|
87
97
|
Content: TreeContent,
|
|
88
|
-
Collection: AriaCollection
|
|
98
|
+
Collection: AriaCollection,
|
|
99
|
+
LoadMore: TreeLoadMore
|
|
89
100
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { BeginPresentationMoveGesture } from "@phreshos/core";
|
|
2
2
|
import { type PointerEventHandler } from "react";
|
|
3
3
|
export interface WindowMoveHandle {
|
|
4
4
|
onPointerDown: PointerEventHandler<HTMLElement>;
|
|
@@ -8,4 +8,4 @@ export interface WindowMoveHandle {
|
|
|
8
8
|
onLostPointerCapture: PointerEventHandler<HTMLElement>;
|
|
9
9
|
}
|
|
10
10
|
/** Turns one DOM element into a move handle for any compatible host gesture. */
|
|
11
|
-
export default function useWindowMoveHandle(beginMoveGesture?:
|
|
11
|
+
export default function useWindowMoveHandle(beginMoveGesture?: BeginPresentationMoveGesture, onError?: (error: unknown) => void): WindowMoveHandle;
|
package/dist/window.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { HTMLAttributes, ReactNode } from "react";
|
|
2
|
-
import type {
|
|
2
|
+
import type { BeginPresentationMoveGesture } from "@phreshos/core";
|
|
3
3
|
import { type ButtonActionProps } from "./button.js";
|
|
4
4
|
import { type Color } from "./foundation/color.js";
|
|
5
5
|
import { type SurfaceProps } from "./surface/surface.js";
|
|
@@ -16,7 +16,7 @@ export interface WindowHeaderProps extends Omit<HTMLAttributes<HTMLDivElement>,
|
|
|
16
16
|
/** Base color inherited by header-owned text and icons. */
|
|
17
17
|
readonly color?: Color;
|
|
18
18
|
/** Hands an intentional header drag to its host after the pointer threshold. */
|
|
19
|
-
readonly beginMoveGesture?:
|
|
19
|
+
readonly beginMoveGesture?: BeginPresentationMoveGesture;
|
|
20
20
|
/** Whether the represented window is currently maximized. */
|
|
21
21
|
readonly maximized?: boolean;
|
|
22
22
|
/** Toggles the represented window between maximized and restored states. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phreshos/react-ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.50",
|
|
4
4
|
"description": "React components for coherent PhreshOS Program interfaces.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"dependencies": {
|
|
58
58
|
"@base-ui/react": "^1.7.0",
|
|
59
59
|
"@internationalized/date": "^3.12.3",
|
|
60
|
-
"@phreshos/core": "^0.1.
|
|
60
|
+
"@phreshos/core": "^0.1.67",
|
|
61
61
|
"colorjs.io": "^0.7.1",
|
|
62
62
|
"lucide-react": "^1.48.0",
|
|
63
63
|
"react-aria": "^3.51.0",
|