@4alldigital/foundation-ui--core 3.10.1 → 3.11.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.
- package/package.json +2 -2
- package/src/components/Accordion/Accordion.tsx +3 -1
- package/src/components/AddressForm/AddressForm.tsx +4 -1
- package/src/components/AnimationCounter/AnimationCounter.tsx +3 -1
- package/src/components/AnimationSet1/AnimationSet1.tsx +3 -1
- package/src/components/Authenticator/Authenticator.tsx +2 -0
- package/src/components/Avatar/Avatar.tsx +2 -0
- package/src/components/Banner/Banner.tsx +1 -1
- package/src/components/Blockquote/Blockquote.tsx +1 -1
- package/src/components/Button/Button.tsx +1 -2
- package/src/components/ButtonDeprecated/Button.tsx +3 -1
- package/src/components/ButtonGroup/ButtonGroup.tsx +1 -1
- package/src/components/Card/Card.types.ts +3 -3
- package/src/components/Card/types/CardBasic/CardBasic.tsx +44 -133
- package/src/components/Card/types/CardData/CardData.tsx +3 -1
- package/src/components/Card/types/CardHorz/CardHorz.tsx +3 -1
- package/src/components/Card/types/CardIcon/CardIcon.tsx +3 -1
- package/src/components/Card/types/CardMedia/CardMedia.tsx +3 -1
- package/src/components/Card/types/CardVideo/CardVideo.tsx +3 -1
- package/src/components/Carousel/Carousel.tsx +3 -1
- package/src/components/Cart/Cart.tsx +15 -5
- package/src/components/Checkbox/Checkbox.tsx +4 -4
- package/src/components/Chip/Chip.tsx +3 -1
- package/src/components/Collapsible/Collapsible.tsx +1 -1
- package/src/components/Container/Container.tsx +1 -1
- package/src/components/ContentPageLayout/ContentPageLayout.tsx +1 -1
- package/src/components/ContentRowsLayout/ContentRowsLayout.tsx +1 -1
- package/src/components/Copy/Copy.tsx +1 -1
- package/src/components/DisplayHeading/DisplayHeading.tsx +1 -1
- package/src/components/ErrorBoundary/ErrorBoundary.tsx +44 -0
- package/src/components/ErrorBoundary/ErrorBoundary.types.ts +12 -0
- package/src/components/ErrorBoundary/index.ts +2 -0
- package/src/components/FileUpload/FileUpload.tsx +3 -1
- package/src/components/Footer/Footer.tsx +3 -1
- package/src/components/Form/Form.tsx +10 -4
- package/src/components/Form/Form.types.ts +4 -3
- package/src/components/FormField/FormField.tsx +12 -10
- package/src/components/FormSelect/FormSelect.tsx +2 -2
- package/src/components/FormSelect/FormSelect.types.ts +5 -11
- package/src/components/FullScreenVideoModal/FullScreenVideoModal.tsx +3 -1
- package/src/components/Header/Header.tsx +27 -9
- package/src/components/Heading/Heading.tsx +12 -19
- package/src/components/Heading/Heading.types.ts +1 -1
- package/src/components/Hero/Hero.tsx +1 -1
- package/src/components/Hr/Hr.tsx +1 -1
- package/src/components/HtmlContent/HtmlContent.tsx +1 -1
- package/src/components/Image/Image.tsx +1 -1
- package/src/components/Label/Label.tsx +1 -1
- package/src/components/Link/Link.tsx +3 -1
- package/src/components/List/List.tsx +1 -1
- package/src/components/ListItem/ListItem.tsx +3 -1
- package/src/components/Loader/Loader.tsx +1 -1
- package/src/components/Logo/Logo.tsx +1 -1
- package/src/components/Menu/Menu.tsx +1 -1
- package/src/components/Notice/Notice.tsx +3 -1
- package/src/components/OTPInput/OTPInput.tsx +4 -2
- package/src/components/PanelCards/PanelCards.tsx +3 -1
- package/src/components/PanelCustom/PanelCustom.tsx +1 -1
- package/src/components/PanelFeature/PanelFeature.tsx +1 -1
- package/src/components/PanelHero/PanelHero.tsx +3 -1
- package/src/components/PanelIntro/PanelIntro.tsx +3 -1
- package/src/components/PanelProduct/PanelProduct.tsx +1 -1
- package/src/components/PanelScroller/PanelScroller.tsx +3 -1
- package/src/components/PanelVideo/PanelVideo.tsx +3 -1
- package/src/components/ProductCard/ProductCard.tsx +2 -0
- package/src/components/ProductDetail/ProductDetail.tsx +2 -0
- package/src/components/Radio/Radio.tsx +1 -1
- package/src/components/Schedule/Schedule.tsx +2 -2
- package/src/components/ScheduleItem/ScheduleItem.tsx +2 -0
- package/src/components/Screen/Screen.tsx +1 -1
- package/src/components/ShadcnCarousel/ShadcnCarousel.tsx +2 -0
- package/src/components/Share/Share.tsx +2 -0
- package/src/components/SubscriptionManager/SubscriptionManager.tsx +3 -1
- package/src/components/Switch/Switch.tsx +1 -1
- package/src/components/Tabs/Tabs.tsx +3 -1
- package/src/components/TextInput/TextInput.tsx +6 -3
- package/src/components/TextInput/TextInput.types.ts +4 -55
- package/src/components/VariantSelector/VariantSelector.tsx +2 -0
- package/src/components/Video/Video.tsx +14 -13
- package/src/components/VisitUs/VisitUs.tsx +2 -0
- package/src/components/index.ts +7 -0
- package/src/context/Amplify/index.tsx +2 -1
- package/src/context/App/index.tsx +2 -0
- package/src/context/Cart/index.tsx +2 -0
- package/src/context/ExampleContext/index.tsx +3 -1
- package/src/context/Theme/index.tsx +2 -0
- package/src/context/index.ts +2 -0
- package/src/features/Search/Search.tsx +2 -0
- package/src/features/Search/config/config-helper.ts +2 -0
- package/src/features/Search/views/Layout/Layout.tsx +1 -1
- package/src/features/Search/views/MultiCheckboxFacet/MultiCheckboxFacet.tsx +3 -1
- package/src/features/Search/views/Paging/Paging.tsx +3 -1
- package/src/features/Search/views/PagingInfo/PagingInfo.tsx +1 -1
- package/src/features/Search/views/Result/Result.tsx +1 -1
- package/src/features/Search/views/Results/Results.tsx +1 -1
- package/src/features/Search/views/ResultsPerPage/ResultsPerPage.tsx +3 -1
- package/src/features/Search/views/SearchBox/SearchBox.tsx +3 -1
- package/src/features/Search/views/SingleLinksFacet/SingleLinksFacet.tsx +3 -1
- package/src/features/Search/views/SingleSelectFacet/SingleSelectFacet.tsx +3 -1
- package/src/features/Search/views/Sorting/Sorting.tsx +3 -1
- package/src/features/index.ts +2 -0
- package/src/forms/ForgotPasswordForm/ForgotPasswordForm.types.ts +1 -1
- package/src/forms/LoginForm/LoginForm.stories.tsx +1 -1
- package/src/forms/LoginForm/LoginForm.tsx +7 -5
- package/src/forms/LoginForm/LoginForm.types.ts +7 -1
- package/src/forms/PromoCodeForm/PromoCodeForm.types.ts +1 -1
- package/src/forms/RegisterForm/RegisterForm.stories.tsx +1 -1
- package/src/forms/RegisterForm/RegisterForm.tsx +7 -10
- package/src/forms/RegisterForm/RegisterForm.types.ts +4 -2
- package/src/forms/ResetPasswordAuthForm/ResetPasswordAuthForm.types.ts +1 -1
- package/src/forms/ResetPasswordForm/ResetPasswordForm.types.ts +1 -1
- package/src/forms/index.ts +2 -0
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useLanguage.ts +2 -0
- package/src/hooks/useTheme.ts +3 -1
- package/src/index.ts +2 -0
- package/src/templates/AccountScreen/AccountScreen.tsx +2 -0
- package/src/templates/ChallengeScreen/ChallengeScreen.tsx +2 -0
- package/src/templates/MenuScreen/MenuScreen.tsx +2 -0
- package/src/templates/OrderDetailScreen/OrderDetailScreen.tsx +2 -0
- package/src/templates/OrdersHistoryScreen/OrdersHistoryScreen.tsx +2 -0
- package/src/templates/PasswordResetScreen/PasswordResetScreen.types.ts +1 -1
- package/src/templates/ProductListScreen/ProductListScreen.tsx +2 -0
- package/src/templates/PurchaseConfirmationScreen/PurchaseConfirmationScreen.tsx +2 -0
- package/src/templates/SubscriptionScreen/SubscriptionScreen.tsx +2 -0
- package/src/templates/WorkoutScreen/WorkoutScreen.tsx +3 -1
- package/src/templates/index.ts +2 -0
- package/src/utils/htmlParser/index.tsx +11 -5
- package/src/utils/index.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@4alldigital/foundation-ui--core",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.11.0",
|
|
4
4
|
"description": "Foundation UI Core Component Library (source distribution)",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "src/index.ts",
|
|
@@ -35,5 +35,5 @@
|
|
|
35
35
|
},
|
|
36
36
|
"author": "Joe Mewes",
|
|
37
37
|
"license": "MIT",
|
|
38
|
-
"gitHead": "
|
|
38
|
+
"gitHead": "f241bcb8eb542b8150a62af69d513687f870dd2b"
|
|
39
39
|
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import * as React from 'react';
|
|
2
4
|
import { useState, useEffect } from 'react';
|
|
3
5
|
import { cn } from '../../utils';
|
|
4
6
|
import { AddressFormProps, ShippingAddress, AddressErrors } from './AddressForm.types';
|
|
5
7
|
import TextInput from '../TextInput';
|
|
8
|
+
import { InputType } from '../TextInput/TextInput.types';
|
|
6
9
|
import FormSelect from '../FormSelect';
|
|
7
10
|
|
|
8
11
|
// Common countries
|
|
@@ -205,7 +208,7 @@ export const AddressForm = React.forwardRef<HTMLDivElement, AddressFormProps>(
|
|
|
205
208
|
{/* Phone */}
|
|
206
209
|
<TextInput
|
|
207
210
|
id="shipping-phone"
|
|
208
|
-
type=
|
|
211
|
+
type={InputType.TEL}
|
|
209
212
|
placeholder="Phone Number (optional)"
|
|
210
213
|
value={address.phone || ''}
|
|
211
214
|
onChange={(e) => handleChange('phone', e.target.value)}
|
|
@@ -7,7 +7,7 @@ import Loader from '../Loader';
|
|
|
7
7
|
import { BTN_VARIANTS, BTN_SIZES, type ButtonProps } from './Button.types';
|
|
8
8
|
|
|
9
9
|
const buttonVariants = cva(
|
|
10
|
-
'inline-flex items-center cursor-pointer justify-center whitespace-nowrap rounded-sm text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50',
|
|
10
|
+
'inline-flex items-center gap-2 cursor-pointer justify-center whitespace-nowrap rounded-sm text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50',
|
|
11
11
|
{
|
|
12
12
|
variants: {
|
|
13
13
|
variant: {
|
|
@@ -248,7 +248,6 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
|
248
248
|
type={type as 'button' | 'submit' | 'reset'}
|
|
249
249
|
disabled={disabled}
|
|
250
250
|
aria-label={ariaLabel}
|
|
251
|
-
role="button"
|
|
252
251
|
{...props}
|
|
253
252
|
>
|
|
254
253
|
{renderContent()}
|
|
@@ -20,10 +20,10 @@ export interface ImageData {
|
|
|
20
20
|
aspectRatio?: 'aspect-[16/10]' | 'aspect-[16/9]' | 'aspect-[4/3]' | 'aspect-[1/1]' | 'aspect-[3/4]' | 'aspect-[9/16]';
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
type ActionItem = {
|
|
23
|
+
export type ActionItem = {
|
|
24
24
|
count?: number;
|
|
25
25
|
isActive: boolean;
|
|
26
|
-
onClick: (
|
|
26
|
+
onClick: (data: { id: string }) => void;
|
|
27
27
|
};
|
|
28
28
|
|
|
29
29
|
export interface Actions {
|
|
@@ -53,7 +53,7 @@ export interface CardData {
|
|
|
53
53
|
moreTitle?: string;
|
|
54
54
|
metaData?: string[];
|
|
55
55
|
actions?: Actions;
|
|
56
|
-
onClick?: (data:
|
|
56
|
+
onClick?: (data: unknown) => void;
|
|
57
57
|
playCallback?: (event: MouseEvent<HTMLButtonElement>) => void;
|
|
58
58
|
isMuted?: boolean;
|
|
59
59
|
icon?: string;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import React, { MouseEvent, useCallback, useContext } from 'react';
|
|
4
|
+
import { clsx as cx } from 'clsx';
|
|
3
5
|
import Image from '../../../Image';
|
|
4
6
|
import { Props } from './CardBasic.types';
|
|
5
7
|
import Heading from '../../../Heading';
|
|
@@ -8,6 +10,7 @@ import Copy from '../../../Copy';
|
|
|
8
10
|
import { COPY_TAG } from '../../../Copy/Copy.types';
|
|
9
11
|
import Button from '../../../Button';
|
|
10
12
|
import { BTN_SIZES, BTN_VARIANTS } from '../../../Button/Button.types';
|
|
13
|
+
import { type ActionItem } from '../../Card.types';
|
|
11
14
|
import { animateClasses, cardWrapperClasses, clickableCardWrapperClasses } from '../../constants';
|
|
12
15
|
import { twMerge } from 'tailwind-merge';
|
|
13
16
|
import HtmlContent from '../../../HtmlContent';
|
|
@@ -30,6 +33,17 @@ const CardBasic = ({
|
|
|
30
33
|
}: Props) => {
|
|
31
34
|
const appContext = useContext(AppContext);
|
|
32
35
|
const cardClasses = onClick ? clickableCardWrapperClasses : cardWrapperClasses;
|
|
36
|
+
|
|
37
|
+
const handleAction = useCallback(
|
|
38
|
+
(actionKey: string) => (event: MouseEvent<HTMLButtonElement>) => {
|
|
39
|
+
event.stopPropagation();
|
|
40
|
+
const action = actions?.[actionKey as keyof Omit<typeof actions, 'custom'>] as ActionItem | undefined;
|
|
41
|
+
if (action?.onClick) {
|
|
42
|
+
action.onClick({ id });
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
[actions, id],
|
|
46
|
+
);
|
|
33
47
|
return (
|
|
34
48
|
<div
|
|
35
49
|
id={id}
|
|
@@ -37,7 +51,10 @@ const CardBasic = ({
|
|
|
37
51
|
className={twMerge(
|
|
38
52
|
cx(animateClasses, cardClasses, { 'p-4': padded }, { 'hover:scale-100': !scaleOnHover }, className),
|
|
39
53
|
)}
|
|
40
|
-
onClick={onClick}
|
|
54
|
+
onClick={onClick}
|
|
55
|
+
onKeyDown={onClick ? (e) => { if (e.key === 'Enter') onClick(e as unknown); } : undefined}
|
|
56
|
+
role={onClick ? 'button' : undefined}
|
|
57
|
+
tabIndex={onClick ? 0 : undefined}>
|
|
41
58
|
{image && (
|
|
42
59
|
<div
|
|
43
60
|
className={twMerge(
|
|
@@ -115,136 +132,30 @@ const CardBasic = ({
|
|
|
115
132
|
)}
|
|
116
133
|
{actions && (
|
|
117
134
|
<div className="flex items-center gap-1 flex-wrap flex-1 justify-end">
|
|
118
|
-
{
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
/>
|
|
143
|
-
)}
|
|
144
|
-
{actions.save && (
|
|
145
|
-
<Button
|
|
146
|
-
variant={BTN_VARIANTS.PRIMARY}
|
|
147
|
-
icon={actions.save.isActive ? 'mdi:bookmark' : 'mdi:bookmark-outline'}
|
|
148
|
-
size={BTN_SIZES.SMALL}
|
|
149
|
-
onClick={(event: MouseEvent<HTMLButtonElement>) => {
|
|
150
|
-
event.stopPropagation();
|
|
151
|
-
if (actions?.save?.onClick && typeof actions.save.onClick === 'function') {
|
|
152
|
-
actions.save.onClick({ id });
|
|
153
|
-
}
|
|
154
|
-
}}
|
|
155
|
-
/>
|
|
156
|
-
)}
|
|
157
|
-
{actions.comment && (
|
|
158
|
-
<Button
|
|
159
|
-
variant={BTN_VARIANTS.PRIMARY}
|
|
160
|
-
icon={actions.comment.isActive ? 'mdi:comment' : 'mdi:comment-outline'}
|
|
161
|
-
size={BTN_SIZES.SMALL}
|
|
162
|
-
onClick={(event: MouseEvent<HTMLButtonElement>) => {
|
|
163
|
-
event.stopPropagation();
|
|
164
|
-
if (actions?.comment?.onClick && typeof actions.comment.onClick === 'function') {
|
|
165
|
-
actions.comment.onClick({ id });
|
|
166
|
-
}
|
|
167
|
-
}}
|
|
168
|
-
/>
|
|
169
|
-
)}
|
|
170
|
-
{actions.bookmark && (
|
|
171
|
-
<Button
|
|
172
|
-
variant={BTN_VARIANTS.PRIMARY}
|
|
173
|
-
icon={actions.bookmark.isActive ? 'mdi:bookmark' : 'mdi:bookmark-outline'}
|
|
174
|
-
size={BTN_SIZES.SMALL}
|
|
175
|
-
onClick={(event: MouseEvent<HTMLButtonElement>) => {
|
|
176
|
-
event.stopPropagation();
|
|
177
|
-
if (actions?.bookmark?.onClick && typeof actions.bookmark.onClick === 'function') {
|
|
178
|
-
actions.bookmark.onClick({ id });
|
|
179
|
-
}
|
|
180
|
-
}}
|
|
181
|
-
/>
|
|
182
|
-
)}
|
|
183
|
-
{actions.report && (
|
|
184
|
-
<Button
|
|
185
|
-
variant={BTN_VARIANTS.PRIMARY}
|
|
186
|
-
icon={actions.report.isActive ? 'mdi:flag' : 'mdi:flag-outline'}
|
|
187
|
-
size={BTN_SIZES.SMALL}
|
|
188
|
-
onClick={(event: MouseEvent<HTMLButtonElement>) => {
|
|
189
|
-
event.stopPropagation();
|
|
190
|
-
if (actions?.report?.onClick && typeof actions.report.onClick === 'function') {
|
|
191
|
-
actions.report.onClick({ id });
|
|
192
|
-
}
|
|
193
|
-
}}
|
|
194
|
-
/>
|
|
195
|
-
)}
|
|
196
|
-
{actions.follow && (
|
|
197
|
-
<Button
|
|
198
|
-
variant={BTN_VARIANTS.PRIMARY}
|
|
199
|
-
icon={actions.follow.isActive ? 'mdi:account-plus' : 'mdi:account-plus-outline'}
|
|
200
|
-
size={BTN_SIZES.SMALL}
|
|
201
|
-
onClick={(event: MouseEvent<HTMLButtonElement>) => {
|
|
202
|
-
event.stopPropagation();
|
|
203
|
-
if (actions?.follow?.onClick && typeof actions.follow.onClick === 'function') {
|
|
204
|
-
actions.follow.onClick({ id });
|
|
205
|
-
}
|
|
206
|
-
}}
|
|
207
|
-
/>
|
|
208
|
-
)}
|
|
209
|
-
{actions.download && (
|
|
210
|
-
<Button
|
|
211
|
-
variant={BTN_VARIANTS.PRIMARY}
|
|
212
|
-
icon={actions.download.isActive ? 'mdi:download' : 'mdi:download-outline'}
|
|
213
|
-
size={BTN_SIZES.SMALL}
|
|
214
|
-
onClick={(event: MouseEvent<HTMLButtonElement>) => {
|
|
215
|
-
event.stopPropagation();
|
|
216
|
-
if (actions?.download?.onClick && typeof actions.download.onClick === 'function') {
|
|
217
|
-
actions.download.onClick({ id });
|
|
218
|
-
}
|
|
219
|
-
}}
|
|
220
|
-
/>
|
|
221
|
-
)}
|
|
222
|
-
{actions.edit && (
|
|
223
|
-
<Button
|
|
224
|
-
variant={BTN_VARIANTS.PRIMARY}
|
|
225
|
-
icon={actions.edit.isActive ? 'mdi:pencil' : 'mdi:pencil-outline'}
|
|
226
|
-
size={BTN_SIZES.SMALL}
|
|
227
|
-
onClick={(event: MouseEvent<HTMLButtonElement>) => {
|
|
228
|
-
event.stopPropagation();
|
|
229
|
-
if (actions?.edit?.onClick && typeof actions.edit.onClick === 'function') {
|
|
230
|
-
actions.edit.onClick({ id });
|
|
231
|
-
}
|
|
232
|
-
}}
|
|
233
|
-
/>
|
|
234
|
-
)}
|
|
235
|
-
{actions.delete && (
|
|
236
|
-
<Button
|
|
237
|
-
variant={BTN_VARIANTS.PRIMARY}
|
|
238
|
-
icon={actions.delete.isActive ? 'mdi:delete' : 'mdi:delete-outline'}
|
|
239
|
-
size={BTN_SIZES.SMALL}
|
|
240
|
-
onClick={(event: MouseEvent<HTMLButtonElement>) => {
|
|
241
|
-
event.stopPropagation();
|
|
242
|
-
if (actions?.delete?.onClick && typeof actions.delete.onClick === 'function') {
|
|
243
|
-
actions.delete.onClick({ id });
|
|
244
|
-
}
|
|
245
|
-
}}
|
|
246
|
-
/>
|
|
247
|
-
)}
|
|
135
|
+
{([
|
|
136
|
+
{ key: 'like', icon: 'mdi:like', iconOutline: 'mdi:like-outline' },
|
|
137
|
+
{ key: 'share', icon: 'mdi:share', iconOutline: 'mdi:share-outline' },
|
|
138
|
+
{ key: 'save', icon: 'mdi:bookmark', iconOutline: 'mdi:bookmark-outline' },
|
|
139
|
+
{ key: 'comment', icon: 'mdi:comment', iconOutline: 'mdi:comment-outline' },
|
|
140
|
+
{ key: 'bookmark', icon: 'mdi:bookmark', iconOutline: 'mdi:bookmark-outline' },
|
|
141
|
+
{ key: 'report', icon: 'mdi:flag', iconOutline: 'mdi:flag-outline' },
|
|
142
|
+
{ key: 'follow', icon: 'mdi:account-plus', iconOutline: 'mdi:account-plus-outline' },
|
|
143
|
+
{ key: 'download', icon: 'mdi:download', iconOutline: 'mdi:download-outline' },
|
|
144
|
+
{ key: 'edit', icon: 'mdi:pencil', iconOutline: 'mdi:pencil-outline' },
|
|
145
|
+
{ key: 'delete', icon: 'mdi:delete', iconOutline: 'mdi:delete-outline' },
|
|
146
|
+
] as const).map(({ key, icon, iconOutline }) => {
|
|
147
|
+
const action = actions[key as keyof Omit<typeof actions, 'custom'>] as ActionItem | undefined;
|
|
148
|
+
if (!action) return null;
|
|
149
|
+
return (
|
|
150
|
+
<Button
|
|
151
|
+
key={key}
|
|
152
|
+
variant={BTN_VARIANTS.PRIMARY}
|
|
153
|
+
icon={action.isActive ? icon : iconOutline}
|
|
154
|
+
size={BTN_SIZES.SMALL}
|
|
155
|
+
onClick={handleAction(key)}
|
|
156
|
+
/>
|
|
157
|
+
);
|
|
158
|
+
})}
|
|
248
159
|
{actions.custom && actions.custom.map((action, index) => <div key={index}>{action}</div>)}
|
|
249
160
|
</div>
|
|
250
161
|
)}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import React, { useEffect } from 'react';
|
|
2
|
-
import cx from '
|
|
4
|
+
import { clsx as cx } from 'clsx';
|
|
3
5
|
import { animate, motionValue } from 'framer-motion';
|
|
4
6
|
import { Props } from './CardData.types';
|
|
5
7
|
import Heading from '../../../Heading';
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import React from 'react';
|
|
2
|
-
import cx from '
|
|
4
|
+
import { clsx as cx } from 'clsx';
|
|
3
5
|
import { Props } from './CardIcon.types';
|
|
4
6
|
import { animateClasses, cardWrapperClasses, clickableCardWrapperClasses } from '../../constants';
|
|
5
7
|
import Heading from '../../../Heading';
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import React, { MouseEvent, useContext } from 'react';
|
|
2
|
-
import cx from '
|
|
4
|
+
import { clsx as cx } from 'clsx';
|
|
3
5
|
import { Props } from './CardMedia.types';
|
|
4
6
|
import { animateClasses, cardWrapperClasses, clickableCardWrapperClasses } from '../../constants';
|
|
5
7
|
import Image from '../../../Image';
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import React, { MouseEvent } from 'react';
|
|
2
|
-
import cx from '
|
|
4
|
+
import { clsx as cx } from 'clsx';
|
|
3
5
|
import HoverVideoPlayer from 'react-hover-video-player';
|
|
4
6
|
import { Props } from './CardVideo.types';
|
|
5
7
|
import Image from '../../../Image';
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import React, { useEffect, useRef, useState } from 'react';
|
|
2
|
-
import cx from '
|
|
4
|
+
import { clsx as cx } from 'clsx';
|
|
3
5
|
import { Props } from './Cart.types';
|
|
4
6
|
import { useCartContext } from '../../context';
|
|
5
7
|
import DisplayHeading from '../DisplayHeading';
|
|
@@ -31,14 +33,20 @@ const Cart = ({ testID, isCheckout }: Props) => {
|
|
|
31
33
|
};
|
|
32
34
|
|
|
33
35
|
useEffect(() => {
|
|
34
|
-
|
|
36
|
+
const handleEscKey = (event: KeyboardEvent) => {
|
|
37
|
+
if (event.key === 'Escape' && showCart) {
|
|
38
|
+
setShowCart(false);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
35
42
|
document.addEventListener('mousedown', handleClickOutside);
|
|
43
|
+
document.addEventListener('keydown', handleEscKey);
|
|
36
44
|
|
|
37
|
-
// Cleanup the event listener when the component unmounts
|
|
38
45
|
return () => {
|
|
39
46
|
document.removeEventListener('mousedown', handleClickOutside);
|
|
47
|
+
document.removeEventListener('keydown', handleEscKey);
|
|
40
48
|
};
|
|
41
|
-
}, []);
|
|
49
|
+
}, [showCart]);
|
|
42
50
|
|
|
43
51
|
return (
|
|
44
52
|
<div data-testid={testID || '"Cart"'} className="relative">
|
|
@@ -48,6 +56,8 @@ const Cart = ({ testID, isCheckout }: Props) => {
|
|
|
48
56
|
<Button
|
|
49
57
|
rounded
|
|
50
58
|
icon="mdi:cart"
|
|
59
|
+
ariaLabel="Shopping cart"
|
|
60
|
+
aria-expanded={showCart}
|
|
51
61
|
onClick={event => {
|
|
52
62
|
event.stopPropagation();
|
|
53
63
|
setShowCart(!showCart);
|
|
@@ -121,7 +131,7 @@ const Cart = ({ testID, isCheckout }: Props) => {
|
|
|
121
131
|
{isCheckout && (
|
|
122
132
|
<>
|
|
123
133
|
<div className="flex items-start justify-start">
|
|
124
|
-
<PromoCodeForm handleSubmit={(
|
|
134
|
+
<PromoCodeForm handleSubmit={(values) => context?.handleAddPromoCode?.(values.promoCode)} />
|
|
125
135
|
</div>
|
|
126
136
|
<Copy>
|
|
127
137
|
{T?.UI?.TAX}: {context?.value?.taxRate?.percentage}%
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { forwardRef } from 'react';
|
|
2
|
-
import cx from '
|
|
2
|
+
import { clsx as cx } from 'clsx';
|
|
3
3
|
import { Props } from './Checkbox.types';
|
|
4
4
|
import Icon from '../Icon';
|
|
5
5
|
|
|
6
|
-
const Checkbox = forwardRef(function MyInput(
|
|
7
|
-
{ id, label, required, className, disabled, ...rest }
|
|
8
|
-
ref
|
|
6
|
+
const Checkbox = forwardRef<HTMLInputElement, Props>(function MyInput(
|
|
7
|
+
{ id, label, required, className, disabled, ...rest },
|
|
8
|
+
ref,
|
|
9
9
|
) {
|
|
10
10
|
return (
|
|
11
11
|
<div data-testid="Checkbox" className={cx('flex items-center', className)}>
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import React, { useMemo } from 'react';
|
|
2
4
|
import { twMerge } from 'tailwind-merge';
|
|
3
|
-
import cx from '
|
|
5
|
+
import { clsx as cx } from 'clsx';
|
|
4
6
|
import { Props } from './Chip.types';
|
|
5
7
|
import Icon from '../Icon';
|
|
6
8
|
import Link from '../Link';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { forwardRef } from 'react';
|
|
2
2
|
import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
|
|
3
|
-
import cx from '
|
|
3
|
+
import { clsx as cx } from 'clsx';
|
|
4
4
|
import { twMerge } from 'tailwind-merge';
|
|
5
5
|
import { CollapsibleRootProps, CollapsibleTriggerProps, CollapsibleContentProps } from './Collapsible.types';
|
|
6
6
|
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import React, { Component } from 'react';
|
|
4
|
+
import { Props, State } from './ErrorBoundary.types';
|
|
5
|
+
|
|
6
|
+
class ErrorBoundary extends Component<Props, State> {
|
|
7
|
+
static displayName = 'ErrorBoundary';
|
|
8
|
+
|
|
9
|
+
constructor(props: Props) {
|
|
10
|
+
super(props);
|
|
11
|
+
this.state = { hasError: false, error: null };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
static getDerivedStateFromError(error: Error): State {
|
|
15
|
+
return { hasError: true, error };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {
|
|
19
|
+
this.props.onError?.(error, errorInfo);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
render() {
|
|
23
|
+
if (this.state.hasError && this.state.error) {
|
|
24
|
+
if (typeof this.props.fallback === 'function') {
|
|
25
|
+
return this.props.fallback(this.state.error);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (this.props.fallback) {
|
|
29
|
+
return this.props.fallback;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<div role="alert" data-testid="ErrorBoundary" className="p-4 rounded border border-red-200 bg-red-50 dark:bg-red-950 dark:border-red-800">
|
|
34
|
+
<p className="text-sm text-red-800 dark:text-red-200">Something went wrong.</p>
|
|
35
|
+
</div>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return this.props.children;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export default ErrorBoundary;
|
|
44
|
+
export type { Props };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface Props {
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
fallback?: ReactNode | ((error: Error) => ReactNode);
|
|
6
|
+
onError?: (error: Error, errorInfo: React.ErrorInfo) => void;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface State {
|
|
10
|
+
hasError: boolean;
|
|
11
|
+
error: Error | null;
|
|
12
|
+
}
|