@x-plat/design-system 0.11.0 → 0.13.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 +2 -2
- package/dist/components/AutoResizeTextArea/index.js +2 -2
- package/dist/components/ChatInput/index.cjs +2 -2
- package/dist/components/ChatInput/index.js +2 -2
- package/dist/components/CheckBox/index.cjs +2 -2
- package/dist/components/CheckBox/index.js +2 -2
- package/dist/components/DatePicker/index.cjs +109 -75
- package/dist/components/DatePicker/index.d.cts +19 -0
- package/dist/components/DatePicker/index.d.ts +19 -0
- package/dist/components/DatePicker/index.js +109 -75
- package/dist/components/Dropdown/index.cjs +22 -9
- package/dist/components/Dropdown/index.css +3 -0
- package/dist/components/Dropdown/index.js +22 -9
- package/dist/components/Editor/index.cjs +602 -30
- package/dist/components/Editor/index.css +103 -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 +602 -30
- package/dist/components/FieldMessage/index.cjs +2 -2
- package/dist/components/FieldMessage/index.d.cts +8 -0
- package/dist/components/FieldMessage/index.d.ts +8 -0
- package/dist/components/FieldMessage/index.js +2 -2
- package/dist/components/FileUpload/index.cjs +10 -6
- package/dist/components/FileUpload/index.d.cts +15 -2
- package/dist/components/FileUpload/index.d.ts +15 -2
- package/dist/components/FileUpload/index.js +10 -6
- package/dist/components/ImageSelector/index.cjs +7 -6
- package/dist/components/ImageSelector/index.d.cts +15 -2
- package/dist/components/ImageSelector/index.d.ts +15 -2
- package/dist/components/ImageSelector/index.js +7 -6
- package/dist/components/Input/index.cjs +2 -2
- package/dist/components/Input/index.d.cts +4 -0
- package/dist/components/Input/index.d.ts +4 -0
- package/dist/components/Input/index.js +2 -2
- package/dist/components/PopOver/index.cjs +21 -7
- package/dist/components/PopOver/index.css +3 -0
- package/dist/components/PopOver/index.js +21 -7
- package/dist/components/Radio/index.cjs +2 -2
- package/dist/components/Radio/index.js +2 -2
- package/dist/components/Select/index.cjs +23 -10
- package/dist/components/Select/index.css +3 -0
- package/dist/components/Select/index.d.cts +1 -2
- package/dist/components/Select/index.d.ts +1 -2
- package/dist/components/Select/index.js +23 -10
- package/dist/components/Switch/index.cjs +2 -2
- package/dist/components/Switch/index.js +2 -2
- package/dist/components/TextArea/index.cjs +2 -2
- package/dist/components/TextArea/index.js +2 -2
- package/dist/components/TimePicker/index.cjs +23 -10
- package/dist/components/TimePicker/index.css +3 -0
- package/dist/components/TimePicker/index.js +23 -10
- package/dist/components/index.cjs +751 -124
- package/dist/components/index.css +113 -0
- package/dist/components/index.js +751 -124
- package/dist/index.cjs +751 -124
- package/dist/index.css +113 -0
- package/dist/index.js +751 -124
- package/guidelines/Guidelines.md +12 -0
- package/guidelines/MIGRATION.md +270 -0
- package/guidelines/components/datepicker.md +26 -0
- package/guidelines/components/editor.md +58 -3
- package/guidelines/components/file-media.md +21 -4
- package/package.json +1 -1
package/dist/components/index.js
CHANGED
|
@@ -1532,11 +1532,11 @@ var FieldMessage = (props) => {
|
|
|
1532
1532
|
FieldMessage.displayName = "FieldMessage";
|
|
1533
1533
|
var FieldMessage_default = FieldMessage;
|
|
1534
1534
|
var Field = (props) => {
|
|
1535
|
-
const { label, required = false, htmlFor, validations, children } = props;
|
|
1535
|
+
const { label, required = false, htmlFor, labelId, validations, children } = props;
|
|
1536
1536
|
const hasMessages = !!validations && validations.length > 0;
|
|
1537
1537
|
if (!label && !hasMessages) return /* @__PURE__ */ jsx297(Fragment, { children });
|
|
1538
1538
|
return /* @__PURE__ */ jsxs191("div", { className: "lib-xplat-field", children: [
|
|
1539
|
-
label && /* @__PURE__ */ jsxs191("label", { className: "lib-xplat-field-label", htmlFor, children: [
|
|
1539
|
+
label && /* @__PURE__ */ jsxs191("label", { className: "lib-xplat-field-label", id: labelId, htmlFor, children: [
|
|
1540
1540
|
label,
|
|
1541
1541
|
required && /* @__PURE__ */ jsx297("span", { className: "required", "aria-hidden": "true", children: "*" })
|
|
1542
1542
|
] }),
|
|
@@ -3303,8 +3303,12 @@ var SingleDatePicker = (props) => {
|
|
|
3303
3303
|
highlightDates = [],
|
|
3304
3304
|
locale = "ko",
|
|
3305
3305
|
rangeStart,
|
|
3306
|
-
rangeEnd
|
|
3306
|
+
rangeEnd,
|
|
3307
|
+
label,
|
|
3308
|
+
required,
|
|
3309
|
+
validations
|
|
3307
3310
|
} = props;
|
|
3311
|
+
const labelId = React12.useId();
|
|
3308
3312
|
const initialYear = value?.getFullYear();
|
|
3309
3313
|
const initialMonth = value?.getMonth();
|
|
3310
3314
|
const { year, month, days, goToPrevMonth, goToNextMonth, setYear, setMonth } = useCalendar(
|
|
@@ -3367,10 +3371,12 @@ var SingleDatePicker = (props) => {
|
|
|
3367
3371
|
const monthLabels = MONTH_LABELS[locale];
|
|
3368
3372
|
const titleText = pickerMode === "days" ? locale === "ko" ? `${year}\uB144 ${monthLabels[month]}` : `${monthLabels[month]} ${year}` : pickerMode === "months" ? `${year}` : `${yearRangeStart} - ${yearRangeStart + 11}`;
|
|
3369
3373
|
const hasRange = rangeStart != null && rangeEnd != null;
|
|
3370
|
-
|
|
3374
|
+
const calendar = /* @__PURE__ */ jsxs200(
|
|
3371
3375
|
"div",
|
|
3372
3376
|
{
|
|
3373
3377
|
className: clsx_default("lib-xplat-datepicker", "single"),
|
|
3378
|
+
role: "group",
|
|
3379
|
+
"aria-labelledby": label ? labelId : void 0,
|
|
3374
3380
|
children: [
|
|
3375
3381
|
/* @__PURE__ */ jsxs200("div", { className: "datepicker-header", children: [
|
|
3376
3382
|
/* @__PURE__ */ jsx314("button", { className: "datepicker-nav", onClick: handlePrev, type: "button", children: /* @__PURE__ */ jsx314(ChevronLeftIcon_default, {}) }),
|
|
@@ -3391,18 +3397,18 @@ var SingleDatePicker = (props) => {
|
|
|
3391
3397
|
y
|
|
3392
3398
|
);
|
|
3393
3399
|
}) }),
|
|
3394
|
-
pickerMode === "months" && /* @__PURE__ */ jsx314("div", { className: "datepicker-picker-grid", children: monthLabels.map((
|
|
3400
|
+
pickerMode === "months" && /* @__PURE__ */ jsx314("div", { className: "datepicker-picker-grid", children: monthLabels.map((label2, i) => /* @__PURE__ */ jsx314(
|
|
3395
3401
|
"button",
|
|
3396
3402
|
{
|
|
3397
3403
|
type: "button",
|
|
3398
3404
|
className: clsx_default("datepicker-picker-cell", i === month && "active"),
|
|
3399
3405
|
onClick: () => handleMonthSelect(i),
|
|
3400
|
-
children:
|
|
3406
|
+
children: label2
|
|
3401
3407
|
},
|
|
3402
3408
|
i
|
|
3403
3409
|
)) }),
|
|
3404
3410
|
pickerMode === "days" && /* @__PURE__ */ jsxs200(Fragment4, { children: [
|
|
3405
|
-
/* @__PURE__ */ jsx314("div", { className: "datepicker-weekdays", children: weekdays.map((
|
|
3411
|
+
/* @__PURE__ */ jsx314("div", { className: "datepicker-weekdays", children: weekdays.map((label2, i) => /* @__PURE__ */ jsx314(
|
|
3406
3412
|
"div",
|
|
3407
3413
|
{
|
|
3408
3414
|
className: clsx_default(
|
|
@@ -3410,9 +3416,9 @@ var SingleDatePicker = (props) => {
|
|
|
3410
3416
|
i === 0 && "sunday",
|
|
3411
3417
|
i === 6 && "saturday"
|
|
3412
3418
|
),
|
|
3413
|
-
children:
|
|
3419
|
+
children: label2
|
|
3414
3420
|
},
|
|
3415
|
-
|
|
3421
|
+
label2
|
|
3416
3422
|
)) }),
|
|
3417
3423
|
/* @__PURE__ */ jsx314("div", { className: "datepicker-grid", children: days.map((day, idx) => {
|
|
3418
3424
|
const t = day.date.getTime();
|
|
@@ -3444,6 +3450,7 @@ var SingleDatePicker = (props) => {
|
|
|
3444
3450
|
]
|
|
3445
3451
|
}
|
|
3446
3452
|
);
|
|
3453
|
+
return /* @__PURE__ */ jsx314(Field, { label, required, labelId, validations, children: calendar });
|
|
3447
3454
|
};
|
|
3448
3455
|
SingleDatePicker.displayName = "SingleDatePicker";
|
|
3449
3456
|
var SingleDatePicker_default = SingleDatePicker;
|
|
@@ -3458,7 +3465,18 @@ var formatDate = (date) => {
|
|
|
3458
3465
|
return `${y}/${m}/${d}`;
|
|
3459
3466
|
};
|
|
3460
3467
|
var InputDatePicker = (props) => {
|
|
3461
|
-
const {
|
|
3468
|
+
const {
|
|
3469
|
+
value,
|
|
3470
|
+
onChange,
|
|
3471
|
+
minDate,
|
|
3472
|
+
maxDate,
|
|
3473
|
+
disabled,
|
|
3474
|
+
locale = "ko",
|
|
3475
|
+
placeholder,
|
|
3476
|
+
label,
|
|
3477
|
+
required,
|
|
3478
|
+
validations
|
|
3479
|
+
} = props;
|
|
3462
3480
|
const [isOpen, setIsOpen] = React13.useState(false);
|
|
3463
3481
|
const [tempDate, setTempDate] = React13.useState(value ?? /* @__PURE__ */ new Date());
|
|
3464
3482
|
const handleOpen = () => {
|
|
@@ -3484,6 +3502,9 @@ var InputDatePicker = (props) => {
|
|
|
3484
3502
|
placeholder,
|
|
3485
3503
|
suffix: /* @__PURE__ */ jsx315(CalenderIcon_default, {}),
|
|
3486
3504
|
disabled,
|
|
3505
|
+
label,
|
|
3506
|
+
required,
|
|
3507
|
+
validations,
|
|
3487
3508
|
readOnly: true
|
|
3488
3509
|
}
|
|
3489
3510
|
) }),
|
|
@@ -3615,8 +3636,12 @@ var RangePicker = (props) => {
|
|
|
3615
3636
|
onChange,
|
|
3616
3637
|
minDate,
|
|
3617
3638
|
maxDate,
|
|
3618
|
-
locale = "ko"
|
|
3639
|
+
locale = "ko",
|
|
3640
|
+
label,
|
|
3641
|
+
required,
|
|
3642
|
+
validations
|
|
3619
3643
|
} = props;
|
|
3644
|
+
const labelId = React16.useId();
|
|
3620
3645
|
const [activeTab, setActiveTab] = React16.useState("start");
|
|
3621
3646
|
const handleStartChange = (date) => {
|
|
3622
3647
|
if (!date) return;
|
|
@@ -3630,70 +3655,79 @@ var RangePicker = (props) => {
|
|
|
3630
3655
|
};
|
|
3631
3656
|
const startMaxDate = maxDate && endDate < maxDate ? endDate : endDate;
|
|
3632
3657
|
const endMinDate = minDate && startDate > minDate ? startDate : startDate;
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3658
|
+
const calendar = /* @__PURE__ */ jsxs203(
|
|
3659
|
+
"div",
|
|
3660
|
+
{
|
|
3661
|
+
className: clsx_default("lib-xplat-datepicker", "range"),
|
|
3662
|
+
role: "group",
|
|
3663
|
+
"aria-labelledby": label ? labelId : void 0,
|
|
3664
|
+
children: [
|
|
3665
|
+
/* @__PURE__ */ jsx318("div", { className: "datepicker-range-tabs", children: /* @__PURE__ */ jsx318(
|
|
3666
|
+
Tab_default,
|
|
3667
|
+
{
|
|
3668
|
+
activeIndex: activeTab === "start" ? 0 : 1,
|
|
3669
|
+
tabs: [
|
|
3670
|
+
{ value: "start", title: locale === "ko" ? "\uC2DC\uC791\uC77C" : "Start" },
|
|
3671
|
+
{ value: "end", title: locale === "ko" ? "\uC885\uB8CC\uC77C" : "End" }
|
|
3672
|
+
],
|
|
3673
|
+
onChange: (tab) => setActiveTab(tab.value),
|
|
3674
|
+
type: "toggle",
|
|
3675
|
+
size: "sm"
|
|
3676
|
+
}
|
|
3677
|
+
) }),
|
|
3678
|
+
/* @__PURE__ */ jsxs203("div", { className: "datepicker-range-panels", children: [
|
|
3679
|
+
/* @__PURE__ */ jsx318(
|
|
3680
|
+
SingleDatePicker_default,
|
|
3681
|
+
{
|
|
3682
|
+
value: startDate,
|
|
3683
|
+
onChange: handleStartChange,
|
|
3684
|
+
minDate,
|
|
3685
|
+
maxDate: startMaxDate,
|
|
3686
|
+
rangeStart: startDate,
|
|
3687
|
+
rangeEnd: endDate,
|
|
3688
|
+
locale
|
|
3689
|
+
}
|
|
3690
|
+
),
|
|
3691
|
+
/* @__PURE__ */ jsx318(
|
|
3692
|
+
SingleDatePicker_default,
|
|
3693
|
+
{
|
|
3694
|
+
value: endDate,
|
|
3695
|
+
onChange: handleEndChange,
|
|
3696
|
+
minDate: endMinDate,
|
|
3697
|
+
maxDate,
|
|
3698
|
+
rangeStart: startDate,
|
|
3699
|
+
rangeEnd: endDate,
|
|
3700
|
+
locale
|
|
3701
|
+
}
|
|
3702
|
+
)
|
|
3703
|
+
] }),
|
|
3704
|
+
/* @__PURE__ */ jsx318("div", { className: "datepicker-range-mobile", children: activeTab === "start" ? /* @__PURE__ */ jsx318(
|
|
3705
|
+
SingleDatePicker_default,
|
|
3706
|
+
{
|
|
3707
|
+
value: startDate,
|
|
3708
|
+
onChange: handleStartChange,
|
|
3709
|
+
minDate,
|
|
3710
|
+
maxDate: startMaxDate,
|
|
3711
|
+
rangeStart: startDate,
|
|
3712
|
+
rangeEnd: endDate,
|
|
3713
|
+
locale
|
|
3714
|
+
}
|
|
3715
|
+
) : /* @__PURE__ */ jsx318(
|
|
3716
|
+
SingleDatePicker_default,
|
|
3717
|
+
{
|
|
3718
|
+
value: endDate,
|
|
3719
|
+
onChange: handleEndChange,
|
|
3720
|
+
minDate: endMinDate,
|
|
3721
|
+
maxDate,
|
|
3722
|
+
rangeStart: startDate,
|
|
3723
|
+
rangeEnd: endDate,
|
|
3724
|
+
locale
|
|
3725
|
+
}
|
|
3726
|
+
) })
|
|
3727
|
+
]
|
|
3728
|
+
}
|
|
3729
|
+
);
|
|
3730
|
+
return /* @__PURE__ */ jsx318(Field, { label, required, labelId, validations, children: calendar });
|
|
3697
3731
|
};
|
|
3698
3732
|
RangePicker.displayName = "RangePicker";
|
|
3699
3733
|
var RangePicker_default = RangePicker;
|
|
@@ -3842,8 +3876,10 @@ import React19 from "react";
|
|
|
3842
3876
|
var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
3843
3877
|
const [position, setPosition] = React19.useState({
|
|
3844
3878
|
position: {},
|
|
3845
|
-
direction: "bottom"
|
|
3879
|
+
direction: "bottom",
|
|
3880
|
+
repositioning: false
|
|
3846
3881
|
});
|
|
3882
|
+
const placedRef = React19.useRef(false);
|
|
3847
3883
|
const calculatePosition = React19.useCallback(() => {
|
|
3848
3884
|
if (!triggerRef.current || !popRef.current) return;
|
|
3849
3885
|
const triggerRect = triggerRef.current.getBoundingClientRect();
|
|
@@ -3868,11 +3904,16 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
3868
3904
|
if (left < 8) left = 8;
|
|
3869
3905
|
setPosition({
|
|
3870
3906
|
position: { top, left },
|
|
3871
|
-
direction
|
|
3907
|
+
direction,
|
|
3908
|
+
repositioning: placedRef.current
|
|
3872
3909
|
});
|
|
3910
|
+
placedRef.current = true;
|
|
3873
3911
|
}, [triggerRef, popRef]);
|
|
3874
3912
|
React19.useLayoutEffect(() => {
|
|
3875
|
-
if (!enabled)
|
|
3913
|
+
if (!enabled) {
|
|
3914
|
+
placedRef.current = false;
|
|
3915
|
+
return;
|
|
3916
|
+
}
|
|
3876
3917
|
calculatePosition();
|
|
3877
3918
|
const raf = requestAnimationFrame(calculatePosition);
|
|
3878
3919
|
return () => cancelAnimationFrame(raf);
|
|
@@ -3887,11 +3928,17 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
3887
3928
|
}, [calculatePosition, enabled, popRef]);
|
|
3888
3929
|
React19.useEffect(() => {
|
|
3889
3930
|
if (!enabled) return;
|
|
3890
|
-
|
|
3891
|
-
|
|
3931
|
+
let raf = 0;
|
|
3932
|
+
const onScrollOrResize = () => {
|
|
3933
|
+
cancelAnimationFrame(raf);
|
|
3934
|
+
raf = requestAnimationFrame(calculatePosition);
|
|
3935
|
+
};
|
|
3936
|
+
window.addEventListener("resize", onScrollOrResize, { passive: true });
|
|
3937
|
+
window.addEventListener("scroll", onScrollOrResize, { passive: true, capture: true });
|
|
3892
3938
|
return () => {
|
|
3893
|
-
|
|
3894
|
-
window.removeEventListener("
|
|
3939
|
+
cancelAnimationFrame(raf);
|
|
3940
|
+
window.removeEventListener("resize", onScrollOrResize);
|
|
3941
|
+
window.removeEventListener("scroll", onScrollOrResize, true);
|
|
3895
3942
|
};
|
|
3896
3943
|
}, [calculatePosition, enabled]);
|
|
3897
3944
|
return position;
|
|
@@ -3932,7 +3979,7 @@ var Dropdown = (props) => {
|
|
|
3932
3979
|
const [visible, setVisible] = React21.useState(false);
|
|
3933
3980
|
const triggerRef = React21.useRef(null);
|
|
3934
3981
|
const menuRef = React21.useRef(null);
|
|
3935
|
-
const { position, direction } = useAutoPosition_default(triggerRef, menuRef, mounted);
|
|
3982
|
+
const { position, direction, repositioning } = useAutoPosition_default(triggerRef, menuRef, mounted);
|
|
3936
3983
|
useClickOutside_default([triggerRef, menuRef], () => setIsOpen(false), isOpen);
|
|
3937
3984
|
useEscapeKey(isOpen, () => {
|
|
3938
3985
|
setIsOpen(false);
|
|
@@ -3967,7 +4014,7 @@ var Dropdown = (props) => {
|
|
|
3967
4014
|
"div",
|
|
3968
4015
|
{
|
|
3969
4016
|
ref: menuRef,
|
|
3970
|
-
className: clsx_default("lib-xplat-dropdown-menu", direction, { visible }),
|
|
4017
|
+
className: clsx_default("lib-xplat-dropdown-menu", direction, { visible }, repositioning && "repositioning"),
|
|
3971
4018
|
style: { top: position.top, left: position.left },
|
|
3972
4019
|
role: "menu",
|
|
3973
4020
|
children: items.map((item) => /* @__PURE__ */ jsx322(
|
|
@@ -3993,6 +4040,111 @@ var Dropdown_default = Dropdown;
|
|
|
3993
4040
|
|
|
3994
4041
|
// src/components/Editor/Editor.tsx
|
|
3995
4042
|
import React22 from "react";
|
|
4043
|
+
|
|
4044
|
+
// src/components/Editor/highlight.ts
|
|
4045
|
+
var CODE_LANGUAGES = [
|
|
4046
|
+
{ value: "plain", label: "\uC5C6\uC74C" },
|
|
4047
|
+
{ value: "javascript", label: "JavaScript" },
|
|
4048
|
+
{ value: "typescript", label: "TypeScript" },
|
|
4049
|
+
{ value: "json", label: "JSON" },
|
|
4050
|
+
{ value: "html", label: "HTML" },
|
|
4051
|
+
{ value: "css", label: "CSS" },
|
|
4052
|
+
{ value: "python", label: "Python" },
|
|
4053
|
+
{ value: "sql", label: "SQL" },
|
|
4054
|
+
{ value: "bash", label: "Bash" }
|
|
4055
|
+
];
|
|
4056
|
+
var KEYWORDS = {
|
|
4057
|
+
plain: [],
|
|
4058
|
+
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(" "),
|
|
4059
|
+
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(" "),
|
|
4060
|
+
json: ["true", "false", "null"],
|
|
4061
|
+
html: [],
|
|
4062
|
+
css: [],
|
|
4063
|
+
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(" "),
|
|
4064
|
+
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(" "),
|
|
4065
|
+
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(" ")
|
|
4066
|
+
};
|
|
4067
|
+
var LINE_COMMENT = {
|
|
4068
|
+
javascript: "//",
|
|
4069
|
+
typescript: "//",
|
|
4070
|
+
css: "",
|
|
4071
|
+
python: "#",
|
|
4072
|
+
sql: "--",
|
|
4073
|
+
bash: "#"
|
|
4074
|
+
};
|
|
4075
|
+
var escape = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
4076
|
+
var wrap = (cls, text) => `<span class="tok-${cls}">${escape(text)}</span>`;
|
|
4077
|
+
var highlight = (code, lang) => {
|
|
4078
|
+
if (lang === "plain" || !code) return escape(code);
|
|
4079
|
+
const keywords = new Set(KEYWORDS[lang]);
|
|
4080
|
+
const lineComment = LINE_COMMENT[lang];
|
|
4081
|
+
const caseInsensitive = lang === "sql";
|
|
4082
|
+
let out = "";
|
|
4083
|
+
let i = 0;
|
|
4084
|
+
while (i < code.length) {
|
|
4085
|
+
const rest = code.slice(i);
|
|
4086
|
+
if ((lang === "javascript" || lang === "typescript" || lang === "css") && rest.startsWith("/*")) {
|
|
4087
|
+
const end = code.indexOf("*/", i + 2);
|
|
4088
|
+
const stop = end === -1 ? code.length : end + 2;
|
|
4089
|
+
out += wrap("comment", code.slice(i, stop));
|
|
4090
|
+
i = stop;
|
|
4091
|
+
continue;
|
|
4092
|
+
}
|
|
4093
|
+
if (lineComment && rest.startsWith(lineComment)) {
|
|
4094
|
+
const nl = code.indexOf("\n", i);
|
|
4095
|
+
const stop = nl === -1 ? code.length : nl;
|
|
4096
|
+
out += wrap("comment", code.slice(i, stop));
|
|
4097
|
+
i = stop;
|
|
4098
|
+
continue;
|
|
4099
|
+
}
|
|
4100
|
+
const q = rest[0];
|
|
4101
|
+
if (q === '"' || q === "'" || q === "`") {
|
|
4102
|
+
let j = 1;
|
|
4103
|
+
while (j < rest.length) {
|
|
4104
|
+
if (rest[j] === "\\") {
|
|
4105
|
+
j += 2;
|
|
4106
|
+
continue;
|
|
4107
|
+
}
|
|
4108
|
+
if (rest[j] === q) {
|
|
4109
|
+
j += 1;
|
|
4110
|
+
break;
|
|
4111
|
+
}
|
|
4112
|
+
if (rest[j] === "\n" && q !== "`") break;
|
|
4113
|
+
j += 1;
|
|
4114
|
+
}
|
|
4115
|
+
out += wrap("string", rest.slice(0, j));
|
|
4116
|
+
i += j;
|
|
4117
|
+
continue;
|
|
4118
|
+
}
|
|
4119
|
+
const num = /^\d+(\.\d+)?/.exec(rest);
|
|
4120
|
+
if (num && !/[\w$]/.test(code[i - 1] ?? "")) {
|
|
4121
|
+
out += wrap("number", num[0]);
|
|
4122
|
+
i += num[0].length;
|
|
4123
|
+
continue;
|
|
4124
|
+
}
|
|
4125
|
+
const word = /^[A-Za-z_$][\w$]*/.exec(rest);
|
|
4126
|
+
if (word) {
|
|
4127
|
+
const w = word[0];
|
|
4128
|
+
const hit = caseInsensitive ? keywords.has(w.toUpperCase()) : keywords.has(w);
|
|
4129
|
+
out += hit ? wrap("keyword", w) : escape(w);
|
|
4130
|
+
i += w.length;
|
|
4131
|
+
continue;
|
|
4132
|
+
}
|
|
4133
|
+
if (lang === "html" && rest.startsWith("<")) {
|
|
4134
|
+
const tag = /^<\/?[A-Za-z][\w-]*/.exec(rest);
|
|
4135
|
+
if (tag) {
|
|
4136
|
+
out += wrap("keyword", tag[0]);
|
|
4137
|
+
i += tag[0].length;
|
|
4138
|
+
continue;
|
|
4139
|
+
}
|
|
4140
|
+
}
|
|
4141
|
+
out += escape(code[i]);
|
|
4142
|
+
i += 1;
|
|
4143
|
+
}
|
|
4144
|
+
return out;
|
|
4145
|
+
};
|
|
4146
|
+
|
|
4147
|
+
// src/components/Editor/Editor.tsx
|
|
3996
4148
|
import { jsx as jsx323, jsxs as jsxs207 } from "react/jsx-runtime";
|
|
3997
4149
|
var DEFAULT_TOOLBAR = [
|
|
3998
4150
|
"bold",
|
|
@@ -4000,14 +4152,27 @@ var DEFAULT_TOOLBAR = [
|
|
|
4000
4152
|
"underline",
|
|
4001
4153
|
"strikethrough",
|
|
4002
4154
|
"code",
|
|
4003
|
-
"heading",
|
|
4155
|
+
"heading-1",
|
|
4156
|
+
"heading-2",
|
|
4157
|
+
"heading-3",
|
|
4004
4158
|
"list",
|
|
4005
4159
|
"ordered-list",
|
|
4006
4160
|
"blockquote",
|
|
4007
4161
|
"code-block",
|
|
4008
4162
|
"link",
|
|
4009
4163
|
"image",
|
|
4010
|
-
"divider"
|
|
4164
|
+
"divider",
|
|
4165
|
+
"checklist",
|
|
4166
|
+
"table",
|
|
4167
|
+
"align-left",
|
|
4168
|
+
"align-center",
|
|
4169
|
+
"align-right",
|
|
4170
|
+
"highlight",
|
|
4171
|
+
"superscript",
|
|
4172
|
+
"subscript",
|
|
4173
|
+
"clear-format",
|
|
4174
|
+
"undo",
|
|
4175
|
+
"redo"
|
|
4011
4176
|
];
|
|
4012
4177
|
var ALLOWED_TAGS = /* @__PURE__ */ new Set([
|
|
4013
4178
|
"p",
|
|
@@ -4036,11 +4201,41 @@ var ALLOWED_TAGS = /* @__PURE__ */ new Set([
|
|
|
4036
4201
|
"img",
|
|
4037
4202
|
"hr",
|
|
4038
4203
|
"span",
|
|
4039
|
-
"div"
|
|
4204
|
+
"div",
|
|
4205
|
+
"sub",
|
|
4206
|
+
"sup",
|
|
4207
|
+
"mark",
|
|
4208
|
+
"table",
|
|
4209
|
+
"thead",
|
|
4210
|
+
"tbody",
|
|
4211
|
+
"tr",
|
|
4212
|
+
"th",
|
|
4213
|
+
"td"
|
|
4040
4214
|
]);
|
|
4041
4215
|
var ALLOWED_ATTRS = {
|
|
4042
4216
|
a: ["href", "target", "rel"],
|
|
4043
|
-
img: ["src", "alt"]
|
|
4217
|
+
img: ["src", "alt", "width"],
|
|
4218
|
+
// 정렬·체크리스트는 클래스로만 표현한다. style 을 열면 붙여넣기로 아무 CSS 나 들어온다
|
|
4219
|
+
p: ["class"],
|
|
4220
|
+
h1: ["class"],
|
|
4221
|
+
h2: ["class"],
|
|
4222
|
+
h3: ["class"],
|
|
4223
|
+
h4: ["class"],
|
|
4224
|
+
h5: ["class"],
|
|
4225
|
+
h6: ["class"],
|
|
4226
|
+
ul: ["class"],
|
|
4227
|
+
ol: ["class"],
|
|
4228
|
+
li: ["class", "data-checked"],
|
|
4229
|
+
blockquote: ["class"],
|
|
4230
|
+
div: ["class"],
|
|
4231
|
+
span: ["class"],
|
|
4232
|
+
pre: ["class"],
|
|
4233
|
+
code: ["class"],
|
|
4234
|
+
mark: ["class"],
|
|
4235
|
+
table: ["class"],
|
|
4236
|
+
td: ["class"],
|
|
4237
|
+
th: ["class"],
|
|
4238
|
+
tr: ["class"]
|
|
4044
4239
|
};
|
|
4045
4240
|
var DROP_WITH_CONTENT = /* @__PURE__ */ new Set([
|
|
4046
4241
|
"script",
|
|
@@ -4093,7 +4288,9 @@ var escapeHtml = (text) => {
|
|
|
4093
4288
|
};
|
|
4094
4289
|
var SLASH_ITEMS = [
|
|
4095
4290
|
{ key: "paragraph", label: "\uB2E8\uB77D", hint: "\uAE30\uBCF8 \uD14D\uC2A4\uD2B8" },
|
|
4096
|
-
{ key: "heading", label: "\uC81C\uBAA9 1", hint: "\uD070 \uC81C\uBAA9" },
|
|
4291
|
+
{ key: "heading-1", label: "\uC81C\uBAA9 1", hint: "\uAC00\uC7A5 \uD070 \uC81C\uBAA9" },
|
|
4292
|
+
{ key: "heading-2", label: "\uC81C\uBAA9 2", hint: "" },
|
|
4293
|
+
{ key: "heading-3", label: "\uC81C\uBAA9 3", hint: "" },
|
|
4097
4294
|
{ key: "list", label: "\uAE00\uBA38\uB9AC \uAE30\uD638 \uBAA9\uB85D", hint: "\u2022 \uD56D\uBAA9" },
|
|
4098
4295
|
{ key: "ordered-list", label: "\uBC88\uD638 \uB9E4\uAE30\uAE30 \uBAA9\uB85D", hint: "1. \uD56D\uBAA9" },
|
|
4099
4296
|
{ key: "blockquote", label: "\uC778\uC6A9", hint: "" },
|
|
@@ -4136,6 +4333,8 @@ var Editor = (props) => {
|
|
|
4136
4333
|
el.innerHTML = sanitizeHtml(value || "");
|
|
4137
4334
|
if (!el.firstChild) el.innerHTML = "<p><br></p>";
|
|
4138
4335
|
lastEmittedRef.current = null;
|
|
4336
|
+
historyRef.current = [{ html: el.innerHTML, caret: 0 }];
|
|
4337
|
+
historyIdxRef.current = 0;
|
|
4139
4338
|
updateEmpty();
|
|
4140
4339
|
}, [value]);
|
|
4141
4340
|
const updateEmpty = () => {
|
|
@@ -4180,6 +4379,17 @@ var Editor = (props) => {
|
|
|
4180
4379
|
if (document.queryCommandState("insertOrderedList")) next.add("ordered-list");
|
|
4181
4380
|
const block = String(document.queryCommandValue("formatBlock") || "").toLowerCase();
|
|
4182
4381
|
if (block) next.add(`block:${block}`);
|
|
4382
|
+
if (document.queryCommandState("superscript")) next.add("superscript");
|
|
4383
|
+
if (document.queryCommandState("subscript")) next.add("subscript");
|
|
4384
|
+
} catch {
|
|
4385
|
+
}
|
|
4386
|
+
try {
|
|
4387
|
+
const blockEl = currentBlock();
|
|
4388
|
+
if (blockEl?.classList.contains("align-center")) next.add("align:center");
|
|
4389
|
+
else if (blockEl?.classList.contains("align-right")) next.add("align:right");
|
|
4390
|
+
else if (blockEl) next.add("align:left");
|
|
4391
|
+
if (blockEl?.closest("mark")) next.add("highlight");
|
|
4392
|
+
if (blockEl?.closest("ul.checklist")) next.add("checklist");
|
|
4183
4393
|
} catch {
|
|
4184
4394
|
}
|
|
4185
4395
|
setActiveFormats(next);
|
|
@@ -4193,6 +4403,122 @@ var Editor = (props) => {
|
|
|
4193
4403
|
const setBlock = (tag) => {
|
|
4194
4404
|
exec("formatBlock", tag);
|
|
4195
4405
|
};
|
|
4406
|
+
const toggleBlock = (tag) => {
|
|
4407
|
+
const current = String(document.queryCommandValue("formatBlock") || "").toLowerCase();
|
|
4408
|
+
setBlock(current === tag ? "p" : tag);
|
|
4409
|
+
};
|
|
4410
|
+
const historyRef = React22.useRef([]);
|
|
4411
|
+
const historyIdxRef = React22.useRef(-1);
|
|
4412
|
+
const lastPushAtRef = React22.useRef(0);
|
|
4413
|
+
const isRestoringRef = React22.useRef(false);
|
|
4414
|
+
const caretOffset = (rootEl) => {
|
|
4415
|
+
const el = rootEl ?? editorRef.current;
|
|
4416
|
+
const sel = window.getSelection();
|
|
4417
|
+
if (!el || !sel || sel.rangeCount === 0 || !el.contains(sel.anchorNode)) return 0;
|
|
4418
|
+
const range = sel.getRangeAt(0).cloneRange();
|
|
4419
|
+
range.selectNodeContents(el);
|
|
4420
|
+
range.setEnd(sel.getRangeAt(0).endContainer, sel.getRangeAt(0).endOffset);
|
|
4421
|
+
return range.toString().length;
|
|
4422
|
+
};
|
|
4423
|
+
const setCaretOffset = (offset, rootEl) => {
|
|
4424
|
+
const el = rootEl ?? editorRef.current;
|
|
4425
|
+
if (!el) return;
|
|
4426
|
+
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
|
|
4427
|
+
let remaining = offset;
|
|
4428
|
+
let node = null;
|
|
4429
|
+
while (node = walker.nextNode()) {
|
|
4430
|
+
const len = node.textContent?.length ?? 0;
|
|
4431
|
+
if (remaining <= len) {
|
|
4432
|
+
const range = document.createRange();
|
|
4433
|
+
range.setStart(node, remaining);
|
|
4434
|
+
range.collapse(true);
|
|
4435
|
+
const sel = window.getSelection();
|
|
4436
|
+
sel?.removeAllRanges();
|
|
4437
|
+
sel?.addRange(range);
|
|
4438
|
+
return;
|
|
4439
|
+
}
|
|
4440
|
+
remaining -= len;
|
|
4441
|
+
}
|
|
4442
|
+
placeCaretAtEnd(el);
|
|
4443
|
+
};
|
|
4444
|
+
const pushHistory = (force = false) => {
|
|
4445
|
+
const el = editorRef.current;
|
|
4446
|
+
if (!el || isRestoringRef.current) return;
|
|
4447
|
+
const html = el.innerHTML;
|
|
4448
|
+
const hist = historyRef.current;
|
|
4449
|
+
const cur = hist[historyIdxRef.current];
|
|
4450
|
+
if (cur && cur.html === html) return;
|
|
4451
|
+
const now = Date.now();
|
|
4452
|
+
const coalesce = !force && cur && now - lastPushAtRef.current < 500;
|
|
4453
|
+
lastPushAtRef.current = now;
|
|
4454
|
+
if (coalesce) {
|
|
4455
|
+
hist[historyIdxRef.current] = { html, caret: caretOffset() };
|
|
4456
|
+
return;
|
|
4457
|
+
}
|
|
4458
|
+
hist.length = historyIdxRef.current + 1;
|
|
4459
|
+
hist.push({ html, caret: caretOffset() });
|
|
4460
|
+
if (hist.length > 200) hist.shift();
|
|
4461
|
+
historyIdxRef.current = hist.length - 1;
|
|
4462
|
+
};
|
|
4463
|
+
const applySnapshot = (snap) => {
|
|
4464
|
+
const el = editorRef.current;
|
|
4465
|
+
if (!el) return;
|
|
4466
|
+
isRestoringRef.current = true;
|
|
4467
|
+
el.innerHTML = snap.html;
|
|
4468
|
+
setCaretOffset(snap.caret);
|
|
4469
|
+
isRestoringRef.current = false;
|
|
4470
|
+
lastEmittedRef.current = el.innerHTML;
|
|
4471
|
+
onChange?.(el.innerHTML);
|
|
4472
|
+
updateEmpty();
|
|
4473
|
+
updateActiveFormats();
|
|
4474
|
+
};
|
|
4475
|
+
const undo = () => {
|
|
4476
|
+
pushHistory(true);
|
|
4477
|
+
if (historyIdxRef.current <= 0) return;
|
|
4478
|
+
historyIdxRef.current -= 1;
|
|
4479
|
+
applySnapshot(historyRef.current[historyIdxRef.current]);
|
|
4480
|
+
};
|
|
4481
|
+
const redo = () => {
|
|
4482
|
+
if (historyIdxRef.current >= historyRef.current.length - 1) return;
|
|
4483
|
+
historyIdxRef.current += 1;
|
|
4484
|
+
applySnapshot(historyRef.current[historyIdxRef.current]);
|
|
4485
|
+
};
|
|
4486
|
+
const langOf = (pre) => {
|
|
4487
|
+
const cls = Array.from(pre.classList).find((c) => c.startsWith("lang-"));
|
|
4488
|
+
return cls?.slice(5) ?? "plain";
|
|
4489
|
+
};
|
|
4490
|
+
const [codeLang, setCodeLang] = React22.useState("plain");
|
|
4491
|
+
const highlightRafRef = React22.useRef(0);
|
|
4492
|
+
const rehighlight = (pre) => {
|
|
4493
|
+
if (composingRef.current) return;
|
|
4494
|
+
const code = pre.querySelector("code");
|
|
4495
|
+
if (!code) return;
|
|
4496
|
+
const lang = langOf(pre);
|
|
4497
|
+
const text = code.textContent || "";
|
|
4498
|
+
const next = highlight(text, lang);
|
|
4499
|
+
if (code.innerHTML === next) return;
|
|
4500
|
+
const caret = caretOffset(code);
|
|
4501
|
+
isRestoringRef.current = true;
|
|
4502
|
+
code.innerHTML = next;
|
|
4503
|
+
setCaretOffset(caret, code);
|
|
4504
|
+
isRestoringRef.current = false;
|
|
4505
|
+
};
|
|
4506
|
+
const scheduleHighlight = () => {
|
|
4507
|
+
const pre = closestPre();
|
|
4508
|
+
if (!pre) return;
|
|
4509
|
+
cancelAnimationFrame(highlightRafRef.current);
|
|
4510
|
+
highlightRafRef.current = requestAnimationFrame(() => rehighlight(pre));
|
|
4511
|
+
};
|
|
4512
|
+
const changeCodeLang = (lang) => {
|
|
4513
|
+
const pre = closestPre();
|
|
4514
|
+
if (!pre) return;
|
|
4515
|
+
pushHistory(true);
|
|
4516
|
+
Array.from(pre.classList).filter((c) => c.startsWith("lang-")).forEach((c) => pre.classList.remove(c));
|
|
4517
|
+
if (lang !== "plain") pre.classList.add(`lang-${lang}`);
|
|
4518
|
+
setCodeLang(lang);
|
|
4519
|
+
rehighlight(pre);
|
|
4520
|
+
handleInput();
|
|
4521
|
+
};
|
|
4196
4522
|
const closestPre = () => {
|
|
4197
4523
|
const sel = window.getSelection();
|
|
4198
4524
|
const node = sel?.anchorNode;
|
|
@@ -4201,6 +4527,7 @@ var Editor = (props) => {
|
|
|
4201
4527
|
return el?.closest("pre") ?? null;
|
|
4202
4528
|
};
|
|
4203
4529
|
const insertCodeBlock = () => {
|
|
4530
|
+
pushHistory(true);
|
|
4204
4531
|
const el = editorRef.current;
|
|
4205
4532
|
const sel = window.getSelection();
|
|
4206
4533
|
if (!el || !sel || sel.rangeCount === 0) return;
|
|
@@ -4283,7 +4610,167 @@ var Editor = (props) => {
|
|
|
4283
4610
|
sel.addRange(r2);
|
|
4284
4611
|
editorRef.current?.focus();
|
|
4285
4612
|
};
|
|
4613
|
+
const clearFormat = () => {
|
|
4614
|
+
exec("removeFormat");
|
|
4615
|
+
exec("unlink");
|
|
4616
|
+
setBlock("p");
|
|
4617
|
+
};
|
|
4618
|
+
const indentList = (outdent) => {
|
|
4619
|
+
exec(outdent ? "outdent" : "indent");
|
|
4620
|
+
};
|
|
4621
|
+
const inListItem = () => {
|
|
4622
|
+
const sel = window.getSelection();
|
|
4623
|
+
const node = sel?.anchorNode;
|
|
4624
|
+
if (!node || !editorRef.current?.contains(node)) return false;
|
|
4625
|
+
const el = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
|
|
4626
|
+
return !!el?.closest("li");
|
|
4627
|
+
};
|
|
4628
|
+
const currentBlock = () => {
|
|
4629
|
+
const sel = window.getSelection();
|
|
4630
|
+
const node = sel?.anchorNode;
|
|
4631
|
+
const root = editorRef.current;
|
|
4632
|
+
if (!node || !root?.contains(node)) return null;
|
|
4633
|
+
let el = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
|
|
4634
|
+
while (el && el !== root && !/^(P|H[1-6]|LI|BLOCKQUOTE|PRE|DIV|TD|TH)$/.test(el.tagName)) {
|
|
4635
|
+
el = el.parentElement;
|
|
4636
|
+
}
|
|
4637
|
+
return el && el !== root ? el : null;
|
|
4638
|
+
};
|
|
4639
|
+
const setAlign = (align) => {
|
|
4640
|
+
const block = currentBlock();
|
|
4641
|
+
if (!block) return;
|
|
4642
|
+
pushHistory(true);
|
|
4643
|
+
block.classList.remove("align-left", "align-center", "align-right");
|
|
4644
|
+
if (align !== "left") block.classList.add(`align-${align}`);
|
|
4645
|
+
handleInput();
|
|
4646
|
+
};
|
|
4647
|
+
const toggleChecklist = () => {
|
|
4648
|
+
pushHistory(true);
|
|
4649
|
+
const block = currentBlock();
|
|
4650
|
+
const list = block?.closest("ul");
|
|
4651
|
+
if (list?.classList.contains("checklist")) {
|
|
4652
|
+
list.classList.remove("checklist");
|
|
4653
|
+
list.querySelectorAll("li").forEach((li) => li.removeAttribute("data-checked"));
|
|
4654
|
+
handleInput();
|
|
4655
|
+
return;
|
|
4656
|
+
}
|
|
4657
|
+
if (list) {
|
|
4658
|
+
list.classList.add("checklist");
|
|
4659
|
+
list.querySelectorAll("li").forEach((li) => li.setAttribute("data-checked", "false"));
|
|
4660
|
+
handleInput();
|
|
4661
|
+
return;
|
|
4662
|
+
}
|
|
4663
|
+
exec("insertUnorderedList");
|
|
4664
|
+
const made = currentBlock()?.closest("ul");
|
|
4665
|
+
if (made) {
|
|
4666
|
+
made.classList.add("checklist");
|
|
4667
|
+
made.querySelectorAll("li").forEach((li) => li.setAttribute("data-checked", "false"));
|
|
4668
|
+
}
|
|
4669
|
+
handleInput();
|
|
4670
|
+
};
|
|
4671
|
+
const handleEditorClick = (e) => {
|
|
4672
|
+
if (readOnly) return;
|
|
4673
|
+
const target = e.target;
|
|
4674
|
+
const li = target.closest?.("li");
|
|
4675
|
+
if (!li || !li.closest("ul.checklist")) return;
|
|
4676
|
+
const rect = li.getBoundingClientRect();
|
|
4677
|
+
if (e.clientX - rect.left > 20) return;
|
|
4678
|
+
e.preventDefault();
|
|
4679
|
+
pushHistory(true);
|
|
4680
|
+
li.setAttribute("data-checked", li.getAttribute("data-checked") === "true" ? "false" : "true");
|
|
4681
|
+
handleInput();
|
|
4682
|
+
};
|
|
4683
|
+
const toggleHighlight = () => {
|
|
4684
|
+
const sel = window.getSelection();
|
|
4685
|
+
if (!sel || sel.rangeCount === 0 || sel.isCollapsed) return;
|
|
4686
|
+
pushHistory(true);
|
|
4687
|
+
const range = sel.getRangeAt(0);
|
|
4688
|
+
const node = sel.anchorNode;
|
|
4689
|
+
const el = node?.nodeType === Node.ELEMENT_NODE ? node : node?.parentElement;
|
|
4690
|
+
const existing = el?.closest("mark");
|
|
4691
|
+
if (existing) {
|
|
4692
|
+
const parent = existing.parentNode;
|
|
4693
|
+
while (existing.firstChild) parent?.insertBefore(existing.firstChild, existing);
|
|
4694
|
+
parent?.removeChild(existing);
|
|
4695
|
+
handleInput();
|
|
4696
|
+
return;
|
|
4697
|
+
}
|
|
4698
|
+
const mark = document.createElement("mark");
|
|
4699
|
+
try {
|
|
4700
|
+
range.surroundContents(mark);
|
|
4701
|
+
} catch {
|
|
4702
|
+
const frag = range.extractContents();
|
|
4703
|
+
mark.appendChild(frag);
|
|
4704
|
+
range.insertNode(mark);
|
|
4705
|
+
}
|
|
4706
|
+
handleInput();
|
|
4707
|
+
};
|
|
4708
|
+
const insertTable = (cols = 3, rows = 2) => {
|
|
4709
|
+
const sel = window.getSelection();
|
|
4710
|
+
if (!sel || sel.rangeCount === 0) return;
|
|
4711
|
+
pushHistory(true);
|
|
4712
|
+
const table = document.createElement("table");
|
|
4713
|
+
const thead = document.createElement("thead");
|
|
4714
|
+
const headRow = document.createElement("tr");
|
|
4715
|
+
for (let c = 0; c < cols; c++) {
|
|
4716
|
+
const th = document.createElement("th");
|
|
4717
|
+
th.innerHTML = "<br>";
|
|
4718
|
+
headRow.appendChild(th);
|
|
4719
|
+
}
|
|
4720
|
+
thead.appendChild(headRow);
|
|
4721
|
+
table.appendChild(thead);
|
|
4722
|
+
const tbody = document.createElement("tbody");
|
|
4723
|
+
for (let r2 = 0; r2 < rows; r2++) {
|
|
4724
|
+
const tr = document.createElement("tr");
|
|
4725
|
+
for (let c = 0; c < cols; c++) {
|
|
4726
|
+
const td = document.createElement("td");
|
|
4727
|
+
td.innerHTML = "<br>";
|
|
4728
|
+
tr.appendChild(td);
|
|
4729
|
+
}
|
|
4730
|
+
tbody.appendChild(tr);
|
|
4731
|
+
}
|
|
4732
|
+
table.appendChild(tbody);
|
|
4733
|
+
const range = sel.getRangeAt(0);
|
|
4734
|
+
range.deleteContents();
|
|
4735
|
+
range.insertNode(table);
|
|
4736
|
+
ensureParagraphAfter(table);
|
|
4737
|
+
const first = table.querySelector("th");
|
|
4738
|
+
if (first) placeCaretAtEnd(first);
|
|
4739
|
+
handleInput();
|
|
4740
|
+
};
|
|
4741
|
+
const moveTableCell = (backwards) => {
|
|
4742
|
+
const block = currentBlock();
|
|
4743
|
+
const cell = block?.closest("td, th");
|
|
4744
|
+
if (!cell) return false;
|
|
4745
|
+
const table = cell.closest("table");
|
|
4746
|
+
if (!table) return false;
|
|
4747
|
+
const cells = Array.from(table.querySelectorAll("td, th"));
|
|
4748
|
+
const i = cells.indexOf(cell);
|
|
4749
|
+
const next = cells[i + (backwards ? -1 : 1)];
|
|
4750
|
+
if (next) {
|
|
4751
|
+
placeCaretAtEnd(next);
|
|
4752
|
+
return true;
|
|
4753
|
+
}
|
|
4754
|
+
if (!backwards) {
|
|
4755
|
+
pushHistory(true);
|
|
4756
|
+
const lastRow = table.querySelector("tbody")?.lastElementChild;
|
|
4757
|
+
if (lastRow) {
|
|
4758
|
+
const tr = document.createElement("tr");
|
|
4759
|
+
for (let c = 0; c < lastRow.children.length; c++) {
|
|
4760
|
+
const td = document.createElement("td");
|
|
4761
|
+
td.innerHTML = "<br>";
|
|
4762
|
+
tr.appendChild(td);
|
|
4763
|
+
}
|
|
4764
|
+
lastRow.after(tr);
|
|
4765
|
+
placeCaretAtEnd(tr.firstElementChild);
|
|
4766
|
+
handleInput();
|
|
4767
|
+
return true;
|
|
4768
|
+
}
|
|
4769
|
+
}
|
|
4770
|
+
return false;
|
|
4771
|
+
};
|
|
4286
4772
|
const insertDivider = () => {
|
|
4773
|
+
pushHistory(true);
|
|
4287
4774
|
exec("insertHorizontalRule");
|
|
4288
4775
|
const el = editorRef.current;
|
|
4289
4776
|
if (el && el.lastElementChild?.tagName === "HR") {
|
|
@@ -4376,8 +4863,14 @@ var Editor = (props) => {
|
|
|
4376
4863
|
case "paragraph":
|
|
4377
4864
|
setBlock("p");
|
|
4378
4865
|
break;
|
|
4379
|
-
case "heading":
|
|
4380
|
-
|
|
4866
|
+
case "heading-1":
|
|
4867
|
+
toggleBlock("h1");
|
|
4868
|
+
break;
|
|
4869
|
+
case "heading-2":
|
|
4870
|
+
toggleBlock("h2");
|
|
4871
|
+
break;
|
|
4872
|
+
case "heading-3":
|
|
4873
|
+
toggleBlock("h3");
|
|
4381
4874
|
break;
|
|
4382
4875
|
case "list":
|
|
4383
4876
|
exec("insertUnorderedList");
|
|
@@ -4470,6 +4963,8 @@ var Editor = (props) => {
|
|
|
4470
4963
|
if (!el) return;
|
|
4471
4964
|
const html = el.innerHTML;
|
|
4472
4965
|
lastEmittedRef.current = html;
|
|
4966
|
+
pushHistory();
|
|
4967
|
+
scheduleHighlight();
|
|
4473
4968
|
onChange?.(html);
|
|
4474
4969
|
updateEmpty();
|
|
4475
4970
|
updateActiveFormats();
|
|
@@ -4523,6 +5018,15 @@ var Editor = (props) => {
|
|
|
4523
5018
|
return;
|
|
4524
5019
|
}
|
|
4525
5020
|
}
|
|
5021
|
+
if (e.key === "Tab" && moveTableCell(e.shiftKey)) {
|
|
5022
|
+
e.preventDefault();
|
|
5023
|
+
return;
|
|
5024
|
+
}
|
|
5025
|
+
if (e.key === "Tab" && inListItem()) {
|
|
5026
|
+
e.preventDefault();
|
|
5027
|
+
indentList(e.shiftKey);
|
|
5028
|
+
return;
|
|
5029
|
+
}
|
|
4526
5030
|
if (slashOpen) {
|
|
4527
5031
|
if (e.key === "ArrowDown") {
|
|
4528
5032
|
e.preventDefault();
|
|
@@ -4546,6 +5050,21 @@ var Editor = (props) => {
|
|
|
4546
5050
|
return;
|
|
4547
5051
|
}
|
|
4548
5052
|
}
|
|
5053
|
+
if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "z") {
|
|
5054
|
+
e.preventDefault();
|
|
5055
|
+
if (e.shiftKey) redo();
|
|
5056
|
+
else undo();
|
|
5057
|
+
return;
|
|
5058
|
+
}
|
|
5059
|
+
if ((e.metaKey || e.ctrlKey) && e.shiftKey && e.key.toLowerCase() === "v") {
|
|
5060
|
+
plainPasteRef.current = true;
|
|
5061
|
+
return;
|
|
5062
|
+
}
|
|
5063
|
+
if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "y") {
|
|
5064
|
+
e.preventDefault();
|
|
5065
|
+
redo();
|
|
5066
|
+
return;
|
|
5067
|
+
}
|
|
4549
5068
|
if ((e.metaKey || e.ctrlKey) && !e.shiftKey && !e.altKey) {
|
|
4550
5069
|
const k = e.key.toLowerCase();
|
|
4551
5070
|
if (k === "b") {
|
|
@@ -4579,10 +5098,16 @@ var Editor = (props) => {
|
|
|
4579
5098
|
}
|
|
4580
5099
|
}
|
|
4581
5100
|
};
|
|
5101
|
+
const plainPasteRef = React22.useRef(false);
|
|
4582
5102
|
const handlePaste = (e) => {
|
|
4583
5103
|
if (readOnly) return;
|
|
4584
5104
|
e.preventDefault();
|
|
4585
5105
|
const text = e.clipboardData.getData("text/plain");
|
|
5106
|
+
if (plainPasteRef.current) {
|
|
5107
|
+
plainPasteRef.current = false;
|
|
5108
|
+
insertTextAtCaret(text);
|
|
5109
|
+
return;
|
|
5110
|
+
}
|
|
4586
5111
|
if (closestPre()) {
|
|
4587
5112
|
insertTextAtCaret(text);
|
|
4588
5113
|
return;
|
|
@@ -4609,9 +5134,11 @@ var Editor = (props) => {
|
|
|
4609
5134
|
};
|
|
4610
5135
|
const handleSelectionUpdate = () => {
|
|
4611
5136
|
updateActiveFormats();
|
|
5137
|
+
const pre = closestPre();
|
|
5138
|
+
setCodeLang(pre ? langOf(pre) : "plain");
|
|
4612
5139
|
};
|
|
4613
5140
|
const onToolbarAction = (item) => {
|
|
4614
|
-
if (closestPre() &&
|
|
5141
|
+
if (closestPre() && !["code-block", "undo", "redo"].includes(item)) return;
|
|
4615
5142
|
switch (item) {
|
|
4616
5143
|
case "bold":
|
|
4617
5144
|
exec("bold");
|
|
@@ -4640,8 +5167,14 @@ var Editor = (props) => {
|
|
|
4640
5167
|
handleInput();
|
|
4641
5168
|
break;
|
|
4642
5169
|
}
|
|
4643
|
-
case "heading":
|
|
4644
|
-
|
|
5170
|
+
case "heading-1":
|
|
5171
|
+
toggleBlock("h1");
|
|
5172
|
+
break;
|
|
5173
|
+
case "heading-2":
|
|
5174
|
+
toggleBlock("h2");
|
|
5175
|
+
break;
|
|
5176
|
+
case "heading-3":
|
|
5177
|
+
toggleBlock("h3");
|
|
4645
5178
|
break;
|
|
4646
5179
|
case "list":
|
|
4647
5180
|
exec("insertUnorderedList");
|
|
@@ -4664,6 +5197,39 @@ var Editor = (props) => {
|
|
|
4664
5197
|
case "divider":
|
|
4665
5198
|
insertDivider();
|
|
4666
5199
|
break;
|
|
5200
|
+
case "checklist":
|
|
5201
|
+
toggleChecklist();
|
|
5202
|
+
break;
|
|
5203
|
+
case "align-left":
|
|
5204
|
+
setAlign("left");
|
|
5205
|
+
break;
|
|
5206
|
+
case "align-center":
|
|
5207
|
+
setAlign("center");
|
|
5208
|
+
break;
|
|
5209
|
+
case "align-right":
|
|
5210
|
+
setAlign("right");
|
|
5211
|
+
break;
|
|
5212
|
+
case "highlight":
|
|
5213
|
+
toggleHighlight();
|
|
5214
|
+
break;
|
|
5215
|
+
case "superscript":
|
|
5216
|
+
exec("superscript");
|
|
5217
|
+
break;
|
|
5218
|
+
case "subscript":
|
|
5219
|
+
exec("subscript");
|
|
5220
|
+
break;
|
|
5221
|
+
case "table":
|
|
5222
|
+
insertTable();
|
|
5223
|
+
break;
|
|
5224
|
+
case "clear-format":
|
|
5225
|
+
clearFormat();
|
|
5226
|
+
break;
|
|
5227
|
+
case "undo":
|
|
5228
|
+
undo();
|
|
5229
|
+
break;
|
|
5230
|
+
case "redo":
|
|
5231
|
+
redo();
|
|
5232
|
+
break;
|
|
4667
5233
|
}
|
|
4668
5234
|
};
|
|
4669
5235
|
return /* @__PURE__ */ jsxs207("div", { className: clsx_default("lib-xplat-editor", isFocused && "focused", readOnly && "readonly"), children: [
|
|
@@ -4672,7 +5238,10 @@ var Editor = (props) => {
|
|
|
4672
5238
|
{
|
|
4673
5239
|
items: toolbar,
|
|
4674
5240
|
active: activeFormats,
|
|
4675
|
-
onAction: onToolbarAction
|
|
5241
|
+
onAction: onToolbarAction,
|
|
5242
|
+
codeLang,
|
|
5243
|
+
inCodeBlock: activeFormats.has("block:pre"),
|
|
5244
|
+
onCodeLangChange: changeCodeLang
|
|
4676
5245
|
}
|
|
4677
5246
|
),
|
|
4678
5247
|
/* @__PURE__ */ jsxs207("div", { className: "lib-xplat-editor__content", style: { minHeight }, children: [
|
|
@@ -4690,6 +5259,7 @@ var Editor = (props) => {
|
|
|
4690
5259
|
className: "lib-xplat-editor__editable",
|
|
4691
5260
|
onInput: handleInput,
|
|
4692
5261
|
onKeyDown: handleKeyDown,
|
|
5262
|
+
onClick: handleEditorClick,
|
|
4693
5263
|
onKeyUp: handleSelectionUpdate,
|
|
4694
5264
|
onMouseUp: handleSelectionUpdate,
|
|
4695
5265
|
onPaste: handlePaste,
|
|
@@ -4731,14 +5301,27 @@ var TOOLBAR_LABEL = {
|
|
|
4731
5301
|
underline: "U",
|
|
4732
5302
|
strikethrough: "S",
|
|
4733
5303
|
code: "<>",
|
|
4734
|
-
heading: "
|
|
5304
|
+
"heading-1": "H1",
|
|
5305
|
+
"heading-2": "H2",
|
|
5306
|
+
"heading-3": "H3",
|
|
4735
5307
|
list: "\u2022",
|
|
4736
5308
|
"ordered-list": "1.",
|
|
4737
5309
|
blockquote: "\u275D",
|
|
4738
5310
|
"code-block": "[ ]",
|
|
4739
5311
|
link: "\u{1F517}",
|
|
4740
5312
|
image: "\u{1F5BC}",
|
|
4741
|
-
divider: "\u2014"
|
|
5313
|
+
divider: "\u2014",
|
|
5314
|
+
checklist: "\u2611",
|
|
5315
|
+
"align-left": "\u21E4",
|
|
5316
|
+
"align-center": "\u2194",
|
|
5317
|
+
"align-right": "\u21E5",
|
|
5318
|
+
highlight: "\u{1F58D}",
|
|
5319
|
+
superscript: "x\xB2",
|
|
5320
|
+
subscript: "x\u2082",
|
|
5321
|
+
table: "\u25A6",
|
|
5322
|
+
"clear-format": "\u232B",
|
|
5323
|
+
undo: "\u21B6",
|
|
5324
|
+
redo: "\u21B7"
|
|
4742
5325
|
};
|
|
4743
5326
|
var TOOLBAR_TITLE = {
|
|
4744
5327
|
bold: "\uAD75\uAC8C (\u2318B)",
|
|
@@ -4746,36 +5329,74 @@ var TOOLBAR_TITLE = {
|
|
|
4746
5329
|
underline: "\uBC11\uC904 (\u2318U)",
|
|
4747
5330
|
strikethrough: "\uCDE8\uC18C\uC120",
|
|
4748
5331
|
code: "\uC778\uB77C\uC778 \uCF54\uB4DC",
|
|
4749
|
-
heading: "\uC81C\uBAA9",
|
|
5332
|
+
"heading-1": "\uC81C\uBAA9 1",
|
|
5333
|
+
"heading-2": "\uC81C\uBAA9 2",
|
|
5334
|
+
"heading-3": "\uC81C\uBAA9 3",
|
|
4750
5335
|
list: "\uAE00\uBA38\uB9AC \uAE30\uD638 \uBAA9\uB85D",
|
|
4751
5336
|
"ordered-list": "\uBC88\uD638 \uB9E4\uAE30\uAE30 \uBAA9\uB85D",
|
|
4752
5337
|
blockquote: "\uC778\uC6A9",
|
|
4753
5338
|
"code-block": "\uCF54\uB4DC \uBE14\uB85D",
|
|
4754
5339
|
link: "\uB9C1\uD06C (\u2318K)",
|
|
4755
5340
|
image: "\uC774\uBBF8\uC9C0",
|
|
4756
|
-
divider: "\uAD6C\uBD84\uC120"
|
|
5341
|
+
divider: "\uAD6C\uBD84\uC120",
|
|
5342
|
+
checklist: "\uCCB4\uD06C\uB9AC\uC2A4\uD2B8",
|
|
5343
|
+
"align-left": "\uC67C\uCABD \uC815\uB82C",
|
|
5344
|
+
"align-center": "\uAC00\uC6B4\uB370 \uC815\uB82C",
|
|
5345
|
+
"align-right": "\uC624\uB978\uCABD \uC815\uB82C",
|
|
5346
|
+
highlight: "\uD615\uAD11\uD39C",
|
|
5347
|
+
superscript: "\uC704 \uCCA8\uC790",
|
|
5348
|
+
subscript: "\uC544\uB798 \uCCA8\uC790",
|
|
5349
|
+
table: "\uD45C \uC0BD\uC785",
|
|
5350
|
+
"clear-format": "\uC11C\uC2DD \uC9C0\uC6B0\uAE30",
|
|
5351
|
+
undo: "\uB418\uB3CC\uB9AC\uAE30 (\u2318Z)",
|
|
5352
|
+
redo: "\uB2E4\uC2DC\uD558\uAE30 (\u2318\u21E7Z)"
|
|
4757
5353
|
};
|
|
4758
5354
|
var isActive = (item, active) => {
|
|
4759
|
-
if (item === "heading") return active.has("block:h1")
|
|
5355
|
+
if (item === "heading-1") return active.has("block:h1");
|
|
5356
|
+
if (item === "heading-2") return active.has("block:h2");
|
|
5357
|
+
if (item === "heading-3") return active.has("block:h3");
|
|
4760
5358
|
if (item === "blockquote") return active.has("block:blockquote");
|
|
4761
5359
|
if (item === "code-block") return active.has("block:pre");
|
|
5360
|
+
if (item === "align-left") return active.has("align:left");
|
|
5361
|
+
if (item === "align-center") return active.has("align:center");
|
|
5362
|
+
if (item === "align-right") return active.has("align:right");
|
|
4762
5363
|
return active.has(item);
|
|
4763
5364
|
};
|
|
4764
|
-
var EditorToolbar = ({
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
|
|
5365
|
+
var EditorToolbar = ({
|
|
5366
|
+
items,
|
|
5367
|
+
active,
|
|
5368
|
+
onAction,
|
|
5369
|
+
codeLang,
|
|
5370
|
+
inCodeBlock,
|
|
5371
|
+
onCodeLangChange
|
|
5372
|
+
}) => {
|
|
5373
|
+
return /* @__PURE__ */ jsxs207("div", { className: "lib-xplat-editor__toolbar", children: [
|
|
5374
|
+
items.map((item) => /* @__PURE__ */ jsx323(
|
|
5375
|
+
"button",
|
|
5376
|
+
{
|
|
5377
|
+
type: "button",
|
|
5378
|
+
className: clsx_default("lib-xplat-editor__toolbar-btn", isActive(item, active) && "active"),
|
|
5379
|
+
title: TOOLBAR_TITLE[item],
|
|
5380
|
+
onMouseDown: (e) => {
|
|
5381
|
+
e.preventDefault();
|
|
5382
|
+
onAction(item);
|
|
5383
|
+
},
|
|
5384
|
+
children: TOOLBAR_LABEL[item]
|
|
4774
5385
|
},
|
|
4775
|
-
|
|
4776
|
-
|
|
4777
|
-
|
|
4778
|
-
|
|
5386
|
+
item
|
|
5387
|
+
)),
|
|
5388
|
+
inCodeBlock && /* @__PURE__ */ jsx323(
|
|
5389
|
+
"select",
|
|
5390
|
+
{
|
|
5391
|
+
className: "lib-xplat-editor__lang",
|
|
5392
|
+
value: codeLang,
|
|
5393
|
+
"aria-label": "\uCF54\uB4DC \uC5B8\uC5B4",
|
|
5394
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
5395
|
+
onChange: (e) => onCodeLangChange(e.target.value),
|
|
5396
|
+
children: CODE_LANGUAGES.map((l) => /* @__PURE__ */ jsx323("option", { value: l.value, children: l.label }, l.value))
|
|
5397
|
+
}
|
|
5398
|
+
)
|
|
5399
|
+
] });
|
|
4779
5400
|
};
|
|
4780
5401
|
var SlashMenu = ({ position, items, activeIndex, onSelect, onClose }) => {
|
|
4781
5402
|
React22.useEffect(() => {
|
|
@@ -4879,10 +5500,13 @@ var FileUpload = (props) => {
|
|
|
4879
5500
|
multiple = false,
|
|
4880
5501
|
maxSize,
|
|
4881
5502
|
onChange,
|
|
4882
|
-
|
|
5503
|
+
placeholder = "\uD30C\uC77C\uC744 \uB4DC\uB798\uADF8\uD558\uAC70\uB098 \uD074\uB9AD\uD558\uC5EC \uC5C5\uB85C\uB4DC",
|
|
4883
5504
|
description,
|
|
4884
|
-
validations
|
|
5505
|
+
validations,
|
|
5506
|
+
label,
|
|
5507
|
+
required
|
|
4885
5508
|
} = props;
|
|
5509
|
+
const fieldId = React23.useId();
|
|
4886
5510
|
const [isDragOver, setIsDragOver] = React23.useState(false);
|
|
4887
5511
|
const inputRef = React23.useRef(null);
|
|
4888
5512
|
const handleFiles = (fileList) => {
|
|
@@ -4927,6 +5551,7 @@ var FileUpload = (props) => {
|
|
|
4927
5551
|
"input",
|
|
4928
5552
|
{
|
|
4929
5553
|
ref: inputRef,
|
|
5554
|
+
id: fieldId,
|
|
4930
5555
|
type: "file",
|
|
4931
5556
|
accept,
|
|
4932
5557
|
multiple,
|
|
@@ -4935,12 +5560,12 @@ var FileUpload = (props) => {
|
|
|
4935
5560
|
}
|
|
4936
5561
|
),
|
|
4937
5562
|
/* @__PURE__ */ jsx325("div", { className: "upload-icon", children: /* @__PURE__ */ jsx325(UploadIcon_default, {}) }),
|
|
4938
|
-
/* @__PURE__ */ jsx325("p", { className: "upload-label", children:
|
|
5563
|
+
/* @__PURE__ */ jsx325("p", { className: "upload-label", children: placeholder }),
|
|
4939
5564
|
description && /* @__PURE__ */ jsx325("p", { className: "upload-description", children: description })
|
|
4940
5565
|
]
|
|
4941
5566
|
}
|
|
4942
5567
|
);
|
|
4943
|
-
return /* @__PURE__ */ jsx325(Field, { validations, children: control });
|
|
5568
|
+
return /* @__PURE__ */ jsx325(Field, { label, required, htmlFor: fieldId, validations, children: control });
|
|
4944
5569
|
};
|
|
4945
5570
|
FileUpload.displayName = "FileUpload";
|
|
4946
5571
|
var FileUpload_default = FileUpload;
|
|
@@ -5083,7 +5708,8 @@ var HtmlTypeWriter_default = HtmlTypeWriter;
|
|
|
5083
5708
|
import React26 from "react";
|
|
5084
5709
|
import { jsx as jsx327, jsxs as jsxs210 } from "react/jsx-runtime";
|
|
5085
5710
|
var ImageSelector = (props) => {
|
|
5086
|
-
const { value,
|
|
5711
|
+
const { value, placeholder, onChange, validations, label, required } = props;
|
|
5712
|
+
const fieldId = React26.useId();
|
|
5087
5713
|
const [previewUrl, setPreviewUrl] = React26.useState();
|
|
5088
5714
|
React26.useEffect(() => {
|
|
5089
5715
|
if (!value) {
|
|
@@ -5113,7 +5739,7 @@ var ImageSelector = (props) => {
|
|
|
5113
5739
|
{
|
|
5114
5740
|
type: "file",
|
|
5115
5741
|
accept: "image/*",
|
|
5116
|
-
id:
|
|
5742
|
+
id: fieldId,
|
|
5117
5743
|
onChange: handleFileChange,
|
|
5118
5744
|
ref: inputRef,
|
|
5119
5745
|
"aria-invalid": hasError(validations) || void 0
|
|
@@ -5125,10 +5751,10 @@ var ImageSelector = (props) => {
|
|
|
5125
5751
|
] }),
|
|
5126
5752
|
/* @__PURE__ */ jsx327("div", { className: "content", children: previewUrl ? /* @__PURE__ */ jsx327("img", { src: previewUrl, alt: "preview" }) : /* @__PURE__ */ jsxs210("div", { className: "skeleton", onClick: handleOpenFileDialog, children: [
|
|
5127
5753
|
/* @__PURE__ */ jsx327("div", { className: "icon-wrapper", children: /* @__PURE__ */ jsx327(ImageIcon_default, {}) }),
|
|
5128
|
-
/* @__PURE__ */ jsx327("div", { className: "label", children:
|
|
5754
|
+
/* @__PURE__ */ jsx327("div", { className: "label", children: placeholder || "\uC774\uBBF8\uC9C0 \uCD94\uAC00\uD558\uAE30" })
|
|
5129
5755
|
] }) })
|
|
5130
5756
|
] });
|
|
5131
|
-
return /* @__PURE__ */ jsx327(Field, { validations, children: control });
|
|
5757
|
+
return /* @__PURE__ */ jsx327(Field, { label, required, htmlFor: fieldId, validations, children: control });
|
|
5132
5758
|
};
|
|
5133
5759
|
ImageSelector.displayName = "ImageSelector";
|
|
5134
5760
|
var ImageSelector_default = ImageSelector;
|
|
@@ -5320,6 +5946,7 @@ var PopOver = (props) => {
|
|
|
5320
5946
|
className: clsx_default(
|
|
5321
5947
|
"lib-xplat-pop-over-content",
|
|
5322
5948
|
position.direction,
|
|
5949
|
+
position.repositioning && "repositioning",
|
|
5323
5950
|
eventTrigger && "visible"
|
|
5324
5951
|
),
|
|
5325
5952
|
ref: popRef,
|
|
@@ -5666,7 +6293,7 @@ var SelectRoot = (props) => {
|
|
|
5666
6293
|
mounted && /* @__PURE__ */ jsx337(Portal_default, { children: /* @__PURE__ */ jsxs216(
|
|
5667
6294
|
"div",
|
|
5668
6295
|
{
|
|
5669
|
-
className: clsx_default("lib-xplat-select-content", size, position.direction, stateClass),
|
|
6296
|
+
className: clsx_default("lib-xplat-select-content", size, position.direction, stateClass, position.repositioning && "repositioning"),
|
|
5670
6297
|
ref: contentRef,
|
|
5671
6298
|
style: { ...position.position, width: triggerRef.current?.offsetWidth },
|
|
5672
6299
|
role: "listbox",
|
|
@@ -6559,7 +7186,7 @@ var TimePicker = (props) => {
|
|
|
6559
7186
|
"div",
|
|
6560
7187
|
{
|
|
6561
7188
|
ref: contentRef,
|
|
6562
|
-
className: clsx_default("lib-xplat-time-picker-content", size, visible ? "enter" : "exit"),
|
|
7189
|
+
className: clsx_default("lib-xplat-time-picker-content", size, visible ? "enter" : "exit", position.repositioning && "repositioning"),
|
|
6563
7190
|
style: { ...position.position, width: triggerRef.current?.offsetWidth },
|
|
6564
7191
|
role: "listbox",
|
|
6565
7192
|
children: options.map((t) => /* @__PURE__ */ jsx351(
|