trotl-filter 1.0.23 → 1.0.26
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 +221 -9
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.esm.js +221 -10
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs.js
CHANGED
|
@@ -7688,8 +7688,16 @@ const DebounceSelect = ({
|
|
|
7688
7688
|
}, "No results")));
|
|
7689
7689
|
};
|
|
7690
7690
|
|
|
7691
|
+
/**
|
|
7692
|
+
* SearchInput Component
|
|
7693
|
+
* @param {string} pushUrlParamObj - URL parameter key (if null, URL params are not updated)
|
|
7694
|
+
* @param {string} height - Input height (e.g., "40px", "3rem")
|
|
7695
|
+
* @param {object} style - Custom inline styles
|
|
7696
|
+
*/
|
|
7691
7697
|
function SearchInput({
|
|
7692
7698
|
pushUrlParamObj = null,
|
|
7699
|
+
height,
|
|
7700
|
+
style = {},
|
|
7693
7701
|
...props
|
|
7694
7702
|
}) {
|
|
7695
7703
|
const key = pushUrlParamObj || "search";
|
|
@@ -7697,6 +7705,7 @@ function SearchInput({
|
|
|
7697
7705
|
|
|
7698
7706
|
// On mount, read the URL param and set value
|
|
7699
7707
|
React.useEffect(() => {
|
|
7708
|
+
if (pushUrlParamObj === null) return;
|
|
7700
7709
|
const params = new URLSearchParams(window.location.search);
|
|
7701
7710
|
const urlValue = params.get(key) || "";
|
|
7702
7711
|
setValue(urlValue);
|
|
@@ -7708,8 +7717,9 @@ function SearchInput({
|
|
|
7708
7717
|
};
|
|
7709
7718
|
window.addEventListener("popstate", onPopState);
|
|
7710
7719
|
return () => window.removeEventListener("popstate", onPopState);
|
|
7711
|
-
}, [key]);
|
|
7720
|
+
}, [key, pushUrlParamObj]);
|
|
7712
7721
|
const setUrlParam = val => {
|
|
7722
|
+
if (pushUrlParamObj === null) return;
|
|
7713
7723
|
const params = new URLSearchParams(window.location.search);
|
|
7714
7724
|
if (val && val.length > 0) {
|
|
7715
7725
|
params.set(key, val);
|
|
@@ -7728,14 +7738,18 @@ function SearchInput({
|
|
|
7728
7738
|
setValue("");
|
|
7729
7739
|
setUrlParam("");
|
|
7730
7740
|
};
|
|
7741
|
+
|
|
7742
|
+
// Apply height to container if provided and style doesn't have height defined
|
|
7743
|
+
const containerStyle = {
|
|
7744
|
+
position: "relative",
|
|
7745
|
+
display: "inline-block",
|
|
7746
|
+
height: height || "34px",
|
|
7747
|
+
verticalAlign: "middle",
|
|
7748
|
+
...style
|
|
7749
|
+
};
|
|
7731
7750
|
return /*#__PURE__*/React.createElement("div", {
|
|
7732
7751
|
title: "tooltip",
|
|
7733
|
-
style:
|
|
7734
|
-
position: "relative",
|
|
7735
|
-
display: "inline-block",
|
|
7736
|
-
height: "34px",
|
|
7737
|
-
verticalAlign: "middle"
|
|
7738
|
-
}
|
|
7752
|
+
style: containerStyle
|
|
7739
7753
|
}, /*#__PURE__*/React.createElement("input", _extends$1({
|
|
7740
7754
|
className: "basic-input",
|
|
7741
7755
|
value: value,
|
|
@@ -10616,6 +10630,7 @@ const Button = ({
|
|
|
10616
10630
|
style = {},
|
|
10617
10631
|
className = "",
|
|
10618
10632
|
height,
|
|
10633
|
+
float = null,
|
|
10619
10634
|
...rest
|
|
10620
10635
|
}) => {
|
|
10621
10636
|
// Determine button class based on type
|
|
@@ -10639,11 +10654,76 @@ const Button = ({
|
|
|
10639
10654
|
} : {}),
|
|
10640
10655
|
...style
|
|
10641
10656
|
};
|
|
10657
|
+
|
|
10658
|
+
// If `float` prop is provided, compute fixed positioning styles.
|
|
10659
|
+
let floatClass = "";
|
|
10660
|
+
const floatStyle = {};
|
|
10661
|
+
if (float) {
|
|
10662
|
+
floatClass = "button--float";
|
|
10663
|
+
// Accept boolean true (use bottom-right default) or object
|
|
10664
|
+
const cfg = typeof float === "object" ? float : {
|
|
10665
|
+
position: "bottom-right"
|
|
10666
|
+
};
|
|
10667
|
+
|
|
10668
|
+
// Default spacing if not provided
|
|
10669
|
+
const gap = cfg.gap || cfg.offset || 16;
|
|
10670
|
+
|
|
10671
|
+
// If explicit top/left/right/bottom provided, use them.
|
|
10672
|
+
if (cfg.top !== undefined) floatStyle.top = cfg.top;
|
|
10673
|
+
if (cfg.left !== undefined) floatStyle.left = cfg.left;
|
|
10674
|
+
if (cfg.right !== undefined) floatStyle.right = cfg.right;
|
|
10675
|
+
if (cfg.bottom !== undefined) floatStyle.bottom = cfg.bottom;
|
|
10676
|
+
|
|
10677
|
+
// If position string is provided, map to offsets unless explicit coords set
|
|
10678
|
+
if (cfg.position && !(cfg.top || cfg.left || cfg.right || cfg.bottom)) {
|
|
10679
|
+
const pos = String(cfg.position).toLowerCase();
|
|
10680
|
+
// Accept common typo 'botton' as 'bottom'
|
|
10681
|
+
const posNormalized = pos.replace(/botton/g, 'bottom');
|
|
10682
|
+
|
|
10683
|
+
// If user requested an edge position like 'bottom-left', place at exact edge (0px)
|
|
10684
|
+
if (posNormalized.includes("bottom") && posNormalized.includes("left")) {
|
|
10685
|
+
floatStyle.bottom = '0px';
|
|
10686
|
+
floatStyle.left = '0px';
|
|
10687
|
+
} else if (posNormalized.includes("bottom") && posNormalized.includes("right")) {
|
|
10688
|
+
floatStyle.bottom = '0px';
|
|
10689
|
+
floatStyle.right = '0px';
|
|
10690
|
+
} else if (posNormalized.includes("top") && posNormalized.includes("left")) {
|
|
10691
|
+
floatStyle.top = '0px';
|
|
10692
|
+
floatStyle.left = '0px';
|
|
10693
|
+
} else if (posNormalized.includes("top") && posNormalized.includes("right")) {
|
|
10694
|
+
floatStyle.top = '0px';
|
|
10695
|
+
floatStyle.right = '0px';
|
|
10696
|
+
} else {
|
|
10697
|
+
// fallback: apply gap offsets
|
|
10698
|
+
if (posNormalized.includes("bottom")) floatStyle.bottom = typeof gap === "number" ? `${gap}px` : gap;
|
|
10699
|
+
if (posNormalized.includes("top")) floatStyle.top = typeof gap === "number" ? `${gap}px` : gap;
|
|
10700
|
+
if (posNormalized.includes("left")) floatStyle.left = typeof gap === "number" ? `${gap}px` : gap;
|
|
10701
|
+
if (posNormalized.includes("right")) floatStyle.right = typeof gap === "number" ? `${gap}px` : gap;
|
|
10702
|
+
}
|
|
10703
|
+
|
|
10704
|
+
// center handling (horizontal or vertical centering)
|
|
10705
|
+
if (posNormalized.startsWith("center-")) {
|
|
10706
|
+
const parts = posNormalized.split("-");
|
|
10707
|
+
const dir = parts[1];
|
|
10708
|
+
if (dir === "bottom" || dir === "top") {
|
|
10709
|
+
floatStyle.left = "50%";
|
|
10710
|
+
floatStyle.transform = (floatStyle.transform ? floatStyle.transform + " " : "") + "translateX(-50%)";
|
|
10711
|
+
}
|
|
10712
|
+
if (dir === "left" || dir === "right") {
|
|
10713
|
+
floatStyle.top = "50%";
|
|
10714
|
+
floatStyle.transform = (floatStyle.transform ? floatStyle.transform + " " : "") + "translateY(-50%)";
|
|
10715
|
+
}
|
|
10716
|
+
}
|
|
10717
|
+
}
|
|
10718
|
+
}
|
|
10642
10719
|
return /*#__PURE__*/React.createElement("button", _extends$1({
|
|
10643
|
-
className: `button ${getButtonClass()} ${className}`,
|
|
10720
|
+
className: `button ${getButtonClass()} ${className} ${floatClass}`,
|
|
10644
10721
|
onClick: onClick,
|
|
10645
10722
|
disabled: disabled,
|
|
10646
|
-
style:
|
|
10723
|
+
style: {
|
|
10724
|
+
...buttonStyle,
|
|
10725
|
+
...floatStyle
|
|
10726
|
+
}
|
|
10647
10727
|
}, rest), children);
|
|
10648
10728
|
};
|
|
10649
10729
|
|
|
@@ -10699,6 +10779,137 @@ const Switch = ({
|
|
|
10699
10779
|
}, label));
|
|
10700
10780
|
};
|
|
10701
10781
|
|
|
10782
|
+
const formatBytes = bytes => {
|
|
10783
|
+
if (!bytes) return "0 B";
|
|
10784
|
+
const sizes = ["B", "KB", "MB", "GB", "TB"];
|
|
10785
|
+
const i = Math.floor(Math.log(bytes) / Math.log(1024));
|
|
10786
|
+
return `${(bytes / Math.pow(1024, i)).toFixed(1)} ${sizes[i]}`;
|
|
10787
|
+
};
|
|
10788
|
+
function Upload({
|
|
10789
|
+
onChange,
|
|
10790
|
+
multiple = false,
|
|
10791
|
+
accept,
|
|
10792
|
+
acceptFiles,
|
|
10793
|
+
maxFiles = null,
|
|
10794
|
+
maxFileSize = null,
|
|
10795
|
+
customPreview = null,
|
|
10796
|
+
buttonLabel = "Browse...",
|
|
10797
|
+
className = "",
|
|
10798
|
+
style = {},
|
|
10799
|
+
value = undefined
|
|
10800
|
+
}) {
|
|
10801
|
+
const inputRef = React.useRef(null);
|
|
10802
|
+
const [dragOver, setDragOver] = React.useState(false);
|
|
10803
|
+
const [files, setFiles] = React.useState([]);
|
|
10804
|
+
const handleFiles = React.useCallback((fileList, event = null) => {
|
|
10805
|
+
const incoming = Array.from(fileList || []);
|
|
10806
|
+
setFiles(prev => {
|
|
10807
|
+
let arr = multiple ? [...prev, ...incoming] : incoming;
|
|
10808
|
+
if (maxFileSize) {
|
|
10809
|
+
arr = arr.filter(f => f.size <= maxFileSize);
|
|
10810
|
+
}
|
|
10811
|
+
if (maxFiles && Number.isFinite(maxFiles)) {
|
|
10812
|
+
arr = arr.slice(0, maxFiles);
|
|
10813
|
+
}
|
|
10814
|
+
if (onChange) {
|
|
10815
|
+
// Call with (files, event) for consistency; provide single file when not multiple
|
|
10816
|
+
onChange(multiple ? arr : arr[0] || null, event || null);
|
|
10817
|
+
}
|
|
10818
|
+
return arr;
|
|
10819
|
+
});
|
|
10820
|
+
}, [onChange, multiple, maxFileSize, maxFiles]);
|
|
10821
|
+
|
|
10822
|
+
// Determine which files to display: prefer `value` prop when provided (controlled),
|
|
10823
|
+
// otherwise use internal `files` state.
|
|
10824
|
+
const displayFiles = (() => {
|
|
10825
|
+
if (value !== undefined && value !== null) {
|
|
10826
|
+
if (Array.isArray(value)) return value;
|
|
10827
|
+
return [value];
|
|
10828
|
+
}
|
|
10829
|
+
return files;
|
|
10830
|
+
})();
|
|
10831
|
+
const onInputChange = e => {
|
|
10832
|
+
handleFiles(e.target.files, e);
|
|
10833
|
+
};
|
|
10834
|
+
const openFileDialog = () => {
|
|
10835
|
+
if (inputRef.current) inputRef.current.click();
|
|
10836
|
+
};
|
|
10837
|
+
const onDrop = e => {
|
|
10838
|
+
e.preventDefault();
|
|
10839
|
+
setDragOver(false);
|
|
10840
|
+
handleFiles(e.dataTransfer.files, e);
|
|
10841
|
+
};
|
|
10842
|
+
const onDragOver = e => {
|
|
10843
|
+
e.preventDefault();
|
|
10844
|
+
setDragOver(true);
|
|
10845
|
+
};
|
|
10846
|
+
const onDragLeave = () => setDragOver(false);
|
|
10847
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
10848
|
+
className: `trotl-upload ${className}`,
|
|
10849
|
+
style: style
|
|
10850
|
+
}, /*#__PURE__*/React.createElement("input", {
|
|
10851
|
+
ref: inputRef,
|
|
10852
|
+
type: "file",
|
|
10853
|
+
style: {
|
|
10854
|
+
display: "none"
|
|
10855
|
+
},
|
|
10856
|
+
onChange: onInputChange,
|
|
10857
|
+
multiple: multiple,
|
|
10858
|
+
accept: acceptFiles || accept
|
|
10859
|
+
}), /*#__PURE__*/React.createElement("div", {
|
|
10860
|
+
className: `upload-dropzone ${dragOver ? "drag-over" : ""}`,
|
|
10861
|
+
onClick: openFileDialog,
|
|
10862
|
+
onDrop: onDrop,
|
|
10863
|
+
onDragOver: onDragOver,
|
|
10864
|
+
onDragLeave: onDragLeave,
|
|
10865
|
+
role: "button",
|
|
10866
|
+
tabIndex: 0,
|
|
10867
|
+
onKeyDown: e => {
|
|
10868
|
+
if (e.key === "Enter") openFileDialog();
|
|
10869
|
+
}
|
|
10870
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
10871
|
+
className: "upload-inner"
|
|
10872
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
10873
|
+
className: "upload-icon"
|
|
10874
|
+
}, "\u2B06\uFE0F"), /*#__PURE__*/React.createElement("div", {
|
|
10875
|
+
className: "upload-text"
|
|
10876
|
+
}, "Drag & drop files here or"), /*#__PURE__*/React.createElement("button", {
|
|
10877
|
+
type: "button",
|
|
10878
|
+
className: "upload-browse",
|
|
10879
|
+
onClick: e => {
|
|
10880
|
+
e.stopPropagation();
|
|
10881
|
+
openFileDialog();
|
|
10882
|
+
}
|
|
10883
|
+
}, buttonLabel))), displayFiles && displayFiles.length > 0 && (customPreview ? (
|
|
10884
|
+
/*#__PURE__*/
|
|
10885
|
+
// If customPreview is a component, render it with `files` prop
|
|
10886
|
+
React.createElement(customPreview, {
|
|
10887
|
+
files: displayFiles
|
|
10888
|
+
})) : /*#__PURE__*/React.createElement("ul", {
|
|
10889
|
+
className: "upload-list"
|
|
10890
|
+
}, displayFiles.map((f, i) => /*#__PURE__*/React.createElement("li", {
|
|
10891
|
+
key: `${f && f.name || f || i}-${i}`,
|
|
10892
|
+
className: "upload-item"
|
|
10893
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
10894
|
+
className: "upload-name"
|
|
10895
|
+
}, f && f.name || String(f)), /*#__PURE__*/React.createElement("span", {
|
|
10896
|
+
className: "upload-size"
|
|
10897
|
+
}, f && f.size ? formatBytes(f.size) : ""))))));
|
|
10898
|
+
}
|
|
10899
|
+
Upload.propTypes = {
|
|
10900
|
+
onChange: PropTypes.func,
|
|
10901
|
+
multiple: PropTypes.bool,
|
|
10902
|
+
accept: PropTypes.string,
|
|
10903
|
+
acceptFiles: PropTypes.string,
|
|
10904
|
+
maxFiles: PropTypes.number,
|
|
10905
|
+
maxFileSize: PropTypes.number,
|
|
10906
|
+
customPreview: PropTypes.oneOfType([PropTypes.elementType, PropTypes.func, PropTypes.node]),
|
|
10907
|
+
value: PropTypes.oneOfType([PropTypes.array, PropTypes.object, PropTypes.string]),
|
|
10908
|
+
buttonLabel: PropTypes.string,
|
|
10909
|
+
className: PropTypes.string,
|
|
10910
|
+
style: PropTypes.object
|
|
10911
|
+
};
|
|
10912
|
+
|
|
10702
10913
|
exports.Button = Button;
|
|
10703
10914
|
exports.CalendarRangePicker = CalendarRangePicker;
|
|
10704
10915
|
exports.DateTimeInput = DateTimeInput;
|
|
@@ -10709,4 +10920,5 @@ exports.MultiSelectDropdown = MultiSelectDropdown;
|
|
|
10709
10920
|
exports.RangePicker = RangePicker;
|
|
10710
10921
|
exports.SearchInput = SearchInput;
|
|
10711
10922
|
exports.Switch = Switch;
|
|
10923
|
+
exports.Upload = Upload;
|
|
10712
10924
|
//# sourceMappingURL=index.cjs.js.map
|