@arbor-education/design-system.components 0.2.1 → 0.2.2

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  ## 0.1.4
2
2
 
3
+ ## 0.2.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [#98](https://github.com/arbor-education/design-system.components/pull/98) [`4c10758`](https://github.com/arbor-education/design-system.components/commit/4c10758ba2dd30679d87828b2dada1281c5471a6) Thanks [@angusmglfraser](https://github.com/angusmglfraser)! - MIS-64989 implement drag-select on table
8
+
9
+ - [#102](https://github.com/arbor-education/design-system.components/pull/102) [`6c67a72`](https://github.com/arbor-education/design-system.components/commit/6c67a727f79841d45e5aa599cc79495c6fbf440c) Thanks [@angusmglfraser](https://github.com/angusmglfraser)! - MIS-67025 add ag grid license key
10
+
3
11
  ## 0.2.1
4
12
 
5
13
  ### Patch Changes
@@ -14,6 +14,8 @@ type TableProps<TData = any> = {
14
14
  'onTableSettingsReset'?: () => void;
15
15
  'onColumnBordersChanged'?: (val: boolean) => void;
16
16
  'onTableSpacingChanged'?: (val: TABLE_SPACING) => void;
17
+ 'enableSimultaneousRangeAndRowSelection'?: boolean;
18
+ 'disableDragSelect'?: boolean;
17
19
  } & AgGridReactProps<TData>;
18
20
  export declare enum TABLE_SPACING {
19
21
  XS = "XS",
@@ -1 +1 @@
1
- {"version":3,"file":"Table.d.ts","sourceRoot":"","sources":["../../../src/components/table/Table.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAuC,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAC;AACvF,OAAO,EAAe,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGnE,OAAO,EAA2B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAUhE,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAG1E,KAAK,UAAU,CAAC,KAAK,GAAG,GAAG,IAAI;IAC7B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,SAAS,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,SAAS,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,wBAAwB,CAAC,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,IAAI,CAAC;IACxD,sBAAsB,CAAC,EAAE,MAAM,IAAI,CAAC;IACpC,wBAAwB,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD,uBAAuB,CAAC,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,IAAI,CAAC;CACxD,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;AAI5B,oBAAY,aAAa;IACvB,EAAE,OAAO;IACT,CAAC,MAAM;IACP,CAAC,MAAM;IACP,CAAC,MAAM;CACR;AAED,eAAO,MAAM,oBAAoB;;;;;;;;EAQ/B,CAAC;AAEH,eAAO,MAAM,KAAK;YAAW,UAAU;;;;;;;;;;;;;;;;;;;CA8EtC,CAAC"}
1
+ {"version":3,"file":"Table.d.ts","sourceRoot":"","sources":["../../../src/components/table/Table.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAuC,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAC;AACvF,OAAO,EAAe,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGnE,OAAO,EAAmC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAUxE,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAK1E,KAAK,UAAU,CAAC,KAAK,GAAG,GAAG,IAAI;IAC7B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,SAAS,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,SAAS,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,wBAAwB,CAAC,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,IAAI,CAAC;IACxD,sBAAsB,CAAC,EAAE,MAAM,IAAI,CAAC;IACpC,wBAAwB,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD,uBAAuB,CAAC,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,IAAI,CAAC;IACvD,wCAAwC,CAAC,EAAE,OAAO,CAAC;IACnD,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;AAM5B,oBAAY,aAAa;IACvB,EAAE,OAAO;IACT,CAAC,MAAM;IACP,CAAC,MAAM;IACP,CAAC,MAAM;CACR;AAED,eAAO,MAAM,oBAAoB;;;;;;;;EAQ/B,CAAC;AAEH,eAAO,MAAM,KAAK;YAAW,UAAU;;;;;;;;;;;;;;;;;;;CAgHtC,CAAC"}
@@ -3,7 +3,7 @@ import { AllEnterpriseModule, ModuleRegistry } from 'ag-grid-enterprise';
3
3
  import { AgGridReact } from 'ag-grid-react';
4
4
  import { tableTheme } from './tableTheme';
5
5
  import classNames from 'classnames';
6
- import { createContext, useState } from 'react';
6
+ import { createContext, useRef, useState } from 'react';
7
7
  import { TableFooter } from './TableFooter';
8
8
  import { TableHeader } from './TableHeader';
9
9
  import { GridApiContext } from './GridApiContext';
@@ -14,6 +14,9 @@ import { RowCountInfo } from './pagination/RowCountInfo';
14
14
  import { BulkActionsDropdown } from './BulkActionsDropdown';
15
15
  import { HideColumnsDropdown } from './HideColumnsDropdown';
16
16
  import { useTableSettings } from './useTableSettings';
17
+ import { setAgGridLicenseKey } from '../../utils/setAgGridLicenseKey';
18
+ import { toggleRowSelectionInCurrentRange } from './toggleRowSelectionInCurrentRange';
19
+ setAgGridLicenseKey();
17
20
  ModuleRegistry.registerModules([AllEnterpriseModule]);
18
21
  export var TABLE_SPACING;
19
22
  (function (TABLE_SPACING) {
@@ -32,7 +35,7 @@ export const TableSettingsContext = createContext({
32
35
  resetSettings: () => { },
33
36
  });
34
37
  export const Table = (props) => {
35
- const { 'data-testid': testId, wrapperClassName, headerContent, headerTestId, hasSearch = true, footerContent, footerTestId, onGridReady, onTableSettingsChanged, onTableSettingsReset, onColumnBordersChanged, onTableSpacingChanged, ...rest } = props;
38
+ const { 'data-testid': testId, wrapperClassName, headerContent, headerTestId, hasSearch = true, footerContent, footerTestId, onGridReady, onTableSettingsChanged, onTableSettingsReset, onColumnBordersChanged, onTableSpacingChanged, enableSimultaneousRangeAndRowSelection = false, disableDragSelect = false, onCellSelectionChanged, ...rest } = props;
36
39
  const [gridApi, setGridApi] = useState(null);
37
40
  const [searchValue, setSearchValue] = useState('');
38
41
  const { settings, resetSettings, setHasColumnBorders, setTableSpacing, } = useTableSettings({
@@ -41,8 +44,14 @@ export const Table = (props) => {
41
44
  onColumnBordersChanged,
42
45
  onTableSpacingChanged,
43
46
  });
47
+ const isUsingKeyboardRef = useRef(false);
44
48
  const { hasColumnBorders, tableSpacing } = settings;
45
- return (_jsx(GridApiContext.Provider, { value: gridApi, children: _jsx(TableSettingsContext.Provider, { value: { settings, resetSettings, setHasColumnBorders, setTableSpacing }, children: _jsxs("section", { "data-testid": testId, className: classNames('ds-table__container', wrapperClassName), children: [headerContent && (_jsx(TableHeader, { "data-testid": headerTestId, hasSearch: hasSearch, searchValue: searchValue, setSearchValue: setSearchValue, children: headerContent })), _jsx(AgGridReact, { theme: tableTheme.withParams({
49
+ return (_jsx(GridApiContext.Provider, { value: gridApi, children: _jsx(TableSettingsContext.Provider, { value: {
50
+ settings,
51
+ resetSettings,
52
+ setHasColumnBorders,
53
+ setTableSpacing,
54
+ }, children: _jsxs("section", { "data-testid": testId, className: classNames('ds-table__container', wrapperClassName), onMouseDown: () => { isUsingKeyboardRef.current = false; }, onMouseUp: () => { isUsingKeyboardRef.current = false; }, onMouseMove: () => { isUsingKeyboardRef.current = false; }, onKeyDown: () => { isUsingKeyboardRef.current = true; }, onKeyUp: () => { isUsingKeyboardRef.current = true; }, children: [headerContent && (_jsx(TableHeader, { "data-testid": headerTestId, hasSearch: hasSearch, searchValue: searchValue, setSearchValue: setSearchValue, children: headerContent })), _jsx(AgGridReact, { theme: tableTheme.withParams({
46
55
  headerRowBorder: hasColumnBorders,
47
56
  rowBorder: hasColumnBorders,
48
57
  wrapperBorder: hasColumnBorders,
@@ -60,7 +69,14 @@ export const Table = (props) => {
60
69
  const { api } = event;
61
70
  setGridApi(api);
62
71
  onGridReady?.(event);
63
- }, suppressPaginationPanel: true, ...rest, ...(hasSearch && { quickFilterText: searchValue }) }), footerContent && (_jsx(TableFooter, { "data-testid": footerTestId, children: footerContent }))] }) }) }));
72
+ }, suppressPaginationPanel: true, onCellSelectionChanged: (event) => {
73
+ if ((!disableDragSelect || !enableSimultaneousRangeAndRowSelection) && gridApi && event.finished) {
74
+ toggleRowSelectionInCurrentRange(gridApi, isUsingKeyboardRef.current, disableDragSelect, enableSimultaneousRangeAndRowSelection);
75
+ }
76
+ if (onCellSelectionChanged) {
77
+ onCellSelectionChanged(event);
78
+ }
79
+ }, ...rest, ...(hasSearch && { quickFilterText: searchValue }) }), footerContent && (_jsx(TableFooter, { "data-testid": footerTestId, children: footerContent }))] }) }) }));
64
80
  };
65
81
  Table.PaginationPanel = PaginationPanel;
66
82
  Table.PageSizeSelector = PageSizeSelector;
@@ -1 +1 @@
1
- {"version":3,"file":"Table.js","sourceRoot":"","sources":["../../../src/components/table/Table.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Table.js","sourceRoot":"","sources":["../../../src/components/table/Table.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { type GridApi } from 'ag-grid-community';
2
+ export declare const toggleRowSelectionInCurrentRange: (gridApi: GridApi, isUsingKeyboard: boolean, disableDragSelect?: boolean, enableSimultaneousRangeAndRowSelection?: boolean) => void;
3
+ //# sourceMappingURL=toggleRowSelectionInCurrentRange.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toggleRowSelectionInCurrentRange.d.ts","sourceRoot":"","sources":["../../../src/components/table/toggleRowSelectionInCurrentRange.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuC,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAC;AActF,eAAO,MAAM,gCAAgC,GAC3C,SAAS,OAAO,EAChB,iBAAiB,OAAO,EACxB,2BAAyB,EACzB,gDAA8C,SAsJ/C,CAAC"}
@@ -0,0 +1,132 @@
1
+ import { SELECTION_COLUMN_ID } from 'ag-grid-community';
2
+ const getIsAnyRangeOutsideOfCheckboxColumn = (selectedCellRanges) => {
3
+ const isAnyRangeOutsideOfCheckboxColumn = selectedCellRanges.findIndex(range => range.columns.length > 1
4
+ || range.columns[0]?.getId() !== SELECTION_COLUMN_ID) > -1;
5
+ return isAnyRangeOutsideOfCheckboxColumn;
6
+ };
7
+ export const toggleRowSelectionInCurrentRange = (gridApi, isUsingKeyboard, disableDragSelect = false, enableSimultaneousRangeAndRowSelection = false) => {
8
+ // In this callback we hack the range selection to allow dragging on checkboxes
9
+ // to change the value of a range of checkboxes
10
+ //
11
+ // When you click on a cell, a single RangeSelectionChangedEvent is triggered.
12
+ // - We want to toggle the selection for this event
13
+ // - Only one cell will be selected in this case
14
+ // When you click and drag on a cell, several RangeSelectionChangedEvents are triggered.
15
+ // - The first and last ones have finished=true, and we can ignore all the others
16
+ //
17
+ // There isn't an easy way to distinguish between the start of both of these cases, so
18
+ // we treat them both the same: toggle the selection of the starting cell.
19
+ // For the click and drag case, at the end of the drag we then toggle the selection of
20
+ // all cells in the range, apart from the starting cell.
21
+ //
22
+ // There isn't any way to tell from RangeSelectionChangedEvent if the event was triggered
23
+ // by mouse or keyboard, so we maintain a this.isUsingKeyboard value for this purpose
24
+ const selectedCellRanges = gridApi.getCellRanges();
25
+ if (selectedCellRanges === null || selectedCellRanges.length === 0) {
26
+ return;
27
+ }
28
+ if (getIsAnyRangeOutsideOfCheckboxColumn(selectedCellRanges)) {
29
+ if (enableSimultaneousRangeAndRowSelection) {
30
+ return;
31
+ }
32
+ // We want to allow either selecting ranges/rows in the checkbox column,
33
+ // or selecting ranges in the other cells, but not both. This is to keep
34
+ // the bulk row action and bulk cell actions separate
35
+ //
36
+ // We want to allow selecting ranges within the checkbox column
37
+ // So that you can do shift+click to enable several columns, and
38
+ // other similar interractions
39
+ const rows = gridApi.getSelectedRows();
40
+ if (rows.length > 0) {
41
+ // Deselect all the selected rows
42
+ gridApi.deselectAll();
43
+ }
44
+ return;
45
+ }
46
+ if (disableDragSelect) {
47
+ return;
48
+ }
49
+ const { startRow: unsafeStartRow, endRow: unsafeEndRow } = selectedCellRanges[0];
50
+ if (typeof unsafeStartRow === 'undefined'
51
+ || typeof unsafeEndRow === 'undefined') {
52
+ console.error('undefined start or end row', { unsafeStartRow, unsafeEndRow });
53
+ return;
54
+ }
55
+ // We need to be careful to exclude any pinned rows
56
+ if (unsafeStartRow.rowPinned === 'top'
57
+ || unsafeStartRow.rowPinned === 'bottom') {
58
+ // If we start on a pinned row just do nothing, as there isn't an initial value to use
59
+ return;
60
+ }
61
+ // startRow will now be safe due to check above
62
+ const startRowIndex = unsafeStartRow.rowIndex;
63
+ // For end row, we shall trim to the fist last row, so you don't have to be
64
+ // really accurate with the mouse
65
+ let endRowIndex = unsafeEndRow.rowIndex;
66
+ if (unsafeEndRow.rowPinned === 'bottom') {
67
+ endRowIndex = gridApi.getDisplayedRowCount() - 1;
68
+ }
69
+ else if (unsafeEndRow.rowPinned === 'top') {
70
+ endRowIndex = 0;
71
+ }
72
+ const startingRowNode = gridApi.getDisplayedRowAtIndex(startRowIndex);
73
+ const isStartingRowNodeSelected = !!startingRowNode?.isSelected();
74
+ if (startRowIndex === endRowIndex) {
75
+ // We do not want to flip the state if we are currently using the keyboard, else
76
+ // navigating to a cell with select it.
77
+ if (!isUsingKeyboard) {
78
+ /**
79
+ * If the drag is started by a click in the cell but outside the checkbox, AG Grid registers it
80
+ * as a CellSelectionChangedEvent and this listener is then fired immediately after the mouseDown.
81
+ *
82
+ * If the drag is started by a click in the cell but inside the checkbox, AG Grid does not register
83
+ * a CellSelectionChangedEvent, so this listener doesn't fire, and is only first triggered once the
84
+ * drag moves the selection into another cell.
85
+ *
86
+ * The key difference between these two cases is that AG Grid will not toggle the cell for mouseDown
87
+ * on the checkbox, it will only do so for mouseDown and mouseUp on the same checkbox, so at the end
88
+ * of a drag on the checkbox row, if the drag started on the checkbox, it will need to be toggled at the
89
+ * end of the drag. If the drag started in a different area of the cell, it will already have been
90
+ * toggled
91
+ */
92
+ startingRowNode?.setSelected(!isStartingRowNodeSelected);
93
+ startingRowNode?.updateData({
94
+ ...startingRowNode.data,
95
+ firstToggledByClickOutsideCheckbox: true,
96
+ });
97
+ }
98
+ return;
99
+ }
100
+ const { smallestIndex, largestIndex } = startRowIndex < endRowIndex
101
+ ? {
102
+ smallestIndex: startRowIndex,
103
+ largestIndex: endRowIndex,
104
+ }
105
+ : {
106
+ smallestIndex: endRowIndex,
107
+ largestIndex: startRowIndex,
108
+ };
109
+ const initiallyToggledOutsideCheckbox = startingRowNode?.data.firstToggledByClickOutsideCheckbox;
110
+ // restoring the data on the node to clear the flag set on the cell
111
+ const {
112
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
113
+ firstToggledByClickOutsideCheckbox: _intentionallyDiscarded, ...initialStartingRowData } = startingRowNode?.data || {};
114
+ startingRowNode?.updateData(initialStartingRowData);
115
+ const shouldInvertNextUpdatedRows = !initiallyToggledOutsideCheckbox && !isUsingKeyboard;
116
+ if (shouldInvertNextUpdatedRows) {
117
+ startingRowNode?.setSelected(!isStartingRowNodeSelected);
118
+ }
119
+ gridApi.forEachNodeAfterFilterAndSort((node, index) => {
120
+ if (index >= smallestIndex
121
+ && index <= largestIndex
122
+ && index !== startRowIndex) {
123
+ if (shouldInvertNextUpdatedRows) {
124
+ node.setSelected(!isStartingRowNodeSelected);
125
+ }
126
+ else {
127
+ node.setSelected(isStartingRowNodeSelected);
128
+ }
129
+ }
130
+ });
131
+ };
132
+ //# sourceMappingURL=toggleRowSelectionInCurrentRange.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toggleRowSelectionInCurrentRange.js","sourceRoot":"","sources":["../../../src/components/table/toggleRowSelectionInCurrentRange.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAgC,MAAM,mBAAmB,CAAC;AAEtF,MAAM,oCAAoC,GAAG,CAC3C,kBAA+B,EAC/B,EAAE;IACF,MAAM,iCAAiC,GACnC,kBAAkB,CAAC,SAAS,CAC5B,KAAK,CAAC,EAAE,CACN,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;WACrB,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,mBAAmB,CACvD,GAAG,CAAC,CAAC,CAAC;IACT,OAAO,iCAAiC,CAAC;AAC3C,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAC9C,OAAgB,EAChB,eAAwB,EACxB,iBAAiB,GAAG,KAAK,EACzB,sCAAsC,GAAG,KAAK,EAC9C,EAAE;IACF,+EAA+E;IAC/E,+CAA+C;IAC/C,EAAE;IACF,8EAA8E;IAC9E,mDAAmD;IACnD,gDAAgD;IAChD,wFAAwF;IACxF,iFAAiF;IACjF,EAAE;IACF,sFAAsF;IACtF,0EAA0E;IAC1E,sFAAsF;IACtF,wDAAwD;IACxD,EAAE;IACF,yFAAyF;IACzF,qFAAqF;IAErF,MAAM,kBAAkB,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IACnD,IAAI,kBAAkB,KAAK,IAAI,IAAI,kBAAkB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnE,OAAO;IACT,CAAC;IAED,IAAI,oCAAoC,CAAC,kBAAkB,CAAC,EAAE,CAAC;QAC7D,IAAI,sCAAsC,EAAE,CAAC;YAC3C,OAAO;QACT,CAAC;QACD,wEAAwE;QACxE,wEAAwE;QACxE,qDAAqD;QACrD,EAAE;QACF,+DAA+D;QAC/D,gEAAgE;QAChE,8BAA8B;QAC9B,MAAM,IAAI,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;QACvC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpB,iCAAiC;YACjC,OAAO,CAAC,WAAW,EAAE,CAAC;QACxB,CAAC;QACD,OAAO;IACT,CAAC;IAED,IAAI,iBAAiB,EAAE,CAAC;QACtB,OAAO;IACT,CAAC;IAED,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,EAAE,YAAY,EAAE,GACpD,kBAAkB,CAAC,CAAC,CAAc,CAAC;IACvC,IACE,OAAO,cAAc,KAAK,WAAW;WAClC,OAAO,YAAY,KAAK,WAAW,EACtC,CAAC;QACD,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC,CAAC;QAC9E,OAAO;IACT,CAAC;IAED,mDAAmD;IACnD,IACE,cAAc,CAAC,SAAS,KAAK,KAAK;WAC/B,cAAc,CAAC,SAAS,KAAK,QAAQ,EACxC,CAAC;QACD,sFAAsF;QACtF,OAAO;IACT,CAAC;IACD,+CAA+C;IAC/C,MAAM,aAAa,GAAG,cAAc,CAAC,QAAQ,CAAC;IAE9C,2EAA2E;IAC3E,iCAAiC;IACjC,IAAI,WAAW,GAAG,YAAY,CAAC,QAAQ,CAAC;IACxC,IAAI,YAAY,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;QACxC,WAAW,GAAG,OAAO,CAAC,oBAAoB,EAAE,GAAG,CAAC,CAAC;IACnD,CAAC;SACI,IAAI,YAAY,CAAC,SAAS,KAAK,KAAK,EAAE,CAAC;QAC1C,WAAW,GAAG,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,eAAe,GAAG,OAAO,CAAC,sBAAsB,CAAC,aAAa,CAAC,CAAC;IACtE,MAAM,yBAAyB,GAAG,CAAC,CAAC,eAAe,EAAE,UAAU,EAAE,CAAC;IAClE,IAAI,aAAa,KAAK,WAAW,EAAE,CAAC;QAClC,gFAAgF;QAChF,uCAAuC;QACvC,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB;;;;;;;;;;;;;qBAaS;YACT,eAAe,EAAE,WAAW,CAAC,CAAC,yBAAyB,CAAC,CAAC;YACzD,eAAe,EAAE,UAAU,CAAC;gBAC1B,GAAG,eAAe,CAAC,IAAI;gBACvB,kCAAkC,EAAE,IAAI;aACzC,CAAC,CAAC;QACL,CAAC;QACD,OAAO;IACT,CAAC;IAED,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,GACjC,aAAa,GAAG,WAAW;QAC3B,CAAC,CAAC;YACE,aAAa,EAAE,aAAa;YAC5B,YAAY,EAAE,WAAW;SAC1B;QACH,CAAC,CAAC;YACE,aAAa,EAAE,WAAW;YAC1B,YAAY,EAAE,aAAa;SAC5B,CAAC;IAER,MAAM,+BAA+B,GACjC,eAAe,EAAE,IAAI,CAAC,kCAAkC,CAAC;IAE7D,mEAAmE;IACnE,MAAM;IACJ,6DAA6D;IAC7D,kCAAkC,EAAE,uBAAuB,EAC3D,GAAG,sBAAsB,EAC1B,GAAG,eAAe,EAAE,IAAI,IAAI,EAAE,CAAC;IAChC,eAAe,EAAE,UAAU,CAAC,sBAAsB,CAAC,CAAC;IAEpD,MAAM,2BAA2B,GAC7B,CAAC,+BAA+B,IAAI,CAAC,eAAe,CAAC;IAEzD,IAAI,2BAA2B,EAAE,CAAC;QAChC,eAAe,EAAE,WAAW,CAAC,CAAC,yBAAyB,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO,CAAC,6BAA6B,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QACpD,IACE,KAAK,IAAI,aAAa;eACnB,KAAK,IAAI,YAAY;eACrB,KAAK,KAAK,aAAa,EAC1B,CAAC;YACD,IAAI,2BAA2B,EAAE,CAAC;gBAChC,IAAI,CAAC,WAAW,CAAC,CAAC,yBAAyB,CAAC,CAAC;YAC/C,CAAC;iBACI,CAAC;gBACJ,IAAI,CAAC,WAAW,CAAC,yBAAyB,CAAC,CAAC;YAC9C,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const setAgGridLicenseKey: () => void;
2
+ //# sourceMappingURL=setAgGridLicenseKey.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setAgGridLicenseKey.d.ts","sourceRoot":"","sources":["../../src/utils/setAgGridLicenseKey.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,mBAAmB,YAQ/B,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { AgChartsCommunityModule } from 'ag-charts-community';
2
+ import { ModuleRegistry } from 'ag-grid-community';
3
+ import { LicenseManager, IntegratedChartsModule, AllEnterpriseModule, } from 'ag-grid-enterprise';
4
+ export const setAgGridLicenseKey = () => {
5
+ LicenseManager.setLicenseKey('Using_this_{AG_Grid}_Enterprise_key_{AG-076208}_in_excess_of_the_licence_granted_is_not_permitted___Please_report_misuse_to_legal@ag-grid.com___For_help_with_changing_this_key_please_contact_info@ag-grid.com___{Arbor_Education_Partners_Ltd}_is_granted_a_{Single_Application}_Developer_License_for_the_application_{Arbor_MIS}_only_for_{4}_Front-End_JavaScript_developers___All_Front-End_JavaScript_developers_working_on_{Arbor_MIS}_need_to_be_licensed___{Arbor_MIS}_has_been_granted_a_Deployment_License_Add-on_for_{1}_Production_Environment___This_key_works_with_{AG_Grid}_Enterprise_versions_released_before_{16_March_2026}____[v3]_[01]_MTc3MzYxOTIwMDAwMA==8820260fc59099926cf507c1e8018e49');
6
+ ModuleRegistry.registerModules([
7
+ IntegratedChartsModule.with(AgChartsCommunityModule),
8
+ AllEnterpriseModule,
9
+ ]);
10
+ };
11
+ //# sourceMappingURL=setAgGridLicenseKey.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setAgGridLicenseKey.js","sourceRoot":"","sources":["../../src/utils/setAgGridLicenseKey.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,EAAE;IACtC,cAAc,CAAC,aAAa,CAC1B,orBAAorB,CACrrB,CAAC;IACF,cAAc,CAAC,eAAe,CAAC;QAC7B,sBAAsB,CAAC,IAAI,CAAC,uBAAuB,CAAC;QACpD,mBAAmB;KACpB,CAAC,CAAC;AACL,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arbor-education/design-system.components",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "The component library for the design system (the baby)",
5
5
  "main": "dist/index.js",
6
6
  "repository": {
@@ -2,7 +2,7 @@ import { AllEnterpriseModule, ModuleRegistry, type GridApi } from 'ag-grid-enter
2
2
  import { AgGridReact, type AgGridReactProps } from 'ag-grid-react';
3
3
  import { tableTheme } from './tableTheme';
4
4
  import classNames from 'classnames';
5
- import { createContext, useState, type ReactNode } from 'react';
5
+ import { createContext, useRef, useState, type ReactNode } from 'react';
6
6
  import { TableFooter } from './TableFooter';
7
7
  import { TableHeader } from './TableHeader';
8
8
  import { GridApiContext } from './GridApiContext';
@@ -13,6 +13,8 @@ import { RowCountInfo } from './pagination/RowCountInfo';
13
13
  import { BulkActionsDropdown } from './BulkActionsDropdown';
14
14
  import { HideColumnsDropdown } from './HideColumnsDropdown';
15
15
  import { useTableSettings, type TableSettings } from './useTableSettings';
16
+ import { setAgGridLicenseKey } from 'Utils/setAgGridLicenseKey';
17
+ import { toggleRowSelectionInCurrentRange } from './toggleRowSelectionInCurrentRange';
16
18
 
17
19
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
18
20
  type TableProps<TData = any> = {
@@ -27,8 +29,12 @@ type TableProps<TData = any> = {
27
29
  'onTableSettingsReset'?: () => void;
28
30
  'onColumnBordersChanged'?: (val: boolean) => void;
29
31
  'onTableSpacingChanged'?: (val: TABLE_SPACING) => void;
32
+ 'enableSimultaneousRangeAndRowSelection'?: boolean;
33
+ 'disableDragSelect'?: boolean;
30
34
  } & AgGridReactProps<TData>;
31
35
 
36
+ setAgGridLicenseKey();
37
+
32
38
  ModuleRegistry.registerModules([AllEnterpriseModule]);
33
39
 
34
40
  export enum TABLE_SPACING {
@@ -62,6 +68,9 @@ export const Table = (props: TableProps) => {
62
68
  onTableSettingsReset,
63
69
  onColumnBordersChanged,
64
70
  onTableSpacingChanged,
71
+ enableSimultaneousRangeAndRowSelection = false,
72
+ disableDragSelect = false,
73
+ onCellSelectionChanged,
65
74
  ...rest
66
75
  } = props;
67
76
 
@@ -81,12 +90,29 @@ export const Table = (props: TableProps) => {
81
90
  onTableSpacingChanged,
82
91
  });
83
92
 
93
+ const isUsingKeyboardRef = useRef(false);
94
+
84
95
  const { hasColumnBorders, tableSpacing } = settings;
85
96
 
86
97
  return (
87
98
  <GridApiContext.Provider value={gridApi}>
88
- <TableSettingsContext.Provider value={{ settings, resetSettings, setHasColumnBorders, setTableSpacing }}>
89
- <section data-testid={testId} className={classNames('ds-table__container', wrapperClassName)}>
99
+ <TableSettingsContext.Provider
100
+ value={{
101
+ settings,
102
+ resetSettings,
103
+ setHasColumnBorders,
104
+ setTableSpacing,
105
+ }}
106
+ >
107
+ <section
108
+ data-testid={testId}
109
+ className={classNames('ds-table__container', wrapperClassName)}
110
+ onMouseDown={() => { isUsingKeyboardRef.current = false; }}
111
+ onMouseUp={() => { isUsingKeyboardRef.current = false; }}
112
+ onMouseMove={() => { isUsingKeyboardRef.current = false; }}
113
+ onKeyDown={() => { isUsingKeyboardRef.current = true; }}
114
+ onKeyUp={() => { isUsingKeyboardRef.current = true; }}
115
+ >
90
116
  {headerContent && (
91
117
  <TableHeader data-testid={headerTestId} hasSearch={hasSearch} searchValue={searchValue} setSearchValue={setSearchValue}>
92
118
  {headerContent}
@@ -114,6 +140,20 @@ export const Table = (props: TableProps) => {
114
140
  onGridReady?.(event);
115
141
  }}
116
142
  suppressPaginationPanel
143
+ onCellSelectionChanged={(event) => {
144
+ if ((!disableDragSelect || !enableSimultaneousRangeAndRowSelection) && gridApi && event.finished) {
145
+ toggleRowSelectionInCurrentRange(
146
+ gridApi,
147
+ isUsingKeyboardRef.current,
148
+ disableDragSelect,
149
+ enableSimultaneousRangeAndRowSelection,
150
+ );
151
+ }
152
+
153
+ if (onCellSelectionChanged) {
154
+ onCellSelectionChanged(event);
155
+ }
156
+ }}
117
157
  {...rest}
118
158
  {...(hasSearch && { quickFilterText: searchValue })}
119
159
  />
@@ -0,0 +1,169 @@
1
+ import { SELECTION_COLUMN_ID, type CellRange, type GridApi } from 'ag-grid-community';
2
+
3
+ const getIsAnyRangeOutsideOfCheckboxColumn = (
4
+ selectedCellRanges: CellRange[],
5
+ ) => {
6
+ const isAnyRangeOutsideOfCheckboxColumn
7
+ = selectedCellRanges.findIndex(
8
+ range =>
9
+ range.columns.length > 1
10
+ || range.columns[0]?.getId() !== SELECTION_COLUMN_ID,
11
+ ) > -1;
12
+ return isAnyRangeOutsideOfCheckboxColumn;
13
+ };
14
+
15
+ export const toggleRowSelectionInCurrentRange = (
16
+ gridApi: GridApi,
17
+ isUsingKeyboard: boolean,
18
+ disableDragSelect = false,
19
+ enableSimultaneousRangeAndRowSelection = false,
20
+ ) => {
21
+ // In this callback we hack the range selection to allow dragging on checkboxes
22
+ // to change the value of a range of checkboxes
23
+ //
24
+ // When you click on a cell, a single RangeSelectionChangedEvent is triggered.
25
+ // - We want to toggle the selection for this event
26
+ // - Only one cell will be selected in this case
27
+ // When you click and drag on a cell, several RangeSelectionChangedEvents are triggered.
28
+ // - The first and last ones have finished=true, and we can ignore all the others
29
+ //
30
+ // There isn't an easy way to distinguish between the start of both of these cases, so
31
+ // we treat them both the same: toggle the selection of the starting cell.
32
+ // For the click and drag case, at the end of the drag we then toggle the selection of
33
+ // all cells in the range, apart from the starting cell.
34
+ //
35
+ // There isn't any way to tell from RangeSelectionChangedEvent if the event was triggered
36
+ // by mouse or keyboard, so we maintain a this.isUsingKeyboard value for this purpose
37
+
38
+ const selectedCellRanges = gridApi.getCellRanges();
39
+ if (selectedCellRanges === null || selectedCellRanges.length === 0) {
40
+ return;
41
+ }
42
+
43
+ if (getIsAnyRangeOutsideOfCheckboxColumn(selectedCellRanges)) {
44
+ if (enableSimultaneousRangeAndRowSelection) {
45
+ return;
46
+ }
47
+ // We want to allow either selecting ranges/rows in the checkbox column,
48
+ // or selecting ranges in the other cells, but not both. This is to keep
49
+ // the bulk row action and bulk cell actions separate
50
+ //
51
+ // We want to allow selecting ranges within the checkbox column
52
+ // So that you can do shift+click to enable several columns, and
53
+ // other similar interractions
54
+ const rows = gridApi.getSelectedRows();
55
+ if (rows.length > 0) {
56
+ // Deselect all the selected rows
57
+ gridApi.deselectAll();
58
+ }
59
+ return;
60
+ }
61
+
62
+ if (disableDragSelect) {
63
+ return;
64
+ }
65
+
66
+ const { startRow: unsafeStartRow, endRow: unsafeEndRow }
67
+ = selectedCellRanges[0] as CellRange;
68
+ if (
69
+ typeof unsafeStartRow === 'undefined'
70
+ || typeof unsafeEndRow === 'undefined'
71
+ ) {
72
+ console.error('undefined start or end row', { unsafeStartRow, unsafeEndRow });
73
+ return;
74
+ }
75
+
76
+ // We need to be careful to exclude any pinned rows
77
+ if (
78
+ unsafeStartRow.rowPinned === 'top'
79
+ || unsafeStartRow.rowPinned === 'bottom'
80
+ ) {
81
+ // If we start on a pinned row just do nothing, as there isn't an initial value to use
82
+ return;
83
+ }
84
+ // startRow will now be safe due to check above
85
+ const startRowIndex = unsafeStartRow.rowIndex;
86
+
87
+ // For end row, we shall trim to the fist last row, so you don't have to be
88
+ // really accurate with the mouse
89
+ let endRowIndex = unsafeEndRow.rowIndex;
90
+ if (unsafeEndRow.rowPinned === 'bottom') {
91
+ endRowIndex = gridApi.getDisplayedRowCount() - 1;
92
+ }
93
+ else if (unsafeEndRow.rowPinned === 'top') {
94
+ endRowIndex = 0;
95
+ }
96
+
97
+ const startingRowNode = gridApi.getDisplayedRowAtIndex(startRowIndex);
98
+ const isStartingRowNodeSelected = !!startingRowNode?.isSelected();
99
+ if (startRowIndex === endRowIndex) {
100
+ // We do not want to flip the state if we are currently using the keyboard, else
101
+ // navigating to a cell with select it.
102
+ if (!isUsingKeyboard) {
103
+ /**
104
+ * If the drag is started by a click in the cell but outside the checkbox, AG Grid registers it
105
+ * as a CellSelectionChangedEvent and this listener is then fired immediately after the mouseDown.
106
+ *
107
+ * If the drag is started by a click in the cell but inside the checkbox, AG Grid does not register
108
+ * a CellSelectionChangedEvent, so this listener doesn't fire, and is only first triggered once the
109
+ * drag moves the selection into another cell.
110
+ *
111
+ * The key difference between these two cases is that AG Grid will not toggle the cell for mouseDown
112
+ * on the checkbox, it will only do so for mouseDown and mouseUp on the same checkbox, so at the end
113
+ * of a drag on the checkbox row, if the drag started on the checkbox, it will need to be toggled at the
114
+ * end of the drag. If the drag started in a different area of the cell, it will already have been
115
+ * toggled
116
+ */
117
+ startingRowNode?.setSelected(!isStartingRowNodeSelected);
118
+ startingRowNode?.updateData({
119
+ ...startingRowNode.data,
120
+ firstToggledByClickOutsideCheckbox: true,
121
+ });
122
+ }
123
+ return;
124
+ }
125
+
126
+ const { smallestIndex, largestIndex }
127
+ = startRowIndex < endRowIndex
128
+ ? {
129
+ smallestIndex: startRowIndex,
130
+ largestIndex: endRowIndex,
131
+ }
132
+ : {
133
+ smallestIndex: endRowIndex,
134
+ largestIndex: startRowIndex,
135
+ };
136
+
137
+ const initiallyToggledOutsideCheckbox
138
+ = startingRowNode?.data.firstToggledByClickOutsideCheckbox;
139
+
140
+ // restoring the data on the node to clear the flag set on the cell
141
+ const {
142
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
143
+ firstToggledByClickOutsideCheckbox: _intentionallyDiscarded,
144
+ ...initialStartingRowData
145
+ } = startingRowNode?.data || {};
146
+ startingRowNode?.updateData(initialStartingRowData);
147
+
148
+ const shouldInvertNextUpdatedRows
149
+ = !initiallyToggledOutsideCheckbox && !isUsingKeyboard;
150
+
151
+ if (shouldInvertNextUpdatedRows) {
152
+ startingRowNode?.setSelected(!isStartingRowNodeSelected);
153
+ }
154
+
155
+ gridApi.forEachNodeAfterFilterAndSort((node, index) => {
156
+ if (
157
+ index >= smallestIndex
158
+ && index <= largestIndex
159
+ && index !== startRowIndex
160
+ ) {
161
+ if (shouldInvertNextUpdatedRows) {
162
+ node.setSelected(!isStartingRowNodeSelected);
163
+ }
164
+ else {
165
+ node.setSelected(isStartingRowNodeSelected);
166
+ }
167
+ }
168
+ });
169
+ };
@@ -0,0 +1,17 @@
1
+ import { AgChartsCommunityModule } from 'ag-charts-community';
2
+ import { ModuleRegistry } from 'ag-grid-community';
3
+ import {
4
+ LicenseManager,
5
+ IntegratedChartsModule,
6
+ AllEnterpriseModule,
7
+ } from 'ag-grid-enterprise';
8
+
9
+ export const setAgGridLicenseKey = () => {
10
+ LicenseManager.setLicenseKey(
11
+ 'Using_this_{AG_Grid}_Enterprise_key_{AG-076208}_in_excess_of_the_licence_granted_is_not_permitted___Please_report_misuse_to_legal@ag-grid.com___For_help_with_changing_this_key_please_contact_info@ag-grid.com___{Arbor_Education_Partners_Ltd}_is_granted_a_{Single_Application}_Developer_License_for_the_application_{Arbor_MIS}_only_for_{4}_Front-End_JavaScript_developers___All_Front-End_JavaScript_developers_working_on_{Arbor_MIS}_need_to_be_licensed___{Arbor_MIS}_has_been_granted_a_Deployment_License_Add-on_for_{1}_Production_Environment___This_key_works_with_{AG_Grid}_Enterprise_versions_released_before_{16_March_2026}____[v3]_[01]_MTc3MzYxOTIwMDAwMA==8820260fc59099926cf507c1e8018e49',
12
+ );
13
+ ModuleRegistry.registerModules([
14
+ IntegratedChartsModule.with(AgChartsCommunityModule),
15
+ AllEnterpriseModule,
16
+ ]);
17
+ };