@hanzo/build 0.2.59 → 0.2.61

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/lib/grip.js DELETED
@@ -1,108 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- /**
3
- * A column's free edge, which is also how wide the column is: a vertical
4
- * separator a person drags, or moves with the arrow keys, to size the column
5
- * beside it. The project workspace sizes its chat with it, and a host sizes its
6
- * own column with it (the Hanzo app's sidebar).
7
- *
8
- * side the edge of the window the column is pinned to: `left` grows
9
- * rightwards (a sidebar, the chat), `right` grows leftwards (an
10
- * aside). One control for both, the arithmetic reflected.
11
- * span the column's width now, px; `floor` and `ceil` bound it.
12
- * onSpan the width while it moves, at most once a frame.
13
- * onKeep the width it settled on: a drag let go, a key, a double-click.
14
- * onShut when given, a drag pulled well past the floor, or a key pressed
15
- * at it, puts the column away; absent, the floor holds.
16
- * reset the width a double-click returns to.
17
- *
18
- * Keys: the arrows step 8px (32px with Shift), Home and End go to the floor and
19
- * the ceiling. Pointer events, so a mouse, a trackpad, a touchscreen and a pen
20
- * are one path, with the pointer captured: a drag that outruns the handle, or
21
- * crosses a framed page, keeps sizing. The drag is measured from the column as
22
- * drawn when it begins, so the edge never jumps to the cursor.
23
- *
24
- * It sits inside the column, absolutely, on the column's free edge; the rest of
25
- * its props place it elsewhere (a gutter beside the column) and win.
26
- */
27
- import { YStack } from '@hanzo/gui';
28
- import { useEffect, useRef, useState } from 'react';
29
- /** A key's step, px; with Shift, the long one. */
30
- const STEP = 8;
31
- const LONG = 32;
32
- /** How far past the floor a drag is pulled before it shuts the column, px: a deliberate pull, not a twitch. */
33
- const SLACK = 48;
34
- export function Grip({ side, span, floor, ceil, reset, onSpan, onKeep, onShut, label, ...rest }) {
35
- // The pinned edge in client coordinates, taken as the drag begins.
36
- const held = useRef(0);
37
- // Whether a press holds the pointer and whether it has moved since, the width
38
- // it last asked for, and the frame that will draw it. A press that never moves
39
- // keeps nothing.
40
- const drag = useRef('none');
41
- const want = useRef(span);
42
- const frame = useRef(0);
43
- const [hovered, setHovered] = useState(false);
44
- const [keyed, setKeyed] = useState(false);
45
- const [moving, setMoving] = useState(false);
46
- useEffect(() => () => cancelAnimationFrame(frame.current), []);
47
- const clamp = (n) => Math.round(Math.min(ceil, Math.max(floor, n)));
48
- const settle = (n) => {
49
- onSpan(n);
50
- onKeep?.(n);
51
- };
52
- const stop = () => {
53
- drag.current = 'none';
54
- cancelAnimationFrame(frame.current);
55
- frame.current = 0;
56
- setMoving(false);
57
- };
58
- const wider = side === 'left' ? 'ArrowRight' : 'ArrowLeft';
59
- const narrower = side === 'left' ? 'ArrowLeft' : 'ArrowRight';
60
- return (_jsx(YStack, { role: "separator", "aria-orientation": "vertical", "aria-label": label, "aria-valuenow": Math.round(span), "aria-valuemin": floor, "aria-valuemax": ceil, tabIndex: 0, "data-slot": "grip", "data-moving": moving ? '' : undefined, position: "absolute", t: 0, b: 0, ...(side === 'left' ? { r: 0 } : { l: 0 }), width: 8, z: 10, items: "center", cursor: "col-resize", outlineWidth: 0, style: { touchAction: 'none' }, onPointerEnter: () => setHovered(true), onPointerLeave: () => setHovered(false),
61
- // The line is the focus ring, drawn for a keyboard's focus and not a pointer's.
62
- onFocus: (e) => setKeyed(e.currentTarget.matches(':focus-visible')), onBlur: () => setKeyed(false), onPointerDown: (e) => {
63
- if (e.button !== 0)
64
- return;
65
- // No text selection starts under a drag.
66
- e.preventDefault();
67
- e.currentTarget.setPointerCapture(e.pointerId);
68
- const drawn = e.currentTarget.parentElement?.getBoundingClientRect().width ?? span;
69
- held.current = side === 'left' ? e.clientX - drawn : e.clientX + drawn;
70
- want.current = clamp(drawn);
71
- drag.current = 'held';
72
- setMoving(true);
73
- }, onPointerMove: (e) => {
74
- if (drag.current === 'none')
75
- return;
76
- drag.current = 'moved';
77
- const pulled = side === 'left' ? e.clientX - held.current : held.current - e.clientX;
78
- if (onShut && pulled < floor - SLACK) {
79
- stop();
80
- e.currentTarget.releasePointerCapture(e.pointerId);
81
- onShut();
82
- return;
83
- }
84
- want.current = clamp(pulled);
85
- if (frame.current)
86
- return;
87
- frame.current = requestAnimationFrame(() => {
88
- frame.current = 0;
89
- onSpan(want.current);
90
- });
91
- },
92
- // A drag ends when the pointer is let go: lifted, or taken by the browser.
93
- onLostPointerCapture: () => {
94
- const moved = drag.current === 'moved';
95
- stop();
96
- if (moved)
97
- settle(want.current);
98
- }, onDoubleClick: () => settle(clamp(reset)), onKeyDown: (e) => {
99
- const step = e.shiftKey ? LONG : STEP;
100
- const to = e.key === wider ? span + step : e.key === narrower ? span - step : e.key === 'Home' ? floor : e.key === 'End' ? ceil : null;
101
- if (to === null)
102
- return;
103
- e.preventDefault?.();
104
- if (onShut && to < floor)
105
- return onShut();
106
- settle(clamp(to));
107
- }, ...rest, children: _jsx(YStack, { width: 2, height: "100%", rounded: 1, bg: keyed || moving ? '$outlineColor' : hovered ? '$rim' : 'transparent', pointerEvents: "none" }) }));
108
- }