@cloudscape-design/components-themeable 3.0.403 → 3.0.405
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/internal/manifest.json +1 -1
- package/lib/internal/scss/app-layout/drawer/styles.scss +11 -0
- package/lib/internal/scss/internal/components/dropdown/styles.scss +5 -11
- package/lib/internal/scss/table/sticky-scrollbar/styles.scss +1 -0
- package/lib/internal/template/app-layout/drawer/drawers-helpers.d.ts +1 -1
- package/lib/internal/template/app-layout/drawer/drawers-helpers.d.ts.map +1 -1
- package/lib/internal/template/app-layout/drawer/drawers-helpers.js +4 -8
- package/lib/internal/template/app-layout/drawer/drawers-helpers.js.map +1 -1
- package/lib/internal/template/app-layout/drawer/index.d.ts.map +1 -1
- package/lib/internal/template/app-layout/drawer/index.js +13 -4
- package/lib/internal/template/app-layout/drawer/index.js.map +1 -1
- package/lib/internal/template/app-layout/drawer/styles.css.js +11 -10
- package/lib/internal/template/app-layout/drawer/styles.scoped.css +24 -17
- package/lib/internal/template/app-layout/drawer/styles.selectors.js +11 -10
- package/lib/internal/template/app-layout/index.d.ts.map +1 -1
- package/lib/internal/template/app-layout/index.js +3 -0
- package/lib/internal/template/app-layout/index.js.map +1 -1
- package/lib/internal/template/app-layout/mobile-toolbar/index.js +1 -1
- package/lib/internal/template/app-layout/mobile-toolbar/index.js.map +1 -1
- package/lib/internal/template/app-layout/visual-refresh/drawers.js +1 -1
- package/lib/internal/template/app-layout/visual-refresh/drawers.js.map +1 -1
- package/lib/internal/template/autosuggest/internal.d.ts.map +1 -1
- package/lib/internal/template/autosuggest/internal.js +5 -3
- package/lib/internal/template/autosuggest/internal.js.map +1 -1
- package/lib/internal/template/button-dropdown/interfaces.d.ts +2 -1
- package/lib/internal/template/button-dropdown/interfaces.d.ts.map +1 -1
- package/lib/internal/template/button-dropdown/interfaces.js.map +1 -1
- package/lib/internal/template/button-dropdown/internal.js +4 -4
- package/lib/internal/template/button-dropdown/internal.js.map +1 -1
- package/lib/internal/template/internal/components/dropdown/index.d.ts.map +1 -1
- package/lib/internal/template/internal/components/dropdown/index.js +6 -8
- package/lib/internal/template/internal/components/dropdown/index.js.map +1 -1
- package/lib/internal/template/internal/components/dropdown/styles.css.js +20 -21
- package/lib/internal/template/internal/components/dropdown/styles.scoped.css +37 -41
- package/lib/internal/template/internal/components/dropdown/styles.selectors.js +20 -21
- package/lib/internal/template/internal/components/dropdown-status/index.d.ts +6 -1
- package/lib/internal/template/internal/components/dropdown-status/index.d.ts.map +1 -1
- package/lib/internal/template/internal/components/dropdown-status/index.js +2 -2
- package/lib/internal/template/internal/components/dropdown-status/index.js.map +1 -1
- package/lib/internal/template/internal/environment.js +1 -1
- package/lib/internal/template/internal/environment.json +1 -1
- package/lib/internal/template/internal/hooks/use-visual-mode/index.d.ts +0 -2
- package/lib/internal/template/internal/hooks/use-visual-mode/index.d.ts.map +1 -1
- package/lib/internal/template/internal/hooks/use-visual-mode/index.js +2 -31
- package/lib/internal/template/internal/hooks/use-visual-mode/index.js.map +1 -1
- package/lib/internal/template/multiselect/internal.d.ts.map +1 -1
- package/lib/internal/template/multiselect/internal.js +7 -2
- package/lib/internal/template/multiselect/internal.js.map +1 -1
- package/lib/internal/template/property-filter/controller.d.ts.map +1 -1
- package/lib/internal/template/property-filter/controller.js +23 -11
- package/lib/internal/template/property-filter/controller.js.map +1 -1
- package/lib/internal/template/property-filter/index.d.ts.map +1 -1
- package/lib/internal/template/property-filter/index.js +26 -11
- package/lib/internal/template/property-filter/index.js.map +1 -1
- package/lib/internal/template/property-filter/property-filter-autosuggest.d.ts.map +1 -1
- package/lib/internal/template/property-filter/property-filter-autosuggest.js +1 -1
- package/lib/internal/template/property-filter/property-filter-autosuggest.js.map +1 -1
- package/lib/internal/template/select/internal.d.ts.map +1 -1
- package/lib/internal/template/select/internal.js +3 -1
- package/lib/internal/template/select/internal.js.map +1 -1
- package/lib/internal/template/table/sticky-scrollbar/sticky-scrollbar.js +1 -1
- package/lib/internal/template/table/sticky-scrollbar/sticky-scrollbar.js.map +1 -1
- package/lib/internal/template/table/sticky-scrollbar/use-sticky-scrollbar.d.ts +1 -1
- package/lib/internal/template/table/sticky-scrollbar/use-sticky-scrollbar.d.ts.map +1 -1
- package/lib/internal/template/table/sticky-scrollbar/use-sticky-scrollbar.js +10 -2
- package/lib/internal/template/table/sticky-scrollbar/use-sticky-scrollbar.js.map +1 -1
- package/lib/internal/template/table/table-role/index.d.ts +1 -1
- package/lib/internal/template/table/table-role/index.d.ts.map +1 -1
- package/lib/internal/template/table/table-role/index.js.map +1 -1
- package/lib/internal/template/table/table-role/interfaces.d.ts +2 -4
- package/lib/internal/template/table/table-role/interfaces.d.ts.map +1 -1
- package/lib/internal/template/table/table-role/interfaces.js.map +1 -1
- package/lib/internal/template/table/table-role/use-grid-navigation.d.ts +6 -3
- package/lib/internal/template/table/table-role/use-grid-navigation.d.ts.map +1 -1
- package/lib/internal/template/table/table-role/use-grid-navigation.js +71 -40
- package/lib/internal/template/table/table-role/use-grid-navigation.js.map +1 -1
- package/lib/internal/template/table/table-role/utils.d.ts +22 -4
- package/lib/internal/template/table/table-role/utils.d.ts.map +1 -1
- package/lib/internal/template/table/table-role/utils.js +86 -57
- package/lib/internal/template/table/table-role/utils.js.map +1 -1
- package/package.json +1 -1
|
@@ -46,7 +46,7 @@ export const updatePosition = (tableEl, wrapperEl, scrollbarEl, scrollbarContent
|
|
|
46
46
|
scrollbarEl.style.bottom = hasContainingBlock ? '0px' : `${consideredFooterHeight}px`;
|
|
47
47
|
}
|
|
48
48
|
};
|
|
49
|
-
export function useStickyScrollbar(scrollbarRef, scrollbarContentRef, tableRef, wrapperRef, footerHeight) {
|
|
49
|
+
export function useStickyScrollbar(scrollbarRef, scrollbarContentRef, tableRef, wrapperRef, footerHeight, offsetScrollbar) {
|
|
50
50
|
// We don't take into account containing-block calculations because that would
|
|
51
51
|
// unnecessarily overcomplicate the position logic. For now, we assume that a
|
|
52
52
|
// containing block, if present, is below the app layout and above the overflow
|
|
@@ -79,7 +79,15 @@ export function useStickyScrollbar(scrollbarRef, scrollbarContentRef, tableRef,
|
|
|
79
79
|
observer.disconnect();
|
|
80
80
|
};
|
|
81
81
|
}
|
|
82
|
-
}, [
|
|
82
|
+
}, [
|
|
83
|
+
scrollbarContentRef,
|
|
84
|
+
scrollbarRef,
|
|
85
|
+
tableRef,
|
|
86
|
+
wrapperRef,
|
|
87
|
+
consideredFooterHeight,
|
|
88
|
+
hasContainingBlock,
|
|
89
|
+
offsetScrollbar,
|
|
90
|
+
]);
|
|
83
91
|
// Update scrollbar position when window resizes (vertically).
|
|
84
92
|
useEffect(() => {
|
|
85
93
|
if (supportsStickyPosition()) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-sticky-scrollbar.js","sourceRoot":"lib/default/","sources":["table/sticky-scrollbar/use-sticky-scrollbar.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,sCAAsC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAa,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACvD,OAAO,MAAM,MAAM,iBAAiB,CAAC;AACrC,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AACtF,OAAO,EAAE,kBAAkB,EAAE,MAAM,4CAA4C,CAAC;AAChF,OAAO,EAAE,oBAAoB,EAAE,MAAM,6CAA6C,CAAC;AAEnF,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,OAA2B,EAC3B,SAA6B,EAC7B,WAA+B,EAC/B,kBAAsC,EACtC,kBAA2B,EAC3B,sBAA8B,EAC9B,EAAE;IACF,IAAI,CAAC,OAAO,IAAI,CAAC,WAAW,IAAI,CAAC,SAAS,EAAE;QAC1C,OAAO;KACR;IAED,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC;IAC9D,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,SAAS,CAAC,qBAAqB,EAAE,CAAC;IAElE,0DAA0D;IAC1D,MAAM,eAAe,GAAG,oBAAoB,EAAE,CAAC,MAAM,CAAC;IACtD,MAAM,gBAAgB,GAAG,UAAU,GAAG,YAAY,CAAC;IAEnD,IAAI,CAAC,gBAAgB,EAAE;QACrB,WAAW,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,0BAA0B,CAAC,CAAC,CAAC;KAClE;SAAM;QACL,qFAAqF;QACrF,mCAAmC;QACnC,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,0BAA0B,CAAC,CAAC,EAAE;YACvE,qBAAqB,CAAC,GAAG,EAAE;gBACzB,WAAW,CAAC,UAAU,GAAG,SAAS,CAAC,UAAU,CAAC;YAChD,CAAC,CAAC,CAAC;SACJ;QAED,WAAW,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,0BAA0B,CAAC,CAAC,CAAC;QAC9D,IAAI,CAAC,eAAe,EAAE;YACpB,uDAAuD;YACvD,WAAW,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,mCAAmC,CAAC,CAAC,CAAC;SACxE;KACF;IAED,IAAI,eAAe,IAAI,WAAW,IAAI,kBAAkB,EAAE;QACxD,WAAW,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,eAAe,IAAI,CAAC;QAClD,kBAAkB,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,eAAe,IAAI,CAAC;KAC1D;IAED,IAAI,OAAO,IAAI,SAAS,IAAI,kBAAkB,IAAI,WAAW,EAAE;QAC7D,MAAM,aAAa,GAAG,SAAS,CAAC,qBAAqB,EAAE,CAAC;QACxD,MAAM,WAAW,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC;QACpD,WAAW,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,aAAa,CAAC,KAAK,IAAI,CAAC;QACrD,kBAAkB,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,WAAW,CAAC,KAAK,IAAI,CAAC;QAE1D,6CAA6C;QAC7C,qEAAqE;QACrE,WAAW,CAAC,KAAK,CAAC,MAAM,GAAG,kBAAkB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,sBAAsB,IAAI,CAAC;KACvF;AACH,CAAC,CAAC;AAEF,MAAM,UAAU,kBAAkB,CAChC,YAAuC,EACvC,mBAA8C,EAC9C,QAAqC,EACrC,UAAqC,EACrC,YAAoB;
|
|
1
|
+
{"version":3,"file":"use-sticky-scrollbar.js","sourceRoot":"lib/default/","sources":["table/sticky-scrollbar/use-sticky-scrollbar.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport { ResizeObserver } from '@juggle/resize-observer';\nimport { RefObject, useEffect, useState } from 'react';\nimport styles from './styles.css.js';\nimport { getContainingBlock, supportsStickyPosition } from '../../internal/utils/dom';\nimport { getOverflowParents } from '../../internal/utils/scrollable-containers';\nimport { browserScrollbarSize } from '../../internal/utils/browser-scrollbar-size';\n\nexport const updatePosition = (\n tableEl: HTMLElement | null,\n wrapperEl: HTMLElement | null,\n scrollbarEl: HTMLElement | null,\n scrollbarContentEl: HTMLElement | null,\n hasContainingBlock: boolean,\n consideredFooterHeight: number\n) => {\n if (!tableEl || !scrollbarEl || !wrapperEl) {\n return;\n }\n\n const { width: tableWidth } = tableEl.getBoundingClientRect();\n const { width: wrapperWidth } = wrapperEl.getBoundingClientRect();\n\n // using 15 px as a height of transparent scrollbar on mac\n const scrollbarHeight = browserScrollbarSize().height;\n const areaIsScrollable = tableWidth > wrapperWidth;\n\n if (!areaIsScrollable) {\n scrollbarEl.classList.remove(styles['sticky-scrollbar-visible']);\n } else {\n // when scrollbar is not displayed scrollLeft property cannot be set by useScrollSync\n // that's why syncing it separately\n if (!scrollbarEl.classList.contains(styles['sticky-scrollbar-visible'])) {\n requestAnimationFrame(() => {\n scrollbarEl.scrollLeft = wrapperEl.scrollLeft;\n });\n }\n\n scrollbarEl.classList.add(styles['sticky-scrollbar-visible']);\n if (!scrollbarHeight) {\n /* istanbul ignore next: covered by screenshot tests */\n scrollbarEl.classList.add(styles['sticky-scrollbar-native-invisible']);\n }\n }\n\n if (scrollbarHeight && scrollbarEl && scrollbarContentEl) {\n scrollbarEl.style.height = `${scrollbarHeight}px`;\n scrollbarContentEl.style.height = `${scrollbarHeight}px`;\n }\n\n if (tableEl && wrapperEl && scrollbarContentEl && scrollbarEl) {\n const wrapperElRect = wrapperEl.getBoundingClientRect();\n const tableElRect = tableEl.getBoundingClientRect();\n scrollbarEl.style.width = `${wrapperElRect.width}px`;\n scrollbarContentEl.style.width = `${tableElRect.width}px`;\n\n // when using sticky scrollbars in containers\n // we agreed to ignore dynamic bottom calculations for footer overlap\n scrollbarEl.style.bottom = hasContainingBlock ? '0px' : `${consideredFooterHeight}px`;\n }\n};\n\nexport function useStickyScrollbar(\n scrollbarRef: RefObject<HTMLDivElement>,\n scrollbarContentRef: RefObject<HTMLDivElement>,\n tableRef: RefObject<HTMLTableElement>,\n wrapperRef: RefObject<HTMLDivElement>,\n footerHeight: number,\n offsetScrollbar: boolean\n) {\n // We don't take into account containing-block calculations because that would\n // unnecessarily overcomplicate the position logic. For now, we assume that a\n // containing block, if present, is below the app layout and above the overflow\n // parent, which is a pretty safe assumption.\n const [hasContainingBlock, setHasContainingBlock] = useState(false);\n // We don't take into account footer height when the overflow parent is child of document body.\n // Because in this case, we think the footer is outside the overflow parent.\n const [hasOverflowParent, setHasOverflowParent] = useState(false);\n const consideredFooterHeight = hasContainingBlock || hasOverflowParent ? 0 : footerHeight;\n\n const wrapperEl = wrapperRef.current;\n useEffect(() => {\n if (wrapperEl && supportsStickyPosition()) {\n setHasContainingBlock(!!getContainingBlock(wrapperEl));\n setHasOverflowParent(!!getOverflowParents(wrapperEl)[0]);\n }\n }, [wrapperEl]);\n\n // Update scrollbar position wrapper or table size change.\n useEffect(() => {\n if (supportsStickyPosition() && wrapperRef.current && tableRef.current) {\n const observer = new ResizeObserver(() => {\n if (scrollbarContentRef.current) {\n updatePosition(\n tableRef.current,\n wrapperRef.current,\n scrollbarRef.current,\n scrollbarContentRef.current,\n hasContainingBlock,\n consideredFooterHeight\n );\n }\n });\n // Scrollbar width must be in sync with wrapper width.\n observer.observe(wrapperRef.current);\n // Scrollbar content width must be in sync with table width.\n observer.observe(tableRef.current);\n return () => {\n observer.disconnect();\n };\n }\n }, [\n scrollbarContentRef,\n scrollbarRef,\n tableRef,\n wrapperRef,\n consideredFooterHeight,\n hasContainingBlock,\n offsetScrollbar,\n ]);\n\n // Update scrollbar position when window resizes (vertically).\n useEffect(() => {\n if (supportsStickyPosition()) {\n const resizeHandler = () => {\n updatePosition(\n tableRef.current,\n wrapperRef.current,\n scrollbarRef.current,\n scrollbarContentRef.current,\n hasContainingBlock,\n consideredFooterHeight\n );\n };\n resizeHandler();\n window.addEventListener('resize', resizeHandler);\n return () => {\n window.removeEventListener('resize', resizeHandler);\n };\n }\n }, [tableRef, wrapperRef, scrollbarRef, scrollbarContentRef, hasContainingBlock, consideredFooterHeight]);\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { TableRole, GridNavigationProps
|
|
1
|
+
export { TableRole, GridNavigationProps } from './interfaces';
|
|
2
2
|
export { getTableCellRoleProps, getTableColHeaderRoleProps, getTableHeaderRowRoleProps, getTableRoleProps, getTableRowRoleProps, getTableWrapperRoleProps, } from './table-role-helper';
|
|
3
3
|
export { useGridNavigation } from './use-grid-navigation';
|
|
4
4
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"lib/default/","sources":["table/table-role/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"lib/default/","sources":["table/table-role/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAE9D,OAAO,EACL,qBAAqB,EACrB,0BAA0B,EAC1B,0BAA0B,EAC1B,iBAAiB,EACjB,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"lib/default/","sources":["table/table-role/index.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,sCAAsC;AAItC,OAAO,EACL,qBAAqB,EACrB,0BAA0B,EAC1B,0BAA0B,EAC1B,iBAAiB,EACjB,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nexport { TableRole, GridNavigationProps
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"lib/default/","sources":["table/table-role/index.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,sCAAsC;AAItC,OAAO,EACL,qBAAqB,EACrB,0BAA0B,EAC1B,0BAA0B,EAC1B,iBAAiB,EACjB,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nexport { TableRole, GridNavigationProps } from './interfaces';\n\nexport {\n getTableCellRoleProps,\n getTableColHeaderRoleProps,\n getTableHeaderRowRoleProps,\n getTableRoleProps,\n getTableRowRoleProps,\n getTableWrapperRoleProps,\n} from './table-role-helper';\n\nexport { useGridNavigation } from './use-grid-navigation';\n"]}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
export type TableRole = 'table' | 'grid' | 'grid-default';
|
|
2
2
|
export interface GridNavigationProps {
|
|
3
|
-
|
|
3
|
+
active: boolean;
|
|
4
4
|
pageSize: number;
|
|
5
5
|
getTable: () => null | HTMLTableElement;
|
|
6
|
-
|
|
7
|
-
export interface GridNavigationAPI {
|
|
6
|
+
isSuppressed?: (focusedElement: HTMLElement) => void;
|
|
8
7
|
}
|
|
9
8
|
export interface FocusedCell {
|
|
10
9
|
rowIndex: number;
|
|
@@ -13,6 +12,5 @@ export interface FocusedCell {
|
|
|
13
12
|
rowElement: HTMLTableRowElement;
|
|
14
13
|
cellElement: HTMLTableCellElement;
|
|
15
14
|
element: HTMLElement;
|
|
16
|
-
dialog: boolean;
|
|
17
15
|
}
|
|
18
16
|
//# sourceMappingURL=interfaces.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interfaces.d.ts","sourceRoot":"lib/default/","sources":["table/table-role/interfaces.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,cAAc,CAAC;AAE1D,MAAM,WAAW,mBAAmB;IAClC,
|
|
1
|
+
{"version":3,"file":"interfaces.d.ts","sourceRoot":"lib/default/","sources":["table/table-role/interfaces.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,cAAc,CAAC;AAE1D,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,IAAI,GAAG,gBAAgB,CAAC;IACxC,YAAY,CAAC,EAAE,CAAC,cAAc,EAAE,WAAW,KAAK,IAAI,CAAC;CACtD;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,mBAAmB,CAAC;IAChC,WAAW,EAAE,oBAAoB,CAAC;IAClC,OAAO,EAAE,WAAW,CAAC;CACtB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interfaces.js","sourceRoot":"lib/default/","sources":["table/table-role/interfaces.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,sCAAsC","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nexport type TableRole = 'table' | 'grid' | 'grid-default';\n\nexport interface GridNavigationProps {\n
|
|
1
|
+
{"version":3,"file":"interfaces.js","sourceRoot":"lib/default/","sources":["table/table-role/interfaces.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,sCAAsC","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nexport type TableRole = 'table' | 'grid' | 'grid-default';\n\nexport interface GridNavigationProps {\n active: boolean;\n pageSize: number;\n getTable: () => null | HTMLTableElement;\n isSuppressed?: (focusedElement: HTMLElement) => void;\n}\n\nexport interface FocusedCell {\n rowIndex: number;\n colIndex: number;\n elementIndex: number;\n rowElement: HTMLTableRowElement;\n cellElement: HTMLTableCellElement;\n element: HTMLElement;\n}\n"]}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { GridNavigationProps } from './interfaces';
|
|
2
2
|
/**
|
|
3
|
-
* Makes table
|
|
3
|
+
* Makes table navigable with keyboard commands.
|
|
4
4
|
* See https://www.w3.org/WAI/ARIA/apg/patterns/grid
|
|
5
|
+
*
|
|
6
|
+
* The hook attaches the GridNavigationHelper helper when active=true.
|
|
7
|
+
* See GridNavigationHelper for more details.
|
|
5
8
|
*/
|
|
6
|
-
export declare function useGridNavigation({
|
|
9
|
+
export declare function useGridNavigation({ active, pageSize, getTable, isSuppressed }: GridNavigationProps): void;
|
|
7
10
|
//# sourceMappingURL=use-grid-navigation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-grid-navigation.d.ts","sourceRoot":"lib/default/","sources":["table/table-role/use-grid-navigation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use-grid-navigation.d.ts","sourceRoot":"lib/default/","sources":["table/table-role/use-grid-navigation.ts"],"names":[],"mappings":"AAaA,OAAO,EAAe,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAKhE;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE,mBAAmB,QAmBlG"}
|
|
@@ -1,53 +1,71 @@
|
|
|
1
1
|
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
import { useEffect, useMemo } from 'react';
|
|
4
|
-
import { findFocusinCell, moveFocusBy,
|
|
4
|
+
import { defaultIsSuppressed, findFocusinCell, moveFocusBy, muteElementFocusables, restoreElementFocusables, ensureSingleFocusable, getFirstFocusable, } from './utils';
|
|
5
5
|
import { KeyCode } from '../../internal/keycode';
|
|
6
6
|
import { nodeContains } from '@cloudscape-design/component-toolkit/dom';
|
|
7
|
+
import { useStableCallback } from '@cloudscape-design/component-toolkit/internal';
|
|
7
8
|
/**
|
|
8
|
-
* Makes table
|
|
9
|
+
* Makes table navigable with keyboard commands.
|
|
9
10
|
* See https://www.w3.org/WAI/ARIA/apg/patterns/grid
|
|
11
|
+
*
|
|
12
|
+
* The hook attaches the GridNavigationHelper helper when active=true.
|
|
13
|
+
* See GridNavigationHelper for more details.
|
|
10
14
|
*/
|
|
11
|
-
export function useGridNavigation({
|
|
12
|
-
const
|
|
15
|
+
export function useGridNavigation({ active, pageSize, getTable, isSuppressed }) {
|
|
16
|
+
const gridNavigation = useMemo(() => new GridNavigationHelper(), []);
|
|
17
|
+
const getTableStable = useStableCallback(getTable);
|
|
18
|
+
const isSuppressedStable = useStableCallback((element) => { var _a; return (_a = isSuppressed === null || isSuppressed === void 0 ? void 0 : isSuppressed(element)) !== null && _a !== void 0 ? _a : false; });
|
|
13
19
|
// Initialize the model with the table container assuming it is mounted synchronously and only once.
|
|
14
20
|
useEffect(() => {
|
|
15
|
-
if (
|
|
16
|
-
const table =
|
|
17
|
-
table &&
|
|
21
|
+
if (active) {
|
|
22
|
+
const table = getTableStable();
|
|
23
|
+
table && gridNavigation.init(table, isSuppressedStable);
|
|
18
24
|
}
|
|
19
|
-
return () =>
|
|
20
|
-
},
|
|
21
|
-
// Assuming getTable is stable.
|
|
22
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
23
|
-
[model, tableRole]);
|
|
25
|
+
return () => gridNavigation.cleanup();
|
|
26
|
+
}, [active, gridNavigation, getTableStable, isSuppressedStable]);
|
|
24
27
|
// Notify the model of the props change.
|
|
25
28
|
useEffect(() => {
|
|
26
|
-
|
|
27
|
-
}, [
|
|
28
|
-
return {};
|
|
29
|
+
gridNavigation.update({ pageSize });
|
|
30
|
+
}, [gridNavigation, pageSize]);
|
|
29
31
|
}
|
|
30
|
-
|
|
32
|
+
/**
|
|
33
|
+
* This helper encapsulates the grid navigation behaviors which are:
|
|
34
|
+
* 1. Responding to keyboard commands and moving the focus accordingly;
|
|
35
|
+
* 2. Muting table interactive elements for only one to be user-focusable at a time;
|
|
36
|
+
* 3. Suppressing the above behaviors when focusing an element inside a dialog or when instructed by the isSuppressed callback.
|
|
37
|
+
*
|
|
38
|
+
* All behaviors are attached upon initialization and are re-evaluated with every focusin, focusout, and keydown events,
|
|
39
|
+
* and also when a node removal inside the table is observed to ensure consistency at any given moment.
|
|
40
|
+
*
|
|
41
|
+
* When the navigation is suppressed the keyboard commands are no longer intercepted and all table interactive elements are made
|
|
42
|
+
* user-focusable to unblock the Tab navigation. The suppression should only be used for interactive elements inside the table that would
|
|
43
|
+
* otherwise conflict with the navigation. Once the interactive element is deactivated or lose focus the table navigation becomes active again.
|
|
44
|
+
*/
|
|
45
|
+
class GridNavigationHelper {
|
|
31
46
|
constructor() {
|
|
32
47
|
// Props
|
|
33
48
|
this._pageSize = 0;
|
|
34
49
|
this._table = null;
|
|
50
|
+
this._isSuppressed = () => false;
|
|
35
51
|
// State
|
|
36
52
|
this.prevFocusedCell = null;
|
|
37
53
|
this.focusedCell = null;
|
|
38
|
-
this.cleanup = () => { };
|
|
39
54
|
this.onFocusin = (event) => {
|
|
55
|
+
var _a;
|
|
40
56
|
const cell = findFocusinCell(event);
|
|
41
57
|
if (!cell) {
|
|
42
58
|
return;
|
|
43
59
|
}
|
|
44
|
-
if (cell.element !== event.target) {
|
|
45
|
-
cell.element.focus();
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
60
|
this.prevFocusedCell = cell;
|
|
49
61
|
this.focusedCell = cell;
|
|
50
|
-
|
|
62
|
+
muteElementFocusables(this.table, this.isSuppressed(cell.element));
|
|
63
|
+
ensureSingleFocusable(this.table, cell);
|
|
64
|
+
// Focusing on cell is not eligible when it contains focusable elements in the content.
|
|
65
|
+
// If content focusables are available - move the focus to the first one.
|
|
66
|
+
if (cell.element === cell.cellElement) {
|
|
67
|
+
(_a = getFirstFocusable(cell.cellElement)) === null || _a === void 0 ? void 0 : _a.focus();
|
|
68
|
+
}
|
|
51
69
|
};
|
|
52
70
|
this.onFocusout = () => {
|
|
53
71
|
this.focusedCell = null;
|
|
@@ -71,8 +89,8 @@ class GridNavigationModel {
|
|
|
71
89
|
const from = this.focusedCell;
|
|
72
90
|
const minExtreme = Number.NEGATIVE_INFINITY;
|
|
73
91
|
const maxExtreme = Number.POSITIVE_INFINITY;
|
|
74
|
-
//
|
|
75
|
-
if (from.
|
|
92
|
+
// Do not intercept any keys when the navigation is suppressed.
|
|
93
|
+
if (this.isSuppressed(from.element)) {
|
|
76
94
|
return;
|
|
77
95
|
}
|
|
78
96
|
switch (key) {
|
|
@@ -112,41 +130,51 @@ class GridNavigationModel {
|
|
|
112
130
|
};
|
|
113
131
|
this.onTableNodeMutation = (mutationRecords) => {
|
|
114
132
|
var _a;
|
|
115
|
-
|
|
116
|
-
|
|
133
|
+
// When focused cell is un-mounted the focusout event handler removes this.cell,
|
|
134
|
+
// while this.prevFocusedCell is retained until the next focusin event.
|
|
135
|
+
const cell = (_a = this.focusedCell) !== null && _a !== void 0 ? _a : this.prevFocusedCell;
|
|
136
|
+
const cellSuppressed = cell ? this.isSuppressed(cell.element) : false;
|
|
137
|
+
// Update table elements focus if new nodes were added.
|
|
138
|
+
if (mutationRecords.some(record => record.addedNodes.length > 0)) {
|
|
139
|
+
muteElementFocusables(this.table, cellSuppressed);
|
|
140
|
+
ensureSingleFocusable(this.table, cell);
|
|
117
141
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
if
|
|
123
|
-
|
|
124
|
-
|
|
142
|
+
if (cell) {
|
|
143
|
+
for (const record of mutationRecords) {
|
|
144
|
+
if (record.type === 'childList') {
|
|
145
|
+
// The lost focus in an unmount event is reapplied to the table using the previous cell position.
|
|
146
|
+
// The moveFocusBy takes care of finding the closest position if the previous one no longer exists.
|
|
147
|
+
for (const removedNode of Array.from(record.removedNodes)) {
|
|
148
|
+
if (removedNode === cell.element || nodeContains(removedNode, cell.element)) {
|
|
149
|
+
ensureSingleFocusable(this.table, cell);
|
|
150
|
+
moveFocusBy(this.table, cell, { y: 0, x: 0 });
|
|
151
|
+
}
|
|
125
152
|
}
|
|
126
153
|
}
|
|
127
154
|
}
|
|
128
155
|
}
|
|
129
156
|
};
|
|
130
157
|
}
|
|
131
|
-
init(table) {
|
|
132
|
-
var _a;
|
|
158
|
+
init(table, isSuppressed) {
|
|
133
159
|
this._table = table;
|
|
160
|
+
this._isSuppressed = isSuppressed;
|
|
134
161
|
this.table.addEventListener('focusin', this.onFocusin);
|
|
135
162
|
this.table.addEventListener('focusout', this.onFocusout);
|
|
136
163
|
this.table.addEventListener('keydown', this.onKeydown);
|
|
137
164
|
const tableNodesObserver = new MutationObserver(this.onTableNodeMutation);
|
|
138
165
|
tableNodesObserver.observe(table, { childList: true, subtree: true });
|
|
139
|
-
|
|
166
|
+
muteElementFocusables(this.table, false);
|
|
167
|
+
ensureSingleFocusable(this.table, null);
|
|
140
168
|
this.cleanup = () => {
|
|
141
169
|
this.table.removeEventListener('focusin', this.onFocusin);
|
|
142
170
|
this.table.removeEventListener('focusout', this.onFocusout);
|
|
143
171
|
this.table.removeEventListener('keydown', this.onKeydown);
|
|
144
172
|
tableNodesObserver.disconnect();
|
|
145
|
-
|
|
173
|
+
restoreElementFocusables(this.table);
|
|
146
174
|
};
|
|
147
175
|
}
|
|
148
|
-
|
|
149
|
-
|
|
176
|
+
cleanup() {
|
|
177
|
+
// Do nothing before initialized.
|
|
150
178
|
}
|
|
151
179
|
update({ pageSize }) {
|
|
152
180
|
this._pageSize = pageSize;
|
|
@@ -156,9 +184,12 @@ class GridNavigationModel {
|
|
|
156
184
|
}
|
|
157
185
|
get table() {
|
|
158
186
|
if (!this._table) {
|
|
159
|
-
throw new Error('Invariant violation:
|
|
187
|
+
throw new Error('Invariant violation: GridNavigationHelper is used before initialization.');
|
|
160
188
|
}
|
|
161
189
|
return this._table;
|
|
162
190
|
}
|
|
191
|
+
isSuppressed(focusedElement) {
|
|
192
|
+
return defaultIsSuppressed(focusedElement) || this._isSuppressed(focusedElement);
|
|
193
|
+
}
|
|
163
194
|
}
|
|
164
195
|
//# sourceMappingURL=use-grid-navigation.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-grid-navigation.js","sourceRoot":"lib/default/","sources":["table/table-role/use-grid-navigation.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { useEffect, useMemo } from 'react';\nimport { findFocusinCell, moveFocusBy, restoreTableFocusables, updateTableFocusables } from './utils';\nimport { FocusedCell, GridNavigationAPI, GridNavigationProps } from './interfaces';\nimport { KeyCode } from '../../internal/keycode';\nimport { nodeContains } from '@cloudscape-design/component-toolkit/dom';\n\n/**\n * Makes table with role=\"grid\" navigable with keyboard commands.\n * See https://www.w3.org/WAI/ARIA/apg/patterns/grid\n */\nexport function useGridNavigation({ tableRole, pageSize, getTable }: GridNavigationProps): GridNavigationAPI {\n const model = useMemo(() => new GridNavigationModel(), []);\n\n // Initialize the model with the table container assuming it is mounted synchronously and only once.\n useEffect(\n () => {\n if (tableRole === 'grid') {\n const table = getTable();\n table && model.init(table);\n }\n return () => model.destroy();\n },\n // Assuming getTable is stable.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [model, tableRole]\n );\n\n // Notify the model of the props change.\n useEffect(() => {\n model.update({ pageSize });\n }, [model, pageSize]);\n\n return {};\n}\n\nclass GridNavigationModel {\n // Props\n private _pageSize = 0;\n private _table: null | HTMLTableElement = null;\n\n // State\n private prevFocusedCell: null | FocusedCell = null;\n private focusedCell: null | FocusedCell = null;\n private cleanup = () => {};\n\n public init(table: HTMLTableElement) {\n this._table = table;\n\n this.table.addEventListener('focusin', this.onFocusin);\n this.table.addEventListener('focusout', this.onFocusout);\n this.table.addEventListener('keydown', this.onKeydown);\n\n const tableNodesObserver = new MutationObserver(this.onTableNodeMutation);\n tableNodesObserver.observe(table, { childList: true, subtree: true });\n\n updateTableFocusables(this.table, this.focusedCell ?? this.prevFocusedCell);\n\n this.cleanup = () => {\n this.table.removeEventListener('focusin', this.onFocusin);\n this.table.removeEventListener('focusout', this.onFocusout);\n this.table.removeEventListener('keydown', this.onKeydown);\n\n tableNodesObserver.disconnect();\n\n restoreTableFocusables(this.table);\n };\n }\n\n public destroy() {\n this.cleanup();\n }\n\n public update({ pageSize }: { pageSize: number }) {\n this._pageSize = pageSize;\n }\n\n private get pageSize() {\n return this._pageSize;\n }\n\n private get table(): HTMLTableElement {\n if (!this._table) {\n throw new Error('Invariant violation: GridNavigationModel is used before initialization.');\n }\n return this._table;\n }\n\n private onFocusin = (event: FocusEvent) => {\n const cell = findFocusinCell(event);\n\n if (!cell) {\n return;\n }\n\n if (cell.element !== event.target) {\n cell.element.focus();\n return;\n }\n\n this.prevFocusedCell = cell;\n this.focusedCell = cell;\n\n updateTableFocusables(this.table, cell);\n };\n\n private onFocusout = () => {\n this.focusedCell = null;\n };\n\n private onKeydown = (event: KeyboardEvent) => {\n if (!this.focusedCell) {\n return;\n }\n\n const ctrlKey = event.ctrlKey ? 1 : 0;\n const altKey = event.altKey ? 1 : 0;\n const shiftKey = event.shiftKey ? 1 : 0;\n const metaKey = event.metaKey ? 1 : 0;\n const numModifiersPressed = ctrlKey + altKey + shiftKey + metaKey;\n\n let key = event.keyCode;\n if (numModifiersPressed === 1 && event.ctrlKey) {\n key = -key;\n } else if (numModifiersPressed) {\n return;\n }\n\n const from = this.focusedCell;\n const minExtreme = Number.NEGATIVE_INFINITY;\n const maxExtreme = Number.POSITIVE_INFINITY;\n\n // When focus is inside a dialog do not intercept any keyboard input.\n if (from.dialog) {\n return;\n }\n\n switch (key) {\n case KeyCode.up:\n event.preventDefault();\n return moveFocusBy(this.table, from, { y: -1, x: 0 });\n\n case KeyCode.down:\n event.preventDefault();\n return moveFocusBy(this.table, from, { y: 1, x: 0 });\n\n case KeyCode.left:\n event.preventDefault();\n return moveFocusBy(this.table, from, { y: 0, x: -1 });\n\n case KeyCode.right:\n event.preventDefault();\n return moveFocusBy(this.table, from, { y: 0, x: 1 });\n\n case KeyCode.pageUp:\n event.preventDefault();\n return moveFocusBy(this.table, from, { y: -this.pageSize, x: 0 });\n\n case KeyCode.pageDown:\n event.preventDefault();\n return moveFocusBy(this.table, from, { y: this.pageSize, x: 0 });\n\n case KeyCode.home:\n event.preventDefault();\n return moveFocusBy(this.table, from, { y: 0, x: minExtreme });\n\n case KeyCode.end:\n event.preventDefault();\n return moveFocusBy(this.table, from, { y: 0, x: maxExtreme });\n\n case -KeyCode.home:\n event.preventDefault();\n return moveFocusBy(this.table, from, { y: minExtreme, x: minExtreme });\n\n case -KeyCode.end:\n event.preventDefault();\n return moveFocusBy(this.table, from, { y: maxExtreme, x: maxExtreme });\n\n default:\n return;\n }\n };\n\n private onTableNodeMutation = (mutationRecords: MutationRecord[]) => {\n if (!this.prevFocusedCell) {\n return;\n }\n\n // When focused cell was un-mounted - re-apply focus to the same location.\n for (const record of mutationRecords) {\n if (record.type === 'childList') {\n for (const removedNode of Array.from(record.removedNodes)) {\n if (removedNode === this.prevFocusedCell.element || nodeContains(removedNode, this.prevFocusedCell.element)) {\n updateTableFocusables(this.table, this.focusedCell ?? this.prevFocusedCell);\n moveFocusBy(this.table, this.prevFocusedCell, { y: 0, x: 0 });\n }\n }\n }\n }\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"use-grid-navigation.js","sourceRoot":"lib/default/","sources":["table/table-role/use-grid-navigation.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { useEffect, useMemo } from 'react';\nimport {\n defaultIsSuppressed,\n findFocusinCell,\n moveFocusBy,\n muteElementFocusables,\n restoreElementFocusables,\n ensureSingleFocusable,\n getFirstFocusable,\n} from './utils';\nimport { FocusedCell, GridNavigationProps } from './interfaces';\nimport { KeyCode } from '../../internal/keycode';\nimport { nodeContains } from '@cloudscape-design/component-toolkit/dom';\nimport { useStableCallback } from '@cloudscape-design/component-toolkit/internal';\n\n/**\n * Makes table navigable with keyboard commands.\n * See https://www.w3.org/WAI/ARIA/apg/patterns/grid\n *\n * The hook attaches the GridNavigationHelper helper when active=true.\n * See GridNavigationHelper for more details.\n */\nexport function useGridNavigation({ active, pageSize, getTable, isSuppressed }: GridNavigationProps) {\n const gridNavigation = useMemo(() => new GridNavigationHelper(), []);\n\n const getTableStable = useStableCallback(getTable);\n const isSuppressedStable = useStableCallback((element: HTMLElement) => isSuppressed?.(element) ?? false);\n\n // Initialize the model with the table container assuming it is mounted synchronously and only once.\n useEffect(() => {\n if (active) {\n const table = getTableStable();\n table && gridNavigation.init(table, isSuppressedStable);\n }\n return () => gridNavigation.cleanup();\n }, [active, gridNavigation, getTableStable, isSuppressedStable]);\n\n // Notify the model of the props change.\n useEffect(() => {\n gridNavigation.update({ pageSize });\n }, [gridNavigation, pageSize]);\n}\n\n/**\n * This helper encapsulates the grid navigation behaviors which are:\n * 1. Responding to keyboard commands and moving the focus accordingly;\n * 2. Muting table interactive elements for only one to be user-focusable at a time;\n * 3. Suppressing the above behaviors when focusing an element inside a dialog or when instructed by the isSuppressed callback.\n *\n * All behaviors are attached upon initialization and are re-evaluated with every focusin, focusout, and keydown events,\n * and also when a node removal inside the table is observed to ensure consistency at any given moment.\n *\n * When the navigation is suppressed the keyboard commands are no longer intercepted and all table interactive elements are made\n * user-focusable to unblock the Tab navigation. The suppression should only be used for interactive elements inside the table that would\n * otherwise conflict with the navigation. Once the interactive element is deactivated or lose focus the table navigation becomes active again.\n */\nclass GridNavigationHelper {\n // Props\n private _pageSize = 0;\n private _table: null | HTMLTableElement = null;\n private _isSuppressed: (focusedElement: HTMLElement) => boolean = () => false;\n\n // State\n private prevFocusedCell: null | FocusedCell = null;\n private focusedCell: null | FocusedCell = null;\n\n public init(table: HTMLTableElement, isSuppressed: (focusedElement: HTMLElement) => boolean) {\n this._table = table;\n this._isSuppressed = isSuppressed;\n\n this.table.addEventListener('focusin', this.onFocusin);\n this.table.addEventListener('focusout', this.onFocusout);\n this.table.addEventListener('keydown', this.onKeydown);\n\n const tableNodesObserver = new MutationObserver(this.onTableNodeMutation);\n tableNodesObserver.observe(table, { childList: true, subtree: true });\n\n muteElementFocusables(this.table, false);\n ensureSingleFocusable(this.table, null);\n\n this.cleanup = () => {\n this.table.removeEventListener('focusin', this.onFocusin);\n this.table.removeEventListener('focusout', this.onFocusout);\n this.table.removeEventListener('keydown', this.onKeydown);\n\n tableNodesObserver.disconnect();\n\n restoreElementFocusables(this.table);\n };\n }\n\n public cleanup() {\n // Do nothing before initialized.\n }\n\n public update({ pageSize }: { pageSize: number }) {\n this._pageSize = pageSize;\n }\n\n private get pageSize() {\n return this._pageSize;\n }\n\n private get table(): HTMLTableElement {\n if (!this._table) {\n throw new Error('Invariant violation: GridNavigationHelper is used before initialization.');\n }\n return this._table;\n }\n\n private isSuppressed(focusedElement: HTMLElement): boolean {\n return defaultIsSuppressed(focusedElement) || this._isSuppressed(focusedElement);\n }\n\n private onFocusin = (event: FocusEvent) => {\n const cell = findFocusinCell(event);\n if (!cell) {\n return;\n }\n\n this.prevFocusedCell = cell;\n this.focusedCell = cell;\n\n muteElementFocusables(this.table, this.isSuppressed(cell.element));\n ensureSingleFocusable(this.table, cell);\n\n // Focusing on cell is not eligible when it contains focusable elements in the content.\n // If content focusables are available - move the focus to the first one.\n if (cell.element === cell.cellElement) {\n getFirstFocusable(cell.cellElement)?.focus();\n }\n };\n\n private onFocusout = () => {\n this.focusedCell = null;\n };\n\n private onKeydown = (event: KeyboardEvent) => {\n if (!this.focusedCell) {\n return;\n }\n\n const ctrlKey = event.ctrlKey ? 1 : 0;\n const altKey = event.altKey ? 1 : 0;\n const shiftKey = event.shiftKey ? 1 : 0;\n const metaKey = event.metaKey ? 1 : 0;\n const numModifiersPressed = ctrlKey + altKey + shiftKey + metaKey;\n\n let key = event.keyCode;\n if (numModifiersPressed === 1 && event.ctrlKey) {\n key = -key;\n } else if (numModifiersPressed) {\n return;\n }\n\n const from = this.focusedCell;\n const minExtreme = Number.NEGATIVE_INFINITY;\n const maxExtreme = Number.POSITIVE_INFINITY;\n\n // Do not intercept any keys when the navigation is suppressed.\n if (this.isSuppressed(from.element)) {\n return;\n }\n\n switch (key) {\n case KeyCode.up:\n event.preventDefault();\n return moveFocusBy(this.table, from, { y: -1, x: 0 });\n\n case KeyCode.down:\n event.preventDefault();\n return moveFocusBy(this.table, from, { y: 1, x: 0 });\n\n case KeyCode.left:\n event.preventDefault();\n return moveFocusBy(this.table, from, { y: 0, x: -1 });\n\n case KeyCode.right:\n event.preventDefault();\n return moveFocusBy(this.table, from, { y: 0, x: 1 });\n\n case KeyCode.pageUp:\n event.preventDefault();\n return moveFocusBy(this.table, from, { y: -this.pageSize, x: 0 });\n\n case KeyCode.pageDown:\n event.preventDefault();\n return moveFocusBy(this.table, from, { y: this.pageSize, x: 0 });\n\n case KeyCode.home:\n event.preventDefault();\n return moveFocusBy(this.table, from, { y: 0, x: minExtreme });\n\n case KeyCode.end:\n event.preventDefault();\n return moveFocusBy(this.table, from, { y: 0, x: maxExtreme });\n\n case -KeyCode.home:\n event.preventDefault();\n return moveFocusBy(this.table, from, { y: minExtreme, x: minExtreme });\n\n case -KeyCode.end:\n event.preventDefault();\n return moveFocusBy(this.table, from, { y: maxExtreme, x: maxExtreme });\n\n default:\n return;\n }\n };\n\n private onTableNodeMutation = (mutationRecords: MutationRecord[]) => {\n // When focused cell is un-mounted the focusout event handler removes this.cell,\n // while this.prevFocusedCell is retained until the next focusin event.\n const cell = this.focusedCell ?? this.prevFocusedCell;\n const cellSuppressed = cell ? this.isSuppressed(cell.element) : false;\n\n // Update table elements focus if new nodes were added.\n if (mutationRecords.some(record => record.addedNodes.length > 0)) {\n muteElementFocusables(this.table, cellSuppressed);\n ensureSingleFocusable(this.table, cell);\n }\n\n if (cell) {\n for (const record of mutationRecords) {\n if (record.type === 'childList') {\n // The lost focus in an unmount event is reapplied to the table using the previous cell position.\n // The moveFocusBy takes care of finding the closest position if the previous one no longer exists.\n for (const removedNode of Array.from(record.removedNodes)) {\n if (removedNode === cell.element || nodeContains(removedNode, cell.element)) {\n ensureSingleFocusable(this.table, cell);\n moveFocusBy(this.table, cell, { y: 0, x: 0 });\n }\n }\n }\n }\n }\n };\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { FocusedCell } from './interfaces';
|
|
2
2
|
/**
|
|
3
3
|
* Finds focused cell props corresponding the focused element inside the table.
|
|
4
|
-
* The function relies on ARIA colindex/rowindex attributes being
|
|
4
|
+
* The function relies on ARIA colindex/rowindex attributes being correctly applied.
|
|
5
5
|
*/
|
|
6
6
|
export declare function findFocusinCell(event: FocusEvent): null | FocusedCell;
|
|
7
7
|
/**
|
|
@@ -12,8 +12,26 @@ export declare function moveFocusBy(table: HTMLTableElement, from: FocusedCell,
|
|
|
12
12
|
x: number;
|
|
13
13
|
}): void;
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
15
|
+
* Makes the cell element, the first interactive element or the first cell of the table user-focusable.
|
|
16
16
|
*/
|
|
17
|
-
export declare function
|
|
18
|
-
|
|
17
|
+
export declare function ensureSingleFocusable(table: HTMLElement, cell: null | FocusedCell): void;
|
|
18
|
+
/**
|
|
19
|
+
* Makes all element focusable children pseudo-focusable unless the grid navigation is suppressed.
|
|
20
|
+
*/
|
|
21
|
+
export declare function muteElementFocusables(element: HTMLElement, suppressed: boolean): void;
|
|
22
|
+
/**
|
|
23
|
+
* This cleanup code ensures all cells are no longer focusable but the interactive elements are.
|
|
24
|
+
* Currently there are no use cases for it as we don't expect the navigation to be used conditionally.
|
|
25
|
+
*/
|
|
26
|
+
export declare function restoreElementFocusables(element: HTMLTableElement): void;
|
|
27
|
+
/**
|
|
28
|
+
* Returns true if the target element or one of its parents is a dialog or is marked with data-awsui-table-suppress-navigation attribute.
|
|
29
|
+
* This is used to suppress navigation for interactive content without a need to use a custom suppression check.
|
|
30
|
+
*/
|
|
31
|
+
export declare function defaultIsSuppressed(target: HTMLElement): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Returns actually focusable or pseudo-focusable elements to find navigation targets.
|
|
34
|
+
*/
|
|
35
|
+
export declare function getFocusables(element: HTMLElement): HTMLElement[];
|
|
36
|
+
export declare function getFirstFocusable(element: HTMLElement): HTMLElement | null;
|
|
19
37
|
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"lib/default/","sources":["table/table-role/utils.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"lib/default/","sources":["table/table-role/utils.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAO3C;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,GAAG,WAAW,CAuBrE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,QA4BtG;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,GAAG,WAAW,QAejF;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,QAwB9E;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,gBAAgB,QAQjE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,WAAW,WAiBtD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,iBAEjD;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,WAAW,sBAErD"}
|