@umodeapporg/ui 0.23.0 → 0.23.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/umode-ui.css +0 -105
- package/dist/components/Form/ControlledSelect.js +5 -3
- package/dist/components/Form/ControlledSelect.js.map +1 -1
- package/dist/locales/en/ui.json.d.ts +0 -67
- package/dist/locales/en/ui.json.js +0 -3
- package/dist/locales/en/ui.json.js.map +1 -1
- package/dist/locales/index.d.ts +0 -134
- package/dist/locales/pt/ui.json.d.ts +0 -67
- package/dist/locales/pt/ui.json.js +0 -3
- package/dist/locales/pt/ui.json.js.map +1 -1
- package/package.json +1 -10
- package/dist/components/UI/Flow/FlowBlockNode.d.ts +0 -35
- package/dist/components/UI/Flow/FlowBlockNode.js +0 -84
- package/dist/components/UI/Flow/FlowBlockNode.js.map +0 -1
- package/dist/components/UI/Flow/FlowCanvas.d.ts +0 -22
- package/dist/components/UI/Flow/FlowCanvas.js +0 -263
- package/dist/components/UI/Flow/FlowCanvas.js.map +0 -1
- package/dist/components/UI/Flow/FlowConnectionEdge.d.ts +0 -10
- package/dist/components/UI/Flow/FlowConnectionEdge.js +0 -54
- package/dist/components/UI/Flow/FlowConnectionEdge.js.map +0 -1
- package/dist/components/UI/Flow/FlowEditorProvider.d.ts +0 -17
- package/dist/components/UI/Flow/FlowEditorProvider.js +0 -27
- package/dist/components/UI/Flow/FlowEditorProvider.js.map +0 -1
- package/dist/components/UI/Flow/FlowInspector.d.ts +0 -11
- package/dist/components/UI/Flow/FlowInspector.js +0 -124
- package/dist/components/UI/Flow/FlowInspector.js.map +0 -1
- package/dist/components/UI/Flow/FlowIssueList.d.ts +0 -8
- package/dist/components/UI/Flow/FlowIssueList.js +0 -55
- package/dist/components/UI/Flow/FlowIssueList.js.map +0 -1
- package/dist/components/UI/Flow/FlowLaneMap.d.ts +0 -30
- package/dist/components/UI/Flow/FlowLaneMap.js +0 -206
- package/dist/components/UI/Flow/FlowLaneMap.js.map +0 -1
- package/dist/components/UI/Flow/FlowNodeShell.d.ts +0 -20
- package/dist/components/UI/Flow/FlowNodeShell.js +0 -81
- package/dist/components/UI/Flow/FlowNodeShell.js.map +0 -1
- package/dist/components/UI/Flow/FlowPalette.d.ts +0 -7
- package/dist/components/UI/Flow/FlowPalette.js +0 -90
- package/dist/components/UI/Flow/FlowPalette.js.map +0 -1
- package/dist/components/UI/Flow/FlowResizablePanel.d.ts +0 -20
- package/dist/components/UI/Flow/FlowResizablePanel.js +0 -117
- package/dist/components/UI/Flow/FlowResizablePanel.js.map +0 -1
- package/dist/components/UI/Flow/FlowZoomControls.d.ts +0 -12
- package/dist/components/UI/Flow/FlowZoomControls.js +0 -53
- package/dist/components/UI/Flow/FlowZoomControls.js.map +0 -1
- package/dist/components/UI/Flow/flowBlockRegistry.d.ts +0 -12
- package/dist/components/UI/Flow/flowBlockRegistry.js +0 -15
- package/dist/components/UI/Flow/flowBlockRegistry.js.map +0 -1
- package/dist/components/UI/Flow/flowConstants.d.ts +0 -2
- package/dist/components/UI/Flow/flowConstants.js +0 -5
- package/dist/components/UI/Flow/flowConstants.js.map +0 -1
- package/dist/components/UI/Flow/flowEditorStore.d.ts +0 -44
- package/dist/components/UI/Flow/flowEditorStore.js +0 -258
- package/dist/components/UI/Flow/flowEditorStore.js.map +0 -1
- package/dist/components/UI/Flow/flowGraph.d.ts +0 -32
- package/dist/components/UI/Flow/flowGraph.js +0 -156
- package/dist/components/UI/Flow/flowGraph.js.map +0 -1
- package/dist/components/UI/Flow/flowTypes.d.ts +0 -74
- package/dist/components/UI/Flow/flowTypes.js +0 -2
- package/dist/components/UI/Flow/flowTypes.js.map +0 -1
- package/dist/components/UI/Flow/index.d.ts +0 -14
- package/dist/components/UI/Flow/index.js +0 -43
- package/dist/components/UI/Flow/index.js.map +0 -1
- package/dist/components/UI/Flow/useFlowLabels.d.ts +0 -10
- package/dist/components/UI/Flow/useFlowLabels.js +0 -51
- package/dist/components/UI/Flow/useFlowLabels.js.map +0 -1
package/dist/assets/umode-ui.css
CHANGED
|
@@ -338,108 +338,3 @@
|
|
|
338
338
|
height: 1.25rem;
|
|
339
339
|
font-size: 1.25rem;
|
|
340
340
|
}
|
|
341
|
-
/* Theme bridge for @xyflow/react internals the components cannot reach with classes. */
|
|
342
|
-
.umode-flow .react-flow__pane {
|
|
343
|
-
cursor: default;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
.umode-flow .react-flow__background {
|
|
347
|
-
--xy-background-pattern-color: rgb(var(--color-border-subtle));
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
.umode-flow .umode-flow-handle {
|
|
351
|
-
width: 0.75rem;
|
|
352
|
-
height: 0.75rem;
|
|
353
|
-
border: 2px solid rgb(var(--color-surface));
|
|
354
|
-
background: rgb(var(--color-border-strong));
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
.umode-flow .umode-flow-handle.connectionindicator:hover,
|
|
358
|
-
.umode-flow .umode-flow-handle.connectingto {
|
|
359
|
-
background: rgb(var(--color-primary));
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
.umode-flow .umode-flow-edge-path {
|
|
363
|
-
stroke: rgb(var(--color-border-strong));
|
|
364
|
-
stroke-width: 1.5;
|
|
365
|
-
transition: stroke 140ms ease-out;
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
.umode-flow .umode-flow-edge-path--selected {
|
|
369
|
-
stroke: rgb(var(--color-primary));
|
|
370
|
-
stroke-width: 2;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
.umode-flow .umode-flow-edge-path--traversed {
|
|
374
|
-
stroke: rgb(var(--color-primary));
|
|
375
|
-
stroke-width: 2.5;
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
.umode-flow .umode-flow-edge-path--warning {
|
|
379
|
-
stroke: rgb(var(--color-warning));
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
.umode-flow .umode-flow-edge-path--error {
|
|
383
|
-
stroke: rgb(var(--color-danger));
|
|
384
|
-
stroke-dasharray: 6 4;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
.umode-flow .react-flow__minimap {
|
|
388
|
-
background: rgb(var(--color-surface));
|
|
389
|
-
border: 1px solid rgb(var(--color-border));
|
|
390
|
-
border-radius: 0.75rem;
|
|
391
|
-
overflow: hidden;
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
.umode-flow .react-flow__minimap-mask {
|
|
395
|
-
fill: rgb(var(--color-muted) / 0.7);
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
.umode-flow .react-flow__minimap-node {
|
|
399
|
-
fill: rgb(var(--color-border-emphasis));
|
|
400
|
-
stroke: none;
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
.umode-flow .react-flow__attribution {
|
|
404
|
-
background: transparent;
|
|
405
|
-
color: rgb(var(--color-foreground-faint));
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
.umode-flow .react-flow__connectionline path {
|
|
409
|
-
stroke: rgb(var(--color-primary));
|
|
410
|
-
stroke-width: 2;
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
.umode-flow .umode-flow-arc {
|
|
414
|
-
stroke: rgb(var(--color-border-strong));
|
|
415
|
-
stroke-width: 1.5;
|
|
416
|
-
fill: none;
|
|
417
|
-
transition: stroke 140ms ease-out;
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
.umode-flow .umode-flow-arc--warning {
|
|
421
|
-
stroke: rgb(var(--color-warning));
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
.umode-flow .umode-flow-arc--danger {
|
|
425
|
-
stroke: rgb(var(--color-danger));
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
.umode-flow .umode-flow-arc--dashed {
|
|
429
|
-
stroke-dasharray: 6 4;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
.umode-flow .umode-flow-arc--selected,
|
|
433
|
-
.umode-flow .react-flow__edge:hover .umode-flow-arc {
|
|
434
|
-
stroke: rgb(var(--color-primary));
|
|
435
|
-
stroke-width: 2.5;
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
.umode-flow .react-flow__edge {
|
|
439
|
-
cursor: pointer;
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
.umode-flow .react-flow__arrowhead polyline {
|
|
443
|
-
stroke: rgb(var(--color-border-strong));
|
|
444
|
-
fill: rgb(var(--color-border-strong));
|
|
445
|
-
}
|
|
@@ -155,6 +155,7 @@ function ControlledSelect({
|
|
|
155
155
|
}, [isOpen]);
|
|
156
156
|
const handleSelect = useCallback(
|
|
157
157
|
(option, event) => {
|
|
158
|
+
if (disabled) return;
|
|
158
159
|
if (multiple) {
|
|
159
160
|
event.stopPropagation();
|
|
160
161
|
event.preventDefault();
|
|
@@ -178,9 +179,10 @@ function ControlledSelect({
|
|
|
178
179
|
setIsOpen(false);
|
|
179
180
|
}
|
|
180
181
|
},
|
|
181
|
-
[multiple, selected, onChangeHook, options, infiniteScroll]
|
|
182
|
+
[disabled, multiple, selected, onChangeHook, options, infiniteScroll]
|
|
182
183
|
);
|
|
183
184
|
const handleClearSelection = useCallback(() => {
|
|
185
|
+
if (disabled) return;
|
|
184
186
|
if (multiple) {
|
|
185
187
|
setSelected([]);
|
|
186
188
|
onChangeHook([]);
|
|
@@ -195,7 +197,7 @@ function ControlledSelect({
|
|
|
195
197
|
if (onClearSearch) {
|
|
196
198
|
onClearSearch();
|
|
197
199
|
}
|
|
198
|
-
}, [multiple, onChangeHook, onClearSearch, options, infiniteScroll]);
|
|
200
|
+
}, [disabled, multiple, onChangeHook, onClearSearch, options, infiniteScroll]);
|
|
199
201
|
const getDisplayLabel = useCallback(() => {
|
|
200
202
|
if (multiple) {
|
|
201
203
|
const selectedArray = selected;
|
|
@@ -592,7 +594,7 @@ function ControlledSelect({
|
|
|
592
594
|
className: classNames("bg-muted-active text-lg", { "px-4 py-1": isLateralPosition }),
|
|
593
595
|
labelClassName: isLateralPosition ? "text-sm" : void 0,
|
|
594
596
|
onClose: (event) => handleSelect(option.value, event),
|
|
595
|
-
canClose:
|
|
597
|
+
canClose: !disabled
|
|
596
598
|
},
|
|
597
599
|
option.value
|
|
598
600
|
)) });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ControlledSelect.js","sources":["../../../src/components/Form/ControlledSelect.tsx"],"sourcesContent":["import { ReactNode, useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from 'react';\nimport classNames from 'classnames';\nimport { useTranslation } from 'react-i18next';\nimport InfiniteScroll from 'react-infinite-scroll-component';\nimport { FixedSizeList as List } from 'react-window';\n\nimport {\n ControlledMenuHandler,\n ControlledMenuItem,\n ControlledMenuList,\n ControlledMenuRoot,\n} from '@/components/UI/ControlledMenu';\nimport ControlledTooltip from '@/components/UI/ControlledTooltip';\nimport { capitalizeAllLetters, formatFilter } from '@/helpers/stringHelpers';\nimport { uiLogger } from '@/helpers/uiLogger';\n\nimport { IFilterOption } from '../../interfaces/IFilterOption';\nimport UnifiedSearchBar from '../Search/UnifiedSearchBar';\nimport OutlinedChip from '../UI/Chips/OutlinedChip';\nimport LoadingSpinner from '../UI/LoadingSpinner';\nimport { MaterialSymbol } from '../UI/MaterialSymbol';\nimport NoDataFound from '../UI/NoDataFound';\n\nimport ControlledCheckbox from './ControlledCheckbox';\nimport ControlledInput from './ControlledInput';\n\nimport '../../styles/virtualizedSelect.css';\n\n/**\n * Contract of `fetchMoreOptions`, the single loader of infinite-scroll selects.\n * `reset: true` means \"replace the list with page 1 of `search`\" (a new search, a cleared\n * search, or the restore to the unfiltered baseline). `reset: false` means \"append the NEXT\n * page of the same `search`\". The consumer owns the page counter and the accumulated\n * `options` prop; this component never accumulates results itself.\n */\nexport interface IControlledSelectFetchParams {\n search: string;\n reset: boolean;\n}\n\ntype TDataAttributes = { [key: `data-${string}`]: string | number | boolean | undefined };\n\n/**\n * Native and ARIA attributes forwarded to the combobox trigger: `id` (so a `<label htmlFor>`\n * names it), `aria-labelledby` / `aria-describedby` / `aria-invalid`, `data-*`, `onBlur`.\n * `name` is submitted through hidden inputs carrying the selected value(s), never the label.\n */\ntype TControlledSelectTriggerProps = Pick<\n React.InputHTMLAttributes<HTMLInputElement>,\n 'id' | 'name' | 'required' | 'onBlur' | 'onFocus' | 'autoFocus'\n> &\n React.AriaAttributes &\n TDataAttributes;\n\ntype TControlledSelectProps = TControlledSelectTriggerProps & {\n label?: string;\n // Mantém a label flutuante visível (encolhida na borda) mesmo com um valor selecionado.\n // Padrão: false — a label some ao selecionar, assumindo que há um rótulo externo acima.\n persistentLabel?: boolean;\n options: Array<IFilterOption>;\n selectedValue: string | Array<string>;\n error?: boolean;\n multiple?: boolean;\n searchable?: boolean;\n disabled?: boolean;\n clearable?: boolean;\n className?: string;\n listClassName?: string;\n onChangeHook: (selected: string | Array<string>) => void;\n infiniteScroll?: boolean;\n fetchMoreOptions?: (params: IControlledSelectFetchParams) => Promise<unknown>;\n hasMoreOptions?: boolean;\n loading?: boolean;\n onClearSearch?: () => void;\n onOpen?: () => void;\n selectedItemsPosition?: 'bottom' | 'top' | 'left' | 'right';\n // When false, the selected-items chips are not rendered beside the trigger;\n // only the count summary (\"N itens selecionados\") shows inside the trigger.\n showSelectedItems?: boolean;\n // Multi-select only: render the selected values as chips inside the trigger\n // field (with a \"+N\" overflow indicator and a tooltip listing all of them)\n // instead of the generic \"N itens selecionados\" count.\n inFieldChips?: boolean;\n // Por padrão as labels passam por capitalizeAllLetters (Primeira Maiúscula, resto\n // minúsculo). Use true quando a label é um identificador literal — nome de tabela,\n // coluna, chave — em que o caixa original é significativo e não pode ser alterado.\n preserveLabelCase?: boolean;\n // Shape of the option swatch. Colors read as the square chip the libraries use;\n // the dot stays the default for tags and categories.\n swatchShape?: 'dot' | 'square';\n // Accessible name of the trigger, for a field whose meaning comes from the\n // surrounding layout and therefore renders no visible label or placeholder.\n ariaLabel?: string;\n // Marks the combobox trigger as required for assistive tech (aria-required).\n ariaRequired?: boolean;\n // Classes for the trigger input itself, for a select embedded in a composed\n // control (a segmented field) that must drop its own border, fill or minimum\n // width. `className` styles the wrapper and cannot reach the input.\n inputClassName?: string;\n // The dropdown follows the width of the field by default, so the panel and the search\n // box in it are never narrower than the trigger they belong to. A trigger below\n // MIN_LIST_WIDTH_CLASS keeps the panel at that floor, because an option list the width\n // of a 72px picker is unreadable. Pass false for a trigger that is not the visual\n // field and must keep the fixed panel width.\n matchTriggerWidth?: boolean;\n compact?: boolean;\n};\n\n// Width of the panel when it is not following the trigger (`matchTriggerWidth={false}`),\n// and the width the node carries until the measured one is written onto it.\nconst FALLBACK_LIST_WIDTH_CLASS = 'w-80 max-w-[calc(100vw-1.5rem)]';\n// Floor of the panel, applied through `min-width` so it wins over the measured width:\n// a 72px pagination picker or a narrow table cell editor would otherwise open an option\n// list too cramped to read.\nconst MIN_LIST_WIDTH_CLASS = 'min-w-56';\n\nconst ITEM_HEIGHT = 40;\nconst MAX_LIST_HEIGHT = 300;\nconst OVERSCAN_COUNT = 10;\nconst SEARCH_DEBOUNCE_MS = 300;\n// How many selected chips fit inside the trigger before collapsing into \"+N\".\nconst MAX_IN_FIELD_CHIPS = 2;\n\n// Marks the search field so focus can be handed back to it without matching the\n// option checkboxes, which are inputs too.\nconst SEARCH_INPUT_MARKER_CLASS = 'controlled-select-search-input';\nconst TYPEAHEAD_RESET_MS = 500;\nconst FOCUS_RETRY_FRAMES = 6;\n\nconst isPrintableKey = (event: React.KeyboardEvent) =>\n event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey;\n\n/* Padding wrapper. The click is stopped here so a press on the search field is never read\n as a press on an option by the list above it. */\nconst SelectSearchSlot: React.FC<{ children?: ReactNode }> = ({ children }) => (\n <div className=\"px-1 py-0.5\" onClick={(event) => event.stopPropagation()}>\n {children}\n </div>\n);\n\nexport function ControlledSelect({\n label,\n persistentLabel = false,\n options: optionsProp,\n selectedValue,\n error = false,\n multiple = false,\n disabled = false,\n searchable = true,\n clearable = true,\n className,\n listClassName,\n onChangeHook,\n onClearSearch,\n infiniteScroll = false,\n fetchMoreOptions,\n hasMoreOptions = false,\n loading = false,\n onOpen,\n selectedItemsPosition = 'bottom',\n showSelectedItems = true,\n inFieldChips = false,\n preserveLabelCase = false,\n swatchShape = 'dot',\n ariaLabel,\n ariaRequired,\n inputClassName,\n matchTriggerWidth = true,\n compact = false,\n id,\n name,\n required,\n onBlur,\n onFocus,\n autoFocus,\n ...triggerAttributes\n}: TControlledSelectProps) {\n const { t } = useTranslation('ui');\n const options = useMemo(() => (Array.isArray(optionsProp) ? optionsProp : []), [optionsProp]);\n const formatLabel = useCallback(\n (value?: string) => (preserveLabelCase ? (value ?? '') : capitalizeAllLetters(value)),\n [preserveLabelCase],\n );\n const normalizeSelected = useCallback(\n (value: string | Array<string>): string | Array<string> => {\n if (multiple) {\n if (typeof value === 'string') {\n return value === '' ? [] : [value];\n }\n if (Array.isArray(value)) {\n // Legacy multi values arrive as one comma-joined string. A legitimate single value\n // that happens to contain a comma is recognizable by matching a loaded option.\n if (value.length === 1 && value[0].includes(',') && !options.some((option) => option.value === value[0])) {\n return value[0]\n .split(',')\n .map((item) => item.trim())\n .filter((item) => item !== '');\n }\n return value;\n }\n return [];\n } else {\n return typeof value === 'string' ? value : '';\n }\n },\n [multiple, options],\n );\n\n const [selected, setSelected] = useState<string | Array<string>>(() => normalizeSelected(selectedValue));\n\n useEffect(() => {\n setSelected(normalizeSelected(selectedValue));\n }, [selectedValue, normalizeSelected]);\n\n const [filteredOptions, setFilteredOptions] = useState(options);\n const [isOpen, setIsOpen] = useState(false);\n const menuListRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLDivElement>(null);\n const triggerInputRef = useRef<HTMLInputElement>(null);\n const virtualListRef = useRef<List>(null);\n const [activeIndex, setActiveIndex] = useState(-1);\n const [focusRequest, setFocusRequest] = useState(0);\n const pendingFocusIndexRef = useRef<number | null>(null);\n const typeaheadRef = useRef({ buffer: '', timer: 0 });\n const [currentSearchText, setCurrentSearchText] = useState('');\n\n // Unique per instance: a fixed id would make InfiniteScroll attach its scroll listener to\n // the FIRST matching node in the document, which can be another select's list still\n // mounted while its close animation plays.\n const scrollableContainerId = useId();\n const scrollableContainerRef = useRef<HTMLDivElement>(null);\n const isLoadingMoreRef = useRef(false);\n\n // Re-sync the rendered list when the consumer's options change. In client-filtered mode an\n // active search survives the re-sync (same predicate as UnifiedSearchBar), otherwise a parent\n // re-render would wipe the filter while the term stays in the search box.\n useEffect(() => {\n if (!infiniteScroll && currentSearchText) {\n setFilteredOptions(\n options.filter((option) =>\n [option.label, option.secondaryLabel].some((field) => formatFilter(String(field ?? ''), currentSearchText)),\n ),\n );\n return;\n }\n setFilteredOptions(options);\n }, [options]);\n\n const requestPagedOptions = useCallback(\n async (params: IControlledSelectFetchParams) => {\n if (!fetchMoreOptions) return;\n try {\n await fetchMoreOptions(params);\n } catch (fetchError) {\n uiLogger.error('Failed to fetch select options', fetchError);\n }\n },\n [fetchMoreOptions],\n );\n\n const handleLoadMoreFromScroll = useCallback(async () => {\n if (!infiniteScroll || !hasMoreOptions || isLoadingMoreRef.current) return;\n isLoadingMoreRef.current = true;\n try {\n await requestPagedOptions({ search: currentSearchText, reset: false });\n } finally {\n isLoadingMoreRef.current = false;\n }\n }, [infiniteScroll, hasMoreOptions, requestPagedOptions, currentSearchText]);\n\n const handleServerSearch = useCallback(\n (searchText: string) => {\n setCurrentSearchText(searchText);\n if (!infiniteScroll) return;\n if (scrollableContainerRef.current) scrollableContainerRef.current.scrollTop = 0;\n void requestPagedOptions({ search: searchText, reset: true });\n },\n [infiniteScroll, requestPagedOptions],\n );\n\n // Closing with an active search would leave the consumer's list holding only the search\n // results, so the next open would show a filtered list with an empty search box. Restore\n // the unfiltered baseline as the menu closes.\n useEffect(() => {\n if (isOpen || !infiniteScroll || currentSearchText === '') return;\n setCurrentSearchText('');\n void requestPagedOptions({ search: '', reset: true });\n }, [isOpen]);\n\n const handleSelect = useCallback(\n (option: string, event: React.MouseEvent) => {\n if (multiple) {\n event.stopPropagation();\n event.preventDefault();\n\n const currentSelection = selected as Array<string>;\n if (currentSelection.includes(option)) {\n const newSelection = currentSelection.filter((item) => item !== option);\n setSelected(newSelection);\n onChangeHook(newSelection);\n } else {\n const newSelection = [...currentSelection, option];\n setSelected(newSelection);\n onChangeHook(newSelection);\n }\n } else {\n setSelected(option);\n onChangeHook(option);\n if (!infiniteScroll) {\n setCurrentSearchText('');\n setFilteredOptions(options);\n }\n setIsOpen(false);\n }\n },\n [multiple, selected, onChangeHook, options, infiniteScroll],\n );\n\n const handleClearSelection = useCallback(() => {\n if (multiple) {\n setSelected([]);\n onChangeHook([]);\n } else {\n setSelected('');\n onChangeHook('');\n }\n\n if (!infiniteScroll) {\n setCurrentSearchText('');\n setFilteredOptions(options);\n }\n\n if (onClearSearch) {\n onClearSearch();\n }\n }, [multiple, onChangeHook, onClearSearch, options, infiniteScroll]);\n\n const getDisplayLabel = useCallback(() => {\n if (multiple) {\n const selectedArray = selected as Array<string>;\n if (selectedArray.length === 0) {\n return '';\n } else if (selectedArray.length === 1) {\n const foundOption = options.find((item) => item.value === selectedArray[0]);\n\n return formatLabel(foundOption?.label || selectedArray[0]);\n } else {\n return `${selectedArray.length} itens selecionados`;\n }\n } else {\n const foundOption = options.find((item) => item.value === selected);\n\n return formatLabel(foundOption?.label || (selected as string) || label);\n }\n }, [multiple, selected, options, label, formatLabel]);\n\n const getOptionId = useCallback(\n (index: number) => `${scrollableContainerId}-option-${index}`,\n [scrollableContainerId],\n );\n\n const isOptionEnabled = useCallback(\n (index: number) => {\n const option = filteredOptions[index];\n return Boolean(option) && !option.disabled;\n },\n [filteredOptions],\n );\n\n /** Next enabled index from `start` walking by `step`, or -1. Never wraps (APG select-only). */\n const findEnabledIndex = useCallback(\n (start: number, step: 1 | -1) => {\n for (let index = start; index >= 0 && index < filteredOptions.length; index += step) {\n if (isOptionEnabled(index)) return index;\n }\n return -1;\n },\n [filteredOptions.length, isOptionEnabled],\n );\n\n const getSelectedIndex = useCallback(() => {\n const firstSelected = multiple ? (selected as Array<string>)[0] : (selected as string);\n const index = filteredOptions.findIndex((option) => option.value === firstSelected);\n return index >= 0 && isOptionEnabled(index) ? index : -1;\n }, [multiple, selected, filteredOptions, isOptionEnabled]);\n\n const focusOptionAt = useCallback((index: number) => {\n if (index < 0) return;\n setActiveIndex(index);\n pendingFocusIndexRef.current = index;\n setFocusRequest((request) => request + 1);\n }, []);\n\n const focusSearchInput = useCallback(() => {\n const searchInput = menuListRef.current?.querySelector<HTMLInputElement>(`.${SEARCH_INPUT_MARKER_CLASS}`);\n if (!searchInput) return false;\n searchInput.focus();\n return true;\n }, []);\n\n const findTypeaheadMatch = useCallback(\n (key: string, fromIndex: number) => {\n const state = typeaheadRef.current;\n window.clearTimeout(state.timer);\n state.buffer += key.toLowerCase();\n state.timer = window.setTimeout(() => {\n state.buffer = '';\n }, TYPEAHEAD_RESET_MS);\n\n // Repeating one letter cycles through the options that start with it.\n const isCycling = state.buffer.split('').every((char) => char === state.buffer[0]);\n const term = isCycling ? state.buffer[0] : state.buffer;\n const start = isCycling ? fromIndex + 1 : Math.max(fromIndex, 0);\n const total = filteredOptions.length;\n\n for (let offset = 0; offset < total; offset += 1) {\n const index = (start + offset) % total;\n const label = formatLabel(filteredOptions[index]?.label).toLowerCase();\n if (isOptionEnabled(index) && label.startsWith(term)) return index;\n }\n return -1;\n },\n [filteredOptions, formatLabel, isOptionEnabled],\n );\n\n type TOpenTarget = 'selected' | 'first' | 'last' | number;\n\n const openAndFocus = useCallback(\n (target: TOpenTarget) => {\n if (disabled) return;\n if (!isOpen) {\n setIsOpen(true);\n onOpen?.();\n }\n\n if (searchable && target === 'selected') {\n // With a search field the keyboard lands on it; ArrowDown then walks into the options.\n pendingFocusIndexRef.current = -1;\n setFocusRequest((request) => request + 1);\n return;\n }\n\n let index: number;\n if (typeof target === 'number') index = target;\n else if (target === 'first') index = findEnabledIndex(0, 1);\n else if (target === 'last') index = findEnabledIndex(filteredOptions.length - 1, -1);\n else index = getSelectedIndex() >= 0 ? getSelectedIndex() : findEnabledIndex(0, 1);\n focusOptionAt(index);\n },\n [disabled, isOpen, onOpen, searchable, findEnabledIndex, filteredOptions.length, getSelectedIndex, focusOptionAt],\n );\n\n // Moves DOM focus to the requested option once it is rendered: a virtualized row far from\n // the viewport only exists after react-window re-renders at the new scroll offset.\n useEffect(() => {\n const index = pendingFocusIndexRef.current;\n if (!isOpen || index === null) return undefined;\n\n if (index >= 0) virtualListRef.current?.scrollToItem(index);\n\n let attempts = 0;\n let frame = 0;\n const tryFocus = () => {\n if (index < 0) {\n if (focusSearchInput()) {\n pendingFocusIndexRef.current = null;\n return;\n }\n } else {\n const node = document.getElementById(getOptionId(index));\n if (node) {\n pendingFocusIndexRef.current = null;\n node.focus({ preventScroll: Boolean(virtualListRef.current) });\n if (!virtualListRef.current) node.scrollIntoView?.({ block: 'nearest' });\n return;\n }\n }\n attempts += 1;\n if (attempts < FOCUS_RETRY_FRAMES) frame = window.requestAnimationFrame(tryFocus);\n };\n\n tryFocus();\n return () => window.cancelAnimationFrame(frame);\n }, [isOpen, focusRequest]);\n\n // Closing hands focus back to the trigger when it was inside the list (a keyboard or pointer\n // selection, ESC) or was lost with it; a click elsewhere keeps the focus it moved.\n const wasOpenRef = useRef(false);\n useEffect(() => {\n if (isOpen) {\n wasOpenRef.current = true;\n return;\n }\n if (!wasOpenRef.current) return;\n wasOpenRef.current = false;\n setActiveIndex(-1);\n pendingFocusIndexRef.current = null;\n\n const active = document.activeElement;\n const focusWasInList = Boolean(active && menuListRef.current?.contains(active));\n if (focusWasInList || active === document.body || active === null) {\n triggerInputRef.current?.focus({ preventScroll: true });\n }\n }, [isOpen]);\n\n useEffect(() => {\n setActiveIndex(-1);\n }, [filteredOptions]);\n\n // A multi-select toggle re-renders the virtualized rows, which replaces the focused node:\n // put focus back on the same option so the keyboard user keeps their place.\n useEffect(() => {\n if (!isOpen || activeIndex < 0) return;\n const active = document.activeElement;\n if (active === null || active === document.body) focusOptionAt(activeIndex);\n }, [selected]);\n\n useEffect(() => () => window.clearTimeout(typeaheadRef.current.timer), []);\n\n // The list is named like its trigger, including a trigger named only by `<label htmlFor>`.\n const listboxLabel =\n triggerAttributes['aria-label'] ??\n ariaLabel ??\n label ??\n (isOpen ? triggerInputRef.current?.labels?.[0]?.textContent?.trim() || undefined : undefined);\n\n const handleTriggerKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (disabled) return;\n\n switch (event.key) {\n case 'Enter':\n case ' ':\n case 'ArrowDown':\n event.preventDefault();\n openAndFocus(isOpen && event.key === 'ArrowDown' && activeIndex >= 0 ? activeIndex : 'selected');\n return;\n case 'ArrowUp':\n event.preventDefault();\n openAndFocus(getSelectedIndex() >= 0 ? getSelectedIndex() : 'last');\n return;\n case 'Home':\n event.preventDefault();\n openAndFocus('first');\n return;\n case 'End':\n event.preventDefault();\n openAndFocus('last');\n return;\n case 'Escape':\n if (!isOpen) return;\n // Marks it handled so an enclosing dialog does not close too.\n event.preventDefault();\n setIsOpen(false);\n return;\n case 'Tab':\n if (isOpen) setIsOpen(false);\n return;\n default:\n if (!isPrintableKey(event) || searchable) return;\n event.preventDefault();\n openAndFocus(findTypeaheadMatch(event.key, getSelectedIndex()));\n }\n };\n\n const handleListKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n const target = event.target as HTMLElement;\n const isOnSearch = target.classList.contains(SEARCH_INPUT_MARKER_CLASS);\n const optionNode = target.closest<HTMLElement>('[role=\"option\"]');\n const currentIndex = optionNode ? Number(optionNode.dataset.optionIndex ?? -1) : activeIndex;\n\n switch (event.key) {\n case 'ArrowDown': {\n event.preventDefault();\n const next = isOnSearch ? findEnabledIndex(0, 1) : findEnabledIndex(currentIndex + 1, 1);\n focusOptionAt(next);\n return;\n }\n case 'ArrowUp': {\n if (isOnSearch) return;\n event.preventDefault();\n const previous = findEnabledIndex(currentIndex - 1, -1);\n if (previous >= 0) focusOptionAt(previous);\n else if (searchable) focusSearchInput();\n return;\n }\n case 'Home':\n case 'End':\n if (isOnSearch) return;\n event.preventDefault();\n focusOptionAt(event.key === 'Home' ? findEnabledIndex(0, 1) : findEnabledIndex(filteredOptions.length - 1, -1));\n return;\n case 'Escape':\n event.preventDefault();\n setIsOpen(false);\n return;\n case 'Tab':\n event.preventDefault();\n setIsOpen(false);\n triggerInputRef.current?.focus({ preventScroll: true });\n return;\n default:\n if (isOnSearch || !isPrintableKey(event) || event.key === ' ') return;\n event.preventDefault();\n focusOptionAt(findTypeaheadMatch(event.key, currentIndex));\n }\n };\n\n const renderOptionItem = useCallback(\n (option: IFilterOption, index: number, style?: React.CSSProperties) => {\n const isSelected = multiple\n ? Array.isArray(selected) && selected.includes(option.value)\n : option.value === selected;\n\n // A disabled option explains itself on hover over the WHOLE row, not just the info icon.\n const isDisabledWithReason = Boolean(option.disabled && option.tooltip);\n\n const menuItem = (\n <ControlledMenuItem\n key={isDisabledWithReason ? undefined : option.value}\n disabled={option.disabled}\n onClick={(event: React.MouseEvent) => handleSelect(option.value, event)}\n role=\"option\"\n id={getOptionId(index)}\n tabIndex={-1}\n aria-selected={isSelected}\n aria-setsize={filteredOptions.length}\n aria-posinset={index + 1}\n data-option-index={index}\n className={classNames(\n 'relative flex items-center p-2 pl-3 text-foreground',\n 'focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring',\n {\n // The hover variant has to live inside the selected branch: the menu item's own\n // default hover would otherwise wipe the selected tint.\n 'bg-brand-soft font-medium text-brand-emphasis hover:!bg-brand-soft focus:!bg-brand-soft': isSelected,\n 'hover:!bg-muted': !isSelected,\n },\n )}\n style={{\n ...(isDisabledWithReason ? {} : style),\n height: ITEM_HEIGHT - 1,\n }}\n >\n {isSelected && <span className=\"absolute inset-y-1 left-0 w-0.5 rounded-full bg-brand\" />}\n {multiple && (\n // The option itself carries aria-selected; the checkbox is only its picture.\n <span aria-hidden className=\"pointer-events-none\">\n <ControlledCheckbox checked={isSelected} onChange={() => {}} />\n </span>\n )}\n {option.tooltip && !isDisabledWithReason && (\n <ControlledTooltip content={option.tooltip} className=\"w-full max-w-72\">\n <MaterialSymbol icon=\"info\" size={15} color=\"rgb(var(--color-foreground-subtle))\" className=\"mr-1\" />\n </ControlledTooltip>\n )}\n {option.swatch && (\n <span\n className={classNames(\n 'mr-2 size-3.5 shrink-0 border border-border',\n swatchShape === 'square' ? 'rounded' : 'rounded-full',\n )}\n style={{ backgroundColor: option.swatch }}\n />\n )}\n <span className=\"truncate text-sm\">{formatLabel(option.label)}</span>\n {option.secondaryLabel && option.emphasizeSecondaryLabel && (\n <OutlinedChip\n label={option.secondaryLabel}\n tone=\"purple\"\n variant=\"soft\"\n size=\"xs\"\n preserveLabelCase\n truncate\n className=\"ml-auto max-w-[45%] shrink-0\"\n />\n )}\n {option.secondaryLabel && !option.emphasizeSecondaryLabel && (\n <span className=\"ml-auto max-w-[45%] shrink-0 truncate pl-3 text-xs text-foreground-faint\">\n {option.secondaryLabel}\n </span>\n )}\n </ControlledMenuItem>\n );\n\n // The wrapper div carries the virtualized position because the tooltip clones its child and\n // injects its own ref.\n return isDisabledWithReason ? (\n <ControlledTooltip key={option.value} content={option.tooltip} className=\"z-[9999] max-w-72\">\n <div style={style}>{menuItem}</div>\n </ControlledTooltip>\n ) : (\n menuItem\n );\n },\n [multiple, selected, handleSelect, formatLabel, getOptionId, filteredOptions.length],\n );\n\n const ItemRenderer = useCallback(\n ({ index, style }: { index: number; style: React.CSSProperties }) => {\n const option = filteredOptions[index];\n if (!option) return null;\n\n return renderOptionItem(option, index, style);\n },\n [filteredOptions, renderOptionItem],\n );\n\n const listHeight = useMemo(\n () => Math.min(filteredOptions.length * ITEM_HEIGHT, MAX_LIST_HEIGHT),\n [filteredOptions.length],\n );\n\n const selectedSwatch = useMemo(\n () => (multiple ? undefined : options.find((option) => option.value === selected)?.swatch),\n [multiple, options, selected],\n );\n\n // Com uma opção selecionada, o próprio valor identifica o campo: a label flutuante\n // some (evita duplicar quando já há um rótulo externo acima do select).\n const selectedHasValue = multiple ? (selected as Array<string>).length > 0 : selected !== '';\n\n /**\n * Opção declarada com valor vazio (\"Todas\", \"Nenhum\", \"Sem recorte\"): é uma\n * escolha de verdade, não a ausência de escolha, então o campo precisa exibir\n * o rótulo dela em vez de ficar em branco.\n */\n const hasEmptyValueOption = useMemo(\n () => !multiple && options.some((option) => option.value === ''),\n [multiple, options],\n );\n\n // The dropdown is portaled, so a percentage width would resolve against the\n // page, and a runtime pixel value cannot become a Tailwind arbitrary class.\n // The measured width is written straight onto the node: the floating logic\n // overwrites the MenuList `style` prop with its own position, and React never\n // clears `width` because it is not part of that style object.\n // It runs as a layout effect because the panel also carries a fallback width class:\n // measuring after paint would show that width for one frame, mid enter animation.\n useLayoutEffect(() => {\n const menuList = menuListRef.current;\n const trigger = triggerRef.current;\n if (!matchTriggerWidth || !isOpen || !menuList || !trigger) return undefined;\n\n const applyTriggerWidth = () => {\n menuList.style.width = `${trigger.getBoundingClientRect().width}px`;\n };\n\n applyTriggerWidth();\n\n const resizeObserver = new ResizeObserver(applyTriggerWidth);\n resizeObserver.observe(trigger);\n\n return () => resizeObserver.disconnect();\n }, [matchTriggerWidth, isOpen]);\n\n // Moving the pointer inside the menu makes floating-ui's list navigation pull\n // focus off the search field (it focuses the hovered option, or the menu\n // container on pointer leave). Take focus back whenever the pointer caused it,\n // while leaving keyboard navigation into the options alone.\n useEffect(() => {\n const menuList = menuListRef.current;\n if (!isOpen || !searchable || !menuList) return undefined;\n\n let isKeyboardInteraction = false;\n let restoreFrame = 0;\n\n const markKeyboardInteraction = () => {\n isKeyboardInteraction = true;\n };\n\n const markPointerInteraction = () => {\n isKeyboardInteraction = false;\n };\n\n const restoreSearchFocus = (event: FocusEvent) => {\n const searchInput = menuList.querySelector<HTMLInputElement>(`.${SEARCH_INPUT_MARKER_CLASS}`);\n if (!searchInput || event.target !== searchInput || isKeyboardInteraction) return;\n\n const nextFocused = event.relatedTarget as Node | null;\n if (nextFocused && !menuList.contains(nextFocused)) return;\n\n // The steal happens as this event is dispatched, so reclaim on the next frame.\n restoreFrame = window.requestAnimationFrame(() => searchInput.focus({ preventScroll: true }));\n };\n\n menuList.addEventListener('keydown', markKeyboardInteraction, true);\n menuList.addEventListener('pointermove', markPointerInteraction, true);\n menuList.addEventListener('focusout', restoreSearchFocus);\n\n return () => {\n window.cancelAnimationFrame(restoreFrame);\n menuList.removeEventListener('keydown', markKeyboardInteraction, true);\n menuList.removeEventListener('pointermove', markPointerInteraction, true);\n menuList.removeEventListener('focusout', restoreSearchFocus);\n };\n }, [isOpen, searchable]);\n\n const handleClearSearch = useCallback(() => {\n setCurrentSearchText('');\n\n if (infiniteScroll) {\n if (scrollableContainerRef.current) scrollableContainerRef.current.scrollTop = 0;\n void requestPagedOptions({ search: '', reset: true });\n } else {\n setFilteredOptions(options);\n }\n\n if (onClearSearch) {\n onClearSearch();\n }\n }, [infiniteScroll, requestPagedOptions, onClearSearch, options]);\n\n const getSelectedOptionsLabels = useCallback(() => {\n if (!multiple || !selected || (selected as Array<string>).length === 0) {\n return [];\n }\n\n const selectedArray = selected as Array<string>;\n\n return selectedArray.map((value) => {\n const trimmedValue = value.trim();\n const foundOption = options.find((option) => option.value === trimmedValue);\n return {\n value: trimmedValue,\n label: foundOption?.label || trimmedValue,\n swatch: foundOption?.swatch,\n };\n });\n }, [multiple, selected, options]);\n\n const isLateralPosition = selectedItemsPosition === 'left' || selectedItemsPosition === 'right';\n\n const inFieldChipItems = inFieldChips ? getSelectedOptionsLabels() : [];\n const showInFieldChips = inFieldChips && multiple && inFieldChipItems.length > 0;\n const visibleInFieldChips = inFieldChipItems.slice(0, MAX_IN_FIELD_CHIPS);\n const inFieldOverflow = inFieldChipItems.length - visibleInFieldChips.length;\n const inFieldChipsTooltip = inFieldChipItems.map((option) => formatLabel(option.label)).join(', ');\n\n const selectedItemsChips = showSelectedItems && multiple && getSelectedOptionsLabels().length > 1 && (\n <div className=\"flex flex-wrap gap-1\">\n {getSelectedOptionsLabels().map((option) => (\n <OutlinedChip\n key={option.value}\n label={option.label}\n preserveLabelCase={preserveLabelCase}\n dot={Boolean(option.swatch)}\n dotColor={option.swatch}\n className={classNames('bg-muted-active text-lg', { 'px-4 py-1': isLateralPosition })}\n labelClassName={isLateralPosition ? 'text-sm' : undefined}\n onClose={(event: React.MouseEvent) => handleSelect(option.value, event)}\n canClose\n />\n ))}\n </div>\n );\n\n const showClear =\n clearable &&\n !disabled &&\n Boolean(selected) &&\n (multiple ? (selected as Array<string>).length > 0 : selected !== '');\n\n const cursorClassName = disabled ? 'cursor-not-allowed' : 'cursor-pointer';\n\n return (\n <ControlledMenuRoot\n placement=\"bottom-start\"\n open={isOpen && !disabled}\n handler={(next) => {\n if (disabled) return;\n setIsOpen(next);\n if (next) onOpen?.();\n }}\n dismiss={{ itemPress: !multiple }}\n >\n <ControlledMenuHandler skipTriggerAria>\n <div\n className={classNames('flex', {\n 'flex-col gap-y-2': selectedItemsPosition === 'bottom' || selectedItemsPosition === 'top',\n 'flex-row items-start gap-x-2': selectedItemsPosition === 'left' || selectedItemsPosition === 'right',\n })}\n >\n {(selectedItemsPosition === 'top' || selectedItemsPosition === 'left') && selectedItemsChips}\n <div ref={triggerRef} className={classNames('relative', cursorClassName, className)}>\n {selectedSwatch && (\n <span\n className={classNames(\n 'pointer-events-none absolute left-3 top-1/2 z-10 size-3.5 -translate-y-1/2 border border-border',\n swatchShape === 'square' ? 'rounded' : 'rounded-full',\n )}\n style={{ backgroundColor: selectedSwatch }}\n />\n )}\n {showInFieldChips && (\n <ControlledTooltip content={inFieldChipsTooltip} className=\"max-w-72\">\n <div\n className={classNames(\n 'absolute inset-y-0 left-2.5 right-14 z-10 flex items-center gap-1 overflow-hidden',\n cursorClassName,\n )}\n >\n {visibleInFieldChips.map((option) => (\n <OutlinedChip\n key={option.value}\n label={option.label}\n preserveLabelCase={preserveLabelCase}\n dot={Boolean(option.swatch)}\n dotColor={option.swatch}\n className=\"min-w-0 shrink-0 bg-muted-active\"\n labelClassName=\"text-xxs\"\n />\n ))}\n {inFieldOverflow > 0 && (\n <OutlinedChip\n label={t('controlledSelect.moreItems', { count: inFieldOverflow })}\n className=\"min-w-0 shrink-0 bg-muted-active\"\n labelClassName=\"text-xxs\"\n />\n )}\n </div>\n </ControlledTooltip>\n )}\n <ControlledInput\n {...triggerAttributes}\n id={id}\n inputRef={triggerInputRef}\n onBlur={onBlur}\n onFocus={onFocus}\n autoFocus={autoFocus}\n readOnly\n role=\"combobox\"\n // eslint-disable-next-line i18n-check/no-literal-jsx-strings -- ARIA token, not user-facing text\n aria-haspopup=\"listbox\"\n aria-expanded={isOpen}\n aria-controls={isOpen ? scrollableContainerId : undefined}\n onKeyDown={handleTriggerKeyDown}\n className={classNames(\n 'controlled-select-input flex w-full min-w-0 justify-between truncate text-left',\n !compact && 'tablet:min-w-52',\n cursorClassName,\n selectedSwatch && '!pl-9',\n // O \"x\" é absoluto SOBRE o input: sem esta reserva o rótulo passa por baixo dele.\n showClear && '!pr-14',\n inputClassName,\n )}\n error={error}\n autoComplete=\"off\"\n rightSlot={<MaterialSymbol className={cursorClassName} icon=\"keyboard_arrow_down\" size={15} />}\n label={selectedHasValue && !persistentLabel ? undefined : label}\n aria-label={triggerAttributes['aria-label'] ?? ariaLabel ?? label}\n aria-required={ariaRequired || required ? true : triggerAttributes['aria-required']}\n value={showInFieldChips ? ' ' : selectedHasValue || hasEmptyValueOption ? getDisplayLabel() : ''}\n disabled={disabled}\n />\n\n {showClear && (\n <ControlledTooltip content={t('dates.clearSelection')}>\n <div\n onClick={handleClearSelection}\n className=\"absolute inset-y-0 right-8 top-0.5 flex cursor-pointer items-center\"\n >\n <MaterialSymbol icon=\"close_small\" size={20} color=\"rgb(var(--color-foreground-subtle))\" />\n </div>\n </ControlledTooltip>\n )}\n </div>\n\n {name &&\n (multiple\n ? (selected as Array<string>).map((value) => (\n <input key={value} type=\"hidden\" name={name} value={value} disabled={disabled} />\n ))\n : selected !== '' && <input type=\"hidden\" name={name} value={selected as string} disabled={disabled} />)}\n\n {(selectedItemsPosition === 'bottom' || selectedItemsPosition === 'right') && selectedItemsChips}\n </div>\n </ControlledMenuHandler>\n\n <ControlledMenuList\n ref={menuListRef}\n role=\"presentation\"\n onKeyDown={handleListKeyDown}\n className={classNames(\n 'zIndexMax overflow-hidden',\n FALLBACK_LIST_WIDTH_CLASS,\n MIN_LIST_WIDTH_CLASS,\n listClassName,\n )}\n >\n {searchable && (\n <SelectSearchSlot>\n <UnifiedSearchBar\n mode=\"default\"\n label={t('actions.search')}\n debounceTime={SEARCH_DEBOUNCE_MS}\n // Em modo infinito quem filtra é o servidor: sem itens, a barra só reporta o\n // termo via onSearchTermChange e nunca escreve na lista local.\n searchableItems={infiniteScroll ? null : options}\n searchKeys={['label', 'secondaryLabel']}\n setFilteredItems={setFilteredOptions}\n onSearchTermChange={handleServerSearch}\n className={classNames('w-full', SEARCH_INPUT_MARKER_CLASS)}\n onClearFilter={handleClearSearch}\n initialValue={currentSearchText}\n />\n </SelectSearchSlot>\n )}\n\n <div\n ref={scrollableContainerRef}\n className={classNames({\n 'max-h-[250px] overflow-y-auto overscroll-contain': infiniteScroll,\n 'overflow-hidden': !infiniteScroll,\n })}\n id={scrollableContainerId}\n role=\"listbox\"\n aria-multiselectable={multiple || undefined}\n aria-labelledby={triggerAttributes['aria-labelledby']}\n aria-label={triggerAttributes['aria-labelledby'] ? undefined : listboxLabel}\n >\n {infiniteScroll ? (\n <InfiniteScroll\n dataLength={filteredOptions.length}\n // O loader do InfiniteScroll é renderizado sempre que `hasMore` é verdadeiro, ao lado\n // do conteúdo. Com a lista vazia isso empilhava o spinner sobre o estado vazio (ou\n // sobre o próprio spinner de `loading`): sem opções, quem manda é o bloco abaixo.\n hasMore={hasMoreOptions && filteredOptions.length > 0}\n next={handleLoadMoreFromScroll}\n loader={\n <div className=\"flex size-full items-center justify-center py-1\">\n <LoadingSpinner size={4} label={t('controlledSelect.loadingOptions')} />\n </div>\n }\n scrollableTarget={scrollableContainerId}\n // `overflow-hidden` makes this a scroll port the user cannot scroll, so\n // `overscroll-none` here stopped the wheel from ever reaching the container\n // that does scroll: the list only moved by dragging its bar. Containment\n // belongs to that container, which already declares `overscroll-contain`.\n className=\"!overflow-hidden\"\n >\n {filteredOptions.length > 0 ? (\n filteredOptions.map((option, index) => renderOptionItem(option, index))\n ) : loading ? (\n <div className=\"flex w-full items-center justify-center py-4\">\n <LoadingSpinner size={4} label={t('controlledSelect.loadingOptions')} />\n </div>\n ) : (\n <ControlledMenuItem disabled role=\"presentation\">\n <NoDataFound compact message={t('controlledSelect.noDataToShow')} />\n </ControlledMenuItem>\n )}\n </InfiniteScroll>\n ) : filteredOptions.length > 0 ? (\n <List\n ref={virtualListRef}\n className=\"virtualized-select-list\"\n height={listHeight}\n // eslint-disable-next-line i18n-check/no-literal-jsx-strings\n width=\"100%\"\n itemCount={filteredOptions.length}\n itemSize={ITEM_HEIGHT}\n overscanCount={OVERSCAN_COUNT}\n >\n {ItemRenderer}\n </List>\n ) : loading ? (\n <div className=\"flex w-full items-center justify-center py-4\">\n <LoadingSpinner size={4} label={t('controlledSelect.loadingOptions')} />\n </div>\n ) : (\n <ControlledMenuItem disabled role=\"presentation\">\n <NoDataFound compact message={t('controlledSelect.noDataToShow')} />\n </ControlledMenuItem>\n )}\n </div>\n </ControlledMenuList>\n </ControlledMenuRoot>\n );\n}\n"],"names":["label","List"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ControlledSelect.js","sources":["../../../src/components/Form/ControlledSelect.tsx"],"sourcesContent":["import { ReactNode, useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from 'react';\nimport classNames from 'classnames';\nimport { useTranslation } from 'react-i18next';\nimport InfiniteScroll from 'react-infinite-scroll-component';\nimport { FixedSizeList as List } from 'react-window';\n\nimport {\n ControlledMenuHandler,\n ControlledMenuItem,\n ControlledMenuList,\n ControlledMenuRoot,\n} from '@/components/UI/ControlledMenu';\nimport ControlledTooltip from '@/components/UI/ControlledTooltip';\nimport { capitalizeAllLetters, formatFilter } from '@/helpers/stringHelpers';\nimport { uiLogger } from '@/helpers/uiLogger';\n\nimport { IFilterOption } from '../../interfaces/IFilterOption';\nimport UnifiedSearchBar from '../Search/UnifiedSearchBar';\nimport OutlinedChip from '../UI/Chips/OutlinedChip';\nimport LoadingSpinner from '../UI/LoadingSpinner';\nimport { MaterialSymbol } from '../UI/MaterialSymbol';\nimport NoDataFound from '../UI/NoDataFound';\n\nimport ControlledCheckbox from './ControlledCheckbox';\nimport ControlledInput from './ControlledInput';\n\nimport '../../styles/virtualizedSelect.css';\n\n/**\n * Contract of `fetchMoreOptions`, the single loader of infinite-scroll selects.\n * `reset: true` means \"replace the list with page 1 of `search`\" (a new search, a cleared\n * search, or the restore to the unfiltered baseline). `reset: false` means \"append the NEXT\n * page of the same `search`\". The consumer owns the page counter and the accumulated\n * `options` prop; this component never accumulates results itself.\n */\nexport interface IControlledSelectFetchParams {\n search: string;\n reset: boolean;\n}\n\ntype TDataAttributes = { [key: `data-${string}`]: string | number | boolean | undefined };\n\n/**\n * Native and ARIA attributes forwarded to the combobox trigger: `id` (so a `<label htmlFor>`\n * names it), `aria-labelledby` / `aria-describedby` / `aria-invalid`, `data-*`, `onBlur`.\n * `name` is submitted through hidden inputs carrying the selected value(s), never the label.\n */\ntype TControlledSelectTriggerProps = Pick<\n React.InputHTMLAttributes<HTMLInputElement>,\n 'id' | 'name' | 'required' | 'onBlur' | 'onFocus' | 'autoFocus'\n> &\n React.AriaAttributes &\n TDataAttributes;\n\ntype TControlledSelectProps = TControlledSelectTriggerProps & {\n label?: string;\n // Mantém a label flutuante visível (encolhida na borda) mesmo com um valor selecionado.\n // Padrão: false — a label some ao selecionar, assumindo que há um rótulo externo acima.\n persistentLabel?: boolean;\n options: Array<IFilterOption>;\n selectedValue: string | Array<string>;\n error?: boolean;\n multiple?: boolean;\n searchable?: boolean;\n disabled?: boolean;\n clearable?: boolean;\n className?: string;\n listClassName?: string;\n onChangeHook: (selected: string | Array<string>) => void;\n infiniteScroll?: boolean;\n fetchMoreOptions?: (params: IControlledSelectFetchParams) => Promise<unknown>;\n hasMoreOptions?: boolean;\n loading?: boolean;\n onClearSearch?: () => void;\n onOpen?: () => void;\n selectedItemsPosition?: 'bottom' | 'top' | 'left' | 'right';\n // When false, the selected-items chips are not rendered beside the trigger;\n // only the count summary (\"N itens selecionados\") shows inside the trigger.\n showSelectedItems?: boolean;\n // Multi-select only: render the selected values as chips inside the trigger\n // field (with a \"+N\" overflow indicator and a tooltip listing all of them)\n // instead of the generic \"N itens selecionados\" count.\n inFieldChips?: boolean;\n // Por padrão as labels passam por capitalizeAllLetters (Primeira Maiúscula, resto\n // minúsculo). Use true quando a label é um identificador literal — nome de tabela,\n // coluna, chave — em que o caixa original é significativo e não pode ser alterado.\n preserveLabelCase?: boolean;\n // Shape of the option swatch. Colors read as the square chip the libraries use;\n // the dot stays the default for tags and categories.\n swatchShape?: 'dot' | 'square';\n // Accessible name of the trigger, for a field whose meaning comes from the\n // surrounding layout and therefore renders no visible label or placeholder.\n ariaLabel?: string;\n // Marks the combobox trigger as required for assistive tech (aria-required).\n ariaRequired?: boolean;\n // Classes for the trigger input itself, for a select embedded in a composed\n // control (a segmented field) that must drop its own border, fill or minimum\n // width. `className` styles the wrapper and cannot reach the input.\n inputClassName?: string;\n // The dropdown follows the width of the field by default, so the panel and the search\n // box in it are never narrower than the trigger they belong to. A trigger below\n // MIN_LIST_WIDTH_CLASS keeps the panel at that floor, because an option list the width\n // of a 72px picker is unreadable. Pass false for a trigger that is not the visual\n // field and must keep the fixed panel width.\n matchTriggerWidth?: boolean;\n compact?: boolean;\n};\n\n// Width of the panel when it is not following the trigger (`matchTriggerWidth={false}`),\n// and the width the node carries until the measured one is written onto it.\nconst FALLBACK_LIST_WIDTH_CLASS = 'w-80 max-w-[calc(100vw-1.5rem)]';\n// Floor of the panel, applied through `min-width` so it wins over the measured width:\n// a 72px pagination picker or a narrow table cell editor would otherwise open an option\n// list too cramped to read.\nconst MIN_LIST_WIDTH_CLASS = 'min-w-56';\n\nconst ITEM_HEIGHT = 40;\nconst MAX_LIST_HEIGHT = 300;\nconst OVERSCAN_COUNT = 10;\nconst SEARCH_DEBOUNCE_MS = 300;\n// How many selected chips fit inside the trigger before collapsing into \"+N\".\nconst MAX_IN_FIELD_CHIPS = 2;\n\n// Marks the search field so focus can be handed back to it without matching the\n// option checkboxes, which are inputs too.\nconst SEARCH_INPUT_MARKER_CLASS = 'controlled-select-search-input';\nconst TYPEAHEAD_RESET_MS = 500;\nconst FOCUS_RETRY_FRAMES = 6;\n\nconst isPrintableKey = (event: React.KeyboardEvent) =>\n event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey;\n\n/* Padding wrapper. The click is stopped here so a press on the search field is never read\n as a press on an option by the list above it. */\nconst SelectSearchSlot: React.FC<{ children?: ReactNode }> = ({ children }) => (\n <div className=\"px-1 py-0.5\" onClick={(event) => event.stopPropagation()}>\n {children}\n </div>\n);\n\nexport function ControlledSelect({\n label,\n persistentLabel = false,\n options: optionsProp,\n selectedValue,\n error = false,\n multiple = false,\n disabled = false,\n searchable = true,\n clearable = true,\n className,\n listClassName,\n onChangeHook,\n onClearSearch,\n infiniteScroll = false,\n fetchMoreOptions,\n hasMoreOptions = false,\n loading = false,\n onOpen,\n selectedItemsPosition = 'bottom',\n showSelectedItems = true,\n inFieldChips = false,\n preserveLabelCase = false,\n swatchShape = 'dot',\n ariaLabel,\n ariaRequired,\n inputClassName,\n matchTriggerWidth = true,\n compact = false,\n id,\n name,\n required,\n onBlur,\n onFocus,\n autoFocus,\n ...triggerAttributes\n}: TControlledSelectProps) {\n const { t } = useTranslation('ui');\n const options = useMemo(() => (Array.isArray(optionsProp) ? optionsProp : []), [optionsProp]);\n const formatLabel = useCallback(\n (value?: string) => (preserveLabelCase ? (value ?? '') : capitalizeAllLetters(value)),\n [preserveLabelCase],\n );\n const normalizeSelected = useCallback(\n (value: string | Array<string>): string | Array<string> => {\n if (multiple) {\n if (typeof value === 'string') {\n return value === '' ? [] : [value];\n }\n if (Array.isArray(value)) {\n // Legacy multi values arrive as one comma-joined string. A legitimate single value\n // that happens to contain a comma is recognizable by matching a loaded option.\n if (value.length === 1 && value[0].includes(',') && !options.some((option) => option.value === value[0])) {\n return value[0]\n .split(',')\n .map((item) => item.trim())\n .filter((item) => item !== '');\n }\n return value;\n }\n return [];\n } else {\n return typeof value === 'string' ? value : '';\n }\n },\n [multiple, options],\n );\n\n const [selected, setSelected] = useState<string | Array<string>>(() => normalizeSelected(selectedValue));\n\n useEffect(() => {\n setSelected(normalizeSelected(selectedValue));\n }, [selectedValue, normalizeSelected]);\n\n const [filteredOptions, setFilteredOptions] = useState(options);\n const [isOpen, setIsOpen] = useState(false);\n const menuListRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLDivElement>(null);\n const triggerInputRef = useRef<HTMLInputElement>(null);\n const virtualListRef = useRef<List>(null);\n const [activeIndex, setActiveIndex] = useState(-1);\n const [focusRequest, setFocusRequest] = useState(0);\n const pendingFocusIndexRef = useRef<number | null>(null);\n const typeaheadRef = useRef({ buffer: '', timer: 0 });\n const [currentSearchText, setCurrentSearchText] = useState('');\n\n // Unique per instance: a fixed id would make InfiniteScroll attach its scroll listener to\n // the FIRST matching node in the document, which can be another select's list still\n // mounted while its close animation plays.\n const scrollableContainerId = useId();\n const scrollableContainerRef = useRef<HTMLDivElement>(null);\n const isLoadingMoreRef = useRef(false);\n\n // Re-sync the rendered list when the consumer's options change. In client-filtered mode an\n // active search survives the re-sync (same predicate as UnifiedSearchBar), otherwise a parent\n // re-render would wipe the filter while the term stays in the search box.\n useEffect(() => {\n if (!infiniteScroll && currentSearchText) {\n setFilteredOptions(\n options.filter((option) =>\n [option.label, option.secondaryLabel].some((field) => formatFilter(String(field ?? ''), currentSearchText)),\n ),\n );\n return;\n }\n setFilteredOptions(options);\n }, [options]);\n\n const requestPagedOptions = useCallback(\n async (params: IControlledSelectFetchParams) => {\n if (!fetchMoreOptions) return;\n try {\n await fetchMoreOptions(params);\n } catch (fetchError) {\n uiLogger.error('Failed to fetch select options', fetchError);\n }\n },\n [fetchMoreOptions],\n );\n\n const handleLoadMoreFromScroll = useCallback(async () => {\n if (!infiniteScroll || !hasMoreOptions || isLoadingMoreRef.current) return;\n isLoadingMoreRef.current = true;\n try {\n await requestPagedOptions({ search: currentSearchText, reset: false });\n } finally {\n isLoadingMoreRef.current = false;\n }\n }, [infiniteScroll, hasMoreOptions, requestPagedOptions, currentSearchText]);\n\n const handleServerSearch = useCallback(\n (searchText: string) => {\n setCurrentSearchText(searchText);\n if (!infiniteScroll) return;\n if (scrollableContainerRef.current) scrollableContainerRef.current.scrollTop = 0;\n void requestPagedOptions({ search: searchText, reset: true });\n },\n [infiniteScroll, requestPagedOptions],\n );\n\n // Closing with an active search would leave the consumer's list holding only the search\n // results, so the next open would show a filtered list with an empty search box. Restore\n // the unfiltered baseline as the menu closes.\n useEffect(() => {\n if (isOpen || !infiniteScroll || currentSearchText === '') return;\n setCurrentSearchText('');\n void requestPagedOptions({ search: '', reset: true });\n }, [isOpen]);\n\n const handleSelect = useCallback(\n (option: string, event: React.MouseEvent) => {\n if (disabled) return;\n\n if (multiple) {\n event.stopPropagation();\n event.preventDefault();\n\n const currentSelection = selected as Array<string>;\n if (currentSelection.includes(option)) {\n const newSelection = currentSelection.filter((item) => item !== option);\n setSelected(newSelection);\n onChangeHook(newSelection);\n } else {\n const newSelection = [...currentSelection, option];\n setSelected(newSelection);\n onChangeHook(newSelection);\n }\n } else {\n setSelected(option);\n onChangeHook(option);\n if (!infiniteScroll) {\n setCurrentSearchText('');\n setFilteredOptions(options);\n }\n setIsOpen(false);\n }\n },\n [disabled, multiple, selected, onChangeHook, options, infiniteScroll],\n );\n\n const handleClearSelection = useCallback(() => {\n if (disabled) return;\n\n if (multiple) {\n setSelected([]);\n onChangeHook([]);\n } else {\n setSelected('');\n onChangeHook('');\n }\n\n if (!infiniteScroll) {\n setCurrentSearchText('');\n setFilteredOptions(options);\n }\n\n if (onClearSearch) {\n onClearSearch();\n }\n }, [disabled, multiple, onChangeHook, onClearSearch, options, infiniteScroll]);\n\n const getDisplayLabel = useCallback(() => {\n if (multiple) {\n const selectedArray = selected as Array<string>;\n if (selectedArray.length === 0) {\n return '';\n } else if (selectedArray.length === 1) {\n const foundOption = options.find((item) => item.value === selectedArray[0]);\n\n return formatLabel(foundOption?.label || selectedArray[0]);\n } else {\n return `${selectedArray.length} itens selecionados`;\n }\n } else {\n const foundOption = options.find((item) => item.value === selected);\n\n return formatLabel(foundOption?.label || (selected as string) || label);\n }\n }, [multiple, selected, options, label, formatLabel]);\n\n const getOptionId = useCallback(\n (index: number) => `${scrollableContainerId}-option-${index}`,\n [scrollableContainerId],\n );\n\n const isOptionEnabled = useCallback(\n (index: number) => {\n const option = filteredOptions[index];\n return Boolean(option) && !option.disabled;\n },\n [filteredOptions],\n );\n\n /** Next enabled index from `start` walking by `step`, or -1. Never wraps (APG select-only). */\n const findEnabledIndex = useCallback(\n (start: number, step: 1 | -1) => {\n for (let index = start; index >= 0 && index < filteredOptions.length; index += step) {\n if (isOptionEnabled(index)) return index;\n }\n return -1;\n },\n [filteredOptions.length, isOptionEnabled],\n );\n\n const getSelectedIndex = useCallback(() => {\n const firstSelected = multiple ? (selected as Array<string>)[0] : (selected as string);\n const index = filteredOptions.findIndex((option) => option.value === firstSelected);\n return index >= 0 && isOptionEnabled(index) ? index : -1;\n }, [multiple, selected, filteredOptions, isOptionEnabled]);\n\n const focusOptionAt = useCallback((index: number) => {\n if (index < 0) return;\n setActiveIndex(index);\n pendingFocusIndexRef.current = index;\n setFocusRequest((request) => request + 1);\n }, []);\n\n const focusSearchInput = useCallback(() => {\n const searchInput = menuListRef.current?.querySelector<HTMLInputElement>(`.${SEARCH_INPUT_MARKER_CLASS}`);\n if (!searchInput) return false;\n searchInput.focus();\n return true;\n }, []);\n\n const findTypeaheadMatch = useCallback(\n (key: string, fromIndex: number) => {\n const state = typeaheadRef.current;\n window.clearTimeout(state.timer);\n state.buffer += key.toLowerCase();\n state.timer = window.setTimeout(() => {\n state.buffer = '';\n }, TYPEAHEAD_RESET_MS);\n\n // Repeating one letter cycles through the options that start with it.\n const isCycling = state.buffer.split('').every((char) => char === state.buffer[0]);\n const term = isCycling ? state.buffer[0] : state.buffer;\n const start = isCycling ? fromIndex + 1 : Math.max(fromIndex, 0);\n const total = filteredOptions.length;\n\n for (let offset = 0; offset < total; offset += 1) {\n const index = (start + offset) % total;\n const label = formatLabel(filteredOptions[index]?.label).toLowerCase();\n if (isOptionEnabled(index) && label.startsWith(term)) return index;\n }\n return -1;\n },\n [filteredOptions, formatLabel, isOptionEnabled],\n );\n\n type TOpenTarget = 'selected' | 'first' | 'last' | number;\n\n const openAndFocus = useCallback(\n (target: TOpenTarget) => {\n if (disabled) return;\n if (!isOpen) {\n setIsOpen(true);\n onOpen?.();\n }\n\n if (searchable && target === 'selected') {\n // With a search field the keyboard lands on it; ArrowDown then walks into the options.\n pendingFocusIndexRef.current = -1;\n setFocusRequest((request) => request + 1);\n return;\n }\n\n let index: number;\n if (typeof target === 'number') index = target;\n else if (target === 'first') index = findEnabledIndex(0, 1);\n else if (target === 'last') index = findEnabledIndex(filteredOptions.length - 1, -1);\n else index = getSelectedIndex() >= 0 ? getSelectedIndex() : findEnabledIndex(0, 1);\n focusOptionAt(index);\n },\n [disabled, isOpen, onOpen, searchable, findEnabledIndex, filteredOptions.length, getSelectedIndex, focusOptionAt],\n );\n\n // Moves DOM focus to the requested option once it is rendered: a virtualized row far from\n // the viewport only exists after react-window re-renders at the new scroll offset.\n useEffect(() => {\n const index = pendingFocusIndexRef.current;\n if (!isOpen || index === null) return undefined;\n\n if (index >= 0) virtualListRef.current?.scrollToItem(index);\n\n let attempts = 0;\n let frame = 0;\n const tryFocus = () => {\n if (index < 0) {\n if (focusSearchInput()) {\n pendingFocusIndexRef.current = null;\n return;\n }\n } else {\n const node = document.getElementById(getOptionId(index));\n if (node) {\n pendingFocusIndexRef.current = null;\n node.focus({ preventScroll: Boolean(virtualListRef.current) });\n if (!virtualListRef.current) node.scrollIntoView?.({ block: 'nearest' });\n return;\n }\n }\n attempts += 1;\n if (attempts < FOCUS_RETRY_FRAMES) frame = window.requestAnimationFrame(tryFocus);\n };\n\n tryFocus();\n return () => window.cancelAnimationFrame(frame);\n }, [isOpen, focusRequest]);\n\n // Closing hands focus back to the trigger when it was inside the list (a keyboard or pointer\n // selection, ESC) or was lost with it; a click elsewhere keeps the focus it moved.\n const wasOpenRef = useRef(false);\n useEffect(() => {\n if (isOpen) {\n wasOpenRef.current = true;\n return;\n }\n if (!wasOpenRef.current) return;\n wasOpenRef.current = false;\n setActiveIndex(-1);\n pendingFocusIndexRef.current = null;\n\n const active = document.activeElement;\n const focusWasInList = Boolean(active && menuListRef.current?.contains(active));\n if (focusWasInList || active === document.body || active === null) {\n triggerInputRef.current?.focus({ preventScroll: true });\n }\n }, [isOpen]);\n\n useEffect(() => {\n setActiveIndex(-1);\n }, [filteredOptions]);\n\n // A multi-select toggle re-renders the virtualized rows, which replaces the focused node:\n // put focus back on the same option so the keyboard user keeps their place.\n useEffect(() => {\n if (!isOpen || activeIndex < 0) return;\n const active = document.activeElement;\n if (active === null || active === document.body) focusOptionAt(activeIndex);\n }, [selected]);\n\n useEffect(() => () => window.clearTimeout(typeaheadRef.current.timer), []);\n\n // The list is named like its trigger, including a trigger named only by `<label htmlFor>`.\n const listboxLabel =\n triggerAttributes['aria-label'] ??\n ariaLabel ??\n label ??\n (isOpen ? triggerInputRef.current?.labels?.[0]?.textContent?.trim() || undefined : undefined);\n\n const handleTriggerKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (disabled) return;\n\n switch (event.key) {\n case 'Enter':\n case ' ':\n case 'ArrowDown':\n event.preventDefault();\n openAndFocus(isOpen && event.key === 'ArrowDown' && activeIndex >= 0 ? activeIndex : 'selected');\n return;\n case 'ArrowUp':\n event.preventDefault();\n openAndFocus(getSelectedIndex() >= 0 ? getSelectedIndex() : 'last');\n return;\n case 'Home':\n event.preventDefault();\n openAndFocus('first');\n return;\n case 'End':\n event.preventDefault();\n openAndFocus('last');\n return;\n case 'Escape':\n if (!isOpen) return;\n // Marks it handled so an enclosing dialog does not close too.\n event.preventDefault();\n setIsOpen(false);\n return;\n case 'Tab':\n if (isOpen) setIsOpen(false);\n return;\n default:\n if (!isPrintableKey(event) || searchable) return;\n event.preventDefault();\n openAndFocus(findTypeaheadMatch(event.key, getSelectedIndex()));\n }\n };\n\n const handleListKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n const target = event.target as HTMLElement;\n const isOnSearch = target.classList.contains(SEARCH_INPUT_MARKER_CLASS);\n const optionNode = target.closest<HTMLElement>('[role=\"option\"]');\n const currentIndex = optionNode ? Number(optionNode.dataset.optionIndex ?? -1) : activeIndex;\n\n switch (event.key) {\n case 'ArrowDown': {\n event.preventDefault();\n const next = isOnSearch ? findEnabledIndex(0, 1) : findEnabledIndex(currentIndex + 1, 1);\n focusOptionAt(next);\n return;\n }\n case 'ArrowUp': {\n if (isOnSearch) return;\n event.preventDefault();\n const previous = findEnabledIndex(currentIndex - 1, -1);\n if (previous >= 0) focusOptionAt(previous);\n else if (searchable) focusSearchInput();\n return;\n }\n case 'Home':\n case 'End':\n if (isOnSearch) return;\n event.preventDefault();\n focusOptionAt(event.key === 'Home' ? findEnabledIndex(0, 1) : findEnabledIndex(filteredOptions.length - 1, -1));\n return;\n case 'Escape':\n event.preventDefault();\n setIsOpen(false);\n return;\n case 'Tab':\n event.preventDefault();\n setIsOpen(false);\n triggerInputRef.current?.focus({ preventScroll: true });\n return;\n default:\n if (isOnSearch || !isPrintableKey(event) || event.key === ' ') return;\n event.preventDefault();\n focusOptionAt(findTypeaheadMatch(event.key, currentIndex));\n }\n };\n\n const renderOptionItem = useCallback(\n (option: IFilterOption, index: number, style?: React.CSSProperties) => {\n const isSelected = multiple\n ? Array.isArray(selected) && selected.includes(option.value)\n : option.value === selected;\n\n // A disabled option explains itself on hover over the WHOLE row, not just the info icon.\n const isDisabledWithReason = Boolean(option.disabled && option.tooltip);\n\n const menuItem = (\n <ControlledMenuItem\n key={isDisabledWithReason ? undefined : option.value}\n disabled={option.disabled}\n onClick={(event: React.MouseEvent) => handleSelect(option.value, event)}\n role=\"option\"\n id={getOptionId(index)}\n tabIndex={-1}\n aria-selected={isSelected}\n aria-setsize={filteredOptions.length}\n aria-posinset={index + 1}\n data-option-index={index}\n className={classNames(\n 'relative flex items-center p-2 pl-3 text-foreground',\n 'focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring',\n {\n // The hover variant has to live inside the selected branch: the menu item's own\n // default hover would otherwise wipe the selected tint.\n 'bg-brand-soft font-medium text-brand-emphasis hover:!bg-brand-soft focus:!bg-brand-soft': isSelected,\n 'hover:!bg-muted': !isSelected,\n },\n )}\n style={{\n ...(isDisabledWithReason ? {} : style),\n height: ITEM_HEIGHT - 1,\n }}\n >\n {isSelected && <span className=\"absolute inset-y-1 left-0 w-0.5 rounded-full bg-brand\" />}\n {multiple && (\n // The option itself carries aria-selected; the checkbox is only its picture.\n <span aria-hidden className=\"pointer-events-none\">\n <ControlledCheckbox checked={isSelected} onChange={() => {}} />\n </span>\n )}\n {option.tooltip && !isDisabledWithReason && (\n <ControlledTooltip content={option.tooltip} className=\"w-full max-w-72\">\n <MaterialSymbol icon=\"info\" size={15} color=\"rgb(var(--color-foreground-subtle))\" className=\"mr-1\" />\n </ControlledTooltip>\n )}\n {option.swatch && (\n <span\n className={classNames(\n 'mr-2 size-3.5 shrink-0 border border-border',\n swatchShape === 'square' ? 'rounded' : 'rounded-full',\n )}\n style={{ backgroundColor: option.swatch }}\n />\n )}\n <span className=\"truncate text-sm\">{formatLabel(option.label)}</span>\n {option.secondaryLabel && option.emphasizeSecondaryLabel && (\n <OutlinedChip\n label={option.secondaryLabel}\n tone=\"purple\"\n variant=\"soft\"\n size=\"xs\"\n preserveLabelCase\n truncate\n className=\"ml-auto max-w-[45%] shrink-0\"\n />\n )}\n {option.secondaryLabel && !option.emphasizeSecondaryLabel && (\n <span className=\"ml-auto max-w-[45%] shrink-0 truncate pl-3 text-xs text-foreground-faint\">\n {option.secondaryLabel}\n </span>\n )}\n </ControlledMenuItem>\n );\n\n // The wrapper div carries the virtualized position because the tooltip clones its child and\n // injects its own ref.\n return isDisabledWithReason ? (\n <ControlledTooltip key={option.value} content={option.tooltip} className=\"z-[9999] max-w-72\">\n <div style={style}>{menuItem}</div>\n </ControlledTooltip>\n ) : (\n menuItem\n );\n },\n [multiple, selected, handleSelect, formatLabel, getOptionId, filteredOptions.length],\n );\n\n const ItemRenderer = useCallback(\n ({ index, style }: { index: number; style: React.CSSProperties }) => {\n const option = filteredOptions[index];\n if (!option) return null;\n\n return renderOptionItem(option, index, style);\n },\n [filteredOptions, renderOptionItem],\n );\n\n const listHeight = useMemo(\n () => Math.min(filteredOptions.length * ITEM_HEIGHT, MAX_LIST_HEIGHT),\n [filteredOptions.length],\n );\n\n const selectedSwatch = useMemo(\n () => (multiple ? undefined : options.find((option) => option.value === selected)?.swatch),\n [multiple, options, selected],\n );\n\n // Com uma opção selecionada, o próprio valor identifica o campo: a label flutuante\n // some (evita duplicar quando já há um rótulo externo acima do select).\n const selectedHasValue = multiple ? (selected as Array<string>).length > 0 : selected !== '';\n\n /**\n * Opção declarada com valor vazio (\"Todas\", \"Nenhum\", \"Sem recorte\"): é uma\n * escolha de verdade, não a ausência de escolha, então o campo precisa exibir\n * o rótulo dela em vez de ficar em branco.\n */\n const hasEmptyValueOption = useMemo(\n () => !multiple && options.some((option) => option.value === ''),\n [multiple, options],\n );\n\n // The dropdown is portaled, so a percentage width would resolve against the\n // page, and a runtime pixel value cannot become a Tailwind arbitrary class.\n // The measured width is written straight onto the node: the floating logic\n // overwrites the MenuList `style` prop with its own position, and React never\n // clears `width` because it is not part of that style object.\n // It runs as a layout effect because the panel also carries a fallback width class:\n // measuring after paint would show that width for one frame, mid enter animation.\n useLayoutEffect(() => {\n const menuList = menuListRef.current;\n const trigger = triggerRef.current;\n if (!matchTriggerWidth || !isOpen || !menuList || !trigger) return undefined;\n\n const applyTriggerWidth = () => {\n menuList.style.width = `${trigger.getBoundingClientRect().width}px`;\n };\n\n applyTriggerWidth();\n\n const resizeObserver = new ResizeObserver(applyTriggerWidth);\n resizeObserver.observe(trigger);\n\n return () => resizeObserver.disconnect();\n }, [matchTriggerWidth, isOpen]);\n\n // Moving the pointer inside the menu makes floating-ui's list navigation pull\n // focus off the search field (it focuses the hovered option, or the menu\n // container on pointer leave). Take focus back whenever the pointer caused it,\n // while leaving keyboard navigation into the options alone.\n useEffect(() => {\n const menuList = menuListRef.current;\n if (!isOpen || !searchable || !menuList) return undefined;\n\n let isKeyboardInteraction = false;\n let restoreFrame = 0;\n\n const markKeyboardInteraction = () => {\n isKeyboardInteraction = true;\n };\n\n const markPointerInteraction = () => {\n isKeyboardInteraction = false;\n };\n\n const restoreSearchFocus = (event: FocusEvent) => {\n const searchInput = menuList.querySelector<HTMLInputElement>(`.${SEARCH_INPUT_MARKER_CLASS}`);\n if (!searchInput || event.target !== searchInput || isKeyboardInteraction) return;\n\n const nextFocused = event.relatedTarget as Node | null;\n if (nextFocused && !menuList.contains(nextFocused)) return;\n\n // The steal happens as this event is dispatched, so reclaim on the next frame.\n restoreFrame = window.requestAnimationFrame(() => searchInput.focus({ preventScroll: true }));\n };\n\n menuList.addEventListener('keydown', markKeyboardInteraction, true);\n menuList.addEventListener('pointermove', markPointerInteraction, true);\n menuList.addEventListener('focusout', restoreSearchFocus);\n\n return () => {\n window.cancelAnimationFrame(restoreFrame);\n menuList.removeEventListener('keydown', markKeyboardInteraction, true);\n menuList.removeEventListener('pointermove', markPointerInteraction, true);\n menuList.removeEventListener('focusout', restoreSearchFocus);\n };\n }, [isOpen, searchable]);\n\n const handleClearSearch = useCallback(() => {\n setCurrentSearchText('');\n\n if (infiniteScroll) {\n if (scrollableContainerRef.current) scrollableContainerRef.current.scrollTop = 0;\n void requestPagedOptions({ search: '', reset: true });\n } else {\n setFilteredOptions(options);\n }\n\n if (onClearSearch) {\n onClearSearch();\n }\n }, [infiniteScroll, requestPagedOptions, onClearSearch, options]);\n\n const getSelectedOptionsLabels = useCallback(() => {\n if (!multiple || !selected || (selected as Array<string>).length === 0) {\n return [];\n }\n\n const selectedArray = selected as Array<string>;\n\n return selectedArray.map((value) => {\n const trimmedValue = value.trim();\n const foundOption = options.find((option) => option.value === trimmedValue);\n return {\n value: trimmedValue,\n label: foundOption?.label || trimmedValue,\n swatch: foundOption?.swatch,\n };\n });\n }, [multiple, selected, options]);\n\n const isLateralPosition = selectedItemsPosition === 'left' || selectedItemsPosition === 'right';\n\n const inFieldChipItems = inFieldChips ? getSelectedOptionsLabels() : [];\n const showInFieldChips = inFieldChips && multiple && inFieldChipItems.length > 0;\n const visibleInFieldChips = inFieldChipItems.slice(0, MAX_IN_FIELD_CHIPS);\n const inFieldOverflow = inFieldChipItems.length - visibleInFieldChips.length;\n const inFieldChipsTooltip = inFieldChipItems.map((option) => formatLabel(option.label)).join(', ');\n\n const selectedItemsChips = showSelectedItems && multiple && getSelectedOptionsLabels().length > 1 && (\n <div className=\"flex flex-wrap gap-1\">\n {getSelectedOptionsLabels().map((option) => (\n <OutlinedChip\n key={option.value}\n label={option.label}\n preserveLabelCase={preserveLabelCase}\n dot={Boolean(option.swatch)}\n dotColor={option.swatch}\n className={classNames('bg-muted-active text-lg', { 'px-4 py-1': isLateralPosition })}\n labelClassName={isLateralPosition ? 'text-sm' : undefined}\n onClose={(event: React.MouseEvent) => handleSelect(option.value, event)}\n canClose={!disabled}\n />\n ))}\n </div>\n );\n\n const showClear =\n clearable &&\n !disabled &&\n Boolean(selected) &&\n (multiple ? (selected as Array<string>).length > 0 : selected !== '');\n\n const cursorClassName = disabled ? 'cursor-not-allowed' : 'cursor-pointer';\n\n return (\n <ControlledMenuRoot\n placement=\"bottom-start\"\n open={isOpen && !disabled}\n handler={(next) => {\n if (disabled) return;\n setIsOpen(next);\n if (next) onOpen?.();\n }}\n dismiss={{ itemPress: !multiple }}\n >\n <ControlledMenuHandler skipTriggerAria>\n <div\n className={classNames('flex', {\n 'flex-col gap-y-2': selectedItemsPosition === 'bottom' || selectedItemsPosition === 'top',\n 'flex-row items-start gap-x-2': selectedItemsPosition === 'left' || selectedItemsPosition === 'right',\n })}\n >\n {(selectedItemsPosition === 'top' || selectedItemsPosition === 'left') && selectedItemsChips}\n <div ref={triggerRef} className={classNames('relative', cursorClassName, className)}>\n {selectedSwatch && (\n <span\n className={classNames(\n 'pointer-events-none absolute left-3 top-1/2 z-10 size-3.5 -translate-y-1/2 border border-border',\n swatchShape === 'square' ? 'rounded' : 'rounded-full',\n )}\n style={{ backgroundColor: selectedSwatch }}\n />\n )}\n {showInFieldChips && (\n <ControlledTooltip content={inFieldChipsTooltip} className=\"max-w-72\">\n <div\n className={classNames(\n 'absolute inset-y-0 left-2.5 right-14 z-10 flex items-center gap-1 overflow-hidden',\n cursorClassName,\n )}\n >\n {visibleInFieldChips.map((option) => (\n <OutlinedChip\n key={option.value}\n label={option.label}\n preserveLabelCase={preserveLabelCase}\n dot={Boolean(option.swatch)}\n dotColor={option.swatch}\n className=\"min-w-0 shrink-0 bg-muted-active\"\n labelClassName=\"text-xxs\"\n />\n ))}\n {inFieldOverflow > 0 && (\n <OutlinedChip\n label={t('controlledSelect.moreItems', { count: inFieldOverflow })}\n className=\"min-w-0 shrink-0 bg-muted-active\"\n labelClassName=\"text-xxs\"\n />\n )}\n </div>\n </ControlledTooltip>\n )}\n <ControlledInput\n {...triggerAttributes}\n id={id}\n inputRef={triggerInputRef}\n onBlur={onBlur}\n onFocus={onFocus}\n autoFocus={autoFocus}\n readOnly\n role=\"combobox\"\n // eslint-disable-next-line i18n-check/no-literal-jsx-strings -- ARIA token, not user-facing text\n aria-haspopup=\"listbox\"\n aria-expanded={isOpen}\n aria-controls={isOpen ? scrollableContainerId : undefined}\n onKeyDown={handleTriggerKeyDown}\n className={classNames(\n 'controlled-select-input flex w-full min-w-0 justify-between truncate text-left',\n !compact && 'tablet:min-w-52',\n cursorClassName,\n selectedSwatch && '!pl-9',\n // O \"x\" é absoluto SOBRE o input: sem esta reserva o rótulo passa por baixo dele.\n showClear && '!pr-14',\n inputClassName,\n )}\n error={error}\n autoComplete=\"off\"\n rightSlot={<MaterialSymbol className={cursorClassName} icon=\"keyboard_arrow_down\" size={15} />}\n label={selectedHasValue && !persistentLabel ? undefined : label}\n aria-label={triggerAttributes['aria-label'] ?? ariaLabel ?? label}\n aria-required={ariaRequired || required ? true : triggerAttributes['aria-required']}\n value={showInFieldChips ? ' ' : selectedHasValue || hasEmptyValueOption ? getDisplayLabel() : ''}\n disabled={disabled}\n />\n\n {showClear && (\n <ControlledTooltip content={t('dates.clearSelection')}>\n <div\n onClick={handleClearSelection}\n className=\"absolute inset-y-0 right-8 top-0.5 flex cursor-pointer items-center\"\n >\n <MaterialSymbol icon=\"close_small\" size={20} color=\"rgb(var(--color-foreground-subtle))\" />\n </div>\n </ControlledTooltip>\n )}\n </div>\n\n {name &&\n (multiple\n ? (selected as Array<string>).map((value) => (\n <input key={value} type=\"hidden\" name={name} value={value} disabled={disabled} />\n ))\n : selected !== '' && <input type=\"hidden\" name={name} value={selected as string} disabled={disabled} />)}\n\n {(selectedItemsPosition === 'bottom' || selectedItemsPosition === 'right') && selectedItemsChips}\n </div>\n </ControlledMenuHandler>\n\n <ControlledMenuList\n ref={menuListRef}\n role=\"presentation\"\n onKeyDown={handleListKeyDown}\n className={classNames(\n 'zIndexMax overflow-hidden',\n FALLBACK_LIST_WIDTH_CLASS,\n MIN_LIST_WIDTH_CLASS,\n listClassName,\n )}\n >\n {searchable && (\n <SelectSearchSlot>\n <UnifiedSearchBar\n mode=\"default\"\n label={t('actions.search')}\n debounceTime={SEARCH_DEBOUNCE_MS}\n // Em modo infinito quem filtra é o servidor: sem itens, a barra só reporta o\n // termo via onSearchTermChange e nunca escreve na lista local.\n searchableItems={infiniteScroll ? null : options}\n searchKeys={['label', 'secondaryLabel']}\n setFilteredItems={setFilteredOptions}\n onSearchTermChange={handleServerSearch}\n className={classNames('w-full', SEARCH_INPUT_MARKER_CLASS)}\n onClearFilter={handleClearSearch}\n initialValue={currentSearchText}\n />\n </SelectSearchSlot>\n )}\n\n <div\n ref={scrollableContainerRef}\n className={classNames({\n 'max-h-[250px] overflow-y-auto overscroll-contain': infiniteScroll,\n 'overflow-hidden': !infiniteScroll,\n })}\n id={scrollableContainerId}\n role=\"listbox\"\n aria-multiselectable={multiple || undefined}\n aria-labelledby={triggerAttributes['aria-labelledby']}\n aria-label={triggerAttributes['aria-labelledby'] ? undefined : listboxLabel}\n >\n {infiniteScroll ? (\n <InfiniteScroll\n dataLength={filteredOptions.length}\n // O loader do InfiniteScroll é renderizado sempre que `hasMore` é verdadeiro, ao lado\n // do conteúdo. Com a lista vazia isso empilhava o spinner sobre o estado vazio (ou\n // sobre o próprio spinner de `loading`): sem opções, quem manda é o bloco abaixo.\n hasMore={hasMoreOptions && filteredOptions.length > 0}\n next={handleLoadMoreFromScroll}\n loader={\n <div className=\"flex size-full items-center justify-center py-1\">\n <LoadingSpinner size={4} label={t('controlledSelect.loadingOptions')} />\n </div>\n }\n scrollableTarget={scrollableContainerId}\n // `overflow-hidden` makes this a scroll port the user cannot scroll, so\n // `overscroll-none` here stopped the wheel from ever reaching the container\n // that does scroll: the list only moved by dragging its bar. Containment\n // belongs to that container, which already declares `overscroll-contain`.\n className=\"!overflow-hidden\"\n >\n {filteredOptions.length > 0 ? (\n filteredOptions.map((option, index) => renderOptionItem(option, index))\n ) : loading ? (\n <div className=\"flex w-full items-center justify-center py-4\">\n <LoadingSpinner size={4} label={t('controlledSelect.loadingOptions')} />\n </div>\n ) : (\n <ControlledMenuItem disabled role=\"presentation\">\n <NoDataFound compact message={t('controlledSelect.noDataToShow')} />\n </ControlledMenuItem>\n )}\n </InfiniteScroll>\n ) : filteredOptions.length > 0 ? (\n <List\n ref={virtualListRef}\n className=\"virtualized-select-list\"\n height={listHeight}\n // eslint-disable-next-line i18n-check/no-literal-jsx-strings\n width=\"100%\"\n itemCount={filteredOptions.length}\n itemSize={ITEM_HEIGHT}\n overscanCount={OVERSCAN_COUNT}\n >\n {ItemRenderer}\n </List>\n ) : loading ? (\n <div className=\"flex w-full items-center justify-center py-4\">\n <LoadingSpinner size={4} label={t('controlledSelect.loadingOptions')} />\n </div>\n ) : (\n <ControlledMenuItem disabled role=\"presentation\">\n <NoDataFound compact message={t('controlledSelect.noDataToShow')} />\n </ControlledMenuItem>\n )}\n </div>\n </ControlledMenuList>\n </ControlledMenuRoot>\n );\n}\n"],"names":["label","List"],"mappings":"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"}
|
|
@@ -216,73 +216,6 @@ declare const _default: {
|
|
|
216
216
|
"keepEditing": "Keep editing",
|
|
217
217
|
"discard": "Discard"
|
|
218
218
|
},
|
|
219
|
-
"flow": {
|
|
220
|
-
"canvas": "Flow editor",
|
|
221
|
-
"resizePanel": "Drag to adjust the width. Double click resets",
|
|
222
|
-
"ports": {
|
|
223
|
-
"next": "Next",
|
|
224
|
-
"true": "Yes",
|
|
225
|
-
"false": "No",
|
|
226
|
-
"error": "Error"
|
|
227
|
-
},
|
|
228
|
-
"categories": {
|
|
229
|
-
"trigger": "Triggers",
|
|
230
|
-
"condition": "Conditions",
|
|
231
|
-
"action": "Actions"
|
|
232
|
-
},
|
|
233
|
-
"palette": {
|
|
234
|
-
"title": "Blocks",
|
|
235
|
-
"search": "Search block",
|
|
236
|
-
"empty": "No block found",
|
|
237
|
-
"limitReached": "This flow already has the maximum of this block"
|
|
238
|
-
},
|
|
239
|
-
"inspector": {
|
|
240
|
-
"title": "Block settings",
|
|
241
|
-
"empty": "Select a block to configure it",
|
|
242
|
-
"label": "Block name",
|
|
243
|
-
"delete": "Delete block",
|
|
244
|
-
"duplicate": "Duplicate block",
|
|
245
|
-
"unknownBlock": "This block type no longer exists",
|
|
246
|
-
"close": "Close"
|
|
247
|
-
},
|
|
248
|
-
"issues": {
|
|
249
|
-
"title": "Issues",
|
|
250
|
-
"none": "No issues",
|
|
251
|
-
"missingTrigger": "The flow needs a trigger",
|
|
252
|
-
"multipleTriggers": "A flow can have only one trigger",
|
|
253
|
-
"unknownBlock": "Block of a type that no longer exists",
|
|
254
|
-
"unreachableNode": "Loose block: no path from the trigger reaches it",
|
|
255
|
-
"multipleInputs": "Block with more than one input",
|
|
256
|
-
"portFanOut": "An output can connect to one block only",
|
|
257
|
-
"cycle": "The blocks form a cycle",
|
|
258
|
-
"missingTrueBranch": "The condition has no yes path"
|
|
259
|
-
},
|
|
260
|
-
"run": {
|
|
261
|
-
"passed": "Passed",
|
|
262
|
-
"failed": "Did not pass",
|
|
263
|
-
"skipped": "Skipped",
|
|
264
|
-
"wouldRun": "Would run",
|
|
265
|
-
"error": "Error",
|
|
266
|
-
"blocked": "Blocked"
|
|
267
|
-
},
|
|
268
|
-
"controls": {
|
|
269
|
-
"zoomIn": "Zoom in",
|
|
270
|
-
"zoomOut": "Zoom out",
|
|
271
|
-
"fitView": "Fit view",
|
|
272
|
-
"undo": "Undo",
|
|
273
|
-
"redo": "Redo",
|
|
274
|
-
"layout": "Arrange blocks"
|
|
275
|
-
},
|
|
276
|
-
"node": {
|
|
277
|
-
"disabled": "Disabled",
|
|
278
|
-
"addBlock": "Add the next block",
|
|
279
|
-
"issueCount_one": "{{count}} issue",
|
|
280
|
-
"issueCount_other": "{{count}} issues"
|
|
281
|
-
},
|
|
282
|
-
"laneMap": {
|
|
283
|
-
"label": "Flow map"
|
|
284
|
-
}
|
|
285
|
-
},
|
|
286
219
|
"followUp": {
|
|
287
220
|
"messages": "Messages",
|
|
288
221
|
"chat": {
|
|
@@ -12,7 +12,6 @@ const detailsTable = { "size": "Size", "quantity": "Qty" };
|
|
|
12
12
|
const errorPage = { "message": "This screen could not load", "headline": "Something unexpected happened while building the page. Refreshing usually fixes it. If it happens again, contact support and tell them what you were doing.", "backToStart": "Back to start" };
|
|
13
13
|
const filters = { "activeFilters": "Applied filters", "appliedCount_one": "{{count}} filter applied", "appliedCount_other": "{{count}} filters applied", "clearAll": "Clear all", "noFields": "No filters available for this list.", "noOptions": "No options found.", "optionsError": "Could not load the options for {{field}}.", "rangeMax": "Maximum", "rangeMin": "Minimum", "rangeSeparator": "to", "searchOptions": "Search options" };
|
|
14
14
|
const filtersDrawer = { "selectedFilters": "Selected filters:", "pendingChanges": "Pending changes", "discardChangesTitle": "Discard changes?", "discardChangesMessage": "You have unapplied filter changes. Discard them?", "keepEditing": "Keep editing", "discard": "Discard" };
|
|
15
|
-
const flow = { "canvas": "Flow editor", "resizePanel": "Drag to adjust the width. Double click resets", "ports": { "next": "Next", "true": "Yes", "false": "No", "error": "Error" }, "categories": { "trigger": "Triggers", "condition": "Conditions", "action": "Actions" }, "palette": { "title": "Blocks", "search": "Search block", "empty": "No block found", "limitReached": "This flow already has the maximum of this block" }, "inspector": { "title": "Block settings", "empty": "Select a block to configure it", "label": "Block name", "delete": "Delete block", "duplicate": "Duplicate block", "unknownBlock": "This block type no longer exists", "close": "Close" }, "issues": { "title": "Issues", "none": "No issues", "missingTrigger": "The flow needs a trigger", "multipleTriggers": "A flow can have only one trigger", "unknownBlock": "Block of a type that no longer exists", "unreachableNode": "Loose block: no path from the trigger reaches it", "multipleInputs": "Block with more than one input", "portFanOut": "An output can connect to one block only", "cycle": "The blocks form a cycle", "missingTrueBranch": "The condition has no yes path" }, "run": { "passed": "Passed", "failed": "Did not pass", "skipped": "Skipped", "wouldRun": "Would run", "error": "Error", "blocked": "Blocked" }, "controls": { "zoomIn": "Zoom in", "zoomOut": "Zoom out", "fitView": "Fit view", "undo": "Undo", "redo": "Redo", "layout": "Arrange blocks" }, "node": { "disabled": "Disabled", "addBlock": "Add the next block", "issueCount_one": "{{count}} issue", "issueCount_other": "{{count}} issues" }, "laneMap": { "label": "Flow map" } };
|
|
16
15
|
const followUp = { "messages": "Messages", "chat": { "loadingMessages": "Loading messages", "placeholder": "Write a message...", "invalidMessage": "Please enter a valid message", "noMessagesYet": "No messages yet", "startConversation": "Start a conversation by adding the first message", "loadError": "Messages could not be loaded", "sendFailed": "The message could not be sent. Try again.", "sendFailedInline": "Failed to send", "resend": "Resend", "discard": "Discard", "today": "Today", "yesterday": "Yesterday", "typingOne": "{{name}} is typing...", "typingMany": "{{count}} people are typing...", "someone": "Someone", "you": "You", "newMessages": "New messages", "backToLatest": "Back to latest", "deletedMessage": "Message deleted", "edited": "edited", "readBy": "Read by {{names}}", "copied": "Message copied", "replyingTo": "Replying to {{name}}", "attachmentFallback": "Attachment", "editTitle": "Edit message", "deleteTitle": "Delete message?", "deleteSubtitle": "The message will be shown as deleted for every participant", "sendHint": "Enter sends, Shift+Enter adds a line break", "formatting": "Formatting" }, "actions": { "reply": "Reply", "copy": "Copy text", "edit": "Edit", "delete": "Delete" }, "attachments": { "attach": "Attach", "pickFile": "File", "pickImage": "Image", "takePhoto": "Take photo", "dropHere": "Drop files to attach", "tooMany": "Limit of {{max}} attachments per message", "tooLarge": "The file {{name}} exceeds the 50 MB limit", "uploadFailed": "Upload failed", "uploading": "Uploading attachments...", "imagePreview": "Preview image", "showTranscript": "Show transcript", "hideTranscript": "Hide transcript" }, "voice": { "record": "Record audio", "recording": "Recording", "stop": "Finish recording", "cancel": "Cancel recording", "rerecord": "Record again", "attach": "Add to message", "discard": "Discard", "transcriptLabel": "Transcript", "transcriptPlaceholder": "The speech transcript appears here and can be edited" }, "camera": { "title": "Take photo", "unavailable": "Camera unavailable", "unavailableHint": "Check the browser camera permission", "switch": "Switch camera", "capture": "Capture photo" }, "search": { "open": "Search in conversation", "placeholder": "Search messages", "noResults": "No messages found", "error": "Messages could not be searched" } };
|
|
17
16
|
const generatedByAI = { "tooltip": "Generated by AI" };
|
|
18
17
|
const imageAiAdjust = { "action": "Adjust with AI", "title": "Adjust image with AI", "subtitle": "Describe the adjustment. The AI changes only what you ask and preserves the rest of the image.", "original": "Original", "result": "Result", "resultHint": "Describe the adjustment and click Generate to see the result here.", "promptLabel": "Desired adjustment", "promptPlaceholder": "E.g. remove the background and make it white, smooth the sleeve creases, brighten the lighting", "generate": "Generate", "generating": "Generating the image...", "tryAgain": "Generate another", "useResult": "Use this image", "errorGenerate": "Could not adjust the image with AI", "errorSave": "Could not save the adjusted image", "errorRefused": "The AI could not make this adjustment: {{reason}}", "mask": { "start": "Mark the area", "stop": "Use the whole image", "hint": "Paint the area the AI may change. The rest of the image is kept." }, "verification": { "changedMoreThanRequested": "The AI changed more than requested. Check the areas outside the adjustment before using it.", "colorMismatch": "The garment color ({{dominant}}) differs from the requested color ({{target}})." } };
|
|
@@ -51,7 +50,6 @@ const en = {
|
|
|
51
50
|
errorPage,
|
|
52
51
|
filters,
|
|
53
52
|
filtersDrawer,
|
|
54
|
-
flow,
|
|
55
53
|
followUp,
|
|
56
54
|
generatedByAI,
|
|
57
55
|
imageAiAdjust,
|
|
@@ -92,7 +90,6 @@ export {
|
|
|
92
90
|
errorPage,
|
|
93
91
|
filters,
|
|
94
92
|
filtersDrawer,
|
|
95
|
-
flow,
|
|
96
93
|
followUp,
|
|
97
94
|
generatedByAI,
|
|
98
95
|
imageAiAdjust,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ui.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|