@phreshos/react-ui 0.1.6 → 0.1.8
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 +12 -12
- package/dist/button.d.ts +1 -1
- package/dist/button.js +1 -1
- package/dist/color.d.ts +8 -0
- package/dist/color.js +15 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +2 -0
- package/dist/radius.d.ts +1 -1
- package/dist/radius.js +1 -1
- package/dist/scale.d.ts +14 -0
- package/dist/scale.js +34 -0
- package/dist/spacing.d.ts +1 -1
- package/dist/spacing.js +1 -1
- package/dist/surface-material.d.ts +1 -2
- package/dist/surface-material.js +9 -76
- package/dist/surface.d.ts +2 -5
- package/dist/surface.js +5 -4
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -68,11 +68,11 @@ Theme's concrete default spacing:
|
|
|
68
68
|
<Grid gap="large">...</Grid>
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
-
Structures that own native spacing pass the explicit Theme value to
|
|
72
|
-
general
|
|
71
|
+
Structures that own native spacing pass the explicit Theme value to React UI's
|
|
72
|
+
general derivation hook:
|
|
73
73
|
|
|
74
74
|
```tsx
|
|
75
|
-
import { useScale } from "@phreshos/react"
|
|
75
|
+
import { useScale } from "@phreshos/react-ui"
|
|
76
76
|
|
|
77
77
|
const spacing = useScale(theme.spacing)
|
|
78
78
|
|
|
@@ -94,13 +94,13 @@ texture:
|
|
|
94
94
|
</Surface>
|
|
95
95
|
|
|
96
96
|
<Surface color="strong" grain="large">...</Surface>
|
|
97
|
-
<Surface color="#101114" grain={0.2}
|
|
97
|
+
<Surface color="#101114" grain={0.2} backdrop={4} opacity={0.9}>...</Surface>
|
|
98
98
|
<Surface distortion={70} waves={8} ripples={4} saturation={1.4} brightness={1.04}>...</Surface>
|
|
99
99
|
```
|
|
100
100
|
|
|
101
101
|
`color` resolves from `Theme.background`; its semantic levels derive from that
|
|
102
102
|
same source and a direct color remains an explicit local override. `grain`,
|
|
103
|
-
`grainAmount`, `
|
|
103
|
+
`grainAmount`, `backdrop`, `opacity`, `distortion`, `waves`,
|
|
104
104
|
`ripples`, `saturation`, and `brightness` resolve from `Theme.surface`, accept
|
|
105
105
|
their semantic levels or direct values, and remain bounded by Core's Theme
|
|
106
106
|
limits. Radius and foreground remain ordinary Theme styles. Grain intensity
|
|
@@ -118,14 +118,14 @@ visible grain and a positive rate joins the internal document clock, while
|
|
|
118
118
|
every texture and seed remains local to its own Surface.
|
|
119
119
|
|
|
120
120
|
The Theme stores unrestricted CSS background, foreground, and accent sources.
|
|
121
|
-
|
|
121
|
+
React UI derives the fixed `subtle`, `soft`, `base`, `strong`, and `intense`
|
|
122
122
|
treatments from any supplied color, preserving the value exactly at `base`.
|
|
123
|
-
`useColor(value)`
|
|
124
|
-
|
|
125
|
-
|
|
123
|
+
`useColor(value)` memoizes that calculation without implicitly choosing a
|
|
124
|
+
Theme property. CSS performs the nearby mixing in OKLCH, and the System retains
|
|
125
|
+
only the concrete Theme color:
|
|
126
126
|
|
|
127
127
|
```tsx
|
|
128
|
-
import { useColor } from "@phreshos/react"
|
|
128
|
+
import { useColor } from "@phreshos/react-ui"
|
|
129
129
|
|
|
130
130
|
const colors = useColor(theme.accent)
|
|
131
131
|
|
|
@@ -143,10 +143,10 @@ overrides:
|
|
|
143
143
|
```
|
|
144
144
|
|
|
145
145
|
Structures whose native element owns the shape derive from the explicit
|
|
146
|
-
radius value through the same
|
|
146
|
+
radius value through the same React UI hook:
|
|
147
147
|
|
|
148
148
|
```tsx
|
|
149
|
-
import { useScale } from "@phreshos/react"
|
|
149
|
+
import { useScale } from "@phreshos/react-ui"
|
|
150
150
|
|
|
151
151
|
const radius = useScale(theme.radius)
|
|
152
152
|
|
package/dist/button.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { CSSProperties, ReactNode } from "react";
|
|
2
2
|
import type { ButtonProps as AriaButtonProps } from "react-aria-components";
|
|
3
|
-
import { type ScaleLevel } from "
|
|
3
|
+
import { type ScaleLevel } from "./scale.js";
|
|
4
4
|
import { type RadiusProps } from "./radius.js";
|
|
5
5
|
type NativeButtonProps = Omit<AriaButtonProps, "children" | "className" | "isDisabled" | "isPending" | "onClick" | "onPress" | "style">;
|
|
6
6
|
/** Properties accepted by the shared interactive button. */
|
package/dist/button.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef } from "react";
|
|
3
3
|
import { Button as AriaButton } from "react-aria-components";
|
|
4
|
-
import { scale } from "
|
|
4
|
+
import { scale } from "./scale.js";
|
|
5
5
|
import { resolveRadius } from "./radius.js";
|
|
6
6
|
import { useTheme } from "./theme-provider.js";
|
|
7
7
|
/** A Theme-aware action with normalized pointer and keyboard behavior. */
|
package/dist/color.d.ts
CHANGED
|
@@ -1,2 +1,10 @@
|
|
|
1
|
+
/** A visual treatment derived from one concrete CSS color. */
|
|
2
|
+
export type ColorLevel = "subtle" | "soft" | "base" | "strong" | "intense";
|
|
3
|
+
/** Every visual treatment derived from one concrete CSS color. */
|
|
4
|
+
export type ColorScale = Readonly<Record<ColorLevel, string>>;
|
|
5
|
+
/** Derives visual treatments while preserving the concrete value at `base`. */
|
|
6
|
+
export declare function color(value: string): ColorScale;
|
|
7
|
+
/** Returns the complete visual treatments derived from one concrete color. */
|
|
8
|
+
export declare function useColor(value: string): ColorScale;
|
|
1
9
|
/** Applies material opacity without restricting the source CSS color syntax. */
|
|
2
10
|
export declare function colorOpacity(value: string, opacity: number): string;
|
package/dist/color.js
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
import { useMemo } from "react";
|
|
2
|
+
/** Derives visual treatments while preserving the concrete value at `base`. */
|
|
3
|
+
export function color(value) {
|
|
4
|
+
return Object.freeze({
|
|
5
|
+
subtle: `color-mix(in oklch, ${value} 25%, white)`,
|
|
6
|
+
soft: `color-mix(in oklch, ${value} 60%, white)`,
|
|
7
|
+
base: value,
|
|
8
|
+
strong: `color-mix(in oklch, ${value} 82%, black)`,
|
|
9
|
+
intense: `color-mix(in oklch, ${value} 68%, black)`
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
/** Returns the complete visual treatments derived from one concrete color. */
|
|
13
|
+
export function useColor(value) {
|
|
14
|
+
return useMemo(() => color(value), [value]);
|
|
15
|
+
}
|
|
1
16
|
/** Applies material opacity without restricting the source CSS color syntax. */
|
|
2
17
|
export function colorOpacity(value, opacity) {
|
|
3
18
|
const percentage = Math.round(opacity * 10_000) / 100;
|
package/dist/main.d.ts
CHANGED
|
@@ -12,3 +12,5 @@ export { Button, type ButtonProps } from "./button.js";
|
|
|
12
12
|
export type { LayoutAlignment, LayoutGap, LayoutJustification } from "./layout.js";
|
|
13
13
|
export { resolveRadius, type Radius, type RadiusProps } from "./radius.js";
|
|
14
14
|
export { resolveSpacing, type Spacing } from "./spacing.js";
|
|
15
|
+
export { useColor, type ColorLevel, type ColorScale } from "./color.js";
|
|
16
|
+
export { useScale, type NumericScale, type ScaleLevel } from "./scale.js";
|
package/dist/main.js
CHANGED
package/dist/radius.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { CSSProperties } from "react";
|
|
2
2
|
import type { Shapeable, ThemeProperties } from "@phreshos/core";
|
|
3
|
-
import { type ScaleLevel } from "
|
|
3
|
+
import { type ScaleLevel } from "./scale.js";
|
|
4
4
|
/** A Theme-derived level, pixel value, or explicit CSS corner radius. */
|
|
5
5
|
export type Radius = ScaleLevel | number | (string & {});
|
|
6
6
|
/** Shared semantic corner-radius capability for React UI components. */
|
package/dist/radius.js
CHANGED
package/dist/scale.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** A visual level derived around one concrete Theme value. */
|
|
2
|
+
export type ScaleLevel = "xsmall" | "small" | "medium" | "large" | "xlarge";
|
|
3
|
+
/** Every visual level derived around one concrete Theme value. */
|
|
4
|
+
export type NumericScale = Readonly<Record<ScaleLevel, number>>;
|
|
5
|
+
/** Returns whether a value names a React UI visual level. */
|
|
6
|
+
export declare function isScaleLevel(value: unknown): value is ScaleLevel;
|
|
7
|
+
/** Derives one visual level from one concrete value. */
|
|
8
|
+
export declare function scale(value: number, level: ScaleLevel): number;
|
|
9
|
+
/** Derives every visual level from one concrete value. */
|
|
10
|
+
export declare function numericScale(value: number): NumericScale;
|
|
11
|
+
/** Derives a multiplier while preserving its neutral value of one. */
|
|
12
|
+
export declare function scaleMultiplier(value: number, level: ScaleLevel): number;
|
|
13
|
+
/** Returns every visual level derived from one concrete Theme value. */
|
|
14
|
+
export declare function useScale(value: number): NumericScale;
|
package/dist/scale.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { useMemo } from "react";
|
|
2
|
+
const factors = Object.freeze({
|
|
3
|
+
xsmall: 0.25,
|
|
4
|
+
small: 0.5,
|
|
5
|
+
medium: 1,
|
|
6
|
+
large: 1.5,
|
|
7
|
+
xlarge: 2
|
|
8
|
+
});
|
|
9
|
+
/** Returns whether a value names a React UI visual level. */
|
|
10
|
+
export function isScaleLevel(value) {
|
|
11
|
+
return value === "xsmall" || value === "small" || value === "medium" || value === "large" || value === "xlarge";
|
|
12
|
+
}
|
|
13
|
+
/** Derives one visual level from one concrete value. */
|
|
14
|
+
export function scale(value, level) {
|
|
15
|
+
return value * factors[level];
|
|
16
|
+
}
|
|
17
|
+
/** Derives every visual level from one concrete value. */
|
|
18
|
+
export function numericScale(value) {
|
|
19
|
+
return Object.freeze({
|
|
20
|
+
xsmall: scale(value, "xsmall"),
|
|
21
|
+
small: scale(value, "small"),
|
|
22
|
+
medium: scale(value, "medium"),
|
|
23
|
+
large: scale(value, "large"),
|
|
24
|
+
xlarge: scale(value, "xlarge")
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/** Derives a multiplier while preserving its neutral value of one. */
|
|
28
|
+
export function scaleMultiplier(value, level) {
|
|
29
|
+
return 1 + (value - 1) * factors[level];
|
|
30
|
+
}
|
|
31
|
+
/** Returns every visual level derived from one concrete Theme value. */
|
|
32
|
+
export function useScale(value) {
|
|
33
|
+
return useMemo(() => numericScale(value), [value]);
|
|
34
|
+
}
|
package/dist/spacing.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { CSSProperties } from "react";
|
|
2
2
|
import type { ThemeProperties } from "@phreshos/core";
|
|
3
|
-
import { type ScaleLevel } from "
|
|
3
|
+
import { type ScaleLevel } from "./scale.js";
|
|
4
4
|
/** A Theme-derived level, pixel value, or explicit CSS spacing value. */
|
|
5
5
|
export type Spacing = ScaleLevel | number | (string & {});
|
|
6
6
|
/** Resolves spacing while preserving explicit CSS and pixel values. */
|
package/dist/spacing.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
interface SurfaceMaterialProps {
|
|
2
|
-
readonly animation: number;
|
|
3
2
|
readonly color: string;
|
|
4
3
|
readonly distortion: number;
|
|
5
4
|
readonly grain: number;
|
|
@@ -10,5 +9,5 @@ interface SurfaceMaterialProps {
|
|
|
10
9
|
readonly waves: number;
|
|
11
10
|
}
|
|
12
11
|
/** The locally owned SVG paint layer inside one Surface. */
|
|
13
|
-
export declare function SurfaceMaterial({
|
|
12
|
+
export declare function SurfaceMaterial({ color, distortion, grain, grainAmount, identity, opacity, ripples, waves }: SurfaceMaterialProps): import("react").JSX.Element | null;
|
|
14
13
|
export {};
|
package/dist/surface-material.js
CHANGED
|
@@ -1,27 +1,15 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Fragment,
|
|
2
|
+
import { Fragment, useMemo } from "react";
|
|
3
3
|
/** The locally owned SVG paint layer inside one Surface. */
|
|
4
|
-
export function SurfaceMaterial({
|
|
4
|
+
export function SurfaceMaterial({ color, distortion, grain, grainAmount, identity, opacity, ripples, waves }) {
|
|
5
5
|
const seed = useMemo(() => seedFrom(identity), [identity]);
|
|
6
6
|
const hasPaint = opacity > 0;
|
|
7
7
|
const hasGrain = hasPaint && grain > 0 && grainAmount > 0;
|
|
8
8
|
const hasDistortion = distortion > 0 || waves > 0 || ripples > 0;
|
|
9
|
-
const initial = useMemo(() => hasGrain ? grainPaths(seed,
|
|
10
|
-
const svg = useRef(null);
|
|
11
|
-
const paths = useRef([]);
|
|
12
|
-
useEffect(() => {
|
|
13
|
-
paths.current.forEach((path, tone) => path?.setAttribute("d", initial[tone] ?? ""));
|
|
14
|
-
if (animation === 0 || !hasGrain || !svg.current)
|
|
15
|
-
return;
|
|
16
|
-
const paint = (frame) => {
|
|
17
|
-
const values = grainPaths(seed, frame, grainAmount);
|
|
18
|
-
paths.current.forEach((path, tone) => path?.setAttribute("d", values[tone] ?? ""));
|
|
19
|
-
};
|
|
20
|
-
return animate(svg.current, animation, paint);
|
|
21
|
-
}, [animation, grainAmount, hasGrain, initial, seed]);
|
|
9
|
+
const initial = useMemo(() => hasGrain ? grainPaths(seed, grainAmount) : [], [grainAmount, hasGrain, seed]);
|
|
22
10
|
if (!hasPaint && !hasDistortion)
|
|
23
11
|
return null;
|
|
24
|
-
return _jsxs("svg", {
|
|
12
|
+
return _jsxs("svg", { "data-surface-material": "", "aria-hidden": "true", focusable: "false", style: {
|
|
25
13
|
position: "absolute",
|
|
26
14
|
zIndex: -1,
|
|
27
15
|
inset: 0,
|
|
@@ -33,7 +21,7 @@ export function SurfaceMaterial({ animation, color, distortion, grain, grainAmou
|
|
|
33
21
|
boxSizing: "border-box",
|
|
34
22
|
opacity,
|
|
35
23
|
pointerEvents: "none"
|
|
36
|
-
}, children: [(hasGrain || hasDistortion) && _jsxs("defs", { children: [hasDistortion && _jsx(DistortionFilter, { distortion: distortion, identity: identity, ripples: ripples, seed: seed, waves: waves }), hasGrain && _jsx("pattern", { id: `${identity}-grain`, width: patternSize, height: patternSize, patternUnits: "userSpaceOnUse", children: initial.map((path, tone) => _jsx("path", {
|
|
24
|
+
}, children: [(hasGrain || hasDistortion) && _jsxs("defs", { children: [hasDistortion && _jsx(DistortionFilter, { distortion: distortion, identity: identity, ripples: ripples, seed: seed, waves: waves }), hasGrain && _jsx("pattern", { id: `${identity}-grain`, width: patternSize, height: patternSize, patternUnits: "userSpaceOnUse", children: initial.map((path, tone) => _jsx("path", { "data-surface-grain-tone": tone, d: path, fill: grainTone(color, tone, grain), shapeRendering: "crispEdges" }, tone)) })] }), hasPaint && _jsx("rect", { "data-surface-base": "", width: "100%", height: "100%", fill: color }), hasGrain && _jsx("rect", { "data-surface-grain": "", width: "100%", height: "100%", fill: `url(#${identity}-grain)`, shapeRendering: "crispEdges" })] });
|
|
37
25
|
}
|
|
38
26
|
function DistortionFilter({ distortion, identity, ripples, seed, waves }) {
|
|
39
27
|
const fields = [
|
|
@@ -58,72 +46,17 @@ function grainTone(color, tone, intensity) {
|
|
|
58
46
|
const percentage = Math.round(intensity * 10_000) / 100;
|
|
59
47
|
return `color-mix(in srgb, ${color} ${100 - percentage}%, rgb(${channel} ${channel} ${channel}) ${percentage}%)`;
|
|
60
48
|
}
|
|
61
|
-
|
|
62
|
-
#entries = new Set();
|
|
63
|
-
#view;
|
|
64
|
-
#request;
|
|
65
|
-
constructor(view) {
|
|
66
|
-
this.#view = view;
|
|
67
|
-
}
|
|
68
|
-
subscribe(rate, paint) {
|
|
69
|
-
const entry = { rate, paint, frame: -1 };
|
|
70
|
-
this.#entries.add(entry);
|
|
71
|
-
this.#start();
|
|
72
|
-
return () => {
|
|
73
|
-
this.#entries.delete(entry);
|
|
74
|
-
if (this.#entries.size === 0)
|
|
75
|
-
this.#stop();
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
#start() {
|
|
79
|
-
if (this.#request !== undefined)
|
|
80
|
-
return;
|
|
81
|
-
this.#request = this.#view.requestAnimationFrame(this.#tick);
|
|
82
|
-
}
|
|
83
|
-
#stop() {
|
|
84
|
-
if (this.#request === undefined)
|
|
85
|
-
return;
|
|
86
|
-
this.#view.cancelAnimationFrame(this.#request);
|
|
87
|
-
this.#request = undefined;
|
|
88
|
-
}
|
|
89
|
-
#tick = (time) => {
|
|
90
|
-
this.#entries.forEach(entry => {
|
|
91
|
-
const frame = Math.floor(time / 1000 * entry.rate);
|
|
92
|
-
if (frame === entry.frame)
|
|
93
|
-
return;
|
|
94
|
-
entry.frame = frame;
|
|
95
|
-
entry.paint(frame);
|
|
96
|
-
});
|
|
97
|
-
this.#request = this.#entries.size === 0
|
|
98
|
-
? undefined
|
|
99
|
-
: this.#view.requestAnimationFrame(this.#tick);
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
const clocks = new WeakMap();
|
|
103
|
-
function animate(element, rate, paint) {
|
|
104
|
-
const view = element.ownerDocument.defaultView;
|
|
105
|
-
if (!view)
|
|
106
|
-
return;
|
|
107
|
-
let clock = clocks.get(view);
|
|
108
|
-
if (!clock) {
|
|
109
|
-
clock = new AnimationClock(view);
|
|
110
|
-
clocks.set(view, clock);
|
|
111
|
-
}
|
|
112
|
-
return clock.subscribe(rate, paint);
|
|
113
|
-
}
|
|
114
|
-
function grainPaths(seed, frame, amount) {
|
|
49
|
+
function grainPaths(seed, amount) {
|
|
115
50
|
const tones = Array.from({ length: toneCount }, () => []);
|
|
116
|
-
const frameX = frame * 19.17;
|
|
117
|
-
const frameY = frame * 7.31;
|
|
118
51
|
for (let y = 0; y < patternSize; y += 1) {
|
|
119
52
|
for (let x = 0; x < patternSize; x += 1) {
|
|
120
53
|
const pointX = x + seed * 41;
|
|
121
54
|
const pointY = y + seed * 17;
|
|
122
|
-
const presence = shaderHash(pointX +
|
|
55
|
+
const presence = shaderHash(pointX + 71.9, pointY + 13.7);
|
|
123
56
|
if (presence > amount)
|
|
124
57
|
continue;
|
|
125
|
-
const fine = shaderHash(Math.floor(pointX * 1.18)
|
|
126
|
-
const clustered = shaderHash(Math.floor(pointX * 0.47) +
|
|
58
|
+
const fine = shaderHash(Math.floor(pointX * 1.18), Math.floor(pointY * 1.18));
|
|
59
|
+
const clustered = shaderHash(Math.floor(pointX * 0.47) + 31.7, Math.floor(pointY * 0.47) + 31.7);
|
|
127
60
|
const value = clamp(fine * 0.8 + clustered * 0.2, 0, 1);
|
|
128
61
|
const tone = Math.min(toneCount - 1, Math.floor(value * toneCount));
|
|
129
62
|
tones[tone]?.push(`M${x} ${y}h1v1h-1z`);
|
package/dist/surface.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ComponentPropsWithoutRef } from "react";
|
|
2
|
-
import { type ColorLevel
|
|
2
|
+
import { type ColorLevel } from "./color.js";
|
|
3
|
+
import { type ScaleLevel } from "./scale.js";
|
|
3
4
|
/** A Theme-derived treatment or direct CSS color. */
|
|
4
5
|
export type SurfaceColor = ColorLevel | (string & {});
|
|
5
6
|
/** Native div properties plus controls for the locally owned material. */
|
|
@@ -10,8 +11,6 @@ export type SurfaceProps = Omit<ComponentPropsWithoutRef<"div">, "color" | "opac
|
|
|
10
11
|
grain?: ScaleLevel | number;
|
|
11
12
|
/** Theme-derived level or direct retained grain amount from zero to one. */
|
|
12
13
|
grainAmount?: ScaleLevel | number;
|
|
13
|
-
/** Theme-derived level or direct grain changes per second from zero to 16. */
|
|
14
|
-
animation?: ScaleLevel | number;
|
|
15
14
|
/** Theme-derived level or direct backdrop blur from zero to 24 CSS pixels. */
|
|
16
15
|
backdrop?: ScaleLevel | number;
|
|
17
16
|
/** Theme-derived level or direct material opacity from zero to one. */
|
|
@@ -35,8 +34,6 @@ export declare const Surface: import("react").ForwardRefExoticComponent<Omit<Omi
|
|
|
35
34
|
grain?: ScaleLevel | number;
|
|
36
35
|
/** Theme-derived level or direct retained grain amount from zero to one. */
|
|
37
36
|
grainAmount?: ScaleLevel | number;
|
|
38
|
-
/** Theme-derived level or direct grain changes per second from zero to 16. */
|
|
39
|
-
animation?: ScaleLevel | number;
|
|
40
37
|
/** Theme-derived level or direct backdrop blur from zero to 24 CSS pixels. */
|
|
41
38
|
backdrop?: ScaleLevel | number;
|
|
42
39
|
/** Theme-derived level or direct material opacity from zero to one. */
|
package/dist/surface.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef, useCallback, useId, useLayoutEffect, useRef } from "react";
|
|
3
|
-
import {
|
|
3
|
+
import { themeLimits } from "@phreshos/core";
|
|
4
|
+
import { color as deriveColor } from "./color.js";
|
|
5
|
+
import { isScaleLevel, scale, scaleMultiplier } from "./scale.js";
|
|
4
6
|
import { SurfaceMaterial } from "./surface-material.js";
|
|
5
7
|
import { useTheme } from "./theme-provider.js";
|
|
6
8
|
const layerStyle = {
|
|
@@ -10,7 +12,7 @@ const layerStyle = {
|
|
|
10
12
|
pointerEvents: "none"
|
|
11
13
|
};
|
|
12
14
|
/** Contains content above locally owned Surface material layers. */
|
|
13
|
-
export const Surface = forwardRef(function Surface({
|
|
15
|
+
export const Surface = forwardRef(function Surface({ backdrop, brightness, children, color, distortion, grain, grainAmount, opacity, ripples, saturation, style, waves, ...properties }, forwardedRef) {
|
|
14
16
|
const theme = useTheme();
|
|
15
17
|
const identity = `phresh-surface-${useId().replaceAll(":", "")}`;
|
|
16
18
|
const element = useRef(null);
|
|
@@ -21,7 +23,7 @@ export const Surface = forwardRef(function Surface({ animation, backdrop, bright
|
|
|
21
23
|
else if (forwardedRef)
|
|
22
24
|
forwardedRef.current = node;
|
|
23
25
|
}, [forwardedRef]);
|
|
24
|
-
const resolved = resolveSurface({
|
|
26
|
+
const resolved = resolveSurface({ backdrop, brightness, color, distortion, grain, grainAmount, opacity, ripples, saturation, waves }, theme);
|
|
25
27
|
useLayoutEffect(() => {
|
|
26
28
|
const surface = element.current;
|
|
27
29
|
if (surface)
|
|
@@ -55,7 +57,6 @@ function BackdropLayer({ filter, name, zIndex }) {
|
|
|
55
57
|
}
|
|
56
58
|
function resolveSurface(values, theme) {
|
|
57
59
|
const material = {
|
|
58
|
-
animation: resolveScale(values.animation, theme.surface.animation, themeLimits.surface.animation),
|
|
59
60
|
color: resolveColor(values.color, theme.background),
|
|
60
61
|
distortion: resolveScale(values.distortion, theme.surface.distortion, themeLimits.surface.distortion),
|
|
61
62
|
grain: resolveScale(values.grain, theme.surface.grain, themeLimits.surface.grain),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phreshos/react-ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "React components for coherent PhreshOS Program interfaces.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"prepack": "node --run test && node --run build"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
|
-
"@phreshos/core": "^0.1.
|
|
55
|
+
"@phreshos/core": "^0.1.16",
|
|
56
56
|
"react": "^19.2.0",
|
|
57
57
|
"react-dom": "^19.2.0"
|
|
58
58
|
},
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
63
|
"@base-ui/react": "^1.7.0",
|
|
64
|
-
"@phreshos/core": "^0.1.
|
|
64
|
+
"@phreshos/core": "^0.1.16",
|
|
65
65
|
"@testing-library/dom": "^10.4.1",
|
|
66
66
|
"@testing-library/react": "^16.3.0",
|
|
67
67
|
"@testing-library/user-event": "^14.6.1",
|