@c15t/dev-tools 0.0.1-rc.3 → 0.0.1-rc.4
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/dist/components/error-state.cjs +87 -115
- package/dist/components/error-state.css +51 -0
- package/dist/components/error-state.d.ts +5 -6
- package/dist/components/error-state.d.ts.map +1 -1
- package/dist/components/error-state.js +61 -107
- package/dist/components/header.cjs +54 -77
- package/dist/components/header.css +29 -0
- package/dist/components/header.d.ts +4 -5
- package/dist/components/header.d.ts.map +1 -1
- package/dist/components/header.js +28 -53
- package/dist/components/ui/accordion.cjs +64 -107
- package/dist/components/ui/accordion.css +72 -0
- package/dist/components/ui/accordion.d.ts +6 -32
- package/dist/components/ui/accordion.d.ts.map +1 -1
- package/dist/components/ui/accordion.js +36 -81
- package/dist/components/ui/alert.cjs +62 -93
- package/dist/components/ui/alert.css +59 -0
- package/dist/components/ui/alert.d.ts +7 -22
- package/dist/components/ui/alert.d.ts.map +1 -1
- package/dist/components/ui/alert.js +34 -64
- package/dist/components/ui/badge.cjs +61 -0
- package/dist/components/ui/badge.css +52 -0
- package/dist/components/ui/badge.d.ts +11 -0
- package/dist/components/ui/badge.d.ts.map +1 -0
- package/dist/components/ui/badge.js +26 -0
- package/dist/components/ui/button.cjs +65 -85
- package/dist/components/ui/button.css +87 -0
- package/dist/components/ui/button.d.ts +9 -24
- package/dist/components/ui/button.d.ts.map +1 -1
- package/dist/components/ui/button.js +38 -53
- package/dist/components/ui/card.cjs +65 -106
- package/dist/components/ui/card.css +41 -0
- package/dist/components/ui/card.d.ts +9 -29
- package/dist/components/ui/card.d.ts.map +1 -1
- package/dist/components/ui/card.js +35 -94
- package/dist/components/ui/error-state.css +34 -0
- package/dist/components/ui/expandable-tabs.cjs +117 -182
- package/dist/components/ui/expandable-tabs.css +57 -0
- package/dist/components/ui/expandable-tabs.d.ts +14 -20
- package/dist/components/ui/expandable-tabs.d.ts.map +1 -1
- package/dist/components/ui/expandable-tabs.js +91 -159
- package/dist/components/ui/logo.cjs +101 -0
- package/dist/components/ui/logo.d.ts +8 -0
- package/dist/components/ui/logo.d.ts.map +1 -0
- package/dist/components/ui/logo.js +67 -0
- package/dist/components/ui/scroll-area.cjs +54 -94
- package/dist/components/ui/scroll-area.css +42 -0
- package/dist/components/ui/scroll-area.d.ts +4 -17
- package/dist/components/ui/scroll-area.d.ts.map +1 -1
- package/dist/components/ui/scroll-area.js +28 -72
- package/dist/components/ui/switch.cjs +38 -60
- package/dist/components/ui/switch.css +49 -0
- package/dist/components/ui/switch.d.ts +3 -9
- package/dist/components/ui/switch.d.ts.map +1 -1
- package/dist/components/ui/switch.js +13 -31
- package/dist/components/ui/tooltip.cjs +41 -61
- package/dist/components/ui/tooltip.css +101 -0
- package/dist/components/ui/tooltip.d.ts +6 -14
- package/dist/components/ui/tooltip.d.ts.map +1 -1
- package/dist/components/ui/tooltip.js +16 -36
- package/dist/components/wrapper.cjs +144 -185
- package/dist/components/wrapper.css +90 -0
- package/dist/components/wrapper.d.ts +8 -12
- package/dist/components/wrapper.d.ts.map +1 -1
- package/dist/components/wrapper.js +117 -161
- package/dist/dev-tool.cjs +110 -150
- package/dist/dev-tool.d.ts +8 -7
- package/dist/dev-tool.d.ts.map +1 -1
- package/dist/dev-tool.js +70 -106
- package/dist/index.cjs +27 -37
- package/dist/index.d.ts +2 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -4
- package/dist/libs/utils.cjs +42 -57
- package/dist/libs/utils.d.ts +1 -1
- package/dist/libs/utils.js +3 -5
- package/dist/router/router.cjs +145 -265
- package/dist/router/router.d.ts +3 -5
- package/dist/router/router.d.ts.map +1 -1
- package/dist/router/router.js +119 -256
- package/dist/styles/theme.css +42 -0
- package/package.json +2 -2
- package/.turbo/turbo-build.log +0 -56
- package/.turbo/turbo-fmt.log +0 -6
- package/.turbo/turbo-lint.log +0 -73
- package/dist/components/ui/overlay.cjs +0 -69
- package/dist/components/ui/overlay.d.ts +0 -7
- package/dist/components/ui/overlay.d.ts.map +0 -1
- package/dist/components/ui/overlay.js +0 -28
- package/rslib.config.ts +0 -28
- package/src/components/error-state.tsx +0 -44
- package/src/components/header.tsx +0 -28
- package/src/components/ui/accordion.tsx +0 -64
- package/src/components/ui/alert.tsx +0 -59
- package/src/components/ui/button.tsx +0 -56
- package/src/components/ui/card.tsx +0 -81
- package/src/components/ui/expandable-tabs.tsx +0 -174
- package/src/components/ui/overlay.tsx +0 -21
- package/src/components/ui/scroll-area.tsx +0 -52
- package/src/components/ui/switch.tsx +0 -28
- package/src/components/ui/tooltip.tsx +0 -32
- package/src/components/wrapper.tsx +0 -103
- package/src/dev-tool.tsx +0 -117
- package/src/index.ts +0 -3
- package/src/libs/utils.ts +0 -6
- package/src/router/router.tsx +0 -164
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
type ComponentPropsWithoutRef,
|
|
7
|
-
type ElementRef,
|
|
8
|
-
forwardRef,
|
|
9
|
-
} from 'react';
|
|
10
|
-
import { cn } from '../../libs/utils';
|
|
11
|
-
|
|
12
|
-
const ScrollArea = forwardRef<
|
|
13
|
-
ElementRef<typeof ScrollAreaPrimitive.Root>,
|
|
14
|
-
ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
|
|
15
|
-
>(({ className, children, ...props }, ref) => (
|
|
16
|
-
<ScrollAreaPrimitive.Root
|
|
17
|
-
ref={ref}
|
|
18
|
-
className={cn('relative overflow-hidden', className)}
|
|
19
|
-
{...props}
|
|
20
|
-
>
|
|
21
|
-
<ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">
|
|
22
|
-
{children}
|
|
23
|
-
</ScrollAreaPrimitive.Viewport>
|
|
24
|
-
<ScrollBar />
|
|
25
|
-
<ScrollAreaPrimitive.Corner />
|
|
26
|
-
</ScrollAreaPrimitive.Root>
|
|
27
|
-
));
|
|
28
|
-
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
|
|
29
|
-
|
|
30
|
-
const ScrollBar = forwardRef<
|
|
31
|
-
ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
|
|
32
|
-
ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>
|
|
33
|
-
>(({ className, orientation = 'vertical', ...props }, ref) => (
|
|
34
|
-
<ScrollAreaPrimitive.ScrollAreaScrollbar
|
|
35
|
-
ref={ref}
|
|
36
|
-
orientation={orientation}
|
|
37
|
-
className={cn(
|
|
38
|
-
'flex touch-none select-none transition-colors',
|
|
39
|
-
orientation === 'vertical' &&
|
|
40
|
-
'h-full w-2.5 border-l border-l-transparent p-[1px]',
|
|
41
|
-
orientation === 'horizontal' &&
|
|
42
|
-
'h-2.5 flex-col border-t border-t-transparent p-[1px]',
|
|
43
|
-
className
|
|
44
|
-
)}
|
|
45
|
-
{...props}
|
|
46
|
-
>
|
|
47
|
-
<ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border" />
|
|
48
|
-
</ScrollAreaPrimitive.ScrollAreaScrollbar>
|
|
49
|
-
));
|
|
50
|
-
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
|
|
51
|
-
|
|
52
|
-
export { ScrollArea, ScrollBar };
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import * as SwitchPrimitives from '@radix-ui/react-switch';
|
|
4
|
-
import * as React from 'react';
|
|
5
|
-
import { cn } from '../../libs/utils';
|
|
6
|
-
|
|
7
|
-
const Switch = React.forwardRef<
|
|
8
|
-
React.ElementRef<typeof SwitchPrimitives.Root>,
|
|
9
|
-
React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root>
|
|
10
|
-
>(({ className, ...props }, ref) => (
|
|
11
|
-
<SwitchPrimitives.Root
|
|
12
|
-
className={cn(
|
|
13
|
-
'peer inline-flex h-[24px] w-[44px] shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input',
|
|
14
|
-
className
|
|
15
|
-
)}
|
|
16
|
-
{...props}
|
|
17
|
-
ref={ref}
|
|
18
|
-
>
|
|
19
|
-
<SwitchPrimitives.Thumb
|
|
20
|
-
className={cn(
|
|
21
|
-
'pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0'
|
|
22
|
-
)}
|
|
23
|
-
/>
|
|
24
|
-
</SwitchPrimitives.Root>
|
|
25
|
-
));
|
|
26
|
-
Switch.displayName = SwitchPrimitives.Root.displayName;
|
|
27
|
-
|
|
28
|
-
export { Switch };
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import * as TooltipPrimitive from '@radix-ui/react-tooltip';
|
|
4
|
-
import * as React from 'react';
|
|
5
|
-
|
|
6
|
-
import { cn } from '../../libs/utils';
|
|
7
|
-
|
|
8
|
-
const TooltipProvider = TooltipPrimitive.Provider;
|
|
9
|
-
|
|
10
|
-
const Tooltip = TooltipPrimitive.Root;
|
|
11
|
-
|
|
12
|
-
const TooltipTrigger = TooltipPrimitive.Trigger;
|
|
13
|
-
|
|
14
|
-
const TooltipContent = React.forwardRef<
|
|
15
|
-
React.ElementRef<typeof TooltipPrimitive.Content>,
|
|
16
|
-
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
|
|
17
|
-
>(({ className, sideOffset = 4, ...props }, ref) => (
|
|
18
|
-
<TooltipPrimitive.Portal>
|
|
19
|
-
<TooltipPrimitive.Content
|
|
20
|
-
ref={ref}
|
|
21
|
-
sideOffset={sideOffset}
|
|
22
|
-
className={cn(
|
|
23
|
-
'fade-in-0 zoom-in-95 data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 animate-in overflow-hidden rounded-md bg-primary px-3 py-1.5 text-primary-foreground text-xs data-[state=closed]:animate-out',
|
|
24
|
-
className
|
|
25
|
-
)}
|
|
26
|
-
{...props}
|
|
27
|
-
/>
|
|
28
|
-
</TooltipPrimitive.Portal>
|
|
29
|
-
));
|
|
30
|
-
TooltipContent.displayName = TooltipPrimitive.Content.displayName;
|
|
31
|
-
|
|
32
|
-
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { Shield } from 'lucide-react';
|
|
4
|
-
import { AnimatePresence, motion } from 'motion/react';
|
|
5
|
-
|
|
6
|
-
import { type ReactNode, useEffect, useState } from 'react';
|
|
7
|
-
import { createPortal } from 'react-dom';
|
|
8
|
-
import { cn } from '../libs/utils';
|
|
9
|
-
import { Button } from './ui/button';
|
|
10
|
-
import { Card } from './ui/card';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Dev Tool Wrapper Component
|
|
14
|
-
*
|
|
15
|
-
* This component serves as both an icon and a wrapper for the development tool interface.
|
|
16
|
-
* It provides a button that, when clicked, toggles the visibility of a pop-up containing
|
|
17
|
-
* the router pages.
|
|
18
|
-
*
|
|
19
|
-
* @component
|
|
20
|
-
* @returns {JSX.Element} The rendered component
|
|
21
|
-
*/
|
|
22
|
-
export function DevToolWrapper({
|
|
23
|
-
children,
|
|
24
|
-
isOpen,
|
|
25
|
-
toggleOpen,
|
|
26
|
-
position = 'bottom-right',
|
|
27
|
-
}: {
|
|
28
|
-
children: ReactNode;
|
|
29
|
-
isOpen: boolean;
|
|
30
|
-
toggleOpen: () => void;
|
|
31
|
-
position?: 'bottom-right' | 'top-right' | 'bottom-left' | 'top-left';
|
|
32
|
-
}) {
|
|
33
|
-
// Track whether component is mounted to handle client-side only features
|
|
34
|
-
const [isMounted, setIsMounted] = useState(false);
|
|
35
|
-
|
|
36
|
-
useEffect(() => {
|
|
37
|
-
setIsMounted(true);
|
|
38
|
-
return () => setIsMounted(false);
|
|
39
|
-
}, []);
|
|
40
|
-
|
|
41
|
-
const DevToolContent = (
|
|
42
|
-
<AnimatePresence>
|
|
43
|
-
{isOpen && (
|
|
44
|
-
<motion.div
|
|
45
|
-
className="fixed inset-0 z-50 flex items-end justify-center sm:items-center"
|
|
46
|
-
initial={{ opacity: 0 }}
|
|
47
|
-
animate={{ opacity: 1 }}
|
|
48
|
-
exit={{ opacity: 0 }}
|
|
49
|
-
>
|
|
50
|
-
<motion.div
|
|
51
|
-
className="fixed inset-0 bg-background/10 backdrop-blur-sm"
|
|
52
|
-
initial={{ opacity: 0 }}
|
|
53
|
-
animate={{ opacity: 1 }}
|
|
54
|
-
exit={{ opacity: 0 }}
|
|
55
|
-
onClick={toggleOpen}
|
|
56
|
-
/>
|
|
57
|
-
<motion.div
|
|
58
|
-
className={cn(
|
|
59
|
-
'fixed z-[9999]',
|
|
60
|
-
position === 'bottom-right' && 'right-4 bottom-4',
|
|
61
|
-
position === 'top-right' && 'top-4 right-4',
|
|
62
|
-
position === 'bottom-left' && 'bottom-4 left-4',
|
|
63
|
-
position === 'top-left' && 'top-4 left-4'
|
|
64
|
-
)}
|
|
65
|
-
initial={{ opacity: 0, y: 50 }}
|
|
66
|
-
animate={{ opacity: 1, y: 0 }}
|
|
67
|
-
exit={{ opacity: 0, y: 50 }}
|
|
68
|
-
transition={{ type: 'spring', stiffness: 300, damping: 30 }}
|
|
69
|
-
>
|
|
70
|
-
<Card className="w-[350px] shadow-lg">{children}</Card>
|
|
71
|
-
</motion.div>
|
|
72
|
-
</motion.div>
|
|
73
|
-
)}
|
|
74
|
-
</AnimatePresence>
|
|
75
|
-
);
|
|
76
|
-
|
|
77
|
-
return (
|
|
78
|
-
<>
|
|
79
|
-
<AnimatePresence>
|
|
80
|
-
{!isOpen && (
|
|
81
|
-
<motion.div
|
|
82
|
-
initial={{ scale: 0.9, opacity: 0 }}
|
|
83
|
-
animate={{ scale: 1, opacity: 1 }}
|
|
84
|
-
exit={{ scale: 0.9, opacity: 0 }}
|
|
85
|
-
className="fixed right-4 bottom-4 z-[9999]"
|
|
86
|
-
>
|
|
87
|
-
<Button
|
|
88
|
-
variant="outline"
|
|
89
|
-
size="icon"
|
|
90
|
-
className="h-10 w-10 rounded-full shadow-lg"
|
|
91
|
-
onClick={toggleOpen}
|
|
92
|
-
>
|
|
93
|
-
<Shield className="h-4 w-4" />
|
|
94
|
-
</Button>
|
|
95
|
-
</motion.div>
|
|
96
|
-
)}
|
|
97
|
-
</AnimatePresence>
|
|
98
|
-
{isMounted && createPortal(DevToolContent, document.body)}
|
|
99
|
-
</>
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
export default DevToolWrapper;
|
package/src/dev-tool.tsx
DELETED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import type { NamespaceProps, PrivacyConsentState } from 'c15t';
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
type FC,
|
|
6
|
-
createContext,
|
|
7
|
-
useCallback,
|
|
8
|
-
useContext,
|
|
9
|
-
useEffect,
|
|
10
|
-
useState,
|
|
11
|
-
} from 'react';
|
|
12
|
-
import type { StoreApi } from 'zustand/vanilla';
|
|
13
|
-
import { ErrorState } from './components/error-state';
|
|
14
|
-
import { Header } from './components/header';
|
|
15
|
-
import DevToolWrapper from './components/wrapper';
|
|
16
|
-
import { Router } from './router/router';
|
|
17
|
-
|
|
18
|
-
const PrivacyConsentContext = createContext<{
|
|
19
|
-
state: PrivacyConsentState | null;
|
|
20
|
-
store: StoreApi<PrivacyConsentState> | null;
|
|
21
|
-
} | null>(null);
|
|
22
|
-
|
|
23
|
-
export const getStore = () => {
|
|
24
|
-
const context = useContext(PrivacyConsentContext);
|
|
25
|
-
if (context === null) {
|
|
26
|
-
throw new Error(
|
|
27
|
-
'useConsentManagerContext must be used within a ConsentManagerProvider'
|
|
28
|
-
);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Create a subscription to the store updates
|
|
32
|
-
const [localState, setLocalState] = useState(context.state);
|
|
33
|
-
|
|
34
|
-
useEffect(() => {
|
|
35
|
-
if (!context.store) {
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// Update local state when context state changes
|
|
40
|
-
setLocalState(context.state);
|
|
41
|
-
|
|
42
|
-
// Subscribe to store updates
|
|
43
|
-
const unsubscribe = context.store.subscribe(
|
|
44
|
-
(newState: PrivacyConsentState) => {
|
|
45
|
-
setLocalState(newState);
|
|
46
|
-
}
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
return () => {
|
|
50
|
-
unsubscribe();
|
|
51
|
-
};
|
|
52
|
-
}, [context.store, context.state]);
|
|
53
|
-
|
|
54
|
-
return localState;
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
export default PrivacyConsentContext;
|
|
58
|
-
|
|
59
|
-
interface ConsentManagerProviderProps extends NamespaceProps {
|
|
60
|
-
position?: 'bottom-right' | 'top-right' | 'bottom-left' | 'top-left';
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export const ConsentManagerDevTool: FC<ConsentManagerProviderProps> = ({
|
|
64
|
-
namespace = 'c15tStore',
|
|
65
|
-
position = 'bottom-right',
|
|
66
|
-
}) => {
|
|
67
|
-
const [state, setState] = useState<PrivacyConsentState | null>(null);
|
|
68
|
-
const [store, setStore] = useState<StoreApi<PrivacyConsentState> | null>(
|
|
69
|
-
null
|
|
70
|
-
);
|
|
71
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
72
|
-
const toggleOpen = useCallback(() => setIsOpen((prev) => !prev), []);
|
|
73
|
-
|
|
74
|
-
useEffect(() => {
|
|
75
|
-
const storeInstance =
|
|
76
|
-
(typeof window !== 'undefined' &&
|
|
77
|
-
(window as Window)[namespace as keyof Window]) ||
|
|
78
|
-
null;
|
|
79
|
-
|
|
80
|
-
if (storeInstance) {
|
|
81
|
-
setStore(storeInstance);
|
|
82
|
-
const currentState = storeInstance.getState() as PrivacyConsentState;
|
|
83
|
-
setState(currentState);
|
|
84
|
-
|
|
85
|
-
// Subscribe to store updates
|
|
86
|
-
const unsubscribe = storeInstance.subscribe(
|
|
87
|
-
(newState: PrivacyConsentState) => {
|
|
88
|
-
setState(newState);
|
|
89
|
-
}
|
|
90
|
-
);
|
|
91
|
-
|
|
92
|
-
return () => {
|
|
93
|
-
unsubscribe();
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
// biome-ignore lint/suspicious/noConsoleLog: needed for dev tools
|
|
97
|
-
// biome-ignore lint/suspicious/noConsole: needed for dev tools
|
|
98
|
-
console.log(`${namespace} is not available on the window object.`);
|
|
99
|
-
}, [namespace]);
|
|
100
|
-
|
|
101
|
-
return (
|
|
102
|
-
<PrivacyConsentContext.Provider value={{ state, store }}>
|
|
103
|
-
<DevToolWrapper
|
|
104
|
-
isOpen={isOpen}
|
|
105
|
-
toggleOpen={toggleOpen}
|
|
106
|
-
position={position}
|
|
107
|
-
>
|
|
108
|
-
<Header onClose={() => setIsOpen(false)} />
|
|
109
|
-
{state ? (
|
|
110
|
-
<Router onClose={() => setIsOpen(false)} />
|
|
111
|
-
) : (
|
|
112
|
-
<ErrorState namespace={namespace} />
|
|
113
|
-
)}
|
|
114
|
-
</DevToolWrapper>
|
|
115
|
-
</PrivacyConsentContext.Provider>
|
|
116
|
-
);
|
|
117
|
-
};
|
package/src/index.ts
DELETED
package/src/libs/utils.ts
DELETED
package/src/router/router.tsx
DELETED
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
Cookie,
|
|
5
|
-
FileText,
|
|
6
|
-
GanttChartSquare,
|
|
7
|
-
RefreshCw,
|
|
8
|
-
ToggleLeft,
|
|
9
|
-
} from 'lucide-react';
|
|
10
|
-
import { motion } from 'motion/react';
|
|
11
|
-
import { useCallback, useState } from 'react';
|
|
12
|
-
|
|
13
|
-
import type { PrivacyConsentState } from 'c15t';
|
|
14
|
-
import { Button } from '../components/ui/button';
|
|
15
|
-
import { ExpandableTabs } from '../components/ui/expandable-tabs';
|
|
16
|
-
import { ScrollArea } from '../components/ui/scroll-area';
|
|
17
|
-
import { getStore } from '../dev-tool';
|
|
18
|
-
import { cn } from '../libs/utils';
|
|
19
|
-
|
|
20
|
-
type TabSection = 'Consents' | 'Compliance' | 'Scripts' | 'Conditional';
|
|
21
|
-
|
|
22
|
-
const tabs = [
|
|
23
|
-
{ title: 'Consents' as const, icon: ToggleLeft },
|
|
24
|
-
{ title: 'Compliance' as const, icon: GanttChartSquare },
|
|
25
|
-
] as const;
|
|
26
|
-
|
|
27
|
-
interface ContentItem {
|
|
28
|
-
title: string;
|
|
29
|
-
status: string;
|
|
30
|
-
details?: string;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
interface RouterProps {
|
|
34
|
-
onClose: () => void;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export function Router({ onClose }: RouterProps) {
|
|
38
|
-
const privacyConsent = getStore() as PrivacyConsentState;
|
|
39
|
-
const { clearAllData, setIsPrivacyDialogOpen, setShowPopup } = privacyConsent;
|
|
40
|
-
|
|
41
|
-
const [activeSection, setActiveSection] = useState<TabSection>('Consents');
|
|
42
|
-
|
|
43
|
-
// Handle tab change locally
|
|
44
|
-
const handleTabChange = useCallback((index: number | null) => {
|
|
45
|
-
if (index !== null) {
|
|
46
|
-
//@ts-expect-error
|
|
47
|
-
setActiveSection(tabs[index].title);
|
|
48
|
-
}
|
|
49
|
-
}, []);
|
|
50
|
-
|
|
51
|
-
// Compute rendering state without conditions
|
|
52
|
-
const renderingState = [
|
|
53
|
-
{ componentName: 'MarketingContent', consentType: 'marketing' as const },
|
|
54
|
-
{ componentName: 'AnalyticsContent', consentType: 'measurement' as const },
|
|
55
|
-
{
|
|
56
|
-
componentName: 'PersonalizationComponent',
|
|
57
|
-
consentType: 'ad_personalization' as const,
|
|
58
|
-
},
|
|
59
|
-
];
|
|
60
|
-
|
|
61
|
-
// Compute content items based on active section
|
|
62
|
-
const contentItems: ContentItem[] =
|
|
63
|
-
activeSection === 'Consents'
|
|
64
|
-
? Object.entries(privacyConsent.consents).map(([name, value]) => ({
|
|
65
|
-
title: name,
|
|
66
|
-
status: value ? 'Enabled' : 'Disabled',
|
|
67
|
-
}))
|
|
68
|
-
: activeSection === 'Compliance'
|
|
69
|
-
? Object.entries(privacyConsent.complianceSettings).map(
|
|
70
|
-
([region, settings]) => ({
|
|
71
|
-
title: region,
|
|
72
|
-
status: settings.enabled ? 'Active' : 'Inactive',
|
|
73
|
-
})
|
|
74
|
-
)
|
|
75
|
-
: activeSection === 'Conditional'
|
|
76
|
-
? renderingState.map((item) => ({
|
|
77
|
-
title: item.componentName,
|
|
78
|
-
status: 'Rendered',
|
|
79
|
-
details: `Requires: ${item.consentType}`,
|
|
80
|
-
}))
|
|
81
|
-
: [];
|
|
82
|
-
|
|
83
|
-
const handleResetConsent = useCallback(() => {
|
|
84
|
-
clearAllData();
|
|
85
|
-
onClose();
|
|
86
|
-
}, [clearAllData, onClose]);
|
|
87
|
-
|
|
88
|
-
const handleOpenPrivacyModal = useCallback(() => {
|
|
89
|
-
setIsPrivacyDialogOpen(true);
|
|
90
|
-
}, [setIsPrivacyDialogOpen]);
|
|
91
|
-
|
|
92
|
-
const handleOpenCookiePopup = useCallback(() => {
|
|
93
|
-
setShowPopup(true);
|
|
94
|
-
}, [setShowPopup]);
|
|
95
|
-
|
|
96
|
-
return (
|
|
97
|
-
<>
|
|
98
|
-
<div className="border-b p-4">
|
|
99
|
-
<ExpandableTabs
|
|
100
|
-
tabs={Array.from(tabs)}
|
|
101
|
-
activeColor="text-primary"
|
|
102
|
-
className="border-muted"
|
|
103
|
-
onChange={handleTabChange}
|
|
104
|
-
/>
|
|
105
|
-
</div>
|
|
106
|
-
<ScrollArea className="h-[300px]">
|
|
107
|
-
<motion.div
|
|
108
|
-
className="space-y-2 p-4"
|
|
109
|
-
initial={{ opacity: 0 }}
|
|
110
|
-
animate={{ opacity: 1 }}
|
|
111
|
-
exit={{ opacity: 0 }}
|
|
112
|
-
>
|
|
113
|
-
{contentItems.map((item, index) => (
|
|
114
|
-
<motion.div
|
|
115
|
-
key={`${activeSection}-${item.title}`}
|
|
116
|
-
className="flex items-center justify-between rounded-lg border bg-card p-3"
|
|
117
|
-
initial={{ opacity: 0, y: 20 }}
|
|
118
|
-
animate={{ opacity: 1, y: 0 }}
|
|
119
|
-
transition={{ delay: index * 0.05 }}
|
|
120
|
-
>
|
|
121
|
-
<div className="flex flex-col">
|
|
122
|
-
<span className="font-medium text-sm">{item.title}</span>
|
|
123
|
-
{item.details && (
|
|
124
|
-
<span className="text-muted-foreground text-xs">
|
|
125
|
-
{item.details}
|
|
126
|
-
</span>
|
|
127
|
-
)}
|
|
128
|
-
</div>
|
|
129
|
-
<span
|
|
130
|
-
className={cn(
|
|
131
|
-
'rounded-full px-2 py-1 text-xs',
|
|
132
|
-
item.status === 'Enabled' ||
|
|
133
|
-
item.status === 'Active' ||
|
|
134
|
-
item.status === 'active' ||
|
|
135
|
-
item.status === 'Rendered'
|
|
136
|
-
? 'bg-green-100 text-green-800'
|
|
137
|
-
: 'bg-red-100 text-red-800'
|
|
138
|
-
)}
|
|
139
|
-
>
|
|
140
|
-
{item.status}
|
|
141
|
-
</span>
|
|
142
|
-
</motion.div>
|
|
143
|
-
))}
|
|
144
|
-
</motion.div>
|
|
145
|
-
</ScrollArea>
|
|
146
|
-
<div className="border-t p-4">
|
|
147
|
-
<div className="flex flex-col gap-2">
|
|
148
|
-
<Button variant="outline" size="sm" onClick={handleResetConsent}>
|
|
149
|
-
<RefreshCw className="mr-2 h-4 w-4" />
|
|
150
|
-
Reset Local Storage Consent
|
|
151
|
-
</Button>
|
|
152
|
-
<Button variant="outline" size="sm" onClick={handleOpenPrivacyModal}>
|
|
153
|
-
<FileText className="mr-2 h-4 w-4" />
|
|
154
|
-
Open Privacy Settings
|
|
155
|
-
</Button>
|
|
156
|
-
<Button variant="outline" size="sm" onClick={handleOpenCookiePopup}>
|
|
157
|
-
<Cookie className="mr-2 h-4 w-4" />
|
|
158
|
-
Open Cookie Popup
|
|
159
|
-
</Button>
|
|
160
|
-
</div>
|
|
161
|
-
</div>
|
|
162
|
-
</>
|
|
163
|
-
);
|
|
164
|
-
}
|