@provex/components 1.3.0 → 1.3.1-rc.20260419204346.f2a62c1

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