@ioca/react 1.5.29 → 1.5.31
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/divider/divider.js +12 -0
- package/lib/es/components/divider/index.js +5 -0
- package/lib/es/components/dropdown/dropdown.js +8 -12
- package/lib/es/components/dropdown/item.js +15 -9
- 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/list/item.js +5 -1
- package/lib/es/components/list/list.js +11 -4
- 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 +2 -2
- package/lib/index.js +319 -297
- package/lib/types/components/divider/divider.d.ts +6 -0
- package/lib/types/components/divider/index.d.ts +5 -0
- package/lib/types/components/divider/type.d.ts +9 -0
- package/lib/types/components/dropdown/type.d.ts +3 -1
- package/lib/types/components/form/useForm.d.ts +1 -1
- package/lib/types/components/list/type.d.ts +1 -0
- 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 +2 -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 }));
|
|
@@ -1951,20 +1725,31 @@ function Drawer(props) {
|
|
|
1951
1725
|
|
|
1952
1726
|
const Item$4 = (props) => {
|
|
1953
1727
|
const { ref, active, type, align, disabled, label, style, border, className, children, ...restProps } = props;
|
|
1728
|
+
const handlers = {};
|
|
1729
|
+
if (disabled) {
|
|
1730
|
+
handlers.onClick = (e) => { e.preventDefault(); e.stopPropagation(); };
|
|
1731
|
+
}
|
|
1954
1732
|
return (jsxs("li", { ref: ref, className: classNames("i-list-item", className, {
|
|
1955
1733
|
"i-list-item-active": active,
|
|
1956
1734
|
"i-list-option": type === "option",
|
|
1957
1735
|
"i-list-item-bordered": border,
|
|
1958
1736
|
disabled,
|
|
1959
|
-
}), style: { alignItems: align, ...style }, ...restProps, children: [label !== undefined && (jsx("span", { className: 'i-list-item-label', children: label })), children] }));
|
|
1737
|
+
}), style: { alignItems: align, ...style }, "aria-disabled": disabled || undefined, tabIndex: disabled ? -1 : undefined, ...restProps, ...handlers, children: [label !== undefined && (jsx("span", { className: 'i-list-item-label', children: label })), children] }));
|
|
1960
1738
|
};
|
|
1961
1739
|
|
|
1962
1740
|
const List$1 = forwardRef((props, ref) => {
|
|
1963
|
-
const { label, type, border, className, children, ...restProps } = props;
|
|
1964
|
-
return (jsx("ul", { ref: ref, className: classNames("i-list", className
|
|
1741
|
+
const { label, type, border, padding, className, style, children, ...restProps } = props;
|
|
1742
|
+
return (jsx("ul", { ref: ref, className: classNames("i-list", className, {
|
|
1743
|
+
"i-list-option-type": type === "option",
|
|
1744
|
+
}), style: {
|
|
1745
|
+
...(padding !== undefined
|
|
1746
|
+
? { "--option-gap": typeof padding === "number" ? `${padding}px` : padding }
|
|
1747
|
+
: undefined),
|
|
1748
|
+
...style,
|
|
1749
|
+
}, ...restProps, children: Children.map(children, (node, i) => {
|
|
1965
1750
|
const renderLabel = typeof label === "function" ? label(i) : label;
|
|
1966
|
-
const { type, props: nodeProps } = node;
|
|
1967
|
-
if (
|
|
1751
|
+
const { type: elementType, props: nodeProps } = node;
|
|
1752
|
+
if (elementType === Item$4) {
|
|
1968
1753
|
return cloneElement(node, {
|
|
1969
1754
|
label: renderLabel,
|
|
1970
1755
|
...nodeProps,
|
|
@@ -2514,50 +2299,52 @@ function Popup(props) {
|
|
|
2514
2299
|
|
|
2515
2300
|
const { Item: ListItem } = List$1;
|
|
2516
2301
|
const Item$3 = (props) => {
|
|
2517
|
-
const { more, moreProps, onClick, ref: itemRef, children, ...restProps } = props;
|
|
2518
|
-
const close = useContext(
|
|
2302
|
+
const { more, moreProps, onClick, ref: itemRef, type = "option", children, ...restProps } = props;
|
|
2303
|
+
const close = useContext(DropdownContext);
|
|
2519
2304
|
const liRef = useRef(null);
|
|
2520
2305
|
const [position, setPosition] = useState("right");
|
|
2521
2306
|
const { position: morePosition, onVisibleChange: moreOnVisibleChange, width: moreWidth, ...restMoreProps } = moreProps ?? {};
|
|
2522
2307
|
const effectivePosition = morePosition ?? position;
|
|
2308
|
+
const rafRef = useRef(0);
|
|
2523
2309
|
const handleVisibleChange = (v) => {
|
|
2524
2310
|
if (v && liRef.current) {
|
|
2525
|
-
|
|
2526
|
-
|
|
2311
|
+
cancelAnimationFrame(rafRef.current);
|
|
2312
|
+
rafRef.current = requestAnimationFrame(() => {
|
|
2313
|
+
if (!liRef.current)
|
|
2314
|
+
return;
|
|
2315
|
+
const rect = liRef.current.getBoundingClientRect();
|
|
2316
|
+
setPosition(rect.left > window.innerWidth / 2 ? "left" : "right");
|
|
2317
|
+
});
|
|
2527
2318
|
}
|
|
2528
2319
|
moreOnVisibleChange?.(v);
|
|
2529
2320
|
};
|
|
2530
|
-
const Li = (jsx(ListItem, { ref: itemRef ?? liRef, onClick: (e) => {
|
|
2321
|
+
const Li = useMemo(() => (jsx(ListItem, { ref: itemRef ?? liRef, role: "menuitem", "aria-haspopup": more ? "menu" : undefined, onClick: (e) => {
|
|
2531
2322
|
e.stopPropagation();
|
|
2532
2323
|
if (!more)
|
|
2533
2324
|
close?.();
|
|
2534
2325
|
onClick?.(e);
|
|
2535
|
-
}, ...restProps, children: children }));
|
|
2326
|
+
}, type: type, ...restProps, children: children })), [itemRef, liRef, more, close, onClick, type, restProps, children]);
|
|
2536
2327
|
if (!more)
|
|
2537
2328
|
return Li;
|
|
2538
|
-
return (jsx(Popup, { ...restMoreProps, position: effectivePosition, touchable: true, arrow: false, align: "start", offset:
|
|
2329
|
+
return (jsx(Popup, { ...restMoreProps, position: effectivePosition, touchable: true, arrow: false, align: "start", offset: 8, hideDelay: 240, onVisibleChange: handleVisibleChange, content: jsx(List$1, { type: "option", padding: 4, className: "i-dropdown-content", style: { minWidth: moreWidth }, onClick: (e) => e.stopPropagation(), children: more }), children: Li }));
|
|
2539
2330
|
};
|
|
2540
2331
|
|
|
2541
|
-
const
|
|
2332
|
+
const DropdownContext = createContext(null);
|
|
2542
2333
|
const Dropdown = (props) => {
|
|
2543
2334
|
const { visible, width, content, children, ...restProps } = props;
|
|
2544
2335
|
const [active, setActive] = useState(visible);
|
|
2545
2336
|
if (!content) {
|
|
2546
2337
|
return children;
|
|
2547
2338
|
}
|
|
2548
|
-
const close = () => setActive(false);
|
|
2549
|
-
const handleVisibleChange = (v) => {
|
|
2339
|
+
const close = useCallback(() => setActive(false), []);
|
|
2340
|
+
const handleVisibleChange = useCallback((v) => {
|
|
2550
2341
|
setActive(v);
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
}
|
|
2554
|
-
};
|
|
2342
|
+
props.onVisibleChange?.(v);
|
|
2343
|
+
}, [props.onVisibleChange]);
|
|
2555
2344
|
useEffect(() => {
|
|
2556
2345
|
setActive(visible);
|
|
2557
2346
|
}, [visible]);
|
|
2558
|
-
return (jsx(Popup, { trigger:
|
|
2559
|
-
? content(close)
|
|
2560
|
-
: content }) }), ...restProps, touchable: true, visible: active, onVisibleChange: handleVisibleChange, children: children }));
|
|
2347
|
+
return (jsx(Popup, { trigger: "click", position: "bottom", content: jsx(DropdownContext.Provider, { value: close, children: jsx(List$1, { type: "option", className: "i-dropdown-content", style: { minWidth: width }, role: "menu", children: typeof content === "function" ? content(close) : content }) }), ...restProps, touchable: true, visible: active, onVisibleChange: handleVisibleChange, children: children }));
|
|
2561
2348
|
};
|
|
2562
2349
|
Dropdown.Item = Item$3;
|
|
2563
2350
|
|
|
@@ -3302,8 +3089,7 @@ class IFormInstance {
|
|
|
3302
3089
|
for (let i = 1; i < parts.length; i++) {
|
|
3303
3090
|
const ancestor = parts.slice(0, i).join(".");
|
|
3304
3091
|
if (ancestor in this.data) {
|
|
3305
|
-
console.warn(`[ioca-form] Field "${field}" conflicts with "${ancestor}". ` +
|
|
3306
|
-
"Nested representation in form.get() may be inconsistent.");
|
|
3092
|
+
console.warn(`[ioca-form] Field "${field}" conflicts with "${ancestor}". ` + "Nested representation in form.get() may be inconsistent.");
|
|
3307
3093
|
}
|
|
3308
3094
|
}
|
|
3309
3095
|
setDeep(this.data, field, value);
|
|
@@ -3355,7 +3141,7 @@ class IFormInstance {
|
|
|
3355
3141
|
if (!field && o === undefined)
|
|
3356
3142
|
return;
|
|
3357
3143
|
const rule = {
|
|
3358
|
-
validator: (v) => Array.isArray(v) ? v.length > 0 : ![undefined, null, ""].includes(v),
|
|
3144
|
+
validator: (v) => (Array.isArray(v) ? v.length > 0 : ![undefined, null, ""].includes(v)),
|
|
3359
3145
|
};
|
|
3360
3146
|
if (typeof o === "function")
|
|
3361
3147
|
rule.validator = o;
|
|
@@ -3380,7 +3166,7 @@ class IFormInstance {
|
|
|
3380
3166
|
});
|
|
3381
3167
|
}
|
|
3382
3168
|
});
|
|
3383
|
-
return
|
|
3169
|
+
return isAllValid ? data : false;
|
|
3384
3170
|
}
|
|
3385
3171
|
}
|
|
3386
3172
|
function useForm(form) {
|
|
@@ -3647,25 +3433,33 @@ function Modal(props) {
|
|
|
3647
3433
|
if (!toggable.current)
|
|
3648
3434
|
return;
|
|
3649
3435
|
toggable.current = false;
|
|
3650
|
-
|
|
3651
|
-
|
|
3436
|
+
const canClose = typeof closable === 'function' ? closable() : closable;
|
|
3437
|
+
const exec = (result) => {
|
|
3438
|
+
if (!result) {
|
|
3439
|
+
setBounced(true);
|
|
3440
|
+
const timer = setTimeout(() => {
|
|
3441
|
+
setBounced(false);
|
|
3442
|
+
toggable.current = true;
|
|
3443
|
+
}, 400);
|
|
3444
|
+
return () => clearTimeout(timer);
|
|
3445
|
+
}
|
|
3446
|
+
setActive(false);
|
|
3447
|
+
updateVisible(mid, false);
|
|
3652
3448
|
const timer = setTimeout(() => {
|
|
3653
|
-
|
|
3449
|
+
if (!keepDOM)
|
|
3450
|
+
setShow(false);
|
|
3654
3451
|
toggable.current = true;
|
|
3655
|
-
|
|
3452
|
+
onVisibleChange?.(false);
|
|
3453
|
+
onClose?.();
|
|
3454
|
+
}, 240);
|
|
3656
3455
|
return () => clearTimeout(timer);
|
|
3456
|
+
};
|
|
3457
|
+
if (canClose instanceof Promise) {
|
|
3458
|
+
canClose.then(exec);
|
|
3459
|
+
return;
|
|
3657
3460
|
}
|
|
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]);
|
|
3461
|
+
return exec(canClose);
|
|
3462
|
+
}, [closable, keepDOM, mid, onClose, onVisibleChange]);
|
|
3669
3463
|
const handleBackdropClick = () => {
|
|
3670
3464
|
backdropClosable && handleHide();
|
|
3671
3465
|
};
|
|
@@ -3725,7 +3519,7 @@ function Modal(props) {
|
|
|
3725
3519
|
e.stopPropagation();
|
|
3726
3520
|
handleClick();
|
|
3727
3521
|
onClick?.(e);
|
|
3728
|
-
}, role: "dialog", "aria-modal": top, "data-mid": mid, ...restProps, children: jsxs(ModalContext.Provider, { value: true, children: [customized && children, !customized &&
|
|
3522
|
+
}, 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
3523
|
}
|
|
3730
3524
|
Modal.useModal = useModal;
|
|
3731
3525
|
|
|
@@ -3739,7 +3533,17 @@ const HookModal = (props) => {
|
|
|
3739
3533
|
},
|
|
3740
3534
|
close: () => {
|
|
3741
3535
|
state.visible = false;
|
|
3742
|
-
|
|
3536
|
+
const canClose = typeof mergedProps.closable === 'function'
|
|
3537
|
+
? mergedProps.closable()
|
|
3538
|
+
: (mergedProps.closable ?? true);
|
|
3539
|
+
if (canClose instanceof Promise) {
|
|
3540
|
+
canClose.then((result) => {
|
|
3541
|
+
if (!result)
|
|
3542
|
+
state.visible = true;
|
|
3543
|
+
});
|
|
3544
|
+
return;
|
|
3545
|
+
}
|
|
3546
|
+
if (canClose)
|
|
3743
3547
|
return;
|
|
3744
3548
|
Promise.resolve().then(() => {
|
|
3745
3549
|
state.visible = true;
|
|
@@ -4385,7 +4189,7 @@ function InputContainer(props) {
|
|
|
4385
4189
|
}
|
|
4386
4190
|
|
|
4387
4191
|
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;
|
|
4192
|
+
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
4193
|
const [inputValue, setInputValue] = useState(value === undefined || value === null ? "" : String(value));
|
|
4390
4194
|
const formatOut = (num) => {
|
|
4391
4195
|
const v = clamp(num, min, max);
|
|
@@ -4398,9 +4202,7 @@ const Number$1 = (props) => {
|
|
|
4398
4202
|
const body = negative ? s.slice(1) : s;
|
|
4399
4203
|
const [integer, decimal] = body.split(".");
|
|
4400
4204
|
const withThousand = integer.replace(/\B(?=(\d{3})+(?!\d))/g, thousand);
|
|
4401
|
-
return decimal
|
|
4402
|
-
? `${negative ? "-" : ""}${withThousand}.${decimal}`
|
|
4403
|
-
: `${negative ? "-" : ""}${withThousand}`;
|
|
4205
|
+
return decimal ? `${negative ? "-" : ""}${withThousand}.${decimal}` : `${negative ? "-" : ""}${withThousand}`;
|
|
4404
4206
|
};
|
|
4405
4207
|
const sanitizeNumberInput = (raw) => {
|
|
4406
4208
|
const hasMinus = raw.startsWith("-");
|
|
@@ -4481,11 +4283,11 @@ const Number$1 = (props) => {
|
|
|
4481
4283
|
[`i-input-${status}`]: status !== "normal",
|
|
4482
4284
|
"i-input-borderless": !border,
|
|
4483
4285
|
"i-input-underline": underline,
|
|
4484
|
-
}), children: [prepend && jsx("div", { className:
|
|
4286
|
+
}), 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
4287
|
};
|
|
4486
4288
|
|
|
4487
4289
|
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;
|
|
4290
|
+
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
4291
|
const [rangeValue, setRangeValue] = useState(value);
|
|
4490
4292
|
const getRangeNumber = (v) => clamp(v, min, max);
|
|
4491
4293
|
const getFormatNumber = (v) => formatNumber(v, { precision, thousand });
|
|
@@ -4545,11 +4347,11 @@ const Range = (props) => {
|
|
|
4545
4347
|
[`i-input-${status}`]: status !== "normal",
|
|
4546
4348
|
"i-input-borderless": !border,
|
|
4547
4349
|
"i-input-underline": underline,
|
|
4548
|
-
}), children: [prepend && jsx("div", { className:
|
|
4350
|
+
}), 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
4351
|
};
|
|
4550
4352
|
|
|
4551
4353
|
const Textarea = (props) => {
|
|
4552
|
-
const { ref, label, name, value = "", labelInline, className, status = "normal", message, tip, autoSize, border, width, style, resize, onChange, onEnter, ...restProps } = props;
|
|
4354
|
+
const { ref, label, name, value = "", labelInline, className, status = "normal", message, tip, autoSize, border = true, width, style, resize, onChange, onEnter, ...restProps } = props;
|
|
4553
4355
|
const [textareaValue, setTextareaValue] = useState(value);
|
|
4554
4356
|
const refTextarea = useRef(null);
|
|
4555
4357
|
const syncTextareaHeight = () => {
|
|
@@ -4598,7 +4400,7 @@ const Textarea = (props) => {
|
|
|
4598
4400
|
};
|
|
4599
4401
|
|
|
4600
4402
|
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;
|
|
4403
|
+
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
4404
|
const [inputValue, setInputValue] = useState(value);
|
|
4603
4405
|
const [inputType, setInputType] = useState(type);
|
|
4604
4406
|
const [visible, setVisible] = useState(false);
|
|
@@ -4656,12 +4458,20 @@ const Input = ((props) => {
|
|
|
4656
4458
|
[`i-input-${status}`]: status !== "normal",
|
|
4657
4459
|
"i-input-borderless": !border,
|
|
4658
4460
|
"i-input-underline": underline,
|
|
4659
|
-
}), children: [prepend && jsx("div", { className:
|
|
4461
|
+
}), 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
4462
|
});
|
|
4661
4463
|
Input.Textarea = Textarea;
|
|
4662
4464
|
Input.Number = Number$1;
|
|
4663
4465
|
Input.Range = Range;
|
|
4664
4466
|
|
|
4467
|
+
const Divider$1 = ({ className, children, color, width, style, ...restProps }) => {
|
|
4468
|
+
return (jsx("li", { role: "separator", className: classNames("i-divider", className), style: {
|
|
4469
|
+
...(color !== undefined ? { "--divider-color": color } : undefined),
|
|
4470
|
+
...(width !== undefined ? { "--divider-width": typeof width === "number" ? `${width}px` : width } : undefined),
|
|
4471
|
+
...style,
|
|
4472
|
+
}, ...restProps, children: children && jsx("div", { className: "i-divider-content", children: children }) }));
|
|
4473
|
+
};
|
|
4474
|
+
|
|
4665
4475
|
const AlignMap = {
|
|
4666
4476
|
left: "flex-start",
|
|
4667
4477
|
center: "center",
|
|
@@ -4938,20 +4748,28 @@ const Pagination = (props) => {
|
|
|
4938
4748
|
}), 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
4749
|
};
|
|
4940
4750
|
|
|
4751
|
+
const Tag = (props) => {
|
|
4752
|
+
const { dot, dotClass, outline, round, size = "normal", className, children, onClose, onClick, ...restProps } = props;
|
|
4753
|
+
return (jsxs("span", { className: classNames("i-tag", {
|
|
4754
|
+
"i-tag-outline": outline,
|
|
4755
|
+
"i-tag-clickable": onClick,
|
|
4756
|
+
[`i-tag-${size}`]: size !== "normal",
|
|
4757
|
+
round,
|
|
4758
|
+
}, 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 }))] }));
|
|
4759
|
+
};
|
|
4760
|
+
|
|
4941
4761
|
const Options = (props) => {
|
|
4942
|
-
const { value: val, options, filter, filterPlaceholder, multiple, empty = jsx(Empty, {}), onSelect, onFilter
|
|
4762
|
+
const { value: val, options, filter, filterPlaceholder, multiple, empty = jsx(Empty, {}), onSelect, onFilter } = props;
|
|
4943
4763
|
return (jsxs("div", { className: classNames("i-select-options", {
|
|
4944
4764
|
"i-select-options-multiple": multiple,
|
|
4945
|
-
}), children: [filter && multiple && (jsxs("div", { className:
|
|
4765
|
+
}), 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
4766
|
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));
|
|
4767
|
+
const isActive = multiple ? val?.includes(value) : val === value;
|
|
4768
|
+
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
4769
|
})] }));
|
|
4952
4770
|
};
|
|
4953
4771
|
const activeOptions = (options = [], value = [], max = 3) => {
|
|
4954
|
-
const total = options.flatMap((opt) => value.includes(opt.value) ? [opt] : []);
|
|
4772
|
+
const total = options.flatMap((opt) => (value.includes(opt.value) ? [opt] : []));
|
|
4955
4773
|
if (max >= total.length)
|
|
4956
4774
|
return total;
|
|
4957
4775
|
const rest = total.length - max;
|
|
@@ -4976,7 +4794,7 @@ const displayValue = (config) => {
|
|
|
4976
4794
|
};
|
|
4977
4795
|
|
|
4978
4796
|
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;
|
|
4797
|
+
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
4798
|
const [filterValue, setFilterValue] = useState("");
|
|
4981
4799
|
const [selectedValue, setSelectedValue] = useState(value);
|
|
4982
4800
|
const [active, setActive] = useState(false);
|
|
@@ -4991,9 +4809,7 @@ const Select = (props) => {
|
|
|
4991
4809
|
if (!fv || !filter)
|
|
4992
4810
|
return formattedOptions;
|
|
4993
4811
|
const lowerFv = fv.toLowerCase();
|
|
4994
|
-
const filterFn = typeof filter === "function"
|
|
4995
|
-
? filter
|
|
4996
|
-
: (opt) => opt._value.includes(lowerFv) || opt._label.includes(lowerFv);
|
|
4812
|
+
const filterFn = typeof filter === "function" ? filter : (opt) => opt._value.includes(lowerFv) || opt._label.includes(lowerFv);
|
|
4997
4813
|
return formattedOptions.filter(filterFn);
|
|
4998
4814
|
}, [formattedOptions, filter, filterValue]);
|
|
4999
4815
|
const changeValue = (v) => {
|
|
@@ -5042,9 +4858,7 @@ const Select = (props) => {
|
|
|
5042
4858
|
useEffect(() => {
|
|
5043
4859
|
setSelectedValue(value);
|
|
5044
4860
|
}, [value]);
|
|
5045
|
-
const hasValue = multiple
|
|
5046
|
-
? selectedValue.length > 0
|
|
5047
|
-
: !!selectedValue;
|
|
4861
|
+
const hasValue = multiple ? selectedValue.length > 0 : !!selectedValue;
|
|
5048
4862
|
const clearable = !hideClear && active && hasValue;
|
|
5049
4863
|
const text = message ?? tip;
|
|
5050
4864
|
return (jsxs("label", { className: classNames("i-input-label", className, {
|
|
@@ -5061,7 +4875,7 @@ const Select = (props) => {
|
|
|
5061
4875
|
multiple,
|
|
5062
4876
|
maxDisplay,
|
|
5063
4877
|
onSelect: handleSelect,
|
|
5064
|
-
}) })) : (jsx("input", { className: "i-input i-select", placeholder: placeholder, readOnly: true }))) : null, !multiple &&
|
|
4878
|
+
}) })) : (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
4879
|
};
|
|
5066
4880
|
|
|
5067
4881
|
const ColorMethods = {
|
|
@@ -5531,6 +5345,214 @@ const DateRange = (props) => {
|
|
|
5531
5345
|
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
5346
|
};
|
|
5533
5347
|
|
|
5348
|
+
const CreateTag = memo(function CreateTag(props) {
|
|
5349
|
+
const { isEditing, isLoading, createTagProps, tagProps, onBlur, onKeyDown, onStartCreate } = props;
|
|
5350
|
+
if (isEditing) {
|
|
5351
|
+
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"));
|
|
5352
|
+
}
|
|
5353
|
+
return (jsx(Tag, { ...createTagProps, className: classNames("i-pill", tagProps?.className, "i-pill-create"), onClick: onStartCreate, children: jsx("b", { children: "\uFF0B" }) }, "pill-create"));
|
|
5354
|
+
});
|
|
5355
|
+
|
|
5356
|
+
const TagItem = memo(function TagItem(props) {
|
|
5357
|
+
const { item, index, isEditing, isLoading, tagProps, editable, readonly, renderItem, onClose, onClick, onBlur, onKeyDown } = props;
|
|
5358
|
+
const isClickable = !isEditing && editable && !readonly;
|
|
5359
|
+
if (renderItem) {
|
|
5360
|
+
return renderItem({
|
|
5361
|
+
value: item,
|
|
5362
|
+
index,
|
|
5363
|
+
editing: isEditing,
|
|
5364
|
+
loading: isLoading,
|
|
5365
|
+
readonly: !!readonly,
|
|
5366
|
+
remove: () => onClose(index),
|
|
5367
|
+
});
|
|
5368
|
+
}
|
|
5369
|
+
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" })] }));
|
|
5370
|
+
});
|
|
5371
|
+
|
|
5372
|
+
function Pill(props) {
|
|
5373
|
+
const { value = [], tagProps, max, icon = jsx(AddRound, {}), className, label, labelInline, readonly, editable, onChange, onUpdate, validator, format, renderItem, hideCreate, ...restProps } = props;
|
|
5374
|
+
const [editingIndex, setEditingIndex] = useState(null);
|
|
5375
|
+
const [loadingSet, setLoadingSet] = useState(new Set());
|
|
5376
|
+
const instRef = useRef({
|
|
5377
|
+
props,
|
|
5378
|
+
editingIndex,
|
|
5379
|
+
loadingSet,
|
|
5380
|
+
setEditingIndex,
|
|
5381
|
+
setLoadingSet,
|
|
5382
|
+
});
|
|
5383
|
+
instRef.current.props = props;
|
|
5384
|
+
instRef.current.editingIndex = editingIndex;
|
|
5385
|
+
instRef.current.loadingSet = loadingSet;
|
|
5386
|
+
instRef.current.setEditingIndex = setEditingIndex;
|
|
5387
|
+
instRef.current.setLoadingSet = setLoadingSet;
|
|
5388
|
+
useEffect(() => {
|
|
5389
|
+
if (editingIndex !== null) {
|
|
5390
|
+
const el = document.querySelector(".i-pill-editing");
|
|
5391
|
+
el?.focus();
|
|
5392
|
+
}
|
|
5393
|
+
}, [editingIndex]);
|
|
5394
|
+
const cleanTagProps = useMemo(() => {
|
|
5395
|
+
if (!tagProps)
|
|
5396
|
+
return {};
|
|
5397
|
+
const { onClose, dot, dotClass, ...rest } = tagProps;
|
|
5398
|
+
return rest;
|
|
5399
|
+
}, [tagProps]);
|
|
5400
|
+
const handleClose = useCallback((index) => {
|
|
5401
|
+
const inst = instRef.current;
|
|
5402
|
+
if (inst.props.readonly)
|
|
5403
|
+
return;
|
|
5404
|
+
const hasAsync = !!inst.props.onUpdate;
|
|
5405
|
+
if (hasAsync)
|
|
5406
|
+
inst.setLoadingSet((prev) => new Set(prev).add(index));
|
|
5407
|
+
setTimeout(async () => {
|
|
5408
|
+
try {
|
|
5409
|
+
const { props } = instRef.current;
|
|
5410
|
+
const values = props.value ?? [];
|
|
5411
|
+
const item = values[index];
|
|
5412
|
+
if (item === undefined)
|
|
5413
|
+
return;
|
|
5414
|
+
const result = props.onUpdate?.(undefined, item, "delete");
|
|
5415
|
+
if (result instanceof Promise) {
|
|
5416
|
+
const ok = await result;
|
|
5417
|
+
if (ok === false)
|
|
5418
|
+
return;
|
|
5419
|
+
}
|
|
5420
|
+
const next = [...values];
|
|
5421
|
+
next.splice(index, 1);
|
|
5422
|
+
props.onChange?.(next);
|
|
5423
|
+
}
|
|
5424
|
+
finally {
|
|
5425
|
+
if (hasAsync) {
|
|
5426
|
+
instRef.current.setLoadingSet((prev) => {
|
|
5427
|
+
const s = new Set(prev);
|
|
5428
|
+
s.delete(index);
|
|
5429
|
+
return s;
|
|
5430
|
+
});
|
|
5431
|
+
}
|
|
5432
|
+
}
|
|
5433
|
+
}, 0);
|
|
5434
|
+
}, []);
|
|
5435
|
+
const handleItemClick = useCallback((e, index) => {
|
|
5436
|
+
if (e.target.closest(".i-helpericon"))
|
|
5437
|
+
return;
|
|
5438
|
+
const inst = instRef.current;
|
|
5439
|
+
if (inst.props.readonly)
|
|
5440
|
+
return;
|
|
5441
|
+
if (index === -1 && inst.props.max !== undefined && (inst.props.value?.length ?? 0) >= inst.props.max)
|
|
5442
|
+
return;
|
|
5443
|
+
inst.setEditingIndex(index);
|
|
5444
|
+
}, []);
|
|
5445
|
+
const commitEdit = useCallback((index, text) => {
|
|
5446
|
+
const inst = instRef.current;
|
|
5447
|
+
const formatted = inst.props.format ? inst.props.format(text) : text;
|
|
5448
|
+
const hasAsync = !!(inst.props.validator || inst.props.onUpdate);
|
|
5449
|
+
if (hasAsync)
|
|
5450
|
+
inst.setLoadingSet((prev) => new Set(prev).add(index));
|
|
5451
|
+
setTimeout(async () => {
|
|
5452
|
+
try {
|
|
5453
|
+
const { props } = instRef.current;
|
|
5454
|
+
if (props.validator) {
|
|
5455
|
+
const valid = await Promise.resolve(props.validator(formatted));
|
|
5456
|
+
if (!valid)
|
|
5457
|
+
return;
|
|
5458
|
+
}
|
|
5459
|
+
const values = props.value ?? [];
|
|
5460
|
+
if (index === -1) {
|
|
5461
|
+
if (values.includes(formatted))
|
|
5462
|
+
return;
|
|
5463
|
+
const result = props.onUpdate?.(formatted, undefined, "create");
|
|
5464
|
+
if (result instanceof Promise) {
|
|
5465
|
+
const ok = await result;
|
|
5466
|
+
if (ok === false)
|
|
5467
|
+
return;
|
|
5468
|
+
}
|
|
5469
|
+
props.onChange?.([...values, formatted]);
|
|
5470
|
+
}
|
|
5471
|
+
else {
|
|
5472
|
+
const oldValue = values[index];
|
|
5473
|
+
if (oldValue === formatted)
|
|
5474
|
+
return;
|
|
5475
|
+
const result = props.onUpdate?.(formatted, oldValue, "update");
|
|
5476
|
+
if (result instanceof Promise) {
|
|
5477
|
+
const ok = await result;
|
|
5478
|
+
if (ok === false)
|
|
5479
|
+
return;
|
|
5480
|
+
}
|
|
5481
|
+
const next = [...values];
|
|
5482
|
+
next[index] = formatted;
|
|
5483
|
+
props.onChange?.(next);
|
|
5484
|
+
}
|
|
5485
|
+
}
|
|
5486
|
+
finally {
|
|
5487
|
+
if (hasAsync) {
|
|
5488
|
+
instRef.current.setLoadingSet((prev) => {
|
|
5489
|
+
const s = new Set(prev);
|
|
5490
|
+
s.delete(index);
|
|
5491
|
+
return s;
|
|
5492
|
+
});
|
|
5493
|
+
}
|
|
5494
|
+
instRef.current.setEditingIndex(null);
|
|
5495
|
+
}
|
|
5496
|
+
}, 0);
|
|
5497
|
+
}, []);
|
|
5498
|
+
const handleBlur = useCallback((index) => {
|
|
5499
|
+
const inst = instRef.current;
|
|
5500
|
+
if (inst.loadingSet.has(index))
|
|
5501
|
+
return;
|
|
5502
|
+
const el = document.querySelector(".i-pill-editing");
|
|
5503
|
+
const text = el?.textContent?.trim();
|
|
5504
|
+
if (!text) {
|
|
5505
|
+
if (index !== -1) {
|
|
5506
|
+
handleClose(index);
|
|
5507
|
+
}
|
|
5508
|
+
else {
|
|
5509
|
+
inst.setEditingIndex(null);
|
|
5510
|
+
}
|
|
5511
|
+
return;
|
|
5512
|
+
}
|
|
5513
|
+
commitEdit(index, text);
|
|
5514
|
+
}, []);
|
|
5515
|
+
const handleKeyDown = useCallback((e, index) => {
|
|
5516
|
+
const inst = instRef.current;
|
|
5517
|
+
if (inst.loadingSet.has(index))
|
|
5518
|
+
return;
|
|
5519
|
+
if (e.key === "Enter") {
|
|
5520
|
+
e.preventDefault();
|
|
5521
|
+
const text = e.currentTarget.textContent?.trim();
|
|
5522
|
+
if (!text) {
|
|
5523
|
+
if (index !== -1) {
|
|
5524
|
+
handleClose(index);
|
|
5525
|
+
}
|
|
5526
|
+
else {
|
|
5527
|
+
inst.setEditingIndex(null);
|
|
5528
|
+
}
|
|
5529
|
+
return;
|
|
5530
|
+
}
|
|
5531
|
+
commitEdit(index, text);
|
|
5532
|
+
}
|
|
5533
|
+
else if (e.key === "Escape") {
|
|
5534
|
+
e.preventDefault();
|
|
5535
|
+
if (index !== -1) {
|
|
5536
|
+
const original = inst.props.value?.[index];
|
|
5537
|
+
if (original !== undefined) {
|
|
5538
|
+
e.currentTarget.textContent = original;
|
|
5539
|
+
}
|
|
5540
|
+
}
|
|
5541
|
+
inst.setEditingIndex(null);
|
|
5542
|
+
}
|
|
5543
|
+
}, []);
|
|
5544
|
+
const handleStartCreate = useCallback(() => {
|
|
5545
|
+
const inst = instRef.current;
|
|
5546
|
+
if (inst.props.readonly)
|
|
5547
|
+
return;
|
|
5548
|
+
if (inst.props.max !== undefined && (inst.props.value?.length ?? 0) >= inst.props.max)
|
|
5549
|
+
return;
|
|
5550
|
+
inst.setEditingIndex(-1);
|
|
5551
|
+
}, []);
|
|
5552
|
+
const canCreate = !hideCreate && !readonly && (max === undefined || value.length < max);
|
|
5553
|
+
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 })] })] }));
|
|
5554
|
+
}
|
|
5555
|
+
|
|
5534
5556
|
const defaultOk = {
|
|
5535
5557
|
children: "确定",
|
|
5536
5558
|
};
|
|
@@ -7182,4 +7204,4 @@ const useTheme = (props) => {
|
|
|
7182
7204
|
};
|
|
7183
7205
|
};
|
|
7184
7206
|
|
|
7185
|
-
export { Affix, Badge, Button,
|
|
7207
|
+
export { Affix, Badge, Button, Checkbox, Collapse, ColorPicker, Datagrid, Datepicker as DatePicker, DateRange, Description, Divider$1 as Divider, 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 };
|