pesona-ui 1.0.28 → 1.0.30

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.esm.js CHANGED
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useState, useRef, useMemo, forwardRef, useCallback } from 'react';
1
+ import React, { useEffect, useState, useRef, useMemo, forwardRef, useImperativeHandle, useCallback } from 'react';
2
2
  import ReactDOM, { createPortal } from 'react-dom';
3
3
 
4
4
  const Button = ({ type = 'button', className, children, ...rest }) => {
@@ -8187,28 +8187,34 @@ const useDropdownPositionAndScroll = (isOpen, dropdownOptionsRef) => {
8187
8187
  }, [isOpen, dropdownOptionsRef]);
8188
8188
  };
8189
8189
 
8190
- const Select = forwardRef(({ name, label, message, selectLabel, size = 'md', floatingLabel = false, error, options, value = '', onChange, required, disabled, }, ref) => {
8190
+ const Select = forwardRef(({ name, label, message, selectLabel, size = 'md', floatingLabel = false, error, options, value = '', onChange, onBlur, required, disabled, }, ref) => {
8191
8191
  const [isOpen, setIsOpen] = useState(false);
8192
+ const [internalValue, setInternalValue] = useState(value);
8192
8193
  const dropdownRef = useRef(null);
8193
8194
  const dropdownOptionsRef = useRef(null);
8195
+ const selectRef = useRef(null);
8196
+ // Update internal value when value prop changes
8197
+ useEffect(() => {
8198
+ setInternalValue(value);
8199
+ }, [value]);
8200
+ // Expose selectRef to parent via forwardRef
8201
+ useImperativeHandle(ref, () => selectRef.current);
8202
+ // Handle option click
8194
8203
  const handleOptionClick = (optionValue) => {
8195
- const selectedOption = options.find((opt) => opt.value === optionValue);
8196
- // Gunakan nilai asli sesuai tipe (number/string)
8197
- const actualValue = typeof selectedOption?.value === 'number'
8198
- ? Number(selectedOption.value)
8199
- : selectedOption?.value;
8200
- if (onChange) {
8201
- onChange({
8202
- target: {
8203
- name,
8204
- value: actualValue,
8205
- },
8206
- });
8204
+ setInternalValue(optionValue);
8205
+ // Trigger onChange
8206
+ onChange?.({
8207
+ target: { name, value: optionValue, type: 'select-one' },
8208
+ });
8209
+ if (selectRef.current) {
8210
+ selectRef.current.value = optionValue.toString();
8211
+ selectRef.current.dispatchEvent(new Event('change', { bubbles: true }));
8207
8212
  }
8208
8213
  setIsOpen(false);
8209
8214
  };
8210
8215
  useOutsideClick([dropdownRef], () => {
8211
8216
  setIsOpen(false);
8217
+ selectRef.current?.blur();
8212
8218
  });
8213
8219
  useDropdownPositionAndScroll(isOpen, dropdownOptionsRef);
8214
8220
  useEffect(() => {
@@ -8216,19 +8222,29 @@ const Select = forwardRef(({ name, label, message, selectLabel, size = 'md', flo
8216
8222
  setIsOpen(false);
8217
8223
  };
8218
8224
  }, []);
8219
- const displayText = value
8220
- ? options.find((option) => option.value === value)?.label
8225
+ const displayText = internalValue
8226
+ ? options.find((option) => option.value === internalValue)?.label
8221
8227
  : selectLabel || 'Select an option';
8222
8228
  return (React.createElement(React.Fragment, null,
8229
+ React.createElement("select", { ref: selectRef, name: name, value: internalValue || '', onChange: onChange, onBlur: onBlur, required: required, disabled: disabled, style: {
8230
+ position: 'absolute',
8231
+ left: '-9999px',
8232
+ opacity: 0,
8233
+ pointerEvents: 'none',
8234
+ width: '1px',
8235
+ height: '1px',
8236
+ }, tabIndex: -1, "aria-hidden": "true" },
8237
+ React.createElement("option", { value: "" }, "Select an option"),
8238
+ options.map((option) => (React.createElement("option", { key: option.value, value: option.value }, option.label)))),
8223
8239
  label && !floatingLabel && (React.createElement("label", { htmlFor: name },
8224
8240
  label,
8225
8241
  " ",
8226
8242
  required && React.createElement("span", { className: "text-danger" }, "*"))),
8227
8243
  React.createElement("div", { className: `dropdown-select-container ${size}`, ref: dropdownRef },
8228
- React.createElement("div", { className: `dropdown-header ${isOpen ? 'open' : ''} ${disabled ? 'disabled' : ''}`, onClick: () => !disabled && setIsOpen(!isOpen), ref: ref, "aria-haspopup": "listbox", "aria-expanded": isOpen },
8244
+ React.createElement("div", { className: `dropdown-header ${isOpen ? 'open' : ''} ${disabled ? 'disabled' : ''}`, onClick: () => !disabled && setIsOpen(!isOpen), "aria-haspopup": "listbox", "aria-expanded": isOpen },
8229
8245
  React.createElement("span", { className: "label" }, displayText),
8230
8246
  React.createElement(FiChevronDown, { className: "arrow" })),
8231
- isOpen && (React.createElement("div", { className: `dropdown-options scrollbar ${disabled ? 'disabled' : ''}`, ref: dropdownOptionsRef, role: "listbox" }, options.map((option, index) => (React.createElement("div", { key: `${option.value}-${index}`, className: `option ${value === option.value ? 'selected' : ''}`, onClick: () => !disabled && handleOptionClick(option.value), role: "option", "aria-selected": value === option.value }, option.label)))))),
8247
+ isOpen && (React.createElement("div", { className: `dropdown-options scrollbar ${disabled ? 'disabled' : ''}`, ref: dropdownOptionsRef, role: "listbox" }, options.map((option, index) => (React.createElement("div", { key: `${option.value}-${index}`, className: `option ${internalValue === option.value ? 'selected' : ''}`, onClick: () => !disabled && handleOptionClick(option.value), role: "option", "aria-selected": internalValue === option.value }, option.label)))))),
8232
8248
  label && floatingLabel && (React.createElement("label", { htmlFor: name },
8233
8249
  label,
8234
8250
  " ",
@@ -8581,12 +8597,15 @@ const RadioButtonGroup = React.forwardRef(({ name, label, message, size = 'md',
8581
8597
  });
8582
8598
  RadioButtonGroup.displayName = 'RadioButtonGroup';
8583
8599
 
8584
- const SelectMultiple = forwardRef(({ name, label, message, selectLabel, floatingLabel = false, error, options, value = [], onChange, required, disabled, className, }, ref) => {
8600
+ const SelectMultiple = forwardRef(({ name, label, message, selectLabel, floatingLabel = false, error, options, value = [], onChange, onBlur, required, disabled, className, }, ref) => {
8585
8601
  const [isOpen, setIsOpen] = useState(false);
8586
8602
  const [selectedValues, setSelectedValues] = useState(value);
8587
8603
  const dropdownRef = useRef(null);
8588
8604
  const dropdownOptionsRef = useRef(null);
8589
- // Update selectedValues hanya jika value dari props berubah
8605
+ const inputRef = useRef(null);
8606
+ // expose to RHF
8607
+ useImperativeHandle(ref, () => inputRef.current);
8608
+ // update when external value changes
8590
8609
  useEffect(() => {
8591
8610
  if (JSON.stringify(value) !== JSON.stringify(selectedValues)) {
8592
8611
  setSelectedValues(value);
@@ -8597,14 +8616,16 @@ const SelectMultiple = forwardRef(({ name, label, message, selectLabel, floating
8597
8616
  ? selectedValues.filter((val) => val !== optionValue)
8598
8617
  : [...selectedValues, optionValue];
8599
8618
  setSelectedValues(newSelectedValues);
8600
- if (onChange) {
8601
- onChange({
8602
- target: { name, value: newSelectedValues },
8603
- });
8604
- }
8619
+ onChange?.({
8620
+ target: {
8621
+ name,
8622
+ value: newSelectedValues,
8623
+ },
8624
+ });
8605
8625
  };
8606
8626
  useOutsideClick([dropdownRef], () => {
8607
8627
  setIsOpen(false);
8628
+ inputRef.current?.blur();
8608
8629
  });
8609
8630
  useDropdownPositionAndScroll(isOpen, dropdownOptionsRef);
8610
8631
  const selectedLabels = selectedValues
@@ -8612,12 +8633,13 @@ const SelectMultiple = forwardRef(({ name, label, message, selectLabel, floating
8612
8633
  .filter(Boolean)
8613
8634
  .join(', ');
8614
8635
  return (React.createElement(React.Fragment, null,
8636
+ React.createElement("input", { type: "hidden", name: name, value: selectedValues.join(','), ref: inputRef, onBlur: onBlur, required: required }),
8615
8637
  label && !floatingLabel && (React.createElement("label", { htmlFor: name },
8616
8638
  label,
8617
8639
  " ",
8618
8640
  required && React.createElement("span", { className: "text-danger" }, "*"))),
8619
8641
  React.createElement("div", { className: `dropdown-select-container ${className || ''}`, ref: dropdownRef },
8620
- React.createElement("div", { className: `dropdown-header ${isOpen ? 'open' : ''} ${disabled ? 'disabled' : ''}`, onClick: () => !disabled && setIsOpen(!isOpen), ref: ref },
8642
+ React.createElement("div", { className: `dropdown-header ${isOpen ? 'open' : ''} ${disabled ? 'disabled' : ''}`, onClick: () => !disabled && setIsOpen(!isOpen) },
8621
8643
  React.createElement("span", { className: "label" }, selectedLabels || selectLabel || 'Select an option'),
8622
8644
  React.createElement(FiChevronDown, { className: `arrow ${isOpen ? 'open' : ''}` })),
8623
8645
  isOpen && !disabled && (React.createElement("div", { className: "dropdown-options scrollbar", ref: dropdownOptionsRef, role: "listbox" }, options?.map((option) => (React.createElement("div", { key: option.value, className: `option ${selectedValues.includes(option.value) ? 'selected' : ''}` },