sellmate-design-system-react 9.0.0-beta.44 → 9.0.0-beta.45
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/AGENTS.md +59 -0
- package/dist/components/SFooter/README.md +13 -8
- package/dist/components/SFooter/SFooter.d.ts +14 -9
- package/dist/components/SPopup/README.md +5 -6
- package/dist/components/SPopup/SPopup.d.ts +6 -7
- package/dist/components/SSelect/README.md +8 -0
- package/dist/components/SSelect/SSelect.d.ts +44 -0
- package/dist/components/SSelect/row-metrics.d.ts +60 -0
- package/dist/components/SSelect/select.config.d.ts +15 -0
- package/dist/components/STextarea/README.md +4 -1
- package/dist/components/STextarea/STextarea.d.ts +25 -2
- package/dist/index.cjs +409 -49
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +409 -49
- package/dist/index.js.map +1 -1
- package/dist/llms-full.txt +89 -15
- package/dist/llms.txt +59 -0
- package/dist/styles.css +3 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3689,14 +3689,14 @@ function SFooter({
|
|
|
3689
3689
|
]
|
|
3690
3690
|
}
|
|
3691
3691
|
),
|
|
3692
|
-
hasButton &&
|
|
3692
|
+
hasButton && // 스프레드를 먼저 두고 기본값을 뒤에 덮는다 — 순서를 뒤집으면 `{ color: undefined }`
|
|
3693
|
+
// 처럼 값 없이 넘어온 키가 footer 기본값을 지우고 SButton 기본값으로 떨어진다.
|
|
3694
|
+
/* @__PURE__ */ jsx(
|
|
3693
3695
|
SButton,
|
|
3694
3696
|
{
|
|
3697
|
+
...button,
|
|
3698
|
+
size: "md",
|
|
3695
3699
|
color: button.color ?? "primary",
|
|
3696
|
-
outline: button.outline,
|
|
3697
|
-
size: button.size ?? "md",
|
|
3698
|
-
disabled: button.disabled,
|
|
3699
|
-
onClick: () => button.onClick?.(),
|
|
3700
3700
|
label: button.label ?? "\uD655\uC778"
|
|
3701
3701
|
}
|
|
3702
3702
|
)
|
|
@@ -12724,6 +12724,130 @@ function collectGroupLeafValues(flat, groupIndex) {
|
|
|
12724
12724
|
}
|
|
12725
12725
|
var isHtmlLabel = (label) => /<[a-z][\s\S]*>/i.test(label);
|
|
12726
12726
|
var extractText = (html) => html.replace(/<[^>]*>/g, "");
|
|
12727
|
+
var OPTION_ROW_HEIGHT = 28;
|
|
12728
|
+
var DEFAULT_VIRTUAL_BUFFER = 10;
|
|
12729
|
+
var DEFAULT_REACH_END_THRESHOLD = 10;
|
|
12730
|
+
var DEFAULT_SEARCH_DEBOUNCE = 300;
|
|
12731
|
+
|
|
12732
|
+
// src/components/SSelect/row-metrics.ts
|
|
12733
|
+
function createRowMetrics(count, estimate) {
|
|
12734
|
+
const safeCount = Math.max(0, Math.floor(count));
|
|
12735
|
+
const safeEstimate = Math.max(1, estimate);
|
|
12736
|
+
const metrics = {
|
|
12737
|
+
sizes: new Array(safeCount).fill(safeEstimate),
|
|
12738
|
+
measured: new Array(safeCount).fill(false),
|
|
12739
|
+
offsets: [],
|
|
12740
|
+
estimate: safeEstimate,
|
|
12741
|
+
measuredCount: 0,
|
|
12742
|
+
measuredTotal: 0,
|
|
12743
|
+
dirtyFrom: 0
|
|
12744
|
+
};
|
|
12745
|
+
rebuildOffsets(metrics);
|
|
12746
|
+
return metrics;
|
|
12747
|
+
}
|
|
12748
|
+
function resizeRowMetrics(metrics, count) {
|
|
12749
|
+
const next = Math.max(0, Math.floor(count));
|
|
12750
|
+
const prev = metrics.sizes.length;
|
|
12751
|
+
if (next === prev) return;
|
|
12752
|
+
if (next < prev) {
|
|
12753
|
+
for (let i = next; i < prev; i++) {
|
|
12754
|
+
if (metrics.measured[i]) {
|
|
12755
|
+
metrics.measuredCount--;
|
|
12756
|
+
metrics.measuredTotal -= metrics.sizes[i];
|
|
12757
|
+
}
|
|
12758
|
+
}
|
|
12759
|
+
metrics.sizes.length = next;
|
|
12760
|
+
metrics.measured.length = next;
|
|
12761
|
+
} else {
|
|
12762
|
+
for (let i = prev; i < next; i++) {
|
|
12763
|
+
metrics.sizes.push(metrics.estimate);
|
|
12764
|
+
metrics.measured.push(false);
|
|
12765
|
+
}
|
|
12766
|
+
}
|
|
12767
|
+
markDirty(metrics, Math.min(prev, next));
|
|
12768
|
+
}
|
|
12769
|
+
function resetRowMetrics(metrics, count) {
|
|
12770
|
+
const fresh = createRowMetrics(count, metrics.estimate);
|
|
12771
|
+
metrics.sizes = fresh.sizes;
|
|
12772
|
+
metrics.measured = fresh.measured;
|
|
12773
|
+
metrics.offsets = fresh.offsets;
|
|
12774
|
+
metrics.measuredCount = 0;
|
|
12775
|
+
metrics.measuredTotal = 0;
|
|
12776
|
+
metrics.dirtyFrom = Infinity;
|
|
12777
|
+
}
|
|
12778
|
+
function setRowSize(metrics, index, size) {
|
|
12779
|
+
if (index < 0 || index >= metrics.sizes.length) return false;
|
|
12780
|
+
const next = Math.max(1, Math.round(size));
|
|
12781
|
+
const wasMeasured = metrics.measured[index];
|
|
12782
|
+
const prev = metrics.sizes[index];
|
|
12783
|
+
if (wasMeasured && prev === next) return false;
|
|
12784
|
+
if (wasMeasured) {
|
|
12785
|
+
metrics.measuredTotal += next - prev;
|
|
12786
|
+
} else {
|
|
12787
|
+
metrics.measured[index] = true;
|
|
12788
|
+
metrics.measuredCount++;
|
|
12789
|
+
metrics.measuredTotal += next;
|
|
12790
|
+
}
|
|
12791
|
+
metrics.sizes[index] = next;
|
|
12792
|
+
let changedFrom = prev === next ? Infinity : index;
|
|
12793
|
+
const average = Math.max(1, Math.round(metrics.measuredTotal / metrics.measuredCount));
|
|
12794
|
+
if (average !== metrics.estimate) {
|
|
12795
|
+
metrics.estimate = average;
|
|
12796
|
+
for (let i = 0; i < metrics.sizes.length; i++) {
|
|
12797
|
+
if (metrics.measured[i] || metrics.sizes[i] === average) continue;
|
|
12798
|
+
metrics.sizes[i] = average;
|
|
12799
|
+
if (i < changedFrom) changedFrom = i;
|
|
12800
|
+
}
|
|
12801
|
+
}
|
|
12802
|
+
if (changedFrom === Infinity) return false;
|
|
12803
|
+
markDirty(metrics, changedFrom);
|
|
12804
|
+
return true;
|
|
12805
|
+
}
|
|
12806
|
+
function markDirty(metrics, from) {
|
|
12807
|
+
metrics.dirtyFrom = Math.min(metrics.dirtyFrom, Math.max(0, from));
|
|
12808
|
+
}
|
|
12809
|
+
function rebuildOffsets(metrics) {
|
|
12810
|
+
const count = metrics.sizes.length;
|
|
12811
|
+
const stale = metrics.offsets.length !== count + 1;
|
|
12812
|
+
if (!stale && metrics.dirtyFrom === Infinity) return;
|
|
12813
|
+
const start = stale ? 0 : Math.min(metrics.dirtyFrom, count);
|
|
12814
|
+
const acc0 = start === 0 ? 0 : metrics.offsets[start] ?? 0;
|
|
12815
|
+
metrics.offsets.length = count + 1;
|
|
12816
|
+
let acc = acc0;
|
|
12817
|
+
for (let i = start; i < count; i++) {
|
|
12818
|
+
metrics.offsets[i] = acc;
|
|
12819
|
+
acc += metrics.sizes[i];
|
|
12820
|
+
}
|
|
12821
|
+
metrics.offsets[count] = acc;
|
|
12822
|
+
metrics.dirtyFrom = Infinity;
|
|
12823
|
+
}
|
|
12824
|
+
function totalSize(metrics) {
|
|
12825
|
+
rebuildOffsets(metrics);
|
|
12826
|
+
return metrics.offsets[metrics.sizes.length] ?? 0;
|
|
12827
|
+
}
|
|
12828
|
+
function offsetOf(metrics, index) {
|
|
12829
|
+
rebuildOffsets(metrics);
|
|
12830
|
+
const clamped = Math.max(0, Math.min(Math.floor(index), metrics.sizes.length));
|
|
12831
|
+
return metrics.offsets[clamped] ?? 0;
|
|
12832
|
+
}
|
|
12833
|
+
function sizeOf(metrics, index) {
|
|
12834
|
+
if (index < 0 || index >= metrics.sizes.length) return metrics.estimate;
|
|
12835
|
+
return metrics.sizes[index];
|
|
12836
|
+
}
|
|
12837
|
+
function indexAtOffset(metrics, y) {
|
|
12838
|
+
rebuildOffsets(metrics);
|
|
12839
|
+
const count = metrics.sizes.length;
|
|
12840
|
+
if (count === 0) return 0;
|
|
12841
|
+
const target = Math.max(0, y);
|
|
12842
|
+
let lo = 0;
|
|
12843
|
+
let hi = count - 1;
|
|
12844
|
+
while (lo < hi) {
|
|
12845
|
+
const mid = lo + hi + 1 >> 1;
|
|
12846
|
+
if (metrics.offsets[mid] <= target) lo = mid;
|
|
12847
|
+
else hi = mid - 1;
|
|
12848
|
+
}
|
|
12849
|
+
return lo;
|
|
12850
|
+
}
|
|
12727
12851
|
var SEARCH_THRESHOLD = 11;
|
|
12728
12852
|
var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
|
|
12729
12853
|
value,
|
|
@@ -12745,6 +12869,14 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
|
|
|
12745
12869
|
dropdownHeight = "640px",
|
|
12746
12870
|
dropdownWidth,
|
|
12747
12871
|
maxDropdownWidth = "640px",
|
|
12872
|
+
virtualBuffer = DEFAULT_VIRTUAL_BUFFER,
|
|
12873
|
+
onReachEnd,
|
|
12874
|
+
reachEndThreshold = DEFAULT_REACH_END_THRESHOLD,
|
|
12875
|
+
hasMore = false,
|
|
12876
|
+
loading: loading2 = false,
|
|
12877
|
+
serverSearch = false,
|
|
12878
|
+
onSearchChange,
|
|
12879
|
+
searchDebounce = DEFAULT_SEARCH_DEBOUNCE,
|
|
12748
12880
|
label,
|
|
12749
12881
|
labelWidth,
|
|
12750
12882
|
icon,
|
|
@@ -12759,6 +12891,9 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
|
|
|
12759
12891
|
style
|
|
12760
12892
|
}, ref) {
|
|
12761
12893
|
const multi = type === "multi" || type === "multi_depth";
|
|
12894
|
+
const isDepth = type === "default_depth" || type === "multi_depth";
|
|
12895
|
+
const pagingEnabled = onReachEnd != null;
|
|
12896
|
+
const partialOptions = pagingEnabled || serverSearch;
|
|
12762
12897
|
const portalContainer = usePortalContainer();
|
|
12763
12898
|
const insideModal = useInsideModal();
|
|
12764
12899
|
const [search, setSearch] = useState("");
|
|
@@ -12766,6 +12901,15 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
|
|
|
12766
12901
|
const [open, setOpen] = useState(false);
|
|
12767
12902
|
const [pendingOpen, setPendingOpen] = useState(false);
|
|
12768
12903
|
const [focusedIndex, setFocusedIndex] = useState(-1);
|
|
12904
|
+
const [win, setWin] = useState({ start: 0, end: 0, top: 0, bottom: 0 });
|
|
12905
|
+
const winRef = useRef(win);
|
|
12906
|
+
winRef.current = win;
|
|
12907
|
+
const metricsRef = useRef(null);
|
|
12908
|
+
metricsRef.current ?? (metricsRef.current = createRowMetrics(0, OPTION_ROW_HEIGHT));
|
|
12909
|
+
const [searchBarHeight, setSearchBarHeight] = useState(0);
|
|
12910
|
+
const [selectAllHeight, setSelectAllHeight] = useState(0);
|
|
12911
|
+
const measuredKeyRef = useRef("");
|
|
12912
|
+
const lastReachEndCountRef = useRef(-1);
|
|
12769
12913
|
const triggerRef = useRef(null);
|
|
12770
12914
|
const searchInputRef = useRef(null);
|
|
12771
12915
|
const searchBarRef = useRef(null);
|
|
@@ -12780,7 +12924,7 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
|
|
|
12780
12924
|
const hasLeaf = useMemo(() => flat.some((o) => !o.isGroup), [flat]);
|
|
12781
12925
|
const allOptionsDisabled = hasLeaf && selectable.length === 0;
|
|
12782
12926
|
const effectiveDisabled = disabled || allOptionsDisabled;
|
|
12783
|
-
const searchVisible = showSearch && selectable.length >= SEARCH_THRESHOLD;
|
|
12927
|
+
const searchVisible = showSearch && (partialOptions || selectable.length >= SEARCH_THRESHOLD);
|
|
12784
12928
|
const labelByValue = useMemo(() => new Map(flat.map((o) => [o.value, o.label])), [flat]);
|
|
12785
12929
|
const rawByValue = useMemo(() => new Map(flat.map((o) => [o.value, o.raw])), [flat]);
|
|
12786
12930
|
const optionByValue = useMemo(
|
|
@@ -12792,12 +12936,26 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
|
|
|
12792
12936
|
const arr = Array.isArray(value) ? value : [value];
|
|
12793
12937
|
return arr.map((v) => v != null && typeof v === "object" ? v.value : v).filter((v) => v != null && v !== "").map(String);
|
|
12794
12938
|
}, [value]);
|
|
12939
|
+
const valueOptions = useMemo(() => {
|
|
12940
|
+
const map = /* @__PURE__ */ new Map();
|
|
12941
|
+
if (value == null) return map;
|
|
12942
|
+
for (const v of Array.isArray(value) ? value : [value]) {
|
|
12943
|
+
if (v != null && typeof v === "object") {
|
|
12944
|
+
map.set(String(v.value), { value: v.value, label: v.label });
|
|
12945
|
+
}
|
|
12946
|
+
}
|
|
12947
|
+
return map;
|
|
12948
|
+
}, [value]);
|
|
12795
12949
|
const selectedRef = useRef(selected);
|
|
12796
12950
|
selectedRef.current = selected;
|
|
12951
|
+
const selectedSet = useMemo(() => new Set(selected), [selected]);
|
|
12952
|
+
const cbRef = useRef({ onReachEnd, onSearchChange });
|
|
12953
|
+
cbRef.current = { onReachEnd, onSearchChange };
|
|
12954
|
+
const emittedQueryRef = useRef("");
|
|
12797
12955
|
const emit3 = (next) => {
|
|
12798
12956
|
if (!onValueChange) return;
|
|
12799
12957
|
const mapped = next.map(
|
|
12800
|
-
(v) => valueAsPrimitive ? rawByValue.get(v) ?? v : optionByValue.get(v) ?? { value: v, label: v }
|
|
12958
|
+
(v) => valueAsPrimitive ? rawByValue.get(v) ?? valueOptions.get(v)?.value ?? v : optionByValue.get(v) ?? valueOptions.get(v) ?? { value: v, label: v }
|
|
12801
12959
|
);
|
|
12802
12960
|
onValueChange(multi ? mapped : mapped[0] ?? (valueAsPrimitive ? "" : null));
|
|
12803
12961
|
};
|
|
@@ -12846,14 +13004,15 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
|
|
|
12846
13004
|
resetValidation: () => setRuleError("")
|
|
12847
13005
|
});
|
|
12848
13006
|
const filtered = useMemo(() => {
|
|
12849
|
-
if (!searchVisible || search.trim() === "") return flat;
|
|
13007
|
+
if (serverSearch || !searchVisible || search.trim() === "") return flat;
|
|
12850
13008
|
const q = search.trim().toLowerCase();
|
|
12851
13009
|
return flat.filter(
|
|
12852
13010
|
(o) => o.isGroup || (isHtmlLabel(o.label) ? extractText(o.label) : o.label).toLowerCase().includes(q)
|
|
12853
13011
|
);
|
|
12854
|
-
}, [flat, search, searchVisible]);
|
|
13012
|
+
}, [flat, search, searchVisible, serverSearch]);
|
|
12855
13013
|
const allValues = selectable.map((o) => o.value);
|
|
12856
|
-
const allSelected = allValues.length > 0 && allValues.every((v) =>
|
|
13014
|
+
const allSelected = !partialOptions && allValues.length > 0 && allValues.every((v) => selectedSet.has(v));
|
|
13015
|
+
const selectAllVisible = multi && showSelectAll && !partialOptions && allValues.length > 0;
|
|
12857
13016
|
const hasItems = filtered.some((o) => !o.isGroup);
|
|
12858
13017
|
const groupLeafValues = useMemo(() => {
|
|
12859
13018
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -12864,7 +13023,7 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
|
|
|
12864
13023
|
}, [filtered]);
|
|
12865
13024
|
const navigableItems = useMemo(() => {
|
|
12866
13025
|
const items = [];
|
|
12867
|
-
if (
|
|
13026
|
+
if (selectAllVisible) {
|
|
12868
13027
|
items.push({ key: "__select_all__", isSelectAll: true });
|
|
12869
13028
|
}
|
|
12870
13029
|
filtered.forEach((o, i) => {
|
|
@@ -12879,20 +13038,129 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
|
|
|
12879
13038
|
}
|
|
12880
13039
|
});
|
|
12881
13040
|
return items;
|
|
12882
|
-
}, [
|
|
13041
|
+
}, [filtered, groupLeafValues, multi, selectAllVisible]);
|
|
12883
13042
|
const selectedAnchorIndex = useMemo(() => {
|
|
12884
|
-
if (
|
|
12885
|
-
const selectedSet = new Set(selected);
|
|
13043
|
+
if (selectedSet.size === 0) return -1;
|
|
12886
13044
|
return navigableItems.findIndex((item4) => item4.value != null && selectedSet.has(item4.value));
|
|
12887
|
-
}, [navigableItems,
|
|
13045
|
+
}, [navigableItems, selectedSet]);
|
|
12888
13046
|
selectedAnchorRef.current = selectedAnchorIndex;
|
|
13047
|
+
const navigableItemsRef = useRef(navigableItems);
|
|
13048
|
+
navigableItemsRef.current = navigableItems;
|
|
13049
|
+
const rowCount = filtered.length;
|
|
13050
|
+
const metrics = metricsRef.current;
|
|
13051
|
+
const lastSearchRef = useRef(search);
|
|
13052
|
+
if (lastSearchRef.current !== search) {
|
|
13053
|
+
lastSearchRef.current = search;
|
|
13054
|
+
resetRowMetrics(metrics, rowCount);
|
|
13055
|
+
measuredKeyRef.current = "";
|
|
13056
|
+
} else {
|
|
13057
|
+
resizeRowMetrics(metrics, rowCount);
|
|
13058
|
+
}
|
|
13059
|
+
const rowsOffset = searchBarHeight + selectAllHeight;
|
|
13060
|
+
const syncScrollState = useCallback(() => {
|
|
13061
|
+
if (!listEl) return;
|
|
13062
|
+
const m = metricsRef.current;
|
|
13063
|
+
if (m == null) return;
|
|
13064
|
+
const buffer = Math.max(0, Math.floor(virtualBuffer));
|
|
13065
|
+
const viewTop = Math.max(0, listEl.scrollTop - rowsOffset);
|
|
13066
|
+
const viewBottom = viewTop + Math.max(0, listEl.clientHeight);
|
|
13067
|
+
const start = Math.max(0, indexAtOffset(m, viewTop) - buffer);
|
|
13068
|
+
const end = Math.min(rowCount, indexAtOffset(m, viewBottom) + 1 + buffer);
|
|
13069
|
+
const top = offsetOf(m, start);
|
|
13070
|
+
const bottom = Math.max(0, totalSize(m) - offsetOf(m, end));
|
|
13071
|
+
setWin(
|
|
13072
|
+
(prev) => prev.start === start && prev.end === end && prev.top === top && prev.bottom === bottom ? prev : { start, end, top, bottom }
|
|
13073
|
+
);
|
|
13074
|
+
if (!pagingEnabled || !hasMore || loading2) return;
|
|
13075
|
+
const contentHeight = rowsOffset + totalSize(m);
|
|
13076
|
+
const remaining = contentHeight - listEl.scrollTop - listEl.clientHeight;
|
|
13077
|
+
if (remaining > Math.max(1, reachEndThreshold) * m.estimate) return;
|
|
13078
|
+
if (lastReachEndCountRef.current === rowCount) return;
|
|
13079
|
+
lastReachEndCountRef.current = rowCount;
|
|
13080
|
+
cbRef.current.onReachEnd?.();
|
|
13081
|
+
}, [
|
|
13082
|
+
hasMore,
|
|
13083
|
+
listEl,
|
|
13084
|
+
loading2,
|
|
13085
|
+
pagingEnabled,
|
|
13086
|
+
reachEndThreshold,
|
|
13087
|
+
rowCount,
|
|
13088
|
+
rowsOffset,
|
|
13089
|
+
virtualBuffer
|
|
13090
|
+
]);
|
|
13091
|
+
const syncScrollStateRef = useRef(syncScrollState);
|
|
13092
|
+
syncScrollStateRef.current = syncScrollState;
|
|
13093
|
+
useLayoutEffect(() => {
|
|
13094
|
+
if (!open) return;
|
|
13095
|
+
syncScrollState();
|
|
13096
|
+
}, [open, syncScrollState]);
|
|
13097
|
+
useLayoutEffect(() => {
|
|
13098
|
+
if (!open || !listEl) {
|
|
13099
|
+
setSearchBarHeight(0);
|
|
13100
|
+
setSelectAllHeight(0);
|
|
13101
|
+
return;
|
|
13102
|
+
}
|
|
13103
|
+
const nextBar = searchVisible ? searchBarRef.current?.offsetHeight ?? 0 : 0;
|
|
13104
|
+
setSearchBarHeight((prev) => prev === nextBar ? prev : nextBar);
|
|
13105
|
+
const nextSelectAll = selectAllVisible ? listEl.querySelector("[data-select-all-row]")?.offsetHeight ?? 0 : 0;
|
|
13106
|
+
setSelectAllHeight((prev) => prev === nextSelectAll ? prev : nextSelectAll);
|
|
13107
|
+
}, [listEl, open, searchVisible, selectAllVisible]);
|
|
13108
|
+
useLayoutEffect(() => {
|
|
13109
|
+
if (!open || !listEl) return;
|
|
13110
|
+
const m = metricsRef.current;
|
|
13111
|
+
if (m == null) return;
|
|
13112
|
+
const key = `${winRef.current.start}:${winRef.current.end}:${rowCount}`;
|
|
13113
|
+
if (measuredKeyRef.current === key) return;
|
|
13114
|
+
measuredKeyRef.current = key;
|
|
13115
|
+
const anchor = winRef.current.start;
|
|
13116
|
+
const anchorBefore = offsetOf(m, anchor);
|
|
13117
|
+
let changed = false;
|
|
13118
|
+
for (const row of listEl.querySelectorAll("[data-select-row]")) {
|
|
13119
|
+
const index = Number(row.dataset.index);
|
|
13120
|
+
if (!Number.isInteger(index)) continue;
|
|
13121
|
+
if (setRowSize(m, index, row.offsetHeight)) changed = true;
|
|
13122
|
+
}
|
|
13123
|
+
if (!changed) return;
|
|
13124
|
+
const delta = offsetOf(m, anchor) - anchorBefore;
|
|
13125
|
+
if (delta !== 0 && listEl.scrollTop > 0) listEl.scrollTop += delta;
|
|
13126
|
+
syncScrollStateRef.current();
|
|
13127
|
+
});
|
|
13128
|
+
useEffect(() => {
|
|
13129
|
+
if (cbRef.current.onSearchChange == null) return;
|
|
13130
|
+
if (search === emittedQueryRef.current) return;
|
|
13131
|
+
if (!serverSearch) {
|
|
13132
|
+
emittedQueryRef.current = search;
|
|
13133
|
+
cbRef.current.onSearchChange(search);
|
|
13134
|
+
return;
|
|
13135
|
+
}
|
|
13136
|
+
const timer = setTimeout(
|
|
13137
|
+
() => {
|
|
13138
|
+
emittedQueryRef.current = search;
|
|
13139
|
+
cbRef.current.onSearchChange?.(search);
|
|
13140
|
+
},
|
|
13141
|
+
Math.max(0, searchDebounce)
|
|
13142
|
+
);
|
|
13143
|
+
return () => clearTimeout(timer);
|
|
13144
|
+
}, [search, searchDebounce, serverSearch]);
|
|
13145
|
+
const selectAllMisuse = multi && showSelectAll && partialOptions;
|
|
13146
|
+
useEffect(() => {
|
|
13147
|
+
if (!isDev()) return;
|
|
13148
|
+
if (selectAllMisuse) {
|
|
13149
|
+
console.warn(
|
|
13150
|
+
'[SSelect] onReachEnd\xB7serverSearch \uC640 \uD568\uAED8 \uC900 showSelectAll \uC744 \uBB34\uC2DC\uD569\uB2C8\uB2E4. options \uAC00 \uBAA9\uB85D\uC758 \uC870\uAC01\uC77C \uBFD0\uC774\uB77C \uC544\uC9C1 \uBC1B\uC9C0 \uC54A\uC740 \uC635\uC158\uC740 \uACE0\uB97C \uC218 \uC5C6\uACE0, \uBC1B\uC544 \uC628 \uB9CC\uD07C\uB9CC \uACE0\uB978 \uC0C1\uD0DC\uB97C "\uC804\uCCB4"\uB77C\uACE0 \uD45C\uC2DC\uD558\uBA74 \uAC70\uC9D3\uC774 \uB429\uB2C8\uB2E4.'
|
|
13151
|
+
);
|
|
13152
|
+
}
|
|
13153
|
+
}, [selectAllMisuse]);
|
|
13154
|
+
const windowStart = Math.min(win.start, rowCount);
|
|
13155
|
+
const windowEnd = Math.max(windowStart, Math.min(win.end, rowCount));
|
|
13156
|
+
const visibleItems = filtered.slice(windowStart, windowEnd);
|
|
12889
13157
|
const triggerText = (() => {
|
|
12890
13158
|
if (selected.length === 0) return placeholder;
|
|
12891
13159
|
if (multi) {
|
|
12892
13160
|
if (allSelected) return allSelectedLabel;
|
|
12893
|
-
return selected.map((v) => labelByValue.get(v) ?? v).filter(Boolean).join(", ");
|
|
13161
|
+
return selected.map((v) => labelByValue.get(v) ?? valueOptions.get(v)?.label ?? v).filter(Boolean).join(", ");
|
|
12894
13162
|
}
|
|
12895
|
-
return labelByValue.get(selected[0]) ?? selected[0];
|
|
13163
|
+
return labelByValue.get(selected[0]) ?? valueOptions.get(selected[0])?.label ?? selected[0];
|
|
12896
13164
|
})();
|
|
12897
13165
|
const isPlaceholder = selected.length === 0;
|
|
12898
13166
|
const showClear = clearable && !effectiveDisabled && !isPlaceholder;
|
|
@@ -12905,7 +13173,6 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
|
|
|
12905
13173
|
const anchor = rangeAnchorRef.current;
|
|
12906
13174
|
if (extend && anchor != null && anchor !== index && filtered[anchor]?.isGroup === false) {
|
|
12907
13175
|
const [from, to] = anchor < index ? [anchor, index] : [index, anchor];
|
|
12908
|
-
const selectedSet = new Set(selected);
|
|
12909
13176
|
const shouldSelect = selectedSet.has(filtered[anchor].value);
|
|
12910
13177
|
const rangeValues = filtered.slice(from, to + 1).filter((o) => !o.isGroup && !o.disabled).map((o) => o.value);
|
|
12911
13178
|
const inRange = new Set(rangeValues);
|
|
@@ -12930,7 +13197,6 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
|
|
|
12930
13197
|
const handleToggleGroup = (leafValues) => {
|
|
12931
13198
|
if (leafValues.length === 0) return;
|
|
12932
13199
|
rangeAnchorRef.current = null;
|
|
12933
|
-
const selectedSet = new Set(selected);
|
|
12934
13200
|
const allSelectedInGroup = leafValues.every((v) => selectedSet.has(v));
|
|
12935
13201
|
if (allSelectedInGroup) {
|
|
12936
13202
|
const remove = new Set(leafValues);
|
|
@@ -12939,35 +13205,51 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
|
|
|
12939
13205
|
emit3([...selected, ...leafValues.filter((v) => !selectedSet.has(v))]);
|
|
12940
13206
|
}
|
|
12941
13207
|
};
|
|
13208
|
+
const hasNavigableItems = navigableItems.length > 0;
|
|
12942
13209
|
useEffect(() => {
|
|
12943
|
-
if (!open ||
|
|
13210
|
+
if (!open || !hasNavigableItems) {
|
|
12944
13211
|
setFocusedIndex(-1);
|
|
12945
13212
|
return;
|
|
12946
13213
|
}
|
|
12947
13214
|
const anchor = alignSelectedTopRef.current ? selectedAnchorRef.current : -1;
|
|
12948
13215
|
setFocusedIndex(anchor >= 0 ? anchor : 0);
|
|
12949
|
-
}, [open, search,
|
|
13216
|
+
}, [open, search, hasNavigableItems]);
|
|
13217
|
+
const lastResetSearchRef = useRef(search);
|
|
13218
|
+
useLayoutEffect(() => {
|
|
13219
|
+
if (lastResetSearchRef.current === search) return;
|
|
13220
|
+
lastResetSearchRef.current = search;
|
|
13221
|
+
if (!open || !listEl) return;
|
|
13222
|
+
listEl.scrollTop = 0;
|
|
13223
|
+
syncScrollStateRef.current();
|
|
13224
|
+
}, [listEl, open, search]);
|
|
12950
13225
|
useEffect(() => {
|
|
12951
13226
|
rangeAnchorRef.current = null;
|
|
13227
|
+
lastReachEndCountRef.current = -1;
|
|
12952
13228
|
}, [open, search]);
|
|
12953
13229
|
useLayoutEffect(() => {
|
|
12954
13230
|
if (!open || focusedIndex < 0 || !listEl) return;
|
|
12955
|
-
const
|
|
12956
|
-
if (
|
|
12957
|
-
const
|
|
12958
|
-
const
|
|
12959
|
-
if (
|
|
13231
|
+
const m = metricsRef.current;
|
|
13232
|
+
if (m == null) return;
|
|
13233
|
+
const stickyOffset = searchBarRef.current?.offsetHeight ?? 0;
|
|
13234
|
+
const rowIndex = navigableItemsRef.current[focusedIndex]?.index;
|
|
13235
|
+
if (rowIndex == null) {
|
|
12960
13236
|
alignSelectedTopRef.current = false;
|
|
12961
|
-
|
|
12962
|
-
|
|
13237
|
+
listEl.scrollTop = 0;
|
|
13238
|
+
syncScrollStateRef.current();
|
|
12963
13239
|
return;
|
|
12964
13240
|
}
|
|
12965
|
-
|
|
12966
|
-
|
|
12967
|
-
|
|
12968
|
-
|
|
12969
|
-
|
|
12970
|
-
|
|
13241
|
+
const top = rowsOffset + offsetOf(m, rowIndex);
|
|
13242
|
+
const height = sizeOf(m, rowIndex);
|
|
13243
|
+
if (alignSelectedTopRef.current) {
|
|
13244
|
+
alignSelectedTopRef.current = false;
|
|
13245
|
+
listEl.scrollTop = top - stickyOffset;
|
|
13246
|
+
} else if (top < listEl.scrollTop + stickyOffset) {
|
|
13247
|
+
listEl.scrollTop = top - stickyOffset;
|
|
13248
|
+
} else if (top + height > listEl.scrollTop + listEl.clientHeight) {
|
|
13249
|
+
listEl.scrollTop = top + height - listEl.clientHeight;
|
|
13250
|
+
}
|
|
13251
|
+
syncScrollStateRef.current();
|
|
13252
|
+
}, [focusedIndex, listEl, open, rowsOffset]);
|
|
12971
13253
|
const moveFocusedIndex = (direction) => {
|
|
12972
13254
|
if (!open || navigableItems.length === 0) return;
|
|
12973
13255
|
setFocusedIndex((current) => {
|
|
@@ -13157,6 +13439,7 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
|
|
|
13157
13439
|
SCROLLBAR_TRACK_BORDER_CLASS
|
|
13158
13440
|
),
|
|
13159
13441
|
style: { maxHeight: clampToAvailableHeight(dropdownHeight, POPOVER_AVAILABLE_HEIGHT) },
|
|
13442
|
+
onScroll: syncScrollState,
|
|
13160
13443
|
onMouseLeave: () => setFocusedIndex(-1),
|
|
13161
13444
|
children: [
|
|
13162
13445
|
searchVisible && /* @__PURE__ */ jsx(
|
|
@@ -13180,12 +13463,16 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
|
|
|
13180
13463
|
hasItems ? /* @__PURE__ */ jsx(
|
|
13181
13464
|
ItemList,
|
|
13182
13465
|
{
|
|
13183
|
-
items:
|
|
13466
|
+
items: visibleItems,
|
|
13467
|
+
indexOffset: windowStart,
|
|
13468
|
+
topSpacer: win.top,
|
|
13469
|
+
bottomSpacer: win.bottom,
|
|
13470
|
+
setSize: isDepth ? void 0 : rowCount,
|
|
13184
13471
|
multi,
|
|
13185
13472
|
selected,
|
|
13186
13473
|
groupLeafValues,
|
|
13187
13474
|
focusedValue: navigableItems[focusedIndex]?.key,
|
|
13188
|
-
showSelectAll:
|
|
13475
|
+
showSelectAll: selectAllVisible,
|
|
13189
13476
|
selectAllLabel: allSelectedLabel,
|
|
13190
13477
|
selectAllSelected: allSelected,
|
|
13191
13478
|
onSelectAll: handleSelectAll,
|
|
@@ -13200,7 +13487,18 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
|
|
|
13200
13487
|
if (index >= 0) setFocusedIndex(index);
|
|
13201
13488
|
}
|
|
13202
13489
|
}
|
|
13203
|
-
) :
|
|
13490
|
+
) : loading2 ? null : (
|
|
13491
|
+
// 첫 페이지를 받는 중에는 "없다"고 단정하지 않는다 — 아래 로딩 표시가 대신 나온다.
|
|
13492
|
+
/* @__PURE__ */ jsx("div", { className: "px-[12px] py-[12px] text-left text-[12px] leading-[20px] text-[color:var(--cmp-listBoxItem-content-disabled)]", children: "\uD45C\uC2DC\uD560 \uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4." })
|
|
13493
|
+
),
|
|
13494
|
+
loading2 && /* @__PURE__ */ jsx(
|
|
13495
|
+
"div",
|
|
13496
|
+
{
|
|
13497
|
+
role: "status",
|
|
13498
|
+
className: "px-[12px] py-[12px] text-center text-[12px] leading-[20px] text-[color:var(--cmp-listBoxItem-content-disabled)]",
|
|
13499
|
+
children: "\uBD88\uB7EC\uC624\uB294 \uC911..."
|
|
13500
|
+
}
|
|
13501
|
+
)
|
|
13204
13502
|
]
|
|
13205
13503
|
}
|
|
13206
13504
|
)
|
|
@@ -13213,6 +13511,10 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
|
|
|
13213
13511
|
var SSelect2 = /* @__PURE__ */ withDisplayName(SSelectImpl, "SSelect");
|
|
13214
13512
|
function ItemList({
|
|
13215
13513
|
items,
|
|
13514
|
+
indexOffset,
|
|
13515
|
+
topSpacer,
|
|
13516
|
+
bottomSpacer,
|
|
13517
|
+
setSize,
|
|
13216
13518
|
multi,
|
|
13217
13519
|
selected,
|
|
13218
13520
|
groupLeafValues,
|
|
@@ -13237,6 +13539,7 @@ function ItemList({
|
|
|
13237
13539
|
"button",
|
|
13238
13540
|
{
|
|
13239
13541
|
type: "button",
|
|
13542
|
+
"data-select-all-row": true,
|
|
13240
13543
|
"data-select-focused": focusedValue === "__select_all__" ? "true" : void 0,
|
|
13241
13544
|
"data-select-active": focusedValue === "__select_all__" ? "true" : void 0,
|
|
13242
13545
|
className: cn(
|
|
@@ -13253,7 +13556,9 @@ function ItemList({
|
|
|
13253
13556
|
]
|
|
13254
13557
|
}
|
|
13255
13558
|
),
|
|
13256
|
-
|
|
13559
|
+
topSpacer > 0 && /* @__PURE__ */ jsx("div", { "aria-hidden": true, style: { height: topSpacer } }),
|
|
13560
|
+
items.map((o, windowIndex) => {
|
|
13561
|
+
const idx = windowIndex + indexOffset;
|
|
13257
13562
|
const padLeft = o.depth === 1 ? 12 : o.depth === 2 ? 20 : 28;
|
|
13258
13563
|
const rowKey = `${o.value}-${idx}`;
|
|
13259
13564
|
if (o.isGroup) {
|
|
@@ -13270,6 +13575,8 @@ function ItemList({
|
|
|
13270
13575
|
"button",
|
|
13271
13576
|
{
|
|
13272
13577
|
type: "button",
|
|
13578
|
+
"data-select-row": true,
|
|
13579
|
+
"data-index": idx,
|
|
13273
13580
|
role: "option",
|
|
13274
13581
|
"aria-selected": groupState === true,
|
|
13275
13582
|
disabled: groupDisabled,
|
|
@@ -13320,6 +13627,8 @@ function ItemList({
|
|
|
13320
13627
|
return /* @__PURE__ */ jsx(
|
|
13321
13628
|
"div",
|
|
13322
13629
|
{
|
|
13630
|
+
"data-select-row": true,
|
|
13631
|
+
"data-index": idx,
|
|
13323
13632
|
className: cn(
|
|
13324
13633
|
"select-none py-[4px] pr-[12px] text-[12px] leading-[20px] text-[color:var(--cmp-listBoxItem-content-default)]",
|
|
13325
13634
|
groupTone,
|
|
@@ -13339,9 +13648,13 @@ function ItemList({
|
|
|
13339
13648
|
"button",
|
|
13340
13649
|
{
|
|
13341
13650
|
type: "button",
|
|
13651
|
+
"data-select-row": true,
|
|
13652
|
+
"data-index": idx,
|
|
13342
13653
|
disabled: o.disabled,
|
|
13343
13654
|
role: "option",
|
|
13344
13655
|
"aria-selected": isSelected,
|
|
13656
|
+
"aria-setsize": setSize,
|
|
13657
|
+
"aria-posinset": setSize != null ? idx + 1 : void 0,
|
|
13345
13658
|
"data-select-focused": focusedValue === o.value ? "true" : void 0,
|
|
13346
13659
|
"data-select-active": focusedValue === o.value ? "true" : void 0,
|
|
13347
13660
|
className: cn(
|
|
@@ -13376,7 +13689,8 @@ function ItemList({
|
|
|
13376
13689
|
},
|
|
13377
13690
|
rowKey
|
|
13378
13691
|
);
|
|
13379
|
-
})
|
|
13692
|
+
}),
|
|
13693
|
+
bottomSpacer > 0 && /* @__PURE__ */ jsx("div", { "aria-hidden": true, style: { height: bottomSpacer } })
|
|
13380
13694
|
] });
|
|
13381
13695
|
}
|
|
13382
13696
|
function CheckboxBox({
|
|
@@ -14537,12 +14851,29 @@ var SInput = /* @__PURE__ */ forwardRef(function SInput2({
|
|
|
14537
14851
|
}
|
|
14538
14852
|
);
|
|
14539
14853
|
});
|
|
14540
|
-
var
|
|
14854
|
+
var TEXTAREA_SIZE = {
|
|
14855
|
+
sm: {
|
|
14856
|
+
fontSize: 12,
|
|
14857
|
+
lineHeight: 20,
|
|
14858
|
+
paddingX: "var(--cmp-textinput-sm-paddingX)",
|
|
14859
|
+
paddingY: "var(--cmp-textinput-sm-paddingY)"
|
|
14860
|
+
},
|
|
14861
|
+
md: {
|
|
14862
|
+
fontSize: 14,
|
|
14863
|
+
lineHeight: 24,
|
|
14864
|
+
paddingX: "var(--cmp-textinput-md-paddingX)",
|
|
14865
|
+
paddingY: "var(--cmp-textinput-md-paddingY)"
|
|
14866
|
+
}
|
|
14867
|
+
};
|
|
14868
|
+
var MIN_ROWS = 2;
|
|
14541
14869
|
var STextarea = /* @__PURE__ */ forwardRef(function STextarea2({
|
|
14542
14870
|
value,
|
|
14543
14871
|
onValueChange,
|
|
14544
14872
|
onChange,
|
|
14545
|
-
|
|
14873
|
+
size = "sm",
|
|
14874
|
+
rows = MIN_ROWS,
|
|
14875
|
+
autogrow = false,
|
|
14876
|
+
maxRows,
|
|
14546
14877
|
rules,
|
|
14547
14878
|
status,
|
|
14548
14879
|
focused,
|
|
@@ -14569,8 +14900,30 @@ var STextarea = /* @__PURE__ */ forwardRef(function STextarea2({
|
|
|
14569
14900
|
style,
|
|
14570
14901
|
...rest
|
|
14571
14902
|
}, ref) {
|
|
14572
|
-
const p =
|
|
14903
|
+
const p = TEXTAREA_SIZE[size];
|
|
14904
|
+
const heightForRows = (n) => `calc(${p.lineHeight * n}px + ${p.paddingY} * 2)`;
|
|
14905
|
+
const minHeight = heightForRows(MIN_ROWS);
|
|
14906
|
+
const maxHeight = autogrow && maxRows != null ? heightForRows(maxRows) : void 0;
|
|
14573
14907
|
const [ruleError, setRuleError] = useState("");
|
|
14908
|
+
const innerRef = useRef(null);
|
|
14909
|
+
const setRefs2 = useCallback(
|
|
14910
|
+
(node) => {
|
|
14911
|
+
innerRef.current = node;
|
|
14912
|
+
if (typeof ref === "function") ref(node);
|
|
14913
|
+
else if (ref) ref.current = node;
|
|
14914
|
+
},
|
|
14915
|
+
[ref]
|
|
14916
|
+
);
|
|
14917
|
+
useLayoutEffect(() => {
|
|
14918
|
+
const el = innerRef.current;
|
|
14919
|
+
if (el == null) return;
|
|
14920
|
+
if (!autogrow) {
|
|
14921
|
+
el.style.height = "";
|
|
14922
|
+
return;
|
|
14923
|
+
}
|
|
14924
|
+
el.style.height = "auto";
|
|
14925
|
+
el.style.height = `${el.scrollHeight}px`;
|
|
14926
|
+
}, [autogrow, maxHeight, minHeight, rows, value]);
|
|
14574
14927
|
useFormField({
|
|
14575
14928
|
name: rest.name,
|
|
14576
14929
|
validate: () => {
|
|
@@ -14595,6 +14948,7 @@ var STextarea = /* @__PURE__ */ forwardRef(function STextarea2({
|
|
|
14595
14948
|
addonLabel,
|
|
14596
14949
|
addonAlign,
|
|
14597
14950
|
hint,
|
|
14951
|
+
size,
|
|
14598
14952
|
error: resolvedError,
|
|
14599
14953
|
status: resolvedStatus,
|
|
14600
14954
|
focused,
|
|
@@ -14609,7 +14963,7 @@ var STextarea = /* @__PURE__ */ forwardRef(function STextarea2({
|
|
|
14609
14963
|
children: /* @__PURE__ */ jsx(
|
|
14610
14964
|
"textarea",
|
|
14611
14965
|
{
|
|
14612
|
-
ref,
|
|
14966
|
+
ref: setRefs2,
|
|
14613
14967
|
value: value ?? "",
|
|
14614
14968
|
rows,
|
|
14615
14969
|
disabled,
|
|
@@ -14625,15 +14979,21 @@ var STextarea = /* @__PURE__ */ forwardRef(function STextarea2({
|
|
|
14625
14979
|
if (rules && rules.length > 0) setRuleError(runRules(e.target.value, rules));
|
|
14626
14980
|
},
|
|
14627
14981
|
className: cn(
|
|
14628
|
-
"w-full
|
|
14982
|
+
"w-full border-0 bg-transparent outline-none placeholder:text-[color:var(--sys-color-field-text-placeholder)] disabled:cursor-not-allowed",
|
|
14983
|
+
// autogrow 와 끌어서 늘리기는 같은 높이를 두고 다투므로 함께 두지 않는다
|
|
14984
|
+
autogrow ? "resize-none" : "resize-y",
|
|
14629
14985
|
AUTOFILL_RESET_CLASS,
|
|
14630
14986
|
textareaClassName
|
|
14631
14987
|
),
|
|
14632
14988
|
style: {
|
|
14633
|
-
minHeight
|
|
14634
|
-
|
|
14989
|
+
minHeight,
|
|
14990
|
+
maxHeight,
|
|
14991
|
+
// 상한이 있으면 거기 닿았을 때 안에서 스크롤한다. 상한이 없으면 높이가 늘 내용과
|
|
14992
|
+
// 같으므로 스크롤바가 나올 일이 없고, 반올림으로 1px 이 넘쳐 깜빡이는 것만 막는다.
|
|
14993
|
+
overflowY: autogrow ? maxRows != null ? "auto" : "hidden" : void 0,
|
|
14994
|
+
padding: `${p.paddingY} ${p.paddingX}`,
|
|
14635
14995
|
fontSize: p.fontSize,
|
|
14636
|
-
lineHeight:
|
|
14996
|
+
lineHeight: `${p.lineHeight}px`,
|
|
14637
14997
|
color: disabled ? "var(--cmp-textinput-text-disabled)" : "var(--sys-color-field-text-default)",
|
|
14638
14998
|
...textareaStyle
|
|
14639
14999
|
},
|
|
@@ -14643,7 +15003,7 @@ var STextarea = /* @__PURE__ */ forwardRef(function STextarea2({
|
|
|
14643
15003
|
}
|
|
14644
15004
|
);
|
|
14645
15005
|
});
|
|
14646
|
-
var
|
|
15006
|
+
var PAD2 = {
|
|
14647
15007
|
sm: { fontSize: 12, lineHeight: 20, stepper: 20, icon: 12 },
|
|
14648
15008
|
md: { fontSize: 14, lineHeight: 24, stepper: 24, icon: 14 }
|
|
14649
15009
|
};
|
|
@@ -14746,7 +15106,7 @@ var SNumberInput = /* @__PURE__ */ forwardRef(function SNumberInput2({
|
|
|
14746
15106
|
className,
|
|
14747
15107
|
style
|
|
14748
15108
|
}, ref) {
|
|
14749
|
-
const p =
|
|
15109
|
+
const p = PAD2[size];
|
|
14750
15110
|
const padX = `var(--cmp-numberInput-${size}-paddingX)`;
|
|
14751
15111
|
const decimalLimit = getDecimalLimit(allowDecimal, maxDecimalLength);
|
|
14752
15112
|
const numValue = applyDecimalLimit(toNumber(value), decimalLimit);
|