@k-int/stripes-kint-components 4.6.0 → 4.7.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 +7 -0
- package/es/index.js +9 -1
- package/es/lib/ActionList/ActionListFieldArray.js +4 -2
- package/es/lib/ComboButton/ComboButton.js +138 -0
- package/es/lib/ComboButton/index.js +13 -0
- package/es/lib/SettingsFormContainer/SettingsFormContainer.js +26 -1
- package/package.json +2 -2
- package/src/index.js +2 -0
- package/src/lib/ActionList/ActionListFieldArray.js +3 -2
- package/src/lib/ComboButton/ComboButton.js +161 -0
- package/src/lib/ComboButton/index.js +1 -0
- package/src/lib/SettingsFormContainer/SettingsFormContainer.js +26 -2
- package/styles/ResponsiveButtonGroup.css +6 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## 4.7.0 2023-06-06
|
|
2
|
+
* Added success callout to SettingsFormContainer
|
|
3
|
+
* Bumped @rehooks/local-storage dep to ^2.4.4
|
|
4
|
+
* Added indexing to ActionList parent div for uniqueness for screen readers
|
|
5
|
+
* Added aria-label to default Fields within ActionList
|
|
6
|
+
* ComboButton - new component for buttonm with one primary and multiple ancillary actions.
|
|
7
|
+
|
|
1
8
|
## 4.6.0 2023-04-14
|
|
2
9
|
* ERM-2884 Regex with lookbehind causes render failure in Safari
|
|
3
10
|
* Deprecated customPropertyContants typo. For now accessible both at customPropertyContants and customPropertyConstants, will be removed in future version.
|
package/es/index.js
CHANGED
|
@@ -47,7 +47,8 @@ var _exportNames = {
|
|
|
47
47
|
useSelectedOption: true,
|
|
48
48
|
FormattedKintMessage: true,
|
|
49
49
|
ResponsiveButtonGroup: true,
|
|
50
|
-
SettingsFormContainer: true
|
|
50
|
+
SettingsFormContainer: true,
|
|
51
|
+
ComboButton: true
|
|
51
52
|
};
|
|
52
53
|
Object.defineProperty(exports, "ActionList", {
|
|
53
54
|
enumerable: true,
|
|
@@ -55,6 +56,12 @@ Object.defineProperty(exports, "ActionList", {
|
|
|
55
56
|
return _ActionList.default;
|
|
56
57
|
}
|
|
57
58
|
});
|
|
59
|
+
Object.defineProperty(exports, "ComboButton", {
|
|
60
|
+
enumerable: true,
|
|
61
|
+
get: function () {
|
|
62
|
+
return _ComboButton.default;
|
|
63
|
+
}
|
|
64
|
+
});
|
|
58
65
|
Object.defineProperty(exports, "CustomPropertiesEdit", {
|
|
59
66
|
enumerable: true,
|
|
60
67
|
get: function () {
|
|
@@ -371,6 +378,7 @@ var _RichSelect = _interopRequireWildcard(require("./lib/RichSelect"));
|
|
|
371
378
|
var _FormattedKintMessage = _interopRequireDefault(require("./lib/FormattedKintMessage"));
|
|
372
379
|
var _ResponsiveButtonGroup = _interopRequireDefault(require("./lib/ResponsiveButtonGroup"));
|
|
373
380
|
var _SettingsFormContainer = _interopRequireDefault(require("./lib/SettingsFormContainer"));
|
|
381
|
+
var _ComboButton = _interopRequireDefault(require("./lib/ComboButton"));
|
|
374
382
|
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
375
383
|
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
376
384
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
@@ -173,7 +173,7 @@ const ActionListFieldArray = /*#__PURE__*/(0, _react.forwardRef)((_ref2, ref) =>
|
|
|
173
173
|
if (data.id === editing || !data.id && editing === 'NEW_ROW') {
|
|
174
174
|
// Render the save/cancel buttons
|
|
175
175
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
176
|
-
id: "action-button-parent",
|
|
176
|
+
id: "action-button-parent-".concat(data.rowIndex + 1),
|
|
177
177
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Button, {
|
|
178
178
|
buttonStyle: "primary",
|
|
179
179
|
disabled: hasValidationErrors || submitting || pristine,
|
|
@@ -215,7 +215,7 @@ const ActionListFieldArray = /*#__PURE__*/(0, _react.forwardRef)((_ref2, ref) =>
|
|
|
215
215
|
});
|
|
216
216
|
}
|
|
217
217
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
218
|
-
id: "action-button-parent",
|
|
218
|
+
id: "action-button-parent-".concat(data.rowIndex + 1),
|
|
219
219
|
children: actions === null || actions === void 0 ? void 0 : actions.map(action => {
|
|
220
220
|
let actionFunction;
|
|
221
221
|
if (action.callback) {
|
|
@@ -356,6 +356,8 @@ const ActionListFieldArray = /*#__PURE__*/(0, _react.forwardRef)((_ref2, ref) =>
|
|
|
356
356
|
};
|
|
357
357
|
const validateFunction = validateFields !== null && validateFields !== void 0 && validateFields[key] ? validateFields === null || validateFields === void 0 ? void 0 : validateFields[key](passedObject) : null;
|
|
358
358
|
returnValue = fieldComponents[key] ? fieldComponents[key](passedObject) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactFinalForm.Field, {
|
|
359
|
+
ariaLabel: key // TODO at the moment the only way to override this is passing in an entire fieldComponent.
|
|
360
|
+
,
|
|
359
361
|
autoFocus: autoFocus,
|
|
360
362
|
component: _components.TextField,
|
|
361
363
|
marginBottom0: true,
|
|
@@ -0,0 +1,138 @@
|
|
|
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 _classnames = _interopRequireDefault(require("classnames"));
|
|
10
|
+
var _components = require("@folio/stripes/components");
|
|
11
|
+
var _ResponsiveButtonGroup = _interopRequireDefault(require("../../../styles/ResponsiveButtonGroup.css"));
|
|
12
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
13
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
14
|
+
// FIXME we should probably store the shared styles in a more aptly named file
|
|
15
|
+
|
|
16
|
+
/*
|
|
17
|
+
* ComboButton component, can either act as Primary/Bonus buttons in a dropdown
|
|
18
|
+
* OR it can act as a popover rendered besides a button.
|
|
19
|
+
* If neither are provided it will act as an ordinary button
|
|
20
|
+
*/const ComboButton = _ref => {
|
|
21
|
+
let {
|
|
22
|
+
children,
|
|
23
|
+
dropdownButtons = [],
|
|
24
|
+
// These MUST be buttons
|
|
25
|
+
dropdownProps = {},
|
|
26
|
+
dropdownRender,
|
|
27
|
+
marginBottom0,
|
|
28
|
+
// Will ONLY control the margin of the dropdown/main button
|
|
29
|
+
popoverProps = {},
|
|
30
|
+
triggerProps,
|
|
31
|
+
...buttonProps
|
|
32
|
+
} = _ref;
|
|
33
|
+
const [open, setOpen] = (0, _react.useState)(false);
|
|
34
|
+
const onToggle = (0, _react.useCallback)(() => setOpen(!open), [open, setOpen]);
|
|
35
|
+
|
|
36
|
+
// FIXME a lot of this is shared with ResponsiveButtonGroup
|
|
37
|
+
const styledDropdownButtons = (0, _react.useMemo)(() => dropdownButtons === null || dropdownButtons === void 0 ? void 0 : dropdownButtons.map(button => {
|
|
38
|
+
return /*#__PURE__*/(0, _react.cloneElement)(button, {
|
|
39
|
+
buttonStyle: 'dropdownItem'
|
|
40
|
+
});
|
|
41
|
+
}), [dropdownButtons]);
|
|
42
|
+
|
|
43
|
+
// eslint-disable-next-line react/prop-types
|
|
44
|
+
const renderActionMenuContent = (0, _react.useCallback)(() => /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.DropdownMenu, {
|
|
45
|
+
children: [...styledDropdownButtons]
|
|
46
|
+
}), [styledDropdownButtons]);
|
|
47
|
+
const renderTrigger = (0, _react.useCallback)(_ref2 => {
|
|
48
|
+
var _buttonProps$buttonSt;
|
|
49
|
+
let {
|
|
50
|
+
onToggle: toggleFunc,
|
|
51
|
+
triggerRef,
|
|
52
|
+
keyHandler,
|
|
53
|
+
open: openState,
|
|
54
|
+
ariaProps,
|
|
55
|
+
getTriggerProps
|
|
56
|
+
} = _ref2;
|
|
57
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Button, {
|
|
58
|
+
ref: triggerRef,
|
|
59
|
+
"aria-label": "menu",
|
|
60
|
+
buttonClass: (0, _classnames.default)(_ResponsiveButtonGroup.default.width100, _ResponsiveButtonGroup.default.dropdownButtonClass, {
|
|
61
|
+
["".concat(_ResponsiveButtonGroup.default.marginBottom)]: !marginBottom0
|
|
62
|
+
}, {
|
|
63
|
+
["".concat(_ResponsiveButtonGroup.default.marginBottom0)]: marginBottom0
|
|
64
|
+
}),
|
|
65
|
+
buttonStyle: (_buttonProps$buttonSt = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.buttonStyle) !== null && _buttonProps$buttonSt !== void 0 ? _buttonProps$buttonSt : 'default',
|
|
66
|
+
onClick: toggleFunc,
|
|
67
|
+
onKeyDown: keyHandler,
|
|
68
|
+
type: "button",
|
|
69
|
+
...getTriggerProps(),
|
|
70
|
+
...ariaProps,
|
|
71
|
+
...triggerProps,
|
|
72
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Icon, {
|
|
73
|
+
icon: openState ? 'triangle-up' : 'triangle-down',
|
|
74
|
+
iconPosition: "end"
|
|
75
|
+
})
|
|
76
|
+
});
|
|
77
|
+
}, [buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.buttonStyle, triggerProps, marginBottom0]);
|
|
78
|
+
let comboTrigger;
|
|
79
|
+
if (dropdownButtons.length > 0) {
|
|
80
|
+
comboTrigger = /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Dropdown, {
|
|
81
|
+
className: _ResponsiveButtonGroup.default.dropdownClass,
|
|
82
|
+
onToggle: onToggle,
|
|
83
|
+
open: open,
|
|
84
|
+
renderMenu: renderActionMenuContent,
|
|
85
|
+
renderTrigger: renderTriggerProps => renderTrigger(renderTriggerProps),
|
|
86
|
+
...dropdownProps
|
|
87
|
+
}, "combobutton-dropdown-toggle");
|
|
88
|
+
} else if (dropdownRender) {
|
|
89
|
+
comboTrigger = /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Popover, {
|
|
90
|
+
onToggle: onToggle,
|
|
91
|
+
open: open,
|
|
92
|
+
renderTrigger: _ref3 => {
|
|
93
|
+
let {
|
|
94
|
+
open: openState,
|
|
95
|
+
ref,
|
|
96
|
+
toggle
|
|
97
|
+
} = _ref3;
|
|
98
|
+
return renderTrigger({
|
|
99
|
+
getTriggerProps: () => {},
|
|
100
|
+
onToggle: toggle,
|
|
101
|
+
open: openState,
|
|
102
|
+
triggerRef: ref
|
|
103
|
+
});
|
|
104
|
+
},
|
|
105
|
+
...popoverProps,
|
|
106
|
+
children: dropdownRender
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
if (comboTrigger) {
|
|
110
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
111
|
+
className: (0, _classnames.default)(_ResponsiveButtonGroup.default.buttonGroup),
|
|
112
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Button, {
|
|
113
|
+
marginBottom0: marginBottom0,
|
|
114
|
+
...buttonProps,
|
|
115
|
+
children: children
|
|
116
|
+
}), comboTrigger]
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Fallback, acts as a normal button
|
|
121
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Button, {
|
|
122
|
+
marginBottom0: marginBottom0,
|
|
123
|
+
...buttonProps,
|
|
124
|
+
children: children
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
ComboButton.propTypes = {
|
|
128
|
+
children: _propTypes.default.node,
|
|
129
|
+
dropdownButtons: _propTypes.default.arrayOf(_propTypes.default.node),
|
|
130
|
+
dropdownProps: _propTypes.default.object,
|
|
131
|
+
dropdownRender: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.node]),
|
|
132
|
+
id: _propTypes.default.string,
|
|
133
|
+
marginBottom0: _propTypes.default.bool,
|
|
134
|
+
popoverProps: _propTypes.default.object,
|
|
135
|
+
triggerProps: _propTypes.default.object
|
|
136
|
+
};
|
|
137
|
+
var _default = ComboButton;
|
|
138
|
+
exports.default = _default;
|
|
@@ -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 _ComboButton.default;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
var _ComboButton = _interopRequireDefault(require("./ComboButton"));
|
|
13
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
8
|
+
var _core = require("@folio/stripes/core");
|
|
8
9
|
var _hooks = require("../hooks");
|
|
9
10
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
10
11
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
@@ -15,11 +16,17 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
15
16
|
ConfigFormComponent,
|
|
16
17
|
configName,
|
|
17
18
|
getInitialValues: passedGetInitialValues,
|
|
19
|
+
intlKey: passedIntlKey,
|
|
20
|
+
intlNS: passedIntlNS,
|
|
21
|
+
labelOverrides = {},
|
|
18
22
|
moduleName,
|
|
19
23
|
scope,
|
|
20
24
|
// We don't use this currently but it's here for future reference
|
|
21
25
|
...rest
|
|
22
26
|
} = _ref;
|
|
27
|
+
const callout = (0, _core.useCallout)();
|
|
28
|
+
const kintIntl = (0, _hooks.useKintIntl)(passedIntlKey, passedIntlNS);
|
|
29
|
+
|
|
23
30
|
/*
|
|
24
31
|
* It is important to pass a namespaceAppend because the same hook could be rendered
|
|
25
32
|
* on the main App component. This means that in settings
|
|
@@ -56,8 +63,23 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
56
63
|
key: configName
|
|
57
64
|
})
|
|
58
65
|
};
|
|
59
|
-
editSettings(setting)
|
|
66
|
+
editSettings(setting).then(() => {
|
|
67
|
+
callout.sendCallout({
|
|
68
|
+
message: kintIntl.formatKintMessage({
|
|
69
|
+
fallbackMessage: 'stripes-smart-components.cm.success',
|
|
70
|
+
id: 'settingSaveSuccess',
|
|
71
|
+
intlKey: passedIntlKey,
|
|
72
|
+
intlNS: passedIntlNS,
|
|
73
|
+
overrideValue: labelOverrides === null || labelOverrides === void 0 ? void 0 : labelOverrides.settingSaveSuccess
|
|
74
|
+
}),
|
|
75
|
+
type: 'success'
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// At some point we might want to add a catch callout.
|
|
80
|
+
// The current ConfigManager doesn't have one, so leaving for now
|
|
60
81
|
};
|
|
82
|
+
|
|
61
83
|
const getInitialValues = () => {
|
|
62
84
|
let initialValues = parsedSettings;
|
|
63
85
|
if (passedGetInitialValues) {
|
|
@@ -80,6 +102,9 @@ SettingsFormContainer.propTypes = {
|
|
|
80
102
|
ConfigFormComponent: _propTypes.default.oneOfType([_propTypes.default.arrayOf(_propTypes.default.node), _propTypes.default.node, _propTypes.default.func]),
|
|
81
103
|
configName: _propTypes.default.string.isRequired,
|
|
82
104
|
getInitialValues: _propTypes.default.func,
|
|
105
|
+
intlKey: _propTypes.default.string,
|
|
106
|
+
intlNS: _propTypes.default.string,
|
|
107
|
+
labelOverrides: _propTypes.default.object,
|
|
83
108
|
moduleName: _propTypes.default.string.isRequired,
|
|
84
109
|
scope: _propTypes.default.string
|
|
85
110
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@k-int/stripes-kint-components",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.7.0",
|
|
4
4
|
"description": "Stripes Component library for K-Int specific applications",
|
|
5
5
|
"sideEffects": [
|
|
6
6
|
"*.css"
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"prepare": "yarn build"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@rehooks/local-storage": "2.4.
|
|
23
|
+
"@rehooks/local-storage": "^2.4.4",
|
|
24
24
|
"compose-function": "^3.0.3",
|
|
25
25
|
"react-resize-detector": "^7.1.2",
|
|
26
26
|
"zustand": "^4.0.0"
|
package/src/index.js
CHANGED
|
@@ -107,3 +107,5 @@ export { default as FormattedKintMessage } from './lib/FormattedKintMessage';
|
|
|
107
107
|
export { default as ResponsiveButtonGroup } from './lib/ResponsiveButtonGroup';
|
|
108
108
|
|
|
109
109
|
export { default as SettingsFormContainer } from './lib/SettingsFormContainer';
|
|
110
|
+
|
|
111
|
+
export { default as ComboButton } from './lib/ComboButton';
|
|
@@ -176,7 +176,7 @@ const ActionListFieldArray = forwardRef(({
|
|
|
176
176
|
if (data.id === editing || (!data.id && editing === 'NEW_ROW')) {
|
|
177
177
|
// Render the save/cancel buttons
|
|
178
178
|
return (
|
|
179
|
-
<div id=
|
|
179
|
+
<div id={`action-button-parent-${data.rowIndex + 1}`}>
|
|
180
180
|
<Button
|
|
181
181
|
key={`save[${data.rowIndex}]`}
|
|
182
182
|
buttonStyle="primary"
|
|
@@ -225,7 +225,7 @@ const ActionListFieldArray = forwardRef(({
|
|
|
225
225
|
}
|
|
226
226
|
|
|
227
227
|
return (
|
|
228
|
-
<div id=
|
|
228
|
+
<div id={`action-button-parent-${data.rowIndex + 1}`}>
|
|
229
229
|
{actions?.map(action => {
|
|
230
230
|
let actionFunction;
|
|
231
231
|
if (action.callback) {
|
|
@@ -379,6 +379,7 @@ const ActionListFieldArray = forwardRef(({
|
|
|
379
379
|
fieldComponents[key] ?
|
|
380
380
|
fieldComponents[key](passedObject) :
|
|
381
381
|
<Field
|
|
382
|
+
ariaLabel={key} // TODO at the moment the only way to override this is passing in an entire fieldComponent.
|
|
382
383
|
autoFocus={autoFocus}
|
|
383
384
|
component={TextField}
|
|
384
385
|
marginBottom0
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { cloneElement, useCallback, useMemo, useState } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
|
|
4
|
+
import classnames from 'classnames';
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
Button,
|
|
8
|
+
Dropdown,
|
|
9
|
+
DropdownMenu,
|
|
10
|
+
Icon,
|
|
11
|
+
Popover
|
|
12
|
+
} from '@folio/stripes/components';
|
|
13
|
+
|
|
14
|
+
// FIXME we should probably store the shared styles in a more aptly named file
|
|
15
|
+
import css from '../../../styles/ResponsiveButtonGroup.css';
|
|
16
|
+
|
|
17
|
+
/*
|
|
18
|
+
* ComboButton component, can either act as Primary/Bonus buttons in a dropdown
|
|
19
|
+
* OR it can act as a popover rendered besides a button.
|
|
20
|
+
* If neither are provided it will act as an ordinary button
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
const ComboButton = ({
|
|
24
|
+
children,
|
|
25
|
+
dropdownButtons = [], // These MUST be buttons
|
|
26
|
+
dropdownProps = {},
|
|
27
|
+
dropdownRender,
|
|
28
|
+
marginBottom0, // Will ONLY control the margin of the dropdown/main button
|
|
29
|
+
popoverProps = {},
|
|
30
|
+
triggerProps,
|
|
31
|
+
...buttonProps
|
|
32
|
+
}) => {
|
|
33
|
+
const [open, setOpen] = useState(false);
|
|
34
|
+
const onToggle = useCallback(() => setOpen(!open), [open, setOpen]);
|
|
35
|
+
|
|
36
|
+
// FIXME a lot of this is shared with ResponsiveButtonGroup
|
|
37
|
+
const styledDropdownButtons = useMemo(() => (
|
|
38
|
+
dropdownButtons
|
|
39
|
+
?.map(button => {
|
|
40
|
+
return cloneElement(button, { buttonStyle: 'dropdownItem' });
|
|
41
|
+
})
|
|
42
|
+
), [dropdownButtons]);
|
|
43
|
+
|
|
44
|
+
// eslint-disable-next-line react/prop-types
|
|
45
|
+
const renderActionMenuContent = useCallback(() => (
|
|
46
|
+
<DropdownMenu>
|
|
47
|
+
{[...styledDropdownButtons]}
|
|
48
|
+
</DropdownMenu>
|
|
49
|
+
), [styledDropdownButtons]);
|
|
50
|
+
|
|
51
|
+
const renderTrigger = useCallback(({
|
|
52
|
+
onToggle: toggleFunc,
|
|
53
|
+
triggerRef,
|
|
54
|
+
keyHandler,
|
|
55
|
+
open: openState,
|
|
56
|
+
ariaProps,
|
|
57
|
+
getTriggerProps
|
|
58
|
+
}) => (
|
|
59
|
+
<Button
|
|
60
|
+
ref={triggerRef}
|
|
61
|
+
aria-label="menu"
|
|
62
|
+
buttonClass={
|
|
63
|
+
classnames(
|
|
64
|
+
css.width100,
|
|
65
|
+
css.dropdownButtonClass,
|
|
66
|
+
{ [`${css.marginBottom}`]: !marginBottom0 },
|
|
67
|
+
{ [`${css.marginBottom0}`]: marginBottom0 }
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
buttonStyle={buttonProps?.buttonStyle ?? 'default'}
|
|
71
|
+
onClick={toggleFunc}
|
|
72
|
+
onKeyDown={keyHandler}
|
|
73
|
+
type="button"
|
|
74
|
+
{...getTriggerProps()}
|
|
75
|
+
{...ariaProps}
|
|
76
|
+
{...triggerProps}
|
|
77
|
+
>
|
|
78
|
+
<Icon icon={openState ? 'triangle-up' : 'triangle-down'} iconPosition="end" />
|
|
79
|
+
</Button>
|
|
80
|
+
), [
|
|
81
|
+
buttonProps?.buttonStyle,
|
|
82
|
+
triggerProps,
|
|
83
|
+
marginBottom0
|
|
84
|
+
]);
|
|
85
|
+
|
|
86
|
+
let comboTrigger;
|
|
87
|
+
if (dropdownButtons.length > 0) {
|
|
88
|
+
comboTrigger = <Dropdown
|
|
89
|
+
key="combobutton-dropdown-toggle"
|
|
90
|
+
className={css.dropdownClass}
|
|
91
|
+
onToggle={onToggle}
|
|
92
|
+
open={open}
|
|
93
|
+
renderMenu={renderActionMenuContent}
|
|
94
|
+
renderTrigger={(renderTriggerProps) => renderTrigger(renderTriggerProps)}
|
|
95
|
+
{...dropdownProps}
|
|
96
|
+
/>;
|
|
97
|
+
} else if (dropdownRender) {
|
|
98
|
+
comboTrigger = (
|
|
99
|
+
<Popover
|
|
100
|
+
onToggle={onToggle}
|
|
101
|
+
open={open}
|
|
102
|
+
renderTrigger={({ open: openState, ref, toggle }) => renderTrigger({
|
|
103
|
+
getTriggerProps: () => {},
|
|
104
|
+
onToggle: toggle,
|
|
105
|
+
open: openState,
|
|
106
|
+
triggerRef: ref
|
|
107
|
+
})}
|
|
108
|
+
{...popoverProps}
|
|
109
|
+
>
|
|
110
|
+
{dropdownRender}
|
|
111
|
+
</Popover>
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (comboTrigger) {
|
|
116
|
+
return (
|
|
117
|
+
<div
|
|
118
|
+
className={
|
|
119
|
+
classnames(
|
|
120
|
+
css.buttonGroup,
|
|
121
|
+
)
|
|
122
|
+
}
|
|
123
|
+
>
|
|
124
|
+
<Button
|
|
125
|
+
marginBottom0={marginBottom0}
|
|
126
|
+
{...buttonProps}
|
|
127
|
+
>
|
|
128
|
+
{children}
|
|
129
|
+
</Button>
|
|
130
|
+
{comboTrigger}
|
|
131
|
+
</div>
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
// Fallback, acts as a normal button
|
|
137
|
+
return (
|
|
138
|
+
<Button
|
|
139
|
+
marginBottom0={marginBottom0}
|
|
140
|
+
{...buttonProps}
|
|
141
|
+
>
|
|
142
|
+
{children}
|
|
143
|
+
</Button>
|
|
144
|
+
);
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
ComboButton.propTypes = {
|
|
148
|
+
children: PropTypes.node,
|
|
149
|
+
dropdownButtons: PropTypes.arrayOf(PropTypes.node),
|
|
150
|
+
dropdownProps: PropTypes.object,
|
|
151
|
+
dropdownRender: PropTypes.oneOfType([
|
|
152
|
+
PropTypes.func,
|
|
153
|
+
PropTypes.node
|
|
154
|
+
]),
|
|
155
|
+
id: PropTypes.string,
|
|
156
|
+
marginBottom0: PropTypes.bool,
|
|
157
|
+
popoverProps: PropTypes.object,
|
|
158
|
+
triggerProps: PropTypes.object,
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
export default ComboButton;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './ComboButton';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import PropTypes from 'prop-types';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { useCallout } from '@folio/stripes/core';
|
|
4
|
+
import { useKintIntl, useModConfigEntries, useMutateModConfigEntry } from '../hooks';
|
|
4
5
|
|
|
5
6
|
/*
|
|
6
7
|
* API is similar to ConfigManager
|
|
@@ -9,10 +10,16 @@ const SettingsFormContainer = ({
|
|
|
9
10
|
ConfigFormComponent,
|
|
10
11
|
configName,
|
|
11
12
|
getInitialValues: passedGetInitialValues,
|
|
13
|
+
intlKey: passedIntlKey,
|
|
14
|
+
intlNS: passedIntlNS,
|
|
15
|
+
labelOverrides = {},
|
|
12
16
|
moduleName,
|
|
13
17
|
scope, // We don't use this currently but it's here for future reference
|
|
14
18
|
...rest
|
|
15
19
|
}) => {
|
|
20
|
+
const callout = useCallout();
|
|
21
|
+
const kintIntl = useKintIntl(passedIntlKey, passedIntlNS);
|
|
22
|
+
|
|
16
23
|
/*
|
|
17
24
|
* It is important to pass a namespaceAppend because the same hook could be rendered
|
|
18
25
|
* on the main App component. This means that in settings
|
|
@@ -46,7 +53,21 @@ const SettingsFormContainer = ({
|
|
|
46
53
|
{ scope, key: configName })
|
|
47
54
|
};
|
|
48
55
|
|
|
49
|
-
editSettings(setting)
|
|
56
|
+
editSettings(setting).then(() => {
|
|
57
|
+
callout.sendCallout({
|
|
58
|
+
message: kintIntl.formatKintMessage({
|
|
59
|
+
fallbackMessage: 'stripes-smart-components.cm.success',
|
|
60
|
+
id: 'settingSaveSuccess',
|
|
61
|
+
intlKey: passedIntlKey,
|
|
62
|
+
intlNS: passedIntlNS,
|
|
63
|
+
overrideValue: labelOverrides?.settingSaveSuccess
|
|
64
|
+
}),
|
|
65
|
+
type: 'success',
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// At some point we might want to add a catch callout.
|
|
70
|
+
// The current ConfigManager doesn't have one, so leaving for now
|
|
50
71
|
};
|
|
51
72
|
|
|
52
73
|
const getInitialValues = () => {
|
|
@@ -77,6 +98,9 @@ SettingsFormContainer.propTypes = {
|
|
|
77
98
|
]),
|
|
78
99
|
configName: PropTypes.string.isRequired,
|
|
79
100
|
getInitialValues: PropTypes.func,
|
|
101
|
+
intlKey: PropTypes.string,
|
|
102
|
+
intlNS: PropTypes.string,
|
|
103
|
+
labelOverrides: PropTypes.object,
|
|
80
104
|
moduleName: PropTypes.string.isRequired,
|
|
81
105
|
scope: PropTypes.string,
|
|
82
106
|
};
|
|
@@ -40,9 +40,11 @@
|
|
|
40
40
|
margin-left: -1px;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
& > :not(:
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
& > :not(button:last-of-type) {
|
|
44
|
+
& > :not(:first-child):not(:last-child),
|
|
45
|
+
& > :not(:first-child):not(:last-child)::before {
|
|
46
|
+
border-radius: 0;
|
|
47
|
+
}
|
|
46
48
|
}
|
|
47
49
|
}
|
|
48
50
|
|
|
@@ -75,12 +77,7 @@
|
|
|
75
77
|
padding: 0 !important; /* As always, this sucks but is forced on us by stripes bad css ordering */
|
|
76
78
|
}
|
|
77
79
|
|
|
78
|
-
.dropdownButtonClass {
|
|
79
|
-
border-top-left-radius: 0;
|
|
80
|
-
border-bottom-left-radius: 0;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
.dropdownButtonClass::before {
|
|
80
|
+
.dropdownButtonClass, .dropdownButtonClass::before {
|
|
84
81
|
border-top-left-radius: 0;
|
|
85
82
|
border-bottom-left-radius: 0;
|
|
86
83
|
}
|