@janrankenhohn/react-thumbnail-list 0.5.0 → 0.5.2

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/dist/index.cjs.js CHANGED
@@ -1,320 +1,628 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
- var material = require('@mui/material');
6
- var React = require('react');
7
- var jsxRuntime = require('react/jsx-runtime');
8
- var system = require('@mui/system');
9
- var SearchIcon = require('@mui/icons-material/Search');
10
- var ClearIcon = require('@mui/icons-material/Clear');
11
- var SwapVertIcon = require('@mui/icons-material/SwapVert');
12
- var SortIcon = require('@mui/icons-material/Sort');
13
-
14
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
15
-
16
- var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
17
- var SearchIcon__default = /*#__PURE__*/_interopDefaultLegacy(SearchIcon);
18
- var ClearIcon__default = /*#__PURE__*/_interopDefaultLegacy(ClearIcon);
19
- var SwapVertIcon__default = /*#__PURE__*/_interopDefaultLegacy(SwapVertIcon);
20
- var SortIcon__default = /*#__PURE__*/_interopDefaultLegacy(SortIcon);
21
-
22
- function HelloWorld() {
23
- return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement("h1", null, "Hello World"), /*#__PURE__*/React__default["default"].createElement(material.Button, {
24
- variant: "contained"
25
- }, "Contained"));
26
- }
27
-
28
- /* eslint-disable @typescript-eslint/no-explicit-any */
29
- const ThumbnailListItemContext = React.createContext(undefined);
30
- // Create a custom hook to consume the context
31
- const useThumbnailListItemContext = () => {
32
- const context = React.useContext(ThumbnailListItemContext);
33
- if (!context) {
34
- throw new Error('useMyContext must be used within a MyContextProvider');
35
- }
36
- return context;
37
- };
38
-
39
- /**
40
- * Can be used as parent component to crop a wrapped image
41
- * @param props width: width for cropping
42
- * height: height for cropping
43
- * seperate xs and sm values for mui breakpoints
44
- * @returns component
45
- */
46
- function ImageCropper(props) {
47
- const ThumbnailImageCrop = material.styled('div')((p) => ({
48
- [p.theme.breakpoints.up('xs')]: {
49
- minWidth: props.width.xs,
50
- maxWidth: props.width.xs,
51
- height: props.height.xs,
52
- overflow: 'hidden'
53
- },
54
- [p.theme.breakpoints.up('sm')]: {
55
- minWidth: props.width.sm,
56
- maxwWidth: props.width.sm,
57
- height: props.height.sm,
58
- },
59
- }));
60
- return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(ThumbnailImageCrop, { children: props.children }) }));
61
- }
62
-
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+ var material = require('@mui/material');
7
+ var React = require('react');
8
+ var system = require('@mui/system');
9
+ var SearchIcon = require('@mui/icons-material/Search');
10
+ var ClearIcon = require('@mui/icons-material/Clear');
11
+ var lodash = require('lodash');
12
+ var SwapVertIcon = require('@mui/icons-material/SwapVert');
13
+ var SortIcon = require('@mui/icons-material/Sort');
14
+
15
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
16
+
17
+ var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
18
+ var SearchIcon__default = /*#__PURE__*/_interopDefaultLegacy(SearchIcon);
19
+ var ClearIcon__default = /*#__PURE__*/_interopDefaultLegacy(ClearIcon);
20
+ var SwapVertIcon__default = /*#__PURE__*/_interopDefaultLegacy(SwapVertIcon);
21
+ var SortIcon__default = /*#__PURE__*/_interopDefaultLegacy(SortIcon);
22
+
23
+ const ThumbnailListItemContext = /*#__PURE__*/React.createContext(undefined);
24
+ const useThumbnailListItemContext = () => {
25
+ const context = React.useContext(ThumbnailListItemContext);
26
+ if (!context) {
27
+ throw new Error('no context provider available');
28
+ }
29
+ return context;
30
+ };
31
+
63
32
  /**
64
33
  * Creates a ellipies text with webkit css styles
65
34
  * @param props lineClamp: lines till ellipses
66
35
  * @returns component
67
- */
68
- function EllipsisContainer(props) {
69
- const EllipsisContainer = material.styled('div')((p) => ({
70
- [p.theme.breakpoints.up('xs')]: {
71
- overflow: 'hidden',
72
- display: '-webkit-box',
73
- WebkitLineClamp: props.lineClamp.xs.toString(),
74
- WebkitBoxOrient: 'vertical',
75
- },
76
- [p.theme.breakpoints.up('sm')]: {
77
- overflow: 'hidden',
78
- display: '-webkit-box',
79
- WebkitLineClamp: props.lineClamp.sm.toString(),
80
- WebkitBoxOrient: 'vertical', /* number of lines to show */
81
- },
82
- }));
83
- return (jsxRuntime.jsx(EllipsisContainer, { children: props.children }));
84
- }
85
-
86
- function ThumbnailListItemTitle(props) {
87
- const StyledCardContent = material.styled('div')((props) => ({
88
- [props.theme.breakpoints.up('xs')]: {
89
- 'padding': props.theme.spacing(1),
90
- 'flex': '1 0 auto',
91
- '&:last-child': { paddingBottom: 0 },
92
- 'overflow': 'hidden',
93
- },
94
- }));
95
- const children = React.Children.toArray(props.children);
96
- return jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(material.Box, { children: jsxRuntime.jsxs(StyledCardContent, { children: [jsxRuntime.jsx(EllipsisContainer, { lineClamp: { xs: 1, sm: 2 }, children: jsxRuntime.jsx(material.Typography, { variant: 'h4', children: props.title }) }), jsxRuntime.jsx(system.Stack, { direction: "row", gap: 1, children: children.map((child, index) => jsxRuntime.jsx(material.Typography, { variant: "subtitle2", color: "text.secondary", children: child }, index)) })] }) }) });
97
- }
98
-
99
- function ThumbnailListItemInfoLabel(props) {
100
- return jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsxs(material.Stack, { textAlign: "right", justifyContent: "space-between", children: [jsxRuntime.jsx(material.Box, { textAlign: "right", padding: 1, children: props.topContent }), jsxRuntime.jsx(material.Box, { textAlign: "right", padding: 1, children: props.bottomContent })] }) });
101
- }
102
-
103
- // import {Link} from 'react-router-dom';
104
- const ThumbnailListItem = (props) => {
105
- return jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(material.Card, { sx: { display: 'flex' }, children: jsxRuntime.jsx(material.CardActionArea, { children: jsxRuntime.jsxs(material.Stack, { direction: "row", width: "100%", children: [jsxRuntime.jsx(ImageCropper, { width: { xs: '98px', sm: '160px' }, height: { xs: '54px', sm: '90px' }, children: jsxRuntime.jsx(material.Box, { children: "Placeholder for image" }) }), jsxRuntime.jsx(material.Stack, { direction: "row", justifyContent: "space-between", width: "100%", gap: 1, children: props.children })] }) }) }) });
106
- };
107
- ThumbnailListItem.Title = ThumbnailListItemTitle;
108
- ThumbnailListItem.InfoLabel = ThumbnailListItemInfoLabel;
109
-
110
- function ThumbnailListMainContent( /* props: {children: ReactNode}*/) {
111
- // const children = Children.toArray(props.children);
112
- const { items } = useThumbnailListItemContext();
113
- return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: items.map((item) => {
114
- return (jsxRuntime.jsx(material.Grid, { item: true, xs: 12, lg: 6, xl: 3, children: jsxRuntime.jsxs(ThumbnailListItem, { id: item.id,
115
- // link={item.link}
116
- thumbnailUrl: item.thumbnailUrl, children: [jsxRuntime.jsx(ThumbnailListItem.Title, { title: item.title, children: item.subTitle }), item.label] }) }, item.id));
117
- }) }));
118
- }
119
-
120
- const ThumbnailListSearchField = () => {
121
- const [input, setInput] = React.useState('');
122
- const [showClearIcon, setShowClearIcon] = React.useState('hidden');
123
- const { setSearchTerm } = useThumbnailListItemContext();
124
- const handleChange = (value) => {
125
- setInput(value);
126
- setShowClearIcon(value === '' ? 'hidden' : '');
127
- setSearchTerm(value);
128
- };
129
- return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(material.FormControl, { children: jsxRuntime.jsx(material.TextField, { sx: { input: { color: 'white' } }, fullWidth: true, value: input, size: "small", variant: "outlined", onChange: (event) => handleChange(event.target.value), InputProps: {
130
- startAdornment: (jsxRuntime.jsx(material.InputAdornment, { position: "start", children: jsxRuntime.jsx(SearchIcon__default["default"], {}) })),
131
- endAdornment: (jsxRuntime.jsx(material.InputAdornment, { position: "end", children: jsxRuntime.jsx(material.IconButton, { onClick: () => handleChange(''), sx: { visibility: showClearIcon, padding: 0 }, children: jsxRuntime.jsx(ClearIcon__default["default"], {}) }) })),
132
- } }) }) }));
133
- };
134
-
135
- function ThumbnailListFilterTag(props) {
136
- const theme = material.useTheme();
137
- const handleOnClick = (value) => {
138
- if (props.onClickCallback) {
139
- props.onClickCallback(value);
140
- }
141
- };
142
- return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: material.useMediaQuery(theme.breakpoints.up(props.collapseBreakpoint ?? 0)) || !props.icon ?
143
- jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(material.Chip, { label: props.label, variant: props.variant, onClick: props.onClickCallback ? () => handleOnClick(props.value) : undefined }) }) :
144
- jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(material.Tooltip, { title: props.label, children: jsxRuntime.jsx(material.IconButton, { onClick: props.onClickCallback ? () => handleOnClick(props.value) : undefined, children: props.icon }) }) }) }));
145
- }
146
-
147
- function ThumbnailListFilterTags(props) {
148
- const { tagFilterCallback, tagAndCondition } = useThumbnailListItemContext();
149
- return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: props.tags.map((tag) => {
150
- return (jsxRuntime.jsx(ThumbnailListFilterTag, { label: tag.label, value: tag.value, variant: tagAndCondition.tag === tag.value ? 'filled' : 'outlined', collapseBreakpoint: props.collapseBreakpoint, onClickCallback: (value) => tagFilterCallback({ tag: value, condition: tag.condition }), icon: tag.icon }));
151
- }) }));
152
- }
153
-
154
- /**
155
- * Displays a generic MUI select dropdown.
156
- * Optinal collapses to a sort icon at a certain breakpoint
157
- * @param props.label Select Label
158
- * @param props.width * Width of the input field
159
- * @param props.collapseBreakPoint * MUI breakpoint after that the select will collapse to the sort icon
160
- * @param props.onChangeCallback * Callback function that gets triggered once a item is selected
161
- * @param props.items * Array of items (name-value-pairs) that will be the select options
162
- * @returns Drowpdown Input Component
163
- */
164
- function DropdownInput(props) {
165
- const [value, setValue] = React.useState(props.defaultValue ?? '');
166
- const theme = material.useTheme();
167
- const [anchorEl, setAnchorEl] = React.useState(null);
168
- const handleChange = (value, name) => {
169
- setValue(value);
170
- setAnchorEl(null);
171
- props.onChangeCallback(value, name);
172
- };
173
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [material.useMediaQuery(theme.breakpoints.up(props.collapseBreakpoint ?? 0)) ?
174
- jsxRuntime.jsxs(material.FormControl, { sx: { width: props.width, textAlign: 'start' }, children: [jsxRuntime.jsx(material.InputLabel, { size: 'small', id: "demo-simple-select-label", children: props.label }), jsxRuntime.jsx(material.Select, { value: value, size: 'small', label: props.label, onChange: (event) => handleChange(event.target.value, event.target.name), children: props.items.map((item) => {
175
- return jsxRuntime.jsx(material.MenuItem, { value: item.value, children: item.name }, item.value);
176
- }) })] }) : (jsxRuntime.jsx(material.IconButton
177
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
178
- , {
179
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
180
- onClick: (event) => setAnchorEl(event.currentTarget), children: props.icon })), jsxRuntime.jsx(material.Menu, { anchorEl: anchorEl, open: Boolean(anchorEl), onClose: () => setAnchorEl(null), children: props.items.map((item) => (jsxRuntime.jsx(material.MenuItem, { onClick: () => handleChange(item.value), children: item.name }, item.value))) })] }));
181
- }
182
-
183
- function ThumbnailListHeaderSort(props) {
184
- const { setSortAscending, sortAscending, setSortBy } = useThumbnailListItemContext();
185
- return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsxs(material.Box, { sx: { width: '-webkit-fill-available', textAlign: 'end' }, children: [jsxRuntime.jsx(material.Tooltip, { title: "asc/desc", children: jsxRuntime.jsx(material.IconButton, { onClick: () => setSortAscending(!sortAscending), children: jsxRuntime.jsx(SwapVertIcon__default["default"], {}) }) }), jsxRuntime.jsx(DropdownInput, { width: "130px", collapseBreakpoint: 'md', label: 'sort', defaultValue: "creationTimeStamp", icon: jsxRuntime.jsx(material.Tooltip, { title: 'sort', children: jsxRuntime.jsx(SortIcon__default["default"], {}) }), items: props.items, onChangeCallback: (value) => setSortBy(value) })] }) }));
186
- }
187
-
188
- const ThumbnailListHeader = function (props) {
189
- return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(material.Grid, { item: true, xs: 12, children: jsxRuntime.jsx(material.Stack, { direction: "row", alignItems: "center", justifyContent: props.justifyContent ?? 'space-between', gap: 2, children: props.children }) }) }));
190
- };
191
- ThumbnailListHeader.SearchField = ThumbnailListSearchField;
192
- ThumbnailListHeader.FilterTags = ThumbnailListFilterTags;
193
- ThumbnailListHeader.Sort = ThumbnailListHeaderSort;
194
-
36
+ */
37
+ function EllipsisContainer(props) {
38
+ const EllipsisContainer = material.styled('div')(p => ({
39
+ [p.theme.breakpoints.up('xs')]: {
40
+ overflow: 'hidden',
41
+ display: '-webkit-box',
42
+ WebkitLineClamp: props.lineClamp.xs.toString() /* number of lines to show */,
43
+ WebkitBoxOrient: 'vertical'
44
+ },
45
+ [p.theme.breakpoints.up('sm')]: {
46
+ overflow: 'hidden',
47
+ display: '-webkit-box',
48
+ WebkitLineClamp: props.lineClamp.sm.toString() /* number of lines to show */,
49
+ WebkitBoxOrient: 'vertical' /* number of lines to show */
50
+ }
51
+ }));
52
+ return jsxRuntime.jsx(EllipsisContainer, {
53
+ children: props.children
54
+ });
55
+ }
56
+
57
+ function ThumbnailListItemTitle(props) {
58
+ const StyledCardContent = material.styled('div')(p => ({
59
+ [p.theme.breakpoints.up('xs')]: {
60
+ padding: p.theme.spacing(1),
61
+ flex: '1 0 auto',
62
+ '&:last-child': {
63
+ paddingBottom: 0
64
+ },
65
+ overflow: 'hidden'
66
+ }
67
+ }));
68
+ console.log('item title rerenders');
69
+ return jsxRuntime.jsx(jsxRuntime.Fragment, {
70
+ children: jsxRuntime.jsx(material.Box, {
71
+ children: jsxRuntime.jsxs(StyledCardContent, {
72
+ children: [jsxRuntime.jsx(EllipsisContainer, {
73
+ lineClamp: {
74
+ xs: 1,
75
+ sm: 2
76
+ },
77
+ children: jsxRuntime.jsx(material.Typography, {
78
+ variant: "subtitle2",
79
+ sx: {
80
+ fontWeight: 'bold'
81
+ },
82
+ children: props.title
83
+ })
84
+ }), jsxRuntime.jsx(system.Stack, {
85
+ direction: "row",
86
+ gap: 1,
87
+ children: jsxRuntime.jsx(EllipsisContainer, {
88
+ lineClamp: {
89
+ xs: 1,
90
+ sm: 2
91
+ },
92
+ children: jsxRuntime.jsx(material.Typography, {
93
+ variant: "subtitle2",
94
+ sx: {
95
+ fontSize: '0.84rem'
96
+ },
97
+ color: "text.secondary",
98
+ children: props.subTitle
99
+ })
100
+ })
101
+ })]
102
+ })
103
+ })
104
+ });
105
+ }
106
+
107
+ const ThumbnailListItem = props => {
108
+ console.log('ThumbnailListItems renders');
109
+ return jsxRuntime.jsx(jsxRuntime.Fragment, {
110
+ children: jsxRuntime.jsx(material.Card, {
111
+ sx: {
112
+ display: 'flex'
113
+ },
114
+ children: jsxRuntime.jsx(material.CardActionArea, {
115
+ disabled: !props.onClick,
116
+ onClick: () => props.onClick(props.id),
117
+ children: jsxRuntime.jsxs(material.Stack, {
118
+ direction: "row",
119
+ width: "100%",
120
+ children: [jsxRuntime.jsx("img", {
121
+ src: props.thumbnailUrl,
122
+ width: '45%'
123
+ }), jsxRuntime.jsxs(material.Stack, {
124
+ direction: "row",
125
+ justifyContent: "space-between",
126
+ width: "100%",
127
+ gap: 1,
128
+ children: [jsxRuntime.jsx(ThumbnailListItemTitle, {
129
+ title: props.title,
130
+ subTitle: props.subTitle
131
+ }), props.infoLabel]
132
+ })]
133
+ })
134
+ })
135
+ })
136
+ });
137
+ };
138
+ var ThumbnailListItem$1 = /*#__PURE__*/React__default["default"].memo(ThumbnailListItem);
139
+
140
+ const RatioWrapper = material.styled('div')(() => ({
141
+ // Assuming a 16:9 aspect ratio
142
+ paddingTop: '27.75%',
143
+ position: 'relative',
144
+ width: '100%',
145
+ '& > *': {
146
+ position: 'absolute',
147
+ top: 0,
148
+ left: 0,
149
+ right: 0,
150
+ bottom: 0
151
+ }
152
+ }));
153
+ function ThumbnailListMainContent(props) {
154
+ const {
155
+ items,
156
+ isLoading
157
+ } = useThumbnailListItemContext();
158
+ console.log('main content rerenders');
159
+ const memoizedItems = React.useMemo(() => {
160
+ return items.map(item => jsxRuntime.jsx(material.Grid, {
161
+ item: true,
162
+ xs: props.muiBreakpoints.xs,
163
+ sm: props.muiBreakpoints.sm,
164
+ md: props.muiBreakpoints.md,
165
+ lg: props.muiBreakpoints.lg,
166
+ xl: props.muiBreakpoints.xl,
167
+ children: jsxRuntime.jsx(RatioWrapper, {
168
+ children: jsxRuntime.jsx(ThumbnailListItem$1, {
169
+ id: item.id,
170
+ thumbnailUrl: item.thumbnailUrl,
171
+ title: item.title,
172
+ subTitle: item.subTitle,
173
+ infoLabel: item.label,
174
+ onClick: item.onClick
175
+ })
176
+ })
177
+ }, item.id));
178
+ }, [items, props.muiBreakpoints]);
179
+ return jsxRuntime.jsxs(jsxRuntime.Fragment, {
180
+ children: [jsxRuntime.jsx(material.Box, {
181
+ sx: {
182
+ mt: 0.75,
183
+ mb: 0.75
184
+ },
185
+ children: jsxRuntime.jsx(material.LinearProgress, {
186
+ sx: {
187
+ opacity: isLoading ? 1 : 0
188
+ }
189
+ })
190
+ }), jsxRuntime.jsx(material.Grid, {
191
+ container: true,
192
+ spacing: props.spacing,
193
+ children: memoizedItems
194
+ })]
195
+ });
196
+ }
197
+ ThumbnailListMainContent.defaultProps = {
198
+ spacing: 2,
199
+ muiBreakpoints: {
200
+ xs: 12,
201
+ sm: 6,
202
+ md: 6,
203
+ lg: 4,
204
+ xl: 3
205
+ }
206
+ };
207
+
195
208
  /**
196
209
  * Generic method that sorts an array of items based on an item key
197
210
  * @param values The array that should be sorted
198
211
  * @param orderType The key of the entity that the array should be sorted by
199
212
  * @returns A new reference of the ordered array
200
- */
201
- function orderByArray(values, orderType) {
202
- return [...values].sort((a, b) => {
203
- const valueA = getComparableValue(a[orderType]);
204
- const valueB = getComparableValue(b[orderType]);
205
- return compareValues(valueA, valueB);
206
- });
207
- }
208
- function getComparableValue(value) {
209
- if (typeof value === 'number') {
210
- return value;
211
- }
212
- else {
213
- return String(value);
214
- }
215
- }
216
- function compareValues(a, b) {
217
- if (typeof a === 'string' && typeof b === 'string') {
218
- return a.localeCompare(b, undefined, { sensitivity: 'base' });
219
- }
220
- else {
221
- return a < b ? -1 : a > b ? 1 : 0;
222
- }
223
- }
224
- function filterByTag(array, tagType, condition) {
225
- const filteredArray = array.filter((item) => {
226
- const tagValue = item[tagType];
227
- return condition ? condition(tagValue) : !!tagValue;
228
- });
229
- console.log('filter array');
230
- console.log(filteredArray);
231
- return [...filteredArray];
232
- }
233
-
234
- // /* eslint-disable @typescript-eslint/no-explicit-any */
235
- const useTagFilteredThumbnailListItems = ({ allItems, initialTag, initialCondition }) => {
236
- const [tagAndCondition, setTagAndCondition] = React.useState({ tag: initialTag, condition: initialCondition });
237
- const [tagFilteredItems, setTagFilteredItems] = React.useState(allItems);
238
- const setTagWithCondition = (t, c) => {
239
- setTagAndCondition({ tag: t, condition: c });
240
- };
241
- React.useEffect(() => {
242
- const tagFiltered = tagAndCondition.tag === 'id' ?
243
- allItems :
244
- filterByTag(allItems, tagAndCondition.tag, tagAndCondition.condition);
245
- setTagFilteredItems(tagFiltered);
246
- }, [allItems, tagAndCondition]);
247
- return {
248
- tagAndCondition,
249
- setTagAndCondition,
250
- tagFilteredItems,
251
- setTagWithCondition,
252
- };
253
- };
254
-
213
+ */
214
+ function orderByArray(values, orderType) {
215
+ return [...values].sort((a, b) => {
216
+ const valueA = getComparableValue(a[orderType]);
217
+ const valueB = getComparableValue(b[orderType]);
218
+ return compareValues(valueA, valueB);
219
+ });
220
+ }
221
+ function getComparableValue(value) {
222
+ if (typeof value === 'number') {
223
+ return value;
224
+ } else {
225
+ return String(value);
226
+ }
227
+ }
228
+ function compareValues(a, b) {
229
+ if (typeof a === 'string' && typeof b === 'string') {
230
+ return a.localeCompare(b, undefined, {
231
+ sensitivity: 'base'
232
+ });
233
+ } else {
234
+ return a < b ? -1 : a > b ? 1 : 0;
235
+ }
236
+ }
237
+ function filterByTag(array, tagType, condition) {
238
+ const filteredArray = array.filter(item => {
239
+ const tagValue = item[tagType];
240
+ return condition ? condition(tagValue) : !!tagValue;
241
+ });
242
+ console.log('filter array');
243
+ console.log(filteredArray);
244
+ return [...filteredArray];
245
+ }
246
+
247
+ const useTagFilteredThumbnailListItems = _ref => {
248
+ let {
249
+ allItems,
250
+ initialTag,
251
+ initialCondition
252
+ } = _ref;
253
+ const [tagAndCondition, setTagAndCondition] = React.useState({
254
+ tag: initialTag,
255
+ condition: initialCondition
256
+ });
257
+ const setTagWithCondition = (t, c) => {
258
+ setTagAndCondition({
259
+ tag: t,
260
+ condition: c
261
+ });
262
+ };
263
+ const tagFilteredItems = React.useMemo(() => {
264
+ const tagFiltered = tagAndCondition.tag === 'id' ? allItems : filterByTag(allItems, tagAndCondition.tag, tagAndCondition.condition);
265
+ return tagFiltered;
266
+ }, [allItems, tagAndCondition]);
267
+ return {
268
+ tagAndCondition,
269
+ setTagAndCondition,
270
+ tagFilteredItems,
271
+ setTagWithCondition
272
+ };
273
+ };
274
+
255
275
  /**
256
276
  * Filters a list of event by a search term
257
277
  * @param allEvents event list that will be formatted
258
278
  * @param initialSearchTerm
259
279
  * @returns
260
- */
261
- const useFilteredThumbnailListItems = (allItems, initialSearchTerm = '') => {
262
- const [searchTerm, setSearchTerm] = React.useState(initialSearchTerm);
263
- const [filteredItems, setFilteredItems] = React.useState(allItems);
264
- React.useEffect(() => {
265
- const filterEvents = () => {
266
- const filtered = [...allItems].filter((item) => item.title.toLowerCase().includes(searchTerm.toLowerCase()));
267
- setFilteredItems(filtered);
268
- };
269
- filterEvents();
270
- }, [allItems, searchTerm]);
271
- return { searchTerm, setSearchTerm, filteredItems };
272
- };
273
-
274
- const useSortedThumbnailListItems = (allItems, initialSortBy, initialSortAscending) => {
275
- const [sortBy, setSortBy] = React.useState(initialSortBy);
276
- const [sortAscending, setSortAscending] = React.useState(initialSortAscending);
277
- const [sortedItems, setSortedItems] = React.useState(allItems);
278
- React.useEffect(() => {
279
- let sorted = orderByArray(allItems, sortBy);
280
- if (!sortAscending) {
281
- sorted = sorted.reverse();
282
- }
283
- setSortedItems(sorted);
284
- }, [allItems, sortBy, sortAscending, initialSortBy, initialSortAscending]);
285
- return { sortBy, sortAscending, setSortBy, setSortAscending, sortedItems };
286
- };
287
-
288
- const ThumbnailList = function (props) {
289
- // const [originalItems, setOriginalItems] = useState(props.items);
290
- const [listItems, setListItems] = React.useState(props.items);
291
- const { sortedItems, setSortBy, setSortAscending, sortAscending } = useSortedThumbnailListItems(listItems, 'creationTimeStamp', false);
292
- const { setSearchTerm, filteredItems } = useFilteredThumbnailListItems(sortedItems);
293
- const { tagFilteredItems, setTagAndCondition, tagAndCondition } = useTagFilteredThumbnailListItems({ allItems: filteredItems, initialTag: 'id' });
294
- console.log('tag filterd');
295
- console.log(tagFilteredItems);
296
- console.log(listItems);
297
- React.useEffect(() => {
298
- if (props.items) {
299
- // setOriginalItems(props.items);
300
- setListItems(props.items);
301
- }
302
- }, [props.items]);
303
- return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(ThumbnailListItemContext.Provider, { value: {
304
- items: tagFilteredItems,
305
- setItems: setListItems,
306
- originalItems: listItems,
307
- setOriginalItems: setListItems,
308
- tagFilterCallback: setTagAndCondition,
309
- tagAndCondition: tagAndCondition,
310
- setSearchTerm: setSearchTerm,
311
- setSortAscending: setSortAscending,
312
- sortAscending: sortAscending,
313
- setSortBy: setSortBy,
314
- }, children: jsxRuntime.jsx(material.Grid, { container: true, spacing: 2, children: props.children }) }) }));
315
- };
316
- ThumbnailList.MainContent = ThumbnailListMainContent;
317
- ThumbnailList.Header = ThumbnailListHeader;
318
-
319
- exports.HelloWorld = HelloWorld;
320
- exports.ThumbnailList = ThumbnailList;
280
+ */
281
+ const useFilteredThumbnailListItems = function (allItems) {
282
+ let initialSearchTerm = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
283
+ const [searchTerm, setSearchTerm] = React.useState(initialSearchTerm);
284
+ const filteredItems = React.useMemo(() => {
285
+ const filtered = [...allItems].filter(item => item.title.toLowerCase().includes(searchTerm.toLowerCase()));
286
+ return filtered;
287
+ }, [allItems, searchTerm]);
288
+ return {
289
+ searchTerm,
290
+ setSearchTerm,
291
+ filteredItems
292
+ };
293
+ };
294
+
295
+ const useSortedThumbnailListItems = (allItems, initialSortBy, initialSortAscending) => {
296
+ const [sortBy, setSortBy] = React.useState(initialSortBy);
297
+ const [sortAscending, setSortAscending] = React.useState(initialSortAscending);
298
+ const sortedItems = React.useMemo(() => {
299
+ let sorted = orderByArray(allItems, sortBy);
300
+ if (!sortAscending) {
301
+ sorted = sorted.reverse();
302
+ }
303
+ return sorted;
304
+ }, [allItems, sortBy, sortAscending]);
305
+ return {
306
+ sortBy,
307
+ sortAscending,
308
+ setSortBy,
309
+ setSortAscending,
310
+ sortedItems
311
+ };
312
+ };
313
+
314
+ const defaultConfiguration = {
315
+ sortBy: 'id',
316
+ sortAscending: true,
317
+ tag: 'id'
318
+ };
319
+
320
+ const ThumbnailListSearchField = () => {
321
+ const [input, setInput] = React.useState('');
322
+ const [showClearIcon, setShowClearIcon] = React.useState('hidden');
323
+ const {
324
+ setSearchTerm
325
+ } = useThumbnailListItemContext();
326
+ console.log('Searchfield rerenders');
327
+ const handleChange = value => {
328
+ setInput(value);
329
+ setShowClearIcon(value === '' ? 'hidden' : '');
330
+ };
331
+ const debouncedSetSearchTerm = React.useCallback(lodash.debounce(setSearchTerm, 50), []);
332
+ React.useEffect(() => {
333
+ debouncedSetSearchTerm(input);
334
+ return () => {
335
+ debouncedSetSearchTerm.cancel();
336
+ };
337
+ }, [input, debouncedSetSearchTerm]);
338
+ return jsxRuntime.jsx(material.Box, {
339
+ sx: {
340
+ marginLeft: 'auto'
341
+ },
342
+ children: jsxRuntime.jsx(material.FormControl, {
343
+ children: jsxRuntime.jsx(material.TextField, {
344
+ fullWidth: true,
345
+ value: input,
346
+ size: "small",
347
+ variant: "outlined",
348
+ onChange: event => handleChange(event.target.value),
349
+ InputProps: {
350
+ startAdornment: jsxRuntime.jsx(material.InputAdornment, {
351
+ position: "start",
352
+ children: jsxRuntime.jsx(SearchIcon__default["default"], {})
353
+ }),
354
+ endAdornment: jsxRuntime.jsx(material.InputAdornment, {
355
+ position: "end",
356
+ children: jsxRuntime.jsx(material.IconButton, {
357
+ onClick: () => handleChange(''),
358
+ sx: {
359
+ visibility: showClearIcon,
360
+ padding: 0
361
+ },
362
+ children: jsxRuntime.jsx(ClearIcon__default["default"], {})
363
+ })
364
+ })
365
+ }
366
+ })
367
+ })
368
+ });
369
+ };
370
+ ThumbnailListSearchField.defaultProps = {
371
+ align: 'start'
372
+ };
373
+ var ThumbnailListSearchField$1 = /*#__PURE__*/React__default["default"].memo(ThumbnailListSearchField);
374
+
375
+ function ThumbnailListFilterTag(props) {
376
+ var _props$collapseBreakp;
377
+ const theme = material.useTheme();
378
+ const handleOnClick = value => {
379
+ if (props.onClickCallback) {
380
+ props.onClickCallback(value);
381
+ }
382
+ };
383
+ return jsxRuntime.jsx(jsxRuntime.Fragment, {
384
+ children: material.useMediaQuery(theme.breakpoints.up((_props$collapseBreakp = props.collapseBreakpoint) !== null && _props$collapseBreakp !== void 0 ? _props$collapseBreakp : 0)) || !props.icon ? jsxRuntime.jsx(jsxRuntime.Fragment, {
385
+ children: jsxRuntime.jsx(material.Chip, {
386
+ label: props.label,
387
+ variant: props.variant,
388
+ onClick: props.onClickCallback ? () => handleOnClick(props.value) : undefined
389
+ })
390
+ }) : jsxRuntime.jsx(jsxRuntime.Fragment, {
391
+ children: jsxRuntime.jsx(material.Tooltip, {
392
+ title: props.label,
393
+ children: jsxRuntime.jsx(material.IconButton, {
394
+ onClick: props.onClickCallback ? () => handleOnClick(props.value) : undefined,
395
+ children: props.icon
396
+ })
397
+ })
398
+ })
399
+ });
400
+ }
401
+
402
+ function ThumbnailListFilterTags(props) {
403
+ const {
404
+ tagFilterCallback,
405
+ tagAndCondition
406
+ } = useThumbnailListItemContext();
407
+ console.log('filter tags rerenders');
408
+ return jsxRuntime.jsx(jsxRuntime.Fragment, {
409
+ children: props.tags.map((tag, index) => {
410
+ return jsxRuntime.jsx(ThumbnailListFilterTag, {
411
+ label: tag.label,
412
+ value: tag.key.toString(),
413
+ variant: tagAndCondition.tag === tag.key ? 'filled' : 'outlined',
414
+ collapseBreakpoint: props.muiCollapseBreakpoint,
415
+ onClickCallback: value => tagFilterCallback({
416
+ tag: value,
417
+ condition: tag.condition
418
+ }),
419
+ icon: tag.icon
420
+ }, "".concat(index, "_").concat(tag.key.toString()));
421
+ })
422
+ });
423
+ }
424
+ ThumbnailListFilterTags.defaultProps = {
425
+ align: 'start',
426
+ muiCollapseBreakpoint: 'md'
427
+ };
428
+
429
+ /**
430
+ * Displays a generic MUI select dropdown.
431
+ * Optinal collapses to a sort icon at a certain breakpoint
432
+ * @param props.label Select Label
433
+ * @param props.width * Width of the input field
434
+ * @param props.collapseBreakPoint * MUI breakpoint after that the select will collapse to the sort icon
435
+ * @param props.onChangeCallback * Callback function that gets triggered once a item is selected
436
+ * @param props.items * Array of items (name-value-pairs) that will be the select options
437
+ * @returns Drowpdown Input Component
438
+ */
439
+ function DropdownInput(props) {
440
+ var _props$defaultValue, _props$collapseBreakp;
441
+ const [value, setValue] = React.useState((_props$defaultValue = props.defaultValue) !== null && _props$defaultValue !== void 0 ? _props$defaultValue : '');
442
+ const theme = material.useTheme();
443
+ const [anchorEl, setAnchorEl] = React.useState(null);
444
+ const handleChange = (value, name) => {
445
+ setValue(value);
446
+ setAnchorEl(null);
447
+ props.onChangeCallback(value, name);
448
+ };
449
+ return jsxRuntime.jsxs(jsxRuntime.Fragment, {
450
+ children: [material.useMediaQuery(theme.breakpoints.up((_props$collapseBreakp = props.collapseBreakpoint) !== null && _props$collapseBreakp !== void 0 ? _props$collapseBreakp : 0)) ? jsxRuntime.jsxs(material.FormControl, {
451
+ sx: {
452
+ width: props.width,
453
+ textAlign: 'start'
454
+ },
455
+ children: [jsxRuntime.jsx(material.InputLabel, {
456
+ size: "small",
457
+ children: props.label
458
+ }), jsxRuntime.jsx(material.Select, {
459
+ value: value,
460
+ size: "small",
461
+ label: props.label,
462
+ onChange: event => handleChange(event.target.value, event.target.name),
463
+ children: props.items.map(item => {
464
+ return jsxRuntime.jsx(material.MenuItem, {
465
+ value: item.value,
466
+ children: item.name
467
+ }, item.value);
468
+ })
469
+ })]
470
+ }) : jsxRuntime.jsx(material.IconButton
471
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
472
+ , {
473
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
474
+ onClick: event => setAnchorEl(event.currentTarget),
475
+ children: props.icon
476
+ }), jsxRuntime.jsx(material.Menu, {
477
+ anchorEl: anchorEl,
478
+ open: Boolean(anchorEl),
479
+ onClose: () => setAnchorEl(null),
480
+ children: props.items.map(item => jsxRuntime.jsx(material.MenuItem, {
481
+ onClick: () => handleChange(item.value),
482
+ children: item.name
483
+ }, item.value))
484
+ })]
485
+ });
486
+ }
487
+
488
+ function ThumbnailListHeaderSort(props) {
489
+ const {
490
+ setSortAscending,
491
+ sortAscending,
492
+ setSortBy,
493
+ sortBy
494
+ } = useThumbnailListItemContext();
495
+ console.log('Header sort rerenders');
496
+ return jsxRuntime.jsx(jsxRuntime.Fragment, {
497
+ children: jsxRuntime.jsxs(material.Box, {
498
+ sx: {
499
+ minWidth: '80px'
500
+ },
501
+ children: [jsxRuntime.jsx(material.Tooltip, {
502
+ title: "asc/desc",
503
+ children: jsxRuntime.jsx(material.IconButton, {
504
+ onClick: () => setSortAscending(!sortAscending),
505
+ children: jsxRuntime.jsx(SwapVertIcon__default["default"], {})
506
+ })
507
+ }), jsxRuntime.jsx(DropdownInput, {
508
+ width: "130px",
509
+ collapseBreakpoint: props.muiBreakpoint,
510
+ label: 'sort',
511
+ defaultValue: sortBy,
512
+ icon: jsxRuntime.jsx(material.Tooltip, {
513
+ title: 'sort',
514
+ children: jsxRuntime.jsx(SortIcon__default["default"], {})
515
+ }),
516
+ items: props.items.map(i => {
517
+ return {
518
+ name: i.label,
519
+ value: i.key.toString()
520
+ };
521
+ }),
522
+ onChangeCallback: value => setSortBy(value)
523
+ })]
524
+ })
525
+ });
526
+ }
527
+ ThumbnailListHeaderSort.defaultProps = {
528
+ align: 'start',
529
+ muiBreakpoint: 'md'
530
+ };
531
+
532
+ const ThumbnailListHeader = function (props) {
533
+ var _props$justifyContent;
534
+ const startAlignedItems = [];
535
+ const endAlignedItems = [];
536
+ // Iterate through each child to categorize them based on their 'align' prop
537
+ React.Children.forEach(props.children, child => {
538
+ if ( /*#__PURE__*/React__default["default"].isValidElement(child)) {
539
+ const alignment = child.props.align || 'start';
540
+ if (alignment === 'end') {
541
+ endAlignedItems.push(child);
542
+ } else {
543
+ startAlignedItems.push(child);
544
+ }
545
+ }
546
+ });
547
+ return jsxRuntime.jsx(jsxRuntime.Fragment, {
548
+ children: jsxRuntime.jsxs(material.Stack, {
549
+ direction: "row",
550
+ alignItems: "center",
551
+ justifyContent: (_props$justifyContent = props.justifyContent) !== null && _props$justifyContent !== void 0 ? _props$justifyContent : 'space-between',
552
+ gap: 2,
553
+ children: [jsxRuntime.jsx(material.Stack, {
554
+ direction: "row",
555
+ alignItems: "center",
556
+ gap: 2,
557
+ justifyContent: "start",
558
+ children: startAlignedItems
559
+ }), endAlignedItems]
560
+ })
561
+ });
562
+ };
563
+ ThumbnailListHeader.SearchField = ThumbnailListSearchField$1;
564
+ ThumbnailListHeader.FilterTags = ThumbnailListFilterTags;
565
+ ThumbnailListHeader.Sort = ThumbnailListHeaderSort;
566
+
567
+ /**
568
+ * Main Component: Renders all sub components
569
+ * Includes ThumbnailList Provider for context data
570
+ * @param props react children, items
571
+ * @returns component
572
+ */
573
+ function ThumbnailList(props) {
574
+ const combinedConfig = {
575
+ ...defaultConfiguration,
576
+ ...props.config // This will override the defaults with any props that are not undefined
577
+ };
578
+ const [listItems, setListItems] = React.useState(props.items);
579
+ const {
580
+ sortedItems,
581
+ setSortBy,
582
+ setSortAscending,
583
+ sortAscending
584
+ } = useSortedThumbnailListItems(listItems, combinedConfig.sortBy.toString(), combinedConfig.sortAscending);
585
+ const {
586
+ tagFilteredItems,
587
+ setTagAndCondition,
588
+ tagAndCondition
589
+ } = useTagFilteredThumbnailListItems({
590
+ allItems: sortedItems,
591
+ initialTag: combinedConfig.tag.toString()
592
+ });
593
+ const {
594
+ setSearchTerm,
595
+ filteredItems
596
+ } = useFilteredThumbnailListItems(tagFilteredItems);
597
+ console.log('Thumbnaillist renders');
598
+ return jsxRuntime.jsx(jsxRuntime.Fragment, {
599
+ children: jsxRuntime.jsx(ThumbnailListItemContext.Provider, {
600
+ value: {
601
+ items: filteredItems,
602
+ setItems: setListItems,
603
+ originalItems: listItems,
604
+ setOriginalItems: setListItems,
605
+ tagFilterCallback: setTagAndCondition,
606
+ tagAndCondition: tagAndCondition,
607
+ setSearchTerm: setSearchTerm,
608
+ setSortAscending: setSortAscending,
609
+ sortAscending: sortAscending,
610
+ setSortBy: setSortBy,
611
+ sortBy: combinedConfig.sortBy.toString(),
612
+ isLoading: false
613
+ },
614
+ children: jsxRuntime.jsx(material.Stack, {
615
+ direction: "column",
616
+ sx: {
617
+ width: '100%',
618
+ minWidth: '425px'
619
+ },
620
+ children: props.children
621
+ })
622
+ })
623
+ });
624
+ }
625
+ ThumbnailList.MainContent = ThumbnailListMainContent;
626
+ ThumbnailList.Header = ThumbnailListHeader;
627
+
628
+ exports.ThumbnailList = ThumbnailList;