@linzjs/step-ag-grid 22.0.0 → 22.1.0

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 (37) hide show
  1. package/dist/index.css +38 -0
  2. package/dist/src/components/Grid.d.ts +1 -2
  3. package/dist/src/components/GridCell.d.ts +1 -1
  4. package/dist/src/components/clickInputWhenContainingCellClicked.d.ts +6 -0
  5. package/dist/src/components/gridForm/GridFormDropDown.d.ts +1 -1
  6. package/dist/src/components/gridPopoverEdit/GridEditBoolean.d.ts +11 -0
  7. package/dist/src/components/gridPopoverEdit/index.d.ts +1 -0
  8. package/dist/src/components/index.d.ts +1 -0
  9. package/dist/src/lui/TextAreaInput.d.ts +0 -1
  10. package/dist/step-ag-grid.cjs.js +101 -76
  11. package/dist/step-ag-grid.cjs.js.map +1 -1
  12. package/dist/step-ag-grid.esm.js +101 -77
  13. package/dist/step-ag-grid.esm.js.map +1 -1
  14. package/package.json +32 -33
  15. package/src/components/Grid.tsx +18 -23
  16. package/src/components/GridCell.tsx +4 -2
  17. package/src/components/clickInputWhenContainingCellClicked.tsx +40 -0
  18. package/src/components/gridForm/GridFormDropDown.tsx +1 -0
  19. package/src/components/gridForm/GridFormMultiSelectGrid.tsx +1 -1
  20. package/src/components/gridPopoverEdit/GridEditBoolean.tsx +79 -0
  21. package/src/components/gridPopoverEdit/GridPopoverEditDropDown.ts +8 -1
  22. package/src/components/gridPopoverEdit/index.ts +1 -0
  23. package/src/components/index.ts +1 -0
  24. package/src/contexts/GridContextProvider.tsx +1 -0
  25. package/src/lui/TextAreaInput.tsx +3 -8
  26. package/src/stories/grid/FormTest.tsx +1 -0
  27. package/src/stories/grid/GridPopoutEditBoolean.stories.tsx +74 -0
  28. package/src/stories/grid/gridFormInteraction/GridFormDropDownInteraction.stories.tsx +1 -0
  29. package/src/stories/grid/gridFormInteraction/GridFormEditBearingCorrectionInteraction.stories.tsx +1 -0
  30. package/src/stories/grid/gridFormInteraction/GridFormEditBearingInteraction.stories.tsx +1 -0
  31. package/src/stories/grid/gridFormInteraction/GridFormMultiSelectGridInteraction.stories.tsx +1 -0
  32. package/src/stories/grid/gridFormInteraction/GridFormMultiSelectInteraction.stories.tsx +1 -0
  33. package/src/stories/grid/gridFormInteraction/GridFormPopoverMenuInteraction.stories.tsx +1 -0
  34. package/src/stories/grid/gridFormInteraction/GridFormTextAreaInteraction.stories.tsx +1 -0
  35. package/src/stories/grid/gridFormInteraction/GridFormTextInputInteraction.stories.tsx +1 -0
  36. package/src/styles/Grid.scss +33 -0
  37. package/src/styles/GridFormDropDown.scss +5 -0
@@ -3,7 +3,7 @@ import { LuiMiniSpinner, LuiStatusSpinner, LuiIcon, LuiButton, LuiCheckboxInput,
3
3
  import { RowHighlightPosition } from 'ag-grid-community';
4
4
  import { AgGridReact } from 'ag-grid-react';
5
5
  import { negate, isEmpty, findIndex, defer as defer$1, debounce as debounce$1, xorBy, last, difference, omit, sortBy, delay, partition, pick, groupBy, fromPairs, toPairs, isEqual, compact, filter, sumBy, pull, remove, castArray, flatten } from 'lodash-es';
6
- import React, { useRef, useEffect, useLayoutEffect, createContext, useContext, forwardRef, useCallback, useState, useMemo, memo, useReducer, cloneElement, useImperativeHandle, Fragment as Fragment$1 } from 'react';
6
+ import React, { useRef, useEffect, useLayoutEffect, createContext, useContext, forwardRef, useCallback, useState, useMemo, memo, useReducer, cloneElement, useImperativeHandle, Fragment as Fragment$1, useId } from 'react';
7
7
  import { unstable_batchedUpdates, flushSync, createPortal } from 'react-dom';
8
8
 
9
9
  /**
@@ -2333,6 +2333,44 @@ const useGridContextMenu = ({ contextMenuSelectRow, contextMenu: ContextMenu, })
2333
2333
  };
2334
2334
  };
2335
2335
 
2336
+ /**
2337
+ * AgGrid checkbox select does not pass clicks within cell but not on the checkbox to checkbox.
2338
+ * This passes the event to the checkbox when you click anywhere in the cell.
2339
+ */
2340
+ const clickInputWhenContainingCellClicked = ({ data, event, colDef }) => {
2341
+ if (!data || !event)
2342
+ return;
2343
+ const element = event.target;
2344
+ // Already handled
2345
+ if (["BUTTON", "INPUT"].includes(element?.tagName) && element.closest(".ag-cell-inline-editing"))
2346
+ return;
2347
+ const row = element.closest("[row-id]");
2348
+ if (!row)
2349
+ return;
2350
+ const colId = colDef.colId;
2351
+ if (!colId)
2352
+ return;
2353
+ const clickInput = (cnt) => {
2354
+ const cell = row.querySelector(`[col-id='${colId}']`);
2355
+ if (!cell)
2356
+ return;
2357
+ const input = cell.querySelector("input, button");
2358
+ if (!input) {
2359
+ return;
2360
+ }
2361
+ // When clicking on a cell that is not editing, the cell changes to editing and the input/button ref becomes invalid
2362
+ // So wait until the cell is in edit mode before sending the click
2363
+ if (!input.ownerDocument.contains(input)) {
2364
+ if (cnt !== 0) {
2365
+ setTimeout(() => clickInput(cnt - 1));
2366
+ }
2367
+ return;
2368
+ }
2369
+ input?.dispatchEvent(event);
2370
+ };
2371
+ setTimeout(() => clickInput(20), 10);
2372
+ };
2373
+
2336
2374
  /**
2337
2375
  * Wrapper for AgGrid to add commonly used functionality.
2338
2376
  */
@@ -2446,16 +2484,6 @@ const Grid = ({ "data-testid": dataTestId, defaultPostSort = true, rowSelection
2446
2484
  selectRowsById,
2447
2485
  getFirstRowId,
2448
2486
  ]);
2449
- /**
2450
- * AgGrid checkbox select does not pass clicks within cell but not on the checkbox to checkbox.
2451
- * This passes the event to the checkbox when you click anywhere in the cell.
2452
- */
2453
- const clickSelectorCheckboxWhenContainingCellClicked = useCallback(({ event }) => {
2454
- if (!event)
2455
- return;
2456
- const input = event.target.querySelector("input");
2457
- input?.dispatchEvent(event);
2458
- }, []);
2459
2487
  /**
2460
2488
  * Ensure external selected items list is in sync with panel.
2461
2489
  */
@@ -2555,7 +2583,7 @@ const Grid = ({ "data-testid": dataTestId, defaultPostSort = true, rowSelection
2555
2583
  }
2556
2584
  return false;
2557
2585
  },
2558
- onCellClicked: clickSelectorCheckboxWhenContainingCellClicked,
2586
+ onCellClicked: clickInputWhenContainingCellClicked,
2559
2587
  },
2560
2588
  ...adjustColDefs,
2561
2589
  ]
@@ -2569,7 +2597,6 @@ const Grid = ({ "data-testid": dataTestId, defaultPostSort = true, rowSelection
2569
2597
  params.defaultColDef?.editable,
2570
2598
  selectColumnPinned,
2571
2599
  rowSelection,
2572
- clickSelectorCheckboxWhenContainingCellClicked,
2573
2600
  ]);
2574
2601
  /**
2575
2602
  * When grid is ready set the apis to the grid context and sync selected items to grid.
@@ -2671,11 +2698,16 @@ const Grid = ({ "data-testid": dataTestId, defaultPostSort = true, rowSelection
2671
2698
  * Start editing on pressing Enter
2672
2699
  */
2673
2700
  const onCellKeyPress = useCallback((e) => {
2674
- if (e.event.key === "Enter") {
2701
+ const kbe = e.event;
2702
+ if (kbe.key === "Enter") {
2675
2703
  if (!invokeEditAction(e))
2676
2704
  startCellEditing(e);
2677
2705
  }
2678
- }, [startCellEditing]);
2706
+ if (kbe.key === "Tab") {
2707
+ // eslint-disable-next-line
2708
+ prePopupOps();
2709
+ }
2710
+ }, [prePopupOps, startCellEditing]);
2679
2711
  /**
2680
2712
  * Once the grid has auto-sized we want to run fit to fit the grid in its container,
2681
2713
  * but we don't want the non-flex auto-sized columns to "fit" size, so suppressSizeToFit is set to true.
@@ -2977,7 +3009,7 @@ const GridCell = (props, custom) => {
2977
3009
  return JSON.stringify(params.value);
2978
3010
  },
2979
3011
  ...props,
2980
- cellRenderer: GridCellRenderer,
3012
+ cellRenderer: typeof props.cellRenderer === "string" ? props.cellRenderer : GridCellRenderer,
2981
3013
  cellRendererParams: {
2982
3014
  originalCellRenderer: props.cellRenderer,
2983
3015
  ...props.cellRendererParams,
@@ -4149,7 +4181,7 @@ const GridFormMultiSelectGrid = (props) => {
4149
4181
  e.keepOpen = true;
4150
4182
  toggleValue(o);
4151
4183
  }
4152
- }, children: jsx(LuiCheckboxInput, { isChecked: !!o.checked ?? false, isIndeterminate: o.checked === "partial", value: `${o.value}`, label: jsxs(Fragment, { children: [o.warning && jsx(GridIcon, { icon: "ic_warning_outline", title: o.warning }, "$$icon$$"), jsx("span", { className: "GridMultiSelectGrid-Label", children: o.label ?? (o.value == null ? `<${o.value}>` : `${o.value}`) }, "$$label$$")] }), inputProps: {
4184
+ }, children: jsx(LuiCheckboxInput, { isChecked: !!o.checked, isIndeterminate: o.checked === "partial", value: `${o.value}`, label: jsxs(Fragment, { children: [o.warning && jsx(GridIcon, { icon: "ic_warning_outline", title: o.warning }, "$$icon$$"), jsx("span", { className: "GridMultiSelectGrid-Label", children: o.label ?? (o.value == null ? `<${o.value}>` : `${o.value}`) }, "$$label$$")] }), inputProps: {
4153
4185
  onClick: (e) => {
4154
4186
  // Click is handled by MenuItem onClick
4155
4187
  e.preventDefault();
@@ -4249,65 +4281,9 @@ const GridFormPopoverMenu = (props) => {
4249
4281
  }, children: jsx("div", { className: "subComponent", children: item.subComponent && jsx(item.subComponent, {}) }) })) }, `${item.label}_subcomponent`))] }, `${item.label}`))))) }) }));
4250
4282
  };
4251
4283
 
4252
- /**
4253
- * Convert array of 16 byte values to UUID string format of the form:
4254
- * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
4255
- */
4256
- var byteToHex = [];
4257
- for (var i = 0; i < 256; ++i) {
4258
- byteToHex.push((i + 0x100).toString(16).slice(1));
4259
- }
4260
- function unsafeStringify(arr, offset = 0) {
4261
- // Note: Be careful editing this code! It's been tuned for performance
4262
- // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434
4263
- //
4264
- // Note to future-self: No, you can't remove the `toLowerCase()` call.
4265
- // REF: https://github.com/uuidjs/uuid/pull/677#issuecomment-1757351351
4266
- return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
4267
- }
4268
-
4269
- // Unique ID creation requires a high quality random # generator. In the browser we therefore
4270
- // require the crypto API and do not support built-in fallback to lower quality random number
4271
- // generators (like Math.random()).
4272
-
4273
- var getRandomValues;
4274
- var rnds8 = new Uint8Array(16);
4275
- function rng() {
4276
- // lazy load so that environments that need to polyfill have a chance to do so
4277
- if (!getRandomValues) {
4278
- // getRandomValues needs to be invoked in a context where "this" is a Crypto implementation.
4279
- getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto);
4280
- if (!getRandomValues) {
4281
- throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');
4282
- }
4283
- }
4284
- return getRandomValues(rnds8);
4285
- }
4286
-
4287
- var randomUUID = typeof crypto !== 'undefined' && crypto.randomUUID && crypto.randomUUID.bind(crypto);
4288
- var native = {
4289
- randomUUID
4290
- };
4291
-
4292
- function v4(options, buf, offset) {
4293
- if (native.randomUUID && !buf && !options) {
4294
- return native.randomUUID();
4295
- }
4296
- options = options || {};
4297
- var rnds = options.random || (options.rng || rng)();
4298
-
4299
- // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
4300
- rnds[6] = rnds[6] & 0x0f | 0x40;
4301
- rnds[8] = rnds[8] & 0x3f | 0x80;
4302
- return unsafeStringify(rnds);
4303
- }
4304
-
4305
- const useGenerateOrDefaultId = (idFromProps) => {
4306
- const [id] = useState(idFromProps ? idFromProps : v4());
4307
- return id;
4308
- };
4309
4284
  const TextAreaInput = (props) => {
4310
- const id = useGenerateOrDefaultId(props?.id);
4285
+ const reactId = useId();
4286
+ const id = props?.id ?? reactId;
4311
4287
  return (jsxs("div", { className: clsx("LuiTextAreaInput Grid-popoverContainer", props.disabled ? "isDisabled" : "", props.error ? "hasError" : "", props.className), children: [jsxs("label", { htmlFor: id, children: [props.mandatory != null && jsx("span", { className: "LuiTextAreaInput-mandatory", children: "*" }), props.label != null && jsx("span", { className: "LuiTextAreaInput-label", children: props.label }), jsx("div", { className: "LuiTextAreaInput-wrapper", children: jsx("textarea", { rows: 5, ...omit(props, ["error", "value", "helpText", "formatted", "className", "allowTabToSave"]), id: id, value: props.value ?? "", spellCheck: true, onMouseEnter: (e) => {
4312
4288
  if (document.activeElement != e.currentTarget) {
4313
4289
  e.currentTarget.focus();
@@ -4457,6 +4433,52 @@ const GridFormTextInput = (props) => {
4457
4433
  return popoverWrapper(jsx("div", { style: { display: "flex", flexDirection: "row" }, className: "FormTest subComponent", children: jsx(TextInputFormatted, { value: value, onChange: (e) => setValue(e.target.value), error: invalid(), formatted: props.units, style: { width: props.width ?? 240 }, placeholder: props.placeholder ?? "Type here", helpText: helpText }) }));
4458
4434
  };
4459
4435
 
4436
+ const BooleanCellRenderer = (props) => {
4437
+ const { onValueChange, value, api, node, column, colDef, data } = props;
4438
+ const inputRef = useRef(null);
4439
+ useEffect(() => {
4440
+ const checkFocus = (event) => {
4441
+ if (event.rowIndex === node.rowIndex && event.column === column) {
4442
+ inputRef.current?.focus();
4443
+ }
4444
+ };
4445
+ api.addEventListener("cellFocused", checkFocus);
4446
+ return () => {
4447
+ api.removeEventListener("cellFocused", checkFocus);
4448
+ };
4449
+ }, [api, column, node.rowIndex]);
4450
+ return (jsx("div", { className: clsx("ag-wrapper ag-input-wrapper ag-checkbox-input-wrapper", { "ag-checked": props.value }), children: jsx("input", { type: "checkbox", className: "ag-input-field-input ag-checkbox-input", disabled: !fnOrVar(colDef?.editable, props), ref: inputRef, checked: value, onChange: () => { }, onClick: (e) => {
4451
+ e.stopPropagation();
4452
+ // cell has to be in edit mode
4453
+ // if in non-edit mode clickInputWhenContainingCellClicked will click to put it in edit mode
4454
+ if (!onValueChange)
4455
+ return;
4456
+ const params = props?.colDef?.cellEditorParams;
4457
+ if (!params)
4458
+ return;
4459
+ const selectedRows = [data];
4460
+ const checked = !value;
4461
+ onValueChange(checked);
4462
+ params.onClick({ selectedRows, selectedRowIds: selectedRows.map((r) => r.id), checked }).then();
4463
+ } }) }));
4464
+ };
4465
+ const GridEditBoolean = (colDef, editorProps) => {
4466
+ return GridCell({
4467
+ minWidth: 64,
4468
+ maxWidth: 64,
4469
+ cellRenderer: BooleanCellRenderer,
4470
+ cellEditor: BooleanCellRenderer,
4471
+ cellEditorParams: editorProps,
4472
+ onCellClicked: clickInputWhenContainingCellClicked,
4473
+ singleClickEdit: true,
4474
+ resizable: false,
4475
+ editable: true,
4476
+ cellClass: "GridCellAlignCenter",
4477
+ headerClass: "GridHeaderAlignCenter",
4478
+ ...colDef,
4479
+ });
4480
+ };
4481
+
4460
4482
  const GridPopoutEditMultiSelect = (colDef, props) => GridCell(colDef, {
4461
4483
  editor: GridFormMultiSelect,
4462
4484
  ...props,
@@ -4540,7 +4562,9 @@ const GridPopoverEditDropDown = (colDef, props) => GridCell(colDef, {
4540
4562
  ...props,
4541
4563
  editorParams: {
4542
4564
  ...props.editorParams,
4543
- className: clsx("GridPopoverEditDropDown-containerLarge", props.editorParams?.className),
4565
+ className: clsx({
4566
+ "GridPopoverEditDropDown-containerLarge": !props.editorParams?.className?.includes("GridPopoverEditDropDown-container"),
4567
+ }, props.editorParams?.className),
4544
4568
  },
4545
4569
  });
4546
4570
 
@@ -5311,5 +5335,5 @@ const useDeferredPromise = () => {
5311
5335
  };
5312
5336
  };
5313
5337
 
5314
- export { ActionButton, ComponentLoadingWrapper, ControlledMenu, Editor, FocusableItem, FormError, GenericCellEditorComponentWrapper, Grid, GridCell, GridCellFiller, GridCellFillerColId, GridCellMultiEditor, GridCellMultiSelectClassRules, GridCellRenderer, GridContext, GridContextProvider, GridFilterButtons, GridFilterColumnsToggle, GridFilterDownloadCsvButton, GridFilterHeaderIconButton, GridFilterQuick, GridFilters, GridFormDropDown, GridFormEditBearing, GridFormMessage, GridFormMultiSelect, GridFormMultiSelectGrid, GridFormPopoverMenu, GridFormSubComponentTextArea, GridFormSubComponentTextInput, GridFormTextArea, GridFormTextInput, GridHeaderSelect, GridIcon, GridLoadableCell, GridNoRowsOverlay, GridNoRowsOverlayFr, GridPopoutEditMultiSelect, GridPopoutEditMultiSelectGrid, GridPopoverContext, GridPopoverContextProvider, GridPopoverEditBearing, GridPopoverEditBearingCorrection, GridPopoverEditBearingCorrectionEditorParams, GridPopoverEditBearingEditorParams, GridPopoverEditDropDown, GridPopoverMenu, GridPopoverMessage, GridPopoverTextArea, GridPopoverTextInput, GridRenderPopoutMenuCell, GridSubComponentContext, GridUpdatingContext, GridUpdatingContextProvider, GridWrapper, Menu, MenuButton, MenuDivider, MenuGroup, MenuHeader, MenuHeaderItem, MenuHeaderString, MenuItem, MenuRadioGroup, MenuSeparator, MenuSeparatorString, PopoutMenuSeparator, SubMenu, TextAreaInput, TextInputFormatted, bearingCorrectionRangeValidator, bearingCorrectionValueFormatter, bearingNumberParser, bearingRangeValidator, bearingStringValidator, bearingValueFormatter, convertDDToDMS, downloadCsvUseValueFormattersProcessCellCallback, findParentWithClass, fnOrVar, generateFilterGetter, hasParentClass, isFloat, isGridCellFiller, isNotEmpty, sanitiseFileName, stringByteLengthIsInvalid, suppressCellKeyboardEvents, useDeferredPromise, useGenerateOrDefaultId, useGridContext, useGridContextMenu, useGridFilter, useGridPopoverContext, useGridPopoverHook, useMenuState, usePostSortRowsHook, wait };
5338
+ export { ActionButton, ComponentLoadingWrapper, ControlledMenu, Editor, FocusableItem, FormError, GenericCellEditorComponentWrapper, Grid, GridCell, GridCellFiller, GridCellFillerColId, GridCellMultiEditor, GridCellMultiSelectClassRules, GridCellRenderer, GridContext, GridContextProvider, GridEditBoolean, GridFilterButtons, GridFilterColumnsToggle, GridFilterDownloadCsvButton, GridFilterHeaderIconButton, GridFilterQuick, GridFilters, GridFormDropDown, GridFormEditBearing, GridFormMessage, GridFormMultiSelect, GridFormMultiSelectGrid, GridFormPopoverMenu, GridFormSubComponentTextArea, GridFormSubComponentTextInput, GridFormTextArea, GridFormTextInput, GridHeaderSelect, GridIcon, GridLoadableCell, GridNoRowsOverlay, GridNoRowsOverlayFr, GridPopoutEditMultiSelect, GridPopoutEditMultiSelectGrid, GridPopoverContext, GridPopoverContextProvider, GridPopoverEditBearing, GridPopoverEditBearingCorrection, GridPopoverEditBearingCorrectionEditorParams, GridPopoverEditBearingEditorParams, GridPopoverEditDropDown, GridPopoverMenu, GridPopoverMessage, GridPopoverTextArea, GridPopoverTextInput, GridRenderPopoutMenuCell, GridSubComponentContext, GridUpdatingContext, GridUpdatingContextProvider, GridWrapper, Menu, MenuButton, MenuDivider, MenuGroup, MenuHeader, MenuHeaderItem, MenuHeaderString, MenuItem, MenuRadioGroup, MenuSeparator, MenuSeparatorString, PopoutMenuSeparator, SubMenu, TextAreaInput, TextInputFormatted, bearingCorrectionRangeValidator, bearingCorrectionValueFormatter, bearingNumberParser, bearingRangeValidator, bearingStringValidator, bearingValueFormatter, clickInputWhenContainingCellClicked, convertDDToDMS, downloadCsvUseValueFormattersProcessCellCallback, findParentWithClass, fnOrVar, generateFilterGetter, hasParentClass, isFloat, isGridCellFiller, isNotEmpty, sanitiseFileName, stringByteLengthIsInvalid, suppressCellKeyboardEvents, useDeferredPromise, useGridContext, useGridContextMenu, useGridFilter, useGridPopoverContext, useGridPopoverHook, useMenuState, usePostSortRowsHook, wait };
5315
5339
  //# sourceMappingURL=step-ag-grid.esm.js.map