@phreshos/react-ui 0.1.28 → 0.1.30

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/dist/window.js ADDED
@@ -0,0 +1,136 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { createContext, forwardRef, useContext } from "react";
3
+ import { useResolvedAppearance } from "./appearance-context.js";
4
+ import { Button } from "./button.js";
5
+ import { transitionTiming } from "./motion-style.js";
6
+ import { scale } from "./scale.js";
7
+ import { Surface } from "./surface.js";
8
+ const HeaderContext = createContext(null);
9
+ function useHeader() {
10
+ const value = useContext(HeaderContext);
11
+ if (value === null)
12
+ throw new Error("Window.Header parts require Window.Header");
13
+ return value;
14
+ }
15
+ const WindowRoot = forwardRef(function WindowRoot({ children, style, ...properties }, ref) {
16
+ return _jsx(Surface, { ...properties, ref: ref, style: {
17
+ display: "flex",
18
+ flexDirection: "column",
19
+ minWidth: 0,
20
+ minHeight: 0,
21
+ ...style
22
+ }, children: children });
23
+ });
24
+ const WindowContent = forwardRef(function WindowContent({ style, ...properties }, ref) {
25
+ return _jsx("div", { ...properties, ref: ref, style: {
26
+ position: "relative",
27
+ flex: "1 1 auto",
28
+ minWidth: 0,
29
+ minHeight: 0,
30
+ ...style
31
+ } });
32
+ });
33
+ /** The composable top region of a window; its enclosing Surface owns the material. */
34
+ const HeaderRoot = forwardRef(function HeaderRoot({ active = true, children, onPointerDown, style, ...properties }, ref) {
35
+ const resolved = useResolvedAppearance();
36
+ const spacing = resolved.appearance.spacing;
37
+ const state = {
38
+ active,
39
+ foreground: resolved.colors.foreground,
40
+ iconRadius: scale(resolved.appearance.radius, "xsmall"),
41
+ spacing,
42
+ transition: transitionTiming(resolved.transaction, resolved.preferences.animations)
43
+ };
44
+ return _jsx(HeaderContext.Provider, { value: state, children: _jsx("div", { ...properties, ref: ref, onPointerDown: onPointerDown, style: {
45
+ boxSizing: "border-box",
46
+ display: "flex",
47
+ alignItems: "center",
48
+ gap: spacing,
49
+ minWidth: 0,
50
+ height: 16 + spacing * 2,
51
+ paddingInline: spacing,
52
+ flexShrink: 0,
53
+ userSelect: "none",
54
+ touchAction: onPointerDown ? "none" : undefined,
55
+ cursor: onPointerDown ? "grab" : undefined,
56
+ ...style
57
+ }, children: children }) });
58
+ });
59
+ /** The icon and truncating title share the window's active treatment. */
60
+ const WindowIdentity = forwardRef(function WindowIdentity({ icon, title, style, ...properties }, ref) {
61
+ const { active, iconRadius, spacing, transition } = useHeader();
62
+ return _jsxs("div", { ...properties, ref: ref, style: {
63
+ ...transition,
64
+ transitionProperty: "opacity",
65
+ display: "flex",
66
+ alignItems: "center",
67
+ gap: spacing,
68
+ flex: "0 1 auto",
69
+ minWidth: 0,
70
+ opacity: active ? 1 : 0.6,
71
+ ...style
72
+ }, children: [icon && _jsx("img", { src: icon, alt: "", draggable: false, style: {
73
+ width: 16,
74
+ height: 16,
75
+ flexShrink: 0,
76
+ borderRadius: iconRadius,
77
+ objectFit: "contain"
78
+ } }), title != null && _jsx("span", { style: {
79
+ minWidth: 0,
80
+ overflow: "hidden",
81
+ textOverflow: "ellipsis",
82
+ whiteSpace: "nowrap",
83
+ fontSize: "0.8125em",
84
+ fontWeight: 500
85
+ }, children: title })] });
86
+ });
87
+ /** Optional flexible space for application-owned content. */
88
+ const WindowCenter = forwardRef(function WindowCenter({ onDoubleClick, onPointerDown, style, ...properties }, ref) {
89
+ useHeader();
90
+ return _jsx("div", { ...properties, ref: ref, onDoubleClick: event => { event.stopPropagation(); onDoubleClick?.(event); }, onPointerDown: event => { event.stopPropagation(); onPointerDown?.(event); }, style: { display: "flex", alignItems: "center", flex: "1 1 auto", minWidth: 0, ...style } });
91
+ });
92
+ /** End-aligned controls that do not begin a header drag or double-click action. */
93
+ const WindowActions = forwardRef(function WindowActions({ onDoubleClick, onPointerDown, style, ...properties }, ref) {
94
+ const { spacing } = useHeader();
95
+ return _jsx("div", { ...properties, ref: ref, onDoubleClick: event => { event.stopPropagation(); onDoubleClick?.(event); }, onPointerDown: event => { event.stopPropagation(); onPointerDown?.(event); }, style: {
96
+ display: "flex",
97
+ alignItems: "center",
98
+ gap: Math.max(4, scale(spacing, "xsmall")),
99
+ flexShrink: 0,
100
+ marginInlineStart: "auto",
101
+ ...style
102
+ } });
103
+ });
104
+ /** A compact header action; extra actions use the same treatment as the standard controls. */
105
+ const WindowAction = forwardRef(function WindowAction({ style, ...properties }, ref) {
106
+ const { foreground } = useHeader();
107
+ return _jsx(Button, { ...properties, ref: ref, size: "xsmall", style: { color: foreground, ...style } });
108
+ });
109
+ const WindowMinimize = forwardRef(function WindowMinimize({ "aria-label": label = "Minimize", preventFocusOnPress = true, ...properties }, ref) {
110
+ return _jsx(WindowAction, { ...properties, ref: ref, "aria-label": label, preventFocusOnPress: preventFocusOnPress, children: _jsx(ControlIcon, { children: _jsx("path", { d: "M1.5 7.5h7" }) }) });
111
+ });
112
+ const WindowMaximize = forwardRef(function WindowMaximize({ "aria-label": label, maximized = false, ...properties }, ref) {
113
+ return _jsx(WindowAction, { ...properties, ref: ref, "aria-label": label ?? (maximized ? "Restore" : "Maximize"), children: _jsx(ControlIcon, { children: maximized
114
+ ? _jsx("path", { d: "M1 4h5v5H1zM4 1h5v5H6.5", strokeWidth: "1.3", strokeLinejoin: "round" })
115
+ : _jsx("path", { d: "M1.5 1.5h7v7h-7z", strokeWidth: "1.3", strokeLinejoin: "round" }) }) });
116
+ });
117
+ const WindowClose = forwardRef(function WindowClose({ "aria-label": label = "Close", preventFocusOnPress = true, ...properties }, ref) {
118
+ return _jsx(WindowAction, { ...properties, ref: ref, "aria-label": label, color: "danger:base", preventFocusOnPress: preventFocusOnPress, children: _jsx(ControlIcon, { children: _jsx("path", { d: "M1.5 1.5 8.5 8.5M8.5 1.5 1.5 8.5" }) }) });
119
+ });
120
+ function ControlIcon({ children }) {
121
+ return _jsx("svg", { "aria-hidden": "true", width: "10", height: "10", viewBox: "0 0 10 10", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", children: children });
122
+ }
123
+ const Header = Object.assign(HeaderRoot, {
124
+ Identity: WindowIdentity,
125
+ Center: WindowCenter,
126
+ Actions: WindowActions,
127
+ Action: WindowAction,
128
+ Minimize: WindowMinimize,
129
+ Maximize: WindowMaximize,
130
+ Close: WindowClose
131
+ });
132
+ /** One Surface with a ready-to-use header-and-content composition. */
133
+ export const Window = Object.assign(WindowRoot, {
134
+ Header,
135
+ Content: WindowContent
136
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phreshos/react-ui",
3
- "version": "0.1.28",
3
+ "version": "0.1.30",
4
4
  "description": "React components for coherent PhreshOS Program interfaces.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -56,7 +56,7 @@
56
56
  },
57
57
  "dependencies": {
58
58
  "@base-ui/react": "^1.7.0",
59
- "@phreshos/core": "^0.1.53",
59
+ "@phreshos/core": "^0.1.55",
60
60
  "colorjs.io": "^0.7.1",
61
61
  "motion": "^13.2.0",
62
62
  "react-aria-components": "^1.20.0"