@react-component-library-nlxx/components 1.0.1

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,690 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ //#region \0rolldown/runtime.js
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
12
+ key = keys[i];
13
+ if (!__hasOwnProp.call(to, key) && key !== except) {
14
+ __defProp(to, key, {
15
+ get: ((k) => from[k]).bind(null, key),
16
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
17
+ });
18
+ }
19
+ }
20
+ }
21
+ return to;
22
+ };
23
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
24
+ value: mod,
25
+ enumerable: true
26
+ }) : target, mod));
27
+
28
+ //#endregion
29
+ let react = require("react");
30
+ react = __toESM(react);
31
+ let styled_components = require("styled-components");
32
+ styled_components = __toESM(styled_components);
33
+ let react_jsx_runtime = require("react/jsx-runtime");
34
+ let rxjs = require("rxjs");
35
+ let rxjs_operators = require("rxjs/operators");
36
+
37
+ //#region src/Button/style.ts
38
+ const sizeStyles = {
39
+ small: styled_components.css`
40
+ height: 24px;
41
+ padding: 0 8px;
42
+ font-size: 12px;
43
+ `,
44
+ medium: styled_components.css`
45
+ height: 32px;
46
+ padding: 0 16px;
47
+ font-size: 14px;
48
+ `,
49
+ large: styled_components.css`
50
+ height: 40px;
51
+ padding: 0 24px;
52
+ font-size: 16px;
53
+ `
54
+ };
55
+ const variantStyles = {
56
+ primary: styled_components.css`
57
+ background: #1890ff;
58
+ color: white;
59
+ border: none;
60
+ &:hover:not(:disabled) { background: #40a9ff; }
61
+ &:active:not(:disabled) { background: #096dd9; }
62
+ `,
63
+ secondary: styled_components.css`
64
+ background: #f0f2f5;
65
+ color: #333;
66
+ border: none;
67
+ &:hover:not(:disabled) { background: #e6e9f0; }
68
+ `,
69
+ outline: styled_components.css`
70
+ background: transparent;
71
+ color: #1890ff;
72
+ border: 1px solid #1890ff;
73
+ &:hover:not(:disabled) { background: #e6f7ff; }
74
+ `,
75
+ ghost: styled_components.css`
76
+ background: transparent;
77
+ color: #1890ff;
78
+ border: none;
79
+ &:hover:not(:disabled) { background: rgba(24, 144, 255, 0.1); }
80
+ `
81
+ };
82
+ const shapeStyles = {
83
+ default: styled_components.css`border-radius: 4px;`,
84
+ round: styled_components.css`border-radius: 32px;`,
85
+ circle: styled_components.css`
86
+ border-radius: 50%;
87
+ padding: 0;
88
+ width: ${(props) => {
89
+ const size = props.size || "medium";
90
+ return size === "small" ? "24px" : size === "medium" ? "32px" : "40px";
91
+ }};
92
+ `
93
+ };
94
+ const StyledButton = styled_components.default.button`
95
+ display: inline-flex;
96
+ align-items: center;
97
+ justify-content: center;
98
+ gap: 8px;
99
+ cursor: pointer;
100
+ transition: all 0.2s;
101
+ font-weight: 400;
102
+ white-space: nowrap;
103
+
104
+ /* 尺寸 */
105
+ ${({ size = "medium" }) => sizeStyles[size]}
106
+
107
+ /* 变体 */
108
+ ${({ variant = "primary" }) => variantStyles[variant]}
109
+
110
+ /* 形状 */
111
+ ${({ shape = "default" }) => shapeStyles[shape]}
112
+
113
+ /* 块级按钮 */
114
+ ${({ block }) => block && styled_components.css`width: 100%;`}
115
+
116
+ /* 加载状态 */
117
+ ${({ loading }) => loading && styled_components.css`
118
+ opacity: 0.7;
119
+ cursor: not-allowed;
120
+ pointer-events: none;
121
+ `}
122
+
123
+ /* 禁用状态 */
124
+ &:disabled {
125
+ opacity: 0.5;
126
+ cursor: not-allowed;
127
+ }
128
+
129
+ /* 图标样式 */
130
+ .btn-icon {
131
+ display: inline-flex;
132
+ align-items: center;
133
+ }
134
+ `;
135
+
136
+ //#endregion
137
+ //#region src/Button/index.tsx
138
+ const Button = (0, react.forwardRef)((props, ref) => {
139
+ const { children, size = "medium", variant = "primary", shape = "default", loading = false, disabled = false, block = false, icon, iconPosition = "left", type = "button", ...rest } = props;
140
+ const renderIcon = () => {
141
+ if (!icon) return null;
142
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
143
+ className: `btn-icon btn-icon-${iconPosition}`,
144
+ children: icon
145
+ });
146
+ };
147
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(StyledButton, {
148
+ ref,
149
+ size,
150
+ variant,
151
+ shape,
152
+ loading,
153
+ disabled: disabled || loading,
154
+ block,
155
+ type,
156
+ ...rest,
157
+ children: [
158
+ iconPosition === "left" && renderIcon(),
159
+ children,
160
+ iconPosition === "right" && renderIcon()
161
+ ]
162
+ });
163
+ });
164
+ Button.displayName = "Button";
165
+
166
+ //#endregion
167
+ //#region src/Input/index.tsx
168
+ const ThemeContext$1 = react.default.createContext("light");
169
+ /**
170
+ * 非受控组件将状态交给 DOM 自己管理
171
+ * - 子组件:通过 forwardRef 接收 ref,并将其附加到内部的 input 元素,通过 ref 调用 clear()、直接操作 DOM(不推荐)。
172
+ *
173
+ * 受控组件将状态
174
+ * - 动态更新值,应采用受控模式(即使用 value 和 onChange)
175
+ */
176
+ const Input = (0, react.memo)((0, react.forwardRef)((props, ref) => {
177
+ const { name, placeholder, value, onChange, disabled, clearable, onClear, ...rest } = props;
178
+ const inputRef = (0, react.useRef)(null);
179
+ const theme = (0, react.useContext)(ThemeContext$1);
180
+ (0, react.useImperativeHandle)(ref, () => ({
181
+ focus: () => inputRef.current?.focus(),
182
+ blur: () => inputRef.current?.blur(),
183
+ clear: () => {
184
+ if (inputRef.current) {
185
+ inputRef.current.value = "";
186
+ if (onChange) {
187
+ const event = new Event("input", { bubbles: true });
188
+ Object.defineProperty(event, "target", { value: { value: "" } });
189
+ onChange(event);
190
+ }
191
+ }
192
+ },
193
+ getValue: () => inputRef.current?.value
194
+ }));
195
+ /**
196
+ * 清除逻辑同时兼容受控和非受控模式:受控时调用 onChange 更新父组件状态;非受控时直接修改 DOM。
197
+ * 通过 onClear 可额外执行清除后的操作
198
+ */
199
+ const handleClear = () => {
200
+ if (onChange) {
201
+ const event = new Event("input", { bubbles: true });
202
+ Object.defineProperty(event, "target", {
203
+ writable: false,
204
+ value: { value: "" }
205
+ });
206
+ onChange(event);
207
+ } else if (inputRef.current) inputRef.current.value = "";
208
+ onClear?.();
209
+ };
210
+ /**
211
+ * 兼容 受控 和 非受控 两种状态
212
+ * 受控模式下,value 和 onChange 必须同时存在且正确传递。
213
+ * 非受控模式下,不要传 value,可以传 defaultValue。
214
+ */
215
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
216
+ style: {
217
+ position: "relative",
218
+ display: "inline-block"
219
+ },
220
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
221
+ ref: inputRef,
222
+ name,
223
+ placeholder,
224
+ value,
225
+ onChange,
226
+ disabled,
227
+ className: `input-${theme}`,
228
+ style: { paddingRight: clearable ? "20px" : void 0 },
229
+ ...rest
230
+ }), clearable && (value || inputRef.current?.value) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
231
+ role: "button",
232
+ "aria-label": "clear",
233
+ onClick: handleClear,
234
+ style: {
235
+ position: "absolute",
236
+ right: "5px",
237
+ top: "50%",
238
+ transform: "translateY(-50%)",
239
+ cursor: "pointer"
240
+ },
241
+ children: "✕"
242
+ })]
243
+ });
244
+ }));
245
+
246
+ //#endregion
247
+ //#region src/SearchInput/style.ts
248
+ const Container$1 = styled_components.default.div`position:relative; width:100%;`;
249
+ const Input$1 = styled_components.default.input`
250
+ width:100%; padding:8px 12px; border:1px solid #d9d9d9; border-radius:4px; font-size:14px;
251
+ &:focus { outline:none; border-color:#1890ff; box-shadow:0 0 0 2px rgba(24,144,255,0.2); }
252
+ &:disabled { background:#f5f5f5; cursor:not-allowed; }
253
+ `;
254
+ const SuggestionsList = styled_components.default.ul`
255
+ position:absolute; top:100%; left:0; right:0; margin:4px 0 0; padding:4px 0;
256
+ list-style:none; background:white; border:1px solid #d9d9d9; border-radius:4px;
257
+ box-shadow:0 2px 8px rgba(0,0,0,0.15); z-index:1000; max-height:200px; overflow-y:auto;
258
+ `;
259
+ const SuggestionItem = styled_components.default.li`
260
+ padding:8px 12px; cursor:pointer; transition:background 0.2s;
261
+ &:hover { background:#f5f5f5; }
262
+ &.selected { background:#e6f7ff; }
263
+ `;
264
+
265
+ //#endregion
266
+ //#region src/SearchInput/index.tsx
267
+ const SearchInput = ({ debounceTime: debounceMs = 300, minSearchLength = 2, onSearch, searchResults$, showSuggestions = true, placeholder = "搜索...", ...rest }) => {
268
+ const [value, setValue] = (0, react.useState)("");
269
+ const [suggestions, setSuggestions] = (0, react.useState)([]);
270
+ const [showList, setShowList] = (0, react.useState)(false);
271
+ const [selectedIndex, setSelectedIndex] = (0, react.useState)(-1);
272
+ const inputRef = (0, react.useRef)(null);
273
+ const containerRef = (0, react.useRef)(null);
274
+ const input$ = (0, react.useMemo)(() => {
275
+ if (!inputRef.current) return null;
276
+ return (0, rxjs.fromEvent)(inputRef.current, "input").pipe((0, rxjs_operators.map)((e) => e.target.value), (0, rxjs_operators.filter)((v) => v.length >= minSearchLength || v.length === 0), (0, rxjs_operators.debounceTime)(debounceMs), (0, rxjs_operators.distinctUntilChanged)());
277
+ }, [debounceMs, minSearchLength]);
278
+ (0, react.useEffect)(() => {
279
+ if (!input$) return;
280
+ const subscription = input$.subscribe((value) => {
281
+ setValue(value);
282
+ onSearch?.(value);
283
+ });
284
+ return () => subscription.unsubscribe();
285
+ }, [input$, onSearch]);
286
+ (0, react.useEffect)(() => {
287
+ if (!searchResults$) {
288
+ setSuggestions([]);
289
+ return;
290
+ }
291
+ const subscription = searchResults$.subscribe((results) => {
292
+ setSuggestions(results);
293
+ if (results.length > 0) setShowList(true);
294
+ });
295
+ return () => subscription.unsubscribe();
296
+ }, [searchResults$]);
297
+ (0, react.useEffect)(() => {
298
+ if (searchResults$) return;
299
+ if (value.length >= minSearchLength) setSuggestions([`结果1: ${value}`, `结果2: ${value}`]);
300
+ else setSuggestions([]);
301
+ }, [
302
+ value,
303
+ minSearchLength,
304
+ searchResults$
305
+ ]);
306
+ (0, react.useEffect)(() => {
307
+ const handleClickOutside = (event) => {
308
+ if (containerRef.current && !containerRef.current.contains(event.target)) setShowList(false);
309
+ };
310
+ document.addEventListener("mousedown", handleClickOutside);
311
+ return () => document.removeEventListener("mousedown", handleClickOutside);
312
+ }, []);
313
+ const handleKeyDown = (e) => {
314
+ switch (e.key) {
315
+ case "ArrowDown":
316
+ e.preventDefault();
317
+ setSelectedIndex((i) => Math.min(i + 1, suggestions.length - 1));
318
+ break;
319
+ case "ArrowUp":
320
+ e.preventDefault();
321
+ setSelectedIndex((i) => Math.max(i - 1, -1));
322
+ break;
323
+ case "Enter":
324
+ if (selectedIndex >= 0) {
325
+ const selected = suggestions[selectedIndex];
326
+ setValue(selected);
327
+ setShowList(false);
328
+ onSearch?.(selected);
329
+ }
330
+ break;
331
+ case "Escape":
332
+ setShowList(false);
333
+ break;
334
+ }
335
+ };
336
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Container$1, {
337
+ ref: containerRef,
338
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Input$1, {
339
+ ref: inputRef,
340
+ value,
341
+ onChange: (e) => setValue(e.target.value),
342
+ onFocus: () => suggestions.length > 0 && setShowList(true),
343
+ onKeyDown: handleKeyDown,
344
+ placeholder,
345
+ ...rest
346
+ }), showSuggestions && showList && suggestions.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SuggestionsList, { children: suggestions.map((s, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SuggestionItem, {
347
+ className: i === selectedIndex ? "selected" : "",
348
+ onClick: () => {
349
+ setValue(s);
350
+ setShowList(false);
351
+ onSearch?.(s);
352
+ },
353
+ children: s
354
+ }, i)) })]
355
+ });
356
+ };
357
+
358
+ //#endregion
359
+ //#region src/Card/style.ts
360
+ const CardContainer = styled_components.default.div`
361
+ background: ${({ theme }) => theme.colors.background};
362
+ border-radius: ${({ theme }) => theme.borderRadius.md}px;
363
+ transition: all ${({ theme }) => theme.transitions.normal};
364
+ overflow: hidden;
365
+
366
+ /* 边框 */
367
+ ${({ bordered, theme }) => bordered && styled_components.css`
368
+ border: 1px solid ${theme.colors.border};
369
+ `}
370
+
371
+ /* 阴影 */
372
+ ${({ shadow, theme }) => {
373
+ if (shadow === "always") return styled_components.css`box-shadow: ${theme.shadows.md};`;
374
+ if (shadow === "hover") return styled_components.css`
375
+ &:hover {
376
+ box-shadow: ${theme.shadows.md};
377
+ }
378
+ `;
379
+ if (shadow === true) return styled_components.css`box-shadow: ${theme.shadows.sm};`;
380
+ return "";
381
+ }}
382
+
383
+ /* 悬停效果 */
384
+ ${({ hoverable, theme }) => hoverable && styled_components.css`
385
+ cursor: pointer;
386
+ &:hover {
387
+ transform: translateY(-2px);
388
+ box-shadow: ${theme.shadows.lg};
389
+ }
390
+ `}
391
+
392
+ /* 尺寸 */
393
+ ${({ size, theme }) => {
394
+ return styled_components.css`
395
+ padding: ${{
396
+ small: theme.spacing.sm,
397
+ default: theme.spacing.md,
398
+ large: theme.spacing.lg
399
+ }[size || "default"]}px;
400
+ `;
401
+ }}
402
+ `;
403
+ const CardHeader = styled_components.default.div`
404
+ display: flex;
405
+ align-items: center;
406
+ justify-content: space-between;
407
+ margin-bottom: ${({ theme }) => theme.spacing.sm}px;
408
+
409
+ h3 {
410
+ margin: 0;
411
+ font-size: ${({ theme }) => theme.typography.fontSize.md}px;
412
+ font-weight: ${({ theme }) => theme.typography.fontWeight.medium};
413
+ color: ${({ theme }) => theme.colors.text.primary};
414
+ }
415
+ `;
416
+ const CardCover = styled_components.default.div`
417
+ margin: -${({ theme }) => theme.spacing.md}px -${({ theme }) => theme.spacing.md}px
418
+ ${({ theme }) => theme.spacing.md}px -${({ theme }) => theme.spacing.md}px;
419
+
420
+ img {
421
+ width: 100%;
422
+ height: auto;
423
+ display: block;
424
+ }
425
+ `;
426
+ const CardContent = styled_components.default.div`
427
+ color: ${({ theme }) => theme.colors.text.secondary};
428
+ font-size: ${({ theme }) => theme.typography.fontSize.sm}px;
429
+ line-height: 1.5;
430
+ `;
431
+ const CardActions = styled_components.default.div`
432
+ display: flex;
433
+ align-items: center;
434
+ justify-content: space-around;
435
+ margin-top: ${({ theme }) => theme.spacing.md}px;
436
+ padding-top: ${({ theme }) => theme.spacing.sm}px;
437
+ border-top: 1px solid ${({ theme }) => theme.colors.border};
438
+ `;
439
+ const CardAction = styled_components.default.div`
440
+ flex: 1;
441
+ display: flex;
442
+ align-items: center;
443
+ justify-content: center;
444
+ cursor: pointer;
445
+ padding: ${({ theme }) => theme.spacing.xs}px;
446
+ transition: color ${({ theme }) => theme.transitions.fast};
447
+
448
+ &:hover {
449
+ color: ${({ theme }) => theme.colors.primary};
450
+ }
451
+ `;
452
+ const CardLoading = styled_components.default.div`
453
+ .loading-line {
454
+ height: 16px;
455
+ background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
456
+ background-size: 200% 100%;
457
+ animation: loading 1.5s infinite;
458
+ border-radius: ${({ theme }) => theme.borderRadius.sm}px;
459
+ margin-bottom: ${({ theme }) => theme.spacing.xs}px;
460
+
461
+ &:last-child {
462
+ width: 60%;
463
+ }
464
+ }
465
+
466
+ @keyframes loading {
467
+ 0% { background-position: 200% 0; }
468
+ 100% { background-position: -200% 0; }
469
+ }
470
+ `;
471
+
472
+ //#endregion
473
+ //#region src/Card/index.tsx
474
+ const Card = ({ title, extra, children, bordered = true, shadow = false, size = "default", hoverable = false, cover, actions, loading = false, onClick, className }) => {
475
+ const renderLoading = () => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(CardLoading, { children: [
476
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
477
+ className: "loading-line",
478
+ style: { width: "40%" }
479
+ }),
480
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "loading-line" }),
481
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "loading-line" }),
482
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "loading-line" })
483
+ ] });
484
+ const renderActions = () => {
485
+ if (!actions?.length) return null;
486
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CardActions, { children: actions.map((action, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CardAction, { children: action }, index)) });
487
+ };
488
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(CardContainer, {
489
+ bordered,
490
+ shadow,
491
+ size,
492
+ hoverable,
493
+ onClick,
494
+ className,
495
+ children: [
496
+ cover && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CardCover, { children: cover }),
497
+ (title || extra) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(CardHeader, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: title }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: extra })] }),
498
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CardContent, { children: loading ? renderLoading() : children }),
499
+ renderActions()
500
+ ]
501
+ });
502
+ };
503
+
504
+ //#endregion
505
+ //#region src/VirtualList/index.tsx
506
+ const Container = styled_components.default.div`
507
+ position: relative;
508
+ overflow-y: auto;
509
+ height: 100%;
510
+ `;
511
+ const Content = styled_components.default.div`
512
+ position: relative;
513
+ width: 100%;
514
+ `;
515
+ const Item = styled_components.default.div`
516
+ position: absolute;
517
+ top: ${({ top }) => top}px;
518
+ left: 0;
519
+ right: 0;
520
+ height: ${({ height }) => height}px;
521
+ `;
522
+ function VirtualList({ data, renderItem, itemHeight, height, overscan = 3, keyExtractor = (_, index) => index.toString() }) {
523
+ const [scrollTop, setScrollTop] = (0, react.useState)(0);
524
+ const containerRef = (0, react.useRef)(null);
525
+ (0, react.useEffect)(() => {
526
+ if (!containerRef.current) return;
527
+ const subscription = (0, rxjs.fromEvent)(containerRef.current, "scroll").pipe((0, rxjs_operators.throttleTime)(16)).subscribe(() => {
528
+ if (containerRef.current) setScrollTop(containerRef.current.scrollTop);
529
+ });
530
+ return () => subscription.unsubscribe();
531
+ }, []);
532
+ const totalHeight = data.length * itemHeight;
533
+ const startIndex = Math.max(0, Math.floor(scrollTop / itemHeight) - overscan);
534
+ const endIndex = Math.min(data.length, Math.ceil((scrollTop + height) / itemHeight) + overscan);
535
+ const visibleData = data.slice(startIndex, endIndex);
536
+ (0, react.useCallback)((index) => ({
537
+ top: index * itemHeight,
538
+ height: itemHeight
539
+ }), [itemHeight]);
540
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Container, {
541
+ ref: containerRef,
542
+ style: { height },
543
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Content, {
544
+ style: { height: totalHeight },
545
+ children: visibleData.map((item, index) => {
546
+ const actualIndex = startIndex + index;
547
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Item, {
548
+ top: actualIndex * itemHeight,
549
+ height: itemHeight,
550
+ children: renderItem(item, actualIndex)
551
+ }, keyExtractor(item, actualIndex));
552
+ })
553
+ })
554
+ });
555
+ }
556
+
557
+ //#endregion
558
+ //#region src/hooks/useDebounce.ts
559
+ /**
560
+ * 对传入的值进行防抖处理
561
+ * @param value 需要防抖的值
562
+ * @param delay 延迟时间(毫秒),默认 300ms
563
+ * @returns 防抖后的值
564
+ */
565
+ function useDebounce(value, delay = 300) {
566
+ const [debouncedValue, setDebouncedValue] = (0, react.useState)(value);
567
+ (0, react.useEffect)(() => {
568
+ const subject = new rxjs.Subject();
569
+ const subscription = subject.pipe((0, rxjs_operators.debounceTime)(delay), (0, rxjs_operators.distinctUntilChanged)()).subscribe(setDebouncedValue);
570
+ subject.next(value);
571
+ return () => {
572
+ subject.complete();
573
+ subscription.unsubscribe();
574
+ };
575
+ }, [value, delay]);
576
+ return debouncedValue;
577
+ }
578
+
579
+ //#endregion
580
+ //#region src/hooks/useObservable.ts
581
+ function useObservable(observable, initialValue) {
582
+ const [value, setValue] = (0, react.useState)(initialValue);
583
+ (0, react.useEffect)(() => {
584
+ const subscription = observable.subscribe(setValue);
585
+ return () => subscription.unsubscribe();
586
+ }, [observable]);
587
+ return value;
588
+ }
589
+
590
+ //#endregion
591
+ //#region ../theme/src/tokens.ts
592
+ const defaultTheme = {
593
+ colors: {
594
+ primary: "#1890ff",
595
+ secondary: "#f0f2f5",
596
+ success: "#52c41a",
597
+ warning: "#faad14",
598
+ error: "#f5222d",
599
+ info: "#1890ff",
600
+ background: "#ffffff",
601
+ text: {
602
+ primary: "#333333",
603
+ secondary: "#666666",
604
+ disabled: "#999999"
605
+ },
606
+ border: "#d9d9d9"
607
+ },
608
+ spacing: {
609
+ xs: 4,
610
+ sm: 8,
611
+ md: 16,
612
+ lg: 24,
613
+ xl: 32
614
+ },
615
+ typography: {
616
+ fontSize: {
617
+ xs: 12,
618
+ sm: 14,
619
+ md: 16,
620
+ lg: 18,
621
+ xl: 20
622
+ },
623
+ fontWeight: {
624
+ normal: 400,
625
+ medium: 500,
626
+ bold: 600
627
+ }
628
+ },
629
+ borderRadius: {
630
+ xs: 2,
631
+ sm: 4,
632
+ md: 6,
633
+ lg: 8,
634
+ xl: 12,
635
+ round: "50%"
636
+ },
637
+ shadows: {
638
+ sm: "0 2px 4px rgba(0, 0, 0, 0.1)",
639
+ md: "0 4px 8px rgba(0, 0, 0, 0.15)",
640
+ lg: "0 8px 16px rgba(0, 0, 0, 0.2)"
641
+ },
642
+ transitions: {
643
+ fast: "0.1s ease",
644
+ normal: "0.2s ease",
645
+ slow: "0.3s ease"
646
+ }
647
+ };
648
+
649
+ //#endregion
650
+ //#region ../theme/src/index.tsx
651
+ function deepMerge(target, source) {
652
+ const output = { ...target };
653
+ if (isObject(target) && isObject(source)) Object.keys(source).forEach((key) => {
654
+ const k = key;
655
+ if (isObject(source[k])) if (!(k in target)) output[k] = source[k];
656
+ else output[k] = deepMerge(target[k], source[k]);
657
+ else output[k] = source[k];
658
+ });
659
+ return output;
660
+ }
661
+ function isObject(item) {
662
+ return item && typeof item === "object" && !Array.isArray(item);
663
+ }
664
+ const ThemeContext = (0, react.createContext)(defaultTheme);
665
+ const useTheme = () => {
666
+ const theme = (0, react.useContext)(ThemeContext);
667
+ if (!theme) throw new Error("useTheme must be used within a ThemeProvider");
668
+ return theme;
669
+ };
670
+ const ThemeProvider = ({ theme = {}, children }) => {
671
+ const mergedTheme = (0, react.useMemo)(() => deepMerge(defaultTheme, theme), [theme]);
672
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ThemeContext.Provider, {
673
+ value: mergedTheme,
674
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(styled_components.ThemeProvider, {
675
+ theme: mergedTheme,
676
+ children
677
+ })
678
+ });
679
+ };
680
+
681
+ //#endregion
682
+ exports.Button = Button;
683
+ exports.Card = Card;
684
+ exports.Input = Input;
685
+ exports.SearchInput = SearchInput;
686
+ exports.ThemeProvider = ThemeProvider;
687
+ exports.VirtualList = VirtualList;
688
+ exports.useDebounce = useDebounce;
689
+ exports.useObservable = useObservable;
690
+ exports.useTheme = useTheme;