@provex/components 1.2.4 → 1.3.0-rc.20260419202236.6109d69

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js DELETED
@@ -1,1223 +0,0 @@
1
- import React, { forwardRef, useRef, useCallback, useEffect, useState, useMemo } from 'react';
2
- import { Box } from '@chakra-ui/react';
3
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
- import { getCurrencyByContractId } from '@provex/utils/currencies';
5
- import { Icon } from '@iconify/react';
6
-
7
- // src/Card.tsx
8
- function Card(props) {
9
- const { children, bg, ...rest } = props;
10
- return /* @__PURE__ */ jsx(
11
- Box,
12
- {
13
- bg: bg ?? "surface.card",
14
- color: "text.primary",
15
- boxShadow: "0 0 0 1px var(--chakra-colors-border-default)",
16
- minW: 0,
17
- mb: "1px",
18
- ...rest,
19
- children
20
- }
21
- );
22
- }
23
- function CardHorizontalRule(props) {
24
- const { children, bg, ...rest } = props;
25
- return /* @__PURE__ */ jsx(
26
- Box,
27
- {
28
- bg: bg ?? "surface.card",
29
- color: "text.primary",
30
- borderTop: "1px solid",
31
- borderBottom: "1px solid",
32
- borderColor: "border.default",
33
- minW: 0,
34
- ...rest,
35
- children
36
- }
37
- );
38
- }
39
- var CurrencyIcon = ({
40
- currencyId,
41
- size = 16,
42
- useZoom = true
43
- }) => {
44
- let currency = null;
45
- try {
46
- currency = getCurrencyByContractId(currencyId);
47
- } catch (err) {
48
- console.warn("Invalid currency ID:", currencyId, err);
49
- }
50
- if (!currency) {
51
- return /* @__PURE__ */ jsx(
52
- "span",
53
- {
54
- style: {
55
- fontSize: size * 0.75,
56
- fontWeight: 600,
57
- color: "#888",
58
- fontFamily: "monospace"
59
- },
60
- title: `Unknown currency: ${currencyId}`,
61
- children: "?"
62
- }
63
- );
64
- }
65
- const zoom = useZoom ? currency.zoom ?? 1.5 : 1;
66
- const objectFit = "cover";
67
- return /* @__PURE__ */ jsx(
68
- "span",
69
- {
70
- style: {
71
- display: "inline-block",
72
- width: size,
73
- height: size,
74
- overflow: "hidden",
75
- borderRadius: "100%"
76
- },
77
- children: /* @__PURE__ */ jsx(
78
- "img",
79
- {
80
- src: currency.flag,
81
- alt: currency.ticker,
82
- title: `${currency.name} (${currency.ticker})`,
83
- style: {
84
- width: size,
85
- height: size,
86
- objectFit,
87
- transform: `scale(${zoom})`,
88
- transformOrigin: "center center"
89
- }
90
- }
91
- )
92
- }
93
- );
94
- };
95
- function OverlappingStack({
96
- items,
97
- limit = 3,
98
- overlap = 8,
99
- itemSize = 24,
100
- reverseZIndex = false
101
- }) {
102
- const visibleItems = items.slice(0, limit);
103
- const remainingCount = items.length - limit;
104
- return /* @__PURE__ */ jsxs(
105
- "div",
106
- {
107
- style: {
108
- display: "flex",
109
- alignItems: "center"
110
- },
111
- children: [
112
- visibleItems.map((item, index) => /* @__PURE__ */ jsx(
113
- "div",
114
- {
115
- style: {
116
- marginLeft: index > 0 ? -overlap : 0,
117
- // Only apply z-index when there's actual overlap (positive overlap value)
118
- ...overlap > 0 ? { position: "relative", zIndex: reverseZIndex ? index + 1 : limit - index } : {},
119
- display: "flex",
120
- alignItems: "center",
121
- justifyContent: "center",
122
- minWidth: itemSize,
123
- minHeight: itemSize
124
- },
125
- children: item
126
- },
127
- index
128
- )),
129
- remainingCount > 0 && /* @__PURE__ */ jsxs(
130
- "div",
131
- {
132
- style: {
133
- fontSize: 11,
134
- marginLeft: 4,
135
- fontWeight: 600,
136
- opacity: 0.7
137
- },
138
- children: [
139
- "+",
140
- remainingCount
141
- ]
142
- }
143
- )
144
- ]
145
- }
146
- );
147
- }
148
- function DepositIdentifier({
149
- chainIcon,
150
- localId,
151
- itemSize = 20,
152
- gap = 2,
153
- textColor
154
- }) {
155
- const idString = typeof localId === "bigint" ? localId.toString() : String(localId);
156
- return /* @__PURE__ */ jsx(
157
- OverlappingStack,
158
- {
159
- items: [
160
- /* @__PURE__ */ jsx(React.Fragment, { children: chainIcon }, "chain"),
161
- /* @__PURE__ */ jsxs(
162
- "span",
163
- {
164
- style: {
165
- fontSize: "14px",
166
- fontWeight: 500,
167
- color: textColor
168
- },
169
- children: [
170
- "#",
171
- idString
172
- ]
173
- },
174
- "id"
175
- )
176
- ],
177
- overlap: -gap,
178
- itemSize,
179
- limit: 2
180
- }
181
- );
182
- }
183
- var FlagIcon = ({
184
- flag,
185
- alt = "Flag",
186
- size = 32,
187
- className = "",
188
- borderColor = "#e5e7eb"
189
- }) => {
190
- const handleError = (e) => {
191
- const target = e.target;
192
- const canvas = document.createElement("canvas");
193
- const ctx = canvas.getContext("2d");
194
- if (ctx) {
195
- canvas.width = size;
196
- canvas.height = size;
197
- ctx.fillStyle = "#e0e0e0";
198
- ctx.fillRect(0, 0, size, size);
199
- ctx.fillStyle = "#666";
200
- ctx.font = `${Math.floor(size * 0.3)}px Arial`;
201
- ctx.textAlign = "center";
202
- ctx.textBaseline = "middle";
203
- ctx.fillText(alt.slice(0, 3), size / 2, size / 2);
204
- target.src = canvas.toDataURL();
205
- }
206
- };
207
- return /* @__PURE__ */ jsx(
208
- "img",
209
- {
210
- src: flag,
211
- alt,
212
- className: `inline-block rounded-full ${className}`,
213
- onError: handleError,
214
- style: {
215
- width: `${size}px`,
216
- height: `${size}px`,
217
- borderWidth: "1px",
218
- borderStyle: "solid",
219
- borderColor,
220
- minWidth: `${size}px`,
221
- minHeight: `${size}px`,
222
- maxWidth: `${size}px`,
223
- maxHeight: `${size}px`,
224
- borderRadius: "50%",
225
- objectFit: "cover",
226
- objectPosition: "center",
227
- flexShrink: 0,
228
- display: "block"
229
- }
230
- }
231
- );
232
- };
233
- function Popover({
234
- isOpen,
235
- onClose,
236
- trigger,
237
- children,
238
- colors,
239
- placement = "bottom-start",
240
- width,
241
- minWidth = 200,
242
- fullWidth = false,
243
- gap = 4
244
- }) {
245
- const popoverRef = useRef(null);
246
- const triggerRef = useRef(null);
247
- const [position, setPosition] = useState(null);
248
- const [triggerWidth, setTriggerWidth] = useState(void 0);
249
- useEffect(() => {
250
- if (!isOpen || !triggerRef.current) return;
251
- const updatePosition = () => {
252
- if (!triggerRef.current || !popoverRef.current) return;
253
- const rect = triggerRef.current.getBoundingClientRect();
254
- if (fullWidth) setTriggerWidth(rect.width);
255
- const popoverRect = popoverRef.current.getBoundingClientRect();
256
- const popoverWidth = popoverRect.width || width || (fullWidth ? rect.width : minWidth);
257
- const popoverHeight = popoverRect.height || 400;
258
- let top = 0;
259
- let left = 0;
260
- if (placement.startsWith("bottom")) {
261
- top = rect.bottom + gap;
262
- if (top + popoverHeight > window.innerHeight - 8) {
263
- top = rect.top - popoverHeight - gap;
264
- }
265
- } else {
266
- top = rect.top - popoverHeight - gap;
267
- if (top < 8) {
268
- top = rect.bottom + gap;
269
- }
270
- }
271
- if (placement.endsWith("start")) {
272
- left = rect.left;
273
- if (left + popoverWidth > window.innerWidth - 8) {
274
- left = window.innerWidth - popoverWidth - 8;
275
- }
276
- } else {
277
- left = rect.right - popoverWidth;
278
- if (left < 8) {
279
- left = 8;
280
- }
281
- }
282
- left = Math.max(8, Math.min(left, window.innerWidth - popoverWidth - 8));
283
- top = Math.max(8, Math.min(top, window.innerHeight - popoverHeight - 8));
284
- setPosition({ top, left });
285
- };
286
- const rafId = requestAnimationFrame(() => {
287
- updatePosition();
288
- });
289
- window.addEventListener("scroll", updatePosition, true);
290
- window.addEventListener("resize", updatePosition);
291
- return () => {
292
- cancelAnimationFrame(rafId);
293
- window.removeEventListener("scroll", updatePosition, true);
294
- window.removeEventListener("resize", updatePosition);
295
- };
296
- }, [isOpen, placement, width, minWidth, fullWidth, gap]);
297
- useEffect(() => {
298
- if (!isOpen) return;
299
- const handleClickOutside = (event) => {
300
- const target = event.target;
301
- const isOutsidePopover = popoverRef.current && !popoverRef.current.contains(target);
302
- const isOutsideTrigger = triggerRef.current && !triggerRef.current.contains(target);
303
- if (isOutsidePopover && isOutsideTrigger) {
304
- requestAnimationFrame(() => {
305
- onClose();
306
- });
307
- }
308
- };
309
- const timeoutId = setTimeout(() => {
310
- document.addEventListener("click", handleClickOutside, { capture: false });
311
- }, 50);
312
- return () => {
313
- clearTimeout(timeoutId);
314
- document.removeEventListener("click", handleClickOutside, { capture: false });
315
- };
316
- }, [isOpen, onClose]);
317
- useEffect(() => {
318
- if (!isOpen) return;
319
- const handleEscape = (event) => {
320
- if (event.key === "Escape") {
321
- onClose();
322
- }
323
- };
324
- document.addEventListener("keydown", handleEscape);
325
- return () => {
326
- document.removeEventListener("keydown", handleEscape);
327
- };
328
- }, [isOpen, onClose]);
329
- return /* @__PURE__ */ jsxs("div", { style: { display: fullWidth ? "block" : "inline-block" }, children: [
330
- /* @__PURE__ */ jsx("div", { ref: triggerRef, children: trigger }),
331
- isOpen && /* @__PURE__ */ jsx(
332
- "div",
333
- {
334
- ref: popoverRef,
335
- style: {
336
- position: "fixed",
337
- zIndex: 1e3,
338
- background: colors.bgCard,
339
- border: "none",
340
- boxShadow: `0 0 0 1px ${colors.border}, 0 4px 12px rgba(0, 0, 0, 0.15)`,
341
- minWidth: fullWidth ? triggerWidth : minWidth,
342
- overflow: "hidden",
343
- ...width ? { width } : {},
344
- ...position ? { top: position.top, left: position.left } : { opacity: 0 }
345
- },
346
- children
347
- }
348
- )
349
- ] });
350
- }
351
- function PopoverHeader({ children, colors }) {
352
- return /* @__PURE__ */ jsx(
353
- "div",
354
- {
355
- style: {
356
- fontSize: 14,
357
- fontWeight: 600,
358
- padding: "12px 12px 0 12px",
359
- marginBottom: 12,
360
- color: colors.text
361
- },
362
- children
363
- }
364
- );
365
- }
366
- function PopoverSection({ children }) {
367
- return /* @__PURE__ */ jsx("div", { children });
368
- }
369
- function PopoverFooter({ children }) {
370
- return /* @__PURE__ */ jsx("div", { children });
371
- }
372
- var injectedDirections = /* @__PURE__ */ new Set();
373
- function injectScrollbarStyles(direction) {
374
- if (typeof document === "undefined") return;
375
- if (injectedDirections.has(direction)) return;
376
- injectedDirections.add(direction);
377
- const scrollClass = scrollbarClassName(direction);
378
- const isHorizontal = direction === "horizontal" || direction === "both";
379
- const isVertical = direction === "vertical" || direction === "both";
380
- const css = `
381
- .${scrollClass}::-webkit-scrollbar {
382
- display: block;
383
- ${isHorizontal ? "height: 8px;" : ""}
384
- ${isVertical ? "width: 8px;" : ""}
385
- }
386
- .${scrollClass}::-webkit-scrollbar-track {
387
- background: rgba(0, 0, 0, 0.1);
388
- border-radius: 0;
389
- }
390
- .${scrollClass}::-webkit-scrollbar-thumb {
391
- background: rgba(0, 0, 0, 0.2);
392
- border-radius: 0;
393
- }
394
- .${scrollClass}::-webkit-scrollbar-thumb:hover {
395
- background: rgba(0, 0, 0, 0.4);
396
- }
397
- `;
398
- const style = document.createElement("style");
399
- style.setAttribute("data-scroll-container", direction);
400
- style.textContent = css;
401
- document.head.appendChild(style);
402
- }
403
- function scrollbarClassName(direction) {
404
- return `scroll-container-${direction}`;
405
- }
406
- var ScrollContainer = forwardRef(
407
- ({
408
- children,
409
- direction = "both",
410
- height,
411
- maxHeight,
412
- width,
413
- extendToEdges = false,
414
- edgePadding = 16,
415
- className = "",
416
- style = {},
417
- onScroll,
418
- scrollPosition,
419
- onScrollPositionChange,
420
- scrollToEnd = false,
421
- scrollbarPosition = "right"
422
- }, ref) => {
423
- const internalRef = useRef(null);
424
- const scrollRef = ref || internalRef;
425
- const isUpdatingScroll = useRef(false);
426
- const hasScrolledToEnd = useRef(false);
427
- const scrollClass = scrollbarClassName(direction);
428
- const isHorizontal = direction === "horizontal" || direction === "both";
429
- const isScrollbarLeft = scrollbarPosition === "left";
430
- injectScrollbarStyles(direction);
431
- const handleScroll = useCallback((e) => {
432
- onScroll?.(e);
433
- if (isUpdatingScroll.current) return;
434
- if (onScrollPositionChange) {
435
- const target = e.currentTarget;
436
- if (isHorizontal) {
437
- const maxScroll = target.scrollWidth - target.clientWidth;
438
- if (maxScroll > 0) {
439
- onScrollPositionChange(target.scrollLeft / maxScroll);
440
- }
441
- } else {
442
- const maxScroll = target.scrollHeight - target.clientHeight;
443
- if (maxScroll > 0) {
444
- onScrollPositionChange(target.scrollTop / maxScroll);
445
- }
446
- }
447
- }
448
- }, [isHorizontal, onScroll, onScrollPositionChange]);
449
- useEffect(() => {
450
- if (scrollPosition === void 0) return;
451
- const container = scrollRef.current;
452
- if (!container) return;
453
- if (isHorizontal) {
454
- const maxScroll = container.scrollWidth - container.clientWidth;
455
- if (maxScroll > 0) {
456
- const target = scrollPosition * maxScroll;
457
- if (Math.abs(container.scrollLeft - target) > 1) {
458
- isUpdatingScroll.current = true;
459
- container.scrollLeft = target;
460
- requestAnimationFrame(() => {
461
- isUpdatingScroll.current = false;
462
- });
463
- }
464
- }
465
- } else {
466
- const maxScroll = container.scrollHeight - container.clientHeight;
467
- if (maxScroll > 0) {
468
- const target = scrollPosition * maxScroll;
469
- if (Math.abs(container.scrollTop - target) > 1) {
470
- isUpdatingScroll.current = true;
471
- container.scrollTop = target;
472
- requestAnimationFrame(() => {
473
- isUpdatingScroll.current = false;
474
- });
475
- }
476
- }
477
- }
478
- }, [scrollPosition, isHorizontal, scrollRef]);
479
- useEffect(() => {
480
- if (!scrollToEnd || hasScrolledToEnd.current) return;
481
- const container = scrollRef.current;
482
- if (!container) return;
483
- const timeoutId = setTimeout(() => {
484
- if (isHorizontal) {
485
- container.scrollLeft = container.scrollWidth;
486
- } else {
487
- container.scrollTop = container.scrollHeight;
488
- }
489
- hasScrolledToEnd.current = true;
490
- }, 100);
491
- return () => clearTimeout(timeoutId);
492
- }, [scrollToEnd, isHorizontal, scrollRef, children]);
493
- const defaultOverflowX = isHorizontal ? "auto" : "hidden";
494
- const defaultOverflowY = direction === "vertical" || direction === "both" ? "auto" : "hidden";
495
- const containerStyle = {
496
- overflowX: style?.overflowX ?? defaultOverflowX,
497
- overflowY: style?.overflowY ?? defaultOverflowY,
498
- ...height !== void 0 ? { height } : {},
499
- ...maxHeight !== void 0 ? { maxHeight } : {},
500
- ...width !== void 0 ? { width } : {},
501
- ...extendToEdges ? { margin: `-${edgePadding}px`, padding: edgePadding } : {},
502
- ...isScrollbarLeft ? { direction: "rtl" } : {},
503
- ...style
504
- };
505
- return /* @__PURE__ */ jsx(
506
- "div",
507
- {
508
- ref: scrollRef,
509
- className: `${scrollClass} ${className}`.trim(),
510
- style: containerStyle,
511
- onScroll: handleScroll,
512
- children: isScrollbarLeft ? /* @__PURE__ */ jsx("div", { style: { direction: "ltr", width: "100%", height: "100%" }, children }) : children
513
- }
514
- );
515
- }
516
- );
517
- ScrollContainer.displayName = "ScrollContainer";
518
- var SIZES = {
519
- sm: { triggerHeight: 32, optionHeight: 32, triggerPadding: "4px 8px", optionPadding: "0 12px", fontSize: 13, chevronSize: 14 },
520
- md: { triggerHeight: 40, optionHeight: 40, triggerPadding: "8px 12px", optionPadding: "0 12px", fontSize: 14, chevronSize: 16 }
521
- };
522
- function MenuSelect({
523
- options,
524
- value,
525
- onChange,
526
- placeholder = "Select...",
527
- isDisabled = false,
528
- colors,
529
- size = "md",
530
- minWidth,
531
- maxDropdownHeight = 240,
532
- placement = "bottom-start",
533
- renderTrigger
534
- }) {
535
- const [isOpen, setIsOpen] = useState(false);
536
- const [focusedIndex, setFocusedIndex] = useState(-1);
537
- const listRef = useRef(null);
538
- const selectedOption = options.find((o) => o.value === value);
539
- const s = SIZES[size];
540
- const handleSelect = useCallback(
541
- (optionValue) => {
542
- onChange(optionValue);
543
- setIsOpen(false);
544
- },
545
- [onChange]
546
- );
547
- const handleToggle = useCallback(() => {
548
- if (isDisabled) return;
549
- setIsOpen((prev) => {
550
- if (!prev) {
551
- const idx = options.findIndex((o) => o.value === value && !o.isDisabled);
552
- setFocusedIndex(idx >= 0 ? idx : options.findIndex((o) => !o.isDisabled));
553
- }
554
- return !prev;
555
- });
556
- }, [isDisabled, options, value]);
557
- const findNextEnabled = useCallback((from, direction) => {
558
- let idx = from + direction;
559
- while (idx >= 0 && idx < options.length) {
560
- if (!options[idx]?.isDisabled) return idx;
561
- idx += direction;
562
- }
563
- return from;
564
- }, [options]);
565
- const handleKeyDown = useCallback(
566
- (e) => {
567
- if (!isOpen) {
568
- if (e.key === "ArrowDown" || e.key === "Enter" || e.key === " ") {
569
- e.preventDefault();
570
- handleToggle();
571
- }
572
- return;
573
- }
574
- switch (e.key) {
575
- case "ArrowDown":
576
- e.preventDefault();
577
- setFocusedIndex((prev) => findNextEnabled(prev, 1));
578
- break;
579
- case "ArrowUp":
580
- e.preventDefault();
581
- setFocusedIndex((prev) => findNextEnabled(prev, -1));
582
- break;
583
- case "Enter":
584
- case " ":
585
- e.preventDefault();
586
- if (focusedIndex >= 0 && focusedIndex < options.length && !options[focusedIndex]?.isDisabled) {
587
- handleSelect(options[focusedIndex].value);
588
- }
589
- break;
590
- case "Escape":
591
- e.preventDefault();
592
- setIsOpen(false);
593
- break;
594
- }
595
- },
596
- [isOpen, focusedIndex, options, handleSelect, handleToggle, findNextEnabled]
597
- );
598
- useEffect(() => {
599
- if (!isOpen || focusedIndex < 0 || !listRef.current) return;
600
- const listbox = listRef.current.querySelector("[role=listbox]");
601
- if (!listbox) return;
602
- const items = listbox.children;
603
- if (items[focusedIndex]) {
604
- items[focusedIndex].scrollIntoView({ block: "nearest" });
605
- }
606
- }, [isOpen, focusedIndex]);
607
- const triggerElement = renderTrigger ? /* @__PURE__ */ jsx(
608
- "div",
609
- {
610
- role: "button",
611
- tabIndex: isDisabled ? -1 : 0,
612
- onClick: handleToggle,
613
- onKeyDown: handleKeyDown,
614
- style: { cursor: isDisabled ? "not-allowed" : "pointer" },
615
- children: renderTrigger({ selected: selectedOption, isOpen, isDisabled })
616
- }
617
- ) : /* @__PURE__ */ jsxs(
618
- "button",
619
- {
620
- type: "button",
621
- onClick: handleToggle,
622
- onKeyDown: handleKeyDown,
623
- disabled: isDisabled,
624
- style: {
625
- display: "flex",
626
- alignItems: "center",
627
- justifyContent: "space-between",
628
- gap: 8,
629
- width: "100%",
630
- minWidth,
631
- padding: s.triggerPadding,
632
- fontSize: s.fontSize,
633
- fontWeight: 400,
634
- fontFamily: "inherit",
635
- border: "none",
636
- borderRadius: 0,
637
- boxShadow: `0 0 0 1px ${colors.border}`,
638
- background: colors.bg,
639
- color: selectedOption ? colors.text : colors.textMuted,
640
- cursor: isDisabled ? "not-allowed" : "pointer",
641
- opacity: isDisabled ? 0.5 : 1,
642
- minHeight: s.triggerHeight
643
- },
644
- children: [
645
- /* @__PURE__ */ jsxs(
646
- "span",
647
- {
648
- style: {
649
- display: "flex",
650
- alignItems: "center",
651
- gap: 8,
652
- overflow: "hidden"
653
- },
654
- children: [
655
- selectedOption?.icon,
656
- /* @__PURE__ */ jsx(
657
- "span",
658
- {
659
- style: {
660
- overflow: "hidden",
661
- textOverflow: "ellipsis",
662
- whiteSpace: "nowrap"
663
- },
664
- children: selectedOption?.label ?? placeholder
665
- }
666
- )
667
- ]
668
- }
669
- ),
670
- /* @__PURE__ */ jsx(
671
- Icon,
672
- {
673
- icon: "feather:chevron-down",
674
- width: s.chevronSize,
675
- height: s.chevronSize,
676
- style: {
677
- flexShrink: 0,
678
- transition: "transform 0.2s",
679
- transform: isOpen ? "rotate(180deg)" : "rotate(0deg)"
680
- }
681
- }
682
- )
683
- ]
684
- }
685
- );
686
- return /* @__PURE__ */ jsx(
687
- Popover,
688
- {
689
- isOpen,
690
- onClose: () => setIsOpen(false),
691
- trigger: triggerElement,
692
- colors,
693
- minWidth,
694
- fullWidth: !renderTrigger,
695
- gap: 0,
696
- placement,
697
- children: /* @__PURE__ */ jsx(
698
- ScrollContainer,
699
- {
700
- ref: listRef,
701
- direction: "vertical",
702
- maxHeight: maxDropdownHeight,
703
- children: /* @__PURE__ */ jsx("div", { role: "listbox", onKeyDown: handleKeyDown, children: options.map((option, index) => {
704
- const isSelected = option.value === value;
705
- const isFocused = index === focusedIndex;
706
- const optDisabled = option.isDisabled ?? false;
707
- return /* @__PURE__ */ jsxs(
708
- "button",
709
- {
710
- type: "button",
711
- role: "option",
712
- "aria-selected": isSelected,
713
- "aria-disabled": optDisabled,
714
- onClick: () => !optDisabled && handleSelect(option.value),
715
- onMouseEnter: () => !optDisabled && setFocusedIndex(index),
716
- style: {
717
- display: "flex",
718
- alignItems: "center",
719
- gap: 8,
720
- width: "100%",
721
- padding: s.optionPadding,
722
- minHeight: s.optionHeight,
723
- fontSize: s.fontSize,
724
- fontFamily: "inherit",
725
- border: "none",
726
- borderRadius: 0,
727
- background: isFocused && !optDisabled ? `${colors.border}40` : "transparent",
728
- color: optDisabled ? colors.textMuted : colors.text,
729
- cursor: optDisabled ? "not-allowed" : "pointer",
730
- fontWeight: isSelected ? 500 : 400,
731
- textAlign: "left",
732
- opacity: optDisabled ? 0.5 : 1
733
- },
734
- children: [
735
- option.icon,
736
- /* @__PURE__ */ jsx(
737
- "span",
738
- {
739
- style: {
740
- overflow: "hidden",
741
- textOverflow: "ellipsis",
742
- whiteSpace: "nowrap",
743
- flex: 1
744
- },
745
- children: option.label
746
- }
747
- ),
748
- /* @__PURE__ */ jsx("span", { style: { width: 14, flexShrink: 0, display: "flex", justifyContent: "center" }, children: isSelected && /* @__PURE__ */ jsx(
749
- Icon,
750
- {
751
- icon: "feather:check",
752
- width: 14,
753
- height: 14
754
- }
755
- ) })
756
- ]
757
- },
758
- option.value
759
- );
760
- }) })
761
- }
762
- )
763
- }
764
- );
765
- }
766
- function MultiSelectFilter({
767
- allItems,
768
- selectedItems,
769
- onSelectionChange,
770
- itemStats,
771
- renderIcon,
772
- renderListIcon,
773
- getLabel,
774
- title,
775
- colors,
776
- placeholder: _placeholder,
777
- buttonWidth = 112,
778
- iconSize = 24,
779
- iconLimit = 3,
780
- iconOverlap = 8,
781
- reverseZIndex = true,
782
- getVolumeRank
783
- }) {
784
- const [isOpen, setIsOpen] = useState(false);
785
- const [localSelection, setLocalSelection] = useState(selectedItems);
786
- const statsMap = useMemo(
787
- () => new Map(itemStats.map((stat) => [stat.item, stat.count])),
788
- [itemStats]
789
- );
790
- const sortedItems = useMemo(() => {
791
- return Array.from(allItems).sort((a, b) => {
792
- if (getVolumeRank) {
793
- const rankA = getVolumeRank(a);
794
- const rankB = getVolumeRank(b);
795
- if (rankA !== rankB) {
796
- return rankA - rankB;
797
- }
798
- }
799
- const countA = statsMap.get(a) ?? 0;
800
- const countB = statsMap.get(b) ?? 0;
801
- if (countA !== countB) {
802
- return countB - countA;
803
- }
804
- return getLabel(a).localeCompare(getLabel(b));
805
- });
806
- }, [allItems, getVolumeRank, statsMap, getLabel]);
807
- const handleToggle = (item) => {
808
- const newSelection = new Set(localSelection);
809
- if (newSelection.has(item)) {
810
- newSelection.delete(item);
811
- } else {
812
- newSelection.add(item);
813
- }
814
- setLocalSelection(newSelection);
815
- };
816
- const handleSelectAll = () => {
817
- setLocalSelection(/* @__PURE__ */ new Set());
818
- };
819
- const handleSelectNone = () => {
820
- setLocalSelection(/* @__PURE__ */ new Set());
821
- };
822
- const handleApply = () => {
823
- onSelectionChange(localSelection);
824
- setIsOpen(false);
825
- };
826
- const handleToggleOpen = () => {
827
- if (isOpen) {
828
- setIsOpen(false);
829
- } else {
830
- setLocalSelection(selectedItems);
831
- setIsOpen(true);
832
- }
833
- };
834
- const selectedCount = selectedItems.size;
835
- const totalCount = allItems.size;
836
- const isShowingAll = selectedCount === 0 || selectedCount === totalCount;
837
- const hasFilter = selectedCount > 0 && selectedCount < totalCount;
838
- const itemsToDisplay = useMemo(() => {
839
- if (isShowingAll) {
840
- return sortedItems;
841
- }
842
- return Array.from(selectedItems).sort((a, b) => {
843
- if (getVolumeRank) {
844
- const rankA = getVolumeRank(a);
845
- const rankB = getVolumeRank(b);
846
- if (rankA !== rankB) {
847
- return rankA - rankB;
848
- }
849
- }
850
- const countA = statsMap.get(a) ?? 0;
851
- const countB = statsMap.get(b) ?? 0;
852
- if (countA !== countB) {
853
- return countB - countA;
854
- }
855
- return getLabel(a).localeCompare(getLabel(b));
856
- });
857
- }, [isShowingAll, sortedItems, selectedItems, getVolumeRank, statsMap, getLabel]);
858
- const iconItems = itemsToDisplay.map((item) => /* @__PURE__ */ jsx(
859
- "div",
860
- {
861
- style: {
862
- width: iconSize,
863
- height: iconSize,
864
- borderRadius: "50%",
865
- boxShadow: `0 0 0 1px ${colors.border}`,
866
- overflow: "hidden",
867
- background: colors.bgCard,
868
- display: "flex",
869
- alignItems: "center",
870
- justifyContent: "center"
871
- },
872
- children: renderIcon(item)
873
- },
874
- item
875
- ));
876
- const triggerButton = /* @__PURE__ */ jsx(
877
- "button",
878
- {
879
- onClick: handleToggleOpen,
880
- style: {
881
- padding: "8px 12px",
882
- fontSize: 13,
883
- fontWeight: 500,
884
- border: `1px solid ${hasFilter ? "#3182ce" : colors.border}`,
885
- background: hasFilter ? "#3182ce" : colors.bgCard,
886
- color: hasFilter ? "#fff" : colors.text,
887
- cursor: "pointer",
888
- display: "flex",
889
- alignItems: "center",
890
- gap: 6,
891
- minWidth: buttonWidth,
892
- maxWidth: buttonWidth,
893
- minHeight: 38,
894
- maxHeight: 38,
895
- justifyContent: "center"
896
- },
897
- children: /* @__PURE__ */ jsx(
898
- OverlappingStack,
899
- {
900
- items: iconItems,
901
- limit: iconLimit,
902
- overlap: iconOverlap,
903
- itemSize: iconSize,
904
- reverseZIndex
905
- }
906
- )
907
- }
908
- );
909
- const listIconRenderer = renderListIcon ?? renderIcon;
910
- return /* @__PURE__ */ jsxs(Popover, { isOpen, onClose: () => setIsOpen(false), trigger: triggerButton, colors, children: [
911
- /* @__PURE__ */ jsx(PopoverHeader, { colors, children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [
912
- /* @__PURE__ */ jsx("span", { children: title }),
913
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 4 }, children: [
914
- /* @__PURE__ */ jsx(
915
- "button",
916
- {
917
- onClick: handleSelectAll,
918
- style: {
919
- padding: "2px 8px",
920
- fontSize: 11,
921
- border: "none",
922
- background: "transparent",
923
- color: colors.textMuted,
924
- cursor: "pointer"
925
- },
926
- children: "All"
927
- }
928
- ),
929
- /* @__PURE__ */ jsx(
930
- "button",
931
- {
932
- onClick: handleSelectNone,
933
- style: {
934
- padding: "2px 8px",
935
- fontSize: 11,
936
- border: "none",
937
- background: "transparent",
938
- color: colors.textMuted,
939
- cursor: "pointer"
940
- },
941
- children: "None"
942
- }
943
- )
944
- ] })
945
- ] }) }),
946
- /* @__PURE__ */ jsx(PopoverSection, { children: /* @__PURE__ */ jsxs("div", { style: { position: "relative" }, children: [
947
- /* @__PURE__ */ jsx("div", { style: { maxHeight: 300, overflowY: "auto", paddingBottom: 12 }, children: sortedItems.map((item) => /* @__PURE__ */ jsxs(
948
- "label",
949
- {
950
- style: {
951
- display: "flex",
952
- alignItems: "center",
953
- justifyContent: "space-between",
954
- padding: "4px 12px",
955
- cursor: "pointer",
956
- fontSize: 13
957
- },
958
- children: [
959
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
960
- /* @__PURE__ */ jsx(
961
- "input",
962
- {
963
- type: "checkbox",
964
- checked: localSelection.has(item),
965
- onChange: () => handleToggle(item),
966
- style: { cursor: "pointer" }
967
- }
968
- ),
969
- /* @__PURE__ */ jsx(
970
- "div",
971
- {
972
- style: {
973
- width: iconSize,
974
- height: iconSize,
975
- borderRadius: "50%",
976
- boxShadow: `0 0 0 1px ${colors.border}`,
977
- overflow: "hidden",
978
- background: colors.bgCard,
979
- display: "flex",
980
- alignItems: "center",
981
- justifyContent: "center",
982
- flexShrink: 0
983
- },
984
- children: listIconRenderer(item)
985
- }
986
- ),
987
- /* @__PURE__ */ jsx("span", { children: getLabel(item) })
988
- ] }),
989
- statsMap.size > 0 && /* @__PURE__ */ jsx(
990
- "span",
991
- {
992
- style: {
993
- fontSize: 11,
994
- color: colors.textMuted,
995
- background: colors.bg,
996
- padding: "2px 6px"
997
- },
998
- children: statsMap.get(item) ?? 0
999
- }
1000
- )
1001
- ]
1002
- },
1003
- item
1004
- )) }),
1005
- /* @__PURE__ */ jsx(
1006
- "div",
1007
- {
1008
- style: {
1009
- position: "absolute",
1010
- bottom: 0,
1011
- left: 0,
1012
- right: 0,
1013
- height: 12,
1014
- background: `linear-gradient(to bottom, transparent, ${colors.bgCard})`,
1015
- pointerEvents: "none"
1016
- }
1017
- }
1018
- )
1019
- ] }) }),
1020
- /* @__PURE__ */ jsx(PopoverFooter, { children: /* @__PURE__ */ jsx(
1021
- "button",
1022
- {
1023
- onClick: handleApply,
1024
- style: {
1025
- width: "100%",
1026
- padding: "8px 12px",
1027
- fontSize: 13,
1028
- fontWeight: 500,
1029
- border: "none",
1030
- background: "#3182ce",
1031
- color: "#fff",
1032
- cursor: "pointer",
1033
- minHeight: 38
1034
- },
1035
- children: "Apply"
1036
- }
1037
- ) })
1038
- ] });
1039
- }
1040
- var PaymentCurrencyCombo = ({
1041
- paymentMethodIcon,
1042
- currencyId,
1043
- size = 20,
1044
- colors
1045
- }) => {
1046
- const badgeSize = size * 0.6;
1047
- return /* @__PURE__ */ jsxs(
1048
- "div",
1049
- {
1050
- style: {
1051
- display: "flex",
1052
- alignItems: "center",
1053
- justifyContent: "center",
1054
- boxSizing: "border-box",
1055
- borderRadius: "100%",
1056
- height: size,
1057
- width: size,
1058
- position: "relative",
1059
- overflow: "hidden"
1060
- },
1061
- children: [
1062
- /* @__PURE__ */ jsx(
1063
- "div",
1064
- {
1065
- style: {
1066
- position: "absolute",
1067
- top: 0,
1068
- left: 0,
1069
- width: "100%",
1070
- height: "100%",
1071
- display: "flex",
1072
- alignItems: "center",
1073
- justifyContent: "center",
1074
- overflow: "hidden"
1075
- },
1076
- children: /* @__PURE__ */ jsx(CurrencyIcon, { currencyId, size })
1077
- }
1078
- ),
1079
- /* @__PURE__ */ jsx(
1080
- "div",
1081
- {
1082
- style: {
1083
- position: "absolute",
1084
- bottom: 0,
1085
- right: 0,
1086
- width: badgeSize,
1087
- height: badgeSize,
1088
- display: "flex",
1089
- alignItems: "center",
1090
- justifyContent: "center",
1091
- background: colors.bg,
1092
- borderRadius: 0
1093
- },
1094
- children: paymentMethodIcon
1095
- }
1096
- )
1097
- ]
1098
- }
1099
- );
1100
- };
1101
- function PaymentMethodIcon({
1102
- icon,
1103
- color = "#6b7280",
1104
- backgroundColor,
1105
- size = 16,
1106
- isUnknown = false,
1107
- tooltip
1108
- }) {
1109
- const effectiveColor = isUnknown ? "#ef4444" : color;
1110
- return /* @__PURE__ */ jsxs(
1111
- "span",
1112
- {
1113
- style: {
1114
- display: "flex",
1115
- alignItems: "center",
1116
- justifyContent: "center",
1117
- width: size,
1118
- height: size,
1119
- opacity: isUnknown ? 0.6 : 1,
1120
- position: "relative",
1121
- backgroundColor,
1122
- borderRadius: backgroundColor ? "4px" : void 0,
1123
- padding: backgroundColor ? "2px" : void 0,
1124
- boxSizing: "border-box"
1125
- },
1126
- title: tooltip,
1127
- children: [
1128
- /* @__PURE__ */ jsx(
1129
- Icon,
1130
- {
1131
- icon,
1132
- width: backgroundColor ? size - 4 : size,
1133
- height: backgroundColor ? size - 4 : size,
1134
- style: { color: effectiveColor }
1135
- }
1136
- ),
1137
- isUnknown && /* @__PURE__ */ jsx(
1138
- "span",
1139
- {
1140
- style: {
1141
- position: "absolute",
1142
- bottom: -2,
1143
- right: -2,
1144
- width: size * 0.35,
1145
- height: size * 0.35,
1146
- borderRadius: "50%",
1147
- background: "#ef4444",
1148
- border: "1px solid white"
1149
- },
1150
- title: "Unknown payment method"
1151
- }
1152
- )
1153
- ]
1154
- }
1155
- );
1156
- }
1157
- var DEFAULT_PAYMENT_ICON = "mdi:credit-card";
1158
- var DEFAULT_PAYMENT_COLOR = "#6b7280";
1159
- function Tooltip({ label, children, isDisabled, placement = "top", display = "inline-flex" }) {
1160
- const [visible, setVisible] = useState(false);
1161
- const ref = useRef(null);
1162
- useEffect(() => {
1163
- if (isDisabled) setVisible(false);
1164
- }, [isDisabled]);
1165
- if (isDisabled) return /* @__PURE__ */ jsx(Fragment, { children });
1166
- const tipStyle = {
1167
- position: "absolute",
1168
- left: 0,
1169
- width: "max-content",
1170
- maxWidth: 280,
1171
- background: "rgba(0,0,0,0.82)",
1172
- color: "#fff",
1173
- fontSize: 11,
1174
- lineHeight: 1.4,
1175
- padding: "4px 8px",
1176
- whiteSpace: "normal",
1177
- zIndex: 9999,
1178
- pointerEvents: "none",
1179
- borderRadius: 2,
1180
- ...placement === "top" ? { bottom: "calc(100% + 5px)" } : { top: "calc(100% + 5px)" }
1181
- };
1182
- return /* @__PURE__ */ jsxs(
1183
- "span",
1184
- {
1185
- ref,
1186
- style: { position: "relative", display, alignItems: display === "inline-flex" ? "center" : void 0 },
1187
- onMouseEnter: () => setVisible(true),
1188
- onMouseLeave: () => setVisible(false),
1189
- children: [
1190
- children,
1191
- visible && /* @__PURE__ */ jsx("span", { style: tipStyle, children: label })
1192
- ]
1193
- }
1194
- );
1195
- }
1196
- function VersionBadge(props) {
1197
- const { version, colors, style } = props;
1198
- const bgColor = version === "v3" ? colors.bgV3 : colors.bgV2;
1199
- return /* @__PURE__ */ jsx(
1200
- "span",
1201
- {
1202
- style: {
1203
- display: "inline-flex",
1204
- alignItems: "center",
1205
- justifyContent: "center",
1206
- padding: "2px 4px",
1207
- fontSize: "10px",
1208
- fontWeight: 600,
1209
- textTransform: "uppercase",
1210
- letterSpacing: "0.25px",
1211
- borderRadius: "4px",
1212
- backgroundColor: bgColor,
1213
- color: colors.text,
1214
- ...style
1215
- },
1216
- children: version
1217
- }
1218
- );
1219
- }
1220
-
1221
- export { Card, CardHorizontalRule, CurrencyIcon, DEFAULT_PAYMENT_COLOR, DEFAULT_PAYMENT_ICON, DepositIdentifier, FlagIcon, MenuSelect, MultiSelectFilter, OverlappingStack, PaymentCurrencyCombo, PaymentMethodIcon, Popover, PopoverFooter, PopoverHeader, PopoverSection, ScrollContainer, Tooltip, VersionBadge, injectScrollbarStyles, scrollbarClassName };
1222
- //# sourceMappingURL=index.js.map
1223
- //# sourceMappingURL=index.js.map