@oneblink/apps-react 6.9.0-beta.2 → 6.9.0-beta.4

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.
@@ -0,0 +1,178 @@
1
+ import { IconButton, Collapse, Tooltip } from '@mui/material';
2
+ import * as React from 'react';
3
+ import MaterialIcon from './MaterialIcon';
4
+ import useBooleanState from '../hooks/useBooleanState';
5
+ import clsx from 'clsx';
6
+ import useFormDefinition from '../hooks/useFormDefinition';
7
+ const NO_PAGE_KEY = 'NO_PAGE';
8
+ const getValidationErrors = ({ formElementsValidation, elements, page, idPrefix, }) => {
9
+ return elements.reduce((memo, el) => {
10
+ switch (el.type) {
11
+ case 'page': {
12
+ memo.push(...getValidationErrors({
13
+ formElementsValidation,
14
+ elements: el.elements,
15
+ page: el,
16
+ idPrefix,
17
+ }));
18
+ break;
19
+ }
20
+ case 'section': {
21
+ memo.push(...getValidationErrors({
22
+ formElementsValidation,
23
+ elements: el.elements,
24
+ page,
25
+ idPrefix,
26
+ }));
27
+ break;
28
+ }
29
+ case 'repeatableSet': {
30
+ const validationData = formElementsValidation[el.name];
31
+ if (!!validationData &&
32
+ typeof validationData !== 'string' &&
33
+ validationData.type === 'repeatableSet') {
34
+ if (validationData.set) {
35
+ memo.push({
36
+ id: `${idPrefix}${el.name}-label`,
37
+ errorMessage: validationData.set,
38
+ label: el.label,
39
+ page,
40
+ });
41
+ }
42
+ for (const [key, entry] of Object.entries(validationData.entries)) {
43
+ if (!entry)
44
+ continue;
45
+ memo.push(...getValidationErrors({
46
+ formElementsValidation: entry,
47
+ elements: el.elements,
48
+ page,
49
+ idPrefix: `${idPrefix}${el.name}_entry-${key}_`,
50
+ }));
51
+ }
52
+ }
53
+ break;
54
+ }
55
+ case 'infoPage':
56
+ case 'form': {
57
+ const validationData = formElementsValidation[el.name];
58
+ if (!!validationData &&
59
+ typeof validationData !== 'string' &&
60
+ validationData.type === 'formElements') {
61
+ if (validationData.formElements && el.elements) {
62
+ memo.push(...getValidationErrors({
63
+ formElementsValidation: validationData.formElements,
64
+ elements: el.elements,
65
+ page,
66
+ idPrefix: `${idPrefix}${el.name}_`,
67
+ }));
68
+ }
69
+ }
70
+ break;
71
+ }
72
+ default: {
73
+ const validationMessage = formElementsValidation[el.name];
74
+ if (typeof validationMessage === 'string') {
75
+ memo.push({
76
+ id: `${idPrefix}${el.name}`,
77
+ label: el.label,
78
+ page,
79
+ errorMessage: validationMessage,
80
+ });
81
+ }
82
+ }
83
+ }
84
+ return memo;
85
+ }, []);
86
+ };
87
+ const ValidationErrorsCard = ({ formElementsValidation, currentPage, setPageId, }) => {
88
+ const [isExpanded, expand, contract] = useBooleanState(false);
89
+ const form = useFormDefinition();
90
+ const pagesWithValidationErrors = React.useMemo(() => {
91
+ if (!formElementsValidation)
92
+ return [];
93
+ const flatErrors = getValidationErrors({
94
+ formElementsValidation,
95
+ elements: form.elements,
96
+ idPrefix: '',
97
+ });
98
+ // Organise into pages
99
+ const pages = new Map();
100
+ for (const error of flatErrors) {
101
+ if (error.page) {
102
+ // If error belongs to a page
103
+ const existingSetEntry = pages.get(error.page.id);
104
+ const errors = [...((existingSetEntry === null || existingSetEntry === void 0 ? void 0 : existingSetEntry.errors) || []), error];
105
+ const page = error.page;
106
+ pages.set(page.id, {
107
+ page,
108
+ errors,
109
+ });
110
+ }
111
+ else {
112
+ // No page associated with error
113
+ const existingSetEntry = pages.get(NO_PAGE_KEY);
114
+ const errors = [...((existingSetEntry === null || existingSetEntry === void 0 ? void 0 : existingSetEntry.errors) || []), error];
115
+ pages.set(NO_PAGE_KEY, {
116
+ page: undefined,
117
+ errors,
118
+ });
119
+ }
120
+ }
121
+ return Array.from(pages.values());
122
+ }, [form.elements, formElementsValidation]);
123
+ return (React.createElement("div", { className: "ob-validation-notification-wrapper" },
124
+ React.createElement("div", { className: clsx('ob-validation-notification-card cypress-invalid-submit-attempt', {
125
+ 'is-clickable': !isExpanded,
126
+ 'is-contracted': !isExpanded,
127
+ 'is-expanded': isExpanded,
128
+ }), onClick: !isExpanded ? expand : undefined },
129
+ React.createElement("div", { className: "ob-validation-notification-card-content" },
130
+ React.createElement("div", { className: "ob-validation-notification-card-header-wrapper" },
131
+ React.createElement("div", { className: "ob-validation-notification-card-header-title-wrapper" },
132
+ React.createElement(MaterialIcon, { className: clsx('ob-validation-notification-card-header-title-icon ob-validation-color-transition', {
133
+ 'has-text-danger': isExpanded,
134
+ 'has-text-white': !isExpanded,
135
+ }) }, "error"),
136
+ React.createElement("p", { className: clsx('ob-validation-color-transition ob-validation-notification-card-header-title-text', {
137
+ 'has-text-danger': isExpanded,
138
+ 'has-text-white': !isExpanded,
139
+ }) }, "Validation Errors")),
140
+ React.createElement("div", { className: "ob-validation-notification-card-header-collapse-icon-wrapper" }, isExpanded ? (React.createElement(IconButton, { onClick: contract },
141
+ React.createElement(MaterialIcon, { className: "icon-small" }, "expand_more"))) : (React.createElement(IconButton, null,
142
+ React.createElement(MaterialIcon, { className: "icon-small has-text-white" }, "expand_less"))))),
143
+ React.createElement("div", { className: "ob-validation-notification-card-collapse-wrapper" },
144
+ React.createElement(Collapse, { in: isExpanded }, pagesWithValidationErrors.map(({ page, errors }, pageIndex) => {
145
+ const isNotFirstPage = pageIndex > 0;
146
+ return (React.createElement(React.Fragment, null,
147
+ page && (React.createElement("p", { className: clsx('ob-validation-notification-card-page-label ob-validation-color-transition', {
148
+ 'is-not-first': isNotFirstPage,
149
+ }) }, page.label)),
150
+ React.createElement("div", { className: "ob-list has-dividers has-borders ob-validation-notification-card-list ob-validation-color-transition" }, errors.map(({ errorMessage, label, id }, index, list) => {
151
+ const isFirst = index === 0;
152
+ const isLast = index === list.length - 1;
153
+ return (React.createElement("div", { key: index, className: clsx('ob-list__item is-clickable ob-validation-notification-card-item', {
154
+ 'is-first': isFirst,
155
+ 'is-last': isLast,
156
+ }), onClick: () => {
157
+ if (page && page.id !== currentPage.id) {
158
+ setPageId(page.id);
159
+ }
160
+ const element = document.getElementById(id);
161
+ if (element) {
162
+ window.requestAnimationFrame(() => {
163
+ element.scrollIntoView({
164
+ behavior: 'smooth',
165
+ });
166
+ });
167
+ }
168
+ } },
169
+ React.createElement("div", { className: "ob-validation-notification-card-item-text" },
170
+ React.createElement("p", null, label),
171
+ React.createElement(Tooltip, { title: errorMessage, placement: "left", arrow: true },
172
+ React.createElement("p", { className: "ob-validation-notification-card-item-text-error-message has-text-danger" }, errorMessage))),
173
+ React.createElement(MaterialIcon, { className: "has-text-grey icon-small ob-validation-notification-card-item-icon" }, "chevron_right")));
174
+ }))));
175
+ })))))));
176
+ };
177
+ export default React.memo(ValidationErrorsCard);
178
+ //# sourceMappingURL=ValidationErrorsCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ValidationErrorsCard.js","sourceRoot":"","sources":["../../src/components/ValidationErrorsCard.tsx"],"names":[],"mappings":"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","sourcesContent":["import { IconButton, Collapse, Tooltip } from '@mui/material'\nimport * as React from 'react'\nimport MaterialIcon from './MaterialIcon'\nimport { FormElementsValidation } from '../types/form'\nimport useBooleanState from '../hooks/useBooleanState'\nimport clsx from 'clsx'\nimport useFormDefinition from '../hooks/useFormDefinition'\nimport { FormTypes } from '@oneblink/types'\n\nconst NO_PAGE_KEY = 'NO_PAGE'\ntype ValidationErrorMetaData = {\n id: string\n label: string\n page?: {\n label: string\n id: string\n }\n errorMessage: string\n}\nconst getValidationErrors = ({\n formElementsValidation,\n elements,\n page,\n idPrefix,\n}: {\n formElementsValidation: FormElementsValidation\n elements: FormTypes.FormElement[]\n page?: ValidationErrorMetaData['page']\n idPrefix: string\n}) => {\n return elements.reduce<Array<ValidationErrorMetaData>>((memo, el) => {\n switch (el.type) {\n case 'page': {\n memo.push(\n ...getValidationErrors({\n formElementsValidation,\n elements: el.elements,\n page: el,\n idPrefix,\n }),\n )\n break\n }\n case 'section': {\n memo.push(\n ...getValidationErrors({\n formElementsValidation,\n elements: el.elements,\n page,\n idPrefix,\n }),\n )\n break\n }\n case 'repeatableSet': {\n const validationData = formElementsValidation[el.name]\n if (\n !!validationData &&\n typeof validationData !== 'string' &&\n validationData.type === 'repeatableSet'\n ) {\n if (validationData.set) {\n memo.push({\n id: `${idPrefix}${el.name}-label`,\n errorMessage: validationData.set,\n label: el.label,\n page,\n })\n }\n for (const [key, entry] of Object.entries(validationData.entries)) {\n if (!entry) continue\n memo.push(\n ...getValidationErrors({\n formElementsValidation: entry,\n elements: el.elements,\n page,\n idPrefix: `${idPrefix}${el.name}_entry-${key}_`,\n }),\n )\n }\n }\n break\n }\n case 'infoPage':\n case 'form': {\n const validationData = formElementsValidation[el.name]\n if (\n !!validationData &&\n typeof validationData !== 'string' &&\n validationData.type === 'formElements'\n ) {\n if (validationData.formElements && el.elements) {\n memo.push(\n ...getValidationErrors({\n formElementsValidation: validationData.formElements,\n elements: el.elements,\n page,\n idPrefix: `${idPrefix}${el.name}_`,\n }),\n )\n }\n }\n break\n }\n default: {\n const validationMessage = formElementsValidation[el.name]\n if (typeof validationMessage === 'string') {\n memo.push({\n id: `${idPrefix}${el.name}`,\n label: el.label,\n page,\n errorMessage: validationMessage,\n })\n }\n }\n }\n return memo\n }, [])\n}\n\nconst ValidationErrorsCard = ({\n formElementsValidation,\n currentPage,\n setPageId,\n}: {\n formElementsValidation: FormElementsValidation | undefined\n currentPage: FormTypes.PageElement\n setPageId: (pageId: string) => void\n}) => {\n const [isExpanded, expand, contract] = useBooleanState(false)\n\n const form = useFormDefinition()\n\n const pagesWithValidationErrors = React.useMemo(() => {\n if (!formElementsValidation) return []\n const flatErrors = getValidationErrors({\n formElementsValidation,\n elements: form.elements,\n idPrefix: '',\n })\n\n // Organise into pages\n const pages = new Map<\n string,\n {\n page: ValidationErrorMetaData['page']\n errors: ValidationErrorMetaData[]\n }\n >()\n for (const error of flatErrors) {\n if (error.page) {\n // If error belongs to a page\n const existingSetEntry = pages.get(error.page.id)\n const errors = [...(existingSetEntry?.errors || []), error]\n const page = error.page\n\n pages.set(page.id, {\n page,\n errors,\n })\n } else {\n // No page associated with error\n const existingSetEntry = pages.get(NO_PAGE_KEY)\n const errors = [...(existingSetEntry?.errors || []), error]\n pages.set(NO_PAGE_KEY, {\n page: undefined,\n errors,\n })\n }\n }\n return Array.from(pages.values())\n }, [form.elements, formElementsValidation])\n\n return (\n <div className=\"ob-validation-notification-wrapper\">\n <div\n className={clsx(\n 'ob-validation-notification-card cypress-invalid-submit-attempt',\n {\n 'is-clickable': !isExpanded,\n 'is-contracted': !isExpanded,\n 'is-expanded': isExpanded,\n },\n )}\n onClick={!isExpanded ? expand : undefined}\n >\n <div className=\"ob-validation-notification-card-content\">\n <div className=\"ob-validation-notification-card-header-wrapper\">\n <div className=\"ob-validation-notification-card-header-title-wrapper\">\n <MaterialIcon\n className={clsx(\n 'ob-validation-notification-card-header-title-icon ob-validation-color-transition',\n {\n 'has-text-danger': isExpanded,\n 'has-text-white': !isExpanded,\n },\n )}\n >\n error\n </MaterialIcon>\n <p\n className={clsx(\n 'ob-validation-color-transition ob-validation-notification-card-header-title-text',\n {\n 'has-text-danger': isExpanded,\n 'has-text-white': !isExpanded,\n },\n )}\n >\n Validation Errors\n </p>\n </div>\n <div className=\"ob-validation-notification-card-header-collapse-icon-wrapper\">\n {isExpanded ? (\n <IconButton onClick={contract}>\n <MaterialIcon className=\"icon-small\">\n expand_more\n </MaterialIcon>\n </IconButton>\n ) : (\n <IconButton>\n <MaterialIcon className=\"icon-small has-text-white\">\n expand_less\n </MaterialIcon>\n </IconButton>\n )}\n </div>\n </div>\n <div className=\"ob-validation-notification-card-collapse-wrapper\">\n <Collapse in={isExpanded}>\n {pagesWithValidationErrors.map(({ page, errors }, pageIndex) => {\n const isNotFirstPage = pageIndex > 0\n return (\n <>\n {page && (\n <p\n className={clsx(\n 'ob-validation-notification-card-page-label ob-validation-color-transition',\n {\n 'is-not-first': isNotFirstPage,\n },\n )}\n >\n {page.label}\n </p>\n )}\n <div className=\"ob-list has-dividers has-borders ob-validation-notification-card-list ob-validation-color-transition\">\n {errors.map(\n ({ errorMessage, label, id }, index, list) => {\n const isFirst = index === 0\n const isLast = index === list.length - 1\n return (\n <div\n key={index}\n className={clsx(\n 'ob-list__item is-clickable ob-validation-notification-card-item',\n {\n 'is-first': isFirst,\n 'is-last': isLast,\n },\n )}\n onClick={() => {\n if (page && page.id !== currentPage.id) {\n setPageId(page.id)\n }\n const element = document.getElementById(id)\n if (element) {\n window.requestAnimationFrame(() => {\n element.scrollIntoView({\n behavior: 'smooth',\n })\n })\n }\n }}\n >\n <div className=\"ob-validation-notification-card-item-text\">\n <p>{label}</p>\n <Tooltip\n title={errorMessage}\n placement=\"left\"\n arrow\n >\n <p className=\"ob-validation-notification-card-item-text-error-message has-text-danger\">\n {errorMessage}\n </p>\n </Tooltip>\n </div>\n <MaterialIcon className=\"has-text-grey icon-small ob-validation-notification-card-item-icon\">\n chevron_right\n </MaterialIcon>\n </div>\n )\n },\n )}\n </div>\n </>\n )\n })}\n </Collapse>\n </div>\n </div>\n </div>\n </div>\n )\n}\n\nexport default React.memo(ValidationErrorsCard)\n"]}
@@ -0,0 +1,10 @@
1
+ import * as React from 'react';
2
+ import { FormElementsValidation } from '../types/form';
3
+ import { FormTypes } from '@oneblink/types';
4
+ declare const _default: React.MemoExoticComponent<({ formElementsValidation, display, currentPage, setPageId, }: {
5
+ formElementsValidation: FormElementsValidation | undefined;
6
+ display: boolean;
7
+ currentPage: FormTypes.PageElement;
8
+ setPageId: (pageId: string) => void;
9
+ }) => React.JSX.Element | null>;
10
+ export default _default;
@@ -0,0 +1,218 @@
1
+ import { Box, Card, CardContent, Typography, Grid, IconButton, Collapse, styled, } from '@mui/material';
2
+ import * as React from 'react';
3
+ import MaterialIcon from './MaterialIcon';
4
+ import useBooleanState from '../hooks/useBooleanState';
5
+ import clsx from 'clsx';
6
+ import useFormDefinition from '../hooks/useFormDefinition';
7
+ const NO_PAGE_KEY = 'NO_PAGE';
8
+ const getValidationErrors = ({ formElementsValidation, elements, page, idPrefix, }) => {
9
+ return elements.reduce((memo, el) => {
10
+ switch (el.type) {
11
+ case 'page': {
12
+ memo.push(...getValidationErrors({
13
+ formElementsValidation,
14
+ elements: el.elements,
15
+ page: el,
16
+ idPrefix,
17
+ }));
18
+ break;
19
+ }
20
+ case 'section': {
21
+ memo.push(...getValidationErrors({
22
+ formElementsValidation,
23
+ elements: el.elements,
24
+ page,
25
+ idPrefix,
26
+ }));
27
+ break;
28
+ }
29
+ case 'repeatableSet': {
30
+ const validationData = formElementsValidation[el.name];
31
+ if (!!validationData &&
32
+ typeof validationData !== 'string' &&
33
+ validationData.type === 'repeatableSet') {
34
+ for (const [key, entry] of Object.entries(validationData.entries)) {
35
+ if (!entry)
36
+ continue;
37
+ memo.push(...getValidationErrors({
38
+ formElementsValidation: entry,
39
+ elements: el.elements,
40
+ page,
41
+ idPrefix: `${idPrefix}${el.name}_entry-${key}_`,
42
+ }));
43
+ }
44
+ }
45
+ break;
46
+ }
47
+ case 'infoPage':
48
+ case 'form': {
49
+ const validationData = formElementsValidation[el.name];
50
+ if (!!validationData &&
51
+ typeof validationData !== 'string' &&
52
+ validationData.type === 'formElements') {
53
+ validationData.formElements;
54
+ if (validationData.formElements && el.elements) {
55
+ memo.push(...getValidationErrors({
56
+ formElementsValidation: validationData.formElements,
57
+ elements: el.elements,
58
+ page,
59
+ idPrefix: `${idPrefix}${el.name}_`,
60
+ }));
61
+ }
62
+ }
63
+ break;
64
+ }
65
+ default: {
66
+ const validationMessage = formElementsValidation[el.name];
67
+ if (typeof validationMessage === 'string') {
68
+ memo.push({
69
+ id: `${idPrefix}${el.name}`,
70
+ label: el.label,
71
+ page,
72
+ errorMessage: validationMessage,
73
+ });
74
+ }
75
+ }
76
+ }
77
+ return memo;
78
+ }, []);
79
+ };
80
+ const PulsingCard = styled(Card)(() => {
81
+ return {
82
+ animation: 'pulse-animation 1.5s infinite',
83
+ '@keyframes pulse-animation': {
84
+ '0%': {
85
+ boxShadow: '0 0 0 0px rgba(255, 0, 0, 0.4)',
86
+ },
87
+ '99%': {
88
+ boxShadow: '0 0 0 16px rgba(255, 0, 0, 0.0)',
89
+ },
90
+ },
91
+ };
92
+ });
93
+ const ValidationErrorsCard = ({ formElementsValidation, display, currentPage, setPageId, }) => {
94
+ const [isExpanded, expand, contract] = useBooleanState(true);
95
+ const form = useFormDefinition();
96
+ const pagesWithValidationErrors = React.useMemo(() => {
97
+ if (!formElementsValidation)
98
+ return [];
99
+ const flatErrors = getValidationErrors({
100
+ formElementsValidation,
101
+ elements: form.elements,
102
+ idPrefix: '',
103
+ });
104
+ // Organise into pages
105
+ const pages = new Map();
106
+ for (const error of flatErrors) {
107
+ if (error.page) {
108
+ // If error belongs to a page
109
+ const existingSetEntry = pages.get(error.page.id);
110
+ const errors = [...((existingSetEntry === null || existingSetEntry === void 0 ? void 0 : existingSetEntry.errors) || []), error];
111
+ const page = error.page;
112
+ pages.set(page.id, {
113
+ page,
114
+ errors,
115
+ });
116
+ }
117
+ else {
118
+ // No page associated with error
119
+ const existingSetEntry = pages.get(NO_PAGE_KEY);
120
+ const errors = [...((existingSetEntry === null || existingSetEntry === void 0 ? void 0 : existingSetEntry.errors) || []), error];
121
+ pages.set(NO_PAGE_KEY, {
122
+ page: undefined,
123
+ errors,
124
+ });
125
+ }
126
+ }
127
+ return Array.from(pages.values());
128
+ }, [form.elements, formElementsValidation]);
129
+ if (!display)
130
+ return null;
131
+ return (React.createElement(Box, { sx: {
132
+ position: 'fixed',
133
+ bottom: 16,
134
+ right: 16,
135
+ zIndex: 10,
136
+ } },
137
+ React.createElement(PulsingCard, { isExpanded: isExpanded, elevation: !isExpanded ? 20 : 0, sx: (theme) => ({
138
+ transition: `${theme.transitions.duration.standard}ms ${theme.transitions.easing.easeInOut}`,
139
+ borderTopLeftRadius: 8,
140
+ borderTopRightRadius: 8,
141
+ borderBottomLeftRadius: 8,
142
+ borderBottomRightRadius: 8,
143
+ maxHeight: 350,
144
+ overflowY: 'auto',
145
+ borderColor: theme.palette.error.light,
146
+ borderWidth: 2,
147
+ borderStyle: 'solid',
148
+ backgroundColor: !isExpanded ? theme.palette.error.light : undefined,
149
+ color: !isExpanded ? theme.palette.error.contrastText : undefined,
150
+ }), className: !isExpanded ? 'is-clickable' : '', onClick: !isExpanded ? expand : undefined },
151
+ React.createElement(CardContent, { sx: (theme) => ({
152
+ transition: `${theme.transitions.duration.standard}ms ${theme.transitions.easing.easeInOut}`,
153
+ paddingBottom: !isExpanded ? `8px !important` : undefined,
154
+ paddingTop: !isExpanded ? `8px !important` : undefined,
155
+ }) },
156
+ React.createElement(Grid, { container: true, justifyContent: "space-between", alignItems: "center" },
157
+ React.createElement(Grid, { item: true, alignItems: "center", display: "flex" },
158
+ React.createElement(MaterialIcon, { className: clsx({
159
+ 'has-text-danger': isExpanded,
160
+ 'has-text-white': !isExpanded,
161
+ }), sx: { mr: 1, fontSize: 22 } }, "error"),
162
+ React.createElement(Typography, { className: clsx({
163
+ 'has-text-danger': isExpanded,
164
+ 'has-text-white': !isExpanded,
165
+ }), fontWeight: 600 }, "Validation Errors")),
166
+ React.createElement(Grid, { item: true }, isExpanded ? (React.createElement(IconButton, { onClick: contract },
167
+ React.createElement(MaterialIcon, { className: "icon-small" }, "expand_more"))) : (React.createElement(IconButton, { onClick: expand },
168
+ React.createElement(MaterialIcon, { className: "icon-small has-text-white" }, "expand_less"))))),
169
+ React.createElement(Box, { sx: (theme) => ({
170
+ transition: `width ${theme.transitions.duration.standard}ms ${theme.transitions.easing.easeInOut}`,
171
+ whiteSpace: 'nowrap',
172
+ width: isExpanded ? 300 : 194,
173
+ overflowX: 'hidden',
174
+ opacity: isExpanded ? 1 : 0,
175
+ }) },
176
+ React.createElement(Collapse, { in: isExpanded }, pagesWithValidationErrors.map(({ page, errors }, pageIndex) => {
177
+ const isNotFirstPage = pageIndex > 0;
178
+ return (React.createElement(React.Fragment, null,
179
+ isNotFirstPage && React.createElement(Box, { mt: 1 }),
180
+ page && (React.createElement(Typography, { variant: "body2", fontWeight: "600", color: "text.primary" }, page.label)),
181
+ React.createElement(Box, { mb: 1 }),
182
+ errors.map(({ errorMessage, label, id }, index, list) => {
183
+ const isFirst = index === 0;
184
+ const isLast = index === list.length - 1;
185
+ return (React.createElement(Box, { display: "flex", justifyContent: "space-between", alignItems: "center", key: index, p: 1, sx: (theme) => ({
186
+ borderColor: theme.palette.divider,
187
+ borderWidth: 1,
188
+ borderStyle: 'solid',
189
+ borderTopLeftRadius: isFirst ? 8 : 0,
190
+ borderTopRightRadius: isFirst ? 8 : 0,
191
+ borderBottomWidth: isLast ? 1 : 0,
192
+ borderBottomLeftRadius: isLast ? 8 : 0,
193
+ borderBottomRightRadius: isLast ? 8 : 0,
194
+ }), className: "ob-list__item is-clickable", onClick: () => {
195
+ if (page && page.id !== currentPage.id) {
196
+ setPageId(page.id);
197
+ }
198
+ const element = document.getElementById(id);
199
+ if (element) {
200
+ window.requestAnimationFrame(() => {
201
+ element.scrollIntoView({
202
+ behavior: 'smooth',
203
+ });
204
+ });
205
+ }
206
+ } },
207
+ React.createElement(Box, { sx: { whitespace: 'nowrap' } },
208
+ React.createElement(Typography, { variant: "body2", color: "text.primary" }, label),
209
+ React.createElement(Typography, { variant: "body2", className: "has-text-danger", sx: {
210
+ whiteSpace: 'nowrap',
211
+ textOverflow: 'ellipsis',
212
+ } }, errorMessage)),
213
+ React.createElement(MaterialIcon, { className: "has-text-grey icon-small", sx: { ml: 1 } }, "chevron_right")));
214
+ })));
215
+ })))))));
216
+ };
217
+ export default React.memo(ValidationErrorsCard);
218
+ //# sourceMappingURL=ValidationErrorsCard_framer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ValidationErrorsCard_framer.js","sourceRoot":"","sources":["../../src/components/ValidationErrorsCard_framer.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n Box,\n Card,\n CardContent,\n Typography,\n Grid,\n IconButton,\n Collapse,\n styled,\n} from '@mui/material'\nimport * as React from 'react'\nimport MaterialIcon from './MaterialIcon'\nimport { FormElementsValidation } from '../types/form'\nimport useBooleanState from '../hooks/useBooleanState'\nimport clsx from 'clsx'\nimport useFormDefinition from '../hooks/useFormDefinition'\nimport { FormTypes } from '@oneblink/types'\n\nconst NO_PAGE_KEY = 'NO_PAGE'\n// const transitionLength = 3000\ntype ValidationErrorMetaData = {\n id: string\n label: string\n page?: {\n label: string\n id: string\n }\n errorMessage: string\n}\nconst getValidationErrors = ({\n formElementsValidation,\n elements,\n page,\n idPrefix,\n}: {\n formElementsValidation: FormElementsValidation\n elements: FormTypes.FormElement[]\n page?: ValidationErrorMetaData['page']\n idPrefix: string\n}) => {\n return elements.reduce<Array<ValidationErrorMetaData>>((memo, el) => {\n switch (el.type) {\n case 'page': {\n memo.push(\n ...getValidationErrors({\n formElementsValidation,\n elements: el.elements,\n page: el,\n idPrefix,\n }),\n )\n break\n }\n case 'section': {\n memo.push(\n ...getValidationErrors({\n formElementsValidation,\n elements: el.elements,\n page,\n idPrefix,\n }),\n )\n break\n }\n case 'repeatableSet': {\n const validationData = formElementsValidation[el.name]\n if (\n !!validationData &&\n typeof validationData !== 'string' &&\n validationData.type === 'repeatableSet'\n ) {\n for (const [key, entry] of Object.entries(validationData.entries)) {\n if (!entry) continue\n memo.push(\n ...getValidationErrors({\n formElementsValidation: entry,\n elements: el.elements,\n page,\n idPrefix: `${idPrefix}${el.name}_entry-${key}_`,\n }),\n )\n }\n }\n break\n }\n case 'infoPage':\n case 'form': {\n const validationData = formElementsValidation[el.name]\n if (\n !!validationData &&\n typeof validationData !== 'string' &&\n validationData.type === 'formElements'\n ) {\n validationData.formElements\n\n if (validationData.formElements && el.elements) {\n memo.push(\n ...getValidationErrors({\n formElementsValidation: validationData.formElements,\n elements: el.elements,\n page,\n idPrefix: `${idPrefix}${el.name}_`,\n }),\n )\n }\n }\n break\n }\n default: {\n const validationMessage = formElementsValidation[el.name]\n if (typeof validationMessage === 'string') {\n memo.push({\n id: `${idPrefix}${el.name}`,\n label: el.label,\n page,\n errorMessage: validationMessage,\n })\n }\n }\n }\n return memo\n }, [])\n}\n\nconst PulsingCard = styled(Card)<{ isExpanded: boolean }>(() => {\n return {\n animation: 'pulse-animation 1.5s infinite',\n '@keyframes pulse-animation': {\n '0%': {\n boxShadow: '0 0 0 0px rgba(255, 0, 0, 0.4)',\n },\n '99%': {\n boxShadow: '0 0 0 16px rgba(255, 0, 0, 0.0)',\n },\n },\n }\n})\nconst ValidationErrorsCard = ({\n formElementsValidation,\n display,\n currentPage,\n setPageId,\n}: {\n formElementsValidation: FormElementsValidation | undefined\n display: boolean\n currentPage: FormTypes.PageElement\n setPageId: (pageId: string) => void\n}) => {\n const [isExpanded, expand, contract] = useBooleanState(true)\n\n const form = useFormDefinition()\n\n const pagesWithValidationErrors = React.useMemo(() => {\n if (!formElementsValidation) return []\n const flatErrors = getValidationErrors({\n formElementsValidation,\n elements: form.elements,\n idPrefix: '',\n })\n\n // Organise into pages\n const pages = new Map<\n string,\n {\n page: ValidationErrorMetaData['page']\n errors: ValidationErrorMetaData[]\n }\n >()\n for (const error of flatErrors) {\n if (error.page) {\n // If error belongs to a page\n const existingSetEntry = pages.get(error.page.id)\n const errors = [...(existingSetEntry?.errors || []), error]\n const page = error.page\n\n pages.set(page.id, {\n page,\n errors,\n })\n } else {\n // No page associated with error\n const existingSetEntry = pages.get(NO_PAGE_KEY)\n const errors = [...(existingSetEntry?.errors || []), error]\n pages.set(NO_PAGE_KEY, {\n page: undefined,\n errors,\n })\n }\n }\n return Array.from(pages.values())\n }, [form.elements, formElementsValidation])\n if (!display) return null\n\n return (\n <Box\n sx={{\n position: 'fixed',\n bottom: 16,\n right: 16,\n zIndex: 10,\n }}\n >\n <PulsingCard\n isExpanded={isExpanded}\n elevation={!isExpanded ? 20 : 0}\n sx={(theme) => ({\n transition: `${theme.transitions.duration.standard}ms ${theme.transitions.easing.easeInOut}`,\n borderTopLeftRadius: 8,\n borderTopRightRadius: 8,\n borderBottomLeftRadius: 8,\n borderBottomRightRadius: 8,\n maxHeight: 350,\n overflowY: 'auto',\n borderColor: theme.palette.error.light,\n borderWidth: 2,\n borderStyle: 'solid',\n backgroundColor: !isExpanded ? theme.palette.error.light : undefined,\n color: !isExpanded ? theme.palette.error.contrastText : undefined,\n })}\n className={!isExpanded ? 'is-clickable' : ''}\n onClick={!isExpanded ? expand : undefined}\n >\n <CardContent\n sx={(theme) => ({\n transition: `${theme.transitions.duration.standard}ms ${theme.transitions.easing.easeInOut}`,\n paddingBottom: !isExpanded ? `8px !important` : undefined,\n paddingTop: !isExpanded ? `8px !important` : undefined,\n })}\n >\n <Grid container justifyContent=\"space-between\" alignItems=\"center\">\n <Grid item alignItems=\"center\" display=\"flex\">\n <MaterialIcon\n className={clsx({\n 'has-text-danger': isExpanded,\n 'has-text-white': !isExpanded,\n })}\n sx={{ mr: 1, fontSize: 22 }}\n >\n error\n </MaterialIcon>\n <Typography\n className={clsx({\n 'has-text-danger': isExpanded,\n 'has-text-white': !isExpanded,\n })}\n fontWeight={600}\n >\n Validation Errors\n </Typography>\n </Grid>\n <Grid item>\n {isExpanded ? (\n <IconButton onClick={contract}>\n <MaterialIcon className=\"icon-small\">\n expand_more\n </MaterialIcon>\n </IconButton>\n ) : (\n <IconButton onClick={expand}>\n <MaterialIcon className=\"icon-small has-text-white\">\n expand_less\n </MaterialIcon>\n </IconButton>\n )}\n </Grid>\n </Grid>\n <Box\n sx={(theme) => ({\n transition: `width ${theme.transitions.duration.standard}ms ${theme.transitions.easing.easeInOut}`,\n whiteSpace: 'nowrap',\n width: isExpanded ? 300 : 194,\n overflowX: 'hidden',\n opacity: isExpanded ? 1 : 0,\n })}\n >\n <Collapse in={isExpanded}>\n {pagesWithValidationErrors.map(({ page, errors }, pageIndex) => {\n const isNotFirstPage = pageIndex > 0\n return (\n <>\n {isNotFirstPage && <Box mt={1} />}\n {page && (\n <Typography\n variant=\"body2\"\n fontWeight=\"600\"\n color=\"text.primary\"\n >\n {page.label}\n </Typography>\n )}\n <Box mb={1} />\n {errors.map(({ errorMessage, label, id }, index, list) => {\n const isFirst = index === 0\n const isLast = index === list.length - 1\n return (\n <Box\n display=\"flex\"\n justifyContent=\"space-between\"\n alignItems=\"center\"\n key={index}\n p={1}\n sx={(theme) => ({\n borderColor: theme.palette.divider,\n borderWidth: 1,\n borderStyle: 'solid',\n borderTopLeftRadius: isFirst ? 8 : 0,\n borderTopRightRadius: isFirst ? 8 : 0,\n borderBottomWidth: isLast ? 1 : 0,\n borderBottomLeftRadius: isLast ? 8 : 0,\n borderBottomRightRadius: isLast ? 8 : 0,\n })}\n className=\"ob-list__item is-clickable\"\n onClick={() => {\n if (page && page.id !== currentPage.id) {\n setPageId(page.id)\n }\n const element = document.getElementById(id)\n if (element) {\n window.requestAnimationFrame(() => {\n element.scrollIntoView({\n behavior: 'smooth',\n })\n })\n }\n }}\n >\n <Box sx={{ whitespace: 'nowrap' }}>\n <Typography variant=\"body2\" color=\"text.primary\">\n {label}\n </Typography>\n <Typography\n variant=\"body2\"\n className=\"has-text-danger\"\n sx={{\n whiteSpace: 'nowrap',\n textOverflow: 'ellipsis',\n }}\n >\n {errorMessage}\n </Typography>\n </Box>\n <MaterialIcon\n className=\"has-text-grey icon-small\"\n sx={{ ml: 1 }}\n >\n chevron_right\n </MaterialIcon>\n </Box>\n )\n })}\n </>\n )\n })}\n </Collapse>\n </Box>\n </CardContent>\n </PulsingCard>\n </Box>\n )\n}\n\nexport default React.memo(ValidationErrorsCard)\n"]}
@@ -27,13 +27,13 @@ const DropdownMenu = ({ element, onRemove, onDownload, onRetry, attachmentUrl, }
27
27
  hideMore();
28
28
  onDownload();
29
29
  }, role: "menuitem" }, "Download")),
30
- attachmentUrl && (React.createElement("a", { href: attachmentUrl || '', target: "_blank", rel: "noreferrer", className: "dropdown-item cypress-file-open-button", style: {
30
+ attachmentUrl && (React.createElement("a", { href: attachmentUrl, target: "_blank", rel: "noreferrer", className: "dropdown-item cypress-file-open-button", style: {
31
31
  display: 'flex',
32
32
  alignItems: 'center',
33
33
  gap: 2,
34
34
  } },
35
- "Open ",
36
- React.createElement(MaterialIcon, { fontSize: "small" }, "open_in_new"))),
35
+ React.createElement("span", null, "Open"),
36
+ React.createElement(MaterialIcon, { className: "icon-small" }, "open_in_new"))),
37
37
  React.createElement("a", { className: clsx('dropdown-item cypress-file-remove-button', {
38
38
  'ob-files__menu-remove-hidden': element.readOnly,
39
39
  }), onClick: () => {
@@ -1 +1 @@
1
- {"version":3,"file":"DropdownMenu.js","sourceRoot":"","sources":["../../../../src/components/renderer/attachments/DropdownMenu.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,IAAI,MAAM,MAAM,CAAA;AAEvB,OAAO,eAAe,MAAM,gCAAgC,CAAA;AAC5D,OAAO,sBAAsB,MAAM,uCAAuC,CAAA;AAC1E,OAAO,YAAY,MAAM,oBAAoB,CAAA;AAU7C,MAAM,YAAY,GAAG,CAAC,EACpB,OAAO,EACP,QAAQ,EACR,UAAU,EACV,OAAO,EACP,aAAa,GACP,EAAE,EAAE;IACV,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACtC,MAAM,CAAC,aAAa,EAAE,QAAQ,EAAE,QAAQ,CAAC,GAAG,eAAe,CAAC,KAAK,CAAC,CAAA;IAElE,sBAAsB,CACpB,WAAW,EACX,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE;QACrB,IAAI,aAAa,EAAE;YACjB,QAAQ,EAAE,CAAA;SACX;IACH,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC,CAC9B,CAAA;IAED,OAAO,CACL,6BACE,SAAS,EAAE,IAAI,CAAC,kCAAkC,EAAE;YAClD,WAAW,EAAE,aAAa;SAC3B,CAAC,EACF,GAAG,EAAE,WAAW;QAEhB,6BAAK,SAAS,EAAC,kBAAkB;YAC/B,gCACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,uDAAuD,mBACnD,MAAM,mBACN,eAAe,EAC7B,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ;gBAE5C,oBAAC,YAAY,IAAC,SAAS,EAAC,qBAAqB,gBAAyB,CAC/D,CACL;QACN,6BAAK,SAAS,EAAC,eAAe,EAAC,IAAI,EAAC,MAAM;YACxC,6BAAK,SAAS,EAAC,kBAAkB;gBAC9B,OAAO,IAAI,CACV,2BACE,SAAS,EAAC,yCAAyC,EACnD,OAAO,EAAE,GAAG,EAAE;wBACZ,QAAQ,EAAE,CAAA;wBACV,OAAO,EAAE,CAAA;oBACX,CAAC,EACD,IAAI,EAAC,UAAU,YAGb,CACL;gBACA,UAAU,IAAI,CACb,2BACE,SAAS,EAAC,4CAA4C,EACtD,OAAO,EAAE,GAAG,EAAE;wBACZ,QAAQ,EAAE,CAAA;wBACV,UAAU,EAAE,CAAA;oBACd,CAAC,EACD,IAAI,EAAC,UAAU,eAGb,CACL;gBACA,aAAa,IAAI,CAChB,2BACE,IAAI,EAAE,aAAa,IAAI,EAAE,EACzB,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,YAAY,EAChB,SAAS,EAAC,wCAAwC,EAClD,KAAK,EAAE;wBACL,OAAO,EAAE,MAAM;wBACf,UAAU,EAAE,QAAQ;wBACpB,GAAG,EAAE,CAAC;qBACP;;oBAEI,oBAAC,YAAY,IAAC,QAAQ,EAAC,OAAO,kBAA2B,CAC5D,CACL;gBACD,2BACE,SAAS,EAAE,IAAI,CAAC,0CAA0C,EAAE;wBAC1D,8BAA8B,EAAE,OAAO,CAAC,QAAQ;qBACjD,CAAC,EACF,OAAO,EAAE,GAAG,EAAE;wBACZ,QAAQ,EAAE,CAAA;wBACV,QAAQ,EAAE,CAAA;oBACZ,CAAC,EACD,IAAI,EAAC,UAAU,aAGb,CACA,CACF,CACF,CACP,CAAA;AACH,CAAC,CAAA;AAED,eAAe,KAAK,CAAC,IAAI,CAAQ,YAAY,CAAC,CAAA","sourcesContent":["import * as React from 'react'\nimport clsx from 'clsx'\nimport { FormTypes } from '@oneblink/types'\nimport useBooleanState from '../../../hooks/useBooleanState'\nimport useClickOutsideElement from '../../../hooks/useClickOutsideElement'\nimport MaterialIcon from '../../MaterialIcon'\n\ninterface Props {\n element: FormTypes.FilesElement\n onRemove: () => void\n onDownload?: () => void\n onRetry?: () => void\n attachmentUrl: string | null | undefined\n}\n\nconst DropdownMenu = ({\n element,\n onRemove,\n onDownload,\n onRetry,\n attachmentUrl,\n}: Props) => {\n const dropDownRef = React.useRef(null)\n const [isShowingMore, showMore, hideMore] = useBooleanState(false)\n\n useClickOutsideElement(\n dropDownRef,\n React.useCallback(() => {\n if (isShowingMore) {\n hideMore()\n }\n }, [hideMore, isShowingMore]),\n )\n\n return (\n <div\n className={clsx('dropdown is-right ob-files__menu', {\n 'is-active': isShowingMore,\n })}\n ref={dropDownRef}\n >\n <div className=\"dropdown-trigger\">\n <button\n type=\"button\"\n className=\"button ob-files__menu-button cypress-file-menu-button\"\n aria-haspopup=\"true\"\n aria-controls=\"dropdown-menu\"\n onClick={isShowingMore ? hideMore : showMore}\n >\n <MaterialIcon className=\"ob-files__menu-icon\">more_vert</MaterialIcon>\n </button>\n </div>\n <div className=\"dropdown-menu\" role=\"menu\">\n <div className=\"dropdown-content\">\n {onRetry && (\n <a\n className=\"dropdown-item cypress-file-retry-button\"\n onClick={() => {\n hideMore()\n onRetry()\n }}\n role=\"menuitem\"\n >\n Retry\n </a>\n )}\n {onDownload && (\n <a\n className=\"dropdown-item cypress-file-download-button\"\n onClick={() => {\n hideMore()\n onDownload()\n }}\n role=\"menuitem\"\n >\n Download\n </a>\n )}\n {attachmentUrl && (\n <a\n href={attachmentUrl || ''}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"dropdown-item cypress-file-open-button\"\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 2,\n }}\n >\n Open <MaterialIcon fontSize=\"small\">open_in_new</MaterialIcon>\n </a>\n )}\n <a\n className={clsx('dropdown-item cypress-file-remove-button', {\n 'ob-files__menu-remove-hidden': element.readOnly,\n })}\n onClick={() => {\n hideMore()\n onRemove()\n }}\n role=\"menuitem\"\n >\n Remove\n </a>\n </div>\n </div>\n </div>\n )\n}\n\nexport default React.memo<Props>(DropdownMenu)\n"]}
1
+ {"version":3,"file":"DropdownMenu.js","sourceRoot":"","sources":["../../../../src/components/renderer/attachments/DropdownMenu.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,IAAI,MAAM,MAAM,CAAA;AAEvB,OAAO,eAAe,MAAM,gCAAgC,CAAA;AAC5D,OAAO,sBAAsB,MAAM,uCAAuC,CAAA;AAC1E,OAAO,YAAY,MAAM,oBAAoB,CAAA;AAU7C,MAAM,YAAY,GAAG,CAAC,EACpB,OAAO,EACP,QAAQ,EACR,UAAU,EACV,OAAO,EACP,aAAa,GACP,EAAE,EAAE;IACV,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACtC,MAAM,CAAC,aAAa,EAAE,QAAQ,EAAE,QAAQ,CAAC,GAAG,eAAe,CAAC,KAAK,CAAC,CAAA;IAElE,sBAAsB,CACpB,WAAW,EACX,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE;QACrB,IAAI,aAAa,EAAE;YACjB,QAAQ,EAAE,CAAA;SACX;IACH,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC,CAC9B,CAAA;IAED,OAAO,CACL,6BACE,SAAS,EAAE,IAAI,CAAC,kCAAkC,EAAE;YAClD,WAAW,EAAE,aAAa;SAC3B,CAAC,EACF,GAAG,EAAE,WAAW;QAEhB,6BAAK,SAAS,EAAC,kBAAkB;YAC/B,gCACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,uDAAuD,mBACnD,MAAM,mBACN,eAAe,EAC7B,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ;gBAE5C,oBAAC,YAAY,IAAC,SAAS,EAAC,qBAAqB,gBAAyB,CAC/D,CACL;QACN,6BAAK,SAAS,EAAC,eAAe,EAAC,IAAI,EAAC,MAAM;YACxC,6BAAK,SAAS,EAAC,kBAAkB;gBAC9B,OAAO,IAAI,CACV,2BACE,SAAS,EAAC,yCAAyC,EACnD,OAAO,EAAE,GAAG,EAAE;wBACZ,QAAQ,EAAE,CAAA;wBACV,OAAO,EAAE,CAAA;oBACX,CAAC,EACD,IAAI,EAAC,UAAU,YAGb,CACL;gBACA,UAAU,IAAI,CACb,2BACE,SAAS,EAAC,4CAA4C,EACtD,OAAO,EAAE,GAAG,EAAE;wBACZ,QAAQ,EAAE,CAAA;wBACV,UAAU,EAAE,CAAA;oBACd,CAAC,EACD,IAAI,EAAC,UAAU,eAGb,CACL;gBACA,aAAa,IAAI,CAChB,2BACE,IAAI,EAAE,aAAa,EACnB,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,YAAY,EAChB,SAAS,EAAC,wCAAwC,EAClD,KAAK,EAAE;wBACL,OAAO,EAAE,MAAM;wBACf,UAAU,EAAE,QAAQ;wBACpB,GAAG,EAAE,CAAC;qBACP;oBAED,yCAAiB;oBACjB,oBAAC,YAAY,IAAC,SAAS,EAAC,YAAY,kBAA2B,CAC7D,CACL;gBACD,2BACE,SAAS,EAAE,IAAI,CAAC,0CAA0C,EAAE;wBAC1D,8BAA8B,EAAE,OAAO,CAAC,QAAQ;qBACjD,CAAC,EACF,OAAO,EAAE,GAAG,EAAE;wBACZ,QAAQ,EAAE,CAAA;wBACV,QAAQ,EAAE,CAAA;oBACZ,CAAC,EACD,IAAI,EAAC,UAAU,aAGb,CACA,CACF,CACF,CACP,CAAA;AACH,CAAC,CAAA;AAED,eAAe,KAAK,CAAC,IAAI,CAAQ,YAAY,CAAC,CAAA","sourcesContent":["import * as React from 'react'\nimport clsx from 'clsx'\nimport { FormTypes } from '@oneblink/types'\nimport useBooleanState from '../../../hooks/useBooleanState'\nimport useClickOutsideElement from '../../../hooks/useClickOutsideElement'\nimport MaterialIcon from '../../MaterialIcon'\n\ninterface Props {\n element: FormTypes.FilesElement\n onRemove: () => void\n onDownload?: () => void\n onRetry?: () => void\n attachmentUrl: string | null | undefined\n}\n\nconst DropdownMenu = ({\n element,\n onRemove,\n onDownload,\n onRetry,\n attachmentUrl,\n}: Props) => {\n const dropDownRef = React.useRef(null)\n const [isShowingMore, showMore, hideMore] = useBooleanState(false)\n\n useClickOutsideElement(\n dropDownRef,\n React.useCallback(() => {\n if (isShowingMore) {\n hideMore()\n }\n }, [hideMore, isShowingMore]),\n )\n\n return (\n <div\n className={clsx('dropdown is-right ob-files__menu', {\n 'is-active': isShowingMore,\n })}\n ref={dropDownRef}\n >\n <div className=\"dropdown-trigger\">\n <button\n type=\"button\"\n className=\"button ob-files__menu-button cypress-file-menu-button\"\n aria-haspopup=\"true\"\n aria-controls=\"dropdown-menu\"\n onClick={isShowingMore ? hideMore : showMore}\n >\n <MaterialIcon className=\"ob-files__menu-icon\">more_vert</MaterialIcon>\n </button>\n </div>\n <div className=\"dropdown-menu\" role=\"menu\">\n <div className=\"dropdown-content\">\n {onRetry && (\n <a\n className=\"dropdown-item cypress-file-retry-button\"\n onClick={() => {\n hideMore()\n onRetry()\n }}\n role=\"menuitem\"\n >\n Retry\n </a>\n )}\n {onDownload && (\n <a\n className=\"dropdown-item cypress-file-download-button\"\n onClick={() => {\n hideMore()\n onDownload()\n }}\n role=\"menuitem\"\n >\n Download\n </a>\n )}\n {attachmentUrl && (\n <a\n href={attachmentUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"dropdown-item cypress-file-open-button\"\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 2,\n }}\n >\n <span>Open</span>\n <MaterialIcon className=\"icon-small\">open_in_new</MaterialIcon>\n </a>\n )}\n <a\n className={clsx('dropdown-item cypress-file-remove-button', {\n 'ob-files__menu-remove-hidden': element.readOnly,\n })}\n onClick={() => {\n hideMore()\n onRemove()\n }}\n role=\"menuitem\"\n >\n Remove\n </a>\n </div>\n </div>\n </div>\n )\n}\n\nexport default React.memo<Props>(DropdownMenu)\n"]}