@evoke-platform/ui-components 1.6.0-dev.3 → 1.6.0-dev.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/dist/published/components/core/SwipeableDrawer/SwipeableDrawer.d.ts +4 -0
  2. package/dist/published/components/core/SwipeableDrawer/SwipeableDrawer.js +8 -0
  3. package/dist/published/components/core/SwipeableDrawer/index.d.ts +3 -0
  4. package/dist/published/components/core/SwipeableDrawer/index.js +3 -0
  5. package/dist/published/components/core/index.d.ts +1 -0
  6. package/dist/published/components/core/index.js +1 -0
  7. package/dist/published/components/custom/CriteriaBuilder/CriteriaBuilder.js +1 -1
  8. package/dist/published/components/custom/Form/FormComponents/DocumentComponent/Document.d.ts +1 -0
  9. package/dist/published/components/custom/Form/FormComponents/DocumentComponent/Document.js +45 -5
  10. package/dist/published/components/custom/Form/FormComponents/DocumentComponent/DocumentComponent.d.ts +1 -0
  11. package/dist/published/components/custom/Form/FormComponents/DocumentComponent/DocumentComponent.js +8 -1
  12. package/dist/published/components/custom/Form/FormComponents/ImageComponent/Image.js +2 -2
  13. package/dist/published/components/custom/Form/FormComponents/RepeatableFieldComponent/RepeatableField.js +87 -57
  14. package/dist/published/components/custom/Form/tests/Form.test.js +1 -1
  15. package/dist/published/components/custom/Form/utils.js +6 -0
  16. package/dist/published/components/custom/FormField/AddressFieldComponent/addressFieldComponent.js +1 -1
  17. package/dist/published/components/custom/FormField/BooleanSelect/BooleanSelect.js +3 -3
  18. package/dist/published/components/custom/FormField/DatePickerSelect/DatePickerSelect.js +7 -1
  19. package/dist/published/components/custom/FormField/DateTimePickerSelect/DateTimePickerSelect.js +7 -1
  20. package/dist/published/components/custom/FormField/InputFieldComponent/InputFieldComponent.js +6 -3
  21. package/dist/published/components/custom/FormField/Select/Select.js +17 -5
  22. package/dist/published/components/custom/FormField/TimePickerSelect/TimePickerSelect.js +13 -3
  23. package/dist/published/components/custom/FormV2/FormRenderer.d.ts +19 -0
  24. package/dist/published/components/custom/FormV2/FormRenderer.js +183 -0
  25. package/dist/published/components/custom/FormV2/components/AccordionSections.d.ts +4 -0
  26. package/dist/published/components/custom/FormV2/components/AccordionSections.js +131 -0
  27. package/dist/published/components/custom/FormV2/components/ActionButtons.d.ts +19 -0
  28. package/dist/published/components/custom/FormV2/components/ActionButtons.js +106 -0
  29. package/dist/published/components/custom/FormV2/components/FieldWrapper.d.ts +24 -0
  30. package/dist/published/components/custom/FormV2/components/FieldWrapper.js +100 -0
  31. package/dist/published/components/custom/FormV2/components/FormContext.d.ts +12 -0
  32. package/dist/published/components/custom/FormV2/components/FormContext.js +8 -0
  33. package/dist/published/components/custom/FormV2/components/FormFieldTypes/AddressFields.d.ts +17 -0
  34. package/dist/published/components/custom/FormV2/components/FormFieldTypes/AddressFields.js +50 -0
  35. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/ActionDialog.d.ts +14 -0
  36. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/ActionDialog.js +88 -0
  37. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/DocumentViewerCell.d.ts +13 -0
  38. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/DocumentViewerCell.js +140 -0
  39. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/DropdownRepeatableField.d.ts +17 -0
  40. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/DropdownRepeatableField.js +233 -0
  41. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/DropdownRepeatableFieldInput.d.ts +40 -0
  42. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/DropdownRepeatableFieldInput.js +95 -0
  43. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/RepeatableField.d.ts +12 -0
  44. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/RepeatableField.js +526 -0
  45. package/dist/published/components/custom/FormV2/components/FormFieldTypes/Criteria.d.ts +12 -0
  46. package/dist/published/components/custom/FormV2/components/FormFieldTypes/Criteria.js +93 -0
  47. package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/Document.d.ts +16 -0
  48. package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/Document.js +113 -0
  49. package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/DocumentList.d.ts +13 -0
  50. package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/DocumentList.js +179 -0
  51. package/dist/published/components/custom/FormV2/components/FormFieldTypes/Image.d.ts +12 -0
  52. package/dist/published/components/custom/FormV2/components/FormFieldTypes/Image.js +108 -0
  53. package/dist/published/components/custom/FormV2/components/FormFieldTypes/UserProperty.d.ts +16 -0
  54. package/dist/published/components/custom/FormV2/components/FormFieldTypes/UserProperty.js +129 -0
  55. package/dist/published/components/custom/FormV2/components/FormFieldTypes/relatedObjectFiles/InstanceLookup.d.ts +15 -0
  56. package/dist/published/components/custom/FormV2/components/FormFieldTypes/relatedObjectFiles/InstanceLookup.js +226 -0
  57. package/dist/published/components/custom/FormV2/components/FormFieldTypes/relatedObjectFiles/ObjectPropertyInput.d.ts +4 -0
  58. package/dist/published/components/custom/FormV2/components/FormFieldTypes/relatedObjectFiles/ObjectPropertyInput.js +439 -0
  59. package/dist/published/components/custom/FormV2/components/FormFieldTypes/relatedObjectFiles/RelatedObjectInstance.d.ts +29 -0
  60. package/dist/published/components/custom/FormV2/components/FormFieldTypes/relatedObjectFiles/RelatedObjectInstance.js +74 -0
  61. package/dist/published/components/custom/FormV2/components/FormSections.d.ts +4 -0
  62. package/dist/published/components/custom/FormV2/components/FormSections.js +104 -0
  63. package/dist/published/components/custom/FormV2/components/RecursiveEntryRenderer.d.ts +2 -0
  64. package/dist/published/components/custom/FormV2/components/RecursiveEntryRenderer.js +209 -0
  65. package/dist/published/components/custom/FormV2/components/TabNav.d.ts +10 -0
  66. package/dist/published/components/custom/FormV2/components/TabNav.js +23 -0
  67. package/dist/published/components/custom/FormV2/components/ValidationFiles/Validation.d.ts +3 -0
  68. package/dist/published/components/custom/FormV2/components/ValidationFiles/Validation.js +176 -0
  69. package/dist/published/components/custom/FormV2/components/ValidationFiles/ValidationErrorDisplay.d.ts +10 -0
  70. package/dist/published/components/custom/FormV2/components/ValidationFiles/ValidationErrorDisplay.js +45 -0
  71. package/dist/published/components/custom/FormV2/components/types.d.ts +122 -0
  72. package/dist/published/components/custom/FormV2/components/types.js +1 -0
  73. package/dist/published/components/custom/FormV2/components/utils.d.ts +47 -0
  74. package/dist/published/components/custom/FormV2/components/utils.js +434 -0
  75. package/dist/published/components/custom/FormV2/index.d.ts +1 -0
  76. package/dist/published/components/custom/FormV2/index.js +1 -0
  77. package/dist/published/components/custom/HistoryLog/HistoryData.d.ts +1 -0
  78. package/dist/published/components/custom/HistoryLog/HistoryData.js +14 -6
  79. package/dist/published/components/custom/HistoryLog/HistoryLoading.d.ts +4 -1
  80. package/dist/published/components/custom/HistoryLog/HistoryLoading.js +14 -8
  81. package/dist/published/components/custom/HistoryLog/index.d.ts +2 -0
  82. package/dist/published/components/custom/HistoryLog/index.js +4 -4
  83. package/dist/published/components/custom/ResponsiveOverflow/ResponsiveOverflow.d.ts +33 -0
  84. package/dist/published/components/custom/ResponsiveOverflow/ResponsiveOverflow.js +140 -0
  85. package/dist/published/components/custom/ResponsiveOverflow/ResponsiveOverflow.test.d.ts +1 -0
  86. package/dist/published/components/custom/ResponsiveOverflow/ResponsiveOverflow.test.js +100 -0
  87. package/dist/published/components/custom/ResponsiveOverflow/index.d.ts +4 -0
  88. package/dist/published/components/custom/ResponsiveOverflow/index.js +3 -0
  89. package/dist/published/components/custom/index.d.ts +2 -0
  90. package/dist/published/components/custom/index.js +2 -0
  91. package/dist/published/components/custom/util.d.ts +1 -0
  92. package/dist/published/components/custom/util.js +28 -0
  93. package/dist/published/index.d.ts +1 -1
  94. package/dist/published/index.js +1 -1
  95. package/dist/published/stories/ResponsiveOverflow.stories.d.ts +8 -0
  96. package/dist/published/stories/ResponsiveOverflow.stories.js +91 -0
  97. package/dist/published/theme/hooks.d.ts +7 -0
  98. package/dist/published/theme/hooks.js +9 -0
  99. package/package.json +6 -2
@@ -0,0 +1,140 @@
1
+ import { KeyboardArrowDownRounded } from '@mui/icons-material';
2
+ import { Box, Menu, MenuItem } from '@mui/material';
3
+ import React, { useCallback, useEffect, useRef, useState } from 'react';
4
+ import { Button } from '../../core';
5
+ const styles = {
6
+ container: {
7
+ display: 'flex',
8
+ alignItems: 'center',
9
+ flex: '1 1 auto',
10
+ minWidth: 0,
11
+ overflow: 'clip',
12
+ overflowClipMargin: '10px',
13
+ justifyContent: 'flex-end',
14
+ },
15
+ moreButton: {
16
+ color: '#637381',
17
+ fontSize: '14px',
18
+ fontWeight: 700,
19
+ minWidth: 'unset',
20
+ '& .MuiButton-endIcon': { margin: '0px' },
21
+ },
22
+ menuPaper: {
23
+ border: '0.5px solid #919EAB52',
24
+ borderRadius: '8px',
25
+ minWidth: '150px',
26
+ boxShadow: '0px 8px 16px 0px #0000001F',
27
+ },
28
+ horizontalItems: {
29
+ display: 'inline-block',
30
+ verticalAlign: 'top',
31
+ whiteSpace: 'nowrap',
32
+ },
33
+ fullWidthItems: {
34
+ padding: '0 4px',
35
+ flexGrow: 1,
36
+ },
37
+ };
38
+ /**
39
+ * ResponsiveOverflow is a container component that displays children horizontally,
40
+ * automatically moving overflow items into a dropdown menu when there isn't enough space.
41
+ */
42
+ export const ResponsiveOverflow = (props) => {
43
+ const { children, customMoreButton, maxVisible, renderOverflowMenuItem, moreButtonText, fullWidth } = props;
44
+ const containerRef = useRef(null);
45
+ const itemRefs = useRef([]);
46
+ const moreButtonBoxRef = useRef(null);
47
+ const [overflowItems, setOverflowItems] = useState([]);
48
+ const [anchorEl, setAnchorEl] = useState(null);
49
+ // Initialize refs array with correct length
50
+ useEffect(() => {
51
+ itemRefs.current = itemRefs.current.slice(0, children.length);
52
+ handleResize();
53
+ }, [children]);
54
+ const handleResize = useCallback(() => {
55
+ if (!containerRef.current)
56
+ return;
57
+ // Reset all items to visible before measuring
58
+ itemRefs.current.forEach((item) => {
59
+ if (item) {
60
+ item.style.display = 'inline-block';
61
+ }
62
+ });
63
+ const availableWidth = containerRef.current.getBoundingClientRect().width;
64
+ const moreButtonWidth = moreButtonBoxRef.current?.getBoundingClientRect().width ?? 0;
65
+ let usedWidth = 0;
66
+ let maxFit = children.length;
67
+ // Determine which items fit, accounting for overflow button width
68
+ for (let i = 0; i < itemRefs.current.length; i++) {
69
+ const item = itemRefs.current[i];
70
+ if (!item) {
71
+ continue;
72
+ }
73
+ const itemWidth = item.getBoundingClientRect().width;
74
+ if (usedWidth + itemWidth + moreButtonWidth > availableWidth) {
75
+ maxFit = i;
76
+ break;
77
+ }
78
+ usedWidth += itemWidth;
79
+ }
80
+ // If maxVisible is set, limit the number of visible items
81
+ if (typeof maxVisible === 'number') {
82
+ maxFit = Math.min(maxFit, maxVisible);
83
+ }
84
+ const newOverflow = [];
85
+ itemRefs.current.forEach((item, idx) => {
86
+ if (!item) {
87
+ return;
88
+ }
89
+ else if (idx >= maxFit) {
90
+ item.style.display = 'none';
91
+ if (children[idx]) {
92
+ newOverflow.push(children[idx]);
93
+ }
94
+ }
95
+ else {
96
+ item.style.display = 'inline-block';
97
+ }
98
+ });
99
+ setOverflowItems(newOverflow);
100
+ // Close menu if nothing is overflowing
101
+ if (newOverflow.length === 0) {
102
+ setAnchorEl(null);
103
+ }
104
+ }, [children, maxVisible]);
105
+ // Set up resize observer
106
+ useEffect(() => {
107
+ const resizeObserver = new ResizeObserver(() => {
108
+ requestAnimationFrame(handleResize);
109
+ });
110
+ if (containerRef.current) {
111
+ resizeObserver.observe(containerRef.current);
112
+ }
113
+ handleResize();
114
+ return () => {
115
+ if (containerRef.current) {
116
+ resizeObserver.unobserve(containerRef.current);
117
+ }
118
+ resizeObserver.disconnect();
119
+ };
120
+ }, [handleResize]);
121
+ const handleMenuOpen = (e) => setAnchorEl(e.currentTarget);
122
+ const handleMenuClose = () => setAnchorEl(null);
123
+ return (React.createElement(Box, { ref: containerRef, sx: styles.container },
124
+ children.map((item, index) => (React.createElement(Box, { ref: (el) => (itemRefs.current[index] = el), key: index, sx: { ...styles.horizontalItems, ...(fullWidth ? styles.fullWidthItems : {}) } }, item))),
125
+ !!overflowItems.length && (React.createElement(React.Fragment, null,
126
+ React.createElement(Box, { ref: moreButtonBoxRef, onClick: anchorEl ? handleMenuClose : handleMenuOpen }, customMoreButton ?? (React.createElement(Button, { variant: "text", sx: styles.moreButton, size: "small", endIcon: React.createElement(KeyboardArrowDownRounded, null) }, moreButtonText ?? 'More'))),
127
+ React.createElement(Menu, { anchorEl: anchorEl, open: Boolean(anchorEl), onClose: handleMenuClose, disablePortal: false, disableScrollLock: true, keepMounted: true, anchorOrigin: {
128
+ vertical: 'bottom',
129
+ horizontal: 'right',
130
+ }, transformOrigin: {
131
+ vertical: 'top',
132
+ horizontal: 'right',
133
+ }, sx: { '& .MuiPaper-root': styles.menuPaper }, onClick: handleMenuClose }, overflowItems.map((item, index) => {
134
+ if (renderOverflowMenuItem) {
135
+ return renderOverflowMenuItem(item);
136
+ }
137
+ return (React.createElement(MenuItem, { key: `overflow-item-${index}`, onClick: handleMenuClose }, item));
138
+ }))))));
139
+ };
140
+ export default ResponsiveOverflow;
@@ -0,0 +1 @@
1
+ import '@testing-library/jest-dom';
@@ -0,0 +1,100 @@
1
+ import '@testing-library/jest-dom';
2
+ import { render, screen } from '@testing-library/react';
3
+ import userEvent from '@testing-library/user-event';
4
+ import React from 'react';
5
+ import { vi } from 'vitest';
6
+ import Button from '../../core/Button/Button';
7
+ import ResponsiveOverflow from './ResponsiveOverflow';
8
+ let mockResizeCallback = null;
9
+ const originalResizeObserver = global.ResizeObserver;
10
+ const originalGetBoundingClientRect = Element.prototype.getBoundingClientRect;
11
+ describe('ResponsiveOverflow', () => {
12
+ // Helper function to simulate resize events
13
+ const simulateResize = (width) => {
14
+ Element.prototype.getBoundingClientRect = vi.fn(() => ({
15
+ width,
16
+ }));
17
+ if (mockResizeCallback) {
18
+ mockResizeCallback([], {});
19
+ }
20
+ };
21
+ beforeEach(() => {
22
+ mockResizeCallback = null;
23
+ global.ResizeObserver = class ResizeObserver {
24
+ constructor(callback) {
25
+ mockResizeCallback = callback;
26
+ }
27
+ observe() { }
28
+ unobserve() { }
29
+ disconnect() { }
30
+ };
31
+ });
32
+ afterEach(() => {
33
+ global.ResizeObserver = originalResizeObserver;
34
+ Element.prototype.getBoundingClientRect = originalGetBoundingClientRect;
35
+ });
36
+ it('renders children correctly', () => {
37
+ render(React.createElement(ResponsiveOverflow, null,
38
+ React.createElement(Button, null, "Button 1"),
39
+ React.createElement(Button, null, "Button 2"),
40
+ React.createElement(Button, null, "Button 3")));
41
+ expect(screen.getByText('Button 1')).toBeInTheDocument();
42
+ expect(screen.getByText('Button 2')).toBeInTheDocument();
43
+ expect(screen.getByText('Button 3')).toBeInTheDocument();
44
+ });
45
+ it('displays custom button text when overflowing', async () => {
46
+ render(React.createElement(ResponsiveOverflow, { moreButtonText: "Show More" },
47
+ React.createElement(Button, null, "Button 1"),
48
+ React.createElement(Button, null, "Button 2"),
49
+ React.createElement(Button, null, "Button 3"),
50
+ React.createElement(Button, null, "Button 4")));
51
+ simulateResize(80); // Narrow width to force overflow
52
+ await screen.findByRole('button', { name: 'Show More' });
53
+ });
54
+ it('displays custom more button when overflowing', async () => {
55
+ const customButton = React.createElement(Button, { "data-testid": "custom-more" }, "Custom More");
56
+ render(React.createElement(ResponsiveOverflow, { customMoreButton: customButton },
57
+ React.createElement(Button, null, "Button 1"),
58
+ React.createElement(Button, null, "Button 2"),
59
+ React.createElement(Button, null, "Button 3"),
60
+ React.createElement(Button, null, "Button 4")));
61
+ simulateResize(80);
62
+ await screen.findByRole('button', { name: 'Custom More' });
63
+ });
64
+ it('shows More button when triggered by ResizeObserver', async () => {
65
+ render(React.createElement(ResponsiveOverflow, { moreButtonText: "More" },
66
+ React.createElement(Button, null, "Button 1"),
67
+ React.createElement(Button, null, "Button 2"),
68
+ React.createElement(Button, null, "Button 3"),
69
+ React.createElement(Button, null, "Button 4"),
70
+ React.createElement(Button, null, "Button 5"),
71
+ React.createElement(Button, null, "Button 6"),
72
+ React.createElement(Button, null, "Button 7"),
73
+ React.createElement(Button, null, "Button 8"),
74
+ React.createElement(Button, null, "Button 9"),
75
+ React.createElement(Button, null, "Button 10")));
76
+ simulateResize(80);
77
+ const moreBtn = await screen.findByRole('button', { name: 'More' });
78
+ await screen.findByRole('button', { name: 'Button 1' });
79
+ await userEvent.click(moreBtn);
80
+ // Button 9 should be in the overflow menu as a menuitem
81
+ await screen.findByRole('menuitem', { name: 'Button 9' });
82
+ });
83
+ it('handles dynamic resizing from wide to narrow conditions', async () => {
84
+ render(React.createElement(ResponsiveOverflow, { moreButtonText: "More" },
85
+ React.createElement(Button, null, "Button 1"),
86
+ React.createElement(Button, null, "Button 2"),
87
+ React.createElement(Button, null, "Button 3"),
88
+ React.createElement(Button, null, "Button 4"),
89
+ React.createElement(Button, null, "Button 5"),
90
+ React.createElement(Button, null, "Button 6")));
91
+ simulateResize(800);
92
+ // With wide container, all buttons should fit
93
+ // More button should not be visible
94
+ expect(screen.queryByRole('button', { name: 'More' })).not.toBeInTheDocument();
95
+ // Now simulate narrow conditions - force overflow
96
+ simulateResize(200);
97
+ // With narrow container, More button should now be visible
98
+ await screen.findByRole('button', { name: 'More' });
99
+ });
100
+ });
@@ -0,0 +1,4 @@
1
+ import ResponsiveOverflow, { ResponsiveOverflowProps } from './ResponsiveOverflow';
2
+ export { ResponsiveOverflow };
3
+ export type { ResponsiveOverflowProps };
4
+ export default ResponsiveOverflow;
@@ -0,0 +1,3 @@
1
+ import ResponsiveOverflow from './ResponsiveOverflow';
2
+ export { ResponsiveOverflow };
3
+ export default ResponsiveOverflow;
@@ -5,9 +5,11 @@ export { ErrorComponent } from './ErrorComponent';
5
5
  export { Form } from './Form';
6
6
  export type { FormRef } from './Form';
7
7
  export { FormField } from './FormField';
8
+ export { FormRenderer } from './FormV2';
8
9
  export { HistoryLog } from './HistoryLog';
9
10
  export { MenuBar } from './Menubar';
10
11
  export { MultiSelect } from './MultiSelect';
11
12
  export { RepeatableField } from './RepeatableField';
13
+ export { ResponsiveOverflow } from './ResponsiveOverflow';
12
14
  export { RichTextViewer } from './RichTextViewer';
13
15
  export { UserAvatar } from './UserAvatar';
@@ -4,9 +4,11 @@ export { DataGrid } from './DataGrid';
4
4
  export { ErrorComponent } from './ErrorComponent';
5
5
  export { Form } from './Form';
6
6
  export { FormField } from './FormField';
7
+ export { FormRenderer } from './FormV2';
7
8
  export { HistoryLog } from './HistoryLog';
8
9
  export { MenuBar } from './Menubar';
9
10
  export { MultiSelect } from './MultiSelect';
10
11
  export { RepeatableField } from './RepeatableField';
12
+ export { ResponsiveOverflow } from './ResponsiveOverflow';
11
13
  export { RichTextViewer } from './RichTextViewer';
12
14
  export { UserAvatar } from './UserAvatar';
@@ -1 +1,2 @@
1
1
  export declare function difference(object?: any, base?: any): any;
2
+ export declare const createAcceptObject: (allowedTypes: string[]) => Record<string, string[]> | undefined;
@@ -1,4 +1,5 @@
1
1
  import { isEqual, isObject, transform } from 'lodash';
2
+ import mime from 'mime-types';
2
3
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
3
4
  export function difference(object, base) {
4
5
  if (!object) {
@@ -14,3 +15,30 @@ export function difference(object, base) {
14
15
  }
15
16
  });
16
17
  }
18
+ // Helper function to convert file extensions array to dropzone accept format
19
+ export const createAcceptObject = (allowedTypes) => {
20
+ if (!allowedTypes.length)
21
+ return undefined;
22
+ const acceptObject = {};
23
+ const customExtensions = [];
24
+ // First pass: collect custom extensions from allowedTypes that don't map to standard MIME types
25
+ allowedTypes.forEach((extension) => {
26
+ const mimeType = mime.lookup(extension);
27
+ // It's a custom extension
28
+ if (!mimeType) {
29
+ customExtensions.push(extension.startsWith('.') ? extension : `.${extension}`);
30
+ }
31
+ else {
32
+ // If it is mapped to a value, add it to the accept object
33
+ if (!acceptObject[mimeType]) {
34
+ acceptObject[mimeType] = [];
35
+ }
36
+ acceptObject[mimeType].push(extension.startsWith('.') ? extension : `.${extension}`);
37
+ }
38
+ });
39
+ if (customExtensions.length) {
40
+ // Add custom files extensions to the accept object
41
+ acceptObject['file/custom'] = customExtensions;
42
+ }
43
+ return acceptObject;
44
+ };
@@ -2,7 +2,7 @@ export { ClickAwayListener, createTheme, darken, lighten, styled, Toolbar, useMe
2
2
  export { CalendarPicker, DateTimePicker, MonthPicker, PickersDay, StaticDateTimePicker, StaticTimePicker, TimePicker, YearPicker, } from '@mui/x-date-pickers';
3
3
  export * from './colors';
4
4
  export * from './components/core';
5
- export { BuilderGrid, CriteriaBuilder, DataGrid, ErrorComponent, Form, FormField, getReadableQuery, HistoryLog, MenuBar, MultiSelect, RepeatableField, RichTextViewer, UserAvatar, } from './components/custom';
5
+ export { BuilderGrid, CriteriaBuilder, DataGrid, ErrorComponent, Form, FormField, FormRenderer, getReadableQuery, HistoryLog, MenuBar, MultiSelect, RepeatableField, ResponsiveOverflow, RichTextViewer, UserAvatar, } from './components/custom';
6
6
  export type { FormRef } from './components/custom';
7
7
  export { NumericFormat } from './components/custom/FormField/InputFieldComponent';
8
8
  export { Box, Container, Grid, Stack } from './components/layout';
@@ -2,7 +2,7 @@ export { ClickAwayListener, createTheme, darken, lighten, styled, Toolbar, useMe
2
2
  export { CalendarPicker, DateTimePicker, MonthPicker, PickersDay, StaticDateTimePicker, StaticTimePicker, TimePicker, YearPicker, } from '@mui/x-date-pickers';
3
3
  export * from './colors';
4
4
  export * from './components/core';
5
- export { BuilderGrid, CriteriaBuilder, DataGrid, ErrorComponent, Form, FormField, getReadableQuery, HistoryLog, MenuBar, MultiSelect, RepeatableField, RichTextViewer, UserAvatar, } from './components/custom';
5
+ export { BuilderGrid, CriteriaBuilder, DataGrid, ErrorComponent, Form, FormField, FormRenderer, getReadableQuery, HistoryLog, MenuBar, MultiSelect, RepeatableField, ResponsiveOverflow, RichTextViewer, UserAvatar, } from './components/custom';
6
6
  export { NumericFormat } from './components/custom/FormField/InputFieldComponent';
7
7
  export { Box, Container, Grid, Stack } from './components/layout';
8
8
  export * from './theme';
@@ -0,0 +1,8 @@
1
+ import { Meta, Story } from '@storybook/react';
2
+ import React from 'react';
3
+ import { ResponsiveOverflowProps } from '../components/custom/ResponsiveOverflow';
4
+ declare const _default: Meta<import("@storybook/react").Args>;
5
+ export default _default;
6
+ export declare const ResizableDemo: () => React.JSX.Element;
7
+ export declare const WithLinks: Story<ResponsiveOverflowProps>;
8
+ export declare const WithCustomMoreButton: Story<ResponsiveOverflowProps>;
@@ -0,0 +1,91 @@
1
+ import { KeyboardArrowDownRounded } from '@mui/icons-material';
2
+ import { Box, Paper, Typography } from '@mui/material';
3
+ import React, { useState } from 'react';
4
+ import Button from '../components/core/Button/Button';
5
+ import Link from '../components/core/Link/Link';
6
+ import ResponsiveOverflow from '../components/custom/ResponsiveOverflow';
7
+ export default {
8
+ title: 'Custom/ResponsiveOverflow',
9
+ component: ResponsiveOverflow,
10
+ parameters: {
11
+ componentSubtitle: 'A container that handles overflow with a dropdown menu',
12
+ },
13
+ argTypes: {
14
+ moreButtonText: {
15
+ control: 'text',
16
+ description: 'Text for the overflow button',
17
+ defaultValue: 'More',
18
+ },
19
+ customMoreButton: {
20
+ control: false,
21
+ description: 'Custom button element to replace the default More button',
22
+ },
23
+ children: {
24
+ control: false,
25
+ description: 'React elements to display in the container',
26
+ },
27
+ },
28
+ };
29
+ const Template = (args) => React.createElement(ResponsiveOverflow, { ...args });
30
+ // Interactive demo with resizable container
31
+ export const ResizableDemo = () => {
32
+ const [width, setWidth] = useState(800);
33
+ const handleChange = (event) => {
34
+ setWidth(Number(event.target.value));
35
+ };
36
+ return (React.createElement(Box, null,
37
+ React.createElement(Typography, { variant: "h6", gutterBottom: true }, "Resize Container"),
38
+ React.createElement(Box, { sx: { mb: 2 } },
39
+ React.createElement(Typography, { variant: "body2", gutterBottom: true },
40
+ "Container Width: ",
41
+ width,
42
+ "px"),
43
+ React.createElement("input", { type: "range", min: 200, max: 1000, value: width, onChange: handleChange,
44
+ // eslint-disable-next-line no-inline-styles/no-inline-styles
45
+ style: { width: '100%' }, "aria-label": "Adjust container width", title: "Drag to resize container" })),
46
+ React.createElement(Paper, { elevation: 1, sx: {
47
+ width: `${width}px`,
48
+ padding: 2,
49
+ transition: 'width 0.3s ease',
50
+ backgroundColor: '#f5f5f5',
51
+ } },
52
+ React.createElement(ResponsiveOverflow, { moreButtonText: "More" },
53
+ React.createElement(Button, { variant: "contained", color: "primary" }, "Dashboard"),
54
+ React.createElement(Button, { variant: "contained" }, "Applications"),
55
+ React.createElement(Button, { variant: "contained" }, "Inspections"),
56
+ React.createElement(Button, { variant: "contained" }, "Reports"),
57
+ React.createElement(Button, { variant: "contained" }, "Licenses"),
58
+ React.createElement(Button, { variant: "contained" }, "Permits"),
59
+ React.createElement(Button, { variant: "contained" }, "Requests"),
60
+ React.createElement(Button, { variant: "contained" }, "Locations")))));
61
+ };
62
+ export const WithLinks = Template.bind({});
63
+ WithLinks.args = {
64
+ moreButtonText: 'More',
65
+ children: [
66
+ React.createElement(Link, { key: "1" }, "Applications"),
67
+ React.createElement(Link, { key: "2" }, "Inspections"),
68
+ React.createElement(Link, { key: "3" }, "Licenses"),
69
+ React.createElement(Link, { key: "4" }, "Permits"),
70
+ React.createElement(Link, { key: "5" }, "Requests"),
71
+ React.createElement(Link, { key: "6" }, "Compliance"),
72
+ ],
73
+ };
74
+ export const WithCustomMoreButton = Template.bind({});
75
+ WithCustomMoreButton.args = {
76
+ customMoreButton: (React.createElement(Button, { variant: "contained", endIcon: React.createElement(KeyboardArrowDownRounded, null) }, "More Options")),
77
+ children: [
78
+ React.createElement(Button, { variant: "contained", color: "primary", key: "1" }, "Dashboard"),
79
+ React.createElement(Button, { variant: "contained", key: "2" }, "Applications"),
80
+ React.createElement(Button, { variant: "contained", key: "3" }, "Inspections"),
81
+ React.createElement(Button, { variant: "contained", key: "4" }, "Reports"),
82
+ React.createElement(Button, { variant: "contained", key: "5" }, "Licenses"),
83
+ React.createElement(Button, { variant: "contained", key: "6" }, "Permits"),
84
+ React.createElement(Button, { variant: "contained", key: "7" }, "Requests"),
85
+ React.createElement(Button, { variant: "contained", key: "8" }, "Documents"),
86
+ React.createElement(Button, { variant: "contained", key: "9" }, "Locations"),
87
+ React.createElement(Button, { variant: "contained", key: "10" }, "Calendar"),
88
+ React.createElement(Button, { variant: "contained", key: "11" }, "Compliance"),
89
+ React.createElement(Button, { variant: "contained", key: "12" }, "Notifications"),
90
+ ],
91
+ };
@@ -107,3 +107,10 @@ export declare const useWidgetSize: (options?: {
107
107
  resize?: boolean;
108
108
  }) => WidgetSizeInfo;
109
109
  export default useWidgetSize;
110
+ export declare function useFormContext(): {
111
+ fetchedOptions: import("react-hook-form").FieldValues;
112
+ setFetchedOptions: (newData: import("react-hook-form").FieldValues) => void;
113
+ getValues: import("react-hook-form").UseFormGetValues<import("react-hook-form").FieldValues>;
114
+ stickyFooter?: boolean | undefined;
115
+ object?: import("@evoke-platform/context").Obj | undefined;
116
+ };
@@ -1,6 +1,8 @@
1
1
  import { useTheme } from '@mui/material';
2
2
  import useMediaQuery from '@mui/material/useMediaQuery';
3
+ import { useContext } from 'react';
3
4
  import useMeasure from 'react-use-measure';
5
+ import { FormContext } from '../components/custom/FormV2/components/FormContext';
4
6
  /**
5
7
  * Custom hook for responsive design breakpoints using size terminology.
6
8
  * Breakpoints based on MUI default theme:
@@ -98,3 +100,10 @@ export const useWidgetSize = (options) => {
98
100
  };
99
101
  };
100
102
  export default useWidgetSize;
103
+ export function useFormContext() {
104
+ const context = useContext(FormContext);
105
+ if (!context) {
106
+ throw new Error('useFormContext must be used within a FormContext.Provider');
107
+ }
108
+ return context;
109
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evoke-platform/ui-components",
3
- "version": "1.6.0-dev.3",
3
+ "version": "1.6.0-dev.30",
4
4
  "description": "",
5
5
  "main": "dist/published/index.js",
6
6
  "module": "dist/published/index.js",
@@ -54,7 +54,9 @@
54
54
  "@testing-library/user-event": "^14.5.2",
55
55
  "@types/flat": "^5.0.5",
56
56
  "@types/jest": "^28.1.4",
57
+ "@types/json-logic-js": "^2.0.8",
57
58
  "@types/luxon": "^3.4.2",
59
+ "@types/mime-types": "^3.0.1",
58
60
  "@types/nanoid-dictionary": "^4.2.3",
59
61
  "@types/node": "^18.0.0",
60
62
  "@types/react": "^18.0.17",
@@ -86,7 +88,7 @@
86
88
  "yalc": "^1.0.0-pre.53"
87
89
  },
88
90
  "peerDependencies": {
89
- "@evoke-platform/context": "^1.3.0-0",
91
+ "@evoke-platform/context": "^1.3.0-testing.9",
90
92
  "react": "^18.1.0",
91
93
  "react-dom": "^18.1.0"
92
94
  },
@@ -118,6 +120,7 @@
118
120
  "formiojs": "^4.15.0-rc.23",
119
121
  "html-react-parser": "^5.1.18",
120
122
  "luxon": "^2.5.2",
123
+ "mime-type": "^5.0.3",
121
124
  "msw": "^2.7.3",
122
125
  "nanoid": "^5.0.8",
123
126
  "nanoid-dictionary": "^4.3.0",
@@ -125,6 +128,7 @@
125
128
  "pluralize": "^8.0.0",
126
129
  "pretty-bytes": "^6.1.1",
127
130
  "react-dropzone": "^14.2.2",
131
+ "react-hook-form": "^7.60.0",
128
132
  "react-input-mask": "^2.0.4",
129
133
  "react-number-format": "^4.9.3",
130
134
  "react-querybuilder": "^6.0.2",