react-aria 3.51.0 → 3.52.0
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/exports/index.cjs +1 -0
- package/dist/exports/index.cjs.map +1 -1
- package/dist/exports/index.js +2 -2
- package/dist/exports/index.js.map +1 -1
- package/dist/exports/index.mjs +2 -2
- package/dist/exports/index.mjs.map +1 -1
- package/dist/exports/private/utils/domHelpers.cjs +1 -0
- package/dist/exports/private/utils/domHelpers.cjs.map +1 -1
- package/dist/exports/private/utils/domHelpers.js +2 -2
- package/dist/exports/private/utils/domHelpers.js.map +1 -1
- package/dist/exports/private/utils/domHelpers.mjs +2 -2
- package/dist/exports/private/utils/domHelpers.mjs.map +1 -1
- package/dist/exports/useFocusVisible.cjs +1 -0
- package/dist/exports/useFocusVisible.cjs.map +1 -1
- package/dist/exports/useFocusVisible.js +2 -2
- package/dist/exports/useFocusVisible.js.map +1 -1
- package/dist/exports/useFocusVisible.mjs +2 -2
- package/dist/exports/useFocusVisible.mjs.map +1 -1
- package/dist/private/actiongroup/useActionGroup.cjs +3 -1
- package/dist/private/actiongroup/useActionGroup.cjs.map +1 -1
- package/dist/private/actiongroup/useActionGroup.js +3 -1
- package/dist/private/actiongroup/useActionGroup.js.map +1 -1
- package/dist/private/actiongroup/useActionGroup.mjs +3 -1
- package/dist/private/actiongroup/useActionGroup.mjs.map +1 -1
- package/dist/private/calendar/useRangeCalendar.cjs +1 -1
- package/dist/private/calendar/useRangeCalendar.cjs.map +1 -1
- package/dist/private/calendar/useRangeCalendar.js +2 -2
- package/dist/private/calendar/useRangeCalendar.js.map +1 -1
- package/dist/private/calendar/useRangeCalendar.mjs +2 -2
- package/dist/private/calendar/useRangeCalendar.mjs.map +1 -1
- package/dist/private/color/useColorField.cjs +26 -4
- package/dist/private/color/useColorField.cjs.map +1 -1
- package/dist/private/color/useColorField.js +26 -4
- package/dist/private/color/useColorField.js.map +1 -1
- package/dist/private/color/useColorField.mjs +26 -4
- package/dist/private/color/useColorField.mjs.map +1 -1
- package/dist/private/combobox/useComboBox.cjs +1 -1
- package/dist/private/combobox/useComboBox.cjs.map +1 -1
- package/dist/private/combobox/useComboBox.js +1 -1
- package/dist/private/combobox/useComboBox.js.map +1 -1
- package/dist/private/combobox/useComboBox.mjs +1 -1
- package/dist/private/combobox/useComboBox.mjs.map +1 -1
- package/dist/private/focus/FocusScope.cjs +7 -2
- package/dist/private/focus/FocusScope.cjs.map +1 -1
- package/dist/private/focus/FocusScope.js +7 -2
- package/dist/private/focus/FocusScope.js.map +1 -1
- package/dist/private/focus/FocusScope.mjs +7 -2
- package/dist/private/focus/FocusScope.mjs.map +1 -1
- package/dist/private/interactions/useFocusVisible.cjs +15 -3
- package/dist/private/interactions/useFocusVisible.cjs.map +1 -1
- package/dist/private/interactions/useFocusVisible.js +15 -3
- package/dist/private/interactions/useFocusVisible.js.map +1 -1
- package/dist/private/interactions/useFocusVisible.mjs +15 -3
- package/dist/private/interactions/useFocusVisible.mjs.map +1 -1
- package/dist/private/interactions/utils.cjs +23 -13
- package/dist/private/interactions/utils.cjs.map +1 -1
- package/dist/private/interactions/utils.js +25 -15
- package/dist/private/interactions/utils.js.map +1 -1
- package/dist/private/interactions/utils.mjs +25 -15
- package/dist/private/interactions/utils.mjs.map +1 -1
- package/dist/private/overlays/calculatePosition.cjs +3 -2
- package/dist/private/overlays/calculatePosition.cjs.map +1 -1
- package/dist/private/overlays/calculatePosition.js +5 -2
- package/dist/private/overlays/calculatePosition.js.map +1 -1
- package/dist/private/overlays/calculatePosition.mjs +3 -2
- package/dist/private/overlays/calculatePosition.mjs.map +1 -1
- package/dist/private/overlays/useOverlayPosition.cjs +5 -0
- package/dist/private/overlays/useOverlayPosition.cjs.map +1 -1
- package/dist/private/overlays/useOverlayPosition.js +6 -1
- package/dist/private/overlays/useOverlayPosition.js.map +1 -1
- package/dist/private/overlays/useOverlayPosition.mjs +6 -1
- package/dist/private/overlays/useOverlayPosition.mjs.map +1 -1
- package/dist/private/overlays/usePreventScroll.cjs +27 -35
- package/dist/private/overlays/usePreventScroll.cjs.map +1 -1
- package/dist/private/overlays/usePreventScroll.js +27 -35
- package/dist/private/overlays/usePreventScroll.js.map +1 -1
- package/dist/private/overlays/usePreventScroll.mjs +27 -35
- package/dist/private/overlays/usePreventScroll.mjs.map +1 -1
- package/dist/private/selection/useSelectableCollection.cjs +1 -0
- package/dist/private/selection/useSelectableCollection.cjs.map +1 -1
- package/dist/private/selection/useSelectableCollection.js +1 -0
- package/dist/private/selection/useSelectableCollection.js.map +1 -1
- package/dist/private/selection/useSelectableCollection.mjs +1 -0
- package/dist/private/selection/useSelectableCollection.mjs.map +1 -1
- package/dist/private/tabs/TabsKeyboardDelegate.cjs +3 -1
- package/dist/private/tabs/TabsKeyboardDelegate.cjs.map +1 -1
- package/dist/private/tabs/TabsKeyboardDelegate.js +3 -1
- package/dist/private/tabs/TabsKeyboardDelegate.js.map +1 -1
- package/dist/private/tabs/TabsKeyboardDelegate.mjs +3 -1
- package/dist/private/tabs/TabsKeyboardDelegate.mjs.map +1 -1
- package/dist/private/tokenfield/useToken.cjs +19 -4
- package/dist/private/tokenfield/useToken.cjs.map +1 -1
- package/dist/private/tokenfield/useToken.js +20 -4
- package/dist/private/tokenfield/useToken.js.map +1 -1
- package/dist/private/tokenfield/useToken.mjs +19 -4
- package/dist/private/tokenfield/useToken.mjs.map +1 -1
- package/dist/private/tokenfield/useTokenField.cjs +118 -42
- package/dist/private/tokenfield/useTokenField.cjs.map +1 -1
- package/dist/private/tokenfield/useTokenField.js +121 -44
- package/dist/private/tokenfield/useTokenField.js.map +1 -1
- package/dist/private/tokenfield/useTokenField.mjs +119 -43
- package/dist/private/tokenfield/useTokenField.mjs.map +1 -1
- package/dist/private/utils/domHelpers.cjs +21 -0
- package/dist/private/utils/domHelpers.cjs.map +1 -1
- package/dist/private/utils/domHelpers.js +20 -1
- package/dist/private/utils/domHelpers.js.map +1 -1
- package/dist/private/utils/domHelpers.mjs +20 -1
- package/dist/private/utils/domHelpers.mjs.map +1 -1
- package/dist/private/utils/getMetaValue.cjs +36 -0
- package/dist/private/utils/getMetaValue.cjs.map +1 -0
- package/dist/private/utils/getMetaValue.js +31 -0
- package/dist/private/utils/getMetaValue.js.map +1 -0
- package/dist/private/utils/getMetaValue.mjs +31 -0
- package/dist/private/utils/getMetaValue.mjs.map +1 -0
- package/dist/private/utils/getNonce.cjs +6 -10
- package/dist/private/utils/getNonce.cjs.map +1 -1
- package/dist/private/utils/getNonce.js +7 -11
- package/dist/private/utils/getNonce.js.map +1 -1
- package/dist/private/utils/getNonce.mjs +7 -11
- package/dist/private/utils/getNonce.mjs.map +1 -1
- package/dist/private/utils/useEvent.cjs +7 -9
- package/dist/private/utils/useEvent.cjs.map +1 -1
- package/dist/private/utils/useEvent.js +7 -9
- package/dist/private/utils/useEvent.js.map +1 -1
- package/dist/private/utils/useEvent.mjs +7 -9
- package/dist/private/utils/useEvent.mjs.map +1 -1
- package/dist/types/exports/index.d.ts +2 -2
- package/dist/types/exports/private/utils/domHelpers.d.ts +1 -1
- package/dist/types/exports/useFocusVisible.d.ts +2 -1
- package/dist/types/src/tokenfield/useTokenField.d.ts +3 -2
- package/dist/types/src/utils/domHelpers.d.ts +6 -2
- package/dist/types/src/utils/getMetaValue.d.ts +7 -0
- package/dist/types/src/utils/useEvent.d.ts +2 -2
- package/dist/types/src/virtualizer/Virtualizer.d.ts +3 -3
- package/package.json +6 -5
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {announce as $a46cf152bb926da5$export$a9b970dcc4ae71a9} from "../live-announcer/LiveAnnouncer.mjs";
|
|
2
|
-
import {getActiveElement as $23f2114a1b82827e$export$cd4e5573fbe2b576} from "../utils/shadowdom/DOMFunctions.mjs";
|
|
2
|
+
import {getActiveElement as $23f2114a1b82827e$export$cd4e5573fbe2b576, nodeContains as $23f2114a1b82827e$export$4282f70798064fe0} from "../utils/shadowdom/DOMFunctions.mjs";
|
|
3
3
|
import {getOwnerDocument as $d447af545b77c9f1$export$b204af158042fbac} from "../utils/domHelpers.mjs";
|
|
4
4
|
import {isMac as $2add3ce32c6007eb$export$9ac100e40613ea10} from "../utils/platform.mjs";
|
|
5
5
|
import {mergeProps as $bbaa08b3cd72f041$export$9d1611c77c2fe928} from "../utils/mergeProps.mjs";
|
|
@@ -102,21 +102,27 @@ function $ae4a1f75a9bc78bb$export$adf3c8de3c7afc8b(props, state, ref) {
|
|
|
102
102
|
if (state.isComposing && value !== nextValue.current) stopComposition();
|
|
103
103
|
nextValue.current = value;
|
|
104
104
|
});
|
|
105
|
-
let
|
|
105
|
+
let selectedRange = (0, $v4J1t$useRef)(null);
|
|
106
106
|
(0, $c4867b2f328c2698$export$e5c5a5f917a5871c)(()=>{
|
|
107
|
-
if (ref.current &&
|
|
107
|
+
if (ref.current && !state.isComposing && value.selectedRange !== selectedRange.current) {
|
|
108
108
|
// Only move the caret when the field is already focused.
|
|
109
|
-
if (ref.current === (0, $23f2114a1b82827e$export$cd4e5573fbe2b576)((0, $d447af545b77c9f1$export$b204af158042fbac)(ref.current)))
|
|
110
|
-
|
|
109
|
+
if (ref.current === (0, $23f2114a1b82827e$export$cd4e5573fbe2b576)((0, $d447af545b77c9f1$export$b204af158042fbac)(ref.current))) {
|
|
110
|
+
$ae4a1f75a9bc78bb$export$9cafaa09e78b6e4b(ref.current, value.selectedRange);
|
|
111
|
+
$ae4a1f75a9bc78bb$var$announceToken(value);
|
|
112
|
+
}
|
|
113
|
+
selectedRange.current = value.selectedRange;
|
|
111
114
|
}
|
|
112
115
|
});
|
|
113
116
|
// Handle text editing commands and prevent browser default behavior.
|
|
114
117
|
(0, $600b3cf69ae46262$export$90fc3a17d93f704c)(ref, 'beforeinput', (e)=>{
|
|
115
118
|
// Android sometimes doesn't fire a compositionend event before a regular input event.
|
|
116
119
|
if (state.isComposing && !e.isComposing) stopComposition();
|
|
117
|
-
let
|
|
118
|
-
if (!
|
|
119
|
-
|
|
120
|
+
let range = e.getTargetRanges()[0];
|
|
121
|
+
if (!range) {
|
|
122
|
+
let selection = window.getSelection();
|
|
123
|
+
if (!selection || selection.rangeCount === 0) return;
|
|
124
|
+
range = selection.getRangeAt(0);
|
|
125
|
+
}
|
|
120
126
|
let [start, end] = $ae4a1f75a9bc78bb$var$rangeToPositions(ref.current, range);
|
|
121
127
|
// https://www.w3.org/TR/input-events-2/#interface-InputEvent-Attributes
|
|
122
128
|
switch(e.inputType){
|
|
@@ -170,7 +176,7 @@ function $ae4a1f75a9bc78bb$export$adf3c8de3c7afc8b(props, state, ref) {
|
|
|
170
176
|
case 'deleteContent':
|
|
171
177
|
case 'deleteByCut':
|
|
172
178
|
case 'deleteCompositionText':
|
|
173
|
-
if (!range.collapsed) {
|
|
179
|
+
if (!range.collapsed && !$ae4a1f75a9bc78bb$var$isSamePosition(start, end)) {
|
|
174
180
|
apply((tokens)=>tokens.replaceRange(start, end, ''));
|
|
175
181
|
break;
|
|
176
182
|
}
|
|
@@ -242,15 +248,19 @@ function $ae4a1f75a9bc78bb$export$adf3c8de3c7afc8b(props, state, ref) {
|
|
|
242
248
|
value.endCoalescing();
|
|
243
249
|
// When the cursor moves next to a token, announce it.
|
|
244
250
|
// Otherwise the screen reader will only announce the first/last character.
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
251
|
+
let range = $ae4a1f75a9bc78bb$export$6ec3e5953919831d(ref.current);
|
|
252
|
+
if (!range) return;
|
|
253
|
+
$ae4a1f75a9bc78bb$var$announceToken(value, range);
|
|
254
|
+
// Update the selected range in the value.
|
|
255
|
+
state.setValue((value)=>value.withSelectedRange(range));
|
|
256
|
+
});
|
|
257
|
+
// Clear selection on blur.
|
|
258
|
+
(0, $600b3cf69ae46262$export$90fc3a17d93f704c)(ref, 'blur', (e)=>{
|
|
259
|
+
if (!e.isTrusted) return;
|
|
260
|
+
let selection = window.getSelection();
|
|
261
|
+
if (ref.current && selection && selection.containsNode(ref.current, true)) {
|
|
262
|
+
selection.removeAllRanges();
|
|
263
|
+
state.setValue((value)=>value.withSelectedRange(new (0, $v4J1t$TokenFieldValue).SelectedRange(value.caretPosition)));
|
|
254
264
|
}
|
|
255
265
|
});
|
|
256
266
|
// Override the default triple click behavior to ensure that tokens get selected.
|
|
@@ -263,7 +273,7 @@ function $ae4a1f75a9bc78bb$export$adf3c8de3c7afc8b(props, state, ref) {
|
|
|
263
273
|
let end = value.findLineBoundary(selection[1], (0, $v4J1t$TokenFieldValue).Direction.Forward);
|
|
264
274
|
if (start && end) {
|
|
265
275
|
e.preventDefault();
|
|
266
|
-
$ae4a1f75a9bc78bb$export$9cafaa09e78b6e4b(ref.current, start, end, true);
|
|
276
|
+
$ae4a1f75a9bc78bb$export$9cafaa09e78b6e4b(ref.current, new (0, $v4J1t$TokenFieldValue).SelectedRange(start, end), true);
|
|
267
277
|
}
|
|
268
278
|
}
|
|
269
279
|
});
|
|
@@ -416,15 +426,22 @@ function $ae4a1f75a9bc78bb$export$ca798a7e6e94638c(container) {
|
|
|
416
426
|
let range = selection.getRangeAt(0);
|
|
417
427
|
return $ae4a1f75a9bc78bb$var$rangeToPositions(container, range);
|
|
418
428
|
}
|
|
429
|
+
function $ae4a1f75a9bc78bb$export$6ec3e5953919831d(container) {
|
|
430
|
+
let selection = window.getSelection();
|
|
431
|
+
if (!selection || !selection.anchorNode || !selection.focusNode || !(0, $23f2114a1b82827e$export$4282f70798064fe0)(container, selection.anchorNode) || !(0, $23f2114a1b82827e$export$4282f70798064fe0)(container, selection.focusNode)) return null;
|
|
432
|
+
let anchor = $ae4a1f75a9bc78bb$var$getPosition(container, selection.anchorNode, selection.anchorOffset, false);
|
|
433
|
+
let current = $ae4a1f75a9bc78bb$var$getPosition(container, selection.focusNode, selection.focusOffset, !selection.isCollapsed);
|
|
434
|
+
return new (0, $v4J1t$TokenFieldValue).SelectedRange(anchor, current);
|
|
435
|
+
}
|
|
419
436
|
function $ae4a1f75a9bc78bb$var$rangeToPositions(container, range) {
|
|
420
|
-
let start = $ae4a1f75a9bc78bb$var$getPosition(container, range.startContainer, range.startOffset);
|
|
421
|
-
let end = $ae4a1f75a9bc78bb$var$getPosition(container, range.endContainer, range.endOffset);
|
|
437
|
+
let start = $ae4a1f75a9bc78bb$var$getPosition(container, range.startContainer, range.startOffset, false);
|
|
438
|
+
let end = $ae4a1f75a9bc78bb$var$getPosition(container, range.endContainer, range.endOffset, !range.collapsed);
|
|
422
439
|
return [
|
|
423
440
|
start,
|
|
424
441
|
end
|
|
425
442
|
];
|
|
426
443
|
}
|
|
427
|
-
function $ae4a1f75a9bc78bb$var$getPosition(container, node, offset) {
|
|
444
|
+
function $ae4a1f75a9bc78bb$var$getPosition(container, node, offset, isRangeEnd = false) {
|
|
428
445
|
if (node === container) return {
|
|
429
446
|
index: offset,
|
|
430
447
|
offset: 0
|
|
@@ -437,7 +454,7 @@ function $ae4a1f75a9bc78bb$var$getPosition(container, node, offset) {
|
|
|
437
454
|
let atEnd;
|
|
438
455
|
let endOffset = 0;
|
|
439
456
|
if (originalNode === tokenNode) // Cursor is inside the token.
|
|
440
|
-
atEnd = offset > 0;
|
|
457
|
+
atEnd = isRangeEnd || offset > 0;
|
|
441
458
|
else if (originalNode === node) // Cursor is inside the wrapper element.
|
|
442
459
|
atEnd = offset > 1;
|
|
443
460
|
else {
|
|
@@ -465,37 +482,81 @@ function $ae4a1f75a9bc78bb$var$getPosition(container, node, offset) {
|
|
|
465
482
|
}
|
|
466
483
|
let $ae4a1f75a9bc78bb$var$isProgrammaticSelectionChange = Symbol('isProgrammaticSelectionChange');
|
|
467
484
|
function $ae4a1f75a9bc78bb$var$setCursor(root, pos, fireEvent = false) {
|
|
468
|
-
$ae4a1f75a9bc78bb$export$9cafaa09e78b6e4b(root,
|
|
485
|
+
$ae4a1f75a9bc78bb$export$9cafaa09e78b6e4b(root, new (0, $v4J1t$TokenFieldValue).SelectedRange(pos), fireEvent);
|
|
469
486
|
}
|
|
470
|
-
function $ae4a1f75a9bc78bb$export$9cafaa09e78b6e4b(root,
|
|
487
|
+
function $ae4a1f75a9bc78bb$export$9cafaa09e78b6e4b(root, selectedRange, fireEvent = false) {
|
|
471
488
|
let selection = window.getSelection();
|
|
472
489
|
if (selection) {
|
|
473
|
-
|
|
490
|
+
// Use setBaseAndExtent to preserve the selection direction. A plain Range +
|
|
491
|
+
// addRange always produces a forward selection and collapses when the
|
|
492
|
+
// anchor comes after the current position (backward selections).
|
|
493
|
+
let [anchorNode, anchorOffset] = $ae4a1f75a9bc78bb$var$getDOMPosition(root, selectedRange.anchor);
|
|
494
|
+
let [focusNode, focusOffset] = $ae4a1f75a9bc78bb$var$getDOMPosition(root, selectedRange.current);
|
|
474
495
|
root[$ae4a1f75a9bc78bb$var$isProgrammaticSelectionChange] = !fireEvent;
|
|
475
|
-
selection.
|
|
476
|
-
selection.
|
|
496
|
+
// Only set selection if it has changed, because this can clobber the browser's selection direction.
|
|
497
|
+
if (selection.anchorNode !== anchorNode || selection.anchorOffset !== anchorOffset || selection.focusNode !== focusNode || selection.focusOffset !== focusOffset) selection.setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset);
|
|
477
498
|
}
|
|
478
499
|
}
|
|
479
500
|
function $ae4a1f75a9bc78bb$export$30729a8cd0694a7c(root, pos) {
|
|
480
|
-
|
|
501
|
+
// Unlike createDOMRange (used for caret/selection placement), this range is only
|
|
502
|
+
// measured via getBoundingClientRect to position things like an autocomplete popover.
|
|
503
|
+
// Place the endpoints inside the token's zero width space wrappers so the range has a
|
|
504
|
+
// valid rect at the token, rather than a collapsed root-level position.
|
|
505
|
+
let range = document.createRange();
|
|
506
|
+
let [startContainer, startOffset] = $ae4a1f75a9bc78bb$var$getDOMRectPosition(root, pos);
|
|
507
|
+
range.setStart(startContainer, startOffset);
|
|
508
|
+
range.setEnd(startContainer, startOffset);
|
|
509
|
+
return range;
|
|
510
|
+
}
|
|
511
|
+
function $ae4a1f75a9bc78bb$var$getDOMRectPosition(root, pos) {
|
|
512
|
+
let child = root.childNodes[pos.index];
|
|
513
|
+
if (child && child.nodeType === Node.ELEMENT_NODE) {
|
|
514
|
+
// Place the position inside the zero width space wrappers around the token.
|
|
515
|
+
if (pos.offset > 0) return [
|
|
516
|
+
child.lastChild,
|
|
517
|
+
1
|
|
518
|
+
];
|
|
519
|
+
else return [
|
|
520
|
+
child.firstChild,
|
|
521
|
+
0
|
|
522
|
+
];
|
|
523
|
+
}
|
|
524
|
+
return $ae4a1f75a9bc78bb$var$getDOMPosition(root, pos);
|
|
481
525
|
}
|
|
482
526
|
function $ae4a1f75a9bc78bb$var$createDOMRange(root, start, end) {
|
|
483
527
|
let range = document.createRange();
|
|
484
|
-
let
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
if (start.offset > 0) range.setStartAfter(startChild);
|
|
489
|
-
else range.setStartBefore(startChild);
|
|
490
|
-
} else range.setStart(startChild, start.offset);
|
|
491
|
-
let endChild = root.childNodes[end.index];
|
|
492
|
-
if (!endChild) range.setEnd(root, Math.min(root.childNodes.length, end.index));
|
|
493
|
-
else if (endChild.nodeType === Node.ELEMENT_NODE) {
|
|
494
|
-
if (end.offset > 0) range.setEndAfter(endChild);
|
|
495
|
-
else range.setEndBefore(endChild);
|
|
496
|
-
} else range.setEnd(endChild, end.offset);
|
|
528
|
+
let [startContainer, startOffset] = $ae4a1f75a9bc78bb$var$getDOMPosition(root, start);
|
|
529
|
+
let [endContainer, endOffset] = $ae4a1f75a9bc78bb$var$getDOMPosition(root, end);
|
|
530
|
+
range.setStart(startContainer, startOffset);
|
|
531
|
+
range.setEnd(endContainer, endOffset);
|
|
497
532
|
return range;
|
|
498
533
|
}
|
|
534
|
+
function $ae4a1f75a9bc78bb$var$getDOMPosition(root, pos) {
|
|
535
|
+
let index = Math.max(0, Math.min(root.childNodes.length, pos.index));
|
|
536
|
+
let child = root.childNodes[index];
|
|
537
|
+
if (!child) return [
|
|
538
|
+
root,
|
|
539
|
+
index
|
|
540
|
+
];
|
|
541
|
+
else if (child.nodeType === Node.ELEMENT_NODE) {
|
|
542
|
+
// Place the cursor outside the token wrapper element.
|
|
543
|
+
// This is necessary for composition events.
|
|
544
|
+
if (pos.offset > 0) return [
|
|
545
|
+
root,
|
|
546
|
+
index + 1
|
|
547
|
+
];
|
|
548
|
+
else return [
|
|
549
|
+
root,
|
|
550
|
+
index
|
|
551
|
+
];
|
|
552
|
+
} else {
|
|
553
|
+
let offset = Math.max(0, Math.min(child.textContent?.length ?? 0, pos.offset));
|
|
554
|
+
return [
|
|
555
|
+
child,
|
|
556
|
+
offset
|
|
557
|
+
];
|
|
558
|
+
}
|
|
559
|
+
}
|
|
499
560
|
function $ae4a1f75a9bc78bb$var$isSamePosition(a, b) {
|
|
500
561
|
return a.index === b.index && a.offset === b.offset;
|
|
501
562
|
}
|
|
@@ -573,7 +634,22 @@ function $ae4a1f75a9bc78bb$var$trackMutations(element) {
|
|
|
573
634
|
}
|
|
574
635
|
};
|
|
575
636
|
}
|
|
637
|
+
function $ae4a1f75a9bc78bb$var$announceToken(value, range = value.selectedRange) {
|
|
638
|
+
if (range.isCollapsed) {
|
|
639
|
+
// Announce adjacent tokens.
|
|
640
|
+
let segment = value.segments[range.current.index];
|
|
641
|
+
if (segment && segment.type !== 'token') {
|
|
642
|
+
if (range.current.offset === 0) segment = value.segments[range.current.index - 1];
|
|
643
|
+
else if (range.current.offset === segment.text.length) segment = value.segments[range.current.index + 1];
|
|
644
|
+
}
|
|
645
|
+
if (segment?.type === 'token') (0, $a46cf152bb926da5$export$a9b970dcc4ae71a9)(segment.text, 'assertive');
|
|
646
|
+
} else {
|
|
647
|
+
// Announce token if it is the only thing selected.
|
|
648
|
+
let selected = value.slice(range.start, range.end).segments;
|
|
649
|
+
if (selected.length === 1 && selected[0].type === 'token') (0, $a46cf152bb926da5$export$a9b970dcc4ae71a9)(selected[0].text, 'assertive');
|
|
650
|
+
}
|
|
651
|
+
}
|
|
576
652
|
|
|
577
653
|
|
|
578
|
-
export {$ae4a1f75a9bc78bb$export$adf3c8de3c7afc8b as useTokenField, $ae4a1f75a9bc78bb$export$ca798a7e6e94638c as getSelection, $ae4a1f75a9bc78bb$export$
|
|
654
|
+
export {$ae4a1f75a9bc78bb$export$adf3c8de3c7afc8b as useTokenField, $ae4a1f75a9bc78bb$export$9cafaa09e78b6e4b as setTokenFieldSelection, $ae4a1f75a9bc78bb$export$ca798a7e6e94638c as getSelection, $ae4a1f75a9bc78bb$export$6ec3e5953919831d as getSelectedRange, $ae4a1f75a9bc78bb$export$30729a8cd0694a7c as tokenFieldPositionToDOMRange};
|
|
579
655
|
//# sourceMappingURL=useTokenField.mjs.map
|
|
@@ -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} from '../utils/shadowdom/DOMFunctions';\nimport {getOwnerDocument} from '../utils/domHelpers';\nimport {isMac} from '../utils/platform';\nimport {mergeProps} from '../utils/mergeProps';\nimport {\n Position,\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 caretPosition = useRef<Position | null>(null);\n useLayoutEffect(() => {\n if (\n ref.current &&\n value.caretPosition &&\n !state.isComposing &&\n value.caretPosition !== caretPosition.current\n ) {\n // Only move the caret when the field is already focused.\n if (ref.current === getActiveElement(getOwnerDocument(ref.current))) {\n setCursor(ref.current, value.caretPosition);\n }\n caretPosition.current = value.caretPosition;\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 selection = window.getSelection();\n if (!selection || selection.rangeCount === 0) {\n return;\n }\n let range = selection.getRangeAt(0);\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) {\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 if (window.getSelection()?.isCollapsed) {\n let [start, end] = getSelection(ref.current!)!;\n if (start.offset === 0) {\n let segment = value.segments[start.index];\n if (segment?.type !== 'token') {\n segment = value.segments[start.index - 1];\n }\n if (segment?.type === 'token') {\n announce(segment.text, 'assertive');\n }\n\n // Update the caret position in the value.\n state.setValue(value => value.withCaretPosition(end));\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!, 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\nfunction rangeToPositions(container: Element, range: Range | StaticRange): [Position, Position] {\n let start = getPosition(container, range.startContainer, range.startOffset);\n let end = getPosition(container, range.endContainer, range.endOffset);\n return [start, end];\n}\n\nfunction getPosition(container: Element, node: Node, offset: number): 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 = 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, pos, pos, fireEvent);\n}\n\nexport function setTokenFieldSelection(\n root: Element,\n start: Position,\n end: Position,\n fireEvent = false\n) {\n let selection = window.getSelection();\n if (selection) {\n let range = createDOMRange(root, start, end);\n root[isProgrammaticSelectionChange] = !fireEvent;\n selection.removeAllRanges();\n selection.addRange(range);\n }\n}\n\nexport function tokenFieldPositionToDOMRange(root: Element, pos: Position): Range {\n return createDOMRange(root, pos, pos);\n}\n\nfunction createDOMRange(root: Element, start: Position, end: Position): Range {\n let range = document.createRange();\n let startChild = root.childNodes[start.index];\n if (!startChild) {\n range.setStart(root, Math.min(root.childNodes.length, start.index));\n } else if (startChild.nodeType === Node.ELEMENT_NODE) {\n // Place the cursor outside the token wrapper element.\n if (start.offset > 0) {\n range.setStartAfter(startChild);\n } else {\n range.setStartBefore(startChild);\n }\n } else {\n range.setStart(startChild, start.offset);\n }\n\n let endChild = root.childNodes[end.index];\n if (!endChild) {\n range.setEnd(root, Math.min(root.childNodes.length, end.index));\n } else if (endChild.nodeType === Node.ELEMENT_NODE) {\n if (end.offset > 0) {\n range.setEndAfter(endChild);\n } else {\n range.setEndBefore(endChild);\n }\n } else {\n range.setEnd(endChild, end.offset);\n }\n return range;\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"],"names":[],"version":3,"file":"useTokenField.mjs.map"}
|
|
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.mjs.map"}
|
|
@@ -4,9 +4,11 @@ function $parcel$export(e, n, v, s) {
|
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
$parcel$export(module.exports, "getOwnerDocument", function () { return $49582955cc364b1c$export$b204af158042fbac; });
|
|
7
|
+
$parcel$export(module.exports, "isDocument", function () { return $49582955cc364b1c$export$62858bae88b53fd0; });
|
|
7
8
|
$parcel$export(module.exports, "getOwnerWindow", function () { return $49582955cc364b1c$export$f21a1ffae260145a; });
|
|
8
9
|
$parcel$export(module.exports, "isShadowRoot", function () { return $49582955cc364b1c$export$af51f0f06c0f328a; });
|
|
9
10
|
$parcel$export(module.exports, "addEvent", function () { return $49582955cc364b1c$export$f531f92e2a15358f; });
|
|
11
|
+
$parcel$export(module.exports, "setStyle", function () { return $49582955cc364b1c$export$37a5fde709c1db82; });
|
|
10
12
|
/*
|
|
11
13
|
* Copyright 2020 Adobe. All rights reserved.
|
|
12
14
|
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
@@ -54,6 +56,25 @@ function $49582955cc364b1c$export$f531f92e2a15358f(target, event, listener, opti
|
|
|
54
56
|
for (let eventTarget of eventTargets)eventTarget.removeEventListener(event, listener, options);
|
|
55
57
|
};
|
|
56
58
|
}
|
|
59
|
+
function $49582955cc364b1c$export$37a5fde709c1db82(target, property, value, priority) {
|
|
60
|
+
if (target == null) return ()=>{};
|
|
61
|
+
let restore = new Array();
|
|
62
|
+
let styleTargets = Array.isArray(target) ? target : [
|
|
63
|
+
target
|
|
64
|
+
];
|
|
65
|
+
for (let styleTarget of styleTargets){
|
|
66
|
+
let initialValue = styleTarget.style.getPropertyValue(property);
|
|
67
|
+
let initialPriority = styleTarget.style.getPropertyPriority(property);
|
|
68
|
+
styleTarget.style.setProperty(property, value, priority);
|
|
69
|
+
restore.unshift(()=>{
|
|
70
|
+
if (initialValue) styleTarget.style.setProperty(property, initialValue, initialPriority);
|
|
71
|
+
else styleTarget.style.removeProperty(property);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return ()=>{
|
|
75
|
+
for (let cleanup of restore)cleanup();
|
|
76
|
+
};
|
|
77
|
+
}
|
|
57
78
|
|
|
58
79
|
|
|
59
80
|
//# sourceMappingURL=domHelpers.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"
|
|
1
|
+
{"mappings":";;;;;;;;;;;AAAA;;;;;;;;;;CAUC,GAIM,MAAM,4CAAmB,CAAC;IAC/B,IAAI,+BAAS,SAAS,OAAO,OAAO,QAAQ;IAE5C,IAAI,0CAAW,SAAS,OAAO;IAE/B,2DAA2D;IAC3D,OAAO,QAAQ,iBAAkB,CAAA,OAAO,aAAa,cAAc,WAAW,SAAQ;AACxF;AAEO,MAAM,4CAAiB,CAAC;IAC7B,IAAI,gBAAgB,0CAAiB;IAErC,2DAA2D;IAC3D,OAAO,eAAe,eAAgB,CAAA,OAAO,WAAW,cAAc,SAAS,SAAQ;AACzF;AAMO,SAAS,0CAAO,KAAc;IACnC,OACE,UAAU,QACV,OAAO,UAAU,YACjB,cAAc,SACd,OAAO,MAAM,QAAQ,KAAK;AAE9B;AAEA;;;CAGC,GACD,SAAS,+BAAS,KAAc;IAC9B,OAAO,OAAO,UAAU,YAAY,SAAS,QAAQ,YAAY,SAAS,MAAM,MAAM,KAAK;AAC7F;AAMO,SAAS,0CAAW,KAAc;IACvC,OAAO,0CAAO,UAAU,MAAM,QAAQ,KAAK;AAC7C;AAMO,SAAS,0CAAa,KAAc;IACzC,8BAA8B;IAC9B,OAAO,0CAAO,UAAU,MAAM,QAAQ,KAAK,MAAM,UAAU;AAC7D;AAKO,SAAS,0CACd,MAAgC,EAChC,KAAyC,EACzC,QAAkE,EAClE,OAA2C;IAE3C,IAAI,YAAY,QAAQ,UAAU,MAChC,OAAO,KAAO;IAGhB,IAAI,eAAe,MAAM,OAAO,CAAC,UAAU,SAAS;QAAC;KAAO;IAE5D,KAAK,IAAI,eAAe,aACtB,YAAY,gBAAgB,CAAC,OAAO,UAA2B;IAGjE,OAAO;QACL,KAAK,IAAI,eAAe,aACtB,YAAY,mBAAmB,CAAC,OAAO,UAA2B;IAEtE;AACF;AAKO,SAAS,0CACd,MAA0C,EAC1C,QAAgB,EAChB,KAAa,EACb,QAAiB;IAEjB,IAAI,UAAU,MACZ,OAAO,KAAO;IAGhB,IAAI,UAAU,IAAI;IAClB,IAAI,eAAe,MAAM,OAAO,CAAC,UAAU,SAAS;QAAC;KAAO;IAE5D,KAAK,IAAI,eAAe,aAAc;QACpC,IAAI,eAAe,YAAY,KAAK,CAAC,gBAAgB,CAAC;QACtD,IAAI,kBAAkB,YAAY,KAAK,CAAC,mBAAmB,CAAC;QAE5D,YAAY,KAAK,CAAC,WAAW,CAAC,UAAU,OAAO;QAE/C,QAAQ,OAAO,CAAC;YACd,IAAI,cACF,YAAY,KAAK,CAAC,WAAW,CAAC,UAAU,cAAc;iBAEtD,YAAY,KAAK,CAAC,cAAc,CAAC;QAErC;IACF;IAEA,OAAO;QACL,KAAK,IAAI,WAAW,QAClB;IAEJ;AACF","sources":["packages/react-aria/src/utils/domHelpers.ts"],"sourcesContent":["/*\n * Copyright 2020 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 permissions and limitations under the License.\n */\n\nimport type {EventMapType} from '@react-types/shared';\n\nexport const getOwnerDocument = (target?: EventTarget | null): Document => {\n if (isWindow(target)) return target.document;\n\n if (isDocument(target)) return target;\n\n // @ts-expect-error Ensure safe access in SSR environments.\n return target?.ownerDocument ?? (typeof document !== 'undefined' ? document : undefined);\n};\n\nexport const getOwnerWindow = (target?: EventTarget | null): Window & typeof globalThis => {\n let ownerDocument = getOwnerDocument(target);\n\n // @ts-expect-error Ensure safe access in SSR environments.\n return ownerDocument?.defaultView ?? (typeof window !== 'undefined' ? window : undefined);\n};\n\n/**\n * Type guard that checks if a value is a Node. Verifies the presence and type of the nodeType\n * property.\n */\nexport function isNode(value: unknown): value is Node {\n return (\n value !== null &&\n typeof value === 'object' &&\n 'nodeType' in value &&\n typeof value.nodeType === 'number'\n );\n}\n\n/**\n * Type guard that checks if a value is a Window. Uses window self reference checks to\n * distinguish Window from other values.\n */\nfunction isWindow(value: unknown): value is Window & typeof globalThis {\n return typeof value === 'object' && value != null && 'window' in value && value.window === value;\n}\n\n/**\n * Type guard that checks if a value is a Document. Uses nodeType and host property checks to\n * distinguish Document from other values.\n */\nexport function isDocument(value: unknown): value is Document {\n return isNode(value) && value.nodeType === 9;\n}\n\n/**\n * Type guard that checks if a value is a ShadowRoot. Uses nodeType and host property checks to\n * distinguish ShadowRoot from other values.\n */\nexport function isShadowRoot(value: unknown): value is ShadowRoot {\n // 11 = DOCUMENT_FRAGMENT_NODE\n return isNode(value) && value.nodeType === 11 && 'host' in value;\n}\n\n/**\n * Attaches an event listener on target(s) and returns a cleanup function.\n */\nexport function addEvent<T extends EventTarget, K extends keyof EventMapType<Exclude<T, null>>>(\n target: T | EventTarget[] | null,\n event: Extract<K, string> | (string & {}),\n listener?: (this: T, ev: EventMapType<Exclude<T, null>>[K]) => any,\n options?: boolean | AddEventListenerOptions\n): () => void {\n if (listener == null || target == null) {\n return () => {};\n }\n\n let eventTargets = Array.isArray(target) ? target : [target];\n\n for (let eventTarget of eventTargets) {\n eventTarget.addEventListener(event, listener as EventListener, options);\n }\n\n return () => {\n for (let eventTarget of eventTargets) {\n eventTarget.removeEventListener(event, listener as EventListener, options);\n }\n };\n}\n\n/**\n * Sets a CSS property on an element and returns a cleanup function.\n */\nexport function setStyle(\n target: HTMLElement | HTMLElement[] | null,\n property: string,\n value: string,\n priority?: string\n): () => void {\n if (target == null) {\n return () => {};\n }\n\n let restore = new Array<Function>();\n let styleTargets = Array.isArray(target) ? target : [target];\n\n for (let styleTarget of styleTargets) {\n let initialValue = styleTarget.style.getPropertyValue(property);\n let initialPriority = styleTarget.style.getPropertyPriority(property);\n\n styleTarget.style.setProperty(property, value, priority);\n\n restore.unshift(() => {\n if (initialValue) {\n styleTarget.style.setProperty(property, initialValue, initialPriority);\n } else {\n styleTarget.style.removeProperty(property);\n }\n });\n }\n\n return () => {\n for (let cleanup of restore) {\n cleanup();\n }\n };\n}\n"],"names":[],"version":3,"file":"domHelpers.cjs.map"}
|
|
@@ -47,7 +47,26 @@ function $cc3c3666b64debad$export$f531f92e2a15358f(target, event, listener, opti
|
|
|
47
47
|
for (let eventTarget of eventTargets)eventTarget.removeEventListener(event, listener, options);
|
|
48
48
|
};
|
|
49
49
|
}
|
|
50
|
+
function $cc3c3666b64debad$export$37a5fde709c1db82(target, property, value, priority) {
|
|
51
|
+
if (target == null) return ()=>{};
|
|
52
|
+
let restore = new Array();
|
|
53
|
+
let styleTargets = Array.isArray(target) ? target : [
|
|
54
|
+
target
|
|
55
|
+
];
|
|
56
|
+
for (let styleTarget of styleTargets){
|
|
57
|
+
let initialValue = styleTarget.style.getPropertyValue(property);
|
|
58
|
+
let initialPriority = styleTarget.style.getPropertyPriority(property);
|
|
59
|
+
styleTarget.style.setProperty(property, value, priority);
|
|
60
|
+
restore.unshift(()=>{
|
|
61
|
+
if (initialValue) styleTarget.style.setProperty(property, initialValue, initialPriority);
|
|
62
|
+
else styleTarget.style.removeProperty(property);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
return ()=>{
|
|
66
|
+
for (let cleanup of restore)cleanup();
|
|
67
|
+
};
|
|
68
|
+
}
|
|
50
69
|
|
|
51
70
|
|
|
52
|
-
export {$cc3c3666b64debad$export$b204af158042fbac as getOwnerDocument, $cc3c3666b64debad$export$62858bae88b53fd0 as isDocument, $cc3c3666b64debad$export$f21a1ffae260145a as getOwnerWindow, $cc3c3666b64debad$export$8ee0fc9ee280b4ee as isNode, $cc3c3666b64debad$export$af51f0f06c0f328a as isShadowRoot, $cc3c3666b64debad$export$f531f92e2a15358f as addEvent};
|
|
71
|
+
export {$cc3c3666b64debad$export$b204af158042fbac as getOwnerDocument, $cc3c3666b64debad$export$62858bae88b53fd0 as isDocument, $cc3c3666b64debad$export$f21a1ffae260145a as getOwnerWindow, $cc3c3666b64debad$export$8ee0fc9ee280b4ee as isNode, $cc3c3666b64debad$export$af51f0f06c0f328a as isShadowRoot, $cc3c3666b64debad$export$f531f92e2a15358f as addEvent, $cc3c3666b64debad$export$37a5fde709c1db82 as setStyle};
|
|
53
72
|
//# sourceMappingURL=domHelpers.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"AAAA;;;;;;;;;;CAUC,GAIM,MAAM,4CAAmB,CAAC;IAC/B,IAAI,+BAAS,SAAS,OAAO,OAAO,QAAQ;IAE5C,IAAI,0CAAW,SAAS,OAAO;QAGxB;IADP,2DAA2D;IAC3D,OAAO,CAAA,wBAAA,mBAAA,6BAAA,OAAQ,aAAa,cAArB,mCAAA,wBAA0B,OAAO,aAAa,cAAc,WAAW;AAChF;AAEO,MAAM,4CAAiB,CAAC;IAC7B,IAAI,gBAAgB,0CAAiB;QAG9B;IADP,2DAA2D;IAC3D,OAAO,CAAA,6BAAA,0BAAA,oCAAA,cAAe,WAAW,cAA1B,wCAAA,6BAA+B,OAAO,WAAW,cAAc,SAAS;AACjF;AAMO,SAAS,0CAAO,KAAc;IACnC,OACE,UAAU,QACV,OAAO,UAAU,YACjB,cAAc,SACd,OAAO,MAAM,QAAQ,KAAK;AAE9B;AAEA;;;CAGC,GACD,SAAS,+BAAS,KAAc;IAC9B,OAAO,OAAO,UAAU,YAAY,SAAS,QAAQ,YAAY,SAAS,MAAM,MAAM,KAAK;AAC7F;AAMO,SAAS,0CAAW,KAAc;IACvC,OAAO,0CAAO,UAAU,MAAM,QAAQ,KAAK;AAC7C;AAMO,SAAS,0CAAa,KAAc;IACzC,8BAA8B;IAC9B,OAAO,0CAAO,UAAU,MAAM,QAAQ,KAAK,MAAM,UAAU;AAC7D;AAKO,SAAS,0CACd,MAAgC,EAChC,KAAyC,EACzC,QAAkE,EAClE,OAA2C;IAE3C,IAAI,YAAY,QAAQ,UAAU,MAChC,OAAO,KAAO;IAGhB,IAAI,eAAe,MAAM,OAAO,CAAC,UAAU,SAAS;QAAC;KAAO;IAE5D,KAAK,IAAI,eAAe,aACtB,YAAY,gBAAgB,CAAC,OAAO,UAA2B;IAGjE,OAAO;QACL,KAAK,IAAI,eAAe,aACtB,YAAY,mBAAmB,CAAC,OAAO,UAA2B;IAEtE;AACF","sources":["packages/react-aria/src/utils/domHelpers.ts"],"sourcesContent":["/*\n * Copyright 2020 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 permissions and limitations under the License.\n */\n\nimport type {EventMapType} from '@react-types/shared';\n\nexport const getOwnerDocument = (target?: EventTarget | null): Document => {\n if (isWindow(target)) return target.document;\n\n if (isDocument(target)) return target;\n\n // @ts-expect-error Ensure safe access in SSR environments.\n return target?.ownerDocument ?? (typeof document !== 'undefined' ? document : undefined);\n};\n\nexport const getOwnerWindow = (target?: EventTarget | null): Window & typeof globalThis => {\n let ownerDocument = getOwnerDocument(target);\n\n // @ts-expect-error Ensure safe access in SSR environments.\n return ownerDocument?.defaultView ?? (typeof window !== 'undefined' ? window : undefined);\n};\n\n/**\n * Type guard that checks if a value is a Node. Verifies the presence and type of the nodeType\n * property.\n */\nexport function isNode(value: unknown): value is Node {\n return (\n value !== null &&\n typeof value === 'object' &&\n 'nodeType' in value &&\n typeof value.nodeType === 'number'\n );\n}\n\n/**\n * Type guard that checks if a value is a Window. Uses window self reference checks to\n * distinguish Window from other values.\n */\nfunction isWindow(value: unknown): value is Window & typeof globalThis {\n return typeof value === 'object' && value != null && 'window' in value && value.window === value;\n}\n\n/**\n * Type guard that checks if a value is a Document. Uses nodeType and host property checks to\n * distinguish Document from other values.\n */\nexport function isDocument(value: unknown): value is Document {\n return isNode(value) && value.nodeType === 9;\n}\n\n/**\n * Type guard that checks if a value is a ShadowRoot. Uses nodeType and host property checks to\n * distinguish ShadowRoot from other values.\n */\nexport function isShadowRoot(value: unknown): value is ShadowRoot {\n // 11 = DOCUMENT_FRAGMENT_NODE\n return isNode(value) && value.nodeType === 11 && 'host' in value;\n}\n\n/**\n * Attaches an event listener on target(s) and returns a cleanup function.\n */\nexport function addEvent<T extends EventTarget, K extends keyof EventMapType<Exclude<T, null>>>(\n target: T | EventTarget[] | null,\n event: Extract<K, string> | (string & {}),\n listener?: (this: T, ev: EventMapType<Exclude<T, null>>[K]) => any,\n options?: boolean | AddEventListenerOptions\n): () => void {\n if (listener == null || target == null) {\n return () => {};\n }\n\n let eventTargets = Array.isArray(target) ? target : [target];\n\n for (let eventTarget of eventTargets) {\n eventTarget.addEventListener(event, listener as EventListener, options);\n }\n\n return () => {\n for (let eventTarget of eventTargets) {\n eventTarget.removeEventListener(event, listener as EventListener, options);\n }\n };\n}\n"],"names":[],"version":3,"file":"domHelpers.js.map"}
|
|
1
|
+
{"mappings":"AAAA;;;;;;;;;;CAUC,GAIM,MAAM,4CAAmB,CAAC;IAC/B,IAAI,+BAAS,SAAS,OAAO,OAAO,QAAQ;IAE5C,IAAI,0CAAW,SAAS,OAAO;QAGxB;IADP,2DAA2D;IAC3D,OAAO,CAAA,wBAAA,mBAAA,6BAAA,OAAQ,aAAa,cAArB,mCAAA,wBAA0B,OAAO,aAAa,cAAc,WAAW;AAChF;AAEO,MAAM,4CAAiB,CAAC;IAC7B,IAAI,gBAAgB,0CAAiB;QAG9B;IADP,2DAA2D;IAC3D,OAAO,CAAA,6BAAA,0BAAA,oCAAA,cAAe,WAAW,cAA1B,wCAAA,6BAA+B,OAAO,WAAW,cAAc,SAAS;AACjF;AAMO,SAAS,0CAAO,KAAc;IACnC,OACE,UAAU,QACV,OAAO,UAAU,YACjB,cAAc,SACd,OAAO,MAAM,QAAQ,KAAK;AAE9B;AAEA;;;CAGC,GACD,SAAS,+BAAS,KAAc;IAC9B,OAAO,OAAO,UAAU,YAAY,SAAS,QAAQ,YAAY,SAAS,MAAM,MAAM,KAAK;AAC7F;AAMO,SAAS,0CAAW,KAAc;IACvC,OAAO,0CAAO,UAAU,MAAM,QAAQ,KAAK;AAC7C;AAMO,SAAS,0CAAa,KAAc;IACzC,8BAA8B;IAC9B,OAAO,0CAAO,UAAU,MAAM,QAAQ,KAAK,MAAM,UAAU;AAC7D;AAKO,SAAS,0CACd,MAAgC,EAChC,KAAyC,EACzC,QAAkE,EAClE,OAA2C;IAE3C,IAAI,YAAY,QAAQ,UAAU,MAChC,OAAO,KAAO;IAGhB,IAAI,eAAe,MAAM,OAAO,CAAC,UAAU,SAAS;QAAC;KAAO;IAE5D,KAAK,IAAI,eAAe,aACtB,YAAY,gBAAgB,CAAC,OAAO,UAA2B;IAGjE,OAAO;QACL,KAAK,IAAI,eAAe,aACtB,YAAY,mBAAmB,CAAC,OAAO,UAA2B;IAEtE;AACF;AAKO,SAAS,0CACd,MAA0C,EAC1C,QAAgB,EAChB,KAAa,EACb,QAAiB;IAEjB,IAAI,UAAU,MACZ,OAAO,KAAO;IAGhB,IAAI,UAAU,IAAI;IAClB,IAAI,eAAe,MAAM,OAAO,CAAC,UAAU,SAAS;QAAC;KAAO;IAE5D,KAAK,IAAI,eAAe,aAAc;QACpC,IAAI,eAAe,YAAY,KAAK,CAAC,gBAAgB,CAAC;QACtD,IAAI,kBAAkB,YAAY,KAAK,CAAC,mBAAmB,CAAC;QAE5D,YAAY,KAAK,CAAC,WAAW,CAAC,UAAU,OAAO;QAE/C,QAAQ,OAAO,CAAC;YACd,IAAI,cACF,YAAY,KAAK,CAAC,WAAW,CAAC,UAAU,cAAc;iBAEtD,YAAY,KAAK,CAAC,cAAc,CAAC;QAErC;IACF;IAEA,OAAO;QACL,KAAK,IAAI,WAAW,QAClB;IAEJ;AACF","sources":["packages/react-aria/src/utils/domHelpers.ts"],"sourcesContent":["/*\n * Copyright 2020 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 permissions and limitations under the License.\n */\n\nimport type {EventMapType} from '@react-types/shared';\n\nexport const getOwnerDocument = (target?: EventTarget | null): Document => {\n if (isWindow(target)) return target.document;\n\n if (isDocument(target)) return target;\n\n // @ts-expect-error Ensure safe access in SSR environments.\n return target?.ownerDocument ?? (typeof document !== 'undefined' ? document : undefined);\n};\n\nexport const getOwnerWindow = (target?: EventTarget | null): Window & typeof globalThis => {\n let ownerDocument = getOwnerDocument(target);\n\n // @ts-expect-error Ensure safe access in SSR environments.\n return ownerDocument?.defaultView ?? (typeof window !== 'undefined' ? window : undefined);\n};\n\n/**\n * Type guard that checks if a value is a Node. Verifies the presence and type of the nodeType\n * property.\n */\nexport function isNode(value: unknown): value is Node {\n return (\n value !== null &&\n typeof value === 'object' &&\n 'nodeType' in value &&\n typeof value.nodeType === 'number'\n );\n}\n\n/**\n * Type guard that checks if a value is a Window. Uses window self reference checks to\n * distinguish Window from other values.\n */\nfunction isWindow(value: unknown): value is Window & typeof globalThis {\n return typeof value === 'object' && value != null && 'window' in value && value.window === value;\n}\n\n/**\n * Type guard that checks if a value is a Document. Uses nodeType and host property checks to\n * distinguish Document from other values.\n */\nexport function isDocument(value: unknown): value is Document {\n return isNode(value) && value.nodeType === 9;\n}\n\n/**\n * Type guard that checks if a value is a ShadowRoot. Uses nodeType and host property checks to\n * distinguish ShadowRoot from other values.\n */\nexport function isShadowRoot(value: unknown): value is ShadowRoot {\n // 11 = DOCUMENT_FRAGMENT_NODE\n return isNode(value) && value.nodeType === 11 && 'host' in value;\n}\n\n/**\n * Attaches an event listener on target(s) and returns a cleanup function.\n */\nexport function addEvent<T extends EventTarget, K extends keyof EventMapType<Exclude<T, null>>>(\n target: T | EventTarget[] | null,\n event: Extract<K, string> | (string & {}),\n listener?: (this: T, ev: EventMapType<Exclude<T, null>>[K]) => any,\n options?: boolean | AddEventListenerOptions\n): () => void {\n if (listener == null || target == null) {\n return () => {};\n }\n\n let eventTargets = Array.isArray(target) ? target : [target];\n\n for (let eventTarget of eventTargets) {\n eventTarget.addEventListener(event, listener as EventListener, options);\n }\n\n return () => {\n for (let eventTarget of eventTargets) {\n eventTarget.removeEventListener(event, listener as EventListener, options);\n }\n };\n}\n\n/**\n * Sets a CSS property on an element and returns a cleanup function.\n */\nexport function setStyle(\n target: HTMLElement | HTMLElement[] | null,\n property: string,\n value: string,\n priority?: string\n): () => void {\n if (target == null) {\n return () => {};\n }\n\n let restore = new Array<Function>();\n let styleTargets = Array.isArray(target) ? target : [target];\n\n for (let styleTarget of styleTargets) {\n let initialValue = styleTarget.style.getPropertyValue(property);\n let initialPriority = styleTarget.style.getPropertyPriority(property);\n\n styleTarget.style.setProperty(property, value, priority);\n\n restore.unshift(() => {\n if (initialValue) {\n styleTarget.style.setProperty(property, initialValue, initialPriority);\n } else {\n styleTarget.style.removeProperty(property);\n }\n });\n }\n\n return () => {\n for (let cleanup of restore) {\n cleanup();\n }\n };\n}\n"],"names":[],"version":3,"file":"domHelpers.js.map"}
|