@phreshos/react-ui 0.1.36 → 0.1.37
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.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 +12 -24
- package/dist/button.js +34 -39
- 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 +34 -0
- package/dist/control/item.js +53 -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 +22 -8
- 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 +7 -4
- 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} +3 -5
- package/dist/{ui-provider.js → foundation/provider.js} +14 -26
- 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 +27 -16
- 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 +19 -5
- 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 +6 -0
- package/dist/surface/paint-class.js +36 -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 +73 -0
- package/dist/surface/surface.js +230 -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 +13 -4
- package/dist/tooltip.js +17 -15
- package/dist/tree.d.ts +22 -27
- package/dist/tree.js +54 -99
- package/dist/window.d.ts +2 -2
- 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,71 @@
|
|
|
1
|
+
import { resolveRadius } from "../foundation/radius.js";
|
|
2
|
+
import { isScaleLevel } from "../foundation/scale.js";
|
|
3
|
+
import { scale } from "../foundation/scale.js";
|
|
4
|
+
import { useVisual } from "../foundation/visual.js";
|
|
5
|
+
/** Relative text scale for control content. Only a component's root applies it. */
|
|
6
|
+
export const controlFontSizes = Object.freeze({
|
|
7
|
+
xsmall: "0.6875em",
|
|
8
|
+
small: "0.75em",
|
|
9
|
+
medium: "0.8125em",
|
|
10
|
+
large: "0.875em",
|
|
11
|
+
xlarge: "0.9375em"
|
|
12
|
+
});
|
|
13
|
+
export const controlFontWeight = 600;
|
|
14
|
+
/** Attenuation shared by every control family. */
|
|
15
|
+
export const controlOpacity = Object.freeze({
|
|
16
|
+
pending: 0.68,
|
|
17
|
+
secondary: 0.66,
|
|
18
|
+
placeholder: 0.55
|
|
19
|
+
});
|
|
20
|
+
const metrics = new WeakMap();
|
|
21
|
+
/** Returns the shared metrics for one size and radius in the active Appearance. */
|
|
22
|
+
export function useControlMetrics(size = "medium", radius = "medium") {
|
|
23
|
+
return controlMetrics(useVisual(), size, radius);
|
|
24
|
+
}
|
|
25
|
+
export function controlMetrics(visual, size, radius) {
|
|
26
|
+
let cache = metrics.get(visual);
|
|
27
|
+
if (cache === undefined)
|
|
28
|
+
metrics.set(visual, cache = new Map());
|
|
29
|
+
const key = `${size}:${radius}`;
|
|
30
|
+
const cached = cache.get(key);
|
|
31
|
+
if (cached !== undefined)
|
|
32
|
+
return cached;
|
|
33
|
+
const spacing = scale(visual.spacing, size);
|
|
34
|
+
const height = controlHeight(spacing);
|
|
35
|
+
const result = Object.freeze({
|
|
36
|
+
visual,
|
|
37
|
+
spacing,
|
|
38
|
+
height,
|
|
39
|
+
// Side padding follows the size, never below half the Appearance spacing,
|
|
40
|
+
// so a compact icon-only control stays close to square.
|
|
41
|
+
inset: Math.max(visual.spacing / 2, spacing),
|
|
42
|
+
gap: Math.max(4, spacing / 2),
|
|
43
|
+
indicator: Math.round(14 + spacing / 3),
|
|
44
|
+
listInset: Math.max(4, spacing / 3),
|
|
45
|
+
radius: isScaleLevel(radius) ? proportionalRadius(visual, height, radius) : resolveRadius(radius, visual.radius),
|
|
46
|
+
fontSize: controlFontSizes[size]
|
|
47
|
+
});
|
|
48
|
+
cache.set(key, result);
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
/** The height of a control whose size level resolves to this spacing. */
|
|
52
|
+
function controlHeight(spacing) {
|
|
53
|
+
return Math.round(22 + spacing);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* An Appearance radius level scaled to one control height, so a control keeps
|
|
57
|
+
* the same shape at every size: the medium control height carries the
|
|
58
|
+
* Appearance radius itself.
|
|
59
|
+
*/
|
|
60
|
+
export function proportionalRadius(visual, height, level = "medium") {
|
|
61
|
+
const medium = controlHeight(visual.spacing);
|
|
62
|
+
return Math.round(scale(visual.radius, level) * height / medium * 100) / 100;
|
|
63
|
+
}
|
|
64
|
+
/** A CSS transition for the given properties using the Appearance transaction. */
|
|
65
|
+
export function transition(visual, properties, factor = 1) {
|
|
66
|
+
return {
|
|
67
|
+
transitionProperty: properties,
|
|
68
|
+
transitionDuration: `${visual.duration * factor}ms`,
|
|
69
|
+
transitionTimingFunction: visual.easing
|
|
70
|
+
};
|
|
71
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { CSSProperties, ReactNode } from "react";
|
|
2
|
+
import { type ButtonProps as AriaButtonProps } from "react-aria-components";
|
|
3
|
+
import type { ControlMetrics } from "./control.js";
|
|
4
|
+
/**
|
|
5
|
+
* A quiet button held at the end of a field's well, such as a date picker's
|
|
6
|
+
* calendar or a number field's steppers. It veils like any quiet control and
|
|
7
|
+
* sits the same distance from every edge of the well.
|
|
8
|
+
*/
|
|
9
|
+
export declare function FieldButton({ metrics, children, style, ...properties }: Readonly<Omit<AriaButtonProps, "children" | "render" | "style"> & {
|
|
10
|
+
metrics: ControlMetrics;
|
|
11
|
+
children: ReactNode;
|
|
12
|
+
style?: CSSProperties;
|
|
13
|
+
}>): import("react").JSX.Element;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Button as AriaButton } from "react-aria-components";
|
|
3
|
+
import { surfaceRender } from "./surface-render.js";
|
|
4
|
+
/**
|
|
5
|
+
* A quiet button held at the end of a field's well, such as a date picker's
|
|
6
|
+
* calendar or a number field's steppers. It veils like any quiet control and
|
|
7
|
+
* sits the same distance from every edge of the well.
|
|
8
|
+
*/
|
|
9
|
+
export function FieldButton({ metrics, children, style, ...properties }) {
|
|
10
|
+
const size = metrics.height - 8;
|
|
11
|
+
return _jsx(AriaButton, { ...properties, render: surfaceRender("button", state => ({
|
|
12
|
+
color: "transparent",
|
|
13
|
+
radius: metrics.radius,
|
|
14
|
+
interaction: { hovered: state.isHovered, pressed: state.isPressed, focusVisible: state.isFocusVisible, disabled: state.isDisabled }
|
|
15
|
+
})), style: {
|
|
16
|
+
appearance: "none",
|
|
17
|
+
display: "grid",
|
|
18
|
+
placeItems: "center",
|
|
19
|
+
flex: "0 0 auto",
|
|
20
|
+
width: size,
|
|
21
|
+
height: size,
|
|
22
|
+
padding: 0,
|
|
23
|
+
border: 0,
|
|
24
|
+
background: "none",
|
|
25
|
+
cursor: "pointer",
|
|
26
|
+
...style
|
|
27
|
+
}, children: children });
|
|
28
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { CSSProperties, ReactNode } from "react";
|
|
2
|
+
import { type ControlMetrics } from "./control.js";
|
|
3
|
+
/**
|
|
4
|
+
* The root of every value-holding component. It is the only element that
|
|
5
|
+
* applies the control text scale; every part inherits from it.
|
|
6
|
+
*/
|
|
7
|
+
export declare function fieldStyle(metrics: ControlMetrics, style?: CSSProperties): CSSProperties;
|
|
8
|
+
export declare function FieldLabel({ label }: Readonly<{
|
|
9
|
+
label?: ReactNode;
|
|
10
|
+
}>): import("react").JSX.Element | null;
|
|
11
|
+
/** Description and validation text shared by every field. */
|
|
12
|
+
export declare function FieldFeedback({ description, errorMessage, metrics }: Readonly<{
|
|
13
|
+
description?: ReactNode;
|
|
14
|
+
errorMessage?: ReactNode;
|
|
15
|
+
metrics: ControlMetrics;
|
|
16
|
+
}>): import("react").JSX.Element;
|
|
17
|
+
/** How strongly every separator shows its text color. */
|
|
18
|
+
export declare const separatorOpacity = 0.1;
|
|
19
|
+
/** Separator paint shared by menus, tables, layouts, and toolbars. */
|
|
20
|
+
export declare function separatorColor(metrics: ControlMetrics): string;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { FieldError, Label, Text } from "react-aria-components";
|
|
3
|
+
import { colorOpacity, mixColor } from "../foundation/color.js";
|
|
4
|
+
import { controlFontWeight, controlOpacity } from "./control.js";
|
|
5
|
+
/**
|
|
6
|
+
* The root of every value-holding component. It is the only element that
|
|
7
|
+
* applies the control text scale; every part inherits from it.
|
|
8
|
+
*/
|
|
9
|
+
export function fieldStyle(metrics, style) {
|
|
10
|
+
return {
|
|
11
|
+
display: "grid",
|
|
12
|
+
alignContent: "start",
|
|
13
|
+
gap: metrics.gap,
|
|
14
|
+
minWidth: 0,
|
|
15
|
+
fontFamily: "inherit",
|
|
16
|
+
fontSize: metrics.fontSize,
|
|
17
|
+
lineHeight: 1.45,
|
|
18
|
+
...style
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export function FieldLabel({ label }) {
|
|
22
|
+
return label == null ? null : _jsx(Label, { style: { fontWeight: controlFontWeight }, children: label });
|
|
23
|
+
}
|
|
24
|
+
/** Description and validation text shared by every field. */
|
|
25
|
+
export function FieldFeedback({ description, errorMessage, metrics }) {
|
|
26
|
+
const { colors } = metrics.visual;
|
|
27
|
+
return _jsxs(_Fragment, { children: [description != null && _jsx(Text, { slot: "description", style: { fontSize: "0.92em", opacity: controlOpacity.secondary }, children: description }), _jsx(FieldError, { style: { fontSize: "0.92em", color: mixColor(colors.danger, colors.foreground, 0.15) }, children: errorMessage })] });
|
|
28
|
+
}
|
|
29
|
+
/** How strongly every separator shows its text color. */
|
|
30
|
+
export const separatorOpacity = 0.1;
|
|
31
|
+
/** Separator paint shared by menus, tables, layouts, and toolbars. */
|
|
32
|
+
export function separatorColor(metrics) {
|
|
33
|
+
return colorOpacity(metrics.visual.colors.foreground, separatorOpacity);
|
|
34
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The treatment of every icon React UI draws inside its own components: a
|
|
3
|
+
* constant 1.5px stroke at any size, hidden from assistive technology because
|
|
4
|
+
* the control that holds it carries the name.
|
|
5
|
+
*/
|
|
6
|
+
export declare function iconProps(size: number): {
|
|
7
|
+
readonly size: number;
|
|
8
|
+
readonly strokeWidth: 1.5;
|
|
9
|
+
readonly nonScalingStroke: true;
|
|
10
|
+
readonly "aria-hidden": true;
|
|
11
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The treatment of every icon React UI draws inside its own components: a
|
|
3
|
+
* constant 1.5px stroke at any size, hidden from assistive technology because
|
|
4
|
+
* the control that holds it carries the name.
|
|
5
|
+
*/
|
|
6
|
+
export function iconProps(size) {
|
|
7
|
+
return { size, strokeWidth: 1.5, nonScalingStroke: true, "aria-hidden": true };
|
|
8
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { CSSProperties } from "react";
|
|
2
|
+
import { type Color } from "../foundation/color.js";
|
|
3
|
+
import type { Visual } from "../foundation/visual.js";
|
|
4
|
+
import { type ControlMetrics } from "./control.js";
|
|
5
|
+
import type { SurfaceRenderProps } from "./surface-render.js";
|
|
6
|
+
/**
|
|
7
|
+
* The level that marks what is selected, in every collection and inside a
|
|
8
|
+
* calendar range.
|
|
9
|
+
*/
|
|
10
|
+
export declare const selectionLevel = "subtle";
|
|
11
|
+
export type ItemState = Readonly<{
|
|
12
|
+
selected: boolean;
|
|
13
|
+
hovered: boolean;
|
|
14
|
+
pressed: boolean;
|
|
15
|
+
focusVisible: boolean;
|
|
16
|
+
disabled: boolean;
|
|
17
|
+
}>;
|
|
18
|
+
/**
|
|
19
|
+
* One entry of a collection. At rest it has no paint of its own; hover and
|
|
20
|
+
* press veil it, and selection lays the selection level of the collection
|
|
21
|
+
* color beneath it. Every collection uses this same treatment.
|
|
22
|
+
*/
|
|
23
|
+
export declare function itemSurface(visual: Visual, color: Color, state: ItemState, radius: CSSProperties["borderRadius"]): SurfaceRenderProps;
|
|
24
|
+
/** The same treatment as a plain paint, for elements that cannot host a Surface. */
|
|
25
|
+
export declare function itemPaint(visual: Visual, color: Color, state: ItemState): Readonly<{
|
|
26
|
+
background: string;
|
|
27
|
+
color: string;
|
|
28
|
+
}>;
|
|
29
|
+
/** Layout shared by list, menu, and tree entries. */
|
|
30
|
+
export declare function itemStyle(metrics: ControlMetrics, disabled: boolean): CSSProperties;
|
|
31
|
+
/** The selection mark drawn at the end of a selected entry. */
|
|
32
|
+
export declare function SelectionMark({ visible }: Readonly<{
|
|
33
|
+
visible: boolean;
|
|
34
|
+
}>): import("react").JSX.Element;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { colorLevel, resolveColor } from "../foundation/color.js";
|
|
3
|
+
import { surfacePaint } from "../surface/surface.js";
|
|
4
|
+
import { transition } from "./control.js";
|
|
5
|
+
import { Check } from "lucide-react";
|
|
6
|
+
import { iconProps } from "./icon.js";
|
|
7
|
+
/**
|
|
8
|
+
* The level that marks what is selected, in every collection and inside a
|
|
9
|
+
* calendar range.
|
|
10
|
+
*/
|
|
11
|
+
export const selectionLevel = "subtle";
|
|
12
|
+
/**
|
|
13
|
+
* One entry of a collection. At rest it has no paint of its own; hover and
|
|
14
|
+
* press veil it, and selection lays the selection level of the collection
|
|
15
|
+
* color beneath it. Every collection uses this same treatment.
|
|
16
|
+
*/
|
|
17
|
+
export function itemSurface(visual, color, state, radius) {
|
|
18
|
+
return {
|
|
19
|
+
color: state.selected ? colorLevel(resolveColor(color, visual.colors), selectionLevel, visual.colors) : "transparent",
|
|
20
|
+
depth: "flat",
|
|
21
|
+
material: "none",
|
|
22
|
+
radius,
|
|
23
|
+
interaction: itemInteraction(state)
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/** The same treatment as a plain paint, for elements that cannot host a Surface. */
|
|
27
|
+
export function itemPaint(visual, color, state) {
|
|
28
|
+
const paint = surfacePaint(visual, state.selected ? colorLevel(resolveColor(color, visual.colors), selectionLevel, visual.colors) : "transparent", "flat", "none", false, itemInteraction(state));
|
|
29
|
+
return { background: paint.fill, color: paint.text };
|
|
30
|
+
}
|
|
31
|
+
function itemInteraction(state) {
|
|
32
|
+
return { hovered: state.hovered, pressed: state.pressed, focusVisible: state.focusVisible, disabled: state.disabled };
|
|
33
|
+
}
|
|
34
|
+
/** Layout shared by list, menu, and tree entries. */
|
|
35
|
+
export function itemStyle(metrics, disabled) {
|
|
36
|
+
return {
|
|
37
|
+
...transition(metrics.visual, "box-shadow, color, outline-color, opacity"),
|
|
38
|
+
display: "flex",
|
|
39
|
+
alignItems: "center",
|
|
40
|
+
gap: metrics.gap,
|
|
41
|
+
minWidth: 0,
|
|
42
|
+
minHeight: metrics.height,
|
|
43
|
+
paddingInline: metrics.inset,
|
|
44
|
+
boxSizing: "border-box",
|
|
45
|
+
cursor: disabled ? "not-allowed" : "pointer",
|
|
46
|
+
userSelect: "none",
|
|
47
|
+
outlineOffset: -1
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/** The selection mark drawn at the end of a selected entry. */
|
|
51
|
+
export function SelectionMark({ visible }) {
|
|
52
|
+
return _jsx(Check, { ...iconProps(14), style: { flexShrink: 0, marginInlineStart: "auto", opacity: visible ? 1 : 0 } });
|
|
53
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Whether an overlay is shown. Its root owns this state; triggers and
|
|
4
|
+
* positioned parts only read it, so they never repeat it.
|
|
5
|
+
*/
|
|
6
|
+
export type OpenStateProps = Readonly<{
|
|
7
|
+
open?: boolean;
|
|
8
|
+
defaultOpen?: boolean;
|
|
9
|
+
onOpenChange?: (open: boolean) => void;
|
|
10
|
+
}>;
|
|
11
|
+
/** The root of an overlay family: its open state and its parts. */
|
|
12
|
+
export type OverlayRootProps = OpenStateProps & Readonly<{
|
|
13
|
+
children: ReactNode;
|
|
14
|
+
}>;
|
|
15
|
+
/**
|
|
16
|
+
* React Aria props that overlay parts own internally, or that belong to the
|
|
17
|
+
* family root as open state. They never appear on React UI overlay parts.
|
|
18
|
+
*/
|
|
19
|
+
export type AriaOverlayInternals = "isOpen" | "defaultOpen" | "onOpenChange" | "isEntering" | "isExiting" | "isNonModal" | "isDismissable" | "isKeyboardDismissDisabled" | "shouldCloseOnInteractOutside" | "shouldFlip" | "shouldUpdatePosition" | "shouldSkipAnimation" | "trigger" | "triggerRef" | "UNSTABLE_portalContainer" | "arrowRef" | "arrowBoundaryOffset" | "scrollRef" | "getTargetRect";
|
|
20
|
+
/** The one translation from React UI's open-state names to React Aria's. */
|
|
21
|
+
export declare function ariaOpenState({ open, defaultOpen, onOpenChange }: OpenStateProps): {
|
|
22
|
+
onOpenChange?: ((open: boolean) => void) | undefined;
|
|
23
|
+
defaultOpen?: boolean | undefined;
|
|
24
|
+
isOpen?: boolean | undefined;
|
|
25
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** The one translation from React UI's open-state names to React Aria's. */
|
|
2
|
+
export function ariaOpenState({ open, defaultOpen, onOpenChange }) {
|
|
3
|
+
return {
|
|
4
|
+
...(open !== undefined ? { isOpen: open } : {}),
|
|
5
|
+
...(defaultOpen !== undefined ? { defaultOpen } : {}),
|
|
6
|
+
...(onOpenChange !== undefined ? { onOpenChange } : {})
|
|
7
|
+
};
|
|
8
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { CSSProperties, ReactNode } from "react";
|
|
2
|
+
import { type Color } from "../foundation/color.js";
|
|
3
|
+
import type { MaterialOverrides } from "../surface/material-options.js";
|
|
4
|
+
import { type ControlMetrics } from "./control.js";
|
|
5
|
+
type Orientation = "horizontal" | "vertical";
|
|
6
|
+
/** The track's padding around the items it holds. */
|
|
7
|
+
export declare const selectionTrackInset = 3;
|
|
8
|
+
/**
|
|
9
|
+
* A recessed track holding a row of mutually exclusive items, such as Tabs or
|
|
10
|
+
* a SegmentedControl; the selection rises out of it as one raised Surface that
|
|
11
|
+
* slides to whichever item is selected. The list inside marks itself with
|
|
12
|
+
* `data-selection-list`, and React Aria marks the selected item `data-selected`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function SelectionTrack({ metrics, color, material, orientation, selectedKey, className, style, children }: Readonly<{
|
|
15
|
+
metrics: ControlMetrics;
|
|
16
|
+
color: Color;
|
|
17
|
+
material: MaterialOverrides["material"];
|
|
18
|
+
orientation: Orientation;
|
|
19
|
+
selectedKey: unknown;
|
|
20
|
+
className?: string;
|
|
21
|
+
style?: CSSProperties;
|
|
22
|
+
children: ReactNode;
|
|
23
|
+
}>): import("react").JSX.Element;
|
|
24
|
+
/** Layout of the list inside a SelectionTrack: equal columns across, or a stack. */
|
|
25
|
+
export declare function selectionListStyle(orientation: Orientation): CSSProperties;
|
|
26
|
+
type ItemState = Readonly<{
|
|
27
|
+
isSelected: boolean;
|
|
28
|
+
isFocusVisible: boolean;
|
|
29
|
+
isDisabled: boolean;
|
|
30
|
+
}>;
|
|
31
|
+
/** One item of a SelectionTrack; its label reads against the selection when selected. */
|
|
32
|
+
export declare function selectionItemStyle(metrics: ControlMetrics, color: Color, orientation: Orientation, state: ItemState): CSSProperties;
|
|
33
|
+
/** An item's label: an optional leading icon and text, centered a gap apart. */
|
|
34
|
+
export declare function SelectionItemLabel({ metrics, emphasized, children }: Readonly<{
|
|
35
|
+
metrics: ControlMetrics;
|
|
36
|
+
emphasized: boolean;
|
|
37
|
+
children: ReactNode;
|
|
38
|
+
}>): import("react").JSX.Element;
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useLayoutEffect, useRef, useState } from "react";
|
|
3
|
+
import { colorOpacity, readableColor, resolveColor } from "../foundation/color.js";
|
|
4
|
+
import { Surface, SurfaceView } from "../surface/surface.js";
|
|
5
|
+
import { controlOpacity, transition } from "./control.js";
|
|
6
|
+
/** The track's padding around the items it holds. */
|
|
7
|
+
export const selectionTrackInset = 3;
|
|
8
|
+
/**
|
|
9
|
+
* A recessed track holding a row of mutually exclusive items, such as Tabs or
|
|
10
|
+
* a SegmentedControl; the selection rises out of it as one raised Surface that
|
|
11
|
+
* slides to whichever item is selected. The list inside marks itself with
|
|
12
|
+
* `data-selection-list`, and React Aria marks the selected item `data-selected`.
|
|
13
|
+
*/
|
|
14
|
+
export function SelectionTrack({ metrics, color, material, orientation, selectedKey, className, style, children }) {
|
|
15
|
+
const track = useRef(null);
|
|
16
|
+
const selection = useSelectionPlacement(track, selectedKey, orientation);
|
|
17
|
+
return _jsxs(SurfaceView, { ref: track, color: "background", depth: "recessed", material: material, radius: metrics.radius, className: className, style: { padding: selectionTrackInset, width: orientation === "horizontal" ? "100%" : undefined, boxSizing: "border-box", ...style }, children: [selection !== null && _jsx(Surface, { "data-selection-indicator": "", "aria-hidden": "true", color: color, material: material, radius: metrics.radius, style: {
|
|
18
|
+
...(selection.moving ? transition(metrics.visual, "translate, width, height") : {}),
|
|
19
|
+
position: "absolute",
|
|
20
|
+
top: 0,
|
|
21
|
+
left: 0,
|
|
22
|
+
zIndex: 1,
|
|
23
|
+
width: selection.width,
|
|
24
|
+
height: selection.height,
|
|
25
|
+
translate: `${selection.x}px ${selection.y}px`
|
|
26
|
+
} }), children] });
|
|
27
|
+
}
|
|
28
|
+
/** Layout of the list inside a SelectionTrack: equal columns across, or a stack. */
|
|
29
|
+
export function selectionListStyle(orientation) {
|
|
30
|
+
return {
|
|
31
|
+
position: "relative",
|
|
32
|
+
zIndex: 2,
|
|
33
|
+
display: "grid",
|
|
34
|
+
gridAutoFlow: orientation === "horizontal" ? "column" : "row",
|
|
35
|
+
gridAutoColumns: orientation === "horizontal" ? "minmax(0, 1fr)" : undefined,
|
|
36
|
+
alignContent: "start",
|
|
37
|
+
gap: 2,
|
|
38
|
+
minWidth: 0
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/** One item of a SelectionTrack; its label reads against the selection when selected. */
|
|
42
|
+
export function selectionItemStyle(metrics, color, orientation, state) {
|
|
43
|
+
const { colors } = metrics.visual;
|
|
44
|
+
return {
|
|
45
|
+
...transition(metrics.visual, "color, outline-color"),
|
|
46
|
+
position: "relative",
|
|
47
|
+
display: "flex",
|
|
48
|
+
alignItems: "center",
|
|
49
|
+
justifyContent: orientation === "vertical" ? "start" : "center",
|
|
50
|
+
minWidth: 0,
|
|
51
|
+
minHeight: metrics.height - selectionTrackInset * 2,
|
|
52
|
+
paddingInline: metrics.inset,
|
|
53
|
+
boxSizing: "border-box",
|
|
54
|
+
border: 0,
|
|
55
|
+
background: "none",
|
|
56
|
+
font: "inherit",
|
|
57
|
+
borderRadius: metrics.radius,
|
|
58
|
+
outline: `3px solid ${state.isFocusVisible ? colorOpacity(colors.primary, 0.34) : "transparent"}`,
|
|
59
|
+
outlineOffset: 1,
|
|
60
|
+
cursor: state.isDisabled ? "not-allowed" : "pointer",
|
|
61
|
+
userSelect: "none",
|
|
62
|
+
fontWeight: 500,
|
|
63
|
+
color: state.isSelected ? readableColor(resolveColor(color, colors), colors) : colors.foreground
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/** An item's label: an optional leading icon and text, centered a gap apart. */
|
|
67
|
+
export function SelectionItemLabel({ metrics, emphasized, children }) {
|
|
68
|
+
return _jsx("span", { style: {
|
|
69
|
+
...transition(metrics.visual, "opacity"),
|
|
70
|
+
display: "flex",
|
|
71
|
+
alignItems: "center",
|
|
72
|
+
gap: metrics.gap,
|
|
73
|
+
minWidth: 0,
|
|
74
|
+
overflow: "hidden",
|
|
75
|
+
whiteSpace: "nowrap",
|
|
76
|
+
opacity: emphasized ? 1 : controlOpacity.secondary
|
|
77
|
+
}, children: children });
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Where the selected item sits inside the track. The first placement appears
|
|
81
|
+
* in place; later ones slide.
|
|
82
|
+
*/
|
|
83
|
+
function useSelectionPlacement(track, selectedKey, orientation) {
|
|
84
|
+
const [placement, setPlacement] = useState(null);
|
|
85
|
+
useLayoutEffect(() => {
|
|
86
|
+
const element = track.current;
|
|
87
|
+
const list = element?.querySelector("[data-selection-list]");
|
|
88
|
+
if (element == null || list == null)
|
|
89
|
+
return;
|
|
90
|
+
const measure = () => {
|
|
91
|
+
const item = list.querySelector("[data-selected]");
|
|
92
|
+
if (item == null)
|
|
93
|
+
return setPlacement(null);
|
|
94
|
+
const outer = element.getBoundingClientRect();
|
|
95
|
+
const inner = item.getBoundingClientRect();
|
|
96
|
+
// Rectangles keep subpixel precision; dividing by the track's own
|
|
97
|
+
// scale undoes any transform, such as an entering overlay's.
|
|
98
|
+
const scale = element.offsetWidth > 0 ? outer.width / element.offsetWidth : 1;
|
|
99
|
+
const next = {
|
|
100
|
+
x: (inner.left - outer.left) / scale - element.clientLeft,
|
|
101
|
+
y: (inner.top - outer.top) / scale - element.clientTop,
|
|
102
|
+
width: inner.width / scale,
|
|
103
|
+
height: inner.height / scale
|
|
104
|
+
};
|
|
105
|
+
setPlacement(previous => previous !== null && previous.x === next.x && previous.y === next.y
|
|
106
|
+
&& previous.width === next.width && previous.height === next.height
|
|
107
|
+
? previous
|
|
108
|
+
: { ...next, moving: previous !== null });
|
|
109
|
+
};
|
|
110
|
+
measure();
|
|
111
|
+
// Items render after the list itself, and selection is written onto them.
|
|
112
|
+
const mutations = new MutationObserver(measure);
|
|
113
|
+
mutations.observe(list, { subtree: true, childList: true, attributeFilter: ["data-selected"] });
|
|
114
|
+
const resizes = typeof ResizeObserver === "function" ? new ResizeObserver(measure) : null;
|
|
115
|
+
resizes?.observe(list);
|
|
116
|
+
return () => {
|
|
117
|
+
mutations.disconnect();
|
|
118
|
+
resizes?.disconnect();
|
|
119
|
+
};
|
|
120
|
+
}, [track, selectedKey, orientation]);
|
|
121
|
+
return placement;
|
|
122
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { Key, Selection } from "react-aria-components";
|
|
2
|
+
export type MultipleStringSelection = readonly string[] | "all";
|
|
3
|
+
export type SingleStringSelectionProps = Readonly<{
|
|
4
|
+
value?: string | null;
|
|
5
|
+
defaultValue?: string | null;
|
|
6
|
+
onChange?: (value: string | null) => void;
|
|
7
|
+
}>;
|
|
8
|
+
export type MultipleStringSelectionProps = Readonly<{
|
|
9
|
+
value?: MultipleStringSelection;
|
|
10
|
+
defaultValue?: MultipleStringSelection;
|
|
11
|
+
onChange?: (value: MultipleStringSelection) => void;
|
|
12
|
+
}>;
|
|
13
|
+
export declare function toAriaSelection(value: string | null | MultipleStringSelection | undefined): "all" | Set<string> | undefined;
|
|
14
|
+
export declare function stringKey(value: Key): string;
|
|
15
|
+
export declare function optionalStringKey(value: Key | null): string | null;
|
|
16
|
+
export declare function singleSelection(selection: Selection): string | null;
|
|
17
|
+
export declare function multipleSelection(selection: Selection): MultipleStringSelection;
|
|
18
|
+
export declare function stringKeys(values: Iterable<Key>): readonly string[];
|
|
19
|
+
export type NoSelectionProps = Readonly<{
|
|
20
|
+
selectionMode?: "none";
|
|
21
|
+
value?: never;
|
|
22
|
+
defaultValue?: never;
|
|
23
|
+
onChange?: never;
|
|
24
|
+
}>;
|
|
25
|
+
export type SingleSelectionProps = SingleStringSelectionProps & Readonly<{
|
|
26
|
+
selectionMode: "single";
|
|
27
|
+
}>;
|
|
28
|
+
export type MultipleSelectionProps = MultipleStringSelectionProps & Readonly<{
|
|
29
|
+
selectionMode: "multiple";
|
|
30
|
+
}>;
|
|
31
|
+
type AnySelection = Readonly<{
|
|
32
|
+
selectionMode?: "none" | "single" | "multiple";
|
|
33
|
+
value?: string | null | MultipleStringSelection;
|
|
34
|
+
defaultValue?: string | null | MultipleStringSelection;
|
|
35
|
+
onChange?: ((value: string | null) => void) | ((value: MultipleStringSelection) => void);
|
|
36
|
+
}>;
|
|
37
|
+
/** Translates one string-valued selection contract into React Aria collection props. */
|
|
38
|
+
export declare function ariaSelection(properties: AnySelection, fallbackMode: "none" | "single" | "multiple"): {
|
|
39
|
+
onSelectionChange?: ((selection: Selection) => void) | undefined;
|
|
40
|
+
defaultSelectedKeys?: "all" | Set<string> | undefined;
|
|
41
|
+
selectedKeys?: "all" | Set<string> | undefined;
|
|
42
|
+
selectionMode: "none" | "multiple" | "single";
|
|
43
|
+
};
|
|
44
|
+
export {};
|
|
@@ -26,3 +26,19 @@ export function multipleSelection(selection) {
|
|
|
26
26
|
export function stringKeys(values) {
|
|
27
27
|
return [...values].map(stringKey);
|
|
28
28
|
}
|
|
29
|
+
/** Translates one string-valued selection contract into React Aria collection props. */
|
|
30
|
+
export function ariaSelection(properties, fallbackMode) {
|
|
31
|
+
const mode = properties.selectionMode ?? fallbackMode;
|
|
32
|
+
const selectedKeys = toAriaSelection(properties.value);
|
|
33
|
+
const defaultSelectedKeys = toAriaSelection(properties.defaultValue);
|
|
34
|
+
const onChange = properties.onChange;
|
|
35
|
+
const onSelectionChange = onChange === undefined || mode === "none"
|
|
36
|
+
? undefined
|
|
37
|
+
: (selection) => onChange(mode === "multiple" ? multipleSelection(selection) : singleSelection(selection));
|
|
38
|
+
return {
|
|
39
|
+
selectionMode: mode,
|
|
40
|
+
...(selectedKeys !== undefined ? { selectedKeys } : {}),
|
|
41
|
+
...(defaultSelectedKeys !== undefined ? { defaultSelectedKeys } : {}),
|
|
42
|
+
...(onSelectionChange !== undefined ? { onSelectionChange } : {})
|
|
43
|
+
};
|
|
44
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ElementType, ReactElement } from "react";
|
|
2
|
+
import { type SurfaceInteraction, type SurfaceOwnProps } from "../surface/surface.js";
|
|
3
|
+
export type SurfaceRenderProps = SurfaceOwnProps & Readonly<{
|
|
4
|
+
interaction?: SurfaceInteraction;
|
|
5
|
+
}>;
|
|
6
|
+
/**
|
|
7
|
+
* Lets a React Aria component render its own DOM element as a Surface. React
|
|
8
|
+
* Aria keeps behavior, semantics, and state; the Surface owns every paint.
|
|
9
|
+
*/
|
|
10
|
+
export declare function surfaceRender<State>(as: ElementType, derive: (state: State) => SurfaceRenderProps): (native: object, state: State) => ReactElement;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { SurfaceView } from "../surface/surface.js";
|
|
3
|
+
/**
|
|
4
|
+
* Lets a React Aria component render its own DOM element as a Surface. React
|
|
5
|
+
* Aria keeps behavior, semantics, and state; the Surface owns every paint.
|
|
6
|
+
*/
|
|
7
|
+
export function surfaceRender(as, derive) {
|
|
8
|
+
return (native, state) => {
|
|
9
|
+
const { ref, ...properties } = native;
|
|
10
|
+
return _jsx(SurfaceView, { ...properties, ...derive(state), as: as, ref: ref });
|
|
11
|
+
};
|
|
12
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { CSSProperties, ReactNode } from "react";
|
|
2
|
+
import type { TextFieldProps } from "react-aria-components";
|
|
3
|
+
import type { RadiusProps } from "../foundation/radius.js";
|
|
4
|
+
import type { MaterialOverrides } from "../surface/material-options.js";
|
|
5
|
+
import type { Color } from "../foundation/color.js";
|
|
6
|
+
import type { ControlMetrics, ControlOverrides, ControlProps, FieldProps } from "./control.js";
|
|
7
|
+
/** Shared contract for native text-entry fields. */
|
|
8
|
+
export interface TextControlProps extends Omit<TextFieldProps, ControlOverrides>, ControlProps, FieldProps, RadiusProps, MaterialOverrides {
|
|
9
|
+
readonly placeholder?: string;
|
|
10
|
+
readonly readOnly?: boolean;
|
|
11
|
+
}
|
|
12
|
+
type FieldState = Readonly<{
|
|
13
|
+
isFocused: boolean;
|
|
14
|
+
isHovered: boolean;
|
|
15
|
+
isInvalid: boolean;
|
|
16
|
+
isDisabled?: boolean;
|
|
17
|
+
}>;
|
|
18
|
+
/**
|
|
19
|
+
* The recessed well that holds typed content. Native text elements cannot host
|
|
20
|
+
* Surface layers, so the well wraps the element that React Aria renders.
|
|
21
|
+
*/
|
|
22
|
+
export declare function TextWell({ children, color, material, metrics, state, style }: Readonly<{
|
|
23
|
+
children: ReactNode;
|
|
24
|
+
color: Color;
|
|
25
|
+
material: MaterialOverrides["material"];
|
|
26
|
+
metrics: ControlMetrics;
|
|
27
|
+
state: FieldState;
|
|
28
|
+
style?: CSSProperties;
|
|
29
|
+
}>): import("react").JSX.Element;
|
|
30
|
+
/** Layout of the native element inside its well. */
|
|
31
|
+
export declare function nativeTextStyle(metrics: ControlMetrics, multiline: boolean): CSSProperties;
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { SurfaceView } from "../surface/surface.js";
|
|
3
|
+
/**
|
|
4
|
+
* The recessed well that holds typed content. Native text elements cannot host
|
|
5
|
+
* Surface layers, so the well wraps the element that React Aria renders.
|
|
6
|
+
*/
|
|
7
|
+
export function TextWell({ children, color, material, metrics, state, style }) {
|
|
8
|
+
return _jsx(SurfaceView, { as: "span", color: color, depth: "recessed", material: material, radius: metrics.radius, interaction: { hovered: state.isHovered, focusVisible: state.isFocused, invalid: state.isInvalid }, style: { display: "grid", minWidth: 0, ...style }, children: children });
|
|
9
|
+
}
|
|
10
|
+
/** Layout of the native element inside its well. */
|
|
11
|
+
export function nativeTextStyle(metrics, multiline) {
|
|
12
|
+
return {
|
|
13
|
+
appearance: "none",
|
|
14
|
+
boxSizing: "border-box",
|
|
15
|
+
width: "100%",
|
|
16
|
+
minWidth: 0,
|
|
17
|
+
height: multiline ? "auto" : metrics.height,
|
|
18
|
+
minHeight: metrics.height,
|
|
19
|
+
paddingBlock: multiline ? Math.max(6, metrics.spacing / 2) : 0,
|
|
20
|
+
paddingInline: metrics.inset,
|
|
21
|
+
border: 0,
|
|
22
|
+
borderRadius: "inherit",
|
|
23
|
+
outline: "none",
|
|
24
|
+
background: "transparent",
|
|
25
|
+
color: "inherit",
|
|
26
|
+
caretColor: "currentColor",
|
|
27
|
+
font: "inherit",
|
|
28
|
+
lineHeight: 1.45,
|
|
29
|
+
resize: multiline ? "vertical" : undefined
|
|
30
|
+
};
|
|
31
|
+
}
|