trotl-filter 1.0.42 → 1.0.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs.js +343 -11
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +343 -12
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs.js
CHANGED
|
@@ -7224,12 +7224,12 @@ const MultiSelectDropdown = ({
|
|
|
7224
7224
|
maxHeight: 34,
|
|
7225
7225
|
minHeight: 34,
|
|
7226
7226
|
height: "auto",
|
|
7227
|
-
|
|
7227
|
+
background: disabled ? '#f5f5f5' : theme === "dark" ? "#1e1e1e" : "#fff",
|
|
7228
7228
|
borderColor: theme === "dark" ? "#555" : "#ccc",
|
|
7229
7229
|
color: theme === "dark" ? "#eee" : "#333",
|
|
7230
7230
|
boxShadow: "none",
|
|
7231
7231
|
borderRadius: 2,
|
|
7232
|
-
cursor: "pointer",
|
|
7232
|
+
cursor: disabled ? 'not-allowed' : "pointer",
|
|
7233
7233
|
paddingRight: showSpinner ? 36 : base.paddingRight
|
|
7234
7234
|
}),
|
|
7235
7235
|
menu: base => ({
|
|
@@ -7293,7 +7293,8 @@ const MultiSelectDropdown = ({
|
|
|
7293
7293
|
position: 'relative',
|
|
7294
7294
|
...style,
|
|
7295
7295
|
...(disabled ? {
|
|
7296
|
-
opacity: 0.6
|
|
7296
|
+
opacity: 0.6,
|
|
7297
|
+
background: '#f5f5f5'
|
|
7297
7298
|
} : {})
|
|
7298
7299
|
},
|
|
7299
7300
|
ref: containerRef,
|
|
@@ -8329,6 +8330,327 @@ function requirePropTypes () {
|
|
|
8329
8330
|
var propTypesExports = /*@__PURE__*/ requirePropTypes();
|
|
8330
8331
|
var PropTypes = /*@__PURE__*/getDefaultExportFromCjs(propTypesExports);
|
|
8331
8332
|
|
|
8333
|
+
function MultiSelect({
|
|
8334
|
+
isMulti = false,
|
|
8335
|
+
options = [],
|
|
8336
|
+
selected = [],
|
|
8337
|
+
onChange,
|
|
8338
|
+
placeholder = 'Select...',
|
|
8339
|
+
allowClear = false,
|
|
8340
|
+
disabled = false,
|
|
8341
|
+
addItem,
|
|
8342
|
+
pushUrlParamObj = false,
|
|
8343
|
+
loading = false,
|
|
8344
|
+
controlStyle = {},
|
|
8345
|
+
className = ''
|
|
8346
|
+
}) {
|
|
8347
|
+
const containerRef = React.useRef(null);
|
|
8348
|
+
const [open, setOpen] = React.useState(false);
|
|
8349
|
+
const [inputValue, setInputValue] = React.useState('');
|
|
8350
|
+
const [maxVisible, setMaxVisible] = React.useState(3);
|
|
8351
|
+
const [isFocused, setIsFocused] = React.useState(false);
|
|
8352
|
+
React.useEffect(() => {
|
|
8353
|
+
if (!containerRef.current) return;
|
|
8354
|
+
const calc = () => {
|
|
8355
|
+
const w = containerRef.current.offsetWidth || 200;
|
|
8356
|
+
const avg = 90;
|
|
8357
|
+
setMaxVisible(Math.max(1, Math.floor((w - 40) / avg)));
|
|
8358
|
+
};
|
|
8359
|
+
calc();
|
|
8360
|
+
window.addEventListener('resize', calc);
|
|
8361
|
+
return () => window.removeEventListener('resize', calc);
|
|
8362
|
+
}, []);
|
|
8363
|
+
|
|
8364
|
+
// URL sync helpers
|
|
8365
|
+
const setUrlParam = value => {
|
|
8366
|
+
if (!pushUrlParamObj) return;
|
|
8367
|
+
const url = new URL(window.location);
|
|
8368
|
+
if (!value || Array.isArray(value) && value.length === 0) url.searchParams.delete(pushUrlParamObj);else url.searchParams.set(pushUrlParamObj, Array.isArray(value) ? value.join(',') : value);
|
|
8369
|
+
window.history.replaceState({}, '', url);
|
|
8370
|
+
};
|
|
8371
|
+
React.useEffect(() => {
|
|
8372
|
+
if (!pushUrlParamObj || !options || options.length === 0) return;
|
|
8373
|
+
const read = () => {
|
|
8374
|
+
const params = new URLSearchParams(window.location.search);
|
|
8375
|
+
const val = params.get(pushUrlParamObj);
|
|
8376
|
+
if (!val) return;
|
|
8377
|
+
if (isMulti) {
|
|
8378
|
+
const arr = val.split(',').filter(Boolean);
|
|
8379
|
+
if (JSON.stringify(arr) !== JSON.stringify(selected)) onChange?.(arr);
|
|
8380
|
+
} else {
|
|
8381
|
+
if (!selected || selected[0] !== val) onChange?.([val]);
|
|
8382
|
+
}
|
|
8383
|
+
};
|
|
8384
|
+
read();
|
|
8385
|
+
window.addEventListener('popstate', read);
|
|
8386
|
+
return () => window.removeEventListener('popstate', read);
|
|
8387
|
+
}, [pushUrlParamObj, options, isMulti, selected, onChange]);
|
|
8388
|
+
const selectedOptions = React.useMemo(() => {
|
|
8389
|
+
if (isMulti) return options.filter(o => (selected || []).includes(o.value));
|
|
8390
|
+
return options.find(o => o.value === (selected && selected[0])) || null;
|
|
8391
|
+
}, [options, selected, isMulti]);
|
|
8392
|
+
const inputExists = React.useMemo(() => {
|
|
8393
|
+
return options.some(opt => String(opt.label).toLowerCase() === inputValue.trim().toLowerCase());
|
|
8394
|
+
}, [inputValue, options]);
|
|
8395
|
+
const menuOptions = React.useMemo(() => {
|
|
8396
|
+
if (inputValue && !inputExists && typeof addItem === 'function') {
|
|
8397
|
+
return [...options, {
|
|
8398
|
+
label: `+ Add "${inputValue.trim()}"`,
|
|
8399
|
+
value: '__add_new__',
|
|
8400
|
+
__isAddNew: true
|
|
8401
|
+
}];
|
|
8402
|
+
}
|
|
8403
|
+
return options;
|
|
8404
|
+
}, [options, inputValue, inputExists, addItem]);
|
|
8405
|
+
|
|
8406
|
+
// Labels for items hidden behind the "overflow" indicator
|
|
8407
|
+
const hiddenLabels = React.useMemo(() => {
|
|
8408
|
+
if (!isMulti) return "";
|
|
8409
|
+
const arr = (selectedOptions || []).slice(maxVisible).map(s => s.label);
|
|
8410
|
+
return arr.join(', ');
|
|
8411
|
+
}, [isMulti, selectedOptions, maxVisible]);
|
|
8412
|
+
const toggleValue = val => {
|
|
8413
|
+
if (disabled) return;
|
|
8414
|
+
if (isMulti) {
|
|
8415
|
+
const prev = Array.isArray(selected) ? [...selected] : [];
|
|
8416
|
+
const idx = prev.findIndex(x => String(x) === String(val));
|
|
8417
|
+
if (idx === -1) prev.push(val);else prev.splice(idx, 1);
|
|
8418
|
+
onChange?.(prev);
|
|
8419
|
+
if (pushUrlParamObj) setUrlParam(prev);
|
|
8420
|
+
} else {
|
|
8421
|
+
const out = [val];
|
|
8422
|
+
onChange?.(out);
|
|
8423
|
+
if (pushUrlParamObj) setUrlParam(val);
|
|
8424
|
+
setOpen(false);
|
|
8425
|
+
}
|
|
8426
|
+
};
|
|
8427
|
+
const handleAddNew = () => {
|
|
8428
|
+
if (disabled) return;
|
|
8429
|
+
const label = inputValue.trim();
|
|
8430
|
+
if (!label) return;
|
|
8431
|
+
const exists = options.some(opt => String(opt.value).toLowerCase() === label.toLowerCase() || String(opt.label).toLowerCase() === label.toLowerCase());
|
|
8432
|
+
if (exists) {
|
|
8433
|
+
setInputValue('');
|
|
8434
|
+
return;
|
|
8435
|
+
}
|
|
8436
|
+
const newOpt = {
|
|
8437
|
+
label,
|
|
8438
|
+
value: label
|
|
8439
|
+
};
|
|
8440
|
+
if (typeof addItem === 'function') addItem(newOpt);
|
|
8441
|
+
if (isMulti) {
|
|
8442
|
+
const next = [...(selected || []), newOpt.value];
|
|
8443
|
+
onChange?.(next);
|
|
8444
|
+
if (pushUrlParamObj) setUrlParam(next);
|
|
8445
|
+
} else {
|
|
8446
|
+
onChange?.([newOpt.value]);
|
|
8447
|
+
if (pushUrlParamObj) setUrlParam(newOpt.value);
|
|
8448
|
+
setOpen(false);
|
|
8449
|
+
}
|
|
8450
|
+
setInputValue('');
|
|
8451
|
+
};
|
|
8452
|
+
const clearSelection = () => {
|
|
8453
|
+
if (disabled) return;
|
|
8454
|
+
onChange?.([]);
|
|
8455
|
+
if (pushUrlParamObj) setUrlParam([]);
|
|
8456
|
+
};
|
|
8457
|
+
React.useEffect(() => {
|
|
8458
|
+
const onDocClick = e => {
|
|
8459
|
+
if (!containerRef.current) return;
|
|
8460
|
+
if (!containerRef.current.contains(e.target)) setOpen(false);
|
|
8461
|
+
};
|
|
8462
|
+
document.addEventListener('mousedown', onDocClick);
|
|
8463
|
+
return () => document.removeEventListener('mousedown', onDocClick);
|
|
8464
|
+
}, []);
|
|
8465
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
8466
|
+
ref: containerRef,
|
|
8467
|
+
className: className,
|
|
8468
|
+
style: {
|
|
8469
|
+
position: 'relative',
|
|
8470
|
+
width: '100%',
|
|
8471
|
+
...controlStyle,
|
|
8472
|
+
...(disabled ? {
|
|
8473
|
+
background: '#f5f5f5',
|
|
8474
|
+
opacity: 0.9
|
|
8475
|
+
} : {})
|
|
8476
|
+
}
|
|
8477
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
8478
|
+
role: "button",
|
|
8479
|
+
tabIndex: 0,
|
|
8480
|
+
onClick: () => !disabled && setOpen(s => !s),
|
|
8481
|
+
onKeyDown: e => {
|
|
8482
|
+
if (e.key === 'Enter' && !disabled) setOpen(s => !s);
|
|
8483
|
+
},
|
|
8484
|
+
onFocus: () => setIsFocused(true),
|
|
8485
|
+
onBlur: () => setIsFocused(false),
|
|
8486
|
+
style: {
|
|
8487
|
+
minHeight: 36,
|
|
8488
|
+
display: 'flex',
|
|
8489
|
+
alignItems: 'center',
|
|
8490
|
+
gap: 8,
|
|
8491
|
+
padding: '6px 8px',
|
|
8492
|
+
border: disabled ? '1px solid #eee' : isFocused && (isMulti ? (selected || []).length > 0 : selected && selected[0] != null) ? '1px solid transparent' : '1px solid #ccc',
|
|
8493
|
+
borderRadius: 2,
|
|
8494
|
+
cursor: disabled ? 'not-allowed' : 'pointer',
|
|
8495
|
+
background: disabled ? '#f5f5f5' : '#fff',
|
|
8496
|
+
outline: 'none',
|
|
8497
|
+
...controlStyle
|
|
8498
|
+
}
|
|
8499
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
8500
|
+
style: {
|
|
8501
|
+
display: 'flex',
|
|
8502
|
+
gap: 6,
|
|
8503
|
+
alignItems: 'center',
|
|
8504
|
+
flexWrap: 'nowrap',
|
|
8505
|
+
flex: 1,
|
|
8506
|
+
overflow: 'hidden',
|
|
8507
|
+
minWidth: 0
|
|
8508
|
+
}
|
|
8509
|
+
}, isMulti ? (selectedOptions || []).slice(0, maxVisible).map(s => /*#__PURE__*/React.createElement("div", {
|
|
8510
|
+
key: s.value,
|
|
8511
|
+
onClick: e => e.stopPropagation(),
|
|
8512
|
+
style: {
|
|
8513
|
+
display: 'inline-flex',
|
|
8514
|
+
alignItems: 'center',
|
|
8515
|
+
gap: 6,
|
|
8516
|
+
padding: '4px 8px',
|
|
8517
|
+
background: '#e6f4ff',
|
|
8518
|
+
borderRadius: 2,
|
|
8519
|
+
fontSize: 13,
|
|
8520
|
+
whiteSpace: 'nowrap',
|
|
8521
|
+
overflow: 'hidden',
|
|
8522
|
+
textOverflow: 'ellipsis',
|
|
8523
|
+
maxWidth: 200,
|
|
8524
|
+
minWidth: 0
|
|
8525
|
+
}
|
|
8526
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
8527
|
+
style: {
|
|
8528
|
+
overflow: 'hidden',
|
|
8529
|
+
textOverflow: 'ellipsis',
|
|
8530
|
+
whiteSpace: 'nowrap',
|
|
8531
|
+
display: 'inline-block'
|
|
8532
|
+
}
|
|
8533
|
+
}, s.label), /*#__PURE__*/React.createElement("button", {
|
|
8534
|
+
"aria-label": `Remove ${s.label}`,
|
|
8535
|
+
onClick: e => {
|
|
8536
|
+
e.stopPropagation();
|
|
8537
|
+
if (!disabled) toggleValue(s.value);
|
|
8538
|
+
},
|
|
8539
|
+
style: {
|
|
8540
|
+
border: 'none',
|
|
8541
|
+
background: 'transparent',
|
|
8542
|
+
cursor: disabled ? 'not-allowed' : 'pointer',
|
|
8543
|
+
padding: 0,
|
|
8544
|
+
margin: 0,
|
|
8545
|
+
fontSize: 12
|
|
8546
|
+
}
|
|
8547
|
+
}, "\u2716"))) : /*#__PURE__*/React.createElement("div", {
|
|
8548
|
+
style: {
|
|
8549
|
+
fontSize: 14,
|
|
8550
|
+
color: selectedOptions ? '#000' : '#666',
|
|
8551
|
+
overflow: 'hidden',
|
|
8552
|
+
textOverflow: 'ellipsis',
|
|
8553
|
+
whiteSpace: 'nowrap'
|
|
8554
|
+
}
|
|
8555
|
+
}, selectedOptions ? selectedOptions.label : placeholder), isMulti && (selectedOptions || []).length > maxVisible && /*#__PURE__*/React.createElement("div", {
|
|
8556
|
+
title: hiddenLabels,
|
|
8557
|
+
style: {
|
|
8558
|
+
fontSize: 13,
|
|
8559
|
+
color: '#666',
|
|
8560
|
+
cursor: 'default',
|
|
8561
|
+
flex: '0 0 auto',
|
|
8562
|
+
paddingLeft: 4
|
|
8563
|
+
}
|
|
8564
|
+
}, "\u2026")), /*#__PURE__*/React.createElement("div", {
|
|
8565
|
+
style: {
|
|
8566
|
+
display: 'flex',
|
|
8567
|
+
alignItems: 'center',
|
|
8568
|
+
gap: 8
|
|
8569
|
+
}
|
|
8570
|
+
}, allowClear && selected && selected.length > 0 && /*#__PURE__*/React.createElement("span", {
|
|
8571
|
+
onClick: e => {
|
|
8572
|
+
e.stopPropagation();
|
|
8573
|
+
clearSelection();
|
|
8574
|
+
},
|
|
8575
|
+
disabled: disabled,
|
|
8576
|
+
style: {
|
|
8577
|
+
cursor: disabled ? 'not-allowed' : 'pointer'
|
|
8578
|
+
}
|
|
8579
|
+
}, "\u2716"), loading && !disabled && /*#__PURE__*/React.createElement("div", {
|
|
8580
|
+
style: {
|
|
8581
|
+
width: 16,
|
|
8582
|
+
height: 16,
|
|
8583
|
+
borderRadius: 2,
|
|
8584
|
+
border: '2px solid #ccc',
|
|
8585
|
+
borderTopColor: '#444',
|
|
8586
|
+
animation: 'spin 0.9s linear infinite'
|
|
8587
|
+
}
|
|
8588
|
+
}))), open && /*#__PURE__*/React.createElement("div", {
|
|
8589
|
+
style: {
|
|
8590
|
+
position: 'absolute',
|
|
8591
|
+
zIndex: 50,
|
|
8592
|
+
marginTop: 6,
|
|
8593
|
+
width: '100%',
|
|
8594
|
+
background: '#fff',
|
|
8595
|
+
border: '1px solid #ddd',
|
|
8596
|
+
borderRadius: 2,
|
|
8597
|
+
boxShadow: '0 4px 12px rgba(0,0,0,0.08)',
|
|
8598
|
+
maxHeight: 260,
|
|
8599
|
+
overflow: 'auto'
|
|
8600
|
+
}
|
|
8601
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
8602
|
+
style: {
|
|
8603
|
+
padding: 8,
|
|
8604
|
+
borderBottom: '1px solid #f1f1f1'
|
|
8605
|
+
}
|
|
8606
|
+
}, /*#__PURE__*/React.createElement("input", {
|
|
8607
|
+
autoFocus: true,
|
|
8608
|
+
value: inputValue,
|
|
8609
|
+
onChange: e => setInputValue(e.target.value),
|
|
8610
|
+
onKeyDown: e => {
|
|
8611
|
+
if (e.key === 'Enter' && inputValue && typeof addItem === 'function') {
|
|
8612
|
+
handleAddNew();
|
|
8613
|
+
}
|
|
8614
|
+
},
|
|
8615
|
+
placeholder: "Type to search...",
|
|
8616
|
+
disabled: disabled,
|
|
8617
|
+
style: {
|
|
8618
|
+
padding: '6px 8px',
|
|
8619
|
+
borderRadius: 2,
|
|
8620
|
+
border: '1px solid #ffffff'
|
|
8621
|
+
}
|
|
8622
|
+
})), /*#__PURE__*/React.createElement("div", null, menuOptions.filter(opt => String(opt.label).toLowerCase().includes(inputValue.trim().toLowerCase())).map(opt => /*#__PURE__*/React.createElement("div", {
|
|
8623
|
+
key: opt.value,
|
|
8624
|
+
onClick: e => {
|
|
8625
|
+
e.stopPropagation();
|
|
8626
|
+
if (opt.__isAddNew) {
|
|
8627
|
+
handleAddNew();
|
|
8628
|
+
} else {
|
|
8629
|
+
toggleValue(opt.value);
|
|
8630
|
+
}
|
|
8631
|
+
},
|
|
8632
|
+
style: {
|
|
8633
|
+
padding: '8px 12px',
|
|
8634
|
+
cursor: disabled ? 'not-allowed' : 'pointer',
|
|
8635
|
+
background: (isMulti ? (selected || []).includes(opt.value) : selected && selected[0] === opt.value) ? '#eef6ff' : '#fff'
|
|
8636
|
+
}
|
|
8637
|
+
}, opt.label)))), /*#__PURE__*/React.createElement("style", null, `@keyframes spin { from { transform: rotate(0deg) } to { transform: rotate(360deg) } }`));
|
|
8638
|
+
}
|
|
8639
|
+
MultiSelect.propTypes = {
|
|
8640
|
+
isMulti: PropTypes.bool,
|
|
8641
|
+
options: PropTypes.array,
|
|
8642
|
+
selected: PropTypes.array,
|
|
8643
|
+
onChange: PropTypes.func,
|
|
8644
|
+
placeholder: PropTypes.string,
|
|
8645
|
+
allowClear: PropTypes.bool,
|
|
8646
|
+
disabled: PropTypes.bool,
|
|
8647
|
+
addItem: PropTypes.func,
|
|
8648
|
+
pushUrlParamObj: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
|
|
8649
|
+
loading: PropTypes.bool,
|
|
8650
|
+
controlStyle: PropTypes.object,
|
|
8651
|
+
className: PropTypes.string
|
|
8652
|
+
};
|
|
8653
|
+
|
|
8332
8654
|
// import "src/style/DebounceSelect.css";
|
|
8333
8655
|
|
|
8334
8656
|
const DebounceSelect = ({
|
|
@@ -9242,23 +9564,32 @@ function DateTimeInput({
|
|
|
9242
9564
|
return new Date(d.getFullYear(), d.getMonth(), 1, 0, 0, 0, 0);
|
|
9243
9565
|
});
|
|
9244
9566
|
// Keep monthCursor in sync when selected date changes externally
|
|
9567
|
+
// Guard updates so changing references (e.g. PREDEFINED array identity) doesn't force state
|
|
9245
9568
|
React.useEffect(() => {
|
|
9246
9569
|
if (selectedDate) {
|
|
9247
|
-
|
|
9248
|
-
|
|
9249
|
-
|
|
9250
|
-
|
|
9570
|
+
const newMonth = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), 1);
|
|
9571
|
+
// only update monthCursor when month/year actually differ
|
|
9572
|
+
setMonthCursor(prev => {
|
|
9573
|
+
if (!prev || prev.getFullYear() !== newMonth.getFullYear() || prev.getMonth() !== newMonth.getMonth()) {
|
|
9574
|
+
return newMonth;
|
|
9575
|
+
}
|
|
9576
|
+
return prev;
|
|
9577
|
+
});
|
|
9578
|
+
|
|
9579
|
+
// Match predefined: set only when value actually changes
|
|
9251
9580
|
const ts = selectedDate.getTime();
|
|
9581
|
+
let matched = false;
|
|
9252
9582
|
for (let i = 0; i < PREDEFINED.length; i++) {
|
|
9253
9583
|
const d = PREDEFINED[i].getDate();
|
|
9254
9584
|
if (d.getTime() === ts) {
|
|
9255
|
-
setSelectedPredefined(String(i));
|
|
9256
|
-
|
|
9585
|
+
setSelectedPredefined(prev => prev !== String(i) ? String(i) : prev);
|
|
9586
|
+
matched = true;
|
|
9587
|
+
break;
|
|
9257
9588
|
}
|
|
9258
9589
|
}
|
|
9259
|
-
setSelectedPredefined("");
|
|
9590
|
+
if (!matched) setSelectedPredefined(prev => prev !== "" ? "" : prev);
|
|
9260
9591
|
} else {
|
|
9261
|
-
setSelectedPredefined("");
|
|
9592
|
+
setSelectedPredefined(prev => prev !== "" ? "" : prev);
|
|
9262
9593
|
}
|
|
9263
9594
|
}, [value, selectedDate, PREDEFINED]);
|
|
9264
9595
|
|
|
@@ -11117,6 +11448,7 @@ exports.DateTimeInput = DateTimeInput;
|
|
|
11117
11448
|
exports.DebounceSelect = DebounceSelect;
|
|
11118
11449
|
exports.IconInput = IconInput;
|
|
11119
11450
|
exports.LineDivider = LineDivider;
|
|
11451
|
+
exports.MultiSelect = MultiSelect;
|
|
11120
11452
|
exports.MultiSelectDropdown = MultiSelectDropdown;
|
|
11121
11453
|
exports.RangePicker = RangePicker;
|
|
11122
11454
|
exports.SearchInput = SearchInput;
|