@pega/cosmos-react-work 2.0.0-dev.2.0 → 2.0.0-dev.21.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/components/AppAnnouncement/AppAnnouncement.d.ts.map +1 -1
- package/lib/components/AppAnnouncement/AppAnnouncement.js +13 -17
- package/lib/components/AppAnnouncement/AppAnnouncement.js.map +1 -1
- package/lib/components/CaseHeader/CaseHeader.d.ts +5 -1
- package/lib/components/CaseHeader/CaseHeader.d.ts.map +1 -1
- package/lib/components/CaseHeader/CaseHeader.js +39 -15
- package/lib/components/CaseHeader/CaseHeader.js.map +1 -1
- package/lib/components/CasePreview/CasePreview.d.ts +5 -5
- package/lib/components/CasePreview/CasePreview.d.ts.map +1 -1
- package/lib/components/CasePreview/CasePreview.js +17 -16
- package/lib/components/CasePreview/CasePreview.js.map +1 -1
- package/lib/components/CaseSummary/CaseSummary.d.ts +20 -8
- package/lib/components/CaseSummary/CaseSummary.d.ts.map +1 -1
- package/lib/components/CaseSummary/CaseSummary.js +121 -14
- package/lib/components/CaseSummary/CaseSummary.js.map +1 -1
- package/lib/components/CaseSummaryFields/CaseSummaryFields.d.ts.map +1 -1
- package/lib/components/CaseSummaryFields/CaseSummaryFields.js +14 -12
- package/lib/components/CaseSummaryFields/CaseSummaryFields.js.map +1 -1
- package/lib/components/CaseView/CaseView.d.ts +6 -19
- package/lib/components/CaseView/CaseView.d.ts.map +1 -1
- package/lib/components/CaseView/CaseView.js +173 -189
- package/lib/components/CaseView/CaseView.js.map +1 -1
- package/lib/components/CaseView/CaseView.styles.d.ts +24 -0
- package/lib/components/CaseView/CaseView.styles.d.ts.map +1 -0
- package/lib/components/CaseView/CaseView.styles.js +111 -0
- package/lib/components/CaseView/CaseView.styles.js.map +1 -0
- package/lib/components/CaseView/MobileCaseView.d.ts +1 -0
- package/lib/components/CaseView/MobileCaseView.d.ts.map +1 -1
- package/lib/components/CaseView/MobileCaseView.js +3 -6
- package/lib/components/CaseView/MobileCaseView.js.map +1 -1
- package/lib/components/CaseView/UtilitiesSummary.d.ts.map +1 -1
- package/lib/components/CaseView/UtilitiesSummary.js +8 -10
- package/lib/components/CaseView/UtilitiesSummary.js.map +1 -1
- package/lib/components/CaseView/index.d.ts +2 -1
- package/lib/components/CaseView/index.d.ts.map +1 -1
- package/lib/components/CaseView/index.js +1 -1
- package/lib/components/CaseView/index.js.map +1 -1
- package/lib/components/ConfigurableLayout/ConfigurableLayout.d.ts +4 -0
- package/lib/components/ConfigurableLayout/ConfigurableLayout.d.ts.map +1 -0
- package/lib/components/ConfigurableLayout/ConfigurableLayout.js +93 -0
- package/lib/components/ConfigurableLayout/ConfigurableLayout.js.map +1 -0
- package/lib/components/ConfigurableLayout/ConfigurableLayout.types.d.ts +43 -0
- package/lib/components/ConfigurableLayout/ConfigurableLayout.types.d.ts.map +1 -0
- package/lib/components/ConfigurableLayout/ConfigurableLayout.types.js +2 -0
- package/lib/components/ConfigurableLayout/ConfigurableLayout.types.js.map +1 -0
- package/lib/components/ConfigurableLayout/LayoutCell.d.ts +6 -0
- package/lib/components/ConfigurableLayout/LayoutCell.d.ts.map +1 -0
- package/lib/components/ConfigurableLayout/LayoutCell.js +64 -0
- package/lib/components/ConfigurableLayout/LayoutCell.js.map +1 -0
- package/lib/components/ConfigurableLayout/defaults.d.ts +4 -0
- package/lib/components/ConfigurableLayout/defaults.d.ts.map +1 -0
- package/lib/components/ConfigurableLayout/defaults.js +4 -0
- package/lib/components/ConfigurableLayout/defaults.js.map +1 -0
- package/lib/components/ConfigurableLayout/index.d.ts +3 -0
- package/lib/components/ConfigurableLayout/index.d.ts.map +1 -0
- package/lib/components/ConfigurableLayout/index.js +3 -0
- package/lib/components/ConfigurableLayout/index.js.map +1 -0
- package/lib/components/ConfigurableLayout/options.d.ts +10 -0
- package/lib/components/ConfigurableLayout/options.d.ts.map +1 -0
- package/lib/components/ConfigurableLayout/options.js +10 -0
- package/lib/components/ConfigurableLayout/options.js.map +1 -0
- package/lib/components/ConfigurableLayout/useTrackWrappedRegions.d.ts +7 -0
- package/lib/components/ConfigurableLayout/useTrackWrappedRegions.d.ts.map +1 -0
- package/lib/components/ConfigurableLayout/useTrackWrappedRegions.js +37 -0
- package/lib/components/ConfigurableLayout/useTrackWrappedRegions.js.map +1 -0
- package/lib/components/Confirmation/Confirmation.d.ts +19 -0
- package/lib/components/Confirmation/Confirmation.d.ts.map +1 -0
- package/lib/components/Confirmation/Confirmation.js +14 -0
- package/lib/components/Confirmation/Confirmation.js.map +1 -0
- package/lib/components/Confirmation/index.d.ts +3 -0
- package/lib/components/Confirmation/index.d.ts.map +1 -0
- package/lib/components/Confirmation/index.js +2 -0
- package/lib/components/Confirmation/index.js.map +1 -0
- package/lib/components/Details/Details.d.ts +13 -0
- package/lib/components/Details/Details.d.ts.map +1 -0
- package/lib/components/Details/Details.js +38 -0
- package/lib/components/Details/Details.js.map +1 -0
- package/lib/components/Details/index.d.ts +4 -0
- package/lib/components/Details/index.d.ts.map +1 -0
- package/lib/components/Details/index.js +3 -0
- package/lib/components/Details/index.js.map +1 -0
- package/lib/components/Glimpse/Glimpse.d.ts +2 -2
- package/lib/components/Glimpse/Glimpse.d.ts.map +1 -1
- package/lib/components/Glimpse/Glimpse.js +3 -6
- package/lib/components/Glimpse/Glimpse.js.map +1 -1
- package/lib/components/SearchResults/Filter.d.ts.map +1 -1
- package/lib/components/SearchResults/Filter.js +15 -48
- package/lib/components/SearchResults/Filter.js.map +1 -1
- package/lib/components/SearchResults/SearchResult.d.ts.map +1 -1
- package/lib/components/SearchResults/SearchResult.js +2 -8
- package/lib/components/SearchResults/SearchResult.js.map +1 -1
- package/lib/components/SearchResults/SearchResults.d.ts.map +1 -1
- package/lib/components/SearchResults/SearchResults.js +44 -101
- package/lib/components/SearchResults/SearchResults.js.map +1 -1
- package/lib/components/SearchResults/SearchResults.styles.d.ts +8 -0
- package/lib/components/SearchResults/SearchResults.styles.d.ts.map +1 -0
- package/lib/components/SearchResults/SearchResults.styles.js +67 -0
- package/lib/components/SearchResults/SearchResults.styles.js.map +1 -0
- package/lib/components/SearchResults/SearchResults.types.d.ts +14 -4
- package/lib/components/SearchResults/SearchResults.types.d.ts.map +1 -1
- package/lib/components/SearchResults/SearchResults.types.js.map +1 -1
- package/lib/components/Stages/Stages.d.ts.map +1 -1
- package/lib/components/Stages/Stages.js +31 -36
- package/lib/components/Stages/Stages.js.map +1 -1
- package/lib/components/Stages/Stages.styles.d.ts.map +1 -1
- package/lib/components/Stages/Stages.styles.js +22 -28
- package/lib/components/Stages/Stages.styles.js.map +1 -1
- package/lib/components/Stages/Steps.d.ts.map +1 -1
- package/lib/components/Stages/Steps.js +7 -7
- package/lib/components/Stages/Steps.js.map +1 -1
- package/lib/components/Stages/StepsContainer.d.ts.map +1 -1
- package/lib/components/Stages/StepsContainer.js +5 -9
- package/lib/components/Stages/StepsContainer.js.map +1 -1
- package/lib/components/Stakeholders/StakeholderForm.d.ts +7 -0
- package/lib/components/Stakeholders/StakeholderForm.d.ts.map +1 -0
- package/lib/components/Stakeholders/StakeholderForm.js +49 -0
- package/lib/components/Stakeholders/StakeholderForm.js.map +1 -0
- package/lib/components/Stakeholders/Stakeholders.d.ts +6 -0
- package/lib/components/Stakeholders/Stakeholders.d.ts.map +1 -0
- package/lib/components/Stakeholders/Stakeholders.js +217 -0
- package/lib/components/Stakeholders/Stakeholders.js.map +1 -0
- package/lib/components/Stakeholders/Stakeholders.types.d.ts +83 -0
- package/lib/components/Stakeholders/Stakeholders.types.d.ts.map +1 -0
- package/lib/components/Stakeholders/Stakeholders.types.js +2 -0
- package/lib/components/Stakeholders/Stakeholders.types.js.map +1 -0
- package/lib/components/Stakeholders/index.d.ts +3 -0
- package/lib/components/Stakeholders/index.d.ts.map +1 -0
- package/lib/components/Stakeholders/index.js +2 -0
- package/lib/components/Stakeholders/index.js.map +1 -0
- package/lib/components/Tags/Tags.d.ts +34 -0
- package/lib/components/Tags/Tags.d.ts.map +1 -0
- package/lib/components/Tags/Tags.js +227 -0
- package/lib/components/Tags/Tags.js.map +1 -0
- package/lib/components/Tags/index.d.ts +3 -0
- package/lib/components/Tags/index.d.ts.map +1 -0
- package/lib/components/Tags/index.js +2 -0
- package/lib/components/Tags/index.js.map +1 -0
- package/lib/components/Tasks/TaskList.d.ts +25 -0
- package/lib/components/Tasks/TaskList.d.ts.map +1 -0
- package/lib/components/Tasks/TaskList.js +25 -0
- package/lib/components/Tasks/TaskList.js.map +1 -0
- package/lib/components/Tasks/Tasks.d.ts +2 -14
- package/lib/components/Tasks/Tasks.d.ts.map +1 -1
- package/lib/components/Tasks/Tasks.js +17 -39
- package/lib/components/Tasks/Tasks.js.map +1 -1
- package/lib/components/Tasks/index.d.ts +3 -0
- package/lib/components/Tasks/index.d.ts.map +1 -1
- package/lib/components/Tasks/index.js +1 -0
- package/lib/components/Tasks/index.js.map +1 -1
- package/lib/components/Timeline/Timeline.d.ts.map +1 -1
- package/lib/components/Timeline/Timeline.js +13 -29
- package/lib/components/Timeline/Timeline.js.map +1 -1
- package/lib/components/Timeline/Timeline.styles.d.ts +9 -5
- package/lib/components/Timeline/Timeline.styles.d.ts.map +1 -1
- package/lib/components/Timeline/Timeline.styles.js +107 -50
- package/lib/components/Timeline/Timeline.styles.js.map +1 -1
- package/lib/components/Timeline/Timeline.types.d.ts +18 -5
- package/lib/components/Timeline/Timeline.types.d.ts.map +1 -1
- package/lib/components/Timeline/Timeline.types.js.map +1 -1
- package/lib/components/Timeline/TimelineItem.d.ts +5 -3
- package/lib/components/Timeline/TimelineItem.d.ts.map +1 -1
- package/lib/components/Timeline/TimelineItem.js +15 -32
- package/lib/components/Timeline/TimelineItem.js.map +1 -1
- package/lib/components/Timeline/utils.d.ts +11 -3
- package/lib/components/Timeline/utils.d.ts.map +1 -1
- package/lib/components/Timeline/utils.js +48 -4
- package/lib/components/Timeline/utils.js.map +1 -1
- package/lib/index.d.ts +10 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +10 -2
- package/lib/index.js.map +1 -1
- package/package.json +14 -14
- package/lib/components/CaseActions/CaseActions.d.ts +0 -12
- package/lib/components/CaseActions/CaseActions.d.ts.map +0 -1
- package/lib/components/CaseActions/CaseActions.js +0 -15
- package/lib/components/CaseActions/CaseActions.js.map +0 -1
- package/lib/components/CaseActions/index.d.ts +0 -4
- package/lib/components/CaseActions/index.d.ts.map +0 -1
- package/lib/components/CaseActions/index.js +0 -3
- package/lib/components/CaseActions/index.js.map +0 -1
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef, useContext, useRef, useEffect, useMemo, useState, useCallback } from 'react';
|
|
3
|
+
import styled from 'styled-components';
|
|
4
|
+
import { createPortal } from 'react-dom';
|
|
5
|
+
import { SummaryList, ModalManagerContext, useI18n, Button, ViewAll, Modal, Popover, Flex, Text, useOuterEvent, cap, Progress, useAfterInitialEffect } from '@pega/cosmos-react-core';
|
|
6
|
+
import StakeholderForm from './StakeholderForm';
|
|
7
|
+
const StyledStakeholders = styled(SummaryList) ``;
|
|
8
|
+
const StyledEditFormWrap = styled.div `
|
|
9
|
+
position: relative;
|
|
10
|
+
min-height: 8rem;
|
|
11
|
+
|
|
12
|
+
&[aria-busy='true'] > :nth-child(2) {
|
|
13
|
+
visibility: hidden;
|
|
14
|
+
}
|
|
15
|
+
`;
|
|
16
|
+
const StyledPopover = styled(Popover) `
|
|
17
|
+
width: 40ch;
|
|
18
|
+
min-height: 12rem;
|
|
19
|
+
`;
|
|
20
|
+
const Stakeholders = forwardRef(({ items: itemsProp, count, loading, onAddNew, form, onViewAll, viewAll, error, ...restProps }, ref) => {
|
|
21
|
+
const { create: createModal } = useContext(ModalManagerContext);
|
|
22
|
+
const t = useI18n();
|
|
23
|
+
const modalMethods = useRef();
|
|
24
|
+
const [mode, setMode] = useState();
|
|
25
|
+
const [editing, setEditing] = useState(false);
|
|
26
|
+
const popoverRef = useRef(null);
|
|
27
|
+
const progressMsgRef = useRef(t('loading'));
|
|
28
|
+
// Why? Don't think this should trigger a re-render. We just need the value when we invoke callback props.
|
|
29
|
+
const selectedRoleNameRef = useRef();
|
|
30
|
+
// Setter for the ref. Avoids a re-render.
|
|
31
|
+
const setSelectedRoleNameRef = useCallback((selectedRoleName) => {
|
|
32
|
+
selectedRoleNameRef.current = selectedRoleName;
|
|
33
|
+
}, []);
|
|
34
|
+
const [popoverTarget, setPopoverTarget] = useState(null);
|
|
35
|
+
const itemElsRef = useRef({
|
|
36
|
+
itemEls: [],
|
|
37
|
+
viewAllItemEls: []
|
|
38
|
+
});
|
|
39
|
+
// This function merges the pre-defined actions(add & edit) to the item object.
|
|
40
|
+
const mergeItemActions = (items) => {
|
|
41
|
+
return items.map(({ onEdit, onRemove, ...rest }, i) => {
|
|
42
|
+
let itemActions = [];
|
|
43
|
+
const elArray = itemElsRef.current[mode === 'viewAll' ? 'viewAllItemEls' : 'itemEls'];
|
|
44
|
+
if (onEdit) {
|
|
45
|
+
itemActions = [
|
|
46
|
+
{
|
|
47
|
+
id: 'edit',
|
|
48
|
+
text: t('edit'),
|
|
49
|
+
icon: 'pencil',
|
|
50
|
+
onClick: () => {
|
|
51
|
+
setEditing(true);
|
|
52
|
+
setPopoverTarget({
|
|
53
|
+
portal: elArray[i],
|
|
54
|
+
button: elArray[i].querySelector('button[aria-haspopup="menu"]')
|
|
55
|
+
});
|
|
56
|
+
onEdit?.();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
];
|
|
60
|
+
}
|
|
61
|
+
if (onRemove) {
|
|
62
|
+
itemActions = [
|
|
63
|
+
...itemActions,
|
|
64
|
+
{
|
|
65
|
+
id: 'remove',
|
|
66
|
+
text: t('remove'),
|
|
67
|
+
icon: 'trash',
|
|
68
|
+
onClick: () => {
|
|
69
|
+
onRemove?.();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
];
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
...rest,
|
|
76
|
+
ref: (el) => {
|
|
77
|
+
elArray[i] = el;
|
|
78
|
+
},
|
|
79
|
+
actions: itemActions
|
|
80
|
+
};
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
const closePopover = () => {
|
|
84
|
+
if (!popoverTarget || (form.loading && progressMsgRef.current === t('submitting')))
|
|
85
|
+
return;
|
|
86
|
+
popoverTarget.button?.focus();
|
|
87
|
+
setPopoverTarget(null);
|
|
88
|
+
setEditing(false);
|
|
89
|
+
progressMsgRef.current = t('loading');
|
|
90
|
+
};
|
|
91
|
+
let formContent = null;
|
|
92
|
+
if ((mode === 'add' || editing) &&
|
|
93
|
+
(!form.loading || progressMsgRef.current === t('submitting'))) {
|
|
94
|
+
formContent = (_jsx(StakeholderForm, { roles: form.roles, currentRole: form.currentRole, renderer: form.renderer, rendererProps: form.rendererProps, setSelectedRoleNameRef: setSelectedRoleNameRef }, void 0));
|
|
95
|
+
}
|
|
96
|
+
// Actions used for add and edit both in the modal and the popover.
|
|
97
|
+
let formActions = null;
|
|
98
|
+
if ((mode === 'add' || editing) &&
|
|
99
|
+
(!form.loading || progressMsgRef.current === t('submitting'))) {
|
|
100
|
+
const closeForm = () => {
|
|
101
|
+
if (mode === 'add') {
|
|
102
|
+
modalMethods.current?.dismiss();
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
closePopover();
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
formActions = (_jsxs(_Fragment, { children: [_jsx(Button, { disabled: form.loading, onClick: () => {
|
|
109
|
+
form.onDismiss({ closeForm });
|
|
110
|
+
}, children: t('cancel') }, void 0), _jsx(Button, { disabled: form.loading, type: 'submit', variant: 'primary', onClick: () => {
|
|
111
|
+
progressMsgRef.current = t('submitting');
|
|
112
|
+
form.onSubmit({
|
|
113
|
+
selectedRoleName: selectedRoleNameRef.current,
|
|
114
|
+
closeForm
|
|
115
|
+
});
|
|
116
|
+
}, children: t('submit') }, void 0)] }, void 0));
|
|
117
|
+
}
|
|
118
|
+
// Content for the modal either for adding new or viewing all.
|
|
119
|
+
let modalContent = null;
|
|
120
|
+
if (mode === 'add')
|
|
121
|
+
modalContent = formContent;
|
|
122
|
+
if (!viewAll.loading && (mode === 'viewAll' || (editing && modalMethods.current))) {
|
|
123
|
+
modalContent = (_jsx(ViewAll, { items: mergeItemActions(viewAll.items), actions: [
|
|
124
|
+
{
|
|
125
|
+
id: 'addStakeHolder',
|
|
126
|
+
text: 'Add new',
|
|
127
|
+
onClick: () => {
|
|
128
|
+
setMode('add');
|
|
129
|
+
onAddNew?.();
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
], searchInputProps: viewAll.onSearch
|
|
133
|
+
? {
|
|
134
|
+
onSearchChange: viewAll.onSearch
|
|
135
|
+
}
|
|
136
|
+
: undefined }, void 0));
|
|
137
|
+
}
|
|
138
|
+
useEffect(() => {
|
|
139
|
+
if (!mode) {
|
|
140
|
+
modalMethods.current = undefined;
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
const modalProps = {
|
|
144
|
+
progress: (mode === 'add' && form.loading) || viewAll.loading
|
|
145
|
+
? { message: progressMsgRef.current }
|
|
146
|
+
: undefined,
|
|
147
|
+
count: mode === 'viewAll' ? count : undefined,
|
|
148
|
+
children: modalContent,
|
|
149
|
+
actions: mode === 'add' ? formActions : undefined,
|
|
150
|
+
onRequestDismiss: form.loading && progressMsgRef.current === t('submitting') ? () => false : undefined
|
|
151
|
+
};
|
|
152
|
+
if (modalMethods.current) {
|
|
153
|
+
modalMethods.current.update(modalProps);
|
|
154
|
+
}
|
|
155
|
+
else if (mode === 'add' || mode === 'viewAll') {
|
|
156
|
+
modalMethods.current = createModal(Modal, {
|
|
157
|
+
...modalProps,
|
|
158
|
+
heading: mode === 'add'
|
|
159
|
+
? t('add_noun', [t('stakeholders', [], { count: 1 })])
|
|
160
|
+
: cap(t('stakeholders')),
|
|
161
|
+
onAfterClose: () => {
|
|
162
|
+
if (mode === 'add') {
|
|
163
|
+
form.onAfterClose?.();
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
viewAll.onAfterClose?.();
|
|
167
|
+
}
|
|
168
|
+
progressMsgRef.current = t('loading');
|
|
169
|
+
setMode(undefined);
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}, [mode, modalContent, form.loading, formActions, count, viewAll.loading]);
|
|
174
|
+
// Using mousedown instead of click since drag selecting an input's value within the popover, then releasing outside the popover triggers outer click.
|
|
175
|
+
useOuterEvent('mousedown', [popoverRef], closePopover);
|
|
176
|
+
let editPopover = null;
|
|
177
|
+
if (popoverTarget) {
|
|
178
|
+
editPopover = (_jsx(StyledPopover, { ref: popoverRef, target: popoverTarget.button, placement: 'auto', role: 'dialog', children: _jsxs(Flex, { container: { direction: 'column', gap: 2, pad: 2 }, children: [_jsx(Text, { variant: 'h3', children: t('edit_noun', [t('stakeholders', [], { count: 1 })]) }, void 0), _jsxs(StyledEditFormWrap, { "aria-busy": form.loading ? 'true' : 'false', children: [_jsx(Progress, { placement: 'local', visible: form.loading, message: progressMsgRef.current }, void 0), (!form.loading || progressMsgRef.current === t('submitting')) && (_jsx(StakeholderForm, { roles: form.roles, currentRole: form.currentRole, renderer: form.renderer, rendererProps: form.rendererProps, setSelectedRoleNameRef: setSelectedRoleNameRef }, void 0))] }, void 0), formActions && _jsx(Flex, { container: { justify: 'between' }, children: formActions }, void 0)] }, void 0) }, void 0));
|
|
179
|
+
}
|
|
180
|
+
const onKeydown = (e) => {
|
|
181
|
+
if (e.key === 'Escape') {
|
|
182
|
+
closePopover();
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
useEffect(() => {
|
|
186
|
+
if (!popoverTarget)
|
|
187
|
+
return;
|
|
188
|
+
document.addEventListener('keydown', onKeydown);
|
|
189
|
+
return () => {
|
|
190
|
+
document.removeEventListener('keydown', onKeydown);
|
|
191
|
+
};
|
|
192
|
+
}, [popoverTarget]);
|
|
193
|
+
useAfterInitialEffect(() => {
|
|
194
|
+
if (!popoverTarget)
|
|
195
|
+
form.onAfterClose?.();
|
|
196
|
+
}, [popoverTarget]);
|
|
197
|
+
return (_jsxs(_Fragment, { children: [_jsx(StyledStakeholders, { ...restProps, ref: ref, icon: 'person', name: cap(t('stakeholders')), loading: loading, count: count, error: error, items: useMemo(() => mergeItemActions(itemsProp.slice(0, 3)), [mergeItemActions, itemsProp]), actions: onAddNew
|
|
198
|
+
? [
|
|
199
|
+
{
|
|
200
|
+
text: t('add_noun', [t('stakeholders', [], { count: 1 })]),
|
|
201
|
+
id: 'addNew',
|
|
202
|
+
icon: 'plus',
|
|
203
|
+
onClick() {
|
|
204
|
+
setMode('add');
|
|
205
|
+
onAddNew?.();
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
]
|
|
209
|
+
: undefined, onViewAll: onViewAll && count && count > 3
|
|
210
|
+
? () => {
|
|
211
|
+
setMode('viewAll');
|
|
212
|
+
onViewAll?.();
|
|
213
|
+
}
|
|
214
|
+
: undefined }, void 0), popoverTarget && createPortal(editPopover, popoverTarget.portal)] }, void 0));
|
|
215
|
+
});
|
|
216
|
+
export default Stakeholders;
|
|
217
|
+
//# sourceMappingURL=Stakeholders.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Stakeholders.js","sourceRoot":"","sources":["../../../src/components/Stakeholders/Stakeholders.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n forwardRef,\n FunctionComponent,\n PropsWithoutRef,\n useContext,\n useRef,\n useEffect,\n useMemo,\n useState,\n ReactNode,\n useCallback\n} from 'react';\nimport styled from 'styled-components';\nimport { createPortal } from 'react-dom';\n\nimport {\n SummaryList,\n ModalManagerContext,\n useI18n,\n ModalMethods,\n Button,\n ViewAll,\n Modal,\n Popover,\n Flex,\n Text,\n useOuterEvent,\n cap,\n Progress,\n useAfterInitialEffect\n} from '@pega/cosmos-react-core';\nimport type { Action, ForwardProps, ModalProps, OmitStrict } from '@pega/cosmos-react-core';\n\nimport type { Role, StakeholdersProps } from './Stakeholders.types';\nimport StakeholderForm from './StakeholderForm';\n\nconst StyledStakeholders = styled(SummaryList)``;\n\nconst StyledEditFormWrap = styled.div`\n position: relative;\n min-height: 8rem;\n\n &[aria-busy='true'] > :nth-child(2) {\n visibility: hidden;\n }\n`;\n\nconst StyledPopover = styled(Popover)`\n width: 40ch;\n min-height: 12rem;\n`;\n\nconst Stakeholders: FunctionComponent<StakeholdersProps & ForwardProps> = forwardRef(\n (\n {\n items: itemsProp,\n count,\n loading,\n onAddNew,\n form,\n onViewAll,\n viewAll,\n error,\n ...restProps\n }: PropsWithoutRef<StakeholdersProps>,\n ref: StakeholdersProps['ref']\n ) => {\n const { create: createModal } = useContext(ModalManagerContext);\n const t = useI18n();\n const modalMethods = useRef<ModalMethods>();\n const [mode, setMode] = useState<undefined | 'add' | 'viewAll'>();\n const [editing, setEditing] = useState(false);\n const popoverRef = useRef<HTMLDivElement>(null);\n const progressMsgRef = useRef(t('loading'));\n\n // Why? Don't think this should trigger a re-render. We just need the value when we invoke callback props.\n const selectedRoleNameRef = useRef<Role['name'] | undefined>();\n // Setter for the ref. Avoids a re-render.\n const setSelectedRoleNameRef = useCallback((selectedRoleName?: Role['name']) => {\n selectedRoleNameRef.current = selectedRoleName;\n }, []);\n\n const [popoverTarget, setPopoverTarget] = useState<{\n portal: HTMLLIElement;\n button: HTMLButtonElement | null;\n } | null>(null);\n\n const itemElsRef = useRef<{ itemEls: HTMLLIElement[]; viewAllItemEls: HTMLLIElement[] }>({\n itemEls: [],\n viewAllItemEls: []\n });\n\n // This function merges the pre-defined actions(add & edit) to the item object.\n const mergeItemActions = (\n items: StakeholdersProps['items'] | NonNullable<StakeholdersProps['viewAll']>['items']\n ) => {\n return items.map(({ onEdit, onRemove, ...rest }, i) => {\n let itemActions: Action[] = [];\n const elArray = itemElsRef.current[mode === 'viewAll' ? 'viewAllItemEls' : 'itemEls'];\n\n if (onEdit) {\n itemActions = [\n {\n id: 'edit',\n text: t('edit'),\n icon: 'pencil',\n onClick: () => {\n setEditing(true);\n setPopoverTarget({\n portal: elArray[i],\n button: elArray[i].querySelector<HTMLButtonElement>(\n 'button[aria-haspopup=\"menu\"]'\n )\n });\n\n onEdit?.();\n }\n }\n ];\n }\n\n if (onRemove) {\n itemActions = [\n ...itemActions,\n {\n id: 'remove',\n text: t('remove'),\n icon: 'trash',\n onClick: () => {\n onRemove?.();\n }\n }\n ];\n }\n\n return {\n ...rest,\n ref: (el: HTMLLIElement) => {\n elArray[i] = el;\n },\n actions: itemActions\n };\n });\n };\n\n const closePopover = () => {\n if (!popoverTarget || (form.loading && progressMsgRef.current === t('submitting'))) return;\n popoverTarget.button?.focus();\n setPopoverTarget(null);\n setEditing(false);\n progressMsgRef.current = t('loading');\n };\n\n let formContent: ReactNode = null;\n if (\n (mode === 'add' || editing) &&\n (!form.loading || progressMsgRef.current === t('submitting'))\n ) {\n formContent = (\n <StakeholderForm\n roles={form.roles}\n currentRole={form.currentRole}\n renderer={form.renderer}\n rendererProps={form.rendererProps}\n setSelectedRoleNameRef={setSelectedRoleNameRef}\n />\n );\n }\n\n // Actions used for add and edit both in the modal and the popover.\n let formActions: ReactNode = null;\n if (\n (mode === 'add' || editing) &&\n (!form.loading || progressMsgRef.current === t('submitting'))\n ) {\n const closeForm = () => {\n if (mode === 'add') {\n modalMethods.current?.dismiss();\n } else {\n closePopover();\n }\n };\n\n formActions = (\n <>\n <Button\n disabled={form.loading}\n onClick={() => {\n form.onDismiss({ closeForm });\n }}\n >\n {t('cancel')}\n </Button>\n <Button\n disabled={form.loading}\n type='submit'\n variant='primary'\n onClick={() => {\n progressMsgRef.current = t('submitting');\n form.onSubmit({\n selectedRoleName: selectedRoleNameRef.current,\n closeForm\n });\n }}\n >\n {t('submit')}\n </Button>\n </>\n );\n }\n\n // Content for the modal either for adding new or viewing all.\n let modalContent: ReactNode = null;\n if (mode === 'add') modalContent = formContent;\n\n if (!viewAll.loading && (mode === 'viewAll' || (editing && modalMethods.current))) {\n modalContent = (\n <ViewAll\n items={mergeItemActions(viewAll.items)}\n actions={[\n {\n id: 'addStakeHolder',\n text: 'Add new',\n onClick: () => {\n setMode('add');\n onAddNew?.();\n }\n }\n ]}\n searchInputProps={\n viewAll.onSearch\n ? {\n onSearchChange: viewAll.onSearch\n }\n : undefined\n }\n />\n );\n }\n\n useEffect(() => {\n if (!mode) {\n modalMethods.current = undefined;\n return;\n }\n\n const modalProps: OmitStrict<ModalProps, 'heading'> = {\n progress:\n (mode === 'add' && form.loading) || viewAll.loading\n ? { message: progressMsgRef.current }\n : undefined,\n count: mode === 'viewAll' ? count : undefined,\n children: modalContent,\n actions: mode === 'add' ? formActions : undefined,\n onRequestDismiss:\n form.loading && progressMsgRef.current === t('submitting') ? () => false : undefined\n };\n\n if (modalMethods.current) {\n modalMethods.current.update(modalProps);\n } else if (mode === 'add' || mode === 'viewAll') {\n modalMethods.current = createModal(Modal, {\n ...modalProps,\n heading:\n mode === 'add'\n ? t('add_noun', [t('stakeholders', [], { count: 1 })])\n : cap(t('stakeholders')),\n onAfterClose: () => {\n if (mode === 'add') {\n form.onAfterClose?.();\n } else {\n viewAll.onAfterClose?.();\n }\n\n progressMsgRef.current = t('loading');\n setMode(undefined);\n }\n });\n }\n }, [mode, modalContent, form.loading, formActions, count, viewAll.loading]);\n\n // Using mousedown instead of click since drag selecting an input's value within the popover, then releasing outside the popover triggers outer click.\n useOuterEvent('mousedown', [popoverRef], closePopover);\n\n let editPopover: ReactNode = null;\n if (popoverTarget) {\n editPopover = (\n <StyledPopover\n ref={popoverRef}\n target={popoverTarget.button}\n placement='auto'\n role='dialog'\n >\n <Flex container={{ direction: 'column', gap: 2, pad: 2 }}>\n <Text variant='h3'>{t('edit_noun', [t('stakeholders', [], { count: 1 })])}</Text>\n <StyledEditFormWrap aria-busy={form.loading ? 'true' : 'false'}>\n <Progress placement='local' visible={form.loading} message={progressMsgRef.current} />\n {(!form.loading || progressMsgRef.current === t('submitting')) && (\n <StakeholderForm\n roles={form.roles}\n currentRole={form.currentRole}\n renderer={form.renderer}\n rendererProps={form.rendererProps}\n setSelectedRoleNameRef={setSelectedRoleNameRef}\n />\n )}\n </StyledEditFormWrap>\n {formActions && <Flex container={{ justify: 'between' }}>{formActions}</Flex>}\n </Flex>\n </StyledPopover>\n );\n }\n\n const onKeydown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n closePopover();\n }\n };\n\n useEffect(() => {\n if (!popoverTarget) return;\n document.addEventListener('keydown', onKeydown);\n return () => {\n document.removeEventListener('keydown', onKeydown);\n };\n }, [popoverTarget]);\n\n useAfterInitialEffect(() => {\n if (!popoverTarget) form.onAfterClose?.();\n }, [popoverTarget]);\n\n return (\n <>\n <StyledStakeholders\n {...restProps}\n ref={ref}\n icon='person'\n name={cap(t('stakeholders'))}\n loading={loading}\n count={count}\n error={error}\n items={useMemo(\n () => mergeItemActions(itemsProp.slice(0, 3)),\n [mergeItemActions, itemsProp]\n )}\n actions={\n onAddNew\n ? [\n {\n text: t('add_noun', [t('stakeholders', [], { count: 1 })]),\n id: 'addNew',\n icon: 'plus',\n onClick() {\n setMode('add');\n onAddNew?.();\n }\n }\n ]\n : undefined\n }\n onViewAll={\n onViewAll && count && count > 3\n ? () => {\n setMode('viewAll');\n onViewAll?.();\n }\n : undefined\n }\n />\n {popoverTarget && createPortal(editPopover, popoverTarget.portal)}\n </>\n );\n }\n);\n\nexport default Stakeholders;\n"]}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { ComponentType } from 'react';
|
|
2
|
+
import type { SummaryListProps, ForwardProps, NoChildrenProp, SummaryListItem } from '@pega/cosmos-react-core';
|
|
3
|
+
export declare type Role = {
|
|
4
|
+
name: string;
|
|
5
|
+
description: string;
|
|
6
|
+
};
|
|
7
|
+
/** A simple extension of a SummaryListItem. Pass onEdit and or onRemove to render either action for a stakeholder. */
|
|
8
|
+
export interface Stakeholder extends SummaryListItem, ForwardProps {
|
|
9
|
+
onEdit?: () => void;
|
|
10
|
+
onRemove?: () => void;
|
|
11
|
+
}
|
|
12
|
+
export interface StakeholdersProps extends NoChildrenProp, Pick<SummaryListProps, 'count' | 'loading' | 'error' | 'ref'> {
|
|
13
|
+
/**
|
|
14
|
+
* The initial array of stakeholders presented in the default state of the widget.
|
|
15
|
+
* This array will be sliced internally to the first three items but recommend only passing up to that length as a best practice.
|
|
16
|
+
*/
|
|
17
|
+
items: Stakeholder[];
|
|
18
|
+
/** Called when a user opens the add form. */
|
|
19
|
+
onAddNew?: () => void;
|
|
20
|
+
/**
|
|
21
|
+
* Data and a component required to render a form for both add and edit.
|
|
22
|
+
* If there are roles, the renderer is passed the currently selected role.
|
|
23
|
+
*/
|
|
24
|
+
form: {
|
|
25
|
+
/** Indicates the form is in a loading state either initially or after add/edit is submitted. */
|
|
26
|
+
loading?: boolean;
|
|
27
|
+
/** An array of available roles a stakeholder may be assigned. */
|
|
28
|
+
roles?: Role[];
|
|
29
|
+
/**
|
|
30
|
+
* Use this when onAdd or onEdit is invoked to indicate to the component which role option to select.
|
|
31
|
+
*/
|
|
32
|
+
currentRole?: Role;
|
|
33
|
+
/**
|
|
34
|
+
* A component to render the main portion of the add/edit stakeholder form.
|
|
35
|
+
* This may be a simple function and will be pass a prop when the selected role changes.
|
|
36
|
+
*/
|
|
37
|
+
renderer: ComponentType<{
|
|
38
|
+
selectedRoleName?: Role['name'];
|
|
39
|
+
}>;
|
|
40
|
+
/**
|
|
41
|
+
* A props object that will be passed to the form renderer.
|
|
42
|
+
*/
|
|
43
|
+
rendererProps?: {
|
|
44
|
+
[key: string]: unknown;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Called when a user submits the form.
|
|
48
|
+
* The name of the currently selected role will be passed along with a function to close the form on an arg object.
|
|
49
|
+
* closeForm will close the modal or popover the form is preseneted in.
|
|
50
|
+
* closeForm can be call once validations and requests have resolved.
|
|
51
|
+
*/
|
|
52
|
+
onSubmit: ({ selectedRoleName, closeForm }: {
|
|
53
|
+
selectedRoleName: Role['name'] | undefined;
|
|
54
|
+
closeForm: () => void;
|
|
55
|
+
}) => void;
|
|
56
|
+
/**
|
|
57
|
+
* Called when a user cancels a form.
|
|
58
|
+
* A function to close the form will be passed on an arg object.
|
|
59
|
+
*/
|
|
60
|
+
onDismiss: ({ closeForm }: {
|
|
61
|
+
closeForm: () => void;
|
|
62
|
+
}) => void;
|
|
63
|
+
/**
|
|
64
|
+
* Called after the modal or popover transitions and un-mounts as a result of a closeForm call or user dismissal.
|
|
65
|
+
*/
|
|
66
|
+
onAfterClose?: () => void;
|
|
67
|
+
};
|
|
68
|
+
/** Called when a user opens the view all modal. */
|
|
69
|
+
onViewAll?: () => void;
|
|
70
|
+
viewAll: {
|
|
71
|
+
/** Indicates the view all list is in a loading state while data is fetched. */
|
|
72
|
+
loading?: boolean;
|
|
73
|
+
/** Pass a full or filtered list of stakeholder items. Filter based on search input. */
|
|
74
|
+
items: StakeholdersProps['items'];
|
|
75
|
+
/** Called when a user enters a view all search. Return a filtered array to viewAll['items'] with matching stakeholders. */
|
|
76
|
+
onSearch?: (value: string) => void;
|
|
77
|
+
/**
|
|
78
|
+
* Called after the modal or popover transitions and un-mounts as a result of a closeForm call or user dismissal.
|
|
79
|
+
*/
|
|
80
|
+
onAfterClose?: () => void;
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=Stakeholders.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Stakeholders.types.d.ts","sourceRoot":"","sources":["../../../src/components/Stakeholders/Stakeholders.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,OAAO,KAAK,EACV,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,eAAe,EAChB,MAAM,yBAAyB,CAAC;AAEjC,oBAAY,IAAI,GAAG;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,sHAAsH;AACtH,MAAM,WAAW,WAAY,SAAQ,eAAe,EAAE,YAAY;IAChE,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,iBACf,SAAQ,cAAc,EACpB,IAAI,CAAC,gBAAgB,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,KAAK,CAAC;IAC/D;;;OAGG;IACH,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB;;;OAGG;IACH,IAAI,EAAE;QACJ,gGAAgG;QAChG,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,iEAAiE;QACjE,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;QACf;;WAEG;QACH,WAAW,CAAC,EAAE,IAAI,CAAC;QACnB;;;WAGG;QACH,QAAQ,EAAE,aAAa,CAAC;YAAE,gBAAgB,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;SAAE,CAAC,CAAC;QAC7D;;WAEG;QACH,aAAa,CAAC,EAAE;YACd,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;SACxB,CAAC;QACF;;;;;WAKG;QACH,QAAQ,EAAE,CAAC,EACT,gBAAgB,EAChB,SAAS,EACV,EAAE;YACD,gBAAgB,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;YAC3C,SAAS,EAAE,MAAM,IAAI,CAAC;SACvB,KAAK,IAAI,CAAC;QACX;;;WAGG;QACH,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE;YAAE,SAAS,EAAE,MAAM,IAAI,CAAA;SAAE,KAAK,IAAI,CAAC;QAC9D;;WAEG;QACH,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;KAC3B,CAAC;IACF,mDAAmD;IACnD,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,OAAO,EAAE;QACP,+EAA+E;QAC/E,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,uFAAuF;QACvF,KAAK,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAClC,2HAA2H;QAC3H,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;QACnC;;WAEG;QACH,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;KAC3B,CAAC;CACH"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Stakeholders.types.js","sourceRoot":"","sources":["../../../src/components/Stakeholders/Stakeholders.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ComponentType } from 'react';\n\nimport type {\n SummaryListProps,\n ForwardProps,\n NoChildrenProp,\n SummaryListItem\n} from '@pega/cosmos-react-core';\n\nexport type Role = {\n name: string;\n description: string;\n};\n\n/** A simple extension of a SummaryListItem. Pass onEdit and or onRemove to render either action for a stakeholder. */\nexport interface Stakeholder extends SummaryListItem, ForwardProps {\n onEdit?: () => void;\n onRemove?: () => void;\n}\n\nexport interface StakeholdersProps\n extends NoChildrenProp,\n Pick<SummaryListProps, 'count' | 'loading' | 'error' | 'ref'> {\n /**\n * The initial array of stakeholders presented in the default state of the widget.\n * This array will be sliced internally to the first three items but recommend only passing up to that length as a best practice.\n */\n items: Stakeholder[];\n /** Called when a user opens the add form. */\n onAddNew?: () => void;\n /**\n * Data and a component required to render a form for both add and edit.\n * If there are roles, the renderer is passed the currently selected role.\n */\n form: {\n /** Indicates the form is in a loading state either initially or after add/edit is submitted. */\n loading?: boolean;\n /** An array of available roles a stakeholder may be assigned. */\n roles?: Role[];\n /**\n * Use this when onAdd or onEdit is invoked to indicate to the component which role option to select.\n */\n currentRole?: Role;\n /**\n * A component to render the main portion of the add/edit stakeholder form.\n * This may be a simple function and will be pass a prop when the selected role changes.\n */\n renderer: ComponentType<{ selectedRoleName?: Role['name'] }>;\n /**\n * A props object that will be passed to the form renderer.\n */\n rendererProps?: {\n [key: string]: unknown;\n };\n /**\n * Called when a user submits the form.\n * The name of the currently selected role will be passed along with a function to close the form on an arg object.\n * closeForm will close the modal or popover the form is preseneted in.\n * closeForm can be call once validations and requests have resolved.\n */\n onSubmit: ({\n selectedRoleName,\n closeForm\n }: {\n selectedRoleName: Role['name'] | undefined;\n closeForm: () => void;\n }) => void;\n /**\n * Called when a user cancels a form.\n * A function to close the form will be passed on an arg object.\n */\n onDismiss: ({ closeForm }: { closeForm: () => void }) => void;\n /**\n * Called after the modal or popover transitions and un-mounts as a result of a closeForm call or user dismissal.\n */\n onAfterClose?: () => void;\n };\n /** Called when a user opens the view all modal. */\n onViewAll?: () => void;\n viewAll: {\n /** Indicates the view all list is in a loading state while data is fetched. */\n loading?: boolean;\n /** Pass a full or filtered list of stakeholder items. Filter based on search input. */\n items: StakeholdersProps['items'];\n /** Called when a user enters a view all search. Return a filtered array to viewAll['items'] with matching stakeholders. */\n onSearch?: (value: string) => void;\n /**\n * Called after the modal or popover transitions and un-mounts as a result of a closeForm call or user dismissal.\n */\n onAfterClose?: () => void;\n };\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Stakeholders/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/Stakeholders/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC","sourcesContent":["export { default } from './Stakeholders';\nexport { StakeholdersProps } from './Stakeholders.types';\n"]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { FunctionComponent, Ref } from 'react';
|
|
2
|
+
import { BaseProps, ForwardProps, ErrorStateProps } from '@pega/cosmos-react-core';
|
|
3
|
+
export interface SelectedTag {
|
|
4
|
+
text: string;
|
|
5
|
+
newTag?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface TagsProps extends BaseProps {
|
|
8
|
+
/** A list of tags. */
|
|
9
|
+
tags: string[];
|
|
10
|
+
/**
|
|
11
|
+
* A list of available tags to add from.
|
|
12
|
+
* @default []
|
|
13
|
+
* */
|
|
14
|
+
availableTags?: string[];
|
|
15
|
+
/** If true, a loading indicator will render in place of the tags list. */
|
|
16
|
+
loading?: boolean;
|
|
17
|
+
/** If defined, an error message will render in the component and actions will be disabled. */
|
|
18
|
+
error?: boolean | string | ErrorStateProps;
|
|
19
|
+
/** Callback triggered when a search query is changed in the Edit tags modal. */
|
|
20
|
+
onSearch?: (filterValue: string) => void;
|
|
21
|
+
/** Callback triggered when a tag is clicked. */
|
|
22
|
+
onTagClick?: (tag: string) => void;
|
|
23
|
+
/** Callback triggered when modified tags are submitted from the modal. */
|
|
24
|
+
onEditTags?: (tags: SelectedTag[]) => Promise<void>;
|
|
25
|
+
/** Ref for the Tags card. */
|
|
26
|
+
ref?: Ref<HTMLElement>;
|
|
27
|
+
}
|
|
28
|
+
export declare const StyledTags: import("styled-components").StyledComponent<"article", import("styled-components").DefaultTheme, {
|
|
29
|
+
isLoading?: boolean | undefined;
|
|
30
|
+
viewAll?: boolean | undefined;
|
|
31
|
+
}, never>;
|
|
32
|
+
declare const Tags: FunctionComponent<TagsProps & ForwardProps>;
|
|
33
|
+
export default Tags;
|
|
34
|
+
//# sourceMappingURL=Tags.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Tags.d.ts","sourceRoot":"","sources":["../../../src/components/Tags/Tags.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,iBAAiB,EAEjB,GAAG,EAMJ,MAAM,OAAO,CAAC;AAGf,OAAO,EAEL,SAAS,EACT,YAAY,EAyBZ,eAAe,EAChB,MAAM,yBAAyB,CAAC;AASjC,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,SAAU,SAAQ,SAAS;IAC1C,sBAAsB;IACtB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf;;;SAGK;IACL,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,0EAA0E;IAC1E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,8FAA8F;IAC9F,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,eAAe,CAAC;IAC3C,gFAAgF;IAChF,QAAQ,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,gDAAgD;IAChD,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,0EAA0E;IAC1E,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,6BAA6B;IAC7B,GAAG,CAAC,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC;CACxB;AASD,eAAO,MAAM,UAAU;;;SAwBtB,CAAC;AAgMF,QAAA,MAAM,IAAI,EAAE,iBAAiB,CAAC,SAAS,GAAG,YAAY,CA+HrD,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef, useContext, useMemo, useState, useEffect, useRef } from 'react';
|
|
3
|
+
import styled, { css } from 'styled-components';
|
|
4
|
+
import { defaultThemeProp, Modal, ModalManagerContext, Tag, Button, useI18n, Count, Flex, Text, CardHeader, Card, Actions, Icon, registerIcon, CardContent, Progress, EmptyState, ErrorState, Popover, Menu, useConsolidatedRef, CardFooter, Banner } from '@pega/cosmos-react-core';
|
|
5
|
+
import * as tagIcon from '@pega/cosmos-react-core/lib/components/Icon/icons/tag.icon';
|
|
6
|
+
import { StyledTag } from '@pega/cosmos-react-core/lib/components/Badges/Tag';
|
|
7
|
+
import { StyledCardContent } from '@pega/cosmos-react-core/lib/components/Card/CardContent';
|
|
8
|
+
import MultiSelectInput from '@pega/cosmos-react-core/lib/components/ComboBox/MultiSelectInput/MultiSelectInput';
|
|
9
|
+
import { StyledCardFooter } from '@pega/cosmos-react-core/lib/components/Card/CardFooter';
|
|
10
|
+
registerIcon(tagIcon);
|
|
11
|
+
export const StyledTags = styled.article(({ isLoading, theme, viewAll }) => {
|
|
12
|
+
return css `
|
|
13
|
+
${StyledCardContent} {
|
|
14
|
+
max-height: ${viewAll ? 'fit-content' : '10rem'};
|
|
15
|
+
overflow-y: hidden;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
${StyledCardFooter} {
|
|
19
|
+
margin-block-start: ${theme.base.spacing};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
${StyledTag} {
|
|
23
|
+
cursor: pointer;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
${isLoading &&
|
|
27
|
+
css `
|
|
28
|
+
& > ${StyledCardContent} {
|
|
29
|
+
height: 4rem;
|
|
30
|
+
}
|
|
31
|
+
`}
|
|
32
|
+
`;
|
|
33
|
+
});
|
|
34
|
+
StyledTags.defaultProps = defaultThemeProp;
|
|
35
|
+
const StyledMenuPopover = styled.div `
|
|
36
|
+
width: 40ch;
|
|
37
|
+
`;
|
|
38
|
+
const StyledBanner = styled(Banner)(({ theme }) => {
|
|
39
|
+
return css `
|
|
40
|
+
padding-block-end: calc(2 * ${theme.base.spacing});
|
|
41
|
+
`;
|
|
42
|
+
});
|
|
43
|
+
StyledBanner.defaultProps = defaultThemeProp;
|
|
44
|
+
const EditTagModal = ({ tags, availableTags = [], onSearch, onEditTags }) => {
|
|
45
|
+
const { ModalContext } = useContext(ModalManagerContext);
|
|
46
|
+
const { dismiss } = useContext(ModalContext);
|
|
47
|
+
const inputRef = useRef(null);
|
|
48
|
+
const [filterValue, setFilterValue] = useState('');
|
|
49
|
+
const [editError, setEditError] = useState('');
|
|
50
|
+
const [selected, setSelected] = useState([]);
|
|
51
|
+
const [items, setItems] = useState([]);
|
|
52
|
+
const t = useI18n();
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
setSelected(tags.map(tag => {
|
|
55
|
+
return { text: tag };
|
|
56
|
+
}));
|
|
57
|
+
}, [tags]);
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
const menuItems = availableTags
|
|
60
|
+
.filter(tag => !selected.some(x => x.text === tag))
|
|
61
|
+
.map(tag => {
|
|
62
|
+
return { id: tag, primary: tag };
|
|
63
|
+
});
|
|
64
|
+
if (filterValue &&
|
|
65
|
+
!menuItems.some(x => x.id === filterValue) &&
|
|
66
|
+
!selected.some(x => x.text === filterValue)) {
|
|
67
|
+
menuItems.push({
|
|
68
|
+
id: `custom:${filterValue}`,
|
|
69
|
+
primary: t('use_input_value', [filterValue])
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
setItems(menuItems);
|
|
73
|
+
}, [availableTags, filterValue, selected]);
|
|
74
|
+
const setInputValue = (value) => {
|
|
75
|
+
setEditError('');
|
|
76
|
+
setFilterValue(value);
|
|
77
|
+
onSearch?.(value);
|
|
78
|
+
};
|
|
79
|
+
const addTag = (tag) => {
|
|
80
|
+
if (tag && !selected.find(x => x.text === tag)) {
|
|
81
|
+
if (items.find(x => x.id === tag)) {
|
|
82
|
+
setSelected(curr => [...curr, { text: tag }]);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
setSelected(curr => [...curr, { text: tag, newTag: true }]);
|
|
86
|
+
}
|
|
87
|
+
setInputValue('');
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
const handlePaste = (e) => {
|
|
91
|
+
const potentialTags = e.clipboardData.getData('Text').split(' ');
|
|
92
|
+
potentialTags.forEach(potentialTag => {
|
|
93
|
+
addTag(potentialTag);
|
|
94
|
+
});
|
|
95
|
+
};
|
|
96
|
+
const handleKeyDown = (e) => {
|
|
97
|
+
if (e.key === ' ') {
|
|
98
|
+
addTag(filterValue);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
return (_jsxs(Modal, { heading: t('edit_tags'), actions: _jsxs(_Fragment, { children: [_jsx(Button, { onClick: dismiss, children: t('cancel') }, void 0), _jsx(Button, { variant: 'primary', onClick: () => {
|
|
102
|
+
onEditTags(selected)
|
|
103
|
+
.then(dismiss)
|
|
104
|
+
.catch((error) => {
|
|
105
|
+
if (error instanceof Error) {
|
|
106
|
+
setEditError(error.message || t('unknown_error'));
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
setEditError(t('unknown_error'));
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}, children: t('submit') }, void 0)] }, void 0), children: [editError && (_jsx(StyledBanner, { id: 'edit-tags-error', variant: 'urgent', messages: [editError], onDismiss: () => {
|
|
113
|
+
setEditError('');
|
|
114
|
+
} }, void 0)), _jsx(MultiSelectInput, { ref: inputRef, selected: selected.map(({ text }) => {
|
|
115
|
+
return { id: text, text };
|
|
116
|
+
}), value: filterValue, onChange: (e) => {
|
|
117
|
+
setInputValue(e.target.value.trim());
|
|
118
|
+
}, onRemove: (id, index) => {
|
|
119
|
+
if (selected[index].text === id) {
|
|
120
|
+
const updatedSelected = [...selected];
|
|
121
|
+
updatedSelected.splice(index, 1);
|
|
122
|
+
setSelected(updatedSelected);
|
|
123
|
+
setEditError('');
|
|
124
|
+
}
|
|
125
|
+
}, onBlur: () => {
|
|
126
|
+
setInputValue('');
|
|
127
|
+
}, onPaste: handlePaste, onKeyDown: handleKeyDown, autoFocus: true }, void 0), _jsx(Popover, { as: StyledMenuPopover, show: !!filterValue && !!items?.length, target: inputRef.current, placement: 'bottom-start', modifiers: [
|
|
128
|
+
{
|
|
129
|
+
name: 'flip',
|
|
130
|
+
enabled: true,
|
|
131
|
+
options: {
|
|
132
|
+
fallbackPlacements: ['top-start']
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
name: 'preventOverflow',
|
|
137
|
+
enabled: true
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
name: 'hide',
|
|
141
|
+
enabled: false
|
|
142
|
+
}
|
|
143
|
+
], onMouseDown: (e) => e.preventDefault(), children: _jsx(Menu, { role: 'listbox', mode: 'action', items: items, focusControlEl: inputRef.current || undefined, onItemClick: id => {
|
|
144
|
+
if (id.includes('custom:')) {
|
|
145
|
+
const tagValue = id.replace('custom:', '');
|
|
146
|
+
if (!selected.some(x => x.text === tagValue)) {
|
|
147
|
+
setSelected(curr => [...curr, { text: tagValue, newTag: true }]);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
setSelected(curr => [...curr, { text: id }]);
|
|
152
|
+
}
|
|
153
|
+
setInputValue('');
|
|
154
|
+
}, arrowNavigationUnsupported: true }, void 0) }, void 0)] }, void 0));
|
|
155
|
+
};
|
|
156
|
+
const Tags = forwardRef(({ tags, availableTags, loading, error, onSearch, onTagClick, onEditTags, ...restProps }, ref) => {
|
|
157
|
+
const { create: createModal } = useContext(ModalManagerContext);
|
|
158
|
+
const editModalMethods = useRef();
|
|
159
|
+
const containerRef = useRef(null);
|
|
160
|
+
const contentRef = useRef(null);
|
|
161
|
+
const consolidatedRef = useConsolidatedRef(containerRef, ref);
|
|
162
|
+
const [footer, setFooter] = useState(false);
|
|
163
|
+
const [viewAll, setViewAll] = useState(false);
|
|
164
|
+
const t = useI18n();
|
|
165
|
+
useEffect(() => {
|
|
166
|
+
if (containerRef.current && contentRef.current) {
|
|
167
|
+
if (contentRef.current.getBoundingClientRect().bottom >
|
|
168
|
+
containerRef.current.getBoundingClientRect().bottom) {
|
|
169
|
+
setFooter(true);
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
setFooter(false);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}, [containerRef.current, contentRef.current, tags]);
|
|
176
|
+
useEffect(() => {
|
|
177
|
+
if (!onEditTags) {
|
|
178
|
+
editModalMethods.current?.dismiss();
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
editModalMethods.current?.update({
|
|
182
|
+
tags,
|
|
183
|
+
availableTags,
|
|
184
|
+
onSearch,
|
|
185
|
+
onEditTags
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
}, [availableTags, tags, onSearch, onEditTags]);
|
|
189
|
+
const openEditModal = () => {
|
|
190
|
+
if (!onEditTags)
|
|
191
|
+
return;
|
|
192
|
+
editModalMethods.current = createModal(EditTagModal, {
|
|
193
|
+
tags,
|
|
194
|
+
availableTags,
|
|
195
|
+
onSearch,
|
|
196
|
+
onEditTags
|
|
197
|
+
});
|
|
198
|
+
};
|
|
199
|
+
const content = useMemo(() => {
|
|
200
|
+
if (loading) {
|
|
201
|
+
return _jsx(Progress, { placement: 'local' }, void 0);
|
|
202
|
+
}
|
|
203
|
+
if (error) {
|
|
204
|
+
if (typeof error === 'boolean')
|
|
205
|
+
return _jsx(ErrorState, {}, void 0);
|
|
206
|
+
if (typeof error === 'string')
|
|
207
|
+
return _jsx(ErrorState, { message: error }, void 0);
|
|
208
|
+
return _jsx(ErrorState, { ...error }, void 0);
|
|
209
|
+
}
|
|
210
|
+
return tags.length > 0 ? (_jsx(Flex, { ref: contentRef, container: { gap: 1, wrap: 'wrap' }, children: tags.map(tag => {
|
|
211
|
+
return (_jsx(Tag, { onClick: () => onTagClick?.(tag), children: tag }, tag));
|
|
212
|
+
}) }, void 0)) : (_jsx(EmptyState, {}, void 0));
|
|
213
|
+
}, [loading, error, tags]);
|
|
214
|
+
return (_jsxs(Card, { ref: consolidatedRef, ...restProps, as: StyledTags, viewAll: viewAll, isLoading: loading, children: [_jsxs(CardHeader, { children: [_jsxs(Flex, { container: { alignItems: 'center', gap: 1 }, children: [_jsx(Icon, { name: 'tag' }, void 0), _jsx(Text, { variant: 'h2', children: t('tags') }, void 0), _jsx(Count, { children: tags.length }, void 0)] }, void 0), _jsx(Actions, { items: onEditTags
|
|
215
|
+
? [
|
|
216
|
+
{
|
|
217
|
+
id: 'editTags',
|
|
218
|
+
text: t('edit_tags'),
|
|
219
|
+
icon: 'pencil',
|
|
220
|
+
onClick: openEditModal,
|
|
221
|
+
disabled: !!error
|
|
222
|
+
}
|
|
223
|
+
]
|
|
224
|
+
: [] }, void 0)] }, void 0), _jsx(CardContent, { children: content }, void 0), footer && (_jsx(CardFooter, { justify: 'center', children: _jsx(Button, { variant: 'link', onClick: () => setViewAll(curr => !curr), children: viewAll ? t('view_less') : t('view_all') }, void 0) }, void 0))] }, void 0));
|
|
225
|
+
});
|
|
226
|
+
export default Tags;
|
|
227
|
+
//# sourceMappingURL=Tags.js.map
|