diff --git a/.buildkite/scripts/steps/storybooks/build_and_upload.ts b/.buildkite/scripts/steps/storybooks/build_and_upload.ts
index b1135490a2023..52aaa7e087a09 100644
--- a/.buildkite/scripts/steps/storybooks/build_and_upload.ts
+++ b/.buildkite/scripts/steps/storybooks/build_and_upload.ts
@@ -26,7 +26,6 @@ const STORYBOOKS = [
'dashboard_enhanced',
'dashboard',
'data',
- 'embeddable',
'esql_editor',
'expression_error',
'expression_image',
diff --git a/src/dev/storybook/aliases.ts b/src/dev/storybook/aliases.ts
index c89df73f1b877..1d3ec990948a9 100644
--- a/src/dev/storybook/aliases.ts
+++ b/src/dev/storybook/aliases.ts
@@ -29,7 +29,6 @@ export const storybookAliases = {
dashboard: 'src/plugins/dashboard/.storybook',
data: 'src/plugins/data/.storybook',
discover: 'src/plugins/discover/.storybook',
- embeddable: 'src/plugins/embeddable/.storybook',
esql_ast_inspector: 'examples/esql_ast_inspector/.storybook',
es_ui_shared: 'src/plugins/es_ui_shared/.storybook',
expandable_flyout: 'packages/kbn-expandable-flyout/.storybook',
diff --git a/src/plugins/embeddable/.storybook/decorator.tsx b/src/plugins/embeddable/.storybook/decorator.tsx
deleted file mode 100644
index 936050352d22a..0000000000000
--- a/src/plugins/embeddable/.storybook/decorator.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import React from 'react';
-
-import { DecoratorFn } from '@storybook/react';
-import { I18nProvider } from '@kbn/i18n-react';
-import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common';
-
-export const servicesContextDecorator: DecoratorFn = (story, { globals }) => {
- const darkMode = ['v8.dark', 'v7.dark'].includes(globals.euiTheme);
-
- return (
-
- {story()}
-
- );
-};
diff --git a/src/plugins/embeddable/.storybook/main.ts b/src/plugins/embeddable/.storybook/main.ts
deleted file mode 100644
index 02a7d1b2dd5e3..0000000000000
--- a/src/plugins/embeddable/.storybook/main.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-// eslint-disable-next-line import/no-default-export
-export { defaultConfig as default } from '@kbn/storybook';
diff --git a/src/plugins/embeddable/.storybook/manager.ts b/src/plugins/embeddable/.storybook/manager.ts
deleted file mode 100644
index b28080883ec14..0000000000000
--- a/src/plugins/embeddable/.storybook/manager.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import { addons } from '@storybook/addons';
-import { create } from '@storybook/theming';
-import { PANEL_ID } from '@storybook/addon-actions';
-
-addons.setConfig({
- theme: create({
- base: 'light',
- brandTitle: 'Kibana Embeddable Storybook',
- brandUrl: 'https://github.com/elastic/kibana/tree/main/src/plugins/embeddable',
- }),
- showPanel: true.valueOf,
- selectedPanel: PANEL_ID,
-});
diff --git a/src/plugins/embeddable/.storybook/preview.tsx b/src/plugins/embeddable/.storybook/preview.tsx
deleted file mode 100644
index 4ddf9e5080d29..0000000000000
--- a/src/plugins/embeddable/.storybook/preview.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import React from 'react';
-import { addDecorator } from '@storybook/react';
-import { Title, Subtitle, Description, Primary, Stories } from '@storybook/addon-docs/blocks';
-
-import { servicesContextDecorator } from './decorator';
-
-addDecorator(servicesContextDecorator);
-
-export const parameters = {
- docs: {
- page: () => (
- <>
-
-
-
-
-
- >
- ),
- },
-};
diff --git a/src/plugins/embeddable/public/__stories__/embeddable_panel.stories.tsx b/src/plugins/embeddable/public/__stories__/embeddable_panel.stories.tsx
deleted file mode 100644
index bcb0af1cf9064..0000000000000
--- a/src/plugins/embeddable/public/__stories__/embeddable_panel.stories.tsx
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import React, {
- forwardRef,
- useCallback,
- useContext,
- useEffect,
- useImperativeHandle,
- useMemo,
- useRef,
-} from 'react';
-import { ReplaySubject } from 'rxjs';
-import { ThemeContext } from '@emotion/react';
-import { DecoratorFn, Meta } from '@storybook/react';
-import { action } from '@storybook/addon-actions';
-import { EuiEmptyPrompt, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
-import { CoreTheme } from '@kbn/core-theme-browser';
-import type { Action } from '@kbn/ui-actions-plugin/public';
-
-import { CONTEXT_MENU_TRIGGER, EmbeddablePanel, PANEL_BADGE_TRIGGER, ViewMode } from '..';
-import { actions } from '../store';
-import { HelloWorldEmbeddable } from './hello_world_embeddable';
-
-const layout: DecoratorFn = (story) => {
- return (
-
-
- {story()}
-
-
- );
-};
-
-export default {
- title: 'components/EmbeddablePanel',
- argTypes: {
- hideHeader: {
- name: 'Hide Header',
- control: { type: 'boolean' },
- },
- loading: {
- name: 'Loading',
- control: { type: 'boolean' },
- },
- showShadow: {
- name: 'Show Shadow',
- control: { type: 'boolean' },
- },
- title: {
- name: 'Title',
- control: { type: 'text' },
- },
- viewMode: {
- name: 'View Mode',
- control: { type: 'boolean' },
- },
- },
- decorators: [layout],
-} as Meta;
-
-interface HelloWorldEmbeddablePanelProps {
- getActions?(type: string): Promise;
- hideHeader: boolean;
- loading: boolean;
- showShadow: boolean;
- showBorder: boolean;
- title: string;
- viewMode: boolean;
-}
-
-const HelloWorldEmbeddablePanel = forwardRef<
- { embeddable: HelloWorldEmbeddable },
- HelloWorldEmbeddablePanelProps
->(
- (
- {
- getActions,
- hideHeader,
- loading,
- showShadow,
- showBorder,
- title,
- viewMode,
- }: HelloWorldEmbeddablePanelProps,
- ref
- ) => {
- const embeddable = useMemo(() => new HelloWorldEmbeddable({ id: `${Math.random()}` }, {}), []);
- const theme$ = useMemo(() => new ReplaySubject(1), []);
- const theme = useContext(ThemeContext) as CoreTheme;
-
- useEffect(() => theme$.next(theme), [theme$, theme]);
- useEffect(() => {
- embeddable.store.dispatch(actions.input.setTitle(title));
- }, [embeddable.store, title]);
- useEffect(() => {
- embeddable.store.dispatch(
- actions.input.setViewMode(viewMode ? ViewMode.VIEW : ViewMode.EDIT)
- );
- }, [embeddable.store, viewMode]);
- useEffect(
- () => void embeddable.store.dispatch(actions.output.setLoading(loading)),
- [embeddable, loading]
- );
- useImperativeHandle(ref, () => ({ embeddable }));
-
- return (
-
- );
- }
-);
-
-export const Default = HelloWorldEmbeddablePanel as Meta;
-
-Default.args = {
- hideHeader: false,
- loading: false,
- showShadow: false,
- showBorder: false,
- title: 'Hello World',
- viewMode: true,
-};
-
-interface DefaultWithBadgesProps extends HelloWorldEmbeddablePanelProps {
- badges: string[];
-}
-
-export function DefaultWithBadges({ badges, ...props }: DefaultWithBadgesProps) {
- const getActions = useCallback(
- async (type: string) => {
- switch (type) {
- case PANEL_BADGE_TRIGGER:
- return (
- badges?.map((badge, id) => ({
- execute: async (...args) => action(`onClick(${badge})`)(...args),
- getDisplayName: () => badge,
- getIconType: () => ['help', 'search', undefined][id % 3],
- id: `${id}`,
- isCompatible: async () => true,
- type: '',
- })) ?? []
- );
- default:
- return [];
- }
- },
- [badges]
- );
- const ref = useRef>(null);
-
- useEffect(
- () =>
- void ref.current?.embeddable.store.dispatch(
- actions.input.setLastReloadRequestTime(new Date().getMilliseconds())
- ),
- [getActions]
- );
-
- return ;
-}
-
-DefaultWithBadges.args = {
- ...Default.args,
- badges: ['Help', 'Search', 'Something'],
-};
-
-DefaultWithBadges.argTypes = {
- badges: { name: 'Badges' },
-};
-
-interface DefaultWithContextMenuProps extends HelloWorldEmbeddablePanelProps {
- items: string[];
-}
-
-export function DefaultWithContextMenu({ items, ...props }: DefaultWithContextMenuProps) {
- const getActions = useCallback(
- async (type: string) => {
- switch (type) {
- case CONTEXT_MENU_TRIGGER:
- return (
- items?.map((item, id) => ({
- execute: async (...args) => action(`onClick(${item})`)(...args),
- getDisplayName: () => item,
- getIconType: () => ['help', 'search', undefined][id % 3],
- id: `${id}`,
- isCompatible: async () => true,
- type: '',
- })) ?? []
- );
- default:
- return [];
- }
- },
- [items]
- );
- const ref = useRef>(null);
-
- useEffect(
- () =>
- void ref.current?.embeddable.store.dispatch(
- actions.input.setLastReloadRequestTime(new Date().getMilliseconds())
- ),
- [getActions]
- );
-
- return ;
-}
-
-DefaultWithContextMenu.args = {
- ...Default.args,
- items: ['Help', 'Search', 'Something'],
-};
-
-DefaultWithContextMenu.argTypes = {
- items: { name: 'Context Menu Items' },
-};
-
-interface DefaultWithErrorProps extends HelloWorldEmbeddablePanelProps {
- message: string;
-}
-
-export function DefaultWithError({ message, ...props }: DefaultWithErrorProps) {
- const ref = useRef>(null);
-
- useEffect(
- () => void ref.current?.embeddable.store.dispatch(actions.output.setError(new Error(message))),
- [message]
- );
-
- return ;
-}
-
-DefaultWithError.args = {
- ...Default.args,
- message: 'Something went wrong',
-};
-
-DefaultWithError.argTypes = {
- message: { name: 'Message', control: { type: 'text' } },
-};
-
-export function DefaultWithCustomError({ message, ...props }: DefaultWithErrorProps) {
- const ref = useRef>(null);
-
- useEffect(() => {
- if (ref.current) {
- ref.current.embeddable.catchError = (error) => {
- return ;
- };
- }
- }, []);
- useEffect(
- () => void ref.current?.embeddable.store.dispatch(actions.output.setError(new Error(message))),
- [message]
- );
-
- return ;
-}
-
-DefaultWithCustomError.args = {
- ...Default.args,
- message: 'Something went wrong',
-};
-
-DefaultWithCustomError.argTypes = {
- message: { name: 'Message', control: { type: 'text' } },
-};
diff --git a/src/plugins/embeddable/public/__stories__/embeddable_root.stories.tsx b/src/plugins/embeddable/public/__stories__/embeddable_root.stories.tsx
deleted file mode 100644
index 8a6addb0a3685..0000000000000
--- a/src/plugins/embeddable/public/__stories__/embeddable_root.stories.tsx
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import React, { useMemo } from 'react';
-import { DecoratorFn, Meta } from '@storybook/react';
-import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
-
-import { EmbeddableInput, EmbeddableRoot } from '..';
-import { HelloWorldEmbeddable } from './hello_world_embeddable';
-
-const layout: DecoratorFn = (story) => {
- return (
-
-
- {story()}
-
-
- );
-};
-
-export default {
- title: 'components/EmbeddableRoot',
- argTypes: {
- loading: {
- name: 'Loading',
- control: { type: 'boolean' },
- },
- title: {
- name: 'Title',
- control: { type: 'text' },
- },
- },
- decorators: [layout],
-} as Meta;
-
-interface DefaultProps {
- error?: string;
- loading?: boolean;
- title: string;
-}
-
-export function Default({ title, ...props }: DefaultProps) {
- const id = useMemo(() => `${Math.random()}`, []);
- const input = useMemo(
- () => ({
- id,
- title,
- lastReloadRequestTime: new Date().getMilliseconds(),
- }),
- [id, title]
- );
- // eslint-disable-next-line react-hooks/exhaustive-deps
- const embeddable = useMemo(() => new HelloWorldEmbeddable(input, {}), []);
-
- return ;
-}
-
-Default.args = {
- title: 'Hello World',
- loading: false,
-};
-
-export const DefaultWithError = Default.bind({}) as Meta;
-
-DefaultWithError.args = {
- ...Default.args,
- error: 'Something went wrong',
-};
-
-DefaultWithError.argTypes = {
- error: { name: 'Error', control: { type: 'text' } },
-};
diff --git a/src/plugins/embeddable/public/__stories__/error_embeddable.stories.tsx b/src/plugins/embeddable/public/__stories__/error_embeddable.stories.tsx
deleted file mode 100644
index ebd388e3d31c2..0000000000000
--- a/src/plugins/embeddable/public/__stories__/error_embeddable.stories.tsx
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import { useEffect, useMemo } from 'react';
-import { Meta } from '@storybook/react';
-
-import { ErrorEmbeddable } from '..';
-
-export default {
- title: 'components/ErrorEmbeddable',
- argTypes: {
- message: {
- name: 'Message',
- control: { type: 'text' },
- },
- },
-} as Meta;
-
-interface ErrorEmbeddableWrapperProps {
- message: string;
-}
-
-function ErrorEmbeddableWrapper({ message }: ErrorEmbeddableWrapperProps) {
- const embeddable = useMemo(
- () => new ErrorEmbeddable(message, { id: `${Math.random()}` }, undefined),
- [message]
- );
- useEffect(() => () => embeddable.destroy(), [embeddable]);
-
- return embeddable.render();
-}
-
-export const Default = ErrorEmbeddableWrapper as Meta;
-
-Default.args = {
- message: 'Something went wrong',
-};
diff --git a/src/plugins/embeddable/public/__stories__/hello_world_embeddable.tsx b/src/plugins/embeddable/public/__stories__/hello_world_embeddable.tsx
deleted file mode 100644
index ef19adedde943..0000000000000
--- a/src/plugins/embeddable/public/__stories__/hello_world_embeddable.tsx
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import React from 'react';
-import { connect, Provider } from 'react-redux';
-import { EuiEmptyPrompt } from '@elastic/eui';
-import { Embeddable } from '..';
-import { createStore, State } from '../store';
-
-export class HelloWorldEmbeddable extends Embeddable {
- // eslint-disable-next-line @kbn/eslint/no_this_in_property_initializers
- readonly store = createStore(this);
-
- readonly type = 'hello-world';
-
- reload() {}
-
- render() {
- const HelloWorld = connect((state: State) => ({ body: state.input.title }))(EuiEmptyPrompt);
-
- return (
-
-
-
- );
- }
-}
diff --git a/src/plugins/embeddable/public/index.ts b/src/plugins/embeddable/public/index.ts
index 25a25b2447146..19d3bd76c1a77 100644
--- a/src/plugins/embeddable/public/index.ts
+++ b/src/plugins/embeddable/public/index.ts
@@ -22,8 +22,6 @@ export {
defaultEmbeddableFactoryProvider,
Embeddable,
EmbeddableFactoryNotFoundError,
- EmbeddableRenderer,
- EmbeddableRoot,
EmbeddableStateTransfer,
ErrorEmbeddable,
genericEmbeddableInputIsEqual,
@@ -52,7 +50,6 @@ export {
SELECT_RANGE_TRIGGER,
shouldFetch$,
shouldRefreshFilterCompareOptions,
- useEmbeddableFactory,
VALUE_CLICK_TRIGGER,
ViewMode,
withEmbeddableSubscription,
@@ -72,7 +69,6 @@ export type {
EmbeddableInstanceConfiguration,
EmbeddableOutput,
EmbeddablePackageState,
- EmbeddableRendererProps,
FilterableEmbeddable,
IContainer,
IEmbeddable,
diff --git a/src/plugins/embeddable/public/lib/embeddables/embeddable_renderer.test.tsx b/src/plugins/embeddable/public/lib/embeddables/embeddable_renderer.test.tsx
deleted file mode 100644
index a7a6fab89973c..0000000000000
--- a/src/plugins/embeddable/public/lib/embeddables/embeddable_renderer.test.tsx
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import React from 'react';
-import { waitFor } from '@testing-library/react';
-import { render, renderHook } from '@testing-library/react';
-import {
- HelloWorldEmbeddable,
- HelloWorldEmbeddableFactoryDefinition,
- HELLO_WORLD_EMBEDDABLE,
-} from '../../tests/fixtures';
-import { EmbeddableRenderer, useEmbeddableFactory } from './embeddable_renderer';
-import { embeddablePluginMock } from '../../mocks';
-
-describe('useEmbeddableFactory', () => {
- it('should update upstream value changes', async () => {
- const { setup, doStart } = embeddablePluginMock.createInstance();
- const getFactory = setup.registerEmbeddableFactory(
- HELLO_WORLD_EMBEDDABLE,
- new HelloWorldEmbeddableFactoryDefinition()
- );
- doStart();
-
- const { result } = renderHook(() =>
- useEmbeddableFactory({ factory: getFactory(), input: { id: 'hello' } })
- );
-
- const [, loading] = result.current;
-
- expect(loading).toBe(true);
-
- await waitFor(() => {
- const [embeddable] = result.current;
- expect(embeddable).toBeDefined();
- });
- });
-});
-
-describe('', () => {
- test('Render embeddable', () => {
- const embeddable = new HelloWorldEmbeddable({ id: 'hello' });
- const { getByTestId } = render();
- expect(getByTestId('helloWorldEmbeddable')).toBeInTheDocument();
- });
-
- test('Render factory', async () => {
- const { setup, doStart } = embeddablePluginMock.createInstance();
- const getFactory = setup.registerEmbeddableFactory(
- HELLO_WORLD_EMBEDDABLE,
- new HelloWorldEmbeddableFactoryDefinition()
- );
- doStart();
-
- const { getByTestId, queryByTestId } = render(
-
- );
- expect(getByTestId('embedSpinner')).toBeInTheDocument();
- await waitFor(() => !queryByTestId('embedSpinner')); // wait until spinner disappears
- expect(getByTestId('helloWorldEmbeddable')).toBeInTheDocument();
- });
-});
diff --git a/src/plugins/embeddable/public/lib/embeddables/embeddable_renderer.tsx b/src/plugins/embeddable/public/lib/embeddables/embeddable_renderer.tsx
deleted file mode 100644
index 14a064827e260..0000000000000
--- a/src/plugins/embeddable/public/lib/embeddables/embeddable_renderer.tsx
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import React, { useEffect, useState } from 'react';
-import { EmbeddableInput, IEmbeddable } from './i_embeddable';
-import { EmbeddableRoot } from './embeddable_root';
-import { EmbeddableFactory } from './embeddable_factory';
-import { ErrorEmbeddable } from './error_embeddable';
-import { isErrorEmbeddable } from './is_error_embeddable';
-
-/**
- * This type is a publicly exposed props of {@link EmbeddableRenderer}
- * Union is used to validate that or factory or embeddable is passed in, but it can't be both simultaneously
- * In case when embeddable is passed in, input is optional, because there is already an input inside of embeddable object
- * In case when factory is used, then input is required, because it will be used as initial input to create an embeddable object
- */
-export type EmbeddableRendererProps =
- | EmbeddableRendererPropsWithEmbeddable
- | EmbeddableRendererWithFactory;
-
-interface EmbeddableRendererPropsWithEmbeddable {
- input?: I;
- onInputUpdated?: (newInput: I) => void;
- embeddable: IEmbeddable;
-}
-
-interface EmbeddableRendererWithFactory {
- input: I;
- onInputUpdated?: (newInput: I) => void;
- factory: EmbeddableFactory;
-}
-
-function isWithFactory(
- props: EmbeddableRendererProps
-): props is EmbeddableRendererWithFactory {
- return 'factory' in props;
-}
-
-export function useEmbeddableFactory({
- input,
- factory,
- onInputUpdated,
-}: EmbeddableRendererWithFactory) {
- const [embeddable, setEmbeddable] = useState | ErrorEmbeddable | undefined>(
- undefined
- );
- const [loading, setLoading] = useState(false);
- const [error, setError] = useState();
- const latestInput = React.useRef(input);
- useEffect(() => {
- latestInput.current = input;
- }, [input]);
-
- useEffect(() => {
- let canceled = false;
-
- // keeping track of embeddables created by this component to be able to destroy them
- let createdEmbeddableRef: IEmbeddable | ErrorEmbeddable | undefined;
- setEmbeddable(undefined);
- setLoading(true);
- factory
- .create(latestInput.current!)
- .then((createdEmbeddable) => {
- if (canceled) {
- if (createdEmbeddable) {
- createdEmbeddable.destroy();
- }
- } else {
- createdEmbeddableRef = createdEmbeddable;
- setEmbeddable(createdEmbeddable);
- }
- })
- .catch((err) => {
- if (canceled) return;
- setError(err?.message);
- })
- .finally(() => {
- if (canceled) return;
- setLoading(false);
- });
-
- return () => {
- canceled = true;
- if (createdEmbeddableRef) {
- createdEmbeddableRef.destroy();
- }
- };
- }, [factory]);
-
- useEffect(() => {
- if (!embeddable) return;
- if (isErrorEmbeddable(embeddable)) return;
- if (!onInputUpdated) return;
- const sub = embeddable.getInput$().subscribe((newInput) => {
- onInputUpdated(newInput);
- });
- return () => {
- sub.unsubscribe();
- };
- }, [embeddable, onInputUpdated]);
-
- return [embeddable, loading, error] as const;
-}
-
-/**
- * Helper react component to render an embeddable
- * Can be used if you have an embeddable object or an embeddable factory
- * Supports updating input by passing `input` prop
- *
- * @remarks
- * This component shouldn't be used inside an embeddable container to render embeddable children
- * because children may lose inherited input, here is why:
- *
- * When passing `input` inside a prop, internally there is a call:
- *
- * ```ts
- * embeddable.updateInput(input);
- * ```
- * If you are simply rendering an embeddable, it's no problem.
- *
- * However when you are dealing with containers,
- * you want to be sure to only pass into updateInput the actual state that changed.
- * This is because calling child.updateInput({ foo }) will make foo explicit state.
- * It cannot be inherited from it's parent.
- *
- * For example, on a dashboard, the time range is inherited by all children,
- * unless they had their time range set explicitly.
- * This is how "per panel time range" works.
- * That action calls embeddable.updateInput({ timeRange }),
- * and the time range will no longer be inherited from the container.
- *
- * see: https://github.com/elastic/kibana/pull/67783#discussion_r435447657 for more details.
- * refer to: examples/embeddable_explorer for examples with correct usage of this component.
- *
- * @public
- * @param props - {@link EmbeddableRendererProps}
- */
-export const EmbeddableRenderer = (
- props: EmbeddableRendererProps
-) => {
- if (isWithFactory(props)) {
- return ;
- }
- return ;
-};
-
-//
-const EmbeddableByFactory = ({
- factory,
- input,
- onInputUpdated,
-}: EmbeddableRendererWithFactory) => {
- const [embeddable, loading, error] = useEmbeddableFactory({
- factory,
- input,
- onInputUpdated,
- });
- return ;
-};
diff --git a/src/plugins/embeddable/public/lib/embeddables/embeddable_root.test.tsx b/src/plugins/embeddable/public/lib/embeddables/embeddable_root.test.tsx
deleted file mode 100644
index 65e23b01f0b8c..0000000000000
--- a/src/plugins/embeddable/public/lib/embeddables/embeddable_root.test.tsx
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import React from 'react';
-import { HelloWorldEmbeddable, HelloWorldEmbeddableReact } from '../../tests/fixtures';
-import { EmbeddableRoot } from './embeddable_root';
-import { mount } from 'enzyme';
-import { findTestSubject } from '@elastic/eui/lib/test';
-
-test('EmbeddableRoot renders an embeddable', async () => {
- const embeddable = new HelloWorldEmbeddable({ id: 'hello' });
- const component = mount();
- // Due to the way embeddables mount themselves on the dom node, they are not forced to be
- // react components, and hence, we can't use the usual
- // findTestSubject.
- expect(
- component.getDOMNode().querySelectorAll('[data-test-subj="helloWorldEmbeddable"]').length
- ).toBe(1);
- expect(findTestSubject(component, 'embedSpinner').length).toBe(0);
- expect(findTestSubject(component, 'embedError').length).toBe(0);
-});
-
-test('EmbeddableRoot renders a React-based embeddable', async () => {
- const embeddable = new HelloWorldEmbeddableReact({ id: 'hello' });
- const component = mount();
-
- expect(component.find('[data-test-subj="helloWorldEmbeddable"]')).toHaveLength(1);
-});
-
-test('EmbeddableRoot updates input', async () => {
- const embeddable = new HelloWorldEmbeddable({ id: 'hello' });
- const component = mount();
- const spy = jest.spyOn(embeddable, 'updateInput');
- const newInput = { id: 'hello', something: 'new' };
- component.setProps({ embeddable, input: newInput });
- expect(spy).toHaveBeenCalledWith(newInput);
-});
-
-test('EmbeddableRoot renders a spinner if loading an no embeddable given', async () => {
- const component = mount();
- // Due to the way embeddables mount themselves on the dom node, they are not forced to be
- // react components, and hence, we can't use the usual
- // findTestSubject.
- expect(findTestSubject(component, 'embedSpinner').length).toBe(1);
- expect(findTestSubject(component, 'embedError').length).toBe(0);
-});
-
-test('EmbeddableRoot renders an error if given with no embeddable', async () => {
- const component = mount();
- // Due to the way embeddables mount themselves on the dom node, they are not forced to be
- // react components, and hence, we can't use the usual
- // findTestSubject.
- expect(findTestSubject(component, 'embedError').length).toBe(1);
- expect(findTestSubject(component, 'embedSpinner').length).toBe(0);
-});
diff --git a/src/plugins/embeddable/public/lib/embeddables/embeddable_root.tsx b/src/plugins/embeddable/public/lib/embeddables/embeddable_root.tsx
deleted file mode 100644
index 30d795aa8b42a..0000000000000
--- a/src/plugins/embeddable/public/lib/embeddables/embeddable_root.tsx
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import React, { ReactNode, useCallback, useEffect, useRef, useState } from 'react';
-import { EuiLoadingSpinner } from '@elastic/eui';
-import { EuiText } from '@elastic/eui';
-import { isPromise } from '@kbn/std';
-import { MaybePromise } from '@kbn/utility-types';
-import { EmbeddableInput, EmbeddableOutput, IEmbeddable } from './i_embeddable';
-import { EmbeddableErrorHandler } from './embeddable_error_handler';
-
-interface Props {
- embeddable?: IEmbeddable>;
- loading?: boolean;
- error?: string;
- input?: EmbeddableInput;
-}
-
-export const EmbeddableRoot: React.FC = ({ embeddable, loading, error, input }) => {
- const [node, setNode] = useState();
- const [embeddableHasMounted, setEmbeddableHasMounted] = useState(false);
- const rootRef = useRef(null);
-
- const updateNode = useCallback((newNode: MaybePromise) => {
- if (isPromise(newNode)) {
- newNode.then(updateNode);
- return;
- }
-
- setNode(newNode);
- }, []);
-
- useEffect(() => {
- if (!rootRef.current || !embeddable) {
- return;
- }
-
- setEmbeddableHasMounted(true);
- updateNode(embeddable.render(rootRef.current) ?? undefined);
- embeddable.render(rootRef.current);
- }, [updateNode, embeddable]);
-
- useEffect(() => {
- if (input && embeddable && embeddableHasMounted) {
- embeddable.updateInput(input);
- }
- }, [input, embeddable, embeddableHasMounted]);
-
- return (
- <>
- {node}
- {loading && }
- {error && (
-
- {({ message }) => {message}}
-
- )}
- >
- );
-};
diff --git a/src/plugins/embeddable/public/lib/embeddables/error_embeddable.test.tsx b/src/plugins/embeddable/public/lib/embeddables/error_embeddable.test.tsx
deleted file mode 100644
index 77ed3a1bc2f1d..0000000000000
--- a/src/plugins/embeddable/public/lib/embeddables/error_embeddable.test.tsx
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the "Elastic License
- * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
- * Public License v 1"; you may not use this file except in compliance with, at
- * your election, the "Elastic License 2.0", the "GNU Affero General Public
- * License v3.0 only", or the "Server Side Public License, v 1".
- */
-
-import React from 'react';
-import { setStubKibanaServices as setPresentationPanelMocks } from '@kbn/presentation-panel-plugin/public/mocks';
-import { waitFor, render } from '@testing-library/react';
-import { ErrorEmbeddable } from './error_embeddable';
-import { EmbeddableRoot } from './embeddable_root';
-
-test('ErrorEmbeddable renders an embeddable', async () => {
- setPresentationPanelMocks();
- const embeddable = new ErrorEmbeddable('some error occurred', { id: '123', title: 'Error' });
- const { getByTestId, getByText } = render();
-
- expect(getByTestId('embeddableStackError')).toBeVisible();
- await waitFor(() => getByTestId('errorMessageMarkdown')); // wait for lazy markdown component
- expect(getByText(/some error occurred/i)).toBeVisible();
-});
-
-test('ErrorEmbeddable renders an embeddable with markdown message', async () => {
- setPresentationPanelMocks();
- const error = '[some link](http://localhost:5601/takeMeThere)';
- const embeddable = new ErrorEmbeddable(error, { id: '123', title: 'Error' });
- const { getByTestId, getByText } = render();
-
- expect(getByTestId('embeddableStackError')).toBeVisible();
- await waitFor(() => getByTestId('errorMessageMarkdown')); // wait for lazy markdown component
- expect(getByText(/some link/i)).toMatchInlineSnapshot(`
-
- some link
-
-
- (external, opens in a new tab or window)
-
-
- `);
-});
diff --git a/src/plugins/embeddable/public/lib/embeddables/index.ts b/src/plugins/embeddable/public/lib/embeddables/index.ts
index 9e606efacaf13..92cd977d1f3d4 100644
--- a/src/plugins/embeddable/public/lib/embeddables/index.ts
+++ b/src/plugins/embeddable/public/lib/embeddables/index.ts
@@ -14,9 +14,6 @@ export { Embeddable } from './embeddable';
export { EmbeddableErrorHandler } from './embeddable_error_handler';
export * from './embeddable_factory';
export * from './embeddable_factory_definition';
-export { EmbeddableRenderer, useEmbeddableFactory } from './embeddable_renderer';
-export type { EmbeddableRendererProps } from './embeddable_renderer';
-export { EmbeddableRoot } from './embeddable_root';
export { ErrorEmbeddable } from './error_embeddable';
export { isErrorEmbeddable } from './is_error_embeddable';
export { isEmbeddable } from './is_embeddable';
diff --git a/src/plugins/embeddable/tsconfig.json b/src/plugins/embeddable/tsconfig.json
index 161b35bc716ea..c3b5925e33233 100644
--- a/src/plugins/embeddable/tsconfig.json
+++ b/src/plugins/embeddable/tsconfig.json
@@ -3,19 +3,16 @@
"compilerOptions": {
"outDir": "target/types"
},
- "include": ["*.ts", ".storybook/**/*", "common/**/*", "public/**/*", "server/**/*"],
+ "include": ["*.ts", "common/**/*", "public/**/*", "server/**/*"],
"kbn_references": [
"@kbn/core",
"@kbn/inspector-plugin",
"@kbn/saved-objects-plugin",
"@kbn/kibana-utils-plugin",
- "@kbn/kibana-react-plugin",
"@kbn/ui-actions-plugin",
"@kbn/i18n-react",
- "@kbn/storybook",
"@kbn/utility-types",
"@kbn/es-query",
- "@kbn/core-theme-browser",
"@kbn/i18n",
"@kbn/std",
"@kbn/expressions-plugin",
diff --git a/x-pack/examples/ui_actions_enhanced_examples/kibana.jsonc b/x-pack/examples/ui_actions_enhanced_examples/kibana.jsonc
index 25211ae2063bd..19e73f0204d6f 100644
--- a/x-pack/examples/ui_actions_enhanced_examples/kibana.jsonc
+++ b/x-pack/examples/ui_actions_enhanced_examples/kibana.jsonc
@@ -21,7 +21,8 @@
"dashboard",
"dashboardEnhanced",
"developerExamples",
- "unifiedSearch"
+ "unifiedSearch",
+ "embeddable",
],
"requiredBundles": [
"dashboardEnhanced",
diff --git a/x-pack/examples/ui_actions_enhanced_examples/public/containers/app/app.tsx b/x-pack/examples/ui_actions_enhanced_examples/public/containers/app/app.tsx
index cbfda603c8ec4..97d281d51fba6 100644
--- a/x-pack/examples/ui_actions_enhanced_examples/public/containers/app/app.tsx
+++ b/x-pack/examples/ui_actions_enhanced_examples/public/containers/app/app.tsx
@@ -7,15 +7,19 @@
import React from 'react';
import { EuiPage } from '@elastic/eui';
+import { CoreStart } from '@kbn/core/public';
+import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
import { Page } from '../../components/page';
import { DrilldownsManager } from '../drilldowns_manager';
-export const App: React.FC = () => {
+export const App = ({ core }: { core: CoreStart }) => {
return (
-
-
-
-
-
+
+
+
+
+
+
+
);
};
diff --git a/x-pack/examples/ui_actions_enhanced_examples/public/containers/drilldowns_with_embeddable_example/drilldowns_with_embeddable_example.tsx b/x-pack/examples/ui_actions_enhanced_examples/public/containers/drilldowns_with_embeddable_example/drilldowns_with_embeddable_example.tsx
index 4ca214aa2cff4..b7a437b3d69d2 100644
--- a/x-pack/examples/ui_actions_enhanced_examples/public/containers/drilldowns_with_embeddable_example/drilldowns_with_embeddable_example.tsx
+++ b/x-pack/examples/ui_actions_enhanced_examples/public/containers/drilldowns_with_embeddable_example/drilldowns_with_embeddable_example.tsx
@@ -18,29 +18,12 @@ import {
EuiFlexItem,
EuiFlexGroup,
} from '@elastic/eui';
-import { EmbeddableRoot, VALUE_CLICK_TRIGGER } from '@kbn/embeddable-plugin/public';
-import { SampleMlJob, SampleApp1ClickContext } from '../../triggers';
-import { ButtonEmbeddable } from '../../embeddables/button_embeddable';
+import { ReactEmbeddableRenderer, VALUE_CLICK_TRIGGER } from '@kbn/embeddable-plugin/public';
import { useUiActions } from '../../context';
-
-export const job: SampleMlJob = {
- job_id: '123',
- job_type: 'anomaly_detector',
- description: 'This is some ML job.',
-};
-
-export const context: SampleApp1ClickContext = { job };
+import { BUTTON_EMBEDDABLE } from '../../embeddables/register_button_embeddable';
export const DrilldownsWithEmbeddableExample: React.FC = () => {
const { plugins, managerWithEmbeddable } = useUiActions();
- const embeddable = React.useMemo(
- () =>
- new ButtonEmbeddable(
- { id: 'DrilldownsWithEmbeddableExample' },
- { uiActions: plugins.uiActionsEnhanced }
- ),
- [plugins.uiActionsEnhanced]
- );
const [showManager, setShowManager] = React.useState(false);
const [openPopup, setOpenPopup] = React.useState(false);
const viewRef = React.useRef<'/create' | '/manage'>('/create');
@@ -112,7 +95,13 @@ export const DrilldownsWithEmbeddableExample: React.FC = () => {
{openManagerButton}
-
+
+ type={BUTTON_EMBEDDABLE}
+ getParentApi={() => ({
+ getSerializedStateForChild: () => undefined,
+ })}
+ hidePanelChrome={true}
+ />
@@ -124,7 +113,6 @@ export const DrilldownsWithEmbeddableExample: React.FC = () => {
initialRoute={viewRef.current}
dynamicActionManager={managerWithEmbeddable}
triggers={[VALUE_CLICK_TRIGGER]}
- placeContext={{ embeddable }}
onClose={() => setShowManager(false)}
/>
diff --git a/x-pack/examples/ui_actions_enhanced_examples/public/embeddables/button_embeddable.tsx b/x-pack/examples/ui_actions_enhanced_examples/public/embeddables/button_embeddable.tsx
new file mode 100644
index 0000000000000..f19a21d98a08c
--- /dev/null
+++ b/x-pack/examples/ui_actions_enhanced_examples/public/embeddables/button_embeddable.tsx
@@ -0,0 +1,60 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React, { useCallback } from 'react';
+import {
+ DefaultEmbeddableApi,
+ ReactEmbeddableFactory,
+ VALUE_CLICK_TRIGGER,
+} from '@kbn/embeddable-plugin/public';
+import { EuiCard, EuiFlexItem, EuiIcon } from '@elastic/eui';
+import { AdvancedUiActionsStart } from '@kbn/ui-actions-enhanced-plugin/public';
+import { BUTTON_EMBEDDABLE } from './register_button_embeddable';
+
+export const getButtonEmbeddableFactory = (uiActionsEnhanced: AdvancedUiActionsStart) => {
+ const factory: ReactEmbeddableFactory<{}, {}, DefaultEmbeddableApi<{}>> = {
+ type: BUTTON_EMBEDDABLE,
+ deserializeState: (state) => state.rawState,
+ buildEmbeddable: async (state, buildApi, uuid, parentApi) => {
+ const api = buildApi(
+ {
+ serializeState: () => {
+ return {
+ rawState: {},
+ references: [],
+ };
+ },
+ },
+ {}
+ );
+ return {
+ api,
+ Component: () => {
+ const onClick = useCallback(() => {
+ uiActionsEnhanced.getTrigger(VALUE_CLICK_TRIGGER).exec({
+ embeddable: api,
+ data: {
+ data: [],
+ },
+ });
+ }, []);
+ return (
+
+ }
+ title={`Click me!`}
+ description={'This embeddable fires "VALUE_CLICK" trigger on click'}
+ onClick={onClick}
+ />
+
+ );
+ },
+ };
+ },
+ };
+ return factory;
+};
diff --git a/x-pack/examples/ui_actions_enhanced_examples/public/embeddables/button_embeddable/button_embeddable.ts b/x-pack/examples/ui_actions_enhanced_examples/public/embeddables/button_embeddable/button_embeddable.ts
deleted file mode 100644
index df44e9061fc0e..0000000000000
--- a/x-pack/examples/ui_actions_enhanced_examples/public/embeddables/button_embeddable/button_embeddable.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { createElement } from 'react';
-import { render, unmountComponentAtNode } from 'react-dom';
-import { AdvancedUiActionsStart } from '@kbn/ui-actions-enhanced-plugin/public';
-import { Embeddable, EmbeddableInput, VALUE_CLICK_TRIGGER } from '@kbn/embeddable-plugin/public';
-import { ButtonEmbeddableComponent } from './button_embeddable_component';
-
-export const BUTTON_EMBEDDABLE = 'BUTTON_EMBEDDABLE';
-
-export interface ButtonEmbeddableParams {
- uiActions: AdvancedUiActionsStart;
-}
-
-export class ButtonEmbeddable extends Embeddable {
- type = BUTTON_EMBEDDABLE;
-
- constructor(input: EmbeddableInput, private readonly params: ButtonEmbeddableParams) {
- super(input, {});
- }
-
- reload() {}
-
- private el?: HTMLElement;
-
- public render(el: HTMLElement): void {
- super.render(el);
- this.el = el;
- render(
- createElement(ButtonEmbeddableComponent, {
- onClick: () => {
- this.params.uiActions.getTrigger(VALUE_CLICK_TRIGGER).exec({
- embeddable: this,
- data: {
- data: [],
- },
- });
- },
- }),
- el
- );
- }
-
- public destroy() {
- super.destroy();
- if (this.el) unmountComponentAtNode(this.el);
- }
-}
diff --git a/x-pack/examples/ui_actions_enhanced_examples/public/embeddables/button_embeddable/button_embeddable_component.tsx b/x-pack/examples/ui_actions_enhanced_examples/public/embeddables/button_embeddable/button_embeddable_component.tsx
deleted file mode 100644
index 044ae3c21900d..0000000000000
--- a/x-pack/examples/ui_actions_enhanced_examples/public/embeddables/button_embeddable/button_embeddable_component.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import * as React from 'react';
-import { EuiCard, EuiFlexItem, EuiIcon } from '@elastic/eui';
-
-export interface ButtonEmbeddableComponentProps {
- onClick: () => void;
-}
-
-export const ButtonEmbeddableComponent: React.FC = ({
- onClick,
-}) => {
- return (
-
- }
- title={`Click me!`}
- description={'This embeddable fires "VALUE_CLICK" trigger on click'}
- onClick={onClick}
- />
-
- );
-};
diff --git a/x-pack/examples/ui_actions_enhanced_examples/public/embeddables/button_embeddable/index.ts b/x-pack/examples/ui_actions_enhanced_examples/public/embeddables/button_embeddable/index.ts
deleted file mode 100644
index fb21a78c24b4a..0000000000000
--- a/x-pack/examples/ui_actions_enhanced_examples/public/embeddables/button_embeddable/index.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-export * from './button_embeddable';
diff --git a/x-pack/examples/ui_actions_enhanced_examples/public/embeddables/register_button_embeddable.ts b/x-pack/examples/ui_actions_enhanced_examples/public/embeddables/register_button_embeddable.ts
new file mode 100644
index 0000000000000..11ab813a85f4b
--- /dev/null
+++ b/x-pack/examples/ui_actions_enhanced_examples/public/embeddables/register_button_embeddable.ts
@@ -0,0 +1,22 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { EmbeddableSetup } from '@kbn/embeddable-plugin/public';
+import { StartDependencies } from '../plugin';
+
+export const BUTTON_EMBEDDABLE = 'BUTTON_EMBEDDABLE';
+
+export function registerButtonEmbeddable(
+ embeddable: EmbeddableSetup,
+ services: Promise
+) {
+ embeddable.registerReactEmbeddableFactory(BUTTON_EMBEDDABLE, async () => {
+ const { getButtonEmbeddableFactory } = await import('./button_embeddable');
+ const { uiActionsEnhanced } = await services;
+ return getButtonEmbeddableFactory(uiActionsEnhanced);
+ });
+}
diff --git a/x-pack/examples/ui_actions_enhanced_examples/public/mount.tsx b/x-pack/examples/ui_actions_enhanced_examples/public/mount.tsx
index 76708ac558fc8..636286b03efdf 100644
--- a/x-pack/examples/ui_actions_enhanced_examples/public/mount.tsx
+++ b/x-pack/examples/ui_actions_enhanced_examples/public/mount.tsx
@@ -31,7 +31,7 @@ export const mount =
};
const reactElement = (
-
+
);
render(reactElement, element);
diff --git a/x-pack/examples/ui_actions_enhanced_examples/public/plugin.ts b/x-pack/examples/ui_actions_enhanced_examples/public/plugin.ts
index fbd74fc581012..fbf06ca7c2fba 100644
--- a/x-pack/examples/ui_actions_enhanced_examples/public/plugin.ts
+++ b/x-pack/examples/ui_actions_enhanced_examples/public/plugin.ts
@@ -21,6 +21,7 @@ import {
UiActionsEnhancedMemoryActionStorage,
UiActionsEnhancedDynamicActionManager,
} from '@kbn/ui-actions-enhanced-plugin/public';
+import { EmbeddableSetup } from '@kbn/embeddable-plugin/public';
import { DashboardHelloWorldDrilldown } from './drilldowns/dashboard_hello_world_drilldown';
import { DashboardToDiscoverDrilldown } from './drilldowns/dashboard_to_discover_drilldown';
import { App1ToDashboardDrilldown } from './drilldowns/app1_to_dashboard_drilldown';
@@ -35,12 +36,14 @@ import {
} from './triggers';
import { mount } from './mount';
import { App2ToDashboardDrilldown } from './drilldowns/app2_to_dashboard_drilldown';
+import { registerButtonEmbeddable } from './embeddables/register_button_embeddable';
export interface SetupDependencies {
dashboard: DashboardSetup;
data: DataPublicPluginSetup;
developerExamples: DeveloperExamplesSetup;
discover: DiscoverSetup;
+ embeddable: EmbeddableSetup;
uiActionsEnhanced: AdvancedUiActionsSetup;
}
@@ -62,7 +65,7 @@ export class UiActionsEnhancedExamplesPlugin
{
public setup(
core: CoreSetup,
- { uiActionsEnhanced: uiActions, developerExamples }: SetupDependencies
+ { embeddable, uiActionsEnhanced: uiActions, developerExamples }: SetupDependencies
) {
const start = createStartServicesGetter(core.getStartServices);
@@ -150,6 +153,12 @@ export class UiActionsEnhancedExamplesPlugin
},
],
});
+
+ const startServicesPromise = core.getStartServices();
+ registerButtonEmbeddable(
+ embeddable,
+ startServicesPromise.then(([_, startDeps]) => startDeps)
+ );
}
public start(_core: CoreStart, plugins: StartDependencies): UiActionsEnhancedExamplesStart {
diff --git a/x-pack/examples/ui_actions_enhanced_examples/tsconfig.json b/x-pack/examples/ui_actions_enhanced_examples/tsconfig.json
index 6010bece3bd1c..666df7ab8d27a 100644
--- a/x-pack/examples/ui_actions_enhanced_examples/tsconfig.json
+++ b/x-pack/examples/ui_actions_enhanced_examples/tsconfig.json
@@ -30,5 +30,6 @@
"@kbn/utility-types",
"@kbn/presentation-publishing",
"@kbn/react-kibana-mount",
+ "@kbn/react-kibana-context-render",
]
}