fix: allow for external focus management (#1730)

* fix: allow for external focus management

* chore: add resetFocus param

* chore: hide new apis behind context option

* chore: fix test check

* fix: unit test
This commit is contained in:
Tobias Åström
2025-05-05 11:17:08 +02:00
committed by GitHub
parent f65c678c80
commit bdf73b6549
4 changed files with 46 additions and 32 deletions

View File

@@ -351,6 +351,7 @@ const Cell = forwardRef(
translator,
language,
keyboardNavigation,
externalFocusManagement,
disableCellPadding = false,
} = useContext(InstanceContext);
const [internalEmitter] = useState(emitter || createEmitter);
@@ -383,18 +384,21 @@ const Cell = forwardRef(
useEffect(() => {
eventmixin(focusHandler.current);
focusHandler.current.blurCallback = (resetFocus) => {
if (focusHandler.current.onBlurHandler) {
focusHandler.current.onBlurHandler(resetFocus);
return;
}
halo.root.toggleFocusOfCells();
if (resetFocus && contentNode) {
contentNode.focus();
}
};
focusHandler.current.refocusContent = () => {
state.sn.component && typeof state.sn.component.focus === 'function' && state.sn.component.focus();
};
}, []);
focusHandler.current.blurCallback = (resetFocus) => {
halo.root.toggleFocusOfCells();
if (resetFocus && contentNode) {
contentNode.focus();
}
};
focusHandler.current.refocusContent = () => {
state.sn.component && typeof state.sn.component.focus === 'function' && state.sn.component.focus();
};
const handleOnMouseEnter = () => {
if (hoveringDebouncer.current.leave) {
clearTimeout(hoveringDebouncer.current.leave);
@@ -510,7 +514,7 @@ const Cell = forwardRef(
}
},
setOnBlurHandler(cb) {
focusHandler.current.blurCallback = cb;
focusHandler.current.onBlurHandler = cb;
},
setSnOptions,
setSnPlugins,
@@ -650,8 +654,8 @@ const Cell = forwardRef(
</Header>
)}
<Grid
tabIndex={keyboardNavigation ? 0 : -1}
onKeyDown={keyboardNavigation ? handleKeyDown : null}
tabIndex={keyboardNavigation && !externalFocusManagement ? 0 : -1}
onKeyDown={keyboardNavigation && !externalFocusManagement ? handleKeyDown : null}
item
xs
className={CellBody.className}

View File

@@ -87,6 +87,31 @@ export default function viz({
}
};
let newExperimental = {};
if (halo.context?.enablePrivateExperimental) {
// ===== undocumented experimental API - use at own risk ======
newExperimental = {
/**
* valid types: viewData, cssScaling, snapshot, exportData, exploration
* questionable types: supportRefresh, quickMobile, fullscreen
* deprecated?: sharing
*
*/
support(type) {
if (mountedReference && successfulRender) {
return cellRef.current.support(type, originalExtensionDef?.support, originalLayout);
}
return false;
},
toggleFocus(focus) {
cellRef.current.toggleFocus(focus);
},
setOnBlurHandler(cb) {
cellRef.current.setOnBlurHandler(cb);
},
};
}
/**
* @class
* @alias Viz
@@ -253,25 +278,7 @@ export default function viz({
await rendered;
return cellRef.current.takeSnapshot();
},
// ===== undocumented experimental API - use at own risk ======
/**
* valid types: viewData, cssScaling, snapshot, exportData, exploration
* questionable types: supportRefresh, quickMobile, fullscreen
* deprecated?: sharing
*
*/
support(type) {
if (mountedReference && successfulRender) {
return cellRef.current.support(type, originalExtensionDef?.support, originalLayout);
}
return false;
},
toggleFocus(focus) {
cellRef.current.toggleFocus(focus);
},
setOnBlurHandler(cb) {
cellRef.current.setOnBlurHandler(cb);
},
...newExperimental,
// ===== unexposed experimental API - use at own risk ======
__DO_NOT_USE__: {
mount(element) {

View File

@@ -121,6 +121,7 @@ describe('creator', () => {
opts = {
nebbie: 'embedAPI',
keyboardNavigation: false,
externalFocusManagement: false,
focusHandler: 'focusHandler',
emitter: 'emitter',
model: 'model',
@@ -145,6 +146,7 @@ describe('creator', () => {
selections: 'selections',
nebbie: 'embedAPI',
keyboardNavigation: false,
externalFocusManagement: false,
focusHandler: 'focusHandler',
emitter: 'emitter',
element: undefined,

View File

@@ -82,6 +82,7 @@ function createWithHooks(generator, opts, galaxy) {
layout: {},
appLayout: {},
keyboardNavigation: opts.keyboardNavigation,
externalFocusManagement: opts.externalFocusManagement || false,
focusHandler: opts.focusHandler,
constraints: forcedConstraints,
interactions: forcedInteractions,