@phreshos/react-ui 0.1.39 → 0.1.41

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 (47) hide show
  1. package/dist/alert.js +3 -4
  2. package/dist/app-layout.d.ts +2 -0
  3. package/dist/app-layout.js +54 -27
  4. package/dist/avatar.d.ts +23 -0
  5. package/dist/avatar.js +42 -0
  6. package/dist/badge.d.ts +20 -0
  7. package/dist/badge.js +31 -0
  8. package/dist/breadcrumbs.d.ts +20 -0
  9. package/dist/breadcrumbs.js +43 -0
  10. package/dist/control/control.d.ts +2 -0
  11. package/dist/control/control.js +4 -0
  12. package/dist/control/meaning.d.ts +5 -0
  13. package/dist/control/meaning.js +10 -0
  14. package/dist/dialog.js +2 -2
  15. package/dist/foundation/motion-style.d.ts +8 -0
  16. package/dist/foundation/motion-style.js +13 -0
  17. package/dist/link.d.ts +18 -0
  18. package/dist/link.js +32 -0
  19. package/dist/loading.d.ts +20 -0
  20. package/dist/loading.js +66 -0
  21. package/dist/main.d.ts +13 -1
  22. package/dist/main.js +12 -0
  23. package/dist/meter.d.ts +26 -0
  24. package/dist/meter.js +29 -0
  25. package/dist/progress-bar.d.ts +3 -0
  26. package/dist/progress-bar.js +7 -3
  27. package/dist/readiness.d.ts +46 -0
  28. package/dist/readiness.js +78 -0
  29. package/dist/search-field.d.ts +13 -0
  30. package/dist/search-field.js +27 -0
  31. package/dist/skeleton.d.ts +15 -0
  32. package/dist/skeleton.js +29 -0
  33. package/dist/spinner.d.ts +2 -0
  34. package/dist/spinner.js +5 -2
  35. package/dist/surface/grain.d.ts +9 -0
  36. package/dist/surface/grain.js +9 -0
  37. package/dist/surface/surface.d.ts +4 -0
  38. package/dist/surface/surface.js +12 -6
  39. package/dist/tag-group.d.ts +21 -0
  40. package/dist/tag-group.js +52 -0
  41. package/dist/toast.d.ts +32 -0
  42. package/dist/toast.js +62 -0
  43. package/dist/typography.d.ts +49 -0
  44. package/dist/typography.js +71 -0
  45. package/dist/window.d.ts +4 -1
  46. package/dist/window.js +2 -0
  47. package/package.json +1 -1
package/dist/toast.js ADDED
@@ -0,0 +1,62 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Text, UNSTABLE_Toast as AriaToast, UNSTABLE_ToastContent as AriaToastContent, UNSTABLE_ToastQueue as AriaToastQueue, UNSTABLE_ToastRegion as AriaToastRegion } from "react-aria-components";
3
+ import { X } from "lucide-react";
4
+ import { controlFontSizes, controlFontWeight, controlOpacity, useControlMetrics } from "./control/control.js";
5
+ import { FieldButton } from "./control/field-button.js";
6
+ import { iconProps } from "./control/icon.js";
7
+ import { meaningIcon } from "./control/meaning.js";
8
+ import { colorLevel, resolveColor } from "./foundation/color.js";
9
+ import MotionStyle, { overlayLayer, overlayTransition } from "./foundation/motion-style.js";
10
+ import { resolveRadius } from "./foundation/radius.js";
11
+ import { scale } from "./foundation/scale.js";
12
+ import { Surface } from "./surface/surface.js";
13
+ import { floatingShadow } from "./surface/shadow-options.js";
14
+ const queue = new AriaToastQueue({ maxVisibleToasts: 5 });
15
+ /**
16
+ * Shows a brief message that does not interrupt, such as "Saved". It appears
17
+ * in the ToastRegion and returns a key that closes it early.
18
+ */
19
+ export const toast = Object.freeze({
20
+ show(content, options = {}) {
21
+ return queue.add(content, options.timeout === undefined ? {} : { timeout: options.timeout });
22
+ },
23
+ close(key) {
24
+ queue.close(key);
25
+ }
26
+ });
27
+ /**
28
+ * Where Toasts appear: stacked at the end of the viewport bottom, above the
29
+ * interface, at the large spacing step from its edges. Render it once.
30
+ */
31
+ export function ToastRegion({ className, style }) {
32
+ const metrics = useControlMetrics();
33
+ const visual = metrics.visual;
34
+ const inset = scale(visual.spacing, "large");
35
+ return _jsxs(_Fragment, { children: [_jsx(MotionStyle, {}), _jsx(AriaToastRegion, { queue: queue, className: className, style: {
36
+ position: "fixed",
37
+ insetBlockEnd: inset,
38
+ insetInlineEnd: inset,
39
+ zIndex: overlayLayer,
40
+ display: "flex",
41
+ flexDirection: "column-reverse",
42
+ // Each Toast is as wide as its message, up to the width of a readable line.
43
+ alignItems: "end",
44
+ gap: metrics.gap,
45
+ maxWidth: `min(28em, calc(100vw - ${inset * 2}px))`,
46
+ outline: "none",
47
+ ...style
48
+ }, children: ({ toast: item }) => {
49
+ const color = item.content.color ?? "info";
50
+ const Icon = meaningIcon(color);
51
+ return _jsx(AriaToast, { toast: item, style: { outline: "none", ...overlayTransition(visual), animation: `phreshos-ui-overlay-enter var(--phreshos-ui-motion-duration) var(--phreshos-ui-motion-easing) both` }, children: _jsxs(Surface, { material: "full", shadow: floatingShadow(visual.shadow), radius: resolveRadius("medium", visual.radius), style: {
52
+ display: "grid",
53
+ gridTemplateColumns: "auto minmax(0, 1fr) auto",
54
+ alignItems: "start",
55
+ gap: metrics.gap * 2,
56
+ padding: metrics.spacing,
57
+ paddingInlineEnd: metrics.spacing / 2,
58
+ fontSize: controlFontSizes.medium,
59
+ lineHeight: 1.45
60
+ }, children: [_jsx("span", { style: { display: "grid", height: "1.45em", alignItems: "center", color: colorLevel(resolveColor(color, visual.colors), "strong", visual.colors) }, children: _jsx(Icon, { ...iconProps(Math.round(metrics.height / 2)) }) }), _jsxs(AriaToastContent, { style: { display: "grid", gap: 2, minWidth: 0 }, children: [_jsx(Text, { slot: "title", style: { fontWeight: controlFontWeight }, children: item.content.title }), item.content.description != null && _jsx(Text, { slot: "description", style: { opacity: controlOpacity.secondary }, children: item.content.description })] }), _jsx(FieldButton, { slot: "close", metrics: metrics, "aria-label": "Close", children: _jsx(X, { ...iconProps(Math.round(metrics.height / 2)) }) })] }) });
61
+ } })] });
62
+ }
@@ -0,0 +1,49 @@
1
+ import type { CSSProperties, ReactNode } from "react";
2
+ import { type ScaleLevel } from "./foundation/scale.js";
3
+ type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
4
+ export interface HeadingProps {
5
+ readonly children?: ReactNode;
6
+ /** The document level, from 1 to 6. */
7
+ readonly level?: HeadingLevel;
8
+ /** The visual size, when it should differ from the level's. */
9
+ readonly size?: ScaleLevel;
10
+ readonly id?: string;
11
+ readonly className?: string;
12
+ readonly style?: CSSProperties;
13
+ }
14
+ /** A heading sized relative to the text around it, so it fits any context. */
15
+ export declare const Heading: import("react").ForwardRefExoticComponent<HeadingProps & import("react").RefAttributes<HTMLHeadingElement>>;
16
+ export interface TextProps {
17
+ readonly children?: ReactNode;
18
+ /** `secondary` recedes to the strength of supporting text, like descriptions. */
19
+ readonly tone?: "default" | "secondary";
20
+ /** The control text scale; omitted, the text keeps the size around it. */
21
+ readonly size?: ScaleLevel;
22
+ /** A slot name when the text describes a field or item, such as `description`. */
23
+ readonly slot?: string;
24
+ readonly elementType?: string;
25
+ readonly id?: string;
26
+ readonly className?: string;
27
+ readonly style?: CSSProperties;
28
+ }
29
+ /** Running text in the tone and scale of the interface. */
30
+ export declare const Text: import("react").ForwardRefExoticComponent<TextProps & import("react").RefAttributes<HTMLElement>>;
31
+ export interface KbdProps {
32
+ readonly children?: ReactNode;
33
+ readonly className?: string;
34
+ readonly style?: CSSProperties;
35
+ }
36
+ /**
37
+ * A key to press, drawn as a small raised keycap. Its label takes the control
38
+ * text scale, and the cap is as tall as the line of text around it, so it
39
+ * never stretches the line.
40
+ */
41
+ export declare const Kbd: import("react").ForwardRefExoticComponent<KbdProps & import("react").RefAttributes<HTMLElement>>;
42
+ export interface CodeProps {
43
+ readonly children?: ReactNode;
44
+ readonly className?: string;
45
+ readonly style?: CSSProperties;
46
+ }
47
+ /** Code inside text, set in the system monospace font in a shallow recess. */
48
+ export declare const Code: import("react").ForwardRefExoticComponent<CodeProps & import("react").RefAttributes<HTMLElement>>;
49
+ export {};
@@ -0,0 +1,71 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { Heading as AriaHeading, Keyboard as AriaKeyboard, Text as AriaText } from "react-aria-components";
4
+ import { controlFontSizes, controlFontWeight, controlOpacity, useControlMetrics } from "./control/control.js";
5
+ import { scale, scaleMultiplier } from "./foundation/scale.js";
6
+ import { useVisual } from "./foundation/visual.js";
7
+ import { Surface } from "./surface/surface.js";
8
+ /** The size each heading level takes unless `size` says otherwise. */
9
+ const levelSizes = Object.freeze({ 1: "xlarge", 2: "large", 3: "medium", 4: "small", 5: "xsmall", 6: "xsmall" });
10
+ /**
11
+ * Headings grow by the same ladder Appearance values scale by, anchored at the
12
+ * large step: a medium heading is one and a half times its surrounding text,
13
+ * an xlarge heading twice.
14
+ */
15
+ const headingGrowth = scale(1, "large");
16
+ /** A heading sized relative to the text around it, so it fits any context. */
17
+ export const Heading = forwardRef(function Heading({ level = 2, size, style, ...properties }, ref) {
18
+ return _jsx(AriaHeading, { ...properties, ref: ref, level: level, style: {
19
+ margin: 0,
20
+ fontSize: `${scaleMultiplier(headingGrowth, size ?? levelSizes[level])}em`,
21
+ fontWeight: controlFontWeight,
22
+ lineHeight: 1.2,
23
+ textWrap: "balance",
24
+ ...style
25
+ } });
26
+ });
27
+ /** Running text in the tone and scale of the interface. */
28
+ export const Text = forwardRef(function Text({ tone = "default", size, style, ...properties }, ref) {
29
+ return _jsx(AriaText, { ...properties, ref: ref, style: {
30
+ fontSize: size === undefined ? undefined : controlFontSizes[size],
31
+ lineHeight: textLineHeight,
32
+ opacity: tone === "secondary" ? controlOpacity.secondary : undefined,
33
+ ...style
34
+ } });
35
+ });
36
+ /** Running text sets its lines at this height, relative to its size. */
37
+ const textLineHeight = 1.45;
38
+ /**
39
+ * A key to press, drawn as a small raised keycap. Its label takes the control
40
+ * text scale, and the cap is as tall as the line of text around it, so it
41
+ * never stretches the line.
42
+ */
43
+ export const Kbd = forwardRef(function Kbd({ children, className, style }, ref) {
44
+ const metrics = useControlMetrics("xsmall");
45
+ const label = Number.parseFloat(controlFontSizes.medium);
46
+ const cap = `${textLineHeight / label}em`;
47
+ return _jsx(AriaKeyboard, { ref: ref, className: className, style: { display: "inline-block", verticalAlign: "middle", lineHeight: 1 }, children: _jsx(Surface, { as: "span", radius: metrics.radius, shadow: false, style: {
48
+ display: "inline-flex",
49
+ alignItems: "center",
50
+ justifyContent: "center",
51
+ minWidth: cap,
52
+ height: cap,
53
+ paddingInline: metrics.gap,
54
+ boxSizing: "border-box",
55
+ fontSize: controlFontSizes.medium,
56
+ fontWeight: controlFontWeight,
57
+ fontVariantNumeric: "tabular-nums",
58
+ lineHeight: 1,
59
+ ...style
60
+ }, children: children }) });
61
+ });
62
+ /** Code inside text, set in the system monospace font in a shallow recess. */
63
+ export const Code = forwardRef(function Code({ children, className, style }, ref) {
64
+ const visual = useVisual();
65
+ return _jsx(Surface, { as: "code", ref: ref, className: className, color: "background", depth: "recessed", radius: scale(visual.radius, "small"), style: {
66
+ paddingInline: scale(visual.spacing, "xsmall"),
67
+ fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
68
+ fontSize: "0.9em",
69
+ ...style
70
+ }, children: children });
71
+ });
package/dist/window.d.ts CHANGED
@@ -3,7 +3,10 @@ import type { BeginWindowMoveGesture } from "@phreshos/core";
3
3
  import { type ButtonActionProps } from "./button.js";
4
4
  import { type Color } from "./foundation/color.js";
5
5
  import { type SurfaceProps } from "./surface/surface.js";
6
- /** The material shell that establishes the complete header-and-content layout. */
6
+ /**
7
+ * The material shell that establishes the complete header-and-content layout.
8
+ * The Window owns its shape: nothing inside is drawn past its edges or corners.
9
+ */
7
10
  export type WindowProps = SurfaceProps;
8
11
  /** The remaining window area. Its consumer owns content behavior, including overflow. */
9
12
  export type WindowContentProps = HTMLAttributes<HTMLDivElement>;
package/dist/window.js CHANGED
@@ -23,6 +23,8 @@ const WindowRoot = forwardRef(function WindowRoot({ children, style, ...properti
23
23
  flexDirection: "column",
24
24
  minWidth: 0,
25
25
  minHeight: 0,
26
+ // Clips to the rounded shape without becoming a scroll container.
27
+ overflow: "clip",
26
28
  ...style
27
29
  }, children: children });
28
30
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phreshos/react-ui",
3
- "version": "0.1.39",
3
+ "version": "0.1.41",
4
4
  "description": "React components for coherent PhreshOS Program interfaces.",
5
5
  "type": "module",
6
6
  "sideEffects": false,