@adaptabletools/adaptable
Version:
Powerful AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements
178 lines (177 loc) • 11.9 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { CheckBox } from '../../../components/CheckBox';
import ErrorBox from '../../../components/ErrorBox';
import FormLayout, { FormRow } from '../../../components/FormLayout';
import { Tag } from '../../../components/Tag';
import { ColorPicker } from '../../../components/ColorPicker';
import { useOnePageAdaptableWizardContext } from '../../Wizard/OnePageAdaptableWizard';
import { Box, Flex } from '../../../components/Flex';
import { SingleSelect } from '../../../components/NewSelect';
import Input from '../../../components/Input';
import { getCellBoxStyleSummaryItems, StyledColumnCellStyleEditor, } from './StyledColumnSliceStyleEditors';
import { Card } from '../../../components/Card';
import { renderSummaryStringTags } from '../../Wizard/SummaryColorTag';
import { DEFAULT_RATING_GAP, DEFAULT_RATING_ICON, DEFAULT_RATING_MAX, DEFAULT_RATING_SIZE, } from './StyledColumnWizardStyleSection/Components/StyledColumnRatingPreview';
const STYLE_FORM_SIZES = ['200px', '1fr'];
const ICON_CHOICES = [
{ value: 'Star', label: 'Star' },
{ value: 'Heart', label: 'Heart' },
{ value: 'Circle', label: 'Circle' },
{ value: 'Thumb', label: 'Thumb' },
];
const formatRatingToolTipSummary = (toolTipText) => toolTipText
?.map((t) => (t === 'CellValue' ? 'Cell Value' : 'Percentage Value'))
.join(' + ') ?? '';
const buildStyledColumnRatingStyleSummaryStrings = (rating, options) => {
const items = [
`Max: ${rating.Max ?? DEFAULT_RATING_MAX}`,
`Icon: ${rating.Icon ?? DEFAULT_RATING_ICON}`,
];
if (rating.FilledColor) {
items.push(`Filled Colour: ${rating.FilledColor}`);
}
if (rating.EmptyColor) {
items.push(`Empty Colour: ${rating.EmptyColor}`);
}
if (rating.Size != null) {
items.push(`Icon Size: ${rating.Size}px`);
}
if (rating.Gap != null) {
items.push(`Icon Gap: ${rating.Gap}px`);
}
items.push(`Allow Half: ${(rating.AllowHalf ?? true) ? 'Yes' : 'No'}`);
items.push(`Show Value: ${rating.ShowValue ? 'Yes' : 'No'}`);
if (rating.ToolTipText?.length) {
items.push(`Tooltip: ${formatRatingToolTipSummary(rating.ToolTipText)}`);
}
else if (options.includeEmptyTooltip) {
items.push('Tooltip: No Tooltip');
}
getCellBoxStyleSummaryItems(rating.Cell).forEach(({ label, value }) => {
items.push(`${label}: ${value}`);
});
return items;
};
export const getStyledColumnRatingStyleViewValues = (data) => {
const rating = data.RatingStyle;
if (!rating) {
return [];
}
return buildStyledColumnRatingStyleSummaryStrings(rating, {
includeEmptyTooltip: false,
});
};
const resolveCssVar = (varName, fallbackHex) => {
if (typeof window === 'undefined')
return fallbackHex;
try {
const v = getComputedStyle(document.documentElement)
.getPropertyValue(varName)
.trim();
return v || fallbackHex;
}
catch {
return fallbackHex;
}
};
const getDisplayedFilledColor = (rating) => rating.FilledColor || resolveCssVar('--ab-color-warn', '#f5a623');
const getDisplayedEmptyColor = (rating) => {
if (rating.EmptyColor)
return rating.EmptyColor;
if (typeof window === 'undefined')
return 'rgba(127, 127, 127, 0.22)';
try {
const fg = getComputedStyle(document.body).color || 'rgb(0, 0, 0)';
const m = fg.match(/^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/);
if (m) {
return `rgba(${m[1]}, ${m[2]}, ${m[3]}, 0.22)`;
}
}
catch {
}
return 'rgba(127, 127, 127, 0.22)';
};
export const renderStyledColumnRatingSummary = (data) => {
const rating = data.RatingStyle;
if (!rating) {
return _jsx(Tag, { children: "No Styling Defined" });
}
const items = buildStyledColumnRatingStyleSummaryStrings(rating, {
includeEmptyTooltip: true,
});
return renderSummaryStringTags(items);
};
export const isValidRatingStyle = (data) => {
const rating = data.RatingStyle;
if (!rating) {
return 'Rating Style is missing';
}
if (rating.Max != undefined && (rating.Max < 1 || !Number.isFinite(rating.Max))) {
return 'Max must be a positive number';
}
if (rating.Size != undefined && rating.Size < 4) {
return 'Icon size must be at least 4 pixels';
}
return true;
};
export const StyledColumnWizardRatingSection = (props) => {
const { data, api } = useOnePageAdaptableWizardContext();
const rating = data.RatingStyle ?? {};
const disabled = !data.ColumnId;
if (!data.ColumnId) {
return (_jsx(Box, { children: _jsx(ErrorBox, { className: "twa:mt-2", children: "You need to select a column before styling." }) }));
}
const update = (patch) => {
props.onChange({
...data,
RatingStyle: { ...rating, ...patch },
});
};
const toggleToolTipText = (token, checked) => {
const current = rating.ToolTipText ?? [];
const next = checked
? [...current.filter((t) => t !== token), token]
: current.filter((t) => t !== token);
update({ ToolTipText: next });
};
return (_jsxs(Box, { children: [_jsxs(Card, { shadow: false, className: "twa:mb-3", children: [_jsx(Card.Title, { children: "Icon" }), _jsx(Card.Body, { children: _jsxs(FormLayout, { sizes: [...STYLE_FORM_SIZES], children: [_jsx(FormRow, { label: "Max:", children: _jsxs(Flex, { alignItems: "center", className: "twa:gap-2", children: [_jsx(Input, { type: "number", min: 1, step: 1, value: rating.Max ?? '', placeholder: String(DEFAULT_RATING_MAX), style: { width: 80 }, onChange: (event) => {
const raw = event.target.value;
if (raw === '' || raw == null) {
update({ Max: undefined });
return;
}
const parsed = Number(raw);
update({
Max: Number.isFinite(parsed) && parsed >= 1 ? Math.floor(parsed) : undefined,
});
} }), _jsx(Box, { className: "twa:text-xs twa:opacity-70 twa:min-w-0 twa:shrink", children: "Icon count and rating cap (no auto scaling is applied)" })] }) }), _jsx(FormRow, { label: "Icon:", children: _jsx(Box, { className: "twa:max-w-[160px]", children: _jsx(SingleSelect, { className: "twa:w-full", value: rating.Icon ?? DEFAULT_RATING_ICON, onValueChange: (v) => update({ Icon: v }), items: ICON_CHOICES }) }) }), _jsx(FormRow, { label: "Filled Colour:", children: _jsx(ColorPicker, { disabled: disabled, api: api, value: getDisplayedFilledColor(rating), onChange: (c) => update({ FilledColor: c }) }) }), _jsx(FormRow, { label: "Empty Colour:", children: _jsx(ColorPicker, { disabled: disabled, api: api, value: getDisplayedEmptyColor(rating), onChange: (c) => update({ EmptyColor: c }) }) }), _jsx(FormRow, { label: "Icon Size (px):", children: _jsxs(Flex, { alignItems: "center", className: "twa:gap-2", children: [_jsx(Input, { type: "number", min: 4, step: 1, value: rating.Size ?? '', placeholder: String(DEFAULT_RATING_SIZE), style: { width: 80 }, onChange: (event) => {
const raw = event.target.value;
if (raw === '' || raw == null) {
update({ Size: undefined });
return;
}
const parsed = Number(raw);
update({
Size: Number.isFinite(parsed) && parsed >= 4 ? parsed : undefined,
});
} }), _jsx(Box, { className: "twa:text-xs twa:opacity-70 twa:min-w-0 twa:shrink", children: "Square pixel size of each icon" })] }) }), _jsx(FormRow, { label: "Icon Gap (px):", children: _jsxs(Flex, { alignItems: "center", className: "twa:gap-2", children: [_jsx(Input, { type: "number", min: 0, step: 1, value: rating.Gap ?? '', placeholder: String(DEFAULT_RATING_GAP), style: { width: 80 }, onChange: (event) => {
const raw = event.target.value;
if (raw === '' || raw == null) {
update({ Gap: undefined });
return;
}
const parsed = Number(raw);
update({
Gap: Number.isFinite(parsed) && parsed >= 0 ? parsed : undefined,
});
} }), _jsx(Box, { className: "twa:text-xs twa:opacity-70 twa:min-w-0 twa:shrink", children: "Pixel space between adjacent icons" })] }) }), _jsx(FormRow, { label: "Allow Half Icons:", children: _jsx(CheckBox, { disabled: disabled, className: "twa:ml-2", checked: rating.AllowHalf ?? true, onChange: (checked) => update({ AllowHalf: checked }), children: "Render fractional values as a partial icon (e.g. 3.5 \u2192 \u2605\u2605\u2605\u00BD\u2606)" }) })] }) })] }), _jsxs(Card, { shadow: false, className: "twa:mb-3", children: [_jsx(Card.Title, { children: "Text" }), _jsx(Card.Body, { children: _jsxs(FormLayout, { sizes: [...STYLE_FORM_SIZES], children: [_jsx(FormRow, { label: "Show Value:", children: _jsx(CheckBox, { disabled: disabled, className: "twa:ml-2", checked: rating.ShowValue ?? false, onChange: (checked) => update({ ShowValue: checked }), children: "Display the numeric value beside the icons" }) }), _jsx(FormRow, { label: "Tooltip:", children: _jsxs(Flex, { flexDirection: "column", className: "twa:gap-1 twa:ml-2", children: [_jsx(CheckBox, { disabled: disabled, checked: rating.ToolTipText?.includes('CellValue') ?? false, onChange: (checked) => toggleToolTipText('CellValue', checked), children: "Cell Value" }), _jsx(CheckBox, { disabled: disabled, checked: rating.ToolTipText?.includes('PercentageValue') ?? false, onChange: (checked) => toggleToolTipText('PercentageValue', checked), children: "Percentage Value (value \u00F7 Max)" })] }) })] }) })] }), _jsxs(Card, { shadow: false, className: "twa:mb-3", children: [_jsxs(Card.Title, { children: [_jsx(Box, { className: "twa:font-medium", children: "Cell" }), _jsx(Box, { className: "twa:text-xs twa:opacity-70 twa:font-normal twa:max-w-[500px]", children: "Optional Cell Style properties overrides Format Column properties)" })] }), _jsx(Card.Body, { children: _jsx(StyledColumnCellStyleEditor, { api: api, disabled: disabled, value: rating.Cell, onChange: (next) => {
if (next) {
update({ Cell: next });
}
else {
const cleaned = { ...rating };
delete cleaned.Cell;
props.onChange({ ...data, RatingStyle: cleaned });
}
} }) })] })] }));
};