@x-plat/design-system 0.5.42 → 0.5.44
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/components/Dropdown/index.cjs +22 -22
- package/dist/components/Dropdown/index.js +22 -22
- package/dist/components/PopOver/index.cjs +22 -22
- package/dist/components/PopOver/index.js +22 -22
- package/dist/components/Select/index.cjs +22 -22
- package/dist/components/Select/index.js +22 -22
- package/dist/components/Video/index.cjs +201 -201
- package/dist/components/Video/index.js +243 -243
- package/dist/components/index.cjs +278 -278
- package/dist/components/index.css +700 -188
- package/dist/components/index.d.cts +2 -2
- package/dist/components/index.d.ts +2 -2
- package/dist/components/index.js +278 -278
- package/dist/index.cjs +278 -278
- package/dist/index.css +700 -188
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +278 -278
- package/dist/layout/index.css +520 -8
- package/guidelines/AGENT_PROMPT.md +248 -0
- package/guidelines/Guidelines.md +8 -0
- package/guidelines/composition/layout.md +87 -16
- package/guidelines/setup.md +11 -2
- package/package.json +1 -1
|
@@ -1637,15 +1637,31 @@ var Badge = (props) => {
|
|
|
1637
1637
|
Badge.displayName = "Badge";
|
|
1638
1638
|
var Badge_default = Badge;
|
|
1639
1639
|
|
|
1640
|
-
// src/components/
|
|
1640
|
+
// src/components/Box/Box.tsx
|
|
1641
1641
|
var import_jsx_runtime299 = require("react/jsx-runtime");
|
|
1642
|
+
var Box = ({
|
|
1643
|
+
children,
|
|
1644
|
+
title,
|
|
1645
|
+
variant = "outlined",
|
|
1646
|
+
padding = "md"
|
|
1647
|
+
}) => {
|
|
1648
|
+
return /* @__PURE__ */ (0, import_jsx_runtime299.jsxs)("div", { className: clsx_default("lib-xplat-box", variant, `pad-${padding}`), children: [
|
|
1649
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime299.jsx)("div", { className: "box-title", children: title }),
|
|
1650
|
+
/* @__PURE__ */ (0, import_jsx_runtime299.jsx)("div", { className: "box-content", children })
|
|
1651
|
+
] });
|
|
1652
|
+
};
|
|
1653
|
+
Box.displayName = "Box";
|
|
1654
|
+
var Box_default = Box;
|
|
1655
|
+
|
|
1656
|
+
// src/components/Breadcrumb/Breadcrumb.tsx
|
|
1657
|
+
var import_jsx_runtime300 = require("react/jsx-runtime");
|
|
1642
1658
|
var Breadcrumb = (props) => {
|
|
1643
1659
|
const { items, separator = "/" } = props;
|
|
1644
|
-
return /* @__PURE__ */ (0,
|
|
1660
|
+
return /* @__PURE__ */ (0, import_jsx_runtime300.jsx)("nav", { className: "lib-xplat-breadcrumb", "aria-label": "\uACBD\uB85C", children: /* @__PURE__ */ (0, import_jsx_runtime300.jsx)("ol", { children: items.map((item, index) => {
|
|
1645
1661
|
const isLast = index === items.length - 1;
|
|
1646
|
-
return /* @__PURE__ */ (0,
|
|
1647
|
-
isLast ? /* @__PURE__ */ (0,
|
|
1648
|
-
!isLast && /* @__PURE__ */ (0,
|
|
1662
|
+
return /* @__PURE__ */ (0, import_jsx_runtime300.jsxs)("li", { children: [
|
|
1663
|
+
isLast ? /* @__PURE__ */ (0, import_jsx_runtime300.jsx)("span", { className: "current", "aria-current": "page", children: item.label }) : item.href ? /* @__PURE__ */ (0, import_jsx_runtime300.jsx)("a", { href: item.href, className: "link", children: item.label }) : /* @__PURE__ */ (0, import_jsx_runtime300.jsx)("button", { className: "link", onClick: item.onClick, children: item.label }),
|
|
1664
|
+
!isLast && /* @__PURE__ */ (0, import_jsx_runtime300.jsx)("span", { className: "separator", children: separator })
|
|
1649
1665
|
] }, index);
|
|
1650
1666
|
}) }) });
|
|
1651
1667
|
};
|
|
@@ -1653,7 +1669,7 @@ Breadcrumb.displayName = "Breadcrumb";
|
|
|
1653
1669
|
var Breadcrumb_default = Breadcrumb;
|
|
1654
1670
|
|
|
1655
1671
|
// src/components/Button/Button.tsx
|
|
1656
|
-
var
|
|
1672
|
+
var import_jsx_runtime301 = require("react/jsx-runtime");
|
|
1657
1673
|
var Button = (props) => {
|
|
1658
1674
|
const {
|
|
1659
1675
|
children,
|
|
@@ -1662,7 +1678,7 @@ var Button = (props) => {
|
|
|
1662
1678
|
disabled,
|
|
1663
1679
|
...rest
|
|
1664
1680
|
} = props;
|
|
1665
|
-
return /* @__PURE__ */ (0,
|
|
1681
|
+
return /* @__PURE__ */ (0, import_jsx_runtime301.jsx)(
|
|
1666
1682
|
"button",
|
|
1667
1683
|
{
|
|
1668
1684
|
className: clsx_default("lib-xplat-button", type, size),
|
|
@@ -1779,7 +1795,7 @@ var MONTH_LABELS = {
|
|
|
1779
1795
|
};
|
|
1780
1796
|
|
|
1781
1797
|
// src/components/Calendar/Calendar.tsx
|
|
1782
|
-
var
|
|
1798
|
+
var import_jsx_runtime302 = require("react/jsx-runtime");
|
|
1783
1799
|
var DayCell = import_react3.default.memo(
|
|
1784
1800
|
({
|
|
1785
1801
|
day,
|
|
@@ -1791,7 +1807,7 @@ var DayCell = import_react3.default.memo(
|
|
|
1791
1807
|
onEventClick
|
|
1792
1808
|
}) => {
|
|
1793
1809
|
if (renderDay) {
|
|
1794
|
-
return /* @__PURE__ */ (0,
|
|
1810
|
+
return /* @__PURE__ */ (0, import_jsx_runtime302.jsx)(
|
|
1795
1811
|
"div",
|
|
1796
1812
|
{
|
|
1797
1813
|
className: clsx_default(
|
|
@@ -1808,7 +1824,7 @@ var DayCell = import_react3.default.memo(
|
|
|
1808
1824
|
}
|
|
1809
1825
|
);
|
|
1810
1826
|
}
|
|
1811
|
-
return /* @__PURE__ */ (0,
|
|
1827
|
+
return /* @__PURE__ */ (0, import_jsx_runtime302.jsxs)(
|
|
1812
1828
|
"div",
|
|
1813
1829
|
{
|
|
1814
1830
|
className: clsx_default(
|
|
@@ -1824,9 +1840,9 @@ var DayCell = import_react3.default.memo(
|
|
|
1824
1840
|
if (!disabled && day.isCurrentMonth) onSelect?.(day.date);
|
|
1825
1841
|
},
|
|
1826
1842
|
children: [
|
|
1827
|
-
/* @__PURE__ */ (0,
|
|
1828
|
-
dayEvents.length > 0 && /* @__PURE__ */ (0,
|
|
1829
|
-
dayEvents.slice(0, 3).map((event, ei) => /* @__PURE__ */ (0,
|
|
1843
|
+
/* @__PURE__ */ (0, import_jsx_runtime302.jsx)("span", { className: "calendar-day-number", children: day.day }),
|
|
1844
|
+
dayEvents.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime302.jsxs)("div", { className: "calendar-day-events", children: [
|
|
1845
|
+
dayEvents.slice(0, 3).map((event, ei) => /* @__PURE__ */ (0, import_jsx_runtime302.jsx)(
|
|
1830
1846
|
"span",
|
|
1831
1847
|
{
|
|
1832
1848
|
className: "calendar-event-dot",
|
|
@@ -1839,7 +1855,7 @@ var DayCell = import_react3.default.memo(
|
|
|
1839
1855
|
},
|
|
1840
1856
|
ei
|
|
1841
1857
|
)),
|
|
1842
|
-
dayEvents.length > 3 && /* @__PURE__ */ (0,
|
|
1858
|
+
dayEvents.length > 3 && /* @__PURE__ */ (0, import_jsx_runtime302.jsxs)("span", { className: "calendar-event-more", children: [
|
|
1843
1859
|
"+",
|
|
1844
1860
|
dayEvents.length - 3
|
|
1845
1861
|
] })
|
|
@@ -1960,21 +1976,21 @@ var Calendar = (props) => {
|
|
|
1960
1976
|
const weekdays = WEEKDAY_LABELS[locale];
|
|
1961
1977
|
const monthLabels = MONTH_LABELS[locale];
|
|
1962
1978
|
const titleText = pickerMode === "days" ? locale === "ko" ? `${year}\uB144 ${monthLabels[month]}` : `${monthLabels[month]} ${year}` : pickerMode === "months" ? `${year}` : `${yearRangeStart} - ${yearRangeStart + 11}`;
|
|
1963
|
-
return /* @__PURE__ */ (0,
|
|
1979
|
+
return /* @__PURE__ */ (0, import_jsx_runtime302.jsxs)(
|
|
1964
1980
|
"div",
|
|
1965
1981
|
{
|
|
1966
1982
|
className: "lib-xplat-calendar",
|
|
1967
1983
|
style: selectedColor ? { "--calendar-selected-color": `var(--${selectedColor})` } : void 0,
|
|
1968
1984
|
children: [
|
|
1969
|
-
/* @__PURE__ */ (0,
|
|
1970
|
-
/* @__PURE__ */ (0,
|
|
1971
|
-
/* @__PURE__ */ (0,
|
|
1972
|
-
/* @__PURE__ */ (0,
|
|
1973
|
-
showToday && /* @__PURE__ */ (0,
|
|
1985
|
+
/* @__PURE__ */ (0, import_jsx_runtime302.jsxs)("div", { className: "calendar-header", children: [
|
|
1986
|
+
/* @__PURE__ */ (0, import_jsx_runtime302.jsx)("button", { className: "calendar-nav", onClick: handlePrev, "aria-label": "\uC774\uC804", children: /* @__PURE__ */ (0, import_jsx_runtime302.jsx)(ChevronLeftIcon_default, {}) }),
|
|
1987
|
+
/* @__PURE__ */ (0, import_jsx_runtime302.jsx)("button", { className: "calendar-title", onClick: handleTitleClick, type: "button", children: titleText }),
|
|
1988
|
+
/* @__PURE__ */ (0, import_jsx_runtime302.jsx)("button", { className: "calendar-nav", onClick: handleNext, "aria-label": "\uB2E4\uC74C", children: /* @__PURE__ */ (0, import_jsx_runtime302.jsx)(ChevronRightIcon_default, {}) }),
|
|
1989
|
+
showToday && /* @__PURE__ */ (0, import_jsx_runtime302.jsx)("button", { className: "calendar-today-btn", onClick: handleToday, children: locale === "ko" ? "\uC624\uB298" : "Today" })
|
|
1974
1990
|
] }),
|
|
1975
|
-
pickerMode === "years" && /* @__PURE__ */ (0,
|
|
1991
|
+
pickerMode === "years" && /* @__PURE__ */ (0, import_jsx_runtime302.jsx)("div", { className: "calendar-picker-grid", children: Array.from({ length: 12 }, (_, i) => {
|
|
1976
1992
|
const y = yearRangeStart + i;
|
|
1977
|
-
return /* @__PURE__ */ (0,
|
|
1993
|
+
return /* @__PURE__ */ (0, import_jsx_runtime302.jsx)(
|
|
1978
1994
|
"button",
|
|
1979
1995
|
{
|
|
1980
1996
|
type: "button",
|
|
@@ -1985,7 +2001,7 @@ var Calendar = (props) => {
|
|
|
1985
2001
|
y
|
|
1986
2002
|
);
|
|
1987
2003
|
}) }),
|
|
1988
|
-
pickerMode === "months" && /* @__PURE__ */ (0,
|
|
2004
|
+
pickerMode === "months" && /* @__PURE__ */ (0, import_jsx_runtime302.jsx)("div", { className: "calendar-picker-grid", children: monthLabels.map((label, i) => /* @__PURE__ */ (0, import_jsx_runtime302.jsx)(
|
|
1989
2005
|
"button",
|
|
1990
2006
|
{
|
|
1991
2007
|
type: "button",
|
|
@@ -1995,8 +2011,8 @@ var Calendar = (props) => {
|
|
|
1995
2011
|
},
|
|
1996
2012
|
i
|
|
1997
2013
|
)) }),
|
|
1998
|
-
pickerMode === "days" && /* @__PURE__ */ (0,
|
|
1999
|
-
/* @__PURE__ */ (0,
|
|
2014
|
+
pickerMode === "days" && /* @__PURE__ */ (0, import_jsx_runtime302.jsxs)(import_jsx_runtime302.Fragment, { children: [
|
|
2015
|
+
/* @__PURE__ */ (0, import_jsx_runtime302.jsx)("div", { className: "calendar-weekdays", children: weekdays.map((label, i) => /* @__PURE__ */ (0, import_jsx_runtime302.jsx)(
|
|
2000
2016
|
"div",
|
|
2001
2017
|
{
|
|
2002
2018
|
className: clsx_default(
|
|
@@ -2008,12 +2024,12 @@ var Calendar = (props) => {
|
|
|
2008
2024
|
},
|
|
2009
2025
|
label
|
|
2010
2026
|
)) }),
|
|
2011
|
-
/* @__PURE__ */ (0,
|
|
2027
|
+
/* @__PURE__ */ (0, import_jsx_runtime302.jsx)("div", { className: "calendar-grid", children: days.map((day, idx) => {
|
|
2012
2028
|
const dayEvents = getEventsForDay(day.date);
|
|
2013
2029
|
const t = day.date.getTime();
|
|
2014
2030
|
const disabled = t < minTime || t > maxTime;
|
|
2015
2031
|
const isSelected = selectedDate ? isSameDay(day.date, selectedDate) : false;
|
|
2016
|
-
return /* @__PURE__ */ (0,
|
|
2032
|
+
return /* @__PURE__ */ (0, import_jsx_runtime302.jsx)(
|
|
2017
2033
|
DayCell,
|
|
2018
2034
|
{
|
|
2019
2035
|
day,
|
|
@@ -2035,139 +2051,14 @@ var Calendar = (props) => {
|
|
|
2035
2051
|
Calendar.displayName = "Calendar";
|
|
2036
2052
|
var Calendar_default = Calendar;
|
|
2037
2053
|
|
|
2038
|
-
// src/components/ChatInput/ChatInput.tsx
|
|
2039
|
-
var import_react4 = __toESM(require("react"), 1);
|
|
2040
|
-
|
|
2041
|
-
// src/components/IconButton/IconButton.tsx
|
|
2042
|
-
var import_jsx_runtime302 = require("react/jsx-runtime");
|
|
2043
|
-
var IconButton = (props) => {
|
|
2044
|
-
const {
|
|
2045
|
-
icon,
|
|
2046
|
-
type = "primary",
|
|
2047
|
-
size = "md",
|
|
2048
|
-
disabled,
|
|
2049
|
-
...rest
|
|
2050
|
-
} = props;
|
|
2051
|
-
return /* @__PURE__ */ (0, import_jsx_runtime302.jsx)(
|
|
2052
|
-
"button",
|
|
2053
|
-
{
|
|
2054
|
-
className: clsx_default("lib-xplat-icon-button", type, size),
|
|
2055
|
-
disabled,
|
|
2056
|
-
...rest,
|
|
2057
|
-
children: icon
|
|
2058
|
-
}
|
|
2059
|
-
);
|
|
2060
|
-
};
|
|
2061
|
-
IconButton.displayName = "IconButton";
|
|
2062
|
-
var IconButton_default = IconButton;
|
|
2063
|
-
|
|
2064
|
-
// src/components/ChatInput/ChatInput.tsx
|
|
2065
|
-
var import_jsx_runtime303 = require("react/jsx-runtime");
|
|
2066
|
-
var MAX_HEIGHT = 200;
|
|
2067
|
-
var ChatInput = import_react4.default.forwardRef(
|
|
2068
|
-
(props, ref) => {
|
|
2069
|
-
const {
|
|
2070
|
-
placeholder,
|
|
2071
|
-
value: valueProp,
|
|
2072
|
-
disabled = false,
|
|
2073
|
-
buttonType = "primary",
|
|
2074
|
-
onSubmit,
|
|
2075
|
-
onChange
|
|
2076
|
-
} = props;
|
|
2077
|
-
const isControlled = valueProp !== void 0;
|
|
2078
|
-
const [internalValue, setInternalValue] = import_react4.default.useState("");
|
|
2079
|
-
const value = isControlled ? valueProp : internalValue;
|
|
2080
|
-
const hasText = value.trim().length > 0;
|
|
2081
|
-
const textareaRef = import_react4.default.useRef(null);
|
|
2082
|
-
const setRefs = import_react4.default.useCallback(
|
|
2083
|
-
(el) => {
|
|
2084
|
-
textareaRef.current = el;
|
|
2085
|
-
if (typeof ref === "function") ref(el);
|
|
2086
|
-
else if (ref) ref.current = el;
|
|
2087
|
-
},
|
|
2088
|
-
[ref]
|
|
2089
|
-
);
|
|
2090
|
-
const updateHeight = import_react4.default.useCallback(() => {
|
|
2091
|
-
const el = textareaRef.current;
|
|
2092
|
-
if (!el) return;
|
|
2093
|
-
el.style.height = "0px";
|
|
2094
|
-
el.style.height = `${Math.min(el.scrollHeight, MAX_HEIGHT)}px`;
|
|
2095
|
-
}, []);
|
|
2096
|
-
const handleChange = (e) => {
|
|
2097
|
-
const val = e.target.value;
|
|
2098
|
-
if (!isControlled) setInternalValue(val);
|
|
2099
|
-
onChange?.(val);
|
|
2100
|
-
};
|
|
2101
|
-
const handleSubmit = () => {
|
|
2102
|
-
if (!hasText || disabled) return;
|
|
2103
|
-
onSubmit?.(value);
|
|
2104
|
-
if (!isControlled) setInternalValue("");
|
|
2105
|
-
requestAnimationFrame(updateHeight);
|
|
2106
|
-
};
|
|
2107
|
-
const handleKeyDown = (e) => {
|
|
2108
|
-
if (e.key === "Enter" && !e.shiftKey) {
|
|
2109
|
-
e.preventDefault();
|
|
2110
|
-
handleSubmit();
|
|
2111
|
-
}
|
|
2112
|
-
};
|
|
2113
|
-
import_react4.default.useEffect(() => {
|
|
2114
|
-
updateHeight();
|
|
2115
|
-
}, [value, updateHeight]);
|
|
2116
|
-
return /* @__PURE__ */ (0, import_jsx_runtime303.jsxs)("div", { className: clsx_default("lib-xplat-chat-input", disabled && "disabled"), children: [
|
|
2117
|
-
/* @__PURE__ */ (0, import_jsx_runtime303.jsx)(
|
|
2118
|
-
"textarea",
|
|
2119
|
-
{
|
|
2120
|
-
ref: setRefs,
|
|
2121
|
-
className: "chat-input-textarea",
|
|
2122
|
-
placeholder,
|
|
2123
|
-
value,
|
|
2124
|
-
disabled,
|
|
2125
|
-
rows: 1,
|
|
2126
|
-
onChange: handleChange,
|
|
2127
|
-
onKeyDown: handleKeyDown
|
|
2128
|
-
}
|
|
2129
|
-
),
|
|
2130
|
-
/* @__PURE__ */ (0, import_jsx_runtime303.jsx)(
|
|
2131
|
-
IconButton_default,
|
|
2132
|
-
{
|
|
2133
|
-
icon: /* @__PURE__ */ (0, import_jsx_runtime303.jsx)(MessageSquareIcon_default, {}),
|
|
2134
|
-
type: buttonType,
|
|
2135
|
-
size: "sm",
|
|
2136
|
-
disabled: !hasText || disabled,
|
|
2137
|
-
onClick: handleSubmit,
|
|
2138
|
-
"aria-label": "\uC804\uC1A1"
|
|
2139
|
-
}
|
|
2140
|
-
)
|
|
2141
|
-
] });
|
|
2142
|
-
}
|
|
2143
|
-
);
|
|
2144
|
-
ChatInput.displayName = "ChatInput";
|
|
2145
|
-
var ChatInput_default = ChatInput;
|
|
2146
|
-
|
|
2147
|
-
// src/components/Box/Box.tsx
|
|
2148
|
-
var import_jsx_runtime304 = require("react/jsx-runtime");
|
|
2149
|
-
var Box = ({
|
|
2150
|
-
children,
|
|
2151
|
-
title,
|
|
2152
|
-
variant = "outlined",
|
|
2153
|
-
padding = "md"
|
|
2154
|
-
}) => {
|
|
2155
|
-
return /* @__PURE__ */ (0, import_jsx_runtime304.jsxs)("div", { className: clsx_default("lib-xplat-box", variant, `pad-${padding}`), children: [
|
|
2156
|
-
title && /* @__PURE__ */ (0, import_jsx_runtime304.jsx)("div", { className: "box-title", children: title }),
|
|
2157
|
-
/* @__PURE__ */ (0, import_jsx_runtime304.jsx)("div", { className: "box-content", children })
|
|
2158
|
-
] });
|
|
2159
|
-
};
|
|
2160
|
-
Box.displayName = "Box";
|
|
2161
|
-
var Box_default = Box;
|
|
2162
|
-
|
|
2163
2054
|
// src/components/CardTab/CardTab.tsx
|
|
2164
|
-
var
|
|
2055
|
+
var import_react4 = __toESM(require("react"), 1);
|
|
2165
2056
|
|
|
2166
2057
|
// src/components/CardTab/CardTabPanel.tsx
|
|
2167
|
-
var
|
|
2058
|
+
var import_jsx_runtime303 = require("react/jsx-runtime");
|
|
2168
2059
|
var CardTabPanel = (props) => {
|
|
2169
2060
|
const { children, columns = 3 } = props;
|
|
2170
|
-
return /* @__PURE__ */ (0,
|
|
2061
|
+
return /* @__PURE__ */ (0, import_jsx_runtime303.jsx)(
|
|
2171
2062
|
"div",
|
|
2172
2063
|
{
|
|
2173
2064
|
className: "card-tab-panel",
|
|
@@ -2180,7 +2071,7 @@ CardTabPanel.displayName = "CardTab.Panel";
|
|
|
2180
2071
|
var CardTabPanel_default = CardTabPanel;
|
|
2181
2072
|
|
|
2182
2073
|
// src/components/CardTab/CardTab.tsx
|
|
2183
|
-
var
|
|
2074
|
+
var import_jsx_runtime304 = require("react/jsx-runtime");
|
|
2184
2075
|
var CardTabRoot = (props) => {
|
|
2185
2076
|
const {
|
|
2186
2077
|
tabs,
|
|
@@ -2190,7 +2081,7 @@ var CardTabRoot = (props) => {
|
|
|
2190
2081
|
children
|
|
2191
2082
|
} = props;
|
|
2192
2083
|
const isControlled = activeValueProp !== void 0;
|
|
2193
|
-
const [uncontrolledValue, setUncontrolledValue] =
|
|
2084
|
+
const [uncontrolledValue, setUncontrolledValue] = import_react4.default.useState(tabs[0]?.value ?? "");
|
|
2194
2085
|
const activeValue = isControlled ? activeValueProp : uncontrolledValue;
|
|
2195
2086
|
const handleTabClick = (tab) => {
|
|
2196
2087
|
if (!isControlled) {
|
|
@@ -2198,16 +2089,16 @@ var CardTabRoot = (props) => {
|
|
|
2198
2089
|
}
|
|
2199
2090
|
onChange?.(tab);
|
|
2200
2091
|
};
|
|
2201
|
-
const panels =
|
|
2202
|
-
(child) =>
|
|
2092
|
+
const panels = import_react4.default.Children.toArray(children).filter(
|
|
2093
|
+
(child) => import_react4.default.isValidElement(child) && child.type === CardTabPanel_default
|
|
2203
2094
|
);
|
|
2204
2095
|
const activePanel = panels.find(
|
|
2205
2096
|
(panel) => panel.props.value === activeValue
|
|
2206
2097
|
);
|
|
2207
|
-
return /* @__PURE__ */ (0,
|
|
2208
|
-
/* @__PURE__ */ (0,
|
|
2098
|
+
return /* @__PURE__ */ (0, import_jsx_runtime304.jsxs)("div", { className: clsx_default("lib-xplat-card-tab", size), children: [
|
|
2099
|
+
/* @__PURE__ */ (0, import_jsx_runtime304.jsx)("div", { className: "card-tab-bar", children: tabs.map((tab) => {
|
|
2209
2100
|
const isActive = tab.value === activeValue;
|
|
2210
|
-
return /* @__PURE__ */ (0,
|
|
2101
|
+
return /* @__PURE__ */ (0, import_jsx_runtime304.jsx)(
|
|
2211
2102
|
"button",
|
|
2212
2103
|
{
|
|
2213
2104
|
className: clsx_default("card-tab-trigger", isActive && "active"),
|
|
@@ -2219,7 +2110,7 @@ var CardTabRoot = (props) => {
|
|
|
2219
2110
|
tab.value
|
|
2220
2111
|
);
|
|
2221
2112
|
}) }),
|
|
2222
|
-
/* @__PURE__ */ (0,
|
|
2113
|
+
/* @__PURE__ */ (0, import_jsx_runtime304.jsx)("div", { className: "card-tab-body", children: activePanel })
|
|
2223
2114
|
] });
|
|
2224
2115
|
};
|
|
2225
2116
|
CardTabRoot.displayName = "CardTab";
|
|
@@ -2229,8 +2120,8 @@ var CardTab = Object.assign(CardTabRoot, {
|
|
|
2229
2120
|
var CardTab_default = CardTab;
|
|
2230
2121
|
|
|
2231
2122
|
// src/components/Chart/Chart.tsx
|
|
2232
|
-
var
|
|
2233
|
-
var
|
|
2123
|
+
var import_react5 = __toESM(require("react"), 1);
|
|
2124
|
+
var import_jsx_runtime305 = require("react/jsx-runtime");
|
|
2234
2125
|
var CATEGORICAL_COUNT2 = 8;
|
|
2235
2126
|
var LINE_BAR_PALETTES = Array.from({ length: CATEGORICAL_COUNT2 }, (_, i) => {
|
|
2236
2127
|
const n = i + 1;
|
|
@@ -2275,8 +2166,8 @@ var toSmoothPath = (points) => {
|
|
|
2275
2166
|
return d;
|
|
2276
2167
|
};
|
|
2277
2168
|
var useChartSize = (ref) => {
|
|
2278
|
-
const [size, setSize] =
|
|
2279
|
-
|
|
2169
|
+
const [size, setSize] = import_react5.default.useState({ width: 0, height: 0 });
|
|
2170
|
+
import_react5.default.useEffect(() => {
|
|
2280
2171
|
const el = ref.current;
|
|
2281
2172
|
if (!el) return;
|
|
2282
2173
|
let rafId = 0;
|
|
@@ -2302,10 +2193,10 @@ var useChartSize = (ref) => {
|
|
|
2302
2193
|
};
|
|
2303
2194
|
var prefersReducedMotion = () => typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
2304
2195
|
var useChartAnimation = (containerRef, dataKey) => {
|
|
2305
|
-
const [animate, setAnimate] =
|
|
2306
|
-
const prevDataKey =
|
|
2307
|
-
const hasAnimated =
|
|
2308
|
-
|
|
2196
|
+
const [animate, setAnimate] = import_react5.default.useState(false);
|
|
2197
|
+
const prevDataKey = import_react5.default.useRef(dataKey);
|
|
2198
|
+
const hasAnimated = import_react5.default.useRef(false);
|
|
2199
|
+
import_react5.default.useEffect(() => {
|
|
2309
2200
|
if (prefersReducedMotion()) return;
|
|
2310
2201
|
const el = containerRef.current;
|
|
2311
2202
|
if (!el) return;
|
|
@@ -2321,7 +2212,7 @@ var useChartAnimation = (containerRef, dataKey) => {
|
|
|
2321
2212
|
observer.observe(el);
|
|
2322
2213
|
return () => observer.disconnect();
|
|
2323
2214
|
}, [containerRef]);
|
|
2324
|
-
|
|
2215
|
+
import_react5.default.useEffect(() => {
|
|
2325
2216
|
if (dataKey !== prevDataKey.current) {
|
|
2326
2217
|
prevDataKey.current = dataKey;
|
|
2327
2218
|
if (prefersReducedMotion()) return;
|
|
@@ -2335,15 +2226,15 @@ var useChartAnimation = (containerRef, dataKey) => {
|
|
|
2335
2226
|
};
|
|
2336
2227
|
var TOOLTIP_OFFSET = 12;
|
|
2337
2228
|
var useChartTooltip = (enabled) => {
|
|
2338
|
-
const [tooltip, setTooltip] =
|
|
2229
|
+
const [tooltip, setTooltip] = import_react5.default.useState({
|
|
2339
2230
|
visible: false,
|
|
2340
2231
|
x: 0,
|
|
2341
2232
|
y: 0,
|
|
2342
2233
|
content: ""
|
|
2343
2234
|
});
|
|
2344
|
-
const containerRef =
|
|
2345
|
-
const rafRef =
|
|
2346
|
-
const move =
|
|
2235
|
+
const containerRef = import_react5.default.useRef(null);
|
|
2236
|
+
const rafRef = import_react5.default.useRef(0);
|
|
2237
|
+
const move = import_react5.default.useCallback((e) => {
|
|
2347
2238
|
if (!enabled) return;
|
|
2348
2239
|
const cx = e.clientX;
|
|
2349
2240
|
const cy = e.clientY;
|
|
@@ -2354,24 +2245,24 @@ var useChartTooltip = (enabled) => {
|
|
|
2354
2245
|
setTooltip((prev) => ({ ...prev, x: cx - rect.left, y: cy - rect.top }));
|
|
2355
2246
|
});
|
|
2356
2247
|
}, [enabled]);
|
|
2357
|
-
const show =
|
|
2248
|
+
const show = import_react5.default.useCallback((e, content) => {
|
|
2358
2249
|
if (!enabled) return;
|
|
2359
2250
|
const rect = containerRef.current?.getBoundingClientRect();
|
|
2360
2251
|
if (!rect) return;
|
|
2361
2252
|
setTooltip({ visible: true, x: e.clientX - rect.left, y: e.clientY - rect.top, content });
|
|
2362
2253
|
}, [enabled]);
|
|
2363
|
-
const hide =
|
|
2254
|
+
const hide = import_react5.default.useCallback(() => {
|
|
2364
2255
|
cancelAnimationFrame(rafRef.current);
|
|
2365
2256
|
setTooltip((prev) => ({ ...prev, visible: false }));
|
|
2366
2257
|
}, []);
|
|
2367
2258
|
return { tooltip, show, hide, move, containerRef };
|
|
2368
2259
|
};
|
|
2369
|
-
var GridLines =
|
|
2260
|
+
var GridLines = import_react5.default.memo(({ width, height, chartH, maxVal }) => /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(import_jsx_runtime305.Fragment, { children: [0, 0.25, 0.5, 0.75, 1].map((ratio) => {
|
|
2370
2261
|
const y = PADDING.top + (1 - ratio) * chartH;
|
|
2371
2262
|
const val = Math.round(maxVal * ratio);
|
|
2372
|
-
return /* @__PURE__ */ (0,
|
|
2373
|
-
/* @__PURE__ */ (0,
|
|
2374
|
-
/* @__PURE__ */ (0,
|
|
2263
|
+
return /* @__PURE__ */ (0, import_jsx_runtime305.jsxs)("g", { children: [
|
|
2264
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsx)("line", { x1: PADDING.left, y1: y, x2: width - PADDING.right, y2: y, className: "chart-grid" }),
|
|
2265
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsx)("text", { x: PADDING.left - 8, y: y + 4, className: "chart-axis-label", textAnchor: "end", children: val })
|
|
2375
2266
|
] }, ratio);
|
|
2376
2267
|
}) }));
|
|
2377
2268
|
GridLines.displayName = "GridLines";
|
|
@@ -2381,18 +2272,18 @@ var getLabelStep = (count, chartW) => {
|
|
|
2381
2272
|
if (count <= maxLabels) return 1;
|
|
2382
2273
|
return Math.ceil(count / maxLabels);
|
|
2383
2274
|
};
|
|
2384
|
-
var AxisLabels =
|
|
2275
|
+
var AxisLabels = import_react5.default.memo(({ labels, count, chartW, height }) => {
|
|
2385
2276
|
const step = getLabelStep(count, chartW);
|
|
2386
|
-
return /* @__PURE__ */ (0,
|
|
2277
|
+
return /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(import_jsx_runtime305.Fragment, { children: labels.map((label, i) => {
|
|
2387
2278
|
if (i % step !== 0) return null;
|
|
2388
2279
|
const x = PADDING.left + i / (count - 1 || 1) * chartW;
|
|
2389
|
-
return /* @__PURE__ */ (0,
|
|
2280
|
+
return /* @__PURE__ */ (0, import_jsx_runtime305.jsx)("text", { x, y: height - 8, className: "chart-axis-label", textAnchor: "middle", children: label }, i);
|
|
2390
2281
|
}) });
|
|
2391
2282
|
});
|
|
2392
2283
|
AxisLabels.displayName = "AxisLabels";
|
|
2393
2284
|
var useCrosshair = (seriesPoints, entries, labels, chartH) => {
|
|
2394
|
-
const [activeIndex, setActiveIndex] =
|
|
2395
|
-
const handleMouseMove =
|
|
2285
|
+
const [activeIndex, setActiveIndex] = import_react5.default.useState(null);
|
|
2286
|
+
const handleMouseMove = import_react5.default.useCallback((e) => {
|
|
2396
2287
|
const svg = e.currentTarget;
|
|
2397
2288
|
const rect = svg.getBoundingClientRect();
|
|
2398
2289
|
const mx = (e.clientX - rect.left) / rect.width * svg.viewBox.baseVal.width;
|
|
@@ -2411,17 +2302,17 @@ var useCrosshair = (seriesPoints, entries, labels, chartH) => {
|
|
|
2411
2302
|
}
|
|
2412
2303
|
setActiveIndex(minDist <= threshold ? closest : null);
|
|
2413
2304
|
}, [seriesPoints]);
|
|
2414
|
-
const handleMouseLeave =
|
|
2305
|
+
const handleMouseLeave = import_react5.default.useCallback(() => {
|
|
2415
2306
|
setActiveIndex(null);
|
|
2416
2307
|
}, []);
|
|
2417
|
-
const tooltipContent =
|
|
2308
|
+
const tooltipContent = import_react5.default.useMemo(() => {
|
|
2418
2309
|
if (activeIndex === null) return "";
|
|
2419
2310
|
return entries.map(([key], di) => {
|
|
2420
2311
|
const p = seriesPoints[di]?.[activeIndex];
|
|
2421
2312
|
return p ? `${key}: ${p.v}` : "";
|
|
2422
2313
|
}).filter(Boolean).join(" / ");
|
|
2423
2314
|
}, [activeIndex, entries, seriesPoints]);
|
|
2424
|
-
const getTooltipAt =
|
|
2315
|
+
const getTooltipAt = import_react5.default.useCallback((idx) => {
|
|
2425
2316
|
return entries.map(([key], di) => {
|
|
2426
2317
|
const p = seriesPoints[di]?.[idx];
|
|
2427
2318
|
return p ? `${key}: ${p.v}` : "";
|
|
@@ -2429,16 +2320,16 @@ var useCrosshair = (seriesPoints, entries, labels, chartH) => {
|
|
|
2429
2320
|
}, [entries, seriesPoints]);
|
|
2430
2321
|
return { activeIndex, handleMouseMove, handleMouseLeave, tooltipContent, getTooltipAt };
|
|
2431
2322
|
};
|
|
2432
|
-
var LineChart =
|
|
2433
|
-
const entries =
|
|
2434
|
-
const maxVal =
|
|
2323
|
+
var LineChart = import_react5.default.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
|
|
2324
|
+
const entries = import_react5.default.useMemo(() => Object.entries(data), [data]);
|
|
2325
|
+
const maxVal = import_react5.default.useMemo(() => {
|
|
2435
2326
|
const allValues = entries.flatMap(([, v]) => v);
|
|
2436
2327
|
return Math.max(...allValues) * 1.2 || 1;
|
|
2437
2328
|
}, [entries]);
|
|
2438
2329
|
const count = labels.length;
|
|
2439
2330
|
const chartW = width - PADDING.left - PADDING.right;
|
|
2440
2331
|
const chartH = height - PADDING.top - PADDING.bottom;
|
|
2441
|
-
const seriesPoints =
|
|
2332
|
+
const seriesPoints = import_react5.default.useMemo(
|
|
2442
2333
|
() => entries.map(
|
|
2443
2334
|
([, values]) => values.map((v, i) => ({
|
|
2444
2335
|
x: PADDING.left + i / (count - 1 || 1) * chartW,
|
|
@@ -2448,9 +2339,9 @@ var LineChart = import_react6.default.memo(({ data, labels, width, height, anima
|
|
|
2448
2339
|
),
|
|
2449
2340
|
[entries, count, chartW, chartH, maxVal]
|
|
2450
2341
|
);
|
|
2451
|
-
const clipRef =
|
|
2342
|
+
const clipRef = import_react5.default.useRef(null);
|
|
2452
2343
|
const { activeIndex, handleMouseMove, handleMouseLeave, getTooltipAt } = useCrosshair(seriesPoints, entries, labels, chartH);
|
|
2453
|
-
|
|
2344
|
+
import_react5.default.useEffect(() => {
|
|
2454
2345
|
if (!animate || !clipRef.current) return;
|
|
2455
2346
|
clipRef.current.setAttribute("width", "0");
|
|
2456
2347
|
requestAnimationFrame(() => {
|
|
@@ -2462,7 +2353,7 @@ var LineChart = import_react6.default.memo(({ data, labels, width, height, anima
|
|
|
2462
2353
|
}, [animate, width]);
|
|
2463
2354
|
const activeX = activeIndex !== null ? seriesPoints[0]?.[activeIndex]?.x ?? null : null;
|
|
2464
2355
|
const lineClipId = "line-area-clip";
|
|
2465
|
-
return /* @__PURE__ */ (0,
|
|
2356
|
+
return /* @__PURE__ */ (0, import_jsx_runtime305.jsxs)(
|
|
2466
2357
|
"svg",
|
|
2467
2358
|
{
|
|
2468
2359
|
viewBox: `0 0 ${width} ${height}`,
|
|
@@ -2480,9 +2371,9 @@ var LineChart = import_react6.default.memo(({ data, labels, width, height, anima
|
|
|
2480
2371
|
onLeave();
|
|
2481
2372
|
},
|
|
2482
2373
|
children: [
|
|
2483
|
-
animate && /* @__PURE__ */ (0,
|
|
2484
|
-
/* @__PURE__ */ (0,
|
|
2485
|
-
/* @__PURE__ */ (0,
|
|
2374
|
+
animate && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime305.jsx)("clipPath", { id: lineClipId, children: /* @__PURE__ */ (0, import_jsx_runtime305.jsx)("rect", { ref: clipRef, x: "0", y: "0", width: animate ? 0 : width, height }) }) }),
|
|
2375
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsx)(GridLines, { width, height, chartH, maxVal }),
|
|
2376
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsx)(AxisLabels, { labels, count, chartW, height }),
|
|
2486
2377
|
entries.map(([key], di) => {
|
|
2487
2378
|
const palette = getPalette(LINE_BAR_PALETTES, di, key);
|
|
2488
2379
|
const color = palette[2];
|
|
@@ -2491,16 +2382,16 @@ var LineChart = import_react6.default.memo(({ data, labels, width, height, anima
|
|
|
2491
2382
|
const gradientId = `line-gradient-${di}`;
|
|
2492
2383
|
const polyPoints = points.map((p) => `${p.x},${p.y}`).join(" ");
|
|
2493
2384
|
const areaD = `M ${points[0].x},${points[0].y} ${points.map((p) => `L ${p.x},${p.y}`).join(" ")} L ${points[points.length - 1].x},${PADDING.top + chartH} L ${points[0].x},${PADDING.top + chartH} Z`;
|
|
2494
|
-
return /* @__PURE__ */ (0,
|
|
2495
|
-
/* @__PURE__ */ (0,
|
|
2496
|
-
/* @__PURE__ */ (0,
|
|
2497
|
-
/* @__PURE__ */ (0,
|
|
2385
|
+
return /* @__PURE__ */ (0, import_jsx_runtime305.jsxs)("g", { children: [
|
|
2386
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime305.jsxs)("linearGradient", { id: gradientId, x1: "0", y1: "0", x2: "0", y2: "1", children: [
|
|
2387
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsx)("stop", { offset: "0%", stopColor: areaColor, stopOpacity: "0.2" }),
|
|
2388
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsx)("stop", { offset: "100%", stopColor: areaColor, stopOpacity: "0" })
|
|
2498
2389
|
] }) }),
|
|
2499
|
-
/* @__PURE__ */ (0,
|
|
2500
|
-
/* @__PURE__ */ (0,
|
|
2501
|
-
/* @__PURE__ */ (0,
|
|
2390
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsxs)("g", { clipPath: animate ? `url(#${lineClipId})` : void 0, children: [
|
|
2391
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsx)("path", { d: areaD, fill: `url(#${gradientId})` }),
|
|
2392
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsx)("polyline", { points: polyPoints, fill: "none", stroke: color, strokeWidth: "2" })
|
|
2502
2393
|
] }),
|
|
2503
|
-
activeIndex !== null && points[activeIndex] && /* @__PURE__ */ (0,
|
|
2394
|
+
activeIndex !== null && points[activeIndex] && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(
|
|
2504
2395
|
"circle",
|
|
2505
2396
|
{
|
|
2506
2397
|
cx: points[activeIndex].x,
|
|
@@ -2512,7 +2403,7 @@ var LineChart = import_react6.default.memo(({ data, labels, width, height, anima
|
|
|
2512
2403
|
)
|
|
2513
2404
|
] }, di);
|
|
2514
2405
|
}),
|
|
2515
|
-
activeX !== null && /* @__PURE__ */ (0,
|
|
2406
|
+
activeX !== null && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(
|
|
2516
2407
|
"line",
|
|
2517
2408
|
{
|
|
2518
2409
|
x1: activeX,
|
|
@@ -2522,7 +2413,7 @@ var LineChart = import_react6.default.memo(({ data, labels, width, height, anima
|
|
|
2522
2413
|
className: "chart-crosshair"
|
|
2523
2414
|
}
|
|
2524
2415
|
),
|
|
2525
|
-
/* @__PURE__ */ (0,
|
|
2416
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsx)(
|
|
2526
2417
|
"rect",
|
|
2527
2418
|
{
|
|
2528
2419
|
x: PADDING.left,
|
|
@@ -2538,16 +2429,16 @@ var LineChart = import_react6.default.memo(({ data, labels, width, height, anima
|
|
|
2538
2429
|
);
|
|
2539
2430
|
});
|
|
2540
2431
|
LineChart.displayName = "LineChart";
|
|
2541
|
-
var CurveChart =
|
|
2542
|
-
const entries =
|
|
2543
|
-
const maxVal =
|
|
2432
|
+
var CurveChart = import_react5.default.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
|
|
2433
|
+
const entries = import_react5.default.useMemo(() => Object.entries(data), [data]);
|
|
2434
|
+
const maxVal = import_react5.default.useMemo(() => {
|
|
2544
2435
|
const allValues = entries.flatMap(([, v]) => v);
|
|
2545
2436
|
return Math.max(...allValues) * 1.2 || 1;
|
|
2546
2437
|
}, [entries]);
|
|
2547
2438
|
const count = labels.length;
|
|
2548
2439
|
const chartW = width - PADDING.left - PADDING.right;
|
|
2549
2440
|
const chartH = height - PADDING.top - PADDING.bottom;
|
|
2550
|
-
const seriesPoints =
|
|
2441
|
+
const seriesPoints = import_react5.default.useMemo(
|
|
2551
2442
|
() => entries.map(
|
|
2552
2443
|
([, values]) => values.map((v, i) => ({
|
|
2553
2444
|
x: PADDING.left + i / (count - 1 || 1) * chartW,
|
|
@@ -2557,9 +2448,9 @@ var CurveChart = import_react6.default.memo(({ data, labels, width, height, anim
|
|
|
2557
2448
|
),
|
|
2558
2449
|
[entries, count, chartW, chartH, maxVal]
|
|
2559
2450
|
);
|
|
2560
|
-
const curveClipRef =
|
|
2451
|
+
const curveClipRef = import_react5.default.useRef(null);
|
|
2561
2452
|
const { activeIndex, handleMouseMove, handleMouseLeave, getTooltipAt } = useCrosshair(seriesPoints, entries, labels, chartH);
|
|
2562
|
-
|
|
2453
|
+
import_react5.default.useEffect(() => {
|
|
2563
2454
|
if (!animate || !curveClipRef.current) return;
|
|
2564
2455
|
curveClipRef.current.setAttribute("width", "0");
|
|
2565
2456
|
requestAnimationFrame(() => {
|
|
@@ -2571,7 +2462,7 @@ var CurveChart = import_react6.default.memo(({ data, labels, width, height, anim
|
|
|
2571
2462
|
}, [animate, width]);
|
|
2572
2463
|
const activeX = activeIndex !== null ? seriesPoints[0]?.[activeIndex]?.x ?? null : null;
|
|
2573
2464
|
const curveClipId = "curve-area-clip";
|
|
2574
|
-
return /* @__PURE__ */ (0,
|
|
2465
|
+
return /* @__PURE__ */ (0, import_jsx_runtime305.jsxs)(
|
|
2575
2466
|
"svg",
|
|
2576
2467
|
{
|
|
2577
2468
|
viewBox: `0 0 ${width} ${height}`,
|
|
@@ -2590,9 +2481,9 @@ var CurveChart = import_react6.default.memo(({ data, labels, width, height, anim
|
|
|
2590
2481
|
onLeave();
|
|
2591
2482
|
},
|
|
2592
2483
|
children: [
|
|
2593
|
-
animate && /* @__PURE__ */ (0,
|
|
2594
|
-
/* @__PURE__ */ (0,
|
|
2595
|
-
/* @__PURE__ */ (0,
|
|
2484
|
+
animate && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime305.jsx)("clipPath", { id: curveClipId, children: /* @__PURE__ */ (0, import_jsx_runtime305.jsx)("rect", { ref: curveClipRef, x: "0", y: "0", width: animate ? 0 : width, height }) }) }),
|
|
2485
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsx)(GridLines, { width, height, chartH, maxVal }),
|
|
2486
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsx)(AxisLabels, { labels, count, chartW, height }),
|
|
2596
2487
|
entries.map(([key], di) => {
|
|
2597
2488
|
const palette = getPalette(LINE_BAR_PALETTES, di, key);
|
|
2598
2489
|
const color = palette[2];
|
|
@@ -2601,16 +2492,16 @@ var CurveChart = import_react6.default.memo(({ data, labels, width, height, anim
|
|
|
2601
2492
|
const gradientId = `curve-gradient-${di}`;
|
|
2602
2493
|
const linePath = toSmoothPath(points);
|
|
2603
2494
|
const areaPath = linePath + ` L ${points[points.length - 1].x} ${PADDING.top + chartH} L ${points[0].x} ${PADDING.top + chartH} Z`;
|
|
2604
|
-
return /* @__PURE__ */ (0,
|
|
2605
|
-
/* @__PURE__ */ (0,
|
|
2606
|
-
/* @__PURE__ */ (0,
|
|
2607
|
-
/* @__PURE__ */ (0,
|
|
2495
|
+
return /* @__PURE__ */ (0, import_jsx_runtime305.jsxs)("g", { children: [
|
|
2496
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime305.jsxs)("linearGradient", { id: gradientId, x1: "0", y1: "0", x2: "0", y2: "1", children: [
|
|
2497
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsx)("stop", { offset: "0%", stopColor: areaColor, stopOpacity: "0.4" }),
|
|
2498
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsx)("stop", { offset: "100%", stopColor: areaColor, stopOpacity: "0.02" })
|
|
2608
2499
|
] }) }),
|
|
2609
|
-
/* @__PURE__ */ (0,
|
|
2610
|
-
/* @__PURE__ */ (0,
|
|
2611
|
-
/* @__PURE__ */ (0,
|
|
2500
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsxs)("g", { clipPath: animate ? `url(#${curveClipId})` : void 0, children: [
|
|
2501
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsx)("path", { d: areaPath, fill: `url(#${gradientId})` }),
|
|
2502
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsx)("path", { d: linePath, fill: "none", stroke: color, strokeWidth: "2" })
|
|
2612
2503
|
] }),
|
|
2613
|
-
activeIndex !== null && points[activeIndex] && /* @__PURE__ */ (0,
|
|
2504
|
+
activeIndex !== null && points[activeIndex] && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(
|
|
2614
2505
|
"circle",
|
|
2615
2506
|
{
|
|
2616
2507
|
cx: points[activeIndex].x,
|
|
@@ -2622,7 +2513,7 @@ var CurveChart = import_react6.default.memo(({ data, labels, width, height, anim
|
|
|
2622
2513
|
)
|
|
2623
2514
|
] }, di);
|
|
2624
2515
|
}),
|
|
2625
|
-
activeX !== null && /* @__PURE__ */ (0,
|
|
2516
|
+
activeX !== null && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(
|
|
2626
2517
|
"line",
|
|
2627
2518
|
{
|
|
2628
2519
|
x1: activeX,
|
|
@@ -2632,7 +2523,7 @@ var CurveChart = import_react6.default.memo(({ data, labels, width, height, anim
|
|
|
2632
2523
|
className: "chart-crosshair"
|
|
2633
2524
|
}
|
|
2634
2525
|
),
|
|
2635
|
-
/* @__PURE__ */ (0,
|
|
2526
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsx)(
|
|
2636
2527
|
"rect",
|
|
2637
2528
|
{
|
|
2638
2529
|
x: PADDING.left,
|
|
@@ -2648,9 +2539,9 @@ var CurveChart = import_react6.default.memo(({ data, labels, width, height, anim
|
|
|
2648
2539
|
);
|
|
2649
2540
|
});
|
|
2650
2541
|
CurveChart.displayName = "CurveChart";
|
|
2651
|
-
var BarChart =
|
|
2652
|
-
const entries =
|
|
2653
|
-
const maxVal =
|
|
2542
|
+
var BarChart = import_react5.default.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
|
|
2543
|
+
const entries = import_react5.default.useMemo(() => Object.entries(data), [data]);
|
|
2544
|
+
const maxVal = import_react5.default.useMemo(() => {
|
|
2654
2545
|
const allValues = entries.flatMap(([, v]) => v);
|
|
2655
2546
|
return Math.max(...allValues) * 1.2 || 1;
|
|
2656
2547
|
}, [entries]);
|
|
@@ -2662,7 +2553,7 @@ var BarChart = import_react6.default.memo(({ data, labels, width, height, animat
|
|
|
2662
2553
|
const barGap = groupCount > 1 ? 2 : 0;
|
|
2663
2554
|
const barW = Math.max(1, Math.min(32, (groupW * 0.7 - barGap * (groupCount - 1)) / groupCount));
|
|
2664
2555
|
const baseline = PADDING.top + chartH;
|
|
2665
|
-
const bars =
|
|
2556
|
+
const bars = import_react5.default.useMemo(
|
|
2666
2557
|
() => entries.map(
|
|
2667
2558
|
([, values], di) => values.map((v, i) => {
|
|
2668
2559
|
const totalBarsW = barW * groupCount + barGap * (groupCount - 1);
|
|
@@ -2675,11 +2566,11 @@ var BarChart = import_react6.default.memo(({ data, labels, width, height, animat
|
|
|
2675
2566
|
[entries, maxVal, chartH, groupW, barW, barGap, groupCount]
|
|
2676
2567
|
);
|
|
2677
2568
|
const barLabelStep = getLabelStep(count, chartW);
|
|
2678
|
-
return /* @__PURE__ */ (0,
|
|
2679
|
-
/* @__PURE__ */ (0,
|
|
2569
|
+
return /* @__PURE__ */ (0, import_jsx_runtime305.jsxs)("svg", { viewBox: `0 0 ${width} ${height}`, className: "chart-svg", children: [
|
|
2570
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsx)(GridLines, { width, height, chartH, maxVal }),
|
|
2680
2571
|
labels.map((label, i) => {
|
|
2681
2572
|
if (i % barLabelStep !== 0) return null;
|
|
2682
|
-
return /* @__PURE__ */ (0,
|
|
2573
|
+
return /* @__PURE__ */ (0, import_jsx_runtime305.jsx)("text", { x: PADDING.left + groupW * i + groupW / 2, y: height - 8, className: "chart-axis-label", textAnchor: "middle", children: label }, i);
|
|
2683
2574
|
}),
|
|
2684
2575
|
entries.map(([key], di) => {
|
|
2685
2576
|
const palette = getPalette(LINE_BAR_PALETTES, di, key);
|
|
@@ -2688,7 +2579,7 @@ var BarChart = import_react6.default.memo(({ data, labels, width, height, animat
|
|
|
2688
2579
|
const r2 = Math.min(4, b.w / 2);
|
|
2689
2580
|
const d = b.h <= r2 ? `M ${b.x} ${b.y + b.h} V ${b.y} H ${b.x + b.w} V ${b.y + b.h} Z` : `M ${b.x} ${b.y + b.h} V ${b.y + r2} Q ${b.x} ${b.y} ${b.x + r2} ${b.y} H ${b.x + b.w - r2} Q ${b.x + b.w} ${b.y} ${b.x + b.w} ${b.y + r2} V ${b.y + b.h} Z`;
|
|
2690
2581
|
const delay = 100 + i * 80;
|
|
2691
|
-
return /* @__PURE__ */ (0,
|
|
2582
|
+
return /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(
|
|
2692
2583
|
"path",
|
|
2693
2584
|
{
|
|
2694
2585
|
d,
|
|
@@ -2709,11 +2600,11 @@ var BarChart = import_react6.default.memo(({ data, labels, width, height, animat
|
|
|
2709
2600
|
] });
|
|
2710
2601
|
});
|
|
2711
2602
|
BarChart.displayName = "BarChart";
|
|
2712
|
-
var PieDonutChart =
|
|
2603
|
+
var PieDonutChart = import_react5.default.memo(
|
|
2713
2604
|
({ data, labels, width, height, animate, isDoughnut, onHover, onMove, onLeave }) => {
|
|
2714
|
-
const entries =
|
|
2715
|
-
const values =
|
|
2716
|
-
const total =
|
|
2605
|
+
const entries = import_react5.default.useMemo(() => Object.entries(data), [data]);
|
|
2606
|
+
const values = import_react5.default.useMemo(() => entries.flatMap(([, v]) => v), [entries]);
|
|
2607
|
+
const total = import_react5.default.useMemo(() => values.reduce((a, b) => a + b, 0) || 1, [values]);
|
|
2717
2608
|
const size = Math.min(width, height);
|
|
2718
2609
|
const cx = size / 2;
|
|
2719
2610
|
const cy = size / 2;
|
|
@@ -2721,10 +2612,10 @@ var PieDonutChart = import_react6.default.memo(
|
|
|
2721
2612
|
const innerR = isDoughnut ? r2 * 0.5 : 0;
|
|
2722
2613
|
const firstKey = entries[0]?.[0] ?? "";
|
|
2723
2614
|
const colorOffset = hashString(firstKey);
|
|
2724
|
-
const maskRef =
|
|
2615
|
+
const maskRef = import_react5.default.useRef(null);
|
|
2725
2616
|
const maskR = r2 + 10;
|
|
2726
2617
|
const maskCircumference = 2 * Math.PI * maskR;
|
|
2727
|
-
|
|
2618
|
+
import_react5.default.useEffect(() => {
|
|
2728
2619
|
if (!animate || !maskRef.current) return;
|
|
2729
2620
|
const el = maskRef.current;
|
|
2730
2621
|
el.style.strokeDasharray = `${maskCircumference}`;
|
|
@@ -2734,7 +2625,7 @@ var PieDonutChart = import_react6.default.memo(
|
|
|
2734
2625
|
el.style.strokeDashoffset = "0";
|
|
2735
2626
|
});
|
|
2736
2627
|
}, [animate, maskCircumference]);
|
|
2737
|
-
const sliceData =
|
|
2628
|
+
const sliceData = import_react5.default.useMemo(() => {
|
|
2738
2629
|
let angle0 = -Math.PI / 2;
|
|
2739
2630
|
let cumulativeAngle = 0;
|
|
2740
2631
|
return values.map((v, i) => {
|
|
@@ -2768,8 +2659,8 @@ var PieDonutChart = import_react6.default.memo(
|
|
|
2768
2659
|
});
|
|
2769
2660
|
}, [values, total, cx, cy, r2, innerR, labels]);
|
|
2770
2661
|
const maskId = `pie-mask-${isDoughnut ? "d" : "p"}`;
|
|
2771
|
-
return /* @__PURE__ */ (0,
|
|
2772
|
-
animate && /* @__PURE__ */ (0,
|
|
2662
|
+
return /* @__PURE__ */ (0, import_jsx_runtime305.jsxs)("svg", { viewBox: `0 0 ${size} ${size}`, className: "chart-svg chart-pie", children: [
|
|
2663
|
+
animate && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime305.jsx)("mask", { id: maskId, children: /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(
|
|
2773
2664
|
"circle",
|
|
2774
2665
|
{
|
|
2775
2666
|
ref: maskRef,
|
|
@@ -2782,7 +2673,7 @@ var PieDonutChart = import_react6.default.memo(
|
|
|
2782
2673
|
transform: `rotate(-90 ${cx} ${cy})`
|
|
2783
2674
|
}
|
|
2784
2675
|
) }) }),
|
|
2785
|
-
/* @__PURE__ */ (0,
|
|
2676
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsx)("g", { mask: animate ? `url(#${maskId})` : void 0, children: sliceData.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime305.jsx)("g", { children: /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(
|
|
2786
2677
|
"path",
|
|
2787
2678
|
{
|
|
2788
2679
|
d: s.d,
|
|
@@ -2798,9 +2689,9 @@ var PieDonutChart = import_react6.default.memo(
|
|
|
2798
2689
|
);
|
|
2799
2690
|
PieDonutChart.displayName = "PieDonutChart";
|
|
2800
2691
|
var ChartTooltip = ({ x, y, containerWidth, containerHeight, tooltipType, children }) => {
|
|
2801
|
-
const ref =
|
|
2802
|
-
const [pos, setPos] =
|
|
2803
|
-
|
|
2692
|
+
const ref = import_react5.default.useRef(null);
|
|
2693
|
+
const [pos, setPos] = import_react5.default.useState({ left: 0, top: 0 });
|
|
2694
|
+
import_react5.default.useLayoutEffect(() => {
|
|
2804
2695
|
const el = ref.current;
|
|
2805
2696
|
if (!el) return;
|
|
2806
2697
|
const w = el.offsetWidth;
|
|
@@ -2817,15 +2708,15 @@ var ChartTooltip = ({ x, y, containerWidth, containerHeight, tooltipType, childr
|
|
|
2817
2708
|
const sepIdx = content.indexOf(" \u2014 ");
|
|
2818
2709
|
const title = sepIdx >= 0 ? content.slice(0, sepIdx) : content;
|
|
2819
2710
|
const desc = sepIdx >= 0 ? content.slice(sepIdx + 3) : "";
|
|
2820
|
-
return /* @__PURE__ */ (0,
|
|
2711
|
+
return /* @__PURE__ */ (0, import_jsx_runtime305.jsxs)(
|
|
2821
2712
|
"div",
|
|
2822
2713
|
{
|
|
2823
2714
|
ref,
|
|
2824
2715
|
className: `lib-xplat-tooltip ${tooltipType} chart-tooltip-pos`,
|
|
2825
2716
|
style: { left: pos.left, top: pos.top },
|
|
2826
2717
|
children: [
|
|
2827
|
-
title && /* @__PURE__ */ (0,
|
|
2828
|
-
desc && /* @__PURE__ */ (0,
|
|
2718
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)("div", { className: "tooltip-title", children: title }),
|
|
2719
|
+
desc && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)("div", { className: "tooltip-desc", children: desc })
|
|
2829
2720
|
]
|
|
2830
2721
|
}
|
|
2831
2722
|
);
|
|
@@ -2837,14 +2728,14 @@ var ChartLegend = ({ data, labels, type }) => {
|
|
|
2837
2728
|
const total = values.reduce((a, b) => a + b, 0) || 1;
|
|
2838
2729
|
const firstKey = entries[0]?.[0] ?? "";
|
|
2839
2730
|
const colorOffset = hashString(firstKey);
|
|
2840
|
-
return /* @__PURE__ */ (0,
|
|
2731
|
+
return /* @__PURE__ */ (0, import_jsx_runtime305.jsx)("div", { className: "chart-legend", children: values.map((v, i) => {
|
|
2841
2732
|
const pct = Math.round(v / total * 100);
|
|
2842
2733
|
const color = PIE_COLORS[(i + colorOffset) % PIE_COLORS.length];
|
|
2843
|
-
return /* @__PURE__ */ (0,
|
|
2844
|
-
/* @__PURE__ */ (0,
|
|
2845
|
-
/* @__PURE__ */ (0,
|
|
2846
|
-
/* @__PURE__ */ (0,
|
|
2847
|
-
/* @__PURE__ */ (0,
|
|
2734
|
+
return /* @__PURE__ */ (0, import_jsx_runtime305.jsxs)("div", { className: "chart-legend-item", children: [
|
|
2735
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsx)("span", { className: "chart-legend-dot", style: { backgroundColor: color } }),
|
|
2736
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsxs)("div", { className: "chart-legend-text", children: [
|
|
2737
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsx)("span", { className: "chart-legend-label", children: labels[i] || `${i + 1}` }),
|
|
2738
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsxs)("span", { className: "chart-legend-value", children: [
|
|
2848
2739
|
v.toLocaleString(),
|
|
2849
2740
|
"(",
|
|
2850
2741
|
pct,
|
|
@@ -2854,42 +2745,151 @@ var ChartLegend = ({ data, labels, type }) => {
|
|
|
2854
2745
|
] }, i);
|
|
2855
2746
|
}) });
|
|
2856
2747
|
}
|
|
2857
|
-
return /* @__PURE__ */ (0,
|
|
2748
|
+
return /* @__PURE__ */ (0, import_jsx_runtime305.jsx)("div", { className: "chart-legend", children: entries.map(([key], di) => {
|
|
2858
2749
|
const palette = getPalette(LINE_BAR_PALETTES, di, key);
|
|
2859
2750
|
const color = palette[2];
|
|
2860
2751
|
const values = entries[di][1];
|
|
2861
2752
|
const sum = values.reduce((a, b) => a + b, 0);
|
|
2862
|
-
return /* @__PURE__ */ (0,
|
|
2863
|
-
/* @__PURE__ */ (0,
|
|
2864
|
-
/* @__PURE__ */ (0,
|
|
2865
|
-
/* @__PURE__ */ (0,
|
|
2866
|
-
/* @__PURE__ */ (0,
|
|
2753
|
+
return /* @__PURE__ */ (0, import_jsx_runtime305.jsxs)("div", { className: "chart-legend-item", children: [
|
|
2754
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsx)("span", { className: "chart-legend-dot", style: { backgroundColor: color } }),
|
|
2755
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsxs)("div", { className: "chart-legend-text", children: [
|
|
2756
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsx)("span", { className: "chart-legend-label", children: key }),
|
|
2757
|
+
/* @__PURE__ */ (0, import_jsx_runtime305.jsx)("span", { className: "chart-legend-value", children: sum.toLocaleString() })
|
|
2867
2758
|
] })
|
|
2868
2759
|
] }, di);
|
|
2869
2760
|
}) });
|
|
2870
2761
|
};
|
|
2871
|
-
var Chart =
|
|
2762
|
+
var Chart = import_react5.default.memo((props) => {
|
|
2872
2763
|
const { type, data, labels, tooltip: showTooltip = true, tooltipType = "light" } = props;
|
|
2873
2764
|
const { tooltip, show, hide, move, containerRef } = useChartTooltip(showTooltip);
|
|
2874
2765
|
const { width, height } = useChartSize(containerRef);
|
|
2875
|
-
const stableData =
|
|
2876
|
-
const stableLabels =
|
|
2877
|
-
const dataKey =
|
|
2766
|
+
const stableData = import_react5.default.useMemo(() => data, [JSON.stringify(data)]);
|
|
2767
|
+
const stableLabels = import_react5.default.useMemo(() => labels, [JSON.stringify(labels)]);
|
|
2768
|
+
const dataKey = import_react5.default.useMemo(() => JSON.stringify(labels), [labels]);
|
|
2878
2769
|
const animate = useChartAnimation(containerRef, dataKey);
|
|
2879
2770
|
const ready = width > 0 && height > 0;
|
|
2880
|
-
return /* @__PURE__ */ (0,
|
|
2881
|
-
ready && type === "line" && /* @__PURE__ */ (0,
|
|
2882
|
-
ready && type === "curve" && /* @__PURE__ */ (0,
|
|
2883
|
-
ready && type === "bar" && /* @__PURE__ */ (0,
|
|
2884
|
-
ready && type === "pie" && /* @__PURE__ */ (0,
|
|
2885
|
-
ready && type === "doughnut" && /* @__PURE__ */ (0,
|
|
2886
|
-
ready && (type === "pie" || type === "doughnut") && /* @__PURE__ */ (0,
|
|
2887
|
-
tooltip.visible && tooltip.content && /* @__PURE__ */ (0,
|
|
2771
|
+
return /* @__PURE__ */ (0, import_jsx_runtime305.jsxs)("div", { className: "lib-xplat-chart", ref: containerRef, children: [
|
|
2772
|
+
ready && type === "line" && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(LineChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
|
|
2773
|
+
ready && type === "curve" && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(CurveChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
|
|
2774
|
+
ready && type === "bar" && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(BarChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
|
|
2775
|
+
ready && type === "pie" && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
|
|
2776
|
+
ready && type === "doughnut" && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, isDoughnut: true, onHover: show, onMove: move, onLeave: hide }),
|
|
2777
|
+
ready && (type === "pie" || type === "doughnut") && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(ChartLegend, { data: stableData, labels: stableLabels, type }),
|
|
2778
|
+
tooltip.visible && tooltip.content && /* @__PURE__ */ (0, import_jsx_runtime305.jsx)(ChartTooltip, { x: tooltip.x, y: tooltip.y, containerWidth: width, containerHeight: height, tooltipType, children: tooltip.content })
|
|
2888
2779
|
] });
|
|
2889
2780
|
});
|
|
2890
2781
|
Chart.displayName = "Chart";
|
|
2891
2782
|
var Chart_default = Chart;
|
|
2892
2783
|
|
|
2784
|
+
// src/components/ChatInput/ChatInput.tsx
|
|
2785
|
+
var import_react6 = __toESM(require("react"), 1);
|
|
2786
|
+
|
|
2787
|
+
// src/components/IconButton/IconButton.tsx
|
|
2788
|
+
var import_jsx_runtime306 = require("react/jsx-runtime");
|
|
2789
|
+
var IconButton = (props) => {
|
|
2790
|
+
const {
|
|
2791
|
+
icon,
|
|
2792
|
+
type = "primary",
|
|
2793
|
+
size = "md",
|
|
2794
|
+
disabled,
|
|
2795
|
+
...rest
|
|
2796
|
+
} = props;
|
|
2797
|
+
return /* @__PURE__ */ (0, import_jsx_runtime306.jsx)(
|
|
2798
|
+
"button",
|
|
2799
|
+
{
|
|
2800
|
+
className: clsx_default("lib-xplat-icon-button", type, size),
|
|
2801
|
+
disabled,
|
|
2802
|
+
...rest,
|
|
2803
|
+
children: icon
|
|
2804
|
+
}
|
|
2805
|
+
);
|
|
2806
|
+
};
|
|
2807
|
+
IconButton.displayName = "IconButton";
|
|
2808
|
+
var IconButton_default = IconButton;
|
|
2809
|
+
|
|
2810
|
+
// src/components/ChatInput/ChatInput.tsx
|
|
2811
|
+
var import_jsx_runtime307 = require("react/jsx-runtime");
|
|
2812
|
+
var MAX_HEIGHT = 200;
|
|
2813
|
+
var ChatInput = import_react6.default.forwardRef(
|
|
2814
|
+
(props, ref) => {
|
|
2815
|
+
const {
|
|
2816
|
+
placeholder,
|
|
2817
|
+
value: valueProp,
|
|
2818
|
+
disabled = false,
|
|
2819
|
+
buttonType = "primary",
|
|
2820
|
+
onSubmit,
|
|
2821
|
+
onChange
|
|
2822
|
+
} = props;
|
|
2823
|
+
const isControlled = valueProp !== void 0;
|
|
2824
|
+
const [internalValue, setInternalValue] = import_react6.default.useState("");
|
|
2825
|
+
const value = isControlled ? valueProp : internalValue;
|
|
2826
|
+
const hasText = value.trim().length > 0;
|
|
2827
|
+
const textareaRef = import_react6.default.useRef(null);
|
|
2828
|
+
const setRefs = import_react6.default.useCallback(
|
|
2829
|
+
(el) => {
|
|
2830
|
+
textareaRef.current = el;
|
|
2831
|
+
if (typeof ref === "function") ref(el);
|
|
2832
|
+
else if (ref) ref.current = el;
|
|
2833
|
+
},
|
|
2834
|
+
[ref]
|
|
2835
|
+
);
|
|
2836
|
+
const updateHeight = import_react6.default.useCallback(() => {
|
|
2837
|
+
const el = textareaRef.current;
|
|
2838
|
+
if (!el) return;
|
|
2839
|
+
el.style.height = "0px";
|
|
2840
|
+
el.style.height = `${Math.min(el.scrollHeight, MAX_HEIGHT)}px`;
|
|
2841
|
+
}, []);
|
|
2842
|
+
const handleChange = (e) => {
|
|
2843
|
+
const val = e.target.value;
|
|
2844
|
+
if (!isControlled) setInternalValue(val);
|
|
2845
|
+
onChange?.(val);
|
|
2846
|
+
};
|
|
2847
|
+
const handleSubmit = () => {
|
|
2848
|
+
if (!hasText || disabled) return;
|
|
2849
|
+
onSubmit?.(value);
|
|
2850
|
+
if (!isControlled) setInternalValue("");
|
|
2851
|
+
requestAnimationFrame(updateHeight);
|
|
2852
|
+
};
|
|
2853
|
+
const handleKeyDown = (e) => {
|
|
2854
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
2855
|
+
e.preventDefault();
|
|
2856
|
+
handleSubmit();
|
|
2857
|
+
}
|
|
2858
|
+
};
|
|
2859
|
+
import_react6.default.useEffect(() => {
|
|
2860
|
+
updateHeight();
|
|
2861
|
+
}, [value, updateHeight]);
|
|
2862
|
+
return /* @__PURE__ */ (0, import_jsx_runtime307.jsxs)("div", { className: clsx_default("lib-xplat-chat-input", disabled && "disabled"), children: [
|
|
2863
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)(
|
|
2864
|
+
"textarea",
|
|
2865
|
+
{
|
|
2866
|
+
ref: setRefs,
|
|
2867
|
+
className: "chat-input-textarea",
|
|
2868
|
+
placeholder,
|
|
2869
|
+
value,
|
|
2870
|
+
disabled,
|
|
2871
|
+
rows: 1,
|
|
2872
|
+
onChange: handleChange,
|
|
2873
|
+
onKeyDown: handleKeyDown
|
|
2874
|
+
}
|
|
2875
|
+
),
|
|
2876
|
+
/* @__PURE__ */ (0, import_jsx_runtime307.jsx)(
|
|
2877
|
+
IconButton_default,
|
|
2878
|
+
{
|
|
2879
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime307.jsx)(MessageSquareIcon_default, {}),
|
|
2880
|
+
type: buttonType,
|
|
2881
|
+
size: "sm",
|
|
2882
|
+
disabled: !hasText || disabled,
|
|
2883
|
+
onClick: handleSubmit,
|
|
2884
|
+
"aria-label": "\uC804\uC1A1"
|
|
2885
|
+
}
|
|
2886
|
+
)
|
|
2887
|
+
] });
|
|
2888
|
+
}
|
|
2889
|
+
);
|
|
2890
|
+
ChatInput.displayName = "ChatInput";
|
|
2891
|
+
var ChatInput_default = ChatInput;
|
|
2892
|
+
|
|
2893
2893
|
// src/tokens/colors.ts
|
|
2894
2894
|
var import_tokens_core = require("@x-plat/tokens-core");
|
|
2895
2895
|
|