@phreshos/react-ui 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dialog.d.ts +2 -0
- package/dist/dialog.js +23 -21
- package/dist/panel.js +9 -9
- package/dist/popover.js +8 -8
- package/dist/surface/surface.d.ts +7 -0
- package/dist/surface/surface.js +16 -3
- package/dist/tooltip.js +11 -11
- package/package.json +2 -2
package/dist/dialog.d.ts
CHANGED
|
@@ -20,6 +20,8 @@ export interface DialogBackdropProps extends Omit<AriaModalOverlayProps, AriaOve
|
|
|
20
20
|
readonly dismissable?: boolean;
|
|
21
21
|
/** Whether Escape closes the Dialog. */
|
|
22
22
|
readonly keyboardDismissable?: boolean;
|
|
23
|
+
/** DOM container the Dialog is drawn in, such as one that scales what it holds; the document's body by default. */
|
|
24
|
+
readonly portalContainer?: Element;
|
|
23
25
|
readonly style?: CSSProperties;
|
|
24
26
|
}
|
|
25
27
|
export declare const DialogBackdrop: import("react").ForwardRefExoticComponent<DialogBackdropProps & import("react").RefAttributes<HTMLDivElement>>;
|
package/dist/dialog.js
CHANGED
|
@@ -11,7 +11,7 @@ import { scale } from "./foundation/scale.js";
|
|
|
11
11
|
import { containerPadding } from "./foundation/spacing.js";
|
|
12
12
|
import { useVisual } from "./foundation/visual.js";
|
|
13
13
|
import { floatingShadow } from "./surface/shadow-options.js";
|
|
14
|
-
import { Surface } from "./surface/surface.js";
|
|
14
|
+
import { FloatingLayer, Surface } from "./surface/surface.js";
|
|
15
15
|
export function DialogRoot({ children, ...state }) {
|
|
16
16
|
return _jsx(AriaDialogTrigger, { ...ariaOpenState(state), children: children });
|
|
17
17
|
}
|
|
@@ -22,7 +22,7 @@ export const DialogTrigger = forwardRef(function DialogTrigger(properties, ref)
|
|
|
22
22
|
const backdropDimming = 0.5;
|
|
23
23
|
/** The share of the Appearance material's blur a backdrop takes: lighter than a frosted Surface. */
|
|
24
24
|
const backdropBlurShare = 0.5;
|
|
25
|
-
export const DialogBackdrop = forwardRef(function DialogBackdrop({ children, className, dir, dismissable = false, keyboardDismissable = true, style, ...attributes }, ref) {
|
|
25
|
+
export const DialogBackdrop = forwardRef(function DialogBackdrop({ children, className, dir, dismissable = false, keyboardDismissable = true, portalContainer, style, ...attributes }, ref) {
|
|
26
26
|
const visual = useVisual();
|
|
27
27
|
const inset = scale(visual.spacing, "medium");
|
|
28
28
|
const colors = visual.colors;
|
|
@@ -33,7 +33,7 @@ export const DialogBackdrop = forwardRef(function DialogBackdrop({ children, cla
|
|
|
33
33
|
const blur = visual.material.backdrop > 0 ? `blur(${visual.material.backdrop * backdropBlurShare}px)` : undefined;
|
|
34
34
|
const transition = overlayTransition(visual);
|
|
35
35
|
const direction = resolveDirection(dir, useDirection());
|
|
36
|
-
return _jsxs(_Fragment, { children: [_jsx(MotionStyle, {}), _jsx(AriaModalOverlay, { ...attributes, isDismissable: dismissable, isKeyboardDismissDisabled: !keyboardDismissable, ref: ref, dir: direction, className: [backdropMotionClass, className].filter(Boolean).join(" "), style: {
|
|
36
|
+
return _jsxs(_Fragment, { children: [_jsx(MotionStyle, {}), _jsx(AriaModalOverlay, { ...attributes, isDismissable: dismissable, isKeyboardDismissDisabled: !keyboardDismissable, UNSTABLE_portalContainer: portalContainer, ref: ref, dir: direction, className: [backdropMotionClass, className].filter(Boolean).join(" "), style: {
|
|
37
37
|
...transition,
|
|
38
38
|
backdropFilter: blur,
|
|
39
39
|
WebkitBackdropFilter: blur,
|
|
@@ -63,24 +63,24 @@ export const DialogContent = forwardRef(function DialogContent({ children, class
|
|
|
63
63
|
maxWidth: maxWidth ?? `calc(100vw - ${inset * 2}px)`,
|
|
64
64
|
maxHeight: `calc(100vh - ${inset * 2}px)`,
|
|
65
65
|
outline: "none"
|
|
66
|
-
}, children: _jsx(Surface, { className: className, color: color, material: material,
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
maxHeight: "inherit",
|
|
73
|
-
padding,
|
|
74
|
-
overflow: "hidden",
|
|
75
|
-
...surfaceStyle
|
|
76
|
-
}, children: _jsx(AriaDialog, { ...properties, ref: ref, style: {
|
|
77
|
-
display: "grid",
|
|
78
|
-
gap: inset,
|
|
79
|
-
minWidth: 0,
|
|
80
|
-
minHeight: 0,
|
|
66
|
+
}, children: _jsx(FloatingLayer, { children: _jsx(Surface, { className: className, color: color, material: material,
|
|
67
|
+
// Dialog content is composed by its consumer, so no owned rounded shape
|
|
68
|
+
// sits at a known inset; it keeps the plain Appearance radius like Popover.
|
|
69
|
+
radius: radius, shadow: shadow ?? floatingShadow(visual.shadow), style: {
|
|
70
|
+
boxSizing: "border-box",
|
|
71
|
+
width: "100%",
|
|
81
72
|
maxHeight: "inherit",
|
|
82
|
-
|
|
83
|
-
|
|
73
|
+
padding,
|
|
74
|
+
overflow: "hidden",
|
|
75
|
+
...surfaceStyle
|
|
76
|
+
}, children: _jsx(AriaDialog, { ...properties, ref: ref, style: {
|
|
77
|
+
display: "grid",
|
|
78
|
+
gap: inset,
|
|
79
|
+
minWidth: 0,
|
|
80
|
+
minHeight: 0,
|
|
81
|
+
maxHeight: "inherit",
|
|
82
|
+
outline: "none"
|
|
83
|
+
}, children: children }) }) }) })] });
|
|
84
84
|
});
|
|
85
85
|
export const DialogHeader = forwardRef(function DialogHeader({ style, ...properties }, ref) {
|
|
86
86
|
const gap = scale(useVisual().spacing, "small");
|
|
@@ -109,7 +109,9 @@ export const DialogDescription = forwardRef(function DialogDescription({ style,
|
|
|
109
109
|
} });
|
|
110
110
|
});
|
|
111
111
|
export const DialogBody = forwardRef(function DialogBody({ style, ...properties }, ref) {
|
|
112
|
-
|
|
112
|
+
// What a Body holds stands apart, as the Header's and the Footer's parts do.
|
|
113
|
+
const gap = scale(useVisual().spacing, "medium");
|
|
114
|
+
return _jsx("div", { ...properties, ref: ref, style: { display: "grid", gap, minWidth: 0, minHeight: 0, ...style } });
|
|
113
115
|
});
|
|
114
116
|
export const DialogFooter = forwardRef(function DialogFooter({ style, ...properties }, ref) {
|
|
115
117
|
const gap = scale(useVisual().spacing, "small");
|
package/dist/panel.js
CHANGED
|
@@ -6,7 +6,7 @@ import { resolveRadius } from "./foundation/radius.js";
|
|
|
6
6
|
import { scale } from "./foundation/scale.js";
|
|
7
7
|
import { useVisual } from "./foundation/visual.js";
|
|
8
8
|
import { paintClass, usePaintClasses } from "./surface/paint-class.js";
|
|
9
|
-
import { Surface } from "./surface/surface.js";
|
|
9
|
+
import { FloatingLayer, Surface } from "./surface/surface.js";
|
|
10
10
|
import { containerPadding } from "./foundation/spacing.js";
|
|
11
11
|
const PanelContext = createContext({ color: undefined, hasHeader: false, radius: undefined });
|
|
12
12
|
export const PanelHeader = forwardRef(function PanelHeader({ style, ...properties }, ref) {
|
|
@@ -29,14 +29,14 @@ export const PanelRoot = forwardRef(function Panel({ children, style, ...propert
|
|
|
29
29
|
const hasHeader = Children.toArray(children).some(child => isValidElement(child) && child.type === PanelHeader);
|
|
30
30
|
// The shell and its content share one radius: the Appearance radius.
|
|
31
31
|
const radius = resolveRadius(properties.radius ?? "medium", useVisual().radius);
|
|
32
|
-
return _jsx(PanelContext.Provider, { value: { color: properties.color, hasHeader, radius }, children: _jsx(Surface, { material: "full", ...properties, ref: ref, radius: radius, style: {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
32
|
+
return _jsx(PanelContext.Provider, { value: { color: properties.color, hasHeader, radius }, children: _jsx(FloatingLayer, { children: _jsx(Surface, { material: "full", ...properties, ref: ref, radius: radius, style: {
|
|
33
|
+
display: "grid",
|
|
34
|
+
gridTemplateRows: hasHeader ? "auto minmax(0, 1fr)" : "minmax(0, 1fr)",
|
|
35
|
+
minWidth: 0,
|
|
36
|
+
minHeight: 0,
|
|
37
|
+
maxHeight: "inherit",
|
|
38
|
+
...style
|
|
39
|
+
}, children: children }) }) });
|
|
40
40
|
});
|
|
41
41
|
export const PanelContent = forwardRef(function PanelContent({ className, style, ...properties }, ref) {
|
|
42
42
|
const { spacing } = useVisual();
|
package/dist/popover.js
CHANGED
|
@@ -10,7 +10,7 @@ import { resolveDirectionalPlacement } from "./foundation/overlay-placement.js";
|
|
|
10
10
|
import { scale } from "./foundation/scale.js";
|
|
11
11
|
import { useVisual } from "./foundation/visual.js";
|
|
12
12
|
import { floatingShadow } from "./surface/shadow-options.js";
|
|
13
|
-
import { Surface } from "./surface/surface.js";
|
|
13
|
+
import { FloatingLayer, Surface } from "./surface/surface.js";
|
|
14
14
|
export function PopoverRoot({ children, ...state }) {
|
|
15
15
|
return _jsx(AriaDialogTrigger, { ...ariaOpenState(state), children: children });
|
|
16
16
|
}
|
|
@@ -22,13 +22,13 @@ const PositionedContent = forwardRef(function PositionedContent({ children, clas
|
|
|
22
22
|
const inset = scale(visual.spacing, "small");
|
|
23
23
|
const transition = overlayTransition(visual);
|
|
24
24
|
const direction = resolveDirection(dir, useDirection());
|
|
25
|
-
return _jsxs(_Fragment, { children: [_jsx(MotionStyle, {}), _jsx(AriaPopover, { ...attributes, isNonModal: nonModal, 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, material: material, shadow: shadow ?? floatingShadow(visual.shadow), radius: radius, style: {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
25
|
+
return _jsxs(_Fragment, { children: [_jsx(MotionStyle, {}), _jsx(AriaPopover, { ...attributes, isNonModal: nonModal, ref: ref, dir: direction, offset: offset ?? inset, placement: resolveDirectionalPlacement(placement, direction), UNSTABLE_portalContainer: portalContainer, className: overlayMotionClass, style: transition, children: _jsx(FloatingLayer, { children: _jsx(Surface, { dir: direction, className: className, color: color, material: material, shadow: shadow ?? floatingShadow(visual.shadow), radius: radius, style: {
|
|
26
|
+
boxSizing: "border-box",
|
|
27
|
+
maxWidth: `calc(100vw - ${inset * 2}px)`,
|
|
28
|
+
maxHeight: `calc(100vh - ${inset * 2}px)`,
|
|
29
|
+
outline: "none",
|
|
30
|
+
...style
|
|
31
|
+
}, children: children }) }) })] });
|
|
32
32
|
});
|
|
33
33
|
export const PopoverContent = forwardRef(function PopoverContent(properties, ref) {
|
|
34
34
|
return _jsx(PositionedContent, { ...properties, ref: ref });
|
|
@@ -47,6 +47,13 @@ export interface SurfaceInteraction {
|
|
|
47
47
|
/** Marks a value-holding Surface whose current value is rejected. */
|
|
48
48
|
readonly invalid?: boolean;
|
|
49
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* A layer that floats above everything, such as a popover, a dialog, or a panel: it is not inside the
|
|
52
|
+
* Surface it was opened from, so what it holds has nothing around it to keep apart from.
|
|
53
|
+
*/
|
|
54
|
+
export declare function FloatingLayer({ children }: Readonly<{
|
|
55
|
+
children: ReactNode;
|
|
56
|
+
}>): import("react").JSX.Element;
|
|
50
57
|
/**
|
|
51
58
|
* How far a nested Surface keeps from the one it sits on: farther on a dark canvas, where
|
|
52
59
|
* differences read smaller.
|
package/dist/surface/surface.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { createContext, createElement, forwardRef, useContext, useId, useInsertionEffect } from "react";
|
|
3
|
-
import { canvasDarkness, colorOpacity, contrast, mixColor, readableColor, recessColor, resolveColor, separateColor } from "../foundation/color.js";
|
|
3
|
+
import { canvasDarkness, colorOpacity, contrast, mixColor, perceivedDistance, readableColor, recessColor, resolveColor, separateColor } from "../foundation/color.js";
|
|
4
4
|
import { resolveRadius } from "../foundation/radius.js";
|
|
5
5
|
import { useVisual } from "../foundation/visual.js";
|
|
6
6
|
import { grainSeed, grainSize, grainTexture } from "./grain.js";
|
|
@@ -9,6 +9,13 @@ import { resolveMaterialOptions } from "./material-options.js";
|
|
|
9
9
|
import { resolveShadowOptions, shadowStyle } from "./shadow-options.js";
|
|
10
10
|
/** The resting paint of the nearest painted Surface around, which a nested Surface keeps apart from. */
|
|
11
11
|
const SurroundingPaint = createContext(null);
|
|
12
|
+
/**
|
|
13
|
+
* A layer that floats above everything, such as a popover, a dialog, or a panel: it is not inside the
|
|
14
|
+
* Surface it was opened from, so what it holds has nothing around it to keep apart from.
|
|
15
|
+
*/
|
|
16
|
+
export function FloatingLayer({ children }) {
|
|
17
|
+
return _jsx(SurroundingPaint.Provider, { value: null, children: children });
|
|
18
|
+
}
|
|
12
19
|
/**
|
|
13
20
|
* How far a nested Surface keeps from the one it sits on: farther on a dark canvas, where
|
|
14
21
|
* differences read smaller.
|
|
@@ -107,14 +114,20 @@ export function surfacePaint(visual, color, depth, options, shadowOptions, inter
|
|
|
107
114
|
const darkness = canvasDarkness(colors);
|
|
108
115
|
// A recess moves away from its surroundings toward whichever extreme has
|
|
109
116
|
// room, by one constant perceptual difference on any canvas.
|
|
110
|
-
const
|
|
117
|
+
const recess = depth === "recessed" ? surfaceColor(color, depth, colors) : base;
|
|
118
|
+
// A recess that would vanish into paint like its own, such as a field or a checkbox in a well,
|
|
119
|
+
// sinks one step below that paint instead.
|
|
120
|
+
const own = depth === "recessed" && surroundings !== null && (perceivedDistance(recess, surroundings) ?? Infinity) < nestingDistance(darkness)
|
|
121
|
+
? recessColor(surroundings)
|
|
122
|
+
: recess;
|
|
111
123
|
// A clear Surface, with no depth or a transparent color, has no substance of
|
|
112
124
|
// its own: it paints nothing at rest, takes the content color of whatever it
|
|
113
125
|
// sits on, and only reveals interaction as a veil. With no depth, a color
|
|
114
126
|
// other than the neutral one colors its content instead of a fill.
|
|
115
127
|
const clear = depth === "none" || base === "transparent";
|
|
116
128
|
// A raised or level Surface nested in another keeps apart from it, however deep the nesting goes.
|
|
117
|
-
// A recess keeps its own constant depth below its color, so a well reads the same wherever it is
|
|
129
|
+
// A recess keeps its own constant depth below its color, so a well reads the same wherever it is,
|
|
130
|
+
// unless it would vanish into what it sits on (above).
|
|
118
131
|
const rest = clear || depth === "recessed" || surroundings === null ? own : separateColor(own, surroundings, nestingDistance(darkness));
|
|
119
132
|
const tinted = depth === "none" && base !== "transparent" && base !== colors.default;
|
|
120
133
|
const fill = clear
|
package/dist/tooltip.js
CHANGED
|
@@ -11,7 +11,7 @@ import { scale } from "./foundation/scale.js";
|
|
|
11
11
|
import { useVisual } from "./foundation/visual.js";
|
|
12
12
|
import { timing } from "./foundation/timing.js";
|
|
13
13
|
import { floatingShadow } from "./surface/shadow-options.js";
|
|
14
|
-
import { Surface } from "./surface/surface.js";
|
|
14
|
+
import { FloatingLayer, Surface } from "./surface/surface.js";
|
|
15
15
|
export function TooltipRoot({ children, delay, closeDelay, trigger, disabled, closeOnPress, ...state }) {
|
|
16
16
|
// A pointer resting on a trigger for four changes in place is asking what it is.
|
|
17
17
|
const rest = timing("change", { tempo: useVisual().appearance.tempo }).duration * 4;
|
|
@@ -25,16 +25,16 @@ export const TooltipContent = forwardRef(function TooltipContent({ children, cla
|
|
|
25
25
|
const inset = scale(visual.spacing, "small");
|
|
26
26
|
const transition = overlayTransition(visual);
|
|
27
27
|
const direction = resolveDirection(dir, useDirection());
|
|
28
|
-
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: {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
28
|
+
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(FloatingLayer, { children: _jsx(Surface, { dir: direction, className: className, color: color ?? "foreground", material: material, radius: radius, shadow: shadow ?? floatingShadow(visual.shadow), style: {
|
|
29
|
+
boxSizing: "border-box",
|
|
30
|
+
maxWidth: "28em",
|
|
31
|
+
paddingBlock: inset,
|
|
32
|
+
paddingInline: inset * 1.5,
|
|
33
|
+
outline: "none",
|
|
34
|
+
fontSize: controlFontSizes.small,
|
|
35
|
+
lineHeight: controlLineHeight,
|
|
36
|
+
...style
|
|
37
|
+
}, children: children }) }) })] });
|
|
38
38
|
});
|
|
39
39
|
/** A description shown from the focus and hover state of its trigger. */
|
|
40
40
|
export const Tooltip = Object.assign(TooltipRoot, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phreshos/react-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
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.
|
|
60
|
+
"@phreshos/core": "^0.3.0",
|
|
61
61
|
"colorjs.io": "^0.7.1",
|
|
62
62
|
"lucide-react": "^1.48.0",
|
|
63
63
|
"react-aria": "^3.51.0",
|