kibana/examples/resizable_layout_examples/public/application.tsx
Gerard Soldevila b24fdf5d3f
Sustainable Kibana Architecture: Categorise straightforward packages (#199630)
## Summary

This PR is part of the Kibana Sustainable Architecture effort.

The goal is to start categorising Kibana packages into _generic
platform_ (`group: "platform"`) vs _solution-specific_.

```
group?: 'search' | 'security' | 'observability' | 'platform'
visibility?: 'private' | 'shared'
```
Uncategorised modules are considered to be `group: 'common', visibility:
'shared'` by default.

We want to prevent code from solution A to depend on code from solution
B.
Thus, the rules are pretty simple:

* Modules can only depend on:
  * Modules in the same group
  * OR modules with 'shared' visibility
* Modules in `'observability', 'security', 'search'` groups are
mandatorily `visibility: "private"`.

Long term, the goal is to re-organise packages into dedicated folders,
e.g.:

```
x-pack/platform/plugins/private
x-pack/observability/packages
```

For this first wave, we have categorised packages that seem
"straightforward":
* Any packages that have:
  * at least one dependant module
  * all dependants belong to the same group
* Categorise all Core packages:
  * `@kbn/core-...-internal` => _platform/private_
  * everything else => _platform/shared_
* Categorise as _platform/shared_ those packages that:
  * Have at least one dependant in the _platform_ group.
  * Don't have any `devOnly: true` dependants.

### What we ask from you, as CODEOWNERS of the _package manifests_, is
that you confirm that the categorisation is correct:

* `group: "platform", visibility: "private"` if it's a package that
should only be used from platform code, not from any solution code. It
will be loaded systematically in all serverless flavors, but solution
plugins and packages won't be able to `import` from it.
* `group: "platform", visibility: "shared"` if it's a package that can
be consumed by both platform and solutions code. It will be loaded
systematically in all serverless flavors, and anybody can import / use
code from it.
* `group: "observability" | "security" | "search", visibility:
"private"` if it's a package that is intented to be used exclusively
from a given solution. It won't be accessible nor loaded from other
solutions nor platform code.

Please refer to
[#kibana-sustainable-architecture](https://elastic.slack.com/archives/C07TCKTA22E)
for any related questions.

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
2024-11-22 10:33:25 +01:00

162 lines
5.3 KiB
TypeScript

/*
* 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 { KibanaThemeProvider } from '@kbn/react-kibana-context-theme';
import type { AppMountParameters } from '@kbn/core/public';
import { I18nProvider } from '@kbn/i18n-react';
import React, { ReactNode, useState } from 'react';
import ReactDOM from 'react-dom';
import { useIsWithinBreakpoints } from '@elastic/eui';
import { css } from '@emotion/react';
import {
ResizableLayout,
ResizableLayoutDirection,
ResizableLayoutMode,
} from '@kbn/resizable-layout';
import { createHtmlPortalNode, InPortal, OutPortal } from 'react-reverse-portal';
const ResizableSection = ({
direction,
initialFixedPanelSize,
minFixedPanelSize,
minFlexPanelSize,
fixedPanelColor,
flexPanelColor,
fixedPanelContent,
flexPanelContent,
}: {
direction: ResizableLayoutDirection;
initialFixedPanelSize: number;
minFixedPanelSize: number;
minFlexPanelSize: number;
fixedPanelColor: string;
flexPanelColor: string;
fixedPanelContent: ReactNode;
flexPanelContent: ReactNode;
}) => {
const [fixedPanelSize, setFixedPanelSize] = useState(initialFixedPanelSize);
const [container, setContainer] = useState<HTMLDivElement | null>(null);
const [fixedPanelNode] = useState(() =>
createHtmlPortalNode({ attributes: { class: 'eui-fullHeight' } })
);
const [flexPanelNode] = useState(() =>
createHtmlPortalNode({ attributes: { class: 'eui-fullHeight' } })
);
const isMobile = useIsWithinBreakpoints(['xs', 's']);
const layoutMode = isMobile ? ResizableLayoutMode.Static : ResizableLayoutMode.Resizable;
const layoutDirection = isMobile ? ResizableLayoutDirection.Vertical : direction;
const fullWidthAndHeightCss = css`
position: relative;
width: 100%;
height: 100%;
`;
const panelBaseCss = css`
${fullWidthAndHeightCss}
padding: 20px;
font-size: 20px;
display: flex;
align-items: center;
justify-content: center;
`;
const fixedPanelCss = css`
${panelBaseCss}
background-color: ${fixedPanelColor};
`;
const flexPanelCss = css`
${panelBaseCss}
background-color: ${flexPanelColor};
`;
return (
<div ref={setContainer} css={fullWidthAndHeightCss}>
<InPortal node={fixedPanelNode}>
<div css={fixedPanelCss}>{fixedPanelContent}</div>
</InPortal>
<InPortal node={flexPanelNode}>
<div css={flexPanelCss}>{flexPanelContent}</div>
</InPortal>
<ResizableLayout
mode={layoutMode}
direction={layoutDirection}
container={container}
fixedPanelSize={fixedPanelSize}
minFixedPanelSize={minFixedPanelSize}
minFlexPanelSize={minFlexPanelSize}
fixedPanel={<OutPortal node={fixedPanelNode} />}
flexPanel={<OutPortal node={flexPanelNode} />}
onFixedPanelSizeChange={setFixedPanelSize}
/>
</div>
);
};
export const renderApp = ({ element, theme$ }: AppMountParameters) => {
ReactDOM.render(
<I18nProvider>
<KibanaThemeProvider theme={{ theme$ }}>
<div
css={css`
height: calc(100vh - var(--euiFixedHeadersOffset, 0));
`}
>
<ResizableSection
direction={ResizableLayoutDirection.Horizontal}
initialFixedPanelSize={500}
minFixedPanelSize={300}
minFlexPanelSize={500}
fixedPanelColor="#16E0BD"
flexPanelColor="#89A6FB"
fixedPanelContent={
<ResizableSection
direction={ResizableLayoutDirection.Vertical}
initialFixedPanelSize={200}
minFixedPanelSize={100}
minFlexPanelSize={200}
fixedPanelColor="#E3655B"
flexPanelColor="#FDCA40"
fixedPanelContent="Sidebar Header"
flexPanelContent="Sidebar Body"
/>
}
flexPanelContent={
<ResizableSection
direction={ResizableLayoutDirection.Vertical}
initialFixedPanelSize={300}
minFixedPanelSize={200}
minFlexPanelSize={300}
fixedPanelColor="#FFA0AC"
flexPanelColor="#F6F740"
fixedPanelContent="Main Body Header"
flexPanelContent={
<ResizableSection
direction={ResizableLayoutDirection.Horizontal}
initialFixedPanelSize={400}
minFixedPanelSize={200}
minFlexPanelSize={200}
fixedPanelColor="#78C3FB"
flexPanelColor="#EF709D"
fixedPanelContent="Main Body Left"
flexPanelContent="Main Body Right"
/>
}
/>
}
/>
</div>
</KibanaThemeProvider>
</I18nProvider>,
element
);
return () => {
ReactDOM.unmountComponentAtNode(element);
};
};