@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
package/dist/index.js
CHANGED
|
@@ -5637,15 +5637,31 @@ var Badge = (props) => {
|
|
|
5637
5637
|
Badge.displayName = "Badge";
|
|
5638
5638
|
var Badge_default = Badge;
|
|
5639
5639
|
|
|
5640
|
-
// src/components/
|
|
5640
|
+
// src/components/Box/Box.tsx
|
|
5641
5641
|
import { jsx as jsx299, jsxs as jsxs192 } from "react/jsx-runtime";
|
|
5642
|
+
var Box = ({
|
|
5643
|
+
children,
|
|
5644
|
+
title,
|
|
5645
|
+
variant = "outlined",
|
|
5646
|
+
padding = "md"
|
|
5647
|
+
}) => {
|
|
5648
|
+
return /* @__PURE__ */ jsxs192("div", { className: clsx_default("lib-xplat-box", variant, `pad-${padding}`), children: [
|
|
5649
|
+
title && /* @__PURE__ */ jsx299("div", { className: "box-title", children: title }),
|
|
5650
|
+
/* @__PURE__ */ jsx299("div", { className: "box-content", children })
|
|
5651
|
+
] });
|
|
5652
|
+
};
|
|
5653
|
+
Box.displayName = "Box";
|
|
5654
|
+
var Box_default = Box;
|
|
5655
|
+
|
|
5656
|
+
// src/components/Breadcrumb/Breadcrumb.tsx
|
|
5657
|
+
import { jsx as jsx300, jsxs as jsxs193 } from "react/jsx-runtime";
|
|
5642
5658
|
var Breadcrumb = (props) => {
|
|
5643
5659
|
const { items, separator = "/" } = props;
|
|
5644
|
-
return /* @__PURE__ */
|
|
5660
|
+
return /* @__PURE__ */ jsx300("nav", { className: "lib-xplat-breadcrumb", "aria-label": "\uACBD\uB85C", children: /* @__PURE__ */ jsx300("ol", { children: items.map((item, index) => {
|
|
5645
5661
|
const isLast = index === items.length - 1;
|
|
5646
|
-
return /* @__PURE__ */
|
|
5647
|
-
isLast ? /* @__PURE__ */
|
|
5648
|
-
!isLast && /* @__PURE__ */
|
|
5662
|
+
return /* @__PURE__ */ jsxs193("li", { children: [
|
|
5663
|
+
isLast ? /* @__PURE__ */ jsx300("span", { className: "current", "aria-current": "page", children: item.label }) : item.href ? /* @__PURE__ */ jsx300("a", { href: item.href, className: "link", children: item.label }) : /* @__PURE__ */ jsx300("button", { className: "link", onClick: item.onClick, children: item.label }),
|
|
5664
|
+
!isLast && /* @__PURE__ */ jsx300("span", { className: "separator", children: separator })
|
|
5649
5665
|
] }, index);
|
|
5650
5666
|
}) }) });
|
|
5651
5667
|
};
|
|
@@ -5653,7 +5669,7 @@ Breadcrumb.displayName = "Breadcrumb";
|
|
|
5653
5669
|
var Breadcrumb_default = Breadcrumb;
|
|
5654
5670
|
|
|
5655
5671
|
// src/components/Button/Button.tsx
|
|
5656
|
-
import { jsx as
|
|
5672
|
+
import { jsx as jsx301 } from "react/jsx-runtime";
|
|
5657
5673
|
var Button = (props) => {
|
|
5658
5674
|
const {
|
|
5659
5675
|
children,
|
|
@@ -5662,7 +5678,7 @@ var Button = (props) => {
|
|
|
5662
5678
|
disabled,
|
|
5663
5679
|
...rest
|
|
5664
5680
|
} = props;
|
|
5665
|
-
return /* @__PURE__ */
|
|
5681
|
+
return /* @__PURE__ */ jsx301(
|
|
5666
5682
|
"button",
|
|
5667
5683
|
{
|
|
5668
5684
|
className: clsx_default("lib-xplat-button", type, size),
|
|
@@ -5779,7 +5795,7 @@ var MONTH_LABELS = {
|
|
|
5779
5795
|
};
|
|
5780
5796
|
|
|
5781
5797
|
// src/components/Calendar/Calendar.tsx
|
|
5782
|
-
import { Fragment, jsx as
|
|
5798
|
+
import { Fragment, jsx as jsx302, jsxs as jsxs194 } from "react/jsx-runtime";
|
|
5783
5799
|
var DayCell = React3.memo(
|
|
5784
5800
|
({
|
|
5785
5801
|
day,
|
|
@@ -5791,7 +5807,7 @@ var DayCell = React3.memo(
|
|
|
5791
5807
|
onEventClick
|
|
5792
5808
|
}) => {
|
|
5793
5809
|
if (renderDay) {
|
|
5794
|
-
return /* @__PURE__ */
|
|
5810
|
+
return /* @__PURE__ */ jsx302(
|
|
5795
5811
|
"div",
|
|
5796
5812
|
{
|
|
5797
5813
|
className: clsx_default(
|
|
@@ -5808,7 +5824,7 @@ var DayCell = React3.memo(
|
|
|
5808
5824
|
}
|
|
5809
5825
|
);
|
|
5810
5826
|
}
|
|
5811
|
-
return /* @__PURE__ */
|
|
5827
|
+
return /* @__PURE__ */ jsxs194(
|
|
5812
5828
|
"div",
|
|
5813
5829
|
{
|
|
5814
5830
|
className: clsx_default(
|
|
@@ -5824,9 +5840,9 @@ var DayCell = React3.memo(
|
|
|
5824
5840
|
if (!disabled && day.isCurrentMonth) onSelect?.(day.date);
|
|
5825
5841
|
},
|
|
5826
5842
|
children: [
|
|
5827
|
-
/* @__PURE__ */
|
|
5828
|
-
dayEvents.length > 0 && /* @__PURE__ */
|
|
5829
|
-
dayEvents.slice(0, 3).map((event, ei) => /* @__PURE__ */
|
|
5843
|
+
/* @__PURE__ */ jsx302("span", { className: "calendar-day-number", children: day.day }),
|
|
5844
|
+
dayEvents.length > 0 && /* @__PURE__ */ jsxs194("div", { className: "calendar-day-events", children: [
|
|
5845
|
+
dayEvents.slice(0, 3).map((event, ei) => /* @__PURE__ */ jsx302(
|
|
5830
5846
|
"span",
|
|
5831
5847
|
{
|
|
5832
5848
|
className: "calendar-event-dot",
|
|
@@ -5839,7 +5855,7 @@ var DayCell = React3.memo(
|
|
|
5839
5855
|
},
|
|
5840
5856
|
ei
|
|
5841
5857
|
)),
|
|
5842
|
-
dayEvents.length > 3 && /* @__PURE__ */
|
|
5858
|
+
dayEvents.length > 3 && /* @__PURE__ */ jsxs194("span", { className: "calendar-event-more", children: [
|
|
5843
5859
|
"+",
|
|
5844
5860
|
dayEvents.length - 3
|
|
5845
5861
|
] })
|
|
@@ -5960,21 +5976,21 @@ var Calendar = (props) => {
|
|
|
5960
5976
|
const weekdays = WEEKDAY_LABELS[locale];
|
|
5961
5977
|
const monthLabels = MONTH_LABELS[locale];
|
|
5962
5978
|
const titleText = pickerMode === "days" ? locale === "ko" ? `${year}\uB144 ${monthLabels[month]}` : `${monthLabels[month]} ${year}` : pickerMode === "months" ? `${year}` : `${yearRangeStart} - ${yearRangeStart + 11}`;
|
|
5963
|
-
return /* @__PURE__ */
|
|
5979
|
+
return /* @__PURE__ */ jsxs194(
|
|
5964
5980
|
"div",
|
|
5965
5981
|
{
|
|
5966
5982
|
className: "lib-xplat-calendar",
|
|
5967
5983
|
style: selectedColor ? { "--calendar-selected-color": `var(--${selectedColor})` } : void 0,
|
|
5968
5984
|
children: [
|
|
5969
|
-
/* @__PURE__ */
|
|
5970
|
-
/* @__PURE__ */
|
|
5971
|
-
/* @__PURE__ */
|
|
5972
|
-
/* @__PURE__ */
|
|
5973
|
-
showToday && /* @__PURE__ */
|
|
5985
|
+
/* @__PURE__ */ jsxs194("div", { className: "calendar-header", children: [
|
|
5986
|
+
/* @__PURE__ */ jsx302("button", { className: "calendar-nav", onClick: handlePrev, "aria-label": "\uC774\uC804", children: /* @__PURE__ */ jsx302(ChevronLeftIcon_default, {}) }),
|
|
5987
|
+
/* @__PURE__ */ jsx302("button", { className: "calendar-title", onClick: handleTitleClick, type: "button", children: titleText }),
|
|
5988
|
+
/* @__PURE__ */ jsx302("button", { className: "calendar-nav", onClick: handleNext, "aria-label": "\uB2E4\uC74C", children: /* @__PURE__ */ jsx302(ChevronRightIcon_default, {}) }),
|
|
5989
|
+
showToday && /* @__PURE__ */ jsx302("button", { className: "calendar-today-btn", onClick: handleToday, children: locale === "ko" ? "\uC624\uB298" : "Today" })
|
|
5974
5990
|
] }),
|
|
5975
|
-
pickerMode === "years" && /* @__PURE__ */
|
|
5991
|
+
pickerMode === "years" && /* @__PURE__ */ jsx302("div", { className: "calendar-picker-grid", children: Array.from({ length: 12 }, (_, i) => {
|
|
5976
5992
|
const y = yearRangeStart + i;
|
|
5977
|
-
return /* @__PURE__ */
|
|
5993
|
+
return /* @__PURE__ */ jsx302(
|
|
5978
5994
|
"button",
|
|
5979
5995
|
{
|
|
5980
5996
|
type: "button",
|
|
@@ -5985,7 +6001,7 @@ var Calendar = (props) => {
|
|
|
5985
6001
|
y
|
|
5986
6002
|
);
|
|
5987
6003
|
}) }),
|
|
5988
|
-
pickerMode === "months" && /* @__PURE__ */
|
|
6004
|
+
pickerMode === "months" && /* @__PURE__ */ jsx302("div", { className: "calendar-picker-grid", children: monthLabels.map((label, i) => /* @__PURE__ */ jsx302(
|
|
5989
6005
|
"button",
|
|
5990
6006
|
{
|
|
5991
6007
|
type: "button",
|
|
@@ -5995,8 +6011,8 @@ var Calendar = (props) => {
|
|
|
5995
6011
|
},
|
|
5996
6012
|
i
|
|
5997
6013
|
)) }),
|
|
5998
|
-
pickerMode === "days" && /* @__PURE__ */
|
|
5999
|
-
/* @__PURE__ */
|
|
6014
|
+
pickerMode === "days" && /* @__PURE__ */ jsxs194(Fragment, { children: [
|
|
6015
|
+
/* @__PURE__ */ jsx302("div", { className: "calendar-weekdays", children: weekdays.map((label, i) => /* @__PURE__ */ jsx302(
|
|
6000
6016
|
"div",
|
|
6001
6017
|
{
|
|
6002
6018
|
className: clsx_default(
|
|
@@ -6008,12 +6024,12 @@ var Calendar = (props) => {
|
|
|
6008
6024
|
},
|
|
6009
6025
|
label
|
|
6010
6026
|
)) }),
|
|
6011
|
-
/* @__PURE__ */
|
|
6027
|
+
/* @__PURE__ */ jsx302("div", { className: "calendar-grid", children: days.map((day, idx) => {
|
|
6012
6028
|
const dayEvents = getEventsForDay(day.date);
|
|
6013
6029
|
const t = day.date.getTime();
|
|
6014
6030
|
const disabled = t < minTime || t > maxTime;
|
|
6015
6031
|
const isSelected = selectedDate ? isSameDay(day.date, selectedDate) : false;
|
|
6016
|
-
return /* @__PURE__ */
|
|
6032
|
+
return /* @__PURE__ */ jsx302(
|
|
6017
6033
|
DayCell,
|
|
6018
6034
|
{
|
|
6019
6035
|
day,
|
|
@@ -6035,139 +6051,14 @@ var Calendar = (props) => {
|
|
|
6035
6051
|
Calendar.displayName = "Calendar";
|
|
6036
6052
|
var Calendar_default = Calendar;
|
|
6037
6053
|
|
|
6038
|
-
// src/components/ChatInput/ChatInput.tsx
|
|
6039
|
-
import React4 from "react";
|
|
6040
|
-
|
|
6041
|
-
// src/components/IconButton/IconButton.tsx
|
|
6042
|
-
import { jsx as jsx302 } from "react/jsx-runtime";
|
|
6043
|
-
var IconButton = (props) => {
|
|
6044
|
-
const {
|
|
6045
|
-
icon,
|
|
6046
|
-
type = "primary",
|
|
6047
|
-
size = "md",
|
|
6048
|
-
disabled,
|
|
6049
|
-
...rest
|
|
6050
|
-
} = props;
|
|
6051
|
-
return /* @__PURE__ */ jsx302(
|
|
6052
|
-
"button",
|
|
6053
|
-
{
|
|
6054
|
-
className: clsx_default("lib-xplat-icon-button", type, size),
|
|
6055
|
-
disabled,
|
|
6056
|
-
...rest,
|
|
6057
|
-
children: icon
|
|
6058
|
-
}
|
|
6059
|
-
);
|
|
6060
|
-
};
|
|
6061
|
-
IconButton.displayName = "IconButton";
|
|
6062
|
-
var IconButton_default = IconButton;
|
|
6063
|
-
|
|
6064
|
-
// src/components/ChatInput/ChatInput.tsx
|
|
6065
|
-
import { jsx as jsx303, jsxs as jsxs194 } from "react/jsx-runtime";
|
|
6066
|
-
var MAX_HEIGHT = 200;
|
|
6067
|
-
var ChatInput = React4.forwardRef(
|
|
6068
|
-
(props, ref) => {
|
|
6069
|
-
const {
|
|
6070
|
-
placeholder,
|
|
6071
|
-
value: valueProp,
|
|
6072
|
-
disabled = false,
|
|
6073
|
-
buttonType = "primary",
|
|
6074
|
-
onSubmit,
|
|
6075
|
-
onChange
|
|
6076
|
-
} = props;
|
|
6077
|
-
const isControlled = valueProp !== void 0;
|
|
6078
|
-
const [internalValue, setInternalValue] = React4.useState("");
|
|
6079
|
-
const value = isControlled ? valueProp : internalValue;
|
|
6080
|
-
const hasText = value.trim().length > 0;
|
|
6081
|
-
const textareaRef = React4.useRef(null);
|
|
6082
|
-
const setRefs = React4.useCallback(
|
|
6083
|
-
(el) => {
|
|
6084
|
-
textareaRef.current = el;
|
|
6085
|
-
if (typeof ref === "function") ref(el);
|
|
6086
|
-
else if (ref) ref.current = el;
|
|
6087
|
-
},
|
|
6088
|
-
[ref]
|
|
6089
|
-
);
|
|
6090
|
-
const updateHeight = React4.useCallback(() => {
|
|
6091
|
-
const el = textareaRef.current;
|
|
6092
|
-
if (!el) return;
|
|
6093
|
-
el.style.height = "0px";
|
|
6094
|
-
el.style.height = `${Math.min(el.scrollHeight, MAX_HEIGHT)}px`;
|
|
6095
|
-
}, []);
|
|
6096
|
-
const handleChange = (e) => {
|
|
6097
|
-
const val = e.target.value;
|
|
6098
|
-
if (!isControlled) setInternalValue(val);
|
|
6099
|
-
onChange?.(val);
|
|
6100
|
-
};
|
|
6101
|
-
const handleSubmit = () => {
|
|
6102
|
-
if (!hasText || disabled) return;
|
|
6103
|
-
onSubmit?.(value);
|
|
6104
|
-
if (!isControlled) setInternalValue("");
|
|
6105
|
-
requestAnimationFrame(updateHeight);
|
|
6106
|
-
};
|
|
6107
|
-
const handleKeyDown = (e) => {
|
|
6108
|
-
if (e.key === "Enter" && !e.shiftKey) {
|
|
6109
|
-
e.preventDefault();
|
|
6110
|
-
handleSubmit();
|
|
6111
|
-
}
|
|
6112
|
-
};
|
|
6113
|
-
React4.useEffect(() => {
|
|
6114
|
-
updateHeight();
|
|
6115
|
-
}, [value, updateHeight]);
|
|
6116
|
-
return /* @__PURE__ */ jsxs194("div", { className: clsx_default("lib-xplat-chat-input", disabled && "disabled"), children: [
|
|
6117
|
-
/* @__PURE__ */ jsx303(
|
|
6118
|
-
"textarea",
|
|
6119
|
-
{
|
|
6120
|
-
ref: setRefs,
|
|
6121
|
-
className: "chat-input-textarea",
|
|
6122
|
-
placeholder,
|
|
6123
|
-
value,
|
|
6124
|
-
disabled,
|
|
6125
|
-
rows: 1,
|
|
6126
|
-
onChange: handleChange,
|
|
6127
|
-
onKeyDown: handleKeyDown
|
|
6128
|
-
}
|
|
6129
|
-
),
|
|
6130
|
-
/* @__PURE__ */ jsx303(
|
|
6131
|
-
IconButton_default,
|
|
6132
|
-
{
|
|
6133
|
-
icon: /* @__PURE__ */ jsx303(MessageSquareIcon_default, {}),
|
|
6134
|
-
type: buttonType,
|
|
6135
|
-
size: "sm",
|
|
6136
|
-
disabled: !hasText || disabled,
|
|
6137
|
-
onClick: handleSubmit,
|
|
6138
|
-
"aria-label": "\uC804\uC1A1"
|
|
6139
|
-
}
|
|
6140
|
-
)
|
|
6141
|
-
] });
|
|
6142
|
-
}
|
|
6143
|
-
);
|
|
6144
|
-
ChatInput.displayName = "ChatInput";
|
|
6145
|
-
var ChatInput_default = ChatInput;
|
|
6146
|
-
|
|
6147
|
-
// src/components/Box/Box.tsx
|
|
6148
|
-
import { jsx as jsx304, jsxs as jsxs195 } from "react/jsx-runtime";
|
|
6149
|
-
var Box = ({
|
|
6150
|
-
children,
|
|
6151
|
-
title,
|
|
6152
|
-
variant = "outlined",
|
|
6153
|
-
padding = "md"
|
|
6154
|
-
}) => {
|
|
6155
|
-
return /* @__PURE__ */ jsxs195("div", { className: clsx_default("lib-xplat-box", variant, `pad-${padding}`), children: [
|
|
6156
|
-
title && /* @__PURE__ */ jsx304("div", { className: "box-title", children: title }),
|
|
6157
|
-
/* @__PURE__ */ jsx304("div", { className: "box-content", children })
|
|
6158
|
-
] });
|
|
6159
|
-
};
|
|
6160
|
-
Box.displayName = "Box";
|
|
6161
|
-
var Box_default = Box;
|
|
6162
|
-
|
|
6163
6054
|
// src/components/CardTab/CardTab.tsx
|
|
6164
|
-
import
|
|
6055
|
+
import React4 from "react";
|
|
6165
6056
|
|
|
6166
6057
|
// src/components/CardTab/CardTabPanel.tsx
|
|
6167
|
-
import { jsx as
|
|
6058
|
+
import { jsx as jsx303 } from "react/jsx-runtime";
|
|
6168
6059
|
var CardTabPanel = (props) => {
|
|
6169
6060
|
const { children, columns = 3 } = props;
|
|
6170
|
-
return /* @__PURE__ */
|
|
6061
|
+
return /* @__PURE__ */ jsx303(
|
|
6171
6062
|
"div",
|
|
6172
6063
|
{
|
|
6173
6064
|
className: "card-tab-panel",
|
|
@@ -6180,7 +6071,7 @@ CardTabPanel.displayName = "CardTab.Panel";
|
|
|
6180
6071
|
var CardTabPanel_default = CardTabPanel;
|
|
6181
6072
|
|
|
6182
6073
|
// src/components/CardTab/CardTab.tsx
|
|
6183
|
-
import { jsx as
|
|
6074
|
+
import { jsx as jsx304, jsxs as jsxs195 } from "react/jsx-runtime";
|
|
6184
6075
|
var CardTabRoot = (props) => {
|
|
6185
6076
|
const {
|
|
6186
6077
|
tabs,
|
|
@@ -6190,7 +6081,7 @@ var CardTabRoot = (props) => {
|
|
|
6190
6081
|
children
|
|
6191
6082
|
} = props;
|
|
6192
6083
|
const isControlled = activeValueProp !== void 0;
|
|
6193
|
-
const [uncontrolledValue, setUncontrolledValue] =
|
|
6084
|
+
const [uncontrolledValue, setUncontrolledValue] = React4.useState(tabs[0]?.value ?? "");
|
|
6194
6085
|
const activeValue = isControlled ? activeValueProp : uncontrolledValue;
|
|
6195
6086
|
const handleTabClick = (tab) => {
|
|
6196
6087
|
if (!isControlled) {
|
|
@@ -6198,16 +6089,16 @@ var CardTabRoot = (props) => {
|
|
|
6198
6089
|
}
|
|
6199
6090
|
onChange?.(tab);
|
|
6200
6091
|
};
|
|
6201
|
-
const panels =
|
|
6202
|
-
(child) =>
|
|
6092
|
+
const panels = React4.Children.toArray(children).filter(
|
|
6093
|
+
(child) => React4.isValidElement(child) && child.type === CardTabPanel_default
|
|
6203
6094
|
);
|
|
6204
6095
|
const activePanel = panels.find(
|
|
6205
6096
|
(panel) => panel.props.value === activeValue
|
|
6206
6097
|
);
|
|
6207
|
-
return /* @__PURE__ */
|
|
6208
|
-
/* @__PURE__ */
|
|
6098
|
+
return /* @__PURE__ */ jsxs195("div", { className: clsx_default("lib-xplat-card-tab", size), children: [
|
|
6099
|
+
/* @__PURE__ */ jsx304("div", { className: "card-tab-bar", children: tabs.map((tab) => {
|
|
6209
6100
|
const isActive = tab.value === activeValue;
|
|
6210
|
-
return /* @__PURE__ */
|
|
6101
|
+
return /* @__PURE__ */ jsx304(
|
|
6211
6102
|
"button",
|
|
6212
6103
|
{
|
|
6213
6104
|
className: clsx_default("card-tab-trigger", isActive && "active"),
|
|
@@ -6219,7 +6110,7 @@ var CardTabRoot = (props) => {
|
|
|
6219
6110
|
tab.value
|
|
6220
6111
|
);
|
|
6221
6112
|
}) }),
|
|
6222
|
-
/* @__PURE__ */
|
|
6113
|
+
/* @__PURE__ */ jsx304("div", { className: "card-tab-body", children: activePanel })
|
|
6223
6114
|
] });
|
|
6224
6115
|
};
|
|
6225
6116
|
CardTabRoot.displayName = "CardTab";
|
|
@@ -6229,8 +6120,8 @@ var CardTab = Object.assign(CardTabRoot, {
|
|
|
6229
6120
|
var CardTab_default = CardTab;
|
|
6230
6121
|
|
|
6231
6122
|
// src/components/Chart/Chart.tsx
|
|
6232
|
-
import
|
|
6233
|
-
import { Fragment as Fragment2, jsx as
|
|
6123
|
+
import React5 from "react";
|
|
6124
|
+
import { Fragment as Fragment2, jsx as jsx305, jsxs as jsxs196 } from "react/jsx-runtime";
|
|
6234
6125
|
var CATEGORICAL_COUNT2 = 8;
|
|
6235
6126
|
var LINE_BAR_PALETTES = Array.from({ length: CATEGORICAL_COUNT2 }, (_, i) => {
|
|
6236
6127
|
const n = i + 1;
|
|
@@ -6275,8 +6166,8 @@ var toSmoothPath = (points) => {
|
|
|
6275
6166
|
return d;
|
|
6276
6167
|
};
|
|
6277
6168
|
var useChartSize = (ref) => {
|
|
6278
|
-
const [size, setSize] =
|
|
6279
|
-
|
|
6169
|
+
const [size, setSize] = React5.useState({ width: 0, height: 0 });
|
|
6170
|
+
React5.useEffect(() => {
|
|
6280
6171
|
const el = ref.current;
|
|
6281
6172
|
if (!el) return;
|
|
6282
6173
|
let rafId = 0;
|
|
@@ -6302,10 +6193,10 @@ var useChartSize = (ref) => {
|
|
|
6302
6193
|
};
|
|
6303
6194
|
var prefersReducedMotion = () => typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
6304
6195
|
var useChartAnimation = (containerRef, dataKey) => {
|
|
6305
|
-
const [animate, setAnimate] =
|
|
6306
|
-
const prevDataKey =
|
|
6307
|
-
const hasAnimated =
|
|
6308
|
-
|
|
6196
|
+
const [animate, setAnimate] = React5.useState(false);
|
|
6197
|
+
const prevDataKey = React5.useRef(dataKey);
|
|
6198
|
+
const hasAnimated = React5.useRef(false);
|
|
6199
|
+
React5.useEffect(() => {
|
|
6309
6200
|
if (prefersReducedMotion()) return;
|
|
6310
6201
|
const el = containerRef.current;
|
|
6311
6202
|
if (!el) return;
|
|
@@ -6321,7 +6212,7 @@ var useChartAnimation = (containerRef, dataKey) => {
|
|
|
6321
6212
|
observer.observe(el);
|
|
6322
6213
|
return () => observer.disconnect();
|
|
6323
6214
|
}, [containerRef]);
|
|
6324
|
-
|
|
6215
|
+
React5.useEffect(() => {
|
|
6325
6216
|
if (dataKey !== prevDataKey.current) {
|
|
6326
6217
|
prevDataKey.current = dataKey;
|
|
6327
6218
|
if (prefersReducedMotion()) return;
|
|
@@ -6335,15 +6226,15 @@ var useChartAnimation = (containerRef, dataKey) => {
|
|
|
6335
6226
|
};
|
|
6336
6227
|
var TOOLTIP_OFFSET = 12;
|
|
6337
6228
|
var useChartTooltip = (enabled) => {
|
|
6338
|
-
const [tooltip, setTooltip] =
|
|
6229
|
+
const [tooltip, setTooltip] = React5.useState({
|
|
6339
6230
|
visible: false,
|
|
6340
6231
|
x: 0,
|
|
6341
6232
|
y: 0,
|
|
6342
6233
|
content: ""
|
|
6343
6234
|
});
|
|
6344
|
-
const containerRef =
|
|
6345
|
-
const rafRef =
|
|
6346
|
-
const move =
|
|
6235
|
+
const containerRef = React5.useRef(null);
|
|
6236
|
+
const rafRef = React5.useRef(0);
|
|
6237
|
+
const move = React5.useCallback((e) => {
|
|
6347
6238
|
if (!enabled) return;
|
|
6348
6239
|
const cx = e.clientX;
|
|
6349
6240
|
const cy = e.clientY;
|
|
@@ -6354,24 +6245,24 @@ var useChartTooltip = (enabled) => {
|
|
|
6354
6245
|
setTooltip((prev) => ({ ...prev, x: cx - rect.left, y: cy - rect.top }));
|
|
6355
6246
|
});
|
|
6356
6247
|
}, [enabled]);
|
|
6357
|
-
const show =
|
|
6248
|
+
const show = React5.useCallback((e, content) => {
|
|
6358
6249
|
if (!enabled) return;
|
|
6359
6250
|
const rect = containerRef.current?.getBoundingClientRect();
|
|
6360
6251
|
if (!rect) return;
|
|
6361
6252
|
setTooltip({ visible: true, x: e.clientX - rect.left, y: e.clientY - rect.top, content });
|
|
6362
6253
|
}, [enabled]);
|
|
6363
|
-
const hide =
|
|
6254
|
+
const hide = React5.useCallback(() => {
|
|
6364
6255
|
cancelAnimationFrame(rafRef.current);
|
|
6365
6256
|
setTooltip((prev) => ({ ...prev, visible: false }));
|
|
6366
6257
|
}, []);
|
|
6367
6258
|
return { tooltip, show, hide, move, containerRef };
|
|
6368
6259
|
};
|
|
6369
|
-
var GridLines =
|
|
6260
|
+
var GridLines = React5.memo(({ width, height, chartH, maxVal }) => /* @__PURE__ */ jsx305(Fragment2, { children: [0, 0.25, 0.5, 0.75, 1].map((ratio) => {
|
|
6370
6261
|
const y = PADDING.top + (1 - ratio) * chartH;
|
|
6371
6262
|
const val = Math.round(maxVal * ratio);
|
|
6372
|
-
return /* @__PURE__ */
|
|
6373
|
-
/* @__PURE__ */
|
|
6374
|
-
/* @__PURE__ */
|
|
6263
|
+
return /* @__PURE__ */ jsxs196("g", { children: [
|
|
6264
|
+
/* @__PURE__ */ jsx305("line", { x1: PADDING.left, y1: y, x2: width - PADDING.right, y2: y, className: "chart-grid" }),
|
|
6265
|
+
/* @__PURE__ */ jsx305("text", { x: PADDING.left - 8, y: y + 4, className: "chart-axis-label", textAnchor: "end", children: val })
|
|
6375
6266
|
] }, ratio);
|
|
6376
6267
|
}) }));
|
|
6377
6268
|
GridLines.displayName = "GridLines";
|
|
@@ -6381,18 +6272,18 @@ var getLabelStep = (count, chartW) => {
|
|
|
6381
6272
|
if (count <= maxLabels) return 1;
|
|
6382
6273
|
return Math.ceil(count / maxLabels);
|
|
6383
6274
|
};
|
|
6384
|
-
var AxisLabels =
|
|
6275
|
+
var AxisLabels = React5.memo(({ labels, count, chartW, height }) => {
|
|
6385
6276
|
const step = getLabelStep(count, chartW);
|
|
6386
|
-
return /* @__PURE__ */
|
|
6277
|
+
return /* @__PURE__ */ jsx305(Fragment2, { children: labels.map((label, i) => {
|
|
6387
6278
|
if (i % step !== 0) return null;
|
|
6388
6279
|
const x = PADDING.left + i / (count - 1 || 1) * chartW;
|
|
6389
|
-
return /* @__PURE__ */
|
|
6280
|
+
return /* @__PURE__ */ jsx305("text", { x, y: height - 8, className: "chart-axis-label", textAnchor: "middle", children: label }, i);
|
|
6390
6281
|
}) });
|
|
6391
6282
|
});
|
|
6392
6283
|
AxisLabels.displayName = "AxisLabels";
|
|
6393
6284
|
var useCrosshair = (seriesPoints, entries, labels, chartH) => {
|
|
6394
|
-
const [activeIndex, setActiveIndex] =
|
|
6395
|
-
const handleMouseMove =
|
|
6285
|
+
const [activeIndex, setActiveIndex] = React5.useState(null);
|
|
6286
|
+
const handleMouseMove = React5.useCallback((e) => {
|
|
6396
6287
|
const svg = e.currentTarget;
|
|
6397
6288
|
const rect = svg.getBoundingClientRect();
|
|
6398
6289
|
const mx = (e.clientX - rect.left) / rect.width * svg.viewBox.baseVal.width;
|
|
@@ -6411,17 +6302,17 @@ var useCrosshair = (seriesPoints, entries, labels, chartH) => {
|
|
|
6411
6302
|
}
|
|
6412
6303
|
setActiveIndex(minDist <= threshold ? closest : null);
|
|
6413
6304
|
}, [seriesPoints]);
|
|
6414
|
-
const handleMouseLeave =
|
|
6305
|
+
const handleMouseLeave = React5.useCallback(() => {
|
|
6415
6306
|
setActiveIndex(null);
|
|
6416
6307
|
}, []);
|
|
6417
|
-
const tooltipContent =
|
|
6308
|
+
const tooltipContent = React5.useMemo(() => {
|
|
6418
6309
|
if (activeIndex === null) return "";
|
|
6419
6310
|
return entries.map(([key], di) => {
|
|
6420
6311
|
const p = seriesPoints[di]?.[activeIndex];
|
|
6421
6312
|
return p ? `${key}: ${p.v}` : "";
|
|
6422
6313
|
}).filter(Boolean).join(" / ");
|
|
6423
6314
|
}, [activeIndex, entries, seriesPoints]);
|
|
6424
|
-
const getTooltipAt =
|
|
6315
|
+
const getTooltipAt = React5.useCallback((idx) => {
|
|
6425
6316
|
return entries.map(([key], di) => {
|
|
6426
6317
|
const p = seriesPoints[di]?.[idx];
|
|
6427
6318
|
return p ? `${key}: ${p.v}` : "";
|
|
@@ -6429,16 +6320,16 @@ var useCrosshair = (seriesPoints, entries, labels, chartH) => {
|
|
|
6429
6320
|
}, [entries, seriesPoints]);
|
|
6430
6321
|
return { activeIndex, handleMouseMove, handleMouseLeave, tooltipContent, getTooltipAt };
|
|
6431
6322
|
};
|
|
6432
|
-
var LineChart =
|
|
6433
|
-
const entries =
|
|
6434
|
-
const maxVal =
|
|
6323
|
+
var LineChart = React5.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
|
|
6324
|
+
const entries = React5.useMemo(() => Object.entries(data), [data]);
|
|
6325
|
+
const maxVal = React5.useMemo(() => {
|
|
6435
6326
|
const allValues = entries.flatMap(([, v]) => v);
|
|
6436
6327
|
return Math.max(...allValues) * 1.2 || 1;
|
|
6437
6328
|
}, [entries]);
|
|
6438
6329
|
const count = labels.length;
|
|
6439
6330
|
const chartW = width - PADDING.left - PADDING.right;
|
|
6440
6331
|
const chartH = height - PADDING.top - PADDING.bottom;
|
|
6441
|
-
const seriesPoints =
|
|
6332
|
+
const seriesPoints = React5.useMemo(
|
|
6442
6333
|
() => entries.map(
|
|
6443
6334
|
([, values]) => values.map((v, i) => ({
|
|
6444
6335
|
x: PADDING.left + i / (count - 1 || 1) * chartW,
|
|
@@ -6448,9 +6339,9 @@ var LineChart = React6.memo(({ data, labels, width, height, animate, onHover, on
|
|
|
6448
6339
|
),
|
|
6449
6340
|
[entries, count, chartW, chartH, maxVal]
|
|
6450
6341
|
);
|
|
6451
|
-
const clipRef =
|
|
6342
|
+
const clipRef = React5.useRef(null);
|
|
6452
6343
|
const { activeIndex, handleMouseMove, handleMouseLeave, getTooltipAt } = useCrosshair(seriesPoints, entries, labels, chartH);
|
|
6453
|
-
|
|
6344
|
+
React5.useEffect(() => {
|
|
6454
6345
|
if (!animate || !clipRef.current) return;
|
|
6455
6346
|
clipRef.current.setAttribute("width", "0");
|
|
6456
6347
|
requestAnimationFrame(() => {
|
|
@@ -6462,7 +6353,7 @@ var LineChart = React6.memo(({ data, labels, width, height, animate, onHover, on
|
|
|
6462
6353
|
}, [animate, width]);
|
|
6463
6354
|
const activeX = activeIndex !== null ? seriesPoints[0]?.[activeIndex]?.x ?? null : null;
|
|
6464
6355
|
const lineClipId = "line-area-clip";
|
|
6465
|
-
return /* @__PURE__ */
|
|
6356
|
+
return /* @__PURE__ */ jsxs196(
|
|
6466
6357
|
"svg",
|
|
6467
6358
|
{
|
|
6468
6359
|
viewBox: `0 0 ${width} ${height}`,
|
|
@@ -6480,9 +6371,9 @@ var LineChart = React6.memo(({ data, labels, width, height, animate, onHover, on
|
|
|
6480
6371
|
onLeave();
|
|
6481
6372
|
},
|
|
6482
6373
|
children: [
|
|
6483
|
-
animate && /* @__PURE__ */
|
|
6484
|
-
/* @__PURE__ */
|
|
6485
|
-
/* @__PURE__ */
|
|
6374
|
+
animate && /* @__PURE__ */ jsx305("defs", { children: /* @__PURE__ */ jsx305("clipPath", { id: lineClipId, children: /* @__PURE__ */ jsx305("rect", { ref: clipRef, x: "0", y: "0", width: animate ? 0 : width, height }) }) }),
|
|
6375
|
+
/* @__PURE__ */ jsx305(GridLines, { width, height, chartH, maxVal }),
|
|
6376
|
+
/* @__PURE__ */ jsx305(AxisLabels, { labels, count, chartW, height }),
|
|
6486
6377
|
entries.map(([key], di) => {
|
|
6487
6378
|
const palette = getPalette(LINE_BAR_PALETTES, di, key);
|
|
6488
6379
|
const color = palette[2];
|
|
@@ -6491,16 +6382,16 @@ var LineChart = React6.memo(({ data, labels, width, height, animate, onHover, on
|
|
|
6491
6382
|
const gradientId = `line-gradient-${di}`;
|
|
6492
6383
|
const polyPoints = points.map((p) => `${p.x},${p.y}`).join(" ");
|
|
6493
6384
|
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`;
|
|
6494
|
-
return /* @__PURE__ */
|
|
6495
|
-
/* @__PURE__ */
|
|
6496
|
-
/* @__PURE__ */
|
|
6497
|
-
/* @__PURE__ */
|
|
6385
|
+
return /* @__PURE__ */ jsxs196("g", { children: [
|
|
6386
|
+
/* @__PURE__ */ jsx305("defs", { children: /* @__PURE__ */ jsxs196("linearGradient", { id: gradientId, x1: "0", y1: "0", x2: "0", y2: "1", children: [
|
|
6387
|
+
/* @__PURE__ */ jsx305("stop", { offset: "0%", stopColor: areaColor, stopOpacity: "0.2" }),
|
|
6388
|
+
/* @__PURE__ */ jsx305("stop", { offset: "100%", stopColor: areaColor, stopOpacity: "0" })
|
|
6498
6389
|
] }) }),
|
|
6499
|
-
/* @__PURE__ */
|
|
6500
|
-
/* @__PURE__ */
|
|
6501
|
-
/* @__PURE__ */
|
|
6390
|
+
/* @__PURE__ */ jsxs196("g", { clipPath: animate ? `url(#${lineClipId})` : void 0, children: [
|
|
6391
|
+
/* @__PURE__ */ jsx305("path", { d: areaD, fill: `url(#${gradientId})` }),
|
|
6392
|
+
/* @__PURE__ */ jsx305("polyline", { points: polyPoints, fill: "none", stroke: color, strokeWidth: "2" })
|
|
6502
6393
|
] }),
|
|
6503
|
-
activeIndex !== null && points[activeIndex] && /* @__PURE__ */
|
|
6394
|
+
activeIndex !== null && points[activeIndex] && /* @__PURE__ */ jsx305(
|
|
6504
6395
|
"circle",
|
|
6505
6396
|
{
|
|
6506
6397
|
cx: points[activeIndex].x,
|
|
@@ -6512,7 +6403,7 @@ var LineChart = React6.memo(({ data, labels, width, height, animate, onHover, on
|
|
|
6512
6403
|
)
|
|
6513
6404
|
] }, di);
|
|
6514
6405
|
}),
|
|
6515
|
-
activeX !== null && /* @__PURE__ */
|
|
6406
|
+
activeX !== null && /* @__PURE__ */ jsx305(
|
|
6516
6407
|
"line",
|
|
6517
6408
|
{
|
|
6518
6409
|
x1: activeX,
|
|
@@ -6522,7 +6413,7 @@ var LineChart = React6.memo(({ data, labels, width, height, animate, onHover, on
|
|
|
6522
6413
|
className: "chart-crosshair"
|
|
6523
6414
|
}
|
|
6524
6415
|
),
|
|
6525
|
-
/* @__PURE__ */
|
|
6416
|
+
/* @__PURE__ */ jsx305(
|
|
6526
6417
|
"rect",
|
|
6527
6418
|
{
|
|
6528
6419
|
x: PADDING.left,
|
|
@@ -6538,16 +6429,16 @@ var LineChart = React6.memo(({ data, labels, width, height, animate, onHover, on
|
|
|
6538
6429
|
);
|
|
6539
6430
|
});
|
|
6540
6431
|
LineChart.displayName = "LineChart";
|
|
6541
|
-
var CurveChart =
|
|
6542
|
-
const entries =
|
|
6543
|
-
const maxVal =
|
|
6432
|
+
var CurveChart = React5.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
|
|
6433
|
+
const entries = React5.useMemo(() => Object.entries(data), [data]);
|
|
6434
|
+
const maxVal = React5.useMemo(() => {
|
|
6544
6435
|
const allValues = entries.flatMap(([, v]) => v);
|
|
6545
6436
|
return Math.max(...allValues) * 1.2 || 1;
|
|
6546
6437
|
}, [entries]);
|
|
6547
6438
|
const count = labels.length;
|
|
6548
6439
|
const chartW = width - PADDING.left - PADDING.right;
|
|
6549
6440
|
const chartH = height - PADDING.top - PADDING.bottom;
|
|
6550
|
-
const seriesPoints =
|
|
6441
|
+
const seriesPoints = React5.useMemo(
|
|
6551
6442
|
() => entries.map(
|
|
6552
6443
|
([, values]) => values.map((v, i) => ({
|
|
6553
6444
|
x: PADDING.left + i / (count - 1 || 1) * chartW,
|
|
@@ -6557,9 +6448,9 @@ var CurveChart = React6.memo(({ data, labels, width, height, animate, onHover, o
|
|
|
6557
6448
|
),
|
|
6558
6449
|
[entries, count, chartW, chartH, maxVal]
|
|
6559
6450
|
);
|
|
6560
|
-
const curveClipRef =
|
|
6451
|
+
const curveClipRef = React5.useRef(null);
|
|
6561
6452
|
const { activeIndex, handleMouseMove, handleMouseLeave, getTooltipAt } = useCrosshair(seriesPoints, entries, labels, chartH);
|
|
6562
|
-
|
|
6453
|
+
React5.useEffect(() => {
|
|
6563
6454
|
if (!animate || !curveClipRef.current) return;
|
|
6564
6455
|
curveClipRef.current.setAttribute("width", "0");
|
|
6565
6456
|
requestAnimationFrame(() => {
|
|
@@ -6571,7 +6462,7 @@ var CurveChart = React6.memo(({ data, labels, width, height, animate, onHover, o
|
|
|
6571
6462
|
}, [animate, width]);
|
|
6572
6463
|
const activeX = activeIndex !== null ? seriesPoints[0]?.[activeIndex]?.x ?? null : null;
|
|
6573
6464
|
const curveClipId = "curve-area-clip";
|
|
6574
|
-
return /* @__PURE__ */
|
|
6465
|
+
return /* @__PURE__ */ jsxs196(
|
|
6575
6466
|
"svg",
|
|
6576
6467
|
{
|
|
6577
6468
|
viewBox: `0 0 ${width} ${height}`,
|
|
@@ -6590,9 +6481,9 @@ var CurveChart = React6.memo(({ data, labels, width, height, animate, onHover, o
|
|
|
6590
6481
|
onLeave();
|
|
6591
6482
|
},
|
|
6592
6483
|
children: [
|
|
6593
|
-
animate && /* @__PURE__ */
|
|
6594
|
-
/* @__PURE__ */
|
|
6595
|
-
/* @__PURE__ */
|
|
6484
|
+
animate && /* @__PURE__ */ jsx305("defs", { children: /* @__PURE__ */ jsx305("clipPath", { id: curveClipId, children: /* @__PURE__ */ jsx305("rect", { ref: curveClipRef, x: "0", y: "0", width: animate ? 0 : width, height }) }) }),
|
|
6485
|
+
/* @__PURE__ */ jsx305(GridLines, { width, height, chartH, maxVal }),
|
|
6486
|
+
/* @__PURE__ */ jsx305(AxisLabels, { labels, count, chartW, height }),
|
|
6596
6487
|
entries.map(([key], di) => {
|
|
6597
6488
|
const palette = getPalette(LINE_BAR_PALETTES, di, key);
|
|
6598
6489
|
const color = palette[2];
|
|
@@ -6601,16 +6492,16 @@ var CurveChart = React6.memo(({ data, labels, width, height, animate, onHover, o
|
|
|
6601
6492
|
const gradientId = `curve-gradient-${di}`;
|
|
6602
6493
|
const linePath = toSmoothPath(points);
|
|
6603
6494
|
const areaPath = linePath + ` L ${points[points.length - 1].x} ${PADDING.top + chartH} L ${points[0].x} ${PADDING.top + chartH} Z`;
|
|
6604
|
-
return /* @__PURE__ */
|
|
6605
|
-
/* @__PURE__ */
|
|
6606
|
-
/* @__PURE__ */
|
|
6607
|
-
/* @__PURE__ */
|
|
6495
|
+
return /* @__PURE__ */ jsxs196("g", { children: [
|
|
6496
|
+
/* @__PURE__ */ jsx305("defs", { children: /* @__PURE__ */ jsxs196("linearGradient", { id: gradientId, x1: "0", y1: "0", x2: "0", y2: "1", children: [
|
|
6497
|
+
/* @__PURE__ */ jsx305("stop", { offset: "0%", stopColor: areaColor, stopOpacity: "0.4" }),
|
|
6498
|
+
/* @__PURE__ */ jsx305("stop", { offset: "100%", stopColor: areaColor, stopOpacity: "0.02" })
|
|
6608
6499
|
] }) }),
|
|
6609
|
-
/* @__PURE__ */
|
|
6610
|
-
/* @__PURE__ */
|
|
6611
|
-
/* @__PURE__ */
|
|
6500
|
+
/* @__PURE__ */ jsxs196("g", { clipPath: animate ? `url(#${curveClipId})` : void 0, children: [
|
|
6501
|
+
/* @__PURE__ */ jsx305("path", { d: areaPath, fill: `url(#${gradientId})` }),
|
|
6502
|
+
/* @__PURE__ */ jsx305("path", { d: linePath, fill: "none", stroke: color, strokeWidth: "2" })
|
|
6612
6503
|
] }),
|
|
6613
|
-
activeIndex !== null && points[activeIndex] && /* @__PURE__ */
|
|
6504
|
+
activeIndex !== null && points[activeIndex] && /* @__PURE__ */ jsx305(
|
|
6614
6505
|
"circle",
|
|
6615
6506
|
{
|
|
6616
6507
|
cx: points[activeIndex].x,
|
|
@@ -6622,7 +6513,7 @@ var CurveChart = React6.memo(({ data, labels, width, height, animate, onHover, o
|
|
|
6622
6513
|
)
|
|
6623
6514
|
] }, di);
|
|
6624
6515
|
}),
|
|
6625
|
-
activeX !== null && /* @__PURE__ */
|
|
6516
|
+
activeX !== null && /* @__PURE__ */ jsx305(
|
|
6626
6517
|
"line",
|
|
6627
6518
|
{
|
|
6628
6519
|
x1: activeX,
|
|
@@ -6632,7 +6523,7 @@ var CurveChart = React6.memo(({ data, labels, width, height, animate, onHover, o
|
|
|
6632
6523
|
className: "chart-crosshair"
|
|
6633
6524
|
}
|
|
6634
6525
|
),
|
|
6635
|
-
/* @__PURE__ */
|
|
6526
|
+
/* @__PURE__ */ jsx305(
|
|
6636
6527
|
"rect",
|
|
6637
6528
|
{
|
|
6638
6529
|
x: PADDING.left,
|
|
@@ -6648,9 +6539,9 @@ var CurveChart = React6.memo(({ data, labels, width, height, animate, onHover, o
|
|
|
6648
6539
|
);
|
|
6649
6540
|
});
|
|
6650
6541
|
CurveChart.displayName = "CurveChart";
|
|
6651
|
-
var BarChart =
|
|
6652
|
-
const entries =
|
|
6653
|
-
const maxVal =
|
|
6542
|
+
var BarChart = React5.memo(({ data, labels, width, height, animate, onHover, onMove, onLeave }) => {
|
|
6543
|
+
const entries = React5.useMemo(() => Object.entries(data), [data]);
|
|
6544
|
+
const maxVal = React5.useMemo(() => {
|
|
6654
6545
|
const allValues = entries.flatMap(([, v]) => v);
|
|
6655
6546
|
return Math.max(...allValues) * 1.2 || 1;
|
|
6656
6547
|
}, [entries]);
|
|
@@ -6662,7 +6553,7 @@ var BarChart = React6.memo(({ data, labels, width, height, animate, onHover, onM
|
|
|
6662
6553
|
const barGap = groupCount > 1 ? 2 : 0;
|
|
6663
6554
|
const barW = Math.max(1, Math.min(32, (groupW * 0.7 - barGap * (groupCount - 1)) / groupCount));
|
|
6664
6555
|
const baseline = PADDING.top + chartH;
|
|
6665
|
-
const bars =
|
|
6556
|
+
const bars = React5.useMemo(
|
|
6666
6557
|
() => entries.map(
|
|
6667
6558
|
([, values], di) => values.map((v, i) => {
|
|
6668
6559
|
const totalBarsW = barW * groupCount + barGap * (groupCount - 1);
|
|
@@ -6675,11 +6566,11 @@ var BarChart = React6.memo(({ data, labels, width, height, animate, onHover, onM
|
|
|
6675
6566
|
[entries, maxVal, chartH, groupW, barW, barGap, groupCount]
|
|
6676
6567
|
);
|
|
6677
6568
|
const barLabelStep = getLabelStep(count, chartW);
|
|
6678
|
-
return /* @__PURE__ */
|
|
6679
|
-
/* @__PURE__ */
|
|
6569
|
+
return /* @__PURE__ */ jsxs196("svg", { viewBox: `0 0 ${width} ${height}`, className: "chart-svg", children: [
|
|
6570
|
+
/* @__PURE__ */ jsx305(GridLines, { width, height, chartH, maxVal }),
|
|
6680
6571
|
labels.map((label, i) => {
|
|
6681
6572
|
if (i % barLabelStep !== 0) return null;
|
|
6682
|
-
return /* @__PURE__ */
|
|
6573
|
+
return /* @__PURE__ */ jsx305("text", { x: PADDING.left + groupW * i + groupW / 2, y: height - 8, className: "chart-axis-label", textAnchor: "middle", children: label }, i);
|
|
6683
6574
|
}),
|
|
6684
6575
|
entries.map(([key], di) => {
|
|
6685
6576
|
const palette = getPalette(LINE_BAR_PALETTES, di, key);
|
|
@@ -6688,7 +6579,7 @@ var BarChart = React6.memo(({ data, labels, width, height, animate, onHover, onM
|
|
|
6688
6579
|
const r2 = Math.min(4, b.w / 2);
|
|
6689
6580
|
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`;
|
|
6690
6581
|
const delay = 100 + i * 80;
|
|
6691
|
-
return /* @__PURE__ */
|
|
6582
|
+
return /* @__PURE__ */ jsx305(
|
|
6692
6583
|
"path",
|
|
6693
6584
|
{
|
|
6694
6585
|
d,
|
|
@@ -6709,11 +6600,11 @@ var BarChart = React6.memo(({ data, labels, width, height, animate, onHover, onM
|
|
|
6709
6600
|
] });
|
|
6710
6601
|
});
|
|
6711
6602
|
BarChart.displayName = "BarChart";
|
|
6712
|
-
var PieDonutChart =
|
|
6603
|
+
var PieDonutChart = React5.memo(
|
|
6713
6604
|
({ data, labels, width, height, animate, isDoughnut, onHover, onMove, onLeave }) => {
|
|
6714
|
-
const entries =
|
|
6715
|
-
const values =
|
|
6716
|
-
const total =
|
|
6605
|
+
const entries = React5.useMemo(() => Object.entries(data), [data]);
|
|
6606
|
+
const values = React5.useMemo(() => entries.flatMap(([, v]) => v), [entries]);
|
|
6607
|
+
const total = React5.useMemo(() => values.reduce((a, b) => a + b, 0) || 1, [values]);
|
|
6717
6608
|
const size = Math.min(width, height);
|
|
6718
6609
|
const cx = size / 2;
|
|
6719
6610
|
const cy = size / 2;
|
|
@@ -6721,10 +6612,10 @@ var PieDonutChart = React6.memo(
|
|
|
6721
6612
|
const innerR = isDoughnut ? r2 * 0.5 : 0;
|
|
6722
6613
|
const firstKey = entries[0]?.[0] ?? "";
|
|
6723
6614
|
const colorOffset = hashString(firstKey);
|
|
6724
|
-
const maskRef =
|
|
6615
|
+
const maskRef = React5.useRef(null);
|
|
6725
6616
|
const maskR = r2 + 10;
|
|
6726
6617
|
const maskCircumference = 2 * Math.PI * maskR;
|
|
6727
|
-
|
|
6618
|
+
React5.useEffect(() => {
|
|
6728
6619
|
if (!animate || !maskRef.current) return;
|
|
6729
6620
|
const el = maskRef.current;
|
|
6730
6621
|
el.style.strokeDasharray = `${maskCircumference}`;
|
|
@@ -6734,7 +6625,7 @@ var PieDonutChart = React6.memo(
|
|
|
6734
6625
|
el.style.strokeDashoffset = "0";
|
|
6735
6626
|
});
|
|
6736
6627
|
}, [animate, maskCircumference]);
|
|
6737
|
-
const sliceData =
|
|
6628
|
+
const sliceData = React5.useMemo(() => {
|
|
6738
6629
|
let angle0 = -Math.PI / 2;
|
|
6739
6630
|
let cumulativeAngle = 0;
|
|
6740
6631
|
return values.map((v, i) => {
|
|
@@ -6768,8 +6659,8 @@ var PieDonutChart = React6.memo(
|
|
|
6768
6659
|
});
|
|
6769
6660
|
}, [values, total, cx, cy, r2, innerR, labels]);
|
|
6770
6661
|
const maskId = `pie-mask-${isDoughnut ? "d" : "p"}`;
|
|
6771
|
-
return /* @__PURE__ */
|
|
6772
|
-
animate && /* @__PURE__ */
|
|
6662
|
+
return /* @__PURE__ */ jsxs196("svg", { viewBox: `0 0 ${size} ${size}`, className: "chart-svg chart-pie", children: [
|
|
6663
|
+
animate && /* @__PURE__ */ jsx305("defs", { children: /* @__PURE__ */ jsx305("mask", { id: maskId, children: /* @__PURE__ */ jsx305(
|
|
6773
6664
|
"circle",
|
|
6774
6665
|
{
|
|
6775
6666
|
ref: maskRef,
|
|
@@ -6782,7 +6673,7 @@ var PieDonutChart = React6.memo(
|
|
|
6782
6673
|
transform: `rotate(-90 ${cx} ${cy})`
|
|
6783
6674
|
}
|
|
6784
6675
|
) }) }),
|
|
6785
|
-
/* @__PURE__ */
|
|
6676
|
+
/* @__PURE__ */ jsx305("g", { mask: animate ? `url(#${maskId})` : void 0, children: sliceData.map((s, i) => /* @__PURE__ */ jsx305("g", { children: /* @__PURE__ */ jsx305(
|
|
6786
6677
|
"path",
|
|
6787
6678
|
{
|
|
6788
6679
|
d: s.d,
|
|
@@ -6798,9 +6689,9 @@ var PieDonutChart = React6.memo(
|
|
|
6798
6689
|
);
|
|
6799
6690
|
PieDonutChart.displayName = "PieDonutChart";
|
|
6800
6691
|
var ChartTooltip = ({ x, y, containerWidth, containerHeight, tooltipType, children }) => {
|
|
6801
|
-
const ref =
|
|
6802
|
-
const [pos, setPos] =
|
|
6803
|
-
|
|
6692
|
+
const ref = React5.useRef(null);
|
|
6693
|
+
const [pos, setPos] = React5.useState({ left: 0, top: 0 });
|
|
6694
|
+
React5.useLayoutEffect(() => {
|
|
6804
6695
|
const el = ref.current;
|
|
6805
6696
|
if (!el) return;
|
|
6806
6697
|
const w = el.offsetWidth;
|
|
@@ -6817,15 +6708,15 @@ var ChartTooltip = ({ x, y, containerWidth, containerHeight, tooltipType, childr
|
|
|
6817
6708
|
const sepIdx = content.indexOf(" \u2014 ");
|
|
6818
6709
|
const title = sepIdx >= 0 ? content.slice(0, sepIdx) : content;
|
|
6819
6710
|
const desc = sepIdx >= 0 ? content.slice(sepIdx + 3) : "";
|
|
6820
|
-
return /* @__PURE__ */
|
|
6711
|
+
return /* @__PURE__ */ jsxs196(
|
|
6821
6712
|
"div",
|
|
6822
6713
|
{
|
|
6823
6714
|
ref,
|
|
6824
6715
|
className: `lib-xplat-tooltip ${tooltipType} chart-tooltip-pos`,
|
|
6825
6716
|
style: { left: pos.left, top: pos.top },
|
|
6826
6717
|
children: [
|
|
6827
|
-
title && /* @__PURE__ */
|
|
6828
|
-
desc && /* @__PURE__ */
|
|
6718
|
+
title && /* @__PURE__ */ jsx305("div", { className: "tooltip-title", children: title }),
|
|
6719
|
+
desc && /* @__PURE__ */ jsx305("div", { className: "tooltip-desc", children: desc })
|
|
6829
6720
|
]
|
|
6830
6721
|
}
|
|
6831
6722
|
);
|
|
@@ -6837,14 +6728,14 @@ var ChartLegend = ({ data, labels, type }) => {
|
|
|
6837
6728
|
const total = values.reduce((a, b) => a + b, 0) || 1;
|
|
6838
6729
|
const firstKey = entries[0]?.[0] ?? "";
|
|
6839
6730
|
const colorOffset = hashString(firstKey);
|
|
6840
|
-
return /* @__PURE__ */
|
|
6731
|
+
return /* @__PURE__ */ jsx305("div", { className: "chart-legend", children: values.map((v, i) => {
|
|
6841
6732
|
const pct = Math.round(v / total * 100);
|
|
6842
6733
|
const color = PIE_COLORS[(i + colorOffset) % PIE_COLORS.length];
|
|
6843
|
-
return /* @__PURE__ */
|
|
6844
|
-
/* @__PURE__ */
|
|
6845
|
-
/* @__PURE__ */
|
|
6846
|
-
/* @__PURE__ */
|
|
6847
|
-
/* @__PURE__ */
|
|
6734
|
+
return /* @__PURE__ */ jsxs196("div", { className: "chart-legend-item", children: [
|
|
6735
|
+
/* @__PURE__ */ jsx305("span", { className: "chart-legend-dot", style: { backgroundColor: color } }),
|
|
6736
|
+
/* @__PURE__ */ jsxs196("div", { className: "chart-legend-text", children: [
|
|
6737
|
+
/* @__PURE__ */ jsx305("span", { className: "chart-legend-label", children: labels[i] || `${i + 1}` }),
|
|
6738
|
+
/* @__PURE__ */ jsxs196("span", { className: "chart-legend-value", children: [
|
|
6848
6739
|
v.toLocaleString(),
|
|
6849
6740
|
"(",
|
|
6850
6741
|
pct,
|
|
@@ -6854,42 +6745,151 @@ var ChartLegend = ({ data, labels, type }) => {
|
|
|
6854
6745
|
] }, i);
|
|
6855
6746
|
}) });
|
|
6856
6747
|
}
|
|
6857
|
-
return /* @__PURE__ */
|
|
6748
|
+
return /* @__PURE__ */ jsx305("div", { className: "chart-legend", children: entries.map(([key], di) => {
|
|
6858
6749
|
const palette = getPalette(LINE_BAR_PALETTES, di, key);
|
|
6859
6750
|
const color = palette[2];
|
|
6860
6751
|
const values = entries[di][1];
|
|
6861
6752
|
const sum = values.reduce((a, b) => a + b, 0);
|
|
6862
|
-
return /* @__PURE__ */
|
|
6863
|
-
/* @__PURE__ */
|
|
6864
|
-
/* @__PURE__ */
|
|
6865
|
-
/* @__PURE__ */
|
|
6866
|
-
/* @__PURE__ */
|
|
6753
|
+
return /* @__PURE__ */ jsxs196("div", { className: "chart-legend-item", children: [
|
|
6754
|
+
/* @__PURE__ */ jsx305("span", { className: "chart-legend-dot", style: { backgroundColor: color } }),
|
|
6755
|
+
/* @__PURE__ */ jsxs196("div", { className: "chart-legend-text", children: [
|
|
6756
|
+
/* @__PURE__ */ jsx305("span", { className: "chart-legend-label", children: key }),
|
|
6757
|
+
/* @__PURE__ */ jsx305("span", { className: "chart-legend-value", children: sum.toLocaleString() })
|
|
6867
6758
|
] })
|
|
6868
6759
|
] }, di);
|
|
6869
6760
|
}) });
|
|
6870
6761
|
};
|
|
6871
|
-
var Chart =
|
|
6762
|
+
var Chart = React5.memo((props) => {
|
|
6872
6763
|
const { type, data, labels, tooltip: showTooltip = true, tooltipType = "light" } = props;
|
|
6873
6764
|
const { tooltip, show, hide, move, containerRef } = useChartTooltip(showTooltip);
|
|
6874
6765
|
const { width, height } = useChartSize(containerRef);
|
|
6875
|
-
const stableData =
|
|
6876
|
-
const stableLabels =
|
|
6877
|
-
const dataKey =
|
|
6766
|
+
const stableData = React5.useMemo(() => data, [JSON.stringify(data)]);
|
|
6767
|
+
const stableLabels = React5.useMemo(() => labels, [JSON.stringify(labels)]);
|
|
6768
|
+
const dataKey = React5.useMemo(() => JSON.stringify(labels), [labels]);
|
|
6878
6769
|
const animate = useChartAnimation(containerRef, dataKey);
|
|
6879
6770
|
const ready = width > 0 && height > 0;
|
|
6880
|
-
return /* @__PURE__ */
|
|
6881
|
-
ready && type === "line" && /* @__PURE__ */
|
|
6882
|
-
ready && type === "curve" && /* @__PURE__ */
|
|
6883
|
-
ready && type === "bar" && /* @__PURE__ */
|
|
6884
|
-
ready && type === "pie" && /* @__PURE__ */
|
|
6885
|
-
ready && type === "doughnut" && /* @__PURE__ */
|
|
6886
|
-
ready && (type === "pie" || type === "doughnut") && /* @__PURE__ */
|
|
6887
|
-
tooltip.visible && tooltip.content && /* @__PURE__ */
|
|
6771
|
+
return /* @__PURE__ */ jsxs196("div", { className: "lib-xplat-chart", ref: containerRef, children: [
|
|
6772
|
+
ready && type === "line" && /* @__PURE__ */ jsx305(LineChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
|
|
6773
|
+
ready && type === "curve" && /* @__PURE__ */ jsx305(CurveChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
|
|
6774
|
+
ready && type === "bar" && /* @__PURE__ */ jsx305(BarChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
|
|
6775
|
+
ready && type === "pie" && /* @__PURE__ */ jsx305(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
|
|
6776
|
+
ready && type === "doughnut" && /* @__PURE__ */ jsx305(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, isDoughnut: true, onHover: show, onMove: move, onLeave: hide }),
|
|
6777
|
+
ready && (type === "pie" || type === "doughnut") && /* @__PURE__ */ jsx305(ChartLegend, { data: stableData, labels: stableLabels, type }),
|
|
6778
|
+
tooltip.visible && tooltip.content && /* @__PURE__ */ jsx305(ChartTooltip, { x: tooltip.x, y: tooltip.y, containerWidth: width, containerHeight: height, tooltipType, children: tooltip.content })
|
|
6888
6779
|
] });
|
|
6889
6780
|
});
|
|
6890
6781
|
Chart.displayName = "Chart";
|
|
6891
6782
|
var Chart_default = Chart;
|
|
6892
6783
|
|
|
6784
|
+
// src/components/ChatInput/ChatInput.tsx
|
|
6785
|
+
import React6 from "react";
|
|
6786
|
+
|
|
6787
|
+
// src/components/IconButton/IconButton.tsx
|
|
6788
|
+
import { jsx as jsx306 } from "react/jsx-runtime";
|
|
6789
|
+
var IconButton = (props) => {
|
|
6790
|
+
const {
|
|
6791
|
+
icon,
|
|
6792
|
+
type = "primary",
|
|
6793
|
+
size = "md",
|
|
6794
|
+
disabled,
|
|
6795
|
+
...rest
|
|
6796
|
+
} = props;
|
|
6797
|
+
return /* @__PURE__ */ jsx306(
|
|
6798
|
+
"button",
|
|
6799
|
+
{
|
|
6800
|
+
className: clsx_default("lib-xplat-icon-button", type, size),
|
|
6801
|
+
disabled,
|
|
6802
|
+
...rest,
|
|
6803
|
+
children: icon
|
|
6804
|
+
}
|
|
6805
|
+
);
|
|
6806
|
+
};
|
|
6807
|
+
IconButton.displayName = "IconButton";
|
|
6808
|
+
var IconButton_default = IconButton;
|
|
6809
|
+
|
|
6810
|
+
// src/components/ChatInput/ChatInput.tsx
|
|
6811
|
+
import { jsx as jsx307, jsxs as jsxs197 } from "react/jsx-runtime";
|
|
6812
|
+
var MAX_HEIGHT = 200;
|
|
6813
|
+
var ChatInput = React6.forwardRef(
|
|
6814
|
+
(props, ref) => {
|
|
6815
|
+
const {
|
|
6816
|
+
placeholder,
|
|
6817
|
+
value: valueProp,
|
|
6818
|
+
disabled = false,
|
|
6819
|
+
buttonType = "primary",
|
|
6820
|
+
onSubmit,
|
|
6821
|
+
onChange
|
|
6822
|
+
} = props;
|
|
6823
|
+
const isControlled = valueProp !== void 0;
|
|
6824
|
+
const [internalValue, setInternalValue] = React6.useState("");
|
|
6825
|
+
const value = isControlled ? valueProp : internalValue;
|
|
6826
|
+
const hasText = value.trim().length > 0;
|
|
6827
|
+
const textareaRef = React6.useRef(null);
|
|
6828
|
+
const setRefs = React6.useCallback(
|
|
6829
|
+
(el) => {
|
|
6830
|
+
textareaRef.current = el;
|
|
6831
|
+
if (typeof ref === "function") ref(el);
|
|
6832
|
+
else if (ref) ref.current = el;
|
|
6833
|
+
},
|
|
6834
|
+
[ref]
|
|
6835
|
+
);
|
|
6836
|
+
const updateHeight = React6.useCallback(() => {
|
|
6837
|
+
const el = textareaRef.current;
|
|
6838
|
+
if (!el) return;
|
|
6839
|
+
el.style.height = "0px";
|
|
6840
|
+
el.style.height = `${Math.min(el.scrollHeight, MAX_HEIGHT)}px`;
|
|
6841
|
+
}, []);
|
|
6842
|
+
const handleChange = (e) => {
|
|
6843
|
+
const val = e.target.value;
|
|
6844
|
+
if (!isControlled) setInternalValue(val);
|
|
6845
|
+
onChange?.(val);
|
|
6846
|
+
};
|
|
6847
|
+
const handleSubmit = () => {
|
|
6848
|
+
if (!hasText || disabled) return;
|
|
6849
|
+
onSubmit?.(value);
|
|
6850
|
+
if (!isControlled) setInternalValue("");
|
|
6851
|
+
requestAnimationFrame(updateHeight);
|
|
6852
|
+
};
|
|
6853
|
+
const handleKeyDown = (e) => {
|
|
6854
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
6855
|
+
e.preventDefault();
|
|
6856
|
+
handleSubmit();
|
|
6857
|
+
}
|
|
6858
|
+
};
|
|
6859
|
+
React6.useEffect(() => {
|
|
6860
|
+
updateHeight();
|
|
6861
|
+
}, [value, updateHeight]);
|
|
6862
|
+
return /* @__PURE__ */ jsxs197("div", { className: clsx_default("lib-xplat-chat-input", disabled && "disabled"), children: [
|
|
6863
|
+
/* @__PURE__ */ jsx307(
|
|
6864
|
+
"textarea",
|
|
6865
|
+
{
|
|
6866
|
+
ref: setRefs,
|
|
6867
|
+
className: "chat-input-textarea",
|
|
6868
|
+
placeholder,
|
|
6869
|
+
value,
|
|
6870
|
+
disabled,
|
|
6871
|
+
rows: 1,
|
|
6872
|
+
onChange: handleChange,
|
|
6873
|
+
onKeyDown: handleKeyDown
|
|
6874
|
+
}
|
|
6875
|
+
),
|
|
6876
|
+
/* @__PURE__ */ jsx307(
|
|
6877
|
+
IconButton_default,
|
|
6878
|
+
{
|
|
6879
|
+
icon: /* @__PURE__ */ jsx307(MessageSquareIcon_default, {}),
|
|
6880
|
+
type: buttonType,
|
|
6881
|
+
size: "sm",
|
|
6882
|
+
disabled: !hasText || disabled,
|
|
6883
|
+
onClick: handleSubmit,
|
|
6884
|
+
"aria-label": "\uC804\uC1A1"
|
|
6885
|
+
}
|
|
6886
|
+
)
|
|
6887
|
+
] });
|
|
6888
|
+
}
|
|
6889
|
+
);
|
|
6890
|
+
ChatInput.displayName = "ChatInput";
|
|
6891
|
+
var ChatInput_default = ChatInput;
|
|
6892
|
+
|
|
6893
6893
|
// src/tokens/breakpoints.ts
|
|
6894
6894
|
var BREAKPOINT_KEYS_ORDERED = ["laptop", "tablet", "mobile"];
|
|
6895
6895
|
var breakpoints = {
|