@tangle-network/ui 11.51.10 → 11.51.12
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/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
## 11.51.12
|
|
2
|
+
|
|
3
|
+
### Patch Changes
|
|
4
|
+
|
|
5
|
+
- e5f85bd: Preserve sequence zero when a named native stream reconnects; omit the cursor before any event arrives.
|
|
6
|
+
|
|
7
|
+
## 11.51.11
|
|
8
|
+
|
|
9
|
+
- Keep tool-row actions and navigation reachable after a hover preview. HoverCard uses its anchor for placement, preserves keyboard inspection, and dismisses previews when a nested control commits an action. Touch actions do not become hover intent.
|
|
10
|
+
|
|
1
11
|
## 11.51.10
|
|
2
12
|
|
|
3
13
|
- Render Runtime’s recorded `down` outcome as Failed; cancellation and no-winner remain Stopped.
|
|
@@ -12,4 +12,4 @@ export interface EventStreamHandlers {
|
|
|
12
12
|
onLiveChange?: (live: boolean) => void;
|
|
13
13
|
}
|
|
14
14
|
/** Producer-owned named events; host transports keep their authenticated reconnect lifecycle. */
|
|
15
|
-
export declare function useEventStream(url: string | undefined, handlers: EventStreamHandlers): void;
|
|
15
|
+
export declare function useEventStream(url: string | (() => string) | undefined, handlers: EventStreamHandlers): void;
|
|
@@ -8,7 +8,7 @@ function openNativeStream(url, handlers) {
|
|
|
8
8
|
const open = () => {
|
|
9
9
|
handlers.onConnecting?.(attempt);
|
|
10
10
|
const target = new URL(typeof url === "function" ? url() : url, globalThis.location?.href), after = handlers.after?.();
|
|
11
|
-
if (after !== void 0 && after
|
|
11
|
+
if (after !== void 0 && after >= 0) target.searchParams.set("after", String(after));
|
|
12
12
|
let connection;
|
|
13
13
|
const live = (value) => {
|
|
14
14
|
if (!stopped && (!connection || source === connection)) handlers.onLiveChange?.(value);
|
|
@@ -56,7 +56,7 @@ function useEventStream(url, handlers) {
|
|
|
56
56
|
const connection = openNativeStream(url, {
|
|
57
57
|
opener: handlers.opener,
|
|
58
58
|
events: Object.fromEntries(Object.keys(handlers.events).map((name) => [name, (event) => latest.current.events[name]?.(event)])),
|
|
59
|
-
after: () => latest.current.after?.() ??
|
|
59
|
+
after: () => latest.current.after?.() ?? -1,
|
|
60
60
|
onStart: () => latest.current.onStart?.(),
|
|
61
61
|
onLiveChange: (live) => latest.current.onLiveChange?.(live),
|
|
62
62
|
terminalEvent: "end"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { cn } from "../lib/utils.js";
|
|
2
|
-
import { Popover, PopoverAnchor, PopoverContent
|
|
2
|
+
import { Popover, PopoverAnchor, PopoverContent } from "./popover.js";
|
|
3
3
|
import { Slot } from "@radix-ui/react-slot";
|
|
4
4
|
import * as React from "react";
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -7,7 +7,8 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
7
7
|
const HoverIntent = React.createContext({
|
|
8
8
|
enter: (_target) => {},
|
|
9
9
|
leave: () => {},
|
|
10
|
-
restore: () => {}
|
|
10
|
+
restore: () => {},
|
|
11
|
+
press: () => {}
|
|
11
12
|
});
|
|
12
13
|
/** One hover policy and Popover's keyboard/focus behavior; delays follow the trigger's fast token. */
|
|
13
14
|
function HoverCard({ anchor, open: controlled, defaultOpen = false, onOpenChange, openDelay, closeDelay, children, ...props }) {
|
|
@@ -31,12 +32,12 @@ function HoverCard({ anchor, open: controlled, defaultOpen = false, onOpenChange
|
|
|
31
32
|
element
|
|
32
33
|
]);
|
|
33
34
|
const delay = (target) => {
|
|
34
|
-
if (typeof document === "undefined") return 0;
|
|
35
35
|
const value = getComputedStyle(target ?? document.documentElement).getPropertyValue("--duration-fast").trim();
|
|
36
36
|
return (parseFloat(value) || 0) * (value.endsWith("ms") ? 1 : 1e3);
|
|
37
37
|
};
|
|
38
38
|
const enter = React.useCallback((target) => {
|
|
39
|
-
if (intent.current.restoring) return;
|
|
39
|
+
if (intent.current.restoring || intent.current.pressed && target.closest("[data-hover-card]")) return;
|
|
40
|
+
intent.current.pressed = false;
|
|
40
41
|
if (!target.closest("[data-hover-card]")) intent.current.target = target;
|
|
41
42
|
clearTimeout(intent.current.timer);
|
|
42
43
|
intent.current.timer = setTimeout(() => change(true), openDelay ?? delay(target));
|
|
@@ -82,7 +83,11 @@ function HoverCard({ anchor, open: controlled, defaultOpen = false, onOpenChange
|
|
|
82
83
|
value: {
|
|
83
84
|
enter,
|
|
84
85
|
leave,
|
|
85
|
-
restore
|
|
86
|
+
restore,
|
|
87
|
+
press: () => {
|
|
88
|
+
intent.current.pressed = true;
|
|
89
|
+
change(false);
|
|
90
|
+
}
|
|
86
91
|
},
|
|
87
92
|
children: /* @__PURE__ */ jsxs(Popover, {
|
|
88
93
|
...props,
|
|
@@ -92,9 +97,9 @@ function HoverCard({ anchor, open: controlled, defaultOpen = false, onOpenChange
|
|
|
92
97
|
})
|
|
93
98
|
});
|
|
94
99
|
}
|
|
95
|
-
const HoverCardTrigger = React.forwardRef(({ className, onPointerEnter, onPointerLeave, onFocus, onBlur, asChild, ...props }, ref) => {
|
|
100
|
+
const HoverCardTrigger = React.forwardRef(({ className, onPointerEnter, onPointerLeave, onFocus, onBlur, onClickCapture, asChild, ...props }, ref) => {
|
|
96
101
|
const intent = React.useContext(HoverIntent);
|
|
97
|
-
return /* @__PURE__ */ jsx(
|
|
102
|
+
return /* @__PURE__ */ jsx(PopoverAnchor, {
|
|
98
103
|
asChild: true,
|
|
99
104
|
children: /* @__PURE__ */ jsx(asChild ? Slot : "a", {
|
|
100
105
|
ref,
|
|
@@ -102,7 +107,7 @@ const HoverCardTrigger = React.forwardRef(({ className, onPointerEnter, onPointe
|
|
|
102
107
|
className: cn("cursor-pointer underline-offset-4 hover:underline", className),
|
|
103
108
|
onPointerEnter: (event) => {
|
|
104
109
|
onPointerEnter?.(event);
|
|
105
|
-
if (!event.defaultPrevented) intent.enter(event.currentTarget);
|
|
110
|
+
if (!event.defaultPrevented && event.pointerType !== "touch") intent.enter(event.currentTarget);
|
|
106
111
|
},
|
|
107
112
|
onPointerLeave: (event) => {
|
|
108
113
|
onPointerLeave?.(event);
|
|
@@ -110,7 +115,12 @@ const HoverCardTrigger = React.forwardRef(({ className, onPointerEnter, onPointe
|
|
|
110
115
|
},
|
|
111
116
|
onFocus: (event) => {
|
|
112
117
|
onFocus?.(event);
|
|
113
|
-
if (!event.defaultPrevented) intent.enter(event.currentTarget);
|
|
118
|
+
if (!event.defaultPrevented && event.target.matches(":focus-visible")) intent.enter(event.currentTarget);
|
|
119
|
+
},
|
|
120
|
+
onClickCapture: (event) => {
|
|
121
|
+
onClickCapture?.(event);
|
|
122
|
+
const action = event.target instanceof Element ? event.target.closest("a,button,input,select,textarea,[role=\"button\"]") : null;
|
|
123
|
+
if (!event.defaultPrevented && action && action !== event.currentTarget) intent.press();
|
|
114
124
|
},
|
|
115
125
|
onBlur: (event) => {
|
|
116
126
|
onBlur?.(event);
|
package/package.json
CHANGED
|
@@ -25,7 +25,7 @@ export function openNativeStream(url: string | (() => string), handlers: NativeP
|
|
|
25
25
|
const open = () => {
|
|
26
26
|
handlers.onConnecting?.(attempt)
|
|
27
27
|
const target = new URL(typeof url === 'function' ? url() : url, globalThis.location?.href), after = handlers.after?.()
|
|
28
|
-
if (after !== undefined && after
|
|
28
|
+
if (after !== undefined && after >= 0) target.searchParams.set('after', String(after))
|
|
29
29
|
let connection: EventStreamSource
|
|
30
30
|
const live = (value: boolean) => { if (!stopped && (!connection || source === connection)) handlers.onLiveChange?.(value) }
|
|
31
31
|
connection = handlers.opener ? handlers.opener(target.toString(), live) : new EventSource(target.toString())
|
|
@@ -52,7 +52,7 @@ export function openNativeStream(url: string | (() => string), handlers: NativeP
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
/** Producer-owned named events; host transports keep their authenticated reconnect lifecycle. */
|
|
55
|
-
export function useEventStream(url: string | undefined, handlers: EventStreamHandlers): void {
|
|
55
|
+
export function useEventStream(url: string | (() => string) | undefined, handlers: EventStreamHandlers): void {
|
|
56
56
|
const latest = useRef(handlers)
|
|
57
57
|
latest.current = handlers
|
|
58
58
|
const names = Object.keys(handlers.events).sort().join(',')
|
|
@@ -61,7 +61,7 @@ export function useEventStream(url: string | undefined, handlers: EventStreamHan
|
|
|
61
61
|
const current: EventStreamHandlers = {
|
|
62
62
|
opener: handlers.opener,
|
|
63
63
|
events: Object.fromEntries(Object.keys(handlers.events).map(name => [name, (event: MessageEvent<string>) => latest.current.events[name]?.(event)])),
|
|
64
|
-
after: () => latest.current.after?.() ??
|
|
64
|
+
after: () => latest.current.after?.() ?? -1,
|
|
65
65
|
onStart: () => latest.current.onStart?.(),
|
|
66
66
|
onLiveChange: live => latest.current.onLiveChange?.(live),
|
|
67
67
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { cn } from "../lib/utils";
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import { Slot } from "@radix-ui/react-slot";
|
|
4
|
-
import { Popover, PopoverAnchor, PopoverContent
|
|
4
|
+
import { Popover, PopoverAnchor, PopoverContent } from "./popover";
|
|
5
5
|
|
|
6
|
-
const HoverIntent = React.createContext({ enter: (_target: Element) => {}, leave: () => {}, restore: () => {} });
|
|
6
|
+
const HoverIntent = React.createContext({ enter: (_target: Element) => {}, leave: () => {}, restore: () => {}, press: () => {} });
|
|
7
7
|
type HoverCardProps = React.ComponentProps<typeof Popover> & {
|
|
8
8
|
/** Existing DOM trigger for delegated canvas or virtual-list previews. */
|
|
9
9
|
anchor?: HTMLElement | { getBoundingClientRect: () => DOMRect; contextElement: HTMLElement } | null;
|
|
@@ -15,15 +15,14 @@ type HoverCardProps = React.ComponentProps<typeof Popover> & {
|
|
|
15
15
|
export function HoverCard({ anchor, open: controlled, defaultOpen = false, onOpenChange, openDelay, closeDelay, children, ...props }: HoverCardProps) {
|
|
16
16
|
const element = anchor && ("contextElement" in anchor ? anchor.contextElement : anchor);
|
|
17
17
|
const [own, setOwn] = React.useState({ anchor: element, open: defaultOpen });
|
|
18
|
-
const intent = React.useRef<{ timer?: ReturnType<typeof setTimeout>; target?: Element; restoring?: boolean }>({});
|
|
18
|
+
const intent = React.useRef<{ timer?: ReturnType<typeof setTimeout>; target?: Element; restoring?: boolean; pressed?: boolean }>({});
|
|
19
19
|
if (element) intent.current.target = element;
|
|
20
20
|
const change = React.useCallback((next: boolean) => { clearTimeout(intent.current.timer); if (controlled === undefined) setOwn({ anchor: element, open: next }); onOpenChange?.(next); }, [controlled, onOpenChange, element]);
|
|
21
21
|
const delay = (target: Element | null | undefined) => {
|
|
22
|
-
if (typeof document === "undefined") return 0;
|
|
23
22
|
const value = getComputedStyle(target ?? document.documentElement).getPropertyValue("--duration-fast").trim();
|
|
24
23
|
return (parseFloat(value) || 0) * (value.endsWith("ms") ? 1 : 1000);
|
|
25
24
|
};
|
|
26
|
-
const enter = React.useCallback((target: Element) => { if (intent.current.restoring) return; if (!target.closest("[data-hover-card]")) intent.current.target = target; clearTimeout(intent.current.timer); intent.current.timer = setTimeout(() => change(true), openDelay ?? delay(target)); }, [change, openDelay]);
|
|
25
|
+
const enter = React.useCallback((target: Element) => { if (intent.current.restoring || (intent.current.pressed && target.closest("[data-hover-card]"))) return; intent.current.pressed = false; if (!target.closest("[data-hover-card]")) intent.current.target = target; clearTimeout(intent.current.timer); intent.current.timer = setTimeout(() => change(true), openDelay ?? delay(target)); }, [change, openDelay]);
|
|
27
26
|
const leave = React.useCallback(() => { clearTimeout(intent.current.timer); intent.current.timer = setTimeout(() => change(false), closeDelay ?? delay(element ?? intent.current.target)); }, [change, closeDelay, element]);
|
|
28
27
|
React.useEffect(() => {
|
|
29
28
|
if (!element) return () => clearTimeout(intent.current.timer);
|
|
@@ -36,20 +35,21 @@ export function HoverCard({ anchor, open: controlled, defaultOpen = false, onOpe
|
|
|
36
35
|
if (document.activeElement === document.body && intent.current.target instanceof HTMLElement) intent.current.target.focus({ preventScroll: true });
|
|
37
36
|
queueMicrotask(() => { intent.current.restoring = false; });
|
|
38
37
|
};
|
|
39
|
-
return <HoverIntent.Provider value={{ enter, leave, restore }}><Popover {...props} open={anchor === null ? false : controlled ?? (own.anchor === element && own.open)} onOpenChange={change}>
|
|
38
|
+
return <HoverIntent.Provider value={{ enter, leave, restore, press: () => { intent.current.pressed = true; change(false); } }}><Popover {...props} open={anchor === null ? false : controlled ?? (own.anchor === element && own.open)} onOpenChange={change}>
|
|
40
39
|
{anchor && <PopoverAnchor virtualRef={{ current: anchor }} />}{children}
|
|
41
40
|
</Popover></HoverIntent.Provider>;
|
|
42
41
|
}
|
|
43
42
|
|
|
44
43
|
export const HoverCardTrigger = React.forwardRef<HTMLAnchorElement, React.AnchorHTMLAttributes<HTMLAnchorElement> & { asChild?: boolean }>(
|
|
45
|
-
({ className, onPointerEnter, onPointerLeave, onFocus, onBlur, asChild, ...props }, ref) => {
|
|
44
|
+
({ className, onPointerEnter, onPointerLeave, onFocus, onBlur, onClickCapture, asChild, ...props }, ref) => {
|
|
46
45
|
const intent = React.useContext(HoverIntent);
|
|
47
46
|
const Trigger = asChild ? Slot : "a";
|
|
48
|
-
return <
|
|
49
|
-
onPointerEnter={event => { onPointerEnter?.(event); if (!event.defaultPrevented) intent.enter(event.currentTarget); }}
|
|
47
|
+
return <PopoverAnchor asChild><Trigger ref={ref} tabIndex={0} className={cn("cursor-pointer underline-offset-4 hover:underline", className)}
|
|
48
|
+
onPointerEnter={event => { onPointerEnter?.(event); if (!event.defaultPrevented && event.pointerType !== "touch") intent.enter(event.currentTarget); }}
|
|
50
49
|
onPointerLeave={event => { onPointerLeave?.(event); if (!event.defaultPrevented) intent.leave(); }}
|
|
51
|
-
onFocus={event => { onFocus?.(event); if (!event.defaultPrevented) intent.enter(event.currentTarget); }}
|
|
52
|
-
|
|
50
|
+
onFocus={event => { onFocus?.(event); if (!event.defaultPrevented && event.target.matches(":focus-visible")) intent.enter(event.currentTarget); }}
|
|
51
|
+
onClickCapture={event => { onClickCapture?.(event); const action = event.target instanceof Element ? event.target.closest('a,button,input,select,textarea,[role="button"]') : null; if (!event.defaultPrevented && action && action !== event.currentTarget) intent.press(); }}
|
|
52
|
+
onBlur={event => { onBlur?.(event); if (!event.defaultPrevented && !(event.relatedTarget instanceof Element && event.relatedTarget.closest("[data-hover-card]"))) intent.leave(); }} {...props} /></PopoverAnchor>;
|
|
53
53
|
},
|
|
54
54
|
);
|
|
55
55
|
HoverCardTrigger.displayName = "HoverCardTrigger";
|