@workflow/web-shared 5.0.0-beta.10 → 5.0.0-beta.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/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +2 -1
- package/dist/components/new-trace-viewer/components/event-list.d.ts.map +1 -1
- package/dist/components/new-trace-viewer/components/event-list.js +9 -4
- package/dist/components/new-trace-viewer/components/split-pane.d.ts +3 -2
- package/dist/components/new-trace-viewer/components/split-pane.d.ts.map +1 -1
- package/dist/components/new-trace-viewer/components/split-pane.js +10 -4
- package/dist/components/new-trace-viewer/components/timeline.d.ts +1 -1
- package/dist/components/new-trace-viewer/components/timeline.d.ts.map +1 -1
- package/dist/components/new-trace-viewer/components/timeline.js +6 -8
- package/dist/components/new-trace-viewer/components/trace-viewer-skeleton.d.ts +2 -0
- package/dist/components/new-trace-viewer/components/trace-viewer-skeleton.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/trace-viewer-skeleton.js +19 -0
- package/dist/components/new-trace-viewer/components/use-row-window.d.ts +20 -0
- package/dist/components/new-trace-viewer/components/use-row-window.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/use-row-window.js +69 -0
- package/dist/components/new-trace-viewer/context.d.ts.map +1 -1
- package/dist/components/new-trace-viewer/context.js +2 -2
- package/dist/components/new-trace-viewer/trace-viewer.d.ts +4 -1
- package/dist/components/new-trace-viewer/trace-viewer.d.ts.map +1 -1
- package/dist/components/new-trace-viewer/trace-viewer.js +19 -6
- package/dist/components/trace-viewer-new.d.ts +5 -1
- package/dist/components/trace-viewer-new.d.ts.map +1 -1
- package/dist/components/trace-viewer-new.js +7 -8
- package/dist/components/ui/icon-button.d.ts +8 -2
- package/dist/components/ui/icon-button.d.ts.map +1 -1
- package/dist/components/ui/icon-button.js +4 -4
- package/dist/components/ui/kbd.d.ts +6 -0
- package/dist/components/ui/kbd.d.ts.map +1 -0
- package/dist/components/ui/kbd.js +6 -0
- package/dist/components/ui/tooltip.d.ts +10 -0
- package/dist/components/ui/tooltip.d.ts.map +1 -0
- package/dist/components/ui/tooltip.js +12 -0
- package/dist/hooks/use-intersection-observer.d.ts +17 -0
- package/dist/hooks/use-intersection-observer.d.ts.map +1 -0
- package/dist/hooks/use-intersection-observer.js +29 -0
- package/dist/hooks/use-load-more-on-scroll.d.ts +21 -0
- package/dist/hooks/use-load-more-on-scroll.d.ts.map +1 -0
- package/dist/hooks/use-load-more-on-scroll.js +28 -0
- package/dist/lib/hydration.d.ts.map +1 -1
- package/dist/lib/hydration.js +26 -2
- package/package.json +4 -4
- package/src/components/index.ts +1 -0
- package/src/components/new-trace-viewer/components/event-list.tsx +19 -11
- package/src/components/new-trace-viewer/components/split-pane.tsx +15 -2
- package/src/components/new-trace-viewer/components/timeline.tsx +27 -19
- package/src/components/new-trace-viewer/components/trace-viewer-skeleton.tsx +94 -0
- package/src/components/new-trace-viewer/components/use-row-window.ts +93 -0
- package/src/components/new-trace-viewer/context.tsx +1 -3
- package/src/components/new-trace-viewer/trace-viewer.tsx +90 -22
- package/src/components/trace-viewer-new.tsx +20 -12
- package/src/components/ui/icon-button.tsx +7 -11
- package/src/components/ui/kbd.tsx +21 -0
- package/src/components/ui/tooltip.tsx +47 -0
- package/src/hooks/use-intersection-observer.ts +57 -0
- package/src/hooks/use-load-more-on-scroll.ts +49 -0
- package/src/lib/hydration.ts +28 -1
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import * as TooltipPrimitive from '@radix-ui/react-tooltip';
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
import { cn } from '../../lib/utils';
|
|
6
|
+
|
|
7
|
+
const TooltipProvider = TooltipPrimitive.Provider;
|
|
8
|
+
|
|
9
|
+
const Tooltip = TooltipPrimitive.Root;
|
|
10
|
+
|
|
11
|
+
const TooltipTrigger = TooltipPrimitive.Trigger;
|
|
12
|
+
|
|
13
|
+
const TooltipContent = React.forwardRef<
|
|
14
|
+
React.ElementRef<typeof TooltipPrimitive.Content>,
|
|
15
|
+
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content> & {
|
|
16
|
+
showArrow?: boolean;
|
|
17
|
+
}
|
|
18
|
+
>(
|
|
19
|
+
(
|
|
20
|
+
{ className, sideOffset = 8, showArrow = true, children, ...props },
|
|
21
|
+
ref
|
|
22
|
+
) => (
|
|
23
|
+
<TooltipPrimitive.Portal>
|
|
24
|
+
<TooltipPrimitive.Content
|
|
25
|
+
ref={ref}
|
|
26
|
+
sideOffset={sideOffset}
|
|
27
|
+
className={cn(
|
|
28
|
+
'z-[99999] flex items-center gap-1 rounded-[10px] bg-gray-1000 px-2 py-1.5 !text-label-13 text-background-100 shadow-md select-none',
|
|
29
|
+
className
|
|
30
|
+
)}
|
|
31
|
+
{...props}
|
|
32
|
+
>
|
|
33
|
+
{children}
|
|
34
|
+
{showArrow ? (
|
|
35
|
+
<TooltipPrimitive.Arrow
|
|
36
|
+
width={11}
|
|
37
|
+
height={5}
|
|
38
|
+
className="fill-gray-1000"
|
|
39
|
+
/>
|
|
40
|
+
) : null}
|
|
41
|
+
</TooltipPrimitive.Content>
|
|
42
|
+
</TooltipPrimitive.Portal>
|
|
43
|
+
)
|
|
44
|
+
);
|
|
45
|
+
TooltipContent.displayName = TooltipPrimitive.Content.displayName;
|
|
46
|
+
|
|
47
|
+
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import type { RefObject } from 'react';
|
|
4
|
+
import { useEffect, useState } from 'react';
|
|
5
|
+
|
|
6
|
+
interface UseIntersectionObserverArgs
|
|
7
|
+
extends Omit<IntersectionObserverInit, 'root'> {
|
|
8
|
+
/**
|
|
9
|
+
* Scroll container the target is observed within. Defaults to the viewport.
|
|
10
|
+
* Passed as a ref so it resolves after commit (when the node exists).
|
|
11
|
+
*/
|
|
12
|
+
rootRef?: RefObject<Element | null>;
|
|
13
|
+
freezeOnceVisible?: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Returns the latest IntersectionObserverEntry for `elementRef`.
|
|
18
|
+
* Ported from vercel/front's `@vercel/hooks` `useIntersectionObserver`, with
|
|
19
|
+
* `root` threaded as a ref so we can observe inside a custom scroll container.
|
|
20
|
+
*/
|
|
21
|
+
export function useIntersectionObserver(
|
|
22
|
+
elementRef: RefObject<Element | null>,
|
|
23
|
+
{
|
|
24
|
+
threshold = 0,
|
|
25
|
+
rootRef,
|
|
26
|
+
rootMargin = '0%',
|
|
27
|
+
freezeOnceVisible = false,
|
|
28
|
+
}: UseIntersectionObserverArgs = {}
|
|
29
|
+
): IntersectionObserverEntry | undefined {
|
|
30
|
+
const [entry, setEntry] = useState<IntersectionObserverEntry>();
|
|
31
|
+
|
|
32
|
+
const frozen = entry?.isIntersecting && freezeOnceVisible;
|
|
33
|
+
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
const node = elementRef?.current;
|
|
36
|
+
|
|
37
|
+
const hasIOSupport = !!window.IntersectionObserver;
|
|
38
|
+
|
|
39
|
+
if (!hasIOSupport || frozen || !node) return;
|
|
40
|
+
|
|
41
|
+
const updateEntry = ([entry]: IntersectionObserverEntry[]): void => {
|
|
42
|
+
setEntry(entry);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const observer = new IntersectionObserver(updateEntry, {
|
|
46
|
+
threshold,
|
|
47
|
+
root: rootRef?.current ?? null,
|
|
48
|
+
rootMargin,
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
observer.observe(node);
|
|
52
|
+
|
|
53
|
+
return () => observer.disconnect();
|
|
54
|
+
}, [elementRef, threshold, rootRef, rootMargin, frozen]);
|
|
55
|
+
|
|
56
|
+
return entry;
|
|
57
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import type { RefObject } from 'react';
|
|
4
|
+
import { useEffect, useRef } from 'react';
|
|
5
|
+
import { useIntersectionObserver } from './use-intersection-observer';
|
|
6
|
+
|
|
7
|
+
interface UseLoadMoreOnScrollOptions {
|
|
8
|
+
hasMore: boolean;
|
|
9
|
+
isLoadingMore: boolean;
|
|
10
|
+
/** Scroll container the sentinel lives in. Defaults to the viewport. */
|
|
11
|
+
rootRef?: RefObject<Element | null>;
|
|
12
|
+
rootMargin?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Triggers `loadMore` when a sentinel element scrolls into view.
|
|
17
|
+
* Returns a ref to attach to an invisible sentinel `<div>` placed after the
|
|
18
|
+
* list content. Ported from vercel/front's `@vercel/hooks`
|
|
19
|
+
* `useLoadMoreOnScroll`.
|
|
20
|
+
*
|
|
21
|
+
* Because it keys off `isIntersecting`/`isLoadingMore`, it self-continues:
|
|
22
|
+
* if the sentinel is still in view once a page finishes loading, the next
|
|
23
|
+
* page is requested automatically.
|
|
24
|
+
*/
|
|
25
|
+
export function useLoadMoreOnScroll(
|
|
26
|
+
loadMore: () => void,
|
|
27
|
+
{
|
|
28
|
+
hasMore,
|
|
29
|
+
isLoadingMore,
|
|
30
|
+
rootRef,
|
|
31
|
+
rootMargin = '400px',
|
|
32
|
+
}: UseLoadMoreOnScrollOptions
|
|
33
|
+
) {
|
|
34
|
+
const sentinelRef = useRef<HTMLDivElement>(null);
|
|
35
|
+
const entry = useIntersectionObserver(sentinelRef, { rootRef, rootMargin });
|
|
36
|
+
|
|
37
|
+
const loadMoreRef = useRef(loadMore);
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
loadMoreRef.current = loadMore;
|
|
40
|
+
}, [loadMore]);
|
|
41
|
+
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
if (entry?.isIntersecting && hasMore && !isLoadingMore) {
|
|
44
|
+
loadMoreRef.current();
|
|
45
|
+
}
|
|
46
|
+
}, [entry?.isIntersecting, hasMore, isLoadingMore]);
|
|
47
|
+
|
|
48
|
+
return sentinelRef;
|
|
49
|
+
}
|
package/src/lib/hydration.ts
CHANGED
|
@@ -135,7 +135,8 @@ export function getWebRevivers(): Revivers {
|
|
|
135
135
|
// Error family. The reducer side (see
|
|
136
136
|
// `packages/core/src/serialization/reducers/common.ts`) emits a tagged
|
|
137
137
|
// entry for each built-in Error subclass plus the workflow-specific
|
|
138
|
-
// `FatalError` / `RetryableError`
|
|
138
|
+
// `FatalError` / `RetryableError` / `HookConflictError` /
|
|
139
|
+
// `RuntimeDecryptionError` and `AggregateError`. Without
|
|
139
140
|
// matching revivers here, `devalue.unflatten` throws "Unknown type X"
|
|
140
141
|
// — which surfaces in the web o11y UI as "Failed to load resource
|
|
141
142
|
// details: Unknown type FatalError".
|
|
@@ -183,6 +184,20 @@ export function getWebRevivers(): Revivers {
|
|
|
183
184
|
if (value.stack !== undefined) error.stack = value.stack;
|
|
184
185
|
return error;
|
|
185
186
|
},
|
|
187
|
+
HookConflictError: (value) => {
|
|
188
|
+
const opts = 'cause' in value ? { cause: value.cause } : undefined;
|
|
189
|
+
const error = new Error(value.message, opts) as Error & {
|
|
190
|
+
token?: string;
|
|
191
|
+
conflictingRunId?: string;
|
|
192
|
+
};
|
|
193
|
+
error.name = 'HookConflictError';
|
|
194
|
+
error.token = value.token;
|
|
195
|
+
if (value.conflictingRunId !== undefined) {
|
|
196
|
+
error.conflictingRunId = value.conflictingRunId;
|
|
197
|
+
}
|
|
198
|
+
if (value.stack !== undefined) error.stack = value.stack;
|
|
199
|
+
return error;
|
|
200
|
+
},
|
|
186
201
|
RetryableError: (value) => {
|
|
187
202
|
const opts = 'cause' in value ? { cause: value.cause } : undefined;
|
|
188
203
|
const error = new Error(value.message, opts) as Error & {
|
|
@@ -201,6 +216,18 @@ export function getWebRevivers(): Revivers {
|
|
|
201
216
|
}
|
|
202
217
|
return error;
|
|
203
218
|
},
|
|
219
|
+
RuntimeDecryptionError: (value) => {
|
|
220
|
+
const opts = 'cause' in value ? { cause: value.cause } : undefined;
|
|
221
|
+
const error = new Error(value.message, opts) as Error & {
|
|
222
|
+
context?: unknown;
|
|
223
|
+
};
|
|
224
|
+
error.name = 'RuntimeDecryptionError';
|
|
225
|
+
if (value.context !== undefined) {
|
|
226
|
+
error.context = value.context;
|
|
227
|
+
}
|
|
228
|
+
if (value.stack !== undefined) error.stack = value.stack;
|
|
229
|
+
return error;
|
|
230
|
+
},
|
|
204
231
|
DOMException: (value) => {
|
|
205
232
|
// Modern browsers and Node 18+ expose `DOMException` on globalThis.
|
|
206
233
|
// `AbortController.abort()` with no argument synthesizes one as the
|