@k-int/stripes-kint-components 5.17.0 → 5.19.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 (129) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/LICENSE +1 -1
  3. package/es/index.js +32 -12
  4. package/es/lib/EditableSettingsList/EditableSettingsList.js +4 -3
  5. package/es/lib/EditableSettingsList/EditableSettingsListFieldArray/EditableSettingsListFieldArray.js +110 -0
  6. package/es/lib/EditableSettingsList/{EditableSettingsListFieldArray.test.js → EditableSettingsListFieldArray/EditableSettingsListFieldArray.test.js} +3 -4
  7. package/es/lib/EditableSettingsList/EditableSettingsListFieldArray/index.js +13 -0
  8. package/es/lib/EditableSettingsList/SettingField/{EditSettingValue.js → EditSettingValue/EditSettingValue.js} +2 -2
  9. package/es/lib/EditableSettingsList/SettingField/{EditSettingValue.test.js → EditSettingValue/EditSettingValue.test.js} +2 -3
  10. package/es/lib/EditableSettingsList/SettingField/EditSettingValue/index.js +13 -0
  11. package/es/lib/EditableSettingsList/SettingField/{RenderSettingValue.js → RenderSettingValue/RenderSettingValue.js} +1 -1
  12. package/es/lib/EditableSettingsList/SettingField/{RenderSettingValue.test.js → RenderSettingValue/RenderSettingValue.test.js} +2 -2
  13. package/es/lib/EditableSettingsList/SettingField/RenderSettingValue/index.js +13 -0
  14. package/es/lib/EditableSettingsList/SettingField/SettingField.js +5 -5
  15. package/es/lib/EditableSettingsList/SettingField/SettingField.test.js +54 -44
  16. package/es/lib/EditableSettingsList/index.js +12 -0
  17. package/es/lib/SASQLookupComponent/SASQLookupComponent.js +5 -1
  18. package/es/lib/SearchKeyControl/SearchKeyControl.js +95 -0
  19. package/es/lib/SearchKeyControl/SearchKeyControl.test.js +177 -0
  20. package/es/lib/SearchKeyControl/index.js +13 -0
  21. package/es/lib/SettingPage/SettingPage.js +3 -1
  22. package/es/lib/SettingPage/{SettingPagePane.js → SettingPagePane/SettingPagePane.js} +2 -2
  23. package/es/lib/SettingPage/SettingPagePane/index.js +13 -0
  24. package/es/lib/hooks/__mocks__/index.js +2 -2
  25. package/es/lib/hooks/index.js +33 -21
  26. package/es/lib/hooks/intlHooks/index.js +27 -0
  27. package/es/lib/hooks/intlHooks/useIntlKey/index.js +13 -0
  28. package/es/lib/hooks/{useIntlKey.js → intlHooks/useIntlKey/useIntlKey.js} +1 -1
  29. package/es/lib/hooks/intlHooks/useIntlKeyStore/index.js +13 -0
  30. package/es/lib/hooks/intlHooks/useKintIntl/index.js +13 -0
  31. package/es/lib/hooks/{useKintIntl.js → intlHooks/useKintIntl/useKintIntl.js} +1 -1
  32. package/es/lib/hooks/useInvalidateRefdata/index.js +13 -0
  33. package/es/lib/hooks/{useInvalidateRefdata.js → useInvalidateRefdata/useInvalidateRefdata.js} +1 -1
  34. package/es/lib/hooks/useMutateCustomProperties/index.js +13 -0
  35. package/es/lib/hooks/{useMutateCustomProperties.js → useMutateCustomProperties/useMutateCustomProperties.js} +1 -1
  36. package/es/lib/hooks/useMutateGeneric/index.js +13 -0
  37. package/es/lib/hooks/useMutateRefdataCategory/index.js +13 -0
  38. package/es/lib/hooks/{useMutateRefdataCategory.js → useMutateRefdataCategory/useMutateRefdataCategory.js} +2 -2
  39. package/es/lib/hooks/useMutateRefdataValue/index.js +13 -0
  40. package/es/lib/hooks/{useMutateRefdataValue.js → useMutateRefdataValue/useMutateRefdataValue.js} +2 -2
  41. package/es/lib/settingsHooks/useAppSettings/index.js +13 -0
  42. package/es/lib/settingsHooks/{useAppSettings.js → useAppSettings/useAppSettings.js} +1 -1
  43. package/es/lib/settingsHooks/useSettingSection/index.js +13 -0
  44. package/es/lib/settingsHooks/{useSettingSection.js → useSettingSection/useSettingSection.js} +1 -1
  45. package/es/lib/settingsHooks/useSettings/index.js +13 -0
  46. package/es/lib/settingsHooks/{useSettings.js → useSettings/useSettings.js} +10 -9
  47. package/es/lib/utils/refdataQueryKey/index.js +13 -0
  48. package/package.json +1 -1
  49. package/src/index.js +8 -3
  50. package/src/lib/ActionList/README.md +18 -18
  51. package/src/lib/EditableSettingsList/EditableSettingsList.js +3 -2
  52. package/src/lib/EditableSettingsList/EditableSettingsListFieldArray/EditableSettingsListFieldArray.js +118 -0
  53. package/src/lib/EditableSettingsList/{EditableSettingsListFieldArray.test.js → EditableSettingsListFieldArray/EditableSettingsListFieldArray.test.js} +3 -5
  54. package/src/lib/EditableSettingsList/EditableSettingsListFieldArray/README.md +68 -0
  55. package/src/lib/EditableSettingsList/EditableSettingsListFieldArray/index.js +1 -0
  56. package/src/lib/EditableSettingsList/README.md +74 -0
  57. package/src/lib/EditableSettingsList/SettingField/{EditSettingValue.js → EditSettingValue/EditSettingValue.js} +2 -2
  58. package/src/lib/EditableSettingsList/SettingField/{EditSettingValue.test.js → EditSettingValue/EditSettingValue.test.js} +2 -5
  59. package/src/lib/EditableSettingsList/SettingField/EditSettingValue/README.md +63 -0
  60. package/src/lib/EditableSettingsList/SettingField/EditSettingValue/index.js +1 -0
  61. package/src/lib/EditableSettingsList/SettingField/README.md +61 -0
  62. package/src/lib/EditableSettingsList/SettingField/{RenderSettingValue.js → RenderSettingValue/RenderSettingValue.js} +1 -1
  63. package/src/lib/EditableSettingsList/SettingField/{RenderSettingValue.test.js → RenderSettingValue/RenderSettingValue.test.js} +2 -2
  64. package/src/lib/EditableSettingsList/SettingField/RenderSettingValue/index.js +1 -0
  65. package/src/lib/EditableSettingsList/SettingField/SettingField.js +5 -3
  66. package/src/lib/EditableSettingsList/SettingField/SettingField.test.js +65 -44
  67. package/src/lib/EditableSettingsList/index.js +1 -1
  68. package/src/lib/NumberField/README.md +134 -0
  69. package/src/lib/SASQLookupComponent/README.md +172 -0
  70. package/src/lib/SASQLookupComponent/SASQLookupComponent.js +6 -1
  71. package/src/lib/SASQLookupComponent/TableBody/README.md +113 -0
  72. package/src/lib/SASQRoute/README.md +49 -18
  73. package/src/lib/SASQViewComponent/README.md +132 -0
  74. package/src/lib/SearchKeyControl/README.md +70 -0
  75. package/src/lib/SearchKeyControl/SearchKeyControl.js +98 -0
  76. package/src/lib/SearchKeyControl/SearchKeyControl.test.js +165 -0
  77. package/src/lib/SearchKeyControl/index.js +1 -0
  78. package/src/lib/SettingPage/README.md +66 -0
  79. package/src/lib/SettingPage/SettingPage.js +3 -1
  80. package/src/lib/SettingPage/SettingPagePane/README.md +31 -0
  81. package/src/lib/SettingPage/{SettingPagePane.js → SettingPagePane/SettingPagePane.js} +2 -2
  82. package/src/lib/SettingPage/SettingPagePane/index.js +1 -0
  83. package/src/lib/hooks/README.md +26 -121
  84. package/src/lib/hooks/__mocks__/index.js +2 -2
  85. package/src/lib/hooks/index.js +2 -3
  86. package/src/lib/hooks/intlHooks/README.md +31 -0
  87. package/src/lib/hooks/intlHooks/index.js +3 -0
  88. package/src/lib/hooks/intlHooks/useIntlKey/README.md +23 -0
  89. package/src/lib/hooks/intlHooks/useIntlKey/index.js +1 -0
  90. package/src/lib/hooks/{useIntlKey.js → intlHooks/useIntlKey/useIntlKey.js} +1 -1
  91. package/src/lib/hooks/intlHooks/useIntlKeyStore/README.md +32 -0
  92. package/src/lib/hooks/intlHooks/useIntlKeyStore/index.js +1 -0
  93. package/src/lib/hooks/intlHooks/useKintIntl/README.md +42 -0
  94. package/src/lib/hooks/intlHooks/useKintIntl/index.js +1 -0
  95. package/src/lib/hooks/{useKintIntl.js → intlHooks/useKintIntl/useKintIntl.js} +1 -1
  96. package/src/lib/hooks/useInvalidateRefdata/README.md +72 -0
  97. package/src/lib/hooks/useInvalidateRefdata/index.js +1 -0
  98. package/src/lib/hooks/{useInvalidateRefdata.js → useInvalidateRefdata/useInvalidateRefdata.js} +1 -1
  99. package/src/lib/hooks/useMutateCustomProperties/README.md +88 -0
  100. package/src/lib/hooks/useMutateCustomProperties/index.js +1 -0
  101. package/src/lib/hooks/{useMutateCustomProperties.js → useMutateCustomProperties/useMutateCustomProperties.js} +1 -1
  102. package/src/lib/hooks/useMutateGeneric/README.md +187 -0
  103. package/src/lib/hooks/useMutateGeneric/index.js +1 -0
  104. package/src/lib/hooks/useMutateRefdataCategory/README.md +85 -0
  105. package/src/lib/hooks/useMutateRefdataCategory/index.js +1 -0
  106. package/src/lib/hooks/{useMutateRefdataCategory.js → useMutateRefdataCategory/useMutateRefdataCategory.js} +2 -2
  107. package/src/lib/hooks/useMutateRefdataValue/README.md +154 -0
  108. package/src/lib/hooks/useMutateRefdataValue/index.js +1 -0
  109. package/src/lib/hooks/{useMutateRefdataValue.js → useMutateRefdataValue/useMutateRefdataValue.js} +2 -2
  110. package/src/lib/settingsHooks/useAppSettings/README.md +24 -0
  111. package/src/lib/settingsHooks/useAppSettings/index.js +1 -0
  112. package/src/lib/settingsHooks/{useAppSettings.js → useAppSettings/useAppSettings.js} +1 -1
  113. package/src/lib/settingsHooks/useSettingSection/README.md +54 -0
  114. package/src/lib/settingsHooks/useSettingSection/index.js +1 -0
  115. package/src/lib/settingsHooks/{useSettingSection.js → useSettingSection/useSettingSection.js} +1 -1
  116. package/src/lib/settingsHooks/useSettings/README.md +84 -0
  117. package/src/lib/settingsHooks/useSettings/index.js +1 -0
  118. package/src/lib/settingsHooks/{useSettings.js → useSettings/useSettings.js} +10 -7
  119. package/src/lib/utils/refdataQueryKey/README.md +38 -0
  120. package/src/lib/utils/refdataQueryKey/index.js +1 -0
  121. package/styles/SearchKeyControl.css +14 -0
  122. package/es/lib/EditableSettingsList/EditableSettingsListFieldArray.js +0 -57
  123. package/src/lib/EditableSettingsList/EditableSettingsListFieldArray.js +0 -58
  124. /package/es/lib/hooks/{useIntlKeyStore.js → intlHooks/useIntlKeyStore/useIntlKeyStore.js} +0 -0
  125. /package/es/lib/hooks/{useMutateGeneric.js → useMutateGeneric/useMutateGeneric.js} +0 -0
  126. /package/es/lib/utils/{refdataQueryKey.js → refdataQueryKey/refdataQueryKey.js} +0 -0
  127. /package/src/lib/hooks/{useIntlKeyStore.js → intlHooks/useIntlKeyStore/useIntlKeyStore.js} +0 -0
  128. /package/src/lib/hooks/{useMutateGeneric.js → useMutateGeneric/useMutateGeneric.js} +0 -0
  129. /package/src/lib/utils/{refdataQueryKey.js → refdataQueryKey/refdataQueryKey.js} +0 -0
@@ -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 _useSettingSection.default;
10
+ }
11
+ });
12
+ var _useSettingSection = _interopRequireDefault(require("./useSettingSection"));
13
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = void 0;
7
7
  var _reactQuery = require("react-query");
8
8
  var _core = require("@folio/stripes/core");
9
- var _utils = require("../utils");
9
+ var _utils = require("../../utils");
10
10
  const useSettingSection = _ref => {
11
11
  let {
12
12
  sectionName,
@@ -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 _useSettings.default;
10
+ }
11
+ });
12
+ var _useSettings = _interopRequireDefault(require("./useSettings"));
13
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
@@ -4,19 +4,17 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
- var _react = _interopRequireWildcard(require("react"));
7
+ var _react = require("react");
8
8
  var _propTypes = _interopRequireDefault(require("prop-types"));
9
9
  var _reactQuery = require("react-query");
10
10
  var _core = require("@folio/stripes/core");
11
11
  var _smartComponents = require("@folio/stripes/smart-components");
12
- var _SettingPage = require("../SettingPage");
13
- var _contexts = require("../contexts");
14
- var _utils = require("../utils");
15
- var _hooks = require("../hooks");
12
+ var _SettingPage = require("../../SettingPage");
13
+ var _contexts = require("../../contexts");
14
+ var _utils = require("../../utils");
15
+ var _hooks = require("../../hooks");
16
16
  var _jsxRuntime = require("react/jsx-runtime");
17
17
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
18
- 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); }
19
- 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; }
20
18
  // TODO work underway to make the settings hook more useful when trying to render multiple sections at a time
21
19
  const useSettings = function () {
22
20
  let settingsProps = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
@@ -40,7 +38,8 @@ const useSettings = function () {
40
38
  // if present, should be an array of objects with the SAME shape as the overall props here.
41
39
  // If a prop isn't present it can fall back to the "global" prop.
42
40
  settingEndpoint,
43
- templateEndpoint
41
+ templateEndpoint,
42
+ render // Allow setting-by-setting rendering of fields, to allow for special treatment for a given setting key etc
44
43
  } = settingsProps;
45
44
  const ky = (0, _core.useOkapiKy)();
46
45
  const stripes = (0, _core.useStripes)();
@@ -105,6 +104,7 @@ const useSettings = function () {
105
104
  const getDynamicPages = (0, _react.useCallback)((qra, sma) => {
106
105
  const pagesFromQueryReturn = [...new Set(qra.data?.map(s => s.section))];
107
106
  const dynamic = pagesFromQueryReturn.map(page => {
107
+ const finalRender = sma.render ?? render;
108
108
  const finalSectionRoute = sma.sectionRoute ?? sectionRoute;
109
109
  const pageRoute = (finalSectionRoute ? `${finalSectionRoute}/` : '') + page;
110
110
  return {
@@ -122,6 +122,7 @@ const useSettings = function () {
122
122
  intlKey: passedIntlKey,
123
123
  intlNS: passedIntlNS,
124
124
  labelOverrides: labelOverrides,
125
+ render: finalRender,
125
126
  sectionName: page,
126
127
  ...props
127
128
  })
@@ -132,7 +133,7 @@ const useSettings = function () {
132
133
  pages: pagesFromQueryReturn,
133
134
  dynamic
134
135
  };
135
- }, [allowGlobalEdit, kintIntl, labelOverrides, passedIntlKey, passedIntlNS, sectionRoute]);
136
+ }, [allowGlobalEdit, kintIntl, labelOverrides, passedIntlKey, passedIntlNS, render, sectionRoute]);
136
137
  (0, _react.useEffect)(() => {
137
138
  // Handle loading
138
139
  if (queryReturnArray.length > 0 && queryReturnArray.every(qra => qra.isLoading === false) && isLoading === true) {
@@ -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 _refdataQueryKey.default;
10
+ }
11
+ });
12
+ var _refdataQueryKey = _interopRequireDefault(require("./refdataQueryKey"));
13
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@k-int/stripes-kint-components",
3
- "version": "5.17.0",
3
+ "version": "5.19.0",
4
4
  "description": "Stripes Component library for K-Int specific applications",
5
5
  "sideEffects": [
6
6
  "*.css"
package/src/index.js CHANGED
@@ -1,9 +1,6 @@
1
1
  // Useful hooks
2
2
  export * from './lib/hooks';
3
3
 
4
- // Settings hooks
5
- export * from './lib/settingsHooks';
6
-
7
4
  // Useful utility stuff
8
5
  export * from './lib/utils';
9
6
 
@@ -20,6 +17,10 @@ export {
20
17
  SettingPage,
21
18
  SettingPagePane,
22
19
  } from './lib/SettingPage';
20
+ export * from './lib/EditableSettingsList';
21
+
22
+ // Settings hooks
23
+ export * from './lib/settingsHooks';
23
24
 
24
25
  // ActionList & RefdataEditor components
25
26
  export { default as ActionList } from './lib/ActionList';
@@ -41,6 +42,10 @@ export {
41
42
  default as SearchField
42
43
  } from './lib/SearchField';
43
44
 
45
+ export {
46
+ default as SearchKeyControl
47
+ } from './lib/SearchKeyControl';
48
+
44
49
  // SASQRoute
45
50
  export {
46
51
  default as SASQRoute
@@ -89,21 +89,21 @@ const myRef = useRef();
89
89
 
90
90
  ## Props
91
91
 
92
- Name | Type | Description | default | required
93
- --- | --- | --- | --- | ---
94
- actionAssigner | function | A function which will be passed the entire row object, and can use that to assign an array of actions valid for that row, in the form `{ name: 'actionName', label: "Action Label", icon: 'someIcon', callback: () => null, to: toObject, ariaLabel: () => null, tooltip: 'tooltip', tooltipSub: 'tooltipSub' }`. The props `name` and `callback` are required, but `label`, `icon`, `to` and `tooltip`/`tooltipSub` are optional props. The `callback` prop will be prioritised ahead of the deprecated actionCalls prop. The `ariaLabel` prop, which can be either a static string or a function accepting the row data and returning a string, will give the associated icon button an aria-label. If a `to` prop is passed, then the resulting button will be rendered as a \<Link/> element, as per Stripes Button/IconButton. If a `tooltip` prop is passed, the actionButton will be rendered with a surrounding Stripes Tooltip, with text `tooltip` and sub `tooltipSub`. | | ✓ |
95
- actionCalls (DEPRECATED) | object\<function> | An object with keys matching any "actions" the `actionAssigner` may have assigned (In addition to special case `create`, if relevant), and values which are functions. These functions will be handed the row as a parameter. THESE CAN NOW BE PASSED AS "callback" in the actionAssigner. | {} | ✕ |
96
- columnMapping | object | An object which will act on the rendered MultiColumnList headers to map the labels for each `visibleField` | | ✕ |
97
- contentData | array | An array of objects to render along with their actions | | ✓ |
98
- creatableFields | object\<function> | An object with keys from the `visibleFields` array, and values of functions which take the entire row object and return a boolean indicating whether that field is fillable on create or not. | | ✕ |
99
- createCallback | function | A callback to be used for the built in "create" action (ie "save" on a new row). Will be prioritised ahead of a `create` entry in the deprecated actionCalls prop. | {} | ✕ |
100
- defaultNewObject | object | An object to use when pushing a new entry into the ActionList fields, acting as a way to bootstrap defaults into new items | {} | ✕ |
101
- editableFields | object\<function> | An object with keys from the `visibleFields` array, and values of functions which take the entire row object and return a boolean indicating whether that field is editable or not. No key for a given field will be interpreted as () => true, so a field is editable by default. | | ✕ |
102
- fieldComponents | object\<function> | An object with keys from the `visibleFields` array, and values of functions which take some `fieldProps` (`allValues`: The full form values, `index`: The current fieldIndex of the editing row, `key`: The object property in question, `name`: The field name for the Field component to glue properly into final-form, `rowFieldName`: The field name in final-form for the whole row object.), and returns a Field component to be used in "edit mode" for the visible field specified. | | ✕ |
103
- formatter | object\<function> | A "formatter" object that takes the same shape as an MCL formatter, and is used in the same way whilst a row is NOT being edited. While editing a given row, this formatter entry is ignored. | | ✕ |
104
- hideActionsColumn | boolean | A simple bool to hide the actions column. This will hide the actions column, unless the ActionList manages to get into a state of "editing/creating". In this case, the actions column will once again display to avoid soft locking the form. | false | ✕ |
105
- hideCreateButton | boolean | A simple bool to hide the create button. Default behaviour without create action is disabled. | false | ✕ |
106
- onRowClick | function | A function accepting an event and the row data, fired on row click. The presence of this prop will cause the MCL to take on the interactive styling | | ✕ |
107
- validateFields | object\<function> | An object with keys from the `visibleFields` array, and values of functions which take the entire row object and either return a validate function for final-form, or null. The validate function will be passed the same properties as fieldComponents, above. THESE WILL NOT BE USED if fieldComponents are defined for the same key. | | ✕ |
108
- visibleFields | array\<String> | An array of strings corresponding to those fields to be displayed in the rendered MultiColumnList | | ✓ |
109
- ...mclProps | any | Any other props supplied to ActionList will be applied to the MCL directly. *WARNING* Some MCL props may override important functionality within ActionList | | ✕ |
92
+ | Name | Type | Description | default | required |
93
+ |--------------------------|-------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|----------|
94
+ | actionAssigner | function | A function which will be passed the entire row object, and can use that to assign an array of actions valid for that row, in the form `{ name: 'actionName', label: "Action Label", icon: 'someIcon', callback: () => null, to: toObject, ariaLabel: () => null, tooltip: 'tooltip', tooltipSub: 'tooltipSub' }`. The props `name` and `callback` are required, but `label`, `icon`, `to` and `tooltip`/`tooltipSub` are optional props. The `callback` prop will be prioritised ahead of the deprecated actionCalls prop. The `ariaLabel` prop, which can be either a static string or a function accepting the row data and returning a string, will give the associated icon button an aria-label. If a `to` prop is passed, then the resulting button will be rendered as a \<Link/> element, as per Stripes Button/IconButton. If a `tooltip` prop is passed, the actionButton will be rendered with a surrounding Stripes Tooltip, with text `tooltip` and sub `tooltipSub`. | | ✓ |
95
+ | actionCalls (DEPRECATED) | object\<function> | An object with keys matching any "actions" the `actionAssigner` may have assigned (In addition to special case `create`, if relevant), and values which are functions. These functions will be handed the row as a parameter. THESE CAN NOW BE PASSED AS "callback" in the actionAssigner. | {} | ✕ |
96
+ | columnMapping | object | An object which will act on the rendered MultiColumnList headers to map the labels for each `visibleField` | | ✕ |
97
+ | contentData | array | An array of objects to render along with their actions | | ✓ |
98
+ | creatableFields | object\<function> | An object with keys from the `visibleFields` array, and values of functions which take the entire row object and return a boolean indicating whether that field is fillable on create or not. | | ✕ |
99
+ | createCallback | function | A callback to be used for the built in "create" action (ie "save" on a new row). Will be prioritised ahead of a `create` entry in the deprecated actionCalls prop. | {} | ✕ |
100
+ | defaultNewObject | object | An object to use when pushing a new entry into the ActionList fields, acting as a way to bootstrap defaults into new items | {} | ✕ |
101
+ | editableFields | object\<function> | An object with keys from the `visibleFields` array, and values of functions which take the entire row object and return a boolean indicating whether that field is editable or not. No key for a given field will be interpreted as () => true, so a field is editable by default. | | ✕ |
102
+ | fieldComponents | object\<function> | An object with keys from the `visibleFields` array, and values of functions which take some `fieldProps` (`allValues`: The full form values, `index`: The current fieldIndex of the editing row, `key`: The object property in question, `name`: The field name for the Field component to glue properly into final-form, `rowFieldName`: The field name in final-form for the whole row object.), and returns a Field component to be used in "edit mode" for the visible field specified. | | ✕ |
103
+ | formatter | object\<function> | A "formatter" object that takes the same shape as an MCL formatter, and is used in the same way whilst a row is NOT being edited. While editing a given row, this formatter entry is ignored. | | ✕ |
104
+ | hideActionsColumn | boolean | A simple bool to hide the actions column. This will hide the actions column, unless the ActionList manages to get into a state of "editing/creating". In this case, the actions column will once again display to avoid soft locking the form. | false | ✕ |
105
+ | hideCreateButton | boolean | A simple bool to hide the create button. Default behaviour without create action is disabled. | false | ✕ |
106
+ | onRowClick | function | A function accepting an event and the row data, fired on row click. The presence of this prop will cause the MCL to take on the interactive styling | | ✕ |
107
+ | validateFields | object\<function> | An object with keys from the `visibleFields` array, and values of functions which take the entire row object and either return a validate function for final-form, or null. The validate function will be passed the same properties as fieldComponents, above. THESE WILL NOT BE USED if fieldComponents are defined for the same key. | | ✕ |
108
+ | visibleFields | array\<String> | An array of strings corresponding to those fields to be displayed in the rendered MultiColumnList | | ✓ |
109
+ | ...mclProps | any | Any other props supplied to ActionList will be applied to the MCL directly. *WARNING* Some MCL props may override important functionality within ActionList | | ✕ |
@@ -1,4 +1,3 @@
1
- import React from 'react';
2
1
  import PropTypes from 'prop-types';
3
2
  import { FieldArray } from 'react-final-form-arrays';
4
3
  import { Form } from 'react-final-form';
@@ -14,7 +13,8 @@ const EditableSettingsList = ({
14
13
  intlNS: passedIntlNS,
15
14
  label,
16
15
  labelOverrides = {},
17
- onSave
16
+ onSave,
17
+ render // Experimental idea, allow unique rendering per setting?
18
18
  }) => {
19
19
  return (
20
20
  <Form
@@ -38,6 +38,7 @@ const EditableSettingsList = ({
38
38
  labelOverrides={labelOverrides}
39
39
  name="settings"
40
40
  onSave={onSave}
41
+ render={render}
41
42
  />
42
43
  </form>
43
44
  )}
@@ -0,0 +1,118 @@
1
+ import { useCallback, useMemo, useState } from 'react';
2
+
3
+ import PropTypes from 'prop-types';
4
+ import { Field } from 'react-final-form';
5
+
6
+ import { SettingField } from '../SettingField';
7
+
8
+ const EditableSettingsListField = ({
9
+ allowEdit,
10
+ data,
11
+ fields,
12
+ handleSave,
13
+ index,
14
+ intlKey,
15
+ intlNS,
16
+ labelOverrides,
17
+ render,
18
+ setting
19
+ }) => {
20
+ // Handle editing or not at this level
21
+ const [editing, setEditing] = useState(false);
22
+
23
+ const settingData = useMemo(() => ({
24
+ currentSetting: fields.value[index],
25
+ ...fields,
26
+ }), [fields, index]);
27
+
28
+ const DefaultField = useCallback(() => {
29
+ return (
30
+ <Field
31
+ key={setting}
32
+ allowEdit={allowEdit}
33
+ component={SettingField}
34
+ data-testid={`editableSettingsListFieldArray[${index}]`}
35
+ editing={editing}
36
+ intlKey={intlKey}
37
+ intlNS={intlNS}
38
+ labelOverrides={labelOverrides}
39
+ name={setting}
40
+ onSave={() => handleSave(index)}
41
+ setEditing={setEditing}
42
+ settingData={settingData}
43
+ />
44
+ );
45
+ }, [allowEdit, editing, handleSave, index, intlKey, intlNS, labelOverrides, setting, settingData]);
46
+
47
+ return render({
48
+ allowEdit,
49
+ data,
50
+ DefaultField,
51
+ editing,
52
+ fields,
53
+ handleSave,
54
+ index,
55
+ intlKey,
56
+ intlNS,
57
+ setEditing,
58
+ setting,
59
+ settingData,
60
+ SettingFieldComponent: SettingField,
61
+ });
62
+ };
63
+
64
+ const EditableSettingsListFieldArray = ({
65
+ allowEdit: passedAllowEdit = true,
66
+ data: passedData,
67
+ fields: passedFields,
68
+ intlKey: passedIntlKey,
69
+ intlNS: passedIntlNS,
70
+ labelOverrides = {},
71
+ onSave,
72
+ render = ({
73
+ DefaultField,
74
+ }) => {
75
+ return (
76
+ <DefaultField />
77
+ );
78
+ }
79
+ }) => {
80
+ const handleSave = (index) => {
81
+ const setting = passedFields.value[index];
82
+ return onSave(setting);
83
+ };
84
+
85
+ return (
86
+ passedFields.map((setting, i) => {
87
+ return (
88
+ <EditableSettingsListField
89
+ allowEdit={passedAllowEdit}
90
+ data={passedData}
91
+ fields={passedFields}
92
+ handleSave={handleSave}
93
+ index={i}
94
+ intlKey={passedIntlKey}
95
+ intlNS={passedIntlNS}
96
+ labelOverrides={labelOverrides}
97
+ render={render}
98
+ setting={setting}
99
+ />
100
+ );
101
+ })
102
+ );
103
+ };
104
+
105
+ EditableSettingsListFieldArray.propTypes = {
106
+ allowEdit: PropTypes.bool,
107
+ fields: PropTypes.object,
108
+ intlKey: PropTypes.string,
109
+ intlNS: PropTypes.string,
110
+ labelOverrides: PropTypes.object,
111
+ onSave: PropTypes.func,
112
+ data: PropTypes.shape({
113
+ refdatavalues: PropTypes.arrayOf(PropTypes.object)
114
+ }),
115
+ initialValues: PropTypes.object
116
+ };
117
+
118
+ export default EditableSettingsListFieldArray;
@@ -1,13 +1,11 @@
1
- import React from 'react';
2
-
3
1
  import { TestForm } from '@folio/stripes-erm-testing';
4
2
  import { FieldArray } from 'react-final-form-arrays';
5
3
  import EditableSettingsListFieldArray from './EditableSettingsListFieldArray';
6
4
 
7
- import { renderWithKintHarness } from '../../../test/jest/helpers';
5
+ import { renderWithKintHarness } from '../../../../test/jest/helpers';
8
6
 
9
7
  const onSubmit = jest.fn();
10
- jest.mock('./SettingField', () => ({ SettingField: () => <div>SettingField</div> }));
8
+ jest.mock('../SettingField', () => ({ SettingField: () => <div>SettingField</div> }));
11
9
 
12
10
  const settings = [{
13
11
  id: 'ff8081817d94374a017d94449a660049',
@@ -61,7 +59,7 @@ describe('EditableSettingsListFieldArray', () => {
61
59
 
62
60
  it('renders empty field', () => {
63
61
  const { queryAllByTestId } = renderComponent;
64
- expect(queryAllByTestId(/editableSettingsListFieldArray\[.*\]/).length).toEqual(0);
62
+ expect(queryAllByTestId(/editableSettingsListFieldArray\[.*]/).length).toEqual(0);
65
63
  });
66
64
  });
67
65
 
@@ -0,0 +1,68 @@
1
+ # EditableSettingsListFieldArray
2
+
3
+ A component designed to render an array of settings fields, typically used within a `react-final-form` and `react-final-form-arrays` context. It iterates over an array of settings provided by `react-final-form-arrays`' `fields` object, rendering each setting using an internal `EditableSettingsListField` component. This internal component manages the display/edit state for each individual setting and uses a `SettingField` component (passed via render prop) for the actual input rendering. The component facilitates saving individual settings within the array and allows for customization of how each setting row is rendered via a `render` prop.
4
+
5
+ ## Basic Usage
6
+
7
+ This component is intended to be used as the `component` prop for `react-final-form-arrays`'s `<FieldArray>` component.
8
+
9
+ ```jsx
10
+ import { FieldArray } from 'react-final-form-arrays';
11
+
12
+ const MyForm = (props) => {
13
+ // Example save handler - should interact with your backend/state management
14
+ // It's often async and should return a Promise for react-final-form
15
+ const handleSettingSave = (setting) => {
16
+ console.log('Saving setting:', setting);
17
+ return Promise.resolve(); // Indicate success to react-final-form
18
+ };
19
+
20
+ return (
21
+ <form onSubmit={props.handleSubmit}>
22
+ {/* Other form fields */}
23
+
24
+ <FieldArray
25
+ name="yourSettingsArrayFieldName" // The name matching your form's initialValues structure
26
+ component={({ fields }) => (
27
+ <EditableSettingsListFieldArray
28
+ fields={fields}
29
+ onSave={handleSettingSave}
30
+ // Optional: Pass contextual data if SettingField needs it
31
+ // data={{ refdatavalues: [...] }}
32
+ // Optional: Customize rendering per row
33
+ // render={({ DefaultField, editing, index, setting, ...rest }) => (
34
+ // <div>
35
+ // Custom Row {index}: {editing ? 'Editing' : 'Displaying'}
36
+ // <DefaultField />
37
+ // </div>
38
+ // )}
39
+ />
40
+ )}
41
+ />
42
+
43
+ {/* Submit button etc. */}
44
+ <button type="submit" disabled={props.pristine || props.submitting}>
45
+ Submit All Changes
46
+ </button>
47
+ </form>
48
+ );
49
+ };
50
+
51
+ // Remember to wrap MyForm with reduxForm or ReactFinalForm as appropriate
52
+ ```
53
+
54
+ **Note:** This component relies heavily on the structure provided by `react-final-form` and `react-final-form-arrays`. The `fields` prop is expected to be the object passed by `<FieldArray>` to its `component`. The `onSave` handler should integrate with your application's data persistence logic and ideally return a `Promise` to manage submission state correctly with `react-final-form`. The actual rendering of the setting input depends on the `SettingField` component used internally (or overridden via the `render` prop).
55
+
56
+ ## Props
57
+
58
+ | Name | Type | Description | default | required |
59
+ |------------------|-----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------|----------|
60
+ | `allowEdit` | `boolean` | Controls whether the edit/save functionality is enabled for the settings in the list. | `true` | ✕ |
61
+ | `data` | `object` | Arbitrary data passed down through the render prop and potentially used by the underlying `SettingField`. The example `propTypes` show a shape `{ refdatavalues: PropTypes.arrayOf(PropTypes.object) }`, often used for dropdown options. | `undefined` | ✕ |
62
+ | `fields` | `object` | The `fields` object provided by `react-final-form-arrays`' `<FieldArray>` component. Contains the array values and methods (`map`, `value`, `push`, `remove`, etc.). | | ✓ |
63
+ | `intlKey` | `string` | A base key used for generating internationalization keys/labels, passed down to `SettingField`. | `undefined` | ✕ |
64
+ | `intlNS` | `string` | The internationalization namespace used for resolving labels, passed down to `SettingField`. | `undefined` | ✕ |
65
+ | `labelOverrides` | `object` | An object where keys are setting names/paths and values are custom labels, allowing override of default labels generated by `SettingField`. | `{}` | ✕ |
66
+ | `onSave` | `func` | A callback function triggered when the save action is initiated for an individual setting row. It receives the specific setting object (`fields.value[index]`) being saved as its argument. Should typically return a `Promise` for `react-final-form` integration. | | ✓ |
67
+ | `render` | `func` | A render prop function allowing customization of the rendering for *each* setting row. It receives an object containing: `allowEdit`, `data`, `DefaultField` (a pre-configured component rendering the standard `SettingField`), `editing` (boolean state of the row), `fields` (the top-level fields object), `handleSave` (the save handler for the specific row), `index`, `intlKey`, `intlNS`, `setEditing` (function to toggle edit state), `setting` (the field name/identifier for the current row), `settingData` (memoized object with `currentSetting` and `fields`), and `SettingFieldComponent` (reference to the `SettingField` component itself). | Renders `<DefaultField />` | ✕ |
68
+ | `initialValues` | `object` | The initial values object for the entire form. Passed down but not directly used by `EditableSettingsListFieldArray` itself; may be needed by the underlying `SettingField`. | `undefined` | ✕ |
@@ -0,0 +1 @@
1
+ export { default } from './EditableSettingsListFieldArray';
@@ -0,0 +1,74 @@
1
+ # EditableSettingsList
2
+
3
+ A wrapper component that sets up a `react-final-form` Form instance specifically configured for managing a list of settings. It utilizes `react-final-form-arrays`'s `<FieldArray>` component, rendering the list using the `EditableSettingsListFieldArray` component.
4
+
5
+ This component simplifies rendering an editable settings list by encapsulating the necessary `react-final-form` setup, including array mutators and form configuration. It expects initial values under a specific structure and passes relevant props down to `EditableSettingsListFieldArray` for rendering and handling individual setting saves.
6
+
7
+ ## Basic Usage
8
+
9
+ Import the component and provide it with initial values (structured correctly) and a save handler.
10
+
11
+ ```jsx
12
+ const MyAppSettingsWrapper = () => {
13
+ // Initial settings data must be under the 'settings' key
14
+ const settingsInitialData = {
15
+ settings: [
16
+ { key: 'siteUrl', settingType: 'Refdata' },
17
+ { key: 'adminPass', settingType: 'Password' },
18
+ { key: 'featureFlagX', value: 'This is a string value', settingType: 'String' },
19
+ // ... other settings with potentially different structures/types
20
+ // handled by the underlying SettingField component
21
+ ]
22
+ };
23
+
24
+ // This handler receives the individual setting object when saving a single row.
25
+ // It's also technically wired to the form's onSubmit, though the component
26
+ // doesn't provide an explicit form submit button.
27
+ const handleSave = (settingData) => {
28
+ console.log('Saving setting:', settingData);
29
+ // Implement logic to persist the changed setting (e.g., API call)
30
+ // It's recommended to return a Promise for react-final-form integration.
31
+ // Example: return updateSettingApi(settingData);
32
+ return Promise.resolve();
33
+ };
34
+
35
+ // Example: Check user permissions
36
+ const userCanEditSettings = true;
37
+
38
+ return (
39
+ <div>
40
+ <h2>Application Settings</h2>
41
+ <EditableSettingsList
42
+ allowEdit={userCanEditSettings}
43
+ initialValues={settingsInitialData}
44
+ intlKey="appSettings" // Optional: for label generation
45
+ intlNS="settings" // Optional: for label generation
46
+ onSave={handleSave}
47
+ // Optional: Pass contextual data if needed by SettingField
48
+ // data={{ refdatavalues: [...] }}
49
+ // Optional: Override specific labels
50
+ // labelOverrides={{ adminEmail: 'Administrator Email Address' }}
51
+ />
52
+ </div>
53
+ );
54
+ };
55
+ ```
56
+
57
+ **Note:**
58
+ * This component depends on `react-final-form`, `react-final-form-arrays`, `final-form-arrays`, and the `EditableSettingsListFieldArray` component.
59
+ * The `initialValues` prop **must** be an object containing a key named `settings`, and the value of `settings` must be the array of setting objects you want to manage.
60
+ * The `onSave` function provided serves primarily as the callback for *individual* setting saves triggered within `EditableSettingsListFieldArray`. It receives the specific setting object being saved in that context.
61
+
62
+ ## Props
63
+
64
+ | Name | Type | Description | default | required |
65
+ |------------------|--------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------|----------|
66
+ | `allowEdit` | `boolean` | A global flag passed down to control whether editing is enabled for all settings in the list. | `true` | ✕ |
67
+ | `data` | `object` | Arbitrary data to be passed down through `EditableSettingsListFieldArray` to the underlying `SettingField` component(s). Often used for context like reference data values (e.g., `{ refdatavalues: [...] }`). | `undefined` | ✕ |
68
+ | `initialValues` | `object` | An object containing the initial values for the form. It **must** include a key named `settings` whose value is the array of setting objects. | `undefined` | ✓ |
69
+ | `intlKey` | `string` | A base key passed down for generating internationalization keys/labels within `EditableSettingsListFieldArray` and `SettingField`. | `undefined` | ✕ |
70
+ | `intlNS` | `string` | An internationalization namespace passed down for resolving labels within `EditableSettingsListFieldArray` and `SettingField`. | `undefined` | ✕ |
71
+ | `label` | `string` \| `node` \| `object` | A label for the entire settings list/section. Passed to `<FieldArray>`, but its rendering depends on downstream components/customization. | `undefined` | ✕ |
72
+ | `labelOverrides` | `object` | An object passed down to `EditableSettingsListFieldArray` to allow overriding default labels for specific settings. Keys should match setting identifiers (e.g., `setting.key`), values are the custom labels. | `{}` | ✕ |
73
+ | `onSave` | `func` | Callback function triggered primarily when an *individual* setting's save action is invoked within `EditableSettingsListFieldArray`. Receives the setting object being saved. Also connected to the internal `<Form>`'s `onSubmit`. Should handle persistence and ideally return a `Promise`. | `undefined` | ✓ |
74
+ | `render` | `func` | A render prop passed down to `EditableSettingsListFieldArray` to allow full customization of how *each* setting row is rendered. See `EditableSettingsListFieldArray` documentation for details. | `undefined` | ✕ |
@@ -6,8 +6,8 @@ import {
6
6
  Select,
7
7
  TextField,
8
8
  } from '@folio/stripes/components';
9
- import RefdataButtons from '../../RefdataButtons';
10
- import { useKintIntl } from '../../hooks';
9
+ import RefdataButtons from '../../../RefdataButtons';
10
+ import { useKintIntl } from '../../../hooks';
11
11
 
12
12
  const EditSettingValue = (props) => {
13
13
  const {
@@ -1,14 +1,11 @@
1
- import React from 'react';
2
-
3
-
4
1
  import { TestForm } from '@folio/stripes-erm-testing';
5
2
 
6
3
  import EditSettingValue from './EditSettingValue';
7
4
 
8
- import { renderWithKintHarness } from '../../../../test/jest/helpers';
5
+ import { renderWithKintHarness } from '../../../../../test/jest/helpers';
9
6
 
10
7
  const onSubmit = jest.fn();
11
- jest.mock('../../hooks');
8
+ jest.mock('../../../hooks');
12
9
 
13
10
  const stringSetting = {
14
11
  id: '12345',