@k-int/stripes-kint-components 5.9.0 → 5.10.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ # [5.10.0](https://gitlab.com/knowledge-integration/folio/stripes-kint-components/compare/v5.9.0...v5.10.0) (2025-02-04)
2
+
3
+
4
+ ### Features
5
+
6
+ * Typedown delay ([c736865](https://gitlab.com/knowledge-integration/folio/stripes-kint-components/commit/c736865cec8f4b5cbe2ad473393452fd7ec34dc8))
7
+
1
8
  # [5.9.0](https://gitlab.com/knowledge-integration/folio/stripes-kint-components/compare/v5.8.3...v5.9.0) (2025-01-31)
2
9
 
3
10
 
@@ -22,8 +22,11 @@ const Typedown = _ref => {
22
22
  className,
23
23
  dataOptions,
24
24
  displayClearItem = true,
25
+ displayValueWhileOpen = true,
25
26
  endOfList,
26
27
  id,
28
+ initialOpenDelay = 800,
29
+ // Initial opening delay of 800ms (handles any stripes animations)
27
30
  input,
28
31
  isSelected,
29
32
  filterPath,
@@ -89,7 +92,9 @@ const Typedown = _ref => {
89
92
  resizeRef,
90
93
  searchWidth
91
94
  }
92
- } = (0, _typedownHooks.useTypedown)(input.name);
95
+ } = (0, _typedownHooks.useTypedown)(input.name, {
96
+ timeout: initialOpenDelay
97
+ });
93
98
  const renderItem = (0, _react.useCallback)(function (option) {
94
99
  let optionIsSelected = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
95
100
  return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
@@ -157,6 +162,9 @@ const Typedown = _ref => {
157
162
  })
158
163
  });
159
164
  };
165
+ const displayValue = (0, _react.useMemo)(() => {
166
+ return !!selectedUniqueId && (!open || displayValueWhileOpen);
167
+ }, [displayValueWhileOpen, open, selectedUniqueId]);
160
168
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
161
169
  ref: resizeRef,
162
170
  className: (0, _classnames.default)(_TypeDown.default.typedown, className),
@@ -185,7 +193,7 @@ const Typedown = _ref => {
185
193
  overlayRef: overlayRef,
186
194
  portal: portal,
187
195
  children: dropDown()
188
- }, "typedown-menu-toggle"), selectedUniqueId && !open && /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
196
+ }, "typedown-menu-toggle"), displayValue && /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
189
197
  className: (0, _classnames.default)(_TypeDown.default.selectedDisplay),
190
198
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
191
199
  className: _TypeDown.default.selectedItem,
@@ -202,9 +210,11 @@ Typedown.propTypes = {
202
210
  className: _propTypes.default.string,
203
211
  dataOptions: _propTypes.default.arrayOf(_propTypes.default.object),
204
212
  displayClearItem: _propTypes.default.bool,
213
+ displayValueWhileOpen: _propTypes.default.bool,
205
214
  endOfList: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.node, _propTypes.default.element]),
206
215
  filterPath: _propTypes.default.string,
207
216
  id: _propTypes.default.string,
217
+ initialOpenDelay: _propTypes.default.number,
208
218
  input: _propTypes.default.object,
209
219
  isSelected: _propTypes.default.func,
210
220
  label: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.element]),
@@ -11,7 +11,10 @@ var _eventCodes = require("../../constants/eventCodes");
11
11
  var _selectorSafe = _interopRequireDefault(require("../../utils/selectorSafe"));
12
12
  var _useTypedownToggle = _interopRequireDefault(require("./useTypedownToggle"));
13
13
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
14
- const useTypedown = name => {
14
+ const useTypedown = function (name) {
15
+ let {
16
+ timeout = 800
17
+ } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
15
18
  // SEARCHFIELD COMPONENT
16
19
  const searchFieldComponent = document.getElementById(`typedown-searchField-${(0, _selectorSafe.default)(name)}`);
17
20
 
@@ -101,6 +104,16 @@ const useTypedown = name => {
101
104
  const {
102
105
  open
103
106
  } = (0, _useTypedownToggle.default)(name);
107
+ const [useOpen, setUseOpen] = (0, _react.useState)(false);
108
+ (0, _react.useEffect)(() => {
109
+ // Use setTimeout to update the message after 2000 milliseconds (2 seconds)
110
+ const timeoutId = setTimeout(() => {
111
+ setUseOpen(true);
112
+ }, timeout); // Wait 0.8 seconds for open prop to get used
113
+
114
+ // Cleanup function to clear the timeout if the component unmounts
115
+ return () => clearTimeout(timeoutId);
116
+ }, [timeout]);
104
117
 
105
118
  // RESIZE STUFF
106
119
  const {
@@ -123,7 +136,7 @@ const useTypedown = name => {
123
136
  searchFieldKeyDownHandler
124
137
  },
125
138
  variables: {
126
- open,
139
+ open: useOpen ? open : false,
127
140
  portal,
128
141
  resizeRef,
129
142
  searchWidth
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@k-int/stripes-kint-components",
3
- "version": "5.9.0",
3
+ "version": "5.10.0",
4
4
  "description": "Stripes Component library for K-Int specific applications",
5
5
  "sideEffects": [
6
6
  "*.css"
@@ -0,0 +1,91 @@
1
+ ## FormModal Component
2
+
3
+ The `FormModal` component provides a simple way to create a modal dialog with a form. It combines the `Modal` component from `@folio/stripes/components` with the `Form` component from `react-final-form`, handling form submission, validation, and modal interactions.
4
+
5
+ ### Basic Usage
6
+
7
+ ```javascript
8
+ import { useState } from 'react';
9
+ import FormModal from '@k-int/stripes-kint-components';
10
+ import { Field } from 'react-final-form';
11
+ import { TextField } from '@folio/stripes/components';
12
+
13
+ const MyFormModal = () => {
14
+ const [open, setOpen] = useState(false);
15
+
16
+ const onSubmit = (values) => {
17
+ // Handle form submission
18
+ console.log(values);
19
+ setOpen(false); // Close the modal after submission
20
+ };
21
+
22
+ return (
23
+ <>
24
+ <Button onClick={() => setOpen(true)}>Open Modal</Button> {/* Button to open the modal */}
25
+ <FormModal
26
+ modalProps={{ open, onClose: () => setOpen(false) }}
27
+ onSubmit={onSubmit}
28
+ >
29
+ <Field
30
+ name="name"
31
+ component={TextField}
32
+ label="Name"
33
+ />
34
+ </FormModal>
35
+ </>
36
+ );
37
+ };
38
+ ```
39
+
40
+ ### Props
41
+
42
+ | Name | Type | Description | Default | Required |
43
+ |---|---|---|---|---|
44
+ | children | node/func | The content of the modal, typically form fields. | | ✓ |
45
+ | intlKey | string | The key to use for internationalization messages. | | ✕ |
46
+ | intlNS | string | The namespace to use for internationalization messages. | | ✕ |
47
+ | labelOverrides | object | An object to override the default labels for buttons. | `{}` | ✕ |
48
+ | modalProps | object | Props to pass to the underlying `Modal` component. Should include `open` and `onClose`. | | ✓ |
49
+ | onError | func | A function to handle errors that occur during form submission. This function will receive the error object as a parameter. | | ✕ |
50
+ | onSubmit | func | A function to handle form submission. | | ✓ |
51
+ | onSuccess | func | A function to handle successful form submission. This function will receive the submitted values as a parameter. | | ✕ |
52
+ |...formProps | object | Any other props will be passed to the underlying `Form` component from `react-final-form`. | | ✕ |
53
+
54
+ ### Features
55
+
56
+ * **Integrated form handling:** The component integrates seamlessly with `react-final-form`, providing access to form state and helper functions within the `footer` and `children` props.
57
+ * **Customizable footer:** The `modalProps.footer` prop allows for customization of the modal footer. It receives an object with the following properties:
58
+ * `formState`: The current state of the form.
59
+ * `handleSubmit`: A function to handle form submission and close the modal.
60
+ * `handleClose`: A function to close the modal.
61
+ * `handleSubmitNoRestart`: **(DEPRECATED)** Use `handleSubmitRaw` instead.
62
+ * `handleSubmitRaw`: A function to handle form submission without closing the modal or clearing the form.
63
+ * **Error and success handling:** The `onError` and `onSuccess` props allow for custom handling of asynchronous form submission errors and successes.
64
+ * **Internationalization:** The component supports internationalization using the `intlKey` and `intlNS` props.
65
+ * **Label overrides:** The `labelOverrides` prop allows for overriding the default button labels.
66
+
67
+ ### Example with Custom Footer
68
+
69
+ ```javascript
70
+ <FormModal
71
+ modalProps={{
72
+ open: true,
73
+ onClose: () => { /*... */ },
74
+ footer: ({ handleSubmit, handleClose }) => (
75
+ <ModalFooter>
76
+ <Button
77
+ buttonStyle="primary"
78
+ onClick={handleSubmit}
79
+ type="submit"
80
+ >
81
+ Save
82
+ </Button>
83
+ <Button onClick={handleClose}>Cancel</Button>
84
+ </ModalFooter>
85
+ )
86
+ }}
87
+ onSubmit={() => { /*... */ }}
88
+ >
89
+ {/*... form content... */}
90
+ </FormModal>
91
+ ```
@@ -24,22 +24,24 @@ import Typedown from '@k-int/stripes-kint-components';
24
24
 
25
25
  ### Props
26
26
 
27
- | Name | Type | Description | Default | Required |
28
- |---|---|---|---|---|
29
- | className | string | CSS class name to apply to the component's outer div. | | ✕ |
30
- | dataOptions | array | An array of objects representing the dropdown options. Each object should have a property (specified by `uniqueIdentificationPath`) that serves as a unique identifier. | | ✓ |
31
- | displayClearItem | bool | Whether to display a clear icon when an item is selected. | `true` | ✕ |
32
- | endOfList | node/func | Component or function to render when the dropdown list is empty. Defaults to `<EndOfList />` from `@folio/stripes/components`. | `<EndOfList />` | ✕ |
33
- | filterPath | string | Path to the property in `dataOptions` objects to use for filtering. If not provided, filtering is done on the property specified by `uniqueIdentificationPath`. | | ✕ |
34
- | id | string | Id to apply to the component's outer div. | | ✕ |
35
- | input | object | An object containing the input props typically provided by a form library like `react-final-form` or `redux-form`. Should include `name`, `value`, and `onChange`. | | |
36
- | isSelected | func | A function `(inputValue, dataOption)` that determines if a given `dataOption` is currently selected. Useful when selected values are complex objects. If not provided, selection is determined by comparing the value of the `uniqueIdentificationPath` property of the `input.value` and the `dataOption`. | | ✕ |
37
- | label | string/element | Label for the input field. | | |
38
- | meta | object | Meta information about the field, typically provided by a form library. Useful for displaying error messages etc. | | ✕ |
39
- | onChange | func | A callback function `(value)` that is called when a value is selected from the dropdown. This is in addition to the `input.onChange` provided. | | ✕ |
40
- | onType | func | A callback function `(event)` that is called when the user types in the search field. Allows for custom filtering or data fetching based on user input. | | ✕ |
41
- | renderFooter | func | A function `(displayData, currentlyTyped, exactMatch)` that renders a footer below the dropdown list. Receives the currently filtered `displayData`, what the user has typed, and whether it is an exact match. | | ✕ |
42
- | renderListItem | func | A function `(option, currentlyTyped, exactMatch, optionIsSelected)` that renders each item in the dropdown list. Receives the current option, what the user has typed, whether there is an exact match, and if the option is selected. If not provided, the value of the `uniqueIdentificationPath` property of the option is displayed. | | ✕ |
43
- | required | bool | Whether the input is required. | | ✕ |
44
- | selectedStyles | string | CSS class name to apply to the selected item display. | | ✕ |
45
- | uniqueIdentificationPath | string | Path to the property in `dataOptions` objects that serves as a unique identifier for each option and is used to determine if an option is selected. | `'id'` | ✕ |
27
+ | Name | Type | Description | Default | Required |
28
+ |--------------------------|-----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------|---|
29
+ | className | string | CSS class name to apply to the component's outer div. | | ✕ |
30
+ | dataOptions | array | An array of objects representing the dropdown options. Each object should have a property (specified by `uniqueIdentificationPath`) that serves as a unique identifier. | | ✓ |
31
+ | displayClearItem | bool | Whether to display a clear icon when an item is selected. | `true` | ✕ |
32
+ | displayValueWhileOpen | bool | Whether or not to display the "value" underneath the typedown search while the dropdown is open. Defaults to true to avoid size changing onClick. | `true` | ✕ |
33
+ | endOfList | node/func | Component or function to render when the dropdown list is empty. Defaults to `<EndOfList />` from `@folio/stripes/components`. | `<EndOfList />` | ✕ |
34
+ | filterPath | string | Path to the property in `dataOptions` objects to use for filtering. If not provided, filtering is done on the property specified by `uniqueIdentificationPath`. | | ✕ |
35
+ | id | string | Id to apply to the component's outer div. | | |
36
+ | initialTimeoutDelay | number | Delay applied to `open` occurring on first render. Set to 800ms to avoid any stripes animations, such as being the first element focused in an opening modal. | 800 | ✕ |
37
+ | input | object | An object containing the input props typically provided by a form library like `react-final-form` or `redux-form`. Should include `name`, `value`, and `onChange`. | | |
38
+ | isSelected | func | A function `(inputValue, dataOption)` that determines if a given `dataOption` is currently selected. Useful when selected values are complex objects. If not provided, selection is determined by comparing the value of the `uniqueIdentificationPath` property of the `input.value` and the `dataOption`. | | ✕ |
39
+ | label | string/element | Label for the input field. | | ✕ |
40
+ | meta | object | Meta information about the field, typically provided by a form library. Useful for displaying error messages etc. | | ✕ |
41
+ | onChange | func | A callback function `(value)` that is called when a value is selected from the dropdown. This is in addition to the `input.onChange` provided. | | ✕ |
42
+ | onType | func | A callback function `(event)` that is called when the user types in the search field. Allows for custom filtering or data fetching based on user input. | | ✕ |
43
+ | renderFooter | func | A function `(displayData, currentlyTyped, exactMatch)` that renders a footer below the dropdown list. Receives the currently filtered `displayData`, what the user has typed, and whether it is an exact match. | | ✕ |
44
+ | renderListItem | func | A function `(option, currentlyTyped, exactMatch, optionIsSelected)` that renders each item in the dropdown list. Receives the current option, what the user has typed, whether there is an exact match, and if the option is selected. If not provided, the value of the `uniqueIdentificationPath` property of the option is displayed. | | ✕ |
45
+ | required | bool | Whether the input is required. | | ✕ |
46
+ | selectedStyles | string | CSS class name to apply to the selected item display. | | ✕ |
47
+ | uniqueIdentificationPath | string | Path to the property in `dataOptions` objects that serves as a unique identifier for each option and is used to determine if an option is selected. | `'id'` | ✕ |
@@ -1,4 +1,4 @@
1
- import React, { useCallback, useEffect, useState } from 'react';
1
+ import React, { useCallback, useEffect, useMemo, useState } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import classnames from 'classnames';
4
4
 
@@ -16,8 +16,10 @@ const Typedown = ({
16
16
  className,
17
17
  dataOptions,
18
18
  displayClearItem = true,
19
+ displayValueWhileOpen = true,
19
20
  endOfList,
20
21
  id,
22
+ initialOpenDelay = 800, // Initial opening delay of 800ms (handles any stripes animations)
21
23
  input,
22
24
  isSelected,
23
25
  filterPath,
@@ -85,7 +87,12 @@ const Typedown = ({
85
87
  resizeRef,
86
88
  searchWidth
87
89
  }
88
- } = useTypedown(input.name);
90
+ } = useTypedown(
91
+ input.name,
92
+ {
93
+ timeout: initialOpenDelay
94
+ }
95
+ );
89
96
 
90
97
  const renderItem = useCallback((option, optionIsSelected = false) => (
91
98
  <div
@@ -197,6 +204,10 @@ const Typedown = ({
197
204
  );
198
205
  };
199
206
 
207
+ const displayValue = useMemo(() => {
208
+ return !!selectedUniqueId && (!open || displayValueWhileOpen);
209
+ }, [displayValueWhileOpen, open, selectedUniqueId]);
210
+
200
211
  return (
201
212
  <div
202
213
  ref={resizeRef}
@@ -229,7 +240,7 @@ const Typedown = ({
229
240
  >
230
241
  {dropDown()}
231
242
  </Popper>
232
- {selectedUniqueId && !open &&
243
+ {displayValue &&
233
244
  <div
234
245
  className={classnames(
235
246
  css.selectedDisplay
@@ -257,6 +268,7 @@ Typedown.propTypes = {
257
268
  className: PropTypes.string,
258
269
  dataOptions: PropTypes.arrayOf(PropTypes.object),
259
270
  displayClearItem: PropTypes.bool,
271
+ displayValueWhileOpen: PropTypes.bool,
260
272
  endOfList: PropTypes.oneOfType([
261
273
  PropTypes.func,
262
274
  PropTypes.node,
@@ -264,6 +276,7 @@ Typedown.propTypes = {
264
276
  ]),
265
277
  filterPath: PropTypes.string,
266
278
  id: PropTypes.string,
279
+ initialOpenDelay: PropTypes.number,
267
280
  input: PropTypes.object,
268
281
  isSelected: PropTypes.func,
269
282
  label: PropTypes.oneOfType([
@@ -1,4 +1,4 @@
1
- import { useRef } from 'react';
1
+ import { useEffect, useRef, useState } from 'react';
2
2
  import { useResizeDetector } from 'react-resize-detector';
3
3
 
4
4
  import {
@@ -18,7 +18,10 @@ import selectorSafe from '../../utils/selectorSafe';
18
18
 
19
19
  import useTypedownToggle from './useTypedownToggle';
20
20
 
21
- const useTypedown = (name) => {
21
+ const useTypedown = (
22
+ name,
23
+ { timeout = 800 } = {}
24
+ ) => {
22
25
  // SEARCHFIELD COMPONENT
23
26
  const searchFieldComponent = document.getElementById(`typedown-searchField-${selectorSafe(name)}`);
24
27
 
@@ -114,6 +117,17 @@ const useTypedown = (name) => {
114
117
 
115
118
  // SET UP VARIABLES
116
119
  const { open } = useTypedownToggle(name);
120
+ const [useOpen, setUseOpen] = useState(false);
121
+
122
+ useEffect(() => {
123
+ // Use setTimeout to update the message after 2000 milliseconds (2 seconds)
124
+ const timeoutId = setTimeout(() => {
125
+ setUseOpen(true);
126
+ }, timeout); // Wait 0.8 seconds for open prop to get used
127
+
128
+ // Cleanup function to clear the timeout if the component unmounts
129
+ return () => clearTimeout(timeoutId);
130
+ }, [timeout]);
117
131
 
118
132
  // RESIZE STUFF
119
133
  const { width: searchWidth, ref: resizeRef } = useResizeDetector();
@@ -134,7 +148,7 @@ const useTypedown = (name) => {
134
148
  searchFieldKeyDownHandler
135
149
  },
136
150
  variables: {
137
- open,
151
+ open: useOpen ? open : false,
138
152
  portal,
139
153
  resizeRef,
140
154
  searchWidth
@@ -1,73 +1,143 @@
1
- # util
2
- A collection of useful util functions
1
+ # Utility Functions
3
2
 
4
3
  ## generateKiwtQuery
5
- A util function for generating a "KIWT" (K-Int Web-Toolkit) style backend query from a SASQ query object
6
- ### Basic usage
7
- ```
8
- import { generateKiwtQuery } from '@k-int/stripes-kint-components'
9
- ...
10
- const nsValues = {
11
- query: 'test',
12
- filters: 'requestStatus.completed,journalVolume.test1,startDate.startDate>=2021-10-28'
13
- }
14
4
 
15
- const options = {
16
- searchKey: 'request.name',
17
- filterKeys: {
18
- requestStatus: 'requestStatus.value,
19
- journalVolume: 'journalVolume'
20
- }
5
+ The `generateKiwtQuery` function generates a URL query string in "KIWT" (K-Int Web Toolkit) style from a SASQ (Search and Sort Query) object. It handles search terms, filters, sorting, and other parameters, making it easy to construct complex query strings for backend APIs.
6
+
7
+ ### Basic Usage
8
+
9
+ ```javascript
10
+ import { generateKiwtQuery } from '@k-int/stripes-kint-components';
11
+
12
+ const nsValues = {
13
+ query: 'test',
14
+ filters: 'requestStatus.completed,journalVolume.test1,startDate.startDate>=2021-10-28',
15
+ sort: '-title' // Example of sorting by title in descending order
16
+ };
17
+
18
+ const options = {
19
+ searchKey: 'request.name',
20
+ filterKeys: {
21
+ requestStatus: 'requestStatus.value',
22
+ journalVolume: 'journalVolume'
23
+ },
24
+ sortKeys: {
25
+ title: 'item.title' // Example of mapping 'title' to 'item.title' for sorting
21
26
  }
27
+ };
22
28
 
23
- const queryString = generateKiwtQuery(options, nsValues)
29
+ const queryString = generateKiwtQuery(options, nsValues);
24
30
 
25
- // We'd expect queryString === "?match=request.name&term=test&filters=requestStatus.value==completed&filters=journalVolume==test1&filters=startDate%3E=2021-10-28&stats=true"
26
- ...
31
+ // queryString will be:
32
+ //?match=request.name&term=test&filters=requestStatus.value==completed&filters=journalVolume==test1&filters=startDate%3E=2021-10-28&sort=item.title;desc&stats=true
27
33
  ```
28
34
 
29
35
  ### Props
30
- Name | Type | Description | default | required
31
- --- | --- | --- | --- | ---
32
- options | object | An object with keys: `searchKey`, `filterKeys`, `sortKeys` and `stats`, which maps the incoming nsValues objects to a KIWT query. You can also pass arbitrary `key`/`value` pairs to append `key==value` onto the query. | | ✓ |
33
- nsValues | object | An object containing the actual query parameters to become the mapped KIWT query | | ✓ |
34
- encode | boolean | A boolean prop which determines if each query param chunk will be encoded using encodeURIComponent or not | true | |
36
+
37
+ | Name | Type | Description | Default | Required |
38
+ |---|---|---|---|---|
39
+ | options | object | An object with keys: `searchKey`, `filterKeys`, `sortKeys`, and `stats`, which maps the incoming `nsValues` object to a KIWT query. You can also pass arbitrary `key`/`value` pairs to append `key==value` onto the query. | | ✓ |
40
+ | nsValues | object | An object containing the query parameters. Can contain `query`, `filters`, and `sort`, as well as any other arbitrary parameters. | | |
41
+ | encode | boolean | A boolean indicating whether to URL-encode the values. | `true` | ✕ |
35
42
 
36
43
  ## generateKiwtQueryParams
37
- A util function for generating an array of "KIWT" (K-Int Web-Toolkit) style backend query parameters from a SASQ query object
38
- ### Basic usage
39
- ```
40
- import { generateKiwtQueryParams } from '@k-int/stripes-kint-components'
41
- ...
42
- const nsValues = {
43
- query: 'test',
44
- filters: 'requestStatus.completed,journalVolume.test1,startDate.startDate>=2021-10-28'
45
- }
46
44
 
47
- const options = {
48
- searchKey: 'request.name',
49
- filterKeys: {
50
- requestStatus: 'requestStatus.value,
51
- journalVolume: 'journalVolume'
52
- }
45
+ The `generateKiwtQueryParams` function is similar to `generateKiwtQuery`, but instead of returning a string, it returns an array of query parameters. This can be useful for more advanced use cases where you need to manipulate the parameters before constructing the final query string.
46
+
47
+ ### Basic Usage
48
+
49
+ ```javascript
50
+ import { generateKiwtQueryParams } from '@k-int/stripes-kint-components';
51
+
52
+ const nsValues = {
53
+ query: 'test',
54
+ filters: 'requestStatus.completed,journalVolume.test1,startDate.startDate>=2021-10-28'
55
+ };
56
+
57
+ const options = {
58
+ searchKey: 'request.name',
59
+ filterKeys: {
60
+ requestStatus: 'requestStatus.value',
61
+ journalVolume: 'journalVolume'
53
62
  }
63
+ };
64
+
65
+ const queryArray = generateKiwtQueryParams(options, nsValues);
54
66
 
55
- const queryArray = generateKiwtQueryParams(options, nsValues)
56
-
57
- // We'd expect queryArray === [
58
- "match=request.name",
59
- "term=test",
60
- "filters=requestStatus.value==completed",
61
- "filters=journalVolume==test1",
62
- "filters=startDate%3E=2021-10-28",
63
- "stats=true"
64
- ]
65
- ...
67
+ // queryArray will be:
68
+ // [
69
+ // "match=request.name",
70
+ // "term=test",
71
+ // "filters=requestStatus.value==completed",
72
+ // "filters=journalVolume==test1",
73
+ // "filters=startDate%3E=2021-10-28",
74
+ // "stats=true"
75
+ // ]
66
76
  ```
67
77
 
68
78
  ### Props
69
- Name | Type | Description | default | required
70
- --- | --- | --- | --- | ---
71
- options | object | An object with keys: `searchKey`, `filterKeys`, `sortKeys` and `stats`, which maps the incoming nsValues objects to an KIWT query array. You can also pass arbitrary `key`/`value` pairs to append `key==value` onto the query. | | ✓ |
72
- nsValues | object | An object containing the actual query parameters to become the mapped KIWT query | | ✓ |
73
- encode | boolean | A boolean prop which determines if each query param chunk will be encoded using encodeURIComponent or not | true | |
79
+
80
+ | Name | Type | Description | Default | Required |
81
+ |---|---|---|---|---|
82
+ | options | object | An object with keys: `searchKey`, `filterKeys`, `sortKeys`, and `stats`, which maps the incoming `nsValues` object to a KIWT query array. You can also pass arbitrary `key`/`value` pairs to append `key==value` onto the query. | | ✓ |
83
+ | nsValues | object | An object containing the query parameters. Can contain `query`, `filters`, and `sort`, as well as any other arbitrary parameters. | | |
84
+ | encode | boolean | A boolean indicating whether to URL-encode the values. | `true` | ✕ |
85
+
86
+
87
+ ### Options Parameter Structure
88
+
89
+ The `options` parameter is a powerful tool for customizing the query string generation. It has the following key elements:
90
+
91
+ * **Search:**
92
+ * `searchKey`: Specifies the field to search on. If using SASQ, the corresponding value in `nsValues.query` will be used as the search term. Otherwise, you can directly specify the search term using the `term` key in `options`.
93
+ * **Filters:** See the "Filters Object Structure" section below for details.
94
+ * **Sorting:**
95
+ * `sortKeys`: An object mapping sort field names from `nsValues.sort` to their corresponding backend keys.
96
+ * `sort`: An array of sort objects. Each object can have `path` (field to sort on) and `direction` (`asc` or `desc`).
97
+ * **Statistics:**
98
+ * `stats`: A boolean value indicating whether to include the `stats=true` parameter.
99
+ * **Other parameters:** Any other key-value pairs in the `options` object will be directly added as query parameters.
100
+
101
+
102
+ ### Filters Object Structure
103
+
104
+ The `filters` option in the `options` parameter allows you to define complex filter expressions using an array of filter objects. Each filter object can have the following properties:
105
+
106
+ * **path:** The path to the field to filter on (e.g., `item.title`).
107
+ * **comparator:** *(Optional)* The comparator to use for the filter (e.g., `==`, `!=`, `>`, `<`). Defaults to `==`.
108
+ * **value:** A single value to filter on.
109
+ * **values:** An array of values to filter on. If present, this property takes precedence over `value`, and an `OR` condition is implied between the values.
110
+ * **groupValues:** An object defining nested filter groups with `AND` or `OR` logic. This property allows for building complex nested filters. See the explanation below.
111
+
112
+ #### Nested Filter Groups (`groupValues`)
113
+
114
+ The `groupValues` property enables the creation of nested filter expressions with `AND` and `OR` logic. It is an object with either `AND` or `OR` properties (or both, with `AND` taking precedence). The value of these properties should be an array of filter objects, allowing for recursive nesting.
115
+
116
+ ```javascript
117
+ // Example: (status==active AND type==local) OR (status==pending)
118
+ const filters = [
119
+ {
120
+ groupValues: {
121
+ OR: [
122
+ {
123
+ groupValues: {
124
+ AND: [
125
+ { path: 'item.status', value: 'active' },
126
+ { path: 'item.type', value: 'local' },
127
+ ],
128
+ }
129
+ },
130
+ { path: 'item.status', value: 'pending' },
131
+ ]
132
+ },
133
+ },
134
+ ];
135
+ ```
136
+
137
+ This structure allows you to express complex filter logic in a clear and organized way.
138
+
139
+ ### Key Takeaways
140
+
141
+ * `generateKiwtQuery` provides a flexible way to construct URL query strings for backend APIs, especially when working with Stripes SASQ.
142
+ * The `options` parameter offers fine-grained control over the query generation process, allowing for complex filtering, sorting, and other customizations.
143
+ * `generateKiwtQueryParams` is useful for advanced use cases where you need to manipulate the parameters before constructing the final query string.