@x-plat/design-system 0.10.0 → 0.12.0
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/AutoResizeTextArea/index.cjs +14 -5
- package/dist/components/AutoResizeTextArea/index.css +15 -0
- package/dist/components/AutoResizeTextArea/index.d.cts +4 -0
- package/dist/components/AutoResizeTextArea/index.d.ts +4 -0
- package/dist/components/AutoResizeTextArea/index.js +14 -5
- package/dist/components/Badge/index.d.cts +1 -1
- package/dist/components/Badge/index.d.ts +1 -1
- package/dist/components/ChatInput/index.cjs +20 -7
- package/dist/components/ChatInput/index.css +15 -0
- package/dist/components/ChatInput/index.d.cts +4 -0
- package/dist/components/ChatInput/index.d.ts +4 -0
- package/dist/components/ChatInput/index.js +20 -7
- package/dist/components/CheckBox/index.cjs +8 -3
- package/dist/components/CheckBox/index.css +15 -0
- package/dist/components/CheckBox/index.d.cts +1 -1
- package/dist/components/CheckBox/index.d.ts +1 -1
- package/dist/components/CheckBox/index.js +8 -3
- package/dist/components/DatePicker/index.cjs +179 -64
- package/dist/components/DatePicker/index.css +19 -0
- package/dist/components/DatePicker/index.js +179 -64
- package/dist/components/Drawer/index.cjs +83 -4
- package/dist/components/Drawer/index.js +83 -4
- package/dist/components/Dropdown/index.cjs +57 -16
- package/dist/components/Dropdown/index.css +3 -0
- package/dist/components/Dropdown/index.js +57 -16
- package/dist/components/Editor/index.cjs +779 -50
- package/dist/components/Editor/index.css +100 -0
- package/dist/components/Editor/index.d.cts +1 -1
- package/dist/components/Editor/index.d.ts +1 -1
- package/dist/components/Editor/index.js +779 -50
- package/dist/components/FieldMessage/index.cjs +8 -3
- package/dist/components/FieldMessage/index.css +15 -0
- package/dist/components/FieldMessage/index.d.cts +11 -4
- package/dist/components/FieldMessage/index.d.ts +11 -4
- package/dist/components/FieldMessage/index.js +8 -3
- package/dist/components/FileUpload/index.cjs +8 -3
- package/dist/components/FileUpload/index.css +15 -0
- package/dist/components/FileUpload/index.js +8 -3
- package/dist/components/ImageSelector/index.cjs +8 -3
- package/dist/components/ImageSelector/index.css +15 -0
- package/dist/components/ImageSelector/index.js +8 -3
- package/dist/components/Input/index.cjs +15 -5
- package/dist/components/Input/index.css +15 -0
- package/dist/components/Input/index.d.cts +4 -0
- package/dist/components/Input/index.d.ts +4 -0
- package/dist/components/Input/index.js +15 -5
- package/dist/components/Modal/index.cjs +84 -5
- package/dist/components/Modal/index.js +84 -5
- package/dist/components/NotificationBadge/index.d.cts +1 -1
- package/dist/components/NotificationBadge/index.d.ts +1 -1
- package/dist/components/Pagination/index.d.cts +1 -1
- package/dist/components/Pagination/index.d.ts +1 -1
- package/dist/components/PopOver/index.cjs +55 -13
- package/dist/components/PopOver/index.css +3 -0
- package/dist/components/PopOver/index.js +55 -13
- package/dist/components/Progress/index.d.cts +1 -1
- package/dist/components/Progress/index.d.ts +1 -1
- package/dist/components/Radio/index.cjs +8 -3
- package/dist/components/Radio/index.css +15 -0
- package/dist/components/Radio/index.d.cts +1 -1
- package/dist/components/Radio/index.d.ts +1 -1
- package/dist/components/Radio/index.js +8 -3
- package/dist/components/Select/index.cjs +120 -39
- package/dist/components/Select/index.css +57 -0
- package/dist/components/Select/index.d.cts +11 -0
- package/dist/components/Select/index.d.ts +11 -0
- package/dist/components/Select/index.js +120 -39
- package/dist/components/Spinner/index.d.cts +1 -1
- package/dist/components/Spinner/index.d.ts +1 -1
- package/dist/components/Stat/index.cjs +84 -0
- package/dist/components/Stat/index.css +96 -0
- package/dist/components/Stat/index.d.cts +37 -0
- package/dist/components/Stat/index.d.ts +37 -0
- package/dist/components/Stat/index.js +57 -0
- package/dist/components/Steps/index.d.cts +1 -1
- package/dist/components/Steps/index.d.ts +1 -1
- package/dist/components/Switch/index.cjs +14 -5
- package/dist/components/Switch/index.css +15 -0
- package/dist/components/Switch/index.d.cts +6 -1
- package/dist/components/Switch/index.d.ts +6 -1
- package/dist/components/Switch/index.js +14 -5
- package/dist/components/Tab/index.cjs +49 -25
- package/dist/components/Tab/index.css +4 -0
- package/dist/components/Tab/index.js +49 -25
- package/dist/components/TextArea/index.cjs +14 -4
- package/dist/components/TextArea/index.css +15 -0
- package/dist/components/TextArea/index.d.cts +4 -0
- package/dist/components/TextArea/index.d.ts +4 -0
- package/dist/components/TextArea/index.js +14 -4
- package/dist/components/TimePicker/index.cjs +461 -0
- package/dist/components/TimePicker/index.css +175 -0
- package/dist/components/TimePicker/index.d.cts +42 -0
- package/dist/components/TimePicker/index.d.ts +42 -0
- package/dist/components/TimePicker/index.js +424 -0
- package/dist/components/index.cjs +1500 -398
- package/dist/components/index.css +385 -0
- package/dist/components/index.d.cts +3 -1
- package/dist/components/index.d.ts +3 -1
- package/dist/components/index.js +1498 -398
- package/dist/index.cjs +1524 -422
- package/dist/index.css +385 -0
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1522 -422
- package/dist/status-njWqQWFV.d.cts +20 -0
- package/dist/status-njWqQWFV.d.ts +20 -0
- package/guidelines/AGENT_PROMPT.md +3 -3
- package/guidelines/Guidelines.md +3 -0
- package/guidelines/components/editor.md +141 -0
- package/guidelines/components/form.md +19 -0
- package/guidelines/components/stat.md +31 -0
- package/guidelines/components/time-picker.md +49 -0
- package/package.json +1 -1
- package/dist/status-g_KP3qT6.d.cts +0 -8
- package/dist/status-g_KP3qT6.d.ts +0 -8
package/dist/components/index.js
CHANGED
|
@@ -1532,11 +1532,16 @@ var FieldMessage = (props) => {
|
|
|
1532
1532
|
FieldMessage.displayName = "FieldMessage";
|
|
1533
1533
|
var FieldMessage_default = FieldMessage;
|
|
1534
1534
|
var Field = (props) => {
|
|
1535
|
-
const { validations, children } = props;
|
|
1536
|
-
|
|
1535
|
+
const { label, required = false, htmlFor, validations, children } = props;
|
|
1536
|
+
const hasMessages = !!validations && validations.length > 0;
|
|
1537
|
+
if (!label && !hasMessages) return /* @__PURE__ */ jsx297(Fragment, { children });
|
|
1537
1538
|
return /* @__PURE__ */ jsxs191("div", { className: "lib-xplat-field", children: [
|
|
1539
|
+
label && /* @__PURE__ */ jsxs191("label", { className: "lib-xplat-field-label", htmlFor, children: [
|
|
1540
|
+
label,
|
|
1541
|
+
required && /* @__PURE__ */ jsx297("span", { className: "required", "aria-hidden": "true", children: "*" })
|
|
1542
|
+
] }),
|
|
1538
1543
|
children,
|
|
1539
|
-
/* @__PURE__ */ jsx297(FieldMessage, { validations })
|
|
1544
|
+
hasMessages && /* @__PURE__ */ jsx297(FieldMessage, { validations })
|
|
1540
1545
|
] });
|
|
1541
1546
|
};
|
|
1542
1547
|
Field.displayName = "Field";
|
|
@@ -1547,7 +1552,9 @@ import { jsx as jsx298 } from "react/jsx-runtime";
|
|
|
1547
1552
|
var MAX_HEIGHT = 400;
|
|
1548
1553
|
var AutoResizeTextArea = React2.forwardRef(
|
|
1549
1554
|
(props, ref) => {
|
|
1550
|
-
const { value, className, onChange, disabled, bare = false, validations, ...textareaProps } = props;
|
|
1555
|
+
const { value, className, onChange, disabled, bare = false, validations, label, required, ...textareaProps } = props;
|
|
1556
|
+
const autoId = React2.useId();
|
|
1557
|
+
const fieldId = props.id ?? autoId;
|
|
1551
1558
|
const localRef = React2.useRef(null);
|
|
1552
1559
|
const setRefs = (el) => {
|
|
1553
1560
|
localRef.current = el;
|
|
@@ -1581,6 +1588,7 @@ var AutoResizeTextArea = React2.forwardRef(
|
|
|
1581
1588
|
"aria-invalid": hasError(validations) || void 0,
|
|
1582
1589
|
...textareaProps,
|
|
1583
1590
|
ref: setRefs,
|
|
1591
|
+
id: fieldId,
|
|
1584
1592
|
className,
|
|
1585
1593
|
disabled,
|
|
1586
1594
|
value,
|
|
@@ -1594,12 +1602,13 @@ var AutoResizeTextArea = React2.forwardRef(
|
|
|
1594
1602
|
"aria-invalid": hasError(validations) || void 0,
|
|
1595
1603
|
...textareaProps,
|
|
1596
1604
|
ref: setRefs,
|
|
1605
|
+
id: fieldId,
|
|
1597
1606
|
disabled,
|
|
1598
1607
|
value,
|
|
1599
1608
|
onChange: handleChange
|
|
1600
1609
|
}
|
|
1601
1610
|
) }) });
|
|
1602
|
-
return /* @__PURE__ */ jsx298(Field, { validations, children: control });
|
|
1611
|
+
return /* @__PURE__ */ jsx298(Field, { validations, label, required, htmlFor: fieldId, children: control });
|
|
1603
1612
|
}
|
|
1604
1613
|
);
|
|
1605
1614
|
AutoResizeTextArea.displayName = "AutoResizeTextArea";
|
|
@@ -2817,8 +2826,11 @@ var ChatInput = React7.forwardRef(
|
|
|
2817
2826
|
buttonType = "primary",
|
|
2818
2827
|
onSubmit,
|
|
2819
2828
|
onChange,
|
|
2820
|
-
validations
|
|
2829
|
+
validations,
|
|
2830
|
+
label,
|
|
2831
|
+
required
|
|
2821
2832
|
} = props;
|
|
2833
|
+
const fieldId = React7.useId();
|
|
2822
2834
|
const isControlled = valueProp !== void 0;
|
|
2823
2835
|
const [internalValue, setInternalValue] = React7.useState("");
|
|
2824
2836
|
const value = isControlled ? valueProp : internalValue;
|
|
@@ -2843,6 +2855,7 @@ var ChatInput = React7.forwardRef(
|
|
|
2843
2855
|
/* @__PURE__ */ jsx308(
|
|
2844
2856
|
AutoResizeTextArea_default,
|
|
2845
2857
|
{
|
|
2858
|
+
id: fieldId,
|
|
2846
2859
|
ref,
|
|
2847
2860
|
bare: true,
|
|
2848
2861
|
className: "chat-input-textarea",
|
|
@@ -2867,7 +2880,7 @@ var ChatInput = React7.forwardRef(
|
|
|
2867
2880
|
}
|
|
2868
2881
|
)
|
|
2869
2882
|
] });
|
|
2870
|
-
return /* @__PURE__ */ jsx308(Field, { validations, children: control });
|
|
2883
|
+
return /* @__PURE__ */ jsx308(Field, { validations, label, required, htmlFor: fieldId, children: control });
|
|
2871
2884
|
}
|
|
2872
2885
|
);
|
|
2873
2886
|
ChatInput.displayName = "ChatInput";
|
|
@@ -2938,7 +2951,7 @@ Chip.displayName = "Chip";
|
|
|
2938
2951
|
var Chip_default = Chip;
|
|
2939
2952
|
|
|
2940
2953
|
// src/components/DatePicker/InputDatePicker/index.tsx
|
|
2941
|
-
import
|
|
2954
|
+
import React13 from "react";
|
|
2942
2955
|
|
|
2943
2956
|
// src/components/Input/Input.tsx
|
|
2944
2957
|
import React8 from "react";
|
|
@@ -3036,8 +3049,12 @@ var Input = React8.forwardRef((props, ref) => {
|
|
|
3036
3049
|
suffix,
|
|
3037
3050
|
disabled,
|
|
3038
3051
|
validations,
|
|
3052
|
+
label,
|
|
3053
|
+
required,
|
|
3039
3054
|
...inputProps
|
|
3040
3055
|
} = props;
|
|
3056
|
+
const autoId = React8.useId();
|
|
3057
|
+
const fieldId = inputProps.id ?? autoId;
|
|
3041
3058
|
const localValue = formatValue(type, value);
|
|
3042
3059
|
const handleChange = (e) => {
|
|
3043
3060
|
let val = e.target.value;
|
|
@@ -3053,7 +3070,7 @@ var Input = React8.forwardRef((props, ref) => {
|
|
|
3053
3070
|
onChange(event);
|
|
3054
3071
|
}
|
|
3055
3072
|
};
|
|
3056
|
-
return /* @__PURE__ */ jsxs199("div", { className: clsx_default("lib-xplat-input-wrap", className), children: [
|
|
3073
|
+
return /* @__PURE__ */ jsx311(Field, { label, required, htmlFor: fieldId, children: /* @__PURE__ */ jsxs199("div", { className: clsx_default("lib-xplat-input-wrap", className), children: [
|
|
3057
3074
|
/* @__PURE__ */ jsxs199(
|
|
3058
3075
|
"div",
|
|
3059
3076
|
{
|
|
@@ -3064,6 +3081,7 @@ var Input = React8.forwardRef((props, ref) => {
|
|
|
3064
3081
|
{
|
|
3065
3082
|
...inputProps,
|
|
3066
3083
|
ref,
|
|
3084
|
+
id: fieldId,
|
|
3067
3085
|
disabled,
|
|
3068
3086
|
type: type === "number" ? "text" : type,
|
|
3069
3087
|
value: localValue,
|
|
@@ -3076,7 +3094,7 @@ var Input = React8.forwardRef((props, ref) => {
|
|
|
3076
3094
|
}
|
|
3077
3095
|
),
|
|
3078
3096
|
/* @__PURE__ */ jsx311(FieldMessage_default, { validations })
|
|
3079
|
-
] });
|
|
3097
|
+
] }) });
|
|
3080
3098
|
});
|
|
3081
3099
|
Input.displayName = "Input";
|
|
3082
3100
|
var Input_default = Input;
|
|
@@ -3106,16 +3124,96 @@ PasswordInput.displayName = "PasswordInput";
|
|
|
3106
3124
|
var PasswordInput_default = PasswordInput;
|
|
3107
3125
|
|
|
3108
3126
|
// src/components/Modal/Modal.tsx
|
|
3109
|
-
import
|
|
3127
|
+
import React11 from "react";
|
|
3110
3128
|
import { createPortal } from "react-dom";
|
|
3129
|
+
|
|
3130
|
+
// src/tokens/hooks/useOverlayKeyboard.ts
|
|
3131
|
+
import React10 from "react";
|
|
3132
|
+
var FOCUSABLE = [
|
|
3133
|
+
"a[href]",
|
|
3134
|
+
"button:not([disabled])",
|
|
3135
|
+
"input:not([disabled]):not([type='hidden'])",
|
|
3136
|
+
"select:not([disabled])",
|
|
3137
|
+
"textarea:not([disabled])",
|
|
3138
|
+
"[tabindex]:not([tabindex='-1'])"
|
|
3139
|
+
].join(",");
|
|
3140
|
+
var focusableIn = (el) => Array.from(el.querySelectorAll(FOCUSABLE)).filter(
|
|
3141
|
+
// 화면에 없는 것은 제외 (display:none 등)
|
|
3142
|
+
(n) => n.offsetWidth > 0 || n.offsetHeight > 0 || n === document.activeElement
|
|
3143
|
+
);
|
|
3144
|
+
var useEscapeKey = (enabled, onEscape) => {
|
|
3145
|
+
React10.useEffect(() => {
|
|
3146
|
+
if (!enabled) return;
|
|
3147
|
+
const onKey = (e) => {
|
|
3148
|
+
if (e.key !== "Escape") return;
|
|
3149
|
+
if (e.defaultPrevented) return;
|
|
3150
|
+
e.preventDefault();
|
|
3151
|
+
onEscape();
|
|
3152
|
+
};
|
|
3153
|
+
document.addEventListener("keydown", onKey);
|
|
3154
|
+
return () => document.removeEventListener("keydown", onKey);
|
|
3155
|
+
}, [enabled, onEscape]);
|
|
3156
|
+
};
|
|
3157
|
+
var useFocusTrap = (containerRef, enabled, options = {}) => {
|
|
3158
|
+
const { trap = false, initialFocus } = options;
|
|
3159
|
+
const restoreRef = React10.useRef(null);
|
|
3160
|
+
React10.useEffect(() => {
|
|
3161
|
+
if (!enabled) return;
|
|
3162
|
+
restoreRef.current = document.activeElement;
|
|
3163
|
+
const raf = requestAnimationFrame(() => {
|
|
3164
|
+
const el = containerRef.current;
|
|
3165
|
+
if (!el) return;
|
|
3166
|
+
const target = initialFocus?.current ?? focusableIn(el)[0] ?? el;
|
|
3167
|
+
if (!target.hasAttribute("tabindex") && !focusableIn(el).includes(target)) {
|
|
3168
|
+
target.setAttribute("tabindex", "-1");
|
|
3169
|
+
}
|
|
3170
|
+
target.focus({ preventScroll: true });
|
|
3171
|
+
});
|
|
3172
|
+
return () => {
|
|
3173
|
+
cancelAnimationFrame(raf);
|
|
3174
|
+
const prev = restoreRef.current;
|
|
3175
|
+
if (prev && document.contains(prev)) prev.focus({ preventScroll: true });
|
|
3176
|
+
};
|
|
3177
|
+
}, [enabled, containerRef, initialFocus]);
|
|
3178
|
+
React10.useEffect(() => {
|
|
3179
|
+
if (!enabled || !trap) return;
|
|
3180
|
+
const onKey = (e) => {
|
|
3181
|
+
if (e.key !== "Tab") return;
|
|
3182
|
+
const el = containerRef.current;
|
|
3183
|
+
if (!el) return;
|
|
3184
|
+
const items = focusableIn(el);
|
|
3185
|
+
if (items.length === 0) {
|
|
3186
|
+
e.preventDefault();
|
|
3187
|
+
return;
|
|
3188
|
+
}
|
|
3189
|
+
const first = items[0];
|
|
3190
|
+
const last = items[items.length - 1];
|
|
3191
|
+
const active = document.activeElement;
|
|
3192
|
+
if (e.shiftKey && (active === first || !el.contains(active))) {
|
|
3193
|
+
e.preventDefault();
|
|
3194
|
+
last.focus();
|
|
3195
|
+
} else if (!e.shiftKey && (active === last || !el.contains(active))) {
|
|
3196
|
+
e.preventDefault();
|
|
3197
|
+
first.focus();
|
|
3198
|
+
}
|
|
3199
|
+
};
|
|
3200
|
+
document.addEventListener("keydown", onKey);
|
|
3201
|
+
return () => document.removeEventListener("keydown", onKey);
|
|
3202
|
+
}, [enabled, trap, containerRef]);
|
|
3203
|
+
};
|
|
3204
|
+
|
|
3205
|
+
// src/components/Modal/Modal.tsx
|
|
3111
3206
|
import { jsx as jsx313 } from "react/jsx-runtime";
|
|
3112
3207
|
var ANIMATION_DURATION_MS = 200;
|
|
3113
3208
|
var Modal = (props) => {
|
|
3114
3209
|
const { isOpen, onClose, children } = props;
|
|
3115
|
-
const [mounted, setMounted] =
|
|
3116
|
-
const [visible, setVisible] =
|
|
3117
|
-
const [settled, setSettled] =
|
|
3118
|
-
|
|
3210
|
+
const [mounted, setMounted] = React11.useState(false);
|
|
3211
|
+
const [visible, setVisible] = React11.useState(false);
|
|
3212
|
+
const [settled, setSettled] = React11.useState(false);
|
|
3213
|
+
const boxRef = React11.useRef(null);
|
|
3214
|
+
useEscapeKey(isOpen, onClose);
|
|
3215
|
+
useFocusTrap(boxRef, isOpen && mounted, { trap: true });
|
|
3216
|
+
React11.useEffect(() => {
|
|
3119
3217
|
if (isOpen) {
|
|
3120
3218
|
setMounted(true);
|
|
3121
3219
|
const show = setTimeout(() => setVisible(true), 1);
|
|
@@ -3142,6 +3240,7 @@ var Modal = (props) => {
|
|
|
3142
3240
|
children: /* @__PURE__ */ jsx313(
|
|
3143
3241
|
"div",
|
|
3144
3242
|
{
|
|
3243
|
+
ref: boxRef,
|
|
3145
3244
|
className: clsx_default("lib-xplat-modal", "modal-box", stateClass, settled && "settled"),
|
|
3146
3245
|
role: "dialog",
|
|
3147
3246
|
"aria-modal": "true",
|
|
@@ -3158,9 +3257,9 @@ Modal.displayName = "Modal";
|
|
|
3158
3257
|
var Modal_default = Modal;
|
|
3159
3258
|
|
|
3160
3259
|
// src/components/DatePicker/SingleDatePicker/index.tsx
|
|
3161
|
-
import
|
|
3260
|
+
import React12 from "react";
|
|
3162
3261
|
import { Fragment as Fragment4, jsx as jsx314, jsxs as jsxs200 } from "react/jsx-runtime";
|
|
3163
|
-
var DayCell2 =
|
|
3262
|
+
var DayCell2 = React12.memo(
|
|
3164
3263
|
({
|
|
3165
3264
|
day,
|
|
3166
3265
|
disabled,
|
|
@@ -3212,26 +3311,26 @@ var SingleDatePicker = (props) => {
|
|
|
3212
3311
|
initialYear,
|
|
3213
3312
|
initialMonth
|
|
3214
3313
|
);
|
|
3215
|
-
const [pickerMode, setPickerMode] =
|
|
3216
|
-
const [yearRangeStart, setYearRangeStart] =
|
|
3314
|
+
const [pickerMode, setPickerMode] = React12.useState("days");
|
|
3315
|
+
const [yearRangeStart, setYearRangeStart] = React12.useState(
|
|
3217
3316
|
Math.floor((initialYear ?? (/* @__PURE__ */ new Date()).getFullYear()) / 12) * 12
|
|
3218
3317
|
);
|
|
3219
|
-
const minTime =
|
|
3318
|
+
const minTime = React12.useMemo(
|
|
3220
3319
|
() => minDate ? new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate()).getTime() : -Infinity,
|
|
3221
3320
|
[minDate]
|
|
3222
3321
|
);
|
|
3223
|
-
const maxTime =
|
|
3322
|
+
const maxTime = React12.useMemo(
|
|
3224
3323
|
() => maxDate ? new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate()).getTime() : Infinity,
|
|
3225
3324
|
[maxDate]
|
|
3226
3325
|
);
|
|
3227
|
-
const highlightSet =
|
|
3326
|
+
const highlightSet = React12.useMemo(() => {
|
|
3228
3327
|
const set = /* @__PURE__ */ new Set();
|
|
3229
3328
|
for (const h of highlightDates) {
|
|
3230
3329
|
set.add(`${h.getFullYear()}-${h.getMonth()}-${h.getDate()}`);
|
|
3231
3330
|
}
|
|
3232
3331
|
return set;
|
|
3233
3332
|
}, [highlightDates]);
|
|
3234
|
-
const handleSelect =
|
|
3333
|
+
const handleSelect = React12.useCallback(
|
|
3235
3334
|
(date) => {
|
|
3236
3335
|
onChange?.(date);
|
|
3237
3336
|
},
|
|
@@ -3360,8 +3459,8 @@ var formatDate = (date) => {
|
|
|
3360
3459
|
};
|
|
3361
3460
|
var InputDatePicker = (props) => {
|
|
3362
3461
|
const { value, onChange, minDate, maxDate, disabled, locale = "ko", placeholder } = props;
|
|
3363
|
-
const [isOpen, setIsOpen] =
|
|
3364
|
-
const [tempDate, setTempDate] =
|
|
3462
|
+
const [isOpen, setIsOpen] = React13.useState(false);
|
|
3463
|
+
const [tempDate, setTempDate] = React13.useState(value ?? /* @__PURE__ */ new Date());
|
|
3365
3464
|
const handleOpen = () => {
|
|
3366
3465
|
if (disabled) return;
|
|
3367
3466
|
setTempDate(value ?? /* @__PURE__ */ new Date());
|
|
@@ -3410,23 +3509,27 @@ InputDatePicker.displayName = "InputDatePicker";
|
|
|
3410
3509
|
var InputDatePicker_default = InputDatePicker;
|
|
3411
3510
|
|
|
3412
3511
|
// src/components/DatePicker/PopupPicker/index.tsx
|
|
3413
|
-
import
|
|
3512
|
+
import React17 from "react";
|
|
3414
3513
|
|
|
3415
3514
|
// src/components/DatePicker/RangePicker/index.tsx
|
|
3416
|
-
import
|
|
3515
|
+
import React16 from "react";
|
|
3417
3516
|
|
|
3418
3517
|
// src/components/Tab/Tab.tsx
|
|
3419
|
-
import
|
|
3518
|
+
import React15 from "react";
|
|
3420
3519
|
|
|
3421
3520
|
// src/components/Tab/TabItem.tsx
|
|
3422
|
-
import
|
|
3521
|
+
import React14 from "react";
|
|
3423
3522
|
import { jsx as jsx316 } from "react/jsx-runtime";
|
|
3424
|
-
var TabItem =
|
|
3523
|
+
var TabItem = React14.forwardRef((props, ref) => {
|
|
3425
3524
|
const { isActive: isActive2, title, onClick } = props;
|
|
3426
3525
|
return /* @__PURE__ */ jsx316(
|
|
3427
|
-
"
|
|
3526
|
+
"button",
|
|
3428
3527
|
{
|
|
3429
3528
|
ref,
|
|
3529
|
+
type: "button",
|
|
3530
|
+
role: "tab",
|
|
3531
|
+
"aria-selected": isActive2,
|
|
3532
|
+
tabIndex: isActive2 ? 0 : -1,
|
|
3430
3533
|
className: clsx_default("tab-item", isActive2 ? "active" : null),
|
|
3431
3534
|
onClick,
|
|
3432
3535
|
children: title
|
|
@@ -3441,44 +3544,64 @@ import { jsx as jsx317, jsxs as jsxs202 } from "react/jsx-runtime";
|
|
|
3441
3544
|
var Tab = (props) => {
|
|
3442
3545
|
const { activeIndex, onChange, tabs, variant, type, size = "md" } = props;
|
|
3443
3546
|
const shape = variant ?? type ?? "default";
|
|
3444
|
-
const [underlineStyle, setUnderlineStyle] =
|
|
3547
|
+
const [underlineStyle, setUnderlineStyle] = React15.useState({
|
|
3445
3548
|
left: 0,
|
|
3446
3549
|
width: 0
|
|
3447
3550
|
});
|
|
3448
|
-
const itemRefs =
|
|
3551
|
+
const itemRefs = React15.useRef([]);
|
|
3552
|
+
const handleKeyDown = (e) => {
|
|
3553
|
+
const last = tabs.length - 1;
|
|
3554
|
+
let next = null;
|
|
3555
|
+
if (e.key === "ArrowRight") next = activeIndex >= last ? 0 : activeIndex + 1;
|
|
3556
|
+
else if (e.key === "ArrowLeft") next = activeIndex <= 0 ? last : activeIndex - 1;
|
|
3557
|
+
else if (e.key === "Home") next = 0;
|
|
3558
|
+
else if (e.key === "End") next = last;
|
|
3559
|
+
if (next === null) return;
|
|
3560
|
+
e.preventDefault();
|
|
3561
|
+
onChange(tabs[next], next);
|
|
3562
|
+
itemRefs.current[next]?.focus();
|
|
3563
|
+
};
|
|
3449
3564
|
const handleChangeActiveTab = (tabItem, tabIdx) => {
|
|
3450
3565
|
onChange(tabItem, tabIdx);
|
|
3451
3566
|
};
|
|
3452
|
-
|
|
3567
|
+
React15.useEffect(() => {
|
|
3453
3568
|
const el = itemRefs.current[activeIndex];
|
|
3454
3569
|
if (el) {
|
|
3455
3570
|
setUnderlineStyle({ left: el.offsetLeft, width: el.offsetWidth });
|
|
3456
3571
|
}
|
|
3457
3572
|
}, [activeIndex, tabs.length]);
|
|
3458
|
-
return /* @__PURE__ */ jsxs202(
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
{
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3573
|
+
return /* @__PURE__ */ jsxs202(
|
|
3574
|
+
"div",
|
|
3575
|
+
{
|
|
3576
|
+
className: clsx_default("lib-xplat-tab", `type-${shape}`, size),
|
|
3577
|
+
role: "tablist",
|
|
3578
|
+
onKeyDown: handleKeyDown,
|
|
3579
|
+
children: [
|
|
3580
|
+
tabs.map((tab, idx) => /* @__PURE__ */ jsx317(
|
|
3581
|
+
TabItem_default,
|
|
3582
|
+
{
|
|
3583
|
+
onClick: () => handleChangeActiveTab(tab, idx),
|
|
3584
|
+
isActive: activeIndex === idx,
|
|
3585
|
+
ref: (el) => {
|
|
3586
|
+
itemRefs.current[idx] = el;
|
|
3587
|
+
},
|
|
3588
|
+
title: tab.title
|
|
3589
|
+
},
|
|
3590
|
+
`${tab.value}_${idx}`
|
|
3591
|
+
)),
|
|
3592
|
+
shape === "toggle" && /* @__PURE__ */ jsx317(
|
|
3593
|
+
"div",
|
|
3594
|
+
{
|
|
3595
|
+
className: "tab-toggle-underline",
|
|
3596
|
+
style: {
|
|
3597
|
+
left: underlineStyle.left,
|
|
3598
|
+
width: underlineStyle.width
|
|
3599
|
+
}
|
|
3600
|
+
}
|
|
3601
|
+
)
|
|
3602
|
+
]
|
|
3603
|
+
}
|
|
3604
|
+
);
|
|
3482
3605
|
};
|
|
3483
3606
|
Tab.displayName = "Tab";
|
|
3484
3607
|
var Tab_default = Tab;
|
|
@@ -3494,7 +3617,7 @@ var RangePicker = (props) => {
|
|
|
3494
3617
|
maxDate,
|
|
3495
3618
|
locale = "ko"
|
|
3496
3619
|
} = props;
|
|
3497
|
-
const [activeTab, setActiveTab] =
|
|
3620
|
+
const [activeTab, setActiveTab] = React16.useState("start");
|
|
3498
3621
|
const handleStartChange = (date) => {
|
|
3499
3622
|
if (!date) return;
|
|
3500
3623
|
const newStart = date > endDate ? endDate : date;
|
|
@@ -3579,7 +3702,7 @@ var RangePicker_default = RangePicker;
|
|
|
3579
3702
|
import { jsx as jsx319, jsxs as jsxs204 } from "react/jsx-runtime";
|
|
3580
3703
|
var PopupPicker = (props) => {
|
|
3581
3704
|
const { component, type, locale } = props;
|
|
3582
|
-
const [isOpen, setIsOpen] =
|
|
3705
|
+
const [isOpen, setIsOpen] = React17.useState(false);
|
|
3583
3706
|
const handleClick = () => setIsOpen(true);
|
|
3584
3707
|
const handleClose = () => setIsOpen(false);
|
|
3585
3708
|
const handleSingleChange = (date) => {
|
|
@@ -3588,7 +3711,7 @@ var PopupPicker = (props) => {
|
|
|
3588
3711
|
handleClose();
|
|
3589
3712
|
};
|
|
3590
3713
|
return /* @__PURE__ */ jsxs204("div", { className: "lib-xplat-popup-datepicker", children: [
|
|
3591
|
-
|
|
3714
|
+
React17.cloneElement(component, { onClick: handleClick }),
|
|
3592
3715
|
/* @__PURE__ */ jsx319(Modal_default, { isOpen, onClose: handleClose, children: /* @__PURE__ */ jsxs204("div", { className: clsx_default("lib-xplat-popup-datepicker-card", type === "range" && "range-mode"), children: [
|
|
3593
3716
|
/* @__PURE__ */ jsxs204("div", { className: "popup-datepicker-content", children: [
|
|
3594
3717
|
type === "single" && /* @__PURE__ */ jsx319(
|
|
@@ -3647,15 +3770,18 @@ Divider.displayName = "Divider";
|
|
|
3647
3770
|
var Divider_default = Divider;
|
|
3648
3771
|
|
|
3649
3772
|
// src/components/Drawer/Drawer.tsx
|
|
3650
|
-
import
|
|
3773
|
+
import React18 from "react";
|
|
3651
3774
|
import { createPortal as createPortal2 } from "react-dom";
|
|
3652
3775
|
import { jsx as jsx321, jsxs as jsxs205 } from "react/jsx-runtime";
|
|
3653
3776
|
var ANIMATION_DURATION_MS2 = 250;
|
|
3654
3777
|
var Drawer = (props) => {
|
|
3655
3778
|
const { isOpen, onClose, placement = "right", size = "md", title, children } = props;
|
|
3656
|
-
const [mounted, setMounted] =
|
|
3657
|
-
const [visible, setVisible] =
|
|
3658
|
-
|
|
3779
|
+
const [mounted, setMounted] = React18.useState(false);
|
|
3780
|
+
const [visible, setVisible] = React18.useState(false);
|
|
3781
|
+
const panelRef = React18.useRef(null);
|
|
3782
|
+
useEscapeKey(isOpen, onClose);
|
|
3783
|
+
useFocusTrap(panelRef, isOpen && mounted, { trap: true });
|
|
3784
|
+
React18.useEffect(() => {
|
|
3659
3785
|
if (isOpen) {
|
|
3660
3786
|
setMounted(true);
|
|
3661
3787
|
const t2 = setTimeout(() => setVisible(true), 1);
|
|
@@ -3677,6 +3803,7 @@ var Drawer = (props) => {
|
|
|
3677
3803
|
children: /* @__PURE__ */ jsxs205(
|
|
3678
3804
|
"div",
|
|
3679
3805
|
{
|
|
3806
|
+
ref: panelRef,
|
|
3680
3807
|
className: clsx_default("lib-xplat-drawer", placement, size, stateClass),
|
|
3681
3808
|
role: "dialog",
|
|
3682
3809
|
"aria-modal": "true",
|
|
@@ -3699,7 +3826,7 @@ Drawer.displayName = "Drawer";
|
|
|
3699
3826
|
var Drawer_default = Drawer;
|
|
3700
3827
|
|
|
3701
3828
|
// src/components/Dropdown/Dropdown.tsx
|
|
3702
|
-
import
|
|
3829
|
+
import React21 from "react";
|
|
3703
3830
|
|
|
3704
3831
|
// src/tokens/hooks/Portal.tsx
|
|
3705
3832
|
import ReactDOM from "react-dom";
|
|
@@ -3711,13 +3838,15 @@ Portal.displayName = "Portal";
|
|
|
3711
3838
|
var Portal_default = Portal;
|
|
3712
3839
|
|
|
3713
3840
|
// src/tokens/hooks/useAutoPosition.ts
|
|
3714
|
-
import
|
|
3841
|
+
import React19 from "react";
|
|
3715
3842
|
var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
3716
|
-
const [position, setPosition] =
|
|
3843
|
+
const [position, setPosition] = React19.useState({
|
|
3717
3844
|
position: {},
|
|
3718
|
-
direction: "bottom"
|
|
3845
|
+
direction: "bottom",
|
|
3846
|
+
repositioning: false
|
|
3719
3847
|
});
|
|
3720
|
-
const
|
|
3848
|
+
const placedRef = React19.useRef(false);
|
|
3849
|
+
const calculatePosition = React19.useCallback(() => {
|
|
3721
3850
|
if (!triggerRef.current || !popRef.current) return;
|
|
3722
3851
|
const triggerRect = triggerRef.current.getBoundingClientRect();
|
|
3723
3852
|
const popW = popRef.current.offsetWidth;
|
|
@@ -3741,16 +3870,21 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
3741
3870
|
if (left < 8) left = 8;
|
|
3742
3871
|
setPosition({
|
|
3743
3872
|
position: { top, left },
|
|
3744
|
-
direction
|
|
3873
|
+
direction,
|
|
3874
|
+
repositioning: placedRef.current
|
|
3745
3875
|
});
|
|
3876
|
+
placedRef.current = true;
|
|
3746
3877
|
}, [triggerRef, popRef]);
|
|
3747
|
-
|
|
3748
|
-
if (!enabled)
|
|
3878
|
+
React19.useLayoutEffect(() => {
|
|
3879
|
+
if (!enabled) {
|
|
3880
|
+
placedRef.current = false;
|
|
3881
|
+
return;
|
|
3882
|
+
}
|
|
3749
3883
|
calculatePosition();
|
|
3750
3884
|
const raf = requestAnimationFrame(calculatePosition);
|
|
3751
3885
|
return () => cancelAnimationFrame(raf);
|
|
3752
3886
|
}, [calculatePosition, enabled]);
|
|
3753
|
-
|
|
3887
|
+
React19.useEffect(() => {
|
|
3754
3888
|
if (!enabled || !popRef.current) return;
|
|
3755
3889
|
const observer = new ResizeObserver(() => {
|
|
3756
3890
|
calculatePosition();
|
|
@@ -3758,13 +3892,19 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
3758
3892
|
observer.observe(popRef.current);
|
|
3759
3893
|
return () => observer.disconnect();
|
|
3760
3894
|
}, [calculatePosition, enabled, popRef]);
|
|
3761
|
-
|
|
3895
|
+
React19.useEffect(() => {
|
|
3762
3896
|
if (!enabled) return;
|
|
3763
|
-
|
|
3764
|
-
|
|
3897
|
+
let raf = 0;
|
|
3898
|
+
const onScrollOrResize = () => {
|
|
3899
|
+
cancelAnimationFrame(raf);
|
|
3900
|
+
raf = requestAnimationFrame(calculatePosition);
|
|
3901
|
+
};
|
|
3902
|
+
window.addEventListener("resize", onScrollOrResize, { passive: true });
|
|
3903
|
+
window.addEventListener("scroll", onScrollOrResize, { passive: true, capture: true });
|
|
3765
3904
|
return () => {
|
|
3766
|
-
|
|
3767
|
-
window.removeEventListener("
|
|
3905
|
+
cancelAnimationFrame(raf);
|
|
3906
|
+
window.removeEventListener("resize", onScrollOrResize);
|
|
3907
|
+
window.removeEventListener("scroll", onScrollOrResize, true);
|
|
3768
3908
|
};
|
|
3769
3909
|
}, [calculatePosition, enabled]);
|
|
3770
3910
|
return position;
|
|
@@ -3772,9 +3912,9 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
3772
3912
|
var useAutoPosition_default = useAutoPosition;
|
|
3773
3913
|
|
|
3774
3914
|
// src/tokens/hooks/useClickOutside.ts
|
|
3775
|
-
import
|
|
3915
|
+
import React20 from "react";
|
|
3776
3916
|
var useClickOutside = (refs, handler, enabled = true) => {
|
|
3777
|
-
|
|
3917
|
+
React20.useEffect(() => {
|
|
3778
3918
|
if (!enabled) return;
|
|
3779
3919
|
const refArray = Array.isArray(refs) ? refs : [refs];
|
|
3780
3920
|
const listener = (event) => {
|
|
@@ -3800,14 +3940,18 @@ var useClickOutside_default = useClickOutside;
|
|
|
3800
3940
|
import { jsx as jsx322, jsxs as jsxs206 } from "react/jsx-runtime";
|
|
3801
3941
|
var Dropdown = (props) => {
|
|
3802
3942
|
const { items, children } = props;
|
|
3803
|
-
const [isOpen, setIsOpen] =
|
|
3804
|
-
const [mounted, setMounted] =
|
|
3805
|
-
const [visible, setVisible] =
|
|
3806
|
-
const triggerRef =
|
|
3807
|
-
const menuRef =
|
|
3808
|
-
const { position, direction } = useAutoPosition_default(triggerRef, menuRef, mounted);
|
|
3943
|
+
const [isOpen, setIsOpen] = React21.useState(false);
|
|
3944
|
+
const [mounted, setMounted] = React21.useState(false);
|
|
3945
|
+
const [visible, setVisible] = React21.useState(false);
|
|
3946
|
+
const triggerRef = React21.useRef(null);
|
|
3947
|
+
const menuRef = React21.useRef(null);
|
|
3948
|
+
const { position, direction, repositioning } = useAutoPosition_default(triggerRef, menuRef, mounted);
|
|
3809
3949
|
useClickOutside_default([triggerRef, menuRef], () => setIsOpen(false), isOpen);
|
|
3810
|
-
|
|
3950
|
+
useEscapeKey(isOpen, () => {
|
|
3951
|
+
setIsOpen(false);
|
|
3952
|
+
triggerRef.current?.focus({ preventScroll: true });
|
|
3953
|
+
});
|
|
3954
|
+
React21.useEffect(() => {
|
|
3811
3955
|
if (isOpen) {
|
|
3812
3956
|
setMounted(true);
|
|
3813
3957
|
const t2 = setTimeout(() => setVisible(true), 1);
|
|
@@ -3836,7 +3980,7 @@ var Dropdown = (props) => {
|
|
|
3836
3980
|
"div",
|
|
3837
3981
|
{
|
|
3838
3982
|
ref: menuRef,
|
|
3839
|
-
className: clsx_default("lib-xplat-dropdown-menu", direction, { visible }),
|
|
3983
|
+
className: clsx_default("lib-xplat-dropdown-menu", direction, { visible }, repositioning && "repositioning"),
|
|
3840
3984
|
style: { top: position.top, left: position.left },
|
|
3841
3985
|
role: "menu",
|
|
3842
3986
|
children: items.map((item) => /* @__PURE__ */ jsx322(
|
|
@@ -3861,7 +4005,112 @@ Dropdown.displayName = "Dropdown";
|
|
|
3861
4005
|
var Dropdown_default = Dropdown;
|
|
3862
4006
|
|
|
3863
4007
|
// src/components/Editor/Editor.tsx
|
|
3864
|
-
import
|
|
4008
|
+
import React22 from "react";
|
|
4009
|
+
|
|
4010
|
+
// src/components/Editor/highlight.ts
|
|
4011
|
+
var CODE_LANGUAGES = [
|
|
4012
|
+
{ value: "plain", label: "\uC5C6\uC74C" },
|
|
4013
|
+
{ value: "javascript", label: "JavaScript" },
|
|
4014
|
+
{ value: "typescript", label: "TypeScript" },
|
|
4015
|
+
{ value: "json", label: "JSON" },
|
|
4016
|
+
{ value: "html", label: "HTML" },
|
|
4017
|
+
{ value: "css", label: "CSS" },
|
|
4018
|
+
{ value: "python", label: "Python" },
|
|
4019
|
+
{ value: "sql", label: "SQL" },
|
|
4020
|
+
{ value: "bash", label: "Bash" }
|
|
4021
|
+
];
|
|
4022
|
+
var KEYWORDS = {
|
|
4023
|
+
plain: [],
|
|
4024
|
+
javascript: "const let var function return if else for while class new this import export from default async await try catch throw typeof instanceof null undefined true false break continue switch case do delete in of yield".split(" "),
|
|
4025
|
+
typescript: "const let var function return if else for while class new this import export from default async await try catch throw typeof instanceof null undefined true false break continue switch case do delete in of yield interface type enum implements extends public private protected readonly as satisfies keyof infer never unknown any".split(" "),
|
|
4026
|
+
json: ["true", "false", "null"],
|
|
4027
|
+
html: [],
|
|
4028
|
+
css: [],
|
|
4029
|
+
python: "def class return if elif else for while import from as try except finally raise with lambda None True False and or not in is pass break continue global nonlocal yield async await".split(" "),
|
|
4030
|
+
sql: "SELECT FROM WHERE INSERT INTO VALUES UPDATE SET DELETE CREATE TABLE ALTER DROP JOIN LEFT RIGHT INNER OUTER ON GROUP BY ORDER HAVING LIMIT OFFSET AS AND OR NOT NULL DISTINCT UNION INDEX PRIMARY KEY FOREIGN REFERENCES DEFAULT".split(" "),
|
|
4031
|
+
bash: "if then else fi for while do done case esac function return export local echo cd ls rm cp mv mkdir sudo source set unset exit".split(" ")
|
|
4032
|
+
};
|
|
4033
|
+
var LINE_COMMENT = {
|
|
4034
|
+
javascript: "//",
|
|
4035
|
+
typescript: "//",
|
|
4036
|
+
css: "",
|
|
4037
|
+
python: "#",
|
|
4038
|
+
sql: "--",
|
|
4039
|
+
bash: "#"
|
|
4040
|
+
};
|
|
4041
|
+
var escape = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
4042
|
+
var wrap = (cls, text) => `<span class="tok-${cls}">${escape(text)}</span>`;
|
|
4043
|
+
var highlight = (code, lang) => {
|
|
4044
|
+
if (lang === "plain" || !code) return escape(code);
|
|
4045
|
+
const keywords = new Set(KEYWORDS[lang]);
|
|
4046
|
+
const lineComment = LINE_COMMENT[lang];
|
|
4047
|
+
const caseInsensitive = lang === "sql";
|
|
4048
|
+
let out = "";
|
|
4049
|
+
let i = 0;
|
|
4050
|
+
while (i < code.length) {
|
|
4051
|
+
const rest = code.slice(i);
|
|
4052
|
+
if ((lang === "javascript" || lang === "typescript" || lang === "css") && rest.startsWith("/*")) {
|
|
4053
|
+
const end = code.indexOf("*/", i + 2);
|
|
4054
|
+
const stop = end === -1 ? code.length : end + 2;
|
|
4055
|
+
out += wrap("comment", code.slice(i, stop));
|
|
4056
|
+
i = stop;
|
|
4057
|
+
continue;
|
|
4058
|
+
}
|
|
4059
|
+
if (lineComment && rest.startsWith(lineComment)) {
|
|
4060
|
+
const nl = code.indexOf("\n", i);
|
|
4061
|
+
const stop = nl === -1 ? code.length : nl;
|
|
4062
|
+
out += wrap("comment", code.slice(i, stop));
|
|
4063
|
+
i = stop;
|
|
4064
|
+
continue;
|
|
4065
|
+
}
|
|
4066
|
+
const q = rest[0];
|
|
4067
|
+
if (q === '"' || q === "'" || q === "`") {
|
|
4068
|
+
let j = 1;
|
|
4069
|
+
while (j < rest.length) {
|
|
4070
|
+
if (rest[j] === "\\") {
|
|
4071
|
+
j += 2;
|
|
4072
|
+
continue;
|
|
4073
|
+
}
|
|
4074
|
+
if (rest[j] === q) {
|
|
4075
|
+
j += 1;
|
|
4076
|
+
break;
|
|
4077
|
+
}
|
|
4078
|
+
if (rest[j] === "\n" && q !== "`") break;
|
|
4079
|
+
j += 1;
|
|
4080
|
+
}
|
|
4081
|
+
out += wrap("string", rest.slice(0, j));
|
|
4082
|
+
i += j;
|
|
4083
|
+
continue;
|
|
4084
|
+
}
|
|
4085
|
+
const num = /^\d+(\.\d+)?/.exec(rest);
|
|
4086
|
+
if (num && !/[\w$]/.test(code[i - 1] ?? "")) {
|
|
4087
|
+
out += wrap("number", num[0]);
|
|
4088
|
+
i += num[0].length;
|
|
4089
|
+
continue;
|
|
4090
|
+
}
|
|
4091
|
+
const word = /^[A-Za-z_$][\w$]*/.exec(rest);
|
|
4092
|
+
if (word) {
|
|
4093
|
+
const w = word[0];
|
|
4094
|
+
const hit = caseInsensitive ? keywords.has(w.toUpperCase()) : keywords.has(w);
|
|
4095
|
+
out += hit ? wrap("keyword", w) : escape(w);
|
|
4096
|
+
i += w.length;
|
|
4097
|
+
continue;
|
|
4098
|
+
}
|
|
4099
|
+
if (lang === "html" && rest.startsWith("<")) {
|
|
4100
|
+
const tag = /^<\/?[A-Za-z][\w-]*/.exec(rest);
|
|
4101
|
+
if (tag) {
|
|
4102
|
+
out += wrap("keyword", tag[0]);
|
|
4103
|
+
i += tag[0].length;
|
|
4104
|
+
continue;
|
|
4105
|
+
}
|
|
4106
|
+
}
|
|
4107
|
+
out += escape(code[i]);
|
|
4108
|
+
i += 1;
|
|
4109
|
+
}
|
|
4110
|
+
return out;
|
|
4111
|
+
};
|
|
4112
|
+
|
|
4113
|
+
// src/components/Editor/Editor.tsx
|
|
3865
4114
|
import { jsx as jsx323, jsxs as jsxs207 } from "react/jsx-runtime";
|
|
3866
4115
|
var DEFAULT_TOOLBAR = [
|
|
3867
4116
|
"bold",
|
|
@@ -3869,14 +4118,27 @@ var DEFAULT_TOOLBAR = [
|
|
|
3869
4118
|
"underline",
|
|
3870
4119
|
"strikethrough",
|
|
3871
4120
|
"code",
|
|
3872
|
-
"heading",
|
|
4121
|
+
"heading-1",
|
|
4122
|
+
"heading-2",
|
|
4123
|
+
"heading-3",
|
|
3873
4124
|
"list",
|
|
3874
4125
|
"ordered-list",
|
|
3875
4126
|
"blockquote",
|
|
3876
4127
|
"code-block",
|
|
3877
4128
|
"link",
|
|
3878
4129
|
"image",
|
|
3879
|
-
"divider"
|
|
4130
|
+
"divider",
|
|
4131
|
+
"checklist",
|
|
4132
|
+
"table",
|
|
4133
|
+
"align-left",
|
|
4134
|
+
"align-center",
|
|
4135
|
+
"align-right",
|
|
4136
|
+
"highlight",
|
|
4137
|
+
"superscript",
|
|
4138
|
+
"subscript",
|
|
4139
|
+
"clear-format",
|
|
4140
|
+
"undo",
|
|
4141
|
+
"redo"
|
|
3880
4142
|
];
|
|
3881
4143
|
var ALLOWED_TAGS = /* @__PURE__ */ new Set([
|
|
3882
4144
|
"p",
|
|
@@ -3905,12 +4167,51 @@ var ALLOWED_TAGS = /* @__PURE__ */ new Set([
|
|
|
3905
4167
|
"img",
|
|
3906
4168
|
"hr",
|
|
3907
4169
|
"span",
|
|
3908
|
-
"div"
|
|
4170
|
+
"div",
|
|
4171
|
+
"sub",
|
|
4172
|
+
"sup",
|
|
4173
|
+
"mark",
|
|
4174
|
+
"table",
|
|
4175
|
+
"thead",
|
|
4176
|
+
"tbody",
|
|
4177
|
+
"tr",
|
|
4178
|
+
"th",
|
|
4179
|
+
"td"
|
|
3909
4180
|
]);
|
|
3910
4181
|
var ALLOWED_ATTRS = {
|
|
3911
4182
|
a: ["href", "target", "rel"],
|
|
3912
|
-
img: ["src", "alt"]
|
|
4183
|
+
img: ["src", "alt", "width"],
|
|
4184
|
+
// 정렬·체크리스트는 클래스로만 표현한다. style 을 열면 붙여넣기로 아무 CSS 나 들어온다
|
|
4185
|
+
p: ["class"],
|
|
4186
|
+
h1: ["class"],
|
|
4187
|
+
h2: ["class"],
|
|
4188
|
+
h3: ["class"],
|
|
4189
|
+
h4: ["class"],
|
|
4190
|
+
h5: ["class"],
|
|
4191
|
+
h6: ["class"],
|
|
4192
|
+
ul: ["class"],
|
|
4193
|
+
ol: ["class"],
|
|
4194
|
+
li: ["class", "data-checked"],
|
|
4195
|
+
blockquote: ["class"],
|
|
4196
|
+
div: ["class"],
|
|
4197
|
+
span: ["class"],
|
|
4198
|
+
pre: ["class"],
|
|
4199
|
+
code: ["class"],
|
|
4200
|
+
mark: ["class"],
|
|
4201
|
+
table: ["class"],
|
|
4202
|
+
td: ["class"],
|
|
4203
|
+
th: ["class"],
|
|
4204
|
+
tr: ["class"]
|
|
3913
4205
|
};
|
|
4206
|
+
var DROP_WITH_CONTENT = /* @__PURE__ */ new Set([
|
|
4207
|
+
"script",
|
|
4208
|
+
"style",
|
|
4209
|
+
"noscript",
|
|
4210
|
+
"iframe",
|
|
4211
|
+
"object",
|
|
4212
|
+
"embed",
|
|
4213
|
+
"template"
|
|
4214
|
+
]);
|
|
3914
4215
|
var sanitizeHtml = (input) => {
|
|
3915
4216
|
const doc = new DOMParser().parseFromString(`<div>${input}</div>`, "text/html");
|
|
3916
4217
|
const root = doc.body.firstElementChild;
|
|
@@ -3919,6 +4220,10 @@ var sanitizeHtml = (input) => {
|
|
|
3919
4220
|
const children = Array.from(node.children);
|
|
3920
4221
|
for (const child of children) {
|
|
3921
4222
|
const tag = child.tagName.toLowerCase();
|
|
4223
|
+
if (DROP_WITH_CONTENT.has(tag)) {
|
|
4224
|
+
node.removeChild(child);
|
|
4225
|
+
continue;
|
|
4226
|
+
}
|
|
3922
4227
|
if (!ALLOWED_TAGS.has(tag)) {
|
|
3923
4228
|
while (child.firstChild) node.insertBefore(child.firstChild, child);
|
|
3924
4229
|
node.removeChild(child);
|
|
@@ -3949,7 +4254,9 @@ var escapeHtml = (text) => {
|
|
|
3949
4254
|
};
|
|
3950
4255
|
var SLASH_ITEMS = [
|
|
3951
4256
|
{ key: "paragraph", label: "\uB2E8\uB77D", hint: "\uAE30\uBCF8 \uD14D\uC2A4\uD2B8" },
|
|
3952
|
-
{ key: "heading", label: "\uC81C\uBAA9 1", hint: "\uD070 \uC81C\uBAA9" },
|
|
4257
|
+
{ key: "heading-1", label: "\uC81C\uBAA9 1", hint: "\uAC00\uC7A5 \uD070 \uC81C\uBAA9" },
|
|
4258
|
+
{ key: "heading-2", label: "\uC81C\uBAA9 2", hint: "" },
|
|
4259
|
+
{ key: "heading-3", label: "\uC81C\uBAA9 3", hint: "" },
|
|
3953
4260
|
{ key: "list", label: "\uAE00\uBA38\uB9AC \uAE30\uD638 \uBAA9\uB85D", hint: "\u2022 \uD56D\uBAA9" },
|
|
3954
4261
|
{ key: "ordered-list", label: "\uBC88\uD638 \uB9E4\uAE30\uAE30 \uBAA9\uB85D", hint: "1. \uD56D\uBAA9" },
|
|
3955
4262
|
{ key: "blockquote", label: "\uC778\uC6A9", hint: "" },
|
|
@@ -3969,26 +4276,32 @@ var Editor = (props) => {
|
|
|
3969
4276
|
onImageUpload,
|
|
3970
4277
|
minHeight = 200
|
|
3971
4278
|
} = props;
|
|
3972
|
-
const editorRef =
|
|
3973
|
-
const lastRangeRef =
|
|
3974
|
-
const composingRef =
|
|
3975
|
-
const [isFocused, setIsFocused] =
|
|
3976
|
-
const [isEmpty, setIsEmpty] =
|
|
3977
|
-
const [activeFormats, setActiveFormats] =
|
|
3978
|
-
const [slashOpen, setSlashOpen] =
|
|
3979
|
-
const [slashFilter, setSlashFilter] =
|
|
3980
|
-
const [slashIdx, setSlashIdx] =
|
|
3981
|
-
const [slashPos, setSlashPos] =
|
|
3982
|
-
const slashStartRangeRef =
|
|
3983
|
-
const [linkOpen, setLinkOpen] =
|
|
3984
|
-
const [linkValue, setLinkValue] =
|
|
3985
|
-
const [linkPos, setLinkPos] =
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
4279
|
+
const editorRef = React22.useRef(null);
|
|
4280
|
+
const lastRangeRef = React22.useRef(null);
|
|
4281
|
+
const composingRef = React22.useRef(false);
|
|
4282
|
+
const [isFocused, setIsFocused] = React22.useState(false);
|
|
4283
|
+
const [isEmpty, setIsEmpty] = React22.useState(!value);
|
|
4284
|
+
const [activeFormats, setActiveFormats] = React22.useState(/* @__PURE__ */ new Set());
|
|
4285
|
+
const [slashOpen, setSlashOpen] = React22.useState(false);
|
|
4286
|
+
const [slashFilter, setSlashFilter] = React22.useState("");
|
|
4287
|
+
const [slashIdx, setSlashIdx] = React22.useState(0);
|
|
4288
|
+
const [slashPos, setSlashPos] = React22.useState({ top: 0, left: 0 });
|
|
4289
|
+
const slashStartRangeRef = React22.useRef(null);
|
|
4290
|
+
const [linkOpen, setLinkOpen] = React22.useState(false);
|
|
4291
|
+
const [linkValue, setLinkValue] = React22.useState("");
|
|
4292
|
+
const [linkPos, setLinkPos] = React22.useState({ top: 0, left: 0 });
|
|
4293
|
+
const lastEmittedRef = React22.useRef(null);
|
|
4294
|
+
React22.useEffect(() => {
|
|
4295
|
+
const el = editorRef.current;
|
|
4296
|
+
if (!el) return;
|
|
4297
|
+
if (value === lastEmittedRef.current) return;
|
|
4298
|
+
if (el.innerHTML === value) return;
|
|
4299
|
+
el.innerHTML = sanitizeHtml(value || "");
|
|
4300
|
+
if (!el.firstChild) el.innerHTML = "<p><br></p>";
|
|
4301
|
+
lastEmittedRef.current = null;
|
|
4302
|
+
historyRef.current = [{ html: el.innerHTML, caret: 0 }];
|
|
4303
|
+
historyIdxRef.current = 0;
|
|
4304
|
+
updateEmpty();
|
|
3992
4305
|
}, [value]);
|
|
3993
4306
|
const updateEmpty = () => {
|
|
3994
4307
|
const el = editorRef.current;
|
|
@@ -4004,10 +4317,19 @@ var Editor = (props) => {
|
|
|
4004
4317
|
}
|
|
4005
4318
|
};
|
|
4006
4319
|
const restoreSelection = () => {
|
|
4007
|
-
|
|
4320
|
+
const range = lastRangeRef.current;
|
|
4321
|
+
if (!range) return;
|
|
4322
|
+
if (!editorRef.current?.contains(range.startContainer)) {
|
|
4323
|
+
lastRangeRef.current = null;
|
|
4324
|
+
return;
|
|
4325
|
+
}
|
|
4008
4326
|
const sel = window.getSelection();
|
|
4009
|
-
|
|
4010
|
-
|
|
4327
|
+
try {
|
|
4328
|
+
sel?.removeAllRanges();
|
|
4329
|
+
sel?.addRange(range);
|
|
4330
|
+
} catch {
|
|
4331
|
+
lastRangeRef.current = null;
|
|
4332
|
+
}
|
|
4011
4333
|
};
|
|
4012
4334
|
const updateActiveFormats = () => {
|
|
4013
4335
|
if (!editorRef.current) return;
|
|
@@ -4023,6 +4345,17 @@ var Editor = (props) => {
|
|
|
4023
4345
|
if (document.queryCommandState("insertOrderedList")) next.add("ordered-list");
|
|
4024
4346
|
const block = String(document.queryCommandValue("formatBlock") || "").toLowerCase();
|
|
4025
4347
|
if (block) next.add(`block:${block}`);
|
|
4348
|
+
if (document.queryCommandState("superscript")) next.add("superscript");
|
|
4349
|
+
if (document.queryCommandState("subscript")) next.add("subscript");
|
|
4350
|
+
} catch {
|
|
4351
|
+
}
|
|
4352
|
+
try {
|
|
4353
|
+
const blockEl = currentBlock();
|
|
4354
|
+
if (blockEl?.classList.contains("align-center")) next.add("align:center");
|
|
4355
|
+
else if (blockEl?.classList.contains("align-right")) next.add("align:right");
|
|
4356
|
+
else if (blockEl) next.add("align:left");
|
|
4357
|
+
if (blockEl?.closest("mark")) next.add("highlight");
|
|
4358
|
+
if (blockEl?.closest("ul.checklist")) next.add("checklist");
|
|
4026
4359
|
} catch {
|
|
4027
4360
|
}
|
|
4028
4361
|
setActiveFormats(next);
|
|
@@ -4036,7 +4369,374 @@ var Editor = (props) => {
|
|
|
4036
4369
|
const setBlock = (tag) => {
|
|
4037
4370
|
exec("formatBlock", tag);
|
|
4038
4371
|
};
|
|
4372
|
+
const toggleBlock = (tag) => {
|
|
4373
|
+
const current = String(document.queryCommandValue("formatBlock") || "").toLowerCase();
|
|
4374
|
+
setBlock(current === tag ? "p" : tag);
|
|
4375
|
+
};
|
|
4376
|
+
const historyRef = React22.useRef([]);
|
|
4377
|
+
const historyIdxRef = React22.useRef(-1);
|
|
4378
|
+
const lastPushAtRef = React22.useRef(0);
|
|
4379
|
+
const isRestoringRef = React22.useRef(false);
|
|
4380
|
+
const caretOffset = (rootEl) => {
|
|
4381
|
+
const el = rootEl ?? editorRef.current;
|
|
4382
|
+
const sel = window.getSelection();
|
|
4383
|
+
if (!el || !sel || sel.rangeCount === 0 || !el.contains(sel.anchorNode)) return 0;
|
|
4384
|
+
const range = sel.getRangeAt(0).cloneRange();
|
|
4385
|
+
range.selectNodeContents(el);
|
|
4386
|
+
range.setEnd(sel.getRangeAt(0).endContainer, sel.getRangeAt(0).endOffset);
|
|
4387
|
+
return range.toString().length;
|
|
4388
|
+
};
|
|
4389
|
+
const setCaretOffset = (offset, rootEl) => {
|
|
4390
|
+
const el = rootEl ?? editorRef.current;
|
|
4391
|
+
if (!el) return;
|
|
4392
|
+
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
|
|
4393
|
+
let remaining = offset;
|
|
4394
|
+
let node = null;
|
|
4395
|
+
while (node = walker.nextNode()) {
|
|
4396
|
+
const len = node.textContent?.length ?? 0;
|
|
4397
|
+
if (remaining <= len) {
|
|
4398
|
+
const range = document.createRange();
|
|
4399
|
+
range.setStart(node, remaining);
|
|
4400
|
+
range.collapse(true);
|
|
4401
|
+
const sel = window.getSelection();
|
|
4402
|
+
sel?.removeAllRanges();
|
|
4403
|
+
sel?.addRange(range);
|
|
4404
|
+
return;
|
|
4405
|
+
}
|
|
4406
|
+
remaining -= len;
|
|
4407
|
+
}
|
|
4408
|
+
placeCaretAtEnd(el);
|
|
4409
|
+
};
|
|
4410
|
+
const pushHistory = (force = false) => {
|
|
4411
|
+
const el = editorRef.current;
|
|
4412
|
+
if (!el || isRestoringRef.current) return;
|
|
4413
|
+
const html = el.innerHTML;
|
|
4414
|
+
const hist = historyRef.current;
|
|
4415
|
+
const cur = hist[historyIdxRef.current];
|
|
4416
|
+
if (cur && cur.html === html) return;
|
|
4417
|
+
const now = Date.now();
|
|
4418
|
+
const coalesce = !force && cur && now - lastPushAtRef.current < 500;
|
|
4419
|
+
lastPushAtRef.current = now;
|
|
4420
|
+
if (coalesce) {
|
|
4421
|
+
hist[historyIdxRef.current] = { html, caret: caretOffset() };
|
|
4422
|
+
return;
|
|
4423
|
+
}
|
|
4424
|
+
hist.length = historyIdxRef.current + 1;
|
|
4425
|
+
hist.push({ html, caret: caretOffset() });
|
|
4426
|
+
if (hist.length > 200) hist.shift();
|
|
4427
|
+
historyIdxRef.current = hist.length - 1;
|
|
4428
|
+
};
|
|
4429
|
+
const applySnapshot = (snap) => {
|
|
4430
|
+
const el = editorRef.current;
|
|
4431
|
+
if (!el) return;
|
|
4432
|
+
isRestoringRef.current = true;
|
|
4433
|
+
el.innerHTML = snap.html;
|
|
4434
|
+
setCaretOffset(snap.caret);
|
|
4435
|
+
isRestoringRef.current = false;
|
|
4436
|
+
lastEmittedRef.current = el.innerHTML;
|
|
4437
|
+
onChange?.(el.innerHTML);
|
|
4438
|
+
updateEmpty();
|
|
4439
|
+
updateActiveFormats();
|
|
4440
|
+
};
|
|
4441
|
+
const undo = () => {
|
|
4442
|
+
pushHistory(true);
|
|
4443
|
+
if (historyIdxRef.current <= 0) return;
|
|
4444
|
+
historyIdxRef.current -= 1;
|
|
4445
|
+
applySnapshot(historyRef.current[historyIdxRef.current]);
|
|
4446
|
+
};
|
|
4447
|
+
const redo = () => {
|
|
4448
|
+
if (historyIdxRef.current >= historyRef.current.length - 1) return;
|
|
4449
|
+
historyIdxRef.current += 1;
|
|
4450
|
+
applySnapshot(historyRef.current[historyIdxRef.current]);
|
|
4451
|
+
};
|
|
4452
|
+
const langOf = (pre) => {
|
|
4453
|
+
const cls = Array.from(pre.classList).find((c) => c.startsWith("lang-"));
|
|
4454
|
+
return cls?.slice(5) ?? "plain";
|
|
4455
|
+
};
|
|
4456
|
+
const [codeLang, setCodeLang] = React22.useState("plain");
|
|
4457
|
+
const highlightRafRef = React22.useRef(0);
|
|
4458
|
+
const rehighlight = (pre) => {
|
|
4459
|
+
if (composingRef.current) return;
|
|
4460
|
+
const code = pre.querySelector("code");
|
|
4461
|
+
if (!code) return;
|
|
4462
|
+
const lang = langOf(pre);
|
|
4463
|
+
const text = code.textContent || "";
|
|
4464
|
+
const next = highlight(text, lang);
|
|
4465
|
+
if (code.innerHTML === next) return;
|
|
4466
|
+
const caret = caretOffset(code);
|
|
4467
|
+
isRestoringRef.current = true;
|
|
4468
|
+
code.innerHTML = next;
|
|
4469
|
+
setCaretOffset(caret, code);
|
|
4470
|
+
isRestoringRef.current = false;
|
|
4471
|
+
};
|
|
4472
|
+
const scheduleHighlight = () => {
|
|
4473
|
+
const pre = closestPre();
|
|
4474
|
+
if (!pre) return;
|
|
4475
|
+
cancelAnimationFrame(highlightRafRef.current);
|
|
4476
|
+
highlightRafRef.current = requestAnimationFrame(() => rehighlight(pre));
|
|
4477
|
+
};
|
|
4478
|
+
const changeCodeLang = (lang) => {
|
|
4479
|
+
const pre = closestPre();
|
|
4480
|
+
if (!pre) return;
|
|
4481
|
+
pushHistory(true);
|
|
4482
|
+
Array.from(pre.classList).filter((c) => c.startsWith("lang-")).forEach((c) => pre.classList.remove(c));
|
|
4483
|
+
if (lang !== "plain") pre.classList.add(`lang-${lang}`);
|
|
4484
|
+
setCodeLang(lang);
|
|
4485
|
+
rehighlight(pre);
|
|
4486
|
+
handleInput();
|
|
4487
|
+
};
|
|
4488
|
+
const closestPre = () => {
|
|
4489
|
+
const sel = window.getSelection();
|
|
4490
|
+
const node = sel?.anchorNode;
|
|
4491
|
+
if (!node || !editorRef.current?.contains(node)) return null;
|
|
4492
|
+
const el = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
|
|
4493
|
+
return el?.closest("pre") ?? null;
|
|
4494
|
+
};
|
|
4495
|
+
const insertCodeBlock = () => {
|
|
4496
|
+
pushHistory(true);
|
|
4497
|
+
const el = editorRef.current;
|
|
4498
|
+
const sel = window.getSelection();
|
|
4499
|
+
if (!el || !sel || sel.rangeCount === 0) return;
|
|
4500
|
+
const existing = closestPre();
|
|
4501
|
+
if (existing) {
|
|
4502
|
+
const p = document.createElement("p");
|
|
4503
|
+
p.textContent = existing.textContent || "";
|
|
4504
|
+
if (!p.textContent) p.innerHTML = "<br>";
|
|
4505
|
+
existing.replaceWith(p);
|
|
4506
|
+
placeCaretAtEnd(p);
|
|
4507
|
+
handleInput();
|
|
4508
|
+
return;
|
|
4509
|
+
}
|
|
4510
|
+
const range = sel.getRangeAt(0);
|
|
4511
|
+
const frag = range.cloneContents();
|
|
4512
|
+
const holder = document.createElement("div");
|
|
4513
|
+
holder.appendChild(frag);
|
|
4514
|
+
const BLOCK = /^(p|div|h[1-6]|li|blockquote|pre|tr)$/i;
|
|
4515
|
+
const linesOf = (node) => {
|
|
4516
|
+
const out = [];
|
|
4517
|
+
let cur = "";
|
|
4518
|
+
for (const child of Array.from(node.childNodes)) {
|
|
4519
|
+
if (child.nodeType === Node.TEXT_NODE) {
|
|
4520
|
+
cur += child.textContent || "";
|
|
4521
|
+
} else if (child.nodeName === "BR") {
|
|
4522
|
+
out.push(cur);
|
|
4523
|
+
cur = "";
|
|
4524
|
+
} else if (BLOCK.test(child.nodeName)) {
|
|
4525
|
+
if (cur) {
|
|
4526
|
+
out.push(cur);
|
|
4527
|
+
cur = "";
|
|
4528
|
+
}
|
|
4529
|
+
const sub = linesOf(child);
|
|
4530
|
+
out.push(...sub.length > 0 ? sub : [""]);
|
|
4531
|
+
} else {
|
|
4532
|
+
cur += linesOf(child).join("\n");
|
|
4533
|
+
}
|
|
4534
|
+
}
|
|
4535
|
+
if (cur) out.push(cur);
|
|
4536
|
+
return out;
|
|
4537
|
+
};
|
|
4538
|
+
const text = linesOf(holder).join("\n").replace(/\n+$/, "");
|
|
4539
|
+
const pre = document.createElement("pre");
|
|
4540
|
+
const code = document.createElement("code");
|
|
4541
|
+
code.textContent = text || "";
|
|
4542
|
+
pre.appendChild(code);
|
|
4543
|
+
range.deleteContents();
|
|
4544
|
+
range.insertNode(pre);
|
|
4545
|
+
ensureParagraphAfter(pre);
|
|
4546
|
+
placeCaretAtEnd(code);
|
|
4547
|
+
handleInput();
|
|
4548
|
+
};
|
|
4549
|
+
const insertTextAtCaret = (text) => {
|
|
4550
|
+
const sel = window.getSelection();
|
|
4551
|
+
if (!sel || sel.rangeCount === 0) return;
|
|
4552
|
+
const range = sel.getRangeAt(0);
|
|
4553
|
+
range.deleteContents();
|
|
4554
|
+
const node = document.createTextNode(text);
|
|
4555
|
+
range.insertNode(node);
|
|
4556
|
+
range.setStartAfter(node);
|
|
4557
|
+
range.collapse(true);
|
|
4558
|
+
sel.removeAllRanges();
|
|
4559
|
+
sel.addRange(range);
|
|
4560
|
+
handleInput();
|
|
4561
|
+
};
|
|
4562
|
+
const ensureParagraphAfter = (node) => {
|
|
4563
|
+
const next = node.nextElementSibling;
|
|
4564
|
+
if (next && next.tagName === "P") return;
|
|
4565
|
+
const p = document.createElement("p");
|
|
4566
|
+
p.innerHTML = "<br>";
|
|
4567
|
+
node.after(p);
|
|
4568
|
+
};
|
|
4569
|
+
const placeCaretAtEnd = (node) => {
|
|
4570
|
+
const sel = window.getSelection();
|
|
4571
|
+
if (!sel) return;
|
|
4572
|
+
const r2 = document.createRange();
|
|
4573
|
+
r2.selectNodeContents(node);
|
|
4574
|
+
r2.collapse(false);
|
|
4575
|
+
sel.removeAllRanges();
|
|
4576
|
+
sel.addRange(r2);
|
|
4577
|
+
editorRef.current?.focus();
|
|
4578
|
+
};
|
|
4579
|
+
const clearFormat = () => {
|
|
4580
|
+
exec("removeFormat");
|
|
4581
|
+
exec("unlink");
|
|
4582
|
+
setBlock("p");
|
|
4583
|
+
};
|
|
4584
|
+
const indentList = (outdent) => {
|
|
4585
|
+
exec(outdent ? "outdent" : "indent");
|
|
4586
|
+
};
|
|
4587
|
+
const inListItem = () => {
|
|
4588
|
+
const sel = window.getSelection();
|
|
4589
|
+
const node = sel?.anchorNode;
|
|
4590
|
+
if (!node || !editorRef.current?.contains(node)) return false;
|
|
4591
|
+
const el = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
|
|
4592
|
+
return !!el?.closest("li");
|
|
4593
|
+
};
|
|
4594
|
+
const currentBlock = () => {
|
|
4595
|
+
const sel = window.getSelection();
|
|
4596
|
+
const node = sel?.anchorNode;
|
|
4597
|
+
const root = editorRef.current;
|
|
4598
|
+
if (!node || !root?.contains(node)) return null;
|
|
4599
|
+
let el = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
|
|
4600
|
+
while (el && el !== root && !/^(P|H[1-6]|LI|BLOCKQUOTE|PRE|DIV|TD|TH)$/.test(el.tagName)) {
|
|
4601
|
+
el = el.parentElement;
|
|
4602
|
+
}
|
|
4603
|
+
return el && el !== root ? el : null;
|
|
4604
|
+
};
|
|
4605
|
+
const setAlign = (align) => {
|
|
4606
|
+
const block = currentBlock();
|
|
4607
|
+
if (!block) return;
|
|
4608
|
+
pushHistory(true);
|
|
4609
|
+
block.classList.remove("align-left", "align-center", "align-right");
|
|
4610
|
+
if (align !== "left") block.classList.add(`align-${align}`);
|
|
4611
|
+
handleInput();
|
|
4612
|
+
};
|
|
4613
|
+
const toggleChecklist = () => {
|
|
4614
|
+
pushHistory(true);
|
|
4615
|
+
const block = currentBlock();
|
|
4616
|
+
const list = block?.closest("ul");
|
|
4617
|
+
if (list?.classList.contains("checklist")) {
|
|
4618
|
+
list.classList.remove("checklist");
|
|
4619
|
+
list.querySelectorAll("li").forEach((li) => li.removeAttribute("data-checked"));
|
|
4620
|
+
handleInput();
|
|
4621
|
+
return;
|
|
4622
|
+
}
|
|
4623
|
+
if (list) {
|
|
4624
|
+
list.classList.add("checklist");
|
|
4625
|
+
list.querySelectorAll("li").forEach((li) => li.setAttribute("data-checked", "false"));
|
|
4626
|
+
handleInput();
|
|
4627
|
+
return;
|
|
4628
|
+
}
|
|
4629
|
+
exec("insertUnorderedList");
|
|
4630
|
+
const made = currentBlock()?.closest("ul");
|
|
4631
|
+
if (made) {
|
|
4632
|
+
made.classList.add("checklist");
|
|
4633
|
+
made.querySelectorAll("li").forEach((li) => li.setAttribute("data-checked", "false"));
|
|
4634
|
+
}
|
|
4635
|
+
handleInput();
|
|
4636
|
+
};
|
|
4637
|
+
const handleEditorClick = (e) => {
|
|
4638
|
+
if (readOnly) return;
|
|
4639
|
+
const target = e.target;
|
|
4640
|
+
const li = target.closest?.("li");
|
|
4641
|
+
if (!li || !li.closest("ul.checklist")) return;
|
|
4642
|
+
const rect = li.getBoundingClientRect();
|
|
4643
|
+
if (e.clientX - rect.left > 20) return;
|
|
4644
|
+
e.preventDefault();
|
|
4645
|
+
pushHistory(true);
|
|
4646
|
+
li.setAttribute("data-checked", li.getAttribute("data-checked") === "true" ? "false" : "true");
|
|
4647
|
+
handleInput();
|
|
4648
|
+
};
|
|
4649
|
+
const toggleHighlight = () => {
|
|
4650
|
+
const sel = window.getSelection();
|
|
4651
|
+
if (!sel || sel.rangeCount === 0 || sel.isCollapsed) return;
|
|
4652
|
+
pushHistory(true);
|
|
4653
|
+
const range = sel.getRangeAt(0);
|
|
4654
|
+
const node = sel.anchorNode;
|
|
4655
|
+
const el = node?.nodeType === Node.ELEMENT_NODE ? node : node?.parentElement;
|
|
4656
|
+
const existing = el?.closest("mark");
|
|
4657
|
+
if (existing) {
|
|
4658
|
+
const parent = existing.parentNode;
|
|
4659
|
+
while (existing.firstChild) parent?.insertBefore(existing.firstChild, existing);
|
|
4660
|
+
parent?.removeChild(existing);
|
|
4661
|
+
handleInput();
|
|
4662
|
+
return;
|
|
4663
|
+
}
|
|
4664
|
+
const mark = document.createElement("mark");
|
|
4665
|
+
try {
|
|
4666
|
+
range.surroundContents(mark);
|
|
4667
|
+
} catch {
|
|
4668
|
+
const frag = range.extractContents();
|
|
4669
|
+
mark.appendChild(frag);
|
|
4670
|
+
range.insertNode(mark);
|
|
4671
|
+
}
|
|
4672
|
+
handleInput();
|
|
4673
|
+
};
|
|
4674
|
+
const insertTable = (cols = 3, rows = 2) => {
|
|
4675
|
+
const sel = window.getSelection();
|
|
4676
|
+
if (!sel || sel.rangeCount === 0) return;
|
|
4677
|
+
pushHistory(true);
|
|
4678
|
+
const table = document.createElement("table");
|
|
4679
|
+
const thead = document.createElement("thead");
|
|
4680
|
+
const headRow = document.createElement("tr");
|
|
4681
|
+
for (let c = 0; c < cols; c++) {
|
|
4682
|
+
const th = document.createElement("th");
|
|
4683
|
+
th.innerHTML = "<br>";
|
|
4684
|
+
headRow.appendChild(th);
|
|
4685
|
+
}
|
|
4686
|
+
thead.appendChild(headRow);
|
|
4687
|
+
table.appendChild(thead);
|
|
4688
|
+
const tbody = document.createElement("tbody");
|
|
4689
|
+
for (let r2 = 0; r2 < rows; r2++) {
|
|
4690
|
+
const tr = document.createElement("tr");
|
|
4691
|
+
for (let c = 0; c < cols; c++) {
|
|
4692
|
+
const td = document.createElement("td");
|
|
4693
|
+
td.innerHTML = "<br>";
|
|
4694
|
+
tr.appendChild(td);
|
|
4695
|
+
}
|
|
4696
|
+
tbody.appendChild(tr);
|
|
4697
|
+
}
|
|
4698
|
+
table.appendChild(tbody);
|
|
4699
|
+
const range = sel.getRangeAt(0);
|
|
4700
|
+
range.deleteContents();
|
|
4701
|
+
range.insertNode(table);
|
|
4702
|
+
ensureParagraphAfter(table);
|
|
4703
|
+
const first = table.querySelector("th");
|
|
4704
|
+
if (first) placeCaretAtEnd(first);
|
|
4705
|
+
handleInput();
|
|
4706
|
+
};
|
|
4707
|
+
const moveTableCell = (backwards) => {
|
|
4708
|
+
const block = currentBlock();
|
|
4709
|
+
const cell = block?.closest("td, th");
|
|
4710
|
+
if (!cell) return false;
|
|
4711
|
+
const table = cell.closest("table");
|
|
4712
|
+
if (!table) return false;
|
|
4713
|
+
const cells = Array.from(table.querySelectorAll("td, th"));
|
|
4714
|
+
const i = cells.indexOf(cell);
|
|
4715
|
+
const next = cells[i + (backwards ? -1 : 1)];
|
|
4716
|
+
if (next) {
|
|
4717
|
+
placeCaretAtEnd(next);
|
|
4718
|
+
return true;
|
|
4719
|
+
}
|
|
4720
|
+
if (!backwards) {
|
|
4721
|
+
pushHistory(true);
|
|
4722
|
+
const lastRow = table.querySelector("tbody")?.lastElementChild;
|
|
4723
|
+
if (lastRow) {
|
|
4724
|
+
const tr = document.createElement("tr");
|
|
4725
|
+
for (let c = 0; c < lastRow.children.length; c++) {
|
|
4726
|
+
const td = document.createElement("td");
|
|
4727
|
+
td.innerHTML = "<br>";
|
|
4728
|
+
tr.appendChild(td);
|
|
4729
|
+
}
|
|
4730
|
+
lastRow.after(tr);
|
|
4731
|
+
placeCaretAtEnd(tr.firstElementChild);
|
|
4732
|
+
handleInput();
|
|
4733
|
+
return true;
|
|
4734
|
+
}
|
|
4735
|
+
}
|
|
4736
|
+
return false;
|
|
4737
|
+
};
|
|
4039
4738
|
const insertDivider = () => {
|
|
4739
|
+
pushHistory(true);
|
|
4040
4740
|
exec("insertHorizontalRule");
|
|
4041
4741
|
const el = editorRef.current;
|
|
4042
4742
|
if (el && el.lastElementChild?.tagName === "HR") {
|
|
@@ -4082,7 +4782,9 @@ var Editor = (props) => {
|
|
|
4082
4782
|
const range = sel.getRangeAt(0);
|
|
4083
4783
|
slashStartRangeRef.current = range.cloneRange();
|
|
4084
4784
|
const rect = range.getBoundingClientRect();
|
|
4085
|
-
const
|
|
4785
|
+
const editorEl = editorRef.current;
|
|
4786
|
+
if (!editorEl) return;
|
|
4787
|
+
const editorRect = editorEl.getBoundingClientRect();
|
|
4086
4788
|
setSlashPos({
|
|
4087
4789
|
top: rect.bottom - editorRect.top + 4,
|
|
4088
4790
|
left: rect.left - editorRect.left
|
|
@@ -4097,7 +4799,7 @@ var Editor = (props) => {
|
|
|
4097
4799
|
setSlashIdx(0);
|
|
4098
4800
|
slashStartRangeRef.current = null;
|
|
4099
4801
|
};
|
|
4100
|
-
const filteredSlashItems =
|
|
4802
|
+
const filteredSlashItems = React22.useMemo(() => {
|
|
4101
4803
|
if (!slashFilter) return SLASH_ITEMS;
|
|
4102
4804
|
const f = slashFilter.toLowerCase();
|
|
4103
4805
|
return SLASH_ITEMS.filter((it) => it.label.toLowerCase().includes(f) || it.key.includes(f));
|
|
@@ -4127,8 +4829,14 @@ var Editor = (props) => {
|
|
|
4127
4829
|
case "paragraph":
|
|
4128
4830
|
setBlock("p");
|
|
4129
4831
|
break;
|
|
4130
|
-
case "heading":
|
|
4131
|
-
|
|
4832
|
+
case "heading-1":
|
|
4833
|
+
toggleBlock("h1");
|
|
4834
|
+
break;
|
|
4835
|
+
case "heading-2":
|
|
4836
|
+
toggleBlock("h2");
|
|
4837
|
+
break;
|
|
4838
|
+
case "heading-3":
|
|
4839
|
+
toggleBlock("h3");
|
|
4132
4840
|
break;
|
|
4133
4841
|
case "list":
|
|
4134
4842
|
exec("insertUnorderedList");
|
|
@@ -4140,7 +4848,7 @@ var Editor = (props) => {
|
|
|
4140
4848
|
setBlock("blockquote");
|
|
4141
4849
|
break;
|
|
4142
4850
|
case "code-block":
|
|
4143
|
-
|
|
4851
|
+
insertCodeBlock();
|
|
4144
4852
|
break;
|
|
4145
4853
|
case "divider":
|
|
4146
4854
|
insertDivider();
|
|
@@ -4158,7 +4866,9 @@ var Editor = (props) => {
|
|
|
4158
4866
|
if (!sel || sel.rangeCount === 0) return;
|
|
4159
4867
|
const range = sel.getRangeAt(0);
|
|
4160
4868
|
const rect = range.getBoundingClientRect();
|
|
4161
|
-
const
|
|
4869
|
+
const editorEl2 = editorRef.current;
|
|
4870
|
+
if (!editorEl2) return;
|
|
4871
|
+
const editorRect = editorEl2.getBoundingClientRect();
|
|
4162
4872
|
setLinkPos({
|
|
4163
4873
|
top: rect.bottom - editorRect.top + 4,
|
|
4164
4874
|
left: rect.left - editorRect.left
|
|
@@ -4191,13 +4901,13 @@ var Editor = (props) => {
|
|
|
4191
4901
|
if (node.nodeType !== Node.TEXT_NODE) return false;
|
|
4192
4902
|
const text = (node.textContent || "").slice(0, range.startOffset);
|
|
4193
4903
|
const patterns = [
|
|
4194
|
-
[
|
|
4195
|
-
[
|
|
4196
|
-
[
|
|
4197
|
-
[
|
|
4198
|
-
[
|
|
4199
|
-
[/^1
|
|
4200
|
-
[
|
|
4904
|
+
[/^###$/, () => setBlock("h3")],
|
|
4905
|
+
[/^##$/, () => setBlock("h2")],
|
|
4906
|
+
[/^#$/, () => setBlock("h1")],
|
|
4907
|
+
[/^-$/, () => exec("insertUnorderedList")],
|
|
4908
|
+
[/^\*$/, () => exec("insertUnorderedList")],
|
|
4909
|
+
[/^1\.$/, () => exec("insertOrderedList")],
|
|
4910
|
+
[/^>$/, () => setBlock("blockquote")]
|
|
4201
4911
|
];
|
|
4202
4912
|
for (const [re, fn] of patterns) {
|
|
4203
4913
|
if (re.test(text)) {
|
|
@@ -4217,7 +4927,11 @@ var Editor = (props) => {
|
|
|
4217
4927
|
if (composingRef.current) return;
|
|
4218
4928
|
const el = editorRef.current;
|
|
4219
4929
|
if (!el) return;
|
|
4220
|
-
|
|
4930
|
+
const html = el.innerHTML;
|
|
4931
|
+
lastEmittedRef.current = html;
|
|
4932
|
+
pushHistory();
|
|
4933
|
+
scheduleHighlight();
|
|
4934
|
+
onChange?.(html);
|
|
4221
4935
|
updateEmpty();
|
|
4222
4936
|
updateActiveFormats();
|
|
4223
4937
|
if (slashOpen) {
|
|
@@ -4245,6 +4959,40 @@ var Editor = (props) => {
|
|
|
4245
4959
|
};
|
|
4246
4960
|
const handleKeyDown = (e) => {
|
|
4247
4961
|
if (readOnly) return;
|
|
4962
|
+
if (composingRef.current || e.nativeEvent.isComposing || e.keyCode === 229) return;
|
|
4963
|
+
const pre = closestPre();
|
|
4964
|
+
if (pre && !slashOpen) {
|
|
4965
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
4966
|
+
const text = pre.textContent || "";
|
|
4967
|
+
if (text.endsWith("\n\n")) {
|
|
4968
|
+
e.preventDefault();
|
|
4969
|
+
const code = pre.querySelector("code") ?? pre;
|
|
4970
|
+
code.textContent = text.replace(/\n\n$/, "");
|
|
4971
|
+
ensureParagraphAfter(pre);
|
|
4972
|
+
const next = pre.nextElementSibling;
|
|
4973
|
+
if (next) placeCaretAtEnd(next);
|
|
4974
|
+
handleInput();
|
|
4975
|
+
return;
|
|
4976
|
+
}
|
|
4977
|
+
e.preventDefault();
|
|
4978
|
+
insertTextAtCaret("\n");
|
|
4979
|
+
return;
|
|
4980
|
+
}
|
|
4981
|
+
if (e.key === "Tab") {
|
|
4982
|
+
e.preventDefault();
|
|
4983
|
+
insertTextAtCaret(" ");
|
|
4984
|
+
return;
|
|
4985
|
+
}
|
|
4986
|
+
}
|
|
4987
|
+
if (e.key === "Tab" && moveTableCell(e.shiftKey)) {
|
|
4988
|
+
e.preventDefault();
|
|
4989
|
+
return;
|
|
4990
|
+
}
|
|
4991
|
+
if (e.key === "Tab" && inListItem()) {
|
|
4992
|
+
e.preventDefault();
|
|
4993
|
+
indentList(e.shiftKey);
|
|
4994
|
+
return;
|
|
4995
|
+
}
|
|
4248
4996
|
if (slashOpen) {
|
|
4249
4997
|
if (e.key === "ArrowDown") {
|
|
4250
4998
|
e.preventDefault();
|
|
@@ -4268,6 +5016,21 @@ var Editor = (props) => {
|
|
|
4268
5016
|
return;
|
|
4269
5017
|
}
|
|
4270
5018
|
}
|
|
5019
|
+
if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "z") {
|
|
5020
|
+
e.preventDefault();
|
|
5021
|
+
if (e.shiftKey) redo();
|
|
5022
|
+
else undo();
|
|
5023
|
+
return;
|
|
5024
|
+
}
|
|
5025
|
+
if ((e.metaKey || e.ctrlKey) && e.shiftKey && e.key.toLowerCase() === "v") {
|
|
5026
|
+
plainPasteRef.current = true;
|
|
5027
|
+
return;
|
|
5028
|
+
}
|
|
5029
|
+
if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "y") {
|
|
5030
|
+
e.preventDefault();
|
|
5031
|
+
redo();
|
|
5032
|
+
return;
|
|
5033
|
+
}
|
|
4271
5034
|
if ((e.metaKey || e.ctrlKey) && !e.shiftKey && !e.altKey) {
|
|
4272
5035
|
const k = e.key.toLowerCase();
|
|
4273
5036
|
if (k === "b") {
|
|
@@ -4291,6 +5054,7 @@ var Editor = (props) => {
|
|
|
4291
5054
|
return;
|
|
4292
5055
|
}
|
|
4293
5056
|
}
|
|
5057
|
+
if (pre) return;
|
|
4294
5058
|
if (enableSlashCommand && e.key === "/") {
|
|
4295
5059
|
setTimeout(openSlashMenu, 0);
|
|
4296
5060
|
}
|
|
@@ -4300,11 +5064,21 @@ var Editor = (props) => {
|
|
|
4300
5064
|
}
|
|
4301
5065
|
}
|
|
4302
5066
|
};
|
|
5067
|
+
const plainPasteRef = React22.useRef(false);
|
|
4303
5068
|
const handlePaste = (e) => {
|
|
4304
5069
|
if (readOnly) return;
|
|
4305
5070
|
e.preventDefault();
|
|
4306
|
-
const html = e.clipboardData.getData("text/html");
|
|
4307
5071
|
const text = e.clipboardData.getData("text/plain");
|
|
5072
|
+
if (plainPasteRef.current) {
|
|
5073
|
+
plainPasteRef.current = false;
|
|
5074
|
+
insertTextAtCaret(text);
|
|
5075
|
+
return;
|
|
5076
|
+
}
|
|
5077
|
+
if (closestPre()) {
|
|
5078
|
+
insertTextAtCaret(text);
|
|
5079
|
+
return;
|
|
5080
|
+
}
|
|
5081
|
+
const html = e.clipboardData.getData("text/html");
|
|
4308
5082
|
const clean = html ? sanitizeHtml(html) : escapeHtml(text);
|
|
4309
5083
|
document.execCommand("insertHTML", false, clean);
|
|
4310
5084
|
handleInput();
|
|
@@ -4326,8 +5100,11 @@ var Editor = (props) => {
|
|
|
4326
5100
|
};
|
|
4327
5101
|
const handleSelectionUpdate = () => {
|
|
4328
5102
|
updateActiveFormats();
|
|
5103
|
+
const pre = closestPre();
|
|
5104
|
+
setCodeLang(pre ? langOf(pre) : "plain");
|
|
4329
5105
|
};
|
|
4330
5106
|
const onToolbarAction = (item) => {
|
|
5107
|
+
if (closestPre() && !["code-block", "undo", "redo"].includes(item)) return;
|
|
4331
5108
|
switch (item) {
|
|
4332
5109
|
case "bold":
|
|
4333
5110
|
exec("bold");
|
|
@@ -4356,8 +5133,14 @@ var Editor = (props) => {
|
|
|
4356
5133
|
handleInput();
|
|
4357
5134
|
break;
|
|
4358
5135
|
}
|
|
4359
|
-
case "heading":
|
|
4360
|
-
|
|
5136
|
+
case "heading-1":
|
|
5137
|
+
toggleBlock("h1");
|
|
5138
|
+
break;
|
|
5139
|
+
case "heading-2":
|
|
5140
|
+
toggleBlock("h2");
|
|
5141
|
+
break;
|
|
5142
|
+
case "heading-3":
|
|
5143
|
+
toggleBlock("h3");
|
|
4361
5144
|
break;
|
|
4362
5145
|
case "list":
|
|
4363
5146
|
exec("insertUnorderedList");
|
|
@@ -4369,7 +5152,7 @@ var Editor = (props) => {
|
|
|
4369
5152
|
setBlock("blockquote");
|
|
4370
5153
|
break;
|
|
4371
5154
|
case "code-block":
|
|
4372
|
-
|
|
5155
|
+
insertCodeBlock();
|
|
4373
5156
|
break;
|
|
4374
5157
|
case "link":
|
|
4375
5158
|
openLinkEditor();
|
|
@@ -4380,6 +5163,39 @@ var Editor = (props) => {
|
|
|
4380
5163
|
case "divider":
|
|
4381
5164
|
insertDivider();
|
|
4382
5165
|
break;
|
|
5166
|
+
case "checklist":
|
|
5167
|
+
toggleChecklist();
|
|
5168
|
+
break;
|
|
5169
|
+
case "align-left":
|
|
5170
|
+
setAlign("left");
|
|
5171
|
+
break;
|
|
5172
|
+
case "align-center":
|
|
5173
|
+
setAlign("center");
|
|
5174
|
+
break;
|
|
5175
|
+
case "align-right":
|
|
5176
|
+
setAlign("right");
|
|
5177
|
+
break;
|
|
5178
|
+
case "highlight":
|
|
5179
|
+
toggleHighlight();
|
|
5180
|
+
break;
|
|
5181
|
+
case "superscript":
|
|
5182
|
+
exec("superscript");
|
|
5183
|
+
break;
|
|
5184
|
+
case "subscript":
|
|
5185
|
+
exec("subscript");
|
|
5186
|
+
break;
|
|
5187
|
+
case "table":
|
|
5188
|
+
insertTable();
|
|
5189
|
+
break;
|
|
5190
|
+
case "clear-format":
|
|
5191
|
+
clearFormat();
|
|
5192
|
+
break;
|
|
5193
|
+
case "undo":
|
|
5194
|
+
undo();
|
|
5195
|
+
break;
|
|
5196
|
+
case "redo":
|
|
5197
|
+
redo();
|
|
5198
|
+
break;
|
|
4383
5199
|
}
|
|
4384
5200
|
};
|
|
4385
5201
|
return /* @__PURE__ */ jsxs207("div", { className: clsx_default("lib-xplat-editor", isFocused && "focused", readOnly && "readonly"), children: [
|
|
@@ -4388,7 +5204,10 @@ var Editor = (props) => {
|
|
|
4388
5204
|
{
|
|
4389
5205
|
items: toolbar,
|
|
4390
5206
|
active: activeFormats,
|
|
4391
|
-
onAction: onToolbarAction
|
|
5207
|
+
onAction: onToolbarAction,
|
|
5208
|
+
codeLang,
|
|
5209
|
+
inCodeBlock: activeFormats.has("block:pre"),
|
|
5210
|
+
onCodeLangChange: changeCodeLang
|
|
4392
5211
|
}
|
|
4393
5212
|
),
|
|
4394
5213
|
/* @__PURE__ */ jsxs207("div", { className: "lib-xplat-editor__content", style: { minHeight }, children: [
|
|
@@ -4399,9 +5218,14 @@ var Editor = (props) => {
|
|
|
4399
5218
|
ref: editorRef,
|
|
4400
5219
|
contentEditable: !readOnly,
|
|
4401
5220
|
suppressContentEditableWarning: true,
|
|
5221
|
+
role: "textbox",
|
|
5222
|
+
"aria-multiline": "true",
|
|
5223
|
+
"aria-readonly": readOnly || void 0,
|
|
5224
|
+
"aria-label": placeholder,
|
|
4402
5225
|
className: "lib-xplat-editor__editable",
|
|
4403
5226
|
onInput: handleInput,
|
|
4404
5227
|
onKeyDown: handleKeyDown,
|
|
5228
|
+
onClick: handleEditorClick,
|
|
4405
5229
|
onKeyUp: handleSelectionUpdate,
|
|
4406
5230
|
onMouseUp: handleSelectionUpdate,
|
|
4407
5231
|
onPaste: handlePaste,
|
|
@@ -4443,14 +5267,27 @@ var TOOLBAR_LABEL = {
|
|
|
4443
5267
|
underline: "U",
|
|
4444
5268
|
strikethrough: "S",
|
|
4445
5269
|
code: "<>",
|
|
4446
|
-
heading: "
|
|
5270
|
+
"heading-1": "H1",
|
|
5271
|
+
"heading-2": "H2",
|
|
5272
|
+
"heading-3": "H3",
|
|
4447
5273
|
list: "\u2022",
|
|
4448
5274
|
"ordered-list": "1.",
|
|
4449
5275
|
blockquote: "\u275D",
|
|
4450
5276
|
"code-block": "[ ]",
|
|
4451
5277
|
link: "\u{1F517}",
|
|
4452
5278
|
image: "\u{1F5BC}",
|
|
4453
|
-
divider: "\u2014"
|
|
5279
|
+
divider: "\u2014",
|
|
5280
|
+
checklist: "\u2611",
|
|
5281
|
+
"align-left": "\u21E4",
|
|
5282
|
+
"align-center": "\u2194",
|
|
5283
|
+
"align-right": "\u21E5",
|
|
5284
|
+
highlight: "\u{1F58D}",
|
|
5285
|
+
superscript: "x\xB2",
|
|
5286
|
+
subscript: "x\u2082",
|
|
5287
|
+
table: "\u25A6",
|
|
5288
|
+
"clear-format": "\u232B",
|
|
5289
|
+
undo: "\u21B6",
|
|
5290
|
+
redo: "\u21B7"
|
|
4454
5291
|
};
|
|
4455
5292
|
var TOOLBAR_TITLE = {
|
|
4456
5293
|
bold: "\uAD75\uAC8C (\u2318B)",
|
|
@@ -4458,39 +5295,77 @@ var TOOLBAR_TITLE = {
|
|
|
4458
5295
|
underline: "\uBC11\uC904 (\u2318U)",
|
|
4459
5296
|
strikethrough: "\uCDE8\uC18C\uC120",
|
|
4460
5297
|
code: "\uC778\uB77C\uC778 \uCF54\uB4DC",
|
|
4461
|
-
heading: "\uC81C\uBAA9",
|
|
5298
|
+
"heading-1": "\uC81C\uBAA9 1",
|
|
5299
|
+
"heading-2": "\uC81C\uBAA9 2",
|
|
5300
|
+
"heading-3": "\uC81C\uBAA9 3",
|
|
4462
5301
|
list: "\uAE00\uBA38\uB9AC \uAE30\uD638 \uBAA9\uB85D",
|
|
4463
5302
|
"ordered-list": "\uBC88\uD638 \uB9E4\uAE30\uAE30 \uBAA9\uB85D",
|
|
4464
5303
|
blockquote: "\uC778\uC6A9",
|
|
4465
5304
|
"code-block": "\uCF54\uB4DC \uBE14\uB85D",
|
|
4466
5305
|
link: "\uB9C1\uD06C (\u2318K)",
|
|
4467
5306
|
image: "\uC774\uBBF8\uC9C0",
|
|
4468
|
-
divider: "\uAD6C\uBD84\uC120"
|
|
5307
|
+
divider: "\uAD6C\uBD84\uC120",
|
|
5308
|
+
checklist: "\uCCB4\uD06C\uB9AC\uC2A4\uD2B8",
|
|
5309
|
+
"align-left": "\uC67C\uCABD \uC815\uB82C",
|
|
5310
|
+
"align-center": "\uAC00\uC6B4\uB370 \uC815\uB82C",
|
|
5311
|
+
"align-right": "\uC624\uB978\uCABD \uC815\uB82C",
|
|
5312
|
+
highlight: "\uD615\uAD11\uD39C",
|
|
5313
|
+
superscript: "\uC704 \uCCA8\uC790",
|
|
5314
|
+
subscript: "\uC544\uB798 \uCCA8\uC790",
|
|
5315
|
+
table: "\uD45C \uC0BD\uC785",
|
|
5316
|
+
"clear-format": "\uC11C\uC2DD \uC9C0\uC6B0\uAE30",
|
|
5317
|
+
undo: "\uB418\uB3CC\uB9AC\uAE30 (\u2318Z)",
|
|
5318
|
+
redo: "\uB2E4\uC2DC\uD558\uAE30 (\u2318\u21E7Z)"
|
|
4469
5319
|
};
|
|
4470
5320
|
var isActive = (item, active) => {
|
|
4471
|
-
if (item === "heading") return active.has("block:h1")
|
|
5321
|
+
if (item === "heading-1") return active.has("block:h1");
|
|
5322
|
+
if (item === "heading-2") return active.has("block:h2");
|
|
5323
|
+
if (item === "heading-3") return active.has("block:h3");
|
|
4472
5324
|
if (item === "blockquote") return active.has("block:blockquote");
|
|
4473
5325
|
if (item === "code-block") return active.has("block:pre");
|
|
5326
|
+
if (item === "align-left") return active.has("align:left");
|
|
5327
|
+
if (item === "align-center") return active.has("align:center");
|
|
5328
|
+
if (item === "align-right") return active.has("align:right");
|
|
4474
5329
|
return active.has(item);
|
|
4475
5330
|
};
|
|
4476
|
-
var EditorToolbar = ({
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
5331
|
+
var EditorToolbar = ({
|
|
5332
|
+
items,
|
|
5333
|
+
active,
|
|
5334
|
+
onAction,
|
|
5335
|
+
codeLang,
|
|
5336
|
+
inCodeBlock,
|
|
5337
|
+
onCodeLangChange
|
|
5338
|
+
}) => {
|
|
5339
|
+
return /* @__PURE__ */ jsxs207("div", { className: "lib-xplat-editor__toolbar", children: [
|
|
5340
|
+
items.map((item) => /* @__PURE__ */ jsx323(
|
|
5341
|
+
"button",
|
|
5342
|
+
{
|
|
5343
|
+
type: "button",
|
|
5344
|
+
className: clsx_default("lib-xplat-editor__toolbar-btn", isActive(item, active) && "active"),
|
|
5345
|
+
title: TOOLBAR_TITLE[item],
|
|
5346
|
+
onMouseDown: (e) => {
|
|
5347
|
+
e.preventDefault();
|
|
5348
|
+
onAction(item);
|
|
5349
|
+
},
|
|
5350
|
+
children: TOOLBAR_LABEL[item]
|
|
4486
5351
|
},
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
5352
|
+
item
|
|
5353
|
+
)),
|
|
5354
|
+
inCodeBlock && /* @__PURE__ */ jsx323(
|
|
5355
|
+
"select",
|
|
5356
|
+
{
|
|
5357
|
+
className: "lib-xplat-editor__lang",
|
|
5358
|
+
value: codeLang,
|
|
5359
|
+
"aria-label": "\uCF54\uB4DC \uC5B8\uC5B4",
|
|
5360
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
5361
|
+
onChange: (e) => onCodeLangChange(e.target.value),
|
|
5362
|
+
children: CODE_LANGUAGES.map((l) => /* @__PURE__ */ jsx323("option", { value: l.value, children: l.label }, l.value))
|
|
5363
|
+
}
|
|
5364
|
+
)
|
|
5365
|
+
] });
|
|
4491
5366
|
};
|
|
4492
5367
|
var SlashMenu = ({ position, items, activeIndex, onSelect, onClose }) => {
|
|
4493
|
-
|
|
5368
|
+
React22.useEffect(() => {
|
|
4494
5369
|
const handleClickOutside = (e) => {
|
|
4495
5370
|
const target = e.target;
|
|
4496
5371
|
const menu = document.querySelector(".lib-xplat-editor__slash-menu");
|
|
@@ -4524,8 +5399,8 @@ var SlashMenu = ({ position, items, activeIndex, onSelect, onClose }) => {
|
|
|
4524
5399
|
);
|
|
4525
5400
|
};
|
|
4526
5401
|
var LinkPopover = ({ position, value, onChange, onConfirm, onClose }) => {
|
|
4527
|
-
const inputRef =
|
|
4528
|
-
|
|
5402
|
+
const inputRef = React22.useRef(null);
|
|
5403
|
+
React22.useEffect(() => {
|
|
4529
5404
|
inputRef.current?.focus();
|
|
4530
5405
|
}, []);
|
|
4531
5406
|
return /* @__PURE__ */ jsxs207(
|
|
@@ -4583,7 +5458,7 @@ EmptyState.displayName = "EmptyState";
|
|
|
4583
5458
|
var EmptyState_default = EmptyState;
|
|
4584
5459
|
|
|
4585
5460
|
// src/components/FileUpload/FileUpload.tsx
|
|
4586
|
-
import
|
|
5461
|
+
import React23 from "react";
|
|
4587
5462
|
import { jsx as jsx325, jsxs as jsxs209 } from "react/jsx-runtime";
|
|
4588
5463
|
var FileUpload = (props) => {
|
|
4589
5464
|
const {
|
|
@@ -4595,8 +5470,8 @@ var FileUpload = (props) => {
|
|
|
4595
5470
|
description,
|
|
4596
5471
|
validations
|
|
4597
5472
|
} = props;
|
|
4598
|
-
const [isDragOver, setIsDragOver] =
|
|
4599
|
-
const inputRef =
|
|
5473
|
+
const [isDragOver, setIsDragOver] = React23.useState(false);
|
|
5474
|
+
const inputRef = React23.useRef(null);
|
|
4600
5475
|
const handleFiles = (fileList) => {
|
|
4601
5476
|
let files = Array.from(fileList);
|
|
4602
5477
|
if (maxSize) {
|
|
@@ -4658,10 +5533,10 @@ FileUpload.displayName = "FileUpload";
|
|
|
4658
5533
|
var FileUpload_default = FileUpload;
|
|
4659
5534
|
|
|
4660
5535
|
// src/components/HtmlTypeWriter/HtmlTypeWriter.tsx
|
|
4661
|
-
import
|
|
5536
|
+
import React25 from "react";
|
|
4662
5537
|
|
|
4663
5538
|
// src/components/HtmlTypeWriter/utils.ts
|
|
4664
|
-
import
|
|
5539
|
+
import React24 from "react";
|
|
4665
5540
|
var voidTags = /* @__PURE__ */ new Set([
|
|
4666
5541
|
"br",
|
|
4667
5542
|
"img",
|
|
@@ -4729,15 +5604,15 @@ var convertNodeToReactWithRange = (node, typedLen, rangeMap) => {
|
|
|
4729
5604
|
props[attr.name] = attr.value;
|
|
4730
5605
|
});
|
|
4731
5606
|
if (voidTags.has(tag)) {
|
|
4732
|
-
return
|
|
5607
|
+
return React24.createElement(tag, props);
|
|
4733
5608
|
}
|
|
4734
5609
|
const children = Array.from(element.childNodes).map((child) => convertNodeToReactWithRange(child, typedLen, rangeMap)).filter((n) => n != null);
|
|
4735
|
-
return
|
|
5610
|
+
return React24.createElement(tag, props, ...children);
|
|
4736
5611
|
};
|
|
4737
5612
|
var htmlToReactProgressive = (root, typedLen, rangeMap) => {
|
|
4738
5613
|
const nodes = Array.from(root.childNodes).map((child, idx) => {
|
|
4739
5614
|
const node = convertNodeToReactWithRange(child, typedLen, rangeMap);
|
|
4740
|
-
return node == null ? null :
|
|
5615
|
+
return node == null ? null : React24.createElement(React24.Fragment, { key: idx }, node);
|
|
4741
5616
|
}).filter(Boolean);
|
|
4742
5617
|
return nodes.length === 0 ? null : nodes;
|
|
4743
5618
|
};
|
|
@@ -4750,20 +5625,20 @@ var HtmlTypeWriter = ({
|
|
|
4750
5625
|
onDone,
|
|
4751
5626
|
onChange
|
|
4752
5627
|
}) => {
|
|
4753
|
-
const [typedLen, setTypedLen] =
|
|
4754
|
-
const doneCalledRef =
|
|
4755
|
-
const { doc, rangeMap, totalLength } =
|
|
5628
|
+
const [typedLen, setTypedLen] = React25.useState(0);
|
|
5629
|
+
const doneCalledRef = React25.useRef(false);
|
|
5630
|
+
const { doc, rangeMap, totalLength } = React25.useMemo(() => {
|
|
4756
5631
|
if (typeof window === "undefined") return { doc: null, rangeMap: /* @__PURE__ */ new Map(), totalLength: 0 };
|
|
4757
5632
|
const decoded = decodeHtmlEntities(html);
|
|
4758
5633
|
const doc2 = new DOMParser().parseFromString(decoded, "text/html");
|
|
4759
5634
|
const { rangeMap: rangeMap2, totalLength: totalLength2 } = buildRangeMap(doc2.body);
|
|
4760
5635
|
return { doc: doc2, rangeMap: rangeMap2, totalLength: totalLength2 };
|
|
4761
5636
|
}, [html]);
|
|
4762
|
-
|
|
5637
|
+
React25.useEffect(() => {
|
|
4763
5638
|
setTypedLen(0);
|
|
4764
5639
|
doneCalledRef.current = false;
|
|
4765
5640
|
}, [html]);
|
|
4766
|
-
|
|
5641
|
+
React25.useEffect(() => {
|
|
4767
5642
|
if (!totalLength) return;
|
|
4768
5643
|
if (typedLen >= totalLength) return;
|
|
4769
5644
|
const timer = window.setInterval(() => {
|
|
@@ -4771,18 +5646,18 @@ var HtmlTypeWriter = ({
|
|
|
4771
5646
|
}, duration);
|
|
4772
5647
|
return () => window.clearInterval(timer);
|
|
4773
5648
|
}, [typedLen, totalLength, duration]);
|
|
4774
|
-
|
|
5649
|
+
React25.useEffect(() => {
|
|
4775
5650
|
if (typedLen > 0 && typedLen < totalLength) {
|
|
4776
5651
|
onChange?.();
|
|
4777
5652
|
}
|
|
4778
5653
|
}, [typedLen, totalLength, onChange]);
|
|
4779
|
-
|
|
5654
|
+
React25.useEffect(() => {
|
|
4780
5655
|
if (typedLen === totalLength && totalLength > 0 && !doneCalledRef.current) {
|
|
4781
5656
|
doneCalledRef.current = true;
|
|
4782
5657
|
onDone?.();
|
|
4783
5658
|
}
|
|
4784
5659
|
}, [typedLen, totalLength, onDone]);
|
|
4785
|
-
const parsed =
|
|
5660
|
+
const parsed = React25.useMemo(
|
|
4786
5661
|
() => doc ? htmlToReactProgressive(doc.body, typedLen, rangeMap) : null,
|
|
4787
5662
|
[doc, typedLen, rangeMap]
|
|
4788
5663
|
);
|
|
@@ -4792,12 +5667,12 @@ HtmlTypeWriter.displayName = "HtmlTypeWriter";
|
|
|
4792
5667
|
var HtmlTypeWriter_default = HtmlTypeWriter;
|
|
4793
5668
|
|
|
4794
5669
|
// src/components/ImageSelector/ImageSelector.tsx
|
|
4795
|
-
import
|
|
5670
|
+
import React26 from "react";
|
|
4796
5671
|
import { jsx as jsx327, jsxs as jsxs210 } from "react/jsx-runtime";
|
|
4797
5672
|
var ImageSelector = (props) => {
|
|
4798
5673
|
const { value, label, onChange, validations } = props;
|
|
4799
|
-
const [previewUrl, setPreviewUrl] =
|
|
4800
|
-
|
|
5674
|
+
const [previewUrl, setPreviewUrl] = React26.useState();
|
|
5675
|
+
React26.useEffect(() => {
|
|
4801
5676
|
if (!value) {
|
|
4802
5677
|
setPreviewUrl(void 0);
|
|
4803
5678
|
return;
|
|
@@ -4806,7 +5681,7 @@ var ImageSelector = (props) => {
|
|
|
4806
5681
|
setPreviewUrl(url);
|
|
4807
5682
|
return () => URL.revokeObjectURL(url);
|
|
4808
5683
|
}, [value]);
|
|
4809
|
-
const inputRef =
|
|
5684
|
+
const inputRef = React26.useRef(null);
|
|
4810
5685
|
const handleFileChange = (e) => {
|
|
4811
5686
|
const selectedFile = e.target.files?.[0];
|
|
4812
5687
|
if (selectedFile) {
|
|
@@ -4989,17 +5864,21 @@ Pagination.displayName = "Pagination";
|
|
|
4989
5864
|
var Pagination_default = Pagination;
|
|
4990
5865
|
|
|
4991
5866
|
// src/components/PopOver/PopOver.tsx
|
|
4992
|
-
import
|
|
5867
|
+
import React27 from "react";
|
|
4993
5868
|
import { jsx as jsx332, jsxs as jsxs213 } from "react/jsx-runtime";
|
|
4994
5869
|
var PopOver = (props) => {
|
|
4995
5870
|
const { children, isOpen, onClose, PopOverEl } = props;
|
|
4996
|
-
const popRef =
|
|
4997
|
-
const triggerRef =
|
|
4998
|
-
const [localOpen, setLocalOpen] =
|
|
4999
|
-
const [eventTrigger, setEventTrigger] =
|
|
5871
|
+
const popRef = React27.useRef(null);
|
|
5872
|
+
const triggerRef = React27.useRef(null);
|
|
5873
|
+
const [localOpen, setLocalOpen] = React27.useState(false);
|
|
5874
|
+
const [eventTrigger, setEventTrigger] = React27.useState(false);
|
|
5000
5875
|
useClickOutside_default([popRef, triggerRef], onClose, isOpen);
|
|
5876
|
+
useEscapeKey(isOpen, () => {
|
|
5877
|
+
onClose();
|
|
5878
|
+
triggerRef.current?.focus({ preventScroll: true });
|
|
5879
|
+
});
|
|
5001
5880
|
const position = useAutoPosition_default(triggerRef, popRef, localOpen);
|
|
5002
|
-
|
|
5881
|
+
React27.useEffect(() => {
|
|
5003
5882
|
if (isOpen) {
|
|
5004
5883
|
setLocalOpen(isOpen);
|
|
5005
5884
|
setTimeout(() => {
|
|
@@ -5028,6 +5907,7 @@ var PopOver = (props) => {
|
|
|
5028
5907
|
className: clsx_default(
|
|
5029
5908
|
"lib-xplat-pop-over-content",
|
|
5030
5909
|
position.direction,
|
|
5910
|
+
position.repositioning && "repositioning",
|
|
5031
5911
|
eventTrigger && "visible"
|
|
5032
5912
|
),
|
|
5033
5913
|
ref: popRef,
|
|
@@ -5084,12 +5964,12 @@ Progress.displayName = "Progress";
|
|
|
5084
5964
|
var Progress_default = Progress;
|
|
5085
5965
|
|
|
5086
5966
|
// src/components/Radio/RadioGroupContext.tsx
|
|
5087
|
-
import
|
|
5088
|
-
var RadioGroupContext =
|
|
5967
|
+
import React28 from "react";
|
|
5968
|
+
var RadioGroupContext = React28.createContext(
|
|
5089
5969
|
null
|
|
5090
5970
|
);
|
|
5091
5971
|
var useRadioGroupContext = () => {
|
|
5092
|
-
return
|
|
5972
|
+
return React28.useContext(RadioGroupContext);
|
|
5093
5973
|
};
|
|
5094
5974
|
var RadioGroupContext_default = RadioGroupContext;
|
|
5095
5975
|
|
|
@@ -5165,19 +6045,19 @@ RadioGroup.displayName = "RadioGroup";
|
|
|
5165
6045
|
var RadioGroup_default = RadioGroup;
|
|
5166
6046
|
|
|
5167
6047
|
// src/components/Select/Select.tsx
|
|
5168
|
-
import
|
|
6048
|
+
import React31 from "react";
|
|
5169
6049
|
|
|
5170
6050
|
// src/components/Select/context.ts
|
|
5171
|
-
import
|
|
5172
|
-
var SelectContext =
|
|
6051
|
+
import React29 from "react";
|
|
6052
|
+
var SelectContext = React29.createContext(null);
|
|
5173
6053
|
var context_default = SelectContext;
|
|
5174
6054
|
|
|
5175
6055
|
// src/components/Select/SelectItem.tsx
|
|
5176
|
-
import
|
|
6056
|
+
import React30 from "react";
|
|
5177
6057
|
import { jsx as jsx336 } from "react/jsx-runtime";
|
|
5178
6058
|
var SelectItem = (props) => {
|
|
5179
6059
|
const { children, value, onClick, disabled = false } = props;
|
|
5180
|
-
const ctx =
|
|
6060
|
+
const ctx = React30.useContext(context_default);
|
|
5181
6061
|
const handleClick = (e) => {
|
|
5182
6062
|
e.preventDefault();
|
|
5183
6063
|
e.stopPropagation();
|
|
@@ -5217,32 +6097,37 @@ var SelectRoot = (props) => {
|
|
|
5217
6097
|
onChange,
|
|
5218
6098
|
children,
|
|
5219
6099
|
disabled = false,
|
|
6100
|
+
searchable = false,
|
|
6101
|
+
searchPlaceholder = "\uAC80\uC0C9",
|
|
5220
6102
|
error = false,
|
|
5221
6103
|
validations,
|
|
6104
|
+
label,
|
|
6105
|
+
required,
|
|
5222
6106
|
size = "md"
|
|
5223
6107
|
} = props;
|
|
5224
|
-
const
|
|
5225
|
-
|
|
6108
|
+
const fieldId = React31.useId();
|
|
6109
|
+
const itemChildren = React31.Children.toArray(children).filter(
|
|
6110
|
+
(child) => React31.isValidElement(child) && child.type === SelectItem_default
|
|
5226
6111
|
);
|
|
5227
6112
|
const isControlled = valueProp !== void 0;
|
|
5228
|
-
const [isOpen, setOpen] =
|
|
5229
|
-
const [uncontrolledLabel, setUncontrolledLabel] =
|
|
5230
|
-
const [uncontrolledValue, setUncontrolledValue] =
|
|
5231
|
-
const controlledLabel =
|
|
6113
|
+
const [isOpen, setOpen] = React31.useState(false);
|
|
6114
|
+
const [uncontrolledLabel, setUncontrolledLabel] = React31.useState(null);
|
|
6115
|
+
const [uncontrolledValue, setUncontrolledValue] = React31.useState(void 0);
|
|
6116
|
+
const controlledLabel = React31.useMemo(() => {
|
|
5232
6117
|
if (!isControlled) return null;
|
|
5233
6118
|
const match = itemChildren.find((child) => child.props.value === valueProp);
|
|
5234
6119
|
return match ? match.props.children : null;
|
|
5235
6120
|
}, [isControlled, valueProp, itemChildren]);
|
|
5236
6121
|
const selectedLabel = isControlled ? controlledLabel : uncontrolledLabel;
|
|
5237
6122
|
const selectedValue = isControlled ? valueProp : uncontrolledValue;
|
|
5238
|
-
const triggerRef =
|
|
5239
|
-
const contentRef =
|
|
5240
|
-
const [mounted, setMounted] =
|
|
5241
|
-
const [visible, setVisible] =
|
|
5242
|
-
|
|
6123
|
+
const triggerRef = React31.useRef(null);
|
|
6124
|
+
const contentRef = React31.useRef(null);
|
|
6125
|
+
const [mounted, setMounted] = React31.useState(false);
|
|
6126
|
+
const [visible, setVisible] = React31.useState(false);
|
|
6127
|
+
React31.useEffect(() => {
|
|
5243
6128
|
if (disabled && isOpen) setOpen(false);
|
|
5244
6129
|
}, [disabled, isOpen]);
|
|
5245
|
-
|
|
6130
|
+
React31.useEffect(() => {
|
|
5246
6131
|
if (isOpen) {
|
|
5247
6132
|
setMounted(true);
|
|
5248
6133
|
const t2 = setTimeout(() => setVisible(true), 1);
|
|
@@ -5252,22 +6137,42 @@ var SelectRoot = (props) => {
|
|
|
5252
6137
|
const t = setTimeout(() => setMounted(false), ANIMATION_DURATION_MS3);
|
|
5253
6138
|
return () => clearTimeout(t);
|
|
5254
6139
|
}, [isOpen]);
|
|
5255
|
-
const
|
|
5256
|
-
const
|
|
5257
|
-
|
|
6140
|
+
const [query, setQuery] = React31.useState("");
|
|
6141
|
+
const textOf = (node) => {
|
|
6142
|
+
if (node === null || node === void 0 || typeof node === "boolean") return "";
|
|
6143
|
+
if (typeof node === "string" || typeof node === "number") return String(node);
|
|
6144
|
+
if (Array.isArray(node)) return node.map(textOf).join("");
|
|
6145
|
+
if (React31.isValidElement(node)) return textOf(node.props.children);
|
|
6146
|
+
return "";
|
|
6147
|
+
};
|
|
6148
|
+
const visibleItems = React31.useMemo(() => {
|
|
6149
|
+
if (!searchable || !query.trim()) return itemChildren;
|
|
6150
|
+
const q = query.trim().toLowerCase();
|
|
6151
|
+
return itemChildren.filter((c) => textOf(c.props.children).toLowerCase().includes(q));
|
|
6152
|
+
}, [searchable, query, itemChildren]);
|
|
6153
|
+
const open = React31.useCallback(() => setOpen(true), []);
|
|
6154
|
+
const close = React31.useCallback(() => {
|
|
6155
|
+
setOpen(false);
|
|
6156
|
+
setQuery("");
|
|
6157
|
+
}, []);
|
|
6158
|
+
const toggle = React31.useCallback(() => setOpen((prev) => !prev), []);
|
|
5258
6159
|
useClickOutside_default([contentRef, triggerRef], close, isOpen);
|
|
6160
|
+
useEscapeKey(isOpen, () => {
|
|
6161
|
+
close();
|
|
6162
|
+
triggerRef.current?.focus({ preventScroll: true });
|
|
6163
|
+
});
|
|
5259
6164
|
const position = useAutoPosition_default(triggerRef, contentRef, mounted);
|
|
5260
|
-
const setSelected =
|
|
5261
|
-
(
|
|
6165
|
+
const setSelected = React31.useCallback(
|
|
6166
|
+
(label2, itemValue) => {
|
|
5262
6167
|
if (!isControlled) {
|
|
5263
|
-
setUncontrolledLabel(
|
|
6168
|
+
setUncontrolledLabel(label2);
|
|
5264
6169
|
setUncontrolledValue(itemValue);
|
|
5265
6170
|
}
|
|
5266
|
-
onChange?.(itemValue,
|
|
6171
|
+
onChange?.(itemValue, label2);
|
|
5267
6172
|
},
|
|
5268
6173
|
[isControlled, onChange]
|
|
5269
6174
|
);
|
|
5270
|
-
const ctxValue =
|
|
6175
|
+
const ctxValue = React31.useMemo(
|
|
5271
6176
|
() => ({
|
|
5272
6177
|
isOpen,
|
|
5273
6178
|
mounted,
|
|
@@ -5303,6 +6208,7 @@ var SelectRoot = (props) => {
|
|
|
5303
6208
|
/* @__PURE__ */ jsxs216(
|
|
5304
6209
|
"div",
|
|
5305
6210
|
{
|
|
6211
|
+
id: fieldId,
|
|
5306
6212
|
ref: triggerRef,
|
|
5307
6213
|
className: clsx_default(
|
|
5308
6214
|
"select-trigger",
|
|
@@ -5345,20 +6251,33 @@ var SelectRoot = (props) => {
|
|
|
5345
6251
|
]
|
|
5346
6252
|
}
|
|
5347
6253
|
),
|
|
5348
|
-
mounted && /* @__PURE__ */ jsx337(Portal_default, { children: /* @__PURE__ */
|
|
6254
|
+
mounted && /* @__PURE__ */ jsx337(Portal_default, { children: /* @__PURE__ */ jsxs216(
|
|
5349
6255
|
"div",
|
|
5350
6256
|
{
|
|
5351
|
-
className: clsx_default("lib-xplat-select-content", size, position.direction, stateClass),
|
|
6257
|
+
className: clsx_default("lib-xplat-select-content", size, position.direction, stateClass, position.repositioning && "repositioning"),
|
|
5352
6258
|
ref: contentRef,
|
|
5353
6259
|
style: { ...position.position, width: triggerRef.current?.offsetWidth },
|
|
5354
6260
|
role: "listbox",
|
|
5355
|
-
children:
|
|
6261
|
+
children: [
|
|
6262
|
+
searchable && /* @__PURE__ */ jsx337("div", { className: "select-search", children: /* @__PURE__ */ jsx337(
|
|
6263
|
+
"input",
|
|
6264
|
+
{
|
|
6265
|
+
type: "text",
|
|
6266
|
+
value: query,
|
|
6267
|
+
placeholder: searchPlaceholder,
|
|
6268
|
+
onChange: (e) => setQuery(e.target.value),
|
|
6269
|
+
autoFocus: true,
|
|
6270
|
+
"aria-label": searchPlaceholder
|
|
6271
|
+
}
|
|
6272
|
+
) }),
|
|
6273
|
+
/* @__PURE__ */ jsx337(context_default.Provider, { value: ctxValue, children: visibleItems.length > 0 ? visibleItems : /* @__PURE__ */ jsx337("div", { className: "select-empty", children: "\uACB0\uACFC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4" }) })
|
|
6274
|
+
]
|
|
5356
6275
|
}
|
|
5357
6276
|
) })
|
|
5358
6277
|
]
|
|
5359
6278
|
}
|
|
5360
6279
|
) });
|
|
5361
|
-
return /* @__PURE__ */ jsx337(Field, { validations, children: control });
|
|
6280
|
+
return /* @__PURE__ */ jsx337(Field, { validations, label, required, htmlFor: fieldId, children: control });
|
|
5362
6281
|
};
|
|
5363
6282
|
SelectRoot.displayName = "Select";
|
|
5364
6283
|
var Select = Object.assign(SelectRoot, {
|
|
@@ -5438,8 +6357,44 @@ var Spinner = (props) => {
|
|
|
5438
6357
|
Spinner.displayName = "Spinner";
|
|
5439
6358
|
var Spinner_default = Spinner;
|
|
5440
6359
|
|
|
5441
|
-
// src/components/
|
|
6360
|
+
// src/components/Stat/Stat.tsx
|
|
5442
6361
|
import { jsx as jsx340, jsxs as jsxs218 } from "react/jsx-runtime";
|
|
6362
|
+
var ARROW = {
|
|
6363
|
+
up: "\u25B2",
|
|
6364
|
+
down: "\u25BC",
|
|
6365
|
+
flat: "\u2014"
|
|
6366
|
+
};
|
|
6367
|
+
var Stat = (props) => {
|
|
6368
|
+
const {
|
|
6369
|
+
label,
|
|
6370
|
+
value,
|
|
6371
|
+
unit,
|
|
6372
|
+
description,
|
|
6373
|
+
trend,
|
|
6374
|
+
icon,
|
|
6375
|
+
size = "md",
|
|
6376
|
+
type = "primary"
|
|
6377
|
+
} = props;
|
|
6378
|
+
const statusType = normalizeStatus(type);
|
|
6379
|
+
return /* @__PURE__ */ jsxs218("div", { className: clsx_default("lib-xplat-stat", size, statusType), children: [
|
|
6380
|
+
/* @__PURE__ */ jsx340("div", { className: "stat-label", children: label }),
|
|
6381
|
+
/* @__PURE__ */ jsxs218("div", { className: "stat-value-row", children: [
|
|
6382
|
+
icon && /* @__PURE__ */ jsx340("span", { className: "stat-icon", children: icon }),
|
|
6383
|
+
/* @__PURE__ */ jsx340("span", { className: "stat-value", children: value }),
|
|
6384
|
+
unit && /* @__PURE__ */ jsx340("span", { className: "stat-unit", children: unit }),
|
|
6385
|
+
trend && /* @__PURE__ */ jsxs218("span", { className: clsx_default("stat-trend", trend.direction), children: [
|
|
6386
|
+
/* @__PURE__ */ jsx340("span", { "aria-hidden": "true", children: ARROW[trend.direction] }),
|
|
6387
|
+
trend.value
|
|
6388
|
+
] })
|
|
6389
|
+
] }),
|
|
6390
|
+
description && /* @__PURE__ */ jsx340("div", { className: "stat-description", children: description })
|
|
6391
|
+
] });
|
|
6392
|
+
};
|
|
6393
|
+
Stat.displayName = "Stat";
|
|
6394
|
+
var Stat_default = Stat;
|
|
6395
|
+
|
|
6396
|
+
// src/components/Steps/Steps.tsx
|
|
6397
|
+
import { jsx as jsx341, jsxs as jsxs219 } from "react/jsx-runtime";
|
|
5443
6398
|
var Steps = (props) => {
|
|
5444
6399
|
const {
|
|
5445
6400
|
items,
|
|
@@ -5447,13 +6402,13 @@ var Steps = (props) => {
|
|
|
5447
6402
|
type = "primary"
|
|
5448
6403
|
} = props;
|
|
5449
6404
|
const statusType = normalizeStatus(type);
|
|
5450
|
-
return /* @__PURE__ */
|
|
6405
|
+
return /* @__PURE__ */ jsx341("div", { className: clsx_default("lib-xplat-steps", statusType), children: items.map((item, index) => {
|
|
5451
6406
|
const status = index < current ? "completed" : index === current ? "active" : "pending";
|
|
5452
|
-
return /* @__PURE__ */
|
|
5453
|
-
/* @__PURE__ */
|
|
5454
|
-
/* @__PURE__ */
|
|
5455
|
-
/* @__PURE__ */
|
|
5456
|
-
item.description && /* @__PURE__ */
|
|
6407
|
+
return /* @__PURE__ */ jsxs219("div", { className: clsx_default("step-item", status), children: [
|
|
6408
|
+
/* @__PURE__ */ jsx341("div", { className: "step-circle", children: status === "completed" ? /* @__PURE__ */ jsx341(CheckIcon_default, {}) : /* @__PURE__ */ jsx341("span", { children: index + 1 }) }),
|
|
6409
|
+
/* @__PURE__ */ jsxs219("div", { className: "step-content", children: [
|
|
6410
|
+
/* @__PURE__ */ jsx341("span", { className: "step-title", children: item.title }),
|
|
6411
|
+
item.description && /* @__PURE__ */ jsx341("span", { className: "step-description", children: item.description })
|
|
5457
6412
|
] })
|
|
5458
6413
|
] }, index);
|
|
5459
6414
|
}) });
|
|
@@ -5462,8 +6417,8 @@ Steps.displayName = "Steps";
|
|
|
5462
6417
|
var Steps_default = Steps;
|
|
5463
6418
|
|
|
5464
6419
|
// src/components/Swiper/Swiper.tsx
|
|
5465
|
-
import
|
|
5466
|
-
import { jsx as
|
|
6420
|
+
import React32 from "react";
|
|
6421
|
+
import { jsx as jsx342, jsxs as jsxs220 } from "react/jsx-runtime";
|
|
5467
6422
|
var Swiper = (props) => {
|
|
5468
6423
|
const {
|
|
5469
6424
|
auto = false,
|
|
@@ -5487,26 +6442,26 @@ var Swiper = (props) => {
|
|
|
5487
6442
|
const maxIndex = Math.max(0, totalSlides - viewItemCount);
|
|
5488
6443
|
const useLoop = loop && canSlide;
|
|
5489
6444
|
const cloneCount = useLoop ? totalSlides : 0;
|
|
5490
|
-
const extendedItems =
|
|
6445
|
+
const extendedItems = React32.useMemo(() => {
|
|
5491
6446
|
if (!useLoop) return items;
|
|
5492
6447
|
return [...items, ...items, ...items];
|
|
5493
6448
|
}, [items, useLoop]);
|
|
5494
6449
|
const initialIdx = Math.max(0, Math.min(indexProp ?? 0, maxIndex));
|
|
5495
|
-
const [innerIndex, setInnerIndex] =
|
|
6450
|
+
const [innerIndex, setInnerIndex] = React32.useState(
|
|
5496
6451
|
useLoop ? cloneCount + initialIdx : initialIdx
|
|
5497
6452
|
);
|
|
5498
|
-
const [isDragging, setIsDragging] =
|
|
5499
|
-
const [dragOffset, setDragOffset] =
|
|
5500
|
-
const [animated, setAnimated] =
|
|
5501
|
-
const [containerWidth, setContainerWidth] =
|
|
5502
|
-
const containerRef =
|
|
5503
|
-
const startXRef =
|
|
5504
|
-
const startTimeRef =
|
|
5505
|
-
const autoplayTimerRef =
|
|
5506
|
-
const resumeTimeoutRef =
|
|
5507
|
-
const [paused, setPaused] =
|
|
5508
|
-
const initializedRef =
|
|
5509
|
-
|
|
6453
|
+
const [isDragging, setIsDragging] = React32.useState(false);
|
|
6454
|
+
const [dragOffset, setDragOffset] = React32.useState(0);
|
|
6455
|
+
const [animated, setAnimated] = React32.useState(false);
|
|
6456
|
+
const [containerWidth, setContainerWidth] = React32.useState(0);
|
|
6457
|
+
const containerRef = React32.useRef(null);
|
|
6458
|
+
const startXRef = React32.useRef(0);
|
|
6459
|
+
const startTimeRef = React32.useRef(0);
|
|
6460
|
+
const autoplayTimerRef = React32.useRef(null);
|
|
6461
|
+
const resumeTimeoutRef = React32.useRef(null);
|
|
6462
|
+
const [paused, setPaused] = React32.useState(false);
|
|
6463
|
+
const initializedRef = React32.useRef(false);
|
|
6464
|
+
React32.useEffect(() => {
|
|
5510
6465
|
const el = containerRef.current;
|
|
5511
6466
|
if (!el) return;
|
|
5512
6467
|
const ro = new ResizeObserver((entries) => {
|
|
@@ -5529,7 +6484,7 @@ var Swiper = (props) => {
|
|
|
5529
6484
|
return ((inner - cloneCount) % totalSlides + totalSlides) % totalSlides;
|
|
5530
6485
|
};
|
|
5531
6486
|
const realIndex = getRealIndex(innerIndex);
|
|
5532
|
-
const moveToInner =
|
|
6487
|
+
const moveToInner = React32.useCallback(
|
|
5533
6488
|
(idx, withAnim = true) => {
|
|
5534
6489
|
if (!useLoop) {
|
|
5535
6490
|
setAnimated(withAnim);
|
|
@@ -5557,7 +6512,7 @@ var Swiper = (props) => {
|
|
|
5557
6512
|
},
|
|
5558
6513
|
[useLoop, cloneCount, totalSlides]
|
|
5559
6514
|
);
|
|
5560
|
-
const handleTransitionEnd =
|
|
6515
|
+
const handleTransitionEnd = React32.useCallback(() => {
|
|
5561
6516
|
if (!useLoop) return;
|
|
5562
6517
|
const real = getRealIndex(innerIndex);
|
|
5563
6518
|
const canonical = cloneCount + real;
|
|
@@ -5567,7 +6522,7 @@ var Swiper = (props) => {
|
|
|
5567
6522
|
}
|
|
5568
6523
|
onChange?.(Math.min(real, maxIndex));
|
|
5569
6524
|
}, [useLoop, innerIndex, cloneCount, totalSlides, maxIndex, onChange]);
|
|
5570
|
-
const slideTo =
|
|
6525
|
+
const slideTo = React32.useCallback(
|
|
5571
6526
|
(logicalIndex) => {
|
|
5572
6527
|
if (!canSlide) return;
|
|
5573
6528
|
const clamped = useLoop ? logicalIndex : Math.max(0, Math.min(logicalIndex, maxIndex));
|
|
@@ -5577,7 +6532,7 @@ var Swiper = (props) => {
|
|
|
5577
6532
|
},
|
|
5578
6533
|
[canSlide, useLoop, cloneCount, maxIndex, onChange, moveToInner]
|
|
5579
6534
|
);
|
|
5580
|
-
const slideNext =
|
|
6535
|
+
const slideNext = React32.useCallback(() => {
|
|
5581
6536
|
if (!canSlide) return;
|
|
5582
6537
|
const nextInner = innerIndex + slideBy;
|
|
5583
6538
|
if (useLoop) {
|
|
@@ -5586,7 +6541,7 @@ var Swiper = (props) => {
|
|
|
5586
6541
|
moveToInner(Math.min(nextInner, maxIndex), true);
|
|
5587
6542
|
}
|
|
5588
6543
|
}, [canSlide, useLoop, innerIndex, slideBy, maxIndex, moveToInner]);
|
|
5589
|
-
const slidePrev =
|
|
6544
|
+
const slidePrev = React32.useCallback(() => {
|
|
5590
6545
|
if (!canSlide) return;
|
|
5591
6546
|
const prevInner = innerIndex - slideBy;
|
|
5592
6547
|
if (useLoop) {
|
|
@@ -5595,7 +6550,7 @@ var Swiper = (props) => {
|
|
|
5595
6550
|
moveToInner(Math.max(prevInner, 0), true);
|
|
5596
6551
|
}
|
|
5597
6552
|
}, [canSlide, useLoop, innerIndex, slideBy, moveToInner]);
|
|
5598
|
-
|
|
6553
|
+
React32.useEffect(() => {
|
|
5599
6554
|
if (indexProp === void 0) return;
|
|
5600
6555
|
const clamped = Math.max(0, Math.min(indexProp, maxIndex));
|
|
5601
6556
|
const target = useLoop ? cloneCount + clamped : clamped;
|
|
@@ -5603,12 +6558,12 @@ var Swiper = (props) => {
|
|
|
5603
6558
|
moveToInner(target, true);
|
|
5604
6559
|
}
|
|
5605
6560
|
}, [indexProp]);
|
|
5606
|
-
|
|
6561
|
+
React32.useImperativeHandle(swiperRef, () => ({
|
|
5607
6562
|
slidePrev,
|
|
5608
6563
|
slideNext,
|
|
5609
6564
|
slideTo
|
|
5610
6565
|
}));
|
|
5611
|
-
|
|
6566
|
+
React32.useEffect(() => {
|
|
5612
6567
|
if (!auto || !canSlide || paused) return;
|
|
5613
6568
|
autoplayTimerRef.current = setInterval(slideNext, autoplayDelay);
|
|
5614
6569
|
return () => {
|
|
@@ -5634,7 +6589,7 @@ var Swiper = (props) => {
|
|
|
5634
6589
|
resumeTimeoutRef.current = null;
|
|
5635
6590
|
}, pauseOnInteraction);
|
|
5636
6591
|
};
|
|
5637
|
-
|
|
6592
|
+
React32.useEffect(() => {
|
|
5638
6593
|
return () => {
|
|
5639
6594
|
if (resumeTimeoutRef.current) clearTimeout(resumeTimeoutRef.current);
|
|
5640
6595
|
};
|
|
@@ -5652,7 +6607,7 @@ var Swiper = (props) => {
|
|
|
5652
6607
|
startXRef.current = getClientX(e);
|
|
5653
6608
|
startTimeRef.current = Date.now();
|
|
5654
6609
|
};
|
|
5655
|
-
|
|
6610
|
+
React32.useEffect(() => {
|
|
5656
6611
|
if (!isDragging) return;
|
|
5657
6612
|
const handleMove = (e) => {
|
|
5658
6613
|
setDragOffset(getClientX(e) - startXRef.current);
|
|
@@ -5691,8 +6646,8 @@ var Swiper = (props) => {
|
|
|
5691
6646
|
}, [isDragging, dragOffset, innerIndex, useLoop, maxIndex, slideStep, moveToInner]);
|
|
5692
6647
|
const slideWidthPercent = 100 / viewItemCount;
|
|
5693
6648
|
const gapAdjust = spaceBetween * (viewItemCount - 1) / viewItemCount;
|
|
5694
|
-
const slideElements =
|
|
5695
|
-
() => extendedItems.map((item, idx) => /* @__PURE__ */
|
|
6649
|
+
const slideElements = React32.useMemo(
|
|
6650
|
+
() => extendedItems.map((item, idx) => /* @__PURE__ */ jsx342(
|
|
5696
6651
|
"div",
|
|
5697
6652
|
{
|
|
5698
6653
|
className: "lib-xplat-swiper__slide",
|
|
@@ -5711,15 +6666,15 @@ var Swiper = (props) => {
|
|
|
5711
6666
|
Math.floor(realIndex / slideBy),
|
|
5712
6667
|
totalSteps - 1
|
|
5713
6668
|
);
|
|
5714
|
-
return /* @__PURE__ */
|
|
5715
|
-
/* @__PURE__ */
|
|
6669
|
+
return /* @__PURE__ */ jsxs220("div", { className: "lib-xplat-swiper", ref: containerRef, children: [
|
|
6670
|
+
/* @__PURE__ */ jsx342(
|
|
5716
6671
|
"div",
|
|
5717
6672
|
{
|
|
5718
6673
|
className: "lib-xplat-swiper__viewport",
|
|
5719
6674
|
onMouseDown: handleDragStart,
|
|
5720
6675
|
onTouchStart: handleDragStart,
|
|
5721
6676
|
onDragStart: (e) => e.preventDefault(),
|
|
5722
|
-
children: /* @__PURE__ */
|
|
6677
|
+
children: /* @__PURE__ */ jsx342(
|
|
5723
6678
|
"div",
|
|
5724
6679
|
{
|
|
5725
6680
|
className: clsx_default(
|
|
@@ -5737,7 +6692,7 @@ var Swiper = (props) => {
|
|
|
5737
6692
|
)
|
|
5738
6693
|
}
|
|
5739
6694
|
),
|
|
5740
|
-
showProgress && canSlide && /* @__PURE__ */
|
|
6695
|
+
showProgress && canSlide && /* @__PURE__ */ jsx342("div", { className: "lib-xplat-swiper__progress", children: /* @__PURE__ */ jsx342("div", { className: "lib-xplat-swiper__progress-track", children: /* @__PURE__ */ jsx342(
|
|
5741
6696
|
"span",
|
|
5742
6697
|
{
|
|
5743
6698
|
className: "lib-xplat-swiper__progress-fill",
|
|
@@ -5747,7 +6702,7 @@ var Swiper = (props) => {
|
|
|
5747
6702
|
}
|
|
5748
6703
|
}
|
|
5749
6704
|
) }) }),
|
|
5750
|
-
canSlide && /* @__PURE__ */
|
|
6705
|
+
canSlide && /* @__PURE__ */ jsx342("div", { className: "lib-xplat-swiper__dots", children: Array.from({ length: totalSteps }, (_, i) => /* @__PURE__ */ jsx342(
|
|
5751
6706
|
"button",
|
|
5752
6707
|
{
|
|
5753
6708
|
className: clsx_default(
|
|
@@ -5765,8 +6720,8 @@ Swiper.displayName = "Swiper";
|
|
|
5765
6720
|
var Swiper_default = Swiper;
|
|
5766
6721
|
|
|
5767
6722
|
// src/components/Switch/Switch.tsx
|
|
5768
|
-
import
|
|
5769
|
-
import { jsx as
|
|
6723
|
+
import React33 from "react";
|
|
6724
|
+
import { jsx as jsx343 } from "react/jsx-runtime";
|
|
5770
6725
|
var KNOB_TRANSITION_MS = 250;
|
|
5771
6726
|
var Switch = (props) => {
|
|
5772
6727
|
const {
|
|
@@ -5775,12 +6730,15 @@ var Switch = (props) => {
|
|
|
5775
6730
|
type = "primary",
|
|
5776
6731
|
disabled,
|
|
5777
6732
|
onChange,
|
|
5778
|
-
validations
|
|
6733
|
+
validations,
|
|
6734
|
+
label,
|
|
6735
|
+
required
|
|
5779
6736
|
} = props;
|
|
6737
|
+
const fieldId = React33.useId();
|
|
5780
6738
|
const statusType = normalizeStatus(type);
|
|
5781
|
-
const [isAnimating, setIsAnimating] =
|
|
5782
|
-
const timeoutRef =
|
|
5783
|
-
|
|
6739
|
+
const [isAnimating, setIsAnimating] = React33.useState(false);
|
|
6740
|
+
const timeoutRef = React33.useRef(null);
|
|
6741
|
+
React33.useEffect(() => {
|
|
5784
6742
|
return () => {
|
|
5785
6743
|
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
5786
6744
|
};
|
|
@@ -5795,9 +6753,10 @@ var Switch = (props) => {
|
|
|
5795
6753
|
timeoutRef.current = null;
|
|
5796
6754
|
}, KNOB_TRANSITION_MS);
|
|
5797
6755
|
};
|
|
5798
|
-
const control = /* @__PURE__ */
|
|
6756
|
+
const control = /* @__PURE__ */ jsx343(
|
|
5799
6757
|
"div",
|
|
5800
6758
|
{
|
|
6759
|
+
id: fieldId,
|
|
5801
6760
|
className: clsx_default(
|
|
5802
6761
|
"lib-xplat-switch",
|
|
5803
6762
|
size,
|
|
@@ -5809,26 +6768,26 @@ var Switch = (props) => {
|
|
|
5809
6768
|
onClick: handleClick,
|
|
5810
6769
|
"aria-invalid": hasError(validations) || void 0,
|
|
5811
6770
|
"aria-disabled": disabled || isAnimating,
|
|
5812
|
-
children: /* @__PURE__ */
|
|
6771
|
+
children: /* @__PURE__ */ jsx343("div", { className: clsx_default("knob", value ? "checked" : void 0) })
|
|
5813
6772
|
}
|
|
5814
6773
|
);
|
|
5815
|
-
return /* @__PURE__ */
|
|
6774
|
+
return /* @__PURE__ */ jsx343(Field, { validations, label, required, htmlFor: fieldId, children: control });
|
|
5816
6775
|
};
|
|
5817
6776
|
Switch.displayName = "Switch";
|
|
5818
6777
|
var Switch_default = Switch;
|
|
5819
6778
|
|
|
5820
6779
|
// src/components/Table/TableContext.tsx
|
|
5821
|
-
import
|
|
5822
|
-
var TableContext =
|
|
6780
|
+
import React34 from "react";
|
|
6781
|
+
var TableContext = React34.createContext(null);
|
|
5823
6782
|
var useTableContext = () => {
|
|
5824
|
-
const ctx =
|
|
6783
|
+
const ctx = React34.useContext(TableContext);
|
|
5825
6784
|
if (!ctx) throw new Error("Table components must be used inside <Table>");
|
|
5826
6785
|
return ctx;
|
|
5827
6786
|
};
|
|
5828
6787
|
var TableContext_default = TableContext;
|
|
5829
6788
|
|
|
5830
6789
|
// src/components/Table/Table.tsx
|
|
5831
|
-
import { jsx as
|
|
6790
|
+
import { jsx as jsx344 } from "react/jsx-runtime";
|
|
5832
6791
|
var Table = (props) => {
|
|
5833
6792
|
const {
|
|
5834
6793
|
children,
|
|
@@ -5838,7 +6797,7 @@ var Table = (props) => {
|
|
|
5838
6797
|
headerSticky = false,
|
|
5839
6798
|
stickyShadow = true
|
|
5840
6799
|
} = props;
|
|
5841
|
-
return /* @__PURE__ */
|
|
6800
|
+
return /* @__PURE__ */ jsx344("div", { className: `lib-xplat-table-wrapper ${size}`, children: /* @__PURE__ */ jsx344(
|
|
5842
6801
|
TableContext_default.Provider,
|
|
5843
6802
|
{
|
|
5844
6803
|
value: {
|
|
@@ -5847,7 +6806,7 @@ var Table = (props) => {
|
|
|
5847
6806
|
headerSticky,
|
|
5848
6807
|
stickyShadow
|
|
5849
6808
|
},
|
|
5850
|
-
children: /* @__PURE__ */
|
|
6809
|
+
children: /* @__PURE__ */ jsx344("table", { className: "lib-xplat-table", children })
|
|
5851
6810
|
}
|
|
5852
6811
|
) });
|
|
5853
6812
|
};
|
|
@@ -5855,41 +6814,41 @@ Table.displayName = "Table";
|
|
|
5855
6814
|
var Table_default = Table;
|
|
5856
6815
|
|
|
5857
6816
|
// src/components/Table/TableBody.tsx
|
|
5858
|
-
import { jsx as
|
|
6817
|
+
import { jsx as jsx345 } from "react/jsx-runtime";
|
|
5859
6818
|
var TableBody = (props) => {
|
|
5860
6819
|
const { children } = props;
|
|
5861
|
-
return /* @__PURE__ */
|
|
6820
|
+
return /* @__PURE__ */ jsx345("tbody", { children });
|
|
5862
6821
|
};
|
|
5863
6822
|
TableBody.displayName = "TableBody";
|
|
5864
6823
|
var TableBody_default = TableBody;
|
|
5865
6824
|
|
|
5866
6825
|
// src/components/Table/TableCell.tsx
|
|
5867
|
-
import
|
|
6826
|
+
import React37 from "react";
|
|
5868
6827
|
|
|
5869
6828
|
// src/components/Table/TableHeadContext.tsx
|
|
5870
|
-
import
|
|
5871
|
-
var TableHeadContext =
|
|
6829
|
+
import React35 from "react";
|
|
6830
|
+
var TableHeadContext = React35.createContext(
|
|
5872
6831
|
null
|
|
5873
6832
|
);
|
|
5874
6833
|
var useTableHeadContext = () => {
|
|
5875
|
-
const ctx =
|
|
6834
|
+
const ctx = React35.useContext(TableHeadContext);
|
|
5876
6835
|
return ctx;
|
|
5877
6836
|
};
|
|
5878
6837
|
var TableHeadContext_default = TableHeadContext;
|
|
5879
6838
|
|
|
5880
6839
|
// src/components/Table/TableRowContext.tsx
|
|
5881
|
-
import
|
|
5882
|
-
var TableRowContext =
|
|
6840
|
+
import React36 from "react";
|
|
6841
|
+
var TableRowContext = React36.createContext(null);
|
|
5883
6842
|
var useTableRowContext = () => {
|
|
5884
|
-
const ctx =
|
|
6843
|
+
const ctx = React36.useContext(TableRowContext);
|
|
5885
6844
|
if (!ctx) throw new Error("Table components must be used inside <Table>");
|
|
5886
6845
|
return ctx;
|
|
5887
6846
|
};
|
|
5888
6847
|
var TableRowContext_default = TableRowContext;
|
|
5889
6848
|
|
|
5890
6849
|
// src/components/Table/TableCell.tsx
|
|
5891
|
-
import { jsx as
|
|
5892
|
-
var TableCell =
|
|
6850
|
+
import { jsx as jsx346 } from "react/jsx-runtime";
|
|
6851
|
+
var TableCell = React37.memo((props) => {
|
|
5893
6852
|
const {
|
|
5894
6853
|
children,
|
|
5895
6854
|
align = "center",
|
|
@@ -5903,9 +6862,9 @@ var TableCell = React36.memo((props) => {
|
|
|
5903
6862
|
const { registerStickyCell, stickyCells } = useTableRowContext();
|
|
5904
6863
|
const { stickyShadow } = useTableContext();
|
|
5905
6864
|
const headContext = useTableHeadContext();
|
|
5906
|
-
const [left, setLeft] =
|
|
5907
|
-
const cellRef =
|
|
5908
|
-
const calculateLeft =
|
|
6865
|
+
const [left, setLeft] = React37.useState(0);
|
|
6866
|
+
const cellRef = React37.useRef(null);
|
|
6867
|
+
const calculateLeft = React37.useCallback(() => {
|
|
5909
6868
|
if (!cellRef.current) return 0;
|
|
5910
6869
|
let totalLeft = 0;
|
|
5911
6870
|
for (const ref of stickyCells) {
|
|
@@ -5914,7 +6873,7 @@ var TableCell = React36.memo((props) => {
|
|
|
5914
6873
|
}
|
|
5915
6874
|
return totalLeft;
|
|
5916
6875
|
}, [stickyCells]);
|
|
5917
|
-
|
|
6876
|
+
React37.useEffect(() => {
|
|
5918
6877
|
if (!isSticky || !cellRef.current) return;
|
|
5919
6878
|
registerStickyCell(cellRef);
|
|
5920
6879
|
setLeft(calculateLeft());
|
|
@@ -5933,7 +6892,7 @@ var TableCell = React36.memo((props) => {
|
|
|
5933
6892
|
const CellTag = isHeaderCell ? "th" : "td";
|
|
5934
6893
|
const isLastSticky = isSticky && stickyCells[stickyCells.length - 1] === cellRef;
|
|
5935
6894
|
const enableHover = headContext && headContext.cellHover;
|
|
5936
|
-
return /* @__PURE__ */
|
|
6895
|
+
return /* @__PURE__ */ jsx346(
|
|
5937
6896
|
CellTag,
|
|
5938
6897
|
{
|
|
5939
6898
|
ref: cellRef,
|
|
@@ -5960,21 +6919,21 @@ TableCell.displayName = "TableCell";
|
|
|
5960
6919
|
var TableCell_default = TableCell;
|
|
5961
6920
|
|
|
5962
6921
|
// src/components/Table/TableHead.tsx
|
|
5963
|
-
import { jsx as
|
|
6922
|
+
import { jsx as jsx347 } from "react/jsx-runtime";
|
|
5964
6923
|
var TableHead = ({
|
|
5965
6924
|
children,
|
|
5966
6925
|
cellHover = false
|
|
5967
6926
|
}) => {
|
|
5968
6927
|
const { headerSticky } = useTableContext();
|
|
5969
|
-
return /* @__PURE__ */
|
|
6928
|
+
return /* @__PURE__ */ jsx347(TableHeadContext_default.Provider, { value: { cellHover }, children: /* @__PURE__ */ jsx347("thead", { className: clsx_default(headerSticky ? "table-sticky" : null), children }) });
|
|
5970
6929
|
};
|
|
5971
6930
|
TableHead.displayName = "TableHead";
|
|
5972
6931
|
var TableHead_default = TableHead;
|
|
5973
6932
|
|
|
5974
6933
|
// src/components/Table/TableRow.tsx
|
|
5975
|
-
import
|
|
5976
|
-
import { jsx as
|
|
5977
|
-
var TableRow =
|
|
6934
|
+
import React38 from "react";
|
|
6935
|
+
import { jsx as jsx348 } from "react/jsx-runtime";
|
|
6936
|
+
var TableRow = React38.memo((props) => {
|
|
5978
6937
|
const {
|
|
5979
6938
|
children,
|
|
5980
6939
|
type = "secondary",
|
|
@@ -5983,14 +6942,14 @@ var TableRow = React37.memo((props) => {
|
|
|
5983
6942
|
onClick
|
|
5984
6943
|
} = props;
|
|
5985
6944
|
const { rowBorderUse } = useTableContext();
|
|
5986
|
-
const [stickyCells, setStickyCells] =
|
|
6945
|
+
const [stickyCells, setStickyCells] = React38.useState([]);
|
|
5987
6946
|
const registerStickyCell = (ref) => {
|
|
5988
6947
|
setStickyCells((prev) => {
|
|
5989
6948
|
if (prev.includes(ref)) return prev;
|
|
5990
6949
|
return [...prev, ref];
|
|
5991
6950
|
});
|
|
5992
6951
|
};
|
|
5993
|
-
return /* @__PURE__ */
|
|
6952
|
+
return /* @__PURE__ */ jsx348(TableRowContext_default.Provider, { value: { stickyCells, registerStickyCell }, children: /* @__PURE__ */ jsx348(
|
|
5994
6953
|
"tr",
|
|
5995
6954
|
{
|
|
5996
6955
|
className: clsx_default(
|
|
@@ -6014,7 +6973,7 @@ TableRow.displayName = "TableRow";
|
|
|
6014
6973
|
var TableRow_default = TableRow;
|
|
6015
6974
|
|
|
6016
6975
|
// src/components/Tag/Tag.tsx
|
|
6017
|
-
import { jsx as
|
|
6976
|
+
import { jsx as jsx349, jsxs as jsxs221 } from "react/jsx-runtime";
|
|
6018
6977
|
var Tag = (props) => {
|
|
6019
6978
|
const {
|
|
6020
6979
|
children,
|
|
@@ -6026,7 +6985,7 @@ var Tag = (props) => {
|
|
|
6026
6985
|
colorIndex
|
|
6027
6986
|
} = props;
|
|
6028
6987
|
const shape = variant ?? type ?? "neutral";
|
|
6029
|
-
return /* @__PURE__ */
|
|
6988
|
+
return /* @__PURE__ */ jsxs221(
|
|
6030
6989
|
"span",
|
|
6031
6990
|
{
|
|
6032
6991
|
className: clsx_default(
|
|
@@ -6037,8 +6996,8 @@ var Tag = (props) => {
|
|
|
6037
6996
|
disabled && "disabled"
|
|
6038
6997
|
),
|
|
6039
6998
|
children: [
|
|
6040
|
-
/* @__PURE__ */
|
|
6041
|
-
onClose && /* @__PURE__ */
|
|
6999
|
+
/* @__PURE__ */ jsx349("span", { className: "tag-label", children }),
|
|
7000
|
+
onClose && /* @__PURE__ */ jsx349("button", { className: "tag-close", onClick: onClose, "aria-label": "\uC0AD\uC81C", disabled, children: /* @__PURE__ */ jsx349(XIcon_default, {}) })
|
|
6042
7001
|
]
|
|
6043
7002
|
}
|
|
6044
7003
|
);
|
|
@@ -6047,24 +7006,29 @@ Tag.displayName = "Tag";
|
|
|
6047
7006
|
var Tag_default = Tag;
|
|
6048
7007
|
|
|
6049
7008
|
// src/components/TextArea/TextArea.tsx
|
|
6050
|
-
import
|
|
6051
|
-
import { jsx as
|
|
6052
|
-
var TextArea =
|
|
7009
|
+
import React39 from "react";
|
|
7010
|
+
import { jsx as jsx350 } from "react/jsx-runtime";
|
|
7011
|
+
var TextArea = React39.forwardRef(
|
|
6053
7012
|
(props, ref) => {
|
|
6054
7013
|
const {
|
|
6055
7014
|
className,
|
|
6056
7015
|
size = "md",
|
|
6057
7016
|
validations,
|
|
7017
|
+
label,
|
|
7018
|
+
required,
|
|
6058
7019
|
resize = "vertical",
|
|
6059
7020
|
rows = 3,
|
|
6060
7021
|
disabled,
|
|
6061
7022
|
...textareaProps
|
|
6062
7023
|
} = props;
|
|
6063
|
-
const
|
|
7024
|
+
const autoId = React39.useId();
|
|
7025
|
+
const fieldId = props.id ?? autoId;
|
|
7026
|
+
const control = /* @__PURE__ */ jsx350("div", { className: clsx_default("lib-xplat-textarea-wrap", className), children: /* @__PURE__ */ jsx350(
|
|
6064
7027
|
"textarea",
|
|
6065
7028
|
{
|
|
6066
7029
|
...textareaProps,
|
|
6067
7030
|
ref,
|
|
7031
|
+
id: fieldId,
|
|
6068
7032
|
rows,
|
|
6069
7033
|
disabled,
|
|
6070
7034
|
"aria-invalid": hasError(validations) || void 0,
|
|
@@ -6072,32 +7036,166 @@ var TextArea = React38.forwardRef(
|
|
|
6072
7036
|
style: { resize }
|
|
6073
7037
|
}
|
|
6074
7038
|
) });
|
|
6075
|
-
return /* @__PURE__ */
|
|
7039
|
+
return /* @__PURE__ */ jsx350(Field, { validations, label, required, htmlFor: fieldId, children: control });
|
|
6076
7040
|
}
|
|
6077
7041
|
);
|
|
6078
7042
|
TextArea.displayName = "TextArea";
|
|
6079
7043
|
var TextArea_default = TextArea;
|
|
6080
7044
|
|
|
7045
|
+
// src/components/TimePicker/TimePicker.tsx
|
|
7046
|
+
import React40 from "react";
|
|
7047
|
+
import { jsx as jsx351, jsxs as jsxs222 } from "react/jsx-runtime";
|
|
7048
|
+
var ANIMATION_DURATION_MS4 = 200;
|
|
7049
|
+
var toMinutes = (hhmm) => {
|
|
7050
|
+
if (!hhmm) return null;
|
|
7051
|
+
const m = /^(\d{1,2}):(\d{2})$/.exec(hhmm.trim());
|
|
7052
|
+
if (!m) return null;
|
|
7053
|
+
const h = Number(m[1]);
|
|
7054
|
+
const min = Number(m[2]);
|
|
7055
|
+
if (h > 23 || min > 59) return null;
|
|
7056
|
+
return h * 60 + min;
|
|
7057
|
+
};
|
|
7058
|
+
var toHHmm = (minutes) => `${String(Math.floor(minutes / 60)).padStart(2, "0")}:${String(minutes % 60).padStart(2, "0")}`;
|
|
7059
|
+
var display = (hhmm, use12Hours) => {
|
|
7060
|
+
if (!use12Hours) return hhmm;
|
|
7061
|
+
const total = toMinutes(hhmm);
|
|
7062
|
+
if (total === null) return hhmm;
|
|
7063
|
+
const h24 = Math.floor(total / 60);
|
|
7064
|
+
const mm = String(total % 60).padStart(2, "0");
|
|
7065
|
+
const period = h24 < 12 ? "\uC624\uC804" : "\uC624\uD6C4";
|
|
7066
|
+
const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
|
|
7067
|
+
return `${period} ${h12}:${mm}`;
|
|
7068
|
+
};
|
|
7069
|
+
var TimePicker = (props) => {
|
|
7070
|
+
const {
|
|
7071
|
+
value,
|
|
7072
|
+
onChange,
|
|
7073
|
+
step = 30,
|
|
7074
|
+
min,
|
|
7075
|
+
max,
|
|
7076
|
+
use12Hours = false,
|
|
7077
|
+
placeholder = "\uC2DC\uAC01 \uC120\uD0DD",
|
|
7078
|
+
disabled = false,
|
|
7079
|
+
size = "md",
|
|
7080
|
+
label,
|
|
7081
|
+
required,
|
|
7082
|
+
validations
|
|
7083
|
+
} = props;
|
|
7084
|
+
const fieldId = React40.useId();
|
|
7085
|
+
const triggerRef = React40.useRef(null);
|
|
7086
|
+
const contentRef = React40.useRef(null);
|
|
7087
|
+
const [isOpen, setOpen] = React40.useState(false);
|
|
7088
|
+
const [mounted, setMounted] = React40.useState(false);
|
|
7089
|
+
const [visible, setVisible] = React40.useState(false);
|
|
7090
|
+
const options = React40.useMemo(() => {
|
|
7091
|
+
const safeStep = step > 0 && step <= 720 ? step : 30;
|
|
7092
|
+
const lo = toMinutes(min) ?? 0;
|
|
7093
|
+
const hi = toMinutes(max) ?? 24 * 60 - 1;
|
|
7094
|
+
const out = [];
|
|
7095
|
+
for (let t = lo; t <= hi; t += safeStep) out.push(toHHmm(t));
|
|
7096
|
+
return out;
|
|
7097
|
+
}, [step, min, max]);
|
|
7098
|
+
const close = React40.useCallback(() => setOpen(false), []);
|
|
7099
|
+
useClickOutside_default([triggerRef, contentRef], close, isOpen);
|
|
7100
|
+
useEscapeKey(isOpen, () => {
|
|
7101
|
+
close();
|
|
7102
|
+
triggerRef.current?.focus({ preventScroll: true });
|
|
7103
|
+
});
|
|
7104
|
+
const position = useAutoPosition_default(triggerRef, contentRef, mounted);
|
|
7105
|
+
React40.useEffect(() => {
|
|
7106
|
+
if (disabled && isOpen) setOpen(false);
|
|
7107
|
+
}, [disabled, isOpen]);
|
|
7108
|
+
React40.useEffect(() => {
|
|
7109
|
+
if (isOpen) {
|
|
7110
|
+
setMounted(true);
|
|
7111
|
+
const t2 = setTimeout(() => setVisible(true), 1);
|
|
7112
|
+
return () => clearTimeout(t2);
|
|
7113
|
+
}
|
|
7114
|
+
setVisible(false);
|
|
7115
|
+
const t = setTimeout(() => setMounted(false), ANIMATION_DURATION_MS4);
|
|
7116
|
+
return () => clearTimeout(t);
|
|
7117
|
+
}, [isOpen]);
|
|
7118
|
+
const pick = (hhmm) => {
|
|
7119
|
+
onChange?.(hhmm);
|
|
7120
|
+
close();
|
|
7121
|
+
triggerRef.current?.focus({ preventScroll: true });
|
|
7122
|
+
};
|
|
7123
|
+
const control = /* @__PURE__ */ jsxs222("div", { className: clsx_default("lib-xplat-time-picker", size, disabled && "disabled"), children: [
|
|
7124
|
+
/* @__PURE__ */ jsx351(
|
|
7125
|
+
"div",
|
|
7126
|
+
{
|
|
7127
|
+
id: fieldId,
|
|
7128
|
+
ref: triggerRef,
|
|
7129
|
+
className: clsx_default("time-picker-trigger", hasError(validations) && "error"),
|
|
7130
|
+
role: "combobox",
|
|
7131
|
+
"aria-expanded": isOpen,
|
|
7132
|
+
"aria-haspopup": "listbox",
|
|
7133
|
+
"aria-invalid": hasError(validations) || void 0,
|
|
7134
|
+
tabIndex: disabled ? void 0 : 0,
|
|
7135
|
+
onClick: () => !disabled && setOpen((p) => !p),
|
|
7136
|
+
onKeyDown: (e) => {
|
|
7137
|
+
if (disabled) return;
|
|
7138
|
+
if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") {
|
|
7139
|
+
e.preventDefault();
|
|
7140
|
+
setOpen(true);
|
|
7141
|
+
}
|
|
7142
|
+
},
|
|
7143
|
+
children: /* @__PURE__ */ jsx351("span", { className: clsx_default("time-picker-value", !value && "placeholder"), children: value ? display(value, use12Hours) : placeholder })
|
|
7144
|
+
}
|
|
7145
|
+
),
|
|
7146
|
+
mounted && /* @__PURE__ */ jsx351(Portal_default, { children: /* @__PURE__ */ jsx351(
|
|
7147
|
+
"div",
|
|
7148
|
+
{
|
|
7149
|
+
ref: contentRef,
|
|
7150
|
+
className: clsx_default("lib-xplat-time-picker-content", size, visible ? "enter" : "exit", position.repositioning && "repositioning"),
|
|
7151
|
+
style: { ...position.position, width: triggerRef.current?.offsetWidth },
|
|
7152
|
+
role: "listbox",
|
|
7153
|
+
children: options.map((t) => /* @__PURE__ */ jsx351(
|
|
7154
|
+
"div",
|
|
7155
|
+
{
|
|
7156
|
+
className: clsx_default("time-picker-item", t === value && "is-selected"),
|
|
7157
|
+
role: "option",
|
|
7158
|
+
"aria-selected": t === value,
|
|
7159
|
+
tabIndex: 0,
|
|
7160
|
+
onClick: () => pick(t),
|
|
7161
|
+
onKeyDown: (e) => {
|
|
7162
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
7163
|
+
e.preventDefault();
|
|
7164
|
+
pick(t);
|
|
7165
|
+
}
|
|
7166
|
+
},
|
|
7167
|
+
children: display(t, use12Hours)
|
|
7168
|
+
},
|
|
7169
|
+
t
|
|
7170
|
+
))
|
|
7171
|
+
}
|
|
7172
|
+
) })
|
|
7173
|
+
] });
|
|
7174
|
+
return /* @__PURE__ */ jsx351(Field, { validations, label, required, htmlFor: fieldId, children: control });
|
|
7175
|
+
};
|
|
7176
|
+
TimePicker.displayName = "TimePicker";
|
|
7177
|
+
var TimePicker_default = TimePicker;
|
|
7178
|
+
|
|
6081
7179
|
// src/components/Toast/Toast.tsx
|
|
6082
|
-
import
|
|
7180
|
+
import React41 from "react";
|
|
6083
7181
|
import { createPortal as createPortal3 } from "react-dom";
|
|
6084
|
-
import { jsx as
|
|
6085
|
-
var ToastContext =
|
|
7182
|
+
import { jsx as jsx352, jsxs as jsxs223 } from "react/jsx-runtime";
|
|
7183
|
+
var ToastContext = React41.createContext(null);
|
|
6086
7184
|
var useToast = () => {
|
|
6087
|
-
const ctx =
|
|
7185
|
+
const ctx = React41.useContext(ToastContext);
|
|
6088
7186
|
if (!ctx) throw new Error("useToast must be used within ToastProvider");
|
|
6089
7187
|
return ctx;
|
|
6090
7188
|
};
|
|
6091
7189
|
var EXIT_DURATION = 300;
|
|
6092
7190
|
var ToastItemComponent = ({ item, isExiting, onClose }) => {
|
|
6093
|
-
const ref =
|
|
6094
|
-
const [height, setHeight] =
|
|
6095
|
-
|
|
7191
|
+
const ref = React41.useRef(null);
|
|
7192
|
+
const [height, setHeight] = React41.useState(void 0);
|
|
7193
|
+
React41.useEffect(() => {
|
|
6096
7194
|
if (ref.current && !isExiting) {
|
|
6097
7195
|
setHeight(ref.current.offsetHeight);
|
|
6098
7196
|
}
|
|
6099
7197
|
}, [isExiting]);
|
|
6100
|
-
return /* @__PURE__ */
|
|
7198
|
+
return /* @__PURE__ */ jsx352(
|
|
6101
7199
|
"div",
|
|
6102
7200
|
{
|
|
6103
7201
|
className: clsx_default("lib-xplat-toast-wrapper", { exit: isExiting }),
|
|
@@ -6105,15 +7203,15 @@ var ToastItemComponent = ({ item, isExiting, onClose }) => {
|
|
|
6105
7203
|
maxHeight: isExiting ? 0 : height ?? "none",
|
|
6106
7204
|
marginBottom: isExiting ? 0 : void 0
|
|
6107
7205
|
},
|
|
6108
|
-
children: /* @__PURE__ */
|
|
7206
|
+
children: /* @__PURE__ */ jsxs223(
|
|
6109
7207
|
"div",
|
|
6110
7208
|
{
|
|
6111
7209
|
ref,
|
|
6112
7210
|
className: clsx_default("lib-xplat-toast", item.type, { exit: isExiting }),
|
|
6113
7211
|
role: "alert",
|
|
6114
7212
|
children: [
|
|
6115
|
-
/* @__PURE__ */
|
|
6116
|
-
/* @__PURE__ */
|
|
7213
|
+
/* @__PURE__ */ jsx352("span", { className: "message", children: item.message }),
|
|
7214
|
+
/* @__PURE__ */ jsx352("button", { className: "close-btn", onClick: onClose, "aria-label": "\uB2EB\uAE30", children: "\xD7" })
|
|
6117
7215
|
]
|
|
6118
7216
|
}
|
|
6119
7217
|
)
|
|
@@ -6124,13 +7222,13 @@ var ToastProvider = ({
|
|
|
6124
7222
|
children,
|
|
6125
7223
|
position = "top-right"
|
|
6126
7224
|
}) => {
|
|
6127
|
-
const [toasts, setToasts] =
|
|
6128
|
-
const [removing, setRemoving] =
|
|
6129
|
-
const [mounted, setMounted] =
|
|
6130
|
-
|
|
7225
|
+
const [toasts, setToasts] = React41.useState([]);
|
|
7226
|
+
const [removing, setRemoving] = React41.useState(/* @__PURE__ */ new Set());
|
|
7227
|
+
const [mounted, setMounted] = React41.useState(false);
|
|
7228
|
+
React41.useEffect(() => {
|
|
6131
7229
|
setMounted(true);
|
|
6132
7230
|
}, []);
|
|
6133
|
-
const remove =
|
|
7231
|
+
const remove = React41.useCallback((id) => {
|
|
6134
7232
|
setRemoving((prev) => new Set(prev).add(id));
|
|
6135
7233
|
setTimeout(() => {
|
|
6136
7234
|
setToasts((prev) => prev.filter((t) => t.id !== id));
|
|
@@ -6141,7 +7239,7 @@ var ToastProvider = ({
|
|
|
6141
7239
|
});
|
|
6142
7240
|
}, EXIT_DURATION);
|
|
6143
7241
|
}, []);
|
|
6144
|
-
const toast =
|
|
7242
|
+
const toast = React41.useCallback(
|
|
6145
7243
|
(type, message, duration = 3e3) => {
|
|
6146
7244
|
const id = `${Date.now()}-${Math.random()}`;
|
|
6147
7245
|
setToasts((prev) => [...prev, { id, type, message }]);
|
|
@@ -6151,10 +7249,10 @@ var ToastProvider = ({
|
|
|
6151
7249
|
},
|
|
6152
7250
|
[remove]
|
|
6153
7251
|
);
|
|
6154
|
-
return /* @__PURE__ */
|
|
7252
|
+
return /* @__PURE__ */ jsxs223(ToastContext.Provider, { value: { toast }, children: [
|
|
6155
7253
|
children,
|
|
6156
7254
|
mounted && createPortal3(
|
|
6157
|
-
/* @__PURE__ */
|
|
7255
|
+
/* @__PURE__ */ jsx352("div", { className: clsx_default("lib-xplat-toast-container", position), children: toasts.map((t) => /* @__PURE__ */ jsx352(
|
|
6158
7256
|
ToastItemComponent,
|
|
6159
7257
|
{
|
|
6160
7258
|
item: t,
|
|
@@ -6170,8 +7268,8 @@ var ToastProvider = ({
|
|
|
6170
7268
|
ToastProvider.displayName = "ToastProvider";
|
|
6171
7269
|
|
|
6172
7270
|
// src/components/Tooltip/Tooltip.tsx
|
|
6173
|
-
import
|
|
6174
|
-
import { Fragment as Fragment6, jsx as
|
|
7271
|
+
import React42 from "react";
|
|
7272
|
+
import { Fragment as Fragment6, jsx as jsx353, jsxs as jsxs224 } from "react/jsx-runtime";
|
|
6175
7273
|
var OFFSET = 12;
|
|
6176
7274
|
var GAP = 8;
|
|
6177
7275
|
var SHOW_DELAY = 300;
|
|
@@ -6186,14 +7284,14 @@ var Tooltip = (props) => {
|
|
|
6186
7284
|
disabled = false
|
|
6187
7285
|
} = props;
|
|
6188
7286
|
const shape = variant ?? type ?? "dark";
|
|
6189
|
-
const triggerRef =
|
|
6190
|
-
const tooltipRef =
|
|
6191
|
-
const [visible, setVisible] =
|
|
6192
|
-
const [pos, setPos] =
|
|
6193
|
-
const delayTimer =
|
|
6194
|
-
const rafRef =
|
|
6195
|
-
const cursor =
|
|
6196
|
-
const clamp =
|
|
7287
|
+
const triggerRef = React42.useRef(null);
|
|
7288
|
+
const tooltipRef = React42.useRef(null);
|
|
7289
|
+
const [visible, setVisible] = React42.useState(false);
|
|
7290
|
+
const [pos, setPos] = React42.useState({ left: 0, top: 0 });
|
|
7291
|
+
const delayTimer = React42.useRef(0);
|
|
7292
|
+
const rafRef = React42.useRef(0);
|
|
7293
|
+
const cursor = React42.useRef(null);
|
|
7294
|
+
const clamp = React42.useCallback((left, top, w, h) => {
|
|
6197
7295
|
const vw = window.innerWidth;
|
|
6198
7296
|
const vh = window.innerHeight;
|
|
6199
7297
|
return {
|
|
@@ -6201,7 +7299,7 @@ var Tooltip = (props) => {
|
|
|
6201
7299
|
top: Math.min(Math.max(GAP, top), Math.max(GAP, vh - h - GAP))
|
|
6202
7300
|
};
|
|
6203
7301
|
}, []);
|
|
6204
|
-
const placeAtCursor =
|
|
7302
|
+
const placeAtCursor = React42.useCallback((x, y) => {
|
|
6205
7303
|
const el = tooltipRef.current;
|
|
6206
7304
|
if (!el) return;
|
|
6207
7305
|
const w = el.offsetWidth;
|
|
@@ -6212,7 +7310,7 @@ var Tooltip = (props) => {
|
|
|
6212
7310
|
if (top < GAP) top = y + OFFSET;
|
|
6213
7311
|
setPos(clamp(left, top, w, h));
|
|
6214
7312
|
}, [clamp]);
|
|
6215
|
-
const placeAtTrigger =
|
|
7313
|
+
const placeAtTrigger = React42.useCallback(() => {
|
|
6216
7314
|
const el = tooltipRef.current;
|
|
6217
7315
|
const trigger = triggerRef.current;
|
|
6218
7316
|
if (!el || !trigger) return;
|
|
@@ -6224,19 +7322,19 @@ var Tooltip = (props) => {
|
|
|
6224
7322
|
const left = rect.left + rect.width / 2 - w / 2;
|
|
6225
7323
|
setPos(clamp(left, top, w, h));
|
|
6226
7324
|
}, [clamp]);
|
|
6227
|
-
const reposition =
|
|
7325
|
+
const reposition = React42.useCallback(() => {
|
|
6228
7326
|
if (follow && cursor.current) {
|
|
6229
7327
|
placeAtCursor(cursor.current.x, cursor.current.y);
|
|
6230
7328
|
} else {
|
|
6231
7329
|
placeAtTrigger();
|
|
6232
7330
|
}
|
|
6233
7331
|
}, [follow, placeAtCursor, placeAtTrigger]);
|
|
6234
|
-
const handleMouseEnter =
|
|
7332
|
+
const handleMouseEnter = React42.useCallback((e) => {
|
|
6235
7333
|
if (disabled) return;
|
|
6236
7334
|
cursor.current = { x: e.clientX, y: e.clientY };
|
|
6237
7335
|
delayTimer.current = window.setTimeout(() => setVisible(true), SHOW_DELAY);
|
|
6238
7336
|
}, [disabled]);
|
|
6239
|
-
const handleMouseMove =
|
|
7337
|
+
const handleMouseMove = React42.useCallback((e) => {
|
|
6240
7338
|
cursor.current = { x: e.clientX, y: e.clientY };
|
|
6241
7339
|
if (!visible || !follow) return;
|
|
6242
7340
|
cancelAnimationFrame(rafRef.current);
|
|
@@ -6244,25 +7342,25 @@ var Tooltip = (props) => {
|
|
|
6244
7342
|
if (cursor.current) placeAtCursor(cursor.current.x, cursor.current.y);
|
|
6245
7343
|
});
|
|
6246
7344
|
}, [visible, follow, placeAtCursor]);
|
|
6247
|
-
const close =
|
|
7345
|
+
const close = React42.useCallback(() => {
|
|
6248
7346
|
window.clearTimeout(delayTimer.current);
|
|
6249
7347
|
cancelAnimationFrame(rafRef.current);
|
|
6250
7348
|
setVisible(false);
|
|
6251
7349
|
}, []);
|
|
6252
|
-
const handleMouseLeave =
|
|
7350
|
+
const handleMouseLeave = React42.useCallback(() => {
|
|
6253
7351
|
cursor.current = null;
|
|
6254
7352
|
close();
|
|
6255
7353
|
}, [close]);
|
|
6256
|
-
const handleFocus =
|
|
7354
|
+
const handleFocus = React42.useCallback(() => {
|
|
6257
7355
|
if (disabled) return;
|
|
6258
7356
|
cursor.current = null;
|
|
6259
7357
|
setVisible(true);
|
|
6260
7358
|
}, [disabled]);
|
|
6261
|
-
|
|
7359
|
+
React42.useLayoutEffect(() => {
|
|
6262
7360
|
if (!visible) return;
|
|
6263
7361
|
reposition();
|
|
6264
7362
|
}, [visible, reposition]);
|
|
6265
|
-
|
|
7363
|
+
React42.useEffect(() => {
|
|
6266
7364
|
if (!visible || follow) return;
|
|
6267
7365
|
const onChange = () => placeAtTrigger();
|
|
6268
7366
|
window.addEventListener("scroll", onChange, true);
|
|
@@ -6272,12 +7370,12 @@ var Tooltip = (props) => {
|
|
|
6272
7370
|
window.removeEventListener("resize", onChange);
|
|
6273
7371
|
};
|
|
6274
7372
|
}, [visible, follow, placeAtTrigger]);
|
|
6275
|
-
|
|
7373
|
+
React42.useEffect(() => () => {
|
|
6276
7374
|
window.clearTimeout(delayTimer.current);
|
|
6277
7375
|
cancelAnimationFrame(rafRef.current);
|
|
6278
7376
|
}, []);
|
|
6279
|
-
if (!title && !description) return /* @__PURE__ */
|
|
6280
|
-
return /* @__PURE__ */
|
|
7377
|
+
if (!title && !description) return /* @__PURE__ */ jsx353(Fragment6, { children });
|
|
7378
|
+
return /* @__PURE__ */ jsxs224(
|
|
6281
7379
|
"div",
|
|
6282
7380
|
{
|
|
6283
7381
|
ref: triggerRef,
|
|
@@ -6290,7 +7388,7 @@ var Tooltip = (props) => {
|
|
|
6290
7388
|
onBlur: close,
|
|
6291
7389
|
children: [
|
|
6292
7390
|
children,
|
|
6293
|
-
visible && /* @__PURE__ */
|
|
7391
|
+
visible && /* @__PURE__ */ jsx353(Portal_default, { children: /* @__PURE__ */ jsxs224(
|
|
6294
7392
|
"div",
|
|
6295
7393
|
{
|
|
6296
7394
|
ref: tooltipRef,
|
|
@@ -6298,8 +7396,8 @@ var Tooltip = (props) => {
|
|
|
6298
7396
|
className: clsx_default("lib-xplat-tooltip", shape),
|
|
6299
7397
|
style: { position: "fixed", left: pos.left, top: pos.top },
|
|
6300
7398
|
children: [
|
|
6301
|
-
title && /* @__PURE__ */
|
|
6302
|
-
description && /* @__PURE__ */
|
|
7399
|
+
title && /* @__PURE__ */ jsx353("div", { className: "tooltip-title", children: title }),
|
|
7400
|
+
description && /* @__PURE__ */ jsx353("div", { className: "tooltip-desc", children: description })
|
|
6303
7401
|
]
|
|
6304
7402
|
}
|
|
6305
7403
|
) })
|
|
@@ -6311,11 +7409,11 @@ Tooltip.displayName = "Tooltip";
|
|
|
6311
7409
|
var Tooltip_default = Tooltip;
|
|
6312
7410
|
|
|
6313
7411
|
// src/components/Video/Video.tsx
|
|
6314
|
-
import
|
|
6315
|
-
import { jsx as
|
|
6316
|
-
var PipIcon = () => /* @__PURE__ */
|
|
6317
|
-
/* @__PURE__ */
|
|
6318
|
-
/* @__PURE__ */
|
|
7412
|
+
import React43 from "react";
|
|
7413
|
+
import { jsx as jsx354, jsxs as jsxs225 } from "react/jsx-runtime";
|
|
7414
|
+
var PipIcon = () => /* @__PURE__ */ jsxs225("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
|
|
7415
|
+
/* @__PURE__ */ jsx354("rect", { x: "3", y: "5", width: "18", height: "14", rx: "2" }),
|
|
7416
|
+
/* @__PURE__ */ jsx354("rect", { x: "12", y: "11", width: "7", height: "6", rx: "1", fill: "currentColor" })
|
|
6319
7417
|
] });
|
|
6320
7418
|
var formatTime = (sec) => {
|
|
6321
7419
|
if (!Number.isFinite(sec) || sec < 0) return "0:00";
|
|
@@ -6323,7 +7421,7 @@ var formatTime = (sec) => {
|
|
|
6323
7421
|
const s = Math.floor(sec % 60);
|
|
6324
7422
|
return `${m}:${s.toString().padStart(2, "0")}`;
|
|
6325
7423
|
};
|
|
6326
|
-
var Video =
|
|
7424
|
+
var Video = React43.forwardRef((props, ref) => {
|
|
6327
7425
|
const {
|
|
6328
7426
|
src,
|
|
6329
7427
|
poster,
|
|
@@ -6347,21 +7445,21 @@ var Video = React41.forwardRef((props, ref) => {
|
|
|
6347
7445
|
children,
|
|
6348
7446
|
...rest
|
|
6349
7447
|
} = props;
|
|
6350
|
-
const containerRef =
|
|
6351
|
-
const videoRef =
|
|
6352
|
-
const [isPlaying, setIsPlaying] =
|
|
6353
|
-
const [isLoaded, setIsLoaded] =
|
|
6354
|
-
const [currentTime, setCurrentTime] =
|
|
6355
|
-
const [duration, setDuration] =
|
|
6356
|
-
const [buffered, setBuffered] =
|
|
6357
|
-
const [volume, setVolume] =
|
|
6358
|
-
const [isMuted, setIsMuted] =
|
|
6359
|
-
const [isFullscreen, setIsFullscreen] =
|
|
6360
|
-
const [playbackRate, setPlaybackRate] =
|
|
6361
|
-
const [rateMenuOpen, setRateMenuOpen] =
|
|
6362
|
-
const [captionsOn, setCaptionsOn] =
|
|
6363
|
-
const [isPip, setIsPip] =
|
|
6364
|
-
const setRefs =
|
|
7448
|
+
const containerRef = React43.useRef(null);
|
|
7449
|
+
const videoRef = React43.useRef(null);
|
|
7450
|
+
const [isPlaying, setIsPlaying] = React43.useState(Boolean(autoPlay));
|
|
7451
|
+
const [isLoaded, setIsLoaded] = React43.useState(false);
|
|
7452
|
+
const [currentTime, setCurrentTime] = React43.useState(0);
|
|
7453
|
+
const [duration, setDuration] = React43.useState(0);
|
|
7454
|
+
const [buffered, setBuffered] = React43.useState(0);
|
|
7455
|
+
const [volume, setVolume] = React43.useState(1);
|
|
7456
|
+
const [isMuted, setIsMuted] = React43.useState(Boolean(muted));
|
|
7457
|
+
const [isFullscreen, setIsFullscreen] = React43.useState(false);
|
|
7458
|
+
const [playbackRate, setPlaybackRate] = React43.useState(1);
|
|
7459
|
+
const [rateMenuOpen, setRateMenuOpen] = React43.useState(false);
|
|
7460
|
+
const [captionsOn, setCaptionsOn] = React43.useState(false);
|
|
7461
|
+
const [isPip, setIsPip] = React43.useState(false);
|
|
7462
|
+
const setRefs = React43.useCallback(
|
|
6365
7463
|
(el) => {
|
|
6366
7464
|
videoRef.current = el;
|
|
6367
7465
|
if (typeof ref === "function") ref(el);
|
|
@@ -6369,14 +7467,14 @@ var Video = React41.forwardRef((props, ref) => {
|
|
|
6369
7467
|
},
|
|
6370
7468
|
[ref]
|
|
6371
7469
|
);
|
|
6372
|
-
|
|
7470
|
+
React43.useEffect(() => {
|
|
6373
7471
|
const onFsChange = () => {
|
|
6374
7472
|
setIsFullscreen(document.fullscreenElement === containerRef.current);
|
|
6375
7473
|
};
|
|
6376
7474
|
document.addEventListener("fullscreenchange", onFsChange);
|
|
6377
7475
|
return () => document.removeEventListener("fullscreenchange", onFsChange);
|
|
6378
7476
|
}, []);
|
|
6379
|
-
|
|
7477
|
+
React43.useEffect(() => {
|
|
6380
7478
|
const v = videoRef.current;
|
|
6381
7479
|
if (!v) return;
|
|
6382
7480
|
const onEnter = () => setIsPip(true);
|
|
@@ -6490,13 +7588,13 @@ var Video = React41.forwardRef((props, ref) => {
|
|
|
6490
7588
|
const volumePct = (isMuted ? 0 : volume) * 100;
|
|
6491
7589
|
const VolumeGlyph = isMuted || volume === 0 ? VolumeXIcon_default : volume < 0.5 ? VolumeIcon_default : Volume2Icon_default;
|
|
6492
7590
|
const pipSupported = typeof document !== "undefined" && "pictureInPictureEnabled" in document && document.pictureInPictureEnabled;
|
|
6493
|
-
return /* @__PURE__ */
|
|
7591
|
+
return /* @__PURE__ */ jsxs225(
|
|
6494
7592
|
"div",
|
|
6495
7593
|
{
|
|
6496
7594
|
ref: containerRef,
|
|
6497
7595
|
className: clsx_default("lib-xplat-video", showControls && "has-controls"),
|
|
6498
7596
|
children: [
|
|
6499
|
-
/* @__PURE__ */
|
|
7597
|
+
/* @__PURE__ */ jsx354(
|
|
6500
7598
|
"video",
|
|
6501
7599
|
{
|
|
6502
7600
|
ref: setRefs,
|
|
@@ -6517,7 +7615,7 @@ var Video = React41.forwardRef((props, ref) => {
|
|
|
6517
7615
|
children
|
|
6518
7616
|
}
|
|
6519
7617
|
),
|
|
6520
|
-
showCenterPlay && /* @__PURE__ */
|
|
7618
|
+
showCenterPlay && /* @__PURE__ */ jsx354(
|
|
6521
7619
|
"button",
|
|
6522
7620
|
{
|
|
6523
7621
|
type: "button",
|
|
@@ -6529,11 +7627,11 @@ var Video = React41.forwardRef((props, ref) => {
|
|
|
6529
7627
|
onClick: togglePlay,
|
|
6530
7628
|
"aria-label": isPlaying ? "\uC77C\uC2DC\uC815\uC9C0" : "\uC7AC\uC0DD",
|
|
6531
7629
|
tabIndex: -1,
|
|
6532
|
-
children: /* @__PURE__ */
|
|
7630
|
+
children: /* @__PURE__ */ jsx354("span", { className: "center-play-icon", children: /* @__PURE__ */ jsx354(PlayCircleIcon_default, {}) })
|
|
6533
7631
|
}
|
|
6534
7632
|
),
|
|
6535
|
-
showControls && /* @__PURE__ */
|
|
6536
|
-
/* @__PURE__ */
|
|
7633
|
+
showControls && /* @__PURE__ */ jsxs225("div", { className: "controls", onClick: (e) => e.stopPropagation(), children: [
|
|
7634
|
+
/* @__PURE__ */ jsx354(
|
|
6537
7635
|
"input",
|
|
6538
7636
|
{
|
|
6539
7637
|
type: "range",
|
|
@@ -6550,29 +7648,29 @@ var Video = React41.forwardRef((props, ref) => {
|
|
|
6550
7648
|
}
|
|
6551
7649
|
}
|
|
6552
7650
|
),
|
|
6553
|
-
/* @__PURE__ */
|
|
6554
|
-
/* @__PURE__ */
|
|
7651
|
+
/* @__PURE__ */ jsxs225("div", { className: "controls-row", children: [
|
|
7652
|
+
/* @__PURE__ */ jsx354(
|
|
6555
7653
|
"button",
|
|
6556
7654
|
{
|
|
6557
7655
|
type: "button",
|
|
6558
7656
|
className: "control-btn",
|
|
6559
7657
|
onClick: togglePlay,
|
|
6560
7658
|
"aria-label": isPlaying ? "\uC77C\uC2DC\uC815\uC9C0" : "\uC7AC\uC0DD",
|
|
6561
|
-
children: isPlaying ? /* @__PURE__ */
|
|
7659
|
+
children: isPlaying ? /* @__PURE__ */ jsx354(PauseIcon_default, {}) : /* @__PURE__ */ jsx354(PlayIcon_default, {})
|
|
6562
7660
|
}
|
|
6563
7661
|
),
|
|
6564
|
-
/* @__PURE__ */
|
|
6565
|
-
/* @__PURE__ */
|
|
7662
|
+
/* @__PURE__ */ jsxs225("div", { className: "volume-group", children: [
|
|
7663
|
+
/* @__PURE__ */ jsx354(
|
|
6566
7664
|
"button",
|
|
6567
7665
|
{
|
|
6568
7666
|
type: "button",
|
|
6569
7667
|
className: "control-btn",
|
|
6570
7668
|
onClick: toggleMute,
|
|
6571
7669
|
"aria-label": isMuted ? "\uC74C\uC18C\uAC70 \uD574\uC81C" : "\uC74C\uC18C\uAC70",
|
|
6572
|
-
children: /* @__PURE__ */
|
|
7670
|
+
children: /* @__PURE__ */ jsx354(VolumeGlyph, {})
|
|
6573
7671
|
}
|
|
6574
7672
|
),
|
|
6575
|
-
/* @__PURE__ */
|
|
7673
|
+
/* @__PURE__ */ jsx354(
|
|
6576
7674
|
"input",
|
|
6577
7675
|
{
|
|
6578
7676
|
type: "range",
|
|
@@ -6587,14 +7685,14 @@ var Video = React41.forwardRef((props, ref) => {
|
|
|
6587
7685
|
}
|
|
6588
7686
|
)
|
|
6589
7687
|
] }),
|
|
6590
|
-
/* @__PURE__ */
|
|
7688
|
+
/* @__PURE__ */ jsxs225("span", { className: "time", children: [
|
|
6591
7689
|
formatTime(currentTime),
|
|
6592
7690
|
" / ",
|
|
6593
7691
|
formatTime(duration)
|
|
6594
7692
|
] }),
|
|
6595
|
-
/* @__PURE__ */
|
|
6596
|
-
playbackRates && playbackRates.length > 0 && /* @__PURE__ */
|
|
6597
|
-
/* @__PURE__ */
|
|
7693
|
+
/* @__PURE__ */ jsx354("div", { className: "controls-spacer" }),
|
|
7694
|
+
playbackRates && playbackRates.length > 0 && /* @__PURE__ */ jsxs225("div", { className: clsx_default("rate-group", rateMenuOpen && "is-open"), children: [
|
|
7695
|
+
/* @__PURE__ */ jsxs225(
|
|
6598
7696
|
"button",
|
|
6599
7697
|
{
|
|
6600
7698
|
type: "button",
|
|
@@ -6608,7 +7706,7 @@ var Video = React41.forwardRef((props, ref) => {
|
|
|
6608
7706
|
]
|
|
6609
7707
|
}
|
|
6610
7708
|
),
|
|
6611
|
-
rateMenuOpen && /* @__PURE__ */
|
|
7709
|
+
rateMenuOpen && /* @__PURE__ */ jsx354("ul", { className: "rate-menu", role: "menu", children: playbackRates.map((r2) => /* @__PURE__ */ jsx354("li", { children: /* @__PURE__ */ jsxs225(
|
|
6612
7710
|
"button",
|
|
6613
7711
|
{
|
|
6614
7712
|
type: "button",
|
|
@@ -6622,7 +7720,7 @@ var Video = React41.forwardRef((props, ref) => {
|
|
|
6622
7720
|
}
|
|
6623
7721
|
) }, r2)) })
|
|
6624
7722
|
] }),
|
|
6625
|
-
showCaptions && /* @__PURE__ */
|
|
7723
|
+
showCaptions && /* @__PURE__ */ jsx354(
|
|
6626
7724
|
"button",
|
|
6627
7725
|
{
|
|
6628
7726
|
type: "button",
|
|
@@ -6630,37 +7728,37 @@ var Video = React41.forwardRef((props, ref) => {
|
|
|
6630
7728
|
onClick: toggleCaptions,
|
|
6631
7729
|
"aria-label": captionsOn ? "\uC790\uB9C9 \uB044\uAE30" : "\uC790\uB9C9 \uCF1C\uAE30",
|
|
6632
7730
|
"aria-pressed": captionsOn,
|
|
6633
|
-
children: /* @__PURE__ */
|
|
7731
|
+
children: /* @__PURE__ */ jsx354(TypeIcon_default, {})
|
|
6634
7732
|
}
|
|
6635
7733
|
),
|
|
6636
|
-
showPip && pipSupported && /* @__PURE__ */
|
|
7734
|
+
showPip && pipSupported && /* @__PURE__ */ jsx354(
|
|
6637
7735
|
"button",
|
|
6638
7736
|
{
|
|
6639
7737
|
type: "button",
|
|
6640
7738
|
className: clsx_default("control-btn", isPip && "is-active"),
|
|
6641
7739
|
onClick: togglePip,
|
|
6642
7740
|
"aria-label": isPip ? "PIP \uC885\uB8CC" : "PIP",
|
|
6643
|
-
children: /* @__PURE__ */
|
|
7741
|
+
children: /* @__PURE__ */ jsx354(PipIcon, {})
|
|
6644
7742
|
}
|
|
6645
7743
|
),
|
|
6646
|
-
showDownload && /* @__PURE__ */
|
|
7744
|
+
showDownload && /* @__PURE__ */ jsx354(
|
|
6647
7745
|
"a",
|
|
6648
7746
|
{
|
|
6649
7747
|
className: "control-btn",
|
|
6650
7748
|
href: src,
|
|
6651
7749
|
download: downloadFileName ?? true,
|
|
6652
7750
|
"aria-label": "\uB2E4\uC6B4\uB85C\uB4DC",
|
|
6653
|
-
children: /* @__PURE__ */
|
|
7751
|
+
children: /* @__PURE__ */ jsx354(DownloadIcon_default, {})
|
|
6654
7752
|
}
|
|
6655
7753
|
),
|
|
6656
|
-
/* @__PURE__ */
|
|
7754
|
+
/* @__PURE__ */ jsx354(
|
|
6657
7755
|
"button",
|
|
6658
7756
|
{
|
|
6659
7757
|
type: "button",
|
|
6660
7758
|
className: "control-btn",
|
|
6661
7759
|
onClick: toggleFullscreen,
|
|
6662
7760
|
"aria-label": isFullscreen ? "\uC804\uCCB4\uD654\uBA74 \uC885\uB8CC" : "\uC804\uCCB4\uD654\uBA74",
|
|
6663
|
-
children: isFullscreen ? /* @__PURE__ */
|
|
7761
|
+
children: isFullscreen ? /* @__PURE__ */ jsx354(MinimizeIcon_default, {}) : /* @__PURE__ */ jsx354(MaximizeIcon_default, {})
|
|
6664
7762
|
}
|
|
6665
7763
|
)
|
|
6666
7764
|
] })
|
|
@@ -6717,6 +7815,7 @@ export {
|
|
|
6717
7815
|
SingleDatePicker_default as SingleDatePicker,
|
|
6718
7816
|
Skeleton_default as Skeleton,
|
|
6719
7817
|
Spinner_default as Spinner,
|
|
7818
|
+
Stat_default as Stat,
|
|
6720
7819
|
Steps_default as Steps,
|
|
6721
7820
|
Swiper_default as Swiper,
|
|
6722
7821
|
Switch_default as Switch,
|
|
@@ -6728,6 +7827,7 @@ export {
|
|
|
6728
7827
|
TableRow_default as TableRow,
|
|
6729
7828
|
Tag_default as Tag,
|
|
6730
7829
|
TextArea_default as TextArea,
|
|
7830
|
+
TimePicker_default as TimePicker,
|
|
6731
7831
|
ToastProvider,
|
|
6732
7832
|
Tooltip_default as Tooltip,
|
|
6733
7833
|
Video_default as Video,
|