@cloudscape-design/board-components 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Config +23 -0
- package/LICENSE +201 -0
- package/NOTICE +2 -0
- package/README-cloudscape.md +20 -0
- package/README-open-source.md +0 -0
- package/README.md +20 -0
- package/board/index.d.ts +4 -0
- package/board/index.js +11 -0
- package/board/interfaces.d.ts +167 -0
- package/board/interfaces.js +1 -0
- package/board/internal.d.ts +4 -0
- package/board/internal.js +199 -0
- package/board/placeholder.d.ts +10 -0
- package/board/placeholder.js +24 -0
- package/board/styles.css.js +10 -0
- package/board/styles.scoped.css +23 -0
- package/board/styles.selectors.js +11 -0
- package/board/transition.d.ts +50 -0
- package/board/transition.js +211 -0
- package/board/utils/announcements.d.ts +10 -0
- package/board/utils/announcements.js +98 -0
- package/board/utils/create-transforms.d.ts +7 -0
- package/board/utils/create-transforms.js +22 -0
- package/board/utils/events.d.ts +3 -0
- package/board/utils/events.js +14 -0
- package/board/utils/get-hovered-rect.d.ts +10 -0
- package/board/utils/get-hovered-rect.js +19 -0
- package/board/utils/layout.d.ts +19 -0
- package/board/utils/layout.js +77 -0
- package/board/utils/path.d.ts +10 -0
- package/board/utils/path.js +73 -0
- package/board-item/header.d.ts +7 -0
- package/board-item/header.js +8 -0
- package/board-item/index.d.ts +4 -0
- package/board-item/index.js +11 -0
- package/board-item/interfaces.d.ts +42 -0
- package/board-item/interfaces.js +1 -0
- package/board-item/internal.d.ts +4 -0
- package/board-item/internal.js +20 -0
- package/board-item/styles.css.js +15 -0
- package/board-item/styles.scoped.css +41 -0
- package/board-item/styles.selectors.js +16 -0
- package/index.d.ts +6 -0
- package/index.js +5 -0
- package/internal/api-docs/components/board-item.js +68 -0
- package/internal/api-docs/components/board.js +117 -0
- package/internal/api-docs/components/index.js +5 -0
- package/internal/api-docs/components/items-palette.js +58 -0
- package/internal/api-docs/test-utils-doc/dom.js +4 -0
- package/internal/api-docs/test-utils-doc/selectors.js +4 -0
- package/internal/base-component/use-base-component.d.ts +12 -0
- package/internal/base-component/use-base-component.js +16 -0
- package/internal/base-component/use-telemetry.d.ts +1 -0
- package/internal/base-component/use-telemetry.js +9 -0
- package/internal/base-component/use-visual-refresh.d.ts +1 -0
- package/internal/base-component/use-visual-refresh.js +24 -0
- package/internal/breakpoints.d.ts +2 -0
- package/internal/breakpoints.js +18 -0
- package/internal/constants.d.ts +3 -0
- package/internal/constants.js +5 -0
- package/internal/debug-tools/converters.d.ts +4 -0
- package/internal/debug-tools/converters.js +21 -0
- package/internal/debug-tools/generators.d.ts +25 -0
- package/internal/debug-tools/generators.js +258 -0
- package/internal/debug-tools/index.d.ts +8 -0
- package/internal/debug-tools/index.js +10 -0
- package/internal/debug-tools/interfaces.d.ts +2 -0
- package/internal/debug-tools/interfaces.js +3 -0
- package/internal/debug-tools/parsers.d.ts +8 -0
- package/internal/debug-tools/parsers.js +66 -0
- package/internal/dnd-controller/__mocks__/controller.d.ts +13 -0
- package/internal/dnd-controller/__mocks__/controller.js +33 -0
- package/internal/dnd-controller/collision.d.ts +17 -0
- package/internal/dnd-controller/collision.js +32 -0
- package/internal/dnd-controller/controller.d.ts +64 -0
- package/internal/dnd-controller/controller.js +131 -0
- package/internal/dnd-controller/event-emitter.d.ts +9 -0
- package/internal/dnd-controller/event-emitter.js +22 -0
- package/internal/drag-handle/icon.d.ts +4 -0
- package/internal/drag-handle/icon.js +12 -0
- package/internal/drag-handle/index.d.ts +9 -0
- package/internal/drag-handle/index.js +11 -0
- package/internal/drag-handle/styles.css.js +6 -0
- package/internal/drag-handle/styles.scoped.css +7 -0
- package/internal/drag-handle/styles.selectors.js +7 -0
- package/internal/environment.d.ts +4 -0
- package/internal/environment.js +4 -0
- package/internal/generated/styles/tokens.d.ts +0 -0
- package/internal/generated/styles/tokens.js +0 -0
- package/internal/grid/grid.d.ts +3 -0
- package/internal/grid/grid.js +28 -0
- package/internal/grid/index.d.ts +2 -0
- package/internal/grid/index.js +3 -0
- package/internal/grid/interfaces.d.ts +14 -0
- package/internal/grid/interfaces.js +3 -0
- package/internal/grid/item.d.ts +8 -0
- package/internal/grid/item.js +10 -0
- package/internal/grid/styles.css.js +7 -0
- package/internal/grid/styles.scoped.css +221 -0
- package/internal/grid/styles.selectors.js +8 -0
- package/internal/handle/index.d.ts +3 -0
- package/internal/handle/index.js +17 -0
- package/internal/handle/styles.css.js +6 -0
- package/internal/handle/styles.scoped.css +32 -0
- package/internal/handle/styles.selectors.js +7 -0
- package/internal/interfaces.d.ts +50 -0
- package/internal/interfaces.js +3 -0
- package/internal/is-development.d.ts +6 -0
- package/internal/is-development.js +8 -0
- package/internal/item-container/get-next-droppable.d.ts +7 -0
- package/internal/item-container/get-next-droppable.js +15 -0
- package/internal/item-container/index.d.ts +48 -0
- package/internal/item-container/index.js +262 -0
- package/internal/item-container/styles.css.js +12 -0
- package/internal/item-container/styles.scoped.css +33 -0
- package/internal/item-container/styles.selectors.js +13 -0
- package/internal/layout-engine/engine-conflicts.d.ts +4 -0
- package/internal/layout-engine/engine-conflicts.js +53 -0
- package/internal/layout-engine/engine-step.d.ts +5 -0
- package/internal/layout-engine/engine-step.js +307 -0
- package/internal/layout-engine/engine.d.ts +19 -0
- package/internal/layout-engine/engine.js +105 -0
- package/internal/layout-engine/grid.d.ts +28 -0
- package/internal/layout-engine/grid.js +140 -0
- package/internal/layout-engine/interfaces.d.ts +30 -0
- package/internal/layout-engine/interfaces.js +3 -0
- package/internal/layout-engine/utils.d.ts +12 -0
- package/internal/layout-engine/utils.js +79 -0
- package/internal/live-region/index.d.ts +44 -0
- package/internal/live-region/index.js +85 -0
- package/internal/logging.d.ts +1 -0
- package/internal/logging.js +10 -0
- package/internal/manifest.json +3 -0
- package/internal/resize-handle/icon.d.ts +4 -0
- package/internal/resize-handle/icon.js +12 -0
- package/internal/resize-handle/index.d.ts +8 -0
- package/internal/resize-handle/index.js +7 -0
- package/internal/resize-handle/styles.css.js +6 -0
- package/internal/resize-handle/styles.scoped.css +3 -0
- package/internal/resize-handle/styles.selectors.js +7 -0
- package/internal/screenreader-grid-navigation/index.d.ts +22 -0
- package/internal/screenreader-grid-navigation/index.js +42 -0
- package/internal/screenreader-grid-navigation/styles.css.js +7 -0
- package/internal/screenreader-grid-navigation/styles.scoped.css +12 -0
- package/internal/screenreader-grid-navigation/styles.selectors.js +8 -0
- package/internal/screenreader-only/index.d.ts +21 -0
- package/internal/screenreader-only/index.js +23 -0
- package/internal/screenreader-only/styles.css.js +6 -0
- package/internal/screenreader-only/styles.scoped.css +9 -0
- package/internal/screenreader-only/styles.selectors.js +7 -0
- package/internal/utils/apply-display-name.d.ts +1 -0
- package/internal/utils/apply-display-name.js +5 -0
- package/internal/utils/coordinates.d.ts +14 -0
- package/internal/utils/coordinates.js +20 -0
- package/internal/utils/events.d.ts +2 -0
- package/internal/utils/events.js +18 -0
- package/internal/utils/layout.d.ts +18 -0
- package/internal/utils/layout.js +132 -0
- package/internal/utils/position.d.ts +9 -0
- package/internal/utils/position.js +9 -0
- package/internal/utils/rects.d.ts +6 -0
- package/internal/utils/rects.js +76 -0
- package/internal/utils/screen.d.ts +1 -0
- package/internal/utils/screen.js +17 -0
- package/internal/utils/stack-set.d.ts +8 -0
- package/internal/utils/stack-set.js +23 -0
- package/internal/utils/throttle.d.ts +5 -0
- package/internal/utils/throttle.js +51 -0
- package/internal/utils/use-auto-scroll.d.ts +5 -0
- package/internal/utils/use-auto-scroll.js +62 -0
- package/internal/utils/use-last-interaction.d.ts +1 -0
- package/internal/utils/use-last-interaction.js +22 -0
- package/internal/utils/use-merge-refs.d.ts +9 -0
- package/internal/utils/use-merge-refs.js +29 -0
- package/internal/utils/use-stable-event-handler.d.ts +9 -0
- package/internal/utils/use-stable-event-handler.js +19 -0
- package/internal/utils/use-throttled-event-handler.d.ts +1 -0
- package/internal/utils/use-throttled-event-handler.js +11 -0
- package/internal/utils/zip-arrays.d.ts +1 -0
- package/internal/utils/zip-arrays.js +8 -0
- package/items-palette/index.d.ts +4 -0
- package/items-palette/index.js +11 -0
- package/items-palette/interfaces.d.ts +49 -0
- package/items-palette/interfaces.js +3 -0
- package/items-palette/internal.d.ts +4 -0
- package/items-palette/internal.js +73 -0
- package/items-palette/styles.css.js +6 -0
- package/items-palette/styles.scoped.css +3 -0
- package/items-palette/styles.selectors.js +7 -0
- package/package.json +43 -0
- package/test-utils/dom/board/index.d.ts +6 -0
- package/test-utils/dom/board/index.js +15 -0
- package/test-utils/dom/board/index.js.map +1 -0
- package/test-utils/dom/board-item/index.d.ts +10 -0
- package/test-utils/dom/board-item/index.js +33 -0
- package/test-utils/dom/board-item/index.js.map +1 -0
- package/test-utils/dom/index.d.ts +19 -0
- package/test-utils/dom/index.js +41 -0
- package/test-utils/dom/index.js.map +1 -0
- package/test-utils/dom/items-palette/index.d.ts +7 -0
- package/test-utils/dom/items-palette/index.js +18 -0
- package/test-utils/dom/items-palette/index.js.map +1 -0
- package/test-utils/dom/palette-item/index.d.ts +5 -0
- package/test-utils/dom/palette-item/index.js +15 -0
- package/test-utils/dom/palette-item/index.js.map +1 -0
- package/test-utils/selectors/board/index.d.ts +6 -0
- package/test-utils/selectors/board/index.js +15 -0
- package/test-utils/selectors/board/index.js.map +1 -0
- package/test-utils/selectors/board-item/index.d.ts +10 -0
- package/test-utils/selectors/board-item/index.js +33 -0
- package/test-utils/selectors/board-item/index.js.map +1 -0
- package/test-utils/selectors/index.d.ts +19 -0
- package/test-utils/selectors/index.js +41 -0
- package/test-utils/selectors/index.js.map +1 -0
- package/test-utils/selectors/items-palette/index.d.ts +7 -0
- package/test-utils/selectors/items-palette/index.js +18 -0
- package/test-utils/selectors/items-palette/index.js.map +1 -0
- package/test-utils/selectors/palette-item/index.d.ts +5 -0
- package/test-utils/selectors/palette-item/index.js +15 -0
- package/test-utils/selectors/palette-item/index.js.map +1 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { Position } from "../utils/position";
|
|
4
|
+
export function sortGridItems(items) {
|
|
5
|
+
return [...items].sort((a, b) => (b.y - a.y === 0 ? b.x - a.x : b.y - a.y));
|
|
6
|
+
}
|
|
7
|
+
export function getItemRect(item) {
|
|
8
|
+
return {
|
|
9
|
+
left: item.x,
|
|
10
|
+
right: item.x + item.width - 1,
|
|
11
|
+
top: item.y,
|
|
12
|
+
bottom: item.y + item.height - 1,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export function normalizeMovePath(origin, path) {
|
|
16
|
+
path = normalizePathOrigin(origin, path);
|
|
17
|
+
// Store last visited indexes per position.
|
|
18
|
+
const positionToLastIndex = new Map();
|
|
19
|
+
for (let index = 0; index < path.length; index++) {
|
|
20
|
+
positionToLastIndex.set(`${path[index].x}:${path[index].y}`, index);
|
|
21
|
+
}
|
|
22
|
+
// Compose path from last visited indices only.
|
|
23
|
+
const normalizedPath = [];
|
|
24
|
+
let index = 0;
|
|
25
|
+
while (index < path.length) {
|
|
26
|
+
const lastVisitedIndex = positionToLastIndex.get(`${path[index].x}:${path[index].y}`);
|
|
27
|
+
normalizedPath.push(path[lastVisitedIndex]);
|
|
28
|
+
index = lastVisitedIndex + 1;
|
|
29
|
+
}
|
|
30
|
+
return normalizePathSteps(origin, normalizedPath);
|
|
31
|
+
}
|
|
32
|
+
export function normalizeResizePath(origin, path) {
|
|
33
|
+
path = normalizePathOrigin(origin, path);
|
|
34
|
+
if (path.length === 0) {
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
const normalizedPath = [path[path.length - 1]];
|
|
38
|
+
for (let stepIndex = path.length - 2; stepIndex >= 0; stepIndex--) {
|
|
39
|
+
const prev = normalizedPath[normalizedPath.length - 1];
|
|
40
|
+
const current = path[stepIndex];
|
|
41
|
+
if (current.x < prev.x || current.y < prev.y) {
|
|
42
|
+
normalizedPath.push(current);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
normalizedPath.reverse();
|
|
46
|
+
return normalizePathSteps(origin, normalizedPath);
|
|
47
|
+
}
|
|
48
|
+
// Removes path prefixes that return to the original location.
|
|
49
|
+
function normalizePathOrigin(origin, path) {
|
|
50
|
+
let lastOriginIndex = -1;
|
|
51
|
+
for (let i = 0; i < path.length; i++) {
|
|
52
|
+
if (path[i].x === origin.x && path[i].y === origin.y) {
|
|
53
|
+
lastOriginIndex = i;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return path.slice(lastOriginIndex + 1);
|
|
57
|
+
}
|
|
58
|
+
// Ensures path only includes single-length steps.
|
|
59
|
+
function normalizePathSteps(origin, path) {
|
|
60
|
+
const normalizedPath = [];
|
|
61
|
+
let prevX = origin.x;
|
|
62
|
+
let prevY = origin.y;
|
|
63
|
+
for (const step of path) {
|
|
64
|
+
const vx = Math.sign(step.x - prevX);
|
|
65
|
+
const vy = Math.sign(step.y - prevY);
|
|
66
|
+
for (let x = prevX, y = prevY; x !== step.x || y !== step.y;) {
|
|
67
|
+
if (x !== step.x) {
|
|
68
|
+
x += vx;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
y += vy;
|
|
72
|
+
}
|
|
73
|
+
normalizedPath.push(new Position({ x, y }));
|
|
74
|
+
}
|
|
75
|
+
prevX = step.x;
|
|
76
|
+
prevY = step.y;
|
|
77
|
+
}
|
|
78
|
+
return normalizedPath;
|
|
79
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { ScreenreaderOnlyProps } from "../screenreader-only";
|
|
3
|
+
export interface LiveRegionProps extends ScreenreaderOnlyProps {
|
|
4
|
+
assertive?: boolean;
|
|
5
|
+
delay?: number;
|
|
6
|
+
visible?: boolean;
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* The live region is hidden in the layout, but visible for screen readers.
|
|
11
|
+
* It's purpose it to announce changes e.g. when custom navigation logic is used.
|
|
12
|
+
*
|
|
13
|
+
* The way live region works differently in different browsers and screen readers and
|
|
14
|
+
* it is recommended to manually test every new implementation.
|
|
15
|
+
*
|
|
16
|
+
* If you notice there are different words being merged together,
|
|
17
|
+
* check if there are text nodes not being wrapped in elements, like:
|
|
18
|
+
* <LiveRegion>
|
|
19
|
+
* {title}
|
|
20
|
+
* <span><Details /></span>
|
|
21
|
+
* </LiveRegion>
|
|
22
|
+
*
|
|
23
|
+
* To fix, wrap "title" in an element:
|
|
24
|
+
* <LiveRegion>
|
|
25
|
+
* <span>{title}</span>
|
|
26
|
+
* <span><Details /></span>
|
|
27
|
+
* </LiveRegion>
|
|
28
|
+
*
|
|
29
|
+
* Or create a single text node if possible:
|
|
30
|
+
* <LiveRegion>
|
|
31
|
+
* {`${title} ${details}`}
|
|
32
|
+
* </LiveRegion>
|
|
33
|
+
*
|
|
34
|
+
* The live region is always atomic, because non-atomic regions can be treated by screen readers
|
|
35
|
+
* differently and produce unexpected results. To imitate non-atomic announcements simply use
|
|
36
|
+
* multiple live regions:
|
|
37
|
+
* <>
|
|
38
|
+
* <LiveRegion>{title}</LiveRegion>
|
|
39
|
+
* <LiveRegion><Details /></LiveRegion>
|
|
40
|
+
* </>
|
|
41
|
+
*/
|
|
42
|
+
declare const _default: import("react").MemoExoticComponent<typeof LiveRegion>;
|
|
43
|
+
export default _default;
|
|
44
|
+
declare function LiveRegion({ assertive, delay, visible, children, ...restProps }: LiveRegionProps): JSX.Element;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
import { memo, useEffect, useRef } from "react";
|
|
5
|
+
import ScreenreaderOnly from "../screenreader-only";
|
|
6
|
+
/**
|
|
7
|
+
* The live region is hidden in the layout, but visible for screen readers.
|
|
8
|
+
* It's purpose it to announce changes e.g. when custom navigation logic is used.
|
|
9
|
+
*
|
|
10
|
+
* The way live region works differently in different browsers and screen readers and
|
|
11
|
+
* it is recommended to manually test every new implementation.
|
|
12
|
+
*
|
|
13
|
+
* If you notice there are different words being merged together,
|
|
14
|
+
* check if there are text nodes not being wrapped in elements, like:
|
|
15
|
+
* <LiveRegion>
|
|
16
|
+
* {title}
|
|
17
|
+
* <span><Details /></span>
|
|
18
|
+
* </LiveRegion>
|
|
19
|
+
*
|
|
20
|
+
* To fix, wrap "title" in an element:
|
|
21
|
+
* <LiveRegion>
|
|
22
|
+
* <span>{title}</span>
|
|
23
|
+
* <span><Details /></span>
|
|
24
|
+
* </LiveRegion>
|
|
25
|
+
*
|
|
26
|
+
* Or create a single text node if possible:
|
|
27
|
+
* <LiveRegion>
|
|
28
|
+
* {`${title} ${details}`}
|
|
29
|
+
* </LiveRegion>
|
|
30
|
+
*
|
|
31
|
+
* The live region is always atomic, because non-atomic regions can be treated by screen readers
|
|
32
|
+
* differently and produce unexpected results. To imitate non-atomic announcements simply use
|
|
33
|
+
* multiple live regions:
|
|
34
|
+
* <>
|
|
35
|
+
* <LiveRegion>{title}</LiveRegion>
|
|
36
|
+
* <LiveRegion><Details /></LiveRegion>
|
|
37
|
+
* </>
|
|
38
|
+
*/
|
|
39
|
+
export default memo(LiveRegion);
|
|
40
|
+
function LiveRegion({ assertive = false, delay = 10, visible = false, children, ...restProps }) {
|
|
41
|
+
const sourceRef = useRef(null);
|
|
42
|
+
const targetRef = useRef(null);
|
|
43
|
+
/*
|
|
44
|
+
When React state changes, React often produces too many DOM updates, causing NVDA to
|
|
45
|
+
issue many announcements for the same logical event (See https://github.com/nvaccess/nvda/issues/7996).
|
|
46
|
+
The code below imitates a debouncing, scheduling a callback every time new React state
|
|
47
|
+
update is detected. When a callback resolves, it copies content from a muted element
|
|
48
|
+
to the live region, which is recognized by screen readers as an update.
|
|
49
|
+
If the use case requires no announcement to be ignored, use delay = 0, but ensure it
|
|
50
|
+
does not impact the performance. If it does, prefer using a string as children prop.
|
|
51
|
+
*/
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
function updateLiveRegion() {
|
|
54
|
+
if (targetRef.current && sourceRef.current) {
|
|
55
|
+
const sourceContent = extractInnerText(sourceRef.current);
|
|
56
|
+
const targetContent = extractInnerText(targetRef.current);
|
|
57
|
+
if (targetContent !== sourceContent) {
|
|
58
|
+
// The aria-atomic does not work properly in Voice Over, causing
|
|
59
|
+
// certain parts of the content to be ignored. To fix that,
|
|
60
|
+
// we assign the source text content as a single node.
|
|
61
|
+
targetRef.current.innerText = sourceContent;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
let timeoutId;
|
|
66
|
+
if (delay) {
|
|
67
|
+
timeoutId = setTimeout(updateLiveRegion, delay);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
updateLiveRegion();
|
|
71
|
+
}
|
|
72
|
+
return () => {
|
|
73
|
+
if (timeoutId) {
|
|
74
|
+
clearTimeout(timeoutId);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
});
|
|
78
|
+
return (_jsxs(_Fragment, { children: [visible && _jsx("span", { ref: sourceRef, children: children }), _jsxs(ScreenreaderOnly, { ...restProps, className: restProps.className, children: [!visible && (_jsx("span", { ref: sourceRef, "aria-hidden": "true", children: children })), _jsx("span", { ref: targetRef, "aria-atomic": "true", "aria-live": assertive ? "assertive" : "polite" })] })] }));
|
|
79
|
+
}
|
|
80
|
+
// This only extracts text content from the node including all its children which is enough for now.
|
|
81
|
+
// To make it more powerful, it is possible to create a more sophisticated extractor with respect to
|
|
82
|
+
// ARIA properties to ignore aria-hidden nodes and read ARIA labels from the live content.
|
|
83
|
+
function extractInnerText(node) {
|
|
84
|
+
return (node.innerText || "").replace(/\s+/g, " ").trim();
|
|
85
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function warnOnce(component: string, message: string): void;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
const messageCache = {};
|
|
4
|
+
export function warnOnce(component, message) {
|
|
5
|
+
const warning = `[${component}] ${message}`;
|
|
6
|
+
if (!messageCache[warning]) {
|
|
7
|
+
messageCache[warning] = true;
|
|
8
|
+
console.warn(warning);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
import Icon from "@cloudscape-design/components/icon";
|
|
5
|
+
import { memo } from "react";
|
|
6
|
+
export function ResizeHandleIcon() {
|
|
7
|
+
return _jsx(Icon, { svg: _jsx(SVG, {}) });
|
|
8
|
+
}
|
|
9
|
+
function SVG() {
|
|
10
|
+
return (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 16 16", children: [_jsx("line", { x1: "9.94", y1: "14.95", x2: "14.98", y2: "9.57" }), _jsx("line", { x1: "5.75", y1: "14.95", x2: "14.98", y2: "5.35" }), _jsx("line", { x1: "0.98", y1: "14.95", x2: "14.98", y2: "0.95" })] }));
|
|
11
|
+
}
|
|
12
|
+
export default memo(ResizeHandleIcon);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { KeyboardEvent, PointerEvent } from "react";
|
|
2
|
+
export interface ResizeHandleProps {
|
|
3
|
+
ariaLabelledBy: string;
|
|
4
|
+
ariaDescribedBy: string;
|
|
5
|
+
onPointerDown: (event: PointerEvent) => void;
|
|
6
|
+
onKeyDown: (event: KeyboardEvent) => void;
|
|
7
|
+
}
|
|
8
|
+
export default function ResizeHandle({ ariaLabelledBy, ariaDescribedBy, onPointerDown, onKeyDown }: ResizeHandleProps): JSX.Element;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import Handle from "../handle";
|
|
3
|
+
import { ResizeHandleIcon } from "./icon";
|
|
4
|
+
import styles from "./styles.css.js";
|
|
5
|
+
export default function ResizeHandle({ ariaLabelledBy, ariaDescribedBy, onPointerDown, onKeyDown }) {
|
|
6
|
+
return (_jsx(Handle, { className: styles.handle, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, onPointerDown: onPointerDown, onKeyDown: onKeyDown, children: _jsx(ResizeHandleIcon, {}) }));
|
|
7
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { GridLayout, ItemId } from "../interfaces";
|
|
3
|
+
export interface ScreenReaderGridNavigationProps<Item> {
|
|
4
|
+
items: readonly Item[];
|
|
5
|
+
itemsLayout: GridLayout;
|
|
6
|
+
ariaLabel: string;
|
|
7
|
+
ariaDescription?: string;
|
|
8
|
+
itemAriaLabel: (item: null | Item) => string;
|
|
9
|
+
onActivateItem: (itemId: ItemId) => void;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* The component provides a native screen-reader grid navigation for board items.
|
|
13
|
+
* A separate navigation component is used because the navigation requires a table or table-like
|
|
14
|
+
* DOM structure while the board uses CSS grid.
|
|
15
|
+
*
|
|
16
|
+
* The screen-reader navigation component is hidden and don't have a tab stop, however, it can be focused
|
|
17
|
+
* programmatically or with a screen-reader. When focused with a screen-reader the component becomes visible
|
|
18
|
+
* so that it can be clicked (e.g. the VO can imitate clicks on the elements under VO cursor with VO+Space).
|
|
19
|
+
*/
|
|
20
|
+
export declare function ScreenReaderGridNavigation<Item extends {
|
|
21
|
+
id: string;
|
|
22
|
+
}>({ items, itemsLayout, ariaLabel, ariaDescription, itemAriaLabel, onActivateItem, }: ScreenReaderGridNavigationProps<Item>): JSX.Element;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
import { useId, useMemo, useState } from "react";
|
|
5
|
+
import ScreenreaderOnly from "../screenreader-only";
|
|
6
|
+
import styles from "./styles.css.js";
|
|
7
|
+
/**
|
|
8
|
+
* The component provides a native screen-reader grid navigation for board items.
|
|
9
|
+
* A separate navigation component is used because the navigation requires a table or table-like
|
|
10
|
+
* DOM structure while the board uses CSS grid.
|
|
11
|
+
*
|
|
12
|
+
* The screen-reader navigation component is hidden and don't have a tab stop, however, it can be focused
|
|
13
|
+
* programmatically or with a screen-reader. When focused with a screen-reader the component becomes visible
|
|
14
|
+
* so that it can be clicked (e.g. the VO can imitate clicks on the elements under VO cursor with VO+Space).
|
|
15
|
+
*/
|
|
16
|
+
export function ScreenReaderGridNavigation({ items, itemsLayout, ariaLabel, ariaDescription, itemAriaLabel, onActivateItem, }) {
|
|
17
|
+
const [isNavigationFocused, setIsNavigationFocused] = useState(false);
|
|
18
|
+
const className = isNavigationFocused
|
|
19
|
+
? styles["screen-reader-navigation-visible"]
|
|
20
|
+
: styles["screen-reader-navigation-hidden"];
|
|
21
|
+
const tableId = useId();
|
|
22
|
+
const navigationDescriptionId = useId();
|
|
23
|
+
const getItem = useMemo(() => {
|
|
24
|
+
const itemById = new Map(items.map((it) => [it.id, it]));
|
|
25
|
+
return (id) => { var _a; return (id ? (_a = itemById.get(id)) !== null && _a !== void 0 ? _a : null : null); };
|
|
26
|
+
}, [items]);
|
|
27
|
+
const layout = [];
|
|
28
|
+
function makeNewRow() {
|
|
29
|
+
layout.push([...Array(itemsLayout.columns)].map(() => null));
|
|
30
|
+
}
|
|
31
|
+
for (const item of itemsLayout.items) {
|
|
32
|
+
for (let y = item.y; y < item.y + item.height; y++) {
|
|
33
|
+
while (layout.length <= y) {
|
|
34
|
+
makeNewRow();
|
|
35
|
+
}
|
|
36
|
+
for (let x = item.x; x < item.x + item.width; x++) {
|
|
37
|
+
layout[y][x] = item.id;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return (_jsxs("div", { role: "navigation", "aria-labelledby": tableId, "aria-describedby": ariaDescription ? navigationDescriptionId : undefined, className: className, children: [_jsx("table", { id: tableId, role: "grid", "aria-label": ariaLabel, "aria-describedby": ariaDescription ? navigationDescriptionId : undefined, children: _jsx("tbody", { children: layout.map((row, rowIndex) => (_jsx("tr", { role: "row", children: row.map((itemId, cellIndex) => (_jsx("td", { role: "gridcell", children: itemId ? (_jsx("button", { tabIndex: -1, onClick: () => itemId && onActivateItem(itemId), onFocus: () => setIsNavigationFocused(true), onBlur: () => setIsNavigationFocused(false), children: itemAriaLabel(getItem(itemId)) })) : (itemAriaLabel(getItem(itemId))) }, cellIndex))) }, rowIndex))) }) }), ariaDescription && _jsx(ScreenreaderOnly, { id: navigationDescriptionId, children: ariaDescription })] }));
|
|
42
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
.awsui_screen-reader-navigation-hidden_1wuib_pl8f7_1:not(#\9) {
|
|
2
|
+
position: absolute !important;
|
|
3
|
+
clip-path: circle(0);
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.awsui_screen-reader-navigation-visible_1wuib_pl8f7_6:not(#\9) {
|
|
7
|
+
position: fixed;
|
|
8
|
+
background: white;
|
|
9
|
+
padding: 8px;
|
|
10
|
+
border: 1px solid black;
|
|
11
|
+
z-index: 10001;
|
|
12
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
|
|
2
|
+
// es-module interop with Babel and Typescript
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
module.exports.default = {
|
|
5
|
+
"screen-reader-navigation-hidden": "awsui_screen-reader-navigation-hidden_1wuib_pl8f7_1",
|
|
6
|
+
"screen-reader-navigation-visible": "awsui_screen-reader-navigation-visible_1wuib_pl8f7_6"
|
|
7
|
+
};
|
|
8
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
export interface ScreenreaderOnlyProps {
|
|
3
|
+
id?: string;
|
|
4
|
+
className?: string;
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Makes content now shown on a screen but still announced by screen-reader users.
|
|
9
|
+
* The component is suitable when the aria-label cannot be used, e.g. to avoid elements being announced as "blank".
|
|
10
|
+
*
|
|
11
|
+
* To exclude screenreader-only content use `:not(.${screenreaderOnlyStyles.root})` selector, for example:
|
|
12
|
+
*
|
|
13
|
+
* ```
|
|
14
|
+
* import screenreaderOnlyStyles from '~internal/components/screenreader-only/styles.css.js'
|
|
15
|
+
*
|
|
16
|
+
* let visibleContent = wrapper.find(`${styles.label}`).find(`:not(.${screenreaderOnlyStyles.root})`).getElement().textContent
|
|
17
|
+
*
|
|
18
|
+
* let screenreaderContent = wrapper.find(`${styles.label}`).find(`.${screenreaderOnlyStyles.root}`).getElement().textContent
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export default function ScreenreaderOnly(props: ScreenreaderOnlyProps): JSX.Element;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
// The code is copied from https://github.com/cloudscape-design/components/blob/main/src/internal/components/screenreader-only/index.tsx
|
|
5
|
+
import clsx from "clsx";
|
|
6
|
+
import styles from "./styles.css.js";
|
|
7
|
+
/**
|
|
8
|
+
* Makes content now shown on a screen but still announced by screen-reader users.
|
|
9
|
+
* The component is suitable when the aria-label cannot be used, e.g. to avoid elements being announced as "blank".
|
|
10
|
+
*
|
|
11
|
+
* To exclude screenreader-only content use `:not(.${screenreaderOnlyStyles.root})` selector, for example:
|
|
12
|
+
*
|
|
13
|
+
* ```
|
|
14
|
+
* import screenreaderOnlyStyles from '~internal/components/screenreader-only/styles.css.js'
|
|
15
|
+
*
|
|
16
|
+
* let visibleContent = wrapper.find(`${styles.label}`).find(`:not(.${screenreaderOnlyStyles.root})`).getElement().textContent
|
|
17
|
+
*
|
|
18
|
+
* let screenreaderContent = wrapper.find(`${styles.label}`).find(`.${screenreaderOnlyStyles.root}`).getElement().textContent
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export default function ScreenreaderOnly(props) {
|
|
22
|
+
return _jsx("span", { ...props, className: clsx(styles.root, props.className) });
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function applyDisplayName<T>(component: T, displayName: string): void;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { PointerEvent as ReactPointerEvent } from "react";
|
|
2
|
+
export declare class Coordinates {
|
|
3
|
+
readonly __type = "Coordinates";
|
|
4
|
+
readonly x: number;
|
|
5
|
+
readonly y: number;
|
|
6
|
+
readonly scrollX: number;
|
|
7
|
+
readonly scrollY: number;
|
|
8
|
+
static fromEvent(event: PointerEvent | ReactPointerEvent<unknown>): Coordinates;
|
|
9
|
+
static cursorOffset(current: Coordinates, start: Coordinates): Coordinates;
|
|
10
|
+
constructor({ x, y }: {
|
|
11
|
+
x: number;
|
|
12
|
+
y: number;
|
|
13
|
+
});
|
|
14
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
export class Coordinates {
|
|
4
|
+
static fromEvent(event) {
|
|
5
|
+
return new Coordinates({ x: event.clientX, y: event.clientY });
|
|
6
|
+
}
|
|
7
|
+
static cursorOffset(current, start) {
|
|
8
|
+
return new Coordinates({
|
|
9
|
+
x: current.x - start.x + (current.scrollX - start.scrollX),
|
|
10
|
+
y: current.y - start.y + (current.scrollY - start.scrollY),
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
constructor({ x, y }) {
|
|
14
|
+
this.__type = "Coordinates";
|
|
15
|
+
this.scrollX = window.scrollX;
|
|
16
|
+
this.scrollY = window.scrollY;
|
|
17
|
+
this.x = x;
|
|
18
|
+
this.y = y;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
class CustomEventStub {
|
|
4
|
+
constructor(detail = null) {
|
|
5
|
+
this.detail = detail;
|
|
6
|
+
this.defaultPrevented = false;
|
|
7
|
+
this.cancelBubble = false;
|
|
8
|
+
}
|
|
9
|
+
preventDefault() {
|
|
10
|
+
// noop
|
|
11
|
+
}
|
|
12
|
+
stopPropagation() {
|
|
13
|
+
// noop
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function createCustomEvent(detail) {
|
|
17
|
+
return new CustomEventStub(detail);
|
|
18
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { BoardItemDefinition, GridLayout, ItemId } from "../interfaces";
|
|
2
|
+
type Item<D = unknown> = BoardItemDefinition<D>;
|
|
3
|
+
/**
|
|
4
|
+
* The function produces grid layout from board items and given number of columns.
|
|
5
|
+
* The positional data is taken from the items when available or the default placement is used otherwise.
|
|
6
|
+
*/
|
|
7
|
+
export declare function interpretItems(items: readonly Item[], columns: number): GridLayout;
|
|
8
|
+
/**
|
|
9
|
+
* The function produces new items from the current state and updated grid layout.
|
|
10
|
+
* The positional data for the given number of columns is preserved as is while the other layouts are partially invalidated.
|
|
11
|
+
*/
|
|
12
|
+
export declare function transformItems<D>(sourceItems: readonly BoardItemDefinition<D>[], gridLayout: GridLayout, resizeTarget: null | ItemId): readonly BoardItemDefinition<D>[];
|
|
13
|
+
export declare function createPlaceholdersLayout(rows: number, columns: number): GridLayout;
|
|
14
|
+
export declare function getMinColumnSpan(item: Item, columns: number): number;
|
|
15
|
+
export declare function getDefaultColumnSpan(item: Item, columns: number): number;
|
|
16
|
+
export declare function getMinRowSpan(item: Item): number;
|
|
17
|
+
export declare function getDefaultRowSpan(item: Item): number;
|
|
18
|
+
export {};
|