Private
Public Access
1
0

feat: Fluent UI Outlook Lite + connections mockup

This commit is contained in:
2026-04-14 18:52:25 +00:00
parent 1199eff6c3
commit dfa4010406
34820 changed files with 1003813 additions and 205 deletions

2392
node_modules/@fluentui/react-tabster/CHANGELOG.md generated vendored Normal file

File diff suppressed because it is too large Load Diff

15
node_modules/@fluentui/react-tabster/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,15 @@
@fluentui/react-focus-management
Copyright (c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Note: Usage of the fonts and icons referenced in Fluent UI React is subject to the terms listed at https://aka.ms/fluentui-assets-license

33
node_modules/@fluentui/react-tabster/README.md generated vendored Normal file
View File

@@ -0,0 +1,33 @@
# @fluentui/react-tabster
**Tabster components for [Fluent UI React](https://react.fluentui.dev)**
Library for focus management that leverages [tabster](https://github.com/microsoft/tabster).
The API currently only supports declarative data-\* attributes that are returned using the exported react hooks:
```tsx
import * as React from 'react';
import { useArrowNavigationGroup } from '@fluentui/react-tabster';
const Item: React.FC = ({ children }) => <div tabIndex={0}>Item</div>;
const ArrowNavigationExample: React.FC = ({ children }) => {
const attrs = useArrowNavigationGroup({ circular: true });
return (
<div {...attrs}>
<Item />
<Item />
<Item />
<Item />
<Item />
<Item />
</div>
);
};
const App: React.FC = () => {
return <ArrowNavigationExample />;
};
```

1571
node_modules/@fluentui/react-tabster/dist/index.d.ts generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,36 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
FOCUS_VISIBLE_ATTR: function() {
return FOCUS_VISIBLE_ATTR;
},
FOCUS_WITHIN_ATTR: function() {
return FOCUS_WITHIN_ATTR;
},
KEYBOARD_NAV_ATTRIBUTE: function() {
return KEYBOARD_NAV_ATTRIBUTE;
},
KEYBOARD_NAV_SELECTOR: function() {
return KEYBOARD_NAV_SELECTOR;
},
defaultOptions: function() {
return defaultOptions;
}
});
const KEYBOARD_NAV_ATTRIBUTE = 'data-keyboard-nav';
const KEYBOARD_NAV_SELECTOR = `:global([${KEYBOARD_NAV_ATTRIBUTE}])`;
const FOCUS_VISIBLE_ATTR = 'data-fui-focus-visible';
const FOCUS_WITHIN_ATTR = 'data-fui-focus-within';
const defaultOptions = {
style: {},
selector: 'focus',
customizeSelector: (selector)=>selector
};

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/focus/constants.ts"],"sourcesContent":["export const KEYBOARD_NAV_ATTRIBUTE = 'data-keyboard-nav' as const;\nexport const KEYBOARD_NAV_SELECTOR = `:global([${KEYBOARD_NAV_ATTRIBUTE}])` as const;\n\n/**\n * @internal\n */\nexport const FOCUS_VISIBLE_ATTR = 'data-fui-focus-visible';\n\n/**\n * @internal\n */\nexport const FOCUS_WITHIN_ATTR = 'data-fui-focus-within';\nexport const defaultOptions = {\n style: {},\n selector: 'focus',\n customizeSelector: (selector: string) => selector,\n} as const;\n"],"names":["FOCUS_VISIBLE_ATTR","FOCUS_WITHIN_ATTR","KEYBOARD_NAV_ATTRIBUTE","KEYBOARD_NAV_SELECTOR","defaultOptions","style","selector","customizeSelector"],"mappings":";;;;;;;;;;;IAMaA,kBAAkB;eAAlBA;;IAKAC,iBAAiB;eAAjBA;;IAXAC,sBAAsB;eAAtBA;;IACAC,qBAAqB;eAArBA;;IAWAC,cAAc;eAAdA;;;AAZN,MAAMF,yBAAyB;AAC/B,MAAMC,wBAAwB,CAAC,SAAS,EAAED,uBAAuB,EAAE,CAAC;AAKpE,MAAMF,qBAAqB;AAK3B,MAAMC,oBAAoB;AAC1B,MAAMG,iBAAiB;IAC5BC,OAAO,CAAC;IACRC,UAAU;IACVC,mBAAmB,CAACD,WAAqBA;AAC3C"}

View File

@@ -0,0 +1,24 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "createCustomFocusIndicatorStyle", {
enumerable: true,
get: function() {
return createCustomFocusIndicatorStyle;
}
});
const _constants = require("./constants");
function createCustomFocusIndicatorStyle(style, { selector: selectorType = _constants.defaultOptions.selector, customizeSelector = _constants.defaultOptions.customizeSelector } = _constants.defaultOptions) {
return {
[customizeSelector(createBaseSelector(selectorType))]: style
};
}
function createBaseSelector(selectorType) {
switch(selectorType){
case 'focus':
return `&[${_constants.FOCUS_VISIBLE_ATTR}]`;
case 'focus-within':
return `&[${_constants.FOCUS_WITHIN_ATTR}]:focus-within`;
}
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/focus/createCustomFocusIndicatorStyle.ts"],"sourcesContent":["import { defaultOptions, FOCUS_VISIBLE_ATTR, FOCUS_WITHIN_ATTR } from './constants';\nimport { makeResetStyles } from '@griffel/react';\nimport type { GriffelStyle } from '@griffel/react';\n\n// TODO: Use the type directly from @griffel/react\n// https://github.com/microsoft/griffel/pull/278\ntype GriffelResetStyle = Parameters<typeof makeResetStyles>[0];\n\nexport interface CreateCustomFocusIndicatorStyleOptions {\n /**\n * Control if the indicator appears when the corresponding element is focused,\n * or any child is focused within the corresponding element.\n * @default 'focus'\n * @alias selectorType\n */\n selector?: 'focus' | 'focus-within';\n /**\n * Customizes the selector provided based on the selector type.\n */\n customizeSelector?: (selector: string) => string;\n /**\n * Enables the browser default outline style\n * @deprecated The custom focus indicator no longer affects outline styles. Outline is overridden\n * in the default focus indicator function, `createFocusOutlineStyle`.\n */\n enableOutline?: boolean;\n}\n\n/**\n * Creates a style for @see makeStyles that includes the necessary selectors for focus.\n * Should be used only when @see createFocusOutlineStyle does not fit requirements\n *\n * If you're using `createCustomFocusIndicatorStyle` instead of `createFocusOutlineStyle`\n * keep in mind that the default outline style is not going to be removed\n * (as it is in `createFocusOutlineStyle`),\n * and is your responsibility to manually remove it from your styles.\n *\n * @example\n * ```ts\n * // Link styles\n * const useStyles = makeStyles({\n focusIndicator: createCustomFocusIndicatorStyle({\n textDecorationColor: tokens.colorStrokeFocus2,\n textDecorationLine: 'underline',\n textDecorationStyle: 'double',\n outlineStyle: 'none',\n }),\n // Common styles.\n root: {\n // ❗️ DO NOT FORGET TO REMOVE THE DEFAULT OUTLINE STYLE\n ':focus-visible': {\n outlineStyle: 'none',\n },\n * ```\n *\n * @param style - styling applied on focus, defaults to @see getDefaultFocusOutlineStyles\n * @param options - Configure the style of the focus outline\n */\nexport function createCustomFocusIndicatorStyle<TStyle extends GriffelStyle | GriffelResetStyle>(\n style: TStyle,\n {\n selector: selectorType = defaultOptions.selector,\n customizeSelector = defaultOptions.customizeSelector,\n }: CreateCustomFocusIndicatorStyleOptions = defaultOptions,\n): TStyle extends GriffelStyle ? GriffelStyle : GriffelResetStyle {\n return { [customizeSelector(createBaseSelector(selectorType))]: style };\n}\n\nfunction createBaseSelector(selectorType: 'focus' | 'focus-within'): string {\n switch (selectorType) {\n case 'focus':\n return `&[${FOCUS_VISIBLE_ATTR}]`;\n case 'focus-within':\n return `&[${FOCUS_WITHIN_ATTR}]:focus-within`;\n }\n}\n"],"names":["createCustomFocusIndicatorStyle","style","selector","selectorType","defaultOptions","customizeSelector","createBaseSelector","FOCUS_VISIBLE_ATTR","FOCUS_WITHIN_ATTR"],"mappings":";;;;+BA0DgBA;;;eAAAA;;;2BA1DsD;AA0D/D,SAASA,gCACdC,KAAa,EACb,EACEC,UAAUC,eAAeC,yBAAc,CAACF,QAAQ,EAChDG,oBAAoBD,yBAAc,CAACC,iBAAiB,EACb,GAAGD,yBAAc;IAE1D,OAAO;QAAE,CAACC,kBAAkBC,mBAAmBH,eAAe,EAAEF;IAAM;AACxE;AAEA,SAASK,mBAAmBH,YAAsC;IAChE,OAAQA;QACN,KAAK;YACH,OAAO,CAAC,EAAE,EAAEI,6BAAkB,CAAC,CAAC,CAAC;QACnC,KAAK;YACH,OAAO,CAAC,EAAE,EAAEC,4BAAiB,CAAC,cAAc,CAAC;IACjD;AACF"}

View File

@@ -0,0 +1,74 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "createFocusOutlineStyle", {
enumerable: true,
get: function() {
return createFocusOutlineStyle;
}
});
const _reacttheme = require("@fluentui/react-theme");
const _react = require("@griffel/react");
const _createCustomFocusIndicatorStyle = require("./createCustomFocusIndicatorStyle");
const _constants = require("./constants");
/**
* Get the position of the focus outline
*
* @param options - Configures the style of the focus outline
* @param position - The position of the focus outline
* @returns CSS value for the position of the focus outline
*/ function getOutlinePosition({ outlineWidth, outlineOffset }, position) {
const offsetValue = (outlineOffset === null || outlineOffset === void 0 ? void 0 : outlineOffset[position]) || outlineOffset;
if (!outlineOffset) {
return `calc(${outlineWidth} * -1)`;
}
return `calc(0px - ${outlineWidth} - ${offsetValue})`;
}
/**
* NOTE: the element with the focus outline needs to have `position: relative` so that the
* pseudo element can be properly positioned.
*
* @param options - Configures the style of the focus outline
* @returns focus outline styles object
*/ const getFocusOutlineStyles = (options)=>{
const { outlineRadius, outlineColor, outlineWidth } = options;
return {
..._react.shorthands.borderColor('transparent'),
'@media (forced-colors: active)': {
'::after': {
..._react.shorthands.borderColor('Highlight')
}
},
'::after': {
content: '""',
position: 'absolute',
pointerEvents: 'none',
zIndex: 1,
border: `${outlineWidth} solid ${outlineColor}`,
borderRadius: outlineRadius,
top: getOutlinePosition(options, 'top'),
right: getOutlinePosition(options, 'right'),
bottom: getOutlinePosition(options, 'bottom'),
left: getOutlinePosition(options, 'left')
}
};
};
const createFocusOutlineStyle = ({ enableOutline = false, selector = _constants.defaultOptions.selector, customizeSelector, style = _constants.defaultOptions.style } = _constants.defaultOptions)=>({
':focus': {
outlineStyle: enableOutline ? undefined : 'none'
},
':focus-visible': {
outlineStyle: enableOutline ? undefined : 'none'
},
...(0, _createCustomFocusIndicatorStyle.createCustomFocusIndicatorStyle)(getFocusOutlineStyles({
outlineColor: _reacttheme.tokens.colorStrokeFocus2,
outlineRadius: _reacttheme.tokens.borderRadiusMedium,
// FIXME: tokens.strokeWidthThick causes some weird bugs
outlineWidth: '2px',
...style
}), {
selector,
customizeSelector
})
});

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,79 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "applyFocusVisiblePolyfill", {
enumerable: true,
get: function() {
return applyFocusVisiblePolyfill;
}
});
const _reactutilities = require("@fluentui/react-utilities");
const _keyborg = require("keyborg");
const _constants = require("./constants");
function applyFocusVisiblePolyfill(scope, targetWindow) {
if (alreadyInScope(scope)) {
// Focus visible polyfill already applied at this scope
return ()=>undefined;
}
const state = {
current: undefined
};
const keyborg = (0, _keyborg.createKeyborg)(targetWindow);
function registerElementIfNavigating(el) {
if (keyborg.isNavigatingWithKeyboard() && (0, _reactutilities.isHTMLElement)(el)) {
state.current = el;
el.setAttribute(_constants.FOCUS_VISIBLE_ATTR, '');
}
}
function disposeCurrentElement() {
if (state.current) {
state.current.removeAttribute(_constants.FOCUS_VISIBLE_ATTR);
state.current = undefined;
}
}
// When navigation mode changes remove the focus-visible selector
keyborg.subscribe((isNavigatingWithKeyboard)=>{
if (!isNavigatingWithKeyboard) {
disposeCurrentElement();
} else {
registerElementIfNavigating(targetWindow.document.activeElement);
}
});
// Keyborg's focusin event is delegated so it's only registered once on the window
// and contains metadata about the focus event
const keyborgListener = (e)=>{
disposeCurrentElement();
const target = e.composedPath()[0];
registerElementIfNavigating(target);
};
// Make sure that when focus leaves the scope, the focus visible class is removed
const blurListener = (e)=>{
if (!e.relatedTarget || (0, _reactutilities.isHTMLElement)(e.relatedTarget) && !scope.contains(e.relatedTarget)) {
disposeCurrentElement();
}
};
scope.addEventListener(_keyborg.KEYBORG_FOCUSIN, keyborgListener);
scope.addEventListener('focusout', blurListener);
scope.focusVisible = true;
if (scope.contains(targetWindow.document.activeElement)) {
registerElementIfNavigating(targetWindow.document.activeElement);
}
// Return disposer
return ()=>{
disposeCurrentElement();
scope.removeEventListener(_keyborg.KEYBORG_FOCUSIN, keyborgListener);
scope.removeEventListener('focusout', blurListener);
scope.focusVisible = undefined;
(0, _keyborg.disposeKeyborg)(keyborg);
};
}
function alreadyInScope(el) {
if (!el) {
return false;
}
if (el.focusVisible) {
return true;
}
return alreadyInScope(el === null || el === void 0 ? void 0 : el.parentElement);
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,55 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "applyFocusWithinPolyfill", {
enumerable: true,
get: function() {
return applyFocusWithinPolyfill;
}
});
const _keyborg = require("keyborg");
const _constants = require("./constants");
function applyFocusWithinPolyfill(element, win) {
const keyborg = (0, _keyborg.createKeyborg)(win);
// When navigation mode changes to mouse, remove the focus-within selector
keyborg.subscribe((isNavigatingWithKeyboard)=>{
if (!isNavigatingWithKeyboard) {
removeFocusWithinClass(element);
}
});
// Keyborg's focusin event is delegated so it's only registered once on the window
// and contains metadata about the focus event
const keyborgListener = (e)=>{
if (keyborg.isNavigatingWithKeyboard() && isHTMLElement(e.target)) {
// Griffel can't create chained global styles so use the parent element for now
applyFocusWithinClass(element);
}
};
// Make sure that when focus leaves the scope, the focus within class is removed
const blurListener = (e)=>{
if (!e.relatedTarget || isHTMLElement(e.relatedTarget) && !element.contains(e.relatedTarget)) {
removeFocusWithinClass(element);
}
};
element.addEventListener(_keyborg.KEYBORG_FOCUSIN, keyborgListener);
element.addEventListener('focusout', blurListener);
// Return disposer
return ()=>{
element.removeEventListener(_keyborg.KEYBORG_FOCUSIN, keyborgListener);
element.removeEventListener('focusout', blurListener);
(0, _keyborg.disposeKeyborg)(keyborg);
};
}
function applyFocusWithinClass(el) {
el.setAttribute(_constants.FOCUS_WITHIN_ATTR, '');
}
function removeFocusWithinClass(el) {
el.removeAttribute(_constants.FOCUS_WITHIN_ATTR);
}
function isHTMLElement(target) {
if (!target) {
return false;
}
return Boolean(target && typeof target === 'object' && 'classList' in target && 'contains' in target);
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/focus/focusWithinPolyfill.ts"],"sourcesContent":["import { KEYBORG_FOCUSIN, KeyborgFocusInEvent, createKeyborg, disposeKeyborg } from 'keyborg';\nimport { FOCUS_WITHIN_ATTR } from './constants';\n\n/**\n * Because `addEventListener` type override falls back to 2nd definition (evt name is unknown string literal)\n * evt is being typed as a base class of MouseEvent -> `Event`.\n * This type is used to override `listener` calls to make TS happy\n */\ntype ListenerOverride = (evt: Event) => void;\n\n/**\n * A ponyfill that allows `:focus-within` to support visibility based on keyboard/mouse navigation\n * like `:focus-visible` https://github.com/WICG/focus-visible/issues/151\n * @returns ref to the element that uses `:focus-within` styles\n */\nexport function applyFocusWithinPolyfill(element: HTMLElement, win: Window): () => void {\n const keyborg = createKeyborg(win);\n\n // When navigation mode changes to mouse, remove the focus-within selector\n keyborg.subscribe(isNavigatingWithKeyboard => {\n if (!isNavigatingWithKeyboard) {\n removeFocusWithinClass(element);\n }\n });\n\n // Keyborg's focusin event is delegated so it's only registered once on the window\n // and contains metadata about the focus event\n const keyborgListener = (e: KeyborgFocusInEvent) => {\n if (keyborg.isNavigatingWithKeyboard() && isHTMLElement(e.target)) {\n // Griffel can't create chained global styles so use the parent element for now\n applyFocusWithinClass(element);\n }\n };\n\n // Make sure that when focus leaves the scope, the focus within class is removed\n const blurListener = (e: FocusEvent) => {\n if (!e.relatedTarget || (isHTMLElement(e.relatedTarget) && !element.contains(e.relatedTarget))) {\n removeFocusWithinClass(element);\n }\n };\n\n element.addEventListener(KEYBORG_FOCUSIN, keyborgListener as ListenerOverride);\n element.addEventListener('focusout', blurListener);\n\n // Return disposer\n return () => {\n element.removeEventListener(KEYBORG_FOCUSIN, keyborgListener as ListenerOverride);\n element.removeEventListener('focusout', blurListener);\n disposeKeyborg(keyborg);\n };\n}\n\nfunction applyFocusWithinClass(el: HTMLElement) {\n el.setAttribute(FOCUS_WITHIN_ATTR, '');\n}\n\nfunction removeFocusWithinClass(el: HTMLElement) {\n el.removeAttribute(FOCUS_WITHIN_ATTR);\n}\n\nfunction isHTMLElement(target: EventTarget | null): target is HTMLElement {\n if (!target) {\n return false;\n }\n return Boolean(target && typeof target === 'object' && 'classList' in target && 'contains' in target);\n}\n"],"names":["applyFocusWithinPolyfill","element","win","keyborg","createKeyborg","subscribe","isNavigatingWithKeyboard","removeFocusWithinClass","keyborgListener","e","isHTMLElement","target","applyFocusWithinClass","blurListener","relatedTarget","contains","addEventListener","KEYBORG_FOCUSIN","removeEventListener","disposeKeyborg","el","setAttribute","FOCUS_WITHIN_ATTR","removeAttribute","Boolean"],"mappings":";;;;+BAegBA;;;eAAAA;;;yBAfoE;2BAClD;AAc3B,SAASA,yBAAyBC,OAAoB,EAAEC,GAAW;IACxE,MAAMC,UAAUC,IAAAA,sBAAa,EAACF;IAE9B,0EAA0E;IAC1EC,QAAQE,SAAS,CAACC,CAAAA;QAChB,IAAI,CAACA,0BAA0B;YAC7BC,uBAAuBN;QACzB;IACF;IAEA,kFAAkF;IAClF,8CAA8C;IAC9C,MAAMO,kBAAkB,CAACC;QACvB,IAAIN,QAAQG,wBAAwB,MAAMI,cAAcD,EAAEE,MAAM,GAAG;YACjE,+EAA+E;YAC/EC,sBAAsBX;QACxB;IACF;IAEA,gFAAgF;IAChF,MAAMY,eAAe,CAACJ;QACpB,IAAI,CAACA,EAAEK,aAAa,IAAKJ,cAAcD,EAAEK,aAAa,KAAK,CAACb,QAAQc,QAAQ,CAACN,EAAEK,aAAa,GAAI;YAC9FP,uBAAuBN;QACzB;IACF;IAEAA,QAAQe,gBAAgB,CAACC,wBAAe,EAAET;IAC1CP,QAAQe,gBAAgB,CAAC,YAAYH;IAErC,kBAAkB;IAClB,OAAO;QACLZ,QAAQiB,mBAAmB,CAACD,wBAAe,EAAET;QAC7CP,QAAQiB,mBAAmB,CAAC,YAAYL;QACxCM,IAAAA,uBAAc,EAAChB;IACjB;AACF;AAEA,SAASS,sBAAsBQ,EAAe;IAC5CA,GAAGC,YAAY,CAACC,4BAAiB,EAAE;AACrC;AAEA,SAASf,uBAAuBa,EAAe;IAC7CA,GAAGG,eAAe,CAACD,4BAAiB;AACtC;AAEA,SAASZ,cAAcC,MAA0B;IAC/C,IAAI,CAACA,QAAQ;QACX,OAAO;IACT;IACA,OAAOa,QAAQb,UAAU,OAAOA,WAAW,YAAY,eAAeA,UAAU,cAAcA;AAChG"}

View File

@@ -0,0 +1,28 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
applyFocusVisiblePolyfill: function() {
return _focusVisiblePolyfill.applyFocusVisiblePolyfill;
},
applyFocusWithinPolyfill: function() {
return _focusWithinPolyfill.applyFocusWithinPolyfill;
},
createCustomFocusIndicatorStyle: function() {
return _createCustomFocusIndicatorStyle.createCustomFocusIndicatorStyle;
},
createFocusOutlineStyle: function() {
return _createFocusOutlineStyle.createFocusOutlineStyle;
}
});
const _createCustomFocusIndicatorStyle = require("./createCustomFocusIndicatorStyle");
const _createFocusOutlineStyle = require("./createFocusOutlineStyle");
const _focusVisiblePolyfill = require("./focusVisiblePolyfill");
const _focusWithinPolyfill = require("./focusWithinPolyfill");

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/focus/index.ts"],"sourcesContent":["export type { CreateCustomFocusIndicatorStyleOptions } from './createCustomFocusIndicatorStyle';\nexport { createCustomFocusIndicatorStyle } from './createCustomFocusIndicatorStyle';\nexport type {\n CreateFocusOutlineStyleOptions,\n FocusOutlineOffset,\n FocusOutlineStyleOptions,\n} from './createFocusOutlineStyle';\nexport { createFocusOutlineStyle } from './createFocusOutlineStyle';\nexport { applyFocusVisiblePolyfill } from './focusVisiblePolyfill';\nexport { applyFocusWithinPolyfill } from './focusWithinPolyfill';\n"],"names":["applyFocusVisiblePolyfill","applyFocusWithinPolyfill","createCustomFocusIndicatorStyle","createFocusOutlineStyle"],"mappings":";;;;;;;;;;;IAQSA,yBAAyB;eAAzBA,+CAAyB;;IACzBC,wBAAwB;eAAxBA,6CAAwB;;IARxBC,+BAA+B;eAA/BA,gEAA+B;;IAM/BC,uBAAuB;eAAvBA,gDAAuB;;;iDANgB;yCAMR;sCACE;qCACD"}

View File

@@ -0,0 +1,90 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
useActivateModal: function() {
return _useActivateModal.useActivateModal;
},
useArrowNavigationGroup: function() {
return _useArrowNavigationGroup.useArrowNavigationGroup;
},
useDangerousNeverHidden_unstable: function() {
return _useModalAttributes.useDangerousNeverHidden_unstable;
},
useFocusFinders: function() {
return _useFocusFinders.useFocusFinders;
},
useFocusObserved: function() {
return _useFocusObserved.useFocusObserved;
},
useFocusVisible: function() {
return _useFocusVisible.useFocusVisible;
},
useFocusWithin: function() {
return _useFocusWithin.useFocusWithin;
},
useFocusableGroup: function() {
return _useFocusableGroup.useFocusableGroup;
},
useFocusedElementChange: function() {
return _useFocusedElementChange.useFocusedElementChange;
},
useIsNavigatingWithKeyboard: function() {
return _useIsNavigatingWithKeyboard.useIsNavigatingWithKeyboard;
},
useKeyboardNavAttribute: function() {
return _useKeyboardNavAttribute.useKeyboardNavAttribute;
},
useMergedTabsterAttributes_unstable: function() {
return _useMergeTabsterAttributes.useMergedTabsterAttributes_unstable;
},
useModalAttributes: function() {
return _useModalAttributes.useModalAttributes;
},
useObservedElement: function() {
return _useObservedElement.useObservedElement;
},
useOnKeyboardNavigationChange: function() {
return _useOnKeyboardNavigationChange.useOnKeyboardNavigationChange;
},
useRestoreFocusSource: function() {
return _useRestoreFocus.useRestoreFocusSource;
},
useRestoreFocusTarget: function() {
return _useRestoreFocus.useRestoreFocusTarget;
},
useSetKeyboardNavigation: function() {
return _useSetKeyboardNavigation.useSetKeyboardNavigation;
},
useTabsterAttributes: function() {
return _useTabsterAttributes.useTabsterAttributes;
},
useUncontrolledFocus: function() {
return _useUncontrolledFocus.useUncontrolledFocus;
}
});
const _useArrowNavigationGroup = require("./useArrowNavigationGroup");
const _useFocusableGroup = require("./useFocusableGroup");
const _useFocusFinders = require("./useFocusFinders");
const _useFocusVisible = require("./useFocusVisible");
const _useFocusWithin = require("./useFocusWithin");
const _useKeyboardNavAttribute = require("./useKeyboardNavAttribute");
const _useOnKeyboardNavigationChange = require("./useOnKeyboardNavigationChange");
const _useModalAttributes = require("./useModalAttributes");
const _useTabsterAttributes = require("./useTabsterAttributes");
const _useObservedElement = require("./useObservedElement");
const _useMergeTabsterAttributes = require("./useMergeTabsterAttributes");
const _useFocusObserved = require("./useFocusObserved");
const _useRestoreFocus = require("./useRestoreFocus");
const _useUncontrolledFocus = require("./useUncontrolledFocus");
const _useIsNavigatingWithKeyboard = require("./useIsNavigatingWithKeyboard");
const _useSetKeyboardNavigation = require("./useSetKeyboardNavigation");
const _useFocusedElementChange = require("./useFocusedElementChange");
const _useActivateModal = require("./useActivateModal");

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/index.ts"],"sourcesContent":["export type { UseArrowNavigationGroupOptions } from './useArrowNavigationGroup';\nexport { useArrowNavigationGroup } from './useArrowNavigationGroup';\nexport type { UseFocusableGroupOptions } from './useFocusableGroup';\nexport { useFocusableGroup } from './useFocusableGroup';\nexport { useFocusFinders } from './useFocusFinders';\nexport { useFocusVisible } from './useFocusVisible';\nexport { useFocusWithin } from './useFocusWithin';\nexport { useKeyboardNavAttribute } from './useKeyboardNavAttribute';\nexport { useOnKeyboardNavigationChange } from './useOnKeyboardNavigationChange';\nexport type { UseModalAttributesOptions } from './useModalAttributes';\nexport { useDangerousNeverHidden_unstable, useModalAttributes } from './useModalAttributes';\nexport { useTabsterAttributes } from './useTabsterAttributes';\nexport { useObservedElement } from './useObservedElement';\nexport { useMergedTabsterAttributes_unstable } from './useMergeTabsterAttributes';\nexport { useFocusObserved } from './useFocusObserved';\nexport { useRestoreFocusSource, useRestoreFocusTarget } from './useRestoreFocus';\nexport { useUncontrolledFocus } from './useUncontrolledFocus';\nexport { useIsNavigatingWithKeyboard } from './useIsNavigatingWithKeyboard';\nexport { useSetKeyboardNavigation } from './useSetKeyboardNavigation';\nexport { useFocusedElementChange } from './useFocusedElementChange';\nexport { useActivateModal } from './useActivateModal';\n"],"names":["useActivateModal","useArrowNavigationGroup","useDangerousNeverHidden_unstable","useFocusFinders","useFocusObserved","useFocusVisible","useFocusWithin","useFocusableGroup","useFocusedElementChange","useIsNavigatingWithKeyboard","useKeyboardNavAttribute","useMergedTabsterAttributes_unstable","useModalAttributes","useObservedElement","useOnKeyboardNavigationChange","useRestoreFocusSource","useRestoreFocusTarget","useSetKeyboardNavigation","useTabsterAttributes","useUncontrolledFocus"],"mappings":";;;;;;;;;;;IAoBSA,gBAAgB;eAAhBA,kCAAgB;;IAnBhBC,uBAAuB;eAAvBA,gDAAuB;;IASvBC,gCAAgC;eAAhCA,oDAAgC;;IANhCC,eAAe;eAAfA,gCAAe;;IAUfC,gBAAgB;eAAhBA,kCAAgB;;IAThBC,eAAe;eAAfA,gCAAe;;IACfC,cAAc;eAAdA,8BAAc;;IAHdC,iBAAiB;eAAjBA,oCAAiB;;IAgBjBC,uBAAuB;eAAvBA,gDAAuB;;IAFvBC,2BAA2B;eAA3BA,wDAA2B;;IAV3BC,uBAAuB;eAAvBA,gDAAuB;;IAMvBC,mCAAmC;eAAnCA,8DAAmC;;IAHDC,kBAAkB;eAAlBA,sCAAkB;;IAEpDC,kBAAkB;eAAlBA,sCAAkB;;IAJlBC,6BAA6B;eAA7BA,4DAA6B;;IAO7BC,qBAAqB;eAArBA,sCAAqB;;IAAEC,qBAAqB;eAArBA,sCAAqB;;IAG5CC,wBAAwB;eAAxBA,kDAAwB;;IAPxBC,oBAAoB;eAApBA,0CAAoB;;IAKpBC,oBAAoB;eAApBA,0CAAoB;;;yCAfW;mCAEN;iCACF;iCACA;gCACD;yCACS;+CACM;oCAEuB;sCAChC;oCACF;2CACiB;kCACnB;iCAC4B;sCACxB;6CACO;0CACH;yCACD;kCACP"}

View File

@@ -0,0 +1,34 @@
'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "useActivateModal", {
enumerable: true,
get: function() {
return useActivateModal;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const _tabster = require("tabster");
const _reactutilities = require("@fluentui/react-utilities");
const _useTabster = require("./useTabster");
function useActivateModal() {
const modalizerRefAPI = (0, _useTabster.useTabster)(_tabster.getModalizer);
const [setActivateModalTimeout] = (0, _reactutilities.useTimeout)();
const activateModal = _react.useCallback((elementFromModal)=>{
// We call the actual activation function on the next tick, because with the typical use case,
// the hook will be called on the same tick when other Tabster attributes are being applied,
// and on the current tick the element has just received the attributes, but Tabster has not
// instantiated the Modalizer yet.
setActivateModalTimeout(()=>{
var _modalizerRefAPI_current;
(_modalizerRefAPI_current = modalizerRefAPI.current) === null || _modalizerRefAPI_current === void 0 ? void 0 : _modalizerRefAPI_current.activate(elementFromModal);
}, 0);
}, [
modalizerRefAPI,
setActivateModalTimeout
]);
return activateModal;
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useActivateModal.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { getModalizer } from 'tabster';\nimport { useTimeout } from '@fluentui/react-utilities';\nimport { useTabster } from './useTabster';\n\n/**\n * Returns a function that activates a modal by element from the modal or modal container.\n */\nexport function useActivateModal(): (elementFromModal: HTMLElement | undefined) => void {\n const modalizerRefAPI = useTabster(getModalizer);\n\n const [setActivateModalTimeout] = useTimeout();\n const activateModal = React.useCallback(\n (elementFromModal: HTMLElement | undefined) => {\n // We call the actual activation function on the next tick, because with the typical use case,\n // the hook will be called on the same tick when other Tabster attributes are being applied,\n // and on the current tick the element has just received the attributes, but Tabster has not\n // instantiated the Modalizer yet.\n setActivateModalTimeout(() => {\n modalizerRefAPI.current?.activate(elementFromModal);\n }, 0);\n },\n [modalizerRefAPI, setActivateModalTimeout],\n );\n\n return activateModal;\n}\n"],"names":["useActivateModal","modalizerRefAPI","useTabster","getModalizer","setActivateModalTimeout","useTimeout","activateModal","React","useCallback","elementFromModal","current","activate"],"mappings":"AAAA;;;;;+BAUgBA;;;eAAAA;;;;iEARO;yBACM;gCACF;4BACA;AAKpB,SAASA;IACd,MAAMC,kBAAkBC,IAAAA,sBAAU,EAACC,qBAAY;IAE/C,MAAM,CAACC,wBAAwB,GAAGC,IAAAA,0BAAU;IAC5C,MAAMC,gBAAgBC,OAAMC,WAAW,CACrC,CAACC;QACC,8FAA8F;QAC9F,4FAA4F;QAC5F,4FAA4F;QAC5F,kCAAkC;QAClCL,wBAAwB;gBACtBH;aAAAA,2BAAAA,gBAAgBS,OAAO,cAAvBT,+CAAAA,yBAAyBU,QAAQ,CAACF;QACpC,GAAG;IACL,GACA;QAACR;QAAiBG;KAAwB;IAG5C,OAAOE;AACT"}

View File

@@ -0,0 +1,48 @@
'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "useArrowNavigationGroup", {
enumerable: true,
get: function() {
return useArrowNavigationGroup;
}
});
const _tabster = require("tabster");
const _useTabsterAttributes = require("./useTabsterAttributes");
const _useTabster = require("./useTabster");
const useArrowNavigationGroup = (options = {})=>{
const { circular, axis, memorizeCurrent = true, tabbable, ignoreDefaultKeydown, // eslint-disable-next-line @typescript-eslint/naming-convention
unstable_hasDefault } = options;
(0, _useTabster.useTabster)(_tabster.getMover);
return (0, _useTabsterAttributes.useTabsterAttributes)({
mover: {
cyclic: !!circular,
direction: axisToMoverDirection(axis !== null && axis !== void 0 ? axis : 'vertical'),
memorizeCurrent,
tabbable,
hasDefault: unstable_hasDefault
},
...ignoreDefaultKeydown && {
focusable: {
ignoreKeydown: ignoreDefaultKeydown
}
}
});
};
function axisToMoverDirection(axis) {
switch(axis){
case 'horizontal':
return _tabster.MoverDirections.Horizontal;
case 'grid':
return _tabster.MoverDirections.Grid;
case 'grid-linear':
return _tabster.MoverDirections.GridLinear;
case 'both':
return _tabster.MoverDirections.Both;
case 'vertical':
default:
return _tabster.MoverDirections.Vertical;
}
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useArrowNavigationGroup.ts"],"sourcesContent":["'use client';\n\nimport { Types, getMover, MoverDirections } from 'tabster';\nimport { useTabsterAttributes } from './useTabsterAttributes';\nimport { useTabster } from './useTabster';\n\nexport interface UseArrowNavigationGroupOptions {\n /**\n * Focus will navigate vertically, horizontally or in both directions (grid), defaults to horizontally\n * @defaultValue vertical\n */\n axis?: 'vertical' | 'horizontal' | 'grid' | 'grid-linear' | 'both';\n /**\n * Focus will cycle to the first/last elements of the group without stopping\n */\n circular?: boolean;\n /**\n * Last focused element in the group will be remembered and focused (if still\n * available) when tabbing from outside of the group\n * @default true\n */\n memorizeCurrent?: boolean;\n /**\n * Allow tabbing within the arrow navigation group items.\n */\n tabbable?: boolean;\n /**\n * Tabster should ignore default handling of keydown events\n */\n ignoreDefaultKeydown?: Types.FocusableProps['ignoreKeydown'];\n /**\n * The default focusable item in the group will be an element with Focusable.isDefault property.\n * Note that there is no way in \\@fluentui/react-tabster to set default focusable element,\n * and this option is currently for internal testing purposes only.\n */\n // eslint-disable-next-line @typescript-eslint/naming-convention\n unstable_hasDefault?: boolean;\n}\n\n/**\n * A hook that returns the necessary tabster attributes to support arrow key navigation\n * @param options - Options to configure keyboard navigation\n */\nexport const useArrowNavigationGroup = (options: UseArrowNavigationGroupOptions = {}): Types.TabsterDOMAttribute => {\n const {\n circular,\n axis,\n memorizeCurrent = true,\n tabbable,\n ignoreDefaultKeydown,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n unstable_hasDefault,\n } = options;\n\n useTabster(getMover);\n\n return useTabsterAttributes({\n mover: {\n cyclic: !!circular,\n direction: axisToMoverDirection(axis ?? 'vertical'),\n memorizeCurrent,\n tabbable,\n hasDefault: unstable_hasDefault,\n },\n ...(ignoreDefaultKeydown && {\n focusable: {\n ignoreKeydown: ignoreDefaultKeydown,\n },\n }),\n });\n};\n\nfunction axisToMoverDirection(axis: UseArrowNavigationGroupOptions['axis']): Types.MoverDirection {\n switch (axis) {\n case 'horizontal':\n return MoverDirections.Horizontal;\n case 'grid':\n return MoverDirections.Grid;\n case 'grid-linear':\n return MoverDirections.GridLinear;\n case 'both':\n return MoverDirections.Both;\n\n case 'vertical':\n default:\n return MoverDirections.Vertical;\n }\n}\n"],"names":["useArrowNavigationGroup","options","circular","axis","memorizeCurrent","tabbable","ignoreDefaultKeydown","unstable_hasDefault","useTabster","getMover","useTabsterAttributes","mover","cyclic","direction","axisToMoverDirection","hasDefault","focusable","ignoreKeydown","MoverDirections","Horizontal","Grid","GridLinear","Both","Vertical"],"mappings":"AAAA;;;;;+BA2CaA;;;eAAAA;;;yBAzCoC;sCACZ;4BACV;AAuCpB,MAAMA,0BAA0B,CAACC,UAA0C,CAAC,CAAC;IAClF,MAAM,EACJC,QAAQ,EACRC,IAAI,EACJC,kBAAkB,IAAI,EACtBC,QAAQ,EACRC,oBAAoB,EACpB,gEAAgE;IAChEC,mBAAmB,EACpB,GAAGN;IAEJO,IAAAA,sBAAU,EAACC,iBAAQ;IAEnB,OAAOC,IAAAA,0CAAoB,EAAC;QAC1BC,OAAO;YACLC,QAAQ,CAAC,CAACV;YACVW,WAAWC,qBAAqBX,iBAAAA,kBAAAA,OAAQ;YACxCC;YACAC;YACAU,YAAYR;QACd;QACA,GAAID,wBAAwB;YAC1BU,WAAW;gBACTC,eAAeX;YACjB;QACF,CAAC;IACH;AACF;AAEA,SAASQ,qBAAqBX,IAA4C;IACxE,OAAQA;QACN,KAAK;YACH,OAAOe,wBAAe,CAACC,UAAU;QACnC,KAAK;YACH,OAAOD,wBAAe,CAACE,IAAI;QAC7B,KAAK;YACH,OAAOF,wBAAe,CAACG,UAAU;QACnC,KAAK;YACH,OAAOH,wBAAe,CAACI,IAAI;QAE7B,KAAK;QACL;YACE,OAAOJ,wBAAe,CAACK,QAAQ;IACnC;AACF"}

View File

@@ -0,0 +1,78 @@
'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "useFocusFinders", {
enumerable: true,
get: function() {
return useFocusFinders;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const _reactsharedcontexts = require("@fluentui/react-shared-contexts");
const _useTabster = require("./useTabster");
const useFocusFinders = ()=>{
const tabsterRef = (0, _useTabster.useTabster)();
const { targetDocument } = (0, _reactsharedcontexts.useFluent_unstable)();
// Narrow props for now and let need dictate additional props in the future
const findAllFocusable = _react.useCallback((container, acceptCondition)=>{
var _tabsterRef_current;
return container && ((_tabsterRef_current = tabsterRef.current) === null || _tabsterRef_current === void 0 ? void 0 : _tabsterRef_current.focusable.findAll({
container,
acceptCondition
})) || [];
}, [
tabsterRef
]);
const findFirstFocusable = _react.useCallback((container)=>{
var _tabsterRef_current;
return container && ((_tabsterRef_current = tabsterRef.current) === null || _tabsterRef_current === void 0 ? void 0 : _tabsterRef_current.focusable.findFirst({
container
}));
}, [
tabsterRef
]);
const findLastFocusable = _react.useCallback((container)=>{
var _tabsterRef_current;
return container && ((_tabsterRef_current = tabsterRef.current) === null || _tabsterRef_current === void 0 ? void 0 : _tabsterRef_current.focusable.findLast({
container
}));
}, [
tabsterRef
]);
const findNextFocusable = _react.useCallback((currentElement, options = {})=>{
if (!tabsterRef.current || !targetDocument || !currentElement) {
return null;
}
const { container = targetDocument.body } = options;
return tabsterRef.current.focusable.findNext({
currentElement,
container
});
}, [
tabsterRef,
targetDocument
]);
const findPrevFocusable = _react.useCallback((currentElement, options = {})=>{
if (!tabsterRef.current || !targetDocument || !currentElement) {
return null;
}
const { container = targetDocument.body } = options;
return tabsterRef.current.focusable.findPrev({
currentElement,
container
});
}, [
tabsterRef,
targetDocument
]);
return {
findAllFocusable,
findFirstFocusable,
findLastFocusable,
findNextFocusable,
findPrevFocusable
};
};

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useFocusFinders.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { Types as TabsterTypes } from 'tabster';\nimport { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';\nimport { useTabster } from './useTabster';\n\n/**\n * Returns a set of helper functions that will traverse focusable elements in the context of a root DOM element\n */\nexport const useFocusFinders = (): {\n findAllFocusable: (container: HTMLElement | null, acceptCondition?: (el: HTMLElement) => boolean) => HTMLElement[];\n findFirstFocusable: (container: HTMLElement | null) => HTMLElement | null | undefined;\n findLastFocusable: (container: HTMLElement | null) => HTMLElement | null | undefined;\n findNextFocusable: (\n currentElement: HTMLElement | null,\n options?: { container?: HTMLElement },\n ) => HTMLElement | null | undefined;\n findPrevFocusable: (\n currentElement: HTMLElement | null,\n options?: { container?: HTMLElement },\n ) => HTMLElement | null | undefined;\n} => {\n const tabsterRef = useTabster();\n const { targetDocument } = useFluent();\n\n // Narrow props for now and let need dictate additional props in the future\n const findAllFocusable = React.useCallback(\n (container: HTMLElement | null, acceptCondition?: (el: HTMLElement) => boolean) =>\n (container && tabsterRef.current?.focusable.findAll({ container, acceptCondition })) || [],\n [tabsterRef],\n );\n\n const findFirstFocusable = React.useCallback(\n (container: HTMLElement | null) => container && tabsterRef.current?.focusable.findFirst({ container }),\n [tabsterRef],\n );\n\n const findLastFocusable = React.useCallback(\n (container: HTMLElement | null) => container && tabsterRef.current?.focusable.findLast({ container }),\n [tabsterRef],\n );\n\n const findNextFocusable = React.useCallback(\n (currentElement: HTMLElement | null, options: Pick<Partial<TabsterTypes.FindNextProps>, 'container'> = {}) => {\n if (!tabsterRef.current || !targetDocument || !currentElement) {\n return null;\n }\n\n const { container = targetDocument.body } = options;\n\n return tabsterRef.current.focusable.findNext({ currentElement, container });\n },\n [tabsterRef, targetDocument],\n );\n\n const findPrevFocusable = React.useCallback(\n (currentElement: HTMLElement | null, options: Pick<Partial<TabsterTypes.FindNextProps>, 'container'> = {}) => {\n if (!tabsterRef.current || !targetDocument || !currentElement) {\n return null;\n }\n\n const { container = targetDocument.body } = options;\n\n return tabsterRef.current.focusable.findPrev({ currentElement, container });\n },\n [tabsterRef, targetDocument],\n );\n\n return {\n findAllFocusable,\n findFirstFocusable,\n findLastFocusable,\n findNextFocusable,\n findPrevFocusable,\n };\n};\n"],"names":["useFocusFinders","tabsterRef","useTabster","targetDocument","useFluent","findAllFocusable","React","useCallback","container","acceptCondition","current","focusable","findAll","findFirstFocusable","findFirst","findLastFocusable","findLast","findNextFocusable","currentElement","options","body","findNext","findPrevFocusable","findPrev"],"mappings":"AAAA;;;;;+BAUaA;;;eAAAA;;;;iEARU;qCAEyB;4BACrB;AAKpB,MAAMA,kBAAkB;IAa7B,MAAMC,aAAaC,IAAAA,sBAAU;IAC7B,MAAM,EAAEC,cAAc,EAAE,GAAGC,IAAAA,uCAAS;IAEpC,2EAA2E;IAC3E,MAAMC,mBAAmBC,OAAMC,WAAW,CACxC,CAACC,WAA+BC;YAChBR;eAAd,AAACO,eAAaP,sBAAAA,WAAWS,OAAO,cAAlBT,0CAAAA,oBAAoBU,SAAS,CAACC,OAAO,CAAC;YAAEJ;YAAWC;QAAgB,OAAO,EAAE;OAC5F;QAACR;KAAW;IAGd,MAAMY,qBAAqBP,OAAMC,WAAW,CAC1C,CAACC;YAA+CP;eAAbO,eAAaP,sBAAAA,WAAWS,OAAO,cAAlBT,0CAAAA,oBAAoBU,SAAS,CAACG,SAAS,CAAC;YAAEN;QAAU;OACpG;QAACP;KAAW;IAGd,MAAMc,oBAAoBT,OAAMC,WAAW,CACzC,CAACC;YAA+CP;eAAbO,eAAaP,sBAAAA,WAAWS,OAAO,cAAlBT,0CAAAA,oBAAoBU,SAAS,CAACK,QAAQ,CAAC;YAAER;QAAU;OACnG;QAACP;KAAW;IAGd,MAAMgB,oBAAoBX,OAAMC,WAAW,CACzC,CAACW,gBAAoCC,UAAkE,CAAC,CAAC;QACvG,IAAI,CAAClB,WAAWS,OAAO,IAAI,CAACP,kBAAkB,CAACe,gBAAgB;YAC7D,OAAO;QACT;QAEA,MAAM,EAAEV,YAAYL,eAAeiB,IAAI,EAAE,GAAGD;QAE5C,OAAOlB,WAAWS,OAAO,CAACC,SAAS,CAACU,QAAQ,CAAC;YAAEH;YAAgBV;QAAU;IAC3E,GACA;QAACP;QAAYE;KAAe;IAG9B,MAAMmB,oBAAoBhB,OAAMC,WAAW,CACzC,CAACW,gBAAoCC,UAAkE,CAAC,CAAC;QACvG,IAAI,CAAClB,WAAWS,OAAO,IAAI,CAACP,kBAAkB,CAACe,gBAAgB;YAC7D,OAAO;QACT;QAEA,MAAM,EAAEV,YAAYL,eAAeiB,IAAI,EAAE,GAAGD;QAE5C,OAAOlB,WAAWS,OAAO,CAACC,SAAS,CAACY,QAAQ,CAAC;YAAEL;YAAgBV;QAAU;IAC3E,GACA;QAACP;QAAYE;KAAe;IAG9B,OAAO;QACLE;QACAQ;QACAE;QACAE;QACAK;IACF;AACF"}

View File

@@ -0,0 +1,33 @@
'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "useFocusObserved", {
enumerable: true,
get: function() {
return useFocusObserved;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const _tabster = require("tabster");
const _useTabster = require("./useTabster");
function useFocusObserved(name, options = {}) {
const { timeout = 1000 } = options;
const observedAPIRef = (0, _useTabster.useTabster)(_tabster.getObservedElement);
return _react.useCallback(()=>{
const observerAPI = observedAPIRef.current;
if (observerAPI) {
return observerAPI.requestFocus(name, timeout);
}
return {
result: Promise.resolve(false),
cancel: ()=>null
};
}, [
observedAPIRef,
name,
timeout
]);
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useFocusObserved.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { getObservedElement, Types as TabsterTypes } from 'tabster';\nimport { useTabster } from './useTabster';\n\ninterface UseFocusObservedOptions {\n /**\n * After timeout the focus attempt fails\n */\n timeout?: number;\n}\n\n/**\n * @param name - The observed element to focus\n * @param options - Options for the focus observed\n *\n * @returns Function that will focus an element\n */\nexport function useFocusObserved(\n name: string,\n options: UseFocusObservedOptions = {},\n): () => TabsterTypes.ObservedElementAsyncRequest<boolean> {\n const { timeout = 1000 } = options;\n const observedAPIRef = useTabster(getObservedElement);\n\n return React.useCallback(() => {\n const observerAPI = observedAPIRef.current;\n\n if (observerAPI) {\n return observerAPI.requestFocus(name, timeout);\n }\n\n return {\n result: Promise.resolve(false),\n cancel: () => null,\n };\n }, [observedAPIRef, name, timeout]);\n}\n"],"names":["useFocusObserved","name","options","timeout","observedAPIRef","useTabster","getObservedElement","React","useCallback","observerAPI","current","requestFocus","result","Promise","resolve","cancel"],"mappings":"AAAA;;;;;+BAmBgBA;;;eAAAA;;;;iEAjBO;yBACmC;4BAC/B;AAepB,SAASA,iBACdC,IAAY,EACZC,UAAmC,CAAC,CAAC;IAErC,MAAM,EAAEC,UAAU,IAAI,EAAE,GAAGD;IAC3B,MAAME,iBAAiBC,IAAAA,sBAAU,EAACC,2BAAkB;IAEpD,OAAOC,OAAMC,WAAW,CAAC;QACvB,MAAMC,cAAcL,eAAeM,OAAO;QAE1C,IAAID,aAAa;YACf,OAAOA,YAAYE,YAAY,CAACV,MAAME;QACxC;QAEA,OAAO;YACLS,QAAQC,QAAQC,OAAO,CAAC;YACxBC,QAAQ,IAAM;QAChB;IACF,GAAG;QAACX;QAAgBH;QAAME;KAAQ;AACpC"}

View File

@@ -0,0 +1,30 @@
'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "useFocusVisible", {
enumerable: true,
get: function() {
return useFocusVisible;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const _reactsharedcontexts = require("@fluentui/react-shared-contexts");
const _focusVisiblePolyfill = require("../focus/focusVisiblePolyfill");
function useFocusVisible(options = {}) {
const contextValue = (0, _reactsharedcontexts.useFluent_unstable)();
const scopeRef = _react.useRef(null);
var _options_targetDocument;
const targetDocument = (_options_targetDocument = options.targetDocument) !== null && _options_targetDocument !== void 0 ? _options_targetDocument : contextValue.targetDocument;
_react.useEffect(()=>{
if ((targetDocument === null || targetDocument === void 0 ? void 0 : targetDocument.defaultView) && scopeRef.current) {
return (0, _focusVisiblePolyfill.applyFocusVisiblePolyfill)(scopeRef.current, targetDocument.defaultView);
}
}, [
scopeRef,
targetDocument
]);
return scopeRef;
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useFocusVisible.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';\n\nimport { applyFocusVisiblePolyfill } from '../focus/focusVisiblePolyfill';\n\ntype UseFocusVisibleOptions = {\n targetDocument?: Document;\n};\n\nexport function useFocusVisible<TElement extends HTMLElement = HTMLElement>(\n options: UseFocusVisibleOptions = {},\n): React.RefObject<TElement | null> {\n const contextValue = useFluent();\n const scopeRef = React.useRef<TElement>(null);\n\n const targetDocument = options.targetDocument ?? contextValue.targetDocument;\n\n React.useEffect(() => {\n if (targetDocument?.defaultView && scopeRef.current) {\n return applyFocusVisiblePolyfill(scopeRef.current, targetDocument.defaultView);\n }\n }, [scopeRef, targetDocument]);\n\n return scopeRef;\n}\n"],"names":["useFocusVisible","options","contextValue","useFluent","scopeRef","React","useRef","targetDocument","useEffect","defaultView","current","applyFocusVisiblePolyfill"],"mappings":"AAAA;;;;;+BAWgBA;;;eAAAA;;;;iEATO;qCACyB;sCAEN;AAMnC,SAASA,gBACdC,UAAkC,CAAC,CAAC;IAEpC,MAAMC,eAAeC,IAAAA,uCAAS;IAC9B,MAAMC,WAAWC,OAAMC,MAAM,CAAW;QAEjBL;IAAvB,MAAMM,iBAAiBN,CAAAA,0BAAAA,QAAQM,cAAc,cAAtBN,qCAAAA,0BAA0BC,aAAaK,cAAc;IAE5EF,OAAMG,SAAS,CAAC;QACd,IAAID,CAAAA,2BAAAA,qCAAAA,eAAgBE,WAAW,KAAIL,SAASM,OAAO,EAAE;YACnD,OAAOC,IAAAA,+CAAyB,EAACP,SAASM,OAAO,EAAEH,eAAeE,WAAW;QAC/E;IACF,GAAG;QAACL;QAAUG;KAAe;IAE7B,OAAOH;AACT"}

View File

@@ -0,0 +1,28 @@
'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "useFocusWithin", {
enumerable: true,
get: function() {
return useFocusWithin;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const _reactsharedcontexts = require("@fluentui/react-shared-contexts");
const _focusWithinPolyfill = require("../focus/focusWithinPolyfill");
function useFocusWithin() {
const { targetDocument } = (0, _reactsharedcontexts.useFluent_unstable)();
const elementRef = _react.useRef(null);
_react.useEffect(()=>{
if ((targetDocument === null || targetDocument === void 0 ? void 0 : targetDocument.defaultView) && elementRef.current) {
return (0, _focusWithinPolyfill.applyFocusWithinPolyfill)(elementRef.current, targetDocument.defaultView);
}
}, [
elementRef,
targetDocument
]);
return elementRef;
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useFocusWithin.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';\nimport { applyFocusWithinPolyfill } from '../focus/focusWithinPolyfill';\n\n/**\n * A ponyfill that allows `:focus-within` to support visibility based on keyboard/mouse navigation\n * like `:focus-visible` https://github.com/WICG/focus-visible/issues/151\n * @returns ref to the element that uses `:focus-within` styles\n */\nexport function useFocusWithin<TElement extends HTMLElement = HTMLElement>(): React.RefObject<TElement | null> {\n const { targetDocument } = useFluent();\n const elementRef = React.useRef<TElement>(null);\n\n React.useEffect(() => {\n if (targetDocument?.defaultView && elementRef.current) {\n return applyFocusWithinPolyfill(elementRef.current, targetDocument.defaultView);\n }\n }, [elementRef, targetDocument]);\n\n return elementRef;\n}\n"],"names":["useFocusWithin","targetDocument","useFluent","elementRef","React","useRef","useEffect","defaultView","current","applyFocusWithinPolyfill"],"mappings":"AAAA;;;;;+BAWgBA;;;eAAAA;;;;iEATO;qCACyB;qCACP;AAOlC,SAASA;IACd,MAAM,EAAEC,cAAc,EAAE,GAAGC,IAAAA,uCAAS;IACpC,MAAMC,aAAaC,OAAMC,MAAM,CAAW;IAE1CD,OAAME,SAAS,CAAC;QACd,IAAIL,CAAAA,2BAAAA,qCAAAA,eAAgBM,WAAW,KAAIJ,WAAWK,OAAO,EAAE;YACrD,OAAOC,IAAAA,6CAAwB,EAACN,WAAWK,OAAO,EAAEP,eAAeM,WAAW;QAChF;IACF,GAAG;QAACJ;QAAYF;KAAe;IAE/B,OAAOE;AACT"}

View File

@@ -0,0 +1,37 @@
'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "useFocusableGroup", {
enumerable: true,
get: function() {
return useFocusableGroup;
}
});
const _tabster = require("tabster");
const _useTabsterAttributes = require("./useTabsterAttributes");
const _useTabster = require("./useTabster");
const useFocusableGroup = (options)=>{
(0, _useTabster.useTabster)(_tabster.getGroupper);
return (0, _useTabsterAttributes.useTabsterAttributes)({
groupper: {
tabbability: getTabbability(options === null || options === void 0 ? void 0 : options.tabBehavior)
},
focusable: {
ignoreKeydown: options === null || options === void 0 ? void 0 : options.ignoreDefaultKeydown
}
});
};
const getTabbability = (tabBehavior)=>{
switch(tabBehavior){
case 'unlimited':
return _tabster.GroupperTabbabilities.Unlimited;
case 'limited':
return _tabster.GroupperTabbabilities.Limited;
case 'limited-trap-focus':
return _tabster.GroupperTabbabilities.LimitedTrapFocus;
default:
return undefined;
}
};

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useFocusableGroup.ts"],"sourcesContent":["'use client';\n\nimport { Types, getGroupper, GroupperTabbabilities } from 'tabster';\nimport { useTabsterAttributes } from './useTabsterAttributes';\nimport { useTabster } from './useTabster';\n\nexport interface UseFocusableGroupOptions {\n /**\n * Behavior for the Tab key.\n */\n tabBehavior?: 'unlimited' | 'limited' | 'limited-trap-focus';\n\n /**\n * Tabster can ignore default handling of keydown events\n */\n ignoreDefaultKeydown?: Types.FocusableProps['ignoreKeydown'];\n}\n\n/**\n * A hook that returns the necessary tabster attributes to support groupping.\n * @param options - Options to configure keyboard navigation\n */\nexport const useFocusableGroup = (options?: UseFocusableGroupOptions): Types.TabsterDOMAttribute => {\n useTabster(getGroupper);\n\n return useTabsterAttributes({\n groupper: {\n tabbability: getTabbability(options?.tabBehavior),\n },\n focusable: {\n ignoreKeydown: options?.ignoreDefaultKeydown,\n },\n });\n};\n\nconst getTabbability = (\n tabBehavior?: UseFocusableGroupOptions['tabBehavior'],\n): Types.GroupperTabbability | undefined => {\n switch (tabBehavior) {\n case 'unlimited':\n return GroupperTabbabilities.Unlimited;\n case 'limited':\n return GroupperTabbabilities.Limited;\n case 'limited-trap-focus':\n return GroupperTabbabilities.LimitedTrapFocus;\n default:\n return undefined;\n }\n};\n"],"names":["useFocusableGroup","options","useTabster","getGroupper","useTabsterAttributes","groupper","tabbability","getTabbability","tabBehavior","focusable","ignoreKeydown","ignoreDefaultKeydown","GroupperTabbabilities","Unlimited","Limited","LimitedTrapFocus","undefined"],"mappings":"AAAA;;;;;+BAsBaA;;;eAAAA;;;yBApB6C;sCACrB;4BACV;AAkBpB,MAAMA,oBAAoB,CAACC;IAChCC,IAAAA,sBAAU,EAACC,oBAAW;IAEtB,OAAOC,IAAAA,0CAAoB,EAAC;QAC1BC,UAAU;YACRC,aAAaC,eAAeN,oBAAAA,8BAAAA,QAASO,WAAW;QAClD;QACAC,WAAW;YACTC,aAAa,EAAET,oBAAAA,8BAAAA,QAASU,oBAAoB;QAC9C;IACF;AACF;AAEA,MAAMJ,iBAAiB,CACrBC;IAEA,OAAQA;QACN,KAAK;YACH,OAAOI,8BAAqB,CAACC,SAAS;QACxC,KAAK;YACH,OAAOD,8BAAqB,CAACE,OAAO;QACtC,KAAK;YACH,OAAOF,8BAAqB,CAACG,gBAAgB;QAC/C;YACE,OAAOC;IACX;AACF"}

View File

@@ -0,0 +1,34 @@
'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "useFocusedElementChange", {
enumerable: true,
get: function() {
return useFocusedElementChange;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _tabster = require("tabster");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const _reactsharedcontexts = require("@fluentui/react-shared-contexts");
const _reactutilities = require("@fluentui/react-utilities");
const _useTabster = require("./useTabster");
function useFocusedElementChange(callback) {
const { targetDocument } = (0, _reactsharedcontexts.useFluent_unstable)();
const listener = (0, _reactutilities.useEventCallback)(callback);
_react.useEffect(()=>{
const tabster = (0, _useTabster.createTabsterWithConfig)(targetDocument);
if (tabster) {
tabster.focusedElement.subscribe(listener);
return ()=>{
tabster.focusedElement.unsubscribe(listener);
(0, _tabster.disposeTabster)(tabster);
};
}
}, [
listener,
targetDocument
]);
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useFocusedElementChange.ts"],"sourcesContent":["'use client';\n\nimport { type Types as TabsterTypes, disposeTabster } from 'tabster';\nimport * as React from 'react';\nimport { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';\nimport { useEventCallback } from '@fluentui/react-utilities';\n\nimport { createTabsterWithConfig } from './useTabster';\n\n/**\n * Subscribes to the tabster focused element. Calls the callback when the focused element changes.\n * @param callback - Callback to subscribe to the focused element.\n */\nexport function useFocusedElementChange(\n callback: TabsterTypes.SubscribableCallback<HTMLElement | undefined, TabsterTypes.FocusedElementDetail>,\n): void {\n const { targetDocument } = useFluent();\n const listener = useEventCallback(callback);\n\n React.useEffect(() => {\n const tabster = createTabsterWithConfig(targetDocument);\n\n if (tabster) {\n tabster.focusedElement.subscribe(listener);\n\n return () => {\n tabster.focusedElement.unsubscribe(listener);\n disposeTabster(tabster);\n };\n }\n }, [listener, targetDocument]);\n}\n"],"names":["useFocusedElementChange","callback","targetDocument","useFluent","listener","useEventCallback","React","useEffect","tabster","createTabsterWithConfig","focusedElement","subscribe","unsubscribe","disposeTabster"],"mappings":"AAAA;;;;;+BAagBA;;;eAAAA;;;;yBAX2C;iEACpC;qCACyB;gCACf;4BAEO;AAMjC,SAASA,wBACdC,QAAuG;IAEvG,MAAM,EAAEC,cAAc,EAAE,GAAGC,IAAAA,uCAAS;IACpC,MAAMC,WAAWC,IAAAA,gCAAgB,EAACJ;IAElCK,OAAMC,SAAS,CAAC;QACd,MAAMC,UAAUC,IAAAA,mCAAuB,EAACP;QAExC,IAAIM,SAAS;YACXA,QAAQE,cAAc,CAACC,SAAS,CAACP;YAEjC,OAAO;gBACLI,QAAQE,cAAc,CAACE,WAAW,CAACR;gBACnCS,IAAAA,uBAAc,EAACL;YACjB;QACF;IACF,GAAG;QAACJ;QAAUF;KAAe;AAC/B"}

View File

@@ -0,0 +1,24 @@
'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "useIsNavigatingWithKeyboard", {
enumerable: true,
get: function() {
return useIsNavigatingWithKeyboard;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const _useKeyborgRef = require("./useKeyborgRef");
function useIsNavigatingWithKeyboard() {
const keyborgRef = (0, _useKeyborgRef.useKeyborgRef)();
return _react.useCallback(()=>{
var _keyborgRef_current;
var _keyborgRef_current_isNavigatingWithKeyboard;
return (_keyborgRef_current_isNavigatingWithKeyboard = (_keyborgRef_current = keyborgRef.current) === null || _keyborgRef_current === void 0 ? void 0 : _keyborgRef_current.isNavigatingWithKeyboard()) !== null && _keyborgRef_current_isNavigatingWithKeyboard !== void 0 ? _keyborgRef_current_isNavigatingWithKeyboard : false;
}, [
keyborgRef
]);
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useIsNavigatingWithKeyboard.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { useKeyborgRef } from './useKeyborgRef';\n\n/**\n * Instantiates [keyborg](https://github.com/microsoft/keyborg) and checks if the user is navigating with the keyboard.\n * @returns\n */\nexport function useIsNavigatingWithKeyboard(): () => boolean {\n const keyborgRef = useKeyborgRef();\n\n return React.useCallback(() => {\n return keyborgRef.current?.isNavigatingWithKeyboard() ?? false;\n }, [keyborgRef]);\n}\n"],"names":["useIsNavigatingWithKeyboard","keyborgRef","useKeyborgRef","React","useCallback","current","isNavigatingWithKeyboard"],"mappings":"AAAA;;;;;+BASgBA;;;eAAAA;;;;iEAPO;+BACO;AAMvB,SAASA;IACd,MAAMC,aAAaC,IAAAA,4BAAa;IAEhC,OAAOC,OAAMC,WAAW,CAAC;YAChBH;YAAAA;QAAP,OAAOA,CAAAA,gDAAAA,sBAAAA,WAAWI,OAAO,cAAlBJ,0CAAAA,oBAAoBK,wBAAwB,gBAA5CL,0DAAAA,+CAAkD;IAC3D,GAAG;QAACA;KAAW;AACjB"}

View File

@@ -0,0 +1,46 @@
'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "useKeyboardNavAttribute", {
enumerable: true,
get: function() {
return useKeyboardNavAttribute;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const _keyborg = require("keyborg");
const _constants = require("../focus/constants");
const _reactsharedcontexts = require("@fluentui/react-shared-contexts");
function useKeyboardNavAttribute() {
const { targetDocument } = (0, _reactsharedcontexts.useFluent_unstable)();
const keyborg = _react.useMemo(()=>targetDocument && (0, _keyborg.createKeyborg)(targetDocument.defaultView), [
targetDocument
]);
const ref = _react.useRef(null);
_react.useEffect(()=>{
if (keyborg) {
setBooleanAttribute(ref, _constants.KEYBOARD_NAV_ATTRIBUTE, keyborg.isNavigatingWithKeyboard());
const cb = (next)=>{
setBooleanAttribute(ref, _constants.KEYBOARD_NAV_ATTRIBUTE, next);
};
keyborg.subscribe(cb);
return ()=>keyborg.unsubscribe(cb);
}
}, [
keyborg
]);
return ref;
}
function setBooleanAttribute(elementRef, attribute, value) {
if (!elementRef.current) {
return;
}
if (value) {
elementRef.current.setAttribute(attribute, '');
} else {
elementRef.current.removeAttribute(attribute);
}
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useKeyboardNavAttribute.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { createKeyborg } from 'keyborg';\nimport { KEYBOARD_NAV_ATTRIBUTE } from '../focus/constants';\nimport { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';\nimport type { KeyborgCallback } from 'keyborg';\n\n/**\n * Instantiates [keyborg](https://github.com/microsoft/keyborg) and adds `data-keyboard-nav`\n * attribute to a referenced element to ensure keyboard navigation awareness\n * synced to keyborg logic without having to cause a re-render on react tree.\n */\nexport function useKeyboardNavAttribute<E extends HTMLElement>(): React.RefObject<E | null> {\n const { targetDocument } = useFluent();\n const keyborg = React.useMemo(() => targetDocument && createKeyborg(targetDocument.defaultView!), [targetDocument]);\n const ref = React.useRef<E>(null);\n React.useEffect(() => {\n if (keyborg) {\n setBooleanAttribute(ref, KEYBOARD_NAV_ATTRIBUTE, keyborg.isNavigatingWithKeyboard());\n const cb: KeyborgCallback = next => {\n setBooleanAttribute(ref, KEYBOARD_NAV_ATTRIBUTE, next);\n };\n keyborg.subscribe(cb);\n return () => keyborg.unsubscribe(cb);\n }\n }, [keyborg]);\n\n return ref;\n}\n\nfunction setBooleanAttribute(elementRef: React.RefObject<HTMLElement | null>, attribute: string, value: boolean) {\n if (!elementRef.current) {\n return;\n }\n if (value) {\n elementRef.current.setAttribute(attribute, '');\n } else {\n elementRef.current.removeAttribute(attribute);\n }\n}\n"],"names":["useKeyboardNavAttribute","targetDocument","useFluent","keyborg","React","useMemo","createKeyborg","defaultView","ref","useRef","useEffect","setBooleanAttribute","KEYBOARD_NAV_ATTRIBUTE","isNavigatingWithKeyboard","cb","next","subscribe","unsubscribe","elementRef","attribute","value","current","setAttribute","removeAttribute"],"mappings":"AAAA;;;;;+BAagBA;;;eAAAA;;;;iEAXO;yBACO;2BACS;qCACS;AAQzC,SAASA;IACd,MAAM,EAAEC,cAAc,EAAE,GAAGC,IAAAA,uCAAS;IACpC,MAAMC,UAAUC,OAAMC,OAAO,CAAC,IAAMJ,kBAAkBK,IAAAA,sBAAa,EAACL,eAAeM,WAAW,GAAI;QAACN;KAAe;IAClH,MAAMO,MAAMJ,OAAMK,MAAM,CAAI;IAC5BL,OAAMM,SAAS,CAAC;QACd,IAAIP,SAAS;YACXQ,oBAAoBH,KAAKI,iCAAsB,EAAET,QAAQU,wBAAwB;YACjF,MAAMC,KAAsBC,CAAAA;gBAC1BJ,oBAAoBH,KAAKI,iCAAsB,EAAEG;YACnD;YACAZ,QAAQa,SAAS,CAACF;YAClB,OAAO,IAAMX,QAAQc,WAAW,CAACH;QACnC;IACF,GAAG;QAACX;KAAQ;IAEZ,OAAOK;AACT;AAEA,SAASG,oBAAoBO,UAA+C,EAAEC,SAAiB,EAAEC,KAAc;IAC7G,IAAI,CAACF,WAAWG,OAAO,EAAE;QACvB;IACF;IACA,IAAID,OAAO;QACTF,WAAWG,OAAO,CAACC,YAAY,CAACH,WAAW;IAC7C,OAAO;QACLD,WAAWG,OAAO,CAACE,eAAe,CAACJ;IACrC;AACF"}

View File

@@ -0,0 +1,33 @@
'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "useKeyborgRef", {
enumerable: true,
get: function() {
return useKeyborgRef;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const _keyborg = require("keyborg");
const _reactsharedcontexts = require("@fluentui/react-shared-contexts");
function useKeyborgRef() {
const { targetDocument } = (0, _reactsharedcontexts.useFluent_unstable)();
const keyborgRef = _react.useRef(null);
_react.useEffect(()=>{
const targetWindow = targetDocument === null || targetDocument === void 0 ? void 0 : targetDocument.defaultView;
if (targetWindow) {
const keyborg = (0, _keyborg.createKeyborg)(targetWindow);
keyborgRef.current = keyborg;
return ()=>{
(0, _keyborg.disposeKeyborg)(keyborg);
keyborgRef.current = null;
};
}
}, [
targetDocument
]);
return keyborgRef;
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useKeyborgRef.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { createKeyborg, disposeKeyborg, type Keyborg } from 'keyborg';\nimport { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';\n\n/**\n * @internal\n * Instantiates [keyborg](https://github.com/microsoft/keyborg)\n * @returns - keyborg instance\n */\nexport function useKeyborgRef(): React.RefObject<Keyborg | null> {\n const { targetDocument } = useFluent();\n const keyborgRef = React.useRef<Keyborg | null>(null);\n\n React.useEffect(() => {\n const targetWindow = targetDocument?.defaultView;\n\n if (targetWindow) {\n const keyborg = createKeyborg(targetWindow);\n keyborgRef.current = keyborg;\n\n return () => {\n disposeKeyborg(keyborg);\n keyborgRef.current = null;\n };\n }\n }, [targetDocument]);\n\n return keyborgRef;\n}\n"],"names":["useKeyborgRef","targetDocument","useFluent","keyborgRef","React","useRef","useEffect","targetWindow","defaultView","keyborg","createKeyborg","current","disposeKeyborg"],"mappings":"AAAA;;;;;+BAWgBA;;;eAAAA;;;;iEATO;yBACqC;qCACZ;AAOzC,SAASA;IACd,MAAM,EAAEC,cAAc,EAAE,GAAGC,IAAAA,uCAAS;IACpC,MAAMC,aAAaC,OAAMC,MAAM,CAAiB;IAEhDD,OAAME,SAAS,CAAC;QACd,MAAMC,eAAeN,2BAAAA,qCAAAA,eAAgBO,WAAW;QAEhD,IAAID,cAAc;YAChB,MAAME,UAAUC,IAAAA,sBAAa,EAACH;YAC9BJ,WAAWQ,OAAO,GAAGF;YAErB,OAAO;gBACLG,IAAAA,uBAAc,EAACH;gBACfN,WAAWQ,OAAO,GAAG;YACvB;QACF;IACF,GAAG;QAACV;KAAe;IAEnB,OAAOE;AACT"}

View File

@@ -0,0 +1,80 @@
'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "useMergedTabsterAttributes_unstable", {
enumerable: true,
get: function() {
return useMergedTabsterAttributes_unstable;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const _tabster = require("tabster");
const useMergedTabsterAttributes_unstable = (...attributes)=>{
'use no memo';
const stringAttributes = attributes.reduce((acc, curr)=>{
if (curr === null || curr === void 0 ? void 0 : curr[_tabster.TABSTER_ATTRIBUTE_NAME]) {
acc.push(curr[_tabster.TABSTER_ATTRIBUTE_NAME]);
}
return acc;
}, []);
if (process.env.NODE_ENV !== 'production') {
// ignoring rules of hooks because this is a condition based on the environment
// it's safe to ignore the rule
// eslint-disable-next-line react-hooks/rules-of-hooks
useWarnIfUnstableAttributes(stringAttributes);
}
return _react.useMemo(()=>({
[_tabster.TABSTER_ATTRIBUTE_NAME]: stringAttributes.length > 0 ? stringAttributes.reduce(mergeJSONStrings) : undefined
}), // disable exhaustive-deps because we want to memoize the result of the reduction
// this is safe because the collection of attributes is not expected to change at runtime
// eslint-disable-next-line react-hooks/exhaustive-deps
stringAttributes);
};
/**
* Merges two JSON strings into one.
*/ const mergeJSONStrings = (a, b)=>JSON.stringify(Object.assign(safelyParseJSON(a), safelyParseJSON(b)));
/**
* Tries to parse a JSON string and returns an object.
* If the JSON string is invalid, an empty object is returned.
*/ const safelyParseJSON = (json)=>{
try {
return JSON.parse(json);
} catch {
return {};
}
};
/**
* Helper hook that ensures that the attributes passed to the hook are stable.
* This is necessary because the attributes are expected to not change at runtime.
*
* This hook will console.warn if the attributes change at runtime.
*/ const useWarnIfUnstableAttributes = (attributes)=>{
'use no memo';
const initialAttributesRef = _react.useRef(attributes);
let isStable = initialAttributesRef.current.length === attributes.length;
if (initialAttributesRef.current !== attributes && isStable) {
for(let i = 0; i < attributes.length; i++){
if (initialAttributesRef.current[i] !== attributes[i]) {
isStable = false;
break;
}
}
}
_react.useEffect(()=>{
if (!isStable) {
const error = new Error();
// eslint-disable-next-line no-console
console.warn(/** #__DE-INDENT__ */ `
@fluentui/react-tabster [useMergedTabsterAttributes]:
The attributes passed to the hook changed at runtime.
This might lead to unexpected behavior, please ensure that the attributes are stable.
${error.stack}
`);
}
}, [
isStable
]);
};

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useMergeTabsterAttributes.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { Types, TABSTER_ATTRIBUTE_NAME } from 'tabster';\n\n/**\n * Merges a collection of tabster attributes.\n *\n * ⚠The attributes passed as arguments to this hook cannot change at runtime.\n * @internal\n * @param attributes - collection of tabster attributes from other react-tabster hooks\n * @returns single merged tabster attribute\n */\nexport const useMergedTabsterAttributes_unstable = (\n ...attributes: (Partial<Types.TabsterDOMAttribute> | null | undefined)[]\n): Types.TabsterDOMAttribute => {\n 'use no memo';\n\n const stringAttributes = attributes.reduce<string[]>((acc, curr) => {\n if (curr?.[TABSTER_ATTRIBUTE_NAME]) {\n acc.push(curr[TABSTER_ATTRIBUTE_NAME]);\n }\n return acc;\n }, []);\n\n if (process.env.NODE_ENV !== 'production') {\n // ignoring rules of hooks because this is a condition based on the environment\n // it's safe to ignore the rule\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useWarnIfUnstableAttributes(stringAttributes);\n }\n\n return React.useMemo(\n () => ({\n [TABSTER_ATTRIBUTE_NAME]: stringAttributes.length > 0 ? stringAttributes.reduce(mergeJSONStrings) : undefined,\n }),\n // disable exhaustive-deps because we want to memoize the result of the reduction\n // this is safe because the collection of attributes is not expected to change at runtime\n // eslint-disable-next-line react-hooks/exhaustive-deps\n stringAttributes,\n );\n};\n\n/**\n * Merges two JSON strings into one.\n */\nconst mergeJSONStrings = (a: string, b: string): string =>\n JSON.stringify(Object.assign(safelyParseJSON(a), safelyParseJSON(b)));\n\n/**\n * Tries to parse a JSON string and returns an object.\n * If the JSON string is invalid, an empty object is returned.\n */\nconst safelyParseJSON = (json: string): object => {\n try {\n return JSON.parse(json);\n } catch {\n return {};\n }\n};\n\n/**\n * Helper hook that ensures that the attributes passed to the hook are stable.\n * This is necessary because the attributes are expected to not change at runtime.\n *\n * This hook will console.warn if the attributes change at runtime.\n */\nconst useWarnIfUnstableAttributes = (attributes: string[]) => {\n 'use no memo';\n\n const initialAttributesRef = React.useRef(attributes);\n\n let isStable = initialAttributesRef.current.length === attributes.length;\n if (initialAttributesRef.current !== attributes && isStable) {\n for (let i = 0; i < attributes.length; i++) {\n if (initialAttributesRef.current[i] !== attributes[i]) {\n isStable = false;\n break;\n }\n }\n }\n React.useEffect(() => {\n if (!isStable) {\n const error = new Error();\n // eslint-disable-next-line no-console\n console.warn(/** #__DE-INDENT__ */ `\n @fluentui/react-tabster [useMergedTabsterAttributes]:\n The attributes passed to the hook changed at runtime.\n This might lead to unexpected behavior, please ensure that the attributes are stable.\n ${error.stack}\n `);\n }\n }, [isStable]);\n};\n"],"names":["useMergedTabsterAttributes_unstable","attributes","stringAttributes","reduce","acc","curr","TABSTER_ATTRIBUTE_NAME","push","process","env","NODE_ENV","useWarnIfUnstableAttributes","React","useMemo","length","mergeJSONStrings","undefined","a","b","JSON","stringify","Object","assign","safelyParseJSON","json","parse","initialAttributesRef","useRef","isStable","current","i","useEffect","error","Error","console","warn","stack"],"mappings":"AAAA;;;;;+BAaaA;;;eAAAA;;;;iEAXU;yBACuB;AAUvC,MAAMA,sCAAsC,CACjD,GAAGC;IAEH;IAEA,MAAMC,mBAAmBD,WAAWE,MAAM,CAAW,CAACC,KAAKC;QACzD,IAAIA,iBAAAA,2BAAAA,IAAM,CAACC,+BAAsB,CAAC,EAAE;YAClCF,IAAIG,IAAI,CAACF,IAAI,CAACC,+BAAsB,CAAC;QACvC;QACA,OAAOF;IACT,GAAG,EAAE;IAEL,IAAII,QAAQC,GAAG,CAACC,QAAQ,KAAK,cAAc;QACzC,+EAA+E;QAC/E,+BAA+B;QAC/B,sDAAsD;QACtDC,4BAA4BT;IAC9B;IAEA,OAAOU,OAAMC,OAAO,CAClB,IAAO,CAAA;YACL,CAACP,+BAAsB,CAAC,EAAEJ,iBAAiBY,MAAM,GAAG,IAAIZ,iBAAiBC,MAAM,CAACY,oBAAoBC;QACtG,CAAA,GACA,iFAAiF;IACjF,yFAAyF;IACzF,uDAAuD;IACvDd;AAEJ;AAEA;;CAEC,GACD,MAAMa,mBAAmB,CAACE,GAAWC,IACnCC,KAAKC,SAAS,CAACC,OAAOC,MAAM,CAACC,gBAAgBN,IAAIM,gBAAgBL;AAEnE;;;CAGC,GACD,MAAMK,kBAAkB,CAACC;IACvB,IAAI;QACF,OAAOL,KAAKM,KAAK,CAACD;IACpB,EAAE,OAAM;QACN,OAAO,CAAC;IACV;AACF;AAEA;;;;;CAKC,GACD,MAAMb,8BAA8B,CAACV;IACnC;IAEA,MAAMyB,uBAAuBd,OAAMe,MAAM,CAAC1B;IAE1C,IAAI2B,WAAWF,qBAAqBG,OAAO,CAACf,MAAM,KAAKb,WAAWa,MAAM;IACxE,IAAIY,qBAAqBG,OAAO,KAAK5B,cAAc2B,UAAU;QAC3D,IAAK,IAAIE,IAAI,GAAGA,IAAI7B,WAAWa,MAAM,EAAEgB,IAAK;YAC1C,IAAIJ,qBAAqBG,OAAO,CAACC,EAAE,KAAK7B,UAAU,CAAC6B,EAAE,EAAE;gBACrDF,WAAW;gBACX;YACF;QACF;IACF;IACAhB,OAAMmB,SAAS,CAAC;QACd,IAAI,CAACH,UAAU;YACb,MAAMI,QAAQ,IAAIC;YAClB,sCAAsC;YACtCC,QAAQC,IAAI,CAAC,mBAAmB,GAAG,CAAC;;;;QAIlC,EAAEH,MAAMI,KAAK,CAAC;MAChB,CAAC;QACH;IACF,GAAG;QAACR;KAAS;AACf"}

View File

@@ -0,0 +1,65 @@
'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
useDangerousNeverHidden_unstable: function() {
return useDangerousNeverHidden_unstable;
},
useModalAttributes: function() {
return useModalAttributes;
}
});
const _reactutilities = require("@fluentui/react-utilities");
const _useTabsterAttributes = require("./useTabsterAttributes");
const _tabster = require("tabster");
const _useTabster = require("./useTabster");
const DangerousNeverHiddenAttribute = 'data-tabster-never-hide';
const DangerousNeverHiddenPropObject = {
[DangerousNeverHiddenAttribute]: ''
};
function useDangerousNeverHidden_unstable() {
return DangerousNeverHiddenPropObject;
}
const tabsterAccessibleCheck = (element)=>{
return element.hasAttribute(DangerousNeverHiddenAttribute);
};
function initTabsterModules(tabster) {
(0, _tabster.getModalizer)(tabster, undefined, tabsterAccessibleCheck);
(0, _tabster.getRestorer)(tabster);
}
const useModalAttributes = (options = {})=>{
const { trapFocus, alwaysFocusable, legacyTrapFocus } = options;
// Initializes the modalizer and restorer APIs
(0, _useTabster.useTabster)(initTabsterModules);
const id = (0, _reactutilities.useId)('modal-', options.id);
const modalAttributes = (0, _useTabsterAttributes.useTabsterAttributes)({
restorer: {
type: _tabster.RestorerTypes.Source
},
...trapFocus && {
modalizer: {
id,
isOthersAccessible: !trapFocus,
isAlwaysAccessible: alwaysFocusable,
isTrapped: legacyTrapFocus && trapFocus
}
}
});
const triggerAttributes = (0, _useTabsterAttributes.useTabsterAttributes)({
restorer: {
type: _tabster.RestorerTypes.Target
}
});
return {
modalAttributes,
triggerAttributes
};
};

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useModalAttributes.ts"],"sourcesContent":["'use client';\n\nimport { useId } from '@fluentui/react-utilities';\nimport { useTabsterAttributes } from './useTabsterAttributes';\nimport { getModalizer, getRestorer, Types as TabsterTypes, RestorerTypes } from 'tabster';\nimport { useTabster } from './useTabster';\n\nconst DangerousNeverHiddenAttribute = 'data-tabster-never-hide';\nconst DangerousNeverHiddenPropObject = { [DangerousNeverHiddenAttribute]: '' };\n\nexport interface UseModalAttributesOptions {\n /**\n * Traps focus inside the elements the attributes are applied.\n * it forbids users to tab out of the focus trap into the actual browser.\n */\n trapFocus?: boolean;\n\n /**\n * Traps focus inside the elements the attributes are applied.\n * This prop enables traditional force-focus behavior to match previous versions of Fluent.\n * Without this, users can tab out of the focus trap and into the browser chrome.\n * This matches the behavior of the native <dialog> element and inert.\n * We recommend setting this to true based on user feedback and consistency.\n */\n legacyTrapFocus?: boolean;\n\n /**\n * Always reachabled in Tab order\n */\n alwaysFocusable?: boolean;\n\n /**\n * Id to use for the modalizer. An id will be generated if not provided.\n */\n id?: string;\n}\n\n/**\n * !!DANGEROUS!! Designates an element that will not be hidden even when outside an open modal.\n * Only works for top-level elements; should be used with extreme care.\n * @returns Attribute to apply to the target element that should never receive aria-hidden\n */\nexport function useDangerousNeverHidden_unstable(): { [key: string]: string } {\n return DangerousNeverHiddenPropObject;\n}\n\nconst tabsterAccessibleCheck: TabsterTypes.ModalizerElementAccessibleCheck = element => {\n return element.hasAttribute(DangerousNeverHiddenAttribute);\n};\n\nfunction initTabsterModules(tabster: TabsterTypes.TabsterCore) {\n getModalizer(tabster, undefined, tabsterAccessibleCheck);\n getRestorer(tabster);\n}\n\n/**\n * Applies modal dialog behaviour through DOM attributes\n * Modal element will focus trap and hide other content on the page\n * The trigger element will be focused if focus is lost after the modal element is removed\n *\n * @returns DOM attributes to apply to the modal element and its trigger\n */\nexport const useModalAttributes = (\n options: UseModalAttributesOptions = {},\n): { modalAttributes: TabsterTypes.TabsterDOMAttribute; triggerAttributes: TabsterTypes.TabsterDOMAttribute } => {\n const { trapFocus, alwaysFocusable, legacyTrapFocus } = options;\n\n // Initializes the modalizer and restorer APIs\n useTabster(initTabsterModules);\n\n const id = useId('modal-', options.id);\n const modalAttributes = useTabsterAttributes({\n restorer: { type: RestorerTypes.Source },\n ...(trapFocus && {\n modalizer: {\n id,\n isOthersAccessible: !trapFocus,\n isAlwaysAccessible: alwaysFocusable,\n isTrapped: legacyTrapFocus && trapFocus,\n },\n }),\n });\n\n const triggerAttributes = useTabsterAttributes({\n restorer: { type: RestorerTypes.Target },\n });\n\n return { modalAttributes, triggerAttributes };\n};\n"],"names":["useDangerousNeverHidden_unstable","useModalAttributes","DangerousNeverHiddenAttribute","DangerousNeverHiddenPropObject","tabsterAccessibleCheck","element","hasAttribute","initTabsterModules","tabster","getModalizer","undefined","getRestorer","options","trapFocus","alwaysFocusable","legacyTrapFocus","useTabster","id","useId","modalAttributes","useTabsterAttributes","restorer","type","RestorerTypes","Source","modalizer","isOthersAccessible","isAlwaysAccessible","isTrapped","triggerAttributes","Target"],"mappings":"AAAA;;;;;;;;;;;;IA0CgBA,gCAAgC;eAAhCA;;IAoBHC,kBAAkB;eAAlBA;;;gCA5DS;sCACe;yBAC2C;4BACrD;AAE3B,MAAMC,gCAAgC;AACtC,MAAMC,iCAAiC;IAAE,CAACD,8BAA8B,EAAE;AAAG;AAkCtE,SAASF;IACd,OAAOG;AACT;AAEA,MAAMC,yBAAuEC,CAAAA;IAC3E,OAAOA,QAAQC,YAAY,CAACJ;AAC9B;AAEA,SAASK,mBAAmBC,OAAiC;IAC3DC,IAAAA,qBAAY,EAACD,SAASE,WAAWN;IACjCO,IAAAA,oBAAW,EAACH;AACd;AASO,MAAMP,qBAAqB,CAChCW,UAAqC,CAAC,CAAC;IAEvC,MAAM,EAAEC,SAAS,EAAEC,eAAe,EAAEC,eAAe,EAAE,GAAGH;IAExD,8CAA8C;IAC9CI,IAAAA,sBAAU,EAACT;IAEX,MAAMU,KAAKC,IAAAA,qBAAK,EAAC,UAAUN,QAAQK,EAAE;IACrC,MAAME,kBAAkBC,IAAAA,0CAAoB,EAAC;QAC3CC,UAAU;YAAEC,MAAMC,sBAAa,CAACC,MAAM;QAAC;QACvC,GAAIX,aAAa;YACfY,WAAW;gBACTR;gBACAS,oBAAoB,CAACb;gBACrBc,oBAAoBb;gBACpBc,WAAWb,mBAAmBF;YAChC;QACF,CAAC;IACH;IAEA,MAAMgB,oBAAoBT,IAAAA,0CAAoB,EAAC;QAC7CC,UAAU;YAAEC,MAAMC,sBAAa,CAACO,MAAM;QAAC;IACzC;IAEA,OAAO;QAAEX;QAAiBU;IAAkB;AAC9C"}

View File

@@ -0,0 +1,24 @@
'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "useObservedElement", {
enumerable: true,
get: function() {
return useObservedElement;
}
});
const _tabster = require("tabster");
const _useTabster = require("./useTabster");
const _useTabsterAttributes = require("./useTabsterAttributes");
function useObservedElement(name) {
(0, _useTabster.useTabster)(_tabster.getObservedElement);
return (0, _useTabsterAttributes.useTabsterAttributes)({
observed: {
names: Array.isArray(name) ? name : [
name
]
}
});
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useObservedElement.ts"],"sourcesContent":["'use client';\n\nimport { getObservedElement, Types as TabsterTypes } from 'tabster';\n\nimport { useTabster } from './useTabster';\nimport { useTabsterAttributes } from './useTabsterAttributes';\n\nexport function useObservedElement(name: string | string[]): TabsterTypes.TabsterDOMAttribute {\n useTabster(getObservedElement);\n\n return useTabsterAttributes({ observed: { names: Array.isArray(name) ? name : [name] } });\n}\n"],"names":["useObservedElement","name","useTabster","getObservedElement","useTabsterAttributes","observed","names","Array","isArray"],"mappings":"AAAA;;;;;+BAOgBA;;;eAAAA;;;yBAL0C;4BAE/B;sCACU;AAE9B,SAASA,mBAAmBC,IAAuB;IACxDC,IAAAA,sBAAU,EAACC,2BAAkB;IAE7B,OAAOC,IAAAA,0CAAoB,EAAC;QAAEC,UAAU;YAAEC,OAAOC,MAAMC,OAAO,CAACP,QAAQA,OAAO;gBAACA;aAAK;QAAC;IAAE;AACzF"}

View File

@@ -0,0 +1,35 @@
'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "useOnKeyboardNavigationChange", {
enumerable: true,
get: function() {
return useOnKeyboardNavigationChange;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const _reactutilities = require("@fluentui/react-utilities");
const _useKeyborgRef = require("./useKeyborgRef");
function useOnKeyboardNavigationChange(callback) {
const keyborgRef = (0, _useKeyborgRef.useKeyborgRef)();
const eventCallback = (0, _reactutilities.useEventCallback)(callback);
_react.useEffect(()=>{
const keyborg = keyborgRef.current;
if (keyborg) {
const cb = (next)=>{
eventCallback(next);
};
keyborg.subscribe(cb);
cb(keyborg.isNavigatingWithKeyboard());
return ()=>{
keyborg.unsubscribe(cb);
};
}
}, [
keyborgRef,
eventCallback
]);
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useOnKeyboardNavigationChange.ts"],"sourcesContent":["'use client';\n\nimport type { KeyborgCallback } from 'keyborg';\nimport * as React from 'react';\nimport { useEventCallback } from '@fluentui/react-utilities';\n\nimport { useKeyborgRef } from './useKeyborgRef';\n\n/**\n * Instantiates [keyborg](https://github.com/microsoft/keyborg) and subscribes to changes\n * in the keyboard navigation mode.\n *\n * @param callback - called every time the keyboard navigation state changes\n */\nexport function useOnKeyboardNavigationChange(callback: (isNavigatingWithKeyboard: boolean) => void): void {\n const keyborgRef = useKeyborgRef();\n const eventCallback = useEventCallback(callback);\n\n React.useEffect(() => {\n const keyborg = keyborgRef.current;\n\n if (keyborg) {\n const cb: KeyborgCallback = next => {\n eventCallback(next);\n };\n\n keyborg.subscribe(cb);\n cb(keyborg.isNavigatingWithKeyboard());\n\n return () => {\n keyborg.unsubscribe(cb);\n };\n }\n }, [keyborgRef, eventCallback]);\n}\n"],"names":["useOnKeyboardNavigationChange","callback","keyborgRef","useKeyborgRef","eventCallback","useEventCallback","React","useEffect","keyborg","current","cb","next","subscribe","isNavigatingWithKeyboard","unsubscribe"],"mappings":"AAAA;;;;;+BAcgBA;;;eAAAA;;;;iEAXO;gCACU;+BAEH;AAQvB,SAASA,8BAA8BC,QAAqD;IACjG,MAAMC,aAAaC,IAAAA,4BAAa;IAChC,MAAMC,gBAAgBC,IAAAA,gCAAgB,EAACJ;IAEvCK,OAAMC,SAAS,CAAC;QACd,MAAMC,UAAUN,WAAWO,OAAO;QAElC,IAAID,SAAS;YACX,MAAME,KAAsBC,CAAAA;gBAC1BP,cAAcO;YAChB;YAEAH,QAAQI,SAAS,CAACF;YAClBA,GAAGF,QAAQK,wBAAwB;YAEnC,OAAO;gBACLL,QAAQM,WAAW,CAACJ;YACtB;QACF;IACF,GAAG;QAACR;QAAYE;KAAc;AAChC"}

View File

@@ -0,0 +1,39 @@
'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
useRestoreFocusSource: function() {
return useRestoreFocusSource;
},
useRestoreFocusTarget: function() {
return useRestoreFocusTarget;
}
});
const _tabster = require("tabster");
const _useTabster = require("./useTabster");
function useRestoreFocusTarget() {
// Initializes the restorer API
(0, _useTabster.useTabster)(_tabster.getRestorer);
return (0, _tabster.getTabsterAttribute)({
restorer: {
type: _tabster.RestorerTypes.Target
}
});
}
function useRestoreFocusSource() {
// Initializes the restorer API
(0, _useTabster.useTabster)(_tabster.getRestorer);
return (0, _tabster.getTabsterAttribute)({
restorer: {
type: _tabster.RestorerTypes.Source
}
});
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useRestoreFocus.ts"],"sourcesContent":["'use client';\n\nimport { getRestorer, getTabsterAttribute, Types as TabsterTypes, RestorerTypes } from 'tabster';\nimport { useTabster } from './useTabster';\n\n/**\n * Focus will be restored to the most recent target element when it is lost from a source\n * @returns Attribute to apply to the target element where focus is restored\n */\nexport function useRestoreFocusTarget(): TabsterTypes.TabsterDOMAttribute {\n // Initializes the restorer API\n useTabster(getRestorer);\n\n return getTabsterAttribute({ restorer: { type: RestorerTypes.Target } });\n}\n\n/**\n * Focus will be restored to the most recent target element when it is lost from a source\n * @returns Attribute to apply to the element that might lose focus\n */\nexport function useRestoreFocusSource(): TabsterTypes.TabsterDOMAttribute {\n // Initializes the restorer API\n useTabster(getRestorer);\n\n return getTabsterAttribute({ restorer: { type: RestorerTypes.Source } });\n}\n"],"names":["useRestoreFocusSource","useRestoreFocusTarget","useTabster","getRestorer","getTabsterAttribute","restorer","type","RestorerTypes","Target","Source"],"mappings":"AAAA;;;;;;;;;;;;IAoBgBA,qBAAqB;eAArBA;;IAXAC,qBAAqB;eAArBA;;;yBAPuE;4BAC5D;AAMpB,SAASA;IACd,+BAA+B;IAC/BC,IAAAA,sBAAU,EAACC,oBAAW;IAEtB,OAAOC,IAAAA,4BAAmB,EAAC;QAAEC,UAAU;YAAEC,MAAMC,sBAAa,CAACC,MAAM;QAAC;IAAE;AACxE;AAMO,SAASR;IACd,+BAA+B;IAC/BE,IAAAA,sBAAU,EAACC,oBAAW;IAEtB,OAAOC,IAAAA,4BAAmB,EAAC;QAAEC,UAAU;YAAEC,MAAMC,sBAAa,CAACE,MAAM;QAAC;IAAE;AACxE"}

View File

@@ -0,0 +1,23 @@
'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "useSetKeyboardNavigation", {
enumerable: true,
get: function() {
return useSetKeyboardNavigation;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const _useKeyborgRef = require("./useKeyborgRef");
function useSetKeyboardNavigation() {
const keyborgRef = (0, _useKeyborgRef.useKeyborgRef)();
return _react.useCallback((isNavigatingWithKeyboard)=>{
var _keyborgRef_current;
(_keyborgRef_current = keyborgRef.current) === null || _keyborgRef_current === void 0 ? void 0 : _keyborgRef_current.setVal(isNavigatingWithKeyboard);
}, [
keyborgRef
]);
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useSetKeyboardNavigation.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { useKeyborgRef } from './useKeyborgRef';\n\n/**\n */\nexport function useSetKeyboardNavigation(): (isNavigatingWithKeyboard: boolean) => void {\n const keyborgRef = useKeyborgRef();\n\n return React.useCallback(\n (isNavigatingWithKeyboard: boolean) => {\n keyborgRef.current?.setVal(isNavigatingWithKeyboard);\n },\n [keyborgRef],\n );\n}\n"],"names":["useSetKeyboardNavigation","keyborgRef","useKeyborgRef","React","useCallback","isNavigatingWithKeyboard","current","setVal"],"mappings":"AAAA;;;;;+BAOgBA;;;eAAAA;;;;iEALO;+BACO;AAIvB,SAASA;IACd,MAAMC,aAAaC,IAAAA,4BAAa;IAEhC,OAAOC,OAAMC,WAAW,CACtB,CAACC;YACCJ;SAAAA,sBAAAA,WAAWK,OAAO,cAAlBL,0CAAAA,oBAAoBM,MAAM,CAACF;IAC7B,GACA;QAACJ;KAAW;AAEhB"}

View File

@@ -0,0 +1,74 @@
'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
createTabsterWithConfig: function() {
return createTabsterWithConfig;
},
useTabster: function() {
return useTabster;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const _tabster = require("tabster");
const _reactsharedcontexts = require("@fluentui/react-shared-contexts");
const _reactutilities = require("@fluentui/react-utilities");
const DEFAULT_FACTORY = (tabster)=>{
return tabster;
};
function createTabsterWithConfig(targetDocument) {
const defaultView = (targetDocument === null || targetDocument === void 0 ? void 0 : targetDocument.defaultView) || undefined;
const shadowDOMAPI = defaultView === null || defaultView === void 0 ? void 0 : defaultView.__tabsterShadowDOMAPI;
if (defaultView) {
return (0, _tabster.createTabster)(defaultView, {
autoRoot: {},
controlTab: false,
getParent: _reactutilities.getParent,
// The non-undefined return value of checkUncontrolledCompletely() dominates the value that the element might
// have in its `uncontrolled: { completely: true }` part of the tabster attribute. We must make sure to return
// undefined if we want the value from tabster attribute to be respected.
checkUncontrolledCompletely: (element)=>{
var _element_firstElementChild;
return ((_element_firstElementChild = element.firstElementChild) === null || _element_firstElementChild === void 0 ? void 0 : _element_firstElementChild.hasAttribute('data-is-focus-trap-zone-bumper')) === true || undefined;
},
DOMAPI: shadowDOMAPI
});
}
}
function useTabster(factory = DEFAULT_FACTORY) {
const { targetDocument } = (0, _reactsharedcontexts.useFluent_unstable)();
const factoryResultRef = _react.useRef(null);
(0, _reactutilities.useIsomorphicLayoutEffect)(()=>{
const tabster = createTabsterWithConfig(targetDocument);
if (tabster) {
factoryResultRef.current = factory(tabster);
return ()=>{
(0, _tabster.disposeTabster)(tabster);
factoryResultRef.current = null;
};
}
}, [
targetDocument,
factory
]);
if (process.env.NODE_ENV !== 'production') {
// eslint-disable-next-line
const previousFactory = (0, _reactutilities.usePrevious)(factory);
if (previousFactory !== null && previousFactory !== factory) {
throw new Error([
'@fluentui/react-tabster: ',
'The factory function passed to useTabster has changed. This should not ever happen.'
].join('\n'));
}
}
return factoryResultRef;
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useTabster.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { createTabster, disposeTabster, Types as TabsterTypes } from 'tabster';\nimport { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';\nimport { getParent, useIsomorphicLayoutEffect, usePrevious } from '@fluentui/react-utilities';\n\ninterface WindowWithTabsterShadowDOMAPI extends Window {\n __tabsterShadowDOMAPI?: TabsterTypes.DOMAPI;\n}\n\ntype UseTabsterFactory<FactoryResult> = (tabster: TabsterTypes.TabsterCore) => FactoryResult;\n\nconst DEFAULT_FACTORY: UseTabsterFactory<TabsterTypes.TabsterCore> = tabster => {\n return tabster;\n};\n\n/**\n * Creates a tabster instance with the provided configuration\n *\n * @internal\n * @param targetDocument\n */\nexport function createTabsterWithConfig(targetDocument: Document | undefined): TabsterTypes.TabsterCore | undefined {\n const defaultView = targetDocument?.defaultView || undefined;\n const shadowDOMAPI = (defaultView as WindowWithTabsterShadowDOMAPI | undefined)?.__tabsterShadowDOMAPI;\n\n if (defaultView) {\n return createTabster(defaultView, {\n autoRoot: {},\n controlTab: false,\n getParent,\n // The non-undefined return value of checkUncontrolledCompletely() dominates the value that the element might\n // have in its `uncontrolled: { completely: true }` part of the tabster attribute. We must make sure to return\n // undefined if we want the value from tabster attribute to be respected.\n checkUncontrolledCompletely: element =>\n element.firstElementChild?.hasAttribute('data-is-focus-trap-zone-bumper') === true || undefined,\n DOMAPI: shadowDOMAPI,\n });\n }\n}\n\n/**\n * Tries to get a tabster instance on the current window or creates a new one\n * Since Tabster is single instance only, feel free to call this hook to ensure Tabster exists if necessary\n *\n * @internal\n * @returns Tabster a ref to core instance or a factory result\n */\nexport function useTabster(): React.RefObject<TabsterTypes.TabsterCore | null>;\nexport function useTabster<FactoryResult>(\n factory: UseTabsterFactory<FactoryResult>,\n): React.RefObject<FactoryResult | null>;\n\nexport function useTabster<FactoryResult>(factory = DEFAULT_FACTORY): React.RefObject<FactoryResult | null> {\n const { targetDocument } = useFluent();\n const factoryResultRef = React.useRef<FactoryResult | null>(null);\n\n useIsomorphicLayoutEffect(() => {\n const tabster = createTabsterWithConfig(targetDocument);\n\n if (tabster) {\n factoryResultRef.current = factory(tabster) as FactoryResult;\n\n return () => {\n disposeTabster(tabster);\n factoryResultRef.current = null;\n };\n }\n }, [targetDocument, factory]);\n\n if (process.env.NODE_ENV !== 'production') {\n // eslint-disable-next-line\n const previousFactory = usePrevious(factory);\n\n if (previousFactory !== null && previousFactory !== factory) {\n throw new Error(\n [\n '@fluentui/react-tabster: ',\n 'The factory function passed to useTabster has changed. This should not ever happen.',\n ].join('\\n'),\n );\n }\n }\n\n return factoryResultRef;\n}\n"],"names":["createTabsterWithConfig","useTabster","DEFAULT_FACTORY","tabster","targetDocument","defaultView","undefined","shadowDOMAPI","__tabsterShadowDOMAPI","createTabster","autoRoot","controlTab","getParent","checkUncontrolledCompletely","element","firstElementChild","hasAttribute","DOMAPI","factory","useFluent","factoryResultRef","React","useRef","useIsomorphicLayoutEffect","current","disposeTabster","process","env","NODE_ENV","previousFactory","usePrevious","Error","join"],"mappings":"AAAA;;;;;;;;;;;;IAuBgBA,uBAAuB;eAAvBA;;IA+BAC,UAAU;eAAVA;;;;iEApDO;yBAC8C;qCACrB;gCACkB;AAQlE,MAAMC,kBAA+DC,CAAAA;IACnE,OAAOA;AACT;AAQO,SAASH,wBAAwBI,cAAoC;IAC1E,MAAMC,cAAcD,CAAAA,2BAAAA,qCAAAA,eAAgBC,WAAW,KAAIC;IACnD,MAAMC,eAAgBF,wBAAAA,kCAAD,AAACA,YAA2DG,qBAAqB;IAEtG,IAAIH,aAAa;QACf,OAAOI,IAAAA,sBAAa,EAACJ,aAAa;YAChCK,UAAU,CAAC;YACXC,YAAY;YACZC,WAAAA,yBAAS;YACT,6GAA6G;YAC7G,8GAA8G;YAC9G,yEAAyE;YACzEC,6BAA6BC,CAAAA;oBAC3BA;uBAAAA,EAAAA,6BAAAA,QAAQC,iBAAiB,cAAzBD,iDAAAA,2BAA2BE,YAAY,CAAC,uCAAsC,QAAQV;;YACxFW,QAAQV;QACV;IACF;AACF;AAcO,SAASN,WAA0BiB,UAAUhB,eAAe;IACjE,MAAM,EAAEE,cAAc,EAAE,GAAGe,IAAAA,uCAAS;IACpC,MAAMC,mBAAmBC,OAAMC,MAAM,CAAuB;IAE5DC,IAAAA,yCAAyB,EAAC;QACxB,MAAMpB,UAAUH,wBAAwBI;QAExC,IAAID,SAAS;YACXiB,iBAAiBI,OAAO,GAAGN,QAAQf;YAEnC,OAAO;gBACLsB,IAAAA,uBAAc,EAACtB;gBACfiB,iBAAiBI,OAAO,GAAG;YAC7B;QACF;IACF,GAAG;QAACpB;QAAgBc;KAAQ;IAE5B,IAAIQ,QAAQC,GAAG,CAACC,QAAQ,KAAK,cAAc;QACzC,2BAA2B;QAC3B,MAAMC,kBAAkBC,IAAAA,2BAAW,EAACZ;QAEpC,IAAIW,oBAAoB,QAAQA,oBAAoBX,SAAS;YAC3D,MAAM,IAAIa,MACR;gBACE;gBACA;aACD,CAACC,IAAI,CAAC;QAEX;IACF;IAEA,OAAOZ;AACT"}

View File

@@ -0,0 +1,26 @@
'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "useTabsterAttributes", {
enumerable: true,
get: function() {
return useTabsterAttributes;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _tabster = require("tabster");
const _useTabster = require("./useTabster");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const useTabsterAttributes = (props)=>{
// A tabster instance is not necessary to generate tabster attributes
// but calling the hook will ensure that a tabster instance exists internally and avoids consumers doing the same
(0, _useTabster.useTabster)();
const strAttr = (0, _tabster.getTabsterAttribute)(props, true);
return _react.useMemo(()=>({
[_tabster.TABSTER_ATTRIBUTE_NAME]: strAttr
}), [
strAttr
]);
};

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useTabsterAttributes.ts"],"sourcesContent":["'use client';\n\nimport { getTabsterAttribute, Types as TabsterTypes, TABSTER_ATTRIBUTE_NAME } from 'tabster';\nimport { useTabster } from './useTabster';\nimport * as React from 'react';\n\n/**\n * @internal\n * Hook that returns tabster attributes while ensuring tabster exists\n */\nexport const useTabsterAttributes = (props: TabsterTypes.TabsterAttributeProps): TabsterTypes.TabsterDOMAttribute => {\n // A tabster instance is not necessary to generate tabster attributes\n // but calling the hook will ensure that a tabster instance exists internally and avoids consumers doing the same\n useTabster();\n\n const strAttr = getTabsterAttribute(props, true);\n\n return React.useMemo(\n () => ({\n [TABSTER_ATTRIBUTE_NAME]: strAttr,\n }),\n [strAttr],\n );\n};\n"],"names":["useTabsterAttributes","props","useTabster","strAttr","getTabsterAttribute","React","useMemo","TABSTER_ATTRIBUTE_NAME"],"mappings":"AAAA;;;;;+BAUaA;;;eAAAA;;;;yBARsE;4BACxD;iEACJ;AAMhB,MAAMA,uBAAuB,CAACC;IACnC,qEAAqE;IACrE,iHAAiH;IACjHC,IAAAA,sBAAU;IAEV,MAAMC,UAAUC,IAAAA,4BAAmB,EAACH,OAAO;IAE3C,OAAOI,OAAMC,OAAO,CAClB,IAAO,CAAA;YACL,CAACC,+BAAsB,CAAC,EAAEJ;QAC5B,CAAA,GACA;QAACA;KAAQ;AAEb"}

View File

@@ -0,0 +1,19 @@
'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "useUncontrolledFocus", {
enumerable: true,
get: function() {
return useUncontrolledFocus;
}
});
const _tabster = require("tabster");
const _useTabster = require("./useTabster");
function useUncontrolledFocus() {
(0, _useTabster.useTabster)();
return (0, _tabster.getTabsterAttribute)({
uncontrolled: {}
});
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useUncontrolledFocus.ts"],"sourcesContent":["'use client';\n\nimport { getTabsterAttribute, Types as TabsterTypes } from 'tabster';\nimport { useTabster } from './useTabster';\n\n/**\n * Designates an area where tabster does not control focus\n * @returns Attribute to apply to the target element that should be uncontrolled by tabster\n */\nexport function useUncontrolledFocus(): TabsterTypes.TabsterDOMAttribute {\n useTabster();\n\n return getTabsterAttribute({ uncontrolled: {} });\n}\n"],"names":["useUncontrolledFocus","useTabster","getTabsterAttribute","uncontrolled"],"mappings":"AAAA;;;;;+BASgBA;;;eAAAA;;;yBAP2C;4BAChC;AAMpB,SAASA;IACdC,IAAAA,sBAAU;IAEV,OAAOC,IAAAA,4BAAmB,EAAC;QAAEC,cAAc,CAAC;IAAE;AAChD"}

View File

@@ -0,0 +1,129 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
GroupperMoveFocusActions: function() {
return _tabster.GroupperMoveFocusActions;
},
GroupperMoveFocusEvent: function() {
return _tabster.GroupperMoveFocusEvent;
},
GroupperMoveFocusEventName: function() {
return _tabster.GroupperMoveFocusEventName;
},
KEYBORG_FOCUSIN: function() {
return _keyborg.KEYBORG_FOCUSIN;
},
MoverKeys: function() {
return _tabster.MoverKeys;
},
MoverMemorizedElementEvent: function() {
return _tabster.MoverMemorizedElementEvent;
},
MoverMemorizedElementEventName: function() {
return _tabster.MoverMemorizedElementEventName;
},
MoverMoveFocusEvent: function() {
return _tabster.MoverMoveFocusEvent;
},
MoverMoveFocusEventName: function() {
return _tabster.MoverMoveFocusEventName;
},
TabsterMoveFocusEvent: function() {
return _tabster.TabsterMoveFocusEvent;
},
TabsterMoveFocusEventName: function() {
return _tabster.TabsterMoveFocusEventName;
},
TabsterTypes: function() {
return /** @deprecated (Do not use! Exposed by mistake and will be removed in the next major version.) */ _tabstertypes601donotuse;
},
applyFocusVisiblePolyfill: function() {
return _index1.applyFocusVisiblePolyfill;
},
createCustomFocusIndicatorStyle: function() {
return _index1.createCustomFocusIndicatorStyle;
},
createFocusOutlineStyle: function() {
return _index1.createFocusOutlineStyle;
},
/** @deprecated Use element.dispatchEvent(new GroupperMoveFocusEvent({ action: GroupperMoveFocusActions.Escape })) */ dispatchGroupperMoveFocusEvent: function() {
return _tabster.dispatchGroupperMoveFocusEvent;
},
/** @deprecated Use element.dispatchEvent(new MoverMoveFocusEvent({ key: MoverKeys.ArrowDown })) */ dispatchMoverMoveFocusEvent: function() {
return _tabster.dispatchMoverMoveFocusEvent;
},
useActivateModal: function() {
return _index.useActivateModal;
},
useArrowNavigationGroup: function() {
return _index.useArrowNavigationGroup;
},
useDangerousNeverHidden_unstable: function() {
return _index.useDangerousNeverHidden_unstable;
},
useFocusFinders: function() {
return _index.useFocusFinders;
},
useFocusObserved: function() {
return _index.useFocusObserved;
},
useFocusVisible: function() {
return _index.useFocusVisible;
},
useFocusWithin: function() {
return _index.useFocusWithin;
},
useFocusableGroup: function() {
return _index.useFocusableGroup;
},
useFocusedElementChange: function() {
return _index.useFocusedElementChange;
},
useIsNavigatingWithKeyboard: function() {
return _index.useIsNavigatingWithKeyboard;
},
useKeyboardNavAttribute: function() {
return _index.useKeyboardNavAttribute;
},
useMergedTabsterAttributes_unstable: function() {
return _index.useMergedTabsterAttributes_unstable;
},
useModalAttributes: function() {
return _index.useModalAttributes;
},
useObservedElement: function() {
return _index.useObservedElement;
},
useOnKeyboardNavigationChange: function() {
return _index.useOnKeyboardNavigationChange;
},
useRestoreFocusSource: function() {
return _index.useRestoreFocusSource;
},
useRestoreFocusTarget: function() {
return _index.useRestoreFocusTarget;
},
useSetKeyboardNavigation: function() {
return _index.useSetKeyboardNavigation;
},
useTabsterAttributes: function() {
return _index.useTabsterAttributes;
},
useUncontrolledFocus: function() {
return _index.useUncontrolledFocus;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _index = require("./hooks/index");
const _index1 = require("./focus/index");
const _tabster = require("tabster");
const _keyborg = require("keyborg");
const _tabstertypes601donotuse = /*#__PURE__*/ _interop_require_wildcard._(require("./tabster-types-6.0.1-do-not-use"));

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,173 @@
/*!
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/ /**
* WARNING! ATTENTION! WARNING! ATTENTION! WARNING! ATTENTION!
* WARNING! ATTENTION! WARNING! ATTENTION! WARNING! ATTENTION!
*
* Do not use anything from this file. It is a snapshot of the older Tabster typings exposed by a mistake.
* The exposed typings should have been removed, but we don't do it in minor versions to avoid breaking changes.
* Everything reexported from this file as react-tabster/TabsterTypes is marked as deprecated and shouldn't
* be used anywhre.
*
* WARNING! ATTENTION! WARNING! ATTENTION! WARNING! ATTENTION!
* WARNING! ATTENTION! WARNING! ATTENTION! WARNING! ATTENTION!
*/ "use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
DeloserEventName: function() {
return DeloserEventName;
},
FocusInEventName: function() {
return FocusInEventName;
},
FocusOutEventName: function() {
return FocusOutEventName;
},
FocusableSelector: function() {
return FocusableSelector;
},
GroupperMoveFocusActions: function() {
return GroupperMoveFocusActions;
},
GroupperMoveFocusEventName: function() {
return GroupperMoveFocusEventName;
},
GroupperTabbabilities: function() {
return GroupperTabbabilities;
},
ModalizerActiveEventName: function() {
return ModalizerActiveEventName;
},
ModalizerBeforeFocusOutEventName: function() {
return ModalizerBeforeFocusOutEventName;
},
ModalizerFocusInEventName: function() {
return ModalizerFocusInEventName;
},
ModalizerFocusOutEventName: function() {
return ModalizerFocusOutEventName;
},
ModalizerInactiveEventName: function() {
return ModalizerInactiveEventName;
},
MoveFocusEventName: function() {
return MoveFocusEventName;
},
MoverDirections: function() {
return MoverDirections;
},
MoverEventName: function() {
return MoverEventName;
},
MoverKeys: function() {
return MoverKeys;
},
MoverMoveFocusEventName: function() {
return MoverMoveFocusEventName;
},
ObservedElementAccesibilities: function() {
return ObservedElementAccesibilities;
},
RestoreFocusOrders: function() {
return RestoreFocusOrders;
},
RestorerTypes: function() {
return RestorerTypes;
},
SysDummyInputsPositions: function() {
return SysDummyInputsPositions;
},
TabsterAttributeName: function() {
return TabsterAttributeName;
},
TabsterDummyInputAttributeName: function() {
return TabsterDummyInputAttributeName;
},
Visibilities: function() {
return Visibilities;
}
});
const TabsterAttributeName = 'data-tabster';
const TabsterDummyInputAttributeName = 'data-tabster-dummy';
const DeloserEventName = 'tabster:deloser';
const ModalizerActiveEventName = 'tabster:modalizer:active';
const ModalizerInactiveEventName = 'tabster:modalizer:inactive';
const ModalizerFocusInEventName = 'tabster:modalizer:focusin';
const ModalizerFocusOutEventName = 'tabster:modalizer:focusout';
const ModalizerBeforeFocusOutEventName = 'tabster:modalizer:beforefocusout';
const MoverEventName = 'tabster:mover';
const FocusInEventName = 'tabster:focusin';
const FocusOutEventName = 'tabster:focusout';
const MoveFocusEventName = 'tabster:movefocus';
const MoverMoveFocusEventName = 'tabster:mover:movefocus';
const GroupperMoveFocusEventName = 'tabster:groupper:movefocus';
const FocusableSelector = [
'a[href]',
'button:not([disabled])',
'input:not([disabled])',
'select:not([disabled])',
'textarea:not([disabled])',
'*[tabindex]',
'*[contenteditable]'
].join(', ');
const GroupperMoveFocusActions = {
Enter: 1,
Escape: 2
};
const ObservedElementAccesibilities = {
Any: 0,
Accessible: 1,
Focusable: 2
};
const RestoreFocusOrders = {
History: 0,
DeloserDefault: 1,
RootDefault: 2,
DeloserFirst: 3,
RootFirst: 4
};
const Visibilities = {
Invisible: 0,
PartiallyVisible: 1,
Visible: 2
};
const RestorerTypes = {
Source: 0,
Target: 1
};
const MoverDirections = {
Both: 0,
Vertical: 1,
Horizontal: 2,
Grid: 3,
GridLinear: 4
};
const MoverKeys = {
ArrowUp: 1,
ArrowDown: 2,
ArrowLeft: 3,
ArrowRight: 4,
PageUp: 5,
PageDown: 6,
Home: 7,
End: 8
};
const GroupperTabbabilities = {
Unlimited: 0,
Limited: 1,
LimitedTrapFocus: 2
};
const SysDummyInputsPositions = {
Auto: 0,
Inside: 1,
Outside: 2
};

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,13 @@
export const KEYBOARD_NAV_ATTRIBUTE = 'data-keyboard-nav';
export const KEYBOARD_NAV_SELECTOR = `:global([${KEYBOARD_NAV_ATTRIBUTE}])`;
/**
* @internal
*/ export const FOCUS_VISIBLE_ATTR = 'data-fui-focus-visible';
/**
* @internal
*/ export const FOCUS_WITHIN_ATTR = 'data-fui-focus-within';
export const defaultOptions = {
style: {},
selector: 'focus',
customizeSelector: (selector)=>selector
};

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/focus/constants.ts"],"sourcesContent":["export const KEYBOARD_NAV_ATTRIBUTE = 'data-keyboard-nav' as const;\nexport const KEYBOARD_NAV_SELECTOR = `:global([${KEYBOARD_NAV_ATTRIBUTE}])` as const;\n\n/**\n * @internal\n */\nexport const FOCUS_VISIBLE_ATTR = 'data-fui-focus-visible';\n\n/**\n * @internal\n */\nexport const FOCUS_WITHIN_ATTR = 'data-fui-focus-within';\nexport const defaultOptions = {\n style: {},\n selector: 'focus',\n customizeSelector: (selector: string) => selector,\n} as const;\n"],"names":["KEYBOARD_NAV_ATTRIBUTE","KEYBOARD_NAV_SELECTOR","FOCUS_VISIBLE_ATTR","FOCUS_WITHIN_ATTR","defaultOptions","style","selector","customizeSelector"],"mappings":"AAAA,OAAO,MAAMA,yBAAyB,oBAA6B;AACnE,OAAO,MAAMC,wBAAwB,CAAC,SAAS,EAAED,uBAAuB,EAAE,CAAC,CAAU;AAErF;;CAEC,GACD,OAAO,MAAME,qBAAqB,yBAAyB;AAE3D;;CAEC,GACD,OAAO,MAAMC,oBAAoB,wBAAwB;AACzD,OAAO,MAAMC,iBAAiB;IAC5BC,OAAO,CAAC;IACRC,UAAU;IACVC,mBAAmB,CAACD,WAAqBA;AAC3C,EAAW"}

View File

@@ -0,0 +1,43 @@
import { defaultOptions, FOCUS_VISIBLE_ATTR, FOCUS_WITHIN_ATTR } from './constants';
/**
* Creates a style for @see makeStyles that includes the necessary selectors for focus.
* Should be used only when @see createFocusOutlineStyle does not fit requirements
*
* If you're using `createCustomFocusIndicatorStyle` instead of `createFocusOutlineStyle`
* keep in mind that the default outline style is not going to be removed
* (as it is in `createFocusOutlineStyle`),
* and is your responsibility to manually remove it from your styles.
*
* @example
* ```ts
* // Link styles
* const useStyles = makeStyles({
focusIndicator: createCustomFocusIndicatorStyle({
textDecorationColor: tokens.colorStrokeFocus2,
textDecorationLine: 'underline',
textDecorationStyle: 'double',
outlineStyle: 'none',
}),
// Common styles.
root: {
// ❗️ DO NOT FORGET TO REMOVE THE DEFAULT OUTLINE STYLE
':focus-visible': {
outlineStyle: 'none',
},
* ```
*
* @param style - styling applied on focus, defaults to @see getDefaultFocusOutlineStyles
* @param options - Configure the style of the focus outline
*/ export function createCustomFocusIndicatorStyle(style, { selector: selectorType = defaultOptions.selector, customizeSelector = defaultOptions.customizeSelector } = defaultOptions) {
return {
[customizeSelector(createBaseSelector(selectorType))]: style
};
}
function createBaseSelector(selectorType) {
switch(selectorType){
case 'focus':
return `&[${FOCUS_VISIBLE_ATTR}]`;
case 'focus-within':
return `&[${FOCUS_WITHIN_ATTR}]:focus-within`;
}
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/focus/createCustomFocusIndicatorStyle.ts"],"sourcesContent":["import { defaultOptions, FOCUS_VISIBLE_ATTR, FOCUS_WITHIN_ATTR } from './constants';\nimport { makeResetStyles } from '@griffel/react';\nimport type { GriffelStyle } from '@griffel/react';\n\n// TODO: Use the type directly from @griffel/react\n// https://github.com/microsoft/griffel/pull/278\ntype GriffelResetStyle = Parameters<typeof makeResetStyles>[0];\n\nexport interface CreateCustomFocusIndicatorStyleOptions {\n /**\n * Control if the indicator appears when the corresponding element is focused,\n * or any child is focused within the corresponding element.\n * @default 'focus'\n * @alias selectorType\n */\n selector?: 'focus' | 'focus-within';\n /**\n * Customizes the selector provided based on the selector type.\n */\n customizeSelector?: (selector: string) => string;\n /**\n * Enables the browser default outline style\n * @deprecated The custom focus indicator no longer affects outline styles. Outline is overridden\n * in the default focus indicator function, `createFocusOutlineStyle`.\n */\n enableOutline?: boolean;\n}\n\n/**\n * Creates a style for @see makeStyles that includes the necessary selectors for focus.\n * Should be used only when @see createFocusOutlineStyle does not fit requirements\n *\n * If you're using `createCustomFocusIndicatorStyle` instead of `createFocusOutlineStyle`\n * keep in mind that the default outline style is not going to be removed\n * (as it is in `createFocusOutlineStyle`),\n * and is your responsibility to manually remove it from your styles.\n *\n * @example\n * ```ts\n * // Link styles\n * const useStyles = makeStyles({\n focusIndicator: createCustomFocusIndicatorStyle({\n textDecorationColor: tokens.colorStrokeFocus2,\n textDecorationLine: 'underline',\n textDecorationStyle: 'double',\n outlineStyle: 'none',\n }),\n // Common styles.\n root: {\n // ❗️ DO NOT FORGET TO REMOVE THE DEFAULT OUTLINE STYLE\n ':focus-visible': {\n outlineStyle: 'none',\n },\n * ```\n *\n * @param style - styling applied on focus, defaults to @see getDefaultFocusOutlineStyles\n * @param options - Configure the style of the focus outline\n */\nexport function createCustomFocusIndicatorStyle<TStyle extends GriffelStyle | GriffelResetStyle>(\n style: TStyle,\n {\n selector: selectorType = defaultOptions.selector,\n customizeSelector = defaultOptions.customizeSelector,\n }: CreateCustomFocusIndicatorStyleOptions = defaultOptions,\n): TStyle extends GriffelStyle ? GriffelStyle : GriffelResetStyle {\n return { [customizeSelector(createBaseSelector(selectorType))]: style };\n}\n\nfunction createBaseSelector(selectorType: 'focus' | 'focus-within'): string {\n switch (selectorType) {\n case 'focus':\n return `&[${FOCUS_VISIBLE_ATTR}]`;\n case 'focus-within':\n return `&[${FOCUS_WITHIN_ATTR}]:focus-within`;\n }\n}\n"],"names":["defaultOptions","FOCUS_VISIBLE_ATTR","FOCUS_WITHIN_ATTR","createCustomFocusIndicatorStyle","style","selector","selectorType","customizeSelector","createBaseSelector"],"mappings":"AAAA,SAASA,cAAc,EAAEC,kBAAkB,EAAEC,iBAAiB,QAAQ,cAAc;AA4BpF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BC,GACD,OAAO,SAASC,gCACdC,KAAa,EACb,EACEC,UAAUC,eAAeN,eAAeK,QAAQ,EAChDE,oBAAoBP,eAAeO,iBAAiB,EACb,GAAGP,cAAc;IAE1D,OAAO;QAAE,CAACO,kBAAkBC,mBAAmBF,eAAe,EAAEF;IAAM;AACxE;AAEA,SAASI,mBAAmBF,YAAsC;IAChE,OAAQA;QACN,KAAK;YACH,OAAO,CAAC,EAAE,EAAEL,mBAAmB,CAAC,CAAC;QACnC,KAAK;YACH,OAAO,CAAC,EAAE,EAAEC,kBAAkB,cAAc,CAAC;IACjD;AACF"}

View File

@@ -0,0 +1,70 @@
import { tokens } from '@fluentui/react-theme';
import { shorthands } from '@griffel/react';
import { createCustomFocusIndicatorStyle } from './createCustomFocusIndicatorStyle';
import { defaultOptions } from './constants';
/**
* Get the position of the focus outline
*
* @param options - Configures the style of the focus outline
* @param position - The position of the focus outline
* @returns CSS value for the position of the focus outline
*/ function getOutlinePosition({ outlineWidth, outlineOffset }, position) {
const offsetValue = (outlineOffset === null || outlineOffset === void 0 ? void 0 : outlineOffset[position]) || outlineOffset;
if (!outlineOffset) {
return `calc(${outlineWidth} * -1)`;
}
return `calc(0px - ${outlineWidth} - ${offsetValue})`;
}
/**
* NOTE: the element with the focus outline needs to have `position: relative` so that the
* pseudo element can be properly positioned.
*
* @param options - Configures the style of the focus outline
* @returns focus outline styles object
*/ const getFocusOutlineStyles = (options)=>{
const { outlineRadius, outlineColor, outlineWidth } = options;
return {
...shorthands.borderColor('transparent'),
'@media (forced-colors: active)': {
'::after': {
...shorthands.borderColor('Highlight')
}
},
'::after': {
content: '""',
position: 'absolute',
pointerEvents: 'none',
zIndex: 1,
border: `${outlineWidth} solid ${outlineColor}`,
borderRadius: outlineRadius,
top: getOutlinePosition(options, 'top'),
right: getOutlinePosition(options, 'right'),
bottom: getOutlinePosition(options, 'bottom'),
left: getOutlinePosition(options, 'left')
}
};
};
/**
* NOTE: The element with the focus outline needs to have `position: relative` so that the
* pseudo element can be properly positioned.
*
* @param options - Configure the style of the focus outline
* @returns focus outline styles object for @see makeStyles
*/ export const createFocusOutlineStyle = ({ enableOutline = false, selector = defaultOptions.selector, customizeSelector, style = defaultOptions.style } = defaultOptions)=>({
':focus': {
outlineStyle: enableOutline ? undefined : 'none'
},
':focus-visible': {
outlineStyle: enableOutline ? undefined : 'none'
},
...createCustomFocusIndicatorStyle(getFocusOutlineStyles({
outlineColor: tokens.colorStrokeFocus2,
outlineRadius: tokens.borderRadiusMedium,
// FIXME: tokens.strokeWidthThick causes some weird bugs
outlineWidth: '2px',
...style
}), {
selector,
customizeSelector
})
});

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,73 @@
import { isHTMLElement } from '@fluentui/react-utilities';
import { KEYBORG_FOCUSIN, createKeyborg, disposeKeyborg } from 'keyborg';
import { FOCUS_VISIBLE_ATTR } from './constants';
/**
* @internal
* @param scope - Applies the ponyfill to all DOM children
* @param targetWindow - window
*/ export function applyFocusVisiblePolyfill(scope, targetWindow) {
if (alreadyInScope(scope)) {
// Focus visible polyfill already applied at this scope
return ()=>undefined;
}
const state = {
current: undefined
};
const keyborg = createKeyborg(targetWindow);
function registerElementIfNavigating(el) {
if (keyborg.isNavigatingWithKeyboard() && isHTMLElement(el)) {
state.current = el;
el.setAttribute(FOCUS_VISIBLE_ATTR, '');
}
}
function disposeCurrentElement() {
if (state.current) {
state.current.removeAttribute(FOCUS_VISIBLE_ATTR);
state.current = undefined;
}
}
// When navigation mode changes remove the focus-visible selector
keyborg.subscribe((isNavigatingWithKeyboard)=>{
if (!isNavigatingWithKeyboard) {
disposeCurrentElement();
} else {
registerElementIfNavigating(targetWindow.document.activeElement);
}
});
// Keyborg's focusin event is delegated so it's only registered once on the window
// and contains metadata about the focus event
const keyborgListener = (e)=>{
disposeCurrentElement();
const target = e.composedPath()[0];
registerElementIfNavigating(target);
};
// Make sure that when focus leaves the scope, the focus visible class is removed
const blurListener = (e)=>{
if (!e.relatedTarget || isHTMLElement(e.relatedTarget) && !scope.contains(e.relatedTarget)) {
disposeCurrentElement();
}
};
scope.addEventListener(KEYBORG_FOCUSIN, keyborgListener);
scope.addEventListener('focusout', blurListener);
scope.focusVisible = true;
if (scope.contains(targetWindow.document.activeElement)) {
registerElementIfNavigating(targetWindow.document.activeElement);
}
// Return disposer
return ()=>{
disposeCurrentElement();
scope.removeEventListener(KEYBORG_FOCUSIN, keyborgListener);
scope.removeEventListener('focusout', blurListener);
scope.focusVisible = undefined;
disposeKeyborg(keyborg);
};
}
function alreadyInScope(el) {
if (!el) {
return false;
}
if (el.focusVisible) {
return true;
}
return alreadyInScope(el === null || el === void 0 ? void 0 : el.parentElement);
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,49 @@
import { KEYBORG_FOCUSIN, createKeyborg, disposeKeyborg } from 'keyborg';
import { FOCUS_WITHIN_ATTR } from './constants';
/**
* A ponyfill that allows `:focus-within` to support visibility based on keyboard/mouse navigation
* like `:focus-visible` https://github.com/WICG/focus-visible/issues/151
* @returns ref to the element that uses `:focus-within` styles
*/ export function applyFocusWithinPolyfill(element, win) {
const keyborg = createKeyborg(win);
// When navigation mode changes to mouse, remove the focus-within selector
keyborg.subscribe((isNavigatingWithKeyboard)=>{
if (!isNavigatingWithKeyboard) {
removeFocusWithinClass(element);
}
});
// Keyborg's focusin event is delegated so it's only registered once on the window
// and contains metadata about the focus event
const keyborgListener = (e)=>{
if (keyborg.isNavigatingWithKeyboard() && isHTMLElement(e.target)) {
// Griffel can't create chained global styles so use the parent element for now
applyFocusWithinClass(element);
}
};
// Make sure that when focus leaves the scope, the focus within class is removed
const blurListener = (e)=>{
if (!e.relatedTarget || isHTMLElement(e.relatedTarget) && !element.contains(e.relatedTarget)) {
removeFocusWithinClass(element);
}
};
element.addEventListener(KEYBORG_FOCUSIN, keyborgListener);
element.addEventListener('focusout', blurListener);
// Return disposer
return ()=>{
element.removeEventListener(KEYBORG_FOCUSIN, keyborgListener);
element.removeEventListener('focusout', blurListener);
disposeKeyborg(keyborg);
};
}
function applyFocusWithinClass(el) {
el.setAttribute(FOCUS_WITHIN_ATTR, '');
}
function removeFocusWithinClass(el) {
el.removeAttribute(FOCUS_WITHIN_ATTR);
}
function isHTMLElement(target) {
if (!target) {
return false;
}
return Boolean(target && typeof target === 'object' && 'classList' in target && 'contains' in target);
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/focus/focusWithinPolyfill.ts"],"sourcesContent":["import { KEYBORG_FOCUSIN, KeyborgFocusInEvent, createKeyborg, disposeKeyborg } from 'keyborg';\nimport { FOCUS_WITHIN_ATTR } from './constants';\n\n/**\n * Because `addEventListener` type override falls back to 2nd definition (evt name is unknown string literal)\n * evt is being typed as a base class of MouseEvent -> `Event`.\n * This type is used to override `listener` calls to make TS happy\n */\ntype ListenerOverride = (evt: Event) => void;\n\n/**\n * A ponyfill that allows `:focus-within` to support visibility based on keyboard/mouse navigation\n * like `:focus-visible` https://github.com/WICG/focus-visible/issues/151\n * @returns ref to the element that uses `:focus-within` styles\n */\nexport function applyFocusWithinPolyfill(element: HTMLElement, win: Window): () => void {\n const keyborg = createKeyborg(win);\n\n // When navigation mode changes to mouse, remove the focus-within selector\n keyborg.subscribe(isNavigatingWithKeyboard => {\n if (!isNavigatingWithKeyboard) {\n removeFocusWithinClass(element);\n }\n });\n\n // Keyborg's focusin event is delegated so it's only registered once on the window\n // and contains metadata about the focus event\n const keyborgListener = (e: KeyborgFocusInEvent) => {\n if (keyborg.isNavigatingWithKeyboard() && isHTMLElement(e.target)) {\n // Griffel can't create chained global styles so use the parent element for now\n applyFocusWithinClass(element);\n }\n };\n\n // Make sure that when focus leaves the scope, the focus within class is removed\n const blurListener = (e: FocusEvent) => {\n if (!e.relatedTarget || (isHTMLElement(e.relatedTarget) && !element.contains(e.relatedTarget))) {\n removeFocusWithinClass(element);\n }\n };\n\n element.addEventListener(KEYBORG_FOCUSIN, keyborgListener as ListenerOverride);\n element.addEventListener('focusout', blurListener);\n\n // Return disposer\n return () => {\n element.removeEventListener(KEYBORG_FOCUSIN, keyborgListener as ListenerOverride);\n element.removeEventListener('focusout', blurListener);\n disposeKeyborg(keyborg);\n };\n}\n\nfunction applyFocusWithinClass(el: HTMLElement) {\n el.setAttribute(FOCUS_WITHIN_ATTR, '');\n}\n\nfunction removeFocusWithinClass(el: HTMLElement) {\n el.removeAttribute(FOCUS_WITHIN_ATTR);\n}\n\nfunction isHTMLElement(target: EventTarget | null): target is HTMLElement {\n if (!target) {\n return false;\n }\n return Boolean(target && typeof target === 'object' && 'classList' in target && 'contains' in target);\n}\n"],"names":["KEYBORG_FOCUSIN","createKeyborg","disposeKeyborg","FOCUS_WITHIN_ATTR","applyFocusWithinPolyfill","element","win","keyborg","subscribe","isNavigatingWithKeyboard","removeFocusWithinClass","keyborgListener","e","isHTMLElement","target","applyFocusWithinClass","blurListener","relatedTarget","contains","addEventListener","removeEventListener","el","setAttribute","removeAttribute","Boolean"],"mappings":"AAAA,SAASA,eAAe,EAAuBC,aAAa,EAAEC,cAAc,QAAQ,UAAU;AAC9F,SAASC,iBAAiB,QAAQ,cAAc;AAShD;;;;CAIC,GACD,OAAO,SAASC,yBAAyBC,OAAoB,EAAEC,GAAW;IACxE,MAAMC,UAAUN,cAAcK;IAE9B,0EAA0E;IAC1EC,QAAQC,SAAS,CAACC,CAAAA;QAChB,IAAI,CAACA,0BAA0B;YAC7BC,uBAAuBL;QACzB;IACF;IAEA,kFAAkF;IAClF,8CAA8C;IAC9C,MAAMM,kBAAkB,CAACC;QACvB,IAAIL,QAAQE,wBAAwB,MAAMI,cAAcD,EAAEE,MAAM,GAAG;YACjE,+EAA+E;YAC/EC,sBAAsBV;QACxB;IACF;IAEA,gFAAgF;IAChF,MAAMW,eAAe,CAACJ;QACpB,IAAI,CAACA,EAAEK,aAAa,IAAKJ,cAAcD,EAAEK,aAAa,KAAK,CAACZ,QAAQa,QAAQ,CAACN,EAAEK,aAAa,GAAI;YAC9FP,uBAAuBL;QACzB;IACF;IAEAA,QAAQc,gBAAgB,CAACnB,iBAAiBW;IAC1CN,QAAQc,gBAAgB,CAAC,YAAYH;IAErC,kBAAkB;IAClB,OAAO;QACLX,QAAQe,mBAAmB,CAACpB,iBAAiBW;QAC7CN,QAAQe,mBAAmB,CAAC,YAAYJ;QACxCd,eAAeK;IACjB;AACF;AAEA,SAASQ,sBAAsBM,EAAe;IAC5CA,GAAGC,YAAY,CAACnB,mBAAmB;AACrC;AAEA,SAASO,uBAAuBW,EAAe;IAC7CA,GAAGE,eAAe,CAACpB;AACrB;AAEA,SAASU,cAAcC,MAA0B;IAC/C,IAAI,CAACA,QAAQ;QACX,OAAO;IACT;IACA,OAAOU,QAAQV,UAAU,OAAOA,WAAW,YAAY,eAAeA,UAAU,cAAcA;AAChG"}

View File

@@ -0,0 +1,4 @@
export { createCustomFocusIndicatorStyle } from './createCustomFocusIndicatorStyle';
export { createFocusOutlineStyle } from './createFocusOutlineStyle';
export { applyFocusVisiblePolyfill } from './focusVisiblePolyfill';
export { applyFocusWithinPolyfill } from './focusWithinPolyfill';

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/focus/index.ts"],"sourcesContent":["export type { CreateCustomFocusIndicatorStyleOptions } from './createCustomFocusIndicatorStyle';\nexport { createCustomFocusIndicatorStyle } from './createCustomFocusIndicatorStyle';\nexport type {\n CreateFocusOutlineStyleOptions,\n FocusOutlineOffset,\n FocusOutlineStyleOptions,\n} from './createFocusOutlineStyle';\nexport { createFocusOutlineStyle } from './createFocusOutlineStyle';\nexport { applyFocusVisiblePolyfill } from './focusVisiblePolyfill';\nexport { applyFocusWithinPolyfill } from './focusWithinPolyfill';\n"],"names":["createCustomFocusIndicatorStyle","createFocusOutlineStyle","applyFocusVisiblePolyfill","applyFocusWithinPolyfill"],"mappings":"AACA,SAASA,+BAA+B,QAAQ,oCAAoC;AAMpF,SAASC,uBAAuB,QAAQ,4BAA4B;AACpE,SAASC,yBAAyB,QAAQ,yBAAyB;AACnE,SAASC,wBAAwB,QAAQ,wBAAwB"}

View File

@@ -0,0 +1,18 @@
export { useArrowNavigationGroup } from './useArrowNavigationGroup';
export { useFocusableGroup } from './useFocusableGroup';
export { useFocusFinders } from './useFocusFinders';
export { useFocusVisible } from './useFocusVisible';
export { useFocusWithin } from './useFocusWithin';
export { useKeyboardNavAttribute } from './useKeyboardNavAttribute';
export { useOnKeyboardNavigationChange } from './useOnKeyboardNavigationChange';
export { useDangerousNeverHidden_unstable, useModalAttributes } from './useModalAttributes';
export { useTabsterAttributes } from './useTabsterAttributes';
export { useObservedElement } from './useObservedElement';
export { useMergedTabsterAttributes_unstable } from './useMergeTabsterAttributes';
export { useFocusObserved } from './useFocusObserved';
export { useRestoreFocusSource, useRestoreFocusTarget } from './useRestoreFocus';
export { useUncontrolledFocus } from './useUncontrolledFocus';
export { useIsNavigatingWithKeyboard } from './useIsNavigatingWithKeyboard';
export { useSetKeyboardNavigation } from './useSetKeyboardNavigation';
export { useFocusedElementChange } from './useFocusedElementChange';
export { useActivateModal } from './useActivateModal';

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/index.ts"],"sourcesContent":["export type { UseArrowNavigationGroupOptions } from './useArrowNavigationGroup';\nexport { useArrowNavigationGroup } from './useArrowNavigationGroup';\nexport type { UseFocusableGroupOptions } from './useFocusableGroup';\nexport { useFocusableGroup } from './useFocusableGroup';\nexport { useFocusFinders } from './useFocusFinders';\nexport { useFocusVisible } from './useFocusVisible';\nexport { useFocusWithin } from './useFocusWithin';\nexport { useKeyboardNavAttribute } from './useKeyboardNavAttribute';\nexport { useOnKeyboardNavigationChange } from './useOnKeyboardNavigationChange';\nexport type { UseModalAttributesOptions } from './useModalAttributes';\nexport { useDangerousNeverHidden_unstable, useModalAttributes } from './useModalAttributes';\nexport { useTabsterAttributes } from './useTabsterAttributes';\nexport { useObservedElement } from './useObservedElement';\nexport { useMergedTabsterAttributes_unstable } from './useMergeTabsterAttributes';\nexport { useFocusObserved } from './useFocusObserved';\nexport { useRestoreFocusSource, useRestoreFocusTarget } from './useRestoreFocus';\nexport { useUncontrolledFocus } from './useUncontrolledFocus';\nexport { useIsNavigatingWithKeyboard } from './useIsNavigatingWithKeyboard';\nexport { useSetKeyboardNavigation } from './useSetKeyboardNavigation';\nexport { useFocusedElementChange } from './useFocusedElementChange';\nexport { useActivateModal } from './useActivateModal';\n"],"names":["useArrowNavigationGroup","useFocusableGroup","useFocusFinders","useFocusVisible","useFocusWithin","useKeyboardNavAttribute","useOnKeyboardNavigationChange","useDangerousNeverHidden_unstable","useModalAttributes","useTabsterAttributes","useObservedElement","useMergedTabsterAttributes_unstable","useFocusObserved","useRestoreFocusSource","useRestoreFocusTarget","useUncontrolledFocus","useIsNavigatingWithKeyboard","useSetKeyboardNavigation","useFocusedElementChange","useActivateModal"],"mappings":"AACA,SAASA,uBAAuB,QAAQ,4BAA4B;AAEpE,SAASC,iBAAiB,QAAQ,sBAAsB;AACxD,SAASC,eAAe,QAAQ,oBAAoB;AACpD,SAASC,eAAe,QAAQ,oBAAoB;AACpD,SAASC,cAAc,QAAQ,mBAAmB;AAClD,SAASC,uBAAuB,QAAQ,4BAA4B;AACpE,SAASC,6BAA6B,QAAQ,kCAAkC;AAEhF,SAASC,gCAAgC,EAAEC,kBAAkB,QAAQ,uBAAuB;AAC5F,SAASC,oBAAoB,QAAQ,yBAAyB;AAC9D,SAASC,kBAAkB,QAAQ,uBAAuB;AAC1D,SAASC,mCAAmC,QAAQ,8BAA8B;AAClF,SAASC,gBAAgB,QAAQ,qBAAqB;AACtD,SAASC,qBAAqB,EAAEC,qBAAqB,QAAQ,oBAAoB;AACjF,SAASC,oBAAoB,QAAQ,yBAAyB;AAC9D,SAASC,2BAA2B,QAAQ,gCAAgC;AAC5E,SAASC,wBAAwB,QAAQ,6BAA6B;AACtE,SAASC,uBAAuB,QAAQ,4BAA4B;AACpE,SAASC,gBAAgB,QAAQ,qBAAqB"}

View File

@@ -0,0 +1,25 @@
'use client';
import * as React from 'react';
import { getModalizer } from 'tabster';
import { useTimeout } from '@fluentui/react-utilities';
import { useTabster } from './useTabster';
/**
* Returns a function that activates a modal by element from the modal or modal container.
*/ export function useActivateModal() {
const modalizerRefAPI = useTabster(getModalizer);
const [setActivateModalTimeout] = useTimeout();
const activateModal = React.useCallback((elementFromModal)=>{
// We call the actual activation function on the next tick, because with the typical use case,
// the hook will be called on the same tick when other Tabster attributes are being applied,
// and on the current tick the element has just received the attributes, but Tabster has not
// instantiated the Modalizer yet.
setActivateModalTimeout(()=>{
var _modalizerRefAPI_current;
(_modalizerRefAPI_current = modalizerRefAPI.current) === null || _modalizerRefAPI_current === void 0 ? void 0 : _modalizerRefAPI_current.activate(elementFromModal);
}, 0);
}, [
modalizerRefAPI,
setActivateModalTimeout
]);
return activateModal;
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useActivateModal.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { getModalizer } from 'tabster';\nimport { useTimeout } from '@fluentui/react-utilities';\nimport { useTabster } from './useTabster';\n\n/**\n * Returns a function that activates a modal by element from the modal or modal container.\n */\nexport function useActivateModal(): (elementFromModal: HTMLElement | undefined) => void {\n const modalizerRefAPI = useTabster(getModalizer);\n\n const [setActivateModalTimeout] = useTimeout();\n const activateModal = React.useCallback(\n (elementFromModal: HTMLElement | undefined) => {\n // We call the actual activation function on the next tick, because with the typical use case,\n // the hook will be called on the same tick when other Tabster attributes are being applied,\n // and on the current tick the element has just received the attributes, but Tabster has not\n // instantiated the Modalizer yet.\n setActivateModalTimeout(() => {\n modalizerRefAPI.current?.activate(elementFromModal);\n }, 0);\n },\n [modalizerRefAPI, setActivateModalTimeout],\n );\n\n return activateModal;\n}\n"],"names":["React","getModalizer","useTimeout","useTabster","useActivateModal","modalizerRefAPI","setActivateModalTimeout","activateModal","useCallback","elementFromModal","current","activate"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,YAAY,QAAQ,UAAU;AACvC,SAASC,UAAU,QAAQ,4BAA4B;AACvD,SAASC,UAAU,QAAQ,eAAe;AAE1C;;CAEC,GACD,OAAO,SAASC;IACd,MAAMC,kBAAkBF,WAAWF;IAEnC,MAAM,CAACK,wBAAwB,GAAGJ;IAClC,MAAMK,gBAAgBP,MAAMQ,WAAW,CACrC,CAACC;QACC,8FAA8F;QAC9F,4FAA4F;QAC5F,4FAA4F;QAC5F,kCAAkC;QAClCH,wBAAwB;gBACtBD;aAAAA,2BAAAA,gBAAgBK,OAAO,cAAvBL,+CAAAA,yBAAyBM,QAAQ,CAACF;QACpC,GAAG;IACL,GACA;QAACJ;QAAiBC;KAAwB;IAG5C,OAAOC;AACT"}

View File

@@ -0,0 +1,41 @@
'use client';
import { getMover, MoverDirections } from 'tabster';
import { useTabsterAttributes } from './useTabsterAttributes';
import { useTabster } from './useTabster';
/**
* A hook that returns the necessary tabster attributes to support arrow key navigation
* @param options - Options to configure keyboard navigation
*/ export const useArrowNavigationGroup = (options = {})=>{
const { circular, axis, memorizeCurrent = true, tabbable, ignoreDefaultKeydown, // eslint-disable-next-line @typescript-eslint/naming-convention
unstable_hasDefault } = options;
useTabster(getMover);
return useTabsterAttributes({
mover: {
cyclic: !!circular,
direction: axisToMoverDirection(axis !== null && axis !== void 0 ? axis : 'vertical'),
memorizeCurrent,
tabbable,
hasDefault: unstable_hasDefault
},
...ignoreDefaultKeydown && {
focusable: {
ignoreKeydown: ignoreDefaultKeydown
}
}
});
};
function axisToMoverDirection(axis) {
switch(axis){
case 'horizontal':
return MoverDirections.Horizontal;
case 'grid':
return MoverDirections.Grid;
case 'grid-linear':
return MoverDirections.GridLinear;
case 'both':
return MoverDirections.Both;
case 'vertical':
default:
return MoverDirections.Vertical;
}
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useArrowNavigationGroup.ts"],"sourcesContent":["'use client';\n\nimport { Types, getMover, MoverDirections } from 'tabster';\nimport { useTabsterAttributes } from './useTabsterAttributes';\nimport { useTabster } from './useTabster';\n\nexport interface UseArrowNavigationGroupOptions {\n /**\n * Focus will navigate vertically, horizontally or in both directions (grid), defaults to horizontally\n * @defaultValue vertical\n */\n axis?: 'vertical' | 'horizontal' | 'grid' | 'grid-linear' | 'both';\n /**\n * Focus will cycle to the first/last elements of the group without stopping\n */\n circular?: boolean;\n /**\n * Last focused element in the group will be remembered and focused (if still\n * available) when tabbing from outside of the group\n * @default true\n */\n memorizeCurrent?: boolean;\n /**\n * Allow tabbing within the arrow navigation group items.\n */\n tabbable?: boolean;\n /**\n * Tabster should ignore default handling of keydown events\n */\n ignoreDefaultKeydown?: Types.FocusableProps['ignoreKeydown'];\n /**\n * The default focusable item in the group will be an element with Focusable.isDefault property.\n * Note that there is no way in \\@fluentui/react-tabster to set default focusable element,\n * and this option is currently for internal testing purposes only.\n */\n // eslint-disable-next-line @typescript-eslint/naming-convention\n unstable_hasDefault?: boolean;\n}\n\n/**\n * A hook that returns the necessary tabster attributes to support arrow key navigation\n * @param options - Options to configure keyboard navigation\n */\nexport const useArrowNavigationGroup = (options: UseArrowNavigationGroupOptions = {}): Types.TabsterDOMAttribute => {\n const {\n circular,\n axis,\n memorizeCurrent = true,\n tabbable,\n ignoreDefaultKeydown,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n unstable_hasDefault,\n } = options;\n\n useTabster(getMover);\n\n return useTabsterAttributes({\n mover: {\n cyclic: !!circular,\n direction: axisToMoverDirection(axis ?? 'vertical'),\n memorizeCurrent,\n tabbable,\n hasDefault: unstable_hasDefault,\n },\n ...(ignoreDefaultKeydown && {\n focusable: {\n ignoreKeydown: ignoreDefaultKeydown,\n },\n }),\n });\n};\n\nfunction axisToMoverDirection(axis: UseArrowNavigationGroupOptions['axis']): Types.MoverDirection {\n switch (axis) {\n case 'horizontal':\n return MoverDirections.Horizontal;\n case 'grid':\n return MoverDirections.Grid;\n case 'grid-linear':\n return MoverDirections.GridLinear;\n case 'both':\n return MoverDirections.Both;\n\n case 'vertical':\n default:\n return MoverDirections.Vertical;\n }\n}\n"],"names":["getMover","MoverDirections","useTabsterAttributes","useTabster","useArrowNavigationGroup","options","circular","axis","memorizeCurrent","tabbable","ignoreDefaultKeydown","unstable_hasDefault","mover","cyclic","direction","axisToMoverDirection","hasDefault","focusable","ignoreKeydown","Horizontal","Grid","GridLinear","Both","Vertical"],"mappings":"AAAA;AAEA,SAAgBA,QAAQ,EAAEC,eAAe,QAAQ,UAAU;AAC3D,SAASC,oBAAoB,QAAQ,yBAAyB;AAC9D,SAASC,UAAU,QAAQ,eAAe;AAmC1C;;;CAGC,GACD,OAAO,MAAMC,0BAA0B,CAACC,UAA0C,CAAC,CAAC;IAClF,MAAM,EACJC,QAAQ,EACRC,IAAI,EACJC,kBAAkB,IAAI,EACtBC,QAAQ,EACRC,oBAAoB,EACpB,gEAAgE;IAChEC,mBAAmB,EACpB,GAAGN;IAEJF,WAAWH;IAEX,OAAOE,qBAAqB;QAC1BU,OAAO;YACLC,QAAQ,CAAC,CAACP;YACVQ,WAAWC,qBAAqBR,iBAAAA,kBAAAA,OAAQ;YACxCC;YACAC;YACAO,YAAYL;QACd;QACA,GAAID,wBAAwB;YAC1BO,WAAW;gBACTC,eAAeR;YACjB;QACF,CAAC;IACH;AACF,EAAE;AAEF,SAASK,qBAAqBR,IAA4C;IACxE,OAAQA;QACN,KAAK;YACH,OAAON,gBAAgBkB,UAAU;QACnC,KAAK;YACH,OAAOlB,gBAAgBmB,IAAI;QAC7B,KAAK;YACH,OAAOnB,gBAAgBoB,UAAU;QACnC,KAAK;YACH,OAAOpB,gBAAgBqB,IAAI;QAE7B,KAAK;QACL;YACE,OAAOrB,gBAAgBsB,QAAQ;IACnC;AACF"}

View File

@@ -0,0 +1,69 @@
'use client';
import * as React from 'react';
import { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';
import { useTabster } from './useTabster';
/**
* Returns a set of helper functions that will traverse focusable elements in the context of a root DOM element
*/ export const useFocusFinders = ()=>{
const tabsterRef = useTabster();
const { targetDocument } = useFluent();
// Narrow props for now and let need dictate additional props in the future
const findAllFocusable = React.useCallback((container, acceptCondition)=>{
var _tabsterRef_current;
return container && ((_tabsterRef_current = tabsterRef.current) === null || _tabsterRef_current === void 0 ? void 0 : _tabsterRef_current.focusable.findAll({
container,
acceptCondition
})) || [];
}, [
tabsterRef
]);
const findFirstFocusable = React.useCallback((container)=>{
var _tabsterRef_current;
return container && ((_tabsterRef_current = tabsterRef.current) === null || _tabsterRef_current === void 0 ? void 0 : _tabsterRef_current.focusable.findFirst({
container
}));
}, [
tabsterRef
]);
const findLastFocusable = React.useCallback((container)=>{
var _tabsterRef_current;
return container && ((_tabsterRef_current = tabsterRef.current) === null || _tabsterRef_current === void 0 ? void 0 : _tabsterRef_current.focusable.findLast({
container
}));
}, [
tabsterRef
]);
const findNextFocusable = React.useCallback((currentElement, options = {})=>{
if (!tabsterRef.current || !targetDocument || !currentElement) {
return null;
}
const { container = targetDocument.body } = options;
return tabsterRef.current.focusable.findNext({
currentElement,
container
});
}, [
tabsterRef,
targetDocument
]);
const findPrevFocusable = React.useCallback((currentElement, options = {})=>{
if (!tabsterRef.current || !targetDocument || !currentElement) {
return null;
}
const { container = targetDocument.body } = options;
return tabsterRef.current.focusable.findPrev({
currentElement,
container
});
}, [
tabsterRef,
targetDocument
]);
return {
findAllFocusable,
findFirstFocusable,
findLastFocusable,
findNextFocusable,
findPrevFocusable
};
};

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useFocusFinders.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { Types as TabsterTypes } from 'tabster';\nimport { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';\nimport { useTabster } from './useTabster';\n\n/**\n * Returns a set of helper functions that will traverse focusable elements in the context of a root DOM element\n */\nexport const useFocusFinders = (): {\n findAllFocusable: (container: HTMLElement | null, acceptCondition?: (el: HTMLElement) => boolean) => HTMLElement[];\n findFirstFocusable: (container: HTMLElement | null) => HTMLElement | null | undefined;\n findLastFocusable: (container: HTMLElement | null) => HTMLElement | null | undefined;\n findNextFocusable: (\n currentElement: HTMLElement | null,\n options?: { container?: HTMLElement },\n ) => HTMLElement | null | undefined;\n findPrevFocusable: (\n currentElement: HTMLElement | null,\n options?: { container?: HTMLElement },\n ) => HTMLElement | null | undefined;\n} => {\n const tabsterRef = useTabster();\n const { targetDocument } = useFluent();\n\n // Narrow props for now and let need dictate additional props in the future\n const findAllFocusable = React.useCallback(\n (container: HTMLElement | null, acceptCondition?: (el: HTMLElement) => boolean) =>\n (container && tabsterRef.current?.focusable.findAll({ container, acceptCondition })) || [],\n [tabsterRef],\n );\n\n const findFirstFocusable = React.useCallback(\n (container: HTMLElement | null) => container && tabsterRef.current?.focusable.findFirst({ container }),\n [tabsterRef],\n );\n\n const findLastFocusable = React.useCallback(\n (container: HTMLElement | null) => container && tabsterRef.current?.focusable.findLast({ container }),\n [tabsterRef],\n );\n\n const findNextFocusable = React.useCallback(\n (currentElement: HTMLElement | null, options: Pick<Partial<TabsterTypes.FindNextProps>, 'container'> = {}) => {\n if (!tabsterRef.current || !targetDocument || !currentElement) {\n return null;\n }\n\n const { container = targetDocument.body } = options;\n\n return tabsterRef.current.focusable.findNext({ currentElement, container });\n },\n [tabsterRef, targetDocument],\n );\n\n const findPrevFocusable = React.useCallback(\n (currentElement: HTMLElement | null, options: Pick<Partial<TabsterTypes.FindNextProps>, 'container'> = {}) => {\n if (!tabsterRef.current || !targetDocument || !currentElement) {\n return null;\n }\n\n const { container = targetDocument.body } = options;\n\n return tabsterRef.current.focusable.findPrev({ currentElement, container });\n },\n [tabsterRef, targetDocument],\n );\n\n return {\n findAllFocusable,\n findFirstFocusable,\n findLastFocusable,\n findNextFocusable,\n findPrevFocusable,\n };\n};\n"],"names":["React","useFluent_unstable","useFluent","useTabster","useFocusFinders","tabsterRef","targetDocument","findAllFocusable","useCallback","container","acceptCondition","current","focusable","findAll","findFirstFocusable","findFirst","findLastFocusable","findLast","findNextFocusable","currentElement","options","body","findNext","findPrevFocusable","findPrev"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAE/B,SAASC,sBAAsBC,SAAS,QAAQ,kCAAkC;AAClF,SAASC,UAAU,QAAQ,eAAe;AAE1C;;CAEC,GACD,OAAO,MAAMC,kBAAkB;IAa7B,MAAMC,aAAaF;IACnB,MAAM,EAAEG,cAAc,EAAE,GAAGJ;IAE3B,2EAA2E;IAC3E,MAAMK,mBAAmBP,MAAMQ,WAAW,CACxC,CAACC,WAA+BC;YAChBL;eAAd,AAACI,eAAaJ,sBAAAA,WAAWM,OAAO,cAAlBN,0CAAAA,oBAAoBO,SAAS,CAACC,OAAO,CAAC;YAAEJ;YAAWC;QAAgB,OAAO,EAAE;OAC5F;QAACL;KAAW;IAGd,MAAMS,qBAAqBd,MAAMQ,WAAW,CAC1C,CAACC;YAA+CJ;eAAbI,eAAaJ,sBAAAA,WAAWM,OAAO,cAAlBN,0CAAAA,oBAAoBO,SAAS,CAACG,SAAS,CAAC;YAAEN;QAAU;OACpG;QAACJ;KAAW;IAGd,MAAMW,oBAAoBhB,MAAMQ,WAAW,CACzC,CAACC;YAA+CJ;eAAbI,eAAaJ,sBAAAA,WAAWM,OAAO,cAAlBN,0CAAAA,oBAAoBO,SAAS,CAACK,QAAQ,CAAC;YAAER;QAAU;OACnG;QAACJ;KAAW;IAGd,MAAMa,oBAAoBlB,MAAMQ,WAAW,CACzC,CAACW,gBAAoCC,UAAkE,CAAC,CAAC;QACvG,IAAI,CAACf,WAAWM,OAAO,IAAI,CAACL,kBAAkB,CAACa,gBAAgB;YAC7D,OAAO;QACT;QAEA,MAAM,EAAEV,YAAYH,eAAee,IAAI,EAAE,GAAGD;QAE5C,OAAOf,WAAWM,OAAO,CAACC,SAAS,CAACU,QAAQ,CAAC;YAAEH;YAAgBV;QAAU;IAC3E,GACA;QAACJ;QAAYC;KAAe;IAG9B,MAAMiB,oBAAoBvB,MAAMQ,WAAW,CACzC,CAACW,gBAAoCC,UAAkE,CAAC,CAAC;QACvG,IAAI,CAACf,WAAWM,OAAO,IAAI,CAACL,kBAAkB,CAACa,gBAAgB;YAC7D,OAAO;QACT;QAEA,MAAM,EAAEV,YAAYH,eAAee,IAAI,EAAE,GAAGD;QAE5C,OAAOf,WAAWM,OAAO,CAACC,SAAS,CAACY,QAAQ,CAAC;YAAEL;YAAgBV;QAAU;IAC3E,GACA;QAACJ;QAAYC;KAAe;IAG9B,OAAO;QACLC;QACAO;QACAE;QACAE;QACAK;IACF;AACF,EAAE"}

View File

@@ -0,0 +1,27 @@
'use client';
import * as React from 'react';
import { getObservedElement } from 'tabster';
import { useTabster } from './useTabster';
/**
* @param name - The observed element to focus
* @param options - Options for the focus observed
*
* @returns Function that will focus an element
*/ export function useFocusObserved(name, options = {}) {
const { timeout = 1000 } = options;
const observedAPIRef = useTabster(getObservedElement);
return React.useCallback(()=>{
const observerAPI = observedAPIRef.current;
if (observerAPI) {
return observerAPI.requestFocus(name, timeout);
}
return {
result: Promise.resolve(false),
cancel: ()=>null
};
}, [
observedAPIRef,
name,
timeout
]);
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useFocusObserved.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { getObservedElement, Types as TabsterTypes } from 'tabster';\nimport { useTabster } from './useTabster';\n\ninterface UseFocusObservedOptions {\n /**\n * After timeout the focus attempt fails\n */\n timeout?: number;\n}\n\n/**\n * @param name - The observed element to focus\n * @param options - Options for the focus observed\n *\n * @returns Function that will focus an element\n */\nexport function useFocusObserved(\n name: string,\n options: UseFocusObservedOptions = {},\n): () => TabsterTypes.ObservedElementAsyncRequest<boolean> {\n const { timeout = 1000 } = options;\n const observedAPIRef = useTabster(getObservedElement);\n\n return React.useCallback(() => {\n const observerAPI = observedAPIRef.current;\n\n if (observerAPI) {\n return observerAPI.requestFocus(name, timeout);\n }\n\n return {\n result: Promise.resolve(false),\n cancel: () => null,\n };\n }, [observedAPIRef, name, timeout]);\n}\n"],"names":["React","getObservedElement","useTabster","useFocusObserved","name","options","timeout","observedAPIRef","useCallback","observerAPI","current","requestFocus","result","Promise","resolve","cancel"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,kBAAkB,QAA+B,UAAU;AACpE,SAASC,UAAU,QAAQ,eAAe;AAS1C;;;;;CAKC,GACD,OAAO,SAASC,iBACdC,IAAY,EACZC,UAAmC,CAAC,CAAC;IAErC,MAAM,EAAEC,UAAU,IAAI,EAAE,GAAGD;IAC3B,MAAME,iBAAiBL,WAAWD;IAElC,OAAOD,MAAMQ,WAAW,CAAC;QACvB,MAAMC,cAAcF,eAAeG,OAAO;QAE1C,IAAID,aAAa;YACf,OAAOA,YAAYE,YAAY,CAACP,MAAME;QACxC;QAEA,OAAO;YACLM,QAAQC,QAAQC,OAAO,CAAC;YACxBC,QAAQ,IAAM;QAChB;IACF,GAAG;QAACR;QAAgBH;QAAME;KAAQ;AACpC"}

View File

@@ -0,0 +1,19 @@
'use client';
import * as React from 'react';
import { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';
import { applyFocusVisiblePolyfill } from '../focus/focusVisiblePolyfill';
export function useFocusVisible(options = {}) {
const contextValue = useFluent();
const scopeRef = React.useRef(null);
var _options_targetDocument;
const targetDocument = (_options_targetDocument = options.targetDocument) !== null && _options_targetDocument !== void 0 ? _options_targetDocument : contextValue.targetDocument;
React.useEffect(()=>{
if ((targetDocument === null || targetDocument === void 0 ? void 0 : targetDocument.defaultView) && scopeRef.current) {
return applyFocusVisiblePolyfill(scopeRef.current, targetDocument.defaultView);
}
}, [
scopeRef,
targetDocument
]);
return scopeRef;
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useFocusVisible.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';\n\nimport { applyFocusVisiblePolyfill } from '../focus/focusVisiblePolyfill';\n\ntype UseFocusVisibleOptions = {\n targetDocument?: Document;\n};\n\nexport function useFocusVisible<TElement extends HTMLElement = HTMLElement>(\n options: UseFocusVisibleOptions = {},\n): React.RefObject<TElement | null> {\n const contextValue = useFluent();\n const scopeRef = React.useRef<TElement>(null);\n\n const targetDocument = options.targetDocument ?? contextValue.targetDocument;\n\n React.useEffect(() => {\n if (targetDocument?.defaultView && scopeRef.current) {\n return applyFocusVisiblePolyfill(scopeRef.current, targetDocument.defaultView);\n }\n }, [scopeRef, targetDocument]);\n\n return scopeRef;\n}\n"],"names":["React","useFluent_unstable","useFluent","applyFocusVisiblePolyfill","useFocusVisible","options","contextValue","scopeRef","useRef","targetDocument","useEffect","defaultView","current"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,sBAAsBC,SAAS,QAAQ,kCAAkC;AAElF,SAASC,yBAAyB,QAAQ,gCAAgC;AAM1E,OAAO,SAASC,gBACdC,UAAkC,CAAC,CAAC;IAEpC,MAAMC,eAAeJ;IACrB,MAAMK,WAAWP,MAAMQ,MAAM,CAAW;QAEjBH;IAAvB,MAAMI,iBAAiBJ,CAAAA,0BAAAA,QAAQI,cAAc,cAAtBJ,qCAAAA,0BAA0BC,aAAaG,cAAc;IAE5ET,MAAMU,SAAS,CAAC;QACd,IAAID,CAAAA,2BAAAA,qCAAAA,eAAgBE,WAAW,KAAIJ,SAASK,OAAO,EAAE;YACnD,OAAOT,0BAA0BI,SAASK,OAAO,EAAEH,eAAeE,WAAW;QAC/E;IACF,GAAG;QAACJ;QAAUE;KAAe;IAE7B,OAAOF;AACT"}

View File

@@ -0,0 +1,21 @@
'use client';
import * as React from 'react';
import { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';
import { applyFocusWithinPolyfill } from '../focus/focusWithinPolyfill';
/**
* A ponyfill that allows `:focus-within` to support visibility based on keyboard/mouse navigation
* like `:focus-visible` https://github.com/WICG/focus-visible/issues/151
* @returns ref to the element that uses `:focus-within` styles
*/ export function useFocusWithin() {
const { targetDocument } = useFluent();
const elementRef = React.useRef(null);
React.useEffect(()=>{
if ((targetDocument === null || targetDocument === void 0 ? void 0 : targetDocument.defaultView) && elementRef.current) {
return applyFocusWithinPolyfill(elementRef.current, targetDocument.defaultView);
}
}, [
elementRef,
targetDocument
]);
return elementRef;
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useFocusWithin.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';\nimport { applyFocusWithinPolyfill } from '../focus/focusWithinPolyfill';\n\n/**\n * A ponyfill that allows `:focus-within` to support visibility based on keyboard/mouse navigation\n * like `:focus-visible` https://github.com/WICG/focus-visible/issues/151\n * @returns ref to the element that uses `:focus-within` styles\n */\nexport function useFocusWithin<TElement extends HTMLElement = HTMLElement>(): React.RefObject<TElement | null> {\n const { targetDocument } = useFluent();\n const elementRef = React.useRef<TElement>(null);\n\n React.useEffect(() => {\n if (targetDocument?.defaultView && elementRef.current) {\n return applyFocusWithinPolyfill(elementRef.current, targetDocument.defaultView);\n }\n }, [elementRef, targetDocument]);\n\n return elementRef;\n}\n"],"names":["React","useFluent_unstable","useFluent","applyFocusWithinPolyfill","useFocusWithin","targetDocument","elementRef","useRef","useEffect","defaultView","current"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,sBAAsBC,SAAS,QAAQ,kCAAkC;AAClF,SAASC,wBAAwB,QAAQ,+BAA+B;AAExE;;;;CAIC,GACD,OAAO,SAASC;IACd,MAAM,EAAEC,cAAc,EAAE,GAAGH;IAC3B,MAAMI,aAAaN,MAAMO,MAAM,CAAW;IAE1CP,MAAMQ,SAAS,CAAC;QACd,IAAIH,CAAAA,2BAAAA,qCAAAA,eAAgBI,WAAW,KAAIH,WAAWI,OAAO,EAAE;YACrD,OAAOP,yBAAyBG,WAAWI,OAAO,EAAEL,eAAeI,WAAW;QAChF;IACF,GAAG;QAACH;QAAYD;KAAe;IAE/B,OAAOC;AACT"}

View File

@@ -0,0 +1,30 @@
'use client';
import { getGroupper, GroupperTabbabilities } from 'tabster';
import { useTabsterAttributes } from './useTabsterAttributes';
import { useTabster } from './useTabster';
/**
* A hook that returns the necessary tabster attributes to support groupping.
* @param options - Options to configure keyboard navigation
*/ export const useFocusableGroup = (options)=>{
useTabster(getGroupper);
return useTabsterAttributes({
groupper: {
tabbability: getTabbability(options === null || options === void 0 ? void 0 : options.tabBehavior)
},
focusable: {
ignoreKeydown: options === null || options === void 0 ? void 0 : options.ignoreDefaultKeydown
}
});
};
const getTabbability = (tabBehavior)=>{
switch(tabBehavior){
case 'unlimited':
return GroupperTabbabilities.Unlimited;
case 'limited':
return GroupperTabbabilities.Limited;
case 'limited-trap-focus':
return GroupperTabbabilities.LimitedTrapFocus;
default:
return undefined;
}
};

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useFocusableGroup.ts"],"sourcesContent":["'use client';\n\nimport { Types, getGroupper, GroupperTabbabilities } from 'tabster';\nimport { useTabsterAttributes } from './useTabsterAttributes';\nimport { useTabster } from './useTabster';\n\nexport interface UseFocusableGroupOptions {\n /**\n * Behavior for the Tab key.\n */\n tabBehavior?: 'unlimited' | 'limited' | 'limited-trap-focus';\n\n /**\n * Tabster can ignore default handling of keydown events\n */\n ignoreDefaultKeydown?: Types.FocusableProps['ignoreKeydown'];\n}\n\n/**\n * A hook that returns the necessary tabster attributes to support groupping.\n * @param options - Options to configure keyboard navigation\n */\nexport const useFocusableGroup = (options?: UseFocusableGroupOptions): Types.TabsterDOMAttribute => {\n useTabster(getGroupper);\n\n return useTabsterAttributes({\n groupper: {\n tabbability: getTabbability(options?.tabBehavior),\n },\n focusable: {\n ignoreKeydown: options?.ignoreDefaultKeydown,\n },\n });\n};\n\nconst getTabbability = (\n tabBehavior?: UseFocusableGroupOptions['tabBehavior'],\n): Types.GroupperTabbability | undefined => {\n switch (tabBehavior) {\n case 'unlimited':\n return GroupperTabbabilities.Unlimited;\n case 'limited':\n return GroupperTabbabilities.Limited;\n case 'limited-trap-focus':\n return GroupperTabbabilities.LimitedTrapFocus;\n default:\n return undefined;\n }\n};\n"],"names":["getGroupper","GroupperTabbabilities","useTabsterAttributes","useTabster","useFocusableGroup","options","groupper","tabbability","getTabbability","tabBehavior","focusable","ignoreKeydown","ignoreDefaultKeydown","Unlimited","Limited","LimitedTrapFocus","undefined"],"mappings":"AAAA;AAEA,SAAgBA,WAAW,EAAEC,qBAAqB,QAAQ,UAAU;AACpE,SAASC,oBAAoB,QAAQ,yBAAyB;AAC9D,SAASC,UAAU,QAAQ,eAAe;AAc1C;;;CAGC,GACD,OAAO,MAAMC,oBAAoB,CAACC;IAChCF,WAAWH;IAEX,OAAOE,qBAAqB;QAC1BI,UAAU;YACRC,aAAaC,eAAeH,oBAAAA,8BAAAA,QAASI,WAAW;QAClD;QACAC,WAAW;YACTC,aAAa,EAAEN,oBAAAA,8BAAAA,QAASO,oBAAoB;QAC9C;IACF;AACF,EAAE;AAEF,MAAMJ,iBAAiB,CACrBC;IAEA,OAAQA;QACN,KAAK;YACH,OAAOR,sBAAsBY,SAAS;QACxC,KAAK;YACH,OAAOZ,sBAAsBa,OAAO;QACtC,KAAK;YACH,OAAOb,sBAAsBc,gBAAgB;QAC/C;YACE,OAAOC;IACX;AACF"}

View File

@@ -0,0 +1,26 @@
'use client';
import { disposeTabster } from 'tabster';
import * as React from 'react';
import { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';
import { useEventCallback } from '@fluentui/react-utilities';
import { createTabsterWithConfig } from './useTabster';
/**
* Subscribes to the tabster focused element. Calls the callback when the focused element changes.
* @param callback - Callback to subscribe to the focused element.
*/ export function useFocusedElementChange(callback) {
const { targetDocument } = useFluent();
const listener = useEventCallback(callback);
React.useEffect(()=>{
const tabster = createTabsterWithConfig(targetDocument);
if (tabster) {
tabster.focusedElement.subscribe(listener);
return ()=>{
tabster.focusedElement.unsubscribe(listener);
disposeTabster(tabster);
};
}
}, [
listener,
targetDocument
]);
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useFocusedElementChange.ts"],"sourcesContent":["'use client';\n\nimport { type Types as TabsterTypes, disposeTabster } from 'tabster';\nimport * as React from 'react';\nimport { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';\nimport { useEventCallback } from '@fluentui/react-utilities';\n\nimport { createTabsterWithConfig } from './useTabster';\n\n/**\n * Subscribes to the tabster focused element. Calls the callback when the focused element changes.\n * @param callback - Callback to subscribe to the focused element.\n */\nexport function useFocusedElementChange(\n callback: TabsterTypes.SubscribableCallback<HTMLElement | undefined, TabsterTypes.FocusedElementDetail>,\n): void {\n const { targetDocument } = useFluent();\n const listener = useEventCallback(callback);\n\n React.useEffect(() => {\n const tabster = createTabsterWithConfig(targetDocument);\n\n if (tabster) {\n tabster.focusedElement.subscribe(listener);\n\n return () => {\n tabster.focusedElement.unsubscribe(listener);\n disposeTabster(tabster);\n };\n }\n }, [listener, targetDocument]);\n}\n"],"names":["disposeTabster","React","useFluent_unstable","useFluent","useEventCallback","createTabsterWithConfig","useFocusedElementChange","callback","targetDocument","listener","useEffect","tabster","focusedElement","subscribe","unsubscribe"],"mappings":"AAAA;AAEA,SAAqCA,cAAc,QAAQ,UAAU;AACrE,YAAYC,WAAW,QAAQ;AAC/B,SAASC,sBAAsBC,SAAS,QAAQ,kCAAkC;AAClF,SAASC,gBAAgB,QAAQ,4BAA4B;AAE7D,SAASC,uBAAuB,QAAQ,eAAe;AAEvD;;;CAGC,GACD,OAAO,SAASC,wBACdC,QAAuG;IAEvG,MAAM,EAAEC,cAAc,EAAE,GAAGL;IAC3B,MAAMM,WAAWL,iBAAiBG;IAElCN,MAAMS,SAAS,CAAC;QACd,MAAMC,UAAUN,wBAAwBG;QAExC,IAAIG,SAAS;YACXA,QAAQC,cAAc,CAACC,SAAS,CAACJ;YAEjC,OAAO;gBACLE,QAAQC,cAAc,CAACE,WAAW,CAACL;gBACnCT,eAAeW;YACjB;QACF;IACF,GAAG;QAACF;QAAUD;KAAe;AAC/B"}

View File

@@ -0,0 +1,16 @@
'use client';
import * as React from 'react';
import { useKeyborgRef } from './useKeyborgRef';
/**
* Instantiates [keyborg](https://github.com/microsoft/keyborg) and checks if the user is navigating with the keyboard.
* @returns
*/ export function useIsNavigatingWithKeyboard() {
const keyborgRef = useKeyborgRef();
return React.useCallback(()=>{
var _keyborgRef_current;
var _keyborgRef_current_isNavigatingWithKeyboard;
return (_keyborgRef_current_isNavigatingWithKeyboard = (_keyborgRef_current = keyborgRef.current) === null || _keyborgRef_current === void 0 ? void 0 : _keyborgRef_current.isNavigatingWithKeyboard()) !== null && _keyborgRef_current_isNavigatingWithKeyboard !== void 0 ? _keyborgRef_current_isNavigatingWithKeyboard : false;
}, [
keyborgRef
]);
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useIsNavigatingWithKeyboard.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { useKeyborgRef } from './useKeyborgRef';\n\n/**\n * Instantiates [keyborg](https://github.com/microsoft/keyborg) and checks if the user is navigating with the keyboard.\n * @returns\n */\nexport function useIsNavigatingWithKeyboard(): () => boolean {\n const keyborgRef = useKeyborgRef();\n\n return React.useCallback(() => {\n return keyborgRef.current?.isNavigatingWithKeyboard() ?? false;\n }, [keyborgRef]);\n}\n"],"names":["React","useKeyborgRef","useIsNavigatingWithKeyboard","keyborgRef","useCallback","current","isNavigatingWithKeyboard"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,aAAa,QAAQ,kBAAkB;AAEhD;;;CAGC,GACD,OAAO,SAASC;IACd,MAAMC,aAAaF;IAEnB,OAAOD,MAAMI,WAAW,CAAC;YAChBD;YAAAA;QAAP,OAAOA,CAAAA,gDAAAA,sBAAAA,WAAWE,OAAO,cAAlBF,0CAAAA,oBAAoBG,wBAAwB,gBAA5CH,0DAAAA,+CAAkD;IAC3D,GAAG;QAACA;KAAW;AACjB"}

View File

@@ -0,0 +1,39 @@
'use client';
import * as React from 'react';
import { createKeyborg } from 'keyborg';
import { KEYBOARD_NAV_ATTRIBUTE } from '../focus/constants';
import { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';
/**
* Instantiates [keyborg](https://github.com/microsoft/keyborg) and adds `data-keyboard-nav`
* attribute to a referenced element to ensure keyboard navigation awareness
* synced to keyborg logic without having to cause a re-render on react tree.
*/ export function useKeyboardNavAttribute() {
const { targetDocument } = useFluent();
const keyborg = React.useMemo(()=>targetDocument && createKeyborg(targetDocument.defaultView), [
targetDocument
]);
const ref = React.useRef(null);
React.useEffect(()=>{
if (keyborg) {
setBooleanAttribute(ref, KEYBOARD_NAV_ATTRIBUTE, keyborg.isNavigatingWithKeyboard());
const cb = (next)=>{
setBooleanAttribute(ref, KEYBOARD_NAV_ATTRIBUTE, next);
};
keyborg.subscribe(cb);
return ()=>keyborg.unsubscribe(cb);
}
}, [
keyborg
]);
return ref;
}
function setBooleanAttribute(elementRef, attribute, value) {
if (!elementRef.current) {
return;
}
if (value) {
elementRef.current.setAttribute(attribute, '');
} else {
elementRef.current.removeAttribute(attribute);
}
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useKeyboardNavAttribute.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { createKeyborg } from 'keyborg';\nimport { KEYBOARD_NAV_ATTRIBUTE } from '../focus/constants';\nimport { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';\nimport type { KeyborgCallback } from 'keyborg';\n\n/**\n * Instantiates [keyborg](https://github.com/microsoft/keyborg) and adds `data-keyboard-nav`\n * attribute to a referenced element to ensure keyboard navigation awareness\n * synced to keyborg logic without having to cause a re-render on react tree.\n */\nexport function useKeyboardNavAttribute<E extends HTMLElement>(): React.RefObject<E | null> {\n const { targetDocument } = useFluent();\n const keyborg = React.useMemo(() => targetDocument && createKeyborg(targetDocument.defaultView!), [targetDocument]);\n const ref = React.useRef<E>(null);\n React.useEffect(() => {\n if (keyborg) {\n setBooleanAttribute(ref, KEYBOARD_NAV_ATTRIBUTE, keyborg.isNavigatingWithKeyboard());\n const cb: KeyborgCallback = next => {\n setBooleanAttribute(ref, KEYBOARD_NAV_ATTRIBUTE, next);\n };\n keyborg.subscribe(cb);\n return () => keyborg.unsubscribe(cb);\n }\n }, [keyborg]);\n\n return ref;\n}\n\nfunction setBooleanAttribute(elementRef: React.RefObject<HTMLElement | null>, attribute: string, value: boolean) {\n if (!elementRef.current) {\n return;\n }\n if (value) {\n elementRef.current.setAttribute(attribute, '');\n } else {\n elementRef.current.removeAttribute(attribute);\n }\n}\n"],"names":["React","createKeyborg","KEYBOARD_NAV_ATTRIBUTE","useFluent_unstable","useFluent","useKeyboardNavAttribute","targetDocument","keyborg","useMemo","defaultView","ref","useRef","useEffect","setBooleanAttribute","isNavigatingWithKeyboard","cb","next","subscribe","unsubscribe","elementRef","attribute","value","current","setAttribute","removeAttribute"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,aAAa,QAAQ,UAAU;AACxC,SAASC,sBAAsB,QAAQ,qBAAqB;AAC5D,SAASC,sBAAsBC,SAAS,QAAQ,kCAAkC;AAGlF;;;;CAIC,GACD,OAAO,SAASC;IACd,MAAM,EAAEC,cAAc,EAAE,GAAGF;IAC3B,MAAMG,UAAUP,MAAMQ,OAAO,CAAC,IAAMF,kBAAkBL,cAAcK,eAAeG,WAAW,GAAI;QAACH;KAAe;IAClH,MAAMI,MAAMV,MAAMW,MAAM,CAAI;IAC5BX,MAAMY,SAAS,CAAC;QACd,IAAIL,SAAS;YACXM,oBAAoBH,KAAKR,wBAAwBK,QAAQO,wBAAwB;YACjF,MAAMC,KAAsBC,CAAAA;gBAC1BH,oBAAoBH,KAAKR,wBAAwBc;YACnD;YACAT,QAAQU,SAAS,CAACF;YAClB,OAAO,IAAMR,QAAQW,WAAW,CAACH;QACnC;IACF,GAAG;QAACR;KAAQ;IAEZ,OAAOG;AACT;AAEA,SAASG,oBAAoBM,UAA+C,EAAEC,SAAiB,EAAEC,KAAc;IAC7G,IAAI,CAACF,WAAWG,OAAO,EAAE;QACvB;IACF;IACA,IAAID,OAAO;QACTF,WAAWG,OAAO,CAACC,YAAY,CAACH,WAAW;IAC7C,OAAO;QACLD,WAAWG,OAAO,CAACE,eAAe,CAACJ;IACrC;AACF"}

View File

@@ -0,0 +1,26 @@
'use client';
import * as React from 'react';
import { createKeyborg, disposeKeyborg } from 'keyborg';
import { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';
/**
* @internal
* Instantiates [keyborg](https://github.com/microsoft/keyborg)
* @returns - keyborg instance
*/ export function useKeyborgRef() {
const { targetDocument } = useFluent();
const keyborgRef = React.useRef(null);
React.useEffect(()=>{
const targetWindow = targetDocument === null || targetDocument === void 0 ? void 0 : targetDocument.defaultView;
if (targetWindow) {
const keyborg = createKeyborg(targetWindow);
keyborgRef.current = keyborg;
return ()=>{
disposeKeyborg(keyborg);
keyborgRef.current = null;
};
}
}, [
targetDocument
]);
return keyborgRef;
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useKeyborgRef.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { createKeyborg, disposeKeyborg, type Keyborg } from 'keyborg';\nimport { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';\n\n/**\n * @internal\n * Instantiates [keyborg](https://github.com/microsoft/keyborg)\n * @returns - keyborg instance\n */\nexport function useKeyborgRef(): React.RefObject<Keyborg | null> {\n const { targetDocument } = useFluent();\n const keyborgRef = React.useRef<Keyborg | null>(null);\n\n React.useEffect(() => {\n const targetWindow = targetDocument?.defaultView;\n\n if (targetWindow) {\n const keyborg = createKeyborg(targetWindow);\n keyborgRef.current = keyborg;\n\n return () => {\n disposeKeyborg(keyborg);\n keyborgRef.current = null;\n };\n }\n }, [targetDocument]);\n\n return keyborgRef;\n}\n"],"names":["React","createKeyborg","disposeKeyborg","useFluent_unstable","useFluent","useKeyborgRef","targetDocument","keyborgRef","useRef","useEffect","targetWindow","defaultView","keyborg","current"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,aAAa,EAAEC,cAAc,QAAsB,UAAU;AACtE,SAASC,sBAAsBC,SAAS,QAAQ,kCAAkC;AAElF;;;;CAIC,GACD,OAAO,SAASC;IACd,MAAM,EAAEC,cAAc,EAAE,GAAGF;IAC3B,MAAMG,aAAaP,MAAMQ,MAAM,CAAiB;IAEhDR,MAAMS,SAAS,CAAC;QACd,MAAMC,eAAeJ,2BAAAA,qCAAAA,eAAgBK,WAAW;QAEhD,IAAID,cAAc;YAChB,MAAME,UAAUX,cAAcS;YAC9BH,WAAWM,OAAO,GAAGD;YAErB,OAAO;gBACLV,eAAeU;gBACfL,WAAWM,OAAO,GAAG;YACvB;QACF;IACF,GAAG;QAACP;KAAe;IAEnB,OAAOC;AACT"}

View File

@@ -0,0 +1,76 @@
'use client';
import * as React from 'react';
import { TABSTER_ATTRIBUTE_NAME } from 'tabster';
/**
* Merges a collection of tabster attributes.
*
* ⚠The attributes passed as arguments to this hook cannot change at runtime.
* @internal
* @param attributes - collection of tabster attributes from other react-tabster hooks
* @returns single merged tabster attribute
*/ export const useMergedTabsterAttributes_unstable = (...attributes)=>{
'use no memo';
const stringAttributes = attributes.reduce((acc, curr)=>{
if (curr === null || curr === void 0 ? void 0 : curr[TABSTER_ATTRIBUTE_NAME]) {
acc.push(curr[TABSTER_ATTRIBUTE_NAME]);
}
return acc;
}, []);
if (process.env.NODE_ENV !== 'production') {
// ignoring rules of hooks because this is a condition based on the environment
// it's safe to ignore the rule
// eslint-disable-next-line react-hooks/rules-of-hooks
useWarnIfUnstableAttributes(stringAttributes);
}
return React.useMemo(()=>({
[TABSTER_ATTRIBUTE_NAME]: stringAttributes.length > 0 ? stringAttributes.reduce(mergeJSONStrings) : undefined
}), // disable exhaustive-deps because we want to memoize the result of the reduction
// this is safe because the collection of attributes is not expected to change at runtime
// eslint-disable-next-line react-hooks/exhaustive-deps
stringAttributes);
};
/**
* Merges two JSON strings into one.
*/ const mergeJSONStrings = (a, b)=>JSON.stringify(Object.assign(safelyParseJSON(a), safelyParseJSON(b)));
/**
* Tries to parse a JSON string and returns an object.
* If the JSON string is invalid, an empty object is returned.
*/ const safelyParseJSON = (json)=>{
try {
return JSON.parse(json);
} catch {
return {};
}
};
/**
* Helper hook that ensures that the attributes passed to the hook are stable.
* This is necessary because the attributes are expected to not change at runtime.
*
* This hook will console.warn if the attributes change at runtime.
*/ const useWarnIfUnstableAttributes = (attributes)=>{
'use no memo';
const initialAttributesRef = React.useRef(attributes);
let isStable = initialAttributesRef.current.length === attributes.length;
if (initialAttributesRef.current !== attributes && isStable) {
for(let i = 0; i < attributes.length; i++){
if (initialAttributesRef.current[i] !== attributes[i]) {
isStable = false;
break;
}
}
}
React.useEffect(()=>{
if (!isStable) {
const error = new Error();
// eslint-disable-next-line no-console
console.warn(/** #__DE-INDENT__ */ `
@fluentui/react-tabster [useMergedTabsterAttributes]:
The attributes passed to the hook changed at runtime.
This might lead to unexpected behavior, please ensure that the attributes are stable.
${error.stack}
`);
}
}, [
isStable
]);
};

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More