102 | >(({ className, ...props }, ref) => (
103 |
108 | ))
109 | DialogDescription.displayName = DialogPrimitive.Description.displayName
110 |
111 | export {
112 | Dialog,
113 | DialogPortal,
114 | DialogOverlay,
115 | DialogClose,
116 | DialogTrigger,
117 | DialogContent,
118 | DialogHeader,
119 | DialogFooter,
120 | DialogTitle,
121 | DialogDescription,
122 | }
123 |
--------------------------------------------------------------------------------
/src/features/brick-edit/editors/title.tsx:
--------------------------------------------------------------------------------
1 | import { Title, TitleParams, ParseTitleParams } from "@/features/bricks";
2 | import { Brick } from "@/entities/pages";
3 | import { Wrapper } from "../ui/wrapper";
4 | import { EditDialog } from "../ui/dialog";
5 | import { DialogClose, DialogFooter } from "@/shared/ui/dialog";
6 | import { Button } from "@/shared/ui/button";
7 | import { Input } from "@/shared/ui/input";
8 | import { useCurrent } from "../hooks/useCurrent";
9 | import { useEffect, useState } from "react";
10 | import {
11 | Select,
12 | SelectContent,
13 | SelectItem,
14 | SelectTrigger,
15 | SelectValue,
16 | } from "@/shared/ui/select";
17 |
18 | export const TitleEditor = (props: Brick) => {
19 | const { handleChangeBrick, handleDeleteBrick } = useCurrent();
20 | const [title, setTitle] = useState(props.payload);
21 | const [size, setSize] = useState("");
22 | const [align, setAlign] = useState("");
23 |
24 | useEffect(() => {
25 | const params = ParseTitleParams(props.params);
26 | setSize(params.size);
27 | setAlign(params.align);
28 | }, []);
29 |
30 | const handleSave = () => {
31 | const { payload, params, ...newBrick } = props;
32 | const newParams = JSON.stringify({ size, align });
33 | handleChangeBrick({ ...newBrick, payload: title, params: newParams });
34 | };
35 |
36 | const handleClose = () => {
37 | setTitle(props.payload);
38 | };
39 |
40 | const handleDelete = () => {
41 | handleDeleteBrick(props.id);
42 | };
43 | return (
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
55 |
56 |
57 |
58 |
61 |
62 |
63 |
66 |
67 |
68 |
69 |
70 |
71 | );
72 | };
73 |
74 | function EditTitle({
75 | value,
76 | handleChange,
77 | }: {
78 | value: string;
79 | handleChange: (value: string) => void;
80 | }) {
81 | return (
82 |
83 |
84 | handleChange(e.target.value)} />
85 |
86 | );
87 | }
88 |
89 | function EditSize({
90 | value,
91 | handleChange,
92 | }: {
93 | value: string;
94 | handleChange: (value: string) => void;
95 | }) {
96 | return (
97 |
98 |
99 |
113 |
114 | );
115 | }
116 |
117 | function EditAlign({
118 | value,
119 | handleChange,
120 | }: {
121 | value: string;
122 | handleChange: (value: string) => void;
123 | }) {
124 | return (
125 |
126 |
127 |
141 |
142 | );
143 | }
144 |
--------------------------------------------------------------------------------
/src/features/brick-edit/editors/text.tsx:
--------------------------------------------------------------------------------
1 | import { ParseTextParams, Text } from "@/features/bricks";
2 | import { Brick } from "@/entities/pages";
3 | import { Wrapper } from "../ui/wrapper";
4 | import { EditDialog } from "../ui/dialog";
5 | import { DialogClose, DialogFooter } from "@/shared/ui/dialog";
6 | import { Button } from "@/shared/ui/button";
7 | import { useCurrent } from "../hooks/useCurrent";
8 | import { useEffect, useState } from "react";
9 | import {
10 | Select,
11 | SelectContent,
12 | SelectItem,
13 | SelectTrigger,
14 | SelectValue,
15 | } from "@/shared/ui/select";
16 | import { Textarea } from "@/shared/ui/textarea";
17 |
18 | export const TextEditor = (props: Brick) => {
19 | const { handleChangeBrick, handleDeleteBrick } = useCurrent();
20 | const [text, setText] = useState(props.payload);
21 | const [size, setSize] = useState("");
22 | const [align, setAlign] = useState("");
23 |
24 | useEffect(() => {
25 | const params = ParseTextParams(props.params);
26 | setSize(params.size);
27 | setAlign(params.align);
28 | }, []);
29 |
30 | const handleSave = () => {
31 | const { payload, params, ...newBrick } = props;
32 | const newParams = JSON.stringify({ size, align });
33 | handleChangeBrick({ ...newBrick, payload: text, params: newParams });
34 | };
35 |
36 | const handleClose = () => {
37 | setText(props.payload);
38 | const params = ParseTextParams(props.params);
39 | setSize(params.size);
40 | setAlign(params.align);
41 | };
42 |
43 | const handleDelete = () => {
44 | handleDeleteBrick(props.id);
45 | };
46 | return (
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
58 |
59 |
60 |
61 |
64 |
65 |
66 |
69 |
70 |
71 |
72 |
73 |
74 | );
75 | };
76 |
77 | function EditText({
78 | value,
79 | handleChange,
80 | }: {
81 | value: string;
82 | handleChange: (value: string) => void;
83 | }) {
84 | return (
85 |
86 |
87 |
89 | );
90 | }
91 |
92 | function EditSize({
93 | value,
94 | handleChange,
95 | }: {
96 | value: string;
97 | handleChange: (value: string) => void;
98 | }) {
99 | return (
100 |
101 |
102 |
116 |
117 | );
118 | }
119 |
120 | function EditAlign({
121 | value,
122 | handleChange,
123 | }: {
124 | value: string;
125 | handleChange: (value: string) => void;
126 | }) {
127 | return (
128 |
129 |
130 |
144 |
145 | );
146 | }
147 |
--------------------------------------------------------------------------------
/src/widgets/auth/ui/register.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { useRegister, useUser, Loader } from "@/features/auth";
4 | import { useMutation } from "react-query";
5 | import { register } from "@/api/auth";
6 | import { SetToken } from "@/shared/lib/token";
7 | import { useRouter } from "next/navigation";
8 | import Link from "next/link";
9 |
10 | export function Register() {
11 | const { setUser } = useUser();
12 | const router = useRouter();
13 | const mutation = useMutation(
14 | () => register(value.name, value.email, value.password),
15 | {
16 | onSuccess: (data) => {
17 | if (!data.Authorization) return;
18 | SetToken(data.Authorization);
19 | setUser({
20 | email: data.email,
21 | name: data.name,
22 | });
23 | router.push("/");
24 | },
25 | }
26 | );
27 | const [
28 | value,
29 | error,
30 | handleEmailChange,
31 | handlePasswordChange,
32 | handleNameChange,
33 | handleEmailBlur,
34 | handlePassBlur,
35 | handleNameBlur,
36 | ] = useRegister();
37 |
38 | async function handleRegister() {
39 | if (!value.email || !value.password || !value.name) return;
40 | mutation.mutate();
41 | }
42 |
43 | return (
44 |
45 |
46 |
47 |
Welcome to Tap!
48 |
49 | Enter your name, email and password
50 |
51 |
52 |
53 |
54 |
62 |
{error.name}
63 |
64 |
65 |
66 |
74 |
{error.email}
75 |
76 |
77 |
78 |
86 |
87 | {error.password}
88 |
89 |
90 |
91 |
103 |
107 | Signin with Google
108 |
109 |
110 |
111 |
112 | Already have an account?
113 |
114 | Login
115 |
116 |
117 |
118 |
119 | );
120 | }
121 |
--------------------------------------------------------------------------------
/tailwind.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from "tailwindcss";
2 | import { withUt } from "uploadthing/tw";
3 |
4 | export default withUt({
5 | darkMode: ["class"],
6 | content: [
7 | "./pages/**/*.{ts,tsx,mdx}",
8 | "./shared/**/*.{ts,tsx,mdx}",
9 | "./app/**/*.{ts,tsx,mdx}",
10 | "./src/**/*.{ts,tsx,mdx}",
11 | ],
12 | prefix: "",
13 | theme: {
14 | container: {
15 | center: true,
16 | padding: "2rem",
17 | screens: {
18 | "2xl": "1400px",
19 | },
20 | },
21 | extend: {
22 | colors: {
23 | border: "hsl(var(--border))",
24 | input: "hsl(var(--input))",
25 | ring: "hsl(var(--ring))",
26 | background: "hsl(var(--background))",
27 | foreground: "hsl(var(--foreground))",
28 | primary: {
29 | DEFAULT: "hsl(var(--primary))",
30 | foreground: "hsl(var(--primary-foreground))",
31 | },
32 | secondary: {
33 | DEFAULT: "hsl(var(--secondary))",
34 | foreground: "hsl(var(--secondary-foreground))",
35 | },
36 | destructive: {
37 | DEFAULT: "hsl(var(--destructive))",
38 | foreground: "hsl(var(--destructive-foreground))",
39 | },
40 | muted: {
41 | DEFAULT: "hsl(var(--muted))",
42 | foreground: "hsl(var(--muted-foreground))",
43 | },
44 | accent: {
45 | DEFAULT: "hsl(var(--accent))",
46 | foreground: "hsl(var(--accent-foreground))",
47 | },
48 | popover: {
49 | DEFAULT: "hsl(var(--popover))",
50 | foreground: "hsl(var(--popover-foreground))",
51 | },
52 | card: {
53 | DEFAULT: "hsl(var(--card))",
54 | foreground: "hsl(var(--card-foreground))",
55 | },
56 | },
57 | borderRadius: {
58 | lg: "var(--radius)",
59 | md: "calc(var(--radius) - 2px)",
60 | sm: "calc(var(--radius) - 4px)",
61 | },
62 | keyframes: {
63 | "accordion-down": {
64 | from: { height: "0" },
65 | to: { height: "var(--radix-accordion-content-height)" },
66 | },
67 | "accordion-up": {
68 | from: { height: "var(--radix-accordion-content-height)" },
69 | to: { height: "0" },
70 | },
71 | },
72 | animation: {
73 | "accordion-down": "accordion-down 0.2s ease-out",
74 | "accordion-up": "accordion-up 0.2s ease-out",
75 | },
76 | },
77 | },
78 | plugins: [require("tailwindcss-animate")],
79 | });
80 |
81 | // const config = {
82 | // darkMode: ["class"],
83 | // content: [
84 | // "./pages/**/*.{ts,tsx,mdx}",
85 | // "./shared/**/*.{ts,tsx,mdx}",
86 | // "./app/**/*.{ts,tsx,mdx}",
87 | // "./src/**/*.{ts,tsx,mdx}",
88 | // ],
89 | // prefix: "",
90 | // theme: {
91 | // container: {
92 | // center: true,
93 | // padding: "2rem",
94 | // screens: {
95 | // "2xl": "1400px",
96 | // },
97 | // },
98 | // extend: {
99 | // colors: {
100 | // border: "hsl(var(--border))",
101 | // input: "hsl(var(--input))",
102 | // ring: "hsl(var(--ring))",
103 | // background: "hsl(var(--background))",
104 | // foreground: "hsl(var(--foreground))",
105 | // primary: {
106 | // DEFAULT: "hsl(var(--primary))",
107 | // foreground: "hsl(var(--primary-foreground))",
108 | // },
109 | // secondary: {
110 | // DEFAULT: "hsl(var(--secondary))",
111 | // foreground: "hsl(var(--secondary-foreground))",
112 | // },
113 | // destructive: {
114 | // DEFAULT: "hsl(var(--destructive))",
115 | // foreground: "hsl(var(--destructive-foreground))",
116 | // },
117 | // muted: {
118 | // DEFAULT: "hsl(var(--muted))",
119 | // foreground: "hsl(var(--muted-foreground))",
120 | // },
121 | // accent: {
122 | // DEFAULT: "hsl(var(--accent))",
123 | // foreground: "hsl(var(--accent-foreground))",
124 | // },
125 | // popover: {
126 | // DEFAULT: "hsl(var(--popover))",
127 | // foreground: "hsl(var(--popover-foreground))",
128 | // },
129 | // card: {
130 | // DEFAULT: "hsl(var(--card))",
131 | // foreground: "hsl(var(--card-foreground))",
132 | // },
133 | // },
134 | // borderRadius: {
135 | // lg: "var(--radius)",
136 | // md: "calc(var(--radius) - 2px)",
137 | // sm: "calc(var(--radius) - 4px)",
138 | // },
139 | // keyframes: {
140 | // "accordion-down": {
141 | // from: { height: "0" },
142 | // to: { height: "var(--radix-accordion-content-height)" },
143 | // },
144 | // "accordion-up": {
145 | // from: { height: "var(--radix-accordion-content-height)" },
146 | // to: { height: "0" },
147 | // },
148 | // },
149 | // animation: {
150 | // "accordion-down": "accordion-down 0.2s ease-out",
151 | // "accordion-up": "accordion-up 0.2s ease-out",
152 | // },
153 | // },
154 | // },
155 | // plugins: [require("tailwindcss-animate")],
156 | // } satisfies Config;
157 |
158 | // export default config;
159 |
--------------------------------------------------------------------------------
/src/features/brick-edit/ui/add.tsx:
--------------------------------------------------------------------------------
1 | import { cn } from "@/shared/lib/utils";
2 |
3 | import {
4 | Dialog,
5 | DialogTrigger,
6 | DialogContent,
7 | DialogHeader,
8 | DialogClose,
9 | } from "@/shared/ui/dialog";
10 | import { useCurrent } from "../hooks/useCurrent";
11 | import { v4 } from "uuid";
12 | import { ComponentPropsWithoutRef } from "react";
13 | import {
14 | AlignVerticalSpaceAround,
15 | Minus,
16 | Image,
17 | Link,
18 | Type,
19 | CaseSensitive,
20 | } from "lucide-react";
21 |
22 | export const AddNewBrick = () => {
23 | return (
24 |
49 | );
50 | };
51 |
52 | interface INewBrick extends ComponentPropsWithoutRef<"div"> {
53 | children: React.ReactNode;
54 | }
55 |
56 | function NewBrickParent({ children, className, ...props }: INewBrick) {
57 | return (
58 |
65 | {children}
66 |
67 | );
68 | }
69 |
70 | function TextAdd() {
71 | const { handleAddBrick } = useCurrent();
72 | function AddTitle() {
73 | handleAddBrick({
74 | id: v4(),
75 | type: "text",
76 | payload: "New Text, example text",
77 | params: '{"size": "medium", "align": "center"}',
78 | children: [],
79 | });
80 | }
81 | return (
82 |
83 |
84 |
85 | Default text
86 |
87 |
88 | );
89 | }
90 |
91 | function TitleAdd() {
92 | const { handleAddBrick } = useCurrent();
93 | function AddTitle() {
94 | handleAddBrick({
95 | id: v4(),
96 | type: "title",
97 | payload: "Example title",
98 | params: '{"size": "medium", "align": "center"}',
99 | children: [],
100 | });
101 | }
102 | return (
103 |
104 |
105 |
106 | Title
107 |
108 |
109 | );
110 | }
111 |
112 | function AirAdd() {
113 | const { handleAddBrick } = useCurrent();
114 | function AddAir() {
115 | handleAddBrick({
116 | id: v4(),
117 | type: "air",
118 | payload: "20",
119 | params: "",
120 | children: [],
121 | });
122 | }
123 | return (
124 |
125 |
126 |
127 | Air
128 |
129 |
130 | );
131 | }
132 |
133 | function LineAdd() {
134 | const { handleAddBrick } = useCurrent();
135 | function AddAir() {
136 | handleAddBrick({
137 | id: v4(),
138 | type: "line",
139 | payload: "solid",
140 | params: "",
141 | children: [],
142 | });
143 | }
144 | return (
145 |
146 |
147 |
148 | Line
149 |
150 |
151 | );
152 | }
153 |
154 | function PictureAdd() {
155 | const { handleAddBrick } = useCurrent();
156 | function AddPicture() {
157 | handleAddBrick({
158 | id: v4(),
159 | type: "picture",
160 | payload: "",
161 | params: "",
162 | children: [],
163 | });
164 | }
165 | return (
166 |
167 |
168 |
169 | Picture
170 |
171 |
172 | );
173 | }
174 |
175 | function ClickAdd() {
176 | const { handleAddBrick } = useCurrent();
177 | function AddPicture() {
178 | handleAddBrick({
179 | id: v4(),
180 | type: "click",
181 | payload: "Example link",
182 | params: "#",
183 | children: [],
184 | });
185 | }
186 | return (
187 |
188 |
189 |
190 | Link
191 |
192 |
193 | );
194 | }
195 |
--------------------------------------------------------------------------------
/src/shared/ui/select.tsx:
--------------------------------------------------------------------------------
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 "@/shared/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,
17 | React.ComponentPropsWithoutRef
18 | >(({ className, children, ...props }, ref) => (
19 | span]:line-clamp-1",
23 | className
24 | )}
25 | {...props}
26 | >
27 | {children}
28 |
29 |
30 |
31 |
32 | ))
33 | SelectTrigger.displayName = SelectPrimitive.Trigger.displayName
34 |
35 | const SelectScrollUpButton = React.forwardRef<
36 | React.ElementRef,
37 | React.ComponentPropsWithoutRef
38 | >(({ className, ...props }, ref) => (
39 |
47 |
48 |
49 | ))
50 | SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName
51 |
52 | const SelectScrollDownButton = React.forwardRef<
53 | React.ElementRef,
54 | React.ComponentPropsWithoutRef
55 | >(({ className, ...props }, ref) => (
56 |
64 |
65 |
66 | ))
67 | SelectScrollDownButton.displayName =
68 | SelectPrimitive.ScrollDownButton.displayName
69 |
70 | const SelectContent = React.forwardRef<
71 | React.ElementRef,
72 | React.ComponentPropsWithoutRef
73 | >(({ className, children, position = "popper", ...props }, ref) => (
74 |
75 |
86 |
87 |
94 | {children}
95 |
96 |
97 |
98 |
99 | ))
100 | SelectContent.displayName = SelectPrimitive.Content.displayName
101 |
102 | const SelectLabel = React.forwardRef<
103 | React.ElementRef,
104 | React.ComponentPropsWithoutRef
105 | >(({ className, ...props }, ref) => (
106 |
111 | ))
112 | SelectLabel.displayName = SelectPrimitive.Label.displayName
113 |
114 | const SelectItem = React.forwardRef<
115 | React.ElementRef,
116 | React.ComponentPropsWithoutRef
117 | >(({ className, children, ...props }, ref) => (
118 |
126 |
127 |
128 |
129 |
130 |
131 |
132 | {children}
133 |
134 | ))
135 | SelectItem.displayName = SelectPrimitive.Item.displayName
136 |
137 | const SelectSeparator = React.forwardRef<
138 | React.ElementRef,
139 | React.ComponentPropsWithoutRef
140 | >(({ className, ...props }, ref) => (
141 |
146 | ))
147 | SelectSeparator.displayName = SelectPrimitive.Separator.displayName
148 |
149 | export {
150 | Select,
151 | SelectGroup,
152 | SelectValue,
153 | SelectTrigger,
154 | SelectContent,
155 | SelectLabel,
156 | SelectItem,
157 | SelectSeparator,
158 | SelectScrollUpButton,
159 | SelectScrollDownButton,
160 | }
161 |
--------------------------------------------------------------------------------
/src/shared/ui/carousel.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import * as React from "react";
4 | import useEmblaCarousel, {
5 | type UseEmblaCarouselType,
6 | } from "embla-carousel-react";
7 | import { ArrowLeft, ArrowRight } from "lucide-react";
8 |
9 | import { cn } from "@/shared/lib/utils";
10 | import { Button } from "@/shared/ui/button";
11 |
12 | type CarouselApi = UseEmblaCarouselType[1];
13 | type UseCarouselParameters = Parameters;
14 | type CarouselOptions = UseCarouselParameters[0];
15 | type CarouselPlugin = UseCarouselParameters[1];
16 |
17 | type CarouselProps = {
18 | opts?: CarouselOptions;
19 | plugins?: CarouselPlugin;
20 | orientation?: "horizontal" | "vertical";
21 | setApi?: (api: CarouselApi) => void;
22 | };
23 |
24 | type CarouselContextProps = {
25 | carouselRef: ReturnType[0];
26 | api: ReturnType[1];
27 | scrollPrev: () => void;
28 | scrollNext: () => void;
29 | canScrollPrev: boolean;
30 | canScrollNext: boolean;
31 | } & CarouselProps;
32 |
33 | const CarouselContext = React.createContext(null);
34 |
35 | function useCarousel() {
36 | const context = React.useContext(CarouselContext);
37 |
38 | if (!context) {
39 | throw new Error("useCarousel must be used within a ");
40 | }
41 |
42 | return context;
43 | }
44 |
45 | const Carousel = React.forwardRef<
46 | HTMLDivElement,
47 | React.HTMLAttributes & CarouselProps
48 | >(
49 | (
50 | {
51 | orientation = "horizontal",
52 | opts,
53 | setApi,
54 | plugins,
55 | className,
56 | children,
57 | ...props
58 | },
59 | ref
60 | ) => {
61 | const [carouselRef, api] = useEmblaCarousel(
62 | {
63 | ...opts,
64 | axis: orientation === "horizontal" ? "x" : "y",
65 | },
66 | plugins
67 | );
68 | const [canScrollPrev, setCanScrollPrev] = React.useState(false);
69 | const [canScrollNext, setCanScrollNext] = React.useState(false);
70 |
71 | const onSelect = React.useCallback((api: CarouselApi) => {
72 | if (!api) {
73 | return;
74 | }
75 |
76 | setCanScrollPrev(api.canScrollPrev());
77 | setCanScrollNext(api.canScrollNext());
78 | }, []);
79 |
80 | const scrollPrev = React.useCallback(() => {
81 | api?.scrollPrev();
82 | }, [api]);
83 |
84 | const scrollNext = React.useCallback(() => {
85 | api?.scrollNext();
86 | }, [api]);
87 |
88 | const handleKeyDown = React.useCallback(
89 | (event: React.KeyboardEvent) => {
90 | if (event.key === "ArrowLeft") {
91 | event.preventDefault();
92 | scrollPrev();
93 | } else if (event.key === "ArrowRight") {
94 | event.preventDefault();
95 | scrollNext();
96 | }
97 | },
98 | [scrollPrev, scrollNext]
99 | );
100 |
101 | React.useEffect(() => {
102 | if (!api || !setApi) {
103 | return;
104 | }
105 |
106 | setApi(api);
107 | }, [api, setApi]);
108 |
109 | React.useEffect(() => {
110 | if (!api) {
111 | return;
112 | }
113 |
114 | onSelect(api);
115 | api.on("reInit", onSelect);
116 | api.on("select", onSelect);
117 |
118 | return () => {
119 | api?.off("select", onSelect);
120 | };
121 | }, [api, onSelect]);
122 |
123 | return (
124 |
137 |
145 | {children}
146 |
147 |
148 | );
149 | }
150 | );
151 | Carousel.displayName = "Carousel";
152 |
153 | const CarouselContent = React.forwardRef<
154 | HTMLDivElement,
155 | React.HTMLAttributes
156 | >(({ className, ...props }, ref) => {
157 | const { carouselRef, orientation } = useCarousel();
158 |
159 | return (
160 |
171 | );
172 | });
173 | CarouselContent.displayName = "CarouselContent";
174 |
175 | const CarouselItem = React.forwardRef<
176 | HTMLDivElement,
177 | React.HTMLAttributes
178 | >(({ className, ...props }, ref) => {
179 | const { orientation } = useCarousel();
180 |
181 | return (
182 |
193 | );
194 | });
195 | CarouselItem.displayName = "CarouselItem";
196 |
197 | const CarouselPrevious = React.forwardRef<
198 | HTMLButtonElement,
199 | React.ComponentProps
200 | >(({ className, variant = "outline", size = "icon", ...props }, ref) => {
201 | const { orientation, scrollPrev, canScrollPrev } = useCarousel();
202 |
203 | return (
204 |
222 | );
223 | });
224 | CarouselPrevious.displayName = "CarouselPrevious";
225 |
226 | const CarouselNext = React.forwardRef<
227 | HTMLButtonElement,
228 | React.ComponentProps
229 | >(({ className, variant = "outline", size = "icon", ...props }, ref) => {
230 | const { orientation, scrollNext, canScrollNext } = useCarousel();
231 |
232 | return (
233 |
251 | );
252 | });
253 | CarouselNext.displayName = "CarouselNext";
254 |
255 | export {
256 | type CarouselApi,
257 | Carousel,
258 | CarouselContent,
259 | CarouselItem,
260 | CarouselPrevious,
261 | CarouselNext,
262 | };
263 |
--------------------------------------------------------------------------------
/src/shared/ui/dropdown-menu.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
5 | import { Check, ChevronRight, Circle } from "lucide-react"
6 |
7 | import { cn } from "@/shared/lib/utils"
8 |
9 | const DropdownMenu = DropdownMenuPrimitive.Root
10 |
11 | const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
12 |
13 | const DropdownMenuGroup = DropdownMenuPrimitive.Group
14 |
15 | const DropdownMenuPortal = DropdownMenuPrimitive.Portal
16 |
17 | const DropdownMenuSub = DropdownMenuPrimitive.Sub
18 |
19 | const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
20 |
21 | const DropdownMenuSubTrigger = React.forwardRef<
22 | React.ElementRef,
23 | React.ComponentPropsWithoutRef & {
24 | inset?: boolean
25 | }
26 | >(({ className, inset, children, ...props }, ref) => (
27 |
36 | {children}
37 |
38 |
39 | ))
40 | DropdownMenuSubTrigger.displayName =
41 | DropdownMenuPrimitive.SubTrigger.displayName
42 |
43 | const DropdownMenuSubContent = React.forwardRef<
44 | React.ElementRef,
45 | React.ComponentPropsWithoutRef
46 | >(({ className, ...props }, ref) => (
47 |
55 | ))
56 | DropdownMenuSubContent.displayName =
57 | DropdownMenuPrimitive.SubContent.displayName
58 |
59 | const DropdownMenuContent = React.forwardRef<
60 | React.ElementRef,
61 | React.ComponentPropsWithoutRef
62 | >(({ className, sideOffset = 4, ...props }, ref) => (
63 |
64 |
73 |
74 | ))
75 | DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
76 |
77 | const DropdownMenuItem = React.forwardRef<
78 | React.ElementRef,
79 | React.ComponentPropsWithoutRef & {
80 | inset?: boolean
81 | }
82 | >(({ className, inset, ...props }, ref) => (
83 |
92 | ))
93 | DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
94 |
95 | const DropdownMenuCheckboxItem = React.forwardRef<
96 | React.ElementRef,
97 | React.ComponentPropsWithoutRef
98 | >(({ className, children, checked, ...props }, ref) => (
99 |
108 |
109 |
110 |
111 |
112 |
113 | {children}
114 |
115 | ))
116 | DropdownMenuCheckboxItem.displayName =
117 | DropdownMenuPrimitive.CheckboxItem.displayName
118 |
119 | const DropdownMenuRadioItem = React.forwardRef<
120 | React.ElementRef,
121 | React.ComponentPropsWithoutRef
122 | >(({ className, children, ...props }, ref) => (
123 |
131 |
132 |
133 |
134 |
135 |
136 | {children}
137 |
138 | ))
139 | DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
140 |
141 | const DropdownMenuLabel = React.forwardRef<
142 | React.ElementRef,
143 | React.ComponentPropsWithoutRef & {
144 | inset?: boolean
145 | }
146 | >(({ className, inset, ...props }, ref) => (
147 |
156 | ))
157 | DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
158 |
159 | const DropdownMenuSeparator = React.forwardRef<
160 | React.ElementRef,
161 | React.ComponentPropsWithoutRef
162 | >(({ className, ...props }, ref) => (
163 |
168 | ))
169 | DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
170 |
171 | const DropdownMenuShortcut = ({
172 | className,
173 | ...props
174 | }: React.HTMLAttributes) => {
175 | return (
176 |
180 | )
181 | }
182 | DropdownMenuShortcut.displayName = "DropdownMenuShortcut"
183 |
184 | export {
185 | DropdownMenu,
186 | DropdownMenuTrigger,
187 | DropdownMenuContent,
188 | DropdownMenuItem,
189 | DropdownMenuCheckboxItem,
190 | DropdownMenuRadioItem,
191 | DropdownMenuLabel,
192 | DropdownMenuSeparator,
193 | DropdownMenuShortcut,
194 | DropdownMenuGroup,
195 | DropdownMenuPortal,
196 | DropdownMenuSub,
197 | DropdownMenuSubContent,
198 | DropdownMenuSubTrigger,
199 | DropdownMenuRadioGroup,
200 | }
201 |
--------------------------------------------------------------------------------
/src/features/bricks/svg/icons.tsx:
--------------------------------------------------------------------------------
1 | export function Web(
2 | props: React.ButtonHTMLAttributes & {
3 | strokeWidth?: number;
4 | }
5 | ) {
6 | return (
7 |
23 | );
24 | }
25 |
26 | export function Github(props: React.ButtonHTMLAttributes) {
27 | return (
28 |
50 | );
51 | }
52 |
53 | export function Facebook(props: React.ButtonHTMLAttributes) {
54 | return (
55 |
79 | );
80 | }
81 |
82 | export function Example(props: React.ButtonHTMLAttributes) {
83 | return;
84 | }
85 |
86 | export function Youtube(props: React.ButtonHTMLAttributes) {
87 | return (
88 |
112 | );
113 | }
114 |
115 | export function X(props: React.ButtonHTMLAttributes) {
116 | return (
117 |
130 | );
131 | }
132 |
133 | export function WhatsApp(props: React.ButtonHTMLAttributes) {
134 | return (
135 |
148 | );
149 | }
150 |
151 | export function Vk(props: React.ButtonHTMLAttributes) {
152 | return (
153 |
177 | );
178 | }
179 |
180 | export function Twitch(props: React.ButtonHTMLAttributes) {
181 | return (
182 |
207 | );
208 | }
209 |
210 | export function Tiktok(props: React.ButtonHTMLAttributes) {
211 | return (
212 |
233 | );
234 | }
235 |
236 | export function Telegram(props: React.ButtonHTMLAttributes) {
237 | return (
238 |
275 | );
276 | }
277 |
278 | export function Instagram(props: React.ButtonHTMLAttributes) {
279 | return (
280 |
308 | );
309 | }
310 |
--------------------------------------------------------------------------------