@expcat/tigercat-react 0.2.27 → 0.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.
Files changed (87) hide show
  1. package/dist/chunk-4IO2M3ZJ.js +110 -0
  2. package/dist/{chunk-2UVQIL26.mjs → chunk-6DYS4PJT.mjs} +1 -1
  3. package/dist/chunk-6YKZAWNX.js +258 -0
  4. package/dist/chunk-73DMQ2SR.mjs +206 -0
  5. package/dist/chunk-FAZQT7YP.mjs +255 -0
  6. package/dist/{chunk-HRYBEBZC.js → chunk-GJKT2B56.js} +5 -1
  7. package/dist/{chunk-5XKYWZZZ.mjs → chunk-HGTF6A46.mjs} +5 -1
  8. package/dist/chunk-HT2BXCEM.js +264 -0
  9. package/dist/{chunk-6ZC7H22S.mjs → chunk-IAF24RKI.mjs} +1 -1
  10. package/dist/chunk-IYFSM2GA.mjs +141 -0
  11. package/dist/chunk-JAVDNFJD.js +144 -0
  12. package/dist/{chunk-P273E6XE.js → chunk-MQTHGPHF.js} +37 -21
  13. package/dist/chunk-OVWCTDAL.js +209 -0
  14. package/dist/{chunk-GIYBVWR4.mjs → chunk-OZLAGTZW.mjs} +38 -22
  15. package/dist/{chunk-OD2NNQD2.js → chunk-PBJ2J2B3.js} +2 -2
  16. package/dist/chunk-PVOQUXIB.mjs +189 -0
  17. package/dist/chunk-R67R3TVA.mjs +261 -0
  18. package/dist/{chunk-VR5OP4MO.js → chunk-UG3I4PCY.js} +2 -2
  19. package/dist/chunk-WKGCUR7O.mjs +107 -0
  20. package/dist/chunk-ZN2BZCTI.js +192 -0
  21. package/dist/components/ActivityFeed.d.mts +10 -0
  22. package/dist/components/ActivityFeed.d.ts +10 -0
  23. package/dist/components/ActivityFeed.js +23 -0
  24. package/dist/components/ActivityFeed.mjs +8 -0
  25. package/dist/components/AreaChart.js +4 -4
  26. package/dist/components/AreaChart.mjs +2 -2
  27. package/dist/components/BarChart.js +4 -4
  28. package/dist/components/BarChart.mjs +2 -2
  29. package/dist/components/ChatWindow.d.mts +12 -0
  30. package/dist/components/ChatWindow.d.ts +12 -0
  31. package/dist/components/ChatWindow.js +20 -0
  32. package/dist/components/ChatWindow.mjs +5 -0
  33. package/dist/components/CommentThread.d.mts +8 -0
  34. package/dist/components/CommentThread.d.ts +8 -0
  35. package/dist/components/CommentThread.js +21 -0
  36. package/dist/components/CommentThread.mjs +6 -0
  37. package/dist/components/DataTableWithToolbar.d.mts +51 -0
  38. package/dist/components/DataTableWithToolbar.d.ts +51 -0
  39. package/dist/components/DataTableWithToolbar.js +24 -0
  40. package/dist/components/DataTableWithToolbar.mjs +9 -0
  41. package/dist/components/DonutChart.js +5 -5
  42. package/dist/components/DonutChart.mjs +3 -3
  43. package/dist/components/Dropdown.js +4 -4
  44. package/dist/components/Dropdown.mjs +2 -2
  45. package/dist/components/DropdownItem.js +4 -4
  46. package/dist/components/DropdownItem.mjs +3 -3
  47. package/dist/components/FormItem.js +2 -2
  48. package/dist/components/FormItem.mjs +1 -1
  49. package/dist/components/FormWizard.d.mts +10 -0
  50. package/dist/components/FormWizard.d.ts +10 -0
  51. package/dist/components/FormWizard.js +19 -0
  52. package/dist/components/FormWizard.mjs +4 -0
  53. package/dist/components/LineChart.js +4 -4
  54. package/dist/components/LineChart.mjs +2 -2
  55. package/dist/components/NotificationCenter.d.mts +8 -0
  56. package/dist/components/NotificationCenter.d.ts +8 -0
  57. package/dist/components/NotificationCenter.js +23 -0
  58. package/dist/components/NotificationCenter.mjs +8 -0
  59. package/dist/components/PieChart.js +4 -4
  60. package/dist/components/PieChart.mjs +2 -2
  61. package/dist/components/RadarChart.js +4 -4
  62. package/dist/components/RadarChart.mjs +2 -2
  63. package/dist/components/ScatterChart.js +4 -4
  64. package/dist/components/ScatterChart.mjs +2 -2
  65. package/dist/components/Table.d.mts +1 -1
  66. package/dist/components/Table.d.ts +1 -1
  67. package/dist/components/Table.js +2 -2
  68. package/dist/components/Table.mjs +1 -1
  69. package/dist/index.d.mts +6 -0
  70. package/dist/index.d.ts +6 -0
  71. package/dist/index.js +197 -167
  72. package/dist/index.mjs +49 -43
  73. package/package.json +2 -2
  74. package/dist/{chunk-ZYF5GI2Q.js → chunk-4PTI6ZUK.js} +1 -1
  75. package/dist/{chunk-LIJLFLYE.js → chunk-4TWHENPT.js} +1 -1
  76. package/dist/{chunk-67WZRMD6.js → chunk-6E5UKM6O.js} +1 -1
  77. package/dist/{chunk-AFFSBNYB.mjs → chunk-AITVDDCE.mjs} +1 -1
  78. package/dist/{chunk-324UKFG2.mjs → chunk-IL2Y5RCX.mjs} +1 -1
  79. package/dist/{chunk-7SOL3UJ2.js → chunk-L63N3LCG.js} +1 -1
  80. package/dist/{chunk-E6GLWHRL.mjs → chunk-LZNG2HGC.mjs} +1 -1
  81. package/dist/{chunk-2VXA4YOP.js → chunk-N32MAX4A.js} +1 -1
  82. package/dist/{chunk-RKBNIEGF.mjs → chunk-PT4WLSTJ.mjs} +1 -1
  83. package/dist/{chunk-LWW2LXCP.js → chunk-SIB4EHB6.js} +1 -1
  84. package/dist/{chunk-2WLSB7K2.mjs → chunk-WYTHTJN3.mjs} +1 -1
  85. package/dist/{chunk-5QKBBGIA.mjs → chunk-YER7IQF4.mjs} +1 -1
  86. package/dist/{chunk-7IKJBQQV.mjs → chunk-YGOTPK2W.mjs} +1 -1
  87. package/dist/{chunk-KKHKQP6Z.js → chunk-ZUUG3WOL.js} +1 -1
@@ -1,6 +1,6 @@
1
1
  import { useFormContext } from './chunk-3XXXM4OB.mjs';
2
2
  import React, { useState, useId, useMemo, useCallback, useEffect } from 'react';
3
- import { getFieldError, classNames } from '@expcat/tigercat-core';
3
+ import { getFieldError, classNames, getFormItemClasses, getFormItemLabelClasses, getFormItemErrorClasses, getFormItemContentClasses, getFormItemFieldClasses, getFormItemAsteriskClasses, getFormItemAsteriskStyle } from '@expcat/tigercat-core';
4
4
  import { jsxs, jsx } from 'react/jsx-runtime';
5
5
 
6
6
  var FormItem = ({
@@ -47,23 +47,33 @@ var FormItem = ({
47
47
  }
48
48
  return width;
49
49
  }, [labelWidth, formContext?.labelWidth]);
50
+ const hasRequiredRule = useCallback((maybeRules) => {
51
+ if (!maybeRules) {
52
+ return false;
53
+ }
54
+ const rules2 = Array.isArray(maybeRules) ? maybeRules : [maybeRules];
55
+ return rules2.some((rule) => {
56
+ if (!rule || typeof rule !== "object") {
57
+ return false;
58
+ }
59
+ return !!rule.required;
60
+ });
61
+ }, []);
50
62
  const showRequiredAsterisk = useMemo(() => {
51
63
  if (required !== void 0) {
52
64
  return required;
53
65
  }
54
66
  if (rules) {
55
- const ruleArray = Array.isArray(rules) ? rules : [rules];
56
- return ruleArray.some((rule) => rule.required);
67
+ return hasRequiredRule(rules);
57
68
  }
58
69
  if (name && formContext?.rules) {
59
70
  const fieldRules = formContext.rules[name];
60
71
  if (fieldRules) {
61
- const ruleArray = Array.isArray(fieldRules) ? fieldRules : [fieldRules];
62
- return ruleArray.some((rule) => rule.required);
72
+ return hasRequiredRule(fieldRules);
63
73
  }
64
74
  }
65
75
  return false;
66
- }, [required, rules, name, formContext?.rules]);
76
+ }, [required, rules, name, formContext?.rules, hasRequiredRule]);
67
77
  const isRequired = useMemo(
68
78
  () => showRequiredAsterisk && (formContext?.showRequiredAsterisk ?? true),
69
79
  [showRequiredAsterisk, formContext?.showRequiredAsterisk]
@@ -148,22 +158,24 @@ var FormItem = ({
148
158
  ]);
149
159
  const formItemClasses = useMemo(
150
160
  () => classNames(
151
- "tiger-form-item",
152
- `tiger-form-item--${actualSize}`,
153
- `tiger-form-item--label-${labelPosition}`,
154
- hasError && "tiger-form-item--error",
155
- formContext?.disabled && "tiger-form-item--disabled",
161
+ getFormItemClasses({
162
+ size: actualSize,
163
+ labelPosition,
164
+ hasError,
165
+ disabled: formContext?.disabled
166
+ }),
156
167
  className
157
168
  ),
158
169
  [actualSize, labelPosition, hasError, formContext?.disabled, className]
159
170
  );
160
171
  const labelClasses = useMemo(
161
- () => classNames(
162
- "tiger-form-item__label",
163
- `tiger-form-item__label--${labelAlign}`,
164
- isRequired && "tiger-form-item__label--required"
165
- ),
166
- [labelAlign, isRequired]
172
+ () => getFormItemLabelClasses({
173
+ size: actualSize,
174
+ labelAlign,
175
+ labelPosition,
176
+ isRequired
177
+ }),
178
+ [actualSize, labelAlign, labelPosition, isRequired]
167
179
  );
168
180
  const labelStyles = useMemo(() => {
169
181
  if (labelPosition === "top") {
@@ -172,9 +184,13 @@ var FormItem = ({
172
184
  return actualLabelWidth ? { width: actualLabelWidth } : {};
173
185
  }, [labelPosition, actualLabelWidth]);
174
186
  const errorClasses = useMemo(
175
- () => classNames("tiger-form-item__error", hasError && "tiger-form-item__error--show"),
176
- [hasError]
187
+ () => classNames(getFormItemErrorClasses(actualSize), hasError && "tiger-form-item__error--show"),
188
+ [actualSize, hasError]
177
189
  );
190
+ const contentClasses = useMemo(() => getFormItemContentClasses(labelPosition), [labelPosition]);
191
+ const fieldClasses = useMemo(() => getFormItemFieldClasses(), []);
192
+ const asteriskClasses = useMemo(() => getFormItemAsteriskClasses(), []);
193
+ const asteriskStyle = useMemo(() => getFormItemAsteriskStyle(), []);
178
194
  return /* @__PURE__ */ jsxs("div", { className: formItemClasses, children: [
179
195
  label && /* @__PURE__ */ jsxs(
180
196
  "label",
@@ -184,16 +200,16 @@ var FormItem = ({
184
200
  style: labelStyles,
185
201
  htmlFor: isClonableChild ? effectiveFieldId : void 0,
186
202
  children: [
187
- isRequired && /* @__PURE__ */ jsx("span", { className: "tiger-form-item__asterisk", children: "*" }),
203
+ isRequired && /* @__PURE__ */ jsx("span", { className: asteriskClasses, style: asteriskStyle, children: "*" }),
188
204
  label
189
205
  ]
190
206
  }
191
207
  ),
192
- /* @__PURE__ */ jsxs("div", { className: "tiger-form-item__content", children: [
208
+ /* @__PURE__ */ jsxs("div", { className: contentClasses, children: [
193
209
  /* @__PURE__ */ jsx(
194
210
  "div",
195
211
  {
196
- className: "tiger-form-item__field",
212
+ className: fieldClasses,
197
213
  role: "group",
198
214
  "aria-labelledby": label ? labelId : void 0,
199
215
  "aria-describedby": describedById,
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkLIJLFLYE_js = require('./chunk-LIJLFLYE.js');
3
+ var chunk4TWHENPT_js = require('./chunk-4TWHENPT.js');
4
4
  var react = require('react');
5
5
  var tigercatCore = require('@expcat/tigercat-core');
6
6
  var jsxRuntime = require('react/jsx-runtime');
@@ -13,7 +13,7 @@ var DropdownItem = ({
13
13
  children,
14
14
  ...buttonProps
15
15
  }) => {
16
- const context = react.useContext(chunkLIJLFLYE_js.DropdownContext);
16
+ const context = react.useContext(chunk4TWHENPT_js.DropdownContext);
17
17
  const handleClick = (event) => {
18
18
  if (disabled) {
19
19
  event.preventDefault();
@@ -0,0 +1,189 @@
1
+ import { Input } from './chunk-6ZTCBQJ7.mjs';
2
+ import { Textarea } from './chunk-672SCJWZ.mjs';
3
+ import { Button } from './chunk-STEIWBMF.mjs';
4
+ import { Avatar } from './chunk-V2HVHLBY.mjs';
5
+ import { useState, useEffect, useMemo, useCallback } from 'react';
6
+ import { classNames, getChatMessageStatusInfo, formatChatTime } from '@expcat/tigercat-core';
7
+ import { jsxs, jsx } from 'react/jsx-runtime';
8
+
9
+ var ChatWindow = ({
10
+ messages = [],
11
+ value,
12
+ defaultValue = "",
13
+ placeholder = "\u8BF7\u8F93\u5165\u6D88\u606F",
14
+ disabled = false,
15
+ maxLength,
16
+ emptyText = "\u6682\u65E0\u6D88\u606F",
17
+ sendText = "\u53D1\u9001",
18
+ messageListAriaLabel,
19
+ inputAriaLabel,
20
+ sendAriaLabel,
21
+ statusText,
22
+ statusVariant = "info",
23
+ showAvatar = true,
24
+ showName = true,
25
+ showTime = false,
26
+ inputType = "textarea",
27
+ inputRows = 3,
28
+ sendOnEnter = true,
29
+ allowShiftEnter = true,
30
+ allowEmpty = false,
31
+ clearOnSend = true,
32
+ statusVariant: _sv,
33
+ onChange,
34
+ onSend,
35
+ renderMessage,
36
+ className,
37
+ ...props
38
+ }) => {
39
+ const [innerValue, setInnerValue] = useState(value ?? defaultValue);
40
+ useEffect(() => {
41
+ if (value !== void 0) {
42
+ setInnerValue(value);
43
+ }
44
+ }, [value]);
45
+ const inputValue = value !== void 0 ? value : innerValue;
46
+ const wrapperClasses = useMemo(
47
+ () => classNames(
48
+ "tiger-chat-window flex flex-col w-full rounded-lg border border-[var(--tiger-border,#e5e7eb)] bg-[var(--tiger-surface,#ffffff)]",
49
+ className
50
+ ),
51
+ [className]
52
+ );
53
+ const canSend = useMemo(() => {
54
+ if (disabled) return false;
55
+ if (allowEmpty) return true;
56
+ const raw = String(inputValue ?? "");
57
+ return raw.trim().length > 0;
58
+ }, [allowEmpty, disabled, inputValue]);
59
+ const handleValueChange = useCallback(
60
+ (nextValue) => {
61
+ if (value === void 0) {
62
+ setInnerValue(nextValue);
63
+ }
64
+ onChange?.(nextValue);
65
+ },
66
+ [onChange, value]
67
+ );
68
+ const handleSend = useCallback(() => {
69
+ if (!canSend) return;
70
+ const payload = String(inputValue ?? "");
71
+ onSend?.(payload);
72
+ if (clearOnSend) {
73
+ if (value === void 0) {
74
+ setInnerValue("");
75
+ }
76
+ onChange?.("");
77
+ }
78
+ }, [canSend, clearOnSend, inputValue, onSend, onChange, value]);
79
+ const handleKeyDown = useCallback(
80
+ (event) => {
81
+ if (!sendOnEnter) return;
82
+ if (event.key !== "Enter") return;
83
+ if (inputType === "textarea" && allowShiftEnter && event.shiftKey) return;
84
+ event.preventDefault();
85
+ handleSend();
86
+ },
87
+ [allowShiftEnter, handleSend, inputType, sendOnEnter]
88
+ );
89
+ const renderMessageItem = useCallback(
90
+ (message, index) => {
91
+ const isSelf = message.direction === "self";
92
+ const statusInfo = message.status ? getChatMessageStatusInfo(message.status) : void 0;
93
+ const timeText = showTime ? formatChatTime(message.time) : "";
94
+ return /* @__PURE__ */ jsxs(
95
+ "div",
96
+ {
97
+ className: classNames(
98
+ "flex gap-3 items-start",
99
+ isSelf ? "flex-row-reverse" : "justify-start"
100
+ ),
101
+ "data-tiger-chat-message": true,
102
+ role: "listitem",
103
+ children: [
104
+ showAvatar && message.user ? /* @__PURE__ */ jsx(
105
+ Avatar,
106
+ {
107
+ size: "sm",
108
+ src: message.user.avatar,
109
+ text: message.user.name,
110
+ className: "flex-shrink-0"
111
+ }
112
+ ) : null,
113
+ /* @__PURE__ */ jsxs("div", { className: classNames("flex flex-col max-w-[75%]", isSelf && "items-end"), children: [
114
+ showName && message.user?.name && /* @__PURE__ */ jsx(
115
+ "div",
116
+ {
117
+ className: classNames(
118
+ "text-xs mb-1 text-[var(--tiger-text-muted,#6b7280)]",
119
+ isSelf && "text-right"
120
+ ),
121
+ children: message.user.name
122
+ }
123
+ ),
124
+ /* @__PURE__ */ jsx(
125
+ "div",
126
+ {
127
+ className: classNames(
128
+ "rounded-lg px-3 py-2 text-sm break-words",
129
+ isSelf ? "bg-[var(--tiger-primary,#2563eb)] text-white rounded-tr-none" : "bg-[var(--tiger-surface-muted,#f3f4f6)] text-[var(--tiger-text,#111827)] rounded-tl-none"
130
+ ),
131
+ "data-tiger-chat-bubble": true,
132
+ children: renderMessage?.(message, index) ?? message.content
133
+ }
134
+ ),
135
+ statusInfo && /* @__PURE__ */ jsx("div", { className: classNames("text-xs mt-1", statusInfo.className), children: message.statusText || statusInfo.text }),
136
+ timeText && /* @__PURE__ */ jsx("div", { className: "text-xs mt-1 text-[var(--tiger-text-muted,#6b7280)]", children: timeText })
137
+ ] })
138
+ ]
139
+ },
140
+ message.id ?? index
141
+ );
142
+ },
143
+ [renderMessage, showAvatar, showName, showTime]
144
+ );
145
+ return /* @__PURE__ */ jsxs("div", { className: wrapperClasses, "data-tiger-chat-window": true, ...props, children: [
146
+ /* @__PURE__ */ jsx(
147
+ "div",
148
+ {
149
+ className: "flex-1 overflow-auto p-4 space-y-3",
150
+ role: "log",
151
+ "aria-live": "polite",
152
+ "aria-relevant": "additions text",
153
+ "aria-label": messageListAriaLabel ?? "\u6D88\u606F\u5217\u8868",
154
+ children: messages.length === 0 ? /* @__PURE__ */ jsx("div", { className: "h-full flex items-center justify-center text-[var(--tiger-text-muted,#6b7280)]", children: emptyText }) : messages.map(renderMessageItem)
155
+ }
156
+ ),
157
+ statusText && /* @__PURE__ */ jsx("div", { className: "px-4 py-1.5 border-t border-[var(--tiger-border,#e5e7eb)] text-xs italic text-[var(--tiger-text-muted,#6b7280)]", children: statusText }),
158
+ /* @__PURE__ */ jsxs("div", { className: "flex items-end gap-3 px-4 py-3 border-t border-[var(--tiger-border,#e5e7eb)] bg-[var(--tiger-surface,#ffffff)] rounded-b-lg", children: [
159
+ /* @__PURE__ */ jsx("div", { className: "flex-1", children: inputType === "input" ? /* @__PURE__ */ jsx(
160
+ Input,
161
+ {
162
+ value: inputValue,
163
+ placeholder,
164
+ disabled,
165
+ maxLength,
166
+ "aria-label": inputAriaLabel ?? placeholder ?? "\u6D88\u606F\u8F93\u5165",
167
+ onChange: (event) => handleValueChange(event.currentTarget.value),
168
+ onKeyDown: handleKeyDown
169
+ }
170
+ ) : /* @__PURE__ */ jsx(
171
+ Textarea,
172
+ {
173
+ value: inputValue,
174
+ placeholder,
175
+ disabled,
176
+ maxLength,
177
+ rows: inputRows,
178
+ "aria-label": inputAriaLabel ?? placeholder ?? "\u6D88\u606F\u8F93\u5165",
179
+ onChange: (event) => handleValueChange(event.currentTarget.value),
180
+ onKeyDown: handleKeyDown
181
+ }
182
+ ) }),
183
+ /* @__PURE__ */ jsx(Button, { disabled: !canSend, onClick: handleSend, "aria-label": sendAriaLabel ?? sendText, children: sendText })
184
+ ] })
185
+ ] });
186
+ };
187
+ var ChatWindow_default = ChatWindow;
188
+
189
+ export { ChatWindow, ChatWindow_default };
@@ -0,0 +1,261 @@
1
+ import { Textarea } from './chunk-672SCJWZ.mjs';
2
+ import { Button } from './chunk-STEIWBMF.mjs';
3
+ import { Tag } from './chunk-DIZNY6N4.mjs';
4
+ import { Text } from './chunk-6YDIBMCM.mjs';
5
+ import { Avatar } from './chunk-V2HVHLBY.mjs';
6
+ import { useState, useMemo } from 'react';
7
+ import { buildCommentTree, clipCommentTreeDepth, classNames, formatCommentTime } from '@expcat/tigercat-core';
8
+ import { jsx, jsxs } from 'react/jsx-runtime';
9
+
10
+ var CommentThread = ({
11
+ nodes,
12
+ items,
13
+ maxDepth = 3,
14
+ maxReplies = 3,
15
+ defaultExpandedKeys = [],
16
+ expandedKeys,
17
+ emptyText = "\u6682\u65E0\u8BC4\u8BBA",
18
+ replyPlaceholder = "\u5199\u4E0B\u56DE\u590D...",
19
+ replyButtonText = "\u56DE\u590D",
20
+ cancelReplyText = "\u53D6\u6D88",
21
+ likeText = "\u70B9\u8D5E",
22
+ likedText = "\u5DF2\u8D5E",
23
+ replyText = "\u56DE\u590D",
24
+ moreText = "\u66F4\u591A",
25
+ loadMoreText = "\u52A0\u8F7D\u66F4\u591A",
26
+ showAvatar = true,
27
+ showDivider = true,
28
+ showLike = true,
29
+ showReply = true,
30
+ showMore = true,
31
+ onLike,
32
+ onReply,
33
+ onMore,
34
+ onAction,
35
+ onExpandedChange,
36
+ onLoadMore,
37
+ className,
38
+ ...divProps
39
+ }) => {
40
+ const [innerExpandedKeys, setInnerExpandedKeys] = useState(defaultExpandedKeys);
41
+ const [expandedAllKeys, setExpandedAllKeys] = useState(/* @__PURE__ */ new Set());
42
+ const [replyingTo, setReplyingTo] = useState(null);
43
+ const [replyValue, setReplyValue] = useState("");
44
+ const mergedExpandedKeys = expandedKeys ?? innerExpandedKeys;
45
+ const expandedSet = useMemo(
46
+ () => new Set(mergedExpandedKeys),
47
+ [mergedExpandedKeys]
48
+ );
49
+ const resolvedNodes = useMemo(() => {
50
+ const tree = nodes && nodes.length > 0 ? nodes : buildCommentTree(items ?? []);
51
+ return clipCommentTreeDepth(tree, maxDepth);
52
+ }, [nodes, items, maxDepth]);
53
+ const updateExpandedKeys = (next) => {
54
+ if (!expandedKeys) {
55
+ setInnerExpandedKeys(next);
56
+ }
57
+ onExpandedChange?.(next);
58
+ };
59
+ const toggleExpanded = (id) => {
60
+ const next = expandedSet.has(id) ? mergedExpandedKeys.filter((key) => key !== id) : [...mergedExpandedKeys, id];
61
+ updateExpandedKeys(next);
62
+ };
63
+ const handleLoadMore = (node) => {
64
+ setExpandedAllKeys((prev) => {
65
+ const next = new Set(prev);
66
+ next.add(node.id);
67
+ return next;
68
+ });
69
+ onLoadMore?.(node);
70
+ };
71
+ const handleReplySubmit = (node) => {
72
+ const trimmed = replyValue.trim();
73
+ if (!trimmed) return;
74
+ onReply?.(node, replyValue);
75
+ setReplyValue("");
76
+ setReplyingTo(null);
77
+ if (!expandedSet.has(node.id)) {
78
+ const next = [...mergedExpandedKeys, node.id];
79
+ updateExpandedKeys(next);
80
+ }
81
+ };
82
+ const BTN_BASE = "px-1.5 py-0.5 h-auto min-h-0 text-xs rounded";
83
+ const ACTION_BTN = `${BTN_BASE} text-gray-400 hover:text-gray-600 font-normal hover:bg-gray-50`;
84
+ const PRIMARY_BTN = `${BTN_BASE} text-[var(--tiger-primary,#2563eb)] hover:text-[var(--tiger-primary-hover,#1d4ed8)] font-medium hover:bg-[var(--tiger-primary,#2563eb)]/5`;
85
+ const renderActionButton = (label, key, onClick, active) => /* @__PURE__ */ jsx(
86
+ Button,
87
+ {
88
+ size: "sm",
89
+ variant: "ghost",
90
+ className: classNames(
91
+ ACTION_BTN,
92
+ active && "text-[var(--tiger-primary,#2563eb)] hover:text-[var(--tiger-primary,#2563eb)] font-medium"
93
+ ),
94
+ onClick,
95
+ children: label
96
+ },
97
+ key
98
+ );
99
+ const renderNode = (node, depth, isLast) => {
100
+ const hasChildren = !!node.children && node.children.length > 0;
101
+ const isExpanded = expandedSet.has(node.id);
102
+ const showReplies = hasChildren && isExpanded;
103
+ const showAllReplies = expandedAllKeys.has(node.id);
104
+ const repliesId = `tiger-comment-replies-${node.id}`;
105
+ const visibleChildren = showReplies ? maxReplies > 0 && !showAllReplies ? node.children.slice(0, maxReplies) : node.children : [];
106
+ const showLoadMoreBtn = showReplies && maxReplies > 0 && node.children.length > maxReplies && !showAllReplies;
107
+ const actions = [];
108
+ if (showLike) {
109
+ const likeLabel = node.liked ? likedText : likeText;
110
+ const likeCount = node.likes ? ` ${node.likes}` : "";
111
+ actions.push(
112
+ renderActionButton(
113
+ `${likeLabel}${likeCount}`,
114
+ "like",
115
+ () => onLike?.(node, !node.liked),
116
+ node.liked
117
+ )
118
+ );
119
+ }
120
+ if (showReply) {
121
+ actions.push(
122
+ renderActionButton(replyText, "reply", () => {
123
+ setReplyingTo((prev) => prev === node.id ? null : node.id);
124
+ setReplyValue("");
125
+ })
126
+ );
127
+ }
128
+ if (showMore) {
129
+ actions.push(renderActionButton(moreText, "more", () => onMore?.(node)));
130
+ }
131
+ if (node.actions && node.actions.length > 0) {
132
+ node.actions.forEach((action, index) => {
133
+ const actionKey = action.key ?? `${node.id}-action-${index}`;
134
+ actions.push(
135
+ /* @__PURE__ */ jsx(
136
+ Button,
137
+ {
138
+ size: "sm",
139
+ variant: action.variant ?? "ghost",
140
+ className: ACTION_BTN,
141
+ disabled: action.disabled,
142
+ onClick: () => {
143
+ action.onClick?.(node, action);
144
+ onAction?.(node, action);
145
+ },
146
+ children: action.label
147
+ },
148
+ actionKey
149
+ )
150
+ );
151
+ });
152
+ }
153
+ return /* @__PURE__ */ jsx(
154
+ "div",
155
+ {
156
+ className: classNames(
157
+ "tiger-comment-thread-item",
158
+ depth === 1 && "py-4",
159
+ depth === 1 && !isLast && showDivider && "border-b border-[var(--tiger-border,#e5e7eb)]"
160
+ ),
161
+ children: /* @__PURE__ */ jsxs("div", { className: "flex gap-3", children: [
162
+ showAvatar && node.user ? /* @__PURE__ */ jsx(
163
+ Avatar,
164
+ {
165
+ size: depth === 1 ? "md" : "sm",
166
+ src: node.user.avatar,
167
+ text: node.user.name,
168
+ className: "shrink-0 mt-0.5"
169
+ }
170
+ ) : null,
171
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
172
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [
173
+ node.user?.name ? /* @__PURE__ */ jsx(Text, { tag: "span", size: "sm", weight: "bold", children: node.user.name }) : null,
174
+ node.user?.title ? /* @__PURE__ */ jsx(Text, { tag: "span", size: "xs", color: "muted", children: node.user.title }) : null,
175
+ node.tag ? /* @__PURE__ */ jsx(Tag, { size: "sm", variant: node.tag.variant ?? "default", children: node.tag.label }) : null,
176
+ node.tags?.map((tag, index) => /* @__PURE__ */ jsx(Tag, { size: "sm", variant: tag.variant ?? "default", children: tag.label }, `${node.id}-tag-${index}`)),
177
+ node.time ? /* @__PURE__ */ jsx(Text, { tag: "span", size: "xs", color: "muted", className: "ml-auto", children: formatCommentTime(node.time) }) : null
178
+ ] }),
179
+ /* @__PURE__ */ jsx("div", { className: "text-sm text-[var(--tiger-text-secondary,#4b5563)] leading-relaxed break-words mt-1.5 mb-2", children: node.content }),
180
+ actions.length > 0 ? /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-1", children: actions }) : null,
181
+ replyingTo === node.id ? /* @__PURE__ */ jsxs("div", { className: "mt-3 space-y-2 bg-[var(--tiger-surface-muted,#f9fafb)] p-3 rounded-lg", children: [
182
+ /* @__PURE__ */ jsx(
183
+ Textarea,
184
+ {
185
+ rows: 2,
186
+ value: replyValue,
187
+ placeholder: replyPlaceholder,
188
+ className: "bg-[var(--tiger-surface,#ffffff)]",
189
+ onChange: (event) => setReplyValue(event.target.value)
190
+ }
191
+ ),
192
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 justify-end", children: [
193
+ /* @__PURE__ */ jsx(
194
+ Button,
195
+ {
196
+ size: "sm",
197
+ variant: "ghost",
198
+ onClick: () => {
199
+ setReplyingTo(null);
200
+ setReplyValue("");
201
+ },
202
+ children: cancelReplyText
203
+ }
204
+ ),
205
+ /* @__PURE__ */ jsx(Button, { size: "sm", variant: "primary", onClick: () => handleReplySubmit(node), children: replyButtonText })
206
+ ] })
207
+ ] }) : null,
208
+ hasChildren ? /* @__PURE__ */ jsx(
209
+ Button,
210
+ {
211
+ size: "sm",
212
+ variant: "ghost",
213
+ className: classNames("mt-2", PRIMARY_BTN),
214
+ "aria-expanded": isExpanded,
215
+ "aria-controls": repliesId,
216
+ onClick: () => toggleExpanded(node.id),
217
+ children: isExpanded ? "\u25BE \u6536\u8D77\u56DE\u590D" : `\u25B8 \u5C55\u5F00 ${node.children.length} \u6761\u56DE\u590D`
218
+ }
219
+ ) : null,
220
+ showReplies ? /* @__PURE__ */ jsxs(
221
+ "div",
222
+ {
223
+ id: repliesId,
224
+ className: "mt-3 ml-1 pl-4 border-l-2 border-[var(--tiger-border,#e5e7eb)] space-y-3",
225
+ children: [
226
+ visibleChildren.map(
227
+ (child, index) => renderNode(child, depth + 1, index === visibleChildren.length - 1)
228
+ ),
229
+ showLoadMoreBtn ? /* @__PURE__ */ jsx(
230
+ Button,
231
+ {
232
+ size: "sm",
233
+ variant: "ghost",
234
+ className: PRIMARY_BTN,
235
+ onClick: () => handleLoadMore(node),
236
+ children: loadMoreText
237
+ }
238
+ ) : null
239
+ ]
240
+ }
241
+ ) : null
242
+ ] })
243
+ ] })
244
+ },
245
+ node.id
246
+ );
247
+ };
248
+ return /* @__PURE__ */ jsx(
249
+ "div",
250
+ {
251
+ className: classNames("tiger-comment-thread flex flex-col", className),
252
+ "data-tiger-comment-thread": true,
253
+ "aria-label": divProps["aria-label"] ?? (divProps["aria-labelledby"] ? void 0 : "\u8BC4\u8BBA\u7EBF\u7A0B"),
254
+ ...divProps,
255
+ children: resolvedNodes.length === 0 ? /* @__PURE__ */ jsx(Text, { tag: "div", size: "sm", color: "muted", className: "text-center py-8", children: emptyText }) : resolvedNodes.map((node, index) => renderNode(node, 1, index === resolvedNodes.length - 1))
256
+ }
257
+ );
258
+ };
259
+ var CommentThread_default = CommentThread;
260
+
261
+ export { CommentThread, CommentThread_default };
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunk2VXA4YOP_js = require('./chunk-2VXA4YOP.js');
3
+ var chunkN32MAX4A_js = require('./chunk-N32MAX4A.js');
4
4
  var react = require('react');
5
5
  var tigercatCore = require('@expcat/tigercat-core');
6
6
  var jsxRuntime = require('react/jsx-runtime');
@@ -60,7 +60,7 @@ var DonutChart = ({
60
60
  return resolvedOuterRadius * ratio;
61
61
  }, [innerRadius, innerRadiusRatio, resolvedOuterRadius]);
62
62
  return /* @__PURE__ */ jsxRuntime.jsx(
63
- chunk2VXA4YOP_js.PieChart,
63
+ chunkN32MAX4A_js.PieChart,
64
64
  {
65
65
  width,
66
66
  height,