react-aria 3.52.0 → 3.52.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.
@@ -1,9 +1,11 @@
1
1
  var $74b2c5b1e7ea9589$exports = require("../live-announcer/LiveAnnouncer.cjs");
2
2
  var $da02ee888921bc9e$exports = require("../utils/shadowdom/DOMFunctions.cjs");
3
+ var $d0df89f3abe2c2ca$exports = require("../interactions/useFocusVisible.cjs");
3
4
  var $49582955cc364b1c$exports = require("../utils/domHelpers.cjs");
5
+ var $e2a63525475bbd9f$exports = require("../utils/getScrollParents.cjs");
4
6
  var $d0b4a781cf26e80b$exports = require("../utils/platform.cjs");
5
7
  var $89b39774f3b79dbb$exports = require("../utils/mergeProps.cjs");
6
- var $d0df89f3abe2c2ca$exports = require("../interactions/useFocusVisible.cjs");
8
+ var $9a1324d6ffd8bbb0$exports = require("../utils/scrollIntoView.cjs");
7
9
  var $6e76e65001bbcda2$exports = require("../utils/useEvent.cjs");
8
10
  var $e3486d9c44549186$exports = require("../label/useField.cjs");
9
11
  var $cfe896014413cb8c$exports = require("../interactions/useFocusable.cjs");
@@ -46,6 +48,8 @@ $parcel$export(module.exports, "tokenFieldPositionToDOMRange", function () { ret
46
48
 
47
49
 
48
50
 
51
+
52
+
49
53
  const $a3a7b013e6c801ed$var$CLIPBOARD_MIME_TYPE = 'application/vnd.react-aria.tokens+json';
50
54
  function $a3a7b013e6c801ed$export$adf3c8de3c7afc8b(props, state, ref) {
51
55
  let { role: role = 'textbox', allowsNewlines: multiline = false, isReadOnly: isReadOnly = false, isDisabled: isDisabled = false, 'aria-details': ariaDetails } = props;
@@ -118,6 +122,9 @@ function $a3a7b013e6c801ed$export$adf3c8de3c7afc8b(props, state, ref) {
118
122
  if (ref.current === (0, $da02ee888921bc9e$exports.getActiveElement)((0, $49582955cc364b1c$exports.getOwnerDocument)(ref.current))) {
119
123
  $a3a7b013e6c801ed$export$9cafaa09e78b6e4b(ref.current, value.selectedRange);
120
124
  $a3a7b013e6c801ed$var$announceToken(value);
125
+ // We call preventDefault in the beforeinput handler below, which also prevents the
126
+ // browser's default behavior of scrolling the caret into view. Do it ourselves instead.
127
+ $a3a7b013e6c801ed$var$scrollCaretIntoView(ref.current);
121
128
  }
122
129
  selectedRange.current = value.selectedRange;
123
130
  }
@@ -267,7 +274,7 @@ function $a3a7b013e6c801ed$export$adf3c8de3c7afc8b(props, state, ref) {
267
274
  (0, $6e76e65001bbcda2$exports.useEvent)(ref, 'blur', (e)=>{
268
275
  if (!e.isTrusted) return;
269
276
  let selection = window.getSelection();
270
- if (ref.current && selection && selection.containsNode(ref.current, true)) {
277
+ if (ref.current && selection && selection.containsNode(ref.current, true) && !selection.isCollapsed) {
271
278
  selection.removeAllRanges();
272
279
  state.setValue((value)=>value.withSelectedRange(new (0, $bmmaU$reactstatelyuseTokenFieldState.TokenFieldValue).SelectedRange(value.caretPosition)));
273
280
  }
@@ -506,6 +513,52 @@ function $a3a7b013e6c801ed$export$9cafaa09e78b6e4b(root, selectedRange, fireEven
506
513
  if (selection.anchorNode !== anchorNode || selection.anchorOffset !== anchorOffset || selection.focusNode !== focusNode || selection.focusOffset !== focusOffset) selection.setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset);
507
514
  }
508
515
  }
516
+ // Calling preventDefault in the beforeinput handler stops the browser from performing its
517
+ // default edit action, which also suppresses its normal behavior of scrolling the caret into
518
+ // view. Recreate that behavior by measuring the caret's position with a Range and
519
+ // scrolling each scrollable ancestor of the field so it is visible.
520
+ function $a3a7b013e6c801ed$var$scrollCaretIntoView(root) {
521
+ let selection = window.getSelection();
522
+ if ((0, $d0df89f3abe2c2ca$exports.getInteractionModality)() !== 'keyboard' || !selection || selection.rangeCount === 0 || !(0, $da02ee888921bc9e$exports.nodeContains)(root, selection.focusNode)) return;
523
+ let range = selection.getRangeAt(0);
524
+ let rect = range.getBoundingClientRect();
525
+ // A collapsed range doesn't always produce a client rect. This happens for empty lines.
526
+ if (rect.top === 0 && rect.bottom === 0 && rect.left === 0 && rect.right === 0) {
527
+ let node = range.endContainer;
528
+ if (node.nodeType === Node.TEXT_NODE && range.endOffset < node.nodeValue.length) {
529
+ // If we are not at the end of the text node, extend the range to include the next character.
530
+ range = range.cloneRange();
531
+ range.setEnd(node, range.endOffset + 1);
532
+ rect = range.getBoundingClientRect();
533
+ } else if (root.firstChild == null) // If the root has no children, use its rect.
534
+ rect = root.getBoundingClientRect();
535
+ else {
536
+ // Otherwise find the next sibling element (e.g. trailing <br>) and use its rect in this case.
537
+ let nextSibling = node.nextSibling;
538
+ while(node && node !== root && !nextSibling){
539
+ node = node.parentNode;
540
+ nextSibling = node ? node.nextSibling : null;
541
+ }
542
+ if (nextSibling?.nodeType === Node.ELEMENT_NODE) rect = nextSibling.getBoundingClientRect();
543
+ }
544
+ }
545
+ for (let element of (0, $e2a63525475bbd9f$exports.getScrollParents)(root, true)){
546
+ // scrollRectIntoView only scrolls a single scroll parent based on `rect`, which is a
547
+ // snapshot of the caret's position before any scrolling occurs. Scrolling an inner ancestor
548
+ // moves the caret within the viewport, so translate `rect` by however much we just scrolled
549
+ // before moving on to the next (outer) ancestor.
550
+ let scrollParent = element;
551
+ let beforeTop = scrollParent.scrollTop;
552
+ let beforeLeft = scrollParent.scrollLeft;
553
+ (0, $9a1324d6ffd8bbb0$exports.scrollRectIntoView)(scrollParent, root, rect, {
554
+ block: 'nearest',
555
+ inline: 'nearest'
556
+ });
557
+ let dy = scrollParent.scrollTop - beforeTop;
558
+ let dx = scrollParent.scrollLeft - beforeLeft;
559
+ if (dy !== 0 || dx !== 0) rect = new DOMRect(rect.x - dx, rect.y - dy, rect.width, rect.height);
560
+ }
561
+ }
509
562
  function $a3a7b013e6c801ed$export$30729a8cd0694a7c(root, pos) {
510
563
  // Unlike createDOMRange (used for caret/selection placement), this range is only
511
564
  // measured via getBoundingClientRect to position things like an autocomplete popover.
@@ -1 +1 @@
1
- {"mappings":"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","sources":["packages/react-aria/src/tokenfield/useTokenField.ts"],"sourcesContent":["/*\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing\n */\n\nimport {announce} from '../live-announcer/LiveAnnouncer';\nimport {AriaLabelingProps, DOMAttributes, FocusableProps} from '@react-types/shared';\nimport {\n ClipboardEventHandler,\n HTMLAttributes,\n RefObject,\n useCallback,\n useMemo,\n useRef\n} from 'react';\nimport {getActiveElement, nodeContains} from '../utils/shadowdom/DOMFunctions';\nimport {getOwnerDocument} from '../utils/domHelpers';\nimport {isMac} from '../utils/platform';\nimport {mergeProps} from '../utils/mergeProps';\nimport {\n Position,\n SelectedRange,\n TokenFieldProps,\n TokenFieldSegment,\n TokenFieldState,\n TokenFieldValue\n} from 'react-stately/useTokenFieldState';\nimport {setInteractionModality} from '../interactions/useFocusVisible';\nimport {useEvent} from '../utils/useEvent';\nimport {useField} from '../label/useField';\nimport {useFocusable} from '../interactions/useFocusable';\nimport {useKeyboard} from '../interactions/useKeyboard';\nimport {useLayoutEffect} from '../utils/useLayoutEffect';\nimport {useLocale} from '../i18n/I18nProvider';\n\nexport interface AriaTokenFieldProps<T extends TokenFieldValue = TokenFieldValue>\n extends TokenFieldProps<T>, FocusableProps, AriaLabelingProps {\n /**\n * The accessibility role of the token field.\n *\n * @default 'textbox'\n */\n role?: 'textbox' | 'searchbox' | 'combobox';\n /** Whether the token field allows newlines. */\n allowsNewlines?: boolean;\n /** Whether the token field is read only. */\n isReadOnly?: boolean;\n /** Whether the token field is disabled. */\n isDisabled?: boolean;\n /** A function that is called when the user presses the Enter key. */\n onSubmit?: () => void;\n /** Handler that is called when a key is pressed. */\n onKeyDown?: (e: React.KeyboardEvent<HTMLDivElement>) => void;\n /** Handler that is called when a key is released. */\n onKeyUp?: (e: React.KeyboardEvent<HTMLDivElement>) => void;\n /**\n * Handler that is called when the user copies text. See\n * [MDN](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/oncopy).\n */\n onCopy?: ClipboardEventHandler<T>;\n\n /**\n * Handler that is called when the user cuts text. See\n * [MDN](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/oncut).\n */\n onCut?: ClipboardEventHandler<T>;\n\n /**\n * Handler that is called when the user pastes text. See\n * [MDN](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/onpaste).\n */\n onPaste?: ClipboardEventHandler<T>;\n}\n\nexport interface TokenFieldAria {\n /** Props for the token field's input element. */\n tokenFieldProps: HTMLAttributes<HTMLDivElement>;\n /** Props for the text field's visible label element, if any. */\n labelProps: DOMAttributes;\n /** Props for the text field's description element, if any. */\n descriptionProps: DOMAttributes;\n}\n\nconst CLIPBOARD_MIME_TYPE = 'application/vnd.react-aria.tokens+json';\n\n/**\n * Provides the behavior and accessibility implementation for a token field.\n * A token field allows users to enter text with inline tokens.\n *\n * @param props - Props for the token field.\n * @param state - State for the token field, as returned by `useTokenFieldState`.\n */\nexport function useTokenField<T extends TokenFieldValue = TokenFieldValue>(\n props: AriaTokenFieldProps<T>,\n state: TokenFieldState,\n ref: RefObject<HTMLDivElement | null>\n): TokenFieldAria {\n let {\n role = 'textbox',\n allowsNewlines: multiline = false,\n isReadOnly = false,\n isDisabled = false,\n 'aria-details': ariaDetails\n } = props;\n\n let {value} = state;\n let {locale} = useLocale();\n let graphemeSegmenter = useMemo(\n () => new Intl.Segmenter(locale, {granularity: 'grapheme'}),\n [locale]\n );\n let wordSegmenter = useMemo(() => new Intl.Segmenter(locale, {granularity: 'word'}), [locale]);\n\n let dropPosition = useRef<Position | null>(null);\n let transferredData = useRef<TokenFieldSegment[] | null>(null);\n\n let nextValue = useRef<TokenFieldValue | null>(null);\n let apply = (fn: (value: TokenFieldValue) => TokenFieldValue) => {\n state.setValue(value => {\n let newValue = fn(value);\n nextValue.current = newValue;\n return newValue;\n });\n };\n\n // Composition events are not cancelable. The browser will mutate the DOM, making it out of sync with React.\n // To account for this, we prevent React from re-rendering during composition, and track DOM mutations performed\n // by the browser. When composition ends, we revert the DOM to its original state, and re-render with React.\n // Mutating the DOM in any way during composition breaks the IME, causing composition to end unexpectedly.\n // During composition, we still emit updates via onChange to ensure that things like autocomplete work,\n // but we don't actually re-render to the DOM unless the value changes from what we expect (e.g. inserting a completion).\n let mutationTracker = useMutationTracker(ref);\n let startComposition = useCallback(() => {\n mutationTracker.start();\n state.setComposing(true);\n }, [state, mutationTracker]);\n let stopComposition = useCallback(() => {\n mutationTracker.stop();\n state.setComposing(false);\n }, [state, mutationTracker]);\n\n useEvent(ref, 'compositionstart', () => {\n startComposition();\n\n let range = window.getSelection()?.getRangeAt(0);\n if (range) {\n let [start, end] = rangeToPositions(ref.current!, range);\n\n // Normalize the range to ensure it is not inside a token, otherwise the browser\n // will attempt to insert the composed text into the token instead of replacing it.\n let r = createDOMRange(ref.current!, start, end);\n if (r.startContainer !== range.startContainer || r.startOffset !== range.startOffset) {\n range.setStart(r.startContainer, r.startOffset);\n }\n if (r.endContainer !== range.endContainer || r.endOffset !== range.endOffset) {\n range.setEnd(r.endContainer, r.endOffset);\n }\n }\n });\n\n useEvent(ref, 'compositionend', stopComposition);\n\n // If a prop update occurs during composition that doesn't match the expected value,\n // end composition and re-render the controlled value.\n useLayoutEffect(() => {\n if (state.isComposing && value !== nextValue.current) {\n stopComposition();\n }\n nextValue.current = value;\n });\n\n let selectedRange = useRef<SelectedRange | null>(null);\n useLayoutEffect(() => {\n if (ref.current && !state.isComposing && value.selectedRange !== selectedRange.current) {\n // Only move the caret when the field is already focused.\n if (ref.current === getActiveElement(getOwnerDocument(ref.current))) {\n setTokenFieldSelection(ref.current, value.selectedRange);\n announceToken(value);\n }\n selectedRange.current = value.selectedRange;\n }\n });\n\n // Handle text editing commands and prevent browser default behavior.\n useEvent(ref, 'beforeinput', e => {\n // Android sometimes doesn't fire a compositionend event before a regular input event.\n if (state.isComposing && !e.isComposing) {\n stopComposition();\n }\n\n let range = e.getTargetRanges()[0];\n if (!range) {\n let selection = window.getSelection();\n if (!selection || selection.rangeCount === 0) {\n return;\n }\n range = selection.getRangeAt(0);\n }\n let [start, end] = rangeToPositions(ref.current!, range);\n\n // https://www.w3.org/TR/input-events-2/#interface-InputEvent-Attributes\n switch (e.inputType) {\n case 'insertText':\n case 'insertReplacementText':\n case 'insertCompositionText':\n case 'insertFromComposition': // Removed from the spec, but still fired by Safari.\n case 'insertFromPaste':\n case 'insertFromYank':\n case 'insertFromDrop': {\n let data: TokenFieldSegment[] = [{type: 'text', text: e.data ?? ''}];\n if (transferredData.current) {\n data = transferredData.current;\n transferredData.current = null;\n } else if (e.dataTransfer) {\n let parsed = e.dataTransfer.types.includes(CLIPBOARD_MIME_TYPE)\n ? parseSegments(e.dataTransfer.getData(CLIPBOARD_MIME_TYPE))\n : null;\n if (parsed) {\n data = parsed;\n } else if (e.dataTransfer.types.includes('text/plain')) {\n data[0].text = e.dataTransfer.getData('text/plain');\n }\n }\n\n if (e.inputType === 'insertFromDrop' && dropPosition.current) {\n start = end = dropPosition.current;\n dropPosition.current = null;\n }\n\n if (!multiline) {\n for (let segment of data) {\n segment.text = segment.text.replace(/[\\r\\n]+/g, ' ');\n }\n }\n\n apply(tokens =>\n tokens.replaceRangeWithSegments(\n start,\n end,\n data,\n // Don't coalesce paste/drop events with other edits.\n e.inputType === 'insertText' ||\n e.inputType === 'insertCompositionText' ||\n e.inputType === 'insertFromComposition'\n )\n );\n break;\n }\n case 'insertParagraph': {\n if (props.onSubmit) {\n props.onSubmit();\n break;\n }\n // fallthrough\n }\n case 'insertLineBreak': {\n if (multiline) {\n apply(tokens => tokens.replaceRange(start, end, '\\n'));\n }\n break;\n }\n case 'deleteContentBackward':\n case 'deleteContentForward':\n case 'deleteWordBackward':\n case 'deleteWordForward':\n case 'deleteHardLineForward':\n case 'deleteHardLineBackward':\n case 'deleteSoftLineForward':\n case 'deleteSoftLineBackward':\n case 'deleteContent':\n case 'deleteByCut':\n case 'deleteCompositionText': {\n if (!range.collapsed && !isSamePosition(start, end)) {\n apply(tokens => tokens.replaceRange(start, end, ''));\n break;\n }\n\n switch (e.inputType) {\n case 'deleteContentBackward': {\n apply(tokens =>\n tokens.delete(start, graphemeSegmenter, TokenFieldValue.Direction.Backward)\n );\n break;\n }\n case 'deleteContentForward':\n apply(tokens =>\n tokens.delete(start, graphemeSegmenter, TokenFieldValue.Direction.Forward)\n );\n break;\n case 'deleteWordBackward': {\n apply(tokens =>\n tokens.delete(start, wordSegmenter, TokenFieldValue.Direction.Backward)\n );\n break;\n }\n case 'deleteWordForward':\n apply(tokens => tokens.delete(start, wordSegmenter, TokenFieldValue.Direction.Forward));\n break;\n case 'deleteHardLineForward':\n case 'deleteSoftLineForward': // TODO: this usually deletes to the nearest *visual* line break rather than a hard break\n apply(tokens => tokens.deleteLine(start, TokenFieldValue.Direction.Forward));\n break;\n case 'deleteHardLineBackward':\n case 'deleteSoftLineBackward':\n apply(tokens => tokens.deleteLine(start, TokenFieldValue.Direction.Backward));\n break;\n }\n break;\n }\n case 'deleteByDrag': {\n apply(tokens => {\n let endOffset =\n start.index === end.index ? end.offset : tokens.segments[start.index].text.length;\n let change = tokens.replaceRange(start, end, '');\n if (\n dropPosition.current &&\n dropPosition.current.index === start.index &&\n dropPosition.current.offset >= start.offset\n ) {\n dropPosition.current.offset -= endOffset - start.offset;\n }\n\n return change;\n });\n break;\n }\n }\n\n e.preventDefault();\n });\n\n let writeClipboardData = (e: ClipboardEvent | DragEvent) => {\n if ('clipboardData' in e) {\n e.preventDefault();\n }\n let selection = getSelection(ref.current!);\n if (!selection) {\n return;\n }\n let [start, end] = selection;\n let slice = value.slice(start, end);\n let dataTransfer = 'clipboardData' in e ? e.clipboardData : e.dataTransfer;\n dataTransfer?.setData(CLIPBOARD_MIME_TYPE, JSON.stringify(slice.segments));\n dataTransfer?.setData('text/plain', slice.toString());\n\n if (e.type === 'cut') {\n apply(tokens => tokens.replaceRange(start, end, '', false));\n }\n };\n\n useEvent(ref, 'copy', writeClipboardData);\n useEvent(ref, 'cut', writeClipboardData);\n useEvent(ref, 'dragstart', writeClipboardData);\n useEvent(ref, 'paste', e => {\n // Safari doesn't pass the custom clipboard data type to beforeinput dataTransfer so we handle it here.\n if (e.clipboardData && e.clipboardData.types.includes(CLIPBOARD_MIME_TYPE)) {\n transferredData.current = parseSegments(e.clipboardData.getData(CLIPBOARD_MIME_TYPE));\n }\n });\n\n // Store the cursor position on drop so we know where to insert when the insertFromDrop event occurs.\n useEvent(ref, 'drop', e => {\n if (typeof document.caretPositionFromPoint === 'function') {\n let pos = document.caretPositionFromPoint(e.clientX, e.clientY);\n if (pos) {\n dropPosition.current = getPosition(ref.current!, pos.offsetNode, pos.offset);\n }\n } else if (typeof document.caretRangeFromPoint === 'function') {\n let range = document.caretRangeFromPoint(e.clientX, e.clientY);\n if (range) {\n dropPosition.current = getPosition(ref.current!, range.startContainer, range.startOffset);\n }\n }\n\n if (e.dataTransfer && e.dataTransfer.types.includes(CLIPBOARD_MIME_TYPE)) {\n transferredData.current = parseSegments(e.dataTransfer.getData(CLIPBOARD_MIME_TYPE));\n }\n });\n\n useSelectionChange(ref, () => {\n if (state.isComposing) {\n return;\n }\n\n value.endCoalescing();\n\n // When the cursor moves next to a token, announce it.\n // Otherwise the screen reader will only announce the first/last character.\n let range = getSelectedRange(ref.current!);\n if (!range) {\n return;\n }\n\n announceToken(value, range);\n\n // Update the selected range in the value.\n state.setValue(value => value.withSelectedRange(range));\n });\n\n // Clear selection on blur.\n useEvent(ref, 'blur', e => {\n if (!e.isTrusted) {\n return;\n }\n\n let selection = window.getSelection();\n if (ref.current && selection && selection.containsNode(ref.current, true)) {\n selection.removeAllRanges();\n state.setValue(value =>\n value.withSelectedRange(new TokenFieldValue.SelectedRange(value.caretPosition))\n );\n }\n });\n\n // Override the default triple click behavior to ensure that tokens get selected.\n // Some browsers only select the text between tokens instead of the entire line.\n useEvent(ref, 'mousedown', e => {\n if (e.detail === 3) {\n let selection = getSelection(ref.current!);\n if (!selection) {\n return;\n }\n\n let start = value.findLineBoundary(selection[0], TokenFieldValue.Direction.Backward);\n let end = value.findLineBoundary(selection[1], TokenFieldValue.Direction.Forward);\n if (start && end) {\n e.preventDefault();\n setTokenFieldSelection(ref.current!, new TokenFieldValue.SelectedRange(start, end), true);\n }\n }\n });\n\n let moveSelection = (\n direction: 'left' | 'right',\n granularity: 'character' | 'word',\n extend = false\n ) => {\n let selection = window.getSelection();\n if (!selection || selection.rangeCount === 0 || !selection.focusNode || !selection.anchorNode) {\n return false;\n }\n\n // Pressing an arrow with a non-empty selection collapses it to the corresponding edge.\n // The browser handles this natively.\n if (!extend && !selection.isCollapsed) {\n return false;\n }\n\n // Move the caret using the browser's native caret movement (Selection.modify) so that\n // bidirectional text is handled correctly. Repeat until the position actually changes\n // to account for the zero width spaces around tokens.\n let pos = getPosition(ref.current!, selection.focusNode, selection.focusOffset);\n while (true) {\n let {focusNode, focusOffset} = selection;\n selection.modify(extend ? 'extend' : 'move', direction, granularity);\n if (selection.focusNode === focusNode && selection.focusOffset === focusOffset) {\n return false;\n }\n let newPos = getPosition(ref.current!, selection.focusNode, selection.focusOffset);\n if (!isSamePosition(pos, newPos)) {\n return true;\n }\n }\n };\n\n // macOS supports additional keyboard shortcuts for text editing.\n // We need to handle these manually so they behave consistently with tokens.\n // https://support.apple.com/en-us/102650#text\n let macShortcuts: Record<string, () => boolean | void> = isMac()\n ? {\n 'Control+a': () => {\n return shortcuts.Home();\n },\n 'Control+e': () => {\n return shortcuts.End();\n },\n 'Control+f': () => {\n return shortcuts.ArrowRight();\n },\n 'Control+b': () => {\n return shortcuts.ArrowLeft();\n }\n }\n : {};\n\n let mod = isMac() ? 'Meta' : 'Control';\n let wordModKey = isMac() ? 'Alt' : 'Control';\n let shortcuts: Record<string, () => boolean | void> = {\n ...macShortcuts,\n [`${mod}+z`]: () => {\n // If composing, the browser handles undo natively.\n if (state.isComposing) {\n return false;\n }\n apply(state => state.undo());\n },\n [isMac() ? 'Shift+Meta+z' : 'Control+y']: () => {\n if (state.isComposing) {\n return false;\n }\n apply(state => state.redo());\n },\n ArrowLeft: () => {\n return moveSelection('left', 'character');\n },\n [`${wordModKey}+ArrowLeft`]: () => {\n return moveSelection('left', 'word');\n },\n 'Shift+ArrowLeft': () => {\n return moveSelection('left', 'character', true);\n },\n [`Shift+${wordModKey}+ArrowLeft`]: () => {\n return moveSelection('left', 'word', true);\n },\n ArrowRight: () => {\n return moveSelection('right', 'character');\n },\n [`${wordModKey}+ArrowRight`]: () => {\n return moveSelection('right', 'word');\n },\n 'Shift+ArrowRight': () => {\n return moveSelection('right', 'character', true);\n },\n [`Shift+${wordModKey}+ArrowRight`]: () => {\n return moveSelection('right', 'word', true);\n },\n Home: () => {\n // Browsers do not behave consistently when there are tokens.\n let selection = getSelection(ref.current!);\n if (!selection) {\n return false;\n }\n let boundary = value.findLineBoundary(selection[0], TokenFieldValue.Direction.Backward);\n if (boundary) {\n setCursor(ref.current!, boundary, true);\n return true;\n }\n return false;\n },\n End: () => {\n let selection = getSelection(ref.current!);\n if (!selection) {\n return false;\n }\n let boundary = value.findLineBoundary(selection[1], TokenFieldValue.Direction.Forward);\n if (boundary) {\n setCursor(ref.current!, boundary, true);\n return true;\n }\n return false;\n }\n };\n\n // TODO: user provided onKeyDown currently relies on user provided preventDefault to stop submit\n // maybe can have them specify a format like shortcuts and merge into above?\n let {keyboardProps} = useKeyboard({\n isDisabled: isDisabled || isReadOnly,\n onKeyDown: props.onKeyDown,\n onKeyUp: props.onKeyUp,\n shortcuts: shortcuts,\n allowRepeats: true\n });\n\n let {focusableProps} = useFocusable(props, ref);\n let {labelProps, fieldProps, descriptionProps} = useField({\n ...props,\n labelElementType: 'span'\n });\n\n return {\n labelProps: {\n ...labelProps,\n onClick: () => {\n if (!props.isDisabled) {\n ref.current?.focus();\n\n // Show the focus ring so the user knows where focus went\n setInteractionModality('keyboard');\n }\n }\n },\n descriptionProps,\n tokenFieldProps: mergeProps(focusableProps, keyboardProps, fieldProps, {\n onPaste: props.onPaste,\n onCopy: props.onCopy,\n onCut: props.onCut,\n contentEditable: !isDisabled && !isReadOnly,\n suppressContentEditableWarning: true,\n role,\n 'aria-multiline': multiline,\n 'aria-details': ariaDetails,\n 'aria-readonly': isReadOnly,\n 'aria-disabled': isDisabled,\n style: {whiteSpace: 'pre-wrap'}\n })\n };\n}\n\nfunction indexOfNode(node: Node) {\n let index = 0;\n let n: Node | null = node;\n\n while ((n = n.previousSibling)) {\n index++;\n }\n return index;\n}\n\nexport function getSelection(container: Element): [Position, Position] | null {\n let selection = window.getSelection();\n if (!selection || selection.rangeCount === 0) {\n return null;\n }\n let range = selection.getRangeAt(0);\n return rangeToPositions(container, range);\n}\n\nexport function getSelectedRange(container: Element) {\n let selection = window.getSelection();\n if (\n !selection ||\n !selection.anchorNode ||\n !selection.focusNode ||\n !nodeContains(container, selection.anchorNode) ||\n !nodeContains(container, selection.focusNode)\n ) {\n return null;\n }\n let anchor = getPosition(container, selection.anchorNode, selection.anchorOffset, false);\n let current = getPosition(\n container,\n selection.focusNode,\n selection.focusOffset,\n !selection.isCollapsed\n );\n return new TokenFieldValue.SelectedRange(anchor, current);\n}\n\nfunction rangeToPositions(container: Element, range: Range | StaticRange): [Position, Position] {\n let start = getPosition(container, range.startContainer, range.startOffset, false);\n let end = getPosition(container, range.endContainer, range.endOffset, !range.collapsed);\n return [start, end];\n}\n\nfunction getPosition(container: Element, node: Node, offset: number, isRangeEnd = false): Position {\n if (node === container) {\n return {index: offset, offset: 0};\n }\n\n let originalNode = node;\n while (node.parentNode !== container) {\n node = node.parentNode!;\n }\n\n let index = indexOfNode(node);\n if (node.nodeType === Node.ELEMENT_NODE) {\n let tokenNode = node.childNodes[1];\n let atEnd: boolean;\n let endOffset = 0;\n if (originalNode === tokenNode) {\n // Cursor is inside the token.\n atEnd = isRangeEnd || offset > 0;\n } else if (originalNode === node) {\n // Cursor is inside the wrapper element.\n atEnd = offset > 1;\n } else {\n // Cursor is on one of the zero width spaces.\n atEnd = originalNode !== tokenNode.previousSibling;\n // If the offset is greater than 1, the browser is trying to insert text into\n // the zero width space node. This will actually end up in the next text node.\n endOffset = atEnd && offset > 1 ? offset - 1 : 0;\n }\n\n offset = atEnd ? (tokenNode?.textContent?.length ?? 0) : 0;\n\n // Several positions are equivalent due to the zero width spaces around tokens.\n // Normalize offset to the end of the preceding text node, or the beginning of the following node.\n if (offset === 0 && node.previousSibling?.nodeType === Node.TEXT_NODE) {\n index--;\n offset = node.previousSibling?.textContent?.length ?? 0;\n } else if (atEnd) {\n index++;\n offset = endOffset;\n }\n }\n return {index, offset};\n}\n\nlet isProgrammaticSelectionChange = Symbol('isProgrammaticSelectionChange');\n\nfunction setCursor(root: Element, pos: Position, fireEvent = false) {\n setTokenFieldSelection(root, new TokenFieldValue.SelectedRange(pos), fireEvent);\n}\n\nexport function setTokenFieldSelection(\n root: Element,\n selectedRange: SelectedRange,\n fireEvent = false\n) {\n let selection = window.getSelection();\n if (selection) {\n // Use setBaseAndExtent to preserve the selection direction. A plain Range +\n // addRange always produces a forward selection and collapses when the\n // anchor comes after the current position (backward selections).\n let [anchorNode, anchorOffset] = getDOMPosition(root, selectedRange.anchor);\n let [focusNode, focusOffset] = getDOMPosition(root, selectedRange.current);\n root[isProgrammaticSelectionChange] = !fireEvent;\n\n // Only set selection if it has changed, because this can clobber the browser's selection direction.\n if (\n selection.anchorNode !== anchorNode ||\n selection.anchorOffset !== anchorOffset ||\n selection.focusNode !== focusNode ||\n selection.focusOffset !== focusOffset\n ) {\n selection.setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset);\n }\n }\n}\n\nexport function tokenFieldPositionToDOMRange(root: Element, pos: Position): Range {\n // Unlike createDOMRange (used for caret/selection placement), this range is only\n // measured via getBoundingClientRect to position things like an autocomplete popover.\n // Place the endpoints inside the token's zero width space wrappers so the range has a\n // valid rect at the token, rather than a collapsed root-level position.\n let range = document.createRange();\n let [startContainer, startOffset] = getDOMRectPosition(root, pos);\n range.setStart(startContainer, startOffset);\n range.setEnd(startContainer, startOffset);\n return range;\n}\n\nfunction getDOMRectPosition(root: Element, pos: Position): [Node, number] {\n let child = root.childNodes[pos.index];\n if (child && child.nodeType === Node.ELEMENT_NODE) {\n // Place the position inside the zero width space wrappers around the token.\n if (pos.offset > 0) {\n return [child.lastChild!, 1];\n } else {\n return [child.firstChild!, 0];\n }\n }\n return getDOMPosition(root, pos);\n}\n\nfunction createDOMRange(root: Element, start: Position, end: Position): Range {\n let range = document.createRange();\n let [startContainer, startOffset] = getDOMPosition(root, start);\n let [endContainer, endOffset] = getDOMPosition(root, end);\n range.setStart(startContainer, startOffset);\n range.setEnd(endContainer, endOffset);\n return range;\n}\n\nfunction getDOMPosition(root: Element, pos: Position): [Node, number] {\n let index = Math.max(0, Math.min(root.childNodes.length, pos.index));\n let child = root.childNodes[index];\n if (!child) {\n return [root, index];\n } else if (child.nodeType === Node.ELEMENT_NODE) {\n // Place the cursor outside the token wrapper element.\n // This is necessary for composition events.\n if (pos.offset > 0) {\n return [root, index + 1];\n } else {\n return [root, index];\n }\n } else {\n let offset = Math.max(0, Math.min(child.textContent?.length ?? 0, pos.offset));\n return [child, offset];\n }\n}\n\nfunction isSamePosition(a: Position, b: Position): boolean {\n return a.index === b.index && a.offset === b.offset;\n}\n\n// Parse and validate segments from clipboard/drag data. Returns null if the data is not valid\n// JSON or does not match the expected shape, so malformed or untrusted data is ignored rather\n// than throwing or being inserted into the field.\nfunction parseSegments(json: string): TokenFieldSegment[] | null {\n try {\n let data = JSON.parse(json);\n if (Array.isArray(data) && data.length > 0 && data.every(isValidSegment)) {\n return data;\n }\n } catch {\n // Ignore invalid clipboard data.\n }\n return null;\n}\n\nfunction isValidSegment(segment: unknown): segment is TokenFieldSegment {\n return (\n typeof segment === 'object' &&\n segment != null &&\n ((segment as TokenFieldSegment).type === 'text' ||\n (segment as TokenFieldSegment).type === 'token') &&\n typeof (segment as TokenFieldSegment).text === 'string'\n );\n}\n\nfunction useSelectionChange(ref: React.RefObject<Element | null>, handler: () => void) {\n useEvent(useRef(typeof document !== 'undefined' ? document : null), 'selectionchange', () => {\n if (ref.current && ref.current[isProgrammaticSelectionChange]) {\n ref.current[isProgrammaticSelectionChange] = false;\n return;\n }\n\n let selection = window.getSelection();\n if (!selection || selection.rangeCount === 0 || !ref.current) {\n return;\n }\n\n let range = selection.getRangeAt(0);\n if (range.intersectsNode(ref.current)) {\n handler();\n }\n });\n}\n\nfunction useMutationTracker(ref: React.RefObject<Element | null>) {\n let mutationTracker = useRef<(() => void) | null>(null);\n\n // Disconnect the mutation observer if the field unmounts mid-composition.\n useLayoutEffect(\n () => () => {\n mutationTracker.current?.();\n mutationTracker.current = null;\n },\n []\n );\n\n return useMemo(\n () => ({\n start() {\n // Android sometimes fires two compositionstart events in a row, without a compositionend.\n // In that case, reuse the existing tracker.\n mutationTracker.current ||= trackMutations(ref.current!);\n },\n stop() {\n mutationTracker.current?.();\n mutationTracker.current = null;\n }\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps - conflicts with compiler\n []\n );\n}\n\n// Tracks mutations to the DOM until the returned function is called,\n// at which point the mutations are reverted.\nfunction trackMutations(element: Element) {\n let mutations: MutationRecord[] = [];\n let observer = new MutationObserver(records => {\n mutations.push(...records);\n });\n\n observer.observe(element, {\n childList: true,\n subtree: true,\n characterData: true,\n characterDataOldValue: true\n });\n\n return () => {\n mutations.push(...observer.takeRecords());\n observer.disconnect();\n\n for (let record of mutations.reverse()) {\n switch (record.type) {\n case 'childList':\n for (let node of record.removedNodes) {\n record.target.insertBefore(node, record.nextSibling);\n }\n for (let node of record.addedNodes) {\n record.target.removeChild(node);\n }\n break;\n case 'characterData':\n record.target.nodeValue = record.oldValue;\n break;\n }\n }\n };\n}\n\nfunction announceToken(value: TokenFieldValue, range = value.selectedRange) {\n if (range.isCollapsed) {\n // Announce adjacent tokens.\n let segment = value.segments[range.current.index];\n if (segment && segment.type !== 'token') {\n if (range.current.offset === 0) {\n segment = value.segments[range.current.index - 1];\n } else if (range.current.offset === segment.text.length) {\n segment = value.segments[range.current.index + 1];\n }\n }\n if (segment?.type === 'token') {\n announce(segment.text, 'assertive');\n }\n } else {\n // Announce token if it is the only thing selected.\n let selected = value.slice(range.start, range.end).segments;\n if (selected.length === 1 && selected[0].type === 'token') {\n announce(selected[0].text, 'assertive');\n }\n }\n}\n"],"names":[],"version":3,"file":"useTokenField.cjs.map"}
1
+ {"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;;;;;;;CAUC;;;;;;;;;;;;;;;;AAkFD,MAAM,4CAAsB;AASrB,SAAS,0CACd,KAA6B,EAC7B,KAAsB,EACtB,GAAqC;IAErC,IAAI,QACF,OAAO,WACP,gBAAgB,YAAY,KAAK,cACjC,aAAa,mBACb,aAAa,OACb,gBAAgB,WAAW,EAC5B,GAAG;IAEJ,IAAI,SAAC,KAAK,EAAC,GAAG;IACd,IAAI,UAAC,MAAM,EAAC,GAAG,CAAA,GAAA,mCAAQ;IACvB,IAAI,oBAAoB,CAAA,GAAA,oBAAM,EAC5B,IAAM,IAAI,KAAK,SAAS,CAAC,QAAQ;YAAC,aAAa;QAAU,IACzD;QAAC;KAAO;IAEV,IAAI,gBAAgB,CAAA,GAAA,oBAAM,EAAE,IAAM,IAAI,KAAK,SAAS,CAAC,QAAQ;YAAC,aAAa;QAAM,IAAI;QAAC;KAAO;IAE7F,IAAI,eAAe,CAAA,GAAA,mBAAK,EAAmB;IAC3C,IAAI,kBAAkB,CAAA,GAAA,mBAAK,EAA8B;IAEzD,IAAI,YAAY,CAAA,GAAA,mBAAK,EAA0B;IAC/C,IAAI,QAAQ,CAAC;QACX,MAAM,QAAQ,CAAC,CAAA;YACb,IAAI,WAAW,GAAG;YAClB,UAAU,OAAO,GAAG;YACpB,OAAO;QACT;IACF;IAEA,4GAA4G;IAC5G,gHAAgH;IAChH,4GAA4G;IAC5G,0GAA0G;IAC1G,uGAAuG;IACvG,yHAAyH;IACzH,IAAI,kBAAkB,yCAAmB;IACzC,IAAI,mBAAmB,CAAA,GAAA,wBAAU,EAAE;QACjC,gBAAgB,KAAK;QACrB,MAAM,YAAY,CAAC;IACrB,GAAG;QAAC;QAAO;KAAgB;IAC3B,IAAI,kBAAkB,CAAA,GAAA,wBAAU,EAAE;QAChC,gBAAgB,IAAI;QACpB,MAAM,YAAY,CAAC;IACrB,GAAG;QAAC;QAAO;KAAgB;IAE3B,CAAA,GAAA,kCAAO,EAAE,KAAK,oBAAoB;QAChC;QAEA,IAAI,QAAQ,OAAO,YAAY,IAAI,WAAW;QAC9C,IAAI,OAAO;YACT,IAAI,CAAC,OAAO,IAAI,GAAG,uCAAiB,IAAI,OAAO,EAAG;YAElD,gFAAgF;YAChF,mFAAmF;YACnF,IAAI,IAAI,qCAAe,IAAI,OAAO,EAAG,OAAO;YAC5C,IAAI,EAAE,cAAc,KAAK,MAAM,cAAc,IAAI,EAAE,WAAW,KAAK,MAAM,WAAW,EAClF,MAAM,QAAQ,CAAC,EAAE,cAAc,EAAE,EAAE,WAAW;YAEhD,IAAI,EAAE,YAAY,KAAK,MAAM,YAAY,IAAI,EAAE,SAAS,KAAK,MAAM,SAAS,EAC1E,MAAM,MAAM,CAAC,EAAE,YAAY,EAAE,EAAE,SAAS;QAE5C;IACF;IAEA,CAAA,GAAA,kCAAO,EAAE,KAAK,kBAAkB;IAEhC,oFAAoF;IACpF,sDAAsD;IACtD,CAAA,GAAA,yCAAc,EAAE;QACd,IAAI,MAAM,WAAW,IAAI,UAAU,UAAU,OAAO,EAClD;QAEF,UAAU,OAAO,GAAG;IACtB;IAEA,IAAI,gBAAgB,CAAA,GAAA,mBAAK,EAAwB;IACjD,CAAA,GAAA,yCAAc,EAAE;QACd,IAAI,IAAI,OAAO,IAAI,CAAC,MAAM,WAAW,IAAI,MAAM,aAAa,KAAK,cAAc,OAAO,EAAE;YACtF,yDAAyD;YACzD,IAAI,IAAI,OAAO,KAAK,CAAA,GAAA,0CAAe,EAAE,CAAA,GAAA,0CAAe,EAAE,IAAI,OAAO,IAAI;gBACnE,0CAAuB,IAAI,OAAO,EAAE,MAAM,aAAa;gBACvD,oCAAc;gBACd,mFAAmF;gBACnF,wFAAwF;gBACxF,0CAAoB,IAAI,OAAO;YACjC;YACA,cAAc,OAAO,GAAG,MAAM,aAAa;QAC7C;IACF;IAEA,qEAAqE;IACrE,CAAA,GAAA,kCAAO,EAAE,KAAK,eAAe,CAAA;QAC3B,sFAAsF;QACtF,IAAI,MAAM,WAAW,IAAI,CAAC,EAAE,WAAW,EACrC;QAGF,IAAI,QAAQ,EAAE,eAAe,EAAE,CAAC,EAAE;QAClC,IAAI,CAAC,OAAO;YACV,IAAI,YAAY,OAAO,YAAY;YACnC,IAAI,CAAC,aAAa,UAAU,UAAU,KAAK,GACzC;YAEF,QAAQ,UAAU,UAAU,CAAC;QAC/B;QACA,IAAI,CAAC,OAAO,IAAI,GAAG,uCAAiB,IAAI,OAAO,EAAG;QAElD,wEAAwE;QACxE,OAAQ,EAAE,SAAS;YACjB,KAAK;YACL,KAAK;YACL,KAAK;YACL,KAAK;YACL,KAAK;YACL,KAAK;YACL,KAAK;gBAAkB;oBACrB,IAAI,OAA4B;wBAAC;4BAAC,MAAM;4BAAQ,MAAM,EAAE,IAAI,IAAI;wBAAE;qBAAE;oBACpE,IAAI,gBAAgB,OAAO,EAAE;wBAC3B,OAAO,gBAAgB,OAAO;wBAC9B,gBAAgB,OAAO,GAAG;oBAC5B,OAAO,IAAI,EAAE,YAAY,EAAE;wBACzB,IAAI,SAAS,EAAE,YAAY,CAAC,KAAK,CAAC,QAAQ,CAAC,6CACvC,oCAAc,EAAE,YAAY,CAAC,OAAO,CAAC,8CACrC;wBACJ,IAAI,QACF,OAAO;6BACF,IAAI,EAAE,YAAY,CAAC,KAAK,CAAC,QAAQ,CAAC,eACvC,IAAI,CAAC,EAAE,CAAC,IAAI,GAAG,EAAE,YAAY,CAAC,OAAO,CAAC;oBAE1C;oBAEA,IAAI,EAAE,SAAS,KAAK,oBAAoB,aAAa,OAAO,EAAE;wBAC5D,QAAQ,MAAM,aAAa,OAAO;wBAClC,aAAa,OAAO,GAAG;oBACzB;oBAEA,IAAI,CAAC,WACH,KAAK,IAAI,WAAW,KAClB,QAAQ,IAAI,GAAG,QAAQ,IAAI,CAAC,OAAO,CAAC,YAAY;oBAIpD,MAAM,CAAA,SACJ,OAAO,wBAAwB,CAC7B,OACA,KACA,MACA,qDAAqD;wBACrD,EAAE,SAAS,KAAK,gBACd,EAAE,SAAS,KAAK,2BAChB,EAAE,SAAS,KAAK;oBAGtB;gBACF;YACA,KAAK;gBACH,IAAI,MAAM,QAAQ,EAAE;oBAClB,MAAM,QAAQ;oBACd;gBACF;YAGF,KAAK;gBACH,IAAI,WACF,MAAM,CAAA,SAAU,OAAO,YAAY,CAAC,OAAO,KAAK;gBAElD;YAEF,KAAK;YACL,KAAK;YACL,KAAK;YACL,KAAK;YACL,KAAK;YACL,KAAK;YACL,KAAK;YACL,KAAK;YACL,KAAK;YACL,KAAK;YACL,KAAK;gBACH,IAAI,CAAC,MAAM,SAAS,IAAI,CAAC,qCAAe,OAAO,MAAM;oBACnD,MAAM,CAAA,SAAU,OAAO,YAAY,CAAC,OAAO,KAAK;oBAChD;gBACF;gBAEA,OAAQ,EAAE,SAAS;oBACjB,KAAK;wBACH,MAAM,CAAA,SACJ,OAAO,MAAM,CAAC,OAAO,mBAAmB,CAAA,GAAA,qDAAc,EAAE,SAAS,CAAC,QAAQ;wBAE5E;oBAEF,KAAK;wBACH,MAAM,CAAA,SACJ,OAAO,MAAM,CAAC,OAAO,mBAAmB,CAAA,GAAA,qDAAc,EAAE,SAAS,CAAC,OAAO;wBAE3E;oBACF,KAAK;wBACH,MAAM,CAAA,SACJ,OAAO,MAAM,CAAC,OAAO,eAAe,CAAA,GAAA,qDAAc,EAAE,SAAS,CAAC,QAAQ;wBAExE;oBAEF,KAAK;wBACH,MAAM,CAAA,SAAU,OAAO,MAAM,CAAC,OAAO,eAAe,CAAA,GAAA,qDAAc,EAAE,SAAS,CAAC,OAAO;wBACrF;oBACF,KAAK;oBACL,KAAK;wBACH,MAAM,CAAA,SAAU,OAAO,UAAU,CAAC,OAAO,CAAA,GAAA,qDAAc,EAAE,SAAS,CAAC,OAAO;wBAC1E;oBACF,KAAK;oBACL,KAAK;wBACH,MAAM,CAAA,SAAU,OAAO,UAAU,CAAC,OAAO,CAAA,GAAA,qDAAc,EAAE,SAAS,CAAC,QAAQ;wBAC3E;gBACJ;gBACA;YAEF,KAAK;gBACH,MAAM,CAAA;oBACJ,IAAI,YACF,MAAM,KAAK,KAAK,IAAI,KAAK,GAAG,IAAI,MAAM,GAAG,OAAO,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM;oBACnF,IAAI,SAAS,OAAO,YAAY,CAAC,OAAO,KAAK;oBAC7C,IACE,aAAa,OAAO,IACpB,aAAa,OAAO,CAAC,KAAK,KAAK,MAAM,KAAK,IAC1C,aAAa,OAAO,CAAC,MAAM,IAAI,MAAM,MAAM,EAE3C,aAAa,OAAO,CAAC,MAAM,IAAI,YAAY,MAAM,MAAM;oBAGzD,OAAO;gBACT;gBACA;QAEJ;QAEA,EAAE,cAAc;IAClB;IAEA,IAAI,qBAAqB,CAAC;QACxB,IAAI,mBAAmB,GACrB,EAAE,cAAc;QAElB,IAAI,YAAY,0CAAa,IAAI,OAAO;QACxC,IAAI,CAAC,WACH;QAEF,IAAI,CAAC,OAAO,IAAI,GAAG;QACnB,IAAI,QAAQ,MAAM,KAAK,CAAC,OAAO;QAC/B,IAAI,eAAe,mBAAmB,IAAI,EAAE,aAAa,GAAG,EAAE,YAAY;QAC1E,cAAc,QAAQ,2CAAqB,KAAK,SAAS,CAAC,MAAM,QAAQ;QACxE,cAAc,QAAQ,cAAc,MAAM,QAAQ;QAElD,IAAI,EAAE,IAAI,KAAK,OACb,MAAM,CAAA,SAAU,OAAO,YAAY,CAAC,OAAO,KAAK,IAAI;IAExD;IAEA,CAAA,GAAA,kCAAO,EAAE,KAAK,QAAQ;IACtB,CAAA,GAAA,kCAAO,EAAE,KAAK,OAAO;IACrB,CAAA,GAAA,kCAAO,EAAE,KAAK,aAAa;IAC3B,CAAA,GAAA,kCAAO,EAAE,KAAK,SAAS,CAAA;QACrB,uGAAuG;QACvG,IAAI,EAAE,aAAa,IAAI,EAAE,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,4CACpD,gBAAgB,OAAO,GAAG,oCAAc,EAAE,aAAa,CAAC,OAAO,CAAC;IAEpE;IAEA,qGAAqG;IACrG,CAAA,GAAA,kCAAO,EAAE,KAAK,QAAQ,CAAA;QACpB,IAAI,OAAO,SAAS,sBAAsB,KAAK,YAAY;YACzD,IAAI,MAAM,SAAS,sBAAsB,CAAC,EAAE,OAAO,EAAE,EAAE,OAAO;YAC9D,IAAI,KACF,aAAa,OAAO,GAAG,kCAAY,IAAI,OAAO,EAAG,IAAI,UAAU,EAAE,IAAI,MAAM;QAE/E,OAAO,IAAI,OAAO,SAAS,mBAAmB,KAAK,YAAY;YAC7D,IAAI,QAAQ,SAAS,mBAAmB,CAAC,EAAE,OAAO,EAAE,EAAE,OAAO;YAC7D,IAAI,OACF,aAAa,OAAO,GAAG,kCAAY,IAAI,OAAO,EAAG,MAAM,cAAc,EAAE,MAAM,WAAW;QAE5F;QAEA,IAAI,EAAE,YAAY,IAAI,EAAE,YAAY,CAAC,KAAK,CAAC,QAAQ,CAAC,4CAClD,gBAAgB,OAAO,GAAG,oCAAc,EAAE,YAAY,CAAC,OAAO,CAAC;IAEnE;IAEA,yCAAmB,KAAK;QACtB,IAAI,MAAM,WAAW,EACnB;QAGF,MAAM,aAAa;QAEnB,sDAAsD;QACtD,2EAA2E;QAC3E,IAAI,QAAQ,0CAAiB,IAAI,OAAO;QACxC,IAAI,CAAC,OACH;QAGF,oCAAc,OAAO;QAErB,0CAA0C;QAC1C,MAAM,QAAQ,CAAC,CAAA,QAAS,MAAM,iBAAiB,CAAC;IAClD;IAEA,2BAA2B;IAC3B,CAAA,GAAA,kCAAO,EAAE,KAAK,QAAQ,CAAA;QACpB,IAAI,CAAC,EAAE,SAAS,EACd;QAGF,IAAI,YAAY,OAAO,YAAY;QACnC,IACE,IAAI,OAAO,IACX,aACA,UAAU,YAAY,CAAC,IAAI,OAAO,EAAE,SACpC,CAAC,UAAU,WAAW,EACtB;YACA,UAAU,eAAe;YACzB,MAAM,QAAQ,CAAC,CAAA,QACb,MAAM,iBAAiB,CAAC,IAAI,CAAA,GAAA,qDAAc,EAAE,aAAa,CAAC,MAAM,aAAa;QAEjF;IACF;IAEA,iFAAiF;IACjF,gFAAgF;IAChF,CAAA,GAAA,kCAAO,EAAE,KAAK,aAAa,CAAA;QACzB,IAAI,EAAE,MAAM,KAAK,GAAG;YAClB,IAAI,YAAY,0CAAa,IAAI,OAAO;YACxC,IAAI,CAAC,WACH;YAGF,IAAI,QAAQ,MAAM,gBAAgB,CAAC,SAAS,CAAC,EAAE,EAAE,CAAA,GAAA,qDAAc,EAAE,SAAS,CAAC,QAAQ;YACnF,IAAI,MAAM,MAAM,gBAAgB,CAAC,SAAS,CAAC,EAAE,EAAE,CAAA,GAAA,qDAAc,EAAE,SAAS,CAAC,OAAO;YAChF,IAAI,SAAS,KAAK;gBAChB,EAAE,cAAc;gBAChB,0CAAuB,IAAI,OAAO,EAAG,IAAI,CAAA,GAAA,qDAAc,EAAE,aAAa,CAAC,OAAO,MAAM;YACtF;QACF;IACF;IAEA,IAAI,gBAAgB,CAClB,WACA,aACA,SAAS,KAAK;QAEd,IAAI,YAAY,OAAO,YAAY;QACnC,IAAI,CAAC,aAAa,UAAU,UAAU,KAAK,KAAK,CAAC,UAAU,SAAS,IAAI,CAAC,UAAU,UAAU,EAC3F,OAAO;QAGT,uFAAuF;QACvF,qCAAqC;QACrC,IAAI,CAAC,UAAU,CAAC,UAAU,WAAW,EACnC,OAAO;QAGT,sFAAsF;QACtF,sFAAsF;QACtF,sDAAsD;QACtD,IAAI,MAAM,kCAAY,IAAI,OAAO,EAAG,UAAU,SAAS,EAAE,UAAU,WAAW;QAC9E,MAAO,KAAM;YACX,IAAI,aAAC,SAAS,eAAE,WAAW,EAAC,GAAG;YAC/B,UAAU,MAAM,CAAC,SAAS,WAAW,QAAQ,WAAW;YACxD,IAAI,UAAU,SAAS,KAAK,aAAa,UAAU,WAAW,KAAK,aACjE,OAAO;YAET,IAAI,SAAS,kCAAY,IAAI,OAAO,EAAG,UAAU,SAAS,EAAE,UAAU,WAAW;YACjF,IAAI,CAAC,qCAAe,KAAK,SACvB,OAAO;QAEX;IACF;IAEA,iEAAiE;IACjE,4EAA4E;IAC5E,8CAA8C;IAC9C,IAAI,eAAqD,CAAA,GAAA,+BAAI,MACzD;QACE,aAAa;YACX,OAAO,UAAU,IAAI;QACvB;QACA,aAAa;YACX,OAAO,UAAU,GAAG;QACtB;QACA,aAAa;YACX,OAAO,UAAU,UAAU;QAC7B;QACA,aAAa;YACX,OAAO,UAAU,SAAS;QAC5B;IACF,IACA,CAAC;IAEL,IAAI,MAAM,CAAA,GAAA,+BAAI,MAAM,SAAS;IAC7B,IAAI,aAAa,CAAA,GAAA,+BAAI,MAAM,QAAQ;IACnC,IAAI,YAAkD;QACpD,GAAG,YAAY;QACf,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,EAAE;YACZ,mDAAmD;YACnD,IAAI,MAAM,WAAW,EACnB,OAAO;YAET,MAAM,CAAA,QAAS,MAAM,IAAI;QAC3B;QACA,CAAC,CAAA,GAAA,+BAAI,MAAM,iBAAiB,YAAY,EAAE;YACxC,IAAI,MAAM,WAAW,EACnB,OAAO;YAET,MAAM,CAAA,QAAS,MAAM,IAAI;QAC3B;QACA,WAAW;YACT,OAAO,cAAc,QAAQ;QAC/B;QACA,CAAC,GAAG,WAAW,UAAU,CAAC,CAAC,EAAE;YAC3B,OAAO,cAAc,QAAQ;QAC/B;QACA,mBAAmB;YACjB,OAAO,cAAc,QAAQ,aAAa;QAC5C;QACA,CAAC,CAAC,MAAM,EAAE,WAAW,UAAU,CAAC,CAAC,EAAE;YACjC,OAAO,cAAc,QAAQ,QAAQ;QACvC;QACA,YAAY;YACV,OAAO,cAAc,SAAS;QAChC;QACA,CAAC,GAAG,WAAW,WAAW,CAAC,CAAC,EAAE;YAC5B,OAAO,cAAc,SAAS;QAChC;QACA,oBAAoB;YAClB,OAAO,cAAc,SAAS,aAAa;QAC7C;QACA,CAAC,CAAC,MAAM,EAAE,WAAW,WAAW,CAAC,CAAC,EAAE;YAClC,OAAO,cAAc,SAAS,QAAQ;QACxC;QACA,MAAM;YACJ,6DAA6D;YAC7D,IAAI,YAAY,0CAAa,IAAI,OAAO;YACxC,IAAI,CAAC,WACH,OAAO;YAET,IAAI,WAAW,MAAM,gBAAgB,CAAC,SAAS,CAAC,EAAE,EAAE,CAAA,GAAA,qDAAc,EAAE,SAAS,CAAC,QAAQ;YACtF,IAAI,UAAU;gBACZ,gCAAU,IAAI,OAAO,EAAG,UAAU;gBAClC,OAAO;YACT;YACA,OAAO;QACT;QACA,KAAK;YACH,IAAI,YAAY,0CAAa,IAAI,OAAO;YACxC,IAAI,CAAC,WACH,OAAO;YAET,IAAI,WAAW,MAAM,gBAAgB,CAAC,SAAS,CAAC,EAAE,EAAE,CAAA,GAAA,qDAAc,EAAE,SAAS,CAAC,OAAO;YACrF,IAAI,UAAU;gBACZ,gCAAU,IAAI,OAAO,EAAG,UAAU;gBAClC,OAAO;YACT;YACA,OAAO;QACT;IACF;IAEA,gGAAgG;IAChG,4EAA4E;IAC5E,IAAI,iBAAC,aAAa,EAAC,GAAG,CAAA,GAAA,qCAAU,EAAE;QAChC,YAAY,cAAc;QAC1B,WAAW,MAAM,SAAS;QAC1B,SAAS,MAAM,OAAO;QACtB,WAAW;QACX,cAAc;IAChB;IAEA,IAAI,kBAAC,cAAc,EAAC,GAAG,CAAA,GAAA,sCAAW,EAAE,OAAO;IAC3C,IAAI,cAAC,UAAU,cAAE,UAAU,oBAAE,gBAAgB,EAAC,GAAG,CAAA,GAAA,kCAAO,EAAE;QACxD,GAAG,KAAK;QACR,kBAAkB;IACpB;IAEA,OAAO;QACL,YAAY;YACV,GAAG,UAAU;YACb,SAAS;gBACP,IAAI,CAAC,MAAM,UAAU,EAAE;oBACrB,IAAI,OAAO,EAAE;oBAEb,yDAAyD;oBACzD,CAAA,GAAA,gDAAqB,EAAE;gBACzB;YACF;QACF;0BACA;QACA,iBAAiB,CAAA,GAAA,oCAAS,EAAE,gBAAgB,eAAe,YAAY;YACrE,SAAS,MAAM,OAAO;YACtB,QAAQ,MAAM,MAAM;YACpB,OAAO,MAAM,KAAK;YAClB,iBAAiB,CAAC,cAAc,CAAC;YACjC,gCAAgC;kBAChC;YACA,kBAAkB;YAClB,gBAAgB;YAChB,iBAAiB;YACjB,iBAAiB;YACjB,OAAO;gBAAC,YAAY;YAAU;QAChC;IACF;AACF;AAEA,SAAS,kCAAY,IAAU;IAC7B,IAAI,QAAQ;IACZ,IAAI,IAAiB;IAErB,MAAQ,IAAI,EAAE,eAAe,CAC3B;IAEF,OAAO;AACT;AAEO,SAAS,0CAAa,SAAkB;IAC7C,IAAI,YAAY,OAAO,YAAY;IACnC,IAAI,CAAC,aAAa,UAAU,UAAU,KAAK,GACzC,OAAO;IAET,IAAI,QAAQ,UAAU,UAAU,CAAC;IACjC,OAAO,uCAAiB,WAAW;AACrC;AAEO,SAAS,0CAAiB,SAAkB;IACjD,IAAI,YAAY,OAAO,YAAY;IACnC,IACE,CAAC,aACD,CAAC,UAAU,UAAU,IACrB,CAAC,UAAU,SAAS,IACpB,CAAC,CAAA,GAAA,sCAAW,EAAE,WAAW,UAAU,UAAU,KAC7C,CAAC,CAAA,GAAA,sCAAW,EAAE,WAAW,UAAU,SAAS,GAE5C,OAAO;IAET,IAAI,SAAS,kCAAY,WAAW,UAAU,UAAU,EAAE,UAAU,YAAY,EAAE;IAClF,IAAI,UAAU,kCACZ,WACA,UAAU,SAAS,EACnB,UAAU,WAAW,EACrB,CAAC,UAAU,WAAW;IAExB,OAAO,IAAI,CAAA,GAAA,qDAAc,EAAE,aAAa,CAAC,QAAQ;AACnD;AAEA,SAAS,uCAAiB,SAAkB,EAAE,KAA0B;IACtE,IAAI,QAAQ,kCAAY,WAAW,MAAM,cAAc,EAAE,MAAM,WAAW,EAAE;IAC5E,IAAI,MAAM,kCAAY,WAAW,MAAM,YAAY,EAAE,MAAM,SAAS,EAAE,CAAC,MAAM,SAAS;IACtF,OAAO;QAAC;QAAO;KAAI;AACrB;AAEA,SAAS,kCAAY,SAAkB,EAAE,IAAU,EAAE,MAAc,EAAE,aAAa,KAAK;IACrF,IAAI,SAAS,WACX,OAAO;QAAC,OAAO;QAAQ,QAAQ;IAAC;IAGlC,IAAI,eAAe;IACnB,MAAO,KAAK,UAAU,KAAK,UACzB,OAAO,KAAK,UAAU;IAGxB,IAAI,QAAQ,kCAAY;IACxB,IAAI,KAAK,QAAQ,KAAK,KAAK,YAAY,EAAE;QACvC,IAAI,YAAY,KAAK,UAAU,CAAC,EAAE;QAClC,IAAI;QACJ,IAAI,YAAY;QAChB,IAAI,iBAAiB,WACnB,8BAA8B;QAC9B,QAAQ,cAAc,SAAS;aAC1B,IAAI,iBAAiB,MAC1B,wCAAwC;QACxC,QAAQ,SAAS;aACZ;YACL,6CAA6C;YAC7C,QAAQ,iBAAiB,UAAU,eAAe;YAClD,6EAA6E;YAC7E,8EAA8E;YAC9E,YAAY,SAAS,SAAS,IAAI,SAAS,IAAI;QACjD;QAEA,SAAS,QAAS,WAAW,aAAa,UAAU,IAAK;QAEzD,+EAA+E;QAC/E,kGAAkG;QAClG,IAAI,WAAW,KAAK,KAAK,eAAe,EAAE,aAAa,KAAK,SAAS,EAAE;YACrE;YACA,SAAS,KAAK,eAAe,EAAE,aAAa,UAAU;QACxD,OAAO,IAAI,OAAO;YAChB;YACA,SAAS;QACX;IACF;IACA,OAAO;eAAC;gBAAO;IAAM;AACvB;AAEA,IAAI,sDAAgC,OAAO;AAE3C,SAAS,gCAAU,IAAa,EAAE,GAAa,EAAE,YAAY,KAAK;IAChE,0CAAuB,MAAM,IAAI,CAAA,GAAA,qDAAc,EAAE,aAAa,CAAC,MAAM;AACvE;AAEO,SAAS,0CACd,IAAa,EACb,aAA4B,EAC5B,YAAY,KAAK;IAEjB,IAAI,YAAY,OAAO,YAAY;IACnC,IAAI,WAAW;QACb,4EAA4E;QAC5E,sEAAsE;QACtE,iEAAiE;QACjE,IAAI,CAAC,YAAY,aAAa,GAAG,qCAAe,MAAM,cAAc,MAAM;QAC1E,IAAI,CAAC,WAAW,YAAY,GAAG,qCAAe,MAAM,cAAc,OAAO;QACzE,IAAI,CAAC,oDAA8B,GAAG,CAAC;QAEvC,oGAAoG;QACpG,IACE,UAAU,UAAU,KAAK,cACzB,UAAU,YAAY,KAAK,gBAC3B,UAAU,SAAS,KAAK,aACxB,UAAU,WAAW,KAAK,aAE1B,UAAU,gBAAgB,CAAC,YAAY,cAAc,WAAW;IAEpE;AACF;AAEA,0FAA0F;AAC1F,6FAA6F;AAC7F,kFAAkF;AAClF,oEAAoE;AACpE,SAAS,0CAAoB,IAAiB;IAC5C,IAAI,YAAY,OAAO,YAAY;IACnC,IACE,CAAA,GAAA,gDAAqB,QAAQ,cAC7B,CAAC,aACD,UAAU,UAAU,KAAK,KACzB,CAAC,CAAA,GAAA,sCAAW,EAAE,MAAM,UAAU,SAAS,GAEvC;IAGF,IAAI,QAAQ,UAAU,UAAU,CAAC;IACjC,IAAI,OAAO,MAAM,qBAAqB;IAEtC,wFAAwF;IACxF,IAAI,KAAK,GAAG,KAAK,KAAK,KAAK,MAAM,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,KAAK,KAAK,KAAK,GAAG;QAC9E,IAAI,OAAoB,MAAM,YAAY;QAC1C,IAAI,KAAK,QAAQ,KAAK,KAAK,SAAS,IAAI,MAAM,SAAS,GAAG,KAAK,SAAS,CAAE,MAAM,EAAE;YAChF,6FAA6F;YAC7F,QAAQ,MAAM,UAAU;YACxB,MAAM,MAAM,CAAC,MAAM,MAAM,SAAS,GAAG;YACrC,OAAO,MAAM,qBAAqB;QACpC,OAAO,IAAI,KAAK,UAAU,IAAI,MAC5B,6CAA6C;QAC7C,OAAO,KAAK,qBAAqB;aAC5B;YACL,8FAA8F;YAC9F,IAAI,cAAc,KAAK,WAAW;YAClC,MAAO,QAAQ,SAAS,QAAQ,CAAC,YAAa;gBAC5C,OAAO,KAAK,UAAU;gBACtB,cAAc,OAAO,KAAK,WAAW,GAAG;YAC1C;YAEA,IAAI,aAAa,aAAa,KAAK,YAAY,EAC7C,OAAO,AAAC,YAA4B,qBAAqB;QAE7D;IACF;IAEA,KAAK,IAAI,WAAW,CAAA,GAAA,0CAAe,EAAE,MAAM,MAAO;QAChD,qFAAqF;QACrF,4FAA4F;QAC5F,4FAA4F;QAC5F,iDAAiD;QACjD,IAAI,eAAe;QACnB,IAAI,YAAY,aAAa,SAAS;QACtC,IAAI,aAAa,aAAa,UAAU;QACxC,CAAA,GAAA,4CAAiB,EAAE,cAAc,MAAM,MAAM;YAAC,OAAO;YAAW,QAAQ;QAAS;QACjF,IAAI,KAAK,aAAa,SAAS,GAAG;QAClC,IAAI,KAAK,aAAa,UAAU,GAAG;QACnC,IAAI,OAAO,KAAK,OAAO,GACrB,OAAO,IAAI,QAAQ,KAAK,CAAC,GAAG,IAAI,KAAK,CAAC,GAAG,IAAI,KAAK,KAAK,EAAE,KAAK,MAAM;IAExE;AACF;AAEO,SAAS,0CAA6B,IAAa,EAAE,GAAa;IACvE,iFAAiF;IACjF,sFAAsF;IACtF,sFAAsF;IACtF,wEAAwE;IACxE,IAAI,QAAQ,SAAS,WAAW;IAChC,IAAI,CAAC,gBAAgB,YAAY,GAAG,yCAAmB,MAAM;IAC7D,MAAM,QAAQ,CAAC,gBAAgB;IAC/B,MAAM,MAAM,CAAC,gBAAgB;IAC7B,OAAO;AACT;AAEA,SAAS,yCAAmB,IAAa,EAAE,GAAa;IACtD,IAAI,QAAQ,KAAK,UAAU,CAAC,IAAI,KAAK,CAAC;IACtC,IAAI,SAAS,MAAM,QAAQ,KAAK,KAAK,YAAY,EAAE;QACjD,4EAA4E;QAC5E,IAAI,IAAI,MAAM,GAAG,GACf,OAAO;YAAC,MAAM,SAAS;YAAG;SAAE;aAE5B,OAAO;YAAC,MAAM,UAAU;YAAG;SAAE;IAEjC;IACA,OAAO,qCAAe,MAAM;AAC9B;AAEA,SAAS,qCAAe,IAAa,EAAE,KAAe,EAAE,GAAa;IACnE,IAAI,QAAQ,SAAS,WAAW;IAChC,IAAI,CAAC,gBAAgB,YAAY,GAAG,qCAAe,MAAM;IACzD,IAAI,CAAC,cAAc,UAAU,GAAG,qCAAe,MAAM;IACrD,MAAM,QAAQ,CAAC,gBAAgB;IAC/B,MAAM,MAAM,CAAC,cAAc;IAC3B,OAAO;AACT;AAEA,SAAS,qCAAe,IAAa,EAAE,GAAa;IAClD,IAAI,QAAQ,KAAK,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,KAAK,UAAU,CAAC,MAAM,EAAE,IAAI,KAAK;IAClE,IAAI,QAAQ,KAAK,UAAU,CAAC,MAAM;IAClC,IAAI,CAAC,OACH,OAAO;QAAC;QAAM;KAAM;SACf,IAAI,MAAM,QAAQ,KAAK,KAAK,YAAY,EAAE;QAC/C,sDAAsD;QACtD,4CAA4C;QAC5C,IAAI,IAAI,MAAM,GAAG,GACf,OAAO;YAAC;YAAM,QAAQ;SAAE;aAExB,OAAO;YAAC;YAAM;SAAM;IAExB,OAAO;QACL,IAAI,SAAS,KAAK,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,MAAM,WAAW,EAAE,UAAU,GAAG,IAAI,MAAM;QAC5E,OAAO;YAAC;YAAO;SAAO;IACxB;AACF;AAEA,SAAS,qCAAe,CAAW,EAAE,CAAW;IAC9C,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,IAAI,EAAE,MAAM,KAAK,EAAE,MAAM;AACrD;AAEA,8FAA8F;AAC9F,8FAA8F;AAC9F,kDAAkD;AAClD,SAAS,oCAAc,IAAY;IACjC,IAAI;QACF,IAAI,OAAO,KAAK,KAAK,CAAC;QACtB,IAAI,MAAM,OAAO,CAAC,SAAS,KAAK,MAAM,GAAG,KAAK,KAAK,KAAK,CAAC,uCACvD,OAAO;IAEX,EAAE,OAAM;IACN,iCAAiC;IACnC;IACA,OAAO;AACT;AAEA,SAAS,qCAAe,OAAgB;IACtC,OACE,OAAO,YAAY,YACnB,WAAW,QACV,CAAA,AAAC,QAA8B,IAAI,KAAK,UACvC,AAAC,QAA8B,IAAI,KAAK,OAAM,KAChD,OAAO,AAAC,QAA8B,IAAI,KAAK;AAEnD;AAEA,SAAS,yCAAmB,GAAoC,EAAE,OAAmB;IACnF,CAAA,GAAA,kCAAO,EAAE,CAAA,GAAA,mBAAK,EAAE,OAAO,aAAa,cAAc,WAAW,OAAO,mBAAmB;QACrF,IAAI,IAAI,OAAO,IAAI,IAAI,OAAO,CAAC,oDAA8B,EAAE;YAC7D,IAAI,OAAO,CAAC,oDAA8B,GAAG;YAC7C;QACF;QAEA,IAAI,YAAY,OAAO,YAAY;QACnC,IAAI,CAAC,aAAa,UAAU,UAAU,KAAK,KAAK,CAAC,IAAI,OAAO,EAC1D;QAGF,IAAI,QAAQ,UAAU,UAAU,CAAC;QACjC,IAAI,MAAM,cAAc,CAAC,IAAI,OAAO,GAClC;IAEJ;AACF;AAEA,SAAS,yCAAmB,GAAoC;IAC9D,IAAI,kBAAkB,CAAA,GAAA,mBAAK,EAAuB;IAElD,0EAA0E;IAC1E,CAAA,GAAA,yCAAc,EACZ,IAAM;YACJ,gBAAgB,OAAO;YACvB,gBAAgB,OAAO,GAAG;QAC5B,GACA,EAAE;IAGJ,OAAO,CAAA,GAAA,oBAAM,EACX,IAAO,CAAA;YACL;gBACE,0FAA0F;gBAC1F,4CAA4C;gBAC5C,gBAAgB,OAAO,KAAK,qCAAe,IAAI,OAAO;YACxD;YACA;gBACE,gBAAgB,OAAO;gBACvB,gBAAgB,OAAO,GAAG;YAC5B;QACF,CAAA,GACA,iFAAiF;IACjF,EAAE;AAEN;AAEA,qEAAqE;AACrE,6CAA6C;AAC7C,SAAS,qCAAe,OAAgB;IACtC,IAAI,YAA8B,EAAE;IACpC,IAAI,WAAW,IAAI,iBAAiB,CAAA;QAClC,UAAU,IAAI,IAAI;IACpB;IAEA,SAAS,OAAO,CAAC,SAAS;QACxB,WAAW;QACX,SAAS;QACT,eAAe;QACf,uBAAuB;IACzB;IAEA,OAAO;QACL,UAAU,IAAI,IAAI,SAAS,WAAW;QACtC,SAAS,UAAU;QAEnB,KAAK,IAAI,UAAU,UAAU,OAAO,GAClC,OAAQ,OAAO,IAAI;YACjB,KAAK;gBACH,KAAK,IAAI,QAAQ,OAAO,YAAY,CAClC,OAAO,MAAM,CAAC,YAAY,CAAC,MAAM,OAAO,WAAW;gBAErD,KAAK,IAAI,QAAQ,OAAO,UAAU,CAChC,OAAO,MAAM,CAAC,WAAW,CAAC;gBAE5B;YACF,KAAK;gBACH,OAAO,MAAM,CAAC,SAAS,GAAG,OAAO,QAAQ;gBACzC;QACJ;IAEJ;AACF;AAEA,SAAS,oCAAc,KAAsB,EAAE,QAAQ,MAAM,aAAa;IACxE,IAAI,MAAM,WAAW,EAAE;QACrB,4BAA4B;QAC5B,IAAI,UAAU,MAAM,QAAQ,CAAC,MAAM,OAAO,CAAC,KAAK,CAAC;QACjD,IAAI,WAAW,QAAQ,IAAI,KAAK,SAAS;YACvC,IAAI,MAAM,OAAO,CAAC,MAAM,KAAK,GAC3B,UAAU,MAAM,QAAQ,CAAC,MAAM,OAAO,CAAC,KAAK,GAAG,EAAE;iBAC5C,IAAI,MAAM,OAAO,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,MAAM,EACrD,UAAU,MAAM,QAAQ,CAAC,MAAM,OAAO,CAAC,KAAK,GAAG,EAAE;QAErD;QACA,IAAI,SAAS,SAAS,SACpB,CAAA,GAAA,kCAAO,EAAE,QAAQ,IAAI,EAAE;IAE3B,OAAO;QACL,mDAAmD;QACnD,IAAI,WAAW,MAAM,KAAK,CAAC,MAAM,KAAK,EAAE,MAAM,GAAG,EAAE,QAAQ;QAC3D,IAAI,SAAS,MAAM,KAAK,KAAK,QAAQ,CAAC,EAAE,CAAC,IAAI,KAAK,SAChD,CAAA,GAAA,kCAAO,EAAE,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE;IAE/B;AACF","sources":["packages/react-aria/src/tokenfield/useTokenField.ts"],"sourcesContent":["/*\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing\n */\n\nimport {announce} from '../live-announcer/LiveAnnouncer';\nimport {AriaLabelingProps, DOMAttributes, FocusableProps} from '@react-types/shared';\nimport {\n ClipboardEventHandler,\n HTMLAttributes,\n RefObject,\n useCallback,\n useMemo,\n useRef\n} from 'react';\nimport {getActiveElement, nodeContains} from '../utils/shadowdom/DOMFunctions';\nimport {getInteractionModality, setInteractionModality} from '../interactions/useFocusVisible';\nimport {getOwnerDocument} from '../utils/domHelpers';\nimport {getScrollParents} from '../utils/getScrollParents';\nimport {isMac} from '../utils/platform';\nimport {mergeProps} from '../utils/mergeProps';\nimport {\n Position,\n SelectedRange,\n TokenFieldProps,\n TokenFieldSegment,\n TokenFieldState,\n TokenFieldValue\n} from 'react-stately/useTokenFieldState';\nimport {scrollRectIntoView} from '../utils/scrollIntoView';\nimport {useEvent} from '../utils/useEvent';\nimport {useField} from '../label/useField';\nimport {useFocusable} from '../interactions/useFocusable';\nimport {useKeyboard} from '../interactions/useKeyboard';\nimport {useLayoutEffect} from '../utils/useLayoutEffect';\nimport {useLocale} from '../i18n/I18nProvider';\n\nexport interface AriaTokenFieldProps<T extends TokenFieldValue = TokenFieldValue>\n extends TokenFieldProps<T>, FocusableProps, AriaLabelingProps {\n /**\n * The accessibility role of the token field.\n *\n * @default 'textbox'\n */\n role?: 'textbox' | 'searchbox' | 'combobox';\n /** Whether the token field allows newlines. */\n allowsNewlines?: boolean;\n /** Whether the token field is read only. */\n isReadOnly?: boolean;\n /** Whether the token field is disabled. */\n isDisabled?: boolean;\n /** A function that is called when the user presses the Enter key. */\n onSubmit?: () => void;\n /** Handler that is called when a key is pressed. */\n onKeyDown?: (e: React.KeyboardEvent<HTMLDivElement>) => void;\n /** Handler that is called when a key is released. */\n onKeyUp?: (e: React.KeyboardEvent<HTMLDivElement>) => void;\n /**\n * Handler that is called when the user copies text. See\n * [MDN](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/oncopy).\n */\n onCopy?: ClipboardEventHandler<T>;\n\n /**\n * Handler that is called when the user cuts text. See\n * [MDN](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/oncut).\n */\n onCut?: ClipboardEventHandler<T>;\n\n /**\n * Handler that is called when the user pastes text. See\n * [MDN](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/onpaste).\n */\n onPaste?: ClipboardEventHandler<T>;\n}\n\nexport interface TokenFieldAria {\n /** Props for the token field's input element. */\n tokenFieldProps: HTMLAttributes<HTMLDivElement>;\n /** Props for the text field's visible label element, if any. */\n labelProps: DOMAttributes;\n /** Props for the text field's description element, if any. */\n descriptionProps: DOMAttributes;\n}\n\nconst CLIPBOARD_MIME_TYPE = 'application/vnd.react-aria.tokens+json';\n\n/**\n * Provides the behavior and accessibility implementation for a token field.\n * A token field allows users to enter text with inline tokens.\n *\n * @param props - Props for the token field.\n * @param state - State for the token field, as returned by `useTokenFieldState`.\n */\nexport function useTokenField<T extends TokenFieldValue = TokenFieldValue>(\n props: AriaTokenFieldProps<T>,\n state: TokenFieldState,\n ref: RefObject<HTMLDivElement | null>\n): TokenFieldAria {\n let {\n role = 'textbox',\n allowsNewlines: multiline = false,\n isReadOnly = false,\n isDisabled = false,\n 'aria-details': ariaDetails\n } = props;\n\n let {value} = state;\n let {locale} = useLocale();\n let graphemeSegmenter = useMemo(\n () => new Intl.Segmenter(locale, {granularity: 'grapheme'}),\n [locale]\n );\n let wordSegmenter = useMemo(() => new Intl.Segmenter(locale, {granularity: 'word'}), [locale]);\n\n let dropPosition = useRef<Position | null>(null);\n let transferredData = useRef<TokenFieldSegment[] | null>(null);\n\n let nextValue = useRef<TokenFieldValue | null>(null);\n let apply = (fn: (value: TokenFieldValue) => TokenFieldValue) => {\n state.setValue(value => {\n let newValue = fn(value);\n nextValue.current = newValue;\n return newValue;\n });\n };\n\n // Composition events are not cancelable. The browser will mutate the DOM, making it out of sync with React.\n // To account for this, we prevent React from re-rendering during composition, and track DOM mutations performed\n // by the browser. When composition ends, we revert the DOM to its original state, and re-render with React.\n // Mutating the DOM in any way during composition breaks the IME, causing composition to end unexpectedly.\n // During composition, we still emit updates via onChange to ensure that things like autocomplete work,\n // but we don't actually re-render to the DOM unless the value changes from what we expect (e.g. inserting a completion).\n let mutationTracker = useMutationTracker(ref);\n let startComposition = useCallback(() => {\n mutationTracker.start();\n state.setComposing(true);\n }, [state, mutationTracker]);\n let stopComposition = useCallback(() => {\n mutationTracker.stop();\n state.setComposing(false);\n }, [state, mutationTracker]);\n\n useEvent(ref, 'compositionstart', () => {\n startComposition();\n\n let range = window.getSelection()?.getRangeAt(0);\n if (range) {\n let [start, end] = rangeToPositions(ref.current!, range);\n\n // Normalize the range to ensure it is not inside a token, otherwise the browser\n // will attempt to insert the composed text into the token instead of replacing it.\n let r = createDOMRange(ref.current!, start, end);\n if (r.startContainer !== range.startContainer || r.startOffset !== range.startOffset) {\n range.setStart(r.startContainer, r.startOffset);\n }\n if (r.endContainer !== range.endContainer || r.endOffset !== range.endOffset) {\n range.setEnd(r.endContainer, r.endOffset);\n }\n }\n });\n\n useEvent(ref, 'compositionend', stopComposition);\n\n // If a prop update occurs during composition that doesn't match the expected value,\n // end composition and re-render the controlled value.\n useLayoutEffect(() => {\n if (state.isComposing && value !== nextValue.current) {\n stopComposition();\n }\n nextValue.current = value;\n });\n\n let selectedRange = useRef<SelectedRange | null>(null);\n useLayoutEffect(() => {\n if (ref.current && !state.isComposing && value.selectedRange !== selectedRange.current) {\n // Only move the caret when the field is already focused.\n if (ref.current === getActiveElement(getOwnerDocument(ref.current))) {\n setTokenFieldSelection(ref.current, value.selectedRange);\n announceToken(value);\n // We call preventDefault in the beforeinput handler below, which also prevents the\n // browser's default behavior of scrolling the caret into view. Do it ourselves instead.\n scrollCaretIntoView(ref.current);\n }\n selectedRange.current = value.selectedRange;\n }\n });\n\n // Handle text editing commands and prevent browser default behavior.\n useEvent(ref, 'beforeinput', e => {\n // Android sometimes doesn't fire a compositionend event before a regular input event.\n if (state.isComposing && !e.isComposing) {\n stopComposition();\n }\n\n let range = e.getTargetRanges()[0];\n if (!range) {\n let selection = window.getSelection();\n if (!selection || selection.rangeCount === 0) {\n return;\n }\n range = selection.getRangeAt(0);\n }\n let [start, end] = rangeToPositions(ref.current!, range);\n\n // https://www.w3.org/TR/input-events-2/#interface-InputEvent-Attributes\n switch (e.inputType) {\n case 'insertText':\n case 'insertReplacementText':\n case 'insertCompositionText':\n case 'insertFromComposition': // Removed from the spec, but still fired by Safari.\n case 'insertFromPaste':\n case 'insertFromYank':\n case 'insertFromDrop': {\n let data: TokenFieldSegment[] = [{type: 'text', text: e.data ?? ''}];\n if (transferredData.current) {\n data = transferredData.current;\n transferredData.current = null;\n } else if (e.dataTransfer) {\n let parsed = e.dataTransfer.types.includes(CLIPBOARD_MIME_TYPE)\n ? parseSegments(e.dataTransfer.getData(CLIPBOARD_MIME_TYPE))\n : null;\n if (parsed) {\n data = parsed;\n } else if (e.dataTransfer.types.includes('text/plain')) {\n data[0].text = e.dataTransfer.getData('text/plain');\n }\n }\n\n if (e.inputType === 'insertFromDrop' && dropPosition.current) {\n start = end = dropPosition.current;\n dropPosition.current = null;\n }\n\n if (!multiline) {\n for (let segment of data) {\n segment.text = segment.text.replace(/[\\r\\n]+/g, ' ');\n }\n }\n\n apply(tokens =>\n tokens.replaceRangeWithSegments(\n start,\n end,\n data,\n // Don't coalesce paste/drop events with other edits.\n e.inputType === 'insertText' ||\n e.inputType === 'insertCompositionText' ||\n e.inputType === 'insertFromComposition'\n )\n );\n break;\n }\n case 'insertParagraph': {\n if (props.onSubmit) {\n props.onSubmit();\n break;\n }\n // fallthrough\n }\n case 'insertLineBreak': {\n if (multiline) {\n apply(tokens => tokens.replaceRange(start, end, '\\n'));\n }\n break;\n }\n case 'deleteContentBackward':\n case 'deleteContentForward':\n case 'deleteWordBackward':\n case 'deleteWordForward':\n case 'deleteHardLineForward':\n case 'deleteHardLineBackward':\n case 'deleteSoftLineForward':\n case 'deleteSoftLineBackward':\n case 'deleteContent':\n case 'deleteByCut':\n case 'deleteCompositionText': {\n if (!range.collapsed && !isSamePosition(start, end)) {\n apply(tokens => tokens.replaceRange(start, end, ''));\n break;\n }\n\n switch (e.inputType) {\n case 'deleteContentBackward': {\n apply(tokens =>\n tokens.delete(start, graphemeSegmenter, TokenFieldValue.Direction.Backward)\n );\n break;\n }\n case 'deleteContentForward':\n apply(tokens =>\n tokens.delete(start, graphemeSegmenter, TokenFieldValue.Direction.Forward)\n );\n break;\n case 'deleteWordBackward': {\n apply(tokens =>\n tokens.delete(start, wordSegmenter, TokenFieldValue.Direction.Backward)\n );\n break;\n }\n case 'deleteWordForward':\n apply(tokens => tokens.delete(start, wordSegmenter, TokenFieldValue.Direction.Forward));\n break;\n case 'deleteHardLineForward':\n case 'deleteSoftLineForward': // TODO: this usually deletes to the nearest *visual* line break rather than a hard break\n apply(tokens => tokens.deleteLine(start, TokenFieldValue.Direction.Forward));\n break;\n case 'deleteHardLineBackward':\n case 'deleteSoftLineBackward':\n apply(tokens => tokens.deleteLine(start, TokenFieldValue.Direction.Backward));\n break;\n }\n break;\n }\n case 'deleteByDrag': {\n apply(tokens => {\n let endOffset =\n start.index === end.index ? end.offset : tokens.segments[start.index].text.length;\n let change = tokens.replaceRange(start, end, '');\n if (\n dropPosition.current &&\n dropPosition.current.index === start.index &&\n dropPosition.current.offset >= start.offset\n ) {\n dropPosition.current.offset -= endOffset - start.offset;\n }\n\n return change;\n });\n break;\n }\n }\n\n e.preventDefault();\n });\n\n let writeClipboardData = (e: ClipboardEvent | DragEvent) => {\n if ('clipboardData' in e) {\n e.preventDefault();\n }\n let selection = getSelection(ref.current!);\n if (!selection) {\n return;\n }\n let [start, end] = selection;\n let slice = value.slice(start, end);\n let dataTransfer = 'clipboardData' in e ? e.clipboardData : e.dataTransfer;\n dataTransfer?.setData(CLIPBOARD_MIME_TYPE, JSON.stringify(slice.segments));\n dataTransfer?.setData('text/plain', slice.toString());\n\n if (e.type === 'cut') {\n apply(tokens => tokens.replaceRange(start, end, '', false));\n }\n };\n\n useEvent(ref, 'copy', writeClipboardData);\n useEvent(ref, 'cut', writeClipboardData);\n useEvent(ref, 'dragstart', writeClipboardData);\n useEvent(ref, 'paste', e => {\n // Safari doesn't pass the custom clipboard data type to beforeinput dataTransfer so we handle it here.\n if (e.clipboardData && e.clipboardData.types.includes(CLIPBOARD_MIME_TYPE)) {\n transferredData.current = parseSegments(e.clipboardData.getData(CLIPBOARD_MIME_TYPE));\n }\n });\n\n // Store the cursor position on drop so we know where to insert when the insertFromDrop event occurs.\n useEvent(ref, 'drop', e => {\n if (typeof document.caretPositionFromPoint === 'function') {\n let pos = document.caretPositionFromPoint(e.clientX, e.clientY);\n if (pos) {\n dropPosition.current = getPosition(ref.current!, pos.offsetNode, pos.offset);\n }\n } else if (typeof document.caretRangeFromPoint === 'function') {\n let range = document.caretRangeFromPoint(e.clientX, e.clientY);\n if (range) {\n dropPosition.current = getPosition(ref.current!, range.startContainer, range.startOffset);\n }\n }\n\n if (e.dataTransfer && e.dataTransfer.types.includes(CLIPBOARD_MIME_TYPE)) {\n transferredData.current = parseSegments(e.dataTransfer.getData(CLIPBOARD_MIME_TYPE));\n }\n });\n\n useSelectionChange(ref, () => {\n if (state.isComposing) {\n return;\n }\n\n value.endCoalescing();\n\n // When the cursor moves next to a token, announce it.\n // Otherwise the screen reader will only announce the first/last character.\n let range = getSelectedRange(ref.current!);\n if (!range) {\n return;\n }\n\n announceToken(value, range);\n\n // Update the selected range in the value.\n state.setValue(value => value.withSelectedRange(range));\n });\n\n // Clear selection on blur.\n useEvent(ref, 'blur', e => {\n if (!e.isTrusted) {\n return;\n }\n\n let selection = window.getSelection();\n if (\n ref.current &&\n selection &&\n selection.containsNode(ref.current, true) &&\n !selection.isCollapsed\n ) {\n selection.removeAllRanges();\n state.setValue(value =>\n value.withSelectedRange(new TokenFieldValue.SelectedRange(value.caretPosition))\n );\n }\n });\n\n // Override the default triple click behavior to ensure that tokens get selected.\n // Some browsers only select the text between tokens instead of the entire line.\n useEvent(ref, 'mousedown', e => {\n if (e.detail === 3) {\n let selection = getSelection(ref.current!);\n if (!selection) {\n return;\n }\n\n let start = value.findLineBoundary(selection[0], TokenFieldValue.Direction.Backward);\n let end = value.findLineBoundary(selection[1], TokenFieldValue.Direction.Forward);\n if (start && end) {\n e.preventDefault();\n setTokenFieldSelection(ref.current!, new TokenFieldValue.SelectedRange(start, end), true);\n }\n }\n });\n\n let moveSelection = (\n direction: 'left' | 'right',\n granularity: 'character' | 'word',\n extend = false\n ) => {\n let selection = window.getSelection();\n if (!selection || selection.rangeCount === 0 || !selection.focusNode || !selection.anchorNode) {\n return false;\n }\n\n // Pressing an arrow with a non-empty selection collapses it to the corresponding edge.\n // The browser handles this natively.\n if (!extend && !selection.isCollapsed) {\n return false;\n }\n\n // Move the caret using the browser's native caret movement (Selection.modify) so that\n // bidirectional text is handled correctly. Repeat until the position actually changes\n // to account for the zero width spaces around tokens.\n let pos = getPosition(ref.current!, selection.focusNode, selection.focusOffset);\n while (true) {\n let {focusNode, focusOffset} = selection;\n selection.modify(extend ? 'extend' : 'move', direction, granularity);\n if (selection.focusNode === focusNode && selection.focusOffset === focusOffset) {\n return false;\n }\n let newPos = getPosition(ref.current!, selection.focusNode, selection.focusOffset);\n if (!isSamePosition(pos, newPos)) {\n return true;\n }\n }\n };\n\n // macOS supports additional keyboard shortcuts for text editing.\n // We need to handle these manually so they behave consistently with tokens.\n // https://support.apple.com/en-us/102650#text\n let macShortcuts: Record<string, () => boolean | void> = isMac()\n ? {\n 'Control+a': () => {\n return shortcuts.Home();\n },\n 'Control+e': () => {\n return shortcuts.End();\n },\n 'Control+f': () => {\n return shortcuts.ArrowRight();\n },\n 'Control+b': () => {\n return shortcuts.ArrowLeft();\n }\n }\n : {};\n\n let mod = isMac() ? 'Meta' : 'Control';\n let wordModKey = isMac() ? 'Alt' : 'Control';\n let shortcuts: Record<string, () => boolean | void> = {\n ...macShortcuts,\n [`${mod}+z`]: () => {\n // If composing, the browser handles undo natively.\n if (state.isComposing) {\n return false;\n }\n apply(state => state.undo());\n },\n [isMac() ? 'Shift+Meta+z' : 'Control+y']: () => {\n if (state.isComposing) {\n return false;\n }\n apply(state => state.redo());\n },\n ArrowLeft: () => {\n return moveSelection('left', 'character');\n },\n [`${wordModKey}+ArrowLeft`]: () => {\n return moveSelection('left', 'word');\n },\n 'Shift+ArrowLeft': () => {\n return moveSelection('left', 'character', true);\n },\n [`Shift+${wordModKey}+ArrowLeft`]: () => {\n return moveSelection('left', 'word', true);\n },\n ArrowRight: () => {\n return moveSelection('right', 'character');\n },\n [`${wordModKey}+ArrowRight`]: () => {\n return moveSelection('right', 'word');\n },\n 'Shift+ArrowRight': () => {\n return moveSelection('right', 'character', true);\n },\n [`Shift+${wordModKey}+ArrowRight`]: () => {\n return moveSelection('right', 'word', true);\n },\n Home: () => {\n // Browsers do not behave consistently when there are tokens.\n let selection = getSelection(ref.current!);\n if (!selection) {\n return false;\n }\n let boundary = value.findLineBoundary(selection[0], TokenFieldValue.Direction.Backward);\n if (boundary) {\n setCursor(ref.current!, boundary, true);\n return true;\n }\n return false;\n },\n End: () => {\n let selection = getSelection(ref.current!);\n if (!selection) {\n return false;\n }\n let boundary = value.findLineBoundary(selection[1], TokenFieldValue.Direction.Forward);\n if (boundary) {\n setCursor(ref.current!, boundary, true);\n return true;\n }\n return false;\n }\n };\n\n // TODO: user provided onKeyDown currently relies on user provided preventDefault to stop submit\n // maybe can have them specify a format like shortcuts and merge into above?\n let {keyboardProps} = useKeyboard({\n isDisabled: isDisabled || isReadOnly,\n onKeyDown: props.onKeyDown,\n onKeyUp: props.onKeyUp,\n shortcuts: shortcuts,\n allowRepeats: true\n });\n\n let {focusableProps} = useFocusable(props, ref);\n let {labelProps, fieldProps, descriptionProps} = useField({\n ...props,\n labelElementType: 'span'\n });\n\n return {\n labelProps: {\n ...labelProps,\n onClick: () => {\n if (!props.isDisabled) {\n ref.current?.focus();\n\n // Show the focus ring so the user knows where focus went\n setInteractionModality('keyboard');\n }\n }\n },\n descriptionProps,\n tokenFieldProps: mergeProps(focusableProps, keyboardProps, fieldProps, {\n onPaste: props.onPaste,\n onCopy: props.onCopy,\n onCut: props.onCut,\n contentEditable: !isDisabled && !isReadOnly,\n suppressContentEditableWarning: true,\n role,\n 'aria-multiline': multiline,\n 'aria-details': ariaDetails,\n 'aria-readonly': isReadOnly,\n 'aria-disabled': isDisabled,\n style: {whiteSpace: 'pre-wrap'}\n })\n };\n}\n\nfunction indexOfNode(node: Node) {\n let index = 0;\n let n: Node | null = node;\n\n while ((n = n.previousSibling)) {\n index++;\n }\n return index;\n}\n\nexport function getSelection(container: Element): [Position, Position] | null {\n let selection = window.getSelection();\n if (!selection || selection.rangeCount === 0) {\n return null;\n }\n let range = selection.getRangeAt(0);\n return rangeToPositions(container, range);\n}\n\nexport function getSelectedRange(container: Element) {\n let selection = window.getSelection();\n if (\n !selection ||\n !selection.anchorNode ||\n !selection.focusNode ||\n !nodeContains(container, selection.anchorNode) ||\n !nodeContains(container, selection.focusNode)\n ) {\n return null;\n }\n let anchor = getPosition(container, selection.anchorNode, selection.anchorOffset, false);\n let current = getPosition(\n container,\n selection.focusNode,\n selection.focusOffset,\n !selection.isCollapsed\n );\n return new TokenFieldValue.SelectedRange(anchor, current);\n}\n\nfunction rangeToPositions(container: Element, range: Range | StaticRange): [Position, Position] {\n let start = getPosition(container, range.startContainer, range.startOffset, false);\n let end = getPosition(container, range.endContainer, range.endOffset, !range.collapsed);\n return [start, end];\n}\n\nfunction getPosition(container: Element, node: Node, offset: number, isRangeEnd = false): Position {\n if (node === container) {\n return {index: offset, offset: 0};\n }\n\n let originalNode = node;\n while (node.parentNode !== container) {\n node = node.parentNode!;\n }\n\n let index = indexOfNode(node);\n if (node.nodeType === Node.ELEMENT_NODE) {\n let tokenNode = node.childNodes[1];\n let atEnd: boolean;\n let endOffset = 0;\n if (originalNode === tokenNode) {\n // Cursor is inside the token.\n atEnd = isRangeEnd || offset > 0;\n } else if (originalNode === node) {\n // Cursor is inside the wrapper element.\n atEnd = offset > 1;\n } else {\n // Cursor is on one of the zero width spaces.\n atEnd = originalNode !== tokenNode.previousSibling;\n // If the offset is greater than 1, the browser is trying to insert text into\n // the zero width space node. This will actually end up in the next text node.\n endOffset = atEnd && offset > 1 ? offset - 1 : 0;\n }\n\n offset = atEnd ? (tokenNode?.textContent?.length ?? 0) : 0;\n\n // Several positions are equivalent due to the zero width spaces around tokens.\n // Normalize offset to the end of the preceding text node, or the beginning of the following node.\n if (offset === 0 && node.previousSibling?.nodeType === Node.TEXT_NODE) {\n index--;\n offset = node.previousSibling?.textContent?.length ?? 0;\n } else if (atEnd) {\n index++;\n offset = endOffset;\n }\n }\n return {index, offset};\n}\n\nlet isProgrammaticSelectionChange = Symbol('isProgrammaticSelectionChange');\n\nfunction setCursor(root: Element, pos: Position, fireEvent = false) {\n setTokenFieldSelection(root, new TokenFieldValue.SelectedRange(pos), fireEvent);\n}\n\nexport function setTokenFieldSelection(\n root: Element,\n selectedRange: SelectedRange,\n fireEvent = false\n) {\n let selection = window.getSelection();\n if (selection) {\n // Use setBaseAndExtent to preserve the selection direction. A plain Range +\n // addRange always produces a forward selection and collapses when the\n // anchor comes after the current position (backward selections).\n let [anchorNode, anchorOffset] = getDOMPosition(root, selectedRange.anchor);\n let [focusNode, focusOffset] = getDOMPosition(root, selectedRange.current);\n root[isProgrammaticSelectionChange] = !fireEvent;\n\n // Only set selection if it has changed, because this can clobber the browser's selection direction.\n if (\n selection.anchorNode !== anchorNode ||\n selection.anchorOffset !== anchorOffset ||\n selection.focusNode !== focusNode ||\n selection.focusOffset !== focusOffset\n ) {\n selection.setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset);\n }\n }\n}\n\n// Calling preventDefault in the beforeinput handler stops the browser from performing its\n// default edit action, which also suppresses its normal behavior of scrolling the caret into\n// view. Recreate that behavior by measuring the caret's position with a Range and\n// scrolling each scrollable ancestor of the field so it is visible.\nfunction scrollCaretIntoView(root: HTMLElement): void {\n let selection = window.getSelection();\n if (\n getInteractionModality() !== 'keyboard' ||\n !selection ||\n selection.rangeCount === 0 ||\n !nodeContains(root, selection.focusNode)\n ) {\n return;\n }\n\n let range = selection.getRangeAt(0);\n let rect = range.getBoundingClientRect();\n\n // A collapsed range doesn't always produce a client rect. This happens for empty lines.\n if (rect.top === 0 && rect.bottom === 0 && rect.left === 0 && rect.right === 0) {\n let node: Node | null = range.endContainer;\n if (node.nodeType === Node.TEXT_NODE && range.endOffset < node.nodeValue!.length) {\n // If we are not at the end of the text node, extend the range to include the next character.\n range = range.cloneRange();\n range.setEnd(node, range.endOffset + 1);\n rect = range.getBoundingClientRect();\n } else if (root.firstChild == null) {\n // If the root has no children, use its rect.\n rect = root.getBoundingClientRect();\n } else {\n // Otherwise find the next sibling element (e.g. trailing <br>) and use its rect in this case.\n let nextSibling = node.nextSibling;\n while (node && node !== root && !nextSibling) {\n node = node.parentNode as Node | null;\n nextSibling = node ? node.nextSibling : null;\n }\n\n if (nextSibling?.nodeType === Node.ELEMENT_NODE) {\n rect = (nextSibling as HTMLElement).getBoundingClientRect();\n }\n }\n }\n\n for (let element of getScrollParents(root, true)) {\n // scrollRectIntoView only scrolls a single scroll parent based on `rect`, which is a\n // snapshot of the caret's position before any scrolling occurs. Scrolling an inner ancestor\n // moves the caret within the viewport, so translate `rect` by however much we just scrolled\n // before moving on to the next (outer) ancestor.\n let scrollParent = element as HTMLElement;\n let beforeTop = scrollParent.scrollTop;\n let beforeLeft = scrollParent.scrollLeft;\n scrollRectIntoView(scrollParent, root, rect, {block: 'nearest', inline: 'nearest'});\n let dy = scrollParent.scrollTop - beforeTop;\n let dx = scrollParent.scrollLeft - beforeLeft;\n if (dy !== 0 || dx !== 0) {\n rect = new DOMRect(rect.x - dx, rect.y - dy, rect.width, rect.height);\n }\n }\n}\n\nexport function tokenFieldPositionToDOMRange(root: Element, pos: Position): Range {\n // Unlike createDOMRange (used for caret/selection placement), this range is only\n // measured via getBoundingClientRect to position things like an autocomplete popover.\n // Place the endpoints inside the token's zero width space wrappers so the range has a\n // valid rect at the token, rather than a collapsed root-level position.\n let range = document.createRange();\n let [startContainer, startOffset] = getDOMRectPosition(root, pos);\n range.setStart(startContainer, startOffset);\n range.setEnd(startContainer, startOffset);\n return range;\n}\n\nfunction getDOMRectPosition(root: Element, pos: Position): [Node, number] {\n let child = root.childNodes[pos.index];\n if (child && child.nodeType === Node.ELEMENT_NODE) {\n // Place the position inside the zero width space wrappers around the token.\n if (pos.offset > 0) {\n return [child.lastChild!, 1];\n } else {\n return [child.firstChild!, 0];\n }\n }\n return getDOMPosition(root, pos);\n}\n\nfunction createDOMRange(root: Element, start: Position, end: Position): Range {\n let range = document.createRange();\n let [startContainer, startOffset] = getDOMPosition(root, start);\n let [endContainer, endOffset] = getDOMPosition(root, end);\n range.setStart(startContainer, startOffset);\n range.setEnd(endContainer, endOffset);\n return range;\n}\n\nfunction getDOMPosition(root: Element, pos: Position): [Node, number] {\n let index = Math.max(0, Math.min(root.childNodes.length, pos.index));\n let child = root.childNodes[index];\n if (!child) {\n return [root, index];\n } else if (child.nodeType === Node.ELEMENT_NODE) {\n // Place the cursor outside the token wrapper element.\n // This is necessary for composition events.\n if (pos.offset > 0) {\n return [root, index + 1];\n } else {\n return [root, index];\n }\n } else {\n let offset = Math.max(0, Math.min(child.textContent?.length ?? 0, pos.offset));\n return [child, offset];\n }\n}\n\nfunction isSamePosition(a: Position, b: Position): boolean {\n return a.index === b.index && a.offset === b.offset;\n}\n\n// Parse and validate segments from clipboard/drag data. Returns null if the data is not valid\n// JSON or does not match the expected shape, so malformed or untrusted data is ignored rather\n// than throwing or being inserted into the field.\nfunction parseSegments(json: string): TokenFieldSegment[] | null {\n try {\n let data = JSON.parse(json);\n if (Array.isArray(data) && data.length > 0 && data.every(isValidSegment)) {\n return data;\n }\n } catch {\n // Ignore invalid clipboard data.\n }\n return null;\n}\n\nfunction isValidSegment(segment: unknown): segment is TokenFieldSegment {\n return (\n typeof segment === 'object' &&\n segment != null &&\n ((segment as TokenFieldSegment).type === 'text' ||\n (segment as TokenFieldSegment).type === 'token') &&\n typeof (segment as TokenFieldSegment).text === 'string'\n );\n}\n\nfunction useSelectionChange(ref: React.RefObject<Element | null>, handler: () => void) {\n useEvent(useRef(typeof document !== 'undefined' ? document : null), 'selectionchange', () => {\n if (ref.current && ref.current[isProgrammaticSelectionChange]) {\n ref.current[isProgrammaticSelectionChange] = false;\n return;\n }\n\n let selection = window.getSelection();\n if (!selection || selection.rangeCount === 0 || !ref.current) {\n return;\n }\n\n let range = selection.getRangeAt(0);\n if (range.intersectsNode(ref.current)) {\n handler();\n }\n });\n}\n\nfunction useMutationTracker(ref: React.RefObject<Element | null>) {\n let mutationTracker = useRef<(() => void) | null>(null);\n\n // Disconnect the mutation observer if the field unmounts mid-composition.\n useLayoutEffect(\n () => () => {\n mutationTracker.current?.();\n mutationTracker.current = null;\n },\n []\n );\n\n return useMemo(\n () => ({\n start() {\n // Android sometimes fires two compositionstart events in a row, without a compositionend.\n // In that case, reuse the existing tracker.\n mutationTracker.current ||= trackMutations(ref.current!);\n },\n stop() {\n mutationTracker.current?.();\n mutationTracker.current = null;\n }\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps - conflicts with compiler\n []\n );\n}\n\n// Tracks mutations to the DOM until the returned function is called,\n// at which point the mutations are reverted.\nfunction trackMutations(element: Element) {\n let mutations: MutationRecord[] = [];\n let observer = new MutationObserver(records => {\n mutations.push(...records);\n });\n\n observer.observe(element, {\n childList: true,\n subtree: true,\n characterData: true,\n characterDataOldValue: true\n });\n\n return () => {\n mutations.push(...observer.takeRecords());\n observer.disconnect();\n\n for (let record of mutations.reverse()) {\n switch (record.type) {\n case 'childList':\n for (let node of record.removedNodes) {\n record.target.insertBefore(node, record.nextSibling);\n }\n for (let node of record.addedNodes) {\n record.target.removeChild(node);\n }\n break;\n case 'characterData':\n record.target.nodeValue = record.oldValue;\n break;\n }\n }\n };\n}\n\nfunction announceToken(value: TokenFieldValue, range = value.selectedRange) {\n if (range.isCollapsed) {\n // Announce adjacent tokens.\n let segment = value.segments[range.current.index];\n if (segment && segment.type !== 'token') {\n if (range.current.offset === 0) {\n segment = value.segments[range.current.index - 1];\n } else if (range.current.offset === segment.text.length) {\n segment = value.segments[range.current.index + 1];\n }\n }\n if (segment?.type === 'token') {\n announce(segment.text, 'assertive');\n }\n } else {\n // Announce token if it is the only thing selected.\n let selected = value.slice(range.start, range.end).segments;\n if (selected.length === 1 && selected[0].type === 'token') {\n announce(selected[0].text, 'assertive');\n }\n }\n}\n"],"names":[],"version":3,"file":"useTokenField.cjs.map"}
@@ -1,9 +1,11 @@
1
1
  import {announce as $a53edfcc12185fd0$export$a9b970dcc4ae71a9} from "../live-announcer/LiveAnnouncer.js";
2
2
  import {getActiveElement as $d8ac7ed472840322$export$cd4e5573fbe2b576, nodeContains as $d8ac7ed472840322$export$4282f70798064fe0} from "../utils/shadowdom/DOMFunctions.js";
3
+ import {getInteractionModality as $b50b1cc8a843ace7$export$630ff653c5ada6a9, setInteractionModality as $b50b1cc8a843ace7$export$8397ddfc504fdb9a} from "../interactions/useFocusVisible.js";
3
4
  import {getOwnerDocument as $cc3c3666b64debad$export$b204af158042fbac} from "../utils/domHelpers.js";
5
+ import {getScrollParents as $3d3c16277aab2036$export$94ed1c92c7beeb22} from "../utils/getScrollParents.js";
4
6
  import {isMac as $d5a2be505488529f$export$9ac100e40613ea10} from "../utils/platform.js";
5
7
  import {mergeProps as $64c36edd757dfa16$export$9d1611c77c2fe928} from "../utils/mergeProps.js";
6
- import {setInteractionModality as $b50b1cc8a843ace7$export$8397ddfc504fdb9a} from "../interactions/useFocusVisible.js";
8
+ import {scrollRectIntoView as $6507765bd7f5ad94$export$f064fd83a2c6e9ca} from "../utils/scrollIntoView.js";
7
9
  import {useEvent as $c3cab330536504ec$export$90fc3a17d93f704c} from "../utils/useEvent.js";
8
10
  import {useField as $b5d79d79d9c34c91$export$294aa081a6c6f55d} from "../label/useField.js";
9
11
  import {useFocusable as $088f27a386bc4a8f$export$4c014de7c8940b4c} from "../interactions/useFocusable.js";
@@ -37,6 +39,8 @@ import {TokenFieldValue as $88wHG$TokenFieldValue} from "react-stately/useTokenF
37
39
 
38
40
 
39
41
 
42
+
43
+
40
44
  const $6b58de437c931efd$var$CLIPBOARD_MIME_TYPE = 'application/vnd.react-aria.tokens+json';
41
45
  function $6b58de437c931efd$export$adf3c8de3c7afc8b(props, state, ref) {
42
46
  let { role: role = 'textbox', allowsNewlines: multiline = false, isReadOnly: isReadOnly = false, isDisabled: isDisabled = false, 'aria-details': ariaDetails } = props;
@@ -110,6 +114,9 @@ function $6b58de437c931efd$export$adf3c8de3c7afc8b(props, state, ref) {
110
114
  if (ref.current === (0, $d8ac7ed472840322$export$cd4e5573fbe2b576)((0, $cc3c3666b64debad$export$b204af158042fbac)(ref.current))) {
111
115
  $6b58de437c931efd$export$9cafaa09e78b6e4b(ref.current, value.selectedRange);
112
116
  $6b58de437c931efd$var$announceToken(value);
117
+ // We call preventDefault in the beforeinput handler below, which also prevents the
118
+ // browser's default behavior of scrolling the caret into view. Do it ourselves instead.
119
+ $6b58de437c931efd$var$scrollCaretIntoView(ref.current);
113
120
  }
114
121
  selectedRange.current = value.selectedRange;
115
122
  }
@@ -260,7 +267,7 @@ function $6b58de437c931efd$export$adf3c8de3c7afc8b(props, state, ref) {
260
267
  (0, $c3cab330536504ec$export$90fc3a17d93f704c)(ref, 'blur', (e)=>{
261
268
  if (!e.isTrusted) return;
262
269
  let selection = window.getSelection();
263
- if (ref.current && selection && selection.containsNode(ref.current, true)) {
270
+ if (ref.current && selection && selection.containsNode(ref.current, true) && !selection.isCollapsed) {
264
271
  selection.removeAllRanges();
265
272
  state.setValue((value)=>value.withSelectedRange(new (0, $88wHG$TokenFieldValue).SelectedRange(value.caretPosition)));
266
273
  }
@@ -504,6 +511,52 @@ function $6b58de437c931efd$export$9cafaa09e78b6e4b(root, selectedRange, fireEven
504
511
  if (selection.anchorNode !== anchorNode || selection.anchorOffset !== anchorOffset || selection.focusNode !== focusNode || selection.focusOffset !== focusOffset) selection.setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset);
505
512
  }
506
513
  }
514
+ // Calling preventDefault in the beforeinput handler stops the browser from performing its
515
+ // default edit action, which also suppresses its normal behavior of scrolling the caret into
516
+ // view. Recreate that behavior by measuring the caret's position with a Range and
517
+ // scrolling each scrollable ancestor of the field so it is visible.
518
+ function $6b58de437c931efd$var$scrollCaretIntoView(root) {
519
+ let selection = window.getSelection();
520
+ if ((0, $b50b1cc8a843ace7$export$630ff653c5ada6a9)() !== 'keyboard' || !selection || selection.rangeCount === 0 || !(0, $d8ac7ed472840322$export$4282f70798064fe0)(root, selection.focusNode)) return;
521
+ let range = selection.getRangeAt(0);
522
+ let rect = range.getBoundingClientRect();
523
+ // A collapsed range doesn't always produce a client rect. This happens for empty lines.
524
+ if (rect.top === 0 && rect.bottom === 0 && rect.left === 0 && rect.right === 0) {
525
+ let node = range.endContainer;
526
+ if (node.nodeType === Node.TEXT_NODE && range.endOffset < node.nodeValue.length) {
527
+ // If we are not at the end of the text node, extend the range to include the next character.
528
+ range = range.cloneRange();
529
+ range.setEnd(node, range.endOffset + 1);
530
+ rect = range.getBoundingClientRect();
531
+ } else if (root.firstChild == null) // If the root has no children, use its rect.
532
+ rect = root.getBoundingClientRect();
533
+ else {
534
+ // Otherwise find the next sibling element (e.g. trailing <br>) and use its rect in this case.
535
+ let nextSibling = node.nextSibling;
536
+ while(node && node !== root && !nextSibling){
537
+ node = node.parentNode;
538
+ nextSibling = node ? node.nextSibling : null;
539
+ }
540
+ if ((nextSibling === null || nextSibling === void 0 ? void 0 : nextSibling.nodeType) === Node.ELEMENT_NODE) rect = nextSibling.getBoundingClientRect();
541
+ }
542
+ }
543
+ for (let element of (0, $3d3c16277aab2036$export$94ed1c92c7beeb22)(root, true)){
544
+ // scrollRectIntoView only scrolls a single scroll parent based on `rect`, which is a
545
+ // snapshot of the caret's position before any scrolling occurs. Scrolling an inner ancestor
546
+ // moves the caret within the viewport, so translate `rect` by however much we just scrolled
547
+ // before moving on to the next (outer) ancestor.
548
+ let scrollParent = element;
549
+ let beforeTop = scrollParent.scrollTop;
550
+ let beforeLeft = scrollParent.scrollLeft;
551
+ (0, $6507765bd7f5ad94$export$f064fd83a2c6e9ca)(scrollParent, root, rect, {
552
+ block: 'nearest',
553
+ inline: 'nearest'
554
+ });
555
+ let dy = scrollParent.scrollTop - beforeTop;
556
+ let dx = scrollParent.scrollLeft - beforeLeft;
557
+ if (dy !== 0 || dx !== 0) rect = new DOMRect(rect.x - dx, rect.y - dy, rect.width, rect.height);
558
+ }
559
+ }
507
560
  function $6b58de437c931efd$export$30729a8cd0694a7c(root, pos) {
508
561
  // Unlike createDOMRange (used for caret/selection placement), this range is only
509
562
  // measured via getBoundingClientRect to position things like an autocomplete popover.