@taskon/widget-react 0.0.1-beta.5 → 0.0.1-beta.6

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 (58) hide show
  1. package/README.md +13 -4
  2. package/dist/CommunityTaskList.css +9 -1
  3. package/dist/EligibilityInfo.css +46 -42
  4. package/dist/LeaderboardWidget.css +73 -71
  5. package/dist/PageBuilder.css +5 -0
  6. package/dist/Quest.css +18 -14
  7. package/dist/TaskOnProvider.css +2 -0
  8. package/dist/UserCenterWidget.css +6 -6
  9. package/dist/UserCenterWidget2.css +1626 -1601
  10. package/dist/{dynamic-import-helper.css → WidgetShell.css} +2 -2
  11. package/dist/chunks/{CommunityTaskList-CrMvOB8w.js → CommunityTaskList-Hde2OKHH.js} +360 -154
  12. package/dist/chunks/{EligibilityInfo-Beww12QX.js → EligibilityInfo-BV0Z2TgY.js} +533 -561
  13. package/dist/chunks/{LeaderboardWidget-DwuSpVl0.js → LeaderboardWidget-BNGRD5Bu.js} +270 -249
  14. package/dist/chunks/{PageBuilder-DsX6Tv0N.js → PageBuilder-C5DSHiW9.js} +5 -5
  15. package/dist/chunks/{Quest-CuD2LElS.js → Quest-DG9zfXJo.js} +72 -50
  16. package/dist/chunks/{TaskOnProvider-xUeP2Nro.js → TaskOnProvider-BhamHIyY.js} +34 -17
  17. package/dist/chunks/{ThemeProvider-Bt4UZ33y.js → ThemeProvider-mXLdLSkq.js} +81 -18
  18. package/dist/chunks/{UserCenterWidget-CvU6K4AC.js → UserCenterWidget-D5ttw4hO.js} +1328 -1337
  19. package/dist/chunks/{UserCenterWidget-CB0hnj-L.js → UserCenterWidget-jDO5zTN1.js} +298 -231
  20. package/dist/chunks/{dynamic-import-helper-WmIF58Sb.js → WidgetShell-D7yC894Y.js} +447 -457
  21. package/dist/chunks/communitytask-es-CBNnS4o2.js +521 -0
  22. package/dist/chunks/communitytask-ja-GRf9cbdx.js +521 -0
  23. package/dist/chunks/communitytask-ko-Bf24PQKI.js +521 -0
  24. package/dist/chunks/{communitytask-ru-DhySaZL8.js → communitytask-ru-CZm2CPoV.js} +211 -1
  25. package/dist/chunks/leaderboardwidget-es-vKjrjQaz.js +146 -0
  26. package/dist/chunks/leaderboardwidget-ja-Q6u0HxKG.js +146 -0
  27. package/dist/chunks/leaderboardwidget-ko-CG6SWgxf.js +146 -0
  28. package/dist/chunks/leaderboardwidget-ru-DCcHcJGz.js +146 -0
  29. package/dist/chunks/{quest-es-D-b5xcme.js → quest-es-Dyyy0zaw.js} +8 -93
  30. package/dist/chunks/{quest-ja-Dxd2vqBF.js → quest-ja-Depog33y.js} +8 -93
  31. package/dist/chunks/{quest-ko-CSmRWgK_.js → quest-ko-BMu3uRQJ.js} +8 -93
  32. package/dist/chunks/{quest-ru-CkEKv1_F.js → quest-ru-xne814Rw.js} +8 -93
  33. package/dist/chunks/usercenter-es-Dz3Wp2vV.js +512 -0
  34. package/dist/chunks/usercenter-ja-CKE4DJC6.js +512 -0
  35. package/dist/chunks/usercenter-ko-Dtpkn2qb.js +512 -0
  36. package/dist/chunks/usercenter-ru-DnBGee45.js +512 -0
  37. package/dist/community-task.d.ts +0 -390
  38. package/dist/community-task.js +2 -7
  39. package/dist/core.d.ts +29 -5
  40. package/dist/core.js +8 -9
  41. package/dist/index.d.ts +29 -701
  42. package/dist/index.js +18 -29
  43. package/dist/leaderboard.d.ts +0 -498
  44. package/dist/leaderboard.js +2 -16
  45. package/dist/page-builder.js +1 -1
  46. package/dist/quest.d.ts +0 -971
  47. package/dist/quest.js +2 -7
  48. package/dist/user-center.d.ts +0 -1610
  49. package/dist/user-center.js +2 -494
  50. package/package.json +2 -2
  51. package/dist/chunks/communitytask-es-1zawvXEX.js +0 -311
  52. package/dist/chunks/communitytask-ja-CmW6nP-L.js +0 -311
  53. package/dist/chunks/communitytask-ko-BD0hzQSi.js +0 -311
  54. package/dist/chunks/createLocaleLoader-BameiEhU.js +0 -65
  55. package/dist/chunks/leaderboardwidget-ja-Bj6gz6y1.js +0 -119
  56. package/dist/chunks/leaderboardwidget-ko-f1cLO9ic.js +0 -119
  57. package/dist/chunks/usercenter-ja-B2465c1O.js +0 -326
  58. package/dist/chunks/usercenter-ko-xAEYxqLg.js +0 -326
@@ -1,9 +1,9 @@
1
- import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
1
  import * as React from "react";
3
- import { forwardRef, useState, useMemo, useCallback, useEffect } from "react";
4
- import { r as composeRefs, o as useLayoutEffect2, l as useCallbackRef$1, f as useComposedRefs, P as Primitive, h as useControllableState, e as createContextScope, j as Presence, m as Portal$1, k as composeEventHandlers, g as createSlot$1, D as DismissableLayer, s as createContext2, t as useTaskOnPortalContainer, d as useTaskOnContext, T as ThemeProvider } from "./ThemeProvider-Bt4UZ33y.js";
2
+ import { useState, useMemo, useCallback, useEffect, forwardRef } from "react";
5
3
  import { createWidgetApi, parseWidgetConfig } from "@taskon/core";
6
- import '../dynamic-import-helper.css';function cloudThemeToReactTheme(cloud) {
4
+ import { h as useTaskOnContext, s as useLayoutEffect2, q as useCallbackRef$1, k as useComposedRefs, P as Primitive, m as useControllableState, j as createContextScope, n as Presence, r as Portal$1, o as composeEventHandlers, l as createSlot$1, D as DismissableLayer, w as createContext2, x as useTaskOnPortalContainer, y as composeRefs, T as ThemeProvider } from "./ThemeProvider-mXLdLSkq.js";
5
+ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
6
+ import '../WidgetShell.css';function cloudThemeToReactTheme(cloud) {
7
7
  const isDual = cloud.colorMode.type === "dual";
8
8
  const modeStrategy = isDual ? cloud.colorMode.dualVariant : "auto";
9
9
  let mode;
@@ -49,247 +49,127 @@ import '../dynamic-import-helper.css';function cloudThemeToReactTheme(cloud) {
49
49
  }
50
50
  };
51
51
  }
52
- var REACT_LAZY_TYPE = Symbol.for("react.lazy");
53
- var use = React[" use ".trim().toString()];
54
- function isPromiseLike(value) {
55
- return typeof value === "object" && value !== null && "then" in value;
56
- }
57
- function isLazyComponent(element) {
58
- return element != null && typeof element === "object" && "$$typeof" in element && element.$$typeof === REACT_LAZY_TYPE && "_payload" in element && isPromiseLike(element._payload);
59
- }
60
- // @__NO_SIDE_EFFECTS__
61
- function createSlot(ownerName) {
62
- const SlotClone = /* @__PURE__ */ createSlotClone(ownerName);
63
- const Slot2 = React.forwardRef((props, forwardedRef) => {
64
- let { children, ...slotProps } = props;
65
- if (isLazyComponent(children) && typeof use === "function") {
66
- children = use(children._payload);
52
+ function usePagination(options) {
53
+ const { total, pageSize, initialPage = 0, mode = "pagination" } = options;
54
+ const [page, setPage] = useState(initialPage);
55
+ const totalPages = useMemo(() => {
56
+ return Math.max(1, Math.ceil(total / pageSize));
57
+ }, [total, pageSize]);
58
+ const safePage = useMemo(() => {
59
+ return Math.min(page, totalPages - 1);
60
+ }, [page, totalPages]);
61
+ if (safePage !== page) {
62
+ setPage(safePage);
63
+ }
64
+ const hasPrevious = safePage > 0;
65
+ const hasNext = safePage < totalPages - 1;
66
+ const goToPage = useCallback(
67
+ (targetPage) => {
68
+ const validPage = Math.max(0, Math.min(targetPage, totalPages - 1));
69
+ setPage(validPage);
70
+ },
71
+ [totalPages]
72
+ );
73
+ const goToPrevious = useCallback(() => {
74
+ if (hasPrevious) {
75
+ setPage((p) => p - 1);
67
76
  }
68
- const childrenArray = React.Children.toArray(children);
69
- const slottable = childrenArray.find(isSlottable);
70
- if (slottable) {
71
- const newElement = slottable.props.children;
72
- const newChildren = childrenArray.map((child) => {
73
- if (child === slottable) {
74
- if (React.Children.count(newElement) > 1) return React.Children.only(null);
75
- return React.isValidElement(newElement) ? newElement.props.children : null;
76
- } else {
77
- return child;
78
- }
79
- });
80
- return /* @__PURE__ */ jsx(SlotClone, { ...slotProps, ref: forwardedRef, children: React.isValidElement(newElement) ? React.cloneElement(newElement, void 0, newChildren) : null });
77
+ }, [hasPrevious]);
78
+ const goToNext = useCallback(() => {
79
+ if (hasNext) {
80
+ setPage((p) => p + 1);
81
81
  }
82
- return /* @__PURE__ */ jsx(SlotClone, { ...slotProps, ref: forwardedRef, children });
83
- });
84
- Slot2.displayName = `${ownerName}.Slot`;
85
- return Slot2;
86
- }
87
- var Slot$1 = /* @__PURE__ */ createSlot("Slot");
88
- // @__NO_SIDE_EFFECTS__
89
- function createSlotClone(ownerName) {
90
- const SlotClone = React.forwardRef((props, forwardedRef) => {
91
- let { children, ...slotProps } = props;
92
- if (isLazyComponent(children) && typeof use === "function") {
93
- children = use(children._payload);
82
+ }, [hasNext]);
83
+ const reset = useCallback(() => {
84
+ setPage(0);
85
+ }, []);
86
+ const startIndex = safePage * pageSize + 1;
87
+ const endIndex = Math.min((safePage + 1) * pageSize, total);
88
+ const hasMore = useMemo(() => {
89
+ if (mode === "infinite") {
90
+ return safePage < totalPages - 1;
94
91
  }
95
- if (React.isValidElement(children)) {
96
- const childrenRef = getElementRef(children);
97
- const props2 = mergeProps(slotProps, children.props);
98
- if (children.type !== React.Fragment) {
99
- props2.ref = forwardedRef ? composeRefs(forwardedRef, childrenRef) : childrenRef;
100
- }
101
- return React.cloneElement(children, props2);
92
+ return hasNext;
93
+ }, [mode, safePage, totalPages, hasNext]);
94
+ const loadedCount = useMemo(() => {
95
+ if (mode === "infinite") {
96
+ return Math.min((safePage + 1) * pageSize, total);
102
97
  }
103
- return React.Children.count(children) > 1 ? React.Children.only(null) : null;
104
- });
105
- SlotClone.displayName = `${ownerName}.SlotClone`;
106
- return SlotClone;
107
- }
108
- var SLOTTABLE_IDENTIFIER = Symbol("radix.slottable");
109
- function isSlottable(child) {
110
- return React.isValidElement(child) && typeof child.type === "function" && "__radixId" in child.type && child.type.__radixId === SLOTTABLE_IDENTIFIER;
111
- }
112
- function mergeProps(slotProps, childProps) {
113
- const overrideProps = { ...childProps };
114
- for (const propName in childProps) {
115
- const slotPropValue = slotProps[propName];
116
- const childPropValue = childProps[propName];
117
- const isHandler = /^on[A-Z]/.test(propName);
118
- if (isHandler) {
119
- if (slotPropValue && childPropValue) {
120
- overrideProps[propName] = (...args) => {
121
- const result = childPropValue(...args);
122
- slotPropValue(...args);
123
- return result;
124
- };
125
- } else if (slotPropValue) {
126
- overrideProps[propName] = slotPropValue;
127
- }
128
- } else if (propName === "style") {
129
- overrideProps[propName] = { ...slotPropValue, ...childPropValue };
130
- } else if (propName === "className") {
131
- overrideProps[propName] = [slotPropValue, childPropValue].filter(Boolean).join(" ");
98
+ return endIndex - startIndex + 1;
99
+ }, [mode, safePage, pageSize, total, startIndex, endIndex]);
100
+ const loadMore = useCallback(() => {
101
+ if (mode === "infinite" && hasMore) {
102
+ setPage((p) => p + 1);
132
103
  }
133
- }
134
- return { ...slotProps, ...overrideProps };
135
- }
136
- function getElementRef(element) {
137
- var _a, _b;
138
- let getter = (_a = Object.getOwnPropertyDescriptor(element.props, "ref")) == null ? void 0 : _a.get;
139
- let mayWarn = getter && "isReactWarning" in getter && getter.isReactWarning;
140
- if (mayWarn) {
141
- return element.ref;
142
- }
143
- getter = (_b = Object.getOwnPropertyDescriptor(element, "ref")) == null ? void 0 : _b.get;
144
- mayWarn = getter && "isReactWarning" in getter && getter.isReactWarning;
145
- if (mayWarn) {
146
- return element.props.ref;
147
- }
148
- return element.props.ref || element.ref;
104
+ }, [mode, hasMore]);
105
+ return {
106
+ page: safePage,
107
+ totalPages,
108
+ hasPrevious,
109
+ hasNext,
110
+ goToPage,
111
+ goToPrevious,
112
+ goToNext,
113
+ reset,
114
+ startIndex,
115
+ endIndex,
116
+ // Infinite 模式专用
117
+ loadMore,
118
+ hasMore,
119
+ loadedCount
120
+ };
149
121
  }
150
- const Button = forwardRef(
151
- ({
152
- size = "medium",
153
- variant = "primary",
154
- loading = false,
155
- iconPosition,
156
- leftIcon,
157
- rightIcon,
158
- asChild = false,
159
- disabled,
160
- className = "",
161
- style,
162
- children,
163
- ...props
164
- }, ref) => {
165
- const Comp = asChild ? Slot$1 : "button";
166
- const actualIconPosition = iconPosition || (leftIcon ? "left" : rightIcon ? "right" : void 0);
167
- const isIconOnly = actualIconPosition === "only" || !children && (leftIcon || rightIcon);
168
- const baseStyles = {
169
- display: "inline-flex",
170
- alignItems: "center",
171
- justifyContent: "center",
172
- gap: "var(--taskon-spacing-xs)",
173
- fontFamily: "inherit",
174
- fontWeight: 500,
175
- lineHeight: 1.5,
176
- border: "none",
177
- outline: "none",
178
- cursor: disabled || loading ? "not-allowed" : "pointer",
179
- transition: "all 0.2s ease-in-out",
180
- position: "relative",
181
- userSelect: "none",
182
- whiteSpace: "nowrap",
183
- opacity: disabled ? 0.5 : 1,
184
- ...style
185
- };
186
- const sizeStyles = {
187
- small: {
188
- fontSize: "var(--taskon-font-size-sm)",
189
- padding: isIconOnly ? "var(--taskon-spacing-xs)" : "var(--taskon-spacing-xs) var(--taskon-spacing-sm)",
190
- borderRadius: "var(--taskon-border-radius-sm)",
191
- minWidth: isIconOnly ? "24px" : "64px",
192
- height: "24px"
193
- },
194
- medium: {
195
- fontSize: "var(--taskon-font-size)",
196
- padding: isIconOnly ? "var(--taskon-spacing-xs)" : "var(--taskon-spacing-xs) var(--taskon-spacing-md)",
197
- borderRadius: "var(--taskon-border-radius)",
198
- minWidth: isIconOnly ? "32px" : "80px",
199
- height: "32px"
200
- },
201
- large: {
202
- fontSize: "var(--taskon-font-size-lg)",
203
- padding: isIconOnly ? "var(--taskon-spacing-sm)" : "var(--taskon-spacing-sm) var(--taskon-spacing-lg)",
204
- borderRadius: "var(--taskon-border-radius)",
205
- minWidth: isIconOnly ? "40px" : "96px",
206
- height: "40px"
122
+ function useWidgetConfig(widgetId) {
123
+ const { client } = useTaskOnContext();
124
+ const [config, setConfig] = useState(null);
125
+ const [isLoading, setIsLoading] = useState(false);
126
+ const [error, setError] = useState(null);
127
+ useEffect(() => {
128
+ if (!widgetId || !client) {
129
+ setConfig(null);
130
+ setIsLoading(false);
131
+ setError(null);
132
+ return;
133
+ }
134
+ let cancelled = false;
135
+ setIsLoading(true);
136
+ setError(null);
137
+ const api = createWidgetApi(client);
138
+ api.getWidgetInfo(widgetId).then((info) => {
139
+ if (!cancelled) {
140
+ setConfig(parseWidgetConfig(info));
141
+ }
142
+ }).catch((err) => {
143
+ if (!cancelled) {
144
+ console.warn("[TaskOn] Failed to load widget config:", err);
145
+ setError(
146
+ err instanceof Error ? err.message : "Failed to load widget config"
147
+ );
148
+ }
149
+ }).finally(() => {
150
+ if (!cancelled) {
151
+ setIsLoading(false);
207
152
  }
153
+ });
154
+ return () => {
155
+ cancelled = true;
208
156
  };
209
- const variantStyles = {
210
- primary: {
211
- backgroundColor: "var(--taskon-color-primary)",
212
- color: "var(--taskon-color-text-on-primary)"
213
- },
214
- secondary: {
215
- backgroundColor: "var(--taskon-color-secondary)",
216
- color: "var(--taskon-color-text-on-primary)"
217
- },
218
- outline: {
219
- backgroundColor: "transparent",
220
- color: "var(--taskon-color-text)",
221
- border: "1px solid var(--taskon-color-border)"
222
- },
223
- ghost: {
224
- backgroundColor: "transparent",
225
- color: "var(--taskon-color-text)"
226
- },
227
- danger: {
228
- backgroundColor: "var(--taskon-color-error)",
229
- color: "var(--taskon-color-text-on-primary)"
230
- }
231
- };
232
- const hoverStyles = {
233
- primary: "hover:bg-[var(--taskon-color-primary-hover)] active:bg-[var(--taskon-color-primary-active)]",
234
- secondary: "hover:opacity-90 active:opacity-80",
235
- outline: "hover:bg-[var(--taskon-color-bg-surface-strong)] active:bg-[var(--taskon-color-bg-surface-strong)]",
236
- ghost: "hover:bg-[var(--taskon-color-bg-surface-strong)] active:bg-[var(--taskon-color-bg-surface-strong)]",
237
- danger: "hover:opacity-90 active:opacity-80"
238
- };
239
- const mergedStyle = {
240
- ...baseStyles,
241
- ...sizeStyles[size],
242
- ...variantStyles[variant]
243
- };
244
- const mergedClassName = `${className} ${hoverStyles[variant]}`.trim();
245
- const renderLoadingIndicator = () => {
246
- if (!loading) return null;
247
- return /* @__PURE__ */ jsx(
248
- "span",
249
- {
250
- style: {
251
- display: "inline-block",
252
- width: "1em",
253
- height: "1em",
254
- border: "2px solid currentColor",
255
- borderTopColor: "transparent",
256
- borderRadius: "50%",
257
- animation: "taskon-button-spin 0.6s linear infinite"
258
- }
259
- }
260
- );
261
- };
262
- return /* @__PURE__ */ jsxs(Fragment, { children: [
263
- /* @__PURE__ */ jsx("style", { children: `
264
- @keyframes taskon-button-spin {
265
- from {
266
- transform: rotate(0deg);
267
- }
268
- to {
269
- transform: rotate(360deg);
270
- }
271
- }
272
- ` }),
273
- /* @__PURE__ */ jsxs(
274
- Comp,
275
- {
276
- ref,
277
- disabled: disabled || loading,
278
- className: mergedClassName,
279
- style: mergedStyle,
280
- ...props,
281
- children: [
282
- loading && renderLoadingIndicator(),
283
- !loading && leftIcon && actualIconPosition === "left" && /* @__PURE__ */ jsx("span", { style: { display: "inline-flex" }, children: leftIcon }),
284
- !isIconOnly && children,
285
- !loading && rightIcon && actualIconPosition === "right" && /* @__PURE__ */ jsx("span", { style: { display: "inline-flex" }, children: rightIcon })
286
- ]
287
- }
288
- )
289
- ] });
290
- }
291
- );
292
- Button.displayName = "Button";
157
+ }, [widgetId, client]);
158
+ return { config, isLoading, error };
159
+ }
160
+ function useResolvedWidgetConfig(widgetId) {
161
+ const { config, isLoading, error } = useWidgetConfig(widgetId);
162
+ const cloudTheme = useMemo(() => {
163
+ if (!(config == null ? void 0 : config.theme)) return void 0;
164
+ return cloudThemeToReactTheme(config.theme);
165
+ }, [config == null ? void 0 : config.theme]);
166
+ return {
167
+ functionConfig: (config == null ? void 0 : config.functionConfig) ?? null,
168
+ cloudTheme,
169
+ isConfigLoading: isLoading,
170
+ configError: error
171
+ };
172
+ }
293
173
  var useReactId = React[" useId ".trim().toString()] || (() => void 0);
294
174
  var count$1 = 0;
295
175
  function useId(deterministicId) {
@@ -1383,7 +1263,7 @@ var DialogOverlay = React.forwardRef(
1383
1263
  }
1384
1264
  );
1385
1265
  DialogOverlay.displayName = OVERLAY_NAME;
1386
- var Slot = createSlot$1("DialogOverlay.RemoveScroll");
1266
+ var Slot$1 = createSlot$1("DialogOverlay.RemoveScroll");
1387
1267
  var DialogOverlayImpl = React.forwardRef(
1388
1268
  (props, forwardedRef) => {
1389
1269
  const { __scopeDialog, ...overlayProps } = props;
@@ -1391,7 +1271,7 @@ var DialogOverlayImpl = React.forwardRef(
1391
1271
  return (
1392
1272
  // Make sure `Content` is scrollable even when it doesn't live inside `RemoveScroll`
1393
1273
  // ie. when `Overlay` and `Content` are siblings
1394
- /* @__PURE__ */ jsx(ReactRemoveScroll, { as: Slot, allowPinchZoom: true, shards: [context.contentRef], children: /* @__PURE__ */ jsx(
1274
+ /* @__PURE__ */ jsx(ReactRemoveScroll, { as: Slot$1, allowPinchZoom: true, shards: [context.contentRef], children: /* @__PURE__ */ jsx(
1395
1275
  Primitive.div,
1396
1276
  {
1397
1277
  "data-state": getState(context.open),
@@ -1620,85 +1500,326 @@ function CloseIcon() {
1620
1500
  children: /* @__PURE__ */ jsx(
1621
1501
  "path",
1622
1502
  {
1623
- d: "M18 6L6 18M6 6L18 18",
1624
- stroke: "currentColor",
1625
- strokeWidth: "2",
1626
- strokeLinecap: "round",
1627
- strokeLinejoin: "round"
1503
+ d: "M18 6L6 18M6 6L18 18",
1504
+ stroke: "currentColor",
1505
+ strokeWidth: "2",
1506
+ strokeLinecap: "round",
1507
+ strokeLinejoin: "round"
1508
+ }
1509
+ )
1510
+ }
1511
+ );
1512
+ }
1513
+ function Dialog({
1514
+ open,
1515
+ onOpenChange,
1516
+ children,
1517
+ title,
1518
+ description,
1519
+ showCloseButton = true,
1520
+ closeOnOverlayClick = true,
1521
+ closeOnEscapeKey = true,
1522
+ className,
1523
+ contentClassName,
1524
+ overlayClassName,
1525
+ rightSlot,
1526
+ maxWidth,
1527
+ bodyPadding = true
1528
+ }) {
1529
+ const portalContainer = useTaskOnPortalContainer();
1530
+ const contentStyle = maxWidth ? { maxWidth: typeof maxWidth === "number" ? `${maxWidth}px` : maxWidth } : {};
1531
+ const handleInteractOutside = (event) => {
1532
+ if (!closeOnOverlayClick) {
1533
+ event.preventDefault();
1534
+ }
1535
+ };
1536
+ const handleEscapeKeyDown = (event) => {
1537
+ if (!closeOnEscapeKey) {
1538
+ event.preventDefault();
1539
+ }
1540
+ };
1541
+ return /* @__PURE__ */ jsx(Root, { open, onOpenChange, children: /* @__PURE__ */ jsxs(Portal, { container: portalContainer ?? void 0, children: [
1542
+ /* @__PURE__ */ jsx(
1543
+ Overlay,
1544
+ {
1545
+ className: `taskon-dialog-overlay ${overlayClassName || ""}`
1546
+ }
1547
+ ),
1548
+ /* @__PURE__ */ jsxs(
1549
+ Content,
1550
+ {
1551
+ className: `taskon-dialog-content ${contentClassName || ""} ${className || ""}`,
1552
+ style: contentStyle,
1553
+ "aria-describedby": description ? void 0 : void 0,
1554
+ onInteractOutside: handleInteractOutside,
1555
+ onEscapeKeyDown: handleEscapeKeyDown,
1556
+ children: [
1557
+ title && /* @__PURE__ */ jsx(Title, { className: "taskon-dialog-title--sr-only", children: title }),
1558
+ description && /* @__PURE__ */ jsx(Description, { className: "taskon-dialog-description--sr-only", children: description }),
1559
+ (showCloseButton || rightSlot) && /* @__PURE__ */ jsxs("div", { className: "taskon-dialog-header", children: [
1560
+ rightSlot && /* @__PURE__ */ jsx("div", { className: "taskon-dialog-header-slot", children: rightSlot }),
1561
+ showCloseButton && /* @__PURE__ */ jsx(
1562
+ Close,
1563
+ {
1564
+ className: "taskon-dialog-close",
1565
+ "aria-label": "关闭",
1566
+ children: /* @__PURE__ */ jsx(CloseIcon, {})
1567
+ }
1568
+ )
1569
+ ] }),
1570
+ /* @__PURE__ */ jsx(
1571
+ "div",
1572
+ {
1573
+ className: `taskon-dialog-body${bodyPadding ? "" : " taskon-dialog-body--no-padding"}`,
1574
+ children
1575
+ }
1576
+ )
1577
+ ]
1578
+ }
1579
+ )
1580
+ ] }) });
1581
+ }
1582
+ var REACT_LAZY_TYPE = Symbol.for("react.lazy");
1583
+ var use = React[" use ".trim().toString()];
1584
+ function isPromiseLike(value) {
1585
+ return typeof value === "object" && value !== null && "then" in value;
1586
+ }
1587
+ function isLazyComponent(element) {
1588
+ return element != null && typeof element === "object" && "$$typeof" in element && element.$$typeof === REACT_LAZY_TYPE && "_payload" in element && isPromiseLike(element._payload);
1589
+ }
1590
+ // @__NO_SIDE_EFFECTS__
1591
+ function createSlot(ownerName) {
1592
+ const SlotClone = /* @__PURE__ */ createSlotClone(ownerName);
1593
+ const Slot2 = React.forwardRef((props, forwardedRef) => {
1594
+ let { children, ...slotProps } = props;
1595
+ if (isLazyComponent(children) && typeof use === "function") {
1596
+ children = use(children._payload);
1597
+ }
1598
+ const childrenArray = React.Children.toArray(children);
1599
+ const slottable = childrenArray.find(isSlottable);
1600
+ if (slottable) {
1601
+ const newElement = slottable.props.children;
1602
+ const newChildren = childrenArray.map((child) => {
1603
+ if (child === slottable) {
1604
+ if (React.Children.count(newElement) > 1) return React.Children.only(null);
1605
+ return React.isValidElement(newElement) ? newElement.props.children : null;
1606
+ } else {
1607
+ return child;
1608
+ }
1609
+ });
1610
+ return /* @__PURE__ */ jsx(SlotClone, { ...slotProps, ref: forwardedRef, children: React.isValidElement(newElement) ? React.cloneElement(newElement, void 0, newChildren) : null });
1611
+ }
1612
+ return /* @__PURE__ */ jsx(SlotClone, { ...slotProps, ref: forwardedRef, children });
1613
+ });
1614
+ Slot2.displayName = `${ownerName}.Slot`;
1615
+ return Slot2;
1616
+ }
1617
+ var Slot = /* @__PURE__ */ createSlot("Slot");
1618
+ // @__NO_SIDE_EFFECTS__
1619
+ function createSlotClone(ownerName) {
1620
+ const SlotClone = React.forwardRef((props, forwardedRef) => {
1621
+ let { children, ...slotProps } = props;
1622
+ if (isLazyComponent(children) && typeof use === "function") {
1623
+ children = use(children._payload);
1624
+ }
1625
+ if (React.isValidElement(children)) {
1626
+ const childrenRef = getElementRef(children);
1627
+ const props2 = mergeProps(slotProps, children.props);
1628
+ if (children.type !== React.Fragment) {
1629
+ props2.ref = forwardedRef ? composeRefs(forwardedRef, childrenRef) : childrenRef;
1630
+ }
1631
+ return React.cloneElement(children, props2);
1632
+ }
1633
+ return React.Children.count(children) > 1 ? React.Children.only(null) : null;
1634
+ });
1635
+ SlotClone.displayName = `${ownerName}.SlotClone`;
1636
+ return SlotClone;
1637
+ }
1638
+ var SLOTTABLE_IDENTIFIER = Symbol("radix.slottable");
1639
+ function isSlottable(child) {
1640
+ return React.isValidElement(child) && typeof child.type === "function" && "__radixId" in child.type && child.type.__radixId === SLOTTABLE_IDENTIFIER;
1641
+ }
1642
+ function mergeProps(slotProps, childProps) {
1643
+ const overrideProps = { ...childProps };
1644
+ for (const propName in childProps) {
1645
+ const slotPropValue = slotProps[propName];
1646
+ const childPropValue = childProps[propName];
1647
+ const isHandler = /^on[A-Z]/.test(propName);
1648
+ if (isHandler) {
1649
+ if (slotPropValue && childPropValue) {
1650
+ overrideProps[propName] = (...args) => {
1651
+ const result = childPropValue(...args);
1652
+ slotPropValue(...args);
1653
+ return result;
1654
+ };
1655
+ } else if (slotPropValue) {
1656
+ overrideProps[propName] = slotPropValue;
1657
+ }
1658
+ } else if (propName === "style") {
1659
+ overrideProps[propName] = { ...slotPropValue, ...childPropValue };
1660
+ } else if (propName === "className") {
1661
+ overrideProps[propName] = [slotPropValue, childPropValue].filter(Boolean).join(" ");
1662
+ }
1663
+ }
1664
+ return { ...slotProps, ...overrideProps };
1665
+ }
1666
+ function getElementRef(element) {
1667
+ var _a, _b;
1668
+ let getter = (_a = Object.getOwnPropertyDescriptor(element.props, "ref")) == null ? void 0 : _a.get;
1669
+ let mayWarn = getter && "isReactWarning" in getter && getter.isReactWarning;
1670
+ if (mayWarn) {
1671
+ return element.ref;
1672
+ }
1673
+ getter = (_b = Object.getOwnPropertyDescriptor(element, "ref")) == null ? void 0 : _b.get;
1674
+ mayWarn = getter && "isReactWarning" in getter && getter.isReactWarning;
1675
+ if (mayWarn) {
1676
+ return element.props.ref;
1677
+ }
1678
+ return element.props.ref || element.ref;
1679
+ }
1680
+ const Button = forwardRef(
1681
+ ({
1682
+ size = "medium",
1683
+ variant = "primary",
1684
+ loading = false,
1685
+ iconPosition,
1686
+ leftIcon,
1687
+ rightIcon,
1688
+ asChild = false,
1689
+ disabled,
1690
+ className = "",
1691
+ style,
1692
+ children,
1693
+ ...props
1694
+ }, ref) => {
1695
+ const Comp = asChild ? Slot : "button";
1696
+ const actualIconPosition = iconPosition || (leftIcon ? "left" : rightIcon ? "right" : void 0);
1697
+ const isIconOnly = actualIconPosition === "only" || !children && (leftIcon || rightIcon);
1698
+ const baseStyles = {
1699
+ display: "inline-flex",
1700
+ alignItems: "center",
1701
+ justifyContent: "center",
1702
+ gap: "var(--taskon-spacing-xs)",
1703
+ fontFamily: "inherit",
1704
+ fontWeight: 500,
1705
+ lineHeight: 1.5,
1706
+ border: "none",
1707
+ outline: "none",
1708
+ cursor: disabled || loading ? "not-allowed" : "pointer",
1709
+ transition: "all 0.2s ease-in-out",
1710
+ position: "relative",
1711
+ userSelect: "none",
1712
+ whiteSpace: "nowrap",
1713
+ opacity: disabled ? 0.5 : 1,
1714
+ ...style
1715
+ };
1716
+ const sizeStyles = {
1717
+ small: {
1718
+ fontSize: "var(--taskon-font-size-sm)",
1719
+ padding: isIconOnly ? "var(--taskon-spacing-xs)" : "var(--taskon-spacing-xs) var(--taskon-spacing-sm)",
1720
+ borderRadius: "var(--taskon-border-radius-sm)",
1721
+ minWidth: isIconOnly ? "24px" : "64px",
1722
+ height: "24px"
1723
+ },
1724
+ medium: {
1725
+ fontSize: "var(--taskon-font-size)",
1726
+ padding: isIconOnly ? "var(--taskon-spacing-xs)" : "var(--taskon-spacing-xs) var(--taskon-spacing-md)",
1727
+ borderRadius: "var(--taskon-border-radius)",
1728
+ minWidth: isIconOnly ? "32px" : "80px",
1729
+ height: "32px"
1730
+ },
1731
+ large: {
1732
+ fontSize: "var(--taskon-font-size-lg)",
1733
+ padding: isIconOnly ? "var(--taskon-spacing-sm)" : "var(--taskon-spacing-sm) var(--taskon-spacing-lg)",
1734
+ borderRadius: "var(--taskon-border-radius)",
1735
+ minWidth: isIconOnly ? "40px" : "96px",
1736
+ height: "40px"
1737
+ }
1738
+ };
1739
+ const variantStyles = {
1740
+ primary: {
1741
+ backgroundColor: "var(--taskon-color-primary)",
1742
+ color: "var(--taskon-color-text-on-primary)"
1743
+ },
1744
+ secondary: {
1745
+ backgroundColor: "var(--taskon-color-secondary)",
1746
+ color: "var(--taskon-color-text-on-primary)"
1747
+ },
1748
+ outline: {
1749
+ backgroundColor: "transparent",
1750
+ color: "var(--taskon-color-text)",
1751
+ border: "1px solid var(--taskon-color-border)"
1752
+ },
1753
+ ghost: {
1754
+ backgroundColor: "transparent",
1755
+ color: "var(--taskon-color-text)"
1756
+ },
1757
+ danger: {
1758
+ backgroundColor: "var(--taskon-color-error)",
1759
+ color: "var(--taskon-color-text-on-primary)"
1760
+ }
1761
+ };
1762
+ const hoverStyles = {
1763
+ primary: "hover:bg-[var(--taskon-color-primary-hover)] active:bg-[var(--taskon-color-primary-active)]",
1764
+ secondary: "hover:opacity-90 active:opacity-80",
1765
+ outline: "hover:bg-[var(--taskon-color-bg-surface-strong)] active:bg-[var(--taskon-color-bg-surface-strong)]",
1766
+ ghost: "hover:bg-[var(--taskon-color-bg-surface-strong)] active:bg-[var(--taskon-color-bg-surface-strong)]",
1767
+ danger: "hover:opacity-90 active:opacity-80"
1768
+ };
1769
+ const mergedStyle = {
1770
+ ...baseStyles,
1771
+ ...sizeStyles[size],
1772
+ ...variantStyles[variant]
1773
+ };
1774
+ const mergedClassName = `${className} ${hoverStyles[variant]}`.trim();
1775
+ const renderLoadingIndicator = () => {
1776
+ if (!loading) return null;
1777
+ return /* @__PURE__ */ jsx(
1778
+ "span",
1779
+ {
1780
+ style: {
1781
+ display: "inline-block",
1782
+ width: "1em",
1783
+ height: "1em",
1784
+ border: "2px solid currentColor",
1785
+ borderTopColor: "transparent",
1786
+ borderRadius: "50%",
1787
+ animation: "taskon-button-spin 0.6s linear infinite"
1788
+ }
1628
1789
  }
1629
- )
1630
- }
1631
- );
1632
- }
1633
- function Dialog({
1634
- open,
1635
- onOpenChange,
1636
- children,
1637
- title,
1638
- description,
1639
- showCloseButton = true,
1640
- closeOnOverlayClick = true,
1641
- closeOnEscapeKey = true,
1642
- className,
1643
- contentClassName,
1644
- overlayClassName,
1645
- rightSlot,
1646
- maxWidth,
1647
- bodyPadding = true
1648
- }) {
1649
- const portalContainer = useTaskOnPortalContainer();
1650
- const contentStyle = maxWidth ? { maxWidth: typeof maxWidth === "number" ? `${maxWidth}px` : maxWidth } : {};
1651
- const handleInteractOutside = (event) => {
1652
- if (!closeOnOverlayClick) {
1653
- event.preventDefault();
1654
- }
1655
- };
1656
- const handleEscapeKeyDown = (event) => {
1657
- if (!closeOnEscapeKey) {
1658
- event.preventDefault();
1659
- }
1660
- };
1661
- return /* @__PURE__ */ jsx(Root, { open, onOpenChange, children: /* @__PURE__ */ jsxs(Portal, { container: portalContainer ?? void 0, children: [
1662
- /* @__PURE__ */ jsx(
1663
- Overlay,
1664
- {
1665
- className: `taskon-dialog-overlay ${overlayClassName || ""}`
1666
- }
1667
- ),
1668
- /* @__PURE__ */ jsxs(
1669
- Content,
1670
- {
1671
- className: `taskon-dialog-content ${contentClassName || ""} ${className || ""}`,
1672
- style: contentStyle,
1673
- "aria-describedby": description ? void 0 : void 0,
1674
- onInteractOutside: handleInteractOutside,
1675
- onEscapeKeyDown: handleEscapeKeyDown,
1676
- children: [
1677
- title && /* @__PURE__ */ jsx(Title, { className: "taskon-dialog-title--sr-only", children: title }),
1678
- description && /* @__PURE__ */ jsx(Description, { className: "taskon-dialog-description--sr-only", children: description }),
1679
- (showCloseButton || rightSlot) && /* @__PURE__ */ jsxs("div", { className: "taskon-dialog-header", children: [
1680
- rightSlot && /* @__PURE__ */ jsx("div", { className: "taskon-dialog-header-slot", children: rightSlot }),
1681
- showCloseButton && /* @__PURE__ */ jsx(
1682
- Close,
1683
- {
1684
- className: "taskon-dialog-close",
1685
- "aria-label": "关闭",
1686
- children: /* @__PURE__ */ jsx(CloseIcon, {})
1687
- }
1688
- )
1689
- ] }),
1690
- /* @__PURE__ */ jsx(
1691
- "div",
1692
- {
1693
- className: `taskon-dialog-body${bodyPadding ? "" : " taskon-dialog-body--no-padding"}`,
1694
- children
1790
+ );
1791
+ };
1792
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1793
+ /* @__PURE__ */ jsx("style", { children: `
1794
+ @keyframes taskon-button-spin {
1795
+ from {
1796
+ transform: rotate(0deg);
1695
1797
  }
1696
- )
1697
- ]
1698
- }
1699
- )
1700
- ] }) });
1701
- }
1798
+ to {
1799
+ transform: rotate(360deg);
1800
+ }
1801
+ }
1802
+ ` }),
1803
+ /* @__PURE__ */ jsxs(
1804
+ Comp,
1805
+ {
1806
+ ref,
1807
+ disabled: disabled || loading,
1808
+ className: mergedClassName,
1809
+ style: mergedStyle,
1810
+ ...props,
1811
+ children: [
1812
+ loading && renderLoadingIndicator(),
1813
+ !loading && leftIcon && actualIconPosition === "left" && /* @__PURE__ */ jsx("span", { style: { display: "inline-flex" }, children: leftIcon }),
1814
+ !isIconOnly && children,
1815
+ !loading && rightIcon && actualIconPosition === "right" && /* @__PURE__ */ jsx("span", { style: { display: "inline-flex" }, children: rightIcon })
1816
+ ]
1817
+ }
1818
+ )
1819
+ ] });
1820
+ }
1821
+ );
1822
+ Button.displayName = "Button";
1702
1823
  const defaultPaginationMessages = {
1703
1824
  previous: "Previous",
1704
1825
  next: "Next",
@@ -1898,127 +2019,6 @@ function Table({
1898
2019
  loading && data && data.length > 0 && /* @__PURE__ */ jsx("div", { className: "taskon-table__loading-overlay", children: /* @__PURE__ */ jsx("div", { className: "taskon-table__loading-spinner" }) })
1899
2020
  ] });
1900
2021
  }
1901
- function usePagination(options) {
1902
- const { total, pageSize, initialPage = 0, mode = "pagination" } = options;
1903
- const [page, setPage] = useState(initialPage);
1904
- const totalPages = useMemo(() => {
1905
- return Math.max(1, Math.ceil(total / pageSize));
1906
- }, [total, pageSize]);
1907
- const safePage = useMemo(() => {
1908
- return Math.min(page, totalPages - 1);
1909
- }, [page, totalPages]);
1910
- if (safePage !== page) {
1911
- setPage(safePage);
1912
- }
1913
- const hasPrevious = safePage > 0;
1914
- const hasNext = safePage < totalPages - 1;
1915
- const goToPage = useCallback(
1916
- (targetPage) => {
1917
- const validPage = Math.max(0, Math.min(targetPage, totalPages - 1));
1918
- setPage(validPage);
1919
- },
1920
- [totalPages]
1921
- );
1922
- const goToPrevious = useCallback(() => {
1923
- if (hasPrevious) {
1924
- setPage((p) => p - 1);
1925
- }
1926
- }, [hasPrevious]);
1927
- const goToNext = useCallback(() => {
1928
- if (hasNext) {
1929
- setPage((p) => p + 1);
1930
- }
1931
- }, [hasNext]);
1932
- const reset = useCallback(() => {
1933
- setPage(0);
1934
- }, []);
1935
- const startIndex = safePage * pageSize + 1;
1936
- const endIndex = Math.min((safePage + 1) * pageSize, total);
1937
- const hasMore = useMemo(() => {
1938
- if (mode === "infinite") {
1939
- return safePage < totalPages - 1;
1940
- }
1941
- return hasNext;
1942
- }, [mode, safePage, totalPages, hasNext]);
1943
- const loadedCount = useMemo(() => {
1944
- if (mode === "infinite") {
1945
- return Math.min((safePage + 1) * pageSize, total);
1946
- }
1947
- return endIndex - startIndex + 1;
1948
- }, [mode, safePage, pageSize, total, startIndex, endIndex]);
1949
- const loadMore = useCallback(() => {
1950
- if (mode === "infinite" && hasMore) {
1951
- setPage((p) => p + 1);
1952
- }
1953
- }, [mode, hasMore]);
1954
- return {
1955
- page: safePage,
1956
- totalPages,
1957
- hasPrevious,
1958
- hasNext,
1959
- goToPage,
1960
- goToPrevious,
1961
- goToNext,
1962
- reset,
1963
- startIndex,
1964
- endIndex,
1965
- // Infinite 模式专用
1966
- loadMore,
1967
- hasMore,
1968
- loadedCount
1969
- };
1970
- }
1971
- function useWidgetConfig(widgetId) {
1972
- const { client } = useTaskOnContext();
1973
- const [config, setConfig] = useState(null);
1974
- const [isLoading, setIsLoading] = useState(false);
1975
- const [error, setError] = useState(null);
1976
- useEffect(() => {
1977
- if (!widgetId || !client) {
1978
- setConfig(null);
1979
- setIsLoading(false);
1980
- setError(null);
1981
- return;
1982
- }
1983
- let cancelled = false;
1984
- setIsLoading(true);
1985
- setError(null);
1986
- const api = createWidgetApi(client);
1987
- api.getWidgetInfo(widgetId).then((info) => {
1988
- if (!cancelled) {
1989
- setConfig(parseWidgetConfig(info));
1990
- }
1991
- }).catch((err) => {
1992
- if (!cancelled) {
1993
- console.warn("[TaskOn] Failed to load widget config:", err);
1994
- setError(
1995
- err instanceof Error ? err.message : "Failed to load widget config"
1996
- );
1997
- }
1998
- }).finally(() => {
1999
- if (!cancelled) {
2000
- setIsLoading(false);
2001
- }
2002
- });
2003
- return () => {
2004
- cancelled = true;
2005
- };
2006
- }, [widgetId, client]);
2007
- return { config, isLoading, error };
2008
- }
2009
- function useResolvedWidgetConfig(widgetId) {
2010
- const { config, isLoading, error } = useWidgetConfig(widgetId);
2011
- const cloudTheme = useMemo(() => {
2012
- if (!(config == null ? void 0 : config.theme)) return void 0;
2013
- return cloudThemeToReactTheme(config.theme);
2014
- }, [config == null ? void 0 : config.theme]);
2015
- return {
2016
- functionConfig: (config == null ? void 0 : config.functionConfig) ?? null,
2017
- cloudTheme,
2018
- isConfigLoading: isLoading,
2019
- configError: error
2020
- };
2021
- }
2022
2022
  function WidgetShell({
2023
2023
  widgetId,
2024
2024
  isConfigLoading,
@@ -2043,29 +2043,20 @@ function WidgetShell({
2043
2043
  ] }) });
2044
2044
  }
2045
2045
  if (errorMessage) {
2046
- return /* @__PURE__ */ jsx("div", { className, children: /* @__PURE__ */ jsx("div", { className: `${className}-error`, children: /* @__PURE__ */ jsx("span", { className: `${className}-error-message`, children: errorMessage }) }) });
2046
+ return /* @__PURE__ */ jsx("div", { className, children: /* @__PURE__ */ jsx("div", { className: `${className}-error`, children: /* @__PURE__ */ jsx(
2047
+ "span",
2048
+ {
2049
+ className: `${className}-error-message`,
2050
+ style: { overflowWrap: "anywhere", wordBreak: "break-word" },
2051
+ children: errorMessage
2052
+ }
2053
+ ) }) });
2047
2054
  }
2048
2055
  if (resolvedCloudTheme) {
2049
2056
  return /* @__PURE__ */ jsx(ThemeProvider, { theme: resolvedCloudTheme, children });
2050
2057
  }
2051
2058
  return /* @__PURE__ */ jsx(Fragment, { children });
2052
2059
  }
2053
- const __variableDynamicImportRuntimeHelper = (glob, path, segs) => {
2054
- const v = glob[path];
2055
- if (v) {
2056
- return typeof v === "function" ? v() : Promise.resolve(v);
2057
- }
2058
- return new Promise((_, reject) => {
2059
- (typeof queueMicrotask === "function" ? queueMicrotask : setTimeout)(
2060
- reject.bind(
2061
- null,
2062
- new Error(
2063
- "Unknown variable dynamic import: " + path + (path.split("/").length !== segs ? ". Note that variables only represent file names one level deep." : "")
2064
- )
2065
- )
2066
- );
2067
- });
2068
- };
2069
2060
  export {
2070
2061
  Button as B,
2071
2062
  Dialog as D,
@@ -2074,11 +2065,10 @@ export {
2074
2065
  ReactRemoveScroll as R,
2075
2066
  Table as T,
2076
2067
  WidgetShell as W,
2077
- __variableDynamicImportRuntimeHelper as _,
2078
- useResolvedWidgetConfig as a,
2068
+ usePagination as a,
2079
2069
  useId as b,
2080
2070
  cloudThemeToReactTheme as c,
2081
2071
  useFocusGuards as d,
2082
2072
  hideOthers as h,
2083
- usePagination as u
2073
+ useResolvedWidgetConfig as u
2084
2074
  };