@homebound/beam 4.59.0 → 4.59.1

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 CHANGED
@@ -20609,9 +20609,20 @@ function useMenuSelectField(props) {
20609
20609
  () => menuTree ? menuTree.orderedKeys.filter((key) => disabledKeySet.has(menuTree.nodes.get(key).valueKey)) : disabledKeys,
20610
20610
  [menuTree, disabledKeySet, disabledKeys]
20611
20611
  );
20612
+ const rememberedSelectedRef = (0, import_react85.useRef)(/* @__PURE__ */ new Map());
20613
+ syncRememberedOptions(rememberedSelectedRef.current, values, optionsByKey);
20612
20614
  const selectedOptions = (0, import_react85.useMemo)(
20613
- () => menuTree ? selectedTreeOptions(menuTree, selectedKeys) : values.map((v) => optionsByKey.get(valueToKey(v))).filter((o) => o !== void 0),
20614
- [menuTree, selectedKeys, values, optionsByKey]
20615
+ () => resolveSelectedOptions(
20616
+ values,
20617
+ menuTree,
20618
+ selectedKeys,
20619
+ optionsByKey,
20620
+ rememberedSelectedRef.current,
20621
+ getOptionValue
20622
+ ),
20623
+ // getOptionValue is typically an inline lambda
20624
+ // oxlint-disable-next-line react-hooks/exhaustive-deps
20625
+ [values, optionsByKey, menuTree, selectedKeys]
20615
20626
  );
20616
20627
  const dottedKeys = (0, import_react85.useMemo)(
20617
20628
  () => new Set(mixedValues?.map(valueToKey).filter((key) => optionsByKey.has(key) && !selectedKeys.has(key))),
@@ -20653,9 +20664,8 @@ function useMenuSelectField(props) {
20653
20664
  const valueKey = key === void 0 ? void 0 : menuTree.nodes.get(key)?.valueKey;
20654
20665
  if (valueKey === void 0) return;
20655
20666
  const next2 = toggleTreeSelection(menuTree, selectedKeys, valueKey, added !== void 0, disabledKeySet);
20656
- const nextOptions = selectedTreeOptions(menuTree, next2);
20657
20667
  proposalProps.onUserEdit?.();
20658
- onCommit(nextOptions.map(getOptionValue), nextOptions);
20668
+ commitTree(next2);
20659
20669
  return;
20660
20670
  }
20661
20671
  if (!multiple) {
@@ -20670,16 +20680,17 @@ function useMenuSelectField(props) {
20670
20680
  close({ restoreFocus: true });
20671
20681
  return;
20672
20682
  }
20673
- const next = values.filter((v) => keys.has(valueToKey(v)));
20683
+ const next = values.filter((value) => {
20684
+ const key = valueToKey(value);
20685
+ if (!optionsByKey.has(key)) return true;
20686
+ return keys.has(key);
20687
+ });
20674
20688
  for (const k of keys) {
20675
20689
  const opt = optionsByKey.get(String(k));
20676
20690
  if (opt !== void 0 && !selectedKeys.has(String(k))) next.push(getOptionValue(opt));
20677
20691
  }
20678
20692
  proposalProps.onUserEdit?.();
20679
- onCommit(
20680
- next,
20681
- next.map((v) => optionsByKey.get(valueToKey(v))).filter((o) => o !== void 0)
20682
- );
20693
+ onCommit(next, optionsForValues(next));
20683
20694
  }
20684
20695
  const collectionItems = (0, import_react85.useMemo)(() => {
20685
20696
  if (treeRows) {
@@ -20891,14 +20902,35 @@ function useMenuSelectField(props) {
20891
20902
  proposalProps.onUserEdit?.();
20892
20903
  if (menuTree) {
20893
20904
  const toggledKeys = toggleTreeSelection(menuTree, selectedKeys, key, false, disabledKeySet);
20894
- const toggledOptions = selectedTreeOptions(menuTree, toggledKeys);
20895
- onCommit(toggledOptions.map(getOptionValue), toggledOptions);
20905
+ commitTree(toggledKeys, key);
20896
20906
  return;
20897
20907
  }
20898
20908
  const next = values.filter((value) => valueToKey(value) !== key);
20909
+ onCommit(next, optionsForValues(next));
20910
+ }
20911
+ function optionsForValues(next) {
20912
+ return next.flatMap((value) => {
20913
+ const option = optionForKey(valueToKey(value), optionsByKey, rememberedSelectedRef.current);
20914
+ return option ? [option] : [];
20915
+ });
20916
+ }
20917
+ function commitTree(nextKeys, clearedKey) {
20918
+ if (!menuTree) return;
20919
+ const selectedInTree = selectedTreeOptions(menuTree, nextKeys);
20920
+ const valueKeysInTree = new Set(menuTree.orderedKeys.map((rowKey) => menuTree.nodes.get(rowKey).valueKey));
20921
+ const seen = /* @__PURE__ */ new Set();
20922
+ const keptSelections = values.flatMap((value) => {
20923
+ const key = valueToKey(value);
20924
+ if (valueKeysInTree.has(key) || key === clearedKey || seen.has(key)) return [];
20925
+ const option = optionForKey(key, optionsByKey, rememberedSelectedRef.current);
20926
+ if (!option) return [];
20927
+ seen.add(key);
20928
+ return [option];
20929
+ });
20930
+ const nextOptions = [...selectedInTree, ...keptSelections];
20899
20931
  onCommit(
20900
- next,
20901
- next.map((value) => optionsByKey.get(valueToKey(value))).filter((option) => option !== void 0)
20932
+ nextOptions.map((option) => getOptionValue(option)),
20933
+ nextOptions
20902
20934
  );
20903
20935
  }
20904
20936
  const triggerProps = {
@@ -20964,6 +20996,41 @@ function useMenuSelectField(props) {
20964
20996
  }
20965
20997
  };
20966
20998
  }
20999
+ function syncRememberedOptions(remembered, values, optionsByKey) {
21000
+ const selected = /* @__PURE__ */ new Set();
21001
+ for (const value of values) {
21002
+ const key = valueToKey(value);
21003
+ selected.add(key);
21004
+ const option = optionsByKey.get(key);
21005
+ if (option) remembered.set(key, option);
21006
+ }
21007
+ for (const key of remembered.keys()) {
21008
+ if (!selected.has(key)) remembered.delete(key);
21009
+ }
21010
+ }
21011
+ function optionForKey(key, optionsByKey, remembered) {
21012
+ return optionsByKey.get(key) ?? remembered.get(key);
21013
+ }
21014
+ function resolveSelectedOptions(values, menuTree, selectedKeys, optionsByKey, remembered, getOptionValue) {
21015
+ if (!menuTree) {
21016
+ return values.flatMap((value) => {
21017
+ const option = optionForKey(valueToKey(value), optionsByKey, remembered);
21018
+ return option ? [option] : [];
21019
+ });
21020
+ }
21021
+ const selectedInTree = selectedTreeOptions(menuTree, selectedKeys);
21022
+ const seen = new Set(selectedInTree.map((option) => valueToKey(getOptionValue(option))));
21023
+ const keptSelections = [];
21024
+ for (const value of values) {
21025
+ const key = valueToKey(value);
21026
+ if (seen.has(key)) continue;
21027
+ const option = optionForKey(key, optionsByKey, remembered);
21028
+ if (!option) continue;
21029
+ seen.add(key);
21030
+ keptSelections.push(option);
21031
+ }
21032
+ return [...selectedInTree, ...keptSelections];
21033
+ }
20967
21034
  function labelsFor(values, options, getOptionValue, getOptionLabel) {
20968
21035
  const keys = new Set(values.map(valueToKey));
20969
21036
  const seen = /* @__PURE__ */ new Set();