cetec-design-system 3.0.1-next.0 → 3.1.0-next.0

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.js CHANGED
@@ -21409,7 +21409,6 @@ const dsPart = (part) => ({
21409
21409
  [DS_PART_ATTRIBUTE]: part
21410
21410
  });
21411
21411
  const AutocompleteListbox = (props) => {
21412
- const floatingLayer = useFloatingLayer();
21413
21412
  const {
21414
21413
  activeIndex,
21415
21414
  baseId,
@@ -21430,11 +21429,11 @@ const AutocompleteListbox = (props) => {
21430
21429
  onSelect,
21431
21430
  query,
21432
21431
  selectedValues,
21432
+ selectionIsCreated = false,
21433
21433
  setItemRef,
21434
21434
  statusClassName,
21435
21435
  value
21436
21436
  } = props;
21437
- const menuClasses = menu({ density, layer: floatingLayer });
21438
21437
  const showInitialLoading = loading && items.length === 0;
21439
21438
  const showNoOptions = !loading && items.length === 0;
21440
21439
  const selectedValueSet = new Set(selectedValues);
@@ -21450,13 +21449,14 @@ const AutocompleteListbox = (props) => {
21450
21449
  density,
21451
21450
  query,
21452
21451
  highlightMatches: true,
21453
- className: cx(menuClasses.wrapper, listboxClassName),
21452
+ className: listboxClassName,
21454
21453
  style: floatingStyles,
21455
21454
  onScroll,
21456
21455
  ...floatingProps,
21457
21456
  children: [
21458
21457
  items.map((option, index2) => {
21459
- const selected = multiple ? selectedValueSet.has(option.value) : value === option.value;
21458
+ const valueSelected = multiple ? selectedValueSet.has(option.value) : value === option.value;
21459
+ const selected = option.created ? valueSelected && selectionIsCreated : valueSelected && (multiple || !selectionIsCreated);
21460
21460
  return /* @__PURE__ */ jsx(
21461
21461
  ListItem,
21462
21462
  {
@@ -21601,6 +21601,12 @@ const useAutocompleteState = ({
21601
21601
  value
21602
21602
  ]
21603
21603
  );
21604
+ const clearInputValue = useCallback(() => {
21605
+ if (isInteractionBlocked) {
21606
+ return;
21607
+ }
21608
+ commitInputValue("", "clear");
21609
+ }, [commitInputValue, isInteractionBlocked]);
21604
21610
  const selectOption = useCallback(
21605
21611
  (option, reason = "select-option") => {
21606
21612
  if (isInteractionBlocked || option.disabled) {
@@ -21690,6 +21696,7 @@ const useAutocompleteState = ({
21690
21696
  inputValue,
21691
21697
  open,
21692
21698
  setInputValue,
21699
+ clearInputValue,
21693
21700
  selectOption,
21694
21701
  createOption,
21695
21702
  removeOption,
@@ -21699,13 +21706,6 @@ const useAutocompleteState = ({
21699
21706
  };
21700
21707
  const optionComponentTypeKey = "__autocompleteComponentType";
21701
21708
  const normalizeAutocompleteText = (value) => value.trim().toLowerCase();
21702
- const isAutocompleteExactMatch = (option, query) => {
21703
- const normalizedQuery = normalizeAutocompleteText(query);
21704
- if (!normalizedQuery) {
21705
- return false;
21706
- }
21707
- return normalizeAutocompleteText(option.value) === normalizedQuery || normalizeAutocompleteText(option.label) === normalizedQuery;
21708
- };
21709
21709
  const isAutocompleteOptionMatch = (option, query) => {
21710
21710
  const normalizedQuery = normalizeAutocompleteText(query);
21711
21711
  if (!normalizedQuery) {
@@ -21735,23 +21735,37 @@ const normalizeAutocompleteOptions = (children) => {
21735
21735
  []
21736
21736
  );
21737
21737
  };
21738
- const mergeAutocompleteOptions = (...optionGroups) => {
21739
- const optionByValue = /* @__PURE__ */ new Map();
21740
- optionGroups.forEach((options) => {
21741
- options.forEach((option) => {
21742
- if (!optionByValue.has(option.value)) {
21743
- optionByValue.set(option.value, option);
21744
- }
21745
- });
21746
- });
21747
- return Array.from(optionByValue.values());
21748
- };
21749
21738
  const getAutocompleteValueArray = (value, multiple) => {
21750
21739
  if (multiple) {
21751
21740
  return Array.isArray(value) ? value : value ? [value] : [];
21752
21741
  }
21753
21742
  return typeof value === "string" ? [value] : [];
21754
21743
  };
21744
+ const resolveSelectedAutocompleteOption = (selectedValue, childOptionByValue, optionByValue, allowCustomValue, isCustomValue) => {
21745
+ if (allowCustomValue && isCustomValue === true) {
21746
+ return {
21747
+ value: selectedValue,
21748
+ label: selectedValue,
21749
+ created: true
21750
+ };
21751
+ }
21752
+ const childOption = childOptionByValue.get(selectedValue);
21753
+ if (childOption) {
21754
+ return childOption;
21755
+ }
21756
+ const mergedOption = optionByValue.get(selectedValue);
21757
+ if (mergedOption == null ? void 0 : mergedOption.created) {
21758
+ return mergedOption;
21759
+ }
21760
+ if (allowCustomValue) {
21761
+ return {
21762
+ value: selectedValue,
21763
+ label: selectedValue,
21764
+ created: true
21765
+ };
21766
+ }
21767
+ return mergedOption;
21768
+ };
21755
21769
  const getFirstEnabledOptionIndex = (options) => options.findIndex((option) => !option.disabled);
21756
21770
  const LOAD_MORE_THRESHOLD_PX = 32;
21757
21771
  const defaultGetCreateOptionLabel = (inputValue) => `Add “${inputValue}”`;
@@ -21775,6 +21789,7 @@ const getDismissReason = (reason) => {
21775
21789
  return reason === "escape-key" ? "escape" : "outside-press";
21776
21790
  };
21777
21791
  const useAutocompleteController = (props) => {
21792
+ var _a;
21778
21793
  const floatingLayer = useFloatingLayer();
21779
21794
  const fieldContext = useFieldContext();
21780
21795
  const {
@@ -21791,6 +21806,7 @@ const useAutocompleteController = (props) => {
21791
21806
  onOpenChange,
21792
21807
  multiple = false,
21793
21808
  allowCustomValue = false,
21809
+ isCustomValue,
21794
21810
  getCreateOptionLabel = defaultGetCreateOptionLabel,
21795
21811
  limitTags,
21796
21812
  placeholder = "Select...",
@@ -21832,22 +21848,20 @@ const useAutocompleteController = (props) => {
21832
21848
  const inputRef = useRef(null);
21833
21849
  const itemRefs = useRef([]);
21834
21850
  const tokenRefs = useRef([]);
21851
+ const suppressCreateCommitRef = useRef(false);
21835
21852
  const [activeIndex, setActiveIndex] = useState(null);
21836
21853
  const [focusedWithin, setFocusedWithin] = useState(false);
21837
- const [createdOptions, setCreatedOptions] = useState([]);
21838
21854
  const [announcement, setAnnouncement] = useState("");
21839
21855
  const baseOptions = useMemo(
21840
21856
  () => normalizeAutocompleteOptions(children),
21841
21857
  [children]
21842
21858
  );
21843
- const options = useMemo(
21844
- () => mergeAutocompleteOptions(baseOptions, createdOptions),
21845
- [baseOptions, createdOptions]
21846
- );
21847
- const optionByValue = useMemo(
21848
- () => new Map(options.map((option) => [option.value, option])),
21849
- [options]
21859
+ const options = baseOptions;
21860
+ const childOptionByValue = useMemo(
21861
+ () => new Map(baseOptions.map((option) => [option.value, option])),
21862
+ [baseOptions]
21850
21863
  );
21864
+ const optionByValue = childOptionByValue;
21851
21865
  const handleValueChange = useCallback(
21852
21866
  (nextValue, reason) => {
21853
21867
  if (multiple) {
@@ -21900,14 +21914,30 @@ const useAutocompleteController = (props) => {
21900
21914
  [currentValue, multiple]
21901
21915
  );
21902
21916
  const selectedOptions = useMemo(
21903
- () => selectedValues.map((selectedValue) => optionByValue.get(selectedValue)),
21904
- [optionByValue, selectedValues]
21917
+ () => selectedValues.map(
21918
+ (selectedValue) => resolveSelectedAutocompleteOption(
21919
+ selectedValue,
21920
+ childOptionByValue,
21921
+ optionByValue,
21922
+ allowCustomValue,
21923
+ multiple ? void 0 : isCustomValue
21924
+ )
21925
+ ),
21926
+ [
21927
+ allowCustomValue,
21928
+ childOptionByValue,
21929
+ isCustomValue,
21930
+ multiple,
21931
+ optionByValue,
21932
+ selectedValues
21933
+ ]
21905
21934
  );
21935
+ const selectionIsCreated = Boolean(!multiple && ((_a = selectedOptions[0]) == null ? void 0 : _a.created));
21906
21936
  const selectedLabels = useMemo(
21907
21937
  () => selectedValues.map(
21908
21938
  (selectedValue, index2) => {
21909
- var _a;
21910
- return ((_a = selectedOptions[index2]) == null ? void 0 : _a.label) ?? selectedValue;
21939
+ var _a2;
21940
+ return ((_a2 = selectedOptions[index2]) == null ? void 0 : _a2.label) ?? selectedValue;
21911
21941
  }
21912
21942
  ),
21913
21943
  [selectedOptions, selectedValues]
@@ -21921,10 +21951,7 @@ const useAutocompleteController = (props) => {
21921
21951
  }, [currentInputValue, options]);
21922
21952
  const createOption = useMemo(() => {
21923
21953
  const query = currentInputValue.trim();
21924
- const hasExactMatch = options.some(
21925
- (option) => isAutocompleteExactMatch(option, query)
21926
- );
21927
- if (!allowCustomValue || !query || hasExactMatch) {
21954
+ if (!allowCustomValue || !query) {
21928
21955
  return null;
21929
21956
  }
21930
21957
  return {
@@ -21932,7 +21959,7 @@ const useAutocompleteController = (props) => {
21932
21959
  label: getCreateOptionLabel(query),
21933
21960
  created: true
21934
21961
  };
21935
- }, [allowCustomValue, currentInputValue, getCreateOptionLabel, options]);
21962
+ }, [allowCustomValue, currentInputValue, getCreateOptionLabel]);
21936
21963
  const navigationItems = useMemo(
21937
21964
  () => createOption ? [createOption, ...visibleOptions] : visibleOptions,
21938
21965
  [createOption, visibleOptions]
@@ -21945,6 +21972,37 @@ const useAutocompleteController = (props) => {
21945
21972
  );
21946
21973
  const firstEnabledIndex = getFirstEnabledOptionIndex(navigationItems);
21947
21974
  const resolvedActiveIndex = isOpen ? activeIndex ?? (firstEnabledIndex >= 0 ? firstEnabledIndex : null) : null;
21975
+ const focusInput = useCallback(() => {
21976
+ var _a2;
21977
+ (_a2 = inputRef.current) == null ? void 0 : _a2.focus();
21978
+ }, []);
21979
+ const handleOptionSelect = useCallback(
21980
+ (option, { restoreFocus = true } = {}) => {
21981
+ if (option.disabled) {
21982
+ return;
21983
+ }
21984
+ if (option.created) {
21985
+ const createdOption = { ...option, label: option.value };
21986
+ state.selectOption(createdOption, "create-option");
21987
+ setAnnouncement(`${option.value} created and selected.`);
21988
+ } else {
21989
+ state.selectOption(option);
21990
+ setAnnouncement(`${option.label} selected.`);
21991
+ }
21992
+ setActiveIndex(null);
21993
+ if (restoreFocus) {
21994
+ requestAnimationFrame(focusInput);
21995
+ }
21996
+ },
21997
+ [focusInput, state]
21998
+ );
21999
+ const tryCommitCreateOption = useCallback(() => {
22000
+ if (!createOption || disabled || readOnly || suppressCreateCommitRef.current) {
22001
+ return false;
22002
+ }
22003
+ handleOptionSelect(createOption, { restoreFocus: false });
22004
+ return true;
22005
+ }, [createOption, disabled, handleOptionSelect, readOnly]);
21948
22006
  const handleFloatingOpenChange = useCallback(
21949
22007
  (nextOpen, _event, reason) => {
21950
22008
  if (nextOpen) {
@@ -21952,9 +22010,27 @@ const useAutocompleteController = (props) => {
21952
22010
  return;
21953
22011
  }
21954
22012
  setActiveIndex(null);
21955
- state.closePopup(getDismissReason(reason));
22013
+ const dismissReason = getDismissReason(reason);
22014
+ if (dismissReason === "escape") {
22015
+ suppressCreateCommitRef.current = true;
22016
+ if (allowCustomValue) {
22017
+ state.clearInputValue();
22018
+ }
22019
+ state.closePopup(dismissReason);
22020
+ return;
22021
+ }
22022
+ if (dismissReason === "outside-press") {
22023
+ const committed = tryCommitCreateOption();
22024
+ if (committed) {
22025
+ if (multiple) {
22026
+ state.closePopup("outside-press");
22027
+ }
22028
+ return;
22029
+ }
22030
+ }
22031
+ state.closePopup(dismissReason);
21956
22032
  },
21957
- [state]
22033
+ [allowCustomValue, multiple, state, tryCommitCreateOption]
21958
22034
  );
21959
22035
  const floating = useOverlayFloating({
21960
22036
  open: isOpen,
@@ -21993,35 +22069,10 @@ const useAutocompleteController = (props) => {
21993
22069
  const visibleTagCount = shouldLimitTags ? limitTags : selectedValues.length;
21994
22070
  const visibleSelectedValues = selectedValues.slice(0, visibleTagCount);
21995
22071
  const hiddenTagCount = selectedValues.length - visibleSelectedValues.length;
21996
- const focusInput = useCallback(() => {
21997
- var _a;
21998
- (_a = inputRef.current) == null ? void 0 : _a.focus();
21999
- }, []);
22000
22072
  const focusToken = useCallback((index2) => {
22001
- var _a;
22002
- (_a = tokenRefs.current[index2]) == null ? void 0 : _a.focus();
22073
+ var _a2;
22074
+ (_a2 = tokenRefs.current[index2]) == null ? void 0 : _a2.focus();
22003
22075
  }, []);
22004
- const handleOptionSelect = useCallback(
22005
- (option) => {
22006
- if (option.disabled) {
22007
- return;
22008
- }
22009
- if (option.created) {
22010
- const createdOption = { ...option, label: option.value };
22011
- setCreatedOptions(
22012
- (currentOptions) => mergeAutocompleteOptions(currentOptions, [createdOption])
22013
- );
22014
- state.selectOption(createdOption, "create-option");
22015
- setAnnouncement(`${option.value} created and selected.`);
22016
- } else {
22017
- state.selectOption(option);
22018
- setAnnouncement(`${option.label} selected.`);
22019
- }
22020
- setActiveIndex(null);
22021
- requestAnimationFrame(focusInput);
22022
- },
22023
- [focusInput, state]
22024
- );
22025
22076
  const removeSelectedValue = useCallback(
22026
22077
  (selectedValue, label2) => {
22027
22078
  state.removeOption(selectedValue);
@@ -22073,6 +22124,7 @@ const useAutocompleteController = (props) => {
22073
22124
  );
22074
22125
  const handleInputChange = useCallback(
22075
22126
  (event) => {
22127
+ suppressCreateCommitRef.current = false;
22076
22128
  setActiveIndex(null);
22077
22129
  state.setInputValue(event.target.value);
22078
22130
  },
@@ -22132,18 +22184,22 @@ const useAutocompleteController = (props) => {
22132
22184
  (event) => {
22133
22185
  const nextTarget = event.relatedTarget;
22134
22186
  requestAnimationFrame(() => {
22135
- var _a, _b, _c, _d;
22187
+ var _a2, _b, _c, _d;
22136
22188
  const activeElement2 = document.activeElement;
22137
- const isInsideRoot = nextTarget && ((_a = rootRef.current) == null ? void 0 : _a.contains(nextTarget)) || activeElement2 && ((_b = rootRef.current) == null ? void 0 : _b.contains(activeElement2));
22189
+ const isInsideRoot = nextTarget && ((_a2 = rootRef.current) == null ? void 0 : _a2.contains(nextTarget)) || activeElement2 && ((_b = rootRef.current) == null ? void 0 : _b.contains(activeElement2));
22138
22190
  const isInsideFloating = nextTarget && ((_c = floatingElementRef.current) == null ? void 0 : _c.contains(nextTarget)) || activeElement2 && ((_d = floatingElementRef.current) == null ? void 0 : _d.contains(activeElement2));
22139
22191
  if (!isInsideRoot && !isInsideFloating) {
22140
22192
  setFocusedWithin(false);
22141
22193
  setActiveIndex(null);
22194
+ const committed = tryCommitCreateOption();
22195
+ if (committed && !multiple) {
22196
+ return;
22197
+ }
22142
22198
  state.closePopup("outside-press");
22143
22199
  }
22144
22200
  });
22145
22201
  },
22146
- [state]
22202
+ [multiple, state, tryCommitCreateOption]
22147
22203
  );
22148
22204
  const handleFocusCapture = useCallback(() => {
22149
22205
  setFocusedWithin(true);
@@ -22238,6 +22294,7 @@ const useAutocompleteController = (props) => {
22238
22294
  selectedLabels,
22239
22295
  selectedOptions,
22240
22296
  selectedValues,
22297
+ selectionIsCreated,
22241
22298
  setFloatingRef,
22242
22299
  setItemRef,
22243
22300
  setTokenRef,
@@ -22297,6 +22354,7 @@ const Autocomplete = (props) => {
22297
22354
  selectedLabels,
22298
22355
  selectedOptions,
22299
22356
  selectedValues,
22357
+ selectionIsCreated,
22300
22358
  setFloatingRef,
22301
22359
  setItemRef,
22302
22360
  setTokenRef,
@@ -22443,6 +22501,7 @@ const Autocomplete = (props) => {
22443
22501
  onSelect: handleOptionSelect,
22444
22502
  query: currentInputValue.trim(),
22445
22503
  selectedValues,
22504
+ selectionIsCreated,
22446
22505
  setItemRef,
22447
22506
  statusClassName: classes.status,
22448
22507
  value: currentValue