@k-int/stripes-kint-components 5.9.0 → 5.11.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 +14 -0
- package/es/index.js +12 -0
- package/es/lib/Tags/Tags.js +143 -0
- package/es/lib/Tags/Tags.test.js +80 -0
- package/es/lib/Tags/hooks/index.js +28 -0
- package/es/lib/Tags/hooks/useTags.js +15 -0
- package/es/lib/Tags/hooks/useTagsEnabled.js +25 -0
- package/es/lib/Tags/index.js +40 -0
- package/es/lib/Tags/tagsConfig.js +10 -0
- package/es/lib/Typedown/Typedown.js +12 -2
- package/es/lib/hooks/typedownHooks/useTypedown.js +15 -2
- package/es/lib/hooks/useHelperApp.js +18 -15
- package/package.json +3 -2
- package/src/index.js +2 -0
- package/src/lib/FormModal/README.md +91 -0
- package/src/lib/Tags/Tags.js +145 -0
- package/src/lib/Tags/Tags.test.js +77 -0
- package/src/lib/Tags/hooks/index.js +2 -0
- package/src/lib/Tags/hooks/useTags.js +16 -0
- package/src/lib/Tags/hooks/useTagsEnabled.js +19 -0
- package/src/lib/Tags/index.js +4 -0
- package/src/lib/Tags/tagsConfig.js +16 -0
- package/src/lib/Typedown/README.md +21 -19
- package/src/lib/Typedown/Typedown.js +16 -3
- package/src/lib/hooks/typedownHooks/useTypedown.js +17 -3
- package/src/lib/hooks/useHelperApp.js +21 -13
- package/src/lib/utils/README.md +126 -56
- package/test/helpers/test-implementor-translations.json +4 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# [5.11.0](https://gitlab.com/knowledge-integration/folio/stripes-kint-components/compare/v5.10.0...v5.11.0) (2025-02-07)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* Added Tags helper app and hooks to stripes-kint-components (Moving out of erm-components longer term) ([e881639](https://gitlab.com/knowledge-integration/folio/stripes-kint-components/commit/e881639b49036d6016dc65d83bcf67e596652acc))
|
|
7
|
+
|
|
8
|
+
# [5.10.0](https://gitlab.com/knowledge-integration/folio/stripes-kint-components/compare/v5.9.0...v5.10.0) (2025-02-04)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* Typedown delay ([c736865](https://gitlab.com/knowledge-integration/folio/stripes-kint-components/commit/c736865cec8f4b5cbe2ad473393452fd7ec34dc8))
|
|
14
|
+
|
|
1
15
|
# [5.9.0](https://gitlab.com/knowledge-integration/folio/stripes-kint-components/compare/v5.8.3...v5.9.0) (2025-01-31)
|
|
2
16
|
|
|
3
17
|
|
package/es/index.js
CHANGED
|
@@ -400,6 +400,18 @@ var _ResponsiveButtonGroup = _interopRequireDefault(require("./lib/ResponsiveBut
|
|
|
400
400
|
var _SettingsFormContainer = _interopRequireDefault(require("./lib/SettingsFormContainer"));
|
|
401
401
|
var _ComboButton = _interopRequireDefault(require("./lib/ComboButton"));
|
|
402
402
|
var _NumberField = _interopRequireDefault(require("./lib/NumberField"));
|
|
403
|
+
var _Tags = require("./lib/Tags");
|
|
404
|
+
Object.keys(_Tags).forEach(function (key) {
|
|
405
|
+
if (key === "default" || key === "__esModule") return;
|
|
406
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
407
|
+
if (key in exports && exports[key] === _Tags[key]) return;
|
|
408
|
+
Object.defineProperty(exports, key, {
|
|
409
|
+
enumerable: true,
|
|
410
|
+
get: function () {
|
|
411
|
+
return _Tags[key];
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
});
|
|
403
415
|
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); }
|
|
404
416
|
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; }
|
|
405
417
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -0,0 +1,143 @@
|
|
|
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 _reactQuery = require("react-query");
|
|
10
|
+
var _core = require("@folio/stripes/core");
|
|
11
|
+
var _lodash = require("lodash");
|
|
12
|
+
var _components = require("@folio/stripes/components");
|
|
13
|
+
var _smartComponents = require("@folio/stripes/smart-components");
|
|
14
|
+
var _tagsConfig = require("./tagsConfig");
|
|
15
|
+
var _hooks = require("./hooks");
|
|
16
|
+
var _hooks2 = require("../hooks");
|
|
17
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
18
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
19
|
+
const Tags = _ref => {
|
|
20
|
+
let {
|
|
21
|
+
invalidateLinks = [],
|
|
22
|
+
// If there are other queries that need invalidating, pass those here
|
|
23
|
+
labelOverrides = {},
|
|
24
|
+
link,
|
|
25
|
+
onToggle,
|
|
26
|
+
intlKey: passedIntlKey,
|
|
27
|
+
intlNS: passedIntlNS
|
|
28
|
+
} = _ref;
|
|
29
|
+
const kintIntl = (0, _hooks2.useKintIntl)(passedIntlKey, passedIntlNS);
|
|
30
|
+
const ky = (0, _core.useOkapiKy)();
|
|
31
|
+
const callout = (0, _react.useContext)(_core.CalloutContext);
|
|
32
|
+
const queryClient = (0, _reactQuery.useQueryClient)();
|
|
33
|
+
|
|
34
|
+
// TAG GET/POST
|
|
35
|
+
const {
|
|
36
|
+
data: {
|
|
37
|
+
tags = []
|
|
38
|
+
} = {}
|
|
39
|
+
} = (0, _hooks.useTags)([..._tagsConfig.tagNamespaceArray, link]);
|
|
40
|
+
|
|
41
|
+
// istanbul ignore next
|
|
42
|
+
const {
|
|
43
|
+
mutateAsync: postTags
|
|
44
|
+
} = (0, _reactQuery.useMutation)(['tags', 'stripes-erm-components', 'Tags', 'postTags'], data => ky.post('tags', {
|
|
45
|
+
json: data
|
|
46
|
+
}).then(() => {
|
|
47
|
+
queryClient.invalidateQueries('tags');
|
|
48
|
+
}));
|
|
49
|
+
|
|
50
|
+
// ENTITY GET/PUT
|
|
51
|
+
const {
|
|
52
|
+
data: entity
|
|
53
|
+
} = (0, _reactQuery.useQuery)([link, 'stripes-erm-components', 'Tags'], () => ky.get(link).json());
|
|
54
|
+
|
|
55
|
+
// istanbul ignore next
|
|
56
|
+
const {
|
|
57
|
+
mutateAsync: putEntity
|
|
58
|
+
} = (0, _reactQuery.useMutation)([link, 'stripes-erm-components', 'Tags', 'putEntity'], data => ky.put(link, {
|
|
59
|
+
json: data
|
|
60
|
+
}).then(() => {
|
|
61
|
+
queryClient.invalidateQueries(link);
|
|
62
|
+
if (invalidateLinks?.length) {
|
|
63
|
+
invalidateLinks.forEach(il => queryClient.invalidateQueries(il));
|
|
64
|
+
}
|
|
65
|
+
}));
|
|
66
|
+
|
|
67
|
+
// add tags to global list of tags
|
|
68
|
+
// istanbul ignore next
|
|
69
|
+
const saveTags = tagsToSave => {
|
|
70
|
+
const newTag = (0, _lodash.difference)(tagsToSave.map(t => t.value || t), tags.map(t => t.label.toLowerCase()));
|
|
71
|
+
if (!newTag || !newTag.length) return;
|
|
72
|
+
postTags({
|
|
73
|
+
label: newTag[0],
|
|
74
|
+
description: newTag[0]
|
|
75
|
+
});
|
|
76
|
+
callout.sendCallout({
|
|
77
|
+
message: kintIntl.formatKintMessage({
|
|
78
|
+
id: 'newTagCreated',
|
|
79
|
+
overrideValue: labelOverrides.newTagCreated
|
|
80
|
+
})
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// add tag to the list of entity tags
|
|
85
|
+
// istanbul ignore next
|
|
86
|
+
const saveEntityTags = tagsToSave => {
|
|
87
|
+
const tagListMap = (entity?.tags ?? []).map(tag => ({
|
|
88
|
+
'value': tag.value
|
|
89
|
+
}));
|
|
90
|
+
const tagsMap = tagsToSave.map(tag => ({
|
|
91
|
+
'value': tag.value || tag
|
|
92
|
+
}));
|
|
93
|
+
const newTags = (0, _lodash.sortBy)((0, _lodash.uniqBy)([...tagListMap, ...tagsMap], 'value'));
|
|
94
|
+
putEntity({
|
|
95
|
+
tags: newTags
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
const onAdd = addTags => {
|
|
99
|
+
saveEntityTags(addTags);
|
|
100
|
+
saveTags(addTags);
|
|
101
|
+
};
|
|
102
|
+
const onRemove = tag => {
|
|
103
|
+
const tagToDelete = (entity?.tags ?? []).filter(t => t.value.toLowerCase() === tag.toLowerCase());
|
|
104
|
+
putEntity({
|
|
105
|
+
tags: [{
|
|
106
|
+
id: tagToDelete[0].id,
|
|
107
|
+
_delete: true
|
|
108
|
+
}]
|
|
109
|
+
});
|
|
110
|
+
};
|
|
111
|
+
const entityTags = (entity?.tags ?? []).map(tag => tag.value.toLowerCase());
|
|
112
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Pane, {
|
|
113
|
+
defaultWidth: "20%",
|
|
114
|
+
dismissible: true,
|
|
115
|
+
id: "tags-helper-pane",
|
|
116
|
+
onClose: onToggle,
|
|
117
|
+
paneSub: kintIntl.formatKintMessage({
|
|
118
|
+
id: 'numberOfTags',
|
|
119
|
+
overrideValue: labelOverrides.numberOfTags
|
|
120
|
+
}, {
|
|
121
|
+
count: entity?.tags?.length ?? 0
|
|
122
|
+
}),
|
|
123
|
+
paneTitle: kintIntl.formatKintMessage({
|
|
124
|
+
id: 'tags',
|
|
125
|
+
overrideValue: labelOverrides.tags
|
|
126
|
+
}),
|
|
127
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_smartComponents.TagsForm, {
|
|
128
|
+
entityTags: entityTags,
|
|
129
|
+
onAdd: onAdd,
|
|
130
|
+
onRemove: onRemove,
|
|
131
|
+
tags: tags
|
|
132
|
+
})
|
|
133
|
+
});
|
|
134
|
+
};
|
|
135
|
+
Tags.propTypes = {
|
|
136
|
+
intlKey: _propTypes.default.string,
|
|
137
|
+
intlNS: _propTypes.default.string,
|
|
138
|
+
invalidateLinks: _propTypes.default.arrayOf(_propTypes.default.string),
|
|
139
|
+
labelOverrides: _propTypes.default.object,
|
|
140
|
+
link: _propTypes.default.string,
|
|
141
|
+
onToggle: _propTypes.default.func
|
|
142
|
+
};
|
|
143
|
+
var _default = exports.default = Tags;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _react = _interopRequireDefault(require("react"));
|
|
4
|
+
var _reactRouterDom = require("react-router-dom");
|
|
5
|
+
var _stripesErmTesting = require("@folio/stripes-erm-testing");
|
|
6
|
+
var _Tags = _interopRequireDefault(require("./Tags"));
|
|
7
|
+
var _jest = require("../../../test/jest");
|
|
8
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
9
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
|
+
const onToggle = jest.fn();
|
|
11
|
+
const onAdd = jest.fn();
|
|
12
|
+
const link = 'erm/sas/14c16fc4-f986-4e60-aa59-4e627fcf160b';
|
|
13
|
+
describe('Tags', () => {
|
|
14
|
+
let renderComponent;
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
renderComponent = (0, _jest.renderWithKintHarness)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactRouterDom.MemoryRouter, {
|
|
17
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Tags.default, {
|
|
18
|
+
invalidateLinks: [],
|
|
19
|
+
link: link,
|
|
20
|
+
onAdd: onAdd,
|
|
21
|
+
onToggle: onToggle
|
|
22
|
+
})
|
|
23
|
+
}));
|
|
24
|
+
});
|
|
25
|
+
test('renders the expected label', () => {
|
|
26
|
+
const {
|
|
27
|
+
getByText
|
|
28
|
+
} = renderComponent;
|
|
29
|
+
expect(getByText('0 Tags')).toBeInTheDocument();
|
|
30
|
+
});
|
|
31
|
+
test('renders expected pane dismiss button ', async () => {
|
|
32
|
+
await (0, _stripesErmTesting.IconButton)('Close Tags').exists();
|
|
33
|
+
});
|
|
34
|
+
test('renders expected open menu button ', () => {
|
|
35
|
+
const {
|
|
36
|
+
getByRole
|
|
37
|
+
} = renderComponent;
|
|
38
|
+
expect(getByRole('button', {
|
|
39
|
+
name: 'stripes-components.multiSelection.dropdownTriggerLabel'
|
|
40
|
+
})).toBeInTheDocument();
|
|
41
|
+
});
|
|
42
|
+
test('renders tags heading ', () => {
|
|
43
|
+
const {
|
|
44
|
+
getByRole
|
|
45
|
+
} = renderComponent;
|
|
46
|
+
expect(getByRole('heading', {
|
|
47
|
+
name: 'Tags'
|
|
48
|
+
})).toBeInTheDocument();
|
|
49
|
+
});
|
|
50
|
+
test('renders expected region with zero tags', () => {
|
|
51
|
+
const {
|
|
52
|
+
getByRole
|
|
53
|
+
} = renderComponent;
|
|
54
|
+
expect(getByRole('region', {
|
|
55
|
+
name: 'Tags 0 Tags'
|
|
56
|
+
})).toBeInTheDocument();
|
|
57
|
+
});
|
|
58
|
+
test('renders the expected multiSelectDescription', () => {
|
|
59
|
+
const {
|
|
60
|
+
getByText
|
|
61
|
+
} = renderComponent;
|
|
62
|
+
expect(getByText('Contains a list of any selected values, followed by an autocomplete textfield for selecting additional values.')).toBeInTheDocument();
|
|
63
|
+
});
|
|
64
|
+
test('renders the expected label', () => {
|
|
65
|
+
const {
|
|
66
|
+
getByText
|
|
67
|
+
} = renderComponent;
|
|
68
|
+
expect(getByText('0 items selected')).toBeInTheDocument();
|
|
69
|
+
});
|
|
70
|
+
test('displays the tags pane', async () => {
|
|
71
|
+
await (0, _stripesErmTesting.Pane)('Tags').is({
|
|
72
|
+
visible: true
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
test('displays the tags pane header', async () => {
|
|
76
|
+
await (0, _stripesErmTesting.PaneHeader)('Tags').is({
|
|
77
|
+
visible: true
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "tagsEnabledQueryKey", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _useTagsEnabled.tagsEnabledQueryKey;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(exports, "useTags", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () {
|
|
15
|
+
return _useTags.default;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
Object.defineProperty(exports, "useTagsEnabled", {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: function () {
|
|
21
|
+
return _useTagsEnabled.default;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
var _useTagsEnabled = _interopRequireWildcard(require("./useTagsEnabled"));
|
|
25
|
+
var _useTags = _interopRequireDefault(require("./useTags"));
|
|
26
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
27
|
+
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); }
|
|
28
|
+
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; }
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _reactQuery = require("react-query");
|
|
8
|
+
var _core = require("@folio/stripes/core");
|
|
9
|
+
var _tagsConfig = require("../tagsConfig");
|
|
10
|
+
const useTags = (namespaceArray, options) => {
|
|
11
|
+
const ky = (0, _core.useOkapiKy)();
|
|
12
|
+
const nsArray = namespaceArray ?? _tagsConfig.tagNamespaceArray;
|
|
13
|
+
return (0, _reactQuery.useQuery)(nsArray, () => ky.get(_tagsConfig.defaultTagQuery).json(), options);
|
|
14
|
+
};
|
|
15
|
+
var _default = exports.default = useTags;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.tagsEnabledQueryKey = exports.default = void 0;
|
|
7
|
+
var _core = require("@folio/stripes/core");
|
|
8
|
+
var _reactQuery = require("react-query");
|
|
9
|
+
var _endpoints = require("../../constants/endpoints");
|
|
10
|
+
const tagsEnabledQueryKey = exports.tagsEnabledQueryKey = [_endpoints.MOD_SETTINGS_ENDPOINT, 'query=(module==TAGS and configName==tags_enabled)', 'stripes-kint-components', 'useTagsEnabled'];
|
|
11
|
+
const useTagsEnabled = () => {
|
|
12
|
+
const ky = (0, _core.useOkapiKy)();
|
|
13
|
+
const queryObject = (0, _reactQuery.useQuery)(tagsEnabledQueryKey, () => ky.get(`${_endpoints.MOD_SETTINGS_ENDPOINT}?query=(module==TAGS and configName==tags_enabled)`).json());
|
|
14
|
+
const {
|
|
15
|
+
data: {
|
|
16
|
+
configs: {
|
|
17
|
+
0: {
|
|
18
|
+
value
|
|
19
|
+
} = {}
|
|
20
|
+
} = []
|
|
21
|
+
} = {}
|
|
22
|
+
} = queryObject;
|
|
23
|
+
return !value || value === 'true';
|
|
24
|
+
};
|
|
25
|
+
var _default = exports.default = useTagsEnabled;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
var _exportNames = {
|
|
7
|
+
Tags: true
|
|
8
|
+
};
|
|
9
|
+
Object.defineProperty(exports, "Tags", {
|
|
10
|
+
enumerable: true,
|
|
11
|
+
get: function () {
|
|
12
|
+
return _Tags.default;
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
var _Tags = _interopRequireDefault(require("./Tags"));
|
|
16
|
+
var _tagsConfig = require("./tagsConfig");
|
|
17
|
+
Object.keys(_tagsConfig).forEach(function (key) {
|
|
18
|
+
if (key === "default" || key === "__esModule") return;
|
|
19
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
20
|
+
if (key in exports && exports[key] === _tagsConfig[key]) return;
|
|
21
|
+
Object.defineProperty(exports, key, {
|
|
22
|
+
enumerable: true,
|
|
23
|
+
get: function () {
|
|
24
|
+
return _tagsConfig[key];
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
var _hooks = require("./hooks");
|
|
29
|
+
Object.keys(_hooks).forEach(function (key) {
|
|
30
|
+
if (key === "default" || key === "__esModule") return;
|
|
31
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
32
|
+
if (key in exports && exports[key] === _hooks[key]) return;
|
|
33
|
+
Object.defineProperty(exports, key, {
|
|
34
|
+
enumerable: true,
|
|
35
|
+
get: function () {
|
|
36
|
+
return _hooks[key];
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.tagsPath = exports.tagNamespaceArray = exports.defaultTagsParams = exports.defaultTagQuery = void 0;
|
|
7
|
+
const tagNamespaceArray = exports.tagNamespaceArray = ['tags', 'stripes-kint-components', 'Tags'];
|
|
8
|
+
const tagsPath = exports.tagsPath = 'tags';
|
|
9
|
+
const defaultTagsParams = exports.defaultTagsParams = ['limit=1000', 'query=cql.allRecords%3D1%20sortby%20label'];
|
|
10
|
+
const defaultTagQuery = exports.defaultTagQuery = `${tagsPath}?${defaultTagsParams?.join('&')}`;
|
|
@@ -22,8 +22,11 @@ const Typedown = _ref => {
|
|
|
22
22
|
className,
|
|
23
23
|
dataOptions,
|
|
24
24
|
displayClearItem = true,
|
|
25
|
+
displayValueWhileOpen = true,
|
|
25
26
|
endOfList,
|
|
26
27
|
id,
|
|
28
|
+
initialOpenDelay = 800,
|
|
29
|
+
// Initial opening delay of 800ms (handles any stripes animations)
|
|
27
30
|
input,
|
|
28
31
|
isSelected,
|
|
29
32
|
filterPath,
|
|
@@ -89,7 +92,9 @@ const Typedown = _ref => {
|
|
|
89
92
|
resizeRef,
|
|
90
93
|
searchWidth
|
|
91
94
|
}
|
|
92
|
-
} = (0, _typedownHooks.useTypedown)(input.name
|
|
95
|
+
} = (0, _typedownHooks.useTypedown)(input.name, {
|
|
96
|
+
timeout: initialOpenDelay
|
|
97
|
+
});
|
|
93
98
|
const renderItem = (0, _react.useCallback)(function (option) {
|
|
94
99
|
let optionIsSelected = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
95
100
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
@@ -157,6 +162,9 @@ const Typedown = _ref => {
|
|
|
157
162
|
})
|
|
158
163
|
});
|
|
159
164
|
};
|
|
165
|
+
const displayValue = (0, _react.useMemo)(() => {
|
|
166
|
+
return !!selectedUniqueId && (!open || displayValueWhileOpen);
|
|
167
|
+
}, [displayValueWhileOpen, open, selectedUniqueId]);
|
|
160
168
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
161
169
|
ref: resizeRef,
|
|
162
170
|
className: (0, _classnames.default)(_TypeDown.default.typedown, className),
|
|
@@ -185,7 +193,7 @@ const Typedown = _ref => {
|
|
|
185
193
|
overlayRef: overlayRef,
|
|
186
194
|
portal: portal,
|
|
187
195
|
children: dropDown()
|
|
188
|
-
}, "typedown-menu-toggle"),
|
|
196
|
+
}, "typedown-menu-toggle"), displayValue && /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
189
197
|
className: (0, _classnames.default)(_TypeDown.default.selectedDisplay),
|
|
190
198
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
191
199
|
className: _TypeDown.default.selectedItem,
|
|
@@ -202,9 +210,11 @@ Typedown.propTypes = {
|
|
|
202
210
|
className: _propTypes.default.string,
|
|
203
211
|
dataOptions: _propTypes.default.arrayOf(_propTypes.default.object),
|
|
204
212
|
displayClearItem: _propTypes.default.bool,
|
|
213
|
+
displayValueWhileOpen: _propTypes.default.bool,
|
|
205
214
|
endOfList: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.node, _propTypes.default.element]),
|
|
206
215
|
filterPath: _propTypes.default.string,
|
|
207
216
|
id: _propTypes.default.string,
|
|
217
|
+
initialOpenDelay: _propTypes.default.number,
|
|
208
218
|
input: _propTypes.default.object,
|
|
209
219
|
isSelected: _propTypes.default.func,
|
|
210
220
|
label: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.element]),
|
|
@@ -11,7 +11,10 @@ var _eventCodes = require("../../constants/eventCodes");
|
|
|
11
11
|
var _selectorSafe = _interopRequireDefault(require("../../utils/selectorSafe"));
|
|
12
12
|
var _useTypedownToggle = _interopRequireDefault(require("./useTypedownToggle"));
|
|
13
13
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
14
|
-
const useTypedown = name
|
|
14
|
+
const useTypedown = function (name) {
|
|
15
|
+
let {
|
|
16
|
+
timeout = 800
|
|
17
|
+
} = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
15
18
|
// SEARCHFIELD COMPONENT
|
|
16
19
|
const searchFieldComponent = document.getElementById(`typedown-searchField-${(0, _selectorSafe.default)(name)}`);
|
|
17
20
|
|
|
@@ -101,6 +104,16 @@ const useTypedown = name => {
|
|
|
101
104
|
const {
|
|
102
105
|
open
|
|
103
106
|
} = (0, _useTypedownToggle.default)(name);
|
|
107
|
+
const [useOpen, setUseOpen] = (0, _react.useState)(false);
|
|
108
|
+
(0, _react.useEffect)(() => {
|
|
109
|
+
// Use setTimeout to update the message after 2000 milliseconds (2 seconds)
|
|
110
|
+
const timeoutId = setTimeout(() => {
|
|
111
|
+
setUseOpen(true);
|
|
112
|
+
}, timeout); // Wait 0.8 seconds for open prop to get used
|
|
113
|
+
|
|
114
|
+
// Cleanup function to clear the timeout if the component unmounts
|
|
115
|
+
return () => clearTimeout(timeoutId);
|
|
116
|
+
}, [timeout]);
|
|
104
117
|
|
|
105
118
|
// RESIZE STUFF
|
|
106
119
|
const {
|
|
@@ -123,7 +136,7 @@ const useTypedown = name => {
|
|
|
123
136
|
searchFieldKeyDownHandler
|
|
124
137
|
},
|
|
125
138
|
variables: {
|
|
126
|
-
open,
|
|
139
|
+
open: useOpen ? open : false,
|
|
127
140
|
portal,
|
|
128
141
|
resizeRef,
|
|
129
142
|
searchWidth
|
|
@@ -4,18 +4,17 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
|
-
var _react =
|
|
7
|
+
var _react = require("react");
|
|
8
8
|
var _reactRouterDom = require("react-router-dom");
|
|
9
9
|
var _queryString = _interopRequireDefault(require("query-string"));
|
|
10
10
|
var _isEqual = _interopRequireDefault(require("lodash/isEqual"));
|
|
11
11
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
12
12
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
13
|
-
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); }
|
|
14
|
-
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; }
|
|
15
|
-
let helperObject = {};
|
|
16
13
|
const useHelperApp = helpers => {
|
|
17
14
|
const history = (0, _reactRouterDom.useHistory)();
|
|
18
15
|
const location = (0, _reactRouterDom.useLocation)();
|
|
16
|
+
const [helperObject, setHelperObject] = (0, _react.useState)({});
|
|
17
|
+
const [helperToggleFunctions, setHelperToggleFunctions] = (0, _react.useState)({});
|
|
19
18
|
const query = _queryString.default.parse(location.search);
|
|
20
19
|
const [currentHelper, setCurrentHelper] = (0, _react.useState)(query?.helper);
|
|
21
20
|
const handleToggleHelper = (0, _react.useCallback)(helper => {
|
|
@@ -25,9 +24,16 @@ const useHelperApp = helpers => {
|
|
|
25
24
|
return currentHelper === hlp;
|
|
26
25
|
};
|
|
27
26
|
(0, _react.useEffect)(() => {
|
|
28
|
-
// Keep object outside of hook to avoid redraw, oncly change when keys change
|
|
29
27
|
if (!(0, _isEqual.default)(Object.keys(helperObject), Object.keys(helpers))) {
|
|
30
|
-
|
|
28
|
+
setHelperObject(helpers);
|
|
29
|
+
}
|
|
30
|
+
const newHelperToggleFunctions = {};
|
|
31
|
+
Object.keys(helperObject).forEach(h => {
|
|
32
|
+
newHelperToggleFunctions[h] = () => handleToggleHelper(h);
|
|
33
|
+
});
|
|
34
|
+
if (!(0, _isEqual.default)(Object.keys(helperToggleFunctions), Object.keys(newHelperToggleFunctions))) {
|
|
35
|
+
// This makes sure adding/removing helpers changes the functions
|
|
36
|
+
setHelperToggleFunctions(newHelperToggleFunctions);
|
|
31
37
|
}
|
|
32
38
|
if (currentHelper !== query?.helper) {
|
|
33
39
|
const newQuery = {
|
|
@@ -38,11 +44,14 @@ const useHelperApp = helpers => {
|
|
|
38
44
|
pathname: location.pathname,
|
|
39
45
|
search: `?${_queryString.default.stringify(newQuery)}`
|
|
40
46
|
});
|
|
47
|
+
|
|
48
|
+
// When helper changes, reset helperToggleFunctions
|
|
49
|
+
setHelperToggleFunctions(newHelperToggleFunctions);
|
|
41
50
|
}
|
|
42
|
-
}, [currentHelper, helpers, history, location, query]);
|
|
51
|
+
}, [currentHelper, handleToggleHelper, helperObject, helperToggleFunctions, helpers, history, location, query]);
|
|
43
52
|
|
|
44
53
|
// Set the HelperComponent
|
|
45
|
-
const HelperComponent = (0, _react.
|
|
54
|
+
const HelperComponent = (0, _react.useCallback)(props => {
|
|
46
55
|
if (!query?.helper) return null;
|
|
47
56
|
let Component = null;
|
|
48
57
|
Component = helperObject[query?.helper];
|
|
@@ -51,13 +60,7 @@ const useHelperApp = helpers => {
|
|
|
51
60
|
onToggle: () => handleToggleHelper(query?.helper),
|
|
52
61
|
...props
|
|
53
62
|
});
|
|
54
|
-
}, [handleToggleHelper, query
|
|
55
|
-
|
|
56
|
-
// Set up the helperToggleFunctions
|
|
57
|
-
const helperToggleFunctions = {};
|
|
58
|
-
Object.keys(helperObject).forEach(h => {
|
|
59
|
-
helperToggleFunctions[h] = () => handleToggleHelper(h);
|
|
60
|
-
});
|
|
63
|
+
}, [handleToggleHelper, helperObject, query?.helper]);
|
|
61
64
|
return {
|
|
62
65
|
currentHelper,
|
|
63
66
|
HelperComponent,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@k-int/stripes-kint-components",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.11.0",
|
|
4
4
|
"description": "Stripes Component library for K-Int specific applications",
|
|
5
5
|
"sideEffects": [
|
|
6
6
|
"*.css"
|
|
@@ -13,7 +13,8 @@
|
|
|
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",
|
|
16
|
-
"clean-
|
|
16
|
+
"clean-install": "yarn clean && yarn install --ignore-scripts",
|
|
17
|
+
"clean-build": "yarn clean-install && yarn build",
|
|
17
18
|
"prepare": "yarn build",
|
|
18
19
|
"semantic-release": "semantic-release"
|
|
19
20
|
},
|
package/src/index.js
CHANGED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
## FormModal Component
|
|
2
|
+
|
|
3
|
+
The `FormModal` component provides a simple way to create a modal dialog with a form. It combines the `Modal` component from `@folio/stripes/components` with the `Form` component from `react-final-form`, handling form submission, validation, and modal interactions.
|
|
4
|
+
|
|
5
|
+
### Basic Usage
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
import { useState } from 'react';
|
|
9
|
+
import FormModal from '@k-int/stripes-kint-components';
|
|
10
|
+
import { Field } from 'react-final-form';
|
|
11
|
+
import { TextField } from '@folio/stripes/components';
|
|
12
|
+
|
|
13
|
+
const MyFormModal = () => {
|
|
14
|
+
const [open, setOpen] = useState(false);
|
|
15
|
+
|
|
16
|
+
const onSubmit = (values) => {
|
|
17
|
+
// Handle form submission
|
|
18
|
+
console.log(values);
|
|
19
|
+
setOpen(false); // Close the modal after submission
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<>
|
|
24
|
+
<Button onClick={() => setOpen(true)}>Open Modal</Button> {/* Button to open the modal */}
|
|
25
|
+
<FormModal
|
|
26
|
+
modalProps={{ open, onClose: () => setOpen(false) }}
|
|
27
|
+
onSubmit={onSubmit}
|
|
28
|
+
>
|
|
29
|
+
<Field
|
|
30
|
+
name="name"
|
|
31
|
+
component={TextField}
|
|
32
|
+
label="Name"
|
|
33
|
+
/>
|
|
34
|
+
</FormModal>
|
|
35
|
+
</>
|
|
36
|
+
);
|
|
37
|
+
};
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Props
|
|
41
|
+
|
|
42
|
+
| Name | Type | Description | Default | Required |
|
|
43
|
+
|---|---|---|---|---|
|
|
44
|
+
| children | node/func | The content of the modal, typically form fields. | | ✓ |
|
|
45
|
+
| intlKey | string | The key to use for internationalization messages. | | ✕ |
|
|
46
|
+
| intlNS | string | The namespace to use for internationalization messages. | | ✕ |
|
|
47
|
+
| labelOverrides | object | An object to override the default labels for buttons. | `{}` | ✕ |
|
|
48
|
+
| modalProps | object | Props to pass to the underlying `Modal` component. Should include `open` and `onClose`. | | ✓ |
|
|
49
|
+
| onError | func | A function to handle errors that occur during form submission. This function will receive the error object as a parameter. | | ✕ |
|
|
50
|
+
| onSubmit | func | A function to handle form submission. | | ✓ |
|
|
51
|
+
| onSuccess | func | A function to handle successful form submission. This function will receive the submitted values as a parameter. | | ✕ |
|
|
52
|
+
|...formProps | object | Any other props will be passed to the underlying `Form` component from `react-final-form`. | | ✕ |
|
|
53
|
+
|
|
54
|
+
### Features
|
|
55
|
+
|
|
56
|
+
* **Integrated form handling:** The component integrates seamlessly with `react-final-form`, providing access to form state and helper functions within the `footer` and `children` props.
|
|
57
|
+
* **Customizable footer:** The `modalProps.footer` prop allows for customization of the modal footer. It receives an object with the following properties:
|
|
58
|
+
* `formState`: The current state of the form.
|
|
59
|
+
* `handleSubmit`: A function to handle form submission and close the modal.
|
|
60
|
+
* `handleClose`: A function to close the modal.
|
|
61
|
+
* `handleSubmitNoRestart`: **(DEPRECATED)** Use `handleSubmitRaw` instead.
|
|
62
|
+
* `handleSubmitRaw`: A function to handle form submission without closing the modal or clearing the form.
|
|
63
|
+
* **Error and success handling:** The `onError` and `onSuccess` props allow for custom handling of asynchronous form submission errors and successes.
|
|
64
|
+
* **Internationalization:** The component supports internationalization using the `intlKey` and `intlNS` props.
|
|
65
|
+
* **Label overrides:** The `labelOverrides` prop allows for overriding the default button labels.
|
|
66
|
+
|
|
67
|
+
### Example with Custom Footer
|
|
68
|
+
|
|
69
|
+
```javascript
|
|
70
|
+
<FormModal
|
|
71
|
+
modalProps={{
|
|
72
|
+
open: true,
|
|
73
|
+
onClose: () => { /*... */ },
|
|
74
|
+
footer: ({ handleSubmit, handleClose }) => (
|
|
75
|
+
<ModalFooter>
|
|
76
|
+
<Button
|
|
77
|
+
buttonStyle="primary"
|
|
78
|
+
onClick={handleSubmit}
|
|
79
|
+
type="submit"
|
|
80
|
+
>
|
|
81
|
+
Save
|
|
82
|
+
</Button>
|
|
83
|
+
<Button onClick={handleClose}>Cancel</Button>
|
|
84
|
+
</ModalFooter>
|
|
85
|
+
)
|
|
86
|
+
}}
|
|
87
|
+
onSubmit={() => { /*... */ }}
|
|
88
|
+
>
|
|
89
|
+
{/*... form content... */}
|
|
90
|
+
</FormModal>
|
|
91
|
+
```
|