@alquimia-ai/ui 1.2.0 → 1.2.1

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 (104) hide show
  1. package/dist/components/hooks/index.js +1 -1
  2. package/dist/components/hooks/index.js.map +1 -1
  3. package/dist/components/hooks/index.mjs +1 -1
  4. package/dist/components/hooks/index.mjs.map +1 -1
  5. package/dist/components/molecules/index.d.mts +15 -2
  6. package/dist/components/molecules/index.d.ts +15 -2
  7. package/dist/components/molecules/index.js +837 -725
  8. package/dist/components/molecules/index.js.map +1 -1
  9. package/dist/components/molecules/index.mjs +819 -707
  10. package/dist/components/molecules/index.mjs.map +1 -1
  11. package/dist/components/organisms/index.js +260 -149
  12. package/dist/components/organisms/index.js.map +1 -1
  13. package/dist/components/organisms/index.mjs +258 -147
  14. package/dist/components/organisms/index.mjs.map +1 -1
  15. package/dist/index.d.mts +2 -2
  16. package/dist/index.d.ts +2 -2
  17. package/dist/index.js +265 -153
  18. package/dist/index.js.map +1 -1
  19. package/dist/index.mjs +263 -151
  20. package/dist/index.mjs.map +1 -1
  21. package/package.json +52 -32
  22. package/src/components/atoms/index.ts +32 -0
  23. package/src/components/atoms/ui/alert.tsx +59 -0
  24. package/src/components/atoms/ui/aspect-ratio.tsx +7 -0
  25. package/src/components/atoms/ui/avatar.tsx +50 -0
  26. package/src/components/atoms/ui/badge.tsx +36 -0
  27. package/src/components/atoms/ui/breadcrumb.tsx +120 -0
  28. package/src/components/atoms/ui/button.tsx +56 -0
  29. package/src/components/atoms/ui/card.tsx +87 -0
  30. package/src/components/atoms/ui/checkbox.tsx +31 -0
  31. package/src/components/atoms/ui/command.tsx +155 -0
  32. package/src/components/atoms/ui/dialog.tsx +125 -0
  33. package/src/components/atoms/ui/drawer.tsx +119 -0
  34. package/src/components/atoms/ui/input.tsx +26 -0
  35. package/src/components/atoms/ui/label.tsx +26 -0
  36. package/src/components/atoms/ui/loader.tsx +52 -0
  37. package/src/components/atoms/ui/popover.tsx +31 -0
  38. package/src/components/atoms/ui/rich-text.tsx +19 -0
  39. package/src/components/atoms/ui/scroll-area.tsx +48 -0
  40. package/src/components/atoms/ui/select.tsx +160 -0
  41. package/src/components/atoms/ui/skeleton.tsx +15 -0
  42. package/src/components/atoms/ui/slider.tsx +29 -0
  43. package/src/components/atoms/ui/switch.tsx +30 -0
  44. package/src/components/atoms/ui/table.tsx +118 -0
  45. package/src/components/atoms/ui/tabs.tsx +56 -0
  46. package/src/components/atoms/ui/text-area/index.tsx +24 -0
  47. package/src/components/atoms/ui/textarea.tsx +25 -0
  48. package/src/components/atoms/ui/think-indicator.tsx +103 -0
  49. package/src/components/atoms/ui/toast.tsx +129 -0
  50. package/src/components/atoms/ui/toaster.tsx +38 -0
  51. package/src/components/atoms/ui/toggle.tsx +45 -0
  52. package/src/components/atoms/ui/typography/index.tsx +30 -0
  53. package/src/components/hooks/index.ts +4 -0
  54. package/src/components/hooks/use-document.tsx +44 -0
  55. package/src/components/hooks/use-resize-observer.ts +28 -0
  56. package/src/components/hooks/use-text-streaming.ts +63 -0
  57. package/src/components/hooks/use-toast.ts +194 -0
  58. package/src/components/index.ts +1 -0
  59. package/src/components/molecules/alert-dialog.tsx +141 -0
  60. package/src/components/molecules/assistant-button.tsx +148 -0
  61. package/src/components/molecules/call-out.tsx +163 -0
  62. package/src/components/molecules/carousel.tsx +262 -0
  63. package/src/components/molecules/documents/document-selector.tsx +79 -0
  64. package/src/components/molecules/documents/document-viewer.tsx +85 -0
  65. package/src/components/molecules/documents/index.ts +2 -0
  66. package/src/components/molecules/index.ts +11 -0
  67. package/src/components/molecules/navigation-menu.tsx +128 -0
  68. package/src/components/molecules/page-container.tsx +17 -0
  69. package/src/components/molecules/rating-comment.tsx +93 -0
  70. package/src/components/molecules/rating-stars.tsx +136 -0
  71. package/src/components/molecules/rating-thumbs.tsx +90 -0
  72. package/src/components/molecules/sidebar.tsx +107 -0
  73. package/src/components/molecules/sonner.tsx +30 -0
  74. package/src/components/molecules/viewers/index.ts +2 -0
  75. package/src/components/molecules/viewers/pdf-viewer.tsx +138 -0
  76. package/src/components/molecules/viewers/plain-text-viewer.tsx +40 -0
  77. package/src/components/organisms/assistant.tsx +271 -0
  78. package/src/components/organisms/index.ts +6 -0
  79. package/src/components/organisms/rating-dialog.tsx +104 -0
  80. package/src/components/organisms/speechToText.tsx +92 -0
  81. package/src/components/organisms/whisper.tsx +106 -0
  82. package/src/components/templates/cards/index.ts +2 -0
  83. package/src/components/templates/cards/with-image-heading-description-avatar.tsx +94 -0
  84. package/src/components/templates/cards/with-image-heading-description.tsx +63 -0
  85. package/src/components/templates/hero/index.tsx +39 -0
  86. package/src/components/templates/index.ts +4 -0
  87. package/src/components/templates/messages-window.tsx +15 -0
  88. package/src/components/templates/query-box.tsx +13 -0
  89. package/src/components/ui/input.tsx +25 -0
  90. package/src/components/ui/select.tsx +163 -0
  91. package/src/index.ts +7 -0
  92. package/src/lib/index.ts +1 -0
  93. package/src/lib/utils.ts +34 -0
  94. package/src/styles/call-out.css +153 -0
  95. package/src/styles/drawer.css +28 -0
  96. package/src/styles/globals.css +69 -0
  97. package/src/styles/prose.css +51 -0
  98. package/src/styles/ratings.css +27 -0
  99. package/src/styles/themes/base-alquimia.css +95 -0
  100. package/src/styles/themes/base-nordic.css +83 -0
  101. package/src/styles/themes/base-primary.css +85 -0
  102. package/src/styles/themes/base.css +8 -0
  103. package/src/types/index.ts +1 -0
  104. package/src/types/type.ts +76 -0
@@ -0,0 +1,106 @@
1
+ import { useState, useEffect } from "react";
2
+ import { cn } from "../../lib/utils";
3
+ import {
4
+ AudioLinesIcon,
5
+ PlayCircleIcon,
6
+ LoaderPinwheelIcon,
7
+ } from "lucide-react";
8
+ import { Message } from "ai";
9
+ import { parseTextToSpeech } from "../../lib/utils";
10
+
11
+ interface WhisperProps extends React.HTMLAttributes<HTMLDivElement> {
12
+ message: Message;
13
+ isMessageStreaming: boolean;
14
+ textToSpeech: (content: string) => Promise<Blob>;
15
+ }
16
+
17
+ function Whisper({
18
+ className,
19
+ message,
20
+ isMessageStreaming,
21
+ textToSpeech,
22
+ }: WhisperProps) {
23
+ const [audioUrl, setAudioUrl] = useState<HTMLAudioElement | null>(null);
24
+ const [isPlaying, setIsPlaying] = useState<boolean>(false);
25
+ const [isLoading, setIsLoading] = useState<boolean>(false);
26
+
27
+ const content = message.content;
28
+
29
+ useEffect(() => {
30
+ if (audioUrl) {
31
+ const handlePlaying = () => setIsPlaying(true);
32
+ const handlePause = () => setIsPlaying(false);
33
+ const handleEnded = () => setIsPlaying(false);
34
+
35
+ audioUrl.addEventListener("playing", handlePlaying);
36
+ audioUrl.addEventListener("pause", handlePause);
37
+ audioUrl.addEventListener("ended", handleEnded);
38
+
39
+ return () => {
40
+ audioUrl.removeEventListener("playing", handlePlaying);
41
+ audioUrl.removeEventListener("pause", handlePause);
42
+ audioUrl.removeEventListener("ended", handleEnded);
43
+ };
44
+ }
45
+ }, [audioUrl]);
46
+
47
+ const resetAudio = () => {
48
+ audioUrl && (audioUrl.currentTime = 0);
49
+ audioUrl?.pause();
50
+ };
51
+
52
+ const handleAudioPlay = () => (isPlaying ? resetAudio() : audioUrl?.play());
53
+
54
+ const handleTextToSpeech = async (content: string) => {
55
+ if (!audioUrl) {
56
+ setIsLoading(true);
57
+ const filteredContent = parseTextToSpeech(content);
58
+ const audioFile = await textToSpeech(filteredContent);
59
+
60
+ if (audioFile) {
61
+ const url = URL.createObjectURL(audioFile);
62
+ const audio = new Audio(url);
63
+
64
+ setIsLoading(false);
65
+ audio.play();
66
+ setAudioUrl(audio);
67
+ }
68
+ } else {
69
+ setIsLoading(false);
70
+ handleAudioPlay();
71
+ }
72
+ };
73
+
74
+ return (
75
+ <div className={cn(className)}>
76
+ {isMessageStreaming && <div className="p-2 w-[24px] h-[24px]"></div>}
77
+ {!isMessageStreaming && (
78
+ <div onClick={() => handleTextToSpeech(content)}>
79
+ {isPlaying && (
80
+ <button className="p-2 items-center justify-center">
81
+ <AudioLinesIcon size={20} />
82
+ </button>
83
+ )}
84
+
85
+ {isLoading && (
86
+ <button className="p-2 items-center justify-center">
87
+ {" "}
88
+ <LoaderPinwheelIcon size={20} className="circular-animation" />
89
+ </button>
90
+ )}
91
+
92
+ {!isLoading && !isPlaying && (
93
+ <button
94
+ disabled={isLoading}
95
+ className="p-2 items-center justify-center"
96
+ >
97
+ <PlayCircleIcon size={20} />
98
+ </button>
99
+ )}
100
+ </div>
101
+ )}
102
+ </div>
103
+ );
104
+ }
105
+
106
+ export { Whisper };
@@ -0,0 +1,2 @@
1
+ export * from "./with-image-heading-description";
2
+ export * from "./with-image-heading-description-avatar";
@@ -0,0 +1,94 @@
1
+ import { cn } from "../../../lib/utils";
2
+ import {
3
+ Avatar,
4
+ AvatarImage,
5
+ Card,
6
+ CardContent,
7
+ CardHeader,
8
+ CardTitle,
9
+ Typography,
10
+ } from "../../atoms";
11
+
12
+ interface CardWithImageHeadingDescriptionAvatarProps {
13
+ orientation: "vertical" | "horizontal";
14
+ showBorder?: boolean;
15
+ image: React.ReactNode;
16
+ heading: React.ReactNode;
17
+ description: React.ReactNode;
18
+ avatarImage: string;
19
+ userName: string;
20
+ email: string;
21
+ }
22
+
23
+ const AvatarInfo = (props: CardWithImageHeadingDescriptionAvatarProps) => {
24
+ const { userName, email, avatarImage } = props;
25
+ return (
26
+ <div className="flex space-x-2 items-center">
27
+ <Avatar className="w-16 h-16">
28
+ <AvatarImage src={avatarImage} />
29
+ </Avatar>
30
+ <div>
31
+ <Typography typeStyle="small" className="font-semibold">
32
+ {userName}
33
+ </Typography>
34
+ <Typography typeStyle="tiny" className="text-font-weak-color">
35
+ {email}
36
+ </Typography>
37
+ </div>
38
+ </div>
39
+ );
40
+ };
41
+
42
+ const CardWithImageHeadingDescriptionAvatarVertical = (
43
+ props: CardWithImageHeadingDescriptionAvatarProps
44
+ ) => {
45
+ const { showBorder, image, heading, description } = props;
46
+
47
+ return (
48
+ <Card className={cn("w-[360px]", !showBorder && "border-none shadow-none")}>
49
+ {image}
50
+ <CardHeader>
51
+ <CardTitle>{heading}</CardTitle>
52
+ <Typography typeStyle="small" className="text-font-weak-color">
53
+ {description}
54
+ </Typography>
55
+ </CardHeader>
56
+ <CardContent>
57
+ <AvatarInfo {...props} />
58
+ </CardContent>
59
+ </Card>
60
+ );
61
+ };
62
+
63
+ const CardImageWithHeadingAndDescriptionAvatarHorizontal = (
64
+ props: CardWithImageHeadingDescriptionAvatarProps
65
+ ) => {
66
+ const { showBorder, image, heading, description } = props;
67
+ return (
68
+ <Card
69
+ className={cn(
70
+ "lg:w-[600px] w-[360px] lg:flex lg:h-[246px]",
71
+ !showBorder && "border-none shadow-none "
72
+ )}
73
+ >
74
+ {image}
75
+ <div>
76
+ <CardHeader>
77
+ <CardTitle>{heading}</CardTitle>
78
+ <Typography typeStyle="small" className="text-font-weak-color">
79
+ {description}
80
+ </Typography>
81
+ </CardHeader>
82
+ <CardContent>
83
+ <AvatarInfo {...props} />
84
+ </CardContent>
85
+ </div>
86
+ </Card>
87
+ );
88
+ };
89
+
90
+ export {
91
+ CardWithImageHeadingDescriptionAvatarVertical,
92
+ CardImageWithHeadingAndDescriptionAvatarHorizontal,
93
+ type CardWithImageHeadingDescriptionAvatarProps,
94
+ };
@@ -0,0 +1,63 @@
1
+ import { cn } from "../../../lib/utils";
2
+ import {
3
+ Card,
4
+ CardContent,
5
+ CardHeader,
6
+ CardTitle,
7
+ Typography,
8
+ } from "../../atoms";
9
+
10
+ interface CardWithImageHeadingDescriptionProps {
11
+ orientation: "vertical" | "horizontal";
12
+ showBorder?: boolean;
13
+ image: React.ReactNode;
14
+ heading: React.ReactNode;
15
+ description: React.ReactNode;
16
+ }
17
+
18
+ const CardWithImageHeadingDescriptionVertical = (
19
+ props: CardWithImageHeadingDescriptionProps
20
+ ) => {
21
+ const { showBorder, image, heading, description } = props;
22
+ return (
23
+ <Card className={cn("w-[360px]", !showBorder && "border-none shadow-none")}>
24
+ {image}
25
+ <CardHeader>
26
+ <CardTitle>{heading}</CardTitle>
27
+ <Typography typeStyle="small" className="text-font-weak-color">
28
+ {description}
29
+ </Typography>
30
+ </CardHeader>
31
+ <CardContent></CardContent>
32
+ </Card>
33
+ );
34
+ };
35
+
36
+ const CardImageWithHeadingAndDescriptionHorizontal = (
37
+ props: CardWithImageHeadingDescriptionProps
38
+ ) => {
39
+ const { showBorder, image, heading, description } = props;
40
+ return (
41
+ <Card
42
+ className={cn(
43
+ "lg:w-[600px] w-[360px] lg:flex lg:h-[150px]",
44
+ !showBorder && "border-none shadow-none "
45
+ )}
46
+ >
47
+ {image}
48
+ <CardHeader>
49
+ <CardTitle>{heading}</CardTitle>
50
+ <Typography typeStyle="small" className="text-font-weak-color">
51
+ {description}
52
+ </Typography>
53
+ </CardHeader>
54
+ <CardContent></CardContent>
55
+ </Card>
56
+ );
57
+ };
58
+
59
+ export {
60
+ CardWithImageHeadingDescriptionVertical,
61
+ CardImageWithHeadingAndDescriptionHorizontal,
62
+ type CardWithImageHeadingDescriptionProps,
63
+ };
@@ -0,0 +1,39 @@
1
+ import { forwardRef } from "react";
2
+ import { cn } from "../../../lib/utils";
3
+
4
+ export interface HeroProps extends React.HTMLAttributes<HTMLDivElement> {}
5
+
6
+ const Hero = forwardRef<HTMLDivElement, HeroProps>(
7
+ ({ className, children, ...props }, ref) => {
8
+ return (
9
+ <div
10
+ ref={ref}
11
+ className={cn("alq--hero-container", "grid", className)}
12
+ {...props}
13
+ >
14
+ {children}
15
+ </div>
16
+ );
17
+ }
18
+ );
19
+
20
+ export interface HeroContentProps
21
+ extends React.HTMLAttributes<HTMLDivElement> {}
22
+ const HeroContent = forwardRef<HTMLDivElement, HeroContentProps>(
23
+ ({ className, children, ...props }, ref) => {
24
+ return (
25
+ <div
26
+ ref={ref}
27
+ className={cn("alq--hero-container", className)}
28
+ {...props}
29
+ >
30
+ {children}
31
+ </div>
32
+ );
33
+ }
34
+ );
35
+
36
+ Hero.displayName = "Hero";
37
+ HeroContent.displayName = "HeroContent";
38
+
39
+ export { Hero, HeroContent };
@@ -0,0 +1,4 @@
1
+ export * from "./messages-window";
2
+ export * from "./query-box";
3
+ export * from "./hero";
4
+ export * from "./cards";
@@ -0,0 +1,15 @@
1
+ import { forwardRef } from "react";
2
+ import { cn } from "../../lib/utils";
3
+
4
+ interface MessagesWindowProps extends React.HTMLAttributes<HTMLDivElement> {}
5
+
6
+ const MessagesWindow = forwardRef<HTMLDivElement, MessagesWindowProps>(
7
+ ({ className, ...props }, ref) => {
8
+ return (
9
+ <div className={cn(className, "alq--messages--window")} {...props}></div>
10
+ );
11
+ }
12
+ );
13
+
14
+ MessagesWindow.displayName = "MessagesWindow";
15
+ export { MessagesWindow };
@@ -0,0 +1,13 @@
1
+ import { forwardRef } from "react";
2
+ import { cn } from "../../lib/utils";
3
+
4
+ interface QueryBoxProps extends React.HTMLAttributes<HTMLDivElement> {}
5
+
6
+ const QueryBox = forwardRef<HTMLDivElement, QueryBoxProps>(
7
+ ({ className, ...props }, ref) => {
8
+ return <div className={cn(className, "alq--querybox")} {...props}></div>;
9
+ }
10
+ );
11
+
12
+ QueryBox.displayName = "QueryBox";
13
+ export { QueryBox };
@@ -0,0 +1,25 @@
1
+ import * as React from "react";
2
+
3
+ import { cn } from "../../lib/utils";
4
+
5
+ export interface InputProps
6
+ extends React.InputHTMLAttributes<HTMLInputElement> {}
7
+
8
+ const Input = React.forwardRef<HTMLInputElement, InputProps>(
9
+ ({ className, type, ...props }, ref) => {
10
+ return (
11
+ <input
12
+ type={type}
13
+ className={cn(
14
+ "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
15
+ className
16
+ )}
17
+ ref={ref}
18
+ {...props}
19
+ />
20
+ );
21
+ }
22
+ );
23
+ Input.displayName = "Input";
24
+
25
+ export { Input };
@@ -0,0 +1,163 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import * as SelectPrimitive from "@radix-ui/react-select"
5
+ import { Check, ChevronDown, ChevronUp } from "lucide-react"
6
+
7
+ import { cn } from "../../lib/utils"
8
+
9
+ const Select = SelectPrimitive.Root
10
+
11
+ const SelectGroup = SelectPrimitive.Group
12
+
13
+ const SelectValue = SelectPrimitive.Value
14
+
15
+ const SelectTrigger = React.forwardRef<
16
+ React.ElementRef<typeof SelectPrimitive.Trigger>,
17
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
18
+ >(({ className, children, ...props }, ref) => (
19
+ <SelectPrimitive.Trigger
20
+ ref={ref}
21
+ className={cn(
22
+ "flex h-10 w-full items-center justify-between rounded-md border border-input bg-background text-foreground px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
23
+ className,
24
+ "alq--select-trigger"
25
+ )}
26
+ {...props}
27
+ >
28
+ {children}
29
+ <SelectPrimitive.Icon asChild>
30
+ <ChevronDown className="h-4 w-4 opacity-50" />
31
+ </SelectPrimitive.Icon>
32
+ </SelectPrimitive.Trigger>
33
+ ))
34
+ SelectTrigger.displayName = SelectPrimitive.Trigger.displayName
35
+
36
+ const SelectScrollUpButton = React.forwardRef<
37
+ React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
38
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
39
+ >(({ className, ...props }, ref) => (
40
+ <SelectPrimitive.ScrollUpButton
41
+ ref={ref}
42
+ className={cn(
43
+ "flex cursor-default items-center justify-center py-1",
44
+ className
45
+ )}
46
+ {...props}
47
+ >
48
+ <ChevronUp className="h-4 w-4" />
49
+ </SelectPrimitive.ScrollUpButton>
50
+ ))
51
+ SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName
52
+
53
+ const SelectScrollDownButton = React.forwardRef<
54
+ React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
55
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
56
+ >(({ className, ...props }, ref) => (
57
+ <SelectPrimitive.ScrollDownButton
58
+ ref={ref}
59
+ className={cn(
60
+ "flex cursor-default items-center justify-center py-1",
61
+ className
62
+ )}
63
+ {...props}
64
+ >
65
+ <ChevronDown className="h-4 w-4" />
66
+ </SelectPrimitive.ScrollDownButton>
67
+ ))
68
+ SelectScrollDownButton.displayName =
69
+ SelectPrimitive.ScrollDownButton.displayName
70
+
71
+ const SelectContent = React.forwardRef<
72
+ React.ElementRef<typeof SelectPrimitive.Content>,
73
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
74
+ >(({ className, children, position = "popper", ...props }, ref) => (
75
+ <SelectPrimitive.Portal>
76
+ <SelectPrimitive.Content
77
+ ref={ref}
78
+ className={cn(
79
+ "relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-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",
80
+ position === "popper" &&
81
+ "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
82
+ className,
83
+ "alq--select-content"
84
+ )}
85
+ position={position}
86
+ {...props}
87
+ >
88
+ <SelectScrollUpButton />
89
+ <SelectPrimitive.Viewport
90
+ className={cn(
91
+ "p-1 bg-popover",
92
+ position === "popper" &&
93
+ "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
94
+ )}
95
+ >
96
+ {children}
97
+ </SelectPrimitive.Viewport>
98
+ <SelectScrollDownButton />
99
+ </SelectPrimitive.Content>
100
+ </SelectPrimitive.Portal>
101
+ ))
102
+ SelectContent.displayName = SelectPrimitive.Content.displayName
103
+
104
+ const SelectLabel = React.forwardRef<
105
+ React.ElementRef<typeof SelectPrimitive.Label>,
106
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
107
+ >(({ className, ...props }, ref) => (
108
+ <SelectPrimitive.Label
109
+ ref={ref}
110
+ className={cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className)}
111
+ {...props}
112
+ />
113
+ ))
114
+ SelectLabel.displayName = SelectPrimitive.Label.displayName
115
+
116
+ const SelectItem = React.forwardRef<
117
+ React.ElementRef<typeof SelectPrimitive.Item>,
118
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
119
+ >(({ className, children, ...props }, ref) => (
120
+ <SelectPrimitive.Item
121
+ ref={ref}
122
+ className={cn(
123
+ "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 text-popover-foreground",
124
+ className,
125
+ "alq--select-item"
126
+ )}
127
+ {...props}
128
+ >
129
+ <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
130
+ <SelectPrimitive.ItemIndicator>
131
+ <Check className="h-4 w-4" />
132
+ </SelectPrimitive.ItemIndicator>
133
+ </span>
134
+
135
+ <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
136
+ </SelectPrimitive.Item>
137
+ ))
138
+ SelectItem.displayName = SelectPrimitive.Item.displayName
139
+
140
+ const SelectSeparator = React.forwardRef<
141
+ React.ElementRef<typeof SelectPrimitive.Separator>,
142
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
143
+ >(({ className, ...props }, ref) => (
144
+ <SelectPrimitive.Separator
145
+ ref={ref}
146
+ className={cn("-mx-1 my-1 h-px bg-muted", className)}
147
+ {...props}
148
+ />
149
+ ))
150
+ SelectSeparator.displayName = SelectPrimitive.Separator.displayName
151
+
152
+ export {
153
+ Select,
154
+ SelectGroup,
155
+ SelectValue,
156
+ SelectTrigger,
157
+ SelectContent,
158
+ SelectLabel,
159
+ SelectItem,
160
+ SelectSeparator,
161
+ SelectScrollUpButton,
162
+ SelectScrollDownButton,
163
+ }
package/src/index.ts ADDED
@@ -0,0 +1,7 @@
1
+ export * from "./components/atoms";
2
+ export * from "./components/templates";
3
+ export * from "./components/organisms";
4
+ export * from "./components/molecules";
5
+ export * from "./components/hooks";
6
+ export * from "./lib/utils";
7
+ export * from "./types";
@@ -0,0 +1 @@
1
+ export * from "./utils";
@@ -0,0 +1,34 @@
1
+ import { clsx, type ClassValue } from "clsx";
2
+ import { twMerge } from "tailwind-merge";
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs));
6
+ }
7
+
8
+ export function parseTextToSpeech(content: string) {
9
+ return content.replace(/[^\p{L}\p{N}\s.,:]/gu, '');
10
+ }
11
+
12
+
13
+ export function blobToBase64(blob: Blob): Promise<string> {
14
+ return new Promise((resolve, reject) => {
15
+ const reader = new FileReader();
16
+ reader.onloadend = () => resolve(reader.result as string);
17
+ reader.onerror = reject;
18
+ reader.readAsDataURL(blob);
19
+ });
20
+ };
21
+
22
+ export const truncateString = (str: string, maxLength: number): string => {
23
+ if (str.length <= maxLength) {
24
+ return str;
25
+ }
26
+ return str.slice(0, maxLength) + "...";
27
+ };
28
+
29
+ export function getCookies(name: string) {
30
+ if (typeof document === 'undefined') return undefined;
31
+ const value = `; ${document.cookie}`;
32
+ const parts = value.split(`; ${name}=`);
33
+ if (parts.length === 2) return parts.pop()?.split(";").shift();
34
+ }