UNPKG

@adaptabletools/adaptable

Version:

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

160 lines (159 loc) 12.9 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import * as React from 'react'; import Input from '../../../../components/Input'; import Radio, { RadioGroup, radioGroupStyling } from '../../../../components/Radio'; import { useAdaptable } from '../../../AdaptableContext'; import { CollapsibleWizardCard } from '../../../Wizard/CollapsibleWizardCard'; import { columnFilter } from './Utilities'; import { AdaptableFormControlTextClear } from '../../../Components/Forms/AdaptableFormControlTextClear'; import { ColumnGroupTag } from '../../../Components/ColumnGroupTag'; import { ColumnTag, Tag } from '../../../../components/Tag'; import { Box, Flex } from '../../../../components/Flex'; import { getLayoutWizardOrderedColumns } from './layoutWizardColumns'; import { cn } from '../../../../lib/utils'; import { COLUMN_PINNING_OPTIONS, formatColumnSizingBrief, getExplicitSizingDisplayValues, getLayoutExplicitSizedColumnIds, getLayoutPinnedColumnIds, hasExplicitLayoutSizing, } from './columnLayoutHelpers'; const PinningColumnRow = (props) => { const columnPinning = props.layout.ColumnPinning?.[props.column.columnId]; const currentPin = columnPinning === 'left' || columnPinning === 'right' ? columnPinning : 'None'; return (_jsxs(Flex, { alignItems: "center", className: cn('ab-Layout-Wizard__ColumnListRow', 'twa:bg-primary twa:text-primary-foreground twa:rounded-standard', 'twa:gap-2 twa:py-1.5 twa:px-2 twa:min-h-[2.5rem]'), "data-name": `pinning-row-${props.column.columnId}`, children: [_jsx(Box, { className: "twa:flex-1 twa:min-w-0 twa:truncate", children: _jsxs(Flex, { alignItems: "center", children: [props.column.friendlyName ?? props.column.columnId, _jsx(ColumnGroupTag, { column: props.column })] }) }), _jsx(RadioGroup, { orientation: "horizontal", variant: "text-only", className: cn(radioGroupStyling.horizontalTextOnly, 'twa:shrink-0'), value: currentPin, name: `pinning-${props.column.columnId}`, onRadioChange: (value) => { props.onPinChange(props.column.columnId, value === 'None' ? null : value); }, children: COLUMN_PINNING_OPTIONS.map((option) => (_jsx(Radio, { value: option.value, "data-name": `pinning-${props.column.columnId}-${option.value}`, children: option.label }, option.value))) })] })); }; const SizingColumnRow = (props) => { const sizing = props.layout.ColumnSizing?.[props.column.columnId]; const displayValues = getExplicitSizingDisplayValues(props.column.columnId, sizing, props.resolveDefaultWidth); const resizable = props.column.resizable !== false; const parseNumberInput = (value) => { const parsed = parseFloat(value); return typeof parsed === 'number' && !isNaN(parsed) ? parsed : undefined; }; const sizingLabelClass = 'twa:text-xs twa:opacity-70 twa:shrink-0'; const sizingInputClass = 'ab-Layout-Wizard__ColumnLayoutSizingInput ab-Layout-Wizard__ColumnPropertiesEditor__Input twa:!min-h-0 twa:text-2'; const sizingField = (label, inputName, value, onChange) => (_jsxs(Flex, { alignItems: "center", className: "twa:gap-1 twa:shrink-0", children: [_jsx(Box, { className: sizingLabelClass, children: label }), _jsx(Input, { "data-name": inputName, className: sizingInputClass, type: "number", placeholder: "\u2014", disabled: !resizable, onChange: (event) => { onChange(parseNumberInput(event.target.value)); }, value: value ?? '' })] })); return (_jsxs(Flex, { alignItems: "center", className: cn('ab-Layout-Wizard__ColumnListRow', 'twa:bg-primary twa:text-primary-foreground twa:rounded-standard', 'twa:gap-2 twa:py-1.5 twa:px-2 twa:min-h-[2.5rem] twa:min-w-0'), "data-name": `sizing-row-${props.column.columnId}`, children: [_jsx(Box, { className: "twa:flex-1 twa:min-w-0 twa:truncate", children: _jsxs(Flex, { alignItems: "center", children: [props.column.friendlyName ?? props.column.columnId, _jsx(ColumnGroupTag, { column: props.column })] }) }), _jsxs(Flex, { alignItems: "center", className: "twa:gap-4 twa:flex-shrink-0", children: [sizingField('Width', `sizing-width-${props.column.columnId}`, displayValues.width, (value) => props.onColumnWidthChange(props.column.columnId, value)), sizingField('Flex', `sizing-flex-${props.column.columnId}`, displayValues.flex, (value) => props.onColumnFlexChange(props.column.columnId, value)), sizingField('Min', `sizing-min-${props.column.columnId}`, displayValues.minWidth, (value) => props.onColumnMinWidthChange(props.column.columnId, value)), sizingField('Max', `sizing-max-${props.column.columnId}`, displayValues.maxWidth, (value) => props.onColumnMaxWidthChange(props.column.columnId, value))] })] })); }; export const buildColumnPinningSummary = (layout, adaptable) => { const leftPinned = getLayoutPinnedColumnIds(layout, 'left'); const rightPinned = getLayoutPinnedColumnIds(layout, 'right'); if (!leftPinned.length && !rightPinned.length) { return _jsx(Tag, { children: "None pinned" }); } return (_jsxs(Flex, { flexDirection: "column", className: "twa:gap-2", children: [leftPinned.length ? (_jsxs(Flex, { flexWrap: "wrap", className: "twa:gap-1 twa:items-center", children: [_jsx(Box, { className: "twa:text-xs twa:opacity-70", children: "Left:" }), leftPinned.map((columnId) => (_jsx(ColumnTag, { children: adaptable.api.columnApi.getFriendlyNameForColumnId(columnId, layout) }, columnId)))] })) : null, rightPinned.length ? (_jsxs(Flex, { flexWrap: "wrap", className: "twa:gap-1 twa:items-center", children: [_jsx(Box, { className: "twa:text-xs twa:opacity-70", children: "Right:" }), rightPinned.map((columnId) => (_jsx(ColumnTag, { children: adaptable.api.columnApi.getFriendlyNameForColumnId(columnId, layout) }, columnId)))] })) : null] })); }; export const buildColumnSizingSummary = (layout, adaptable, resolveDefaultWidth) => { const sizedColumnIds = getLayoutExplicitSizedColumnIds(layout, resolveDefaultWidth); if (!sizedColumnIds.length) { return _jsx(Tag, { children: "Default sizing" }); } return (_jsx(Flex, { flexWrap: "wrap", className: "twa:gap-1", children: sizedColumnIds.map((columnId) => (_jsxs(ColumnTag, { children: [adaptable.api.columnApi.getFriendlyNameForColumnId(columnId, layout), " (", formatColumnSizingBrief(columnId, layout.ColumnSizing?.[columnId], resolveDefaultWidth), ")"] }, columnId))) })); }; export const ColumnPinningWizardCard = (props) => { const adaptable = useAdaptable(); const [pinningSearch, setPinningSearch] = React.useState(''); const layoutColumns = React.useMemo(() => getLayoutWizardOrderedColumns(adaptable, props.layout), [adaptable, props.layout]); const filteredPinningColumns = pinningSearch ? layoutColumns.filter((col) => columnFilter(col, pinningSearch)) : layoutColumns; const handlePinChange = (columnId, pinning) => { const ColumnPinning = { ...props.layout.ColumnPinning }; if (pinning) { ColumnPinning[columnId] = pinning; } else { delete ColumnPinning[columnId]; } props.onChange({ ...props.layout, ColumnPinning, }); }; const leftPinned = getLayoutPinnedColumnIds(props.layout, 'left'); const rightPinned = getLayoutPinnedColumnIds(props.layout, 'right'); const pinnedColumnIds = [...leftPinned, ...rightPinned]; return (_jsx(CollapsibleWizardCard, { ...props.bindCard('pinning', { fillAvailable: true }), surface: "panel", "data-name": "column-pinning", title: "Pinning", help: "Pin columns to the left or right of the grid", collapsedHelp: "", compactSummary: pinnedColumnIds.length ? (_jsxs("span", { children: [pinnedColumnIds.length, " pinned", leftPinned.length && rightPinned.length ? ` (${leftPinned.length} left, ${rightPinned.length} right)` : leftPinned.length ? ' (left)' : ' (right)'] })) : ('None pinned'), summary: buildColumnPinningSummary(props.layout, adaptable), className: "twa:overflow-hidden twa:flex twa:flex-col", bodyClassName: "twa:min-h-[200px] twa:max-h-[420px] twa:overflow-hidden twa:flex twa:flex-col", children: _jsxs(Flex, { flexDirection: "column", className: "twa:gap-2 twa:h-full twa:min-h-0 twa:p-1", children: [_jsx(AdaptableFormControlTextClear, { value: pinningSearch, OnTextChange: setPinningSearch, placeholder: "Search columns...", className: "twa:w-full" }), _jsx(Flex, { flexDirection: "column", className: "twa:gap-0.5 twa:flex-1 twa:min-h-0 twa:overflow-y-auto", children: filteredPinningColumns.map((column) => (_jsx(PinningColumnRow, { column: column, layout: props.layout, onPinChange: handlePinChange }, column.columnId))) })] }) })); }; export const ColumnSizingWizardCard = (props) => { const adaptable = useAdaptable(); const [sizingSearch, setSizingSearch] = React.useState(''); const resolveDefaultWidth = React.useCallback((columnId) => adaptable.getDefaultColumnWidthForCol(columnId), [adaptable]); const layoutColumns = React.useMemo(() => getLayoutWizardOrderedColumns(adaptable, props.layout), [adaptable, props.layout]); const filteredSizingColumns = sizingSearch ? layoutColumns.filter((col) => columnFilter(col, sizingSearch)) : layoutColumns; const updateColumnSizing = (columnId, update) => { const ColumnSizing = { ...props.layout.ColumnSizing }; const colSizingForCol = { ...(ColumnSizing[columnId] ?? {}) }; const updated = update(colSizingForCol); if (hasExplicitLayoutSizing(columnId, updated, resolveDefaultWidth)) { ColumnSizing[columnId] = updated; } else { delete ColumnSizing[columnId]; } props.onChange({ ...props.layout, ColumnSizing, }); }; const handleColumnWidthChange = (columnId, width) => { updateColumnSizing(columnId, (colSizing) => { const next = { ...colSizing }; if (width == null || width === resolveDefaultWidth(columnId)) { delete next.Width; } else { delete next.Flex; next.Width = width; } return next; }); }; const handleColumnFlexChange = (columnId, flex) => { updateColumnSizing(columnId, (colSizing) => { const next = { ...colSizing }; if (flex == null) { delete next.Flex; } else { delete next.Width; next.Flex = flex; } return next; }); }; const handleColumnMinWidthChange = (columnId, minWidth) => { updateColumnSizing(columnId, (colSizing) => { const next = { ...colSizing }; if (minWidth == null) { delete next.MinWidth; } else { next.MinWidth = minWidth; } return next; }); }; const handleColumnMaxWidthChange = (columnId, maxWidth) => { updateColumnSizing(columnId, (colSizing) => { const next = { ...colSizing }; if (maxWidth == null) { delete next.MaxWidth; } else { next.MaxWidth = maxWidth; } return next; }); }; const sizedColumnIds = getLayoutExplicitSizedColumnIds(props.layout, resolveDefaultWidth); return (_jsx(CollapsibleWizardCard, { ...props.bindCard('sizing', { fillAvailable: true }), surface: "panel", "data-name": "column-sizing", title: "Sizing", help: "Set width, flex, and min/max overrides. Default column widths are not stored in the Layout.", collapsedHelp: "", compactSummary: sizedColumnIds.length ? `${sizedColumnIds.length} custom ${sizedColumnIds.length === 1 ? 'size' : 'sizes'}` : 'Default sizing', summary: buildColumnSizingSummary(props.layout, adaptable, resolveDefaultWidth), className: "twa:overflow-hidden twa:flex twa:flex-col", bodyClassName: "twa:min-h-[200px] twa:max-h-[420px] twa:overflow-hidden twa:flex twa:flex-col", children: _jsxs(Flex, { flexDirection: "column", className: "twa:gap-1.5 twa:h-full twa:min-h-0 twa:p-1", children: [_jsx(AdaptableFormControlTextClear, { value: sizingSearch, OnTextChange: setSizingSearch, placeholder: "Search columns...", className: "twa:w-full" }), _jsx(Flex, { flexDirection: "column", className: "twa:gap-0.5 twa:flex-1 twa:min-h-0 twa:overflow-y-auto", children: filteredSizingColumns.map((column) => (_jsx(SizingColumnRow, { column: column, layout: props.layout, resolveDefaultWidth: resolveDefaultWidth, onColumnWidthChange: handleColumnWidthChange, onColumnFlexChange: handleColumnFlexChange, onColumnMinWidthChange: handleColumnMinWidthChange, onColumnMaxWidthChange: handleColumnMaxWidthChange }, column.columnId))) })] }) })); };