[Canvas] Top Menu (#59982)

* Redesigned workpad_header to top menu layout

* Added comments

* Fixed element spec

* Removed element preview images

* Removed tooltip from menus

* Removed extraneous JSX

* Fixed element fixtures

* Moved component strings

* top menu design tweaks

* Added filter debug element

* Fix file picker in asset manager

* Sort components strings object keys

* Removed ElementTypes component in favor of SavedElementsModal

* Updated stories

* Fixed custom elements functional tests

* Removed unused tag strings

* Fixed test fixtures

* Updated element_menu stories

* Updated view_menu stories

* TS for SavedElementsModal

* Updated types

* Fixed TS errors

* Fix i18n errors

* Renamed stories

* Fixed test file name

* Fixed stories

* Updated storyshots

* Reverted storybook webpack config change

* Fixed SavedElementsModal stories

* Updated comments

* Removed unnecessary ts-ignores

* Moved workpad_shortcuts back to /components

* Unskip custom elements functional test

* Reverted workpad_loader changes

* Added element_menu stories and mocks

* Fixed element i18n strings

* Updated storyshots

* Updated storyshot

Co-authored-by: Ryan Keairns <contactryank@gmail.com>
Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
Catherine Liu 2020-04-22 21:06:49 -07:00 committed by GitHub
parent 4fc1c5f5cb
commit 1a0988f964
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
142 changed files with 4160 additions and 2392 deletions

View file

@ -7,6 +7,7 @@
import path from 'path'; import path from 'path';
import moment from 'moment'; import moment from 'moment';
import 'moment-timezone'; import 'moment-timezone';
import ReactDOM from "react-dom";
import initStoryshots, { multiSnapshotWithOptions } from '@storybook/addon-storyshots'; import initStoryshots, { multiSnapshotWithOptions } from '@storybook/addon-storyshots';
import styleSheetSerializer from 'jest-styled-components/src/styleSheetSerializer'; import styleSheetSerializer from 'jest-styled-components/src/styleSheetSerializer';
@ -24,6 +25,9 @@ moment.tz.setDefault('UTC');
const testTime = new Date(Date.UTC(2019, 5, 1)); // June 1 2019 const testTime = new Date(Date.UTC(2019, 5, 1)); // June 1 2019
Date.now = jest.fn(() => testTime); Date.now = jest.fn(() => testTime);
// Mock telemetry service
jest.mock('../public/lib/ui_metric', () => ({ trackCanvasUiMetric: () => { } }));
// Mock EUI generated ids to be consistently predictable for snapshots. // Mock EUI generated ids to be consistently predictable for snapshots.
jest.mock(`@elastic/eui/lib/components/form/form_row/make_id`, () => () => `generated-id`); jest.mock(`@elastic/eui/lib/components/form/form_row/make_id`, () => () => `generated-id`);
@ -32,7 +36,7 @@ jest.mock(`@elastic/eui/lib/components/form/form_row/make_id`, () => () => `gene
jest.mock('@elastic/eui/lib/components/code/code', () => { jest.mock('@elastic/eui/lib/components/code/code', () => {
const React = require.requireActual('react'); const React = require.requireActual('react');
return { return {
EuiCode: ({children, className}) => ( EuiCode: ({ children, className }) => (
<span> <span>
<code>{children}</code> <code>{children}</code>
</span> </span>
@ -61,6 +65,12 @@ jest.mock('@elastic/eui/packages/react-datepicker', () => {
}; };
}); });
// Mock React Portal for components that use modals, tooltips, etc
ReactDOM.createPortal = jest.fn((element) => {
return element;
});
jest.mock('@elastic/eui/lib/services/accessibility/html_id_generator', () => { jest.mock('@elastic/eui/lib/services/accessibility/html_id_generator', () => {
return { return {
htmlIdGenerator: () => () => `generated-id`, htmlIdGenerator: () => () => `generated-id`,
@ -71,7 +81,7 @@ jest.mock('plugins/interpreter/registries', () => ({}));
// Disabling this test due to https://github.com/elastic/eui/issues/2242 // Disabling this test due to https://github.com/elastic/eui/issues/2242
jest.mock( jest.mock(
'../public/components/workpad_header/workpad_export/flyout/__examples__/share_website_flyout.stories', '../public/components/workpad_header/share_menu/flyout/__examples__/share_website_flyout.stories',
() => { () => {
return 'Disabled Panel'; return 'Disabled Panel';
} }

View file

@ -177,8 +177,10 @@ module.exports = async ({ config }) => {
}), }),
// Mock out libs used by a few componets to avoid loading in kibana_legacy and platform // Mock out libs used by a few componets to avoid loading in kibana_legacy and platform
new webpack.NormalModuleReplacementPlugin(/lib\/notify/, path.resolve(__dirname, '../tasks/mocks/uiNotify')), new webpack.NormalModuleReplacementPlugin(/(lib)?\/notify/, path.resolve(__dirname, '../tasks/mocks/uiNotify')),
new webpack.NormalModuleReplacementPlugin(/lib\/download_workpad/, path.resolve(__dirname, '../tasks/mocks/downloadWorkpad')), new webpack.NormalModuleReplacementPlugin(/lib\/download_workpad/, path.resolve(__dirname, '../tasks/mocks/downloadWorkpad')),
new webpack.NormalModuleReplacementPlugin(/(lib)?\/custom_element_service/, path.resolve(__dirname, '../tasks/mocks/customElementService')),
new webpack.NormalModuleReplacementPlugin(/(lib)?\/ui_metric/, path.resolve(__dirname, '../tasks/mocks/uiMetric')),
); );
// Tell Webpack about relevant extensions // Tell Webpack about relevant extensions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 149 KiB

View file

@ -5,14 +5,13 @@
*/ */
import { ElementFactory } from '../../../types'; import { ElementFactory } from '../../../types';
import header from './header.png';
export const areaChart: ElementFactory = () => ({ export const areaChart: ElementFactory = () => ({
name: 'areaChart', name: 'areaChart',
displayName: 'Area chart', displayName: 'Area',
help: 'A line chart with a filled body', help: 'A line chart with a filled body',
tags: ['chart'], type: 'chart',
image: header, icon: 'visArea',
expression: `filters expression: `filters
| demodata | demodata
| pointseries x="time" y="mean(price)" | pointseries x="time" y="mean(price)"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

View file

@ -5,16 +5,15 @@
*/ */
import { ElementFactory } from '../../../types'; import { ElementFactory } from '../../../types';
import header from './header.png';
export const bubbleChart: ElementFactory = () => ({ export const bubbleChart: ElementFactory = () => ({
name: 'bubbleChart', name: 'bubbleChart',
displayName: 'Bubble chart', displayName: 'Bubble',
tags: ['chart'], type: 'chart',
help: 'A customizable bubble chart', help: 'A customizable bubble chart',
width: 700, width: 700,
height: 300, height: 300,
image: header, icon: 'heatmap',
expression: `filters expression: `filters
| demodata | demodata
| pointseries x="project" y="sum(price)" color="state" size="size(username)" | pointseries x="project" y="sum(price)" color="state" size="size(username)"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View file

@ -5,14 +5,12 @@
*/ */
import { ElementFactory } from '../../../types'; import { ElementFactory } from '../../../types';
import header from './header.png';
export const debug: ElementFactory = () => ({ export const debug: ElementFactory = () => ({
name: 'debug', name: 'debug',
displayName: 'Debug', displayName: 'Debug data',
tags: ['text'],
help: 'Just dumps the configuration of the element', help: 'Just dumps the configuration of the element',
image: header, icon: 'bug',
expression: `demodata expression: `demodata
| render as=debug`, | render as=debug`,
}); });

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

View file

@ -1,21 +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;
* you may not use this file except in compliance with the Elastic License.
*/
import { ElementFactory } from '../../../types';
import header from './header.png';
export const donut: ElementFactory = () => ({
name: 'donut',
displayName: 'Donut chart',
tags: ['chart', 'proportion'],
help: 'A customizable donut chart',
image: header,
expression: `filters
| demodata
| pointseries color="project" size="max(price)"
| pie hole=50 labels=false legend="ne"
| render`,
});

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View file

@ -5,14 +5,13 @@
*/ */
import { ElementFactory } from '../../../types'; import { ElementFactory } from '../../../types';
import header from './header.png';
export const dropdownFilter: ElementFactory = () => ({ export const dropdownFilter: ElementFactory = () => ({
name: 'dropdown_filter', name: 'dropdownFilter',
displayName: 'Dropdown filter', displayName: 'Dropdown select',
tags: ['filter'], type: 'filter',
help: 'A dropdown from which you can select values for an "exactly" filter', help: 'A dropdown from which you can select values for an "exactly" filter',
image: header, icon: 'filter',
height: 50, height: 50,
expression: `demodata expression: `demodata
| dropdownControl valueColumn=project filterColumn=project | render`, | dropdownControl valueColumn=project filterColumn=project | render`,

View file

@ -0,0 +1,16 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { ElementFactory } from '../../../types';
export const filterDebug: ElementFactory = () => ({
name: 'filterDebug',
displayName: 'Debug filter',
help: 'Shows the underlying global filters in a workpad',
icon: 'bug',
expression: `filters
| render as=debug`,
});

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

View file

@ -5,14 +5,13 @@
*/ */
import { ElementFactory } from '../../../types'; import { ElementFactory } from '../../../types';
import header from './header.png';
export const horizontalBarChart: ElementFactory = () => ({ export const horizontalBarChart: ElementFactory = () => ({
name: 'horizontalBarChart', name: 'horizontalBarChart',
displayName: 'Horizontal bar chart', displayName: 'Bar horizontal',
tags: ['chart'], type: 'chart',
help: 'A customizable horizontal bar chart', help: 'A customizable horizontal bar chart',
image: header, icon: 'visBarHorizontal',
expression: `filters expression: `filters
| demodata | demodata
| pointseries x="size(cost)" y="project" color="project" | pointseries x="size(cost)" y="project" color="project"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View file

@ -6,16 +6,14 @@
import { openSans } from '../../../common/lib/fonts'; import { openSans } from '../../../common/lib/fonts';
import { ElementFactory } from '../../../types'; import { ElementFactory } from '../../../types';
import header from './header.png';
export const horizontalProgressBar: ElementFactory = () => ({ export const horizontalProgressBar: ElementFactory = () => ({
name: 'horizontalProgressBar', name: 'horizontalProgressBar',
displayName: 'Horizontal progress bar', displayName: 'Horizontal bar',
tags: ['chart', 'proportion'], type: 'progress',
help: 'Displays progress as a portion of a horizontal bar', help: 'Displays progress as a portion of a horizontal bar',
width: 400, width: 400,
height: 30, height: 30,
image: header,
expression: `filters expression: `filters
| demodata | demodata
| math "mean(percent_uptime)" | math "mean(percent_uptime)"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

View file

@ -6,16 +6,14 @@
import { openSans } from '../../../common/lib/fonts'; import { openSans } from '../../../common/lib/fonts';
import { ElementFactory } from '../../../types'; import { ElementFactory } from '../../../types';
import header from './header.png';
export const horizontalProgressPill: ElementFactory = () => ({ export const horizontalProgressPill: ElementFactory = () => ({
name: 'horizontalProgressPill', name: 'horizontalProgressPill',
displayName: 'Horizontal progress pill', displayName: 'Horizontal pill',
tags: ['chart', 'proportion'], type: 'progress',
help: 'Displays progress as a portion of a horizontal pill', help: 'Displays progress as a portion of a horizontal pill',
width: 400, width: 400,
height: 30, height: 30,
image: header,
expression: `filters expression: `filters
| demodata | demodata
| math "mean(percent_uptime)" | math "mean(percent_uptime)"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

View file

@ -5,14 +5,13 @@
*/ */
import { ElementFactory } from '../../../types'; import { ElementFactory } from '../../../types';
import header from './header.png';
export const image: ElementFactory = () => ({ export const image: ElementFactory = () => ({
name: 'image', name: 'image',
displayName: 'Image', displayName: 'Image',
tags: ['graphic'], type: 'image',
help: 'A static image', help: 'A static image',
image: header, icon: 'image',
expression: `image dataurl=null mode="contain" expression: `image dataurl=null mode="contain"
| render`, | render`,
}); });

View file

@ -8,8 +8,8 @@ import { applyElementStrings } from '../../i18n/elements';
import { areaChart } from './area_chart'; import { areaChart } from './area_chart';
import { bubbleChart } from './bubble_chart'; import { bubbleChart } from './bubble_chart';
import { debug } from './debug'; import { debug } from './debug';
import { donut } from './donut';
import { dropdownFilter } from './dropdown_filter'; import { dropdownFilter } from './dropdown_filter';
import { filterDebug } from './filter_debug';
import { horizontalBarChart } from './horizontal_bar_chart'; import { horizontalBarChart } from './horizontal_bar_chart';
import { horizontalProgressBar } from './horizontal_progress_bar'; import { horizontalProgressBar } from './horizontal_progress_bar';
import { horizontalProgressPill } from './horizontal_progress_pill'; import { horizontalProgressPill } from './horizontal_progress_pill';
@ -26,7 +26,6 @@ import { repeatImage } from './repeat_image';
import { revealImage } from './reveal_image'; import { revealImage } from './reveal_image';
import { shape } from './shape'; import { shape } from './shape';
import { table } from './table'; import { table } from './table';
import { tiltedPie } from './tilted_pie';
import { timeFilter } from './time_filter'; import { timeFilter } from './time_filter';
import { verticalBarChart } from './vert_bar_chart'; import { verticalBarChart } from './vert_bar_chart';
import { verticalProgressBar } from './vertical_progress_bar'; import { verticalProgressBar } from './vertical_progress_bar';
@ -39,8 +38,8 @@ const elementSpecs = [
areaChart, areaChart,
bubbleChart, bubbleChart,
debug, debug,
donut,
dropdownFilter, dropdownFilter,
filterDebug,
image, image,
horizontalBarChart, horizontalBarChart,
horizontalProgressBar, horizontalProgressBar,
@ -56,7 +55,6 @@ const elementSpecs = [
revealImage, revealImage,
shape, shape,
table, table,
tiltedPie,
timeFilter, timeFilter,
verticalBarChart, verticalBarChart,
verticalProgressBar, verticalProgressBar,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

View file

@ -5,14 +5,13 @@
*/ */
import { ElementFactory } from '../../../types'; import { ElementFactory } from '../../../types';
import header from './header.png';
export const lineChart: ElementFactory = () => ({ export const lineChart: ElementFactory = () => ({
name: 'lineChart', name: 'lineChart',
displayName: 'Line chart', displayName: 'Line',
tags: ['chart'], type: 'chart',
help: 'A customizable line chart', help: 'A customizable line chart',
image: header, icon: 'visLine',
expression: `filters expression: `filters
| demodata | demodata
| pointseries x="time" y="mean(price)" | pointseries x="time" y="mean(price)"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

View file

@ -4,15 +4,13 @@
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
import header from './header.png';
import { ElementFactory } from '../../../types'; import { ElementFactory } from '../../../types';
export const markdown: ElementFactory = () => ({ export const markdown: ElementFactory = () => ({
name: 'markdown', name: 'markdown',
displayName: 'Markdown', displayName: 'Text',
tags: ['text'], type: 'text',
help: 'Markup from Markdown', help: 'Add text using Markdown',
image: header, icon: 'visText',
expression: `filters expression: `filters
| demodata | demodata
| markdown "### Welcome to the Markdown element | markdown "### Welcome to the Markdown element

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View file

@ -5,8 +5,6 @@
*/ */
import { openSans } from '../../../common/lib/fonts'; import { openSans } from '../../../common/lib/fonts';
import header from './header.png';
import { ElementFactory } from '../../../types'; import { ElementFactory } from '../../../types';
import { SetupInitializer } from '../../plugin'; import { SetupInitializer } from '../../plugin';
@ -14,11 +12,11 @@ export const metricElementInitializer: SetupInitializer<ElementFactory> = (core,
return () => ({ return () => ({
name: 'metric', name: 'metric',
displayName: 'Metric', displayName: 'Metric',
tags: ['text'], type: 'chart',
help: 'A number with a label', help: 'A number with a label',
width: 200, width: 200,
height: 100, height: 100,
image: header, icon: 'visMetric',
expression: `filters expression: `filters
| demodata | demodata
| math "unique(country)" | math "unique(country)"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View file

@ -4,17 +4,15 @@
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
import header from './header.png';
import { ElementFactory } from '../../../types'; import { ElementFactory } from '../../../types';
export const pie: ElementFactory = () => ({ export const pie: ElementFactory = () => ({
name: 'pie', name: 'pie',
displayName: 'Pie chart', displayName: 'Pie',
tags: ['chart', 'proportion'], type: 'chart',
width: 300, width: 300,
height: 300, height: 300,
help: 'A simple pie chart', help: 'A simple pie chart',
image: header, icon: 'visPie',
expression: `filters expression: `filters
| demodata | demodata
| pointseries color="state" size="max(price)" | pointseries color="state" size="max(price)"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

View file

@ -5,14 +5,12 @@
*/ */
import { ElementFactory } from '../../../types'; import { ElementFactory } from '../../../types';
import header from './header.png';
export const plot: ElementFactory = () => ({ export const plot: ElementFactory = () => ({
name: 'plot', name: 'plot',
displayName: 'Coordinate plot', displayName: 'Coordinate plot',
tags: ['chart'], type: 'chart',
help: 'Mixed line, bar or dot charts', help: 'Mixed line, bar or dot charts',
image: header,
expression: `filters expression: `filters
| demodata | demodata
| pointseries x="time" y="sum(price)" color="state" | pointseries x="time" y="sum(price)" color="state"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

View file

@ -6,16 +6,15 @@
import { openSans } from '../../../common/lib/fonts'; import { openSans } from '../../../common/lib/fonts';
import { ElementFactory } from '../../../types'; import { ElementFactory } from '../../../types';
import header from './header.png';
export const progressGauge: ElementFactory = () => ({ export const progressGauge: ElementFactory = () => ({
name: 'progressGauge', name: 'progressGauge',
displayName: 'Progress gauge', displayName: 'Gauge',
tags: ['chart', 'proportion'], type: 'progress',
help: 'Displays progress as a portion of a gauge', help: 'Displays progress as a portion of a gauge',
width: 200, width: 200,
height: 200, height: 200,
image: header, icon: 'visGoal',
expression: `filters expression: `filters
| demodata | demodata
| math "mean(percent_uptime)" | math "mean(percent_uptime)"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

View file

@ -6,16 +6,14 @@
import { openSans } from '../../../common/lib/fonts'; import { openSans } from '../../../common/lib/fonts';
import { ElementFactory } from '../../../types'; import { ElementFactory } from '../../../types';
import header from './header.png';
export const progressSemicircle: ElementFactory = () => ({ export const progressSemicircle: ElementFactory = () => ({
name: 'progressSemicircle', name: 'progressSemicircle',
displayName: 'Progress semicircle', displayName: 'Semicircle',
tags: ['chart', 'proportion'], type: 'progress',
help: 'Displays progress as a portion of a semicircle', help: 'Displays progress as a portion of a semicircle',
width: 200, width: 200,
height: 100, height: 100,
image: header,
expression: `filters expression: `filters
| demodata | demodata
| math "mean(percent_uptime)" | math "mean(percent_uptime)"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

View file

@ -6,16 +6,14 @@
import { openSans } from '../../../common/lib/fonts'; import { openSans } from '../../../common/lib/fonts';
import { ElementFactory } from '../../../types'; import { ElementFactory } from '../../../types';
import header from './header.png';
export const progressWheel: ElementFactory = () => ({ export const progressWheel: ElementFactory = () => ({
name: 'progressWheel', name: 'progressWheel',
displayName: 'Progress wheel', displayName: 'Wheel',
tags: ['chart', 'proportion'], type: 'progress',
help: 'Displays progress as a portion of a wheel', help: 'Displays progress as a portion of a wheel',
width: 200, width: 200,
height: 200, height: 200,
image: header,
expression: `filters expression: `filters
| demodata | demodata
| math "mean(percent_uptime)" | math "mean(percent_uptime)"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

View file

@ -5,14 +5,12 @@
*/ */
import { ElementFactory } from '../../../types'; import { ElementFactory } from '../../../types';
import header from './header.png';
export const repeatImage: ElementFactory = () => ({ export const repeatImage: ElementFactory = () => ({
name: 'repeatImage', name: 'repeatImage',
displayName: 'Image repeat', displayName: 'Image repeat',
tags: ['graphic', 'proportion'], type: 'image',
help: 'Repeats an image N times', help: 'Repeats an image N times',
image: header,
expression: `filters expression: `filters
| demodata | demodata
| math "mean(cost)" | math "mean(cost)"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

View file

@ -5,14 +5,12 @@
*/ */
import { ElementFactory } from '../../../types'; import { ElementFactory } from '../../../types';
import header from './header.png';
export const revealImage: ElementFactory = () => ({ export const revealImage: ElementFactory = () => ({
name: 'revealImage', name: 'revealImage',
displayName: 'Image reveal', displayName: 'Image reveal',
tags: ['graphic', 'proportion'], type: 'image',
help: 'Reveals a percentage of an image', help: 'Reveals a percentage of an image',
image: header,
expression: `filters expression: `filters
| demodata | demodata
| math "mean(percent_uptime)" | math "mean(percent_uptime)"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

View file

@ -5,16 +5,15 @@
*/ */
import { ElementFactory } from '../../../types'; import { ElementFactory } from '../../../types';
import header from './header.png';
export const shape: ElementFactory = () => ({ export const shape: ElementFactory = () => ({
name: 'shape', name: 'shape',
displayName: 'Shape', displayName: 'Shape',
tags: ['graphic'], type: 'shape',
help: 'A customizable shape', help: 'A customizable shape',
width: 200, width: 200,
height: 200, height: 200,
image: header, icon: 'node',
expression: expression:
'shape "square" fill="#4cbce4" border="rgba(255,255,255,0)" borderWidth=0 maintainAspect=false | render', 'shape "square" fill="#4cbce4" border="rgba(255,255,255,0)" borderWidth=0 maintainAspect=false | render',
}); });

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View file

@ -5,14 +5,13 @@
*/ */
import { ElementFactory } from '../../../types'; import { ElementFactory } from '../../../types';
import header from './header.png';
export const table: ElementFactory = () => ({ export const table: ElementFactory = () => ({
name: 'table', name: 'table',
displayName: 'Data table', displayName: 'Data table',
tags: ['text'], type: 'chart',
help: 'A scrollable grid for displaying data in a tabular format', help: 'A scrollable grid for displaying data in a tabular format',
image: header, icon: 'visTable',
expression: `filters expression: `filters
| demodata | demodata
| table | table

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

View file

@ -1,23 +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;
* you may not use this file except in compliance with the Elastic License.
*/
import { ElementFactory } from '../../../types';
import header from './header.png';
export const tiltedPie: ElementFactory = () => ({
name: 'tiltedPie',
displayName: 'Tilted pie chart',
tags: ['chart', 'proportion'],
width: 500,
height: 250,
help: 'A customizable tilted pie chart',
image: header,
expression: `filters
| demodata
| pointseries color="project" size="max(price)"
| pie tilt=0.5
| render`,
});

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

View file

@ -5,14 +5,13 @@
*/ */
import { ElementFactory } from '../../../types'; import { ElementFactory } from '../../../types';
import header from './header.png';
export const timeFilter: ElementFactory = () => ({ export const timeFilter: ElementFactory = () => ({
name: 'time_filter', name: 'timeFilter',
displayName: 'Time filter', displayName: 'Time filter',
tags: ['filter'], type: 'filter',
help: 'Set a time window', help: 'Set a time window',
image: header, icon: 'calendar',
height: 50, height: 50,
expression: `timefilterControl compact=true column=@timestamp expression: `timefilterControl compact=true column=@timestamp
| render`, | render`,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

View file

@ -5,14 +5,13 @@
*/ */
import { ElementFactory } from '../../../types'; import { ElementFactory } from '../../../types';
import header from './header.png';
export const verticalBarChart: ElementFactory = () => ({ export const verticalBarChart: ElementFactory = () => ({
name: 'verticalBarChart', name: 'verticalBarChart',
displayName: 'Vertical bar chart', displayName: 'Vertical bar chart',
tags: ['chart'], type: 'chart',
help: 'A customizable vertical bar chart', help: 'A customizable vertical bar chart',
image: header, icon: 'visBarVertical',
expression: `filters expression: `filters
| demodata | demodata
| pointseries x="project" y="size(cost)" color="project" | pointseries x="project" y="size(cost)" color="project"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View file

@ -6,16 +6,14 @@
import { openSans } from '../../../common/lib/fonts'; import { openSans } from '../../../common/lib/fonts';
import { ElementFactory } from '../../../types'; import { ElementFactory } from '../../../types';
import header from './header.png';
export const verticalProgressBar: ElementFactory = () => ({ export const verticalProgressBar: ElementFactory = () => ({
name: 'verticalProgressBar', name: 'verticalProgressBar',
displayName: 'Vertical progress bar', displayName: 'Vertical progress bar',
tags: ['chart', 'proportion'], type: 'progress',
help: 'Displays progress as a portion of a vertical bar', help: 'Displays progress as a portion of a vertical bar',
width: 80, width: 80,
height: 400, height: 400,
image: header,
expression: `filters expression: `filters
| demodata | demodata
| math "mean(percent_uptime)" | math "mean(percent_uptime)"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

View file

@ -6,16 +6,14 @@
import { openSans } from '../../../common/lib/fonts'; import { openSans } from '../../../common/lib/fonts';
import { ElementFactory } from '../../../types'; import { ElementFactory } from '../../../types';
import header from './header.png';
export const verticalProgressPill: ElementFactory = () => ({ export const verticalProgressPill: ElementFactory = () => ({
name: 'verticalProgressPill', name: 'verticalProgressPill',
displayName: 'Vertical progress pill', displayName: 'Vertical progress pill',
tags: ['chart', 'proportion'], type: 'progress',
help: 'Displays progress as a portion of a vertical pill', help: 'Displays progress as a portion of a vertical pill',
width: 80, width: 80,
height: 400, height: 400,
image: header,
expression: `filters expression: `filters
| demodata | demodata
| math "mean(percent_uptime)" | math "mean(percent_uptime)"

View file

@ -1,15 +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;
* you may not use this file except in compliance with the Elastic License.
*/
import { euiPaletteColorBlind } from '@elastic/eui';
import { TagFactory } from '../../../public/lib/tag';
import { TagStrings as strings } from '../../../i18n';
const euiVisPalette = euiPaletteColorBlind();
export const chart: TagFactory = () => ({
name: strings.chart(),
color: euiVisPalette[4],
});

View file

@ -1,16 +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;
* you may not use this file except in compliance with the Elastic License.
*/
import { euiPaletteColorBlind } from '@elastic/eui';
import { TagFactory } from '../../../public/lib/tag';
import { TagStrings as strings } from '../../../i18n';
const euiVisPalette = euiPaletteColorBlind();
export const filter: TagFactory = () => ({
name: strings.filter(),
color: euiVisPalette[1],
});

View file

@ -1,15 +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;
* you may not use this file except in compliance with the Elastic License.
*/
import { euiPaletteColorBlind } from '@elastic/eui';
import { TagFactory } from '../../../public/lib/tag';
import { TagStrings as strings } from '../../../i18n';
const euiVisPalette = euiPaletteColorBlind();
export const graphic: TagFactory = () => ({
name: strings.graphic(),
color: euiVisPalette[5],
});

View file

@ -4,13 +4,8 @@
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
import { chart } from './chart';
import { filter } from './filter';
import { graphic } from './graphic';
import { presentation } from './presentation'; import { presentation } from './presentation';
import { proportion } from './proportion';
import { report } from './report'; import { report } from './report';
import { text } from './text';
// Registry expects a function that returns a spec object // Registry expects a function that returns a spec object
export const tagSpecs = [chart, filter, graphic, presentation, proportion, report, text]; export const tagSpecs = [presentation, report];

View file

@ -1,15 +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;
* you may not use this file except in compliance with the Elastic License.
*/
import { euiPaletteColorBlind } from '@elastic/eui';
import { TagFactory } from '../../../public/lib/tag';
import { TagStrings as strings } from '../../../i18n';
const euiVisPalette = euiPaletteColorBlind();
export const proportion: TagFactory = () => ({
name: strings.proportion(),
color: euiVisPalette[3],
});

View file

@ -1,13 +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;
* you may not use this file except in compliance with the Elastic License.
*/
import { TagFactory } from '../../../public/lib/tag';
import { TagStrings as strings } from '../../../i18n';
export const text: TagFactory = () => ({
name: strings.text(),
color: '#D3DAE6',
});

View file

@ -40,3 +40,4 @@ export const API_ROUTE_SHAREABLE_ZIP = '/public/canvas/zip';
export const API_ROUTE_SHAREABLE_RUNTIME = '/public/canvas/runtime'; export const API_ROUTE_SHAREABLE_RUNTIME = '/public/canvas/runtime';
export const API_ROUTE_SHAREABLE_RUNTIME_DOWNLOAD = `/public/canvas/${SHAREABLE_RUNTIME_NAME}.js`; export const API_ROUTE_SHAREABLE_RUNTIME_DOWNLOAD = `/public/canvas/${SHAREABLE_RUNTIME_NAME}.js`;
export const CANVAS_EMBEDDABLE_CLASSNAME = `canvasEmbeddable`; export const CANVAS_EMBEDDABLE_CLASSNAME = `canvasEmbeddable`;
export const CONTEXT_MENU_TOP_BORDER_CLASSNAME = 'canvasContextMenu--topBorder';

View file

@ -15,7 +15,7 @@ export const ComponentStrings = {
}), }),
getTitleText: () => getTitleText: () =>
i18n.translate('xpack.canvas.embedObject.titleText', { i18n.translate('xpack.canvas.embedObject.titleText', {
defaultMessage: 'Embed Object', defaultMessage: 'Add from Visualize library',
}), }),
}, },
AdvancedFilter: { AdvancedFilter: {
@ -305,21 +305,21 @@ export const ComponentStrings = {
}), }),
}, },
ElementControls: { ElementControls: {
getEditTooltip: () => getDeleteAriaLabel: () =>
i18n.translate('xpack.canvas.elementControls.editToolTip', { i18n.translate('xpack.canvas.elementControls.deleteAriaLabel', {
defaultMessage: 'Edit', defaultMessage: 'Delete element',
}),
getEditAriaLabel: () =>
i18n.translate('xpack.canvas.elementControls.editAriaLabel', {
defaultMessage: 'Edit element',
}), }),
getDeleteTooltip: () => getDeleteTooltip: () =>
i18n.translate('xpack.canvas.elementControls.deleteToolTip', { i18n.translate('xpack.canvas.elementControls.deleteToolTip', {
defaultMessage: 'Delete', defaultMessage: 'Delete',
}), }),
getDeleteAriaLabel: () => getEditAriaLabel: () =>
i18n.translate('xpack.canvas.elementControls.deleteAriaLabel', { i18n.translate('xpack.canvas.elementControls.editAriaLabel', {
defaultMessage: 'Delete element', defaultMessage: 'Edit element',
}),
getEditTooltip: () =>
i18n.translate('xpack.canvas.elementControls.editToolTip', {
defaultMessage: 'Edit',
}), }),
}, },
ElementSettings: { ElementSettings: {
@ -336,53 +336,6 @@ export const ComponentStrings = {
description: 'This tab contains the settings for how data is displayed in a Canvas element', description: 'This tab contains the settings for how data is displayed in a Canvas element',
}), }),
}, },
ElementTypes: {
getEditElementTitle: () =>
i18n.translate('xpack.canvas.elementTypes.editElementTitle', {
defaultMessage: 'Edit element',
}),
getDeleteElementTitle: (elementName: string) =>
i18n.translate('xpack.canvas.elementTypes.deleteElementTitle', {
defaultMessage: `Delete element '{elementName}'?`,
values: {
elementName,
},
}),
getDeleteElementDescription: () =>
i18n.translate('xpack.canvas.elementTypes.deleteElementDescription', {
defaultMessage: 'Are you sure you want to delete this element?',
}),
getCancelButtonLabel: () =>
i18n.translate('xpack.canvas.elementTypes.cancelButtonLabel', {
defaultMessage: 'Cancel',
}),
getDeleteButtonLabel: () =>
i18n.translate('xpack.canvas.elementTypes.deleteButtonLabel', {
defaultMessage: 'Delete',
}),
getAddNewElementTitle: () =>
i18n.translate('xpack.canvas.elementTypes.addNewElementTitle', {
defaultMessage: 'Add new elements',
}),
getAddNewElementDescription: () =>
i18n.translate('xpack.canvas.elementTypes.addNewElementDescription', {
defaultMessage: 'Group and save workpad elements to create new elements',
}),
getFindElementPlaceholder: () =>
i18n.translate('xpack.canvas.elementTypes.findElementPlaceholder', {
defaultMessage: 'Find element',
}),
getElementsTitle: () =>
i18n.translate('xpack.canvas.elementTypes.elementsTitle', {
defaultMessage: 'Elements',
description: 'Title for the "Elements" tab when adding a new element',
}),
getMyElementsTitle: () =>
i18n.translate('xpack.canvas.elementTypes.myElementsTitle', {
defaultMessage: 'My elements',
description: 'Title for the "My elements" tab when adding a new element',
}),
},
Error: { Error: {
getDescription: () => getDescription: () =>
i18n.translate('xpack.canvas.errorComponent.description', { i18n.translate('xpack.canvas.errorComponent.description', {
@ -633,6 +586,61 @@ export const ComponentStrings = {
defaultMessage: 'Delete', defaultMessage: 'Delete',
}), }),
}, },
SavedElementsModal: {
getAddNewElementDescription: () =>
i18n.translate('xpack.canvas.savedElementsModal.addNewElementDescription', {
defaultMessage: 'Group and save workpad elements to create new elements',
}),
getAddNewElementTitle: () =>
i18n.translate('xpack.canvas.savedElementsModal.addNewElementTitle', {
defaultMessage: 'Add new elements',
}),
getCancelButtonLabel: () =>
i18n.translate('xpack.canvas.savedElementsModal.cancelButtonLabel', {
defaultMessage: 'Cancel',
}),
getDeleteButtonLabel: () =>
i18n.translate('xpack.canvas.savedElementsModal.deleteButtonLabel', {
defaultMessage: 'Delete',
}),
getDeleteElementDescription: () =>
i18n.translate('xpack.canvas.savedElementsModal.deleteElementDescription', {
defaultMessage: 'Are you sure you want to delete this element?',
}),
getDeleteElementTitle: (elementName: string) =>
i18n.translate('xpack.canvas.savedElementsModal.deleteElementTitle', {
defaultMessage: `Delete element '{elementName}'?`,
values: {
elementName,
},
}),
getEditElementTitle: () =>
i18n.translate('xpack.canvas.savedElementsModal.editElementTitle', {
defaultMessage: 'Edit element',
}),
getElementsTitle: () =>
i18n.translate('xpack.canvas.savedElementsModal.elementsTitle', {
defaultMessage: 'Elements',
description: 'Title for the "Elements" tab when adding a new element',
}),
getFindElementPlaceholder: () =>
i18n.translate('xpack.canvas.savedElementsModal.findElementPlaceholder', {
defaultMessage: 'Find element',
}),
getModalTitle: () =>
i18n.translate('xpack.canvas.savedElementsModal.modalTitle', {
defaultMessage: 'My elements',
}),
getMyElementsTitle: () =>
i18n.translate('xpack.canvas.savedElementsModal.myElementsTitle', {
defaultMessage: 'My elements',
description: 'Title for the "My elements" tab when adding a new element',
}),
getSavedElementsModalCloseButtonLabel: () =>
i18n.translate('xpack.canvas.workpadHeader.addElementModalCloseButtonLabel', {
defaultMessage: 'Close',
}),
},
ShareWebsiteFlyout: { ShareWebsiteFlyout: {
getRuntimeStepTitle: () => getRuntimeStepTitle: () =>
i18n.translate('xpack.canvas.shareWebsiteFlyout.snippetsStep.downloadRuntimeTitle', { i18n.translate('xpack.canvas.shareWebsiteFlyout.snippetsStep.downloadRuntimeTitle', {
@ -652,7 +660,7 @@ export const ComponentStrings = {
defaultMessage: 'Share on a website', defaultMessage: 'Share on a website',
}), }),
getUnsupportedRendererWarning: () => getUnsupportedRendererWarning: () =>
i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.unsupportedRendererWarning', { i18n.translate('xpack.canvas.workpadHeaderShareMenu.unsupportedRendererWarning', {
defaultMessage: defaultMessage:
'This workpad contains render functions that are not supported by the {CANVAS} Shareable Workpad Runtime. These elements will not be rendered:', 'This workpad contains render functions that are not supported by the {CANVAS} Shareable Workpad Runtime. These elements will not be rendered:',
values: { values: {
@ -900,6 +908,10 @@ export const ComponentStrings = {
i18n.translate('xpack.canvas.textStylePicker.alignRightOption', { i18n.translate('xpack.canvas.textStylePicker.alignRightOption', {
defaultMessage: 'Align right', defaultMessage: 'Align right',
}), }),
getFontColorLabel: () =>
i18n.translate('xpack.canvas.textStylePicker.fontColorLabel', {
defaultMessage: 'Font Color',
}),
getStyleBoldOption: () => getStyleBoldOption: () =>
i18n.translate('xpack.canvas.textStylePicker.styleBoldOption', { i18n.translate('xpack.canvas.textStylePicker.styleBoldOption', {
defaultMessage: 'Bold', defaultMessage: 'Bold',
@ -912,10 +924,6 @@ export const ComponentStrings = {
i18n.translate('xpack.canvas.textStylePicker.styleUnderlineOption', { i18n.translate('xpack.canvas.textStylePicker.styleUnderlineOption', {
defaultMessage: 'Underline', defaultMessage: 'Underline',
}), }),
getFontColorLabel: () =>
i18n.translate('xpack.canvas.textStylePicker.fontColorLabel', {
defaultMessage: 'Font Color',
}),
}, },
TimePicker: { TimePicker: {
getApplyButtonLabel: () => getApplyButtonLabel: () =>
@ -962,6 +970,10 @@ export const ComponentStrings = {
description: description:
'"stylesheet" refers to the collection of CSS style rules entered by the user.', '"stylesheet" refers to the collection of CSS style rules entered by the user.',
}), }),
getBackgroundColorLabel: () =>
i18n.translate('xpack.canvas.workpadConfig.backgroundColorLabel', {
defaultMessage: 'Background color',
}),
getFlipDimensionAriaLabel: () => getFlipDimensionAriaLabel: () =>
i18n.translate('xpack.canvas.workpadConfig.swapDimensionsAriaLabel', { i18n.translate('xpack.canvas.workpadConfig.swapDimensionsAriaLabel', {
defaultMessage: `Swap the page's width and height`, defaultMessage: `Swap the page's width and height`,
@ -1013,10 +1025,6 @@ export const ComponentStrings = {
defaultMessage: 'US Letter', defaultMessage: 'US Letter',
description: 'This is referring to the dimensions of U.S. standard letter paper.', description: 'This is referring to the dimensions of U.S. standard letter paper.',
}), }),
getBackgroundColorLabel: () =>
i18n.translate('xpack.canvas.workpadConfig.backgroundColorLabel', {
defaultMessage: 'Background color',
}),
}, },
WorkpadCreate: { WorkpadCreate: {
getWorkpadCreateButtonLabel: () => getWorkpadCreateButtonLabel: () =>
@ -1029,14 +1037,6 @@ export const ComponentStrings = {
i18n.translate('xpack.canvas.workpadHeader.addElementButtonLabel', { i18n.translate('xpack.canvas.workpadHeader.addElementButtonLabel', {
defaultMessage: 'Add element', defaultMessage: 'Add element',
}), }),
getAddElementModalCloseButtonLabel: () =>
i18n.translate('xpack.canvas.workpadHeader.addElementModalCloseButtonLabel', {
defaultMessage: 'Close',
}),
getEmbedObjectButtonLabel: () =>
i18n.translate('xpack.canvas.workpadHeader.embedObjectButtonLabel', {
defaultMessage: 'Embed object',
}),
getFullScreenButtonAriaLabel: () => getFullScreenButtonAriaLabel: () =>
i18n.translate('xpack.canvas.workpadHeader.fullscreenButtonAriaLabel', { i18n.translate('xpack.canvas.workpadHeader.fullscreenButtonAriaLabel', {
defaultMessage: 'View fullscreen', defaultMessage: 'View fullscreen',
@ -1080,9 +1080,9 @@ export const ComponentStrings = {
}), }),
}, },
WorkpadHeaderControlSettings: { WorkpadHeaderControlSettings: {
getTooltip: () => getButtonLabel: () =>
i18n.translate('xpack.canvas.workpadHeaderControlSettings.settingsTooltip', { i18n.translate('xpack.canvas.workpadHeaderControlSettings.buttonLabel', {
defaultMessage: 'Control settings', defaultMessage: 'Options',
}), }),
}, },
WorkpadHeaderCustomInterval: { WorkpadHeaderCustomInterval: {
@ -1105,6 +1105,56 @@ export const ComponentStrings = {
defaultMessage: 'Set a custom interval', defaultMessage: 'Set a custom interval',
}), }),
}, },
WorkpadHeaderElementMenu: {
getAssetsMenuItemLabel: () =>
i18n.translate('xpack.canvas.workpadHeaderElementMenu.manageAssetsMenuItemLabel', {
defaultMessage: 'Manage assets',
}),
getChartMenuItemLabel: () =>
i18n.translate('xpack.canvas.workpadHeaderElementMenu.chartMenuItemLabel', {
defaultMessage: 'Chart',
}),
getElementMenuButtonLabel: () =>
i18n.translate('xpack.canvas.workpadHeaderElementMenu.elementMenuButtonLabel', {
defaultMessage: 'Add element',
}),
getElementMenuLabel: () =>
i18n.translate('xpack.canvas.workpadHeaderElementMenu.elementMenuLabel', {
defaultMessage: 'Add an element',
}),
getEmbedObjectMenuItemLabel: () =>
i18n.translate('xpack.canvas.workpadHeaderElementMenu.embedObjectMenuItemLabel', {
defaultMessage: 'Add from Visualize library',
}),
getFilterMenuItemLabel: () =>
i18n.translate('xpack.canvas.workpadHeaderElementMenu.filterMenuItemLabel', {
defaultMessage: 'Filter',
}),
getImageMenuItemLabel: () =>
i18n.translate('xpack.canvas.workpadHeaderElementMenu.imageMenuItemLabel', {
defaultMessage: 'Image',
}),
getMyElementsMenuItemLabel: () =>
i18n.translate('xpack.canvas.workpadHeaderElementMenu.myElementsMenuItemLabel', {
defaultMessage: 'My elements',
}),
getOtherMenuItemLabel: () =>
i18n.translate('xpack.canvas.workpadHeaderElementMenu.otherMenuItemLabel', {
defaultMessage: 'Other',
}),
getProgressMenuItemLabel: () =>
i18n.translate('xpack.canvas.workpadHeaderElementMenu.progressMenuItemLabel', {
defaultMessage: 'Progress',
}),
getShapeMenuItemLabel: () =>
i18n.translate('xpack.canvas.workpadHeaderElementMenu.shapeMenuItemLabel', {
defaultMessage: 'Shape',
}),
getTextMenuItemLabel: () =>
i18n.translate('xpack.canvas.workpadHeaderElementMenu.textMenuItemLabel', {
defaultMessage: 'Text',
}),
},
WorkpadHeaderKioskControls: { WorkpadHeaderKioskControls: {
getCycleFormLabel: () => getCycleFormLabel: () =>
i18n.translate('xpack.canvas.workpadHeaderKioskControl.cycleFormLabel', { i18n.translate('xpack.canvas.workpadHeaderKioskControl.cycleFormLabel', {
@ -1129,9 +1179,9 @@ export const ComponentStrings = {
defaultMessage: 'Refresh data', defaultMessage: 'Refresh data',
}), }),
}, },
WorkpadHeaderWorkpadExport: { WorkpadHeaderShareMenu: {
getCopyPDFMessage: () => getCopyPDFMessage: () =>
i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.copyPDFMessage', { i18n.translate('xpack.canvas.workpadHeaderShareMenu.copyPDFMessage', {
defaultMessage: 'The {PDF} generation {URL} was copied to your clipboard.', defaultMessage: 'The {PDF} generation {URL} was copied to your clipboard.',
values: { values: {
PDF, PDF,
@ -1139,15 +1189,15 @@ export const ComponentStrings = {
}, },
}), }),
getCopyReportingConfigMessage: () => getCopyReportingConfigMessage: () =>
i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.copyReportingConfigMessage', { i18n.translate('xpack.canvas.workpadHeaderShareMenu.copyReportingConfigMessage', {
defaultMessage: 'Copied reporting configuration to clipboard', defaultMessage: 'Copied reporting configuration to clipboard',
}), }),
getCopyShareConfigMessage: () => getCopyShareConfigMessage: () =>
i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.copyShareConfigMessage', { i18n.translate('xpack.canvas.workpadHeaderShareMenu.copyShareConfigMessage', {
defaultMessage: 'Copied share markup to clipboard', defaultMessage: 'Copied share markup to clipboard',
}), }),
getExportPDFErrorTitle: (workpadName: string) => getExportPDFErrorTitle: (workpadName: string) =>
i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.exportPDFErrorMessage', { i18n.translate('xpack.canvas.workpadHeaderShareMenu.exportPDFErrorMessage', {
defaultMessage: "Failed to create {PDF} for '{workpadName}'", defaultMessage: "Failed to create {PDF} for '{workpadName}'",
values: { values: {
PDF, PDF,
@ -1155,14 +1205,14 @@ export const ComponentStrings = {
}, },
}), }),
getExportPDFMessage: () => getExportPDFMessage: () =>
i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.exportPDFMessage', { i18n.translate('xpack.canvas.workpadHeaderShareMenu.exportPDFMessage', {
defaultMessage: 'Exporting {PDF}. You can track the progress in Management.', defaultMessage: 'Exporting {PDF}. You can track the progress in Management.',
values: { values: {
PDF, PDF,
}, },
}), }),
getExportPDFTitle: (workpadName: string) => getExportPDFTitle: (workpadName: string) =>
i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.exportPDFTitle', { i18n.translate('xpack.canvas.workpadHeaderShareMenu.exportPDFTitle', {
defaultMessage: "{PDF} export of workpad '{workpadName}'", defaultMessage: "{PDF} export of workpad '{workpadName}'",
values: { values: {
PDF, PDF,
@ -1170,7 +1220,7 @@ export const ComponentStrings = {
}, },
}), }),
getPDFPanelCopyAriaLabel: () => getPDFPanelCopyAriaLabel: () =>
i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.pdfPanelCopyAriaLabel', { i18n.translate('xpack.canvas.workpadHeaderShareMenu.pdfPanelCopyAriaLabel', {
defaultMessage: defaultMessage:
'Alternatively, you can generate a {PDF} from a script or with Watcher by using this {URL}. Press Enter to copy the {URL} to clipboard.', 'Alternatively, you can generate a {PDF} from a script or with Watcher by using this {URL}. Press Enter to copy the {URL} to clipboard.',
values: { values: {
@ -1179,7 +1229,7 @@ export const ComponentStrings = {
}, },
}), }),
getPDFPanelCopyButtonLabel: () => getPDFPanelCopyButtonLabel: () =>
i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.pdfPanelCopyButtonLabel', { i18n.translate('xpack.canvas.workpadHeaderShareMenu.pdfPanelCopyButtonLabel', {
defaultMessage: 'Copy {POST} {URL}', defaultMessage: 'Copy {POST} {URL}',
values: { values: {
POST, POST,
@ -1187,7 +1237,7 @@ export const ComponentStrings = {
}, },
}), }),
getPDFPanelCopyDescription: () => getPDFPanelCopyDescription: () =>
i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.pdfPanelCopyDescription', { i18n.translate('xpack.canvas.workpadHeaderShareMenu.pdfPanelCopyDescription', {
defaultMessage: defaultMessage:
'Alternatively, copy this {POST} {URL} to call generation from outside {KIBANA} or from Watcher.', 'Alternatively, copy this {POST} {URL} to call generation from outside {KIBANA} or from Watcher.',
values: { values: {
@ -1197,14 +1247,14 @@ export const ComponentStrings = {
}, },
}), }),
getPDFPanelGenerateButtonLabel: () => getPDFPanelGenerateButtonLabel: () =>
i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.pdfPanelGenerateButtonLabel', { i18n.translate('xpack.canvas.workpadHeaderShareMenu.pdfPanelGenerateButtonLabel', {
defaultMessage: 'Generate {PDF}', defaultMessage: 'Generate {PDF}',
values: { values: {
PDF, PDF,
}, },
}), }),
getPDFPanelGenerateDescription: () => getPDFPanelGenerateDescription: () =>
i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.pdfPanelGenerateDescription', { i18n.translate('xpack.canvas.workpadHeaderShareMenu.pdfPanelGenerateDescription', {
defaultMessage: defaultMessage:
'{PDF}s can take a minute or two to generate based on the size of your workpad.', '{PDF}s can take a minute or two to generate based on the size of your workpad.',
values: { values: {
@ -1212,7 +1262,7 @@ export const ComponentStrings = {
}, },
}), }),
getShareableZipErrorTitle: (workpadName: string) => getShareableZipErrorTitle: (workpadName: string) =>
i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.shareWebsiteErrorTitle', { i18n.translate('xpack.canvas.workpadHeaderShareMenu.shareWebsiteErrorTitle', {
defaultMessage: defaultMessage:
"Failed to create {ZIP} file for '{workpadName}'. The workpad may be too large. You'll need to download the files separately.", "Failed to create {ZIP} file for '{workpadName}'. The workpad may be too large. You'll need to download the files separately.",
values: { values: {
@ -1221,69 +1271,101 @@ export const ComponentStrings = {
}, },
}), }),
getShareDownloadJSONTitle: () => getShareDownloadJSONTitle: () =>
i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.shareDownloadJSONTitle', { i18n.translate('xpack.canvas.workpadHeaderShareMenu.shareDownloadJSONTitle', {
defaultMessage: 'Download as {JSON}', defaultMessage: 'Download as {JSON}',
values: { values: {
JSON, JSON,
}, },
}), }),
getShareDownloadPDFTitle: () => getShareDownloadPDFTitle: () =>
i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.shareDownloadPDFTitle', { i18n.translate('xpack.canvas.workpadHeaderShareMenu.shareDownloadPDFTitle', {
defaultMessage: '{PDF} reports', defaultMessage: '{PDF} reports',
values: { values: {
PDF, PDF,
}, },
}), }),
getShareMenuButtonLabel: () =>
i18n.translate('xpack.canvas.workpadHeaderShareMenu.shareMenuButtonLabel', {
defaultMessage: 'Share',
}),
getShareWebsiteTitle: () => getShareWebsiteTitle: () =>
i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.shareWebsiteTitle', { i18n.translate('xpack.canvas.workpadHeaderShareMenu.shareWebsiteTitle', {
defaultMessage: 'Share on a website', defaultMessage: 'Share on a website',
}), }),
getShareWorkpadMessage: () => getShareWorkpadMessage: () =>
i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.shareWorkpadMessage', { i18n.translate('xpack.canvas.workpadHeaderShareMenu.shareWorkpadMessage', {
defaultMessage: 'Share this workpad', defaultMessage: 'Share this workpad',
}), }),
getUnknownExportErrorMessage: (type: string) => getUnknownExportErrorMessage: (type: string) =>
i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.unknownExportErrorMessage', { i18n.translate('xpack.canvas.workpadHeaderShareMenu.unknownExportErrorMessage', {
defaultMessage: 'Unknown export type: {type}', defaultMessage: 'Unknown export type: {type}',
values: { values: {
type, type,
}, },
}), }),
}, },
WorkpadHeaderWorkpadZoom: { WorkpadHeaderViewMenu: {
getFullscreenMenuItemLabel: () =>
i18n.translate('xpack.canvas.workpadHeaderViewMenu.fullscreenMenuLabel', {
defaultMessage: 'Enter fullscreen mode',
}),
getHideEditModeLabel: () =>
i18n.translate('xpack.canvas.workpadHeaderViewMenu.hideEditModeLabel', {
defaultMessage: 'Hide editing controls',
}),
getRefreshMenuItemLabel: () =>
i18n.translate('xpack.canvas.workpadHeaderViewMenu.refreshMenuItemLabel', {
defaultMessage: 'Refresh data',
}),
getShowEditModeLabel: () =>
i18n.translate('xpack.canvas.workpadHeaderViewMenu.showEditModeLabel', {
defaultMessage: 'Show editing controls',
}),
getViewMenuButtonLabel: () =>
i18n.translate('xpack.canvas.workpadHeaderViewMenu.viewMenuButtonLabel', {
defaultMessage: 'View',
}),
getViewMenuLabel: () =>
i18n.translate('xpack.canvas.workpadHeaderViewMenu.viewMenuLabel', {
defaultMessage: 'View options',
}),
getZoomControlsAriaLabel: () => getZoomControlsAriaLabel: () =>
i18n.translate('xpack.canvas.workpadHeaderWorkpadZoom.zoomControlsAriaLabel', { i18n.translate('xpack.canvas.workpadHeaderViewMenu.zoomControlsAriaLabel', {
defaultMessage: 'Zoom controls', defaultMessage: 'Zoom controls',
}), }),
getZoomControlsTooltip: () => getZoomControlsTooltip: () =>
i18n.translate('xpack.canvas.workpadHeaderWorkpadZoom.zoomControlsTooltip', { i18n.translate('xpack.canvas.workpadHeaderViewMenu.zoomControlsTooltip', {
defaultMessage: 'Zoom controls', defaultMessage: 'Zoom controls',
}), }),
getZoomFitToWindowText: () => getZoomFitToWindowText: () =>
i18n.translate('xpack.canvas.workpadHeaderWorkpadZoom.zoomFitToWindowText', { i18n.translate('xpack.canvas.workpadHeaderViewMenu.zoomFitToWindowText', {
defaultMessage: 'Fit to window', defaultMessage: 'Fit to window',
}), }),
getZoomInText: () => getZoomInText: () =>
i18n.translate('xpack.canvas.workpadHeaderWorkpadZoom.zoomInText', { i18n.translate('xpack.canvas.workpadHeaderViewMenu.zoomInText', {
defaultMessage: 'Zoom in', defaultMessage: 'Zoom in',
}), }),
getZoomMenuItemLabel: () =>
i18n.translate('xpack.canvas.workpadHeaderViewMenu.zoomMenuItemLabel', {
defaultMessage: 'Zoom',
}),
getZoomOutText: () => getZoomOutText: () =>
i18n.translate('xpack.canvas.workpadHeaderWorkpadZoom.zoomOutText', { i18n.translate('xpack.canvas.workpadHeaderViewMenu.zoomOutText', {
defaultMessage: 'Zoom out', defaultMessage: 'Zoom out',
}), }),
getZoomPanelTitle: () => getZoomPanelTitle: () =>
i18n.translate('xpack.canvas.workpadHeaderWorkpadZoom.zoomPanelTitle', { i18n.translate('xpack.canvas.workpadHeaderViewMenu.zoomPanelTitle', {
defaultMessage: 'Zoom', defaultMessage: 'Zoom',
}), }),
getZoomPercentage: (scale: number) => getZoomPercentage: (scale: number) =>
i18n.translate('xpack.canvas.workpadHeaderWorkpadZoom.zoomResetText', { i18n.translate('xpack.canvas.workpadHeaderViewMenu.zoomResetText', {
defaultMessage: '{scalePercentage}%', defaultMessage: '{scalePercentage}%',
values: { values: {
scalePercentage: scale * 100, scalePercentage: scale * 100,
}, },
}), }),
getZoomResetText: () => getZoomResetText: () =>
i18n.translate('xpack.canvas.workpadHeaderWorkpadZoom.zoomPrecentageValue', { i18n.translate('xpack.canvas.workpadHeaderViewMenu.zoomPrecentageValue', {
defaultMessage: 'Reset', defaultMessage: 'Reset',
}), }),
}, },

View file

@ -7,8 +7,6 @@
import { ElementFactory } from '../../types'; import { ElementFactory } from '../../types';
import { getElementStrings } from './index'; import { getElementStrings } from './index';
import { TagStrings } from '../../i18n';
/** /**
* This function takes a set of Canvas Element specification factories, runs them, * This function takes a set of Canvas Element specification factories, runs them,
* replaces relevant strings (if available) and returns a new factory. We do this * replaces relevant strings (if available) and returns a new factory. We do this
@ -34,17 +32,6 @@ export const applyElementStrings = (elements: ElementFactory[]) => {
if (displayName) { if (displayName) {
result.displayName = displayName; result.displayName = displayName;
} }
// Set translated tags
if (result.tags) {
result.tags = result.tags.map(tag => {
if (tag in TagStrings) {
return TagStrings[tag]();
}
return tag;
});
}
} }
return () => result; return () => result;

View file

@ -9,8 +9,6 @@ import { coreMock } from '../../../../../../src/core/public/mocks';
const elementSpecs = initializeElements(coreMock.createSetup() as any, {} as any); const elementSpecs = initializeElements(coreMock.createSetup() as any, {} as any);
import { TagStrings } from '../tags';
describe('ElementStrings', () => { describe('ElementStrings', () => {
const elementStrings = getElementStrings(); const elementStrings = getElementStrings();
const elementNames = elementSpecs.map(spec => spec().name); const elementNames = elementSpecs.map(spec => spec().name);
@ -37,15 +35,4 @@ describe('ElementStrings', () => {
expect(value).toHaveProperty('help'); expect(value).toHaveProperty('help');
}); });
}); });
test('All elements should have tags that are defined', () => {
const tagNames = Object.keys(TagStrings);
elementSpecs.forEach(spec => {
const element = spec();
if (element.tags) {
element.tags.forEach((tagName: string) => expect(tagNames).toContain(tagName));
}
});
});
}); });

View file

@ -23,7 +23,7 @@ interface ElementStringDict {
export const getElementStrings = (): ElementStringDict => ({ export const getElementStrings = (): ElementStringDict => ({
areaChart: { areaChart: {
displayName: i18n.translate('xpack.canvas.elements.areaChartDisplayName', { displayName: i18n.translate('xpack.canvas.elements.areaChartDisplayName', {
defaultMessage: 'Area chart', defaultMessage: 'Area',
}), }),
help: i18n.translate('xpack.canvas.elements.areaChartHelpText', { help: i18n.translate('xpack.canvas.elements.areaChartHelpText', {
defaultMessage: 'A line chart with a filled body', defaultMessage: 'A line chart with a filled body',
@ -31,7 +31,7 @@ export const getElementStrings = (): ElementStringDict => ({
}, },
bubbleChart: { bubbleChart: {
displayName: i18n.translate('xpack.canvas.elements.bubbleChartDisplayName', { displayName: i18n.translate('xpack.canvas.elements.bubbleChartDisplayName', {
defaultMessage: 'Bubble chart', defaultMessage: 'Bubble',
}), }),
help: i18n.translate('xpack.canvas.elements.bubbleChartHelpText', { help: i18n.translate('xpack.canvas.elements.bubbleChartHelpText', {
defaultMessage: 'A customizable bubble chart', defaultMessage: 'A customizable bubble chart',
@ -39,31 +39,31 @@ export const getElementStrings = (): ElementStringDict => ({
}, },
debug: { debug: {
displayName: i18n.translate('xpack.canvas.elements.debugDisplayName', { displayName: i18n.translate('xpack.canvas.elements.debugDisplayName', {
defaultMessage: 'Debug', defaultMessage: 'Debug data',
}), }),
help: i18n.translate('xpack.canvas.elements.debugHelpText', { help: i18n.translate('xpack.canvas.elements.debugHelpText', {
defaultMessage: 'Just dumps the configuration of the element', defaultMessage: 'Just dumps the configuration of the element',
}), }),
}, },
donut: { dropdownFilter: {
displayName: i18n.translate('xpack.canvas.elements.donutChartDisplayName', {
defaultMessage: 'Donut chart',
}),
help: i18n.translate('xpack.canvas.elements.donutChartHelpText', {
defaultMessage: 'A customizable donut chart',
}),
},
dropdown_filter: {
displayName: i18n.translate('xpack.canvas.elements.dropdownFilterDisplayName', { displayName: i18n.translate('xpack.canvas.elements.dropdownFilterDisplayName', {
defaultMessage: 'Dropdown filter', defaultMessage: 'Dropdown select',
}), }),
help: i18n.translate('xpack.canvas.elements.dropdownFilterHelpText', { help: i18n.translate('xpack.canvas.elements.dropdownFilterHelpText', {
defaultMessage: 'A dropdown from which you can select values for an "exactly" filter', defaultMessage: 'A dropdown from which you can select values for an "exactly" filter',
}), }),
}, },
filterDebug: {
displayName: i18n.translate('xpack.canvas.elements.filterDebugDisplayName', {
defaultMessage: 'Debug filters',
}),
help: i18n.translate('xpack.canvas.elements.filterDebugHelpText', {
defaultMessage: 'Shows the underlying global filters in a workpad',
}),
},
horizontalBarChart: { horizontalBarChart: {
displayName: i18n.translate('xpack.canvas.elements.horizontalBarChartDisplayName', { displayName: i18n.translate('xpack.canvas.elements.horizontalBarChartDisplayName', {
defaultMessage: 'Horizontal bar chart', defaultMessage: 'Horizontal bar',
}), }),
help: i18n.translate('xpack.canvas.elements.horizontalBarChartHelpText', { help: i18n.translate('xpack.canvas.elements.horizontalBarChartHelpText', {
defaultMessage: 'A customizable horizontal bar chart', defaultMessage: 'A customizable horizontal bar chart',
@ -71,7 +71,7 @@ export const getElementStrings = (): ElementStringDict => ({
}, },
horizontalProgressBar: { horizontalProgressBar: {
displayName: i18n.translate('xpack.canvas.elements.horizontalProgressBarDisplayName', { displayName: i18n.translate('xpack.canvas.elements.horizontalProgressBarDisplayName', {
defaultMessage: 'Horizontal progress bar', defaultMessage: 'Horizontal bar',
}), }),
help: i18n.translate('xpack.canvas.elements.horizontalProgressBarHelpText', { help: i18n.translate('xpack.canvas.elements.horizontalProgressBarHelpText', {
defaultMessage: 'Displays progress as a portion of a horizontal bar', defaultMessage: 'Displays progress as a portion of a horizontal bar',
@ -79,7 +79,7 @@ export const getElementStrings = (): ElementStringDict => ({
}, },
horizontalProgressPill: { horizontalProgressPill: {
displayName: i18n.translate('xpack.canvas.elements.horizontalProgressPillDisplayName', { displayName: i18n.translate('xpack.canvas.elements.horizontalProgressPillDisplayName', {
defaultMessage: 'Horizontal progress pill', defaultMessage: 'Horizontal pill',
}), }),
help: i18n.translate('xpack.canvas.elements.horizontalProgressPillHelpText', { help: i18n.translate('xpack.canvas.elements.horizontalProgressPillHelpText', {
defaultMessage: 'Displays progress as a portion of a horizontal pill', defaultMessage: 'Displays progress as a portion of a horizontal pill',
@ -95,7 +95,7 @@ export const getElementStrings = (): ElementStringDict => ({
}, },
lineChart: { lineChart: {
displayName: i18n.translate('xpack.canvas.elements.lineChartDisplayName', { displayName: i18n.translate('xpack.canvas.elements.lineChartDisplayName', {
defaultMessage: 'Line chart', defaultMessage: 'Line',
}), }),
help: i18n.translate('xpack.canvas.elements.lineChartHelpText', { help: i18n.translate('xpack.canvas.elements.lineChartHelpText', {
defaultMessage: 'A customizable line chart', defaultMessage: 'A customizable line chart',
@ -119,7 +119,7 @@ export const getElementStrings = (): ElementStringDict => ({
}, },
pie: { pie: {
displayName: i18n.translate('xpack.canvas.elements.pieDisplayName', { displayName: i18n.translate('xpack.canvas.elements.pieDisplayName', {
defaultMessage: 'Pie chart', defaultMessage: 'Pie',
}), }),
help: i18n.translate('xpack.canvas.elements.pieHelpText', { help: i18n.translate('xpack.canvas.elements.pieHelpText', {
defaultMessage: 'Pie chart', defaultMessage: 'Pie chart',
@ -135,7 +135,7 @@ export const getElementStrings = (): ElementStringDict => ({
}, },
progressGauge: { progressGauge: {
displayName: i18n.translate('xpack.canvas.elements.progressGaugeDisplayName', { displayName: i18n.translate('xpack.canvas.elements.progressGaugeDisplayName', {
defaultMessage: 'Progress gauge', defaultMessage: 'Gauge',
}), }),
help: i18n.translate('xpack.canvas.elements.progressGaugeHelpText', { help: i18n.translate('xpack.canvas.elements.progressGaugeHelpText', {
defaultMessage: 'Displays progress as a portion of a gauge', defaultMessage: 'Displays progress as a portion of a gauge',
@ -143,7 +143,7 @@ export const getElementStrings = (): ElementStringDict => ({
}, },
progressSemicircle: { progressSemicircle: {
displayName: i18n.translate('xpack.canvas.elements.progressSemicircleDisplayName', { displayName: i18n.translate('xpack.canvas.elements.progressSemicircleDisplayName', {
defaultMessage: 'Progress semicircle', defaultMessage: 'Semicircle',
}), }),
help: i18n.translate('xpack.canvas.elements.progressSemicircleHelpText', { help: i18n.translate('xpack.canvas.elements.progressSemicircleHelpText', {
defaultMessage: 'Displays progress as a portion of a semicircle', defaultMessage: 'Displays progress as a portion of a semicircle',
@ -151,7 +151,7 @@ export const getElementStrings = (): ElementStringDict => ({
}, },
progressWheel: { progressWheel: {
displayName: i18n.translate('xpack.canvas.elements.progressWheelDisplayName', { displayName: i18n.translate('xpack.canvas.elements.progressWheelDisplayName', {
defaultMessage: 'Progress wheel', defaultMessage: 'Wheel',
}), }),
help: i18n.translate('xpack.canvas.elements.progressWheelHelpText', { help: i18n.translate('xpack.canvas.elements.progressWheelHelpText', {
defaultMessage: 'Displays progress as a portion of a wheel', defaultMessage: 'Displays progress as a portion of a wheel',
@ -189,15 +189,7 @@ export const getElementStrings = (): ElementStringDict => ({
defaultMessage: 'A scrollable grid for displaying data in a tabular format', defaultMessage: 'A scrollable grid for displaying data in a tabular format',
}), }),
}, },
tiltedPie: { timeFilter: {
displayName: i18n.translate('xpack.canvas.elements.tiltedPieDisplayName', {
defaultMessage: 'Tilted pie chart',
}),
help: i18n.translate('xpack.canvas.elements.tiltedPieHelpText', {
defaultMessage: 'A customizable tilted pie chart',
}),
},
time_filter: {
displayName: i18n.translate('xpack.canvas.elements.timeFilterDisplayName', { displayName: i18n.translate('xpack.canvas.elements.timeFilterDisplayName', {
defaultMessage: 'Time filter', defaultMessage: 'Time filter',
}), }),
@ -207,7 +199,7 @@ export const getElementStrings = (): ElementStringDict => ({
}, },
verticalBarChart: { verticalBarChart: {
displayName: i18n.translate('xpack.canvas.elements.verticalBarChartDisplayName', { displayName: i18n.translate('xpack.canvas.elements.verticalBarChartDisplayName', {
defaultMessage: 'Vertical bar chart', defaultMessage: 'Vertical bar',
}), }),
help: i18n.translate('xpack.canvas.elements.verticalBarChartHelpText', { help: i18n.translate('xpack.canvas.elements.verticalBarChartHelpText', {
defaultMessage: 'A customizable vertical bar chart', defaultMessage: 'A customizable vertical bar chart',
@ -215,7 +207,7 @@ export const getElementStrings = (): ElementStringDict => ({
}, },
verticalProgressBar: { verticalProgressBar: {
displayName: i18n.translate('xpack.canvas.elements.verticalProgressBarDisplayName', { displayName: i18n.translate('xpack.canvas.elements.verticalProgressBarDisplayName', {
defaultMessage: 'Vertical progress bar', defaultMessage: 'Vertical bar',
}), }),
help: i18n.translate('xpack.canvas.elements.verticalProgressBarHelpText', { help: i18n.translate('xpack.canvas.elements.verticalProgressBarHelpText', {
defaultMessage: 'Displays progress as a portion of a vertical bar', defaultMessage: 'Displays progress as a portion of a vertical bar',
@ -223,7 +215,7 @@ export const getElementStrings = (): ElementStringDict => ({
}, },
verticalProgressPill: { verticalProgressPill: {
displayName: i18n.translate('xpack.canvas.elements.verticalProgressPillDisplayName', { displayName: i18n.translate('xpack.canvas.elements.verticalProgressPillDisplayName', {
defaultMessage: 'Vertical progress pill', defaultMessage: 'Vertical pill',
}), }),
help: i18n.translate('xpack.canvas.elements.verticalProgressPillHelpText', { help: i18n.translate('xpack.canvas.elements.verticalProgressPillHelpText', {
defaultMessage: 'Displays progress as a portion of a vertical pill', defaultMessage: 'Displays progress as a portion of a vertical pill',

View file

@ -8,7 +8,7 @@ import { i18n } from '@kbn/i18n';
import { alterColumn } from '../../../canvas_plugin_src/functions/common/alterColumn'; import { alterColumn } from '../../../canvas_plugin_src/functions/common/alterColumn';
import { FunctionHelp } from '../function_help'; import { FunctionHelp } from '../function_help';
import { FunctionFactory } from '../../../types'; import { FunctionFactory } from '../../../types';
import { DATATABLE_COLUMN_TYPES } from '../../../common/lib'; import { DATATABLE_COLUMN_TYPES } from '../../../common/lib/constants';
export const help: FunctionHelp<FunctionFactory<typeof alterColumn>> = { export const help: FunctionHelp<FunctionFactory<typeof alterColumn>> = {
help: i18n.translate('xpack.canvas.functions.alterColumnHelpText', { help: i18n.translate('xpack.canvas.functions.alterColumnHelpText', {

View file

@ -7,32 +7,12 @@
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
export const TagStrings: { [key: string]: () => string } = { export const TagStrings: { [key: string]: () => string } = {
chart: () =>
i18n.translate('xpack.canvas.tags.chartTag', {
defaultMessage: 'chart',
}),
filter: () =>
i18n.translate('xpack.canvas.tags.filterTag', {
defaultMessage: 'filter',
}),
graphic: () =>
i18n.translate('xpack.canvas.tags.graphicTag', {
defaultMessage: 'graphic',
}),
presentation: () => presentation: () =>
i18n.translate('xpack.canvas.tags.presentationTag', { i18n.translate('xpack.canvas.tags.presentationTag', {
defaultMessage: 'presentation', defaultMessage: 'presentation',
}), }),
proportion: () =>
i18n.translate('xpack.canvas.tags.proportionTag', {
defaultMessage: 'proportion',
}),
report: () => report: () =>
i18n.translate('xpack.canvas.tags.reportTag', { i18n.translate('xpack.canvas.tags.reportTag', {
defaultMessage: 'report', defaultMessage: 'report',
}), }),
text: () =>
i18n.translate('xpack.canvas.tags.textTag', {
defaultMessage: 'text',
}),
}; };

View file

@ -31,7 +31,7 @@ $canvasLayoutFontSize: $euiFontSizeS;
.canvasLayout__stageHeader { .canvasLayout__stageHeader {
flex-grow: 0; flex-grow: 0;
flex-basis: auto; flex-basis: auto;
padding: ($euiSizeXS + 1px) $euiSize $euiSizeXS; padding: 1px $euiSize 0;
font-size: $canvasLayoutFontSize; font-size: $canvasLayoutFontSize;
border-bottom: $euiBorderThin; border-bottom: $euiBorderThin;
background: $euiColorLightestShade; background: $euiColorLightestShade;

View file

@ -0,0 +1,761 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Storyshots components/Assets/AssetManager no assets 1`] = `
Array [
<div
data-focus-guard={true}
style={
Object {
"height": "0px",
"left": "1px",
"overflow": "hidden",
"padding": 0,
"position": "fixed",
"top": "1px",
"width": "1px",
}
}
tabIndex={0}
/>,
<div
data-focus-guard={true}
style={
Object {
"height": "0px",
"left": "1px",
"overflow": "hidden",
"padding": 0,
"position": "fixed",
"top": "1px",
"width": "1px",
}
}
tabIndex={1}
/>,
<div
data-focus-lock-disabled={false}
onBlur={[Function]}
onFocus={[Function]}
>
<div
className="euiModal canvasAssetManager canvasModal--fixedSize"
onKeyDown={[Function]}
style={
Object {
"maxWidth": "1000px",
}
}
tabIndex={0}
>
<button
aria-label="Closes this modal window"
className="euiButtonIcon euiButtonIcon--text euiModal__closeIcon"
onClick={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="cross"
size="m"
/>
</button>
<div
className="euiModal__flex"
>
<div
className="euiModalHeader canvasAssetManager__modalHeader"
>
<div
className="euiModalHeader__title canvasAssetManager__modalHeaderTitle"
>
Manage workpad assets
</div>
<div
className="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--directionRow euiFlexGroup--responsive canvasAssetManager__fileUploadWrapper"
>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<div
className="euiFilePicker euiFilePicker--compressed"
>
<div
className="euiFilePicker__wrap"
>
<input
accept="image/*"
aria-describedby="generated-id"
className="euiFilePicker__input"
multiple={true}
onChange={[Function]}
onDragLeave={[Function]}
onDragOver={[Function]}
onDrop={[Function]}
type="file"
/>
<div
className="euiFilePicker__prompt"
id="generated-id"
>
<div
aria-hidden="true"
className="euiFilePicker__icon"
data-euiicon-type="importAction"
size="m"
/>
<div
className="euiFilePicker__promptText"
>
Select or drag and drop images
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div
className="euiModalBody"
>
<div
className="euiModalBody__overflow"
>
<div
className="euiText euiText--small"
>
<div
className="euiTextColor euiTextColor--subdued"
>
<p>
Below are the image assets in this workpad. Any assets that are currently in use cannot be determined at this time. To reclaim space, delete assets.
</p>
</div>
</div>
<div
className="euiSpacer euiSpacer--l"
/>
<div
className="euiPanel euiPanel--paddingMedium canvasAssetManager__emptyPanel"
>
<div
className="euiEmptyPrompt"
>
<div
color="subdued"
data-euiicon-type="importAction"
size="xxl"
/>
<div
className="euiSpacer euiSpacer--s"
/>
<span
className="euiTextColor euiTextColor--subdued"
>
<h2
className="euiTitle euiTitle--xsmall"
>
Import your assets to get started
</h2>
<div
className="euiSpacer euiSpacer--m"
/>
</span>
</div>
</div>
</div>
</div>
<div
className="euiModalFooter canvasAssetManager__modalFooter"
>
<div
className="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--directionRow canvasAssetManager__meterWrapper"
>
<div
className="euiFlexItem"
>
<progress
aria-labelledby="CanvasAssetManagerLabel"
className="euiProgress euiProgress--native euiProgress--s euiProgress--secondary"
max={25000}
value={0}
/>
</div>
<div
className="euiFlexItem euiFlexItem--flexGrowZero eui-textNoWrap"
>
<div
className="euiText euiText--medium"
id="CanvasAssetManagerLabel"
>
0% space used
</div>
</div>
</div>
<button
className="euiButton euiButton--primary euiButton--small"
onClick={[Function]}
type="button"
>
<span
className="euiButton__content"
>
<span
className="euiButton__text"
>
Close
</span>
</span>
</button>
</div>
</div>
</div>
</div>,
<div
data-focus-guard={true}
style={
Object {
"height": "0px",
"left": "1px",
"overflow": "hidden",
"padding": 0,
"position": "fixed",
"top": "1px",
"width": "1px",
}
}
tabIndex={0}
/>,
]
`;
exports[`Storyshots components/Assets/AssetManager two assets 1`] = `
Array [
<div
data-focus-guard={true}
style={
Object {
"height": "0px",
"left": "1px",
"overflow": "hidden",
"padding": 0,
"position": "fixed",
"top": "1px",
"width": "1px",
}
}
tabIndex={0}
/>,
<div
data-focus-guard={true}
style={
Object {
"height": "0px",
"left": "1px",
"overflow": "hidden",
"padding": 0,
"position": "fixed",
"top": "1px",
"width": "1px",
}
}
tabIndex={1}
/>,
<div
data-focus-lock-disabled={false}
onBlur={[Function]}
onFocus={[Function]}
>
<div
className="euiModal canvasAssetManager canvasModal--fixedSize"
onKeyDown={[Function]}
style={
Object {
"maxWidth": "1000px",
}
}
tabIndex={0}
>
<button
aria-label="Closes this modal window"
className="euiButtonIcon euiButtonIcon--text euiModal__closeIcon"
onClick={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="cross"
size="m"
/>
</button>
<div
className="euiModal__flex"
>
<div
className="euiModalHeader canvasAssetManager__modalHeader"
>
<div
className="euiModalHeader__title canvasAssetManager__modalHeaderTitle"
>
Manage workpad assets
</div>
<div
className="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--directionRow euiFlexGroup--responsive canvasAssetManager__fileUploadWrapper"
>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<div
className="euiFilePicker euiFilePicker--compressed"
>
<div
className="euiFilePicker__wrap"
>
<input
accept="image/*"
aria-describedby="generated-id"
className="euiFilePicker__input"
multiple={true}
onChange={[Function]}
onDragLeave={[Function]}
onDragOver={[Function]}
onDrop={[Function]}
type="file"
/>
<div
className="euiFilePicker__prompt"
id="generated-id"
>
<div
aria-hidden="true"
className="euiFilePicker__icon"
data-euiicon-type="importAction"
size="m"
/>
<div
className="euiFilePicker__promptText"
>
Select or drag and drop images
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div
className="euiModalBody"
>
<div
className="euiModalBody__overflow"
>
<div
className="euiText euiText--small"
>
<div
className="euiTextColor euiTextColor--subdued"
>
<p>
Below are the image assets in this workpad. Any assets that are currently in use cannot be determined at this time. To reclaim space, delete assets.
</p>
</div>
</div>
<div
className="euiSpacer euiSpacer--l"
/>
<div
className="euiFlexGrid euiFlexGrid--gutterLarge euiFlexGrid--fourths euiFlexGrid--responsive"
>
<div
className="euiFlexItem"
>
<div
className="euiPanel euiPanel--paddingSmall canvasAsset"
>
<div
className="canvasAsset__thumb canvasCheckered"
>
<figure
className="euiImage canvasAsset__img "
>
<img
alt="Asset thumbnail"
className="euiImage__img"
src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1Ni4zMSA1Ni4zMSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOiNmZmY7c3Ryb2tlOiMwMDc4YTA7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlLXdpZHRoOjJweDt9PC9zdHlsZT48L2RlZnM+PHRpdGxlPlBsYW5lIEljb248L3RpdGxlPjxnIGlkPSJMYXllcl8yIiBkYXRhLW5hbWU9IkxheWVyIDIiPjxnIGlkPSJMYXllcl8xLTIiIGRhdGEtbmFtZT0iTGF5ZXIgMSI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNDkuNTEsNDguOTMsNDEuMjYsMjIuNTIsNTMuNzYsMTBhNS4yOSw1LjI5LDAsMCwwLTcuNDgtNy40N2wtMTIuNSwxMi41TDcuMzgsNi43OUEuNy43LDAsMCwwLDYuNjksN0wxLjIsMTIuNDVhLjcuNywwLDAsMCwwLDFMMTkuODUsMjlsLTcuMjQsNy4yNC03Ljc0LS42YS43MS43MSwwLDAsMC0uNTMuMkwxLjIxLDM5YS42Ny42NywwLDAsMCwuMDgsMUw5LjQ1LDQ2bC4wNywwYy4xMS4xMy4yMi4yNi4zNC4zOHMuMjUuMjMuMzguMzRhLjM2LjM2LDAsMCwwLDAsLjA3TDE2LjMzLDU1YS42OC42OCwwLDAsMCwxLC4wN0wyMC40OSw1MmEuNjcuNjcsMCwwLDAsLjE5LS41NGwtLjU5LTcuNzQsNy4yNC03LjI0TDQyLjg1LDU1LjA2YS42OC42OCwwLDAsMCwxLDBsNS41LTUuNUEuNjYuNjYsMCwwLDAsNDkuNTEsNDguOTNaIi8+PC9nPjwvZz48L3N2Zz4="
style={Object {}}
/>
</figure>
</div>
<div
className="euiSpacer euiSpacer--s"
/>
<div
className="euiText euiText--extraSmall eui-textBreakAll"
>
<p
className="eui-textBreakAll"
>
<strong>
airplane
</strong>
<br />
<span
className="euiTextColor euiTextColor--subdued"
>
<small>
(
1
kb)
</small>
</span>
</p>
</div>
<div
className="euiSpacer euiSpacer--s"
/>
<div
className="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--alignItemsBaseline euiFlexGroup--justifyContentCenter euiFlexGroup--directionRow"
>
<div
className="euiFlexItem euiFlexItem--flexGrowZero asset-create-image"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<button
aria-label="Create image element"
className="euiButtonIcon euiButtonIcon--primary"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="vector"
size="m"
/>
</button>
</span>
</div>
<div
className="euiFlexItem euiFlexItem--flexGrowZero asset-download"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<div
className="canvasDownload"
onClick={[Function]}
onKeyPress={[Function]}
role="button"
tabIndex={0}
>
<button
aria-label="Download"
className="euiButtonIcon euiButtonIcon--primary"
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="sortDown"
size="m"
/>
</button>
</div>
</span>
</div>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<div
className="canvasClipboard"
onClick={[Function]}
onKeyPress={[Function]}
role="button"
tabIndex={0}
>
<button
aria-label="Copy id to clipboard"
className="euiButtonIcon euiButtonIcon--primary"
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="copyClipboard"
size="m"
/>
</button>
</div>
</span>
</div>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<button
aria-label="Delete"
className="euiButtonIcon euiButtonIcon--danger"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="trash"
size="m"
/>
</button>
</span>
</div>
</div>
</div>
</div>
<div
className="euiFlexItem"
>
<div
className="euiPanel euiPanel--paddingSmall canvasAsset"
>
<div
className="canvasAsset__thumb canvasCheckered"
>
<figure
className="euiImage canvasAsset__img "
>
<img
alt="Asset thumbnail"
className="euiImage__img"
src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzOC4zOSA1Ny41NyI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOiNmZmY7c3Ryb2tlOiMwMTliOGY7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlLXdpZHRoOjJweDt9PC9zdHlsZT48L2RlZnM+PHRpdGxlPkxvY2F0aW9uIEljb248L3RpdGxlPjxnIGlkPSJMYXllcl8yIiBkYXRhLW5hbWU9IkxheWVyIDIiPjxnIGlkPSJMYXllcl8xLTIiIGRhdGEtbmFtZT0iTGF5ZXIgMSI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTkuMTksMUExOC4xOSwxOC4xOSwwLDAsMCwyLjk0LDI3LjM2aDBhMTkuNTEsMTkuNTEsMCwwLDAsMSwxLjc4TDE5LjE5LDU1LjU3LDM0LjM4LDI5LjIxQTE4LjE5LDE4LjE5LDAsMCwwLDE5LjE5LDFabTAsMjMuMjlhNS41Myw1LjUzLDAsMSwxLDUuNTMtNS41M0E1LjUzLDUuNTMsMCwwLDEsMTkuMTksMjQuMjlaIi8+PC9nPjwvZz48L3N2Zz4="
style={Object {}}
/>
</figure>
</div>
<div
className="euiSpacer euiSpacer--s"
/>
<div
className="euiText euiText--extraSmall eui-textBreakAll"
>
<p
className="eui-textBreakAll"
>
<strong>
marker
</strong>
<br />
<span
className="euiTextColor euiTextColor--subdued"
>
<small>
(
1
kb)
</small>
</span>
</p>
</div>
<div
className="euiSpacer euiSpacer--s"
/>
<div
className="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--alignItemsBaseline euiFlexGroup--justifyContentCenter euiFlexGroup--directionRow"
>
<div
className="euiFlexItem euiFlexItem--flexGrowZero asset-create-image"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<button
aria-label="Create image element"
className="euiButtonIcon euiButtonIcon--primary"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="vector"
size="m"
/>
</button>
</span>
</div>
<div
className="euiFlexItem euiFlexItem--flexGrowZero asset-download"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<div
className="canvasDownload"
onClick={[Function]}
onKeyPress={[Function]}
role="button"
tabIndex={0}
>
<button
aria-label="Download"
className="euiButtonIcon euiButtonIcon--primary"
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="sortDown"
size="m"
/>
</button>
</div>
</span>
</div>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<div
className="canvasClipboard"
onClick={[Function]}
onKeyPress={[Function]}
role="button"
tabIndex={0}
>
<button
aria-label="Copy id to clipboard"
className="euiButtonIcon euiButtonIcon--primary"
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="copyClipboard"
size="m"
/>
</button>
</div>
</span>
</div>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<button
aria-label="Delete"
className="euiButtonIcon euiButtonIcon--danger"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="trash"
size="m"
/>
</button>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div
className="euiModalFooter canvasAssetManager__modalFooter"
>
<div
className="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--directionRow canvasAssetManager__meterWrapper"
>
<div
className="euiFlexItem"
>
<progress
aria-labelledby="CanvasAssetManagerLabel"
className="euiProgress euiProgress--native euiProgress--s euiProgress--secondary"
max={25000}
value={2}
/>
</div>
<div
className="euiFlexItem euiFlexItem--flexGrowZero eui-textNoWrap"
>
<div
className="euiText euiText--medium"
id="CanvasAssetManagerLabel"
>
0% space used
</div>
</div>
</div>
<button
className="euiButton euiButton--primary euiButton--small"
onClick={[Function]}
type="button"
>
<span
className="euiButton__content"
>
<span
className="euiButton__text"
>
Close
</span>
</span>
</button>
</div>
</div>
</div>
</div>,
<div
data-focus-guard={true}
style={
Object {
"height": "0px",
"left": "1px",
"overflow": "hidden",
"padding": 0,
"position": "fixed",
"top": "1px",
"width": "1px",
}
}
tabIndex={0}
/>,
]
`;

View file

@ -28,12 +28,12 @@ const MARKER: AssetType = {
storiesOf('components/Assets/AssetManager', module) storiesOf('components/Assets/AssetManager', module)
.add('no assets', () => ( .add('no assets', () => (
// @ts-ignore @types/react has not been updated to support defaultProps yet.
<AssetManager <AssetManager
onAddImageElement={action('onAddImageElement')} onAddImageElement={action('onAddImageElement')}
onAssetAdd={action('onAssetAdd')} onAssetAdd={action('onAssetAdd')}
onAssetCopy={action('onAssetCopy')} onAssetCopy={action('onAssetCopy')}
onAssetDelete={action('onAssetDelete')} onAssetDelete={action('onAssetDelete')}
onClose={action('onClose')}
/> />
)) ))
.add('two assets', () => ( .add('two assets', () => (
@ -43,5 +43,6 @@ storiesOf('components/Assets/AssetManager', module)
onAssetAdd={action('onAssetAdd')} onAssetAdd={action('onAssetAdd')}
onAssetCopy={action('onAssetCopy')} onAssetCopy={action('onAssetCopy')}
onAssetDelete={action('onAssetDelete')} onAssetDelete={action('onAssetDelete')}
onClose={action('onClose')}
/> />
)); ));

View file

@ -4,13 +4,6 @@
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
import {
EuiButtonEmpty,
// @ts-ignore (elastic/eui#1557) EuiFilePicker is not exported yet
EuiFilePicker,
// @ts-ignore (elastic/eui#1557) EuiImage is not exported yet
EuiImage,
} from '@elastic/eui';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, { Fragment, PureComponent } from 'react'; import React, { Fragment, PureComponent } from 'react';
@ -33,13 +26,13 @@ interface Props {
onAssetCopy: () => void; onAssetCopy: () => void;
/** Function to invoke when an asset is added */ /** Function to invoke when an asset is added */
onAssetAdd: (asset: File) => void; onAssetAdd: (asset: File) => void;
/** Function to invoke when an asset modal is closed */
onClose: () => void;
} }
interface State { interface State {
/** The id of the asset to delete, if applicable. Is set if the viewer clicks the delete icon */ /** The id of the asset to delete, if applicable. Is set if the viewer clicks the delete icon */
deleteId: string | null; deleteId: string | null;
/** Determines if the modal is currently visible */
isModalVisible: boolean;
/** Indicates if the modal is currently loading */ /** Indicates if the modal is currently loading */
isLoading: boolean; isLoading: boolean;
} }
@ -51,6 +44,7 @@ export class AssetManager extends PureComponent<Props, State> {
onAssetAdd: PropTypes.func.isRequired, onAssetAdd: PropTypes.func.isRequired,
onAssetCopy: PropTypes.func.isRequired, onAssetCopy: PropTypes.func.isRequired,
onAssetDelete: PropTypes.func.isRequired, onAssetDelete: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired,
}; };
public static defaultProps = { public static defaultProps = {
@ -60,12 +54,11 @@ export class AssetManager extends PureComponent<Props, State> {
public state = { public state = {
deleteId: null, deleteId: null,
isLoading: false, isLoading: false,
isModalVisible: false,
}; };
public render() { public render() {
const { isModalVisible, isLoading } = this.state; const { isLoading } = this.state;
const { assetValues, onAssetCopy, onAddImageElement } = this.props; const { assetValues, onAssetCopy, onAddImageElement, onClose } = this.props;
const assetModal = ( const assetModal = (
<AssetModal <AssetModal
@ -74,10 +67,10 @@ export class AssetManager extends PureComponent<Props, State> {
onAssetCopy={onAssetCopy} onAssetCopy={onAssetCopy}
onAssetCreate={(createdAsset: AssetType) => { onAssetCreate={(createdAsset: AssetType) => {
onAddImageElement(createdAsset.id); onAddImageElement(createdAsset.id);
this.setState({ isModalVisible: false }); onClose();
}} }}
onAssetDelete={(asset: AssetType) => this.setState({ deleteId: asset.id })} onAssetDelete={(asset: AssetType) => this.setState({ deleteId: asset.id })}
onClose={() => this.setState({ isModalVisible: false })} onClose={onClose}
onFileUpload={this.handleFileUpload} onFileUpload={this.handleFileUpload}
/> />
); );
@ -95,14 +88,12 @@ export class AssetManager extends PureComponent<Props, State> {
return ( return (
<Fragment> <Fragment>
<EuiButtonEmpty onClick={this.showModal}>{strings.getButtonLabel()}</EuiButtonEmpty> {assetModal}
{isModalVisible ? assetModal : null}
{confirmModal} {confirmModal}
</Fragment> </Fragment>
); );
} }
private showModal = () => this.setState({ isModalVisible: true });
private resetDelete = () => this.setState({ deleteId: null }); private resetDelete = () => this.setState({ deleteId: null });
private doDelete = () => { private doDelete = () => {

View file

@ -98,6 +98,7 @@ export const AssetModal: FunctionComponent<Props> = props => {
<EuiFilePicker <EuiFilePicker
initialPromptText={strings.getFilePickerPromptText()} initialPromptText={strings.getFilePickerPromptText()}
compressed compressed
display="default"
multiple multiple
onChange={onFileUpload} onChange={onFileUpload}
accept="image/*" accept="image/*"

View file

@ -1,797 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Storyshots components/Elements/ElementGrid with controls 1`] = `
<div
style={
Object {
"width": "1000px",
}
}
>
<div
className="euiFlexGrid euiFlexGrid--gutterLarge euiFlexGrid--fourths euiFlexGrid--responsive"
>
<div
className="euiFlexItem canvasElementCard__wrapper"
>
<div
className="euiCard euiCard--leftAligned euiCard--isClickable canvasElementCard"
onClick={[Function]}
>
<div
className="euiCard__top"
>
<img
alt=""
className="euiCard__image"
src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmlld0JveD0iMCAwIDI3MC42MDAwMSAyNjkuNTQ2NjYiCiAgIGhlaWdodD0iMjY5LjU0NjY2IgogICB3aWR0aD0iMjcwLjYwMDAxIgogICB4bWw6c3BhY2U9InByZXNlcnZlIgogICBpZD0ic3ZnMiIKICAgdmVyc2lvbj0iMS4xIj48bWV0YWRhdGEKICAgICBpZD0ibWV0YWRhdGE4Ij48cmRmOlJERj48Y2M6V29yawogICAgICAgICByZGY6YWJvdXQ9IiI+PGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+PGRjOnR5cGUKICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPjwvY2M6V29yaz48L3JkZjpSREY+PC9tZXRhZGF0YT48ZGVmcwogICAgIGlkPSJkZWZzNiIgLz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMzMzMzMzMywwLDAsLTEuMzMzMzMzMywwLDI2OS41NDY2NykiCiAgICAgaWQ9ImcxMCI+PGcKICAgICAgIHRyYW5zZm9ybT0ic2NhbGUoMC4xKSIKICAgICAgIGlkPSJnMTIiPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMTQiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNmZmZmZmY7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMjAyOS40OCw5NjIuNDQxIGMgMCwxNzAuMDk5IC0xMDUuNDYsMzE4Ljc5OSAtMjY0LjE3LDM3Ni42NTkgNi45OCwzNS44NiAxMC42Miw3MS43MSAxMC42MiwxMDkuMDUgMCwzMTYuMTkgLTI1Ny4yNCw1NzMuNDMgLTU3My40Nyw1NzMuNDMgLTE4NC43MiwwIC0zNTYuNTU4LC04OC41OSAtNDY0LjUzLC0yMzcuODUgLTUzLjA5LDQxLjE4IC0xMTguMjg1LDYzLjc1IC0xODYuMzA1LDYzLjc1IC0xNjcuODM2LDAgLTMwNC4zODMsLTEzNi41NCAtMzA0LjM4MywtMzA0LjM4IDAsLTM3LjA4IDYuNjE3LC03Mi41OCAxOS4wMzEsLTEwNi4wOCBDIDEwOC40ODgsMTM4MC4wOSAwLDEyMjcuODkgMCwxMDU4Ljg4IDAsODg3LjkxIDEwNS45NzcsNzM4LjUzOSAyNjUuMzk4LDY4MS4wOSBjIC02Ljc2OSwtMzUuNDQyIC0xMC40NiwtNzIuMDIgLTEwLjQ2LC0xMDkgQyAyNTQuOTM4LDI1Ni42MjEgNTExLjU2NiwwIDgyNy4wMjcsMCAxMDEyLjIsMCAxMTgzLjk0LDg4Ljk0MTQgMTI5MS4zLDIzOC44MzIgYyA1My40NSwtNDEuOTYxIDExOC44LC02NC45OTIgMTg2LjU2LC02NC45OTIgMTY3LjgzLDAgMzA0LjM4LDEzNi40OTIgMzA0LjM4LDMwNC4zMzIgMCwzNy4wNzggLTYuNjIsNzIuNjI5IC0xOS4wMywxMDYuMTI5IDE1Ny43OCw1Ni44NzkgMjY2LjI3LDIwOS4xMjkgMjY2LjI3LDM3OC4xNCIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDE2IgogICAgICAgICBzdHlsZT0iZmlsbDojZmFjZjA5O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDc5Ny44OTgsMTE1MC45MyA0NDQuMDcyLC0yMDIuNDUgNDQ4LjA1LDM5Mi41OCBjIDYuNDksMzIuMzkgOS42Niw2NC42NyA5LjY2LDk4LjQ2IDAsMjc2LjIzIC0yMjQuNjgsNTAwLjk1IC01MDAuOSw1MDAuOTUgLTE2NS4yNCwwIC0zMTkuMzcsLTgxLjM2IC00MTMuMDUzLC0yMTcuNzkgbCAtNzQuNTI0LC0zODYuNjQgODYuNjk1LC0xODUuMTEiIC8+PHBhdGgKICAgICAgICAgaWQ9InBhdGgxOCIKICAgICAgICAgc3R5bGU9ImZpbGw6IzQ5YzFhZTtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIKICAgICAgICAgZD0ibSAzMzguMjIzLDY4MC42NzIgYyAtNi40ODksLTMyLjM4MyAtOS44MDksLTY1Ljk4MSAtOS44MDksLTk5Ljk3MyAwLC0yNzYuOTI5IDIyNS4zMzYsLTUwMi4yNTc2IDUwMi4zMTMsLTUwMi4yNTc2IDE2Ni41OTMsMCAzMjEuNDczLDgyLjExNzYgNDE1LjAxMywyMTkuOTQ5NiBsIDczLjk3LDM4NS4zNDcgLTk4LjcyLDE4OC42MjEgTCA3NzUuMTU2LDEwNzUuNTcgMzM4LjIyMyw2ODAuNjcyIiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjAiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNlZjI5OWI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMzM1LjQxLDE0NDkuMTggMzA0LjMzMiwtNzEuODYgNjYuNjgsMzQ2LjAyIGMgLTQxLjU4NiwzMS43OCAtOTIuOTMsNDkuMTggLTE0NS43MzEsNDkuMTggLTEzMi4yNSwwIC0yMzkuODEyLC0xMDcuNjEgLTIzOS44MTIsLTIzOS44NyAwLC0yOS4yMSA0Ljg3OSwtNTcuMjIgMTQuNTMxLC04My40NyIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDIyIgogICAgICAgICBzdHlsZT0iZmlsbDojNGNhYmU0O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJNIDMwOC45OTIsMTM3Ni43IEMgMTczLjAyLDEzMzEuNjQgNzguNDgwNSwxMjAxLjMgNzguNDgwNSwxMDU3LjkzIDc4LjQ4MDUsOTE4LjM0IDE2NC44Miw3OTMuNjggMjk0LjQwNiw3NDQuMzUyIGwgNDI2Ljk4MSwzODUuOTM4IC03OC4zOTUsMTY3LjUxIC0zMzQsNzguOSIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICBzdHlsZT0iZmlsbDojODVjZTI2O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDEzMjMuOCwyOTguNDEgYyA0MS43NCwtMzIuMDkgOTIuODMsLTQ5LjU5IDE0NC45OCwtNDkuNTkgMTMyLjI1LDAgMjM5LjgxLDEwNy41NTkgMjM5LjgxLDIzOS44MjEgMCwyOS4xNiAtNC44OCw1Ny4xNjggLTE0LjUzLDgzLjQxOCBsIC0zMDQuMDgsNzEuMTYgLTY2LjE4LC0zNDQuODA5IiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjYiCiAgICAgICAgIHN0eWxlPSJmaWxsOiMzMTc3YTc7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMTM4NS42Nyw3MjIuOTMgMzM0Ljc2LC03OC4zMDEgYyAxMzYuMDIsNDQuOTYxIDIzMC41NiwxNzUuMzUxIDIzMC41NiwzMTguNzYyIDAsMTM5LjMzOSAtODYuNTQsMjYzLjg1OSAtMjE2LjM4LDMxMy4wMzkgbCAtNDM3Ljg0LC0zODMuNTkgODguOSwtMTY5LjkxIiAvPjwvZz48L2c+PC9zdmc+"
/>
</div>
<div
className="euiCard__content"
>
<span
className="euiTitle euiTitle--small euiCard__title"
id="generated-idTitle"
>
<button
aria-describedby=" generated-idDescription"
className="euiCard__titleButton"
onClick={[Function]}
>
Custom Element 1
</button>
</span>
<div
className="euiText euiText--small euiCard__description"
id="generated-idDescription"
>
<p>
sample description
</p>
</div>
</div>
<div
className="euiCard__footer"
/>
</div>
<div
className="euiFlexGroup euiFlexGroup--gutterExtraSmall euiFlexGroup--justifyContentSpaceBetween euiFlexGroup--directionRow euiFlexGroup--responsive canvasElementCard__controls"
>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<button
aria-label="Edit element"
className="euiButtonIcon euiButtonIcon--primary"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="pencil"
size="m"
/>
</button>
</span>
</div>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<button
aria-label="Delete element"
className="euiButtonIcon euiButtonIcon--danger"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="trash"
size="m"
/>
</button>
</span>
</div>
</div>
</div>
<div
className="euiFlexItem canvasElementCard__wrapper"
>
<div
className="euiCard euiCard--leftAligned euiCard--isClickable canvasElementCard"
onClick={[Function]}
>
<div
className="euiCard__top"
>
<img
alt=""
className="euiCard__image"
src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmlld0JveD0iMCAwIDI3MC42MDAwMSAyNjkuNTQ2NjYiCiAgIGhlaWdodD0iMjY5LjU0NjY2IgogICB3aWR0aD0iMjcwLjYwMDAxIgogICB4bWw6c3BhY2U9InByZXNlcnZlIgogICBpZD0ic3ZnMiIKICAgdmVyc2lvbj0iMS4xIj48bWV0YWRhdGEKICAgICBpZD0ibWV0YWRhdGE4Ij48cmRmOlJERj48Y2M6V29yawogICAgICAgICByZGY6YWJvdXQ9IiI+PGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+PGRjOnR5cGUKICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPjwvY2M6V29yaz48L3JkZjpSREY+PC9tZXRhZGF0YT48ZGVmcwogICAgIGlkPSJkZWZzNiIgLz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMzMzMzMzMywwLDAsLTEuMzMzMzMzMywwLDI2OS41NDY2NykiCiAgICAgaWQ9ImcxMCI+PGcKICAgICAgIHRyYW5zZm9ybT0ic2NhbGUoMC4xKSIKICAgICAgIGlkPSJnMTIiPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMTQiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNmZmZmZmY7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMjAyOS40OCw5NjIuNDQxIGMgMCwxNzAuMDk5IC0xMDUuNDYsMzE4Ljc5OSAtMjY0LjE3LDM3Ni42NTkgNi45OCwzNS44NiAxMC42Miw3MS43MSAxMC42MiwxMDkuMDUgMCwzMTYuMTkgLTI1Ny4yNCw1NzMuNDMgLTU3My40Nyw1NzMuNDMgLTE4NC43MiwwIC0zNTYuNTU4LC04OC41OSAtNDY0LjUzLC0yMzcuODUgLTUzLjA5LDQxLjE4IC0xMTguMjg1LDYzLjc1IC0xODYuMzA1LDYzLjc1IC0xNjcuODM2LDAgLTMwNC4zODMsLTEzNi41NCAtMzA0LjM4MywtMzA0LjM4IDAsLTM3LjA4IDYuNjE3LC03Mi41OCAxOS4wMzEsLTEwNi4wOCBDIDEwOC40ODgsMTM4MC4wOSAwLDEyMjcuODkgMCwxMDU4Ljg4IDAsODg3LjkxIDEwNS45NzcsNzM4LjUzOSAyNjUuMzk4LDY4MS4wOSBjIC02Ljc2OSwtMzUuNDQyIC0xMC40NiwtNzIuMDIgLTEwLjQ2LC0xMDkgQyAyNTQuOTM4LDI1Ni42MjEgNTExLjU2NiwwIDgyNy4wMjcsMCAxMDEyLjIsMCAxMTgzLjk0LDg4Ljk0MTQgMTI5MS4zLDIzOC44MzIgYyA1My40NSwtNDEuOTYxIDExOC44LC02NC45OTIgMTg2LjU2LC02NC45OTIgMTY3LjgzLDAgMzA0LjM4LDEzNi40OTIgMzA0LjM4LDMwNC4zMzIgMCwzNy4wNzggLTYuNjIsNzIuNjI5IC0xOS4wMywxMDYuMTI5IDE1Ny43OCw1Ni44NzkgMjY2LjI3LDIwOS4xMjkgMjY2LjI3LDM3OC4xNCIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDE2IgogICAgICAgICBzdHlsZT0iZmlsbDojZmFjZjA5O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDc5Ny44OTgsMTE1MC45MyA0NDQuMDcyLC0yMDIuNDUgNDQ4LjA1LDM5Mi41OCBjIDYuNDksMzIuMzkgOS42Niw2NC42NyA5LjY2LDk4LjQ2IDAsMjc2LjIzIC0yMjQuNjgsNTAwLjk1IC01MDAuOSw1MDAuOTUgLTE2NS4yNCwwIC0zMTkuMzcsLTgxLjM2IC00MTMuMDUzLC0yMTcuNzkgbCAtNzQuNTI0LC0zODYuNjQgODYuNjk1LC0xODUuMTEiIC8+PHBhdGgKICAgICAgICAgaWQ9InBhdGgxOCIKICAgICAgICAgc3R5bGU9ImZpbGw6IzQ5YzFhZTtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIKICAgICAgICAgZD0ibSAzMzguMjIzLDY4MC42NzIgYyAtNi40ODksLTMyLjM4MyAtOS44MDksLTY1Ljk4MSAtOS44MDksLTk5Ljk3MyAwLC0yNzYuOTI5IDIyNS4zMzYsLTUwMi4yNTc2IDUwMi4zMTMsLTUwMi4yNTc2IDE2Ni41OTMsMCAzMjEuNDczLDgyLjExNzYgNDE1LjAxMywyMTkuOTQ5NiBsIDczLjk3LDM4NS4zNDcgLTk4LjcyLDE4OC42MjEgTCA3NzUuMTU2LDEwNzUuNTcgMzM4LjIyMyw2ODAuNjcyIiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjAiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNlZjI5OWI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMzM1LjQxLDE0NDkuMTggMzA0LjMzMiwtNzEuODYgNjYuNjgsMzQ2LjAyIGMgLTQxLjU4NiwzMS43OCAtOTIuOTMsNDkuMTggLTE0NS43MzEsNDkuMTggLTEzMi4yNSwwIC0yMzkuODEyLC0xMDcuNjEgLTIzOS44MTIsLTIzOS44NyAwLC0yOS4yMSA0Ljg3OSwtNTcuMjIgMTQuNTMxLC04My40NyIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDIyIgogICAgICAgICBzdHlsZT0iZmlsbDojNGNhYmU0O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJNIDMwOC45OTIsMTM3Ni43IEMgMTczLjAyLDEzMzEuNjQgNzguNDgwNSwxMjAxLjMgNzguNDgwNSwxMDU3LjkzIDc4LjQ4MDUsOTE4LjM0IDE2NC44Miw3OTMuNjggMjk0LjQwNiw3NDQuMzUyIGwgNDI2Ljk4MSwzODUuOTM4IC03OC4zOTUsMTY3LjUxIC0zMzQsNzguOSIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICBzdHlsZT0iZmlsbDojODVjZTI2O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDEzMjMuOCwyOTguNDEgYyA0MS43NCwtMzIuMDkgOTIuODMsLTQ5LjU5IDE0NC45OCwtNDkuNTkgMTMyLjI1LDAgMjM5LjgxLDEwNy41NTkgMjM5LjgxLDIzOS44MjEgMCwyOS4xNiAtNC44OCw1Ny4xNjggLTE0LjUzLDgzLjQxOCBsIC0zMDQuMDgsNzEuMTYgLTY2LjE4LC0zNDQuODA5IiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjYiCiAgICAgICAgIHN0eWxlPSJmaWxsOiMzMTc3YTc7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMTM4NS42Nyw3MjIuOTMgMzM0Ljc2LC03OC4zMDEgYyAxMzYuMDIsNDQuOTYxIDIzMC41NiwxNzUuMzUxIDIzMC41NiwzMTguNzYyIDAsMTM5LjMzOSAtODYuNTQsMjYzLjg1OSAtMjE2LjM4LDMxMy4wMzkgbCAtNDM3Ljg0LC0zODMuNTkgODguOSwtMTY5LjkxIiAvPjwvZz48L2c+PC9zdmc+"
/>
</div>
<div
className="euiCard__content"
>
<span
className="euiTitle euiTitle--small euiCard__title"
id="generated-idTitle"
>
<button
aria-describedby=" generated-idDescription"
className="euiCard__titleButton"
onClick={[Function]}
>
Custom Element 2
</button>
</span>
<div
className="euiText euiText--small euiCard__description"
id="generated-idDescription"
>
<p>
Aenean eu justo auctor, placerat felis non, scelerisque dolor.
</p>
</div>
</div>
<div
className="euiCard__footer"
/>
</div>
<div
className="euiFlexGroup euiFlexGroup--gutterExtraSmall euiFlexGroup--justifyContentSpaceBetween euiFlexGroup--directionRow euiFlexGroup--responsive canvasElementCard__controls"
>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<button
aria-label="Edit element"
className="euiButtonIcon euiButtonIcon--primary"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="pencil"
size="m"
/>
</button>
</span>
</div>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<button
aria-label="Delete element"
className="euiButtonIcon euiButtonIcon--danger"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="trash"
size="m"
/>
</button>
</span>
</div>
</div>
</div>
<div
className="euiFlexItem canvasElementCard__wrapper"
>
<div
className="euiCard euiCard--leftAligned euiCard--isClickable canvasElementCard"
onClick={[Function]}
>
<div
className="euiCard__top"
>
<img
alt=""
className="euiCard__image"
src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmlld0JveD0iMCAwIDI3MC42MDAwMSAyNjkuNTQ2NjYiCiAgIGhlaWdodD0iMjY5LjU0NjY2IgogICB3aWR0aD0iMjcwLjYwMDAxIgogICB4bWw6c3BhY2U9InByZXNlcnZlIgogICBpZD0ic3ZnMiIKICAgdmVyc2lvbj0iMS4xIj48bWV0YWRhdGEKICAgICBpZD0ibWV0YWRhdGE4Ij48cmRmOlJERj48Y2M6V29yawogICAgICAgICByZGY6YWJvdXQ9IiI+PGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+PGRjOnR5cGUKICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPjwvY2M6V29yaz48L3JkZjpSREY+PC9tZXRhZGF0YT48ZGVmcwogICAgIGlkPSJkZWZzNiIgLz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMzMzMzMzMywwLDAsLTEuMzMzMzMzMywwLDI2OS41NDY2NykiCiAgICAgaWQ9ImcxMCI+PGcKICAgICAgIHRyYW5zZm9ybT0ic2NhbGUoMC4xKSIKICAgICAgIGlkPSJnMTIiPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMTQiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNmZmZmZmY7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMjAyOS40OCw5NjIuNDQxIGMgMCwxNzAuMDk5IC0xMDUuNDYsMzE4Ljc5OSAtMjY0LjE3LDM3Ni42NTkgNi45OCwzNS44NiAxMC42Miw3MS43MSAxMC42MiwxMDkuMDUgMCwzMTYuMTkgLTI1Ny4yNCw1NzMuNDMgLTU3My40Nyw1NzMuNDMgLTE4NC43MiwwIC0zNTYuNTU4LC04OC41OSAtNDY0LjUzLC0yMzcuODUgLTUzLjA5LDQxLjE4IC0xMTguMjg1LDYzLjc1IC0xODYuMzA1LDYzLjc1IC0xNjcuODM2LDAgLTMwNC4zODMsLTEzNi41NCAtMzA0LjM4MywtMzA0LjM4IDAsLTM3LjA4IDYuNjE3LC03Mi41OCAxOS4wMzEsLTEwNi4wOCBDIDEwOC40ODgsMTM4MC4wOSAwLDEyMjcuODkgMCwxMDU4Ljg4IDAsODg3LjkxIDEwNS45NzcsNzM4LjUzOSAyNjUuMzk4LDY4MS4wOSBjIC02Ljc2OSwtMzUuNDQyIC0xMC40NiwtNzIuMDIgLTEwLjQ2LC0xMDkgQyAyNTQuOTM4LDI1Ni42MjEgNTExLjU2NiwwIDgyNy4wMjcsMCAxMDEyLjIsMCAxMTgzLjk0LDg4Ljk0MTQgMTI5MS4zLDIzOC44MzIgYyA1My40NSwtNDEuOTYxIDExOC44LC02NC45OTIgMTg2LjU2LC02NC45OTIgMTY3LjgzLDAgMzA0LjM4LDEzNi40OTIgMzA0LjM4LDMwNC4zMzIgMCwzNy4wNzggLTYuNjIsNzIuNjI5IC0xOS4wMywxMDYuMTI5IDE1Ny43OCw1Ni44NzkgMjY2LjI3LDIwOS4xMjkgMjY2LjI3LDM3OC4xNCIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDE2IgogICAgICAgICBzdHlsZT0iZmlsbDojZmFjZjA5O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDc5Ny44OTgsMTE1MC45MyA0NDQuMDcyLC0yMDIuNDUgNDQ4LjA1LDM5Mi41OCBjIDYuNDksMzIuMzkgOS42Niw2NC42NyA5LjY2LDk4LjQ2IDAsMjc2LjIzIC0yMjQuNjgsNTAwLjk1IC01MDAuOSw1MDAuOTUgLTE2NS4yNCwwIC0zMTkuMzcsLTgxLjM2IC00MTMuMDUzLC0yMTcuNzkgbCAtNzQuNTI0LC0zODYuNjQgODYuNjk1LC0xODUuMTEiIC8+PHBhdGgKICAgICAgICAgaWQ9InBhdGgxOCIKICAgICAgICAgc3R5bGU9ImZpbGw6IzQ5YzFhZTtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIKICAgICAgICAgZD0ibSAzMzguMjIzLDY4MC42NzIgYyAtNi40ODksLTMyLjM4MyAtOS44MDksLTY1Ljk4MSAtOS44MDksLTk5Ljk3MyAwLC0yNzYuOTI5IDIyNS4zMzYsLTUwMi4yNTc2IDUwMi4zMTMsLTUwMi4yNTc2IDE2Ni41OTMsMCAzMjEuNDczLDgyLjExNzYgNDE1LjAxMywyMTkuOTQ5NiBsIDczLjk3LDM4NS4zNDcgLTk4LjcyLDE4OC42MjEgTCA3NzUuMTU2LDEwNzUuNTcgMzM4LjIyMyw2ODAuNjcyIiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjAiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNlZjI5OWI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMzM1LjQxLDE0NDkuMTggMzA0LjMzMiwtNzEuODYgNjYuNjgsMzQ2LjAyIGMgLTQxLjU4NiwzMS43OCAtOTIuOTMsNDkuMTggLTE0NS43MzEsNDkuMTggLTEzMi4yNSwwIC0yMzkuODEyLC0xMDcuNjEgLTIzOS44MTIsLTIzOS44NyAwLC0yOS4yMSA0Ljg3OSwtNTcuMjIgMTQuNTMxLC04My40NyIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDIyIgogICAgICAgICBzdHlsZT0iZmlsbDojNGNhYmU0O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJNIDMwOC45OTIsMTM3Ni43IEMgMTczLjAyLDEzMzEuNjQgNzguNDgwNSwxMjAxLjMgNzguNDgwNSwxMDU3LjkzIDc4LjQ4MDUsOTE4LjM0IDE2NC44Miw3OTMuNjggMjk0LjQwNiw3NDQuMzUyIGwgNDI2Ljk4MSwzODUuOTM4IC03OC4zOTUsMTY3LjUxIC0zMzQsNzguOSIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICBzdHlsZT0iZmlsbDojODVjZTI2O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDEzMjMuOCwyOTguNDEgYyA0MS43NCwtMzIuMDkgOTIuODMsLTQ5LjU5IDE0NC45OCwtNDkuNTkgMTMyLjI1LDAgMjM5LjgxLDEwNy41NTkgMjM5LjgxLDIzOS44MjEgMCwyOS4xNiAtNC44OCw1Ny4xNjggLTE0LjUzLDgzLjQxOCBsIC0zMDQuMDgsNzEuMTYgLTY2LjE4LC0zNDQuODA5IiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjYiCiAgICAgICAgIHN0eWxlPSJmaWxsOiMzMTc3YTc7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMTM4NS42Nyw3MjIuOTMgMzM0Ljc2LC03OC4zMDEgYyAxMzYuMDIsNDQuOTYxIDIzMC41NiwxNzUuMzUxIDIzMC41NiwzMTguNzYyIDAsMTM5LjMzOSAtODYuNTQsMjYzLjg1OSAtMjE2LjM4LDMxMy4wMzkgbCAtNDM3Ljg0LC0zODMuNTkgODguOSwtMTY5LjkxIiAvPjwvZz48L2c+PC9zdmc+"
/>
</div>
<div
className="euiCard__content"
>
<span
className="euiTitle euiTitle--small euiCard__title"
id="generated-idTitle"
>
<button
aria-describedby=" generated-idDescription"
className="euiCard__titleButton"
onClick={[Function]}
>
Custom Element 3
</button>
</span>
<div
className="euiText euiText--small euiCard__description"
id="generated-idDescription"
>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce lobortis aliquet arcu ut turpis duis.
</p>
</div>
</div>
<div
className="euiCard__footer"
/>
</div>
<div
className="euiFlexGroup euiFlexGroup--gutterExtraSmall euiFlexGroup--justifyContentSpaceBetween euiFlexGroup--directionRow euiFlexGroup--responsive canvasElementCard__controls"
>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<button
aria-label="Edit element"
className="euiButtonIcon euiButtonIcon--primary"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="pencil"
size="m"
/>
</button>
</span>
</div>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<button
aria-label="Delete element"
className="euiButtonIcon euiButtonIcon--danger"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="trash"
size="m"
/>
</button>
</span>
</div>
</div>
</div>
</div>
</div>
`;
exports[`Storyshots components/Elements/ElementGrid with controls and filter 1`] = `
<div
style={
Object {
"width": "1000px",
}
}
>
<div
className="euiFlexGrid euiFlexGrid--gutterLarge euiFlexGrid--fourths euiFlexGrid--responsive"
>
<div
className="euiFlexItem canvasElementCard__wrapper"
>
<div
className="euiCard euiCard--leftAligned euiCard--isClickable canvasElementCard"
onClick={[Function]}
>
<div
className="euiCard__top"
>
<img
alt=""
className="euiCard__image"
src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmlld0JveD0iMCAwIDI3MC42MDAwMSAyNjkuNTQ2NjYiCiAgIGhlaWdodD0iMjY5LjU0NjY2IgogICB3aWR0aD0iMjcwLjYwMDAxIgogICB4bWw6c3BhY2U9InByZXNlcnZlIgogICBpZD0ic3ZnMiIKICAgdmVyc2lvbj0iMS4xIj48bWV0YWRhdGEKICAgICBpZD0ibWV0YWRhdGE4Ij48cmRmOlJERj48Y2M6V29yawogICAgICAgICByZGY6YWJvdXQ9IiI+PGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+PGRjOnR5cGUKICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPjwvY2M6V29yaz48L3JkZjpSREY+PC9tZXRhZGF0YT48ZGVmcwogICAgIGlkPSJkZWZzNiIgLz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMzMzMzMzMywwLDAsLTEuMzMzMzMzMywwLDI2OS41NDY2NykiCiAgICAgaWQ9ImcxMCI+PGcKICAgICAgIHRyYW5zZm9ybT0ic2NhbGUoMC4xKSIKICAgICAgIGlkPSJnMTIiPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMTQiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNmZmZmZmY7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMjAyOS40OCw5NjIuNDQxIGMgMCwxNzAuMDk5IC0xMDUuNDYsMzE4Ljc5OSAtMjY0LjE3LDM3Ni42NTkgNi45OCwzNS44NiAxMC42Miw3MS43MSAxMC42MiwxMDkuMDUgMCwzMTYuMTkgLTI1Ny4yNCw1NzMuNDMgLTU3My40Nyw1NzMuNDMgLTE4NC43MiwwIC0zNTYuNTU4LC04OC41OSAtNDY0LjUzLC0yMzcuODUgLTUzLjA5LDQxLjE4IC0xMTguMjg1LDYzLjc1IC0xODYuMzA1LDYzLjc1IC0xNjcuODM2LDAgLTMwNC4zODMsLTEzNi41NCAtMzA0LjM4MywtMzA0LjM4IDAsLTM3LjA4IDYuNjE3LC03Mi41OCAxOS4wMzEsLTEwNi4wOCBDIDEwOC40ODgsMTM4MC4wOSAwLDEyMjcuODkgMCwxMDU4Ljg4IDAsODg3LjkxIDEwNS45NzcsNzM4LjUzOSAyNjUuMzk4LDY4MS4wOSBjIC02Ljc2OSwtMzUuNDQyIC0xMC40NiwtNzIuMDIgLTEwLjQ2LC0xMDkgQyAyNTQuOTM4LDI1Ni42MjEgNTExLjU2NiwwIDgyNy4wMjcsMCAxMDEyLjIsMCAxMTgzLjk0LDg4Ljk0MTQgMTI5MS4zLDIzOC44MzIgYyA1My40NSwtNDEuOTYxIDExOC44LC02NC45OTIgMTg2LjU2LC02NC45OTIgMTY3LjgzLDAgMzA0LjM4LDEzNi40OTIgMzA0LjM4LDMwNC4zMzIgMCwzNy4wNzggLTYuNjIsNzIuNjI5IC0xOS4wMywxMDYuMTI5IDE1Ny43OCw1Ni44NzkgMjY2LjI3LDIwOS4xMjkgMjY2LjI3LDM3OC4xNCIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDE2IgogICAgICAgICBzdHlsZT0iZmlsbDojZmFjZjA5O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDc5Ny44OTgsMTE1MC45MyA0NDQuMDcyLC0yMDIuNDUgNDQ4LjA1LDM5Mi41OCBjIDYuNDksMzIuMzkgOS42Niw2NC42NyA5LjY2LDk4LjQ2IDAsMjc2LjIzIC0yMjQuNjgsNTAwLjk1IC01MDAuOSw1MDAuOTUgLTE2NS4yNCwwIC0zMTkuMzcsLTgxLjM2IC00MTMuMDUzLC0yMTcuNzkgbCAtNzQuNTI0LC0zODYuNjQgODYuNjk1LC0xODUuMTEiIC8+PHBhdGgKICAgICAgICAgaWQ9InBhdGgxOCIKICAgICAgICAgc3R5bGU9ImZpbGw6IzQ5YzFhZTtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIKICAgICAgICAgZD0ibSAzMzguMjIzLDY4MC42NzIgYyAtNi40ODksLTMyLjM4MyAtOS44MDksLTY1Ljk4MSAtOS44MDksLTk5Ljk3MyAwLC0yNzYuOTI5IDIyNS4zMzYsLTUwMi4yNTc2IDUwMi4zMTMsLTUwMi4yNTc2IDE2Ni41OTMsMCAzMjEuNDczLDgyLjExNzYgNDE1LjAxMywyMTkuOTQ5NiBsIDczLjk3LDM4NS4zNDcgLTk4LjcyLDE4OC42MjEgTCA3NzUuMTU2LDEwNzUuNTcgMzM4LjIyMyw2ODAuNjcyIiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjAiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNlZjI5OWI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMzM1LjQxLDE0NDkuMTggMzA0LjMzMiwtNzEuODYgNjYuNjgsMzQ2LjAyIGMgLTQxLjU4NiwzMS43OCAtOTIuOTMsNDkuMTggLTE0NS43MzEsNDkuMTggLTEzMi4yNSwwIC0yMzkuODEyLC0xMDcuNjEgLTIzOS44MTIsLTIzOS44NyAwLC0yOS4yMSA0Ljg3OSwtNTcuMjIgMTQuNTMxLC04My40NyIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDIyIgogICAgICAgICBzdHlsZT0iZmlsbDojNGNhYmU0O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJNIDMwOC45OTIsMTM3Ni43IEMgMTczLjAyLDEzMzEuNjQgNzguNDgwNSwxMjAxLjMgNzguNDgwNSwxMDU3LjkzIDc4LjQ4MDUsOTE4LjM0IDE2NC44Miw3OTMuNjggMjk0LjQwNiw3NDQuMzUyIGwgNDI2Ljk4MSwzODUuOTM4IC03OC4zOTUsMTY3LjUxIC0zMzQsNzguOSIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICBzdHlsZT0iZmlsbDojODVjZTI2O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDEzMjMuOCwyOTguNDEgYyA0MS43NCwtMzIuMDkgOTIuODMsLTQ5LjU5IDE0NC45OCwtNDkuNTkgMTMyLjI1LDAgMjM5LjgxLDEwNy41NTkgMjM5LjgxLDIzOS44MjEgMCwyOS4xNiAtNC44OCw1Ny4xNjggLTE0LjUzLDgzLjQxOCBsIC0zMDQuMDgsNzEuMTYgLTY2LjE4LC0zNDQuODA5IiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjYiCiAgICAgICAgIHN0eWxlPSJmaWxsOiMzMTc3YTc7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMTM4NS42Nyw3MjIuOTMgMzM0Ljc2LC03OC4zMDEgYyAxMzYuMDIsNDQuOTYxIDIzMC41NiwxNzUuMzUxIDIzMC41NiwzMTguNzYyIDAsMTM5LjMzOSAtODYuNTQsMjYzLjg1OSAtMjE2LjM4LDMxMy4wMzkgbCAtNDM3Ljg0LC0zODMuNTkgODguOSwtMTY5LjkxIiAvPjwvZz48L2c+PC9zdmc+"
/>
</div>
<div
className="euiCard__content"
>
<span
className="euiTitle euiTitle--small euiCard__title"
id="generated-idTitle"
>
<button
aria-describedby=" generated-idDescription"
className="euiCard__titleButton"
onClick={[Function]}
>
Custom Element 3
</button>
</span>
<div
className="euiText euiText--small euiCard__description"
id="generated-idDescription"
>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce lobortis aliquet arcu ut turpis duis.
</p>
</div>
</div>
<div
className="euiCard__footer"
/>
</div>
<div
className="euiFlexGroup euiFlexGroup--gutterExtraSmall euiFlexGroup--justifyContentSpaceBetween euiFlexGroup--directionRow euiFlexGroup--responsive canvasElementCard__controls"
>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<button
aria-label="Edit element"
className="euiButtonIcon euiButtonIcon--primary"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="pencil"
size="m"
/>
</button>
</span>
</div>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<button
aria-label="Delete element"
className="euiButtonIcon euiButtonIcon--danger"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="trash"
size="m"
/>
</button>
</span>
</div>
</div>
</div>
</div>
</div>
`;
exports[`Storyshots components/Elements/ElementGrid with tags filter 1`] = `
<div
style={
Object {
"width": "1000px",
}
}
>
<div
className="euiFlexGrid euiFlexGrid--gutterLarge euiFlexGrid--fourths euiFlexGrid--responsive"
>
<div
className="euiFlexItem canvasElementCard__wrapper"
>
<div
className="euiCard euiCard--leftAligned euiCard--isClickable canvasElementCard"
onClick={[Function]}
>
<div
className="euiCard__top"
>
<img
alt=""
className="euiCard__image"
src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmlld0JveD0iMCAwIDI3MC42MDAwMSAyNjkuNTQ2NjYiCiAgIGhlaWdodD0iMjY5LjU0NjY2IgogICB3aWR0aD0iMjcwLjYwMDAxIgogICB4bWw6c3BhY2U9InByZXNlcnZlIgogICBpZD0ic3ZnMiIKICAgdmVyc2lvbj0iMS4xIj48bWV0YWRhdGEKICAgICBpZD0ibWV0YWRhdGE4Ij48cmRmOlJERj48Y2M6V29yawogICAgICAgICByZGY6YWJvdXQ9IiI+PGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+PGRjOnR5cGUKICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPjwvY2M6V29yaz48L3JkZjpSREY+PC9tZXRhZGF0YT48ZGVmcwogICAgIGlkPSJkZWZzNiIgLz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMzMzMzMzMywwLDAsLTEuMzMzMzMzMywwLDI2OS41NDY2NykiCiAgICAgaWQ9ImcxMCI+PGcKICAgICAgIHRyYW5zZm9ybT0ic2NhbGUoMC4xKSIKICAgICAgIGlkPSJnMTIiPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMTQiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNmZmZmZmY7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMjAyOS40OCw5NjIuNDQxIGMgMCwxNzAuMDk5IC0xMDUuNDYsMzE4Ljc5OSAtMjY0LjE3LDM3Ni42NTkgNi45OCwzNS44NiAxMC42Miw3MS43MSAxMC42MiwxMDkuMDUgMCwzMTYuMTkgLTI1Ny4yNCw1NzMuNDMgLTU3My40Nyw1NzMuNDMgLTE4NC43MiwwIC0zNTYuNTU4LC04OC41OSAtNDY0LjUzLC0yMzcuODUgLTUzLjA5LDQxLjE4IC0xMTguMjg1LDYzLjc1IC0xODYuMzA1LDYzLjc1IC0xNjcuODM2LDAgLTMwNC4zODMsLTEzNi41NCAtMzA0LjM4MywtMzA0LjM4IDAsLTM3LjA4IDYuNjE3LC03Mi41OCAxOS4wMzEsLTEwNi4wOCBDIDEwOC40ODgsMTM4MC4wOSAwLDEyMjcuODkgMCwxMDU4Ljg4IDAsODg3LjkxIDEwNS45NzcsNzM4LjUzOSAyNjUuMzk4LDY4MS4wOSBjIC02Ljc2OSwtMzUuNDQyIC0xMC40NiwtNzIuMDIgLTEwLjQ2LC0xMDkgQyAyNTQuOTM4LDI1Ni42MjEgNTExLjU2NiwwIDgyNy4wMjcsMCAxMDEyLjIsMCAxMTgzLjk0LDg4Ljk0MTQgMTI5MS4zLDIzOC44MzIgYyA1My40NSwtNDEuOTYxIDExOC44LC02NC45OTIgMTg2LjU2LC02NC45OTIgMTY3LjgzLDAgMzA0LjM4LDEzNi40OTIgMzA0LjM4LDMwNC4zMzIgMCwzNy4wNzggLTYuNjIsNzIuNjI5IC0xOS4wMywxMDYuMTI5IDE1Ny43OCw1Ni44NzkgMjY2LjI3LDIwOS4xMjkgMjY2LjI3LDM3OC4xNCIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDE2IgogICAgICAgICBzdHlsZT0iZmlsbDojZmFjZjA5O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDc5Ny44OTgsMTE1MC45MyA0NDQuMDcyLC0yMDIuNDUgNDQ4LjA1LDM5Mi41OCBjIDYuNDksMzIuMzkgOS42Niw2NC42NyA5LjY2LDk4LjQ2IDAsMjc2LjIzIC0yMjQuNjgsNTAwLjk1IC01MDAuOSw1MDAuOTUgLTE2NS4yNCwwIC0zMTkuMzcsLTgxLjM2IC00MTMuMDUzLC0yMTcuNzkgbCAtNzQuNTI0LC0zODYuNjQgODYuNjk1LC0xODUuMTEiIC8+PHBhdGgKICAgICAgICAgaWQ9InBhdGgxOCIKICAgICAgICAgc3R5bGU9ImZpbGw6IzQ5YzFhZTtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIKICAgICAgICAgZD0ibSAzMzguMjIzLDY4MC42NzIgYyAtNi40ODksLTMyLjM4MyAtOS44MDksLTY1Ljk4MSAtOS44MDksLTk5Ljk3MyAwLC0yNzYuOTI5IDIyNS4zMzYsLTUwMi4yNTc2IDUwMi4zMTMsLTUwMi4yNTc2IDE2Ni41OTMsMCAzMjEuNDczLDgyLjExNzYgNDE1LjAxMywyMTkuOTQ5NiBsIDczLjk3LDM4NS4zNDcgLTk4LjcyLDE4OC42MjEgTCA3NzUuMTU2LDEwNzUuNTcgMzM4LjIyMyw2ODAuNjcyIiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjAiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNlZjI5OWI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMzM1LjQxLDE0NDkuMTggMzA0LjMzMiwtNzEuODYgNjYuNjgsMzQ2LjAyIGMgLTQxLjU4NiwzMS43OCAtOTIuOTMsNDkuMTggLTE0NS43MzEsNDkuMTggLTEzMi4yNSwwIC0yMzkuODEyLC0xMDcuNjEgLTIzOS44MTIsLTIzOS44NyAwLC0yOS4yMSA0Ljg3OSwtNTcuMjIgMTQuNTMxLC04My40NyIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDIyIgogICAgICAgICBzdHlsZT0iZmlsbDojNGNhYmU0O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJNIDMwOC45OTIsMTM3Ni43IEMgMTczLjAyLDEzMzEuNjQgNzguNDgwNSwxMjAxLjMgNzguNDgwNSwxMDU3LjkzIDc4LjQ4MDUsOTE4LjM0IDE2NC44Miw3OTMuNjggMjk0LjQwNiw3NDQuMzUyIGwgNDI2Ljk4MSwzODUuOTM4IC03OC4zOTUsMTY3LjUxIC0zMzQsNzguOSIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICBzdHlsZT0iZmlsbDojODVjZTI2O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDEzMjMuOCwyOTguNDEgYyA0MS43NCwtMzIuMDkgOTIuODMsLTQ5LjU5IDE0NC45OCwtNDkuNTkgMTMyLjI1LDAgMjM5LjgxLDEwNy41NTkgMjM5LjgxLDIzOS44MjEgMCwyOS4xNiAtNC44OCw1Ny4xNjggLTE0LjUzLDgzLjQxOCBsIC0zMDQuMDgsNzEuMTYgLTY2LjE4LC0zNDQuODA5IiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjYiCiAgICAgICAgIHN0eWxlPSJmaWxsOiMzMTc3YTc7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMTM4NS42Nyw3MjIuOTMgMzM0Ljc2LC03OC4zMDEgYyAxMzYuMDIsNDQuOTYxIDIzMC41NiwxNzUuMzUxIDIzMC41NiwzMTguNzYyIDAsMTM5LjMzOSAtODYuNTQsMjYzLjg1OSAtMjE2LjM4LDMxMy4wMzkgbCAtNDM3Ljg0LC0zODMuNTkgODguOSwtMTY5LjkxIiAvPjwvZz48L2c+PC9zdmc+"
/>
</div>
<div
className="euiCard__content"
>
<span
className="euiTitle euiTitle--small euiCard__title"
id="generated-idTitle"
>
<button
aria-describedby=" generated-idDescription"
className="euiCard__titleButton"
onClick={[Function]}
>
Image
</button>
</span>
<div
className="euiText euiText--small euiCard__description"
id="generated-idDescription"
>
<p>
A static image
</p>
</div>
</div>
<div
className="euiCard__footer"
>
<span
className="euiBadge euiBadge--iconLeft"
style={
Object {
"backgroundColor": "#666666",
"color": "#fff",
}
}
>
<span
className="euiBadge__content"
>
<span
className="euiBadge__text"
>
graphic
</span>
</span>
</span>
</div>
</div>
</div>
</div>
</div>
`;
exports[`Storyshots components/Elements/ElementGrid with text filter 1`] = `
<div
style={
Object {
"width": "1000px",
}
}
>
<div
className="euiFlexGrid euiFlexGrid--gutterLarge euiFlexGrid--fourths euiFlexGrid--responsive"
>
<div
className="euiFlexItem canvasElementCard__wrapper"
>
<div
className="euiCard euiCard--leftAligned euiCard--isClickable canvasElementCard"
onClick={[Function]}
>
<div
className="euiCard__top"
>
<img
alt=""
className="euiCard__image"
src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmlld0JveD0iMCAwIDI3MC42MDAwMSAyNjkuNTQ2NjYiCiAgIGhlaWdodD0iMjY5LjU0NjY2IgogICB3aWR0aD0iMjcwLjYwMDAxIgogICB4bWw6c3BhY2U9InByZXNlcnZlIgogICBpZD0ic3ZnMiIKICAgdmVyc2lvbj0iMS4xIj48bWV0YWRhdGEKICAgICBpZD0ibWV0YWRhdGE4Ij48cmRmOlJERj48Y2M6V29yawogICAgICAgICByZGY6YWJvdXQ9IiI+PGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+PGRjOnR5cGUKICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPjwvY2M6V29yaz48L3JkZjpSREY+PC9tZXRhZGF0YT48ZGVmcwogICAgIGlkPSJkZWZzNiIgLz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMzMzMzMzMywwLDAsLTEuMzMzMzMzMywwLDI2OS41NDY2NykiCiAgICAgaWQ9ImcxMCI+PGcKICAgICAgIHRyYW5zZm9ybT0ic2NhbGUoMC4xKSIKICAgICAgIGlkPSJnMTIiPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMTQiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNmZmZmZmY7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMjAyOS40OCw5NjIuNDQxIGMgMCwxNzAuMDk5IC0xMDUuNDYsMzE4Ljc5OSAtMjY0LjE3LDM3Ni42NTkgNi45OCwzNS44NiAxMC42Miw3MS43MSAxMC42MiwxMDkuMDUgMCwzMTYuMTkgLTI1Ny4yNCw1NzMuNDMgLTU3My40Nyw1NzMuNDMgLTE4NC43MiwwIC0zNTYuNTU4LC04OC41OSAtNDY0LjUzLC0yMzcuODUgLTUzLjA5LDQxLjE4IC0xMTguMjg1LDYzLjc1IC0xODYuMzA1LDYzLjc1IC0xNjcuODM2LDAgLTMwNC4zODMsLTEzNi41NCAtMzA0LjM4MywtMzA0LjM4IDAsLTM3LjA4IDYuNjE3LC03Mi41OCAxOS4wMzEsLTEwNi4wOCBDIDEwOC40ODgsMTM4MC4wOSAwLDEyMjcuODkgMCwxMDU4Ljg4IDAsODg3LjkxIDEwNS45NzcsNzM4LjUzOSAyNjUuMzk4LDY4MS4wOSBjIC02Ljc2OSwtMzUuNDQyIC0xMC40NiwtNzIuMDIgLTEwLjQ2LC0xMDkgQyAyNTQuOTM4LDI1Ni42MjEgNTExLjU2NiwwIDgyNy4wMjcsMCAxMDEyLjIsMCAxMTgzLjk0LDg4Ljk0MTQgMTI5MS4zLDIzOC44MzIgYyA1My40NSwtNDEuOTYxIDExOC44LC02NC45OTIgMTg2LjU2LC02NC45OTIgMTY3LjgzLDAgMzA0LjM4LDEzNi40OTIgMzA0LjM4LDMwNC4zMzIgMCwzNy4wNzggLTYuNjIsNzIuNjI5IC0xOS4wMywxMDYuMTI5IDE1Ny43OCw1Ni44NzkgMjY2LjI3LDIwOS4xMjkgMjY2LjI3LDM3OC4xNCIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDE2IgogICAgICAgICBzdHlsZT0iZmlsbDojZmFjZjA5O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDc5Ny44OTgsMTE1MC45MyA0NDQuMDcyLC0yMDIuNDUgNDQ4LjA1LDM5Mi41OCBjIDYuNDksMzIuMzkgOS42Niw2NC42NyA5LjY2LDk4LjQ2IDAsMjc2LjIzIC0yMjQuNjgsNTAwLjk1IC01MDAuOSw1MDAuOTUgLTE2NS4yNCwwIC0zMTkuMzcsLTgxLjM2IC00MTMuMDUzLC0yMTcuNzkgbCAtNzQuNTI0LC0zODYuNjQgODYuNjk1LC0xODUuMTEiIC8+PHBhdGgKICAgICAgICAgaWQ9InBhdGgxOCIKICAgICAgICAgc3R5bGU9ImZpbGw6IzQ5YzFhZTtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIKICAgICAgICAgZD0ibSAzMzguMjIzLDY4MC42NzIgYyAtNi40ODksLTMyLjM4MyAtOS44MDksLTY1Ljk4MSAtOS44MDksLTk5Ljk3MyAwLC0yNzYuOTI5IDIyNS4zMzYsLTUwMi4yNTc2IDUwMi4zMTMsLTUwMi4yNTc2IDE2Ni41OTMsMCAzMjEuNDczLDgyLjExNzYgNDE1LjAxMywyMTkuOTQ5NiBsIDczLjk3LDM4NS4zNDcgLTk4LjcyLDE4OC42MjEgTCA3NzUuMTU2LDEwNzUuNTcgMzM4LjIyMyw2ODAuNjcyIiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjAiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNlZjI5OWI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMzM1LjQxLDE0NDkuMTggMzA0LjMzMiwtNzEuODYgNjYuNjgsMzQ2LjAyIGMgLTQxLjU4NiwzMS43OCAtOTIuOTMsNDkuMTggLTE0NS43MzEsNDkuMTggLTEzMi4yNSwwIC0yMzkuODEyLC0xMDcuNjEgLTIzOS44MTIsLTIzOS44NyAwLC0yOS4yMSA0Ljg3OSwtNTcuMjIgMTQuNTMxLC04My40NyIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDIyIgogICAgICAgICBzdHlsZT0iZmlsbDojNGNhYmU0O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJNIDMwOC45OTIsMTM3Ni43IEMgMTczLjAyLDEzMzEuNjQgNzguNDgwNSwxMjAxLjMgNzguNDgwNSwxMDU3LjkzIDc4LjQ4MDUsOTE4LjM0IDE2NC44Miw3OTMuNjggMjk0LjQwNiw3NDQuMzUyIGwgNDI2Ljk4MSwzODUuOTM4IC03OC4zOTUsMTY3LjUxIC0zMzQsNzguOSIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICBzdHlsZT0iZmlsbDojODVjZTI2O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDEzMjMuOCwyOTguNDEgYyA0MS43NCwtMzIuMDkgOTIuODMsLTQ5LjU5IDE0NC45OCwtNDkuNTkgMTMyLjI1LDAgMjM5LjgxLDEwNy41NTkgMjM5LjgxLDIzOS44MjEgMCwyOS4xNiAtNC44OCw1Ny4xNjggLTE0LjUzLDgzLjQxOCBsIC0zMDQuMDgsNzEuMTYgLTY2LjE4LC0zNDQuODA5IiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjYiCiAgICAgICAgIHN0eWxlPSJmaWxsOiMzMTc3YTc7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMTM4NS42Nyw3MjIuOTMgMzM0Ljc2LC03OC4zMDEgYyAxMzYuMDIsNDQuOTYxIDIzMC41NiwxNzUuMzUxIDIzMC41NiwzMTguNzYyIDAsMTM5LjMzOSAtODYuNTQsMjYzLjg1OSAtMjE2LjM4LDMxMy4wMzkgbCAtNDM3Ljg0LC0zODMuNTkgODguOSwtMTY5LjkxIiAvPjwvZz48L2c+PC9zdmc+"
/>
</div>
<div
className="euiCard__content"
>
<span
className="euiTitle euiTitle--small euiCard__title"
id="generated-idTitle"
>
<button
aria-describedby=" generated-idDescription"
className="euiCard__titleButton"
onClick={[Function]}
>
Data table
</button>
</span>
<div
className="euiText euiText--small euiCard__description"
id="generated-idDescription"
>
<p>
A scrollable grid for displaying data in a tabular format
</p>
</div>
</div>
<div
className="euiCard__footer"
>
<span
className="euiBadge euiBadge--iconLeft"
style={
Object {
"backgroundColor": "#666666",
"color": "#fff",
}
}
>
<span
className="euiBadge__content"
>
<span
className="euiBadge__text"
>
text
</span>
</span>
</span>
</div>
</div>
</div>
</div>
</div>
`;
exports[`Storyshots components/Elements/ElementGrid without controls 1`] = `
<div
style={
Object {
"width": "1000px",
}
}
>
<div
className="euiFlexGrid euiFlexGrid--gutterLarge euiFlexGrid--fourths euiFlexGrid--responsive"
>
<div
className="euiFlexItem canvasElementCard__wrapper"
>
<div
className="euiCard euiCard--leftAligned euiCard--isClickable canvasElementCard"
onClick={[Function]}
>
<div
className="euiCard__top"
>
<img
alt=""
className="euiCard__image"
src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmlld0JveD0iMCAwIDI3MC42MDAwMSAyNjkuNTQ2NjYiCiAgIGhlaWdodD0iMjY5LjU0NjY2IgogICB3aWR0aD0iMjcwLjYwMDAxIgogICB4bWw6c3BhY2U9InByZXNlcnZlIgogICBpZD0ic3ZnMiIKICAgdmVyc2lvbj0iMS4xIj48bWV0YWRhdGEKICAgICBpZD0ibWV0YWRhdGE4Ij48cmRmOlJERj48Y2M6V29yawogICAgICAgICByZGY6YWJvdXQ9IiI+PGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+PGRjOnR5cGUKICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPjwvY2M6V29yaz48L3JkZjpSREY+PC9tZXRhZGF0YT48ZGVmcwogICAgIGlkPSJkZWZzNiIgLz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMzMzMzMzMywwLDAsLTEuMzMzMzMzMywwLDI2OS41NDY2NykiCiAgICAgaWQ9ImcxMCI+PGcKICAgICAgIHRyYW5zZm9ybT0ic2NhbGUoMC4xKSIKICAgICAgIGlkPSJnMTIiPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMTQiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNmZmZmZmY7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMjAyOS40OCw5NjIuNDQxIGMgMCwxNzAuMDk5IC0xMDUuNDYsMzE4Ljc5OSAtMjY0LjE3LDM3Ni42NTkgNi45OCwzNS44NiAxMC42Miw3MS43MSAxMC42MiwxMDkuMDUgMCwzMTYuMTkgLTI1Ny4yNCw1NzMuNDMgLTU3My40Nyw1NzMuNDMgLTE4NC43MiwwIC0zNTYuNTU4LC04OC41OSAtNDY0LjUzLC0yMzcuODUgLTUzLjA5LDQxLjE4IC0xMTguMjg1LDYzLjc1IC0xODYuMzA1LDYzLjc1IC0xNjcuODM2LDAgLTMwNC4zODMsLTEzNi41NCAtMzA0LjM4MywtMzA0LjM4IDAsLTM3LjA4IDYuNjE3LC03Mi41OCAxOS4wMzEsLTEwNi4wOCBDIDEwOC40ODgsMTM4MC4wOSAwLDEyMjcuODkgMCwxMDU4Ljg4IDAsODg3LjkxIDEwNS45NzcsNzM4LjUzOSAyNjUuMzk4LDY4MS4wOSBjIC02Ljc2OSwtMzUuNDQyIC0xMC40NiwtNzIuMDIgLTEwLjQ2LC0xMDkgQyAyNTQuOTM4LDI1Ni42MjEgNTExLjU2NiwwIDgyNy4wMjcsMCAxMDEyLjIsMCAxMTgzLjk0LDg4Ljk0MTQgMTI5MS4zLDIzOC44MzIgYyA1My40NSwtNDEuOTYxIDExOC44LC02NC45OTIgMTg2LjU2LC02NC45OTIgMTY3LjgzLDAgMzA0LjM4LDEzNi40OTIgMzA0LjM4LDMwNC4zMzIgMCwzNy4wNzggLTYuNjIsNzIuNjI5IC0xOS4wMywxMDYuMTI5IDE1Ny43OCw1Ni44NzkgMjY2LjI3LDIwOS4xMjkgMjY2LjI3LDM3OC4xNCIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDE2IgogICAgICAgICBzdHlsZT0iZmlsbDojZmFjZjA5O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDc5Ny44OTgsMTE1MC45MyA0NDQuMDcyLC0yMDIuNDUgNDQ4LjA1LDM5Mi41OCBjIDYuNDksMzIuMzkgOS42Niw2NC42NyA5LjY2LDk4LjQ2IDAsMjc2LjIzIC0yMjQuNjgsNTAwLjk1IC01MDAuOSw1MDAuOTUgLTE2NS4yNCwwIC0zMTkuMzcsLTgxLjM2IC00MTMuMDUzLC0yMTcuNzkgbCAtNzQuNTI0LC0zODYuNjQgODYuNjk1LC0xODUuMTEiIC8+PHBhdGgKICAgICAgICAgaWQ9InBhdGgxOCIKICAgICAgICAgc3R5bGU9ImZpbGw6IzQ5YzFhZTtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIKICAgICAgICAgZD0ibSAzMzguMjIzLDY4MC42NzIgYyAtNi40ODksLTMyLjM4MyAtOS44MDksLTY1Ljk4MSAtOS44MDksLTk5Ljk3MyAwLC0yNzYuOTI5IDIyNS4zMzYsLTUwMi4yNTc2IDUwMi4zMTMsLTUwMi4yNTc2IDE2Ni41OTMsMCAzMjEuNDczLDgyLjExNzYgNDE1LjAxMywyMTkuOTQ5NiBsIDczLjk3LDM4NS4zNDcgLTk4LjcyLDE4OC42MjEgTCA3NzUuMTU2LDEwNzUuNTcgMzM4LjIyMyw2ODAuNjcyIiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjAiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNlZjI5OWI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMzM1LjQxLDE0NDkuMTggMzA0LjMzMiwtNzEuODYgNjYuNjgsMzQ2LjAyIGMgLTQxLjU4NiwzMS43OCAtOTIuOTMsNDkuMTggLTE0NS43MzEsNDkuMTggLTEzMi4yNSwwIC0yMzkuODEyLC0xMDcuNjEgLTIzOS44MTIsLTIzOS44NyAwLC0yOS4yMSA0Ljg3OSwtNTcuMjIgMTQuNTMxLC04My40NyIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDIyIgogICAgICAgICBzdHlsZT0iZmlsbDojNGNhYmU0O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJNIDMwOC45OTIsMTM3Ni43IEMgMTczLjAyLDEzMzEuNjQgNzguNDgwNSwxMjAxLjMgNzguNDgwNSwxMDU3LjkzIDc4LjQ4MDUsOTE4LjM0IDE2NC44Miw3OTMuNjggMjk0LjQwNiw3NDQuMzUyIGwgNDI2Ljk4MSwzODUuOTM4IC03OC4zOTUsMTY3LjUxIC0zMzQsNzguOSIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICBzdHlsZT0iZmlsbDojODVjZTI2O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDEzMjMuOCwyOTguNDEgYyA0MS43NCwtMzIuMDkgOTIuODMsLTQ5LjU5IDE0NC45OCwtNDkuNTkgMTMyLjI1LDAgMjM5LjgxLDEwNy41NTkgMjM5LjgxLDIzOS44MjEgMCwyOS4xNiAtNC44OCw1Ny4xNjggLTE0LjUzLDgzLjQxOCBsIC0zMDQuMDgsNzEuMTYgLTY2LjE4LC0zNDQuODA5IiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjYiCiAgICAgICAgIHN0eWxlPSJmaWxsOiMzMTc3YTc7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMTM4NS42Nyw3MjIuOTMgMzM0Ljc2LC03OC4zMDEgYyAxMzYuMDIsNDQuOTYxIDIzMC41NiwxNzUuMzUxIDIzMC41NiwzMTguNzYyIDAsMTM5LjMzOSAtODYuNTQsMjYzLjg1OSAtMjE2LjM4LDMxMy4wMzkgbCAtNDM3Ljg0LC0zODMuNTkgODguOSwtMTY5LjkxIiAvPjwvZz48L2c+PC9zdmc+"
/>
</div>
<div
className="euiCard__content"
>
<span
className="euiTitle euiTitle--small euiCard__title"
id="generated-idTitle"
>
<button
aria-describedby=" generated-idDescription"
className="euiCard__titleButton"
onClick={[Function]}
>
Area chart
</button>
</span>
<div
className="euiText euiText--small euiCard__description"
id="generated-idDescription"
>
<p>
A line chart with a filled body
</p>
</div>
</div>
<div
className="euiCard__footer"
>
<span
className="euiBadge euiBadge--iconLeft"
style={
Object {
"backgroundColor": "#666666",
"color": "#fff",
}
}
>
<span
className="euiBadge__content"
>
<span
className="euiBadge__text"
>
chart
</span>
</span>
</span>
</div>
</div>
</div>
<div
className="euiFlexItem canvasElementCard__wrapper"
>
<div
className="euiCard euiCard--leftAligned euiCard--isClickable canvasElementCard"
onClick={[Function]}
>
<div
className="euiCard__top"
>
<img
alt=""
className="euiCard__image"
src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmlld0JveD0iMCAwIDI3MC42MDAwMSAyNjkuNTQ2NjYiCiAgIGhlaWdodD0iMjY5LjU0NjY2IgogICB3aWR0aD0iMjcwLjYwMDAxIgogICB4bWw6c3BhY2U9InByZXNlcnZlIgogICBpZD0ic3ZnMiIKICAgdmVyc2lvbj0iMS4xIj48bWV0YWRhdGEKICAgICBpZD0ibWV0YWRhdGE4Ij48cmRmOlJERj48Y2M6V29yawogICAgICAgICByZGY6YWJvdXQ9IiI+PGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+PGRjOnR5cGUKICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPjwvY2M6V29yaz48L3JkZjpSREY+PC9tZXRhZGF0YT48ZGVmcwogICAgIGlkPSJkZWZzNiIgLz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMzMzMzMzMywwLDAsLTEuMzMzMzMzMywwLDI2OS41NDY2NykiCiAgICAgaWQ9ImcxMCI+PGcKICAgICAgIHRyYW5zZm9ybT0ic2NhbGUoMC4xKSIKICAgICAgIGlkPSJnMTIiPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMTQiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNmZmZmZmY7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMjAyOS40OCw5NjIuNDQxIGMgMCwxNzAuMDk5IC0xMDUuNDYsMzE4Ljc5OSAtMjY0LjE3LDM3Ni42NTkgNi45OCwzNS44NiAxMC42Miw3MS43MSAxMC42MiwxMDkuMDUgMCwzMTYuMTkgLTI1Ny4yNCw1NzMuNDMgLTU3My40Nyw1NzMuNDMgLTE4NC43MiwwIC0zNTYuNTU4LC04OC41OSAtNDY0LjUzLC0yMzcuODUgLTUzLjA5LDQxLjE4IC0xMTguMjg1LDYzLjc1IC0xODYuMzA1LDYzLjc1IC0xNjcuODM2LDAgLTMwNC4zODMsLTEzNi41NCAtMzA0LjM4MywtMzA0LjM4IDAsLTM3LjA4IDYuNjE3LC03Mi41OCAxOS4wMzEsLTEwNi4wOCBDIDEwOC40ODgsMTM4MC4wOSAwLDEyMjcuODkgMCwxMDU4Ljg4IDAsODg3LjkxIDEwNS45NzcsNzM4LjUzOSAyNjUuMzk4LDY4MS4wOSBjIC02Ljc2OSwtMzUuNDQyIC0xMC40NiwtNzIuMDIgLTEwLjQ2LC0xMDkgQyAyNTQuOTM4LDI1Ni42MjEgNTExLjU2NiwwIDgyNy4wMjcsMCAxMDEyLjIsMCAxMTgzLjk0LDg4Ljk0MTQgMTI5MS4zLDIzOC44MzIgYyA1My40NSwtNDEuOTYxIDExOC44LC02NC45OTIgMTg2LjU2LC02NC45OTIgMTY3LjgzLDAgMzA0LjM4LDEzNi40OTIgMzA0LjM4LDMwNC4zMzIgMCwzNy4wNzggLTYuNjIsNzIuNjI5IC0xOS4wMywxMDYuMTI5IDE1Ny43OCw1Ni44NzkgMjY2LjI3LDIwOS4xMjkgMjY2LjI3LDM3OC4xNCIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDE2IgogICAgICAgICBzdHlsZT0iZmlsbDojZmFjZjA5O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDc5Ny44OTgsMTE1MC45MyA0NDQuMDcyLC0yMDIuNDUgNDQ4LjA1LDM5Mi41OCBjIDYuNDksMzIuMzkgOS42Niw2NC42NyA5LjY2LDk4LjQ2IDAsMjc2LjIzIC0yMjQuNjgsNTAwLjk1IC01MDAuOSw1MDAuOTUgLTE2NS4yNCwwIC0zMTkuMzcsLTgxLjM2IC00MTMuMDUzLC0yMTcuNzkgbCAtNzQuNTI0LC0zODYuNjQgODYuNjk1LC0xODUuMTEiIC8+PHBhdGgKICAgICAgICAgaWQ9InBhdGgxOCIKICAgICAgICAgc3R5bGU9ImZpbGw6IzQ5YzFhZTtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIKICAgICAgICAgZD0ibSAzMzguMjIzLDY4MC42NzIgYyAtNi40ODksLTMyLjM4MyAtOS44MDksLTY1Ljk4MSAtOS44MDksLTk5Ljk3MyAwLC0yNzYuOTI5IDIyNS4zMzYsLTUwMi4yNTc2IDUwMi4zMTMsLTUwMi4yNTc2IDE2Ni41OTMsMCAzMjEuNDczLDgyLjExNzYgNDE1LjAxMywyMTkuOTQ5NiBsIDczLjk3LDM4NS4zNDcgLTk4LjcyLDE4OC42MjEgTCA3NzUuMTU2LDEwNzUuNTcgMzM4LjIyMyw2ODAuNjcyIiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjAiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNlZjI5OWI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMzM1LjQxLDE0NDkuMTggMzA0LjMzMiwtNzEuODYgNjYuNjgsMzQ2LjAyIGMgLTQxLjU4NiwzMS43OCAtOTIuOTMsNDkuMTggLTE0NS43MzEsNDkuMTggLTEzMi4yNSwwIC0yMzkuODEyLC0xMDcuNjEgLTIzOS44MTIsLTIzOS44NyAwLC0yOS4yMSA0Ljg3OSwtNTcuMjIgMTQuNTMxLC04My40NyIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDIyIgogICAgICAgICBzdHlsZT0iZmlsbDojNGNhYmU0O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJNIDMwOC45OTIsMTM3Ni43IEMgMTczLjAyLDEzMzEuNjQgNzguNDgwNSwxMjAxLjMgNzguNDgwNSwxMDU3LjkzIDc4LjQ4MDUsOTE4LjM0IDE2NC44Miw3OTMuNjggMjk0LjQwNiw3NDQuMzUyIGwgNDI2Ljk4MSwzODUuOTM4IC03OC4zOTUsMTY3LjUxIC0zMzQsNzguOSIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICBzdHlsZT0iZmlsbDojODVjZTI2O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDEzMjMuOCwyOTguNDEgYyA0MS43NCwtMzIuMDkgOTIuODMsLTQ5LjU5IDE0NC45OCwtNDkuNTkgMTMyLjI1LDAgMjM5LjgxLDEwNy41NTkgMjM5LjgxLDIzOS44MjEgMCwyOS4xNiAtNC44OCw1Ny4xNjggLTE0LjUzLDgzLjQxOCBsIC0zMDQuMDgsNzEuMTYgLTY2LjE4LC0zNDQuODA5IiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjYiCiAgICAgICAgIHN0eWxlPSJmaWxsOiMzMTc3YTc7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMTM4NS42Nyw3MjIuOTMgMzM0Ljc2LC03OC4zMDEgYyAxMzYuMDIsNDQuOTYxIDIzMC41NiwxNzUuMzUxIDIzMC41NiwzMTguNzYyIDAsMTM5LjMzOSAtODYuNTQsMjYzLjg1OSAtMjE2LjM4LDMxMy4wMzkgbCAtNDM3Ljg0LC0zODMuNTkgODguOSwtMTY5LjkxIiAvPjwvZz48L2c+PC9zdmc+"
/>
</div>
<div
className="euiCard__content"
>
<span
className="euiTitle euiTitle--small euiCard__title"
id="generated-idTitle"
>
<button
aria-describedby=" generated-idDescription"
className="euiCard__titleButton"
onClick={[Function]}
>
Image
</button>
</span>
<div
className="euiText euiText--small euiCard__description"
id="generated-idDescription"
>
<p>
A static image
</p>
</div>
</div>
<div
className="euiCard__footer"
>
<span
className="euiBadge euiBadge--iconLeft"
style={
Object {
"backgroundColor": "#666666",
"color": "#fff",
}
}
>
<span
className="euiBadge__content"
>
<span
className="euiBadge__text"
>
graphic
</span>
</span>
</span>
</div>
</div>
</div>
<div
className="euiFlexItem canvasElementCard__wrapper"
>
<div
className="euiCard euiCard--leftAligned euiCard--isClickable canvasElementCard"
onClick={[Function]}
>
<div
className="euiCard__top"
>
<img
alt=""
className="euiCard__image"
src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmlld0JveD0iMCAwIDI3MC42MDAwMSAyNjkuNTQ2NjYiCiAgIGhlaWdodD0iMjY5LjU0NjY2IgogICB3aWR0aD0iMjcwLjYwMDAxIgogICB4bWw6c3BhY2U9InByZXNlcnZlIgogICBpZD0ic3ZnMiIKICAgdmVyc2lvbj0iMS4xIj48bWV0YWRhdGEKICAgICBpZD0ibWV0YWRhdGE4Ij48cmRmOlJERj48Y2M6V29yawogICAgICAgICByZGY6YWJvdXQ9IiI+PGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+PGRjOnR5cGUKICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPjwvY2M6V29yaz48L3JkZjpSREY+PC9tZXRhZGF0YT48ZGVmcwogICAgIGlkPSJkZWZzNiIgLz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMzMzMzMzMywwLDAsLTEuMzMzMzMzMywwLDI2OS41NDY2NykiCiAgICAgaWQ9ImcxMCI+PGcKICAgICAgIHRyYW5zZm9ybT0ic2NhbGUoMC4xKSIKICAgICAgIGlkPSJnMTIiPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMTQiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNmZmZmZmY7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMjAyOS40OCw5NjIuNDQxIGMgMCwxNzAuMDk5IC0xMDUuNDYsMzE4Ljc5OSAtMjY0LjE3LDM3Ni42NTkgNi45OCwzNS44NiAxMC42Miw3MS43MSAxMC42MiwxMDkuMDUgMCwzMTYuMTkgLTI1Ny4yNCw1NzMuNDMgLTU3My40Nyw1NzMuNDMgLTE4NC43MiwwIC0zNTYuNTU4LC04OC41OSAtNDY0LjUzLC0yMzcuODUgLTUzLjA5LDQxLjE4IC0xMTguMjg1LDYzLjc1IC0xODYuMzA1LDYzLjc1IC0xNjcuODM2LDAgLTMwNC4zODMsLTEzNi41NCAtMzA0LjM4MywtMzA0LjM4IDAsLTM3LjA4IDYuNjE3LC03Mi41OCAxOS4wMzEsLTEwNi4wOCBDIDEwOC40ODgsMTM4MC4wOSAwLDEyMjcuODkgMCwxMDU4Ljg4IDAsODg3LjkxIDEwNS45NzcsNzM4LjUzOSAyNjUuMzk4LDY4MS4wOSBjIC02Ljc2OSwtMzUuNDQyIC0xMC40NiwtNzIuMDIgLTEwLjQ2LC0xMDkgQyAyNTQuOTM4LDI1Ni42MjEgNTExLjU2NiwwIDgyNy4wMjcsMCAxMDEyLjIsMCAxMTgzLjk0LDg4Ljk0MTQgMTI5MS4zLDIzOC44MzIgYyA1My40NSwtNDEuOTYxIDExOC44LC02NC45OTIgMTg2LjU2LC02NC45OTIgMTY3LjgzLDAgMzA0LjM4LDEzNi40OTIgMzA0LjM4LDMwNC4zMzIgMCwzNy4wNzggLTYuNjIsNzIuNjI5IC0xOS4wMywxMDYuMTI5IDE1Ny43OCw1Ni44NzkgMjY2LjI3LDIwOS4xMjkgMjY2LjI3LDM3OC4xNCIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDE2IgogICAgICAgICBzdHlsZT0iZmlsbDojZmFjZjA5O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDc5Ny44OTgsMTE1MC45MyA0NDQuMDcyLC0yMDIuNDUgNDQ4LjA1LDM5Mi41OCBjIDYuNDksMzIuMzkgOS42Niw2NC42NyA5LjY2LDk4LjQ2IDAsMjc2LjIzIC0yMjQuNjgsNTAwLjk1IC01MDAuOSw1MDAuOTUgLTE2NS4yNCwwIC0zMTkuMzcsLTgxLjM2IC00MTMuMDUzLC0yMTcuNzkgbCAtNzQuNTI0LC0zODYuNjQgODYuNjk1LC0xODUuMTEiIC8+PHBhdGgKICAgICAgICAgaWQ9InBhdGgxOCIKICAgICAgICAgc3R5bGU9ImZpbGw6IzQ5YzFhZTtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIKICAgICAgICAgZD0ibSAzMzguMjIzLDY4MC42NzIgYyAtNi40ODksLTMyLjM4MyAtOS44MDksLTY1Ljk4MSAtOS44MDksLTk5Ljk3MyAwLC0yNzYuOTI5IDIyNS4zMzYsLTUwMi4yNTc2IDUwMi4zMTMsLTUwMi4yNTc2IDE2Ni41OTMsMCAzMjEuNDczLDgyLjExNzYgNDE1LjAxMywyMTkuOTQ5NiBsIDczLjk3LDM4NS4zNDcgLTk4LjcyLDE4OC42MjEgTCA3NzUuMTU2LDEwNzUuNTcgMzM4LjIyMyw2ODAuNjcyIiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjAiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNlZjI5OWI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMzM1LjQxLDE0NDkuMTggMzA0LjMzMiwtNzEuODYgNjYuNjgsMzQ2LjAyIGMgLTQxLjU4NiwzMS43OCAtOTIuOTMsNDkuMTggLTE0NS43MzEsNDkuMTggLTEzMi4yNSwwIC0yMzkuODEyLC0xMDcuNjEgLTIzOS44MTIsLTIzOS44NyAwLC0yOS4yMSA0Ljg3OSwtNTcuMjIgMTQuNTMxLC04My40NyIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDIyIgogICAgICAgICBzdHlsZT0iZmlsbDojNGNhYmU0O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJNIDMwOC45OTIsMTM3Ni43IEMgMTczLjAyLDEzMzEuNjQgNzguNDgwNSwxMjAxLjMgNzguNDgwNSwxMDU3LjkzIDc4LjQ4MDUsOTE4LjM0IDE2NC44Miw3OTMuNjggMjk0LjQwNiw3NDQuMzUyIGwgNDI2Ljk4MSwzODUuOTM4IC03OC4zOTUsMTY3LjUxIC0zMzQsNzguOSIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICBzdHlsZT0iZmlsbDojODVjZTI2O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDEzMjMuOCwyOTguNDEgYyA0MS43NCwtMzIuMDkgOTIuODMsLTQ5LjU5IDE0NC45OCwtNDkuNTkgMTMyLjI1LDAgMjM5LjgxLDEwNy41NTkgMjM5LjgxLDIzOS44MjEgMCwyOS4xNiAtNC44OCw1Ny4xNjggLTE0LjUzLDgzLjQxOCBsIC0zMDQuMDgsNzEuMTYgLTY2LjE4LC0zNDQuODA5IiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjYiCiAgICAgICAgIHN0eWxlPSJmaWxsOiMzMTc3YTc7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMTM4NS42Nyw3MjIuOTMgMzM0Ljc2LC03OC4zMDEgYyAxMzYuMDIsNDQuOTYxIDIzMC41NiwxNzUuMzUxIDIzMC41NiwzMTguNzYyIDAsMTM5LjMzOSAtODYuNTQsMjYzLjg1OSAtMjE2LjM4LDMxMy4wMzkgbCAtNDM3Ljg0LC0zODMuNTkgODguOSwtMTY5LjkxIiAvPjwvZz48L2c+PC9zdmc+"
/>
</div>
<div
className="euiCard__content"
>
<span
className="euiTitle euiTitle--small euiCard__title"
id="generated-idTitle"
>
<button
aria-describedby=" generated-idDescription"
className="euiCard__titleButton"
onClick={[Function]}
>
Data table
</button>
</span>
<div
className="euiText euiText--small euiCard__description"
id="generated-idDescription"
>
<p>
A scrollable grid for displaying data in a tabular format
</p>
</div>
</div>
<div
className="euiCard__footer"
>
<span
className="euiBadge euiBadge--iconLeft"
style={
Object {
"backgroundColor": "#666666",
"color": "#fff",
}
}
>
<span
className="euiBadge__content"
>
<span
className="euiBadge__text"
>
text
</span>
</span>
</span>
</div>
</div>
</div>
</div>
</div>
`;

View file

@ -1,110 +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;
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
import PropTypes from 'prop-types';
import { map } from 'lodash';
import { EuiFlexItem, EuiFlexGrid } from '@elastic/eui';
import { ElementControls } from './element_controls';
import { CustomElement, ElementSpec } from '../../../types';
import { ElementCard } from '../element_card';
export interface Props {
/**
* list of elements to generate cards for
*/
elements: Array<ElementSpec | CustomElement>;
/**
* text to filter out cards
*/
filterText: string;
/**
* tags to filter out cards
*/
filterTags: string[];
/**
* indicate whether or not edit/delete controls should be displayed
*/
showControls: boolean;
/**
* handler invoked when clicking a card
*/
handleClick: (element: ElementSpec | CustomElement) => void;
/**
* click handler for the edit button
*/
onEdit?: (element: ElementSpec | CustomElement) => void;
/**
* click handler for the delete button
*/
onDelete?: (element: ElementSpec | CustomElement) => void;
}
export const ElementGrid = ({
elements,
filterText,
filterTags,
handleClick,
onEdit,
onDelete,
showControls,
}: Props) => {
filterText = filterText.toLowerCase();
return (
<EuiFlexGrid gutterSize="l" columns={4}>
{map(elements, (element: ElementSpec | CustomElement, index) => {
const { name, displayName = '', help = '', image, tags = [] } = element;
const whenClicked = () => handleClick(element);
let textMatch = false;
let tagsMatch = false;
if (
!filterText.length ||
name.toLowerCase().includes(filterText) ||
displayName.toLowerCase().includes(filterText) ||
help.toLowerCase().includes(filterText)
) {
textMatch = true;
}
if (!filterTags.length || filterTags.every(tag => tags.includes(tag))) {
tagsMatch = true;
}
if (!textMatch || !tagsMatch) {
return null;
}
return (
<EuiFlexItem key={index} className="canvasElementCard__wrapper">
<ElementCard
title={displayName || name}
description={help}
image={image}
tags={tags}
onClick={whenClicked}
/>
{showControls && onEdit && onDelete && (
<ElementControls onEdit={() => onEdit(element)} onDelete={() => onDelete(element)} />
)}
</EuiFlexItem>
);
})}
</EuiFlexGrid>
);
};
ElementGrid.propTypes = {
elements: PropTypes.array.isRequired,
handleClick: PropTypes.func.isRequired,
showControls: PropTypes.bool,
};
ElementGrid.defaultProps = {
showControls: false,
filterTags: [],
filterText: '',
};

View file

@ -1,224 +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;
* you may not use this file except in compliance with the Elastic License.
*/
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import {
EuiModalBody,
EuiTabbedContent,
EuiEmptyPrompt,
EuiSearchBar,
EuiSpacer,
EuiOverlayMask,
} from '@elastic/eui';
import { map, sortBy } from 'lodash';
import { ConfirmModal } from '../confirm_modal/confirm_modal';
import { CustomElementModal } from '../custom_element_modal';
import { getTagsFilter } from '../../lib/get_tags_filter';
import { extractSearch } from '../../lib/extract_search';
import { ComponentStrings } from '../../../i18n';
import { ElementGrid } from './element_grid';
const { ElementTypes: strings } = ComponentStrings;
const tagType = 'badge';
export class ElementTypes extends Component {
static propTypes = {
addCustomElement: PropTypes.func.isRequired,
addElement: PropTypes.func.isRequired,
customElements: PropTypes.array.isRequired,
elements: PropTypes.object,
filterTags: PropTypes.arrayOf(PropTypes.string).isRequired,
findCustomElements: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired,
removeCustomElement: PropTypes.func.isRequired,
search: PropTypes.string,
setCustomElements: PropTypes.func.isRequired,
setSearch: PropTypes.func.isRequired,
setFilterTags: PropTypes.func.isRequired,
updateCustomElement: PropTypes.func.isRequired,
};
state = {
elementToDelete: null,
elementToEdit: null,
};
componentDidMount() {
// fetch custom elements
this.props.findCustomElements();
}
_showEditModal = elementToEdit => this.setState({ elementToEdit });
_hideEditModal = () => this.setState({ elementToEdit: null });
_handleEdit = async (name, description, image) => {
const { updateCustomElement } = this.props;
const { elementToEdit } = this.state;
await updateCustomElement(elementToEdit.id, name, description, image);
this._hideEditModal();
};
_showDeleteModal = elementToDelete => this.setState({ elementToDelete });
_hideDeleteModal = () => this.setState({ elementToDelete: null });
_handleDelete = async () => {
const { removeCustomElement } = this.props;
const { elementToDelete } = this.state;
await removeCustomElement(elementToDelete.id);
this._hideDeleteModal();
};
_renderEditModal = () => {
const { elementToEdit } = this.state;
if (!elementToEdit) {
return null;
}
return (
<EuiOverlayMask>
<CustomElementModal
title={strings.getEditElementTitle()}
name={elementToEdit.displayName}
description={elementToEdit.help}
image={elementToEdit.image}
onSave={this._handleEdit}
onCancel={this._hideEditModal}
/>
</EuiOverlayMask>
);
};
_renderDeleteModal = () => {
const { elementToDelete } = this.state;
if (!elementToDelete) {
return null;
}
return (
<ConfirmModal
isOpen
title={strings.getDeleteElementTitle(elementToDelete.displayName)}
message={strings.getDeleteElementDescription()}
confirmButtonText={strings.getDeleteButtonLabel()}
cancelButtonText={strings.getCancelButtonLabel()}
onConfirm={this._handleDelete}
onCancel={this._hideDeleteModal}
/>
);
};
_sortElements = elements =>
sortBy(
map(elements, (element, name) => ({ name, ...element })),
'displayName'
);
render() {
const {
search,
setSearch,
addElement,
addCustomElement,
filterTags,
setFilterTags,
} = this.props;
let { elements, customElements } = this.props;
elements = this._sortElements(elements);
let customElementContent = (
<EuiEmptyPrompt
iconType="vector"
title={<h2>{strings.getAddNewElementTitle()}</h2>}
body={<p>{strings.getAddNewElementDescription()}</p>}
titleSize="s"
/>
);
if (customElements.length) {
customElements = this._sortElements(customElements);
customElementContent = (
<ElementGrid
elements={customElements}
filter={search}
handleClick={addCustomElement}
showControls
onEdit={this._showEditModal}
onDelete={this._showDeleteModal}
/>
);
}
const filters = [getTagsFilter(tagType)];
const onSearch = ({ queryText }) => {
const { searchTerm, filterTags } = extractSearch(queryText);
setSearch(searchTerm);
setFilterTags(filterTags);
};
const tabs = [
{
id: 'elements',
name: strings.getElementsTitle(),
content: (
<div className="canvasElements__filter">
<EuiSpacer />
<EuiSearchBar
defaultQuery={search}
box={{
placeholder: strings.getFindElementPlaceholder(),
incremental: true,
}}
filters={filters}
onChange={onSearch}
/>
<EuiSpacer />
<ElementGrid
elements={elements}
filterText={search}
filterTags={filterTags}
handleClick={addElement}
/>
</div>
),
},
{
id: 'customElements',
name: strings.getMyElementsTitle(),
content: (
<Fragment>
<EuiSpacer />
<EuiSearchBar
defaultQuery={search}
box={{
placeholder: strings.getFindElementPlaceholder(),
incremental: true,
}}
onChange={onSearch}
/>
<EuiSpacer />
{customElementContent}
</Fragment>
),
},
];
return (
<Fragment>
<EuiModalBody style={{ paddingRight: '1px' }}>
<EuiTabbedContent tabs={tabs} initialSelectedTab={tabs[0]} />
</EuiModalBody>
{this._renderDeleteModal()}
{this._renderEditModal()}
</Fragment>
);
}
}

View file

@ -1,103 +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;
* you may not use this file except in compliance with the Elastic License.
*/
import PropTypes from 'prop-types';
import { compose, withProps, withState } from 'recompose';
import { connect } from 'react-redux';
import { camelCase } from 'lodash';
import { cloneSubgraphs } from '../../lib/clone_subgraphs';
import * as customElementService from '../../lib/custom_element_service';
import { elementsRegistry } from '../../lib/elements_registry';
import { notify } from '../../lib/notify';
import { selectToplevelNodes } from '../../state/actions/transient';
import { insertNodes, addElement } from '../../state/actions/elements';
import { getSelectedPage } from '../../state/selectors/workpad';
import { trackCanvasUiMetric, METRIC_TYPE } from '../../lib/ui_metric';
import { ElementTypes as Component } from './element_types';
const customElementAdded = 'elements-custom-added';
const mapStateToProps = state => ({ pageId: getSelectedPage(state) });
const mapDispatchToProps = dispatch => ({
selectToplevelNodes: nodes =>
dispatch(selectToplevelNodes(nodes.filter(e => !e.position.parent).map(e => e.id))),
insertNodes: (selectedNodes, pageId) => dispatch(insertNodes(selectedNodes, pageId)),
addElement: (pageId, partialElement) => dispatch(addElement(pageId, partialElement)),
});
const mergeProps = (stateProps, dispatchProps, ownProps) => {
const { pageId, ...remainingStateProps } = stateProps;
const { addElement, insertNodes, selectToplevelNodes } = dispatchProps;
const { search, setCustomElements, onClose } = ownProps;
return {
...remainingStateProps,
...ownProps,
// add built-in element to the page
addElement: element => {
addElement(pageId, element);
onClose();
},
// add custom element to the page
addCustomElement: customElement => {
const { selectedNodes = [] } = JSON.parse(customElement.content) || {};
const clonedNodes = selectedNodes && cloneSubgraphs(selectedNodes);
if (clonedNodes) {
insertNodes(clonedNodes, pageId); // first clone and persist the new node(s)
selectToplevelNodes(clonedNodes); // then select the cloned node(s)
}
onClose();
trackCanvasUiMetric(METRIC_TYPE.LOADED, customElementAdded);
},
// custom element search
findCustomElements: async text => {
try {
const { customElements } = await customElementService.find(text);
setCustomElements(customElements);
} catch (err) {
notify.error(err, { title: `Couldn't find custom elements` });
}
},
// remove custom element
removeCustomElement: async id => {
try {
await customElementService.remove(id).then();
const { customElements } = await customElementService.find(search);
setCustomElements(customElements);
} catch (err) {
notify.error(err, { title: `Couldn't delete custom elements` });
}
},
// update custom element
updateCustomElement: async (id, name, description, image) => {
try {
await customElementService.update(id, {
name: camelCase(name),
displayName: name,
image,
help: description,
});
const { customElements } = await customElementService.find(search);
setCustomElements(customElements);
} catch (err) {
notify.error(err, { title: `Couldn't update custom elements` });
}
},
};
};
export const ElementTypes = compose(
withState('search', 'setSearch', ''),
withState('customElements', 'setCustomElements', []),
withState('filterTags', 'setFilterTags', []),
withProps(() => ({ elements: elementsRegistry.toJS() })),
connect(mapStateToProps, mapDispatchToProps, mergeProps)
)(Component);
ElementTypes.propTypes = {
onClose: PropTypes.func,
};

View file

@ -4,4 +4,4 @@
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
export { Popover } from './popover'; export { Popover, ClosePopoverFn } from './popover';

View file

@ -24,6 +24,8 @@ interface Props {
className?: string; className?: string;
} }
export type ClosePopoverFn = () => void;
interface State { interface State {
isPopoverOpen: boolean; isPopoverOpen: boolean;
} }
@ -61,7 +63,7 @@ export class Popover extends Component<Props, State> {
})); }));
}; };
closePopover = () => { closePopover: ClosePopoverFn = () => {
this.setState({ this.setState({
isPopoverOpen: false, isPopoverOpen: false,
}); });

View file

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Storyshots components/Elements/ElementControls has two buttons 1`] = ` exports[`Storyshots components/SavedElementsModal/ElementControls has two buttons 1`] = `
<div <div
style={ style={
Object { Object {
@ -22,6 +22,7 @@ exports[`Storyshots components/Elements/ElementControls has two buttons 1`] = `
<button <button
aria-label="Edit element" aria-label="Edit element"
className="euiButtonIcon euiButtonIcon--primary" className="euiButtonIcon euiButtonIcon--primary"
data-test-subj="canvasElementCard__editButton"
onBlur={[Function]} onBlur={[Function]}
onClick={[Function]} onClick={[Function]}
onFocus={[Function]} onFocus={[Function]}
@ -47,6 +48,7 @@ exports[`Storyshots components/Elements/ElementControls has two buttons 1`] = `
<button <button
aria-label="Delete element" aria-label="Delete element"
className="euiButtonIcon euiButtonIcon--danger" className="euiButtonIcon euiButtonIcon--danger"
data-test-subj="canvasElementCard__deleteButton"
onBlur={[Function]} onBlur={[Function]}
onClick={[Function]} onClick={[Function]}
onFocus={[Function]} onFocus={[Function]}

View file

@ -0,0 +1,333 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Storyshots components/SavedElementsModal/ElementGrid default 1`] = `
<div
style={
Object {
"width": "1000px",
}
}
>
<div
className="euiFlexGrid euiFlexGrid--gutterLarge euiFlexGrid--fourths euiFlexGrid--responsive"
>
<div
className="euiFlexItem canvasElementCard__wrapper"
>
<div
className="euiCard euiCard--leftAligned euiCard--isClickable canvasElementCard"
onClick={[Function]}
>
<div
className="euiCard__top"
>
<img
alt=""
className="euiCard__image"
src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmlld0JveD0iMCAwIDI3MC42MDAwMSAyNjkuNTQ2NjYiCiAgIGhlaWdodD0iMjY5LjU0NjY2IgogICB3aWR0aD0iMjcwLjYwMDAxIgogICB4bWw6c3BhY2U9InByZXNlcnZlIgogICBpZD0ic3ZnMiIKICAgdmVyc2lvbj0iMS4xIj48bWV0YWRhdGEKICAgICBpZD0ibWV0YWRhdGE4Ij48cmRmOlJERj48Y2M6V29yawogICAgICAgICByZGY6YWJvdXQ9IiI+PGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+PGRjOnR5cGUKICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPjwvY2M6V29yaz48L3JkZjpSREY+PC9tZXRhZGF0YT48ZGVmcwogICAgIGlkPSJkZWZzNiIgLz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMzMzMzMzMywwLDAsLTEuMzMzMzMzMywwLDI2OS41NDY2NykiCiAgICAgaWQ9ImcxMCI+PGcKICAgICAgIHRyYW5zZm9ybT0ic2NhbGUoMC4xKSIKICAgICAgIGlkPSJnMTIiPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMTQiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNmZmZmZmY7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMjAyOS40OCw5NjIuNDQxIGMgMCwxNzAuMDk5IC0xMDUuNDYsMzE4Ljc5OSAtMjY0LjE3LDM3Ni42NTkgNi45OCwzNS44NiAxMC42Miw3MS43MSAxMC42MiwxMDkuMDUgMCwzMTYuMTkgLTI1Ny4yNCw1NzMuNDMgLTU3My40Nyw1NzMuNDMgLTE4NC43MiwwIC0zNTYuNTU4LC04OC41OSAtNDY0LjUzLC0yMzcuODUgLTUzLjA5LDQxLjE4IC0xMTguMjg1LDYzLjc1IC0xODYuMzA1LDYzLjc1IC0xNjcuODM2LDAgLTMwNC4zODMsLTEzNi41NCAtMzA0LjM4MywtMzA0LjM4IDAsLTM3LjA4IDYuNjE3LC03Mi41OCAxOS4wMzEsLTEwNi4wOCBDIDEwOC40ODgsMTM4MC4wOSAwLDEyMjcuODkgMCwxMDU4Ljg4IDAsODg3LjkxIDEwNS45NzcsNzM4LjUzOSAyNjUuMzk4LDY4MS4wOSBjIC02Ljc2OSwtMzUuNDQyIC0xMC40NiwtNzIuMDIgLTEwLjQ2LC0xMDkgQyAyNTQuOTM4LDI1Ni42MjEgNTExLjU2NiwwIDgyNy4wMjcsMCAxMDEyLjIsMCAxMTgzLjk0LDg4Ljk0MTQgMTI5MS4zLDIzOC44MzIgYyA1My40NSwtNDEuOTYxIDExOC44LC02NC45OTIgMTg2LjU2LC02NC45OTIgMTY3LjgzLDAgMzA0LjM4LDEzNi40OTIgMzA0LjM4LDMwNC4zMzIgMCwzNy4wNzggLTYuNjIsNzIuNjI5IC0xOS4wMywxMDYuMTI5IDE1Ny43OCw1Ni44NzkgMjY2LjI3LDIwOS4xMjkgMjY2LjI3LDM3OC4xNCIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDE2IgogICAgICAgICBzdHlsZT0iZmlsbDojZmFjZjA5O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDc5Ny44OTgsMTE1MC45MyA0NDQuMDcyLC0yMDIuNDUgNDQ4LjA1LDM5Mi41OCBjIDYuNDksMzIuMzkgOS42Niw2NC42NyA5LjY2LDk4LjQ2IDAsMjc2LjIzIC0yMjQuNjgsNTAwLjk1IC01MDAuOSw1MDAuOTUgLTE2NS4yNCwwIC0zMTkuMzcsLTgxLjM2IC00MTMuMDUzLC0yMTcuNzkgbCAtNzQuNTI0LC0zODYuNjQgODYuNjk1LC0xODUuMTEiIC8+PHBhdGgKICAgICAgICAgaWQ9InBhdGgxOCIKICAgICAgICAgc3R5bGU9ImZpbGw6IzQ5YzFhZTtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIKICAgICAgICAgZD0ibSAzMzguMjIzLDY4MC42NzIgYyAtNi40ODksLTMyLjM4MyAtOS44MDksLTY1Ljk4MSAtOS44MDksLTk5Ljk3MyAwLC0yNzYuOTI5IDIyNS4zMzYsLTUwMi4yNTc2IDUwMi4zMTMsLTUwMi4yNTc2IDE2Ni41OTMsMCAzMjEuNDczLDgyLjExNzYgNDE1LjAxMywyMTkuOTQ5NiBsIDczLjk3LDM4NS4zNDcgLTk4LjcyLDE4OC42MjEgTCA3NzUuMTU2LDEwNzUuNTcgMzM4LjIyMyw2ODAuNjcyIiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjAiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNlZjI5OWI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMzM1LjQxLDE0NDkuMTggMzA0LjMzMiwtNzEuODYgNjYuNjgsMzQ2LjAyIGMgLTQxLjU4NiwzMS43OCAtOTIuOTMsNDkuMTggLTE0NS43MzEsNDkuMTggLTEzMi4yNSwwIC0yMzkuODEyLC0xMDcuNjEgLTIzOS44MTIsLTIzOS44NyAwLC0yOS4yMSA0Ljg3OSwtNTcuMjIgMTQuNTMxLC04My40NyIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDIyIgogICAgICAgICBzdHlsZT0iZmlsbDojNGNhYmU0O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJNIDMwOC45OTIsMTM3Ni43IEMgMTczLjAyLDEzMzEuNjQgNzguNDgwNSwxMjAxLjMgNzguNDgwNSwxMDU3LjkzIDc4LjQ4MDUsOTE4LjM0IDE2NC44Miw3OTMuNjggMjk0LjQwNiw3NDQuMzUyIGwgNDI2Ljk4MSwzODUuOTM4IC03OC4zOTUsMTY3LjUxIC0zMzQsNzguOSIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICBzdHlsZT0iZmlsbDojODVjZTI2O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDEzMjMuOCwyOTguNDEgYyA0MS43NCwtMzIuMDkgOTIuODMsLTQ5LjU5IDE0NC45OCwtNDkuNTkgMTMyLjI1LDAgMjM5LjgxLDEwNy41NTkgMjM5LjgxLDIzOS44MjEgMCwyOS4xNiAtNC44OCw1Ny4xNjggLTE0LjUzLDgzLjQxOCBsIC0zMDQuMDgsNzEuMTYgLTY2LjE4LC0zNDQuODA5IiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjYiCiAgICAgICAgIHN0eWxlPSJmaWxsOiMzMTc3YTc7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMTM4NS42Nyw3MjIuOTMgMzM0Ljc2LC03OC4zMDEgYyAxMzYuMDIsNDQuOTYxIDIzMC41NiwxNzUuMzUxIDIzMC41NiwzMTguNzYyIDAsMTM5LjMzOSAtODYuNTQsMjYzLjg1OSAtMjE2LjM4LDMxMy4wMzkgbCAtNDM3Ljg0LC0zODMuNTkgODguOSwtMTY5LjkxIiAvPjwvZz48L2c+PC9zdmc+"
/>
</div>
<div
className="euiCard__content"
>
<span
className="euiTitle euiTitle--small euiCard__title"
id="generated-idTitle"
>
<button
aria-describedby=" generated-idDescription"
className="euiCard__titleButton"
onClick={[Function]}
>
Custom Element 1
</button>
</span>
<div
className="euiText euiText--small euiCard__description"
id="generated-idDescription"
>
<p>
sample description
</p>
</div>
</div>
<div
className="euiCard__footer"
/>
</div>
<div
className="euiFlexGroup euiFlexGroup--gutterExtraSmall euiFlexGroup--justifyContentSpaceBetween euiFlexGroup--directionRow euiFlexGroup--responsive canvasElementCard__controls"
>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<button
aria-label="Edit element"
className="euiButtonIcon euiButtonIcon--primary"
data-test-subj="canvasElementCard__editButton"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="pencil"
size="m"
/>
</button>
</span>
</div>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<button
aria-label="Delete element"
className="euiButtonIcon euiButtonIcon--danger"
data-test-subj="canvasElementCard__deleteButton"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="trash"
size="m"
/>
</button>
</span>
</div>
</div>
</div>
<div
className="euiFlexItem canvasElementCard__wrapper"
>
<div
className="euiCard euiCard--leftAligned euiCard--isClickable canvasElementCard"
onClick={[Function]}
>
<div
className="euiCard__top"
>
<img
alt=""
className="euiCard__image"
src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmlld0JveD0iMCAwIDI3MC42MDAwMSAyNjkuNTQ2NjYiCiAgIGhlaWdodD0iMjY5LjU0NjY2IgogICB3aWR0aD0iMjcwLjYwMDAxIgogICB4bWw6c3BhY2U9InByZXNlcnZlIgogICBpZD0ic3ZnMiIKICAgdmVyc2lvbj0iMS4xIj48bWV0YWRhdGEKICAgICBpZD0ibWV0YWRhdGE4Ij48cmRmOlJERj48Y2M6V29yawogICAgICAgICByZGY6YWJvdXQ9IiI+PGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+PGRjOnR5cGUKICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPjwvY2M6V29yaz48L3JkZjpSREY+PC9tZXRhZGF0YT48ZGVmcwogICAgIGlkPSJkZWZzNiIgLz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMzMzMzMzMywwLDAsLTEuMzMzMzMzMywwLDI2OS41NDY2NykiCiAgICAgaWQ9ImcxMCI+PGcKICAgICAgIHRyYW5zZm9ybT0ic2NhbGUoMC4xKSIKICAgICAgIGlkPSJnMTIiPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMTQiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNmZmZmZmY7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMjAyOS40OCw5NjIuNDQxIGMgMCwxNzAuMDk5IC0xMDUuNDYsMzE4Ljc5OSAtMjY0LjE3LDM3Ni42NTkgNi45OCwzNS44NiAxMC42Miw3MS43MSAxMC42MiwxMDkuMDUgMCwzMTYuMTkgLTI1Ny4yNCw1NzMuNDMgLTU3My40Nyw1NzMuNDMgLTE4NC43MiwwIC0zNTYuNTU4LC04OC41OSAtNDY0LjUzLC0yMzcuODUgLTUzLjA5LDQxLjE4IC0xMTguMjg1LDYzLjc1IC0xODYuMzA1LDYzLjc1IC0xNjcuODM2LDAgLTMwNC4zODMsLTEzNi41NCAtMzA0LjM4MywtMzA0LjM4IDAsLTM3LjA4IDYuNjE3LC03Mi41OCAxOS4wMzEsLTEwNi4wOCBDIDEwOC40ODgsMTM4MC4wOSAwLDEyMjcuODkgMCwxMDU4Ljg4IDAsODg3LjkxIDEwNS45NzcsNzM4LjUzOSAyNjUuMzk4LDY4MS4wOSBjIC02Ljc2OSwtMzUuNDQyIC0xMC40NiwtNzIuMDIgLTEwLjQ2LC0xMDkgQyAyNTQuOTM4LDI1Ni42MjEgNTExLjU2NiwwIDgyNy4wMjcsMCAxMDEyLjIsMCAxMTgzLjk0LDg4Ljk0MTQgMTI5MS4zLDIzOC44MzIgYyA1My40NSwtNDEuOTYxIDExOC44LC02NC45OTIgMTg2LjU2LC02NC45OTIgMTY3LjgzLDAgMzA0LjM4LDEzNi40OTIgMzA0LjM4LDMwNC4zMzIgMCwzNy4wNzggLTYuNjIsNzIuNjI5IC0xOS4wMywxMDYuMTI5IDE1Ny43OCw1Ni44NzkgMjY2LjI3LDIwOS4xMjkgMjY2LjI3LDM3OC4xNCIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDE2IgogICAgICAgICBzdHlsZT0iZmlsbDojZmFjZjA5O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDc5Ny44OTgsMTE1MC45MyA0NDQuMDcyLC0yMDIuNDUgNDQ4LjA1LDM5Mi41OCBjIDYuNDksMzIuMzkgOS42Niw2NC42NyA5LjY2LDk4LjQ2IDAsMjc2LjIzIC0yMjQuNjgsNTAwLjk1IC01MDAuOSw1MDAuOTUgLTE2NS4yNCwwIC0zMTkuMzcsLTgxLjM2IC00MTMuMDUzLC0yMTcuNzkgbCAtNzQuNTI0LC0zODYuNjQgODYuNjk1LC0xODUuMTEiIC8+PHBhdGgKICAgICAgICAgaWQ9InBhdGgxOCIKICAgICAgICAgc3R5bGU9ImZpbGw6IzQ5YzFhZTtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIKICAgICAgICAgZD0ibSAzMzguMjIzLDY4MC42NzIgYyAtNi40ODksLTMyLjM4MyAtOS44MDksLTY1Ljk4MSAtOS44MDksLTk5Ljk3MyAwLC0yNzYuOTI5IDIyNS4zMzYsLTUwMi4yNTc2IDUwMi4zMTMsLTUwMi4yNTc2IDE2Ni41OTMsMCAzMjEuNDczLDgyLjExNzYgNDE1LjAxMywyMTkuOTQ5NiBsIDczLjk3LDM4NS4zNDcgLTk4LjcyLDE4OC42MjEgTCA3NzUuMTU2LDEwNzUuNTcgMzM4LjIyMyw2ODAuNjcyIiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjAiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNlZjI5OWI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMzM1LjQxLDE0NDkuMTggMzA0LjMzMiwtNzEuODYgNjYuNjgsMzQ2LjAyIGMgLTQxLjU4NiwzMS43OCAtOTIuOTMsNDkuMTggLTE0NS43MzEsNDkuMTggLTEzMi4yNSwwIC0yMzkuODEyLC0xMDcuNjEgLTIzOS44MTIsLTIzOS44NyAwLC0yOS4yMSA0Ljg3OSwtNTcuMjIgMTQuNTMxLC04My40NyIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDIyIgogICAgICAgICBzdHlsZT0iZmlsbDojNGNhYmU0O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJNIDMwOC45OTIsMTM3Ni43IEMgMTczLjAyLDEzMzEuNjQgNzguNDgwNSwxMjAxLjMgNzguNDgwNSwxMDU3LjkzIDc4LjQ4MDUsOTE4LjM0IDE2NC44Miw3OTMuNjggMjk0LjQwNiw3NDQuMzUyIGwgNDI2Ljk4MSwzODUuOTM4IC03OC4zOTUsMTY3LjUxIC0zMzQsNzguOSIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICBzdHlsZT0iZmlsbDojODVjZTI2O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDEzMjMuOCwyOTguNDEgYyA0MS43NCwtMzIuMDkgOTIuODMsLTQ5LjU5IDE0NC45OCwtNDkuNTkgMTMyLjI1LDAgMjM5LjgxLDEwNy41NTkgMjM5LjgxLDIzOS44MjEgMCwyOS4xNiAtNC44OCw1Ny4xNjggLTE0LjUzLDgzLjQxOCBsIC0zMDQuMDgsNzEuMTYgLTY2LjE4LC0zNDQuODA5IiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjYiCiAgICAgICAgIHN0eWxlPSJmaWxsOiMzMTc3YTc7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMTM4NS42Nyw3MjIuOTMgMzM0Ljc2LC03OC4zMDEgYyAxMzYuMDIsNDQuOTYxIDIzMC41NiwxNzUuMzUxIDIzMC41NiwzMTguNzYyIDAsMTM5LjMzOSAtODYuNTQsMjYzLjg1OSAtMjE2LjM4LDMxMy4wMzkgbCAtNDM3Ljg0LC0zODMuNTkgODguOSwtMTY5LjkxIiAvPjwvZz48L2c+PC9zdmc+"
/>
</div>
<div
className="euiCard__content"
>
<span
className="euiTitle euiTitle--small euiCard__title"
id="generated-idTitle"
>
<button
aria-describedby=" generated-idDescription"
className="euiCard__titleButton"
onClick={[Function]}
>
Custom Element 2
</button>
</span>
<div
className="euiText euiText--small euiCard__description"
id="generated-idDescription"
>
<p>
Aenean eu justo auctor, placerat felis non, scelerisque dolor.
</p>
</div>
</div>
<div
className="euiCard__footer"
/>
</div>
<div
className="euiFlexGroup euiFlexGroup--gutterExtraSmall euiFlexGroup--justifyContentSpaceBetween euiFlexGroup--directionRow euiFlexGroup--responsive canvasElementCard__controls"
>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<button
aria-label="Edit element"
className="euiButtonIcon euiButtonIcon--primary"
data-test-subj="canvasElementCard__editButton"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="pencil"
size="m"
/>
</button>
</span>
</div>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<button
aria-label="Delete element"
className="euiButtonIcon euiButtonIcon--danger"
data-test-subj="canvasElementCard__deleteButton"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="trash"
size="m"
/>
</button>
</span>
</div>
</div>
</div>
<div
className="euiFlexItem canvasElementCard__wrapper"
>
<div
className="euiCard euiCard--leftAligned euiCard--isClickable canvasElementCard"
onClick={[Function]}
>
<div
className="euiCard__top"
>
<img
alt=""
className="euiCard__image"
src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmlld0JveD0iMCAwIDI3MC42MDAwMSAyNjkuNTQ2NjYiCiAgIGhlaWdodD0iMjY5LjU0NjY2IgogICB3aWR0aD0iMjcwLjYwMDAxIgogICB4bWw6c3BhY2U9InByZXNlcnZlIgogICBpZD0ic3ZnMiIKICAgdmVyc2lvbj0iMS4xIj48bWV0YWRhdGEKICAgICBpZD0ibWV0YWRhdGE4Ij48cmRmOlJERj48Y2M6V29yawogICAgICAgICByZGY6YWJvdXQ9IiI+PGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+PGRjOnR5cGUKICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPjwvY2M6V29yaz48L3JkZjpSREY+PC9tZXRhZGF0YT48ZGVmcwogICAgIGlkPSJkZWZzNiIgLz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMzMzMzMzMywwLDAsLTEuMzMzMzMzMywwLDI2OS41NDY2NykiCiAgICAgaWQ9ImcxMCI+PGcKICAgICAgIHRyYW5zZm9ybT0ic2NhbGUoMC4xKSIKICAgICAgIGlkPSJnMTIiPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMTQiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNmZmZmZmY7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMjAyOS40OCw5NjIuNDQxIGMgMCwxNzAuMDk5IC0xMDUuNDYsMzE4Ljc5OSAtMjY0LjE3LDM3Ni42NTkgNi45OCwzNS44NiAxMC42Miw3MS43MSAxMC42MiwxMDkuMDUgMCwzMTYuMTkgLTI1Ny4yNCw1NzMuNDMgLTU3My40Nyw1NzMuNDMgLTE4NC43MiwwIC0zNTYuNTU4LC04OC41OSAtNDY0LjUzLC0yMzcuODUgLTUzLjA5LDQxLjE4IC0xMTguMjg1LDYzLjc1IC0xODYuMzA1LDYzLjc1IC0xNjcuODM2LDAgLTMwNC4zODMsLTEzNi41NCAtMzA0LjM4MywtMzA0LjM4IDAsLTM3LjA4IDYuNjE3LC03Mi41OCAxOS4wMzEsLTEwNi4wOCBDIDEwOC40ODgsMTM4MC4wOSAwLDEyMjcuODkgMCwxMDU4Ljg4IDAsODg3LjkxIDEwNS45NzcsNzM4LjUzOSAyNjUuMzk4LDY4MS4wOSBjIC02Ljc2OSwtMzUuNDQyIC0xMC40NiwtNzIuMDIgLTEwLjQ2LC0xMDkgQyAyNTQuOTM4LDI1Ni42MjEgNTExLjU2NiwwIDgyNy4wMjcsMCAxMDEyLjIsMCAxMTgzLjk0LDg4Ljk0MTQgMTI5MS4zLDIzOC44MzIgYyA1My40NSwtNDEuOTYxIDExOC44LC02NC45OTIgMTg2LjU2LC02NC45OTIgMTY3LjgzLDAgMzA0LjM4LDEzNi40OTIgMzA0LjM4LDMwNC4zMzIgMCwzNy4wNzggLTYuNjIsNzIuNjI5IC0xOS4wMywxMDYuMTI5IDE1Ny43OCw1Ni44NzkgMjY2LjI3LDIwOS4xMjkgMjY2LjI3LDM3OC4xNCIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDE2IgogICAgICAgICBzdHlsZT0iZmlsbDojZmFjZjA5O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDc5Ny44OTgsMTE1MC45MyA0NDQuMDcyLC0yMDIuNDUgNDQ4LjA1LDM5Mi41OCBjIDYuNDksMzIuMzkgOS42Niw2NC42NyA5LjY2LDk4LjQ2IDAsMjc2LjIzIC0yMjQuNjgsNTAwLjk1IC01MDAuOSw1MDAuOTUgLTE2NS4yNCwwIC0zMTkuMzcsLTgxLjM2IC00MTMuMDUzLC0yMTcuNzkgbCAtNzQuNTI0LC0zODYuNjQgODYuNjk1LC0xODUuMTEiIC8+PHBhdGgKICAgICAgICAgaWQ9InBhdGgxOCIKICAgICAgICAgc3R5bGU9ImZpbGw6IzQ5YzFhZTtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIKICAgICAgICAgZD0ibSAzMzguMjIzLDY4MC42NzIgYyAtNi40ODksLTMyLjM4MyAtOS44MDksLTY1Ljk4MSAtOS44MDksLTk5Ljk3MyAwLC0yNzYuOTI5IDIyNS4zMzYsLTUwMi4yNTc2IDUwMi4zMTMsLTUwMi4yNTc2IDE2Ni41OTMsMCAzMjEuNDczLDgyLjExNzYgNDE1LjAxMywyMTkuOTQ5NiBsIDczLjk3LDM4NS4zNDcgLTk4LjcyLDE4OC42MjEgTCA3NzUuMTU2LDEwNzUuNTcgMzM4LjIyMyw2ODAuNjcyIiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjAiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNlZjI5OWI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMzM1LjQxLDE0NDkuMTggMzA0LjMzMiwtNzEuODYgNjYuNjgsMzQ2LjAyIGMgLTQxLjU4NiwzMS43OCAtOTIuOTMsNDkuMTggLTE0NS43MzEsNDkuMTggLTEzMi4yNSwwIC0yMzkuODEyLC0xMDcuNjEgLTIzOS44MTIsLTIzOS44NyAwLC0yOS4yMSA0Ljg3OSwtNTcuMjIgMTQuNTMxLC04My40NyIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDIyIgogICAgICAgICBzdHlsZT0iZmlsbDojNGNhYmU0O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJNIDMwOC45OTIsMTM3Ni43IEMgMTczLjAyLDEzMzEuNjQgNzguNDgwNSwxMjAxLjMgNzguNDgwNSwxMDU3LjkzIDc4LjQ4MDUsOTE4LjM0IDE2NC44Miw3OTMuNjggMjk0LjQwNiw3NDQuMzUyIGwgNDI2Ljk4MSwzODUuOTM4IC03OC4zOTUsMTY3LjUxIC0zMzQsNzguOSIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICBzdHlsZT0iZmlsbDojODVjZTI2O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDEzMjMuOCwyOTguNDEgYyA0MS43NCwtMzIuMDkgOTIuODMsLTQ5LjU5IDE0NC45OCwtNDkuNTkgMTMyLjI1LDAgMjM5LjgxLDEwNy41NTkgMjM5LjgxLDIzOS44MjEgMCwyOS4xNiAtNC44OCw1Ny4xNjggLTE0LjUzLDgzLjQxOCBsIC0zMDQuMDgsNzEuMTYgLTY2LjE4LC0zNDQuODA5IiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjYiCiAgICAgICAgIHN0eWxlPSJmaWxsOiMzMTc3YTc7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMTM4NS42Nyw3MjIuOTMgMzM0Ljc2LC03OC4zMDEgYyAxMzYuMDIsNDQuOTYxIDIzMC41NiwxNzUuMzUxIDIzMC41NiwzMTguNzYyIDAsMTM5LjMzOSAtODYuNTQsMjYzLjg1OSAtMjE2LjM4LDMxMy4wMzkgbCAtNDM3Ljg0LC0zODMuNTkgODguOSwtMTY5LjkxIiAvPjwvZz48L2c+PC9zdmc+"
/>
</div>
<div
className="euiCard__content"
>
<span
className="euiTitle euiTitle--small euiCard__title"
id="generated-idTitle"
>
<button
aria-describedby=" generated-idDescription"
className="euiCard__titleButton"
onClick={[Function]}
>
Custom Element 3
</button>
</span>
<div
className="euiText euiText--small euiCard__description"
id="generated-idDescription"
>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce lobortis aliquet arcu ut turpis duis.
</p>
</div>
</div>
<div
className="euiCard__footer"
/>
</div>
<div
className="euiFlexGroup euiFlexGroup--gutterExtraSmall euiFlexGroup--justifyContentSpaceBetween euiFlexGroup--directionRow euiFlexGroup--responsive canvasElementCard__controls"
>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<button
aria-label="Edit element"
className="euiButtonIcon euiButtonIcon--primary"
data-test-subj="canvasElementCard__editButton"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="pencil"
size="m"
/>
</button>
</span>
</div>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<button
aria-label="Delete element"
className="euiButtonIcon euiButtonIcon--danger"
data-test-subj="canvasElementCard__deleteButton"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="trash"
size="m"
/>
</button>
</span>
</div>
</div>
</div>
</div>
</div>
`;
exports[`Storyshots components/SavedElementsModal/ElementGrid with text filter 1`] = `
<div
style={
Object {
"width": "1000px",
}
}
>
<div
className="euiFlexGrid euiFlexGrid--gutterLarge euiFlexGrid--fourths euiFlexGrid--responsive"
/>
</div>
`;

View file

@ -0,0 +1,933 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Storyshots components/SavedElementsModal no custom elements 1`] = `
Array [
<div
data-focus-guard={true}
style={
Object {
"height": "0px",
"left": "1px",
"overflow": "hidden",
"padding": 0,
"position": "fixed",
"top": "1px",
"width": "1px",
}
}
tabIndex={0}
/>,
<div
data-focus-guard={true}
style={
Object {
"height": "0px",
"left": "1px",
"overflow": "hidden",
"padding": 0,
"position": "fixed",
"top": "1px",
"width": "1px",
}
}
tabIndex={1}
/>,
<div
data-focus-lock-disabled={false}
onBlur={[Function]}
onFocus={[Function]}
>
<div
className="euiModal canvasModal--fixedSize"
onKeyDown={[Function]}
style={
Object {
"maxWidth": "1000px",
}
}
tabIndex={0}
>
<button
aria-label="Closes this modal window"
className="euiButtonIcon euiButtonIcon--text euiModal__closeIcon"
onClick={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="cross"
size="m"
/>
</button>
<div
className="euiModal__flex"
>
<div
className="euiModalHeader canvasAssetManager__modalHeader"
>
<div
className="euiModalHeader__title canvasAssetManager__modalHeaderTitle"
>
My elements
</div>
</div>
<div
className="euiModalBody"
style={
Object {
"paddingRight": "1px",
}
}
>
<div
className="euiModalBody__overflow"
>
<div
className="euiFormControlLayout euiFormControlLayout--fullWidth"
>
<div
className="euiFormControlLayout__childrenWrapper"
>
<input
className="euiFieldSearch euiFieldSearch--fullWidth"
onChange={[Function]}
onKeyUp={[Function]}
placeholder="Find element"
type="search"
value=""
/>
<div
className="euiFormControlLayoutIcons"
>
<span
className="euiFormControlLayoutCustomIcon"
>
<div
aria-hidden="true"
className="euiFormControlLayoutCustomIcon__icon"
data-euiicon-type="search"
/>
</span>
</div>
</div>
</div>
<div
className="euiSpacer euiSpacer--l"
/>
<div
className="euiEmptyPrompt"
>
<div
color="subdued"
data-euiicon-type="vector"
size="xxl"
/>
<div
className="euiSpacer euiSpacer--s"
/>
<span
className="euiTextColor euiTextColor--subdued"
>
<h2
className="euiTitle euiTitle--small"
>
Add new elements
</h2>
<div
className="euiSpacer euiSpacer--m"
/>
<div
className="euiText euiText--medium"
>
<p>
Group and save workpad elements to create new elements
</p>
</div>
</span>
</div>
</div>
</div>
<div
className="euiModalFooter"
>
<button
className="euiButton euiButton--primary euiButton--small"
data-test-subj="saved-elements-modal-close-button"
onClick={[Function]}
type="button"
>
<span
className="euiButton__content"
>
<span
className="euiButton__text"
>
Close
</span>
</span>
</button>
</div>
</div>
</div>
</div>,
<div
data-focus-guard={true}
style={
Object {
"height": "0px",
"left": "1px",
"overflow": "hidden",
"padding": 0,
"position": "fixed",
"top": "1px",
"width": "1px",
}
}
tabIndex={0}
/>,
]
`;
exports[`Storyshots components/SavedElementsModal with custom elements 1`] = `
Array [
<div
data-focus-guard={true}
style={
Object {
"height": "0px",
"left": "1px",
"overflow": "hidden",
"padding": 0,
"position": "fixed",
"top": "1px",
"width": "1px",
}
}
tabIndex={0}
/>,
<div
data-focus-guard={true}
style={
Object {
"height": "0px",
"left": "1px",
"overflow": "hidden",
"padding": 0,
"position": "fixed",
"top": "1px",
"width": "1px",
}
}
tabIndex={1}
/>,
<div
data-focus-lock-disabled={false}
onBlur={[Function]}
onFocus={[Function]}
>
<div
className="euiModal canvasModal--fixedSize"
onKeyDown={[Function]}
style={
Object {
"maxWidth": "1000px",
}
}
tabIndex={0}
>
<button
aria-label="Closes this modal window"
className="euiButtonIcon euiButtonIcon--text euiModal__closeIcon"
onClick={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="cross"
size="m"
/>
</button>
<div
className="euiModal__flex"
>
<div
className="euiModalHeader canvasAssetManager__modalHeader"
>
<div
className="euiModalHeader__title canvasAssetManager__modalHeaderTitle"
>
My elements
</div>
</div>
<div
className="euiModalBody"
style={
Object {
"paddingRight": "1px",
}
}
>
<div
className="euiModalBody__overflow"
>
<div
className="euiFormControlLayout euiFormControlLayout--fullWidth"
>
<div
className="euiFormControlLayout__childrenWrapper"
>
<input
className="euiFieldSearch euiFieldSearch--fullWidth"
onChange={[Function]}
onKeyUp={[Function]}
placeholder="Find element"
type="search"
value=""
/>
<div
className="euiFormControlLayoutIcons"
>
<span
className="euiFormControlLayoutCustomIcon"
>
<div
aria-hidden="true"
className="euiFormControlLayoutCustomIcon__icon"
data-euiicon-type="search"
/>
</span>
</div>
</div>
</div>
<div
className="euiSpacer euiSpacer--l"
/>
<div
className="euiFlexGrid euiFlexGrid--gutterLarge euiFlexGrid--fourths euiFlexGrid--responsive"
>
<div
className="euiFlexItem canvasElementCard__wrapper"
>
<div
className="euiCard euiCard--leftAligned euiCard--isClickable canvasElementCard"
onClick={[Function]}
>
<div
className="euiCard__top"
>
<img
alt=""
className="euiCard__image"
src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmlld0JveD0iMCAwIDI3MC42MDAwMSAyNjkuNTQ2NjYiCiAgIGhlaWdodD0iMjY5LjU0NjY2IgogICB3aWR0aD0iMjcwLjYwMDAxIgogICB4bWw6c3BhY2U9InByZXNlcnZlIgogICBpZD0ic3ZnMiIKICAgdmVyc2lvbj0iMS4xIj48bWV0YWRhdGEKICAgICBpZD0ibWV0YWRhdGE4Ij48cmRmOlJERj48Y2M6V29yawogICAgICAgICByZGY6YWJvdXQ9IiI+PGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+PGRjOnR5cGUKICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPjwvY2M6V29yaz48L3JkZjpSREY+PC9tZXRhZGF0YT48ZGVmcwogICAgIGlkPSJkZWZzNiIgLz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMzMzMzMzMywwLDAsLTEuMzMzMzMzMywwLDI2OS41NDY2NykiCiAgICAgaWQ9ImcxMCI+PGcKICAgICAgIHRyYW5zZm9ybT0ic2NhbGUoMC4xKSIKICAgICAgIGlkPSJnMTIiPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMTQiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNmZmZmZmY7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMjAyOS40OCw5NjIuNDQxIGMgMCwxNzAuMDk5IC0xMDUuNDYsMzE4Ljc5OSAtMjY0LjE3LDM3Ni42NTkgNi45OCwzNS44NiAxMC42Miw3MS43MSAxMC42MiwxMDkuMDUgMCwzMTYuMTkgLTI1Ny4yNCw1NzMuNDMgLTU3My40Nyw1NzMuNDMgLTE4NC43MiwwIC0zNTYuNTU4LC04OC41OSAtNDY0LjUzLC0yMzcuODUgLTUzLjA5LDQxLjE4IC0xMTguMjg1LDYzLjc1IC0xODYuMzA1LDYzLjc1IC0xNjcuODM2LDAgLTMwNC4zODMsLTEzNi41NCAtMzA0LjM4MywtMzA0LjM4IDAsLTM3LjA4IDYuNjE3LC03Mi41OCAxOS4wMzEsLTEwNi4wOCBDIDEwOC40ODgsMTM4MC4wOSAwLDEyMjcuODkgMCwxMDU4Ljg4IDAsODg3LjkxIDEwNS45NzcsNzM4LjUzOSAyNjUuMzk4LDY4MS4wOSBjIC02Ljc2OSwtMzUuNDQyIC0xMC40NiwtNzIuMDIgLTEwLjQ2LC0xMDkgQyAyNTQuOTM4LDI1Ni42MjEgNTExLjU2NiwwIDgyNy4wMjcsMCAxMDEyLjIsMCAxMTgzLjk0LDg4Ljk0MTQgMTI5MS4zLDIzOC44MzIgYyA1My40NSwtNDEuOTYxIDExOC44LC02NC45OTIgMTg2LjU2LC02NC45OTIgMTY3LjgzLDAgMzA0LjM4LDEzNi40OTIgMzA0LjM4LDMwNC4zMzIgMCwzNy4wNzggLTYuNjIsNzIuNjI5IC0xOS4wMywxMDYuMTI5IDE1Ny43OCw1Ni44NzkgMjY2LjI3LDIwOS4xMjkgMjY2LjI3LDM3OC4xNCIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDE2IgogICAgICAgICBzdHlsZT0iZmlsbDojZmFjZjA5O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDc5Ny44OTgsMTE1MC45MyA0NDQuMDcyLC0yMDIuNDUgNDQ4LjA1LDM5Mi41OCBjIDYuNDksMzIuMzkgOS42Niw2NC42NyA5LjY2LDk4LjQ2IDAsMjc2LjIzIC0yMjQuNjgsNTAwLjk1IC01MDAuOSw1MDAuOTUgLTE2NS4yNCwwIC0zMTkuMzcsLTgxLjM2IC00MTMuMDUzLC0yMTcuNzkgbCAtNzQuNTI0LC0zODYuNjQgODYuNjk1LC0xODUuMTEiIC8+PHBhdGgKICAgICAgICAgaWQ9InBhdGgxOCIKICAgICAgICAgc3R5bGU9ImZpbGw6IzQ5YzFhZTtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIKICAgICAgICAgZD0ibSAzMzguMjIzLDY4MC42NzIgYyAtNi40ODksLTMyLjM4MyAtOS44MDksLTY1Ljk4MSAtOS44MDksLTk5Ljk3MyAwLC0yNzYuOTI5IDIyNS4zMzYsLTUwMi4yNTc2IDUwMi4zMTMsLTUwMi4yNTc2IDE2Ni41OTMsMCAzMjEuNDczLDgyLjExNzYgNDE1LjAxMywyMTkuOTQ5NiBsIDczLjk3LDM4NS4zNDcgLTk4LjcyLDE4OC42MjEgTCA3NzUuMTU2LDEwNzUuNTcgMzM4LjIyMyw2ODAuNjcyIiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjAiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNlZjI5OWI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMzM1LjQxLDE0NDkuMTggMzA0LjMzMiwtNzEuODYgNjYuNjgsMzQ2LjAyIGMgLTQxLjU4NiwzMS43OCAtOTIuOTMsNDkuMTggLTE0NS43MzEsNDkuMTggLTEzMi4yNSwwIC0yMzkuODEyLC0xMDcuNjEgLTIzOS44MTIsLTIzOS44NyAwLC0yOS4yMSA0Ljg3OSwtNTcuMjIgMTQuNTMxLC04My40NyIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDIyIgogICAgICAgICBzdHlsZT0iZmlsbDojNGNhYmU0O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJNIDMwOC45OTIsMTM3Ni43IEMgMTczLjAyLDEzMzEuNjQgNzguNDgwNSwxMjAxLjMgNzguNDgwNSwxMDU3LjkzIDc4LjQ4MDUsOTE4LjM0IDE2NC44Miw3OTMuNjggMjk0LjQwNiw3NDQuMzUyIGwgNDI2Ljk4MSwzODUuOTM4IC03OC4zOTUsMTY3LjUxIC0zMzQsNzguOSIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICBzdHlsZT0iZmlsbDojODVjZTI2O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDEzMjMuOCwyOTguNDEgYyA0MS43NCwtMzIuMDkgOTIuODMsLTQ5LjU5IDE0NC45OCwtNDkuNTkgMTMyLjI1LDAgMjM5LjgxLDEwNy41NTkgMjM5LjgxLDIzOS44MjEgMCwyOS4xNiAtNC44OCw1Ny4xNjggLTE0LjUzLDgzLjQxOCBsIC0zMDQuMDgsNzEuMTYgLTY2LjE4LC0zNDQuODA5IiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjYiCiAgICAgICAgIHN0eWxlPSJmaWxsOiMzMTc3YTc7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMTM4NS42Nyw3MjIuOTMgMzM0Ljc2LC03OC4zMDEgYyAxMzYuMDIsNDQuOTYxIDIzMC41NiwxNzUuMzUxIDIzMC41NiwzMTguNzYyIDAsMTM5LjMzOSAtODYuNTQsMjYzLjg1OSAtMjE2LjM4LDMxMy4wMzkgbCAtNDM3Ljg0LC0zODMuNTkgODguOSwtMTY5LjkxIiAvPjwvZz48L2c+PC9zdmc+"
/>
</div>
<div
className="euiCard__content"
>
<span
className="euiTitle euiTitle--small euiCard__title"
id="generated-idTitle"
>
<button
aria-describedby=" generated-idDescription"
className="euiCard__titleButton"
onClick={[Function]}
>
Custom Element 1
</button>
</span>
<div
className="euiText euiText--small euiCard__description"
id="generated-idDescription"
>
<p>
sample description
</p>
</div>
</div>
<div
className="euiCard__footer"
/>
</div>
<div
className="euiFlexGroup euiFlexGroup--gutterExtraSmall euiFlexGroup--justifyContentSpaceBetween euiFlexGroup--directionRow euiFlexGroup--responsive canvasElementCard__controls"
>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<button
aria-label="Edit element"
className="euiButtonIcon euiButtonIcon--primary"
data-test-subj="canvasElementCard__editButton"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="pencil"
size="m"
/>
</button>
</span>
</div>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<button
aria-label="Delete element"
className="euiButtonIcon euiButtonIcon--danger"
data-test-subj="canvasElementCard__deleteButton"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="trash"
size="m"
/>
</button>
</span>
</div>
</div>
</div>
<div
className="euiFlexItem canvasElementCard__wrapper"
>
<div
className="euiCard euiCard--leftAligned euiCard--isClickable canvasElementCard"
onClick={[Function]}
>
<div
className="euiCard__top"
>
<img
alt=""
className="euiCard__image"
src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmlld0JveD0iMCAwIDI3MC42MDAwMSAyNjkuNTQ2NjYiCiAgIGhlaWdodD0iMjY5LjU0NjY2IgogICB3aWR0aD0iMjcwLjYwMDAxIgogICB4bWw6c3BhY2U9InByZXNlcnZlIgogICBpZD0ic3ZnMiIKICAgdmVyc2lvbj0iMS4xIj48bWV0YWRhdGEKICAgICBpZD0ibWV0YWRhdGE4Ij48cmRmOlJERj48Y2M6V29yawogICAgICAgICByZGY6YWJvdXQ9IiI+PGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+PGRjOnR5cGUKICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPjwvY2M6V29yaz48L3JkZjpSREY+PC9tZXRhZGF0YT48ZGVmcwogICAgIGlkPSJkZWZzNiIgLz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMzMzMzMzMywwLDAsLTEuMzMzMzMzMywwLDI2OS41NDY2NykiCiAgICAgaWQ9ImcxMCI+PGcKICAgICAgIHRyYW5zZm9ybT0ic2NhbGUoMC4xKSIKICAgICAgIGlkPSJnMTIiPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMTQiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNmZmZmZmY7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMjAyOS40OCw5NjIuNDQxIGMgMCwxNzAuMDk5IC0xMDUuNDYsMzE4Ljc5OSAtMjY0LjE3LDM3Ni42NTkgNi45OCwzNS44NiAxMC42Miw3MS43MSAxMC42MiwxMDkuMDUgMCwzMTYuMTkgLTI1Ny4yNCw1NzMuNDMgLTU3My40Nyw1NzMuNDMgLTE4NC43MiwwIC0zNTYuNTU4LC04OC41OSAtNDY0LjUzLC0yMzcuODUgLTUzLjA5LDQxLjE4IC0xMTguMjg1LDYzLjc1IC0xODYuMzA1LDYzLjc1IC0xNjcuODM2LDAgLTMwNC4zODMsLTEzNi41NCAtMzA0LjM4MywtMzA0LjM4IDAsLTM3LjA4IDYuNjE3LC03Mi41OCAxOS4wMzEsLTEwNi4wOCBDIDEwOC40ODgsMTM4MC4wOSAwLDEyMjcuODkgMCwxMDU4Ljg4IDAsODg3LjkxIDEwNS45NzcsNzM4LjUzOSAyNjUuMzk4LDY4MS4wOSBjIC02Ljc2OSwtMzUuNDQyIC0xMC40NiwtNzIuMDIgLTEwLjQ2LC0xMDkgQyAyNTQuOTM4LDI1Ni42MjEgNTExLjU2NiwwIDgyNy4wMjcsMCAxMDEyLjIsMCAxMTgzLjk0LDg4Ljk0MTQgMTI5MS4zLDIzOC44MzIgYyA1My40NSwtNDEuOTYxIDExOC44LC02NC45OTIgMTg2LjU2LC02NC45OTIgMTY3LjgzLDAgMzA0LjM4LDEzNi40OTIgMzA0LjM4LDMwNC4zMzIgMCwzNy4wNzggLTYuNjIsNzIuNjI5IC0xOS4wMywxMDYuMTI5IDE1Ny43OCw1Ni44NzkgMjY2LjI3LDIwOS4xMjkgMjY2LjI3LDM3OC4xNCIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDE2IgogICAgICAgICBzdHlsZT0iZmlsbDojZmFjZjA5O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDc5Ny44OTgsMTE1MC45MyA0NDQuMDcyLC0yMDIuNDUgNDQ4LjA1LDM5Mi41OCBjIDYuNDksMzIuMzkgOS42Niw2NC42NyA5LjY2LDk4LjQ2IDAsMjc2LjIzIC0yMjQuNjgsNTAwLjk1IC01MDAuOSw1MDAuOTUgLTE2NS4yNCwwIC0zMTkuMzcsLTgxLjM2IC00MTMuMDUzLC0yMTcuNzkgbCAtNzQuNTI0LC0zODYuNjQgODYuNjk1LC0xODUuMTEiIC8+PHBhdGgKICAgICAgICAgaWQ9InBhdGgxOCIKICAgICAgICAgc3R5bGU9ImZpbGw6IzQ5YzFhZTtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIKICAgICAgICAgZD0ibSAzMzguMjIzLDY4MC42NzIgYyAtNi40ODksLTMyLjM4MyAtOS44MDksLTY1Ljk4MSAtOS44MDksLTk5Ljk3MyAwLC0yNzYuOTI5IDIyNS4zMzYsLTUwMi4yNTc2IDUwMi4zMTMsLTUwMi4yNTc2IDE2Ni41OTMsMCAzMjEuNDczLDgyLjExNzYgNDE1LjAxMywyMTkuOTQ5NiBsIDczLjk3LDM4NS4zNDcgLTk4LjcyLDE4OC42MjEgTCA3NzUuMTU2LDEwNzUuNTcgMzM4LjIyMyw2ODAuNjcyIiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjAiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNlZjI5OWI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMzM1LjQxLDE0NDkuMTggMzA0LjMzMiwtNzEuODYgNjYuNjgsMzQ2LjAyIGMgLTQxLjU4NiwzMS43OCAtOTIuOTMsNDkuMTggLTE0NS43MzEsNDkuMTggLTEzMi4yNSwwIC0yMzkuODEyLC0xMDcuNjEgLTIzOS44MTIsLTIzOS44NyAwLC0yOS4yMSA0Ljg3OSwtNTcuMjIgMTQuNTMxLC04My40NyIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDIyIgogICAgICAgICBzdHlsZT0iZmlsbDojNGNhYmU0O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJNIDMwOC45OTIsMTM3Ni43IEMgMTczLjAyLDEzMzEuNjQgNzguNDgwNSwxMjAxLjMgNzguNDgwNSwxMDU3LjkzIDc4LjQ4MDUsOTE4LjM0IDE2NC44Miw3OTMuNjggMjk0LjQwNiw3NDQuMzUyIGwgNDI2Ljk4MSwzODUuOTM4IC03OC4zOTUsMTY3LjUxIC0zMzQsNzguOSIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICBzdHlsZT0iZmlsbDojODVjZTI2O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDEzMjMuOCwyOTguNDEgYyA0MS43NCwtMzIuMDkgOTIuODMsLTQ5LjU5IDE0NC45OCwtNDkuNTkgMTMyLjI1LDAgMjM5LjgxLDEwNy41NTkgMjM5LjgxLDIzOS44MjEgMCwyOS4xNiAtNC44OCw1Ny4xNjggLTE0LjUzLDgzLjQxOCBsIC0zMDQuMDgsNzEuMTYgLTY2LjE4LC0zNDQuODA5IiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjYiCiAgICAgICAgIHN0eWxlPSJmaWxsOiMzMTc3YTc7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMTM4NS42Nyw3MjIuOTMgMzM0Ljc2LC03OC4zMDEgYyAxMzYuMDIsNDQuOTYxIDIzMC41NiwxNzUuMzUxIDIzMC41NiwzMTguNzYyIDAsMTM5LjMzOSAtODYuNTQsMjYzLjg1OSAtMjE2LjM4LDMxMy4wMzkgbCAtNDM3Ljg0LC0zODMuNTkgODguOSwtMTY5LjkxIiAvPjwvZz48L2c+PC9zdmc+"
/>
</div>
<div
className="euiCard__content"
>
<span
className="euiTitle euiTitle--small euiCard__title"
id="generated-idTitle"
>
<button
aria-describedby=" generated-idDescription"
className="euiCard__titleButton"
onClick={[Function]}
>
Custom Element 2
</button>
</span>
<div
className="euiText euiText--small euiCard__description"
id="generated-idDescription"
>
<p>
Aenean eu justo auctor, placerat felis non, scelerisque dolor.
</p>
</div>
</div>
<div
className="euiCard__footer"
/>
</div>
<div
className="euiFlexGroup euiFlexGroup--gutterExtraSmall euiFlexGroup--justifyContentSpaceBetween euiFlexGroup--directionRow euiFlexGroup--responsive canvasElementCard__controls"
>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<button
aria-label="Edit element"
className="euiButtonIcon euiButtonIcon--primary"
data-test-subj="canvasElementCard__editButton"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="pencil"
size="m"
/>
</button>
</span>
</div>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<button
aria-label="Delete element"
className="euiButtonIcon euiButtonIcon--danger"
data-test-subj="canvasElementCard__deleteButton"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="trash"
size="m"
/>
</button>
</span>
</div>
</div>
</div>
<div
className="euiFlexItem canvasElementCard__wrapper"
>
<div
className="euiCard euiCard--leftAligned euiCard--isClickable canvasElementCard"
onClick={[Function]}
>
<div
className="euiCard__top"
>
<img
alt=""
className="euiCard__image"
src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmlld0JveD0iMCAwIDI3MC42MDAwMSAyNjkuNTQ2NjYiCiAgIGhlaWdodD0iMjY5LjU0NjY2IgogICB3aWR0aD0iMjcwLjYwMDAxIgogICB4bWw6c3BhY2U9InByZXNlcnZlIgogICBpZD0ic3ZnMiIKICAgdmVyc2lvbj0iMS4xIj48bWV0YWRhdGEKICAgICBpZD0ibWV0YWRhdGE4Ij48cmRmOlJERj48Y2M6V29yawogICAgICAgICByZGY6YWJvdXQ9IiI+PGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+PGRjOnR5cGUKICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPjwvY2M6V29yaz48L3JkZjpSREY+PC9tZXRhZGF0YT48ZGVmcwogICAgIGlkPSJkZWZzNiIgLz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMzMzMzMzMywwLDAsLTEuMzMzMzMzMywwLDI2OS41NDY2NykiCiAgICAgaWQ9ImcxMCI+PGcKICAgICAgIHRyYW5zZm9ybT0ic2NhbGUoMC4xKSIKICAgICAgIGlkPSJnMTIiPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMTQiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNmZmZmZmY7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMjAyOS40OCw5NjIuNDQxIGMgMCwxNzAuMDk5IC0xMDUuNDYsMzE4Ljc5OSAtMjY0LjE3LDM3Ni42NTkgNi45OCwzNS44NiAxMC42Miw3MS43MSAxMC42MiwxMDkuMDUgMCwzMTYuMTkgLTI1Ny4yNCw1NzMuNDMgLTU3My40Nyw1NzMuNDMgLTE4NC43MiwwIC0zNTYuNTU4LC04OC41OSAtNDY0LjUzLC0yMzcuODUgLTUzLjA5LDQxLjE4IC0xMTguMjg1LDYzLjc1IC0xODYuMzA1LDYzLjc1IC0xNjcuODM2LDAgLTMwNC4zODMsLTEzNi41NCAtMzA0LjM4MywtMzA0LjM4IDAsLTM3LjA4IDYuNjE3LC03Mi41OCAxOS4wMzEsLTEwNi4wOCBDIDEwOC40ODgsMTM4MC4wOSAwLDEyMjcuODkgMCwxMDU4Ljg4IDAsODg3LjkxIDEwNS45NzcsNzM4LjUzOSAyNjUuMzk4LDY4MS4wOSBjIC02Ljc2OSwtMzUuNDQyIC0xMC40NiwtNzIuMDIgLTEwLjQ2LC0xMDkgQyAyNTQuOTM4LDI1Ni42MjEgNTExLjU2NiwwIDgyNy4wMjcsMCAxMDEyLjIsMCAxMTgzLjk0LDg4Ljk0MTQgMTI5MS4zLDIzOC44MzIgYyA1My40NSwtNDEuOTYxIDExOC44LC02NC45OTIgMTg2LjU2LC02NC45OTIgMTY3LjgzLDAgMzA0LjM4LDEzNi40OTIgMzA0LjM4LDMwNC4zMzIgMCwzNy4wNzggLTYuNjIsNzIuNjI5IC0xOS4wMywxMDYuMTI5IDE1Ny43OCw1Ni44NzkgMjY2LjI3LDIwOS4xMjkgMjY2LjI3LDM3OC4xNCIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDE2IgogICAgICAgICBzdHlsZT0iZmlsbDojZmFjZjA5O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDc5Ny44OTgsMTE1MC45MyA0NDQuMDcyLC0yMDIuNDUgNDQ4LjA1LDM5Mi41OCBjIDYuNDksMzIuMzkgOS42Niw2NC42NyA5LjY2LDk4LjQ2IDAsMjc2LjIzIC0yMjQuNjgsNTAwLjk1IC01MDAuOSw1MDAuOTUgLTE2NS4yNCwwIC0zMTkuMzcsLTgxLjM2IC00MTMuMDUzLC0yMTcuNzkgbCAtNzQuNTI0LC0zODYuNjQgODYuNjk1LC0xODUuMTEiIC8+PHBhdGgKICAgICAgICAgaWQ9InBhdGgxOCIKICAgICAgICAgc3R5bGU9ImZpbGw6IzQ5YzFhZTtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIKICAgICAgICAgZD0ibSAzMzguMjIzLDY4MC42NzIgYyAtNi40ODksLTMyLjM4MyAtOS44MDksLTY1Ljk4MSAtOS44MDksLTk5Ljk3MyAwLC0yNzYuOTI5IDIyNS4zMzYsLTUwMi4yNTc2IDUwMi4zMTMsLTUwMi4yNTc2IDE2Ni41OTMsMCAzMjEuNDczLDgyLjExNzYgNDE1LjAxMywyMTkuOTQ5NiBsIDczLjk3LDM4NS4zNDcgLTk4LjcyLDE4OC42MjEgTCA3NzUuMTU2LDEwNzUuNTcgMzM4LjIyMyw2ODAuNjcyIiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjAiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNlZjI5OWI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMzM1LjQxLDE0NDkuMTggMzA0LjMzMiwtNzEuODYgNjYuNjgsMzQ2LjAyIGMgLTQxLjU4NiwzMS43OCAtOTIuOTMsNDkuMTggLTE0NS43MzEsNDkuMTggLTEzMi4yNSwwIC0yMzkuODEyLC0xMDcuNjEgLTIzOS44MTIsLTIzOS44NyAwLC0yOS4yMSA0Ljg3OSwtNTcuMjIgMTQuNTMxLC04My40NyIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDIyIgogICAgICAgICBzdHlsZT0iZmlsbDojNGNhYmU0O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJNIDMwOC45OTIsMTM3Ni43IEMgMTczLjAyLDEzMzEuNjQgNzguNDgwNSwxMjAxLjMgNzguNDgwNSwxMDU3LjkzIDc4LjQ4MDUsOTE4LjM0IDE2NC44Miw3OTMuNjggMjk0LjQwNiw3NDQuMzUyIGwgNDI2Ljk4MSwzODUuOTM4IC03OC4zOTUsMTY3LjUxIC0zMzQsNzguOSIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICBzdHlsZT0iZmlsbDojODVjZTI2O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDEzMjMuOCwyOTguNDEgYyA0MS43NCwtMzIuMDkgOTIuODMsLTQ5LjU5IDE0NC45OCwtNDkuNTkgMTMyLjI1LDAgMjM5LjgxLDEwNy41NTkgMjM5LjgxLDIzOS44MjEgMCwyOS4xNiAtNC44OCw1Ny4xNjggLTE0LjUzLDgzLjQxOCBsIC0zMDQuMDgsNzEuMTYgLTY2LjE4LC0zNDQuODA5IiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjYiCiAgICAgICAgIHN0eWxlPSJmaWxsOiMzMTc3YTc7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMTM4NS42Nyw3MjIuOTMgMzM0Ljc2LC03OC4zMDEgYyAxMzYuMDIsNDQuOTYxIDIzMC41NiwxNzUuMzUxIDIzMC41NiwzMTguNzYyIDAsMTM5LjMzOSAtODYuNTQsMjYzLjg1OSAtMjE2LjM4LDMxMy4wMzkgbCAtNDM3Ljg0LC0zODMuNTkgODguOSwtMTY5LjkxIiAvPjwvZz48L2c+PC9zdmc+"
/>
</div>
<div
className="euiCard__content"
>
<span
className="euiTitle euiTitle--small euiCard__title"
id="generated-idTitle"
>
<button
aria-describedby=" generated-idDescription"
className="euiCard__titleButton"
onClick={[Function]}
>
Custom Element 3
</button>
</span>
<div
className="euiText euiText--small euiCard__description"
id="generated-idDescription"
>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce lobortis aliquet arcu ut turpis duis.
</p>
</div>
</div>
<div
className="euiCard__footer"
/>
</div>
<div
className="euiFlexGroup euiFlexGroup--gutterExtraSmall euiFlexGroup--justifyContentSpaceBetween euiFlexGroup--directionRow euiFlexGroup--responsive canvasElementCard__controls"
>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<button
aria-label="Edit element"
className="euiButtonIcon euiButtonIcon--primary"
data-test-subj="canvasElementCard__editButton"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="pencil"
size="m"
/>
</button>
</span>
</div>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<button
aria-label="Delete element"
className="euiButtonIcon euiButtonIcon--danger"
data-test-subj="canvasElementCard__deleteButton"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="trash"
size="m"
/>
</button>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div
className="euiModalFooter"
>
<button
className="euiButton euiButton--primary euiButton--small"
data-test-subj="saved-elements-modal-close-button"
onClick={[Function]}
type="button"
>
<span
className="euiButton__content"
>
<span
className="euiButton__text"
>
Close
</span>
</span>
</button>
</div>
</div>
</div>
</div>,
<div
data-focus-guard={true}
style={
Object {
"height": "0px",
"left": "1px",
"overflow": "hidden",
"padding": 0,
"position": "fixed",
"top": "1px",
"width": "1px",
}
}
tabIndex={0}
/>,
]
`;
exports[`Storyshots components/SavedElementsModal with text filter 1`] = `
Array [
<div
data-focus-guard={true}
style={
Object {
"height": "0px",
"left": "1px",
"overflow": "hidden",
"padding": 0,
"position": "fixed",
"top": "1px",
"width": "1px",
}
}
tabIndex={0}
/>,
<div
data-focus-guard={true}
style={
Object {
"height": "0px",
"left": "1px",
"overflow": "hidden",
"padding": 0,
"position": "fixed",
"top": "1px",
"width": "1px",
}
}
tabIndex={1}
/>,
<div
data-focus-lock-disabled={false}
onBlur={[Function]}
onFocus={[Function]}
>
<div
className="euiModal canvasModal--fixedSize"
onKeyDown={[Function]}
style={
Object {
"maxWidth": "1000px",
}
}
tabIndex={0}
>
<button
aria-label="Closes this modal window"
className="euiButtonIcon euiButtonIcon--text euiModal__closeIcon"
onClick={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="cross"
size="m"
/>
</button>
<div
className="euiModal__flex"
>
<div
className="euiModalHeader canvasAssetManager__modalHeader"
>
<div
className="euiModalHeader__title canvasAssetManager__modalHeaderTitle"
>
My elements
</div>
</div>
<div
className="euiModalBody"
style={
Object {
"paddingRight": "1px",
}
}
>
<div
className="euiModalBody__overflow"
>
<div
className="euiFormControlLayout euiFormControlLayout--fullWidth"
>
<div
className="euiFormControlLayout__childrenWrapper"
>
<input
className="euiFieldSearch euiFieldSearch--fullWidth"
onChange={[Function]}
onKeyUp={[Function]}
placeholder="Find element"
type="search"
value="Element 2"
/>
<div
className="euiFormControlLayoutIcons"
>
<span
className="euiFormControlLayoutCustomIcon"
>
<div
aria-hidden="true"
className="euiFormControlLayoutCustomIcon__icon"
data-euiicon-type="search"
/>
</span>
</div>
<div
className="euiFormControlLayoutIcons euiFormControlLayoutIcons--right"
>
<button
aria-label="Clear input"
className="euiFormControlLayoutClearButton"
onClick={[Function]}
type="button"
>
<div
className="euiFormControlLayoutClearButton__icon"
data-euiicon-type="cross"
/>
</button>
</div>
</div>
</div>
<div
className="euiSpacer euiSpacer--l"
/>
<div
className="euiFlexGrid euiFlexGrid--gutterLarge euiFlexGrid--fourths euiFlexGrid--responsive"
>
<div
className="euiFlexItem canvasElementCard__wrapper"
>
<div
className="euiCard euiCard--leftAligned euiCard--isClickable canvasElementCard"
onClick={[Function]}
>
<div
className="euiCard__top"
>
<img
alt=""
className="euiCard__image"
src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmlld0JveD0iMCAwIDI3MC42MDAwMSAyNjkuNTQ2NjYiCiAgIGhlaWdodD0iMjY5LjU0NjY2IgogICB3aWR0aD0iMjcwLjYwMDAxIgogICB4bWw6c3BhY2U9InByZXNlcnZlIgogICBpZD0ic3ZnMiIKICAgdmVyc2lvbj0iMS4xIj48bWV0YWRhdGEKICAgICBpZD0ibWV0YWRhdGE4Ij48cmRmOlJERj48Y2M6V29yawogICAgICAgICByZGY6YWJvdXQ9IiI+PGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+PGRjOnR5cGUKICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPjwvY2M6V29yaz48L3JkZjpSREY+PC9tZXRhZGF0YT48ZGVmcwogICAgIGlkPSJkZWZzNiIgLz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMzMzMzMzMywwLDAsLTEuMzMzMzMzMywwLDI2OS41NDY2NykiCiAgICAgaWQ9ImcxMCI+PGcKICAgICAgIHRyYW5zZm9ybT0ic2NhbGUoMC4xKSIKICAgICAgIGlkPSJnMTIiPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMTQiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNmZmZmZmY7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMjAyOS40OCw5NjIuNDQxIGMgMCwxNzAuMDk5IC0xMDUuNDYsMzE4Ljc5OSAtMjY0LjE3LDM3Ni42NTkgNi45OCwzNS44NiAxMC42Miw3MS43MSAxMC42MiwxMDkuMDUgMCwzMTYuMTkgLTI1Ny4yNCw1NzMuNDMgLTU3My40Nyw1NzMuNDMgLTE4NC43MiwwIC0zNTYuNTU4LC04OC41OSAtNDY0LjUzLC0yMzcuODUgLTUzLjA5LDQxLjE4IC0xMTguMjg1LDYzLjc1IC0xODYuMzA1LDYzLjc1IC0xNjcuODM2LDAgLTMwNC4zODMsLTEzNi41NCAtMzA0LjM4MywtMzA0LjM4IDAsLTM3LjA4IDYuNjE3LC03Mi41OCAxOS4wMzEsLTEwNi4wOCBDIDEwOC40ODgsMTM4MC4wOSAwLDEyMjcuODkgMCwxMDU4Ljg4IDAsODg3LjkxIDEwNS45NzcsNzM4LjUzOSAyNjUuMzk4LDY4MS4wOSBjIC02Ljc2OSwtMzUuNDQyIC0xMC40NiwtNzIuMDIgLTEwLjQ2LC0xMDkgQyAyNTQuOTM4LDI1Ni42MjEgNTExLjU2NiwwIDgyNy4wMjcsMCAxMDEyLjIsMCAxMTgzLjk0LDg4Ljk0MTQgMTI5MS4zLDIzOC44MzIgYyA1My40NSwtNDEuOTYxIDExOC44LC02NC45OTIgMTg2LjU2LC02NC45OTIgMTY3LjgzLDAgMzA0LjM4LDEzNi40OTIgMzA0LjM4LDMwNC4zMzIgMCwzNy4wNzggLTYuNjIsNzIuNjI5IC0xOS4wMywxMDYuMTI5IDE1Ny43OCw1Ni44NzkgMjY2LjI3LDIwOS4xMjkgMjY2LjI3LDM3OC4xNCIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDE2IgogICAgICAgICBzdHlsZT0iZmlsbDojZmFjZjA5O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDc5Ny44OTgsMTE1MC45MyA0NDQuMDcyLC0yMDIuNDUgNDQ4LjA1LDM5Mi41OCBjIDYuNDksMzIuMzkgOS42Niw2NC42NyA5LjY2LDk4LjQ2IDAsMjc2LjIzIC0yMjQuNjgsNTAwLjk1IC01MDAuOSw1MDAuOTUgLTE2NS4yNCwwIC0zMTkuMzcsLTgxLjM2IC00MTMuMDUzLC0yMTcuNzkgbCAtNzQuNTI0LC0zODYuNjQgODYuNjk1LC0xODUuMTEiIC8+PHBhdGgKICAgICAgICAgaWQ9InBhdGgxOCIKICAgICAgICAgc3R5bGU9ImZpbGw6IzQ5YzFhZTtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIKICAgICAgICAgZD0ibSAzMzguMjIzLDY4MC42NzIgYyAtNi40ODksLTMyLjM4MyAtOS44MDksLTY1Ljk4MSAtOS44MDksLTk5Ljk3MyAwLC0yNzYuOTI5IDIyNS4zMzYsLTUwMi4yNTc2IDUwMi4zMTMsLTUwMi4yNTc2IDE2Ni41OTMsMCAzMjEuNDczLDgyLjExNzYgNDE1LjAxMywyMTkuOTQ5NiBsIDczLjk3LDM4NS4zNDcgLTk4LjcyLDE4OC42MjEgTCA3NzUuMTU2LDEwNzUuNTcgMzM4LjIyMyw2ODAuNjcyIiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjAiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNlZjI5OWI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMzM1LjQxLDE0NDkuMTggMzA0LjMzMiwtNzEuODYgNjYuNjgsMzQ2LjAyIGMgLTQxLjU4NiwzMS43OCAtOTIuOTMsNDkuMTggLTE0NS43MzEsNDkuMTggLTEzMi4yNSwwIC0yMzkuODEyLC0xMDcuNjEgLTIzOS44MTIsLTIzOS44NyAwLC0yOS4yMSA0Ljg3OSwtNTcuMjIgMTQuNTMxLC04My40NyIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDIyIgogICAgICAgICBzdHlsZT0iZmlsbDojNGNhYmU0O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJNIDMwOC45OTIsMTM3Ni43IEMgMTczLjAyLDEzMzEuNjQgNzguNDgwNSwxMjAxLjMgNzguNDgwNSwxMDU3LjkzIDc4LjQ4MDUsOTE4LjM0IDE2NC44Miw3OTMuNjggMjk0LjQwNiw3NDQuMzUyIGwgNDI2Ljk4MSwzODUuOTM4IC03OC4zOTUsMTY3LjUxIC0zMzQsNzguOSIgLz48cGF0aAogICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICBzdHlsZT0iZmlsbDojODVjZTI2O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIgogICAgICAgICBkPSJtIDEzMjMuOCwyOTguNDEgYyA0MS43NCwtMzIuMDkgOTIuODMsLTQ5LjU5IDE0NC45OCwtNDkuNTkgMTMyLjI1LDAgMjM5LjgxLDEwNy41NTkgMjM5LjgxLDIzOS44MjEgMCwyOS4xNiAtNC44OCw1Ny4xNjggLTE0LjUzLDgzLjQxOCBsIC0zMDQuMDgsNzEuMTYgLTY2LjE4LC0zNDQuODA5IiAvPjxwYXRoCiAgICAgICAgIGlkPSJwYXRoMjYiCiAgICAgICAgIHN0eWxlPSJmaWxsOiMzMTc3YTc7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiCiAgICAgICAgIGQ9Im0gMTM4NS42Nyw3MjIuOTMgMzM0Ljc2LC03OC4zMDEgYyAxMzYuMDIsNDQuOTYxIDIzMC41NiwxNzUuMzUxIDIzMC41NiwzMTguNzYyIDAsMTM5LjMzOSAtODYuNTQsMjYzLjg1OSAtMjE2LjM4LDMxMy4wMzkgbCAtNDM3Ljg0LC0zODMuNTkgODguOSwtMTY5LjkxIiAvPjwvZz48L2c+PC9zdmc+"
/>
</div>
<div
className="euiCard__content"
>
<span
className="euiTitle euiTitle--small euiCard__title"
id="generated-idTitle"
>
<button
aria-describedby=" generated-idDescription"
className="euiCard__titleButton"
onClick={[Function]}
>
Custom Element 2
</button>
</span>
<div
className="euiText euiText--small euiCard__description"
id="generated-idDescription"
>
<p>
Aenean eu justo auctor, placerat felis non, scelerisque dolor.
</p>
</div>
</div>
<div
className="euiCard__footer"
/>
</div>
<div
className="euiFlexGroup euiFlexGroup--gutterExtraSmall euiFlexGroup--justifyContentSpaceBetween euiFlexGroup--directionRow euiFlexGroup--responsive canvasElementCard__controls"
>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<button
aria-label="Edit element"
className="euiButtonIcon euiButtonIcon--primary"
data-test-subj="canvasElementCard__editButton"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="pencil"
size="m"
/>
</button>
</span>
</div>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<button
aria-label="Delete element"
className="euiButtonIcon euiButtonIcon--danger"
data-test-subj="canvasElementCard__deleteButton"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="trash"
size="m"
/>
</button>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div
className="euiModalFooter"
>
<button
className="euiButton euiButton--primary euiButton--small"
data-test-subj="saved-elements-modal-close-button"
onClick={[Function]}
type="button"
>
<span
className="euiButton__content"
>
<span
className="euiButton__text"
>
Close
</span>
</span>
</button>
</div>
</div>
</div>
</div>,
<div
data-focus-guard={true}
style={
Object {
"height": "0px",
"left": "1px",
"overflow": "hidden",
"padding": 0,
"position": "fixed",
"top": "1px",
"width": "1px",
}
}
tabIndex={0}
/>,
]
`;

View file

@ -9,7 +9,7 @@ import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions'; import { action } from '@storybook/addon-actions';
import { ElementControls } from '../element_controls'; import { ElementControls } from '../element_controls';
storiesOf('components/Elements/ElementControls', module) storiesOf('components/SavedElementsModal/ElementControls', module)
.addDecorator(story => ( .addDecorator(story => (
<div <div
style={{ style={{

View file

@ -8,9 +8,9 @@ import React from 'react';
import { storiesOf } from '@storybook/react'; import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions'; import { action } from '@storybook/addon-actions';
import { ElementGrid } from '../element_grid'; import { ElementGrid } from '../element_grid';
import { testElements, testCustomElements } from './fixtures/test_elements'; import { testCustomElements } from './fixtures/test_elements';
storiesOf('components/Elements/ElementGrid', module) storiesOf('components/SavedElementsModal/ElementGrid', module)
.addDecorator(story => ( .addDecorator(story => (
<div <div
style={{ style={{
@ -20,38 +20,19 @@ storiesOf('components/Elements/ElementGrid', module)
{story()} {story()}
</div> </div>
)) ))
.add('without controls', () => ( .add('default', () => (
<ElementGrid elements={testElements} handleClick={action('addElement')} />
))
.add('with controls', () => (
<ElementGrid <ElementGrid
elements={testCustomElements} elements={testCustomElements}
handleClick={action('addCustomElement')} onClick={action('addCustomElement')}
showControls
onDelete={action('onDelete')} onDelete={action('onDelete')}
onEdit={action('onEdit')} onEdit={action('onEdit')}
/> />
)) ))
.add('with text filter', () => ( .add('with text filter', () => (
<ElementGrid
elements={testElements}
handleClick={action('addCustomElement')}
filterText="table"
/>
))
.add('with tags filter', () => (
<ElementGrid
elements={testElements}
handleClick={action('addCustomElement')}
filterTags={['graphic']}
/>
))
.add('with controls and filter', () => (
<ElementGrid <ElementGrid
elements={testCustomElements} elements={testCustomElements}
handleClick={action('addCustomElement')} onClick={action('addCustomElement')}
filterText="Lorem" filterText="table"
showControls
onDelete={action('onDelete')} onDelete={action('onDelete')}
onEdit={action('onEdit')} onEdit={action('onEdit')}
/> />

View file

@ -6,41 +6,6 @@
import { elasticLogo } from '../../../../lib/elastic_logo'; import { elasticLogo } from '../../../../lib/elastic_logo';
export const testElements = [
{
name: 'areaChart',
displayName: 'Area chart',
help: 'A line chart with a filled body',
tags: ['chart'],
image: elasticLogo,
expression: `filters
| demodata
| pointseries x="time" y="mean(price)"
| plot defaultStyle={seriesStyle lines=1 fill=1}
| render`,
},
{
name: 'image',
displayName: 'Image',
help: 'A static image',
tags: ['graphic'],
image: elasticLogo,
expression: `image dataurl=null mode="contain"
| render`,
},
{
name: 'table',
displayName: 'Data table',
tags: ['text'],
help: 'A scrollable grid for displaying data in a tabular format',
image: elasticLogo,
expression: `filters
| demodata
| table
| render`,
},
];
export const testCustomElements = [ export const testCustomElements = [
{ {
id: 'custom-element-10d625f5-1342-47c9-8f19-d174ea6b65d5', id: 'custom-element-10d625f5-1342-47c9-8f19-d174ea6b65d5',

View file

@ -0,0 +1,50 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { SavedElementsModal } from '../saved_elements_modal';
import { testCustomElements } from './fixtures/test_elements';
import { CustomElement } from '../../../../types';
storiesOf('components/SavedElementsModal', module)
.add('no custom elements', () => (
<SavedElementsModal
customElements={[] as CustomElement[]}
search=""
setSearch={action('setSearch')}
onClose={action('onClose')}
addCustomElement={action('addCustomElement')}
findCustomElements={action('findCustomElements')}
updateCustomElement={action('updateCustomElement')}
removeCustomElement={action('removeCustomElement')}
/>
))
.add('with custom elements', () => (
<SavedElementsModal
customElements={testCustomElements}
search=""
setSearch={action('setSearch')}
onClose={action('onClose')}
addCustomElement={action('addCustomElement')}
findCustomElements={action('findCustomElements')}
updateCustomElement={action('updateCustomElement')}
removeCustomElement={action('removeCustomElement')}
/>
))
.add('with text filter', () => (
<SavedElementsModal
customElements={testCustomElements}
search="Element 2"
onClose={action('onClose')}
setSearch={action('setSearch')}
addCustomElement={action('addCustomElement')}
findCustomElements={action('findCustomElements')}
updateCustomElement={action('updateCustomElement')}
removeCustomElement={action('removeCustomElement')}
/>
));

View file

@ -30,7 +30,12 @@ export const ElementControls: FunctionComponent<Props> = ({ onDelete, onEdit })
> >
<EuiFlexItem grow={false}> <EuiFlexItem grow={false}>
<EuiToolTip content={strings.getEditTooltip()}> <EuiToolTip content={strings.getEditTooltip()}>
<EuiButtonIcon iconType="pencil" aria-label={strings.getEditAriaLabel()} onClick={onEdit} /> <EuiButtonIcon
iconType="pencil"
aria-label={strings.getEditAriaLabel()}
onClick={onEdit}
data-test-subj="canvasElementCard__editButton"
/>
</EuiToolTip> </EuiToolTip>
</EuiFlexItem> </EuiFlexItem>
<EuiFlexItem grow={false}> <EuiFlexItem grow={false}>
@ -40,6 +45,7 @@ export const ElementControls: FunctionComponent<Props> = ({ onDelete, onEdit })
iconType="trash" iconType="trash"
aria-label={strings.getDeleteAriaLabel()} aria-label={strings.getDeleteAriaLabel()}
onClick={onDelete} onClick={onDelete}
data-test-subj="canvasElementCard__deleteButton"
/> />
</EuiToolTip> </EuiToolTip>
</EuiFlexItem> </EuiFlexItem>

View file

@ -0,0 +1,81 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
import PropTypes from 'prop-types';
import { map } from 'lodash';
import { EuiFlexItem, EuiFlexGrid } from '@elastic/eui';
import { ElementControls } from './element_controls';
import { CustomElement } from '../../../types';
import { ElementCard } from '../element_card';
export interface Props {
/**
* list of elements to generate cards for
*/
elements: CustomElement[];
/**
* text to filter out cards
*/
filterText: string;
/**
* handler invoked when clicking a card
*/
onClick: (element: CustomElement) => void;
/**
* click handler for the edit button
*/
onEdit: (element: CustomElement) => void;
/**
* click handler for the delete button
*/
onDelete: (element: CustomElement) => void;
}
export const ElementGrid = ({ elements, filterText, onClick, onEdit, onDelete }: Props) => {
filterText = filterText.toLowerCase();
return (
<EuiFlexGrid gutterSize="l" columns={4}>
{map(elements, (element: CustomElement, index) => {
const { name, displayName = '', help = '', image } = element;
const whenClicked = () => onClick(element);
if (
filterText.length &&
!name.toLowerCase().includes(filterText) &&
!displayName.toLowerCase().includes(filterText) &&
!help.toLowerCase().includes(filterText)
) {
return null;
}
return (
<EuiFlexItem key={index} className="canvasElementCard__wrapper">
<ElementCard
title={displayName || name}
description={help}
image={image}
onClick={whenClicked}
/>
<ElementControls onEdit={() => onEdit(element)} onDelete={() => onDelete(element)} />
</EuiFlexItem>
);
})}
</EuiFlexGrid>
);
};
ElementGrid.propTypes = {
elements: PropTypes.array.isRequired,
filterText: PropTypes.string.isRequired,
onClick: PropTypes.func.isRequired,
onEdit: PropTypes.func.isRequired,
onDelete: PropTypes.func.isRequired,
};
ElementGrid.defaultProps = {
filterText: '',
};

View file

@ -0,0 +1,128 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
import { compose, withState } from 'recompose';
import { camelCase } from 'lodash';
// @ts-ignore Untyped local
import { cloneSubgraphs } from '../../lib/clone_subgraphs';
import * as customElementService from '../../lib/custom_element_service';
// @ts-ignore Untyped local
import { notify } from '../../lib/notify';
// @ts-ignore Untyped local
import { selectToplevelNodes } from '../../state/actions/transient';
// @ts-ignore Untyped local
import { insertNodes } from '../../state/actions/elements';
import { getSelectedPage } from '../../state/selectors/workpad';
import { trackCanvasUiMetric, METRIC_TYPE } from '../../lib/ui_metric';
import { SavedElementsModal as Component, Props as ComponentProps } from './saved_elements_modal';
import { State, PositionedElement, CustomElement } from '../../../types';
const customElementAdded = 'elements-custom-added';
interface OwnProps {
onClose: () => void;
}
interface OwnPropsWithState extends OwnProps {
customElements: CustomElement[];
setCustomElements: (customElements: CustomElement[]) => void;
search: string;
setSearch: (search: string) => void;
}
interface DispatchProps {
selectToplevelNodes: (nodes: PositionedElement[]) => void;
insertNodes: (selectedNodes: PositionedElement[], pageId: string) => void;
}
interface StateProps {
pageId: string;
}
const mapStateToProps = (state: State): StateProps => ({
pageId: getSelectedPage(state),
});
const mapDispatchToProps = (dispatch: Dispatch): DispatchProps => ({
selectToplevelNodes: (nodes: PositionedElement[]) =>
dispatch(
selectToplevelNodes(
nodes
.filter((e: PositionedElement): boolean => !e.position.parent)
.map((e: PositionedElement): string => e.id)
)
),
insertNodes: (selectedNodes: PositionedElement[], pageId: string) =>
dispatch(insertNodes(selectedNodes, pageId)),
});
const mergeProps = (
stateProps: StateProps,
dispatchProps: DispatchProps,
ownProps: OwnPropsWithState
): ComponentProps => {
const { pageId } = stateProps;
const { onClose, search, setCustomElements } = ownProps;
const findCustomElements = async () => {
const { customElements } = await customElementService.find(search);
setCustomElements(customElements);
};
return {
...ownProps,
// add custom element to the page
addCustomElement: (customElement: CustomElement) => {
const { selectedNodes = [] } = JSON.parse(customElement.content) || {};
const clonedNodes = selectedNodes && cloneSubgraphs(selectedNodes);
if (clonedNodes) {
dispatchProps.insertNodes(clonedNodes, pageId); // first clone and persist the new node(s)
dispatchProps.selectToplevelNodes(clonedNodes); // then select the cloned node(s)
}
onClose();
trackCanvasUiMetric(METRIC_TYPE.LOADED, customElementAdded);
},
// custom element search
findCustomElements: async (text?: string) => {
try {
await findCustomElements();
} catch (err) {
notify.error(err, { title: `Couldn't find custom elements` });
}
},
// remove custom element
removeCustomElement: async (id: string) => {
try {
await customElementService.remove(id);
await findCustomElements();
} catch (err) {
notify.error(err, { title: `Couldn't delete custom elements` });
}
},
// update custom element
updateCustomElement: async (id: string, name: string, description: string, image: string) => {
try {
await customElementService.update(id, {
name: camelCase(name),
displayName: name,
image,
help: description,
});
await findCustomElements();
} catch (err) {
notify.error(err, { title: `Couldn't update custom elements` });
}
},
};
};
export const SavedElementsModal = compose<ComponentProps, OwnProps>(
withState('search', 'setSearch', ''),
withState('customElements', 'setCustomElements', []),
connect(mapStateToProps, mapDispatchToProps, mergeProps)
)(Component);

View file

@ -0,0 +1,217 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import React, { Fragment, ChangeEvent, FunctionComponent, useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import {
EuiModal,
EuiModalBody,
EuiModalFooter,
EuiModalHeader,
EuiModalHeaderTitle,
EuiEmptyPrompt,
EuiFieldSearch,
EuiSpacer,
EuiOverlayMask,
EuiButton,
} from '@elastic/eui';
import { map, sortBy } from 'lodash';
import { ComponentStrings } from '../../../i18n';
import { CustomElement } from '../../../types';
import { ConfirmModal } from '../confirm_modal/confirm_modal';
import { CustomElementModal } from '../custom_element_modal';
import { ElementGrid } from './element_grid';
const { SavedElementsModal: strings } = ComponentStrings;
export interface Props {
/**
* Adds the custom element to the workpad
*/
addCustomElement: (customElement: CustomElement) => void;
/**
* Queries ES for custom element saved objects
*/
findCustomElements: () => void;
/**
* Handler invoked when the modal closes
*/
onClose: () => void;
/**
* Deletes the custom element
*/
removeCustomElement: (id: string) => void;
/**
* Saved edits to the custom element
*/
updateCustomElement: (id: string, name: string, description: string, image: string) => void;
/**
* Array of custom elements to display
*/
customElements: CustomElement[];
/**
* Text used to filter custom elements list
*/
search: string;
/**
* Setter for search text
*/
setSearch: (search: string) => void;
}
export const SavedElementsModal: FunctionComponent<Props> = ({
search,
setSearch,
customElements,
addCustomElement,
findCustomElements,
onClose,
removeCustomElement,
updateCustomElement,
}) => {
const [elementToDelete, setElementToDelete] = useState<CustomElement | null>(null);
const [elementToEdit, setElementToEdit] = useState<CustomElement | null>(null);
useEffect(() => {
findCustomElements();
});
const showEditModal = (element: CustomElement) => setElementToEdit(element);
const hideEditModal = () => setElementToEdit(null);
const handleEdit = async (name: string, description: string, image: string) => {
if (elementToEdit) {
await updateCustomElement(elementToEdit.id, name, description, image);
}
hideEditModal();
};
const showDeleteModal = (element: CustomElement) => setElementToDelete(element);
const hideDeleteModal = () => setElementToDelete(null);
const handleDelete = async () => {
if (elementToDelete) {
await removeCustomElement(elementToDelete.id);
}
hideDeleteModal();
};
const renderEditModal = () => {
if (!elementToEdit) {
return null;
}
return (
<EuiOverlayMask>
<CustomElementModal
title={strings.getEditElementTitle()}
name={elementToEdit.displayName}
description={elementToEdit.help}
image={elementToEdit.image}
onSave={handleEdit}
onCancel={hideEditModal}
/>
</EuiOverlayMask>
);
};
const renderDeleteModal = () => {
if (!elementToDelete) {
return null;
}
return (
<ConfirmModal
isOpen
title={strings.getDeleteElementTitle(elementToDelete.displayName)}
message={strings.getDeleteElementDescription()}
confirmButtonText={strings.getDeleteButtonLabel()}
cancelButtonText={strings.getCancelButtonLabel()}
onConfirm={handleDelete}
onCancel={hideDeleteModal}
/>
);
};
const sortElements = (elements: CustomElement[]): CustomElement[] =>
sortBy(
map(elements, (element, name) => ({ name, ...element })),
'displayName'
);
const onSearch = (e: ChangeEvent<HTMLInputElement>) => setSearch(e.target.value);
let customElementContent = (
<EuiEmptyPrompt
iconType="vector"
title={<h2>{strings.getAddNewElementTitle()}</h2>}
body={<p>{strings.getAddNewElementDescription()}</p>}
titleSize="s"
/>
);
if (customElements.length) {
customElementContent = (
<ElementGrid
elements={sortElements(customElements)}
filterText={search}
onClick={addCustomElement}
onEdit={showEditModal}
onDelete={showDeleteModal}
/>
);
}
return (
<Fragment>
<EuiOverlayMask>
<EuiModal
onClose={onClose}
className="canvasModal--fixedSize"
maxWidth="1000px"
initialFocus=".canvasElements__filter input"
>
<EuiModalHeader className="canvasAssetManager__modalHeader">
<EuiModalHeaderTitle className="canvasAssetManager__modalHeaderTitle">
{strings.getModalTitle()}
</EuiModalHeaderTitle>
</EuiModalHeader>
<EuiModalBody style={{ paddingRight: '1px' }}>
<EuiFieldSearch
fullWidth
value={search}
placeholder={strings.getFindElementPlaceholder()}
onChange={onSearch}
/>
<EuiSpacer />
{customElementContent}
</EuiModalBody>
<EuiModalFooter>
<EuiButton
size="s"
onClick={onClose}
data-test-subj="saved-elements-modal-close-button"
>
{strings.getSavedElementsModalCloseButtonLabel()}
</EuiButton>
</EuiModalFooter>
</EuiModal>
</EuiOverlayMask>
{renderDeleteModal()}
{renderEditModal()}
</Fragment>
);
};
SavedElementsModal.propTypes = {
addCustomElement: PropTypes.func.isRequired,
findCustomElements: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired,
removeCustomElement: PropTypes.func.isRequired,
updateCustomElement: PropTypes.func.isRequired,
};

View file

@ -37,6 +37,7 @@ exports[`Storyshots components/Sidebar/SidebarHeader default 1`] = `
<button <button
aria-label="Save as new element" aria-label="Save as new element"
className="euiButtonIcon euiButtonIcon--text" className="euiButtonIcon euiButtonIcon--text"
data-test-subj="canvasSidebarHeader__saveElementButton"
onBlur={[Function]} onBlur={[Function]}
onClick={[Function]} onClick={[Function]}
onFocus={[Function]} onFocus={[Function]}
@ -97,7 +98,7 @@ exports[`Storyshots components/Sidebar/SidebarHeader default 1`] = `
</div> </div>
`; `;
exports[`Storyshots components/Sidebar/SidebarHeader without layer controls 1`] = ` exports[`Storyshots components/Sidebar/SidebarHeader with layer controls 1`] = `
<div <div
style={ style={
Object { Object {
@ -123,6 +124,106 @@ exports[`Storyshots components/Sidebar/SidebarHeader without layer controls 1`]
<div <div
className="euiFlexGroup euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow euiFlexGroup--responsive" className="euiFlexGroup euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow euiFlexGroup--responsive"
> >
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<button
aria-label="Move element to top layer"
className="euiButtonIcon euiButtonIcon--text"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="sortUp"
size="m"
/>
</button>
</span>
</div>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<button
aria-label="Move element up one layer"
className="euiButtonIcon euiButtonIcon--text"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="arrowUp"
size="m"
/>
</button>
</span>
</div>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<button
aria-label="Move element down one layer"
className="euiButtonIcon euiButtonIcon--text"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="arrowDown"
size="m"
/>
</button>
</span>
</div>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
className="euiToolTipAnchor"
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<button
aria-label="Move element to bottom layer"
className="euiButtonIcon euiButtonIcon--text"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
type="button"
>
<div
aria-hidden="true"
className="euiButtonIcon__icon"
data-euiicon-type="sortDown"
size="m"
/>
</button>
</span>
</div>
<div <div
className="euiFlexItem euiFlexItem--flexGrowZero" className="euiFlexItem euiFlexItem--flexGrowZero"
> >
@ -134,6 +235,7 @@ exports[`Storyshots components/Sidebar/SidebarHeader without layer controls 1`]
<button <button
aria-label="Save as new element" aria-label="Save as new element"
className="euiButtonIcon euiButtonIcon--text" className="euiButtonIcon euiButtonIcon--text"
data-test-subj="canvasSidebarHeader__saveElementButton"
onBlur={[Function]} onBlur={[Function]}
onClick={[Function]} onClick={[Function]}
onFocus={[Function]} onFocus={[Function]}

View file

@ -35,6 +35,6 @@ const handlers = {
storiesOf('components/Sidebar/SidebarHeader', module) storiesOf('components/Sidebar/SidebarHeader', module)
.addDecorator(story => <div style={{ width: '300px' }}>{story()}</div>) .addDecorator(story => <div style={{ width: '300px' }}>{story()}</div>)
.add('default', () => <SidebarHeader title="Selected layer" {...handlers} />) .add('default', () => <SidebarHeader title="Selected layer" {...handlers} />)
.add('without layer controls', () => ( .add('with layer controls', () => (
<SidebarHeader title="Grouped element" showLayerControls={false} {...handlers} /> <SidebarHeader title="Grouped element" showLayerControls={true} {...handlers} />
)); ));

View file

@ -22,8 +22,7 @@ import { CustomElementModal } from '../custom_element_modal';
import { ToolTipShortcut } from '../tool_tip_shortcut/'; import { ToolTipShortcut } from '../tool_tip_shortcut/';
import { ComponentStrings } from '../../../i18n/components'; import { ComponentStrings } from '../../../i18n/components';
import { ShortcutStrings } from '../../../i18n/shortcuts'; import { ShortcutStrings } from '../../../i18n/shortcuts';
import { CONTEXT_MENU_TOP_BORDER_CLASSNAME } from '../../../common/lib/constants';
const topBorderClassName = 'canvasContextMenu--topBorder';
const { SidebarHeader: strings } = ComponentStrings; const { SidebarHeader: strings } = ComponentStrings;
const shortcutHelp = ShortcutStrings.getShortcutHelp(); const shortcutHelp = ShortcutStrings.getShortcutHelp();
@ -282,7 +281,11 @@ export class SidebarHeader extends Component<Props, State> {
const { bringToFront, bringForward, sendBackward, sendToBack } = this.props; const { bringToFront, bringForward, sendBackward, sendToBack } = this.props;
return { return {
menuItem: { name: strings.getOrderMenuItemLabel(), className: topBorderClassName, panel: 1 }, menuItem: {
name: strings.getOrderMenuItemLabel(),
className: CONTEXT_MENU_TOP_BORDER_CLASSNAME,
panel: 1,
},
panel: { panel: {
id: 1, id: 1,
title: strings.getOrderMenuItemLabel(), title: strings.getOrderMenuItemLabel(),
@ -396,7 +399,7 @@ export class SidebarHeader extends Component<Props, State> {
? [ ? [
{ {
name: strings.getUngroupMenuItemLabel(), name: strings.getUngroupMenuItemLabel(),
className: topBorderClassName, className: CONTEXT_MENU_TOP_BORDER_CLASSNAME,
onClick: close(ungroupNodes), onClick: close(ungroupNodes),
}, },
] ]
@ -404,7 +407,7 @@ export class SidebarHeader extends Component<Props, State> {
? [ ? [
{ {
name: strings.getGroupMenuItemLabel(), name: strings.getGroupMenuItemLabel(),
className: topBorderClassName, className: CONTEXT_MENU_TOP_BORDER_CLASSNAME,
onClick: close(groupNodes), onClick: close(groupNodes),
}, },
] ]
@ -483,7 +486,7 @@ export class SidebarHeader extends Component<Props, State> {
items.push({ items.push({
name: strings.getSaveElementMenuItemLabel(), name: strings.getSaveElementMenuItemLabel(),
icon: 'indexOpen', icon: 'indexOpen',
className: topBorderClassName, className: CONTEXT_MENU_TOP_BORDER_CLASSNAME,
onClick: this._showModal, onClick: this._showModal,
}); });
@ -537,6 +540,7 @@ export class SidebarHeader extends Component<Props, State> {
color="text" color="text"
iconType="indexOpen" iconType="indexOpen"
onClick={this._showModal} onClick={this._showModal}
data-test-subj="canvasSidebarHeader__saveElementButton"
aria-label={strings.getSaveElementMenuItemLabel()} aria-label={strings.getSaveElementMenuItemLabel()}
/> />
</EuiToolTip> </EuiToolTip>

View file

@ -6,7 +6,7 @@
import React, { MouseEventHandler } from 'react'; import React, { MouseEventHandler } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { EuiFlexGroup, EuiFlexItem, EuiButtonIcon, EuiToolTip } from '@elastic/eui'; import { EuiFlexGroup, EuiFlexItem, EuiButtonEmpty } from '@elastic/eui';
// @ts-ignore untyped local // @ts-ignore untyped local
import { Popover } from '../../popover'; import { Popover } from '../../popover';
import { AutoRefreshControls } from './auto_refresh_controls'; import { AutoRefreshControls } from './auto_refresh_controls';
@ -39,16 +39,16 @@ export const ControlSettings = ({
}; };
const popoverButton = (handleClick: MouseEventHandler<HTMLButtonElement>) => ( const popoverButton = (handleClick: MouseEventHandler<HTMLButtonElement>) => (
<EuiToolTip position="bottom" content={strings.getTooltip()}> <EuiButtonEmpty size="xs" aria-label={strings.getButtonLabel()} onClick={handleClick}>
<EuiButtonIcon iconType="gear" aria-label={strings.getTooltip()} onClick={handleClick} /> {strings.getButtonLabel()}
</EuiToolTip> </EuiButtonEmpty>
); );
return ( return (
<Popover <Popover
id="auto-refresh-popover" id="auto-refresh-popover"
button={popoverButton} button={popoverButton}
anchorPosition="rightUp" anchorPosition="downLeft"
panelClassName="canvasControlSettings__popover" panelClassName="canvasControlSettings__popover"
> >
{() => ( {() => (

View file

@ -0,0 +1,41 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Storyshots components/WorkpadHeader/ElementMenu default 1`] = `
<div
className="euiPopover euiPopover--anchorDownLeft"
container={null}
onKeyDown={[Function]}
onMouseDown={[Function]}
onMouseUp={[Function]}
onTouchEnd={[Function]}
onTouchStart={[Function]}
>
<div
className="euiPopover__anchor"
>
<button
aria-label="Add an element"
className="euiButton euiButton--primary euiButton--small canvasElementMenu__popoverButton euiButton--fill"
data-test-subj="add-element-button"
onClick={[Function]}
type="button"
>
<span
className="euiButton__content"
>
<div
aria-hidden="true"
className="euiButton__icon"
data-euiicon-type="plusInCircle"
size="m"
/>
<span
className="euiButton__text"
>
Add element
</span>
</span>
</button>
</div>
</div>
`;

View file

@ -0,0 +1,150 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import React from 'react';
import { ElementSpec } from '../../../../../types';
import { ElementMenu } from '../element_menu';
const testElements: { [key: string]: ElementSpec } = {
areaChart: {
name: 'areaChart',
displayName: 'Area chart',
help: 'A line chart with a filled body',
type: 'chart',
expression: `filters
| demodata
| pointseries x="time" y="mean(price)"
| plot defaultStyle={seriesStyle lines=1 fill=1}
| render`,
},
debug: {
name: 'debug',
displayName: 'Debug data',
help: 'Just dumps the configuration of the element',
icon: 'bug',
expression: `demodata
| render as=debug`,
},
dropdownFilter: {
name: 'dropdownFilter',
displayName: 'Dropdown select',
type: 'filter',
help: 'A dropdown from which you can select values for an "exactly" filter',
icon: 'filter',
height: 50,
expression: `demodata
| dropdownControl valueColumn=project filterColumn=project | render`,
filter: '',
},
filterDebug: {
name: 'filterDebug',
displayName: 'Debug filter',
help: 'Shows the underlying global filters in a workpad',
icon: 'bug',
expression: `filters
| render as=debug`,
},
image: {
name: 'image',
displayName: 'Image',
help: 'A static image',
type: 'image',
expression: `image dataurl=null mode="contain"
| render`,
},
markdown: {
name: 'markdown',
displayName: 'Text',
type: 'text',
help: 'Add text using Markdown',
icon: 'visText',
expression: `filters
| demodata
| markdown "### Welcome to the Markdown element
Good news! You're already connected to some demo data!
The data table contains
**{{rows.length}} rows**, each containing
the following columns:
{{#each columns}}
**{{name}}**
{{/each}}
You can use standard Markdown in here, but you can also access your piped-in data using Handlebars. If you want to know more, check out the [Handlebars documentation](https://handlebarsjs.com/guide/expressions.html).
#### Enjoy!" | render`,
},
progressGauge: {
name: 'progressGauge',
displayName: 'Gauge',
type: 'progress',
help: 'Displays progress as a portion of a gauge',
width: 200,
height: 200,
icon: 'visGoal',
expression: `filters
| demodata
| math "mean(percent_uptime)"
| progress shape="gauge" label={formatnumber 0%} font={font size=24 family="Helvetica" color="#000000" align=center}
| render`,
},
revealImage: {
name: 'revealImage',
displayName: 'Image reveal',
type: 'image',
help: 'Reveals a percentage of an image',
expression: `filters
| demodata
| math "mean(percent_uptime)"
| revealImage origin=bottom image=null
| render`,
},
shape: {
name: 'shape',
displayName: 'Shape',
type: 'shape',
help: 'A customizable shape',
width: 200,
height: 200,
icon: 'node',
expression:
'shape "square" fill="#4cbce4" border="rgba(255,255,255,0)" borderWidth=0 maintainAspect=false | render',
},
table: {
name: 'table',
displayName: 'Data table',
type: 'chart',
help: 'A scrollable grid for displaying data in a tabular format',
expression: `filters
| demodata
| table
| render`,
},
timeFilter: {
name: 'timeFilter',
displayName: 'Time filter',
type: 'filter',
help: 'Set a time window',
icon: 'calendar',
height: 50,
expression: `timefilterControl compact=true column=@timestamp
| render`,
filter: 'timefilter column=@timestamp from=now-24h to=now',
},
};
const mockRenderEmbedPanel = () => <div id="embeddablePanel" />;
storiesOf('components/WorkpadHeader/ElementMenu', module).add('default', () => (
<ElementMenu
elements={testElements}
addElement={action('addElement')}
renderEmbedPanel={mockRenderEmbedPanel}
/>
));

View file

@ -0,0 +1,3 @@
.canvasElementMenu__popoverButton {
margin-right: $euiSizeS;
}

View file

@ -0,0 +1,216 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { sortBy } from 'lodash';
import React, { Fragment, FunctionComponent, useState } from 'react';
import PropTypes from 'prop-types';
import {
EuiButton,
EuiContextMenu,
EuiIcon,
EuiContextMenuPanelItemDescriptor,
} from '@elastic/eui';
import { CONTEXT_MENU_TOP_BORDER_CLASSNAME } from '../../../../common/lib';
import { ComponentStrings } from '../../../../i18n/components';
import { ElementSpec } from '../../../../types';
import { flattenPanelTree } from '../../../lib/flatten_panel_tree';
import { getId } from '../../../lib/get_id';
import { Popover, ClosePopoverFn } from '../../popover';
// @ts-ignore Untyped local
import { AssetManager } from '../../asset_manager';
import { SavedElementsModal } from '../../saved_elements_modal';
interface CategorizedElementLists {
[key: string]: ElementSpec[];
}
interface ElementTypeMeta {
[key: string]: { name: string; icon: string };
}
export const { WorkpadHeaderElementMenu: strings } = ComponentStrings;
// label and icon for the context menu item for each element type
const elementTypeMeta: ElementTypeMeta = {
chart: { name: strings.getChartMenuItemLabel(), icon: 'visArea' },
filter: { name: strings.getFilterMenuItemLabel(), icon: 'filter' },
image: { name: strings.getImageMenuItemLabel(), icon: 'image' },
other: { name: strings.getOtherMenuItemLabel(), icon: 'empty' },
progress: { name: strings.getProgressMenuItemLabel(), icon: 'visGoal' },
shape: { name: strings.getShapeMenuItemLabel(), icon: 'node' },
text: { name: strings.getTextMenuItemLabel(), icon: 'visText' },
};
const getElementType = (element: ElementSpec): string =>
element && element.type && Object.keys(elementTypeMeta).includes(element.type)
? element.type
: 'other';
const categorizeElementsByType = (elements: ElementSpec[]): { [key: string]: ElementSpec[] } => {
elements = sortBy(elements, 'displayName');
const categories: CategorizedElementLists = { other: [] };
elements.forEach((element: ElementSpec) => {
const type = getElementType(element);
if (categories[type]) {
categories[type].push(element);
} else {
categories[type] = [element];
}
});
return categories;
};
export interface Props {
/**
* Dictionary of elements from elements registry
*/
elements: { [key: string]: ElementSpec };
/**
* Handler for adding a selected element to the workpad
*/
addElement: (element: ElementSpec) => void;
/**
* Renders embeddable flyout
*/
renderEmbedPanel: (onClose: () => void) => JSX.Element;
}
export const ElementMenu: FunctionComponent<Props> = ({
elements,
addElement,
renderEmbedPanel,
}) => {
const [isAssetModalVisible, setAssetModalVisible] = useState(false);
const [isEmbedPanelVisible, setEmbedPanelVisible] = useState(false);
const [isSavedElementsModalVisible, setSavedElementsModalVisible] = useState(false);
const hideAssetModal = () => setAssetModalVisible(false);
const showAssetModal = () => setAssetModalVisible(true);
const showEmbedPanel = () => setEmbedPanelVisible(false);
const hideEmbedPanel = () => setEmbedPanelVisible(false);
const hideSavedElementsModal = () => setSavedElementsModalVisible(false);
const showSavedElementsModal = () => setSavedElementsModalVisible(true);
const {
chart: chartElements,
filter: filterElements,
image: imageElements,
other: otherElements,
progress: progressElements,
shape: shapeElements,
text: textElements,
} = categorizeElementsByType(Object.values(elements));
const getPanelTree = (closePopover: ClosePopoverFn) => {
const elementToMenuItem = (element: ElementSpec): EuiContextMenuPanelItemDescriptor => ({
name: element.displayName || element.name,
icon: element.icon,
onClick: () => {
addElement(element);
closePopover();
},
});
const elementListToMenuItems = (elementList: ElementSpec[]) => {
const type = getElementType(elementList[0]);
const { name, icon } = elementTypeMeta[type] || elementTypeMeta.other;
if (elementList.length > 1) {
return {
name,
icon: <EuiIcon type={icon} size="m" />,
panel: {
id: getId('element-type'),
title: name,
items: elementList.map(elementToMenuItem),
},
};
}
return elementToMenuItem(elementList[0]);
};
return {
id: 0,
title: strings.getElementMenuLabel(),
items: [
elementListToMenuItems(textElements),
elementListToMenuItems(shapeElements),
elementListToMenuItems(chartElements),
elementListToMenuItems(imageElements),
elementListToMenuItems(filterElements),
elementListToMenuItems(progressElements),
elementListToMenuItems(otherElements),
{
name: strings.getMyElementsMenuItemLabel(),
className: CONTEXT_MENU_TOP_BORDER_CLASSNAME,
'data-test-subj': 'saved-elements-menu-option',
icon: <EuiIcon type="empty" size="m" />,
onClick: () => {
showSavedElementsModal();
closePopover();
},
},
{
name: strings.getAssetsMenuItemLabel(),
icon: <EuiIcon type="empty" size="m" />,
onClick: () => {
showAssetModal();
closePopover();
},
},
{
name: strings.getEmbedObjectMenuItemLabel(),
className: CONTEXT_MENU_TOP_BORDER_CLASSNAME,
icon: <EuiIcon type="logoKibana" size="m" />,
onClick: () => {
showEmbedPanel();
closePopover();
},
},
],
};
};
const exportControl = (togglePopover: React.MouseEventHandler<any>) => (
<EuiButton
fill
iconType="plusInCircle"
size="s"
aria-label={strings.getElementMenuLabel()}
onClick={togglePopover}
className="canvasElementMenu__popoverButton"
data-test-subj="add-element-button"
>
{strings.getElementMenuButtonLabel()}
</EuiButton>
);
return (
<Fragment>
<Popover button={exportControl} panelPaddingSize="none" anchorPosition="downLeft">
{({ closePopover }: { closePopover: ClosePopoverFn }) => (
<EuiContextMenu
initialPanelId={0}
panels={flattenPanelTree(getPanelTree(closePopover))}
/>
)}
</Popover>
{isAssetModalVisible ? <AssetManager onClose={hideAssetModal} /> : null}
{isEmbedPanelVisible ? renderEmbedPanel(hideEmbedPanel) : null}
{isSavedElementsModalVisible ? <SavedElementsModal onClose={hideSavedElementsModal} /> : null}
</Fragment>
);
};
ElementMenu.propTypes = {
elements: PropTypes.object,
addElement: PropTypes.func.isRequired,
};

View file

@ -0,0 +1,49 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
import { connect } from 'react-redux';
import { compose, withProps } from 'recompose';
import { Dispatch } from 'redux';
import { withKibana } from '../../../../../../../../src/plugins/kibana_react/public/';
import { State, ElementSpec } from '../../../../types';
// @ts-ignore Untyped local
import { elementsRegistry } from '../../../lib/elements_registry';
import { ElementMenu as Component, Props as ComponentProps } from './element_menu';
// @ts-ignore Untyped local
import { addElement } from '../../../state/actions/elements';
import { getSelectedPage } from '../../../state/selectors/workpad';
import { AddEmbeddablePanel } from '../../embeddable_flyout';
interface StateProps {
pageId: string;
}
interface DispatchProps {
addElement: (pageId: string) => (partialElement: ElementSpec) => void;
}
const mapStateToProps = (state: State) => ({
pageId: getSelectedPage(state),
});
const mapDispatchToProps = (dispatch: Dispatch) => ({
addElement: (pageId: string) => (element: ElementSpec) => dispatch(addElement(pageId, element)),
});
const mergeProps = (stateProps: StateProps, dispatchProps: DispatchProps) => ({
...stateProps,
...dispatchProps,
addElement: dispatchProps.addElement(stateProps.pageId),
// Moved this section out of the main component to enable stories
renderEmbedPanel: (onClose: () => void) => <AddEmbeddablePanel onClose={onClose} />,
});
export const ElementMenu = compose<ComponentProps, {}>(
connect(mapStateToProps, mapDispatchToProps, mergeProps),
withKibana,
withProps(() => ({ elements: elementsRegistry.toJS() }))
)(Component);

Some files were not shown because too many files have changed in this diff Show more