@abcagency/hc-ui-components 1.0.0

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 (102) hide show
  1. package/dist/globals.css +3 -0
  2. package/dist/index.js +4644 -0
  3. package/dist/output.css +784 -0
  4. package/dist/services/globals.css +3 -0
  5. package/dist/services/listingService.js +606 -0
  6. package/package.json +38 -0
  7. package/postcss.config.js +15 -0
  8. package/rollup.config.js +67 -0
  9. package/src/apis/hcApi.js +68 -0
  10. package/src/clientToken.js +9 -0
  11. package/src/components/layout/footer.js +34 -0
  12. package/src/components/layout/header.js +23 -0
  13. package/src/components/layout/layout.js +36 -0
  14. package/src/components/modules/accordions/MapAccordionItem.js +69 -0
  15. package/src/components/modules/accordions/default.js +173 -0
  16. package/src/components/modules/accordions/filterItem.js +53 -0
  17. package/src/components/modules/accordions/filters.js +44 -0
  18. package/src/components/modules/animations/slidein.js +41 -0
  19. package/src/components/modules/buttons/button-group-apply.js +75 -0
  20. package/src/components/modules/buttons/commute-pill.js +21 -0
  21. package/src/components/modules/buttons/default.js +196 -0
  22. package/src/components/modules/buttons/items-pill.js +31 -0
  23. package/src/components/modules/buttons/pill-wrapper.js +26 -0
  24. package/src/components/modules/buttons/show-all-button.js +20 -0
  25. package/src/components/modules/cards/default.js +168 -0
  26. package/src/components/modules/cards/filter.js +55 -0
  27. package/src/components/modules/dialogs/apply-dialog.js +47 -0
  28. package/src/components/modules/filter/commute.js +149 -0
  29. package/src/components/modules/filter/index.js +86 -0
  30. package/src/components/modules/filter/item.js +77 -0
  31. package/src/components/modules/filter/location.js +69 -0
  32. package/src/components/modules/filter/points-of-interest.js +43 -0
  33. package/src/components/modules/filter/radio-item.js +51 -0
  34. package/src/components/modules/filter/search.js +89 -0
  35. package/src/components/modules/filter/search.js.rej +9 -0
  36. package/src/components/modules/filter/sort.js +83 -0
  37. package/src/components/modules/form.js +362 -0
  38. package/src/components/modules/grid.js +75 -0
  39. package/src/components/modules/icon.js +33 -0
  40. package/src/components/modules/jobListing/listing-details.js +87 -0
  41. package/src/components/modules/jumbotron.js +81 -0
  42. package/src/components/modules/maps/info-window-card.js +17 -0
  43. package/src/components/modules/maps/info-window-content.js +60 -0
  44. package/src/components/modules/maps/list/field-mapper.js +113 -0
  45. package/src/components/modules/maps/list/header-item.js +90 -0
  46. package/src/components/modules/maps/list/header.js +46 -0
  47. package/src/components/modules/maps/list/index.js +104 -0
  48. package/src/components/modules/maps/list/item-expand-card/index.js +21 -0
  49. package/src/components/modules/maps/list/item-expand-card/recruiter-contact-nav.js +48 -0
  50. package/src/components/modules/maps/list/item-expand-card/recruiter-details.js +67 -0
  51. package/src/components/modules/maps/list/item-expand-card/recruiter-headshot.js +22 -0
  52. package/src/components/modules/maps/list/list-item/index.js +133 -0
  53. package/src/components/modules/maps/map-list.js +73 -0
  54. package/src/components/modules/maps/map-marker.js +84 -0
  55. package/src/components/modules/maps/map.js +218 -0
  56. package/src/components/modules/maps/place-marker.js +41 -0
  57. package/src/components/modules/maps/tabs.js +79 -0
  58. package/src/components/modules/navigation/nav-link.js +65 -0
  59. package/src/components/modules/navigation/navbar.js +109 -0
  60. package/src/components/modules/navigation/skip-link.js +21 -0
  61. package/src/components/modules/navigation/social.js +29 -0
  62. package/src/components/modules/sections/default.js +59 -0
  63. package/src/components/modules/sections/sectionContext.js +4 -0
  64. package/src/components/modules/video-player.js +126 -0
  65. package/src/constants/placeTypes.js +8 -0
  66. package/src/contexts/mapContext.js +116 -0
  67. package/src/contexts/mapListContext.js +212 -0
  68. package/src/contexts/placesContext.js +98 -0
  69. package/src/hooks/useClickOutside.js +16 -0
  70. package/src/hooks/useEventListener.js +25 -0
  71. package/src/hooks/useEventTracker.js +19 -0
  72. package/src/hooks/useList.js +102 -0
  73. package/src/hooks/useRefScrollProgress.js +24 -0
  74. package/src/hooks/useScript.js +63 -0
  75. package/src/hooks/useScrollDirection.js +39 -0
  76. package/src/hooks/useSectionTracker.js +95 -0
  77. package/src/hooks/useUserAgent.js +43 -0
  78. package/src/hooks/useWindowSize.js +28 -0
  79. package/src/index.css +25 -0
  80. package/src/index.js +116 -0
  81. package/src/services/configService.js +16 -0
  82. package/src/services/googlePlacesNearbyService.js +33 -0
  83. package/src/services/listingAggregatorService.js +42 -0
  84. package/src/services/listingEntityService.js +14 -0
  85. package/src/services/listingService.js +28 -0
  86. package/src/services/recruiterService.js +17 -0
  87. package/src/styles/fonts.js +0 -0
  88. package/src/styles/globals.css +25 -0
  89. package/src/tailwind/preset.default.js +15 -0
  90. package/src/tailwind/tailwind.config.js +126 -0
  91. package/src/util/arrayUtil.js +3 -0
  92. package/src/util/fieldMapper.js +19 -0
  93. package/src/util/filterUtil.js +195 -0
  94. package/src/util/loading.js +17 -0
  95. package/src/util/localStorageUtil.js +27 -0
  96. package/src/util/mapIconUtil.js +179 -0
  97. package/src/util/mapUtil.js +91 -0
  98. package/src/util/page-head.js +62 -0
  99. package/src/util/provider.js +12 -0
  100. package/src/util/sortUtil.js +33 -0
  101. package/src/util/stringUtils.js +6 -0
  102. package/src/util/urlFilterUtil.js +91 -0
@@ -0,0 +1,21 @@
1
+ import React from 'react';
2
+ import Icon from "~/components/modules/icon";
3
+ import PillWrapper from './pill-wrapper';
4
+
5
+ const CommutePill = ({ travelTime }) => {
6
+ if(!travelTime)return;
7
+ return (
8
+ <div className="pt-2">
9
+ <PillWrapper >
10
+ <Icon
11
+ icon="ri:pin-distance-fill"
12
+ size="w-5 h-5"
13
+ className="text-uiAccent/30"
14
+ />
15
+ commute time = {travelTime}
16
+ </PillWrapper>
17
+ </div>
18
+ );
19
+ };
20
+
21
+ export default CommutePill;
@@ -0,0 +1,196 @@
1
+ import { forwardRef } from 'react';
2
+ import { Link, useLocation, useNavigate } from 'react-router-dom';
3
+ import { twMerge } from 'tailwind-merge';
4
+ import Icon from '~/components/modules/icon';
5
+ import React from 'react'
6
+ const linkDefaultClasses = "normal-case text-inherit !font-[inherit] [font-weight:inherit] !p-0 rounded-none";
7
+ const underlineClasses = "!underline decoration-1 underline-offset-2 hover:!no-underline focus:!no-underline";
8
+
9
+ const ButtonVariant = {
10
+ none: '',
11
+ primary: 'bg-primary border border-primary text-white hover:bg-opacity-70 focus:bg-opacity-70',
12
+ secondary: 'bg-secondary border border-secondary text-white hover:bg-opacity-70 focus:bg-opacity-70',
13
+ outline: 'bg-transparent border border-primary text-primary hover:bg-primaryDark hover:border-primaryDark hover:text-white focus:bg-primaryDark focus:border-primaryDark focus:text-white',
14
+ link: `${linkDefaultClasses} text-primary hover:text-uiText focus:text-uiText`,
15
+ icon: 'opacity-100 hover:opacity-70 focus:opacity-70'
16
+ };
17
+
18
+ const ButtonSize = {
19
+ none: '',
20
+ default: 'py-2 px-6 text-base',
21
+ sq: 'p-2.5',
22
+ sqsm: 'p-1',
23
+ xs: 'py-1.5 px-3 text-xs',
24
+ sm: 'py-1.5 px-4 text-sm',
25
+ lg: 'py-4 px-10 text-lg'
26
+ };
27
+
28
+ const ButtonDefaults = {
29
+ style: 'group font-medium uppercase text-center rounded transition',
30
+ size: ButtonSize.default,
31
+ variant: ButtonVariant.primary,
32
+ block: 'block w-full'
33
+ };
34
+
35
+ const linkVariants = variant => variant === 'link';
36
+
37
+ const buttonClasses = (variant, size, isBlock, hasUnderline, className) => twMerge(
38
+ isBlock ? ButtonDefaults.block : linkVariants(variant) ? 'inline' : 'inline-block',
39
+ ButtonDefaults.style,
40
+ variant ? ButtonVariant[variant] : ButtonDefaults.variant,
41
+ size ? ButtonSize[size] : ButtonDefaults.size,
42
+ hasUnderline ? underlineClasses : '',
43
+ className ?? ''
44
+ );
45
+
46
+ const Button = ({
47
+ children
48
+ }) => {
49
+ return (
50
+ { children }
51
+ );
52
+ };
53
+
54
+ export const Anchor = ({
55
+ children,
56
+ href,
57
+ className,
58
+ size,
59
+ variant,
60
+ isBlock,
61
+ hasUnderline,
62
+ target = '_blank',
63
+ ...rest
64
+ }) => {
65
+ return (
66
+ <a
67
+ href={href}
68
+ target={target}
69
+ className={buttonClasses(variant, size, isBlock, hasUnderline, className)}
70
+ onClick={href === '#' ? e => {
71
+ e.preventDefault();
72
+ } : null}
73
+ {...rest}
74
+ >
75
+ {children}
76
+ </a>
77
+ );
78
+ };
79
+
80
+ export const AnchorLink = ({
81
+ children,
82
+ href,
83
+ className,
84
+ activeClassName,
85
+ partiallyActive = false,
86
+ size,
87
+ variant,
88
+ isBlock,
89
+ hasUnderline,
90
+ ...rest
91
+ }) => {
92
+ const router = useRouter();
93
+
94
+ return (
95
+ <Link
96
+ href={href}
97
+ className={`
98
+ ${buttonClasses(variant, size, isBlock, hasUnderline, className)}
99
+ ${(activeClassName && router.pathname === href) || (router.pathname.startsWith(href) && partiallyActive) ? activeClassName : ''}
100
+ `}
101
+ {...rest}
102
+ >
103
+ {children}
104
+ </Link>
105
+ );
106
+ };
107
+
108
+ export const ScrollAnchor = forwardRef((props, ref) => {
109
+ const {
110
+ children,
111
+ href,
112
+ className,
113
+ size,
114
+ variant,
115
+ isBlock,
116
+ hasUnderline,
117
+ ...rest
118
+ } = props;
119
+
120
+ return (
121
+ <Link
122
+ ref={ref}
123
+ href={`#${href}`}
124
+ scroll={false}
125
+ className={buttonClasses(variant, size, isBlock, hasUnderline, className)}
126
+ {...rest}
127
+ >
128
+ {children}
129
+ </Link>
130
+ );
131
+ });
132
+
133
+ export const Btn = forwardRef((props, ref) => {
134
+ const {
135
+ children,
136
+ type = 'button',
137
+ className,
138
+ size,
139
+ variant,
140
+ isBlock,
141
+ hasUnderline,
142
+ ...rest
143
+ } = props;
144
+ return (
145
+ <button
146
+ ref={ref}
147
+ type={type}
148
+ className={buttonClasses(variant, size, isBlock, hasUnderline, className)}
149
+ {...rest}
150
+ >
151
+ {children}
152
+ </button>
153
+ );
154
+ });
155
+
156
+ export const ButtonBody = ({
157
+ children,
158
+ className
159
+ }) => {
160
+ return (
161
+ <span
162
+ className={twMerge(
163
+ 'inline-flex w-full items-center justify-between gap-1.5',
164
+ className ?? ''
165
+ )}
166
+ >
167
+ {children}
168
+ </span>
169
+ );
170
+ };
171
+
172
+ export const ButtonIcon = ({
173
+ icon,
174
+ size = 'w-4 h-4',
175
+ className
176
+ }) => {
177
+ return (
178
+ <Icon
179
+
180
+ icon={icon}
181
+ size={size}
182
+ className={className ?? ''}
183
+ />
184
+ );
185
+ };
186
+
187
+ Button.Anchor = Anchor;
188
+ Button.Link = AnchorLink;
189
+ Button.Scroll = ScrollAnchor;
190
+ Button.Btn = Btn;
191
+ Button.Body = ButtonBody;
192
+ Button.Icon = ButtonIcon;
193
+
194
+ Btn.displayName = 'Button:Button';
195
+ ScrollAnchor.displayName = 'Button:ScrollAnchor';
196
+ export default Button;
@@ -0,0 +1,31 @@
1
+ import { forwardRef } from 'react';
2
+ import React from 'react'
3
+ import Button from '~/components/modules/buttons/default';
4
+
5
+ export const ButtonItemsPill = forwardRef((
6
+ {
7
+ className,
8
+ activeItemsCount,
9
+ ...props
10
+ },
11
+ ref
12
+ ) => {
13
+ return (
14
+ <Button.Btn
15
+ ref={ref}
16
+ size="none"
17
+ variant="none"
18
+ className="relative z-[2] group inline-flex items-center gap-px ml-auto mr-1.5 pl-1.5 pr-1 py-0.5 rounded bg-primary/10 text-xs font-bold text-primary ring-1 ring-inset ring-primary/20"
19
+ {...props}
20
+ >
21
+ {activeItemsCount > 9 ? '9+' : activeItemsCount}
22
+ <Button.Icon
23
+ icon="uil:times"
24
+ size="w-3.5 h-3.5"
25
+ />
26
+ </Button.Btn>
27
+ );
28
+ });
29
+
30
+ ButtonItemsPill.displayName = 'ButtonItemsPill';
31
+ export default ButtonItemsPill;
@@ -0,0 +1,26 @@
1
+ import { forwardRef } from 'react';
2
+ import Button from '~/components/modules/buttons/default';
3
+ import React from 'react'
4
+ export const PillWrapper = forwardRef((
5
+ {
6
+ className,
7
+ children,
8
+ ...props
9
+ },
10
+ ref
11
+ ) => {
12
+ return (
13
+ <Button.Btn
14
+ ref={ref}
15
+ size="none"
16
+ variant="none"
17
+ className={`relative group inline-flex items-center gap-px ml-auto mr-1.5 pl-1.5 pr-1 py-0.5 rounded bg-primary/10 text-xs font-bold text-primary ring-1 ring-inset ring-primary/20 ${className}`}
18
+ {...props}
19
+ >
20
+ {children}
21
+ </Button.Btn>
22
+ );
23
+ });
24
+
25
+ PillWrapper.displayName = 'PillWrapper';
26
+ export default PillWrapper;
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+
3
+ const ShowAllButton = ({ mapInteracted, markerConfigs, setMapInteracted, fitBounds, mapRef, pinIconUrl, setSelectedFilters, setQuery, listingCount }) => {
4
+ if (!mapInteracted || !markerConfigs) {
5
+ return null;
6
+ }
7
+
8
+ return (
9
+ <button
10
+ style={{ fontFamily: 'Roboto, Arial, sans-serif', fontSize: '14px', fontWeight: '500' }}
11
+ className="absolute bottom-10 left-2.5 z-10 flex items-center justify-center pl-2 pb-1 pt-1.5 pr-3 bg-white text-black border-none rounded-full shadow cursor-pointer text-sm font-medium"
12
+ onClick={() => { setMapInteracted(false); fitBounds(mapRef.current, true); if(listingCount < 2){ setSelectedFilters({}); setQuery(null);};}}
13
+ >
14
+ <img src={pinIconUrl} alt="Pin Icon" className="w-5 h-5" />
15
+ Show All
16
+ </button>
17
+ );
18
+ };
19
+
20
+ export default ShowAllButton;
@@ -0,0 +1,168 @@
1
+ import { forwardRef } from 'react';
2
+ import { Link } from 'react-router-dom';
3
+ import { twMerge } from 'tailwind-merge';
4
+ import React from 'react'
5
+
6
+ const cardClasses = (className, hasShadow) => twMerge(
7
+ 'relative flex flex-wrap flex-col bg-clip-border break-words bg-white border border-gray-100',
8
+ hasShadow ? 'shadow-lg' : '',
9
+ className ?? ''
10
+ );
11
+
12
+ const Card = ({ children }) => {
13
+ return (
14
+ <>{children}</>
15
+ );
16
+ };
17
+
18
+ export const CardDefault = forwardRef((
19
+ {
20
+ as = 'div',
21
+ className,
22
+ hasShadow = false,
23
+ image,
24
+ body,
25
+ children,
26
+ footer,
27
+ ...rest
28
+ },
29
+ ref
30
+ ) => {
31
+ const Container = as;
32
+
33
+ return (
34
+ <Container
35
+ ref={ref}
36
+ className={cardClasses(className, hasShadow)}
37
+ {...rest}
38
+ >
39
+ {image}
40
+ {children}
41
+ {body}
42
+ {footer}
43
+ </Container>
44
+ );
45
+ });
46
+
47
+ const CardLink = ({
48
+ as = 'link',
49
+ href,
50
+ className,
51
+ hasShadow = false,
52
+ image,
53
+ body,
54
+ children,
55
+ footer,
56
+ ...rest
57
+ }) => {
58
+ const Container = as === 'link' ? Link : as;
59
+
60
+ return (
61
+ <Container
62
+ to={href}
63
+ className={twMerge(
64
+ cardClasses(className, hasShadow),
65
+ 'group transition hover:shadow-xl hover:border-indigo-300 focus:shadow-xl focus:border-indigo-300'
66
+ )}
67
+ {...rest}
68
+ >
69
+ {image && image}
70
+ {children}
71
+ {body && body}
72
+ {footer && footer}
73
+ </Container>
74
+ );
75
+ };
76
+
77
+ export const CardImage = ({
78
+ image,
79
+ alt,
80
+ className,
81
+ imageClassName,
82
+ ...rest
83
+ }) => {
84
+ return (
85
+ <div
86
+ className={twMerge(
87
+ 'w-full',
88
+ className ?? ''
89
+ )}
90
+ >
91
+ <img
92
+ src={typeof image === 'string' ? image : image.src}
93
+ width={image.width ? image.width : null}
94
+ height={image.height ? image.height : null}
95
+ alt={alt ?? ''}
96
+ className={twMerge(
97
+ 'w-full h-auto',
98
+ imageClassName ?? ''
99
+ )}
100
+ {...rest}
101
+ />
102
+ </div>
103
+ );
104
+ };
105
+
106
+ export const CardBody = ({
107
+ children,
108
+ className
109
+ }) => {
110
+ return (
111
+ <div
112
+ className={twMerge(
113
+ 'flex-auto p-4 md:px-6 lg:px-8',
114
+ className ?? ''
115
+ )}
116
+ >
117
+ {children}
118
+ </div>
119
+ );
120
+ };
121
+
122
+ export const CardTitle = ({
123
+ as = 'h3',
124
+ children,
125
+ className,
126
+ ...rest
127
+ }) => {
128
+ const Title = as;
129
+
130
+ return (
131
+ <Title
132
+ className={twMerge(
133
+ 'text-2xl font-bold',
134
+ className ?? ''
135
+ )}
136
+ {...rest}
137
+ >
138
+ {children}
139
+ </Title>
140
+ );
141
+ };
142
+
143
+ export const CardFooter = ({
144
+ children,
145
+ className
146
+ }) => {
147
+ return (
148
+ <div
149
+ className={twMerge(
150
+ 'py-2 px-4 md:px-6 lg:px-8 bg-gray-100',
151
+ className ?? ''
152
+ )}
153
+ >
154
+ {children}
155
+ </div>
156
+ );
157
+ };
158
+
159
+ Card.Default = CardDefault;
160
+ Card.Link = CardLink;
161
+ Card.Image = CardImage;
162
+ Card.Body = CardBody;
163
+ Card.Title = CardTitle;
164
+ Card.Footer = CardFooter;
165
+
166
+ CardDefault.displayName = 'Card:Default';
167
+
168
+ export default Card;
@@ -0,0 +1,55 @@
1
+ import Card from '~/components/modules/cards/default';
2
+ import Icon from '~/components/modules/icon';
3
+ import React from 'react'
4
+
5
+ const CardFilter = ({
6
+ as,
7
+ className,
8
+ children,
9
+ ...rest
10
+ }) => {
11
+ return (
12
+ <Card.Default
13
+ as={as}
14
+ className={`
15
+ bg-uiAccent/5 border border-uiAccent/20 rounded
16
+ ${className ?? ''}
17
+ `}
18
+ {...rest}
19
+ >
20
+ <Card.Body className="!p-3">
21
+ {children}
22
+ </Card.Body>
23
+ </Card.Default>
24
+ );
25
+ };
26
+
27
+ export const CardTitle = ({
28
+ as,
29
+ children,
30
+ icon,
31
+ className,
32
+ ...rest
33
+ }) => {
34
+ return (
35
+ <Card.Title
36
+ as={as}
37
+ className={`
38
+ flex items-center gap-2 mb-2 text-xs uppercase font-bold text-uiText
39
+ ${className ?? ''}
40
+ `}
41
+ {...rest}
42
+ >
43
+ <Icon
44
+ icon={icon}
45
+ size="w-5 h-5"
46
+ className="text-uiAccent/30"
47
+ />
48
+ {children}
49
+ </Card.Title>
50
+ );
51
+ };
52
+
53
+ CardFilter.Title = CardTitle;
54
+
55
+ export default CardFilter;
@@ -0,0 +1,47 @@
1
+ import React from 'react';
2
+ import * as Dialog from '@radix-ui/react-dialog';
3
+ import Button from '~/components/modules/buttons/default';
4
+ import Icon from '~/components/modules/icon';
5
+
6
+ const ApplyDialog = ({ children, applyUrl, internalApplyLink, companyName }) => (
7
+
8
+ <Dialog.Root >
9
+ <Dialog.Trigger asChild>
10
+ {children}
11
+ </Dialog.Trigger>
12
+ <Dialog.Portal>
13
+ <Dialog.Overlay className="bg-blackA6 fixed inset-0 animate-overlayShow" />
14
+ <Dialog.Content className="fit-content animate-contentShow fixed inset-0 m-auto max-h-[85vh] w-[90vw] max-w-[450px] rounded-[6px] bg-white p-[25px] shadow-lg focus:outline-none flex flex-col items-center text-center">
15
+ <Dialog.Title className="text-[17px] font-medium w-full">
16
+ Career Opportunities
17
+ </Dialog.Title>
18
+ <Dialog.Description className="mt-4 mb-5 text-[15px] leading-normal w-full">
19
+ Are you currently a {companyName} employee?
20
+ </Dialog.Description>
21
+ <div className="flex justify-center space-x-4 w-full">
22
+ <Dialog.Close asChild>
23
+ <Button.Anchor variant="outline" href={internalApplyLink}>
24
+ Yes
25
+ </Button.Anchor>
26
+ </Dialog.Close>
27
+ <Dialog.Close asChild>
28
+ <Button.Anchor variant="primary" href={applyUrl}>
29
+ No
30
+ </Button.Anchor>
31
+ </Dialog.Close>
32
+ </div>
33
+ <Dialog.Close asChild>
34
+ <Button.Anchor className="absolute top-[10px] right-[10px] inline-flex h-[25px] w-[25px] items-center justify-center rounded-full focus:outline-none"
35
+ variant="ghost" aria-label="Close">
36
+ <Icon
37
+ icon="mdi:times"
38
+ className="cursor-pointer text-black hover:text-gray-500 hover:opacity-75"
39
+ />
40
+ </Button.Anchor>
41
+ </Dialog.Close>
42
+ </Dialog.Content>
43
+ </Dialog.Portal>
44
+ </Dialog.Root>
45
+ );
46
+
47
+ export default ApplyDialog;