@k-int/stripes-kint-components 5.7.1 → 5.8.1

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,25 @@
1
+ ## [5.8.1](https://gitlab.com/knowledge-integration/folio/stripes-kint-components/compare/v5.8.0...v5.8.1) (2024-07-22)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * NumberField treating 0 as undefined ([75bd7d3](https://gitlab.com/knowledge-integration/folio/stripes-kint-components/commit/75bd7d33c77f103df6dd0efdde059b90dc3a9b8f))
7
+
8
+ # [5.8.0](https://gitlab.com/knowledge-integration/folio/stripes-kint-components/compare/v5.7.1...v5.8.0) (2024-06-27)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * Add default MCLProps to TableBody to fix issue with SASQRoute (or below) not being passed mclProps ([af4a143](https://gitlab.com/knowledge-integration/folio/stripes-kint-components/commit/af4a14368621f8194e7a656c4e01355b8b9eff50))
14
+ * **deps:** update dependency react-resize-detector to v11 ([5c3f22a](https://gitlab.com/knowledge-integration/folio/stripes-kint-components/commit/5c3f22ac702c8eafe556f2dd61ed787c0961b53e))
15
+ * NumberField could not initialise with a previous input ([adc21e4](https://gitlab.com/knowledge-integration/folio/stripes-kint-components/commit/adc21e4f9b2aa2d262ed0358cbb07cf771f45408))
16
+
17
+
18
+ ### Features
19
+
20
+ * added ability for generateKiwtQueryParams sortKeys to contain multiple terms, eg `columnName: 'name, description'` ([1f5df10](https://gitlab.com/knowledge-integration/folio/stripes-kint-components/commit/1f5df103b14e3cabf450809bba6cefef8892a3d7))
21
+ * NumberField ([c428844](https://gitlab.com/knowledge-integration/folio/stripes-kint-components/commit/c4288449e0a84bbf17f2bdb05250f36642e44e51))
22
+
1
23
  ## [5.7.1](https://gitlab.com/knowledge-integration/folio/stripes-kint-components/compare/v5.7.0...v5.7.1) (2024-06-27)
2
24
 
3
25
 
package/es/index.js CHANGED
@@ -49,7 +49,8 @@ var _exportNames = {
49
49
  FormattedKintMessage: true,
50
50
  ResponsiveButtonGroup: true,
51
51
  SettingsFormContainer: true,
52
- ComboButton: true
52
+ ComboButton: true,
53
+ NumberField: true
53
54
  };
54
55
  Object.defineProperty(exports, "ActionList", {
55
56
  enumerable: true,
@@ -201,6 +202,12 @@ Object.defineProperty(exports, "NoResultsMessage", {
201
202
  return _NoResultsMessage.default;
202
203
  }
203
204
  });
205
+ Object.defineProperty(exports, "NumberField", {
206
+ enumerable: true,
207
+ get: function () {
208
+ return _NumberField.default;
209
+ }
210
+ });
204
211
  Object.defineProperty(exports, "QueryTypedown", {
205
212
  enumerable: true,
206
213
  get: function () {
@@ -392,6 +399,7 @@ var _FormattedKintMessage = _interopRequireDefault(require("./lib/FormattedKintM
392
399
  var _ResponsiveButtonGroup = _interopRequireDefault(require("./lib/ResponsiveButtonGroup"));
393
400
  var _SettingsFormContainer = _interopRequireDefault(require("./lib/SettingsFormContainer"));
394
401
  var _ComboButton = _interopRequireDefault(require("./lib/ComboButton"));
402
+ var _NumberField = _interopRequireDefault(require("./lib/NumberField"));
395
403
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
396
404
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
397
405
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
@@ -11,6 +11,7 @@ var _components = require("@folio/stripes/components");
11
11
  var _validators = require("../../validators");
12
12
  var _customProperties = require("../../constants/customProperties");
13
13
  var _hooks = require("../../hooks");
14
+ var _NumberField = _interopRequireDefault(require("../../NumberField"));
14
15
  var _jsxRuntime = require("react/jsx-runtime");
15
16
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
16
17
  const CustomPropertyForm = _ref => {
@@ -250,7 +251,7 @@ const CustomPropertyForm = _ref => {
250
251
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Col, {
251
252
  xs: 3,
252
253
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactFinalForm.Field, {
253
- component: _components.TextField,
254
+ component: _NumberField.default,
254
255
  id: "custom-prop-weight",
255
256
  label: /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
256
257
  children: [kintIntl.formatKintMessage({
@@ -262,7 +263,6 @@ const CustomPropertyForm = _ref => {
262
263
  }),
263
264
  name: "weight",
264
265
  required: true,
265
- type: "number",
266
266
  validate: _validators.required
267
267
  })
268
268
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Col, {
@@ -10,6 +10,7 @@ var _orderBy = _interopRequireDefault(require("lodash/orderBy"));
10
10
  var _components = require("@folio/stripes/components");
11
11
  var CUSTOM_PROPERTY_TYPES = _interopRequireWildcard(require("../../constants/customProperties"));
12
12
  var _hooks = require("../../hooks");
13
+ var _NumberField = _interopRequireDefault(require("../../NumberField"));
13
14
  var _jsxRuntime = require("react/jsx-runtime");
14
15
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
15
16
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
@@ -179,11 +180,10 @@ const CustomPropertyField = _ref => {
179
180
  case CUSTOM_PROPERTY_TYPES.INTEGER_CLASS_NAME:
180
181
  case CUSTOM_PROPERTY_TYPES.DECIMAL_CLASS_NAME:
181
182
  fieldProps = {
182
- component: _components.TextField,
183
+ component: _NumberField.default,
183
184
  max,
184
185
  min,
185
- step: 'any',
186
- type: 'number'
186
+ step: 'any'
187
187
  };
188
188
  handleChange = e => {
189
189
  onChange({
@@ -192,7 +192,7 @@ const CustomPropertyField = _ref => {
192
192
  ...currentValue,
193
193
  _delete: e.target.value === '' ? true : undefined,
194
194
  // Delete customProperty if removing the value.
195
- value: parseFloat(e.target.value)
195
+ value: e.target.value
196
196
  }]
197
197
  });
198
198
  };
@@ -29,6 +29,10 @@ const EditSettingValue = props => {
29
29
  }, {
30
30
  name: setting.key
31
31
  });
32
+
33
+ // Adding default sort to refdata object in ascending order by label
34
+ const sortByLabel = (a, b) => a.label.localeCompare(b.label);
35
+ const sortedRefdata = refdata?.sort(sortByLabel);
32
36
  switch (setting.settingType) {
33
37
  case 'Refdata':
34
38
  // Grab refdata values corresponding to setting
@@ -37,10 +41,6 @@ const EditSettingValue = props => {
37
41
  if (refdata.length > 0 && refdata.length <= 4) {
38
42
  RefdataComponent = _RefdataButtons.default;
39
43
  }
40
-
41
- // Adding default sort to refdata object in ascending order by label
42
- const sortByLabel = (a, b) => a.label.localeCompare(b.label);
43
- const sortedRefdata = refdata.sort(sortByLabel);
44
44
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactFinalForm.Field, {
45
45
  "aria-label": fieldLabel,
46
46
  component: RefdataComponent,
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _react = require("react");
8
+ var _propTypes = _interopRequireDefault(require("prop-types"));
9
+ var _noop = _interopRequireDefault(require("lodash/noop"));
10
+ var _components = require("@folio/stripes/components");
11
+ var _jsxRuntime = require("react/jsx-runtime");
12
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
+ const NumberField = props => {
14
+ const {
15
+ onChange: passedOnChange = _noop.default,
16
+ input,
17
+ value,
18
+ ...rest
19
+ } = props;
20
+
21
+ // Treat TextField ALWAYS as a controlled component, whether or not NumberField itself is controlled
22
+ // This enforces the behaviour whereby 1e2 -> 100 in the typed field automatically
23
+ const [forceControl, setForceControl] = (0, _react.useState)(value ?? input?.value);
24
+ const inputRef = (0, _react.useRef)();
25
+ const userInputRef = (0, _react.useRef)();
26
+ const [numValue, setNumValue] = (0, _react.useState)('');
27
+ const changeField = val => {
28
+ (0, _components.nativeChangeFieldValue)(inputRef, false, val);
29
+ };
30
+
31
+ // Allow direct control of field
32
+ (0, _react.useEffect)(() => {
33
+ if (value && numValue !== value) {
34
+ setNumValue(value);
35
+ }
36
+ if (numValue && forceControl !== numValue) {
37
+ setForceControl(numValue);
38
+ }
39
+ }, [forceControl, numValue, value]);
40
+ const handleChange = e => {
41
+ // Actually set the value in the form
42
+ if (input?.onChange) {
43
+ input.onChange(e);
44
+ }
45
+
46
+ // Set the forced control (this may be wiped by passedOnChange)
47
+ setForceControl(e.target.value);
48
+
49
+ // If the user has set up an onChange, this will ensure that that fires
50
+ if (passedOnChange) {
51
+ passedOnChange(e, e.target.value);
52
+ }
53
+ };
54
+ const handleUserChange = e => {
55
+ const parsedValue = parseFloat(e.target.value);
56
+
57
+ // ReturnValue needed for contorlled components
58
+ if (parsedValue || parsedValue === 0) {
59
+ setNumValue(parsedValue);
60
+ changeField(parsedValue);
61
+ } else {
62
+ setNumValue('');
63
+ changeField('');
64
+ }
65
+ };
66
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
67
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.TextField, {
68
+ ref: userInputRef,
69
+ ...rest,
70
+ // Keep an eye on this
71
+ onChange: handleUserChange,
72
+ type: "number",
73
+ value: forceControl
74
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("input", {
75
+ ref: inputRef,
76
+ ...input,
77
+ hidden: true,
78
+ onChange: handleChange,
79
+ type: "number",
80
+ value: numValue
81
+ })]
82
+ });
83
+ };
84
+ NumberField.propTypes = {
85
+ onChange: _propTypes.default.func,
86
+ input: _propTypes.default.shape({
87
+ onChange: _propTypes.default.func.isRequired,
88
+ value: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string])
89
+ }),
90
+ value: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string])
91
+ };
92
+ var _default = exports.default = NumberField;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "default", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _NumberField.default;
10
+ }
11
+ });
12
+ var _NumberField = _interopRequireDefault(require("./NumberField"));
13
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
@@ -160,13 +160,22 @@ const generateKiwtQueryParams = function (options, nsValues) {
160
160
  }
161
161
  if (sort) {
162
162
  paramsArray.push(...(sort.trim()?.split(',') ?? []).map(sortKey => {
163
- const descending = sortKey.startsWith('-');
163
+ const reverse = sortKey.startsWith('-');
164
164
  let term = sortKey.replace('-', '');
165
165
  if (term in sortKeys) {
166
166
  term = term.replace(term, sortKeys[term]);
167
167
  }
168
- const sortString = `${term};${descending ? 'desc' : 'asc'}`;
169
- return `sort=${conditionalEncodeURIComponent(sortString, encode)}`;
168
+
169
+ // Split the term by commas to handle multiple fields if specified
170
+ const fields = term.split(',');
171
+ const sortStrings = fields.map(field => {
172
+ const descending = field.startsWith('-');
173
+ const sortField = field.replace('-', '');
174
+ const sortOrder = reverse && !descending || !reverse && descending ? 'desc' : 'asc';
175
+ const sortString = `${sortField};${sortOrder}`;
176
+ return `sort=${conditionalEncodeURIComponent(sortString, encode)}`;
177
+ });
178
+ return sortStrings.join('&');
170
179
  }));
171
180
  }
172
181
  if (stats) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@k-int/stripes-kint-components",
3
- "version": "5.7.1",
3
+ "version": "5.8.1",
4
4
  "description": "Stripes Component library for K-Int specific applications",
5
5
  "sideEffects": [
6
6
  "*.css"
@@ -9,7 +9,7 @@
9
9
  "scripts": {
10
10
  "lint": "eslint src --resolve-plugins-relative-to ./node_modules/@folio/eslint-config-stripes/",
11
11
  "test": "yarn run test:jest",
12
- "test:jest": "jest --ci --coverage",
12
+ "test:jest": "jest --ci --coverage --maxWorkers=50%",
13
13
  "build:es": "rm -rf ./es && babel --extensions .js --ignore ./src/**/tests/**/* ./src --out-dir es",
14
14
  "build": "yarn build:es",
15
15
  "clean": "rm -rf ./node_modules ./*/node_modules ./yarn.lock && yarn install --ignore-scripts",
@@ -23,7 +23,7 @@
23
23
  "dependencies": {
24
24
  "@rehooks/local-storage": "^2.4.4",
25
25
  "compose-function": "^3.0.3",
26
- "react-resize-detector": "^10.0.0",
26
+ "react-resize-detector": "^11.0.0",
27
27
  "zustand": "^4.0.0"
28
28
  },
29
29
  "devDependencies": {
@@ -60,7 +60,6 @@
60
60
  "eslint-plugin-jest": "^28.0.0",
61
61
  "graphql": "^16.0.0",
62
62
  "identity-obj-proxy": "^3.0.0",
63
- "moment": "^2.29.4",
64
63
  "prop-types-extra": ">=1.1.0",
65
64
  "react": "^18.2.0",
66
65
  "react-dom": "^18.2.0",
@@ -74,7 +73,7 @@
74
73
  "regenerator-runtime": "^0.14.0",
75
74
  "rxjs": "^7.0.0",
76
75
  "semantic-release": "^22.0.6",
77
- "sinon": "^17.0.0"
76
+ "sinon": "^18.0.0"
78
77
  },
79
78
  "peerDependencies": {
80
79
  "@folio/stripes": ">=9.0.0",
package/src/index.js CHANGED
@@ -111,3 +111,5 @@ export { default as ResponsiveButtonGroup } from './lib/ResponsiveButtonGroup';
111
111
  export { default as SettingsFormContainer } from './lib/SettingsFormContainer';
112
112
 
113
113
  export { default as ComboButton } from './lib/ComboButton';
114
+
115
+ export { default as NumberField } from './lib/NumberField';
@@ -22,6 +22,7 @@ import {
22
22
  DATE_CLASS_NAME
23
23
  } from '../../constants/customProperties';
24
24
  import { useKintIntl } from '../../hooks';
25
+ import NumberField from '../../NumberField';
25
26
 
26
27
  const CustomPropertyForm = ({
27
28
  contextFilterOptions,
@@ -298,7 +299,7 @@ const CustomPropertyForm = ({
298
299
  <Row>
299
300
  <Col xs={3}>
300
301
  <Field
301
- component={TextField}
302
+ component={NumberField}
302
303
  id="custom-prop-weight"
303
304
  label={
304
305
  <div>
@@ -316,7 +317,6 @@ const CustomPropertyForm = ({
316
317
  }
317
318
  name="weight"
318
319
  required
319
- type="number"
320
320
  validate={requiredValidator}
321
321
  />
322
322
  </Col>
@@ -17,6 +17,7 @@ import {
17
17
  import * as CUSTOM_PROPERTY_TYPES from '../../constants/customProperties';
18
18
 
19
19
  import { useKintIntl } from '../../hooks';
20
+ import NumberField from '../../NumberField';
20
21
 
21
22
  const CustomPropertyField = ({
22
23
  availableCustomProperties,
@@ -195,11 +196,10 @@ const CustomPropertyField = ({
195
196
  case CUSTOM_PROPERTY_TYPES.INTEGER_CLASS_NAME:
196
197
  case CUSTOM_PROPERTY_TYPES.DECIMAL_CLASS_NAME:
197
198
  fieldProps = {
198
- component: TextField,
199
+ component: NumberField,
199
200
  max,
200
201
  min,
201
202
  step: 'any',
202
- type: 'number',
203
203
  };
204
204
  handleChange = e => {
205
205
  onChange({
@@ -207,7 +207,7 @@ const CustomPropertyField = ({
207
207
  [customProperty.value]: [{
208
208
  ...currentValue,
209
209
  _delete: e.target.value === '' ? true : undefined, // Delete customProperty if removing the value.
210
- value: parseFloat(e.target.value)
210
+ value: e.target.value
211
211
  }],
212
212
  });
213
213
  };
@@ -27,6 +27,10 @@ const EditSettingValue = (props) => {
27
27
  overrideValue: labelOverrides?.valueFor
28
28
  }, { name: setting.key });
29
29
 
30
+ // Adding default sort to refdata object in ascending order by label
31
+ const sortByLabel = (a, b) => (a.label.localeCompare(b.label));
32
+ const sortedRefdata = refdata?.sort(sortByLabel);
33
+
30
34
  switch (setting.settingType) {
31
35
  case 'Refdata':
32
36
  // Grab refdata values corresponding to setting
@@ -36,10 +40,6 @@ const EditSettingValue = (props) => {
36
40
  RefdataComponent = RefdataButtons;
37
41
  }
38
42
 
39
- // Adding default sort to refdata object in ascending order by label
40
- const sortByLabel = (a, b) => (a.label.localeCompare(b.label));
41
- const sortedRefdata = refdata.sort(sortByLabel);
42
-
43
43
  return (
44
44
  <Field
45
45
  aria-label={fieldLabel}
@@ -0,0 +1,113 @@
1
+ import {
2
+ useEffect,
3
+ useRef,
4
+ useState
5
+ } from 'react';
6
+ import PropTypes from 'prop-types';
7
+ import noop from 'lodash/noop';
8
+
9
+ import {
10
+ nativeChangeFieldValue as nativeChangeField,
11
+ TextField
12
+ } from '@folio/stripes/components';
13
+
14
+
15
+ const NumberField = (props) => {
16
+ const {
17
+ onChange: passedOnChange = noop,
18
+ input,
19
+ value,
20
+ ...rest
21
+ } = props;
22
+
23
+ // Treat TextField ALWAYS as a controlled component, whether or not NumberField itself is controlled
24
+ // This enforces the behaviour whereby 1e2 -> 100 in the typed field automatically
25
+ const [forceControl, setForceControl] = useState(value ?? input?.value);
26
+
27
+ const inputRef = useRef();
28
+ const userInputRef = useRef();
29
+
30
+ const [numValue, setNumValue] = useState('');
31
+
32
+ const changeField = (val) => {
33
+ nativeChangeField(inputRef, false, val);
34
+ };
35
+
36
+ // Allow direct control of field
37
+ useEffect(() => {
38
+ if (value && numValue !== value) {
39
+ setNumValue(value);
40
+ }
41
+
42
+ if (numValue && forceControl !== numValue) {
43
+ setForceControl(numValue);
44
+ }
45
+ }, [forceControl, numValue, value]);
46
+
47
+ const handleChange = (e) => {
48
+ // Actually set the value in the form
49
+ if (input?.onChange) {
50
+ input.onChange(e);
51
+ }
52
+
53
+ // Set the forced control (this may be wiped by passedOnChange)
54
+ setForceControl(e.target.value);
55
+
56
+ // If the user has set up an onChange, this will ensure that that fires
57
+ if (passedOnChange) {
58
+ passedOnChange(e, e.target.value);
59
+ }
60
+ };
61
+
62
+
63
+
64
+ const handleUserChange = (e) => {
65
+ const parsedValue = parseFloat(e.target.value);
66
+
67
+ // ReturnValue needed for contorlled components
68
+ if (parsedValue || parsedValue === 0) {
69
+ setNumValue(parsedValue);
70
+ changeField(parsedValue);
71
+ } else {
72
+ setNumValue('');
73
+ changeField('');
74
+ }
75
+ };
76
+
77
+ return (
78
+ <>
79
+ <TextField
80
+ ref={userInputRef}
81
+ {...rest} // Keep an eye on this
82
+ onChange={handleUserChange}
83
+ type="number"
84
+ value={forceControl}
85
+ />
86
+ <input
87
+ ref={inputRef}
88
+ {...input}
89
+ hidden
90
+ onChange={handleChange}
91
+ type="number"
92
+ value={numValue}
93
+ />
94
+ </>
95
+ );
96
+ };
97
+
98
+ NumberField.propTypes = {
99
+ onChange: PropTypes.func,
100
+ input: PropTypes.shape({
101
+ onChange: PropTypes.func.isRequired,
102
+ value: PropTypes.oneOfType([
103
+ PropTypes.number,
104
+ PropTypes.string
105
+ ])
106
+ }),
107
+ value: PropTypes.oneOfType([
108
+ PropTypes.number,
109
+ PropTypes.string
110
+ ])
111
+ };
112
+
113
+ export default NumberField;
@@ -0,0 +1,3 @@
1
+ export { default } from './NumberField';
2
+
3
+
@@ -157,19 +157,28 @@ const generateKiwtQueryParams = (options, nsValues, encode = true) => {
157
157
 
158
158
  if (sort) {
159
159
  paramsArray.push(...(sort.trim()?.split(',') ?? []).map(sortKey => {
160
- const descending = sortKey.startsWith('-');
160
+ const reverse = sortKey.startsWith('-');
161
161
  let term = sortKey.replace('-', '');
162
162
 
163
163
  if (term in sortKeys) {
164
164
  term = term.replace(term, sortKeys[term]);
165
165
  }
166
166
 
167
- const sortString = `${term};${descending ? 'desc' : 'asc'}`;
168
-
169
- return `sort=${conditionalEncodeURIComponent(sortString, encode)}`;
167
+ // Split the term by commas to handle multiple fields if specified
168
+ const fields = term.split(',');
169
+ const sortStrings = fields.map(field => {
170
+ const descending = field.startsWith('-');
171
+ const sortField = field.replace('-', '');
172
+ const sortOrder = (reverse && !descending) || (!reverse && descending) ? 'desc' : 'asc';
173
+ const sortString = `${sortField};${sortOrder}`;
174
+ return `sort=${conditionalEncodeURIComponent(sortString, encode)}`;
175
+ });
176
+
177
+ return sortStrings.join('&');
170
178
  }));
171
179
  }
172
180
 
181
+
173
182
  if (stats) {
174
183
  paramsArray.push('stats=true');
175
184
  }