{"version":3,"file":"optGroupUtils-VeZ3k7-1.mjs","names":["defaultPlaceholderFieldName: typeof defaultPlaceholderName","defaultPlaceholderOperatorName: typeof defaultPlaceholderName","defaultOperatorNegationMap: Record<DefaultOperatorName, DefaultOperatorName>","defaultCombinators: DefaultCombinators","defaultCombinatorsExtended: DefaultCombinatorsExtended","idObj: { name?: string; value?: string }","newArray: T[]"],"sources":["../src/defaults.ts","../src/utils/objectUtils.ts","../src/utils/optGroupUtils.ts"],"sourcesContent":["import type {\n  BaseTranslationsFull,\n  Classnames,\n  DefaultCombinatorName,\n  DefaultCombinatorNameExtended,\n  DefaultOperatorName,\n  MatchMode,\n  Path,\n  QueryBuilderFlags,\n  StringUnionToFullOptionArray,\n} from './types';\n\n// DO NOT ALTER OR REMOVE REGION NAMES. Some of them are used\n// to generate code snippets in the documentation.\n\n/**\n * @group Defaults\n */\nexport const defaultPlaceholderName = '~';\n/**\n * @group Defaults\n */\nexport const defaultPlaceholderLabel = '------';\n/**\n * Default `name` for placeholder option in the `fields` array.\n *\n * @group Defaults\n */\nexport const defaultPlaceholderFieldName: typeof defaultPlaceholderName = defaultPlaceholderName;\n/**\n * Default `label` for placeholder option in the `fields` array.\n *\n * @group Defaults\n */\nexport const defaultPlaceholderFieldLabel: typeof defaultPlaceholderLabel = defaultPlaceholderLabel;\n/**\n * Default `label` for placeholder option group in the `fields` array.\n *\n * @group Defaults\n */\nexport const defaultPlaceholderFieldGroupLabel: typeof defaultPlaceholderLabel =\n  defaultPlaceholderLabel;\n/**\n * Default `name` for placeholder option in the `operators` array.\n *\n * @group Defaults\n */\nexport const defaultPlaceholderOperatorName: typeof defaultPlaceholderName = defaultPlaceholderName;\n/**\n * Default `label` for placeholder option in the `operators` array.\n *\n * @group Defaults\n */\nexport const defaultPlaceholderOperatorLabel: typeof defaultPlaceholderLabel =\n  defaultPlaceholderLabel;\n/**\n * Default `label` for placeholder option group in the `operators` array.\n *\n * @group Defaults\n */\nexport const defaultPlaceholderOperatorGroupLabel: typeof defaultPlaceholderLabel =\n  defaultPlaceholderLabel;\n/**\n * Default `name` for placeholder option in the `values` array.\n *\n * @group Defaults\n */\nexport const defaultPlaceholderValueName: typeof defaultPlaceholderName = defaultPlaceholderName;\n/**\n * Default `label` for placeholder option in the `values` array.\n *\n * @group Defaults\n */\nexport const defaultPlaceholderValueLabel: typeof defaultPlaceholderLabel = defaultPlaceholderLabel;\n/**\n * Default `label` for placeholder option group in the `values` array.\n *\n * @group Defaults\n */\nexport const defaultPlaceholderValueGroupLabel: typeof defaultPlaceholderLabel =\n  defaultPlaceholderLabel;\n\n/**\n * Default configuration of translatable strings.\n *\n * @group Defaults\n */\n// #region docs-translations\nexport const defaultTranslations: BaseTranslationsFull = {\n  fields: {\n    title: 'Field',\n    placeholderName: defaultPlaceholderFieldName,\n    placeholderLabel: defaultPlaceholderFieldLabel,\n    placeholderGroupLabel: defaultPlaceholderFieldGroupLabel,\n  } as const,\n  operators: {\n    title: 'Operator',\n    placeholderName: defaultPlaceholderOperatorName,\n    placeholderLabel: defaultPlaceholderOperatorLabel,\n    placeholderGroupLabel: defaultPlaceholderOperatorGroupLabel,\n  } as const,\n  values: {\n    title: 'Values',\n    placeholderName: defaultPlaceholderValueName,\n    placeholderLabel: defaultPlaceholderValueLabel,\n    placeholderGroupLabel: defaultPlaceholderValueGroupLabel,\n  } as const,\n  matchMode: { title: 'Match mode' } as const,\n  matchThreshold: { title: 'Match threshold' } as const,\n  value: { title: 'Value' } as const,\n  removeRule: { label: '⨯', title: 'Remove rule' } as const,\n  removeGroup: { label: '⨯', title: 'Remove group' } as const,\n  addRule: { label: '+ Rule', title: 'Add rule' } as const,\n  addGroup: { label: '+ Group', title: 'Add group' } as const,\n  combinators: { title: 'Combinator' } as const,\n  notToggle: { label: 'Not', title: 'Invert this group' } as const,\n  cloneRule: { label: '⧉', title: 'Clone rule' } as const,\n  cloneRuleGroup: { label: '⧉', title: 'Clone group' } as const,\n  shiftActionUp: { label: '˄', title: 'Shift up' } as const,\n  shiftActionDown: { label: '˅', title: 'Shift down' } as const,\n  dragHandle: { label: '⁞⁞', title: 'Drag handle' } as const,\n  lockRule: { label: '🔓', title: 'Lock rule' } as const,\n  lockGroup: { label: '🔓', title: 'Lock group' } as const,\n  lockRuleDisabled: { label: '🔒', title: 'Unlock rule' } as const,\n  lockGroupDisabled: { label: '🔒', title: 'Unlock group' } as const,\n  muteRule: { label: '🔊', title: 'Mute rule' } as const,\n  muteGroup: { label: '🔊', title: 'Mute group' } as const,\n  unmuteRule: { label: '🔇', title: 'Unmute rule' } as const,\n  unmuteGroup: { label: '🔇', title: 'Unmute group' } as const,\n  valueSourceSelector: { title: 'Value source' } as const,\n} satisfies BaseTranslationsFull;\n// #endregion\n\n/**\n * Default character used to `.join` and `.split` arrays.\n *\n * @group Defaults\n */\nexport const defaultJoinChar = ',';\n\nexport type DefaultOperators = StringUnionToFullOptionArray<DefaultOperatorName>;\n\nexport const defaultOperatorLabelMap: Record<DefaultOperatorName, string> = {\n  '=': '=',\n  '!=': '!=',\n  '<': '<',\n  '>': '>',\n  '<=': '<=',\n  '>=': '>=',\n  contains: 'contains',\n  beginsWith: 'begins with',\n  endsWith: 'ends with',\n  doesNotContain: 'does not contain',\n  doesNotBeginWith: 'does not begin with',\n  doesNotEndWith: 'does not end with',\n  null: 'is null',\n  notNull: 'is not null',\n  in: 'in',\n  notIn: 'not in',\n  between: 'between',\n  notBetween: 'not between',\n};\n\nexport const defaultCombinatorLabelMap: Record<DefaultCombinatorNameExtended, string> = {\n  and: 'AND',\n  or: 'OR',\n  xor: 'XOR',\n};\n\n/**\n * Default operator list.\n *\n * @group Defaults\n */\n// #region docs-operators\nexport const defaultOperators: DefaultOperators = [\n  { name: '=', value: '=', label: '=' },\n  { name: '!=', value: '!=', label: '!=' },\n  { name: '<', value: '<', label: '<' },\n  { name: '>', value: '>', label: '>' },\n  { name: '<=', value: '<=', label: '<=' },\n  { name: '>=', value: '>=', label: '>=' },\n  { name: 'contains', value: 'contains', label: 'contains' },\n  { name: 'beginsWith', value: 'beginsWith', label: 'begins with' },\n  { name: 'endsWith', value: 'endsWith', label: 'ends with' },\n  { name: 'doesNotContain', value: 'doesNotContain', label: 'does not contain' },\n  { name: 'doesNotBeginWith', value: 'doesNotBeginWith', label: 'does not begin with' },\n  { name: 'doesNotEndWith', value: 'doesNotEndWith', label: 'does not end with' },\n  { name: 'null', value: 'null', label: 'is null' },\n  { name: 'notNull', value: 'notNull', label: 'is not null' },\n  { name: 'in', value: 'in', label: 'in' },\n  { name: 'notIn', value: 'notIn', label: 'not in' },\n  { name: 'between', value: 'between', label: 'between' },\n  { name: 'notBetween', value: 'notBetween', label: 'not between' },\n];\n// #endregion\n\n/**\n * Map of default operators to their respective opposite/negating operators.\n *\n * @group Defaults\n */\nexport const defaultOperatorNegationMap: Record<DefaultOperatorName, DefaultOperatorName> = {\n  '=': '!=',\n  '!=': '=',\n  '<': '>=',\n  '<=': '>',\n  '>': '<=',\n  '>=': '<',\n  beginsWith: 'doesNotBeginWith',\n  doesNotBeginWith: 'beginsWith',\n  endsWith: 'doesNotEndWith',\n  doesNotEndWith: 'endsWith',\n  contains: 'doesNotContain',\n  doesNotContain: 'contains',\n  between: 'notBetween',\n  notBetween: 'between',\n  in: 'notIn',\n  notIn: 'in',\n  notNull: 'null',\n  null: 'notNull',\n} satisfies Record<DefaultOperatorName, DefaultOperatorName>;\n\nexport type DefaultCombinators = StringUnionToFullOptionArray<DefaultCombinatorName>;\n\n/**\n * Default combinator list.\n *\n * @group Defaults\n */\n// #region docs-combinators\nexport const defaultCombinators: DefaultCombinators = [\n  { name: 'and', value: 'and', label: 'AND' } as const,\n  { name: 'or', value: 'or', label: 'OR' } as const,\n];\n// #endregion\n\nexport type DefaultCombinatorsExtended =\n  StringUnionToFullOptionArray<DefaultCombinatorNameExtended>;\n\n/**\n * Default combinator list, with `XOR` added.\n *\n * @group Defaults\n */\nexport const defaultCombinatorsExtended: DefaultCombinatorsExtended = [\n  ...defaultCombinators,\n  { name: 'xor', value: 'xor', label: 'XOR' } as const,\n];\n\nexport type DefaultMatchModes = StringUnionToFullOptionArray<MatchMode>;\n\n/**\n * Default match modes.\n *\n * @group Defaults\n */\n// #region docs-matchmodes\nexport const defaultMatchModes: DefaultMatchModes = [\n  { name: 'all', value: 'all', label: 'all' },\n  { name: 'some', value: 'some', label: 'some' },\n  { name: 'none', value: 'none', label: 'none' },\n  { name: 'atLeast', value: 'atLeast', label: 'at least' },\n  { name: 'atMost', value: 'atMost', label: 'at most' },\n  { name: 'exactly', value: 'exactly', label: 'exactly' },\n];\n// #endregion\n\n/**\n * Standard classnames applied to each component.\n *\n * @group Defaults\n */\n// #region docs-standardclassnames\nexport const standardClassnames = {\n  queryBuilder: 'queryBuilder',\n  ruleGroup: 'ruleGroup',\n  header: 'ruleGroup-header',\n  body: 'ruleGroup-body',\n  combinators: 'ruleGroup-combinators',\n  addRule: 'ruleGroup-addRule',\n  addGroup: 'ruleGroup-addGroup',\n  cloneRule: 'rule-cloneRule',\n  cloneGroup: 'ruleGroup-cloneGroup',\n  removeGroup: 'ruleGroup-remove',\n  notToggle: 'ruleGroup-notToggle',\n  rule: 'rule',\n  fields: 'rule-fields',\n  matchMode: 'rule-matchMode',\n  matchThreshold: 'rule-matchThreshold',\n  operators: 'rule-operators',\n  value: 'rule-value',\n  removeRule: 'rule-remove',\n  betweenRules: 'betweenRules',\n  valid: 'queryBuilder-valid',\n  invalid: 'queryBuilder-invalid',\n  shiftActions: 'shiftActions',\n  dndDragging: 'dndDragging',\n  dndOver: 'dndOver',\n  dndCopy: 'dndCopy',\n  dndGroup: 'dndGroup',\n  dndDropNotAllowed: 'dndDropNotAllowed',\n  dragHandle: 'queryBuilder-dragHandle',\n  disabled: 'queryBuilder-disabled',\n  muted: 'queryBuilder-muted',\n  lockRule: 'rule-lock',\n  lockGroup: 'ruleGroup-lock',\n  muteRule: 'rule-mute',\n  muteGroup: 'ruleGroup-mute',\n  valueSource: 'rule-valueSource',\n  valueListItem: 'rule-value-list-item',\n  branches: 'queryBuilder-branches',\n  justified: 'queryBuilder-justified',\n  hasSubQuery: 'rule-hasSubQuery',\n} as const;\n// #endregion\n\n/**\n * Default classnames for each component.\n *\n * @group Defaults\n */\nexport const defaultControlClassnames: Classnames = {\n  queryBuilder: '',\n  ruleGroup: '',\n  header: '',\n  body: '',\n  combinators: '',\n  addRule: '',\n  addGroup: '',\n  cloneRule: '',\n  cloneGroup: '',\n  removeGroup: '',\n  notToggle: '',\n  rule: '',\n  fields: '',\n  matchMode: '',\n  matchThreshold: '',\n  operators: '',\n  value: '',\n  removeRule: '',\n  shiftActions: '',\n  dragHandle: '',\n  lockRule: '',\n  lockGroup: '',\n  muteRule: '',\n  muteGroup: '',\n  muted: '',\n  valueSource: '',\n  actionElement: '',\n  valueSelector: '',\n  betweenRules: '',\n  valid: '',\n  invalid: '',\n  dndDragging: '',\n  dndOver: '',\n  dndGroup: '',\n  dndCopy: '',\n  dndDropNotAllowed: '',\n  disabled: '',\n  valueListItem: '',\n  branches: '',\n  hasSubQuery: '',\n} satisfies Classnames;\n\n/**\n * Default reason codes for a group being invalid.\n *\n * @group Defaults\n */\nexport const groupInvalidReasons = {\n  empty: 'empty',\n  invalidCombinator: 'invalid combinator',\n  invalidIndependentCombinators: 'invalid independent combinators',\n} as const;\n\n/**\n * Component identifiers for testing.\n *\n * @group Defaults\n */\nexport const TestID = {\n  rule: 'rule',\n  ruleGroup: 'rule-group',\n  inlineCombinator: 'inline-combinator',\n  addGroup: 'add-group',\n  removeGroup: 'remove-group',\n  cloneGroup: 'clone-group',\n  cloneRule: 'clone-rule',\n  addRule: 'add-rule',\n  removeRule: 'remove-rule',\n  combinators: 'combinators',\n  fields: 'fields',\n  operators: 'operators',\n  valueEditor: 'value-editor',\n  notToggle: 'not-toggle',\n  shiftActions: 'shift-actions',\n  dragHandle: 'drag-handle',\n  lockRule: 'lock-rule',\n  lockGroup: 'lock-group',\n  muteRule: 'mute-rule',\n  muteGroup: 'mute-group',\n  valueSourceSelector: 'value-source-selector',\n  matchModeEditor: 'match-mode-editor',\n} as const;\n\nexport const LogType = {\n  parentPathDisabled: 'action aborted: parent path disabled',\n  pathDisabled: 'action aborted: path is disabled',\n  queryUpdate: 'query updated',\n  onAddRuleFalse: 'onAddRule callback returned false',\n  onAddGroupFalse: 'onAddGroup callback returned false',\n  onGroupRuleFalse: 'onGroupRule callback returned false',\n  onGroupGroupFalse: 'onGroupGroup callback returned false',\n  onMoveRuleFalse: 'onMoveRule callback returned false',\n  onMoveGroupFalse: 'onMoveGroup callback returned false',\n  onRemoveFalse: 'onRemove callback returned false',\n  add: 'rule or group added',\n  remove: 'rule or group removed',\n  update: 'rule or group updated',\n  move: 'rule or group moved',\n  group: 'rule or group grouped with another',\n} as const;\n\n/**\n * The {@link Path} of the root group.\n *\n * @group Defaults\n */\nexport const rootPath: Path = [] satisfies Path;\n\n/**\n * Default values for all `boolean`\n * {@link react-querybuilder!QueryBuilder QueryBuilder} options.\n *\n * @group Defaults\n */\nexport const queryBuilderFlagDefaults: Required<QueryBuilderFlags> = {\n  addRuleToNewGroups: false,\n  autoSelectField: true,\n  autoSelectOperator: true,\n  autoSelectValue: false,\n  debugMode: false,\n  enableDragAndDrop: false,\n  enableMountQueryChange: true,\n  listsAsArrays: false,\n  resetOnFieldChange: true,\n  resetOnOperatorChange: false,\n  showCloneButtons: false,\n  showCombinatorsBetweenRules: false,\n  showLockButtons: false,\n  showMuteButtons: false,\n  showNotToggle: false,\n  showShiftActions: false,\n  suppressStandardClassnames: false,\n};\n","// All code in this file is adapted from:\n// npm: https://www.npmjs.com/package/ts-extras\n// src: https://github.com/sindresorhus/ts-extras\n\n/**\n * Original looked like this (not sure why template string is used):\n * ```\n * type ObjectKeys<T extends object> = `${Exclude<keyof T, symbol>}`;\n * ```\n */\ntype ObjectKeys<T extends object> = Exclude<keyof T, symbol>;\n\n/**\n * A strongly-typed version of `Object.keys()`.\n *\n * [Original source](https://github.com/sindresorhus/ts-extras/blob/44f57392c5f027268330771996c4fdf9260b22d6/source/object-keys.ts)\n */\nexport const objectKeys = Object.keys as <Type extends object>(\n  value: Type\n) => Array<ObjectKeys<Type>>;\n\n/**\n * A strongly-typed version of `Object.entries()`.\n *\n * [Original source](https://github.com/sindresorhus/ts-extras/blob/44f57392c5f027268330771996c4fdf9260b22d6/source/object-entries.ts)\n */\nexport const objectEntries = Object.entries as <Type extends Record<PropertyKey, unknown>>(\n  value: Type\n) => Array<[ObjectKeys<Type>, Type[ObjectKeys<Type>]]>;\n","import type { Draft } from 'immer';\nimport { produce } from 'immer';\nimport type { RequireAtLeastOne } from 'type-fest';\nimport { defaultPlaceholderLabel, defaultPlaceholderName } from '../defaults';\nimport type {\n  BaseOption,\n  BaseOptionMap,\n  FlexibleOption,\n  FlexibleOptionGroup,\n  FlexibleOptionList,\n  FlexibleOptionListProp,\n  FullOption,\n  FullOptionList,\n  FullOptionMap,\n  FullOptionRecord,\n  GetOptionIdentifierType,\n  Option,\n  OptionGroup,\n  Placeholder,\n  ToFullOption,\n  ValueOption,\n  WithUnknownIndex,\n} from '../types';\nimport { isPojo } from './misc';\nimport { objectKeys } from './objectUtils';\n\nconst isOptionWithName = (opt: BaseOption): opt is Option =>\n  isPojo(opt) && 'name' in opt && typeof opt.name === 'string';\nconst isOptionWithValue = (opt: BaseOption): opt is ValueOption =>\n  isPojo(opt) && 'value' in opt && typeof opt.value === 'string';\n\n/**\n * Converts an {@link Option} or {@link ValueOption} (i.e., {@link BaseOption})\n * into a {@link FullOption}. Full options are left unchanged.\n *\n * @group Option Lists\n */\nexport function toFullOption<Opt extends BaseOption>(\n  opt: Opt | string,\n  baseProperties?: Record<string, unknown>,\n  labelMap?: Record<string, unknown>\n): ToFullOption<Opt> {\n  const recipe: (o: Opt | string) => ToFullOption<Opt> = produce(draft => {\n    const idObj: { name?: string; value?: string } = {};\n    let needsUpdating = !!baseProperties;\n\n    if (typeof draft === 'string') {\n      return {\n        ...baseProperties,\n        name: draft,\n        value: draft,\n        label: labelMap?.[draft] ?? draft,\n      } as Draft<Opt>;\n    }\n\n    if (isOptionWithName(draft) && !isOptionWithValue(draft)) {\n      idObj.value = draft.name;\n      needsUpdating = true;\n    } else if (!isOptionWithName(draft) && isOptionWithValue(draft)) {\n      idObj.name = draft.value;\n      needsUpdating = true;\n    }\n\n    if (needsUpdating) {\n      return Object.assign({}, baseProperties, draft, idObj);\n    }\n  });\n  return recipe(opt);\n}\n\n/**\n * Converts an {@link OptionList} or {@link FlexibleOptionList} into a {@link FullOptionList}.\n * Lists of full options are left unchanged.\n *\n * @group Option Lists\n */\nexport function toFullOptionList<Opt extends BaseOption>(\n  optList: unknown[],\n  baseProperties?: Record<string, unknown>,\n  labelMap?: Record<string, unknown>\n): FullOptionList<Opt> {\n  if (!Array.isArray(optList)) {\n    return [] as unknown as FullOptionList<Opt>;\n  }\n\n  const recipe: (ol: FlexibleOptionList<Opt>) => FullOptionList<Opt> = produce(draft => {\n    if (isFlexibleOptionGroupArray(draft)) {\n      for (const optGroup of draft) {\n        for (const [idx, opt] of optGroup.options.entries())\n          optGroup.options[idx] = toFullOption(opt, baseProperties, labelMap);\n      }\n    } else {\n      for (const [idx, opt] of (draft as Opt[]).entries())\n        draft[idx] = toFullOption(opt, baseProperties, labelMap);\n    }\n  });\n\n  return recipe(optList as FlexibleOptionList<Opt>);\n}\n\n/**\n * Converts a {@link FlexibleOptionList} into a {@link FullOptionList}.\n * Lists of full options are left unchanged.\n *\n * @group Option Lists\n */\nexport function toFullOptionMap<OptMap extends BaseOptionMap>(\n  optMap: OptMap,\n  baseProperties?: Record<string, unknown>\n): OptMap extends BaseOptionMap<infer V, infer K> ? Partial<Record<K, ToFullOption<V>>> : never {\n  type FullOptMapType =\n    OptMap extends BaseOptionMap<infer VT, infer KT>\n      ? Partial<Record<KT, ToFullOption<VT>>>\n      : never;\n\n  return Object.fromEntries(\n    (Object.entries(optMap) as [string, FlexibleOption][]).map(([k, v]) => [\n      k,\n      toFullOption(v, baseProperties),\n    ])\n  ) as FullOptMapType;\n}\n\n/**\n * @deprecated Renamed to {@link uniqByIdentifier}.\n *\n * @group Option Lists\n */\nexport const uniqByName = <\n  T extends { name: string; value?: string } | { name?: string; value: string },\n>(\n  originalArray: T[]\n): T[] => uniqByIdentifier(originalArray);\n\n/**\n * Generates a new array of objects with duplicates removed based\n * on the identifying property (`value` or `name`)\n *\n * @group Option Lists\n */\nexport const uniqByIdentifier = <\n  T extends RequireAtLeastOne<{ name: string; value: string }, 'name' | 'value'>,\n>(\n  originalArray: T[]\n): T[] => {\n  const names = new Set<string>();\n  const newArray: T[] = [];\n  for (const el of originalArray) {\n    if (!names.has((el.value ?? el.name)!)) {\n      names.add((el.value ?? el.name)!);\n      newArray.push(el);\n    }\n  }\n  return originalArray.length === newArray.length ? originalArray : newArray;\n};\n\n/**\n * Determines if an {@link OptionList} is an {@link OptionGroup} array.\n *\n * @group Option Lists\n */\n// oxlint-disable-next-line typescript/no-explicit-any\nexport const isOptionGroupArray = (arr: any): arr is OptionGroup<BaseOption>[] =>\n  Array.isArray(arr) &&\n  arr.length > 0 &&\n  isPojo(arr[0]) &&\n  'options' in arr[0] &&\n  Array.isArray(arr[0].options);\n\n/**\n * Determines if an array is a flat array of {@link FlexibleOption}.\n *\n * @group Option Lists\n */\n// oxlint-disable-next-line typescript/no-explicit-any\nexport const isFlexibleOptionArray = (arr: any): arr is FlexibleOption[] => {\n  let isFOA = false;\n  if (Array.isArray(arr)) {\n    for (const o of arr) {\n      if (isOptionWithName(o) || isOptionWithValue(o)) {\n        isFOA = true;\n      } else {\n        return false;\n      }\n    }\n  }\n  return isFOA;\n};\n\n/**\n * Determines if an array is a flat array of {@link FullOption}.\n *\n * @group Option Lists\n */\n// oxlint-disable-next-line typescript/no-explicit-any\nexport const isFullOptionArray = (arr: any): arr is FullOption[] => {\n  let isFOA = false;\n  if (Array.isArray(arr)) {\n    for (const o of arr) {\n      if (isOptionWithName(o) && isOptionWithValue(o)) {\n        isFOA = true;\n      } else {\n        return false;\n      }\n    }\n  }\n  return isFOA;\n};\n\n/**\n * Determines if a {@link FlexibleOptionList} is a {@link FlexibleOptionGroup} array.\n *\n * @group Option Lists\n */\nexport const isFlexibleOptionGroupArray = (\n  // oxlint-disable-next-line typescript/no-explicit-any\n  arr: any,\n  { allowEmpty = false }: { allowEmpty?: boolean } = {}\n): arr is FlexibleOptionGroup[] => {\n  let isFOGA = false;\n  if (Array.isArray(arr)) {\n    for (const og of arr) {\n      if (\n        isPojo(og) &&\n        'options' in og &&\n        (isFlexibleOptionArray(og.options) ||\n          (allowEmpty && Array.isArray(og.options) && og.options.length === 0))\n      ) {\n        isFOGA = true;\n      } else {\n        return false;\n      }\n    }\n  }\n  return isFOGA;\n};\n\n/**\n * Determines if a {@link FlexibleOptionList} is a {@link OptionGroup} array of {@link FullOption}.\n *\n * @group Option Lists\n */\nexport const isFullOptionGroupArray = (\n  // oxlint-disable-next-line typescript/no-explicit-any\n  arr: any,\n  { allowEmpty = false }: { allowEmpty?: boolean } = {}\n): arr is OptionGroup<FullOption>[] => {\n  let isFOGA = false;\n  if (Array.isArray(arr)) {\n    for (const og of arr) {\n      if (\n        isPojo(og) &&\n        'options' in og &&\n        (isFullOptionArray(og.options) ||\n          (allowEmpty && Array.isArray(og.options) && og.options.length === 0))\n      ) {\n        isFOGA = true;\n      } else {\n        return false;\n      }\n    }\n  }\n  return isFOGA;\n};\n\n/**\n * Gets the option from an {@link OptionList} with the given `name`. Handles\n * {@link Option} arrays as well as {@link OptionGroup} arrays.\n *\n * @group Option Lists\n */\nexport function getOption<OptType extends FullOption>(\n  arr: FullOptionList<OptType>,\n  name: string\n): OptType | undefined;\nexport function getOption<OptType extends ValueOption>(\n  arr: FlexibleOptionList<OptType>,\n  name: string\n): OptType | undefined;\nexport function getOption<OptType extends Option>(\n  arr: FlexibleOptionList<OptType>,\n  name: string\n): OptType | undefined;\nexport function getOption<OptType extends BaseOption>(\n  arr: FlexibleOptionList<OptType>,\n  name: string\n): OptType | undefined {\n  const options = isFlexibleOptionGroupArray(arr, { allowEmpty: true })\n    ? arr.flatMap(og => og.options)\n    : arr;\n  return options.find(op => op.value === name || op.name === name) as OptType | undefined;\n}\n\n/**\n * Gets the first option from an {@link OptionList}.\n *\n * @group Option Lists\n */\nexport function getFirstOption<Opt extends FullOption>(\n  arr?: OptionGroup<Opt>[] | Opt[]\n): GetOptionIdentifierType<Opt> | null;\nexport function getFirstOption<Opt extends ValueOption>(\n  arr?: OptionGroup<Opt>[] | Opt[]\n): GetOptionIdentifierType<Opt> | null;\nexport function getFirstOption<Opt extends Option>(\n  arr?: OptionGroup<Opt>[] | Opt[]\n): GetOptionIdentifierType<Opt> | null;\nexport function getFirstOption<Opt extends BaseOption>(\n  arr?: FlexibleOptionGroup<Opt>[] | Opt[]\n): GetOptionIdentifierType<Opt> | null {\n  if (!Array.isArray(arr) || arr.length === 0) {\n    return null;\n  } else if (isFlexibleOptionGroupArray(arr, { allowEmpty: true })) {\n    for (const og of arr) {\n      if (og.options.length > 0) {\n        return (og.options[0].value ?? og.options[0].name) as GetOptionIdentifierType<Opt>;\n      }\n    }\n    // istanbul ignore next\n    return null;\n  }\n\n  return (arr[0].value ?? arr[0].name) as GetOptionIdentifierType<Opt>;\n}\n\n/**\n * Flattens {@link FlexibleOptionGroup} arrays into {@link BaseOption} arrays.\n * If the array is already flat, it is returned as is.\n *\n * @group Option Lists\n */\nexport const toFlatOptionArray = <T extends FullOption, OL extends FullOptionList<T>>(arr: OL) =>\n  uniqByIdentifier(isOptionGroupArray(arr) ? arr.flatMap(og => og.options) : arr) as T[];\n\n/**\n * Generates a new {@link OptionGroup} array with duplicates\n * removed based on the identifying property (`value` or `name`).\n *\n * @group Option Lists\n */\nexport const uniqOptGroups = <T extends BaseOption>(\n  originalArray: FlexibleOptionGroup<T>[]\n): OptionGroup<ToFullOption<T>>[] => {\n  type K = T extends BaseOption<infer KT> ? KT : never;\n  const labels = new Set<string>();\n  const names = new Set<K>();\n  const newArray: OptionGroup<ToFullOption<T>>[] = [];\n  for (const el of originalArray) {\n    if (!labels.has(el.label)) {\n      labels.add(el.label);\n      const optionsForThisGroup: WithUnknownIndex<ToFullOption<T>>[] = [];\n      for (const opt of el.options) {\n        if (!names.has((opt.value ?? opt.name) as K)) {\n          names.add((opt.value ?? opt.name) as K);\n          optionsForThisGroup.push(toFullOption(opt) as WithUnknownIndex<ToFullOption<T>>);\n        }\n      }\n      newArray.push({ ...el, options: optionsForThisGroup });\n    }\n  }\n  return newArray;\n};\n\n/**\n * Generates a new {@link Option} or {@link OptionGroup} array with duplicates\n * removed based on the identifier property (`value` or `name`).\n *\n * @group Option Lists\n */\nexport const uniqOptList = <T extends BaseOption>(\n  originalArray: FlexibleOptionList<T>\n): WithUnknownIndex<BaseOption & FullOption>[] | OptionGroup<ToFullOption<T>>[] => {\n  if (isFlexibleOptionGroupArray(originalArray)) {\n    return uniqOptGroups(originalArray) as OptionGroup<ToFullOption<T>>[];\n  }\n  return uniqByIdentifier((originalArray as BaseOption[]).map(o => toFullOption(o)));\n};\n\nexport interface PreparedOptionList<O extends FullOption> {\n  defaultOption: FullOption;\n  optionList: O[] | OptionGroup<O>[];\n  optionsMap: Partial<FullOptionRecord<FullOption>>;\n}\n\nexport interface PrepareOptionListParams<O extends FullOption> {\n  placeholder?: Placeholder;\n  optionList?: FlexibleOptionListProp<O> | BaseOptionMap<O>;\n  baseOption?: Record<string, unknown>;\n  labelMap?: Record<string, string>;\n  autoSelectOption?: boolean;\n}\n\nexport const prepareOptionList = <O extends FullOption>(\n  props: PrepareOptionListParams<O>\n): PreparedOptionList<O> => {\n  type OptionIdentifier = GetOptionIdentifierType<O>;\n\n  // istanbul ignore next\n  const {\n    optionList: optionListPropOriginal,\n    baseOption = {},\n    labelMap = {},\n    placeholder: {\n      placeholderName = defaultPlaceholderName,\n      placeholderLabel = defaultPlaceholderLabel,\n      placeholderGroupLabel = defaultPlaceholderLabel,\n    } = {},\n    autoSelectOption = true,\n  } = props;\n\n  const defaultOption = {\n    id: placeholderName,\n    name: placeholderName,\n    value: placeholderName,\n    label: placeholderLabel,\n  } as FullOption;\n\n  const optionsProp = optionListPropOriginal ?? ([defaultOption] as FlexibleOptionList<O>);\n\n  let optionList: O[] | OptionGroup<O>[] = [];\n  const opts = (\n    Array.isArray(optionsProp)\n      ? toFullOptionList(optionsProp, baseOption, labelMap)\n      : (objectKeys(toFullOptionMap(optionsProp, baseOption)) as unknown as OptionIdentifier[])\n          .map<FullOption<OptionIdentifier>>(opt => ({\n            ...optionsProp[opt]!,\n            name: opt,\n            value: opt,\n          }))\n          // oxlint-disable-next-line no-array-sort\n          .sort((a, b) => a.label.localeCompare(b.label))\n  ) as FullOptionList<O>;\n  if (isFlexibleOptionGroupArray(opts)) {\n    optionList = autoSelectOption\n      ? (uniqOptGroups(opts) as FullOptionList<O>)\n      : (uniqOptGroups([\n          {\n            label: placeholderGroupLabel,\n            options: [defaultOption],\n          },\n          ...opts,\n        ]) as FullOptionList<O>);\n  } else {\n    optionList = autoSelectOption\n      ? (uniqByIdentifier(opts as O[]) as FullOptionList<O>)\n      : (uniqByIdentifier([defaultOption, ...(opts as O[])]) as FullOptionList<O>);\n  }\n\n  let optionsMap: Partial<FullOptionRecord<FullOption>> = {};\n  if (!Array.isArray(optionsProp)) {\n    const op = toFullOptionMap(optionsProp, baseOption) as FullOptionMap<\n      FullOption,\n      OptionIdentifier\n    >;\n    optionsMap = autoSelectOption ? op : { ...op, [placeholderName]: defaultOption };\n  } else {\n    if (isFlexibleOptionGroupArray(optionList)) {\n      for (const og of optionList) {\n        for (const opt of og.options) {\n          optionsMap[(opt.value ?? /* istanbul ignore next */ opt.name) as OptionIdentifier] =\n            toFullOption(opt, baseOption) as FullOption;\n        }\n      }\n    } else {\n      for (const opt of optionList) {\n        optionsMap[(opt.value ?? /* istanbul ignore next */ opt.name) as OptionIdentifier] =\n          toFullOption(opt, baseOption) as FullOption;\n      }\n    }\n  }\n\n  return { defaultOption, optionList, optionsMap };\n};\n"],"mappings":"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"}