@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.
Files changed (201) hide show
  1. package/README.md +147 -167
  2. package/dist/accordion.d.ts +7 -6
  3. package/dist/accordion.js +5 -5
  4. package/dist/alert-dialog.js +3 -1
  5. package/dist/alert.d.ts +17 -0
  6. package/dist/alert.js +30 -0
  7. package/dist/app-layout.d.ts +13 -0
  8. package/dist/app-layout.js +84 -0
  9. package/dist/button.d.ts +12 -24
  10. package/dist/button.js +34 -39
  11. package/dist/calendar-layout.d.ts +9 -5
  12. package/dist/calendar-layout.js +67 -78
  13. package/dist/calendar-trigger.d.ts +4 -4
  14. package/dist/calendar-trigger.js +7 -29
  15. package/dist/calendar.d.ts +2 -2
  16. package/dist/calendar.js +6 -5
  17. package/dist/checkbox.d.ts +4 -4
  18. package/dist/checkbox.js +16 -6
  19. package/dist/color-area.d.ts +20 -0
  20. package/dist/color-area.js +30 -0
  21. package/dist/color-field.d.ts +17 -0
  22. package/dist/color-field.js +17 -0
  23. package/dist/color-picker.d.ts +24 -0
  24. package/dist/color-picker.js +30 -0
  25. package/dist/color-slider.d.ts +19 -0
  26. package/dist/color-slider.js +29 -0
  27. package/dist/color-swatch-picker.d.ts +23 -0
  28. package/dist/color-swatch-picker.js +36 -0
  29. package/dist/color-swatch.d.ts +18 -0
  30. package/dist/color-swatch.js +20 -0
  31. package/dist/combo-box.d.ts +18 -10
  32. package/dist/combo-box.js +43 -58
  33. package/dist/context-menu.d.ts +14 -10
  34. package/dist/context-menu.js +7 -6
  35. package/dist/control/color-thumb.d.ts +13 -0
  36. package/dist/control/color-thumb.js +33 -0
  37. package/dist/control/color-value.d.ts +6 -0
  38. package/dist/control/color-value.js +7 -0
  39. package/dist/control/control.d.ts +60 -0
  40. package/dist/control/control.js +71 -0
  41. package/dist/control/field-button.d.ts +13 -0
  42. package/dist/control/field-button.js +28 -0
  43. package/dist/control/field.d.ts +20 -0
  44. package/dist/control/field.js +34 -0
  45. package/dist/control/icon.d.ts +11 -0
  46. package/dist/control/icon.js +8 -0
  47. package/dist/control/item.d.ts +34 -0
  48. package/dist/control/item.js +53 -0
  49. package/dist/control/open-state.d.ts +25 -0
  50. package/dist/control/open-state.js +8 -0
  51. package/dist/control/selection-track.d.ts +39 -0
  52. package/dist/control/selection-track.js +122 -0
  53. package/dist/control/selection.d.ts +44 -0
  54. package/dist/{selection.js → control/selection.js} +16 -0
  55. package/dist/control/surface-render.d.ts +10 -0
  56. package/dist/control/surface-render.js +12 -0
  57. package/dist/control/text-control.d.ts +32 -0
  58. package/dist/control/text-control.js +31 -0
  59. package/dist/control/toggle.d.ts +32 -0
  60. package/dist/control/toggle.js +80 -0
  61. package/dist/date-control.d.ts +9 -9
  62. package/dist/date-control.js +31 -34
  63. package/dist/date-field.d.ts +7 -6
  64. package/dist/date-field.js +8 -6
  65. package/dist/date-picker.d.ts +13 -6
  66. package/dist/date-picker.js +9 -6
  67. package/dist/date-range-picker.d.ts +15 -6
  68. package/dist/date-range-picker.js +12 -9
  69. package/dist/dialog.d.ts +22 -8
  70. package/dist/dialog.js +37 -28
  71. package/dist/disclosure.d.ts +8 -7
  72. package/dist/disclosure.js +31 -52
  73. package/dist/drop-zone.d.ts +18 -0
  74. package/dist/drop-zone.js +32 -0
  75. package/dist/dropdown-menu.d.ts +7 -4
  76. package/dist/dropdown-menu.js +5 -4
  77. package/dist/fieldset.d.ts +13 -0
  78. package/dist/fieldset.js +26 -0
  79. package/dist/file-trigger.d.ts +13 -0
  80. package/dist/file-trigger.js +6 -0
  81. package/dist/flex.d.ts +1 -1
  82. package/dist/flex.js +5 -4
  83. package/dist/foundation/appearance.d.ts +83 -0
  84. package/dist/foundation/appearance.js +38 -0
  85. package/dist/{aria-direction.js → foundation/aria-direction.js} +3 -1
  86. package/dist/foundation/color.d.ts +61 -0
  87. package/dist/foundation/color.js +247 -0
  88. package/dist/{layout.d.ts → foundation/layout.d.ts} +6 -4
  89. package/dist/{layout.js → foundation/layout.js} +7 -5
  90. package/dist/foundation/motion-style.d.ts +9 -0
  91. package/dist/foundation/motion-style.js +50 -0
  92. package/dist/foundation/preferences.d.ts +15 -0
  93. package/dist/{ui-provider.d.ts → foundation/provider.d.ts} +3 -5
  94. package/dist/{ui-provider.js → foundation/provider.js} +14 -26
  95. package/dist/{radius.d.ts → foundation/radius.d.ts} +6 -3
  96. package/dist/foundation/radius.js +11 -0
  97. package/dist/foundation/spacing.d.ts +11 -0
  98. package/dist/foundation/spacing.js +4 -0
  99. package/dist/foundation/visual.d.ts +42 -0
  100. package/dist/{appearance-context.js → foundation/visual.js} +41 -27
  101. package/dist/grid.d.ts +1 -1
  102. package/dist/grid.js +5 -4
  103. package/dist/icons/main.d.ts +5 -3
  104. package/dist/icons/main.js +5 -3
  105. package/dist/input.d.ts +2 -2
  106. package/dist/input.js +9 -7
  107. package/dist/list-box.d.ts +24 -19
  108. package/dist/list-box.js +52 -109
  109. package/dist/main.d.ts +27 -16
  110. package/dist/main.js +22 -9
  111. package/dist/menu.d.ts +28 -32
  112. package/dist/menu.js +47 -93
  113. package/dist/number-field.d.ts +17 -0
  114. package/dist/number-field.js +28 -0
  115. package/dist/panel.d.ts +10 -5
  116. package/dist/panel.js +33 -12
  117. package/dist/popover.d.ts +19 -5
  118. package/dist/popover.js +22 -15
  119. package/dist/progress-bar.d.ts +8 -10
  120. package/dist/progress-bar.js +18 -34
  121. package/dist/radio.d.ts +15 -12
  122. package/dist/radio.js +27 -37
  123. package/dist/range-calendar.d.ts +5 -3
  124. package/dist/range-calendar.js +8 -7
  125. package/dist/scroll-area.d.ts +2 -2
  126. package/dist/scroll-area.js +10 -9
  127. package/dist/segmented-control.d.ts +23 -0
  128. package/dist/segmented-control.js +38 -0
  129. package/dist/select.d.ts +40 -13
  130. package/dist/select.js +63 -18
  131. package/dist/slider.d.ts +7 -3
  132. package/dist/slider.js +51 -50
  133. package/dist/spinner.d.ts +5 -8
  134. package/dist/spinner.js +12 -27
  135. package/dist/surface/grain.d.ts +12 -0
  136. package/dist/surface/grain.js +65 -0
  137. package/dist/{material-options.d.ts → surface/material-options.d.ts} +1 -2
  138. package/dist/{material-options.js → surface/material-options.js} +2 -2
  139. package/dist/surface/paint-class.d.ts +6 -0
  140. package/dist/surface/paint-class.js +36 -0
  141. package/dist/{shadow-options.d.ts → surface/shadow-options.d.ts} +13 -1
  142. package/dist/{shadow-options.js → surface/shadow-options.js} +17 -2
  143. package/dist/surface/surface.d.ts +73 -0
  144. package/dist/surface/surface.js +230 -0
  145. package/dist/switch.d.ts +4 -5
  146. package/dist/switch.js +17 -8
  147. package/dist/table.d.ts +29 -32
  148. package/dist/table.js +68 -106
  149. package/dist/tabs.d.ts +16 -15
  150. package/dist/tabs.js +44 -86
  151. package/dist/textarea.d.ts +2 -2
  152. package/dist/textarea.js +10 -14
  153. package/dist/time-field.d.ts +6 -6
  154. package/dist/time-field.js +8 -6
  155. package/dist/toolbar.d.ts +6 -4
  156. package/dist/toolbar.js +16 -15
  157. package/dist/tooltip.d.ts +13 -4
  158. package/dist/tooltip.js +17 -15
  159. package/dist/tree.d.ts +22 -27
  160. package/dist/tree.js +54 -99
  161. package/dist/window.d.ts +2 -2
  162. package/dist/window.js +18 -20
  163. package/package.json +3 -3
  164. package/dist/appearance-context.d.ts +0 -54
  165. package/dist/appearance.d.ts +0 -11
  166. package/dist/appearance.js +0 -11
  167. package/dist/color.d.ts +0 -69
  168. package/dist/color.js +0 -192
  169. package/dist/control-surface.d.ts +0 -20
  170. package/dist/control-surface.js +0 -11
  171. package/dist/control.d.ts +0 -70
  172. package/dist/control.js +0 -105
  173. package/dist/field-style.d.ts +0 -3
  174. package/dist/field-style.js +0 -12
  175. package/dist/material-paint.d.ts +0 -13
  176. package/dist/material-paint.js +0 -119
  177. package/dist/motion-style.d.ts +0 -13
  178. package/dist/motion-style.js +0 -75
  179. package/dist/preferences.d.ts +0 -12
  180. package/dist/radius.js +0 -11
  181. package/dist/readiness.d.ts +0 -37
  182. package/dist/readiness.js +0 -134
  183. package/dist/selection.d.ts +0 -18
  184. package/dist/spacing.d.ts +0 -8
  185. package/dist/spacing.js +0 -8
  186. package/dist/surface-edge.d.ts +0 -11
  187. package/dist/surface-edge.js +0 -55
  188. package/dist/surface.d.ts +0 -27
  189. package/dist/surface.js +0 -92
  190. package/dist/text-control.d.ts +0 -10
  191. package/dist/text-control.js +0 -0
  192. package/dist/toggle-indicator.d.ts +0 -18
  193. package/dist/toggle-indicator.js +0 -49
  194. /package/dist/{aria-direction.d.ts → foundation/aria-direction.d.ts} +0 -0
  195. /package/dist/{direction.d.ts → foundation/direction.d.ts} +0 -0
  196. /package/dist/{direction.js → foundation/direction.js} +0 -0
  197. /package/dist/{overlay-placement.d.ts → foundation/overlay-placement.d.ts} +0 -0
  198. /package/dist/{overlay-placement.js → foundation/overlay-placement.js} +0 -0
  199. /package/dist/{preferences.js → foundation/preferences.js} +0 -0
  200. /package/dist/{scale.d.ts → foundation/scale.d.ts} +0 -0
  201. /package/dist/{scale.js → foundation/scale.js} +0 -0
@@ -0,0 +1,84 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createContext, forwardRef, useContext } from "react";
3
+ import { useControlMetrics } from "./control/control.js";
4
+ import { separatorColor } from "./control/field.js";
5
+ import { headerHeight } from "./foundation/layout.js";
6
+ import { scale } from "./foundation/scale.js";
7
+ import { ScrollArea } from "./scroll-area.js";
8
+ const AppLayoutContext = createContext(null);
9
+ /**
10
+ * The frame of a program's interface: a sidebar beside a header, the content,
11
+ * and an optional footer. It owns only the regions, their scrolling, and the
12
+ * hairlines between them; the program places its own components inside.
13
+ */
14
+ const AppLayoutRoot = forwardRef(function AppLayout({ children, sidebarWidth, style, ...properties }, ref) {
15
+ const metrics = useControlMetrics();
16
+ const { spacing } = metrics.visual;
17
+ return _jsx(AppLayoutContext.Provider, { value: { separator: separatorColor(metrics), spacing }, children: _jsx("div", { ...properties, ref: ref, style: {
18
+ display: "grid",
19
+ gridTemplateColumns: `${typeof sidebarWidth === "number" ? `${sidebarWidth}px` : sidebarWidth ?? `${spacing * 18}px`} minmax(0, 1fr)`,
20
+ gridTemplateRows: "auto minmax(0, 1fr) auto",
21
+ gridTemplateAreas: `"sidebar header" "sidebar content" "sidebar footer"`,
22
+ width: "100%",
23
+ height: "100%",
24
+ minWidth: 0,
25
+ minHeight: 0,
26
+ // The frame of a program: its text takes the Appearance text color.
27
+ color: metrics.visual.colors.foreground,
28
+ fontFamily: "inherit",
29
+ ...style
30
+ }, children: children }) });
31
+ });
32
+ /** The sidebar, such as a program's navigation. It scrolls on its own. */
33
+ const AppLayoutSidebar = forwardRef(function AppLayoutSidebar({ children, style, ...properties }, ref) {
34
+ const { separator, spacing } = useLayout();
35
+ return _jsx("aside", { ...properties, ref: ref, style: { gridArea: "sidebar", minHeight: 0, boxSizing: "border-box", borderInlineEnd: `1px solid ${separator}`, ...style }, children: _jsx(ScrollArea, { style: { height: "100%" }, children: _jsx("div", { style: { padding: scale(spacing, "small") }, children: children }) }) });
36
+ });
37
+ /** The header row above the content, as tall as a Window or Panel header. */
38
+ const AppLayoutHeader = forwardRef(function AppLayoutHeader({ style, ...properties }, ref) {
39
+ const { separator, spacing } = useLayout();
40
+ return _jsx("header", { ...properties, ref: ref, style: {
41
+ gridArea: "header",
42
+ display: "flex",
43
+ alignItems: "center",
44
+ gap: scale(spacing, "small"),
45
+ minWidth: 0,
46
+ minHeight: headerHeight(spacing),
47
+ paddingInline: spacing,
48
+ boxSizing: "border-box",
49
+ borderBlockEnd: `1px solid ${separator}`,
50
+ ...style
51
+ } });
52
+ });
53
+ /** The content. It scrolls on its own, padded by the Appearance spacing. */
54
+ const AppLayoutContent = forwardRef(function AppLayoutContent({ children, style, ...properties }, ref) {
55
+ const { spacing } = useLayout();
56
+ return _jsx("main", { ...properties, ref: ref, style: { gridArea: "content", minWidth: 0, minHeight: 0, ...style }, children: _jsx(ScrollArea, { style: { height: "100%" }, children: _jsx("div", { style: { padding: spacing }, children: children }) }) });
57
+ });
58
+ /** An optional row below the content, such as the actions that apply to it. */
59
+ const AppLayoutFooter = forwardRef(function AppLayoutFooter({ style, ...properties }, ref) {
60
+ const { separator, spacing } = useLayout();
61
+ return _jsx("footer", { ...properties, ref: ref, style: {
62
+ gridArea: "footer",
63
+ display: "flex",
64
+ alignItems: "center",
65
+ justifyContent: "flex-end",
66
+ gap: scale(spacing, "small"),
67
+ minWidth: 0,
68
+ padding: `${scale(spacing, "small")}px ${spacing}px`,
69
+ borderBlockStart: `1px solid ${separator}`,
70
+ ...style
71
+ } });
72
+ });
73
+ function useLayout() {
74
+ const context = useContext(AppLayoutContext);
75
+ if (context == null)
76
+ throw new Error("AppLayout parts must be used inside AppLayout");
77
+ return context;
78
+ }
79
+ export const AppLayout = Object.assign(AppLayoutRoot, {
80
+ Sidebar: AppLayoutSidebar,
81
+ Header: AppLayoutHeader,
82
+ Content: AppLayoutContent,
83
+ Footer: AppLayoutFooter
84
+ });
package/dist/button.d.ts CHANGED
@@ -1,32 +1,20 @@
1
- import type { CSSProperties, ReactNode } from "react";
2
- import type { ButtonProps as AriaButtonProps } from "react-aria-components";
3
- import type { ScaleLevel } from "./scale.js";
4
- import type { RadiusProps } from "./radius.js";
5
- import { type ControlColor } from "./control.js";
6
- import type { MaterialOverrides } from "./material-options.js";
7
- import type { ShadowOverrides } from "./shadow-options.js";
8
- type NativeButtonProps = Omit<AriaButtonProps, "children" | "className" | "color" | "isDisabled" | "isPending" | "onClick" | "onPress" | "style">;
9
- /** A semantic color from Appearance; omission uses `default:base`. */
10
- export type ButtonColor = ControlColor;
11
- /** Properties accepted by the shared interactive button. */
12
- export interface ButtonProps extends NativeButtonProps, RadiusProps, MaterialOverrides, ShadowOverrides {
13
- /** Visible Button content. */
1
+ import type { ReactNode } from "react";
2
+ import { type ButtonProps as AriaButtonProps } from "react-aria-components";
3
+ import { type ControlProps } from "./control/control.js";
4
+ import type { Color } from "./foundation/color.js";
5
+ import type { RadiusProps } from "./foundation/radius.js";
6
+ import type { MaterialOverrides } from "./surface/material-options.js";
7
+ import type { ShadowOverrides } from "./surface/shadow-options.js";
8
+ type NativeButtonProps = Omit<AriaButtonProps, "children" | "className" | "color" | "isDisabled" | "isPending" | "onClick" | "render" | "style">;
9
+ /** A color from Appearance or CSS; omission keeps the Button neutral. */
10
+ export type ButtonColor = Color;
11
+ export interface ButtonProps extends NativeButtonProps, ControlProps, RadiusProps, MaterialOverrides, ShadowOverrides {
14
12
  readonly children?: ReactNode;
15
- /** Base color for the material. Omission keeps the Button neutral. */
16
- readonly color?: ButtonColor;
17
- /** Native class name applied without replacing the component contract. */
18
- readonly className?: string;
19
- /** Prevents focus and activation. */
20
- readonly disabled?: boolean;
21
13
  /** Prevents activation while keeping the Button focusable. */
22
14
  readonly pending?: boolean;
23
15
  /** Runs once for a normalized pointer, Enter, or Space activation. */
24
16
  readonly onPress?: () => void;
25
- /** Derives the Button's spacing from Appearance's concrete default. */
26
- readonly size?: ScaleLevel;
27
- /** Native styles applied after Button defaults. */
28
- readonly style?: CSSProperties;
29
17
  }
30
- /** An Appearance-aware action with normalized pointer and keyboard behavior. */
18
+ /** A raised Surface you act on. */
31
19
  export declare const Button: import("react").ForwardRefExoticComponent<ButtonProps & import("react").RefAttributes<HTMLButtonElement>>;
32
20
  export {};
package/dist/button.js CHANGED
@@ -1,58 +1,53 @@
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 { controlOpacity, useControlTheme } from "./control.js";
5
- import { SurfaceButton } from "./control-surface.js";
6
- /** An Appearance-aware action with normalized pointer and keyboard behavior. */
7
- export const Button = forwardRef(function Button({ children, color, disabled = false, pending = false, onPress, radius = "medium", size = "medium", style, material, shadow, type = "button", ...properties }, ref) {
8
- const theme = useControlTheme({ color, radius, size });
9
- return _jsx(AriaButton, { ...properties, ref: ref, type: type, isDisabled: disabled, isPending: pending, onPress: onPress, render: (native, state) => _jsx(SurfaceButton, { native: native, material: material, shadow: shadow, paint: buttonPaint(theme, !disabled && !pending, state.isHovered, state.isPressed) }), style: ({ isFocusVisible, isHovered, isPressed }) => buttonStyle({
10
- theme,
11
- disabled,
12
- isFocusVisible,
13
- isHovered,
14
- isPressed,
15
- pending,
16
- style
17
- }), children: children });
4
+ import { controlOpacity, transition, useControlMetrics } from "./control/control.js";
5
+ import { surfaceRender } from "./control/surface-render.js";
6
+ /** A raised Surface you act on. */
7
+ export const Button = forwardRef(function Button({ children, color = "default", disabled, pending = false, radius, size, style, className, material, shadow, type = "button", ...properties }, ref) {
8
+ const metrics = useControlMetrics(size, radius);
9
+ // Disabled state is read from React Aria, so a Button placed in a slot, such
10
+ // as a calendar's month buttons, follows the owner that disables it.
11
+ return _jsx(AriaButton, { ...properties, ref: ref, type: type, className: className, isDisabled: disabled, isPending: pending, render: surfaceRender("button", state => ({
12
+ color,
13
+ material,
14
+ shadow,
15
+ radius: metrics.radius,
16
+ interaction: {
17
+ hovered: !state.isDisabled && !pending && state.isHovered,
18
+ pressed: !state.isDisabled && !pending && state.isPressed,
19
+ focusVisible: state.isFocusVisible,
20
+ disabled: state.isDisabled
21
+ }
22
+ })), style: state => buttonStyle(metrics, !state.isDisabled && !pending && state.isPressed, state.isDisabled, pending, style), children: children });
18
23
  });
19
- function buttonStyle({ theme, disabled, isFocusVisible, isHovered, isPressed, pending, style }) {
20
- const { spacing, focusColor } = theme;
21
- const interactive = !disabled && !pending;
22
- const paint = buttonPaint(theme, interactive, isHovered, isPressed);
24
+ function buttonStyle(metrics, pressed, disabled, pending, style) {
23
25
  return {
24
- ...theme.transition,
26
+ ...transition(metrics.visual, "box-shadow, color, outline-color, opacity, scale"),
25
27
  appearance: "none",
26
28
  boxSizing: "border-box",
27
- display: "inline-grid",
28
- gridAutoFlow: "column",
29
- gridAutoColumns: "max-content",
30
- placeItems: "center",
29
+ display: "inline-flex",
30
+ alignItems: "center",
31
31
  justifyContent: "center",
32
+ gap: metrics.gap,
32
33
  flexShrink: 0,
33
34
  minWidth: 0,
34
- height: theme.height,
35
+ height: metrics.height,
35
36
  paddingBlock: 0,
36
- paddingInline: Math.max(8, spacing),
37
- gap: theme.gap,
38
- border: "none",
39
- borderRadius: theme.radius,
40
- outline: isFocusVisible ? `1px solid ${focusColor}` : "none",
41
- outlineOffset: 1,
42
- ...paint,
43
- opacity: disabled ? controlOpacity.disabled : pending ? controlOpacity.pending : 1,
44
- cursor: disabled ? "not-allowed" : pending ? "progress" : "pointer",
37
+ paddingInline: metrics.inset,
38
+ border: 0,
39
+ background: "none",
45
40
  font: "inherit",
46
- fontSize: theme.fontSize,
41
+ fontSize: metrics.fontSize,
42
+ fontWeight: 500,
47
43
  lineHeight: 1,
48
- textAlign: "center",
44
+ whiteSpace: "nowrap",
49
45
  textDecoration: "none",
50
46
  userSelect: "none",
51
47
  WebkitTapHighlightColor: "transparent",
48
+ cursor: disabled ? "not-allowed" : pending ? "progress" : "pointer",
49
+ scale: pressed ? "0.97" : "1",
50
+ ...(pending ? { opacity: controlOpacity.pending } : {}),
52
51
  ...style
53
52
  };
54
53
  }
55
- function buttonPaint(theme, interactive, hovered, pressed) {
56
- const paints = theme.paints.palette;
57
- return interactive && pressed ? paints.pressed : interactive && hovered ? paints.hover : paints.rest;
58
- }
@@ -1,8 +1,12 @@
1
- import type { CSSProperties } from "react";
2
- import { type ControlProps, type ControlTheme } from "./control.js";
1
+ import { type CSSProperties } from "react";
2
+ import { type ControlMetrics } from "./control/control.js";
3
+ import { type Color } from "./foundation/color.js";
4
+ import type { ScaleLevel } from "./foundation/scale.js";
3
5
  /** Shared month layout used by both single-date and range calendar roots. */
4
- export declare function CalendarLayout({ color, range, size, theme }: Pick<ControlProps, "color" | "size"> & Readonly<{
6
+ export declare function CalendarLayout({ color, metrics, range, size }: Readonly<{
7
+ color: Color;
8
+ metrics: ControlMetrics;
5
9
  range?: boolean;
6
- theme: ControlTheme;
10
+ size?: ScaleLevel;
7
11
  }>): import("react").JSX.Element;
8
- export declare function calendarRootStyle(theme: ControlTheme, disabled?: boolean, style?: CSSProperties): CSSProperties;
12
+ export declare function calendarRootStyle(metrics: ControlMetrics, style?: CSSProperties): CSSProperties;
@@ -1,103 +1,92 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { CalendarCell, CalendarGrid, CalendarGridBody, CalendarGridHeader, CalendarHeaderCell, CalendarHeading } from "react-aria-components";
2
+ import { useContext } from "react";
3
+ import { isSameDay } from "@internationalized/date";
4
+ import { CalendarCell, CalendarGrid, CalendarGridBody, CalendarGridHeader, CalendarHeaderCell, CalendarHeading, CalendarStateContext, RangeCalendarStateContext } from "react-aria-components";
3
5
  import { Button } from "./button.js";
4
- import { resolveColorLevel, solidColors } from "./color.js";
5
- import { controlFontWeight, controlOpacity } from "./control.js";
6
- import { useDirection } from "./direction.js";
6
+ import { controlFontWeight, controlOpacity, transition } from "./control/control.js";
7
+ import { selectionLevel } from "./control/item.js";
8
+ import { colorLevel, colorOpacity, readableColor, resolveColor } from "./foundation/color.js";
9
+ import { useDirection } from "./foundation/direction.js";
10
+ import { dimmedClass, surfacePaint } from "./surface/surface.js";
11
+ import { ChevronLeft, ChevronRight } from "lucide-react";
12
+ import { iconProps } from "./control/icon.js";
7
13
  /** Shared month layout used by both single-date and range calendar roots. */
8
- export function CalendarLayout({ color, range = false, size, theme }) {
14
+ export function CalendarLayout({ color, metrics, range = false, size }) {
9
15
  const direction = useDirection();
10
- return _jsxs(_Fragment, { children: [_jsxs("header", { style: { display: "grid", gridTemplateColumns: "auto 1fr auto", alignItems: "center", gap: theme.gap }, children: [_jsx(Button, { slot: "previous", color: color, size: size, "aria-label": "Previous month", style: navigationStyle(theme), children: _jsx(Chevron, { direction: direction === "rtl" ? "next" : "previous" }) }), _jsx(CalendarHeading, { style: {
11
- margin: 0,
12
- textAlign: "center",
13
- fontFamily: "inherit",
14
- fontSize: "inherit",
15
- fontStyle: "inherit",
16
- lineHeight: "inherit",
17
- fontWeight: controlFontWeight
18
- } }), _jsx(Button, { slot: "next", color: color, size: size, "aria-label": "Next month", style: navigationStyle(theme), children: _jsx(Chevron, { direction: direction === "rtl" ? "previous" : "next" }) })] }), _jsxs(CalendarGrid, { style: {
19
- width: "max-content",
20
- margin: 0,
21
- tableLayout: "fixed",
22
- border: 0,
23
- borderRadius: 0,
24
- borderCollapse: "separate",
25
- borderSpacing: Math.max(1, theme.gap / 4),
26
- background: "transparent"
27
- }, children: [_jsx(CalendarGridHeader, { children: day => _jsx(CalendarHeaderCell, { style: {
28
- height: theme.height * 0.72,
29
- padding: 0,
30
- border: 0,
31
- background: "transparent",
32
- textAlign: "center",
33
- fontFamily: "inherit",
34
- fontSize: "inherit",
35
- fontStyle: "inherit",
36
- lineHeight: "inherit",
37
- fontWeight: controlFontWeight,
38
- opacity: controlOpacity.secondary
39
- }, children: day }) }), _jsx(CalendarGridBody, { children: date => _jsx(CalendarCell, { date: date, style: state => calendarCellStyle(theme, state, range) }) })] })] });
16
+ const cell = metrics.height;
17
+ const single = useContext(CalendarStateContext);
18
+ const ranged = useContext(RangeCalendarStateContext);
19
+ return _jsxs(_Fragment, { children: [_jsxs("header", { style: { display: "grid", gridTemplateColumns: "auto 1fr auto", alignItems: "center", gap: metrics.gap }, children: [_jsx(Button, { slot: "previous", size: size, "aria-label": "Previous month", style: { width: metrics.height, paddingInline: 0 }, children: _jsx(Chevron, { direction: direction === "rtl" ? "next" : "previous" }) }), _jsx(CalendarHeading, { style: { margin: 0, textAlign: "center", fontFamily: "inherit", fontSize: "inherit", fontStyle: "inherit", lineHeight: "inherit", fontWeight: controlFontWeight } }), _jsx(Button, { slot: "next", size: size, "aria-label": "Next month", style: { width: metrics.height, paddingInline: 0 }, children: _jsx(Chevron, { direction: direction === "rtl" ? "previous" : "next" }) })] }), _jsxs(CalendarGrid, { style: { width: "max-content", margin: 0, borderCollapse: "separate", borderSpacing: 2, background: "transparent" }, children: [_jsx(CalendarGridHeader, { children: day => _jsx(CalendarHeaderCell, { style: { height: cell * 0.72, padding: 0, textAlign: "center", fontFamily: "inherit", fontSize: "inherit", fontStyle: "inherit", lineHeight: "inherit", fontWeight: controlFontWeight, opacity: controlOpacity.secondary }, children: day }) }), _jsx(CalendarGridBody, { children: date => _jsx(CalendarCell, { date: date, className: state => dimmedClass(state.isDisabled || state.isUnavailable, state.defaultClassName) ?? "", style: state => cellStyle(metrics, color, state, daySelection(state, ranged ?? single), range) }) })] })] });
40
20
  }
41
- export function calendarRootStyle(theme, disabled = false, style) {
21
+ export function calendarRootStyle(metrics, style) {
42
22
  return {
43
23
  ...style,
44
24
  display: "grid",
45
25
  width: "max-content",
46
26
  maxWidth: "100%",
47
- gap: theme.gap,
48
- padding: theme.spacing,
27
+ gap: metrics.gap,
28
+ padding: metrics.spacing,
49
29
  fontFamily: "inherit",
50
- fontSize: theme.fontSize,
51
- lineHeight: 1.5,
52
- opacity: disabled ? controlOpacity.disabled : 1
30
+ fontSize: metrics.fontSize,
31
+ lineHeight: 1.45
53
32
  };
54
33
  }
55
- function navigationStyle(theme) {
56
- return {
57
- width: theme.height,
58
- paddingInline: 0
59
- };
34
+ /**
35
+ * Whether a day shows as chosen. React Aria reports no chosen day while the
36
+ * whole calendar is disabled, but a disabled calendar still holds its value,
37
+ * so the value is shown from the calendar state itself.
38
+ */
39
+ function daySelection(state, calendar) {
40
+ if (calendar == null || !calendar.isDisabled)
41
+ return { selected: state.isSelected, start: state.isSelectionStart, end: state.isSelectionEnd };
42
+ const shown = !state.isUnavailable && !calendar.isInvalid(state.date);
43
+ if ("highlightedRange" in calendar) {
44
+ const range = calendar.highlightedRange;
45
+ const selected = shown && range != null && state.date.compare(range.start) >= 0 && state.date.compare(range.end) <= 0;
46
+ return { selected, start: selected && isSameDay(state.date, range.start), end: selected && isSameDay(state.date, range.end) };
47
+ }
48
+ const values = [calendar.value].flat();
49
+ const selected = shown && values.some(value => value != null && isSameDay(state.date, value));
50
+ return { selected, start: selected, end: selected };
60
51
  }
61
- function calendarCellStyle(theme, state, range) {
62
- const rangeInterior = range && state.isSelected && !state.isSelectionStart && !state.isSelectionEnd
63
- ? rangeInteriorPaint(theme)
64
- : null;
65
- const paint = state.isSelected
66
- ? rangeInterior ?? theme.paints.palette.pressed
67
- : state.isPressed
68
- ? theme.paints.subtle.pressed
69
- : state.isHovered || state.isFocused
70
- ? theme.paints.subtle.hover
71
- : null;
52
+ /**
53
+ * A chosen day is the calendar's one decision, so it takes the full color;
54
+ * the days inside a range take the selection level; every other day only veils.
55
+ */
56
+ function cellStyle(metrics, color, state, selection, range) {
57
+ const { visual } = metrics;
58
+ const { colors } = visual;
59
+ const base = resolveColor(color, colors);
60
+ const endpoint = selection.selected && (!range || selection.start || selection.end);
61
+ const fill = endpoint
62
+ ? base
63
+ : selection.selected
64
+ ? colorLevel(base, selectionLevel, colors)
65
+ : "transparent";
66
+ const paint = surfacePaint(visual, fill, "flat", "none", false, {
67
+ hovered: state.isHovered || state.isFocused,
68
+ pressed: state.isPressed,
69
+ disabled: state.isDisabled || state.isUnavailable
70
+ });
72
71
  return {
73
- ...theme.transition,
72
+ ...transition(visual, "background-color, color, outline-color"),
74
73
  display: "grid",
75
74
  placeItems: "center",
76
75
  boxSizing: "border-box",
77
- width: theme.height,
78
- height: theme.height,
79
- borderRadius: theme.radius,
80
- outline: state.isFocusVisible ? `1px solid ${theme.focusColor}` : "none",
81
- outlineOffset: -1,
82
- background: paint?.background ?? "transparent",
83
- color: paint?.color ?? "inherit",
84
- opacity: state.isDisabled || state.isUnavailable
85
- ? controlOpacity.disabled
86
- : state.isOutsideMonth ? controlOpacity.secondary : 1,
76
+ width: metrics.height,
77
+ height: metrics.height,
78
+ borderRadius: metrics.radius,
79
+ outline: `3px solid ${state.isFocusVisible ? colorOpacity(colors.primary, 0.34) : "transparent"}`,
80
+ outlineOffset: 1,
81
+ background: paint.fill,
82
+ color: endpoint ? readableColor(base, colors) : "inherit",
83
+ fontWeight: state.isToday ? controlFontWeight : undefined,
84
+ opacity: state.isOutsideMonth ? controlOpacity.secondary : undefined,
87
85
  textDecoration: state.isUnavailable ? "line-through" : "none",
88
86
  cursor: state.isDisabled || state.isUnavailable ? "not-allowed" : "pointer",
89
87
  fontVariantNumeric: "tabular-nums"
90
88
  };
91
89
  }
92
- function rangeInteriorPaint(theme) {
93
- // Range interiors are the same Appearance color at its defined lighter
94
- // treatment; endpoints retain the stronger selected control paint.
95
- const background = resolveColorLevel(theme.tint, "soft");
96
- return {
97
- background,
98
- color: solidColors(background, theme.background, theme.foreground).rest.color
99
- };
100
- }
101
90
  function Chevron({ direction }) {
102
- return _jsx("svg", { "aria-hidden": "true", width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: _jsx("path", { d: direction === "previous" ? "m7.5 2-4 4 4 4" : "m4.5 2 4 4-4 4" }) });
91
+ return direction === "previous" ? _jsx(ChevronLeft, { ...iconProps(14) }) : _jsx(ChevronRight, { ...iconProps(14) });
103
92
  }
@@ -1,5 +1,5 @@
1
- import type { ControlTheme } from "./control.js";
2
- /** Calendar trigger shared by date picker fields. */
3
- export declare function CalendarTrigger({ theme }: Readonly<{
4
- theme: ControlTheme;
1
+ import type { ControlMetrics } from "./control/control.js";
2
+ /** The calendar button at the end of a date picker well. */
3
+ export declare function CalendarTrigger({ metrics }: Readonly<{
4
+ metrics: ControlMetrics;
5
5
  }>): import("react").JSX.Element;
@@ -1,30 +1,8 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Button as AriaButton } from "react-aria-components";
3
- /** Calendar trigger shared by date picker fields. */
4
- export function CalendarTrigger({ theme }) {
5
- const inset = Math.max(8, theme.spacing) - Math.max(4, theme.spacing / 2);
6
- return _jsx(AriaButton, { "data-date-control-end": "", style: state => ({
7
- ...theme.transition,
8
- appearance: "none",
9
- display: "grid",
10
- placeItems: "center",
11
- alignSelf: "stretch",
12
- flex: "0 0 auto",
13
- width: theme.height - Math.max(4, theme.spacing / 2),
14
- height: "auto",
15
- marginBlock: inset,
16
- marginInlineEnd: -Math.max(4, theme.spacing / 2),
17
- padding: 0,
18
- border: 0,
19
- borderRadius: Math.max(2, theme.spacing / 3),
20
- outline: state.isFocusVisible ? `1px solid ${theme.focusColor}` : "none",
21
- background: state.isPressed
22
- ? theme.paints.subtle.pressed.background
23
- : state.isHovered ? theme.paints.subtle.hover.background : "transparent",
24
- color: "inherit",
25
- cursor: state.isDisabled ? "not-allowed" : "pointer"
26
- }), children: _jsx(CalendarIcon, {}) });
27
- }
28
- function CalendarIcon() {
29
- return _jsxs("svg", { "aria-hidden": "true", width: "15", height: "15", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.35", children: [_jsx("rect", { x: "2.25", y: "3.25", width: "11.5", height: "10.5", rx: "2" }), _jsx("path", { d: "M5 1.75v3M11 1.75v3M2.5 6.5h11" })] });
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Calendar as CalendarIcon } from "lucide-react";
3
+ import { FieldButton } from "./control/field-button.js";
4
+ import { iconProps } from "./control/icon.js";
5
+ /** The calendar button at the end of a date picker well. */
6
+ export function CalendarTrigger({ metrics }) {
7
+ return _jsx(FieldButton, { "data-date-control-end": "", metrics: metrics, style: { marginInlineEnd: -Math.max(4, metrics.inset - 4) }, children: _jsx(CalendarIcon, { ...iconProps(16) }) });
30
8
  }
@@ -1,7 +1,7 @@
1
1
  import type { CalendarDate } from "@internationalized/date";
2
2
  import type { CalendarProps as AriaCalendarProps } from "react-aria-components";
3
- import { type ControlOverrides, type ControlProps } from "./control.js";
4
- import type { RadiusProps } from "./radius.js";
3
+ import { type ControlOverrides, type ControlProps } from "./control/control.js";
4
+ import type { RadiusProps } from "./foundation/radius.js";
5
5
  type CalendarOverrides = ControlOverrides | "children" | "isReadOnly" | "isInvalid" | "value" | "defaultValue" | "onChange" | "minValue" | "maxValue" | "isDateUnavailable" | "selectionMode" | "visibleDuration" | "createCalendar" | "errorMessage" | "validationState";
6
6
  export interface CalendarProps extends Omit<AriaCalendarProps<CalendarDate>, CalendarOverrides>, ControlProps, RadiusProps {
7
7
  readonly value?: CalendarDate | null;
package/dist/calendar.js CHANGED
@@ -1,13 +1,14 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { forwardRef } from "react";
3
3
  import { Calendar as AriaCalendar } from "react-aria-components";
4
- import { AriaDirectionBoundary } from "./aria-direction.js";
4
+ import { AriaDirectionBoundary } from "./foundation/aria-direction.js";
5
5
  import { CalendarLayout, calendarRootStyle } from "./calendar-layout.js";
6
- import { useControlTheme } from "./control.js";
7
- import { resolveDirection, useDirection } from "./direction.js";
6
+ import { useControlMetrics } from "./control/control.js";
7
+ import { resolveDirection, useDirection } from "./foundation/direction.js";
8
+ import { dimmedClass } from "./surface/surface.js";
8
9
  /** A locale-aware, keyboard-navigable month view for selecting one date. */
9
10
  export const Calendar = forwardRef(function Calendar({ disabled, readOnly, invalid, size, color, radius, style, className, isDateUnavailable, ...properties }, ref) {
10
- const theme = useControlTheme({ size, color, radius });
11
+ const metrics = useControlMetrics(size, radius);
11
12
  const direction = resolveDirection(properties.dir, useDirection());
12
- return _jsx(AriaDirectionBoundary, { direction: direction, children: _jsx(AriaCalendar, { ...properties, ref: ref, dir: direction, className: className, isDisabled: disabled, isReadOnly: readOnly, isInvalid: invalid, isDateUnavailable: isDateUnavailable == null ? undefined : date => isDateUnavailable(date), style: calendarRootStyle(theme, disabled, style), children: _jsx(CalendarLayout, { color: color, size: size, theme: theme }) }) });
13
+ return _jsx(AriaDirectionBoundary, { direction: direction, children: _jsx(AriaCalendar, { ...properties, ref: ref, dir: direction, className: dimmedClass(disabled ?? false, className), isDisabled: disabled, isReadOnly: readOnly, isInvalid: invalid, isDateUnavailable: isDateUnavailable == null ? undefined : date => isDateUnavailable(date), style: calendarRootStyle(metrics, style), children: _jsx(CalendarLayout, { color: color ?? "primary", size: size, metrics: metrics }) }) });
13
14
  });
@@ -1,8 +1,8 @@
1
1
  import type { CheckboxFieldProps } from "react-aria-components";
2
- import type { ControlOverrides, ControlProps, FieldProps } from "./control.js";
3
- import type { MaterialOverrides } from "./material-options.js";
4
- import type { ShadowOverrides } from "./shadow-options.js";
5
- export interface CheckboxProps extends Omit<CheckboxFieldProps, ControlOverrides | "isReadOnly" | "isSelected" | "defaultSelected" | "isIndeterminate">, ControlProps, FieldProps, MaterialOverrides, ShadowOverrides {
2
+ import { type ControlOverrides, type ControlProps, type FieldProps } from "./control/control.js";
3
+ import type { RadiusProps } from "./foundation/radius.js";
4
+ import type { MaterialOverrides } from "./surface/material-options.js";
5
+ export interface CheckboxProps extends Omit<CheckboxFieldProps, ControlOverrides | "isSelected" | "defaultSelected" | "isIndeterminate">, ControlProps, FieldProps, MaterialOverrides, RadiusProps {
6
6
  readonly checked?: boolean;
7
7
  readonly defaultChecked?: boolean;
8
8
  readonly indeterminate?: boolean;
package/dist/checkbox.js CHANGED
@@ -1,10 +1,20 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { forwardRef } from "react";
3
- import { CheckboxField, CheckboxButton } from "react-aria-components";
4
- import { FieldFeedback, fieldStyle, useControlTheme } from "./control.js";
5
- import { ToggleIndicator, toggleStyle } from "./toggle-indicator.js";
3
+ import { CheckboxButton, CheckboxField } 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 { dimmedClass } from "./surface/surface.js";
6
8
  /** An independent boolean field with optional mixed-state presentation. */
7
- export const Checkbox = forwardRef(function Checkbox({ label, description, errorMessage, disabled, required, invalid, readOnly, checked, defaultChecked, indeterminate, size, color, style, material, shadow, ...properties }, ref) {
8
- const theme = useControlTheme({ size, color });
9
- return _jsxs(CheckboxField, { ...properties, ref: ref, isDisabled: disabled, isRequired: required, isInvalid: invalid, isReadOnly: readOnly, isSelected: checked, defaultSelected: defaultChecked, isIndeterminate: indeterminate, style: state => fieldStyle(theme, state.isDisabled, style), children: [_jsx(CheckboxButton, { style: state => toggleStyle(theme, state.isDisabled, state.isReadOnly), children: state => _jsxs(_Fragment, { children: [_jsx(ToggleIndicator, { kind: "checkbox", material: material, shadow: shadow, theme: theme, selected: state.isSelected, indeterminate: state.isIndeterminate, focused: state.isFocusVisible, invalid: state.isInvalid, hovered: !state.isDisabled && !state.isReadOnly && state.isHovered, pressed: !state.isDisabled && !state.isReadOnly && state.isPressed }), label] }) }), _jsx(FieldFeedback, { theme: theme, description: description, errorMessage: errorMessage })] });
9
+ export const Checkbox = forwardRef(function Checkbox({ label, description, errorMessage, disabled, required, invalid, readOnly, className, checked, defaultChecked, indeterminate, size, color = "primary", style, material, radius, ...properties }, ref) {
10
+ const metrics = useControlMetrics(size);
11
+ return _jsxs(CheckboxField, { ...properties, ref: ref, isDisabled: disabled, isRequired: required, isInvalid: invalid, isReadOnly: readOnly, isSelected: checked, defaultSelected: defaultChecked, isIndeterminate: indeterminate, className: state => dimmedClass(state.isDisabled, className ?? state.defaultClassName) ?? "", style: fieldStyle(metrics, style), children: [_jsx(CheckboxButton, { style: state => toggleRowStyle(metrics, state.isDisabled, state.isReadOnly), children: state => _jsxs(_Fragment, { children: [_jsx(ToggleIndicator, { kind: "checkbox", color: color, material: material, metrics: metrics, radius: radius, state: {
12
+ selected: state.isSelected,
13
+ indeterminate: state.isIndeterminate,
14
+ hovered: !state.isReadOnly && state.isHovered,
15
+ pressed: !state.isReadOnly && state.isPressed,
16
+ focusVisible: state.isFocusVisible,
17
+ invalid: state.isInvalid,
18
+ disabled: state.isDisabled
19
+ } }), label] }) }), _jsx(FieldFeedback, { metrics: metrics, description: description, errorMessage: errorMessage })] });
10
20
  });
@@ -0,0 +1,20 @@
1
+ import type { CSSProperties } from "react";
2
+ import type { ColorAreaProps as AriaColorAreaProps } from "react-aria-components";
3
+ import { type RadiusProps } from "./foundation/radius.js";
4
+ import type { ScaleLevel } from "./foundation/scale.js";
5
+ export interface ColorAreaProps extends Omit<AriaColorAreaProps, "value" | "defaultValue" | "onChange" | "onChangeEnd" | "isDisabled" | "className" | "style" | "children">, RadiusProps {
6
+ readonly value?: string;
7
+ readonly defaultValue?: string;
8
+ readonly onChange?: (value: string) => void;
9
+ readonly onChangeEnd?: (value: string) => void;
10
+ readonly disabled?: boolean;
11
+ /** Sets the thumb and the default extent of the area. */
12
+ readonly size?: ScaleLevel;
13
+ readonly className?: string;
14
+ readonly style?: CSSProperties;
15
+ }
16
+ /**
17
+ * Two channels of a color, such as saturation and brightness, on a square
18
+ * painted with both ranges. Inside a ColorPicker it edits the picker's color.
19
+ */
20
+ export declare const ColorArea: import("react").ForwardRefExoticComponent<ColorAreaProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { ColorArea as AriaColorArea } from "react-aria-components";
4
+ import { colorEdge, ColorThumb } from "./control/color-thumb.js";
5
+ import { colorValue } from "./control/color-value.js";
6
+ import { useControlMetrics } from "./control/control.js";
7
+ import { AriaDirectionBoundary } from "./foundation/aria-direction.js";
8
+ import { resolveDirection, useDirection } from "./foundation/direction.js";
9
+ import { resolveRadius } from "./foundation/radius.js";
10
+ import { dimmedClass } from "./surface/surface.js";
11
+ /**
12
+ * Two channels of a color, such as saturation and brightness, on a square
13
+ * painted with both ranges. Inside a ColorPicker it edits the picker's color.
14
+ */
15
+ export const ColorArea = forwardRef(function ColorArea({ value, defaultValue, onChange, onChangeEnd, disabled, size, radius, className, style, ...properties }, ref) {
16
+ const metrics = useControlMetrics(size);
17
+ const direction = resolveDirection(properties.dir, useDirection());
18
+ return _jsx(AriaDirectionBoundary, { direction: direction, children: _jsx(AriaColorArea, { ...properties, ref: ref, dir: direction, ...(value !== undefined ? { value } : {}), ...(defaultValue !== undefined ? { defaultValue } : {}), ...(onChange !== undefined ? { onChange: (color) => onChange(colorValue(color)) } : {}), ...(onChangeEnd !== undefined ? { onChangeEnd: (color) => onChangeEnd(colorValue(color)) } : {}), isDisabled: disabled, className: dimmedClass(disabled ?? false, className), style: ({ defaultStyle }) => ({
19
+ ...defaultStyle,
20
+ position: "relative",
21
+ boxSizing: "border-box",
22
+ flexShrink: 0,
23
+ width: metrics.height * 6,
24
+ aspectRatio: "1",
25
+ // An area is a region, not a control: it keeps the Appearance radius.
26
+ borderRadius: resolveRadius(radius ?? "medium", metrics.visual.radius),
27
+ boxShadow: colorEdge(metrics),
28
+ ...style
29
+ }), children: _jsx(ColorThumb, { metrics: metrics }) }) });
30
+ });
@@ -0,0 +1,17 @@
1
+ import type { ColorFieldProps as AriaColorFieldProps } from "react-aria-components";
2
+ import { type ControlOverrides, type ControlProps, type FieldProps } from "./control/control.js";
3
+ import type { RadiusProps } from "./foundation/radius.js";
4
+ import type { MaterialOverrides } from "./surface/material-options.js";
5
+ export interface ColorFieldProps extends Omit<AriaColorFieldProps, ControlOverrides | "value" | "defaultValue" | "onChange" | "className" | "style">, ControlProps, FieldProps, RadiusProps, MaterialOverrides {
6
+ /** A hex color, or `null` while the field is empty. */
7
+ readonly value?: string | null;
8
+ readonly defaultValue?: string | null;
9
+ readonly onChange?: (value: string | null) => void;
10
+ readonly placeholder?: string;
11
+ readonly readOnly?: boolean;
12
+ }
13
+ /**
14
+ * A color typed as text: a hex value, or one channel when `channel` is set.
15
+ * Inside a ColorPicker it edits the picker's color.
16
+ */
17
+ export declare const ColorField: import("react").ForwardRefExoticComponent<ColorFieldProps & import("react").RefAttributes<HTMLInputElement>>;