@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
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { createElement, forwardRef, useId, useInsertionEffect } from "react";
|
|
3
|
+
import { canvasDarkness, colorOpacity, contrast, mixColor, readableColor, recessColor, resolveColor } from "../foundation/color.js";
|
|
4
|
+
import { resolveRadius } from "../foundation/radius.js";
|
|
5
|
+
import { useVisual } from "../foundation/visual.js";
|
|
6
|
+
import { grainImage, grainSeed, grainSize } from "./grain.js";
|
|
7
|
+
import { flushPaintRules, paintClass, usePaintClasses } from "./paint-class.js";
|
|
8
|
+
import { resolveMaterialOptions } from "./material-options.js";
|
|
9
|
+
import { resolveShadowOptions, shadowStyle } from "./shadow-options.js";
|
|
10
|
+
/**
|
|
11
|
+
* The single visual primitive. Components express what they are through
|
|
12
|
+
* color, depth, and interaction; paint, grain, frost, edge, shadow, focus,
|
|
13
|
+
* and the text color are all derived here from Appearance.
|
|
14
|
+
*/
|
|
15
|
+
export const SurfaceView = forwardRef(function Surface({ as: Element = "div", color = "background", depth = "raised", material, shadow, radius, interaction, className, children, style, ...properties }, ref) {
|
|
16
|
+
const visual = useVisual();
|
|
17
|
+
const identity = useId();
|
|
18
|
+
const paint = surfacePaint(visual, color, depth, material, shadow, interaction);
|
|
19
|
+
const borderRadius = radius === undefined && style?.borderRadius !== undefined
|
|
20
|
+
? style.borderRadius
|
|
21
|
+
: resolveRadius(radius ?? "medium", visual.radius);
|
|
22
|
+
const declarations = [
|
|
23
|
+
...Object.entries(paint.variables).map(([name, value]) => `${name}: ${value}`),
|
|
24
|
+
"transition-property: box-shadow, color, outline-color, opacity",
|
|
25
|
+
`transition-duration: ${visual.duration}ms`,
|
|
26
|
+
`transition-timing-function: ${visual.easing}`,
|
|
27
|
+
`box-shadow: ${paint.shadow}`,
|
|
28
|
+
`color: ${paint.text}`,
|
|
29
|
+
`outline: 3px solid ${interaction?.focusVisible ? paint.ring : "transparent"}`,
|
|
30
|
+
"outline-offset: 1px",
|
|
31
|
+
`border-radius: ${typeof borderRadius === "number" ? `${borderRadius}px` : borderRadius}`
|
|
32
|
+
].join("; ");
|
|
33
|
+
const painted = usePaintClasses() ? paintClass(declarations) : undefined;
|
|
34
|
+
useInsertionEffect(flushPaintRules);
|
|
35
|
+
return createElement(Element, {
|
|
36
|
+
...properties,
|
|
37
|
+
ref,
|
|
38
|
+
className: [surfaceClass, painted, dimmedClass(interaction?.disabled ?? false), className].filter(Boolean).join(" "),
|
|
39
|
+
// Without a document (server rendering), the same declarations travel inline.
|
|
40
|
+
style: painted === undefined ? { ...inlineDeclarations(declarations), ...style } : style
|
|
41
|
+
}, _jsx(SurfaceStyle, {}), paint.distortion > 0 && _jsx(Refraction, { identity: identity, distortion: paint.distortion }), children);
|
|
42
|
+
});
|
|
43
|
+
function inlineDeclarations(declarations) {
|
|
44
|
+
const result = {};
|
|
45
|
+
for (const declaration of declarations.split("; ")) {
|
|
46
|
+
const separator = declaration.indexOf(": ");
|
|
47
|
+
const name = declaration.slice(0, separator);
|
|
48
|
+
result[name.startsWith("--") ? name : name.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase())] = declaration.slice(separator + 2);
|
|
49
|
+
}
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
/** One material- and depth-owning element. The host is a div unless `as` selects another. */
|
|
53
|
+
export const Surface = SurfaceView;
|
|
54
|
+
/**
|
|
55
|
+
* Marks an element that is disabled. Disabling fades only the outermost
|
|
56
|
+
* disabled element: parts inside it, such as a field's well or a disabled
|
|
57
|
+
* calendar's days, are disabled with it and do not fade a second time.
|
|
58
|
+
*/
|
|
59
|
+
export function dimmedClass(disabled, className) {
|
|
60
|
+
return [disabled ? dimmed : undefined, className].filter(Boolean).join(" ") || undefined;
|
|
61
|
+
}
|
|
62
|
+
const disabledOpacity = 0.46;
|
|
63
|
+
const dimmed = "phreshos-dimmed";
|
|
64
|
+
const surfaceClass = "phreshos-surface";
|
|
65
|
+
const materialLevel = Object.freeze({ none: 0, basic: 1, extended: 2, full: 3 });
|
|
66
|
+
/** How far hover and press move a paint toward the text color. */
|
|
67
|
+
export const interactionShift = Object.freeze({ hovered: 0.05, pressed: 0.1 });
|
|
68
|
+
/** A clear Surface has no paint to move, so it shows the same shift as a slightly stronger veil. */
|
|
69
|
+
export const clearVeil = 1.3;
|
|
70
|
+
/** Resolves every visual value of one Surface. Pure over its inputs. */
|
|
71
|
+
export function surfacePaint(visual, color, depth, options, shadowOptions, interaction) {
|
|
72
|
+
const { colors } = visual;
|
|
73
|
+
const base = resolveColor(color, colors);
|
|
74
|
+
const active = interaction !== undefined && !interaction.disabled;
|
|
75
|
+
const shift = active ? interaction.pressed ? interactionShift.pressed : interaction.hovered ? interactionShift.hovered : 0 : 0;
|
|
76
|
+
// Recessed paint sinks slightly below its surroundings; interaction then
|
|
77
|
+
// moves the same base toward the content color so every state stays related.
|
|
78
|
+
const darkness = canvasDarkness(colors);
|
|
79
|
+
// A recess moves away from its surroundings toward whichever extreme has
|
|
80
|
+
// room, by one constant perceptual difference on any canvas.
|
|
81
|
+
const rest = depth === "recessed" ? recessColor(base) : base;
|
|
82
|
+
// A transparent Surface has no substance of its own: it takes the content
|
|
83
|
+
// color of whatever it sits on and only reveals interaction as a veil.
|
|
84
|
+
const clear = base === "transparent";
|
|
85
|
+
const fill = clear
|
|
86
|
+
? shift > 0 ? colorOpacity(colors.foreground, shift * clearVeil) : "transparent"
|
|
87
|
+
: mixColor(rest, colors.foreground, shift);
|
|
88
|
+
const mode = clear ? "none" : typeof options === "object" ? "full" : options ?? "basic";
|
|
89
|
+
const level = materialLevel[mode];
|
|
90
|
+
const material = resolveMaterialOptions(typeof options === "object" ? options : {}, visual.material);
|
|
91
|
+
const opacity = level >= materialLevel.extended ? material.opacity : 1;
|
|
92
|
+
const translucent = opacity < 1;
|
|
93
|
+
const frost = level >= materialLevel.full && translucent
|
|
94
|
+
? [material.backdrop > 0 ? `blur(${material.backdrop}px)` : "", material.saturation !== 1 ? `saturate(${material.saturation})` : ""].filter(Boolean).join(" ")
|
|
95
|
+
: "";
|
|
96
|
+
const grain = level >= materialLevel.basic && material.grain > 0 && material.grainAmount > 0
|
|
97
|
+
? grainImage(grainSeed, material.grainAmount, level === materialLevel.basic ? material.grain * material.opacity : material.grain)
|
|
98
|
+
: "none";
|
|
99
|
+
const ringBase = interaction?.invalid
|
|
100
|
+
? colors.danger
|
|
101
|
+
: !clear && (contrast(base, colors.background) ?? 1) >= 1.6 ? base : colors.primary;
|
|
102
|
+
const edged = level >= materialLevel.basic;
|
|
103
|
+
const lit = edgeLight(depth, darkness);
|
|
104
|
+
const light = mixColor(fill, "#ffffff", 0.7);
|
|
105
|
+
// Light rises from the middle of the top and bottom edges and spreads along
|
|
106
|
+
// them, fading as it goes, so it leans toward the sides without reaching
|
|
107
|
+
// them; the same slight spill falls inward from both middles. A hairline
|
|
108
|
+
// outside separates the Surface from whatever it sits on. Neither edge
|
|
109
|
+
// dominates, so no Surface reads as a bevel. Depth changes only how much
|
|
110
|
+
// light the rim receives.
|
|
111
|
+
const rim = edged
|
|
112
|
+
? `linear-gradient(to right, transparent, ${colorOpacity(light, lit.side)} 18%, ${colorOpacity(light, lit.edge)} 50%, ${colorOpacity(light, lit.side)} 82%, transparent)`
|
|
113
|
+
: "none";
|
|
114
|
+
// The spill reaches at most a fixed depth, and less on short Surfaces: at a
|
|
115
|
+
// fixed depth, a small button was lit through nearly half its height and
|
|
116
|
+
// read as swollen, while a large panel barely changes.
|
|
117
|
+
const spill = (edge) => edged && lit.spill > 0
|
|
118
|
+
? `radial-gradient(50% ${spillDepth} at 50% ${edge === "top" ? "0" : "100%"}, ${colorOpacity(light, lit.spill)}, transparent)`
|
|
119
|
+
: "none";
|
|
120
|
+
// A recessed Surface holds a value, so focus and validity also claim its hairline.
|
|
121
|
+
const claimed = interaction?.invalid || (depth === "recessed" && interaction?.focusVisible);
|
|
122
|
+
const hairline = !edged
|
|
123
|
+
? null
|
|
124
|
+
: claimed
|
|
125
|
+
? `0 0 0 1px ${ringBase}`
|
|
126
|
+
: `0 0 0 0.5px ${colorOpacity("#000000", lit.hairline)}`;
|
|
127
|
+
const shadow = visual.shadow;
|
|
128
|
+
const outer = clear || depth !== "raised" || shadowOptions === false || (active && interaction.pressed)
|
|
129
|
+
? null
|
|
130
|
+
: shadowStyle(resolveShadowOptions(typeof shadowOptions === "object" ? shadowOptions : {}, shadow));
|
|
131
|
+
return {
|
|
132
|
+
fill,
|
|
133
|
+
// The label is chosen once for the resting paint: interaction shades stay
|
|
134
|
+
// close to it, and re-deciding per state would flip text on near-ties.
|
|
135
|
+
text: clear ? "inherit" : readableColor(rest, colors),
|
|
136
|
+
ring: colorOpacity(ringBase, 0.34),
|
|
137
|
+
shadow: [hairline, outer === "none" ? null : outer].filter(Boolean).join(", ") || "none",
|
|
138
|
+
distortion: level >= materialLevel.full && translucent ? material.distortion : 0,
|
|
139
|
+
variables: {
|
|
140
|
+
"--phreshos-surface-paint": translucent ? colorOpacity(fill, opacity) : fill,
|
|
141
|
+
"--phreshos-surface-grain": grain,
|
|
142
|
+
"--phreshos-surface-frost": frost || "none",
|
|
143
|
+
"--phreshos-surface-rim": rim,
|
|
144
|
+
"--phreshos-surface-spill-top": spill("top"),
|
|
145
|
+
"--phreshos-surface-spill-bottom": spill("bottom"),
|
|
146
|
+
"--phreshos-surface-duration": `${visual.duration}ms`,
|
|
147
|
+
"--phreshos-surface-easing": visual.easing
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
/** How far the inward spill reaches: a fixed depth, or a share of a short Surface's height. */
|
|
152
|
+
const spillDepth = "min(6px, 12%)";
|
|
153
|
+
/** How much light each part of the rim receives, interpolated along the canvas darkness. */
|
|
154
|
+
function edgeLight(depth, darkness) {
|
|
155
|
+
const { light, dark } = edgeLightEnds[depth];
|
|
156
|
+
return {
|
|
157
|
+
edge: round(mix(light.edge, dark.edge, darkness)),
|
|
158
|
+
side: round(mix(light.side, dark.side, darkness)),
|
|
159
|
+
spill: round(mix(light.spill, dark.spill, darkness)),
|
|
160
|
+
hairline: round(mix(light.hairline, dark.hairline, darkness))
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
function round(value) {
|
|
164
|
+
return Math.round(value * 1_000) / 1_000;
|
|
165
|
+
}
|
|
166
|
+
function mix(from, to, amount) {
|
|
167
|
+
return from + (to - from) * amount;
|
|
168
|
+
}
|
|
169
|
+
const edgeLightEnds = Object.freeze({
|
|
170
|
+
raised: {
|
|
171
|
+
light: { edge: 0.55, side: 0.22, spill: 0.15, hairline: 0.16 },
|
|
172
|
+
dark: { edge: 0.18, side: 0.08, spill: 0.035, hairline: 0.55 }
|
|
173
|
+
},
|
|
174
|
+
flat: {
|
|
175
|
+
light: { edge: 0.3, side: 0.14, spill: 0, hairline: 0.12 },
|
|
176
|
+
dark: { edge: 0.1, side: 0.05, spill: 0, hairline: 0.45 }
|
|
177
|
+
},
|
|
178
|
+
recessed: {
|
|
179
|
+
light: { edge: 0.45, side: 0.12, spill: 0, hairline: 0.12 },
|
|
180
|
+
dark: { edge: 0.12, side: 0.04, spill: 0, hairline: 0.45 }
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
/** A separate compositor pass for refraction, present only when it is visible. */
|
|
184
|
+
function Refraction({ identity, distortion }) {
|
|
185
|
+
const filter = `phreshos-refraction-${identity.replaceAll(":", "")}`;
|
|
186
|
+
return _jsx("span", { "aria-hidden": "true", "data-surface-refraction": "", style: {
|
|
187
|
+
position: "absolute",
|
|
188
|
+
inset: 0,
|
|
189
|
+
zIndex: -2,
|
|
190
|
+
borderRadius: "inherit",
|
|
191
|
+
pointerEvents: "none",
|
|
192
|
+
backdropFilter: `url("#${filter}")`,
|
|
193
|
+
WebkitBackdropFilter: `url("#${filter}")`
|
|
194
|
+
}, children: _jsx("svg", { width: "0", height: "0", focusable: "false", style: { position: "absolute" }, children: _jsxs("filter", { id: filter, x: "-20%", y: "-20%", width: "140%", height: "140%", colorInterpolationFilters: "sRGB", children: [_jsx("feTurbulence", { type: "fractalNoise", baseFrequency: "0.008 0.008", numOctaves: 2, seed: 92, result: "noise" }), _jsx("feGaussianBlur", { in: "noise", stdDeviation: 2, result: "soft" }), _jsx("feDisplacementMap", { in: "SourceGraphic", in2: "soft", scale: distortion, xChannelSelector: "R", yChannelSelector: "G" })] }) }) });
|
|
195
|
+
}
|
|
196
|
+
/*
|
|
197
|
+
* Paint and edge live on pseudo-elements driven by per-Surface custom
|
|
198
|
+
* properties, so a Surface is one DOM element regardless of its Material.
|
|
199
|
+
* Position and isolation use zero specificity so any consumer class or style
|
|
200
|
+
* can replace them.
|
|
201
|
+
*/
|
|
202
|
+
const stylesheet = `
|
|
203
|
+
:where(.${dimmed}:not(.${dimmed} .${dimmed})) {
|
|
204
|
+
opacity: ${disabledOpacity};
|
|
205
|
+
}
|
|
206
|
+
:where(.${surfaceClass}) {
|
|
207
|
+
position: relative;
|
|
208
|
+
isolation: isolate;
|
|
209
|
+
}
|
|
210
|
+
.${surfaceClass}::before,
|
|
211
|
+
.${surfaceClass}::after {
|
|
212
|
+
content: "";
|
|
213
|
+
position: absolute;
|
|
214
|
+
inset: 0;
|
|
215
|
+
border-radius: inherit;
|
|
216
|
+
pointer-events: none;
|
|
217
|
+
}
|
|
218
|
+
.${surfaceClass}::before {
|
|
219
|
+
z-index: -1;
|
|
220
|
+
background-color: var(--phreshos-surface-paint);
|
|
221
|
+
background-image: var(--phreshos-surface-spill-top), var(--phreshos-surface-spill-bottom), var(--phreshos-surface-grain);
|
|
222
|
+
background-size: auto, auto, ${grainSize}px ${grainSize}px;
|
|
223
|
+
-webkit-backdrop-filter: var(--phreshos-surface-frost);
|
|
224
|
+
backdrop-filter: var(--phreshos-surface-frost);
|
|
225
|
+
transition: background-color var(--phreshos-surface-duration) var(--phreshos-surface-easing);
|
|
226
|
+
}
|
|
227
|
+
.${surfaceClass}::after {
|
|
228
|
+
z-index: 1;
|
|
229
|
+
padding: 0.5px;
|
|
230
|
+
background: var(--phreshos-surface-rim);
|
|
231
|
+
-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
|
|
232
|
+
-webkit-mask-composite: xor;
|
|
233
|
+
mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
|
|
234
|
+
}
|
|
235
|
+
`;
|
|
236
|
+
/** React hoists and deduplicates this stylesheet, including inside portals. */
|
|
237
|
+
function SurfaceStyle() {
|
|
238
|
+
return _jsx("style", { href: "phreshos-react-ui-surface", precedence: "phreshos", children: stylesheet });
|
|
239
|
+
}
|
package/dist/switch.d.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import type { SwitchFieldProps } from "react-aria-components";
|
|
2
|
-
import type
|
|
3
|
-
import type { MaterialOverrides } from "./material-options.js";
|
|
4
|
-
|
|
5
|
-
export interface SwitchProps extends Omit<SwitchFieldProps, ControlOverrides | "isReadOnly" | "isSelected" | "defaultSelected">, ControlProps, FieldProps, MaterialOverrides, ShadowOverrides {
|
|
2
|
+
import { type ControlOverrides, type ControlProps, type FieldProps } from "./control/control.js";
|
|
3
|
+
import type { MaterialOverrides } from "./surface/material-options.js";
|
|
4
|
+
export interface SwitchProps extends Omit<SwitchFieldProps, ControlOverrides | "isSelected" | "defaultSelected">, ControlProps, FieldProps, MaterialOverrides {
|
|
6
5
|
readonly checked?: boolean;
|
|
7
6
|
readonly defaultChecked?: boolean;
|
|
8
7
|
readonly readOnly?: boolean;
|
|
9
8
|
}
|
|
10
|
-
/** An on/off setting. onChange receives the next boolean value. */
|
|
9
|
+
/** An on/off setting. `onChange` receives the next boolean value. */
|
|
11
10
|
export declare const Switch: import("react").ForwardRefExoticComponent<SwitchProps & import("react").RefAttributes<HTMLDivElement>>;
|
package/dist/switch.js
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef } from "react";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
import { SwitchButton, SwitchField } from "react-aria-components";
|
|
4
|
+
import { useControlMetrics } from "./control/control.js";
|
|
5
|
+
import { FieldFeedback, fieldStyle } from "./control/field.js";
|
|
6
|
+
import { ToggleIndicator, toggleRowStyle } from "./control/toggle.js";
|
|
7
|
+
import { resolveDirection, useDirection } from "./foundation/direction.js";
|
|
8
|
+
import { dimmedClass } from "./surface/surface.js";
|
|
9
|
+
/** An on/off setting. `onChange` receives the next boolean value. */
|
|
10
|
+
export const Switch = forwardRef(function Switch({ label, description, errorMessage, disabled, required, invalid, readOnly, className, checked, defaultChecked, size, color = "primary", style, material, ...properties }, ref) {
|
|
11
|
+
const metrics = useControlMetrics(size);
|
|
10
12
|
const direction = resolveDirection(properties.dir, useDirection());
|
|
11
|
-
return _jsxs(SwitchField, { ...properties, ref: ref, isDisabled: disabled, isRequired: required, isInvalid: invalid, isReadOnly: readOnly, isSelected: checked, defaultSelected: defaultChecked,
|
|
13
|
+
return _jsxs(SwitchField, { ...properties, ref: ref, isDisabled: disabled, isRequired: required, isInvalid: invalid, isReadOnly: readOnly, isSelected: checked, defaultSelected: defaultChecked, className: state => dimmedClass(state.isDisabled, className ?? state.defaultClassName) ?? "", style: fieldStyle(metrics, style), children: [_jsx(SwitchButton, { style: state => toggleRowStyle(metrics, state.isDisabled, state.isReadOnly), children: state => _jsxs(_Fragment, { children: [_jsx(ToggleIndicator, { kind: "switch", direction: direction, color: color, material: material, metrics: metrics, state: {
|
|
14
|
+
selected: state.isSelected,
|
|
15
|
+
hovered: !state.isReadOnly && state.isHovered,
|
|
16
|
+
pressed: !state.isReadOnly && state.isPressed,
|
|
17
|
+
focusVisible: state.isFocusVisible,
|
|
18
|
+
invalid: state.isInvalid,
|
|
19
|
+
disabled: state.isDisabled
|
|
20
|
+
} }), label] }) }), _jsx(FieldFeedback, { metrics: metrics, description: description, errorMessage: errorMessage })] });
|
|
12
21
|
});
|
package/dist/table.d.ts
CHANGED
|
@@ -1,71 +1,68 @@
|
|
|
1
1
|
import type { CSSProperties, ReactElement, RefAttributes } from "react";
|
|
2
2
|
import type { CellProps as AriaCellProps, ColumnProps as AriaColumnProps, RowProps as AriaRowProps, TableBodyProps as AriaTableBodyProps, TableHeaderProps as AriaTableHeaderProps, TableProps as AriaTableProps } from "react-aria-components";
|
|
3
|
-
import type
|
|
4
|
-
import type
|
|
5
|
-
import type {
|
|
6
|
-
import
|
|
3
|
+
import { type MultipleSelectionProps, type MultipleStringSelection, type NoSelectionProps, type SingleSelectionProps } from "./control/selection.js";
|
|
4
|
+
import { type Color } from "./foundation/color.js";
|
|
5
|
+
import type { RadiusProps } from "./foundation/radius.js";
|
|
6
|
+
import type { ScaleLevel } from "./foundation/scale.js";
|
|
7
7
|
export type TableSortDirection = "ascending" | "descending";
|
|
8
8
|
export interface TableSort {
|
|
9
9
|
readonly column: string;
|
|
10
10
|
readonly direction: TableSortDirection;
|
|
11
11
|
}
|
|
12
|
-
type TableRootBaseProps = Omit<AriaTableProps, "className" | "defaultSelectedKeys" | "disabledKeys" | "onRowAction" | "onSelectionChange" | "onSortChange" | "selectedKeys" | "selectionMode" | "sortDescriptor" | "style"> & RadiusProps & Readonly<{
|
|
12
|
+
type TableRootBaseProps = Omit<AriaTableProps, "className" | "defaultSelectedKeys" | "disabledKeys" | "onRowAction" | "onSelectionChange" | "onSortChange" | "selectedKeys" | "selectionMode" | "sortDescriptor" | "style" | "expandedKeys" | "defaultExpandedKeys" | "onExpandedChange" | "treeColumn" | "shouldSelectOnPressUp"> & RadiusProps & Readonly<{
|
|
13
13
|
className?: string;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
/** Color laid beneath selected Rows. */
|
|
15
|
+
color?: Color;
|
|
16
|
+
/** Runs with the value of the Row that was activated. */
|
|
17
|
+
onAction?: (value: string) => void;
|
|
17
18
|
onSortChange?: (sort: TableSort) => void;
|
|
19
|
+
/** Whether a Row is selected when the press ends instead of when it starts. */
|
|
20
|
+
selectOnPressUp?: boolean;
|
|
18
21
|
size?: ScaleLevel;
|
|
19
22
|
sort?: TableSort;
|
|
20
23
|
style?: CSSProperties;
|
|
21
24
|
}>;
|
|
22
|
-
export type TableNoSelectionProps =
|
|
23
|
-
|
|
24
|
-
value?: never;
|
|
25
|
-
defaultValue?: never;
|
|
26
|
-
onChange?: never;
|
|
27
|
-
}>;
|
|
28
|
-
export type TableSingleSelectionProps = SingleStringSelectionProps & Readonly<{
|
|
29
|
-
selectionMode: "single";
|
|
30
|
-
}>;
|
|
25
|
+
export type TableNoSelectionProps = NoSelectionProps;
|
|
26
|
+
export type TableSingleSelectionProps = SingleSelectionProps;
|
|
31
27
|
export type TableMultipleValue = MultipleStringSelection;
|
|
32
|
-
export type TableMultipleSelectionProps =
|
|
33
|
-
selectionMode: "multiple";
|
|
34
|
-
}>;
|
|
28
|
+
export type TableMultipleSelectionProps = MultipleSelectionProps;
|
|
35
29
|
export type TableRootProps = TableRootBaseProps & (TableNoSelectionProps | TableSingleSelectionProps | TableMultipleSelectionProps);
|
|
36
|
-
export declare const TableRoot: import("react").ForwardRefExoticComponent<TableRootProps & RefAttributes<HTMLDivElement | HTMLTableElement>>;
|
|
37
30
|
export interface TableHeaderProps<T extends object = object> extends Omit<AriaTableHeaderProps<T>, "className" | "style"> {
|
|
38
31
|
readonly className?: string;
|
|
39
|
-
readonly color?: ControlColor;
|
|
40
32
|
readonly style?: CSSProperties;
|
|
41
33
|
}
|
|
42
34
|
export type TableHeaderComponent = <T extends object = object>(properties: TableHeaderProps<T> & RefAttributes<HTMLTableSectionElement | HTMLDivElement>) => ReactElement | null;
|
|
43
|
-
export
|
|
44
|
-
|
|
45
|
-
readonly
|
|
35
|
+
export interface TableColumnProps extends Omit<AriaColumnProps, "allowsSorting" | "allowsArrowNavigation" | "className" | "id" | "isRowHeader" | "style"> {
|
|
36
|
+
/** Whether arrow keys move between cells while focus is inside this one. */
|
|
37
|
+
readonly arrowNavigation?: boolean;
|
|
38
|
+
/** Identity of this Column, reported in sort changes. */
|
|
46
39
|
readonly id: string;
|
|
40
|
+
/** Whether cells in this Column label their Row. */
|
|
41
|
+
readonly rowHeader?: boolean;
|
|
42
|
+
/** Whether pressing this Column requests a sort. */
|
|
43
|
+
readonly sortable?: boolean;
|
|
44
|
+
readonly className?: string;
|
|
47
45
|
readonly style?: CSSProperties;
|
|
48
46
|
}
|
|
49
|
-
export declare const TableColumn: import("react").ForwardRefExoticComponent<TableColumnProps & RefAttributes<HTMLDivElement | HTMLTableCellElement>>;
|
|
50
47
|
export interface TableBodyProps<T extends object = object> extends Omit<AriaTableBodyProps<T>, "className" | "style"> {
|
|
51
48
|
readonly className?: string;
|
|
52
49
|
readonly style?: CSSProperties;
|
|
53
50
|
}
|
|
54
51
|
export type TableBodyComponent = <T extends object = object>(properties: TableBodyProps<T> & RefAttributes<HTMLTableSectionElement | HTMLDivElement>) => ReactElement | null;
|
|
55
|
-
export
|
|
56
|
-
|
|
52
|
+
export interface TableRowProps<T extends object = object> extends Omit<AriaRowProps<T>, "className" | "id" | "isDisabled" | "style" | "hasChildItems"> {
|
|
53
|
+
/** Identity of this Row within its Table. */
|
|
54
|
+
readonly id: string;
|
|
57
55
|
readonly className?: string;
|
|
58
56
|
readonly disabled?: boolean;
|
|
59
|
-
readonly id: string;
|
|
60
57
|
readonly style?: CSSProperties;
|
|
61
58
|
}
|
|
62
59
|
export type TableRowComponent = <T extends object = object>(properties: TableRowProps<T> & RefAttributes<HTMLTableRowElement | HTMLDivElement>) => ReactElement | null;
|
|
63
|
-
export
|
|
64
|
-
|
|
60
|
+
export interface TableCellProps extends Omit<AriaCellProps, "className" | "style" | "allowsArrowNavigation"> {
|
|
61
|
+
/** Whether arrow keys move between cells while focus is inside this one. */
|
|
62
|
+
readonly arrowNavigation?: boolean;
|
|
65
63
|
readonly className?: string;
|
|
66
64
|
readonly style?: CSSProperties;
|
|
67
65
|
}
|
|
68
|
-
export declare const TableCell: import("react").ForwardRefExoticComponent<TableCellProps & RefAttributes<HTMLDivElement | HTMLTableCellElement>>;
|
|
69
66
|
/** Structured rows and columns with optional selection and consumer-owned sorting. */
|
|
70
67
|
export declare const Table: import("react").ForwardRefExoticComponent<TableRootProps & RefAttributes<HTMLDivElement | HTMLTableElement>> & {
|
|
71
68
|
Header: TableHeaderComponent;
|
package/dist/table.js
CHANGED
|
@@ -1,148 +1,110 @@
|
|
|
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 { Cell as AriaCell, Column as AriaColumn, Row as AriaRow, Table as AriaTable, TableBody as AriaTableBody, TableHeader as AriaTableHeader } from "react-aria-components";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { AriaDirectionBoundary } from "./aria-direction.js";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
4
|
+
import { controlFontWeight, controlOpacity, transition, useControlMetrics } from "./control/control.js";
|
|
5
|
+
import { separatorColor } from "./control/field.js";
|
|
6
|
+
import { itemPaint } from "./control/item.js";
|
|
7
|
+
import { ariaSelection, stringKey } from "./control/selection.js";
|
|
8
|
+
import { AriaDirectionBoundary } from "./foundation/aria-direction.js";
|
|
9
|
+
import { colorOpacity } from "./foundation/color.js";
|
|
10
|
+
import { resolveDirection, useDirection } from "./foundation/direction.js";
|
|
11
|
+
import { dimmedClass } from "./surface/surface.js";
|
|
12
|
+
import { ChevronUp } from "lucide-react";
|
|
13
|
+
import { iconProps } from "./control/icon.js";
|
|
14
|
+
const TableStyleContext = createContext(null);
|
|
15
|
+
/** Structured rows and columns with optional selection and consumer-owned sorting. */
|
|
16
|
+
const TableRoot = forwardRef(function Table(properties, ref) {
|
|
17
|
+
const { className, color = "primary", defaultValue: _defaultValue, onAction, onChange: _onChange, onSortChange, radius, selectOnPressUp, selectionMode = "none", size, sort, style, value: _value, ...native } = properties;
|
|
18
|
+
const metrics = useControlMetrics(size, radius);
|
|
19
|
+
const context = useMemo(() => ({ color, interactive: selectionMode !== "none" || onAction != null, metrics }), [color, metrics, onAction, selectionMode]);
|
|
14
20
|
const direction = resolveDirection(native.dir, useDirection());
|
|
15
|
-
return _jsx(
|
|
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: {
|
|
16
22
|
width: "100%",
|
|
17
23
|
minWidth: "max-content",
|
|
18
24
|
borderCollapse: "separate",
|
|
19
25
|
borderSpacing: 0,
|
|
20
26
|
boxSizing: "border-box",
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
// them rather than relying on a surrounding surface for its radius.
|
|
27
|
+
// Row paints belong to the table, so the table clips them to its own radius.
|
|
28
|
+
borderRadius: metrics.radius,
|
|
24
29
|
overflow: "hidden",
|
|
25
30
|
fontFamily: "inherit",
|
|
26
|
-
fontSize:
|
|
31
|
+
fontSize: metrics.fontSize,
|
|
27
32
|
...style
|
|
28
33
|
} }) }) });
|
|
29
34
|
});
|
|
30
|
-
function selectionProperties(properties) {
|
|
31
|
-
const selectedKeys = toAriaSelection(properties.value);
|
|
32
|
-
const defaultSelectedKeys = toAriaSelection(properties.defaultValue);
|
|
33
|
-
const onSelectionChange = properties.onChange == null
|
|
34
|
-
? undefined
|
|
35
|
-
: (selection) => {
|
|
36
|
-
if (properties.selectionMode === "multiple") {
|
|
37
|
-
properties.onChange?.(multipleSelection(selection));
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
if (properties.selectionMode === "single")
|
|
41
|
-
properties.onChange?.(singleSelection(selection));
|
|
42
|
-
};
|
|
43
|
-
return {
|
|
44
|
-
...(selectedKeys !== undefined ? { selectedKeys } : {}),
|
|
45
|
-
...(defaultSelectedKeys !== undefined ? { defaultSelectedKeys } : {}),
|
|
46
|
-
...(onSelectionChange !== undefined ? { onSelectionChange } : {})
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
35
|
function tableSort(descriptor) {
|
|
50
36
|
return { column: stringKey(descriptor.column), direction: descriptor.direction };
|
|
51
37
|
}
|
|
52
|
-
const TableHeaderImplementation = forwardRef(function TableHeader({ className,
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const theme = useControlTheme({ color: resolvedColor, radius: inherited.radius, size: inherited.size });
|
|
56
|
-
const context = useMemo(() => ({ ...inherited, color: resolvedColor, theme }), [inherited, resolvedColor, theme]);
|
|
57
|
-
return _jsx(TableThemeContext.Provider, { value: context, children: _jsx(AriaTableHeader, { ...properties, ref: ref, className: className, style: { ...style } }) });
|
|
38
|
+
const TableHeaderImplementation = forwardRef(function TableHeader({ className, style, ...properties }, ref) {
|
|
39
|
+
useTableStyle();
|
|
40
|
+
return _jsx(AriaTableHeader, { ...properties, ref: ref, className: className, style: style });
|
|
58
41
|
});
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const
|
|
62
|
-
return _jsx(AriaColumn, { ...properties, ref: ref, allowsSorting:
|
|
63
|
-
...
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
paddingBlock: theme.gap,
|
|
67
|
-
paddingInline: Math.max(8, theme.spacing),
|
|
42
|
+
const TableColumn = forwardRef(function TableColumn({ sortable = false, rowHeader, arrowNavigation, children, className, style, textValue, ...properties }, ref) {
|
|
43
|
+
const { metrics } = useTableStyle();
|
|
44
|
+
const { colors } = metrics.visual;
|
|
45
|
+
return _jsx(AriaColumn, { ...properties, allowsArrowNavigation: arrowNavigation, ref: ref, isRowHeader: rowHeader, allowsSorting: sortable, className: className, textValue: textValue ?? (typeof children === "string" ? children : undefined), style: state => ({
|
|
46
|
+
...transition(metrics.visual, "color, outline-color"),
|
|
47
|
+
height: metrics.height,
|
|
48
|
+
paddingInline: metrics.inset,
|
|
68
49
|
boxSizing: "border-box",
|
|
69
|
-
outline: state.isFocusVisible ?
|
|
70
|
-
outlineOffset: -
|
|
71
|
-
|
|
72
|
-
|
|
50
|
+
outline: `3px solid ${state.isFocusVisible ? colorOpacity(colors.primary, 0.34) : "transparent"}`,
|
|
51
|
+
outlineOffset: -3,
|
|
52
|
+
cursor: sortable ? "pointer" : "default",
|
|
53
|
+
fontSize: "0.92em",
|
|
73
54
|
fontWeight: controlFontWeight,
|
|
74
55
|
textAlign: "start",
|
|
75
56
|
userSelect: "none",
|
|
57
|
+
opacity: state.isHovered && sortable ? 1 : controlOpacity.secondary,
|
|
76
58
|
...style
|
|
77
|
-
}), children: state => _jsxs("span", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap:
|
|
59
|
+
}), children: state => _jsxs("span", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: metrics.gap, minWidth: 0 }, children: [_jsx("span", { style: { minWidth: 0 }, children: typeof children === "function" ? children(state) : children }), sortable && state.sortDirection != null && _jsx(ChevronUp, { ...iconProps(14), style: { ...transition(metrics.visual, "rotate"), flexShrink: 0, rotate: state.sortDirection === "descending" ? "180deg" : "0deg" } })] }) });
|
|
78
60
|
});
|
|
79
|
-
function SortIndicator({ direction, theme }) {
|
|
80
|
-
return _jsx("svg", { "aria-hidden": "true", width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", stroke: "currentColor", strokeWidth: "1.5", style: {
|
|
81
|
-
...theme.transition,
|
|
82
|
-
flexShrink: 0,
|
|
83
|
-
transitionProperty: "transform",
|
|
84
|
-
transform: `rotate(${direction === "descending" ? 180 : 0}deg)`
|
|
85
|
-
}, children: _jsx("path", { d: "m2 8 4-4 4 4" }) });
|
|
86
|
-
}
|
|
87
61
|
const TableBodyImplementation = forwardRef(function TableBody({ className, style, ...properties }, ref) {
|
|
88
|
-
return _jsx(AriaTableBody, { ...properties, ref: ref, className: className, style:
|
|
62
|
+
return _jsx(AriaTableBody, { ...properties, ref: ref, className: className, style: style });
|
|
89
63
|
});
|
|
90
|
-
|
|
64
|
+
/** Rows use the collection Item treatment as their own paint. */
|
|
91
65
|
const TableRowImplementation = forwardRef(function TableRow({ className, disabled = false, onAction, style, ...properties }, ref) {
|
|
92
|
-
const { interactive,
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
? theme.paints.subtle.hover
|
|
107
|
-
: { background: "transparent", color: "inherit" }),
|
|
66
|
+
const { color, interactive, metrics } = useTableStyle();
|
|
67
|
+
const responds = interactive || onAction != null;
|
|
68
|
+
return _jsx(AriaRow, { ...properties, ref: ref, className: state => dimmedClass(state.isDisabled, className ?? state.defaultClassName) ?? "", isDisabled: disabled, onAction: onAction, style: state => ({
|
|
69
|
+
...transition(metrics.visual, "background-color, color, outline-color"),
|
|
70
|
+
...itemPaint(metrics.visual, color, {
|
|
71
|
+
selected: state.isSelected,
|
|
72
|
+
hovered: responds && state.isHovered,
|
|
73
|
+
pressed: responds && state.isPressed,
|
|
74
|
+
focusVisible: false,
|
|
75
|
+
disabled: state.isDisabled
|
|
76
|
+
}),
|
|
77
|
+
outline: `3px solid ${state.isFocusVisible ? colorOpacity(metrics.visual.colors.primary, 0.34) : "transparent"}`,
|
|
78
|
+
outlineOffset: -3,
|
|
79
|
+
cursor: state.isDisabled ? "not-allowed" : responds ? "pointer" : "default",
|
|
108
80
|
...style
|
|
109
81
|
}) });
|
|
110
82
|
});
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
minWidth: 0,
|
|
117
|
-
height: theme.height,
|
|
118
|
-
paddingBlock: theme.gap,
|
|
119
|
-
paddingInline: Math.max(8, theme.spacing),
|
|
83
|
+
const TableCell = forwardRef(function TableCell({ arrowNavigation, className, style, ...properties }, ref) {
|
|
84
|
+
const { metrics } = useTableStyle();
|
|
85
|
+
return _jsx(AriaCell, { ...properties, allowsArrowNavigation: arrowNavigation, ref: ref, className: className, style: state => ({
|
|
86
|
+
height: metrics.height,
|
|
87
|
+
paddingInline: metrics.inset,
|
|
120
88
|
boxSizing: "border-box",
|
|
121
|
-
// Separators belong to the row that follows them
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
outlineOffset: -1,
|
|
126
|
-
background: "transparent",
|
|
127
|
-
color: "inherit",
|
|
89
|
+
// Separators belong to the row that follows them, so the last row has no bottom edge.
|
|
90
|
+
borderBlockStart: `1px solid ${separatorColor(metrics)}`,
|
|
91
|
+
outline: `3px solid ${state.isFocusVisible ? colorOpacity(metrics.visual.colors.primary, 0.34) : "transparent"}`,
|
|
92
|
+
outlineOffset: -3,
|
|
128
93
|
textAlign: "start",
|
|
129
94
|
...style
|
|
130
95
|
}) });
|
|
131
96
|
});
|
|
132
|
-
function
|
|
133
|
-
const
|
|
134
|
-
if (
|
|
97
|
+
function useTableStyle() {
|
|
98
|
+
const context = useContext(TableStyleContext);
|
|
99
|
+
if (context == null)
|
|
135
100
|
throw new Error("Table parts must be used inside Table");
|
|
136
|
-
return
|
|
137
|
-
}
|
|
138
|
-
function useTableTheme() {
|
|
139
|
-
return useTableContext().theme;
|
|
101
|
+
return context;
|
|
140
102
|
}
|
|
141
103
|
/** Structured rows and columns with optional selection and consumer-owned sorting. */
|
|
142
104
|
export const Table = Object.assign(TableRoot, {
|
|
143
|
-
Header:
|
|
105
|
+
Header: TableHeaderImplementation,
|
|
144
106
|
Column: TableColumn,
|
|
145
|
-
Body:
|
|
146
|
-
Row:
|
|
107
|
+
Body: TableBodyImplementation,
|
|
108
|
+
Row: TableRowImplementation,
|
|
147
109
|
Cell: TableCell
|
|
148
110
|
});
|