@plannotator/ui 0.25.0 → 0.27.0
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/README.md +32 -0
- package/components/InlineMarkdown.tsx +41 -3
- package/components/MarkdownEditor.tsx +46 -0
- package/components/ResizeHandle.tsx +86 -47
- package/components/html-viewer/HtmlViewer.tsx +1 -1
- package/components/html-viewer/useHtmlAnnotation.ts +0 -1
- package/components/sidebar/FileBrowser.tsx +132 -6
- package/hooks/useResizablePanel.ts +36 -5
- package/package.json +3 -3
- package/styles.css +1 -1
- package/theme.css +16 -0
|
@@ -23,6 +23,16 @@ interface UseResizablePanelOptions {
|
|
|
23
23
|
* (still rAF-coalesced).
|
|
24
24
|
*/
|
|
25
25
|
apply?: (width: number) => void;
|
|
26
|
+
/**
|
|
27
|
+
* Fires on pointer-up when the pointer never moved beyond `clickThreshold` —
|
|
28
|
+
* i.e. a genuine click on the handle, not a drag. The hook owns the pointer
|
|
29
|
+
* state machine, so this is the only reliable way to tell a click from a
|
|
30
|
+
* drag-start. Lets a host make the whole handle a click target (e.g. click
|
|
31
|
+
* anywhere on the handle to collapse the panel). Not fired on a snap-close.
|
|
32
|
+
*/
|
|
33
|
+
onClick?: () => void;
|
|
34
|
+
/** Max pointer travel (px) still counted as a click for `onClick`. Default 4. */
|
|
35
|
+
clickThreshold?: number;
|
|
26
36
|
}
|
|
27
37
|
|
|
28
38
|
export interface ResizeHandleProps {
|
|
@@ -43,6 +53,8 @@ export function useResizablePanel({
|
|
|
43
53
|
onSnapClose,
|
|
44
54
|
snapCloseRatio = 0.6,
|
|
45
55
|
apply,
|
|
56
|
+
onClick,
|
|
57
|
+
clickThreshold = 4,
|
|
46
58
|
}: UseResizablePanelOptions) {
|
|
47
59
|
const [width, setWidth] = useState(() => {
|
|
48
60
|
const saved = storage.getItem(storageKey);
|
|
@@ -61,6 +73,9 @@ export function useResizablePanel({
|
|
|
61
73
|
const startWidthRef = useRef(0);
|
|
62
74
|
const draggingRef = useRef(false);
|
|
63
75
|
const snappedRef = useRef(false);
|
|
76
|
+
// Latches true once the pointer travels past clickThreshold — distinguishes a
|
|
77
|
+
// click from a drag. Reset on each pointerdown.
|
|
78
|
+
const movedRef = useRef(false);
|
|
64
79
|
const latestXRef = useRef(0);
|
|
65
80
|
const rafRef = useRef<number | null>(null);
|
|
66
81
|
|
|
@@ -69,6 +84,8 @@ export function useResizablePanel({
|
|
|
69
84
|
applyRef.current = apply;
|
|
70
85
|
const onSnapCloseRef = useRef(onSnapClose);
|
|
71
86
|
onSnapCloseRef.current = onSnapClose;
|
|
87
|
+
const onClickRef = useRef(onClick);
|
|
88
|
+
onClickRef.current = onClick;
|
|
72
89
|
|
|
73
90
|
// rAF tick: compute the width from the most recent pointer position and apply
|
|
74
91
|
// it. At most one DOM/state write per frame regardless of pointer-event rate.
|
|
@@ -110,6 +127,7 @@ export function useResizablePanel({
|
|
|
110
127
|
startWidthRef.current = widthRef.current;
|
|
111
128
|
latestXRef.current = pos;
|
|
112
129
|
snappedRef.current = false;
|
|
130
|
+
movedRef.current = false;
|
|
113
131
|
draggingRef.current = true;
|
|
114
132
|
setIsDragging(true);
|
|
115
133
|
|
|
@@ -120,6 +138,8 @@ export function useResizablePanel({
|
|
|
120
138
|
const onMove = (ev: PointerEvent) => {
|
|
121
139
|
if (!draggingRef.current) return;
|
|
122
140
|
latestXRef.current = axis === 'y' ? ev.clientY : ev.clientX;
|
|
141
|
+
if (Math.abs(latestXRef.current - startXRef.current) > clickThreshold)
|
|
142
|
+
movedRef.current = true;
|
|
123
143
|
if (rafRef.current == null) rafRef.current = requestAnimationFrame(flush);
|
|
124
144
|
};
|
|
125
145
|
const cleanup = () => {
|
|
@@ -127,7 +147,11 @@ export function useResizablePanel({
|
|
|
127
147
|
window.removeEventListener('pointerup', onUp);
|
|
128
148
|
window.removeEventListener('pointercancel', onUp);
|
|
129
149
|
};
|
|
130
|
-
function onUp() {
|
|
150
|
+
function onUp(e: PointerEvent) {
|
|
151
|
+
// pointercancel = the browser aborted the gesture (palm rejection, a
|
|
152
|
+
// system gesture, focus loss). It is NOT a completed click — only clean
|
|
153
|
+
// up drag state, never treat it as a click-to-collapse.
|
|
154
|
+
const cancelled = e?.type === 'pointercancel';
|
|
131
155
|
const wasSnapped = snappedRef.current;
|
|
132
156
|
draggingRef.current = false;
|
|
133
157
|
snappedRef.current = false;
|
|
@@ -137,9 +161,16 @@ export function useResizablePanel({
|
|
|
137
161
|
}
|
|
138
162
|
setIsDragging(false);
|
|
139
163
|
if (!wasSnapped) {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
164
|
+
if (onClickRef.current && !movedRef.current && !cancelled) {
|
|
165
|
+
// A pointerdown+up that never crossed the threshold is a click, not
|
|
166
|
+
// a resize — fire onClick and leave the width untouched. Only when a
|
|
167
|
+
// host opts in via onClick; otherwise commit exactly as before.
|
|
168
|
+
onClickRef.current();
|
|
169
|
+
} else {
|
|
170
|
+
// Commit the live width to React state + persist.
|
|
171
|
+
setWidth(widthRef.current);
|
|
172
|
+
storage.setItem(storageKey, String(widthRef.current));
|
|
173
|
+
}
|
|
143
174
|
}
|
|
144
175
|
cleanup();
|
|
145
176
|
}
|
|
@@ -148,7 +179,7 @@ export function useResizablePanel({
|
|
|
148
179
|
window.addEventListener('pointerup', onUp);
|
|
149
180
|
window.addEventListener('pointercancel', onUp);
|
|
150
181
|
},
|
|
151
|
-
[flush, storageKey, axis],
|
|
182
|
+
[flush, storageKey, axis, clickThreshold],
|
|
152
183
|
);
|
|
153
184
|
|
|
154
185
|
const resetWidth = useCallback(() => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plannotator/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
"./components/*": "./components/*.tsx",
|
|
@@ -65,9 +65,9 @@
|
|
|
65
65
|
"@lezer/common": "^1.5.2",
|
|
66
66
|
"@lezer/highlight": "^1.2.3",
|
|
67
67
|
"@pierre/diffs": "1.2.8",
|
|
68
|
-
"@plannotator/atomic-editor": "^0.
|
|
68
|
+
"@plannotator/atomic-editor": "^0.7.0",
|
|
69
69
|
"@plannotator/core": "0.22.0",
|
|
70
|
-
"@plannotator/markdown-editor": "^0.2
|
|
70
|
+
"@plannotator/markdown-editor": "^0.3.2",
|
|
71
71
|
"@plannotator/web-highlighter": "^0.8.1",
|
|
72
72
|
"@tanstack/react-table": "^8.21.3",
|
|
73
73
|
"@viz-js/viz": "^3.25.0",
|