@12-apps/ui 6.39.7 → 6.39.8

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 (25) hide show
  1. package/dist/_internal/components/form/Autocomplete/Autocomplete.helpers.js +1 -1
  2. package/dist/_internal/components/form/Autocomplete/Autocomplete.js +5 -5
  3. package/dist/_internal/components/form/Autocomplete/Autocomplete.keys.js +2 -2
  4. package/dist/_internal/components/form/Autocomplete/Autocomplete.parts.js +2 -2
  5. package/dist/_internal/components/form/Autocomplete/useAutocomplete.js +3 -3
  6. package/dist/_internal/components/form/index.js +5 -5
  7. package/dist/_internal/components/index.js +5 -5
  8. package/dist/{chunk-PH36XEB3.js → chunk-DQZCQV2C.js} +4 -4
  9. package/dist/{chunk-BN742L2M.js → chunk-H6AWKLOV.js} +13 -5
  10. package/dist/chunk-H6AWKLOV.js.map +1 -0
  11. package/dist/{chunk-362OGE5J.js → chunk-HBRKA67N.js} +3 -3
  12. package/dist/{chunk-XBHQT4BQ.js → chunk-JXS56EW5.js} +3 -3
  13. package/dist/{chunk-XBHQT4BQ.js.map → chunk-JXS56EW5.js.map} +1 -1
  14. package/dist/{chunk-JDFTIK4L.js → chunk-PELRSZFU.js} +2 -2
  15. package/dist/form/Autocomplete.js +5 -5
  16. package/dist/types/components/form/Autocomplete/Autocomplete.helpers.d.ts +16 -3
  17. package/dist/types/components/form/Autocomplete/Autocomplete.helpers.d.ts.map +1 -1
  18. package/dist/types/components/form/Autocomplete/Autocomplete.parts.d.ts.map +1 -1
  19. package/package.json +1 -1
  20. package/src/components/form/Autocomplete/Autocomplete.helpers.ts +23 -5
  21. package/src/components/form/Autocomplete/Autocomplete.parts.tsx +17 -3
  22. package/dist/chunk-BN742L2M.js.map +0 -1
  23. /package/dist/{chunk-PH36XEB3.js.map → chunk-DQZCQV2C.js.map} +0 -0
  24. /package/dist/{chunk-362OGE5J.js.map → chunk-HBRKA67N.js.map} +0 -0
  25. /package/dist/{chunk-JDFTIK4L.js.map → chunk-PELRSZFU.js.map} +0 -0
@@ -7,7 +7,7 @@ import {
7
7
  filterSuggestions,
8
8
  firstGhostSuggestion,
9
9
  highlightLabel
10
- } from "../../../../chunk-XBHQT4BQ.js";
10
+ } from "../../../../chunk-JXS56EW5.js";
11
11
  import "../../../../chunk-PZ5AY32C.js";
12
12
  export {
13
13
  defaultGetKey,
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  Autocomplete,
3
3
  Autocomplete_default
4
- } from "../../../../chunk-PH36XEB3.js";
5
- import "../../../../chunk-362OGE5J.js";
6
- import "../../../../chunk-BN742L2M.js";
7
- import "../../../../chunk-JDFTIK4L.js";
8
- import "../../../../chunk-XBHQT4BQ.js";
4
+ } from "../../../../chunk-DQZCQV2C.js";
5
+ import "../../../../chunk-HBRKA67N.js";
6
+ import "../../../../chunk-H6AWKLOV.js";
7
+ import "../../../../chunk-PELRSZFU.js";
8
+ import "../../../../chunk-JXS56EW5.js";
9
9
  import "../../../../chunk-CGO452DC.js";
10
10
  import "../../../../chunk-GDN2LUTZ.js";
11
11
  import "../../../../chunk-7FDU3FIN.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  handleAutocompleteKey
3
- } from "../../../../chunk-JDFTIK4L.js";
4
- import "../../../../chunk-XBHQT4BQ.js";
3
+ } from "../../../../chunk-PELRSZFU.js";
4
+ import "../../../../chunk-JXS56EW5.js";
5
5
  import "../../../../chunk-PZ5AY32C.js";
6
6
  export {
7
7
  handleAutocompleteKey
@@ -6,8 +6,8 @@ import {
6
6
  NoResultsRow,
7
7
  SuggestionListBox,
8
8
  suggestionTypeIcon
9
- } from "../../../../chunk-BN742L2M.js";
10
- import "../../../../chunk-XBHQT4BQ.js";
9
+ } from "../../../../chunk-H6AWKLOV.js";
10
+ import "../../../../chunk-JXS56EW5.js";
11
11
  import "../../../../chunk-CGO452DC.js";
12
12
  import "../../../../chunk-GDN2LUTZ.js";
13
13
  import "../../../../chunk-7FDU3FIN.js";
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  useAutocomplete
3
- } from "../../../../chunk-362OGE5J.js";
4
- import "../../../../chunk-JDFTIK4L.js";
5
- import "../../../../chunk-XBHQT4BQ.js";
3
+ } from "../../../../chunk-HBRKA67N.js";
4
+ import "../../../../chunk-PELRSZFU.js";
5
+ import "../../../../chunk-JXS56EW5.js";
6
6
  import "../../../../chunk-PZ5AY32C.js";
7
7
  export {
8
8
  useAutocomplete
@@ -139,11 +139,11 @@ import "../../../chunk-7VRCGWQL.js";
139
139
  import "../../../chunk-2LXHUGYB.js";
140
140
  import {
141
141
  Autocomplete
142
- } from "../../../chunk-PH36XEB3.js";
143
- import "../../../chunk-362OGE5J.js";
144
- import "../../../chunk-BN742L2M.js";
145
- import "../../../chunk-JDFTIK4L.js";
146
- import "../../../chunk-XBHQT4BQ.js";
142
+ } from "../../../chunk-DQZCQV2C.js";
143
+ import "../../../chunk-HBRKA67N.js";
144
+ import "../../../chunk-H6AWKLOV.js";
145
+ import "../../../chunk-PELRSZFU.js";
146
+ import "../../../chunk-JXS56EW5.js";
147
147
  import "../../../chunk-BO6S47KI.js";
148
148
  import {
149
149
  Calendar
@@ -345,11 +345,11 @@ import "../../chunk-7VRCGWQL.js";
345
345
  import "../../chunk-2LXHUGYB.js";
346
346
  import {
347
347
  Autocomplete
348
- } from "../../chunk-PH36XEB3.js";
349
- import "../../chunk-362OGE5J.js";
350
- import "../../chunk-BN742L2M.js";
351
- import "../../chunk-JDFTIK4L.js";
352
- import "../../chunk-XBHQT4BQ.js";
348
+ } from "../../chunk-DQZCQV2C.js";
349
+ import "../../chunk-HBRKA67N.js";
350
+ import "../../chunk-H6AWKLOV.js";
351
+ import "../../chunk-PELRSZFU.js";
352
+ import "../../chunk-JXS56EW5.js";
353
353
  import "../../chunk-BO6S47KI.js";
354
354
  import {
355
355
  Calendar
@@ -1,17 +1,17 @@
1
1
  import {
2
2
  useAutocomplete
3
- } from "./chunk-362OGE5J.js";
3
+ } from "./chunk-HBRKA67N.js";
4
4
  import {
5
5
  AutocompleteInput,
6
6
  ChipList,
7
7
  DefaultSuggestion,
8
8
  SuggestionListBox
9
- } from "./chunk-BN742L2M.js";
9
+ } from "./chunk-H6AWKLOV.js";
10
10
  import {
11
11
  defaultGetKey,
12
12
  defaultGetLabel,
13
13
  defaultGetSuggestionType
14
- } from "./chunk-XBHQT4BQ.js";
14
+ } from "./chunk-JXS56EW5.js";
15
15
 
16
16
  // src/components/form/Autocomplete/Autocomplete.tsx
17
17
  import Box from "@mui/material/Box/index.js";
@@ -131,4 +131,4 @@ export {
131
131
  Autocomplete,
132
132
  Autocomplete_default
133
133
  };
134
- //# sourceMappingURL=chunk-PH36XEB3.js.map
134
+ //# sourceMappingURL=chunk-DQZCQV2C.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  highlightLabel
3
- } from "./chunk-XBHQT4BQ.js";
3
+ } from "./chunk-JXS56EW5.js";
4
4
  import {
5
5
  fieldTextFieldStyles
6
6
  } from "./chunk-CGO452DC.js";
@@ -23,6 +23,7 @@ import Popper from "@mui/material/Popper/index.js";
23
23
  import TextField from "@mui/material/TextField/index.js";
24
24
  import Typography from "@mui/material/Typography/index.js";
25
25
  import { styled, useTheme } from "@mui/material/styles/index.js";
26
+ import React from "react";
26
27
  import { jsx, jsxs } from "react/jsx-runtime";
27
28
  var StyledPopper = styled(Popper)(({ theme }) => ({
28
29
  zIndex: theme.zIndex.tooltip,
@@ -144,7 +145,7 @@ function DefaultSuggestion({
144
145
  }) {
145
146
  const label = getLabel(item);
146
147
  const description = getDescription?.(item);
147
- const displayLabel = highlightLabel(label, state.query, matchMode);
148
+ const segments = highlightLabel(label, state.query, matchMode);
148
149
  return /* @__PURE__ */ jsxs(
149
150
  Box,
150
151
  {
@@ -153,7 +154,8 @@ function DefaultSuggestion({
153
154
  alignItems: "center",
154
155
  gap: 1,
155
156
  width: "100%",
156
- // Bold the matched prefix (not a yellow <mark> highlight).
157
+ // Bold every run the query matched, in any match mode but fuzzy — not
158
+ // only a prefix, even under `startsWith` (not a yellow <mark> highlight).
157
159
  "& mark": { backgroundColor: "transparent", color: "inherit", fontWeight: 700 }
158
160
  },
159
161
  children: [
@@ -161,7 +163,13 @@ function DefaultSuggestion({
161
163
  /* @__PURE__ */ jsx(
162
164
  ListItemText,
163
165
  {
164
- primary: /* @__PURE__ */ jsx("span", { dangerouslySetInnerHTML: { __html: displayLabel } }),
166
+ primary: /* @__PURE__ */ jsx("span", { children: segments.map(
167
+ (segment, index) => (
168
+ // The runs are derived from one label and never reorder, so the
169
+ // position is a stable key.
170
+ segment.match ? /* @__PURE__ */ jsx("mark", { children: segment.text }, index) : /* @__PURE__ */ jsx(React.Fragment, { children: segment.text }, index)
171
+ )
172
+ ) }),
165
173
  secondary: description
166
174
  }
167
175
  )
@@ -267,4 +275,4 @@ export {
267
275
  NoResultsRow,
268
276
  SuggestionListBox
269
277
  };
270
- //# sourceMappingURL=chunk-BN742L2M.js.map
278
+ //# sourceMappingURL=chunk-H6AWKLOV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/form/Autocomplete/Autocomplete.parts.tsx"],"sourcesContent":["import LinkIcon from '@mui/icons-material/Link';\nimport SearchIcon from '@mui/icons-material/Search';\nimport Box from '@mui/material/Box/index.js';\nimport Chip from '@mui/material/Chip/index.js';\nimport CircularProgress from '@mui/material/CircularProgress/index.js';\nimport List from '@mui/material/List/index.js';\nimport ListItem from '@mui/material/ListItem/index.js';\nimport ListItemText from '@mui/material/ListItemText/index.js';\nimport Paper from '@mui/material/Paper/index.js';\nimport Popper from '@mui/material/Popper/index.js';\nimport TextField from '@mui/material/TextField/index.js';\nimport Typography from '@mui/material/Typography/index.js';\nimport { styled, useTheme } from '@mui/material/styles/index.js';\nimport React from 'react';\n\nimport { highlightLabel, type MatchMode } from './Autocomplete.helpers';\nimport type { SuggestionItemState, SuggestionType } from './Autocomplete.types';\nimport type { AutocompleteCopy } from '../../../copy';\nimport { fieldTextFieldStyles } from '../../../tokens/field-height';\nimport { rem, sxRem } from '../../../tokens/relative';\n\nconst StyledPopper = styled(Popper)(({ theme }) => ({\n zIndex: theme.zIndex.tooltip,\n width: '100%',\n maxHeight: rem(theme, 300),\n overflow: 'auto',\n // Popper.js writes the computed position (and stamps `data-popper-placement`)\n // in a layout effect that can land AFTER the first paint. Until it does, the\n // element would paint once unpositioned — at the offset-parent origin, far\n // left and full width — then jump under the input, a visible per-keystroke\n // flash as the list re-renders. Hide that unpositioned first frame; it becomes\n // visible the instant popper assigns a placement.\n '&:not([data-popper-placement])': { visibility: 'hidden' },\n}));\n\nconst InlineSuggestionDisplay = styled('div')(({ theme }) => ({\n position: 'absolute',\n pointerEvents: 'none',\n left: rem(theme, 14), // Match TextField padding\n top: '50%',\n transform: 'translateY(-50%)',\n fontSize: 'inherit',\n fontFamily: 'inherit',\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n zIndex: 1,\n}));\n\nconst UserTextTwin = styled('span')({\n visibility: 'hidden',\n});\n\nconst GhostText = styled('span')(({ theme }) => ({\n color: theme.palette.text.secondary,\n opacity: 0.6,\n}));\n\nconst ChipContainer = styled(Box)(({ theme }) => ({\n display: 'flex',\n flexWrap: 'wrap',\n gap: theme.spacing(0.5),\n marginBottom: theme.spacing(1),\n}));\n\n/** Leading icon for a typed suggestion (search vs. link); null for untyped items. */\nexport function suggestionTypeIcon(type: SuggestionType | undefined): React.ReactNode {\n const sx = { color: 'text.secondary', flexShrink: 0 } as const;\n if (type === 'link') return <LinkIcon fontSize=\"small\" sx={sx} />;\n if (type === 'search') return <SearchIcon fontSize=\"small\" sx={sx} />;\n return null;\n}\n\n/** The inline ghost-text overlay: an invisible twin of the typed text + the grey remainder. */\nfunction GhostOverlay({ inputValue, ghost }: { inputValue: string; ghost: string }): React.JSX.Element {\n return (\n <InlineSuggestionDisplay>\n <UserTextTwin>{inputValue}</UserTextTwin>\n <GhostText>{ghost}</GhostText>\n </InlineSuggestionDisplay>\n );\n}\n\nexport interface AutocompleteInputProps {\n id: string;\n listId: string;\n inputRef: React.RefObject<HTMLInputElement | null>;\n inputValue: string;\n ghost: string;\n showGhost: boolean;\n isInputFocused: boolean;\n open: boolean;\n activeDescendant: string | undefined;\n isLoading: boolean;\n disabled: boolean;\n autoFocus: boolean;\n placeholder: string;\n startAdornment?: React.ReactNode;\n inputAriaLabel?: string;\n inputClassName?: string;\n onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;\n onKeyDown: (e: React.KeyboardEvent<HTMLInputElement>) => void;\n onFocus: () => void;\n onBlur: () => void;\n onCompositionStart: () => void;\n onCompositionEnd: () => void;\n}\n\n/** The combobox text field plus its inline ghost-text overlay. */\nexport function AutocompleteInput(props: AutocompleteInputProps): React.JSX.Element {\n const theme = useTheme();\n const showOverlay = Boolean(props.ghost) && props.showGhost && props.isInputFocused;\n return (\n <Box sx={{ position: 'relative' }}>\n {showOverlay && <GhostOverlay inputValue={props.inputValue} ghost={props.ghost} />}\n <TextField\n ref={props.inputRef}\n fullWidth\n sx={fieldTextFieldStyles}\n value={props.inputValue}\n onChange={props.onChange}\n onKeyDown={props.onKeyDown}\n onFocus={props.onFocus}\n onBlur={props.onBlur}\n onCompositionStart={props.onCompositionStart}\n onCompositionEnd={props.onCompositionEnd}\n placeholder={props.placeholder}\n disabled={props.disabled}\n autoFocus={props.autoFocus}\n className={props.inputClassName}\n InputProps={{\n startAdornment: props.startAdornment,\n endAdornment: props.isLoading ? <CircularProgress size={rem(theme, 20)} /> : undefined,\n }}\n inputProps={{\n role: 'combobox',\n 'aria-expanded': props.open,\n 'aria-controls': props.open ? props.listId : undefined,\n 'aria-activedescendant': props.activeDescendant,\n 'aria-autocomplete': 'list',\n 'aria-label': props.inputAriaLabel,\n id: props.id,\n }}\n />\n </Box>\n );\n}\n\n/** Selected-item chips (multiple mode). */\nexport function ChipList<T>({\n items,\n getKey,\n getLabel,\n onRemove,\n chipClassName,\n}: {\n items: T[];\n getKey: (item: T) => string;\n getLabel: (item: T) => string;\n onRemove: (item: T) => void;\n chipClassName?: string;\n}): React.JSX.Element {\n return (\n <ChipContainer data-testid=\"selected-items-container\">\n {items.map((item, index) => (\n <Chip\n key={`${getKey(item)}-${index}`}\n label={getLabel(item)}\n onDelete={() => onRemove(item)}\n size=\"small\"\n className={chipClassName}\n data-testid={`selected-chip-${index}`}\n />\n ))}\n </ChipContainer>\n );\n}\n\n/** Default suggestion row: per-type icon + highlighted label + optional description. */\nexport function DefaultSuggestion<T>({\n item,\n state,\n getLabel,\n getDescription,\n getSuggestionType,\n matchMode,\n}: {\n item: T;\n state: SuggestionItemState;\n getLabel: (item: T) => string;\n getDescription?: (item: T) => string | undefined;\n getSuggestionType: (item: T) => SuggestionType | undefined;\n matchMode: MatchMode;\n}): React.JSX.Element {\n const label = getLabel(item);\n const description = getDescription?.(item);\n // Each run is a React text child, so the label is escaped however it reads.\n const segments = highlightLabel(label, state.query, matchMode);\n return (\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n gap: 1,\n width: '100%',\n // Bold every run the query matched, in any match mode but fuzzy — not\n // only a prefix, even under `startsWith` (not a yellow <mark> highlight).\n '& mark': { backgroundColor: 'transparent', color: 'inherit', fontWeight: 700 },\n }}\n >\n {suggestionTypeIcon(getSuggestionType(item))}\n <ListItemText\n primary={\n <span>\n {segments.map((segment, index) =>\n // The runs are derived from one label and never reorder, so the\n // position is a stable key.\n segment.match ? (\n <mark key={index}>{segment.text}</mark>\n ) : (\n <React.Fragment key={index}>{segment.text}</React.Fragment>\n ),\n )}\n </span>\n }\n secondary={description}\n />\n </Box>\n );\n}\n\n/** A \"Loading…\" row shown while async suggestions resolve. */\nexport function LoadingRow({ label }: { label: string }): React.JSX.Element {\n const theme = useTheme();\n return (\n <ListItem>\n <Box display=\"flex\" alignItems=\"center\" gap={1}>\n <CircularProgress size={rem(theme, 16)} />\n <Typography variant=\"body2\" color=\"text.secondary\">\n {label}\n </Typography>\n </Box>\n </ListItem>\n );\n}\n\n/** The empty \"No results found\" row. */\nexport function NoResultsRow({ label }: { label: string }): React.JSX.Element {\n return (\n <ListItem>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {label}\n </Typography>\n </ListItem>\n );\n}\n\n/** Keep the Popper the same width as its anchor input. */\nconst SAME_WIDTH_MODIFIER = {\n name: 'sameWidth',\n enabled: true,\n fn: ({ state }: { state: { elements: { reference?: unknown }; styles: { popper?: Record<string, string> }; rects: { reference: { width: number } } } }) => {\n if (state.elements.reference && state.styles.popper) {\n state.styles.popper.width = `${state.rects.reference.width}px`;\n }\n },\n phase: 'beforeWrite' as const,\n requires: ['computeStyles'],\n};\n\nexport interface SuggestionListBoxProps<T> {\n copy: AutocompleteCopy;\n open: boolean;\n anchorEl: HTMLElement | null;\n portal: boolean | { container?: HTMLElement };\n listRef: React.RefObject<HTMLUListElement | null>;\n listId: string;\n optionIdPrefix: string;\n items: T[];\n activeIndex: number;\n isLoading: boolean;\n showNoResults: boolean;\n getKey: (item: T) => string;\n onSelect: (item: T) => void;\n onHover: (index: number) => void;\n renderItem: (item: T, active: boolean) => React.ReactNode;\n listClassName?: string;\n itemClassName?: string;\n activeItemClassName?: string;\n}\n\n/** The suggestions dropdown: a same-width Popper with the option list + loading/empty rows. */\nexport function SuggestionListBox<T>({\n copy,\n open,\n anchorEl,\n portal,\n listRef,\n listId,\n optionIdPrefix,\n items,\n activeIndex,\n isLoading,\n showNoResults,\n getKey,\n onSelect,\n onHover,\n renderItem,\n listClassName,\n itemClassName,\n activeItemClassName,\n}: SuggestionListBoxProps<T>): React.JSX.Element {\n return (\n <StyledPopper\n open={open}\n anchorEl={anchorEl}\n placement=\"bottom-start\"\n disablePortal={!portal}\n modifiers={[SAME_WIDTH_MODIFIER]}\n >\n <Paper elevation={8} className={listClassName} data-testid=\"suggestions-dropdown\">\n <List\n ref={listRef}\n role=\"listbox\"\n id={listId}\n dense\n sx={{ maxHeight: sxRem(300), overflow: 'auto' }}\n data-testid=\"suggestions-list\"\n >\n {items.map((item, index) => (\n <ListItem\n key={getKey(item)}\n id={`${optionIdPrefix}-${index}`}\n role=\"option\"\n component=\"div\"\n sx={{\n cursor: 'pointer',\n backgroundColor: index === activeIndex ? 'action.hover' : 'transparent',\n '&:hover': { backgroundColor: 'action.hover' },\n }}\n aria-selected={index === activeIndex}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => onSelect(item)}\n onMouseEnter={() => onHover(index)}\n className={`${itemClassName} ${index === activeIndex ? activeItemClassName : ''}`}\n data-testid={`suggestion-item-${index}`}\n >\n {renderItem(item, index === activeIndex)}\n </ListItem>\n ))}\n {isLoading && <LoadingRow label={copy.loading} />}\n {showNoResults && <NoResultsRow label={copy.noResults} />}\n </List>\n </Paper>\n </StyledPopper>\n );\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  handleAutocompleteKey
3
- } from "./chunk-JDFTIK4L.js";
3
+ } from "./chunk-PELRSZFU.js";
4
4
  import {
5
5
  defaultGetKey,
6
6
  defaultGetLabel,
@@ -9,7 +9,7 @@ import {
9
9
  defaultOpenLink,
10
10
  filterSuggestions,
11
11
  firstGhostSuggestion
12
- } from "./chunk-XBHQT4BQ.js";
12
+ } from "./chunk-JXS56EW5.js";
13
13
 
14
14
  // src/components/form/Autocomplete/useAutocomplete.ts
15
15
  import { useEffect, useId, useRef, useState } from "react";
@@ -258,4 +258,4 @@ function useAutocomplete(p) {
258
258
  export {
259
259
  useAutocomplete
260
260
  };
261
- //# sourceMappingURL=chunk-362OGE5J.js.map
261
+ //# sourceMappingURL=chunk-HBRKA67N.js.map
@@ -67,9 +67,9 @@ function escapeRegExp(value) {
67
67
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
68
68
  }
69
69
  function highlightLabel(label, query, matchMode) {
70
- if (!query || matchMode === "fuzzy") return label;
70
+ if (!query || matchMode === "fuzzy") return [{ text: label, match: false }];
71
71
  const regex = new RegExp(`(${escapeRegExp(query)})`, "gi");
72
- return label.replace(regex, "<mark>$1</mark>");
72
+ return label.split(regex).map((text, index) => ({ text, match: index % 2 === 1 })).filter((segment) => segment.text !== "");
73
73
  }
74
74
 
75
75
  export {
@@ -82,4 +82,4 @@ export {
82
82
  firstGhostSuggestion,
83
83
  highlightLabel
84
84
  };
85
- //# sourceMappingURL=chunk-XBHQT4BQ.js.map
85
+ //# sourceMappingURL=chunk-JXS56EW5.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/form/Autocomplete/Autocomplete.helpers.ts"],"sourcesContent":["import type { SuggestionType } from './Autocomplete.types';\n\n/** Local filtering strategy. */\nexport type MatchMode = 'startsWith' | 'contains' | 'fuzzy';\n\n/** Default key extractor: id/key/value/label, else the item itself stringified. */\nexport const defaultGetKey = <T,>(item: T): string => {\n if (typeof item === 'string') return item;\n if (typeof item === 'object' && item !== null) {\n const obj = item as Record<string, unknown>;\n return String(obj.id ?? obj.key ?? obj.value ?? obj.label ?? obj);\n }\n return String(item);\n};\n\n/** Default label extractor: label/name/text, else the item itself stringified. */\nexport const defaultGetLabel = <T,>(item: T): string => {\n if (typeof item === 'string') return item;\n if (typeof item === 'object' && item !== null) {\n const obj = item as Record<string, unknown>;\n return String(obj.label ?? obj.name ?? obj.text ?? obj);\n }\n return String(item);\n};\n\n/** Default suggestion-type extractor: reads a `type: 'search' | 'link'` field. */\nexport const defaultGetSuggestionType = <T,>(item: T): SuggestionType | undefined => {\n if (typeof item === 'object' && item !== null) {\n const { type } = item as { type?: unknown };\n if (type === 'search' || type === 'link') return type;\n }\n return undefined;\n};\n\n/** Default URL extractor for `link` suggestions: reads a `url: string` field. */\nexport const defaultGetUrl = <T,>(item: T): string | undefined => {\n if (typeof item === 'object' && item !== null) {\n const { url } = item as { url?: unknown };\n if (typeof url === 'string') return url;\n }\n return undefined;\n};\n\n/** Default link opener: a new tab with `noopener,noreferrer`. SSR-guarded. */\nexport const defaultOpenLink = (url: string): void => {\n if (typeof window !== 'undefined') {\n window.open(url, '_blank', 'noopener,noreferrer');\n }\n};\n\n/** Fuzzy match: every char of `query` appears in `label`, in order. */\nfunction fuzzyMatch(label: string, query: string): boolean {\n let labelIndex = 0;\n for (let queryIndex = 0; queryIndex < query.length; queryIndex++) {\n const char = query[queryIndex];\n if (!char) continue;\n labelIndex = label.indexOf(char, labelIndex);\n if (labelIndex === -1) return false;\n labelIndex++;\n }\n return true;\n}\n\n/** True when `label` matches `query` under the given {@link MatchMode} (case-insensitive). */\nfunction matchesQuery(label: string, query: string, matchMode: MatchMode): boolean {\n const haystack = label.toLowerCase();\n const needle = query.toLowerCase();\n if (matchMode === 'startsWith') return haystack.startsWith(needle);\n if (matchMode === 'fuzzy') return fuzzyMatch(haystack, needle);\n return haystack.includes(needle);\n}\n\n/** Filter `suggestions` by `query` under `matchMode`; an empty query returns all. */\nexport function filterSuggestions<T>(\n suggestions: T[],\n query: string,\n matchMode: MatchMode,\n getLabel: (item: T) => string,\n): T[] {\n if (!query) return suggestions;\n return suggestions.filter((item) => matchesQuery(getLabel(item), query, matchMode));\n}\n\n/**\n * The first suggestion eligible for inline ghost completion: a non-`link` item\n * whose label starts with `inputValue` (case-insensitive) but isn't equal to it.\n * Shared by the ghost-text effect and ArrowRight completion.\n */\nexport function firstGhostSuggestion<T>(\n list: T[],\n inputValue: string,\n getLabel: (item: T) => string,\n getSuggestionType: (item: T) => SuggestionType | undefined,\n): T | undefined {\n const needle = inputValue.toLowerCase();\n return list.find((item) => {\n const label = getLabel(item).toLowerCase();\n return getSuggestionType(item) !== 'link' && label.startsWith(needle) && label !== needle;\n });\n}\n\n/** Escape a user query for safe use inside a `RegExp`. */\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/**\n * Wrap query matches in `<mark>` for the default suggestion renderer. Skipped for\n * fuzzy mode (non-contiguous matches) and empty queries. Returns HTML.\n */\nexport function highlightLabel(label: string, query: string, matchMode: MatchMode): string {\n if (!query || matchMode === 'fuzzy') return label;\n const regex = new RegExp(`(${escapeRegExp(query)})`, 'gi');\n return label.replace(regex, '<mark>$1</mark>');\n}\n"],"mappings":";AAMO,IAAM,gBAAgB,CAAK,SAAoB;AACpD,MAAI,OAAO,SAAS,SAAU,QAAO;AACrC,MAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAC7C,UAAM,MAAM;AACZ,WAAO,OAAO,IAAI,MAAM,IAAI,OAAO,IAAI,SAAS,IAAI,SAAS,GAAG;AAAA,EAClE;AACA,SAAO,OAAO,IAAI;AACpB;AAGO,IAAM,kBAAkB,CAAK,SAAoB;AACtD,MAAI,OAAO,SAAS,SAAU,QAAO;AACrC,MAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAC7C,UAAM,MAAM;AACZ,WAAO,OAAO,IAAI,SAAS,IAAI,QAAQ,IAAI,QAAQ,GAAG;AAAA,EACxD;AACA,SAAO,OAAO,IAAI;AACpB;AAGO,IAAM,2BAA2B,CAAK,SAAwC;AACnF,MAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAC7C,UAAM,EAAE,KAAK,IAAI;AACjB,QAAI,SAAS,YAAY,SAAS,OAAQ,QAAO;AAAA,EACnD;AACA,SAAO;AACT;AAGO,IAAM,gBAAgB,CAAK,SAAgC;AAChE,MAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAC7C,UAAM,EAAE,IAAI,IAAI;AAChB,QAAI,OAAO,QAAQ,SAAU,QAAO;AAAA,EACtC;AACA,SAAO;AACT;AAGO,IAAM,kBAAkB,CAAC,QAAsB;AACpD,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO,KAAK,KAAK,UAAU,qBAAqB;AAAA,EAClD;AACF;AAGA,SAAS,WAAW,OAAe,OAAwB;AACzD,MAAI,aAAa;AACjB,WAAS,aAAa,GAAG,aAAa,MAAM,QAAQ,cAAc;AAChE,UAAM,OAAO,MAAM,UAAU;AAC7B,QAAI,CAAC,KAAM;AACX,iBAAa,MAAM,QAAQ,MAAM,UAAU;AAC3C,QAAI,eAAe,GAAI,QAAO;AAC9B;AAAA,EACF;AACA,SAAO;AACT;AAGA,SAAS,aAAa,OAAe,OAAe,WAA+B;AACjF,QAAM,WAAW,MAAM,YAAY;AACnC,QAAM,SAAS,MAAM,YAAY;AACjC,MAAI,cAAc,aAAc,QAAO,SAAS,WAAW,MAAM;AACjE,MAAI,cAAc,QAAS,QAAO,WAAW,UAAU,MAAM;AAC7D,SAAO,SAAS,SAAS,MAAM;AACjC;AAGO,SAAS,kBACd,aACA,OACA,WACA,UACK;AACL,MAAI,CAAC,MAAO,QAAO;AACnB,SAAO,YAAY,OAAO,CAAC,SAAS,aAAa,SAAS,IAAI,GAAG,OAAO,SAAS,CAAC;AACpF;AAOO,SAAS,qBACd,MACA,YACA,UACA,mBACe;AACf,QAAM,SAAS,WAAW,YAAY;AACtC,SAAO,KAAK,KAAK,CAAC,SAAS;AACzB,UAAM,QAAQ,SAAS,IAAI,EAAE,YAAY;AACzC,WAAO,kBAAkB,IAAI,MAAM,UAAU,MAAM,WAAW,MAAM,KAAK,UAAU;AAAA,EACrF,CAAC;AACH;AAGA,SAAS,aAAa,OAAuB;AAC3C,SAAO,MAAM,QAAQ,uBAAuB,MAAM;AACpD;AAMO,SAAS,eAAe,OAAe,OAAe,WAA8B;AACzF,MAAI,CAAC,SAAS,cAAc,QAAS,QAAO;AAC5C,QAAM,QAAQ,IAAI,OAAO,IAAI,aAAa,KAAK,CAAC,KAAK,IAAI;AACzD,SAAO,MAAM,QAAQ,OAAO,iBAAiB;AAC/C;","names":[]}
1
+ {"version":3,"sources":["../src/components/form/Autocomplete/Autocomplete.helpers.ts"],"sourcesContent":["import type { SuggestionType } from './Autocomplete.types';\n\n/** Local filtering strategy. */\nexport type MatchMode = 'startsWith' | 'contains' | 'fuzzy';\n\n/** Default key extractor: id/key/value/label, else the item itself stringified. */\nexport const defaultGetKey = <T,>(item: T): string => {\n if (typeof item === 'string') return item;\n if (typeof item === 'object' && item !== null) {\n const obj = item as Record<string, unknown>;\n return String(obj.id ?? obj.key ?? obj.value ?? obj.label ?? obj);\n }\n return String(item);\n};\n\n/** Default label extractor: label/name/text, else the item itself stringified. */\nexport const defaultGetLabel = <T,>(item: T): string => {\n if (typeof item === 'string') return item;\n if (typeof item === 'object' && item !== null) {\n const obj = item as Record<string, unknown>;\n return String(obj.label ?? obj.name ?? obj.text ?? obj);\n }\n return String(item);\n};\n\n/** Default suggestion-type extractor: reads a `type: 'search' | 'link'` field. */\nexport const defaultGetSuggestionType = <T,>(item: T): SuggestionType | undefined => {\n if (typeof item === 'object' && item !== null) {\n const { type } = item as { type?: unknown };\n if (type === 'search' || type === 'link') return type;\n }\n return undefined;\n};\n\n/** Default URL extractor for `link` suggestions: reads a `url: string` field. */\nexport const defaultGetUrl = <T,>(item: T): string | undefined => {\n if (typeof item === 'object' && item !== null) {\n const { url } = item as { url?: unknown };\n if (typeof url === 'string') return url;\n }\n return undefined;\n};\n\n/** Default link opener: a new tab with `noopener,noreferrer`. SSR-guarded. */\nexport const defaultOpenLink = (url: string): void => {\n if (typeof window !== 'undefined') {\n window.open(url, '_blank', 'noopener,noreferrer');\n }\n};\n\n/** Fuzzy match: every char of `query` appears in `label`, in order. */\nfunction fuzzyMatch(label: string, query: string): boolean {\n let labelIndex = 0;\n for (let queryIndex = 0; queryIndex < query.length; queryIndex++) {\n const char = query[queryIndex];\n if (!char) continue;\n labelIndex = label.indexOf(char, labelIndex);\n if (labelIndex === -1) return false;\n labelIndex++;\n }\n return true;\n}\n\n/** True when `label` matches `query` under the given {@link MatchMode} (case-insensitive). */\nfunction matchesQuery(label: string, query: string, matchMode: MatchMode): boolean {\n const haystack = label.toLowerCase();\n const needle = query.toLowerCase();\n if (matchMode === 'startsWith') return haystack.startsWith(needle);\n if (matchMode === 'fuzzy') return fuzzyMatch(haystack, needle);\n return haystack.includes(needle);\n}\n\n/** Filter `suggestions` by `query` under `matchMode`; an empty query returns all. */\nexport function filterSuggestions<T>(\n suggestions: T[],\n query: string,\n matchMode: MatchMode,\n getLabel: (item: T) => string,\n): T[] {\n if (!query) return suggestions;\n return suggestions.filter((item) => matchesQuery(getLabel(item), query, matchMode));\n}\n\n/**\n * The first suggestion eligible for inline ghost completion: a non-`link` item\n * whose label starts with `inputValue` (case-insensitive) but isn't equal to it.\n * Shared by the ghost-text effect and ArrowRight completion.\n */\nexport function firstGhostSuggestion<T>(\n list: T[],\n inputValue: string,\n getLabel: (item: T) => string,\n getSuggestionType: (item: T) => SuggestionType | undefined,\n): T | undefined {\n const needle = inputValue.toLowerCase();\n return list.find((item) => {\n const label = getLabel(item).toLowerCase();\n return getSuggestionType(item) !== 'link' && label.startsWith(needle) && label !== needle;\n });\n}\n\n/** Escape a user query for safe use inside a `RegExp`. */\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/** One run of a highlighted label: plain text, or text the query matched. */\nexport interface HighlightSegment {\n text: string;\n match: boolean;\n}\n\n/**\n * Split `label` into the runs the query matches and the runs between them, in\n * order, for the default suggestion renderer to wrap the matches in `<mark>`.\n * Every occurrence of the query matches, case-insensitively and literally (regex\n * metacharacters are escaped). Fuzzy mode (non-contiguous matches) and an empty\n * query yield the whole label as one unmatched run.\n *\n * Returns TEXT, never markup: a label is caller data (in a consumer, a user's\n * own display name), so the renderer must hand each run to React as a text\n * child, which escapes it. Building an HTML string here and injecting it is how\n * a label of `<img onerror=…>` once ran script in the host page.\n */\nexport function highlightLabel(label: string, query: string, matchMode: MatchMode): HighlightSegment[] {\n if (!query || matchMode === 'fuzzy') return [{ text: label, match: false }];\n // The capturing group makes `split` keep each match, at the odd indices.\n const regex = new RegExp(`(${escapeRegExp(query)})`, 'gi');\n return label\n .split(regex)\n .map((text, index) => ({ text, match: index % 2 === 1 }))\n .filter((segment) => segment.text !== '');\n}\n"],"mappings":";AAMO,IAAM,gBAAgB,CAAK,SAAoB;AACpD,MAAI,OAAO,SAAS,SAAU,QAAO;AACrC,MAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAC7C,UAAM,MAAM;AACZ,WAAO,OAAO,IAAI,MAAM,IAAI,OAAO,IAAI,SAAS,IAAI,SAAS,GAAG;AAAA,EAClE;AACA,SAAO,OAAO,IAAI;AACpB;AAGO,IAAM,kBAAkB,CAAK,SAAoB;AACtD,MAAI,OAAO,SAAS,SAAU,QAAO;AACrC,MAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAC7C,UAAM,MAAM;AACZ,WAAO,OAAO,IAAI,SAAS,IAAI,QAAQ,IAAI,QAAQ,GAAG;AAAA,EACxD;AACA,SAAO,OAAO,IAAI;AACpB;AAGO,IAAM,2BAA2B,CAAK,SAAwC;AACnF,MAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAC7C,UAAM,EAAE,KAAK,IAAI;AACjB,QAAI,SAAS,YAAY,SAAS,OAAQ,QAAO;AAAA,EACnD;AACA,SAAO;AACT;AAGO,IAAM,gBAAgB,CAAK,SAAgC;AAChE,MAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAC7C,UAAM,EAAE,IAAI,IAAI;AAChB,QAAI,OAAO,QAAQ,SAAU,QAAO;AAAA,EACtC;AACA,SAAO;AACT;AAGO,IAAM,kBAAkB,CAAC,QAAsB;AACpD,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO,KAAK,KAAK,UAAU,qBAAqB;AAAA,EAClD;AACF;AAGA,SAAS,WAAW,OAAe,OAAwB;AACzD,MAAI,aAAa;AACjB,WAAS,aAAa,GAAG,aAAa,MAAM,QAAQ,cAAc;AAChE,UAAM,OAAO,MAAM,UAAU;AAC7B,QAAI,CAAC,KAAM;AACX,iBAAa,MAAM,QAAQ,MAAM,UAAU;AAC3C,QAAI,eAAe,GAAI,QAAO;AAC9B;AAAA,EACF;AACA,SAAO;AACT;AAGA,SAAS,aAAa,OAAe,OAAe,WAA+B;AACjF,QAAM,WAAW,MAAM,YAAY;AACnC,QAAM,SAAS,MAAM,YAAY;AACjC,MAAI,cAAc,aAAc,QAAO,SAAS,WAAW,MAAM;AACjE,MAAI,cAAc,QAAS,QAAO,WAAW,UAAU,MAAM;AAC7D,SAAO,SAAS,SAAS,MAAM;AACjC;AAGO,SAAS,kBACd,aACA,OACA,WACA,UACK;AACL,MAAI,CAAC,MAAO,QAAO;AACnB,SAAO,YAAY,OAAO,CAAC,SAAS,aAAa,SAAS,IAAI,GAAG,OAAO,SAAS,CAAC;AACpF;AAOO,SAAS,qBACd,MACA,YACA,UACA,mBACe;AACf,QAAM,SAAS,WAAW,YAAY;AACtC,SAAO,KAAK,KAAK,CAAC,SAAS;AACzB,UAAM,QAAQ,SAAS,IAAI,EAAE,YAAY;AACzC,WAAO,kBAAkB,IAAI,MAAM,UAAU,MAAM,WAAW,MAAM,KAAK,UAAU;AAAA,EACrF,CAAC;AACH;AAGA,SAAS,aAAa,OAAuB;AAC3C,SAAO,MAAM,QAAQ,uBAAuB,MAAM;AACpD;AAoBO,SAAS,eAAe,OAAe,OAAe,WAA0C;AACrG,MAAI,CAAC,SAAS,cAAc,QAAS,QAAO,CAAC,EAAE,MAAM,OAAO,OAAO,MAAM,CAAC;AAE1E,QAAM,QAAQ,IAAI,OAAO,IAAI,aAAa,KAAK,CAAC,KAAK,IAAI;AACzD,SAAO,MACJ,MAAM,KAAK,EACX,IAAI,CAAC,MAAM,WAAW,EAAE,MAAM,OAAO,QAAQ,MAAM,EAAE,EAAE,EACvD,OAAO,CAAC,YAAY,QAAQ,SAAS,EAAE;AAC5C;","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  firstGhostSuggestion
3
- } from "./chunk-XBHQT4BQ.js";
3
+ } from "./chunk-JXS56EW5.js";
4
4
 
5
5
  // src/components/form/Autocomplete/Autocomplete.keys.ts
6
6
  function canAcceptGhost(ctx) {
@@ -86,4 +86,4 @@ function handleAutocompleteKey(event, composition, ctx) {
86
86
  export {
87
87
  handleAutocompleteKey
88
88
  };
89
- //# sourceMappingURL=chunk-JDFTIK4L.js.map
89
+ //# sourceMappingURL=chunk-PELRSZFU.js.map
@@ -2,11 +2,11 @@ import "../chunk-2LXHUGYB.js";
2
2
  import {
3
3
  Autocomplete,
4
4
  Autocomplete_default
5
- } from "../chunk-PH36XEB3.js";
6
- import "../chunk-362OGE5J.js";
7
- import "../chunk-BN742L2M.js";
8
- import "../chunk-JDFTIK4L.js";
9
- import "../chunk-XBHQT4BQ.js";
5
+ } from "../chunk-DQZCQV2C.js";
6
+ import "../chunk-HBRKA67N.js";
7
+ import "../chunk-H6AWKLOV.js";
8
+ import "../chunk-PELRSZFU.js";
9
+ import "../chunk-JXS56EW5.js";
10
10
  import "../chunk-CGO452DC.js";
11
11
  import "../chunk-GDN2LUTZ.js";
12
12
  import "../chunk-7FDU3FIN.js";
@@ -19,9 +19,22 @@ export declare function filterSuggestions<T>(suggestions: T[], query: string, ma
19
19
  * Shared by the ghost-text effect and ArrowRight completion.
20
20
  */
21
21
  export declare function firstGhostSuggestion<T>(list: T[], inputValue: string, getLabel: (item: T) => string, getSuggestionType: (item: T) => SuggestionType | undefined): T | undefined;
22
+ /** One run of a highlighted label: plain text, or text the query matched. */
23
+ export interface HighlightSegment {
24
+ text: string;
25
+ match: boolean;
26
+ }
22
27
  /**
23
- * Wrap query matches in `<mark>` for the default suggestion renderer. Skipped for
24
- * fuzzy mode (non-contiguous matches) and empty queries. Returns HTML.
28
+ * Split `label` into the runs the query matches and the runs between them, in
29
+ * order, for the default suggestion renderer to wrap the matches in `<mark>`.
30
+ * Every occurrence of the query matches, case-insensitively and literally (regex
31
+ * metacharacters are escaped). Fuzzy mode (non-contiguous matches) and an empty
32
+ * query yield the whole label as one unmatched run.
33
+ *
34
+ * Returns TEXT, never markup: a label is caller data (in a consumer, a user's
35
+ * own display name), so the renderer must hand each run to React as a text
36
+ * child, which escapes it. Building an HTML string here and injecting it is how
37
+ * a label of `<img onerror=…>` once ran script in the host page.
25
38
  */
26
- export declare function highlightLabel(label: string, query: string, matchMode: MatchMode): string;
39
+ export declare function highlightLabel(label: string, query: string, matchMode: MatchMode): HighlightSegment[];
27
40
  //# sourceMappingURL=Autocomplete.helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Autocomplete.helpers.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/Autocomplete/Autocomplete.helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,gCAAgC;AAChC,MAAM,MAAM,SAAS,GAAG,YAAY,GAAG,UAAU,GAAG,OAAO,CAAC;AAE5D,mFAAmF;AACnF,eAAO,MAAM,aAAa,GAAI,CAAC,EAAG,MAAM,CAAC,KAAG,MAO3C,CAAC;AAEF,kFAAkF;AAClF,eAAO,MAAM,eAAe,GAAI,CAAC,EAAG,MAAM,CAAC,KAAG,MAO7C,CAAC;AAEF,kFAAkF;AAClF,eAAO,MAAM,wBAAwB,GAAI,CAAC,EAAG,MAAM,CAAC,KAAG,cAAc,GAAG,SAMvE,CAAC;AAEF,iFAAiF;AACjF,eAAO,MAAM,aAAa,GAAI,CAAC,EAAG,MAAM,CAAC,KAAG,MAAM,GAAG,SAMpD,CAAC;AAEF,8EAA8E;AAC9E,eAAO,MAAM,eAAe,GAAI,KAAK,MAAM,KAAG,IAI7C,CAAC;AAwBF,qFAAqF;AACrF,wBAAgB,iBAAiB,CAAC,CAAC,EACjC,WAAW,EAAE,CAAC,EAAE,EAChB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,GAC5B,CAAC,EAAE,CAGL;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EACpC,IAAI,EAAE,CAAC,EAAE,EACT,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,EAC7B,iBAAiB,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,cAAc,GAAG,SAAS,GACzD,CAAC,GAAG,SAAS,CAMf;AAOD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,GAAG,MAAM,CAIzF"}
1
+ {"version":3,"file":"Autocomplete.helpers.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/Autocomplete/Autocomplete.helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,gCAAgC;AAChC,MAAM,MAAM,SAAS,GAAG,YAAY,GAAG,UAAU,GAAG,OAAO,CAAC;AAE5D,mFAAmF;AACnF,eAAO,MAAM,aAAa,GAAI,CAAC,EAAG,MAAM,CAAC,KAAG,MAO3C,CAAC;AAEF,kFAAkF;AAClF,eAAO,MAAM,eAAe,GAAI,CAAC,EAAG,MAAM,CAAC,KAAG,MAO7C,CAAC;AAEF,kFAAkF;AAClF,eAAO,MAAM,wBAAwB,GAAI,CAAC,EAAG,MAAM,CAAC,KAAG,cAAc,GAAG,SAMvE,CAAC;AAEF,iFAAiF;AACjF,eAAO,MAAM,aAAa,GAAI,CAAC,EAAG,MAAM,CAAC,KAAG,MAAM,GAAG,SAMpD,CAAC;AAEF,8EAA8E;AAC9E,eAAO,MAAM,eAAe,GAAI,KAAK,MAAM,KAAG,IAI7C,CAAC;AAwBF,qFAAqF;AACrF,wBAAgB,iBAAiB,CAAC,CAAC,EACjC,WAAW,EAAE,CAAC,EAAE,EAChB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,GAC5B,CAAC,EAAE,CAGL;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EACpC,IAAI,EAAE,CAAC,EAAE,EACT,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,EAC7B,iBAAiB,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,cAAc,GAAG,SAAS,GACzD,CAAC,GAAG,SAAS,CAMf;AAOD,6EAA6E;AAC7E,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,GAAG,gBAAgB,EAAE,CAQrG"}
@@ -1 +1 @@
1
- {"version":3,"file":"Autocomplete.parts.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/Autocomplete/Autocomplete.parts.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Autocomplete.parts.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/Autocomplete/Autocomplete.parts.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@12-apps/ui",
3
- "version": "6.39.7",
3
+ "version": "6.39.8",
4
4
  "license": "MIT",
5
5
  "packageManager": "pnpm@10.34.5",
6
6
  "type": "module",
@@ -104,12 +104,30 @@ function escapeRegExp(value: string): string {
104
104
  return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
105
105
  }
106
106
 
107
+ /** One run of a highlighted label: plain text, or text the query matched. */
108
+ export interface HighlightSegment {
109
+ text: string;
110
+ match: boolean;
111
+ }
112
+
107
113
  /**
108
- * Wrap query matches in `<mark>` for the default suggestion renderer. Skipped for
109
- * fuzzy mode (non-contiguous matches) and empty queries. Returns HTML.
114
+ * Split `label` into the runs the query matches and the runs between them, in
115
+ * order, for the default suggestion renderer to wrap the matches in `<mark>`.
116
+ * Every occurrence of the query matches, case-insensitively and literally (regex
117
+ * metacharacters are escaped). Fuzzy mode (non-contiguous matches) and an empty
118
+ * query yield the whole label as one unmatched run.
119
+ *
120
+ * Returns TEXT, never markup: a label is caller data (in a consumer, a user's
121
+ * own display name), so the renderer must hand each run to React as a text
122
+ * child, which escapes it. Building an HTML string here and injecting it is how
123
+ * a label of `<img onerror=…>` once ran script in the host page.
110
124
  */
111
- export function highlightLabel(label: string, query: string, matchMode: MatchMode): string {
112
- if (!query || matchMode === 'fuzzy') return label;
125
+ export function highlightLabel(label: string, query: string, matchMode: MatchMode): HighlightSegment[] {
126
+ if (!query || matchMode === 'fuzzy') return [{ text: label, match: false }];
127
+ // The capturing group makes `split` keep each match, at the odd indices.
113
128
  const regex = new RegExp(`(${escapeRegExp(query)})`, 'gi');
114
- return label.replace(regex, '<mark>$1</mark>');
129
+ return label
130
+ .split(regex)
131
+ .map((text, index) => ({ text, match: index % 2 === 1 }))
132
+ .filter((segment) => segment.text !== '');
115
133
  }
@@ -194,7 +194,8 @@ export function DefaultSuggestion<T>({
194
194
  }): React.JSX.Element {
195
195
  const label = getLabel(item);
196
196
  const description = getDescription?.(item);
197
- const displayLabel = highlightLabel(label, state.query, matchMode);
197
+ // Each run is a React text child, so the label is escaped however it reads.
198
+ const segments = highlightLabel(label, state.query, matchMode);
198
199
  return (
199
200
  <Box
200
201
  sx={{
@@ -202,13 +203,26 @@ export function DefaultSuggestion<T>({
202
203
  alignItems: 'center',
203
204
  gap: 1,
204
205
  width: '100%',
205
- // Bold the matched prefix (not a yellow <mark> highlight).
206
+ // Bold every run the query matched, in any match mode but fuzzy — not
207
+ // only a prefix, even under `startsWith` (not a yellow <mark> highlight).
206
208
  '& mark': { backgroundColor: 'transparent', color: 'inherit', fontWeight: 700 },
207
209
  }}
208
210
  >
209
211
  {suggestionTypeIcon(getSuggestionType(item))}
210
212
  <ListItemText
211
- primary={<span dangerouslySetInnerHTML={{ __html: displayLabel }} />}
213
+ primary={
214
+ <span>
215
+ {segments.map((segment, index) =>
216
+ // The runs are derived from one label and never reorder, so the
217
+ // position is a stable key.
218
+ segment.match ? (
219
+ <mark key={index}>{segment.text}</mark>
220
+ ) : (
221
+ <React.Fragment key={index}>{segment.text}</React.Fragment>
222
+ ),
223
+ )}
224
+ </span>
225
+ }
212
226
  secondary={description}
213
227
  />
214
228
  </Box>
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/form/Autocomplete/Autocomplete.parts.tsx"],"sourcesContent":["import LinkIcon from '@mui/icons-material/Link';\nimport SearchIcon from '@mui/icons-material/Search';\nimport Box from '@mui/material/Box/index.js';\nimport Chip from '@mui/material/Chip/index.js';\nimport CircularProgress from '@mui/material/CircularProgress/index.js';\nimport List from '@mui/material/List/index.js';\nimport ListItem from '@mui/material/ListItem/index.js';\nimport ListItemText from '@mui/material/ListItemText/index.js';\nimport Paper from '@mui/material/Paper/index.js';\nimport Popper from '@mui/material/Popper/index.js';\nimport TextField from '@mui/material/TextField/index.js';\nimport Typography from '@mui/material/Typography/index.js';\nimport { styled, useTheme } from '@mui/material/styles/index.js';\nimport React from 'react';\n\nimport { highlightLabel, type MatchMode } from './Autocomplete.helpers';\nimport type { SuggestionItemState, SuggestionType } from './Autocomplete.types';\nimport type { AutocompleteCopy } from '../../../copy';\nimport { fieldTextFieldStyles } from '../../../tokens/field-height';\nimport { rem, sxRem } from '../../../tokens/relative';\n\nconst StyledPopper = styled(Popper)(({ theme }) => ({\n zIndex: theme.zIndex.tooltip,\n width: '100%',\n maxHeight: rem(theme, 300),\n overflow: 'auto',\n // Popper.js writes the computed position (and stamps `data-popper-placement`)\n // in a layout effect that can land AFTER the first paint. Until it does, the\n // element would paint once unpositioned — at the offset-parent origin, far\n // left and full width — then jump under the input, a visible per-keystroke\n // flash as the list re-renders. Hide that unpositioned first frame; it becomes\n // visible the instant popper assigns a placement.\n '&:not([data-popper-placement])': { visibility: 'hidden' },\n}));\n\nconst InlineSuggestionDisplay = styled('div')(({ theme }) => ({\n position: 'absolute',\n pointerEvents: 'none',\n left: rem(theme, 14), // Match TextField padding\n top: '50%',\n transform: 'translateY(-50%)',\n fontSize: 'inherit',\n fontFamily: 'inherit',\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n zIndex: 1,\n}));\n\nconst UserTextTwin = styled('span')({\n visibility: 'hidden',\n});\n\nconst GhostText = styled('span')(({ theme }) => ({\n color: theme.palette.text.secondary,\n opacity: 0.6,\n}));\n\nconst ChipContainer = styled(Box)(({ theme }) => ({\n display: 'flex',\n flexWrap: 'wrap',\n gap: theme.spacing(0.5),\n marginBottom: theme.spacing(1),\n}));\n\n/** Leading icon for a typed suggestion (search vs. link); null for untyped items. */\nexport function suggestionTypeIcon(type: SuggestionType | undefined): React.ReactNode {\n const sx = { color: 'text.secondary', flexShrink: 0 } as const;\n if (type === 'link') return <LinkIcon fontSize=\"small\" sx={sx} />;\n if (type === 'search') return <SearchIcon fontSize=\"small\" sx={sx} />;\n return null;\n}\n\n/** The inline ghost-text overlay: an invisible twin of the typed text + the grey remainder. */\nfunction GhostOverlay({ inputValue, ghost }: { inputValue: string; ghost: string }): React.JSX.Element {\n return (\n <InlineSuggestionDisplay>\n <UserTextTwin>{inputValue}</UserTextTwin>\n <GhostText>{ghost}</GhostText>\n </InlineSuggestionDisplay>\n );\n}\n\nexport interface AutocompleteInputProps {\n id: string;\n listId: string;\n inputRef: React.RefObject<HTMLInputElement | null>;\n inputValue: string;\n ghost: string;\n showGhost: boolean;\n isInputFocused: boolean;\n open: boolean;\n activeDescendant: string | undefined;\n isLoading: boolean;\n disabled: boolean;\n autoFocus: boolean;\n placeholder: string;\n startAdornment?: React.ReactNode;\n inputAriaLabel?: string;\n inputClassName?: string;\n onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;\n onKeyDown: (e: React.KeyboardEvent<HTMLInputElement>) => void;\n onFocus: () => void;\n onBlur: () => void;\n onCompositionStart: () => void;\n onCompositionEnd: () => void;\n}\n\n/** The combobox text field plus its inline ghost-text overlay. */\nexport function AutocompleteInput(props: AutocompleteInputProps): React.JSX.Element {\n const theme = useTheme();\n const showOverlay = Boolean(props.ghost) && props.showGhost && props.isInputFocused;\n return (\n <Box sx={{ position: 'relative' }}>\n {showOverlay && <GhostOverlay inputValue={props.inputValue} ghost={props.ghost} />}\n <TextField\n ref={props.inputRef}\n fullWidth\n sx={fieldTextFieldStyles}\n value={props.inputValue}\n onChange={props.onChange}\n onKeyDown={props.onKeyDown}\n onFocus={props.onFocus}\n onBlur={props.onBlur}\n onCompositionStart={props.onCompositionStart}\n onCompositionEnd={props.onCompositionEnd}\n placeholder={props.placeholder}\n disabled={props.disabled}\n autoFocus={props.autoFocus}\n className={props.inputClassName}\n InputProps={{\n startAdornment: props.startAdornment,\n endAdornment: props.isLoading ? <CircularProgress size={rem(theme, 20)} /> : undefined,\n }}\n inputProps={{\n role: 'combobox',\n 'aria-expanded': props.open,\n 'aria-controls': props.open ? props.listId : undefined,\n 'aria-activedescendant': props.activeDescendant,\n 'aria-autocomplete': 'list',\n 'aria-label': props.inputAriaLabel,\n id: props.id,\n }}\n />\n </Box>\n );\n}\n\n/** Selected-item chips (multiple mode). */\nexport function ChipList<T>({\n items,\n getKey,\n getLabel,\n onRemove,\n chipClassName,\n}: {\n items: T[];\n getKey: (item: T) => string;\n getLabel: (item: T) => string;\n onRemove: (item: T) => void;\n chipClassName?: string;\n}): React.JSX.Element {\n return (\n <ChipContainer data-testid=\"selected-items-container\">\n {items.map((item, index) => (\n <Chip\n key={`${getKey(item)}-${index}`}\n label={getLabel(item)}\n onDelete={() => onRemove(item)}\n size=\"small\"\n className={chipClassName}\n data-testid={`selected-chip-${index}`}\n />\n ))}\n </ChipContainer>\n );\n}\n\n/** Default suggestion row: per-type icon + highlighted label + optional description. */\nexport function DefaultSuggestion<T>({\n item,\n state,\n getLabel,\n getDescription,\n getSuggestionType,\n matchMode,\n}: {\n item: T;\n state: SuggestionItemState;\n getLabel: (item: T) => string;\n getDescription?: (item: T) => string | undefined;\n getSuggestionType: (item: T) => SuggestionType | undefined;\n matchMode: MatchMode;\n}): React.JSX.Element {\n const label = getLabel(item);\n const description = getDescription?.(item);\n const displayLabel = highlightLabel(label, state.query, matchMode);\n return (\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n gap: 1,\n width: '100%',\n // Bold the matched prefix (not a yellow <mark> highlight).\n '& mark': { backgroundColor: 'transparent', color: 'inherit', fontWeight: 700 },\n }}\n >\n {suggestionTypeIcon(getSuggestionType(item))}\n <ListItemText\n primary={<span dangerouslySetInnerHTML={{ __html: displayLabel }} />}\n secondary={description}\n />\n </Box>\n );\n}\n\n/** A \"Loading…\" row shown while async suggestions resolve. */\nexport function LoadingRow({ label }: { label: string }): React.JSX.Element {\n const theme = useTheme();\n return (\n <ListItem>\n <Box display=\"flex\" alignItems=\"center\" gap={1}>\n <CircularProgress size={rem(theme, 16)} />\n <Typography variant=\"body2\" color=\"text.secondary\">\n {label}\n </Typography>\n </Box>\n </ListItem>\n );\n}\n\n/** The empty \"No results found\" row. */\nexport function NoResultsRow({ label }: { label: string }): React.JSX.Element {\n return (\n <ListItem>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {label}\n </Typography>\n </ListItem>\n );\n}\n\n/** Keep the Popper the same width as its anchor input. */\nconst SAME_WIDTH_MODIFIER = {\n name: 'sameWidth',\n enabled: true,\n fn: ({ state }: { state: { elements: { reference?: unknown }; styles: { popper?: Record<string, string> }; rects: { reference: { width: number } } } }) => {\n if (state.elements.reference && state.styles.popper) {\n state.styles.popper.width = `${state.rects.reference.width}px`;\n }\n },\n phase: 'beforeWrite' as const,\n requires: ['computeStyles'],\n};\n\nexport interface SuggestionListBoxProps<T> {\n copy: AutocompleteCopy;\n open: boolean;\n anchorEl: HTMLElement | null;\n portal: boolean | { container?: HTMLElement };\n listRef: React.RefObject<HTMLUListElement | null>;\n listId: string;\n optionIdPrefix: string;\n items: T[];\n activeIndex: number;\n isLoading: boolean;\n showNoResults: boolean;\n getKey: (item: T) => string;\n onSelect: (item: T) => void;\n onHover: (index: number) => void;\n renderItem: (item: T, active: boolean) => React.ReactNode;\n listClassName?: string;\n itemClassName?: string;\n activeItemClassName?: string;\n}\n\n/** The suggestions dropdown: a same-width Popper with the option list + loading/empty rows. */\nexport function SuggestionListBox<T>({\n copy,\n open,\n anchorEl,\n portal,\n listRef,\n listId,\n optionIdPrefix,\n items,\n activeIndex,\n isLoading,\n showNoResults,\n getKey,\n onSelect,\n onHover,\n renderItem,\n listClassName,\n itemClassName,\n activeItemClassName,\n}: SuggestionListBoxProps<T>): React.JSX.Element {\n return (\n <StyledPopper\n open={open}\n anchorEl={anchorEl}\n placement=\"bottom-start\"\n disablePortal={!portal}\n modifiers={[SAME_WIDTH_MODIFIER]}\n >\n <Paper elevation={8} className={listClassName} data-testid=\"suggestions-dropdown\">\n <List\n ref={listRef}\n role=\"listbox\"\n id={listId}\n dense\n sx={{ maxHeight: sxRem(300), overflow: 'auto' }}\n data-testid=\"suggestions-list\"\n >\n {items.map((item, index) => (\n <ListItem\n key={getKey(item)}\n id={`${optionIdPrefix}-${index}`}\n role=\"option\"\n component=\"div\"\n sx={{\n cursor: 'pointer',\n backgroundColor: index === activeIndex ? 'action.hover' : 'transparent',\n '&:hover': { backgroundColor: 'action.hover' },\n }}\n aria-selected={index === activeIndex}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => onSelect(item)}\n onMouseEnter={() => onHover(index)}\n className={`${itemClassName} ${index === activeIndex ? activeItemClassName : ''}`}\n data-testid={`suggestion-item-${index}`}\n >\n {renderItem(item, index === activeIndex)}\n </ListItem>\n ))}\n {isLoading && <LoadingRow label={copy.loading} />}\n {showNoResults && <NoResultsRow label={copy.noResults} />}\n </List>\n </Paper>\n </StyledPopper>\n );\n}\n"],"mappings":"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","names":[]}