@khanacademy/wonder-blocks-modal 5.1.11 → 5.1.13

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 (33) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/package.json +10 -10
  3. package/src/components/__tests__/close-button.test.tsx +0 -37
  4. package/src/components/__tests__/focus-trap.test.tsx +0 -100
  5. package/src/components/__tests__/modal-backdrop.test.tsx +0 -241
  6. package/src/components/__tests__/modal-dialog.test.tsx +0 -87
  7. package/src/components/__tests__/modal-header.test.tsx +0 -97
  8. package/src/components/__tests__/modal-launcher.test.tsx +0 -436
  9. package/src/components/__tests__/modal-panel.test.tsx +0 -42
  10. package/src/components/__tests__/one-pane-dialog.test.tsx +0 -87
  11. package/src/components/close-button.tsx +0 -64
  12. package/src/components/focus-trap.tsx +0 -148
  13. package/src/components/modal-backdrop.tsx +0 -172
  14. package/src/components/modal-content.tsx +0 -81
  15. package/src/components/modal-context.ts +0 -16
  16. package/src/components/modal-dialog.tsx +0 -164
  17. package/src/components/modal-footer.tsx +0 -54
  18. package/src/components/modal-header.tsx +0 -194
  19. package/src/components/modal-launcher.tsx +0 -297
  20. package/src/components/modal-panel.tsx +0 -188
  21. package/src/components/one-pane-dialog.tsx +0 -244
  22. package/src/components/scroll-disabler.ts +0 -95
  23. package/src/index.ts +0 -17
  24. package/src/themes/default.ts +0 -36
  25. package/src/themes/khanmigo.ts +0 -16
  26. package/src/themes/themed-modal-dialog.tsx +0 -44
  27. package/src/util/constants.ts +0 -6
  28. package/src/util/find-focusable-nodes.ts +0 -12
  29. package/src/util/maybe-get-portal-mounted-modal-host-element.test.tsx +0 -133
  30. package/src/util/maybe-get-portal-mounted-modal-host-element.ts +0 -35
  31. package/src/util/types.ts +0 -13
  32. package/tsconfig-build.json +0 -20
  33. package/tsconfig-build.tsbuildinfo +0 -1
@@ -1,244 +0,0 @@
1
- import * as React from "react";
2
- import {StyleSheet} from "aphrodite";
3
- import {Breadcrumbs} from "@khanacademy/wonder-blocks-breadcrumbs";
4
- import {MediaLayout} from "@khanacademy/wonder-blocks-layout";
5
- import type {StyleType} from "@khanacademy/wonder-blocks-core";
6
-
7
- import {IDProvider} from "@khanacademy/wonder-blocks-core";
8
- import ModalDialog from "./modal-dialog";
9
- import ModalPanel from "./modal-panel";
10
- import ModalHeader from "./modal-header";
11
-
12
- type Common = {
13
- /**
14
- * The content of the modal, appearing between the titlebar and footer.
15
- */
16
- content: React.ReactNode;
17
- /**
18
- * The title of the modal, appearing in the titlebar.
19
- */
20
- title: string;
21
- /**
22
- * The content of the modal's footer. A great place for buttons!
23
- *
24
- * Content is right-aligned by default. To control alignment yourself,
25
- * provide a container element with 100% width.
26
- */
27
- footer?: React.ReactNode;
28
- /**
29
- * Called when the close button is clicked.
30
- *
31
- * If you're using `ModalLauncher`, you probably shouldn't use this prop!
32
- * Instead, to listen for when the modal closes, add an `onClose` handler
33
- * to the `ModalLauncher`. Doing so will result in a console.warn().
34
- */
35
- onClose?: () => unknown;
36
- /**
37
- * When true, the close button is shown; otherwise, the close button is not shown.
38
- */
39
- closeButtonVisible?: boolean;
40
- /**
41
- * When set, provides a component that can render content above the top of the modal;
42
- * when not set, no additional content is shown above the modal.
43
- * This prop is passed down to the ModalDialog.
44
- */
45
- above?: React.ReactNode;
46
- /**
47
- * When set, provides a component that will render content below the bottom of the modal;
48
- * when not set, no additional content is shown below the modal.
49
- * This prop is passed down to the ModalDialog.
50
- *
51
- * NOTE: Devs can customize this content by rendering the component assigned to this prop with custom styles,
52
- * such as by wrapping it in a View.
53
- */
54
- below?: React.ReactNode;
55
- /**
56
- * When set, overrides the default role value. Default role is "dialog"
57
- * Roles other than dialog and alertdialog aren't appropriate for this
58
- * component
59
- */
60
- role?: "dialog" | "alertdialog";
61
- /**
62
- * Optional custom styles.
63
- */
64
- style?: StyleType;
65
- /**
66
- * Test ID used for e2e testing. This ID will be passed down to the Dialog.
67
- */
68
- testId?: string;
69
- /**
70
- * An optional id parameter for the title. If one is
71
- * not provided, a unique id will be generated.
72
- */
73
- titleId?: string;
74
- /**
75
- * The ID of the content describing this dialog, if applicable.
76
- */
77
- "aria-describedby"?: string;
78
- };
79
-
80
- type WithSubtitle = Common & {
81
- /**
82
- * The subtitle of the modal, appearing in the titlebar, below the title.
83
- */
84
- subtitle: string;
85
- };
86
-
87
- type WithBreadcrumbs = Common & {
88
- /**
89
- * Adds a breadcrumb-trail, appearing in the ModalHeader, above the title.
90
- */
91
- breadcrumbs: React.ReactElement<React.ComponentProps<typeof Breadcrumbs>>;
92
- };
93
-
94
- type Props = Common | WithSubtitle | WithBreadcrumbs;
95
-
96
- type DefaultProps = {
97
- closeButtonVisible: Props["closeButtonVisible"];
98
- };
99
-
100
- /**
101
- * This is the standard layout for most straightforward modal experiences.
102
- *
103
- * The ModalHeader is required, but the ModalFooter is optional.
104
- * The content of the dialog itself is fully customizable, but the
105
- * left/right/top/bottom padding is fixed.
106
- *
107
- * ### Usage
108
- *
109
- * ```jsx
110
- * import {OnePaneDialog} from "@khanacademy/wonder-blocks-modal";
111
- * import {Body} from "@khanacademy/wonder-blocks-typography";
112
- *
113
- * <OnePaneDialog
114
- * title="Some title"
115
- * content={
116
- * <Body>
117
- * {`Lorem ipsum dolor sit amet, consectetur adipiscing
118
- * elit, sed do eiusmod tempor incididunt ut labore et
119
- * dolore magna aliqua. Ut enim ad minim veniam,
120
- * quis nostrud exercitation ullamco laboris nisi ut
121
- * aliquip ex ea commodo consequat. Duis aute irure
122
- * dolor in reprehenderit in voluptate velit esse
123
- * cillum dolore eu fugiat nulla pariatur. Excepteur
124
- * sint occaecat cupidatat non proident, sunt in culpa
125
- * qui officia deserunt mollit anim id est.`}
126
- * </Body>
127
- * }
128
- * />
129
- * ```
130
- */
131
- export default class OnePaneDialog extends React.Component<Props> {
132
- static defaultProps: DefaultProps = {
133
- closeButtonVisible: true,
134
- };
135
-
136
- renderHeader(
137
- uniqueId: string,
138
- ): React.ReactElement<React.ComponentProps<typeof ModalHeader>> {
139
- const {
140
- title,
141
- // @ts-expect-error [FEI-5019] - TS2339 - Property 'breadcrumbs' does not exist on type 'Readonly<Props> & Readonly<{ children?: ReactNode; }>'.
142
- breadcrumbs = undefined,
143
- // @ts-expect-error [FEI-5019] - TS2339 - Property 'subtitle' does not exist on type 'Readonly<Props> & Readonly<{ children?: ReactNode; }>'.
144
- subtitle = undefined,
145
- testId,
146
- } = this.props;
147
-
148
- if (breadcrumbs) {
149
- return (
150
- <ModalHeader
151
- title={title}
152
- breadcrumbs={
153
- breadcrumbs as React.ReactElement<
154
- React.ComponentProps<typeof Breadcrumbs>
155
- >
156
- }
157
- titleId={uniqueId}
158
- testId={testId && `${testId}-header`}
159
- />
160
- );
161
- } else if (subtitle) {
162
- return (
163
- <ModalHeader
164
- title={title}
165
- subtitle={subtitle as string}
166
- titleId={uniqueId}
167
- testId={testId && `${testId}-header`}
168
- />
169
- );
170
- } else {
171
- return (
172
- <ModalHeader
173
- title={title}
174
- titleId={uniqueId}
175
- testId={testId && `${testId}-header`}
176
- />
177
- );
178
- }
179
- }
180
-
181
- render(): React.ReactNode {
182
- const {
183
- onClose,
184
- footer,
185
- content,
186
- above,
187
- below,
188
- style,
189
- closeButtonVisible,
190
- testId,
191
- titleId,
192
- role,
193
- "aria-describedby": ariaDescribedBy,
194
- } = this.props;
195
-
196
- return (
197
- <MediaLayout styleSheets={styleSheets}>
198
- {({styles}) => (
199
- <IDProvider id={titleId} scope="modal">
200
- {(uniqueId) => (
201
- <ModalDialog
202
- style={[styles.dialog, style]}
203
- above={above}
204
- below={below}
205
- testId={testId}
206
- aria-labelledby={uniqueId}
207
- aria-describedby={ariaDescribedBy}
208
- role={role}
209
- >
210
- <ModalPanel
211
- onClose={onClose}
212
- header={this.renderHeader(uniqueId)}
213
- content={content}
214
- footer={footer}
215
- closeButtonVisible={closeButtonVisible}
216
- testId={testId}
217
- />
218
- </ModalDialog>
219
- )}
220
- </IDProvider>
221
- )}
222
- </MediaLayout>
223
- );
224
- }
225
- }
226
-
227
- const styleSheets = {
228
- small: StyleSheet.create({
229
- dialog: {
230
- width: "100%",
231
- height: "100%",
232
- overflow: "hidden",
233
- },
234
- }),
235
-
236
- mdOrLarger: StyleSheet.create({
237
- dialog: {
238
- width: "93.75%",
239
- maxWidth: 576,
240
- height: "81.25%",
241
- maxHeight: 624,
242
- },
243
- }),
244
- } as const;
@@ -1,95 +0,0 @@
1
- /**
2
- * A UI-less component that lets `ModalLauncher` disable page scroll.
3
- *
4
- * The positioning of the modal requires some global page state changed
5
- * unfortunately, and this handles that in an encapsulated way.
6
- *
7
- * NOTE(mdr): This component was copied from webapp. Be wary of sync issues. It
8
- * also doesn't have unit tests, and we haven't added any, since it's a
9
- * relatively stable component that has now been stress-tested lots in prod.
10
- */
11
-
12
- import * as React from "react";
13
-
14
- const needsHackyMobileSafariScrollDisabler = (() => {
15
- if (typeof window === "undefined") {
16
- return false;
17
- }
18
-
19
- const userAgent = window.navigator.userAgent;
20
- return userAgent.indexOf("iPad") > -1 || userAgent.indexOf("iPhone") > -1;
21
- })();
22
-
23
- type Props = Record<any, any>;
24
-
25
- class ScrollDisabler extends React.Component<Props> {
26
- static oldOverflow: string;
27
- static oldPosition: string;
28
- static oldScrollY: number;
29
- static oldWidth: string;
30
- static oldTop: string;
31
-
32
- componentDidMount() {
33
- if (ScrollDisabler.numModalsOpened === 0) {
34
- const body = document.body;
35
- if (!body) {
36
- throw new Error("couldn't find document.body");
37
- }
38
-
39
- // Prevent scrolling of the background, the first time a modal is
40
- // opened.
41
- ScrollDisabler.oldOverflow = body.style.overflow;
42
- ScrollDisabler.oldScrollY = window.scrollY;
43
-
44
- // We need to grab all of the original style properties before we
45
- // modified any of them.
46
- if (needsHackyMobileSafariScrollDisabler) {
47
- ScrollDisabler.oldPosition = body.style.position;
48
- ScrollDisabler.oldWidth = body.style.width;
49
- ScrollDisabler.oldTop = body.style.top;
50
- }
51
-
52
- body.style.overflow = "hidden";
53
-
54
- // On mobile Safari, overflow: hidden is not enough, position:
55
- // fixed is also required. Setting style.top = -scollTop maintains
56
- // the scroll position (without which we'd scroll to the top).
57
- if (needsHackyMobileSafariScrollDisabler) {
58
- body.style.position = "fixed";
59
- body.style.width = "100%";
60
- body.style.top = `${-ScrollDisabler.oldScrollY}px`;
61
- }
62
- }
63
- ScrollDisabler.numModalsOpened++;
64
- }
65
-
66
- componentWillUnmount() {
67
- ScrollDisabler.numModalsOpened--;
68
- if (ScrollDisabler.numModalsOpened === 0) {
69
- const body = document.body;
70
- if (!body) {
71
- throw new Error("couldn't find document.body");
72
- }
73
-
74
- // Reset all values on the closing of the final modal.
75
- body.style.overflow = ScrollDisabler.oldOverflow;
76
- if (needsHackyMobileSafariScrollDisabler) {
77
- body.style.position = ScrollDisabler.oldPosition;
78
- body.style.width = ScrollDisabler.oldWidth;
79
- body.style.top = ScrollDisabler.oldTop;
80
- }
81
-
82
- if (typeof window !== "undefined" && window.scrollTo) {
83
- window.scrollTo(0, ScrollDisabler.oldScrollY);
84
- }
85
- }
86
- }
87
-
88
- static numModalsOpened = 0;
89
-
90
- render(): React.ReactElement | null {
91
- return null;
92
- }
93
- }
94
-
95
- export default ScrollDisabler;
package/src/index.ts DELETED
@@ -1,17 +0,0 @@
1
- import ModalDialog from "./components/modal-dialog";
2
- import ModalFooter from "./components/modal-footer";
3
- import ModalHeader from "./components/modal-header";
4
- import ModalLauncher from "./components/modal-launcher";
5
- import ModalPanel from "./components/modal-panel";
6
- import OnePaneDialog from "./components/one-pane-dialog";
7
- import maybeGetPortalMountedModalHostElement from "./util/maybe-get-portal-mounted-modal-host-element";
8
-
9
- export {
10
- ModalHeader,
11
- ModalFooter,
12
- ModalDialog,
13
- ModalPanel,
14
- ModalLauncher,
15
- OnePaneDialog,
16
- maybeGetPortalMountedModalHostElement,
17
- };
@@ -1,36 +0,0 @@
1
- import * as tokens from "@khanacademy/wonder-blocks-tokens";
2
-
3
- const theme = {
4
- color: {
5
- bg: {
6
- inverse: tokens.color.darkBlue,
7
- },
8
- text: {
9
- inverse: tokens.color.white,
10
- secondary: tokens.color.offBlack64,
11
- },
12
- shadow: {
13
- default: tokens.color.offBlack16,
14
- },
15
- },
16
- border: {
17
- radius: tokens.border.radius.medium_4,
18
- },
19
- spacing: {
20
- dialog: {
21
- small: tokens.spacing.medium_16,
22
- },
23
- panel: {
24
- closeButton: tokens.spacing.medium_16,
25
- footer: tokens.spacing.xLarge_32,
26
- },
27
- header: {
28
- xsmall: tokens.spacing.xSmall_8,
29
- small: tokens.spacing.medium_16,
30
- medium: tokens.spacing.large_24,
31
- large: tokens.spacing.xLarge_32,
32
- },
33
- },
34
- };
35
-
36
- export default theme;
@@ -1,16 +0,0 @@
1
- import {mergeTheme} from "@khanacademy/wonder-blocks-theming";
2
- import {color} from "@khanacademy/wonder-blocks-tokens";
3
- import defaultTheme from "./default";
4
-
5
- /**
6
- * The overrides for the Khanmigo theme.
7
- */
8
- const theme = mergeTheme(defaultTheme, {
9
- color: {
10
- bg: {
11
- inverse: color.eggplant,
12
- },
13
- },
14
- });
15
-
16
- export default theme;
@@ -1,44 +0,0 @@
1
- import * as React from "react";
2
- import {
3
- createThemeContext,
4
- Themes,
5
- ThemeSwitcherContext,
6
- } from "@khanacademy/wonder-blocks-theming";
7
-
8
- import defaultTheme from "./default";
9
- import khanmigoTheme from "./khanmigo";
10
-
11
- type Props = {
12
- children: React.ReactNode;
13
- };
14
-
15
- export type ModalDialogThemeContract = typeof defaultTheme;
16
-
17
- /**
18
- * The themes available to the ModalDialog component.
19
- */
20
- const themes: Themes<ModalDialogThemeContract> = {
21
- default: defaultTheme,
22
- khanmigo: khanmigoTheme,
23
- };
24
-
25
- /**
26
- * The context that provides the theme to the ModalDialog component.
27
- * This is generally consumed via the `useScopedTheme` hook.
28
- */
29
- export const ModalDialogThemeContext = createThemeContext(defaultTheme);
30
-
31
- /**
32
- * ThemeModalDialog is a component that provides a theme to the <ModalDialog/>
33
- * component.
34
- */
35
- export default function ThemeModalDialog(props: Props) {
36
- const currentTheme = React.useContext(ThemeSwitcherContext);
37
-
38
- const theme = themes[currentTheme] || defaultTheme;
39
- return (
40
- <ModalDialogThemeContext.Provider value={theme}>
41
- {props.children}
42
- </ModalDialogThemeContext.Provider>
43
- );
44
- }
@@ -1,6 +0,0 @@
1
- /**
2
- * The attribute used to identify a modal launcher portal.
3
- */
4
- const ModalLauncherPortalAttributeName = "data-modal-launcher-portal";
5
-
6
- export {ModalLauncherPortalAttributeName};
@@ -1,12 +0,0 @@
1
- /**
2
- * List of elements that can be focused
3
- * @see https://www.w3.org/TR/html5/editing.html#can-be-focused
4
- */
5
- const FOCUSABLE_ELEMENTS =
6
- 'a[href], details, input, textarea, select, button:not([aria-label^="Close"])';
7
-
8
- export function findFocusableNodes(
9
- root: HTMLElement | Document,
10
- ): Array<HTMLElement> {
11
- return Array.from(root.querySelectorAll(FOCUSABLE_ELEMENTS));
12
- }
@@ -1,133 +0,0 @@
1
- import * as React from "react";
2
- import * as ReactDOM from "react-dom";
3
- import {render, screen} from "@testing-library/react";
4
- import {userEvent} from "@testing-library/user-event";
5
-
6
- import {ModalLauncherPortalAttributeName} from "./constants";
7
- import maybeGetPortalMountedModalHostElement from "./maybe-get-portal-mounted-modal-host-element";
8
- import ModalLauncher from "../components/modal-launcher";
9
- import OnePaneDialog from "../components/one-pane-dialog";
10
-
11
- describe("maybeGetPortalMountedModalHostElement", () => {
12
- test("when candidate is null, returns null", async () => {
13
- // Arrange
14
- const candidateElement = null;
15
-
16
- // Act
17
- const result = maybeGetPortalMountedModalHostElement(candidateElement);
18
-
19
- // Assert
20
- expect(result).toBeFalsy();
21
- });
22
-
23
- test("when candidate is not hosted in a modal portal, returns null", async () => {
24
- // Arrange
25
- const nodes = (
26
- <div>
27
- <div>
28
- <button>Button</button>
29
- </div>
30
- </div>
31
- );
32
- render(nodes);
33
- const candidateElement = await screen.findByRole("button");
34
-
35
- // Act
36
- const result = maybeGetPortalMountedModalHostElement(candidateElement);
37
-
38
- // Assert
39
- expect(result).toBeFalsy();
40
- expect(candidateElement).not.toBe(null);
41
- });
42
-
43
- describe("hosted in a modal", () => {
44
- test("modal is not mounted in a modal portal, returns null", async () => {
45
- // Arrange
46
- const modalContent = (
47
- <div>
48
- Fake modal things
49
- <div>
50
- <button>Candidate</button>
51
- </div>
52
- </div>
53
- );
54
-
55
- const modal = (
56
- <OnePaneDialog
57
- title="Testing"
58
- footer="Footer"
59
- content={modalContent}
60
- />
61
- );
62
-
63
- render(modal);
64
- const candidateElement = await screen.findByRole("button", {
65
- name: "Candidate",
66
- });
67
-
68
- // Act
69
- const result =
70
- maybeGetPortalMountedModalHostElement(candidateElement);
71
-
72
- // Assert
73
- expect(result).toBeFalsy();
74
- expect(candidateElement).not.toBe(null);
75
- });
76
-
77
- test("modal is mounted in a modal portal, returns host", (done: any) => {
78
- const arrange = async (checkDone: any) => {
79
- // Arrange
80
- const modalContent = (
81
- <div>
82
- Fake modal things
83
- <div>
84
- <span ref={checkDone}>Candidate</span>
85
- </div>
86
- </div>
87
- );
88
- const modal = (
89
- <OnePaneDialog
90
- title="Testing"
91
- footer="Footer"
92
- content={modalContent}
93
- />
94
- );
95
- const launcher = (
96
- <ModalLauncher modal={modal}>
97
- {({openModal}: any) => (
98
- <button onClick={openModal}>Modal</button>
99
- )}
100
- </ModalLauncher>
101
- );
102
- render(launcher);
103
- await userEvent.click(await screen.findByRole("button"));
104
- };
105
-
106
- const actAndAssert = (node: any) => {
107
- if (node) {
108
- // Act
109
- const candidateElement = ReactDOM.findDOMNode(node);
110
- const result =
111
- maybeGetPortalMountedModalHostElement(candidateElement);
112
-
113
- // Assert
114
- expect(result).toBeTruthy();
115
-
116
- const modalPortalElement = result;
117
- expect(modalPortalElement).not.toBe(null);
118
-
119
- const isModalPortal =
120
- modalPortalElement &&
121
- modalPortalElement.hasAttribute(
122
- ModalLauncherPortalAttributeName,
123
- );
124
- expect(isModalPortal).toBeTruthy();
125
-
126
- done();
127
- }
128
- };
129
-
130
- arrange(actAndAssert);
131
- });
132
- });
133
- });
@@ -1,35 +0,0 @@
1
- import {ModalLauncherPortalAttributeName} from "./constants";
2
-
3
- /**
4
- * From a given element, finds its next ancestor that is a modal launcher portal
5
- * element.
6
- * @param {?(Element | Text)} element The element whose ancestors are to be
7
- * walked.
8
- * @returns {?Element} The nearest parent modal launcher portal.
9
- */
10
- function maybeGetNextAncestorModalLauncherPortal(
11
- element?: Element | Text | null,
12
- ) {
13
- let candidateElement = element && element.parentElement;
14
- while (
15
- candidateElement &&
16
- !candidateElement.hasAttribute(ModalLauncherPortalAttributeName)
17
- ) {
18
- candidateElement = candidateElement.parentElement;
19
- }
20
- return candidateElement;
21
- }
22
-
23
- /**
24
- * From a given element, finds the next modal host that has been mounted in
25
- * a modal portal.
26
- * @param {?(Element | Text)} element The element whose ancestors are to be
27
- * walked.
28
- * @returns {?Element} The next portal-mounted modal host element.
29
- * TODO(kevinb): look into getting rid of this
30
- */
31
- export default function maybeGetPortalMountedModalHostElement(
32
- element?: Element | Text | null,
33
- ): Element | null | undefined {
34
- return maybeGetNextAncestorModalLauncherPortal(element);
35
- }
package/src/util/types.ts DELETED
@@ -1,13 +0,0 @@
1
- import * as React from "react";
2
-
3
- /**
4
- * A `ModalElement` is a React element that should either itself be a modal
5
- * (OnePaneDialog), or wrap a modal.
6
- *
7
- * If it's a wrapper component, then its props must be passed along to the child
8
- * modal, because we clone this element and add new props in order to capture
9
- * `onClose` events.
10
- *
11
- * NOTE(kevinb): we include `| null` here because that's what React.FC<> returns.
12
- */
13
- export type ModalElement = React.ReactElement | null;
@@ -1,20 +0,0 @@
1
- {
2
- "exclude": ["dist"],
3
- "extends": "../tsconfig-shared.json",
4
- "compilerOptions": {
5
- "outDir": "./dist",
6
- "rootDir": "src",
7
- },
8
- "references": [
9
- {"path": "../wonder-blocks-breadcrumbs/tsconfig-build.json"},
10
- {"path": "../wonder-blocks-core/tsconfig-build.json"},
11
- {"path": "../wonder-blocks-form/tsconfig-build.json"},
12
- {"path": "../wonder-blocks-icon/tsconfig-build.json"},
13
- {"path": "../wonder-blocks-icon-button/tsconfig-build.json"},
14
- {"path": "../wonder-blocks-layout/tsconfig-build.json"},
15
- {"path": "../wonder-blocks-theming/tsconfig-build.json"},
16
- {"path": "../wonder-blocks-timing/tsconfig-build.json"},
17
- {"path": "../wonder-blocks-tokens/tsconfig-build.json"},
18
- {"path": "../wonder-blocks-typography/tsconfig-build.json"},
19
- ]
20
- }