UNPKG

@adaptabletools/adaptable

Version:

Powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements

372 lines (371 loc) 25.5 kB
import * as React from 'react'; import { Box, Flex } from 'rebass'; import { Select } from '../../../components/Select'; import { Tabs } from '../../../components/Tabs'; import { useOnePageAdaptableWizardContext } from '../../Wizard/OnePageAdaptableWizard'; import FormLayout, { FormRow } from '../../../components/FormLayout'; import { Tag } from '../../../components/Tag'; import AdaptableInput from '../../Components/AdaptableInput'; import { ColorPicker } from '../../../components/ColorPicker'; import { CheckBox } from '../../../components/CheckBox'; const SparklineTypes = { LINE: 'line', AREA: 'area', BAR_VERTICAL: 'bar_vertical', BAR_HORIZONTAL: 'bar_horizontal', }; const sparklineTypeOptions = [ { label: 'Line', value: SparklineTypes.LINE }, { label: 'Area', value: SparklineTypes.AREA }, { label: 'Column', value: SparklineTypes.BAR_VERTICAL }, { label: 'Bar', value: SparklineTypes.BAR_HORIZONTAL }, ]; export const StyledColumnSparklineSettingsSection = ({ onChange }) => { const { data, api } = useOnePageAdaptableWizardContext(); const sparklineOptions = data.SparklineStyle?.options ?? { type: SparklineTypes.LINE, }; if (!sparklineOptions.type) { sparklineOptions.type = SparklineTypes.LINE; } const handleOptionsChange = (newOptions) => { const updatedStyledColumn = { ...data, SparklineStyle: { ...data.SparklineStyle, options: newOptions }, }; onChange(updatedStyledColumn); }; const currentType = sparklineOptions.type ?? 'line'; const currentDirection = sparklineOptions.direction; const sparklineType = (currentType === 'bar' ? `bar_${currentDirection ?? 'vertical'}` : currentType); const handleTypeChange = (value) => { const [type, direction] = value.split('_'); const newOptions = { ...sparklineOptions, type }; if (direction) { newOptions.direction = direction; } else { delete newOptions.direction; } handleOptionsChange(newOptions); }; const isObjectNumberArray = api.columnApi.getColumnWithColumnId(data.ColumnId)?.dataType === 'objectArray'; return (React.createElement(React.Fragment, null, React.createElement(Tabs, { mb: 2 }, React.createElement(Tabs.Tab, null, "Settings"), React.createElement(Tabs.Content, null, React.createElement(FormLayout, null, React.createElement(FormRow, { label: "Sparkline Type" }, React.createElement(Box, { maxWidth: 160 }, React.createElement(Select, { options: sparklineTypeOptions, value: sparklineType, onChange: handleTypeChange, placeholder: "Select Sparkline Type" }))), isObjectNumberArray && (React.createElement(SparklineObjectArrayProperties, { options: sparklineOptions, onChange: handleOptionsChange })), React.createElement(FormRow, { label: "Min Value" }, React.createElement(AdaptableInput, { type: "number", value: sparklineOptions.min ?? '', onChange: (e) => handleOptionsChange({ ...sparklineOptions, min: e.target.value === '' ? undefined : Number(e.target.value), }), placeholder: 'Auto', title: "User override for the automatically determined min value (based on series data)" })), React.createElement(FormRow, { label: "Max Value" }, React.createElement(AdaptableInput, { type: "number", value: sparklineOptions.max ?? '', onChange: (e) => handleOptionsChange({ ...sparklineOptions, max: e.target.value === '' ? undefined : Number(e.target.value), }), placeholder: 'Auto', title: "User override for the automatically determined max value (based on series data)" }))))), React.createElement(Tabs, { mb: 2 }, React.createElement(Tabs.Tab, null, "Theming"), React.createElement(Tabs.Tab, null, "Axis"), React.createElement(Tabs.Tab, { hidden: sparklineOptions.type === 'bar' }, "Marker"), React.createElement(Tabs.Tab, null, "Tooltip"), React.createElement(Tabs.Tab, null, "Highlight Style"), React.createElement(Tabs.Content, null, React.createElement(SparklineThemingOptions, { options: sparklineOptions, onChange: handleOptionsChange })), React.createElement(Tabs.Content, null, React.createElement(SparklineAxisOptions, { options: sparklineOptions, onChange: handleOptionsChange })), React.createElement(Tabs.Content, null, React.createElement(SparklineMarkerOptions, { options: sparklineOptions, onChange: handleOptionsChange })), React.createElement(Tabs.Content, null, React.createElement(SparklineTooltipOptions, { options: sparklineOptions, onChange: handleOptionsChange })), React.createElement(Tabs.Content, null, React.createElement(SparklineHighlightOptions, { options: sparklineOptions, onChange: handleOptionsChange }))))); }; const SparklineObjectArrayProperties = ({ options, onChange, }) => { const { data, api } = useOnePageAdaptableWizardContext(); const [previewData, setPreviewData] = React.useState(''); React.useEffect(() => { const column = api.columnApi.getColumnWithColumnId(data.ColumnId); if (!column) { return; } try { for (let row = 0; row < 20; row++) { const rowNode = api.gridApi.getRowNodeForIndex(row); const cellData = rowNode?.data?.[column.field]?.[0]; if (cellData) { const preview = JSON.stringify(cellData, null, 2).replace(/[{}",]/g, ''); setPreviewData(preview); break; } } } catch (error) { api.logError('Error parsing sparkline data', error); } }, [api, data.ColumnId]); return (React.createElement(React.Fragment, null, React.createElement(FormRow, { label: "X Key" }, React.createElement(AdaptableInput, { value: options.xKey ?? 'x', onChange: (e) => onChange({ ...options, xKey: e.target.value }) })), React.createElement(FormRow, { label: "Y Key" }, React.createElement(AdaptableInput, { value: options.yKey ?? 'y', onChange: (e) => onChange({ ...options, yKey: e.target.value }) })), previewData && (React.createElement(FormRow, { label: "Preview" }, React.createElement(Tag, null, previewData))))); }; const SparklineThemingOptions = ({ options, onChange, }) => { const { api } = useOnePageAdaptableWizardContext(); const sparklineOptions = options; const handleChange = (key, value) => { onChange({ ...options, [key]: value }); }; const handlePaddingChange = (key, value) => { const currentPadding = sparklineOptions.padding || {}; handleChange('padding', { ...currentPadding, [key]: value }); }; const themes = [ { value: 'ag-default', label: 'Default' }, { value: 'ag-default-dark', label: 'Default Dark' }, { value: 'ag-sheets', label: 'Sheets' }, { value: 'ag-sheets-dark', label: 'Sheets Dark' }, { value: 'ag-polychroma', label: 'Polychroma' }, { value: 'ag-polychroma-dark', label: 'Polychroma Dark' }, { value: 'ag-vivid', label: 'Vivid' }, { value: 'ag-vivid-dark', label: 'Vivid Dark' }, { value: 'ag-material', label: 'Material' }, { value: 'ag-material-dark', label: 'Material Dark' }, { value: 'ag-financial', label: 'Financial' }, { value: 'ag-financial-dark', label: 'Financial Dark' }, ]; return (React.createElement(FormLayout, null, sparklineOptions.type !== 'line' && (React.createElement(FormRow, { label: "Fill" }, React.createElement(ColorPicker, { title: "The colour for filling shapes", api: api, value: sparklineOptions.fill, onChange: (color) => handleChange('fill', color) }))), React.createElement(FormRow, { label: "Stroke" }, React.createElement(Flex, { alignItems: "center" }, React.createElement(ColorPicker, { title: "The colour for the stroke", api: api, value: sparklineOptions.stroke, onChange: (color) => handleChange('stroke', color) }), React.createElement(Box, { ml: 2, mr: 1 }, "Width"), React.createElement(AdaptableInput, { title: "The width of the stroke in pixels", type: "number", style: { width: '70px' }, min: 0, value: sparklineOptions.strokeWidth ?? '', onChange: (e) => handleChange('strokeWidth', Number(e.target.value)) }))), React.createElement(FormRow, { label: "Padding" }, React.createElement(Flex, { alignItems: "center" }, React.createElement(Box, { mr: 1 }, "Top"), React.createElement(AdaptableInput, { type: "number", min: 0, value: sparklineOptions.padding?.top ?? '', onChange: (e) => handlePaddingChange('top', Number(e.target.value)), style: { width: '70px' }, title: "The number of pixels of padding at the top of the chart area" }), React.createElement(Box, { ml: 2, mr: 1 }, "Right"), React.createElement(AdaptableInput, { type: "number", min: 0, value: sparklineOptions.padding?.right ?? '', onChange: (e) => handlePaddingChange('right', Number(e.target.value)), style: { width: '70px' }, title: "The number of pixels of padding at the right of the chart area" }), React.createElement(Box, { ml: 2, mr: 1 }, "Bottom"), React.createElement(AdaptableInput, { type: "number", min: 0, value: sparklineOptions.padding?.bottom ?? '', onChange: (e) => handlePaddingChange('bottom', Number(e.target.value)), style: { width: '70px' }, title: "The number of pixels of padding at the bottom of the chart area" }), React.createElement(Box, { ml: 2, mr: 1 }, "Left"), React.createElement(AdaptableInput, { type: "number", min: 0, value: sparklineOptions.padding?.left ?? '', onChange: (e) => handlePaddingChange('left', Number(e.target.value)), style: { width: '70px' }, title: "The number of pixels of padding at the left of the chart area" }))), React.createElement(FormRow, { label: "Line Dash" }, React.createElement(AdaptableInput, { title: "Length of dashes and gaps in pixels (comma-separated values, e.g. '3,6,9')", value: sparklineOptions.lineDash?.join(',') ?? '', onChange: (e) => { const value = e.target.value; const dashArray = value ? value .split(',') .map(Number) .filter((n) => !isNaN(n)) : []; handleChange('lineDash', dashArray); } })), React.createElement(FormRow, { label: "Line Dash Offset" }, React.createElement(AdaptableInput, { title: "The offset of the line dash pattern in pixels", type: "number", min: 0, value: sparklineOptions.lineDashOffset ?? '', onChange: (e) => handleChange('lineDashOffset', Number(e.target.value)) })), React.createElement(FormRow, { label: "Background" }, React.createElement(Flex, { alignItems: "center" }, React.createElement(CheckBox, { checked: sparklineOptions.background?.visible ?? false, onChange: (visible) => handleChange('background', { ...sparklineOptions.background, visible, }) }), React.createElement(Box, { ml: 2 }, React.createElement(ColorPicker, { disabled: !sparklineOptions.background?.visible, title: "The colour of the chart background", api: api, value: sparklineOptions.background?.fill, onChange: (fill) => handleChange('background', { ...sparklineOptions.background, fill, }) })))), typeof sparklineOptions.theme !== 'object' && (React.createElement(FormRow, { label: "Theme" }, React.createElement(Box, { maxWidth: 160 }, React.createElement(Select, { value: sparklineOptions.theme ?? 'ag-default', onChange: (themeName) => handleChange('theme', themeName), options: themes })))))); }; const SparklineAxisOptions = ({ options, onChange, }) => { const { api } = useOnePageAdaptableWizardContext(); const sparklineOptions = options ?? {}; if (!sparklineOptions.axis?.type) { sparklineOptions.axis = sparklineOptions.axis ?? { type: 'category' }; sparklineOptions.axis.type = 'category'; } const handleChange = (value) => { onChange({ ...options, axis: { ...options.axis, ...value, }, }); }; const axisTypes = [ { value: 'category', label: 'Category' }, { value: 'number', label: 'Number' }, { value: 'time', label: 'Time' }, ]; const isAxisEnabled = sparklineOptions.axis?.visible ?? false; return (React.createElement(FormLayout, null, React.createElement(FormRow, { label: "Show Axis" }, React.createElement(CheckBox, { checked: isAxisEnabled, onChange: (visible) => handleChange({ visible }) })), React.createElement(FormRow, { label: "Axis Type" }, React.createElement(Box, { maxWidth: 160 }, React.createElement(Select, { disabled: !isAxisEnabled, value: sparklineOptions.axis.type, onChange: (type) => handleChange({ type }), options: axisTypes }))), React.createElement(FormRow, { label: "Stroke" }, React.createElement(Flex, { alignItems: "center" }, React.createElement(ColorPicker, { disabled: !isAxisEnabled, title: "The colour of the axis line", api: api, value: sparklineOptions.axis?.stroke, onChange: (stroke) => handleChange({ stroke }) }), React.createElement(Box, { ml: 2, mr: 1 }, "Width"), React.createElement(AdaptableInput, { disabled: !isAxisEnabled, style: { width: '70px' }, title: "The width in pixels of the axis line", type: "number", min: 0, value: sparklineOptions.axis?.strokeWidth ?? '', onChange: (e) => handleChange({ strokeWidth: Number(e.target.value) }) }))), React.createElement(FormRow, { label: "Reverse Scale" }, React.createElement(CheckBox, { disabled: !isAxisEnabled, checked: sparklineOptions.axis?.reverse, onChange: (reverse) => handleChange({ reverse }) })), sparklineOptions.axis.type === 'category' && (React.createElement(React.Fragment, null, React.createElement(FormRow, { label: "Padding" }, React.createElement(Flex, { alignItems: "center" }, React.createElement(Box, { mr: 1 }, "Inner"), React.createElement(AdaptableInput, { disabled: !isAxisEnabled, title: "The size of the gap between categories (0-1)", type: "number", min: 0, max: 1, step: 0.1, value: sparklineOptions.axis?.paddingInner ?? '', onChange: (e) => handleChange({ paddingInner: Number(e.target.value) }) }), React.createElement(Box, { ml: 2, mr: 1 }, "Outer"), React.createElement(AdaptableInput, { disabled: !isAxisEnabled, title: "The padding on the outside of first and last categories (0-1)", type: "number", min: 0, max: 1, step: 0.1, value: sparklineOptions.axis?.paddingOuter ?? '', onChange: (e) => handleChange({ paddingOuter: Number(e.target.value) }) }))))))); }; const SparklineTooltipOptions = ({ options, onChange, }) => { const sparklineOptions = options; const handleChange = (key, value) => { onChange({ ...options, [key]: value }); }; const isTooltipEnabled = sparklineOptions.tooltip?.enabled; const positionTypes = [ { value: 'pointer', label: 'Pointer' }, { value: 'node', label: 'Node' }, { value: 'top', label: 'Top' }, { value: 'right', label: 'Right' }, { value: 'bottom', label: 'Bottom' }, { value: 'left', label: 'Left' }, { value: 'top-left', label: 'Top Left' }, { value: 'top-right', label: 'Top Right' }, { value: 'bottom-right', label: 'Bottom Right' }, { value: 'bottom-left', label: 'Bottom Left' }, ]; const interactionRanges = [ { value: 'exact', label: 'Exact' }, { value: 'nearest', label: 'Nearest' }, ]; return (React.createElement(FormLayout, null, React.createElement(FormRow, { label: "Enabled" }, React.createElement(CheckBox, { checked: sparklineOptions.tooltip?.enabled, onChange: (enabled) => handleChange('tooltip', { ...sparklineOptions.tooltip, enabled }) })), React.createElement(FormRow, { label: "Show Arrow" }, React.createElement(CheckBox, { disabled: !isTooltipEnabled, checked: sparklineOptions.tooltip?.showArrow, onChange: (showArrow) => handleChange('tooltip', { ...sparklineOptions.tooltip, showArrow }) })), React.createElement(FormRow, { label: "Interaction Enabled" }, React.createElement(CheckBox, { disabled: !isTooltipEnabled, checked: sparklineOptions.tooltip?.interaction?.enabled, onChange: (enabled) => handleChange('tooltip', { ...sparklineOptions.tooltip, interaction: { enabled }, }) })), React.createElement(FormRow, { label: "Range" }, React.createElement(Box, { maxWidth: 160 }, React.createElement(Select, { disabled: !isTooltipEnabled, value: sparklineOptions.tooltip?.range ?? 'nearest', onChange: (range) => handleChange('tooltip', { ...sparklineOptions.tooltip, range }), options: interactionRanges }))), React.createElement(FormRow, { label: "Position Type" }, React.createElement(Box, { maxWidth: 160 }, React.createElement(Select, { disabled: !isTooltipEnabled, value: sparklineOptions.tooltip?.position?.type ?? 'pointer', onChange: (type) => handleChange('tooltip', { ...sparklineOptions.tooltip, position: { ...sparklineOptions.tooltip?.position, type }, }), options: positionTypes }))), React.createElement(FormRow, { label: "Position Offset X" }, React.createElement(AdaptableInput, { disabled: !isTooltipEnabled, title: "The horizontal offset in pixels for the position of the tooltip.", type: "number", value: sparklineOptions.tooltip?.position?.xOffset ?? '', onChange: (e) => handleChange('tooltip', { ...sparklineOptions.tooltip, position: { ...sparklineOptions.tooltip?.position, xOffset: Number(e.target.value) }, }) })), React.createElement(FormRow, { label: "Position Offset Y" }, React.createElement(AdaptableInput, { disabled: !isTooltipEnabled, title: "The vertical offset in pixels for the position of the tooltip.", type: "number", value: sparklineOptions.tooltip?.position?.yOffset ?? '', onChange: (e) => handleChange('tooltip', { ...sparklineOptions.tooltip, position: { ...sparklineOptions.tooltip?.position, yOffset: Number(e.target.value) }, }) })))); }; const SparklineMarkerOptions = ({ options, onChange }) => { const { api } = useOnePageAdaptableWizardContext(); const sparklineOptions = options; const handleChange = (value) => { onChange({ ...options, marker: { ...options.marker, ...value, }, }); }; const markerShapes = [ { value: 'circle', label: 'Circle' }, { value: 'cross', label: 'Cross' }, { value: 'diamond', label: 'Diamond' }, { value: 'heart', label: 'Heart' }, { value: 'plus', label: 'Plus' }, { value: 'pin', label: 'Pin' }, { value: 'square', label: 'Square' }, { value: 'star', label: 'Star' }, { value: 'triangle', label: 'Triangle' }, ]; const isMarkerEnabled = sparklineOptions.marker?.enabled ?? false; return (React.createElement(FormLayout, null, React.createElement(FormRow, { label: "Show Markers" }, React.createElement(CheckBox, { checked: isMarkerEnabled, onChange: (enabled) => handleChange({ enabled }) })), React.createElement(FormRow, { label: "Marker Size" }, React.createElement(AdaptableInput, { disabled: !isMarkerEnabled, type: "number", min: 1, value: sparklineOptions.marker?.size ?? '', onChange: (e) => handleChange({ size: Number(e.target.value) }), title: "The size in pixels of the markers" })), React.createElement(FormRow, { label: "Marker Shape" }, React.createElement(Box, { maxWidth: 160 }, React.createElement(Select, { disabled: !isMarkerEnabled, value: sparklineOptions.marker?.shape, onChange: (shape) => handleChange({ shape: shape }), options: markerShapes }))), React.createElement(FormRow, { label: "Fill" }, React.createElement(ColorPicker, { disabled: !isMarkerEnabled, title: "The colour for filling markers", api: api, value: sparklineOptions.marker?.fill, onChange: (fill) => handleChange({ fill }) })), React.createElement(FormRow, { label: "Stroke" }, React.createElement(Flex, { alignItems: "center" }, React.createElement(ColorPicker, { disabled: !isMarkerEnabled, title: "The colour for the marker stroke", api: api, value: sparklineOptions.marker?.stroke, onChange: (stroke) => handleChange({ stroke }) }), React.createElement(Box, { ml: 2, mr: 1 }, "Width"), React.createElement(AdaptableInput, { disabled: !isMarkerEnabled, style: { width: '70px' }, type: "number", min: 0, value: sparklineOptions.marker?.strokeWidth ?? '', onChange: (e) => handleChange({ strokeWidth: Number(e.target.value) }), title: "The width of the marker stroke in pixels" }))))); }; const SparklineHighlightOptions = ({ options, onChange, }) => { const { api } = useOnePageAdaptableWizardContext(); const sparklineOptions = options; const handleItemChange = (value) => { onChange({ ...options, highlightStyle: { ...options.highlightStyle, item: { ...options.highlightStyle?.item, ...value, }, }, }); }; const handleSeriesChange = (value) => { onChange({ ...options, highlightStyle: { ...options.highlightStyle, series: { ...options.highlightStyle?.series, ...value, }, }, }); }; return (React.createElement(FormLayout, null, React.createElement(FormRow, { label: "Item Fill" }, React.createElement(ColorPicker, { title: "The colour for filling highlighted items", api: api, value: sparklineOptions.highlightStyle?.item?.fill, onChange: (fill) => handleItemChange({ fill }) })), React.createElement(FormRow, { label: "Item Stroke" }, React.createElement(Flex, { alignItems: "center" }, React.createElement(ColorPicker, { title: "The colour for the highlighted item stroke", api: api, value: sparklineOptions.highlightStyle?.item?.stroke, onChange: (stroke) => handleItemChange({ stroke }) }), React.createElement(Box, { ml: 2, mr: 1 }, "Width"), React.createElement(AdaptableInput, { style: { width: '70px' }, type: "number", min: 0, value: sparklineOptions.highlightStyle?.item?.strokeWidth ?? '', onChange: (e) => handleItemChange({ strokeWidth: Number(e.target.value) }), title: "The width of the highlighted item stroke in pixels" }))), React.createElement(FormRow, { label: "Series" }, React.createElement(Flex, { alignItems: "center" }, React.createElement(CheckBox, { checked: sparklineOptions.highlightStyle?.series?.enabled ?? false, onChange: (enabled) => handleSeriesChange({ enabled }) }), React.createElement(Box, { ml: 2, mr: 1 }, "Opacity"), React.createElement(AdaptableInput, { disabled: !sparklineOptions.highlightStyle?.series?.enabled, style: { width: '70px' }, type: "number", min: 0, max: 1, step: 0.1, value: sparklineOptions.highlightStyle?.series?.dimOpacity ?? '', onChange: (e) => handleSeriesChange({ dimOpacity: Number(e.target.value) }), title: "The opacity of the whole series when another series is highlighted" }), React.createElement(Box, { ml: 2, mr: 1 }, "Stroke Width"), React.createElement(AdaptableInput, { disabled: !sparklineOptions.highlightStyle?.series?.enabled, style: { width: '70px' }, type: "number", min: 0, value: sparklineOptions.highlightStyle?.series?.strokeWidth ?? '', onChange: (e) => handleSeriesChange({ strokeWidth: Number(e.target.value) }), title: "The stroke width when markers are hovered or tooltip is shown" }))))); }; const test = { type: 'line', xName: 'test', };