@phreshos/react-ui 0.1.36 → 0.1.38
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/README.md +147 -167
- package/dist/accordion.d.ts +7 -6
- package/dist/accordion.js +5 -5
- package/dist/alert-dialog.d.ts +2 -2
- package/dist/alert-dialog.js +3 -1
- package/dist/alert.d.ts +17 -0
- package/dist/alert.js +30 -0
- package/dist/app-layout.d.ts +13 -0
- package/dist/app-layout.js +84 -0
- package/dist/button.d.ts +31 -27
- package/dist/button.js +48 -40
- package/dist/calendar-layout.d.ts +9 -5
- package/dist/calendar-layout.js +67 -78
- package/dist/calendar-trigger.d.ts +4 -4
- package/dist/calendar-trigger.js +7 -29
- package/dist/calendar.d.ts +2 -2
- package/dist/calendar.js +6 -5
- package/dist/checkbox.d.ts +4 -4
- package/dist/checkbox.js +16 -6
- package/dist/color-area.d.ts +20 -0
- package/dist/color-area.js +30 -0
- package/dist/color-field.d.ts +17 -0
- package/dist/color-field.js +17 -0
- package/dist/color-picker.d.ts +24 -0
- package/dist/color-picker.js +30 -0
- package/dist/color-slider.d.ts +19 -0
- package/dist/color-slider.js +29 -0
- package/dist/color-swatch-picker.d.ts +23 -0
- package/dist/color-swatch-picker.js +36 -0
- package/dist/color-swatch.d.ts +18 -0
- package/dist/color-swatch.js +20 -0
- package/dist/combo-box.d.ts +18 -10
- package/dist/combo-box.js +43 -58
- package/dist/context-menu.d.ts +14 -10
- package/dist/context-menu.js +7 -6
- package/dist/control/color-thumb.d.ts +13 -0
- package/dist/control/color-thumb.js +33 -0
- package/dist/control/color-value.d.ts +6 -0
- package/dist/control/color-value.js +7 -0
- package/dist/control/control.d.ts +60 -0
- package/dist/control/control.js +71 -0
- package/dist/control/field-button.d.ts +13 -0
- package/dist/control/field-button.js +28 -0
- package/dist/control/field.d.ts +20 -0
- package/dist/control/field.js +34 -0
- package/dist/control/icon.d.ts +11 -0
- package/dist/control/icon.js +8 -0
- package/dist/control/item.d.ts +37 -0
- package/dist/control/item.js +57 -0
- package/dist/control/open-state.d.ts +25 -0
- package/dist/control/open-state.js +8 -0
- package/dist/control/selection-track.d.ts +39 -0
- package/dist/control/selection-track.js +122 -0
- package/dist/control/selection.d.ts +44 -0
- package/dist/{selection.js → control/selection.js} +16 -0
- package/dist/control/surface-render.d.ts +10 -0
- package/dist/control/surface-render.js +12 -0
- package/dist/control/text-control.d.ts +32 -0
- package/dist/control/text-control.js +31 -0
- package/dist/control/toggle.d.ts +32 -0
- package/dist/control/toggle.js +80 -0
- package/dist/date-control.d.ts +9 -9
- package/dist/date-control.js +31 -34
- package/dist/date-field.d.ts +7 -6
- package/dist/date-field.js +8 -6
- package/dist/date-picker.d.ts +13 -6
- package/dist/date-picker.js +9 -6
- package/dist/date-range-picker.d.ts +15 -6
- package/dist/date-range-picker.js +12 -9
- package/dist/dialog.d.ts +29 -15
- package/dist/dialog.js +37 -28
- package/dist/disclosure.d.ts +8 -7
- package/dist/disclosure.js +31 -52
- package/dist/drop-zone.d.ts +18 -0
- package/dist/drop-zone.js +32 -0
- package/dist/dropdown-menu.d.ts +11 -8
- package/dist/dropdown-menu.js +5 -4
- package/dist/fieldset.d.ts +13 -0
- package/dist/fieldset.js +26 -0
- package/dist/file-trigger.d.ts +13 -0
- package/dist/file-trigger.js +6 -0
- package/dist/flex.d.ts +1 -1
- package/dist/flex.js +5 -4
- package/dist/foundation/appearance.d.ts +83 -0
- package/dist/foundation/appearance.js +38 -0
- package/dist/{aria-direction.js → foundation/aria-direction.js} +3 -1
- package/dist/foundation/color.d.ts +61 -0
- package/dist/foundation/color.js +247 -0
- package/dist/{layout.d.ts → foundation/layout.d.ts} +6 -4
- package/dist/{layout.js → foundation/layout.js} +7 -5
- package/dist/foundation/motion-style.d.ts +9 -0
- package/dist/foundation/motion-style.js +50 -0
- package/dist/foundation/preferences.d.ts +15 -0
- package/dist/{ui-provider.d.ts → foundation/provider.d.ts} +9 -5
- package/dist/{ui-provider.js → foundation/provider.js} +18 -27
- package/dist/{radius.d.ts → foundation/radius.d.ts} +6 -3
- package/dist/foundation/radius.js +11 -0
- package/dist/foundation/spacing.d.ts +11 -0
- package/dist/foundation/spacing.js +4 -0
- package/dist/foundation/visual.d.ts +42 -0
- package/dist/{appearance-context.js → foundation/visual.js} +41 -27
- package/dist/grid.d.ts +1 -1
- package/dist/grid.js +5 -4
- package/dist/icons/main.d.ts +5 -3
- package/dist/icons/main.js +5 -3
- package/dist/input.d.ts +2 -2
- package/dist/input.js +9 -7
- package/dist/list-box.d.ts +24 -19
- package/dist/list-box.js +52 -109
- package/dist/main.d.ts +28 -17
- package/dist/main.js +22 -9
- package/dist/menu.d.ts +28 -32
- package/dist/menu.js +47 -93
- package/dist/number-field.d.ts +17 -0
- package/dist/number-field.js +28 -0
- package/dist/panel.d.ts +10 -5
- package/dist/panel.js +33 -12
- package/dist/popover.d.ts +26 -12
- package/dist/popover.js +22 -15
- package/dist/progress-bar.d.ts +8 -10
- package/dist/progress-bar.js +18 -34
- package/dist/radio.d.ts +15 -12
- package/dist/radio.js +27 -37
- package/dist/range-calendar.d.ts +5 -3
- package/dist/range-calendar.js +8 -7
- package/dist/scroll-area.d.ts +2 -2
- package/dist/scroll-area.js +10 -9
- package/dist/segmented-control.d.ts +23 -0
- package/dist/segmented-control.js +38 -0
- package/dist/select.d.ts +40 -13
- package/dist/select.js +63 -18
- package/dist/slider.d.ts +7 -3
- package/dist/slider.js +51 -50
- package/dist/spinner.d.ts +5 -8
- package/dist/spinner.js +12 -27
- package/dist/surface/grain.d.ts +12 -0
- package/dist/surface/grain.js +65 -0
- package/dist/{material-options.d.ts → surface/material-options.d.ts} +1 -2
- package/dist/{material-options.js → surface/material-options.js} +2 -2
- package/dist/surface/paint-class.d.ts +13 -0
- package/dist/surface/paint-class.js +47 -0
- package/dist/{shadow-options.d.ts → surface/shadow-options.d.ts} +13 -1
- package/dist/{shadow-options.js → surface/shadow-options.js} +17 -2
- package/dist/surface/surface.d.ts +80 -0
- package/dist/surface/surface.js +239 -0
- package/dist/switch.d.ts +4 -5
- package/dist/switch.js +17 -8
- package/dist/table.d.ts +29 -32
- package/dist/table.js +68 -106
- package/dist/tabs.d.ts +16 -15
- package/dist/tabs.js +44 -86
- package/dist/textarea.d.ts +2 -2
- package/dist/textarea.js +10 -14
- package/dist/time-field.d.ts +6 -6
- package/dist/time-field.js +8 -6
- package/dist/toolbar.d.ts +6 -4
- package/dist/toolbar.js +16 -15
- package/dist/tooltip.d.ts +17 -8
- package/dist/tooltip.js +17 -15
- package/dist/tree.d.ts +22 -27
- package/dist/tree.js +54 -99
- package/dist/window.d.ts +4 -4
- package/dist/window.js +18 -20
- package/package.json +3 -3
- package/dist/appearance-context.d.ts +0 -54
- package/dist/appearance.d.ts +0 -11
- package/dist/appearance.js +0 -11
- package/dist/color.d.ts +0 -69
- package/dist/color.js +0 -192
- package/dist/control-surface.d.ts +0 -20
- package/dist/control-surface.js +0 -11
- package/dist/control.d.ts +0 -70
- package/dist/control.js +0 -105
- package/dist/field-style.d.ts +0 -3
- package/dist/field-style.js +0 -12
- package/dist/material-paint.d.ts +0 -13
- package/dist/material-paint.js +0 -119
- package/dist/motion-style.d.ts +0 -13
- package/dist/motion-style.js +0 -75
- package/dist/preferences.d.ts +0 -12
- package/dist/radius.js +0 -11
- package/dist/readiness.d.ts +0 -37
- package/dist/readiness.js +0 -134
- package/dist/selection.d.ts +0 -18
- package/dist/spacing.d.ts +0 -8
- package/dist/spacing.js +0 -8
- package/dist/surface-edge.d.ts +0 -11
- package/dist/surface-edge.js +0 -55
- package/dist/surface.d.ts +0 -27
- package/dist/surface.js +0 -92
- package/dist/text-control.d.ts +0 -10
- package/dist/text-control.js +0 -0
- package/dist/toggle-indicator.d.ts +0 -18
- package/dist/toggle-indicator.js +0 -49
- /package/dist/{aria-direction.d.ts → foundation/aria-direction.d.ts} +0 -0
- /package/dist/{direction.d.ts → foundation/direction.d.ts} +0 -0
- /package/dist/{direction.js → foundation/direction.js} +0 -0
- /package/dist/{overlay-placement.d.ts → foundation/overlay-placement.d.ts} +0 -0
- /package/dist/{overlay-placement.js → foundation/overlay-placement.js} +0 -0
- /package/dist/{preferences.js → foundation/preferences.js} +0 -0
- /package/dist/{scale.d.ts → foundation/scale.d.ts} +0 -0
- /package/dist/{scale.js → foundation/scale.js} +0 -0
package/dist/dialog.js
CHANGED
|
@@ -1,32 +1,36 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef } from "react";
|
|
3
3
|
import { Dialog as AriaDialog, DialogTrigger as AriaDialogTrigger, Heading as AriaHeading, Modal as AriaModal, ModalOverlay as AriaModalOverlay, Text as AriaText } from "react-aria-components";
|
|
4
|
-
import { useAppearance } from "./ui-provider.js";
|
|
5
|
-
import { useResolvedAppearance } from "./appearance-context.js";
|
|
6
|
-
import { colorOpacity, orderColors, resolveColor } from "./color.js";
|
|
7
|
-
import { controlFontSizes, controlFontWeight, controlOpacity } from "./control.js";
|
|
8
4
|
import { Button } from "./button.js";
|
|
9
|
-
import
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import { resolveDirection, useDirection } from "./direction.js";
|
|
13
|
-
|
|
14
|
-
|
|
5
|
+
import { controlFontSizes, controlFontWeight, controlOpacity } from "./control/control.js";
|
|
6
|
+
import { ariaOpenState } from "./control/open-state.js";
|
|
7
|
+
import { colorOpacity, darkCanvas } from "./foundation/color.js";
|
|
8
|
+
import { resolveDirection, useDirection } from "./foundation/direction.js";
|
|
9
|
+
import MotionStyle, { backdropMotionClass, overlayMotionClass, overlayTransition } from "./foundation/motion-style.js";
|
|
10
|
+
import { scale } from "./foundation/scale.js";
|
|
11
|
+
import { useVisual } from "./foundation/visual.js";
|
|
12
|
+
import { floatingShadow } from "./surface/shadow-options.js";
|
|
13
|
+
import { Surface } from "./surface/surface.js";
|
|
14
|
+
export function DialogRoot({ children, ...state }) {
|
|
15
|
+
return _jsx(AriaDialogTrigger, { ...ariaOpenState(state), children: children });
|
|
15
16
|
}
|
|
16
17
|
export const DialogTrigger = forwardRef(function DialogTrigger(properties, ref) {
|
|
17
18
|
return _jsx(Button, { ...properties, ref: ref });
|
|
18
19
|
});
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
|
|
20
|
+
// A blurred backdrop still dims a little, so the Dialog stays distinct on a
|
|
21
|
+
// light canvas where blur alone barely separates it.
|
|
22
|
+
const backdropDimming = { dim: 0.32, blur: 0.16 };
|
|
23
|
+
export const DialogBackdrop = forwardRef(function DialogBackdrop({ children, className, dir, dismissable = false, keyboardDismissable = true, style, variant = "dim", ...attributes }, ref) {
|
|
24
|
+
const visual = useVisual();
|
|
25
|
+
const inset = scale(visual.spacing, "medium");
|
|
26
|
+
const colors = visual.colors;
|
|
27
|
+
// The backdrop dims toward whichever Appearance color is darker, in any Theme.
|
|
28
|
+
const darker = darkCanvas(colors) ? colors.background : colors.foreground;
|
|
29
|
+
const backdrop = colorOpacity(darker, backdropDimming[variant]);
|
|
30
|
+
const blur = variant === "blur" && visual.material.backdrop > 0 ? `blur(${visual.material.backdrop}px)` : undefined;
|
|
31
|
+
const transition = overlayTransition(visual);
|
|
32
|
+
const direction = resolveDirection(dir, useDirection());
|
|
33
|
+
return _jsxs(_Fragment, { children: [_jsx(MotionStyle, {}), _jsx(AriaModalOverlay, { ...attributes, isDismissable: dismissable, isKeyboardDismissDisabled: !keyboardDismissable, ref: ref, dir: direction, className: [backdropMotionClass, className].filter(Boolean).join(" "), style: {
|
|
30
34
|
...transition,
|
|
31
35
|
position: "fixed",
|
|
32
36
|
inset: 0,
|
|
@@ -37,20 +41,25 @@ export const DialogBackdrop = forwardRef(function DialogBackdrop({ className, co
|
|
|
37
41
|
padding: inset,
|
|
38
42
|
overflow: "auto",
|
|
39
43
|
background: backdrop,
|
|
44
|
+
backdropFilter: blur,
|
|
45
|
+
WebkitBackdropFilter: blur,
|
|
40
46
|
...style
|
|
41
|
-
} })] });
|
|
47
|
+
}, children: children })] });
|
|
42
48
|
});
|
|
43
49
|
export const DialogContent = forwardRef(function DialogContent({ children, className, color, material, radius, shadow, style, ...properties }, ref) {
|
|
44
|
-
const
|
|
45
|
-
const inset = scale(
|
|
46
|
-
const transition = overlayTransition(
|
|
50
|
+
const visual = useVisual();
|
|
51
|
+
const inset = scale(visual.spacing, "medium");
|
|
52
|
+
const transition = overlayTransition(visual);
|
|
47
53
|
const direction = resolveDirection(properties.dir, useDirection());
|
|
48
54
|
return _jsxs(_Fragment, { children: [_jsx(MotionStyle, {}), _jsx(AriaModal, { dir: direction, className: overlayMotionClass, style: {
|
|
49
55
|
...transition,
|
|
50
56
|
width: `min(32rem, calc(100vw - ${inset * 2}px))`,
|
|
51
57
|
maxHeight: `calc(100vh - ${inset * 2}px)`,
|
|
52
58
|
outline: "none"
|
|
53
|
-
}, children: _jsx(Surface, { className: className, color: color, material: material,
|
|
59
|
+
}, children: _jsx(Surface, { className: className, color: color, material: material,
|
|
60
|
+
// Dialog content is composed by its consumer, so no owned rounded shape
|
|
61
|
+
// sits at a known inset; it keeps the plain Appearance radius like Popover.
|
|
62
|
+
radius: radius, shadow: shadow ?? floatingShadow(visual.shadow), style: {
|
|
54
63
|
boxSizing: "border-box",
|
|
55
64
|
width: "100%",
|
|
56
65
|
maxHeight: "inherit",
|
|
@@ -67,7 +76,7 @@ export const DialogContent = forwardRef(function DialogContent({ children, class
|
|
|
67
76
|
}, children: children }) }) })] });
|
|
68
77
|
});
|
|
69
78
|
export const DialogHeader = forwardRef(function DialogHeader({ style, ...properties }, ref) {
|
|
70
|
-
const gap = scale(
|
|
79
|
+
const gap = scale(useVisual().spacing, "small");
|
|
71
80
|
return _jsx("div", { ...properties, ref: ref, style: { display: "grid", gap, minWidth: 0, ...style } });
|
|
72
81
|
});
|
|
73
82
|
export const DialogTitle = forwardRef(function DialogTitle({ style, ...properties }, ref) {
|
|
@@ -95,7 +104,7 @@ export const DialogBody = forwardRef(function DialogBody({ style, ...properties
|
|
|
95
104
|
return _jsx("div", { ...properties, ref: ref, style: { minWidth: 0, minHeight: 0, ...style } });
|
|
96
105
|
});
|
|
97
106
|
export const DialogFooter = forwardRef(function DialogFooter({ style, ...properties }, ref) {
|
|
98
|
-
const gap = scale(
|
|
107
|
+
const gap = scale(useVisual().spacing, "small");
|
|
99
108
|
return _jsx("div", { ...properties, ref: ref, style: { display: "flex", justifyContent: "flex-end", flexWrap: "wrap", gap, minWidth: 0, ...style } });
|
|
100
109
|
});
|
|
101
110
|
export const DialogClose = forwardRef(function DialogClose(properties, ref) {
|
package/dist/disclosure.d.ts
CHANGED
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
import type { CSSProperties, ReactElement, ReactNode } from "react";
|
|
2
2
|
import type { ButtonProps as AriaButtonProps, DisclosurePanelProps as AriaDisclosurePanelProps, DisclosureProps as AriaDisclosureProps } from "react-aria-components";
|
|
3
|
-
import type {
|
|
4
|
-
import type { RadiusProps } from "./radius.js";
|
|
5
|
-
import type { ScaleLevel } from "./scale.js";
|
|
6
|
-
import { type Spacing } from "./spacing.js";
|
|
3
|
+
import type { Color } from "./foundation/color.js";
|
|
4
|
+
import type { RadiusProps } from "./foundation/radius.js";
|
|
5
|
+
import type { ScaleLevel } from "./foundation/scale.js";
|
|
6
|
+
import { type Spacing } from "./foundation/spacing.js";
|
|
7
7
|
export interface DisclosureRootProps extends Omit<AriaDisclosureProps, "children" | "className" | "defaultExpanded" | "isDisabled" | "isExpanded" | "onExpandedChange" | "style">, RadiusProps {
|
|
8
8
|
readonly children?: ReactNode;
|
|
9
9
|
readonly className?: string;
|
|
10
|
-
|
|
10
|
+
/** Paint of the trigger. Transparent by default, so it only veils on interaction. */
|
|
11
|
+
readonly color?: Color;
|
|
11
12
|
readonly defaultExpanded?: boolean;
|
|
12
13
|
readonly disabled?: boolean;
|
|
13
14
|
readonly expanded?: boolean;
|
|
14
|
-
readonly
|
|
15
|
+
readonly onExpandedChange?: (expanded: boolean) => void;
|
|
15
16
|
readonly size?: ScaleLevel;
|
|
16
17
|
readonly style?: CSSProperties;
|
|
17
18
|
}
|
|
18
19
|
/** One independently expandable region. */
|
|
19
20
|
export declare const DisclosureRoot: import("react").ForwardRefExoticComponent<DisclosureRootProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
20
|
-
export interface DisclosureTriggerProps extends Omit<AriaButtonProps, "children" | "className" | "isDisabled" | "onPress" | "style"> {
|
|
21
|
+
export interface DisclosureTriggerProps extends Omit<AriaButtonProps, "children" | "className" | "isDisabled" | "isPending" | "onPress" | "render" | "style"> {
|
|
21
22
|
readonly children?: ReactNode;
|
|
22
23
|
readonly className?: string;
|
|
23
24
|
readonly style?: CSSProperties;
|
package/dist/disclosure.js
CHANGED
|
@@ -1,83 +1,62 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { createContext, forwardRef, useContext, useMemo } from "react";
|
|
3
3
|
import { Button as AriaButton, Disclosure as AriaDisclosure, DisclosurePanel as AriaDisclosurePanel, DisclosureStateContext } from "react-aria-components";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
4
|
+
import { transition, useControlMetrics } from "./control/control.js";
|
|
5
|
+
import { surfaceRender } from "./control/surface-render.js";
|
|
6
|
+
import { resolveSpacing } from "./foundation/spacing.js";
|
|
7
|
+
import { ChevronDown } from "lucide-react";
|
|
8
|
+
import { iconProps } from "./control/icon.js";
|
|
9
|
+
const DisclosureStyleContext = createContext(null);
|
|
9
10
|
/** One independently expandable region. */
|
|
10
|
-
export const DisclosureRoot = forwardRef(function
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
motion: transitionTiming(resolved.transaction, resolved.preferences.animations),
|
|
15
|
-
theme
|
|
16
|
-
}), [resolved.preferences.animations, resolved.transaction, theme]);
|
|
17
|
-
return _jsx(DisclosureThemeContext.Provider, { value: context, children: _jsx(AriaDisclosure, { ...properties, ...(expanded === undefined ? {} : { isExpanded: expanded }), ...(defaultExpanded === undefined ? {} : { defaultExpanded }), ref: ref, className: className, isDisabled: disabled, onExpandedChange: onChange, style: {
|
|
18
|
-
display: "grid",
|
|
19
|
-
minWidth: 0,
|
|
20
|
-
fontFamily: "inherit",
|
|
21
|
-
fontSize: theme.fontSize,
|
|
22
|
-
...style
|
|
23
|
-
}, children: children }) });
|
|
11
|
+
export const DisclosureRoot = forwardRef(function Disclosure({ children, className, color = "transparent", defaultExpanded, disabled = false, expanded, onExpandedChange, radius, size, style, ...properties }, ref) {
|
|
12
|
+
const metrics = useControlMetrics(size, radius);
|
|
13
|
+
const context = useMemo(() => ({ color, metrics }), [color, metrics]);
|
|
14
|
+
return _jsx(DisclosureStyleContext.Provider, { value: context, children: _jsx(AriaDisclosure, { ...properties, ...(expanded === undefined ? {} : { isExpanded: expanded }), ...(defaultExpanded === undefined ? {} : { defaultExpanded }), ref: ref, className: className, isDisabled: disabled, onExpandedChange: onExpandedChange, style: { display: "grid", minWidth: 0, fontFamily: "inherit", fontSize: metrics.fontSize, ...style }, children: children }) });
|
|
24
15
|
});
|
|
25
16
|
/** The control that changes the Disclosure's expansion state. */
|
|
26
17
|
export const DisclosureTrigger = forwardRef(function DisclosureTrigger({ children, className, style, ...properties }, ref) {
|
|
27
|
-
const {
|
|
18
|
+
const { color, metrics } = useDisclosureStyle();
|
|
28
19
|
const disclosure = useDisclosureState();
|
|
29
|
-
return _jsxs(AriaButton, { ...properties, ref: ref, slot: "trigger", className: className,
|
|
30
|
-
|
|
20
|
+
return _jsxs(AriaButton, { ...properties, ref: ref, slot: "trigger", className: className, render: surfaceRender("button", state => ({
|
|
21
|
+
color,
|
|
22
|
+
radius: metrics.radius,
|
|
23
|
+
shadow: false,
|
|
24
|
+
interaction: { hovered: state.isHovered, pressed: state.isPressed, focusVisible: state.isFocusVisible, disabled: state.isDisabled }
|
|
25
|
+
})), style: {
|
|
31
26
|
appearance: "none",
|
|
32
27
|
display: "grid",
|
|
33
28
|
gridTemplateColumns: "minmax(0, 1fr) auto",
|
|
34
29
|
alignItems: "center",
|
|
35
|
-
gap:
|
|
30
|
+
gap: metrics.gap,
|
|
36
31
|
width: "100%",
|
|
37
32
|
minWidth: 0,
|
|
38
|
-
minHeight:
|
|
39
|
-
paddingBlock:
|
|
40
|
-
paddingInline:
|
|
33
|
+
minHeight: metrics.height,
|
|
34
|
+
paddingBlock: metrics.gap / 2,
|
|
35
|
+
paddingInline: metrics.inset,
|
|
41
36
|
boxSizing: "border-box",
|
|
42
37
|
border: 0,
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
outlineOffset: 1,
|
|
46
|
-
cursor: state.isDisabled ? "not-allowed" : "pointer",
|
|
47
|
-
opacity: state.isDisabled ? controlOpacity.disabled : 1,
|
|
38
|
+
background: "none",
|
|
39
|
+
cursor: "pointer",
|
|
48
40
|
font: "inherit",
|
|
49
|
-
|
|
41
|
+
fontWeight: 500,
|
|
42
|
+
lineHeight: 1.45,
|
|
50
43
|
textAlign: "start",
|
|
51
44
|
userSelect: "none",
|
|
52
45
|
WebkitTapHighlightColor: "transparent",
|
|
53
|
-
...(disclosure.isExpanded
|
|
54
|
-
? state.isPressed ? theme.paints.palette.pressed : state.isHovered ? theme.paints.palette.hover : theme.paints.palette.rest
|
|
55
|
-
: state.isPressed ? theme.paints.subtle.pressed : state.isHovered ? theme.paints.subtle.hover : { background: "transparent", color: "inherit" }),
|
|
56
46
|
...style
|
|
57
|
-
}
|
|
58
|
-
...motion,
|
|
59
|
-
transitionProperty: "transform",
|
|
60
|
-
width: "0.5em",
|
|
61
|
-
height: "0.5em",
|
|
62
|
-
marginInline: "0.25em",
|
|
63
|
-
borderInlineEnd: "1px solid currentColor",
|
|
64
|
-
borderBlockEnd: "1px solid currentColor",
|
|
65
|
-
transform: disclosure.isExpanded ? "rotate(225deg)" : "rotate(45deg)"
|
|
66
|
-
} })] });
|
|
47
|
+
}, children: [_jsx("span", { style: { minWidth: 0 }, children: children }), _jsx(ChevronDown, { ...iconProps(14), style: { ...transition(metrics.visual, "rotate"), rotate: disclosure.isExpanded ? "180deg" : "0deg" } })] });
|
|
67
48
|
});
|
|
68
49
|
/** Content revealed by a Disclosure trigger. */
|
|
69
50
|
export const DisclosureContent = forwardRef(function DisclosureContent({ children, className, padding = "small", style, ...properties }, ref) {
|
|
70
|
-
const {
|
|
51
|
+
const { metrics } = useDisclosureStyle();
|
|
71
52
|
const disclosure = useDisclosureState();
|
|
72
|
-
const { appearance } = useResolvedAppearance();
|
|
73
53
|
return _jsx(AriaDisclosurePanel, { ...properties, ref: ref, className: className, style: {
|
|
74
|
-
...
|
|
75
|
-
transitionProperty: "height, opacity",
|
|
54
|
+
...transition(metrics.visual, "height, opacity"),
|
|
76
55
|
height: "var(--disclosure-panel-height)",
|
|
77
56
|
overflow: "clip",
|
|
78
57
|
opacity: disclosure.isExpanded ? 1 : 0,
|
|
79
58
|
...style
|
|
80
|
-
}, children: _jsx("div", { style: { minHeight: 0, overflow: "hidden" }, children: _jsx("div", { style: { padding: resolveSpacing(padding,
|
|
59
|
+
}, children: _jsx("div", { style: { minHeight: 0, overflow: "hidden" }, children: _jsx("div", { style: { padding: resolveSpacing(padding, metrics.visual.spacing) }, children: children }) }) });
|
|
81
60
|
});
|
|
82
61
|
function useDisclosureState() {
|
|
83
62
|
const state = useContext(DisclosureStateContext);
|
|
@@ -85,8 +64,8 @@ function useDisclosureState() {
|
|
|
85
64
|
throw new Error("Disclosure parts must be used inside Disclosure");
|
|
86
65
|
return state;
|
|
87
66
|
}
|
|
88
|
-
function
|
|
89
|
-
const context = useContext(
|
|
67
|
+
function useDisclosureStyle() {
|
|
68
|
+
const context = useContext(DisclosureStyleContext);
|
|
90
69
|
if (context == null)
|
|
91
70
|
throw new Error("Disclosure parts must be used inside Disclosure");
|
|
92
71
|
return context;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { CSSProperties, ReactNode } from "react";
|
|
2
|
+
import type { DropZoneProps as AriaDropZoneProps } from "react-aria-components";
|
|
3
|
+
import { type RadiusProps } from "./foundation/radius.js";
|
|
4
|
+
import type { MaterialOverrides } from "./surface/material-options.js";
|
|
5
|
+
export interface DropZoneProps extends Omit<AriaDropZoneProps, "onDrop" | "getDropOperation" | "isDisabled" | "className" | "style" | "children">, RadiusProps, MaterialOverrides {
|
|
6
|
+
readonly children?: ReactNode;
|
|
7
|
+
/** MIME types it accepts, such as `image/png`, or a family such as `image/*`. Anything, when absent. */
|
|
8
|
+
readonly accept?: readonly string[];
|
|
9
|
+
readonly onDrop?: (files: File[]) => void;
|
|
10
|
+
readonly disabled?: boolean;
|
|
11
|
+
readonly className?: string;
|
|
12
|
+
readonly style?: CSSProperties;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* An area that takes files dragged onto it. It recesses like every value
|
|
16
|
+
* holder, and takes the subtle `primary` level while files hover it.
|
|
17
|
+
*/
|
|
18
|
+
export declare const DropZone: import("react").ForwardRefExoticComponent<DropZoneProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef } from "react";
|
|
3
|
+
import { DropZone as AriaDropZone } from "react-aria-components";
|
|
4
|
+
import { useControlMetrics } from "./control/control.js";
|
|
5
|
+
import { surfaceRender } from "./control/surface-render.js";
|
|
6
|
+
import { colorLevel } from "./foundation/color.js";
|
|
7
|
+
import { resolveRadius } from "./foundation/radius.js";
|
|
8
|
+
import { dimmedClass } from "./surface/surface.js";
|
|
9
|
+
/**
|
|
10
|
+
* An area that takes files dragged onto it. It recesses like every value
|
|
11
|
+
* holder, and takes the subtle `primary` level while files hover it.
|
|
12
|
+
*/
|
|
13
|
+
export const DropZone = forwardRef(function DropZone({ children, accept, onDrop, disabled, radius, material, className, style, ...properties }, ref) {
|
|
14
|
+
const metrics = useControlMetrics();
|
|
15
|
+
const { colors } = metrics.visual;
|
|
16
|
+
const accepts = (type) => accept === undefined || accept.some(pattern => pattern.endsWith("/*") ? type.startsWith(pattern.slice(0, -1)) : type === pattern);
|
|
17
|
+
return _jsx(AriaDropZone, { ...properties, ref: ref, isDisabled: disabled,
|
|
18
|
+
// A drag names exact types only, so a family such as `image/*` is checked on drop.
|
|
19
|
+
getDropOperation: types => accept === undefined || accept.some(pattern => pattern.endsWith("/*") || types.has(pattern)) ? "copy" : "cancel", onDrop: async (event) => {
|
|
20
|
+
const files = await Promise.all(event.items
|
|
21
|
+
.filter((item) => item.kind === "file" && accepts(item.type))
|
|
22
|
+
.map(item => item.getFile()));
|
|
23
|
+
if (files.length > 0)
|
|
24
|
+
onDrop?.(files);
|
|
25
|
+
}, className: state => dimmedClass(state.isDisabled, className ?? state.defaultClassName) ?? "", render: surfaceRender("div", state => ({
|
|
26
|
+
color: state.isDropTarget ? colorLevel(colors.primary, "subtle", colors) : "background",
|
|
27
|
+
depth: "recessed",
|
|
28
|
+
material,
|
|
29
|
+
radius: resolveRadius(radius ?? "medium", metrics.visual.radius),
|
|
30
|
+
interaction: { hovered: false, focusVisible: state.isFocusVisible || state.isDropTarget, disabled: state.isDisabled }
|
|
31
|
+
})), style: { display: "grid", placeItems: "center", gap: metrics.gap, padding: metrics.spacing * 2, textAlign: "center", ...style }, children: children });
|
|
32
|
+
});
|
package/dist/dropdown-menu.d.ts
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import type { ComponentProps } from "react";
|
|
2
2
|
import type { MenuTriggerProps as AriaMenuTriggerProps } from "react-aria-components";
|
|
3
|
-
import { type
|
|
4
|
-
|
|
5
|
-
export
|
|
6
|
-
export
|
|
7
|
-
export
|
|
3
|
+
import { type ButtonActionProps } from "./button.js";
|
|
4
|
+
import { type OverlayRootProps } from "./control/open-state.js";
|
|
5
|
+
export type DropdownMenuRootProps = OverlayRootProps & Readonly<Pick<AriaMenuTriggerProps, "trigger">>;
|
|
6
|
+
export declare function DropdownMenuRoot({ children, trigger, ...state }: DropdownMenuRootProps): import("react").JSX.Element;
|
|
7
|
+
export type DropdownMenuTriggerProps = ButtonActionProps;
|
|
8
|
+
export declare const DropdownMenuTrigger: import("react").ForwardRefExoticComponent<ButtonActionProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
8
9
|
/** A button-triggered overlay. Its Content owns positioning; Menu owns commands and selection. */
|
|
9
10
|
export declare const DropdownMenu: typeof DropdownMenuRoot & {
|
|
10
|
-
Trigger: import("react").ForwardRefExoticComponent<
|
|
11
|
-
Content: import("react").ForwardRefExoticComponent<import("./popover.js").PopoverContentProps &
|
|
11
|
+
Trigger: import("react").ForwardRefExoticComponent<ButtonActionProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
12
|
+
Content: import("react").ForwardRefExoticComponent<import("./popover.js").PopoverContentProps & Readonly<{
|
|
13
|
+
nonModal?: boolean;
|
|
14
|
+
}> & import("react").RefAttributes<HTMLElement>>;
|
|
12
15
|
Menu: import("./menu.js").MenuRootComponent & {
|
|
13
16
|
Item: import("./menu.js").MenuItemComponent;
|
|
14
|
-
Section: <T>(
|
|
17
|
+
Section: <T extends object = object>(properties: import("./menu.js").MenuSectionProps<T>) => import("react").ReactElement | null;
|
|
15
18
|
Header: import("react").ForwardRefExoticComponent<import("react-aria-components").HeaderProps & import("react").RefAttributes<HTMLElement>>;
|
|
16
19
|
Separator: import("react").ForwardRefExoticComponent<import("react-aria-components").SeparatorProps & import("react").RefAttributes<HTMLElement>>;
|
|
17
20
|
};
|
package/dist/dropdown-menu.js
CHANGED
|
@@ -2,10 +2,11 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { forwardRef } from "react";
|
|
3
3
|
import { MenuTrigger as AriaMenuTrigger } from "react-aria-components";
|
|
4
4
|
import { Button } from "./button.js";
|
|
5
|
+
import { ariaOpenState } from "./control/open-state.js";
|
|
5
6
|
import { Menu } from "./menu.js";
|
|
6
|
-
import {
|
|
7
|
-
export function DropdownMenuRoot(
|
|
8
|
-
return _jsx(AriaMenuTrigger, { ...
|
|
7
|
+
import { MenuContent } from "./popover.js";
|
|
8
|
+
export function DropdownMenuRoot({ children, trigger, ...state }) {
|
|
9
|
+
return _jsx(AriaMenuTrigger, { ...ariaOpenState(state), trigger: trigger, children: children });
|
|
9
10
|
}
|
|
10
11
|
export const DropdownMenuTrigger = forwardRef(function DropdownMenuTrigger(properties, ref) {
|
|
11
12
|
return _jsx(Button, { ...properties, ref: ref });
|
|
@@ -13,6 +14,6 @@ export const DropdownMenuTrigger = forwardRef(function DropdownMenuTrigger(prope
|
|
|
13
14
|
/** A button-triggered overlay. Its Content owns positioning; Menu owns commands and selection. */
|
|
14
15
|
export const DropdownMenu = Object.assign(DropdownMenuRoot, {
|
|
15
16
|
Trigger: DropdownMenuTrigger,
|
|
16
|
-
Content:
|
|
17
|
+
Content: MenuContent,
|
|
17
18
|
Menu
|
|
18
19
|
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { FieldsetHTMLAttributes, ReactNode } from "react";
|
|
2
|
+
export interface FieldsetProps extends Omit<FieldsetHTMLAttributes<HTMLFieldSetElement>, "title"> {
|
|
3
|
+
/** Names the group for everyone, including assistive technology. */
|
|
4
|
+
readonly title: ReactNode;
|
|
5
|
+
readonly description?: ReactNode;
|
|
6
|
+
readonly children: ReactNode;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* A titled group of related fields, such as one section of settings. Each
|
|
10
|
+
* field keeps its own label; the group adds only its title, its description,
|
|
11
|
+
* and the spacing between fields.
|
|
12
|
+
*/
|
|
13
|
+
export declare const Fieldset: import("react").ForwardRefExoticComponent<FieldsetProps & import("react").RefAttributes<HTMLFieldSetElement>>;
|
package/dist/fieldset.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef, useId } from "react";
|
|
3
|
+
import { controlFontSizes, controlFontWeight, controlOpacity, useControlMetrics } from "./control/control.js";
|
|
4
|
+
import { resolveSpacing } from "./foundation/spacing.js";
|
|
5
|
+
/**
|
|
6
|
+
* A titled group of related fields, such as one section of settings. Each
|
|
7
|
+
* field keeps its own label; the group adds only its title, its description,
|
|
8
|
+
* and the spacing between fields.
|
|
9
|
+
*/
|
|
10
|
+
export const Fieldset = forwardRef(function Fieldset({ title, description, children, style, ...properties }, ref) {
|
|
11
|
+
const metrics = useControlMetrics();
|
|
12
|
+
const { spacing } = metrics.visual;
|
|
13
|
+
const titleId = useId();
|
|
14
|
+
const descriptionId = useId();
|
|
15
|
+
// The title names the group through aria-labelledby: a styled legend loses
|
|
16
|
+
// its naming role in some browsers.
|
|
17
|
+
return _jsxs("fieldset", { "aria-labelledby": titleId, "aria-describedby": description != null ? descriptionId : undefined, ...properties, ref: ref, style: {
|
|
18
|
+
display: "grid",
|
|
19
|
+
gap: resolveSpacing("large", spacing),
|
|
20
|
+
minWidth: 0,
|
|
21
|
+
margin: 0,
|
|
22
|
+
padding: 0,
|
|
23
|
+
border: 0,
|
|
24
|
+
...style
|
|
25
|
+
}, children: [_jsxs("div", { style: { display: "grid", gap: resolveSpacing("xsmall", spacing) }, children: [_jsx("span", { id: titleId, style: { fontSize: controlFontSizes.large, fontWeight: controlFontWeight }, children: title }), description != null && _jsx("span", { id: descriptionId, style: { fontSize: controlFontSizes.medium, opacity: controlOpacity.secondary }, children: description })] }), _jsx("div", { style: { display: "grid", gap: resolveSpacing("large", spacing), minWidth: 0 }, children: children })] });
|
|
26
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
export interface FileTriggerProps {
|
|
3
|
+
/** A Button, or any pressable React UI control, that opens the file chooser. */
|
|
4
|
+
readonly children: ReactNode;
|
|
5
|
+
/** MIME types or extensions the chooser offers, such as `image/*` or `.html`. */
|
|
6
|
+
readonly accept?: readonly string[];
|
|
7
|
+
readonly multiple?: boolean;
|
|
8
|
+
/** Choose a directory instead of files. */
|
|
9
|
+
readonly directory?: boolean;
|
|
10
|
+
readonly onSelect?: (files: File[]) => void;
|
|
11
|
+
}
|
|
12
|
+
/** Opens the system file chooser from the control it wraps. It draws nothing of its own. */
|
|
13
|
+
export declare function FileTrigger({ children, accept, multiple, directory, onSelect }: FileTriggerProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { FileTrigger as AriaFileTrigger } from "react-aria-components";
|
|
3
|
+
/** Opens the system file chooser from the control it wraps. It draws nothing of its own. */
|
|
4
|
+
export function FileTrigger({ children, accept, multiple, directory, onSelect }) {
|
|
5
|
+
return _jsx(AriaFileTrigger, { acceptedFileTypes: accept, allowsMultiple: multiple, acceptDirectory: directory, onSelect: files => onSelect?.(files === null ? [] : [...files]), children: children });
|
|
6
|
+
}
|
package/dist/flex.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ComponentPropsWithoutRef } from "react";
|
|
2
|
-
import type { LayoutAlignment, LayoutGap, LayoutJustification } from "./layout.js";
|
|
2
|
+
import type { LayoutAlignment, LayoutGap, LayoutJustification } from "./foundation/layout.js";
|
|
3
3
|
/** Properties accepted by the Flex layout primitive. */
|
|
4
4
|
export interface FlexProps extends ComponentPropsWithoutRef<"div"> {
|
|
5
5
|
/** Main-axis direction. The browser default is `row`. */
|
package/dist/flex.js
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef } from "react";
|
|
3
|
-
import { alignment, justification
|
|
4
|
-
import {
|
|
3
|
+
import { alignment, justification } from "./foundation/layout.js";
|
|
4
|
+
import { resolveSpacing } from "./foundation/spacing.js";
|
|
5
|
+
import { useVisual } from "./foundation/visual.js";
|
|
5
6
|
/** A predictable Flexbox container with no visual appearance of its own. */
|
|
6
7
|
export const Flex = forwardRef(function Flex({ align, direction, gap, inline = false, justify, style, wrap, ...properties }, ref) {
|
|
7
|
-
const
|
|
8
|
+
const { spacing } = useVisual();
|
|
8
9
|
return _jsx("div", { ...properties, ref: ref, style: {
|
|
9
10
|
...style,
|
|
10
11
|
display: inline ? "inline-flex" : "flex",
|
|
11
12
|
alignItems: alignment(align) ?? style?.alignItems,
|
|
12
13
|
flexDirection: direction ?? style?.flexDirection,
|
|
13
14
|
flexWrap: wrap === undefined ? style?.flexWrap : wrap === "reverse" ? "wrap-reverse" : wrap ? "wrap" : "nowrap",
|
|
14
|
-
gap: gap === undefined ? style?.gap :
|
|
15
|
+
gap: gap === undefined ? style?.gap : resolveSpacing(gap, spacing),
|
|
15
16
|
justifyContent: justification(justify) ?? style?.justifyContent
|
|
16
17
|
} });
|
|
17
18
|
});
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { type Appearance as SystemAppearance, type AppearanceColors, type AppearanceMaterial, type AppearanceShadow, type AppearanceTransaction } from "@phreshos/core";
|
|
2
|
+
export type { AppearanceColor, AppearanceColors, AppearanceMaterial, AppearanceRange, AppearanceShadow, AppearanceTransaction, Easing, ThemedValue } from "@phreshos/core";
|
|
3
|
+
/** The System Appearance fields consumed by React UI. */
|
|
4
|
+
export type Appearance = Pick<SystemAppearance, "colors" | "spacing" | "radius" | "shadow" | "material" | "transaction">;
|
|
5
|
+
type Themed<Value> = Readonly<{
|
|
6
|
+
light?: Readonly<Partial<Value>>;
|
|
7
|
+
dark?: Readonly<Partial<Value>>;
|
|
8
|
+
}>;
|
|
9
|
+
type AppearanceUpdateFields = Readonly<{
|
|
10
|
+
colors?: Themed<AppearanceColors>;
|
|
11
|
+
spacing?: number;
|
|
12
|
+
radius?: number;
|
|
13
|
+
shadow?: Themed<AppearanceShadow>;
|
|
14
|
+
material?: Themed<AppearanceMaterial>;
|
|
15
|
+
transaction?: Readonly<Partial<AppearanceTransaction>>;
|
|
16
|
+
}>;
|
|
17
|
+
/** At least one partial visual field merged recursively with the nearest UIProvider. */
|
|
18
|
+
export type AppearanceUpdate = {
|
|
19
|
+
[Field in keyof AppearanceUpdateFields]-?: Readonly<Required<Pick<AppearanceUpdateFields, Field>> & Omit<AppearanceUpdateFields, Field>>;
|
|
20
|
+
}[keyof AppearanceUpdateFields];
|
|
21
|
+
/** Bounds for the visual Appearance fields consumed by React UI. */
|
|
22
|
+
export declare const appearanceLimits: Readonly<{
|
|
23
|
+
spacing: Readonly<{
|
|
24
|
+
minimum: 6;
|
|
25
|
+
maximum: 18;
|
|
26
|
+
}>;
|
|
27
|
+
radius: Readonly<{
|
|
28
|
+
minimum: 6;
|
|
29
|
+
maximum: 18;
|
|
30
|
+
}>;
|
|
31
|
+
shadow: Readonly<{
|
|
32
|
+
x: Readonly<{
|
|
33
|
+
minimum: -48;
|
|
34
|
+
maximum: 48;
|
|
35
|
+
}>;
|
|
36
|
+
y: Readonly<{
|
|
37
|
+
minimum: -48;
|
|
38
|
+
maximum: 48;
|
|
39
|
+
}>;
|
|
40
|
+
blur: Readonly<{
|
|
41
|
+
minimum: 0;
|
|
42
|
+
maximum: 96;
|
|
43
|
+
}>;
|
|
44
|
+
spread: Readonly<{
|
|
45
|
+
minimum: -24;
|
|
46
|
+
maximum: 24;
|
|
47
|
+
}>;
|
|
48
|
+
opacity: Readonly<{
|
|
49
|
+
minimum: 0;
|
|
50
|
+
maximum: 1;
|
|
51
|
+
}>;
|
|
52
|
+
}>;
|
|
53
|
+
material: Readonly<{
|
|
54
|
+
grain: Readonly<{
|
|
55
|
+
minimum: 0;
|
|
56
|
+
maximum: 1;
|
|
57
|
+
}>;
|
|
58
|
+
grainAmount: Readonly<{
|
|
59
|
+
minimum: 0;
|
|
60
|
+
maximum: 1;
|
|
61
|
+
}>;
|
|
62
|
+
backdrop: Readonly<{
|
|
63
|
+
minimum: 0;
|
|
64
|
+
maximum: 24;
|
|
65
|
+
}>;
|
|
66
|
+
opacity: Readonly<{
|
|
67
|
+
minimum: 0;
|
|
68
|
+
maximum: 1;
|
|
69
|
+
}>;
|
|
70
|
+
distortion: Readonly<{
|
|
71
|
+
minimum: 0;
|
|
72
|
+
maximum: 140;
|
|
73
|
+
}>;
|
|
74
|
+
saturation: Readonly<{
|
|
75
|
+
minimum: 1;
|
|
76
|
+
maximum: 2.6;
|
|
77
|
+
}>;
|
|
78
|
+
}>;
|
|
79
|
+
}>;
|
|
80
|
+
/** The visual portion of the System's default Appearance. */
|
|
81
|
+
export declare const defaultAppearance: Appearance;
|
|
82
|
+
/** Applies one partial update; omitted leaves continue to inherit. */
|
|
83
|
+
export declare function mergeAppearance(appearance: Appearance, update: AppearanceUpdate): Appearance;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { appearanceLimits as coreAppearanceLimits, defaultAppearance as systemDefaultAppearance } from "@phreshos/core";
|
|
2
|
+
/** Bounds for the visual Appearance fields consumed by React UI. */
|
|
3
|
+
export const appearanceLimits = Object.freeze({
|
|
4
|
+
spacing: coreAppearanceLimits.spacing,
|
|
5
|
+
radius: coreAppearanceLimits.radius,
|
|
6
|
+
shadow: coreAppearanceLimits.shadow,
|
|
7
|
+
material: coreAppearanceLimits.material
|
|
8
|
+
});
|
|
9
|
+
/** The visual portion of the System's default Appearance. */
|
|
10
|
+
export const defaultAppearance = Object.freeze({
|
|
11
|
+
colors: systemDefaultAppearance.colors,
|
|
12
|
+
spacing: systemDefaultAppearance.spacing,
|
|
13
|
+
radius: systemDefaultAppearance.radius,
|
|
14
|
+
shadow: systemDefaultAppearance.shadow,
|
|
15
|
+
material: systemDefaultAppearance.material,
|
|
16
|
+
transaction: systemDefaultAppearance.transaction
|
|
17
|
+
});
|
|
18
|
+
/** Applies one partial update; omitted leaves continue to inherit. */
|
|
19
|
+
export function mergeAppearance(appearance, update) {
|
|
20
|
+
return Object.freeze({
|
|
21
|
+
colors: mergeThemed(appearance.colors, update.colors),
|
|
22
|
+
spacing: update.spacing ?? appearance.spacing,
|
|
23
|
+
radius: update.radius ?? appearance.radius,
|
|
24
|
+
shadow: mergeThemed(appearance.shadow, update.shadow),
|
|
25
|
+
material: mergeThemed(appearance.material, update.material),
|
|
26
|
+
transaction: update.transaction === undefined
|
|
27
|
+
? appearance.transaction
|
|
28
|
+
: Object.freeze({ ...appearance.transaction, ...update.transaction })
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function mergeThemed(current, update) {
|
|
32
|
+
if (update === undefined)
|
|
33
|
+
return current;
|
|
34
|
+
return Object.freeze({
|
|
35
|
+
light: update.light === undefined ? current.light : Object.freeze({ ...current.light, ...update.light }),
|
|
36
|
+
dark: update.dark === undefined ? current.dark : Object.freeze({ ...current.dark, ...update.dark })
|
|
37
|
+
});
|
|
38
|
+
}
|
|
@@ -3,6 +3,8 @@ import { useMemo } from "react";
|
|
|
3
3
|
import { useLocale } from "react-aria/I18nProvider";
|
|
4
4
|
const ariaDirectionBoundary = "data-phreshos-ui-aria-direction";
|
|
5
5
|
const redirectedEvents = new WeakSet();
|
|
6
|
+
// Text entry keeps native caret movement; choice inputs move selection by direction.
|
|
7
|
+
const directionalInputTypes = new Set(["radio", "checkbox", "range"]);
|
|
6
8
|
/** Aligns React Aria's directional keyboard behavior with the React UI direction contract. */
|
|
7
9
|
export function useAriaDirectionBridge(direction) {
|
|
8
10
|
const { direction: ariaDirection } = useLocale();
|
|
@@ -18,7 +20,7 @@ export function useAriaDirectionBridge(direction) {
|
|
|
18
20
|
if (!(target instanceof Element) || target.closest(`[${ariaDirectionBoundary}]`) !== event.currentTarget)
|
|
19
21
|
return;
|
|
20
22
|
const editable = target.closest("[contenteditable=true]");
|
|
21
|
-
if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement || target instanceof HTMLSelectElement || (editable && editable.getAttribute("role") !== "spinbutton"))
|
|
23
|
+
if ((target instanceof HTMLInputElement && !directionalInputTypes.has(target.type)) || target instanceof HTMLTextAreaElement || target instanceof HTMLSelectElement || (editable && editable.getAttribute("role") !== "spinbutton"))
|
|
22
24
|
return;
|
|
23
25
|
event.preventDefault();
|
|
24
26
|
event.stopPropagation();
|