pesona-ui 1.0.29 → 1.0.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/dist/index.cjs.js
CHANGED
|
@@ -8189,120 +8189,55 @@ const useDropdownPositionAndScroll = (isOpen, dropdownOptionsRef) => {
|
|
|
8189
8189
|
}, [isOpen, dropdownOptionsRef]);
|
|
8190
8190
|
};
|
|
8191
8191
|
|
|
8192
|
-
const Select = React.forwardRef((
|
|
8192
|
+
const Select = React.forwardRef((props, ref) => {
|
|
8193
|
+
const { name, label, message, selectLabel = 'Select an option', size = 'md', floatingLabel = false, error, options, value = '', onChange, onBlur, required, disabled, } = props;
|
|
8193
8194
|
const [isOpen, setIsOpen] = React.useState(false);
|
|
8194
|
-
const [highlightIndex, setHighlightIndex] = React.useState(-1);
|
|
8195
8195
|
const dropdownRef = React.useRef(null);
|
|
8196
8196
|
const dropdownOptionsRef = React.useRef(null);
|
|
8197
|
-
const
|
|
8198
|
-
|
|
8199
|
-
|
|
8200
|
-
|
|
8201
|
-
target: { name, value: coerceValue(val), type: 'select-one' },
|
|
8202
|
-
currentTarget: { name, value: coerceValue(val), type: 'select-one' },
|
|
8203
|
-
}), [name, coerceValue]);
|
|
8204
|
-
const handleOptionSelect = React.useCallback((optionValue) => {
|
|
8205
|
-
const selectedOption = options.find((opt) => opt.value === optionValue);
|
|
8206
|
-
if (!selectedOption)
|
|
8207
|
-
return;
|
|
8208
|
-
hiddenSelectRef.current.value = String(selectedOption.value);
|
|
8209
|
-
onChange?.(createSyntheticEvent(selectedOption.value));
|
|
8210
|
-
setIsOpen(false);
|
|
8211
|
-
setTimeout(() => {
|
|
8212
|
-
onBlur?.(createSyntheticEvent(selectedOption.value));
|
|
8213
|
-
}, 0);
|
|
8214
|
-
}, [options, onChange, onBlur, createSyntheticEvent]);
|
|
8215
|
-
const handleOutsideClick = React.useCallback(() => {
|
|
8197
|
+
const selectRef = React.useRef(null);
|
|
8198
|
+
React.useImperativeHandle(ref, () => selectRef.current);
|
|
8199
|
+
React.useEffect(() => setIsOpen(false), []);
|
|
8200
|
+
useOutsideClick([dropdownRef], () => {
|
|
8216
8201
|
setIsOpen(false);
|
|
8217
|
-
|
|
8218
|
-
|
|
8219
|
-
onBlur(createSyntheticEvent(value));
|
|
8220
|
-
}, 0);
|
|
8221
|
-
}
|
|
8222
|
-
}, [value, onBlur, createSyntheticEvent]);
|
|
8223
|
-
useOutsideClick([dropdownRef], handleOutsideClick);
|
|
8202
|
+
selectRef.current?.blur(); // Trigger onBlur RHF
|
|
8203
|
+
});
|
|
8224
8204
|
useDropdownPositionAndScroll(isOpen, dropdownOptionsRef);
|
|
8225
|
-
const
|
|
8226
|
-
|
|
8227
|
-
|
|
8228
|
-
|
|
8229
|
-
|
|
8230
|
-
|
|
8231
|
-
|
|
8232
|
-
|
|
8233
|
-
|
|
8234
|
-
|
|
8235
|
-
|
|
8236
|
-
|
|
8237
|
-
|
|
8238
|
-
|
|
8239
|
-
|
|
8240
|
-
return;
|
|
8241
|
-
if (e.key === 'Enter' || e.key === ' ') {
|
|
8242
|
-
e.preventDefault();
|
|
8243
|
-
if (isOpen && highlightIndex >= 0) {
|
|
8244
|
-
handleOptionSelect(options[highlightIndex].value);
|
|
8245
|
-
}
|
|
8246
|
-
else {
|
|
8247
|
-
setIsOpen((prev) => !prev);
|
|
8248
|
-
}
|
|
8249
|
-
}
|
|
8250
|
-
else if (e.key === 'Escape' && isOpen) {
|
|
8251
|
-
setIsOpen(false);
|
|
8252
|
-
}
|
|
8253
|
-
else if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
|
|
8254
|
-
e.preventDefault();
|
|
8255
|
-
if (!isOpen) {
|
|
8256
|
-
setIsOpen(true);
|
|
8257
|
-
}
|
|
8258
|
-
else {
|
|
8259
|
-
setHighlightIndex((prev) => {
|
|
8260
|
-
const next = e.key === 'ArrowDown'
|
|
8261
|
-
? (prev + 1) % options.length
|
|
8262
|
-
: (prev - 1 + options.length) % options.length;
|
|
8263
|
-
return next;
|
|
8264
|
-
});
|
|
8265
|
-
}
|
|
8266
|
-
}
|
|
8267
|
-
}, [disabled, isOpen, highlightIndex, options, handleOptionSelect]);
|
|
8268
|
-
React.useEffect(() => {
|
|
8269
|
-
if (isOpen && dropdownOptionsRef.current && highlightIndex >= 0) {
|
|
8270
|
-
const optionElements = dropdownOptionsRef.current.querySelectorAll('.option');
|
|
8271
|
-
const highlighted = optionElements[highlightIndex];
|
|
8272
|
-
highlighted?.scrollIntoView({ block: 'nearest' });
|
|
8205
|
+
const displayText = value
|
|
8206
|
+
? options.find((opt) => opt.value === value)?.label
|
|
8207
|
+
: selectLabel;
|
|
8208
|
+
const handleOptionClick = (optionValue) => {
|
|
8209
|
+
const syntheticEvent = {
|
|
8210
|
+
target: {
|
|
8211
|
+
name,
|
|
8212
|
+
value: optionValue,
|
|
8213
|
+
},
|
|
8214
|
+
};
|
|
8215
|
+
onChange?.(syntheticEvent);
|
|
8216
|
+
// Change the select value to trigger onChange in RHF
|
|
8217
|
+
if (selectRef.current) {
|
|
8218
|
+
selectRef.current.value = String(optionValue);
|
|
8219
|
+
selectRef.current.dispatchEvent(new Event('change', { bubbles: true }));
|
|
8273
8220
|
}
|
|
8274
|
-
|
|
8221
|
+
setIsOpen(false);
|
|
8222
|
+
};
|
|
8275
8223
|
return (React.createElement(React.Fragment, null,
|
|
8276
|
-
React.createElement("select", { ref:
|
|
8277
|
-
hiddenSelectRef.current = el;
|
|
8278
|
-
if (typeof ref === 'function')
|
|
8279
|
-
ref(el);
|
|
8280
|
-
else if (ref)
|
|
8281
|
-
ref.current = el;
|
|
8282
|
-
}, name: name, value: normalizedValue, onChange: onChange, onBlur: onBlur, required: required, disabled: disabled, style: {
|
|
8283
|
-
position: 'absolute',
|
|
8284
|
-
left: '-9999px',
|
|
8285
|
-
opacity: 0,
|
|
8286
|
-
pointerEvents: 'none',
|
|
8287
|
-
width: '1px',
|
|
8288
|
-
height: '1px',
|
|
8289
|
-
}, tabIndex: -1, "aria-hidden": "true" },
|
|
8224
|
+
React.createElement("select", { ref: selectRef, name: name, value: value, onChange: onChange, onBlur: onBlur, required: required, disabled: disabled, style: { position: 'absolute', left: '-9999px' }, tabIndex: -1, "aria-hidden": "true" },
|
|
8290
8225
|
React.createElement("option", { value: "" }, "Select an option"),
|
|
8291
|
-
options.map((
|
|
8226
|
+
options.map((opt) => (React.createElement("option", { key: opt.value, value: opt.value }, opt.label)))),
|
|
8292
8227
|
label && !floatingLabel && (React.createElement("label", { htmlFor: name },
|
|
8293
8228
|
label,
|
|
8294
8229
|
" ",
|
|
8295
8230
|
required && React.createElement("span", { className: "text-danger" }, "*"))),
|
|
8296
8231
|
React.createElement("div", { className: `dropdown-select-container ${size}`, ref: dropdownRef },
|
|
8297
|
-
React.createElement("div", { className: `dropdown-header ${isOpen ? 'open' : ''} ${disabled ? 'disabled' : ''}
|
|
8232
|
+
React.createElement("div", { className: `dropdown-header ${isOpen ? 'open' : ''} ${disabled ? 'disabled' : ''}`, onClick: () => !disabled && setIsOpen(!isOpen), "aria-haspopup": "listbox", "aria-expanded": isOpen },
|
|
8298
8233
|
React.createElement("span", { className: "label" }, displayText),
|
|
8299
8234
|
React.createElement(FiChevronDown, { className: "arrow" })),
|
|
8300
|
-
isOpen && (React.createElement("div", { className: "dropdown-options scrollbar", ref: dropdownOptionsRef, role: "listbox" }, options.map((
|
|
8235
|
+
isOpen && (React.createElement("div", { className: "dropdown-options scrollbar", ref: dropdownOptionsRef, role: "listbox" }, options.map((opt) => (React.createElement("div", { key: opt.value, className: `option ${opt.value === value ? 'selected' : ''}`, onClick: () => handleOptionClick(opt.value), role: "option", "aria-selected": opt.value === value }, opt.label)))))),
|
|
8301
8236
|
label && floatingLabel && (React.createElement("label", { htmlFor: name },
|
|
8302
8237
|
label,
|
|
8303
8238
|
" ",
|
|
8304
8239
|
required && React.createElement("span", { className: "text-danger" }, "*"))),
|
|
8305
|
-
error ? (React.createElement("small", { className: "form-message text-danger"
|
|
8240
|
+
error ? (React.createElement("small", { className: "form-message text-danger" }, error)) : (message && React.createElement("small", { className: "form-message text-muted" }, message))));
|
|
8306
8241
|
});
|
|
8307
8242
|
Select.displayName = 'Select';
|
|
8308
8243
|
|
|
@@ -8699,39 +8634,49 @@ const SelectMultiple = React.forwardRef(({ name, label, message, selectLabel, fl
|
|
|
8699
8634
|
});
|
|
8700
8635
|
SelectMultiple.displayName = 'SelectMultiple';
|
|
8701
8636
|
|
|
8702
|
-
const SelectWithSearch = React.forwardRef((
|
|
8637
|
+
const SelectWithSearch = React.forwardRef((props, ref) => {
|
|
8638
|
+
const { name, label, message, selectLabel = 'Select an option', size = 'md', floatingLabel = false, error, options = [], value = '', onChange, required, disabled, selectSearch = '', setSelectSearch, isLoading = false, } = props;
|
|
8703
8639
|
const [isOpen, setIsOpen] = React.useState(false);
|
|
8704
8640
|
const dropdownRef = React.useRef(null);
|
|
8705
8641
|
const dropdownOptionsRef = React.useRef(null);
|
|
8642
|
+
const selectRef = React.useRef(null);
|
|
8643
|
+
React.useImperativeHandle(ref, () => selectRef.current);
|
|
8644
|
+
useOutsideClick([dropdownRef], () => setIsOpen(false));
|
|
8645
|
+
useDropdownPositionAndScroll(isOpen, dropdownOptionsRef);
|
|
8646
|
+
const displayText = value
|
|
8647
|
+
? options.find((opt) => opt.value === value)?.label
|
|
8648
|
+
: selectLabel;
|
|
8706
8649
|
const handleOptionClick = (optionValue) => {
|
|
8707
|
-
|
|
8708
|
-
|
|
8709
|
-
|
|
8710
|
-
|
|
8650
|
+
const syntheticEvent = {
|
|
8651
|
+
target: {
|
|
8652
|
+
name,
|
|
8653
|
+
value: optionValue,
|
|
8654
|
+
},
|
|
8655
|
+
};
|
|
8656
|
+
onChange?.(syntheticEvent);
|
|
8657
|
+
// Change the select value to trigger onChange in RHF
|
|
8658
|
+
if (selectRef.current) {
|
|
8659
|
+
selectRef.current.value = String(optionValue);
|
|
8660
|
+
selectRef.current.dispatchEvent(new Event('change', { bubbles: true }));
|
|
8711
8661
|
}
|
|
8712
8662
|
setIsOpen(false);
|
|
8713
8663
|
};
|
|
8714
|
-
useOutsideClick([dropdownRef], () => setIsOpen(false));
|
|
8715
|
-
useDropdownPositionAndScroll(isOpen, dropdownOptionsRef);
|
|
8716
|
-
React.useEffect(() => {
|
|
8717
|
-
return () => setIsOpen(false);
|
|
8718
|
-
}, []);
|
|
8719
|
-
const displayText = value
|
|
8720
|
-
? options.find((option) => option.value === value)?.label
|
|
8721
|
-
: selectLabel || 'Select an option';
|
|
8722
8664
|
return (React.createElement(React.Fragment, null,
|
|
8665
|
+
React.createElement("select", { ref: selectRef, name: name, value: value, onChange: onChange, style: { position: 'absolute', left: '-9999px' }, tabIndex: -1, "aria-hidden": "true" },
|
|
8666
|
+
React.createElement("option", { value: "" }, "Select an option"),
|
|
8667
|
+
options.map((opt) => (React.createElement("option", { key: opt.value, value: opt.value }, opt.label)))),
|
|
8723
8668
|
label && !floatingLabel && (React.createElement("label", { htmlFor: name },
|
|
8724
8669
|
label,
|
|
8725
8670
|
" ",
|
|
8726
8671
|
required && React.createElement("span", { className: "text-danger" }, "*"))),
|
|
8727
8672
|
React.createElement("div", { className: `dropdown-select-container ${size}`, ref: dropdownRef },
|
|
8728
|
-
React.createElement("div", { className: `dropdown-header ${isOpen ? 'open' : ''} ${disabled ? 'disabled' : ''}`, onClick: () => !disabled && setIsOpen(!isOpen),
|
|
8673
|
+
React.createElement("div", { className: `dropdown-header ${isOpen ? 'open' : ''} ${disabled ? 'disabled' : ''}`, onClick: () => !disabled && setIsOpen(!isOpen), "aria-haspopup": "listbox", "aria-expanded": isOpen },
|
|
8729
8674
|
React.createElement("span", { className: "label" }, displayText),
|
|
8730
8675
|
React.createElement(FiChevronDown, { className: "arrow" })),
|
|
8731
|
-
isOpen && (React.createElement("div", { className:
|
|
8676
|
+
isOpen && (React.createElement("div", { className: "dropdown-options scrollbar", ref: dropdownOptionsRef, role: "listbox" },
|
|
8732
8677
|
React.createElement("div", { className: "search-input" },
|
|
8733
|
-
React.createElement(Input, { name: "search", placeholder: "Ketik untuk mencari..", type: "search",
|
|
8734
|
-
isLoading ? (React.createElement("div", { className: "p-10 text-center" }, "Loading options...")) : options.length === 0 ? (React.createElement("div", { className: "p-10 text-center" }, "Tidak ada hasil ditemukan")) : (options.map((
|
|
8678
|
+
React.createElement(Input, { name: "search", placeholder: "Ketik untuk mencari..", type: "search", autoFocus: true, value: selectSearch, onChange: (e) => setSelectSearch?.(e.currentTarget.value) })),
|
|
8679
|
+
isLoading ? (React.createElement("div", { className: "p-10 text-center" }, "Loading options...")) : options.length === 0 ? (React.createElement("div", { className: "p-10 text-center" }, "Tidak ada hasil ditemukan")) : (options.map((opt) => (React.createElement("div", { key: opt.value, className: `option ${value === opt.value ? 'selected' : ''}`, onClick: () => handleOptionClick(opt.value), role: "option", "aria-selected": value === opt.value }, opt.label))))))),
|
|
8735
8680
|
label && floatingLabel && (React.createElement("label", { htmlFor: name },
|
|
8736
8681
|
label,
|
|
8737
8682
|
" ",
|