diff --git a/package.json b/package.json
index 5b18fa5302..51b8032459 100644
--- a/package.json
+++ b/package.json
@@ -166,7 +166,7 @@
{
"path": "lib/components/internal/widget-exports.js",
"brotli": false,
- "limit": "890 kB",
+ "limit": "891 kB",
"ignore": "react-dom"
}
],
diff --git a/src/app-layout/__tests__/runtime-drawers-widgetized.test.tsx b/src/app-layout/__tests__/runtime-drawers-widgetized.test.tsx
index dcc32b9095..7df9ba1aa2 100644
--- a/src/app-layout/__tests__/runtime-drawers-widgetized.test.tsx
+++ b/src/app-layout/__tests__/runtime-drawers-widgetized.test.tsx
@@ -48,17 +48,36 @@ describeEachAppLayout({ themes: ['refresh-toolbar'] }, ({ size }) => {
expect(globalDrawersWrapper.findDrawerById(drawerDefaults.id)!.isActive()).toBe(true);
});
- test('isAppLayoutReady returns true when app layout is ready', () => {
+ test('isAppLayoutReady returns true when app layout is ready', async () => {
expect(awsuiWidgetPlugins.isAppLayoutReady()).toBe(false);
const { rerender } = renderComponent();
expect(awsuiWidgetPlugins.isAppLayoutReady()).toBe(true);
+ await expect(awsuiWidgetPlugins.whenAppLayoutReady()).resolves.toBe(undefined);
rerender(<>>);
expect(awsuiWidgetPlugins.isAppLayoutReady()).toBe(false);
});
+ test('whenAppLayoutReady resolves when app layout is ready', async () => {
+ const readyPromise = awsuiWidgetPlugins.whenAppLayoutReady();
+
+ let isResolved = false;
+ readyPromise.then(() => {
+ isResolved = true;
+ });
+
+ expect(isResolved).toBe(false);
+
+ const { rerender } = renderComponent();
+
+ rerender(<>>);
+
+ await readyPromise;
+ expect(isResolved).toBe(true);
+ });
+
test('adds ai drawer to an already rendered component', () => {
const { globalDrawersWrapper } = renderComponent();
expect(globalDrawersWrapper.findAiDrawerTrigger()).toBeFalsy();
diff --git a/src/internal/plugins/widget.ts b/src/internal/plugins/widget.ts
index a5456b944d..252e44c7b2 100644
--- a/src/internal/plugins/widget.ts
+++ b/src/internal/plugins/widget.ts
@@ -1,4 +1,4 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
export * from './widget/interfaces';
-export { registerLeftDrawer, updateDrawer, isAppLayoutReady } from './widget/internal';
+export { registerLeftDrawer, updateDrawer, isAppLayoutReady, whenAppLayoutReady } from './widget/internal';
diff --git a/src/internal/plugins/widget/internal.ts b/src/internal/plugins/widget/internal.ts
index 77efb3746b..a70122c207 100644
--- a/src/internal/plugins/widget/internal.ts
+++ b/src/internal/plugins/widget/internal.ts
@@ -6,10 +6,12 @@ import { AppLayoutMessage, AppLayoutUpdateMessage, DrawerPayload, RegisterDrawer
const storageKeyMessageHandler = Symbol.for('awsui-widget-api-message-handler');
const storageKeyInitialMessages = Symbol.for('awsui-widget-api-initial-messages');
+const storageKeyReadyDeferCallbacks = Symbol.for('awsui-widget-api-ready-defer');
interface WindowWithApi extends Window {
[storageKeyMessageHandler]: AppLayoutHandler | undefined;
[storageKeyInitialMessages]: Array | undefined;
+ [storageKeyReadyDeferCallbacks]: Array<(value?: unknown) => void> | undefined;
}
type AppLayoutHandler = (event: AppLayoutMessage) => void;
@@ -33,6 +35,8 @@ export function registerAppLayoutHandler(handler: AppLayoutHandler) {
reportRuntimeApiWarning('AppLayoutWidget', 'Double registration attempt, the old handler will be overridden');
}
win[storageKeyMessageHandler] = handler;
+ win[storageKeyReadyDeferCallbacks]?.forEach(fn => fn());
+ win[storageKeyReadyDeferCallbacks] = [];
return () => {
win[storageKeyMessageHandler] = undefined;
};
@@ -49,6 +53,18 @@ export function isAppLayoutReady() {
return !!getAppLayoutMessageHandler();
}
+/**
+ * Returns a promise that resolves once the app layout has loaded
+ */
+export function whenAppLayoutReady() {
+ if (isAppLayoutReady()) {
+ return Promise.resolve();
+ }
+ const win = getWindow();
+ win[storageKeyReadyDeferCallbacks] = win[storageKeyReadyDeferCallbacks] ?? [];
+ return new Promise(resolve => win[storageKeyReadyDeferCallbacks]?.push(resolve));
+}
+
/**
* Registers a new runtime drawer to app layout
* @param drawer