├── .prettierignore ├── src-tauri ├── build.rs ├── icons │ ├── icon.ico │ ├── icon.png │ ├── icon.icns │ ├── solanis.png │ ├── StoreLogo.png │ ├── solanis.jpeg │ ├── finder-icon.png │ ├── trashempty.png │ ├── Square107x107Logo.png │ ├── Square142x142Logo.png │ ├── Square150x150Logo.png │ ├── Square284x284Logo.png │ ├── Square30x30Logo.png │ ├── Square310x310Logo.png │ ├── Square44x44Logo.png │ ├── Square71x71Logo.png │ ├── Square89x89Logo.png │ ├── solanis-transparent.png │ ├── solanis-border-shadow.png │ └── apple.svg ├── .gitignore ├── src │ └── main.rs ├── Cargo.toml └── tauri.conf.json ├── public ├── icon-mac.png ├── solanis.jpeg ├── solanis.png ├── finder-icon.png ├── trashempty.png ├── solanis-border-shadow.png ├── solanis-transparent.png ├── apple.svg └── solanis-transparent.svg ├── src ├── app │ ├── favicon.ico │ ├── HelveticaNeue.woff2 │ ├── solanized │ │ └── [username] │ │ │ ├── page.tsx │ │ │ ├── dashboard │ │ │ └── page.tsx │ │ │ ├── markdown-editor │ │ │ └── page.tsx │ │ │ ├── annotations │ │ │ └── page.tsx │ │ │ ├── layout.tsx │ │ │ └── settings │ │ │ └── page.tsx │ ├── layout.tsx │ ├── (lp-pages) │ │ ├── register │ │ │ └── page.tsx │ │ └── login │ │ │ └── page.tsx │ ├── globals.css │ └── page.tsx ├── types │ └── Annotation.ts ├── components │ ├── Command.tsx │ ├── ui │ │ ├── skeleton.tsx │ │ ├── label.tsx │ │ ├── separator.tsx │ │ ├── input.tsx │ │ ├── animated-shiny-text.tsx │ │ ├── switch.tsx │ │ ├── badge.tsx │ │ ├── word-fade-in.tsx │ │ ├── staggered-fade.tsx │ │ ├── bento-grid.tsx │ │ ├── enchanced-separator.tsx │ │ ├── input-icon.tsx │ │ ├── tooltip.tsx │ │ ├── resizable.tsx │ │ ├── gradient-text.tsx │ │ ├── tabs.tsx │ │ ├── card.tsx │ │ ├── gradient-heading.tsx │ │ ├── container-scroll-animation.tsx │ │ ├── breadcrumb.tsx │ │ ├── table.tsx │ │ ├── dialog.tsx │ │ ├── link-preview.tsx │ │ ├── typewriter-effect.tsx │ │ ├── sparkles-text.tsx │ │ ├── button.tsx │ │ ├── command.tsx │ │ ├── select.tsx │ │ └── dropdown-menu.tsx │ ├── DynamicIcon.tsx │ ├── UserItem.tsx │ ├── SolanisAvatar.tsx │ ├── AnnotationList.tsx │ ├── ModalCreateSummary.tsx │ ├── Header.tsx │ ├── Annotation.tsx │ ├── Footer.tsx │ ├── Editor.tsx │ ├── Sidebar.tsx │ └── Dashboard.tsx ├── lib │ └── utils.ts ├── contexts │ ├── theme-provider.tsx │ └── editor-provider.tsx └── hooks │ └── useAnthropic.ts ├── .prettierrc ├── postcss.config.js ├── .prettierrc.mjs ├── .eslintrc.json ├── docker-compose.yml ├── components.json ├── next.config.mjs ├── .gitignore ├── tsconfig.json ├── README.md ├── LICENSE ├── react-graph-vis.d.ts ├── package.json └── tailwind.config.ts /.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | package.json 4 | src-tauri -------------------------------------------------------------------------------- /src-tauri/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | tauri_build::build() 3 | } 4 | -------------------------------------------------------------------------------- /public/icon-mac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solanisdev/solanis/HEAD/public/icon-mac.png -------------------------------------------------------------------------------- /public/solanis.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solanisdev/solanis/HEAD/public/solanis.jpeg -------------------------------------------------------------------------------- /public/solanis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solanisdev/solanis/HEAD/public/solanis.png -------------------------------------------------------------------------------- /src/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solanisdev/solanis/HEAD/src/app/favicon.ico -------------------------------------------------------------------------------- /public/finder-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solanisdev/solanis/HEAD/public/finder-icon.png -------------------------------------------------------------------------------- /public/trashempty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solanisdev/solanis/HEAD/public/trashempty.png -------------------------------------------------------------------------------- /src-tauri/icons/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solanisdev/solanis/HEAD/src-tauri/icons/icon.ico -------------------------------------------------------------------------------- /src-tauri/icons/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solanisdev/solanis/HEAD/src-tauri/icons/icon.png -------------------------------------------------------------------------------- /src-tauri/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | -------------------------------------------------------------------------------- /src-tauri/icons/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solanisdev/solanis/HEAD/src-tauri/icons/icon.icns -------------------------------------------------------------------------------- /src-tauri/icons/solanis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solanisdev/solanis/HEAD/src-tauri/icons/solanis.png -------------------------------------------------------------------------------- /src/app/HelveticaNeue.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solanisdev/solanis/HEAD/src/app/HelveticaNeue.woff2 -------------------------------------------------------------------------------- /src-tauri/icons/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solanisdev/solanis/HEAD/src-tauri/icons/StoreLogo.png -------------------------------------------------------------------------------- /src-tauri/icons/solanis.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solanisdev/solanis/HEAD/src-tauri/icons/solanis.jpeg -------------------------------------------------------------------------------- /public/solanis-border-shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solanisdev/solanis/HEAD/public/solanis-border-shadow.png -------------------------------------------------------------------------------- /public/solanis-transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solanisdev/solanis/HEAD/public/solanis-transparent.png -------------------------------------------------------------------------------- /src-tauri/icons/finder-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solanisdev/solanis/HEAD/src-tauri/icons/finder-icon.png -------------------------------------------------------------------------------- /src-tauri/icons/trashempty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solanisdev/solanis/HEAD/src-tauri/icons/trashempty.png -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 2, 3 | "semi": true, 4 | "singleQuote": false, 5 | "trailingComma": "all" 6 | } 7 | -------------------------------------------------------------------------------- /src-tauri/icons/Square107x107Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solanisdev/solanis/HEAD/src-tauri/icons/Square107x107Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square142x142Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solanisdev/solanis/HEAD/src-tauri/icons/Square142x142Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square150x150Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solanisdev/solanis/HEAD/src-tauri/icons/Square150x150Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square284x284Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solanisdev/solanis/HEAD/src-tauri/icons/Square284x284Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square30x30Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solanisdev/solanis/HEAD/src-tauri/icons/Square30x30Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square310x310Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solanisdev/solanis/HEAD/src-tauri/icons/Square310x310Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square44x44Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solanisdev/solanis/HEAD/src-tauri/icons/Square44x44Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square71x71Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solanisdev/solanis/HEAD/src-tauri/icons/Square71x71Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square89x89Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solanisdev/solanis/HEAD/src-tauri/icons/Square89x89Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/solanis-transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solanisdev/solanis/HEAD/src-tauri/icons/solanis-transparent.png -------------------------------------------------------------------------------- /src-tauri/icons/solanis-border-shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solanisdev/solanis/HEAD/src-tauri/icons/solanis-border-shadow.png -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /src/app/solanized/[username]/page.tsx: -------------------------------------------------------------------------------- 1 | import Dashboard from "@/components/Dashboard"; 2 | 3 | interface Props {} 4 | export default function page({}: Props) { 5 | return ; 6 | } 7 | -------------------------------------------------------------------------------- /src/app/solanized/[username]/dashboard/page.tsx: -------------------------------------------------------------------------------- 1 | import Dashboard from "@/components/Dashboard"; 2 | 3 | interface Props {} 4 | export default function page({}: Props) { 5 | return ; 6 | } 7 | -------------------------------------------------------------------------------- /.prettierrc.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import("prettier").Config} */ 2 | const config = { 3 | tabWidth: 2, 4 | semi: true, 5 | singleQuote: false, 6 | trailingComma: "all", 7 | }; 8 | 9 | export default config; 10 | -------------------------------------------------------------------------------- /src/app/solanized/[username]/markdown-editor/page.tsx: -------------------------------------------------------------------------------- 1 | import Editor from "@/components/Editor"; 2 | import React from "react"; 3 | 4 | type Props = {}; 5 | 6 | export default function MarkdownEditorPage({}: Props) { 7 | return ; 8 | } 9 | -------------------------------------------------------------------------------- /src/types/Annotation.ts: -------------------------------------------------------------------------------- 1 | import dynamicIconImports from "lucide-react/dynamicIconImports"; 2 | 3 | export type AnnotationT = { 4 | icon: keyof typeof dynamicIconImports; 5 | title: string; 6 | description: string; 7 | tags: string[]; 8 | lastUpdate: string; 9 | }; 10 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["next", "next/core-web-vitals", "eslint:recommended"], 3 | "globals": { 4 | "React": "readonly" 5 | }, 6 | "plugins": ["prettier"], 7 | "rules": { 8 | "no-unused-vars": "warn", 9 | "prettier/prettier": "warn" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/components/Command.tsx: -------------------------------------------------------------------------------- 1 | import { Command, CommandInput } from "@/components/ui/command"; 2 | 3 | export function CommandDemo() { 4 | return ( 5 | 6 | 7 | 8 | ); 9 | } 10 | -------------------------------------------------------------------------------- /src-tauri/src/main.rs: -------------------------------------------------------------------------------- 1 | // Prevents additional console window on Windows in release, DO NOT REMOVE!! 2 | #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] 3 | 4 | fn main() { 5 | tauri::Builder::default() 6 | .run(tauri::generate_context!()) 7 | .expect("error while running tauri application"); 8 | } 9 | -------------------------------------------------------------------------------- /src/components/ui/skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from "@/lib/utils" 2 | 3 | function Skeleton({ 4 | className, 5 | ...props 6 | }: React.HTMLAttributes) { 7 | return ( 8 |
12 | ) 13 | } 14 | 15 | export { Skeleton } 16 | -------------------------------------------------------------------------------- /src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { type ClassValue, clsx } 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 ellipsize(str: string, maxLength: number) { 9 | if (str.length <= maxLength) return str; 10 | return str.slice(0, maxLength) + "..."; 11 | } 12 | -------------------------------------------------------------------------------- /src/contexts/theme-provider.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as React from "react"; 4 | import { ThemeProvider as NextThemesProvider } from "next-themes"; 5 | import { type ThemeProviderProps } from "next-themes/dist/types"; 6 | 7 | export function ThemeProvider({ children, ...props }: ThemeProviderProps) { 8 | return {children}; 9 | } 10 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | services: 4 | postgres: 5 | image: postgres 6 | container_name: solanis-pg 7 | restart: always 8 | environment: 9 | POSTGRES_PASSWORD: postgres 10 | POSTGRES_USER: postgres 11 | POSTGRES_DB: solanis 12 | ports: 13 | - "5432:5432" 14 | volumes: 15 | - db:/var/lib/postgresql/data 16 | volumes: 17 | db: 18 | driver: local 19 | -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "default", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "src/app/globals.css", 9 | "baseColor": "neutral", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/components/DynamicIcon.tsx: -------------------------------------------------------------------------------- 1 | import dynamic from "next/dynamic"; 2 | import { LucideProps } from "lucide-react"; 3 | import dynamicIconImports from "lucide-react/dynamicIconImports"; 4 | 5 | interface IconProps extends LucideProps { 6 | name: keyof typeof dynamicIconImports; 7 | } 8 | 9 | const DynamicIcon = ({ name, ...props }: IconProps) => { 10 | const LucideIcon = dynamic(dynamicIconImports[name]); 11 | 12 | return ; 13 | }; 14 | 15 | export default DynamicIcon; 16 | -------------------------------------------------------------------------------- /next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | env: { 4 | ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY, 5 | }, 6 | rewrites: async () => { 7 | return [ 8 | { 9 | source: "/anthropic/:path*", 10 | destination: "https://api.anthropic.com/:path*", 11 | }, 12 | ]; 13 | }, 14 | images: { 15 | domains: ["api.microlink.io"], 16 | }, 17 | transpilePackages: ["lucide-react"], 18 | }; 19 | 20 | export default nextConfig; 21 | -------------------------------------------------------------------------------- /src/app/solanized/[username]/annotations/page.tsx: -------------------------------------------------------------------------------- 1 | import AnnotationList from "@/components/AnnotationList"; 2 | import { GradientHeading } from "@/components/ui/gradient-heading"; 3 | import React from "react"; 4 | 5 | type Props = {}; 6 | 7 | export default function AnnotationsPage({}: Props) { 8 | return ( 9 |
10 | 11 | Anotações 12 | 13 | 14 |
15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | .env 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["dom", "dom.iterable", "esnext"], 4 | "allowJs": true, 5 | "skipLibCheck": true, 6 | "strict": true, 7 | "noEmit": true, 8 | "esModuleInterop": true, 9 | "module": "esnext", 10 | "moduleResolution": "bundler", 11 | "resolveJsonModule": true, 12 | "isolatedModules": true, 13 | "jsx": "preserve", 14 | "incremental": true, 15 | "plugins": [ 16 | { 17 | "name": "next" 18 | } 19 | ], 20 | "paths": { 21 | "@/*": ["./src/*"] 22 | } 23 | }, 24 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 25 | "exclude": ["node_modules"] 26 | } 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Solanis - Create markdowns efficiently. 2 | 3 | Solanis is a cutting-edge AI generator designed to create markdowns efficiently. Powered by Solanis AI v1.0, this tool leverages advanced natural language processing capabilities to generate high-quality, well-structured markdown documents effortlessly. 4 | 5 | We use the most simple structure to save every information to be as light and as fast as possible. 6 | 7 | Solanis by right now is in Alpha and if you wan't to help us, you can use Git or any version control of your choice. 8 | 9 | ### Authors 10 | 11 |
12 | 13 | 14 | 15 |
16 | -------------------------------------------------------------------------------- /src/components/ui/label.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import * as LabelPrimitive from "@radix-ui/react-label" 5 | import { cva, type VariantProps } from "class-variance-authority" 6 | 7 | import { cn } from "@/lib/utils" 8 | 9 | const labelVariants = cva( 10 | "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" 11 | ) 12 | 13 | const Label = React.forwardRef< 14 | React.ElementRef, 15 | React.ComponentPropsWithoutRef & 16 | VariantProps 17 | >(({ className, ...props }, ref) => ( 18 | 23 | )) 24 | Label.displayName = LabelPrimitive.Root.displayName 25 | 26 | export { Label } 27 | -------------------------------------------------------------------------------- /src/components/UserItem.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { GradientHeading } from "./ui/gradient-heading"; 4 | import { GradientText } from "./ui/gradient-text"; 5 | 6 | export default function UserItem() { 7 | return ( 8 |
9 |
10 | 11 | GR 12 | 13 |
14 |
15 | 16 | gustavorteuber 17 | 18 | 19 | gustavorteuber@dev.com 20 | 21 |
22 |
23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /src-tauri/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "app" 3 | version = "0.1.0" 4 | description = "A Tauri App" 5 | authors = ["you"] 6 | license = "" 7 | repository = "" 8 | default-run = "app" 9 | edition = "2021" 10 | rust-version = "1.60" 11 | 12 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 13 | 14 | [build-dependencies] 15 | tauri-build = { version = "1.5.2", features = [] } 16 | 17 | [dependencies] 18 | serde_json = "1.0" 19 | serde = { version = "1.0", features = ["derive"] } 20 | tauri = { version = "1.6.5", features = [] } 21 | 22 | [features] 23 | # this feature is used for production builds or when `devPath` points to the filesystem and the built-in dev server is disabled. 24 | # If you use cargo directly instead of tauri's cli you can use this feature flag to switch between tauri's `dev` and `build` modes. 25 | # DO NOT REMOVE!! 26 | custom-protocol = [ "tauri/custom-protocol" ] 27 | -------------------------------------------------------------------------------- /src/components/ui/separator.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as React from "react"; 4 | import * as SeparatorPrimitive from "@radix-ui/react-separator"; 5 | 6 | import { cn } from "@/lib/utils"; 7 | 8 | const Separator = React.forwardRef< 9 | React.ElementRef, 10 | React.ComponentPropsWithoutRef 11 | >( 12 | ( 13 | { className, orientation = "horizontal", decorative = true, ...props }, 14 | ref, 15 | ) => ( 16 | 27 | ), 28 | ); 29 | Separator.displayName = SeparatorPrimitive.Root.displayName; 30 | 31 | export { Separator }; 32 | -------------------------------------------------------------------------------- /src/components/ui/input.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | 3 | import { cn } from "@/lib/utils"; 4 | 5 | export interface InputProps 6 | extends React.InputHTMLAttributes {} 7 | 8 | const Input = React.forwardRef( 9 | ({ className, type, ...props }, ref) => { 10 | return ( 11 | 20 | ); 21 | }, 22 | ); 23 | Input.displayName = "Input"; 24 | 25 | export { Input }; 26 | -------------------------------------------------------------------------------- /public/apple.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src-tauri/icons/apple.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/SolanisAvatar.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import Image from "next/image"; 4 | import SolanisTransparent from "../../public/solanis-transparent.png"; 5 | import { GradientHeading } from "@/components/ui/gradient-heading"; 6 | 7 | interface SolanisAvatarProps { 8 | hasBorder?: boolean; 9 | size?: "SM" | "MD" | "LG"; 10 | } 11 | 12 | export default function SolanisAvatar({ 13 | hasBorder = true, 14 | size = "MD", 15 | }: SolanisAvatarProps) { 16 | const sizeClass = { 17 | SM: "min-h-10 min-w-10 h-12 w-12", 18 | MD: "min-h-12 min-w-12 h-14 w-14", 19 | LG: "min-h-14 min-w-14 h-16 w-16", 20 | }; 21 | 22 | return ( 23 |
26 | avatar 32 | 33 | solanis 34 | 35 |
36 | ); 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Solanis Team (caiodutra08 and gustavorteuber) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/components/ui/animated-shiny-text.tsx: -------------------------------------------------------------------------------- 1 | import type { CSSProperties, FC, ReactNode } from "react"; 2 | import { cn } from "@/lib/utils"; 3 | 4 | interface AnimatedShinyTextProps { 5 | children: ReactNode; 6 | className?: string; 7 | shimmerWidth?: number; 8 | } 9 | 10 | const AnimatedShinyText: FC = ({ 11 | children, 12 | className, 13 | shimmerWidth = 100, 14 | }) => { 15 | return ( 16 |

34 | {children} 35 |

36 | ); 37 | }; 38 | 39 | export default AnimatedShinyText; 40 | -------------------------------------------------------------------------------- /src/app/solanized/[username]/layout.tsx: -------------------------------------------------------------------------------- 1 | import Sidebar from "@/components/Sidebar"; 2 | import SolanisAvatar from "@/components/SolanisAvatar"; 3 | import { 4 | ResizableHandle, 5 | ResizablePanel, 6 | ResizablePanelGroup, 7 | } from "@/components/ui/resizable"; 8 | import Header from "@/components/Header"; 9 | import React from "react"; 10 | 11 | interface LayoutProps { 12 | children: React.ReactNode; 13 | params: { username: string }; 14 | } 15 | 16 | export default function Layout({ children, params }: LayoutProps) { 17 | return ( 18 | <> 19 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 |
31 |
{children}
32 |
33 |
34 |
35 | 36 | ); 37 | } 38 | -------------------------------------------------------------------------------- /react-graph-vis.d.ts: -------------------------------------------------------------------------------- 1 | declare module "react-graph-vis" { 2 | import { Network, NetworkEvents, Options, Node, Edge, DataSet } from "vis"; 3 | import { Component } from "react"; 4 | 5 | export { Network, NetworkEvents, Options, Node, Edge, DataSet } from "vis"; 6 | 7 | export interface graphEvents { 8 | [event: NetworkEvents]: (params?: any) => void; 9 | } 10 | 11 | //Doesn't appear that this module supports passing in a vis.DataSet directly. Once it does graph can just use the Data object from vis. 12 | export interface graphData { 13 | nodes: Node[]; 14 | edges: Edge[]; 15 | } 16 | 17 | export interface NetworkGraphProps { 18 | graph: graphData; 19 | options?: Options; 20 | events?: graphEvents; 21 | getNetwork?: (network: Network) => void; 22 | identifier?: string; 23 | style?: React.CSSProperties; 24 | getNodes?: (nodes: DataSet) => void; 25 | getEdges?: (edges: DataSet) => void; 26 | } 27 | 28 | export interface NetworkGraphState { 29 | identifier: string; 30 | } 31 | 32 | export default class NetworkGraph extends Component< 33 | NetworkGraphProps, 34 | NetworkGraphState 35 | > { 36 | render(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/components/ui/switch.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import * as SwitchPrimitives from "@radix-ui/react-switch" 5 | 6 | import { cn } from "@/lib/utils" 7 | 8 | const Switch = React.forwardRef< 9 | React.ElementRef, 10 | React.ComponentPropsWithoutRef 11 | >(({ className, ...props }, ref) => ( 12 | 20 | 25 | 26 | )) 27 | Switch.displayName = SwitchPrimitives.Root.displayName 28 | 29 | export { Switch } 30 | -------------------------------------------------------------------------------- /src/components/ui/badge.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { cva, type VariantProps } from "class-variance-authority"; 3 | 4 | import { cn } from "@/lib/utils"; 5 | 6 | const badgeVariants = cva( 7 | "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", 8 | { 9 | variants: { 10 | variant: { 11 | default: 12 | "border-transparent bg-primary text-primary-foreground hover:bg-primary/80", 13 | secondary: 14 | "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", 15 | destructive: 16 | "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80", 17 | outline: "text-foreground", 18 | }, 19 | }, 20 | defaultVariants: { 21 | variant: "default", 22 | }, 23 | }, 24 | ); 25 | 26 | export interface BadgeProps 27 | extends React.HTMLAttributes, 28 | VariantProps {} 29 | 30 | function Badge({ className, variant, ...props }: BadgeProps) { 31 | return ( 32 |
33 | ); 34 | } 35 | 36 | export { Badge, badgeVariants }; 37 | -------------------------------------------------------------------------------- /src/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from "next"; 2 | import { Inter } from "next/font/google"; 3 | import localFont from "next/font/local"; 4 | import "./globals.css"; 5 | 6 | import { ThemeProvider } from "@/contexts/theme-provider"; 7 | import { TooltipProvider } from "@/components/ui/tooltip"; 8 | import { EditorProvider } from "@/contexts/editor-provider"; 9 | const inter = Inter({ subsets: ["latin"] }); 10 | const helvetica_neue = localFont({ 11 | src: "./HelveticaNeue.woff2", 12 | display: "swap", 13 | variable: "--font-helvetica-neue", 14 | }); 15 | 16 | export const metadata: Metadata = { 17 | title: "Solanis - Escrita inteligente", 18 | description: "Solanis é um app de escrita e resumo de alto desempenho.", 19 | }; 20 | 21 | export default function RootLayout({ 22 | children, 23 | }: Readonly<{ 24 | children: React.ReactNode; 25 | }>) { 26 | return ( 27 | 28 | 31 | 32 | 33 | {children} 34 | 35 | 36 | 37 | 38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /src/components/ui/word-fade-in.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import type { Variants } from 'framer-motion' 4 | import { motion } from 'framer-motion' 5 | import { cn } from '@/lib/utils' 6 | 7 | interface WordFadeInProps { 8 | words: string 9 | className?: string 10 | delay?: number 11 | variants?: Variants 12 | } 13 | 14 | export function WordFadeIn({ 15 | words, 16 | delay = 0.15, 17 | variants = { 18 | hidden: { opacity: 0 }, 19 | visible: (i: any) => ({ 20 | y: 0, 21 | opacity: 1, 22 | transition: { delay: i * delay }, 23 | }), 24 | }, 25 | className, 26 | }: WordFadeInProps) { 27 | const _words = words.split(' ') 28 | 29 | return ( 30 | 39 | {_words.map((word, i) => ( 40 | 41 | {word} 42 | {' '} 43 | 44 | ))} 45 | 46 | ) 47 | } 48 | -------------------------------------------------------------------------------- /src/components/ui/staggered-fade.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { cn } from "@/lib/utils"; 4 | import { motion, useInView } from "framer-motion"; 5 | import * as React from "react"; 6 | 7 | type TextStaggeredFadeProps = { 8 | text: string; 9 | className?: string; 10 | }; 11 | 12 | export const StaggeredFade: React.FC = ({ 13 | text, 14 | className = "", 15 | }) => { 16 | const variants = { 17 | hidden: { opacity: 0 }, 18 | show: (i: number) => ({ 19 | y: 0, 20 | opacity: 1, 21 | transition: { delay: i * 0.07 }, 22 | }), 23 | }; 24 | 25 | const letters = text.split(""); 26 | const ref = React.useRef(null); 27 | const isInView = useInView(ref, { once: true }); 28 | 29 | return ( 30 | 41 | {letters.map((word, i) => ( 42 | 43 | {word} 44 | 45 | ))} 46 | 47 | ); 48 | }; 49 | -------------------------------------------------------------------------------- /src/components/AnnotationList.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import React from "react"; 4 | import Annotation from "@/components/Annotation"; 5 | import dynamicIconImports from "lucide-react/dynamicIconImports"; 6 | import { Plus } from "lucide-react"; 7 | import { AnnotationT } from "@/types/Annotation"; 8 | 9 | type Props = {}; 10 | 11 | export default function AnnotationList({}: Props) { 12 | const [annotations, setAnnotations] = React.useState([]); 13 | const icon = "box" as keyof typeof dynamicIconImports; 14 | 15 | const ButtonCreateAnnotation = () => { 16 | return ( 17 |
18 | 19 |

Criar nova anotação

20 |
21 | ); 22 | }; 23 | 24 | return ( 25 | <> 26 |
27 | {Array.from({ length: 3 }).map((_, index) => ( 28 | 36 | ))} 37 |
38 | 39 | 40 | ); 41 | } 42 | -------------------------------------------------------------------------------- /src/contexts/editor-provider.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { Dispatch, RefObject, createContext, useRef, useState } from "react"; 4 | import { EditorChange } from "codemirror"; 5 | 6 | interface EditorContextProps { 7 | markdown: string; 8 | setMarkdown: Dispatch>; 9 | titleRef: RefObject | null; 10 | onChange: (v: string, _chobj?: EditorChange) => void; 11 | onBlur: () => void; 12 | } 13 | 14 | interface EditorProviderProps { 15 | children: React.ReactNode; 16 | } 17 | 18 | const EditorContext = createContext( 19 | {} as EditorContextProps, 20 | ); 21 | 22 | const EditorProvider = ({ children }: EditorProviderProps) => { 23 | const [markdown, setMarkdown] = useState(""); 24 | const [lastTitleSaved, setLastTitleSaved] = useState("Untitled"); 25 | const titleRef = useRef(null); 26 | 27 | const onChange = (v: string, _chobj?: EditorChange) => { 28 | setMarkdown(v); 29 | }; 30 | 31 | const onBlur = () => { 32 | if (titleRef.current) { 33 | if (!titleRef.current.value) titleRef.current.value = lastTitleSaved; 34 | 35 | setLastTitleSaved(titleRef.current.value); 36 | } 37 | }; 38 | 39 | return ( 40 | 43 | {children} 44 | 45 | ); 46 | }; 47 | 48 | export { EditorContext, EditorProvider }; 49 | -------------------------------------------------------------------------------- /src/components/ModalCreateSummary.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import React from "react"; 4 | import { 5 | Dialog, 6 | DialogContent, 7 | DialogDescription, 8 | DialogTitle, 9 | } from "@/components/ui/dialog"; 10 | import { InputIcon } from "@/components/ui/input-icon"; 11 | import { PencilLine, Sparkles } from "lucide-react"; 12 | import { Button } from "@/components/ui/button"; 13 | 14 | type ModalCreateSummaryProps = { 15 | open: boolean; 16 | setOpen: (open: boolean) => void; 17 | }; 18 | 19 | export default function ModalCreateSummary({ 20 | open, 21 | setOpen, 22 | }: ModalCreateSummaryProps) { 23 | return ( 24 | 25 | 26 | 27 |

Crie um resumo

28 |

29 | Crie um resumo para um tópico de seu interesse 30 |

31 |
32 | 33 | 34 | 43 | 44 |
45 |
46 | ); 47 | } 48 | -------------------------------------------------------------------------------- /src/components/ui/bento-grid.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from "@/lib/utils"; 2 | 3 | export const BentoGrid = ({ 4 | className, 5 | children, 6 | }: { 7 | className?: string; 8 | children?: React.ReactNode; 9 | }) => { 10 | return ( 11 |
17 | {children} 18 |
19 | ); 20 | }; 21 | 22 | export const BentoGridItem = ({ 23 | className, 24 | title, 25 | description, 26 | header, 27 | icon, 28 | }: { 29 | className?: string; 30 | title?: string | React.ReactNode; 31 | description?: string | React.ReactNode; 32 | header?: React.ReactNode; 33 | icon?: React.ReactNode; 34 | }) => { 35 | return ( 36 |
42 | {header} 43 |
44 | {icon} 45 |
46 | {title} 47 |
48 |
49 | {description} 50 |
51 |
52 |
53 | ); 54 | }; 55 | -------------------------------------------------------------------------------- /src-tauri/tauri.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "beforeBuildCommand": "yarn build", 4 | "beforeDevCommand": "yarn dev", 5 | "devPath": "http://localhost:3000", 6 | "distDir": "../out" 7 | }, 8 | "package": { 9 | "productName": "Solanis", 10 | "version": "0.1.0" 11 | }, 12 | "tauri": { 13 | "allowlist": { 14 | "all": false 15 | }, 16 | "bundle": { 17 | "active": true, 18 | "category": "DeveloperTool", 19 | "copyright": "", 20 | "deb": { 21 | "depends": [] 22 | }, 23 | "externalBin": [], 24 | "icon": [ 25 | "icons/32x32.png", 26 | "icons/128x128.png", 27 | "icons/128x128@2x.png", 28 | "icons/icon.icns", 29 | "icons/icon.ico" 30 | ], 31 | "identifier": "com.seudominio.solanis", 32 | "longDescription": "", 33 | "macOS": { 34 | "entitlements": null, 35 | "exceptionDomain": "", 36 | "frameworks": [], 37 | "providerShortName": null, 38 | "signingIdentity": null 39 | }, 40 | "resources": [], 41 | "shortDescription": "", 42 | "targets": "all", 43 | "windows": { 44 | "certificateThumbprint": null, 45 | "digestAlgorithm": "sha256", 46 | "timestampUrl": "" 47 | } 48 | }, 49 | "security": { 50 | "csp": null 51 | }, 52 | "updater": { 53 | "active": false 54 | }, 55 | "windows": [ 56 | { 57 | "fullscreen": false, 58 | "height": 600, 59 | "resizable": true, 60 | "title": "Solanis", 61 | "width": 800 62 | } 63 | ] 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/components/ui/enchanced-separator.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from "@/lib/utils"; 2 | 3 | type SeparatorProps = { 4 | /** 5 | * @default "" 6 | */ 7 | label?: React.ReactNode; 8 | /** 9 | * @default false 10 | */ 11 | gradient?: boolean; 12 | className?: string; 13 | }; 14 | //====================================== 15 | export const EnchancedSeparator = ({ 16 | label, 17 | gradient = false, 18 | className = "", 19 | }: SeparatorProps) => { 20 | if (label) { 21 | return ( 22 |
23 |
32 |
33 | {label} 34 |
35 |
44 |
45 | ); 46 | } 47 | return ( 48 |
57 | ); 58 | }; 59 | -------------------------------------------------------------------------------- /src/components/ui/input-icon.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | 3 | import { cn } from "@/lib/utils"; 4 | import { LucideIcon } from "lucide-react"; 5 | 6 | export interface InputProps 7 | extends React.InputHTMLAttributes { 8 | startIcon?: LucideIcon; 9 | endIcon?: LucideIcon; 10 | } 11 | 12 | const InputIcon = React.forwardRef( 13 | ({ className, type, startIcon, endIcon, ...props }, ref) => { 14 | const StartIcon = startIcon; 15 | const EndIcon = endIcon; 16 | 17 | return ( 18 |
19 | 42 |
43 | ); 44 | }, 45 | ); 46 | InputIcon.displayName = "InputIcon"; 47 | 48 | export { InputIcon }; 49 | -------------------------------------------------------------------------------- /src/components/ui/tooltip.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as React from "react"; 4 | import * as TooltipPrimitive from "@radix-ui/react-tooltip"; 5 | 6 | import { cn } from "@/lib/utils"; 7 | 8 | const TooltipProvider = TooltipPrimitive.Provider; 9 | 10 | const Tooltip = TooltipPrimitive.Root; 11 | 12 | const TooltipTrigger = TooltipPrimitive.Trigger; 13 | 14 | const TooltipArrow = React.forwardRef< 15 | React.ElementRef, 16 | React.ComponentPropsWithoutRef 17 | >(({ className, ...props }, ref) => ( 18 | 26 | )); 27 | 28 | const TooltipContent = React.forwardRef< 29 | React.ElementRef, 30 | React.ComponentPropsWithoutRef 31 | >(({ className, sideOffset = 4, ...props }, ref) => ( 32 | 41 | )); 42 | TooltipContent.displayName = TooltipPrimitive.Content.displayName; 43 | 44 | export { 45 | Tooltip, 46 | TooltipTrigger, 47 | TooltipContent, 48 | TooltipProvider, 49 | TooltipArrow, 50 | }; 51 | -------------------------------------------------------------------------------- /src/components/Header.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { CommandDemo } from "./Command"; 4 | import { Button } from "./ui/button"; 5 | import * as React from "react"; 6 | import { Moon, Sun } from "lucide-react"; 7 | import { useTheme } from "next-themes"; 8 | import UserItem from "@/components/UserItem"; 9 | 10 | import { 11 | DropdownMenu, 12 | DropdownMenuContent, 13 | DropdownMenuItem, 14 | DropdownMenuTrigger, 15 | } from "@/components/ui/dropdown-menu"; 16 | 17 | export default function Header() { 18 | const { setTheme } = useTheme(); 19 | return ( 20 |
21 |
22 | 23 |
24 | 25 | 26 | 27 | 32 | 33 | 34 | setTheme("light")}> 35 | Light 36 | 37 | setTheme("dark")}> 38 | Dark 39 | 40 | setTheme("system")}> 41 | System 42 | 43 | 44 | 45 |
46 |
47 |
48 | ); 49 | } 50 | -------------------------------------------------------------------------------- /src/components/ui/resizable.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { GripVertical } from "lucide-react"; 4 | import * as ResizablePrimitive from "react-resizable-panels"; 5 | 6 | import { cn } from "@/lib/utils"; 7 | 8 | const ResizablePanelGroup = ({ 9 | className, 10 | ...props 11 | }: React.ComponentProps) => ( 12 | 19 | ); 20 | 21 | const ResizablePanel = ResizablePrimitive.Panel; 22 | 23 | const ResizableHandle = ({ 24 | withHandle, 25 | className, 26 | ...props 27 | }: React.ComponentProps & { 28 | withHandle?: boolean; 29 | }) => ( 30 | div]:rotate-90", 33 | className, 34 | )} 35 | {...props} 36 | > 37 | {withHandle && ( 38 |
39 | 40 |
41 | )} 42 |
43 | ); 44 | 45 | export { ResizablePanelGroup, ResizablePanel, ResizableHandle }; 46 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bucetisian", 3 | "version": "0.1.0", 4 | "type": "module", 5 | "private": true, 6 | "scripts": { 7 | "dev": "next dev", 8 | "build": "next build", 9 | "start": "next start", 10 | "lint": "next lint", 11 | "prettier": "prettier --write ." 12 | }, 13 | "dependencies": { 14 | "@anthropic-ai/sdk": "^0.24.0", 15 | "@icons-pack/react-simple-icons": "^9.6.0", 16 | "@radix-ui/react-dialog": "^1.1.1", 17 | "@radix-ui/react-dropdown-menu": "^2.1.1", 18 | "@radix-ui/react-hover-card": "^1.1.1", 19 | "@radix-ui/react-label": "^2.1.0", 20 | "@radix-ui/react-select": "^2.1.1", 21 | "@radix-ui/react-separator": "^1.1.0", 22 | "@radix-ui/react-slot": "^1.1.0", 23 | "@radix-ui/react-switch": "^1.1.0", 24 | "@radix-ui/react-tabs": "^1.1.0", 25 | "@radix-ui/react-tooltip": "^1.1.1", 26 | "@tanstack/react-table": "^8.19.2", 27 | "class-variance-authority": "^0.7.0", 28 | "clsx": "^2.1.1", 29 | "cmdk": "^1.0.0", 30 | "easymde": "^2.18.0", 31 | "framer-motion": "^11.3.2", 32 | "gridstack": "^10.3.0", 33 | "jotai": "^2.8.4", 34 | "loadash": "^1.0.0", 35 | "lucide-react": "^0.396.0", 36 | "mini-svg-data-uri": "^1.4.4", 37 | "next": "14.2.4", 38 | "next-themes": "^0.3.0", 39 | "qss": "^3.0.0", 40 | "react": "^18", 41 | "react-dom": "^18", 42 | "react-draggable": "^4.4.6", 43 | "react-graph-vis": "^1.0.7", 44 | "react-resizable-panels": "^2.0.19", 45 | "react-simplemde-editor": "^5.2.0", 46 | "tailwind-merge": "^2.4.0", 47 | "tailwindcss-animate": "^1.0.7", 48 | "uuid": "^10.0.0" 49 | }, 50 | "devDependencies": { 51 | "@types/node": "^20", 52 | "@types/react": "^18.3.3", 53 | "@types/react-dom": "^18", 54 | "@types/uuid": "^10.0.0", 55 | "@types/vis": "^4.21.27", 56 | "eslint": "^8", 57 | "eslint-config-next": "14.2.4", 58 | "postcss": "^8", 59 | "prettier": "^3.3.2", 60 | "tailwindcss": "^3.4.1", 61 | "typescript": "^5" 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/components/ui/gradient-text.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { cva, type VariantProps } from "class-variance-authority"; 3 | 4 | import { cn } from "@/lib/utils"; 5 | 6 | const textVariants = cva("tracking-tight bg-clip-text text-transparent", { 7 | variants: { 8 | variant: { 9 | default: 10 | "bg-gradient-to-t from-neutral-700 to-neutral-800 dark:from-stone-200 dark:to-neutral-200", 11 | pink: "bg-gradient-to-t from-accent to-accent/90 dark:from-stone-200 dark:to-neutral-200", 12 | light: "bg-gradient-to-t from-neutral-200 to-neutral-300", 13 | secondary: "bg-gradient-to-t from-primary-foreground to-muted-foreground", 14 | }, 15 | size: { 16 | default: "text-base", 17 | xs: "text-xs", 18 | sm: "text-sm", 19 | md: "text-md", 20 | lg: "text-lg", 21 | xl: "text-xl", 22 | }, 23 | weight: { 24 | default: "font-medium", 25 | thin: "font-thin", 26 | semi: "font-semibold", 27 | bold: "font-bold", 28 | black: "font-black", 29 | }, 30 | }, 31 | defaultVariants: { 32 | variant: "default", 33 | size: "default", 34 | weight: "default", 35 | }, 36 | }); 37 | 38 | export interface GradientTextProps extends VariantProps { 39 | children: React.ReactNode; 40 | className?: string; 41 | } 42 | 43 | const GradientText = React.forwardRef( 44 | ({ variant, weight, size, className, children, ...props }, ref) => { 45 | return ( 46 | 51 | {children} 52 | 53 | ); 54 | }, 55 | ); 56 | 57 | GradientText.displayName = "GradientText"; 58 | 59 | export type Variant = "default" | "pink" | "light" | "secondary"; 60 | export type Size = "default" | "sm" | "md" | "lg" | "xl"; 61 | export type Weight = "default" | "thin" | "base" | "semi" | "bold" | "black"; 62 | 63 | export { GradientText, textVariants }; 64 | -------------------------------------------------------------------------------- /src/components/ui/tabs.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import * as TabsPrimitive from "@radix-ui/react-tabs" 5 | 6 | import { cn } from "@/lib/utils" 7 | 8 | const Tabs = TabsPrimitive.Root 9 | 10 | const TabsList = React.forwardRef< 11 | React.ElementRef, 12 | React.ComponentPropsWithoutRef 13 | >(({ className, ...props }, ref) => ( 14 | 22 | )) 23 | TabsList.displayName = TabsPrimitive.List.displayName 24 | 25 | const TabsTrigger = React.forwardRef< 26 | React.ElementRef, 27 | React.ComponentPropsWithoutRef 28 | >(({ className, ...props }, ref) => ( 29 | 37 | )) 38 | TabsTrigger.displayName = TabsPrimitive.Trigger.displayName 39 | 40 | const TabsContent = React.forwardRef< 41 | React.ElementRef, 42 | React.ComponentPropsWithoutRef 43 | >(({ className, ...props }, ref) => ( 44 | 52 | )) 53 | TabsContent.displayName = TabsPrimitive.Content.displayName 54 | 55 | export { Tabs, TabsList, TabsTrigger, TabsContent } 56 | -------------------------------------------------------------------------------- /src/components/Annotation.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import React, { Suspense } from "react"; 4 | import { Button } from "@/components/ui/button"; 5 | import { LoaderCircle, PencilLine } from "lucide-react"; 6 | import { 7 | Tooltip, 8 | TooltipContent, 9 | TooltipTrigger, 10 | } from "@/components/ui/tooltip"; 11 | import { Badge } from "@/components/ui/badge"; 12 | import DynamicIcon from "@/components/DynamicIcon"; 13 | import { AnnotationT } from "@/types/Annotation"; 14 | 15 | export default function Annotation({ 16 | icon, 17 | title, 18 | description, 19 | tags, 20 | lastUpdate, 21 | }: AnnotationT) { 22 | const renderTags = () => { 23 | return tags.map((tag, index) => ( 24 | 25 | {tag} 26 | 27 | )); 28 | }; 29 | 30 | return ( 31 |
32 |
33 |
34 | } 36 | > 37 | 42 | 43 |
44 |

{title}

45 | 51 |
52 |
53 | 54 | 55 | {tags.length} Tags 56 | 57 | 58 |
59 | {renderTags()} 60 |
61 |
62 |
63 |

{lastUpdate}

64 |
65 |
66 | ); 67 | } 68 | -------------------------------------------------------------------------------- /src/components/ui/card.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | 3 | import { cn } from "@/lib/utils"; 4 | 5 | const Card = React.forwardRef< 6 | HTMLDivElement, 7 | React.HTMLAttributes 8 | >(({ className, ...props }, ref) => ( 9 |
17 | )); 18 | Card.displayName = "Card"; 19 | 20 | const CardHeader = React.forwardRef< 21 | HTMLDivElement, 22 | React.HTMLAttributes 23 | >(({ className, ...props }, ref) => ( 24 |
29 | )); 30 | CardHeader.displayName = "CardHeader"; 31 | 32 | const CardTitle = React.forwardRef< 33 | HTMLParagraphElement, 34 | React.HTMLAttributes 35 | >(({ className, ...props }, ref) => ( 36 |

44 | )); 45 | CardTitle.displayName = "CardTitle"; 46 | 47 | const CardDescription = React.forwardRef< 48 | HTMLParagraphElement, 49 | React.HTMLAttributes 50 | >(({ className, ...props }, ref) => ( 51 |

56 | )); 57 | CardDescription.displayName = "CardDescription"; 58 | 59 | const CardContent = React.forwardRef< 60 | HTMLDivElement, 61 | React.HTMLAttributes 62 | >(({ className, ...props }, ref) => ( 63 |

64 | )); 65 | CardContent.displayName = "CardContent"; 66 | 67 | const CardFooter = React.forwardRef< 68 | HTMLDivElement, 69 | React.HTMLAttributes 70 | >(({ className, ...props }, ref) => ( 71 |
76 | )); 77 | CardFooter.displayName = "CardFooter"; 78 | 79 | export { 80 | Card, 81 | CardHeader, 82 | CardFooter, 83 | CardTitle, 84 | CardDescription, 85 | CardContent, 86 | }; 87 | -------------------------------------------------------------------------------- /src/components/Footer.tsx: -------------------------------------------------------------------------------- 1 | import { LinkedinIcon } from "lucide-react"; 2 | import Link from "next/link"; 3 | import { SiGithub, SiX } from "@icons-pack/react-simple-icons" 4 | 5 | export default function Footer() { 6 | return ( 7 |
8 |
9 |
10 | 11 | Solanis 12 | 13 |

14 | An AI-powered markdown generator to help you create beautiful 15 | content with ease. 16 |

17 |
18 |
19 |

Connect

20 |
21 | 26 | 27 | 28 | 33 | 34 | 35 | 40 | 41 | 42 |
43 |
44 |
45 |

Legal

46 | 51 | Terms of Service 52 | 53 | 58 | Privacy Policy 59 | 60 |
61 |
62 |
63 | ); 64 | } 65 | -------------------------------------------------------------------------------- /src/app/(lp-pages)/register/page.tsx: -------------------------------------------------------------------------------- 1 | import { Button } from "@/components/ui/button"; 2 | import { GradientHeading } from "@/components/ui/gradient-heading"; 3 | import { Input } from "@/components/ui/input"; 4 | import Image from "next/image"; 5 | import Link from "next/link"; 6 | 7 | export default function CreateAccountPage() { 8 | return ( 9 |
10 |
11 |
12 | avatar 19 | 20 | solanis 21 | 22 |
23 |
24 |
25 | 26 | Registrar! 27 | 28 |

29 | Já tem uma conta?{" "} 30 | 31 | Faça o Login 32 | 33 |

34 |
35 |
36 |
37 | 38 | 39 | 40 | 43 |
44 |
45 |
46 |
47 |
48 |
49 |

50 | Olá! Por favor insira seus dados para criar sua conta. 51 |

52 |

53 | Você sabia que com o solanis você pode criar e compartilhar suas 54 | anotações de forma simples e rápida? 55 |

56 |
57 |
58 |
59 |
60 |
61 |
62 | ); 63 | } 64 | -------------------------------------------------------------------------------- /src/components/ui/gradient-heading.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Slot } from "@radix-ui/react-slot"; 3 | import { cva, type VariantProps } from "class-variance-authority"; 4 | 5 | import { cn } from "@/lib/utils"; 6 | 7 | const headingVariants = cva( 8 | "tracking-tight pb-3 bg-clip-text text-transparent", 9 | { 10 | variants: { 11 | variant: { 12 | default: 13 | "bg-gradient-to-t from-neutral-700 to-neutral-800 dark:from-stone-200 dark:to-neutral-200", 14 | pink: "bg-gradient-to-t from-accent to-accent/90 dark:from-stone-200 dark:to-neutral-200", 15 | light: "bg-gradient-to-t from-neutral-200 to-neutral-300", 16 | solanis: "bg-gradient-to-t from-primary to-[#8c74ff]/60", 17 | secondary: 18 | "bg-gradient-to-t from-primary-foreground to-muted-foreground", 19 | }, 20 | size: { 21 | default: "text-2xl sm:text-3xl lg:text-4xl", 22 | xxs: "text-base sm:text-lg lg:text-lg", 23 | xs: "text-lg sm:text-xl lg:text-2xl", 24 | sm: "text-xl sm:text-2xl lg:text-3xl", 25 | md: "text-2xl sm:text-3xl lg:text-4xl", 26 | lg: "text-3xl sm:text-4xl lg:text-5xl", 27 | xl: "text-4xl sm:text-5xl lg:text-6xl", 28 | xxl: "text-5xl sm:text-6xl lg:text-[6rem]", 29 | xxxl: "text-5xl sm:text-6xl lg:text-[8rem]", 30 | }, 31 | weight: { 32 | default: "font-bold", 33 | thin: "font-thin", 34 | base: "font-base", 35 | semi: "font-semibold", 36 | bold: "font-bold", 37 | black: "font-black", 38 | }, 39 | }, 40 | defaultVariants: { 41 | variant: "default", 42 | size: "default", 43 | weight: "default", 44 | }, 45 | }, 46 | ); 47 | 48 | export interface HeadingProps extends VariantProps { 49 | asChild?: boolean; 50 | children: React.ReactNode; 51 | className?: string; 52 | } 53 | 54 | const GradientHeading = React.forwardRef( 55 | ({ asChild, variant, weight, size, className, children, ...props }, ref) => { 56 | const Comp = asChild ? Slot : "h3"; // default to 'h3' if not a child 57 | return ( 58 | 59 | 60 | {children} 61 | 62 | 63 | ); 64 | }, 65 | ); 66 | 67 | GradientHeading.displayName = "GradientHeading"; 68 | 69 | // Manually define the variant types 70 | export type Variant = "default" | "pink" | "light" | "secondary"; 71 | export type Size = 72 | | "default" 73 | | "xxs" 74 | | "xs" 75 | | "sm" 76 | | "md" 77 | | "lg" 78 | | "xl" 79 | | "xxl" 80 | | "xxxl"; 81 | export type Weight = "default" | "thin" | "base" | "semi" | "bold" | "black"; 82 | 83 | export { GradientHeading, headingVariants }; 84 | -------------------------------------------------------------------------------- /src/hooks/useAnthropic.ts: -------------------------------------------------------------------------------- 1 | import Anthropic from "@anthropic-ai/sdk"; 2 | 3 | const anthropicPrompts = { 4 | briefing: 5 | "You are tasked with creating a comprehensive briefing on a given subject. Your goal is to provide an informative and well-structured overview of the topic, supported by credible sources.\n\nThe subject of the briefing is:\n\n{{SUBJECT}}\n\n\nFollow these steps to create your briefing:\n\n1. Research: Gather information from reputable sources such as academic journals, respected news outlets, official websites, and expert opinions. Aim to find a diverse range of perspectives on the subject.\n\n2. Analyze: Critically evaluate the information you've gathered. Look for consensus among experts, identify any controversies or debates, and note any significant recent developments.\n\n3. Organize: Structure your briefing logically. Typically, this should include:\n a. An introduction that provides context and outlines the scope of the briefing\n b. Main body sections that cover key aspects of the subject\n c. A conclusion that summarizes the main points and, if appropriate, looks at future implications or unanswered questions\n\n4. Write: Compose your briefing in clear, concise language. Avoid jargon unless it's necessary, and explain any technical terms you use.\n\n5. Cite sources: For each piece of information you include, note the source. Use a consistent citation format throughout your briefing.\n\n6. Review and refine: After completing your draft, review it for clarity, coherence, and accuracy. Make any necessary revisions.\n\nPresent your final briefing as a Markdown document.\n\n For example:\n\n#[Title here] [Your introduction here] ##[Section title here]: [Content from the section here] >[Source details here] ###[Conclusion title]: [Your conclusion here] \n\nRemember to maintain objectivity throughout your briefing. Your goal is to inform, not to argue for a particular position. If the subject is controversial, present multiple viewpoints fairly.", 6 | }; 7 | 8 | export default function useAnthropic() { 9 | const domain = window?.location?.origin || ""; 10 | 11 | const anthropic = new Anthropic({ 12 | apiKey: process.env.ANTHROPIC_API_KEY, 13 | baseURL: domain + "/anthropic/", 14 | }); 15 | 16 | const anthropicStream = (subject: string) => 17 | anthropic.messages.stream({ 18 | model: "claude-3-5-sonnet-20240620", 19 | max_tokens: 1024, 20 | temperature: 0, 21 | messages: [ 22 | { 23 | role: "user", 24 | content: [ 25 | { 26 | type: "text", 27 | text: anthropicPrompts["briefing"].replace( 28 | "{{SUBJECT}}", 29 | subject, 30 | ), 31 | }, 32 | ], 33 | }, 34 | ], 35 | stream: true, 36 | }); 37 | return { 38 | anthropic, 39 | anthropicStream, 40 | }; 41 | } 42 | -------------------------------------------------------------------------------- /src/app/(lp-pages)/login/page.tsx: -------------------------------------------------------------------------------- 1 | import { Button } from "@/components/ui/button"; 2 | import { GradientHeading } from "@/components/ui/gradient-heading"; 3 | import { Input } from "@/components/ui/input"; 4 | import Image from "next/image"; 5 | import Link from "next/link"; 6 | 7 | export default function LoginPage() { 8 | return ( 9 |
10 |
11 |
12 | avatar 19 | 20 | solanis 21 | 22 |
23 |
24 |
25 | 26 | Entrar! 27 | 28 |

29 | Não tem uma conta?{" "} 30 | 34 | Registre-se 35 | 36 |

37 |
38 |
39 |
40 | 41 |
42 | 43 | 47 | Esqueceu sua senha? 48 | 49 |
50 |
51 | 54 |
55 |
56 |
57 |
58 |
59 |

60 | Olá! Por favor faça login em sua conta. 61 |

62 |

63 | Você sabia que com a solanis você pode criar resumos acadêmicos 64 | diretamente com IA? 65 |

66 |
67 |
68 |
69 |
70 |
71 |
72 | ); 73 | } 74 | -------------------------------------------------------------------------------- /src/components/ui/container-scroll-animation.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import React, { useRef } from "react"; 3 | import { useScroll, useTransform, motion, MotionValue } from "framer-motion"; 4 | 5 | export const ContainerScroll = ({ 6 | titleComponent, 7 | children, 8 | }: { 9 | titleComponent: string | React.ReactNode; 10 | children: React.ReactNode; 11 | }) => { 12 | const containerRef = useRef(null); 13 | const { scrollYProgress } = useScroll({ 14 | target: containerRef, 15 | }); 16 | const [isMobile, setIsMobile] = React.useState(false); 17 | 18 | React.useEffect(() => { 19 | const checkMobile = () => { 20 | setIsMobile(window.innerWidth <= 768); 21 | }; 22 | checkMobile(); 23 | window.addEventListener("resize", checkMobile); 24 | return () => { 25 | window.removeEventListener("resize", checkMobile); 26 | }; 27 | }, []); 28 | 29 | const scaleDimensions = () => { 30 | return isMobile ? [0.7, 0.9] : [1.05, 1]; 31 | }; 32 | 33 | const rotate = useTransform(scrollYProgress, [0, 1], [20, 0]); 34 | const scale = useTransform(scrollYProgress, [0, 1], scaleDimensions()); 35 | const translate = useTransform(scrollYProgress, [0, 1], [0, -100]); 36 | 37 | return ( 38 |
42 |
48 |
49 | 50 | {children} 51 | 52 |
53 |
54 | ); 55 | }; 56 | 57 | export const Header = ({ translate, titleComponent }: any) => { 58 | return ( 59 | 65 | {titleComponent} 66 | 67 | ); 68 | }; 69 | 70 | export const Card = ({ 71 | rotate, 72 | scale, 73 | children, 74 | }: { 75 | rotate: MotionValue; 76 | scale: MotionValue; 77 | translate: MotionValue; 78 | children: React.ReactNode; 79 | }) => { 80 | return ( 81 | 90 |
91 | {children} 92 |
93 |
94 | ); 95 | }; 96 | -------------------------------------------------------------------------------- /src/components/Editor.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { EditorContext } from "@/contexts/editor-provider"; 4 | import useAnthropic from "@/hooks/useAnthropic"; 5 | import { useCallback, useContext, useEffect, useMemo } from "react"; 6 | import "easymde/dist/easymde.min.css"; 7 | import SimpleMDE from "react-simplemde-editor"; 8 | import { Input } from "./ui/input"; 9 | import { ChevronRight, Sparkles } from "lucide-react"; 10 | import { Button } from "./ui/button"; 11 | 12 | const mdeOptions = { minHeight: "100%" }; 13 | 14 | export default function Editor({ isDemo = false }: { isDemo?: boolean }) { 15 | const { titleRef, onChange, markdown, setMarkdown } = 16 | useContext(EditorContext); 17 | const { anthropicStream } = useAnthropic(); 18 | 19 | const memoMdeOptions = useMemo(() => mdeOptions, []); 20 | 21 | const callStream = async () => { 22 | const title = titleRef?.current?.value || "Untitled"; 23 | anthropicStream(title).on("text", (text: string) => { 24 | setMarkdown((prev: string) => prev + text); 25 | }); 26 | }; 27 | 28 | useEffect(() => { 29 | if (titleRef?.current) { 30 | titleRef.current.value = ""; 31 | } 32 | }, []); 33 | 34 | return ( 35 | <> 36 | 40 |
46 | 52 | 64 |
65 | 71 | 72 | ); 73 | } 74 | -------------------------------------------------------------------------------- /src/components/ui/breadcrumb.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { Slot } from "@radix-ui/react-slot"; 3 | import { ChevronRight, MoreHorizontal } from "lucide-react"; 4 | 5 | import { cn } from "@/lib/utils"; 6 | 7 | const Breadcrumb = React.forwardRef< 8 | HTMLElement, 9 | React.ComponentPropsWithoutRef<"nav"> & { 10 | separator?: React.ReactNode; 11 | } 12 | >(({ ...props }, ref) =>