@abcagency/hc-ui-components 1.3.29 → 1.3.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.
- package/dist/components/modules/list/field-mapper.js +2 -2
- package/dist/components/modules/list/field-mapper.js.map +1 -1
- package/dist/components/modules/list/header-item.js +2 -1
- package/dist/components/modules/list/header-item.js.map +1 -1
- package/dist/components/modules/list/header.js +6 -2
- package/dist/components/modules/list/header.js.map +1 -1
- package/dist/components/modules/list/item-list.js +46 -19
- package/dist/components/modules/list/item-list.js.map +1 -1
- package/dist/components/modules/list/list-item/list-item.js +4 -4
- package/dist/components/modules/list/list-item/list-item.js.map +1 -1
- package/dist/components/modules/maps/info-window-content.js +1 -2
- package/dist/components/modules/maps/info-window-content.js.map +1 -1
- package/dist/styles/index.css +1 -1
- package/dist/types/components/modules/list/header.d.ts +2 -1
- package/package.json +1 -1
- package/src/components/modules/list/field-mapper.js +4 -3
- package/src/components/modules/list/header-item.js +92 -91
- package/src/components/modules/list/header.js +51 -49
- package/src/components/modules/list/item-list.tsx +93 -59
- package/src/components/modules/list/list-item/list-item.js +130 -130
|
@@ -27,14 +27,15 @@ const FieldMapper = ({
|
|
|
27
27
|
|
|
28
28
|
return (
|
|
29
29
|
<>
|
|
30
|
-
{orderedFields.map(field => {
|
|
30
|
+
{orderedFields.map((field, index) => {
|
|
31
31
|
let value = item.fields[field];
|
|
32
32
|
return (
|
|
33
33
|
<Grid.Item
|
|
34
34
|
key={field}
|
|
35
35
|
className={`
|
|
36
|
-
hc-hidden md:hc-block
|
|
37
|
-
${
|
|
36
|
+
hc-hidden md:hc-block hc-px-2
|
|
37
|
+
${index === 0 ? "hc-pl-7" : ""}
|
|
38
|
+
${field.toLowerCase() === "position" ? "hc-col-span-4 hc-text-balance hc-font-semibold" : (field.toLowerCase() === "state" || field.toLowerCase() == "favorite") ? "hc-col-span-1" : "hc-col-span-2"}
|
|
38
39
|
`}
|
|
39
40
|
>
|
|
40
41
|
<span className="hc-sr-only">{capitalize(field)}</span>
|
|
@@ -1,91 +1,92 @@
|
|
|
1
|
-
import React, { useState, useEffect } from 'react';
|
|
2
|
-
|
|
3
|
-
import Button from '~/components/modules/buttons/default';
|
|
4
|
-
|
|
5
|
-
const SORT_STATE = {
|
|
6
|
-
notSorted: "not-sorted",
|
|
7
|
-
sortedAsc: "sorted-asc",
|
|
8
|
-
sortedDesc: "sorted-desc"
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
const HeaderItem = ({
|
|
12
|
-
className,
|
|
13
|
-
children,
|
|
14
|
-
field,
|
|
15
|
-
setSortSetting,
|
|
16
|
-
sortSetting,
|
|
17
|
-
isSortable,
|
|
18
|
-
...rest
|
|
19
|
-
}) => {
|
|
20
|
-
const [isSorted, setIsSorted] = useState(SORT_STATE.notSorted);
|
|
21
|
-
|
|
22
|
-
const handleChange = field => {
|
|
23
|
-
if (isSortable === false)
|
|
24
|
-
return;
|
|
25
|
-
let setting = {
|
|
26
|
-
field: field,
|
|
27
|
-
type: isSorted === SORT_STATE.sortedAsc ? "desc" : "asc"
|
|
28
|
-
};
|
|
29
|
-
setSortSetting(setting);
|
|
30
|
-
isSorted === SORT_STATE.notSorted
|
|
31
|
-
? setIsSorted(SORT_STATE.sortedAsc)
|
|
32
|
-
: isSorted === SORT_STATE.sortedAsc
|
|
33
|
-
? setIsSorted(SORT_STATE.sortedDesc)
|
|
34
|
-
: setIsSorted(SORT_STATE.sortedAsc);
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
useEffect(() => {
|
|
38
|
-
if (sortSetting?.field != null && sortSetting.field != field) {
|
|
39
|
-
setIsSorted(SORT_STATE.notSorted);
|
|
40
|
-
} else if (
|
|
41
|
-
sortSetting?.field != null &&
|
|
42
|
-
isSorted == SORT_STATE.notSorted &&
|
|
43
|
-
sortSetting.field == field
|
|
44
|
-
) {
|
|
45
|
-
setIsSorted(
|
|
46
|
-
sortSetting.type == "asc"
|
|
47
|
-
? SORT_STATE.sortedAsc
|
|
48
|
-
: SORT_STATE.sortedDesc
|
|
49
|
-
);
|
|
50
|
-
}
|
|
51
|
-
}, [sortSetting, isSorted, field]);
|
|
52
|
-
|
|
53
|
-
return (
|
|
54
|
-
<Button.Btn
|
|
55
|
-
onClick={() => handleChange(field)}
|
|
56
|
-
variant="none"
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
${
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
{
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
import Button from '~/components/modules/buttons/default';
|
|
4
|
+
|
|
5
|
+
const SORT_STATE = {
|
|
6
|
+
notSorted: "not-sorted",
|
|
7
|
+
sortedAsc: "sorted-asc",
|
|
8
|
+
sortedDesc: "sorted-desc"
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const HeaderItem = ({
|
|
12
|
+
className,
|
|
13
|
+
children,
|
|
14
|
+
field,
|
|
15
|
+
setSortSetting,
|
|
16
|
+
sortSetting,
|
|
17
|
+
isSortable,
|
|
18
|
+
...rest
|
|
19
|
+
}) => {
|
|
20
|
+
const [isSorted, setIsSorted] = useState(SORT_STATE.notSorted);
|
|
21
|
+
|
|
22
|
+
const handleChange = field => {
|
|
23
|
+
if (isSortable === false)
|
|
24
|
+
return;
|
|
25
|
+
let setting = {
|
|
26
|
+
field: field,
|
|
27
|
+
type: isSorted === SORT_STATE.sortedAsc ? "desc" : "asc"
|
|
28
|
+
};
|
|
29
|
+
setSortSetting(setting);
|
|
30
|
+
isSorted === SORT_STATE.notSorted
|
|
31
|
+
? setIsSorted(SORT_STATE.sortedAsc)
|
|
32
|
+
: isSorted === SORT_STATE.sortedAsc
|
|
33
|
+
? setIsSorted(SORT_STATE.sortedDesc)
|
|
34
|
+
: setIsSorted(SORT_STATE.sortedAsc);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (sortSetting?.field != null && sortSetting.field != field) {
|
|
39
|
+
setIsSorted(SORT_STATE.notSorted);
|
|
40
|
+
} else if (
|
|
41
|
+
sortSetting?.field != null &&
|
|
42
|
+
isSorted == SORT_STATE.notSorted &&
|
|
43
|
+
sortSetting.field == field
|
|
44
|
+
) {
|
|
45
|
+
setIsSorted(
|
|
46
|
+
sortSetting.type == "asc"
|
|
47
|
+
? SORT_STATE.sortedAsc
|
|
48
|
+
: SORT_STATE.sortedDesc
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
}, [sortSetting, isSorted, field]);
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<Button.Btn
|
|
55
|
+
onClick={() => handleChange(field)}
|
|
56
|
+
variant="none"
|
|
57
|
+
size="none"
|
|
58
|
+
className={`
|
|
59
|
+
hc-p-2 hc-rounded-none hc-text-left hc-normal-case hover:hc-bg-uiAccent/5 focus:hc-bg-uiAccent/5
|
|
60
|
+
${field.toLowerCase() === "position" ? "hc-pl-7 hc-col-span-4" : (field.toLowerCase() === "state" || field.toLowerCase() == "favorite") ? "hc-col-span-1" : "hc-col-span-2"}
|
|
61
|
+
${className ?? ""}
|
|
62
|
+
`}
|
|
63
|
+
{...rest}
|
|
64
|
+
>
|
|
65
|
+
<Button.Body>
|
|
66
|
+
<span className="hc-font-semibold">{children}</span>
|
|
67
|
+
{isSortable && (
|
|
68
|
+
<div className="hc-flex hc-flex-col hc-pr-2">
|
|
69
|
+
<Button.Icon
|
|
70
|
+
icon="bi:caret-up-fill"
|
|
71
|
+
size="hc-size-2.5"
|
|
72
|
+
className={`
|
|
73
|
+
hc-transition-opacity
|
|
74
|
+
${isSorted === "sorted-asc" ? "hc-opacity-100 hc-text-primary" : "hc-opacity-30"}
|
|
75
|
+
`}
|
|
76
|
+
/>
|
|
77
|
+
<Button.Icon
|
|
78
|
+
icon="bi:caret-down-fill"
|
|
79
|
+
size="hc-size-2.5"
|
|
80
|
+
className={`
|
|
81
|
+
transition-opacity
|
|
82
|
+
${isSorted === "sorted-desc" ? "hc-opacity-100" : "hc-opacity-30"}
|
|
83
|
+
`}
|
|
84
|
+
/>
|
|
85
|
+
</div>
|
|
86
|
+
)}
|
|
87
|
+
</Button.Body>
|
|
88
|
+
</Button.Btn>
|
|
89
|
+
);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export default HeaderItem;
|
|
@@ -1,49 +1,51 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { twMerge } from 'tailwind-merge';
|
|
3
|
-
|
|
4
|
-
import Grid from '~/components/modules/grid';
|
|
5
|
-
import HeaderItem from '~/components/modules/list/header-item';
|
|
6
|
-
|
|
7
|
-
const ListHeader = ({
|
|
8
|
-
className,
|
|
9
|
-
fieldsShown,
|
|
10
|
-
fieldNames,
|
|
11
|
-
fieldIsSortable = true,
|
|
12
|
-
setSortSetting,
|
|
13
|
-
sortSetting,
|
|
14
|
-
includeFavorite = false
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
{
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { twMerge } from 'tailwind-merge';
|
|
3
|
+
|
|
4
|
+
import Grid from '~/components/modules/grid';
|
|
5
|
+
import HeaderItem from '~/components/modules/list/header-item';
|
|
6
|
+
|
|
7
|
+
const ListHeader = ({
|
|
8
|
+
className,
|
|
9
|
+
fieldsShown,
|
|
10
|
+
fieldNames,
|
|
11
|
+
fieldIsSortable = true,
|
|
12
|
+
setSortSetting,
|
|
13
|
+
sortSetting,
|
|
14
|
+
includeFavorite = false,
|
|
15
|
+
scrollbarWidth
|
|
16
|
+
}) => {
|
|
17
|
+
return (
|
|
18
|
+
<Grid
|
|
19
|
+
columns="hc-grid-flow-col hc-auto-cols-fr"
|
|
20
|
+
gap="hc-gap-0"
|
|
21
|
+
isAnimated={false}
|
|
22
|
+
style={{ paddingRight: `${scrollbarWidth && scrollbarWidth > 0 ? scrollbarWidth + 6 : 1 }px` }}
|
|
23
|
+
className={twMerge`
|
|
24
|
+
hc-hidden md:hc-grid hc-bg-uiAccent/10 hc-border-b hc-border-uiAccent/10 hc-sticky hc-top-0 hc-z-10
|
|
25
|
+
${className ?? ""}
|
|
26
|
+
`}
|
|
27
|
+
>
|
|
28
|
+
{fieldsShown.map(field => (
|
|
29
|
+
<HeaderItem
|
|
30
|
+
key={field}
|
|
31
|
+
isSortable={fieldIsSortable}
|
|
32
|
+
sortSetting={sortSetting}
|
|
33
|
+
field={field}
|
|
34
|
+
setSortSetting={setSortSetting}
|
|
35
|
+
>
|
|
36
|
+
{fieldNames[field]}
|
|
37
|
+
</HeaderItem>
|
|
38
|
+
))}
|
|
39
|
+
{ includeFavorite == true &&
|
|
40
|
+
<HeaderItem key={"favorite"}
|
|
41
|
+
isSortable={false}
|
|
42
|
+
field={"favorite"}
|
|
43
|
+
>
|
|
44
|
+
Favorite
|
|
45
|
+
</HeaderItem>
|
|
46
|
+
}
|
|
47
|
+
</Grid>
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export default ListHeader;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { RefObject, ReactNode } from 'react';
|
|
1
|
+
import React, { useEffect, useRef, useState, RefObject, ReactNode } from 'react';
|
|
2
2
|
import Header from '~/components/modules/list/header';
|
|
3
3
|
import Sort from '~/components/modules/filter/sort';
|
|
4
4
|
import Loading from "~/util/loading";
|
|
@@ -22,63 +22,97 @@ interface ItemsListProps {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
const ItemsList: React.FC<ItemsListProps> = ({
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}) =>
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
25
|
+
fieldNames,
|
|
26
|
+
showMap,
|
|
27
|
+
fieldsShown,
|
|
28
|
+
filteredListings,
|
|
29
|
+
loading,
|
|
30
|
+
sortSetting,
|
|
31
|
+
setSortSetting,
|
|
32
|
+
itemLimit,
|
|
33
|
+
loader,
|
|
34
|
+
scrollContainerRef,
|
|
35
|
+
includeFavorite = false,
|
|
36
|
+
children
|
|
37
|
+
}) => {
|
|
38
|
+
const [scrollbarWidth, setScrollbarWidth] = useState<number>(0);
|
|
39
|
+
|
|
40
|
+
const checkScrollbar = () => {
|
|
41
|
+
if (scrollContainerRef.current) {
|
|
42
|
+
const { scrollHeight, clientHeight, offsetWidth, clientWidth } = scrollContainerRef.current;
|
|
43
|
+
const hasVerticalScrollbar = scrollHeight > clientHeight;
|
|
44
|
+
const newScrollbarWidth = hasVerticalScrollbar ? offsetWidth - clientWidth : 0;
|
|
45
|
+
setScrollbarWidth(newScrollbarWidth);
|
|
46
|
+
console.log('Scrollbar width:', newScrollbarWidth);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
checkScrollbar();
|
|
52
|
+
|
|
53
|
+
const resizeObserver = new ResizeObserver(() => checkScrollbar());
|
|
54
|
+
const mutationObserver = new MutationObserver(() => checkScrollbar());
|
|
55
|
+
|
|
56
|
+
if (scrollContainerRef.current) {
|
|
57
|
+
resizeObserver.observe(scrollContainerRef.current);
|
|
58
|
+
mutationObserver.observe(scrollContainerRef.current, { childList: true, subtree: true, attributes: true });
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return () => {
|
|
62
|
+
if (scrollContainerRef.current) {
|
|
63
|
+
resizeObserver.unobserve(scrollContainerRef.current);
|
|
64
|
+
mutationObserver.disconnect();
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
}, [scrollContainerRef]);
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
<div className="hc-relative hc-bg-white md:hc-px-4 hc-flex hc-flex-col">
|
|
71
|
+
<div className="hc-flex hc-flex-wrap hc-items-center hc-justify-between hc-gap-4 md:hc-mb-2 hc-p-3 md:hc-p-0 hc-bg-uiAccent/10 md:hc-bg-transparent hc-border-b md:hc-border-none hc-border-uiAccent/20">
|
|
72
|
+
<h2 className="hc-text-gray-500 hc-font-semibold hc-text-xs md:hc-text-sm">
|
|
73
|
+
{loading && <span>Loading...</span>}
|
|
74
|
+
{!loading && <span>{filteredListings.length} results</span>}
|
|
75
|
+
</h2>
|
|
76
|
+
<div className="hc-block md:hc-hidden">
|
|
77
|
+
<Sort
|
|
78
|
+
className={''}
|
|
79
|
+
fields={fieldsShown}
|
|
80
|
+
setSortSetting={setSortSetting}
|
|
81
|
+
fieldNames={fieldNames}
|
|
82
|
+
/>
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
<div>
|
|
86
|
+
<Header
|
|
87
|
+
className={''}
|
|
88
|
+
setSortSetting={setSortSetting}
|
|
89
|
+
sortSetting={sortSetting}
|
|
90
|
+
fieldsShown={fieldsShown}
|
|
91
|
+
fieldNames={fieldNames}
|
|
92
|
+
includeFavorite={includeFavorite}
|
|
93
|
+
scrollbarWidth={scrollbarWidth}
|
|
94
|
+
/>
|
|
95
|
+
</div>
|
|
96
|
+
<div
|
|
97
|
+
ref={scrollContainerRef}
|
|
98
|
+
className={`
|
|
99
|
+
hc-flex-grow hc-overflow-y-auto
|
|
100
|
+
${showMap ? "md:hc-max-h-45vh hc-max-h-[100vh]" : "md:hc-max-h-95vh hc-max-h-[95vh]"}
|
|
101
|
+
`}
|
|
102
|
+
>
|
|
103
|
+
{loading ? (
|
|
104
|
+
<div className="hc-flex hc-justify-center hc-items-center hc-pt-20">
|
|
105
|
+
<Loading />
|
|
106
|
+
</div>
|
|
107
|
+
) : (
|
|
108
|
+
children
|
|
109
|
+
)}
|
|
110
|
+
<div ref={loader} style={{ height: "100px", textAlign: "center" }}>
|
|
111
|
+
{filteredListings.length >= itemLimit && <Loading />}
|
|
112
|
+
</div>
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
);
|
|
116
|
+
};
|
|
83
117
|
|
|
84
118
|
export default ItemsList;
|