@adaptabletools/adaptable 23.0.0-canary.7 → 23.0.0-canary.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/index.css +75 -9
  2. package/package.json +1 -1
  3. package/src/AdaptableState/StyledColumnState.d.ts +8 -850
  4. package/src/AdaptableState/StyledColumnState.js +1 -9
  5. package/src/AdaptableState/StyledColumns/BadgeStyle.d.ts +143 -0
  6. package/src/AdaptableState/StyledColumns/BadgeStyle.js +9 -0
  7. package/src/AdaptableState/StyledColumns/BulletChartStyle.d.ts +147 -0
  8. package/src/AdaptableState/StyledColumns/BulletChartStyle.js +1 -0
  9. package/src/AdaptableState/StyledColumns/Common/BarChartCellText.d.ts +60 -0
  10. package/src/AdaptableState/StyledColumns/Common/BarChartCellText.js +6 -0
  11. package/src/AdaptableState/StyledColumns/Common/BarChartMarker.d.ts +24 -0
  12. package/src/AdaptableState/StyledColumns/Common/BarChartMarker.js +5 -0
  13. package/src/AdaptableState/StyledColumns/Common/CellTextOptions.d.ts +13 -0
  14. package/src/AdaptableState/StyledColumns/Common/CellTextOptions.js +6 -0
  15. package/src/AdaptableState/StyledColumns/Common/NumericStyledColumn.d.ts +79 -0
  16. package/src/AdaptableState/StyledColumns/Common/NumericStyledColumn.js +9 -0
  17. package/src/AdaptableState/StyledColumns/GradientStyle.d.ts +48 -0
  18. package/src/AdaptableState/StyledColumns/GradientStyle.js +1 -0
  19. package/src/AdaptableState/StyledColumns/IconStyle.d.ts +158 -0
  20. package/src/AdaptableState/StyledColumns/IconStyle.js +1 -0
  21. package/src/AdaptableState/StyledColumns/PercentBarStyle.d.ts +32 -0
  22. package/src/AdaptableState/StyledColumns/PercentBarStyle.js +1 -0
  23. package/src/AdaptableState/StyledColumns/RangeBarStyle.d.ts +155 -0
  24. package/src/AdaptableState/StyledColumns/RangeBarStyle.js +1 -0
  25. package/src/AdaptableState/StyledColumns/RatingStyle.d.ts +111 -0
  26. package/src/AdaptableState/StyledColumns/RatingStyle.js +1 -0
  27. package/src/AdaptableState/StyledColumns/SparklineStyle.d.ts +21 -0
  28. package/src/AdaptableState/StyledColumns/SparklineStyle.js +1 -0
  29. package/src/Api/ColumnScopeApi.d.ts +1 -1
  30. package/src/Api/Implementation/ColumnScopeApiImpl.d.ts +1 -1
  31. package/src/Api/Internal/StyledColumnInternalApi.d.ts +3 -1
  32. package/src/Utilities/Helpers/IconStylePresets.d.ts +1 -1
  33. package/src/Utilities/Helpers/StyledColumnGradientHelper.d.ts +3 -1
  34. package/src/Utilities/Helpers/barChartCellText.d.ts +63 -0
  35. package/src/Utilities/Helpers/barChartCellText.js +316 -0
  36. package/src/Utilities/Helpers/percentBarPreviewHelper.d.ts +2 -1
  37. package/src/Utilities/Helpers/percentBarPreviewHelper.js +3 -8
  38. package/src/View/Alert/Wizard/AlertButtonsEditor.js +159 -126
  39. package/src/View/Alert/Wizard/AlertNotificationWizardSection.js +1 -1
  40. package/src/View/Alert/Wizard/AlertWizard.js +9 -1
  41. package/src/View/Components/AdaptableObjectList/AdaptableObjectCompactList.js +3 -2
  42. package/src/View/Components/AdaptableObjectList/AdaptableObjectList.js +3 -2
  43. package/src/View/Components/AdaptableObjectList/objectListActionButtonStyles.d.ts +2 -0
  44. package/src/View/Components/AdaptableObjectList/objectListActionButtonStyles.js +2 -0
  45. package/src/View/Components/Buttons/EntityListActionButtons.js +1 -1
  46. package/src/View/Components/Buttons/SuspendToggleButton/SuspendToggleButton.d.ts +1 -0
  47. package/src/View/Components/Buttons/SuspendToggleButton/SuspendToggleButton.js +8 -8
  48. package/src/View/Components/ColumnFilter/ColumnFilter.js +14 -1
  49. package/src/View/Components/Popups/AdaptablePopup/AdaptablePopupModuleView.js +1 -1
  50. package/src/View/Components/RangesComponent.d.ts +2 -1
  51. package/src/View/Export/ExportSchedulesTab.js +3 -4
  52. package/src/View/Filter/FilterViewPanel.js +1 -1
  53. package/src/View/Layout/Wizard/sections/RowSummarySection.js +129 -103
  54. package/src/View/StyledColumn/Wizard/BadgePillStyleEditor.d.ts +1 -1
  55. package/src/View/StyledColumn/Wizard/StyledColumnBadgeSection.js +36 -30
  56. package/src/View/StyledColumn/Wizard/StyledColumnSliceStyleEditors.d.ts +1 -3
  57. package/src/View/StyledColumn/Wizard/StyledColumnWizardBulletSection.js +73 -58
  58. package/src/View/StyledColumn/Wizard/StyledColumnWizardIconSection.js +38 -11
  59. package/src/View/StyledColumn/Wizard/StyledColumnWizardRangeBarSection.js +86 -44
  60. package/src/View/StyledColumn/Wizard/StyledColumnWizardStyleSection/Components/BarChartCellTextLayoutEditor.d.ts +9 -0
  61. package/src/View/StyledColumn/Wizard/StyledColumnWizardStyleSection/Components/BarChartCellTextLayoutEditor.js +35 -0
  62. package/src/View/StyledColumn/Wizard/StyledColumnWizardStyleSection/Components/BarChartCellTextPreview.d.ts +23 -0
  63. package/src/View/StyledColumn/Wizard/StyledColumnWizardStyleSection/Components/BarChartCellTextPreview.js +57 -0
  64. package/src/View/StyledColumn/Wizard/StyledColumnWizardStyleSection/Components/BulletRangesSummaryPreview.d.ts +1 -1
  65. package/src/View/StyledColumn/Wizard/StyledColumnWizardStyleSection/Components/GradientSummaryPreview.d.ts +2 -1
  66. package/src/View/StyledColumn/Wizard/StyledColumnWizardStyleSection/Components/RangeBarRangesSummaryPreview.d.ts +1 -1
  67. package/src/View/StyledColumn/Wizard/StyledColumnWizardStyleSection/Components/StyledColumnBadgePreview.js +3 -2
  68. package/src/View/StyledColumn/Wizard/StyledColumnWizardStyleSection/Components/StyledColumnBulletPreview.d.ts +2 -1
  69. package/src/View/StyledColumn/Wizard/StyledColumnWizardStyleSection/Components/StyledColumnBulletPreview.js +13 -17
  70. package/src/View/StyledColumn/Wizard/StyledColumnWizardStyleSection/Components/StyledColumnChartListPreviews.d.ts +2 -1
  71. package/src/View/StyledColumn/Wizard/StyledColumnWizardStyleSection/Components/StyledColumnChartListPreviews.js +5 -5
  72. package/src/View/StyledColumn/Wizard/StyledColumnWizardStyleSection/Components/StyledColumnIconPreview.js +2 -2
  73. package/src/View/StyledColumn/Wizard/StyledColumnWizardStyleSection/Components/StyledColumnPercentBarPreview.js +14 -7
  74. package/src/View/StyledColumn/Wizard/StyledColumnWizardStyleSection/Components/StyledColumnRangeBarPreview.js +11 -17
  75. package/src/View/StyledColumn/Wizard/StyledColumnWizardStyleSection/Components/StyledColumnRatingPreview.d.ts +2 -1
  76. package/src/View/StyledColumn/Wizard/StyledColumnWizardStyleSection/StyledColumnWizardStyleSection.js +18 -54
  77. package/src/agGrid/AgGridColumnAdapter.js +2 -1
  78. package/src/agGrid/cellRenderers/BadgeRenderer.js +7 -5
  79. package/src/agGrid/cellRenderers/BulletChartRenderer.js +43 -42
  80. package/src/agGrid/cellRenderers/IconRenderer.d.ts +2 -1
  81. package/src/agGrid/cellRenderers/IconRenderer.js +13 -11
  82. package/src/agGrid/cellRenderers/PercentBarRenderer.js +24 -96
  83. package/src/agGrid/cellRenderers/RangeBarRenderer.js +49 -46
  84. package/src/env.js +2 -2
  85. package/src/metamodel/adaptable.metamodel.d.ts +80 -14
  86. package/src/metamodel/adaptable.metamodel.js +1 -1
  87. package/src/migration/VersionUpgrade23.d.ts +27 -31
  88. package/src/migration/VersionUpgrade23.js +110 -29
  89. package/src/types.d.ts +12 -1
  90. package/tsconfig.esm.tsbuildinfo +1 -1
@@ -1,8 +1,7 @@
1
- import { jsxs as _jsxs, Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import * as React from 'react';
3
3
  import { CheckBox } from '../../../../components/CheckBox';
4
4
  import FormLayout, { FormRow } from '../../../../components/FormLayout';
5
- import Panel from '../../../../components/Panel';
6
5
  import SimpleButton from '../../../../components/SimpleButton';
7
6
  import { ButtonNew } from '../../../Components/Buttons/ButtonNew';
8
7
  import { Card } from '../../../../components/Card';
@@ -20,6 +19,9 @@ import { ColumnGroupTag } from '../../../Components/ColumnGroupTag';
20
19
  import ArrayExtensions from '../../../../Utilities/Extensions/ArrayExtensions';
21
20
  import { Box, Flex } from '../../../../components/Flex';
22
21
  import { SingleSelect } from '../../../../components/NewSelect';
22
+ import { CollapsibleWizardCard, getWizardAccordionSectionClassName, useWizardCardAccordion, } from '../../../Wizard/CollapsibleWizardCard';
23
+ import { cn } from '../../../../lib/utils';
24
+ import { objectListActionButtonClassName } from '../../../Components/AdaptableObjectList/objectListActionButtonStyles';
23
25
  export const areSummaryRowsValid = (layout) => {
24
26
  if (!layout.RowSummaries)
25
27
  return true;
@@ -34,6 +36,7 @@ export const areSummaryRowsValid = (layout) => {
34
36
  });
35
37
  return valid;
36
38
  };
39
+ const rowSummaryCardId = (index) => `row-summary-${index}`;
37
40
  const availableExpressionsForColumnTypeCache = new Map();
38
41
  const getAvailableExpressionsForColumnType = (columnType, availableScalarExpressions) => {
39
42
  const key = columnType;
@@ -99,18 +102,27 @@ const getDefaultRowSummaryExpression = (column, availableScalarExpressions, layo
99
102
  }
100
103
  return optionValues[0] ?? null;
101
104
  };
105
+ const RowSummaryPositionTag = ({ position }) => _jsx(Tag, { className: "twa:shrink-0", children: position });
106
+ const RowSummaryCardSummary = ({ rowSummary }) => {
107
+ const adaptable = useAdaptable();
108
+ const columnIds = Object.keys(rowSummary.ColumnsMap ?? {}).filter((colId) => colId !== 'Source' && colId !== 'Uuid');
109
+ if (!columnIds.length) {
110
+ return _jsx(Tag, { children: "No columns" });
111
+ }
112
+ return (_jsx(Flex, { flexWrap: "wrap", className: "twa:gap-1", children: columnIds.map((colId) => (_jsxs(ColumnTag, { children: [rowSummary.ColumnsMap[colId], "(", adaptable.api.columnApi.getFriendlyNameForColumnId(colId), ")"] }, colId))) }));
113
+ };
102
114
  export const RowSummarySectionSummary = () => {
103
115
  const adaptable = useAdaptable();
104
116
  const { data: layout } = useOnePageAdaptableWizardContext();
105
117
  return (_jsx(Box, { className: "twa:flex twa:flex-col", children: layout.RowSummaries?.length ? (layout.RowSummaries.map((rowSummary, index) => {
106
- return (_jsx(_Fragment, { children: _jsxs(Box, { className: "twa:mr-1 twa:mb-1", children: [rowSummary.Position, ":", ' ', Object.keys(rowSummary.ColumnsMap).map((colId) => {
107
- if (colId === 'Source' || colId === 'Uuid')
108
- return null;
109
- return (_jsxs(ColumnTag, { className: "twa:mr-1", children: [rowSummary.ColumnsMap[colId], "(", adaptable.api.columnApi.getFriendlyNameForColumnId(colId), ")"] }, colId));
110
- })] }, index) }));
118
+ return (_jsxs(Box, { className: "twa:mr-1 twa:mb-1", children: [rowSummary.Position, ":", ' ', Object.keys(rowSummary.ColumnsMap).map((colId) => {
119
+ if (colId === 'Source' || colId === 'Uuid')
120
+ return null;
121
+ return (_jsxs(ColumnTag, { className: "twa:mr-1", children: [rowSummary.ColumnsMap[colId], "(", adaptable.api.columnApi.getFriendlyNameForColumnId(colId), ")"] }, colId));
122
+ })] }, index));
111
123
  })) : (_jsx(Tag, { children: "No Row Summaries" })) }));
112
124
  };
113
- const RowSummaryEditor = React.memo(({ rowSummary, onChange, availableScalarExpressions, onDelete, }) => {
125
+ const RowSummaryEditorForm = React.memo(({ rowSummary, onChange, availableScalarExpressions, }) => {
114
126
  const { data: layout } = useOnePageAdaptableWizardContext();
115
127
  const adaptable = useAdaptable();
116
128
  const columns = React.useMemo(() => {
@@ -126,109 +138,123 @@ const RowSummaryEditor = React.memo(({ rowSummary, onChange, availableScalarExpr
126
138
  sortUnorderedItems: false,
127
139
  }).map((colId) => adaptable.api.columnApi.getColumnWithColumnId(colId));
128
140
  }, [rowSummary.ColumnsMap]);
129
- return (_jsx(Panel, { className: "twa:mb-3", bodyProps: { className: 'twa:p-2' }, children: _jsxs(Card, { shadow: false, children: [_jsxs(Card.Title, { className: "twa:w-full", children: [_jsx(Box, { className: "twa:font-medium twa:flex-1", children: "Row Summary" }), _jsxs(Flex, { alignItems: "center", className: "twa:gap-2 twa:shrink-0", children: [_jsx(SuspendToggleButton, { onSuspend: () => {
130
- onChange({
131
- ...rowSummary,
132
- IsSuspended: true,
133
- });
134
- }, onUnSuspend: () => {
135
- onChange({
136
- ...rowSummary,
137
- IsSuspended: false,
138
- });
139
- }, suspendableObject: rowSummary }), _jsx(SimpleButton, { icon: "delete", onClick: () => {
140
- onDelete();
141
- } })] })] }), _jsxs(Card.Body, { className: "twa:p-1 twa:gap-3", children: [_jsxs(FormLayout, { children: [_jsx(FormRow, { label: "Position", children: _jsx(SingleSelect, { items: [
142
- {
143
- label: 'Top',
144
- value: 'Top',
145
- },
146
- {
147
- label: 'Bottom',
148
- value: 'Bottom',
149
- },
150
- ], value: rowSummary.Position, onValueChange: (position) => {
151
- onChange({
152
- ...rowSummary,
153
- Position: position,
154
- });
155
- } }) }), _jsx(FormRow, { label: "", children: _jsx(CheckBox, { checked: rowSummary.IncludeOnlyFilteredRows ?? true, onChange: (IncludeOnlyFilteredRows) => {
156
- onChange({
157
- ...rowSummary,
158
- IncludeOnlyFilteredRows,
159
- });
160
- }, children: "Include Only Filtered Rows" }) })] }), _jsxs(Card, { shadow: false, className: "twa:h-[400px] twa:overflow-hidden twa:flex twa:flex-col", children: [_jsxs(Card.Title, { children: [_jsx(Box, { className: "twa:font-medium", children: "Column Aggregations" }), _jsx(Box, { className: "twa:text-xs twa:opacity-70 twa:font-normal twa:max-w-[520px]", children: "Select columns and choose an aggregation function for each" })] }), _jsx(Card.Body, { className: "twa:flex-1 twa:min-h-0 twa:overflow-hidden twa:p-1", children: _jsx(ValueSelector, { style: { minHeight: 0, maxHeight: '100%' }, showFilterInput: true, toggleSelectionOnRowClick: false, filter: columnFilter, toIdentifier: (column) => column.columnId, toLabel: (option) => option.friendlyName ?? option.columnId, options: columns, optionLayout: "label-beside-checkbox", toListLabel: (column) => {
161
- const label = column.friendlyName ?? column.columnId;
162
- const disabled = !(column.columnId in (rowSummary.ColumnsMap ?? {}));
163
- if (disabled) {
164
- return (_jsxs(Flex, { alignItems: "center", className: "twa:gap-2", children: [label, _jsx(ColumnGroupTag, { column: column }), _jsx(SingleSelect, { disabled: true, items: [{ label: 'Select Aggregation', value: null }] })] }));
165
- }
166
- const expressionOptions = buildRowSummaryExpressionOptions(column, availableScalarExpressions, layout);
167
- const expression = rowSummary.ColumnsMap[column.columnId];
168
- return (_jsxs(Flex, { children: [_jsxs(Flex, { className: "twa:mr-2", alignItems: 'center', children: [label, _jsx(ColumnGroupTag, { column: column })] }), _jsx(SingleSelect, { value: expression, items: expressionOptions, onValueChange: (expression) => {
169
- onChange({
170
- ...rowSummary,
171
- ColumnsMap: {
172
- ...rowSummary.ColumnsMap,
173
- [column.columnId]: expression,
174
- },
175
- });
176
- } })] }));
177
- }, value: Object.keys(rowSummary.ColumnsMap), onChange: (colIds) => {
178
- const newColumnsMap = {};
179
- colIds.forEach((colId) => {
180
- const existing = rowSummary.ColumnsMap[colId];
181
- if (existing) {
182
- newColumnsMap[colId] = existing;
183
- return;
184
- }
185
- const column = adaptable.api.columnApi.getColumnWithColumnId(colId);
186
- newColumnsMap[colId] = column
187
- ? getDefaultRowSummaryExpression(column, availableScalarExpressions, layout)
188
- : null;
189
- });
190
- onChange({
191
- ...rowSummary,
192
- ColumnsMap: newColumnsMap,
193
- });
194
- } }) })] })] })] }) }));
141
+ return (_jsxs(Box, { className: "twa:flex twa:flex-col twa:gap-3 twa:h-full twa:min-h-0 twa:overflow-hidden", children: [_jsxs(FormLayout, { children: [_jsx(FormRow, { label: "Position", children: _jsx(SingleSelect, { items: [
142
+ {
143
+ label: 'Top',
144
+ value: 'Top',
145
+ },
146
+ {
147
+ label: 'Bottom',
148
+ value: 'Bottom',
149
+ },
150
+ ], value: rowSummary.Position, onValueChange: (position) => {
151
+ onChange({
152
+ ...rowSummary,
153
+ Position: position,
154
+ });
155
+ } }) }), _jsx(FormRow, { label: "", children: _jsx(CheckBox, { checked: rowSummary.IncludeOnlyFilteredRows ?? true, onChange: (IncludeOnlyFilteredRows) => {
156
+ onChange({
157
+ ...rowSummary,
158
+ IncludeOnlyFilteredRows,
159
+ });
160
+ }, children: "Include Only Filtered Rows" }) })] }), _jsxs(Card, { shadow: false, className: "twa:flex-1 twa:min-h-0 twa:overflow-hidden twa:flex twa:flex-col", children: [_jsxs(Card.Title, { children: [_jsx(Box, { className: "twa:font-medium", children: "Column Aggregations" }), _jsx(Box, { className: "twa:text-xs twa:opacity-70 twa:font-normal twa:max-w-[520px]", children: "Select columns and choose an aggregation function for each" })] }), _jsx(Card.Body, { className: "twa:flex-1 twa:min-h-0 twa:overflow-hidden twa:p-1", children: _jsx(ValueSelector, { style: { minHeight: 0, maxHeight: '100%' }, showFilterInput: true, toggleSelectionOnRowClick: false, filter: columnFilter, toIdentifier: (column) => column.columnId, toLabel: (option) => option.friendlyName ?? option.columnId, options: columns, optionLayout: "label-beside-checkbox", toListLabel: (column) => {
161
+ const label = column.friendlyName ?? column.columnId;
162
+ const disabled = !(column.columnId in (rowSummary.ColumnsMap ?? {}));
163
+ if (disabled) {
164
+ return (_jsxs(Flex, { alignItems: "center", className: "twa:gap-2", children: [label, _jsx(ColumnGroupTag, { column: column }), _jsx(SingleSelect, { disabled: true, items: [{ label: 'Select Aggregation', value: null }] })] }));
165
+ }
166
+ const expressionOptions = buildRowSummaryExpressionOptions(column, availableScalarExpressions, layout);
167
+ const expression = rowSummary.ColumnsMap[column.columnId];
168
+ return (_jsxs(Flex, { children: [_jsxs(Flex, { className: "twa:mr-2", alignItems: 'center', children: [label, _jsx(ColumnGroupTag, { column: column })] }), _jsx(SingleSelect, { value: expression, items: expressionOptions, onValueChange: (expression) => {
169
+ onChange({
170
+ ...rowSummary,
171
+ ColumnsMap: {
172
+ ...rowSummary.ColumnsMap,
173
+ [column.columnId]: expression,
174
+ },
175
+ });
176
+ } })] }));
177
+ }, value: Object.keys(rowSummary.ColumnsMap), onChange: (colIds) => {
178
+ const newColumnsMap = {};
179
+ colIds.forEach((colId) => {
180
+ const existing = rowSummary.ColumnsMap[colId];
181
+ if (existing) {
182
+ newColumnsMap[colId] = existing;
183
+ return;
184
+ }
185
+ const column = adaptable.api.columnApi.getColumnWithColumnId(colId);
186
+ newColumnsMap[colId] = column
187
+ ? getDefaultRowSummaryExpression(column, availableScalarExpressions, layout)
188
+ : null;
189
+ });
190
+ onChange({
191
+ ...rowSummary,
192
+ ColumnsMap: newColumnsMap,
193
+ });
194
+ } }) })] })] }));
195
195
  });
196
196
  export const RowSummarySection = (props) => {
197
197
  const adaptable = useAdaptable();
198
198
  const { data: layout } = useOnePageAdaptableWizardContext();
199
+ const rowSummaries = layout.RowSummaries ?? [];
199
200
  const availableScalarExpressions = React.useMemo(() => {
200
201
  const sytemExpressions = adaptable.api.internalApi
201
202
  .getQueryLanguageService()
202
203
  .getModuleExpressionFunctionsMap(LayoutModuleId).aggregatedScalarFunctions;
203
204
  return sytemExpressions;
204
205
  }, []);
205
- return (_jsx(Flex, { flexDirection: "column", className: "twa:gap-3 twa:p-3 twa:h-full", children: _jsxs(Card, { shadow: false, children: [_jsxs(Card.Title, { children: [_jsx(Box, { className: "twa:font-medium", children: "Row Summaries" }), _jsx(Box, { className: "twa:text-xs twa:opacity-70 twa:font-normal twa:max-w-[520px]", children: "Add summary rows at the top or bottom of the grid with aggregated column values" })] }), _jsxs(Card.Body, { className: "twa:p-1", children: [_jsxs(Flex, { className: "twa:mb-2", children: [_jsx(Flex, { className: "twa:flex-1" }), _jsx(ButtonNew, { onClick: () => {
206
- props.onChange({
207
- ...layout,
208
- RowSummaries: [
209
- ...(layout.RowSummaries ?? []),
210
- {
211
- Position: 'Top',
212
- ColumnsMap: {},
213
- IncludeOnlyFilteredRows: true,
214
- },
215
- ],
216
- });
217
- }, children: "Add Row Summary" })] }), (layout.RowSummaries ?? []).map((rowSummary, index) => {
218
- return (_jsx(RowSummaryEditor, { onDelete: () => {
219
- const newSummaries = [...layout.RowSummaries];
220
- newSummaries.splice(index, 1);
221
- props.onChange({
222
- ...layout,
223
- RowSummaries: newSummaries,
224
- });
225
- }, availableScalarExpressions: availableScalarExpressions, rowSummary: rowSummary, onChange: (rowSummary) => {
226
- const newSummaries = [...layout.RowSummaries];
227
- newSummaries[index] = rowSummary;
228
- props.onChange({
229
- ...layout,
230
- RowSummaries: newSummaries,
231
- });
232
- } }, index));
233
- })] })] }) }));
206
+ const { bindCard, hasExpandedCard, expandedFillsSpace, expandedId, setExpandedId } = useWizardCardAccordion(null);
207
+ const handleAddRowSummary = () => {
208
+ const newIndex = rowSummaries.length;
209
+ props.onChange({
210
+ ...layout,
211
+ RowSummaries: [
212
+ ...rowSummaries,
213
+ {
214
+ Position: 'Top',
215
+ ColumnsMap: {},
216
+ IncludeOnlyFilteredRows: true,
217
+ },
218
+ ],
219
+ });
220
+ setExpandedId(rowSummaryCardId(newIndex));
221
+ };
222
+ const handleDeleteRowSummary = (index) => {
223
+ const cardId = rowSummaryCardId(index);
224
+ const newSummaries = [...rowSummaries];
225
+ newSummaries.splice(index, 1);
226
+ props.onChange({
227
+ ...layout,
228
+ RowSummaries: newSummaries,
229
+ });
230
+ if (expandedId === cardId) {
231
+ setExpandedId(null);
232
+ return;
233
+ }
234
+ if (expandedId?.startsWith('row-summary-')) {
235
+ const expandedIndex = Number(expandedId.replace('row-summary-', ''));
236
+ if (!Number.isNaN(expandedIndex) && expandedIndex > index) {
237
+ setExpandedId(rowSummaryCardId(expandedIndex - 1));
238
+ }
239
+ }
240
+ };
241
+ return (_jsxs(Box, { className: cn(getWizardAccordionSectionClassName(hasExpandedCard, expandedFillsSpace), 'twa:p-3'), children: [_jsx(Box, { className: "twa:text-xs twa:opacity-70 twa:mb-2 twa:max-w-[520px] twa:shrink-0", children: "Add summary rows at the top or bottom of the grid with aggregated column values" }), _jsx(Flex, { className: "twa:justify-end twa:mb-2 twa:shrink-0", children: _jsx(ButtonNew, { onClick: handleAddRowSummary, children: "Add Row Summary" }) }), _jsx(Flex, { flexDirection: "column", className: "twa:gap-3 twa:min-h-0", children: rowSummaries.map((rowSummary, index) => {
242
+ const cardBinding = bindCard(rowSummaryCardId(index), { fillAvailable: true });
243
+ return (_jsx(CollapsibleWizardCard, { ...cardBinding, surface: "panel", "data-name": `row-summary-${index}`, title: `Row Summary ${index + 1}`, help: "Configure position, filters, and column aggregations for this summary row", collapsedHelp: false, compactSummary: _jsx(RowSummaryPositionTag, { position: rowSummary.Position }), headerVisual: !cardBinding.expanded ? (_jsx(RowSummaryPositionTag, { position: rowSummary.Position })) : undefined, headerActions: _jsxs(_Fragment, { children: [cardBinding.expanded ? (_jsx(SuspendToggleButton, { iconSize: 26, className: objectListActionButtonClassName('suspend'), onSuspend: () => {
244
+ const newSummaries = [...rowSummaries];
245
+ newSummaries[index] = { ...rowSummary, IsSuspended: true };
246
+ props.onChange({ ...layout, RowSummaries: newSummaries });
247
+ }, onUnSuspend: () => {
248
+ const newSummaries = [...rowSummaries];
249
+ newSummaries[index] = { ...rowSummary, IsSuspended: false };
250
+ props.onChange({ ...layout, RowSummaries: newSummaries });
251
+ }, suspendableObject: rowSummary })) : null, _jsx(SimpleButton, { icon: "delete", variant: "text", tooltip: "Delete row summary", className: objectListActionButtonClassName('delete'), onClick: () => handleDeleteRowSummary(index) })] }), summary: _jsx(RowSummaryCardSummary, { rowSummary: rowSummary }), 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 twa:!pt-0", children: _jsx(RowSummaryEditorForm, { rowSummary: rowSummary, availableScalarExpressions: availableScalarExpressions, onChange: (nextRowSummary) => {
252
+ const newSummaries = [...rowSummaries];
253
+ newSummaries[index] = nextRowSummary;
254
+ props.onChange({
255
+ ...layout,
256
+ RowSummaries: newSummaries,
257
+ });
258
+ } }) }, rowSummaryCardId(index)));
259
+ }) })] }));
234
260
  };
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { AdaptableApi } from '../../../Api/AdaptableApi';
3
- import { BadgePillStyle } from '../../../AdaptableState/StyledColumnState';
3
+ import { BadgePillStyle } from '../../../AdaptableState/StyledColumns/BadgeStyle';
4
4
  export interface BadgePillStyleEditorProps {
5
5
  api: AdaptableApi;
6
6
  /** Current pill style (may be undefined / partial). */
@@ -57,32 +57,47 @@ const getBadgeDefinitionSummaryItems = (badge, api) => {
57
57
  items.push({ label: 'Rule', value: rule });
58
58
  items.push({ label: 'Shape', value: badge.Shape ?? 'Rounded' });
59
59
  items.push(...getBadgePillStyleSummaryItems(badge.PillStyle));
60
- if (badge.Icon) {
60
+ const iconProps = badge.IconProperties;
61
+ if (iconProps?.Icon) {
61
62
  items.push({
62
63
  label: 'Icon',
63
- value: 'name' in badge.Icon ? badge.Icon.name : 'Custom',
64
- icon: badge.Icon,
64
+ value: 'name' in iconProps.Icon ? iconProps.Icon.name : 'Custom',
65
+ icon: iconProps.Icon,
65
66
  });
66
67
  }
67
- if (badge.IconOnly) {
68
+ if (iconProps?.IconOnly) {
68
69
  items.push({ label: 'Icon Only', value: 'Yes' });
69
70
  }
70
- if (badge.Icon && badge.IconPosition) {
71
- items.push({ label: 'Icon Position', value: badge.IconPosition });
71
+ if (iconProps?.Icon && iconProps.Position) {
72
+ items.push({ label: 'Icon Position', value: iconProps.Position });
72
73
  }
73
- if (typeof badge.IconGap === 'number') {
74
- items.push({ label: 'Icon Gap', value: `${badge.IconGap}px` });
74
+ if (typeof iconProps?.Gap === 'number') {
75
+ items.push({ label: 'Icon Gap', value: `${iconProps.Gap}px` });
75
76
  }
76
77
  return items;
77
78
  };
78
- const BadgePreview = ({ badge, density, previewValue }) => (_jsx(Badge, { pillStyle: badge.PillStyle, icon: badge.Icon, iconPosition: badge.IconPosition, shape: badge.Shape, density: density, iconGap: badge.IconGap, children: badge.IconOnly ? '' : previewValue }));
79
+ const BadgePreview = ({ badge, density, previewValue }) => (_jsx(Badge, { pillStyle: badge.PillStyle, icon: badge.IconProperties?.Icon, iconPosition: badge.IconProperties?.Position, shape: badge.Shape, density: density, iconGap: badge.IconProperties?.Gap, children: badge.IconProperties?.IconOnly ? '' : previewValue }));
79
80
  const BadgeCardSummary = ({ badge, api }) => (_jsx(CollapsibleWizardValueSummary, { value: renderSummaryLabelValueTags(getBadgeDefinitionSummaryItems(badge, api)) }));
80
81
  const BadgeEditorForm = (props) => {
81
82
  const { api } = useOnePageAdaptableWizardContext();
82
83
  const { badge, columnId, onChange } = props;
83
84
  const predicateDefs = api.styledColumnApi.internalApi.getBadgePredicateDefsForColumn(columnId);
84
85
  const currentShape = badge.Shape ?? 'Rounded';
85
- const hasIcon = Boolean(badge.Icon);
86
+ const iconProps = badge.IconProperties;
87
+ const hasIcon = Boolean(iconProps?.Icon);
88
+ const updateIconProperties = (patch) => {
89
+ const next = {
90
+ ...(iconProps ?? { Icon: undefined }),
91
+ ...patch,
92
+ };
93
+ if (!next.Icon) {
94
+ const cleaned = { ...badge };
95
+ delete cleaned.IconProperties;
96
+ onChange(cleaned);
97
+ return;
98
+ }
99
+ onChange({ ...badge, IconProperties: next });
100
+ };
86
101
  return (_jsxs(Flex, { flexDirection: "column", className: "twa:gap-3 twa:p-2", children: [_jsxs(Card, { shadow: false, children: [_jsxs(Card.Title, { children: [_jsx(Box, { className: "twa:font-medium", children: "Shape" }), _jsx(Box, { className: "twa:text-xs twa:opacity-70 twa:font-normal twa:max-w-[520px]", children: "Define shape of the corners for this badge" })] }), _jsx(Card.Body, { className: "twa:p-1", children: _jsx(RadioGroup, { orientation: "horizontal", name: `ab-badge-shape-${columnId}`, value: currentShape, onRadioChange: (value) => onChange({ ...badge, Shape: value }), className: "twa:gap-3", children: SHAPE_CHOICES.map((choice) => (_jsx(Radio, { value: choice.value, children: choice.label }, choice.value))) }) })] }), _jsxs(Card, { shadow: false, children: [_jsxs(Card.Title, { children: [_jsx(Box, { className: "twa:font-medium", children: "Style" }), _jsx(Box, { className: "twa:text-xs twa:opacity-70 twa:font-normal twa:max-w-[520px]", children: "Colours and font styling for the badge pill" })] }), _jsx(Card.Body, { className: "twa:p-1", children: _jsx(BadgePillStyleEditor, { embedded: true, api: api, value: badge.PillStyle, onChange: (next) => {
87
102
  if (next) {
88
103
  onChange({ ...badge, PillStyle: next });
@@ -100,31 +115,23 @@ const BadgeEditorForm = (props) => {
100
115
  }, onClear: () => onChange({
101
116
  ...badge,
102
117
  Predicate: undefined,
103
- }) })) : (_jsx(ErrorBox, { children: "Select a column first" })) })] }), _jsxs(Card, { shadow: false, children: [_jsxs(Card.Title, { children: [_jsx(Box, { className: "twa:font-medium", children: "Icon" }), _jsx(Box, { className: "twa:text-xs twa:opacity-70 twa:font-normal twa:max-w-[520px]", children: "Optional icon inside the badge \u2014 position and spacing apply once an icon is selected" })] }), _jsx(Card.Body, { className: "twa:p-1", children: _jsxs(FormLayout, { children: [_jsx(FormRow, { label: "Icon", children: !badge.Icon || 'name' in badge.Icon ? (_jsx(AdaptableIconSelector, { value: badge?.Icon && 'name' in badge.Icon ? badge.Icon.name : undefined, onChange: (iconName) => {
118
+ }) })) : (_jsx(ErrorBox, { children: "Select a column first" })) })] }), _jsxs(Card, { shadow: false, children: [_jsxs(Card.Title, { children: [_jsx(Box, { className: "twa:font-medium", children: "Icon" }), _jsx(Box, { className: "twa:text-xs twa:opacity-70 twa:font-normal twa:max-w-[520px]", children: "Optional icon inside the badge \u2014 position and spacing apply once an icon is selected" })] }), _jsx(Card.Body, { className: "twa:p-1", children: _jsxs(FormLayout, { children: [_jsx(FormRow, { label: "Icon", children: !iconProps?.Icon || 'name' in iconProps.Icon ? (_jsx(AdaptableIconSelector, { value: iconProps?.Icon && 'name' in iconProps.Icon ? iconProps.Icon.name : undefined, onChange: (iconName) => {
104
119
  if (iconName) {
105
- onChange({
106
- ...badge,
107
- Icon: {
108
- name: iconName,
109
- },
120
+ updateIconProperties({
121
+ Icon: { name: iconName },
110
122
  });
111
123
  }
112
124
  else {
113
- onChange({
114
- ...badge,
115
- Icon: undefined,
116
- IconOnly: undefined,
117
- IconPosition: undefined,
118
- IconGap: undefined,
119
- });
125
+ const cleaned = { ...badge };
126
+ delete cleaned.IconProperties;
127
+ onChange(cleaned);
120
128
  }
121
- } })) : (_jsx(AdaptableIconComponent, { icon: badge.Icon })) }), _jsx(FormRow, { label: "Icon Position", children: _jsx(Box, { className: "twa:max-w-[160px]", children: _jsx(SingleSelect, { disabled: !hasIcon, className: "twa:w-full", value: badge.IconPosition ?? 'Start', onValueChange: (v) => onChange({ ...badge, IconPosition: v }), items: [
129
+ } })) : (_jsx(AdaptableIconComponent, { icon: iconProps.Icon })) }), _jsx(FormRow, { label: "Icon Position", children: _jsx(Box, { className: "twa:max-w-[160px]", children: _jsx(SingleSelect, { disabled: !hasIcon, className: "twa:w-full", value: iconProps?.Position ?? 'Start', onValueChange: (v) => updateIconProperties({ Position: v }), items: [
122
130
  { value: 'Start', label: 'Start' },
123
131
  { value: 'End', label: 'End' },
124
- ] }) }) }), _jsx(FormRow, { label: "Show Icon Only", children: _jsx(CheckBox, { disabled: !hasIcon, checked: badge.IconOnly, onClick: () => onChange({ ...badge, IconOnly: !badge.IconOnly }) }) }), _jsx(FormRow, { label: "Icon Gap", children: _jsxs(Flex, { alignItems: "center", className: "twa:gap-2", children: [_jsx(NumberInput, { disabled: !hasIcon || badge.IconOnly, value: badge.IconGap ?? '', placeholder: "auto", step: 1, min: 0, style: { width: 70 }, onChange: (value) => {
125
- onChange({
126
- ...badge,
127
- IconGap: typeof value === 'number' && value >= 0 ? value : undefined,
132
+ ] }) }) }), _jsx(FormRow, { label: "Show Icon Only", children: _jsx(CheckBox, { disabled: !hasIcon, checked: iconProps?.IconOnly, onClick: () => updateIconProperties({ IconOnly: !iconProps?.IconOnly }) }) }), _jsx(FormRow, { label: "Icon Gap", children: _jsxs(Flex, { alignItems: "center", className: "twa:gap-2", children: [_jsx(NumberInput, { disabled: !hasIcon || iconProps?.IconOnly, value: iconProps?.Gap ?? '', placeholder: "auto", step: 1, min: 0, style: { width: 70 }, onChange: (value) => {
133
+ updateIconProperties({
134
+ Gap: typeof value === 'number' && value >= 0 ? value : undefined,
128
135
  });
129
136
  } }), _jsx(Box, { className: "twa:text-xs twa:opacity-70", children: "px between icon and text \u2014 leave blank to follow Density" })] }) })] }) })] })] }));
130
137
  };
@@ -188,8 +195,7 @@ export const StyledColumnBadgeSection = (props) => {
188
195
  ? api.columnApi.getColumnDataTypeForColumnId(data.ColumnId)
189
196
  : 'text';
190
197
  const previewValue = getBadgePreviewValue(dataType);
191
- const initialExpandedCardId = badges.length === 1 ? badgeCardId(0) : null;
192
- const { bindCard, hasExpandedCard, expandedFillsSpace, expandedId, setExpandedId } = useWizardCardAccordion(initialExpandedCardId);
198
+ const { bindCard, hasExpandedCard, expandedFillsSpace, expandedId, setExpandedId } = useWizardCardAccordion(null);
193
199
  const handleAddBadge = () => {
194
200
  const newIndex = badges.length;
195
201
  props.onChange({
@@ -13,9 +13,7 @@ export interface StyledColumnFontStyleEditorProps {
13
13
  disabled?: boolean;
14
14
  /**
15
15
  * When true, the Alignment row is omitted entirely. Used by Styled Columns
16
- * that own horizontal alignment elsewhere (e.g. Percent Bar's "Auto / Left /
17
- * Center / Right" controls drive `CellTextAlignment`, so showing a second
18
- * Alignment row inside the font editor is confusing).
16
+ * that own horizontal alignment elsewhere (e.g. Badge row layout).
19
17
  */
20
18
  hideAlignment?: boolean;
21
19
  }