@hanzo/ui 8.27.85 → 8.27.87
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/auth/session.cjs +47 -2
- package/dist/auth/session.d.ts +2 -0
- package/dist/auth/session.d.ts.map +1 -1
- package/dist/auth/session.js +45 -1
- package/dist/auth/session.js.map +1 -1
- package/dist/backends/gui/choice.cjs +4 -0
- package/dist/backends/gui/choice.d.ts +3 -0
- package/dist/backends/gui/choice.d.ts.map +1 -1
- package/dist/backends/gui/choice.js +3 -0
- package/dist/backends/gui/choice.js.map +1 -1
- package/dist/backends/gui/code-editor.cjs +13 -13
- package/dist/backends/gui/code-editor.d.ts +4 -4
- package/dist/backends/gui/code-editor.d.ts.map +1 -1
- package/dist/backends/gui/code-editor.js +14 -14
- package/dist/backends/gui/code-editor.js.map +1 -1
- package/dist/backends/gui/grip.cjs +128 -81
- package/dist/backends/gui/grip.d.ts +48 -25
- package/dist/backends/gui/grip.d.ts.map +1 -1
- package/dist/backends/gui/grip.js +129 -81
- package/dist/backends/gui/grip.js.map +1 -1
- package/dist/backends/gui/index.cjs +12 -7
- package/dist/backends/gui/index.d.ts +3 -1
- package/dist/backends/gui/index.d.ts.map +1 -1
- package/dist/backends/gui/index.js +3 -1
- package/dist/backends/gui/index.js.map +1 -1
- package/dist/backends/gui/json-tree.cjs +14 -16
- package/dist/backends/gui/json-tree.d.ts +3 -3
- package/dist/backends/gui/json-tree.d.ts.map +1 -1
- package/dist/backends/gui/json-tree.js +15 -17
- package/dist/backends/gui/json-tree.js.map +1 -1
- package/dist/backends/gui/span.cjs +54 -0
- package/dist/backends/gui/span.d.ts +15 -0
- package/dist/backends/gui/span.d.ts.map +1 -0
- package/dist/backends/gui/span.js +52 -0
- package/dist/backends/gui/span.js.map +1 -0
- package/dist/gallery.html +9 -4
- package/dist/index.cjs +8 -5
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.node.cjs +8 -5
- package/dist/index.node.js +1 -1
- package/dist/onboarding/Checkout.cjs +40 -23
- package/dist/onboarding/Checkout.d.ts +1 -0
- package/dist/onboarding/Checkout.d.ts.map +1 -1
- package/dist/onboarding/Checkout.js +44 -27
- package/dist/onboarding/Checkout.js.map +1 -1
- package/dist/onboarding/Onboarding.cjs +2 -3
- package/dist/onboarding/Onboarding.d.ts +3 -2
- package/dist/onboarding/Onboarding.d.ts.map +1 -1
- package/dist/onboarding/Onboarding.js +2 -3
- package/dist/onboarding/Onboarding.js.map +1 -1
- package/dist/onboarding/api.cjs +47 -5
- package/dist/onboarding/api.d.ts +2 -1
- package/dist/onboarding/api.d.ts.map +1 -1
- package/dist/onboarding/api.js +47 -6
- package/dist/onboarding/api.js.map +1 -1
- package/dist/onboarding/attempt.cjs +3 -3
- package/dist/onboarding/attempt.js +3 -3
- package/dist/onboarding/attempt.js.map +1 -1
- package/dist/onboarding/screens.cjs +1 -1
- package/dist/onboarding/screens.d.ts.map +1 -1
- package/dist/onboarding/screens.js +2 -2
- package/dist/onboarding/screens.js.map +1 -1
- package/dist/primitives/Grip.cjs +8 -0
- package/dist/primitives/Grip.d.ts +2 -0
- package/dist/primitives/Grip.d.ts.map +1 -0
- package/dist/primitives/Grip.js +5 -0
- package/dist/primitives/Grip.js.map +1 -0
- package/dist/primitives/useSpan.cjs +8 -0
- package/dist/primitives/useSpan.d.ts +2 -0
- package/dist/primitives/useSpan.d.ts.map +1 -0
- package/dist/primitives/useSpan.js +5 -0
- package/dist/primitives/useSpan.js.map +1 -0
- package/dist/styles.css +5 -0
- package/package.json +1 -1
|
@@ -34,99 +34,146 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
};
|
|
35
35
|
})();
|
|
36
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
-
exports.useGrip = useGrip;
|
|
38
37
|
exports.Grip = Grip;
|
|
39
38
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
40
39
|
/**
|
|
41
|
-
*
|
|
40
|
+
* Grip — a box's free edge, which is also how big the box is: a separator a
|
|
41
|
+
* person drags, or moves with the arrow keys, to size the box beside it. The one
|
|
42
|
+
* resizer: a sidebar, an aside, a split between two panes, and an editor's
|
|
43
|
+
* height all use it.
|
|
42
44
|
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
45
|
+
* side the edge the box is pinned to. `left` grows rightwards (a sidebar,
|
|
46
|
+
* the first pane of a split), `right` grows leftwards (an aside, a
|
|
47
|
+
* drawer), `top` grows downwards (an editor, a tree). One control,
|
|
48
|
+
* the arithmetic reflected.
|
|
49
|
+
* span the box's size now, px, for assistive tech; `floor` and `ceil`
|
|
50
|
+
* bound it.
|
|
51
|
+
* onSpan the size while it moves, at most once a frame.
|
|
52
|
+
* onKeep the size it settled on: a drag let go, a key, a double-click.
|
|
53
|
+
* onShut when given, a drag pulled well past the floor, or a key pressed at
|
|
54
|
+
* it, puts the box away (a sidebar snaps to its icons); absent, the
|
|
55
|
+
* floor holds.
|
|
56
|
+
* reset the size a double-click returns to; `onReset` instead hands the
|
|
57
|
+
* size back to the box (an editor that follows its text).
|
|
58
|
+
*
|
|
59
|
+
* Keys: the arrows step 8px (32px with Shift), Home and End go to the floor and
|
|
60
|
+
* the ceiling. Pointer events, so a mouse, a trackpad, a touchscreen and a pen
|
|
61
|
+
* are one path, with the pointer captured: a drag that outruns the handle keeps
|
|
62
|
+
* sizing. A drag and a key both start from the box as drawn, so the edge never
|
|
63
|
+
* jumps to the cursor and a box that follows its content steps from where it is.
|
|
64
|
+
*
|
|
65
|
+
* It sits inside the box, absolutely, on the free edge; the rest of its props
|
|
66
|
+
* place it elsewhere and win. The line is drawn only while a person reaches for
|
|
67
|
+
* it: under the pointer, while it moves, and for a keyboard's focus, which it
|
|
68
|
+
* draws instead of an outline.
|
|
69
|
+
*
|
|
70
|
+
* Moved here from @hanzo/build, where hanzo.ai's sidebar and asides used it.
|
|
48
71
|
*/
|
|
49
72
|
const gui_1 = require("@hanzo/gui");
|
|
50
|
-
const lucide_icons_2_1 = require("@hanzogui/lucide-icons-2");
|
|
51
73
|
const React = __importStar(require("react"));
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
/**
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
74
|
+
/** A key's step, px; with Shift, the long one. */
|
|
75
|
+
const STEP = 8;
|
|
76
|
+
const LONG = 32;
|
|
77
|
+
/** How far past the floor a drag is pulled before it shuts the box, px: a deliberate pull, not a twitch. */
|
|
78
|
+
const SLACK = 48;
|
|
79
|
+
/** The grab band's thickness, px; the line drawn inside it is 2. */
|
|
80
|
+
const BAND = 8;
|
|
81
|
+
function Grip({ side, span, floor, ceil, reset, onReset, onSpan, onKeep, onShut, label, ...rest }) {
|
|
82
|
+
const tall = side === 'top';
|
|
83
|
+
/** +1 when the pointer moving away from the pinned edge grows the box. */
|
|
84
|
+
const grows = side === 'right' ? -1 : 1;
|
|
85
|
+
// The pinned edge in client coordinates, taken as the drag begins.
|
|
86
|
+
const held = React.useRef(0);
|
|
87
|
+
// Whether a press holds the pointer and whether it has moved since, the size it
|
|
88
|
+
// last asked for, and the frame that will draw it. A press that never moves
|
|
89
|
+
// keeps nothing.
|
|
90
|
+
const drag = React.useRef('none');
|
|
91
|
+
const want = React.useRef(span);
|
|
92
|
+
const frame = React.useRef(0);
|
|
93
|
+
const [hovered, setHovered] = React.useState(false);
|
|
94
|
+
const [keyed, setKeyed] = React.useState(false);
|
|
95
|
+
const [moving, setMoving] = React.useState(false);
|
|
96
|
+
React.useEffect(() => () => cancelAnimationFrame(frame.current), []);
|
|
97
|
+
const clamp = (n) => Math.round(Math.min(ceil, Math.max(floor, n)));
|
|
98
|
+
const along = (e) => (tall ? e.clientY : e.clientX);
|
|
99
|
+
/** The box as drawn, read off the element the grip sits in. */
|
|
100
|
+
const drawn = (el) => {
|
|
101
|
+
const box = el?.parentElement?.getBoundingClientRect();
|
|
102
|
+
return box ? (tall ? box.height : box.width) : span;
|
|
103
|
+
};
|
|
104
|
+
const settle = (n) => {
|
|
105
|
+
onSpan(n);
|
|
106
|
+
onKeep?.(n);
|
|
107
|
+
};
|
|
108
|
+
const stop = () => {
|
|
109
|
+
drag.current = 'none';
|
|
110
|
+
cancelAnimationFrame(frame.current);
|
|
111
|
+
frame.current = 0;
|
|
112
|
+
setMoving(false);
|
|
113
|
+
};
|
|
114
|
+
const end = () => {
|
|
115
|
+
if (drag.current === 'none')
|
|
71
116
|
return;
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
117
|
+
const moved = drag.current === 'moved';
|
|
118
|
+
stop();
|
|
119
|
+
if (moved)
|
|
120
|
+
settle(want.current);
|
|
121
|
+
};
|
|
122
|
+
const wider = side === 'left' ? 'ArrowRight' : side === 'right' ? 'ArrowLeft' : 'ArrowDown';
|
|
123
|
+
const narrower = side === 'left' ? 'ArrowLeft' : side === 'right' ? 'ArrowRight' : 'ArrowUp';
|
|
124
|
+
const edge = tall
|
|
125
|
+
? { l: 0, r: 0, b: 0, height: BAND, justify: 'center' }
|
|
126
|
+
: { t: 0, b: 0, width: BAND, items: 'center', ...(side === 'left' ? { r: 0 } : { l: 0 }) };
|
|
127
|
+
return ((0, jsx_runtime_1.jsx)(gui_1.YStack, { role: "separator", "aria-orientation": tall ? 'horizontal' : 'vertical', "aria-label": label, "aria-valuenow": Math.round(span), "aria-valuemin": floor, "aria-valuemax": ceil, tabIndex: 0, "data-slot": "grip", "data-side": side, "data-moving": moving ? '' : undefined, position: "absolute", ...edge, z: 10, cursor: tall ? 'row-resize' : 'col-resize', outlineWidth: 0, focusVisibleStyle: { outlineWidth: 0 }, style: { touchAction: 'none' }, onPointerEnter: () => setHovered(true), onPointerLeave: () => setHovered(false),
|
|
128
|
+
// The line is the focus ring, drawn for a keyboard's focus and not a pointer's.
|
|
129
|
+
onFocus: (e) => setKeyed(e.currentTarget.matches(':focus-visible')), onBlur: () => setKeyed(false), onPointerDown: (e) => {
|
|
76
130
|
if (e.button !== 0)
|
|
77
131
|
return;
|
|
132
|
+
// No text selection starts under a drag.
|
|
78
133
|
e.preventDefault();
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
134
|
+
e.currentTarget.setPointerCapture?.(e.pointerId);
|
|
135
|
+
const now = drawn(e.currentTarget);
|
|
136
|
+
held.current = along(e) - grows * now;
|
|
137
|
+
want.current = clamp(now);
|
|
138
|
+
drag.current = 'held';
|
|
139
|
+
setMoving(true);
|
|
140
|
+
}, onPointerMove: (e) => {
|
|
141
|
+
if (drag.current === 'none')
|
|
86
142
|
return;
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
143
|
+
drag.current = 'moved';
|
|
144
|
+
const pulled = grows * (along(e) - held.current);
|
|
145
|
+
if (onShut && pulled < floor - SLACK) {
|
|
146
|
+
stop();
|
|
147
|
+
e.currentTarget.releasePointerCapture?.(e.pointerId);
|
|
148
|
+
onShut();
|
|
91
149
|
return;
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
const key = (e) => {
|
|
96
|
-
if (e.key !== 'ArrowUp' && e.key !== 'ArrowDown')
|
|
150
|
+
}
|
|
151
|
+
want.current = clamp(pulled);
|
|
152
|
+
if (frame.current)
|
|
97
153
|
return;
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
'aria-orientation': 'horizontal',
|
|
124
|
-
'aria-label': `Resize ${label}`,
|
|
125
|
-
'aria-valuemin': min,
|
|
126
|
-
// A drag has no ceiling; this stands in for "as tall as you like".
|
|
127
|
-
'aria-valuemax': CEILING,
|
|
128
|
-
'aria-valuenow': height ?? min,
|
|
129
|
-
'aria-valuetext': height === null ? 'Fits its content' : `${height} pixels`,
|
|
130
|
-
tabIndex: 0,
|
|
131
|
-
}, rounded: "$2", p: "$1", focusVisibleStyle: { bg: '$hover' }, children: (0, jsx_runtime_1.jsx)(lucide_icons_2_1.GripHorizontal, { size: 14, color: "$soft" }) }));
|
|
154
|
+
frame.current = requestAnimationFrame(() => {
|
|
155
|
+
frame.current = 0;
|
|
156
|
+
onSpan(want.current);
|
|
157
|
+
});
|
|
158
|
+
},
|
|
159
|
+
// A drag ends when the pointer is let go: lifted, or taken by the browser.
|
|
160
|
+
onPointerUp: end, onPointerCancel: end, onDoubleClick: () => (onReset ? onReset() : settle(clamp(reset ?? span))), onKeyDown: (e) => {
|
|
161
|
+
const step = e.shiftKey ? LONG : STEP;
|
|
162
|
+
const now = drawn(e.currentTarget);
|
|
163
|
+
const to = e.key === wider
|
|
164
|
+
? now + step
|
|
165
|
+
: e.key === narrower
|
|
166
|
+
? now - step
|
|
167
|
+
: e.key === 'Home'
|
|
168
|
+
? floor
|
|
169
|
+
: e.key === 'End'
|
|
170
|
+
? ceil
|
|
171
|
+
: null;
|
|
172
|
+
if (to === null)
|
|
173
|
+
return;
|
|
174
|
+
e.preventDefault?.();
|
|
175
|
+
if (onShut && to < floor)
|
|
176
|
+
return onShut();
|
|
177
|
+
settle(clamp(to));
|
|
178
|
+
}, ...rest, children: (0, jsx_runtime_1.jsx)(gui_1.YStack, { ...(tall ? { height: 2, width: '100%' } : { width: 2, height: '100%' }), rounded: 1, bg: keyed || moving ? '$outlineColor' : hovered ? '$rim' : 'transparent', pointerEvents: "none" }) }));
|
|
132
179
|
}
|
|
@@ -1,28 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grip — a box's free edge, which is also how big the box is: a separator a
|
|
3
|
+
* person drags, or moves with the arrow keys, to size the box beside it. The one
|
|
4
|
+
* resizer: a sidebar, an aside, a split between two panes, and an editor's
|
|
5
|
+
* height all use it.
|
|
6
|
+
*
|
|
7
|
+
* side the edge the box is pinned to. `left` grows rightwards (a sidebar,
|
|
8
|
+
* the first pane of a split), `right` grows leftwards (an aside, a
|
|
9
|
+
* drawer), `top` grows downwards (an editor, a tree). One control,
|
|
10
|
+
* the arithmetic reflected.
|
|
11
|
+
* span the box's size now, px, for assistive tech; `floor` and `ceil`
|
|
12
|
+
* bound it.
|
|
13
|
+
* onSpan the size while it moves, at most once a frame.
|
|
14
|
+
* onKeep the size it settled on: a drag let go, a key, a double-click.
|
|
15
|
+
* onShut when given, a drag pulled well past the floor, or a key pressed at
|
|
16
|
+
* it, puts the box away (a sidebar snaps to its icons); absent, the
|
|
17
|
+
* floor holds.
|
|
18
|
+
* reset the size a double-click returns to; `onReset` instead hands the
|
|
19
|
+
* size back to the box (an editor that follows its text).
|
|
20
|
+
*
|
|
21
|
+
* Keys: the arrows step 8px (32px with Shift), Home and End go to the floor and
|
|
22
|
+
* the ceiling. Pointer events, so a mouse, a trackpad, a touchscreen and a pen
|
|
23
|
+
* are one path, with the pointer captured: a drag that outruns the handle keeps
|
|
24
|
+
* sizing. A drag and a key both start from the box as drawn, so the edge never
|
|
25
|
+
* jumps to the cursor and a box that follows its content steps from where it is.
|
|
26
|
+
*
|
|
27
|
+
* It sits inside the box, absolutely, on the free edge; the rest of its props
|
|
28
|
+
* place it elsewhere and win. The line is drawn only while a person reaches for
|
|
29
|
+
* it: under the pointer, while it moves, and for a keyboard's focus, which it
|
|
30
|
+
* draws instead of an outline.
|
|
31
|
+
*
|
|
32
|
+
* Moved here from @hanzo/build, where hanzo.ai's sidebar and asides used it.
|
|
33
|
+
*/
|
|
34
|
+
import { type YStackProps } from '@hanzo/gui';
|
|
1
35
|
import * as React from 'react';
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
grip: React.RefObject<HTMLElement | null>;
|
|
15
|
-
knob: React.RefObject<HTMLElement | null>;
|
|
16
|
-
height: number | null;
|
|
17
|
-
};
|
|
18
|
-
/** The knob: a separator that names what it resizes and says how tall it is. */
|
|
19
|
-
export declare function Grip({ knob, name, label, min, height, }: {
|
|
20
|
-
knob: React.RefObject<HTMLElement | null>;
|
|
21
|
-
/** Its `data-slot`. */
|
|
22
|
-
name: string;
|
|
23
|
-
/** What it resizes, for "Resize <label>". */
|
|
36
|
+
export type GripSide = 'left' | 'right' | 'top';
|
|
37
|
+
export interface GripProps extends Omit<YStackProps, 'children'> {
|
|
38
|
+
side: GripSide;
|
|
39
|
+
span: number;
|
|
40
|
+
floor: number;
|
|
41
|
+
ceil: number;
|
|
42
|
+
reset?: number;
|
|
43
|
+
onReset?: () => void;
|
|
44
|
+
onSpan: (n: number) => void;
|
|
45
|
+
onKeep?: (n: number) => void;
|
|
46
|
+
onShut?: () => void;
|
|
47
|
+
/** The separator's accessible name: "Resize sidebar", "Resize Input". */
|
|
24
48
|
label: string;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}): React.JSX.Element;
|
|
49
|
+
}
|
|
50
|
+
export declare function Grip({ side, span, floor, ceil, reset, onReset, onSpan, onKeep, onShut, label, ...rest }: GripProps): React.JSX.Element;
|
|
28
51
|
//# sourceMappingURL=grip.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grip.d.ts","sourceRoot":"","sources":["../../../src/backends/gui/grip.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"grip.d.ts","sourceRoot":"","sources":["../../../src/backends/gui/grip.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,YAAY,CAAA;AACrD,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAY9B,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAA;AAE/C,MAAM,WAAW,SAAU,SAAQ,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC;IAC9D,IAAI,EAAE,QAAQ,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;IAC3B,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5B,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB,yEAAyE;IACzE,KAAK,EAAE,MAAM,CAAA;CACd;AAKD,wBAAgB,IAAI,CAAC,EACnB,IAAI,EACJ,IAAI,EACJ,KAAK,EACL,IAAI,EACJ,KAAK,EACL,OAAO,EACP,MAAM,EACN,MAAM,EACN,MAAM,EACN,KAAK,EACL,GAAG,IAAI,EACR,EAAE,SAAS,qBAmIX"}
|
|
@@ -1,96 +1,144 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Grip — a box's free edge, which is also how big the box is: a separator a
|
|
5
|
+
* person drags, or moves with the arrow keys, to size the box beside it. The one
|
|
6
|
+
* resizer: a sidebar, an aside, a split between two panes, and an editor's
|
|
7
|
+
* height all use it.
|
|
5
8
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
9
|
+
* side the edge the box is pinned to. `left` grows rightwards (a sidebar,
|
|
10
|
+
* the first pane of a split), `right` grows leftwards (an aside, a
|
|
11
|
+
* drawer), `top` grows downwards (an editor, a tree). One control,
|
|
12
|
+
* the arithmetic reflected.
|
|
13
|
+
* span the box's size now, px, for assistive tech; `floor` and `ceil`
|
|
14
|
+
* bound it.
|
|
15
|
+
* onSpan the size while it moves, at most once a frame.
|
|
16
|
+
* onKeep the size it settled on: a drag let go, a key, a double-click.
|
|
17
|
+
* onShut when given, a drag pulled well past the floor, or a key pressed at
|
|
18
|
+
* it, puts the box away (a sidebar snaps to its icons); absent, the
|
|
19
|
+
* floor holds.
|
|
20
|
+
* reset the size a double-click returns to; `onReset` instead hands the
|
|
21
|
+
* size back to the box (an editor that follows its text).
|
|
22
|
+
*
|
|
23
|
+
* Keys: the arrows step 8px (32px with Shift), Home and End go to the floor and
|
|
24
|
+
* the ceiling. Pointer events, so a mouse, a trackpad, a touchscreen and a pen
|
|
25
|
+
* are one path, with the pointer captured: a drag that outruns the handle keeps
|
|
26
|
+
* sizing. A drag and a key both start from the box as drawn, so the edge never
|
|
27
|
+
* jumps to the cursor and a box that follows its content steps from where it is.
|
|
28
|
+
*
|
|
29
|
+
* It sits inside the box, absolutely, on the free edge; the rest of its props
|
|
30
|
+
* place it elsewhere and win. The line is drawn only while a person reaches for
|
|
31
|
+
* it: under the pointer, while it moves, and for a keyboard's focus, which it
|
|
32
|
+
* draws instead of an outline.
|
|
33
|
+
*
|
|
34
|
+
* Moved here from @hanzo/build, where hanzo.ai's sidebar and asides used it.
|
|
11
35
|
*/
|
|
12
|
-
import {
|
|
13
|
-
import { GripHorizontal } from '@hanzogui/lucide-icons-2';
|
|
36
|
+
import { YStack } from '@hanzo/gui';
|
|
14
37
|
import * as React from 'react';
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
/**
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
38
|
+
/** A key's step, px; with Shift, the long one. */
|
|
39
|
+
const STEP = 8;
|
|
40
|
+
const LONG = 32;
|
|
41
|
+
/** How far past the floor a drag is pulled before it shuts the box, px: a deliberate pull, not a twitch. */
|
|
42
|
+
const SLACK = 48;
|
|
43
|
+
/** The grab band's thickness, px; the line drawn inside it is 2. */
|
|
44
|
+
const BAND = 8;
|
|
45
|
+
export function Grip({ side, span, floor, ceil, reset, onReset, onSpan, onKeep, onShut, label, ...rest }) {
|
|
46
|
+
const tall = side === 'top';
|
|
47
|
+
/** +1 when the pointer moving away from the pinned edge grows the box. */
|
|
48
|
+
const grows = side === 'right' ? -1 : 1;
|
|
49
|
+
// The pinned edge in client coordinates, taken as the drag begins.
|
|
50
|
+
const held = React.useRef(0);
|
|
51
|
+
// Whether a press holds the pointer and whether it has moved since, the size it
|
|
52
|
+
// last asked for, and the frame that will draw it. A press that never moves
|
|
53
|
+
// keeps nothing.
|
|
54
|
+
const drag = React.useRef('none');
|
|
55
|
+
const want = React.useRef(span);
|
|
56
|
+
const frame = React.useRef(0);
|
|
57
|
+
const [hovered, setHovered] = React.useState(false);
|
|
58
|
+
const [keyed, setKeyed] = React.useState(false);
|
|
59
|
+
const [moving, setMoving] = React.useState(false);
|
|
60
|
+
React.useEffect(() => () => cancelAnimationFrame(frame.current), []);
|
|
61
|
+
const clamp = (n) => Math.round(Math.min(ceil, Math.max(floor, n)));
|
|
62
|
+
const along = (e) => (tall ? e.clientY : e.clientX);
|
|
63
|
+
/** The box as drawn, read off the element the grip sits in. */
|
|
64
|
+
const drawn = (el) => {
|
|
65
|
+
const box = el?.parentElement?.getBoundingClientRect();
|
|
66
|
+
return box ? (tall ? box.height : box.width) : span;
|
|
67
|
+
};
|
|
68
|
+
const settle = (n) => {
|
|
69
|
+
onSpan(n);
|
|
70
|
+
onKeep?.(n);
|
|
71
|
+
};
|
|
72
|
+
const stop = () => {
|
|
73
|
+
drag.current = 'none';
|
|
74
|
+
cancelAnimationFrame(frame.current);
|
|
75
|
+
frame.current = 0;
|
|
76
|
+
setMoving(false);
|
|
77
|
+
};
|
|
78
|
+
const end = () => {
|
|
79
|
+
if (drag.current === 'none')
|
|
34
80
|
return;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
81
|
+
const moved = drag.current === 'moved';
|
|
82
|
+
stop();
|
|
83
|
+
if (moved)
|
|
84
|
+
settle(want.current);
|
|
85
|
+
};
|
|
86
|
+
const wider = side === 'left' ? 'ArrowRight' : side === 'right' ? 'ArrowLeft' : 'ArrowDown';
|
|
87
|
+
const narrower = side === 'left' ? 'ArrowLeft' : side === 'right' ? 'ArrowRight' : 'ArrowUp';
|
|
88
|
+
const edge = tall
|
|
89
|
+
? { l: 0, r: 0, b: 0, height: BAND, justify: 'center' }
|
|
90
|
+
: { t: 0, b: 0, width: BAND, items: 'center', ...(side === 'left' ? { r: 0 } : { l: 0 }) };
|
|
91
|
+
return (_jsx(YStack, { role: "separator", "aria-orientation": tall ? 'horizontal' : 'vertical', "aria-label": label, "aria-valuenow": Math.round(span), "aria-valuemin": floor, "aria-valuemax": ceil, tabIndex: 0, "data-slot": "grip", "data-side": side, "data-moving": moving ? '' : undefined, position: "absolute", ...edge, z: 10, cursor: tall ? 'row-resize' : 'col-resize', outlineWidth: 0, focusVisibleStyle: { outlineWidth: 0 }, style: { touchAction: 'none' }, onPointerEnter: () => setHovered(true), onPointerLeave: () => setHovered(false),
|
|
92
|
+
// The line is the focus ring, drawn for a keyboard's focus and not a pointer's.
|
|
93
|
+
onFocus: (e) => setKeyed(e.currentTarget.matches(':focus-visible')), onBlur: () => setKeyed(false), onPointerDown: (e) => {
|
|
39
94
|
if (e.button !== 0)
|
|
40
95
|
return;
|
|
96
|
+
// No text selection starts under a drag.
|
|
41
97
|
e.preventDefault();
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
98
|
+
e.currentTarget.setPointerCapture?.(e.pointerId);
|
|
99
|
+
const now = drawn(e.currentTarget);
|
|
100
|
+
held.current = along(e) - grows * now;
|
|
101
|
+
want.current = clamp(now);
|
|
102
|
+
drag.current = 'held';
|
|
103
|
+
setMoving(true);
|
|
104
|
+
}, onPointerMove: (e) => {
|
|
105
|
+
if (drag.current === 'none')
|
|
49
106
|
return;
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
107
|
+
drag.current = 'moved';
|
|
108
|
+
const pulled = grows * (along(e) - held.current);
|
|
109
|
+
if (onShut && pulled < floor - SLACK) {
|
|
110
|
+
stop();
|
|
111
|
+
e.currentTarget.releasePointerCapture?.(e.pointerId);
|
|
112
|
+
onShut();
|
|
54
113
|
return;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const key = (e) => {
|
|
59
|
-
if (e.key !== 'ArrowUp' && e.key !== 'ArrowDown')
|
|
114
|
+
}
|
|
115
|
+
want.current = clamp(pulled);
|
|
116
|
+
if (frame.current)
|
|
60
117
|
return;
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
'aria-orientation': 'horizontal',
|
|
87
|
-
'aria-label': `Resize ${label}`,
|
|
88
|
-
'aria-valuemin': min,
|
|
89
|
-
// A drag has no ceiling; this stands in for "as tall as you like".
|
|
90
|
-
'aria-valuemax': CEILING,
|
|
91
|
-
'aria-valuenow': height ?? min,
|
|
92
|
-
'aria-valuetext': height === null ? 'Fits its content' : `${height} pixels`,
|
|
93
|
-
tabIndex: 0,
|
|
94
|
-
}, rounded: "$2", p: "$1", focusVisibleStyle: { bg: '$hover' }, children: _jsx(GripHorizontal, { size: 14, color: "$soft" }) }));
|
|
118
|
+
frame.current = requestAnimationFrame(() => {
|
|
119
|
+
frame.current = 0;
|
|
120
|
+
onSpan(want.current);
|
|
121
|
+
});
|
|
122
|
+
},
|
|
123
|
+
// A drag ends when the pointer is let go: lifted, or taken by the browser.
|
|
124
|
+
onPointerUp: end, onPointerCancel: end, onDoubleClick: () => (onReset ? onReset() : settle(clamp(reset ?? span))), onKeyDown: (e) => {
|
|
125
|
+
const step = e.shiftKey ? LONG : STEP;
|
|
126
|
+
const now = drawn(e.currentTarget);
|
|
127
|
+
const to = e.key === wider
|
|
128
|
+
? now + step
|
|
129
|
+
: e.key === narrower
|
|
130
|
+
? now - step
|
|
131
|
+
: e.key === 'Home'
|
|
132
|
+
? floor
|
|
133
|
+
: e.key === 'End'
|
|
134
|
+
? ceil
|
|
135
|
+
: null;
|
|
136
|
+
if (to === null)
|
|
137
|
+
return;
|
|
138
|
+
e.preventDefault?.();
|
|
139
|
+
if (onShut && to < floor)
|
|
140
|
+
return onShut();
|
|
141
|
+
settle(clamp(to));
|
|
142
|
+
}, ...rest, children: _jsx(YStack, { ...(tall ? { height: 2, width: '100%' } : { width: 2, height: '100%' }), rounded: 1, bg: keyed || moving ? '$outlineColor' : hovered ? '$rim' : 'transparent', pointerEvents: "none" }) }));
|
|
95
143
|
}
|
|
96
144
|
//# sourceMappingURL=grip.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grip.js","sourceRoot":"","sources":["../../../src/backends/gui/grip.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ
|
|
1
|
+
{"version":3,"file":"grip.js","sourceRoot":"","sources":["../../../src/backends/gui/grip.tsx"],"names":[],"mappings":"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"}
|