@12-apps/ui 6.45.2 → 6.45.4

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.
Files changed (26) hide show
  1. package/dist/_internal/components/form/Autocomplete/Autocomplete.js +2 -2
  2. package/dist/_internal/components/form/Autocomplete/useAutocomplete.js +1 -1
  3. package/dist/_internal/components/form/index.js +2 -2
  4. package/dist/_internal/components/index.js +5 -5
  5. package/dist/_internal/components/utility/WorkflowStep/WorkflowStep.js +3 -3
  6. package/dist/_internal/components/utility/WorkflowStep/WorkflowStep.parts.js +1 -1
  7. package/dist/_internal/components/utility/WorkflowStep/WorkflowStepRow.js +2 -2
  8. package/dist/_internal/components/utility/index.js +3 -3
  9. package/dist/{chunk-PXGURBIU.js → chunk-JBGCGYEC.js} +2 -2
  10. package/dist/{chunk-6S25ZCEW.js → chunk-KNWG77FB.js} +5 -5
  11. package/dist/chunk-KNWG77FB.js.map +1 -0
  12. package/dist/{chunk-JHW62I7Z.js → chunk-LOLR2BWW.js} +2 -2
  13. package/dist/{chunk-Y6RSQEOU.js → chunk-LV4WSWQZ.js} +2 -2
  14. package/dist/{chunk-YWJZPN5C.js → chunk-SY5FYBAF.js} +4 -4
  15. package/dist/chunk-SY5FYBAF.js.map +1 -0
  16. package/dist/form/Autocomplete.js +2 -2
  17. package/dist/types/components/form/Autocomplete/useAutocomplete.d.ts.map +1 -1
  18. package/dist/utility/WorkflowStep.js +3 -3
  19. package/package.json +1 -1
  20. package/src/components/form/Autocomplete/useAutocomplete.ts +14 -7
  21. package/src/components/utility/WorkflowStep/WorkflowStep.parts.tsx +4 -4
  22. package/dist/chunk-6S25ZCEW.js.map +0 -1
  23. package/dist/chunk-YWJZPN5C.js.map +0 -1
  24. /package/dist/{chunk-PXGURBIU.js.map → chunk-JBGCGYEC.js.map} +0 -0
  25. /package/dist/{chunk-JHW62I7Z.js.map → chunk-LOLR2BWW.js.map} +0 -0
  26. /package/dist/{chunk-Y6RSQEOU.js.map → chunk-LV4WSWQZ.js.map} +0 -0
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  Autocomplete,
3
3
  Autocomplete_default
4
- } from "../../../../chunk-PXGURBIU.js";
4
+ } from "../../../../chunk-JBGCGYEC.js";
5
5
  import "../../../../chunk-XBLFK2FL.js";
6
- import "../../../../chunk-YWJZPN5C.js";
6
+ import "../../../../chunk-SY5FYBAF.js";
7
7
  import "../../../../chunk-PELRSZFU.js";
8
8
  import "../../../../chunk-JXS56EW5.js";
9
9
  import "../../../../chunk-M47ZOUGF.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  useAutocomplete
3
- } from "../../../../chunk-YWJZPN5C.js";
3
+ } from "../../../../chunk-SY5FYBAF.js";
4
4
  import "../../../../chunk-PELRSZFU.js";
5
5
  import "../../../../chunk-JXS56EW5.js";
6
6
  import "../../../../chunk-PZ5AY32C.js";
@@ -146,9 +146,9 @@ import "../../../chunk-O7QPPJAK.js";
146
146
  import "../../../chunk-2LXHUGYB.js";
147
147
  import {
148
148
  Autocomplete
149
- } from "../../../chunk-PXGURBIU.js";
149
+ } from "../../../chunk-JBGCGYEC.js";
150
150
  import "../../../chunk-XBLFK2FL.js";
151
- import "../../../chunk-YWJZPN5C.js";
151
+ import "../../../chunk-SY5FYBAF.js";
152
152
  import "../../../chunk-PELRSZFU.js";
153
153
  import "../../../chunk-JXS56EW5.js";
154
154
  import "../../../chunk-BO6S47KI.js";
@@ -28,9 +28,9 @@ import "../../chunk-PVM7XTLZ.js";
28
28
  import "../../chunk-IO36MEBD.js";
29
29
  import {
30
30
  WorkflowStep
31
- } from "../../chunk-JHW62I7Z.js";
32
- import "../../chunk-Y6RSQEOU.js";
33
- import "../../chunk-6S25ZCEW.js";
31
+ } from "../../chunk-LOLR2BWW.js";
32
+ import "../../chunk-LV4WSWQZ.js";
33
+ import "../../chunk-KNWG77FB.js";
34
34
  import "../../chunk-TM5QQJTF.js";
35
35
  import {
36
36
  Paragraph
@@ -387,9 +387,9 @@ import "../../chunk-O7QPPJAK.js";
387
387
  import "../../chunk-2LXHUGYB.js";
388
388
  import {
389
389
  Autocomplete
390
- } from "../../chunk-PXGURBIU.js";
390
+ } from "../../chunk-JBGCGYEC.js";
391
391
  import "../../chunk-XBLFK2FL.js";
392
- import "../../chunk-YWJZPN5C.js";
392
+ import "../../chunk-SY5FYBAF.js";
393
393
  import "../../chunk-PELRSZFU.js";
394
394
  import "../../chunk-JXS56EW5.js";
395
395
  import "../../chunk-BO6S47KI.js";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  WorkflowStep,
3
3
  WorkflowStep_default
4
- } from "../../../../chunk-JHW62I7Z.js";
5
- import "../../../../chunk-Y6RSQEOU.js";
6
- import "../../../../chunk-6S25ZCEW.js";
4
+ } from "../../../../chunk-LOLR2BWW.js";
5
+ import "../../../../chunk-LV4WSWQZ.js";
6
+ import "../../../../chunk-KNWG77FB.js";
7
7
  import "../../../../chunk-TM5QQJTF.js";
8
8
  import "../../../../chunk-FHWXRHMA.js";
9
9
  import "../../../../chunk-7ZPUN7TV.js";
@@ -3,7 +3,7 @@ import {
3
3
  StepContentComponent,
4
4
  StepIndicatorComponent,
5
5
  StepItemRow
6
- } from "../../../../chunk-6S25ZCEW.js";
6
+ } from "../../../../chunk-KNWG77FB.js";
7
7
  import "../../../../chunk-TM5QQJTF.js";
8
8
  import "../../../../chunk-FHWXRHMA.js";
9
9
  import "../../../../chunk-7ZPUN7TV.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  StepRow
3
- } from "../../../../chunk-Y6RSQEOU.js";
4
- import "../../../../chunk-6S25ZCEW.js";
3
+ } from "../../../../chunk-LV4WSWQZ.js";
4
+ import "../../../../chunk-KNWG77FB.js";
5
5
  import "../../../../chunk-TM5QQJTF.js";
6
6
  import "../../../../chunk-FHWXRHMA.js";
7
7
  import "../../../../chunk-7ZPUN7TV.js";
@@ -17,9 +17,9 @@ import "../../../chunk-PVM7XTLZ.js";
17
17
  import "../../../chunk-IO36MEBD.js";
18
18
  import {
19
19
  WorkflowStep
20
- } from "../../../chunk-JHW62I7Z.js";
21
- import "../../../chunk-Y6RSQEOU.js";
22
- import "../../../chunk-6S25ZCEW.js";
20
+ } from "../../../chunk-LOLR2BWW.js";
21
+ import "../../../chunk-LV4WSWQZ.js";
22
+ import "../../../chunk-KNWG77FB.js";
23
23
  import "../../../chunk-TM5QQJTF.js";
24
24
  import "../../../chunk-H2PTB6FD.js";
25
25
  import {
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-XBLFK2FL.js";
7
7
  import {
8
8
  useAutocomplete
9
- } from "./chunk-YWJZPN5C.js";
9
+ } from "./chunk-SY5FYBAF.js";
10
10
  import {
11
11
  defaultGetKey,
12
12
  defaultGetLabel,
@@ -131,4 +131,4 @@ export {
131
131
  Autocomplete,
132
132
  Autocomplete_default
133
133
  };
134
- //# sourceMappingURL=chunk-PXGURBIU.js.map
134
+ //# sourceMappingURL=chunk-JBGCGYEC.js.map
@@ -178,18 +178,18 @@ var StepIndicatorComponent = forwardRef(({
178
178
  }, ref) => {
179
179
  const isDisabled = Boolean(disabled || step.disabled);
180
180
  const handleClick = useCallback(() => {
181
- if (interactive && !disabled && onClick) {
181
+ if (interactive && !isDisabled && onClick) {
182
182
  onClick(index, step);
183
183
  }
184
- }, [interactive, disabled, onClick, index, step]);
184
+ }, [interactive, isDisabled, onClick, index, step]);
185
185
  const handleKeyDown = useCallback((event) => {
186
- if (interactive && !disabled && (event.key === "Enter" || event.key === " ")) {
186
+ if (interactive && !isDisabled && (event.key === "Enter" || event.key === " ")) {
187
187
  event.preventDefault();
188
188
  if (onClick) {
189
189
  onClick(index, step);
190
190
  }
191
191
  }
192
- }, [interactive, disabled, onClick, index, step]);
192
+ }, [interactive, isDisabled, onClick, index, step]);
193
193
  const renderIndicatorContent = () => {
194
194
  if (isError && errorIcon) {
195
195
  return errorIcon;
@@ -283,4 +283,4 @@ export {
283
283
  StepContentComponent,
284
284
  StepItemRow
285
285
  };
286
- //# sourceMappingURL=chunk-6S25ZCEW.js.map
286
+ //# sourceMappingURL=chunk-KNWG77FB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/utility/WorkflowStep/WorkflowStep.parts.tsx"],"sourcesContent":["import Box from '@mui/material/Box/index.js';\nimport type { CSSObject, Theme } from '@mui/material/styles/index.js';\nimport { styled } from '@mui/material/styles/index.js';\nimport React, { forwardRef, useCallback } from 'react';\n\nimport type { StepColors } from './WorkflowStep.helpers';\nimport { indicatorSizeFor, stepColors, stepPalette } from './WorkflowStep.helpers';\nimport type {\n StepConnectorProps,\n StepContentProps,\n StepIndicatorProps,\n WorkflowStepProps,\n} from './WorkflowStep.types';\nimport { neutralTones } from '../../../tokens/ink';\nimport { rem } from '../../../tokens/relative';\n\n// `outlined` shows the surface through a coloured rim; the other three fill it and\n// differ only in what border they keep.\nconst indicatorVariantStyles = (\n theme: Theme,\n variant: WorkflowStepProps['variant'],\n { backgroundColor, borderColor, textColor }: StepColors,\n): CSSObject => {\n if (variant === 'outlined') {\n return {\n border: `${rem(theme, 2)} solid ${borderColor}`,\n backgroundColor: theme.palette.background.paper,\n };\n }\n\n const filled = { backgroundColor, color: textColor };\n\n switch (variant) {\n case 'filled':\n return filled;\n case 'minimal':\n return { ...filled, border: 'none' };\n case 'default':\n return { ...filled, border: `1px solid ${borderColor}` };\n default:\n return {};\n }\n};\n\nconst StepItem = styled(Box, {\n shouldForwardProp: (prop) => !['orientation', 'isLast'].includes(prop as string),\n})<{\n orientation: WorkflowStepProps['orientation'];\n isLast: boolean;\n}>(({ orientation, isLast }) => ({\n display: 'flex',\n flexDirection: orientation === 'vertical' ? 'column' : 'row',\n alignItems: orientation === 'vertical' ? 'flex-start' : 'center',\n flex: orientation === 'horizontal' && !isLast ? 1 : 'none',\n position: 'relative',\n minWidth: 0, // Allow content to shrink\n}));\n\nconst StepIndicator = styled(Box, {\n shouldForwardProp: (prop) => !['size', 'variant', 'color', 'isActive', 'isCompleted', 'isError', 'interactive', 'animated', 'disabled'].includes(prop as string),\n})<{\n size: WorkflowStepProps['size'];\n variant: WorkflowStepProps['variant'];\n color: WorkflowStepProps['color'];\n isActive: boolean;\n isCompleted: boolean;\n isError: boolean;\n interactive: boolean;\n animated: boolean;\n disabled: boolean;\n}>(({ theme, size, variant, color, isActive, isCompleted, isError, interactive, animated, disabled }) => {\n const indicatorSize = indicatorSizeFor(size);\n const palette = stepPalette(theme, color);\n const { backgroundColor, borderColor, textColor } = stepColors(theme, palette, {\n isActive,\n isCompleted,\n isError,\n variant,\n });\n\n return {\n width: rem(theme, indicatorSize),\n height: rem(theme, indicatorSize),\n borderRadius: '50%',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: rem(theme, 12),\n fontWeight: theme.typography.fontWeightMedium,\n cursor: interactive && !disabled ? 'pointer' : 'default',\n transition: animated\n ? theme.transitions.create(['background-color', 'border-color', 'transform'], {\n duration: theme.transitions.duration.short,\n })\n : 'none',\n flexShrink: 0,\n\n ...indicatorVariantStyles(theme, variant, { backgroundColor, borderColor, textColor }),\n\n // Interactive states\n ...(interactive && !disabled && {\n '&:hover': {\n transform: 'scale(1.1)',\n boxShadow: theme.shadows[2],\n },\n '&:focus-visible': {\n outline: `${rem(theme, 2)} solid ${palette.main}`,\n outlineOffset: rem(theme, 2),\n },\n }),\n\n // Disabled state\n ...(disabled && {\n opacity: 0.5,\n cursor: 'not-allowed',\n }),\n };\n});\n\nconst StepContent = styled(Box, {\n shouldForwardProp: (prop) => !['orientation', 'interactive', 'disabled'].includes(prop as string),\n})<{\n orientation: WorkflowStepProps['orientation'];\n interactive: boolean;\n disabled: boolean;\n}>(({ theme, orientation, disabled }) => ({\n display: 'flex',\n flexDirection: 'column',\n alignItems: orientation === 'vertical' ? 'flex-start' : 'center',\n textAlign: orientation === 'vertical' ? 'left' : 'center',\n marginTop: orientation === 'vertical' ? theme.spacing(1) : theme.spacing(0.5),\n marginLeft: orientation === 'horizontal' ? theme.spacing(1) : 0,\n // Inert (FUT-2773): the content block has no click handling of its own —\n // the indicator is the step's one interactive element — so its cursor\n // never claims to be clickable, whatever `interactive` says.\n cursor: 'default',\n minWidth: 0,\n flex: 1,\n\n '& .step-title': {\n fontSize: rem(theme, 14),\n fontWeight: theme.typography.fontWeightMedium,\n color: theme.palette.text.primary,\n marginBottom: theme.spacing(0.5),\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n maxWidth: '100%',\n },\n\n '& .step-description': {\n fontSize: rem(theme, 12),\n color: theme.palette.text.secondary,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n maxWidth: '100%',\n },\n\n ...(disabled && {\n opacity: 0.5,\n }),\n}));\n\nconst StepConnector = styled(Box, {\n shouldForwardProp: (prop) => !['orientation', 'isCompleted', 'color', 'variant', 'animated'].includes(prop as string),\n})<{\n orientation: WorkflowStepProps['orientation'];\n isCompleted: boolean;\n color: WorkflowStepProps['color'];\n variant: WorkflowStepProps['variant'];\n animated: boolean;\n}>(({ theme, orientation, isCompleted, color, variant, animated }) => {\n const connectorColor = isCompleted ? stepPalette(theme, color).main : neutralTones(theme).track;\n\n return {\n flex: 1,\n position: 'relative',\n\n ...(orientation === 'horizontal' && {\n height: rem(theme, 2),\n backgroundColor: connectorColor,\n margin: `0 ${theme.spacing(1)}`,\n minWidth: theme.spacing(2),\n }),\n\n ...(orientation === 'vertical' && {\n width: rem(theme, 2),\n backgroundColor: connectorColor,\n minHeight: theme.spacing(3),\n marginLeft: theme.spacing(2),\n position: 'absolute',\n left: '50%',\n transform: 'translateX(-50%)',\n top: '100%',\n }),\n\n transition: animated\n ? theme.transitions.create('background-color', {\n duration: theme.transitions.duration.short,\n })\n : 'none',\n\n ...(variant === 'minimal' && {\n opacity: 0.6,\n }),\n };\n});\n\n/**\n * Individual step indicator component\n */\nconst StepIndicatorComponent = forwardRef<HTMLDivElement, StepIndicatorProps>(({\n step,\n index,\n isActive,\n isCompleted,\n isError,\n variant,\n color,\n size,\n showNumbers,\n showIcons,\n completedIcon,\n errorIcon,\n interactive,\n animated,\n disabled,\n onClick,\n 'data-testid': dataTestId,\n}, ref) => {\n const isDisabled = Boolean(disabled || step.disabled);\n\n const handleClick = useCallback(() => {\n if (interactive && !isDisabled && onClick) {\n onClick(index, step);\n }\n }, [interactive, isDisabled, onClick, index, step]);\n\n const handleKeyDown = useCallback((event: React.KeyboardEvent) => {\n if (interactive && !isDisabled && (event.key === 'Enter' || event.key === ' ')) {\n event.preventDefault();\n if (onClick) {\n onClick(index, step);\n }\n }\n }, [interactive, isDisabled, onClick, index, step]);\n\n const renderIndicatorContent = () => {\n if (isError && errorIcon) {\n return errorIcon;\n }\n if (isCompleted && completedIcon) {\n return completedIcon;\n }\n if (showIcons && step.icon) {\n return step.icon;\n }\n if (showNumbers) {\n return index + 1;\n }\n return null;\n };\n\n return (\n <StepIndicator\n ref={ref}\n size={size}\n variant={variant}\n color={color}\n isActive={isActive}\n isCompleted={isCompleted}\n isError={isError}\n interactive={interactive}\n animated={animated}\n disabled={isDisabled}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n role={interactive ? 'button' : undefined}\n tabIndex={!interactive ? undefined : isDisabled ? -1 : 0}\n aria-label={`Step ${index + 1}: ${step.title}`}\n aria-current={isActive ? 'step' : undefined}\n aria-disabled={interactive && isDisabled ? true : undefined}\n data-testid={dataTestId}\n >\n {renderIndicatorContent()}\n </StepIndicator>\n );\n});\n\nStepIndicatorComponent.displayName = 'StepIndicator';\n\n/**\n * Step connector component\n */\nconst StepConnectorComponent = forwardRef<HTMLDivElement, StepConnectorProps>(({\n isCompleted,\n orientation,\n variant,\n color,\n // Defaults to the connector's own prior, unconditional behaviour (FUT-2773):\n // an external caller building a `StepConnectorProps` value that predates\n // this field keeps the transition it always had.\n animated = true,\n 'data-testid': dataTestId,\n}, ref) => (\n <StepConnector\n ref={ref}\n orientation={orientation}\n isCompleted={isCompleted}\n color={color}\n variant={variant}\n animated={animated}\n data-testid={dataTestId}\n />\n));\n\nStepConnectorComponent.displayName = 'StepConnector';\n\n/**\n * Step content component.\n *\n * Inert on purpose (FUT-2773): the indicator is the step's one focusable\n * `role=\"button\"` element — it already carries `aria-label=\"Step N: <title>\"`\n * — so the title/description block gets no `role`, `tabIndex`, click or key\n * handling of its own. Two independently-interactive elements per step gave\n * assistive tech two tab stops for what a caller means as a single control.\n */\nconst StepContentComponent = forwardRef<HTMLDivElement, StepContentProps>(({\n step,\n orientation,\n interactive,\n disabled,\n 'data-testid': dataTestId,\n}, ref) => (\n <StepContent\n ref={ref}\n orientation={orientation}\n interactive={interactive}\n disabled={Boolean(disabled || step.disabled)}\n data-testid={dataTestId}\n >\n <div className=\"step-title\">{step.title}</div>\n {step.description && (\n <div className=\"step-description\">{step.description}</div>\n )}\n </StepContent>\n));\n\nStepContentComponent.displayName = 'StepContent';\n\n/**\n * A plain wrapper around the styled row. Exporting the styled component itself\n * trips TS2742 — its inferred type names a pnpm-internal @mui/system path.\n */\nexport const StepItemRow: React.FC<{\n orientation: WorkflowStepProps['orientation'];\n isLast: boolean;\n children: React.ReactNode;\n}> = ({ orientation, isLast, children }) => (\n <StepItem orientation={orientation} isLast={isLast}>\n {children}\n </StepItem>\n);\n\nexport { StepConnectorComponent, StepContentComponent, StepIndicatorComponent };\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  StepRow
3
- } from "./chunk-Y6RSQEOU.js";
3
+ } from "./chunk-LV4WSWQZ.js";
4
4
  import {
5
5
  progressValueRange,
6
6
  progressValueText,
@@ -107,4 +107,4 @@ export {
107
107
  WorkflowStep,
108
108
  WorkflowStep_default
109
109
  };
110
- //# sourceMappingURL=chunk-JHW62I7Z.js.map
110
+ //# sourceMappingURL=chunk-LOLR2BWW.js.map
@@ -3,7 +3,7 @@ import {
3
3
  StepContentComponent,
4
4
  StepIndicatorComponent,
5
5
  StepItemRow
6
- } from "./chunk-6S25ZCEW.js";
6
+ } from "./chunk-KNWG77FB.js";
7
7
 
8
8
  // src/components/utility/WorkflowStep/WorkflowStepRow.tsx
9
9
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -79,4 +79,4 @@ var StepRow = ({
79
79
  export {
80
80
  StepRow
81
81
  };
82
- //# sourceMappingURL=chunk-Y6RSQEOU.js.map
82
+ //# sourceMappingURL=chunk-LV4WSWQZ.js.map
@@ -163,15 +163,15 @@ function commitMultiSelect(item, p, s, onChange) {
163
163
  onChange("");
164
164
  setDeliberateClose(s, false);
165
165
  }
166
- function commitSingleSelect(item, p, s, onChange) {
166
+ function commitSingleSelect(item, p, s) {
167
167
  const label = (p.getLabel ?? defaultGetLabel)(item);
168
168
  s.setInputValue(label);
169
- onChange(label);
169
+ p.onChange(label);
170
170
  }
171
171
  function commitPick(item, linkUrl, p, s, onChange) {
172
172
  if (linkUrl !== null) (p.openLink ?? defaultOpenLink)(linkUrl, item);
173
173
  else if (p.multiple) commitMultiSelect(item, p, s, onChange);
174
- else commitSingleSelect(item, p, s, onChange);
174
+ else commitSingleSelect(item, p, s);
175
175
  }
176
176
  function runSelectItem(item, p, s, onChange) {
177
177
  const url = (p.getUrl ?? defaultGetUrl)(item);
@@ -284,4 +284,4 @@ function useAutocomplete(p) {
284
284
  export {
285
285
  useAutocomplete
286
286
  };
287
- //# sourceMappingURL=chunk-YWJZPN5C.js.map
287
+ //# sourceMappingURL=chunk-SY5FYBAF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/form/Autocomplete/useAutocomplete.ts"],"sourcesContent":["import { useEffect, useId, useRef, useState } from 'react';\n\nimport {\n defaultGetKey,\n defaultGetLabel,\n defaultGetSuggestionType,\n defaultGetUrl,\n defaultOpenLink,\n filterSuggestions,\n firstGhostSuggestion,\n type MatchMode,\n} from './Autocomplete.helpers';\nimport { handleAutocompleteKey, type KeyContext } from './Autocomplete.keys';\nimport type { AutocompleteProps } from './Autocomplete.types';\n\ntype Setter<V> = React.Dispatch<React.SetStateAction<V>>;\n\n/** All mutable state + refs for one Autocomplete instance. */\ninterface AutocompleteState<T> {\n open: boolean;\n setOpen: Setter<boolean>;\n activeIndex: number;\n setActiveIndex: Setter<number>;\n ghost: string;\n setGhost: Setter<string>;\n inputValue: string;\n setInputValue: Setter<string>;\n composition: boolean;\n setComposition: Setter<boolean>;\n filteredSuggestions: T[];\n setFilteredSuggestions: Setter<T[]>;\n isInputFocused: boolean;\n setIsInputFocused: Setter<boolean>;\n justCompletedGhost: boolean;\n setJustCompletedGhost: Setter<boolean>;\n userClosedDropdown: boolean;\n setUserClosedDropdown: Setter<boolean>;\n /**\n * Mirrors `userClosedDropdown`, set synchronously wherever the state is\n * (see {@link setDeliberateClose}). An effect scheduled by one render and\n * flushed after a LATER render has already changed this flag reads a\n * stale, closed-over `userClosedDropdown` — but `.current` on a ref is\n * dereferenced live, so it always reflects the latest write regardless of\n * which render's closure is doing the reading (FUT-2780).\n */\n userClosedDropdownRef: React.RefObject<boolean>;\n inputRef: React.RefObject<HTMLInputElement | null>;\n listRef: React.RefObject<HTMLUListElement | null>;\n debounceRef: React.RefObject<number | undefined>;\n}\n\nfunction useAutocompleteState<T>(value: string, suggestions: T[]): AutocompleteState<T> {\n const [open, setOpen] = useState(false);\n const [activeIndex, setActiveIndex] = useState(-1);\n const [ghost, setGhost] = useState('');\n const [inputValue, setInputValue] = useState(value);\n const [composition, setComposition] = useState(false);\n const [filteredSuggestions, setFilteredSuggestions] = useState<T[]>(suggestions);\n const [isInputFocused, setIsInputFocused] = useState(false);\n const [justCompletedGhost, setJustCompletedGhost] = useState(false);\n const [userClosedDropdown, setUserClosedDropdown] = useState(false);\n const userClosedDropdownRef = useRef(false);\n const inputRef = useRef<HTMLInputElement>(null);\n const listRef = useRef<HTMLUListElement | null>(null);\n const debounceRef = useRef<number | undefined>(undefined);\n return {\n open, setOpen, activeIndex, setActiveIndex, ghost, setGhost, inputValue, setInputValue,\n composition, setComposition, filteredSuggestions, setFilteredSuggestions, isInputFocused,\n setIsInputFocused, justCompletedGhost, setJustCompletedGhost, userClosedDropdown,\n setUserClosedDropdown, userClosedDropdownRef, inputRef, listRef, debounceRef,\n };\n}\n\n/**\n * Set the \"this close was deliberate\" flag in both the ref effects read\n * synchronously (live, even from a stale closure) and the state the rest of\n * the component reads for render — every call site that touches\n * `userClosedDropdown` goes through this so the two never drift (FUT-2780).\n */\nfunction setDeliberateClose<T>(s: AutocompleteState<T>, closed: boolean): void {\n s.userClosedDropdownRef.current = closed;\n s.setUserClosedDropdown(closed);\n}\n\n// ---- effects (one tiny hook each; explicit params keep deps complete) --------\n\nfunction useValueSync(value: string, setInputValue: Setter<string>): void {\n useEffect(() => setInputValue(value), [value, setInputValue]);\n}\n\nfunction useDebounceCleanup(debounceRef: React.RefObject<number | undefined>): void {\n useEffect(\n () => () => {\n if (debounceRef.current) window.clearTimeout(debounceRef.current);\n },\n [debounceRef],\n );\n}\n\nfunction useScrollActiveIntoView(\n activeIndex: number,\n optionIdPrefix: string,\n listRef: React.RefObject<HTMLUListElement | null>,\n): void {\n useEffect(() => {\n if (activeIndex < 0 || !listRef.current) return;\n document\n .getElementById(`${optionIdPrefix}-${activeIndex}`)\n ?.scrollIntoView({ block: 'nearest' });\n }, [activeIndex, optionIdPrefix, listRef]);\n}\n\nfunction useGhostFlagReset(justCompletedGhost: boolean, setJustCompletedGhost: Setter<boolean>): void {\n useEffect(() => {\n if (!justCompletedGhost) return;\n const timer = setTimeout(() => setJustCompletedGhost(false), 50);\n return () => clearTimeout(timer);\n }, [justCompletedGhost, setJustCompletedGhost]);\n}\n\nfunction useLoadingOpen(\n isLoading: boolean,\n inputValue: string,\n disabled: boolean,\n userClosedDropdownRef: React.RefObject<boolean>,\n setOpen: Setter<boolean>,\n setActiveIndex: Setter<number>,\n): void {\n useEffect(() => {\n if (isLoading && inputValue.trim().length > 0 && !disabled && !userClosedDropdownRef.current) setOpen(true);\n if (disabled) {\n setOpen(false);\n setActiveIndex(-1);\n }\n }, [isLoading, inputValue, disabled, userClosedDropdownRef, setOpen, setActiveIndex]);\n}\n\n/** Inputs to the auto-open check, all primitive/stable so effect deps stay complete. */\ninterface AutoOpenArgs {\n inputValue: string;\n isInputFocused: boolean;\n composition: boolean;\n justCompletedGhost: boolean;\n userClosedDropdownRef: React.RefObject<boolean>;\n activeIndex: number;\n setOpen: Setter<boolean>;\n setActiveIndex: Setter<number>;\n}\n\n/** Auto-open the dropdown once local filtering has a fresh result set. */\nfunction maybeAutoOpen(a: AutoOpenArgs, hasResults: boolean): void {\n const canAutoOpen =\n a.inputValue.trim() &&\n a.isInputFocused &&\n !a.composition &&\n !a.justCompletedGhost &&\n !a.userClosedDropdownRef.current;\n if (!canAutoOpen) return;\n a.setOpen(true);\n if (hasResults && a.activeIndex === -1) a.setActiveIndex(0);\n}\n\nfunction useLocalFilter<T>(p: AutocompleteProps<T>, s: AutocompleteState<T>): void {\n const propSuggestions = p.suggestions;\n const getLabel = p.getLabel ?? defaultGetLabel;\n const matchMode: MatchMode = p.matchMode ?? 'contains';\n const async = Boolean(p.async);\n const {\n inputValue, isInputFocused, composition, justCompletedGhost, userClosedDropdown, activeIndex,\n setFilteredSuggestions, setOpen, setActiveIndex, userClosedDropdownRef,\n } = s;\n useEffect(() => {\n const suggestions = propSuggestions ?? [];\n if (async || !inputValue) {\n setFilteredSuggestions(suggestions);\n return;\n }\n const filtered = filterSuggestions(suggestions, inputValue, matchMode, getLabel);\n setFilteredSuggestions(filtered);\n maybeAutoOpen(\n { inputValue, isInputFocused, composition, justCompletedGhost, userClosedDropdownRef, activeIndex, setOpen, setActiveIndex },\n filtered.length > 0,\n );\n // `userClosedDropdown` (state) stays a dependency so this effect still\n // reruns on every change of it, same as before — only the VALUE read\n // inside `maybeAutoOpen` moved to the ref (see `userClosedDropdownRef`'s\n // doc comment).\n }, [\n propSuggestions, inputValue, async, getLabel, matchMode, isInputFocused, composition,\n justCompletedGhost, userClosedDropdown, activeIndex, setFilteredSuggestions, setOpen, setActiveIndex,\n userClosedDropdownRef,\n ]);\n}\n\nfunction useGhostText<T>(p: AutocompleteProps<T>, s: AutocompleteState<T>): void {\n const getLabel = p.getLabel ?? defaultGetLabel;\n const getType = p.getSuggestionType ?? defaultGetSuggestionType;\n const showGhost = p.showGhostText ?? true;\n const { inputValue, filteredSuggestions, isInputFocused, composition, setGhost } = s;\n useEffect(() => {\n if (!inputValue || !isInputFocused || composition || !showGhost) {\n setGhost('');\n return;\n }\n const first = firstGhostSuggestion(filteredSuggestions, inputValue, getLabel, getType);\n setGhost(first ? getLabel(first).slice(inputValue.length) : '');\n }, [inputValue, filteredSuggestions, isInputFocused, composition, showGhost, getLabel, getType, setGhost]);\n}\n\n// ---- selection (split by mode to keep each function under the complexity bar) -\n\nfunction commitMultiSelect<T>(item: T, p: AutocompleteProps<T>, s: AutocompleteState<T>, onChange: (v: string) => void): void {\n const getKey = p.getKey ?? defaultGetKey;\n const current = p.selectedItems ?? [];\n if (!current.some((sel) => getKey(sel) === getKey(item))) p.onSelectedItemsChange?.([...current, item]);\n s.setInputValue('');\n onChange('');\n setDeliberateClose(s, false);\n}\n\n/**\n * A single-select pick's own correction must land in the same tick as\n * `setInputValue(label)`, not up to `debounceMs` later — so it calls\n * `p.onChange` DIRECTLY rather than going through `debouncedOnChange`\n * (FUT-2860). `commitMultiSelect` is unaffected: it keeps calling the\n * debounced `onChange('')`, per the ticket's own decision.\n */\nfunction commitSingleSelect<T>(item: T, p: AutocompleteProps<T>, s: AutocompleteState<T>): void {\n const label = (p.getLabel ?? defaultGetLabel)(item);\n s.setInputValue(label);\n p.onChange(label);\n}\n\n/** Apply a pick: open a link suggestion, or commit a search one to the input. */\nfunction commitPick<T>(\n item: T,\n linkUrl: string | null,\n p: AutocompleteProps<T>,\n s: AutocompleteState<T>,\n onChange: (v: string) => void,\n): void {\n if (linkUrl !== null) (p.openLink ?? defaultOpenLink)(linkUrl, item);\n else if (p.multiple) commitMultiSelect(item, p, s, onChange);\n else commitSingleSelect(item, p, s);\n}\n\nfunction runSelectItem<T>(item: T, p: AutocompleteProps<T>, s: AutocompleteState<T>, onChange: (v: string) => void): void {\n const url = (p.getUrl ?? defaultGetUrl)(item);\n const isLink = (p.getSuggestionType ?? defaultGetSuggestionType)(item) === 'link' && Boolean(url);\n // A single-select pick (search or link) ends the current search: the list\n // stays closed until the user types again. `multiple` mode is unchanged —\n // commitMultiSelect already clears inputValue and resets the flag itself,\n // so the empty-input branch of the filter effect keeps the list closed.\n const isSingleSelectPick = isLink || !p.multiple;\n // Cancel a still-pending keystroke debounce BEFORE dispatching the pick, so\n // no branch below — including `openLink`, which never touches `onChange`\n // at all — can leave it armed to fire the STALE pre-pick text later\n // (FUT-2779 #1). `commitMultiSelect` already clears it as a side effect of\n // calling the same `debouncedOnChange`; `commitSingleSelect` bypasses that\n // path entirely now (FUT-2860), so this cancel is what covers IT and a\n // `link` pick (which skips `onChange` entirely) alike.\n if (s.debounceRef.current) window.clearTimeout(s.debounceRef.current);\n commitPick(item, isLink ? (url as string) : null, p, s, onChange);\n s.setOpen(false);\n s.setActiveIndex(-1);\n p.onSelect?.(item);\n s.inputRef.current?.focus();\n // Set LAST so a re-fired `onFocus` cannot clear the flag. The close itself\n // relies on the input never blurring during a pick (the option's\n // `onMouseDown` preventDefault, and Enter keeps focus): `onFocus` reopens a\n // non-empty input directly, without reading this flag. The REF half is set\n // in the same synchronous tick as the pick, so an effect scheduled by an\n // earlier keystroke — and still pending when this runs — reads the\n // up-to-date value instead of the one it closed over (FUT-2780).\n if (isSingleSelectPick) setDeliberateClose(s, true);\n}\n\nfunction buildKeyContext<T>(\n p: AutocompleteProps<T>,\n s: AutocompleteState<T>,\n selectItem: (item: T) => void,\n onChange: (v: string) => void,\n): KeyContext<T> {\n return {\n open: s.open, activeIndex: s.activeIndex, filteredSuggestions: s.filteredSuggestions,\n maxVisibleItems: p.maxVisibleItems ?? 10, allowFreeText: p.allowFreeText ?? true,\n inputValue: s.inputValue, ghost: s.ghost, isInputFocused: s.isInputFocused,\n multiple: Boolean(p.multiple), selectedItems: p.selectedItems ?? [],\n getLabel: p.getLabel ?? defaultGetLabel,\n getSuggestionType: p.getSuggestionType ?? defaultGetSuggestionType,\n setOpen: s.setOpen, setActiveIndex: s.setActiveIndex,\n setUserClosedDropdown: (closed: boolean) => setDeliberateClose(s, closed),\n setInputValue: s.setInputValue, setGhost: s.setGhost, setJustCompletedGhost: s.setJustCompletedGhost,\n debouncedOnChange: onChange, selectItem, onSelectedItemsChange: p.onSelectedItemsChange,\n };\n}\n\n/** The full view-model the presentational component renders. */\nexport interface AutocompleteView<T> {\n id: string;\n listId: string;\n optionIdPrefix: string;\n state: AutocompleteState<T>;\n visibleSuggestions: T[];\n activeDescendant: string | undefined;\n selectItem: (item: T) => void;\n removeSelectedItem: (item: T) => void;\n onKeyDown: (e: React.KeyboardEvent<HTMLInputElement>) => void;\n onInputChange: (e: React.ChangeEvent<HTMLInputElement>) => void;\n onFocus: () => void;\n onBlur: () => void;\n onClickAway: () => void;\n}\n\n/** Wire state, effects, and (plain, per-render) handlers for the Autocomplete component. */\nexport function useAutocomplete<T>(p: AutocompleteProps<T>): AutocompleteView<T> {\n const componentId = useId();\n const id = p.id || componentId;\n const optionIdPrefix = `${id}-option`;\n const s = useAutocompleteState<T>(p.value, p.suggestions ?? []);\n\n const debouncedOnChange = (val: string): void => {\n if (s.debounceRef.current) window.clearTimeout(s.debounceRef.current);\n s.debounceRef.current = window.setTimeout(() => p.onChange(val), p.debounceMs ?? 150);\n };\n\n useValueSync(p.value, s.setInputValue);\n useDebounceCleanup(s.debounceRef);\n useScrollActiveIntoView(s.activeIndex, optionIdPrefix, s.listRef);\n useGhostFlagReset(s.justCompletedGhost, s.setJustCompletedGhost);\n useLoadingOpen(\n Boolean(p.isLoading),\n s.inputValue,\n Boolean(p.disabled),\n s.userClosedDropdownRef,\n s.setOpen,\n s.setActiveIndex,\n );\n useLocalFilter(p, s);\n useGhostText(p, s);\n\n const selectItem = (item: T): void => runSelectItem(item, p, s, debouncedOnChange);\n\n return {\n id,\n listId: `${id}-listbox`,\n optionIdPrefix,\n state: s,\n visibleSuggestions: s.filteredSuggestions.slice(0, p.maxVisibleItems ?? 10),\n activeDescendant: s.activeIndex >= 0 ? `${optionIdPrefix}-${s.activeIndex}` : undefined,\n selectItem,\n removeSelectedItem: (item: T): void => {\n const getKey = p.getKey ?? defaultGetKey;\n p.onSelectedItemsChange?.((p.selectedItems ?? []).filter((sel) => getKey(sel) !== getKey(item)));\n s.inputRef.current?.focus();\n },\n onKeyDown: (e: React.KeyboardEvent<HTMLInputElement>): void =>\n handleAutocompleteKey(e, s.composition, buildKeyContext(p, s, selectItem, debouncedOnChange)),\n onInputChange: (e: React.ChangeEvent<HTMLInputElement>): void => {\n s.setInputValue(e.target.value);\n debouncedOnChange(e.target.value);\n if (!s.open || s.filteredSuggestions.length === 0) s.setActiveIndex(-1);\n setDeliberateClose(s, false);\n },\n // Unconditionally reopens on a non-empty input, unguarded by\n // `userClosedDropdownRef` — plausible on a touch device that blurs the\n // input on `touchstart` before a tap's own `click`/`mousedown` reaches the\n // option (FUT-2779 #2). Checked under Playwright touch emulation\n // (`hasTouch`/`isMobile` context, both the `.tap()` API and raw CDP\n // `Input.dispatchTouchEvent` at the option's coordinates) against this\n // Chromium build: `document.activeElement` never left the input across\n // the touch, so the reopen never happened — not reproduced, left\n // unguarded per the ticket's decision rather than fixed blind.\n onFocus: (): void => {\n s.setIsInputFocused(true);\n setDeliberateClose(s, false);\n if (!s.inputValue.trim()) return;\n s.setOpen(true);\n if (s.filteredSuggestions.length > 0 && s.activeIndex === -1) s.setActiveIndex(0);\n },\n onBlur: (): void => {\n window.setTimeout(() => s.setIsInputFocused(false), 150);\n },\n onClickAway: (): void => {\n s.setOpen(false);\n s.setActiveIndex(-1);\n setDeliberateClose(s, true);\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;AAAA,SAAS,WAAW,OAAO,QAAQ,gBAAgB;AAmDnD,SAAS,qBAAwB,OAAe,aAAwC;AACtF,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,KAAK;AACtC,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,EAAE;AACjD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,EAAE;AACrC,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,KAAK;AAClD,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,KAAK;AACpD,QAAM,CAAC,qBAAqB,sBAAsB,IAAI,SAAc,WAAW;AAC/E,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAS,KAAK;AAC1D,QAAM,CAAC,oBAAoB,qBAAqB,IAAI,SAAS,KAAK;AAClE,QAAM,CAAC,oBAAoB,qBAAqB,IAAI,SAAS,KAAK;AAClE,QAAM,wBAAwB,OAAO,KAAK;AAC1C,QAAM,WAAW,OAAyB,IAAI;AAC9C,QAAM,UAAU,OAAgC,IAAI;AACpD,QAAM,cAAc,OAA2B,MAAS;AACxD,SAAO;AAAA,IACL;AAAA,IAAM;AAAA,IAAS;AAAA,IAAa;AAAA,IAAgB;AAAA,IAAO;AAAA,IAAU;AAAA,IAAY;AAAA,IACzE;AAAA,IAAa;AAAA,IAAgB;AAAA,IAAqB;AAAA,IAAwB;AAAA,IAC1E;AAAA,IAAmB;AAAA,IAAoB;AAAA,IAAuB;AAAA,IAC9D;AAAA,IAAuB;AAAA,IAAuB;AAAA,IAAU;AAAA,IAAS;AAAA,EACnE;AACF;AAQA,SAAS,mBAAsB,GAAyB,QAAuB;AAC7E,IAAE,sBAAsB,UAAU;AAClC,IAAE,sBAAsB,MAAM;AAChC;AAIA,SAAS,aAAa,OAAe,eAAqC;AACxE,YAAU,MAAM,cAAc,KAAK,GAAG,CAAC,OAAO,aAAa,CAAC;AAC9D;AAEA,SAAS,mBAAmB,aAAwD;AAClF;AAAA,IACE,MAAM,MAAM;AACV,UAAI,YAAY,QAAS,QAAO,aAAa,YAAY,OAAO;AAAA,IAClE;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AACF;AAEA,SAAS,wBACP,aACA,gBACA,SACM;AACN,YAAU,MAAM;AACd,QAAI,cAAc,KAAK,CAAC,QAAQ,QAAS;AACzC,aACG,eAAe,GAAG,cAAc,IAAI,WAAW,EAAE,GAChD,eAAe,EAAE,OAAO,UAAU,CAAC;AAAA,EACzC,GAAG,CAAC,aAAa,gBAAgB,OAAO,CAAC;AAC3C;AAEA,SAAS,kBAAkB,oBAA6B,uBAA8C;AACpG,YAAU,MAAM;AACd,QAAI,CAAC,mBAAoB;AACzB,UAAM,QAAQ,WAAW,MAAM,sBAAsB,KAAK,GAAG,EAAE;AAC/D,WAAO,MAAM,aAAa,KAAK;AAAA,EACjC,GAAG,CAAC,oBAAoB,qBAAqB,CAAC;AAChD;AAEA,SAAS,eACP,WACA,YACA,UACA,uBACA,SACA,gBACM;AACN,YAAU,MAAM;AACd,QAAI,aAAa,WAAW,KAAK,EAAE,SAAS,KAAK,CAAC,YAAY,CAAC,sBAAsB,QAAS,SAAQ,IAAI;AAC1G,QAAI,UAAU;AACZ,cAAQ,KAAK;AACb,qBAAe,EAAE;AAAA,IACnB;AAAA,EACF,GAAG,CAAC,WAAW,YAAY,UAAU,uBAAuB,SAAS,cAAc,CAAC;AACtF;AAeA,SAAS,cAAc,GAAiB,YAA2B;AACjE,QAAM,cACJ,EAAE,WAAW,KAAK,KAClB,EAAE,kBACF,CAAC,EAAE,eACH,CAAC,EAAE,sBACH,CAAC,EAAE,sBAAsB;AAC3B,MAAI,CAAC,YAAa;AAClB,IAAE,QAAQ,IAAI;AACd,MAAI,cAAc,EAAE,gBAAgB,GAAI,GAAE,eAAe,CAAC;AAC5D;AAEA,SAAS,eAAkB,GAAyB,GAA+B;AACjF,QAAM,kBAAkB,EAAE;AAC1B,QAAM,WAAW,EAAE,YAAY;AAC/B,QAAM,YAAuB,EAAE,aAAa;AAC5C,QAAM,QAAQ,QAAQ,EAAE,KAAK;AAC7B,QAAM;AAAA,IACJ;AAAA,IAAY;AAAA,IAAgB;AAAA,IAAa;AAAA,IAAoB;AAAA,IAAoB;AAAA,IACjF;AAAA,IAAwB;AAAA,IAAS;AAAA,IAAgB;AAAA,EACnD,IAAI;AACJ,YAAU,MAAM;AACd,UAAM,cAAc,mBAAmB,CAAC;AACxC,QAAI,SAAS,CAAC,YAAY;AACxB,6BAAuB,WAAW;AAClC;AAAA,IACF;AACA,UAAM,WAAW,kBAAkB,aAAa,YAAY,WAAW,QAAQ;AAC/E,2BAAuB,QAAQ;AAC/B;AAAA,MACE,EAAE,YAAY,gBAAgB,aAAa,oBAAoB,uBAAuB,aAAa,SAAS,eAAe;AAAA,MAC3H,SAAS,SAAS;AAAA,IACpB;AAAA,EAKF,GAAG;AAAA,IACD;AAAA,IAAiB;AAAA,IAAY;AAAA,IAAO;AAAA,IAAU;AAAA,IAAW;AAAA,IAAgB;AAAA,IACzE;AAAA,IAAoB;AAAA,IAAoB;AAAA,IAAa;AAAA,IAAwB;AAAA,IAAS;AAAA,IACtF;AAAA,EACF,CAAC;AACH;AAEA,SAAS,aAAgB,GAAyB,GAA+B;AAC/E,QAAM,WAAW,EAAE,YAAY;AAC/B,QAAM,UAAU,EAAE,qBAAqB;AACvC,QAAM,YAAY,EAAE,iBAAiB;AACrC,QAAM,EAAE,YAAY,qBAAqB,gBAAgB,aAAa,SAAS,IAAI;AACnF,YAAU,MAAM;AACd,QAAI,CAAC,cAAc,CAAC,kBAAkB,eAAe,CAAC,WAAW;AAC/D,eAAS,EAAE;AACX;AAAA,IACF;AACA,UAAM,QAAQ,qBAAqB,qBAAqB,YAAY,UAAU,OAAO;AACrF,aAAS,QAAQ,SAAS,KAAK,EAAE,MAAM,WAAW,MAAM,IAAI,EAAE;AAAA,EAChE,GAAG,CAAC,YAAY,qBAAqB,gBAAgB,aAAa,WAAW,UAAU,SAAS,QAAQ,CAAC;AAC3G;AAIA,SAAS,kBAAqB,MAAS,GAAyB,GAAyB,UAAqC;AAC5H,QAAM,SAAS,EAAE,UAAU;AAC3B,QAAM,UAAU,EAAE,iBAAiB,CAAC;AACpC,MAAI,CAAC,QAAQ,KAAK,CAAC,QAAQ,OAAO,GAAG,MAAM,OAAO,IAAI,CAAC,EAAG,GAAE,wBAAwB,CAAC,GAAG,SAAS,IAAI,CAAC;AACtG,IAAE,cAAc,EAAE;AAClB,WAAS,EAAE;AACX,qBAAmB,GAAG,KAAK;AAC7B;AASA,SAAS,mBAAsB,MAAS,GAAyB,GAA+B;AAC9F,QAAM,SAAS,EAAE,YAAY,iBAAiB,IAAI;AAClD,IAAE,cAAc,KAAK;AACrB,IAAE,SAAS,KAAK;AAClB;AAGA,SAAS,WACP,MACA,SACA,GACA,GACA,UACM;AACN,MAAI,YAAY,KAAM,EAAC,EAAE,YAAY,iBAAiB,SAAS,IAAI;AAAA,WAC1D,EAAE,SAAU,mBAAkB,MAAM,GAAG,GAAG,QAAQ;AAAA,MACtD,oBAAmB,MAAM,GAAG,CAAC;AACpC;AAEA,SAAS,cAAiB,MAAS,GAAyB,GAAyB,UAAqC;AACxH,QAAM,OAAO,EAAE,UAAU,eAAe,IAAI;AAC5C,QAAM,UAAU,EAAE,qBAAqB,0BAA0B,IAAI,MAAM,UAAU,QAAQ,GAAG;AAKhG,QAAM,qBAAqB,UAAU,CAAC,EAAE;AAQxC,MAAI,EAAE,YAAY,QAAS,QAAO,aAAa,EAAE,YAAY,OAAO;AACpE,aAAW,MAAM,SAAU,MAAiB,MAAM,GAAG,GAAG,QAAQ;AAChE,IAAE,QAAQ,KAAK;AACf,IAAE,eAAe,EAAE;AACnB,IAAE,WAAW,IAAI;AACjB,IAAE,SAAS,SAAS,MAAM;AAQ1B,MAAI,mBAAoB,oBAAmB,GAAG,IAAI;AACpD;AAEA,SAAS,gBACP,GACA,GACA,YACA,UACe;AACf,SAAO;AAAA,IACL,MAAM,EAAE;AAAA,IAAM,aAAa,EAAE;AAAA,IAAa,qBAAqB,EAAE;AAAA,IACjE,iBAAiB,EAAE,mBAAmB;AAAA,IAAI,eAAe,EAAE,iBAAiB;AAAA,IAC5E,YAAY,EAAE;AAAA,IAAY,OAAO,EAAE;AAAA,IAAO,gBAAgB,EAAE;AAAA,IAC5D,UAAU,QAAQ,EAAE,QAAQ;AAAA,IAAG,eAAe,EAAE,iBAAiB,CAAC;AAAA,IAClE,UAAU,EAAE,YAAY;AAAA,IACxB,mBAAmB,EAAE,qBAAqB;AAAA,IAC1C,SAAS,EAAE;AAAA,IAAS,gBAAgB,EAAE;AAAA,IACtC,uBAAuB,CAAC,WAAoB,mBAAmB,GAAG,MAAM;AAAA,IACxE,eAAe,EAAE;AAAA,IAAe,UAAU,EAAE;AAAA,IAAU,uBAAuB,EAAE;AAAA,IAC/E,mBAAmB;AAAA,IAAU;AAAA,IAAY,uBAAuB,EAAE;AAAA,EACpE;AACF;AAoBO,SAAS,gBAAmB,GAA8C;AAC/E,QAAM,cAAc,MAAM;AAC1B,QAAM,KAAK,EAAE,MAAM;AACnB,QAAM,iBAAiB,GAAG,EAAE;AAC5B,QAAM,IAAI,qBAAwB,EAAE,OAAO,EAAE,eAAe,CAAC,CAAC;AAE9D,QAAM,oBAAoB,CAAC,QAAsB;AAC/C,QAAI,EAAE,YAAY,QAAS,QAAO,aAAa,EAAE,YAAY,OAAO;AACpE,MAAE,YAAY,UAAU,OAAO,WAAW,MAAM,EAAE,SAAS,GAAG,GAAG,EAAE,cAAc,GAAG;AAAA,EACtF;AAEA,eAAa,EAAE,OAAO,EAAE,aAAa;AACrC,qBAAmB,EAAE,WAAW;AAChC,0BAAwB,EAAE,aAAa,gBAAgB,EAAE,OAAO;AAChE,oBAAkB,EAAE,oBAAoB,EAAE,qBAAqB;AAC/D;AAAA,IACE,QAAQ,EAAE,SAAS;AAAA,IACnB,EAAE;AAAA,IACF,QAAQ,EAAE,QAAQ;AAAA,IAClB,EAAE;AAAA,IACF,EAAE;AAAA,IACF,EAAE;AAAA,EACJ;AACA,iBAAe,GAAG,CAAC;AACnB,eAAa,GAAG,CAAC;AAEjB,QAAM,aAAa,CAAC,SAAkB,cAAc,MAAM,GAAG,GAAG,iBAAiB;AAEjF,SAAO;AAAA,IACL;AAAA,IACA,QAAQ,GAAG,EAAE;AAAA,IACb;AAAA,IACA,OAAO;AAAA,IACP,oBAAoB,EAAE,oBAAoB,MAAM,GAAG,EAAE,mBAAmB,EAAE;AAAA,IAC1E,kBAAkB,EAAE,eAAe,IAAI,GAAG,cAAc,IAAI,EAAE,WAAW,KAAK;AAAA,IAC9E;AAAA,IACA,oBAAoB,CAAC,SAAkB;AACrC,YAAM,SAAS,EAAE,UAAU;AAC3B,QAAE,yBAAyB,EAAE,iBAAiB,CAAC,GAAG,OAAO,CAAC,QAAQ,OAAO,GAAG,MAAM,OAAO,IAAI,CAAC,CAAC;AAC/F,QAAE,SAAS,SAAS,MAAM;AAAA,IAC5B;AAAA,IACA,WAAW,CAAC,MACV,sBAAsB,GAAG,EAAE,aAAa,gBAAgB,GAAG,GAAG,YAAY,iBAAiB,CAAC;AAAA,IAC9F,eAAe,CAAC,MAAiD;AAC/D,QAAE,cAAc,EAAE,OAAO,KAAK;AAC9B,wBAAkB,EAAE,OAAO,KAAK;AAChC,UAAI,CAAC,EAAE,QAAQ,EAAE,oBAAoB,WAAW,EAAG,GAAE,eAAe,EAAE;AACtE,yBAAmB,GAAG,KAAK;AAAA,IAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAUA,SAAS,MAAY;AACnB,QAAE,kBAAkB,IAAI;AACxB,yBAAmB,GAAG,KAAK;AAC3B,UAAI,CAAC,EAAE,WAAW,KAAK,EAAG;AAC1B,QAAE,QAAQ,IAAI;AACd,UAAI,EAAE,oBAAoB,SAAS,KAAK,EAAE,gBAAgB,GAAI,GAAE,eAAe,CAAC;AAAA,IAClF;AAAA,IACA,QAAQ,MAAY;AAClB,aAAO,WAAW,MAAM,EAAE,kBAAkB,KAAK,GAAG,GAAG;AAAA,IACzD;AAAA,IACA,aAAa,MAAY;AACvB,QAAE,QAAQ,KAAK;AACf,QAAE,eAAe,EAAE;AACnB,yBAAmB,GAAG,IAAI;AAAA,IAC5B;AAAA,EACF;AACF;","names":[]}
@@ -2,9 +2,9 @@ import "../chunk-2LXHUGYB.js";
2
2
  import {
3
3
  Autocomplete,
4
4
  Autocomplete_default
5
- } from "../chunk-PXGURBIU.js";
5
+ } from "../chunk-JBGCGYEC.js";
6
6
  import "../chunk-XBLFK2FL.js";
7
- import "../chunk-YWJZPN5C.js";
7
+ import "../chunk-SY5FYBAF.js";
8
8
  import "../chunk-PELRSZFU.js";
9
9
  import "../chunk-JXS56EW5.js";
10
10
  import "../chunk-M47ZOUGF.js";
@@ -1 +1 @@
1
- {"version":3,"file":"useAutocomplete.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/Autocomplete/useAutocomplete.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,KAAK,MAAM,CAAC,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;AAEzD,8DAA8D;AAC9D,UAAU,iBAAiB,CAAC,CAAC;IAC3B,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC9B,WAAW,EAAE,OAAO,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAChC,mBAAmB,EAAE,CAAC,EAAE,CAAC;IACzB,sBAAsB,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;IACpC,cAAc,EAAE,OAAO,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACnC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,qBAAqB,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACvC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,qBAAqB,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACvC;;;;;;;OAOG;IACH,qBAAqB,EAAE,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAChD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IACnD,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAClD,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CAClD;AAiPD,gEAAgE;AAChE,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;IAC5B,kBAAkB,EAAE,CAAC,EAAE,CAAC;IACxB,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;IAC9B,kBAAkB,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;IACtC,SAAS,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IAC9D,aAAa,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IAChE,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,WAAW,EAAE,MAAM,IAAI,CAAC;CACzB;AAED,4FAA4F;AAC5F,wBAAgB,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,CA0E/E"}
1
+ {"version":3,"file":"useAutocomplete.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/Autocomplete/useAutocomplete.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,KAAK,MAAM,CAAC,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;AAEzD,8DAA8D;AAC9D,UAAU,iBAAiB,CAAC,CAAC;IAC3B,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC9B,WAAW,EAAE,OAAO,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAChC,mBAAmB,EAAE,CAAC,EAAE,CAAC;IACzB,sBAAsB,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;IACpC,cAAc,EAAE,OAAO,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACnC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,qBAAqB,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACvC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,qBAAqB,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACvC;;;;;;;OAOG;IACH,qBAAqB,EAAE,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAChD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IACnD,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAClD,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CAClD;AAwPD,gEAAgE;AAChE,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;IAC5B,kBAAkB,EAAE,CAAC,EAAE,CAAC;IACxB,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;IAC9B,kBAAkB,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;IACtC,SAAS,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IAC9D,aAAa,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IAChE,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,WAAW,EAAE,MAAM,IAAI,CAAC;CACzB;AAED,4FAA4F;AAC5F,wBAAgB,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,CA0E/E"}
@@ -1,9 +1,9 @@
1
1
  import "../chunk-IO36MEBD.js";
2
2
  import {
3
3
  WorkflowStep
4
- } from "../chunk-JHW62I7Z.js";
5
- import "../chunk-Y6RSQEOU.js";
6
- import "../chunk-6S25ZCEW.js";
4
+ } from "../chunk-LOLR2BWW.js";
5
+ import "../chunk-LV4WSWQZ.js";
6
+ import "../chunk-KNWG77FB.js";
7
7
  import "../chunk-TM5QQJTF.js";
8
8
  import "../chunk-FHWXRHMA.js";
9
9
  import "../chunk-7ZPUN7TV.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@12-apps/ui",
3
- "version": "6.45.2",
3
+ "version": "6.45.4",
4
4
  "license": "MIT",
5
5
  "packageManager": "pnpm@10.34.5",
6
6
  "type": "module",
@@ -218,10 +218,17 @@ function commitMultiSelect<T>(item: T, p: AutocompleteProps<T>, s: AutocompleteS
218
218
  setDeliberateClose(s, false);
219
219
  }
220
220
 
221
- function commitSingleSelect<T>(item: T, p: AutocompleteProps<T>, s: AutocompleteState<T>, onChange: (v: string) => void): void {
221
+ /**
222
+ * A single-select pick's own correction must land in the same tick as
223
+ * `setInputValue(label)`, not up to `debounceMs` later — so it calls
224
+ * `p.onChange` DIRECTLY rather than going through `debouncedOnChange`
225
+ * (FUT-2860). `commitMultiSelect` is unaffected: it keeps calling the
226
+ * debounced `onChange('')`, per the ticket's own decision.
227
+ */
228
+ function commitSingleSelect<T>(item: T, p: AutocompleteProps<T>, s: AutocompleteState<T>): void {
222
229
  const label = (p.getLabel ?? defaultGetLabel)(item);
223
230
  s.setInputValue(label);
224
- onChange(label);
231
+ p.onChange(label);
225
232
  }
226
233
 
227
234
  /** Apply a pick: open a link suggestion, or commit a search one to the input. */
@@ -234,7 +241,7 @@ function commitPick<T>(
234
241
  ): void {
235
242
  if (linkUrl !== null) (p.openLink ?? defaultOpenLink)(linkUrl, item);
236
243
  else if (p.multiple) commitMultiSelect(item, p, s, onChange);
237
- else commitSingleSelect(item, p, s, onChange);
244
+ else commitSingleSelect(item, p, s);
238
245
  }
239
246
 
240
247
  function runSelectItem<T>(item: T, p: AutocompleteProps<T>, s: AutocompleteState<T>, onChange: (v: string) => void): void {
@@ -248,10 +255,10 @@ function runSelectItem<T>(item: T, p: AutocompleteProps<T>, s: AutocompleteState
248
255
  // Cancel a still-pending keystroke debounce BEFORE dispatching the pick, so
249
256
  // no branch below — including `openLink`, which never touches `onChange`
250
257
  // at all — can leave it armed to fire the STALE pre-pick text later
251
- // (FUT-2779 #1). `commitSingleSelect`/`commitMultiSelect` already clear it
252
- // as a side effect of calling the same `debouncedOnChange`; this makes it
253
- // unconditional so a `link` pick (which skips `onChange` entirely) is
254
- // covered too.
258
+ // (FUT-2779 #1). `commitMultiSelect` already clears it as a side effect of
259
+ // calling the same `debouncedOnChange`; `commitSingleSelect` bypasses that
260
+ // path entirely now (FUT-2860), so this cancel is what covers IT and a
261
+ // `link` pick (which skips `onChange` entirely) alike.
255
262
  if (s.debounceRef.current) window.clearTimeout(s.debounceRef.current);
256
263
  commitPick(item, isLink ? (url as string) : null, p, s, onChange);
257
264
  s.setOpen(false);
@@ -232,19 +232,19 @@ const StepIndicatorComponent = forwardRef<HTMLDivElement, StepIndicatorProps>(({
232
232
  const isDisabled = Boolean(disabled || step.disabled);
233
233
 
234
234
  const handleClick = useCallback(() => {
235
- if (interactive && !disabled && onClick) {
235
+ if (interactive && !isDisabled && onClick) {
236
236
  onClick(index, step);
237
237
  }
238
- }, [interactive, disabled, onClick, index, step]);
238
+ }, [interactive, isDisabled, onClick, index, step]);
239
239
 
240
240
  const handleKeyDown = useCallback((event: React.KeyboardEvent) => {
241
- if (interactive && !disabled && (event.key === 'Enter' || event.key === ' ')) {
241
+ if (interactive && !isDisabled && (event.key === 'Enter' || event.key === ' ')) {
242
242
  event.preventDefault();
243
243
  if (onClick) {
244
244
  onClick(index, step);
245
245
  }
246
246
  }
247
- }, [interactive, disabled, onClick, index, step]);
247
+ }, [interactive, isDisabled, onClick, index, step]);
248
248
 
249
249
  const renderIndicatorContent = () => {
250
250
  if (isError && errorIcon) {
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/utility/WorkflowStep/WorkflowStep.parts.tsx"],"sourcesContent":["import Box from '@mui/material/Box/index.js';\nimport type { CSSObject, Theme } from '@mui/material/styles/index.js';\nimport { styled } from '@mui/material/styles/index.js';\nimport React, { forwardRef, useCallback } from 'react';\n\nimport type { StepColors } from './WorkflowStep.helpers';\nimport { indicatorSizeFor, stepColors, stepPalette } from './WorkflowStep.helpers';\nimport type {\n StepConnectorProps,\n StepContentProps,\n StepIndicatorProps,\n WorkflowStepProps,\n} from './WorkflowStep.types';\nimport { neutralTones } from '../../../tokens/ink';\nimport { rem } from '../../../tokens/relative';\n\n// `outlined` shows the surface through a coloured rim; the other three fill it and\n// differ only in what border they keep.\nconst indicatorVariantStyles = (\n theme: Theme,\n variant: WorkflowStepProps['variant'],\n { backgroundColor, borderColor, textColor }: StepColors,\n): CSSObject => {\n if (variant === 'outlined') {\n return {\n border: `${rem(theme, 2)} solid ${borderColor}`,\n backgroundColor: theme.palette.background.paper,\n };\n }\n\n const filled = { backgroundColor, color: textColor };\n\n switch (variant) {\n case 'filled':\n return filled;\n case 'minimal':\n return { ...filled, border: 'none' };\n case 'default':\n return { ...filled, border: `1px solid ${borderColor}` };\n default:\n return {};\n }\n};\n\nconst StepItem = styled(Box, {\n shouldForwardProp: (prop) => !['orientation', 'isLast'].includes(prop as string),\n})<{\n orientation: WorkflowStepProps['orientation'];\n isLast: boolean;\n}>(({ orientation, isLast }) => ({\n display: 'flex',\n flexDirection: orientation === 'vertical' ? 'column' : 'row',\n alignItems: orientation === 'vertical' ? 'flex-start' : 'center',\n flex: orientation === 'horizontal' && !isLast ? 1 : 'none',\n position: 'relative',\n minWidth: 0, // Allow content to shrink\n}));\n\nconst StepIndicator = styled(Box, {\n shouldForwardProp: (prop) => !['size', 'variant', 'color', 'isActive', 'isCompleted', 'isError', 'interactive', 'animated', 'disabled'].includes(prop as string),\n})<{\n size: WorkflowStepProps['size'];\n variant: WorkflowStepProps['variant'];\n color: WorkflowStepProps['color'];\n isActive: boolean;\n isCompleted: boolean;\n isError: boolean;\n interactive: boolean;\n animated: boolean;\n disabled: boolean;\n}>(({ theme, size, variant, color, isActive, isCompleted, isError, interactive, animated, disabled }) => {\n const indicatorSize = indicatorSizeFor(size);\n const palette = stepPalette(theme, color);\n const { backgroundColor, borderColor, textColor } = stepColors(theme, palette, {\n isActive,\n isCompleted,\n isError,\n variant,\n });\n\n return {\n width: rem(theme, indicatorSize),\n height: rem(theme, indicatorSize),\n borderRadius: '50%',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: rem(theme, 12),\n fontWeight: theme.typography.fontWeightMedium,\n cursor: interactive && !disabled ? 'pointer' : 'default',\n transition: animated\n ? theme.transitions.create(['background-color', 'border-color', 'transform'], {\n duration: theme.transitions.duration.short,\n })\n : 'none',\n flexShrink: 0,\n\n ...indicatorVariantStyles(theme, variant, { backgroundColor, borderColor, textColor }),\n\n // Interactive states\n ...(interactive && !disabled && {\n '&:hover': {\n transform: 'scale(1.1)',\n boxShadow: theme.shadows[2],\n },\n '&:focus-visible': {\n outline: `${rem(theme, 2)} solid ${palette.main}`,\n outlineOffset: rem(theme, 2),\n },\n }),\n\n // Disabled state\n ...(disabled && {\n opacity: 0.5,\n cursor: 'not-allowed',\n }),\n };\n});\n\nconst StepContent = styled(Box, {\n shouldForwardProp: (prop) => !['orientation', 'interactive', 'disabled'].includes(prop as string),\n})<{\n orientation: WorkflowStepProps['orientation'];\n interactive: boolean;\n disabled: boolean;\n}>(({ theme, orientation, disabled }) => ({\n display: 'flex',\n flexDirection: 'column',\n alignItems: orientation === 'vertical' ? 'flex-start' : 'center',\n textAlign: orientation === 'vertical' ? 'left' : 'center',\n marginTop: orientation === 'vertical' ? theme.spacing(1) : theme.spacing(0.5),\n marginLeft: orientation === 'horizontal' ? theme.spacing(1) : 0,\n // Inert (FUT-2773): the content block has no click handling of its own —\n // the indicator is the step's one interactive element — so its cursor\n // never claims to be clickable, whatever `interactive` says.\n cursor: 'default',\n minWidth: 0,\n flex: 1,\n\n '& .step-title': {\n fontSize: rem(theme, 14),\n fontWeight: theme.typography.fontWeightMedium,\n color: theme.palette.text.primary,\n marginBottom: theme.spacing(0.5),\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n maxWidth: '100%',\n },\n\n '& .step-description': {\n fontSize: rem(theme, 12),\n color: theme.palette.text.secondary,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n maxWidth: '100%',\n },\n\n ...(disabled && {\n opacity: 0.5,\n }),\n}));\n\nconst StepConnector = styled(Box, {\n shouldForwardProp: (prop) => !['orientation', 'isCompleted', 'color', 'variant', 'animated'].includes(prop as string),\n})<{\n orientation: WorkflowStepProps['orientation'];\n isCompleted: boolean;\n color: WorkflowStepProps['color'];\n variant: WorkflowStepProps['variant'];\n animated: boolean;\n}>(({ theme, orientation, isCompleted, color, variant, animated }) => {\n const connectorColor = isCompleted ? stepPalette(theme, color).main : neutralTones(theme).track;\n\n return {\n flex: 1,\n position: 'relative',\n\n ...(orientation === 'horizontal' && {\n height: rem(theme, 2),\n backgroundColor: connectorColor,\n margin: `0 ${theme.spacing(1)}`,\n minWidth: theme.spacing(2),\n }),\n\n ...(orientation === 'vertical' && {\n width: rem(theme, 2),\n backgroundColor: connectorColor,\n minHeight: theme.spacing(3),\n marginLeft: theme.spacing(2),\n position: 'absolute',\n left: '50%',\n transform: 'translateX(-50%)',\n top: '100%',\n }),\n\n transition: animated\n ? theme.transitions.create('background-color', {\n duration: theme.transitions.duration.short,\n })\n : 'none',\n\n ...(variant === 'minimal' && {\n opacity: 0.6,\n }),\n };\n});\n\n/**\n * Individual step indicator component\n */\nconst StepIndicatorComponent = forwardRef<HTMLDivElement, StepIndicatorProps>(({\n step,\n index,\n isActive,\n isCompleted,\n isError,\n variant,\n color,\n size,\n showNumbers,\n showIcons,\n completedIcon,\n errorIcon,\n interactive,\n animated,\n disabled,\n onClick,\n 'data-testid': dataTestId,\n}, ref) => {\n const isDisabled = Boolean(disabled || step.disabled);\n\n const handleClick = useCallback(() => {\n if (interactive && !disabled && onClick) {\n onClick(index, step);\n }\n }, [interactive, disabled, onClick, index, step]);\n\n const handleKeyDown = useCallback((event: React.KeyboardEvent) => {\n if (interactive && !disabled && (event.key === 'Enter' || event.key === ' ')) {\n event.preventDefault();\n if (onClick) {\n onClick(index, step);\n }\n }\n }, [interactive, disabled, onClick, index, step]);\n\n const renderIndicatorContent = () => {\n if (isError && errorIcon) {\n return errorIcon;\n }\n if (isCompleted && completedIcon) {\n return completedIcon;\n }\n if (showIcons && step.icon) {\n return step.icon;\n }\n if (showNumbers) {\n return index + 1;\n }\n return null;\n };\n\n return (\n <StepIndicator\n ref={ref}\n size={size}\n variant={variant}\n color={color}\n isActive={isActive}\n isCompleted={isCompleted}\n isError={isError}\n interactive={interactive}\n animated={animated}\n disabled={isDisabled}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n role={interactive ? 'button' : undefined}\n tabIndex={!interactive ? undefined : isDisabled ? -1 : 0}\n aria-label={`Step ${index + 1}: ${step.title}`}\n aria-current={isActive ? 'step' : undefined}\n aria-disabled={interactive && isDisabled ? true : undefined}\n data-testid={dataTestId}\n >\n {renderIndicatorContent()}\n </StepIndicator>\n );\n});\n\nStepIndicatorComponent.displayName = 'StepIndicator';\n\n/**\n * Step connector component\n */\nconst StepConnectorComponent = forwardRef<HTMLDivElement, StepConnectorProps>(({\n isCompleted,\n orientation,\n variant,\n color,\n // Defaults to the connector's own prior, unconditional behaviour (FUT-2773):\n // an external caller building a `StepConnectorProps` value that predates\n // this field keeps the transition it always had.\n animated = true,\n 'data-testid': dataTestId,\n}, ref) => (\n <StepConnector\n ref={ref}\n orientation={orientation}\n isCompleted={isCompleted}\n color={color}\n variant={variant}\n animated={animated}\n data-testid={dataTestId}\n />\n));\n\nStepConnectorComponent.displayName = 'StepConnector';\n\n/**\n * Step content component.\n *\n * Inert on purpose (FUT-2773): the indicator is the step's one focusable\n * `role=\"button\"` element — it already carries `aria-label=\"Step N: <title>\"`\n * — so the title/description block gets no `role`, `tabIndex`, click or key\n * handling of its own. Two independently-interactive elements per step gave\n * assistive tech two tab stops for what a caller means as a single control.\n */\nconst StepContentComponent = forwardRef<HTMLDivElement, StepContentProps>(({\n step,\n orientation,\n interactive,\n disabled,\n 'data-testid': dataTestId,\n}, ref) => (\n <StepContent\n ref={ref}\n orientation={orientation}\n interactive={interactive}\n disabled={Boolean(disabled || step.disabled)}\n data-testid={dataTestId}\n >\n <div className=\"step-title\">{step.title}</div>\n {step.description && (\n <div className=\"step-description\">{step.description}</div>\n )}\n </StepContent>\n));\n\nStepContentComponent.displayName = 'StepContent';\n\n/**\n * A plain wrapper around the styled row. Exporting the styled component itself\n * trips TS2742 — its inferred type names a pnpm-internal @mui/system path.\n */\nexport const StepItemRow: React.FC<{\n orientation: WorkflowStepProps['orientation'];\n isLast: boolean;\n children: React.ReactNode;\n}> = ({ orientation, isLast, children }) => (\n <StepItem orientation={orientation} isLast={isLast}>\n {children}\n </StepItem>\n);\n\nexport { StepConnectorComponent, StepContentComponent, StepIndicatorComponent };\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/form/Autocomplete/useAutocomplete.ts"],"sourcesContent":["import { useEffect, useId, useRef, useState } from 'react';\n\nimport {\n defaultGetKey,\n defaultGetLabel,\n defaultGetSuggestionType,\n defaultGetUrl,\n defaultOpenLink,\n filterSuggestions,\n firstGhostSuggestion,\n type MatchMode,\n} from './Autocomplete.helpers';\nimport { handleAutocompleteKey, type KeyContext } from './Autocomplete.keys';\nimport type { AutocompleteProps } from './Autocomplete.types';\n\ntype Setter<V> = React.Dispatch<React.SetStateAction<V>>;\n\n/** All mutable state + refs for one Autocomplete instance. */\ninterface AutocompleteState<T> {\n open: boolean;\n setOpen: Setter<boolean>;\n activeIndex: number;\n setActiveIndex: Setter<number>;\n ghost: string;\n setGhost: Setter<string>;\n inputValue: string;\n setInputValue: Setter<string>;\n composition: boolean;\n setComposition: Setter<boolean>;\n filteredSuggestions: T[];\n setFilteredSuggestions: Setter<T[]>;\n isInputFocused: boolean;\n setIsInputFocused: Setter<boolean>;\n justCompletedGhost: boolean;\n setJustCompletedGhost: Setter<boolean>;\n userClosedDropdown: boolean;\n setUserClosedDropdown: Setter<boolean>;\n /**\n * Mirrors `userClosedDropdown`, set synchronously wherever the state is\n * (see {@link setDeliberateClose}). An effect scheduled by one render and\n * flushed after a LATER render has already changed this flag reads a\n * stale, closed-over `userClosedDropdown` — but `.current` on a ref is\n * dereferenced live, so it always reflects the latest write regardless of\n * which render's closure is doing the reading (FUT-2780).\n */\n userClosedDropdownRef: React.RefObject<boolean>;\n inputRef: React.RefObject<HTMLInputElement | null>;\n listRef: React.RefObject<HTMLUListElement | null>;\n debounceRef: React.RefObject<number | undefined>;\n}\n\nfunction useAutocompleteState<T>(value: string, suggestions: T[]): AutocompleteState<T> {\n const [open, setOpen] = useState(false);\n const [activeIndex, setActiveIndex] = useState(-1);\n const [ghost, setGhost] = useState('');\n const [inputValue, setInputValue] = useState(value);\n const [composition, setComposition] = useState(false);\n const [filteredSuggestions, setFilteredSuggestions] = useState<T[]>(suggestions);\n const [isInputFocused, setIsInputFocused] = useState(false);\n const [justCompletedGhost, setJustCompletedGhost] = useState(false);\n const [userClosedDropdown, setUserClosedDropdown] = useState(false);\n const userClosedDropdownRef = useRef(false);\n const inputRef = useRef<HTMLInputElement>(null);\n const listRef = useRef<HTMLUListElement | null>(null);\n const debounceRef = useRef<number | undefined>(undefined);\n return {\n open, setOpen, activeIndex, setActiveIndex, ghost, setGhost, inputValue, setInputValue,\n composition, setComposition, filteredSuggestions, setFilteredSuggestions, isInputFocused,\n setIsInputFocused, justCompletedGhost, setJustCompletedGhost, userClosedDropdown,\n setUserClosedDropdown, userClosedDropdownRef, inputRef, listRef, debounceRef,\n };\n}\n\n/**\n * Set the \"this close was deliberate\" flag in both the ref effects read\n * synchronously (live, even from a stale closure) and the state the rest of\n * the component reads for render — every call site that touches\n * `userClosedDropdown` goes through this so the two never drift (FUT-2780).\n */\nfunction setDeliberateClose<T>(s: AutocompleteState<T>, closed: boolean): void {\n s.userClosedDropdownRef.current = closed;\n s.setUserClosedDropdown(closed);\n}\n\n// ---- effects (one tiny hook each; explicit params keep deps complete) --------\n\nfunction useValueSync(value: string, setInputValue: Setter<string>): void {\n useEffect(() => setInputValue(value), [value, setInputValue]);\n}\n\nfunction useDebounceCleanup(debounceRef: React.RefObject<number | undefined>): void {\n useEffect(\n () => () => {\n if (debounceRef.current) window.clearTimeout(debounceRef.current);\n },\n [debounceRef],\n );\n}\n\nfunction useScrollActiveIntoView(\n activeIndex: number,\n optionIdPrefix: string,\n listRef: React.RefObject<HTMLUListElement | null>,\n): void {\n useEffect(() => {\n if (activeIndex < 0 || !listRef.current) return;\n document\n .getElementById(`${optionIdPrefix}-${activeIndex}`)\n ?.scrollIntoView({ block: 'nearest' });\n }, [activeIndex, optionIdPrefix, listRef]);\n}\n\nfunction useGhostFlagReset(justCompletedGhost: boolean, setJustCompletedGhost: Setter<boolean>): void {\n useEffect(() => {\n if (!justCompletedGhost) return;\n const timer = setTimeout(() => setJustCompletedGhost(false), 50);\n return () => clearTimeout(timer);\n }, [justCompletedGhost, setJustCompletedGhost]);\n}\n\nfunction useLoadingOpen(\n isLoading: boolean,\n inputValue: string,\n disabled: boolean,\n userClosedDropdownRef: React.RefObject<boolean>,\n setOpen: Setter<boolean>,\n setActiveIndex: Setter<number>,\n): void {\n useEffect(() => {\n if (isLoading && inputValue.trim().length > 0 && !disabled && !userClosedDropdownRef.current) setOpen(true);\n if (disabled) {\n setOpen(false);\n setActiveIndex(-1);\n }\n }, [isLoading, inputValue, disabled, userClosedDropdownRef, setOpen, setActiveIndex]);\n}\n\n/** Inputs to the auto-open check, all primitive/stable so effect deps stay complete. */\ninterface AutoOpenArgs {\n inputValue: string;\n isInputFocused: boolean;\n composition: boolean;\n justCompletedGhost: boolean;\n userClosedDropdownRef: React.RefObject<boolean>;\n activeIndex: number;\n setOpen: Setter<boolean>;\n setActiveIndex: Setter<number>;\n}\n\n/** Auto-open the dropdown once local filtering has a fresh result set. */\nfunction maybeAutoOpen(a: AutoOpenArgs, hasResults: boolean): void {\n const canAutoOpen =\n a.inputValue.trim() &&\n a.isInputFocused &&\n !a.composition &&\n !a.justCompletedGhost &&\n !a.userClosedDropdownRef.current;\n if (!canAutoOpen) return;\n a.setOpen(true);\n if (hasResults && a.activeIndex === -1) a.setActiveIndex(0);\n}\n\nfunction useLocalFilter<T>(p: AutocompleteProps<T>, s: AutocompleteState<T>): void {\n const propSuggestions = p.suggestions;\n const getLabel = p.getLabel ?? defaultGetLabel;\n const matchMode: MatchMode = p.matchMode ?? 'contains';\n const async = Boolean(p.async);\n const {\n inputValue, isInputFocused, composition, justCompletedGhost, userClosedDropdown, activeIndex,\n setFilteredSuggestions, setOpen, setActiveIndex, userClosedDropdownRef,\n } = s;\n useEffect(() => {\n const suggestions = propSuggestions ?? [];\n if (async || !inputValue) {\n setFilteredSuggestions(suggestions);\n return;\n }\n const filtered = filterSuggestions(suggestions, inputValue, matchMode, getLabel);\n setFilteredSuggestions(filtered);\n maybeAutoOpen(\n { inputValue, isInputFocused, composition, justCompletedGhost, userClosedDropdownRef, activeIndex, setOpen, setActiveIndex },\n filtered.length > 0,\n );\n // `userClosedDropdown` (state) stays a dependency so this effect still\n // reruns on every change of it, same as before — only the VALUE read\n // inside `maybeAutoOpen` moved to the ref (see `userClosedDropdownRef`'s\n // doc comment).\n }, [\n propSuggestions, inputValue, async, getLabel, matchMode, isInputFocused, composition,\n justCompletedGhost, userClosedDropdown, activeIndex, setFilteredSuggestions, setOpen, setActiveIndex,\n userClosedDropdownRef,\n ]);\n}\n\nfunction useGhostText<T>(p: AutocompleteProps<T>, s: AutocompleteState<T>): void {\n const getLabel = p.getLabel ?? defaultGetLabel;\n const getType = p.getSuggestionType ?? defaultGetSuggestionType;\n const showGhost = p.showGhostText ?? true;\n const { inputValue, filteredSuggestions, isInputFocused, composition, setGhost } = s;\n useEffect(() => {\n if (!inputValue || !isInputFocused || composition || !showGhost) {\n setGhost('');\n return;\n }\n const first = firstGhostSuggestion(filteredSuggestions, inputValue, getLabel, getType);\n setGhost(first ? getLabel(first).slice(inputValue.length) : '');\n }, [inputValue, filteredSuggestions, isInputFocused, composition, showGhost, getLabel, getType, setGhost]);\n}\n\n// ---- selection (split by mode to keep each function under the complexity bar) -\n\nfunction commitMultiSelect<T>(item: T, p: AutocompleteProps<T>, s: AutocompleteState<T>, onChange: (v: string) => void): void {\n const getKey = p.getKey ?? defaultGetKey;\n const current = p.selectedItems ?? [];\n if (!current.some((sel) => getKey(sel) === getKey(item))) p.onSelectedItemsChange?.([...current, item]);\n s.setInputValue('');\n onChange('');\n setDeliberateClose(s, false);\n}\n\nfunction commitSingleSelect<T>(item: T, p: AutocompleteProps<T>, s: AutocompleteState<T>, onChange: (v: string) => void): void {\n const label = (p.getLabel ?? defaultGetLabel)(item);\n s.setInputValue(label);\n onChange(label);\n}\n\n/** Apply a pick: open a link suggestion, or commit a search one to the input. */\nfunction commitPick<T>(\n item: T,\n linkUrl: string | null,\n p: AutocompleteProps<T>,\n s: AutocompleteState<T>,\n onChange: (v: string) => void,\n): void {\n if (linkUrl !== null) (p.openLink ?? defaultOpenLink)(linkUrl, item);\n else if (p.multiple) commitMultiSelect(item, p, s, onChange);\n else commitSingleSelect(item, p, s, onChange);\n}\n\nfunction runSelectItem<T>(item: T, p: AutocompleteProps<T>, s: AutocompleteState<T>, onChange: (v: string) => void): void {\n const url = (p.getUrl ?? defaultGetUrl)(item);\n const isLink = (p.getSuggestionType ?? defaultGetSuggestionType)(item) === 'link' && Boolean(url);\n // A single-select pick (search or link) ends the current search: the list\n // stays closed until the user types again. `multiple` mode is unchanged —\n // commitMultiSelect already clears inputValue and resets the flag itself,\n // so the empty-input branch of the filter effect keeps the list closed.\n const isSingleSelectPick = isLink || !p.multiple;\n // Cancel a still-pending keystroke debounce BEFORE dispatching the pick, so\n // no branch below — including `openLink`, which never touches `onChange`\n // at all — can leave it armed to fire the STALE pre-pick text later\n // (FUT-2779 #1). `commitSingleSelect`/`commitMultiSelect` already clear it\n // as a side effect of calling the same `debouncedOnChange`; this makes it\n // unconditional so a `link` pick (which skips `onChange` entirely) is\n // covered too.\n if (s.debounceRef.current) window.clearTimeout(s.debounceRef.current);\n commitPick(item, isLink ? (url as string) : null, p, s, onChange);\n s.setOpen(false);\n s.setActiveIndex(-1);\n p.onSelect?.(item);\n s.inputRef.current?.focus();\n // Set LAST so a re-fired `onFocus` cannot clear the flag. The close itself\n // relies on the input never blurring during a pick (the option's\n // `onMouseDown` preventDefault, and Enter keeps focus): `onFocus` reopens a\n // non-empty input directly, without reading this flag. The REF half is set\n // in the same synchronous tick as the pick, so an effect scheduled by an\n // earlier keystroke — and still pending when this runs — reads the\n // up-to-date value instead of the one it closed over (FUT-2780).\n if (isSingleSelectPick) setDeliberateClose(s, true);\n}\n\nfunction buildKeyContext<T>(\n p: AutocompleteProps<T>,\n s: AutocompleteState<T>,\n selectItem: (item: T) => void,\n onChange: (v: string) => void,\n): KeyContext<T> {\n return {\n open: s.open, activeIndex: s.activeIndex, filteredSuggestions: s.filteredSuggestions,\n maxVisibleItems: p.maxVisibleItems ?? 10, allowFreeText: p.allowFreeText ?? true,\n inputValue: s.inputValue, ghost: s.ghost, isInputFocused: s.isInputFocused,\n multiple: Boolean(p.multiple), selectedItems: p.selectedItems ?? [],\n getLabel: p.getLabel ?? defaultGetLabel,\n getSuggestionType: p.getSuggestionType ?? defaultGetSuggestionType,\n setOpen: s.setOpen, setActiveIndex: s.setActiveIndex,\n setUserClosedDropdown: (closed: boolean) => setDeliberateClose(s, closed),\n setInputValue: s.setInputValue, setGhost: s.setGhost, setJustCompletedGhost: s.setJustCompletedGhost,\n debouncedOnChange: onChange, selectItem, onSelectedItemsChange: p.onSelectedItemsChange,\n };\n}\n\n/** The full view-model the presentational component renders. */\nexport interface AutocompleteView<T> {\n id: string;\n listId: string;\n optionIdPrefix: string;\n state: AutocompleteState<T>;\n visibleSuggestions: T[];\n activeDescendant: string | undefined;\n selectItem: (item: T) => void;\n removeSelectedItem: (item: T) => void;\n onKeyDown: (e: React.KeyboardEvent<HTMLInputElement>) => void;\n onInputChange: (e: React.ChangeEvent<HTMLInputElement>) => void;\n onFocus: () => void;\n onBlur: () => void;\n onClickAway: () => void;\n}\n\n/** Wire state, effects, and (plain, per-render) handlers for the Autocomplete component. */\nexport function useAutocomplete<T>(p: AutocompleteProps<T>): AutocompleteView<T> {\n const componentId = useId();\n const id = p.id || componentId;\n const optionIdPrefix = `${id}-option`;\n const s = useAutocompleteState<T>(p.value, p.suggestions ?? []);\n\n const debouncedOnChange = (val: string): void => {\n if (s.debounceRef.current) window.clearTimeout(s.debounceRef.current);\n s.debounceRef.current = window.setTimeout(() => p.onChange(val), p.debounceMs ?? 150);\n };\n\n useValueSync(p.value, s.setInputValue);\n useDebounceCleanup(s.debounceRef);\n useScrollActiveIntoView(s.activeIndex, optionIdPrefix, s.listRef);\n useGhostFlagReset(s.justCompletedGhost, s.setJustCompletedGhost);\n useLoadingOpen(\n Boolean(p.isLoading),\n s.inputValue,\n Boolean(p.disabled),\n s.userClosedDropdownRef,\n s.setOpen,\n s.setActiveIndex,\n );\n useLocalFilter(p, s);\n useGhostText(p, s);\n\n const selectItem = (item: T): void => runSelectItem(item, p, s, debouncedOnChange);\n\n return {\n id,\n listId: `${id}-listbox`,\n optionIdPrefix,\n state: s,\n visibleSuggestions: s.filteredSuggestions.slice(0, p.maxVisibleItems ?? 10),\n activeDescendant: s.activeIndex >= 0 ? `${optionIdPrefix}-${s.activeIndex}` : undefined,\n selectItem,\n removeSelectedItem: (item: T): void => {\n const getKey = p.getKey ?? defaultGetKey;\n p.onSelectedItemsChange?.((p.selectedItems ?? []).filter((sel) => getKey(sel) !== getKey(item)));\n s.inputRef.current?.focus();\n },\n onKeyDown: (e: React.KeyboardEvent<HTMLInputElement>): void =>\n handleAutocompleteKey(e, s.composition, buildKeyContext(p, s, selectItem, debouncedOnChange)),\n onInputChange: (e: React.ChangeEvent<HTMLInputElement>): void => {\n s.setInputValue(e.target.value);\n debouncedOnChange(e.target.value);\n if (!s.open || s.filteredSuggestions.length === 0) s.setActiveIndex(-1);\n setDeliberateClose(s, false);\n },\n // Unconditionally reopens on a non-empty input, unguarded by\n // `userClosedDropdownRef` — plausible on a touch device that blurs the\n // input on `touchstart` before a tap's own `click`/`mousedown` reaches the\n // option (FUT-2779 #2). Checked under Playwright touch emulation\n // (`hasTouch`/`isMobile` context, both the `.tap()` API and raw CDP\n // `Input.dispatchTouchEvent` at the option's coordinates) against this\n // Chromium build: `document.activeElement` never left the input across\n // the touch, so the reopen never happened — not reproduced, left\n // unguarded per the ticket's decision rather than fixed blind.\n onFocus: (): void => {\n s.setIsInputFocused(true);\n setDeliberateClose(s, false);\n if (!s.inputValue.trim()) return;\n s.setOpen(true);\n if (s.filteredSuggestions.length > 0 && s.activeIndex === -1) s.setActiveIndex(0);\n },\n onBlur: (): void => {\n window.setTimeout(() => s.setIsInputFocused(false), 150);\n },\n onClickAway: (): void => {\n s.setOpen(false);\n s.setActiveIndex(-1);\n setDeliberateClose(s, true);\n },\n };\n}\n"],"mappings":"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","names":[]}