@expcat/tigercat-react 2.1.4 → 2.3.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/dist/chunk-2MV3F7WP.mjs +56 -0
- package/dist/{chunk-SUHSOVWP.mjs → chunk-6T5AEQJV.mjs} +1 -1
- package/dist/{chunk-R2VBVZIH.mjs → chunk-75SQCTLC.mjs} +4 -4
- package/dist/{chunk-73OFTRG5.mjs → chunk-AHQR57Z4.mjs} +1 -1
- package/dist/{chunk-2STETY2J.mjs → chunk-CCFKRKGJ.mjs} +12 -6
- package/dist/{chunk-UNT7WJ2M.mjs → chunk-DNRLMEKE.mjs} +10 -3
- package/dist/chunk-F4XF5CGQ.mjs +72 -0
- package/dist/chunk-FZQUUTWN.mjs +145 -0
- package/dist/{chunk-NPXT436C.mjs → chunk-MMDVFCCL.mjs} +1 -1
- package/dist/chunk-NCVZCG4W.mjs +138 -0
- package/dist/{chunk-25BKSXTX.mjs → chunk-NMRCBGFP.mjs} +1 -1
- package/dist/chunk-REHHFHZ3.mjs +67 -0
- package/dist/{chunk-XI6KQAHW.mjs → chunk-RJ2FJXHT.mjs} +5 -6
- package/dist/{chunk-WN6ZHQTI.mjs → chunk-SIBNSFVR.mjs} +10 -4
- package/dist/{chunk-3WP4PGHF.mjs → chunk-TFHQODGK.mjs} +7 -1
- package/dist/{chunk-IR45LOEZ.mjs → chunk-UGKTSPS4.mjs} +38 -4
- package/dist/components/ActivityFeed.mjs +2 -2
- package/dist/components/Anchor.mjs +1 -1
- package/dist/components/BackTop.mjs +1 -1
- package/dist/components/Badge.d.mts +1 -1
- package/dist/components/Calendar.mjs +1 -1
- package/dist/components/Code.mjs +1 -1
- package/dist/components/CommentThread.mjs +2 -2
- package/dist/components/DataTableWithToolbar.mjs +1 -1
- package/dist/components/DatePicker.mjs +2 -2
- package/dist/components/Drag.d.mts +17 -0
- package/dist/components/Drag.mjs +9 -0
- package/dist/components/Footer.mjs +1 -1
- package/dist/components/FullscreenButton.d.mts +8 -0
- package/dist/components/FullscreenButton.mjs +10 -0
- package/dist/components/Menu.mjs +1 -1
- package/dist/components/NotificationCenter.mjs +2 -2
- package/dist/components/Popconfirm.d.mts +1 -1
- package/dist/components/Popover.d.mts +1 -1
- package/dist/components/ScrollSpy.mjs +1 -1
- package/dist/components/Segmented.d.mts +1 -1
- package/dist/components/Space.d.mts +1 -1
- package/dist/components/Text.d.mts +6 -2
- package/dist/components/Text.mjs +2 -1
- package/dist/components/Tooltip.d.mts +1 -1
- package/dist/components/WorkflowTimeline.d.mts +20 -0
- package/dist/components/WorkflowTimeline.mjs +15 -0
- package/dist/hooks/useFullscreen.d.mts +13 -0
- package/dist/hooks/useFullscreen.mjs +6 -0
- package/dist/index.d.mts +6 -2
- package/dist/index.mjs +64 -0
- package/package.json +27 -2
- package/dist/chunk-VDBLI5Y3.mjs +0 -33
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// src/hooks/useFullscreen.ts
|
|
2
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
3
|
+
import {
|
|
4
|
+
exitElementFullscreen,
|
|
5
|
+
getFullscreenElement,
|
|
6
|
+
isElementFullscreen,
|
|
7
|
+
isFullscreenSupported,
|
|
8
|
+
requestElementFullscreen,
|
|
9
|
+
resolveFullscreenTarget,
|
|
10
|
+
subscribeFullscreenChange
|
|
11
|
+
} from "@expcat/tigercat-core";
|
|
12
|
+
function useFullscreen(options = {}) {
|
|
13
|
+
const optionsRef = useRef(options);
|
|
14
|
+
optionsRef.current = options;
|
|
15
|
+
const [supported] = useState(() => isFullscreenSupported());
|
|
16
|
+
const [isFullscreen, setIsFullscreen] = useState(false);
|
|
17
|
+
const sync = useCallback(() => {
|
|
18
|
+
const target = resolveFullscreenTarget(optionsRef.current.target);
|
|
19
|
+
const next = isElementFullscreen(target);
|
|
20
|
+
setIsFullscreen(next);
|
|
21
|
+
optionsRef.current.onChange?.(next);
|
|
22
|
+
}, []);
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
sync();
|
|
25
|
+
return subscribeFullscreenChange(sync);
|
|
26
|
+
}, [sync]);
|
|
27
|
+
const enter = useCallback(async () => {
|
|
28
|
+
const target = resolveFullscreenTarget(optionsRef.current.target);
|
|
29
|
+
if (!target) return;
|
|
30
|
+
if (isElementFullscreen(target)) return;
|
|
31
|
+
try {
|
|
32
|
+
await requestElementFullscreen(target);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
const err = error instanceof Error ? error : new Error("Fullscreen request failed");
|
|
35
|
+
optionsRef.current.onError?.(err);
|
|
36
|
+
}
|
|
37
|
+
}, []);
|
|
38
|
+
const exit = useCallback(async () => {
|
|
39
|
+
if (!getFullscreenElement()) return;
|
|
40
|
+
try {
|
|
41
|
+
await exitElementFullscreen();
|
|
42
|
+
} catch (error) {
|
|
43
|
+
const err = error instanceof Error ? error : new Error("Fullscreen exit failed");
|
|
44
|
+
optionsRef.current.onError?.(err);
|
|
45
|
+
}
|
|
46
|
+
}, []);
|
|
47
|
+
const toggle = useCallback(async () => {
|
|
48
|
+
if (isFullscreen) await exit();
|
|
49
|
+
else await enter();
|
|
50
|
+
}, [enter, exit, isFullscreen]);
|
|
51
|
+
return { isFullscreen, supported, enter, exit, toggle };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export {
|
|
55
|
+
useFullscreen
|
|
56
|
+
};
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
import { forwardRef } from "react";
|
|
3
3
|
import {
|
|
4
4
|
classNames,
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
getLayoutFooterClasses,
|
|
6
|
+
injectLayoutGridStyles
|
|
7
7
|
} from "@expcat/tigercat-core";
|
|
8
8
|
import { jsx } from "react/jsx-runtime";
|
|
9
|
-
var Footer = forwardRef(function Footer2({ className, height, style, as = "footer", children, ...props }, ref) {
|
|
9
|
+
var Footer = forwardRef(function Footer2({ className, height, size = "default", style, as = "footer", children, ...props }, ref) {
|
|
10
10
|
injectLayoutGridStyles();
|
|
11
|
-
const footerClasses = classNames(
|
|
11
|
+
const footerClasses = classNames(getLayoutFooterClasses(size), className);
|
|
12
12
|
const footerStyle = height ? { ...style, height } : style;
|
|
13
13
|
const Tag = as;
|
|
14
14
|
return /* @__PURE__ */ jsx(Tag, { ref, className: footerClasses, style: footerStyle, ...props, children });
|
|
@@ -65,13 +65,18 @@ var ScrollSpy = forwardRef(function ScrollSpy2({
|
|
|
65
65
|
const flatItems = useMemo(() => flattenScrollSpyItems(items), [items]);
|
|
66
66
|
const activeKeyRef = useRef(currentActiveKey);
|
|
67
67
|
activeKeyRef.current = currentActiveKey;
|
|
68
|
-
const
|
|
68
|
+
const hostRef = useRef(null);
|
|
69
|
+
const setHostRef = (node) => {
|
|
70
|
+
hostRef.current = node;
|
|
71
|
+
if (typeof ref === "function") ref(node);
|
|
72
|
+
else if (ref) ref.current = node;
|
|
73
|
+
};
|
|
74
|
+
const resolvedContainer = resolveScrollSpyContainer(getContainer, hostRef.current);
|
|
69
75
|
const containerKey = resolvedContainer === window ? "window" : resolvedContainer;
|
|
70
76
|
const getContainerRef = useRef(getContainer);
|
|
71
77
|
getContainerRef.current = getContainer;
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
);
|
|
78
|
+
const resolveContainer = () => resolveScrollSpyContainer(getContainerRef.current, hostRef.current);
|
|
79
|
+
const scrollLockRef = useRef(createProgrammaticScrollLock(() => resolveContainer()));
|
|
75
80
|
const emitActive = useCallback(
|
|
76
81
|
(item, source) => {
|
|
77
82
|
const nextKeyString = getScrollSpyKeyString(item.key);
|
|
@@ -85,6 +90,7 @@ var ScrollSpy = forwardRef(function ScrollSpy2({
|
|
|
85
90
|
useEffect(() => {
|
|
86
91
|
return createScrollSpyObserver(items, {
|
|
87
92
|
container: getContainerRef.current,
|
|
93
|
+
from: hostRef.current,
|
|
88
94
|
offsetTop: offset,
|
|
89
95
|
bounds,
|
|
90
96
|
onChange: (item) => {
|
|
@@ -110,7 +116,7 @@ var ScrollSpy = forwardRef(function ScrollSpy2({
|
|
|
110
116
|
onClick?.(item, event);
|
|
111
117
|
emitActive(item, "click");
|
|
112
118
|
scrollLockRef.current.lock();
|
|
113
|
-
activateScrollSpyClick(item,
|
|
119
|
+
activateScrollSpyClick(item, resolveContainer(), offset);
|
|
114
120
|
},
|
|
115
121
|
[emitActive, offset, onClick]
|
|
116
122
|
);
|
|
@@ -144,7 +150,7 @@ var ScrollSpy = forwardRef(function ScrollSpy2({
|
|
|
144
150
|
"nav",
|
|
145
151
|
{
|
|
146
152
|
...rest,
|
|
147
|
-
ref,
|
|
153
|
+
ref: setHostRef,
|
|
148
154
|
className: classNames(getScrollSpyRootClasses(sticky, className)),
|
|
149
155
|
style: getScrollSpyRootStyle(sticky, offset, style),
|
|
150
156
|
"aria-label": ariaLabel ?? labels.ariaLabel,
|
|
@@ -50,7 +50,9 @@ import {
|
|
|
50
50
|
reconcileSearchOpenKeys,
|
|
51
51
|
resolveMenuCollapsed,
|
|
52
52
|
resolveMenuMode,
|
|
53
|
+
resolveMenuSearchQuery,
|
|
53
54
|
resolveSearchFilter,
|
|
55
|
+
shouldShowMenuSearch,
|
|
54
56
|
warnControlledSearchOpenKeys
|
|
55
57
|
} from "@expcat/tigercat-core";
|
|
56
58
|
|
|
@@ -201,9 +203,14 @@ function useMenuRootState(props) {
|
|
|
201
203
|
},
|
|
202
204
|
[setSearchValue]
|
|
203
205
|
);
|
|
206
|
+
const showSearch = shouldShowMenuSearch(searchable, collapsed);
|
|
204
207
|
const { filtered: filteredItems, expandKeys } = useMemo(
|
|
205
|
-
() => resolveSearchFilter({
|
|
206
|
-
|
|
208
|
+
() => resolveSearchFilter({
|
|
209
|
+
items,
|
|
210
|
+
query: resolveMenuSearchQuery(searchable, collapsed, searchValue),
|
|
211
|
+
filterMode
|
|
212
|
+
}),
|
|
213
|
+
[items, searchValue, filterMode, searchable, collapsed]
|
|
207
214
|
);
|
|
208
215
|
useEffect(() => {
|
|
209
216
|
const current = openKeysRef.current;
|
|
@@ -285,7 +292,7 @@ function useMenuRootState(props) {
|
|
|
285
292
|
resolvedMode,
|
|
286
293
|
mode,
|
|
287
294
|
contextValue,
|
|
288
|
-
searchable,
|
|
295
|
+
searchable: showSearch,
|
|
289
296
|
searchValue,
|
|
290
297
|
searchPlaceholder: searchPlaceholder ?? locale?.common?.searchPlaceholder ?? "Search",
|
|
291
298
|
emptyText: emptyText ?? locale?.common?.emptyText ?? "No data",
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useDrag
|
|
3
|
+
} from "./chunk-REJVXLW5.mjs";
|
|
4
|
+
|
|
5
|
+
// src/components/Drag.tsx
|
|
6
|
+
import React from "react";
|
|
7
|
+
import {
|
|
8
|
+
classNames,
|
|
9
|
+
reorderSequence
|
|
10
|
+
} from "@expcat/tigercat-core";
|
|
11
|
+
import { jsx } from "react/jsx-runtime";
|
|
12
|
+
function Drag({
|
|
13
|
+
items = [],
|
|
14
|
+
onItemsChange,
|
|
15
|
+
config,
|
|
16
|
+
containerId,
|
|
17
|
+
onDragStart,
|
|
18
|
+
onDragOver,
|
|
19
|
+
onDrop,
|
|
20
|
+
onDragEnd,
|
|
21
|
+
className,
|
|
22
|
+
children,
|
|
23
|
+
renderItem
|
|
24
|
+
}) {
|
|
25
|
+
const itemsRef = React.useRef(items);
|
|
26
|
+
itemsRef.current = items;
|
|
27
|
+
const onItemsChangeRef = React.useRef(onItemsChange);
|
|
28
|
+
onItemsChangeRef.current = onItemsChange;
|
|
29
|
+
const onDropRef = React.useRef(onDrop);
|
|
30
|
+
onDropRef.current = onDrop;
|
|
31
|
+
const drag = useDrag({
|
|
32
|
+
config,
|
|
33
|
+
containerId,
|
|
34
|
+
onDragStart,
|
|
35
|
+
onDragOver,
|
|
36
|
+
onDragEnd,
|
|
37
|
+
onDrop: (event) => {
|
|
38
|
+
onDropRef.current?.(event);
|
|
39
|
+
if (event.fromIndex === event.toIndex) return;
|
|
40
|
+
const next = reorderSequence(itemsRef.current, event.fromIndex, event.toIndex).map(
|
|
41
|
+
(item, index) => ({ ...item, index })
|
|
42
|
+
);
|
|
43
|
+
onItemsChangeRef.current?.(next);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
const render = children ?? renderItem;
|
|
47
|
+
const zoneProps = drag.getDropZoneProps();
|
|
48
|
+
return /* @__PURE__ */ jsx(
|
|
49
|
+
"ul",
|
|
50
|
+
{
|
|
51
|
+
...zoneProps,
|
|
52
|
+
className: classNames("m-0 list-none p-0", className),
|
|
53
|
+
"data-tiger-drag": "",
|
|
54
|
+
role: "list",
|
|
55
|
+
children: items.map((item) => {
|
|
56
|
+
const itemProps = drag.getDragItemProps(item);
|
|
57
|
+
const node = render?.(item, {
|
|
58
|
+
dragItemProps: itemProps,
|
|
59
|
+
isDragging: drag.draggedItem?.id === item.id
|
|
60
|
+
});
|
|
61
|
+
return /* @__PURE__ */ jsx(React.Fragment, { children: node ?? /* @__PURE__ */ jsx("li", { ...itemProps, role: "listitem", children: String(item.id) }) }, item.id);
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
Drag.displayName = "Drag";
|
|
67
|
+
var Drag_default = Drag;
|
|
68
|
+
|
|
69
|
+
export {
|
|
70
|
+
Drag,
|
|
71
|
+
Drag_default
|
|
72
|
+
};
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useTigerConfig
|
|
3
|
+
} from "./chunk-RUIFGSVN.mjs";
|
|
4
|
+
|
|
5
|
+
// src/components/Text.tsx
|
|
6
|
+
import React, { forwardRef, useEffect, useMemo, useRef, useState } from "react";
|
|
7
|
+
import {
|
|
8
|
+
classNames,
|
|
9
|
+
copyTextToClipboard,
|
|
10
|
+
createCopyStatusReset,
|
|
11
|
+
getCodeLabels,
|
|
12
|
+
getIconDefinition,
|
|
13
|
+
getTextClasses,
|
|
14
|
+
isTextCopyable,
|
|
15
|
+
mergeTigerLocale,
|
|
16
|
+
resolveLocaleText,
|
|
17
|
+
resolveTextCopyableOptions,
|
|
18
|
+
resolveTextCopyContent,
|
|
19
|
+
resolveTextTag,
|
|
20
|
+
textCopyableBodyClasses,
|
|
21
|
+
textCopyableButtonClasses,
|
|
22
|
+
textCopyableLiveClasses,
|
|
23
|
+
textCopyableRootClasses
|
|
24
|
+
} from "@expcat/tigercat-core";
|
|
25
|
+
import { jsx } from "react/jsx-runtime";
|
|
26
|
+
var copyIcon = getIconDefinition("copy");
|
|
27
|
+
function CopyGlyph() {
|
|
28
|
+
if (!copyIcon) return null;
|
|
29
|
+
return /* @__PURE__ */ jsx(
|
|
30
|
+
"svg",
|
|
31
|
+
{
|
|
32
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
33
|
+
viewBox: copyIcon.viewBox,
|
|
34
|
+
fill: "none",
|
|
35
|
+
stroke: "currentColor",
|
|
36
|
+
strokeWidth: "1.5",
|
|
37
|
+
strokeLinecap: "round",
|
|
38
|
+
strokeLinejoin: "round",
|
|
39
|
+
className: "h-3.5 w-3.5",
|
|
40
|
+
"aria-hidden": "true",
|
|
41
|
+
children: copyIcon.paths.map((d, i) => /* @__PURE__ */ jsx("path", { d }, i))
|
|
42
|
+
}
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
var Text = forwardRef(function Text2({
|
|
46
|
+
tag = "p",
|
|
47
|
+
size,
|
|
48
|
+
weight,
|
|
49
|
+
align,
|
|
50
|
+
color,
|
|
51
|
+
truncate,
|
|
52
|
+
italic,
|
|
53
|
+
underline,
|
|
54
|
+
lineThrough,
|
|
55
|
+
copyable,
|
|
56
|
+
locale,
|
|
57
|
+
children,
|
|
58
|
+
className,
|
|
59
|
+
onCopy,
|
|
60
|
+
...props
|
|
61
|
+
}, ref) {
|
|
62
|
+
const resolvedTag = resolveTextTag(tag);
|
|
63
|
+
const copyEnabled = isTextCopyable(copyable);
|
|
64
|
+
const copyOptions = resolveTextCopyableOptions(copyable);
|
|
65
|
+
const textClasses = classNames(
|
|
66
|
+
getTextClasses({
|
|
67
|
+
size,
|
|
68
|
+
weight,
|
|
69
|
+
align,
|
|
70
|
+
color,
|
|
71
|
+
truncate,
|
|
72
|
+
italic,
|
|
73
|
+
underline,
|
|
74
|
+
lineThrough,
|
|
75
|
+
copyable
|
|
76
|
+
}),
|
|
77
|
+
!copyEnabled && className
|
|
78
|
+
);
|
|
79
|
+
const config = useTigerConfig();
|
|
80
|
+
const mergedLocale = useMemo(
|
|
81
|
+
() => mergeTigerLocale(config.locale, locale),
|
|
82
|
+
[config.locale, locale]
|
|
83
|
+
);
|
|
84
|
+
const labels = useMemo(() => getCodeLabels(mergedLocale), [mergedLocale]);
|
|
85
|
+
const idleLabel = resolveLocaleText(labels.copyLabel, copyOptions?.tooltip);
|
|
86
|
+
const [copyStatus, setCopyStatus] = useState("idle");
|
|
87
|
+
const resetRef = useRef(null);
|
|
88
|
+
if (resetRef.current == null) {
|
|
89
|
+
resetRef.current = createCopyStatusReset(setCopyStatus);
|
|
90
|
+
}
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
const machine = resetRef.current;
|
|
93
|
+
return () => machine?.dispose();
|
|
94
|
+
}, []);
|
|
95
|
+
const bodyRef = useRef(null);
|
|
96
|
+
const buttonLabel = copyStatus === "failed" ? labels.copyFailedLabel : copyStatus === "copied" ? labels.copiedLabel : idleLabel;
|
|
97
|
+
const liveText = copyStatus === "idle" ? "" : buttonLabel;
|
|
98
|
+
const handleCopy = async () => {
|
|
99
|
+
if (!copyOptions) return;
|
|
100
|
+
const fallback = bodyRef.current?.textContent ?? "";
|
|
101
|
+
const text = resolveTextCopyContent(copyOptions, fallback);
|
|
102
|
+
const ok = await copyTextToClipboard(text);
|
|
103
|
+
if (ok) {
|
|
104
|
+
resetRef.current?.schedule("copied");
|
|
105
|
+
copyOptions.onCopy?.(text);
|
|
106
|
+
onCopy?.(text);
|
|
107
|
+
} else {
|
|
108
|
+
resetRef.current?.schedule("failed");
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
if (!copyEnabled) {
|
|
112
|
+
return React.createElement(resolvedTag, { ...props, ref, className: textClasses }, children);
|
|
113
|
+
}
|
|
114
|
+
return React.createElement(
|
|
115
|
+
resolvedTag,
|
|
116
|
+
{ ...props, ref, className: classNames(textCopyableRootClasses, className) },
|
|
117
|
+
/* @__PURE__ */ jsx(
|
|
118
|
+
"span",
|
|
119
|
+
{
|
|
120
|
+
ref: bodyRef,
|
|
121
|
+
className: classNames(textCopyableBodyClasses, truncate && "truncate", textClasses),
|
|
122
|
+
children
|
|
123
|
+
}
|
|
124
|
+
),
|
|
125
|
+
/* @__PURE__ */ jsx(
|
|
126
|
+
"button",
|
|
127
|
+
{
|
|
128
|
+
type: "button",
|
|
129
|
+
className: textCopyableButtonClasses,
|
|
130
|
+
"aria-label": buttonLabel,
|
|
131
|
+
title: buttonLabel,
|
|
132
|
+
onClick: () => {
|
|
133
|
+
void handleCopy();
|
|
134
|
+
},
|
|
135
|
+
children: /* @__PURE__ */ jsx(CopyGlyph, {})
|
|
136
|
+
}
|
|
137
|
+
),
|
|
138
|
+
/* @__PURE__ */ jsx("span", { className: textCopyableLiveClasses, "aria-live": "polite", children: liveText })
|
|
139
|
+
);
|
|
140
|
+
});
|
|
141
|
+
Text.displayName = "Text";
|
|
142
|
+
|
|
143
|
+
export {
|
|
144
|
+
Text
|
|
145
|
+
};
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Timeline
|
|
3
|
+
} from "./chunk-4DFN6RZ4.mjs";
|
|
4
|
+
import {
|
|
5
|
+
Tag
|
|
6
|
+
} from "./chunk-FVA5VKN2.mjs";
|
|
7
|
+
import {
|
|
8
|
+
Button
|
|
9
|
+
} from "./chunk-WFLXJOFU.mjs";
|
|
10
|
+
|
|
11
|
+
// src/components/WorkflowTimeline.tsx
|
|
12
|
+
import { useMemo } from "react";
|
|
13
|
+
import {
|
|
14
|
+
classNames,
|
|
15
|
+
resolveWorkflowActionButtonProps,
|
|
16
|
+
shouldShowWorkflowActions,
|
|
17
|
+
timelineDescriptionClasses,
|
|
18
|
+
timelineLabelClasses,
|
|
19
|
+
workflowStepsToTimelineItems,
|
|
20
|
+
workflowStepStatusLabel,
|
|
21
|
+
workflowStepStatusTagVariant
|
|
22
|
+
} from "@expcat/tigercat-core";
|
|
23
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
24
|
+
var workflowTimelineRootClasses = "flex flex-col gap-4";
|
|
25
|
+
var workflowActionBarClasses = "flex flex-wrap items-center gap-2";
|
|
26
|
+
var workflowStepHeaderClasses = "flex flex-wrap items-center gap-2";
|
|
27
|
+
var workflowStepActorClasses = "text-sm text-[var(--tiger-text-muted,#6b7280)]";
|
|
28
|
+
var workflowStepCommentClasses = "text-sm text-[var(--tiger-text-secondary,#4b5563)] mt-1";
|
|
29
|
+
function isWorkflowTimelineItem(item) {
|
|
30
|
+
return typeof item === "object" && item != null && "step" in item && "status" in item && typeof item.status === "string";
|
|
31
|
+
}
|
|
32
|
+
function renderStepContent(item) {
|
|
33
|
+
const step = item.step;
|
|
34
|
+
const title = step.title ?? step.label;
|
|
35
|
+
const statusLabel = workflowStepStatusLabel(item.status);
|
|
36
|
+
return /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
37
|
+
step.time ? /* @__PURE__ */ jsx("div", { className: timelineLabelClasses, children: step.time }) : null,
|
|
38
|
+
/* @__PURE__ */ jsxs("div", { className: workflowStepHeaderClasses, children: [
|
|
39
|
+
title ? /* @__PURE__ */ jsx("div", { className: timelineDescriptionClasses, children: title }) : null,
|
|
40
|
+
/* @__PURE__ */ jsx(Tag, { variant: workflowStepStatusTagVariant(item.status), size: "sm", pill: true, children: statusLabel })
|
|
41
|
+
] }),
|
|
42
|
+
step.actor?.name ? /* @__PURE__ */ jsx("div", { className: workflowStepActorClasses, children: step.actor.name }) : null,
|
|
43
|
+
step.comment ? /* @__PURE__ */ jsx("div", { className: workflowStepCommentClasses, children: step.comment }) : null
|
|
44
|
+
] });
|
|
45
|
+
}
|
|
46
|
+
var WorkflowActionBar = ({
|
|
47
|
+
items,
|
|
48
|
+
disabled,
|
|
49
|
+
ariaLabel,
|
|
50
|
+
className,
|
|
51
|
+
style,
|
|
52
|
+
onAction,
|
|
53
|
+
"aria-label": ariaLabelAttr,
|
|
54
|
+
...rest
|
|
55
|
+
}) => {
|
|
56
|
+
const toolbarClasses = useMemo(() => classNames(workflowActionBarClasses, className), [className]);
|
|
57
|
+
return /* @__PURE__ */ jsx(
|
|
58
|
+
"div",
|
|
59
|
+
{
|
|
60
|
+
...rest,
|
|
61
|
+
className: toolbarClasses,
|
|
62
|
+
style,
|
|
63
|
+
role: "toolbar",
|
|
64
|
+
"aria-label": ariaLabel ?? ariaLabelAttr ?? "Workflow actions",
|
|
65
|
+
children: (items ?? []).map((item) => {
|
|
66
|
+
const buttonProps = resolveWorkflowActionButtonProps(item);
|
|
67
|
+
const isDisabled = Boolean(disabled || item.disabled);
|
|
68
|
+
return /* @__PURE__ */ jsx(
|
|
69
|
+
Button,
|
|
70
|
+
{
|
|
71
|
+
size: "sm",
|
|
72
|
+
variant: buttonProps.variant,
|
|
73
|
+
danger: buttonProps.danger,
|
|
74
|
+
disabled: isDisabled,
|
|
75
|
+
onClick: () => {
|
|
76
|
+
if (isDisabled) return;
|
|
77
|
+
onAction?.(item);
|
|
78
|
+
},
|
|
79
|
+
children: item.label
|
|
80
|
+
},
|
|
81
|
+
item.key
|
|
82
|
+
);
|
|
83
|
+
})
|
|
84
|
+
}
|
|
85
|
+
);
|
|
86
|
+
};
|
|
87
|
+
var WorkflowTimeline = ({
|
|
88
|
+
steps,
|
|
89
|
+
actions,
|
|
90
|
+
showActions,
|
|
91
|
+
mode = "left",
|
|
92
|
+
pending = false,
|
|
93
|
+
pendingDot,
|
|
94
|
+
pendingContent,
|
|
95
|
+
reverse = false,
|
|
96
|
+
className,
|
|
97
|
+
style,
|
|
98
|
+
onAction,
|
|
99
|
+
renderItem,
|
|
100
|
+
renderDot,
|
|
101
|
+
renderActions,
|
|
102
|
+
"aria-label": ariaLabel,
|
|
103
|
+
...rest
|
|
104
|
+
}) => {
|
|
105
|
+
const timelineItems = useMemo(() => workflowStepsToTimelineItems(steps), [steps]);
|
|
106
|
+
const showActionBar = shouldShowWorkflowActions(steps, actions, showActions);
|
|
107
|
+
const rootClasses = useMemo(() => classNames(workflowTimelineRootClasses, className), [className]);
|
|
108
|
+
const handleRenderItem = (item, index) => {
|
|
109
|
+
if (renderItem) return renderItem(item, index);
|
|
110
|
+
if (isWorkflowTimelineItem(item)) return renderStepContent(item);
|
|
111
|
+
return null;
|
|
112
|
+
};
|
|
113
|
+
const actionBar = showActionBar && actions ? renderActions ? renderActions(actions) : /* @__PURE__ */ jsx(WorkflowActionBar, { items: actions, onAction }) : null;
|
|
114
|
+
return /* @__PURE__ */ jsxs("div", { ...rest, className: rootClasses, style, children: [
|
|
115
|
+
/* @__PURE__ */ jsx(
|
|
116
|
+
Timeline,
|
|
117
|
+
{
|
|
118
|
+
items: timelineItems,
|
|
119
|
+
mode,
|
|
120
|
+
pending,
|
|
121
|
+
pendingDot,
|
|
122
|
+
pendingContent,
|
|
123
|
+
reverse,
|
|
124
|
+
renderItem: handleRenderItem,
|
|
125
|
+
renderDot,
|
|
126
|
+
"aria-label": ariaLabel ?? "Workflow timeline"
|
|
127
|
+
}
|
|
128
|
+
),
|
|
129
|
+
actionBar
|
|
130
|
+
] });
|
|
131
|
+
};
|
|
132
|
+
var WorkflowTimeline_default = WorkflowTimeline;
|
|
133
|
+
|
|
134
|
+
export {
|
|
135
|
+
WorkflowActionBar,
|
|
136
|
+
WorkflowTimeline,
|
|
137
|
+
WorkflowTimeline_default
|
|
138
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useFullscreen
|
|
3
|
+
} from "./chunk-2MV3F7WP.mjs";
|
|
4
|
+
import {
|
|
5
|
+
useTigerConfig
|
|
6
|
+
} from "./chunk-RUIFGSVN.mjs";
|
|
7
|
+
|
|
8
|
+
// src/components/FullscreenButton.tsx
|
|
9
|
+
import { forwardRef } from "react";
|
|
10
|
+
import {
|
|
11
|
+
classNames,
|
|
12
|
+
fullscreenButtonClasses,
|
|
13
|
+
getFullscreenLabels,
|
|
14
|
+
getIconDefinition,
|
|
15
|
+
mergeTigerLocale
|
|
16
|
+
} from "@expcat/tigercat-core";
|
|
17
|
+
import { jsx } from "react/jsx-runtime";
|
|
18
|
+
function Glyph({ name }) {
|
|
19
|
+
const definition = getIconDefinition(name);
|
|
20
|
+
if (!definition) return null;
|
|
21
|
+
return /* @__PURE__ */ jsx(
|
|
22
|
+
"svg",
|
|
23
|
+
{
|
|
24
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
25
|
+
viewBox: definition.viewBox,
|
|
26
|
+
fill: "none",
|
|
27
|
+
stroke: "currentColor",
|
|
28
|
+
strokeWidth: "1.5",
|
|
29
|
+
strokeLinecap: "round",
|
|
30
|
+
strokeLinejoin: "round",
|
|
31
|
+
className: "h-5 w-5",
|
|
32
|
+
"aria-hidden": "true",
|
|
33
|
+
children: definition.paths.map((d, i) => /* @__PURE__ */ jsx("path", { d }, i))
|
|
34
|
+
}
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
var FullscreenButton = forwardRef(
|
|
38
|
+
function FullscreenButton2({ target, locale, labels, className, onChange, onError, ...props }, ref) {
|
|
39
|
+
const config = useTigerConfig();
|
|
40
|
+
const labelSet = getFullscreenLabels(mergeTigerLocale(config.locale, locale), labels);
|
|
41
|
+
const fullscreen = useFullscreen({ target, onChange, onError });
|
|
42
|
+
const label = fullscreen.isFullscreen ? labelSet.exitAriaLabel : labelSet.enterAriaLabel;
|
|
43
|
+
return /* @__PURE__ */ jsx(
|
|
44
|
+
"button",
|
|
45
|
+
{
|
|
46
|
+
...props,
|
|
47
|
+
ref,
|
|
48
|
+
type: "button",
|
|
49
|
+
className: classNames(fullscreenButtonClasses, className),
|
|
50
|
+
"aria-label": label,
|
|
51
|
+
"aria-pressed": fullscreen.isFullscreen,
|
|
52
|
+
disabled: !fullscreen.supported,
|
|
53
|
+
onClick: () => {
|
|
54
|
+
void fullscreen.toggle();
|
|
55
|
+
},
|
|
56
|
+
children: /* @__PURE__ */ jsx(Glyph, { name: fullscreen.isFullscreen ? "fullscreen-exit" : "fullscreen" })
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
);
|
|
61
|
+
FullscreenButton.displayName = "FullscreenButton";
|
|
62
|
+
var FullscreenButton_default = FullscreenButton;
|
|
63
|
+
|
|
64
|
+
export {
|
|
65
|
+
FullscreenButton,
|
|
66
|
+
FullscreenButton_default
|
|
67
|
+
};
|
|
@@ -122,9 +122,8 @@ var Anchor = forwardRef(function Anchor2({
|
|
|
122
122
|
getCurrentAnchorRef.current = getCurrentAnchor;
|
|
123
123
|
const onChangeRef = useRef(onChange);
|
|
124
124
|
onChangeRef.current = onChange;
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
);
|
|
125
|
+
const resolveContainer = () => resolveAnchorScrollContainer(getContainerRef.current, anchorRef.current);
|
|
126
|
+
const scrollLockRef = useRef(createProgrammaticScrollLock(() => resolveContainer()));
|
|
128
127
|
const config = useTigerConfig();
|
|
129
128
|
const mergedLocale = useMemo(
|
|
130
129
|
() => mergeTigerLocale(config.locale, locale),
|
|
@@ -158,7 +157,7 @@ var Anchor = forwardRef(function Anchor2({
|
|
|
158
157
|
}, []);
|
|
159
158
|
const scrollTo = useCallback(
|
|
160
159
|
(href) => {
|
|
161
|
-
const container =
|
|
160
|
+
const container = resolveContainer();
|
|
162
161
|
scrollToAnchor(href, container, scrollOffset);
|
|
163
162
|
},
|
|
164
163
|
[scrollOffset]
|
|
@@ -182,10 +181,10 @@ var Anchor = forwardRef(function Anchor2({
|
|
|
182
181
|
},
|
|
183
182
|
[applyActive, onClick, scrollTo]
|
|
184
183
|
);
|
|
185
|
-
const resolved = resolveScrollRoot(getContainer);
|
|
184
|
+
const resolved = resolveScrollRoot(getContainer, { from: anchorRef.current });
|
|
186
185
|
const resolvedKey = resolved.isWindow ? "window" : resolved.target;
|
|
187
186
|
useEffect(() => {
|
|
188
|
-
const container =
|
|
187
|
+
const container = resolveContainer();
|
|
189
188
|
const root = container === window ? null : container;
|
|
190
189
|
const stop = createAnchorObserver(links, {
|
|
191
190
|
offsetTop: scrollOffset,
|