@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
JavaScript
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))) })] }) }));
};