@c15t/dev-tools 0.0.1-rc.3 → 0.0.1-rc.5

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 (107) hide show
  1. package/README.md +1 -1
  2. package/dist/components/error-state.cjs +87 -115
  3. package/dist/components/error-state.css +51 -0
  4. package/dist/components/error-state.d.ts +5 -6
  5. package/dist/components/error-state.d.ts.map +1 -1
  6. package/dist/components/error-state.js +61 -107
  7. package/dist/components/header.cjs +54 -77
  8. package/dist/components/header.css +29 -0
  9. package/dist/components/header.d.ts +4 -5
  10. package/dist/components/header.d.ts.map +1 -1
  11. package/dist/components/header.js +28 -53
  12. package/dist/components/ui/accordion.cjs +64 -107
  13. package/dist/components/ui/accordion.css +72 -0
  14. package/dist/components/ui/accordion.d.ts +6 -32
  15. package/dist/components/ui/accordion.d.ts.map +1 -1
  16. package/dist/components/ui/accordion.js +36 -81
  17. package/dist/components/ui/alert.cjs +62 -93
  18. package/dist/components/ui/alert.css +59 -0
  19. package/dist/components/ui/alert.d.ts +7 -22
  20. package/dist/components/ui/alert.d.ts.map +1 -1
  21. package/dist/components/ui/alert.js +34 -64
  22. package/dist/components/ui/badge.cjs +61 -0
  23. package/dist/components/ui/badge.css +52 -0
  24. package/dist/components/ui/badge.d.ts +11 -0
  25. package/dist/components/ui/badge.d.ts.map +1 -0
  26. package/dist/components/ui/badge.js +26 -0
  27. package/dist/components/ui/button.cjs +65 -85
  28. package/dist/components/ui/button.css +87 -0
  29. package/dist/components/ui/button.d.ts +9 -24
  30. package/dist/components/ui/button.d.ts.map +1 -1
  31. package/dist/components/ui/button.js +38 -53
  32. package/dist/components/ui/card.cjs +65 -106
  33. package/dist/components/ui/card.css +41 -0
  34. package/dist/components/ui/card.d.ts +9 -29
  35. package/dist/components/ui/card.d.ts.map +1 -1
  36. package/dist/components/ui/card.js +35 -94
  37. package/dist/components/ui/error-state.css +34 -0
  38. package/dist/components/ui/expandable-tabs.cjs +117 -182
  39. package/dist/components/ui/expandable-tabs.css +57 -0
  40. package/dist/components/ui/expandable-tabs.d.ts +14 -20
  41. package/dist/components/ui/expandable-tabs.d.ts.map +1 -1
  42. package/dist/components/ui/expandable-tabs.js +91 -159
  43. package/dist/components/ui/logo.cjs +101 -0
  44. package/dist/components/ui/logo.d.ts +8 -0
  45. package/dist/components/ui/logo.d.ts.map +1 -0
  46. package/dist/components/ui/logo.js +67 -0
  47. package/dist/components/ui/scroll-area.cjs +54 -94
  48. package/dist/components/ui/scroll-area.css +42 -0
  49. package/dist/components/ui/scroll-area.d.ts +4 -17
  50. package/dist/components/ui/scroll-area.d.ts.map +1 -1
  51. package/dist/components/ui/scroll-area.js +28 -72
  52. package/dist/components/ui/switch.cjs +38 -60
  53. package/dist/components/ui/switch.css +49 -0
  54. package/dist/components/ui/switch.d.ts +3 -9
  55. package/dist/components/ui/switch.d.ts.map +1 -1
  56. package/dist/components/ui/switch.js +13 -31
  57. package/dist/components/ui/tooltip.cjs +41 -61
  58. package/dist/components/ui/tooltip.css +101 -0
  59. package/dist/components/ui/tooltip.d.ts +6 -14
  60. package/dist/components/ui/tooltip.d.ts.map +1 -1
  61. package/dist/components/ui/tooltip.js +16 -36
  62. package/dist/components/wrapper.cjs +144 -185
  63. package/dist/components/wrapper.css +90 -0
  64. package/dist/components/wrapper.d.ts +8 -12
  65. package/dist/components/wrapper.d.ts.map +1 -1
  66. package/dist/components/wrapper.js +117 -161
  67. package/dist/dev-tool.cjs +110 -150
  68. package/dist/dev-tool.d.ts +8 -7
  69. package/dist/dev-tool.d.ts.map +1 -1
  70. package/dist/dev-tool.js +70 -106
  71. package/dist/index.cjs +27 -37
  72. package/dist/index.d.ts +2 -3
  73. package/dist/index.d.ts.map +1 -1
  74. package/dist/index.js +3 -4
  75. package/dist/libs/utils.cjs +42 -57
  76. package/dist/libs/utils.d.ts +1 -1
  77. package/dist/libs/utils.js +3 -5
  78. package/dist/router/router.cjs +145 -265
  79. package/dist/router/router.d.ts +3 -5
  80. package/dist/router/router.d.ts.map +1 -1
  81. package/dist/router/router.js +119 -256
  82. package/dist/styles/theme.css +42 -0
  83. package/package.json +3 -3
  84. package/.turbo/turbo-build.log +0 -56
  85. package/.turbo/turbo-fmt.log +0 -6
  86. package/.turbo/turbo-lint.log +0 -73
  87. package/dist/components/ui/overlay.cjs +0 -69
  88. package/dist/components/ui/overlay.d.ts +0 -7
  89. package/dist/components/ui/overlay.d.ts.map +0 -1
  90. package/dist/components/ui/overlay.js +0 -28
  91. package/rslib.config.ts +0 -28
  92. package/src/components/error-state.tsx +0 -44
  93. package/src/components/header.tsx +0 -28
  94. package/src/components/ui/accordion.tsx +0 -64
  95. package/src/components/ui/alert.tsx +0 -59
  96. package/src/components/ui/button.tsx +0 -56
  97. package/src/components/ui/card.tsx +0 -81
  98. package/src/components/ui/expandable-tabs.tsx +0 -174
  99. package/src/components/ui/overlay.tsx +0 -21
  100. package/src/components/ui/scroll-area.tsx +0 -52
  101. package/src/components/ui/switch.tsx +0 -28
  102. package/src/components/ui/tooltip.tsx +0 -32
  103. package/src/components/wrapper.tsx +0 -103
  104. package/src/dev-tool.tsx +0 -117
  105. package/src/index.ts +0 -3
  106. package/src/libs/utils.ts +0 -6
  107. package/src/router/router.tsx +0 -164
@@ -1,69 +0,0 @@
1
- 'use strict';
2
- var __webpack_require__ = {};
3
- (() => {
4
- __webpack_require__.d = function (exports1, definition) {
5
- for (var key in definition)
6
- if (
7
- __webpack_require__.o(definition, key) &&
8
- !__webpack_require__.o(exports1, key)
9
- )
10
- Object.defineProperty(exports1, key, {
11
- enumerable: true,
12
- get: definition[key],
13
- });
14
- };
15
- })();
16
- (() => {
17
- __webpack_require__.o = function (obj, prop) {
18
- return Object.prototype.hasOwnProperty.call(obj, prop);
19
- };
20
- })();
21
- (() => {
22
- __webpack_require__.r = function (exports1) {
23
- if ('undefined' != typeof Symbol && Symbol.toStringTag)
24
- Object.defineProperty(exports1, Symbol.toStringTag, {
25
- value: 'Module',
26
- });
27
- Object.defineProperty(exports1, '__esModule', {
28
- value: true,
29
- });
30
- };
31
- })();
32
- var __webpack_exports__ = {};
33
- __webpack_require__.r(__webpack_exports__);
34
- __webpack_require__.d(__webpack_exports__, {
35
- Overlay: () => Overlay,
36
- });
37
- const jsx_runtime_namespaceObject = require('react/jsx-runtime');
38
- const react_namespaceObject = require('motion/react');
39
- const Overlay = ({ show }) =>
40
- /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(
41
- react_namespaceObject.AnimatePresence,
42
- {
43
- children:
44
- show &&
45
- /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(
46
- react_namespaceObject.motion.div,
47
- {
48
- className:
49
- 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 flex flex-col items-center justify-center overflow-y-auto bg-overlay p-4 backdrop-blur-[10px] data-[state=closed]:animate-out data-[state=open]:animate-in',
50
- initial: {
51
- opacity: 0,
52
- },
53
- animate: {
54
- opacity: 1,
55
- },
56
- exit: {
57
- opacity: 0,
58
- },
59
- }
60
- ),
61
- }
62
- );
63
- var __webpack_export_target__ = exports;
64
- for (var __webpack_i__ in __webpack_exports__)
65
- __webpack_export_target__[__webpack_i__] = __webpack_exports__[__webpack_i__];
66
- if (__webpack_exports__.__esModule)
67
- Object.defineProperty(__webpack_export_target__, '__esModule', {
68
- value: true,
69
- });
@@ -1,7 +0,0 @@
1
- import type { FC } from 'react';
2
- interface OverlayProps {
3
- show: boolean;
4
- }
5
- export declare const Overlay: FC<OverlayProps>;
6
- export {};
7
- //# sourceMappingURL=overlay.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../../../src/components/ui/overlay.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAEhC,UAAU,YAAY;IACrB,IAAI,EAAE,OAAO,CAAC;CACd;AAED,eAAO,MAAM,OAAO,EAAE,EAAE,CAAC,YAAY,CAapC,CAAC"}
@@ -1,28 +0,0 @@
1
- import * as __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__ from 'react/jsx-runtime';
2
- import * as __WEBPACK_EXTERNAL_MODULE_motion_react_9decfa63__ from 'motion/react';
3
- const Overlay = ({ show }) =>
4
- /*#__PURE__*/ (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)(
5
- __WEBPACK_EXTERNAL_MODULE_motion_react_9decfa63__.AnimatePresence,
6
- {
7
- children:
8
- show &&
9
- /*#__PURE__*/ (0,
10
- __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)(
11
- __WEBPACK_EXTERNAL_MODULE_motion_react_9decfa63__.motion.div,
12
- {
13
- className:
14
- 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 flex flex-col items-center justify-center overflow-y-auto bg-overlay p-4 backdrop-blur-[10px] data-[state=closed]:animate-out data-[state=open]:animate-in',
15
- initial: {
16
- opacity: 0,
17
- },
18
- animate: {
19
- opacity: 1,
20
- },
21
- exit: {
22
- opacity: 0,
23
- },
24
- }
25
- ),
26
- }
27
- );
28
- export { Overlay };
package/rslib.config.ts DELETED
@@ -1,28 +0,0 @@
1
- import { pluginReact } from '@rsbuild/plugin-react';
2
- import { defineConfig } from '@rslib/core';
3
-
4
- export default defineConfig({
5
- source: {
6
- entry: {
7
- index: ['./src/**'],
8
- },
9
- },
10
- lib: [
11
- {
12
- bundle: false,
13
- dts: true,
14
- format: 'esm',
15
- },
16
- {
17
- bundle: false,
18
- dts: true,
19
- format: 'cjs',
20
- },
21
- ],
22
- output: {
23
- target: 'web',
24
-
25
- cleanDistPath: true,
26
- },
27
- plugins: [pluginReact()],
28
- });
@@ -1,44 +0,0 @@
1
- import { AlertCircle } from 'lucide-react';
2
- import { motion } from 'motion/react';
3
- import { Alert, AlertDescription, AlertTitle } from './ui/alert';
4
-
5
- export function ErrorState({
6
- namespace,
7
- }: {
8
- namespace: string;
9
- }) {
10
- return (
11
- <motion.div
12
- className="space-y-4 rounded-lg text-center text-base shadow-lg "
13
- initial={{ opacity: 0 }}
14
- animate={{ opacity: 1 }}
15
- exit={{ opacity: 0 }}
16
- >
17
- <Alert variant="destructive" className="max-w-2xl rounded-t-none">
18
- <AlertCircle className="h-4 w-4" />
19
- <AlertTitle className="font-semibold text-lg">
20
- SDK Initialization Failed
21
- </AlertTitle>
22
-
23
- <AlertDescription className="-ml-7 mt-2">
24
- <p className="mb-2">
25
- The c15t SDK could not be found in the global scope. This usually
26
- means either:
27
- </p>
28
- <ul className="list-disc space-y-1 pl-6">
29
- <li>The namespace has been changed from its default value</li>
30
- <li>The SDK initialization failed</li>
31
- </ul>
32
- {namespace && (
33
- <p className="mt-3 text-sm">
34
- Current namespace:{' '}
35
- <code className="rounded bg-red-100/10 px-1 py-0.5">
36
- {namespace}
37
- </code>
38
- </p>
39
- )}
40
- </AlertDescription>
41
- </Alert>
42
- </motion.div>
43
- );
44
- }
@@ -1,28 +0,0 @@
1
- import { Shield, X } from 'lucide-react';
2
-
3
- import { Button } from '../components/ui/button';
4
-
5
- interface HeaderProps {
6
- onClose: () => void;
7
- }
8
-
9
- export function Header({ onClose }: HeaderProps) {
10
- return (
11
- <>
12
- <div className="flex items-center justify-between border-b p-4">
13
- <div className="flex items-center gap-2">
14
- <Shield className="h-4 w-4" />
15
- <span className="font-medium text-sm">c15t.com Dev Tool</span>
16
- </div>
17
- <Button
18
- variant="ghost"
19
- size="icon"
20
- className="h-8 w-8"
21
- onClick={onClose}
22
- >
23
- <X className="h-4 w-4" />
24
- </Button>
25
- </div>
26
- </>
27
- );
28
- }
@@ -1,64 +0,0 @@
1
- 'use client';
2
-
3
- import * as AccordionPrimitive from '@radix-ui/react-accordion';
4
- import { ChevronDown } from 'lucide-react';
5
-
6
- import {
7
- type ComponentPropsWithoutRef,
8
- type ComponentRef,
9
- forwardRef,
10
- } from 'react';
11
- import { cn } from '../../libs/utils';
12
-
13
- const Accordion = AccordionPrimitive.Root;
14
-
15
- const AccordionItem = forwardRef<
16
- ComponentRef<typeof AccordionPrimitive.Item>,
17
- ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
18
- >(({ className, ...props }, ref) => (
19
- <AccordionPrimitive.Item
20
- ref={ref}
21
- className={cn('border-b', className)}
22
- {...props}
23
- />
24
- ));
25
- AccordionItem.displayName = 'AccordionItem';
26
-
27
- const AccordionTrigger = forwardRef<
28
- ComponentRef<typeof AccordionPrimitive.Trigger>,
29
- ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
30
- >(({ className, children, ...props }, ref) => (
31
- <AccordionPrimitive.Header className="flex">
32
- <AccordionPrimitive.Trigger
33
- ref={ref}
34
- className={cn(
35
- 'flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180',
36
- className
37
- )}
38
- {...props}
39
- >
40
- {children}
41
- <ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" />
42
- </AccordionPrimitive.Trigger>
43
- </AccordionPrimitive.Header>
44
- ));
45
- AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;
46
-
47
- const AccordionContent = forwardRef<
48
- ComponentRef<typeof AccordionPrimitive.Content>,
49
- ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
50
- >(({ className, children, ...props }, ref) => (
51
- <AccordionPrimitive.Content
52
- ref={ref}
53
- className={cn(
54
- 'overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down',
55
- className
56
- )}
57
- {...props}
58
- >
59
- <div className="pt-0 pb-4">{children}</div>
60
- </AccordionPrimitive.Content>
61
- ));
62
- AccordionContent.displayName = AccordionPrimitive.Content.displayName;
63
-
64
- export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };
@@ -1,59 +0,0 @@
1
- import { type VariantProps, cva } from 'class-variance-authority';
2
-
3
- import { type HTMLAttributes, forwardRef } from 'react';
4
- import { cn } from '../../libs/utils';
5
-
6
- const alertVariants = cva(
7
- 'relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:top-4 [&>svg]:left-4 [&>svg]:text-foreground [&>svg~*]:pl-7',
8
- {
9
- variants: {
10
- variant: {
11
- default: 'bg-background text-foreground',
12
- destructive:
13
- 'border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive',
14
- },
15
- },
16
- defaultVariants: {
17
- variant: 'default',
18
- },
19
- }
20
- );
21
-
22
- const Alert = forwardRef<
23
- HTMLDivElement,
24
- HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>
25
- >(({ className, variant, ...props }, ref) => (
26
- <div
27
- ref={ref}
28
- role="alert"
29
- className={cn(alertVariants({ variant }), className)}
30
- {...props}
31
- />
32
- ));
33
- Alert.displayName = 'Alert';
34
-
35
- const AlertTitle = forwardRef<
36
- HTMLParagraphElement,
37
- HTMLAttributes<HTMLHeadingElement>
38
- >(({ className, ...props }, ref) => (
39
- <h5
40
- ref={ref}
41
- className={cn('mb-1 font-medium leading-none tracking-tight', className)}
42
- {...props}
43
- />
44
- ));
45
- AlertTitle.displayName = 'AlertTitle';
46
-
47
- const AlertDescription = forwardRef<
48
- HTMLParagraphElement,
49
- HTMLAttributes<HTMLParagraphElement>
50
- >(({ className, ...props }, ref) => (
51
- <div
52
- ref={ref}
53
- className={cn('text-sm [&_p]:leading-relaxed', className)}
54
- {...props}
55
- />
56
- ));
57
- AlertDescription.displayName = 'AlertDescription';
58
-
59
- export { Alert, AlertTitle, AlertDescription };
@@ -1,56 +0,0 @@
1
- import { Slot } from '@radix-ui/react-slot';
2
- import { type VariantProps, cva } from 'class-variance-authority';
3
-
4
- import { type ButtonHTMLAttributes, forwardRef } from 'react';
5
- import { cn } from '../../libs/utils';
6
-
7
- const buttonVariants = cva(
8
- 'inline-flex items-center justify-center rounded-md font-medium text-sm ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
9
- {
10
- variants: {
11
- variant: {
12
- default: 'bg-primary text-primary-foreground hover:bg-primary/90',
13
- destructive:
14
- 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
15
- outline:
16
- 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
17
- secondary:
18
- 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
19
- ghost: 'hover:bg-accent hover:text-accent-foreground',
20
- link: 'text-primary underline-offset-4 hover:underline',
21
- },
22
- size: {
23
- default: 'h-10 px-4 py-2',
24
- sm: 'h-9 rounded-md px-3',
25
- lg: 'h-11 rounded-md px-8',
26
- icon: 'h-10 w-10',
27
- },
28
- },
29
- defaultVariants: {
30
- variant: 'default',
31
- size: 'default',
32
- },
33
- }
34
- );
35
-
36
- export interface ButtonProps
37
- extends ButtonHTMLAttributes<HTMLButtonElement>,
38
- VariantProps<typeof buttonVariants> {
39
- asChild?: boolean;
40
- }
41
-
42
- const Button = forwardRef<HTMLButtonElement, ButtonProps>(
43
- ({ className, variant, size, asChild = false, ...props }, ref) => {
44
- const Comp = asChild ? Slot : 'button';
45
- return (
46
- <Comp
47
- className={cn(buttonVariants({ variant, size, className }))}
48
- ref={ref}
49
- {...props}
50
- />
51
- );
52
- }
53
- );
54
- Button.displayName = 'Button';
55
-
56
- export { Button, buttonVariants };
@@ -1,81 +0,0 @@
1
- import { type HTMLAttributes, forwardRef } from 'react';
2
- import { cn } from '../../libs/utils';
3
-
4
- const Card = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
5
- ({ className, ...props }, ref) => (
6
- <div
7
- ref={ref}
8
- className={cn(
9
- 'rounded-lg border bg-card text-card-foreground shadow-sm',
10
- className
11
- )}
12
- {...props}
13
- />
14
- )
15
- );
16
- Card.displayName = 'Card';
17
-
18
- const CardHeader = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
19
- ({ className, ...props }, ref) => (
20
- <div
21
- ref={ref}
22
- className={cn('flex flex-col space-y-1.5 p-6', className)}
23
- {...props}
24
- />
25
- )
26
- );
27
- CardHeader.displayName = 'CardHeader';
28
-
29
- const CardTitle = forwardRef<
30
- HTMLParagraphElement,
31
- HTMLAttributes<HTMLHeadingElement>
32
- >(({ className, ...props }, ref) => (
33
- <h3
34
- ref={ref}
35
- className={cn(
36
- 'font-semibold text-2xl leading-none tracking-tight',
37
- className
38
- )}
39
- {...props}
40
- />
41
- ));
42
- CardTitle.displayName = 'CardTitle';
43
-
44
- const CardDescription = forwardRef<
45
- HTMLParagraphElement,
46
- HTMLAttributes<HTMLParagraphElement>
47
- >(({ className, ...props }, ref) => (
48
- <p
49
- ref={ref}
50
- className={cn('text-muted-foreground text-sm', className)}
51
- {...props}
52
- />
53
- ));
54
- CardDescription.displayName = 'CardDescription';
55
-
56
- const CardContent = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
57
- ({ className, ...props }, ref) => (
58
- <div ref={ref} className={cn('p-6 pt-0', className)} {...props} />
59
- )
60
- );
61
- CardContent.displayName = 'CardContent';
62
-
63
- const CardFooter = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
64
- ({ className, ...props }, ref) => (
65
- <div
66
- ref={ref}
67
- className={cn('flex items-center p-6 pt-0', className)}
68
- {...props}
69
- />
70
- )
71
- );
72
- CardFooter.displayName = 'CardFooter';
73
-
74
- export {
75
- Card,
76
- CardHeader,
77
- CardFooter,
78
- CardTitle,
79
- CardDescription,
80
- CardContent,
81
- };
@@ -1,174 +0,0 @@
1
- 'use client';
2
-
3
- import type { LucideIcon } from 'lucide-react';
4
- import { AnimatePresence, motion } from 'motion/react';
5
-
6
- import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
7
- import { useOnClickOutside } from 'usehooks-ts';
8
- import { cn } from '../../libs/utils';
9
-
10
- interface Tab {
11
- title: string;
12
- icon: LucideIcon;
13
- type?: never;
14
- }
15
-
16
- interface Separator {
17
- type: 'separator';
18
- title?: never;
19
- icon?: never;
20
- }
21
-
22
- type TabItem = Tab | Separator;
23
-
24
- interface ExpandableTabsProps {
25
- tabs: TabItem[];
26
- className?: string;
27
- activeColor?: string;
28
- onChange?: (index: number | null) => void;
29
- }
30
-
31
- const buttonVariants = {
32
- initial: {
33
- gap: 0,
34
- paddingLeft: '.5rem',
35
- paddingRight: '.5rem',
36
- },
37
- animate: (isSelected: boolean) => ({
38
- gap: isSelected ? '.5rem' : 0,
39
- paddingLeft: isSelected ? '1rem' : '.5rem',
40
- paddingRight: isSelected ? '1rem' : '.5rem',
41
- }),
42
- };
43
-
44
- const spanVariants = {
45
- initial: { width: 0, opacity: 0 },
46
- animate: { width: 'auto', opacity: 1 },
47
- exit: { width: 0, opacity: 0 },
48
- };
49
-
50
- const transition = { delay: 0.1, type: 'spring', bounce: 0, duration: 0.6 };
51
-
52
- const Separator = memo(() => (
53
- <div className="mx-1 h-[24px] w-[1.2px] bg-border" aria-hidden="true" />
54
- ));
55
- Separator.displayName = 'Separator';
56
-
57
- const TabButton = memo(
58
- ({
59
- tab,
60
- index,
61
- isSelected,
62
- activeColor,
63
- onClick,
64
- }: {
65
- tab: Tab;
66
- index: number;
67
- isSelected: boolean;
68
- activeColor: string;
69
- onClick: (index: number) => void;
70
- }) => {
71
- const Icon = tab.icon;
72
-
73
- return (
74
- <motion.button
75
- variants={buttonVariants}
76
- initial={false}
77
- animate="animate"
78
- custom={isSelected}
79
- onClick={() => onClick(index)}
80
- transition={transition}
81
- className={cn(
82
- 'relative flex flex-grow items-center justify-center rounded-xl px-4 py-2 font-medium text-sm transition-colors duration-300',
83
- isSelected
84
- ? cn('bg-muted', activeColor)
85
- : 'text-muted-foreground hover:bg-muted hover:text-foreground'
86
- )}
87
- >
88
- <Icon size={20} />
89
- <AnimatePresence initial={false}>
90
- {isSelected && (
91
- <motion.span
92
- variants={spanVariants}
93
- initial="initial"
94
- animate="animate"
95
- exit="exit"
96
- transition={transition}
97
- className="overflow-hidden whitespace-nowrap"
98
- >
99
- {tab.title}
100
- </motion.span>
101
- )}
102
- </AnimatePresence>
103
- </motion.button>
104
- );
105
- }
106
- );
107
- TabButton.displayName = 'TabButton';
108
-
109
- export function ExpandableTabs({
110
- tabs,
111
- className,
112
- activeColor = 'text-primary',
113
- onChange,
114
- }: ExpandableTabsProps) {
115
- const [selected, setSelected] = useState<number | null>(0);
116
- const outsideClickRef = useRef<HTMLDivElement>(null);
117
-
118
- const handleInitialChange = useCallback(() => {
119
- onChange?.(0);
120
- }, [onChange]);
121
-
122
- useEffect(() => {
123
- handleInitialChange();
124
- }, [handleInitialChange]);
125
-
126
- const handleOutsideClick = useCallback(() => {
127
- setSelected(null);
128
- onChange?.(null);
129
- }, [onChange]);
130
-
131
- //@ts-expect-error
132
- useOnClickOutside(outsideClickRef, handleOutsideClick);
133
-
134
- const handleSelect = useCallback(
135
- (index: number) => {
136
- setSelected(index);
137
- onChange?.(index);
138
- },
139
- [onChange]
140
- );
141
-
142
- const containerClassName = useMemo(
143
- () =>
144
- cn(
145
- 'flex flex-wrap items-center gap-2 rounded-2xl border bg-background p-1 shadow-sm',
146
- className
147
- ),
148
- [className]
149
- );
150
-
151
- return (
152
- <div ref={outsideClickRef} className={containerClassName}>
153
- {tabs.map((tab, index) =>
154
- tab.type === 'separator' ? (
155
- <Separator
156
- key={`separator-${
157
- // biome-ignore lint/suspicious/noArrayIndexKey: <explanation>
158
- index
159
- }`}
160
- />
161
- ) : (
162
- <TabButton
163
- key={`${tab.title}-${index}`}
164
- tab={tab}
165
- index={index}
166
- isSelected={selected === index}
167
- activeColor={activeColor}
168
- onClick={handleSelect}
169
- />
170
- )
171
- )}
172
- </div>
173
- );
174
- }
@@ -1,21 +0,0 @@
1
- import { AnimatePresence, motion } from 'motion/react';
2
- import type { FC } from 'react';
3
-
4
- interface OverlayProps {
5
- show: boolean;
6
- }
7
-
8
- export const Overlay: FC<OverlayProps> = ({ show }) => {
9
- return (
10
- <AnimatePresence>
11
- {show && (
12
- <motion.div
13
- className="data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 flex flex-col items-center justify-center overflow-y-auto bg-overlay p-4 backdrop-blur-[10px] data-[state=closed]:animate-out data-[state=open]:animate-in"
14
- initial={{ opacity: 0 }}
15
- animate={{ opacity: 1 }}
16
- exit={{ opacity: 0 }}
17
- />
18
- )}
19
- </AnimatePresence>
20
- );
21
- };