sa2kit 2.0.0 → 2.0.2

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 (264) hide show
  1. package/README.md +1 -1
  2. package/dist/CollisionBalls-BpHufX3H.d.mts +41 -0
  3. package/dist/CollisionBalls-BpHufX3H.d.ts +41 -0
  4. package/dist/ConfigService-BxK06xP6.d.mts +262 -0
  5. package/dist/ConfigService-BxK06xP6.d.ts +262 -0
  6. package/dist/UniversalFileService-BpvbZitV.d.mts +139 -0
  7. package/dist/UniversalFileService-GsP6D3Rc.d.ts +139 -0
  8. package/dist/audioDetection/index.d.mts +449 -0
  9. package/dist/audioDetection/index.d.ts +449 -0
  10. package/dist/audioDetection/index.js +1244 -0
  11. package/dist/audioDetection/index.js.map +1 -0
  12. package/dist/audioDetection/index.mjs +1227 -0
  13. package/dist/audioDetection/index.mjs.map +1 -0
  14. package/dist/auth/legacy/core/index.d.mts +42 -0
  15. package/dist/auth/legacy/core/index.d.ts +42 -0
  16. package/dist/auth/legacy/core/index.js +242 -0
  17. package/dist/auth/legacy/core/index.js.map +1 -0
  18. package/dist/auth/legacy/core/index.mjs +226 -0
  19. package/dist/auth/legacy/core/index.mjs.map +1 -0
  20. package/dist/auth/legacy/db/index.d.mts +5 -0
  21. package/dist/auth/legacy/db/index.d.ts +5 -0
  22. package/dist/auth/legacy/db/index.js +261 -0
  23. package/dist/auth/legacy/db/index.js.map +1 -0
  24. package/dist/auth/legacy/db/index.mjs +250 -0
  25. package/dist/auth/legacy/db/index.mjs.map +1 -0
  26. package/dist/auth/legacy/index.d.mts +5 -0
  27. package/dist/auth/legacy/index.d.ts +5 -0
  28. package/dist/auth/legacy/index.js +1107 -0
  29. package/dist/auth/legacy/index.js.map +1 -0
  30. package/dist/auth/legacy/index.mjs +1086 -0
  31. package/dist/auth/legacy/index.mjs.map +1 -0
  32. package/dist/auth/legacy/logic/index.d.mts +9 -0
  33. package/dist/auth/legacy/logic/index.d.ts +9 -0
  34. package/dist/auth/legacy/logic/index.js +194 -0
  35. package/dist/auth/legacy/logic/index.js.map +1 -0
  36. package/dist/auth/legacy/logic/index.mjs +187 -0
  37. package/dist/auth/legacy/logic/index.mjs.map +1 -0
  38. package/dist/auth/legacy/miniapp/index.d.mts +5 -0
  39. package/dist/auth/legacy/miniapp/index.d.ts +5 -0
  40. package/dist/auth/legacy/miniapp/index.js +506 -0
  41. package/dist/auth/legacy/miniapp/index.js.map +1 -0
  42. package/dist/auth/legacy/miniapp/index.mjs +487 -0
  43. package/dist/auth/legacy/miniapp/index.mjs.map +1 -0
  44. package/dist/auth/legacy/routes/index.d.mts +53 -0
  45. package/dist/auth/legacy/routes/index.d.ts +53 -0
  46. package/dist/auth/legacy/routes/index.js +278 -0
  47. package/dist/auth/legacy/routes/index.js.map +1 -0
  48. package/dist/auth/legacy/routes/index.mjs +271 -0
  49. package/dist/auth/legacy/routes/index.mjs.map +1 -0
  50. package/dist/auth/legacy/schema/index.d.mts +401 -0
  51. package/dist/auth/legacy/schema/index.d.ts +401 -0
  52. package/dist/auth/legacy/schema/index.js +50 -0
  53. package/dist/auth/legacy/schema/index.js.map +1 -0
  54. package/dist/auth/legacy/schema/index.mjs +44 -0
  55. package/dist/auth/legacy/schema/index.mjs.map +1 -0
  56. package/dist/auth/legacy/server/index.d.mts +13 -0
  57. package/dist/auth/legacy/server/index.d.ts +13 -0
  58. package/dist/auth/legacy/server/index.js +21 -0
  59. package/dist/auth/legacy/server/index.js.map +1 -0
  60. package/dist/auth/legacy/server/index.mjs +19 -0
  61. package/dist/auth/legacy/server/index.mjs.map +1 -0
  62. package/dist/auth/legacy/services/index.d.mts +40 -0
  63. package/dist/auth/legacy/services/index.d.ts +40 -0
  64. package/dist/auth/legacy/services/index.js +258 -0
  65. package/dist/auth/legacy/services/index.js.map +1 -0
  66. package/dist/auth/legacy/services/index.mjs +252 -0
  67. package/dist/auth/legacy/services/index.mjs.map +1 -0
  68. package/dist/auth/legacy/ui/miniapp/index.d.mts +10 -0
  69. package/dist/auth/legacy/ui/miniapp/index.d.ts +10 -0
  70. package/dist/auth/legacy/ui/miniapp/index.js +298 -0
  71. package/dist/auth/legacy/ui/miniapp/index.js.map +1 -0
  72. package/dist/auth/legacy/ui/miniapp/index.mjs +290 -0
  73. package/dist/auth/legacy/ui/miniapp/index.mjs.map +1 -0
  74. package/dist/auth/legacy/ui/web/index.d.mts +22 -0
  75. package/dist/auth/legacy/ui/web/index.d.ts +22 -0
  76. package/dist/auth/legacy/ui/web/index.js +899 -0
  77. package/dist/auth/legacy/ui/web/index.js.map +1 -0
  78. package/dist/auth/legacy/ui/web/index.mjs +889 -0
  79. package/dist/auth/legacy/ui/web/index.mjs.map +1 -0
  80. package/dist/auth/legacy/web/index.d.mts +5 -0
  81. package/dist/auth/legacy/web/index.d.ts +5 -0
  82. package/dist/auth/legacy/web/index.js +1107 -0
  83. package/dist/auth/legacy/web/index.js.map +1 -0
  84. package/dist/auth/legacy/web/index.mjs +1086 -0
  85. package/dist/auth/legacy/web/index.mjs.map +1 -0
  86. package/dist/auth/rn/index.d.mts +64 -0
  87. package/dist/auth/rn/index.d.ts +64 -0
  88. package/dist/auth/rn/index.js +765 -0
  89. package/dist/auth/rn/index.js.map +1 -0
  90. package/dist/auth/rn/index.mjs +754 -0
  91. package/dist/auth/rn/index.mjs.map +1 -0
  92. package/dist/base-api-client-ACKKt13v.d.mts +277 -0
  93. package/dist/base-api-client-ACKKt13v.d.ts +277 -0
  94. package/dist/boothVaultService-Cn4WPhjg.d.mts +83 -0
  95. package/dist/boothVaultService-Cn4WPhjg.d.ts +83 -0
  96. package/dist/business/index.d.mts +6 -0
  97. package/dist/business/index.d.ts +6 -0
  98. package/dist/business/index.js +1682 -0
  99. package/dist/business/index.js.map +1 -0
  100. package/dist/business/index.mjs +1675 -0
  101. package/dist/business/index.mjs.map +1 -0
  102. package/dist/calendar/index.d.mts +1325 -0
  103. package/dist/calendar/index.d.ts +1325 -0
  104. package/dist/calendar/index.js +5964 -0
  105. package/dist/calendar/index.js.map +1 -0
  106. package/dist/calendar/index.mjs +5878 -0
  107. package/dist/calendar/index.mjs.map +1 -0
  108. package/dist/components/index.d.mts +405 -0
  109. package/dist/components/index.d.ts +405 -0
  110. package/dist/components/index.js +2516 -0
  111. package/dist/components/index.js.map +1 -0
  112. package/dist/components/index.mjs +2396 -0
  113. package/dist/components/index.mjs.map +1 -0
  114. package/dist/drizzle-schema-BNhqj2AZ.d.mts +1114 -0
  115. package/dist/drizzle-schema-BNhqj2AZ.d.ts +1114 -0
  116. package/dist/festivalCard/index.d.mts +75 -0
  117. package/dist/festivalCard/index.d.ts +75 -0
  118. package/dist/festivalCard/index.js +1492 -0
  119. package/dist/festivalCard/index.js.map +1 -0
  120. package/dist/festivalCard/index.mjs +1475 -0
  121. package/dist/festivalCard/index.mjs.map +1 -0
  122. package/dist/festivalCard/server/index.d.mts +120 -0
  123. package/dist/festivalCard/server/index.d.ts +120 -0
  124. package/dist/festivalCard/server/index.js +272 -0
  125. package/dist/festivalCard/server/index.js.map +1 -0
  126. package/dist/festivalCard/server/index.mjs +265 -0
  127. package/dist/festivalCard/server/index.mjs.map +1 -0
  128. package/dist/festivalCardService-CZomuQ4E.d.mts +80 -0
  129. package/dist/festivalCardService-CZomuQ4E.d.ts +80 -0
  130. package/dist/index-1Ag7IBXN.d.ts +144 -0
  131. package/dist/index-DNKZ7-R_.d.mts +184 -0
  132. package/dist/index-DNKZ7-R_.d.ts +184 -0
  133. package/dist/index-DSel44Ke.d.mts +93 -0
  134. package/dist/index-DSel44Ke.d.ts +93 -0
  135. package/dist/index-DdeZSeTJ.d.mts +144 -0
  136. package/dist/index-DrPcMJPc.d.mts +250 -0
  137. package/dist/index-DrPcMJPc.d.ts +250 -0
  138. package/dist/index.d.mts +5333 -0
  139. package/dist/index.d.ts +5333 -0
  140. package/dist/index.js +18809 -0
  141. package/dist/index.js.map +1 -0
  142. package/dist/index.mjs +18533 -0
  143. package/dist/index.mjs.map +1 -0
  144. package/dist/mikuContest/ui/web/index.d.mts +2 -0
  145. package/dist/mikuContest/ui/web/index.d.ts +2 -0
  146. package/dist/mikuContest/ui/web/index.js +353 -0
  147. package/dist/mikuContest/ui/web/index.js.map +1 -0
  148. package/dist/mikuContest/ui/web/index.mjs +343 -0
  149. package/dist/mikuContest/ui/web/index.mjs.map +1 -0
  150. package/dist/mikuFireworks3D/index.d.mts +268 -0
  151. package/dist/mikuFireworks3D/index.d.ts +268 -0
  152. package/dist/mikuFireworks3D/index.js +1267 -0
  153. package/dist/mikuFireworks3D/index.js.map +1 -0
  154. package/dist/mikuFireworks3D/index.mjs +1228 -0
  155. package/dist/mikuFireworks3D/index.mjs.map +1 -0
  156. package/dist/mikuFusionGame/index.d.mts +117 -0
  157. package/dist/mikuFusionGame/index.d.ts +117 -0
  158. package/dist/mikuFusionGame/index.js +1208 -0
  159. package/dist/mikuFusionGame/index.js.map +1 -0
  160. package/dist/mikuFusionGame/index.mjs +1195 -0
  161. package/dist/mikuFusionGame/index.mjs.map +1 -0
  162. package/dist/mmd/admin/index.d.mts +487 -0
  163. package/dist/mmd/admin/index.d.ts +487 -0
  164. package/dist/mmd/admin/index.js +1058 -0
  165. package/dist/mmd/admin/index.js.map +1 -0
  166. package/dist/mmd/admin/index.mjs +1027 -0
  167. package/dist/mmd/admin/index.mjs.map +1 -0
  168. package/dist/mmd/index.d.mts +2467 -0
  169. package/dist/mmd/index.d.ts +2467 -0
  170. package/dist/mmd/index.js +10119 -0
  171. package/dist/mmd/index.js.map +1 -0
  172. package/dist/mmd/index.mjs +10028 -0
  173. package/dist/mmd/index.mjs.map +1 -0
  174. package/dist/mmd/server/index.d.mts +139 -0
  175. package/dist/mmd/server/index.d.ts +139 -0
  176. package/dist/mmd/server/index.js +424 -0
  177. package/dist/mmd/server/index.js.map +1 -0
  178. package/dist/mmd/server/index.mjs +404 -0
  179. package/dist/mmd/server/index.mjs.map +1 -0
  180. package/dist/music/index.d.mts +74 -0
  181. package/dist/music/index.d.ts +74 -0
  182. package/dist/music/index.js +830 -0
  183. package/dist/music/index.js.map +1 -0
  184. package/dist/music/index.mjs +809 -0
  185. package/dist/music/index.mjs.map +1 -0
  186. package/dist/music/server/index.d.mts +1 -0
  187. package/dist/music/server/index.d.ts +1 -0
  188. package/dist/music/server/index.js +194 -0
  189. package/dist/music/server/index.js.map +1 -0
  190. package/dist/music/server/index.mjs +182 -0
  191. package/dist/music/server/index.mjs.map +1 -0
  192. package/dist/navigation/index.d.mts +93 -0
  193. package/dist/navigation/index.d.ts +93 -0
  194. package/dist/navigation/index.js +453 -0
  195. package/dist/navigation/index.js.map +1 -0
  196. package/dist/navigation/index.mjs +443 -0
  197. package/dist/navigation/index.mjs.map +1 -0
  198. package/dist/portfolio/index.d.mts +66 -0
  199. package/dist/portfolio/index.d.ts +66 -0
  200. package/dist/portfolio/index.js +736 -0
  201. package/dist/portfolio/index.js.map +1 -0
  202. package/dist/portfolio/index.mjs +724 -0
  203. package/dist/portfolio/index.mjs.map +1 -0
  204. package/dist/qqbot/server/index.d.mts +216 -0
  205. package/dist/qqbot/server/index.d.ts +216 -0
  206. package/dist/qqbot/server/index.js +394 -0
  207. package/dist/qqbot/server/index.js.map +1 -0
  208. package/dist/qqbot/server/index.mjs +385 -0
  209. package/dist/qqbot/server/index.mjs.map +1 -0
  210. package/dist/qqbot/ui/web/index.d.mts +10 -0
  211. package/dist/qqbot/ui/web/index.d.ts +10 -0
  212. package/dist/qqbot/ui/web/index.js +105 -0
  213. package/dist/qqbot/ui/web/index.js.map +1 -0
  214. package/dist/qqbot/ui/web/index.mjs +99 -0
  215. package/dist/qqbot/ui/web/index.mjs.map +1 -0
  216. package/dist/screenReceiver/index.d.mts +86 -0
  217. package/dist/screenReceiver/index.d.ts +86 -0
  218. package/dist/screenReceiver/index.js +281 -0
  219. package/dist/screenReceiver/index.js.map +1 -0
  220. package/dist/screenReceiver/index.mjs +273 -0
  221. package/dist/screenReceiver/index.mjs.map +1 -0
  222. package/dist/testYourself/admin/index.d.mts +58 -0
  223. package/dist/testYourself/admin/index.d.ts +58 -0
  224. package/dist/testYourself/admin/index.js +1009 -0
  225. package/dist/testYourself/admin/index.js.map +1 -0
  226. package/dist/testYourself/admin/index.mjs +1002 -0
  227. package/dist/testYourself/admin/index.mjs.map +1 -0
  228. package/dist/testYourself/index.d.mts +53 -0
  229. package/dist/testYourself/index.d.ts +53 -0
  230. package/dist/testYourself/index.js +2551 -0
  231. package/dist/testYourself/index.js.map +1 -0
  232. package/dist/testYourself/index.mjs +2531 -0
  233. package/dist/testYourself/index.mjs.map +1 -0
  234. package/dist/testYourself/server/index.d.mts +1029 -0
  235. package/dist/testYourself/server/index.d.ts +1029 -0
  236. package/dist/testYourself/server/index.js +825 -0
  237. package/dist/testYourself/server/index.js.map +1 -0
  238. package/dist/testYourself/server/index.mjs +816 -0
  239. package/dist/testYourself/server/index.mjs.map +1 -0
  240. package/dist/types-BTiaMsBz.d.mts +292 -0
  241. package/dist/types-DyG3ZV9V.d.mts +270 -0
  242. package/dist/types-DyG3ZV9V.d.ts +270 -0
  243. package/dist/types-ERmJyjx8.d.ts +292 -0
  244. package/dist/types-HorDyIRv.d.mts +303 -0
  245. package/dist/types-HorDyIRv.d.ts +303 -0
  246. package/dist/vocaloidBooth/index.d.mts +64 -0
  247. package/dist/vocaloidBooth/index.d.ts +64 -0
  248. package/dist/vocaloidBooth/index.js +376 -0
  249. package/dist/vocaloidBooth/index.js.map +1 -0
  250. package/dist/vocaloidBooth/index.mjs +362 -0
  251. package/dist/vocaloidBooth/index.mjs.map +1 -0
  252. package/dist/vocaloidBooth/server/index.d.mts +111 -0
  253. package/dist/vocaloidBooth/server/index.d.ts +111 -0
  254. package/dist/vocaloidBooth/server/index.js +247 -0
  255. package/dist/vocaloidBooth/server/index.js.map +1 -0
  256. package/dist/vocaloidBooth/server/index.mjs +237 -0
  257. package/dist/vocaloidBooth/server/index.mjs.map +1 -0
  258. package/dist/vocaloidBooth/web/index.d.mts +3 -0
  259. package/dist/vocaloidBooth/web/index.d.ts +3 -0
  260. package/dist/vocaloidBooth/web/index.js +376 -0
  261. package/dist/vocaloidBooth/web/index.js.map +1 -0
  262. package/dist/vocaloidBooth/web/index.mjs +362 -0
  263. package/dist/vocaloidBooth/web/index.mjs.map +1 -0
  264. package/package.json +1 -1
@@ -0,0 +1,2396 @@
1
+ import * as React10 from 'react';
2
+ import React10__default, { useRef, useState, useEffect, useCallback } from 'react';
3
+ import { cva } from 'class-variance-authority';
4
+ import { clsx } from 'clsx';
5
+ import { twMerge } from 'tailwind-merge';
6
+ import { createPortal } from 'react-dom';
7
+ import { X, Check, Circle, ChevronRight, ChevronDown, ChevronUp, RotateCcw, Save, AlertCircle, GripVertical } from 'lucide-react';
8
+ import { useRouter } from 'next/navigation';
9
+
10
+ // src/components/Button.tsx
11
+
12
+ // src/logger/console-adapter.ts
13
+ var ConsoleLoggerAdapter = class {
14
+ constructor() {
15
+ this.colors = {
16
+ DEBUG: "\x1B[36m",
17
+ // Cyan
18
+ INFO: "\x1B[32m",
19
+ // Green
20
+ WARN: "\x1B[33m",
21
+ // Yellow
22
+ ERROR: "\x1B[31m",
23
+ // Red
24
+ RESET: "\x1B[0m"
25
+ };
26
+ }
27
+ log(entry) {
28
+ const { level, message, timestamp, data, context, error } = entry;
29
+ let logMessage = "";
30
+ if (timestamp) {
31
+ logMessage += "[" + this.formatTimestamp(timestamp) + "] ";
32
+ }
33
+ const levelName = this.getLevelName(level);
34
+ logMessage += levelName + ": ";
35
+ if (context) {
36
+ logMessage += "[" + context + "] ";
37
+ }
38
+ logMessage += message;
39
+ switch (level) {
40
+ case 0:
41
+ console.debug(this.colorize(logMessage, "DEBUG"), data || "");
42
+ break;
43
+ case 1:
44
+ console.info(this.colorize(logMessage, "INFO"), data || "");
45
+ break;
46
+ case 2:
47
+ console.warn(this.colorize(logMessage, "WARN"), data || "");
48
+ break;
49
+ case 3:
50
+ console.error(this.colorize(logMessage, "ERROR"), data || "");
51
+ if (error) {
52
+ console.error(error);
53
+ }
54
+ break;
55
+ }
56
+ }
57
+ formatTimestamp(date) {
58
+ return date.toISOString();
59
+ }
60
+ getLevelName(level) {
61
+ const names = ["DEBUG", "INFO", "WARN", "ERROR", "NONE"];
62
+ return names[level] || "UNKNOWN";
63
+ }
64
+ colorize(message, level) {
65
+ if (typeof process !== "undefined" && process.stdout?.isTTY) {
66
+ return this.colors[level] + message + this.colors.RESET;
67
+ }
68
+ return message;
69
+ }
70
+ };
71
+
72
+ // src/logger/Logger.ts
73
+ var Logger = class _Logger {
74
+ constructor(config, context) {
75
+ const isProduction = typeof process !== "undefined" ? process.env.NODE_ENV === "production" : false;
76
+ this.config = {
77
+ minLevel: config?.minLevel ?? (isProduction ? 1 : 0),
78
+ // INFO in prod, DEBUG in dev
79
+ enableTimestamp: config?.enableTimestamp ?? true,
80
+ enableContext: config?.enableContext ?? true,
81
+ environment: config?.environment ?? (isProduction ? "production" : "development"),
82
+ adapter: config?.adapter ?? new ConsoleLoggerAdapter()
83
+ };
84
+ this.adapter = this.config.adapter;
85
+ this.context = context;
86
+ }
87
+ /**
88
+ * 创建带上下文的子 Logger
89
+ */
90
+ createChild(context) {
91
+ return new _Logger(this.config, context);
92
+ }
93
+ /**
94
+ * 调试日志
95
+ */
96
+ debug(message, data) {
97
+ this.log(0, message, data);
98
+ }
99
+ /**
100
+ * 信息日志
101
+ */
102
+ info(message, data) {
103
+ this.log(1, message, data);
104
+ }
105
+ /**
106
+ * 警告日志
107
+ */
108
+ warn(message, data) {
109
+ this.log(2, message, data);
110
+ }
111
+ /**
112
+ * 错误日志
113
+ */
114
+ error(message, error) {
115
+ this.log(
116
+ 3,
117
+ // LogLevel.ERROR
118
+ message,
119
+ error instanceof Error ? void 0 : error,
120
+ error instanceof Error ? error : void 0
121
+ );
122
+ }
123
+ /**
124
+ * 核心日志方法
125
+ */
126
+ log(level, message, data, error) {
127
+ if (level < this.config.minLevel) {
128
+ return;
129
+ }
130
+ if (typeof window !== "undefined" && typeof localStorage !== "undefined") {
131
+ const loggerDebug = localStorage.getItem("logger-debug");
132
+ if (loggerDebug === "false" && level < 3) {
133
+ return;
134
+ }
135
+ }
136
+ const entry = {
137
+ level,
138
+ message,
139
+ timestamp: this.config.enableTimestamp ? /* @__PURE__ */ new Date() : void 0,
140
+ data,
141
+ context: this.config.enableContext ? this.context : void 0,
142
+ error
143
+ };
144
+ this.adapter.log(entry);
145
+ }
146
+ /**
147
+ * 设置日志级别
148
+ */
149
+ setLevel(level) {
150
+ this.config.minLevel = level;
151
+ }
152
+ /**
153
+ * 获取当前日志级别
154
+ */
155
+ getLevel() {
156
+ return this.config.minLevel;
157
+ }
158
+ };
159
+ new Logger();
160
+ function cn(...inputs) {
161
+ return twMerge(clsx(inputs));
162
+ }
163
+
164
+ // src/components/Button.tsx
165
+ var buttonVariants = cva(
166
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
167
+ {
168
+ variants: {
169
+ variant: {
170
+ default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
171
+ destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
172
+ outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
173
+ secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
174
+ ghost: "hover:bg-accent hover:text-accent-foreground",
175
+ link: "text-primary underline-offset-4 hover:underline"
176
+ },
177
+ size: {
178
+ default: "h-9 px-4 py-2",
179
+ sm: "h-8 rounded-md px-3 text-xs",
180
+ lg: "h-10 rounded-md px-8",
181
+ icon: "h-9 w-9"
182
+ }
183
+ },
184
+ defaultVariants: {
185
+ variant: "default",
186
+ size: "default"
187
+ }
188
+ }
189
+ );
190
+ var Button = React10.forwardRef(
191
+ ({ className, variant = "default", size = "default", asChild = false, children, ...props }, ref) => {
192
+ if (asChild && React10.isValidElement(children)) {
193
+ const childProps = children.props;
194
+ return React10.cloneElement(children, {
195
+ ...props,
196
+ className: cn(buttonVariants({ variant, size, className }), childProps.className)
197
+ });
198
+ }
199
+ return /* @__PURE__ */ React10.createElement(
200
+ "button",
201
+ {
202
+ className: cn(buttonVariants({ variant, size, className })),
203
+ ref,
204
+ ...props
205
+ },
206
+ children
207
+ );
208
+ }
209
+ );
210
+ Button.displayName = "Button";
211
+ var Card = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React10.createElement(
212
+ "div",
213
+ {
214
+ ref,
215
+ className: cn(
216
+ "rounded-xl border bg-card text-card-foreground shadow",
217
+ className
218
+ ),
219
+ ...props
220
+ }
221
+ ));
222
+ Card.displayName = "Card";
223
+ var CardHeader = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React10.createElement(
224
+ "div",
225
+ {
226
+ ref,
227
+ className: cn("flex flex-col space-y-1.5 p-6", className),
228
+ ...props
229
+ }
230
+ ));
231
+ CardHeader.displayName = "CardHeader";
232
+ var CardTitle = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React10.createElement(
233
+ "div",
234
+ {
235
+ ref,
236
+ className: cn("font-semibold leading-none tracking-tight", className),
237
+ ...props
238
+ }
239
+ ));
240
+ CardTitle.displayName = "CardTitle";
241
+ var CardDescription = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React10.createElement(
242
+ "div",
243
+ {
244
+ ref,
245
+ className: cn("text-sm text-muted-foreground", className),
246
+ ...props
247
+ }
248
+ ));
249
+ CardDescription.displayName = "CardDescription";
250
+ var CardContent = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React10.createElement("div", { ref, className: cn("p-6 pt-0", className), ...props }));
251
+ CardContent.displayName = "CardContent";
252
+ var CardFooter = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React10.createElement(
253
+ "div",
254
+ {
255
+ ref,
256
+ className: cn("flex items-center p-6 pt-0", className),
257
+ ...props
258
+ }
259
+ ));
260
+ CardFooter.displayName = "CardFooter";
261
+ var badgeVariants = cva(
262
+ "inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
263
+ {
264
+ variants: {
265
+ variant: {
266
+ default: "border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80",
267
+ secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
268
+ destructive: "border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80",
269
+ outline: "text-foreground"
270
+ }
271
+ },
272
+ defaultVariants: {
273
+ variant: "default"
274
+ }
275
+ }
276
+ );
277
+ function Badge({ className, variant, ...props }) {
278
+ return /* @__PURE__ */ React10.createElement("div", { className: cn(badgeVariants({ variant }), className), ...props });
279
+ }
280
+ var Input = React10.forwardRef(
281
+ ({ className, type, ...props }, ref) => {
282
+ return /* @__PURE__ */ React10.createElement(
283
+ "input",
284
+ {
285
+ type,
286
+ className: cn(
287
+ "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
288
+ className
289
+ ),
290
+ ref,
291
+ ...props
292
+ }
293
+ );
294
+ }
295
+ );
296
+ Input.displayName = "Input";
297
+ var labelVariants = cva(
298
+ "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
299
+ );
300
+ var Label = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React10.createElement(
301
+ "label",
302
+ {
303
+ ref,
304
+ className: cn(labelVariants(), className),
305
+ ...props
306
+ }
307
+ ));
308
+ Label.displayName = "Label";
309
+ function useControllableState({
310
+ value,
311
+ defaultValue,
312
+ onChange
313
+ }) {
314
+ const [internal, setInternal] = React10.useState(defaultValue);
315
+ const isControlled = value !== void 0;
316
+ const state = isControlled ? value : internal;
317
+ const setState = React10.useCallback(
318
+ (next) => {
319
+ if (!isControlled) setInternal(next);
320
+ onChange?.(next);
321
+ },
322
+ [isControlled, onChange]
323
+ );
324
+ return [state, setState];
325
+ }
326
+ function Portal({
327
+ children,
328
+ container
329
+ }) {
330
+ const [mounted, setMounted] = React10.useState(false);
331
+ React10.useEffect(() => {
332
+ setMounted(true);
333
+ }, []);
334
+ if (!mounted) return null;
335
+ return createPortal(children, container ?? document.body);
336
+ }
337
+ function useOnClickOutside(refs, handler, enabled) {
338
+ React10.useEffect(() => {
339
+ if (!enabled) return;
340
+ const listener = (event) => {
341
+ const target = event.target;
342
+ const clickedInside = refs.some((ref) => {
343
+ const el = ref.current;
344
+ return el && el.contains(target);
345
+ });
346
+ if (!clickedInside) {
347
+ handler(event);
348
+ }
349
+ };
350
+ document.addEventListener("mousedown", listener);
351
+ document.addEventListener("touchstart", listener);
352
+ return () => {
353
+ document.removeEventListener("mousedown", listener);
354
+ document.removeEventListener("touchstart", listener);
355
+ };
356
+ }, [refs, handler, enabled]);
357
+ }
358
+ function mergeRefs(...refs) {
359
+ return (value) => {
360
+ refs.forEach((ref) => {
361
+ if (!ref) return;
362
+ if (typeof ref === "function") {
363
+ ref(value);
364
+ } else {
365
+ ref.current = value;
366
+ }
367
+ });
368
+ };
369
+ }
370
+
371
+ // src/components/Tabs.tsx
372
+ var TabsContext = React10.createContext(null);
373
+ var Tabs = ({
374
+ value,
375
+ defaultValue = "",
376
+ onValueChange,
377
+ className,
378
+ ...props
379
+ }) => {
380
+ const [current, setCurrent] = useControllableState({
381
+ value,
382
+ defaultValue,
383
+ onChange: onValueChange
384
+ });
385
+ return /* @__PURE__ */ React10.createElement(TabsContext.Provider, { value: { value: current, setValue: setCurrent } }, /* @__PURE__ */ React10.createElement("div", { className, ...props }));
386
+ };
387
+ var TabsList = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React10.createElement(
388
+ "div",
389
+ {
390
+ ref,
391
+ className: cn(
392
+ "inline-flex h-9 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground",
393
+ className
394
+ ),
395
+ ...props
396
+ }
397
+ ));
398
+ TabsList.displayName = "TabsList";
399
+ var TabsTrigger = React10.forwardRef(
400
+ ({ className, value, onClick, ...props }, ref) => {
401
+ const ctx = React10.useContext(TabsContext);
402
+ const active = ctx?.value === value;
403
+ return /* @__PURE__ */ React10.createElement(
404
+ "button",
405
+ {
406
+ ref,
407
+ type: "button",
408
+ "data-state": active ? "active" : "inactive",
409
+ className: cn(
410
+ "inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
411
+ active && "bg-background text-foreground shadow",
412
+ className
413
+ ),
414
+ onClick: (e) => {
415
+ ctx?.setValue(value);
416
+ onClick?.(e);
417
+ },
418
+ ...props
419
+ }
420
+ );
421
+ }
422
+ );
423
+ TabsTrigger.displayName = "TabsTrigger";
424
+ var TabsContent = React10.forwardRef(
425
+ ({ className, value, forceMount = false, ...props }, ref) => {
426
+ const ctx = React10.useContext(TabsContext);
427
+ const active = ctx?.value === value;
428
+ if (!active && !forceMount) return null;
429
+ return /* @__PURE__ */ React10.createElement(
430
+ "div",
431
+ {
432
+ ref,
433
+ "data-state": active ? "active" : "inactive",
434
+ hidden: !active && forceMount,
435
+ className: cn(
436
+ "mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
437
+ className
438
+ ),
439
+ ...props
440
+ }
441
+ );
442
+ }
443
+ );
444
+ TabsContent.displayName = "TabsContent";
445
+ var DialogContext = React10.createContext(null);
446
+ var Dialog = ({ open, defaultOpen = false, onOpenChange, children }) => {
447
+ const [isOpen, setIsOpen] = useControllableState({
448
+ value: open,
449
+ defaultValue: defaultOpen,
450
+ onChange: onOpenChange
451
+ });
452
+ const triggerRef = React10.useRef(null);
453
+ const contentRef = React10.useRef(null);
454
+ return /* @__PURE__ */ React10.createElement(DialogContext.Provider, { value: { open: isOpen, setOpen: setIsOpen, triggerRef, contentRef } }, children);
455
+ };
456
+ var DialogTrigger = React10.forwardRef(
457
+ ({ children, onClick, ...props }, ref) => {
458
+ const ctx = React10.useContext(DialogContext);
459
+ if (!ctx) return null;
460
+ const mergedRef = mergeRefs(ctx.triggerRef, ref);
461
+ const handleClick = (e) => {
462
+ ctx.setOpen(true);
463
+ onClick?.(e);
464
+ };
465
+ return /* @__PURE__ */ React10.createElement("button", { ref: mergedRef, type: "button", onClick: handleClick, ...props }, children);
466
+ }
467
+ );
468
+ DialogTrigger.displayName = "DialogTrigger";
469
+ var DialogPortal = ({ children }) => {
470
+ const ctx = React10.useContext(DialogContext);
471
+ if (!ctx?.open) return null;
472
+ return /* @__PURE__ */ React10.createElement(Portal, null, children);
473
+ };
474
+ var DialogClose = React10.forwardRef(({ onClick, ...props }, ref) => {
475
+ const ctx = React10.useContext(DialogContext);
476
+ return /* @__PURE__ */ React10.createElement(
477
+ "button",
478
+ {
479
+ ref,
480
+ type: "button",
481
+ onClick: (e) => {
482
+ ctx?.setOpen(false);
483
+ onClick?.(e);
484
+ },
485
+ ...props
486
+ }
487
+ );
488
+ });
489
+ DialogClose.displayName = "DialogClose";
490
+ var DialogOverlay = React10.forwardRef(({ className, ...props }, ref) => {
491
+ const ctx = React10.useContext(DialogContext);
492
+ if (!ctx?.open) return null;
493
+ return /* @__PURE__ */ React10.createElement(
494
+ "div",
495
+ {
496
+ ref,
497
+ className: cn("fixed inset-0 z-[9999] bg-black/80", className),
498
+ ...props
499
+ }
500
+ );
501
+ });
502
+ DialogOverlay.displayName = "DialogOverlay";
503
+ var DialogContent = React10.forwardRef(
504
+ ({ className, children, onPointerDownOutside, onEscapeKeyDown, showCloseButton = true, overlayClassName, ...props }, ref) => {
505
+ const ctx = React10.useContext(DialogContext);
506
+ const open = !!ctx?.open;
507
+ useOnClickOutside(
508
+ [ctx?.contentRef ?? { current: null }, ctx?.triggerRef ?? { current: null }],
509
+ (evt) => {
510
+ onPointerDownOutside?.(evt);
511
+ if (!evt.defaultPrevented) {
512
+ ctx?.setOpen(false);
513
+ }
514
+ },
515
+ open
516
+ );
517
+ React10.useEffect(() => {
518
+ if (!open) return;
519
+ const onKey = (e) => {
520
+ if (e.key !== "Escape") return;
521
+ onEscapeKeyDown?.(e);
522
+ if (!e.defaultPrevented) {
523
+ ctx?.setOpen(false);
524
+ }
525
+ };
526
+ document.addEventListener("keydown", onKey);
527
+ return () => document.removeEventListener("keydown", onKey);
528
+ }, [ctx, onEscapeKeyDown, open]);
529
+ if (!ctx || !open) return null;
530
+ return /* @__PURE__ */ React10.createElement(DialogPortal, null, /* @__PURE__ */ React10.createElement(DialogOverlay, { className: overlayClassName }), /* @__PURE__ */ React10.createElement(
531
+ "div",
532
+ {
533
+ ref: mergeRefs(ctx.contentRef, ref),
534
+ className: cn(
535
+ "fixed left-[50%] top-[50%] z-[10000] grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg sm:rounded-lg",
536
+ className
537
+ ),
538
+ ...props
539
+ },
540
+ children,
541
+ showCloseButton ? /* @__PURE__ */ React10.createElement(DialogClose, { className: "absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100" }, /* @__PURE__ */ React10.createElement(X, { className: "h-4 w-4" }), /* @__PURE__ */ React10.createElement("span", { className: "sr-only" }, "Close")) : null
542
+ ));
543
+ }
544
+ );
545
+ DialogContent.displayName = "DialogContent";
546
+ var DialogHeader = ({
547
+ className,
548
+ ...props
549
+ }) => /* @__PURE__ */ React10.createElement(
550
+ "div",
551
+ {
552
+ className: cn(
553
+ "flex flex-col space-y-1.5 text-center sm:text-left",
554
+ className
555
+ ),
556
+ ...props
557
+ }
558
+ );
559
+ DialogHeader.displayName = "DialogHeader";
560
+ var DialogFooter = ({
561
+ className,
562
+ ...props
563
+ }) => /* @__PURE__ */ React10.createElement(
564
+ "div",
565
+ {
566
+ className: cn(
567
+ "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
568
+ className
569
+ ),
570
+ ...props
571
+ }
572
+ );
573
+ DialogFooter.displayName = "DialogFooter";
574
+ var DialogTitle = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React10.createElement(
575
+ "h2",
576
+ {
577
+ ref,
578
+ className: cn(
579
+ "text-lg font-semibold leading-none tracking-tight",
580
+ className
581
+ ),
582
+ ...props
583
+ }
584
+ ));
585
+ DialogTitle.displayName = "DialogTitle";
586
+ var DialogDescription = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React10.createElement(
587
+ "p",
588
+ {
589
+ ref,
590
+ className: cn("text-sm text-muted-foreground", className),
591
+ ...props
592
+ }
593
+ ));
594
+ DialogDescription.displayName = "DialogDescription";
595
+ var AlertDialogContent = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React10.createElement(
596
+ DialogContent,
597
+ {
598
+ ref,
599
+ className: cn("z-[9999]", className),
600
+ ...props
601
+ }
602
+ ));
603
+ AlertDialogContent.displayName = "AlertDialogContent";
604
+ var AlertDialogAction = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React10.createElement(
605
+ DialogClose,
606
+ {
607
+ ref,
608
+ className: cn(buttonVariants(), className),
609
+ ...props
610
+ }
611
+ ));
612
+ AlertDialogAction.displayName = "AlertDialogAction";
613
+ var AlertDialogCancel = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React10.createElement(
614
+ DialogClose,
615
+ {
616
+ ref,
617
+ className: cn(
618
+ buttonVariants({ variant: "outline" }),
619
+ "mt-2 sm:mt-0",
620
+ className
621
+ ),
622
+ ...props
623
+ }
624
+ ));
625
+ AlertDialogCancel.displayName = "AlertDialogCancel";
626
+ var DropdownMenuContext = React10.createContext(null);
627
+ var DropdownMenuRadioGroupContext = React10.createContext(null);
628
+ var DropdownMenu = ({ open, defaultOpen = false, onOpenChange, children }) => {
629
+ const [isOpen, setIsOpen] = useControllableState({
630
+ value: open,
631
+ defaultValue: defaultOpen,
632
+ onChange: onOpenChange
633
+ });
634
+ const triggerRef = React10.useRef(null);
635
+ const contentRef = React10.useRef(null);
636
+ return /* @__PURE__ */ React10.createElement(DropdownMenuContext.Provider, { value: { open: isOpen, setOpen: setIsOpen, triggerRef, contentRef } }, children);
637
+ };
638
+ var DropdownMenuTrigger = React10.forwardRef(({ children, onClick, ...props }, ref) => {
639
+ const ctx = React10.useContext(DropdownMenuContext);
640
+ if (!ctx) return null;
641
+ const mergedRef = mergeRefs(ctx.triggerRef, ref);
642
+ const handleClick = (e) => {
643
+ ctx.setOpen(!ctx.open);
644
+ onClick?.(e);
645
+ };
646
+ return /* @__PURE__ */ React10.createElement("button", { ref: mergedRef, type: "button", onClick: handleClick, ...props }, children);
647
+ });
648
+ DropdownMenuTrigger.displayName = "DropdownMenuTrigger";
649
+ var DropdownMenuGroup = ({ children }) => /* @__PURE__ */ React10.createElement(React10.Fragment, null, children);
650
+ var DropdownMenuPortal = ({ children }) => /* @__PURE__ */ React10.createElement(Portal, null, children);
651
+ var DropdownMenuSub = ({ children }) => /* @__PURE__ */ React10.createElement(React10.Fragment, null, children);
652
+ var DropdownMenuContent = React10.forwardRef(({ className, sideOffset = 4, style, ...props }, ref) => {
653
+ const ctx = React10.useContext(DropdownMenuContext);
654
+ const [pos, setPos] = React10.useState({ top: 0, left: 0 });
655
+ const open = !!ctx?.open;
656
+ const trigger = ctx?.triggerRef.current ?? null;
657
+ React10.useLayoutEffect(() => {
658
+ if (!trigger) return;
659
+ const rect = trigger.getBoundingClientRect();
660
+ setPos({ top: rect.bottom + sideOffset, left: rect.left });
661
+ }, [trigger, sideOffset]);
662
+ useOnClickOutside(
663
+ [ctx?.contentRef ?? { current: null }, ctx?.triggerRef ?? { current: null }],
664
+ () => ctx?.setOpen(false),
665
+ open
666
+ );
667
+ if (!ctx || !open || !trigger) return null;
668
+ return /* @__PURE__ */ React10.createElement(DropdownMenuPortal, null, /* @__PURE__ */ React10.createElement(
669
+ "div",
670
+ {
671
+ ref: mergeRefs(ctx.contentRef, ref),
672
+ className: cn(
673
+ "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md",
674
+ className
675
+ ),
676
+ style: { position: "fixed", top: pos.top, left: pos.left, ...style },
677
+ ...props
678
+ }
679
+ ));
680
+ });
681
+ DropdownMenuContent.displayName = "DropdownMenuContent";
682
+ var DropdownMenuItem = React10.forwardRef(({ className, inset, onSelect, onClick, ...props }, ref) => {
683
+ const ctx = React10.useContext(DropdownMenuContext);
684
+ return /* @__PURE__ */ React10.createElement(
685
+ "button",
686
+ {
687
+ ref,
688
+ type: "button",
689
+ className: cn(
690
+ "relative flex w-full cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground disabled:pointer-events-none disabled:opacity-50",
691
+ inset && "pl-8",
692
+ className
693
+ ),
694
+ onClick: (e) => {
695
+ onSelect?.(e.nativeEvent);
696
+ onClick?.(e);
697
+ if (!e.isDefaultPrevented()) {
698
+ ctx?.setOpen(false);
699
+ }
700
+ },
701
+ ...props
702
+ }
703
+ );
704
+ });
705
+ DropdownMenuItem.displayName = "DropdownMenuItem";
706
+ var DropdownMenuCheckboxItem = React10.forwardRef(({ className, children, checked = false, onCheckedChange, onClick, ...props }, ref) => /* @__PURE__ */ React10.createElement(
707
+ "button",
708
+ {
709
+ ref,
710
+ type: "button",
711
+ className: cn(
712
+ "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground disabled:pointer-events-none disabled:opacity-50",
713
+ className
714
+ ),
715
+ onClick: (e) => {
716
+ onCheckedChange?.(!checked);
717
+ onClick?.(e);
718
+ },
719
+ ...props
720
+ },
721
+ /* @__PURE__ */ React10.createElement("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center" }, checked ? /* @__PURE__ */ React10.createElement(Check, { className: "h-4 w-4" }) : null),
722
+ children
723
+ ));
724
+ DropdownMenuCheckboxItem.displayName = "DropdownMenuCheckboxItem";
725
+ var DropdownMenuRadioGroup = ({
726
+ value,
727
+ onValueChange,
728
+ children
729
+ }) => /* @__PURE__ */ React10.createElement(DropdownMenuRadioGroupContext.Provider, { value: { value, onValueChange } }, children);
730
+ var DropdownMenuRadioItem = React10.forwardRef(({ className, children, value, onClick, ...props }, ref) => {
731
+ const radioCtx = React10.useContext(DropdownMenuRadioGroupContext);
732
+ const menuCtx = React10.useContext(DropdownMenuContext);
733
+ const checked = radioCtx?.value === value;
734
+ return /* @__PURE__ */ React10.createElement(
735
+ "button",
736
+ {
737
+ ref,
738
+ type: "button",
739
+ className: cn(
740
+ "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground disabled:pointer-events-none disabled:opacity-50",
741
+ className
742
+ ),
743
+ onClick: (e) => {
744
+ radioCtx?.onValueChange?.(value);
745
+ onClick?.(e);
746
+ menuCtx?.setOpen(false);
747
+ },
748
+ ...props
749
+ },
750
+ /* @__PURE__ */ React10.createElement("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center" }, checked ? /* @__PURE__ */ React10.createElement(Circle, { className: "h-2 w-2 fill-current" }) : null),
751
+ children
752
+ );
753
+ });
754
+ DropdownMenuRadioItem.displayName = "DropdownMenuRadioItem";
755
+ var DropdownMenuLabel = React10.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ React10.createElement(
756
+ "div",
757
+ {
758
+ ref,
759
+ className: cn("px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className),
760
+ ...props
761
+ }
762
+ ));
763
+ DropdownMenuLabel.displayName = "DropdownMenuLabel";
764
+ var DropdownMenuSeparator = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React10.createElement(
765
+ "div",
766
+ {
767
+ ref,
768
+ className: cn("-mx-1 my-1 h-px bg-muted", className),
769
+ ...props
770
+ }
771
+ ));
772
+ DropdownMenuSeparator.displayName = "DropdownMenuSeparator";
773
+ var DropdownMenuShortcut = ({
774
+ className,
775
+ ...props
776
+ }) => /* @__PURE__ */ React10.createElement(
777
+ "span",
778
+ {
779
+ className: cn("ml-auto text-xs tracking-widest opacity-60", className),
780
+ ...props
781
+ }
782
+ );
783
+ DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
784
+ var DropdownMenuSubTrigger = React10.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ React10.createElement(
785
+ "button",
786
+ {
787
+ ref,
788
+ type: "button",
789
+ className: cn(
790
+ "flex w-full cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent",
791
+ inset && "pl-8",
792
+ className
793
+ ),
794
+ ...props
795
+ },
796
+ children,
797
+ /* @__PURE__ */ React10.createElement(ChevronRight, { className: "ml-auto" })
798
+ ));
799
+ DropdownMenuSubTrigger.displayName = "DropdownMenuSubTrigger";
800
+ var DropdownMenuSubContent = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React10.createElement(
801
+ "div",
802
+ {
803
+ ref,
804
+ className: cn(
805
+ "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg",
806
+ className
807
+ ),
808
+ ...props
809
+ }
810
+ ));
811
+ DropdownMenuSubContent.displayName = "DropdownMenuSubContent";
812
+ var PopoverContext = React10.createContext(null);
813
+ var Popover = ({ open, defaultOpen = false, onOpenChange, children }) => {
814
+ const [isOpen, setIsOpen] = useControllableState({
815
+ value: open,
816
+ defaultValue: defaultOpen,
817
+ onChange: onOpenChange
818
+ });
819
+ const triggerRef = React10.useRef(null);
820
+ const anchorRef = React10.useRef(null);
821
+ const contentRef = React10.useRef(null);
822
+ return /* @__PURE__ */ React10.createElement(PopoverContext.Provider, { value: { open: isOpen, setOpen: setIsOpen, triggerRef, anchorRef, contentRef } }, children);
823
+ };
824
+ var PopoverTrigger = React10.forwardRef(
825
+ ({ children, onClick, ...props }, ref) => {
826
+ const ctx = React10.useContext(PopoverContext);
827
+ if (!ctx) return null;
828
+ const mergedRef = mergeRefs(ctx.triggerRef, ref);
829
+ const handleClick = (e) => {
830
+ ctx.setOpen(!ctx.open);
831
+ onClick?.(e);
832
+ };
833
+ return /* @__PURE__ */ React10.createElement("button", { ref: mergedRef, type: "button", onClick: handleClick, ...props }, children);
834
+ }
835
+ );
836
+ PopoverTrigger.displayName = "PopoverTrigger";
837
+ var PopoverAnchor = React10.forwardRef(
838
+ ({ ...props }, ref) => {
839
+ const ctx = React10.useContext(PopoverContext);
840
+ if (!ctx) return null;
841
+ return /* @__PURE__ */ React10.createElement("span", { ref: mergeRefs(ctx.anchorRef, ref), ...props });
842
+ }
843
+ );
844
+ PopoverAnchor.displayName = "PopoverAnchor";
845
+ var PopoverContent = React10.forwardRef(
846
+ ({ className, align = "center", sideOffset = 4, style, ...props }, ref) => {
847
+ const ctx = React10.useContext(PopoverContext);
848
+ const [position, setPosition] = React10.useState({ top: 0, left: 0 });
849
+ const open = !!ctx?.open;
850
+ const anchor = ctx?.anchorRef.current ?? ctx?.triggerRef.current ?? null;
851
+ React10.useLayoutEffect(() => {
852
+ if (!anchor) return;
853
+ const rect = anchor.getBoundingClientRect();
854
+ let left = rect.left + rect.width / 2;
855
+ if (align === "start") left = rect.left;
856
+ if (align === "end") left = rect.right;
857
+ setPosition({ top: rect.bottom + sideOffset, left });
858
+ }, [anchor, align, sideOffset]);
859
+ useOnClickOutside(
860
+ [ctx?.contentRef ?? { current: null }, ctx?.triggerRef ?? { current: null }],
861
+ () => ctx?.setOpen(false),
862
+ open
863
+ );
864
+ if (!ctx || !open) return null;
865
+ return /* @__PURE__ */ React10.createElement(Portal, null, /* @__PURE__ */ React10.createElement(
866
+ "div",
867
+ {
868
+ ref: mergeRefs(ctx.contentRef, ref),
869
+ className: cn(
870
+ "z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none",
871
+ className
872
+ ),
873
+ style: {
874
+ position: "fixed",
875
+ top: position.top,
876
+ left: position.left,
877
+ transform: align === "center" ? "translateX(-50%)" : align === "end" ? "translateX(-100%)" : void 0,
878
+ ...style
879
+ },
880
+ ...props
881
+ }
882
+ ));
883
+ }
884
+ );
885
+ PopoverContent.displayName = "PopoverContent";
886
+ var Progress = React10.forwardRef(
887
+ ({ className, value = 0, max = 100, ...props }, ref) => {
888
+ const safeMax = max <= 0 ? 100 : max;
889
+ const safeValue = Math.max(0, Math.min(value, safeMax));
890
+ const percent = safeValue / safeMax * 100;
891
+ return /* @__PURE__ */ React10.createElement(
892
+ "div",
893
+ {
894
+ ref,
895
+ role: "progressbar",
896
+ "aria-valuemin": 0,
897
+ "aria-valuemax": safeMax,
898
+ "aria-valuenow": safeValue,
899
+ className: cn(
900
+ "relative h-2 w-full overflow-hidden rounded-full bg-primary/20",
901
+ className
902
+ ),
903
+ ...props
904
+ },
905
+ /* @__PURE__ */ React10.createElement(
906
+ "div",
907
+ {
908
+ className: "h-full w-full flex-1 bg-primary transition-all",
909
+ style: { transform: `translateX(-${100 - percent}%)` }
910
+ }
911
+ )
912
+ );
913
+ }
914
+ );
915
+ Progress.displayName = "Progress";
916
+ var ScrollArea = React10.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ React10.createElement(
917
+ "div",
918
+ {
919
+ ref,
920
+ className: cn("relative overflow-auto", className),
921
+ ...props
922
+ },
923
+ children
924
+ ));
925
+ ScrollArea.displayName = "ScrollArea";
926
+ var ScrollBar = React10.forwardRef(
927
+ ({ className, orientation = "vertical", ...props }, ref) => /* @__PURE__ */ React10.createElement(
928
+ "div",
929
+ {
930
+ ref,
931
+ className: cn(
932
+ "pointer-events-none absolute",
933
+ orientation === "vertical" ? "right-0 top-0 h-full w-2.5" : "bottom-0 left-0 h-2.5 w-full",
934
+ className
935
+ ),
936
+ ...props
937
+ }
938
+ )
939
+ );
940
+ ScrollBar.displayName = "ScrollBar";
941
+ var SelectContext = React10.createContext(null);
942
+ var SelectGroupContext = React10.createContext(false);
943
+ var Select = ({
944
+ value,
945
+ defaultValue,
946
+ onValueChange,
947
+ open,
948
+ defaultOpen = false,
949
+ onOpenChange,
950
+ disabled = false,
951
+ children
952
+ }) => {
953
+ const [isOpen, setIsOpen] = useControllableState({
954
+ value: open,
955
+ defaultValue: defaultOpen,
956
+ onChange: onOpenChange
957
+ });
958
+ const [currentValue, setCurrentValue] = useControllableState({
959
+ value,
960
+ defaultValue,
961
+ onChange: (next) => {
962
+ if (next !== void 0) {
963
+ onValueChange?.(next);
964
+ }
965
+ }
966
+ });
967
+ const triggerRef = React10.useRef(null);
968
+ const contentRef = React10.useRef(null);
969
+ const itemsRef = React10.useRef(/* @__PURE__ */ new Map());
970
+ return /* @__PURE__ */ React10.createElement(
971
+ SelectContext.Provider,
972
+ {
973
+ value: {
974
+ open: disabled ? false : isOpen,
975
+ setOpen: disabled ? () => void 0 : setIsOpen,
976
+ value: currentValue,
977
+ setValue: (next) => {
978
+ if (disabled) return;
979
+ setCurrentValue(next);
980
+ setIsOpen(false);
981
+ },
982
+ triggerRef,
983
+ contentRef,
984
+ itemsRef
985
+ }
986
+ },
987
+ children
988
+ );
989
+ };
990
+ var SelectGroup = ({ children }) => /* @__PURE__ */ React10.createElement(SelectGroupContext.Provider, { value: true }, children);
991
+ var SelectValue = ({
992
+ placeholder,
993
+ children
994
+ }) => {
995
+ const ctx = React10.useContext(SelectContext);
996
+ if (!ctx) return null;
997
+ if (children) return /* @__PURE__ */ React10.createElement(React10.Fragment, null, children);
998
+ if (ctx.value && ctx.itemsRef.current.has(ctx.value)) {
999
+ return /* @__PURE__ */ React10.createElement(React10.Fragment, null, ctx.itemsRef.current.get(ctx.value));
1000
+ }
1001
+ return /* @__PURE__ */ React10.createElement("span", { className: "text-muted-foreground" }, placeholder);
1002
+ };
1003
+ var SelectTrigger = React10.forwardRef(({ className, children, onClick, ...props }, ref) => {
1004
+ const ctx = React10.useContext(SelectContext);
1005
+ if (!ctx) return null;
1006
+ return /* @__PURE__ */ React10.createElement(
1007
+ "button",
1008
+ {
1009
+ ref: mergeRefs(ctx.triggerRef, ref),
1010
+ type: "button",
1011
+ className: cn(
1012
+ "flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
1013
+ className
1014
+ ),
1015
+ onClick: (e) => {
1016
+ ctx.setOpen(!ctx.open);
1017
+ onClick?.(e);
1018
+ },
1019
+ ...props
1020
+ },
1021
+ /* @__PURE__ */ React10.createElement("span", null, children),
1022
+ /* @__PURE__ */ React10.createElement(ChevronDown, { className: "h-4 w-4 opacity-50" })
1023
+ );
1024
+ });
1025
+ SelectTrigger.displayName = "SelectTrigger";
1026
+ var SelectScrollUpButton = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React10.createElement(
1027
+ "div",
1028
+ {
1029
+ ref,
1030
+ className: cn("flex cursor-default items-center justify-center py-1", className),
1031
+ ...props
1032
+ },
1033
+ /* @__PURE__ */ React10.createElement(ChevronUp, { className: "h-4 w-4" })
1034
+ ));
1035
+ SelectScrollUpButton.displayName = "SelectScrollUpButton";
1036
+ var SelectScrollDownButton = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React10.createElement(
1037
+ "div",
1038
+ {
1039
+ ref,
1040
+ className: cn("flex cursor-default items-center justify-center py-1", className),
1041
+ ...props
1042
+ },
1043
+ /* @__PURE__ */ React10.createElement(ChevronDown, { className: "h-4 w-4" })
1044
+ ));
1045
+ SelectScrollDownButton.displayName = "SelectScrollDownButton";
1046
+ var SelectContent = React10.forwardRef(({ className, children, style, ...props }, ref) => {
1047
+ const ctx = React10.useContext(SelectContext);
1048
+ const [pos, setPos] = React10.useState({ top: 0, left: 0, width: 0 });
1049
+ const open = !!ctx?.open;
1050
+ const trigger = ctx?.triggerRef.current ?? null;
1051
+ React10.useLayoutEffect(() => {
1052
+ if (!trigger) return;
1053
+ const rect = trigger.getBoundingClientRect();
1054
+ setPos({ top: rect.bottom + 4, left: rect.left, width: rect.width });
1055
+ }, [trigger]);
1056
+ useOnClickOutside(
1057
+ [ctx?.contentRef ?? { current: null }, ctx?.triggerRef ?? { current: null }],
1058
+ () => ctx?.setOpen(false),
1059
+ open
1060
+ );
1061
+ if (!ctx || !open || !trigger) return null;
1062
+ return /* @__PURE__ */ React10.createElement(Portal, null, /* @__PURE__ */ React10.createElement(
1063
+ "div",
1064
+ {
1065
+ ref: mergeRefs(ctx.contentRef, ref),
1066
+ className: cn(
1067
+ "relative z-50 max-h-80 overflow-y-auto overflow-x-hidden rounded-md border bg-popover text-popover-foreground shadow-md",
1068
+ className
1069
+ ),
1070
+ style: {
1071
+ position: "fixed",
1072
+ top: pos.top,
1073
+ left: pos.left,
1074
+ minWidth: Math.max(pos.width, 128),
1075
+ ...style
1076
+ },
1077
+ ...props
1078
+ },
1079
+ /* @__PURE__ */ React10.createElement("div", { className: "p-1" }, children)
1080
+ ));
1081
+ });
1082
+ SelectContent.displayName = "SelectContent";
1083
+ var SelectLabel = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React10.createElement(
1084
+ "div",
1085
+ {
1086
+ ref,
1087
+ className: cn("px-2 py-1.5 text-sm font-semibold", className),
1088
+ ...props
1089
+ }
1090
+ ));
1091
+ SelectLabel.displayName = "SelectLabel";
1092
+ var SelectItem = React10.forwardRef(
1093
+ ({ className, children, value, onClick, ...props }, ref) => {
1094
+ const ctx = React10.useContext(SelectContext);
1095
+ React10.useEffect(() => {
1096
+ if (!ctx) return;
1097
+ ctx.itemsRef.current.set(value, children);
1098
+ return () => {
1099
+ ctx.itemsRef.current.delete(value);
1100
+ };
1101
+ }, [ctx, value, children]);
1102
+ if (!ctx) return null;
1103
+ const selected = ctx.value === value;
1104
+ return /* @__PURE__ */ React10.createElement(
1105
+ "button",
1106
+ {
1107
+ ref,
1108
+ type: "button",
1109
+ className: cn(
1110
+ "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none hover:bg-accent hover:text-accent-foreground disabled:pointer-events-none disabled:opacity-50",
1111
+ className
1112
+ ),
1113
+ onClick: (e) => {
1114
+ ctx.setValue(value);
1115
+ onClick?.(e);
1116
+ },
1117
+ ...props
1118
+ },
1119
+ /* @__PURE__ */ React10.createElement("span", { className: "absolute right-2 flex h-3.5 w-3.5 items-center justify-center" }, selected ? /* @__PURE__ */ React10.createElement(Check, { className: "h-4 w-4" }) : null),
1120
+ /* @__PURE__ */ React10.createElement("span", null, children)
1121
+ );
1122
+ }
1123
+ );
1124
+ SelectItem.displayName = "SelectItem";
1125
+ var SelectSeparator = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React10.createElement(
1126
+ "div",
1127
+ {
1128
+ ref,
1129
+ className: cn("-mx-1 my-1 h-px bg-muted", className),
1130
+ ...props
1131
+ }
1132
+ ));
1133
+ SelectSeparator.displayName = "SelectSeparator";
1134
+ var Separator = React10.forwardRef(
1135
+ ({ className, orientation = "horizontal", decorative = true, ...props }, ref) => /* @__PURE__ */ React10.createElement(
1136
+ "div",
1137
+ {
1138
+ ref,
1139
+ role: decorative ? void 0 : "separator",
1140
+ "aria-orientation": orientation,
1141
+ className: cn(
1142
+ "shrink-0 bg-border",
1143
+ orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
1144
+ className
1145
+ ),
1146
+ ...props
1147
+ }
1148
+ )
1149
+ );
1150
+ Separator.displayName = "Separator";
1151
+ var sheetVariants = cva(
1152
+ "fixed z-[10000] gap-4 bg-background p-6 shadow-lg transition ease-in-out translate-x-0 translate-y-0",
1153
+ {
1154
+ variants: {
1155
+ side: {
1156
+ top: "inset-x-0 top-0 left-0 border-b",
1157
+ bottom: "inset-x-0 bottom-0 left-0 border-t",
1158
+ left: "inset-y-0 left-0 top-0 h-full w-3/4 border-r sm:max-w-sm",
1159
+ right: "inset-y-0 right-0 top-0 h-full w-3/4 border-l sm:max-w-sm"
1160
+ }
1161
+ },
1162
+ defaultVariants: {
1163
+ side: "right"
1164
+ }
1165
+ }
1166
+ );
1167
+ var SheetContent = React10.forwardRef(
1168
+ ({ side = "right", className, children, ...props }, ref) => /* @__PURE__ */ React10.createElement(
1169
+ DialogContent,
1170
+ {
1171
+ ref,
1172
+ className: cn(
1173
+ "max-w-none rounded-none",
1174
+ sheetVariants({ side }),
1175
+ className
1176
+ ),
1177
+ showCloseButton: false,
1178
+ ...props
1179
+ },
1180
+ /* @__PURE__ */ React10.createElement(DialogClose, { className: "absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100" }, /* @__PURE__ */ React10.createElement(X, { className: "h-4 w-4" }), /* @__PURE__ */ React10.createElement("span", { className: "sr-only" }, "Close")),
1181
+ children
1182
+ )
1183
+ );
1184
+ SheetContent.displayName = "SheetContent";
1185
+ var SheetHeader = ({
1186
+ className,
1187
+ ...props
1188
+ }) => /* @__PURE__ */ React10.createElement(
1189
+ "div",
1190
+ {
1191
+ className: cn(
1192
+ "flex flex-col space-y-2 text-center sm:text-left",
1193
+ className
1194
+ ),
1195
+ ...props
1196
+ }
1197
+ );
1198
+ SheetHeader.displayName = "SheetHeader";
1199
+ var SheetFooter = ({
1200
+ className,
1201
+ ...props
1202
+ }) => /* @__PURE__ */ React10.createElement(
1203
+ "div",
1204
+ {
1205
+ className: cn(
1206
+ "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
1207
+ className
1208
+ ),
1209
+ ...props
1210
+ }
1211
+ );
1212
+ SheetFooter.displayName = "SheetFooter";
1213
+ var SheetTitle = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React10.createElement(
1214
+ "h2",
1215
+ {
1216
+ ref,
1217
+ className: cn("text-lg font-semibold text-foreground", className),
1218
+ ...props
1219
+ }
1220
+ ));
1221
+ SheetTitle.displayName = "SheetTitle";
1222
+ var SheetDescription = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React10.createElement(
1223
+ "p",
1224
+ {
1225
+ ref,
1226
+ className: cn("text-sm text-muted-foreground", className),
1227
+ ...props
1228
+ }
1229
+ ));
1230
+ SheetDescription.displayName = "SheetDescription";
1231
+ var Textarea = React10.forwardRef(({ className, ...props }, ref) => {
1232
+ return /* @__PURE__ */ React10.createElement(
1233
+ "textarea",
1234
+ {
1235
+ className: cn(
1236
+ "flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
1237
+ className
1238
+ ),
1239
+ ref,
1240
+ ...props
1241
+ }
1242
+ );
1243
+ });
1244
+ Textarea.displayName = "Textarea";
1245
+ var TooltipConfigContext = React10.createContext({
1246
+ delayDuration: 200
1247
+ });
1248
+ var TooltipContext = React10.createContext(null);
1249
+ var TooltipProvider = ({
1250
+ children,
1251
+ delayDuration = 200
1252
+ }) => {
1253
+ return /* @__PURE__ */ React10.createElement(TooltipConfigContext.Provider, { value: { delayDuration } }, children);
1254
+ };
1255
+ var Tooltip = ({ children }) => {
1256
+ const [open, setOpen] = React10.useState(false);
1257
+ const triggerRef = React10.useRef(null);
1258
+ return /* @__PURE__ */ React10.createElement(TooltipContext.Provider, { value: { open, setOpen, triggerRef } }, children);
1259
+ };
1260
+ var TooltipTrigger = React10.forwardRef(({ children, ...props }, ref) => {
1261
+ const ctx = React10.useContext(TooltipContext);
1262
+ const cfg = React10.useContext(TooltipConfigContext);
1263
+ const timer = React10.useRef(null);
1264
+ if (!ctx) return null;
1265
+ const setRef = mergeRefs(ctx.triggerRef, ref);
1266
+ const openWithDelay = () => {
1267
+ if (timer.current) clearTimeout(timer.current);
1268
+ timer.current = setTimeout(() => ctx.setOpen(true), cfg.delayDuration);
1269
+ };
1270
+ const closeNow = () => {
1271
+ if (timer.current) clearTimeout(timer.current);
1272
+ ctx.setOpen(false);
1273
+ };
1274
+ const shared = {
1275
+ onMouseEnter: openWithDelay,
1276
+ onMouseLeave: closeNow,
1277
+ onFocus: openWithDelay,
1278
+ onBlur: closeNow,
1279
+ ...props
1280
+ };
1281
+ return /* @__PURE__ */ React10.createElement("span", { ref: setRef, ...shared }, children);
1282
+ });
1283
+ TooltipTrigger.displayName = "TooltipTrigger";
1284
+ var TooltipContent = React10.forwardRef(({ className, sideOffset = 4, style, ...props }, ref) => {
1285
+ const ctx = React10.useContext(TooltipContext);
1286
+ const [pos, setPos] = React10.useState({ top: 0, left: 0 });
1287
+ const open = !!ctx?.open;
1288
+ const trigger = ctx?.triggerRef.current ?? null;
1289
+ React10.useLayoutEffect(() => {
1290
+ if (!trigger) return;
1291
+ const rect = trigger.getBoundingClientRect();
1292
+ setPos({
1293
+ top: rect.top - sideOffset,
1294
+ left: rect.left + rect.width / 2
1295
+ });
1296
+ }, [trigger, sideOffset]);
1297
+ if (!ctx || !open || !trigger) return null;
1298
+ return /* @__PURE__ */ React10.createElement(Portal, null, /* @__PURE__ */ React10.createElement(
1299
+ "div",
1300
+ {
1301
+ ref,
1302
+ className: cn(
1303
+ "z-50 overflow-hidden rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground",
1304
+ className
1305
+ ),
1306
+ style: {
1307
+ position: "fixed",
1308
+ top: pos.top,
1309
+ left: pos.left,
1310
+ transform: "translate(-50%, -100%)",
1311
+ ...style
1312
+ },
1313
+ ...props
1314
+ }
1315
+ ));
1316
+ });
1317
+ TooltipContent.displayName = "TooltipContent";
1318
+ var AvatarContext = React10.createContext(null);
1319
+ var Avatar = React10.forwardRef(({ className, ...props }, ref) => {
1320
+ const [status, setStatus] = React10.useState("idle");
1321
+ return /* @__PURE__ */ React10.createElement(AvatarContext.Provider, { value: { status, setStatus } }, /* @__PURE__ */ React10.createElement(
1322
+ "span",
1323
+ {
1324
+ ref,
1325
+ className: cn(
1326
+ "relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full",
1327
+ className
1328
+ ),
1329
+ ...props
1330
+ }
1331
+ ));
1332
+ });
1333
+ Avatar.displayName = "Avatar";
1334
+ var AvatarImage = React10.forwardRef(({ className, onLoad, onError, ...props }, ref) => {
1335
+ const ctx = React10.useContext(AvatarContext);
1336
+ return /* @__PURE__ */ React10.createElement(
1337
+ "img",
1338
+ {
1339
+ ref,
1340
+ className: cn(
1341
+ "aspect-square h-full w-full",
1342
+ ctx?.status === "error" ? "hidden" : void 0,
1343
+ className
1344
+ ),
1345
+ onLoad: (e) => {
1346
+ ctx?.setStatus("loaded");
1347
+ onLoad?.(e);
1348
+ },
1349
+ onError: (e) => {
1350
+ ctx?.setStatus("error");
1351
+ onError?.(e);
1352
+ },
1353
+ ...props
1354
+ }
1355
+ );
1356
+ });
1357
+ AvatarImage.displayName = "AvatarImage";
1358
+ var AvatarFallback = React10.forwardRef(({ className, ...props }, ref) => {
1359
+ const ctx = React10.useContext(AvatarContext);
1360
+ const show = ctx?.status !== "loaded";
1361
+ if (!show) return null;
1362
+ return /* @__PURE__ */ React10.createElement(
1363
+ "span",
1364
+ {
1365
+ ref,
1366
+ className: cn(
1367
+ "flex h-full w-full items-center justify-center rounded-full bg-muted",
1368
+ className
1369
+ ),
1370
+ ...props
1371
+ }
1372
+ );
1373
+ });
1374
+ AvatarFallback.displayName = "AvatarFallback";
1375
+ function buildGridColsClasses(columns) {
1376
+ return [
1377
+ "grid-cols-1",
1378
+ // 默认单列
1379
+ columns.sm ? "sm:grid-cols-" + columns.sm : "",
1380
+ columns.md ? "md:grid-cols-" + columns.md : "md:grid-cols-2",
1381
+ columns.lg ? "lg:grid-cols-" + columns.lg : "lg:grid-cols-3",
1382
+ columns.xl ? "xl:grid-cols-" + columns.xl : ""
1383
+ ].filter(Boolean).join(" ");
1384
+ }
1385
+ function getGapClassName(gap) {
1386
+ const gapClasses = {
1387
+ sm: "gap-3",
1388
+ md: "gap-6",
1389
+ lg: "gap-8",
1390
+ xl: "gap-10"
1391
+ };
1392
+ return gapClasses[gap];
1393
+ }
1394
+ function Grid({
1395
+ items,
1396
+ renderItem,
1397
+ columns = { md: 2, lg: 3 },
1398
+ gap = "md",
1399
+ className = "",
1400
+ style
1401
+ }) {
1402
+ const gridColsClasses = buildGridColsClasses(columns);
1403
+ const gapClass = getGapClassName(gap);
1404
+ return /* @__PURE__ */ React10__default.createElement(
1405
+ "div",
1406
+ {
1407
+ className: clsx("grid", gridColsClasses, gapClass, className),
1408
+ style
1409
+ },
1410
+ items.map((item, index) => /* @__PURE__ */ React10__default.createElement("div", { key: item.id }, renderItem(item, index)))
1411
+ );
1412
+ }
1413
+ var SearchBox = ({
1414
+ searchQuery,
1415
+ onSearchChange,
1416
+ placeholder = "\u641C\u7D22\u5B9E\u9A8C\u9879\u76EE\u7684\u6807\u9898\u3001\u63CF\u8FF0\u6216\u6807\u7B7E...",
1417
+ size = "large"
1418
+ }) => {
1419
+ const getSizeStyles = () => {
1420
+ switch (size) {
1421
+ case "small":
1422
+ return {
1423
+ container: "h-10",
1424
+ input: "pl-10 pr-10 text-sm",
1425
+ icon: "w-4 h-4",
1426
+ iconPosition: "left-3",
1427
+ clearButton: "right-2 w-6 h-6",
1428
+ clearIcon: "w-3 h-3"
1429
+ };
1430
+ case "medium":
1431
+ return {
1432
+ container: "h-12",
1433
+ input: "pl-12 pr-12 text-base",
1434
+ icon: "w-5 h-5",
1435
+ iconPosition: "left-3",
1436
+ clearButton: "right-3 w-7 h-7",
1437
+ clearIcon: "w-4 h-4"
1438
+ };
1439
+ case "large":
1440
+ default:
1441
+ return {
1442
+ container: "h-16",
1443
+ input: "pl-6 pr-16 text-lg",
1444
+ icon: "w-6 h-6",
1445
+ iconPosition: "left-6",
1446
+ clearButton: "right-4 w-8 h-8",
1447
+ clearIcon: "w-4 h-4"
1448
+ };
1449
+ }
1450
+ };
1451
+ const styles = getSizeStyles();
1452
+ const isLarge = size === "large";
1453
+ return /* @__PURE__ */ React10__default.createElement("div", { className: "relative group w-full" }, /* @__PURE__ */ React10__default.createElement(
1454
+ "input",
1455
+ {
1456
+ type: "text",
1457
+ placeholder,
1458
+ value: searchQuery,
1459
+ onChange: (e) => onSearchChange(e.target.value),
1460
+ className: clsx(
1461
+ "w-full",
1462
+ styles.container,
1463
+ styles.input,
1464
+ isLarge ? "border-2 border-gray-200 rounded-2xl shadow-lg" : "border border-gray-300 rounded-lg shadow-sm",
1465
+ "bg-white focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 hover:border-gray-400",
1466
+ isLarge ? "hover:shadow-xl" : "hover:shadow-md",
1467
+ "transition-all duration-300 ease-out text-gray-800 placeholder-gray-500",
1468
+ isLarge ? "font-medium" : "font-normal"
1469
+ )
1470
+ }
1471
+ ), searchQuery && /* @__PURE__ */ React10__default.createElement(
1472
+ "button",
1473
+ {
1474
+ onClick: () => onSearchChange(""),
1475
+ className: clsx(
1476
+ "absolute top-1/2",
1477
+ styles.clearButton,
1478
+ "transform -translate-y-1/2 z-10 group/clear"
1479
+ )
1480
+ },
1481
+ /* @__PURE__ */ React10__default.createElement("div", { className: clsx(
1482
+ styles.clearButton,
1483
+ "flex items-center justify-center rounded-full bg-gray-100 hover:bg-gray-200 transition-all duration-200 group-hover/clear:scale-105"
1484
+ ) }, /* @__PURE__ */ React10__default.createElement(
1485
+ "svg",
1486
+ {
1487
+ className: clsx(styles.clearIcon, "text-gray-500 group-hover/clear:text-gray-700"),
1488
+ fill: "none",
1489
+ stroke: "currentColor",
1490
+ viewBox: "0 0 24 24"
1491
+ },
1492
+ /* @__PURE__ */ React10__default.createElement(
1493
+ "path",
1494
+ {
1495
+ strokeLinecap: "round",
1496
+ strokeLinejoin: "round",
1497
+ strokeWidth: 2,
1498
+ d: "M6 18L18 6M6 6l12 12"
1499
+ }
1500
+ )
1501
+ ))
1502
+ ));
1503
+ };
1504
+ var Timeline = ({ items = [] }) => {
1505
+ if (!items || items.length === 0) {
1506
+ return null;
1507
+ }
1508
+ return /* @__PURE__ */ React10__default.createElement("div", { className: "relative" }, /* @__PURE__ */ React10__default.createElement("div", { className: "absolute left-4 top-0 bottom-0 w-0.5 bg-gray-200" }), items.map((item, index) => /* @__PURE__ */ React10__default.createElement("div", { key: index, className: "relative pl-12 pb-8" }, /* @__PURE__ */ React10__default.createElement("div", { className: "absolute left-0 w-8 h-8 rounded-full bg-blue-500 border-4 border-white shadow-md flex items-center justify-center" }, /* @__PURE__ */ React10__default.createElement("div", { className: "w-2 h-2 rounded-full bg-white" })), /* @__PURE__ */ React10__default.createElement("div", { className: "bg-white rounded-lg p-4 shadow-md" }, /* @__PURE__ */ React10__default.createElement("div", { className: "text-sm text-gray-500 mb-2" }, item.date), /* @__PURE__ */ React10__default.createElement("h4", { className: "text-lg font-semibold mb-2" }, item.title), /* @__PURE__ */ React10__default.createElement("p", { className: "text-gray-600" }, item.description)))));
1509
+ };
1510
+ var CollisionBalls = ({
1511
+ collisionBallsConfig: {
1512
+ balls,
1513
+ width,
1514
+ height
1515
+ }
1516
+ }) => {
1517
+ const canvasRef = useRef(null);
1518
+ const containerRef = useRef(null);
1519
+ const ballsRef = useRef([]);
1520
+ const [isShaking, setIsShaking] = useState(false);
1521
+ const [draggedBall, setDraggedBall] = useState(null);
1522
+ const [mousePos, setMousePos] = useState({ x: 0, y: 0 });
1523
+ const animationRef = useRef(null);
1524
+ const updateCanvasSize = () => {
1525
+ const container = containerRef.current;
1526
+ const canvas = canvasRef.current;
1527
+ if (!container || !canvas) {
1528
+ console.error("Container or canvas not found");
1529
+ return;
1530
+ }
1531
+ const containerWidth = container.clientWidth;
1532
+ const containerHeight = container.clientHeight;
1533
+ console.log("Container size:", { containerWidth, containerHeight });
1534
+ canvas.width = containerWidth;
1535
+ canvas.height = containerHeight;
1536
+ canvas.style.width = containerWidth + "px";
1537
+ canvas.style.height = containerHeight + "px";
1538
+ console.log("Canvas size updated:", {
1539
+ width: canvas.width,
1540
+ height: canvas.height,
1541
+ containerWidth,
1542
+ containerHeight
1543
+ });
1544
+ };
1545
+ const initBalls = () => {
1546
+ const canvas = canvasRef.current;
1547
+ if (!canvas) {
1548
+ console.error("Canvas not found during ball initialization");
1549
+ return [];
1550
+ }
1551
+ console.log("Initializing balls with canvas size:", {
1552
+ width: canvas.width,
1553
+ height: canvas.height
1554
+ });
1555
+ return balls.map((ballConfig) => ({
1556
+ x: Math.random() * (canvas.width - 100) + 50,
1557
+ y: Math.random() * (canvas.height - 100) + 50,
1558
+ vx: (Math.random() - 0.5) * 4,
1559
+ vy: (Math.random() - 0.5) * 4,
1560
+ radius: ballConfig.size,
1561
+ color: ballConfig.color,
1562
+ text: ballConfig.label,
1563
+ isDragging: false
1564
+ }));
1565
+ };
1566
+ useEffect(() => {
1567
+ const handleResize = () => {
1568
+ console.log("Window resized");
1569
+ updateCanvasSize();
1570
+ };
1571
+ if (typeof window !== "undefined") {
1572
+ window.addEventListener("resize", handleResize);
1573
+ updateCanvasSize();
1574
+ }
1575
+ return () => {
1576
+ if (typeof window !== "undefined") {
1577
+ window.removeEventListener("resize", handleResize);
1578
+ }
1579
+ };
1580
+ }, []);
1581
+ useEffect(() => {
1582
+ const canvas = canvasRef.current;
1583
+ if (!canvas) {
1584
+ console.error("Canvas element not found");
1585
+ return;
1586
+ }
1587
+ const ctx = canvas.getContext("2d");
1588
+ if (!ctx) {
1589
+ console.error("Failed to get canvas context");
1590
+ return;
1591
+ }
1592
+ console.log("Starting animation setup...");
1593
+ updateCanvasSize();
1594
+ ballsRef.current = initBalls();
1595
+ console.log("Balls initialized:", ballsRef.current);
1596
+ let lastTime = performance.now();
1597
+ let frameCount = 0;
1598
+ const animate = (currentTime) => {
1599
+ try {
1600
+ frameCount++;
1601
+ if (currentTime - lastTime >= 1e3) {
1602
+ console.log("FPS: " + frameCount);
1603
+ frameCount = 0;
1604
+ lastTime = currentTime;
1605
+ }
1606
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
1607
+ ballsRef.current.forEach((ball) => {
1608
+ if (!ball.isDragging) {
1609
+ updatePosition(ball, canvas.width, canvas.height);
1610
+ }
1611
+ for (let i = 0; i < ballsRef.current.length; i++) {
1612
+ for (let j = i + 1; j < ballsRef.current.length; j++) {
1613
+ const ball1 = ballsRef.current[i];
1614
+ const ball2 = ballsRef.current[j];
1615
+ if (ball1 && ball2) {
1616
+ checkCollision(ball1, ball2);
1617
+ }
1618
+ }
1619
+ }
1620
+ draw(ctx, ball);
1621
+ });
1622
+ animationRef.current = requestAnimationFrame(animate);
1623
+ } catch (error) {
1624
+ console.error("Animation error:", error);
1625
+ }
1626
+ };
1627
+ console.log("Starting animation loop...");
1628
+ animationRef.current = requestAnimationFrame(animate);
1629
+ return () => {
1630
+ console.log("Cleaning up animation...");
1631
+ if (animationRef.current) {
1632
+ cancelAnimationFrame(animationRef.current);
1633
+ animationRef.current = null;
1634
+ }
1635
+ };
1636
+ }, []);
1637
+ const shake = () => {
1638
+ setIsShaking(true);
1639
+ ballsRef.current.forEach((ball) => {
1640
+ ball.vx = (Math.random() - 0.5) * 10;
1641
+ ball.vy = (Math.random() - 0.5) * 10;
1642
+ });
1643
+ setTimeout(() => setIsShaking(false), 200);
1644
+ };
1645
+ const slowdown = () => {
1646
+ setIsShaking(true);
1647
+ ballsRef.current.forEach((ball) => {
1648
+ ball.vx = ball.vx * 0.5;
1649
+ ball.vy = ball.vy * 0.5;
1650
+ });
1651
+ setTimeout(() => setIsShaking(false), 200);
1652
+ };
1653
+ const checkCollision = (ball1, ball2) => {
1654
+ const dx = ball2.x - ball1.x;
1655
+ const dy = ball2.y - ball1.y;
1656
+ const distance = Math.sqrt(dx * dx + dy * dy);
1657
+ if (distance < ball1.radius + ball2.radius) {
1658
+ const angle = Math.atan2(dy, dx);
1659
+ const overlap = (ball1.radius + ball2.radius - distance) / 2;
1660
+ if (ball1.isDragging || ball2.isDragging) {
1661
+ const draggedBall2 = ball1.isDragging ? ball1 : ball2;
1662
+ const otherBall = ball1.isDragging ? ball2 : ball1;
1663
+ otherBall.x += (draggedBall2 === ball1 ? 1 : -1) * overlap * Math.cos(angle);
1664
+ otherBall.y += (draggedBall2 === ball1 ? 1 : -1) * overlap * Math.sin(angle);
1665
+ const pushForce = 2;
1666
+ otherBall.vx = (draggedBall2 === ball1 ? -1 : 1) * Math.cos(angle) * pushForce;
1667
+ otherBall.vy = (draggedBall2 === ball1 ? -1 : 1) * Math.sin(angle) * pushForce;
1668
+ return;
1669
+ }
1670
+ const sin = Math.sin(angle);
1671
+ const cos = Math.cos(angle);
1672
+ const vx1 = ball1.vx * cos + ball1.vy * sin;
1673
+ const vy1 = ball1.vy * cos - ball1.vx * sin;
1674
+ const vx2 = ball2.vx * cos + ball2.vy * sin;
1675
+ const vy2 = ball2.vy * cos - ball2.vx * sin;
1676
+ const newVx1 = vx2;
1677
+ const newVx2 = vx1;
1678
+ ball1.vx = newVx1 * cos - vy1 * sin;
1679
+ ball1.vy = vy1 * cos + newVx1 * sin;
1680
+ ball2.vx = newVx2 * cos - vy2 * sin;
1681
+ ball2.vy = vy2 * cos + newVx2 * sin;
1682
+ ball1.x -= overlap * Math.cos(angle);
1683
+ ball1.y -= overlap * Math.sin(angle);
1684
+ ball2.x += overlap * Math.cos(angle);
1685
+ ball2.y += overlap * Math.sin(angle);
1686
+ }
1687
+ };
1688
+ const updatePosition = (ball, width2, height2) => {
1689
+ const handleBoundaryCollision = (velocity, position, boundary, radius) => {
1690
+ let newVelocity = velocity;
1691
+ let newPosition = position;
1692
+ if (position - radius < 0) {
1693
+ newPosition = radius;
1694
+ newVelocity = Math.abs(velocity);
1695
+ } else if (position + radius > boundary) {
1696
+ newPosition = boundary - radius;
1697
+ newVelocity = -Math.abs(velocity);
1698
+ }
1699
+ return [newVelocity, newPosition];
1700
+ };
1701
+ const [newVx, newX] = handleBoundaryCollision(
1702
+ ball.vx,
1703
+ ball.x,
1704
+ width2,
1705
+ ball.radius
1706
+ );
1707
+ const [newVy, newY] = handleBoundaryCollision(
1708
+ ball.vy,
1709
+ ball.y,
1710
+ height2,
1711
+ ball.radius
1712
+ );
1713
+ ball.vx = newVx;
1714
+ ball.vy = newVy;
1715
+ ball.x = newX;
1716
+ ball.y = newY;
1717
+ };
1718
+ const draw = (ctx, ball) => {
1719
+ ctx.beginPath();
1720
+ ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
1721
+ ctx.fillStyle = ball.color;
1722
+ ctx.fill();
1723
+ ctx.closePath();
1724
+ if (ball.text) {
1725
+ ctx.font = "14px Arial";
1726
+ ctx.fillStyle = "#fff";
1727
+ ctx.textAlign = "center";
1728
+ ctx.textBaseline = "middle";
1729
+ ctx.fillText(ball.text, ball.x, ball.y);
1730
+ }
1731
+ };
1732
+ const handleMouseDown = (event) => {
1733
+ const mousePos2 = getMousePos(event);
1734
+ const ball = ballsRef.current.find((b) => {
1735
+ const dx = b.x - mousePos2.x;
1736
+ const dy = b.y - mousePos2.y;
1737
+ return Math.sqrt(dx * dx + dy * dy) < b.radius;
1738
+ });
1739
+ if (ball) {
1740
+ ball.isDragging = true;
1741
+ setDraggedBall(ball);
1742
+ }
1743
+ };
1744
+ const handleMouseMove = (event) => {
1745
+ const mousePos2 = getMousePos(event);
1746
+ setMousePos(mousePos2);
1747
+ if (draggedBall) {
1748
+ draggedBall.x = mousePos2.x;
1749
+ draggedBall.y = mousePos2.y;
1750
+ draggedBall.vx = 0;
1751
+ draggedBall.vy = 0;
1752
+ }
1753
+ };
1754
+ const handleMouseUp = () => {
1755
+ if (draggedBall) {
1756
+ draggedBall.isDragging = false;
1757
+ setDraggedBall(null);
1758
+ }
1759
+ };
1760
+ const getMousePos = (event) => {
1761
+ const canvas = canvasRef.current;
1762
+ if (!canvas) return { x: 0, y: 0 };
1763
+ const rect = canvas.getBoundingClientRect();
1764
+ const scaleX = canvas.width / rect.width;
1765
+ const scaleY = canvas.height / rect.height;
1766
+ return {
1767
+ x: (event.clientX - rect.left) * scaleX,
1768
+ y: (event.clientY - rect.top) * scaleY
1769
+ };
1770
+ };
1771
+ return /* @__PURE__ */ React10__default.createElement("div", { style: { width: "100%", height: "100%", position: "relative", backgroundColor: "#f9fafb", borderRadius: "0.5rem" } }, /* @__PURE__ */ React10__default.createElement("div", { ref: containerRef, style: { width: "100%", height: "100%", position: "absolute", top: 0, left: 0 } }, /* @__PURE__ */ React10__default.createElement(
1772
+ "canvas",
1773
+ {
1774
+ ref: canvasRef,
1775
+ style: {
1776
+ width: "100%",
1777
+ height: "100%",
1778
+ display: "block"
1779
+ // 确保canvas正确显示
1780
+ },
1781
+ onMouseDown: handleMouseDown,
1782
+ onMouseMove: handleMouseMove,
1783
+ onMouseUp: handleMouseUp,
1784
+ onMouseLeave: handleMouseUp
1785
+ }
1786
+ )), /* @__PURE__ */ React10__default.createElement("div", { className: "absolute bottom-4 right-4 flex gap-2" }, /* @__PURE__ */ React10__default.createElement(
1787
+ "button",
1788
+ {
1789
+ onClick: shake,
1790
+ className: clsx("px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors", isShaking ? "animate-pulse" : "")
1791
+ },
1792
+ "\u6447\u4E00\u6447"
1793
+ ), /* @__PURE__ */ React10__default.createElement(
1794
+ "button",
1795
+ {
1796
+ onClick: slowdown,
1797
+ className: clsx("px-4 py-2 bg-green-500 text-white rounded-lg hover:bg-green-600 transition-colors", isShaking ? "animate-pulse" : "")
1798
+ },
1799
+ "\u51CF\u901F"
1800
+ )));
1801
+ };
1802
+ function GenericOrderManager({
1803
+ operations,
1804
+ renderItem,
1805
+ className = "",
1806
+ title = "\u987A\u5E8F\u7BA1\u7406",
1807
+ description = "\u62D6\u62FD\u6216\u4F7F\u7528\u6309\u94AE\u8C03\u6574\u663E\u793A\u987A\u5E8F",
1808
+ onOrderChanged,
1809
+ emptyMessage = "\u6682\u65E0\u6570\u636E",
1810
+ loadingMessage = "\u52A0\u8F7D\u6570\u636E..."
1811
+ }) {
1812
+ const [items, setItems] = useState([]);
1813
+ const [originalOrder, setOriginalOrder] = useState([]);
1814
+ const [loading, setLoading] = useState(true);
1815
+ const [saving, setSaving] = useState(false);
1816
+ const [error, setError] = useState(null);
1817
+ const [hasChanges, setHasChanges] = useState(false);
1818
+ const [draggedItem, setDraggedItem] = useState(null);
1819
+ const loadItems = useCallback(async () => {
1820
+ try {
1821
+ setLoading(true);
1822
+ setError(null);
1823
+ const data = await operations.loadItems();
1824
+ setItems(data);
1825
+ setOriginalOrder([...data]);
1826
+ setHasChanges(false);
1827
+ } catch (err) {
1828
+ console.error("\u274C [\u901A\u7528\u6392\u5E8F] \u52A0\u8F7D\u6570\u636E\u9519\u8BEF:", err);
1829
+ setError(err instanceof Error ? err.message : "\u52A0\u8F7D\u6570\u636E\u5931\u8D25");
1830
+ } finally {
1831
+ setLoading(false);
1832
+ }
1833
+ }, [operations]);
1834
+ useEffect(() => {
1835
+ loadItems();
1836
+ }, [loadItems]);
1837
+ useEffect(() => {
1838
+ const hasOrderChanged = items.some(
1839
+ (item, index) => originalOrder[index]?.id !== item.id
1840
+ );
1841
+ setHasChanges(hasOrderChanged);
1842
+ }, [items, originalOrder]);
1843
+ const handleMoveUp = async (itemId) => {
1844
+ try {
1845
+ setError(null);
1846
+ const currentIndex = items.findIndex((item) => item.id === itemId);
1847
+ if (currentIndex === -1) {
1848
+ setError("\u9879\u76EE\u4E0D\u5B58\u5728");
1849
+ return;
1850
+ }
1851
+ if (currentIndex === 0) {
1852
+ setError("\u9879\u76EE\u5DF2\u7ECF\u5728\u6700\u524D\u9762\uFF0C\u65E0\u6CD5\u4E0A\u79FB");
1853
+ return;
1854
+ }
1855
+ await operations.moveItemUp(itemId);
1856
+ await loadItems();
1857
+ onOrderChanged?.();
1858
+ } catch (err) {
1859
+ console.error("\u274C [\u901A\u7528\u6392\u5E8F] \u4E0A\u79FB\u9879\u76EE\u9519\u8BEF:", err);
1860
+ setError(err instanceof Error ? err.message : "\u4E0A\u79FB\u5931\u8D25");
1861
+ }
1862
+ };
1863
+ const handleMoveDown = async (itemId) => {
1864
+ try {
1865
+ setError(null);
1866
+ const currentIndex = items.findIndex((item) => item.id === itemId);
1867
+ if (currentIndex === -1) {
1868
+ setError("\u9879\u76EE\u4E0D\u5B58\u5728");
1869
+ return;
1870
+ }
1871
+ if (currentIndex === items.length - 1) {
1872
+ setError("\u9879\u76EE\u5DF2\u7ECF\u5728\u6700\u540E\u9762\uFF0C\u65E0\u6CD5\u4E0B\u79FB");
1873
+ return;
1874
+ }
1875
+ await operations.moveItemDown(itemId);
1876
+ await loadItems();
1877
+ onOrderChanged?.();
1878
+ } catch (err) {
1879
+ console.error("\u274C [\u901A\u7528\u6392\u5E8F] \u4E0B\u79FB\u9879\u76EE\u9519\u8BEF:", err);
1880
+ setError(err instanceof Error ? err.message : "\u4E0B\u79FB\u5931\u8D25");
1881
+ }
1882
+ };
1883
+ const handleDragStart = (e, index) => {
1884
+ setDraggedItem(index);
1885
+ e.dataTransfer.effectAllowed = "move";
1886
+ };
1887
+ const handleDragOver = (e, _index) => {
1888
+ e.preventDefault();
1889
+ e.dataTransfer.dropEffect = "move";
1890
+ };
1891
+ const handleDrop = async (e, dropIndex) => {
1892
+ e.preventDefault();
1893
+ if (draggedItem === null || draggedItem === dropIndex) {
1894
+ setDraggedItem(null);
1895
+ return;
1896
+ }
1897
+ try {
1898
+ setError(null);
1899
+ const newItems = [...items];
1900
+ const draggedItemData = newItems[draggedItem];
1901
+ if (!draggedItemData) return;
1902
+ newItems.splice(draggedItem, 1);
1903
+ newItems.splice(dropIndex, 0, draggedItemData);
1904
+ const itemOrders = newItems.map((item, index) => ({
1905
+ id: item.id,
1906
+ order: index
1907
+ }));
1908
+ await operations.updateItemOrder(itemOrders);
1909
+ await loadItems();
1910
+ onOrderChanged?.();
1911
+ } catch (err) {
1912
+ console.error("\u274C [\u901A\u7528\u6392\u5E8F] \u62D6\u62FD\u6392\u5E8F\u9519\u8BEF:", err);
1913
+ setError(err instanceof Error ? err.message : "\u6392\u5E8F\u5931\u8D25");
1914
+ } finally {
1915
+ setDraggedItem(null);
1916
+ }
1917
+ };
1918
+ const handleSaveOrder = async () => {
1919
+ try {
1920
+ setSaving(true);
1921
+ setError(null);
1922
+ const itemOrders = items.map((item, index) => ({
1923
+ id: item.id,
1924
+ order: index
1925
+ }));
1926
+ await operations.updateItemOrder(itemOrders);
1927
+ setOriginalOrder([...items]);
1928
+ setHasChanges(false);
1929
+ onOrderChanged?.();
1930
+ } catch (err) {
1931
+ console.error("\u274C [\u901A\u7528\u6392\u5E8F] \u4FDD\u5B58\u987A\u5E8F\u9519\u8BEF:", err);
1932
+ setError(err instanceof Error ? err.message : "\u4FDD\u5B58\u5931\u8D25");
1933
+ await loadItems();
1934
+ } finally {
1935
+ setSaving(false);
1936
+ }
1937
+ };
1938
+ const handleResetOrder = () => {
1939
+ setItems([...originalOrder]);
1940
+ };
1941
+ if (loading) {
1942
+ return /* @__PURE__ */ React10__default.createElement("div", { className: cn("flex flex-col items-center justify-center p-12 text-gray-500", className) }, /* @__PURE__ */ React10__default.createElement("div", { className: "w-6 h-6 border-2 border-gray-200 border-t-blue-500 rounded-full animate-spin mb-2" }), /* @__PURE__ */ React10__default.createElement("span", null, loadingMessage));
1943
+ }
1944
+ return /* @__PURE__ */ React10__default.createElement("div", { className: cn("bg-white rounded-xl p-6 shadow-md border-2 border-gray-100", className) }, /* @__PURE__ */ React10__default.createElement("div", { className: "flex items-center justify-between mb-4 pb-3 border-b border-gray-100 sm:flex-row flex-col sm:items-center items-start gap-4" }, /* @__PURE__ */ React10__default.createElement("h3", { className: "m-0 text-gray-900 text-lg font-semibold" }, title), /* @__PURE__ */ React10__default.createElement("div", { className: "flex gap-3 w-full sm:w-auto" }, hasChanges && /* @__PURE__ */ React10__default.createElement(React10__default.Fragment, null, /* @__PURE__ */ React10__default.createElement(
1945
+ "button",
1946
+ {
1947
+ onClick: handleResetOrder,
1948
+ className: "flex items-center gap-2 bg-amber-500 hover:bg-amber-600 text-white px-4 py-2 rounded-lg font-medium transition-colors",
1949
+ title: "\u91CD\u7F6E\u4E3A\u539F\u59CB\u987A\u5E8F"
1950
+ },
1951
+ /* @__PURE__ */ React10__default.createElement(RotateCcw, { size: 16 }),
1952
+ "\u91CD\u7F6E"
1953
+ ), /* @__PURE__ */ React10__default.createElement(
1954
+ "button",
1955
+ {
1956
+ onClick: handleSaveOrder,
1957
+ disabled: saving,
1958
+ className: "flex items-center gap-2 bg-blue-500 hover:bg-blue-600 disabled:opacity-50 disabled:cursor-not-allowed text-white px-4 py-2 rounded-lg font-medium transition-colors",
1959
+ title: "\u4FDD\u5B58\u65B0\u987A\u5E8F"
1960
+ },
1961
+ /* @__PURE__ */ React10__default.createElement(Save, { size: 16 }),
1962
+ saving ? "\u4FDD\u5B58\u4E2D..." : "\u4FDD\u5B58\u987A\u5E8F"
1963
+ )))), error && /* @__PURE__ */ React10__default.createElement("div", { className: "flex items-center gap-2 bg-red-50 text-red-600 p-3 rounded-lg mb-4 border border-red-200" }, /* @__PURE__ */ React10__default.createElement(AlertCircle, { size: 16 }), /* @__PURE__ */ React10__default.createElement("span", null, error)), /* @__PURE__ */ React10__default.createElement("div", { className: "bg-slate-50 border border-slate-200 rounded-lg p-4 mb-6" }, /* @__PURE__ */ React10__default.createElement("p", { className: "m-0 mb-2 color-slate-500 text-sm" }, description), /* @__PURE__ */ React10__default.createElement("ul", { className: "m-0 pl-6 color-slate-500 text-sm list-disc" }, /* @__PURE__ */ React10__default.createElement("li", { className: "mb-1" }, "\u4F7F\u7528\u62D6\u62FD\uFF1A\u70B9\u51FB\u5E76\u62D6\u52A8 ", /* @__PURE__ */ React10__default.createElement(GripVertical, { size: 14, className: "inline-block align-middle text-gray-500" }), " \u56FE\u6807"), /* @__PURE__ */ React10__default.createElement("li", { className: "mb-1" }, "\u4F7F\u7528\u6309\u94AE\uFF1A\u70B9\u51FB ", /* @__PURE__ */ React10__default.createElement(ChevronUp, { size: 14, className: "inline-block align-middle text-gray-500" }), " \u6216 ", /* @__PURE__ */ React10__default.createElement(ChevronDown, { size: 14, className: "inline-block align-middle text-gray-500" }), " \u6309\u94AE"), /* @__PURE__ */ React10__default.createElement("li", null, '\u5B8C\u6210\u8C03\u6574\u540E\uFF0C\u70B9\u51FB"\u4FDD\u5B58\u987A\u5E8F"\u6309\u94AE\u4FDD\u5B58\u66F4\u6539'))), /* @__PURE__ */ React10__default.createElement("div", { className: "flex flex-col gap-3" }, items.map((item, index) => /* @__PURE__ */ React10__default.createElement(
1964
+ "div",
1965
+ {
1966
+ key: item.id,
1967
+ className: cn(
1968
+ "flex items-center gap-3 p-4 bg-gray-50 border-2 border-gray-200 rounded-lg transition-all hover:border-gray-300 hover:shadow-sm",
1969
+ draggedItem === index && "opacity-50 rotate-2 border-blue-500"
1970
+ ),
1971
+ draggable: true,
1972
+ onDragStart: (e) => handleDragStart(e, index),
1973
+ onDragOver: (e) => handleDragOver(e),
1974
+ onDrop: (e) => handleDrop(e, index)
1975
+ },
1976
+ /* @__PURE__ */ React10__default.createElement("div", { className: "flex items-center cursor-grab active:cursor-grabbing text-gray-400 p-1 rounded hover:text-gray-500 hover:bg-gray-100 transition-colors" }, /* @__PURE__ */ React10__default.createElement(GripVertical, { size: 20 })),
1977
+ /* @__PURE__ */ React10__default.createElement("div", { className: "flex-1 min-w-0" }, renderItem(item, index, index === 0, index === items.length - 1)),
1978
+ /* @__PURE__ */ React10__default.createElement("div", { className: "flex items-center mx-3" }, /* @__PURE__ */ React10__default.createElement("span", { className: "flex items-center justify-center w-8 h-8 bg-blue-500 text-white text-sm font-semibold rounded-full sm:w-8 sm:h-8 w-7 h-7 sm:text-sm text-xs" }, "#", index + 1)),
1979
+ /* @__PURE__ */ React10__default.createElement("div", { className: "flex flex-col gap-1 sm:flex-col flex-row" }, /* @__PURE__ */ React10__default.createElement(
1980
+ "button",
1981
+ {
1982
+ onClick: () => handleMoveUp(item.id),
1983
+ disabled: index === 0,
1984
+ className: "flex items-center justify-center w-8 h-8 p-0 border border-gray-300 bg-white text-gray-500 rounded cursor-pointer transition-all hover:bg-gray-100 hover:border-gray-400 hover:text-gray-700 disabled:opacity-40 disabled:cursor-not-allowed disabled:bg-gray-50 sm:w-8 sm:h-8 w-7 h-7",
1985
+ title: "\u4E0A\u79FB"
1986
+ },
1987
+ /* @__PURE__ */ React10__default.createElement(ChevronUp, { size: 18 })
1988
+ ), /* @__PURE__ */ React10__default.createElement(
1989
+ "button",
1990
+ {
1991
+ onClick: () => handleMoveDown(item.id),
1992
+ disabled: index === items.length - 1,
1993
+ className: "flex items-center justify-center w-8 h-8 p-0 border border-gray-300 bg-white text-gray-500 rounded cursor-pointer transition-all hover:bg-gray-100 hover:border-gray-400 hover:text-gray-700 disabled:opacity-40 disabled:cursor-not-allowed disabled:bg-gray-50 sm:w-8 sm:h-8 w-7 h-7",
1994
+ title: "\u4E0B\u79FB"
1995
+ },
1996
+ /* @__PURE__ */ React10__default.createElement(ChevronDown, { size: 18 })
1997
+ ))
1998
+ ))), items.length === 0 && /* @__PURE__ */ React10__default.createElement("div", { className: "text-center p-12 text-gray-400 italic" }, /* @__PURE__ */ React10__default.createElement("p", { className: "m-0" }, emptyMessage)));
1999
+ }
2000
+ var BackButton = ({ href, className = "" }) => {
2001
+ const router = useRouter();
2002
+ const handleClick = () => {
2003
+ if (href) {
2004
+ router.push(href);
2005
+ } else {
2006
+ router.back();
2007
+ }
2008
+ };
2009
+ return /* @__PURE__ */ React10__default.createElement(
2010
+ "button",
2011
+ {
2012
+ onClick: handleClick,
2013
+ className: cn(
2014
+ "inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors",
2015
+ className
2016
+ )
2017
+ },
2018
+ /* @__PURE__ */ React10__default.createElement(
2019
+ "svg",
2020
+ {
2021
+ className: "w-5 h-5 mr-2",
2022
+ fill: "none",
2023
+ stroke: "currentColor",
2024
+ viewBox: "0 0 24 24"
2025
+ },
2026
+ /* @__PURE__ */ React10__default.createElement(
2027
+ "path",
2028
+ {
2029
+ strokeLinecap: "round",
2030
+ strokeLinejoin: "round",
2031
+ strokeWidth: 2,
2032
+ d: "M10 19l-7-7m0 0l7-7m-7 7h18"
2033
+ }
2034
+ )
2035
+ ),
2036
+ "\u8FD4\u56DE"
2037
+ );
2038
+ };
2039
+ function getColorValue(bgClass) {
2040
+ const colorMap = {
2041
+ "bg-blue-500": "#3b82f6",
2042
+ "bg-green-500": "#10b981",
2043
+ "bg-red-500": "#ef4444",
2044
+ "bg-purple-500": "#8b5cf6",
2045
+ "bg-slate-500": "#64748b",
2046
+ "bg-emerald-500": "#10b981",
2047
+ "bg-orange-500": "#f97316"
2048
+ };
2049
+ return colorMap[bgClass] || "#3b82f6";
2050
+ }
2051
+ function FilterButtonGroup({
2052
+ label,
2053
+ value,
2054
+ options,
2055
+ onChange,
2056
+ className
2057
+ }) {
2058
+ return /* @__PURE__ */ React10__default.createElement("div", { className: cn("space-y-4", className) }, /* @__PURE__ */ React10__default.createElement("h3", { className: "text-lg font-semibold text-gray-800" }, label), /* @__PURE__ */ React10__default.createElement("div", { className: "flex gap-3" }, options.map((option) => {
2059
+ const isActive = value === option.value;
2060
+ return /* @__PURE__ */ React10__default.createElement(
2061
+ "button",
2062
+ {
2063
+ key: option.value,
2064
+ onClick: () => onChange(option.value),
2065
+ style: isActive ? { backgroundColor: getColorValue(option.activeColor.bg) } : void 0,
2066
+ className: cn(
2067
+ "flex-1 h-12 rounded-lg font-medium text-sm transition-all duration-200 ease-out focus:outline-none focus:ring-2 focus:ring-opacity-50 border",
2068
+ isActive ? "text-white border-transparent shadow-md focus:ring-white" : "bg-white text-gray-700 border-gray-200 shadow-sm hover:bg-gray-50 hover:border-gray-300 hover:shadow focus:ring-blue-300"
2069
+ )
2070
+ },
2071
+ /* @__PURE__ */ React10__default.createElement("div", { className: "flex items-center justify-center space-x-2" }, /* @__PURE__ */ React10__default.createElement("span", { className: "text-lg" }, option.icon), /* @__PURE__ */ React10__default.createElement("span", null, option.label), option.showCount && option.count !== void 0 && /* @__PURE__ */ React10__default.createElement("span", { className: cn(
2072
+ "text-xs font-semibold px-2 py-0.5 rounded-full min-w-[1.25rem] text-center",
2073
+ isActive ? "bg-white/20 text-white" : "bg-gray-100 text-gray-600"
2074
+ ) }, option.count))
2075
+ );
2076
+ })));
2077
+ }
2078
+ function SearchResultHint({ searchQuery, resultCount, className }) {
2079
+ if (!searchQuery) return null;
2080
+ return /* @__PURE__ */ React10__default.createElement("div", { className: cn("mb-6 p-4 bg-blue-50 border border-blue-200 rounded-lg", className) }, /* @__PURE__ */ React10__default.createElement("p", { className: "text-sm text-blue-700" }, '\u641C\u7D22 "', /* @__PURE__ */ React10__default.createElement("span", { className: "font-medium" }, searchQuery), '" \u627E\u5230 ', resultCount, " \u4E2A\u7ED3\u679C"));
2081
+ }
2082
+ var Modal = ({
2083
+ isOpen,
2084
+ onClose,
2085
+ title,
2086
+ width,
2087
+ height,
2088
+ className,
2089
+ maskClosable = true,
2090
+ children,
2091
+ zIndex = 50,
2092
+ overlayClassName
2093
+ }) => {
2094
+ const contentZIndex = Math.max(zIndex, 1e4);
2095
+ return /* @__PURE__ */ React10__default.createElement(Dialog, { open: isOpen, onOpenChange: (open) => {
2096
+ if (!open) {
2097
+ if (maskClosable) {
2098
+ onClose();
2099
+ }
2100
+ }
2101
+ } }, /* @__PURE__ */ React10__default.createElement(
2102
+ DialogContent,
2103
+ {
2104
+ className: cn("sm:max-w-[425px]", className),
2105
+ overlayClassName,
2106
+ onPointerDownOutside: (e) => {
2107
+ if (!maskClosable) e.preventDefault();
2108
+ },
2109
+ onEscapeKeyDown: (e) => {
2110
+ if (!maskClosable) e.preventDefault();
2111
+ },
2112
+ style: {
2113
+ zIndex: contentZIndex,
2114
+ ...width ? { maxWidth: typeof width === "number" ? `${width}px` : width } : void 0,
2115
+ ...height ? { height: typeof height === "number" ? `${height}px` : height } : void 0
2116
+ }
2117
+ },
2118
+ title ? /* @__PURE__ */ React10__default.createElement(DialogHeader, null, /* @__PURE__ */ React10__default.createElement(DialogTitle, null, title)) : (
2119
+ // 无障碍性:始终需要 DialogTitle,使用 sr-only 对视觉隐藏但对屏幕阅读器可见
2120
+ /* @__PURE__ */ React10__default.createElement(DialogTitle, { className: "sr-only" }, "\u5F39\u7A97")
2121
+ ),
2122
+ /* @__PURE__ */ React10__default.createElement("div", { className: "py-4" }, children)
2123
+ ));
2124
+ };
2125
+ var ConfirmModal = ({
2126
+ isOpen,
2127
+ onClose,
2128
+ onConfirm,
2129
+ title = "\u786E\u8BA4\u64CD\u4F5C",
2130
+ message,
2131
+ confirmText = "\u786E\u8BA4",
2132
+ cancelText = "\u53D6\u6D88",
2133
+ isLoading = false
2134
+ }) => {
2135
+ return /* @__PURE__ */ React10__default.createElement(Dialog, { open: isOpen, onOpenChange: (open) => !open && onClose() }, /* @__PURE__ */ React10__default.createElement(AlertDialogContent, null, /* @__PURE__ */ React10__default.createElement(DialogHeader, null, /* @__PURE__ */ React10__default.createElement(DialogTitle, null, title), /* @__PURE__ */ React10__default.createElement(DialogDescription, null, message)), /* @__PURE__ */ React10__default.createElement(DialogFooter, null, /* @__PURE__ */ React10__default.createElement(AlertDialogCancel, { disabled: isLoading }, cancelText), /* @__PURE__ */ React10__default.createElement(
2136
+ AlertDialogAction,
2137
+ {
2138
+ onClick: (e) => {
2139
+ e.preventDefault();
2140
+ onConfirm();
2141
+ },
2142
+ disabled: isLoading,
2143
+ className: "bg-destructive text-destructive-foreground hover:bg-destructive/90"
2144
+ },
2145
+ isLoading ? "\u5904\u7406\u4E2D..." : confirmText
2146
+ ))));
2147
+ };
2148
+ function ImageMappingPanel({
2149
+ title,
2150
+ items,
2151
+ value,
2152
+ onChange,
2153
+ className,
2154
+ uploadLabel = "\u4E0A\u4F20\u56FE\u7247",
2155
+ clearLabel = "\u6E05\u9664"
2156
+ }) {
2157
+ const handleFileChange = (id, file) => {
2158
+ if (!file) {
2159
+ return;
2160
+ }
2161
+ const reader = new FileReader();
2162
+ reader.onload = () => {
2163
+ const base64 = typeof reader.result === "string" ? reader.result : "";
2164
+ if (!base64) {
2165
+ return;
2166
+ }
2167
+ onChange({
2168
+ ...value,
2169
+ [id]: base64
2170
+ });
2171
+ };
2172
+ reader.readAsDataURL(file);
2173
+ };
2174
+ const handleRemove = (id) => {
2175
+ const next = { ...value };
2176
+ delete next[id];
2177
+ onChange(next);
2178
+ };
2179
+ return /* @__PURE__ */ React10__default.createElement("details", { className: cn("rounded-lg border border-slate-200 bg-white/80 p-3", className) }, /* @__PURE__ */ React10__default.createElement("summary", { className: "cursor-pointer text-sm font-semibold text-slate-700" }, title), /* @__PURE__ */ React10__default.createElement("div", { className: "mt-3 grid grid-cols-1 gap-2 sm:grid-cols-2" }, items.map((item) => {
2180
+ const image = value[item.id];
2181
+ return /* @__PURE__ */ React10__default.createElement(
2182
+ "div",
2183
+ {
2184
+ key: item.id,
2185
+ className: "flex items-center gap-2 rounded-md border border-slate-200 bg-white p-2"
2186
+ },
2187
+ /* @__PURE__ */ React10__default.createElement("div", { className: "w-16 text-xs font-semibold text-slate-600" }, item.label),
2188
+ /* @__PURE__ */ React10__default.createElement("label", { className: "flex-1 cursor-pointer rounded-md bg-cyan-600 px-2 py-1 text-center text-xs font-medium text-white" }, uploadLabel, /* @__PURE__ */ React10__default.createElement(
2189
+ "input",
2190
+ {
2191
+ type: "file",
2192
+ accept: "image/*",
2193
+ className: "hidden",
2194
+ onChange: (event) => {
2195
+ handleFileChange(item.id, event.target.files?.[0]);
2196
+ event.currentTarget.value = "";
2197
+ }
2198
+ }
2199
+ )),
2200
+ image ? /* @__PURE__ */ React10__default.createElement(React10__default.Fragment, null, /* @__PURE__ */ React10__default.createElement(
2201
+ "img",
2202
+ {
2203
+ src: image,
2204
+ alt: item.label,
2205
+ className: "h-8 w-8 rounded-full border border-slate-200 object-cover"
2206
+ }
2207
+ ), /* @__PURE__ */ React10__default.createElement(
2208
+ "button",
2209
+ {
2210
+ type: "button",
2211
+ className: "rounded-md border border-red-200 px-2 py-1 text-xs text-red-600",
2212
+ onClick: () => handleRemove(item.id)
2213
+ },
2214
+ clearLabel
2215
+ )) : null
2216
+ );
2217
+ })));
2218
+ }
2219
+ function useStorage(storage, key, defaultValue) {
2220
+ const [value, setValue] = useState(defaultValue);
2221
+ const [loading, setLoading] = useState(true);
2222
+ useEffect(() => {
2223
+ const loadValue = async () => {
2224
+ try {
2225
+ const stored = await storage.getItem(key);
2226
+ if (stored !== null) {
2227
+ setValue(JSON.parse(stored));
2228
+ }
2229
+ } catch (error) {
2230
+ console.error('Error reading storage key "' + key + '":', error);
2231
+ } finally {
2232
+ setLoading(false);
2233
+ }
2234
+ };
2235
+ void loadValue();
2236
+ }, [storage, key]);
2237
+ const updateValue = useCallback(
2238
+ async (newValue) => {
2239
+ try {
2240
+ setValue(newValue);
2241
+ await storage.setItem(key, JSON.stringify(newValue));
2242
+ if ("dispatchChange" in storage && typeof storage.dispatchChange === "function") {
2243
+ storage.dispatchChange(key, JSON.stringify(newValue));
2244
+ }
2245
+ } catch (error) {
2246
+ console.error('Error setting storage key "' + key + '":', error);
2247
+ }
2248
+ },
2249
+ [storage, key]
2250
+ );
2251
+ const removeValue = useCallback(async () => {
2252
+ try {
2253
+ setValue(defaultValue);
2254
+ await storage.removeItem(key);
2255
+ if ("dispatchChange" in storage && typeof storage.dispatchChange === "function") {
2256
+ storage.dispatchChange(key, null);
2257
+ }
2258
+ } catch (error) {
2259
+ console.error('Error removing storage key "' + key + '":', error);
2260
+ }
2261
+ }, [storage, key, defaultValue]);
2262
+ useEffect(() => {
2263
+ if (!storage.addChangeListener) {
2264
+ return;
2265
+ }
2266
+ const cleanup = storage.addChangeListener((changedKey, newValue) => {
2267
+ if (changedKey === key) {
2268
+ try {
2269
+ if (newValue === null) {
2270
+ setValue(defaultValue);
2271
+ } else {
2272
+ setValue(JSON.parse(newValue));
2273
+ }
2274
+ } catch (error) {
2275
+ console.error("Error parsing storage change event:", error);
2276
+ }
2277
+ }
2278
+ });
2279
+ return cleanup;
2280
+ }, [storage, key, defaultValue]);
2281
+ return [value, updateValue, removeValue, loading];
2282
+ }
2283
+
2284
+ // src/storage/adapters/web-adapter.ts
2285
+ var isBrowser = typeof window !== "undefined" && typeof window.localStorage !== "undefined";
2286
+ var WebStorageAdapter = class {
2287
+ async getItem(key) {
2288
+ if (!isBrowser) {
2289
+ return null;
2290
+ }
2291
+ try {
2292
+ return localStorage.getItem(key);
2293
+ } catch (error) {
2294
+ console.error('[WebStorage] Error getting item "' + key + '":', error);
2295
+ return null;
2296
+ }
2297
+ }
2298
+ async setItem(key, value) {
2299
+ if (!isBrowser) {
2300
+ return;
2301
+ }
2302
+ try {
2303
+ localStorage.setItem(key, value);
2304
+ } catch (error) {
2305
+ console.error('[WebStorage] Error setting item "' + key + '":', error);
2306
+ throw error;
2307
+ }
2308
+ }
2309
+ async removeItem(key) {
2310
+ if (!isBrowser) {
2311
+ return;
2312
+ }
2313
+ try {
2314
+ localStorage.removeItem(key);
2315
+ } catch (error) {
2316
+ console.error('[WebStorage] Error removing item "' + key + '":', error);
2317
+ throw error;
2318
+ }
2319
+ }
2320
+ async clear() {
2321
+ if (!isBrowser) {
2322
+ return;
2323
+ }
2324
+ try {
2325
+ localStorage.clear();
2326
+ } catch (error) {
2327
+ console.error("[WebStorage] Error clearing storage:", error);
2328
+ throw error;
2329
+ }
2330
+ }
2331
+ addChangeListener(callback) {
2332
+ if (!isBrowser) {
2333
+ return () => {
2334
+ };
2335
+ }
2336
+ const handleStorageEvent = (e) => {
2337
+ if (e.key) {
2338
+ callback(e.key, e.newValue);
2339
+ }
2340
+ };
2341
+ const handleCustomEvent = (e) => {
2342
+ const customEvent = e;
2343
+ callback(customEvent.detail.key, customEvent.detail.value);
2344
+ };
2345
+ window.addEventListener("storage", handleStorageEvent);
2346
+ window.addEventListener("local-storage-change", handleCustomEvent);
2347
+ return () => {
2348
+ window.removeEventListener("storage", handleStorageEvent);
2349
+ window.removeEventListener("local-storage-change", handleCustomEvent);
2350
+ };
2351
+ }
2352
+ /**
2353
+ * 触发自定义事件,通知同标签页的其他组件
2354
+ */
2355
+ dispatchChange(key, value) {
2356
+ if (!isBrowser) {
2357
+ return;
2358
+ }
2359
+ window.dispatchEvent(
2360
+ new CustomEvent("local-storage-change", {
2361
+ detail: { key, value }
2362
+ })
2363
+ );
2364
+ }
2365
+ };
2366
+
2367
+ // src/storage/hooks/useLocalStorage.ts
2368
+ var webStorage = new WebStorageAdapter();
2369
+ function useLocalStorage(key, defaultValue) {
2370
+ return useStorage(webStorage, key, defaultValue);
2371
+ }
2372
+
2373
+ // src/components/LocalImageMappingPanel.tsx
2374
+ function LocalImageMappingPanel({
2375
+ storageKey,
2376
+ defaultValue = {},
2377
+ onValueChange,
2378
+ ...panelProps
2379
+ }) {
2380
+ const [value, setValue] = useLocalStorage(storageKey, defaultValue);
2381
+ return /* @__PURE__ */ React10__default.createElement(
2382
+ ImageMappingPanel,
2383
+ {
2384
+ ...panelProps,
2385
+ value,
2386
+ onChange: (next) => {
2387
+ setValue(next);
2388
+ onValueChange?.(next);
2389
+ }
2390
+ }
2391
+ );
2392
+ }
2393
+
2394
+ export { Dialog as AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, DialogDescription as AlertDialogDescription, DialogFooter as AlertDialogFooter, DialogHeader as AlertDialogHeader, DialogOverlay as AlertDialogOverlay, DialogPortal as AlertDialogPortal, DialogTitle as AlertDialogTitle, DialogTrigger as AlertDialogTrigger, Avatar, AvatarFallback, AvatarImage, BackButton, Badge, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CollisionBalls, ConfirmModal, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, FilterButtonGroup, GenericOrderManager, Grid, ImageMappingPanel, Input, Label, LocalImageMappingPanel, Modal, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, ScrollArea, ScrollBar, SearchBox, SearchResultHint, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Dialog as Sheet, DialogClose as SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, DialogOverlay as SheetOverlay, DialogPortal as SheetPortal, SheetTitle, DialogTrigger as SheetTrigger, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Timeline, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, badgeVariants, buttonVariants };
2395
+ //# sourceMappingURL=index.mjs.map
2396
+ //# sourceMappingURL=index.mjs.map