@ryanhe919/lumen-ui 0.1.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.cjs ADDED
@@ -0,0 +1,3847 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const React = require("react");
5
+ const reactDom = require("react-dom");
6
+ const COMPONENT_SIZE_ORDER = [
7
+ "xs",
8
+ "sm",
9
+ "md",
10
+ "lg",
11
+ "xl",
12
+ "2xl"
13
+ ];
14
+ const SIZE_TEXT_CLASSES = {
15
+ xs: "text-xs",
16
+ sm: "text-sm",
17
+ md: "text-base",
18
+ lg: "text-lg",
19
+ xl: "text-xl",
20
+ "2xl": "text-2xl"
21
+ };
22
+ const SIZE_HEADING_CLASSES = {
23
+ xs: "text-lg",
24
+ sm: "text-xl",
25
+ md: "text-2xl",
26
+ lg: "text-3xl",
27
+ xl: "text-4xl",
28
+ "2xl": "text-5xl"
29
+ };
30
+ const SIZE_DISPLAY_CLASSES = {
31
+ xs: "text-xl",
32
+ sm: "text-2xl",
33
+ md: "text-3xl",
34
+ lg: "text-4xl",
35
+ xl: "text-5xl",
36
+ "2xl": "text-6xl"
37
+ };
38
+ const SIZE_GAP_CLASSES = {
39
+ xs: "gap-1",
40
+ sm: "gap-1.5",
41
+ md: "gap-2",
42
+ lg: "gap-2.5",
43
+ xl: "gap-3",
44
+ "2xl": "gap-4"
45
+ };
46
+ const SIZE_PADDING_CLASSES = {
47
+ xs: "p-3",
48
+ sm: "p-4",
49
+ md: "p-6",
50
+ lg: "p-8",
51
+ xl: "p-10",
52
+ "2xl": "p-12"
53
+ };
54
+ const SIZE_BUTTON_CONFIG = {
55
+ xs: { padding: "px-2.5 py-1.5", height: "h-7" },
56
+ sm: { padding: "px-3 py-2", height: "h-8" },
57
+ md: { padding: "px-4 py-2.5", height: "h-10" },
58
+ lg: { padding: "px-5 py-3", height: "h-12" },
59
+ xl: { padding: "px-6 py-3.5", height: "h-14" },
60
+ "2xl": { padding: "px-8 py-4", height: "h-16" }
61
+ };
62
+ const SIZE_INPUT_CONFIG = {
63
+ xs: { padding: "px-3 py-1", height: "h-7", fontSize: "text-xs" },
64
+ sm: { padding: "px-3 py-1.5", height: "h-9", fontSize: "text-sm" },
65
+ md: { padding: "px-4 py-2", height: "h-10", fontSize: "text-sm" },
66
+ lg: { padding: "px-4 py-2.5", height: "h-12", fontSize: "text-base" },
67
+ xl: { padding: "px-5 py-3", height: "h-14", fontSize: "text-base" },
68
+ "2xl": { padding: "px-6 py-4", height: "h-16", fontSize: "text-lg" }
69
+ };
70
+ const SIZE_SELECTOR_CONFIG = {
71
+ xs: { padding: "px-3 py-1", height: "h-7", fontSize: "text-xs" },
72
+ sm: { padding: "px-3 py-1.5", height: "h-9", fontSize: "text-sm" },
73
+ md: { padding: "px-4 py-2", height: "h-10", fontSize: "text-sm" },
74
+ lg: { padding: "px-4 py-2.5", height: "h-12", fontSize: "text-base" },
75
+ xl: { padding: "px-5 py-3", height: "h-14", fontSize: "text-base" },
76
+ "2xl": { padding: "px-6 py-4", height: "h-16", fontSize: "text-lg" }
77
+ };
78
+ const SIZE_MODAL_CONFIG = {
79
+ xs: { width: "360px", maxWidth: "90vw" },
80
+ sm: { width: "480px", maxWidth: "90vw" },
81
+ md: { width: "640px", maxWidth: "90vw" },
82
+ lg: { width: "800px", maxWidth: "95vw" },
83
+ xl: { width: "960px", maxWidth: "95vw" },
84
+ "2xl": { width: "1200px", maxWidth: "95vw" }
85
+ };
86
+ const SIZE_TOOLTIP_CONFIG = {
87
+ xs: { paddingClass: "px-2.5 py-1.5", textClass: "text-xs", maxWidth: 200 },
88
+ sm: { paddingClass: "px-3 py-2", textClass: "text-sm", maxWidth: 240 },
89
+ md: { paddingClass: "px-4 py-2.5", textClass: "text-sm", maxWidth: 300 },
90
+ lg: { paddingClass: "px-4 py-3", textClass: "text-base", maxWidth: 360 },
91
+ xl: { paddingClass: "px-5 py-3", textClass: "text-lg", maxWidth: 420 },
92
+ "2xl": { paddingClass: "px-6 py-4", textClass: "text-xl", maxWidth: 500 }
93
+ };
94
+ const SIZE_ICON_CONFIG = {
95
+ xs: "w-4 h-4",
96
+ sm: "w-5 h-5",
97
+ md: "w-6 h-6",
98
+ lg: "w-8 h-8",
99
+ xl: "w-10 h-10",
100
+ "2xl": "w-12 h-12"
101
+ };
102
+ const SIZE_TABLE_CONFIG = {
103
+ xs: { cellPadding: "px-2 py-1", rowHeight: "h-8" },
104
+ sm: { cellPadding: "px-3 py-1.5", rowHeight: "h-10" },
105
+ md: { cellPadding: "px-4 py-2", rowHeight: "h-12" },
106
+ lg: { cellPadding: "px-6 py-3", rowHeight: "h-14" },
107
+ xl: { cellPadding: "px-8 py-4", rowHeight: "h-16" },
108
+ "2xl": { cellPadding: "px-10 py-5", rowHeight: "h-20" }
109
+ };
110
+ const clampComponentSize = (size, allowedSizes, fallback = "md") => {
111
+ const nextSize = size ?? fallback;
112
+ return allowedSizes.includes(nextSize) ? nextSize : fallback;
113
+ };
114
+ const LMButton$1 = ({
115
+ children,
116
+ variant = "primary",
117
+ size = "md",
118
+ loading = false,
119
+ loadingText,
120
+ leftIcon,
121
+ rightIcon,
122
+ fullWidth = false,
123
+ rounded = false,
124
+ disabled = false,
125
+ className = "",
126
+ ...props
127
+ }) => {
128
+ const isDisabled = disabled || loading;
129
+ const resolvedSize = clampComponentSize(size, COMPONENT_SIZE_ORDER);
130
+ const roundedClasses = rounded ? "rounded-full" : "rounded-2xl";
131
+ const widthClasses = fullWidth ? "w-full" : "";
132
+ const baseClassName = `
133
+ ${SIZE_BUTTON_CONFIG[resolvedSize].padding} ${SIZE_TEXT_CLASSES[resolvedSize]} ${SIZE_GAP_CLASSES[resolvedSize]}
134
+ ${roundedClasses} ${widthClasses}
135
+ backdrop-blur-md border transition-all duration-300
136
+ shadow-sm font-medium focus:ring-2 focus:ring-offset-0
137
+ focus:outline-none disabled:cursor-not-allowed
138
+ flex items-center justify-center
139
+ ${className}
140
+ `.trim().replace(/\s+/g, " ");
141
+ const getButtonStyles = () => {
142
+ const baseStyles = {
143
+ backgroundColor: "var(--lm-bg-elevated)",
144
+ color: "var(--lm-text-primary)",
145
+ borderColor: "var(--lm-border-default)",
146
+ boxShadow: "var(--lm-shadow-sm)"
147
+ };
148
+ switch (variant) {
149
+ case "primary":
150
+ return {
151
+ ...baseStyles,
152
+ backgroundColor: "var(--lm-primary-500)",
153
+ color: "white",
154
+ borderColor: "var(--lm-primary-500)",
155
+ "--tw-ring-color": "var(--lm-primary-400)",
156
+ "--tw-ring-opacity": "0.3"
157
+ };
158
+ case "secondary":
159
+ return {
160
+ ...baseStyles,
161
+ backgroundColor: "var(--lm-bg-paper)",
162
+ color: "var(--lm-text-primary)",
163
+ borderColor: "var(--lm-border-default)",
164
+ "--tw-ring-color": "var(--lm-primary-400)",
165
+ "--tw-ring-opacity": "0.3"
166
+ };
167
+ case "outline":
168
+ return {
169
+ ...baseStyles,
170
+ backgroundColor: "transparent",
171
+ color: "var(--lm-primary-600)",
172
+ borderColor: "var(--lm-primary-300)",
173
+ "--tw-ring-color": "var(--lm-primary-400)",
174
+ "--tw-ring-opacity": "0.3"
175
+ };
176
+ case "ghost":
177
+ return {
178
+ ...baseStyles,
179
+ backgroundColor: "transparent",
180
+ color: "var(--lm-text-primary)",
181
+ borderColor: "transparent",
182
+ "--tw-ring-color": "var(--lm-primary-400)",
183
+ "--tw-ring-opacity": "0.3"
184
+ };
185
+ case "danger":
186
+ return {
187
+ ...baseStyles,
188
+ backgroundColor: "var(--lm-error-500)",
189
+ color: "white",
190
+ borderColor: "var(--lm-error-500)",
191
+ "--tw-ring-color": "var(--lm-error-400)",
192
+ "--tw-ring-opacity": "0.3"
193
+ };
194
+ case "success":
195
+ return {
196
+ ...baseStyles,
197
+ backgroundColor: "var(--lm-success-500)",
198
+ color: "white",
199
+ borderColor: "var(--lm-success-500)",
200
+ "--tw-ring-color": "var(--lm-success-400)",
201
+ "--tw-ring-opacity": "0.3"
202
+ };
203
+ case "warning":
204
+ return {
205
+ ...baseStyles,
206
+ backgroundColor: "var(--lm-warning-500)",
207
+ color: "white",
208
+ borderColor: "var(--lm-warning-500)",
209
+ "--tw-ring-color": "var(--lm-warning-400)",
210
+ "--tw-ring-opacity": "0.3"
211
+ };
212
+ default:
213
+ return baseStyles;
214
+ }
215
+ };
216
+ const getDisabledStyles = () => {
217
+ if (isDisabled) {
218
+ return {
219
+ backgroundColor: "var(--lm-bg-paper)",
220
+ color: "var(--lm-text-disabled)",
221
+ borderColor: "var(--lm-border-light)",
222
+ cursor: "not-allowed",
223
+ opacity: 0.6
224
+ };
225
+ }
226
+ return {};
227
+ };
228
+ const getHoverStyles = () => {
229
+ if (isDisabled) return {};
230
+ switch (variant) {
231
+ case "primary":
232
+ return {
233
+ backgroundColor: "var(--lm-primary-600)",
234
+ borderColor: "var(--lm-primary-600)"
235
+ };
236
+ case "secondary":
237
+ return {
238
+ backgroundColor: "var(--lm-bg-elevated)",
239
+ borderColor: "var(--lm-border-strong)"
240
+ };
241
+ case "outline":
242
+ return {
243
+ backgroundColor: "var(--lm-primary-50)",
244
+ borderColor: "var(--lm-primary-400)"
245
+ };
246
+ case "ghost":
247
+ return {
248
+ backgroundColor: "var(--lm-bg-paper)"
249
+ };
250
+ case "danger":
251
+ return {
252
+ backgroundColor: "var(--lm-error-600)",
253
+ borderColor: "var(--lm-error-600)"
254
+ };
255
+ case "success":
256
+ return {
257
+ backgroundColor: "var(--lm-success-600)",
258
+ borderColor: "var(--lm-success-600)"
259
+ };
260
+ case "warning":
261
+ return {
262
+ backgroundColor: "var(--lm-warning-600)",
263
+ borderColor: "var(--lm-warning-600)"
264
+ };
265
+ default:
266
+ return {};
267
+ }
268
+ };
269
+ const getActiveStyles = () => {
270
+ if (isDisabled) return {};
271
+ switch (variant) {
272
+ case "primary":
273
+ return {
274
+ backgroundColor: "var(--lm-primary-700)",
275
+ borderColor: "var(--lm-primary-700)"
276
+ };
277
+ case "secondary":
278
+ return {
279
+ backgroundColor: "var(--lm-bg-paper)",
280
+ borderColor: "var(--lm-border-default)"
281
+ };
282
+ case "outline":
283
+ return {
284
+ backgroundColor: "var(--lm-primary-100)",
285
+ borderColor: "var(--lm-primary-500)"
286
+ };
287
+ case "ghost":
288
+ return {
289
+ backgroundColor: "var(--lm-bg-elevated)"
290
+ };
291
+ case "danger":
292
+ return {
293
+ backgroundColor: "var(--lm-error-700)",
294
+ borderColor: "var(--lm-error-700)"
295
+ };
296
+ case "success":
297
+ return {
298
+ backgroundColor: "var(--lm-success-700)",
299
+ borderColor: "var(--lm-success-700)"
300
+ };
301
+ case "warning":
302
+ return {
303
+ backgroundColor: "var(--lm-warning-700)",
304
+ borderColor: "var(--lm-warning-700)"
305
+ };
306
+ default:
307
+ return {};
308
+ }
309
+ };
310
+ const getIconStyles = () => {
311
+ if (isDisabled) {
312
+ return { color: "var(--lm-text-disabled)" };
313
+ }
314
+ switch (variant) {
315
+ case "primary":
316
+ case "danger":
317
+ case "success":
318
+ case "warning":
319
+ return { color: "white" };
320
+ case "outline":
321
+ return { color: "var(--lm-primary-600)" };
322
+ default:
323
+ return { color: "var(--lm-text-primary)" };
324
+ }
325
+ };
326
+ const LoadingSpinner = () => /* @__PURE__ */ jsxRuntime.jsxs(
327
+ "svg",
328
+ {
329
+ className: "animate-spin h-4 w-4",
330
+ xmlns: "http://www.w3.org/2000/svg",
331
+ fill: "none",
332
+ viewBox: "0 0 24 24",
333
+ style: getIconStyles(),
334
+ children: [
335
+ /* @__PURE__ */ jsxRuntime.jsx(
336
+ "circle",
337
+ {
338
+ className: "opacity-25",
339
+ cx: "12",
340
+ cy: "12",
341
+ r: "10",
342
+ stroke: "currentColor",
343
+ strokeWidth: "4"
344
+ }
345
+ ),
346
+ /* @__PURE__ */ jsxRuntime.jsx(
347
+ "path",
348
+ {
349
+ className: "opacity-75",
350
+ fill: "currentColor",
351
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
352
+ }
353
+ )
354
+ ]
355
+ }
356
+ );
357
+ return /* @__PURE__ */ jsxRuntime.jsx(
358
+ "button",
359
+ {
360
+ ...props,
361
+ disabled: isDisabled,
362
+ className: baseClassName,
363
+ style: {
364
+ ...getButtonStyles(),
365
+ ...getDisabledStyles()
366
+ },
367
+ onMouseEnter: (e) => {
368
+ var _a;
369
+ if (!isDisabled) Object.assign(e.currentTarget.style, getHoverStyles());
370
+ (_a = props.onMouseEnter) == null ? void 0 : _a.call(props, e);
371
+ },
372
+ onMouseLeave: (e) => {
373
+ var _a;
374
+ if (!isDisabled)
375
+ Object.assign(e.currentTarget.style, {
376
+ ...getButtonStyles(),
377
+ ...getDisabledStyles()
378
+ });
379
+ (_a = props.onMouseLeave) == null ? void 0 : _a.call(props, e);
380
+ },
381
+ onMouseDown: (e) => {
382
+ var _a;
383
+ if (!isDisabled) Object.assign(e.currentTarget.style, getActiveStyles());
384
+ (_a = props.onMouseDown) == null ? void 0 : _a.call(props, e);
385
+ },
386
+ onMouseUp: (e) => {
387
+ var _a;
388
+ if (!isDisabled) Object.assign(e.currentTarget.style, getHoverStyles());
389
+ (_a = props.onMouseUp) == null ? void 0 : _a.call(props, e);
390
+ },
391
+ onFocus: (e) => {
392
+ var _a;
393
+ if (!isDisabled) {
394
+ e.currentTarget.style.borderColor = "var(--lm-primary-400)";
395
+ }
396
+ (_a = props.onFocus) == null ? void 0 : _a.call(props, e);
397
+ },
398
+ onBlur: (e) => {
399
+ var _a;
400
+ if (!isDisabled)
401
+ Object.assign(e.currentTarget.style, {
402
+ ...getButtonStyles(),
403
+ ...getDisabledStyles()
404
+ });
405
+ (_a = props.onBlur) == null ? void 0 : _a.call(props, e);
406
+ },
407
+ children: loading ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
408
+ /* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner, {}),
409
+ loadingText || children
410
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
411
+ leftIcon && /* @__PURE__ */ jsxRuntime.jsx("span", { style: getIconStyles(), children: leftIcon }),
412
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex items-center", children }),
413
+ rightIcon && /* @__PURE__ */ jsxRuntime.jsx("span", { style: getIconStyles(), children: rightIcon })
414
+ ] })
415
+ }
416
+ );
417
+ };
418
+ const LMButton = React.memo(LMButton$1);
419
+ const LMInput = ({
420
+ leftIcon,
421
+ rightElement,
422
+ error = false,
423
+ errorMessage,
424
+ className = "",
425
+ size = "md",
426
+ includeSeconds = false,
427
+ ...props
428
+ }) => {
429
+ const hasLeftIcon = !!leftIcon;
430
+ const hasRightElement = !!rightElement;
431
+ const errorId = React.useRef(
432
+ `lm-input-err-${Math.random().toString(36).slice(2)}`
433
+ ).current;
434
+ const timeInputProps = () => {
435
+ if ((props.type === "datetime-local" || props.type === "time") && includeSeconds) {
436
+ return { step: "1" };
437
+ }
438
+ return {};
439
+ };
440
+ const baseClassName = `
441
+ w-full ${SIZE_INPUT_CONFIG[size].padding} ${SIZE_INPUT_CONFIG[size].height} ${SIZE_INPUT_CONFIG[size].fontSize}
442
+ backdrop-blur-md border rounded-2xl
443
+ focus:ring-2 focus:outline-none transition-all duration-300
444
+ shadow-sm
445
+ ${hasLeftIcon ? "pl-10" : ""}
446
+ ${hasRightElement ? "pr-10" : ""}
447
+ ${className}
448
+ `.trim().replace(/\s+/g, " ");
449
+ const getInputStyles = () => {
450
+ const baseStyles = {
451
+ backgroundColor: "var(--lm-bg-elevated)",
452
+ color: "var(--lm-text-primary)",
453
+ borderColor: error ? "var(--lm-error-300)" : "var(--lm-border-default)",
454
+ boxShadow: "var(--lm-shadow-sm)"
455
+ };
456
+ return {
457
+ ...baseStyles,
458
+ "--tw-ring-color": error ? "var(--lm-error-400)" : "var(--lm-primary-400)",
459
+ "--tw-ring-opacity": "0.3"
460
+ };
461
+ };
462
+ const getDisabledStyles = () => props.disabled ? {
463
+ backgroundColor: "var(--lm-bg-paper)",
464
+ color: "var(--lm-text-disabled)",
465
+ cursor: "not-allowed",
466
+ opacity: 0.6
467
+ } : {};
468
+ const getIconStyles = () => error ? { color: "var(--lm-error-400)" } : { color: "var(--lm-text-secondary)" };
469
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
470
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative group", children: [
471
+ hasLeftIcon && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-y-0 left-0 pl-4 flex items-center pointer-events-none z-10", children: /* @__PURE__ */ jsxRuntime.jsx(
472
+ "div",
473
+ {
474
+ className: "transition-colors duration-200",
475
+ style: getIconStyles(),
476
+ children: leftIcon
477
+ }
478
+ ) }),
479
+ /* @__PURE__ */ jsxRuntime.jsx(
480
+ "input",
481
+ {
482
+ ...props,
483
+ ...timeInputProps(),
484
+ className: baseClassName,
485
+ "aria-invalid": error || void 0,
486
+ "aria-describedby": errorMessage ? errorId : void 0,
487
+ style: {
488
+ ...getInputStyles(),
489
+ ...getDisabledStyles()
490
+ },
491
+ onMouseEnter: (e) => {
492
+ var _a;
493
+ if (!props.disabled && !error) {
494
+ e.currentTarget.style.borderColor = "var(--lm-border-strong)";
495
+ }
496
+ (_a = props.onMouseEnter) == null ? void 0 : _a.call(props, e);
497
+ },
498
+ onMouseLeave: (e) => {
499
+ var _a;
500
+ if (!props.disabled && !error) {
501
+ e.currentTarget.style.borderColor = "var(--lm-border-default)";
502
+ }
503
+ (_a = props.onMouseLeave) == null ? void 0 : _a.call(props, e);
504
+ },
505
+ onFocus: (e) => {
506
+ var _a;
507
+ if (!props.disabled) {
508
+ e.currentTarget.style.borderColor = error ? "var(--lm-error-400)" : "var(--lm-primary-400)";
509
+ }
510
+ (_a = props.onFocus) == null ? void 0 : _a.call(props, e);
511
+ },
512
+ onBlur: (e) => {
513
+ var _a;
514
+ if (!props.disabled) {
515
+ e.currentTarget.style.borderColor = error ? "var(--lm-error-300)" : "var(--lm-border-default)";
516
+ }
517
+ (_a = props.onBlur) == null ? void 0 : _a.call(props, e);
518
+ }
519
+ }
520
+ ),
521
+ hasRightElement && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-y-0 right-0 pr-4 flex items-center z-10", children: rightElement })
522
+ ] }),
523
+ errorMessage && /* @__PURE__ */ jsxRuntime.jsxs(
524
+ "p",
525
+ {
526
+ id: errorId,
527
+ className: "text-xs flex items-center gap-1",
528
+ style: { color: "var(--lm-error-500)" },
529
+ role: "alert",
530
+ "aria-live": "polite",
531
+ children: [
532
+ /* @__PURE__ */ jsxRuntime.jsx(
533
+ "svg",
534
+ {
535
+ className: "w-3 h-3",
536
+ fill: "currentColor",
537
+ viewBox: "0 0 20 20",
538
+ "aria-hidden": "true",
539
+ children: /* @__PURE__ */ jsxRuntime.jsx(
540
+ "path",
541
+ {
542
+ fillRule: "evenodd",
543
+ d: "M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z",
544
+ clipRule: "evenodd"
545
+ }
546
+ )
547
+ }
548
+ ),
549
+ errorMessage
550
+ ]
551
+ }
552
+ )
553
+ ] });
554
+ };
555
+ const sizeConfig$3 = {
556
+ xs: {
557
+ padding: "px-2 py-0.5",
558
+ fontSize: "text-xs",
559
+ dotSize: "w-1.5 h-1.5",
560
+ iconSize: "text-xs"
561
+ },
562
+ sm: {
563
+ padding: "px-3 py-1",
564
+ fontSize: "text-xs",
565
+ dotSize: "w-2 h-2",
566
+ iconSize: "text-xs"
567
+ },
568
+ md: {
569
+ padding: "px-3.5 py-1.5",
570
+ fontSize: "text-sm",
571
+ dotSize: "w-2 h-2",
572
+ iconSize: "text-sm"
573
+ },
574
+ lg: {
575
+ padding: "px-4 py-2",
576
+ fontSize: "text-sm",
577
+ dotSize: "w-2.5 h-2.5",
578
+ iconSize: "text-sm"
579
+ }
580
+ };
581
+ const LMBadge = ({
582
+ children,
583
+ variant = "primary",
584
+ size = "sm",
585
+ className = "",
586
+ dot = false,
587
+ icon
588
+ }) => {
589
+ const getVariantStyles = () => {
590
+ const variantMap = {
591
+ primary: {
592
+ backgroundColor: "var(--lm-primary-100)",
593
+ color: "var(--lm-primary-700)",
594
+ borderColor: "var(--lm-primary-200)"
595
+ },
596
+ secondary: {
597
+ backgroundColor: "var(--lm-gray-100)",
598
+ color: "var(--lm-gray-700)",
599
+ borderColor: "var(--lm-gray-200)"
600
+ },
601
+ success: {
602
+ backgroundColor: "var(--lm-success-100)",
603
+ color: "var(--lm-success-700)",
604
+ borderColor: "var(--lm-success-200)"
605
+ },
606
+ warning: {
607
+ backgroundColor: "var(--lm-warning-100)",
608
+ color: "var(--lm-warning-700)",
609
+ borderColor: "var(--lm-warning-200)"
610
+ },
611
+ error: {
612
+ backgroundColor: "var(--lm-error-100)",
613
+ color: "var(--lm-error-700)",
614
+ borderColor: "var(--lm-error-200)"
615
+ },
616
+ info: {
617
+ backgroundColor: "var(--lm-info-100)",
618
+ color: "var(--lm-info-700)",
619
+ borderColor: "var(--lm-info-200)"
620
+ },
621
+ neutral: {
622
+ backgroundColor: "var(--lm-bg-elevated)",
623
+ color: "var(--lm-text-secondary)",
624
+ borderColor: "var(--lm-border-default)"
625
+ }
626
+ };
627
+ return variantMap[variant];
628
+ };
629
+ const getDotColor = () => {
630
+ const dotColorMap = {
631
+ primary: "var(--lm-primary-500)",
632
+ secondary: "var(--lm-gray-500)",
633
+ success: "var(--lm-success-500)",
634
+ warning: "var(--lm-warning-500)",
635
+ error: "var(--lm-error-500)",
636
+ info: "var(--lm-info-500)",
637
+ neutral: "var(--lm-text-disabled)"
638
+ };
639
+ return dotColorMap[variant];
640
+ };
641
+ const currentSize = sizeConfig$3[size];
642
+ return /* @__PURE__ */ jsxRuntime.jsxs(
643
+ "span",
644
+ {
645
+ className: `inline-flex items-center justify-center ${currentSize.padding} ${currentSize.fontSize} rounded-full border font-medium transition-all duration-200 ${className}`,
646
+ style: getVariantStyles(),
647
+ children: [
648
+ dot && /* @__PURE__ */ jsxRuntime.jsx(
649
+ "span",
650
+ {
651
+ className: `${currentSize.dotSize} rounded-full mr-1.5 flex-shrink-0`,
652
+ style: { backgroundColor: getDotColor() }
653
+ }
654
+ ),
655
+ icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${currentSize.iconSize} mr-1.5 flex-shrink-0`, children: icon }),
656
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children })
657
+ ]
658
+ }
659
+ );
660
+ };
661
+ const LMTooltip = ({
662
+ content,
663
+ children,
664
+ placement = "top",
665
+ maxWidth,
666
+ size = "sm"
667
+ }) => {
668
+ const [visible, setVisible] = React.useState(false);
669
+ const [position, setPosition] = React.useState({ top: 0, left: 0 });
670
+ const triggerRef = React.useRef(null);
671
+ const tooltipRef = React.useRef(null);
672
+ const resolvedSize = clampComponentSize(size, COMPONENT_SIZE_ORDER);
673
+ const effectiveMaxWidth = maxWidth ?? SIZE_TOOLTIP_CONFIG[resolvedSize].maxWidth;
674
+ React.useEffect(() => {
675
+ if (visible && triggerRef.current && tooltipRef.current) {
676
+ const triggerRect = triggerRef.current.getBoundingClientRect();
677
+ const tooltipRect = tooltipRef.current.getBoundingClientRect();
678
+ let top = 0;
679
+ let left = 0;
680
+ switch (placement) {
681
+ case "top":
682
+ top = triggerRect.top - tooltipRect.height - 8;
683
+ left = triggerRect.left + triggerRect.width / 2 - tooltipRect.width / 2;
684
+ break;
685
+ case "bottom":
686
+ top = triggerRect.bottom + 8;
687
+ left = triggerRect.left + triggerRect.width / 2 - tooltipRect.width / 2;
688
+ break;
689
+ case "left":
690
+ top = triggerRect.top + triggerRect.height / 2 - tooltipRect.height / 2;
691
+ left = triggerRect.left - tooltipRect.width - 8;
692
+ break;
693
+ case "right":
694
+ top = triggerRect.top + triggerRect.height / 2 - tooltipRect.height / 2;
695
+ left = triggerRect.right + 8;
696
+ break;
697
+ }
698
+ const padding = 8;
699
+ if (left < padding) left = padding;
700
+ if (left + tooltipRect.width > window.innerWidth - padding) {
701
+ left = window.innerWidth - tooltipRect.width - padding;
702
+ }
703
+ if (top < padding) top = padding;
704
+ if (top + tooltipRect.height > window.innerHeight - padding) {
705
+ top = window.innerHeight - tooltipRect.height - padding;
706
+ }
707
+ setPosition({ top, left });
708
+ }
709
+ }, [visible, placement]);
710
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
711
+ /* @__PURE__ */ jsxRuntime.jsx(
712
+ "div",
713
+ {
714
+ ref: triggerRef,
715
+ onMouseEnter: () => setVisible(true),
716
+ onMouseLeave: () => setVisible(false),
717
+ className: "inline-block",
718
+ children
719
+ }
720
+ ),
721
+ visible && /* @__PURE__ */ jsxRuntime.jsx(
722
+ "div",
723
+ {
724
+ ref: tooltipRef,
725
+ className: `fixed z-50 ${SIZE_TOOLTIP_CONFIG[resolvedSize].paddingClass} ${SIZE_TOOLTIP_CONFIG[resolvedSize].textClass} rounded-lg shadow-lg pointer-events-none`,
726
+ style: {
727
+ top: `${position.top}px`,
728
+ left: `${position.left}px`,
729
+ maxWidth: `${effectiveMaxWidth}px`,
730
+ backgroundColor: "var(--lm-bg-elevated)",
731
+ borderColor: "var(--lm-border-default)",
732
+ color: "var(--lm-text-primary)",
733
+ border: "1px solid"
734
+ },
735
+ children: content
736
+ }
737
+ )
738
+ ] });
739
+ };
740
+ const MODAL_FOOTER_SIZE_MAP = {
741
+ xs: "xs",
742
+ sm: "xs",
743
+ md: "sm",
744
+ lg: "md",
745
+ xl: "md",
746
+ "2xl": "lg"
747
+ };
748
+ const LMModal = ({
749
+ visible,
750
+ title,
751
+ children,
752
+ footer,
753
+ onClose,
754
+ onOk,
755
+ onCancel,
756
+ okText = "Confirm",
757
+ cancelText = "Cancel",
758
+ showOk = true,
759
+ showCancel = true,
760
+ okLoading = false,
761
+ cancelLoading = false,
762
+ mask = true,
763
+ maskClosable = false,
764
+ closable = true,
765
+ closeIcon,
766
+ headerIcon,
767
+ width,
768
+ height,
769
+ size = "md",
770
+ className = "",
771
+ style,
772
+ centered = true,
773
+ fullscreen = false,
774
+ animationDuration = 300,
775
+ animation = true
776
+ }) => {
777
+ const modalRef = React.useRef(null);
778
+ const backdropRef = React.useRef(null);
779
+ const resolvedSize = clampComponentSize(size, COMPONENT_SIZE_ORDER);
780
+ const footerButtonSize = MODAL_FOOTER_SIZE_MAP[resolvedSize];
781
+ const getModalStyles = () => {
782
+ const baseStyles = {
783
+ backgroundColor: "var(--lm-bg-elevated)",
784
+ color: "var(--lm-text-primary)",
785
+ borderColor: "var(--lm-border-default)",
786
+ boxShadow: "var(--lm-shadow-xl)",
787
+ borderRadius: "1rem",
788
+ border: "1px solid var(--lm-border-default)",
789
+ backdropFilter: "blur(10px)",
790
+ ...style
791
+ };
792
+ if (fullscreen) {
793
+ baseStyles.width = "100vw";
794
+ baseStyles.height = "100vh";
795
+ baseStyles.maxWidth = "100vw";
796
+ baseStyles.maxHeight = "100vh";
797
+ baseStyles.borderRadius = "0";
798
+ } else {
799
+ baseStyles.width = width ? typeof width === "number" ? `${width}px` : width : SIZE_MODAL_CONFIG[resolvedSize].width;
800
+ baseStyles.maxWidth = SIZE_MODAL_CONFIG[resolvedSize].maxWidth;
801
+ if (height) {
802
+ baseStyles.height = typeof height === "number" ? `${height}px` : height;
803
+ }
804
+ }
805
+ return baseStyles;
806
+ };
807
+ const getBackdropStyles = () => mask ? { backgroundColor: "rgba(0, 0, 0, 0.5)", backdropFilter: "blur(4px)" } : { backgroundColor: "transparent", backdropFilter: "none" };
808
+ const handleOk = () => onOk ? onOk() : onClose == null ? void 0 : onClose();
809
+ const handleCancel = React.useCallback(() => {
810
+ if (onCancel) onCancel();
811
+ else onClose == null ? void 0 : onClose();
812
+ }, [onCancel, onClose]);
813
+ const handleBackdropClick = (e) => {
814
+ if (maskClosable && e.target === backdropRef.current) handleCancel();
815
+ };
816
+ React.useEffect(() => {
817
+ const keyHandler = (e) => {
818
+ if (visible && e.key === "Escape") handleCancel();
819
+ };
820
+ if (visible) {
821
+ document.addEventListener("keydown", keyHandler);
822
+ document.body.style.overflow = "hidden";
823
+ }
824
+ return () => {
825
+ document.removeEventListener("keydown", keyHandler);
826
+ if (visible) document.body.style.overflow = "";
827
+ };
828
+ }, [visible, handleCancel]);
829
+ const CloseIcon = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) });
830
+ const WindowIcon = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 6h16M4 12h16M4 18h16" }) });
831
+ const defaultFooter = /* @__PURE__ */ jsxRuntime.jsxs(
832
+ "div",
833
+ {
834
+ className: "flex items-center justify-end gap-3 px-6 py-4 border-t",
835
+ style: { borderColor: "var(--lm-border-default)" },
836
+ children: [
837
+ showCancel && /* @__PURE__ */ jsxRuntime.jsx(
838
+ LMButton,
839
+ {
840
+ variant: "secondary",
841
+ size: footerButtonSize,
842
+ onClick: handleCancel,
843
+ disabled: cancelLoading,
844
+ loading: cancelLoading,
845
+ children: cancelText
846
+ }
847
+ ),
848
+ showOk && /* @__PURE__ */ jsxRuntime.jsx(
849
+ LMButton,
850
+ {
851
+ variant: "primary",
852
+ size: footerButtonSize,
853
+ onClick: handleOk,
854
+ disabled: okLoading,
855
+ loading: okLoading,
856
+ children: okText
857
+ }
858
+ )
859
+ ]
860
+ }
861
+ );
862
+ const getAnimationClasses = () => {
863
+ if (!animation) return "";
864
+ const ms = animationDuration;
865
+ const durationClass = ms <= 150 ? "duration-150" : ms <= 200 ? "duration-200" : ms <= 300 ? "duration-300" : ms <= 500 ? "duration-500" : ms <= 700 ? "duration-700" : "duration-1000";
866
+ return `transition-all ${durationClass} ease-in-out`;
867
+ };
868
+ if (!visible) return null;
869
+ const modalContent = /* @__PURE__ */ jsxRuntime.jsx(
870
+ "div",
871
+ {
872
+ ref: backdropRef,
873
+ className: `fixed inset-0 z-50 flex ${centered ? "items-center" : "items-start pt-20"} justify-center ${getAnimationClasses()}`,
874
+ style: getBackdropStyles(),
875
+ onClick: handleBackdropClick,
876
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
877
+ "div",
878
+ {
879
+ ref: modalRef,
880
+ className: `relative ${getAnimationClasses()} ${className}`,
881
+ style: getModalStyles(),
882
+ onClick: (e) => e.stopPropagation(),
883
+ children: [
884
+ (title || closable) && /* @__PURE__ */ jsxRuntime.jsxs(
885
+ "div",
886
+ {
887
+ className: "flex items-center justify-between p-6 pb-4 border-b",
888
+ style: { borderColor: "var(--lm-border-default)" },
889
+ children: [
890
+ title && /* @__PURE__ */ jsxRuntime.jsxs(
891
+ "h3",
892
+ {
893
+ className: `font-bold flex items-center gap-2 ${SIZE_HEADING_CLASSES[resolvedSize]}`,
894
+ style: { color: "var(--lm-text-primary)" },
895
+ children: [
896
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--lm-text-secondary)" }, children: headerIcon || /* @__PURE__ */ jsxRuntime.jsx(WindowIcon, {}) }),
897
+ title
898
+ ]
899
+ }
900
+ ),
901
+ closable && /* @__PURE__ */ jsxRuntime.jsx(
902
+ LMButton,
903
+ {
904
+ variant: "ghost",
905
+ size: "xs",
906
+ onClick: handleCancel,
907
+ leftIcon: closeIcon || /* @__PURE__ */ jsxRuntime.jsx(CloseIcon, {}),
908
+ className: "w-8 h-8 p-0",
909
+ "aria-label": "Close dialog",
910
+ title: "Close",
911
+ style: {
912
+ borderRadius: "0.5rem",
913
+ backgroundColor: "var(--lm-bg-paper)",
914
+ borderColor: "var(--lm-border-default)",
915
+ color: "var(--lm-text-secondary)"
916
+ }
917
+ }
918
+ )
919
+ ]
920
+ }
921
+ ),
922
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6", children }),
923
+ footer !== void 0 ? footer : showOk || showCancel ? defaultFooter : null
924
+ ]
925
+ }
926
+ )
927
+ }
928
+ );
929
+ return reactDom.createPortal(modalContent, document.body);
930
+ };
931
+ const LMModal_default = React.memo(LMModal);
932
+ const sizeConfig$2 = {
933
+ xs: {
934
+ container: "p-2 gap-2",
935
+ label: "text-xs",
936
+ description: "text-xs mt-0.5",
937
+ errorMessage: "text-xs"
938
+ },
939
+ sm: {
940
+ container: "p-3 gap-2.5",
941
+ label: "text-sm",
942
+ description: "text-xs mt-1",
943
+ errorMessage: "text-xs"
944
+ },
945
+ md: {
946
+ container: "p-4 gap-3",
947
+ label: "text-base",
948
+ description: "text-sm mt-1",
949
+ errorMessage: "text-xs"
950
+ },
951
+ lg: {
952
+ container: "p-5 gap-4",
953
+ label: "text-lg",
954
+ description: "text-base mt-1.5",
955
+ errorMessage: "text-sm"
956
+ },
957
+ xl: {
958
+ container: "p-6 gap-4",
959
+ label: "text-xl",
960
+ description: "text-lg mt-2",
961
+ errorMessage: "text-sm"
962
+ },
963
+ "2xl": {
964
+ container: "p-8 gap-5",
965
+ label: "text-2xl",
966
+ description: "text-xl mt-2.5",
967
+ errorMessage: "text-base"
968
+ }
969
+ };
970
+ const LMCheckbox = ({
971
+ label,
972
+ description,
973
+ error = false,
974
+ errorMessage,
975
+ size = "md",
976
+ className = "",
977
+ ...props
978
+ }) => {
979
+ const currentSize = sizeConfig$2[size];
980
+ const checkboxSizeClass = SIZE_ICON_CONFIG[size];
981
+ const getCheckboxStyles = () => {
982
+ const baseStyles = {
983
+ backgroundColor: "var(--lm-bg-elevated)",
984
+ borderColor: error ? "var(--lm-error-300)" : "var(--lm-border-default)",
985
+ color: "var(--lm-primary-500)"
986
+ };
987
+ return {
988
+ ...baseStyles,
989
+ "--tw-ring-color": error ? "var(--lm-error-400)" : "var(--lm-primary-400)",
990
+ "--tw-ring-opacity": "0.3"
991
+ };
992
+ };
993
+ const getDisabledStyles = () => {
994
+ if (props.disabled) {
995
+ return {
996
+ backgroundColor: "var(--lm-bg-paper)",
997
+ borderColor: "var(--lm-border-light)",
998
+ color: "var(--lm-text-disabled)",
999
+ cursor: "not-allowed",
1000
+ opacity: 0.6
1001
+ };
1002
+ }
1003
+ return {};
1004
+ };
1005
+ const getContainerStyles = () => ({
1006
+ backgroundColor: error ? "var(--lm-error-50)" : "var(--lm-bg-paper)"
1007
+ });
1008
+ const getHoverContainerStyles = () => ({
1009
+ backgroundColor: error ? "var(--lm-error-100)" : "var(--lm-bg-elevated)"
1010
+ });
1011
+ const getLabelStyles = () => {
1012
+ if (error)
1013
+ return { color: "var(--lm-error-700)" };
1014
+ if (props.disabled)
1015
+ return {
1016
+ color: "var(--lm-text-disabled)",
1017
+ cursor: "not-allowed"
1018
+ };
1019
+ return {
1020
+ color: "var(--lm-text-primary)",
1021
+ cursor: "pointer"
1022
+ };
1023
+ };
1024
+ const getDescriptionStyles = () => error ? { color: "var(--lm-error-600)" } : { color: "var(--lm-text-secondary)" };
1025
+ const checkboxClassName = `
1026
+ ${checkboxSizeClass} border-2 rounded-md
1027
+ focus:ring-2 focus:ring-offset-0
1028
+ transition-all duration-200
1029
+ ${className}
1030
+ `.trim().replace(/\s+/g, " ");
1031
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1032
+ /* @__PURE__ */ jsxRuntime.jsxs(
1033
+ "label",
1034
+ {
1035
+ className: `flex items-center rounded-2xl transition-colors duration-200 ${currentSize.container} ${props.disabled ? "" : "cursor-pointer"}`,
1036
+ style: getContainerStyles(),
1037
+ onMouseEnter: (e) => {
1038
+ if (!props.disabled) {
1039
+ Object.assign(e.currentTarget.style, getHoverContainerStyles());
1040
+ }
1041
+ },
1042
+ onMouseLeave: (e) => {
1043
+ if (!props.disabled) {
1044
+ Object.assign(e.currentTarget.style, getContainerStyles());
1045
+ }
1046
+ },
1047
+ children: [
1048
+ /* @__PURE__ */ jsxRuntime.jsx(
1049
+ "input",
1050
+ {
1051
+ type: "checkbox",
1052
+ ...props,
1053
+ className: checkboxClassName,
1054
+ style: {
1055
+ ...getCheckboxStyles(),
1056
+ ...getDisabledStyles()
1057
+ },
1058
+ onFocus: (e) => {
1059
+ var _a;
1060
+ if (!props.disabled) {
1061
+ e.currentTarget.style.borderColor = error ? "var(--lm-error-400)" : "var(--lm-primary-400)";
1062
+ }
1063
+ (_a = props.onFocus) == null ? void 0 : _a.call(props, e);
1064
+ },
1065
+ onBlur: (e) => {
1066
+ var _a;
1067
+ if (!props.disabled) {
1068
+ e.currentTarget.style.borderColor = error ? "var(--lm-error-300)" : "var(--lm-border-default)";
1069
+ }
1070
+ (_a = props.onBlur) == null ? void 0 : _a.call(props, e);
1071
+ }
1072
+ }
1073
+ ),
1074
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1", children: [
1075
+ /* @__PURE__ */ jsxRuntime.jsx(
1076
+ "span",
1077
+ {
1078
+ className: `font-medium leading-tight transition-colors duration-200 ${currentSize.label}`,
1079
+ style: getLabelStyles(),
1080
+ children: label
1081
+ }
1082
+ ),
1083
+ description && /* @__PURE__ */ jsxRuntime.jsx(
1084
+ "p",
1085
+ {
1086
+ className: currentSize.description,
1087
+ style: getDescriptionStyles(),
1088
+ children: description
1089
+ }
1090
+ )
1091
+ ] })
1092
+ ]
1093
+ }
1094
+ ),
1095
+ errorMessage && /* @__PURE__ */ jsxRuntime.jsxs(
1096
+ "p",
1097
+ {
1098
+ className: `flex items-center gap-1 ${currentSize.errorMessage}`,
1099
+ style: { color: "var(--lm-error-500)" },
1100
+ children: [
1101
+ /* @__PURE__ */ jsxRuntime.jsx(
1102
+ "svg",
1103
+ {
1104
+ className: "w-3 h-3",
1105
+ fill: "currentColor",
1106
+ viewBox: "0 0 20 20",
1107
+ "aria-hidden": "true",
1108
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1109
+ "path",
1110
+ {
1111
+ fillRule: "evenodd",
1112
+ d: "M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z",
1113
+ clipRule: "evenodd"
1114
+ }
1115
+ )
1116
+ }
1117
+ ),
1118
+ errorMessage
1119
+ ]
1120
+ }
1121
+ )
1122
+ ] });
1123
+ };
1124
+ const LMRadio = ({
1125
+ label,
1126
+ description,
1127
+ error = false,
1128
+ errorMessage,
1129
+ size = "md",
1130
+ className = "",
1131
+ id,
1132
+ ...props
1133
+ }) => {
1134
+ const autoId = React.useId();
1135
+ const controlId = id ?? `lm-radio-${autoId}`;
1136
+ const errId = `lm-radio-err-${autoId}`;
1137
+ const radioSizeClass = SIZE_ICON_CONFIG[size];
1138
+ const getRadioStyles = () => {
1139
+ const baseStyles = {
1140
+ backgroundColor: "var(--lm-bg-elevated)",
1141
+ borderColor: error ? "var(--lm-error-300)" : "var(--lm-border-default)",
1142
+ color: "var(--lm-primary-500)"
1143
+ };
1144
+ return {
1145
+ ...baseStyles,
1146
+ "--tw-ring-color": error ? "var(--lm-error-400)" : "var(--lm-primary-400)",
1147
+ "--tw-ring-opacity": "0.3"
1148
+ };
1149
+ };
1150
+ const getDisabledStyles = () => {
1151
+ if (props.disabled) {
1152
+ return {
1153
+ backgroundColor: "var(--lm-bg-paper)",
1154
+ borderColor: "var(--lm-border-light)",
1155
+ color: "var(--lm-text-disabled)",
1156
+ cursor: "not-allowed",
1157
+ opacity: 0.6
1158
+ };
1159
+ }
1160
+ return {};
1161
+ };
1162
+ const getContainerStyles = () => {
1163
+ const base = { backgroundColor: "var(--lm-bg-paper)" };
1164
+ return error ? { ...base, backgroundColor: "var(--lm-error-50)" } : base;
1165
+ };
1166
+ const getHoverContainerStyles = () => error ? { backgroundColor: "var(--lm-error-100)" } : { backgroundColor: "var(--lm-bg-elevated)" };
1167
+ const getLabelStyles = () => {
1168
+ if (error) return { color: "var(--lm-error-700)" };
1169
+ if (props.disabled)
1170
+ return { color: "var(--lm-text-disabled)", cursor: "not-allowed" };
1171
+ return { color: "var(--lm-text-primary)", cursor: "pointer" };
1172
+ };
1173
+ const getDescriptionStyles = () => error ? { color: "var(--lm-error-600)" } : { color: "var(--lm-text-secondary)" };
1174
+ const radioClassName = `
1175
+ ${radioSizeClass} border-2 rounded-full
1176
+ focus:ring-2 focus:ring-offset-0
1177
+ transition-all duration-200
1178
+ ${className}
1179
+ `.trim().replace(/\s+/g, " ");
1180
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1181
+ /* @__PURE__ */ jsxRuntime.jsxs(
1182
+ "div",
1183
+ {
1184
+ className: "flex items-start gap-3 p-4 rounded-2xl transition-colors duration-200",
1185
+ style: getContainerStyles(),
1186
+ onMouseEnter: (e) => {
1187
+ if (!props.disabled)
1188
+ Object.assign(e.currentTarget.style, getHoverContainerStyles());
1189
+ },
1190
+ onMouseLeave: (e) => {
1191
+ if (!props.disabled)
1192
+ Object.assign(e.currentTarget.style, getContainerStyles());
1193
+ },
1194
+ children: [
1195
+ /* @__PURE__ */ jsxRuntime.jsx(
1196
+ "input",
1197
+ {
1198
+ type: "radio",
1199
+ id: controlId,
1200
+ ...props,
1201
+ className: radioClassName,
1202
+ "aria-invalid": error || void 0,
1203
+ "aria-describedby": errorMessage ? errId : void 0,
1204
+ style: { ...getRadioStyles(), ...getDisabledStyles() },
1205
+ onFocus: (e) => {
1206
+ var _a;
1207
+ if (!props.disabled) {
1208
+ e.currentTarget.style.borderColor = error ? "var(--lm-error-400)" : "var(--lm-primary-400)";
1209
+ }
1210
+ (_a = props.onFocus) == null ? void 0 : _a.call(props, e);
1211
+ },
1212
+ onBlur: (e) => {
1213
+ var _a;
1214
+ if (!props.disabled) {
1215
+ e.currentTarget.style.borderColor = error ? "var(--lm-error-300)" : "var(--lm-border-default)";
1216
+ }
1217
+ (_a = props.onBlur) == null ? void 0 : _a.call(props, e);
1218
+ }
1219
+ }
1220
+ ),
1221
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1", children: [
1222
+ /* @__PURE__ */ jsxRuntime.jsx(
1223
+ "label",
1224
+ {
1225
+ htmlFor: controlId,
1226
+ className: "text-base font-medium transition-colors duration-200",
1227
+ style: getLabelStyles(),
1228
+ children: label
1229
+ }
1230
+ ),
1231
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm mt-1", style: getDescriptionStyles(), children: description })
1232
+ ] })
1233
+ ]
1234
+ }
1235
+ ),
1236
+ errorMessage && /* @__PURE__ */ jsxRuntime.jsxs(
1237
+ "p",
1238
+ {
1239
+ id: errId,
1240
+ className: "text-xs flex items-center gap-1",
1241
+ style: { color: "var(--lm-error-500)" },
1242
+ role: "alert",
1243
+ "aria-live": "polite",
1244
+ children: [
1245
+ /* @__PURE__ */ jsxRuntime.jsx(
1246
+ "svg",
1247
+ {
1248
+ className: "w-3 h-3",
1249
+ fill: "currentColor",
1250
+ viewBox: "0 0 20 20",
1251
+ "aria-hidden": "true",
1252
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1253
+ "path",
1254
+ {
1255
+ fillRule: "evenodd",
1256
+ d: "M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z",
1257
+ clipRule: "evenodd"
1258
+ }
1259
+ )
1260
+ }
1261
+ ),
1262
+ errorMessage
1263
+ ]
1264
+ }
1265
+ )
1266
+ ] });
1267
+ };
1268
+ const sizeConfig$1 = {
1269
+ xs: {
1270
+ container: "p-2 gap-2",
1271
+ label: "text-xs",
1272
+ description: "text-xs mt-0.5",
1273
+ errorMessage: "text-xs",
1274
+ track: "w-7 h-4",
1275
+ thumb: "w-2.5 h-2.5",
1276
+ translate: "translate-x-3"
1277
+ },
1278
+ sm: {
1279
+ container: "p-3 gap-2.5",
1280
+ label: "text-sm",
1281
+ description: "text-xs mt-1",
1282
+ errorMessage: "text-xs",
1283
+ track: "w-9 h-5",
1284
+ thumb: "w-3 h-3",
1285
+ translate: "translate-x-4"
1286
+ },
1287
+ md: {
1288
+ container: "p-4 gap-3",
1289
+ label: "text-base",
1290
+ description: "text-sm mt-1",
1291
+ errorMessage: "text-xs",
1292
+ track: "w-11 h-6",
1293
+ thumb: "w-4 h-4",
1294
+ translate: "translate-x-5"
1295
+ },
1296
+ lg: {
1297
+ container: "p-5 gap-4",
1298
+ label: "text-lg",
1299
+ description: "text-base mt-1.5",
1300
+ errorMessage: "text-sm",
1301
+ track: "w-14 h-7",
1302
+ thumb: "w-5 h-5",
1303
+ translate: "translate-x-7"
1304
+ },
1305
+ xl: {
1306
+ container: "p-6 gap-4",
1307
+ label: "text-xl",
1308
+ description: "text-lg mt-2",
1309
+ errorMessage: "text-sm",
1310
+ track: "w-16 h-8",
1311
+ thumb: "w-6 h-6",
1312
+ translate: "translate-x-8"
1313
+ },
1314
+ "2xl": {
1315
+ container: "p-8 gap-5",
1316
+ label: "text-2xl",
1317
+ description: "text-xl mt-2.5",
1318
+ errorMessage: "text-base",
1319
+ track: "w-20 h-10",
1320
+ thumb: "w-8 h-8",
1321
+ translate: "translate-x-10"
1322
+ }
1323
+ };
1324
+ const LMSwitch = ({
1325
+ label,
1326
+ description,
1327
+ error = false,
1328
+ errorMessage,
1329
+ size = "md",
1330
+ id,
1331
+ ...props
1332
+ }) => {
1333
+ const autoId = React.useId();
1334
+ const controlId = id ?? `lm-switch-${autoId}`;
1335
+ const errId = `lm-switch-err-${autoId}`;
1336
+ const currentSize = sizeConfig$1[size];
1337
+ const getTrackBg = () => {
1338
+ if (props.disabled) return "var(--lm-bg-paper)";
1339
+ if (error && !props.checked) return "var(--lm-error-300)";
1340
+ if (props.checked) return "var(--lm-primary-500)";
1341
+ return "var(--lm-border-default)";
1342
+ };
1343
+ const getDisabledStyles = () => {
1344
+ if (props.disabled) {
1345
+ return {
1346
+ opacity: 0.6,
1347
+ cursor: "not-allowed"
1348
+ };
1349
+ }
1350
+ return {};
1351
+ };
1352
+ const getContainerStyles = () => {
1353
+ const base = { backgroundColor: "var(--lm-bg-paper)" };
1354
+ return error ? { ...base, backgroundColor: "var(--lm-error-50)" } : base;
1355
+ };
1356
+ const getHoverContainerStyles = () => error ? { backgroundColor: "var(--lm-error-100)" } : { backgroundColor: "var(--lm-bg-elevated)" };
1357
+ const getLabelStyles = () => {
1358
+ if (error) return { color: "var(--lm-error-700)" };
1359
+ if (props.disabled)
1360
+ return { color: "var(--lm-text-disabled)", cursor: "not-allowed" };
1361
+ return { color: "var(--lm-text-primary)", cursor: "pointer" };
1362
+ };
1363
+ const getDescriptionStyles = () => error ? { color: "var(--lm-error-600)" } : { color: "var(--lm-text-secondary)" };
1364
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1365
+ /* @__PURE__ */ jsxRuntime.jsxs(
1366
+ "label",
1367
+ {
1368
+ htmlFor: controlId,
1369
+ className: `flex items-start rounded-2xl transition-colors duration-200 ${currentSize.container} ${props.disabled ? "" : "cursor-pointer"}`,
1370
+ style: getContainerStyles(),
1371
+ onMouseEnter: (e) => {
1372
+ if (!props.disabled) {
1373
+ Object.assign(e.currentTarget.style, getHoverContainerStyles());
1374
+ }
1375
+ },
1376
+ onMouseLeave: (e) => {
1377
+ if (!props.disabled) {
1378
+ Object.assign(e.currentTarget.style, getContainerStyles());
1379
+ }
1380
+ },
1381
+ children: [
1382
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-shrink-0 relative", children: [
1383
+ /* @__PURE__ */ jsxRuntime.jsx(
1384
+ "input",
1385
+ {
1386
+ type: "checkbox",
1387
+ id: controlId,
1388
+ ...props,
1389
+ className: "sr-only peer",
1390
+ "aria-invalid": error || void 0,
1391
+ "aria-describedby": errorMessage ? errId : void 0,
1392
+ style: getDisabledStyles()
1393
+ }
1394
+ ),
1395
+ /* @__PURE__ */ jsxRuntime.jsx(
1396
+ "div",
1397
+ {
1398
+ className: `${currentSize.track} rounded-full transition-all duration-300 relative`,
1399
+ style: {
1400
+ backgroundColor: getTrackBg(),
1401
+ ...getDisabledStyles()
1402
+ },
1403
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1404
+ "div",
1405
+ {
1406
+ className: `${currentSize.thumb} absolute left-1 top-1/2 -translate-y-1/2 rounded-full transition-transform duration-300 ${props.checked ? currentSize.translate : "translate-x-0"}`,
1407
+ style: {
1408
+ backgroundColor: "var(--lm-bg-elevated)",
1409
+ boxShadow: "0 1px 3px rgba(0, 0, 0, 0.1)"
1410
+ }
1411
+ }
1412
+ )
1413
+ }
1414
+ )
1415
+ ] }),
1416
+ (label || description) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1", children: [
1417
+ label && /* @__PURE__ */ jsxRuntime.jsx(
1418
+ "span",
1419
+ {
1420
+ className: `font-medium leading-tight transition-colors duration-200 ${currentSize.label}`,
1421
+ style: getLabelStyles(),
1422
+ children: label
1423
+ }
1424
+ ),
1425
+ description && /* @__PURE__ */ jsxRuntime.jsx(
1426
+ "p",
1427
+ {
1428
+ className: currentSize.description,
1429
+ style: getDescriptionStyles(),
1430
+ children: description
1431
+ }
1432
+ )
1433
+ ] })
1434
+ ]
1435
+ }
1436
+ ),
1437
+ errorMessage && /* @__PURE__ */ jsxRuntime.jsxs(
1438
+ "p",
1439
+ {
1440
+ id: errId,
1441
+ className: `flex items-center gap-1 mt-2 ${currentSize.errorMessage}`,
1442
+ style: { color: "var(--lm-error-500)" },
1443
+ role: "alert",
1444
+ "aria-live": "polite",
1445
+ children: [
1446
+ /* @__PURE__ */ jsxRuntime.jsx(
1447
+ "svg",
1448
+ {
1449
+ className: "w-3 h-3",
1450
+ fill: "currentColor",
1451
+ viewBox: "0 0 20 20",
1452
+ "aria-hidden": "true",
1453
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1454
+ "path",
1455
+ {
1456
+ fillRule: "evenodd",
1457
+ d: "M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z",
1458
+ clipRule: "evenodd"
1459
+ }
1460
+ )
1461
+ }
1462
+ ),
1463
+ errorMessage
1464
+ ]
1465
+ }
1466
+ )
1467
+ ] });
1468
+ };
1469
+ const sizeConfig = {
1470
+ xs: {
1471
+ minHeight: "min-h-[60px]",
1472
+ fontSize: "text-xs",
1473
+ padding: "px-3 py-2"
1474
+ },
1475
+ sm: {
1476
+ minHeight: "min-h-[80px]",
1477
+ fontSize: "text-sm",
1478
+ padding: "px-3 py-2"
1479
+ },
1480
+ md: {
1481
+ minHeight: "min-h-[100px]",
1482
+ fontSize: "text-sm",
1483
+ padding: "px-4 py-2.5"
1484
+ },
1485
+ lg: {
1486
+ minHeight: "min-h-[120px]",
1487
+ fontSize: "text-base",
1488
+ padding: "px-4 py-3"
1489
+ },
1490
+ xl: {
1491
+ minHeight: "min-h-[140px]",
1492
+ fontSize: "text-base",
1493
+ padding: "px-5 py-3.5"
1494
+ },
1495
+ "2xl": {
1496
+ minHeight: "min-h-[160px]",
1497
+ fontSize: "text-lg",
1498
+ padding: "px-6 py-4"
1499
+ }
1500
+ };
1501
+ const LMTextarea = ({
1502
+ error = false,
1503
+ errorMessage,
1504
+ className = "",
1505
+ size = "md",
1506
+ ...props
1507
+ }) => {
1508
+ const baseClassName = `
1509
+ w-full ${sizeConfig[size].padding} ${sizeConfig[size].fontSize} backdrop-blur-md border rounded-2xl
1510
+ focus:ring-2 focus:outline-none transition-all duration-300
1511
+ shadow-sm resize-none ${className.includes("h-full") ? "" : sizeConfig[size].minHeight}
1512
+ ${className}
1513
+ `.trim().replace(/\s+/g, " ");
1514
+ const getTextareaStyles = () => {
1515
+ const baseStyles = {
1516
+ backgroundColor: "var(--lm-bg-elevated)",
1517
+ color: "var(--lm-text-primary)",
1518
+ borderColor: error ? "var(--lm-error-300)" : "var(--lm-border-default)",
1519
+ boxShadow: "var(--lm-shadow-sm)"
1520
+ };
1521
+ return {
1522
+ ...baseStyles,
1523
+ "--tw-ring-color": error ? "var(--lm-error-400)" : "var(--lm-primary-400)",
1524
+ "--tw-ring-opacity": "0.3"
1525
+ };
1526
+ };
1527
+ const getDisabledStyles = () => {
1528
+ if (props.disabled) {
1529
+ return {
1530
+ backgroundColor: "var(--lm-bg-paper)",
1531
+ color: "var(--lm-text-disabled)",
1532
+ cursor: "not-allowed",
1533
+ opacity: 0.6
1534
+ };
1535
+ }
1536
+ return {};
1537
+ };
1538
+ const isFullHeight = className.includes("h-full");
1539
+ const containerClassName = isFullHeight ? "h-full flex flex-col" : "space-y-2";
1540
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: containerClassName, children: [
1541
+ /* @__PURE__ */ jsxRuntime.jsx(
1542
+ "textarea",
1543
+ {
1544
+ ...props,
1545
+ className: baseClassName,
1546
+ style: {
1547
+ ...getTextareaStyles(),
1548
+ ...getDisabledStyles()
1549
+ },
1550
+ onMouseEnter: (e) => {
1551
+ var _a;
1552
+ if (!props.disabled && !error) {
1553
+ e.currentTarget.style.borderColor = "var(--lm-border-strong)";
1554
+ }
1555
+ (_a = props.onMouseEnter) == null ? void 0 : _a.call(props, e);
1556
+ },
1557
+ onMouseLeave: (e) => {
1558
+ var _a;
1559
+ if (!props.disabled && !error) {
1560
+ e.currentTarget.style.borderColor = "var(--lm-border-default)";
1561
+ }
1562
+ (_a = props.onMouseLeave) == null ? void 0 : _a.call(props, e);
1563
+ },
1564
+ onFocus: (e) => {
1565
+ var _a;
1566
+ if (!props.disabled) {
1567
+ e.currentTarget.style.borderColor = error ? "var(--lm-error-400)" : "var(--lm-primary-400)";
1568
+ }
1569
+ (_a = props.onFocus) == null ? void 0 : _a.call(props, e);
1570
+ },
1571
+ onBlur: (e) => {
1572
+ var _a;
1573
+ if (!props.disabled) {
1574
+ e.currentTarget.style.borderColor = error ? "var(--lm-error-300)" : "var(--lm-border-default)";
1575
+ }
1576
+ (_a = props.onBlur) == null ? void 0 : _a.call(props, e);
1577
+ }
1578
+ }
1579
+ ),
1580
+ errorMessage && /* @__PURE__ */ jsxRuntime.jsxs(
1581
+ "p",
1582
+ {
1583
+ className: "text-xs flex items-center gap-1",
1584
+ style: { color: "var(--lm-error-500)" },
1585
+ children: [
1586
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-3 h-3", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsxRuntime.jsx(
1587
+ "path",
1588
+ {
1589
+ fillRule: "evenodd",
1590
+ d: "M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z",
1591
+ clipRule: "evenodd"
1592
+ }
1593
+ ) }),
1594
+ errorMessage
1595
+ ]
1596
+ }
1597
+ )
1598
+ ] });
1599
+ };
1600
+ const LMNumberInput = ({
1601
+ value,
1602
+ onChange,
1603
+ error = false,
1604
+ errorMessage,
1605
+ placeholder = "Enter number...",
1606
+ disabled = false,
1607
+ className = "",
1608
+ name,
1609
+ size = "md",
1610
+ min,
1611
+ max,
1612
+ step = 1,
1613
+ precision = 0,
1614
+ showControls = true,
1615
+ prefix,
1616
+ suffix
1617
+ }) => {
1618
+ const [inputValue, setInputValue] = React.useState(
1619
+ value !== null && value !== void 0 ? String(value) : ""
1620
+ );
1621
+ const [isFocused, setIsFocused] = React.useState(false);
1622
+ const inputRef = React.useRef(null);
1623
+ const errId = React.useRef(`lm-ni-err-${Math.random().toString(36).slice(2)}`).current;
1624
+ const formatNumber = React.useCallback(
1625
+ (num) => {
1626
+ if (!Number.isFinite(num)) return "";
1627
+ if (precision <= 0) return String(Math.round(num));
1628
+ return num.toFixed(precision);
1629
+ },
1630
+ [precision]
1631
+ );
1632
+ React.useEffect(() => {
1633
+ if (value === void 0 || value === null) {
1634
+ setInputValue("");
1635
+ } else if (!isFocused) {
1636
+ setInputValue(formatNumber(value));
1637
+ }
1638
+ }, [value, isFocused, formatNumber]);
1639
+ const baseClassName = `
1640
+ w-full ${SIZE_INPUT_CONFIG[size].padding} ${SIZE_INPUT_CONFIG[size].height} ${SIZE_INPUT_CONFIG[size].fontSize}
1641
+ backdrop-blur-md border rounded-2xl
1642
+ focus:ring-2 focus:outline-none transition-all duration-300
1643
+ shadow-sm
1644
+ ${showControls ? "pr-10" : ""}
1645
+ ${prefix ? "pl-10" : ""}
1646
+ ${suffix ? "pr-10" : ""}
1647
+ ${className}
1648
+ [&::-webkit-outer-spin-button]:appearance-none
1649
+ [&::-webkit-inner-spin-button]:appearance-none
1650
+ [-moz-appearance:textfield]
1651
+ `.trim().replace(/\s+/g, " ");
1652
+ const getNumberInputStyles = () => {
1653
+ const base = {
1654
+ backgroundColor: "var(--lm-bg-elevated)",
1655
+ color: "var(--lm-text-primary)",
1656
+ borderColor: error ? "var(--lm-error-300)" : isFocused ? "var(--lm-primary-400)" : "var(--lm-border-default)",
1657
+ boxShadow: "var(--lm-shadow-sm)"
1658
+ };
1659
+ return {
1660
+ ...base,
1661
+ "--tw-ring-color": error ? "var(--lm-error-400)" : "var(--lm-primary-400)",
1662
+ "--tw-ring-opacity": "0.3"
1663
+ };
1664
+ };
1665
+ const getDisabledStyles = () => disabled ? {
1666
+ backgroundColor: "var(--lm-bg-paper)",
1667
+ color: "var(--lm-text-disabled)",
1668
+ cursor: "not-allowed",
1669
+ opacity: 0.6
1670
+ } : {};
1671
+ const getIconStyles = () => {
1672
+ if (error) return { color: "var(--lm-error-400)" };
1673
+ if (isFocused) return { color: "var(--lm-primary-500)" };
1674
+ return { color: "var(--lm-text-secondary)" };
1675
+ };
1676
+ const getControlButtonStyles = () => ({
1677
+ backgroundColor: "var(--lm-bg-paper)",
1678
+ color: "var(--lm-text-secondary)",
1679
+ borderColor: "var(--lm-border-light)"
1680
+ });
1681
+ const getHoverControlButtonStyles = () => ({
1682
+ backgroundColor: "var(--lm-bg-elevated)",
1683
+ color: "var(--lm-text-primary)"
1684
+ });
1685
+ const parseNumber = (str) => {
1686
+ const n = parseFloat(str);
1687
+ return Number.isNaN(n) ? null : n;
1688
+ };
1689
+ const clamp = (num) => {
1690
+ let v = num;
1691
+ if (min !== void 0) v = Math.max(v, min);
1692
+ if (max !== void 0) v = Math.min(v, max);
1693
+ return v;
1694
+ };
1695
+ const stepFrom = React.useMemo(() => min ?? 0, [min]);
1696
+ const alignToStep = (num) => {
1697
+ const offset = num - stepFrom;
1698
+ const k = Math.round(offset / step);
1699
+ const next = stepFrom + k * step;
1700
+ return Number(next.toFixed(Math.max(precision, 12)));
1701
+ };
1702
+ const handleInputChange = (event) => {
1703
+ const val = event.target.value;
1704
+ setInputValue(val);
1705
+ if (val.trim() === "") {
1706
+ onChange == null ? void 0 : onChange(null);
1707
+ return;
1708
+ }
1709
+ const num = parseNumber(val);
1710
+ if (num === null) return;
1711
+ const clamped = clamp(num);
1712
+ if (clamped !== num) return;
1713
+ onChange == null ? void 0 : onChange(num);
1714
+ };
1715
+ const changeByStep = (delta) => {
1716
+ if (disabled) return;
1717
+ const current = parseNumber(inputValue);
1718
+ const base = current ?? min ?? 0;
1719
+ const raw = base + delta * step;
1720
+ const clamped = clamp(raw);
1721
+ const aligned = alignToStep(clamped);
1722
+ setInputValue(formatNumber(aligned));
1723
+ onChange == null ? void 0 : onChange(aligned);
1724
+ };
1725
+ const handleIncrement = () => changeByStep(1);
1726
+ const handleDecrement = () => changeByStep(-1);
1727
+ const handleKeyDown = (event) => {
1728
+ if (event.key === "ArrowUp") {
1729
+ event.preventDefault();
1730
+ handleIncrement();
1731
+ } else if (event.key === "ArrowDown") {
1732
+ event.preventDefault();
1733
+ handleDecrement();
1734
+ }
1735
+ };
1736
+ const handleFocus = () => setIsFocused(true);
1737
+ const handleBlur = () => {
1738
+ setIsFocused(false);
1739
+ if (inputValue.trim() === "") {
1740
+ setInputValue("");
1741
+ if (value !== null) onChange == null ? void 0 : onChange(null);
1742
+ return;
1743
+ }
1744
+ const num = parseNumber(inputValue);
1745
+ if (num === null) {
1746
+ if (typeof value === "number") {
1747
+ setInputValue(formatNumber(clamp(value)));
1748
+ } else {
1749
+ setInputValue("");
1750
+ if (value !== null) onChange == null ? void 0 : onChange(null);
1751
+ }
1752
+ return;
1753
+ }
1754
+ let v = clamp(num);
1755
+ v = alignToStep(v);
1756
+ const formatted = formatNumber(v);
1757
+ setInputValue(formatted);
1758
+ if (v !== value) onChange == null ? void 0 : onChange(v);
1759
+ };
1760
+ const handleWheel = (e) => {
1761
+ if (document.activeElement === inputRef.current) {
1762
+ e.preventDefault();
1763
+ }
1764
+ };
1765
+ const currentNum = parseNumber(inputValue);
1766
+ const incDisabled = React.useMemo(() => {
1767
+ if (disabled) return true;
1768
+ const base = currentNum ?? min ?? 0;
1769
+ return max !== void 0 && base >= max;
1770
+ }, [disabled, currentNum, min, max]);
1771
+ const decDisabled = React.useMemo(() => {
1772
+ if (disabled) return true;
1773
+ const base = currentNum ?? min ?? 0;
1774
+ return min !== void 0 && base <= min;
1775
+ }, [disabled, currentNum, min]);
1776
+ const ChevronUp = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-3 h-3", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 15l7-7 7 7" }) });
1777
+ const ChevronDown = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-3 h-3", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) });
1778
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1779
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative group", children: [
1780
+ prefix && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-y-0 left-0 pl-4 flex items-center pointer-events-none z-10", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium", style: getIconStyles(), children: prefix }) }),
1781
+ /* @__PURE__ */ jsxRuntime.jsx(
1782
+ "input",
1783
+ {
1784
+ ref: inputRef,
1785
+ type: "number",
1786
+ name,
1787
+ value: inputValue,
1788
+ placeholder,
1789
+ disabled,
1790
+ min,
1791
+ max,
1792
+ step,
1793
+ inputMode: "decimal",
1794
+ className: baseClassName,
1795
+ style: { ...getNumberInputStyles(), ...getDisabledStyles() },
1796
+ "aria-invalid": error || void 0,
1797
+ "aria-describedby": errorMessage ? errId : void 0,
1798
+ onChange: handleInputChange,
1799
+ onKeyDown: handleKeyDown,
1800
+ onFocus: handleFocus,
1801
+ onBlur: handleBlur,
1802
+ onWheel: handleWheel,
1803
+ onMouseEnter: (e) => {
1804
+ if (!disabled && !error && !isFocused) {
1805
+ e.currentTarget.style.borderColor = "var(--lm-border-strong)";
1806
+ }
1807
+ },
1808
+ onMouseLeave: (e) => {
1809
+ if (!disabled && !error && !isFocused) {
1810
+ e.currentTarget.style.borderColor = "var(--lm-border-default)";
1811
+ }
1812
+ }
1813
+ }
1814
+ ),
1815
+ suffix && /* @__PURE__ */ jsxRuntime.jsx(
1816
+ "div",
1817
+ {
1818
+ className: `absolute inset-y-0 flex items-center pointer-events-none z-10 ${showControls ? "right-10" : "right-4"}`,
1819
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium", style: getIconStyles(), children: suffix })
1820
+ }
1821
+ ),
1822
+ showControls && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute inset-y-0 right-0 flex flex-col w-8", children: [
1823
+ /* @__PURE__ */ jsxRuntime.jsx(
1824
+ "button",
1825
+ {
1826
+ type: "button",
1827
+ "aria-label": "Increment",
1828
+ onClick: handleIncrement,
1829
+ disabled: incDisabled,
1830
+ className: "flex-1 px-1 border-l border-b rounded-tr-2xl transition-colors duration-200 flex items-center justify-center",
1831
+ style: getControlButtonStyles(),
1832
+ onMouseEnter: (e) => {
1833
+ if (!incDisabled)
1834
+ Object.assign(e.currentTarget.style, getHoverControlButtonStyles());
1835
+ },
1836
+ onMouseLeave: (e) => {
1837
+ if (!incDisabled)
1838
+ Object.assign(e.currentTarget.style, getControlButtonStyles());
1839
+ },
1840
+ children: /* @__PURE__ */ jsxRuntime.jsx(ChevronUp, {})
1841
+ }
1842
+ ),
1843
+ /* @__PURE__ */ jsxRuntime.jsx(
1844
+ "button",
1845
+ {
1846
+ type: "button",
1847
+ "aria-label": "Decrement",
1848
+ onClick: handleDecrement,
1849
+ disabled: decDisabled,
1850
+ className: "flex-1 px-1 border-l rounded-br-2xl transition-colors duration-200 flex items-center justify-center",
1851
+ style: getControlButtonStyles(),
1852
+ onMouseEnter: (e) => {
1853
+ if (!decDisabled)
1854
+ Object.assign(e.currentTarget.style, getHoverControlButtonStyles());
1855
+ },
1856
+ onMouseLeave: (e) => {
1857
+ if (!decDisabled)
1858
+ Object.assign(e.currentTarget.style, getControlButtonStyles());
1859
+ },
1860
+ children: /* @__PURE__ */ jsxRuntime.jsx(ChevronDown, {})
1861
+ }
1862
+ )
1863
+ ] })
1864
+ ] }),
1865
+ errorMessage && /* @__PURE__ */ jsxRuntime.jsxs(
1866
+ "p",
1867
+ {
1868
+ id: errId,
1869
+ className: "text-xs flex items-center gap-1",
1870
+ style: { color: "var(--lm-error-500)" },
1871
+ role: "alert",
1872
+ "aria-live": "polite",
1873
+ children: [
1874
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-3 h-3", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsxRuntime.jsx(
1875
+ "path",
1876
+ {
1877
+ fillRule: "evenodd",
1878
+ d: "M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z",
1879
+ clipRule: "evenodd"
1880
+ }
1881
+ ) }),
1882
+ errorMessage
1883
+ ]
1884
+ }
1885
+ )
1886
+ ] });
1887
+ };
1888
+ const LMSearchInput = ({
1889
+ value,
1890
+ onChange,
1891
+ onSearch,
1892
+ error = false,
1893
+ errorMessage,
1894
+ placeholder = "Search...",
1895
+ disabled = false,
1896
+ className = "",
1897
+ name,
1898
+ size = "md",
1899
+ showClear = true,
1900
+ showSearchButton = true,
1901
+ searchButtonText = "Search",
1902
+ debounceDelay = 300
1903
+ }) => {
1904
+ const [inputValue, setInputValue] = React.useState(value || "");
1905
+ const [isFocused, setIsFocused] = React.useState(false);
1906
+ const debounceRef = React.useRef(null);
1907
+ const inputRef = React.useRef(null);
1908
+ const searchBtnRef = React.useRef(null);
1909
+ const [searchBtnWidth, setSearchBtnWidth] = React.useState(0);
1910
+ React.useEffect(() => {
1911
+ if (value !== void 0 && value !== null) setInputValue(value);
1912
+ }, [value]);
1913
+ React.useEffect(() => {
1914
+ if (showSearchButton && searchBtnRef.current) {
1915
+ setSearchBtnWidth(searchBtnRef.current.offsetWidth || 0);
1916
+ } else {
1917
+ setSearchBtnWidth(0);
1918
+ }
1919
+ }, [showSearchButton, searchButtonText]);
1920
+ const baseClassName = `
1921
+ w-full ${SIZE_INPUT_CONFIG[size].padding} ${SIZE_INPUT_CONFIG[size].height} backdrop-blur-md border rounded-2xl
1922
+ focus:ring-2 focus:outline-none transition-all duration-300
1923
+ shadow-sm
1924
+ ${showSearchButton ? "pr-20" : showClear ? "pr-10" : "pr-4"}
1925
+ pl-12
1926
+ ${className}
1927
+ `.trim().replace(/\s+/g, " ");
1928
+ const getSearchInputStyles = () => {
1929
+ const baseStyles = {
1930
+ backgroundColor: "var(--lm-bg-elevated)",
1931
+ color: "var(--lm-text-primary)",
1932
+ borderColor: error ? "var(--lm-error-300)" : isFocused ? "var(--lm-primary-400)" : "var(--lm-border-default)",
1933
+ boxShadow: "var(--lm-shadow-sm)"
1934
+ };
1935
+ return {
1936
+ ...baseStyles,
1937
+ "--tw-ring-color": error ? "var(--lm-error-400)" : "var(--lm-primary-400)",
1938
+ "--tw-ring-opacity": "0.3"
1939
+ };
1940
+ };
1941
+ const getDisabledStyles = () => disabled ? {
1942
+ backgroundColor: "var(--lm-bg-paper)",
1943
+ color: "var(--lm-text-disabled)",
1944
+ cursor: "not-allowed",
1945
+ opacity: 0.6
1946
+ } : {};
1947
+ const getIconStyles = () => {
1948
+ if (error) return { color: "var(--lm-error-400)" };
1949
+ if (isFocused) return { color: "var(--lm-primary-500)" };
1950
+ return { color: "var(--lm-text-secondary)" };
1951
+ };
1952
+ const getButtonStyles = () => ({
1953
+ backgroundColor: "var(--lm-primary-500)",
1954
+ color: "white"
1955
+ });
1956
+ const getClearButtonStyles = () => ({
1957
+ backgroundColor: "var(--lm-bg-paper)",
1958
+ color: "var(--lm-text-secondary)"
1959
+ });
1960
+ const handleInputChange = (event) => {
1961
+ const newValue = event.target.value;
1962
+ setInputValue(newValue);
1963
+ onChange == null ? void 0 : onChange(newValue);
1964
+ if (debounceRef.current) clearTimeout(debounceRef.current);
1965
+ debounceRef.current = setTimeout(() => {
1966
+ onSearch == null ? void 0 : onSearch(newValue);
1967
+ }, debounceDelay);
1968
+ };
1969
+ const handleSearch = () => onSearch == null ? void 0 : onSearch(inputValue);
1970
+ const handleClear = () => {
1971
+ var _a;
1972
+ setInputValue("");
1973
+ onChange == null ? void 0 : onChange("");
1974
+ onSearch == null ? void 0 : onSearch("");
1975
+ (_a = inputRef.current) == null ? void 0 : _a.focus();
1976
+ };
1977
+ const handleKeyDown = (event) => {
1978
+ if (event.key === "Enter") {
1979
+ event.preventDefault();
1980
+ handleSearch();
1981
+ }
1982
+ };
1983
+ const clearBtnSizeClass = size === "sm" ? "w-7 h-7 text-xs" : size === "lg" ? "w-9 h-9 text-sm" : "w-8 h-8 text-sm";
1984
+ const clearRightPx = showSearchButton ? searchBtnWidth + 8 : 8;
1985
+ const SearchIcon = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) });
1986
+ const ClearIcon = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-3 h-3", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) });
1987
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1988
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative group", children: [
1989
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-y-0 left-0 pl-4 flex items-center pointer-events-none z-10", children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: getIconStyles(), children: /* @__PURE__ */ jsxRuntime.jsx(SearchIcon, {}) }) }),
1990
+ /* @__PURE__ */ jsxRuntime.jsx(
1991
+ "input",
1992
+ {
1993
+ ref: inputRef,
1994
+ type: "search",
1995
+ name,
1996
+ value: inputValue,
1997
+ placeholder,
1998
+ disabled,
1999
+ className: baseClassName,
2000
+ style: {
2001
+ ...getSearchInputStyles(),
2002
+ ...getDisabledStyles()
2003
+ },
2004
+ onChange: handleInputChange,
2005
+ onKeyDown: handleKeyDown,
2006
+ onFocus: () => setIsFocused(true),
2007
+ onBlur: () => setIsFocused(false),
2008
+ onMouseEnter: (e) => {
2009
+ if (!disabled && !error && !isFocused) {
2010
+ e.currentTarget.style.borderColor = "var(--lm-border-strong)";
2011
+ }
2012
+ },
2013
+ onMouseLeave: (e) => {
2014
+ if (!disabled && !error && !isFocused) {
2015
+ e.currentTarget.style.borderColor = "var(--lm-border-default)";
2016
+ }
2017
+ }
2018
+ }
2019
+ ),
2020
+ /* @__PURE__ */ jsxRuntime.jsx("style", { children: `
2021
+ input[type='search']::-webkit-search-cancel-button {
2022
+ -webkit-appearance: none;
2023
+ appearance: none;
2024
+ }
2025
+ ` }),
2026
+ showClear && inputValue && !disabled && /* @__PURE__ */ jsxRuntime.jsx(
2027
+ "button",
2028
+ {
2029
+ onClick: handleClear,
2030
+ className: `absolute top-1/2 -translate-y-1/2 z-10 rounded-full flex items-center justify-center ${clearBtnSizeClass}`,
2031
+ style: {
2032
+ ...getClearButtonStyles(),
2033
+ right: `${clearRightPx}px`
2034
+ },
2035
+ onMouseEnter: (e) => {
2036
+ e.currentTarget.style.backgroundColor = "var(--lm-bg-elevated)";
2037
+ e.currentTarget.style.color = "var(--lm-text-primary)";
2038
+ },
2039
+ onMouseLeave: (e) => {
2040
+ e.currentTarget.style.backgroundColor = "var(--lm-bg-paper)";
2041
+ e.currentTarget.style.color = "var(--lm-text-secondary)";
2042
+ },
2043
+ "aria-label": "Clear",
2044
+ type: "button",
2045
+ children: /* @__PURE__ */ jsxRuntime.jsx(ClearIcon, {})
2046
+ }
2047
+ ),
2048
+ showSearchButton && !disabled && /* @__PURE__ */ jsxRuntime.jsx(
2049
+ "button",
2050
+ {
2051
+ ref: searchBtnRef,
2052
+ onClick: handleSearch,
2053
+ className: "absolute inset-y-0 right-0 px-4 rounded-r-2xl transition-colors duration-200 z-20",
2054
+ style: getButtonStyles(),
2055
+ onMouseEnter: (e) => {
2056
+ e.currentTarget.style.backgroundColor = "var(--lm-primary-600)";
2057
+ },
2058
+ onMouseLeave: (e) => {
2059
+ e.currentTarget.style.backgroundColor = "var(--lm-primary-500)";
2060
+ },
2061
+ type: "button",
2062
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium", children: searchButtonText })
2063
+ }
2064
+ )
2065
+ ] }),
2066
+ errorMessage && /* @__PURE__ */ jsxRuntime.jsxs(
2067
+ "p",
2068
+ {
2069
+ className: "text-xs flex items-center gap-1",
2070
+ style: { color: "var(--lm-error-500)" },
2071
+ children: [
2072
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-3 h-3", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsxRuntime.jsx(
2073
+ "path",
2074
+ {
2075
+ fillRule: "evenodd",
2076
+ d: "M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z",
2077
+ clipRule: "evenodd"
2078
+ }
2079
+ ) }),
2080
+ errorMessage
2081
+ ]
2082
+ }
2083
+ )
2084
+ ] });
2085
+ };
2086
+ const SIZE_DROPDOWN_CONFIG = {
2087
+ xs: { maxHeight: "max-h-32", optionPadding: "px-3 py-1.5", optionTextSize: "text-xs" },
2088
+ sm: { maxHeight: "max-h-40", optionPadding: "px-3 py-2", optionTextSize: "text-xs" },
2089
+ md: { maxHeight: "max-h-48", optionPadding: "px-4 py-2.5", optionTextSize: "text-sm" },
2090
+ lg: { maxHeight: "max-h-56", optionPadding: "px-4 py-3", optionTextSize: "text-sm" },
2091
+ xl: { maxHeight: "max-h-64", optionPadding: "px-5 py-3", optionTextSize: "text-base" },
2092
+ "2xl": { maxHeight: "max-h-72", optionPadding: "px-6 py-4", optionTextSize: "text-lg" }
2093
+ };
2094
+ const LMSelect = ({
2095
+ options,
2096
+ value,
2097
+ onChange,
2098
+ onDropdownVisibleChange,
2099
+ error = false,
2100
+ errorMessage,
2101
+ placeholder = "Select...",
2102
+ disabled = false,
2103
+ className = "",
2104
+ name,
2105
+ size = "md",
2106
+ multiple = false
2107
+ }) => {
2108
+ const [isOpen, setIsOpen] = React.useState(false);
2109
+ const [selectedOption, setSelectedOption] = React.useState(null);
2110
+ const [selectedOptions, setSelectedOptions] = React.useState([]);
2111
+ const dropdownRef = React.useRef(null);
2112
+ React.useEffect(() => {
2113
+ if (!multiple) {
2114
+ if (value !== void 0 && value !== null && !Array.isArray(value)) {
2115
+ const option = options.find((opt) => opt.value === value);
2116
+ setSelectedOption(option || null);
2117
+ } else {
2118
+ setSelectedOption(null);
2119
+ }
2120
+ }
2121
+ }, [value, options, multiple]);
2122
+ React.useEffect(() => {
2123
+ if (multiple && Array.isArray(value)) {
2124
+ const selectedOpts = options.filter((opt) => value.includes(opt.value));
2125
+ setSelectedOptions(selectedOpts);
2126
+ } else if (multiple) {
2127
+ setSelectedOptions([]);
2128
+ }
2129
+ }, [value, options, multiple]);
2130
+ React.useEffect(() => {
2131
+ const handleClickOutside = (event) => {
2132
+ if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
2133
+ setIsOpen(false);
2134
+ onDropdownVisibleChange == null ? void 0 : onDropdownVisibleChange(false);
2135
+ }
2136
+ };
2137
+ if (isOpen) {
2138
+ document.addEventListener("mousedown", handleClickOutside);
2139
+ return () => document.removeEventListener("mousedown", handleClickOutside);
2140
+ }
2141
+ }, [isOpen, onDropdownVisibleChange]);
2142
+ const handleSelect = (option) => {
2143
+ if (option.disabled) return;
2144
+ if (multiple) {
2145
+ const currentValues = Array.isArray(value) ? value : [];
2146
+ const isSelected = currentValues.includes(option.value);
2147
+ const newValues = isSelected ? currentValues.filter((v) => v !== option.value) : [...currentValues, option.value];
2148
+ onChange == null ? void 0 : onChange(newValues);
2149
+ } else {
2150
+ setSelectedOption(option);
2151
+ onChange == null ? void 0 : onChange(option.value);
2152
+ setIsOpen(false);
2153
+ onDropdownVisibleChange == null ? void 0 : onDropdownVisibleChange(false);
2154
+ }
2155
+ };
2156
+ const toggleDropdown = () => {
2157
+ if (!disabled) {
2158
+ const newIsOpen = !isOpen;
2159
+ setIsOpen(newIsOpen);
2160
+ onDropdownVisibleChange == null ? void 0 : onDropdownVisibleChange(newIsOpen);
2161
+ }
2162
+ };
2163
+ const baseClassName = `
2164
+ w-full ${SIZE_SELECTOR_CONFIG[size].padding} ${SIZE_SELECTOR_CONFIG[size].height} ${SIZE_SELECTOR_CONFIG[size].fontSize}
2165
+ backdrop-blur-md border rounded-2xl
2166
+ transition-all duration-300 shadow-sm cursor-pointer
2167
+ flex items-center justify-between
2168
+ ${className}
2169
+ `.trim().replace(/\s+/g, " ");
2170
+ const getSelectorStyles = () => {
2171
+ const baseStyles = {
2172
+ backgroundColor: "var(--lm-bg-elevated)",
2173
+ color: "var(--lm-text-primary)",
2174
+ borderColor: error ? "var(--lm-error-300)" : "var(--lm-border-default)",
2175
+ boxShadow: "var(--lm-shadow-sm)"
2176
+ };
2177
+ return {
2178
+ ...baseStyles,
2179
+ "--tw-ring-color": error ? "var(--lm-error-400)" : "var(--lm-primary-400)",
2180
+ "--tw-ring-opacity": "0.3"
2181
+ };
2182
+ };
2183
+ const getDisabledStyles = () => disabled ? {
2184
+ backgroundColor: "var(--lm-bg-paper)",
2185
+ color: "var(--lm-text-disabled)",
2186
+ cursor: "not-allowed",
2187
+ opacity: 0.6
2188
+ } : {};
2189
+ const getIconStyles = () => error ? { color: "var(--lm-error-400)" } : { color: "var(--lm-text-secondary)" };
2190
+ const getDropdownStyles = () => ({
2191
+ backgroundColor: "var(--lm-bg-elevated)",
2192
+ borderColor: "var(--lm-border-default)",
2193
+ boxShadow: "var(--lm-shadow-lg)"
2194
+ });
2195
+ const isOptionSelected = (optionValue) => {
2196
+ if (multiple) {
2197
+ return Array.isArray(value) && value.includes(optionValue);
2198
+ }
2199
+ return (selectedOption == null ? void 0 : selectedOption.value) === optionValue;
2200
+ };
2201
+ const getOptionStyles = (option) => {
2202
+ const baseStyles = {
2203
+ color: option.disabled ? "var(--lm-text-disabled)" : "var(--lm-text-primary)",
2204
+ backgroundColor: option.disabled ? "var(--lm-bg-paper)" : "transparent"
2205
+ };
2206
+ if (isOptionSelected(option.value)) {
2207
+ return {
2208
+ ...baseStyles,
2209
+ backgroundColor: "var(--lm-primary-50)",
2210
+ color: "var(--lm-primary-700)"
2211
+ };
2212
+ }
2213
+ return baseStyles;
2214
+ };
2215
+ const getHoverOptionStyles = (option) => {
2216
+ if (option.disabled) return {};
2217
+ if (isOptionSelected(option.value)) {
2218
+ return { backgroundColor: "var(--lm-primary-100)" };
2219
+ }
2220
+ return { backgroundColor: "var(--lm-bg-paper)" };
2221
+ };
2222
+ const getDisplayText = () => {
2223
+ if (multiple) {
2224
+ if (selectedOptions.length === 0) return placeholder;
2225
+ if (selectedOptions.length === 1) return selectedOptions[0].label;
2226
+ return `${selectedOptions.length} selected`;
2227
+ }
2228
+ return selectedOption ? selectedOption.label : placeholder;
2229
+ };
2230
+ const ChevronDown = () => /* @__PURE__ */ jsxRuntime.jsx(
2231
+ "svg",
2232
+ {
2233
+ className: `w-4 h-4 transition-transform duration-200 ${isOpen ? "rotate-180" : ""}`,
2234
+ fill: "none",
2235
+ stroke: "currentColor",
2236
+ viewBox: "0 0 24 24",
2237
+ style: getIconStyles(),
2238
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" })
2239
+ }
2240
+ );
2241
+ const CheckIcon = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) });
2242
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", ref: dropdownRef, children: [
2243
+ /* @__PURE__ */ jsxRuntime.jsx(
2244
+ "select",
2245
+ {
2246
+ name,
2247
+ value: multiple ? Array.isArray(value) ? value.map(String) : [] : value !== void 0 && value !== null && !Array.isArray(value) ? String(value) : "",
2248
+ onChange: () => {
2249
+ },
2250
+ className: "sr-only",
2251
+ disabled,
2252
+ tabIndex: -1,
2253
+ multiple,
2254
+ children: options.map((option) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: option.value, disabled: option.disabled, children: option.label }, option.value))
2255
+ }
2256
+ ),
2257
+ /* @__PURE__ */ jsxRuntime.jsxs(
2258
+ "div",
2259
+ {
2260
+ className: baseClassName,
2261
+ onClick: toggleDropdown,
2262
+ role: "button",
2263
+ tabIndex: disabled ? -1 : 0,
2264
+ style: {
2265
+ ...getSelectorStyles(),
2266
+ ...getDisabledStyles()
2267
+ },
2268
+ onMouseEnter: (e) => {
2269
+ if (!disabled && !error) {
2270
+ e.currentTarget.style.borderColor = "var(--lm-border-strong)";
2271
+ }
2272
+ },
2273
+ onMouseLeave: (e) => {
2274
+ if (!disabled && !error) {
2275
+ e.currentTarget.style.borderColor = "var(--lm-border-default)";
2276
+ }
2277
+ },
2278
+ onFocus: (e) => {
2279
+ if (!disabled) {
2280
+ e.currentTarget.style.borderColor = error ? "var(--lm-error-400)" : "var(--lm-primary-400)";
2281
+ }
2282
+ },
2283
+ onBlur: (e) => {
2284
+ if (!disabled) {
2285
+ e.currentTarget.style.borderColor = error ? "var(--lm-error-300)" : "var(--lm-border-default)";
2286
+ }
2287
+ },
2288
+ onKeyDown: (e) => {
2289
+ if (e.key === "Enter" || e.key === " ") {
2290
+ e.preventDefault();
2291
+ toggleDropdown();
2292
+ }
2293
+ },
2294
+ children: [
2295
+ /* @__PURE__ */ jsxRuntime.jsx(
2296
+ "span",
2297
+ {
2298
+ style: {
2299
+ color: multiple && selectedOptions.length > 0 || selectedOption ? "var(--lm-text-primary)" : "var(--lm-text-secondary)"
2300
+ },
2301
+ children: getDisplayText()
2302
+ }
2303
+ ),
2304
+ /* @__PURE__ */ jsxRuntime.jsx(ChevronDown, {})
2305
+ ]
2306
+ }
2307
+ ),
2308
+ isOpen && /* @__PURE__ */ jsxRuntime.jsx(
2309
+ "div",
2310
+ {
2311
+ className: `absolute left-0 right-0 z-50 backdrop-blur-md border rounded-xl overflow-y-auto ${SIZE_DROPDOWN_CONFIG[size].maxHeight}`,
2312
+ style: {
2313
+ ...getDropdownStyles(),
2314
+ top: "calc(100% + 4px)"
2315
+ },
2316
+ children: options.map((option, index) => /* @__PURE__ */ jsxRuntime.jsx(
2317
+ "div",
2318
+ {
2319
+ className: `
2320
+ ${SIZE_DROPDOWN_CONFIG[size].optionPadding} ${SIZE_DROPDOWN_CONFIG[size].optionTextSize} font-medium
2321
+ cursor-pointer transition-all duration-150
2322
+ ${option.disabled ? "cursor-not-allowed" : ""}
2323
+ ${index === 0 ? "rounded-t-xl" : ""}
2324
+ ${index === options.length - 1 ? "rounded-b-xl" : ""}
2325
+ ${index > 0 ? "border-t" : ""}
2326
+ `,
2327
+ style: {
2328
+ ...getOptionStyles(option),
2329
+ borderTopColor: index > 0 ? "var(--lm-border-light)" : "transparent"
2330
+ },
2331
+ onMouseEnter: (e) => {
2332
+ if (!option.disabled) {
2333
+ Object.assign(e.currentTarget.style, getHoverOptionStyles(option));
2334
+ }
2335
+ },
2336
+ onMouseLeave: (e) => {
2337
+ if (!option.disabled) {
2338
+ Object.assign(e.currentTarget.style, getOptionStyles(option));
2339
+ }
2340
+ },
2341
+ onClick: () => handleSelect(option),
2342
+ role: "option",
2343
+ "aria-selected": isOptionSelected(option.value),
2344
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
2345
+ multiple && /* @__PURE__ */ jsxRuntime.jsx(
2346
+ "input",
2347
+ {
2348
+ type: "checkbox",
2349
+ checked: isOptionSelected(option.value),
2350
+ onChange: () => {
2351
+ },
2352
+ className: "mr-2 cursor-pointer",
2353
+ style: { accentColor: "var(--lm-primary-500)" },
2354
+ onClick: (e) => e.stopPropagation()
2355
+ }
2356
+ ),
2357
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate flex-1", children: option.label }),
2358
+ !multiple && isOptionSelected(option.value) && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2 flex-shrink-0", style: { color: "var(--lm-primary-600)" }, children: /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, {}) })
2359
+ ] })
2360
+ },
2361
+ option.value
2362
+ ))
2363
+ }
2364
+ ),
2365
+ errorMessage && /* @__PURE__ */ jsxRuntime.jsxs(
2366
+ "p",
2367
+ {
2368
+ className: "text-xs flex items-center gap-1 mt-2",
2369
+ style: { color: "var(--lm-error-500)" },
2370
+ children: [
2371
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-3 h-3", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsxRuntime.jsx(
2372
+ "path",
2373
+ {
2374
+ fillRule: "evenodd",
2375
+ d: "M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z",
2376
+ clipRule: "evenodd"
2377
+ }
2378
+ ) }),
2379
+ errorMessage
2380
+ ]
2381
+ }
2382
+ )
2383
+ ] });
2384
+ };
2385
+ const LMField = ({
2386
+ label,
2387
+ required = false,
2388
+ errorMessage,
2389
+ help,
2390
+ children,
2391
+ className = ""
2392
+ }) => {
2393
+ let controlId;
2394
+ const firstChild = Array.isArray(children) ? children.find(Boolean) : children;
2395
+ if (React.isValidElement(firstChild) && typeof firstChild.props.id === "string") {
2396
+ controlId = firstChild.props.id;
2397
+ }
2398
+ const containerClass = `space-y-2 ${className}`.trim().replace(/\s+/g, " ");
2399
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: containerClass, children: [
2400
+ /* @__PURE__ */ jsxRuntime.jsxs(
2401
+ "label",
2402
+ {
2403
+ htmlFor: controlId,
2404
+ className: "block text-xs font-semibold tracking-wide",
2405
+ style: { color: "var(--lm-text-primary)" },
2406
+ "aria-required": required || void 0,
2407
+ children: [
2408
+ label,
2409
+ required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1", style: { color: "var(--lm-error-500)" }, children: "*" })
2410
+ ]
2411
+ }
2412
+ ),
2413
+ help && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs", style: { color: "var(--lm-text-secondary)" }, children: help }),
2414
+ children,
2415
+ errorMessage && /* @__PURE__ */ jsxRuntime.jsxs(
2416
+ "p",
2417
+ {
2418
+ className: "text-xs flex items-center gap-1",
2419
+ style: { color: "var(--lm-error-500)" },
2420
+ role: "alert",
2421
+ "aria-live": "polite",
2422
+ children: [
2423
+ /* @__PURE__ */ jsxRuntime.jsx(
2424
+ "svg",
2425
+ {
2426
+ className: "w-3 h-3",
2427
+ fill: "currentColor",
2428
+ viewBox: "0 0 20 20",
2429
+ "aria-hidden": "true",
2430
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2431
+ "path",
2432
+ {
2433
+ fillRule: "evenodd",
2434
+ d: "M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z",
2435
+ clipRule: "evenodd"
2436
+ }
2437
+ )
2438
+ }
2439
+ ),
2440
+ errorMessage
2441
+ ]
2442
+ }
2443
+ )
2444
+ ] });
2445
+ };
2446
+ const CaretUpIcon = ({ active }) => /* @__PURE__ */ jsxRuntime.jsx(
2447
+ "svg",
2448
+ {
2449
+ className: "w-2.5 h-2.5",
2450
+ viewBox: "0 0 10 6",
2451
+ fill: "none",
2452
+ style: { color: active ? "var(--lm-primary-500)" : "var(--lm-gray-400)" },
2453
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 0L10 6H0L5 0Z", fill: "currentColor" })
2454
+ }
2455
+ );
2456
+ const CaretDownIcon = ({ active }) => /* @__PURE__ */ jsxRuntime.jsx(
2457
+ "svg",
2458
+ {
2459
+ className: "w-2.5 h-2.5",
2460
+ viewBox: "0 0 10 6",
2461
+ fill: "none",
2462
+ style: { color: active ? "var(--lm-primary-500)" : "var(--lm-gray-400)" },
2463
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 6L0 0H10L5 6Z", fill: "currentColor" })
2464
+ }
2465
+ );
2466
+ const ChevronLeftIcon = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-4 h-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15 19l-7-7 7-7" }) });
2467
+ const ChevronRightIcon = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-4 h-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 5l7 7-7 7" }) });
2468
+ const SpinnerIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { className: "w-4 h-4 animate-spin", viewBox: "0 0 24 24", fill: "none", children: [
2469
+ /* @__PURE__ */ jsxRuntime.jsx(
2470
+ "circle",
2471
+ {
2472
+ className: "opacity-25",
2473
+ cx: "12",
2474
+ cy: "12",
2475
+ r: "10",
2476
+ stroke: "currentColor",
2477
+ strokeWidth: "4"
2478
+ }
2479
+ ),
2480
+ /* @__PURE__ */ jsxRuntime.jsx(
2481
+ "path",
2482
+ {
2483
+ className: "opacity-75",
2484
+ fill: "currentColor",
2485
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
2486
+ }
2487
+ )
2488
+ ] });
2489
+ const LMTable = ({
2490
+ dataSource,
2491
+ columns,
2492
+ rowKey = "id",
2493
+ pagination,
2494
+ loadMore,
2495
+ loading = false,
2496
+ emptyText = "No data",
2497
+ size = "md",
2498
+ bordered = false,
2499
+ striped = false,
2500
+ selectable = false,
2501
+ selectedRowKeys = [],
2502
+ onSelectionChange,
2503
+ onRowClick,
2504
+ onSortChange,
2505
+ className = "",
2506
+ fullHeight = false,
2507
+ variant = "default"
2508
+ }) => {
2509
+ const [currentPage, setCurrentPage] = React.useState(1);
2510
+ const [pageSize, setPageSize] = React.useState(10);
2511
+ const [sortField, setSortField] = React.useState("");
2512
+ const [sortOrder, setSortOrder] = React.useState("ascend");
2513
+ const containerRef = React.useRef(null);
2514
+ const getRowKey = React.useCallback(
2515
+ (record, index) => {
2516
+ if (typeof rowKey === "function") {
2517
+ return rowKey(record, index);
2518
+ }
2519
+ const key = record[rowKey];
2520
+ return (typeof key === "string" ? key : String(key)) || index.toString();
2521
+ },
2522
+ [rowKey]
2523
+ );
2524
+ const getValueByDataIndex = React.useCallback((record, dataIndex) => {
2525
+ const parts = String(dataIndex).split(".");
2526
+ let current = record;
2527
+ for (const p of parts) {
2528
+ if (current == null || typeof current !== "object" || !(p in current)) {
2529
+ return "";
2530
+ }
2531
+ current = current[p];
2532
+ }
2533
+ return current;
2534
+ }, []);
2535
+ const handleSort = React.useCallback(
2536
+ (column) => {
2537
+ if (!column.sorter) return;
2538
+ let newSortOrder = "ascend";
2539
+ if (sortField === column.dataIndex) {
2540
+ newSortOrder = sortOrder === "ascend" ? "descend" : "ascend";
2541
+ }
2542
+ setSortField(column.dataIndex);
2543
+ setSortOrder(newSortOrder);
2544
+ onSortChange == null ? void 0 : onSortChange(column.dataIndex, newSortOrder);
2545
+ },
2546
+ [sortField, sortOrder, onSortChange]
2547
+ );
2548
+ const handlePageChange = React.useCallback(
2549
+ (page) => {
2550
+ var _a;
2551
+ setCurrentPage(page);
2552
+ (_a = pagination == null ? void 0 : pagination.onChange) == null ? void 0 : _a.call(pagination, page, pageSize);
2553
+ },
2554
+ [pagination, pageSize]
2555
+ );
2556
+ const handlePageSizeChange = React.useCallback(
2557
+ (newPageSize) => {
2558
+ var _a;
2559
+ setPageSize(newPageSize);
2560
+ setCurrentPage(1);
2561
+ (_a = pagination == null ? void 0 : pagination.onChange) == null ? void 0 : _a.call(pagination, 1, newPageSize);
2562
+ },
2563
+ [pagination]
2564
+ );
2565
+ const handleRowSelect = React.useCallback(
2566
+ (record, checked) => {
2567
+ const key = getRowKey(record, dataSource.indexOf(record));
2568
+ let newSelectedRowKeys;
2569
+ if (checked) {
2570
+ newSelectedRowKeys = [...selectedRowKeys, key];
2571
+ } else {
2572
+ newSelectedRowKeys = selectedRowKeys.filter((k) => k !== key);
2573
+ }
2574
+ const newSelectedRows = dataSource.filter(
2575
+ (item) => newSelectedRowKeys.includes(getRowKey(item, dataSource.indexOf(item)))
2576
+ );
2577
+ onSelectionChange == null ? void 0 : onSelectionChange(newSelectedRowKeys, newSelectedRows);
2578
+ },
2579
+ [selectedRowKeys, dataSource, getRowKey, onSelectionChange]
2580
+ );
2581
+ const handleSelectAll = React.useCallback(
2582
+ (checked) => {
2583
+ if (checked) {
2584
+ const allKeys = dataSource.map((record, index) => getRowKey(record, index));
2585
+ onSelectionChange == null ? void 0 : onSelectionChange(allKeys, dataSource);
2586
+ } else {
2587
+ onSelectionChange == null ? void 0 : onSelectionChange([], []);
2588
+ }
2589
+ },
2590
+ [dataSource, getRowKey, onSelectionChange]
2591
+ );
2592
+ const handleScroll = React.useCallback(() => {
2593
+ if (!(loadMore == null ? void 0 : loadMore.enabled) || loadMore.loading || !loadMore.hasMore) return;
2594
+ const container = containerRef.current;
2595
+ if (!container) return;
2596
+ const { scrollTop, scrollHeight, clientHeight } = container;
2597
+ const threshold = loadMore.threshold || 100;
2598
+ if (scrollTop + clientHeight >= scrollHeight - threshold) {
2599
+ loadMore.onLoadMore();
2600
+ }
2601
+ }, [loadMore]);
2602
+ React.useEffect(() => {
2603
+ const container = containerRef.current;
2604
+ if (!container || !(loadMore == null ? void 0 : loadMore.enabled)) return;
2605
+ container.addEventListener("scroll", handleScroll);
2606
+ return () => container.removeEventListener("scroll", handleScroll);
2607
+ }, [handleScroll, loadMore == null ? void 0 : loadMore.enabled, loadMore == null ? void 0 : loadMore.loading, loadMore == null ? void 0 : loadMore.hasMore]);
2608
+ React.useEffect(() => {
2609
+ if ((pagination == null ? void 0 : pagination.current) !== void 0) {
2610
+ setCurrentPage(pagination.current);
2611
+ }
2612
+ if ((pagination == null ? void 0 : pagination.pageSize) !== void 0) {
2613
+ setPageSize(pagination.pageSize);
2614
+ }
2615
+ }, [pagination]);
2616
+ const paginationUiClasses = {
2617
+ xs: {
2618
+ container: "px-3 py-2",
2619
+ text: "text-xs",
2620
+ control: "px-2 py-1 text-xs",
2621
+ gap: "gap-1",
2622
+ select: "px-2 py-1 text-xs",
2623
+ input: "px-2 py-1 text-xs w-14"
2624
+ },
2625
+ sm: {
2626
+ container: "px-3 py-2",
2627
+ text: "text-sm",
2628
+ control: "px-2 py-1 text-sm",
2629
+ gap: "gap-2",
2630
+ select: "px-2 py-1 text-sm",
2631
+ input: "px-2 py-1 text-sm w-16"
2632
+ },
2633
+ md: {
2634
+ container: "px-4 py-3",
2635
+ text: "text-sm",
2636
+ control: "px-3 py-1 text-sm",
2637
+ gap: "gap-2",
2638
+ select: "px-2 py-1 text-sm",
2639
+ input: "px-2 py-1 text-sm w-16"
2640
+ },
2641
+ lg: {
2642
+ container: "px-5 py-3.5",
2643
+ text: "text-base",
2644
+ control: "px-3.5 py-1.5 text-base",
2645
+ gap: "gap-3",
2646
+ select: "px-3 py-1.5 text-base",
2647
+ input: "px-3 py-1.5 text-base w-20"
2648
+ },
2649
+ xl: {
2650
+ container: "px-6 py-4",
2651
+ text: "text-lg",
2652
+ control: "px-4 py-2 text-lg",
2653
+ gap: "gap-3",
2654
+ select: "px-4 py-2 text-lg",
2655
+ input: "px-4 py-2 text-lg w-24"
2656
+ },
2657
+ "2xl": {
2658
+ container: "px-8 py-5",
2659
+ text: "text-xl",
2660
+ control: "px-5 py-2.5 text-xl",
2661
+ gap: "gap-4",
2662
+ select: "px-5 py-2.5 text-xl",
2663
+ input: "px-5 py-2.5 text-xl w-28"
2664
+ }
2665
+ };
2666
+ const totalPages = pagination && pagination.total && pageSize ? Math.max(1, Math.ceil(pagination.total / pageSize)) : 1;
2667
+ const getTableStyles = () => ({
2668
+ backgroundColor: variant === "minimal" ? "transparent" : variant === "soft" ? "var(--lm-bg-paper)" : "var(--lm-bg-elevated)",
2669
+ borderColor: variant === "outline" ? "var(--lm-border-strong)" : bordered ? "var(--lm-border-default)" : "transparent"
2670
+ });
2671
+ const getHeaderStyles = () => ({
2672
+ backgroundColor: variant === "minimal" ? "transparent" : "var(--lm-bg-elevated)",
2673
+ color: "var(--lm-text-primary)",
2674
+ borderColor: variant === "outline" ? "var(--lm-border-strong)" : "var(--lm-border-light)"
2675
+ });
2676
+ const getCellStyles = (isHeader = false) => ({
2677
+ backgroundColor: isHeader ? variant === "minimal" ? "transparent" : "var(--lm-bg-paper)" : variant === "minimal" ? "transparent" : variant === "soft" ? "var(--lm-bg-paper)" : "var(--lm-bg-elevated)",
2678
+ color: "var(--lm-text-primary)",
2679
+ borderColor: variant === "outline" ? "var(--lm-border-strong)" : variant === "minimal" ? "transparent" : "var(--lm-border-light)"
2680
+ });
2681
+ const getRowStyles = (index, isSelected = false) => {
2682
+ const baseStyles = {
2683
+ backgroundColor: isSelected ? "var(--lm-primary-50)" : (striped || variant === "zebra") && index % 2 === 1 ? "var(--lm-bg-paper)" : variant === "minimal" ? "transparent" : variant === "soft" ? "var(--lm-bg-paper)" : "var(--lm-bg-elevated)",
2684
+ color: "var(--lm-text-primary)"
2685
+ };
2686
+ if (isSelected) {
2687
+ return {
2688
+ ...baseStyles,
2689
+ borderColor: "var(--lm-primary-200)"
2690
+ };
2691
+ }
2692
+ return baseStyles;
2693
+ };
2694
+ const getPaginationStyles = () => ({
2695
+ backgroundColor: variant === "minimal" ? "transparent" : variant === "soft" ? "var(--lm-bg-paper)" : "var(--lm-bg-elevated)",
2696
+ color: "var(--lm-text-primary)",
2697
+ borderColor: variant === "outline" ? "var(--lm-border-strong)" : "var(--lm-border-default)",
2698
+ boxShadow: variant === "elevated" ? "var(--lm-shadow-md)" : void 0
2699
+ });
2700
+ const getButtonStyles = (disabled = false, active = false) => {
2701
+ if (disabled) {
2702
+ return {
2703
+ backgroundColor: "var(--lm-bg-paper)",
2704
+ color: "var(--lm-text-disabled)",
2705
+ borderColor: "var(--lm-border-light)",
2706
+ cursor: "not-allowed",
2707
+ opacity: 0.6
2708
+ };
2709
+ }
2710
+ if (active) {
2711
+ return {
2712
+ backgroundColor: "var(--lm-primary-500)",
2713
+ color: "white",
2714
+ borderColor: "var(--lm-primary-500)"
2715
+ };
2716
+ }
2717
+ return {
2718
+ backgroundColor: "var(--lm-bg-paper)",
2719
+ color: "var(--lm-text-primary)",
2720
+ borderColor: "var(--lm-border-default)"
2721
+ };
2722
+ };
2723
+ const getLoadingStyles = () => ({
2724
+ color: "var(--lm-text-secondary)"
2725
+ });
2726
+ const getEmptyStyles = () => ({
2727
+ color: "var(--lm-text-secondary)"
2728
+ });
2729
+ const tableClassName = `w-full ${SIZE_TEXT_CLASSES[size]} border-collapse ${className}`.trim().replace(/\s+/g, " ");
2730
+ const isAllSelected = dataSource.length > 0 && selectedRowKeys.length === dataSource.length;
2731
+ const isIndeterminate = selectedRowKeys.length > 0 && selectedRowKeys.length < dataSource.length;
2732
+ const rootClassName = `space-y-4 ${fullHeight ? "h-full flex flex-col min-h-0" : ""}`.trim().replace(/\s+/g, " ");
2733
+ const tableContainerClassName = `${fullHeight ? "flex-1 min-h-0 overflow-auto" : `overflow-auto ${(loadMore == null ? void 0 : loadMore.enabled) ? "max-h-96" : ""}`}`.trim().replace(/\s+/g, " ");
2734
+ const wrapperVariantClasses = (() => {
2735
+ switch (variant) {
2736
+ case "elevated":
2737
+ return "rounded-2xl border shadow-lg";
2738
+ case "outline":
2739
+ return "rounded-xl border";
2740
+ case "soft":
2741
+ return "rounded-xl border";
2742
+ case "minimal":
2743
+ return "rounded-xl";
2744
+ case "zebra":
2745
+ return "rounded-xl border";
2746
+ default:
2747
+ return "";
2748
+ }
2749
+ })();
2750
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: rootClassName, children: [
2751
+ /* @__PURE__ */ jsxRuntime.jsx(
2752
+ "div",
2753
+ {
2754
+ ref: containerRef,
2755
+ className: `${tableContainerClassName} ${wrapperVariantClasses}`,
2756
+ style: { borderColor: "var(--lm-border-default)" },
2757
+ children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: tableClassName, style: getTableStyles(), children: [
2758
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { className: "sticky top-0 z-20", style: getHeaderStyles(), children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
2759
+ selectable && /* @__PURE__ */ jsxRuntime.jsx(
2760
+ "th",
2761
+ {
2762
+ className: `${SIZE_TABLE_CONFIG[size].cellPadding} py-3 ${SIZE_TEXT_CLASSES[size]} text-left ${bordered ? "border-r" : ""} font-semibold`,
2763
+ style: getCellStyles(true),
2764
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2765
+ "input",
2766
+ {
2767
+ type: "checkbox",
2768
+ checked: isAllSelected,
2769
+ ref: (input) => {
2770
+ if (input) input.indeterminate = isIndeterminate;
2771
+ },
2772
+ onChange: (e) => handleSelectAll(e.target.checked),
2773
+ className: "w-4 h-4",
2774
+ style: { accentColor: "var(--lm-primary-500)" }
2775
+ }
2776
+ )
2777
+ }
2778
+ ),
2779
+ columns.map((column) => /* @__PURE__ */ jsxRuntime.jsx(
2780
+ "th",
2781
+ {
2782
+ className: `${SIZE_TABLE_CONFIG[size].cellPadding} py-3 text-left ${bordered ? "border-r" : ""} ${column.sorter ? "cursor-pointer hover:bg-opacity-60" : ""} font-semibold`,
2783
+ style: {
2784
+ ...getCellStyles(true),
2785
+ width: column.width,
2786
+ textAlign: column.align || "left",
2787
+ fontSize: size === "xs" ? "0.8125rem" : size === "sm" ? "0.875rem" : "0.9375rem"
2788
+ },
2789
+ onClick: () => handleSort(column),
2790
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2791
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: column.title }),
2792
+ column.sorter && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col -space-y-1", children: [
2793
+ /* @__PURE__ */ jsxRuntime.jsx(
2794
+ CaretUpIcon,
2795
+ {
2796
+ active: sortField === column.dataIndex && sortOrder === "ascend"
2797
+ }
2798
+ ),
2799
+ /* @__PURE__ */ jsxRuntime.jsx(
2800
+ CaretDownIcon,
2801
+ {
2802
+ active: sortField === column.dataIndex && sortOrder === "descend"
2803
+ }
2804
+ )
2805
+ ] })
2806
+ ] })
2807
+ },
2808
+ column.dataIndex
2809
+ ))
2810
+ ] }) }),
2811
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: loading ? /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx(
2812
+ "td",
2813
+ {
2814
+ colSpan: columns.length + (selectable ? 1 : 0),
2815
+ className: `px-4 py-8 text-center ${SIZE_TEXT_CLASSES[size]}`,
2816
+ style: getLoadingStyles(),
2817
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-2", children: [
2818
+ /* @__PURE__ */ jsxRuntime.jsx(SpinnerIcon, {}),
2819
+ "Loading..."
2820
+ ] })
2821
+ }
2822
+ ) }) : dataSource.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx(
2823
+ "td",
2824
+ {
2825
+ colSpan: columns.length + (selectable ? 1 : 0),
2826
+ className: `px-4 py-8 text-center ${SIZE_TEXT_CLASSES[size]}`,
2827
+ style: getEmptyStyles(),
2828
+ children: emptyText
2829
+ }
2830
+ ) }) : dataSource.map((record, index) => {
2831
+ const key = getRowKey(record, index);
2832
+ const isSelected = selectedRowKeys.includes(key);
2833
+ const isLastRow = index === dataSource.length - 1;
2834
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2835
+ "tr",
2836
+ {
2837
+ className: `${onRowClick ? "cursor-pointer hover:bg-opacity-60" : ""} transition-colors border-t ${isLastRow ? "border-b" : ""}`,
2838
+ style: {
2839
+ ...getRowStyles(index, isSelected),
2840
+ borderColor: "var(--lm-border-light)"
2841
+ },
2842
+ onClick: () => onRowClick == null ? void 0 : onRowClick(record, index),
2843
+ children: [
2844
+ selectable && /* @__PURE__ */ jsxRuntime.jsx(
2845
+ "td",
2846
+ {
2847
+ className: `${SIZE_TABLE_CONFIG[size].cellPadding} ${SIZE_TEXT_CLASSES[size]} ${bordered ? "border-r" : ""}`,
2848
+ style: getCellStyles(),
2849
+ onClick: (e) => e.stopPropagation(),
2850
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2851
+ "input",
2852
+ {
2853
+ type: "checkbox",
2854
+ checked: isSelected,
2855
+ onChange: (e) => handleRowSelect(record, e.target.checked),
2856
+ className: "w-4 h-4",
2857
+ style: { accentColor: "var(--lm-primary-500)" }
2858
+ }
2859
+ )
2860
+ }
2861
+ ),
2862
+ columns.map((column) => /* @__PURE__ */ jsxRuntime.jsx(
2863
+ "td",
2864
+ {
2865
+ className: `${SIZE_TABLE_CONFIG[size].cellPadding} ${SIZE_TEXT_CLASSES[size]} ${bordered ? "border-r" : ""}`,
2866
+ style: {
2867
+ ...getCellStyles(),
2868
+ textAlign: column.align || "left"
2869
+ },
2870
+ children: column.render ? column.render(
2871
+ getValueByDataIndex(record, column.dataIndex),
2872
+ record,
2873
+ index
2874
+ ) : String(getValueByDataIndex(record, column.dataIndex) ?? "")
2875
+ },
2876
+ column.dataIndex
2877
+ ))
2878
+ ]
2879
+ },
2880
+ key
2881
+ );
2882
+ }) })
2883
+ ] })
2884
+ }
2885
+ ),
2886
+ (pagination == null ? void 0 : pagination.showPagination) && /* @__PURE__ */ jsxRuntime.jsx(
2887
+ "div",
2888
+ {
2889
+ className: `flex items-center justify-between ${paginationUiClasses[size].container} rounded-2xl border`,
2890
+ style: getPaginationStyles(),
2891
+ children: (() => {
2892
+ var _a;
2893
+ const maxButtons = 5;
2894
+ const half = Math.floor(maxButtons / 2);
2895
+ let start = Math.max(1, currentPage - half);
2896
+ const end = Math.min(totalPages, start + maxButtons - 1);
2897
+ if (end - start + 1 < maxButtons) {
2898
+ start = Math.max(1, end - maxButtons + 1);
2899
+ }
2900
+ const pageNumbers = Array.from({ length: end - start + 1 }, (_, i) => start + i);
2901
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2902
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4", children: [
2903
+ pagination.showTotal && /* @__PURE__ */ jsxRuntime.jsxs(
2904
+ "span",
2905
+ {
2906
+ className: paginationUiClasses[size].text,
2907
+ style: { color: "var(--lm-text-secondary)" },
2908
+ children: [
2909
+ "Total ",
2910
+ pagination.total,
2911
+ " items / ",
2912
+ totalPages,
2913
+ " pages"
2914
+ ]
2915
+ }
2916
+ ),
2917
+ pagination.showSizeChanger && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2918
+ /* @__PURE__ */ jsxRuntime.jsx(
2919
+ "span",
2920
+ {
2921
+ className: paginationUiClasses[size].text,
2922
+ style: { color: "var(--lm-text-secondary)" },
2923
+ children: "Show:"
2924
+ }
2925
+ ),
2926
+ /* @__PURE__ */ jsxRuntime.jsx(
2927
+ "select",
2928
+ {
2929
+ value: pageSize,
2930
+ onChange: (e) => handlePageSizeChange(Number(e.target.value)),
2931
+ className: `${paginationUiClasses[size].select} border rounded-lg focus:ring-2 focus:ring-primary-400 focus:outline-none`,
2932
+ style: {
2933
+ backgroundColor: "var(--lm-bg-paper)",
2934
+ color: "var(--lm-text-primary)",
2935
+ borderColor: "var(--lm-border-default)"
2936
+ },
2937
+ children: (_a = pagination.pageSizeOptions) == null ? void 0 : _a.map((s) => /* @__PURE__ */ jsxRuntime.jsxs("option", { value: s, children: [
2938
+ s,
2939
+ " / page"
2940
+ ] }, s))
2941
+ }
2942
+ )
2943
+ ] })
2944
+ ] }),
2945
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex items-center ${paginationUiClasses[size].gap}`, children: [
2946
+ /* @__PURE__ */ jsxRuntime.jsx(
2947
+ "button",
2948
+ {
2949
+ onClick: () => handlePageChange(currentPage - 1),
2950
+ disabled: currentPage <= 1,
2951
+ className: `${paginationUiClasses[size].control} border rounded-lg transition-colors`,
2952
+ style: getButtonStyles(currentPage <= 1),
2953
+ "aria-label": "Previous page",
2954
+ title: "Previous page",
2955
+ children: /* @__PURE__ */ jsxRuntime.jsx(ChevronLeftIcon, {})
2956
+ }
2957
+ ),
2958
+ pageNumbers.map((page) => /* @__PURE__ */ jsxRuntime.jsx(
2959
+ "button",
2960
+ {
2961
+ onClick: () => handlePageChange(page),
2962
+ className: `${paginationUiClasses[size].control} border rounded-lg transition-colors ${currentPage === page ? "font-medium" : ""}`,
2963
+ style: getButtonStyles(false, currentPage === page),
2964
+ children: page
2965
+ },
2966
+ page
2967
+ )),
2968
+ /* @__PURE__ */ jsxRuntime.jsx(
2969
+ "button",
2970
+ {
2971
+ onClick: () => handlePageChange(currentPage + 1),
2972
+ disabled: currentPage >= totalPages,
2973
+ className: `${paginationUiClasses[size].control} border rounded-lg transition-colors`,
2974
+ style: getButtonStyles(currentPage >= totalPages),
2975
+ "aria-label": "Next page",
2976
+ title: "Next page",
2977
+ children: /* @__PURE__ */ jsxRuntime.jsx(ChevronRightIcon, {})
2978
+ }
2979
+ ),
2980
+ pagination.showQuickJumper && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex items-center ${paginationUiClasses[size].gap} ml-4`, children: [
2981
+ /* @__PURE__ */ jsxRuntime.jsx(
2982
+ "span",
2983
+ {
2984
+ className: paginationUiClasses[size].text,
2985
+ style: { color: "var(--lm-text-secondary)" },
2986
+ children: "Go to:"
2987
+ }
2988
+ ),
2989
+ /* @__PURE__ */ jsxRuntime.jsx(
2990
+ "input",
2991
+ {
2992
+ type: "number",
2993
+ min: 1,
2994
+ max: totalPages,
2995
+ className: `${paginationUiClasses[size].input} border rounded-lg focus:ring-2 focus:ring-primary-400 focus:outline-none`,
2996
+ style: {
2997
+ backgroundColor: "var(--lm-bg-paper)",
2998
+ color: "var(--lm-text-primary)",
2999
+ borderColor: "var(--lm-border-default)"
3000
+ },
3001
+ onKeyDown: (e) => {
3002
+ if (e.key === "Enter") {
3003
+ const page = Number(e.currentTarget.value);
3004
+ if (page >= 1 && page <= totalPages) {
3005
+ handlePageChange(page);
3006
+ }
3007
+ }
3008
+ }
3009
+ }
3010
+ )
3011
+ ] })
3012
+ ] })
3013
+ ] });
3014
+ })()
3015
+ }
3016
+ ),
3017
+ (loadMore == null ? void 0 : loadMore.enabled) && loadMore.hasMore && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-center py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
3018
+ "button",
3019
+ {
3020
+ onClick: loadMore.onLoadMore,
3021
+ disabled: loadMore.loading,
3022
+ className: "px-6 py-2 text-sm border rounded-2xl transition-colors",
3023
+ style: getButtonStyles(loadMore.loading),
3024
+ children: loadMore.loading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
3025
+ /* @__PURE__ */ jsxRuntime.jsx(SpinnerIcon, {}),
3026
+ "Loading..."
3027
+ ] }) : "Load more"
3028
+ }
3029
+ ) })
3030
+ ] });
3031
+ };
3032
+ const LMTable_default = React.memo(LMTable);
3033
+ const ICONS = {
3034
+ success: /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", className: "h-5 w-5", "aria-hidden": "true", children: [
3035
+ /* @__PURE__ */ jsxRuntime.jsx(
3036
+ "path",
3037
+ {
3038
+ d: "M12 22a10 10 0 1 1 0-20 10 10 0 0 1 0 20Z",
3039
+ fill: "currentColor",
3040
+ opacity: "0.15"
3041
+ }
3042
+ ),
3043
+ /* @__PURE__ */ jsxRuntime.jsx(
3044
+ "path",
3045
+ {
3046
+ d: "M16.7 9.3a1 1 0 0 0-1.4-1.4L11 12.2 8.7 9.9a1 1 0 1 0-1.4 1.4l3 3a1 1 0 0 0 1.4 0l5-5Z",
3047
+ fill: "currentColor"
3048
+ }
3049
+ )
3050
+ ] }),
3051
+ error: /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", className: "h-5 w-5", "aria-hidden": "true", children: [
3052
+ /* @__PURE__ */ jsxRuntime.jsx(
3053
+ "path",
3054
+ {
3055
+ d: "M12 22c5.5 0 10-4.5 10-10S17.5 2 12 2 2 6.5 2 12s4.5 10 10 10Z",
3056
+ fill: "currentColor",
3057
+ opacity: "0.15"
3058
+ }
3059
+ ),
3060
+ /* @__PURE__ */ jsxRuntime.jsx(
3061
+ "path",
3062
+ {
3063
+ d: "M15.5 8.5l-7 7M8.5 8.5l7 7",
3064
+ stroke: "currentColor",
3065
+ strokeWidth: "1.8",
3066
+ strokeLinecap: "round"
3067
+ }
3068
+ )
3069
+ ] }),
3070
+ warning: /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", className: "h-5 w-5", "aria-hidden": "true", children: [
3071
+ /* @__PURE__ */ jsxRuntime.jsx(
3072
+ "path",
3073
+ {
3074
+ d: "M12.9 4.5c-.4-.7-1.4-.7-1.8 0L3.5 18a1 1 0 0 0 .9 1.5h15.2a1 1 0 0 0 .9-1.5l-7.6-13.5Z",
3075
+ fill: "currentColor",
3076
+ opacity: "0.15"
3077
+ }
3078
+ ),
3079
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 9v5", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" }),
3080
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "16.5", r: "1", fill: "currentColor" })
3081
+ ] }),
3082
+ info: /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", className: "h-5 w-5", "aria-hidden": "true", children: [
3083
+ /* @__PURE__ */ jsxRuntime.jsx(
3084
+ "path",
3085
+ {
3086
+ d: "M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20Z",
3087
+ fill: "currentColor",
3088
+ opacity: "0.15"
3089
+ }
3090
+ ),
3091
+ /* @__PURE__ */ jsxRuntime.jsx(
3092
+ "path",
3093
+ {
3094
+ d: "M12 10.5v5M12 7.5h.01",
3095
+ stroke: "currentColor",
3096
+ strokeWidth: "1.8",
3097
+ strokeLinecap: "round"
3098
+ }
3099
+ )
3100
+ ] })
3101
+ };
3102
+ const useTone = (type) => {
3103
+ switch (type) {
3104
+ case "success":
3105
+ return {
3106
+ accent: "var(--lm-success-500)",
3107
+ background: "color-mix(in srgb, var(--lm-success-100) 60%, transparent)",
3108
+ text: "var(--lm-success-700)",
3109
+ title: "var(--lm-success-800)"
3110
+ };
3111
+ case "error":
3112
+ return {
3113
+ accent: "var(--lm-error-500)",
3114
+ background: "color-mix(in srgb, var(--lm-error-100) 60%, transparent)",
3115
+ text: "var(--lm-error-700)",
3116
+ title: "var(--lm-error-800)"
3117
+ };
3118
+ case "warning":
3119
+ return {
3120
+ accent: "var(--lm-warning-500)",
3121
+ background: "color-mix(in srgb, var(--lm-warning-100) 60%, transparent)",
3122
+ text: "var(--lm-warning-700)",
3123
+ title: "var(--lm-warning-800)"
3124
+ };
3125
+ case "info":
3126
+ default:
3127
+ return {
3128
+ accent: "var(--lm-primary-500)",
3129
+ background: "color-mix(in srgb, var(--lm-primary-100) 60%, transparent)",
3130
+ text: "var(--lm-primary-700)",
3131
+ title: "var(--lm-primary-800)"
3132
+ };
3133
+ }
3134
+ };
3135
+ const LMMessage = ({ id, type, title, content, duration = 2e3, onClose }) => {
3136
+ const tone = useTone(type);
3137
+ React.useEffect(() => {
3138
+ if (duration <= 0) return;
3139
+ const timer = setTimeout(() => onClose(id), duration);
3140
+ return () => clearTimeout(timer);
3141
+ }, [id, duration, onClose]);
3142
+ const icon = React.useMemo(() => ICONS[type], [type]);
3143
+ const ariaRole = "status";
3144
+ const ariaLabel = React.useMemo(() => {
3145
+ switch (type) {
3146
+ case "success":
3147
+ return "Success message";
3148
+ case "error":
3149
+ return "Error message";
3150
+ case "warning":
3151
+ return "Warning message";
3152
+ default:
3153
+ return "Information message";
3154
+ }
3155
+ }, [type]);
3156
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-sm mx-auto will-change-transform", role: ariaRole, "aria-label": ariaLabel, children: /* @__PURE__ */ jsxRuntime.jsx(
3157
+ "div",
3158
+ {
3159
+ className: "rounded-3xl shadow-lg p-5 mb-3 backdrop-blur-md border transition-all duration-300 ease-out",
3160
+ style: {
3161
+ backgroundColor: tone.background,
3162
+ borderColor: "var(--lm-border-light)",
3163
+ boxShadow: "var(--lm-shadow-lg)"
3164
+ },
3165
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-4", children: [
3166
+ /* @__PURE__ */ jsxRuntime.jsx(
3167
+ "div",
3168
+ {
3169
+ className: "mt-0.5 flex h-10 w-10 items-center justify-center rounded-2xl",
3170
+ style: {
3171
+ color: tone.accent,
3172
+ backgroundColor: "color-mix(in srgb, currentColor 12%, transparent)"
3173
+ },
3174
+ children: icon
3175
+ }
3176
+ ),
3177
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
3178
+ title && /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "text-sm font-semibold mb-2 truncate", style: { color: tone.title }, children: title }),
3179
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm leading-relaxed break-words", style: { color: tone.text }, children: content })
3180
+ ] }),
3181
+ /* @__PURE__ */ jsxRuntime.jsx(
3182
+ "button",
3183
+ {
3184
+ onClick: () => onClose(id),
3185
+ "aria-label": "Close message",
3186
+ className: "flex-shrink-0 p-2 rounded-xl transition-all duration-200 hover:bg-black/5 active:bg-black/10",
3187
+ style: { color: tone.accent },
3188
+ children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", className: "h-4 w-4", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(
3189
+ "path",
3190
+ {
3191
+ d: "M6 6l12 12M18 6L6 18",
3192
+ stroke: "currentColor",
3193
+ strokeWidth: "2",
3194
+ strokeLinecap: "round"
3195
+ }
3196
+ ) })
3197
+ }
3198
+ )
3199
+ ] })
3200
+ }
3201
+ ) });
3202
+ };
3203
+ const LMMessageContainer = ({
3204
+ messages,
3205
+ onClose,
3206
+ position = "top-right"
3207
+ }) => {
3208
+ if (messages.length === 0) return null;
3209
+ const positionClasses = {
3210
+ "top-right": "top-20 right-6",
3211
+ "top-left": "top-20 left-6",
3212
+ "top-center": "top-20 left-1/2 -translate-x-1/2",
3213
+ "bottom-right": "bottom-6 right-6",
3214
+ "bottom-left": "bottom-6 left-6",
3215
+ "bottom-center": "bottom-6 left-1/2 -translate-x-1/2"
3216
+ };
3217
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `fixed z-50 space-y-3 ${positionClasses[position]}`, children: messages.map((message) => /* @__PURE__ */ jsxRuntime.jsx(LMMessage, { ...message, onClose }, message.id)) });
3218
+ };
3219
+ let messageIdCounter = 0;
3220
+ const useMessage = () => {
3221
+ const [messages, setMessages] = React.useState([]);
3222
+ const addMessage = React.useCallback((message) => {
3223
+ const id = `lm-message-${++messageIdCounter}`;
3224
+ setMessages((prev) => [...prev, { ...message, id }]);
3225
+ return id;
3226
+ }, []);
3227
+ const removeMessage = React.useCallback((id) => {
3228
+ setMessages((prev) => prev.filter((m) => m.id !== id));
3229
+ }, []);
3230
+ const success = React.useCallback(
3231
+ (content, title, duration) => {
3232
+ return addMessage({ type: "success", content, title, duration });
3233
+ },
3234
+ [addMessage]
3235
+ );
3236
+ const error = React.useCallback(
3237
+ (content, title, duration) => {
3238
+ return addMessage({ type: "error", content, title, duration });
3239
+ },
3240
+ [addMessage]
3241
+ );
3242
+ const warning = React.useCallback(
3243
+ (content, title, duration) => {
3244
+ return addMessage({ type: "warning", content, title, duration });
3245
+ },
3246
+ [addMessage]
3247
+ );
3248
+ const info = React.useCallback(
3249
+ (content, title, duration) => {
3250
+ return addMessage({ type: "info", content, title, duration });
3251
+ },
3252
+ [addMessage]
3253
+ );
3254
+ const clearAll = React.useCallback(() => {
3255
+ setMessages([]);
3256
+ }, []);
3257
+ return {
3258
+ messages,
3259
+ addMessage,
3260
+ removeMessage,
3261
+ success,
3262
+ error,
3263
+ warning,
3264
+ info,
3265
+ clearAll
3266
+ };
3267
+ };
3268
+ const QuestionIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", className: "w-6 h-6", fill: "none", stroke: "currentColor", strokeWidth: 2, children: [
3269
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10" }),
3270
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3", strokeLinecap: "round", strokeLinejoin: "round" }),
3271
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 17h.01", strokeLinecap: "round", strokeLinejoin: "round" })
3272
+ ] });
3273
+ const LMConfirm = ({
3274
+ visible,
3275
+ title = "Confirm",
3276
+ content,
3277
+ confirmText = "Confirm",
3278
+ cancelText = "Cancel",
3279
+ confirmButtonStyle = "primary",
3280
+ onConfirm,
3281
+ onCancel,
3282
+ closeOnOverlayClick = true
3283
+ }) => {
3284
+ const [isVisible, setIsVisible] = React.useState(false);
3285
+ const [isAnimating, setIsAnimating] = React.useState(false);
3286
+ React.useEffect(() => {
3287
+ if (visible) {
3288
+ setIsVisible(true);
3289
+ requestAnimationFrame(() => {
3290
+ setIsAnimating(true);
3291
+ });
3292
+ } else {
3293
+ setIsAnimating(false);
3294
+ const timer = setTimeout(() => {
3295
+ setIsVisible(false);
3296
+ }, 200);
3297
+ return () => clearTimeout(timer);
3298
+ }
3299
+ }, [visible]);
3300
+ const getConfirmButtonStyles = () => {
3301
+ switch (confirmButtonStyle) {
3302
+ case "primary":
3303
+ return {
3304
+ backgroundColor: "var(--lm-primary-500)",
3305
+ color: "var(--lm-text-inverse)"
3306
+ };
3307
+ case "danger":
3308
+ return {
3309
+ backgroundColor: "var(--lm-error-500)",
3310
+ color: "var(--lm-text-inverse)"
3311
+ };
3312
+ }
3313
+ };
3314
+ const getConfirmButtonHoverStyles = () => {
3315
+ switch (confirmButtonStyle) {
3316
+ case "primary":
3317
+ return {
3318
+ backgroundColor: "var(--lm-primary-600)"
3319
+ };
3320
+ case "danger":
3321
+ return {
3322
+ backgroundColor: "var(--lm-error-600)"
3323
+ };
3324
+ }
3325
+ };
3326
+ const handleOverlayClick = () => {
3327
+ if (closeOnOverlayClick) {
3328
+ onCancel();
3329
+ }
3330
+ };
3331
+ if (!isVisible) return null;
3332
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fixed inset-0 z-50 flex items-center justify-center px-4", children: [
3333
+ /* @__PURE__ */ jsxRuntime.jsx(
3334
+ "div",
3335
+ {
3336
+ className: `absolute inset-0 backdrop-blur-sm transition-opacity duration-200 ${isAnimating ? "opacity-100" : "opacity-0"}`,
3337
+ style: {
3338
+ backgroundColor: "rgba(0, 0, 0, 0.2)"
3339
+ },
3340
+ onClick: handleOverlayClick
3341
+ }
3342
+ ),
3343
+ /* @__PURE__ */ jsxRuntime.jsxs(
3344
+ "div",
3345
+ {
3346
+ className: `relative backdrop-blur-xl rounded-3xl shadow-2xl border p-8 max-w-md w-full mx-auto transition-all duration-200 ${isAnimating ? "opacity-100 scale-100" : "opacity-0 scale-95"}`,
3347
+ style: {
3348
+ backgroundColor: "var(--lm-bg-elevated)",
3349
+ borderColor: "var(--lm-border-default)",
3350
+ boxShadow: "var(--lm-shadow-xl)"
3351
+ },
3352
+ children: [
3353
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center mb-6", children: [
3354
+ /* @__PURE__ */ jsxRuntime.jsx(
3355
+ "div",
3356
+ {
3357
+ className: "inline-flex items-center justify-center w-16 h-16 rounded-full mb-4",
3358
+ style: {
3359
+ backgroundColor: "var(--lm-gray-100)"
3360
+ },
3361
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--lm-gray-600)" }, children: /* @__PURE__ */ jsxRuntime.jsx(QuestionIcon, {}) })
3362
+ }
3363
+ ),
3364
+ /* @__PURE__ */ jsxRuntime.jsx(
3365
+ "h3",
3366
+ {
3367
+ className: "text-xl font-semibold mb-2",
3368
+ style: {
3369
+ color: "var(--lm-text-primary)"
3370
+ },
3371
+ children: title
3372
+ }
3373
+ ),
3374
+ /* @__PURE__ */ jsxRuntime.jsx(
3375
+ "p",
3376
+ {
3377
+ className: "text-sm leading-relaxed",
3378
+ style: {
3379
+ color: "var(--lm-text-secondary)"
3380
+ },
3381
+ children: content
3382
+ }
3383
+ )
3384
+ ] }),
3385
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex space-x-3", children: [
3386
+ /* @__PURE__ */ jsxRuntime.jsx(
3387
+ "button",
3388
+ {
3389
+ onClick: onCancel,
3390
+ className: "flex-1 py-3 px-4 font-medium rounded-xl transition-all duration-200 hover:scale-[1.02] active:scale-[0.98]",
3391
+ style: {
3392
+ backgroundColor: "var(--lm-gray-100)",
3393
+ color: "var(--lm-text-primary)"
3394
+ },
3395
+ onMouseEnter: (e) => {
3396
+ e.currentTarget.style.backgroundColor = "var(--lm-gray-200)";
3397
+ },
3398
+ onMouseLeave: (e) => {
3399
+ e.currentTarget.style.backgroundColor = "var(--lm-gray-100)";
3400
+ },
3401
+ children: cancelText
3402
+ }
3403
+ ),
3404
+ /* @__PURE__ */ jsxRuntime.jsx(
3405
+ "button",
3406
+ {
3407
+ onClick: onConfirm,
3408
+ className: "flex-1 py-3 px-4 font-medium rounded-xl transition-all duration-200 hover:scale-[1.02] active:scale-[0.98]",
3409
+ style: getConfirmButtonStyles(),
3410
+ onMouseEnter: (e) => {
3411
+ const hoverStyles = getConfirmButtonHoverStyles();
3412
+ e.currentTarget.style.backgroundColor = (hoverStyles == null ? void 0 : hoverStyles.backgroundColor) || "";
3413
+ },
3414
+ onMouseLeave: (e) => {
3415
+ const normalStyles = getConfirmButtonStyles();
3416
+ e.currentTarget.style.backgroundColor = (normalStyles == null ? void 0 : normalStyles.backgroundColor) || "";
3417
+ },
3418
+ children: confirmText
3419
+ }
3420
+ )
3421
+ ] })
3422
+ ]
3423
+ }
3424
+ )
3425
+ ] });
3426
+ };
3427
+ const useConfirm = () => {
3428
+ const [visible, setVisible] = React.useState(false);
3429
+ const [config, setConfig] = React.useState(null);
3430
+ const [resolveRef, setResolveRef] = React.useState(null);
3431
+ const confirm = React.useCallback((options) => {
3432
+ return new Promise((resolve) => {
3433
+ setConfig(options);
3434
+ setVisible(true);
3435
+ setResolveRef(() => resolve);
3436
+ });
3437
+ }, []);
3438
+ const handleConfirm = React.useCallback(() => {
3439
+ setVisible(false);
3440
+ resolveRef == null ? void 0 : resolveRef(true);
3441
+ setResolveRef(null);
3442
+ }, [resolveRef]);
3443
+ const handleCancel = React.useCallback(() => {
3444
+ setVisible(false);
3445
+ resolveRef == null ? void 0 : resolveRef(false);
3446
+ setResolveRef(null);
3447
+ }, [resolveRef]);
3448
+ const ConfirmDialog = React.useCallback(() => {
3449
+ if (!config) return null;
3450
+ return /* @__PURE__ */ jsxRuntime.jsx(
3451
+ LMConfirm,
3452
+ {
3453
+ visible,
3454
+ ...config,
3455
+ onConfirm: handleConfirm,
3456
+ onCancel: handleCancel
3457
+ }
3458
+ );
3459
+ }, [visible, config, handleConfirm, handleCancel]);
3460
+ return {
3461
+ visible,
3462
+ config,
3463
+ confirm,
3464
+ ConfirmDialog
3465
+ };
3466
+ };
3467
+ const ArrowUpIcon = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-3 h-3", viewBox: "0 0 12 12", fill: "none", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 10V2M6 2l4 4M6 2L2 6" }) });
3468
+ const ArrowDownIcon = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-3 h-3", viewBox: "0 0 12 12", fill: "none", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 2v8M6 10l4-4M6 10l-4-4" }) });
3469
+ const MinusIcon = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-3 h-3", viewBox: "0 0 12 12", fill: "none", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M2 6h8" }) });
3470
+ const LMStatCard = ({
3471
+ title,
3472
+ value,
3473
+ description,
3474
+ icon,
3475
+ trend,
3476
+ trendText,
3477
+ variant = "default",
3478
+ size = "md",
3479
+ clickable = false,
3480
+ onClick,
3481
+ className = "",
3482
+ prefix,
3483
+ suffix,
3484
+ bordered = true,
3485
+ shadow = true,
3486
+ compact = false
3487
+ }) => {
3488
+ const resolvedSize = clampComponentSize(size, COMPONENT_SIZE_ORDER);
3489
+ const iconSizeClasses = compact ? {
3490
+ xs: "w-4 h-4",
3491
+ sm: "w-5 h-5",
3492
+ md: "w-6 h-6",
3493
+ lg: "w-8 h-8",
3494
+ xl: "w-10 h-10",
3495
+ "2xl": "w-12 h-12"
3496
+ } : {
3497
+ xs: "w-5 h-5",
3498
+ sm: "w-6 h-6",
3499
+ md: "w-10 h-10",
3500
+ lg: "w-12 h-12",
3501
+ xl: "w-14 h-14",
3502
+ "2xl": "w-16 h-16"
3503
+ };
3504
+ const titleTextClasses = compact ? {
3505
+ xs: "text-[10px]",
3506
+ sm: "text-[10px]",
3507
+ md: "text-xs",
3508
+ lg: "text-sm",
3509
+ xl: "text-base",
3510
+ "2xl": "text-lg"
3511
+ } : {
3512
+ xs: "text-xs",
3513
+ sm: "text-xs",
3514
+ md: "text-sm",
3515
+ lg: "text-base",
3516
+ xl: "text-lg",
3517
+ "2xl": "text-xl"
3518
+ };
3519
+ const metaTextClasses = compact ? {
3520
+ xs: "text-[10px]",
3521
+ sm: "text-[10px]",
3522
+ md: "text-[10px]",
3523
+ lg: "text-[10px]",
3524
+ xl: "text-xs",
3525
+ "2xl": "text-xs"
3526
+ } : {
3527
+ xs: "text-xs",
3528
+ sm: "text-xs",
3529
+ md: "text-sm",
3530
+ lg: "text-sm",
3531
+ xl: "text-base",
3532
+ "2xl": "text-lg"
3533
+ };
3534
+ const descriptionTextClasses = {
3535
+ xs: "text-xs",
3536
+ sm: "text-xs",
3537
+ md: "text-xs",
3538
+ lg: "text-xs",
3539
+ xl: "text-xs",
3540
+ "2xl": "text-xs"
3541
+ };
3542
+ const valueTextClasses = compact ? {
3543
+ xs: "text-sm",
3544
+ sm: "text-base",
3545
+ md: "text-lg",
3546
+ lg: "text-xl",
3547
+ xl: "text-2xl",
3548
+ "2xl": "text-3xl"
3549
+ } : {
3550
+ xs: "text-lg",
3551
+ sm: "text-xl",
3552
+ md: "text-3xl",
3553
+ lg: "text-4xl",
3554
+ xl: "text-5xl",
3555
+ "2xl": "text-6xl"
3556
+ };
3557
+ const roundedClasses = "rounded-2xl";
3558
+ const borderClasses = bordered ? "border" : "";
3559
+ const shadowClasses = shadow ? "shadow-sm" : "";
3560
+ const clickableClasses = clickable ? "cursor-pointer transition-transform hover:scale-105" : "";
3561
+ const baseClassName = `
3562
+ ${SIZE_PADDING_CLASSES[resolvedSize]} ${roundedClasses} ${borderClasses} ${shadowClasses} ${clickableClasses}
3563
+ backdrop-blur-md transition-all duration-300
3564
+ ${className}
3565
+ `.trim().replace(/\s+/g, " ");
3566
+ const getCardStyles = () => {
3567
+ const baseStyles = {
3568
+ backgroundColor: "var(--lm-bg-elevated)",
3569
+ color: "var(--lm-text-primary)",
3570
+ borderColor: "var(--lm-border-default)",
3571
+ boxShadow: "var(--lm-shadow-sm)"
3572
+ };
3573
+ switch (variant) {
3574
+ case "primary":
3575
+ return {
3576
+ ...baseStyles,
3577
+ backgroundColor: "var(--lm-primary-50)",
3578
+ borderColor: "var(--lm-primary-200)"
3579
+ };
3580
+ case "success":
3581
+ return {
3582
+ ...baseStyles,
3583
+ backgroundColor: "var(--lm-success-50)",
3584
+ borderColor: "var(--lm-success-200)"
3585
+ };
3586
+ case "warning":
3587
+ return {
3588
+ ...baseStyles,
3589
+ backgroundColor: "var(--lm-warning-50)",
3590
+ borderColor: "var(--lm-warning-200)"
3591
+ };
3592
+ case "error":
3593
+ return {
3594
+ ...baseStyles,
3595
+ backgroundColor: "var(--lm-error-50)",
3596
+ borderColor: "var(--lm-error-200)"
3597
+ };
3598
+ case "info":
3599
+ return {
3600
+ ...baseStyles,
3601
+ backgroundColor: "var(--lm-gray-50)",
3602
+ borderColor: "var(--lm-gray-200)"
3603
+ };
3604
+ default:
3605
+ return baseStyles;
3606
+ }
3607
+ };
3608
+ const getHoverStyles = () => {
3609
+ if (!clickable) return {};
3610
+ switch (variant) {
3611
+ case "primary":
3612
+ return {
3613
+ backgroundColor: "var(--lm-primary-100)",
3614
+ borderColor: "var(--lm-primary-300)",
3615
+ boxShadow: "var(--lm-shadow-md)"
3616
+ };
3617
+ case "success":
3618
+ return {
3619
+ backgroundColor: "var(--lm-success-100)",
3620
+ borderColor: "var(--lm-success-300)",
3621
+ boxShadow: "var(--lm-shadow-md)"
3622
+ };
3623
+ case "warning":
3624
+ return {
3625
+ backgroundColor: "var(--lm-warning-100)",
3626
+ borderColor: "var(--lm-warning-300)",
3627
+ boxShadow: "var(--lm-shadow-md)"
3628
+ };
3629
+ case "error":
3630
+ return {
3631
+ backgroundColor: "var(--lm-error-100)",
3632
+ borderColor: "var(--lm-error-300)",
3633
+ boxShadow: "var(--lm-shadow-md)"
3634
+ };
3635
+ case "info":
3636
+ return {
3637
+ backgroundColor: "var(--lm-gray-100)",
3638
+ borderColor: "var(--lm-gray-300)",
3639
+ boxShadow: "var(--lm-shadow-md)"
3640
+ };
3641
+ default:
3642
+ return {
3643
+ backgroundColor: "var(--lm-bg-paper)",
3644
+ borderColor: "var(--lm-border-strong)",
3645
+ boxShadow: "var(--lm-shadow-md)"
3646
+ };
3647
+ }
3648
+ };
3649
+ const getIconStyles = () => {
3650
+ switch (variant) {
3651
+ case "primary":
3652
+ return {
3653
+ color: "var(--lm-primary-600)",
3654
+ backgroundColor: "var(--lm-primary-100)"
3655
+ };
3656
+ case "success":
3657
+ return {
3658
+ color: "var(--lm-success-600)",
3659
+ backgroundColor: "var(--lm-success-100)"
3660
+ };
3661
+ case "warning":
3662
+ return {
3663
+ color: "var(--lm-warning-600)",
3664
+ backgroundColor: "var(--lm-warning-100)"
3665
+ };
3666
+ case "error":
3667
+ return {
3668
+ color: "var(--lm-error-600)",
3669
+ backgroundColor: "var(--lm-error-100)"
3670
+ };
3671
+ case "info":
3672
+ return {
3673
+ color: "var(--lm-gray-600)",
3674
+ backgroundColor: "var(--lm-gray-100)"
3675
+ };
3676
+ default:
3677
+ return {
3678
+ color: "var(--lm-primary-600)",
3679
+ backgroundColor: "var(--lm-bg-paper)"
3680
+ };
3681
+ }
3682
+ };
3683
+ const getValueStyles = () => {
3684
+ switch (variant) {
3685
+ case "primary":
3686
+ return { color: "var(--lm-primary-700)" };
3687
+ case "success":
3688
+ return { color: "var(--lm-success-700)" };
3689
+ case "warning":
3690
+ return { color: "var(--lm-warning-700)" };
3691
+ case "error":
3692
+ return { color: "var(--lm-error-700)" };
3693
+ case "info":
3694
+ return { color: "var(--lm-gray-700)" };
3695
+ default:
3696
+ return { color: "var(--lm-text-primary)" };
3697
+ }
3698
+ };
3699
+ const getTrendStyles = () => {
3700
+ if (trend == null) return {};
3701
+ if (trend > 0) return { color: "var(--lm-success-600)" };
3702
+ if (trend < 0) return { color: "var(--lm-error-600)" };
3703
+ return { color: "var(--lm-text-secondary)" };
3704
+ };
3705
+ const getTrendIcon = () => {
3706
+ if (trend == null) return null;
3707
+ if (trend > 0) return /* @__PURE__ */ jsxRuntime.jsx(ArrowUpIcon, {});
3708
+ if (trend < 0) return /* @__PURE__ */ jsxRuntime.jsx(ArrowDownIcon, {});
3709
+ return /* @__PURE__ */ jsxRuntime.jsx(MinusIcon, {});
3710
+ };
3711
+ const handleKeyDown = (e) => {
3712
+ if (!clickable) return;
3713
+ if (e.key === "Enter" || e.key === " ") {
3714
+ e.preventDefault();
3715
+ onClick == null ? void 0 : onClick();
3716
+ }
3717
+ };
3718
+ return /* @__PURE__ */ jsxRuntime.jsx(
3719
+ "div",
3720
+ {
3721
+ className: baseClassName,
3722
+ style: getCardStyles(),
3723
+ onClick: clickable ? onClick : void 0,
3724
+ onKeyDown: handleKeyDown,
3725
+ onMouseEnter: (e) => {
3726
+ if (clickable) Object.assign(e.currentTarget.style, getHoverStyles());
3727
+ },
3728
+ onMouseLeave: (e) => {
3729
+ if (clickable) Object.assign(e.currentTarget.style, getCardStyles());
3730
+ },
3731
+ role: clickable ? "button" : void 0,
3732
+ tabIndex: clickable ? 0 : void 0,
3733
+ "aria-label": clickable ? title : void 0,
3734
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-start justify-between overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
3735
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-2 min-w-0", children: [
3736
+ icon && /* @__PURE__ */ jsxRuntime.jsx(
3737
+ "div",
3738
+ {
3739
+ className: `${iconSizeClasses[resolvedSize]} rounded-lg flex items-center justify-center flex-shrink-0`,
3740
+ style: getIconStyles(),
3741
+ children: icon
3742
+ }
3743
+ ),
3744
+ /* @__PURE__ */ jsxRuntime.jsx(
3745
+ "h3",
3746
+ {
3747
+ className: `${titleTextClasses[resolvedSize]} font-medium truncate`,
3748
+ style: { color: "var(--lm-text-secondary)" },
3749
+ title,
3750
+ children: title
3751
+ }
3752
+ )
3753
+ ] }),
3754
+ /* @__PURE__ */ jsxRuntime.jsxs(
3755
+ "div",
3756
+ {
3757
+ className: `flex items-baseline ${SIZE_GAP_CLASSES[resolvedSize]} min-w-0 overflow-hidden w-full`,
3758
+ children: [
3759
+ prefix && /* @__PURE__ */ jsxRuntime.jsx(
3760
+ "span",
3761
+ {
3762
+ className: `${metaTextClasses[resolvedSize]} flex-shrink-0`,
3763
+ style: { color: "var(--lm-text-secondary)" },
3764
+ children: prefix
3765
+ }
3766
+ ),
3767
+ /* @__PURE__ */ jsxRuntime.jsx(
3768
+ "span",
3769
+ {
3770
+ className: `font-bold ${valueTextClasses[resolvedSize]} overflow-hidden`,
3771
+ style: getValueStyles(),
3772
+ children: value
3773
+ }
3774
+ ),
3775
+ suffix && /* @__PURE__ */ jsxRuntime.jsx(
3776
+ "span",
3777
+ {
3778
+ className: `${metaTextClasses[resolvedSize]} flex-shrink-0`,
3779
+ style: { color: "var(--lm-text-secondary)" },
3780
+ children: suffix
3781
+ }
3782
+ )
3783
+ ]
3784
+ }
3785
+ ),
3786
+ description && /* @__PURE__ */ jsxRuntime.jsx(
3787
+ "p",
3788
+ {
3789
+ className: `${descriptionTextClasses[resolvedSize]} mt-1 truncate`,
3790
+ style: { color: "var(--lm-text-secondary)" },
3791
+ title: description,
3792
+ children: description
3793
+ }
3794
+ ),
3795
+ (trend != null || trendText) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex items-center ${SIZE_GAP_CLASSES[resolvedSize]} mt-2`, children: [
3796
+ trend != null && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", style: getTrendStyles(), children: [
3797
+ getTrendIcon(),
3798
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm font-medium", children: [
3799
+ Math.abs(trend),
3800
+ "%"
3801
+ ] })
3802
+ ] }),
3803
+ trendText && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", style: { color: "var(--lm-text-secondary)" }, children: trendText })
3804
+ ] })
3805
+ ] }) })
3806
+ }
3807
+ );
3808
+ };
3809
+ function cn(...inputs) {
3810
+ return inputs.flat().filter((x) => typeof x === "string" && x.length > 0).join(" ");
3811
+ }
3812
+ exports.COMPONENT_SIZE_ORDER = COMPONENT_SIZE_ORDER;
3813
+ exports.LMBadge = LMBadge;
3814
+ exports.LMButton = LMButton;
3815
+ exports.LMCheckbox = LMCheckbox;
3816
+ exports.LMConfirm = LMConfirm;
3817
+ exports.LMField = LMField;
3818
+ exports.LMInput = LMInput;
3819
+ exports.LMMessage = LMMessage;
3820
+ exports.LMMessageContainer = LMMessageContainer;
3821
+ exports.LMModal = LMModal_default;
3822
+ exports.LMNumberInput = LMNumberInput;
3823
+ exports.LMRadio = LMRadio;
3824
+ exports.LMSearchInput = LMSearchInput;
3825
+ exports.LMSelect = LMSelect;
3826
+ exports.LMStatCard = LMStatCard;
3827
+ exports.LMSwitch = LMSwitch;
3828
+ exports.LMTable = LMTable_default;
3829
+ exports.LMTextarea = LMTextarea;
3830
+ exports.LMTooltip = LMTooltip;
3831
+ exports.SIZE_BUTTON_CONFIG = SIZE_BUTTON_CONFIG;
3832
+ exports.SIZE_DISPLAY_CLASSES = SIZE_DISPLAY_CLASSES;
3833
+ exports.SIZE_GAP_CLASSES = SIZE_GAP_CLASSES;
3834
+ exports.SIZE_HEADING_CLASSES = SIZE_HEADING_CLASSES;
3835
+ exports.SIZE_ICON_CONFIG = SIZE_ICON_CONFIG;
3836
+ exports.SIZE_INPUT_CONFIG = SIZE_INPUT_CONFIG;
3837
+ exports.SIZE_MODAL_CONFIG = SIZE_MODAL_CONFIG;
3838
+ exports.SIZE_PADDING_CLASSES = SIZE_PADDING_CLASSES;
3839
+ exports.SIZE_SELECTOR_CONFIG = SIZE_SELECTOR_CONFIG;
3840
+ exports.SIZE_TABLE_CONFIG = SIZE_TABLE_CONFIG;
3841
+ exports.SIZE_TEXT_CLASSES = SIZE_TEXT_CLASSES;
3842
+ exports.SIZE_TOOLTIP_CONFIG = SIZE_TOOLTIP_CONFIG;
3843
+ exports.clampComponentSize = clampComponentSize;
3844
+ exports.cn = cn;
3845
+ exports.useConfirm = useConfirm;
3846
+ exports.useMessage = useMessage;
3847
+ //# sourceMappingURL=index.cjs.map