* expression_reveal_image skeleton. * expression_functions added. * expression_renderers added. * Backup of daily work. * Fixed errors. * Added legacy support. Added button for legacy. * Added storybook. * Removed revealImage from canvas. * Types fixed. * Fixed test suite error. * Fixed eslint error. * Moved UI and elements, related to expressionRevealImage from canvas. * Fixed unused translations errors. * Moved type of element to types. * Fixed types and added service for representing elements, ui and supported renderers to canvas. * Added expression registration to canvas. * Fixed * Fixed mutiple call of the function. * Removed support of a legacy lib for revealImage chart. * Removed legacy presentation_utils plugin import. * Removed useless translations and tried to fix error. * One more fix. * Small imports fix. * Fixed translations. * Made fixes based on nits. * Removed useless params. * fix. * Fixed errors, related to jest and __mocks__. * Removed useless type definition. * Replaced RendererHandlers with IInterpreterRendererHandlers. * fixed supported_shareable. * Moved elements back to canvas. * Moved views to canvas, removed expression service and imported renderer to canvas. * Fixed translations. * Moved libs to presentation utils. * Fixed types and removed function_wrapper.ts * Fixed types of test helpers. * Fixed imports. * One more fix. * Fixed public API. * Moved css to component. * Fixed spaces at element. * Removed unused plugin. * Basic setup of error plugin. * Removed not used `function` files at `error` expression. * Moved related components from canvas. * Changed imports of components. * Removed useless translations and fixed .i18nrc.json * More fixes of i18nrc. * Fixed async functions. Written current code, based on https://github.com/storybookjs/storybook/issues/7745 * Fixed one test with Expression input. After changing the way of rendering in stories, all elements are mounting and componentDidMount is involved. The previous snapshot was without mounted `monaco` editor. * generated plugin and copied code from expression_reveal_image * fixed double import after merge. * Changed all names from reveal_image to shape. * moved shape to plugin and added all necessary configs * Fixed translations, fixed all imports and debug of svg. * `function` moved to `server`. * One shape is rewritten to `React` and rendering is written with passing necessary props. * changed default width and heigth. * Added `ShapeHOC`. * Shapes changed. * small refactor. * Removed useless import. * one more refactor. * Refactor + fix errors + updated limits. * Changed ShapePreview from pure js to react and removed `dangerouslySetInnerHTML` * Fixed types of viewbox. * Changed types source for Shape components. * small refactor. * Fixed imports. * Removed `shape` from `canvas` * Updated docs. * Basic setup of error plugin. * Removed not used `function` files at `error` expression. * Changed imports of components. * Fixed errors, related to shape and autosuggestions. * Fixed i18n for shape. * Moved function from public to common and registered at server. * Fixed types error. * Fixed snapshots and shape mocks. * Moved some libs from `presentations_util` to `expression_shape` * Shape refactored. * Shape picker fixed. * Moved `Popover` back to `canvas` * Removed `Popover` export from presentation_utils components. * Moved error_component and debug_component from presentation_util to expression_error. * Removed `.i18nrc.json`. * Removed `.i18nrc.json`. * Removed useless scss. * Fixed color of `error`. * added fixes of rebase. * More fixes of rebase error . * Removed useless .i18nrc.json file. * More fixes. * More fixes of rebase. * One more fix. * More fixes. * Fixed limits and translations. * Added. * Fixed i18nrc. * Fixed error.. * Moved shapes to async chunks. * One more fix. * Some fixes. * Trying to fix the typecheck error. * Added temp of drawer. * Moved shapes to the async chunk in a less complex way. * Made `ShapeDrawer` reusable among different `expressions`. * Changed type of `shapes` from `any` and `Shape` to `string`. * Made changes, based on nits. * Removed not necessary changes. * Moved all reusable libs to `expression_shapes`. * Reduced the size of the bundle. * Hope, fixed type check errors. * Removed getDefaultShapeData. * Removed `getViewBox` from bundle. # Conflicts: # packages/kbn-optimizer/limits.yml
|
@ -452,6 +452,7 @@ module.exports = {
|
|||
'!(src|x-pack)/plugins/**/(public|server)/mocks/index.{js,mjs,ts}',
|
||||
'!(src|x-pack)/plugins/**/(public|server)/(index|mocks).{js,mjs,ts,tsx}',
|
||||
'!(src|x-pack)/plugins/**/__stories__/index.{js,mjs,ts,tsx}',
|
||||
'!(src|x-pack)/plugins/**/__fixtures__/index.{js,mjs,ts,tsx}',
|
||||
],
|
||||
allowSameFolder: true,
|
||||
errorMessage: 'Plugins may only import from top-level public and server modules.',
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
"expressions": "src/plugins/expressions",
|
||||
"expressionError": "src/plugins/expression_error",
|
||||
"expressionRevealImage": "src/plugins/expression_reveal_image",
|
||||
"expressionShape": "src/plugins/expression_shape",
|
||||
"inputControl": "src/plugins/input_control_vis",
|
||||
"inspector": "src/plugins/inspector",
|
||||
"inspectorViews": "src/legacy/core_plugins/inspector_views",
|
||||
|
|
|
@ -97,6 +97,10 @@ want to incorporate their own functions, types, and renderers into the service
|
|||
for use in their own application.
|
||||
|
||||
|
||||
|{kib-repo}blob/{branch}/src/plugins/expression_shape/README.md[expressionShape]
|
||||
|Expression Shape plugin adds a shape function to the expression plugin and an associated renderer. The renderer will display the given shape with selected decorations.
|
||||
|
||||
|
||||
|{kib-repo}blob/{branch}/src/plugins/home/README.md[home]
|
||||
|Moves the legacy ui/registry/feature_catalogue module for registering "features" that should be shown in the home page's feature catalogue to a service within a "home" plugin. The feature catalogue refered to here should not be confused with the "feature" plugin for registering features used to derive UI capabilities for feature controls.
|
||||
|
||||
|
|
|
@ -113,3 +113,4 @@ pageLoadAssetSize:
|
|||
expressionRevealImage: 25675
|
||||
cases: 144442
|
||||
expressionError: 22127
|
||||
expressionShape: 30033
|
||||
|
|
|
@ -19,6 +19,7 @@ export const storybookAliases = {
|
|||
embeddable: 'src/plugins/embeddable/.storybook',
|
||||
expression_error: 'src/plugins/expression_error/.storybook',
|
||||
expression_reveal_image: 'src/plugins/expression_reveal_image/.storybook',
|
||||
expression_shape: 'src/plugins/expression_shape/.storybook',
|
||||
infra: 'x-pack/plugins/infra/.storybook',
|
||||
security_solution: 'x-pack/plugins/security_solution/.storybook',
|
||||
ui_actions_enhanced: 'x-pack/plugins/ui_actions_enhanced/.storybook',
|
||||
|
|
10
src/plugins/expression_shape/.storybook/main.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line import/no-commonjs
|
||||
module.exports = require('@kbn/storybook').defaultConfig;
|
9
src/plugins/expression_shape/README.md
Executable file
|
@ -0,0 +1,9 @@
|
|||
# expressionShape
|
||||
|
||||
Expression Shape plugin adds a `shape` function to the expression plugin and an associated renderer. The renderer will display the given shape with selected decorations.
|
||||
|
||||
---
|
||||
|
||||
## Development
|
||||
|
||||
See the [kibana contributing guide](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md) for instructions setting up your development environment.
|
12
src/plugins/expression_shape/__fixtures__/function_specs.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { shapeFunction } from '../common/expression_functions';
|
||||
import { ExpressionFunction } from '../../../../src/plugins/expressions';
|
||||
|
||||
export const functionSpecs = [shapeFunction].map((fn) => new ExpressionFunction(fn()));
|
9
src/plugins/expression_shape/__fixtures__/index.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export * from './function_specs';
|
11
src/plugins/expression_shape/common/constants.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export const PLUGIN_ID = 'expressionShape';
|
||||
export const PLUGIN_NAME = 'expressionShape';
|
||||
export const SVG = 'SVG';
|
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export { shapeFunction } from './shape_function';
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { ExpressionShapeFunction, Shape } from '../types';
|
||||
import { SVG } from '../constants';
|
||||
import { getAvailableShapes } from '../lib';
|
||||
|
||||
export const strings = {
|
||||
help: i18n.translate('expressionShape.functions.shapeHelpText', {
|
||||
defaultMessage: 'Creates a shape.',
|
||||
}),
|
||||
args: {
|
||||
shape: i18n.translate('expressionShape.functions.shape.args.shapeHelpText', {
|
||||
defaultMessage: 'Pick a shape.',
|
||||
}),
|
||||
border: i18n.translate('expressionShape.functions.shape.args.borderHelpText', {
|
||||
defaultMessage: 'An {SVG} color for the border outlining the shape.',
|
||||
values: {
|
||||
SVG,
|
||||
},
|
||||
}),
|
||||
borderWidth: i18n.translate('expressionShape.functions.shape.args.borderWidthHelpText', {
|
||||
defaultMessage: 'The thickness of the border.',
|
||||
}),
|
||||
fill: i18n.translate('expressionShape.functions.shape.args.fillHelpText', {
|
||||
defaultMessage: 'An {SVG} color to fill the shape.',
|
||||
values: {
|
||||
SVG,
|
||||
},
|
||||
}),
|
||||
maintainAspect: i18n.translate('expressionShape.functions.shape.args.maintainAspectHelpText', {
|
||||
defaultMessage: `Maintain the shape's original aspect ratio?`,
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
||||
export const errors = {
|
||||
invalidShape: (shape: string) =>
|
||||
new Error(
|
||||
i18n.translate('expressionShape.functions.shape.invalidShapeErrorMessage', {
|
||||
defaultMessage: "Invalid value: '{shape}'. Such a shape doesn't exist.",
|
||||
values: {
|
||||
shape,
|
||||
},
|
||||
})
|
||||
),
|
||||
};
|
||||
|
||||
export const shapeFunction: ExpressionShapeFunction = () => {
|
||||
const { help, args: argHelp } = strings;
|
||||
|
||||
return {
|
||||
name: 'shape',
|
||||
aliases: [],
|
||||
inputTypes: ['null'],
|
||||
help,
|
||||
args: {
|
||||
shape: {
|
||||
types: ['string'],
|
||||
help: argHelp.shape,
|
||||
aliases: ['_'],
|
||||
default: 'square',
|
||||
options: Object.values(Shape),
|
||||
},
|
||||
border: {
|
||||
types: ['string'],
|
||||
aliases: ['stroke'],
|
||||
help: argHelp.border,
|
||||
},
|
||||
borderWidth: {
|
||||
types: ['number'],
|
||||
aliases: ['strokeWidth'],
|
||||
help: argHelp.borderWidth,
|
||||
default: 0,
|
||||
},
|
||||
fill: {
|
||||
types: ['string'],
|
||||
help: argHelp.fill,
|
||||
default: 'black',
|
||||
},
|
||||
maintainAspect: {
|
||||
types: ['boolean'],
|
||||
help: argHelp.maintainAspect,
|
||||
default: false,
|
||||
options: [true, false],
|
||||
},
|
||||
},
|
||||
fn: (input, args) => {
|
||||
const avaliableShapes = getAvailableShapes();
|
||||
if (!avaliableShapes.includes(args.shape)) {
|
||||
throw errors.invalidShape(args.shape);
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'shape',
|
||||
...args,
|
||||
};
|
||||
},
|
||||
};
|
||||
};
|
12
src/plugins/expression_shape/common/index.ts
Executable file
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export * from './constants';
|
||||
export * from './types';
|
||||
|
||||
export { getAvailableShapes } from './lib/available_shapes';
|
11
src/plugins/expression_shape/common/lib/available_shapes.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { Shape } from '../types';
|
||||
|
||||
export const getAvailableShapes = () => Object.values(Shape);
|
10
src/plugins/expression_shape/common/lib/index.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export * from './view_box';
|
||||
export * from './available_shapes';
|
52
src/plugins/expression_shape/common/lib/view_box.ts
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { ParentNodeParams, ViewBoxParams } from '../types';
|
||||
|
||||
export function viewBoxToString(viewBox?: ViewBoxParams): undefined | string {
|
||||
if (!viewBox) return;
|
||||
return `${viewBox?.minX} ${viewBox?.minY} ${viewBox?.width} ${viewBox?.height}`;
|
||||
}
|
||||
|
||||
function getMinxAndWidth(viewBoxParams: ViewBoxParams, { borderOffset, width }: ParentNodeParams) {
|
||||
let { minX, width: shapeWidth } = viewBoxParams;
|
||||
if (width) {
|
||||
const xOffset = (shapeWidth / width) * borderOffset;
|
||||
minX -= xOffset;
|
||||
shapeWidth += xOffset * 2;
|
||||
} else {
|
||||
shapeWidth = 0;
|
||||
}
|
||||
|
||||
return [minX, shapeWidth];
|
||||
}
|
||||
|
||||
function getMinyAndHeight(
|
||||
viewBoxParams: ViewBoxParams,
|
||||
{ borderOffset, height }: ParentNodeParams
|
||||
) {
|
||||
let { minY, height: shapeHeight } = viewBoxParams;
|
||||
if (height) {
|
||||
const yOffset = (shapeHeight / height) * borderOffset;
|
||||
minY -= yOffset;
|
||||
shapeHeight += yOffset * 2;
|
||||
} else {
|
||||
shapeHeight = 0;
|
||||
}
|
||||
|
||||
return [minY, shapeHeight];
|
||||
}
|
||||
|
||||
export function getViewBox(
|
||||
viewBoxParams: ViewBoxParams,
|
||||
parentNodeParams: ParentNodeParams
|
||||
): ViewBoxParams {
|
||||
const [minX, width] = getMinxAndWidth(viewBoxParams, parentNodeParams);
|
||||
const [minY, height] = getMinyAndHeight(viewBoxParams, parentNodeParams);
|
||||
return { minX, minY, width, height };
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
import { ExpressionFunctionDefinition } from 'src/plugins/expressions';
|
||||
|
||||
export enum Shape {
|
||||
ARROW = 'arrow',
|
||||
ARROW_MULTI = 'arrowMulti',
|
||||
BOOKMARK = 'bookmark',
|
||||
CIRCLE = 'circle',
|
||||
CROSS = 'cross',
|
||||
HEXAGON = 'hexagon',
|
||||
KITE = 'kite',
|
||||
PENTAGON = 'pentagon',
|
||||
RHOMBUS = 'rhombus',
|
||||
SEMICIRCLE = 'semicircle',
|
||||
SPEECH_BUBBLE = 'speechBubble',
|
||||
SQUARE = 'square',
|
||||
STAR = 'star',
|
||||
TAG = 'tag',
|
||||
TRIANGLE = 'triangle',
|
||||
TRIANGLE_RIGHT = 'triangleRight',
|
||||
}
|
||||
|
||||
interface Arguments {
|
||||
border: string;
|
||||
borderWidth: number;
|
||||
shape: Shape;
|
||||
fill: string;
|
||||
maintainAspect: boolean;
|
||||
}
|
||||
|
||||
export interface Output extends Arguments {
|
||||
type: 'shape';
|
||||
}
|
||||
|
||||
export type ExpressionShapeFunction = () => ExpressionFunctionDefinition<
|
||||
'shape',
|
||||
number | null,
|
||||
Arguments,
|
||||
Output
|
||||
>;
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
import { Shape } from './expression_functions';
|
||||
|
||||
export type OriginString = 'bottom' | 'left' | 'top' | 'right';
|
||||
export interface ShapeRendererConfig {
|
||||
border: string;
|
||||
borderWidth: number;
|
||||
shape: Shape;
|
||||
fill: string;
|
||||
maintainAspect: boolean;
|
||||
}
|
||||
|
||||
export interface NodeDimensions {
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export interface ParentNodeParams {
|
||||
borderOffset: number;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export interface ViewBoxParams {
|
||||
minX: number;
|
||||
minY: number;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
9
src/plugins/expression_shape/common/types/index.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
export * from './expression_functions';
|
||||
export * from './expression_renderers';
|
13
src/plugins/expression_shape/jest.config.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
preset: '@kbn/test',
|
||||
rootDir: '../../..',
|
||||
roots: ['<rootDir>/src/plugins/expression_shape'],
|
||||
};
|
13
src/plugins/expression_shape/kibana.json
Executable file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"id": "expressionShape",
|
||||
"version": "1.0.0",
|
||||
"kibanaVersion": "kibana",
|
||||
"server": true,
|
||||
"ui": true,
|
||||
"extraPublicDirs": [
|
||||
"common"
|
||||
],
|
||||
"requiredPlugins": ["expressions", "presentationUtil"],
|
||||
"optionalPlugins": [],
|
||||
"requiredBundles": []
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export * from './shape_drawer';
|
||||
export * from './utils';
|
||||
export * from './types';
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import React, { forwardRef, Ref, useImperativeHandle } from 'react';
|
||||
import { ShapeDrawerProps, ShapeRef } from './types';
|
||||
|
||||
function ShapeDrawerComponent(props: ShapeDrawerProps, ref: Ref<ShapeRef>) {
|
||||
const { shapeType, getShape } = props;
|
||||
const Shape = getShape(shapeType);
|
||||
|
||||
if (!Shape) throw new Error("Shape doesn't exist.");
|
||||
|
||||
useImperativeHandle(ref, () => ({ getData: () => Shape.data }), [Shape]);
|
||||
|
||||
return <Shape.Component {...props} />;
|
||||
}
|
||||
|
||||
export const ShapeDrawer = forwardRef(ShapeDrawerComponent);
|
|
@ -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
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { viewBoxToString } from '../../../common/lib';
|
||||
import { ShapeProps, SvgConfig, SvgElementTypes } from './types';
|
||||
|
||||
const getShapeComponent = (svgParams: SvgConfig) =>
|
||||
function Shape({ shapeAttributes, shapeContentAttributes }: ShapeProps) {
|
||||
const { viewBox: initialViewBox, shapeProps, shapeType } = svgParams;
|
||||
|
||||
const viewBox = shapeAttributes?.viewBox
|
||||
? viewBoxToString(shapeAttributes?.viewBox)
|
||||
: viewBoxToString(initialViewBox);
|
||||
|
||||
const SvgContentElement = getShapeContentElement(shapeType);
|
||||
return (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" {...{ ...(shapeAttributes || {}), viewBox }}>
|
||||
<SvgContentElement {...{ ...(shapeContentAttributes || {}), ...shapeProps }} />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
function getShapeContentElement(type?: SvgElementTypes) {
|
||||
switch (type) {
|
||||
case SvgElementTypes.circle:
|
||||
return (props: SvgConfig['shapeProps']) => <circle {...props} />;
|
||||
case SvgElementTypes.rect:
|
||||
return (props: SvgConfig['shapeProps']) => <rect {...props} />;
|
||||
case SvgElementTypes.path:
|
||||
return (props: SvgConfig['shapeProps']) => <path {...props} />;
|
||||
default:
|
||||
return (props: SvgConfig['shapeProps']) => <polygon {...props} />;
|
||||
}
|
||||
}
|
||||
|
||||
export const createShape = (props: SvgConfig) => {
|
||||
return {
|
||||
Component: getShapeComponent(props),
|
||||
data: props,
|
||||
};
|
||||
};
|
||||
|
||||
export type ShapeType = ReturnType<typeof createShape>;
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { Ref, SVGProps } from 'react';
|
||||
import { ViewBoxParams } from '../../../common/types';
|
||||
import type { ShapeType } from './shape_factory';
|
||||
|
||||
export interface ShapeProps {
|
||||
shapeAttributes?: ShapeAttributes;
|
||||
shapeContentAttributes?: ShapeContentAttributes;
|
||||
}
|
||||
|
||||
export enum SvgElementTypes {
|
||||
polygon,
|
||||
circle,
|
||||
rect,
|
||||
path,
|
||||
}
|
||||
|
||||
export interface ShapeAttributes {
|
||||
fill?: SVGProps<SVGElement>['fill'];
|
||||
stroke?: SVGProps<SVGElement>['stroke'];
|
||||
width?: SVGProps<SVGElement>['width'];
|
||||
height?: SVGProps<SVGElement>['height'];
|
||||
viewBox?: ViewBoxParams;
|
||||
overflow?: SVGProps<SVGElement>['overflow'];
|
||||
preserveAspectRatio?: SVGProps<SVGElement>['preserveAspectRatio'];
|
||||
}
|
||||
|
||||
export interface ShapeContentAttributes {
|
||||
strokeWidth?: SVGProps<SVGElement>['strokeWidth'];
|
||||
stroke?: SVGProps<SVGElement>['stroke'];
|
||||
fill?: SVGProps<SVGElement>['fill'];
|
||||
vectorEffect?: SVGProps<SVGElement>['vectorEffect'];
|
||||
strokeMiterlimit?: SVGProps<SVGElement>['strokeMiterlimit'];
|
||||
}
|
||||
|
||||
interface CircleParams {
|
||||
r: SVGProps<SVGCircleElement>['r'];
|
||||
cx: SVGProps<SVGCircleElement>['cx'];
|
||||
cy: SVGProps<SVGCircleElement>['cy'];
|
||||
}
|
||||
|
||||
interface RectParams {
|
||||
x: SVGProps<SVGRectElement>['x'];
|
||||
y: SVGProps<SVGRectElement>['y'];
|
||||
width: SVGProps<SVGRectElement>['width'];
|
||||
height: SVGProps<SVGRectElement>['height'];
|
||||
}
|
||||
|
||||
interface PathParams {
|
||||
d: SVGProps<SVGPathElement>['d'];
|
||||
}
|
||||
|
||||
interface PolygonParams {
|
||||
points?: SVGProps<SVGPolygonElement>['points'];
|
||||
strokeLinejoin?: SVGProps<SVGPolygonElement>['strokeLinejoin'];
|
||||
}
|
||||
|
||||
type SpecificShapeContentAttributes = CircleParams | RectParams | PathParams | PolygonParams;
|
||||
|
||||
export interface SvgConfig {
|
||||
shapeType?: SvgElementTypes;
|
||||
viewBox: ViewBoxParams;
|
||||
shapeProps: ShapeContentAttributes & SpecificShapeContentAttributes;
|
||||
}
|
||||
|
||||
export type ShapeDrawerProps = {
|
||||
shapeType: string;
|
||||
getShape: (shapeType: string) => ShapeType | undefined;
|
||||
ref: Ref<ShapeRef>;
|
||||
} & ShapeProps;
|
||||
|
||||
export interface ShapeRef {
|
||||
getData: () => SvgConfig;
|
||||
}
|
||||
|
||||
export type { ShapeType };
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { SvgConfig } from './types';
|
||||
|
||||
export const getDefaultShapeData = (): SvgConfig => ({
|
||||
viewBox: {
|
||||
minX: 0,
|
||||
minY: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
},
|
||||
shapeProps: {},
|
||||
});
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { lazy } from 'react';
|
||||
|
||||
export const LazyShapeComponent = lazy(() => import('./shape_component'));
|
||||
export const LazyShapeDrawer = lazy(() => import('./shape_drawer'));
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import React, { useState, useEffect, useCallback, RefCallback } from 'react';
|
||||
import { useResizeObserver } from '@elastic/eui';
|
||||
import { withSuspense } from '../../../../presentation_util/public';
|
||||
import {
|
||||
ShapeRef,
|
||||
ShapeAttributes,
|
||||
ShapeContentAttributes,
|
||||
SvgConfig,
|
||||
getDefaultShapeData,
|
||||
} from '../reusable';
|
||||
import { Dimensions, ShapeComponentProps } from './types';
|
||||
import { getViewBox } from '../../../common/lib';
|
||||
import { LazyShapeDrawer } from '../..';
|
||||
|
||||
const ShapeDrawer = withSuspense(LazyShapeDrawer);
|
||||
|
||||
function ShapeComponent({
|
||||
onLoaded,
|
||||
parentNode,
|
||||
shape: shapeType,
|
||||
fill,
|
||||
border,
|
||||
borderWidth,
|
||||
maintainAspect,
|
||||
}: ShapeComponentProps) {
|
||||
const parentNodeDimensions = useResizeObserver(parentNode);
|
||||
const [dimensions, setDimensions] = useState<Dimensions>({
|
||||
width: parentNode.offsetWidth,
|
||||
height: parentNode.offsetHeight,
|
||||
});
|
||||
const [shapeData, setShapeData] = useState<SvgConfig>(getDefaultShapeData());
|
||||
|
||||
useEffect(() => {
|
||||
setDimensions({
|
||||
width: parentNode.offsetWidth,
|
||||
height: parentNode.offsetHeight,
|
||||
});
|
||||
onLoaded();
|
||||
}, [parentNode, parentNodeDimensions, onLoaded]);
|
||||
|
||||
const shapeRef = useCallback<RefCallback<ShapeRef>>((node) => {
|
||||
if (node !== null) setShapeData(node.getData());
|
||||
}, []);
|
||||
|
||||
const strokeWidth = Math.max(borderWidth, 0);
|
||||
|
||||
const shapeContentAttributes: ShapeContentAttributes = {
|
||||
strokeWidth: String(strokeWidth),
|
||||
vectorEffect: 'non-scaling-stroke',
|
||||
strokeMiterlimit: '999',
|
||||
};
|
||||
if (fill) shapeContentAttributes.fill = fill;
|
||||
if (border) shapeContentAttributes.stroke = border;
|
||||
|
||||
const { width, height } = dimensions;
|
||||
|
||||
const shapeAttributes: ShapeAttributes = {
|
||||
width,
|
||||
height,
|
||||
overflow: 'visible',
|
||||
preserveAspectRatio: maintainAspect ? 'xMidYMid meet' : 'none',
|
||||
viewBox: getViewBox(shapeData.viewBox, {
|
||||
borderOffset: strokeWidth,
|
||||
width,
|
||||
height,
|
||||
}),
|
||||
};
|
||||
|
||||
parentNode.style.lineHeight = '0';
|
||||
|
||||
return (
|
||||
<div className="shapeAligner">
|
||||
<ShapeDrawer
|
||||
shapeType={shapeType}
|
||||
shapeContentAttributes={shapeContentAttributes}
|
||||
shapeAttributes={shapeAttributes}
|
||||
ref={shapeRef}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// default export required for React.Lazy
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export { ShapeComponent as default };
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
import React, { Ref } from 'react';
|
||||
import { ShapeDrawer, ShapeRef } from '../reusable';
|
||||
import { getShape } from './shapes';
|
||||
import { ShapeDrawerComponentProps } from './types';
|
||||
|
||||
const ShapeDrawerComponent = React.forwardRef(
|
||||
(props: ShapeDrawerComponentProps, ref: Ref<ShapeRef>) => (
|
||||
<ShapeDrawer {...props} ref={ref} getShape={getShape} />
|
||||
)
|
||||
);
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export { ShapeDrawerComponent as default };
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
import { createShape } from '../../reusable/shape_factory';
|
||||
|
||||
export const Arrow = createShape({
|
||||
viewBox: {
|
||||
minX: 0,
|
||||
minY: 0,
|
||||
width: 100,
|
||||
height: 100,
|
||||
},
|
||||
shapeProps: {
|
||||
points: '0,40 60,40 60,20 95,50 60,80 60,60 0,60',
|
||||
},
|
||||
});
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
import { createShape } from '../../reusable/shape_factory';
|
||||
|
||||
export const ArrowMulti = createShape({
|
||||
viewBox: {
|
||||
minX: 0,
|
||||
minY: 0,
|
||||
width: 100,
|
||||
height: 60,
|
||||
},
|
||||
shapeProps: {
|
||||
points: '5,30 25,10 25,20 75,20 75,10 95,30 75,50 75,40 25,40 25,50',
|
||||
},
|
||||
});
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { createShape } from '../../reusable/shape_factory';
|
||||
|
||||
export const Bookmark = createShape({
|
||||
viewBox: {
|
||||
minX: 0,
|
||||
minY: 0,
|
||||
width: 60,
|
||||
height: 100,
|
||||
},
|
||||
shapeProps: {
|
||||
points: '0,0 60,0 60,95 30,75 0,95 0,0',
|
||||
},
|
||||
});
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { createShape } from '../../reusable/shape_factory';
|
||||
import { SvgElementTypes } from '../../reusable/types';
|
||||
|
||||
export const Circle = createShape({
|
||||
viewBox: {
|
||||
minX: 0,
|
||||
minY: 0,
|
||||
width: 100,
|
||||
height: 100,
|
||||
},
|
||||
shapeProps: {
|
||||
r: '45',
|
||||
cx: '50',
|
||||
cy: '50',
|
||||
},
|
||||
shapeType: SvgElementTypes.circle,
|
||||
});
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { createShape } from '../../reusable/shape_factory';
|
||||
|
||||
export const Cross = createShape({
|
||||
viewBox: {
|
||||
minX: 0,
|
||||
minY: 0,
|
||||
width: 100,
|
||||
height: 100,
|
||||
},
|
||||
shapeProps: {
|
||||
points: '30,0 70,0 70,30 100,30 100,70 70,70 70,100 30,100 30,70 0,70 0,30 30,30',
|
||||
},
|
||||
});
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { createShape } from '../../reusable/shape_factory';
|
||||
|
||||
export const Hexagon = createShape({
|
||||
viewBox: {
|
||||
minX: 0,
|
||||
minY: 0,
|
||||
width: 100,
|
||||
height: 100,
|
||||
},
|
||||
shapeProps: {
|
||||
points:
|
||||
'70.000, 15.359 30.000, 15.359 10.000, 50.000 30.000, 84.641 70.000, 84.641 90.000, 50.000',
|
||||
},
|
||||
});
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { Arrow as arrow } from './arrow';
|
||||
import { ArrowMulti as arrowMulti } from './arrow_multi';
|
||||
import { Bookmark as bookmark } from './bookmark';
|
||||
import { Cross as cross } from './cross';
|
||||
import { Circle as circle } from './circle';
|
||||
import { Hexagon as hexagon } from './hexagon';
|
||||
import { Kite as kite } from './kite';
|
||||
import { Pentagon as pentagon } from './pentagon';
|
||||
import { Rhombus as rhombus } from './rhombus';
|
||||
import { Semicircle as semicircle } from './semicircle';
|
||||
import { SpeechBubble as speechBubble } from './speech_bubble';
|
||||
import { Square as square } from './square';
|
||||
import { Star as star } from './star';
|
||||
import { Tag as tag } from './tag';
|
||||
import { Triangle as triangle } from './triangle';
|
||||
import { TriangleRight as triangleRight } from './triangle_right';
|
||||
import { ShapeType } from '../../reusable';
|
||||
|
||||
const shapes: { [key: string]: ShapeType } = {
|
||||
arrow,
|
||||
arrowMulti,
|
||||
bookmark,
|
||||
cross,
|
||||
circle,
|
||||
hexagon,
|
||||
kite,
|
||||
pentagon,
|
||||
rhombus,
|
||||
semicircle,
|
||||
speechBubble,
|
||||
square,
|
||||
star,
|
||||
tag,
|
||||
triangle,
|
||||
triangleRight,
|
||||
};
|
||||
|
||||
export const getShape = (shapeType: string) => shapes[shapeType];
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { createShape } from '../../reusable/shape_factory';
|
||||
|
||||
export const Kite = createShape({
|
||||
viewBox: {
|
||||
minX: 0,
|
||||
minY: 0,
|
||||
width: 100,
|
||||
height: 150,
|
||||
},
|
||||
shapeProps: {
|
||||
points: '50,10 10,50 50,140 90,50',
|
||||
},
|
||||
});
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { createShape } from '../../reusable/shape_factory';
|
||||
|
||||
export const Pentagon = createShape({
|
||||
viewBox: {
|
||||
minX: 0,
|
||||
minY: 0,
|
||||
width: 100,
|
||||
height: 100,
|
||||
},
|
||||
shapeProps: {
|
||||
points: '50.0000, 14.0000 11.9577, 41.6393 26.4886, 86.3607 73.5114, 86.3607 88.0423, 41.6393',
|
||||
},
|
||||
});
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { createShape } from '../../reusable/shape_factory';
|
||||
|
||||
export const Rhombus = createShape({
|
||||
viewBox: {
|
||||
minX: 0,
|
||||
minY: 0,
|
||||
width: 100,
|
||||
height: 100,
|
||||
},
|
||||
shapeProps: {
|
||||
points: '50,10 10,50 50,90 90,50',
|
||||
},
|
||||
});
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { createShape } from '../../reusable/shape_factory';
|
||||
import { SvgElementTypes } from '../../reusable/types';
|
||||
|
||||
export const Semicircle = createShape({
|
||||
viewBox: {
|
||||
minX: 0,
|
||||
minY: 0,
|
||||
width: 100,
|
||||
height: 100,
|
||||
},
|
||||
shapeProps: {
|
||||
d: 'M 5,50 h 90 A 45 45 180 1 0 5,50 Z',
|
||||
},
|
||||
shapeType: SvgElementTypes.path,
|
||||
});
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { createShape } from '../../reusable/shape_factory';
|
||||
|
||||
export const SpeechBubble = createShape({
|
||||
viewBox: {
|
||||
minX: 0,
|
||||
minY: 0,
|
||||
width: 100,
|
||||
height: 100,
|
||||
},
|
||||
shapeProps: {
|
||||
points: '0,0 100,0 100,70 40,70 20,85 25,70 0,70',
|
||||
strokeLinejoin: 'round',
|
||||
},
|
||||
});
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { createShape } from '../../reusable/shape_factory';
|
||||
import { SvgElementTypes } from '../../reusable/types';
|
||||
|
||||
export const Square = createShape({
|
||||
viewBox: {
|
||||
minX: 0,
|
||||
minY: 0,
|
||||
width: 100,
|
||||
height: 100,
|
||||
},
|
||||
shapeProps: {
|
||||
x: '0',
|
||||
y: '0',
|
||||
width: '100',
|
||||
height: '100',
|
||||
},
|
||||
shapeType: SvgElementTypes.rect,
|
||||
});
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { createShape } from '../../reusable/shape_factory';
|
||||
|
||||
export const Star = createShape({
|
||||
viewBox: {
|
||||
minX: 0,
|
||||
minY: 0,
|
||||
width: 100,
|
||||
height: 100,
|
||||
},
|
||||
shapeProps: {
|
||||
points:
|
||||
'41.183, 37.865 12.652, 37.865 35.734, 54.635 26.917, 81.771 50.000, 65.000 73.265, 81.904 64.266, 54.635 87.348, 37.865 58.817, 37.865 50.07, 10.515',
|
||||
},
|
||||
});
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { createShape } from '../../reusable/shape_factory';
|
||||
|
||||
export const Tag = createShape({
|
||||
viewBox: {
|
||||
minX: 0,
|
||||
minY: 0,
|
||||
width: 100,
|
||||
height: 60,
|
||||
},
|
||||
shapeProps: {
|
||||
points: '0,0 75,0 90,30 75,60 0,60',
|
||||
},
|
||||
});
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { createShape } from '../../reusable/shape_factory';
|
||||
|
||||
export const Triangle = createShape({
|
||||
viewBox: {
|
||||
minX: 0,
|
||||
minY: 0,
|
||||
width: 100,
|
||||
height: 100,
|
||||
},
|
||||
shapeProps: {
|
||||
points: '50.000, 20.000 15.359, 80.000 84.641, 80.000',
|
||||
},
|
||||
});
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { createShape } from '../../reusable/shape_factory';
|
||||
|
||||
export const TriangleRight = createShape({
|
||||
viewBox: {
|
||||
minX: 0,
|
||||
minY: 0,
|
||||
width: 100,
|
||||
height: 100,
|
||||
},
|
||||
shapeProps: {
|
||||
points: '0, 10 0, 100 90, 100',
|
||||
},
|
||||
});
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { IInterpreterRenderHandlers } from '../../../../../../src/plugins/expressions';
|
||||
import { ShapeRendererConfig } from '../../../common/types';
|
||||
import { ShapeDrawerProps } from '../reusable/types';
|
||||
|
||||
export interface ShapeComponentProps extends ShapeRendererConfig {
|
||||
onLoaded: IInterpreterRenderHandlers['done'];
|
||||
parentNode: HTMLElement;
|
||||
}
|
||||
|
||||
export interface Dimensions {
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
export type ShapeDrawerComponentProps = Omit<ShapeDrawerProps, 'getShape'>;
|
|
@ -1,15 +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
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import { shape } from '../';
|
||||
import { Render } from '../../__stories__/render';
|
||||
import { Shape } from '../../../functions/common/shape';
|
||||
import { shapeRenderer as shape } from '../';
|
||||
import { Render } from '../../../../presentation_util/public/__stories__';
|
||||
import { Shape } from '../../../common/types';
|
||||
|
||||
storiesOf('renderers/shape', module).add('default', () => {
|
||||
const config = {
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { shapeRenderer } from './shape_renderer';
|
||||
|
||||
export const renderers = [shapeRenderer];
|
||||
|
||||
export { shapeRenderer };
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { render, unmountComponentAtNode } from 'react-dom';
|
||||
import { I18nProvider } from '@kbn/i18n/react';
|
||||
import { ExpressionRenderDefinition, IInterpreterRenderHandlers } from 'src/plugins/expressions';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { withSuspense } from '../../../presentation_util/public';
|
||||
import { ShapeRendererConfig } from '../../common/types';
|
||||
import { LazyShapeComponent } from '../components/shape';
|
||||
|
||||
const strings = {
|
||||
getDisplayName: () =>
|
||||
i18n.translate('expressionShape.renderer.shape.displayName', {
|
||||
defaultMessage: 'Shape',
|
||||
}),
|
||||
getHelpDescription: () =>
|
||||
i18n.translate('expressionShape.renderer.shape.helpDescription', {
|
||||
defaultMessage: 'Render a basic shape',
|
||||
}),
|
||||
};
|
||||
|
||||
const ShapeComponent = withSuspense(LazyShapeComponent);
|
||||
|
||||
export const shapeRenderer = (): ExpressionRenderDefinition<ShapeRendererConfig> => ({
|
||||
name: 'shape',
|
||||
displayName: strings.getDisplayName(),
|
||||
help: strings.getHelpDescription(),
|
||||
reuseDomNode: true,
|
||||
render: async (
|
||||
domNode: HTMLElement,
|
||||
config: ShapeRendererConfig,
|
||||
handlers: IInterpreterRenderHandlers
|
||||
) => {
|
||||
handlers.onDestroy(() => {
|
||||
unmountComponentAtNode(domNode);
|
||||
});
|
||||
|
||||
render(
|
||||
<I18nProvider>
|
||||
<ShapeComponent onLoaded={handlers.done} {...config} parentNode={domNode} />
|
||||
</I18nProvider>,
|
||||
domNode
|
||||
);
|
||||
},
|
||||
});
|
22
src/plugins/expression_shape/public/index.ts
Executable file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { ExpressionShapePlugin } from './plugin';
|
||||
|
||||
export type { ExpressionShapePluginSetup, ExpressionShapePluginStart } from './plugin';
|
||||
|
||||
export function plugin() {
|
||||
return new ExpressionShapePlugin();
|
||||
}
|
||||
|
||||
export * from './expression_renderers';
|
||||
export { LazyShapeDrawer } from './components/shape';
|
||||
export { getDefaultShapeData } from './components/reusable';
|
||||
export * from './components/shape/types';
|
||||
export * from './components/reusable/types';
|
||||
export * from '../common/types';
|
33
src/plugins/expression_shape/public/plugin.ts
Executable file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { CoreSetup, CoreStart, Plugin } from '../../../core/public';
|
||||
import { ExpressionsStart, ExpressionsSetup } from '../../expressions/public';
|
||||
import { shapeRenderer } from './expression_renderers';
|
||||
|
||||
interface SetupDeps {
|
||||
expressions: ExpressionsSetup;
|
||||
}
|
||||
|
||||
interface StartDeps {
|
||||
expression: ExpressionsStart;
|
||||
}
|
||||
|
||||
export type ExpressionShapePluginSetup = void;
|
||||
export type ExpressionShapePluginStart = void;
|
||||
|
||||
export class ExpressionShapePlugin
|
||||
implements Plugin<ExpressionShapePluginSetup, ExpressionShapePluginStart, SetupDeps, StartDeps> {
|
||||
public setup(core: CoreSetup, { expressions }: SetupDeps): ExpressionShapePluginSetup {
|
||||
expressions.registerRenderer(shapeRenderer);
|
||||
}
|
||||
|
||||
public start(core: CoreStart): ExpressionShapePluginStart {}
|
||||
|
||||
public stop() {}
|
||||
}
|
15
src/plugins/expression_shape/server/index.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { ExpressionShapePlugin } from './plugin';
|
||||
|
||||
export type { ExpressionShapePluginSetup, ExpressionShapePluginStart } from './plugin';
|
||||
|
||||
export function plugin() {
|
||||
return new ExpressionShapePlugin();
|
||||
}
|
33
src/plugins/expression_shape/server/plugin.ts
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { CoreSetup, CoreStart, Plugin } from '../../../core/public';
|
||||
import { ExpressionsServerStart, ExpressionsServerSetup } from '../../expressions/server';
|
||||
import { shapeFunction } from '../common/expression_functions';
|
||||
|
||||
interface SetupDeps {
|
||||
expressions: ExpressionsServerSetup;
|
||||
}
|
||||
|
||||
interface StartDeps {
|
||||
expression: ExpressionsServerStart;
|
||||
}
|
||||
|
||||
export type ExpressionShapePluginSetup = void;
|
||||
export type ExpressionShapePluginStart = void;
|
||||
|
||||
export class ExpressionShapePlugin
|
||||
implements Plugin<ExpressionShapePluginSetup, ExpressionShapePluginStart, SetupDeps, StartDeps> {
|
||||
public setup(core: CoreSetup, { expressions }: SetupDeps): ExpressionShapePluginSetup {
|
||||
expressions.registerFunction(shapeFunction);
|
||||
}
|
||||
|
||||
public start(core: CoreStart): ExpressionShapePluginStart {}
|
||||
|
||||
public stop() {}
|
||||
}
|
22
src/plugins/expression_shape/tsconfig.json
Normal file
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"outDir": "./target/types",
|
||||
"emitDeclarationOnly": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"isolatedModules": true
|
||||
},
|
||||
"include": [
|
||||
"common/**/*",
|
||||
"public/**/*",
|
||||
"server/**/*",
|
||||
"__fixtures__/**/*",
|
||||
],
|
||||
"references": [
|
||||
{ "path": "../../core/tsconfig.json" },
|
||||
{ "path": "../presentation_util/tsconfig.json" },
|
||||
{ "path": "../expressions/tsconfig.json" },
|
||||
]
|
||||
}
|
|
@ -6,7 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import React, { Suspense, ComponentType, ReactElement } from 'react';
|
||||
import React, { Suspense, ComponentType, ReactElement, Ref } from 'react';
|
||||
import { EuiLoadingSpinner, EuiErrorBoundary } from '@elastic/eui';
|
||||
|
||||
/**
|
||||
|
@ -14,16 +14,19 @@ import { EuiLoadingSpinner, EuiErrorBoundary } from '@elastic/eui';
|
|||
* @param Component A component deferred by `React.lazy`
|
||||
* @param fallback A fallback component to render while things load; default is `EuiLoadingSpinner`
|
||||
*/
|
||||
export const withSuspense = <P extends {}>(
|
||||
export const withSuspense = <P extends {}, R = {}>(
|
||||
Component: ComponentType<P>,
|
||||
fallback: ReactElement | null = <EuiLoadingSpinner />
|
||||
) => (props: P) => (
|
||||
<EuiErrorBoundary>
|
||||
<Suspense fallback={fallback}>
|
||||
<Component {...props} />
|
||||
</Suspense>
|
||||
</EuiErrorBoundary>
|
||||
);
|
||||
) =>
|
||||
React.forwardRef((props: P, ref: Ref<R>) => {
|
||||
return (
|
||||
<EuiErrorBoundary>
|
||||
<Suspense fallback={fallback}>
|
||||
<Component {...props} ref={ref} />
|
||||
</Suspense>
|
||||
</EuiErrorBoundary>
|
||||
);
|
||||
});
|
||||
|
||||
export const LazyLabsBeakerButton = React.lazy(() => import('./labs/labs_beaker_button'));
|
||||
|
||||
|
@ -34,3 +37,5 @@ export const LazyDashboardPicker = React.lazy(() => import('./dashboard_picker')
|
|||
export const LazySavedObjectSaveModalDashboard = React.lazy(
|
||||
() => import('./saved_object_save_modal_dashboard')
|
||||
);
|
||||
|
||||
export * from './types';
|
||||
|
|
|
@ -38,6 +38,8 @@ export {
|
|||
withSuspense,
|
||||
} from './components';
|
||||
|
||||
export * from './components/types';
|
||||
|
||||
export {
|
||||
AddFromLibraryButton,
|
||||
PrimaryActionButton,
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
import { functions as browserFns } from '../canvas_plugin_src/functions/browser';
|
||||
import { ExpressionFunction } from '../../../../src/plugins/expressions';
|
||||
import { initFunctions } from '../public/functions';
|
||||
import { functionSpecs as shapeFunctionSpecs } from '../../../../src/plugins/expression_shape/__fixtures__';
|
||||
|
||||
export const functionSpecs = browserFns
|
||||
.concat(...(initFunctions({} as any) as any))
|
||||
.map((fn) => new ExpressionFunction(fn()));
|
||||
.map((fn) => new ExpressionFunction(fn()))
|
||||
.concat(...shapeFunctionSpecs);
|
||||
|
|
|
@ -44,7 +44,6 @@ import { rounddate } from './rounddate';
|
|||
import { rowCount } from './rowCount';
|
||||
import { repeatImage } from './repeat_image';
|
||||
import { seriesStyle } from './seriesStyle';
|
||||
import { shape } from './shape';
|
||||
import { sort } from './sort';
|
||||
import { staticColumn } from './staticColumn';
|
||||
import { string } from './string';
|
||||
|
@ -96,7 +95,6 @@ export const functions = [
|
|||
rounddate,
|
||||
rowCount,
|
||||
seriesStyle,
|
||||
shape,
|
||||
sort,
|
||||
staticColumn,
|
||||
string,
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { ExpressionFunctionDefinition } from 'src/plugins/expressions';
|
||||
import { getFunctionHelp } from '../../../i18n';
|
||||
|
||||
export enum Shape {
|
||||
ARROW = 'arrow',
|
||||
ARROW_MULTI = 'arrowMulti',
|
||||
BOOKMARK = 'bookmark',
|
||||
CIRCLE = 'circle',
|
||||
CROSS = 'cross',
|
||||
HEXAGON = 'hexagon',
|
||||
KITE = 'kite',
|
||||
PENTAGON = 'pentagon',
|
||||
RHOMBUS = 'rhombus',
|
||||
SEMICIRCLE = 'semicircle',
|
||||
SPEECH_BUBBLE = 'speechBubble',
|
||||
SQUARE = 'square',
|
||||
STAR = 'star',
|
||||
TAG = 'tag',
|
||||
TRIANGLE = 'triangle',
|
||||
TRIANGLE_RIGHT = 'triangleRight',
|
||||
}
|
||||
|
||||
interface Arguments {
|
||||
border: string;
|
||||
borderWidth: number;
|
||||
shape: Shape;
|
||||
fill: string;
|
||||
maintainAspect: boolean;
|
||||
}
|
||||
|
||||
export interface Output extends Arguments {
|
||||
type: 'shape';
|
||||
}
|
||||
|
||||
export function shape(): ExpressionFunctionDefinition<'shape', null, Arguments, Output> {
|
||||
const { help, args: argHelp } = getFunctionHelp().shape;
|
||||
|
||||
return {
|
||||
name: 'shape',
|
||||
aliases: [],
|
||||
type: 'shape',
|
||||
inputTypes: ['null'],
|
||||
help,
|
||||
args: {
|
||||
shape: {
|
||||
types: ['string'],
|
||||
help: argHelp.shape,
|
||||
aliases: ['_'],
|
||||
default: 'square',
|
||||
options: Object.values(Shape),
|
||||
},
|
||||
border: {
|
||||
types: ['string'],
|
||||
aliases: ['stroke'],
|
||||
help: argHelp.border,
|
||||
},
|
||||
borderWidth: {
|
||||
types: ['number'],
|
||||
aliases: ['strokeWidth'],
|
||||
help: argHelp.borderWidth,
|
||||
default: 0,
|
||||
},
|
||||
fill: {
|
||||
types: ['string'],
|
||||
help: argHelp.fill,
|
||||
default: 'black',
|
||||
},
|
||||
maintainAspect: {
|
||||
types: ['boolean'],
|
||||
help: argHelp.maintainAspect,
|
||||
default: false,
|
||||
options: [true, false],
|
||||
},
|
||||
},
|
||||
fn: (input, args) => ({
|
||||
type: 'shape',
|
||||
...args,
|
||||
}),
|
||||
};
|
||||
}
|
|
@ -12,7 +12,6 @@ import { pie } from './pie';
|
|||
import { plot } from './plot';
|
||||
import { progress } from './progress';
|
||||
import { repeatImage } from './repeat_image';
|
||||
import { shape } from './shape';
|
||||
import { table } from './table';
|
||||
import { text } from './text';
|
||||
|
||||
|
@ -24,7 +23,6 @@ export const renderFunctions = [
|
|||
plot,
|
||||
progress,
|
||||
repeatImage,
|
||||
shape,
|
||||
table,
|
||||
text,
|
||||
];
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import { revealImageRenderer } from '../../../../../src/plugins/expression_reveal_image/public';
|
||||
import { errorRenderer, debugRenderer } from '../../../../../src/plugins/expression_error/public';
|
||||
import { shapeRenderer } from '../../../../../src/plugins/expression_shape/public';
|
||||
|
||||
export const renderFunctions = [revealImageRenderer, errorRenderer, debugRenderer];
|
||||
export const renderFunctions = [revealImageRenderer, debugRenderer, errorRenderer, shapeRenderer];
|
||||
export const renderFunctionFactories = [];
|
||||
|
|
|
@ -1,91 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { RendererStrings } from '../../../i18n';
|
||||
import { shapes } from './shapes';
|
||||
import { RendererFactory } from '../../../types';
|
||||
import { Output } from '../../functions/common/shape';
|
||||
|
||||
const { shape: strings } = RendererStrings;
|
||||
|
||||
export const shape: RendererFactory<Output> = () => ({
|
||||
name: 'shape',
|
||||
displayName: strings.getDisplayName(),
|
||||
help: strings.getHelpDescription(),
|
||||
reuseDomNode: true,
|
||||
render(domNode, config, handlers) {
|
||||
const { shape: shapeType, fill, border, borderWidth, maintainAspect } = config;
|
||||
|
||||
const parser = new DOMParser();
|
||||
const shapeSvg = parser
|
||||
.parseFromString(shapes[shapeType], 'image/svg+xml')
|
||||
.getElementsByTagName('svg')
|
||||
.item(0)!;
|
||||
|
||||
const shapeContent = shapeSvg.firstElementChild!;
|
||||
|
||||
if (fill) {
|
||||
shapeContent.setAttribute('fill', fill);
|
||||
}
|
||||
if (border) {
|
||||
shapeContent.setAttribute('stroke', border);
|
||||
}
|
||||
const strokeWidth = Math.max(borderWidth, 0);
|
||||
shapeContent.setAttribute('stroke-width', String(strokeWidth));
|
||||
shapeContent.setAttribute('stroke-miterlimit', '999');
|
||||
shapeContent.setAttribute('vector-effect', 'non-scaling-stroke');
|
||||
|
||||
shapeSvg.setAttribute('preserveAspectRatio', maintainAspect ? 'xMidYMid meet' : 'none');
|
||||
shapeSvg.setAttribute('overflow', 'visible');
|
||||
|
||||
const initialViewBox = shapeSvg
|
||||
.getAttribute('viewBox')!
|
||||
.split(' ')
|
||||
.map((v) => parseInt(v, 10));
|
||||
|
||||
const draw = () => {
|
||||
const width = domNode.offsetWidth;
|
||||
const height = domNode.offsetHeight;
|
||||
|
||||
// adjust viewBox based on border width
|
||||
let [minX, minY, shapeWidth, shapeHeight] = initialViewBox;
|
||||
const borderOffset = strokeWidth;
|
||||
|
||||
if (width) {
|
||||
const xOffset = (shapeWidth / width) * borderOffset;
|
||||
minX -= xOffset;
|
||||
shapeWidth += xOffset * 2;
|
||||
} else {
|
||||
shapeWidth = 0;
|
||||
}
|
||||
|
||||
if (height) {
|
||||
const yOffset = (shapeHeight / height) * borderOffset;
|
||||
minY -= yOffset;
|
||||
shapeHeight += yOffset * 2;
|
||||
} else {
|
||||
shapeHeight = 0;
|
||||
}
|
||||
|
||||
shapeSvg.setAttribute('width', String(width));
|
||||
shapeSvg.setAttribute('height', String(height));
|
||||
shapeSvg.setAttribute('viewBox', [minX, minY, shapeWidth, shapeHeight].join(' '));
|
||||
|
||||
const oldShape = domNode.firstElementChild;
|
||||
if (oldShape) {
|
||||
domNode.removeChild(oldShape);
|
||||
}
|
||||
|
||||
domNode.style.lineHeight = '0';
|
||||
domNode.appendChild(shapeSvg);
|
||||
};
|
||||
|
||||
draw();
|
||||
handlers.done();
|
||||
handlers.onResize(draw); // debouncing avoided for fluidity
|
||||
},
|
||||
});
|
|
@ -1,3 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<polygon points="0,40 60,40 60,20 95,50 60,80 60,60 0,60" />
|
||||
</svg>
|
Before Width: | Height: | Size: 132 B |
|
@ -1,3 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 60">
|
||||
<polygon points="5,30 25,10 25,20 75,20 75,10 95,30 75,50 75,40 25,40 25,50" />
|
||||
</svg>
|
Before Width: | Height: | Size: 150 B |
|
@ -1,3 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 100">
|
||||
<polygon points="0,0 60,0 60,95 30,75 0,95 0,0"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 121 B |
|
@ -1,3 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<circle r="45" cx="50" cy="50" />
|
||||
</svg>
|
Before Width: | Height: | Size: 105 B |
|
@ -1,3 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<polygon points="30,0 70,0 70,30 100,30 100,70 70,70 70,100 30,100 30,70 0,70 0,30 30,30"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 163 B |
|
@ -1,3 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<polygon points="70.000, 15.359 30.000, 15.359 10.000, 50.000 30.000, 84.641 70.000, 84.641 90.000, 50.000"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 183 B |
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import arrow from '!!raw-loader!./arrow.svg';
|
||||
import arrowMulti from '!!raw-loader!./arrow_multi.svg';
|
||||
import bookmark from '!!raw-loader!./bookmark.svg';
|
||||
import cross from '!!raw-loader!./cross.svg';
|
||||
import circle from '!!raw-loader!./circle.svg';
|
||||
import hexagon from '!!raw-loader!./hexagon.svg';
|
||||
import kite from '!!raw-loader!./kite.svg';
|
||||
import pentagon from '!!raw-loader!./pentagon.svg';
|
||||
import rhombus from '!!raw-loader!./rhombus.svg';
|
||||
import semicircle from '!!raw-loader!./semicircle.svg';
|
||||
import speechBubble from '!!raw-loader!./speech_bubble.svg';
|
||||
import square from '!!raw-loader!./square.svg';
|
||||
import star from '!!raw-loader!./star.svg';
|
||||
import tag from '!!raw-loader!./tag.svg';
|
||||
import triangle from '!!raw-loader!./triangle.svg';
|
||||
import triangleRight from '!!raw-loader!./triangle_right.svg';
|
||||
|
||||
export const shapes = {
|
||||
arrow,
|
||||
arrowMulti,
|
||||
bookmark,
|
||||
cross,
|
||||
circle,
|
||||
hexagon,
|
||||
kite,
|
||||
pentagon,
|
||||
rhombus,
|
||||
semicircle,
|
||||
speechBubble,
|
||||
square,
|
||||
star,
|
||||
tag,
|
||||
triangle,
|
||||
triangleRight,
|
||||
};
|
|
@ -1,3 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 150">
|
||||
<polygon points="50,10 10,50 50,140 90,50"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 116 B |
|
@ -1,3 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<polygon points="50.0000, 14.0000 11.9577, 41.6393 26.4886, 86.3607 73.5114, 86.3607 88.0423, 41.6393"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 176 B |
|
@ -1,3 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<polygon points="50,10 10,50 50,90 90,50"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 115 B |
|
@ -1,3 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 50">
|
||||
<path d="M 5,50 h 90 A 45 45 180 1 0 5,50 Z"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 117 B |
|
@ -1,3 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<polygon points="0,0 100,0 100,70 40,70 20,85 25,70 0,70" stroke-linejoin="round" />
|
||||
</svg>
|
Before Width: | Height: | Size: 156 B |
|
@ -1,3 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<rect x="0" y="0" width="100" height="100" />
|
||||
</svg>
|
Before Width: | Height: | Size: 118 B |
|
@ -1,3 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<polygon points="41.183, 37.865 12.652, 37.865 35.734, 54.635 26.917, 81.771 50.000, 65.000 73.265, 81.904 64.266, 54.635 87.348, 37.865 58.817, 37.865 50.07, 10.515" />
|
||||
</svg>
|
Before Width: | Height: | Size: 241 B |
|
@ -1,3 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 60">
|
||||
<polygon points="0,0 75,0 90,30 75,60 0,60"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 116 B |
|
@ -1,3 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" >
|
||||
<polygon points="50.000, 20.000 15.359, 80.000 84.641, 80.000"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 137 B |
|
@ -1,3 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" >
|
||||
<polygon points="0, 10 0, 100 90, 100"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 113 B |
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { shapes } from '../../renderers/shape/shapes';
|
||||
import { getAvailableShapes } from '../../../../../../src/plugins/expression_shape/common';
|
||||
import { ViewStrings } from '../../../i18n';
|
||||
|
||||
const { Shape: strings } = ViewStrings;
|
||||
|
@ -21,7 +21,7 @@ export const shape = () => ({
|
|||
displayName: strings.getShapeDisplayName(),
|
||||
argType: 'shape',
|
||||
options: {
|
||||
shapes,
|
||||
shapes: getAvailableShapes(),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { shape } from '../../../canvas_plugin_src/functions/common/shape';
|
||||
import { FunctionHelp } from '../function_help';
|
||||
import { FunctionFactory } from '../../../types';
|
||||
import { SVG } from '../../constants';
|
||||
|
||||
export const help: FunctionHelp<FunctionFactory<typeof shape>> = {
|
||||
help: i18n.translate('xpack.canvas.functions.shapeHelpText', {
|
||||
defaultMessage: 'Creates a shape.',
|
||||
}),
|
||||
args: {
|
||||
shape: i18n.translate('xpack.canvas.functions.shape.args.shapeHelpText', {
|
||||
defaultMessage: 'Pick a shape.',
|
||||
}),
|
||||
border: i18n.translate('xpack.canvas.functions.shape.args.borderHelpText', {
|
||||
defaultMessage: 'An {SVG} color for the border outlining the shape.',
|
||||
values: {
|
||||
SVG,
|
||||
},
|
||||
}),
|
||||
borderWidth: i18n.translate('xpack.canvas.functions.shape.args.borderWidthHelpText', {
|
||||
defaultMessage: 'The thickness of the border.',
|
||||
}),
|
||||
fill: i18n.translate('xpack.canvas.functions.shape.args.fillHelpText', {
|
||||
defaultMessage: 'An {SVG} color to fill the shape.',
|
||||
values: {
|
||||
SVG,
|
||||
},
|
||||
}),
|
||||
maintainAspect: i18n.translate('xpack.canvas.functions.shape.args.maintainAspectHelpText', {
|
||||
defaultMessage: `Maintain the shape's original aspect ratio?`,
|
||||
}),
|
||||
},
|
||||
};
|
|
@ -64,7 +64,6 @@ import { help as savedMap } from './dict/saved_map';
|
|||
import { help as savedSearch } from './dict/saved_search';
|
||||
import { help as savedVisualization } from './dict/saved_visualization';
|
||||
import { help as seriesStyle } from './dict/series_style';
|
||||
import { help as shape } from './dict/shape';
|
||||
import { help as sort } from './dict/sort';
|
||||
import { help as staticColumn } from './dict/static_column';
|
||||
import { help as string } from './dict/string';
|
||||
|
@ -226,7 +225,6 @@ export const getFunctionHelp = (): FunctionHelpDict => ({
|
|||
savedSearch,
|
||||
savedVisualization,
|
||||
seriesStyle,
|
||||
shape,
|
||||
sort,
|
||||
staticColumn,
|
||||
string,
|
||||
|
|
|
@ -129,16 +129,6 @@ export const RendererStrings = {
|
|||
defaultMessage: 'Repeat an image a given number of times',
|
||||
}),
|
||||
},
|
||||
shape: {
|
||||
getDisplayName: () =>
|
||||
i18n.translate('xpack.canvas.renderer.shape.displayName', {
|
||||
defaultMessage: 'Shape',
|
||||
}),
|
||||
getHelpDescription: () =>
|
||||
i18n.translate('xpack.canvas.renderer.shape.helpDescription', {
|
||||
defaultMessage: 'Render a basic shape',
|
||||
}),
|
||||
},
|
||||
table: {
|
||||
getDisplayName: () =>
|
||||
i18n.translate('xpack.canvas.renderer.table.displayName', {
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
"expressionError",
|
||||
"expressionRevealImage",
|
||||
"expressions",
|
||||
"expressionShape",
|
||||
"features",
|
||||
"inspector",
|
||||
"presentationUtil",
|
||||
|
|
|
@ -15,14 +15,18 @@ exports[`Storyshots components/Shapes/ShapePicker default 1`] = `
|
|||
>
|
||||
<div
|
||||
className="canvasShapePreview"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "<svg xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"-2.5 -2.5 105 105\\" fill=\\"none\\" stroke=\\"black\\">
|
||||
<polygon points=\\"0,40 60,40 60,20 95,50 60,80 60,60 0,60\\"/>
|
||||
</svg>",
|
||||
}
|
||||
}
|
||||
/>
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="black"
|
||||
viewBox="-2.5 -2.5 105 105"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<polygon
|
||||
points="0,40 60,40 60,20 95,50 60,80 60,60 0,60"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
|
@ -36,14 +40,374 @@ exports[`Storyshots components/Shapes/ShapePicker default 1`] = `
|
|||
>
|
||||
<div
|
||||
className="canvasShapePreview"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "<svg xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"-2.5 -2.5 105 105\\" fill=\\"none\\" stroke=\\"black\\">
|
||||
<rect x=\\"0\\" y=\\"0\\" width=\\"100\\" height=\\"100\\"/>
|
||||
</svg>",
|
||||
}
|
||||
}
|
||||
/>
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="black"
|
||||
viewBox="-2.5 -2.5 105 65"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<polygon
|
||||
points="5,30 25,10 25,20 75,20 75,10 95,30 75,50 75,40 25,40 25,50"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem"
|
||||
>
|
||||
<button
|
||||
className="euiLink euiLink--primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
className="canvasShapePreview"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="black"
|
||||
viewBox="-2.5 -2.5 65 105"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<polygon
|
||||
points="0,0 60,0 60,95 30,75 0,95 0,0"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem"
|
||||
>
|
||||
<button
|
||||
className="euiLink euiLink--primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
className="canvasShapePreview"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="black"
|
||||
viewBox="-2.5 -2.5 105 105"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<circle
|
||||
cx="50"
|
||||
cy="50"
|
||||
r="45"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem"
|
||||
>
|
||||
<button
|
||||
className="euiLink euiLink--primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
className="canvasShapePreview"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="black"
|
||||
viewBox="-2.5 -2.5 105 105"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<polygon
|
||||
points="30,0 70,0 70,30 100,30 100,70 70,70 70,100 30,100 30,70 0,70 0,30 30,30"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem"
|
||||
>
|
||||
<button
|
||||
className="euiLink euiLink--primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
className="canvasShapePreview"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="black"
|
||||
viewBox="-2.5 -2.5 105 105"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<polygon
|
||||
points="70.000, 15.359 30.000, 15.359 10.000, 50.000 30.000, 84.641 70.000, 84.641 90.000, 50.000"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem"
|
||||
>
|
||||
<button
|
||||
className="euiLink euiLink--primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
className="canvasShapePreview"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="black"
|
||||
viewBox="-2.5 -2.5 105 155"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<polygon
|
||||
points="50,10 10,50 50,140 90,50"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem"
|
||||
>
|
||||
<button
|
||||
className="euiLink euiLink--primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
className="canvasShapePreview"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="black"
|
||||
viewBox="-2.5 -2.5 105 105"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<polygon
|
||||
points="50.0000, 14.0000 11.9577, 41.6393 26.4886, 86.3607 73.5114, 86.3607 88.0423, 41.6393"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem"
|
||||
>
|
||||
<button
|
||||
className="euiLink euiLink--primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
className="canvasShapePreview"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="black"
|
||||
viewBox="-2.5 -2.5 105 105"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<polygon
|
||||
points="50,10 10,50 50,90 90,50"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem"
|
||||
>
|
||||
<button
|
||||
className="euiLink euiLink--primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
className="canvasShapePreview"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="black"
|
||||
viewBox="-2.5 -2.5 105 105"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M 5,50 h 90 A 45 45 180 1 0 5,50 Z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem"
|
||||
>
|
||||
<button
|
||||
className="euiLink euiLink--primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
className="canvasShapePreview"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="black"
|
||||
viewBox="-2.5 -2.5 105 105"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<polygon
|
||||
points="0,0 100,0 100,70 40,70 20,85 25,70 0,70"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem"
|
||||
>
|
||||
<button
|
||||
className="euiLink euiLink--primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
className="canvasShapePreview"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="black"
|
||||
viewBox="-2.5 -2.5 105 105"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect
|
||||
height="100"
|
||||
width="100"
|
||||
x="0"
|
||||
y="0"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem"
|
||||
>
|
||||
<button
|
||||
className="euiLink euiLink--primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
className="canvasShapePreview"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="black"
|
||||
viewBox="-2.5 -2.5 105 105"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<polygon
|
||||
points="41.183, 37.865 12.652, 37.865 35.734, 54.635 26.917, 81.771 50.000, 65.000 73.265, 81.904 64.266, 54.635 87.348, 37.865 58.817, 37.865 50.07, 10.515"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem"
|
||||
>
|
||||
<button
|
||||
className="euiLink euiLink--primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
className="canvasShapePreview"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="black"
|
||||
viewBox="-2.5 -2.5 105 65"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<polygon
|
||||
points="0,0 75,0 90,30 75,60 0,60"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem"
|
||||
>
|
||||
<button
|
||||
className="euiLink euiLink--primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
className="canvasShapePreview"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="black"
|
||||
viewBox="-2.5 -2.5 105 105"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<polygon
|
||||
points="50.000, 20.000 15.359, 80.000 84.641, 80.000"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
className="euiFlexItem"
|
||||
>
|
||||
<button
|
||||
className="euiLink euiLink--primary"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
className="canvasShapePreview"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="black"
|
||||
viewBox="-2.5 -2.5 105 105"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<polygon
|
||||
points="0, 10 0, 100 90, 100"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -9,9 +9,8 @@ import { action } from '@storybook/addon-actions';
|
|||
import { storiesOf } from '@storybook/react';
|
||||
import React from 'react';
|
||||
import { ShapePicker } from '../shape_picker';
|
||||
|
||||
import { shapes } from '../../../../canvas_plugin_src/renderers/shape/shapes';
|
||||
import { getAvailableShapes } from '../../../../../../../src/plugins/expression_shape/common';
|
||||
|
||||
storiesOf('components/Shapes/ShapePicker', module).add('default', () => (
|
||||
<ShapePicker shapes={shapes} onChange={action('onChange')} />
|
||||
<ShapePicker shapes={getAvailableShapes()} onChange={action('onChange')} />
|
||||
));
|
||||
|
|
|
@ -9,29 +9,24 @@ import React, { FC } from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import { EuiFlexGrid, EuiFlexItem, EuiLink } from '@elastic/eui';
|
||||
import { ShapePreview } from '../shape_preview';
|
||||
import { Shape } from '../../../../../../src/plugins/expression_shape/common';
|
||||
|
||||
interface Props {
|
||||
shapes: {
|
||||
[key: string]: string;
|
||||
};
|
||||
shapes: Shape[];
|
||||
onChange?: (key: string) => void;
|
||||
}
|
||||
|
||||
export const ShapePicker: FC<Props> = ({ shapes, onChange = () => {} }) => {
|
||||
return (
|
||||
<EuiFlexGrid gutterSize="s" columns={4} className="canvasShapePicker">
|
||||
{Object.keys(shapes)
|
||||
.sort()
|
||||
.map((shapeKey) => (
|
||||
<EuiFlexItem key={shapeKey}>
|
||||
<EuiLink onClick={() => onChange(shapeKey)}>
|
||||
<ShapePreview shape={shapes[shapeKey]} />
|
||||
</EuiLink>
|
||||
</EuiFlexItem>
|
||||
))}
|
||||
</EuiFlexGrid>
|
||||
);
|
||||
};
|
||||
export const ShapePicker: FC<Props> = ({ shapes, onChange = () => {} }) => (
|
||||
<EuiFlexGrid gutterSize="s" columns={4} className="canvasShapePicker">
|
||||
{shapes.sort().map((shapeKey) => (
|
||||
<EuiFlexItem key={shapeKey}>
|
||||
<EuiLink onClick={() => onChange(shapeKey)}>
|
||||
<ShapePreview shape={shapeKey} />
|
||||
</EuiLink>
|
||||
</EuiFlexItem>
|
||||
))}
|
||||
</EuiFlexGrid>
|
||||
);
|
||||
|
||||
ShapePicker.propTypes = {
|
||||
onChange: PropTypes.func,
|
||||
|
|
|
@ -53,14 +53,21 @@ exports[`Storyshots components/Shapes/ShapePickerPopover interactive 1`] = `
|
|||
>
|
||||
<div
|
||||
className="canvasShapePreview"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "<svg xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"-2.5 -2.5 105 105\\" fill=\\"none\\" stroke=\\"black\\">
|
||||
<rect x=\\"0\\" y=\\"0\\" width=\\"100\\" height=\\"100\\"/>
|
||||
</svg>",
|
||||
}
|
||||
}
|
||||
/>
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="black"
|
||||
viewBox="-2.5 -2.5 105 105"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect
|
||||
height="100"
|
||||
width="100"
|
||||
x="0"
|
||||
y="0"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -90,14 +97,21 @@ exports[`Storyshots components/Shapes/ShapePickerPopover shape selected 1`] = `
|
|||
>
|
||||
<div
|
||||
className="canvasShapePreview"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "<svg xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"-2.5 -2.5 105 105\\" fill=\\"none\\" stroke=\\"black\\">
|
||||
<rect x=\\"0\\" y=\\"0\\" width=\\"100\\" height=\\"100\\"/>
|
||||
</svg>",
|
||||
}
|
||||
}
|
||||
/>
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="black"
|
||||
viewBox="-2.5 -2.5 105 105"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect
|
||||
height="100"
|
||||
width="100"
|
||||
x="0"
|
||||
y="0"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -9,18 +9,20 @@ import { action } from '@storybook/addon-actions';
|
|||
import { storiesOf } from '@storybook/react';
|
||||
import React from 'react';
|
||||
import { ShapePickerPopover } from '../shape_picker_popover';
|
||||
|
||||
import { shapes } from '../../../../canvas_plugin_src/renderers/shape/shapes';
|
||||
import {
|
||||
getAvailableShapes,
|
||||
Shape,
|
||||
} from '../../../../../../../src/plugins/expression_shape/common';
|
||||
|
||||
class Interactive extends React.Component<{}, { value: string }> {
|
||||
public state = {
|
||||
value: 'square',
|
||||
value: Shape.SQUARE,
|
||||
};
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<ShapePickerPopover
|
||||
shapes={shapes}
|
||||
shapes={getAvailableShapes()}
|
||||
onChange={(value) => this.setState({ value })}
|
||||
value={this.state.value}
|
||||
/>
|
||||
|
@ -29,9 +31,15 @@ class Interactive extends React.Component<{}, { value: string }> {
|
|||
}
|
||||
|
||||
storiesOf('components/Shapes/ShapePickerPopover', module)
|
||||
.add('default', () => <ShapePickerPopover shapes={shapes} onChange={action('onChange')} />)
|
||||
.add('default', () => (
|
||||
<ShapePickerPopover shapes={getAvailableShapes()} onChange={action('onChange')} />
|
||||
))
|
||||
.add('shape selected', () => (
|
||||
<ShapePickerPopover shapes={shapes} onChange={action('onChange')} value="square" />
|
||||
<ShapePickerPopover
|
||||
shapes={getAvailableShapes()}
|
||||
onChange={action('onChange')}
|
||||
value={Shape.SQUARE}
|
||||
/>
|
||||
))
|
||||
.add('interactive', () => <Interactive />, {
|
||||
info: {
|
||||
|
|
|
@ -11,13 +11,12 @@ import { EuiLink, EuiPanel } from '@elastic/eui';
|
|||
import { Popover } from '../popover';
|
||||
import { ShapePicker } from '../shape_picker';
|
||||
import { ShapePreview } from '../shape_preview';
|
||||
import { Shape } from '../../../../../../src/plugins/expression_shape/common';
|
||||
|
||||
interface Props {
|
||||
shapes: {
|
||||
[key: string]: string;
|
||||
};
|
||||
shapes: Shape[];
|
||||
onChange?: (key: string) => void;
|
||||
value?: string;
|
||||
value?: Shape;
|
||||
ariaLabel?: string;
|
||||
}
|
||||
|
||||
|
@ -25,7 +24,7 @@ export const ShapePickerPopover: FC<Props> = ({ shapes, onChange, value, ariaLab
|
|||
const button = (handleClick: React.MouseEventHandler<any>) => (
|
||||
<EuiPanel paddingSize="s" hasShadow={false}>
|
||||
<EuiLink aria-label={ariaLabel} style={{ fontSize: 0 }} onClick={handleClick}>
|
||||
<ShapePreview shape={value ? shapes[value] : undefined} />
|
||||
<ShapePreview shape={value} />
|
||||
</EuiLink>
|
||||
</EuiPanel>
|
||||
);
|
||||
|
|
|
@ -3,25 +3,36 @@
|
|||
exports[`Storyshots components/Shapes/ShapePreview arrow 1`] = `
|
||||
<div
|
||||
className="canvasShapePreview"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "<svg xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"-2.5 -2.5 105 105\\" fill=\\"none\\" stroke=\\"black\\">
|
||||
<polygon points=\\"0,40 60,40 60,20 95,50 60,80 60,60 0,60\\"/>
|
||||
</svg>",
|
||||
}
|
||||
}
|
||||
/>
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="black"
|
||||
viewBox="-2.5 -2.5 105 105"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<polygon
|
||||
points="0,40 60,40 60,20 95,50 60,80 60,60 0,60"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Storyshots components/Shapes/ShapePreview square 1`] = `
|
||||
<div
|
||||
className="canvasShapePreview"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "<svg xmlns=\\"http://www.w3.org/2000/svg\\" viewBox=\\"-2.5 -2.5 105 105\\" fill=\\"none\\" stroke=\\"black\\">
|
||||
<rect x=\\"0\\" y=\\"0\\" width=\\"100\\" height=\\"100\\"/>
|
||||
</svg>",
|
||||
}
|
||||
}
|
||||
/>
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
stroke="black"
|
||||
viewBox="-2.5 -2.5 105 105"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect
|
||||
height="100"
|
||||
width="100"
|
||||
x="0"
|
||||
y="0"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
`;
|
||||
|
|
|
@ -8,9 +8,8 @@
|
|||
import { storiesOf } from '@storybook/react';
|
||||
import React from 'react';
|
||||
import { ShapePreview } from '../shape_preview';
|
||||
|
||||
import { shapes } from '../../../../canvas_plugin_src/renderers/shape/shapes';
|
||||
import { Shape } from '../../../../../../../src/plugins/expression_shape/public';
|
||||
|
||||
storiesOf('components/Shapes/ShapePreview', module)
|
||||
.add('arrow', () => <ShapePreview shape={shapes.arrow} />)
|
||||
.add('square', () => <ShapePreview shape={shapes.square} />);
|
||||
.add('arrow', () => <ShapePreview shape={Shape.ARROW} />)
|
||||
.add('square', () => <ShapePreview shape={Shape.SQUARE} />);
|
||||
|
|
|
@ -5,45 +5,55 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { FC } from 'react';
|
||||
import React, { FC, RefCallback, useCallback, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
LazyShapeDrawer,
|
||||
Shape,
|
||||
ShapeDrawerComponentProps,
|
||||
getDefaultShapeData,
|
||||
SvgConfig,
|
||||
ShapeRef,
|
||||
ViewBoxParams,
|
||||
} from '../../../../../../src/plugins/expression_shape/public';
|
||||
import { withSuspense } from '../../../../../../src/plugins/presentation_util/public';
|
||||
|
||||
interface Props {
|
||||
shape?: string;
|
||||
shape?: Shape;
|
||||
}
|
||||
|
||||
const ShapeDrawer = withSuspense<ShapeDrawerComponentProps, ShapeRef>(LazyShapeDrawer);
|
||||
|
||||
function getViewBox(defaultWidth: number, defaultViewBox: ViewBoxParams): ViewBoxParams {
|
||||
const { minX, minY, width, height } = defaultViewBox;
|
||||
return {
|
||||
minX: minX - defaultWidth / 2,
|
||||
minY: minY - defaultWidth / 2,
|
||||
width: width + defaultWidth,
|
||||
height: height + defaultWidth,
|
||||
};
|
||||
}
|
||||
|
||||
export const ShapePreview: FC<Props> = ({ shape }) => {
|
||||
if (!shape) {
|
||||
return <div className="canvasShapePreview" />;
|
||||
}
|
||||
const [shapeData, setShapeData] = useState<SvgConfig>(getDefaultShapeData());
|
||||
|
||||
const weight = 5;
|
||||
const parser = new DOMParser();
|
||||
const shapeSvg = parser
|
||||
.parseFromString(shape, 'image/svg+xml')
|
||||
.getElementsByTagName('svg')
|
||||
.item(0);
|
||||
|
||||
if (!shapeSvg) {
|
||||
throw new Error('An unexpected error occurred: the SVG was not parseable');
|
||||
}
|
||||
|
||||
shapeSvg.setAttribute('fill', 'none');
|
||||
shapeSvg.setAttribute('stroke', 'black');
|
||||
|
||||
const viewBox = shapeSvg.getAttribute('viewBox') || '0 0 0 0';
|
||||
const initialViewBox = viewBox.split(' ').map((v: string) => parseInt(v, 10));
|
||||
|
||||
let [minX, minY, width, height] = initialViewBox;
|
||||
minX -= weight / 2;
|
||||
minY -= weight / 2;
|
||||
width += weight;
|
||||
height += weight;
|
||||
shapeSvg.setAttribute('viewBox', [minX, minY, width, height].join(' '));
|
||||
const shapeRef = useCallback<RefCallback<ShapeRef>>((node) => {
|
||||
if (node !== null) setShapeData(node.getData());
|
||||
}, []);
|
||||
|
||||
if (!shape) return <div className="canvasShapePreview" />;
|
||||
return (
|
||||
// eslint-disable-next-line react/no-danger
|
||||
<div className="canvasShapePreview" dangerouslySetInnerHTML={{ __html: shapeSvg.outerHTML }} />
|
||||
<div className="canvasShapePreview">
|
||||
<ShapeDrawer
|
||||
ref={shapeRef}
|
||||
shapeType={shape}
|
||||
shapeAttributes={{
|
||||
fill: 'none',
|
||||
stroke: 'black',
|
||||
viewBox: getViewBox(5, shapeData.viewBox),
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ import { metric } from '../canvas_plugin_src/renderers/metric';
|
|||
import { pie } from '../canvas_plugin_src/renderers/pie';
|
||||
import { plot } from '../canvas_plugin_src/renderers/plot';
|
||||
import { progress } from '../canvas_plugin_src/renderers/progress';
|
||||
import { shape } from '../canvas_plugin_src/renderers/shape';
|
||||
import { table } from '../canvas_plugin_src/renderers/table';
|
||||
import { text } from '../canvas_plugin_src/renderers/text';
|
||||
import { revealImageRenderer as revealImage } from '../../../../src/plugins/expression_reveal_image/public';
|
||||
|
@ -20,6 +19,7 @@ import {
|
|||
errorRenderer as error,
|
||||
debugRenderer as debug,
|
||||
} from '../../../../src/plugins/expression_error/public';
|
||||
import { shapeRenderer as shape } from '../../../../src/plugins/expression_shape/public';
|
||||
|
||||
/**
|
||||
* This is a collection of renderers which are bundled with the runtime. If
|
||||
|
|
|
@ -39,19 +39,6 @@ jest.mock('../public/lib/ui_metric', () => ({ trackCanvasUiMetric: () => {} }));
|
|||
// Mock EUI generated ids to be consistently predictable for snapshots.
|
||||
jest.mock(`@elastic/eui/lib/components/form/form_row/make_id`, () => () => `generated-id`);
|
||||
|
||||
// Jest automatically mocks SVGs to be a plain-text string that isn't an SVG. Canvas uses
|
||||
// them in examples, so let's mock a few for tests.
|
||||
jest.mock('../canvas_plugin_src/renderers/shape/shapes', () => ({
|
||||
shapes: {
|
||||
arrow: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<polygon points="0,40 60,40 60,20 95,50 60,80 60,60 0,60" />
|
||||
</svg>`,
|
||||
square: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<rect x="0" y="0" width="100" height="100" />
|
||||
</svg>`,
|
||||
},
|
||||
}));
|
||||
|
||||
// Mock react-datepicker dep used by eui to avoid rendering the entire large component
|
||||
jest.mock('@elastic/eui/packages/react-datepicker', () => {
|
||||
return {
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
{ "path": "../../../src/plugins/expressions/tsconfig.json" },
|
||||
{ "path": "../../../src/plugins/expression_error/tsconfig.json" },
|
||||
{ "path": "../../../src/plugins/expression_reveal_image/tsconfig.json" },
|
||||
{ "path": "../../../src/plugins/expression_shape/tsconfig.json" },
|
||||
{ "path": "../../../src/plugins/home/tsconfig.json" },
|
||||
{ "path": "../../../src/plugins/inspector/tsconfig.json" },
|
||||
{ "path": "../../../src/plugins/kibana_legacy/tsconfig.json" },
|
||||
|
|
|
@ -6353,12 +6353,12 @@
|
|||
"xpack.canvas.functions.seriesStyle.args.pointsHelpText": "線上の点のサイズです。",
|
||||
"xpack.canvas.functions.seriesStyle.args.stackHelpText": "数列をスタックするかを指定します。数字はスタック ID です。同じスタック ID の数列は一緒にスタックされます。",
|
||||
"xpack.canvas.functions.seriesStyleHelpText": "チャートの数列のプロパティの説明に使用されるオブジェクトを作成します。{plotFn} や {pieFn} のように、チャート関数内で {seriesStyleFn} を使用します。",
|
||||
"xpack.canvas.functions.shape.args.borderHelpText": "図形の外郭の {SVG} カラーです。",
|
||||
"xpack.canvas.functions.shape.args.borderWidthHelpText": "境界の太さです。",
|
||||
"xpack.canvas.functions.shape.args.fillHelpText": "図形を塗りつぶす {SVG} カラーです。",
|
||||
"xpack.canvas.functions.shape.args.maintainAspectHelpText": "図形の元の横縦比を維持しますか?",
|
||||
"xpack.canvas.functions.shape.args.shapeHelpText": "図形を選択します。",
|
||||
"xpack.canvas.functions.shapeHelpText": "図形を作成します。",
|
||||
"expressionShape.functions.shape.args.borderHelpText": "図形の外郭の {SVG} カラーです。",
|
||||
"expressionShape.functions.shape.args.borderWidthHelpText": "境界の太さです。",
|
||||
"expressionShape.functions.shape.args.fillHelpText": "図形を塗りつぶす {SVG} カラーです。",
|
||||
"expressionShape.functions.shape.args.maintainAspectHelpText": "図形の元の横縦比を維持しますか?",
|
||||
"expressionShape.functions.shape.args.shapeHelpText": "図形を選択します。",
|
||||
"expressionShape.functions.shapeHelpText": "図形を作成します。",
|
||||
"xpack.canvas.functions.sort.args.byHelpText": "並べ替えの基準となる列です。指定されていない場合、{DATATABLE}は初めの列で並べられます。",
|
||||
"xpack.canvas.functions.sort.args.reverseHelpText": "並び順を反転させます。指定されていない場合、{DATATABLE}は昇順で並べられます。",
|
||||
"xpack.canvas.functions.sortHelpText": "{DATATABLE}を指定された列で並べ替えます。",
|
||||
|
@ -6515,8 +6515,8 @@
|
|||
"xpack.canvas.renderer.progress.helpDescription": "エレメントのパーセンテージを示す進捗インジケーターをレンダリングします",
|
||||
"xpack.canvas.renderer.repeatImage.displayName": "画像の繰り返し",
|
||||
"xpack.canvas.renderer.repeatImage.helpDescription": "画像を指定回数繰り返し表示します",
|
||||
"xpack.canvas.renderer.shape.displayName": "形状",
|
||||
"xpack.canvas.renderer.shape.helpDescription": "基本的な図形をレンダリングします",
|
||||
"expressionShape.renderer.shape.displayName": "形状",
|
||||
"expressionShape.renderer.shape.helpDescription": "基本的な図形をレンダリングします",
|
||||
"xpack.canvas.renderer.table.displayName": "データテーブル",
|
||||
"xpack.canvas.renderer.table.helpDescription": "表形式データを {HTML} としてレンダリングします",
|
||||
"xpack.canvas.renderer.text.displayName": "プレインテキスト",
|
||||
|
|
|
@ -6077,8 +6077,6 @@
|
|||
"xpack.canvas.elements.progressWheelHelpText": "将进度显示为轮盘的一部分",
|
||||
"xpack.canvas.elements.repeatImageDisplayName": "图像重复",
|
||||
"xpack.canvas.elements.repeatImageHelpText": "使图像重复 N 次",
|
||||
"xpack.canvas.elements.revealImageDisplayName": "图像显示",
|
||||
"xpack.canvas.elements.revealImageHelpText": "显示图像特定百分比",
|
||||
"xpack.canvas.elements.shapeDisplayName": "形状",
|
||||
"xpack.canvas.elements.shapeHelpText": "可定制的形状",
|
||||
"xpack.canvas.elements.tableDisplayName": "数据表",
|
||||
|
@ -6392,12 +6390,12 @@
|
|||
"xpack.canvas.functions.seriesStyle.args.pointsHelpText": "折线图上的点大小。",
|
||||
"xpack.canvas.functions.seriesStyle.args.stackHelpText": "指定是否应堆叠序列。数字为堆叠 ID。具有相同堆叠 ID 的序列将堆叠在一起。",
|
||||
"xpack.canvas.functions.seriesStyleHelpText": "创建用于在图表上描述序列属性的对象。在绘图函数 (如 {plotFn} 或 {pieFn} ) 内使用 {seriesStyleFn}。",
|
||||
"xpack.canvas.functions.shape.args.borderHelpText": "形状轮廓边框的 {SVG} 颜色。",
|
||||
"xpack.canvas.functions.shape.args.borderWidthHelpText": "边框的粗细。",
|
||||
"xpack.canvas.functions.shape.args.fillHelpText": "填充形状的 {SVG} 颜色。",
|
||||
"xpack.canvas.functions.shape.args.maintainAspectHelpText": "维持形状的原始纵横比?",
|
||||
"xpack.canvas.functions.shape.args.shapeHelpText": "选取形状。",
|
||||
"xpack.canvas.functions.shapeHelpText": "创建形状。",
|
||||
"expressionShape.functions.shape.args.borderHelpText": "形状轮廓边框的 {SVG} 颜色。",
|
||||
"expressionShape.functions.shape.args.borderWidthHelpText": "边框的粗细。",
|
||||
"expressionShape.functions.shape.args.fillHelpText": "填充形状的 {SVG} 颜色。",
|
||||
"expressionShape.functions.shape.args.maintainAspectHelpText": "维持形状的原始纵横比?",
|
||||
"expressionShape.functions.shape.args.shapeHelpText": "选取形状。",
|
||||
"expressionShape.functions.shapeHelpText": "创建形状。",
|
||||
"xpack.canvas.functions.sort.args.byHelpText": "排序依据的列。如果未指定,则 {DATATABLE} 按第一列排序。",
|
||||
"xpack.canvas.functions.sort.args.reverseHelpText": "反转排序顺序。如果未指定,则 {DATATABLE} 按升序排序。",
|
||||
"xpack.canvas.functions.sortHelpText": "按指定列对 {DATATABLE} 进行排序。",
|
||||
|
@ -6554,8 +6552,8 @@
|
|||
"xpack.canvas.renderer.progress.helpDescription": "呈现显示元素百分比的进度指示",
|
||||
"xpack.canvas.renderer.repeatImage.displayName": "图像重复",
|
||||
"xpack.canvas.renderer.repeatImage.helpDescription": "重复图像给定次数",
|
||||
"xpack.canvas.renderer.shape.displayName": "形状",
|
||||
"xpack.canvas.renderer.shape.helpDescription": "呈现基本形状",
|
||||
"expressionShape.renderer.shape.displayName": "形状",
|
||||
"expressionShape.renderer.shape.helpDescription": "呈现基本形状",
|
||||
"xpack.canvas.renderer.table.displayName": "数据表",
|
||||
"xpack.canvas.renderer.table.helpDescription": "将表格数据呈现为 {HTML}",
|
||||
"xpack.canvas.renderer.text.displayName": "纯文本",
|
||||
|
|