@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.
Files changed (220) hide show
  1. package/Config +23 -0
  2. package/LICENSE +201 -0
  3. package/NOTICE +2 -0
  4. package/README-cloudscape.md +20 -0
  5. package/README-open-source.md +0 -0
  6. package/README.md +20 -0
  7. package/board/index.d.ts +4 -0
  8. package/board/index.js +11 -0
  9. package/board/interfaces.d.ts +167 -0
  10. package/board/interfaces.js +1 -0
  11. package/board/internal.d.ts +4 -0
  12. package/board/internal.js +199 -0
  13. package/board/placeholder.d.ts +10 -0
  14. package/board/placeholder.js +24 -0
  15. package/board/styles.css.js +10 -0
  16. package/board/styles.scoped.css +23 -0
  17. package/board/styles.selectors.js +11 -0
  18. package/board/transition.d.ts +50 -0
  19. package/board/transition.js +211 -0
  20. package/board/utils/announcements.d.ts +10 -0
  21. package/board/utils/announcements.js +98 -0
  22. package/board/utils/create-transforms.d.ts +7 -0
  23. package/board/utils/create-transforms.js +22 -0
  24. package/board/utils/events.d.ts +3 -0
  25. package/board/utils/events.js +14 -0
  26. package/board/utils/get-hovered-rect.d.ts +10 -0
  27. package/board/utils/get-hovered-rect.js +19 -0
  28. package/board/utils/layout.d.ts +19 -0
  29. package/board/utils/layout.js +77 -0
  30. package/board/utils/path.d.ts +10 -0
  31. package/board/utils/path.js +73 -0
  32. package/board-item/header.d.ts +7 -0
  33. package/board-item/header.js +8 -0
  34. package/board-item/index.d.ts +4 -0
  35. package/board-item/index.js +11 -0
  36. package/board-item/interfaces.d.ts +42 -0
  37. package/board-item/interfaces.js +1 -0
  38. package/board-item/internal.d.ts +4 -0
  39. package/board-item/internal.js +20 -0
  40. package/board-item/styles.css.js +15 -0
  41. package/board-item/styles.scoped.css +41 -0
  42. package/board-item/styles.selectors.js +16 -0
  43. package/index.d.ts +6 -0
  44. package/index.js +5 -0
  45. package/internal/api-docs/components/board-item.js +68 -0
  46. package/internal/api-docs/components/board.js +117 -0
  47. package/internal/api-docs/components/index.js +5 -0
  48. package/internal/api-docs/components/items-palette.js +58 -0
  49. package/internal/api-docs/test-utils-doc/dom.js +4 -0
  50. package/internal/api-docs/test-utils-doc/selectors.js +4 -0
  51. package/internal/base-component/use-base-component.d.ts +12 -0
  52. package/internal/base-component/use-base-component.js +16 -0
  53. package/internal/base-component/use-telemetry.d.ts +1 -0
  54. package/internal/base-component/use-telemetry.js +9 -0
  55. package/internal/base-component/use-visual-refresh.d.ts +1 -0
  56. package/internal/base-component/use-visual-refresh.js +24 -0
  57. package/internal/breakpoints.d.ts +2 -0
  58. package/internal/breakpoints.js +18 -0
  59. package/internal/constants.d.ts +3 -0
  60. package/internal/constants.js +5 -0
  61. package/internal/debug-tools/converters.d.ts +4 -0
  62. package/internal/debug-tools/converters.js +21 -0
  63. package/internal/debug-tools/generators.d.ts +25 -0
  64. package/internal/debug-tools/generators.js +258 -0
  65. package/internal/debug-tools/index.d.ts +8 -0
  66. package/internal/debug-tools/index.js +10 -0
  67. package/internal/debug-tools/interfaces.d.ts +2 -0
  68. package/internal/debug-tools/interfaces.js +3 -0
  69. package/internal/debug-tools/parsers.d.ts +8 -0
  70. package/internal/debug-tools/parsers.js +66 -0
  71. package/internal/dnd-controller/__mocks__/controller.d.ts +13 -0
  72. package/internal/dnd-controller/__mocks__/controller.js +33 -0
  73. package/internal/dnd-controller/collision.d.ts +17 -0
  74. package/internal/dnd-controller/collision.js +32 -0
  75. package/internal/dnd-controller/controller.d.ts +64 -0
  76. package/internal/dnd-controller/controller.js +131 -0
  77. package/internal/dnd-controller/event-emitter.d.ts +9 -0
  78. package/internal/dnd-controller/event-emitter.js +22 -0
  79. package/internal/drag-handle/icon.d.ts +4 -0
  80. package/internal/drag-handle/icon.js +12 -0
  81. package/internal/drag-handle/index.d.ts +9 -0
  82. package/internal/drag-handle/index.js +11 -0
  83. package/internal/drag-handle/styles.css.js +6 -0
  84. package/internal/drag-handle/styles.scoped.css +7 -0
  85. package/internal/drag-handle/styles.selectors.js +7 -0
  86. package/internal/environment.d.ts +4 -0
  87. package/internal/environment.js +4 -0
  88. package/internal/generated/styles/tokens.d.ts +0 -0
  89. package/internal/generated/styles/tokens.js +0 -0
  90. package/internal/grid/grid.d.ts +3 -0
  91. package/internal/grid/grid.js +28 -0
  92. package/internal/grid/index.d.ts +2 -0
  93. package/internal/grid/index.js +3 -0
  94. package/internal/grid/interfaces.d.ts +14 -0
  95. package/internal/grid/interfaces.js +3 -0
  96. package/internal/grid/item.d.ts +8 -0
  97. package/internal/grid/item.js +10 -0
  98. package/internal/grid/styles.css.js +7 -0
  99. package/internal/grid/styles.scoped.css +221 -0
  100. package/internal/grid/styles.selectors.js +8 -0
  101. package/internal/handle/index.d.ts +3 -0
  102. package/internal/handle/index.js +17 -0
  103. package/internal/handle/styles.css.js +6 -0
  104. package/internal/handle/styles.scoped.css +32 -0
  105. package/internal/handle/styles.selectors.js +7 -0
  106. package/internal/interfaces.d.ts +50 -0
  107. package/internal/interfaces.js +3 -0
  108. package/internal/is-development.d.ts +6 -0
  109. package/internal/is-development.js +8 -0
  110. package/internal/item-container/get-next-droppable.d.ts +7 -0
  111. package/internal/item-container/get-next-droppable.js +15 -0
  112. package/internal/item-container/index.d.ts +48 -0
  113. package/internal/item-container/index.js +262 -0
  114. package/internal/item-container/styles.css.js +12 -0
  115. package/internal/item-container/styles.scoped.css +33 -0
  116. package/internal/item-container/styles.selectors.js +13 -0
  117. package/internal/layout-engine/engine-conflicts.d.ts +4 -0
  118. package/internal/layout-engine/engine-conflicts.js +53 -0
  119. package/internal/layout-engine/engine-step.d.ts +5 -0
  120. package/internal/layout-engine/engine-step.js +307 -0
  121. package/internal/layout-engine/engine.d.ts +19 -0
  122. package/internal/layout-engine/engine.js +105 -0
  123. package/internal/layout-engine/grid.d.ts +28 -0
  124. package/internal/layout-engine/grid.js +140 -0
  125. package/internal/layout-engine/interfaces.d.ts +30 -0
  126. package/internal/layout-engine/interfaces.js +3 -0
  127. package/internal/layout-engine/utils.d.ts +12 -0
  128. package/internal/layout-engine/utils.js +79 -0
  129. package/internal/live-region/index.d.ts +44 -0
  130. package/internal/live-region/index.js +85 -0
  131. package/internal/logging.d.ts +1 -0
  132. package/internal/logging.js +10 -0
  133. package/internal/manifest.json +3 -0
  134. package/internal/resize-handle/icon.d.ts +4 -0
  135. package/internal/resize-handle/icon.js +12 -0
  136. package/internal/resize-handle/index.d.ts +8 -0
  137. package/internal/resize-handle/index.js +7 -0
  138. package/internal/resize-handle/styles.css.js +6 -0
  139. package/internal/resize-handle/styles.scoped.css +3 -0
  140. package/internal/resize-handle/styles.selectors.js +7 -0
  141. package/internal/screenreader-grid-navigation/index.d.ts +22 -0
  142. package/internal/screenreader-grid-navigation/index.js +42 -0
  143. package/internal/screenreader-grid-navigation/styles.css.js +7 -0
  144. package/internal/screenreader-grid-navigation/styles.scoped.css +12 -0
  145. package/internal/screenreader-grid-navigation/styles.selectors.js +8 -0
  146. package/internal/screenreader-only/index.d.ts +21 -0
  147. package/internal/screenreader-only/index.js +23 -0
  148. package/internal/screenreader-only/styles.css.js +6 -0
  149. package/internal/screenreader-only/styles.scoped.css +9 -0
  150. package/internal/screenreader-only/styles.selectors.js +7 -0
  151. package/internal/utils/apply-display-name.d.ts +1 -0
  152. package/internal/utils/apply-display-name.js +5 -0
  153. package/internal/utils/coordinates.d.ts +14 -0
  154. package/internal/utils/coordinates.js +20 -0
  155. package/internal/utils/events.d.ts +2 -0
  156. package/internal/utils/events.js +18 -0
  157. package/internal/utils/layout.d.ts +18 -0
  158. package/internal/utils/layout.js +132 -0
  159. package/internal/utils/position.d.ts +9 -0
  160. package/internal/utils/position.js +9 -0
  161. package/internal/utils/rects.d.ts +6 -0
  162. package/internal/utils/rects.js +76 -0
  163. package/internal/utils/screen.d.ts +1 -0
  164. package/internal/utils/screen.js +17 -0
  165. package/internal/utils/stack-set.d.ts +8 -0
  166. package/internal/utils/stack-set.js +23 -0
  167. package/internal/utils/throttle.d.ts +5 -0
  168. package/internal/utils/throttle.js +51 -0
  169. package/internal/utils/use-auto-scroll.d.ts +5 -0
  170. package/internal/utils/use-auto-scroll.js +62 -0
  171. package/internal/utils/use-last-interaction.d.ts +1 -0
  172. package/internal/utils/use-last-interaction.js +22 -0
  173. package/internal/utils/use-merge-refs.d.ts +9 -0
  174. package/internal/utils/use-merge-refs.js +29 -0
  175. package/internal/utils/use-stable-event-handler.d.ts +9 -0
  176. package/internal/utils/use-stable-event-handler.js +19 -0
  177. package/internal/utils/use-throttled-event-handler.d.ts +1 -0
  178. package/internal/utils/use-throttled-event-handler.js +11 -0
  179. package/internal/utils/zip-arrays.d.ts +1 -0
  180. package/internal/utils/zip-arrays.js +8 -0
  181. package/items-palette/index.d.ts +4 -0
  182. package/items-palette/index.js +11 -0
  183. package/items-palette/interfaces.d.ts +49 -0
  184. package/items-palette/interfaces.js +3 -0
  185. package/items-palette/internal.d.ts +4 -0
  186. package/items-palette/internal.js +73 -0
  187. package/items-palette/styles.css.js +6 -0
  188. package/items-palette/styles.scoped.css +3 -0
  189. package/items-palette/styles.selectors.js +7 -0
  190. package/package.json +43 -0
  191. package/test-utils/dom/board/index.d.ts +6 -0
  192. package/test-utils/dom/board/index.js +15 -0
  193. package/test-utils/dom/board/index.js.map +1 -0
  194. package/test-utils/dom/board-item/index.d.ts +10 -0
  195. package/test-utils/dom/board-item/index.js +33 -0
  196. package/test-utils/dom/board-item/index.js.map +1 -0
  197. package/test-utils/dom/index.d.ts +19 -0
  198. package/test-utils/dom/index.js +41 -0
  199. package/test-utils/dom/index.js.map +1 -0
  200. package/test-utils/dom/items-palette/index.d.ts +7 -0
  201. package/test-utils/dom/items-palette/index.js +18 -0
  202. package/test-utils/dom/items-palette/index.js.map +1 -0
  203. package/test-utils/dom/palette-item/index.d.ts +5 -0
  204. package/test-utils/dom/palette-item/index.js +15 -0
  205. package/test-utils/dom/palette-item/index.js.map +1 -0
  206. package/test-utils/selectors/board/index.d.ts +6 -0
  207. package/test-utils/selectors/board/index.js +15 -0
  208. package/test-utils/selectors/board/index.js.map +1 -0
  209. package/test-utils/selectors/board-item/index.d.ts +10 -0
  210. package/test-utils/selectors/board-item/index.js +33 -0
  211. package/test-utils/selectors/board-item/index.js.map +1 -0
  212. package/test-utils/selectors/index.d.ts +19 -0
  213. package/test-utils/selectors/index.js +41 -0
  214. package/test-utils/selectors/index.js.map +1 -0
  215. package/test-utils/selectors/items-palette/index.d.ts +7 -0
  216. package/test-utils/selectors/items-palette/index.js +18 -0
  217. package/test-utils/selectors/items-palette/index.js.map +1 -0
  218. package/test-utils/selectors/palette-item/index.d.ts +5 -0
  219. package/test-utils/selectors/palette-item/index.js +15 -0
  220. package/test-utils/selectors/palette-item/index.js.map +1 -0
@@ -0,0 +1,199 @@
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 clsx from "clsx";
5
+ import { useEffect, useRef } from "react";
6
+ import { useContainerColumns } from "../internal/breakpoints";
7
+ import { TRANSITION_DURATION_MS } from "../internal/constants";
8
+ import { useDragSubscription } from "../internal/dnd-controller/controller";
9
+ import Grid from "../internal/grid";
10
+ import { ItemContainer } from "../internal/item-container";
11
+ import { LayoutEngine } from "../internal/layout-engine/engine";
12
+ import LiveRegion from "../internal/live-region";
13
+ import { ScreenReaderGridNavigation } from "../internal/screenreader-grid-navigation";
14
+ import { createPlaceholdersLayout, getDefaultColumnSpan, getDefaultRowSpan, getMinColumnSpan, getMinRowSpan, interpretItems, } from "../internal/utils/layout";
15
+ import { Position } from "../internal/utils/position";
16
+ import { useAutoScroll } from "../internal/utils/use-auto-scroll";
17
+ import { useMergeRefs } from "../internal/utils/use-merge-refs";
18
+ import Placeholder from "./placeholder";
19
+ import styles from "./styles.css.js";
20
+ import { selectTransitionRows, useTransition } from "./transition";
21
+ import { announcementToString } from "./utils/announcements";
22
+ import { createTransforms } from "./utils/create-transforms";
23
+ import { createItemsChangeEvent } from "./utils/events";
24
+ export function InternalBoard({ items, renderItem, onItemsChange, empty, i18nStrings, __internalRootRef, }) {
25
+ var _a, _b;
26
+ const containerAccessRef = useRef(null);
27
+ const [columns, containerQueryRef] = useContainerColumns();
28
+ const containerRef = useMergeRefs(containerAccessRef, containerQueryRef);
29
+ const itemContainerRef = useRef({});
30
+ const autoScrollHandlers = useAutoScroll();
31
+ const [transitionState, dispatch] = useTransition();
32
+ const transition = transitionState.transition;
33
+ const removeTransition = transitionState.removeTransition;
34
+ const transitionAnnouncement = transitionState.announcement;
35
+ const acquiredItem = (_a = transition === null || transition === void 0 ? void 0 : transition.acquiredItem) !== null && _a !== void 0 ? _a : null;
36
+ // Use previous items while remove transition is in progress.
37
+ items = (_b = removeTransition === null || removeTransition === void 0 ? void 0 : removeTransition.items) !== null && _b !== void 0 ? _b : items;
38
+ // The acquired item is the one being inserting at the moment but not submitted yet.
39
+ // It needs to be included to the layout to be a part of layout shifts and rendering.
40
+ items = acquiredItem ? [...items, acquiredItem] : items;
41
+ const itemsLayout = interpretItems(items, columns);
42
+ const layoutItemById = new Map(itemsLayout.items.map((item) => [item.id, item]));
43
+ const layoutItemIndexById = new Map(itemsLayout.items.map((item, index) => [item.id, index]));
44
+ // Items and layout items must maintain the same order visually, in the DOM and in the data
45
+ // to ensure on-change events and tab order work as expected.
46
+ items = [...items].sort((a, b) => { var _a, _b; return ((_a = layoutItemIndexById.get(a.id)) !== null && _a !== void 0 ? _a : -1) - ((_b = layoutItemIndexById.get(b.id)) !== null && _b !== void 0 ? _b : -1); });
47
+ // When an item gets acquired or removed the focus needs to be dispatched on the next render.
48
+ const focusNextRenderIndexRef = useRef(null);
49
+ const focusNextRenderIdRef = useRef(null);
50
+ useEffect(() => {
51
+ var _a, _b, _c;
52
+ const focusTarget = (_a = focusNextRenderIdRef.current) !== null && _a !== void 0 ? _a : (_c = items[(_b = focusNextRenderIndexRef.current) !== null && _b !== void 0 ? _b : -1]) === null || _c === void 0 ? void 0 : _c.id;
53
+ if (focusTarget) {
54
+ itemContainerRef.current[focusTarget].focusDragHandle();
55
+ }
56
+ focusNextRenderIndexRef.current = null;
57
+ focusNextRenderIdRef.current = null;
58
+ });
59
+ // Submit scheduled removal after a delay to let animations play.
60
+ useEffect(() => {
61
+ if (!removeTransition) {
62
+ return;
63
+ }
64
+ const timeoutId = setTimeout(() => {
65
+ dispatch({ type: "submit" });
66
+ const removedItemIndex = items.findIndex((it) => it.id === removeTransition.removedItem.id);
67
+ const nextIndexToFocus = removedItemIndex !== items.length - 1 ? removedItemIndex : items.length - 2;
68
+ focusNextRenderIndexRef.current = nextIndexToFocus;
69
+ }, TRANSITION_DURATION_MS);
70
+ return () => clearTimeout(timeoutId);
71
+ }, [removeTransition, items]);
72
+ const rows = selectTransitionRows(transitionState) || itemsLayout.rows;
73
+ const placeholdersLayout = createPlaceholdersLayout(rows, columns);
74
+ function isElementOverBoard(draggableElement) {
75
+ const board = containerAccessRef.current;
76
+ const boardContains = (target) => board === target || board.contains(target);
77
+ const rect = draggableElement.getBoundingClientRect();
78
+ return (boardContains(document.elementFromPoint(rect.left, rect.top)) ||
79
+ boardContains(document.elementFromPoint(rect.right, rect.top)) ||
80
+ boardContains(document.elementFromPoint(rect.right, rect.bottom)) ||
81
+ boardContains(document.elementFromPoint(rect.left, rect.bottom)));
82
+ }
83
+ useDragSubscription("start", ({ operation, interactionType, draggableItem, draggableElement, collisionIds }) => {
84
+ dispatch({
85
+ type: "init",
86
+ operation,
87
+ interactionType,
88
+ itemsLayout,
89
+ // TODO: resolve any
90
+ // The code only works assuming the board can take any draggable.
91
+ // If draggables can be of different types a check of some sort is required here.
92
+ draggableItem: draggableItem,
93
+ draggableElement,
94
+ collisionIds: interactionType === "keyboard" || isElementOverBoard(draggableElement) ? collisionIds : [],
95
+ });
96
+ autoScrollHandlers.addPointerEventHandlers();
97
+ });
98
+ useDragSubscription("update", ({ interactionType, collisionIds, positionOffset, draggableElement }) => {
99
+ dispatch({
100
+ type: "update-with-pointer",
101
+ collisionIds: interactionType === "keyboard" || isElementOverBoard(draggableElement) ? collisionIds : [],
102
+ positionOffset,
103
+ });
104
+ });
105
+ useDragSubscription("submit", () => {
106
+ dispatch({ type: "submit" });
107
+ autoScrollHandlers.removePointerEventHandlers();
108
+ if (!transition) {
109
+ throw new Error("Invariant violation: no transition.");
110
+ }
111
+ if (!transition.layoutShift ||
112
+ transition.layoutShift.conflicts.length > 0 ||
113
+ transition.layoutShift.moves.length === 0) {
114
+ return null;
115
+ }
116
+ // Commit new layout for insert case.
117
+ if (transition.operation === "insert") {
118
+ onItemsChange(createItemsChangeEvent([...items, transition.draggableItem], transition.layoutShift));
119
+ }
120
+ // Commit new layout for reorder/resize case.
121
+ else {
122
+ onItemsChange(createItemsChangeEvent(items, transition.layoutShift));
123
+ }
124
+ });
125
+ useDragSubscription("discard", () => {
126
+ dispatch({ type: "discard" });
127
+ autoScrollHandlers.removePointerEventHandlers();
128
+ });
129
+ useDragSubscription("acquire", ({ droppableId, draggableItem }) => {
130
+ const placeholder = placeholdersLayout.items.find((it) => it.id === droppableId);
131
+ // If missing then it does not belong to this board.
132
+ if (!placeholder) {
133
+ return;
134
+ }
135
+ dispatch({
136
+ type: "acquire-item",
137
+ position: new Position({ x: placeholder.x, y: placeholder.y }),
138
+ layoutElement: containerAccessRef.current,
139
+ });
140
+ focusNextRenderIdRef.current = draggableItem.id;
141
+ });
142
+ const removeItemAction = (removedItem) => {
143
+ dispatch({ type: "init-remove", items, itemsLayout, removedItem });
144
+ const layoutShift = new LayoutEngine(itemsLayout).remove(removedItem.id).getLayoutShift();
145
+ onItemsChange(createItemsChangeEvent(items, layoutShift));
146
+ };
147
+ function focusItem(itemId) {
148
+ itemContainerRef.current[itemId].focusDragHandle();
149
+ }
150
+ function onItemMove(direction) {
151
+ if (transition) {
152
+ dispatch({ type: "update-with-keyboard", direction });
153
+ autoScrollHandlers.scheduleActiveElementScrollIntoView(TRANSITION_DURATION_MS);
154
+ }
155
+ }
156
+ const announcement = transitionAnnouncement
157
+ ? announcementToString(transitionAnnouncement, items, i18nStrings, columns)
158
+ : "";
159
+ return (_jsxs("div", { ref: __internalRootRef, children: [_jsx(ScreenReaderGridNavigation, { items: items, itemsLayout: itemsLayout, ariaLabel: i18nStrings.navigationAriaLabel, ariaDescription: i18nStrings.navigationAriaDescription, itemAriaLabel: i18nStrings.navigationItemAriaLabel, onActivateItem: focusItem }), _jsx("div", { ref: containerRef, className: clsx(styles.root, { [styles.empty]: rows === 0 }), children: rows > 0 ? (_jsx(Grid, { columns: columns, rows: rows, layout: [...placeholdersLayout.items, ...itemsLayout.items], children: (gridContext) => {
160
+ var _a;
161
+ const layoutShift = (_a = transition === null || transition === void 0 ? void 0 : transition.layoutShift) !== null && _a !== void 0 ? _a : removeTransition === null || removeTransition === void 0 ? void 0 : removeTransition.layoutShift;
162
+ const transforms = layoutShift ? createTransforms(itemsLayout, layoutShift.moves, gridContext) : {};
163
+ // Exclude drag target from transforms.
164
+ if (transition && transition.interactionType === "pointer") {
165
+ delete transforms[transition.draggableItem.id];
166
+ }
167
+ const children = [];
168
+ /* Placeholders are rendered even when there is no transition to support the first collisions check. */
169
+ placeholdersLayout.items.forEach((placeholder) => {
170
+ var _a;
171
+ return children.push(_jsx(Placeholder, { id: placeholder.id, state: transition ? (((_a = transition.collisionIds) === null || _a === void 0 ? void 0 : _a.has(placeholder.id)) ? "hover" : "active") : "default", gridContext: gridContext, columns: columns }, placeholder.id));
172
+ });
173
+ items.forEach((item) => {
174
+ const layoutItem = layoutItemById.get(item.id);
175
+ const isResizing = (transition === null || transition === void 0 ? void 0 : transition.operation) === "resize" && (transition === null || transition === void 0 ? void 0 : transition.draggableItem.id) === item.id;
176
+ const itemSize = layoutItem !== null && layoutItem !== void 0 ? layoutItem : {
177
+ width: getDefaultColumnSpan(item, columns),
178
+ height: getDefaultRowSpan(item),
179
+ };
180
+ const itemMaxSize = isResizing && layoutItem ? { width: columns - layoutItem.x, height: 999 } : itemSize;
181
+ children.push(_jsx(ItemContainer, { ref: (elem) => {
182
+ if (elem) {
183
+ itemContainerRef.current[item.id] = elem;
184
+ }
185
+ else {
186
+ delete itemContainerRef.current[item.id];
187
+ }
188
+ }, item: item, transform: transforms[item.id], inTransition: !!layoutShift, placed: true, acquired: item.id === (acquiredItem === null || acquiredItem === void 0 ? void 0 : acquiredItem.id), getItemSize: () => ({
189
+ width: gridContext.getWidth(itemSize.width),
190
+ minWidth: gridContext.getWidth(getMinColumnSpan(item, columns)),
191
+ maxWidth: gridContext.getWidth(itemMaxSize.width),
192
+ height: gridContext.getHeight(itemSize.height),
193
+ minHeight: gridContext.getHeight(getMinRowSpan(item)),
194
+ maxHeight: gridContext.getHeight(itemMaxSize.height),
195
+ }), onKeyMove: onItemMove, children: renderItem(item, { removeItem: () => removeItemAction(item) }) }, item.id));
196
+ });
197
+ return children;
198
+ } })) : (empty) }), _jsx(LiveRegion, { children: announcement })] }));
199
+ }
@@ -0,0 +1,10 @@
1
+ /// <reference types="react" />
2
+ import { GridContext } from "../internal/grid/interfaces";
3
+ export type PlaceholderState = "default" | "active" | "hover";
4
+ export interface PlaceholderProps {
5
+ id: string;
6
+ state: PlaceholderState;
7
+ gridContext: GridContext;
8
+ columns: number;
9
+ }
10
+ export default function Placeholder({ id, state, gridContext, columns }: PlaceholderProps): JSX.Element;
@@ -0,0 +1,24 @@
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
+ import clsx from "clsx";
5
+ import { useRef } from "react";
6
+ import { useDroppable } from "../internal/dnd-controller/controller";
7
+ import { getDefaultColumnSpan, getDefaultRowSpan } from "../internal/utils/layout";
8
+ import styles from "./styles.css.js";
9
+ export default function Placeholder({ id, state, gridContext, columns }) {
10
+ const ref = useRef(null);
11
+ const dropTargetContext = {
12
+ scale: (item, size) => {
13
+ var _a, _b;
14
+ const width = (_a = size === null || size === void 0 ? void 0 : size.width) !== null && _a !== void 0 ? _a : getDefaultColumnSpan(item, columns);
15
+ const height = (_b = size === null || size === void 0 ? void 0 : size.height) !== null && _b !== void 0 ? _b : getDefaultRowSpan(item);
16
+ return {
17
+ width: gridContext.getWidth(width),
18
+ height: gridContext.getHeight(height),
19
+ };
20
+ },
21
+ };
22
+ useDroppable({ itemId: id, context: dropTargetContext, getElement: () => ref.current });
23
+ return _jsx("div", { ref: ref, className: clsx(styles.placeholder, styles[`placeholder--${state}`]) });
24
+ }
@@ -0,0 +1,10 @@
1
+
2
+ import './styles.scoped.css';
3
+ export default {
4
+ "placeholder": "awsui_placeholder_1h7dk_4221b_1",
5
+ "placeholder--active": "awsui_placeholder--active_1h7dk_4221b_5",
6
+ "placeholder--hover": "awsui_placeholder--hover_1h7dk_4221b_8",
7
+ "root": "awsui_root_1h7dk_4221b_12",
8
+ "empty": "awsui_empty_1h7dk_4221b_16"
9
+ };
10
+
@@ -0,0 +1,23 @@
1
+ .awsui_placeholder_1h7dk_4221b_1:not(#\9) {
2
+ border-radius: var(--border-radius-container-1aveko, 0px);
3
+ height: 100%;
4
+ }
5
+ .awsui_placeholder--active_1h7dk_4221b_5:not(#\9) {
6
+ background-color: var(--color-board-placeholder-active-03p6jc, #d5dbdb);
7
+ }
8
+ .awsui_placeholder--hover_1h7dk_4221b_8:not(#\9) {
9
+ background-color: var(--color-board-placeholder-hover-82yrwq, #99cbe4);
10
+ }
11
+
12
+ .awsui_root_1h7dk_4221b_12:not(#\9) {
13
+ /* used in test-utils */
14
+ }
15
+
16
+ .awsui_empty_1h7dk_4221b_16:not(#\9) {
17
+ box-sizing: border-box;
18
+ width: 100%;
19
+ padding: var(--space-scaled-m-pv0fmt, 16px) var(--space-scaled-l-t03y3z, 20px) var(--space-scaled-l-t03y3z, 20px);
20
+ color: var(--color-text-empty-izapdt, #687078);
21
+ display: flex;
22
+ justify-content: center;
23
+ }
@@ -0,0 +1,11 @@
1
+
2
+ // es-module interop with Babel and Typescript
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ module.exports.default = {
5
+ "placeholder": "awsui_placeholder_1h7dk_4221b_1",
6
+ "placeholder--active": "awsui_placeholder--active_1h7dk_4221b_5",
7
+ "placeholder--hover": "awsui_placeholder--hover_1h7dk_4221b_8",
8
+ "root": "awsui_root_1h7dk_4221b_12",
9
+ "empty": "awsui_empty_1h7dk_4221b_16"
10
+ };
11
+
@@ -0,0 +1,50 @@
1
+ import { Dispatch } from "react";
2
+ import { InteractionType, Operation } from "../internal/dnd-controller/controller";
3
+ import { BoardItemDefinitionBase, Direction, GridLayout, ItemId } from "../internal/interfaces";
4
+ import { Coordinates } from "../internal/utils/coordinates";
5
+ import { Position } from "../internal/utils/position";
6
+ import { BoardProps, RemoveTransition, Transition, TransitionAnnouncement } from "./interfaces";
7
+ export interface TransitionState<D> {
8
+ transition: null | Transition<D>;
9
+ removeTransition: null | RemoveTransition<D>;
10
+ announcement: null | TransitionAnnouncement;
11
+ }
12
+ export type Action<D> = InitAction<D> | InitRemoveAction<D> | SubmitAction | DiscardAction | UpdateWithPointerAction | UpdateWithKeyboardAction | AcquireItemAction;
13
+ interface InitAction<D> {
14
+ type: "init";
15
+ operation: Operation;
16
+ interactionType: InteractionType;
17
+ itemsLayout: GridLayout;
18
+ draggableItem: BoardItemDefinitionBase<D>;
19
+ draggableElement: HTMLElement;
20
+ collisionIds: readonly ItemId[];
21
+ }
22
+ interface InitRemoveAction<D> {
23
+ type: "init-remove";
24
+ items: readonly BoardProps.Item<D>[];
25
+ removedItem: BoardItemDefinitionBase<D>;
26
+ itemsLayout: GridLayout;
27
+ }
28
+ interface SubmitAction {
29
+ type: "submit";
30
+ }
31
+ interface DiscardAction {
32
+ type: "discard";
33
+ }
34
+ interface UpdateWithPointerAction {
35
+ type: "update-with-pointer";
36
+ collisionIds: readonly ItemId[];
37
+ positionOffset: Coordinates;
38
+ }
39
+ interface UpdateWithKeyboardAction {
40
+ type: "update-with-keyboard";
41
+ direction: Direction;
42
+ }
43
+ interface AcquireItemAction {
44
+ type: "acquire-item";
45
+ position: Position;
46
+ layoutElement: HTMLElement;
47
+ }
48
+ export declare function useTransition<D>(): [TransitionState<D>, Dispatch<Action<D>>];
49
+ export declare function selectTransitionRows<D>(state: TransitionState<D>): number;
50
+ export {};
@@ -0,0 +1,211 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { useReducer } from "react";
4
+ import { LayoutEngine } from "../internal/layout-engine/engine";
5
+ import { Coordinates } from "../internal/utils/coordinates";
6
+ import { getDefaultColumnSpan, getDefaultRowSpan, getMinColumnSpan, getMinRowSpan } from "../internal/utils/layout";
7
+ import { Position } from "../internal/utils/position";
8
+ import { createOperationAnnouncement } from "./utils/announcements";
9
+ import { getHoveredRect } from "./utils/get-hovered-rect";
10
+ import { getInsertionDirection, getLayoutPlaceholders, getLayoutRows, getLayoutShift } from "./utils/layout";
11
+ import { appendMovePath, appendResizePath } from "./utils/path";
12
+ export function useTransition() {
13
+ return useReducer((transitionReducer), { transition: null, removeTransition: null, announcement: null });
14
+ }
15
+ export function selectTransitionRows(state) {
16
+ return state.transition ? getLayoutRows(state.transition) : 0;
17
+ }
18
+ function transitionReducer(state, action) {
19
+ switch (action.type) {
20
+ case "init":
21
+ return initTransition(action);
22
+ case "init-remove":
23
+ return initRemoveTransition(action);
24
+ case "submit":
25
+ return submitTransition(state);
26
+ case "discard":
27
+ return discardTransition(state);
28
+ case "update-with-pointer":
29
+ return updateTransitionWithPointerEvent(state, action);
30
+ case "update-with-keyboard":
31
+ return updateTransitionWithKeyboardEvent(state, action);
32
+ case "acquire-item":
33
+ return acquireTransitionItem(state, action);
34
+ }
35
+ }
36
+ function initTransition({ operation, interactionType, itemsLayout, draggableItem, draggableElement, collisionIds, }) {
37
+ const transition = {
38
+ operation,
39
+ interactionType,
40
+ itemsLayout,
41
+ insertionDirection: null,
42
+ draggableItem,
43
+ draggableElement,
44
+ acquiredItem: null,
45
+ collisionIds: new Set(),
46
+ layoutShift: null,
47
+ path: [],
48
+ };
49
+ const placeholdersLayout = getLayoutPlaceholders(transition);
50
+ const itemBelongsToBoard = itemsLayout.items.find((it) => it.id === draggableItem.id);
51
+ const collisionRect = getHoveredRect(collisionIds, placeholdersLayout.items);
52
+ const appendPath = operation === "resize" ? appendResizePath : appendMovePath;
53
+ const path = itemBelongsToBoard ? appendPath([], collisionRect) : [];
54
+ return {
55
+ transition: { ...transition, path },
56
+ removeTransition: null,
57
+ announcement: itemBelongsToBoard ? { type: "dnd-started", item: draggableItem, operation } : null,
58
+ };
59
+ }
60
+ function initRemoveTransition({ items, removedItem, itemsLayout }) {
61
+ const layoutShift = new LayoutEngine(itemsLayout).remove(removedItem.id).refloat().getLayoutShift();
62
+ const removeTransition = { items, removedItem, layoutShift };
63
+ return { transition: null, removeTransition, announcement: null };
64
+ }
65
+ function submitTransition(state) {
66
+ var _a;
67
+ const { transition, removeTransition } = state;
68
+ if (removeTransition) {
69
+ const disturbed = new Set(removeTransition.layoutShift.moves.map((move) => move.itemId));
70
+ disturbed.delete(removeTransition.removedItem.id);
71
+ return {
72
+ transition: null,
73
+ removeTransition: null,
74
+ announcement: { type: "item-removed", item: removeTransition.removedItem, disturbed },
75
+ };
76
+ }
77
+ if (!transition) {
78
+ throw new Error("Invariant violation: no transition.");
79
+ }
80
+ const { operation, itemsLayout, draggableItem: item, acquiredItem } = transition;
81
+ const itemBelongsToBoard = item.id === (acquiredItem === null || acquiredItem === void 0 ? void 0 : acquiredItem.id) || itemsLayout.items.some((it) => it.id === item.id);
82
+ return ((_a = transition.layoutShift) === null || _a === void 0 ? void 0 : _a.conflicts.length) === 0
83
+ ? {
84
+ transition: null,
85
+ removeTransition: null,
86
+ announcement: itemBelongsToBoard ? { type: "dnd-committed", item, operation } : null,
87
+ }
88
+ : {
89
+ transition: null,
90
+ removeTransition: null,
91
+ announcement: itemBelongsToBoard ? { type: "dnd-discarded", item, operation } : null,
92
+ };
93
+ }
94
+ function discardTransition(state) {
95
+ const { transition, removeTransition } = state;
96
+ if (removeTransition) {
97
+ throw new Error("Can't discard remove transition.");
98
+ }
99
+ if (!transition) {
100
+ throw new Error("Invariant violation: no transition.");
101
+ }
102
+ const { operation, itemsLayout, draggableItem: item, acquiredItem } = transition;
103
+ const itemBelongsToBoard = item.id === (acquiredItem === null || acquiredItem === void 0 ? void 0 : acquiredItem.id) || itemsLayout.items.some((it) => it.id === item.id);
104
+ return {
105
+ transition: null,
106
+ removeTransition: null,
107
+ announcement: itemBelongsToBoard ? { type: "dnd-discarded", item, operation } : null,
108
+ };
109
+ }
110
+ function updateTransitionWithPointerEvent(state, { collisionIds, positionOffset }) {
111
+ var _a, _b, _c;
112
+ const { transition } = state;
113
+ if (!transition) {
114
+ throw new Error("Invariant violation: no transition.");
115
+ }
116
+ const layout = (_b = (_a = transition.layoutShift) === null || _a === void 0 ? void 0 : _a.next) !== null && _b !== void 0 ? _b : transition.itemsLayout;
117
+ const layoutItem = layout.items.find((it) => it.id === transition.draggableItem.id);
118
+ const itemWidth = layoutItem ? layoutItem.width : getDefaultColumnSpan(transition.draggableItem, layout.columns);
119
+ const itemHeight = layoutItem ? layoutItem.height : getDefaultRowSpan(transition.draggableItem);
120
+ const itemSize = itemWidth * itemHeight;
121
+ const isOutOfBoundaries = transition.operation !== "resize" ? collisionIds.length < itemSize : collisionIds.length === 0;
122
+ if (isOutOfBoundaries) {
123
+ return {
124
+ transition: { ...transition, collisionIds: new Set(), layoutShift: null, insertionDirection: null },
125
+ removeTransition: null,
126
+ announcement: null,
127
+ };
128
+ }
129
+ const placeholdersLayout = getLayoutPlaceholders(transition);
130
+ const collisionRect = getHoveredRect(collisionIds, placeholdersLayout.items);
131
+ const appendPath = transition.operation === "resize" ? appendResizePath : appendMovePath;
132
+ const path = appendPath(transition.path, collisionRect);
133
+ const insertionDirection = (_c = transition.insertionDirection) !== null && _c !== void 0 ? _c : getInsertionDirection(positionOffset);
134
+ const layoutShift = getLayoutShift(transition, path, insertionDirection);
135
+ return {
136
+ transition: { ...transition, collisionIds: new Set(collisionIds), layoutShift, path, insertionDirection },
137
+ removeTransition: null,
138
+ announcement: null,
139
+ };
140
+ }
141
+ function updateTransitionWithKeyboardEvent(state, { direction }) {
142
+ const { transition } = state;
143
+ if (!transition) {
144
+ throw new Error("Invariant violation: no transition.");
145
+ }
146
+ const updateManualItemTransition = (transition, direction) => {
147
+ var _a, _b;
148
+ const xDelta = direction === "left" ? -1 : direction === "right" ? 1 : 0;
149
+ const yDelta = direction === "up" ? -1 : direction === "down" ? 1 : 0;
150
+ const lastPosition = transition.path[transition.path.length - 1];
151
+ const nextPosition = new Position({ x: lastPosition.x + xDelta, y: lastPosition.y + yDelta });
152
+ const nextPath = [...transition.path, nextPosition];
153
+ // Check resizing below min size.
154
+ const layout = (_b = (_a = transition.layoutShift) === null || _a === void 0 ? void 0 : _a.next) !== null && _b !== void 0 ? _b : transition.itemsLayout;
155
+ const layoutItem = layout.items.find((it) => it.id === transition.draggableItem.id);
156
+ const minWidth = getMinColumnSpan(transition.draggableItem, transition.itemsLayout.columns);
157
+ const minHeight = getMinRowSpan(transition.draggableItem);
158
+ if (transition.operation === "resize" &&
159
+ layoutItem &&
160
+ (layoutItem.width + xDelta < minWidth || layoutItem.height + yDelta < minHeight)) {
161
+ return state;
162
+ }
163
+ try {
164
+ const layoutShift = getLayoutShift(transition, nextPath);
165
+ const nextTransition = { ...transition, layoutShift, path: nextPath };
166
+ return {
167
+ transition: nextTransition,
168
+ removeTransition: null,
169
+ announcement: createOperationAnnouncement(nextTransition, direction),
170
+ };
171
+ }
172
+ catch (e) {
173
+ // Can't create next layout because the next path is out of bounds.
174
+ return state;
175
+ }
176
+ };
177
+ switch (direction) {
178
+ case "left":
179
+ return updateManualItemTransition(transition, "left");
180
+ case "right":
181
+ return updateManualItemTransition(transition, "right");
182
+ case "up":
183
+ return updateManualItemTransition(transition, "up");
184
+ case "down":
185
+ return updateManualItemTransition(transition, "down");
186
+ }
187
+ }
188
+ function acquireTransitionItem(state, { position, layoutElement }) {
189
+ const { transition } = state;
190
+ if (!transition) {
191
+ throw new Error("Invariant violation: no transition.");
192
+ }
193
+ const { columns } = transition.itemsLayout;
194
+ const layoutRect = layoutElement.getBoundingClientRect();
195
+ const itemRect = transition.draggableElement.getBoundingClientRect();
196
+ const offset = new Coordinates({ x: itemRect.x - layoutRect.x, y: itemRect.y - layoutRect.y });
197
+ const insertionDirection = getInsertionDirection(offset);
198
+ // Update original insertion position if the item can't fit into the layout by width.
199
+ const width = getDefaultColumnSpan(transition.draggableItem, columns);
200
+ position = new Position({ x: Math.min(columns - width, position.x), y: position.y });
201
+ const path = [...transition.path, position];
202
+ const layoutShift = getLayoutShift(transition, path, insertionDirection);
203
+ // The columnOffset, columnSpan and rowSpan are of no use as of being overridden by the layout shift.
204
+ const acquiredItem = { ...transition.draggableItem, columnOffset: 0, columnSpan: 1, rowSpan: 1 };
205
+ const nextTransition = { ...transition, collisionIds: new Set(), layoutShift, path, acquiredItem };
206
+ return {
207
+ transition: nextTransition,
208
+ removeTransition: null,
209
+ announcement: createOperationAnnouncement(nextTransition, null),
210
+ };
211
+ }
@@ -0,0 +1,10 @@
1
+ import { Direction } from "../../internal/interfaces";
2
+ import { BoardProps, DndActionAnnouncement, Transition, TransitionAnnouncement } from "../interfaces";
3
+ /**
4
+ * Creates an announcement object describing the last user move.
5
+ */
6
+ export declare function createOperationAnnouncement<D>(transition: Transition<D>, direction: null | Direction): null | DndActionAnnouncement;
7
+ /**
8
+ * Applies i18nStrings to the announcement object to produce a string for the live region.
9
+ */
10
+ export declare function announcementToString<D>(announcement: TransitionAnnouncement, items: readonly BoardProps.Item<D>[], i18nStrings: BoardProps.I18nStrings<D>, columns: number): string;
@@ -0,0 +1,98 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { getMinColumnSpan, getMinRowSpan } from "../../internal/utils/layout";
4
+ /**
5
+ * Creates an announcement object describing the last user move.
6
+ */
7
+ export function createOperationAnnouncement(transition, direction) {
8
+ var _a, _b;
9
+ const { operation, layoutShift, itemsLayout } = transition;
10
+ const targetItem = (_a = itemsLayout.items.find((it) => it.id === transition.draggableItem.id)) !== null && _a !== void 0 ? _a : null;
11
+ if (!layoutShift) {
12
+ return null;
13
+ }
14
+ const firstMove = layoutShift.moves[0];
15
+ const targetId = (_b = firstMove === null || firstMove === void 0 ? void 0 : firstMove.itemId) !== null && _b !== void 0 ? _b : targetItem === null || targetItem === void 0 ? void 0 : targetItem.id;
16
+ if (!targetId) {
17
+ return null;
18
+ }
19
+ const itemMoves = layoutShift.moves.filter((m) => m.itemId === targetId);
20
+ const lastItemMove = itemMoves[itemMoves.length - 1];
21
+ const placement = lastItemMove !== null && lastItemMove !== void 0 ? lastItemMove : targetItem;
22
+ const conflicts = new Set(layoutShift.conflicts);
23
+ const disturbed = new Set(layoutShift.moves.map((move) => move.itemId));
24
+ disturbed.delete(targetId);
25
+ return {
26
+ type: "dnd-action",
27
+ item: transition.draggableItem,
28
+ operation,
29
+ placement: {
30
+ x: placement.x,
31
+ y: placement.y,
32
+ width: placement.width,
33
+ height: placement.height,
34
+ },
35
+ direction,
36
+ conflicts,
37
+ disturbed,
38
+ };
39
+ }
40
+ /**
41
+ * Applies i18nStrings to the announcement object to produce a string for the live region.
42
+ */
43
+ export function announcementToString(announcement, items, i18nStrings, columns) {
44
+ if (!announcement) {
45
+ return "";
46
+ }
47
+ const item = announcement.item;
48
+ const toItem = (id) => items.find((it) => (it === null || it === void 0 ? void 0 : it.id) === id);
49
+ const formatDirection = (direction) => {
50
+ if (!direction) {
51
+ return null;
52
+ }
53
+ return direction === "left" || direction === "right" ? "horizontal" : "vertical";
54
+ };
55
+ function createDndActionAnnouncement(announcement) {
56
+ const placement = announcement.placement;
57
+ const direction = formatDirection(announcement.direction);
58
+ const conflicts = [...announcement.conflicts].map(toItem);
59
+ const disturbed = [...announcement.disturbed].map(toItem);
60
+ switch (announcement.operation) {
61
+ case "reorder":
62
+ return i18nStrings.liveAnnouncementDndItemReordered({
63
+ item,
64
+ placement,
65
+ direction: direction,
66
+ conflicts,
67
+ disturbed,
68
+ });
69
+ case "resize":
70
+ return i18nStrings.liveAnnouncementDndItemResized({
71
+ item,
72
+ placement,
73
+ direction: direction,
74
+ isMinimalColumnsReached: placement.width === getMinColumnSpan(item, columns),
75
+ isMinimalRowsReached: placement.height === getMinRowSpan(item),
76
+ conflicts,
77
+ disturbed,
78
+ });
79
+ case "insert":
80
+ return i18nStrings.liveAnnouncementDndItemInserted({ item, placement, conflicts, disturbed });
81
+ }
82
+ }
83
+ function createItemRemovedAnnouncement(announcement) {
84
+ return i18nStrings.liveAnnouncementItemRemoved({ item, disturbed: [...announcement.disturbed].map(toItem) });
85
+ }
86
+ switch (announcement.type) {
87
+ case "dnd-started":
88
+ return i18nStrings.liveAnnouncementDndStarted(announcement.operation);
89
+ case "dnd-action":
90
+ return createDndActionAnnouncement(announcement);
91
+ case "dnd-committed":
92
+ return i18nStrings.liveAnnouncementDndCommitted(announcement.operation);
93
+ case "dnd-discarded":
94
+ return i18nStrings.liveAnnouncementDndDiscarded(announcement.operation);
95
+ case "item-removed":
96
+ return createItemRemovedAnnouncement(announcement);
97
+ }
98
+ }
@@ -0,0 +1,7 @@
1
+ import { GridContext } from "../../internal/grid/interfaces";
2
+ import { GridLayout, Transform } from "../../internal/interfaces";
3
+ import { CommittedMove } from "../../internal/layout-engine/interfaces";
4
+ /**
5
+ * Creates a mapping of between items and transforms to be applied while in transition.
6
+ */
7
+ export declare function createTransforms(grid: GridLayout, moves: readonly CommittedMove[], gridContext: GridContext): Record<string, Transform>;