@windrun-huaiin/third-ui 14.4.0 → 14.4.1
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.
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* References most of its code and SVG animation design from
|
|
3
|
+
* https://github.com/fuma-nama/fumadocs/blob/dev/packages/radix-ui/src/components/toc/clerk.tsx
|
|
4
|
+
*/
|
|
1
5
|
import * as Primitive from 'fumadocs-core/toc';
|
|
2
6
|
import { type ComponentProps, type ReactNode } from 'react';
|
|
3
7
|
type TOCItemType = Primitive.TOCItemType;
|
|
@@ -37,6 +37,14 @@ const CLERK_TURN_CURVE_HEIGHT = 12;
|
|
|
37
37
|
const CLERK_TURN_CONTROL_FACTOR = 0.68;
|
|
38
38
|
// Safety margin that keeps turns away from the heading rows themselves.
|
|
39
39
|
const CLERK_TURN_GAP_MARGIN = 7;
|
|
40
|
+
// Shared duration for active rail fade transitions and endpoint dot movement.
|
|
41
|
+
const CLERK_ACTIVE_ANIMATION_DURATION_MS = 300;
|
|
42
|
+
// Easing curve for the active rail and dot; tuned for a slightly delayed, softer motion.
|
|
43
|
+
const CLERK_ACTIVE_ANIMATION_EASING = 'cubic-bezier(0.22, 1, 0.36, 1)';
|
|
44
|
+
// Horizontal gap between the path centerline and the heading text start.
|
|
45
|
+
const CLERK_TEXT_GAP_FROM_PATH = 12;
|
|
46
|
+
// Radius of numbered step badges rendered on top of the path centerline.
|
|
47
|
+
const CLERK_STEP_BADGE_RADIUS = 7;
|
|
40
48
|
function PortableClerkTOC({ toc, header, footer, title, emptyLabel = 'No headings', className, }) {
|
|
41
49
|
return (jsxRuntime.jsxs(page.PageTOC, { className: className, children: [header, title !== null && title !== void 0 ? title : jsxRuntime.jsx(page.PageTOCTitle, {}), jsxRuntime.jsx(PortableClerkTOCScrollArea, { children: jsxRuntime.jsx(PortableClerkTOCItems, { toc: toc, emptyLabel: emptyLabel }) }), footer] }));
|
|
42
50
|
}
|
|
@@ -128,22 +136,44 @@ function PortableClerkTOCItem({ item, isActive, resolvedContent, itemPadding, co
|
|
|
128
136
|
}, className: cn('prose group relative py-1.5 text-sm transition-colors wrap-anywhere first:pt-0 last:pb-0 hover:text-fd-accent-foreground', isActive ? lib.themeIconColor : 'text-fd-muted-foreground'), children: jsxRuntime.jsx("span", { ref: contentRef, className: "relative z-10", children: resolvedContent }) }));
|
|
129
137
|
}
|
|
130
138
|
function ClerkOutline({ path, items, activePath, activeAnchors, activeEndpoint, }) {
|
|
139
|
+
const activeSet = new Set(activeAnchors);
|
|
140
|
+
const [displayPath, setDisplayPath] = React.useState(activePath);
|
|
141
|
+
const [fadingPath, setFadingPath] = React.useState(null);
|
|
142
|
+
React.useEffect(() => {
|
|
143
|
+
if (activePath === displayPath)
|
|
144
|
+
return;
|
|
145
|
+
if (!displayPath) {
|
|
146
|
+
setDisplayPath(activePath);
|
|
147
|
+
setFadingPath(null);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
setFadingPath(displayPath);
|
|
151
|
+
setDisplayPath(activePath);
|
|
152
|
+
const timeout = window.setTimeout(() => {
|
|
153
|
+
setFadingPath(null);
|
|
154
|
+
}, CLERK_ACTIVE_ANIMATION_DURATION_MS);
|
|
155
|
+
return () => window.clearTimeout(timeout);
|
|
156
|
+
}, [activePath, displayPath]);
|
|
157
|
+
const dotTranslate = activeEndpoint
|
|
158
|
+
? `translate(${activeEndpoint.x - CLERK_ACTIVE_DOT_RADIUS}px, ${activeEndpoint.y - CLERK_ACTIVE_DOT_RADIUS}px)`
|
|
159
|
+
: undefined;
|
|
160
|
+
const transitionStyle = {
|
|
161
|
+
transitionDuration: `${CLERK_ACTIVE_ANIMATION_DURATION_MS}ms`,
|
|
162
|
+
transitionTimingFunction: CLERK_ACTIVE_ANIMATION_EASING,
|
|
163
|
+
};
|
|
131
164
|
if (!path)
|
|
132
165
|
return null;
|
|
133
|
-
|
|
134
|
-
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("svg", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 z-0 overflow-visible", width: "100%", height: "100%", children: jsxRuntime.jsx("path", { d: path, className: "stroke-fd-foreground/15", fill: "none", strokeWidth: CLERK_PATH_STROKE_WIDTH, strokeLinecap: "round", strokeLinejoin: "round" }) }), jsxRuntime.jsx("svg", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 z-0 overflow-visible", width: "100%", height: "100%", children: activePath ? (jsxRuntime.jsx("path", { d: activePath, fill: "none", strokeWidth: CLERK_PATH_STROKE_WIDTH, strokeLinecap: "round", strokeLinejoin: "round", stroke: lib.themeSvgIconColor })) : null }), jsxRuntime.jsx("svg", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 z-0 overflow-visible", width: "100%", height: "100%", children: activeEndpoint ? (jsxRuntime.jsx("circle", { cx: activeEndpoint.x, cy: activeEndpoint.y, r: CLERK_ACTIVE_DOT_RADIUS, fill: lib.themeSvgIconColor })) : null }), jsxRuntime.jsx("svg", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 z-1 overflow-visible", width: "100%", height: "100%", children: items.map((item) => {
|
|
166
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("svg", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 z-0 overflow-visible", width: "100%", height: "100%", children: jsxRuntime.jsx("path", { d: path, className: "stroke-fd-foreground/15", fill: "none", strokeWidth: CLERK_PATH_STROKE_WIDTH, strokeLinecap: "round", strokeLinejoin: "round" }) }), jsxRuntime.jsxs("svg", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 z-0 overflow-visible", width: "100%", height: "100%", children: [fadingPath ? (jsxRuntime.jsx("path", { d: fadingPath, fill: "none", strokeWidth: CLERK_PATH_STROKE_WIDTH, strokeLinecap: "round", strokeLinejoin: "round", stroke: lib.themeSvgIconColor, className: "transition-opacity", style: Object.assign({ opacity: 0 }, transitionStyle) })) : null, displayPath ? (jsxRuntime.jsx("path", { d: displayPath, fill: "none", strokeWidth: CLERK_PATH_STROKE_WIDTH, strokeLinecap: "round", strokeLinejoin: "round", stroke: lib.themeSvgIconColor, className: "transition-opacity", style: Object.assign({ opacity: 1 }, transitionStyle) })) : null] }), jsxRuntime.jsx("div", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 z-0", children: jsxRuntime.jsx("div", { className: "absolute rounded-full transition-transform", style: Object.assign({ width: CLERK_ACTIVE_DOT_RADIUS * 2, height: CLERK_ACTIVE_DOT_RADIUS * 2, backgroundColor: lib.themeSvgIconColor, transform: dotTranslate, opacity: activeEndpoint ? 1 : 0 }, transitionStyle) }) }), jsxRuntime.jsx("svg", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 z-1 overflow-visible", width: "100%", height: "100%", children: items.map((item) => {
|
|
135
167
|
if (!item.stepNumber)
|
|
136
168
|
return null;
|
|
137
169
|
const isActive = activeSet.has(item.url.slice(1));
|
|
138
|
-
return (jsxRuntime.jsxs("g", { transform: `translate(${item.x}, ${item.y})`, children: [jsxRuntime.jsx("circle", { r:
|
|
170
|
+
return (jsxRuntime.jsxs("g", { transform: `translate(${item.x}, ${item.y})`, children: [jsxRuntime.jsx("circle", { r: CLERK_STEP_BADGE_RADIUS, fill: isActive ? lib.themeSvgIconColor : undefined, className: cn(!isActive && 'fill-black dark:fill-white') }), jsxRuntime.jsx("text", { y: "0.5", textAnchor: "middle", dominantBaseline: "middle", className: "fill-white text-[9px] font-medium dark:fill-black", children: item.stepNumber })] }, item.url));
|
|
139
171
|
}) })] }));
|
|
140
172
|
}
|
|
141
173
|
function getItemOffset(depth) {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
return 26;
|
|
146
|
-
return 36;
|
|
174
|
+
const lineOffset = getLineOffset(depth);
|
|
175
|
+
const badgeRadius = depth === 3 ? CLERK_STEP_BADGE_RADIUS : 0;
|
|
176
|
+
return lineOffset + badgeRadius + CLERK_TEXT_GAP_FROM_PATH;
|
|
147
177
|
}
|
|
148
178
|
function getLineOffset(depth) {
|
|
149
179
|
return depth >= 3 ? 18 : 6;
|
|
@@ -3,7 +3,7 @@ import { __rest } from '../../node_modules/.pnpm/@rollup_plugin-typescript@12.1.
|
|
|
3
3
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
4
4
|
import * as Primitive from 'fumadocs-core/toc';
|
|
5
5
|
import { PageTOC, PageTOCTitle, PageTOCPopover, PageTOCPopoverTrigger, PageTOCPopoverContent } from 'fumadocs-ui/layouts/docs/page';
|
|
6
|
-
import { useRef, useState, useMemo, useLayoutEffect } from 'react';
|
|
6
|
+
import { useRef, useState, useMemo, useLayoutEffect, useEffect } from 'react';
|
|
7
7
|
import { themeSvgIconColor, themeIconColor } from '@windrun-huaiin/base-ui/lib';
|
|
8
8
|
|
|
9
9
|
// Base stroke width for both the inactive rail and the active highlight path.
|
|
@@ -16,6 +16,14 @@ const CLERK_TURN_CURVE_HEIGHT = 12;
|
|
|
16
16
|
const CLERK_TURN_CONTROL_FACTOR = 0.68;
|
|
17
17
|
// Safety margin that keeps turns away from the heading rows themselves.
|
|
18
18
|
const CLERK_TURN_GAP_MARGIN = 7;
|
|
19
|
+
// Shared duration for active rail fade transitions and endpoint dot movement.
|
|
20
|
+
const CLERK_ACTIVE_ANIMATION_DURATION_MS = 300;
|
|
21
|
+
// Easing curve for the active rail and dot; tuned for a slightly delayed, softer motion.
|
|
22
|
+
const CLERK_ACTIVE_ANIMATION_EASING = 'cubic-bezier(0.22, 1, 0.36, 1)';
|
|
23
|
+
// Horizontal gap between the path centerline and the heading text start.
|
|
24
|
+
const CLERK_TEXT_GAP_FROM_PATH = 12;
|
|
25
|
+
// Radius of numbered step badges rendered on top of the path centerline.
|
|
26
|
+
const CLERK_STEP_BADGE_RADIUS = 7;
|
|
19
27
|
function PortableClerkTOC({ toc, header, footer, title, emptyLabel = 'No headings', className, }) {
|
|
20
28
|
return (jsxs(PageTOC, { className: className, children: [header, title !== null && title !== void 0 ? title : jsx(PageTOCTitle, {}), jsx(PortableClerkTOCScrollArea, { children: jsx(PortableClerkTOCItems, { toc: toc, emptyLabel: emptyLabel }) }), footer] }));
|
|
21
29
|
}
|
|
@@ -107,22 +115,44 @@ function PortableClerkTOCItem({ item, isActive, resolvedContent, itemPadding, co
|
|
|
107
115
|
}, className: cn('prose group relative py-1.5 text-sm transition-colors wrap-anywhere first:pt-0 last:pb-0 hover:text-fd-accent-foreground', isActive ? themeIconColor : 'text-fd-muted-foreground'), children: jsx("span", { ref: contentRef, className: "relative z-10", children: resolvedContent }) }));
|
|
108
116
|
}
|
|
109
117
|
function ClerkOutline({ path, items, activePath, activeAnchors, activeEndpoint, }) {
|
|
118
|
+
const activeSet = new Set(activeAnchors);
|
|
119
|
+
const [displayPath, setDisplayPath] = useState(activePath);
|
|
120
|
+
const [fadingPath, setFadingPath] = useState(null);
|
|
121
|
+
useEffect(() => {
|
|
122
|
+
if (activePath === displayPath)
|
|
123
|
+
return;
|
|
124
|
+
if (!displayPath) {
|
|
125
|
+
setDisplayPath(activePath);
|
|
126
|
+
setFadingPath(null);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
setFadingPath(displayPath);
|
|
130
|
+
setDisplayPath(activePath);
|
|
131
|
+
const timeout = window.setTimeout(() => {
|
|
132
|
+
setFadingPath(null);
|
|
133
|
+
}, CLERK_ACTIVE_ANIMATION_DURATION_MS);
|
|
134
|
+
return () => window.clearTimeout(timeout);
|
|
135
|
+
}, [activePath, displayPath]);
|
|
136
|
+
const dotTranslate = activeEndpoint
|
|
137
|
+
? `translate(${activeEndpoint.x - CLERK_ACTIVE_DOT_RADIUS}px, ${activeEndpoint.y - CLERK_ACTIVE_DOT_RADIUS}px)`
|
|
138
|
+
: undefined;
|
|
139
|
+
const transitionStyle = {
|
|
140
|
+
transitionDuration: `${CLERK_ACTIVE_ANIMATION_DURATION_MS}ms`,
|
|
141
|
+
transitionTimingFunction: CLERK_ACTIVE_ANIMATION_EASING,
|
|
142
|
+
};
|
|
110
143
|
if (!path)
|
|
111
144
|
return null;
|
|
112
|
-
|
|
113
|
-
return (jsxs(Fragment, { children: [jsx("svg", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 z-0 overflow-visible", width: "100%", height: "100%", children: jsx("path", { d: path, className: "stroke-fd-foreground/15", fill: "none", strokeWidth: CLERK_PATH_STROKE_WIDTH, strokeLinecap: "round", strokeLinejoin: "round" }) }), jsx("svg", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 z-0 overflow-visible", width: "100%", height: "100%", children: activePath ? (jsx("path", { d: activePath, fill: "none", strokeWidth: CLERK_PATH_STROKE_WIDTH, strokeLinecap: "round", strokeLinejoin: "round", stroke: themeSvgIconColor })) : null }), jsx("svg", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 z-0 overflow-visible", width: "100%", height: "100%", children: activeEndpoint ? (jsx("circle", { cx: activeEndpoint.x, cy: activeEndpoint.y, r: CLERK_ACTIVE_DOT_RADIUS, fill: themeSvgIconColor })) : null }), jsx("svg", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 z-1 overflow-visible", width: "100%", height: "100%", children: items.map((item) => {
|
|
145
|
+
return (jsxs(Fragment, { children: [jsx("svg", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 z-0 overflow-visible", width: "100%", height: "100%", children: jsx("path", { d: path, className: "stroke-fd-foreground/15", fill: "none", strokeWidth: CLERK_PATH_STROKE_WIDTH, strokeLinecap: "round", strokeLinejoin: "round" }) }), jsxs("svg", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 z-0 overflow-visible", width: "100%", height: "100%", children: [fadingPath ? (jsx("path", { d: fadingPath, fill: "none", strokeWidth: CLERK_PATH_STROKE_WIDTH, strokeLinecap: "round", strokeLinejoin: "round", stroke: themeSvgIconColor, className: "transition-opacity", style: Object.assign({ opacity: 0 }, transitionStyle) })) : null, displayPath ? (jsx("path", { d: displayPath, fill: "none", strokeWidth: CLERK_PATH_STROKE_WIDTH, strokeLinecap: "round", strokeLinejoin: "round", stroke: themeSvgIconColor, className: "transition-opacity", style: Object.assign({ opacity: 1 }, transitionStyle) })) : null] }), jsx("div", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 z-0", children: jsx("div", { className: "absolute rounded-full transition-transform", style: Object.assign({ width: CLERK_ACTIVE_DOT_RADIUS * 2, height: CLERK_ACTIVE_DOT_RADIUS * 2, backgroundColor: themeSvgIconColor, transform: dotTranslate, opacity: activeEndpoint ? 1 : 0 }, transitionStyle) }) }), jsx("svg", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 z-1 overflow-visible", width: "100%", height: "100%", children: items.map((item) => {
|
|
114
146
|
if (!item.stepNumber)
|
|
115
147
|
return null;
|
|
116
148
|
const isActive = activeSet.has(item.url.slice(1));
|
|
117
|
-
return (jsxs("g", { transform: `translate(${item.x}, ${item.y})`, children: [jsx("circle", { r:
|
|
149
|
+
return (jsxs("g", { transform: `translate(${item.x}, ${item.y})`, children: [jsx("circle", { r: CLERK_STEP_BADGE_RADIUS, fill: isActive ? themeSvgIconColor : undefined, className: cn(!isActive && 'fill-black dark:fill-white') }), jsx("text", { y: "0.5", textAnchor: "middle", dominantBaseline: "middle", className: "fill-white text-[9px] font-medium dark:fill-black", children: item.stepNumber })] }, item.url));
|
|
118
150
|
}) })] }));
|
|
119
151
|
}
|
|
120
152
|
function getItemOffset(depth) {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
return 26;
|
|
125
|
-
return 36;
|
|
153
|
+
const lineOffset = getLineOffset(depth);
|
|
154
|
+
const badgeRadius = depth === 3 ? CLERK_STEP_BADGE_RADIUS : 0;
|
|
155
|
+
return lineOffset + badgeRadius + CLERK_TEXT_GAP_FROM_PATH;
|
|
126
156
|
}
|
|
127
157
|
function getLineOffset(depth) {
|
|
128
158
|
return depth >= 3 ? 18 : 6;
|
package/package.json
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* References most of its code and SVG animation design from
|
|
5
|
+
* https://github.com/fuma-nama/fumadocs/blob/dev/packages/radix-ui/src/components/toc/clerk.tsx
|
|
6
|
+
*/
|
|
3
7
|
import * as Primitive from 'fumadocs-core/toc';
|
|
4
8
|
import {
|
|
5
9
|
PageTOC,
|
|
@@ -11,6 +15,7 @@ import {
|
|
|
11
15
|
import {
|
|
12
16
|
type ComponentProps,
|
|
13
17
|
type ReactNode,
|
|
18
|
+
useEffect,
|
|
14
19
|
useLayoutEffect,
|
|
15
20
|
useMemo,
|
|
16
21
|
useRef,
|
|
@@ -57,6 +62,14 @@ const CLERK_TURN_CURVE_HEIGHT = 12;
|
|
|
57
62
|
const CLERK_TURN_CONTROL_FACTOR = 0.68;
|
|
58
63
|
// Safety margin that keeps turns away from the heading rows themselves.
|
|
59
64
|
const CLERK_TURN_GAP_MARGIN = 7;
|
|
65
|
+
// Shared duration for active rail fade transitions and endpoint dot movement.
|
|
66
|
+
const CLERK_ACTIVE_ANIMATION_DURATION_MS = 300;
|
|
67
|
+
// Easing curve for the active rail and dot; tuned for a slightly delayed, softer motion.
|
|
68
|
+
const CLERK_ACTIVE_ANIMATION_EASING = 'cubic-bezier(0.22, 1, 0.36, 1)';
|
|
69
|
+
// Horizontal gap between the path centerline and the heading text start.
|
|
70
|
+
const CLERK_TEXT_GAP_FROM_PATH = 12;
|
|
71
|
+
// Radius of numbered step badges rendered on top of the path centerline.
|
|
72
|
+
const CLERK_STEP_BADGE_RADIUS = 7;
|
|
60
73
|
|
|
61
74
|
export function PortableClerkTOC({
|
|
62
75
|
toc,
|
|
@@ -298,9 +311,39 @@ function ClerkOutline({
|
|
|
298
311
|
activeAnchors: string[];
|
|
299
312
|
activeEndpoint: { x: number; y: number } | null;
|
|
300
313
|
}) {
|
|
301
|
-
if (!path) return null;
|
|
302
|
-
|
|
303
314
|
const activeSet = new Set(activeAnchors);
|
|
315
|
+
const [displayPath, setDisplayPath] = useState(activePath);
|
|
316
|
+
const [fadingPath, setFadingPath] = useState<string | null>(null);
|
|
317
|
+
|
|
318
|
+
useEffect(() => {
|
|
319
|
+
if (activePath === displayPath) return;
|
|
320
|
+
if (!displayPath) {
|
|
321
|
+
setDisplayPath(activePath);
|
|
322
|
+
setFadingPath(null);
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
setFadingPath(displayPath);
|
|
327
|
+
setDisplayPath(activePath);
|
|
328
|
+
|
|
329
|
+
const timeout = window.setTimeout(() => {
|
|
330
|
+
setFadingPath(null);
|
|
331
|
+
}, CLERK_ACTIVE_ANIMATION_DURATION_MS);
|
|
332
|
+
|
|
333
|
+
return () => window.clearTimeout(timeout);
|
|
334
|
+
}, [activePath, displayPath]);
|
|
335
|
+
|
|
336
|
+
const dotTranslate = activeEndpoint
|
|
337
|
+
? `translate(${activeEndpoint.x - CLERK_ACTIVE_DOT_RADIUS}px, ${
|
|
338
|
+
activeEndpoint.y - CLERK_ACTIVE_DOT_RADIUS
|
|
339
|
+
}px)`
|
|
340
|
+
: undefined;
|
|
341
|
+
const transitionStyle = {
|
|
342
|
+
transitionDuration: `${CLERK_ACTIVE_ANIMATION_DURATION_MS}ms`,
|
|
343
|
+
transitionTimingFunction: CLERK_ACTIVE_ANIMATION_EASING,
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
if (!path) return null;
|
|
304
347
|
|
|
305
348
|
return (
|
|
306
349
|
<>
|
|
@@ -325,32 +368,50 @@ function ClerkOutline({
|
|
|
325
368
|
width="100%"
|
|
326
369
|
height="100%"
|
|
327
370
|
>
|
|
328
|
-
{
|
|
371
|
+
{fadingPath ? (
|
|
329
372
|
<path
|
|
330
|
-
d={
|
|
373
|
+
d={fadingPath}
|
|
331
374
|
fill="none"
|
|
332
375
|
strokeWidth={CLERK_PATH_STROKE_WIDTH}
|
|
333
376
|
strokeLinecap="round"
|
|
334
377
|
strokeLinejoin="round"
|
|
335
378
|
stroke={themeSvgIconColor}
|
|
379
|
+
className="transition-opacity"
|
|
380
|
+
style={{
|
|
381
|
+
opacity: 0,
|
|
382
|
+
...transitionStyle,
|
|
383
|
+
}}
|
|
336
384
|
/>
|
|
337
385
|
) : null}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
386
|
+
{displayPath ? (
|
|
387
|
+
<path
|
|
388
|
+
d={displayPath}
|
|
389
|
+
fill="none"
|
|
390
|
+
strokeWidth={CLERK_PATH_STROKE_WIDTH}
|
|
391
|
+
strokeLinecap="round"
|
|
392
|
+
strokeLinejoin="round"
|
|
393
|
+
stroke={themeSvgIconColor}
|
|
394
|
+
className="transition-opacity"
|
|
395
|
+
style={{
|
|
396
|
+
opacity: 1,
|
|
397
|
+
...transitionStyle,
|
|
398
|
+
}}
|
|
351
399
|
/>
|
|
352
400
|
) : null}
|
|
353
401
|
</svg>
|
|
402
|
+
<div aria-hidden="true" className="pointer-events-none absolute inset-0 z-0">
|
|
403
|
+
<div
|
|
404
|
+
className="absolute rounded-full transition-transform"
|
|
405
|
+
style={{
|
|
406
|
+
width: CLERK_ACTIVE_DOT_RADIUS * 2,
|
|
407
|
+
height: CLERK_ACTIVE_DOT_RADIUS * 2,
|
|
408
|
+
backgroundColor: themeSvgIconColor,
|
|
409
|
+
transform: dotTranslate,
|
|
410
|
+
opacity: activeEndpoint ? 1 : 0,
|
|
411
|
+
...transitionStyle,
|
|
412
|
+
}}
|
|
413
|
+
/>
|
|
414
|
+
</div>
|
|
354
415
|
<svg
|
|
355
416
|
aria-hidden="true"
|
|
356
417
|
className="pointer-events-none absolute inset-0 z-1 overflow-visible"
|
|
@@ -365,7 +426,7 @@ function ClerkOutline({
|
|
|
365
426
|
return (
|
|
366
427
|
<g key={item.url} transform={`translate(${item.x}, ${item.y})`}>
|
|
367
428
|
<circle
|
|
368
|
-
r=
|
|
429
|
+
r={CLERK_STEP_BADGE_RADIUS}
|
|
369
430
|
fill={isActive ? themeSvgIconColor : undefined}
|
|
370
431
|
className={cn(!isActive && 'fill-black dark:fill-white')}
|
|
371
432
|
/>
|
|
@@ -386,9 +447,9 @@ function ClerkOutline({
|
|
|
386
447
|
}
|
|
387
448
|
|
|
388
449
|
function getItemOffset(depth: number): number {
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
return
|
|
450
|
+
const lineOffset = getLineOffset(depth);
|
|
451
|
+
const badgeRadius = depth === 3 ? CLERK_STEP_BADGE_RADIUS : 0;
|
|
452
|
+
return lineOffset + badgeRadius + CLERK_TEXT_GAP_FROM_PATH;
|
|
392
453
|
}
|
|
393
454
|
|
|
394
455
|
function getLineOffset(depth: number): number {
|
|
@@ -614,7 +675,7 @@ function mergeRefs<T>(
|
|
|
614
675
|
}
|
|
615
676
|
|
|
616
677
|
try {
|
|
617
|
-
(ref as React.
|
|
678
|
+
(ref as React.RefObject<T | null>).current = node;
|
|
618
679
|
} catch {
|
|
619
680
|
// ignore readonly refs
|
|
620
681
|
}
|