@loafmarkets/ui 0.1.2 → 0.1.4
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.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +240 -31
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +240 -31
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -280,7 +280,7 @@ declare const YourOrders: React.ForwardRefExoticComponent<React.HTMLAttributes<H
|
|
|
280
280
|
renderOrderActions?: (order: YourOrder) => React.ReactNode;
|
|
281
281
|
} & React.RefAttributes<HTMLDivElement>>;
|
|
282
282
|
|
|
283
|
-
type PriceChartRange = "
|
|
283
|
+
type PriceChartRange = "30s" | "1m" | "5m" | "15m" | "1h" | "4h" | "24h" | "1W" | "1M";
|
|
284
284
|
type PriceChartCandle = {
|
|
285
285
|
time: LightweightCharts.Time;
|
|
286
286
|
open: number;
|
package/dist/index.d.ts
CHANGED
|
@@ -280,7 +280,7 @@ declare const YourOrders: React.ForwardRefExoticComponent<React.HTMLAttributes<H
|
|
|
280
280
|
renderOrderActions?: (order: YourOrder) => React.ReactNode;
|
|
281
281
|
} & React.RefAttributes<HTMLDivElement>>;
|
|
282
282
|
|
|
283
|
-
type PriceChartRange = "
|
|
283
|
+
type PriceChartRange = "30s" | "1m" | "5m" | "15m" | "1h" | "4h" | "24h" | "1W" | "1M";
|
|
284
284
|
type PriceChartCandle = {
|
|
285
285
|
time: LightweightCharts.Time;
|
|
286
286
|
open: number;
|
package/dist/index.js
CHANGED
|
@@ -3300,7 +3300,7 @@ function DesktopOrderbookLayout({
|
|
|
3300
3300
|
)
|
|
3301
3301
|
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-3", children: rightHeader })
|
|
3302
3302
|
] }),
|
|
3303
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4
|
|
3303
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 pt-2", children: [
|
|
3304
3304
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-3 px-3 py-2 text-xs text-white/60", children: [
|
|
3305
3305
|
/* @__PURE__ */ jsxRuntime.jsx("div", { children: priceLabel }),
|
|
3306
3306
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-right", children: amountLabel })
|
|
@@ -3354,7 +3354,7 @@ function DesktopOrderbookLayout({
|
|
|
3354
3354
|
))
|
|
3355
3355
|
}
|
|
3356
3356
|
),
|
|
3357
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
3357
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 items-center gap-3 bg-[#0b1a24] px-3 py-2", children: [
|
|
3358
3358
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("text-lg font-semibold tabular-nums", midClass), children: [
|
|
3359
3359
|
"$",
|
|
3360
3360
|
formatNumber(midPrice, precision),
|
|
@@ -4567,7 +4567,119 @@ var YourOrders = o__namespace.forwardRef(
|
|
|
4567
4567
|
}
|
|
4568
4568
|
);
|
|
4569
4569
|
YourOrders.displayName = "YourOrders";
|
|
4570
|
-
var
|
|
4570
|
+
var timeToDate = (time) => {
|
|
4571
|
+
if (typeof time === "number") {
|
|
4572
|
+
return new Date(time * 1e3);
|
|
4573
|
+
}
|
|
4574
|
+
if (typeof time === "object" && time !== null && "year" in time && "month" in time && "day" in time) {
|
|
4575
|
+
const { year, month, day } = time;
|
|
4576
|
+
return new Date(Date.UTC(year, month - 1, day));
|
|
4577
|
+
}
|
|
4578
|
+
return null;
|
|
4579
|
+
};
|
|
4580
|
+
var createTickFormatter = (formatOptions) => {
|
|
4581
|
+
return (time, _tickMarkType, locale) => {
|
|
4582
|
+
const date = timeToDate(time);
|
|
4583
|
+
if (!date) return "";
|
|
4584
|
+
return date.toLocaleString(locale || void 0, formatOptions);
|
|
4585
|
+
};
|
|
4586
|
+
};
|
|
4587
|
+
var getTimeScaleOptions = (range) => {
|
|
4588
|
+
switch (range) {
|
|
4589
|
+
case "30s":
|
|
4590
|
+
return {
|
|
4591
|
+
timeVisible: true,
|
|
4592
|
+
secondsVisible: true,
|
|
4593
|
+
borderColor: "rgba(255,255,255,0.06)",
|
|
4594
|
+
tickMarkFormatter: createTickFormatter({ hour: "2-digit", minute: "2-digit", second: "2-digit" })
|
|
4595
|
+
};
|
|
4596
|
+
case "1m":
|
|
4597
|
+
return {
|
|
4598
|
+
timeVisible: true,
|
|
4599
|
+
secondsVisible: true,
|
|
4600
|
+
borderColor: "rgba(255,255,255,0.06)",
|
|
4601
|
+
tickMarkFormatter: createTickFormatter({ hour: "2-digit", minute: "2-digit", second: "2-digit" })
|
|
4602
|
+
};
|
|
4603
|
+
case "5m":
|
|
4604
|
+
return {
|
|
4605
|
+
timeVisible: true,
|
|
4606
|
+
secondsVisible: false,
|
|
4607
|
+
borderColor: "rgba(255,255,255,0.06)",
|
|
4608
|
+
tickMarkFormatter: createTickFormatter({ hour: "2-digit", minute: "2-digit" })
|
|
4609
|
+
};
|
|
4610
|
+
case "15m":
|
|
4611
|
+
return {
|
|
4612
|
+
timeVisible: true,
|
|
4613
|
+
secondsVisible: false,
|
|
4614
|
+
borderColor: "rgba(255,255,255,0.06)",
|
|
4615
|
+
tickMarkFormatter: createTickFormatter({ hour: "2-digit", minute: "2-digit" })
|
|
4616
|
+
};
|
|
4617
|
+
case "1h":
|
|
4618
|
+
return {
|
|
4619
|
+
timeVisible: true,
|
|
4620
|
+
secondsVisible: false,
|
|
4621
|
+
borderColor: "rgba(255,255,255,0.06)",
|
|
4622
|
+
tickMarkFormatter: createTickFormatter({ hour: "2-digit", minute: "2-digit" })
|
|
4623
|
+
};
|
|
4624
|
+
case "4h":
|
|
4625
|
+
return {
|
|
4626
|
+
timeVisible: true,
|
|
4627
|
+
secondsVisible: false,
|
|
4628
|
+
borderColor: "rgba(255,255,255,0.06)",
|
|
4629
|
+
tickMarkFormatter: createTickFormatter({ weekday: "short", hour: "2-digit" })
|
|
4630
|
+
};
|
|
4631
|
+
case "24h":
|
|
4632
|
+
return {
|
|
4633
|
+
timeVisible: true,
|
|
4634
|
+
secondsVisible: false,
|
|
4635
|
+
borderColor: "rgba(255,255,255,0.06)",
|
|
4636
|
+
tickMarkFormatter: createTickFormatter({ month: "short", day: "numeric" })
|
|
4637
|
+
};
|
|
4638
|
+
case "1W":
|
|
4639
|
+
return {
|
|
4640
|
+
timeVisible: true,
|
|
4641
|
+
secondsVisible: false,
|
|
4642
|
+
borderColor: "rgba(255,255,255,0.06)",
|
|
4643
|
+
tickMarkFormatter: createTickFormatter({ month: "short", day: "numeric" })
|
|
4644
|
+
};
|
|
4645
|
+
case "1M":
|
|
4646
|
+
return {
|
|
4647
|
+
timeVisible: true,
|
|
4648
|
+
secondsVisible: false,
|
|
4649
|
+
borderColor: "rgba(255,255,255,0.06)",
|
|
4650
|
+
tickMarkFormatter: createTickFormatter({ month: "short", year: "2-digit" })
|
|
4651
|
+
};
|
|
4652
|
+
default:
|
|
4653
|
+
return {
|
|
4654
|
+
timeVisible: true,
|
|
4655
|
+
secondsVisible: false,
|
|
4656
|
+
borderColor: "rgba(255,255,255,0.06)"
|
|
4657
|
+
};
|
|
4658
|
+
}
|
|
4659
|
+
};
|
|
4660
|
+
var getPriceScaleOptions = (data) => {
|
|
4661
|
+
if (!data.length) return {
|
|
4662
|
+
borderColor: "rgba(230, 200, 126, 0.25)",
|
|
4663
|
+
textColor: "rgba(230, 200, 126, 0.7)"
|
|
4664
|
+
};
|
|
4665
|
+
const prices = data.flatMap((d2) => [d2.open, d2.high, d2.low, d2.close]);
|
|
4666
|
+
const minPrice = Math.min(...prices);
|
|
4667
|
+
const maxPrice = Math.max(...prices);
|
|
4668
|
+
const priceRange = maxPrice - minPrice;
|
|
4669
|
+
let scaleMargins = { top: 0.1, bottom: 0.1 };
|
|
4670
|
+
if (priceRange < 1) {
|
|
4671
|
+
scaleMargins = { top: 0.2, bottom: 0.2 };
|
|
4672
|
+
} else if (priceRange > 1e3) {
|
|
4673
|
+
scaleMargins = { top: 0.05, bottom: 0.05 };
|
|
4674
|
+
}
|
|
4675
|
+
return {
|
|
4676
|
+
borderColor: "rgba(230, 200, 126, 0.25)",
|
|
4677
|
+
textColor: "rgba(230, 200, 126, 0.7)",
|
|
4678
|
+
scaleMargins
|
|
4679
|
+
};
|
|
4680
|
+
};
|
|
4681
|
+
var defaultRanges = ["30s", "1m", "5m", "15m", "1h", "4h", "24h", "1W", "1M"];
|
|
4682
|
+
var VISIBLE_RANGE_COUNT = 4;
|
|
4571
4683
|
var formatPrice = (value, currencySymbol) => {
|
|
4572
4684
|
return `${currencySymbol}${value.toLocaleString(void 0, {
|
|
4573
4685
|
minimumFractionDigits: 2,
|
|
@@ -4604,6 +4716,21 @@ var PriceChart = o__namespace.forwardRef(
|
|
|
4604
4716
|
const seriesRef = o__namespace.useRef(null);
|
|
4605
4717
|
const priceLineRef = o__namespace.useRef(null);
|
|
4606
4718
|
const [hoveredRange, setHoveredRange] = o__namespace.useState(null);
|
|
4719
|
+
const [dropdownOpen, setDropdownOpen] = o__namespace.useState(false);
|
|
4720
|
+
const dropdownRef = o__namespace.useRef(null);
|
|
4721
|
+
const isAutoScrollRef = o__namespace.useRef(true);
|
|
4722
|
+
const visibleRanges = ranges.slice(0, VISIBLE_RANGE_COUNT);
|
|
4723
|
+
const dropdownRanges = ranges.slice(VISIBLE_RANGE_COUNT);
|
|
4724
|
+
const selectedInDropdown = dropdownRanges.includes(selectedRange);
|
|
4725
|
+
o__namespace.useEffect(() => {
|
|
4726
|
+
const handleClickOutside = (e) => {
|
|
4727
|
+
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
|
|
4728
|
+
setDropdownOpen(false);
|
|
4729
|
+
}
|
|
4730
|
+
};
|
|
4731
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
4732
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
4733
|
+
}, []);
|
|
4607
4734
|
const resolvedPrice = o__namespace.useMemo(() => {
|
|
4608
4735
|
if (price != null) return price;
|
|
4609
4736
|
const last = data.at(-1);
|
|
@@ -4636,15 +4763,8 @@ var PriceChart = o__namespace.forwardRef(
|
|
|
4636
4763
|
vertLines: { color: "rgba(255,255,255,0.06)" },
|
|
4637
4764
|
horzLines: { color: "rgba(255,255,255,0.06)" }
|
|
4638
4765
|
},
|
|
4639
|
-
rightPriceScale:
|
|
4640
|
-
|
|
4641
|
-
textColor: "rgba(230, 200, 126, 0.7)"
|
|
4642
|
-
},
|
|
4643
|
-
timeScale: {
|
|
4644
|
-
borderColor: "rgba(255,255,255,0.06)",
|
|
4645
|
-
timeVisible: true,
|
|
4646
|
-
secondsVisible: false
|
|
4647
|
-
},
|
|
4766
|
+
rightPriceScale: getPriceScaleOptions(data),
|
|
4767
|
+
timeScale: getTimeScaleOptions(selectedRange || defaultRanges[0]),
|
|
4648
4768
|
crosshair: {
|
|
4649
4769
|
vertLine: { color: "rgba(255,255,255,0.12)" },
|
|
4650
4770
|
horzLine: { color: "rgba(255,255,255,0.12)" }
|
|
@@ -4659,17 +4779,37 @@ var PriceChart = o__namespace.forwardRef(
|
|
|
4659
4779
|
});
|
|
4660
4780
|
chartRef.current = chart;
|
|
4661
4781
|
seriesRef.current = series;
|
|
4782
|
+
const handleVisibleRangeChange = () => {
|
|
4783
|
+
const timeScale2 = chart.timeScale();
|
|
4784
|
+
const position2 = timeScale2.scrollPosition();
|
|
4785
|
+
const atRightEdge = position2 <= 0.01;
|
|
4786
|
+
isAutoScrollRef.current = atRightEdge;
|
|
4787
|
+
};
|
|
4788
|
+
const timeScale = chart.timeScale();
|
|
4789
|
+
timeScale.subscribeVisibleLogicalRangeChange(handleVisibleRangeChange);
|
|
4662
4790
|
return () => {
|
|
4663
4791
|
chartRef.current = null;
|
|
4664
4792
|
seriesRef.current = null;
|
|
4793
|
+
timeScale.unsubscribeVisibleLogicalRangeChange(handleVisibleRangeChange);
|
|
4665
4794
|
chart.remove();
|
|
4666
4795
|
};
|
|
4667
4796
|
}, []);
|
|
4797
|
+
o__namespace.useEffect(() => {
|
|
4798
|
+
const chart = chartRef.current;
|
|
4799
|
+
if (!chart) return;
|
|
4800
|
+
const effectiveRange = selectedRange ?? ranges?.[0] ?? "1D";
|
|
4801
|
+
chart.applyOptions({
|
|
4802
|
+
timeScale: getTimeScaleOptions(effectiveRange)
|
|
4803
|
+
});
|
|
4804
|
+
}, [selectedRange, ranges]);
|
|
4668
4805
|
o__namespace.useEffect(() => {
|
|
4669
4806
|
const chart = chartRef.current;
|
|
4670
4807
|
const series = seriesRef.current;
|
|
4671
4808
|
if (!chart || !series) return;
|
|
4672
4809
|
series.setData(data);
|
|
4810
|
+
chart.applyOptions({
|
|
4811
|
+
rightPriceScale: getPriceScaleOptions(data)
|
|
4812
|
+
});
|
|
4673
4813
|
if (priceLineRef.current) {
|
|
4674
4814
|
series.removePriceLine(priceLineRef.current);
|
|
4675
4815
|
priceLineRef.current = null;
|
|
@@ -4685,7 +4825,9 @@ var PriceChart = o__namespace.forwardRef(
|
|
|
4685
4825
|
title: resolvedPrice.toFixed(2)
|
|
4686
4826
|
});
|
|
4687
4827
|
}
|
|
4688
|
-
|
|
4828
|
+
if (isAutoScrollRef.current) {
|
|
4829
|
+
chart.timeScale().scrollToPosition(0, true);
|
|
4830
|
+
}
|
|
4689
4831
|
}, [data, resolvedPrice]);
|
|
4690
4832
|
const sign = inferredChangePercent == null ? null : inferredChangePercent >= 0 ? "+" : "";
|
|
4691
4833
|
const changeClass = inferredChangePercent == null ? "" : inferredChangePercent >= 0 ? "text-[#0ecb81]" : "text-[#f6465d]";
|
|
@@ -4717,30 +4859,97 @@ var PriceChart = o__namespace.forwardRef(
|
|
|
4717
4859
|
/* @__PURE__ */ jsxRuntime.jsxs(CardHeader, { className: "flex flex-col gap-4 px-4 pb-2 pt-5 md:flex-row md:items-start md:justify-between md:px-6 md:pt-6", children: [
|
|
4718
4860
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full flex-col gap-3 md:w-auto", children: [
|
|
4719
4861
|
/* @__PURE__ */ jsxRuntime.jsx(CardTitle, { className: "m-0 text-[1.1rem] font-semibold text-white", children: title }),
|
|
4720
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4721
|
-
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
|
|
4726
|
-
|
|
4727
|
-
|
|
4728
|
-
|
|
4862
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
4863
|
+
visibleRanges.map((r2) => {
|
|
4864
|
+
const active = r2 === selectedRange;
|
|
4865
|
+
const hovered = hoveredRange === r2;
|
|
4866
|
+
const style = {
|
|
4867
|
+
...btnBaseStyle,
|
|
4868
|
+
...hovered ? btnHoverStyle : null,
|
|
4869
|
+
...active ? btnActiveStyle : null
|
|
4870
|
+
};
|
|
4871
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4872
|
+
"button",
|
|
4873
|
+
{
|
|
4874
|
+
type: "button",
|
|
4875
|
+
onClick: () => onRangeChange?.(r2),
|
|
4876
|
+
onMouseEnter: () => setHoveredRange(r2),
|
|
4877
|
+
onMouseLeave: () => setHoveredRange((prev2) => prev2 === r2 ? null : prev2),
|
|
4878
|
+
style,
|
|
4879
|
+
className: cn(
|
|
4880
|
+
"rounded border px-3 py-1 text-[0.85rem] font-medium transition-all duration-200"
|
|
4881
|
+
),
|
|
4882
|
+
children: r2
|
|
4883
|
+
},
|
|
4884
|
+
r2
|
|
4885
|
+
);
|
|
4886
|
+
}),
|
|
4887
|
+
selectedInDropdown && selectedRange ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4729
4888
|
"button",
|
|
4730
4889
|
{
|
|
4731
4890
|
type: "button",
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
|
|
4891
|
+
style: {
|
|
4892
|
+
...btnBaseStyle,
|
|
4893
|
+
...btnActiveStyle
|
|
4894
|
+
},
|
|
4736
4895
|
className: cn(
|
|
4737
4896
|
"rounded border px-3 py-1 text-[0.85rem] font-medium transition-all duration-200"
|
|
4738
4897
|
),
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
)
|
|
4743
|
-
|
|
4898
|
+
disabled: true,
|
|
4899
|
+
children: selectedRange
|
|
4900
|
+
}
|
|
4901
|
+
) : null,
|
|
4902
|
+
dropdownRanges.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", ref: dropdownRef, children: [
|
|
4903
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4904
|
+
"button",
|
|
4905
|
+
{
|
|
4906
|
+
type: "button",
|
|
4907
|
+
onClick: () => setDropdownOpen((prev2) => !prev2),
|
|
4908
|
+
onMouseEnter: () => setHoveredRange("__dropdown__"),
|
|
4909
|
+
onMouseLeave: () => setHoveredRange((prev2) => prev2 === "__dropdown__" ? null : prev2),
|
|
4910
|
+
style: {
|
|
4911
|
+
...btnBaseStyle,
|
|
4912
|
+
...hoveredRange === "__dropdown__" ? btnHoverStyle : null
|
|
4913
|
+
},
|
|
4914
|
+
className: cn(
|
|
4915
|
+
"flex items-center gap-1 rounded border px-3 py-1 text-[0.85rem] font-medium transition-all duration-200"
|
|
4916
|
+
),
|
|
4917
|
+
children: [
|
|
4918
|
+
"More",
|
|
4919
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4920
|
+
"svg",
|
|
4921
|
+
{
|
|
4922
|
+
className: cn("h-3 w-3 transition-transform", dropdownOpen && "rotate-180"),
|
|
4923
|
+
fill: "none",
|
|
4924
|
+
stroke: "currentColor",
|
|
4925
|
+
viewBox: "0 0 24 24",
|
|
4926
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" })
|
|
4927
|
+
}
|
|
4928
|
+
)
|
|
4929
|
+
]
|
|
4930
|
+
}
|
|
4931
|
+
),
|
|
4932
|
+
dropdownOpen && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute left-0 top-full z-50 mt-1 min-w-[80px] rounded border border-white/10 bg-black/90 py-1 backdrop-blur-md", children: dropdownRanges.map((r2) => {
|
|
4933
|
+
const active = r2 === selectedRange;
|
|
4934
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4935
|
+
"button",
|
|
4936
|
+
{
|
|
4937
|
+
type: "button",
|
|
4938
|
+
onClick: () => {
|
|
4939
|
+
onRangeChange?.(r2);
|
|
4940
|
+
setDropdownOpen(false);
|
|
4941
|
+
},
|
|
4942
|
+
className: cn(
|
|
4943
|
+
"block w-full px-3 py-1.5 text-left text-[0.85rem] font-medium transition-colors hover:bg-white/10",
|
|
4944
|
+
active ? "bg-[#e6c87e]/20 text-[#e6c87e]" : "text-white/70"
|
|
4945
|
+
),
|
|
4946
|
+
children: r2
|
|
4947
|
+
},
|
|
4948
|
+
r2
|
|
4949
|
+
);
|
|
4950
|
+
}) })
|
|
4951
|
+
] })
|
|
4952
|
+
] })
|
|
4744
4953
|
] }),
|
|
4745
4954
|
resolvedPrice == null && inferredChangePercent == null ? null : /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center" }, children: [
|
|
4746
4955
|
resolvedPrice == null ? null : /* @__PURE__ */ jsxRuntime.jsx(
|