Bumping EUI to version 64.0.4 (#140323)

* Bumping EUI to version 64.0.1.

* Updating snapshot tests for two directories.

* Deprecate basic usages of getBreakpoint

- in favor of useCurrentEuiBreakpoint

* [Fleet] Deprecate isWithinMaxBreakpoint

- in favor of hook

* [DataViz] Update DataVisualizerTable to use window breakpoint vs table resize observer

- since getBreakpoint is now deprecated, we're only looking at the current EUI breakpoint (based off window width)

* [KibanaThemeProvider] Allow apps to modify the default EUI theme

- Setup for custom xl+ breakpoint sizes used by APM and Synthetics

* [APM] Update useBreakpoints hook with EUI breakpoint deprecations

- since getBreakpoint is no longer an usable util

- EUI's new breakpoint hooks already use/debounce window resize events, so we now get to skip all that custom logic by simply making custom EUI breakpoint overrides and using EUI breakpoint hooks

- remove returned `breakpoint` and `width` keys - they weren't actually being used anywhere in APM that I could see and were causing type errors.
- If someone wants to access them, they can use `useCurrentEuiBreakpoint` and `useWindowSize` individually instead

* [UX] Update useBreakpoints hook copied from APM

- basically the exact same logic, they just also need the xxl and xxxl breakpoints

* [Synthetics] Remove `useBreakpoints` in favor of new EUI breakpoint hooks

+ add xxl and xxxl breakpoints to Synthetics EUI themes

- `useBreakpoints`: - as far as I can tell, all attached APIs are basically the same APIs that EUI provides OOTB:
  - up -> `useIsWithinMinBreakpoint`
  - down -> `useIsWithinMaxBreakpoint`
  - between -> `useIsWithinBreakpoints`
  - debouncedWidth - not used, but could just use `useWindowSize` directly instead

- note: i'm confused by the `xl` override/conflation with `xxl`, but left the default xl breakpoint size as-is and assumed that all usage instances of 'xl' actually wanted 'xxl'

* v64.0.2 - add missing backports and several new fixes

* v64.0.3

* Fix type error from breakpoint deprecation

- functionally doesn't matter since the array doesn't include undefined, so basically just silence TS complaining about it

* Updating additional snapshots after bump to EUI 64.0.3

* Adding RUM Jest snapshot update.

* Adding Timeout to Fleet token generation test.

* Revert "[DataViz] Update DataVisualizerTable to use window breakpoint vs table resize observer"

This reverts commit 4e60ce281d.

* [DataViz] Remove getBreakpoint usage

- by replacing the breakpoint logic/switch with custom breakpoint sizes and names

- since the table size can be within panels that don't match `window.innerWidth`, we can't use EUI's breakpoint utils here

* Restoring a needed hook for breakpoints.

* Fix broken side navs on uptime/apm/ux/synthetics

- because of their new custom xxl/xxxl breakpoints, the `isLargerBreakpoint` logic was broken on the shared solution nav. switching to a min breakpoint bound fixes the issue and futureproofs the solution nav for all apps that add larger breakpoints than xl

* Fix snapshots/unit tests from previous commits

* Bumping EUI to 64.0.4 backport.

* [PR feedback] Separate DataVisualizerTable more clearly from EUI breakpoints

- per discussion with Quynh and Walter, there's some confusion around the breakpoints that the table is using. Since the table is width is not always the width of the browser window, it cannot use EUI's breakpoint hooks, and should instead use its own custom map of table-specific breakpoints to make that separation clearer

* [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix'

Co-authored-by: Constance Chen <constance.chen@elastic.co>
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Trevor Pierce 2022-09-20 08:50:15 -05:00 committed by GitHub
parent 7026b57eb9
commit 378829348c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
39 changed files with 814 additions and 577 deletions

View file

@ -109,7 +109,7 @@
"@elastic/datemath": "5.0.3",
"@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@8.3.0-canary.1",
"@elastic/ems-client": "8.3.3",
"@elastic/eui": "63.0.6",
"@elastic/eui": "64.0.4",
"@elastic/filesaver": "1.1.2",
"@elastic/node-crypto": "1.2.1",
"@elastic/numeral": "^2.5.1",

View file

@ -4,7 +4,7 @@ exports[`SolutionNav accepts EuiSideNavProps 1`] = `
<Fragment>
<EuiCollapsibleNavGroup
background="none"
className="kbnSolutionNav"
className="kbnSolutionNav kbnSolutionNav--hidden"
initialIsOpen={false}
isCollapsible={true}
paddingSize="none"
@ -36,7 +36,7 @@ exports[`SolutionNav accepts EuiSideNavProps 1`] = `
paddingSize="s"
>
<EuiSideNav
aria-hidden={false}
aria-hidden={true}
aria-labelledby="SolutionNav_generated-id_heading"
data-test-subj="DTS"
items={
@ -48,23 +48,23 @@ exports[`SolutionNav accepts EuiSideNavProps 1`] = `
"id": "1.1",
"items": undefined,
"name": "Ingest Node Pipelines",
"tabIndex": undefined,
"tabIndex": -1,
},
Object {
"id": "1.2",
"items": undefined,
"name": "Logstash Pipelines",
"tabIndex": undefined,
"tabIndex": -1,
},
Object {
"id": "1.3",
"items": undefined,
"name": "Beats Central Management",
"tabIndex": undefined,
"tabIndex": -1,
},
],
"name": "Ingest",
"tabIndex": undefined,
"tabIndex": -1,
},
Object {
"id": "2",
@ -73,23 +73,23 @@ exports[`SolutionNav accepts EuiSideNavProps 1`] = `
"id": "2.1",
"items": undefined,
"name": "Index Management",
"tabIndex": undefined,
"tabIndex": -1,
},
Object {
"id": "2.2",
"items": undefined,
"name": "Index Lifecycle Policies",
"tabIndex": undefined,
"tabIndex": -1,
},
Object {
"id": "2.3",
"items": undefined,
"name": "Snapshot and Restore",
"tabIndex": undefined,
"tabIndex": -1,
},
],
"name": "Data",
"tabIndex": undefined,
"tabIndex": -1,
},
]
}
@ -97,6 +97,95 @@ exports[`SolutionNav accepts EuiSideNavProps 1`] = `
/>
</EuiPanel>
</EuiCollapsibleNavGroup>
<div
className="kbnSolutionNav kbnSolutionNav--hidden"
>
<EuiTitle
id="SolutionNav_generated-id_heading"
size="xs"
>
<h2>
<strong>
<FormattedMessage
defaultMessage="{solutionName} {menuText}"
id="sharedUXPackages.solutionNav.mobileTitleText"
values={
Object {
"menuText": "menu",
"solutionName": "Solution",
}
}
/>
</strong>
</h2>
</EuiTitle>
<EuiSpacer
size="l"
/>
<EuiSideNav
aria-hidden={true}
aria-labelledby="SolutionNav_generated-id_heading"
data-test-subj="DTS"
items={
Array [
Object {
"id": "1",
"items": Array [
Object {
"id": "1.1",
"items": undefined,
"name": "Ingest Node Pipelines",
"tabIndex": -1,
},
Object {
"id": "1.2",
"items": undefined,
"name": "Logstash Pipelines",
"tabIndex": -1,
},
Object {
"id": "1.3",
"items": undefined,
"name": "Beats Central Management",
"tabIndex": -1,
},
],
"name": "Ingest",
"tabIndex": -1,
},
Object {
"id": "2",
"items": Array [
Object {
"id": "2.1",
"items": undefined,
"name": "Index Management",
"tabIndex": -1,
},
Object {
"id": "2.2",
"items": undefined,
"name": "Index Lifecycle Policies",
"tabIndex": -1,
},
Object {
"id": "2.3",
"items": undefined,
"name": "Snapshot and Restore",
"tabIndex": -1,
},
],
"name": "Data",
"tabIndex": -1,
},
]
}
mobileBreakpoints={Array []}
/>
</div>
<SolutionNavCollapseButton
isCollapsed={true}
/>
</Fragment>
`;
@ -104,7 +193,7 @@ exports[`SolutionNav accepts canBeCollapsed prop 1`] = `
<Fragment>
<EuiCollapsibleNavGroup
background="none"
className="kbnSolutionNav"
className="kbnSolutionNav kbnSolutionNav--hidden"
initialIsOpen={false}
isCollapsible={true}
paddingSize="none"
@ -136,7 +225,7 @@ exports[`SolutionNav accepts canBeCollapsed prop 1`] = `
paddingSize="s"
>
<EuiSideNav
aria-hidden={false}
aria-hidden={true}
aria-labelledby="SolutionNav_generated-id_heading"
items={
Array [
@ -147,23 +236,23 @@ exports[`SolutionNav accepts canBeCollapsed prop 1`] = `
"id": "1.1",
"items": undefined,
"name": "Ingest Node Pipelines",
"tabIndex": undefined,
"tabIndex": -1,
},
Object {
"id": "1.2",
"items": undefined,
"name": "Logstash Pipelines",
"tabIndex": undefined,
"tabIndex": -1,
},
Object {
"id": "1.3",
"items": undefined,
"name": "Beats Central Management",
"tabIndex": undefined,
"tabIndex": -1,
},
],
"name": "Ingest",
"tabIndex": undefined,
"tabIndex": -1,
},
Object {
"id": "2",
@ -172,23 +261,23 @@ exports[`SolutionNav accepts canBeCollapsed prop 1`] = `
"id": "2.1",
"items": undefined,
"name": "Index Management",
"tabIndex": undefined,
"tabIndex": -1,
},
Object {
"id": "2.2",
"items": undefined,
"name": "Index Lifecycle Policies",
"tabIndex": undefined,
"tabIndex": -1,
},
Object {
"id": "2.3",
"items": undefined,
"name": "Snapshot and Restore",
"tabIndex": undefined,
"tabIndex": -1,
},
],
"name": "Data",
"tabIndex": undefined,
"tabIndex": -1,
},
]
}
@ -196,6 +285,94 @@ exports[`SolutionNav accepts canBeCollapsed prop 1`] = `
/>
</EuiPanel>
</EuiCollapsibleNavGroup>
<div
className="kbnSolutionNav kbnSolutionNav--hidden"
>
<EuiTitle
id="SolutionNav_generated-id_heading"
size="xs"
>
<h2>
<strong>
<FormattedMessage
defaultMessage="{solutionName} {menuText}"
id="sharedUXPackages.solutionNav.mobileTitleText"
values={
Object {
"menuText": "menu",
"solutionName": "Solution",
}
}
/>
</strong>
</h2>
</EuiTitle>
<EuiSpacer
size="l"
/>
<EuiSideNav
aria-hidden={true}
aria-labelledby="SolutionNav_generated-id_heading"
items={
Array [
Object {
"id": "1",
"items": Array [
Object {
"id": "1.1",
"items": undefined,
"name": "Ingest Node Pipelines",
"tabIndex": -1,
},
Object {
"id": "1.2",
"items": undefined,
"name": "Logstash Pipelines",
"tabIndex": -1,
},
Object {
"id": "1.3",
"items": undefined,
"name": "Beats Central Management",
"tabIndex": -1,
},
],
"name": "Ingest",
"tabIndex": -1,
},
Object {
"id": "2",
"items": Array [
Object {
"id": "2.1",
"items": undefined,
"name": "Index Management",
"tabIndex": -1,
},
Object {
"id": "2.2",
"items": undefined,
"name": "Index Lifecycle Policies",
"tabIndex": -1,
},
Object {
"id": "2.3",
"items": undefined,
"name": "Snapshot and Restore",
"tabIndex": -1,
},
],
"name": "Data",
"tabIndex": -1,
},
]
}
mobileBreakpoints={Array []}
/>
</div>
<SolutionNavCollapseButton
isCollapsed={true}
/>
</Fragment>
`;
@ -295,6 +472,91 @@ exports[`SolutionNav accepts canBeCollapsed prop 2`] = `
/>
</EuiPanel>
</EuiCollapsibleNavGroup>
<div
className="kbnSolutionNav"
>
<EuiTitle
id="SolutionNav_generated-id_heading"
size="xs"
>
<h2>
<strong>
<FormattedMessage
defaultMessage="{solutionName} {menuText}"
id="sharedUXPackages.solutionNav.mobileTitleText"
values={
Object {
"menuText": "menu",
"solutionName": "Solution",
}
}
/>
</strong>
</h2>
</EuiTitle>
<EuiSpacer
size="l"
/>
<EuiSideNav
aria-hidden={false}
aria-labelledby="SolutionNav_generated-id_heading"
items={
Array [
Object {
"id": "1",
"items": Array [
Object {
"id": "1.1",
"items": undefined,
"name": "Ingest Node Pipelines",
"tabIndex": undefined,
},
Object {
"id": "1.2",
"items": undefined,
"name": "Logstash Pipelines",
"tabIndex": undefined,
},
Object {
"id": "1.3",
"items": undefined,
"name": "Beats Central Management",
"tabIndex": undefined,
},
],
"name": "Ingest",
"tabIndex": undefined,
},
Object {
"id": "2",
"items": Array [
Object {
"id": "2.1",
"items": undefined,
"name": "Index Management",
"tabIndex": undefined,
},
Object {
"id": "2.2",
"items": undefined,
"name": "Index Lifecycle Policies",
"tabIndex": undefined,
},
Object {
"id": "2.3",
"items": undefined,
"name": "Snapshot and Restore",
"tabIndex": undefined,
},
],
"name": "Data",
"tabIndex": undefined,
},
]
}
mobileBreakpoints={Array []}
/>
</div>
</Fragment>
`;
@ -302,7 +564,7 @@ exports[`SolutionNav heading accepts more headingProps 1`] = `
<Fragment>
<EuiCollapsibleNavGroup
background="none"
className="kbnSolutionNav"
className="kbnSolutionNav kbnSolutionNav--hidden"
initialIsOpen={false}
isCollapsible={true}
paddingSize="none"
@ -334,6 +596,35 @@ exports[`SolutionNav heading accepts more headingProps 1`] = `
paddingSize="s"
/>
</EuiCollapsibleNavGroup>
<div
className="kbnSolutionNav kbnSolutionNav--hidden"
>
<EuiTitle
id="testID"
size="xs"
>
<h3>
<strong>
<FormattedMessage
defaultMessage="{solutionName} {menuText}"
id="sharedUXPackages.solutionNav.mobileTitleText"
values={
Object {
"menuText": "menu",
"solutionName": "Solution",
}
}
/>
</strong>
</h3>
</EuiTitle>
<EuiSpacer
size="l"
/>
</div>
<SolutionNavCollapseButton
isCollapsed={true}
/>
</Fragment>
`;
@ -341,7 +632,7 @@ exports[`SolutionNav renders 1`] = `
<Fragment>
<EuiCollapsibleNavGroup
background="none"
className="kbnSolutionNav"
className="kbnSolutionNav kbnSolutionNav--hidden"
initialIsOpen={false}
isCollapsible={true}
paddingSize="none"
@ -373,7 +664,7 @@ exports[`SolutionNav renders 1`] = `
paddingSize="s"
>
<EuiSideNav
aria-hidden={false}
aria-hidden={true}
aria-labelledby="SolutionNav_generated-id_heading"
items={
Array [
@ -384,23 +675,23 @@ exports[`SolutionNav renders 1`] = `
"id": "1.1",
"items": undefined,
"name": "Ingest Node Pipelines",
"tabIndex": undefined,
"tabIndex": -1,
},
Object {
"id": "1.2",
"items": undefined,
"name": "Logstash Pipelines",
"tabIndex": undefined,
"tabIndex": -1,
},
Object {
"id": "1.3",
"items": undefined,
"name": "Beats Central Management",
"tabIndex": undefined,
"tabIndex": -1,
},
],
"name": "Ingest",
"tabIndex": undefined,
"tabIndex": -1,
},
Object {
"id": "2",
@ -409,23 +700,23 @@ exports[`SolutionNav renders 1`] = `
"id": "2.1",
"items": undefined,
"name": "Index Management",
"tabIndex": undefined,
"tabIndex": -1,
},
Object {
"id": "2.2",
"items": undefined,
"name": "Index Lifecycle Policies",
"tabIndex": undefined,
"tabIndex": -1,
},
Object {
"id": "2.3",
"items": undefined,
"name": "Snapshot and Restore",
"tabIndex": undefined,
"tabIndex": -1,
},
],
"name": "Data",
"tabIndex": undefined,
"tabIndex": -1,
},
]
}
@ -433,6 +724,94 @@ exports[`SolutionNav renders 1`] = `
/>
</EuiPanel>
</EuiCollapsibleNavGroup>
<div
className="kbnSolutionNav kbnSolutionNav--hidden"
>
<EuiTitle
id="SolutionNav_generated-id_heading"
size="xs"
>
<h2>
<strong>
<FormattedMessage
defaultMessage="{solutionName} {menuText}"
id="sharedUXPackages.solutionNav.mobileTitleText"
values={
Object {
"menuText": "menu",
"solutionName": "Solution",
}
}
/>
</strong>
</h2>
</EuiTitle>
<EuiSpacer
size="l"
/>
<EuiSideNav
aria-hidden={true}
aria-labelledby="SolutionNav_generated-id_heading"
items={
Array [
Object {
"id": "1",
"items": Array [
Object {
"id": "1.1",
"items": undefined,
"name": "Ingest Node Pipelines",
"tabIndex": -1,
},
Object {
"id": "1.2",
"items": undefined,
"name": "Logstash Pipelines",
"tabIndex": -1,
},
Object {
"id": "1.3",
"items": undefined,
"name": "Beats Central Management",
"tabIndex": -1,
},
],
"name": "Ingest",
"tabIndex": -1,
},
Object {
"id": "2",
"items": Array [
Object {
"id": "2.1",
"items": undefined,
"name": "Index Management",
"tabIndex": -1,
},
Object {
"id": "2.2",
"items": undefined,
"name": "Index Lifecycle Policies",
"tabIndex": -1,
},
Object {
"id": "2.3",
"items": undefined,
"name": "Snapshot and Restore",
"tabIndex": -1,
},
],
"name": "Data",
"tabIndex": -1,
},
]
}
mobileBreakpoints={Array []}
/>
</div>
<SolutionNavCollapseButton
isCollapsed={true}
/>
</Fragment>
`;
@ -440,7 +819,7 @@ exports[`SolutionNav renders with icon 1`] = `
<Fragment>
<EuiCollapsibleNavGroup
background="none"
className="kbnSolutionNav"
className="kbnSolutionNav kbnSolutionNav--hidden"
initialIsOpen={false}
isCollapsible={true}
paddingSize="none"
@ -477,7 +856,7 @@ exports[`SolutionNav renders with icon 1`] = `
paddingSize="s"
>
<EuiSideNav
aria-hidden={false}
aria-hidden={true}
aria-labelledby="SolutionNav_generated-id_heading"
items={
Array [
@ -488,23 +867,23 @@ exports[`SolutionNav renders with icon 1`] = `
"id": "1.1",
"items": undefined,
"name": "Ingest Node Pipelines",
"tabIndex": undefined,
"tabIndex": -1,
},
Object {
"id": "1.2",
"items": undefined,
"name": "Logstash Pipelines",
"tabIndex": undefined,
"tabIndex": -1,
},
Object {
"id": "1.3",
"items": undefined,
"name": "Beats Central Management",
"tabIndex": undefined,
"tabIndex": -1,
},
],
"name": "Ingest",
"tabIndex": undefined,
"tabIndex": -1,
},
Object {
"id": "2",
@ -513,23 +892,23 @@ exports[`SolutionNav renders with icon 1`] = `
"id": "2.1",
"items": undefined,
"name": "Index Management",
"tabIndex": undefined,
"tabIndex": -1,
},
Object {
"id": "2.2",
"items": undefined,
"name": "Index Lifecycle Policies",
"tabIndex": undefined,
"tabIndex": -1,
},
Object {
"id": "2.3",
"items": undefined,
"name": "Snapshot and Restore",
"tabIndex": undefined,
"tabIndex": -1,
},
],
"name": "Data",
"tabIndex": undefined,
"tabIndex": -1,
},
]
}
@ -537,5 +916,98 @@ exports[`SolutionNav renders with icon 1`] = `
/>
</EuiPanel>
</EuiCollapsibleNavGroup>
<div
className="kbnSolutionNav kbnSolutionNav--hidden"
>
<EuiTitle
id="SolutionNav_generated-id_heading"
size="xs"
>
<h2>
<KibanaSolutionAvatar
className="kbnSolutionNav__avatar"
iconType="logoElastic"
name="Solution"
/>
<strong>
<FormattedMessage
defaultMessage="{solutionName} {menuText}"
id="sharedUXPackages.solutionNav.mobileTitleText"
values={
Object {
"menuText": "menu",
"solutionName": "Solution",
}
}
/>
</strong>
</h2>
</EuiTitle>
<EuiSpacer
size="l"
/>
<EuiSideNav
aria-hidden={true}
aria-labelledby="SolutionNav_generated-id_heading"
items={
Array [
Object {
"id": "1",
"items": Array [
Object {
"id": "1.1",
"items": undefined,
"name": "Ingest Node Pipelines",
"tabIndex": -1,
},
Object {
"id": "1.2",
"items": undefined,
"name": "Logstash Pipelines",
"tabIndex": -1,
},
Object {
"id": "1.3",
"items": undefined,
"name": "Beats Central Management",
"tabIndex": -1,
},
],
"name": "Ingest",
"tabIndex": -1,
},
Object {
"id": "2",
"items": Array [
Object {
"id": "2.1",
"items": undefined,
"name": "Index Management",
"tabIndex": -1,
},
Object {
"id": "2.2",
"items": undefined,
"name": "Index Lifecycle Policies",
"tabIndex": -1,
},
Object {
"id": "2.3",
"items": undefined,
"name": "Snapshot and Restore",
"tabIndex": -1,
},
],
"name": "Data",
"tabIndex": -1,
},
]
}
mobileBreakpoints={Array []}
/>
</div>
<SolutionNavCollapseButton
isCollapsed={true}
/>
</Fragment>
`;

View file

@ -22,6 +22,7 @@ import {
EuiTitle,
htmlIdGenerator,
useIsWithinBreakpoints,
useIsWithinMinBreakpoint,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';
import { i18n } from '@kbn/i18n';
@ -100,7 +101,7 @@ export const SolutionNav: FC<SolutionNavProps> = ({
}) => {
const isSmallerBreakpoint = useIsWithinBreakpoints(mobileBreakpoints);
const isMediumBreakpoint = useIsWithinBreakpoints(['m']);
const isLargerBreakpoint = useIsWithinBreakpoints(['l', 'xl']);
const isLargerBreakpoint = useIsWithinMinBreakpoint('l');
// This is used for both the `EuiSideNav` and `EuiFlyout` toggling
const [isSideNavOpenOnMobile, setIsSideNavOpenOnMobile] = useState(false);

View file

@ -8,7 +8,12 @@
import React, { ComponentType, ReactNode, useState } from 'react';
import classNames from 'classnames';
import { useIsWithinBreakpoints, useEuiTheme, EuiPageSidebarProps } from '@elastic/eui';
import {
useIsWithinBreakpoints,
useEuiTheme,
useIsWithinMinBreakpoint,
EuiPageSidebarProps,
} from '@elastic/eui';
import { SolutionNav, SolutionNavProps } from './solution_nav';
import './with_solution_nav.scss';
@ -35,7 +40,7 @@ const SOLUTION_NAV_COLLAPSED_KEY = 'solutionNavIsCollapsed';
export const withSolutionNav = <P extends TemplateProps>(WrappedComponent: ComponentType<P>) => {
const WithSolutionNav = (props: Props<P>) => {
const isMediumBreakpoint = useIsWithinBreakpoints(['m']);
const isLargerBreakpoint = useIsWithinBreakpoints(['l', 'xl']);
const isLargerBreakpoint = useIsWithinMinBreakpoint('l');
const [isSideNavOpenOnDesktop, setisSideNavOpenOnDesktop] = useState(
!JSON.parse(String(localStorage.getItem(SOLUTION_NAV_COLLAPSED_KEY)))
);

View file

@ -84,6 +84,6 @@ export const LICENSE_OVERRIDES = {
'jsts@1.6.2': ['Eclipse Distribution License - v 1.0'], // cf. https://github.com/bjornharrtell/jsts
'@mapbox/jsonlint-lines-primitives@2.0.2': ['MIT'], // license in readme https://github.com/tmcw/jsonlint
'@elastic/ems-client@8.3.3': ['Elastic License 2.0'],
'@elastic/eui@63.0.6': ['SSPL-1.0 OR Elastic License 2.0'],
'@elastic/eui@64.0.4': ['SSPL-1.0 OR Elastic License 2.0'],
'language-subtag-registry@0.3.21': ['CC-BY-4.0'], // retired ODCBy license https://github.com/mattcg/language-subtag-registry
};

View file

@ -6,7 +6,7 @@
* Side Public License, v 1.
*/
import { EuiProvider } from '@elastic/eui';
import { EuiProvider, EuiProviderProps } from '@elastic/eui';
import createCache from '@emotion/cache';
import type { FC } from 'react';
import React, { useMemo } from 'react';
@ -19,6 +19,7 @@ import { getColorMode } from './utils';
interface KibanaThemeProviderProps {
theme$: Observable<CoreTheme>;
modify?: EuiProviderProps<{}>['modify'];
}
const defaultTheme: CoreTheme = {
@ -38,7 +39,7 @@ emotionCache.compat = true;
/**
* Copied from the `kibana_react` plugin, remove once https://github.com/elastic/kibana/issues/119204 is implemented.
*/
export const KibanaThemeProvider: FC<KibanaThemeProviderProps> = ({ theme$, children }) => {
export const KibanaThemeProvider: FC<KibanaThemeProviderProps> = ({ theme$, modify, children }) => {
const theme = useObservable(theme$, defaultTheme);
const colorMode = useMemo(() => getColorMode(theme), [theme]);
return (
@ -47,6 +48,7 @@ export const KibanaThemeProvider: FC<KibanaThemeProviderProps> = ({ theme$, chil
cache={{ default: emotionCache, global: globalCache }}
globalStyles={false}
utilityClasses={false}
modify={modify}
>
{children}
</EuiProvider>

View file

@ -9,13 +9,14 @@
import React, { FC, useMemo } from 'react';
import useObservable from 'react-use/lib/useObservable';
import { Observable } from 'rxjs';
import { EuiProvider } from '@elastic/eui';
import { EuiProvider, EuiProviderProps } from '@elastic/eui';
import createCache from '@emotion/cache';
import type { CoreTheme } from '@kbn/core/public';
import { getColorMode } from './utils';
interface KibanaThemeProviderProps {
theme$: Observable<CoreTheme>;
modify?: EuiProviderProps<{}>['modify'];
}
const defaultTheme: CoreTheme = {
@ -36,7 +37,7 @@ emotionCache.compat = true;
That copy and this comment can be removed once https://github.com/elastic/kibana/issues/119204 is implemented.*/
// IMPORTANT: This code has been copied to the `kibana_utils` plugin, to avoid cyclical dependency, any changes here should be applied there too.
export const KibanaThemeProvider: FC<KibanaThemeProviderProps> = ({ theme$, children }) => {
export const KibanaThemeProvider: FC<KibanaThemeProviderProps> = ({ theme$, modify, children }) => {
const theme = useObservable(theme$, defaultTheme);
const colorMode = useMemo(() => getColorMode(theme), [theme]);
return (
@ -45,6 +46,7 @@ export const KibanaThemeProvider: FC<KibanaThemeProviderProps> = ({ theme$, chil
cache={{ default: emotionCache, global: globalCache }}
globalStyles={false}
utilityClasses={false}
modify={modify}
>
{children}
</EuiProvider>

View file

@ -6,7 +6,7 @@
* Side Public License, v 1.
*/
import { EuiProvider } from '@elastic/eui';
import { EuiProvider, EuiProviderProps } from '@elastic/eui';
import createCache from '@emotion/cache';
import type { FC } from 'react';
import React, { useMemo } from 'react';
@ -18,6 +18,7 @@ import { getColorMode } from './utils';
interface KibanaThemeProviderProps {
theme$: Observable<CoreTheme>;
modify?: EuiProviderProps<{}>['modify'];
}
const defaultTheme: CoreTheme = {
@ -37,7 +38,7 @@ emotionCache.compat = true;
/**
* Copied from the `kibana_react` plugin, to avoid cyclical dependency
*/
export const KibanaThemeProvider: FC<KibanaThemeProviderProps> = ({ theme$, children }) => {
export const KibanaThemeProvider: FC<KibanaThemeProviderProps> = ({ theme$, modify, children }) => {
const theme = useObservable(theme$, defaultTheme);
const colorMode = useMemo(() => getColorMode(theme), [theme]);
return (
@ -46,6 +47,7 @@ export const KibanaThemeProvider: FC<KibanaThemeProviderProps> = ({ theme$, chil
cache={{ default: emotionCache, global: globalCache }}
globalStyles={false}
utilityClasses={false}
modify={modify}
>
{children}
</EuiProvider>

View file

@ -64,7 +64,15 @@ export const renderApp = ({
element.classList.add(APP_WRAPPER_CLASS);
ReactDOM.render(
<KibanaThemeProvider theme$={theme$}>
<KibanaThemeProvider
theme$={theme$}
modify={{
breakpoint: {
xxl: 1600,
xxxl: 2000,
},
}}
>
<ApmAppRoot
apmPluginContextValue={apmPluginContextValue}
pluginsStart={pluginsStart}

View file

@ -1,153 +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 { getScreenSizes } from './use_breakpoints';
describe('use_breakpoints', () => {
describe('getScreenSizes', () => {
it('return xs when within 0px - 5740x', () => {
expect(getScreenSizes(0)).toEqual({
isXSmall: true,
isSmall: true,
isMedium: true,
isLarge: true,
isXl: true,
isXXL: true,
isXXXL: false,
});
expect(getScreenSizes(574)).toEqual({
isXSmall: true,
isSmall: true,
isMedium: true,
isLarge: true,
isXl: true,
isXXL: true,
isXXXL: false,
});
});
it('return s when within 575px - 767px', () => {
expect(getScreenSizes(575)).toEqual({
isXSmall: false,
isSmall: true,
isMedium: true,
isLarge: true,
isXl: true,
isXXL: true,
isXXXL: false,
});
expect(getScreenSizes(767)).toEqual({
isXSmall: false,
isSmall: true,
isMedium: true,
isLarge: true,
isXl: true,
isXXL: true,
isXXXL: false,
});
});
it('return m when within 768px - 991', () => {
expect(getScreenSizes(768)).toEqual({
isXSmall: false,
isSmall: false,
isMedium: true,
isLarge: true,
isXl: true,
isXXL: true,
isXXXL: false,
});
expect(getScreenSizes(991)).toEqual({
isXSmall: false,
isSmall: false,
isMedium: true,
isLarge: true,
isXl: true,
isXXL: true,
isXXXL: false,
});
});
it('return l when within 992px - 1199px', () => {
expect(getScreenSizes(992)).toEqual({
isXSmall: false,
isSmall: false,
isMedium: false,
isLarge: true,
isXl: true,
isXXL: true,
isXXXL: false,
});
expect(getScreenSizes(1199)).toEqual({
isXSmall: false,
isSmall: false,
isMedium: false,
isLarge: true,
isXl: true,
isXXL: true,
isXXXL: false,
});
});
it('return xl when within 1200px - 1599px', () => {
expect(getScreenSizes(1200)).toEqual({
isXSmall: false,
isSmall: false,
isMedium: false,
isLarge: false,
isXl: true,
isXXL: true,
isXXXL: false,
});
expect(getScreenSizes(1599)).toEqual({
isXSmall: false,
isSmall: false,
isMedium: false,
isLarge: false,
isXl: true,
isXXL: true,
isXXXL: false,
});
});
it('return xxl when within 1600px - 1999px', () => {
expect(getScreenSizes(1600)).toEqual({
isXSmall: false,
isSmall: false,
isMedium: false,
isLarge: false,
isXl: false,
isXXL: true,
isXXXL: false,
});
expect(getScreenSizes(1999)).toEqual({
isXSmall: false,
isSmall: false,
isMedium: false,
isLarge: false,
isXl: false,
isXXL: true,
isXXXL: false,
});
});
it('return xxxl when greater than or equals to 2000px', () => {
expect(getScreenSizes(2000)).toEqual({
isXSmall: false,
isSmall: false,
isMedium: false,
isLarge: false,
isXl: false,
isXXL: false,
isXXXL: true,
});
expect(getScreenSizes(3000)).toEqual({
isXSmall: false,
isSmall: false,
isMedium: false,
isLarge: false,
isXl: false,
isXXL: false,
isXXXL: true,
});
});
});
});

View file

@ -0,0 +1,125 @@
/*
* 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, { FC } from 'react';
import { renderHook } from '@testing-library/react-hooks';
import { EuiProvider } from '@elastic/eui';
import { useBreakpoints } from './use_breakpoints';
const wrapper: FC = ({ children }) => (
<EuiProvider
modify={{
// set in apm/public/application/index.tsx
breakpoint: {
xxl: 1600,
xxxl: 2000,
},
}}
>
{children}
</EuiProvider>
);
describe('useBreakpoints', () => {
test('xs breakpoint', () => {
window.innerWidth = 0;
const { result } = renderHook(() => useBreakpoints(), { wrapper });
expect(result.current).toEqual({
isXSmall: true,
isSmall: true,
isMedium: true,
isLarge: true,
isXl: true,
isXXL: true,
isXXXL: false,
});
});
test('s breakpoint', () => {
window.innerWidth = 575;
const { result } = renderHook(() => useBreakpoints(), { wrapper });
expect(result.current).toEqual({
isXSmall: false,
isSmall: true,
isMedium: true,
isLarge: true,
isXl: true,
isXXL: true,
isXXXL: false,
});
});
test('m breakpoint', () => {
window.innerWidth = 768;
const { result } = renderHook(() => useBreakpoints(), { wrapper });
expect(result.current).toEqual({
isXSmall: false,
isSmall: false,
isMedium: true,
isLarge: true,
isXl: true,
isXXL: true,
isXXXL: false,
});
});
test('l breakpoint', () => {
window.innerWidth = 992;
const { result } = renderHook(() => useBreakpoints(), { wrapper });
expect(result.current).toEqual({
isXSmall: false,
isSmall: false,
isMedium: false,
isLarge: true,
isXl: true,
isXXL: true,
isXXXL: false,
});
});
test('xl breakpoint', () => {
window.innerWidth = 1200;
const { result } = renderHook(() => useBreakpoints(), { wrapper });
expect(result.current).toEqual({
isXSmall: false,
isSmall: false,
isMedium: false,
isLarge: false,
isXl: true,
isXXL: true,
isXXXL: false,
});
});
test('xxl breakpoint', () => {
window.innerWidth = 1600;
const { result } = renderHook(() => useBreakpoints(), { wrapper });
expect(result.current).toEqual({
isXSmall: false,
isSmall: false,
isMedium: false,
isLarge: false,
isXl: false,
isXXL: true,
isXXXL: false,
});
});
test('xxxl breakpoint', () => {
window.innerWidth = 2000;
const { result } = renderHook(() => useBreakpoints(), { wrapper });
expect(result.current).toEqual({
isXSmall: false,
isSmall: false,
isMedium: false,
isLarge: false,
isXl: false,
isXXL: false,
isXXXL: true,
});
});
});

View file

@ -5,42 +5,23 @@
* 2.0.
*/
import { useState } from 'react';
import useWindowSize from 'react-use/lib/useWindowSize';
import useDebounce from 'react-use/lib/useDebounce';
import {
getBreakpoint,
isWithinMaxBreakpoint,
isWithinMinBreakpoint,
useIsWithinMaxBreakpoint,
useIsWithinMinBreakpoint,
} from '@elastic/eui';
export type Breakpoints = ReturnType<typeof getScreenSizes>;
export function getScreenSizes(windowWidth: number) {
return {
isXSmall: isWithinMaxBreakpoint(windowWidth, 'xs'),
isSmall: isWithinMaxBreakpoint(windowWidth, 's'),
isMedium: isWithinMaxBreakpoint(windowWidth, 'm'),
isLarge: isWithinMaxBreakpoint(windowWidth, 'l'),
isXl: isWithinMaxBreakpoint(windowWidth, 1599),
isXXL: isWithinMaxBreakpoint(windowWidth, 1999),
isXXXL: isWithinMinBreakpoint(windowWidth, 2000),
};
}
export type Breakpoints = Record<string, boolean>;
export function useBreakpoints() {
const { width } = useWindowSize();
const [breakpoint, setBreakpoint] = useState(getBreakpoint(width));
const [screenSizes, setScreenSizes] = useState(getScreenSizes(width));
const screenSizes = {
isXSmall: useIsWithinMaxBreakpoint('xs'),
isSmall: useIsWithinMaxBreakpoint('s'),
isMedium: useIsWithinMaxBreakpoint('m'),
isLarge: useIsWithinMaxBreakpoint('l'),
isXl: useIsWithinMaxBreakpoint('xl'),
isXXL: useIsWithinMaxBreakpoint('xxl'),
isXXXL: useIsWithinMinBreakpoint('xxxl'),
};
useDebounce(
() => {
setBreakpoint(getBreakpoint(width));
setScreenSizes(getScreenSizes(width));
},
50,
[width]
);
return { ...screenSizes, breakpoint, width };
return screenSizes;
}

View file

@ -36,6 +36,7 @@ exports[`Storyshots components/Variables/VarConfig default 1`] = `
aria-controls="accordion-variables"
aria-expanded={false}
className="euiAccordion__button emotion-euiAccordion__button"
disabled={false}
id="generated-id"
onClick={[Function]}
type="button"

View file

@ -41,6 +41,7 @@ exports[`Storyshots components/WorkpadFilters/FiltersGroupComponent default 1`]
aria-controls="canvas-filter-group-0"
aria-expanded={true}
className="euiAccordion__button emotion-euiAccordion__button"
disabled={false}
id="generated-id"
onClick={[Function]}
type="button"
@ -696,6 +697,7 @@ exports[`Storyshots components/WorkpadFilters/FiltersGroupComponent empty group
aria-controls="canvas-filter-group-0"
aria-expanded={true}
className="euiAccordion__button emotion-euiAccordion__button"
disabled={false}
id="generated-id"
onClick={[Function]}
type="button"

View file

@ -206,6 +206,7 @@ exports[`Storyshots components/WorkpadFilters/WorkpadFiltersComponent Filters gr
aria-controls="canvas-filter-group-0"
aria-expanded={true}
className="euiAccordion__button emotion-euiAccordion__button"
disabled={false}
id="generated-id"
onClick={[Function]}
type="button"
@ -941,6 +942,7 @@ exports[`Storyshots components/WorkpadFilters/WorkpadFiltersComponent Filters gr
aria-controls="canvas-filter-group-0"
aria-expanded={true}
className="euiAccordion__button emotion-euiAccordion__button"
disabled={false}
id="generated-id"
onClick={[Function]}
type="button"
@ -1676,6 +1678,7 @@ exports[`Storyshots components/WorkpadFilters/WorkpadFiltersComponent Filters gr
aria-controls="canvas-filter-group-0"
aria-expanded={true}
className="euiAccordion__button emotion-euiAccordion__button"
disabled={false}
id="generated-id"
onClick={[Function]}
type="button"
@ -1834,6 +1837,7 @@ exports[`Storyshots components/WorkpadFilters/WorkpadFiltersComponent default 1`
aria-controls="canvas-filter-group-0"
aria-expanded={true}
className="euiAccordion__button emotion-euiAccordion__button"
disabled={false}
id="generated-id"
onClick={[Function]}
type="button"
@ -2194,6 +2198,7 @@ exports[`Storyshots components/WorkpadFilters/WorkpadFiltersComponent default 1`
aria-controls="canvas-filter-group-1"
aria-expanded={true}
className="euiAccordion__button emotion-euiAccordion__button"
disabled={false}
id="generated-id"
onClick={[Function]}
type="button"

View file

@ -134,7 +134,7 @@ export const DataVisualizerTable = <T extends DataVisualizerTableItem>({
const columns = useMemo(() => {
const expanderColumn: EuiTableComputedColumnType<DataVisualizerTableItem> = {
name:
dimensions.breakPoint !== 'xs' && dimensions.breakPoint !== 's' ? (
dimensions.breakPoint !== 'small' ? (
<EuiButtonIcon
data-test-subj={`dataVisualizerToggleDetailsForAllRowsButton ${
expandAll ? 'expanded' : 'collapsed'

View file

@ -5,7 +5,6 @@
* 2.0.
*/
import { getBreakpoint } from '@elastic/eui';
import { FileBasedFieldVisConfig } from './types';
export const getTFPercentage = (config: FileBasedFieldVisConfig) => {
@ -38,6 +37,13 @@ export const getTFPercentage = (config: FileBasedFieldVisConfig) => {
};
};
// Map of DataVisualizerTable breakpoints specific to the table component
// Note that the table width is not always the full width of the browser window
const TABLE_BREAKPOINTS = {
small: 600,
medium: 1000,
large: Infinity, // default
};
export const calculateTableColumnsDimensions = (width?: number) => {
const defaultSettings = {
expander: '40px',
@ -46,36 +52,30 @@ export const calculateTableColumnsDimensions = (width?: number) => {
distinctValues: '225px',
distributions: '225px',
showIcon: true,
breakPoint: 'xl',
breakPoint: 'large',
};
if (width === undefined) return defaultSettings;
const breakPoint = getBreakpoint(width);
switch (breakPoint) {
case 'xs':
case 's':
return {
expander: '25px',
type: '40px',
docCount: 'auto',
distinctValues: 'auto',
distributions: 'auto',
showIcon: false,
breakPoint,
};
case 'm':
case 'l':
return {
expander: '25px',
type: '40px',
docCount: 'auto',
distinctValues: 'auto',
distributions: 'auto',
showIcon: false,
breakPoint,
};
default:
return defaultSettings;
if (width <= TABLE_BREAKPOINTS.small) {
return {
expander: '25px',
type: '40px',
docCount: 'auto',
distinctValues: 'auto',
distributions: 'auto',
showIcon: false,
breakPoint: 'small',
};
}
if (width <= TABLE_BREAKPOINTS.medium) {
return {
expander: '25px',
type: '40px',
docCount: 'auto',
distinctValues: 'auto',
distributions: 'auto',
showIcon: false,
breakPoint: 'medium',
};
}
return defaultSettings;
};

View file

@ -24,7 +24,9 @@ describe('Enrollment token page', () => {
},
headers: { 'kbn-xsrf': 'cypress' },
});
cy.getBySel(ENROLLMENT_TOKENS_TAB).click();
cy.getBySel(ENROLLMENT_TOKENS_TAB, {
timeout: 15000,
}).click();
});
after(() => {

View file

@ -6,7 +6,6 @@
*/
import React from 'react';
import styled from 'styled-components';
import useWindowSize from 'react-use/lib/useWindowSize';
import { FormattedMessage } from '@kbn/i18n-react';
import type { EuiImageProps } from '@elastic/eui';
@ -22,7 +21,7 @@ import {
EuiLink,
EuiHideFor,
EuiShowFor,
isWithinMaxBreakpoint,
useIsWithinMaxBreakpoint,
} from '@elastic/eui';
import type { RegistryPolicyTemplate, PackageInfo } from '../../../../../types';
@ -66,8 +65,7 @@ const CenteredEuiImage = (props: EuiImageProps) => (
);
const ResponsiveStepGroup: React.FC = ({ children }) => {
const { width } = useWindowSize();
const isScreenSmall = isWithinMaxBreakpoint(width, 's');
const isScreenSmall = useIsWithinMaxBreakpoint('s');
return (
<EuiFlexGroup

View file

@ -7,7 +7,7 @@
import { i18n } from '@kbn/i18n';
import React, { useCallback } from 'react';
import { getBreakpoint } from '@elastic/eui';
import { useCurrentEuiBreakpoint } from '@elastic/eui';
import { euiStyled } from '@kbn/kibana-react-plugin/common';
import { InventoryItemType } from '../../../../../common/inventory_models/types';
@ -58,6 +58,8 @@ export const NodesOverview = ({
topMargin,
showLoading,
}: Props) => {
const currentBreakpoint = useCurrentEuiBreakpoint();
const handleDrilldown = useCallback(
(filter: string) => {
onDrilldown({
@ -102,7 +104,7 @@ export const NodesOverview = ({
}
const dataBounds = calculateBoundsFromNodes(nodes);
const bounds = autoBounds ? dataBounds : boundsOverride;
const isStatic = ['xs', 's'].includes(getBreakpoint(window.innerWidth)!);
const isStatic = ['xs', 's'].includes(currentBreakpoint!);
if (view === 'table') {
return (

View file

@ -16,12 +16,12 @@ import type { DefaultSideNavItem } from './types';
import { bottomNavOffset } from '../../../lib/helpers';
import { BETA } from '@kbn/kubernetes-security-plugin/common/translations';
const mockUseIsWithinBreakpoints = jest.fn(() => true);
const mockUseIsWithinMinBreakpoint = jest.fn(() => true);
jest.mock('@elastic/eui', () => {
const original = jest.requireActual('@elastic/eui');
return {
...original,
useIsWithinBreakpoints: () => mockUseIsWithinBreakpoints(),
useIsWithinMinBreakpoint: () => mockUseIsWithinMinBreakpoint(),
};
});
@ -143,14 +143,14 @@ describe('SolutionGroupedNav', () => {
describe('bottom offset', () => {
it('should add bottom offset', () => {
mockUseIsWithinBreakpoints.mockReturnValueOnce(true);
mockUseIsWithinMinBreakpoint.mockReturnValueOnce(true);
const result = renderNavPanel({ bottomOffset: bottomNavOffset });
expect(result.getByTestId('groupedNavPanel')).toHaveStyle({ bottom: bottomNavOffset });
});
it('should not add bottom offset if not large screen', () => {
mockUseIsWithinBreakpoints.mockReturnValueOnce(false);
mockUseIsWithinMinBreakpoint.mockReturnValueOnce(false);
const result = renderNavPanel({ bottomOffset: bottomNavOffset });
expect(result.getByTestId('groupedNavPanel')).not.toHaveStyle({ bottom: bottomNavOffset });

View file

@ -20,7 +20,7 @@ import {
EuiTitle,
EuiWindowEvent,
keys,
useIsWithinBreakpoints,
useIsWithinMinBreakpoint,
} from '@elastic/eui';
import classNames from 'classnames';
import { EuiPanelStyled, FlexLink } from './solution_grouped_nav_panel.styles';
@ -57,7 +57,7 @@ const SolutionNavPanelComponent: React.FC<SolutionNavPanelProps> = ({
items,
bottomOffset,
}) => {
const isLargerBreakpoint = useIsWithinBreakpoints(['l', 'xl']);
const isLargerBreakpoint = useIsWithinMinBreakpoint('l');
const panelClasses = classNames('eui-yScroll');
// Only larger breakpoint needs to add bottom offset, other sizes should have full height

View file

@ -11,14 +11,6 @@ import 'jest-styled-components';
import { render } from '../../../utils/testing/rtl_helpers';
import { SyntheticsPageTemplateComponent } from './synthetics_page_template';
import { OVERVIEW_ROUTE } from '../../../../../../common/constants';
import { useBreakpoints } from '../../../../../hooks/use_breakpoints';
jest.mock('../../../../../hooks/use_breakpoints', () => {
const down = jest.fn().mockReturnValue(false);
return {
useBreakpoints: () => ({ down }),
};
});
describe('SyntheticsPageTemplateComponent', () => {
describe('styling', () => {
@ -34,7 +26,7 @@ describe('SyntheticsPageTemplateComponent', () => {
});
it('applies the header centering on mobile', () => {
(useBreakpoints().down as jest.Mock).mockReturnValue(true);
window.innerWidth = 600;
const { container } = render(<SyntheticsPageTemplateComponent path={OVERVIEW_ROUTE} />);
expect(container.firstChild).toBeDefined();
});

View file

@ -7,14 +7,13 @@
import React, { useEffect, useMemo } from 'react';
import styled from 'styled-components';
import { EuiPageHeaderProps, EuiPageTemplateProps } from '@elastic/eui';
import { EuiPageHeaderProps, EuiPageTemplateProps, useIsWithinMaxBreakpoint } from '@elastic/eui';
import { useKibana } from '@kbn/kibana-react-plugin/public';
import { useInspectorContext } from '@kbn/observability-plugin/public';
import { ClientPluginsStart } from '../../../../../plugin';
import { EmptyStateLoading } from '../../monitors_page/overview/empty_state/empty_state_loading';
import { EmptyStateError } from '../../monitors_page/overview/empty_state/empty_state_error';
import { useHasData } from '../../monitors_page/overview/empty_state/use_has_data';
import { useBreakpoints } from '../../../hooks';
interface Props {
path: string;
@ -36,8 +35,7 @@ export const SyntheticsPageTemplateComponent: React.FC<Props & EuiPageTemplatePr
const {
services: { observability },
} = useKibana<ClientPluginsStart>();
const { down } = useBreakpoints();
const isMobile = down('s');
const isMobile = useIsWithinMaxBreakpoint('s');
const PageTemplateComponent = observability.navigation.PageTemplate;
const StyledPageTemplateComponent = useMemo(() => {

View file

@ -13,6 +13,7 @@ import {
EuiPanel,
EuiSpacer,
useEuiTheme,
useIsWithinMinBreakpoint,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { ListFilters } from '../list_filters/list_filters';
@ -25,7 +26,6 @@ import {
EncryptedSyntheticsSavedMonitor,
} from '../../../../../../../common/runtime_types';
import { SyntheticsSettingsContext } from '../../../../contexts/synthetics_settings_context';
import { useBreakpoints } from '../../../../hooks';
import { getMonitorListColumns } from './columns';
import * as labels from './labels';
@ -51,7 +51,7 @@ export const MonitorList = ({
errorSummaries,
}: Props) => {
const { basePath } = useContext(SyntheticsSettingsContext);
const isXl = useBreakpoints().up('xl');
const isXl = useIsWithinMinBreakpoint('xxl');
const canEditSynthetics = useCanEditSynthetics();
const { euiTheme } = useEuiTheme();

View file

@ -7,7 +7,6 @@
export * from './use_url_params';
export * from './use_breadcrumbs';
export * from '../../../hooks/use_breakpoints';
export * from './use_service_allowed';
export * from './use_enablement';
export * from './use_locations';

View file

@ -71,7 +71,15 @@ const Application = (props: SyntheticsAppProps) => {
return (
<EuiErrorBoundary>
<i18nCore.Context>
<KibanaThemeProvider theme$={props.appMountParameters.theme$}>
<KibanaThemeProvider
theme$={props.appMountParameters.theme$}
modify={{
breakpoint: {
xxl: 1600,
xxxl: 2000,
},
}}
>
<ReduxProvider store={store}>
<KibanaContextProvider
services={{

View file

@ -1,96 +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 { BREAKPOINTS } from '@elastic/eui';
import { renderHook } from '@testing-library/react-hooks';
import { useBreakpoints } from './use_breakpoints';
describe('use_breakpoints', () => {
describe('useBreakpoints', () => {
const width = global.innerWidth;
beforeEach(() => {
jest.useFakeTimers();
});
afterEach(() => {
jest.runOnlyPendingTimers();
jest.useRealTimers();
});
afterAll(() => {
(global as { innerWidth: number }).innerWidth = width;
});
it('should only return up => false and down => true for "xs" when width is less than BREAKPOINTS.xs', () => {
(global as { innerWidth: number }).innerWidth = BREAKPOINTS.xs - 1;
const { result } = renderHook(() => useBreakpoints());
expect(result.current.up('xs')).toBeFalsy();
expect(result.current.down('xs')).toBeTruthy();
});
it('should only return up => true and down => false for "xs" when width is above or equal BREAKPOINTS.xs', () => {
(global as { innerWidth: number }).innerWidth = BREAKPOINTS.xs;
const { result } = renderHook(() => useBreakpoints());
expect(result.current.up('xs')).toBeTruthy();
expect(result.current.down('xs')).toBeFalsy();
});
it('should return down => true for "m" when width equals BREAKPOINTS.l', () => {
(global as { innerWidth: number }).innerWidth = BREAKPOINTS.l;
const { result } = renderHook(() => useBreakpoints());
expect(result.current.up('m')).toBeTruthy();
expect(result.current.down('m')).toBeFalsy();
});
it('should return `between` => true for "m" and "xl" when width equals BREAKPOINTS.l', () => {
(global as { innerWidth: number }).innerWidth = BREAKPOINTS.l;
const { result } = renderHook(() => useBreakpoints());
expect(result.current.between('m', 'xl')).toBeTruthy();
});
it('should return `between` => true for "s" and "m" when width equals BREAKPOINTS.s', () => {
(global as { innerWidth: number }).innerWidth = BREAKPOINTS.s;
const { result } = renderHook(() => useBreakpoints());
expect(result.current.between('s', 'm')).toBeTruthy();
});
it('should return up => true for all when size is > xxxl+', () => {
(global as { innerWidth: number }).innerWidth = 3000;
const { result } = renderHook(() => useBreakpoints());
expect(result.current.up('xs')).toBeTruthy();
expect(result.current.up('s')).toBeTruthy();
expect(result.current.up('m')).toBeTruthy();
expect(result.current.up('l')).toBeTruthy();
expect(result.current.up('xl')).toBeTruthy();
expect(result.current.up('xxl')).toBeTruthy();
expect(result.current.up('xxxl')).toBeTruthy();
});
it('should determine `isIpad (Portrait)', () => {
(global as { innerWidth: number }).innerWidth = 768;
const { result } = renderHook(() => useBreakpoints());
const isIpad = result.current.up('m') && result.current.down('l');
expect(isIpad).toEqual(true);
});
it('should determine `isMobile (Portrait)`', () => {
(global as { innerWidth: number }).innerWidth = 480;
const { result } = renderHook(() => useBreakpoints());
const isMobile = result.current.up('xs') && result.current.down('s');
expect(isMobile).toEqual(true);
});
});
});

View file

@ -1,114 +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 { useCallback, useState } from 'react';
import useWindowSize from 'react-use/lib/useWindowSize';
import useDebounce from 'react-use/lib/useDebounce';
import { BREAKPOINTS, EuiBreakpointSize } from '@elastic/eui';
// Custom breakpoints
const BREAKPOINT_XL = 1599; // Overriding the theme's default 'xl' breakpoint
const BREAKPOINT_XXL = 1599;
const BREAKPOINT_XXXL = 2000;
export type BreakpointKey = EuiBreakpointSize | 'xxl' | 'xxxl';
type BreakpointPredicate = (breakpointKey: BreakpointKey) => boolean;
type BreakpointRangePredicate = (from: BreakpointKey, to: BreakpointKey) => boolean;
/**
* Returns the predicates functions used to determine whether the current device's width is above or below the asked
* breakpoint. (Implementation inspired by React Material UI).
*
* @example
* const { breakpoints } = useBreakpoints();
* const isMobile = breakpoint.down('m');
*
* @example
* const { breakpoints } = useBreakpoints();
* const isTablet = breakpoint.between('m', 'l');
*
* @param debounce {number} Debounce interval for optimization
*
* @returns { {up: BreakpointPredicate, down: BreakpointPredicate, between: BreakpointRangePredicate} }
* Returns object containing predicates which determine whether the current device's width lies above, below or
* in-between the given breakpoint(s)
* {
* up => Returns `true` if the current width is equal or above (inclusive) the given breakpoint size,
* or `false` otherwise.
* down => Returns `true` if the current width is below (exclusive) the given breakpoint size, or `false` otherwise.
* between => Returns `true` if the current width is equal or above (inclusive) the corresponding size of
* `fromBreakpointKey` AND is below (exclusive) the corresponding width of `toBreakpointKey`.
* Returns `false` otherwise.
* }
*/
export function useBreakpoints(debounce = 50) {
const { width } = useWindowSize();
const [debouncedWidth, setDebouncedWidth] = useState(width);
const up = useCallback<BreakpointPredicate>(
(breakpointKey: BreakpointKey) => isUp(debouncedWidth, breakpointKey),
[debouncedWidth]
);
const down = useCallback<BreakpointPredicate>(
(breakpointKey: BreakpointKey) => isDown(debouncedWidth, breakpointKey),
[debouncedWidth]
);
const between = useCallback<BreakpointRangePredicate>(
(fromBreakpointKey: BreakpointKey, toBreakpointKey: BreakpointKey) =>
isBetween(debouncedWidth, fromBreakpointKey, toBreakpointKey),
[debouncedWidth]
);
useDebounce(
() => {
setDebouncedWidth(width);
},
debounce,
[width]
);
return { up, down, between, debouncedWidth };
}
/**
* Returns the corresponding device width against the provided breakpoint key, either the overridden value or the
* default value from theme.
* @param key {BreakpointKey} string key representing the device breakpoint e.g. 'xs', 's', 'xxxl'
*/
function getSizeForBreakpointKey(key: BreakpointKey): number {
switch (key) {
case 'xxxl':
return BREAKPOINT_XXXL;
case 'xxl':
return BREAKPOINT_XXL;
case 'xl':
return BREAKPOINT_XL;
case 'l':
return BREAKPOINTS.l;
case 'm':
return BREAKPOINTS.m;
case 's':
return BREAKPOINTS.s;
}
return BREAKPOINTS.xs;
}
function isUp(size: number, breakpointKey: BreakpointKey) {
return size >= getSizeForBreakpointKey(breakpointKey);
}
function isDown(size: number, breakpointKey: BreakpointKey) {
return size < getSizeForBreakpointKey(breakpointKey);
}
function isBetween(size: number, fromBreakpointKey: BreakpointKey, toBreakpointKey: BreakpointKey) {
return isUp(size, fromBreakpointKey) && isDown(size, toBreakpointKey);
}

View file

@ -104,7 +104,15 @@ const Application = (props: UptimeAppProps) => {
return (
<EuiErrorBoundary>
<i18nCore.Context>
<KibanaThemeProvider theme$={props.appMountParameters.theme$}>
<KibanaThemeProvider
theme$={props.appMountParameters.theme$}
modify={{
breakpoint: {
xxl: 1600,
xxxl: 2000,
},
}}
>
<ReduxProvider store={store}>
<KibanaContextProvider
services={{

View file

@ -11,14 +11,6 @@ import 'jest-styled-components';
import { render } from '../lib/helper/rtl_helpers';
import { UptimePageTemplateComponent } from './uptime_page_template';
import { OVERVIEW_ROUTE } from '../../../common/constants';
import { useBreakpoints } from '../../hooks/use_breakpoints';
jest.mock('../../hooks/use_breakpoints', () => {
const down = jest.fn().mockReturnValue(false);
return {
useBreakpoints: () => ({ down }),
};
});
describe('UptimePageTemplateComponent', () => {
describe('styling', () => {
@ -34,7 +26,7 @@ describe('UptimePageTemplateComponent', () => {
});
it('applies the header centering on mobile', () => {
(useBreakpoints().down as jest.Mock).mockReturnValue(true);
window.innerWidth = 600;
const { container } = render(<UptimePageTemplateComponent path={OVERVIEW_ROUTE} />);
expect(container.firstChild).toMatchSnapshot();
});

View file

@ -7,7 +7,7 @@
import React, { useEffect, useMemo } from 'react';
import styled from 'styled-components';
import { EuiPageHeaderProps, EuiPageTemplateProps } from '@elastic/eui';
import { EuiPageHeaderProps, EuiPageTemplateProps, useIsWithinMaxBreakpoint } from '@elastic/eui';
import { useKibana } from '@kbn/kibana-react-plugin/public';
import { useInspectorContext } from '@kbn/observability-plugin/public';
import { CERTIFICATES_ROUTE, OVERVIEW_ROUTE } from '../../../common/constants';
@ -16,7 +16,6 @@ import { useNoDataConfig } from './use_no_data_config';
import { EmptyStateLoading } from '../components/overview/empty_state/empty_state_loading';
import { EmptyStateError } from '../components/overview/empty_state/empty_state_error';
import { useHasData } from '../components/overview/empty_state/use_has_data';
import { useBreakpoints } from '../../hooks/use_breakpoints';
interface Props {
path: string;
@ -38,8 +37,7 @@ export const UptimePageTemplateComponent: React.FC<Props & EuiPageTemplateProps>
const {
services: { observability },
} = useKibana<ClientPluginsStart>();
const { down } = useBreakpoints();
const isMobile = down('s');
const isMobile = useIsWithinMaxBreakpoint('s');
const PageTemplateComponent = observability.navigation.PageTemplate;
const StyledPageTemplateComponent = useMemo(() => {

View file

@ -6,11 +6,17 @@
*/
import React, { MouseEvent, useEffect } from 'react';
import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiText, useEuiTheme } from '@elastic/eui';
import {
EuiButtonEmpty,
EuiFlexGroup,
EuiFlexItem,
EuiText,
useEuiTheme,
useIsWithinMaxBreakpoint,
} from '@elastic/eui';
import { euiStyled } from '@kbn/kibana-react-plugin/common';
import { ScreenshotRefImageData } from '../../../../../../../common/runtime_types';
import { useBreakpoints } from '../../../../../../hooks/use_breakpoints';
import { nextAriaLabel, prevAriaLabel } from './translations';
@ -38,7 +44,7 @@ export const StepImageCaption: React.FC<StepImageCaptionProps> = ({
onVisible,
}) => {
const { euiTheme } = useEuiTheme();
const breakpoints = useBreakpoints();
const isSmall = useIsWithinMaxBreakpoint('m');
useEffect(() => {
onVisible(true);
@ -48,8 +54,6 @@ export const StepImageCaption: React.FC<StepImageCaptionProps> = ({
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const isSmall = breakpoints.down('m');
return (
<CaptionWrapper
onClick={(evt) => {

View file

@ -12,6 +12,7 @@ import {
EuiPanel,
EuiSpacer,
EuiText,
useIsWithinMinBreakpoint,
} from '@elastic/eui';
import { EuiTableSortingType } from '@elastic/eui/src/components/basic_table/table_types';
import { i18n } from '@kbn/i18n';
@ -30,7 +31,6 @@ import {
BrowserFields,
} from '../../../../../common/runtime_types';
import { UptimeSettingsContext } from '../../../contexts';
import { useBreakpoints } from '../../../../hooks/use_breakpoints';
import { MonitorManagementList as MonitorManagementListState } from '../../../state/reducers/monitor_management';
import * as labels from '../../overview/monitor_list/translations';
import { Actions } from './actions';
@ -70,7 +70,7 @@ export const MonitorManagementList = ({
errorSummaries,
}: Props) => {
const { basePath } = useContext(UptimeSettingsContext);
const isXl = useBreakpoints().up('xl');
const isXl = useIsWithinMinBreakpoint('xxl');
const { total } = list as MonitorManagementListState['list'];
const monitors: EncryptedSyntheticsMonitorWithId[] = useMemo(

View file

@ -5,7 +5,6 @@
* 2.0.
*/
import React, { useState } from 'react';
import useWindowSize from 'react-use/lib/useWindowSize';
import useDebounce from 'react-use/lib/useDebounce';
import {
EuiButtonIcon,
@ -15,7 +14,7 @@ import {
EuiLink,
EuiPanel,
EuiSpacer,
getBreakpoint,
useCurrentEuiBreakpoint,
} from '@elastic/eui';
import { euiStyled } from '@kbn/kibana-react-plugin/common';
import { X509Expiry } from '../../../../../common/runtime_types';
@ -61,15 +60,17 @@ export const MonitorListComponent: ({
setPageSize,
}) => {
const [expandedDrawerIds, updateExpandedDrawerIds] = useState<string[]>([]);
const { width } = useWindowSize();
const currentBreakpoint = useCurrentEuiBreakpoint();
const [hideExtraColumns, setHideExtraColumns] = useState(false);
useDebounce(
() => {
setHideExtraColumns(['m', 'l'].includes(getBreakpoint(width) ?? ''));
if (currentBreakpoint) {
setHideExtraColumns(['m', 'l'].includes(currentBreakpoint));
}
},
50,
[width]
[currentBreakpoint]
);
const items = list.summaries ?? [];

View file

@ -6,13 +6,18 @@
*/
import React from 'react';
import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui';
import {
EuiButtonEmpty,
EuiFlexGroup,
EuiFlexItem,
EuiText,
useIsWithinMaxBreakpoint,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';
import { useHistory } from 'react-router-dom';
import moment from 'moment';
import { SyntheticsJourneyApiResponse } from '../../../../common/runtime_types/ping';
import { getShortTimeStamp } from '../../components/overview/monitor_list/columns/monitor_status_column';
import { useBreakpoints } from '../../../hooks/use_breakpoints';
interface Props {
timestamp: string;
@ -21,9 +26,7 @@ interface Props {
export const ChecksNavigation = ({ timestamp, details }: Props) => {
const history = useHistory();
const { down } = useBreakpoints();
const isMobile = down('s');
const isMobile = useIsWithinMaxBreakpoint('s');
return (
<EuiFlexGroup alignItems="center" responsive={false} gutterSize="none">

View file

@ -142,7 +142,15 @@ export function UXAppRoot({
lens,
}}
>
<KibanaThemeProvider theme$={appMountParameters.theme$}>
<KibanaThemeProvider
theme$={appMountParameters.theme$}
modify={{
breakpoint: {
xxl: 1600,
xxxl: 2000,
},
}}
>
<i18nCore.Context>
<RouterProvider history={history} router={uxRouter}>
<DatePickerContextProvider>

View file

@ -5,42 +5,23 @@
* 2.0.
*/
import { useState } from 'react';
import useWindowSize from 'react-use/lib/useWindowSize';
import useDebounce from 'react-use/lib/useDebounce';
import {
getBreakpoint,
isWithinMaxBreakpoint,
isWithinMinBreakpoint,
useIsWithinMaxBreakpoint,
useIsWithinMinBreakpoint,
} from '@elastic/eui';
export type Breakpoints = ReturnType<typeof getScreenSizes>;
export function getScreenSizes(windowWidth: number) {
return {
isXSmall: isWithinMaxBreakpoint(windowWidth, 'xs'),
isSmall: isWithinMaxBreakpoint(windowWidth, 's'),
isMedium: isWithinMaxBreakpoint(windowWidth, 'm'),
isLarge: isWithinMaxBreakpoint(windowWidth, 'l'),
isXl: isWithinMaxBreakpoint(windowWidth, 1599),
isXXL: isWithinMaxBreakpoint(windowWidth, 1999),
isXXXL: isWithinMinBreakpoint(windowWidth, 2000),
};
}
export type Breakpoints = Record<string, boolean>;
export function useBreakpoints() {
const { width } = useWindowSize();
const [breakpoint, setBreakpoint] = useState(getBreakpoint(width));
const [screenSizes, setScreenSizes] = useState(getScreenSizes(width));
const screenSizes = {
isXSmall: useIsWithinMaxBreakpoint('xs'),
isSmall: useIsWithinMaxBreakpoint('s'),
isMedium: useIsWithinMaxBreakpoint('m'),
isLarge: useIsWithinMaxBreakpoint('l'),
isXl: useIsWithinMaxBreakpoint('xl'),
isXXL: useIsWithinMaxBreakpoint('xxl'),
isXXXL: useIsWithinMinBreakpoint('xxxl'),
};
useDebounce(
() => {
setBreakpoint(getBreakpoint(width));
setScreenSizes(getScreenSizes(width));
},
50,
[width]
);
return { ...screenSizes, breakpoint, width };
return screenSizes;
}

View file

@ -1530,10 +1530,10 @@
resolved "https://registry.yarnpkg.com/@elastic/eslint-plugin-eui/-/eslint-plugin-eui-0.0.2.tgz#56b9ef03984a05cc213772ae3713ea8ef47b0314"
integrity sha512-IoxURM5zraoQ7C8f+mJb9HYSENiZGgRVcG4tLQxE61yHNNRDXtGDWTZh8N1KIHcsqN1CEPETjuzBXkJYF/fDiQ==
"@elastic/eui@63.0.6":
version "63.0.6"
resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-63.0.6.tgz#8f2d1d0bd1fd39ca67e9c65ecfef2dc7222af100"
integrity sha512-3uW/Q1VA9CMRLzm8lGhTHcBnyLhyoLPnJ3GdXxgTC4zzDlIlIsxrSnn+7sDxAsyVgnSCvHlO0dVbrEf1+G7Y8w==
"@elastic/eui@64.0.4":
version "64.0.4"
resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-64.0.4.tgz#4a6a997a3f43f459c82e3b992ac2e6ab318d5a12"
integrity sha512-4wpZcVJyNvxfZA58kVSwnJxIbWCrFriU6vARr/DoDB6Vvt/5zHeFrHzXFjdo+hqTWZApPoEQlK7aJ7FDZTEbkw==
dependencies:
"@types/chroma-js" "^2.0.0"
"@types/lodash" "^4.14.160"