@kb-labs/studio-hooks 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,1468 @@
1
+ import { createContext, useContext, useRef, useEffect, useCallback, useState } from 'react';
2
+ import { jsx } from 'react/jsx-runtime';
3
+ import { useEventBusContext } from '@kb-labs/studio-event-bus';
4
+ import { useQuery, useMutation, useInfiniteQuery } from '@tanstack/react-query';
5
+ import { useNavigate, useLocation } from 'react-router-dom';
6
+ import { notification, theme } from 'antd';
7
+ import { lightSemanticColors, darkSemanticColors, shadows, radius, typography, spacing, colors } from '@kb-labs/studio-ui-core';
8
+
9
+ // src/page-context.tsx
10
+ var PageCtx = createContext(null);
11
+ function PageContextProvider({ children, value }) {
12
+ return /* @__PURE__ */ jsx(PageCtx.Provider, { value, children });
13
+ }
14
+ function usePageContext() {
15
+ const ctx = useContext(PageCtx);
16
+ if (!ctx) {
17
+ throw new Error("usePage() must be used inside a PageContextProvider (are you inside a Studio page?)");
18
+ }
19
+ return ctx;
20
+ }
21
+
22
+ // src/use-page.ts
23
+ function usePage() {
24
+ return usePageContext();
25
+ }
26
+ function useEventBus() {
27
+ const bus = useEventBusContext();
28
+ const { pluginId, pageId } = usePageContext();
29
+ const unsubs = useRef([]);
30
+ useEffect(() => {
31
+ return () => {
32
+ for (const unsub of unsubs.current) {
33
+ unsub();
34
+ }
35
+ unsubs.current = [];
36
+ };
37
+ }, []);
38
+ const publish = useCallback(
39
+ (event, payload) => {
40
+ bus.publish(event, payload, pluginId, pageId);
41
+ },
42
+ [bus, pluginId, pageId]
43
+ );
44
+ const subscribe = useCallback(
45
+ (event, handler) => {
46
+ const unsub = bus.subscribe(event, handler, pluginId, pageId);
47
+ unsubs.current.push(unsub);
48
+ return unsub;
49
+ },
50
+ [bus, pluginId, pageId]
51
+ );
52
+ return { publish, subscribe };
53
+ }
54
+ function useData(endpoint, options) {
55
+ const url = buildUrl(endpoint, options?.params);
56
+ const query = useQuery({
57
+ queryKey: ["studio-data", url],
58
+ queryFn: () => fetchJson(url),
59
+ enabled: options?.enabled,
60
+ staleTime: options?.staleTime,
61
+ refetchInterval: options?.pollingMs || void 0,
62
+ select: options?.select
63
+ });
64
+ return {
65
+ data: query.data,
66
+ isLoading: query.isLoading,
67
+ isError: query.isError,
68
+ error: query.error,
69
+ refetch: query.refetch,
70
+ isFetching: query.isFetching
71
+ };
72
+ }
73
+ function useMutateData(endpoint, method = "POST") {
74
+ const mutation = useMutation({
75
+ mutationFn: async (input) => {
76
+ const hasBody = input !== void 0 && input !== null;
77
+ const res = await fetch(`/api${endpoint}`, {
78
+ method,
79
+ headers: hasBody ? { "Content-Type": "application/json" } : {},
80
+ body: hasBody ? JSON.stringify(input) : void 0
81
+ });
82
+ if (!res.ok) {
83
+ throw new Error(`${method} ${endpoint} failed: ${res.status} ${res.statusText}`);
84
+ }
85
+ return res.json();
86
+ }
87
+ });
88
+ return {
89
+ mutate: mutation.mutate,
90
+ mutateAsync: mutation.mutateAsync,
91
+ isLoading: mutation.isPending,
92
+ isError: mutation.isError,
93
+ error: mutation.error,
94
+ data: mutation.data
95
+ };
96
+ }
97
+ function buildUrl(endpoint, params) {
98
+ if (!params || Object.keys(params).length === 0) {
99
+ return endpoint;
100
+ }
101
+ const searchParams = new URLSearchParams();
102
+ for (const [key, value] of Object.entries(params)) {
103
+ if (value !== void 0 && value !== null) {
104
+ searchParams.set(key, String(value));
105
+ }
106
+ }
107
+ const sep = endpoint.includes("?") ? "&" : "?";
108
+ return `${endpoint}${sep}${searchParams.toString()}`;
109
+ }
110
+ async function fetchJson(endpoint) {
111
+ const res = await fetch(`/api${endpoint}`);
112
+ if (!res.ok) {
113
+ throw new Error(`GET ${endpoint} failed: ${res.status} ${res.statusText}`);
114
+ }
115
+ const json = await res.json();
116
+ if (json && typeof json === "object" && "ok" in json && "data" in json) {
117
+ return json.data;
118
+ }
119
+ return json;
120
+ }
121
+ function useSSE(endpoint, options = {}) {
122
+ const {
123
+ events: eventNames = "message",
124
+ doneEvent,
125
+ enabled = true,
126
+ reconnect = false,
127
+ maxReconnects = 5,
128
+ reconnectIntervalMs = 2e3,
129
+ maxEvents = 0,
130
+ parse = defaultParse,
131
+ params,
132
+ onEvent,
133
+ onOpen,
134
+ onError,
135
+ onDone
136
+ } = options;
137
+ const [items, setItems] = useState([]);
138
+ const [latest, setLatest] = useState(void 0);
139
+ const [error, setError] = useState(null);
140
+ const [isConnected, setIsConnected] = useState(false);
141
+ const [reconnectCount, setReconnectCount] = useState(0);
142
+ const esRef = useRef(null);
143
+ const reconnectTimer = useRef(null);
144
+ const closedByUser = useRef(false);
145
+ const onEventRef = useRef(onEvent);
146
+ const onOpenRef = useRef(onOpen);
147
+ const onErrorRef = useRef(onError);
148
+ const onDoneRef = useRef(onDone);
149
+ const parseRef = useRef(parse);
150
+ onEventRef.current = onEvent;
151
+ onOpenRef.current = onOpen;
152
+ onErrorRef.current = onError;
153
+ onDoneRef.current = onDone;
154
+ parseRef.current = parse;
155
+ const eventNamesKey = JSON.stringify(eventNames);
156
+ const paramsKey = JSON.stringify(params);
157
+ const close = useCallback(() => {
158
+ closedByUser.current = true;
159
+ if (reconnectTimer.current) {
160
+ clearTimeout(reconnectTimer.current);
161
+ reconnectTimer.current = null;
162
+ }
163
+ if (esRef.current) {
164
+ esRef.current.close();
165
+ esRef.current = null;
166
+ }
167
+ setIsConnected(false);
168
+ }, []);
169
+ const clear = useCallback(() => {
170
+ setItems([]);
171
+ setLatest(void 0);
172
+ }, []);
173
+ useEffect(() => {
174
+ if (!endpoint || !enabled) {
175
+ if (esRef.current) {
176
+ esRef.current.close();
177
+ esRef.current = null;
178
+ }
179
+ setIsConnected(false);
180
+ return;
181
+ }
182
+ closedByUser.current = false;
183
+ setItems([]);
184
+ setLatest(void 0);
185
+ setError(null);
186
+ setReconnectCount(0);
187
+ let attempt = 0;
188
+ function connect() {
189
+ const url = buildSSEUrl(endpoint, params);
190
+ const es = new EventSource(url);
191
+ esRef.current = es;
192
+ const names = Array.isArray(eventNames) ? eventNames : [eventNames];
193
+ const handleMessage = (e) => {
194
+ try {
195
+ const parsed = parseRef.current(e.data);
196
+ setLatest(parsed);
197
+ setItems((prev) => {
198
+ const next = [...prev, parsed];
199
+ return maxEvents > 0 && next.length > maxEvents ? next.slice(-maxEvents) : next;
200
+ });
201
+ onEventRef.current?.(parsed);
202
+ } catch (err) {
203
+ const parseError = err instanceof Error ? err : new Error("Failed to parse SSE event data");
204
+ setError(parseError);
205
+ onErrorRef.current?.(parseError);
206
+ }
207
+ };
208
+ for (const name of names) {
209
+ es.addEventListener(name, handleMessage);
210
+ }
211
+ if (doneEvent) {
212
+ es.addEventListener(doneEvent, () => {
213
+ es.close();
214
+ esRef.current = null;
215
+ setIsConnected(false);
216
+ onDoneRef.current?.();
217
+ });
218
+ }
219
+ es.onopen = () => {
220
+ attempt = 0;
221
+ setReconnectCount(0);
222
+ setIsConnected(true);
223
+ setError(null);
224
+ onOpenRef.current?.();
225
+ };
226
+ es.onerror = () => {
227
+ es.close();
228
+ esRef.current = null;
229
+ setIsConnected(false);
230
+ if (closedByUser.current) {
231
+ return;
232
+ }
233
+ const connError = new Error("SSE connection lost");
234
+ setError(connError);
235
+ onErrorRef.current?.(connError);
236
+ if (reconnect && attempt < maxReconnects) {
237
+ attempt++;
238
+ setReconnectCount(attempt);
239
+ const delay = reconnectIntervalMs * Math.pow(2, attempt - 1);
240
+ reconnectTimer.current = setTimeout(connect, delay);
241
+ }
242
+ };
243
+ }
244
+ connect();
245
+ return () => {
246
+ closedByUser.current = true;
247
+ if (reconnectTimer.current) {
248
+ clearTimeout(reconnectTimer.current);
249
+ reconnectTimer.current = null;
250
+ }
251
+ if (esRef.current) {
252
+ esRef.current.close();
253
+ esRef.current = null;
254
+ }
255
+ };
256
+ }, [endpoint, enabled, doneEvent, reconnect, maxReconnects, reconnectIntervalMs, maxEvents, eventNamesKey, paramsKey]);
257
+ return { events: items, latest, isConnected, error, close, clear, reconnectCount };
258
+ }
259
+ function defaultParse(raw) {
260
+ return JSON.parse(raw);
261
+ }
262
+ function buildSSEUrl(endpoint, params) {
263
+ const base = endpoint.startsWith("http") ? endpoint : `/api${endpoint}`;
264
+ if (!params || Object.keys(params).length === 0) {
265
+ return base;
266
+ }
267
+ const sp = new URLSearchParams();
268
+ for (const [key, value] of Object.entries(params)) {
269
+ if (value !== void 0 && value !== null) {
270
+ sp.set(key, String(value));
271
+ }
272
+ }
273
+ const sep = base.includes("?") ? "&" : "?";
274
+ return `${base}${sep}${sp.toString()}`;
275
+ }
276
+ function useInfiniteData(endpoint, options) {
277
+ const {
278
+ getNextCursor,
279
+ params,
280
+ enabled,
281
+ staleTime,
282
+ cursorParam = "cursor",
283
+ initialCursor
284
+ } = options;
285
+ const query = useInfiniteQuery({
286
+ queryKey: ["studio-infinite", endpoint, params],
287
+ queryFn: async ({ pageParam }) => {
288
+ const url = buildInfiniteUrl(endpoint, params, cursorParam, pageParam);
289
+ return fetchPage(url);
290
+ },
291
+ initialPageParam: initialCursor,
292
+ getNextPageParam: getNextCursor,
293
+ enabled,
294
+ staleTime
295
+ });
296
+ const pages = query.data?.pages ?? [];
297
+ const flatData = pages.flatMap((page) => Array.isArray(page) ? page : [page]);
298
+ return {
299
+ pages,
300
+ data: flatData,
301
+ isLoading: query.isLoading,
302
+ isFetching: query.isFetching,
303
+ isFetchingNextPage: query.isFetchingNextPage,
304
+ hasNextPage: query.hasNextPage,
305
+ fetchNextPage: query.fetchNextPage,
306
+ error: query.error,
307
+ isError: query.isError,
308
+ refetch: query.refetch
309
+ };
310
+ }
311
+ function buildInfiniteUrl(endpoint, params, cursorParam, cursor) {
312
+ const sp = new URLSearchParams();
313
+ if (params) {
314
+ for (const [key, value] of Object.entries(params)) {
315
+ if (value !== void 0 && value !== null) {
316
+ sp.set(key, String(value));
317
+ }
318
+ }
319
+ }
320
+ if (cursor !== void 0 && cursor !== null) {
321
+ sp.set(cursorParam, String(cursor));
322
+ }
323
+ const qs = sp.toString();
324
+ const base = endpoint.startsWith("http") ? endpoint : `/api${endpoint}`;
325
+ return qs ? `${base}?${qs}` : base;
326
+ }
327
+ async function fetchPage(url) {
328
+ const res = await fetch(url);
329
+ if (!res.ok) {
330
+ throw new Error(`GET ${url} failed: ${res.status} ${res.statusText}`);
331
+ }
332
+ const json = await res.json();
333
+ if (json && typeof json === "object" && "ok" in json && "data" in json) {
334
+ return json.data;
335
+ }
336
+ return json;
337
+ }
338
+ function useWebSocket(url, options = {}) {
339
+ const {
340
+ enabled = true,
341
+ reconnect = false,
342
+ maxReconnects = 5,
343
+ reconnectIntervalMs = 2e3,
344
+ protocols,
345
+ parse = defaultParse2,
346
+ serialize = defaultSerialize,
347
+ maxMessages = 100,
348
+ onMessage,
349
+ onOpen,
350
+ onClose,
351
+ onError
352
+ } = options;
353
+ const [messages, setMessages] = useState([]);
354
+ const [latest, setLatest] = useState(void 0);
355
+ const [status, setStatus] = useState("disconnected");
356
+ const [error, setError] = useState(null);
357
+ const [reconnectCount, setReconnectCount] = useState(0);
358
+ const wsRef = useRef(null);
359
+ const reconnectTimer = useRef(null);
360
+ const closedByUser = useRef(false);
361
+ const onMessageRef = useRef(onMessage);
362
+ const onOpenRef = useRef(onOpen);
363
+ const onCloseRef = useRef(onClose);
364
+ const onErrorRef = useRef(onError);
365
+ const parseRef = useRef(parse);
366
+ const serializeRef = useRef(serialize);
367
+ onMessageRef.current = onMessage;
368
+ onOpenRef.current = onOpen;
369
+ onCloseRef.current = onClose;
370
+ onErrorRef.current = onError;
371
+ parseRef.current = parse;
372
+ serializeRef.current = serialize;
373
+ const cleanup = useCallback(() => {
374
+ if (reconnectTimer.current) {
375
+ clearTimeout(reconnectTimer.current);
376
+ reconnectTimer.current = null;
377
+ }
378
+ if (wsRef.current) {
379
+ wsRef.current.close();
380
+ wsRef.current = null;
381
+ }
382
+ }, []);
383
+ const doConnect = useCallback(() => {
384
+ if (!url) {
385
+ return;
386
+ }
387
+ cleanup();
388
+ closedByUser.current = false;
389
+ setStatus("connecting");
390
+ setError(null);
391
+ let attempt = 0;
392
+ function open() {
393
+ const resolvedUrl = resolveWsUrl(url);
394
+ const ws = protocols ? new WebSocket(resolvedUrl, protocols) : new WebSocket(resolvedUrl);
395
+ wsRef.current = ws;
396
+ ws.onopen = (e) => {
397
+ attempt = 0;
398
+ setReconnectCount(0);
399
+ setStatus("connected");
400
+ setError(null);
401
+ onOpenRef.current?.(e);
402
+ };
403
+ ws.onmessage = (e) => {
404
+ try {
405
+ const data = parseRef.current(e.data);
406
+ setLatest(data);
407
+ setMessages((prev) => {
408
+ const next = [...prev, data];
409
+ return maxMessages > 0 && next.length > maxMessages ? next.slice(-maxMessages) : next;
410
+ });
411
+ onMessageRef.current?.(data);
412
+ } catch {
413
+ }
414
+ };
415
+ ws.onclose = (e) => {
416
+ wsRef.current = null;
417
+ setStatus("disconnected");
418
+ onCloseRef.current?.(e);
419
+ if (closedByUser.current) {
420
+ return;
421
+ }
422
+ if (reconnect && attempt < maxReconnects && e.code !== 1e3) {
423
+ attempt++;
424
+ setReconnectCount(attempt);
425
+ const delay = reconnectIntervalMs * Math.pow(2, attempt - 1);
426
+ reconnectTimer.current = setTimeout(open, delay);
427
+ }
428
+ };
429
+ ws.onerror = (e) => {
430
+ setStatus("error");
431
+ setError(e);
432
+ onErrorRef.current?.(e);
433
+ };
434
+ }
435
+ open();
436
+ }, [url, protocols, reconnect, maxReconnects, reconnectIntervalMs, maxMessages, cleanup]);
437
+ const disconnect = useCallback((code, reason) => {
438
+ closedByUser.current = true;
439
+ if (reconnectTimer.current) {
440
+ clearTimeout(reconnectTimer.current);
441
+ reconnectTimer.current = null;
442
+ }
443
+ if (wsRef.current) {
444
+ wsRef.current.close(code, reason);
445
+ wsRef.current = null;
446
+ }
447
+ setStatus("disconnected");
448
+ }, []);
449
+ const send = useCallback((data) => {
450
+ if (wsRef.current?.readyState === WebSocket.OPEN) {
451
+ wsRef.current.send(serializeRef.current(data));
452
+ }
453
+ }, []);
454
+ const sendRaw = useCallback((data) => {
455
+ if (wsRef.current?.readyState === WebSocket.OPEN) {
456
+ wsRef.current.send(data);
457
+ }
458
+ }, []);
459
+ const clear = useCallback(() => {
460
+ setMessages([]);
461
+ setLatest(void 0);
462
+ }, []);
463
+ useEffect(() => {
464
+ if (!url || !enabled) {
465
+ cleanup();
466
+ setStatus("disconnected");
467
+ return;
468
+ }
469
+ setMessages([]);
470
+ setLatest(void 0);
471
+ doConnect();
472
+ return () => {
473
+ closedByUser.current = true;
474
+ cleanup();
475
+ };
476
+ }, [url, enabled]);
477
+ return {
478
+ send,
479
+ sendRaw,
480
+ messages,
481
+ latest,
482
+ status,
483
+ isConnected: status === "connected",
484
+ error,
485
+ connect: doConnect,
486
+ disconnect,
487
+ clear,
488
+ reconnectCount
489
+ };
490
+ }
491
+ function defaultParse2(raw) {
492
+ return JSON.parse(raw);
493
+ }
494
+ function defaultSerialize(data) {
495
+ return JSON.stringify(data);
496
+ }
497
+ function resolveWsUrl(url) {
498
+ if (url.startsWith("ws://") || url.startsWith("wss://")) {
499
+ return url;
500
+ }
501
+ const proto = window.location.protocol === "https:" ? "wss:" : "ws:";
502
+ const path = url.startsWith("/") ? url : `/${url}`;
503
+ return `${proto}//${window.location.host}${path}`;
504
+ }
505
+ function usePermissions() {
506
+ const { permissions } = usePageContext();
507
+ const hasPermission = useCallback(
508
+ (permission) => permissions.includes(permission),
509
+ [permissions]
510
+ );
511
+ return { hasPermission, permissions };
512
+ }
513
+ function useNavigation() {
514
+ const nav = useNavigate();
515
+ const location = useLocation();
516
+ const navigate = useCallback((path) => nav(path), [nav]);
517
+ const goBack = useCallback(() => nav(-1), [nav]);
518
+ const openExternal = useCallback((url) => window.open(url, "_blank", "noopener"), []);
519
+ return {
520
+ navigate,
521
+ currentPath: location.pathname,
522
+ goBack,
523
+ openExternal
524
+ };
525
+ }
526
+ function useNotification() {
527
+ const notify = useCallback(
528
+ (opts) => {
529
+ notification[opts.type]({
530
+ message: opts.message,
531
+ description: opts.description,
532
+ duration: opts.duration ?? 4.5
533
+ });
534
+ },
535
+ []
536
+ );
537
+ const success = useCallback(
538
+ (message, description) => notify({ type: "success", message, description }),
539
+ [notify]
540
+ );
541
+ const error = useCallback(
542
+ (message, description) => notify({ type: "error", message, description }),
543
+ [notify]
544
+ );
545
+ const warning = useCallback(
546
+ (message, description) => notify({ type: "warning", message, description }),
547
+ [notify]
548
+ );
549
+ const info = useCallback(
550
+ (message, description) => notify({ type: "info", message, description }),
551
+ [notify]
552
+ );
553
+ return { notify, success, error, warning, info };
554
+ }
555
+ var LIGHT_SEMANTIC = {
556
+ bgPrimary: lightSemanticColors["bg-primary"],
557
+ bgSecondary: lightSemanticColors["bg-secondary"],
558
+ bgTertiary: lightSemanticColors["bg-tertiary"],
559
+ textPrimary: lightSemanticColors["text-primary"],
560
+ textSecondary: lightSemanticColors["text-secondary"],
561
+ textTertiary: lightSemanticColors["text-tertiary"],
562
+ textInverse: lightSemanticColors["text-inverse"],
563
+ borderPrimary: lightSemanticColors["border-primary"],
564
+ borderSecondary: lightSemanticColors["border-secondary"],
565
+ link: lightSemanticColors["link"],
566
+ linkHover: lightSemanticColors["link-hover"],
567
+ accentSubtle: lightSemanticColors["accent-subtle"],
568
+ success: lightSemanticColors["success"],
569
+ warning: lightSemanticColors["warning"],
570
+ error: lightSemanticColors["error"],
571
+ info: lightSemanticColors["info"],
572
+ disabled: lightSemanticColors["disabled"],
573
+ shadow: lightSemanticColors["shadow"]
574
+ };
575
+ var DARK_SEMANTIC = {
576
+ bgPrimary: darkSemanticColors["bg-primary"],
577
+ bgSecondary: darkSemanticColors["bg-secondary"],
578
+ bgTertiary: darkSemanticColors["bg-tertiary"],
579
+ textPrimary: darkSemanticColors["text-primary"],
580
+ textSecondary: darkSemanticColors["text-secondary"],
581
+ textTertiary: darkSemanticColors["text-tertiary"],
582
+ textInverse: darkSemanticColors["text-inverse"],
583
+ borderPrimary: darkSemanticColors["border-primary"],
584
+ borderSecondary: darkSemanticColors["border-secondary"],
585
+ link: darkSemanticColors["link"],
586
+ linkHover: darkSemanticColors["link-hover"],
587
+ accentSubtle: darkSemanticColors["accent-subtle"],
588
+ success: darkSemanticColors["success"],
589
+ warning: darkSemanticColors["warning"],
590
+ error: darkSemanticColors["error"],
591
+ info: darkSemanticColors["info"],
592
+ disabled: darkSemanticColors["disabled"],
593
+ shadow: darkSemanticColors["shadow"]
594
+ };
595
+ function useTheme() {
596
+ const { token: antdToken } = theme.useToken();
597
+ const mode = "light";
598
+ return {
599
+ mode,
600
+ antdToken,
601
+ semantic: mode === "dark" ? DARK_SEMANTIC : LIGHT_SEMANTIC,
602
+ tokens: { colors, spacing, typography, radius, shadows }
603
+ };
604
+ }
605
+ function getAntDesignTokens() {
606
+ return {
607
+ // ============ Primary Colors ============
608
+ colorPrimary: "var(--link, #0c66ff)",
609
+ colorPrimaryHover: "var(--link-hover, #0050cc)",
610
+ colorPrimaryActive: "var(--link-hover, #0050cc)",
611
+ colorPrimaryBg: "var(--accent-subtle, #dbeafe)",
612
+ // Light primary background
613
+ colorPrimaryBgHover: "var(--accent-subtle, #dbeafe)",
614
+ colorPrimaryBorder: "var(--link, #0c66ff)",
615
+ colorPrimaryBorderHover: "var(--link-hover, #0050cc)",
616
+ colorPrimaryText: "var(--link, #0c66ff)",
617
+ colorPrimaryTextHover: "var(--link-hover, #0050cc)",
618
+ colorPrimaryTextActive: "var(--link-hover, #0050cc)",
619
+ // ============ Success Colors ============
620
+ colorSuccess: "var(--success, #16A34A)",
621
+ colorSuccessHover: "var(--success, #16A34A)",
622
+ // Use same color
623
+ colorSuccessActive: "var(--success, #16A34A)",
624
+ colorSuccessBg: "var(--bg-tertiary, #F3F4F6)",
625
+ // Light background, could be success-specific
626
+ colorSuccessBgHover: "var(--bg-tertiary, #F3F4F6)",
627
+ colorSuccessBorder: "var(--success, #16A34A)",
628
+ colorSuccessBorderHover: "var(--success, #16A34A)",
629
+ colorSuccessText: "var(--success, #16A34A)",
630
+ colorSuccessTextHover: "var(--success, #16A34A)",
631
+ colorSuccessTextActive: "var(--success, #16A34A)",
632
+ // ============ Warning Colors ============
633
+ colorWarning: "var(--warning, #F59E0B)",
634
+ colorWarningHover: "var(--warning, #F59E0B)",
635
+ colorWarningActive: "var(--warning, #F59E0B)",
636
+ colorWarningBg: "var(--bg-tertiary, #F3F4F6)",
637
+ colorWarningBgHover: "var(--bg-tertiary, #F3F4F6)",
638
+ colorWarningBorder: "var(--warning, #F59E0B)",
639
+ colorWarningBorderHover: "var(--warning, #F59E0B)",
640
+ colorWarningText: "var(--warning, #F59E0B)",
641
+ colorWarningTextHover: "var(--warning, #F59E0B)",
642
+ colorWarningTextActive: "var(--warning, #F59E0B)",
643
+ colorWarningOutline: "rgba(245, 158, 11, 0.2)",
644
+ // NEW: Warning outline
645
+ // ============ Error Colors ============
646
+ colorError: "var(--error, #DC2626)",
647
+ colorErrorHover: "var(--error, #DC2626)",
648
+ colorErrorActive: "var(--error, #DC2626)",
649
+ colorErrorBg: "var(--bg-tertiary, #F3F4F6)",
650
+ colorErrorBgHover: "var(--bg-tertiary, #F3F4F6)",
651
+ colorErrorBorder: "var(--error, #DC2626)",
652
+ colorErrorBorderHover: "var(--error, #DC2626)",
653
+ colorErrorText: "var(--error, #DC2626)",
654
+ colorErrorTextHover: "var(--error, #DC2626)",
655
+ colorErrorTextActive: "var(--error, #DC2626)",
656
+ colorErrorOutline: "rgba(220, 38, 38, 0.2)",
657
+ // NEW: Error outline
658
+ // ============ Info Colors ============
659
+ colorInfo: "var(--info, #0EA5E9)",
660
+ colorInfoHover: "var(--info, #0EA5E9)",
661
+ colorInfoActive: "var(--info, #0EA5E9)",
662
+ colorInfoBg: "var(--bg-tertiary, #F3F4F6)",
663
+ colorInfoBgHover: "var(--bg-tertiary, #F3F4F6)",
664
+ colorInfoBorder: "var(--info, #0EA5E9)",
665
+ colorInfoBorderHover: "var(--info, #0EA5E9)",
666
+ colorInfoText: "var(--info, #0EA5E9)",
667
+ colorInfoTextHover: "var(--info, #0EA5E9)",
668
+ colorInfoTextActive: "var(--info, #0EA5E9)",
669
+ // ============ Background Colors ============
670
+ colorBgContainer: "var(--bg-secondary, #FFFFFF)",
671
+ colorBgBase: "var(--bg-primary, #F9FAFB)",
672
+ colorBgElevated: "var(--bg-secondary, #FFFFFF)",
673
+ colorBgLayout: "var(--bg-primary, #F9FAFB)",
674
+ colorBgSpotlight: "var(--bg-tertiary, #F3F4F6)",
675
+ colorBgMask: "rgba(0, 0, 0, 0.45)",
676
+ // Overlay/modal backdrop - use standard dark overlay
677
+ colorBgTextHover: "var(--bg-hover, #F3F4F6)",
678
+ // NEW: Text hover background
679
+ colorBgTextActive: "var(--bg-hover, #F3F4F6)",
680
+ // NEW: Text active background
681
+ colorBgContainerDisabled: "var(--bg-tertiary, #F3F4F6)",
682
+ // NEW: Disabled container bg
683
+ // ============ Text Colors ============
684
+ colorText: "var(--text-primary, #111827)",
685
+ colorTextBase: "var(--text-primary, #111827)",
686
+ // NEW: Base text color
687
+ colorTextSecondary: "var(--text-secondary, #6B7280)",
688
+ colorTextTertiary: "var(--text-tertiary, #6B7280)",
689
+ colorTextQuaternary: "var(--text-tertiary, #6B7280)",
690
+ // Use tertiary as fallback
691
+ colorTextDisabled: "var(--disabled, #9CA3AF)",
692
+ colorTextHeading: "var(--text-primary, #111827)",
693
+ // Headings use primary text
694
+ colorTextLabel: "var(--text-secondary, #6B7280)",
695
+ // Labels use secondary
696
+ colorTextDescription: "var(--text-secondary, #6B7280)",
697
+ // Descriptions use secondary
698
+ colorTextPlaceholder: "var(--text-tertiary, #6B7280)",
699
+ // Placeholders use tertiary
700
+ colorTextLightSolid: "var(--text-inverse, #FFFFFF)",
701
+ // NEW: Text on colored backgrounds
702
+ // ============ Border Colors ============
703
+ colorBorder: "var(--border-primary, #E5E7EB)",
704
+ colorBorderSecondary: "var(--border-secondary, #D4D4D4)",
705
+ colorBorderBg: "var(--bg-secondary, #FFFFFF)",
706
+ // NEW: Background border color
707
+ colorSplit: "var(--border-primary, #E5E7EB)",
708
+ // Splitter/divider uses primary border
709
+ // ============ Fill Colors (for input backgrounds, etc.) ============
710
+ colorFill: "var(--bg-tertiary, #F3F4F6)",
711
+ // Fill uses tertiary background
712
+ colorFillSecondary: "var(--bg-tertiary, #F3F4F6)",
713
+ // Used for table row hover
714
+ colorFillTertiary: "var(--bg-primary, #F9FAFB)",
715
+ // Used for table header backgrounds
716
+ colorFillQuaternary: "var(--bg-primary, #F9FAFB)",
717
+ colorFillContent: "var(--bg-hover, #F3F4F6)",
718
+ // NEW: Content area fill
719
+ colorFillContentHover: "var(--bg-hover, #F3F4F6)",
720
+ // NEW: Content hover fill
721
+ colorFillAlter: "var(--bg-tertiary, #F3F4F6)",
722
+ // NEW: Alternative fill
723
+ // ============ Neutral Colors ============
724
+ colorWhite: "#FFFFFF",
725
+ // Always white
726
+ // ============ Shadow ============
727
+ boxShadow: "0 1px 3px rgba(0,0,0,0.08), 0 1px 2px rgba(0,0,0,0.04)",
728
+ boxShadowSecondary: "0 4px 12px rgba(0,0,0,0.08)",
729
+ boxShadowTertiary: "0 8px 24px rgba(0,0,0,0.08)",
730
+ // ============ Border Radius ============
731
+ borderRadius: 8,
732
+ borderRadiusLG: 12,
733
+ borderRadiusSM: 6,
734
+ borderRadiusXS: 4,
735
+ borderRadiusOuter: 6,
736
+ // ============ Control Heights ============
737
+ controlHeight: 36,
738
+ controlHeightLG: 40,
739
+ controlHeightSM: 28,
740
+ controlHeightXS: 22,
741
+ // ============ Font Family ============
742
+ fontFamily: "var(--font-body, 'Inter', 'Segoe UI', sans-serif)",
743
+ // ============ Font Sizes ============
744
+ fontSize: 14,
745
+ fontSizeLG: 16,
746
+ fontSizeSM: 12,
747
+ fontSizeXL: 20,
748
+ fontSizeHeading1: 38,
749
+ fontSizeHeading2: 30,
750
+ fontSizeHeading3: 24,
751
+ fontSizeHeading4: 20,
752
+ fontSizeHeading5: 16,
753
+ fontSizeIcon: 12,
754
+ // ============ Font Weights ============
755
+ fontWeightStrong: 600,
756
+ lineHeight: 1.5714285714285714,
757
+ lineHeightLG: 1.5,
758
+ lineHeightSM: 1.6666666666666667,
759
+ // ============ Padding ============
760
+ padding: 16,
761
+ paddingLG: 24,
762
+ paddingSM: 12,
763
+ paddingXS: 8,
764
+ paddingXXS: 4,
765
+ // ============ Margin ============
766
+ margin: 16,
767
+ marginLG: 24,
768
+ marginSM: 12,
769
+ marginXS: 8,
770
+ marginXXS: 4,
771
+ // ============ Motion ============
772
+ motionDurationFast: "0.1s",
773
+ motionDurationMid: "0.2s",
774
+ motionDurationSlow: "0.3s",
775
+ motionEaseInOut: "cubic-bezier(0.645, 0.045, 0.355, 1)",
776
+ motionEaseOut: "cubic-bezier(0.215, 0.61, 0.355, 1)",
777
+ // ============ Link ============
778
+ colorLink: "var(--link, #0c66ff)",
779
+ colorLinkHover: "var(--link-hover, #0050cc)",
780
+ colorLinkActive: "var(--link-hover, #0050cc)",
781
+ // ============ Icons & Highlights ============
782
+ colorIcon: "var(--text-secondary, #6B7280)",
783
+ // NEW: Icon color
784
+ colorIconHover: "var(--text-primary, #111827)",
785
+ // NEW: Icon hover
786
+ colorHighlight: "var(--link, #0c66ff)",
787
+ // NEW: Highlight color
788
+ // ============ Control States (Inputs, Buttons, etc.) ============
789
+ controlOutline: "rgba(12, 102, 255, 0.15)",
790
+ // NEW: Input outline on focus
791
+ controlOutlineWidth: 2,
792
+ // NEW: Outline width
793
+ controlInteractiveSize: 16,
794
+ // NEW: Interactive hit area size
795
+ controlItemBgHover: "var(--bg-hover, #F3F4F6)",
796
+ // NEW: Item hover bg
797
+ controlItemBgActive: "var(--accent-subtle, #dbeafe)",
798
+ // NEW: Item active bg
799
+ controlItemBgActiveHover: "var(--accent-subtle, #dbeafe)",
800
+ // NEW: Item active hover
801
+ controlItemBgActiveDisabled: "var(--bg-tertiary, #F3F4F6)",
802
+ // NEW: Disabled active bg
803
+ controlTmpOutline: "rgba(12, 102, 255, 0.08)",
804
+ // NEW: Temporary outline
805
+ // ============ Screen Sizes (for responsive) ============
806
+ screenXS: 480,
807
+ screenSM: 576,
808
+ screenMD: 768,
809
+ screenLG: 992,
810
+ screenXL: 1200,
811
+ screenXXL: 1600
812
+ };
813
+ }
814
+ function getAntDesignComponents() {
815
+ return {
816
+ Table: {
817
+ // Colors
818
+ headerBg: "var(--bg-tertiary)",
819
+ headerColor: "var(--text-primary)",
820
+ borderColor: "var(--border-primary)",
821
+ colorText: "var(--text-primary)",
822
+ colorTextHeading: "var(--text-primary)",
823
+ // Row states (IMPORTANT for UX)
824
+ rowHoverBg: "var(--bg-hover)",
825
+ rowSelectedBg: "var(--accent-subtle)",
826
+ // NEW: Selected row background
827
+ rowSelectedHoverBg: "var(--accent-subtle)",
828
+ // NEW: Selected row hover
829
+ rowExpandedBg: "var(--bg-secondary)",
830
+ // NEW: Expanded row background
831
+ bodySortBg: "var(--bg-tertiary)",
832
+ // NEW: Sorted column background
833
+ // Header states
834
+ headerSortActiveBg: "var(--bg-tertiary)",
835
+ headerSortHoverBg: "var(--bg-tertiary)",
836
+ headerFilterHoverBg: "var(--bg-tertiary)",
837
+ fixedHeaderSortActiveBg: "var(--bg-tertiary)",
838
+ // Icons (IMPORTANT for visibility)
839
+ colorIcon: "var(--text-secondary)",
840
+ colorIconHover: "var(--text-primary)",
841
+ expandIconBg: "var(--bg-secondary)",
842
+ // Footer
843
+ footerBg: "var(--bg-tertiary)",
844
+ // NEW: Table footer background
845
+ footerColor: "var(--text-primary)",
846
+ // NEW: Footer text color
847
+ // Sizing
848
+ selectionColumnWidth: 60,
849
+ stickyScrollBarBg: "var(--bg-tertiary)",
850
+ stickyScrollBarBorderRadius: 4
851
+ },
852
+ Tag: {
853
+ defaultBg: "var(--bg-tertiary)",
854
+ defaultColor: "var(--text-primary)",
855
+ colorBorder: "var(--border-primary)",
856
+ colorSuccess: "var(--success)",
857
+ colorError: "var(--error)",
858
+ colorWarning: "var(--warning)",
859
+ colorInfo: "var(--info)"
860
+ },
861
+ Badge: {
862
+ colorError: "var(--error)",
863
+ colorSuccess: "var(--success)",
864
+ colorWarning: "var(--warning)",
865
+ colorInfo: "var(--info)",
866
+ colorText: "var(--text-primary)"
867
+ },
868
+ Alert: {
869
+ // ============ Status colors ============
870
+ colorSuccess: "var(--success)",
871
+ colorError: "var(--error)",
872
+ colorWarning: "var(--warning)",
873
+ colorInfo: "var(--info)",
874
+ // ============ Text & background ============
875
+ colorText: "var(--text-primary)",
876
+ colorTextHeading: "var(--text-primary)",
877
+ colorBgContainer: "var(--bg-secondary)",
878
+ colorBorder: "var(--border-primary)",
879
+ // ============ Icons (IMPORTANT for close button visibility) ============
880
+ colorIcon: "var(--text-secondary)",
881
+ // NEW: Icon color (close button)
882
+ colorIconHover: "var(--text-primary)",
883
+ // NEW: Icon hover (close button hover)
884
+ // ============ Status-specific backgrounds ============
885
+ colorSuccessBg: "var(--bg-tertiary)",
886
+ // NEW: Success alert background
887
+ colorErrorBg: "var(--bg-tertiary)",
888
+ // NEW: Error alert background
889
+ colorWarningBg: "var(--bg-tertiary)",
890
+ // NEW: Warning alert background
891
+ colorInfoBg: "var(--bg-tertiary)",
892
+ // NEW: Info alert background
893
+ // ============ Status-specific borders ============
894
+ colorSuccessBorder: "var(--success)",
895
+ // NEW: Success alert border
896
+ colorErrorBorder: "var(--error)",
897
+ // NEW: Error alert border
898
+ colorWarningBorder: "var(--warning)",
899
+ // NEW: Warning alert border
900
+ colorInfoBorder: "var(--info)"
901
+ // NEW: Info alert border
902
+ },
903
+ Card: {
904
+ // Colors
905
+ colorText: "var(--text-primary)",
906
+ colorTextHeading: "var(--text-primary)",
907
+ colorBgContainer: "var(--bg-secondary)",
908
+ colorBorder: "var(--border-primary)",
909
+ colorBorderSecondary: "var(--border-primary)",
910
+ // Header & Actions (IMPORTANT for visual hierarchy)
911
+ headerBg: "var(--bg-secondary)",
912
+ // NEW: Card header background
913
+ actionsBg: "var(--bg-tertiary)",
914
+ // NEW: Card actions background
915
+ extraColor: "var(--text-secondary)"
916
+ // NEW: Extra area text color
917
+ },
918
+ Descriptions: {
919
+ colorText: "var(--text-primary)",
920
+ colorTextLabel: "var(--text-secondary)",
921
+ colorBorder: "var(--border-primary)"
922
+ },
923
+ Button: {
924
+ // ============ Base colors ============
925
+ colorText: "var(--text-primary)",
926
+ colorBgContainer: "var(--bg-secondary)",
927
+ colorBorder: "var(--border-primary)",
928
+ // ============ Primary button ============
929
+ colorPrimary: "var(--link)",
930
+ colorPrimaryHover: "var(--link-hover)",
931
+ colorPrimaryActive: "var(--link-hover)",
932
+ primaryColor: "var(--text-inverse)",
933
+ primaryShadow: "0 2px 0 rgba(12, 102, 255, 0.15)",
934
+ // ============ Default button (filled style) ============
935
+ defaultBg: "var(--bg-secondary)",
936
+ defaultColor: "var(--text-primary)",
937
+ defaultBorderColor: "var(--border-primary)",
938
+ defaultShadow: "0 2px 0 rgba(0, 0, 0, 0.015)",
939
+ // Default button - hover states (IMPORTANT for dark theme)
940
+ defaultHoverBg: "var(--bg-hover)",
941
+ defaultHoverColor: "var(--text-primary)",
942
+ defaultHoverBorderColor: "var(--border-secondary)",
943
+ // Default button - active states
944
+ defaultActiveBg: "var(--bg-hover)",
945
+ defaultActiveColor: "var(--text-primary)",
946
+ defaultActiveBorderColor: "var(--border-secondary)",
947
+ // ============ Ghost button (transparent with border) ============
948
+ ghostBg: "transparent",
949
+ defaultGhostColor: "var(--text-primary)",
950
+ // Text color
951
+ defaultGhostBorderColor: "var(--border-primary)",
952
+ // Border color
953
+ // Ghost button - active states
954
+ // ============ Dashed button (dashed border) ============
955
+ borderColorDisabled: "var(--border-primary)",
956
+ // Dashed border uses this
957
+ colorBgContainerDisabled: "var(--bg-tertiary)",
958
+ // Disabled background
959
+ // ============ Text button (no background, no border) ============
960
+ // CRITICAL: These control icon-only buttons like notification close button!
961
+ textTextColor: "var(--text-secondary)",
962
+ // Base text color for text buttons (icons!)
963
+ textTextHoverColor: "var(--text-primary)",
964
+ // Text button hover (icon hover!)
965
+ textTextActiveColor: "var(--text-primary)",
966
+ // Text button active (icon active!)
967
+ textHoverBg: "var(--accent-subtle)",
968
+ // Text button hover background
969
+ // ============ Link button (looks like a link) ============
970
+ linkHoverBg: "transparent",
971
+ colorLink: "var(--link)",
972
+ colorLinkHover: "var(--link-hover)",
973
+ colorLinkActive: "var(--link-hover)",
974
+ // ============ Solid button (filled buttons) ============
975
+ solidTextColor: "var(--text-primary)",
976
+ // Text color for solid buttons
977
+ // ============ Danger button ============
978
+ dangerColor: "var(--error)",
979
+ // Danger button text & border color
980
+ dangerShadow: "0 2px 0 rgba(220, 38, 38, 0.1)",
981
+ // Danger ghost button
982
+ colorErrorBg: "transparent",
983
+ // Ghost danger background
984
+ colorErrorBgHover: "var(--bg-hover)",
985
+ // Ghost danger hover
986
+ colorErrorBorder: "var(--error)",
987
+ // Ghost danger border
988
+ colorErrorBorderHover: "var(--error)",
989
+ // Ghost danger border hover
990
+ colorErrorHover: "var(--error)",
991
+ // Ghost danger text hover
992
+ colorErrorActive: "var(--error)"
993
+ // Ghost danger text active
994
+ },
995
+ Input: {
996
+ // Base colors
997
+ colorText: "var(--text-primary)",
998
+ colorBgContainer: "var(--bg-secondary)",
999
+ colorBorder: "var(--border-primary)",
1000
+ colorTextPlaceholder: "var(--text-tertiary)",
1001
+ // Interactive states (IMPORTANT for focus feedback)
1002
+ hoverBorderColor: "var(--border-secondary)",
1003
+ activeBorderColor: "var(--link)",
1004
+ activeShadow: "0 0 0 3px rgba(12, 102, 255, 0.12)",
1005
+ // NEW: Focus shadow
1006
+ errorActiveShadow: "0 0 0 2px rgba(220, 38, 38, 0.1)",
1007
+ // NEW: Error focus shadow
1008
+ warningActiveShadow: "0 0 0 2px rgba(245, 158, 11, 0.1)",
1009
+ // NEW: Warning focus shadow
1010
+ // Clear icon (IMPORTANT for visibility)
1011
+ colorIcon: "var(--text-secondary)",
1012
+ // NEW: Clear icon color
1013
+ colorIconHover: "var(--text-primary)"
1014
+ // NEW: Clear icon hover
1015
+ },
1016
+ Select: {
1017
+ // ============ Base colors ============
1018
+ colorText: "var(--text-primary)",
1019
+ colorBgContainer: "var(--bg-secondary)",
1020
+ // Input background
1021
+ colorBorder: "var(--border-primary)",
1022
+ // Input border
1023
+ colorBgElevated: "var(--bg-secondary)",
1024
+ // Dropdown panel background
1025
+ colorTextPlaceholder: "var(--text-tertiary)",
1026
+ // Placeholder text
1027
+ // ============ Primary & status colors ============
1028
+ colorPrimary: "var(--link)",
1029
+ // Selected item marker color
1030
+ colorPrimaryHover: "var(--link-hover)",
1031
+ // Selected item hover
1032
+ // ============ Options/items (IMPORTANT for selection feedback) ============
1033
+ optionSelectedBg: "var(--accent-subtle)",
1034
+ // Selected option background
1035
+ optionSelectedColor: "var(--link)",
1036
+ // Selected option text color
1037
+ optionActiveBg: "var(--bg-hover)",
1038
+ // Option hover background
1039
+ optionSelectedFontWeight: 600,
1040
+ // Bold for selected items
1041
+ // ============ Multiple select (tags mode) ============
1042
+ multipleItemBg: "var(--bg-tertiary)",
1043
+ // Tag background
1044
+ multipleItemBorderColor: "var(--border-primary)",
1045
+ // Tag border
1046
+ multipleItemColorDisabled: "var(--disabled)",
1047
+ // Disabled tag color
1048
+ // ============ Icons (IMPORTANT for visibility) ============
1049
+ colorIcon: "var(--text-secondary)",
1050
+ // Dropdown arrow, clear icon
1051
+ colorIconHover: "var(--text-primary)",
1052
+ // Icon hover
1053
+ // ============ Selector (input area) ============
1054
+ selectorBg: "var(--bg-secondary)"
1055
+ // Selector background
1056
+ },
1057
+ Dropdown: {
1058
+ // ============ Base colors ============
1059
+ colorText: "var(--text-primary)",
1060
+ colorBgElevated: "var(--bg-secondary)",
1061
+ // Dropdown panel background
1062
+ colorBorder: "var(--border-primary)",
1063
+ colorTextDisabled: "var(--disabled)",
1064
+ // ============ Item states (IMPORTANT for visual feedback) ============
1065
+ controlItemBgHover: "var(--bg-hover)",
1066
+ // Item hover background
1067
+ controlItemBgActive: "var(--accent-subtle)",
1068
+ // Selected item background
1069
+ controlItemBgActiveHover: "var(--accent-subtle)",
1070
+ // Selected item hover
1071
+ // ============ Colors for items ============
1072
+ colorPrimary: "var(--link)",
1073
+ // Primary color for selected items
1074
+ colorPrimaryHover: "var(--link-hover)",
1075
+ // Primary hover
1076
+ // ============ Dropdown.Button specific ============
1077
+ colorBgContainer: "var(--bg-secondary)",
1078
+ // Button background
1079
+ colorSplit: "var(--border-primary)",
1080
+ // Split line between button parts
1081
+ // ============ Padding & sizing ============
1082
+ paddingBlock: 8,
1083
+ // Vertical padding for items
1084
+ controlPaddingHorizontal: 12
1085
+ // Horizontal padding for items
1086
+ },
1087
+ Menu: {
1088
+ // ============ Base colors ============
1089
+ colorText: "var(--text-primary)",
1090
+ colorTextSecondary: "var(--text-secondary)",
1091
+ // NEW: Secondary text in menu items
1092
+ colorBgContainer: "var(--bg-sidebar)",
1093
+ // Menu background
1094
+ colorBorder: "var(--border-primary)",
1095
+ // NEW: Border color
1096
+ colorSplit: "var(--border-primary)",
1097
+ // NEW: Divider color
1098
+ // ============ Item colors (IMPORTANT for visibility) ============
1099
+ itemColor: "var(--text-primary)",
1100
+ // NEW: Default item text color
1101
+ itemBg: "var(--bg-secondary)",
1102
+ // NEW: Item background
1103
+ // ============ Hover states (IMPORTANT for feedback) ============
1104
+ itemHoverBg: "var(--bg-hover)",
1105
+ // Item hover background
1106
+ itemHoverColor: "var(--link)",
1107
+ // Item hover text color
1108
+ // ============ Selected states ============
1109
+ itemSelectedBg: "var(--accent-subtle)",
1110
+ // Selected item background
1111
+ itemSelectedColor: "var(--link)",
1112
+ // Selected item text color
1113
+ // ============ Active states ============
1114
+ itemActiveBg: "var(--accent-subtle)",
1115
+ // Active item background
1116
+ colorActiveBarBorderSize: 0,
1117
+ // No active bar (using background instead)
1118
+ // ============ Dark theme specific ============
1119
+ darkItemBg: "var(--bg-secondary)",
1120
+ // NEW: Dark mode item background
1121
+ darkItemColor: "var(--text-primary)",
1122
+ // NEW: Dark mode item text
1123
+ darkItemHoverBg: "var(--bg-hover)",
1124
+ // NEW: Dark mode hover
1125
+ darkItemSelectedBg: "var(--accent-subtle)",
1126
+ // Dark mode selected
1127
+ darkItemSelectedColor: "var(--link)",
1128
+ // Dark mode selected text
1129
+ darkSubMenuItemBg: "var(--bg-secondary)",
1130
+ // NEW: Dark mode submenu background
1131
+ // ============ SubMenu (dropdown menus) ============
1132
+ subMenuItemBg: "var(--bg-secondary)",
1133
+ // Submenu background
1134
+ popupBg: "var(--bg-secondary)",
1135
+ // NEW: Popup menu background
1136
+ // ============ Primary color ============
1137
+ colorPrimary: "var(--link)",
1138
+ // Primary color for active elements
1139
+ // ============ Icons (IMPORTANT for visibility) ============
1140
+ colorIcon: "var(--text-secondary)",
1141
+ // NEW: Icon color
1142
+ colorIconHover: "var(--text-primary)",
1143
+ // NEW: Icon hover
1144
+ // ============ Group title ============
1145
+ groupTitleColor: "var(--text-tertiary)",
1146
+ groupTitleFontSize: 11,
1147
+ // ============ Item border radius ============
1148
+ itemBorderRadius: 8,
1149
+ subMenuItemBorderRadius: 6,
1150
+ // ============ Padding ============
1151
+ itemPaddingInline: 12
1152
+ },
1153
+ Tabs: {
1154
+ // Base colors
1155
+ colorText: "var(--text-secondary)",
1156
+ colorTextHeading: "var(--text-primary)",
1157
+ colorBorder: "var(--border-primary)",
1158
+ colorBorderSecondary: "var(--border-primary)",
1159
+ // Interactive states (IMPORTANT for tab navigation feedback)
1160
+ colorPrimary: "var(--link)",
1161
+ itemHoverColor: "var(--link)",
1162
+ // Tab hover color
1163
+ itemSelectedColor: "var(--link)",
1164
+ // Selected tab color
1165
+ itemActiveColor: "var(--link)",
1166
+ // Active tab color
1167
+ inkBarColor: "var(--link)"
1168
+ // Active tab underline
1169
+ },
1170
+ Modal: {
1171
+ // Content colors
1172
+ colorText: "var(--text-primary)",
1173
+ colorTextHeading: "var(--text-primary)",
1174
+ colorBgElevated: "var(--bg-secondary)",
1175
+ colorBorder: "var(--border-primary)",
1176
+ // Header & Footer
1177
+ headerBg: "var(--bg-secondary)",
1178
+ // NEW: Modal header background
1179
+ footerBg: "var(--bg-tertiary)",
1180
+ // NEW: Modal footer background
1181
+ contentBg: "var(--bg-secondary)",
1182
+ // NEW: Modal content background
1183
+ // Close icon (IMPORTANT for visibility)
1184
+ colorIcon: "var(--text-secondary)",
1185
+ // NEW: Close icon color
1186
+ colorIconHover: "var(--text-primary)"
1187
+ // NEW: Close icon hover
1188
+ },
1189
+ Drawer: {
1190
+ // Content colors
1191
+ colorText: "var(--text-primary)",
1192
+ colorBgElevated: "var(--bg-secondary)",
1193
+ colorBorder: "var(--border-primary)",
1194
+ // Close icon (IMPORTANT for visibility)
1195
+ colorIcon: "var(--text-secondary)",
1196
+ // NEW: Close icon color
1197
+ colorIconHover: "var(--text-primary)"
1198
+ // NEW: Close icon hover
1199
+ },
1200
+ Popover: {
1201
+ colorText: "var(--text-primary)",
1202
+ colorBgElevated: "var(--bg-secondary)",
1203
+ colorBorder: "var(--border-primary)"
1204
+ },
1205
+ Tooltip: {
1206
+ colorText: "var(--text-primary)",
1207
+ colorBgSpotlight: "var(--bg-secondary)",
1208
+ colorTextLightSolid: "var(--text-primary)"
1209
+ },
1210
+ List: {
1211
+ // Base colors
1212
+ colorText: "var(--text-primary)",
1213
+ colorTextHeading: "var(--text-primary)",
1214
+ colorBorder: "var(--border-primary)",
1215
+ colorSplit: "var(--border-primary)",
1216
+ metaMarginBottom: 8,
1217
+ // Meta info spacing
1218
+ avatarMarginRight: 16
1219
+ // NEW: Avatar spacing
1220
+ },
1221
+ Switch: {
1222
+ colorPrimary: "var(--link)",
1223
+ colorPrimaryHover: "var(--link-hover)"
1224
+ },
1225
+ Radio: {
1226
+ colorPrimary: "var(--link)",
1227
+ colorText: "var(--text-primary)",
1228
+ buttonCheckedBg: "var(--link)",
1229
+ buttonCheckedBgDisabled: "var(--disabled)",
1230
+ buttonColor: "var(--text-primary)",
1231
+ buttonSolidCheckedColor: "var(--text-inverse)",
1232
+ buttonSolidCheckedBg: "var(--link)",
1233
+ buttonSolidCheckedHoverBg: "var(--link-hover)",
1234
+ buttonSolidCheckedActiveBg: "var(--link-hover)"
1235
+ },
1236
+ Checkbox: {
1237
+ colorPrimary: "var(--link)",
1238
+ colorText: "var(--text-primary)"
1239
+ },
1240
+ DatePicker: {
1241
+ // Base colors
1242
+ colorText: "var(--text-primary)",
1243
+ colorBgContainer: "var(--bg-secondary)",
1244
+ colorBorder: "var(--border-primary)",
1245
+ colorBgElevated: "var(--bg-secondary)",
1246
+ colorTextPlaceholder: "var(--text-tertiary)",
1247
+ colorTextDisabled: "var(--disabled)",
1248
+ // Interactive states (IMPORTANT for date selection feedback)
1249
+ colorLink: "var(--link)",
1250
+ // Selected date color
1251
+ colorLinkHover: "var(--link-hover)",
1252
+ // Date hover color
1253
+ cellHoverBg: "var(--bg-hover)",
1254
+ // NEW: Date cell hover background
1255
+ cellActiveWithRangeBg: "var(--accent-subtle)",
1256
+ // NEW: Range selection background
1257
+ cellBgDisabled: "var(--bg-tertiary)",
1258
+ // NEW: Disabled date background
1259
+ // Icons (IMPORTANT for visibility)
1260
+ colorIcon: "var(--text-secondary)",
1261
+ // NEW: Calendar icon color
1262
+ colorIconHover: "var(--text-primary)"
1263
+ // NEW: Calendar icon hover
1264
+ },
1265
+ Form: {
1266
+ colorText: "var(--text-primary)",
1267
+ colorTextLabel: "var(--text-secondary)",
1268
+ colorError: "var(--error)",
1269
+ colorWarning: "var(--warning)"
1270
+ },
1271
+ Pagination: {
1272
+ // Base colors
1273
+ colorText: "var(--text-primary)",
1274
+ colorTextDisabled: "var(--disabled)",
1275
+ colorBgContainer: "var(--bg-secondary)",
1276
+ // Interactive states (IMPORTANT for navigation feedback)
1277
+ colorPrimary: "var(--link)",
1278
+ // Active page background
1279
+ colorPrimaryHover: "var(--link-hover)",
1280
+ // Active page hover
1281
+ itemBg: "var(--bg-secondary)",
1282
+ // NEW: Page item background
1283
+ itemActiveBg: "var(--link)",
1284
+ // NEW: Active page background
1285
+ itemActiveBgDisabled: "var(--bg-tertiary)",
1286
+ // NEW: Disabled active page
1287
+ itemInputBg: "var(--bg-secondary)",
1288
+ // NEW: Quick jumper input background
1289
+ itemLinkBg: "var(--bg-secondary)",
1290
+ // NEW: Page link background
1291
+ // Hover states (IMPORTANT for visual feedback)
1292
+ colorBgTextHover: "var(--bg-hover)"
1293
+ // NEW: Page item hover background
1294
+ },
1295
+ Steps: {
1296
+ colorText: "var(--text-primary)",
1297
+ colorTextDescription: "var(--text-secondary)",
1298
+ colorPrimary: "var(--link)",
1299
+ colorBorder: "var(--border-primary)"
1300
+ },
1301
+ Breadcrumb: {
1302
+ colorText: "var(--text-secondary)",
1303
+ colorTextDescription: "var(--text-tertiary)",
1304
+ linkColor: "var(--link)",
1305
+ linkHoverColor: "var(--link-hover)",
1306
+ separatorColor: "var(--text-tertiary)"
1307
+ },
1308
+ Progress: {
1309
+ colorText: "var(--text-primary)",
1310
+ colorSuccess: "var(--success)",
1311
+ colorError: "var(--error)",
1312
+ remainingColor: "var(--bg-tertiary)"
1313
+ },
1314
+ Skeleton: {
1315
+ colorFill: "var(--bg-tertiary)",
1316
+ colorFillContent: "var(--bg-hover)"
1317
+ },
1318
+ Spin: {
1319
+ colorPrimary: "var(--link)",
1320
+ colorBgContainer: "var(--bg-secondary)"
1321
+ },
1322
+ Divider: {
1323
+ colorSplit: "var(--border-primary)",
1324
+ colorText: "var(--text-secondary)"
1325
+ },
1326
+ Layout: {
1327
+ headerBg: "var(--bg-secondary)",
1328
+ bodyBg: "var(--bg-primary)",
1329
+ triggerBg: "var(--bg-tertiary)",
1330
+ colorText: "var(--text-primary)"
1331
+ },
1332
+ Collapse: {
1333
+ colorText: "var(--text-primary)",
1334
+ colorTextHeading: "var(--text-primary)",
1335
+ colorBorder: "var(--border-primary)",
1336
+ colorBgContainer: "var(--bg-secondary)",
1337
+ headerBg: "var(--bg-tertiary)"
1338
+ },
1339
+ Carousel: {
1340
+ colorBgContainer: "var(--bg-secondary)",
1341
+ dotActiveWidth: 24
1342
+ },
1343
+ Anchor: {
1344
+ colorPrimary: "var(--link)",
1345
+ colorText: "var(--text-secondary)",
1346
+ linkPaddingBlock: 4
1347
+ },
1348
+ Timeline: {
1349
+ colorText: "var(--text-primary)",
1350
+ colorTextDescription: "var(--text-secondary)",
1351
+ tailColor: "var(--border-primary)",
1352
+ dotBg: "var(--bg-secondary)"
1353
+ },
1354
+ Transfer: {
1355
+ colorText: "var(--text-primary)",
1356
+ colorBgContainer: "var(--bg-secondary)",
1357
+ colorBorder: "var(--border-primary)",
1358
+ controlItemBgActive: "var(--bg-hover)"
1359
+ },
1360
+ Tree: {
1361
+ colorText: "var(--text-primary)",
1362
+ colorBgContainer: "var(--bg-secondary)",
1363
+ colorPrimary: "var(--link)",
1364
+ nodeHoverBg: "var(--bg-hover)",
1365
+ nodeSelectedBg: "var(--accent-subtle)"
1366
+ },
1367
+ TreeSelect: {
1368
+ colorText: "var(--text-primary)",
1369
+ colorBgContainer: "var(--bg-secondary)",
1370
+ colorBorder: "var(--border-primary)",
1371
+ colorBgElevated: "var(--bg-secondary)",
1372
+ nodeHoverBg: "var(--bg-hover)",
1373
+ nodeSelectedBg: "var(--accent-subtle)"
1374
+ },
1375
+ Cascader: {
1376
+ colorText: "var(--text-primary)",
1377
+ colorBgContainer: "var(--bg-secondary)",
1378
+ colorBorder: "var(--border-primary)",
1379
+ colorBgElevated: "var(--bg-secondary)",
1380
+ optionSelectedBg: "var(--bg-hover)"
1381
+ },
1382
+ Segmented: {
1383
+ colorText: "var(--text-primary)",
1384
+ colorTextLabel: "var(--text-secondary)",
1385
+ colorBgLayout: "var(--bg-tertiary)",
1386
+ itemSelectedBg: "var(--bg-secondary)",
1387
+ itemSelectedColor: "var(--link)",
1388
+ itemHoverBg: "var(--bg-hover)"
1389
+ },
1390
+ Rate: {
1391
+ colorText: "var(--warning)"
1392
+ },
1393
+ Slider: {
1394
+ colorPrimary: "var(--link)",
1395
+ colorPrimaryBorder: "var(--link)",
1396
+ trackBg: "var(--bg-tertiary)",
1397
+ trackHoverBg: "var(--bg-hover)"
1398
+ },
1399
+ Upload: {
1400
+ colorText: "var(--text-primary)",
1401
+ colorTextDescription: "var(--text-secondary)",
1402
+ colorBorder: "var(--border-primary)",
1403
+ colorFillAlter: "var(--bg-tertiary)",
1404
+ colorPrimary: "var(--link)"
1405
+ },
1406
+ Calendar: {
1407
+ colorText: "var(--text-primary)",
1408
+ colorTextHeading: "var(--text-primary)",
1409
+ colorBgContainer: "var(--bg-secondary)",
1410
+ colorBorder: "var(--border-primary)",
1411
+ itemActiveBg: "var(--accent-subtle)"
1412
+ },
1413
+ Image: {
1414
+ colorTextLightSolid: "var(--text-primary)",
1415
+ colorBgMask: "rgba(0, 0, 0, 0.45)"
1416
+ },
1417
+ Statistic: {
1418
+ colorText: "var(--text-primary)",
1419
+ colorTextDescription: "var(--text-secondary)"
1420
+ },
1421
+ Result: {
1422
+ colorText: "var(--text-primary)",
1423
+ colorTextHeading: "var(--text-primary)",
1424
+ colorTextDescription: "var(--text-secondary)"
1425
+ },
1426
+ Empty: {
1427
+ colorText: "var(--text-secondary)",
1428
+ colorTextDescription: "var(--text-tertiary)"
1429
+ },
1430
+ Message: {
1431
+ // ============ Base colors ============
1432
+ colorText: "var(--text-primary)",
1433
+ colorBgElevated: "var(--bg-secondary)",
1434
+ // Message background
1435
+ contentBg: "var(--bg-secondary)",
1436
+ // NEW: Content background
1437
+ contentPadding: "10px 16px",
1438
+ // NEW: Message padding
1439
+ // ============ Status colors ============
1440
+ colorSuccess: "var(--success)",
1441
+ colorError: "var(--error)",
1442
+ colorWarning: "var(--warning)",
1443
+ colorInfo: "var(--info)"
1444
+ },
1445
+ Notification: {
1446
+ // ============ Base colors ============
1447
+ colorText: "var(--text-primary)",
1448
+ colorTextHeading: "var(--text-primary)",
1449
+ colorBgElevated: "var(--bg-secondary)",
1450
+ // Notification background
1451
+ colorBorder: "var(--border-primary)",
1452
+ // ============ Close icon (IMPORTANT for visibility in dark theme!) ============
1453
+ colorIcon: "var(--text-secondary)",
1454
+ // NEW: Close button icon color
1455
+ colorIconHover: "var(--text-primary)",
1456
+ // NEW: Close button hover color
1457
+ // ============ Status colors ============
1458
+ colorSuccess: "var(--success)",
1459
+ colorError: "var(--error)",
1460
+ colorWarning: "var(--warning)",
1461
+ colorInfo: "var(--info)"
1462
+ }
1463
+ };
1464
+ }
1465
+
1466
+ export { PageContextProvider, getAntDesignComponents, getAntDesignTokens, useData, useEventBus, useInfiniteData, useMutateData, useNavigation, useNotification, usePage, usePageContext, usePermissions, useSSE, useTheme, useWebSocket };
1467
+ //# sourceMappingURL=index.js.map
1468
+ //# sourceMappingURL=index.js.map