@rxdrag/website-lib-core 0.0.126 → 0.0.128
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/README.md +1 -1
- package/index.ts +1 -1
- package/package.json +2 -2
- package/src/astro/animation.ts +146 -146
- package/src/astro/background.ts +82 -53
- package/src/astro/base.ts +7 -0
- package/src/astro/business.ts +13 -0
- package/src/astro/grid/consts.ts +80 -80
- package/src/astro/grid/index.ts +2 -2
- package/src/astro/grid/types.ts +35 -35
- package/src/astro/image.ts +239 -239
- package/src/astro/index.ts +12 -9
- package/src/astro/link.ts +20 -0
- package/src/astro/media.ts +123 -123
- package/src/astro/nav.ts +13 -13
- package/src/astro/section/index.ts +7 -12
- package/src/component-logic/index.ts +1 -1
- package/src/component-logic/link-client.ts +32 -32
- package/src/component-logic/link.ts +61 -61
- package/src/design-tokens.ts +160 -160
- package/src/entify/Entify.ts +533 -530
- package/src/entify/IEntify.ts +151 -177
- package/src/entify/index.ts +4 -4
- package/src/entify/lib/collectCategoryIds.ts +20 -20
- package/src/entify/lib/fulltextSearch.ts +63 -62
- package/src/entify/lib/langFields.ts +14 -14
- package/src/entify/lib/listToTree.ts +23 -23
- package/src/entify/lib/newAvatarQueryOptions.ts +4 -4
- package/src/entify/lib/newOgImageQueryOptions.ts +5 -5
- package/src/entify/lib/newQueryPostOptions.ts +42 -45
- package/src/entify/lib/newQueryProductOptions.ts +96 -98
- package/src/entify/lib/newQueryProductsMediaOptions.ts +28 -28
- package/src/entify/lib/queryAllProducts.ts +40 -40
- package/src/entify/lib/queryBulletin.ts +28 -16
- package/src/entify/lib/queryEntityList.ts +41 -41
- package/src/entify/lib/queryFeaturedProducts.ts +69 -68
- package/src/entify/lib/queryLangs.ts +36 -60
- package/src/entify/lib/queryLatestPosts.ts +92 -91
- package/src/entify/lib/queryOneEntity.ts +63 -63
- package/src/entify/lib/queryOneMedia.ts +27 -27
- package/src/entify/lib/queryOnePostById.ts +21 -21
- package/src/entify/lib/queryOnePostBySlug.ts +40 -39
- package/src/entify/lib/queryOnePostCategoryBySlug.ts +35 -35
- package/src/entify/lib/queryOneProductById.ts +20 -20
- package/src/entify/lib/queryOneProductBySlug.ts +53 -52
- package/src/entify/lib/queryOneProductCategoryBySlug.ts +50 -49
- package/src/entify/lib/queryOneTheme.ts +54 -72
- package/src/entify/lib/queryOneUser.ts +38 -38
- package/src/entify/lib/queryPostCategories.ts +67 -67
- package/src/entify/lib/queryPostSlugs.ts +37 -37
- package/src/entify/lib/queryPosts.ts +175 -174
- package/src/entify/lib/queryProductCategories.ts +59 -59
- package/src/entify/lib/queryProducts.ts +145 -144
- package/src/entify/lib/queryProductsInMenu.ts +45 -45
- package/src/entify/lib/queryTagCategories.ts +58 -58
- package/src/entify/lib/queryTags.ts +57 -57
- package/src/entify/lib/queryUserIds.ts +24 -24
- package/src/entify/lib/queryUserPosts.ts +80 -79
- package/src/entify/lib/queryWebSiteSettings.ts +28 -28
- package/src/entify/lib/queryWebsite.ts +43 -43
- package/src/entify/lib/sendEmail.ts +7 -7
- package/src/entify/lib/toQueryOptions.ts +19 -19
- package/src/entify/lib/upsertEntity.ts +8 -8
- package/src/entify/types/index.ts +1 -1
- package/src/entify/types/utils.ts +11 -6
- package/src/entify/types/variables.ts +5 -6
- package/src/entify/view-model/funcs.ts +230 -230
- package/src/entify/view-model/index.ts +1 -1
- package/src/entify/view-model/models.ts +135 -135
- package/src/global.d.ts +7 -7
- package/src/index.ts +8 -8
- package/src/lib/formatDate.ts +15 -15
- package/src/lib/index.ts +3 -3
- package/src/lib/pagination.ts +114 -114
- package/src/lib/utils.ts +135 -135
- package/src/react/components/Analytics/eventHandlers.ts +173 -173
- package/src/react/components/Analytics/index.tsx +21 -21
- package/src/react/components/Analytics/singleton.ts +214 -214
- package/src/react/components/Analytics/tracking.ts +221 -221
- package/src/react/components/Analytics/types.ts +60 -60
- package/src/react/components/Analytics/utils.ts +95 -95
- package/src/react/components/AttachmentIcon/index.tsx +53 -53
- package/src/react/components/BackgroundHlsVideoPlayer.tsx +97 -97
- package/src/react/components/BackgroundVideoPlayer.tsx +32 -32
- package/src/react/components/Bulletin.tsx +30 -30
- package/src/react/components/ContactForm/ContactForm.tsx +289 -289
- package/src/react/components/ContactForm/Input.tsx +48 -48
- package/src/react/components/ContactForm/Input2.tsx +59 -59
- package/src/react/components/ContactForm/Submit.tsx +48 -48
- package/src/react/components/ContactForm/TelInput.tsx +215 -215
- package/src/react/components/ContactForm/Textarea.tsx +48 -48
- package/src/react/components/ContactForm/Textarea2.tsx +89 -89
- package/src/react/components/ContactForm/funcs.ts +64 -64
- package/src/react/components/ContactForm/index.ts +7 -7
- package/src/react/components/ContactForm/types.ts +68 -68
- package/src/react/components/GoogleConsent/CookieItemPanel.tsx +80 -80
- package/src/react/components/GoogleConsent/CumtomizedModal.tsx +148 -148
- package/src/react/components/GoogleConsent/GoogleConsent.tsx +100 -100
- package/src/react/components/GoogleConsent/gtags.ts +67 -67
- package/src/react/components/GoogleConsent/index.ts +2 -2
- package/src/react/components/GoogleConsent/types.ts +18 -18
- package/src/react/components/GoogleConsent//345/217/202/350/200/203.md +4 -4
- package/src/react/components/Icon/index.tsx +19 -19
- package/src/react/components/Medias/MainMedia.tsx +257 -257
- package/src/react/components/Medias/Thumbnail.tsx +62 -62
- package/src/react/components/Medias/VideoPlayer.tsx +114 -114
- package/src/react/components/Medias/index.tsx +271 -271
- package/src/react/components/ProductCard/ProductCard.tsx +24 -24
- package/src/react/components/ProductCard/ProductCta/index.tsx +28 -28
- package/src/react/components/ProductCard/ProductCta/style.css +3 -3
- package/src/react/components/ProductCard/ProductDescription/index.tsx +12 -12
- package/src/react/components/ProductCard/ProductDescription/style.css +5 -5
- package/src/react/components/ProductCard/ProductMedia/index.tsx +35 -35
- package/src/react/components/ProductCard/ProductMedia/style.css +5 -5
- package/src/react/components/ProductCard/ProductTitle/index.tsx +7 -7
- package/src/react/components/ProductCard/ProductTitle/style.css +3 -3
- package/src/react/components/ProductCard/ProductView.tsx +36 -36
- package/src/react/components/ProductCard/index.ts +4 -4
- package/src/react/components/ProductCard/useQueryProduct.ts +32 -32
- package/src/react/components/ReactModalTrigger.tsx +28 -28
- package/src/react/components/ReactVideoPlayer.tsx +29 -52
- package/src/react/components/RichTextOutline/index.tsx +75 -75
- package/src/react/components/RichTextOutline/useAnchorScroll.ts +23 -23
- package/src/react/components/Scroller.tsx +39 -39
- package/src/react/components/SearchInput.tsx +21 -21
- package/src/react/components/Share/index.tsx +86 -86
- package/src/react/components/Share/socials.tsx +79 -77
- package/src/react/components/Share//350/265/204/346/226/231.md +7 -7
- package/src/react/components/ToTop.tsx +72 -72
- package/src/react/components/VideoPlayIcon.tsx +43 -0
- package/src/react/components/all.ts +38 -38
- package/src/react/components/index.ts +16 -16
- package/src/robots.ts +4 -4
- package/src/entify/lib/newPageMetaOptions.ts +0 -18
- package/src/entify/lib/newQueryPageOptions.ts +0 -14
- package/src/entify/lib/queryOneIcon.ts +0 -27
- package/src/entify/lib/queryPageBySlug.ts +0 -43
- package/src/entify/lib/queryPageByType.ts +0 -44
|
@@ -1,81 +1,81 @@
|
|
|
1
|
-
import type { CookieItem } from "./types";
|
|
2
|
-
import clsx from "clsx";
|
|
3
|
-
import { motion } from "framer-motion";
|
|
4
|
-
|
|
5
|
-
export function CookieItemPanel(props: {
|
|
6
|
-
item: CookieItem,
|
|
7
|
-
openedItem?: string,
|
|
8
|
-
onToggle: (value: string) => void,
|
|
9
|
-
checked?: boolean
|
|
10
|
-
onChange?: (checked: boolean) => void
|
|
11
|
-
}) {
|
|
12
|
-
const { item, openedItem, checked, onChange, onToggle } = props;
|
|
13
|
-
|
|
14
|
-
const opened = openedItem === item.checkbox.valueName;
|
|
15
|
-
return (
|
|
16
|
-
<div className="p-4 bg-gray-100 rounded-md">
|
|
17
|
-
<div className="flex justify-between">
|
|
18
|
-
<h2
|
|
19
|
-
className="flex text-sm font-bold items-center gap-2 cursor-pointer select-none"
|
|
20
|
-
onClick={() => onToggle(item.checkbox.valueName)}
|
|
21
|
-
>
|
|
22
|
-
<span
|
|
23
|
-
className={
|
|
24
|
-
clsx(
|
|
25
|
-
"rounded-full h-7 w-7 p-1 bg-gray-200 transition-transform duration-200 ease-in-out",
|
|
26
|
-
opened ? "transform rotate-[-180deg]" : ""
|
|
27
|
-
)
|
|
28
|
-
}>
|
|
29
|
-
<svg
|
|
30
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
31
|
-
fill="none"
|
|
32
|
-
viewBox="0 0 24 24"
|
|
33
|
-
strokeWidth="1.5"
|
|
34
|
-
stroke="currentColor">
|
|
35
|
-
<path
|
|
36
|
-
strokeLinecap="round"
|
|
37
|
-
strokeLinejoin="round"
|
|
38
|
-
d="M19.5 8.25l-7.5 7.5-7.5-7.5" />
|
|
39
|
-
</svg>
|
|
40
|
-
</span>
|
|
41
|
-
<span>
|
|
42
|
-
{item.title}
|
|
43
|
-
</span>
|
|
44
|
-
</h2>
|
|
45
|
-
<div className="flex items-center gap-2">
|
|
46
|
-
<span className="text-sm">
|
|
47
|
-
{item.checkbox.alwaysActive ? item.checkbox.label : (checked ? "Active" : "")}
|
|
48
|
-
</span>
|
|
49
|
-
<label className="relative inline-flex cursor-pointer items-center">
|
|
50
|
-
<input
|
|
51
|
-
id="switch"
|
|
52
|
-
checked={item.checkbox.alwaysActive || checked}
|
|
53
|
-
type="checkbox" className="peer sr-only"
|
|
54
|
-
onChange={() => {
|
|
55
|
-
onChange?.(!checked);
|
|
56
|
-
}}
|
|
57
|
-
/>
|
|
58
|
-
<label htmlFor="switch" className="hidden"></label>
|
|
59
|
-
<div className="peer h-6 w-11 rounded-full border bg-slate-200 after:absolute after:left-[2px] after:top-0.5 after:h-5 after:w-5 after:rounded-full after:border after:border-gray-300 after:bg-white after:transition-all after:content-[''] peer-checked:bg-slate-800 peer-checked:after:translate-x-full peer-checked:after:border-white peer-focus:ring-green-300"></div>
|
|
60
|
-
</label>
|
|
61
|
-
</div>
|
|
62
|
-
</div>
|
|
63
|
-
|
|
64
|
-
<p className={clsx(opened ? "" : "hidden")}>
|
|
65
|
-
<motion.div
|
|
66
|
-
initial="hidden"
|
|
67
|
-
className={
|
|
68
|
-
clsx("text-sm pt-4")
|
|
69
|
-
}
|
|
70
|
-
animate={{
|
|
71
|
-
opacity: opened ? "1" : "0",
|
|
72
|
-
height: opened ? "auto" : "0",
|
|
73
|
-
transition: opened ? { duration: 0.2, } : {}
|
|
74
|
-
}}
|
|
75
|
-
>
|
|
76
|
-
{item.content}
|
|
77
|
-
</motion.div>
|
|
78
|
-
</p>
|
|
79
|
-
</div >
|
|
80
|
-
)
|
|
1
|
+
import type { CookieItem } from "./types";
|
|
2
|
+
import clsx from "clsx";
|
|
3
|
+
import { motion } from "framer-motion";
|
|
4
|
+
|
|
5
|
+
export function CookieItemPanel(props: {
|
|
6
|
+
item: CookieItem,
|
|
7
|
+
openedItem?: string,
|
|
8
|
+
onToggle: (value: string) => void,
|
|
9
|
+
checked?: boolean
|
|
10
|
+
onChange?: (checked: boolean) => void
|
|
11
|
+
}) {
|
|
12
|
+
const { item, openedItem, checked, onChange, onToggle } = props;
|
|
13
|
+
|
|
14
|
+
const opened = openedItem === item.checkbox.valueName;
|
|
15
|
+
return (
|
|
16
|
+
<div className="p-4 bg-gray-100 rounded-md">
|
|
17
|
+
<div className="flex justify-between">
|
|
18
|
+
<h2
|
|
19
|
+
className="flex text-sm font-bold items-center gap-2 cursor-pointer select-none"
|
|
20
|
+
onClick={() => onToggle(item.checkbox.valueName)}
|
|
21
|
+
>
|
|
22
|
+
<span
|
|
23
|
+
className={
|
|
24
|
+
clsx(
|
|
25
|
+
"rounded-full h-7 w-7 p-1 bg-gray-200 transition-transform duration-200 ease-in-out",
|
|
26
|
+
opened ? "transform rotate-[-180deg]" : ""
|
|
27
|
+
)
|
|
28
|
+
}>
|
|
29
|
+
<svg
|
|
30
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
31
|
+
fill="none"
|
|
32
|
+
viewBox="0 0 24 24"
|
|
33
|
+
strokeWidth="1.5"
|
|
34
|
+
stroke="currentColor">
|
|
35
|
+
<path
|
|
36
|
+
strokeLinecap="round"
|
|
37
|
+
strokeLinejoin="round"
|
|
38
|
+
d="M19.5 8.25l-7.5 7.5-7.5-7.5" />
|
|
39
|
+
</svg>
|
|
40
|
+
</span>
|
|
41
|
+
<span>
|
|
42
|
+
{item.title}
|
|
43
|
+
</span>
|
|
44
|
+
</h2>
|
|
45
|
+
<div className="flex items-center gap-2">
|
|
46
|
+
<span className="text-sm">
|
|
47
|
+
{item.checkbox.alwaysActive ? item.checkbox.label : (checked ? "Active" : "")}
|
|
48
|
+
</span>
|
|
49
|
+
<label className="relative inline-flex cursor-pointer items-center">
|
|
50
|
+
<input
|
|
51
|
+
id="switch"
|
|
52
|
+
checked={item.checkbox.alwaysActive || checked}
|
|
53
|
+
type="checkbox" className="peer sr-only"
|
|
54
|
+
onChange={() => {
|
|
55
|
+
onChange?.(!checked);
|
|
56
|
+
}}
|
|
57
|
+
/>
|
|
58
|
+
<label htmlFor="switch" className="hidden"></label>
|
|
59
|
+
<div className="peer h-6 w-11 rounded-full border bg-slate-200 after:absolute after:left-[2px] after:top-0.5 after:h-5 after:w-5 after:rounded-full after:border after:border-gray-300 after:bg-white after:transition-all after:content-[''] peer-checked:bg-slate-800 peer-checked:after:translate-x-full peer-checked:after:border-white peer-focus:ring-green-300"></div>
|
|
60
|
+
</label>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
<p className={clsx(opened ? "" : "hidden")}>
|
|
65
|
+
<motion.div
|
|
66
|
+
initial="hidden"
|
|
67
|
+
className={
|
|
68
|
+
clsx("text-sm pt-4")
|
|
69
|
+
}
|
|
70
|
+
animate={{
|
|
71
|
+
opacity: opened ? "1" : "0",
|
|
72
|
+
height: opened ? "auto" : "0",
|
|
73
|
+
transition: opened ? { duration: 0.2, } : {}
|
|
74
|
+
}}
|
|
75
|
+
>
|
|
76
|
+
{item.content}
|
|
77
|
+
</motion.div>
|
|
78
|
+
</p>
|
|
79
|
+
</div >
|
|
80
|
+
)
|
|
81
81
|
}
|
|
@@ -1,149 +1,149 @@
|
|
|
1
|
-
import type { ConsentSettings, CookieItem } from "./types"
|
|
2
|
-
import { CookieItemPanel } from "./CookieItemPanel"
|
|
3
|
-
import { useState } from "react"
|
|
4
|
-
import { XModal } from "../XModal/XModal"
|
|
5
|
-
import { XModalAction } from "../XModalAction"
|
|
6
|
-
import { XModalOverlay } from "../XModalOverlay"
|
|
7
|
-
import { XModalContent } from "../XModalContent"
|
|
8
|
-
import { XModalClose } from "../XModalClose"
|
|
9
|
-
|
|
10
|
-
const items: CookieItem[] = [
|
|
11
|
-
{
|
|
12
|
-
title: "Strictly Necessary Cookies",
|
|
13
|
-
content: "These cookies are necessary for the website to function and cannot be switched off in our systems. They are usually only set in response to actions made by you which amount to a request for services, such as setting your privacy preferences or filling in forms.",
|
|
14
|
-
checkbox: {
|
|
15
|
-
valueName: "strictlyNecessary",
|
|
16
|
-
label: "Always Active",
|
|
17
|
-
alwaysActive: true,
|
|
18
|
-
}
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
title: "Analytics Cookies",
|
|
22
|
-
content: "These cookies allow us to track analytics by counting visits and traffic sources so we can measure and improve the performance of our website. They may be set by us or by third party providers to help us to know which pages are the most and least popular and see how visitors move around the website.",
|
|
23
|
-
checkbox: {
|
|
24
|
-
valueName: "analytics",
|
|
25
|
-
}
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
title: "Functionality Cookies",
|
|
29
|
-
content: "These cookies enable the website to provide enhanced functionality and personalization based on your interaction with the website. They may be set by us or by third party providers whose services we have added to our pages.",
|
|
30
|
-
checkbox: {
|
|
31
|
-
valueName: "functionality",
|
|
32
|
-
}
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
title: "Advertisement Cookies",
|
|
36
|
-
content: "These cookies may be set through our site by our advertising partners. They may be used by those partners to build a profile of your interests and show you relevant advertisements on other websites.",
|
|
37
|
-
checkbox: {
|
|
38
|
-
valueName: "advertisement",
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
]
|
|
42
|
-
|
|
43
|
-
export function CumtomizedModal(
|
|
44
|
-
props: {
|
|
45
|
-
onAcceptAll?: () => void,
|
|
46
|
-
onRejectAll?: () => void,
|
|
47
|
-
onSavePreferences?: (consent: ConsentSettings) => void
|
|
48
|
-
}
|
|
49
|
-
) {
|
|
50
|
-
const { onAcceptAll, onRejectAll, onSavePreferences } = props;
|
|
51
|
-
const [openedItem, setOpenedItem] = useState<string>();
|
|
52
|
-
const [consent, setConsent] = useState<ConsentSettings>({
|
|
53
|
-
strictlyNecessary: true,
|
|
54
|
-
analytics: false,
|
|
55
|
-
functionality: false,
|
|
56
|
-
advertisement: false,
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const handleSavePreferences = () => {
|
|
61
|
-
onSavePreferences?.(consent);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return (
|
|
65
|
-
<XModal
|
|
66
|
-
className="col-span-2 "
|
|
67
|
-
action={
|
|
68
|
-
<XModalAction
|
|
69
|
-
className="w-full text-white py-2 px-2 rounded bg-gray-700 hover:bg-gray-800"
|
|
70
|
-
>
|
|
71
|
-
Custimized Settings
|
|
72
|
-
</XModalAction>
|
|
73
|
-
}
|
|
74
|
-
overlay={
|
|
75
|
-
<XModalOverlay
|
|
76
|
-
initial={{ opacity: 0 }}
|
|
77
|
-
animate={{ opacity: 1 }}
|
|
78
|
-
exit={{ opacity: 0 }}
|
|
79
|
-
className="fixed inset-0 bg-black/30 backdrop-blur-md"
|
|
80
|
-
/>
|
|
81
|
-
}
|
|
82
|
-
content={
|
|
83
|
-
<div className="fixed inset-0 flex w-screen items-center justify-center p-4">
|
|
84
|
-
<XModalContent
|
|
85
|
-
initial={{ opacity: 0, scale: 0.95 }}
|
|
86
|
-
animate={{ opacity: 1, scale: 1 }}
|
|
87
|
-
exit={{ opacity: 0, scale: 0.95 }}
|
|
88
|
-
className="relative max-w-2xl space-y-4 bg-white pb-4 pt-0 px-4 rounded-lg w-full overflow-hidden"
|
|
89
|
-
>
|
|
90
|
-
<XModalClose className="absolute right-4 top-4 ">
|
|
91
|
-
<svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" aria-hidden="true">
|
|
92
|
-
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
|
|
93
|
-
</svg>
|
|
94
|
-
</XModalClose>
|
|
95
|
-
<div className="text-xl font-bold px-2">Privacy Preference Center</div>
|
|
96
|
-
<div className="h-[420px] overflow-y-scroll flex flex-col gap-2 px-2">
|
|
97
|
-
<h2 className="text-md font-bold">Cookie Usage</h2>
|
|
98
|
-
<p className="text-sm">
|
|
99
|
-
These cookies allow us to track analytics by counting visits and traffic sources so we can measure and improve the performance of our website. They may be set by us or by third party providers to help us to know which pages are the most and least popular and see how visitors move around the website.
|
|
100
|
-
</p>
|
|
101
|
-
{
|
|
102
|
-
items.map((item, index) => (
|
|
103
|
-
<CookieItemPanel
|
|
104
|
-
key={index}
|
|
105
|
-
item={item}
|
|
106
|
-
openedItem={openedItem}
|
|
107
|
-
checked={consent[item.checkbox.valueName as keyof ConsentSettings]}
|
|
108
|
-
onToggle={(value) => {
|
|
109
|
-
setOpenedItem(openedItem === value ? undefined : value);
|
|
110
|
-
}}
|
|
111
|
-
onChange={(checked) => {
|
|
112
|
-
setConsent((prev) => ({
|
|
113
|
-
...prev,
|
|
114
|
-
[item.checkbox.valueName]: checked
|
|
115
|
-
}))
|
|
116
|
-
}}
|
|
117
|
-
/>
|
|
118
|
-
))
|
|
119
|
-
}
|
|
120
|
-
</div>
|
|
121
|
-
<div className="flex items-center justify-between text-sm">
|
|
122
|
-
<div className="flex gap-4">
|
|
123
|
-
<button
|
|
124
|
-
className="bg-gray-700 hover:bg-gray-800 text-white py-2 px-3 rounded"
|
|
125
|
-
onClick={onAcceptAll}
|
|
126
|
-
>
|
|
127
|
-
Accept All Cookies
|
|
128
|
-
</button>
|
|
129
|
-
<button
|
|
130
|
-
className="bg-gray-700 hover:bg-gray-800 text-white py-2 px-3 rounded"
|
|
131
|
-
onClick={onRejectAll}
|
|
132
|
-
>
|
|
133
|
-
Reject All
|
|
134
|
-
</button>
|
|
135
|
-
</div>
|
|
136
|
-
<button
|
|
137
|
-
className="bg-green-500 hover:bg-green-600 text-white py-2 px-3 rounded"
|
|
138
|
-
onClick={handleSavePreferences}
|
|
139
|
-
>
|
|
140
|
-
Save Preferences
|
|
141
|
-
</button>
|
|
142
|
-
</div>
|
|
143
|
-
</XModalContent>
|
|
144
|
-
</div>
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/>
|
|
148
|
-
)
|
|
1
|
+
import type { ConsentSettings, CookieItem } from "./types"
|
|
2
|
+
import { CookieItemPanel } from "./CookieItemPanel"
|
|
3
|
+
import { useState } from "react"
|
|
4
|
+
import { XModal } from "../XModal/XModal"
|
|
5
|
+
import { XModalAction } from "../XModalAction"
|
|
6
|
+
import { XModalOverlay } from "../XModalOverlay"
|
|
7
|
+
import { XModalContent } from "../XModalContent"
|
|
8
|
+
import { XModalClose } from "../XModalClose"
|
|
9
|
+
|
|
10
|
+
const items: CookieItem[] = [
|
|
11
|
+
{
|
|
12
|
+
title: "Strictly Necessary Cookies",
|
|
13
|
+
content: "These cookies are necessary for the website to function and cannot be switched off in our systems. They are usually only set in response to actions made by you which amount to a request for services, such as setting your privacy preferences or filling in forms.",
|
|
14
|
+
checkbox: {
|
|
15
|
+
valueName: "strictlyNecessary",
|
|
16
|
+
label: "Always Active",
|
|
17
|
+
alwaysActive: true,
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
title: "Analytics Cookies",
|
|
22
|
+
content: "These cookies allow us to track analytics by counting visits and traffic sources so we can measure and improve the performance of our website. They may be set by us or by third party providers to help us to know which pages are the most and least popular and see how visitors move around the website.",
|
|
23
|
+
checkbox: {
|
|
24
|
+
valueName: "analytics",
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
title: "Functionality Cookies",
|
|
29
|
+
content: "These cookies enable the website to provide enhanced functionality and personalization based on your interaction with the website. They may be set by us or by third party providers whose services we have added to our pages.",
|
|
30
|
+
checkbox: {
|
|
31
|
+
valueName: "functionality",
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
title: "Advertisement Cookies",
|
|
36
|
+
content: "These cookies may be set through our site by our advertising partners. They may be used by those partners to build a profile of your interests and show you relevant advertisements on other websites.",
|
|
37
|
+
checkbox: {
|
|
38
|
+
valueName: "advertisement",
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
export function CumtomizedModal(
|
|
44
|
+
props: {
|
|
45
|
+
onAcceptAll?: () => void,
|
|
46
|
+
onRejectAll?: () => void,
|
|
47
|
+
onSavePreferences?: (consent: ConsentSettings) => void
|
|
48
|
+
}
|
|
49
|
+
) {
|
|
50
|
+
const { onAcceptAll, onRejectAll, onSavePreferences } = props;
|
|
51
|
+
const [openedItem, setOpenedItem] = useState<string>();
|
|
52
|
+
const [consent, setConsent] = useState<ConsentSettings>({
|
|
53
|
+
strictlyNecessary: true,
|
|
54
|
+
analytics: false,
|
|
55
|
+
functionality: false,
|
|
56
|
+
advertisement: false,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
const handleSavePreferences = () => {
|
|
61
|
+
onSavePreferences?.(consent);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<XModal
|
|
66
|
+
className="col-span-2 "
|
|
67
|
+
action={
|
|
68
|
+
<XModalAction
|
|
69
|
+
className="w-full text-white py-2 px-2 rounded bg-gray-700 hover:bg-gray-800"
|
|
70
|
+
>
|
|
71
|
+
Custimized Settings
|
|
72
|
+
</XModalAction>
|
|
73
|
+
}
|
|
74
|
+
overlay={
|
|
75
|
+
<XModalOverlay
|
|
76
|
+
initial={{ opacity: 0 }}
|
|
77
|
+
animate={{ opacity: 1 }}
|
|
78
|
+
exit={{ opacity: 0 }}
|
|
79
|
+
className="fixed inset-0 bg-black/30 backdrop-blur-md"
|
|
80
|
+
/>
|
|
81
|
+
}
|
|
82
|
+
content={
|
|
83
|
+
<div className="fixed inset-0 flex w-screen items-center justify-center p-4">
|
|
84
|
+
<XModalContent
|
|
85
|
+
initial={{ opacity: 0, scale: 0.95 }}
|
|
86
|
+
animate={{ opacity: 1, scale: 1 }}
|
|
87
|
+
exit={{ opacity: 0, scale: 0.95 }}
|
|
88
|
+
className="relative max-w-2xl space-y-4 bg-white pb-4 pt-0 px-4 rounded-lg w-full overflow-hidden"
|
|
89
|
+
>
|
|
90
|
+
<XModalClose className="absolute right-4 top-4 ">
|
|
91
|
+
<svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" aria-hidden="true">
|
|
92
|
+
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
|
|
93
|
+
</svg>
|
|
94
|
+
</XModalClose>
|
|
95
|
+
<div className="text-xl font-bold px-2">Privacy Preference Center</div>
|
|
96
|
+
<div className="h-[420px] overflow-y-scroll flex flex-col gap-2 px-2">
|
|
97
|
+
<h2 className="text-md font-bold">Cookie Usage</h2>
|
|
98
|
+
<p className="text-sm">
|
|
99
|
+
These cookies allow us to track analytics by counting visits and traffic sources so we can measure and improve the performance of our website. They may be set by us or by third party providers to help us to know which pages are the most and least popular and see how visitors move around the website.
|
|
100
|
+
</p>
|
|
101
|
+
{
|
|
102
|
+
items.map((item, index) => (
|
|
103
|
+
<CookieItemPanel
|
|
104
|
+
key={index}
|
|
105
|
+
item={item}
|
|
106
|
+
openedItem={openedItem}
|
|
107
|
+
checked={consent[item.checkbox.valueName as keyof ConsentSettings]}
|
|
108
|
+
onToggle={(value) => {
|
|
109
|
+
setOpenedItem(openedItem === value ? undefined : value);
|
|
110
|
+
}}
|
|
111
|
+
onChange={(checked) => {
|
|
112
|
+
setConsent((prev) => ({
|
|
113
|
+
...prev,
|
|
114
|
+
[item.checkbox.valueName]: checked
|
|
115
|
+
}))
|
|
116
|
+
}}
|
|
117
|
+
/>
|
|
118
|
+
))
|
|
119
|
+
}
|
|
120
|
+
</div>
|
|
121
|
+
<div className="flex items-center justify-between text-sm">
|
|
122
|
+
<div className="flex gap-4">
|
|
123
|
+
<button
|
|
124
|
+
className="bg-gray-700 hover:bg-gray-800 text-white py-2 px-3 rounded"
|
|
125
|
+
onClick={onAcceptAll}
|
|
126
|
+
>
|
|
127
|
+
Accept All Cookies
|
|
128
|
+
</button>
|
|
129
|
+
<button
|
|
130
|
+
className="bg-gray-700 hover:bg-gray-800 text-white py-2 px-3 rounded"
|
|
131
|
+
onClick={onRejectAll}
|
|
132
|
+
>
|
|
133
|
+
Reject All
|
|
134
|
+
</button>
|
|
135
|
+
</div>
|
|
136
|
+
<button
|
|
137
|
+
className="bg-green-500 hover:bg-green-600 text-white py-2 px-3 rounded"
|
|
138
|
+
onClick={handleSavePreferences}
|
|
139
|
+
>
|
|
140
|
+
Save Preferences
|
|
141
|
+
</button>
|
|
142
|
+
</div>
|
|
143
|
+
</XModalContent>
|
|
144
|
+
</div>
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/>
|
|
148
|
+
)
|
|
149
149
|
}
|
|
@@ -1,101 +1,101 @@
|
|
|
1
|
-
import { useEffect, useMemo, useState } from "react";
|
|
2
|
-
import { CumtomizedModal } from "./CumtomizedModal";
|
|
3
|
-
import Cookies from "universal-cookie"
|
|
4
|
-
import { ConsentSettings } from "./types";
|
|
5
|
-
import { Container } from "../Container";
|
|
6
|
-
import { gtag } from "./gtags";
|
|
7
|
-
|
|
8
|
-
const COOKIE_NAME = "gdpr-consent";
|
|
9
|
-
|
|
10
|
-
const DEINED_ALL: ConsentSettings = {
|
|
11
|
-
strictlyNecessary: true,
|
|
12
|
-
analytics: false,
|
|
13
|
-
functionality: false,
|
|
14
|
-
advertisement: false,
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function XGoogleConsent(props: {
|
|
18
|
-
domain?: string
|
|
19
|
-
}) {
|
|
20
|
-
const { domain } = props;
|
|
21
|
-
|
|
22
|
-
const [decisionMade, setDecisionMade] = useState(true) // start with true to avoid flashing
|
|
23
|
-
const cookies = useMemo(() => new Cookies(), []);
|
|
24
|
-
|
|
25
|
-
useEffect(() => {
|
|
26
|
-
const consent = cookies.get(COOKIE_NAME);
|
|
27
|
-
if (consent !== undefined) {
|
|
28
|
-
setDecisionMade(true)
|
|
29
|
-
sendConsent(consent)
|
|
30
|
-
} else {
|
|
31
|
-
setDecisionMade(false)
|
|
32
|
-
// 默认设置
|
|
33
|
-
gtag.consent(DEINED_ALL);
|
|
34
|
-
}
|
|
35
|
-
}, [cookies, setDecisionMade])
|
|
36
|
-
|
|
37
|
-
const handleSavePreferences = (consent: ConsentSettings) => {
|
|
38
|
-
saveDecision(consent)
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
const handleDeclineAll = () => {
|
|
42
|
-
saveDecision(DEINED_ALL)
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const saveDecision = (consent: ConsentSettings) => {
|
|
46
|
-
sendConsent(consent);
|
|
47
|
-
|
|
48
|
-
cookies.set(COOKIE_NAME, consent, {
|
|
49
|
-
expires: new Date(new Date().setFullYear(new Date().getFullYear() + 1)),
|
|
50
|
-
path: "/",
|
|
51
|
-
domain: domain
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
setDecisionMade(true)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const sendConsent = (consent: ConsentSettings) => {
|
|
58
|
-
gtag.consent(consent);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const handleAcceptAll = () => {
|
|
62
|
-
saveDecision({
|
|
63
|
-
advertisement: true,
|
|
64
|
-
analytics: true,
|
|
65
|
-
functionality: true,
|
|
66
|
-
strictlyNecessary: true
|
|
67
|
-
})
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
if (decisionMade) {
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
return (
|
|
75
|
-
<div className="fixed left-0 bottom-0 w-full shadow-lg bg-gray-600">
|
|
76
|
-
<Container>
|
|
77
|
-
<div className="text-white p-6 w-full">
|
|
78
|
-
<div className="flex flex-1 items-center gap-8 justify-between">
|
|
79
|
-
<div className="text-sm">
|
|
80
|
-
<h2 className="text-md font-bold pb-2">We Value Your Privacy</h2>
|
|
81
|
-
We use cookies for site improvement, personalization, and ads. Accepting enhances your experience, but you can manage preferences or decline non-essential cookies. See our <a className="text-blue-500" target="_blank" href="/privacy-policy">Cookie Policy</a> for details.
|
|
82
|
-
</div>
|
|
83
|
-
<div className="grid grid-cols-2 w-[300px] gap-2 text-sm">
|
|
84
|
-
<button onClick={handleAcceptAll} className="bg-green-400 hover:bg-green-500 text-white py-2 px-2 rounded">
|
|
85
|
-
Accept All
|
|
86
|
-
</button>
|
|
87
|
-
<button onClick={handleDeclineAll} className="text-white py-2 px-2 rounded bg-gray-700 hover:bg-gray-800">
|
|
88
|
-
Decline All
|
|
89
|
-
</button>
|
|
90
|
-
<CumtomizedModal
|
|
91
|
-
onAcceptAll={handleAcceptAll}
|
|
92
|
-
onRejectAll={handleDeclineAll}
|
|
93
|
-
onSavePreferences={handleSavePreferences}
|
|
94
|
-
/>
|
|
95
|
-
</div>
|
|
96
|
-
</div>
|
|
97
|
-
</div>
|
|
98
|
-
</Container>
|
|
99
|
-
</div>
|
|
100
|
-
);
|
|
1
|
+
import { useEffect, useMemo, useState } from "react";
|
|
2
|
+
import { CumtomizedModal } from "./CumtomizedModal";
|
|
3
|
+
import Cookies from "universal-cookie"
|
|
4
|
+
import { ConsentSettings } from "./types";
|
|
5
|
+
import { Container } from "../Container";
|
|
6
|
+
import { gtag } from "./gtags";
|
|
7
|
+
|
|
8
|
+
const COOKIE_NAME = "gdpr-consent";
|
|
9
|
+
|
|
10
|
+
const DEINED_ALL: ConsentSettings = {
|
|
11
|
+
strictlyNecessary: true,
|
|
12
|
+
analytics: false,
|
|
13
|
+
functionality: false,
|
|
14
|
+
advertisement: false,
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function XGoogleConsent(props: {
|
|
18
|
+
domain?: string
|
|
19
|
+
}) {
|
|
20
|
+
const { domain } = props;
|
|
21
|
+
|
|
22
|
+
const [decisionMade, setDecisionMade] = useState(true) // start with true to avoid flashing
|
|
23
|
+
const cookies = useMemo(() => new Cookies(), []);
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
const consent = cookies.get(COOKIE_NAME);
|
|
27
|
+
if (consent !== undefined) {
|
|
28
|
+
setDecisionMade(true)
|
|
29
|
+
sendConsent(consent)
|
|
30
|
+
} else {
|
|
31
|
+
setDecisionMade(false)
|
|
32
|
+
// 默认设置
|
|
33
|
+
gtag.consent(DEINED_ALL);
|
|
34
|
+
}
|
|
35
|
+
}, [cookies, setDecisionMade])
|
|
36
|
+
|
|
37
|
+
const handleSavePreferences = (consent: ConsentSettings) => {
|
|
38
|
+
saveDecision(consent)
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const handleDeclineAll = () => {
|
|
42
|
+
saveDecision(DEINED_ALL)
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const saveDecision = (consent: ConsentSettings) => {
|
|
46
|
+
sendConsent(consent);
|
|
47
|
+
|
|
48
|
+
cookies.set(COOKIE_NAME, consent, {
|
|
49
|
+
expires: new Date(new Date().setFullYear(new Date().getFullYear() + 1)),
|
|
50
|
+
path: "/",
|
|
51
|
+
domain: domain
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
setDecisionMade(true)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const sendConsent = (consent: ConsentSettings) => {
|
|
58
|
+
gtag.consent(consent);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const handleAcceptAll = () => {
|
|
62
|
+
saveDecision({
|
|
63
|
+
advertisement: true,
|
|
64
|
+
analytics: true,
|
|
65
|
+
functionality: true,
|
|
66
|
+
strictlyNecessary: true
|
|
67
|
+
})
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
if (decisionMade) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<div className="fixed left-0 bottom-0 w-full shadow-lg bg-gray-600">
|
|
76
|
+
<Container>
|
|
77
|
+
<div className="text-white p-6 w-full">
|
|
78
|
+
<div className="flex flex-1 items-center gap-8 justify-between">
|
|
79
|
+
<div className="text-sm">
|
|
80
|
+
<h2 className="text-md font-bold pb-2">We Value Your Privacy</h2>
|
|
81
|
+
We use cookies for site improvement, personalization, and ads. Accepting enhances your experience, but you can manage preferences or decline non-essential cookies. See our <a className="text-blue-500" target="_blank" href="/privacy-policy">Cookie Policy</a> for details.
|
|
82
|
+
</div>
|
|
83
|
+
<div className="grid grid-cols-2 w-[300px] gap-2 text-sm">
|
|
84
|
+
<button onClick={handleAcceptAll} className="bg-green-400 hover:bg-green-500 text-white py-2 px-2 rounded">
|
|
85
|
+
Accept All
|
|
86
|
+
</button>
|
|
87
|
+
<button onClick={handleDeclineAll} className="text-white py-2 px-2 rounded bg-gray-700 hover:bg-gray-800">
|
|
88
|
+
Decline All
|
|
89
|
+
</button>
|
|
90
|
+
<CumtomizedModal
|
|
91
|
+
onAcceptAll={handleAcceptAll}
|
|
92
|
+
onRejectAll={handleDeclineAll}
|
|
93
|
+
onSavePreferences={handleSavePreferences}
|
|
94
|
+
/>
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
</Container>
|
|
99
|
+
</div>
|
|
100
|
+
);
|
|
101
101
|
}
|