@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/index.js
CHANGED
|
@@ -5622,11 +5622,16 @@ var FieldMessage = (props) => {
|
|
|
5622
5622
|
FieldMessage.displayName = "FieldMessage";
|
|
5623
5623
|
var FieldMessage_default = FieldMessage;
|
|
5624
5624
|
var Field = (props) => {
|
|
5625
|
-
const { validations, children } = props;
|
|
5626
|
-
|
|
5625
|
+
const { label, required = false, htmlFor, validations, children } = props;
|
|
5626
|
+
const hasMessages = !!validations && validations.length > 0;
|
|
5627
|
+
if (!label && !hasMessages) return /* @__PURE__ */ jsx297(Fragment, { children });
|
|
5627
5628
|
return /* @__PURE__ */ jsxs191("div", { className: "lib-xplat-field", children: [
|
|
5629
|
+
label && /* @__PURE__ */ jsxs191("label", { className: "lib-xplat-field-label", htmlFor, children: [
|
|
5630
|
+
label,
|
|
5631
|
+
required && /* @__PURE__ */ jsx297("span", { className: "required", "aria-hidden": "true", children: "*" })
|
|
5632
|
+
] }),
|
|
5628
5633
|
children,
|
|
5629
|
-
/* @__PURE__ */ jsx297(FieldMessage, { validations })
|
|
5634
|
+
hasMessages && /* @__PURE__ */ jsx297(FieldMessage, { validations })
|
|
5630
5635
|
] });
|
|
5631
5636
|
};
|
|
5632
5637
|
Field.displayName = "Field";
|
|
@@ -5637,7 +5642,9 @@ import { jsx as jsx298 } from "react/jsx-runtime";
|
|
|
5637
5642
|
var MAX_HEIGHT = 400;
|
|
5638
5643
|
var AutoResizeTextArea = React2.forwardRef(
|
|
5639
5644
|
(props, ref) => {
|
|
5640
|
-
const { value, className, onChange, disabled, bare = false, validations, ...textareaProps } = props;
|
|
5645
|
+
const { value, className, onChange, disabled, bare = false, validations, label, required, ...textareaProps } = props;
|
|
5646
|
+
const autoId = React2.useId();
|
|
5647
|
+
const fieldId = props.id ?? autoId;
|
|
5641
5648
|
const localRef = React2.useRef(null);
|
|
5642
5649
|
const setRefs = (el) => {
|
|
5643
5650
|
localRef.current = el;
|
|
@@ -5671,6 +5678,7 @@ var AutoResizeTextArea = React2.forwardRef(
|
|
|
5671
5678
|
"aria-invalid": hasError(validations) || void 0,
|
|
5672
5679
|
...textareaProps,
|
|
5673
5680
|
ref: setRefs,
|
|
5681
|
+
id: fieldId,
|
|
5674
5682
|
className,
|
|
5675
5683
|
disabled,
|
|
5676
5684
|
value,
|
|
@@ -5684,12 +5692,13 @@ var AutoResizeTextArea = React2.forwardRef(
|
|
|
5684
5692
|
"aria-invalid": hasError(validations) || void 0,
|
|
5685
5693
|
...textareaProps,
|
|
5686
5694
|
ref: setRefs,
|
|
5695
|
+
id: fieldId,
|
|
5687
5696
|
disabled,
|
|
5688
5697
|
value,
|
|
5689
5698
|
onChange: handleChange
|
|
5690
5699
|
}
|
|
5691
5700
|
) }) });
|
|
5692
|
-
return /* @__PURE__ */ jsx298(Field, { validations, children: control });
|
|
5701
|
+
return /* @__PURE__ */ jsx298(Field, { validations, label, required, htmlFor: fieldId, children: control });
|
|
5693
5702
|
}
|
|
5694
5703
|
);
|
|
5695
5704
|
AutoResizeTextArea.displayName = "AutoResizeTextArea";
|
|
@@ -6907,8 +6916,11 @@ var ChatInput = React7.forwardRef(
|
|
|
6907
6916
|
buttonType = "primary",
|
|
6908
6917
|
onSubmit,
|
|
6909
6918
|
onChange,
|
|
6910
|
-
validations
|
|
6919
|
+
validations,
|
|
6920
|
+
label,
|
|
6921
|
+
required
|
|
6911
6922
|
} = props;
|
|
6923
|
+
const fieldId = React7.useId();
|
|
6912
6924
|
const isControlled = valueProp !== void 0;
|
|
6913
6925
|
const [internalValue, setInternalValue] = React7.useState("");
|
|
6914
6926
|
const value = isControlled ? valueProp : internalValue;
|
|
@@ -6933,6 +6945,7 @@ var ChatInput = React7.forwardRef(
|
|
|
6933
6945
|
/* @__PURE__ */ jsx308(
|
|
6934
6946
|
AutoResizeTextArea_default,
|
|
6935
6947
|
{
|
|
6948
|
+
id: fieldId,
|
|
6936
6949
|
ref,
|
|
6937
6950
|
bare: true,
|
|
6938
6951
|
className: "chat-input-textarea",
|
|
@@ -6957,7 +6970,7 @@ var ChatInput = React7.forwardRef(
|
|
|
6957
6970
|
}
|
|
6958
6971
|
)
|
|
6959
6972
|
] });
|
|
6960
|
-
return /* @__PURE__ */ jsx308(Field, { validations, children: control });
|
|
6973
|
+
return /* @__PURE__ */ jsx308(Field, { validations, label, required, htmlFor: fieldId, children: control });
|
|
6961
6974
|
}
|
|
6962
6975
|
);
|
|
6963
6976
|
ChatInput.displayName = "ChatInput";
|
|
@@ -7041,7 +7054,7 @@ Chip.displayName = "Chip";
|
|
|
7041
7054
|
var Chip_default = Chip;
|
|
7042
7055
|
|
|
7043
7056
|
// src/components/DatePicker/InputDatePicker/index.tsx
|
|
7044
|
-
import
|
|
7057
|
+
import React13 from "react";
|
|
7045
7058
|
|
|
7046
7059
|
// src/components/Input/Input.tsx
|
|
7047
7060
|
import React8 from "react";
|
|
@@ -7139,8 +7152,12 @@ var Input = React8.forwardRef((props, ref) => {
|
|
|
7139
7152
|
suffix,
|
|
7140
7153
|
disabled,
|
|
7141
7154
|
validations,
|
|
7155
|
+
label,
|
|
7156
|
+
required,
|
|
7142
7157
|
...inputProps
|
|
7143
7158
|
} = props;
|
|
7159
|
+
const autoId = React8.useId();
|
|
7160
|
+
const fieldId = inputProps.id ?? autoId;
|
|
7144
7161
|
const localValue = formatValue(type, value);
|
|
7145
7162
|
const handleChange = (e) => {
|
|
7146
7163
|
let val = e.target.value;
|
|
@@ -7156,7 +7173,7 @@ var Input = React8.forwardRef((props, ref) => {
|
|
|
7156
7173
|
onChange(event);
|
|
7157
7174
|
}
|
|
7158
7175
|
};
|
|
7159
|
-
return /* @__PURE__ */ jsxs199("div", { className: clsx_default("lib-xplat-input-wrap", className), children: [
|
|
7176
|
+
return /* @__PURE__ */ jsx311(Field, { label, required, htmlFor: fieldId, children: /* @__PURE__ */ jsxs199("div", { className: clsx_default("lib-xplat-input-wrap", className), children: [
|
|
7160
7177
|
/* @__PURE__ */ jsxs199(
|
|
7161
7178
|
"div",
|
|
7162
7179
|
{
|
|
@@ -7167,6 +7184,7 @@ var Input = React8.forwardRef((props, ref) => {
|
|
|
7167
7184
|
{
|
|
7168
7185
|
...inputProps,
|
|
7169
7186
|
ref,
|
|
7187
|
+
id: fieldId,
|
|
7170
7188
|
disabled,
|
|
7171
7189
|
type: type === "number" ? "text" : type,
|
|
7172
7190
|
value: localValue,
|
|
@@ -7179,7 +7197,7 @@ var Input = React8.forwardRef((props, ref) => {
|
|
|
7179
7197
|
}
|
|
7180
7198
|
),
|
|
7181
7199
|
/* @__PURE__ */ jsx311(FieldMessage_default, { validations })
|
|
7182
|
-
] });
|
|
7200
|
+
] }) });
|
|
7183
7201
|
});
|
|
7184
7202
|
Input.displayName = "Input";
|
|
7185
7203
|
var Input_default = Input;
|
|
@@ -7209,16 +7227,96 @@ PasswordInput.displayName = "PasswordInput";
|
|
|
7209
7227
|
var PasswordInput_default = PasswordInput;
|
|
7210
7228
|
|
|
7211
7229
|
// src/components/Modal/Modal.tsx
|
|
7212
|
-
import
|
|
7230
|
+
import React11 from "react";
|
|
7213
7231
|
import { createPortal } from "react-dom";
|
|
7232
|
+
|
|
7233
|
+
// src/tokens/hooks/useOverlayKeyboard.ts
|
|
7234
|
+
import React10 from "react";
|
|
7235
|
+
var FOCUSABLE = [
|
|
7236
|
+
"a[href]",
|
|
7237
|
+
"button:not([disabled])",
|
|
7238
|
+
"input:not([disabled]):not([type='hidden'])",
|
|
7239
|
+
"select:not([disabled])",
|
|
7240
|
+
"textarea:not([disabled])",
|
|
7241
|
+
"[tabindex]:not([tabindex='-1'])"
|
|
7242
|
+
].join(",");
|
|
7243
|
+
var focusableIn = (el) => Array.from(el.querySelectorAll(FOCUSABLE)).filter(
|
|
7244
|
+
// 화면에 없는 것은 제외 (display:none 등)
|
|
7245
|
+
(n) => n.offsetWidth > 0 || n.offsetHeight > 0 || n === document.activeElement
|
|
7246
|
+
);
|
|
7247
|
+
var useEscapeKey = (enabled, onEscape) => {
|
|
7248
|
+
React10.useEffect(() => {
|
|
7249
|
+
if (!enabled) return;
|
|
7250
|
+
const onKey = (e) => {
|
|
7251
|
+
if (e.key !== "Escape") return;
|
|
7252
|
+
if (e.defaultPrevented) return;
|
|
7253
|
+
e.preventDefault();
|
|
7254
|
+
onEscape();
|
|
7255
|
+
};
|
|
7256
|
+
document.addEventListener("keydown", onKey);
|
|
7257
|
+
return () => document.removeEventListener("keydown", onKey);
|
|
7258
|
+
}, [enabled, onEscape]);
|
|
7259
|
+
};
|
|
7260
|
+
var useFocusTrap = (containerRef, enabled, options = {}) => {
|
|
7261
|
+
const { trap = false, initialFocus } = options;
|
|
7262
|
+
const restoreRef = React10.useRef(null);
|
|
7263
|
+
React10.useEffect(() => {
|
|
7264
|
+
if (!enabled) return;
|
|
7265
|
+
restoreRef.current = document.activeElement;
|
|
7266
|
+
const raf = requestAnimationFrame(() => {
|
|
7267
|
+
const el = containerRef.current;
|
|
7268
|
+
if (!el) return;
|
|
7269
|
+
const target = initialFocus?.current ?? focusableIn(el)[0] ?? el;
|
|
7270
|
+
if (!target.hasAttribute("tabindex") && !focusableIn(el).includes(target)) {
|
|
7271
|
+
target.setAttribute("tabindex", "-1");
|
|
7272
|
+
}
|
|
7273
|
+
target.focus({ preventScroll: true });
|
|
7274
|
+
});
|
|
7275
|
+
return () => {
|
|
7276
|
+
cancelAnimationFrame(raf);
|
|
7277
|
+
const prev = restoreRef.current;
|
|
7278
|
+
if (prev && document.contains(prev)) prev.focus({ preventScroll: true });
|
|
7279
|
+
};
|
|
7280
|
+
}, [enabled, containerRef, initialFocus]);
|
|
7281
|
+
React10.useEffect(() => {
|
|
7282
|
+
if (!enabled || !trap) return;
|
|
7283
|
+
const onKey = (e) => {
|
|
7284
|
+
if (e.key !== "Tab") return;
|
|
7285
|
+
const el = containerRef.current;
|
|
7286
|
+
if (!el) return;
|
|
7287
|
+
const items = focusableIn(el);
|
|
7288
|
+
if (items.length === 0) {
|
|
7289
|
+
e.preventDefault();
|
|
7290
|
+
return;
|
|
7291
|
+
}
|
|
7292
|
+
const first = items[0];
|
|
7293
|
+
const last = items[items.length - 1];
|
|
7294
|
+
const active = document.activeElement;
|
|
7295
|
+
if (e.shiftKey && (active === first || !el.contains(active))) {
|
|
7296
|
+
e.preventDefault();
|
|
7297
|
+
last.focus();
|
|
7298
|
+
} else if (!e.shiftKey && (active === last || !el.contains(active))) {
|
|
7299
|
+
e.preventDefault();
|
|
7300
|
+
first.focus();
|
|
7301
|
+
}
|
|
7302
|
+
};
|
|
7303
|
+
document.addEventListener("keydown", onKey);
|
|
7304
|
+
return () => document.removeEventListener("keydown", onKey);
|
|
7305
|
+
}, [enabled, trap, containerRef]);
|
|
7306
|
+
};
|
|
7307
|
+
|
|
7308
|
+
// src/components/Modal/Modal.tsx
|
|
7214
7309
|
import { jsx as jsx313 } from "react/jsx-runtime";
|
|
7215
7310
|
var ANIMATION_DURATION_MS = 200;
|
|
7216
7311
|
var Modal = (props) => {
|
|
7217
7312
|
const { isOpen, onClose, children } = props;
|
|
7218
|
-
const [mounted, setMounted] =
|
|
7219
|
-
const [visible, setVisible] =
|
|
7220
|
-
const [settled, setSettled] =
|
|
7221
|
-
|
|
7313
|
+
const [mounted, setMounted] = React11.useState(false);
|
|
7314
|
+
const [visible, setVisible] = React11.useState(false);
|
|
7315
|
+
const [settled, setSettled] = React11.useState(false);
|
|
7316
|
+
const boxRef = React11.useRef(null);
|
|
7317
|
+
useEscapeKey(isOpen, onClose);
|
|
7318
|
+
useFocusTrap(boxRef, isOpen && mounted, { trap: true });
|
|
7319
|
+
React11.useEffect(() => {
|
|
7222
7320
|
if (isOpen) {
|
|
7223
7321
|
setMounted(true);
|
|
7224
7322
|
const show = setTimeout(() => setVisible(true), 1);
|
|
@@ -7245,6 +7343,7 @@ var Modal = (props) => {
|
|
|
7245
7343
|
children: /* @__PURE__ */ jsx313(
|
|
7246
7344
|
"div",
|
|
7247
7345
|
{
|
|
7346
|
+
ref: boxRef,
|
|
7248
7347
|
className: clsx_default("lib-xplat-modal", "modal-box", stateClass, settled && "settled"),
|
|
7249
7348
|
role: "dialog",
|
|
7250
7349
|
"aria-modal": "true",
|
|
@@ -7261,9 +7360,9 @@ Modal.displayName = "Modal";
|
|
|
7261
7360
|
var Modal_default = Modal;
|
|
7262
7361
|
|
|
7263
7362
|
// src/components/DatePicker/SingleDatePicker/index.tsx
|
|
7264
|
-
import
|
|
7363
|
+
import React12 from "react";
|
|
7265
7364
|
import { Fragment as Fragment4, jsx as jsx314, jsxs as jsxs200 } from "react/jsx-runtime";
|
|
7266
|
-
var DayCell2 =
|
|
7365
|
+
var DayCell2 = React12.memo(
|
|
7267
7366
|
({
|
|
7268
7367
|
day,
|
|
7269
7368
|
disabled,
|
|
@@ -7315,26 +7414,26 @@ var SingleDatePicker = (props) => {
|
|
|
7315
7414
|
initialYear,
|
|
7316
7415
|
initialMonth
|
|
7317
7416
|
);
|
|
7318
|
-
const [pickerMode, setPickerMode] =
|
|
7319
|
-
const [yearRangeStart, setYearRangeStart] =
|
|
7417
|
+
const [pickerMode, setPickerMode] = React12.useState("days");
|
|
7418
|
+
const [yearRangeStart, setYearRangeStart] = React12.useState(
|
|
7320
7419
|
Math.floor((initialYear ?? (/* @__PURE__ */ new Date()).getFullYear()) / 12) * 12
|
|
7321
7420
|
);
|
|
7322
|
-
const minTime =
|
|
7421
|
+
const minTime = React12.useMemo(
|
|
7323
7422
|
() => minDate ? new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate()).getTime() : -Infinity,
|
|
7324
7423
|
[minDate]
|
|
7325
7424
|
);
|
|
7326
|
-
const maxTime =
|
|
7425
|
+
const maxTime = React12.useMemo(
|
|
7327
7426
|
() => maxDate ? new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate()).getTime() : Infinity,
|
|
7328
7427
|
[maxDate]
|
|
7329
7428
|
);
|
|
7330
|
-
const highlightSet =
|
|
7429
|
+
const highlightSet = React12.useMemo(() => {
|
|
7331
7430
|
const set = /* @__PURE__ */ new Set();
|
|
7332
7431
|
for (const h of highlightDates) {
|
|
7333
7432
|
set.add(`${h.getFullYear()}-${h.getMonth()}-${h.getDate()}`);
|
|
7334
7433
|
}
|
|
7335
7434
|
return set;
|
|
7336
7435
|
}, [highlightDates]);
|
|
7337
|
-
const handleSelect =
|
|
7436
|
+
const handleSelect = React12.useCallback(
|
|
7338
7437
|
(date) => {
|
|
7339
7438
|
onChange?.(date);
|
|
7340
7439
|
},
|
|
@@ -7463,8 +7562,8 @@ var formatDate = (date) => {
|
|
|
7463
7562
|
};
|
|
7464
7563
|
var InputDatePicker = (props) => {
|
|
7465
7564
|
const { value, onChange, minDate, maxDate, disabled, locale = "ko", placeholder } = props;
|
|
7466
|
-
const [isOpen, setIsOpen] =
|
|
7467
|
-
const [tempDate, setTempDate] =
|
|
7565
|
+
const [isOpen, setIsOpen] = React13.useState(false);
|
|
7566
|
+
const [tempDate, setTempDate] = React13.useState(value ?? /* @__PURE__ */ new Date());
|
|
7468
7567
|
const handleOpen = () => {
|
|
7469
7568
|
if (disabled) return;
|
|
7470
7569
|
setTempDate(value ?? /* @__PURE__ */ new Date());
|
|
@@ -7513,23 +7612,27 @@ InputDatePicker.displayName = "InputDatePicker";
|
|
|
7513
7612
|
var InputDatePicker_default = InputDatePicker;
|
|
7514
7613
|
|
|
7515
7614
|
// src/components/DatePicker/PopupPicker/index.tsx
|
|
7516
|
-
import
|
|
7615
|
+
import React17 from "react";
|
|
7517
7616
|
|
|
7518
7617
|
// src/components/DatePicker/RangePicker/index.tsx
|
|
7519
|
-
import
|
|
7618
|
+
import React16 from "react";
|
|
7520
7619
|
|
|
7521
7620
|
// src/components/Tab/Tab.tsx
|
|
7522
|
-
import
|
|
7621
|
+
import React15 from "react";
|
|
7523
7622
|
|
|
7524
7623
|
// src/components/Tab/TabItem.tsx
|
|
7525
|
-
import
|
|
7624
|
+
import React14 from "react";
|
|
7526
7625
|
import { jsx as jsx316 } from "react/jsx-runtime";
|
|
7527
|
-
var TabItem =
|
|
7626
|
+
var TabItem = React14.forwardRef((props, ref) => {
|
|
7528
7627
|
const { isActive: isActive2, title, onClick } = props;
|
|
7529
7628
|
return /* @__PURE__ */ jsx316(
|
|
7530
|
-
"
|
|
7629
|
+
"button",
|
|
7531
7630
|
{
|
|
7532
7631
|
ref,
|
|
7632
|
+
type: "button",
|
|
7633
|
+
role: "tab",
|
|
7634
|
+
"aria-selected": isActive2,
|
|
7635
|
+
tabIndex: isActive2 ? 0 : -1,
|
|
7533
7636
|
className: clsx_default("tab-item", isActive2 ? "active" : null),
|
|
7534
7637
|
onClick,
|
|
7535
7638
|
children: title
|
|
@@ -7544,44 +7647,64 @@ import { jsx as jsx317, jsxs as jsxs202 } from "react/jsx-runtime";
|
|
|
7544
7647
|
var Tab = (props) => {
|
|
7545
7648
|
const { activeIndex, onChange, tabs, variant, type, size = "md" } = props;
|
|
7546
7649
|
const shape = variant ?? type ?? "default";
|
|
7547
|
-
const [underlineStyle, setUnderlineStyle] =
|
|
7650
|
+
const [underlineStyle, setUnderlineStyle] = React15.useState({
|
|
7548
7651
|
left: 0,
|
|
7549
7652
|
width: 0
|
|
7550
7653
|
});
|
|
7551
|
-
const itemRefs =
|
|
7654
|
+
const itemRefs = React15.useRef([]);
|
|
7655
|
+
const handleKeyDown = (e) => {
|
|
7656
|
+
const last = tabs.length - 1;
|
|
7657
|
+
let next = null;
|
|
7658
|
+
if (e.key === "ArrowRight") next = activeIndex >= last ? 0 : activeIndex + 1;
|
|
7659
|
+
else if (e.key === "ArrowLeft") next = activeIndex <= 0 ? last : activeIndex - 1;
|
|
7660
|
+
else if (e.key === "Home") next = 0;
|
|
7661
|
+
else if (e.key === "End") next = last;
|
|
7662
|
+
if (next === null) return;
|
|
7663
|
+
e.preventDefault();
|
|
7664
|
+
onChange(tabs[next], next);
|
|
7665
|
+
itemRefs.current[next]?.focus();
|
|
7666
|
+
};
|
|
7552
7667
|
const handleChangeActiveTab = (tabItem, tabIdx) => {
|
|
7553
7668
|
onChange(tabItem, tabIdx);
|
|
7554
7669
|
};
|
|
7555
|
-
|
|
7670
|
+
React15.useEffect(() => {
|
|
7556
7671
|
const el = itemRefs.current[activeIndex];
|
|
7557
7672
|
if (el) {
|
|
7558
7673
|
setUnderlineStyle({ left: el.offsetLeft, width: el.offsetWidth });
|
|
7559
7674
|
}
|
|
7560
7675
|
}, [activeIndex, tabs.length]);
|
|
7561
|
-
return /* @__PURE__ */ jsxs202(
|
|
7562
|
-
|
|
7563
|
-
|
|
7564
|
-
{
|
|
7565
|
-
|
|
7566
|
-
|
|
7567
|
-
|
|
7568
|
-
|
|
7569
|
-
|
|
7570
|
-
|
|
7571
|
-
|
|
7572
|
-
|
|
7573
|
-
|
|
7574
|
-
|
|
7575
|
-
|
|
7576
|
-
|
|
7577
|
-
|
|
7578
|
-
|
|
7579
|
-
|
|
7580
|
-
|
|
7581
|
-
|
|
7582
|
-
|
|
7583
|
-
|
|
7584
|
-
|
|
7676
|
+
return /* @__PURE__ */ jsxs202(
|
|
7677
|
+
"div",
|
|
7678
|
+
{
|
|
7679
|
+
className: clsx_default("lib-xplat-tab", `type-${shape}`, size),
|
|
7680
|
+
role: "tablist",
|
|
7681
|
+
onKeyDown: handleKeyDown,
|
|
7682
|
+
children: [
|
|
7683
|
+
tabs.map((tab, idx) => /* @__PURE__ */ jsx317(
|
|
7684
|
+
TabItem_default,
|
|
7685
|
+
{
|
|
7686
|
+
onClick: () => handleChangeActiveTab(tab, idx),
|
|
7687
|
+
isActive: activeIndex === idx,
|
|
7688
|
+
ref: (el) => {
|
|
7689
|
+
itemRefs.current[idx] = el;
|
|
7690
|
+
},
|
|
7691
|
+
title: tab.title
|
|
7692
|
+
},
|
|
7693
|
+
`${tab.value}_${idx}`
|
|
7694
|
+
)),
|
|
7695
|
+
shape === "toggle" && /* @__PURE__ */ jsx317(
|
|
7696
|
+
"div",
|
|
7697
|
+
{
|
|
7698
|
+
className: "tab-toggle-underline",
|
|
7699
|
+
style: {
|
|
7700
|
+
left: underlineStyle.left,
|
|
7701
|
+
width: underlineStyle.width
|
|
7702
|
+
}
|
|
7703
|
+
}
|
|
7704
|
+
)
|
|
7705
|
+
]
|
|
7706
|
+
}
|
|
7707
|
+
);
|
|
7585
7708
|
};
|
|
7586
7709
|
Tab.displayName = "Tab";
|
|
7587
7710
|
var Tab_default = Tab;
|
|
@@ -7597,7 +7720,7 @@ var RangePicker = (props) => {
|
|
|
7597
7720
|
maxDate,
|
|
7598
7721
|
locale = "ko"
|
|
7599
7722
|
} = props;
|
|
7600
|
-
const [activeTab, setActiveTab] =
|
|
7723
|
+
const [activeTab, setActiveTab] = React16.useState("start");
|
|
7601
7724
|
const handleStartChange = (date) => {
|
|
7602
7725
|
if (!date) return;
|
|
7603
7726
|
const newStart = date > endDate ? endDate : date;
|
|
@@ -7682,7 +7805,7 @@ var RangePicker_default = RangePicker;
|
|
|
7682
7805
|
import { jsx as jsx319, jsxs as jsxs204 } from "react/jsx-runtime";
|
|
7683
7806
|
var PopupPicker = (props) => {
|
|
7684
7807
|
const { component, type, locale } = props;
|
|
7685
|
-
const [isOpen, setIsOpen] =
|
|
7808
|
+
const [isOpen, setIsOpen] = React17.useState(false);
|
|
7686
7809
|
const handleClick = () => setIsOpen(true);
|
|
7687
7810
|
const handleClose = () => setIsOpen(false);
|
|
7688
7811
|
const handleSingleChange = (date) => {
|
|
@@ -7691,7 +7814,7 @@ var PopupPicker = (props) => {
|
|
|
7691
7814
|
handleClose();
|
|
7692
7815
|
};
|
|
7693
7816
|
return /* @__PURE__ */ jsxs204("div", { className: "lib-xplat-popup-datepicker", children: [
|
|
7694
|
-
|
|
7817
|
+
React17.cloneElement(component, { onClick: handleClick }),
|
|
7695
7818
|
/* @__PURE__ */ jsx319(Modal_default, { isOpen, onClose: handleClose, children: /* @__PURE__ */ jsxs204("div", { className: clsx_default("lib-xplat-popup-datepicker-card", type === "range" && "range-mode"), children: [
|
|
7696
7819
|
/* @__PURE__ */ jsxs204("div", { className: "popup-datepicker-content", children: [
|
|
7697
7820
|
type === "single" && /* @__PURE__ */ jsx319(
|
|
@@ -7750,15 +7873,18 @@ Divider.displayName = "Divider";
|
|
|
7750
7873
|
var Divider_default = Divider;
|
|
7751
7874
|
|
|
7752
7875
|
// src/components/Drawer/Drawer.tsx
|
|
7753
|
-
import
|
|
7876
|
+
import React18 from "react";
|
|
7754
7877
|
import { createPortal as createPortal2 } from "react-dom";
|
|
7755
7878
|
import { jsx as jsx321, jsxs as jsxs205 } from "react/jsx-runtime";
|
|
7756
7879
|
var ANIMATION_DURATION_MS2 = 250;
|
|
7757
7880
|
var Drawer = (props) => {
|
|
7758
7881
|
const { isOpen, onClose, placement = "right", size = "md", title, children } = props;
|
|
7759
|
-
const [mounted, setMounted] =
|
|
7760
|
-
const [visible, setVisible] =
|
|
7761
|
-
|
|
7882
|
+
const [mounted, setMounted] = React18.useState(false);
|
|
7883
|
+
const [visible, setVisible] = React18.useState(false);
|
|
7884
|
+
const panelRef = React18.useRef(null);
|
|
7885
|
+
useEscapeKey(isOpen, onClose);
|
|
7886
|
+
useFocusTrap(panelRef, isOpen && mounted, { trap: true });
|
|
7887
|
+
React18.useEffect(() => {
|
|
7762
7888
|
if (isOpen) {
|
|
7763
7889
|
setMounted(true);
|
|
7764
7890
|
const t2 = setTimeout(() => setVisible(true), 1);
|
|
@@ -7780,6 +7906,7 @@ var Drawer = (props) => {
|
|
|
7780
7906
|
children: /* @__PURE__ */ jsxs205(
|
|
7781
7907
|
"div",
|
|
7782
7908
|
{
|
|
7909
|
+
ref: panelRef,
|
|
7783
7910
|
className: clsx_default("lib-xplat-drawer", placement, size, stateClass),
|
|
7784
7911
|
role: "dialog",
|
|
7785
7912
|
"aria-modal": "true",
|
|
@@ -7802,7 +7929,7 @@ Drawer.displayName = "Drawer";
|
|
|
7802
7929
|
var Drawer_default = Drawer;
|
|
7803
7930
|
|
|
7804
7931
|
// src/components/Dropdown/Dropdown.tsx
|
|
7805
|
-
import
|
|
7932
|
+
import React21 from "react";
|
|
7806
7933
|
|
|
7807
7934
|
// src/tokens/hooks/Portal.tsx
|
|
7808
7935
|
import ReactDOM from "react-dom";
|
|
@@ -7814,13 +7941,15 @@ Portal.displayName = "Portal";
|
|
|
7814
7941
|
var Portal_default = Portal;
|
|
7815
7942
|
|
|
7816
7943
|
// src/tokens/hooks/useAutoPosition.ts
|
|
7817
|
-
import
|
|
7944
|
+
import React19 from "react";
|
|
7818
7945
|
var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
7819
|
-
const [position, setPosition] =
|
|
7946
|
+
const [position, setPosition] = React19.useState({
|
|
7820
7947
|
position: {},
|
|
7821
|
-
direction: "bottom"
|
|
7948
|
+
direction: "bottom",
|
|
7949
|
+
repositioning: false
|
|
7822
7950
|
});
|
|
7823
|
-
const
|
|
7951
|
+
const placedRef = React19.useRef(false);
|
|
7952
|
+
const calculatePosition = React19.useCallback(() => {
|
|
7824
7953
|
if (!triggerRef.current || !popRef.current) return;
|
|
7825
7954
|
const triggerRect = triggerRef.current.getBoundingClientRect();
|
|
7826
7955
|
const popW = popRef.current.offsetWidth;
|
|
@@ -7844,16 +7973,21 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
7844
7973
|
if (left < 8) left = 8;
|
|
7845
7974
|
setPosition({
|
|
7846
7975
|
position: { top, left },
|
|
7847
|
-
direction
|
|
7976
|
+
direction,
|
|
7977
|
+
repositioning: placedRef.current
|
|
7848
7978
|
});
|
|
7979
|
+
placedRef.current = true;
|
|
7849
7980
|
}, [triggerRef, popRef]);
|
|
7850
|
-
|
|
7851
|
-
if (!enabled)
|
|
7981
|
+
React19.useLayoutEffect(() => {
|
|
7982
|
+
if (!enabled) {
|
|
7983
|
+
placedRef.current = false;
|
|
7984
|
+
return;
|
|
7985
|
+
}
|
|
7852
7986
|
calculatePosition();
|
|
7853
7987
|
const raf = requestAnimationFrame(calculatePosition);
|
|
7854
7988
|
return () => cancelAnimationFrame(raf);
|
|
7855
7989
|
}, [calculatePosition, enabled]);
|
|
7856
|
-
|
|
7990
|
+
React19.useEffect(() => {
|
|
7857
7991
|
if (!enabled || !popRef.current) return;
|
|
7858
7992
|
const observer = new ResizeObserver(() => {
|
|
7859
7993
|
calculatePosition();
|
|
@@ -7861,13 +7995,19 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
7861
7995
|
observer.observe(popRef.current);
|
|
7862
7996
|
return () => observer.disconnect();
|
|
7863
7997
|
}, [calculatePosition, enabled, popRef]);
|
|
7864
|
-
|
|
7998
|
+
React19.useEffect(() => {
|
|
7865
7999
|
if (!enabled) return;
|
|
7866
|
-
|
|
7867
|
-
|
|
8000
|
+
let raf = 0;
|
|
8001
|
+
const onScrollOrResize = () => {
|
|
8002
|
+
cancelAnimationFrame(raf);
|
|
8003
|
+
raf = requestAnimationFrame(calculatePosition);
|
|
8004
|
+
};
|
|
8005
|
+
window.addEventListener("resize", onScrollOrResize, { passive: true });
|
|
8006
|
+
window.addEventListener("scroll", onScrollOrResize, { passive: true, capture: true });
|
|
7868
8007
|
return () => {
|
|
7869
|
-
|
|
7870
|
-
window.removeEventListener("
|
|
8008
|
+
cancelAnimationFrame(raf);
|
|
8009
|
+
window.removeEventListener("resize", onScrollOrResize);
|
|
8010
|
+
window.removeEventListener("scroll", onScrollOrResize, true);
|
|
7871
8011
|
};
|
|
7872
8012
|
}, [calculatePosition, enabled]);
|
|
7873
8013
|
return position;
|
|
@@ -7875,9 +8015,9 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
7875
8015
|
var useAutoPosition_default = useAutoPosition;
|
|
7876
8016
|
|
|
7877
8017
|
// src/tokens/hooks/useClickOutside.ts
|
|
7878
|
-
import
|
|
8018
|
+
import React20 from "react";
|
|
7879
8019
|
var useClickOutside = (refs, handler, enabled = true) => {
|
|
7880
|
-
|
|
8020
|
+
React20.useEffect(() => {
|
|
7881
8021
|
if (!enabled) return;
|
|
7882
8022
|
const refArray = Array.isArray(refs) ? refs : [refs];
|
|
7883
8023
|
const listener = (event) => {
|
|
@@ -7903,14 +8043,18 @@ var useClickOutside_default = useClickOutside;
|
|
|
7903
8043
|
import { jsx as jsx322, jsxs as jsxs206 } from "react/jsx-runtime";
|
|
7904
8044
|
var Dropdown = (props) => {
|
|
7905
8045
|
const { items, children } = props;
|
|
7906
|
-
const [isOpen, setIsOpen] =
|
|
7907
|
-
const [mounted, setMounted] =
|
|
7908
|
-
const [visible, setVisible] =
|
|
7909
|
-
const triggerRef =
|
|
7910
|
-
const menuRef =
|
|
7911
|
-
const { position, direction } = useAutoPosition_default(triggerRef, menuRef, mounted);
|
|
8046
|
+
const [isOpen, setIsOpen] = React21.useState(false);
|
|
8047
|
+
const [mounted, setMounted] = React21.useState(false);
|
|
8048
|
+
const [visible, setVisible] = React21.useState(false);
|
|
8049
|
+
const triggerRef = React21.useRef(null);
|
|
8050
|
+
const menuRef = React21.useRef(null);
|
|
8051
|
+
const { position, direction, repositioning } = useAutoPosition_default(triggerRef, menuRef, mounted);
|
|
7912
8052
|
useClickOutside_default([triggerRef, menuRef], () => setIsOpen(false), isOpen);
|
|
7913
|
-
|
|
8053
|
+
useEscapeKey(isOpen, () => {
|
|
8054
|
+
setIsOpen(false);
|
|
8055
|
+
triggerRef.current?.focus({ preventScroll: true });
|
|
8056
|
+
});
|
|
8057
|
+
React21.useEffect(() => {
|
|
7914
8058
|
if (isOpen) {
|
|
7915
8059
|
setMounted(true);
|
|
7916
8060
|
const t2 = setTimeout(() => setVisible(true), 1);
|
|
@@ -7939,7 +8083,7 @@ var Dropdown = (props) => {
|
|
|
7939
8083
|
"div",
|
|
7940
8084
|
{
|
|
7941
8085
|
ref: menuRef,
|
|
7942
|
-
className: clsx_default("lib-xplat-dropdown-menu", direction, { visible }),
|
|
8086
|
+
className: clsx_default("lib-xplat-dropdown-menu", direction, { visible }, repositioning && "repositioning"),
|
|
7943
8087
|
style: { top: position.top, left: position.left },
|
|
7944
8088
|
role: "menu",
|
|
7945
8089
|
children: items.map((item) => /* @__PURE__ */ jsx322(
|
|
@@ -7964,7 +8108,112 @@ Dropdown.displayName = "Dropdown";
|
|
|
7964
8108
|
var Dropdown_default = Dropdown;
|
|
7965
8109
|
|
|
7966
8110
|
// src/components/Editor/Editor.tsx
|
|
7967
|
-
import
|
|
8111
|
+
import React22 from "react";
|
|
8112
|
+
|
|
8113
|
+
// src/components/Editor/highlight.ts
|
|
8114
|
+
var CODE_LANGUAGES = [
|
|
8115
|
+
{ value: "plain", label: "\uC5C6\uC74C" },
|
|
8116
|
+
{ value: "javascript", label: "JavaScript" },
|
|
8117
|
+
{ value: "typescript", label: "TypeScript" },
|
|
8118
|
+
{ value: "json", label: "JSON" },
|
|
8119
|
+
{ value: "html", label: "HTML" },
|
|
8120
|
+
{ value: "css", label: "CSS" },
|
|
8121
|
+
{ value: "python", label: "Python" },
|
|
8122
|
+
{ value: "sql", label: "SQL" },
|
|
8123
|
+
{ value: "bash", label: "Bash" }
|
|
8124
|
+
];
|
|
8125
|
+
var KEYWORDS = {
|
|
8126
|
+
plain: [],
|
|
8127
|
+
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(" "),
|
|
8128
|
+
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(" "),
|
|
8129
|
+
json: ["true", "false", "null"],
|
|
8130
|
+
html: [],
|
|
8131
|
+
css: [],
|
|
8132
|
+
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(" "),
|
|
8133
|
+
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(" "),
|
|
8134
|
+
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(" ")
|
|
8135
|
+
};
|
|
8136
|
+
var LINE_COMMENT = {
|
|
8137
|
+
javascript: "//",
|
|
8138
|
+
typescript: "//",
|
|
8139
|
+
css: "",
|
|
8140
|
+
python: "#",
|
|
8141
|
+
sql: "--",
|
|
8142
|
+
bash: "#"
|
|
8143
|
+
};
|
|
8144
|
+
var escape = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
8145
|
+
var wrap = (cls, text) => `<span class="tok-${cls}">${escape(text)}</span>`;
|
|
8146
|
+
var highlight = (code, lang) => {
|
|
8147
|
+
if (lang === "plain" || !code) return escape(code);
|
|
8148
|
+
const keywords = new Set(KEYWORDS[lang]);
|
|
8149
|
+
const lineComment = LINE_COMMENT[lang];
|
|
8150
|
+
const caseInsensitive = lang === "sql";
|
|
8151
|
+
let out = "";
|
|
8152
|
+
let i = 0;
|
|
8153
|
+
while (i < code.length) {
|
|
8154
|
+
const rest = code.slice(i);
|
|
8155
|
+
if ((lang === "javascript" || lang === "typescript" || lang === "css") && rest.startsWith("/*")) {
|
|
8156
|
+
const end = code.indexOf("*/", i + 2);
|
|
8157
|
+
const stop = end === -1 ? code.length : end + 2;
|
|
8158
|
+
out += wrap("comment", code.slice(i, stop));
|
|
8159
|
+
i = stop;
|
|
8160
|
+
continue;
|
|
8161
|
+
}
|
|
8162
|
+
if (lineComment && rest.startsWith(lineComment)) {
|
|
8163
|
+
const nl = code.indexOf("\n", i);
|
|
8164
|
+
const stop = nl === -1 ? code.length : nl;
|
|
8165
|
+
out += wrap("comment", code.slice(i, stop));
|
|
8166
|
+
i = stop;
|
|
8167
|
+
continue;
|
|
8168
|
+
}
|
|
8169
|
+
const q = rest[0];
|
|
8170
|
+
if (q === '"' || q === "'" || q === "`") {
|
|
8171
|
+
let j = 1;
|
|
8172
|
+
while (j < rest.length) {
|
|
8173
|
+
if (rest[j] === "\\") {
|
|
8174
|
+
j += 2;
|
|
8175
|
+
continue;
|
|
8176
|
+
}
|
|
8177
|
+
if (rest[j] === q) {
|
|
8178
|
+
j += 1;
|
|
8179
|
+
break;
|
|
8180
|
+
}
|
|
8181
|
+
if (rest[j] === "\n" && q !== "`") break;
|
|
8182
|
+
j += 1;
|
|
8183
|
+
}
|
|
8184
|
+
out += wrap("string", rest.slice(0, j));
|
|
8185
|
+
i += j;
|
|
8186
|
+
continue;
|
|
8187
|
+
}
|
|
8188
|
+
const num = /^\d+(\.\d+)?/.exec(rest);
|
|
8189
|
+
if (num && !/[\w$]/.test(code[i - 1] ?? "")) {
|
|
8190
|
+
out += wrap("number", num[0]);
|
|
8191
|
+
i += num[0].length;
|
|
8192
|
+
continue;
|
|
8193
|
+
}
|
|
8194
|
+
const word = /^[A-Za-z_$][\w$]*/.exec(rest);
|
|
8195
|
+
if (word) {
|
|
8196
|
+
const w = word[0];
|
|
8197
|
+
const hit = caseInsensitive ? keywords.has(w.toUpperCase()) : keywords.has(w);
|
|
8198
|
+
out += hit ? wrap("keyword", w) : escape(w);
|
|
8199
|
+
i += w.length;
|
|
8200
|
+
continue;
|
|
8201
|
+
}
|
|
8202
|
+
if (lang === "html" && rest.startsWith("<")) {
|
|
8203
|
+
const tag = /^<\/?[A-Za-z][\w-]*/.exec(rest);
|
|
8204
|
+
if (tag) {
|
|
8205
|
+
out += wrap("keyword", tag[0]);
|
|
8206
|
+
i += tag[0].length;
|
|
8207
|
+
continue;
|
|
8208
|
+
}
|
|
8209
|
+
}
|
|
8210
|
+
out += escape(code[i]);
|
|
8211
|
+
i += 1;
|
|
8212
|
+
}
|
|
8213
|
+
return out;
|
|
8214
|
+
};
|
|
8215
|
+
|
|
8216
|
+
// src/components/Editor/Editor.tsx
|
|
7968
8217
|
import { jsx as jsx323, jsxs as jsxs207 } from "react/jsx-runtime";
|
|
7969
8218
|
var DEFAULT_TOOLBAR = [
|
|
7970
8219
|
"bold",
|
|
@@ -7972,14 +8221,27 @@ var DEFAULT_TOOLBAR = [
|
|
|
7972
8221
|
"underline",
|
|
7973
8222
|
"strikethrough",
|
|
7974
8223
|
"code",
|
|
7975
|
-
"heading",
|
|
8224
|
+
"heading-1",
|
|
8225
|
+
"heading-2",
|
|
8226
|
+
"heading-3",
|
|
7976
8227
|
"list",
|
|
7977
8228
|
"ordered-list",
|
|
7978
8229
|
"blockquote",
|
|
7979
8230
|
"code-block",
|
|
7980
8231
|
"link",
|
|
7981
8232
|
"image",
|
|
7982
|
-
"divider"
|
|
8233
|
+
"divider",
|
|
8234
|
+
"checklist",
|
|
8235
|
+
"table",
|
|
8236
|
+
"align-left",
|
|
8237
|
+
"align-center",
|
|
8238
|
+
"align-right",
|
|
8239
|
+
"highlight",
|
|
8240
|
+
"superscript",
|
|
8241
|
+
"subscript",
|
|
8242
|
+
"clear-format",
|
|
8243
|
+
"undo",
|
|
8244
|
+
"redo"
|
|
7983
8245
|
];
|
|
7984
8246
|
var ALLOWED_TAGS = /* @__PURE__ */ new Set([
|
|
7985
8247
|
"p",
|
|
@@ -8008,12 +8270,51 @@ var ALLOWED_TAGS = /* @__PURE__ */ new Set([
|
|
|
8008
8270
|
"img",
|
|
8009
8271
|
"hr",
|
|
8010
8272
|
"span",
|
|
8011
|
-
"div"
|
|
8273
|
+
"div",
|
|
8274
|
+
"sub",
|
|
8275
|
+
"sup",
|
|
8276
|
+
"mark",
|
|
8277
|
+
"table",
|
|
8278
|
+
"thead",
|
|
8279
|
+
"tbody",
|
|
8280
|
+
"tr",
|
|
8281
|
+
"th",
|
|
8282
|
+
"td"
|
|
8012
8283
|
]);
|
|
8013
8284
|
var ALLOWED_ATTRS = {
|
|
8014
8285
|
a: ["href", "target", "rel"],
|
|
8015
|
-
img: ["src", "alt"]
|
|
8286
|
+
img: ["src", "alt", "width"],
|
|
8287
|
+
// 정렬·체크리스트는 클래스로만 표현한다. style 을 열면 붙여넣기로 아무 CSS 나 들어온다
|
|
8288
|
+
p: ["class"],
|
|
8289
|
+
h1: ["class"],
|
|
8290
|
+
h2: ["class"],
|
|
8291
|
+
h3: ["class"],
|
|
8292
|
+
h4: ["class"],
|
|
8293
|
+
h5: ["class"],
|
|
8294
|
+
h6: ["class"],
|
|
8295
|
+
ul: ["class"],
|
|
8296
|
+
ol: ["class"],
|
|
8297
|
+
li: ["class", "data-checked"],
|
|
8298
|
+
blockquote: ["class"],
|
|
8299
|
+
div: ["class"],
|
|
8300
|
+
span: ["class"],
|
|
8301
|
+
pre: ["class"],
|
|
8302
|
+
code: ["class"],
|
|
8303
|
+
mark: ["class"],
|
|
8304
|
+
table: ["class"],
|
|
8305
|
+
td: ["class"],
|
|
8306
|
+
th: ["class"],
|
|
8307
|
+
tr: ["class"]
|
|
8016
8308
|
};
|
|
8309
|
+
var DROP_WITH_CONTENT = /* @__PURE__ */ new Set([
|
|
8310
|
+
"script",
|
|
8311
|
+
"style",
|
|
8312
|
+
"noscript",
|
|
8313
|
+
"iframe",
|
|
8314
|
+
"object",
|
|
8315
|
+
"embed",
|
|
8316
|
+
"template"
|
|
8317
|
+
]);
|
|
8017
8318
|
var sanitizeHtml = (input) => {
|
|
8018
8319
|
const doc = new DOMParser().parseFromString(`<div>${input}</div>`, "text/html");
|
|
8019
8320
|
const root = doc.body.firstElementChild;
|
|
@@ -8022,6 +8323,10 @@ var sanitizeHtml = (input) => {
|
|
|
8022
8323
|
const children = Array.from(node.children);
|
|
8023
8324
|
for (const child of children) {
|
|
8024
8325
|
const tag = child.tagName.toLowerCase();
|
|
8326
|
+
if (DROP_WITH_CONTENT.has(tag)) {
|
|
8327
|
+
node.removeChild(child);
|
|
8328
|
+
continue;
|
|
8329
|
+
}
|
|
8025
8330
|
if (!ALLOWED_TAGS.has(tag)) {
|
|
8026
8331
|
while (child.firstChild) node.insertBefore(child.firstChild, child);
|
|
8027
8332
|
node.removeChild(child);
|
|
@@ -8052,7 +8357,9 @@ var escapeHtml = (text) => {
|
|
|
8052
8357
|
};
|
|
8053
8358
|
var SLASH_ITEMS = [
|
|
8054
8359
|
{ key: "paragraph", label: "\uB2E8\uB77D", hint: "\uAE30\uBCF8 \uD14D\uC2A4\uD2B8" },
|
|
8055
|
-
{ key: "heading", label: "\uC81C\uBAA9 1", hint: "\uD070 \uC81C\uBAA9" },
|
|
8360
|
+
{ key: "heading-1", label: "\uC81C\uBAA9 1", hint: "\uAC00\uC7A5 \uD070 \uC81C\uBAA9" },
|
|
8361
|
+
{ key: "heading-2", label: "\uC81C\uBAA9 2", hint: "" },
|
|
8362
|
+
{ key: "heading-3", label: "\uC81C\uBAA9 3", hint: "" },
|
|
8056
8363
|
{ key: "list", label: "\uAE00\uBA38\uB9AC \uAE30\uD638 \uBAA9\uB85D", hint: "\u2022 \uD56D\uBAA9" },
|
|
8057
8364
|
{ key: "ordered-list", label: "\uBC88\uD638 \uB9E4\uAE30\uAE30 \uBAA9\uB85D", hint: "1. \uD56D\uBAA9" },
|
|
8058
8365
|
{ key: "blockquote", label: "\uC778\uC6A9", hint: "" },
|
|
@@ -8072,26 +8379,32 @@ var Editor = (props) => {
|
|
|
8072
8379
|
onImageUpload,
|
|
8073
8380
|
minHeight = 200
|
|
8074
8381
|
} = props;
|
|
8075
|
-
const editorRef =
|
|
8076
|
-
const lastRangeRef =
|
|
8077
|
-
const composingRef =
|
|
8078
|
-
const [isFocused, setIsFocused] =
|
|
8079
|
-
const [isEmpty, setIsEmpty] =
|
|
8080
|
-
const [activeFormats, setActiveFormats] =
|
|
8081
|
-
const [slashOpen, setSlashOpen] =
|
|
8082
|
-
const [slashFilter, setSlashFilter] =
|
|
8083
|
-
const [slashIdx, setSlashIdx] =
|
|
8084
|
-
const [slashPos, setSlashPos] =
|
|
8085
|
-
const slashStartRangeRef =
|
|
8086
|
-
const [linkOpen, setLinkOpen] =
|
|
8087
|
-
const [linkValue, setLinkValue] =
|
|
8088
|
-
const [linkPos, setLinkPos] =
|
|
8089
|
-
|
|
8090
|
-
|
|
8091
|
-
|
|
8092
|
-
|
|
8093
|
-
|
|
8094
|
-
|
|
8382
|
+
const editorRef = React22.useRef(null);
|
|
8383
|
+
const lastRangeRef = React22.useRef(null);
|
|
8384
|
+
const composingRef = React22.useRef(false);
|
|
8385
|
+
const [isFocused, setIsFocused] = React22.useState(false);
|
|
8386
|
+
const [isEmpty, setIsEmpty] = React22.useState(!value);
|
|
8387
|
+
const [activeFormats, setActiveFormats] = React22.useState(/* @__PURE__ */ new Set());
|
|
8388
|
+
const [slashOpen, setSlashOpen] = React22.useState(false);
|
|
8389
|
+
const [slashFilter, setSlashFilter] = React22.useState("");
|
|
8390
|
+
const [slashIdx, setSlashIdx] = React22.useState(0);
|
|
8391
|
+
const [slashPos, setSlashPos] = React22.useState({ top: 0, left: 0 });
|
|
8392
|
+
const slashStartRangeRef = React22.useRef(null);
|
|
8393
|
+
const [linkOpen, setLinkOpen] = React22.useState(false);
|
|
8394
|
+
const [linkValue, setLinkValue] = React22.useState("");
|
|
8395
|
+
const [linkPos, setLinkPos] = React22.useState({ top: 0, left: 0 });
|
|
8396
|
+
const lastEmittedRef = React22.useRef(null);
|
|
8397
|
+
React22.useEffect(() => {
|
|
8398
|
+
const el = editorRef.current;
|
|
8399
|
+
if (!el) return;
|
|
8400
|
+
if (value === lastEmittedRef.current) return;
|
|
8401
|
+
if (el.innerHTML === value) return;
|
|
8402
|
+
el.innerHTML = sanitizeHtml(value || "");
|
|
8403
|
+
if (!el.firstChild) el.innerHTML = "<p><br></p>";
|
|
8404
|
+
lastEmittedRef.current = null;
|
|
8405
|
+
historyRef.current = [{ html: el.innerHTML, caret: 0 }];
|
|
8406
|
+
historyIdxRef.current = 0;
|
|
8407
|
+
updateEmpty();
|
|
8095
8408
|
}, [value]);
|
|
8096
8409
|
const updateEmpty = () => {
|
|
8097
8410
|
const el = editorRef.current;
|
|
@@ -8107,10 +8420,19 @@ var Editor = (props) => {
|
|
|
8107
8420
|
}
|
|
8108
8421
|
};
|
|
8109
8422
|
const restoreSelection = () => {
|
|
8110
|
-
|
|
8423
|
+
const range = lastRangeRef.current;
|
|
8424
|
+
if (!range) return;
|
|
8425
|
+
if (!editorRef.current?.contains(range.startContainer)) {
|
|
8426
|
+
lastRangeRef.current = null;
|
|
8427
|
+
return;
|
|
8428
|
+
}
|
|
8111
8429
|
const sel = window.getSelection();
|
|
8112
|
-
|
|
8113
|
-
|
|
8430
|
+
try {
|
|
8431
|
+
sel?.removeAllRanges();
|
|
8432
|
+
sel?.addRange(range);
|
|
8433
|
+
} catch {
|
|
8434
|
+
lastRangeRef.current = null;
|
|
8435
|
+
}
|
|
8114
8436
|
};
|
|
8115
8437
|
const updateActiveFormats = () => {
|
|
8116
8438
|
if (!editorRef.current) return;
|
|
@@ -8126,6 +8448,17 @@ var Editor = (props) => {
|
|
|
8126
8448
|
if (document.queryCommandState("insertOrderedList")) next.add("ordered-list");
|
|
8127
8449
|
const block = String(document.queryCommandValue("formatBlock") || "").toLowerCase();
|
|
8128
8450
|
if (block) next.add(`block:${block}`);
|
|
8451
|
+
if (document.queryCommandState("superscript")) next.add("superscript");
|
|
8452
|
+
if (document.queryCommandState("subscript")) next.add("subscript");
|
|
8453
|
+
} catch {
|
|
8454
|
+
}
|
|
8455
|
+
try {
|
|
8456
|
+
const blockEl = currentBlock();
|
|
8457
|
+
if (blockEl?.classList.contains("align-center")) next.add("align:center");
|
|
8458
|
+
else if (blockEl?.classList.contains("align-right")) next.add("align:right");
|
|
8459
|
+
else if (blockEl) next.add("align:left");
|
|
8460
|
+
if (blockEl?.closest("mark")) next.add("highlight");
|
|
8461
|
+
if (blockEl?.closest("ul.checklist")) next.add("checklist");
|
|
8129
8462
|
} catch {
|
|
8130
8463
|
}
|
|
8131
8464
|
setActiveFormats(next);
|
|
@@ -8139,7 +8472,374 @@ var Editor = (props) => {
|
|
|
8139
8472
|
const setBlock = (tag) => {
|
|
8140
8473
|
exec("formatBlock", tag);
|
|
8141
8474
|
};
|
|
8475
|
+
const toggleBlock = (tag) => {
|
|
8476
|
+
const current = String(document.queryCommandValue("formatBlock") || "").toLowerCase();
|
|
8477
|
+
setBlock(current === tag ? "p" : tag);
|
|
8478
|
+
};
|
|
8479
|
+
const historyRef = React22.useRef([]);
|
|
8480
|
+
const historyIdxRef = React22.useRef(-1);
|
|
8481
|
+
const lastPushAtRef = React22.useRef(0);
|
|
8482
|
+
const isRestoringRef = React22.useRef(false);
|
|
8483
|
+
const caretOffset = (rootEl) => {
|
|
8484
|
+
const el = rootEl ?? editorRef.current;
|
|
8485
|
+
const sel = window.getSelection();
|
|
8486
|
+
if (!el || !sel || sel.rangeCount === 0 || !el.contains(sel.anchorNode)) return 0;
|
|
8487
|
+
const range = sel.getRangeAt(0).cloneRange();
|
|
8488
|
+
range.selectNodeContents(el);
|
|
8489
|
+
range.setEnd(sel.getRangeAt(0).endContainer, sel.getRangeAt(0).endOffset);
|
|
8490
|
+
return range.toString().length;
|
|
8491
|
+
};
|
|
8492
|
+
const setCaretOffset = (offset, rootEl) => {
|
|
8493
|
+
const el = rootEl ?? editorRef.current;
|
|
8494
|
+
if (!el) return;
|
|
8495
|
+
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
|
|
8496
|
+
let remaining = offset;
|
|
8497
|
+
let node = null;
|
|
8498
|
+
while (node = walker.nextNode()) {
|
|
8499
|
+
const len = node.textContent?.length ?? 0;
|
|
8500
|
+
if (remaining <= len) {
|
|
8501
|
+
const range = document.createRange();
|
|
8502
|
+
range.setStart(node, remaining);
|
|
8503
|
+
range.collapse(true);
|
|
8504
|
+
const sel = window.getSelection();
|
|
8505
|
+
sel?.removeAllRanges();
|
|
8506
|
+
sel?.addRange(range);
|
|
8507
|
+
return;
|
|
8508
|
+
}
|
|
8509
|
+
remaining -= len;
|
|
8510
|
+
}
|
|
8511
|
+
placeCaretAtEnd(el);
|
|
8512
|
+
};
|
|
8513
|
+
const pushHistory = (force = false) => {
|
|
8514
|
+
const el = editorRef.current;
|
|
8515
|
+
if (!el || isRestoringRef.current) return;
|
|
8516
|
+
const html = el.innerHTML;
|
|
8517
|
+
const hist = historyRef.current;
|
|
8518
|
+
const cur = hist[historyIdxRef.current];
|
|
8519
|
+
if (cur && cur.html === html) return;
|
|
8520
|
+
const now = Date.now();
|
|
8521
|
+
const coalesce = !force && cur && now - lastPushAtRef.current < 500;
|
|
8522
|
+
lastPushAtRef.current = now;
|
|
8523
|
+
if (coalesce) {
|
|
8524
|
+
hist[historyIdxRef.current] = { html, caret: caretOffset() };
|
|
8525
|
+
return;
|
|
8526
|
+
}
|
|
8527
|
+
hist.length = historyIdxRef.current + 1;
|
|
8528
|
+
hist.push({ html, caret: caretOffset() });
|
|
8529
|
+
if (hist.length > 200) hist.shift();
|
|
8530
|
+
historyIdxRef.current = hist.length - 1;
|
|
8531
|
+
};
|
|
8532
|
+
const applySnapshot = (snap) => {
|
|
8533
|
+
const el = editorRef.current;
|
|
8534
|
+
if (!el) return;
|
|
8535
|
+
isRestoringRef.current = true;
|
|
8536
|
+
el.innerHTML = snap.html;
|
|
8537
|
+
setCaretOffset(snap.caret);
|
|
8538
|
+
isRestoringRef.current = false;
|
|
8539
|
+
lastEmittedRef.current = el.innerHTML;
|
|
8540
|
+
onChange?.(el.innerHTML);
|
|
8541
|
+
updateEmpty();
|
|
8542
|
+
updateActiveFormats();
|
|
8543
|
+
};
|
|
8544
|
+
const undo = () => {
|
|
8545
|
+
pushHistory(true);
|
|
8546
|
+
if (historyIdxRef.current <= 0) return;
|
|
8547
|
+
historyIdxRef.current -= 1;
|
|
8548
|
+
applySnapshot(historyRef.current[historyIdxRef.current]);
|
|
8549
|
+
};
|
|
8550
|
+
const redo = () => {
|
|
8551
|
+
if (historyIdxRef.current >= historyRef.current.length - 1) return;
|
|
8552
|
+
historyIdxRef.current += 1;
|
|
8553
|
+
applySnapshot(historyRef.current[historyIdxRef.current]);
|
|
8554
|
+
};
|
|
8555
|
+
const langOf = (pre) => {
|
|
8556
|
+
const cls = Array.from(pre.classList).find((c) => c.startsWith("lang-"));
|
|
8557
|
+
return cls?.slice(5) ?? "plain";
|
|
8558
|
+
};
|
|
8559
|
+
const [codeLang, setCodeLang] = React22.useState("plain");
|
|
8560
|
+
const highlightRafRef = React22.useRef(0);
|
|
8561
|
+
const rehighlight = (pre) => {
|
|
8562
|
+
if (composingRef.current) return;
|
|
8563
|
+
const code = pre.querySelector("code");
|
|
8564
|
+
if (!code) return;
|
|
8565
|
+
const lang = langOf(pre);
|
|
8566
|
+
const text = code.textContent || "";
|
|
8567
|
+
const next = highlight(text, lang);
|
|
8568
|
+
if (code.innerHTML === next) return;
|
|
8569
|
+
const caret = caretOffset(code);
|
|
8570
|
+
isRestoringRef.current = true;
|
|
8571
|
+
code.innerHTML = next;
|
|
8572
|
+
setCaretOffset(caret, code);
|
|
8573
|
+
isRestoringRef.current = false;
|
|
8574
|
+
};
|
|
8575
|
+
const scheduleHighlight = () => {
|
|
8576
|
+
const pre = closestPre();
|
|
8577
|
+
if (!pre) return;
|
|
8578
|
+
cancelAnimationFrame(highlightRafRef.current);
|
|
8579
|
+
highlightRafRef.current = requestAnimationFrame(() => rehighlight(pre));
|
|
8580
|
+
};
|
|
8581
|
+
const changeCodeLang = (lang) => {
|
|
8582
|
+
const pre = closestPre();
|
|
8583
|
+
if (!pre) return;
|
|
8584
|
+
pushHistory(true);
|
|
8585
|
+
Array.from(pre.classList).filter((c) => c.startsWith("lang-")).forEach((c) => pre.classList.remove(c));
|
|
8586
|
+
if (lang !== "plain") pre.classList.add(`lang-${lang}`);
|
|
8587
|
+
setCodeLang(lang);
|
|
8588
|
+
rehighlight(pre);
|
|
8589
|
+
handleInput();
|
|
8590
|
+
};
|
|
8591
|
+
const closestPre = () => {
|
|
8592
|
+
const sel = window.getSelection();
|
|
8593
|
+
const node = sel?.anchorNode;
|
|
8594
|
+
if (!node || !editorRef.current?.contains(node)) return null;
|
|
8595
|
+
const el = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
|
|
8596
|
+
return el?.closest("pre") ?? null;
|
|
8597
|
+
};
|
|
8598
|
+
const insertCodeBlock = () => {
|
|
8599
|
+
pushHistory(true);
|
|
8600
|
+
const el = editorRef.current;
|
|
8601
|
+
const sel = window.getSelection();
|
|
8602
|
+
if (!el || !sel || sel.rangeCount === 0) return;
|
|
8603
|
+
const existing = closestPre();
|
|
8604
|
+
if (existing) {
|
|
8605
|
+
const p = document.createElement("p");
|
|
8606
|
+
p.textContent = existing.textContent || "";
|
|
8607
|
+
if (!p.textContent) p.innerHTML = "<br>";
|
|
8608
|
+
existing.replaceWith(p);
|
|
8609
|
+
placeCaretAtEnd(p);
|
|
8610
|
+
handleInput();
|
|
8611
|
+
return;
|
|
8612
|
+
}
|
|
8613
|
+
const range = sel.getRangeAt(0);
|
|
8614
|
+
const frag = range.cloneContents();
|
|
8615
|
+
const holder = document.createElement("div");
|
|
8616
|
+
holder.appendChild(frag);
|
|
8617
|
+
const BLOCK = /^(p|div|h[1-6]|li|blockquote|pre|tr)$/i;
|
|
8618
|
+
const linesOf = (node) => {
|
|
8619
|
+
const out = [];
|
|
8620
|
+
let cur = "";
|
|
8621
|
+
for (const child of Array.from(node.childNodes)) {
|
|
8622
|
+
if (child.nodeType === Node.TEXT_NODE) {
|
|
8623
|
+
cur += child.textContent || "";
|
|
8624
|
+
} else if (child.nodeName === "BR") {
|
|
8625
|
+
out.push(cur);
|
|
8626
|
+
cur = "";
|
|
8627
|
+
} else if (BLOCK.test(child.nodeName)) {
|
|
8628
|
+
if (cur) {
|
|
8629
|
+
out.push(cur);
|
|
8630
|
+
cur = "";
|
|
8631
|
+
}
|
|
8632
|
+
const sub = linesOf(child);
|
|
8633
|
+
out.push(...sub.length > 0 ? sub : [""]);
|
|
8634
|
+
} else {
|
|
8635
|
+
cur += linesOf(child).join("\n");
|
|
8636
|
+
}
|
|
8637
|
+
}
|
|
8638
|
+
if (cur) out.push(cur);
|
|
8639
|
+
return out;
|
|
8640
|
+
};
|
|
8641
|
+
const text = linesOf(holder).join("\n").replace(/\n+$/, "");
|
|
8642
|
+
const pre = document.createElement("pre");
|
|
8643
|
+
const code = document.createElement("code");
|
|
8644
|
+
code.textContent = text || "";
|
|
8645
|
+
pre.appendChild(code);
|
|
8646
|
+
range.deleteContents();
|
|
8647
|
+
range.insertNode(pre);
|
|
8648
|
+
ensureParagraphAfter(pre);
|
|
8649
|
+
placeCaretAtEnd(code);
|
|
8650
|
+
handleInput();
|
|
8651
|
+
};
|
|
8652
|
+
const insertTextAtCaret = (text) => {
|
|
8653
|
+
const sel = window.getSelection();
|
|
8654
|
+
if (!sel || sel.rangeCount === 0) return;
|
|
8655
|
+
const range = sel.getRangeAt(0);
|
|
8656
|
+
range.deleteContents();
|
|
8657
|
+
const node = document.createTextNode(text);
|
|
8658
|
+
range.insertNode(node);
|
|
8659
|
+
range.setStartAfter(node);
|
|
8660
|
+
range.collapse(true);
|
|
8661
|
+
sel.removeAllRanges();
|
|
8662
|
+
sel.addRange(range);
|
|
8663
|
+
handleInput();
|
|
8664
|
+
};
|
|
8665
|
+
const ensureParagraphAfter = (node) => {
|
|
8666
|
+
const next = node.nextElementSibling;
|
|
8667
|
+
if (next && next.tagName === "P") return;
|
|
8668
|
+
const p = document.createElement("p");
|
|
8669
|
+
p.innerHTML = "<br>";
|
|
8670
|
+
node.after(p);
|
|
8671
|
+
};
|
|
8672
|
+
const placeCaretAtEnd = (node) => {
|
|
8673
|
+
const sel = window.getSelection();
|
|
8674
|
+
if (!sel) return;
|
|
8675
|
+
const r2 = document.createRange();
|
|
8676
|
+
r2.selectNodeContents(node);
|
|
8677
|
+
r2.collapse(false);
|
|
8678
|
+
sel.removeAllRanges();
|
|
8679
|
+
sel.addRange(r2);
|
|
8680
|
+
editorRef.current?.focus();
|
|
8681
|
+
};
|
|
8682
|
+
const clearFormat = () => {
|
|
8683
|
+
exec("removeFormat");
|
|
8684
|
+
exec("unlink");
|
|
8685
|
+
setBlock("p");
|
|
8686
|
+
};
|
|
8687
|
+
const indentList = (outdent) => {
|
|
8688
|
+
exec(outdent ? "outdent" : "indent");
|
|
8689
|
+
};
|
|
8690
|
+
const inListItem = () => {
|
|
8691
|
+
const sel = window.getSelection();
|
|
8692
|
+
const node = sel?.anchorNode;
|
|
8693
|
+
if (!node || !editorRef.current?.contains(node)) return false;
|
|
8694
|
+
const el = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
|
|
8695
|
+
return !!el?.closest("li");
|
|
8696
|
+
};
|
|
8697
|
+
const currentBlock = () => {
|
|
8698
|
+
const sel = window.getSelection();
|
|
8699
|
+
const node = sel?.anchorNode;
|
|
8700
|
+
const root = editorRef.current;
|
|
8701
|
+
if (!node || !root?.contains(node)) return null;
|
|
8702
|
+
let el = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
|
|
8703
|
+
while (el && el !== root && !/^(P|H[1-6]|LI|BLOCKQUOTE|PRE|DIV|TD|TH)$/.test(el.tagName)) {
|
|
8704
|
+
el = el.parentElement;
|
|
8705
|
+
}
|
|
8706
|
+
return el && el !== root ? el : null;
|
|
8707
|
+
};
|
|
8708
|
+
const setAlign = (align) => {
|
|
8709
|
+
const block = currentBlock();
|
|
8710
|
+
if (!block) return;
|
|
8711
|
+
pushHistory(true);
|
|
8712
|
+
block.classList.remove("align-left", "align-center", "align-right");
|
|
8713
|
+
if (align !== "left") block.classList.add(`align-${align}`);
|
|
8714
|
+
handleInput();
|
|
8715
|
+
};
|
|
8716
|
+
const toggleChecklist = () => {
|
|
8717
|
+
pushHistory(true);
|
|
8718
|
+
const block = currentBlock();
|
|
8719
|
+
const list = block?.closest("ul");
|
|
8720
|
+
if (list?.classList.contains("checklist")) {
|
|
8721
|
+
list.classList.remove("checklist");
|
|
8722
|
+
list.querySelectorAll("li").forEach((li) => li.removeAttribute("data-checked"));
|
|
8723
|
+
handleInput();
|
|
8724
|
+
return;
|
|
8725
|
+
}
|
|
8726
|
+
if (list) {
|
|
8727
|
+
list.classList.add("checklist");
|
|
8728
|
+
list.querySelectorAll("li").forEach((li) => li.setAttribute("data-checked", "false"));
|
|
8729
|
+
handleInput();
|
|
8730
|
+
return;
|
|
8731
|
+
}
|
|
8732
|
+
exec("insertUnorderedList");
|
|
8733
|
+
const made = currentBlock()?.closest("ul");
|
|
8734
|
+
if (made) {
|
|
8735
|
+
made.classList.add("checklist");
|
|
8736
|
+
made.querySelectorAll("li").forEach((li) => li.setAttribute("data-checked", "false"));
|
|
8737
|
+
}
|
|
8738
|
+
handleInput();
|
|
8739
|
+
};
|
|
8740
|
+
const handleEditorClick = (e) => {
|
|
8741
|
+
if (readOnly) return;
|
|
8742
|
+
const target = e.target;
|
|
8743
|
+
const li = target.closest?.("li");
|
|
8744
|
+
if (!li || !li.closest("ul.checklist")) return;
|
|
8745
|
+
const rect = li.getBoundingClientRect();
|
|
8746
|
+
if (e.clientX - rect.left > 20) return;
|
|
8747
|
+
e.preventDefault();
|
|
8748
|
+
pushHistory(true);
|
|
8749
|
+
li.setAttribute("data-checked", li.getAttribute("data-checked") === "true" ? "false" : "true");
|
|
8750
|
+
handleInput();
|
|
8751
|
+
};
|
|
8752
|
+
const toggleHighlight = () => {
|
|
8753
|
+
const sel = window.getSelection();
|
|
8754
|
+
if (!sel || sel.rangeCount === 0 || sel.isCollapsed) return;
|
|
8755
|
+
pushHistory(true);
|
|
8756
|
+
const range = sel.getRangeAt(0);
|
|
8757
|
+
const node = sel.anchorNode;
|
|
8758
|
+
const el = node?.nodeType === Node.ELEMENT_NODE ? node : node?.parentElement;
|
|
8759
|
+
const existing = el?.closest("mark");
|
|
8760
|
+
if (existing) {
|
|
8761
|
+
const parent = existing.parentNode;
|
|
8762
|
+
while (existing.firstChild) parent?.insertBefore(existing.firstChild, existing);
|
|
8763
|
+
parent?.removeChild(existing);
|
|
8764
|
+
handleInput();
|
|
8765
|
+
return;
|
|
8766
|
+
}
|
|
8767
|
+
const mark = document.createElement("mark");
|
|
8768
|
+
try {
|
|
8769
|
+
range.surroundContents(mark);
|
|
8770
|
+
} catch {
|
|
8771
|
+
const frag = range.extractContents();
|
|
8772
|
+
mark.appendChild(frag);
|
|
8773
|
+
range.insertNode(mark);
|
|
8774
|
+
}
|
|
8775
|
+
handleInput();
|
|
8776
|
+
};
|
|
8777
|
+
const insertTable = (cols = 3, rows = 2) => {
|
|
8778
|
+
const sel = window.getSelection();
|
|
8779
|
+
if (!sel || sel.rangeCount === 0) return;
|
|
8780
|
+
pushHistory(true);
|
|
8781
|
+
const table = document.createElement("table");
|
|
8782
|
+
const thead = document.createElement("thead");
|
|
8783
|
+
const headRow = document.createElement("tr");
|
|
8784
|
+
for (let c = 0; c < cols; c++) {
|
|
8785
|
+
const th = document.createElement("th");
|
|
8786
|
+
th.innerHTML = "<br>";
|
|
8787
|
+
headRow.appendChild(th);
|
|
8788
|
+
}
|
|
8789
|
+
thead.appendChild(headRow);
|
|
8790
|
+
table.appendChild(thead);
|
|
8791
|
+
const tbody = document.createElement("tbody");
|
|
8792
|
+
for (let r2 = 0; r2 < rows; r2++) {
|
|
8793
|
+
const tr = document.createElement("tr");
|
|
8794
|
+
for (let c = 0; c < cols; c++) {
|
|
8795
|
+
const td = document.createElement("td");
|
|
8796
|
+
td.innerHTML = "<br>";
|
|
8797
|
+
tr.appendChild(td);
|
|
8798
|
+
}
|
|
8799
|
+
tbody.appendChild(tr);
|
|
8800
|
+
}
|
|
8801
|
+
table.appendChild(tbody);
|
|
8802
|
+
const range = sel.getRangeAt(0);
|
|
8803
|
+
range.deleteContents();
|
|
8804
|
+
range.insertNode(table);
|
|
8805
|
+
ensureParagraphAfter(table);
|
|
8806
|
+
const first = table.querySelector("th");
|
|
8807
|
+
if (first) placeCaretAtEnd(first);
|
|
8808
|
+
handleInput();
|
|
8809
|
+
};
|
|
8810
|
+
const moveTableCell = (backwards) => {
|
|
8811
|
+
const block = currentBlock();
|
|
8812
|
+
const cell = block?.closest("td, th");
|
|
8813
|
+
if (!cell) return false;
|
|
8814
|
+
const table = cell.closest("table");
|
|
8815
|
+
if (!table) return false;
|
|
8816
|
+
const cells = Array.from(table.querySelectorAll("td, th"));
|
|
8817
|
+
const i = cells.indexOf(cell);
|
|
8818
|
+
const next = cells[i + (backwards ? -1 : 1)];
|
|
8819
|
+
if (next) {
|
|
8820
|
+
placeCaretAtEnd(next);
|
|
8821
|
+
return true;
|
|
8822
|
+
}
|
|
8823
|
+
if (!backwards) {
|
|
8824
|
+
pushHistory(true);
|
|
8825
|
+
const lastRow = table.querySelector("tbody")?.lastElementChild;
|
|
8826
|
+
if (lastRow) {
|
|
8827
|
+
const tr = document.createElement("tr");
|
|
8828
|
+
for (let c = 0; c < lastRow.children.length; c++) {
|
|
8829
|
+
const td = document.createElement("td");
|
|
8830
|
+
td.innerHTML = "<br>";
|
|
8831
|
+
tr.appendChild(td);
|
|
8832
|
+
}
|
|
8833
|
+
lastRow.after(tr);
|
|
8834
|
+
placeCaretAtEnd(tr.firstElementChild);
|
|
8835
|
+
handleInput();
|
|
8836
|
+
return true;
|
|
8837
|
+
}
|
|
8838
|
+
}
|
|
8839
|
+
return false;
|
|
8840
|
+
};
|
|
8142
8841
|
const insertDivider = () => {
|
|
8842
|
+
pushHistory(true);
|
|
8143
8843
|
exec("insertHorizontalRule");
|
|
8144
8844
|
const el = editorRef.current;
|
|
8145
8845
|
if (el && el.lastElementChild?.tagName === "HR") {
|
|
@@ -8185,7 +8885,9 @@ var Editor = (props) => {
|
|
|
8185
8885
|
const range = sel.getRangeAt(0);
|
|
8186
8886
|
slashStartRangeRef.current = range.cloneRange();
|
|
8187
8887
|
const rect = range.getBoundingClientRect();
|
|
8188
|
-
const
|
|
8888
|
+
const editorEl = editorRef.current;
|
|
8889
|
+
if (!editorEl) return;
|
|
8890
|
+
const editorRect = editorEl.getBoundingClientRect();
|
|
8189
8891
|
setSlashPos({
|
|
8190
8892
|
top: rect.bottom - editorRect.top + 4,
|
|
8191
8893
|
left: rect.left - editorRect.left
|
|
@@ -8200,7 +8902,7 @@ var Editor = (props) => {
|
|
|
8200
8902
|
setSlashIdx(0);
|
|
8201
8903
|
slashStartRangeRef.current = null;
|
|
8202
8904
|
};
|
|
8203
|
-
const filteredSlashItems =
|
|
8905
|
+
const filteredSlashItems = React22.useMemo(() => {
|
|
8204
8906
|
if (!slashFilter) return SLASH_ITEMS;
|
|
8205
8907
|
const f = slashFilter.toLowerCase();
|
|
8206
8908
|
return SLASH_ITEMS.filter((it) => it.label.toLowerCase().includes(f) || it.key.includes(f));
|
|
@@ -8230,8 +8932,14 @@ var Editor = (props) => {
|
|
|
8230
8932
|
case "paragraph":
|
|
8231
8933
|
setBlock("p");
|
|
8232
8934
|
break;
|
|
8233
|
-
case "heading":
|
|
8234
|
-
|
|
8935
|
+
case "heading-1":
|
|
8936
|
+
toggleBlock("h1");
|
|
8937
|
+
break;
|
|
8938
|
+
case "heading-2":
|
|
8939
|
+
toggleBlock("h2");
|
|
8940
|
+
break;
|
|
8941
|
+
case "heading-3":
|
|
8942
|
+
toggleBlock("h3");
|
|
8235
8943
|
break;
|
|
8236
8944
|
case "list":
|
|
8237
8945
|
exec("insertUnorderedList");
|
|
@@ -8243,7 +8951,7 @@ var Editor = (props) => {
|
|
|
8243
8951
|
setBlock("blockquote");
|
|
8244
8952
|
break;
|
|
8245
8953
|
case "code-block":
|
|
8246
|
-
|
|
8954
|
+
insertCodeBlock();
|
|
8247
8955
|
break;
|
|
8248
8956
|
case "divider":
|
|
8249
8957
|
insertDivider();
|
|
@@ -8261,7 +8969,9 @@ var Editor = (props) => {
|
|
|
8261
8969
|
if (!sel || sel.rangeCount === 0) return;
|
|
8262
8970
|
const range = sel.getRangeAt(0);
|
|
8263
8971
|
const rect = range.getBoundingClientRect();
|
|
8264
|
-
const
|
|
8972
|
+
const editorEl2 = editorRef.current;
|
|
8973
|
+
if (!editorEl2) return;
|
|
8974
|
+
const editorRect = editorEl2.getBoundingClientRect();
|
|
8265
8975
|
setLinkPos({
|
|
8266
8976
|
top: rect.bottom - editorRect.top + 4,
|
|
8267
8977
|
left: rect.left - editorRect.left
|
|
@@ -8294,13 +9004,13 @@ var Editor = (props) => {
|
|
|
8294
9004
|
if (node.nodeType !== Node.TEXT_NODE) return false;
|
|
8295
9005
|
const text = (node.textContent || "").slice(0, range.startOffset);
|
|
8296
9006
|
const patterns = [
|
|
8297
|
-
[
|
|
8298
|
-
[
|
|
8299
|
-
[
|
|
8300
|
-
[
|
|
8301
|
-
[
|
|
8302
|
-
[/^1
|
|
8303
|
-
[
|
|
9007
|
+
[/^###$/, () => setBlock("h3")],
|
|
9008
|
+
[/^##$/, () => setBlock("h2")],
|
|
9009
|
+
[/^#$/, () => setBlock("h1")],
|
|
9010
|
+
[/^-$/, () => exec("insertUnorderedList")],
|
|
9011
|
+
[/^\*$/, () => exec("insertUnorderedList")],
|
|
9012
|
+
[/^1\.$/, () => exec("insertOrderedList")],
|
|
9013
|
+
[/^>$/, () => setBlock("blockquote")]
|
|
8304
9014
|
];
|
|
8305
9015
|
for (const [re, fn] of patterns) {
|
|
8306
9016
|
if (re.test(text)) {
|
|
@@ -8320,7 +9030,11 @@ var Editor = (props) => {
|
|
|
8320
9030
|
if (composingRef.current) return;
|
|
8321
9031
|
const el = editorRef.current;
|
|
8322
9032
|
if (!el) return;
|
|
8323
|
-
|
|
9033
|
+
const html = el.innerHTML;
|
|
9034
|
+
lastEmittedRef.current = html;
|
|
9035
|
+
pushHistory();
|
|
9036
|
+
scheduleHighlight();
|
|
9037
|
+
onChange?.(html);
|
|
8324
9038
|
updateEmpty();
|
|
8325
9039
|
updateActiveFormats();
|
|
8326
9040
|
if (slashOpen) {
|
|
@@ -8348,6 +9062,40 @@ var Editor = (props) => {
|
|
|
8348
9062
|
};
|
|
8349
9063
|
const handleKeyDown = (e) => {
|
|
8350
9064
|
if (readOnly) return;
|
|
9065
|
+
if (composingRef.current || e.nativeEvent.isComposing || e.keyCode === 229) return;
|
|
9066
|
+
const pre = closestPre();
|
|
9067
|
+
if (pre && !slashOpen) {
|
|
9068
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
9069
|
+
const text = pre.textContent || "";
|
|
9070
|
+
if (text.endsWith("\n\n")) {
|
|
9071
|
+
e.preventDefault();
|
|
9072
|
+
const code = pre.querySelector("code") ?? pre;
|
|
9073
|
+
code.textContent = text.replace(/\n\n$/, "");
|
|
9074
|
+
ensureParagraphAfter(pre);
|
|
9075
|
+
const next = pre.nextElementSibling;
|
|
9076
|
+
if (next) placeCaretAtEnd(next);
|
|
9077
|
+
handleInput();
|
|
9078
|
+
return;
|
|
9079
|
+
}
|
|
9080
|
+
e.preventDefault();
|
|
9081
|
+
insertTextAtCaret("\n");
|
|
9082
|
+
return;
|
|
9083
|
+
}
|
|
9084
|
+
if (e.key === "Tab") {
|
|
9085
|
+
e.preventDefault();
|
|
9086
|
+
insertTextAtCaret(" ");
|
|
9087
|
+
return;
|
|
9088
|
+
}
|
|
9089
|
+
}
|
|
9090
|
+
if (e.key === "Tab" && moveTableCell(e.shiftKey)) {
|
|
9091
|
+
e.preventDefault();
|
|
9092
|
+
return;
|
|
9093
|
+
}
|
|
9094
|
+
if (e.key === "Tab" && inListItem()) {
|
|
9095
|
+
e.preventDefault();
|
|
9096
|
+
indentList(e.shiftKey);
|
|
9097
|
+
return;
|
|
9098
|
+
}
|
|
8351
9099
|
if (slashOpen) {
|
|
8352
9100
|
if (e.key === "ArrowDown") {
|
|
8353
9101
|
e.preventDefault();
|
|
@@ -8371,6 +9119,21 @@ var Editor = (props) => {
|
|
|
8371
9119
|
return;
|
|
8372
9120
|
}
|
|
8373
9121
|
}
|
|
9122
|
+
if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "z") {
|
|
9123
|
+
e.preventDefault();
|
|
9124
|
+
if (e.shiftKey) redo();
|
|
9125
|
+
else undo();
|
|
9126
|
+
return;
|
|
9127
|
+
}
|
|
9128
|
+
if ((e.metaKey || e.ctrlKey) && e.shiftKey && e.key.toLowerCase() === "v") {
|
|
9129
|
+
plainPasteRef.current = true;
|
|
9130
|
+
return;
|
|
9131
|
+
}
|
|
9132
|
+
if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "y") {
|
|
9133
|
+
e.preventDefault();
|
|
9134
|
+
redo();
|
|
9135
|
+
return;
|
|
9136
|
+
}
|
|
8374
9137
|
if ((e.metaKey || e.ctrlKey) && !e.shiftKey && !e.altKey) {
|
|
8375
9138
|
const k = e.key.toLowerCase();
|
|
8376
9139
|
if (k === "b") {
|
|
@@ -8394,6 +9157,7 @@ var Editor = (props) => {
|
|
|
8394
9157
|
return;
|
|
8395
9158
|
}
|
|
8396
9159
|
}
|
|
9160
|
+
if (pre) return;
|
|
8397
9161
|
if (enableSlashCommand && e.key === "/") {
|
|
8398
9162
|
setTimeout(openSlashMenu, 0);
|
|
8399
9163
|
}
|
|
@@ -8403,11 +9167,21 @@ var Editor = (props) => {
|
|
|
8403
9167
|
}
|
|
8404
9168
|
}
|
|
8405
9169
|
};
|
|
9170
|
+
const plainPasteRef = React22.useRef(false);
|
|
8406
9171
|
const handlePaste = (e) => {
|
|
8407
9172
|
if (readOnly) return;
|
|
8408
9173
|
e.preventDefault();
|
|
8409
|
-
const html = e.clipboardData.getData("text/html");
|
|
8410
9174
|
const text = e.clipboardData.getData("text/plain");
|
|
9175
|
+
if (plainPasteRef.current) {
|
|
9176
|
+
plainPasteRef.current = false;
|
|
9177
|
+
insertTextAtCaret(text);
|
|
9178
|
+
return;
|
|
9179
|
+
}
|
|
9180
|
+
if (closestPre()) {
|
|
9181
|
+
insertTextAtCaret(text);
|
|
9182
|
+
return;
|
|
9183
|
+
}
|
|
9184
|
+
const html = e.clipboardData.getData("text/html");
|
|
8411
9185
|
const clean = html ? sanitizeHtml(html) : escapeHtml(text);
|
|
8412
9186
|
document.execCommand("insertHTML", false, clean);
|
|
8413
9187
|
handleInput();
|
|
@@ -8429,8 +9203,11 @@ var Editor = (props) => {
|
|
|
8429
9203
|
};
|
|
8430
9204
|
const handleSelectionUpdate = () => {
|
|
8431
9205
|
updateActiveFormats();
|
|
9206
|
+
const pre = closestPre();
|
|
9207
|
+
setCodeLang(pre ? langOf(pre) : "plain");
|
|
8432
9208
|
};
|
|
8433
9209
|
const onToolbarAction = (item) => {
|
|
9210
|
+
if (closestPre() && !["code-block", "undo", "redo"].includes(item)) return;
|
|
8434
9211
|
switch (item) {
|
|
8435
9212
|
case "bold":
|
|
8436
9213
|
exec("bold");
|
|
@@ -8459,8 +9236,14 @@ var Editor = (props) => {
|
|
|
8459
9236
|
handleInput();
|
|
8460
9237
|
break;
|
|
8461
9238
|
}
|
|
8462
|
-
case "heading":
|
|
8463
|
-
|
|
9239
|
+
case "heading-1":
|
|
9240
|
+
toggleBlock("h1");
|
|
9241
|
+
break;
|
|
9242
|
+
case "heading-2":
|
|
9243
|
+
toggleBlock("h2");
|
|
9244
|
+
break;
|
|
9245
|
+
case "heading-3":
|
|
9246
|
+
toggleBlock("h3");
|
|
8464
9247
|
break;
|
|
8465
9248
|
case "list":
|
|
8466
9249
|
exec("insertUnorderedList");
|
|
@@ -8472,7 +9255,7 @@ var Editor = (props) => {
|
|
|
8472
9255
|
setBlock("blockquote");
|
|
8473
9256
|
break;
|
|
8474
9257
|
case "code-block":
|
|
8475
|
-
|
|
9258
|
+
insertCodeBlock();
|
|
8476
9259
|
break;
|
|
8477
9260
|
case "link":
|
|
8478
9261
|
openLinkEditor();
|
|
@@ -8483,6 +9266,39 @@ var Editor = (props) => {
|
|
|
8483
9266
|
case "divider":
|
|
8484
9267
|
insertDivider();
|
|
8485
9268
|
break;
|
|
9269
|
+
case "checklist":
|
|
9270
|
+
toggleChecklist();
|
|
9271
|
+
break;
|
|
9272
|
+
case "align-left":
|
|
9273
|
+
setAlign("left");
|
|
9274
|
+
break;
|
|
9275
|
+
case "align-center":
|
|
9276
|
+
setAlign("center");
|
|
9277
|
+
break;
|
|
9278
|
+
case "align-right":
|
|
9279
|
+
setAlign("right");
|
|
9280
|
+
break;
|
|
9281
|
+
case "highlight":
|
|
9282
|
+
toggleHighlight();
|
|
9283
|
+
break;
|
|
9284
|
+
case "superscript":
|
|
9285
|
+
exec("superscript");
|
|
9286
|
+
break;
|
|
9287
|
+
case "subscript":
|
|
9288
|
+
exec("subscript");
|
|
9289
|
+
break;
|
|
9290
|
+
case "table":
|
|
9291
|
+
insertTable();
|
|
9292
|
+
break;
|
|
9293
|
+
case "clear-format":
|
|
9294
|
+
clearFormat();
|
|
9295
|
+
break;
|
|
9296
|
+
case "undo":
|
|
9297
|
+
undo();
|
|
9298
|
+
break;
|
|
9299
|
+
case "redo":
|
|
9300
|
+
redo();
|
|
9301
|
+
break;
|
|
8486
9302
|
}
|
|
8487
9303
|
};
|
|
8488
9304
|
return /* @__PURE__ */ jsxs207("div", { className: clsx_default("lib-xplat-editor", isFocused && "focused", readOnly && "readonly"), children: [
|
|
@@ -8491,7 +9307,10 @@ var Editor = (props) => {
|
|
|
8491
9307
|
{
|
|
8492
9308
|
items: toolbar,
|
|
8493
9309
|
active: activeFormats,
|
|
8494
|
-
onAction: onToolbarAction
|
|
9310
|
+
onAction: onToolbarAction,
|
|
9311
|
+
codeLang,
|
|
9312
|
+
inCodeBlock: activeFormats.has("block:pre"),
|
|
9313
|
+
onCodeLangChange: changeCodeLang
|
|
8495
9314
|
}
|
|
8496
9315
|
),
|
|
8497
9316
|
/* @__PURE__ */ jsxs207("div", { className: "lib-xplat-editor__content", style: { minHeight }, children: [
|
|
@@ -8502,9 +9321,14 @@ var Editor = (props) => {
|
|
|
8502
9321
|
ref: editorRef,
|
|
8503
9322
|
contentEditable: !readOnly,
|
|
8504
9323
|
suppressContentEditableWarning: true,
|
|
9324
|
+
role: "textbox",
|
|
9325
|
+
"aria-multiline": "true",
|
|
9326
|
+
"aria-readonly": readOnly || void 0,
|
|
9327
|
+
"aria-label": placeholder,
|
|
8505
9328
|
className: "lib-xplat-editor__editable",
|
|
8506
9329
|
onInput: handleInput,
|
|
8507
9330
|
onKeyDown: handleKeyDown,
|
|
9331
|
+
onClick: handleEditorClick,
|
|
8508
9332
|
onKeyUp: handleSelectionUpdate,
|
|
8509
9333
|
onMouseUp: handleSelectionUpdate,
|
|
8510
9334
|
onPaste: handlePaste,
|
|
@@ -8546,14 +9370,27 @@ var TOOLBAR_LABEL = {
|
|
|
8546
9370
|
underline: "U",
|
|
8547
9371
|
strikethrough: "S",
|
|
8548
9372
|
code: "<>",
|
|
8549
|
-
heading: "
|
|
9373
|
+
"heading-1": "H1",
|
|
9374
|
+
"heading-2": "H2",
|
|
9375
|
+
"heading-3": "H3",
|
|
8550
9376
|
list: "\u2022",
|
|
8551
9377
|
"ordered-list": "1.",
|
|
8552
9378
|
blockquote: "\u275D",
|
|
8553
9379
|
"code-block": "[ ]",
|
|
8554
9380
|
link: "\u{1F517}",
|
|
8555
9381
|
image: "\u{1F5BC}",
|
|
8556
|
-
divider: "\u2014"
|
|
9382
|
+
divider: "\u2014",
|
|
9383
|
+
checklist: "\u2611",
|
|
9384
|
+
"align-left": "\u21E4",
|
|
9385
|
+
"align-center": "\u2194",
|
|
9386
|
+
"align-right": "\u21E5",
|
|
9387
|
+
highlight: "\u{1F58D}",
|
|
9388
|
+
superscript: "x\xB2",
|
|
9389
|
+
subscript: "x\u2082",
|
|
9390
|
+
table: "\u25A6",
|
|
9391
|
+
"clear-format": "\u232B",
|
|
9392
|
+
undo: "\u21B6",
|
|
9393
|
+
redo: "\u21B7"
|
|
8557
9394
|
};
|
|
8558
9395
|
var TOOLBAR_TITLE = {
|
|
8559
9396
|
bold: "\uAD75\uAC8C (\u2318B)",
|
|
@@ -8561,39 +9398,77 @@ var TOOLBAR_TITLE = {
|
|
|
8561
9398
|
underline: "\uBC11\uC904 (\u2318U)",
|
|
8562
9399
|
strikethrough: "\uCDE8\uC18C\uC120",
|
|
8563
9400
|
code: "\uC778\uB77C\uC778 \uCF54\uB4DC",
|
|
8564
|
-
heading: "\uC81C\uBAA9",
|
|
9401
|
+
"heading-1": "\uC81C\uBAA9 1",
|
|
9402
|
+
"heading-2": "\uC81C\uBAA9 2",
|
|
9403
|
+
"heading-3": "\uC81C\uBAA9 3",
|
|
8565
9404
|
list: "\uAE00\uBA38\uB9AC \uAE30\uD638 \uBAA9\uB85D",
|
|
8566
9405
|
"ordered-list": "\uBC88\uD638 \uB9E4\uAE30\uAE30 \uBAA9\uB85D",
|
|
8567
9406
|
blockquote: "\uC778\uC6A9",
|
|
8568
9407
|
"code-block": "\uCF54\uB4DC \uBE14\uB85D",
|
|
8569
9408
|
link: "\uB9C1\uD06C (\u2318K)",
|
|
8570
9409
|
image: "\uC774\uBBF8\uC9C0",
|
|
8571
|
-
divider: "\uAD6C\uBD84\uC120"
|
|
9410
|
+
divider: "\uAD6C\uBD84\uC120",
|
|
9411
|
+
checklist: "\uCCB4\uD06C\uB9AC\uC2A4\uD2B8",
|
|
9412
|
+
"align-left": "\uC67C\uCABD \uC815\uB82C",
|
|
9413
|
+
"align-center": "\uAC00\uC6B4\uB370 \uC815\uB82C",
|
|
9414
|
+
"align-right": "\uC624\uB978\uCABD \uC815\uB82C",
|
|
9415
|
+
highlight: "\uD615\uAD11\uD39C",
|
|
9416
|
+
superscript: "\uC704 \uCCA8\uC790",
|
|
9417
|
+
subscript: "\uC544\uB798 \uCCA8\uC790",
|
|
9418
|
+
table: "\uD45C \uC0BD\uC785",
|
|
9419
|
+
"clear-format": "\uC11C\uC2DD \uC9C0\uC6B0\uAE30",
|
|
9420
|
+
undo: "\uB418\uB3CC\uB9AC\uAE30 (\u2318Z)",
|
|
9421
|
+
redo: "\uB2E4\uC2DC\uD558\uAE30 (\u2318\u21E7Z)"
|
|
8572
9422
|
};
|
|
8573
9423
|
var isActive = (item, active) => {
|
|
8574
|
-
if (item === "heading") return active.has("block:h1")
|
|
9424
|
+
if (item === "heading-1") return active.has("block:h1");
|
|
9425
|
+
if (item === "heading-2") return active.has("block:h2");
|
|
9426
|
+
if (item === "heading-3") return active.has("block:h3");
|
|
8575
9427
|
if (item === "blockquote") return active.has("block:blockquote");
|
|
8576
9428
|
if (item === "code-block") return active.has("block:pre");
|
|
9429
|
+
if (item === "align-left") return active.has("align:left");
|
|
9430
|
+
if (item === "align-center") return active.has("align:center");
|
|
9431
|
+
if (item === "align-right") return active.has("align:right");
|
|
8577
9432
|
return active.has(item);
|
|
8578
9433
|
};
|
|
8579
|
-
var EditorToolbar = ({
|
|
8580
|
-
|
|
8581
|
-
|
|
8582
|
-
|
|
8583
|
-
|
|
8584
|
-
|
|
8585
|
-
|
|
8586
|
-
|
|
8587
|
-
|
|
8588
|
-
|
|
9434
|
+
var EditorToolbar = ({
|
|
9435
|
+
items,
|
|
9436
|
+
active,
|
|
9437
|
+
onAction,
|
|
9438
|
+
codeLang,
|
|
9439
|
+
inCodeBlock,
|
|
9440
|
+
onCodeLangChange
|
|
9441
|
+
}) => {
|
|
9442
|
+
return /* @__PURE__ */ jsxs207("div", { className: "lib-xplat-editor__toolbar", children: [
|
|
9443
|
+
items.map((item) => /* @__PURE__ */ jsx323(
|
|
9444
|
+
"button",
|
|
9445
|
+
{
|
|
9446
|
+
type: "button",
|
|
9447
|
+
className: clsx_default("lib-xplat-editor__toolbar-btn", isActive(item, active) && "active"),
|
|
9448
|
+
title: TOOLBAR_TITLE[item],
|
|
9449
|
+
onMouseDown: (e) => {
|
|
9450
|
+
e.preventDefault();
|
|
9451
|
+
onAction(item);
|
|
9452
|
+
},
|
|
9453
|
+
children: TOOLBAR_LABEL[item]
|
|
8589
9454
|
},
|
|
8590
|
-
|
|
8591
|
-
|
|
8592
|
-
|
|
8593
|
-
|
|
9455
|
+
item
|
|
9456
|
+
)),
|
|
9457
|
+
inCodeBlock && /* @__PURE__ */ jsx323(
|
|
9458
|
+
"select",
|
|
9459
|
+
{
|
|
9460
|
+
className: "lib-xplat-editor__lang",
|
|
9461
|
+
value: codeLang,
|
|
9462
|
+
"aria-label": "\uCF54\uB4DC \uC5B8\uC5B4",
|
|
9463
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
9464
|
+
onChange: (e) => onCodeLangChange(e.target.value),
|
|
9465
|
+
children: CODE_LANGUAGES.map((l) => /* @__PURE__ */ jsx323("option", { value: l.value, children: l.label }, l.value))
|
|
9466
|
+
}
|
|
9467
|
+
)
|
|
9468
|
+
] });
|
|
8594
9469
|
};
|
|
8595
9470
|
var SlashMenu = ({ position, items, activeIndex, onSelect, onClose }) => {
|
|
8596
|
-
|
|
9471
|
+
React22.useEffect(() => {
|
|
8597
9472
|
const handleClickOutside = (e) => {
|
|
8598
9473
|
const target = e.target;
|
|
8599
9474
|
const menu = document.querySelector(".lib-xplat-editor__slash-menu");
|
|
@@ -8627,8 +9502,8 @@ var SlashMenu = ({ position, items, activeIndex, onSelect, onClose }) => {
|
|
|
8627
9502
|
);
|
|
8628
9503
|
};
|
|
8629
9504
|
var LinkPopover = ({ position, value, onChange, onConfirm, onClose }) => {
|
|
8630
|
-
const inputRef =
|
|
8631
|
-
|
|
9505
|
+
const inputRef = React22.useRef(null);
|
|
9506
|
+
React22.useEffect(() => {
|
|
8632
9507
|
inputRef.current?.focus();
|
|
8633
9508
|
}, []);
|
|
8634
9509
|
return /* @__PURE__ */ jsxs207(
|
|
@@ -8686,7 +9561,7 @@ EmptyState.displayName = "EmptyState";
|
|
|
8686
9561
|
var EmptyState_default = EmptyState;
|
|
8687
9562
|
|
|
8688
9563
|
// src/components/FileUpload/FileUpload.tsx
|
|
8689
|
-
import
|
|
9564
|
+
import React23 from "react";
|
|
8690
9565
|
import { jsx as jsx325, jsxs as jsxs209 } from "react/jsx-runtime";
|
|
8691
9566
|
var FileUpload = (props) => {
|
|
8692
9567
|
const {
|
|
@@ -8698,8 +9573,8 @@ var FileUpload = (props) => {
|
|
|
8698
9573
|
description,
|
|
8699
9574
|
validations
|
|
8700
9575
|
} = props;
|
|
8701
|
-
const [isDragOver, setIsDragOver] =
|
|
8702
|
-
const inputRef =
|
|
9576
|
+
const [isDragOver, setIsDragOver] = React23.useState(false);
|
|
9577
|
+
const inputRef = React23.useRef(null);
|
|
8703
9578
|
const handleFiles = (fileList) => {
|
|
8704
9579
|
let files = Array.from(fileList);
|
|
8705
9580
|
if (maxSize) {
|
|
@@ -8761,10 +9636,10 @@ FileUpload.displayName = "FileUpload";
|
|
|
8761
9636
|
var FileUpload_default = FileUpload;
|
|
8762
9637
|
|
|
8763
9638
|
// src/components/HtmlTypeWriter/HtmlTypeWriter.tsx
|
|
8764
|
-
import
|
|
9639
|
+
import React25 from "react";
|
|
8765
9640
|
|
|
8766
9641
|
// src/components/HtmlTypeWriter/utils.ts
|
|
8767
|
-
import
|
|
9642
|
+
import React24 from "react";
|
|
8768
9643
|
var voidTags = /* @__PURE__ */ new Set([
|
|
8769
9644
|
"br",
|
|
8770
9645
|
"img",
|
|
@@ -8832,15 +9707,15 @@ var convertNodeToReactWithRange = (node, typedLen, rangeMap) => {
|
|
|
8832
9707
|
props[attr.name] = attr.value;
|
|
8833
9708
|
});
|
|
8834
9709
|
if (voidTags.has(tag)) {
|
|
8835
|
-
return
|
|
9710
|
+
return React24.createElement(tag, props);
|
|
8836
9711
|
}
|
|
8837
9712
|
const children = Array.from(element.childNodes).map((child) => convertNodeToReactWithRange(child, typedLen, rangeMap)).filter((n) => n != null);
|
|
8838
|
-
return
|
|
9713
|
+
return React24.createElement(tag, props, ...children);
|
|
8839
9714
|
};
|
|
8840
9715
|
var htmlToReactProgressive = (root, typedLen, rangeMap) => {
|
|
8841
9716
|
const nodes = Array.from(root.childNodes).map((child, idx) => {
|
|
8842
9717
|
const node = convertNodeToReactWithRange(child, typedLen, rangeMap);
|
|
8843
|
-
return node == null ? null :
|
|
9718
|
+
return node == null ? null : React24.createElement(React24.Fragment, { key: idx }, node);
|
|
8844
9719
|
}).filter(Boolean);
|
|
8845
9720
|
return nodes.length === 0 ? null : nodes;
|
|
8846
9721
|
};
|
|
@@ -8853,20 +9728,20 @@ var HtmlTypeWriter = ({
|
|
|
8853
9728
|
onDone,
|
|
8854
9729
|
onChange
|
|
8855
9730
|
}) => {
|
|
8856
|
-
const [typedLen, setTypedLen] =
|
|
8857
|
-
const doneCalledRef =
|
|
8858
|
-
const { doc, rangeMap, totalLength } =
|
|
9731
|
+
const [typedLen, setTypedLen] = React25.useState(0);
|
|
9732
|
+
const doneCalledRef = React25.useRef(false);
|
|
9733
|
+
const { doc, rangeMap, totalLength } = React25.useMemo(() => {
|
|
8859
9734
|
if (typeof window === "undefined") return { doc: null, rangeMap: /* @__PURE__ */ new Map(), totalLength: 0 };
|
|
8860
9735
|
const decoded = decodeHtmlEntities(html);
|
|
8861
9736
|
const doc2 = new DOMParser().parseFromString(decoded, "text/html");
|
|
8862
9737
|
const { rangeMap: rangeMap2, totalLength: totalLength2 } = buildRangeMap(doc2.body);
|
|
8863
9738
|
return { doc: doc2, rangeMap: rangeMap2, totalLength: totalLength2 };
|
|
8864
9739
|
}, [html]);
|
|
8865
|
-
|
|
9740
|
+
React25.useEffect(() => {
|
|
8866
9741
|
setTypedLen(0);
|
|
8867
9742
|
doneCalledRef.current = false;
|
|
8868
9743
|
}, [html]);
|
|
8869
|
-
|
|
9744
|
+
React25.useEffect(() => {
|
|
8870
9745
|
if (!totalLength) return;
|
|
8871
9746
|
if (typedLen >= totalLength) return;
|
|
8872
9747
|
const timer = window.setInterval(() => {
|
|
@@ -8874,18 +9749,18 @@ var HtmlTypeWriter = ({
|
|
|
8874
9749
|
}, duration);
|
|
8875
9750
|
return () => window.clearInterval(timer);
|
|
8876
9751
|
}, [typedLen, totalLength, duration]);
|
|
8877
|
-
|
|
9752
|
+
React25.useEffect(() => {
|
|
8878
9753
|
if (typedLen > 0 && typedLen < totalLength) {
|
|
8879
9754
|
onChange?.();
|
|
8880
9755
|
}
|
|
8881
9756
|
}, [typedLen, totalLength, onChange]);
|
|
8882
|
-
|
|
9757
|
+
React25.useEffect(() => {
|
|
8883
9758
|
if (typedLen === totalLength && totalLength > 0 && !doneCalledRef.current) {
|
|
8884
9759
|
doneCalledRef.current = true;
|
|
8885
9760
|
onDone?.();
|
|
8886
9761
|
}
|
|
8887
9762
|
}, [typedLen, totalLength, onDone]);
|
|
8888
|
-
const parsed =
|
|
9763
|
+
const parsed = React25.useMemo(
|
|
8889
9764
|
() => doc ? htmlToReactProgressive(doc.body, typedLen, rangeMap) : null,
|
|
8890
9765
|
[doc, typedLen, rangeMap]
|
|
8891
9766
|
);
|
|
@@ -8895,12 +9770,12 @@ HtmlTypeWriter.displayName = "HtmlTypeWriter";
|
|
|
8895
9770
|
var HtmlTypeWriter_default = HtmlTypeWriter;
|
|
8896
9771
|
|
|
8897
9772
|
// src/components/ImageSelector/ImageSelector.tsx
|
|
8898
|
-
import
|
|
9773
|
+
import React26 from "react";
|
|
8899
9774
|
import { jsx as jsx327, jsxs as jsxs210 } from "react/jsx-runtime";
|
|
8900
9775
|
var ImageSelector = (props) => {
|
|
8901
9776
|
const { value, label, onChange, validations } = props;
|
|
8902
|
-
const [previewUrl, setPreviewUrl] =
|
|
8903
|
-
|
|
9777
|
+
const [previewUrl, setPreviewUrl] = React26.useState();
|
|
9778
|
+
React26.useEffect(() => {
|
|
8904
9779
|
if (!value) {
|
|
8905
9780
|
setPreviewUrl(void 0);
|
|
8906
9781
|
return;
|
|
@@ -8909,7 +9784,7 @@ var ImageSelector = (props) => {
|
|
|
8909
9784
|
setPreviewUrl(url);
|
|
8910
9785
|
return () => URL.revokeObjectURL(url);
|
|
8911
9786
|
}, [value]);
|
|
8912
|
-
const inputRef =
|
|
9787
|
+
const inputRef = React26.useRef(null);
|
|
8913
9788
|
const handleFileChange = (e) => {
|
|
8914
9789
|
const selectedFile = e.target.files?.[0];
|
|
8915
9790
|
if (selectedFile) {
|
|
@@ -9092,17 +9967,21 @@ Pagination.displayName = "Pagination";
|
|
|
9092
9967
|
var Pagination_default = Pagination;
|
|
9093
9968
|
|
|
9094
9969
|
// src/components/PopOver/PopOver.tsx
|
|
9095
|
-
import
|
|
9970
|
+
import React27 from "react";
|
|
9096
9971
|
import { jsx as jsx332, jsxs as jsxs213 } from "react/jsx-runtime";
|
|
9097
9972
|
var PopOver = (props) => {
|
|
9098
9973
|
const { children, isOpen, onClose, PopOverEl } = props;
|
|
9099
|
-
const popRef =
|
|
9100
|
-
const triggerRef =
|
|
9101
|
-
const [localOpen, setLocalOpen] =
|
|
9102
|
-
const [eventTrigger, setEventTrigger] =
|
|
9974
|
+
const popRef = React27.useRef(null);
|
|
9975
|
+
const triggerRef = React27.useRef(null);
|
|
9976
|
+
const [localOpen, setLocalOpen] = React27.useState(false);
|
|
9977
|
+
const [eventTrigger, setEventTrigger] = React27.useState(false);
|
|
9103
9978
|
useClickOutside_default([popRef, triggerRef], onClose, isOpen);
|
|
9979
|
+
useEscapeKey(isOpen, () => {
|
|
9980
|
+
onClose();
|
|
9981
|
+
triggerRef.current?.focus({ preventScroll: true });
|
|
9982
|
+
});
|
|
9104
9983
|
const position = useAutoPosition_default(triggerRef, popRef, localOpen);
|
|
9105
|
-
|
|
9984
|
+
React27.useEffect(() => {
|
|
9106
9985
|
if (isOpen) {
|
|
9107
9986
|
setLocalOpen(isOpen);
|
|
9108
9987
|
setTimeout(() => {
|
|
@@ -9131,6 +10010,7 @@ var PopOver = (props) => {
|
|
|
9131
10010
|
className: clsx_default(
|
|
9132
10011
|
"lib-xplat-pop-over-content",
|
|
9133
10012
|
position.direction,
|
|
10013
|
+
position.repositioning && "repositioning",
|
|
9134
10014
|
eventTrigger && "visible"
|
|
9135
10015
|
),
|
|
9136
10016
|
ref: popRef,
|
|
@@ -9187,12 +10067,12 @@ Progress.displayName = "Progress";
|
|
|
9187
10067
|
var Progress_default = Progress;
|
|
9188
10068
|
|
|
9189
10069
|
// src/components/Radio/RadioGroupContext.tsx
|
|
9190
|
-
import
|
|
9191
|
-
var RadioGroupContext =
|
|
10070
|
+
import React28 from "react";
|
|
10071
|
+
var RadioGroupContext = React28.createContext(
|
|
9192
10072
|
null
|
|
9193
10073
|
);
|
|
9194
10074
|
var useRadioGroupContext = () => {
|
|
9195
|
-
return
|
|
10075
|
+
return React28.useContext(RadioGroupContext);
|
|
9196
10076
|
};
|
|
9197
10077
|
var RadioGroupContext_default = RadioGroupContext;
|
|
9198
10078
|
|
|
@@ -9268,19 +10148,19 @@ RadioGroup.displayName = "RadioGroup";
|
|
|
9268
10148
|
var RadioGroup_default = RadioGroup;
|
|
9269
10149
|
|
|
9270
10150
|
// src/components/Select/Select.tsx
|
|
9271
|
-
import
|
|
10151
|
+
import React31 from "react";
|
|
9272
10152
|
|
|
9273
10153
|
// src/components/Select/context.ts
|
|
9274
|
-
import
|
|
9275
|
-
var SelectContext =
|
|
10154
|
+
import React29 from "react";
|
|
10155
|
+
var SelectContext = React29.createContext(null);
|
|
9276
10156
|
var context_default = SelectContext;
|
|
9277
10157
|
|
|
9278
10158
|
// src/components/Select/SelectItem.tsx
|
|
9279
|
-
import
|
|
10159
|
+
import React30 from "react";
|
|
9280
10160
|
import { jsx as jsx336 } from "react/jsx-runtime";
|
|
9281
10161
|
var SelectItem = (props) => {
|
|
9282
10162
|
const { children, value, onClick, disabled = false } = props;
|
|
9283
|
-
const ctx =
|
|
10163
|
+
const ctx = React30.useContext(context_default);
|
|
9284
10164
|
const handleClick = (e) => {
|
|
9285
10165
|
e.preventDefault();
|
|
9286
10166
|
e.stopPropagation();
|
|
@@ -9320,32 +10200,37 @@ var SelectRoot = (props) => {
|
|
|
9320
10200
|
onChange,
|
|
9321
10201
|
children,
|
|
9322
10202
|
disabled = false,
|
|
10203
|
+
searchable = false,
|
|
10204
|
+
searchPlaceholder = "\uAC80\uC0C9",
|
|
9323
10205
|
error = false,
|
|
9324
10206
|
validations,
|
|
10207
|
+
label,
|
|
10208
|
+
required,
|
|
9325
10209
|
size = "md"
|
|
9326
10210
|
} = props;
|
|
9327
|
-
const
|
|
9328
|
-
|
|
10211
|
+
const fieldId = React31.useId();
|
|
10212
|
+
const itemChildren = React31.Children.toArray(children).filter(
|
|
10213
|
+
(child) => React31.isValidElement(child) && child.type === SelectItem_default
|
|
9329
10214
|
);
|
|
9330
10215
|
const isControlled = valueProp !== void 0;
|
|
9331
|
-
const [isOpen, setOpen] =
|
|
9332
|
-
const [uncontrolledLabel, setUncontrolledLabel] =
|
|
9333
|
-
const [uncontrolledValue, setUncontrolledValue] =
|
|
9334
|
-
const controlledLabel =
|
|
10216
|
+
const [isOpen, setOpen] = React31.useState(false);
|
|
10217
|
+
const [uncontrolledLabel, setUncontrolledLabel] = React31.useState(null);
|
|
10218
|
+
const [uncontrolledValue, setUncontrolledValue] = React31.useState(void 0);
|
|
10219
|
+
const controlledLabel = React31.useMemo(() => {
|
|
9335
10220
|
if (!isControlled) return null;
|
|
9336
10221
|
const match = itemChildren.find((child) => child.props.value === valueProp);
|
|
9337
10222
|
return match ? match.props.children : null;
|
|
9338
10223
|
}, [isControlled, valueProp, itemChildren]);
|
|
9339
10224
|
const selectedLabel = isControlled ? controlledLabel : uncontrolledLabel;
|
|
9340
10225
|
const selectedValue = isControlled ? valueProp : uncontrolledValue;
|
|
9341
|
-
const triggerRef =
|
|
9342
|
-
const contentRef =
|
|
9343
|
-
const [mounted, setMounted] =
|
|
9344
|
-
const [visible, setVisible] =
|
|
9345
|
-
|
|
10226
|
+
const triggerRef = React31.useRef(null);
|
|
10227
|
+
const contentRef = React31.useRef(null);
|
|
10228
|
+
const [mounted, setMounted] = React31.useState(false);
|
|
10229
|
+
const [visible, setVisible] = React31.useState(false);
|
|
10230
|
+
React31.useEffect(() => {
|
|
9346
10231
|
if (disabled && isOpen) setOpen(false);
|
|
9347
10232
|
}, [disabled, isOpen]);
|
|
9348
|
-
|
|
10233
|
+
React31.useEffect(() => {
|
|
9349
10234
|
if (isOpen) {
|
|
9350
10235
|
setMounted(true);
|
|
9351
10236
|
const t2 = setTimeout(() => setVisible(true), 1);
|
|
@@ -9355,22 +10240,42 @@ var SelectRoot = (props) => {
|
|
|
9355
10240
|
const t = setTimeout(() => setMounted(false), ANIMATION_DURATION_MS3);
|
|
9356
10241
|
return () => clearTimeout(t);
|
|
9357
10242
|
}, [isOpen]);
|
|
9358
|
-
const
|
|
9359
|
-
const
|
|
9360
|
-
|
|
10243
|
+
const [query, setQuery] = React31.useState("");
|
|
10244
|
+
const textOf = (node) => {
|
|
10245
|
+
if (node === null || node === void 0 || typeof node === "boolean") return "";
|
|
10246
|
+
if (typeof node === "string" || typeof node === "number") return String(node);
|
|
10247
|
+
if (Array.isArray(node)) return node.map(textOf).join("");
|
|
10248
|
+
if (React31.isValidElement(node)) return textOf(node.props.children);
|
|
10249
|
+
return "";
|
|
10250
|
+
};
|
|
10251
|
+
const visibleItems = React31.useMemo(() => {
|
|
10252
|
+
if (!searchable || !query.trim()) return itemChildren;
|
|
10253
|
+
const q = query.trim().toLowerCase();
|
|
10254
|
+
return itemChildren.filter((c) => textOf(c.props.children).toLowerCase().includes(q));
|
|
10255
|
+
}, [searchable, query, itemChildren]);
|
|
10256
|
+
const open = React31.useCallback(() => setOpen(true), []);
|
|
10257
|
+
const close = React31.useCallback(() => {
|
|
10258
|
+
setOpen(false);
|
|
10259
|
+
setQuery("");
|
|
10260
|
+
}, []);
|
|
10261
|
+
const toggle = React31.useCallback(() => setOpen((prev) => !prev), []);
|
|
9361
10262
|
useClickOutside_default([contentRef, triggerRef], close, isOpen);
|
|
10263
|
+
useEscapeKey(isOpen, () => {
|
|
10264
|
+
close();
|
|
10265
|
+
triggerRef.current?.focus({ preventScroll: true });
|
|
10266
|
+
});
|
|
9362
10267
|
const position = useAutoPosition_default(triggerRef, contentRef, mounted);
|
|
9363
|
-
const setSelected =
|
|
9364
|
-
(
|
|
10268
|
+
const setSelected = React31.useCallback(
|
|
10269
|
+
(label2, itemValue) => {
|
|
9365
10270
|
if (!isControlled) {
|
|
9366
|
-
setUncontrolledLabel(
|
|
10271
|
+
setUncontrolledLabel(label2);
|
|
9367
10272
|
setUncontrolledValue(itemValue);
|
|
9368
10273
|
}
|
|
9369
|
-
onChange?.(itemValue,
|
|
10274
|
+
onChange?.(itemValue, label2);
|
|
9370
10275
|
},
|
|
9371
10276
|
[isControlled, onChange]
|
|
9372
10277
|
);
|
|
9373
|
-
const ctxValue =
|
|
10278
|
+
const ctxValue = React31.useMemo(
|
|
9374
10279
|
() => ({
|
|
9375
10280
|
isOpen,
|
|
9376
10281
|
mounted,
|
|
@@ -9406,6 +10311,7 @@ var SelectRoot = (props) => {
|
|
|
9406
10311
|
/* @__PURE__ */ jsxs216(
|
|
9407
10312
|
"div",
|
|
9408
10313
|
{
|
|
10314
|
+
id: fieldId,
|
|
9409
10315
|
ref: triggerRef,
|
|
9410
10316
|
className: clsx_default(
|
|
9411
10317
|
"select-trigger",
|
|
@@ -9448,20 +10354,33 @@ var SelectRoot = (props) => {
|
|
|
9448
10354
|
]
|
|
9449
10355
|
}
|
|
9450
10356
|
),
|
|
9451
|
-
mounted && /* @__PURE__ */ jsx337(Portal_default, { children: /* @__PURE__ */
|
|
10357
|
+
mounted && /* @__PURE__ */ jsx337(Portal_default, { children: /* @__PURE__ */ jsxs216(
|
|
9452
10358
|
"div",
|
|
9453
10359
|
{
|
|
9454
|
-
className: clsx_default("lib-xplat-select-content", size, position.direction, stateClass),
|
|
10360
|
+
className: clsx_default("lib-xplat-select-content", size, position.direction, stateClass, position.repositioning && "repositioning"),
|
|
9455
10361
|
ref: contentRef,
|
|
9456
10362
|
style: { ...position.position, width: triggerRef.current?.offsetWidth },
|
|
9457
10363
|
role: "listbox",
|
|
9458
|
-
children:
|
|
10364
|
+
children: [
|
|
10365
|
+
searchable && /* @__PURE__ */ jsx337("div", { className: "select-search", children: /* @__PURE__ */ jsx337(
|
|
10366
|
+
"input",
|
|
10367
|
+
{
|
|
10368
|
+
type: "text",
|
|
10369
|
+
value: query,
|
|
10370
|
+
placeholder: searchPlaceholder,
|
|
10371
|
+
onChange: (e) => setQuery(e.target.value),
|
|
10372
|
+
autoFocus: true,
|
|
10373
|
+
"aria-label": searchPlaceholder
|
|
10374
|
+
}
|
|
10375
|
+
) }),
|
|
10376
|
+
/* @__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" }) })
|
|
10377
|
+
]
|
|
9459
10378
|
}
|
|
9460
10379
|
) })
|
|
9461
10380
|
]
|
|
9462
10381
|
}
|
|
9463
10382
|
) });
|
|
9464
|
-
return /* @__PURE__ */ jsx337(Field, { validations, children: control });
|
|
10383
|
+
return /* @__PURE__ */ jsx337(Field, { validations, label, required, htmlFor: fieldId, children: control });
|
|
9465
10384
|
};
|
|
9466
10385
|
SelectRoot.displayName = "Select";
|
|
9467
10386
|
var Select = Object.assign(SelectRoot, {
|
|
@@ -9541,8 +10460,44 @@ var Spinner = (props) => {
|
|
|
9541
10460
|
Spinner.displayName = "Spinner";
|
|
9542
10461
|
var Spinner_default = Spinner;
|
|
9543
10462
|
|
|
9544
|
-
// src/components/
|
|
10463
|
+
// src/components/Stat/Stat.tsx
|
|
9545
10464
|
import { jsx as jsx340, jsxs as jsxs218 } from "react/jsx-runtime";
|
|
10465
|
+
var ARROW = {
|
|
10466
|
+
up: "\u25B2",
|
|
10467
|
+
down: "\u25BC",
|
|
10468
|
+
flat: "\u2014"
|
|
10469
|
+
};
|
|
10470
|
+
var Stat = (props) => {
|
|
10471
|
+
const {
|
|
10472
|
+
label,
|
|
10473
|
+
value,
|
|
10474
|
+
unit,
|
|
10475
|
+
description,
|
|
10476
|
+
trend,
|
|
10477
|
+
icon,
|
|
10478
|
+
size = "md",
|
|
10479
|
+
type = "primary"
|
|
10480
|
+
} = props;
|
|
10481
|
+
const statusType = normalizeStatus(type);
|
|
10482
|
+
return /* @__PURE__ */ jsxs218("div", { className: clsx_default("lib-xplat-stat", size, statusType), children: [
|
|
10483
|
+
/* @__PURE__ */ jsx340("div", { className: "stat-label", children: label }),
|
|
10484
|
+
/* @__PURE__ */ jsxs218("div", { className: "stat-value-row", children: [
|
|
10485
|
+
icon && /* @__PURE__ */ jsx340("span", { className: "stat-icon", children: icon }),
|
|
10486
|
+
/* @__PURE__ */ jsx340("span", { className: "stat-value", children: value }),
|
|
10487
|
+
unit && /* @__PURE__ */ jsx340("span", { className: "stat-unit", children: unit }),
|
|
10488
|
+
trend && /* @__PURE__ */ jsxs218("span", { className: clsx_default("stat-trend", trend.direction), children: [
|
|
10489
|
+
/* @__PURE__ */ jsx340("span", { "aria-hidden": "true", children: ARROW[trend.direction] }),
|
|
10490
|
+
trend.value
|
|
10491
|
+
] })
|
|
10492
|
+
] }),
|
|
10493
|
+
description && /* @__PURE__ */ jsx340("div", { className: "stat-description", children: description })
|
|
10494
|
+
] });
|
|
10495
|
+
};
|
|
10496
|
+
Stat.displayName = "Stat";
|
|
10497
|
+
var Stat_default = Stat;
|
|
10498
|
+
|
|
10499
|
+
// src/components/Steps/Steps.tsx
|
|
10500
|
+
import { jsx as jsx341, jsxs as jsxs219 } from "react/jsx-runtime";
|
|
9546
10501
|
var Steps = (props) => {
|
|
9547
10502
|
const {
|
|
9548
10503
|
items,
|
|
@@ -9550,13 +10505,13 @@ var Steps = (props) => {
|
|
|
9550
10505
|
type = "primary"
|
|
9551
10506
|
} = props;
|
|
9552
10507
|
const statusType = normalizeStatus(type);
|
|
9553
|
-
return /* @__PURE__ */
|
|
10508
|
+
return /* @__PURE__ */ jsx341("div", { className: clsx_default("lib-xplat-steps", statusType), children: items.map((item, index) => {
|
|
9554
10509
|
const status = index < current ? "completed" : index === current ? "active" : "pending";
|
|
9555
|
-
return /* @__PURE__ */
|
|
9556
|
-
/* @__PURE__ */
|
|
9557
|
-
/* @__PURE__ */
|
|
9558
|
-
/* @__PURE__ */
|
|
9559
|
-
item.description && /* @__PURE__ */
|
|
10510
|
+
return /* @__PURE__ */ jsxs219("div", { className: clsx_default("step-item", status), children: [
|
|
10511
|
+
/* @__PURE__ */ jsx341("div", { className: "step-circle", children: status === "completed" ? /* @__PURE__ */ jsx341(CheckIcon_default, {}) : /* @__PURE__ */ jsx341("span", { children: index + 1 }) }),
|
|
10512
|
+
/* @__PURE__ */ jsxs219("div", { className: "step-content", children: [
|
|
10513
|
+
/* @__PURE__ */ jsx341("span", { className: "step-title", children: item.title }),
|
|
10514
|
+
item.description && /* @__PURE__ */ jsx341("span", { className: "step-description", children: item.description })
|
|
9560
10515
|
] })
|
|
9561
10516
|
] }, index);
|
|
9562
10517
|
}) });
|
|
@@ -9565,8 +10520,8 @@ Steps.displayName = "Steps";
|
|
|
9565
10520
|
var Steps_default = Steps;
|
|
9566
10521
|
|
|
9567
10522
|
// src/components/Swiper/Swiper.tsx
|
|
9568
|
-
import
|
|
9569
|
-
import { jsx as
|
|
10523
|
+
import React32 from "react";
|
|
10524
|
+
import { jsx as jsx342, jsxs as jsxs220 } from "react/jsx-runtime";
|
|
9570
10525
|
var Swiper = (props) => {
|
|
9571
10526
|
const {
|
|
9572
10527
|
auto = false,
|
|
@@ -9590,26 +10545,26 @@ var Swiper = (props) => {
|
|
|
9590
10545
|
const maxIndex = Math.max(0, totalSlides - viewItemCount);
|
|
9591
10546
|
const useLoop = loop && canSlide;
|
|
9592
10547
|
const cloneCount = useLoop ? totalSlides : 0;
|
|
9593
|
-
const extendedItems =
|
|
10548
|
+
const extendedItems = React32.useMemo(() => {
|
|
9594
10549
|
if (!useLoop) return items;
|
|
9595
10550
|
return [...items, ...items, ...items];
|
|
9596
10551
|
}, [items, useLoop]);
|
|
9597
10552
|
const initialIdx = Math.max(0, Math.min(indexProp ?? 0, maxIndex));
|
|
9598
|
-
const [innerIndex, setInnerIndex] =
|
|
10553
|
+
const [innerIndex, setInnerIndex] = React32.useState(
|
|
9599
10554
|
useLoop ? cloneCount + initialIdx : initialIdx
|
|
9600
10555
|
);
|
|
9601
|
-
const [isDragging, setIsDragging] =
|
|
9602
|
-
const [dragOffset, setDragOffset] =
|
|
9603
|
-
const [animated, setAnimated] =
|
|
9604
|
-
const [containerWidth, setContainerWidth] =
|
|
9605
|
-
const containerRef =
|
|
9606
|
-
const startXRef =
|
|
9607
|
-
const startTimeRef =
|
|
9608
|
-
const autoplayTimerRef =
|
|
9609
|
-
const resumeTimeoutRef =
|
|
9610
|
-
const [paused, setPaused] =
|
|
9611
|
-
const initializedRef =
|
|
9612
|
-
|
|
10556
|
+
const [isDragging, setIsDragging] = React32.useState(false);
|
|
10557
|
+
const [dragOffset, setDragOffset] = React32.useState(0);
|
|
10558
|
+
const [animated, setAnimated] = React32.useState(false);
|
|
10559
|
+
const [containerWidth, setContainerWidth] = React32.useState(0);
|
|
10560
|
+
const containerRef = React32.useRef(null);
|
|
10561
|
+
const startXRef = React32.useRef(0);
|
|
10562
|
+
const startTimeRef = React32.useRef(0);
|
|
10563
|
+
const autoplayTimerRef = React32.useRef(null);
|
|
10564
|
+
const resumeTimeoutRef = React32.useRef(null);
|
|
10565
|
+
const [paused, setPaused] = React32.useState(false);
|
|
10566
|
+
const initializedRef = React32.useRef(false);
|
|
10567
|
+
React32.useEffect(() => {
|
|
9613
10568
|
const el = containerRef.current;
|
|
9614
10569
|
if (!el) return;
|
|
9615
10570
|
const ro = new ResizeObserver((entries) => {
|
|
@@ -9632,7 +10587,7 @@ var Swiper = (props) => {
|
|
|
9632
10587
|
return ((inner - cloneCount) % totalSlides + totalSlides) % totalSlides;
|
|
9633
10588
|
};
|
|
9634
10589
|
const realIndex = getRealIndex(innerIndex);
|
|
9635
|
-
const moveToInner =
|
|
10590
|
+
const moveToInner = React32.useCallback(
|
|
9636
10591
|
(idx, withAnim = true) => {
|
|
9637
10592
|
if (!useLoop) {
|
|
9638
10593
|
setAnimated(withAnim);
|
|
@@ -9660,7 +10615,7 @@ var Swiper = (props) => {
|
|
|
9660
10615
|
},
|
|
9661
10616
|
[useLoop, cloneCount, totalSlides]
|
|
9662
10617
|
);
|
|
9663
|
-
const handleTransitionEnd =
|
|
10618
|
+
const handleTransitionEnd = React32.useCallback(() => {
|
|
9664
10619
|
if (!useLoop) return;
|
|
9665
10620
|
const real = getRealIndex(innerIndex);
|
|
9666
10621
|
const canonical = cloneCount + real;
|
|
@@ -9670,7 +10625,7 @@ var Swiper = (props) => {
|
|
|
9670
10625
|
}
|
|
9671
10626
|
onChange?.(Math.min(real, maxIndex));
|
|
9672
10627
|
}, [useLoop, innerIndex, cloneCount, totalSlides, maxIndex, onChange]);
|
|
9673
|
-
const slideTo =
|
|
10628
|
+
const slideTo = React32.useCallback(
|
|
9674
10629
|
(logicalIndex) => {
|
|
9675
10630
|
if (!canSlide) return;
|
|
9676
10631
|
const clamped = useLoop ? logicalIndex : Math.max(0, Math.min(logicalIndex, maxIndex));
|
|
@@ -9680,7 +10635,7 @@ var Swiper = (props) => {
|
|
|
9680
10635
|
},
|
|
9681
10636
|
[canSlide, useLoop, cloneCount, maxIndex, onChange, moveToInner]
|
|
9682
10637
|
);
|
|
9683
|
-
const slideNext =
|
|
10638
|
+
const slideNext = React32.useCallback(() => {
|
|
9684
10639
|
if (!canSlide) return;
|
|
9685
10640
|
const nextInner = innerIndex + slideBy;
|
|
9686
10641
|
if (useLoop) {
|
|
@@ -9689,7 +10644,7 @@ var Swiper = (props) => {
|
|
|
9689
10644
|
moveToInner(Math.min(nextInner, maxIndex), true);
|
|
9690
10645
|
}
|
|
9691
10646
|
}, [canSlide, useLoop, innerIndex, slideBy, maxIndex, moveToInner]);
|
|
9692
|
-
const slidePrev =
|
|
10647
|
+
const slidePrev = React32.useCallback(() => {
|
|
9693
10648
|
if (!canSlide) return;
|
|
9694
10649
|
const prevInner = innerIndex - slideBy;
|
|
9695
10650
|
if (useLoop) {
|
|
@@ -9698,7 +10653,7 @@ var Swiper = (props) => {
|
|
|
9698
10653
|
moveToInner(Math.max(prevInner, 0), true);
|
|
9699
10654
|
}
|
|
9700
10655
|
}, [canSlide, useLoop, innerIndex, slideBy, moveToInner]);
|
|
9701
|
-
|
|
10656
|
+
React32.useEffect(() => {
|
|
9702
10657
|
if (indexProp === void 0) return;
|
|
9703
10658
|
const clamped = Math.max(0, Math.min(indexProp, maxIndex));
|
|
9704
10659
|
const target = useLoop ? cloneCount + clamped : clamped;
|
|
@@ -9706,12 +10661,12 @@ var Swiper = (props) => {
|
|
|
9706
10661
|
moveToInner(target, true);
|
|
9707
10662
|
}
|
|
9708
10663
|
}, [indexProp]);
|
|
9709
|
-
|
|
10664
|
+
React32.useImperativeHandle(swiperRef, () => ({
|
|
9710
10665
|
slidePrev,
|
|
9711
10666
|
slideNext,
|
|
9712
10667
|
slideTo
|
|
9713
10668
|
}));
|
|
9714
|
-
|
|
10669
|
+
React32.useEffect(() => {
|
|
9715
10670
|
if (!auto || !canSlide || paused) return;
|
|
9716
10671
|
autoplayTimerRef.current = setInterval(slideNext, autoplayDelay);
|
|
9717
10672
|
return () => {
|
|
@@ -9737,7 +10692,7 @@ var Swiper = (props) => {
|
|
|
9737
10692
|
resumeTimeoutRef.current = null;
|
|
9738
10693
|
}, pauseOnInteraction);
|
|
9739
10694
|
};
|
|
9740
|
-
|
|
10695
|
+
React32.useEffect(() => {
|
|
9741
10696
|
return () => {
|
|
9742
10697
|
if (resumeTimeoutRef.current) clearTimeout(resumeTimeoutRef.current);
|
|
9743
10698
|
};
|
|
@@ -9755,7 +10710,7 @@ var Swiper = (props) => {
|
|
|
9755
10710
|
startXRef.current = getClientX(e);
|
|
9756
10711
|
startTimeRef.current = Date.now();
|
|
9757
10712
|
};
|
|
9758
|
-
|
|
10713
|
+
React32.useEffect(() => {
|
|
9759
10714
|
if (!isDragging) return;
|
|
9760
10715
|
const handleMove = (e) => {
|
|
9761
10716
|
setDragOffset(getClientX(e) - startXRef.current);
|
|
@@ -9794,8 +10749,8 @@ var Swiper = (props) => {
|
|
|
9794
10749
|
}, [isDragging, dragOffset, innerIndex, useLoop, maxIndex, slideStep, moveToInner]);
|
|
9795
10750
|
const slideWidthPercent = 100 / viewItemCount;
|
|
9796
10751
|
const gapAdjust = spaceBetween * (viewItemCount - 1) / viewItemCount;
|
|
9797
|
-
const slideElements =
|
|
9798
|
-
() => extendedItems.map((item, idx) => /* @__PURE__ */
|
|
10752
|
+
const slideElements = React32.useMemo(
|
|
10753
|
+
() => extendedItems.map((item, idx) => /* @__PURE__ */ jsx342(
|
|
9799
10754
|
"div",
|
|
9800
10755
|
{
|
|
9801
10756
|
className: "lib-xplat-swiper__slide",
|
|
@@ -9814,15 +10769,15 @@ var Swiper = (props) => {
|
|
|
9814
10769
|
Math.floor(realIndex / slideBy),
|
|
9815
10770
|
totalSteps - 1
|
|
9816
10771
|
);
|
|
9817
|
-
return /* @__PURE__ */
|
|
9818
|
-
/* @__PURE__ */
|
|
10772
|
+
return /* @__PURE__ */ jsxs220("div", { className: "lib-xplat-swiper", ref: containerRef, children: [
|
|
10773
|
+
/* @__PURE__ */ jsx342(
|
|
9819
10774
|
"div",
|
|
9820
10775
|
{
|
|
9821
10776
|
className: "lib-xplat-swiper__viewport",
|
|
9822
10777
|
onMouseDown: handleDragStart,
|
|
9823
10778
|
onTouchStart: handleDragStart,
|
|
9824
10779
|
onDragStart: (e) => e.preventDefault(),
|
|
9825
|
-
children: /* @__PURE__ */
|
|
10780
|
+
children: /* @__PURE__ */ jsx342(
|
|
9826
10781
|
"div",
|
|
9827
10782
|
{
|
|
9828
10783
|
className: clsx_default(
|
|
@@ -9840,7 +10795,7 @@ var Swiper = (props) => {
|
|
|
9840
10795
|
)
|
|
9841
10796
|
}
|
|
9842
10797
|
),
|
|
9843
|
-
showProgress && canSlide && /* @__PURE__ */
|
|
10798
|
+
showProgress && canSlide && /* @__PURE__ */ jsx342("div", { className: "lib-xplat-swiper__progress", children: /* @__PURE__ */ jsx342("div", { className: "lib-xplat-swiper__progress-track", children: /* @__PURE__ */ jsx342(
|
|
9844
10799
|
"span",
|
|
9845
10800
|
{
|
|
9846
10801
|
className: "lib-xplat-swiper__progress-fill",
|
|
@@ -9850,7 +10805,7 @@ var Swiper = (props) => {
|
|
|
9850
10805
|
}
|
|
9851
10806
|
}
|
|
9852
10807
|
) }) }),
|
|
9853
|
-
canSlide && /* @__PURE__ */
|
|
10808
|
+
canSlide && /* @__PURE__ */ jsx342("div", { className: "lib-xplat-swiper__dots", children: Array.from({ length: totalSteps }, (_, i) => /* @__PURE__ */ jsx342(
|
|
9854
10809
|
"button",
|
|
9855
10810
|
{
|
|
9856
10811
|
className: clsx_default(
|
|
@@ -9868,8 +10823,8 @@ Swiper.displayName = "Swiper";
|
|
|
9868
10823
|
var Swiper_default = Swiper;
|
|
9869
10824
|
|
|
9870
10825
|
// src/components/Switch/Switch.tsx
|
|
9871
|
-
import
|
|
9872
|
-
import { jsx as
|
|
10826
|
+
import React33 from "react";
|
|
10827
|
+
import { jsx as jsx343 } from "react/jsx-runtime";
|
|
9873
10828
|
var KNOB_TRANSITION_MS = 250;
|
|
9874
10829
|
var Switch = (props) => {
|
|
9875
10830
|
const {
|
|
@@ -9878,12 +10833,15 @@ var Switch = (props) => {
|
|
|
9878
10833
|
type = "primary",
|
|
9879
10834
|
disabled,
|
|
9880
10835
|
onChange,
|
|
9881
|
-
validations
|
|
10836
|
+
validations,
|
|
10837
|
+
label,
|
|
10838
|
+
required
|
|
9882
10839
|
} = props;
|
|
10840
|
+
const fieldId = React33.useId();
|
|
9883
10841
|
const statusType = normalizeStatus(type);
|
|
9884
|
-
const [isAnimating, setIsAnimating] =
|
|
9885
|
-
const timeoutRef =
|
|
9886
|
-
|
|
10842
|
+
const [isAnimating, setIsAnimating] = React33.useState(false);
|
|
10843
|
+
const timeoutRef = React33.useRef(null);
|
|
10844
|
+
React33.useEffect(() => {
|
|
9887
10845
|
return () => {
|
|
9888
10846
|
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
9889
10847
|
};
|
|
@@ -9898,9 +10856,10 @@ var Switch = (props) => {
|
|
|
9898
10856
|
timeoutRef.current = null;
|
|
9899
10857
|
}, KNOB_TRANSITION_MS);
|
|
9900
10858
|
};
|
|
9901
|
-
const control = /* @__PURE__ */
|
|
10859
|
+
const control = /* @__PURE__ */ jsx343(
|
|
9902
10860
|
"div",
|
|
9903
10861
|
{
|
|
10862
|
+
id: fieldId,
|
|
9904
10863
|
className: clsx_default(
|
|
9905
10864
|
"lib-xplat-switch",
|
|
9906
10865
|
size,
|
|
@@ -9912,26 +10871,26 @@ var Switch = (props) => {
|
|
|
9912
10871
|
onClick: handleClick,
|
|
9913
10872
|
"aria-invalid": hasError(validations) || void 0,
|
|
9914
10873
|
"aria-disabled": disabled || isAnimating,
|
|
9915
|
-
children: /* @__PURE__ */
|
|
10874
|
+
children: /* @__PURE__ */ jsx343("div", { className: clsx_default("knob", value ? "checked" : void 0) })
|
|
9916
10875
|
}
|
|
9917
10876
|
);
|
|
9918
|
-
return /* @__PURE__ */
|
|
10877
|
+
return /* @__PURE__ */ jsx343(Field, { validations, label, required, htmlFor: fieldId, children: control });
|
|
9919
10878
|
};
|
|
9920
10879
|
Switch.displayName = "Switch";
|
|
9921
10880
|
var Switch_default = Switch;
|
|
9922
10881
|
|
|
9923
10882
|
// src/components/Table/TableContext.tsx
|
|
9924
|
-
import
|
|
9925
|
-
var TableContext =
|
|
10883
|
+
import React34 from "react";
|
|
10884
|
+
var TableContext = React34.createContext(null);
|
|
9926
10885
|
var useTableContext = () => {
|
|
9927
|
-
const ctx =
|
|
10886
|
+
const ctx = React34.useContext(TableContext);
|
|
9928
10887
|
if (!ctx) throw new Error("Table components must be used inside <Table>");
|
|
9929
10888
|
return ctx;
|
|
9930
10889
|
};
|
|
9931
10890
|
var TableContext_default = TableContext;
|
|
9932
10891
|
|
|
9933
10892
|
// src/components/Table/Table.tsx
|
|
9934
|
-
import { jsx as
|
|
10893
|
+
import { jsx as jsx344 } from "react/jsx-runtime";
|
|
9935
10894
|
var Table = (props) => {
|
|
9936
10895
|
const {
|
|
9937
10896
|
children,
|
|
@@ -9941,7 +10900,7 @@ var Table = (props) => {
|
|
|
9941
10900
|
headerSticky = false,
|
|
9942
10901
|
stickyShadow = true
|
|
9943
10902
|
} = props;
|
|
9944
|
-
return /* @__PURE__ */
|
|
10903
|
+
return /* @__PURE__ */ jsx344("div", { className: `lib-xplat-table-wrapper ${size}`, children: /* @__PURE__ */ jsx344(
|
|
9945
10904
|
TableContext_default.Provider,
|
|
9946
10905
|
{
|
|
9947
10906
|
value: {
|
|
@@ -9950,7 +10909,7 @@ var Table = (props) => {
|
|
|
9950
10909
|
headerSticky,
|
|
9951
10910
|
stickyShadow
|
|
9952
10911
|
},
|
|
9953
|
-
children: /* @__PURE__ */
|
|
10912
|
+
children: /* @__PURE__ */ jsx344("table", { className: "lib-xplat-table", children })
|
|
9954
10913
|
}
|
|
9955
10914
|
) });
|
|
9956
10915
|
};
|
|
@@ -9958,41 +10917,41 @@ Table.displayName = "Table";
|
|
|
9958
10917
|
var Table_default = Table;
|
|
9959
10918
|
|
|
9960
10919
|
// src/components/Table/TableBody.tsx
|
|
9961
|
-
import { jsx as
|
|
10920
|
+
import { jsx as jsx345 } from "react/jsx-runtime";
|
|
9962
10921
|
var TableBody = (props) => {
|
|
9963
10922
|
const { children } = props;
|
|
9964
|
-
return /* @__PURE__ */
|
|
10923
|
+
return /* @__PURE__ */ jsx345("tbody", { children });
|
|
9965
10924
|
};
|
|
9966
10925
|
TableBody.displayName = "TableBody";
|
|
9967
10926
|
var TableBody_default = TableBody;
|
|
9968
10927
|
|
|
9969
10928
|
// src/components/Table/TableCell.tsx
|
|
9970
|
-
import
|
|
10929
|
+
import React37 from "react";
|
|
9971
10930
|
|
|
9972
10931
|
// src/components/Table/TableHeadContext.tsx
|
|
9973
|
-
import
|
|
9974
|
-
var TableHeadContext =
|
|
10932
|
+
import React35 from "react";
|
|
10933
|
+
var TableHeadContext = React35.createContext(
|
|
9975
10934
|
null
|
|
9976
10935
|
);
|
|
9977
10936
|
var useTableHeadContext = () => {
|
|
9978
|
-
const ctx =
|
|
10937
|
+
const ctx = React35.useContext(TableHeadContext);
|
|
9979
10938
|
return ctx;
|
|
9980
10939
|
};
|
|
9981
10940
|
var TableHeadContext_default = TableHeadContext;
|
|
9982
10941
|
|
|
9983
10942
|
// src/components/Table/TableRowContext.tsx
|
|
9984
|
-
import
|
|
9985
|
-
var TableRowContext =
|
|
10943
|
+
import React36 from "react";
|
|
10944
|
+
var TableRowContext = React36.createContext(null);
|
|
9986
10945
|
var useTableRowContext = () => {
|
|
9987
|
-
const ctx =
|
|
10946
|
+
const ctx = React36.useContext(TableRowContext);
|
|
9988
10947
|
if (!ctx) throw new Error("Table components must be used inside <Table>");
|
|
9989
10948
|
return ctx;
|
|
9990
10949
|
};
|
|
9991
10950
|
var TableRowContext_default = TableRowContext;
|
|
9992
10951
|
|
|
9993
10952
|
// src/components/Table/TableCell.tsx
|
|
9994
|
-
import { jsx as
|
|
9995
|
-
var TableCell =
|
|
10953
|
+
import { jsx as jsx346 } from "react/jsx-runtime";
|
|
10954
|
+
var TableCell = React37.memo((props) => {
|
|
9996
10955
|
const {
|
|
9997
10956
|
children,
|
|
9998
10957
|
align = "center",
|
|
@@ -10006,9 +10965,9 @@ var TableCell = React36.memo((props) => {
|
|
|
10006
10965
|
const { registerStickyCell, stickyCells } = useTableRowContext();
|
|
10007
10966
|
const { stickyShadow } = useTableContext();
|
|
10008
10967
|
const headContext = useTableHeadContext();
|
|
10009
|
-
const [left, setLeft] =
|
|
10010
|
-
const cellRef =
|
|
10011
|
-
const calculateLeft =
|
|
10968
|
+
const [left, setLeft] = React37.useState(0);
|
|
10969
|
+
const cellRef = React37.useRef(null);
|
|
10970
|
+
const calculateLeft = React37.useCallback(() => {
|
|
10012
10971
|
if (!cellRef.current) return 0;
|
|
10013
10972
|
let totalLeft = 0;
|
|
10014
10973
|
for (const ref of stickyCells) {
|
|
@@ -10017,7 +10976,7 @@ var TableCell = React36.memo((props) => {
|
|
|
10017
10976
|
}
|
|
10018
10977
|
return totalLeft;
|
|
10019
10978
|
}, [stickyCells]);
|
|
10020
|
-
|
|
10979
|
+
React37.useEffect(() => {
|
|
10021
10980
|
if (!isSticky || !cellRef.current) return;
|
|
10022
10981
|
registerStickyCell(cellRef);
|
|
10023
10982
|
setLeft(calculateLeft());
|
|
@@ -10036,7 +10995,7 @@ var TableCell = React36.memo((props) => {
|
|
|
10036
10995
|
const CellTag = isHeaderCell ? "th" : "td";
|
|
10037
10996
|
const isLastSticky = isSticky && stickyCells[stickyCells.length - 1] === cellRef;
|
|
10038
10997
|
const enableHover = headContext && headContext.cellHover;
|
|
10039
|
-
return /* @__PURE__ */
|
|
10998
|
+
return /* @__PURE__ */ jsx346(
|
|
10040
10999
|
CellTag,
|
|
10041
11000
|
{
|
|
10042
11001
|
ref: cellRef,
|
|
@@ -10063,21 +11022,21 @@ TableCell.displayName = "TableCell";
|
|
|
10063
11022
|
var TableCell_default = TableCell;
|
|
10064
11023
|
|
|
10065
11024
|
// src/components/Table/TableHead.tsx
|
|
10066
|
-
import { jsx as
|
|
11025
|
+
import { jsx as jsx347 } from "react/jsx-runtime";
|
|
10067
11026
|
var TableHead = ({
|
|
10068
11027
|
children,
|
|
10069
11028
|
cellHover = false
|
|
10070
11029
|
}) => {
|
|
10071
11030
|
const { headerSticky } = useTableContext();
|
|
10072
|
-
return /* @__PURE__ */
|
|
11031
|
+
return /* @__PURE__ */ jsx347(TableHeadContext_default.Provider, { value: { cellHover }, children: /* @__PURE__ */ jsx347("thead", { className: clsx_default(headerSticky ? "table-sticky" : null), children }) });
|
|
10073
11032
|
};
|
|
10074
11033
|
TableHead.displayName = "TableHead";
|
|
10075
11034
|
var TableHead_default = TableHead;
|
|
10076
11035
|
|
|
10077
11036
|
// src/components/Table/TableRow.tsx
|
|
10078
|
-
import
|
|
10079
|
-
import { jsx as
|
|
10080
|
-
var TableRow =
|
|
11037
|
+
import React38 from "react";
|
|
11038
|
+
import { jsx as jsx348 } from "react/jsx-runtime";
|
|
11039
|
+
var TableRow = React38.memo((props) => {
|
|
10081
11040
|
const {
|
|
10082
11041
|
children,
|
|
10083
11042
|
type = "secondary",
|
|
@@ -10086,14 +11045,14 @@ var TableRow = React37.memo((props) => {
|
|
|
10086
11045
|
onClick
|
|
10087
11046
|
} = props;
|
|
10088
11047
|
const { rowBorderUse } = useTableContext();
|
|
10089
|
-
const [stickyCells, setStickyCells] =
|
|
11048
|
+
const [stickyCells, setStickyCells] = React38.useState([]);
|
|
10090
11049
|
const registerStickyCell = (ref) => {
|
|
10091
11050
|
setStickyCells((prev) => {
|
|
10092
11051
|
if (prev.includes(ref)) return prev;
|
|
10093
11052
|
return [...prev, ref];
|
|
10094
11053
|
});
|
|
10095
11054
|
};
|
|
10096
|
-
return /* @__PURE__ */
|
|
11055
|
+
return /* @__PURE__ */ jsx348(TableRowContext_default.Provider, { value: { stickyCells, registerStickyCell }, children: /* @__PURE__ */ jsx348(
|
|
10097
11056
|
"tr",
|
|
10098
11057
|
{
|
|
10099
11058
|
className: clsx_default(
|
|
@@ -10117,7 +11076,7 @@ TableRow.displayName = "TableRow";
|
|
|
10117
11076
|
var TableRow_default = TableRow;
|
|
10118
11077
|
|
|
10119
11078
|
// src/components/Tag/Tag.tsx
|
|
10120
|
-
import { jsx as
|
|
11079
|
+
import { jsx as jsx349, jsxs as jsxs221 } from "react/jsx-runtime";
|
|
10121
11080
|
var Tag = (props) => {
|
|
10122
11081
|
const {
|
|
10123
11082
|
children,
|
|
@@ -10129,7 +11088,7 @@ var Tag = (props) => {
|
|
|
10129
11088
|
colorIndex
|
|
10130
11089
|
} = props;
|
|
10131
11090
|
const shape = variant ?? type ?? "neutral";
|
|
10132
|
-
return /* @__PURE__ */
|
|
11091
|
+
return /* @__PURE__ */ jsxs221(
|
|
10133
11092
|
"span",
|
|
10134
11093
|
{
|
|
10135
11094
|
className: clsx_default(
|
|
@@ -10140,8 +11099,8 @@ var Tag = (props) => {
|
|
|
10140
11099
|
disabled && "disabled"
|
|
10141
11100
|
),
|
|
10142
11101
|
children: [
|
|
10143
|
-
/* @__PURE__ */
|
|
10144
|
-
onClose && /* @__PURE__ */
|
|
11102
|
+
/* @__PURE__ */ jsx349("span", { className: "tag-label", children }),
|
|
11103
|
+
onClose && /* @__PURE__ */ jsx349("button", { className: "tag-close", onClick: onClose, "aria-label": "\uC0AD\uC81C", disabled, children: /* @__PURE__ */ jsx349(XIcon_default, {}) })
|
|
10145
11104
|
]
|
|
10146
11105
|
}
|
|
10147
11106
|
);
|
|
@@ -10150,24 +11109,29 @@ Tag.displayName = "Tag";
|
|
|
10150
11109
|
var Tag_default = Tag;
|
|
10151
11110
|
|
|
10152
11111
|
// src/components/TextArea/TextArea.tsx
|
|
10153
|
-
import
|
|
10154
|
-
import { jsx as
|
|
10155
|
-
var TextArea =
|
|
11112
|
+
import React39 from "react";
|
|
11113
|
+
import { jsx as jsx350 } from "react/jsx-runtime";
|
|
11114
|
+
var TextArea = React39.forwardRef(
|
|
10156
11115
|
(props, ref) => {
|
|
10157
11116
|
const {
|
|
10158
11117
|
className,
|
|
10159
11118
|
size = "md",
|
|
10160
11119
|
validations,
|
|
11120
|
+
label,
|
|
11121
|
+
required,
|
|
10161
11122
|
resize = "vertical",
|
|
10162
11123
|
rows = 3,
|
|
10163
11124
|
disabled,
|
|
10164
11125
|
...textareaProps
|
|
10165
11126
|
} = props;
|
|
10166
|
-
const
|
|
11127
|
+
const autoId = React39.useId();
|
|
11128
|
+
const fieldId = props.id ?? autoId;
|
|
11129
|
+
const control = /* @__PURE__ */ jsx350("div", { className: clsx_default("lib-xplat-textarea-wrap", className), children: /* @__PURE__ */ jsx350(
|
|
10167
11130
|
"textarea",
|
|
10168
11131
|
{
|
|
10169
11132
|
...textareaProps,
|
|
10170
11133
|
ref,
|
|
11134
|
+
id: fieldId,
|
|
10171
11135
|
rows,
|
|
10172
11136
|
disabled,
|
|
10173
11137
|
"aria-invalid": hasError(validations) || void 0,
|
|
@@ -10175,32 +11139,166 @@ var TextArea = React38.forwardRef(
|
|
|
10175
11139
|
style: { resize }
|
|
10176
11140
|
}
|
|
10177
11141
|
) });
|
|
10178
|
-
return /* @__PURE__ */
|
|
11142
|
+
return /* @__PURE__ */ jsx350(Field, { validations, label, required, htmlFor: fieldId, children: control });
|
|
10179
11143
|
}
|
|
10180
11144
|
);
|
|
10181
11145
|
TextArea.displayName = "TextArea";
|
|
10182
11146
|
var TextArea_default = TextArea;
|
|
10183
11147
|
|
|
11148
|
+
// src/components/TimePicker/TimePicker.tsx
|
|
11149
|
+
import React40 from "react";
|
|
11150
|
+
import { jsx as jsx351, jsxs as jsxs222 } from "react/jsx-runtime";
|
|
11151
|
+
var ANIMATION_DURATION_MS4 = 200;
|
|
11152
|
+
var toMinutes = (hhmm) => {
|
|
11153
|
+
if (!hhmm) return null;
|
|
11154
|
+
const m = /^(\d{1,2}):(\d{2})$/.exec(hhmm.trim());
|
|
11155
|
+
if (!m) return null;
|
|
11156
|
+
const h = Number(m[1]);
|
|
11157
|
+
const min = Number(m[2]);
|
|
11158
|
+
if (h > 23 || min > 59) return null;
|
|
11159
|
+
return h * 60 + min;
|
|
11160
|
+
};
|
|
11161
|
+
var toHHmm = (minutes) => `${String(Math.floor(minutes / 60)).padStart(2, "0")}:${String(minutes % 60).padStart(2, "0")}`;
|
|
11162
|
+
var display = (hhmm, use12Hours) => {
|
|
11163
|
+
if (!use12Hours) return hhmm;
|
|
11164
|
+
const total = toMinutes(hhmm);
|
|
11165
|
+
if (total === null) return hhmm;
|
|
11166
|
+
const h24 = Math.floor(total / 60);
|
|
11167
|
+
const mm = String(total % 60).padStart(2, "0");
|
|
11168
|
+
const period = h24 < 12 ? "\uC624\uC804" : "\uC624\uD6C4";
|
|
11169
|
+
const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
|
|
11170
|
+
return `${period} ${h12}:${mm}`;
|
|
11171
|
+
};
|
|
11172
|
+
var TimePicker = (props) => {
|
|
11173
|
+
const {
|
|
11174
|
+
value,
|
|
11175
|
+
onChange,
|
|
11176
|
+
step = 30,
|
|
11177
|
+
min,
|
|
11178
|
+
max,
|
|
11179
|
+
use12Hours = false,
|
|
11180
|
+
placeholder = "\uC2DC\uAC01 \uC120\uD0DD",
|
|
11181
|
+
disabled = false,
|
|
11182
|
+
size = "md",
|
|
11183
|
+
label,
|
|
11184
|
+
required,
|
|
11185
|
+
validations
|
|
11186
|
+
} = props;
|
|
11187
|
+
const fieldId = React40.useId();
|
|
11188
|
+
const triggerRef = React40.useRef(null);
|
|
11189
|
+
const contentRef = React40.useRef(null);
|
|
11190
|
+
const [isOpen, setOpen] = React40.useState(false);
|
|
11191
|
+
const [mounted, setMounted] = React40.useState(false);
|
|
11192
|
+
const [visible, setVisible] = React40.useState(false);
|
|
11193
|
+
const options = React40.useMemo(() => {
|
|
11194
|
+
const safeStep = step > 0 && step <= 720 ? step : 30;
|
|
11195
|
+
const lo = toMinutes(min) ?? 0;
|
|
11196
|
+
const hi = toMinutes(max) ?? 24 * 60 - 1;
|
|
11197
|
+
const out = [];
|
|
11198
|
+
for (let t = lo; t <= hi; t += safeStep) out.push(toHHmm(t));
|
|
11199
|
+
return out;
|
|
11200
|
+
}, [step, min, max]);
|
|
11201
|
+
const close = React40.useCallback(() => setOpen(false), []);
|
|
11202
|
+
useClickOutside_default([triggerRef, contentRef], close, isOpen);
|
|
11203
|
+
useEscapeKey(isOpen, () => {
|
|
11204
|
+
close();
|
|
11205
|
+
triggerRef.current?.focus({ preventScroll: true });
|
|
11206
|
+
});
|
|
11207
|
+
const position = useAutoPosition_default(triggerRef, contentRef, mounted);
|
|
11208
|
+
React40.useEffect(() => {
|
|
11209
|
+
if (disabled && isOpen) setOpen(false);
|
|
11210
|
+
}, [disabled, isOpen]);
|
|
11211
|
+
React40.useEffect(() => {
|
|
11212
|
+
if (isOpen) {
|
|
11213
|
+
setMounted(true);
|
|
11214
|
+
const t2 = setTimeout(() => setVisible(true), 1);
|
|
11215
|
+
return () => clearTimeout(t2);
|
|
11216
|
+
}
|
|
11217
|
+
setVisible(false);
|
|
11218
|
+
const t = setTimeout(() => setMounted(false), ANIMATION_DURATION_MS4);
|
|
11219
|
+
return () => clearTimeout(t);
|
|
11220
|
+
}, [isOpen]);
|
|
11221
|
+
const pick = (hhmm) => {
|
|
11222
|
+
onChange?.(hhmm);
|
|
11223
|
+
close();
|
|
11224
|
+
triggerRef.current?.focus({ preventScroll: true });
|
|
11225
|
+
};
|
|
11226
|
+
const control = /* @__PURE__ */ jsxs222("div", { className: clsx_default("lib-xplat-time-picker", size, disabled && "disabled"), children: [
|
|
11227
|
+
/* @__PURE__ */ jsx351(
|
|
11228
|
+
"div",
|
|
11229
|
+
{
|
|
11230
|
+
id: fieldId,
|
|
11231
|
+
ref: triggerRef,
|
|
11232
|
+
className: clsx_default("time-picker-trigger", hasError(validations) && "error"),
|
|
11233
|
+
role: "combobox",
|
|
11234
|
+
"aria-expanded": isOpen,
|
|
11235
|
+
"aria-haspopup": "listbox",
|
|
11236
|
+
"aria-invalid": hasError(validations) || void 0,
|
|
11237
|
+
tabIndex: disabled ? void 0 : 0,
|
|
11238
|
+
onClick: () => !disabled && setOpen((p) => !p),
|
|
11239
|
+
onKeyDown: (e) => {
|
|
11240
|
+
if (disabled) return;
|
|
11241
|
+
if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") {
|
|
11242
|
+
e.preventDefault();
|
|
11243
|
+
setOpen(true);
|
|
11244
|
+
}
|
|
11245
|
+
},
|
|
11246
|
+
children: /* @__PURE__ */ jsx351("span", { className: clsx_default("time-picker-value", !value && "placeholder"), children: value ? display(value, use12Hours) : placeholder })
|
|
11247
|
+
}
|
|
11248
|
+
),
|
|
11249
|
+
mounted && /* @__PURE__ */ jsx351(Portal_default, { children: /* @__PURE__ */ jsx351(
|
|
11250
|
+
"div",
|
|
11251
|
+
{
|
|
11252
|
+
ref: contentRef,
|
|
11253
|
+
className: clsx_default("lib-xplat-time-picker-content", size, visible ? "enter" : "exit", position.repositioning && "repositioning"),
|
|
11254
|
+
style: { ...position.position, width: triggerRef.current?.offsetWidth },
|
|
11255
|
+
role: "listbox",
|
|
11256
|
+
children: options.map((t) => /* @__PURE__ */ jsx351(
|
|
11257
|
+
"div",
|
|
11258
|
+
{
|
|
11259
|
+
className: clsx_default("time-picker-item", t === value && "is-selected"),
|
|
11260
|
+
role: "option",
|
|
11261
|
+
"aria-selected": t === value,
|
|
11262
|
+
tabIndex: 0,
|
|
11263
|
+
onClick: () => pick(t),
|
|
11264
|
+
onKeyDown: (e) => {
|
|
11265
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
11266
|
+
e.preventDefault();
|
|
11267
|
+
pick(t);
|
|
11268
|
+
}
|
|
11269
|
+
},
|
|
11270
|
+
children: display(t, use12Hours)
|
|
11271
|
+
},
|
|
11272
|
+
t
|
|
11273
|
+
))
|
|
11274
|
+
}
|
|
11275
|
+
) })
|
|
11276
|
+
] });
|
|
11277
|
+
return /* @__PURE__ */ jsx351(Field, { validations, label, required, htmlFor: fieldId, children: control });
|
|
11278
|
+
};
|
|
11279
|
+
TimePicker.displayName = "TimePicker";
|
|
11280
|
+
var TimePicker_default = TimePicker;
|
|
11281
|
+
|
|
10184
11282
|
// src/components/Toast/Toast.tsx
|
|
10185
|
-
import
|
|
11283
|
+
import React41 from "react";
|
|
10186
11284
|
import { createPortal as createPortal3 } from "react-dom";
|
|
10187
|
-
import { jsx as
|
|
10188
|
-
var ToastContext =
|
|
11285
|
+
import { jsx as jsx352, jsxs as jsxs223 } from "react/jsx-runtime";
|
|
11286
|
+
var ToastContext = React41.createContext(null);
|
|
10189
11287
|
var useToast = () => {
|
|
10190
|
-
const ctx =
|
|
11288
|
+
const ctx = React41.useContext(ToastContext);
|
|
10191
11289
|
if (!ctx) throw new Error("useToast must be used within ToastProvider");
|
|
10192
11290
|
return ctx;
|
|
10193
11291
|
};
|
|
10194
11292
|
var EXIT_DURATION = 300;
|
|
10195
11293
|
var ToastItemComponent = ({ item, isExiting, onClose }) => {
|
|
10196
|
-
const ref =
|
|
10197
|
-
const [height, setHeight] =
|
|
10198
|
-
|
|
11294
|
+
const ref = React41.useRef(null);
|
|
11295
|
+
const [height, setHeight] = React41.useState(void 0);
|
|
11296
|
+
React41.useEffect(() => {
|
|
10199
11297
|
if (ref.current && !isExiting) {
|
|
10200
11298
|
setHeight(ref.current.offsetHeight);
|
|
10201
11299
|
}
|
|
10202
11300
|
}, [isExiting]);
|
|
10203
|
-
return /* @__PURE__ */
|
|
11301
|
+
return /* @__PURE__ */ jsx352(
|
|
10204
11302
|
"div",
|
|
10205
11303
|
{
|
|
10206
11304
|
className: clsx_default("lib-xplat-toast-wrapper", { exit: isExiting }),
|
|
@@ -10208,15 +11306,15 @@ var ToastItemComponent = ({ item, isExiting, onClose }) => {
|
|
|
10208
11306
|
maxHeight: isExiting ? 0 : height ?? "none",
|
|
10209
11307
|
marginBottom: isExiting ? 0 : void 0
|
|
10210
11308
|
},
|
|
10211
|
-
children: /* @__PURE__ */
|
|
11309
|
+
children: /* @__PURE__ */ jsxs223(
|
|
10212
11310
|
"div",
|
|
10213
11311
|
{
|
|
10214
11312
|
ref,
|
|
10215
11313
|
className: clsx_default("lib-xplat-toast", item.type, { exit: isExiting }),
|
|
10216
11314
|
role: "alert",
|
|
10217
11315
|
children: [
|
|
10218
|
-
/* @__PURE__ */
|
|
10219
|
-
/* @__PURE__ */
|
|
11316
|
+
/* @__PURE__ */ jsx352("span", { className: "message", children: item.message }),
|
|
11317
|
+
/* @__PURE__ */ jsx352("button", { className: "close-btn", onClick: onClose, "aria-label": "\uB2EB\uAE30", children: "\xD7" })
|
|
10220
11318
|
]
|
|
10221
11319
|
}
|
|
10222
11320
|
)
|
|
@@ -10227,13 +11325,13 @@ var ToastProvider = ({
|
|
|
10227
11325
|
children,
|
|
10228
11326
|
position = "top-right"
|
|
10229
11327
|
}) => {
|
|
10230
|
-
const [toasts, setToasts] =
|
|
10231
|
-
const [removing, setRemoving] =
|
|
10232
|
-
const [mounted, setMounted] =
|
|
10233
|
-
|
|
11328
|
+
const [toasts, setToasts] = React41.useState([]);
|
|
11329
|
+
const [removing, setRemoving] = React41.useState(/* @__PURE__ */ new Set());
|
|
11330
|
+
const [mounted, setMounted] = React41.useState(false);
|
|
11331
|
+
React41.useEffect(() => {
|
|
10234
11332
|
setMounted(true);
|
|
10235
11333
|
}, []);
|
|
10236
|
-
const remove =
|
|
11334
|
+
const remove = React41.useCallback((id) => {
|
|
10237
11335
|
setRemoving((prev) => new Set(prev).add(id));
|
|
10238
11336
|
setTimeout(() => {
|
|
10239
11337
|
setToasts((prev) => prev.filter((t) => t.id !== id));
|
|
@@ -10244,7 +11342,7 @@ var ToastProvider = ({
|
|
|
10244
11342
|
});
|
|
10245
11343
|
}, EXIT_DURATION);
|
|
10246
11344
|
}, []);
|
|
10247
|
-
const toast =
|
|
11345
|
+
const toast = React41.useCallback(
|
|
10248
11346
|
(type, message, duration = 3e3) => {
|
|
10249
11347
|
const id = `${Date.now()}-${Math.random()}`;
|
|
10250
11348
|
setToasts((prev) => [...prev, { id, type, message }]);
|
|
@@ -10254,10 +11352,10 @@ var ToastProvider = ({
|
|
|
10254
11352
|
},
|
|
10255
11353
|
[remove]
|
|
10256
11354
|
);
|
|
10257
|
-
return /* @__PURE__ */
|
|
11355
|
+
return /* @__PURE__ */ jsxs223(ToastContext.Provider, { value: { toast }, children: [
|
|
10258
11356
|
children,
|
|
10259
11357
|
mounted && createPortal3(
|
|
10260
|
-
/* @__PURE__ */
|
|
11358
|
+
/* @__PURE__ */ jsx352("div", { className: clsx_default("lib-xplat-toast-container", position), children: toasts.map((t) => /* @__PURE__ */ jsx352(
|
|
10261
11359
|
ToastItemComponent,
|
|
10262
11360
|
{
|
|
10263
11361
|
item: t,
|
|
@@ -10273,8 +11371,8 @@ var ToastProvider = ({
|
|
|
10273
11371
|
ToastProvider.displayName = "ToastProvider";
|
|
10274
11372
|
|
|
10275
11373
|
// src/components/Tooltip/Tooltip.tsx
|
|
10276
|
-
import
|
|
10277
|
-
import { Fragment as Fragment6, jsx as
|
|
11374
|
+
import React42 from "react";
|
|
11375
|
+
import { Fragment as Fragment6, jsx as jsx353, jsxs as jsxs224 } from "react/jsx-runtime";
|
|
10278
11376
|
var OFFSET = 12;
|
|
10279
11377
|
var GAP = 8;
|
|
10280
11378
|
var SHOW_DELAY = 300;
|
|
@@ -10289,14 +11387,14 @@ var Tooltip = (props) => {
|
|
|
10289
11387
|
disabled = false
|
|
10290
11388
|
} = props;
|
|
10291
11389
|
const shape = variant ?? type ?? "dark";
|
|
10292
|
-
const triggerRef =
|
|
10293
|
-
const tooltipRef =
|
|
10294
|
-
const [visible, setVisible] =
|
|
10295
|
-
const [pos, setPos] =
|
|
10296
|
-
const delayTimer =
|
|
10297
|
-
const rafRef =
|
|
10298
|
-
const cursor =
|
|
10299
|
-
const clamp =
|
|
11390
|
+
const triggerRef = React42.useRef(null);
|
|
11391
|
+
const tooltipRef = React42.useRef(null);
|
|
11392
|
+
const [visible, setVisible] = React42.useState(false);
|
|
11393
|
+
const [pos, setPos] = React42.useState({ left: 0, top: 0 });
|
|
11394
|
+
const delayTimer = React42.useRef(0);
|
|
11395
|
+
const rafRef = React42.useRef(0);
|
|
11396
|
+
const cursor = React42.useRef(null);
|
|
11397
|
+
const clamp = React42.useCallback((left, top, w, h) => {
|
|
10300
11398
|
const vw = window.innerWidth;
|
|
10301
11399
|
const vh = window.innerHeight;
|
|
10302
11400
|
return {
|
|
@@ -10304,7 +11402,7 @@ var Tooltip = (props) => {
|
|
|
10304
11402
|
top: Math.min(Math.max(GAP, top), Math.max(GAP, vh - h - GAP))
|
|
10305
11403
|
};
|
|
10306
11404
|
}, []);
|
|
10307
|
-
const placeAtCursor =
|
|
11405
|
+
const placeAtCursor = React42.useCallback((x, y) => {
|
|
10308
11406
|
const el = tooltipRef.current;
|
|
10309
11407
|
if (!el) return;
|
|
10310
11408
|
const w = el.offsetWidth;
|
|
@@ -10315,7 +11413,7 @@ var Tooltip = (props) => {
|
|
|
10315
11413
|
if (top < GAP) top = y + OFFSET;
|
|
10316
11414
|
setPos(clamp(left, top, w, h));
|
|
10317
11415
|
}, [clamp]);
|
|
10318
|
-
const placeAtTrigger =
|
|
11416
|
+
const placeAtTrigger = React42.useCallback(() => {
|
|
10319
11417
|
const el = tooltipRef.current;
|
|
10320
11418
|
const trigger = triggerRef.current;
|
|
10321
11419
|
if (!el || !trigger) return;
|
|
@@ -10327,19 +11425,19 @@ var Tooltip = (props) => {
|
|
|
10327
11425
|
const left = rect.left + rect.width / 2 - w / 2;
|
|
10328
11426
|
setPos(clamp(left, top, w, h));
|
|
10329
11427
|
}, [clamp]);
|
|
10330
|
-
const reposition =
|
|
11428
|
+
const reposition = React42.useCallback(() => {
|
|
10331
11429
|
if (follow && cursor.current) {
|
|
10332
11430
|
placeAtCursor(cursor.current.x, cursor.current.y);
|
|
10333
11431
|
} else {
|
|
10334
11432
|
placeAtTrigger();
|
|
10335
11433
|
}
|
|
10336
11434
|
}, [follow, placeAtCursor, placeAtTrigger]);
|
|
10337
|
-
const handleMouseEnter =
|
|
11435
|
+
const handleMouseEnter = React42.useCallback((e) => {
|
|
10338
11436
|
if (disabled) return;
|
|
10339
11437
|
cursor.current = { x: e.clientX, y: e.clientY };
|
|
10340
11438
|
delayTimer.current = window.setTimeout(() => setVisible(true), SHOW_DELAY);
|
|
10341
11439
|
}, [disabled]);
|
|
10342
|
-
const handleMouseMove =
|
|
11440
|
+
const handleMouseMove = React42.useCallback((e) => {
|
|
10343
11441
|
cursor.current = { x: e.clientX, y: e.clientY };
|
|
10344
11442
|
if (!visible || !follow) return;
|
|
10345
11443
|
cancelAnimationFrame(rafRef.current);
|
|
@@ -10347,25 +11445,25 @@ var Tooltip = (props) => {
|
|
|
10347
11445
|
if (cursor.current) placeAtCursor(cursor.current.x, cursor.current.y);
|
|
10348
11446
|
});
|
|
10349
11447
|
}, [visible, follow, placeAtCursor]);
|
|
10350
|
-
const close =
|
|
11448
|
+
const close = React42.useCallback(() => {
|
|
10351
11449
|
window.clearTimeout(delayTimer.current);
|
|
10352
11450
|
cancelAnimationFrame(rafRef.current);
|
|
10353
11451
|
setVisible(false);
|
|
10354
11452
|
}, []);
|
|
10355
|
-
const handleMouseLeave =
|
|
11453
|
+
const handleMouseLeave = React42.useCallback(() => {
|
|
10356
11454
|
cursor.current = null;
|
|
10357
11455
|
close();
|
|
10358
11456
|
}, [close]);
|
|
10359
|
-
const handleFocus =
|
|
11457
|
+
const handleFocus = React42.useCallback(() => {
|
|
10360
11458
|
if (disabled) return;
|
|
10361
11459
|
cursor.current = null;
|
|
10362
11460
|
setVisible(true);
|
|
10363
11461
|
}, [disabled]);
|
|
10364
|
-
|
|
11462
|
+
React42.useLayoutEffect(() => {
|
|
10365
11463
|
if (!visible) return;
|
|
10366
11464
|
reposition();
|
|
10367
11465
|
}, [visible, reposition]);
|
|
10368
|
-
|
|
11466
|
+
React42.useEffect(() => {
|
|
10369
11467
|
if (!visible || follow) return;
|
|
10370
11468
|
const onChange = () => placeAtTrigger();
|
|
10371
11469
|
window.addEventListener("scroll", onChange, true);
|
|
@@ -10375,12 +11473,12 @@ var Tooltip = (props) => {
|
|
|
10375
11473
|
window.removeEventListener("resize", onChange);
|
|
10376
11474
|
};
|
|
10377
11475
|
}, [visible, follow, placeAtTrigger]);
|
|
10378
|
-
|
|
11476
|
+
React42.useEffect(() => () => {
|
|
10379
11477
|
window.clearTimeout(delayTimer.current);
|
|
10380
11478
|
cancelAnimationFrame(rafRef.current);
|
|
10381
11479
|
}, []);
|
|
10382
|
-
if (!title && !description) return /* @__PURE__ */
|
|
10383
|
-
return /* @__PURE__ */
|
|
11480
|
+
if (!title && !description) return /* @__PURE__ */ jsx353(Fragment6, { children });
|
|
11481
|
+
return /* @__PURE__ */ jsxs224(
|
|
10384
11482
|
"div",
|
|
10385
11483
|
{
|
|
10386
11484
|
ref: triggerRef,
|
|
@@ -10393,7 +11491,7 @@ var Tooltip = (props) => {
|
|
|
10393
11491
|
onBlur: close,
|
|
10394
11492
|
children: [
|
|
10395
11493
|
children,
|
|
10396
|
-
visible && /* @__PURE__ */
|
|
11494
|
+
visible && /* @__PURE__ */ jsx353(Portal_default, { children: /* @__PURE__ */ jsxs224(
|
|
10397
11495
|
"div",
|
|
10398
11496
|
{
|
|
10399
11497
|
ref: tooltipRef,
|
|
@@ -10401,8 +11499,8 @@ var Tooltip = (props) => {
|
|
|
10401
11499
|
className: clsx_default("lib-xplat-tooltip", shape),
|
|
10402
11500
|
style: { position: "fixed", left: pos.left, top: pos.top },
|
|
10403
11501
|
children: [
|
|
10404
|
-
title && /* @__PURE__ */
|
|
10405
|
-
description && /* @__PURE__ */
|
|
11502
|
+
title && /* @__PURE__ */ jsx353("div", { className: "tooltip-title", children: title }),
|
|
11503
|
+
description && /* @__PURE__ */ jsx353("div", { className: "tooltip-desc", children: description })
|
|
10406
11504
|
]
|
|
10407
11505
|
}
|
|
10408
11506
|
) })
|
|
@@ -10414,11 +11512,11 @@ Tooltip.displayName = "Tooltip";
|
|
|
10414
11512
|
var Tooltip_default = Tooltip;
|
|
10415
11513
|
|
|
10416
11514
|
// src/components/Video/Video.tsx
|
|
10417
|
-
import
|
|
10418
|
-
import { jsx as
|
|
10419
|
-
var PipIcon = () => /* @__PURE__ */
|
|
10420
|
-
/* @__PURE__ */
|
|
10421
|
-
/* @__PURE__ */
|
|
11515
|
+
import React43 from "react";
|
|
11516
|
+
import { jsx as jsx354, jsxs as jsxs225 } from "react/jsx-runtime";
|
|
11517
|
+
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: [
|
|
11518
|
+
/* @__PURE__ */ jsx354("rect", { x: "3", y: "5", width: "18", height: "14", rx: "2" }),
|
|
11519
|
+
/* @__PURE__ */ jsx354("rect", { x: "12", y: "11", width: "7", height: "6", rx: "1", fill: "currentColor" })
|
|
10422
11520
|
] });
|
|
10423
11521
|
var formatTime = (sec) => {
|
|
10424
11522
|
if (!Number.isFinite(sec) || sec < 0) return "0:00";
|
|
@@ -10426,7 +11524,7 @@ var formatTime = (sec) => {
|
|
|
10426
11524
|
const s = Math.floor(sec % 60);
|
|
10427
11525
|
return `${m}:${s.toString().padStart(2, "0")}`;
|
|
10428
11526
|
};
|
|
10429
|
-
var Video =
|
|
11527
|
+
var Video = React43.forwardRef((props, ref) => {
|
|
10430
11528
|
const {
|
|
10431
11529
|
src,
|
|
10432
11530
|
poster,
|
|
@@ -10450,21 +11548,21 @@ var Video = React41.forwardRef((props, ref) => {
|
|
|
10450
11548
|
children,
|
|
10451
11549
|
...rest
|
|
10452
11550
|
} = props;
|
|
10453
|
-
const containerRef =
|
|
10454
|
-
const videoRef =
|
|
10455
|
-
const [isPlaying, setIsPlaying] =
|
|
10456
|
-
const [isLoaded, setIsLoaded] =
|
|
10457
|
-
const [currentTime, setCurrentTime] =
|
|
10458
|
-
const [duration, setDuration] =
|
|
10459
|
-
const [buffered, setBuffered] =
|
|
10460
|
-
const [volume, setVolume] =
|
|
10461
|
-
const [isMuted, setIsMuted] =
|
|
10462
|
-
const [isFullscreen, setIsFullscreen] =
|
|
10463
|
-
const [playbackRate, setPlaybackRate] =
|
|
10464
|
-
const [rateMenuOpen, setRateMenuOpen] =
|
|
10465
|
-
const [captionsOn, setCaptionsOn] =
|
|
10466
|
-
const [isPip, setIsPip] =
|
|
10467
|
-
const setRefs =
|
|
11551
|
+
const containerRef = React43.useRef(null);
|
|
11552
|
+
const videoRef = React43.useRef(null);
|
|
11553
|
+
const [isPlaying, setIsPlaying] = React43.useState(Boolean(autoPlay));
|
|
11554
|
+
const [isLoaded, setIsLoaded] = React43.useState(false);
|
|
11555
|
+
const [currentTime, setCurrentTime] = React43.useState(0);
|
|
11556
|
+
const [duration, setDuration] = React43.useState(0);
|
|
11557
|
+
const [buffered, setBuffered] = React43.useState(0);
|
|
11558
|
+
const [volume, setVolume] = React43.useState(1);
|
|
11559
|
+
const [isMuted, setIsMuted] = React43.useState(Boolean(muted));
|
|
11560
|
+
const [isFullscreen, setIsFullscreen] = React43.useState(false);
|
|
11561
|
+
const [playbackRate, setPlaybackRate] = React43.useState(1);
|
|
11562
|
+
const [rateMenuOpen, setRateMenuOpen] = React43.useState(false);
|
|
11563
|
+
const [captionsOn, setCaptionsOn] = React43.useState(false);
|
|
11564
|
+
const [isPip, setIsPip] = React43.useState(false);
|
|
11565
|
+
const setRefs = React43.useCallback(
|
|
10468
11566
|
(el) => {
|
|
10469
11567
|
videoRef.current = el;
|
|
10470
11568
|
if (typeof ref === "function") ref(el);
|
|
@@ -10472,14 +11570,14 @@ var Video = React41.forwardRef((props, ref) => {
|
|
|
10472
11570
|
},
|
|
10473
11571
|
[ref]
|
|
10474
11572
|
);
|
|
10475
|
-
|
|
11573
|
+
React43.useEffect(() => {
|
|
10476
11574
|
const onFsChange = () => {
|
|
10477
11575
|
setIsFullscreen(document.fullscreenElement === containerRef.current);
|
|
10478
11576
|
};
|
|
10479
11577
|
document.addEventListener("fullscreenchange", onFsChange);
|
|
10480
11578
|
return () => document.removeEventListener("fullscreenchange", onFsChange);
|
|
10481
11579
|
}, []);
|
|
10482
|
-
|
|
11580
|
+
React43.useEffect(() => {
|
|
10483
11581
|
const v = videoRef.current;
|
|
10484
11582
|
if (!v) return;
|
|
10485
11583
|
const onEnter = () => setIsPip(true);
|
|
@@ -10593,13 +11691,13 @@ var Video = React41.forwardRef((props, ref) => {
|
|
|
10593
11691
|
const volumePct = (isMuted ? 0 : volume) * 100;
|
|
10594
11692
|
const VolumeGlyph = isMuted || volume === 0 ? VolumeXIcon_default : volume < 0.5 ? VolumeIcon_default : Volume2Icon_default;
|
|
10595
11693
|
const pipSupported = typeof document !== "undefined" && "pictureInPictureEnabled" in document && document.pictureInPictureEnabled;
|
|
10596
|
-
return /* @__PURE__ */
|
|
11694
|
+
return /* @__PURE__ */ jsxs225(
|
|
10597
11695
|
"div",
|
|
10598
11696
|
{
|
|
10599
11697
|
ref: containerRef,
|
|
10600
11698
|
className: clsx_default("lib-xplat-video", showControls && "has-controls"),
|
|
10601
11699
|
children: [
|
|
10602
|
-
/* @__PURE__ */
|
|
11700
|
+
/* @__PURE__ */ jsx354(
|
|
10603
11701
|
"video",
|
|
10604
11702
|
{
|
|
10605
11703
|
ref: setRefs,
|
|
@@ -10620,7 +11718,7 @@ var Video = React41.forwardRef((props, ref) => {
|
|
|
10620
11718
|
children
|
|
10621
11719
|
}
|
|
10622
11720
|
),
|
|
10623
|
-
showCenterPlay && /* @__PURE__ */
|
|
11721
|
+
showCenterPlay && /* @__PURE__ */ jsx354(
|
|
10624
11722
|
"button",
|
|
10625
11723
|
{
|
|
10626
11724
|
type: "button",
|
|
@@ -10632,11 +11730,11 @@ var Video = React41.forwardRef((props, ref) => {
|
|
|
10632
11730
|
onClick: togglePlay,
|
|
10633
11731
|
"aria-label": isPlaying ? "\uC77C\uC2DC\uC815\uC9C0" : "\uC7AC\uC0DD",
|
|
10634
11732
|
tabIndex: -1,
|
|
10635
|
-
children: /* @__PURE__ */
|
|
11733
|
+
children: /* @__PURE__ */ jsx354("span", { className: "center-play-icon", children: /* @__PURE__ */ jsx354(PlayCircleIcon_default, {}) })
|
|
10636
11734
|
}
|
|
10637
11735
|
),
|
|
10638
|
-
showControls && /* @__PURE__ */
|
|
10639
|
-
/* @__PURE__ */
|
|
11736
|
+
showControls && /* @__PURE__ */ jsxs225("div", { className: "controls", onClick: (e) => e.stopPropagation(), children: [
|
|
11737
|
+
/* @__PURE__ */ jsx354(
|
|
10640
11738
|
"input",
|
|
10641
11739
|
{
|
|
10642
11740
|
type: "range",
|
|
@@ -10653,29 +11751,29 @@ var Video = React41.forwardRef((props, ref) => {
|
|
|
10653
11751
|
}
|
|
10654
11752
|
}
|
|
10655
11753
|
),
|
|
10656
|
-
/* @__PURE__ */
|
|
10657
|
-
/* @__PURE__ */
|
|
11754
|
+
/* @__PURE__ */ jsxs225("div", { className: "controls-row", children: [
|
|
11755
|
+
/* @__PURE__ */ jsx354(
|
|
10658
11756
|
"button",
|
|
10659
11757
|
{
|
|
10660
11758
|
type: "button",
|
|
10661
11759
|
className: "control-btn",
|
|
10662
11760
|
onClick: togglePlay,
|
|
10663
11761
|
"aria-label": isPlaying ? "\uC77C\uC2DC\uC815\uC9C0" : "\uC7AC\uC0DD",
|
|
10664
|
-
children: isPlaying ? /* @__PURE__ */
|
|
11762
|
+
children: isPlaying ? /* @__PURE__ */ jsx354(PauseIcon_default, {}) : /* @__PURE__ */ jsx354(PlayIcon_default, {})
|
|
10665
11763
|
}
|
|
10666
11764
|
),
|
|
10667
|
-
/* @__PURE__ */
|
|
10668
|
-
/* @__PURE__ */
|
|
11765
|
+
/* @__PURE__ */ jsxs225("div", { className: "volume-group", children: [
|
|
11766
|
+
/* @__PURE__ */ jsx354(
|
|
10669
11767
|
"button",
|
|
10670
11768
|
{
|
|
10671
11769
|
type: "button",
|
|
10672
11770
|
className: "control-btn",
|
|
10673
11771
|
onClick: toggleMute,
|
|
10674
11772
|
"aria-label": isMuted ? "\uC74C\uC18C\uAC70 \uD574\uC81C" : "\uC74C\uC18C\uAC70",
|
|
10675
|
-
children: /* @__PURE__ */
|
|
11773
|
+
children: /* @__PURE__ */ jsx354(VolumeGlyph, {})
|
|
10676
11774
|
}
|
|
10677
11775
|
),
|
|
10678
|
-
/* @__PURE__ */
|
|
11776
|
+
/* @__PURE__ */ jsx354(
|
|
10679
11777
|
"input",
|
|
10680
11778
|
{
|
|
10681
11779
|
type: "range",
|
|
@@ -10690,14 +11788,14 @@ var Video = React41.forwardRef((props, ref) => {
|
|
|
10690
11788
|
}
|
|
10691
11789
|
)
|
|
10692
11790
|
] }),
|
|
10693
|
-
/* @__PURE__ */
|
|
11791
|
+
/* @__PURE__ */ jsxs225("span", { className: "time", children: [
|
|
10694
11792
|
formatTime(currentTime),
|
|
10695
11793
|
" / ",
|
|
10696
11794
|
formatTime(duration)
|
|
10697
11795
|
] }),
|
|
10698
|
-
/* @__PURE__ */
|
|
10699
|
-
playbackRates && playbackRates.length > 0 && /* @__PURE__ */
|
|
10700
|
-
/* @__PURE__ */
|
|
11796
|
+
/* @__PURE__ */ jsx354("div", { className: "controls-spacer" }),
|
|
11797
|
+
playbackRates && playbackRates.length > 0 && /* @__PURE__ */ jsxs225("div", { className: clsx_default("rate-group", rateMenuOpen && "is-open"), children: [
|
|
11798
|
+
/* @__PURE__ */ jsxs225(
|
|
10701
11799
|
"button",
|
|
10702
11800
|
{
|
|
10703
11801
|
type: "button",
|
|
@@ -10711,7 +11809,7 @@ var Video = React41.forwardRef((props, ref) => {
|
|
|
10711
11809
|
]
|
|
10712
11810
|
}
|
|
10713
11811
|
),
|
|
10714
|
-
rateMenuOpen && /* @__PURE__ */
|
|
11812
|
+
rateMenuOpen && /* @__PURE__ */ jsx354("ul", { className: "rate-menu", role: "menu", children: playbackRates.map((r2) => /* @__PURE__ */ jsx354("li", { children: /* @__PURE__ */ jsxs225(
|
|
10715
11813
|
"button",
|
|
10716
11814
|
{
|
|
10717
11815
|
type: "button",
|
|
@@ -10725,7 +11823,7 @@ var Video = React41.forwardRef((props, ref) => {
|
|
|
10725
11823
|
}
|
|
10726
11824
|
) }, r2)) })
|
|
10727
11825
|
] }),
|
|
10728
|
-
showCaptions && /* @__PURE__ */
|
|
11826
|
+
showCaptions && /* @__PURE__ */ jsx354(
|
|
10729
11827
|
"button",
|
|
10730
11828
|
{
|
|
10731
11829
|
type: "button",
|
|
@@ -10733,37 +11831,37 @@ var Video = React41.forwardRef((props, ref) => {
|
|
|
10733
11831
|
onClick: toggleCaptions,
|
|
10734
11832
|
"aria-label": captionsOn ? "\uC790\uB9C9 \uB044\uAE30" : "\uC790\uB9C9 \uCF1C\uAE30",
|
|
10735
11833
|
"aria-pressed": captionsOn,
|
|
10736
|
-
children: /* @__PURE__ */
|
|
11834
|
+
children: /* @__PURE__ */ jsx354(TypeIcon_default, {})
|
|
10737
11835
|
}
|
|
10738
11836
|
),
|
|
10739
|
-
showPip && pipSupported && /* @__PURE__ */
|
|
11837
|
+
showPip && pipSupported && /* @__PURE__ */ jsx354(
|
|
10740
11838
|
"button",
|
|
10741
11839
|
{
|
|
10742
11840
|
type: "button",
|
|
10743
11841
|
className: clsx_default("control-btn", isPip && "is-active"),
|
|
10744
11842
|
onClick: togglePip,
|
|
10745
11843
|
"aria-label": isPip ? "PIP \uC885\uB8CC" : "PIP",
|
|
10746
|
-
children: /* @__PURE__ */
|
|
11844
|
+
children: /* @__PURE__ */ jsx354(PipIcon, {})
|
|
10747
11845
|
}
|
|
10748
11846
|
),
|
|
10749
|
-
showDownload && /* @__PURE__ */
|
|
11847
|
+
showDownload && /* @__PURE__ */ jsx354(
|
|
10750
11848
|
"a",
|
|
10751
11849
|
{
|
|
10752
11850
|
className: "control-btn",
|
|
10753
11851
|
href: src,
|
|
10754
11852
|
download: downloadFileName ?? true,
|
|
10755
11853
|
"aria-label": "\uB2E4\uC6B4\uB85C\uB4DC",
|
|
10756
|
-
children: /* @__PURE__ */
|
|
11854
|
+
children: /* @__PURE__ */ jsx354(DownloadIcon_default, {})
|
|
10757
11855
|
}
|
|
10758
11856
|
),
|
|
10759
|
-
/* @__PURE__ */
|
|
11857
|
+
/* @__PURE__ */ jsx354(
|
|
10760
11858
|
"button",
|
|
10761
11859
|
{
|
|
10762
11860
|
type: "button",
|
|
10763
11861
|
className: "control-btn",
|
|
10764
11862
|
onClick: toggleFullscreen,
|
|
10765
11863
|
"aria-label": isFullscreen ? "\uC804\uCCB4\uD654\uBA74 \uC885\uB8CC" : "\uC804\uCCB4\uD654\uBA74",
|
|
10766
|
-
children: isFullscreen ? /* @__PURE__ */
|
|
11864
|
+
children: isFullscreen ? /* @__PURE__ */ jsx354(MinimizeIcon_default, {}) : /* @__PURE__ */ jsx354(MaximizeIcon_default, {})
|
|
10767
11865
|
}
|
|
10768
11866
|
)
|
|
10769
11867
|
] })
|
|
@@ -10776,7 +11874,7 @@ Video.displayName = "Video";
|
|
|
10776
11874
|
var Video_default = Video;
|
|
10777
11875
|
|
|
10778
11876
|
// src/layout/Grid/FullGrid/FullGrid.tsx
|
|
10779
|
-
import { jsx as
|
|
11877
|
+
import { jsx as jsx355 } from "react/jsx-runtime";
|
|
10780
11878
|
var GAP_MAP = {
|
|
10781
11879
|
none: "var(--spacing-space-none)",
|
|
10782
11880
|
xs: "var(--spacing-space-1)",
|
|
@@ -10789,13 +11887,13 @@ var GAP_MAP = {
|
|
|
10789
11887
|
var FullGrid = (props) => {
|
|
10790
11888
|
const { children, gap } = props;
|
|
10791
11889
|
const style = gap != null ? { gap: GAP_MAP[gap] } : void 0;
|
|
10792
|
-
return /* @__PURE__ */
|
|
11890
|
+
return /* @__PURE__ */ jsx355("div", { className: "lib-xplat-full-grid", style, children });
|
|
10793
11891
|
};
|
|
10794
11892
|
FullGrid.displayName = "FullGrid";
|
|
10795
11893
|
var FullGrid_default = FullGrid;
|
|
10796
11894
|
|
|
10797
11895
|
// src/layout/Grid/FullScreen/FullScreen.tsx
|
|
10798
|
-
import { jsx as
|
|
11896
|
+
import { jsx as jsx356 } from "react/jsx-runtime";
|
|
10799
11897
|
var GAP_MAP2 = {
|
|
10800
11898
|
none: "var(--spacing-space-none)",
|
|
10801
11899
|
xs: "var(--spacing-space-1)",
|
|
@@ -10808,13 +11906,13 @@ var GAP_MAP2 = {
|
|
|
10808
11906
|
var FullScreen = (props) => {
|
|
10809
11907
|
const { children, gap } = props;
|
|
10810
11908
|
const style = gap != null ? { gap: GAP_MAP2[gap] } : void 0;
|
|
10811
|
-
return /* @__PURE__ */
|
|
11909
|
+
return /* @__PURE__ */ jsx356("div", { className: "lib-xplat-full-screen", style, children });
|
|
10812
11910
|
};
|
|
10813
11911
|
FullScreen.displayName = "FullScreen";
|
|
10814
11912
|
var FullScreen_default = FullScreen;
|
|
10815
11913
|
|
|
10816
11914
|
// src/layout/Grid/Item/Item.tsx
|
|
10817
|
-
import { jsx as
|
|
11915
|
+
import { jsx as jsx357 } from "react/jsx-runtime";
|
|
10818
11916
|
var calculateSpans = (column) => {
|
|
10819
11917
|
const spans = {};
|
|
10820
11918
|
let inherited = column.default;
|
|
@@ -10831,35 +11929,35 @@ var GridItem = ({ column, children, className }) => {
|
|
|
10831
11929
|
Object.entries(spans).forEach(([key, value]) => {
|
|
10832
11930
|
style[`--column-${key}`] = value;
|
|
10833
11931
|
});
|
|
10834
|
-
return /* @__PURE__ */
|
|
11932
|
+
return /* @__PURE__ */ jsx357("div", { className: clsx_default("lib-xplat-grid-item", className), style, children });
|
|
10835
11933
|
};
|
|
10836
11934
|
GridItem.displayName = "GridItem";
|
|
10837
11935
|
var Item_default = GridItem;
|
|
10838
11936
|
|
|
10839
11937
|
// src/layout/Header/Header.tsx
|
|
10840
|
-
import { jsx as
|
|
11938
|
+
import { jsx as jsx358, jsxs as jsxs226 } from "react/jsx-runtime";
|
|
10841
11939
|
var Header = ({
|
|
10842
11940
|
logo,
|
|
10843
11941
|
centerContent,
|
|
10844
11942
|
rightContent
|
|
10845
11943
|
}) => {
|
|
10846
|
-
return /* @__PURE__ */
|
|
10847
|
-
/* @__PURE__ */
|
|
10848
|
-
/* @__PURE__ */
|
|
10849
|
-
/* @__PURE__ */
|
|
11944
|
+
return /* @__PURE__ */ jsxs226("div", { className: "lib-xplat-layout-header", children: [
|
|
11945
|
+
/* @__PURE__ */ jsx358("div", { children: logo }),
|
|
11946
|
+
/* @__PURE__ */ jsx358("div", { children: centerContent }),
|
|
11947
|
+
/* @__PURE__ */ jsx358("div", { children: rightContent })
|
|
10850
11948
|
] });
|
|
10851
11949
|
};
|
|
10852
11950
|
Header.displayName = "Header";
|
|
10853
11951
|
var Header_default = Header;
|
|
10854
11952
|
|
|
10855
11953
|
// src/layout/Layout/Layout.tsx
|
|
10856
|
-
import { Fragment as Fragment7, jsx as
|
|
11954
|
+
import { Fragment as Fragment7, jsx as jsx359, jsxs as jsxs227 } from "react/jsx-runtime";
|
|
10857
11955
|
var Layout = (props) => {
|
|
10858
11956
|
const { header, sideBar, children } = props;
|
|
10859
|
-
return /* @__PURE__ */
|
|
10860
|
-
sideBar && /* @__PURE__ */
|
|
10861
|
-
/* @__PURE__ */
|
|
10862
|
-
header && /* @__PURE__ */
|
|
11957
|
+
return /* @__PURE__ */ jsx359("div", { className: "lib-xplat-layout", children: /* @__PURE__ */ jsxs227("div", { className: "lib-xplat-layout-content-wrapper", children: [
|
|
11958
|
+
sideBar && /* @__PURE__ */ jsx359(Fragment7, { children: sideBar }),
|
|
11959
|
+
/* @__PURE__ */ jsxs227("div", { className: "lib-xplat-layout-content", children: [
|
|
11960
|
+
header && /* @__PURE__ */ jsx359("div", { className: "lib-xplat-layout-conent-header", children: header }),
|
|
10863
11961
|
children
|
|
10864
11962
|
] })
|
|
10865
11963
|
] }) });
|
|
@@ -10868,31 +11966,31 @@ Layout.displayName = "Layout";
|
|
|
10868
11966
|
var Layout_default = Layout;
|
|
10869
11967
|
|
|
10870
11968
|
// src/layout/SideBar/SideBar.tsx
|
|
10871
|
-
import
|
|
11969
|
+
import React45 from "react";
|
|
10872
11970
|
|
|
10873
11971
|
// src/layout/SideBar/SideBarContext.tsx
|
|
10874
|
-
import
|
|
10875
|
-
var SideBarContext =
|
|
11972
|
+
import React44 from "react";
|
|
11973
|
+
var SideBarContext = React44.createContext(null);
|
|
10876
11974
|
var useSideBarContext = () => {
|
|
10877
|
-
const ctx =
|
|
11975
|
+
const ctx = React44.useContext(SideBarContext);
|
|
10878
11976
|
if (!ctx) throw new Error("Error");
|
|
10879
11977
|
return ctx;
|
|
10880
11978
|
};
|
|
10881
11979
|
var SideBarContext_default = SideBarContext;
|
|
10882
11980
|
|
|
10883
11981
|
// src/layout/SideBar/SideBar.tsx
|
|
10884
|
-
import { jsx as
|
|
11982
|
+
import { jsx as jsx360 } from "react/jsx-runtime";
|
|
10885
11983
|
var SideBar = (props) => {
|
|
10886
11984
|
const { children, className } = props;
|
|
10887
|
-
const [isOpen, setIsOpen] =
|
|
11985
|
+
const [isOpen, setIsOpen] = React45.useState(true);
|
|
10888
11986
|
const handleSwitchSideBar = () => {
|
|
10889
11987
|
setIsOpen((prev) => !prev);
|
|
10890
11988
|
};
|
|
10891
|
-
return /* @__PURE__ */
|
|
11989
|
+
return /* @__PURE__ */ jsx360(
|
|
10892
11990
|
SideBarContext_default.Provider,
|
|
10893
11991
|
{
|
|
10894
11992
|
value: { isSidebarOpen: isOpen, handleSwitchSideBar },
|
|
10895
|
-
children: /* @__PURE__ */
|
|
11993
|
+
children: /* @__PURE__ */ jsx360(
|
|
10896
11994
|
"div",
|
|
10897
11995
|
{
|
|
10898
11996
|
className: clsx_default(
|
|
@@ -11199,6 +12297,7 @@ export {
|
|
|
11199
12297
|
Spinner_default as Spinner,
|
|
11200
12298
|
SquareIcon_default as SquareIcon,
|
|
11201
12299
|
StarIcon_default as StarIcon,
|
|
12300
|
+
Stat_default as Stat,
|
|
11202
12301
|
Steps_default as Steps,
|
|
11203
12302
|
StopCircleIcon_default as StopCircleIcon,
|
|
11204
12303
|
SuccessIcon_default as SuccessIcon,
|
|
@@ -11223,6 +12322,7 @@ export {
|
|
|
11223
12322
|
ThermometerIcon_default as ThermometerIcon,
|
|
11224
12323
|
ThumbsDownIcon_default as ThumbsDownIcon,
|
|
11225
12324
|
ThumbsUpIcon_default as ThumbsUpIcon,
|
|
12325
|
+
TimePicker_default as TimePicker,
|
|
11226
12326
|
ToastProvider,
|
|
11227
12327
|
ToggleLeftIcon_default as ToggleLeftIcon,
|
|
11228
12328
|
ToggleRightIcon_default as ToggleRightIcon,
|