@ioca/react 1.5.29 → 1.5.30
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/lib/css/index.css +1 -1
- package/lib/es/components/checkbox/checkbox.js +1 -1
- package/lib/es/components/form/useForm.js +3 -4
- package/lib/es/components/input/input.js +2 -2
- package/lib/es/components/input/number.js +3 -5
- package/lib/es/components/input/range.js +2 -2
- package/lib/es/components/input/textarea.js +1 -1
- package/lib/es/components/modal/hookModal.js +11 -1
- package/lib/es/components/modal/modal.js +24 -16
- package/lib/es/components/pill/pill.js +2 -2
- package/lib/es/components/select/options.js +5 -7
- package/lib/es/components/select/select.js +4 -8
- package/lib/es/index.js +1 -2
- package/lib/index.js +276 -275
- package/lib/types/components/form/useForm.d.ts +1 -1
- package/lib/types/components/modal/type.d.ts +1 -1
- package/lib/types/components/pill/type.d.ts +1 -0
- package/lib/types/index.d.ts +1 -2
- package/package.json +1 -1
- package/lib/es/components/card/card.js +0 -12
- package/lib/es/components/card/index.js +0 -5
- package/lib/types/components/card/card.d.ts +0 -6
- package/lib/types/components/card/index.d.ts +0 -5
- package/lib/types/components/card/type.d.ts +0 -13
package/lib/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
|
2
2
|
import classNames from 'classnames';
|
|
3
3
|
import { debounce, uid, crush, throttle } from 'radash';
|
|
4
4
|
import { useState, useRef, useEffect, useCallback, useMemo, Children, cloneElement, createElement, isValidElement, memo, Fragment as Fragment$1, useTransition, forwardRef, useLayoutEffect, useContext, createContext, useImperativeHandle } from 'react';
|
|
5
|
-
import { SkipPreviousRound, CloseRound, MinusRound, PlusRound,
|
|
5
|
+
import { SkipPreviousRound, CloseRound, MinusRound, PlusRound, InboxTwotone, UndoRound, RedoRound, FormatBoldRound, FormatItalicRound, FormatUnderlinedRound, StrikethroughSRound, ClearAllRound, PlayArrowRound, PauseRound, StopRound, VolumeDownRound, VolumeOffRound, FullscreenRound, FullscreenExitRound, FeedOutlined, AspectRatioRound, OpenInNewRound, FileDownloadOutlined, RotateRightRound, RotateLeftRound, KeyboardArrowLeftRound, KeyboardArrowRightRound, KeyboardDoubleArrowUpRound, SyncAltRound, VisibilityRound, VisibilityOffRound, MoreHorizRound, SearchRound, CheckRound, UnfoldMoreRound, CalendarMonthTwotone, AccessTimeRound, AddRound, KeyboardArrowDownRound, MoveToInboxTwotone, OutboxTwotone, FilePresentOutlined, DriveFolderUploadOutlined } from '@ricons/material';
|
|
6
6
|
import { createRoot } from 'react-dom/client';
|
|
7
7
|
import { getScrollbarSize, List as List$2 } from 'react-window';
|
|
8
8
|
import { createPortal, flushSync } from 'react-dom';
|
|
@@ -575,14 +575,6 @@ const Badge = (props) => {
|
|
|
575
575
|
}), style: { fontSize: dotSize }, children: content })] }));
|
|
576
576
|
};
|
|
577
577
|
|
|
578
|
-
const Card = (props) => {
|
|
579
|
-
const { hideShadow, border, className, children, header, footer, ...restProps } = props;
|
|
580
|
-
return (jsxs("div", { className: classNames("i-card", className, {
|
|
581
|
-
shadow: !hideShadow,
|
|
582
|
-
"i-card-bordered": border,
|
|
583
|
-
}), ...restProps, children: [header && jsx("div", { className: 'i-card-header', children: header }), children && jsx("div", { className: 'i-card-content', children: children }), footer && jsx("div", { className: 'i-card-footer', children: footer })] }));
|
|
584
|
-
};
|
|
585
|
-
|
|
586
578
|
function getPosition($source, $popup, options = {}) {
|
|
587
579
|
const { refWindow, gap = 0, offset = 0, position = "top", align } = options;
|
|
588
580
|
if (!$source || !$popup)
|
|
@@ -917,7 +909,7 @@ function Checkbox(props) {
|
|
|
917
909
|
"i-input-inline": labelInline,
|
|
918
910
|
}, className), ...restProps, children: [label && (jsxs("span", { className: "i-input-label-text", children: [required && jsx("span", { className: "error", children: "*" }), label, message && jsx("p", { className: "i-checkbox-message", children: message })] })), jsx("div", { className: classNames("i-checkbox-options", {
|
|
919
911
|
"i-options-block": !optionInline,
|
|
920
|
-
|
|
912
|
+
[`i-checkbox-options-${type}`]: true,
|
|
921
913
|
}), children: formattedOptions.map((option) => {
|
|
922
914
|
return (jsx(CheckboxItem, { name: name, value: selectedValues.includes(option.value), optionValue: option.value, type: type, disabled: disabled || option.disabled, onChange: (checked, e) => handleChange(checked, option, e), children: renderItem ?? option.label }, option.value));
|
|
923
915
|
}) })] }));
|
|
@@ -1006,224 +998,6 @@ const Collapse = (props) => {
|
|
|
1006
998
|
};
|
|
1007
999
|
Collapse.Item = Item$5;
|
|
1008
1000
|
|
|
1009
|
-
const Tag = (props) => {
|
|
1010
|
-
const { dot, dotClass, outline, round, size = "normal", className, children, onClose, onClick, ...restProps } = props;
|
|
1011
|
-
return (jsxs("span", { className: classNames("i-tag", {
|
|
1012
|
-
"i-tag-outline": outline,
|
|
1013
|
-
"i-tag-clickable": onClick,
|
|
1014
|
-
[`i-tag-${size}`]: size !== "normal",
|
|
1015
|
-
round,
|
|
1016
|
-
}, className), onClick: onClick, ...restProps, children: [dot && jsx("span", { className: classNames("i-tag-dot", dotClass) }), children, onClose && (jsx(Helpericon, { active: true, className: "i-tag-close i-tag-hover-close", onClick: onClose }))] }));
|
|
1017
|
-
};
|
|
1018
|
-
|
|
1019
|
-
const CreateTag = memo(function CreateTag(props) {
|
|
1020
|
-
const { isEditing, isLoading, createTagProps, tagProps, onBlur, onKeyDown, onStartCreate } = props;
|
|
1021
|
-
if (isEditing) {
|
|
1022
|
-
return (jsx(Tag, { ...createTagProps, className: classNames("i-pill", tagProps?.className, "i-pill-editing"), contentEditable: true, suppressContentEditableWarning: true, onBlur: () => onBlur(-1), onKeyDown: (e) => onKeyDown(e, -1), children: isLoading && jsx(Loading, { size: ".86em", className: "ml-4" }) }, "pill-editing"));
|
|
1023
|
-
}
|
|
1024
|
-
return (jsx(Tag, { ...createTagProps, className: classNames("i-pill", tagProps?.className, "i-pill-create"), onClick: onStartCreate, children: jsx("b", { children: "\uFF0B" }) }, "pill-create"));
|
|
1025
|
-
});
|
|
1026
|
-
|
|
1027
|
-
const TagItem = memo(function TagItem(props) {
|
|
1028
|
-
const { item, index, isEditing, isLoading, tagProps, editable, readonly, renderItem, onClose, onClick, onBlur, onKeyDown } = props;
|
|
1029
|
-
const isClickable = !isEditing && editable && !readonly;
|
|
1030
|
-
if (renderItem) {
|
|
1031
|
-
return renderItem({
|
|
1032
|
-
value: item,
|
|
1033
|
-
index,
|
|
1034
|
-
editing: isEditing,
|
|
1035
|
-
loading: isLoading,
|
|
1036
|
-
readonly: !!readonly,
|
|
1037
|
-
remove: () => onClose(index),
|
|
1038
|
-
});
|
|
1039
|
-
}
|
|
1040
|
-
return (jsxs(Tag, { ...tagProps, className: classNames("i-pill", tagProps?.className, { "i-pill-editing": isEditing }), contentEditable: isEditing, suppressContentEditableWarning: true, onClose: !isEditing && !isLoading && !readonly ? () => onClose(index) : undefined, onClick: isClickable ? (e) => onClick(e, index) : undefined, onBlur: isEditing ? () => onBlur(index) : undefined, onKeyDown: isEditing ? (e) => onKeyDown(e, index) : undefined, children: [item, isLoading && jsx(Loading, { size: ".86em", className: "ml-4" })] }));
|
|
1041
|
-
});
|
|
1042
|
-
|
|
1043
|
-
function Pill(props) {
|
|
1044
|
-
const { value = [], tagProps, max, icon = jsx(AddRound, {}), className, label, labelInline, readonly, editable, onChange, onUpdate, validator, format, renderItem, ...restProps } = props;
|
|
1045
|
-
const [editingIndex, setEditingIndex] = useState(null);
|
|
1046
|
-
const [loadingSet, setLoadingSet] = useState(new Set());
|
|
1047
|
-
const instRef = useRef({
|
|
1048
|
-
props,
|
|
1049
|
-
editingIndex,
|
|
1050
|
-
loadingSet,
|
|
1051
|
-
setEditingIndex,
|
|
1052
|
-
setLoadingSet,
|
|
1053
|
-
});
|
|
1054
|
-
instRef.current.props = props;
|
|
1055
|
-
instRef.current.editingIndex = editingIndex;
|
|
1056
|
-
instRef.current.loadingSet = loadingSet;
|
|
1057
|
-
instRef.current.setEditingIndex = setEditingIndex;
|
|
1058
|
-
instRef.current.setLoadingSet = setLoadingSet;
|
|
1059
|
-
useEffect(() => {
|
|
1060
|
-
if (editingIndex !== null) {
|
|
1061
|
-
const el = document.querySelector(".i-pill-editing");
|
|
1062
|
-
el?.focus();
|
|
1063
|
-
}
|
|
1064
|
-
}, [editingIndex]);
|
|
1065
|
-
const cleanTagProps = useMemo(() => {
|
|
1066
|
-
if (!tagProps)
|
|
1067
|
-
return {};
|
|
1068
|
-
const { onClose, dot, dotClass, ...rest } = tagProps;
|
|
1069
|
-
return rest;
|
|
1070
|
-
}, [tagProps]);
|
|
1071
|
-
const handleClose = useCallback((index) => {
|
|
1072
|
-
const inst = instRef.current;
|
|
1073
|
-
if (inst.props.readonly)
|
|
1074
|
-
return;
|
|
1075
|
-
const hasAsync = !!inst.props.onUpdate;
|
|
1076
|
-
if (hasAsync)
|
|
1077
|
-
inst.setLoadingSet((prev) => new Set(prev).add(index));
|
|
1078
|
-
setTimeout(async () => {
|
|
1079
|
-
try {
|
|
1080
|
-
const { props } = instRef.current;
|
|
1081
|
-
const values = props.value ?? [];
|
|
1082
|
-
const item = values[index];
|
|
1083
|
-
if (item === undefined)
|
|
1084
|
-
return;
|
|
1085
|
-
const result = props.onUpdate?.(undefined, item, "delete");
|
|
1086
|
-
if (result instanceof Promise) {
|
|
1087
|
-
const ok = await result;
|
|
1088
|
-
if (ok === false)
|
|
1089
|
-
return;
|
|
1090
|
-
}
|
|
1091
|
-
const next = [...values];
|
|
1092
|
-
next.splice(index, 1);
|
|
1093
|
-
props.onChange?.(next);
|
|
1094
|
-
}
|
|
1095
|
-
finally {
|
|
1096
|
-
if (hasAsync) {
|
|
1097
|
-
instRef.current.setLoadingSet((prev) => {
|
|
1098
|
-
const s = new Set(prev);
|
|
1099
|
-
s.delete(index);
|
|
1100
|
-
return s;
|
|
1101
|
-
});
|
|
1102
|
-
}
|
|
1103
|
-
}
|
|
1104
|
-
}, 0);
|
|
1105
|
-
}, []);
|
|
1106
|
-
const handleItemClick = useCallback((e, index) => {
|
|
1107
|
-
if (e.target.closest(".i-helpericon"))
|
|
1108
|
-
return;
|
|
1109
|
-
const inst = instRef.current;
|
|
1110
|
-
if (inst.props.readonly)
|
|
1111
|
-
return;
|
|
1112
|
-
if (index === -1 && inst.props.max !== undefined && (inst.props.value?.length ?? 0) >= inst.props.max)
|
|
1113
|
-
return;
|
|
1114
|
-
inst.setEditingIndex(index);
|
|
1115
|
-
}, []);
|
|
1116
|
-
const commitEdit = useCallback((index, text) => {
|
|
1117
|
-
const inst = instRef.current;
|
|
1118
|
-
const formatted = inst.props.format ? inst.props.format(text) : text;
|
|
1119
|
-
const hasAsync = !!(inst.props.validator || inst.props.onUpdate);
|
|
1120
|
-
if (hasAsync)
|
|
1121
|
-
inst.setLoadingSet((prev) => new Set(prev).add(index));
|
|
1122
|
-
setTimeout(async () => {
|
|
1123
|
-
try {
|
|
1124
|
-
const { props } = instRef.current;
|
|
1125
|
-
if (props.validator) {
|
|
1126
|
-
const valid = await Promise.resolve(props.validator(formatted));
|
|
1127
|
-
if (!valid)
|
|
1128
|
-
return;
|
|
1129
|
-
}
|
|
1130
|
-
const values = props.value ?? [];
|
|
1131
|
-
if (index === -1) {
|
|
1132
|
-
if (values.includes(formatted))
|
|
1133
|
-
return;
|
|
1134
|
-
const result = props.onUpdate?.(formatted, undefined, "create");
|
|
1135
|
-
if (result instanceof Promise) {
|
|
1136
|
-
const ok = await result;
|
|
1137
|
-
if (ok === false)
|
|
1138
|
-
return;
|
|
1139
|
-
}
|
|
1140
|
-
props.onChange?.([...values, formatted]);
|
|
1141
|
-
}
|
|
1142
|
-
else {
|
|
1143
|
-
const oldValue = values[index];
|
|
1144
|
-
if (oldValue === formatted)
|
|
1145
|
-
return;
|
|
1146
|
-
const result = props.onUpdate?.(formatted, oldValue, "update");
|
|
1147
|
-
if (result instanceof Promise) {
|
|
1148
|
-
const ok = await result;
|
|
1149
|
-
if (ok === false)
|
|
1150
|
-
return;
|
|
1151
|
-
}
|
|
1152
|
-
const next = [...values];
|
|
1153
|
-
next[index] = formatted;
|
|
1154
|
-
props.onChange?.(next);
|
|
1155
|
-
}
|
|
1156
|
-
}
|
|
1157
|
-
finally {
|
|
1158
|
-
if (hasAsync) {
|
|
1159
|
-
instRef.current.setLoadingSet((prev) => {
|
|
1160
|
-
const s = new Set(prev);
|
|
1161
|
-
s.delete(index);
|
|
1162
|
-
return s;
|
|
1163
|
-
});
|
|
1164
|
-
}
|
|
1165
|
-
instRef.current.setEditingIndex(null);
|
|
1166
|
-
}
|
|
1167
|
-
}, 0);
|
|
1168
|
-
}, []);
|
|
1169
|
-
const handleBlur = useCallback((index) => {
|
|
1170
|
-
const inst = instRef.current;
|
|
1171
|
-
if (inst.loadingSet.has(index))
|
|
1172
|
-
return;
|
|
1173
|
-
const el = document.querySelector(".i-pill-editing");
|
|
1174
|
-
const text = el?.textContent?.trim();
|
|
1175
|
-
if (!text) {
|
|
1176
|
-
if (index !== -1) {
|
|
1177
|
-
handleClose(index);
|
|
1178
|
-
}
|
|
1179
|
-
else {
|
|
1180
|
-
inst.setEditingIndex(null);
|
|
1181
|
-
}
|
|
1182
|
-
return;
|
|
1183
|
-
}
|
|
1184
|
-
commitEdit(index, text);
|
|
1185
|
-
}, []);
|
|
1186
|
-
const handleKeyDown = useCallback((e, index) => {
|
|
1187
|
-
const inst = instRef.current;
|
|
1188
|
-
if (inst.loadingSet.has(index))
|
|
1189
|
-
return;
|
|
1190
|
-
if (e.key === "Enter") {
|
|
1191
|
-
e.preventDefault();
|
|
1192
|
-
const text = e.currentTarget.textContent?.trim();
|
|
1193
|
-
if (!text) {
|
|
1194
|
-
if (index !== -1) {
|
|
1195
|
-
handleClose(index);
|
|
1196
|
-
}
|
|
1197
|
-
else {
|
|
1198
|
-
inst.setEditingIndex(null);
|
|
1199
|
-
}
|
|
1200
|
-
return;
|
|
1201
|
-
}
|
|
1202
|
-
commitEdit(index, text);
|
|
1203
|
-
}
|
|
1204
|
-
else if (e.key === "Escape") {
|
|
1205
|
-
e.preventDefault();
|
|
1206
|
-
if (index !== -1) {
|
|
1207
|
-
const original = inst.props.value?.[index];
|
|
1208
|
-
if (original !== undefined) {
|
|
1209
|
-
e.currentTarget.textContent = original;
|
|
1210
|
-
}
|
|
1211
|
-
}
|
|
1212
|
-
inst.setEditingIndex(null);
|
|
1213
|
-
}
|
|
1214
|
-
}, []);
|
|
1215
|
-
const handleStartCreate = useCallback(() => {
|
|
1216
|
-
const inst = instRef.current;
|
|
1217
|
-
if (inst.props.readonly)
|
|
1218
|
-
return;
|
|
1219
|
-
if (inst.props.max !== undefined && (inst.props.value?.length ?? 0) >= inst.props.max)
|
|
1220
|
-
return;
|
|
1221
|
-
inst.setEditingIndex(-1);
|
|
1222
|
-
}, []);
|
|
1223
|
-
const canCreate = !readonly && (max === undefined || value.length < max);
|
|
1224
|
-
return (jsxs("div", { className: classNames("i-pills i-input-label", { "i-input-inline": labelInline }, className), ...restProps, children: [label && jsx("span", { className: "i-input-label-text", children: label }), jsxs("div", { className: "i-pill-list", children: [value.map((item, i) => (jsx(TagItem, { item: item, index: i, isEditing: editingIndex === i, isLoading: loadingSet.has(i), tagProps: tagProps, editable: editable, readonly: readonly, renderItem: renderItem, onClose: handleClose, onClick: handleItemClick, onBlur: handleBlur, onKeyDown: handleKeyDown }, i))), canCreate && jsx(CreateTag, { isEditing: editingIndex === -1, isLoading: loadingSet.has(-1), createTagProps: cleanTagProps, tagProps: tagProps, onBlur: handleBlur, onKeyDown: handleKeyDown, onStartCreate: handleStartCreate })] })] }));
|
|
1225
|
-
}
|
|
1226
|
-
|
|
1227
1001
|
function Empty(props) {
|
|
1228
1002
|
const { className, ...restProps } = props;
|
|
1229
1003
|
return (jsx(InboxTwotone, { className: classNames("i-empty", className), ...restProps }));
|
|
@@ -3302,8 +3076,7 @@ class IFormInstance {
|
|
|
3302
3076
|
for (let i = 1; i < parts.length; i++) {
|
|
3303
3077
|
const ancestor = parts.slice(0, i).join(".");
|
|
3304
3078
|
if (ancestor in this.data) {
|
|
3305
|
-
console.warn(`[ioca-form] Field "${field}" conflicts with "${ancestor}". ` +
|
|
3306
|
-
"Nested representation in form.get() may be inconsistent.");
|
|
3079
|
+
console.warn(`[ioca-form] Field "${field}" conflicts with "${ancestor}". ` + "Nested representation in form.get() may be inconsistent.");
|
|
3307
3080
|
}
|
|
3308
3081
|
}
|
|
3309
3082
|
setDeep(this.data, field, value);
|
|
@@ -3355,7 +3128,7 @@ class IFormInstance {
|
|
|
3355
3128
|
if (!field && o === undefined)
|
|
3356
3129
|
return;
|
|
3357
3130
|
const rule = {
|
|
3358
|
-
validator: (v) => Array.isArray(v) ? v.length > 0 : ![undefined, null, ""].includes(v),
|
|
3131
|
+
validator: (v) => (Array.isArray(v) ? v.length > 0 : ![undefined, null, ""].includes(v)),
|
|
3359
3132
|
};
|
|
3360
3133
|
if (typeof o === "function")
|
|
3361
3134
|
rule.validator = o;
|
|
@@ -3380,7 +3153,7 @@ class IFormInstance {
|
|
|
3380
3153
|
});
|
|
3381
3154
|
}
|
|
3382
3155
|
});
|
|
3383
|
-
return
|
|
3156
|
+
return isAllValid ? data : false;
|
|
3384
3157
|
}
|
|
3385
3158
|
}
|
|
3386
3159
|
function useForm(form) {
|
|
@@ -3647,25 +3420,33 @@ function Modal(props) {
|
|
|
3647
3420
|
if (!toggable.current)
|
|
3648
3421
|
return;
|
|
3649
3422
|
toggable.current = false;
|
|
3650
|
-
|
|
3651
|
-
|
|
3423
|
+
const canClose = typeof closable === 'function' ? closable() : closable;
|
|
3424
|
+
const exec = (result) => {
|
|
3425
|
+
if (!result) {
|
|
3426
|
+
setBounced(true);
|
|
3427
|
+
const timer = setTimeout(() => {
|
|
3428
|
+
setBounced(false);
|
|
3429
|
+
toggable.current = true;
|
|
3430
|
+
}, 400);
|
|
3431
|
+
return () => clearTimeout(timer);
|
|
3432
|
+
}
|
|
3433
|
+
setActive(false);
|
|
3434
|
+
updateVisible(mid, false);
|
|
3652
3435
|
const timer = setTimeout(() => {
|
|
3653
|
-
|
|
3436
|
+
if (!keepDOM)
|
|
3437
|
+
setShow(false);
|
|
3654
3438
|
toggable.current = true;
|
|
3655
|
-
|
|
3439
|
+
onVisibleChange?.(false);
|
|
3440
|
+
onClose?.();
|
|
3441
|
+
}, 240);
|
|
3656
3442
|
return () => clearTimeout(timer);
|
|
3443
|
+
};
|
|
3444
|
+
if (canClose instanceof Promise) {
|
|
3445
|
+
canClose.then(exec);
|
|
3446
|
+
return;
|
|
3657
3447
|
}
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
const timer = setTimeout(() => {
|
|
3661
|
-
if (!keepDOM)
|
|
3662
|
-
setShow(false);
|
|
3663
|
-
toggable.current = true;
|
|
3664
|
-
onVisibleChange?.(false);
|
|
3665
|
-
onClose?.();
|
|
3666
|
-
}, 240);
|
|
3667
|
-
return () => clearTimeout(timer);
|
|
3668
|
-
}, [closable, keepDOM, onClose, onVisibleChange]);
|
|
3448
|
+
return exec(canClose);
|
|
3449
|
+
}, [closable, keepDOM, mid, onClose, onVisibleChange]);
|
|
3669
3450
|
const handleBackdropClick = () => {
|
|
3670
3451
|
backdropClosable && handleHide();
|
|
3671
3452
|
};
|
|
@@ -3725,7 +3506,7 @@ function Modal(props) {
|
|
|
3725
3506
|
e.stopPropagation();
|
|
3726
3507
|
handleClick();
|
|
3727
3508
|
onClick?.(e);
|
|
3728
|
-
}, role: "dialog", "aria-modal": top, "data-mid": mid, ...restProps, children: jsxs(ModalContext.Provider, { value: true, children: [customized && children, !customized &&
|
|
3509
|
+
}, role: "dialog", "aria-modal": top, "data-mid": mid, ...restProps, children: jsxs(ModalContext.Provider, { value: true, children: [customized && children, !customized && jsx(Content$2, { title: title, hideCloseButton: hideCloseButton, footer: footer, okButtonProps: okButtonProps, cancelButtonProps: cancelButtonProps, children: children, footerLeft: footerLeft, onOk: onOk, onClose: handleHide })] }) }) }), getContainer());
|
|
3729
3510
|
}
|
|
3730
3511
|
Modal.useModal = useModal;
|
|
3731
3512
|
|
|
@@ -3739,7 +3520,17 @@ const HookModal = (props) => {
|
|
|
3739
3520
|
},
|
|
3740
3521
|
close: () => {
|
|
3741
3522
|
state.visible = false;
|
|
3742
|
-
|
|
3523
|
+
const canClose = typeof mergedProps.closable === 'function'
|
|
3524
|
+
? mergedProps.closable()
|
|
3525
|
+
: (mergedProps.closable ?? true);
|
|
3526
|
+
if (canClose instanceof Promise) {
|
|
3527
|
+
canClose.then((result) => {
|
|
3528
|
+
if (!result)
|
|
3529
|
+
state.visible = true;
|
|
3530
|
+
});
|
|
3531
|
+
return;
|
|
3532
|
+
}
|
|
3533
|
+
if (canClose)
|
|
3743
3534
|
return;
|
|
3744
3535
|
Promise.resolve().then(() => {
|
|
3745
3536
|
state.visible = true;
|
|
@@ -4385,7 +4176,7 @@ function InputContainer(props) {
|
|
|
4385
4176
|
}
|
|
4386
4177
|
|
|
4387
4178
|
const Number$1 = (props) => {
|
|
4388
|
-
const { ref, label, name, value = "", labelInline, step = 1, min = -Infinity, max = Infinity, thousand, precision, type, className, width, status = "normal", append, border, underline, prepend, disabled, message, tip, hideControl, showMax, style, onChange, onEnter, onInput, onBlur, ...restProps } = props;
|
|
4179
|
+
const { ref, label, name, value = "", labelInline, step = 1, min = -Infinity, max = Infinity, thousand, precision, type, className, width, status = "normal", append, border = true, underline, prepend, disabled, message, tip, hideControl, showMax, style, onChange, onEnter, onInput, onBlur, ...restProps } = props;
|
|
4389
4180
|
const [inputValue, setInputValue] = useState(value === undefined || value === null ? "" : String(value));
|
|
4390
4181
|
const formatOut = (num) => {
|
|
4391
4182
|
const v = clamp(num, min, max);
|
|
@@ -4398,9 +4189,7 @@ const Number$1 = (props) => {
|
|
|
4398
4189
|
const body = negative ? s.slice(1) : s;
|
|
4399
4190
|
const [integer, decimal] = body.split(".");
|
|
4400
4191
|
const withThousand = integer.replace(/\B(?=(\d{3})+(?!\d))/g, thousand);
|
|
4401
|
-
return decimal
|
|
4402
|
-
? `${negative ? "-" : ""}${withThousand}.${decimal}`
|
|
4403
|
-
: `${negative ? "-" : ""}${withThousand}`;
|
|
4192
|
+
return decimal ? `${negative ? "-" : ""}${withThousand}.${decimal}` : `${negative ? "-" : ""}${withThousand}`;
|
|
4404
4193
|
};
|
|
4405
4194
|
const sanitizeNumberInput = (raw) => {
|
|
4406
4195
|
const hasMinus = raw.startsWith("-");
|
|
@@ -4481,11 +4270,11 @@ const Number$1 = (props) => {
|
|
|
4481
4270
|
[`i-input-${status}`]: status !== "normal",
|
|
4482
4271
|
"i-input-borderless": !border,
|
|
4483
4272
|
"i-input-underline": underline,
|
|
4484
|
-
}), children: [prepend && jsx("div", { className:
|
|
4273
|
+
}), children: [prepend && jsx("div", { className: "i-input-prepend", children: prepend }), !hideControl && !disabled && jsx(Helpericon, { active: true, icon: jsx(MinusRound, {}), onClick: () => handleOperate(-step) }), jsx("input", { ...inputProps }), !hideControl && !disabled && jsx(Helpericon, { active: true, icon: jsx(PlusRound, {}), onClick: () => handleOperate(step) }), showMax && max && !disabled && jsx(Helpericon, { active: true, icon: jsx(KeyboardDoubleArrowUpRound, {}), onClick: handleMax }), append && jsx("div", { className: "i-input-append", children: append })] }) }));
|
|
4485
4274
|
};
|
|
4486
4275
|
|
|
4487
4276
|
const Range = (props) => {
|
|
4488
|
-
const { label, name, value, labelInline, min = -Infinity, max = Infinity, type, className, status = "normal", message, tip, append, prepend, step = 1, width, thousand, precision, hideControl, placeholder, border, underline, autoSwitch, onChange, onBlur, style, ...restProps } = props;
|
|
4277
|
+
const { label, name, value, labelInline, min = -Infinity, max = Infinity, type, className, status = "normal", message, tip, append, prepend, step = 1, width, thousand, precision, hideControl, placeholder, border = true, underline, autoSwitch, onChange, onBlur, style, ...restProps } = props;
|
|
4489
4278
|
const [rangeValue, setRangeValue] = useState(value);
|
|
4490
4279
|
const getRangeNumber = (v) => clamp(v, min, max);
|
|
4491
4280
|
const getFormatNumber = (v) => formatNumber(v, { precision, thousand });
|
|
@@ -4545,11 +4334,11 @@ const Range = (props) => {
|
|
|
4545
4334
|
[`i-input-${status}`]: status !== "normal",
|
|
4546
4335
|
"i-input-borderless": !border,
|
|
4547
4336
|
"i-input-underline": underline,
|
|
4548
|
-
}), children: [prepend && jsx("div", { className:
|
|
4337
|
+
}), children: [prepend && jsx("div", { className: "i-input-prepend", children: prepend }), !hideControl && jsx(Helpericon, { active: true, icon: jsx(MinusRound, {}), onClick: (e) => handleOperate(e, -step, 0) }), jsx("input", { value: rangeValue?.[0] || "", placeholder: placeholder?.[0], ...inputProps, onBlur: handleBlur, onChange: (e) => handleChange(e, 0) }), !hideControl && jsx(Helpericon, { active: true, icon: jsx(PlusRound, {}), onClick: (e) => handleOperate(e, step, 0) }), jsx(Helpericon, { active: true, icon: jsx(SyncAltRound, {}), style: { margin: 0 }, onClick: handleSwitch }), !hideControl && jsx(Helpericon, { active: true, icon: jsx(MinusRound, {}), onClick: (e) => handleOperate(e, -step, 1) }), jsx("input", { value: rangeValue?.[1] || "", placeholder: placeholder?.[1], ...inputProps, onBlur: handleBlur, onChange: (e) => handleChange(e, 1) }), !hideControl && jsx(Helpericon, { active: true, icon: jsx(PlusRound, {}), onClick: (e) => handleOperate(e, step, 1) }), append && jsx("div", { className: "i-input-append", children: append })] }) }));
|
|
4549
4338
|
};
|
|
4550
4339
|
|
|
4551
4340
|
const Textarea = (props) => {
|
|
4552
|
-
const { ref, label, name, value = "", labelInline, className, status = "normal", message, tip, autoSize, border, width, style, resize, onChange, onEnter, ...restProps } = props;
|
|
4341
|
+
const { ref, label, name, value = "", labelInline, className, status = "normal", message, tip, autoSize, border = true, width, style, resize, onChange, onEnter, ...restProps } = props;
|
|
4553
4342
|
const [textareaValue, setTextareaValue] = useState(value);
|
|
4554
4343
|
const refTextarea = useRef(null);
|
|
4555
4344
|
const syncTextareaHeight = () => {
|
|
@@ -4598,7 +4387,7 @@ const Textarea = (props) => {
|
|
|
4598
4387
|
};
|
|
4599
4388
|
|
|
4600
4389
|
const Input = ((props) => {
|
|
4601
|
-
const { ref, type = "text", label, name, value = "", prepend, append, labelInline, className, status = "normal", message, tip, clear, width, hideVisible, border, underline, required, maxLength, onChange, onEnter, onClear, style, ...restProps } = props;
|
|
4390
|
+
const { ref, type = "text", label, name, value = "", prepend, append, labelInline, className, status = "normal", message, tip, clear, width, hideVisible, border = true, underline, required, maxLength, onChange, onEnter, onClear, style, ...restProps } = props;
|
|
4602
4391
|
const [inputValue, setInputValue] = useState(value);
|
|
4603
4392
|
const [inputType, setInputType] = useState(type);
|
|
4604
4393
|
const [visible, setVisible] = useState(false);
|
|
@@ -4656,7 +4445,7 @@ const Input = ((props) => {
|
|
|
4656
4445
|
[`i-input-${status}`]: status !== "normal",
|
|
4657
4446
|
"i-input-borderless": !border,
|
|
4658
4447
|
"i-input-underline": underline,
|
|
4659
|
-
}), children: [prepend && jsx("div", { className:
|
|
4448
|
+
}), children: [prepend && jsx("div", { className: "i-input-prepend", children: prepend }), jsx("input", { ...inputProps }), maxLength && inputValue?.length > 0 && (jsxs("span", { className: "color-8 pr-4 font-sm", children: [inputValue.length, " / ", maxLength] })), jsx(Helpericon, { active: !!clearable || showHelper, icon: HelperIcon, className: classNames({ "i-helpericon-clear": isClearBtn }), onClick: handleHelperClick }), append && jsx("div", { className: "i-input-append", children: append })] }) }));
|
|
4660
4449
|
});
|
|
4661
4450
|
Input.Textarea = Textarea;
|
|
4662
4451
|
Input.Number = Number$1;
|
|
@@ -4938,20 +4727,28 @@ const Pagination = (props) => {
|
|
|
4938
4727
|
}), end < totalPage - 1 && renderEllipsis(), end < totalPage && (jsx(Page, { page: totalPage, onChange: handlePageChange, children: renderPage(totalPage) })), next && (jsx(Page, { page: page + 1, disabled: page === totalPage, onChange: handlePageChange, children: next }))] }));
|
|
4939
4728
|
};
|
|
4940
4729
|
|
|
4730
|
+
const Tag = (props) => {
|
|
4731
|
+
const { dot, dotClass, outline, round, size = "normal", className, children, onClose, onClick, ...restProps } = props;
|
|
4732
|
+
return (jsxs("span", { className: classNames("i-tag", {
|
|
4733
|
+
"i-tag-outline": outline,
|
|
4734
|
+
"i-tag-clickable": onClick,
|
|
4735
|
+
[`i-tag-${size}`]: size !== "normal",
|
|
4736
|
+
round,
|
|
4737
|
+
}, className), onClick: onClick, ...restProps, children: [dot && jsx("span", { className: classNames("i-tag-dot", dotClass) }), children, onClose && (jsx(Helpericon, { active: true, className: "i-tag-close i-tag-hover-close", onClick: onClose }))] }));
|
|
4738
|
+
};
|
|
4739
|
+
|
|
4941
4740
|
const Options = (props) => {
|
|
4942
|
-
const { value: val, options, filter, filterPlaceholder, multiple, empty = jsx(Empty, {}), onSelect, onFilter
|
|
4741
|
+
const { value: val, options, filter, filterPlaceholder, multiple, empty = jsx(Empty, {}), onSelect, onFilter } = props;
|
|
4943
4742
|
return (jsxs("div", { className: classNames("i-select-options", {
|
|
4944
4743
|
"i-select-options-multiple": multiple,
|
|
4945
|
-
}), children: [filter && multiple && (jsxs("div", { className:
|
|
4744
|
+
}), children: [filter && multiple && (jsxs("div", { className: "i-select-filter", children: [jsx(Icon, { icon: jsx(SearchRound, {}), className: "color-8 ml-8 my-auto", size: "1.2em" }), jsx("input", { type: "text", className: "i-input", placeholder: filterPlaceholder, onChange: onFilter })] })), options.length === 0 && empty, options.map((option, i) => {
|
|
4946
4745
|
const { label, value, disabled } = option;
|
|
4947
|
-
const isActive = multiple
|
|
4948
|
-
|
|
4949
|
-
: val === value;
|
|
4950
|
-
return (jsxs(List$1.Item, { active: isActive, type: 'option', onClick: () => onSelect?.(value, option), disabled: disabled, children: [multiple && (jsx(Icon, { icon: jsx(CheckRound, {}), className: 'i-select-option-check', size: '1em' })), label] }, value || i));
|
|
4746
|
+
const isActive = multiple ? val?.includes(value) : val === value;
|
|
4747
|
+
return (jsxs(List$1.Item, { active: isActive, type: "option", onClick: () => onSelect?.(value, option), disabled: disabled, children: [multiple && jsx(Icon, { icon: jsx(CheckRound, {}), className: "i-select-option-check", size: "1em" }), label] }, value || i));
|
|
4951
4748
|
})] }));
|
|
4952
4749
|
};
|
|
4953
4750
|
const activeOptions = (options = [], value = [], max = 3) => {
|
|
4954
|
-
const total = options.flatMap((opt) => value.includes(opt.value) ? [opt] : []);
|
|
4751
|
+
const total = options.flatMap((opt) => (value.includes(opt.value) ? [opt] : []));
|
|
4955
4752
|
if (max >= total.length)
|
|
4956
4753
|
return total;
|
|
4957
4754
|
const rest = total.length - max;
|
|
@@ -4976,7 +4773,7 @@ const displayValue = (config) => {
|
|
|
4976
4773
|
};
|
|
4977
4774
|
|
|
4978
4775
|
const Select = (props) => {
|
|
4979
|
-
const { ref, type = "text", name, label, value = "", placeholder, required, options = [], multiple, prepend, append, labelInline, style, className, message, status = "normal", hideClear, hideArrow, maxDisplay, border, filter, tip, filterPlaceholder = "...", popupProps, onSelect, onChange, ...restProps } = props;
|
|
4776
|
+
const { ref, type = "text", name, label, value = "", placeholder, required, options = [], multiple, prepend, append, labelInline, style, className, message, status = "normal", hideClear, hideArrow, maxDisplay, border = true, filter, tip, filterPlaceholder = "...", popupProps, onSelect, onChange, ...restProps } = props;
|
|
4980
4777
|
const [filterValue, setFilterValue] = useState("");
|
|
4981
4778
|
const [selectedValue, setSelectedValue] = useState(value);
|
|
4982
4779
|
const [active, setActive] = useState(false);
|
|
@@ -4991,9 +4788,7 @@ const Select = (props) => {
|
|
|
4991
4788
|
if (!fv || !filter)
|
|
4992
4789
|
return formattedOptions;
|
|
4993
4790
|
const lowerFv = fv.toLowerCase();
|
|
4994
|
-
const filterFn = typeof filter === "function"
|
|
4995
|
-
? filter
|
|
4996
|
-
: (opt) => opt._value.includes(lowerFv) || opt._label.includes(lowerFv);
|
|
4791
|
+
const filterFn = typeof filter === "function" ? filter : (opt) => opt._value.includes(lowerFv) || opt._label.includes(lowerFv);
|
|
4997
4792
|
return formattedOptions.filter(filterFn);
|
|
4998
4793
|
}, [formattedOptions, filter, filterValue]);
|
|
4999
4794
|
const changeValue = (v) => {
|
|
@@ -5042,9 +4837,7 @@ const Select = (props) => {
|
|
|
5042
4837
|
useEffect(() => {
|
|
5043
4838
|
setSelectedValue(value);
|
|
5044
4839
|
}, [value]);
|
|
5045
|
-
const hasValue = multiple
|
|
5046
|
-
? selectedValue.length > 0
|
|
5047
|
-
: !!selectedValue;
|
|
4840
|
+
const hasValue = multiple ? selectedValue.length > 0 : !!selectedValue;
|
|
5048
4841
|
const clearable = !hideClear && active && hasValue;
|
|
5049
4842
|
const text = message ?? tip;
|
|
5050
4843
|
return (jsxs("label", { className: classNames("i-input-label", className, {
|
|
@@ -5061,7 +4854,7 @@ const Select = (props) => {
|
|
|
5061
4854
|
multiple,
|
|
5062
4855
|
maxDisplay,
|
|
5063
4856
|
onSelect: handleSelect,
|
|
5064
|
-
}) })) : (jsx("input", { className: "i-input i-select", placeholder: placeholder, readOnly: true }))) : null, !multiple &&
|
|
4857
|
+
}) })) : (jsx("input", { className: "i-input i-select", placeholder: placeholder, readOnly: true }))) : null, !multiple && jsx("input", { value: active ? filterValue : displayLabel, className: "i-input i-select", placeholder: displayLabel || placeholder, onChange: handleInputChange, readOnly: !filter }), jsx(Helpericon, { active: !hideArrow, icon: clearable ? undefined : jsx(UnfoldMoreRound, {}), onClick: handleHelperClick }), append] }) }), text && jsx("span", { className: "i-input-message", children: text })] }));
|
|
5065
4858
|
};
|
|
5066
4859
|
|
|
5067
4860
|
const ColorMethods = {
|
|
@@ -5531,6 +5324,214 @@ const DateRange = (props) => {
|
|
|
5531
5324
|
return (jsx(Popup, { visible: active, trigger: 'click', position: 'bottom', arrow: false, align: 'start', onVisibleChange: handleVisibleChange, content: jsx(DoublePanel, { value: dayJsValue, weeks: weeks, unitYear: unitYear, unitMonth: unitMonth, renderDate: renderDate, renderMonth: renderMonth, renderYear: renderYear, disabledDate: disabledDate, onSelected: handleSelected }), children: jsx(Input, { value: inputValue, placeholder: placeholder, readOnly: true, clear: clear, onClear: handleClear, append: jsx(Icon, { icon: jsx(CalendarMonthTwotone, {}), className: 'i-datepicker-icon', size: '1em' }), className: classNames("i-datepicker-label", className), ...restProps }) }));
|
|
5532
5325
|
};
|
|
5533
5326
|
|
|
5327
|
+
const CreateTag = memo(function CreateTag(props) {
|
|
5328
|
+
const { isEditing, isLoading, createTagProps, tagProps, onBlur, onKeyDown, onStartCreate } = props;
|
|
5329
|
+
if (isEditing) {
|
|
5330
|
+
return (jsx(Tag, { ...createTagProps, className: classNames("i-pill", tagProps?.className, "i-pill-editing"), contentEditable: true, suppressContentEditableWarning: true, onBlur: () => onBlur(-1), onKeyDown: (e) => onKeyDown(e, -1), children: isLoading && jsx(Loading, { size: ".86em", className: "ml-4" }) }, "pill-editing"));
|
|
5331
|
+
}
|
|
5332
|
+
return (jsx(Tag, { ...createTagProps, className: classNames("i-pill", tagProps?.className, "i-pill-create"), onClick: onStartCreate, children: jsx("b", { children: "\uFF0B" }) }, "pill-create"));
|
|
5333
|
+
});
|
|
5334
|
+
|
|
5335
|
+
const TagItem = memo(function TagItem(props) {
|
|
5336
|
+
const { item, index, isEditing, isLoading, tagProps, editable, readonly, renderItem, onClose, onClick, onBlur, onKeyDown } = props;
|
|
5337
|
+
const isClickable = !isEditing && editable && !readonly;
|
|
5338
|
+
if (renderItem) {
|
|
5339
|
+
return renderItem({
|
|
5340
|
+
value: item,
|
|
5341
|
+
index,
|
|
5342
|
+
editing: isEditing,
|
|
5343
|
+
loading: isLoading,
|
|
5344
|
+
readonly: !!readonly,
|
|
5345
|
+
remove: () => onClose(index),
|
|
5346
|
+
});
|
|
5347
|
+
}
|
|
5348
|
+
return (jsxs(Tag, { ...tagProps, className: classNames("i-pill", tagProps?.className, { "i-pill-editing": isEditing }), contentEditable: isEditing, suppressContentEditableWarning: true, onClose: !isEditing && !isLoading && !readonly ? () => onClose(index) : undefined, onClick: isClickable ? (e) => onClick(e, index) : undefined, onBlur: isEditing ? () => onBlur(index) : undefined, onKeyDown: isEditing ? (e) => onKeyDown(e, index) : undefined, children: [item, isLoading && jsx(Loading, { size: ".86em", className: "ml-4" })] }));
|
|
5349
|
+
});
|
|
5350
|
+
|
|
5351
|
+
function Pill(props) {
|
|
5352
|
+
const { value = [], tagProps, max, icon = jsx(AddRound, {}), className, label, labelInline, readonly, editable, onChange, onUpdate, validator, format, renderItem, hideCreate, ...restProps } = props;
|
|
5353
|
+
const [editingIndex, setEditingIndex] = useState(null);
|
|
5354
|
+
const [loadingSet, setLoadingSet] = useState(new Set());
|
|
5355
|
+
const instRef = useRef({
|
|
5356
|
+
props,
|
|
5357
|
+
editingIndex,
|
|
5358
|
+
loadingSet,
|
|
5359
|
+
setEditingIndex,
|
|
5360
|
+
setLoadingSet,
|
|
5361
|
+
});
|
|
5362
|
+
instRef.current.props = props;
|
|
5363
|
+
instRef.current.editingIndex = editingIndex;
|
|
5364
|
+
instRef.current.loadingSet = loadingSet;
|
|
5365
|
+
instRef.current.setEditingIndex = setEditingIndex;
|
|
5366
|
+
instRef.current.setLoadingSet = setLoadingSet;
|
|
5367
|
+
useEffect(() => {
|
|
5368
|
+
if (editingIndex !== null) {
|
|
5369
|
+
const el = document.querySelector(".i-pill-editing");
|
|
5370
|
+
el?.focus();
|
|
5371
|
+
}
|
|
5372
|
+
}, [editingIndex]);
|
|
5373
|
+
const cleanTagProps = useMemo(() => {
|
|
5374
|
+
if (!tagProps)
|
|
5375
|
+
return {};
|
|
5376
|
+
const { onClose, dot, dotClass, ...rest } = tagProps;
|
|
5377
|
+
return rest;
|
|
5378
|
+
}, [tagProps]);
|
|
5379
|
+
const handleClose = useCallback((index) => {
|
|
5380
|
+
const inst = instRef.current;
|
|
5381
|
+
if (inst.props.readonly)
|
|
5382
|
+
return;
|
|
5383
|
+
const hasAsync = !!inst.props.onUpdate;
|
|
5384
|
+
if (hasAsync)
|
|
5385
|
+
inst.setLoadingSet((prev) => new Set(prev).add(index));
|
|
5386
|
+
setTimeout(async () => {
|
|
5387
|
+
try {
|
|
5388
|
+
const { props } = instRef.current;
|
|
5389
|
+
const values = props.value ?? [];
|
|
5390
|
+
const item = values[index];
|
|
5391
|
+
if (item === undefined)
|
|
5392
|
+
return;
|
|
5393
|
+
const result = props.onUpdate?.(undefined, item, "delete");
|
|
5394
|
+
if (result instanceof Promise) {
|
|
5395
|
+
const ok = await result;
|
|
5396
|
+
if (ok === false)
|
|
5397
|
+
return;
|
|
5398
|
+
}
|
|
5399
|
+
const next = [...values];
|
|
5400
|
+
next.splice(index, 1);
|
|
5401
|
+
props.onChange?.(next);
|
|
5402
|
+
}
|
|
5403
|
+
finally {
|
|
5404
|
+
if (hasAsync) {
|
|
5405
|
+
instRef.current.setLoadingSet((prev) => {
|
|
5406
|
+
const s = new Set(prev);
|
|
5407
|
+
s.delete(index);
|
|
5408
|
+
return s;
|
|
5409
|
+
});
|
|
5410
|
+
}
|
|
5411
|
+
}
|
|
5412
|
+
}, 0);
|
|
5413
|
+
}, []);
|
|
5414
|
+
const handleItemClick = useCallback((e, index) => {
|
|
5415
|
+
if (e.target.closest(".i-helpericon"))
|
|
5416
|
+
return;
|
|
5417
|
+
const inst = instRef.current;
|
|
5418
|
+
if (inst.props.readonly)
|
|
5419
|
+
return;
|
|
5420
|
+
if (index === -1 && inst.props.max !== undefined && (inst.props.value?.length ?? 0) >= inst.props.max)
|
|
5421
|
+
return;
|
|
5422
|
+
inst.setEditingIndex(index);
|
|
5423
|
+
}, []);
|
|
5424
|
+
const commitEdit = useCallback((index, text) => {
|
|
5425
|
+
const inst = instRef.current;
|
|
5426
|
+
const formatted = inst.props.format ? inst.props.format(text) : text;
|
|
5427
|
+
const hasAsync = !!(inst.props.validator || inst.props.onUpdate);
|
|
5428
|
+
if (hasAsync)
|
|
5429
|
+
inst.setLoadingSet((prev) => new Set(prev).add(index));
|
|
5430
|
+
setTimeout(async () => {
|
|
5431
|
+
try {
|
|
5432
|
+
const { props } = instRef.current;
|
|
5433
|
+
if (props.validator) {
|
|
5434
|
+
const valid = await Promise.resolve(props.validator(formatted));
|
|
5435
|
+
if (!valid)
|
|
5436
|
+
return;
|
|
5437
|
+
}
|
|
5438
|
+
const values = props.value ?? [];
|
|
5439
|
+
if (index === -1) {
|
|
5440
|
+
if (values.includes(formatted))
|
|
5441
|
+
return;
|
|
5442
|
+
const result = props.onUpdate?.(formatted, undefined, "create");
|
|
5443
|
+
if (result instanceof Promise) {
|
|
5444
|
+
const ok = await result;
|
|
5445
|
+
if (ok === false)
|
|
5446
|
+
return;
|
|
5447
|
+
}
|
|
5448
|
+
props.onChange?.([...values, formatted]);
|
|
5449
|
+
}
|
|
5450
|
+
else {
|
|
5451
|
+
const oldValue = values[index];
|
|
5452
|
+
if (oldValue === formatted)
|
|
5453
|
+
return;
|
|
5454
|
+
const result = props.onUpdate?.(formatted, oldValue, "update");
|
|
5455
|
+
if (result instanceof Promise) {
|
|
5456
|
+
const ok = await result;
|
|
5457
|
+
if (ok === false)
|
|
5458
|
+
return;
|
|
5459
|
+
}
|
|
5460
|
+
const next = [...values];
|
|
5461
|
+
next[index] = formatted;
|
|
5462
|
+
props.onChange?.(next);
|
|
5463
|
+
}
|
|
5464
|
+
}
|
|
5465
|
+
finally {
|
|
5466
|
+
if (hasAsync) {
|
|
5467
|
+
instRef.current.setLoadingSet((prev) => {
|
|
5468
|
+
const s = new Set(prev);
|
|
5469
|
+
s.delete(index);
|
|
5470
|
+
return s;
|
|
5471
|
+
});
|
|
5472
|
+
}
|
|
5473
|
+
instRef.current.setEditingIndex(null);
|
|
5474
|
+
}
|
|
5475
|
+
}, 0);
|
|
5476
|
+
}, []);
|
|
5477
|
+
const handleBlur = useCallback((index) => {
|
|
5478
|
+
const inst = instRef.current;
|
|
5479
|
+
if (inst.loadingSet.has(index))
|
|
5480
|
+
return;
|
|
5481
|
+
const el = document.querySelector(".i-pill-editing");
|
|
5482
|
+
const text = el?.textContent?.trim();
|
|
5483
|
+
if (!text) {
|
|
5484
|
+
if (index !== -1) {
|
|
5485
|
+
handleClose(index);
|
|
5486
|
+
}
|
|
5487
|
+
else {
|
|
5488
|
+
inst.setEditingIndex(null);
|
|
5489
|
+
}
|
|
5490
|
+
return;
|
|
5491
|
+
}
|
|
5492
|
+
commitEdit(index, text);
|
|
5493
|
+
}, []);
|
|
5494
|
+
const handleKeyDown = useCallback((e, index) => {
|
|
5495
|
+
const inst = instRef.current;
|
|
5496
|
+
if (inst.loadingSet.has(index))
|
|
5497
|
+
return;
|
|
5498
|
+
if (e.key === "Enter") {
|
|
5499
|
+
e.preventDefault();
|
|
5500
|
+
const text = e.currentTarget.textContent?.trim();
|
|
5501
|
+
if (!text) {
|
|
5502
|
+
if (index !== -1) {
|
|
5503
|
+
handleClose(index);
|
|
5504
|
+
}
|
|
5505
|
+
else {
|
|
5506
|
+
inst.setEditingIndex(null);
|
|
5507
|
+
}
|
|
5508
|
+
return;
|
|
5509
|
+
}
|
|
5510
|
+
commitEdit(index, text);
|
|
5511
|
+
}
|
|
5512
|
+
else if (e.key === "Escape") {
|
|
5513
|
+
e.preventDefault();
|
|
5514
|
+
if (index !== -1) {
|
|
5515
|
+
const original = inst.props.value?.[index];
|
|
5516
|
+
if (original !== undefined) {
|
|
5517
|
+
e.currentTarget.textContent = original;
|
|
5518
|
+
}
|
|
5519
|
+
}
|
|
5520
|
+
inst.setEditingIndex(null);
|
|
5521
|
+
}
|
|
5522
|
+
}, []);
|
|
5523
|
+
const handleStartCreate = useCallback(() => {
|
|
5524
|
+
const inst = instRef.current;
|
|
5525
|
+
if (inst.props.readonly)
|
|
5526
|
+
return;
|
|
5527
|
+
if (inst.props.max !== undefined && (inst.props.value?.length ?? 0) >= inst.props.max)
|
|
5528
|
+
return;
|
|
5529
|
+
inst.setEditingIndex(-1);
|
|
5530
|
+
}, []);
|
|
5531
|
+
const canCreate = !hideCreate && !readonly && (max === undefined || value.length < max);
|
|
5532
|
+
return (jsxs("div", { className: classNames("i-pills i-input-label", { "i-input-inline": labelInline }, className), ...restProps, children: [label && jsx("span", { className: "i-input-label-text", children: label }), jsxs("div", { className: "i-pill-list", children: [value.map((item, i) => (jsx(TagItem, { item: item, index: i, isEditing: editingIndex === i, isLoading: loadingSet.has(i), tagProps: tagProps, editable: editable, readonly: readonly, renderItem: renderItem, onClose: handleClose, onClick: handleItemClick, onBlur: handleBlur, onKeyDown: handleKeyDown }, i))), canCreate && jsx(CreateTag, { isEditing: editingIndex === -1, isLoading: loadingSet.has(-1), createTagProps: cleanTagProps, tagProps: tagProps, onBlur: handleBlur, onKeyDown: handleKeyDown, onStartCreate: handleStartCreate })] })] }));
|
|
5533
|
+
}
|
|
5534
|
+
|
|
5534
5535
|
const defaultOk = {
|
|
5535
5536
|
children: "确定",
|
|
5536
5537
|
};
|
|
@@ -7182,4 +7183,4 @@ const useTheme = (props) => {
|
|
|
7182
7183
|
};
|
|
7183
7184
|
};
|
|
7184
7185
|
|
|
7185
|
-
export { Affix, Badge, Button,
|
|
7186
|
+
export { Affix, Badge, Button, Checkbox, Collapse, ColorPicker, Datagrid, Datepicker as DatePicker, DateRange, Description, Drawer, Dropdown, Editor, Flex, Form, Icon, MemoImage as Image, Input, List$1 as List, Loading, Message, Modal, Pagination, Pill, Popconfirm, Popup, Progress, Radio, Resizable, River, Scroll, Select, Step, Swiper, Tabs, Tag, Text, TimePicker, Tree, Upload, Video, usePreview, useTheme };
|