diff --git a/next.config.js b/next.config.js index 898b289..93718cc 100644 --- a/next.config.js +++ b/next.config.js @@ -5,11 +5,6 @@ const nextConfig = { images: { unoptimized: true, }, - typescript: { - // TypeScript incorrectly flags CSS imports as errors in Next.js - // This is a known issue: https://github.com/vercel/next.js/issues/54282 - ignoreBuildErrors: true, - }, experimental: { optimizePackageImports: ['@radix-ui/react-icons', '@phosphor-icons/react'], turbopackScopeHoisting: false, diff --git a/src/app/globals.scss b/src/app/globals.scss index 12de7d6..77d6958 100644 --- a/src/app/globals.scss +++ b/src/app/globals.scss @@ -1,17 +1,18 @@ -@import '../styles/abstracts'; -@import '../styles/utilities/utilities'; -@import './theme.scss'; +@use '../styles/abstracts' as *; +@use '../styles/abstracts/variables' as vars; +@use '../styles/utilities/utilities'; +@use './theme.scss'; * { margin: 0; padding: 0; box-sizing: border-box; - border-color: $border; + border-color: vars.$border; } body { - background: $background; - color: $foreground; + background: vars.$background; + color: vars.$foreground; font-family: var(--font-inter), 'Inter', sans-serif; line-height: 1.5; } diff --git a/src/components/ui/calendar.tsx b/src/components/ui/calendar.tsx deleted file mode 100644 index 426ef4c..0000000 --- a/src/components/ui/calendar.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import { ComponentProps } from "react" -import ChevronLeft from "lucide-react/dist/esm/icons/chevron-left" -import ChevronRight from "lucide-react/dist/esm/icons/chevron-right" -import { DayPicker } from "react-day-picker" - -import { cn } from "@/lib/utils" -import { buttonVariants } from "@/components/ui/button" - -function Calendar({ - className, - classNames, - showOutsideDays = true, - ...props -}: ComponentProps) { - return ( - .day-range-end)]:rounded-r-md [&:has(>.day-range-start)]:rounded-l-md first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md" - : "[&:has([aria-selected])]:rounded-md" - ), - day: cn( - buttonVariants({ variant: "ghost" }), - "size-8 p-0 font-normal aria-selected:opacity-100" - ), - day_range_start: - "day-range-start aria-selected:bg-primary aria-selected:text-primary-foreground", - day_range_end: - "day-range-end aria-selected:bg-primary aria-selected:text-primary-foreground", - day_selected: - "bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground", - day_today: "bg-accent text-accent-foreground", - day_outside: - "day-outside text-muted-foreground aria-selected:text-muted-foreground", - day_disabled: "text-muted-foreground opacity-50", - day_range_middle: - "aria-selected:bg-accent aria-selected:text-accent-foreground", - day_hidden: "invisible", - ...classNames, - }} - components={{ - PreviousMonthButton: ({ className, ...props }) => ( - - ), - NextMonthButton: ({ className, ...props }) => ( - - ), - }} - {...props} - /> - ) -} - -export { Calendar } diff --git a/src/components/ui/command.tsx b/src/components/ui/command.tsx deleted file mode 100644 index 07eefef..0000000 --- a/src/components/ui/command.tsx +++ /dev/null @@ -1,177 +0,0 @@ -"use client" - -import { ComponentProps } from "react" -import { Command as CommandPrimitive } from "cmdk" -import SearchIcon from "lucide-react/dist/esm/icons/search" - -import { cn } from "@/lib/utils" -import { - Dialog, - DialogContent, - DialogDescription, - DialogHeader, - DialogTitle, -} from "@/components/ui/dialog" - -function Command({ - className, - ...props -}: ComponentProps) { - return ( - - ) -} - -function CommandDialog({ - title = "Command Palette", - description = "Search for a command to run...", - children, - ...props -}: ComponentProps & { - title?: string - description?: string -}) { - return ( - - - {title} - {description} - - - - {children} - - - - ) -} - -function CommandInput({ - className, - ...props -}: ComponentProps) { - return ( -
- - -
- ) -} - -function CommandList({ - className, - ...props -}: ComponentProps) { - return ( - - ) -} - -function CommandEmpty({ - ...props -}: ComponentProps) { - return ( - - ) -} - -function CommandGroup({ - className, - ...props -}: ComponentProps) { - return ( - - ) -} - -function CommandSeparator({ - className, - ...props -}: ComponentProps) { - return ( - - ) -} - -function CommandItem({ - className, - ...props -}: ComponentProps) { - return ( - - ) -} - -function CommandShortcut({ - className, - ...props -}: ComponentProps<"span">) { - return ( - - ) -} - -export { - Command, - CommandDialog, - CommandInput, - CommandList, - CommandEmpty, - CommandGroup, - CommandItem, - CommandShortcut, - CommandSeparator, -} diff --git a/src/components/ui/drawer.tsx b/src/components/ui/drawer.tsx deleted file mode 100644 index 37fbeda..0000000 --- a/src/components/ui/drawer.tsx +++ /dev/null @@ -1,130 +0,0 @@ -import { ComponentProps } from "react" -import { Drawer as DrawerPrimitive } from "vaul" - -import { cn } from "@/lib/utils" - -function Drawer({ - ...props -}: ComponentProps) { - return -} - -function DrawerTrigger({ - ...props -}: ComponentProps) { - return -} - -function DrawerPortal({ - ...props -}: ComponentProps) { - return -} - -function DrawerClose({ - ...props -}: ComponentProps) { - return -} - -function DrawerOverlay({ - className, - ...props -}: ComponentProps) { - return ( - - ) -} - -function DrawerContent({ - className, - children, - ...props -}: ComponentProps) { - return ( - - - -
- {children} - - - ) -} - -function DrawerHeader({ className, ...props }: ComponentProps<"div">) { - return ( -
- ) -} - -function DrawerFooter({ className, ...props }: ComponentProps<"div">) { - return ( -
- ) -} - -function DrawerTitle({ - className, - ...props -}: ComponentProps) { - return ( - - ) -} - -function DrawerDescription({ - className, - ...props -}: ComponentProps) { - return ( - - ) -} - -export { - Drawer, - DrawerPortal, - DrawerOverlay, - DrawerTrigger, - DrawerClose, - DrawerContent, - DrawerHeader, - DrawerFooter, - DrawerTitle, - DrawerDescription, -} diff --git a/src/components/ui/input-otp.tsx b/src/components/ui/input-otp.tsx deleted file mode 100644 index dd69e58..0000000 --- a/src/components/ui/input-otp.tsx +++ /dev/null @@ -1,77 +0,0 @@ -"use client" - -import { ComponentProps, useContext } from "react" -import { OTPInput, OTPInputContext } from "input-otp" -import MinusIcon from "lucide-react/dist/esm/icons/minus" - -import { cn } from "@/lib/utils" - -function InputOTP({ - className, - containerClassName, - ...props -}: ComponentProps & { - containerClassName?: string -}) { - return ( - - ) -} - -function InputOTPGroup({ className, ...props }: ComponentProps<"div">) { - return ( -
- ) -} - -function InputOTPSlot({ - index, - className, - ...props -}: ComponentProps<"div"> & { - index: number -}) { - const inputOTPContext = useContext(OTPInputContext) - const { char, hasFakeCaret, isActive } = inputOTPContext?.slots[index] ?? {} - - return ( -
- {char} - {hasFakeCaret && ( -
-
-
- )} -
- ) -} - -function InputOTPSeparator({ ...props }: ComponentProps<"div">) { - return ( -
- -
- ) -} - -export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator } diff --git a/src/scss.d.ts b/src/scss.d.ts new file mode 100644 index 0000000..bd1067e --- /dev/null +++ b/src/scss.d.ts @@ -0,0 +1,4 @@ +declare module '*.scss' { + const content: Record; + export default content; +} diff --git a/src/styles/abstracts/_functions.scss b/src/styles/abstracts/_functions.scss index 9408614..2d7f07a 100644 --- a/src/styles/abstracts/_functions.scss +++ b/src/styles/abstracts/_functions.scss @@ -1,24 +1,27 @@ +@use 'sass:map'; +@use './variables' as vars; + // Spacing function @function spacing($key) { - @return map-get($spacing, $key); + @return map.get(vars.$spacing, $key); } // Border radius function @function radius($key) { - @return map-get($radius, $key); + @return map.get(vars.$radius, $key); } // Font size function @function font-size($key) { - @return map-get($font-sizes, $key); + @return map.get(vars.$font-sizes, $key); } // Font weight function @function font-weight($key) { - @return map-get($font-weights, $key); + @return map.get(vars.$font-weights, $key); } // Breakpoint function @function breakpoint($key) { - @return map-get($breakpoints, $key); + @return map.get(vars.$breakpoints, $key); } diff --git a/src/styles/abstracts/_index.scss b/src/styles/abstracts/_index.scss index 115e2ad..d4e0105 100644 --- a/src/styles/abstracts/_index.scss +++ b/src/styles/abstracts/_index.scss @@ -1,3 +1,3 @@ -@import './variables'; -@import './functions'; -@import './mixins'; +@forward './variables'; +@forward './functions'; +@forward './mixins'; diff --git a/src/styles/abstracts/_mixins.scss b/src/styles/abstracts/_mixins.scss index 99d06c7..1d495f5 100644 --- a/src/styles/abstracts/_mixins.scss +++ b/src/styles/abstracts/_mixins.scss @@ -1,3 +1,6 @@ +@use './functions' as fn; +@use './variables' as vars; + // Flexbox mixins @mixin flex($direction: row, $justify: flex-start, $align: stretch, $wrap: nowrap) { display: flex; @@ -20,7 +23,7 @@ } // Grid mixin -@mixin grid($columns: 1, $gap: spacing(4)) { +@mixin grid($columns: 1, $gap: fn.spacing(4)) { display: grid; grid-template-columns: repeat($columns, 1fr); gap: $gap; @@ -28,87 +31,87 @@ // Spacing mixins @mixin p($value) { - padding: spacing($value); + padding: fn.spacing($value); } @mixin px($value) { - padding-left: spacing($value); - padding-right: spacing($value); + padding-left: fn.spacing($value); + padding-right: fn.spacing($value); } @mixin py($value) { - padding-top: spacing($value); - padding-bottom: spacing($value); + padding-top: fn.spacing($value); + padding-bottom: fn.spacing($value); } @mixin pt($value) { - padding-top: spacing($value); + padding-top: fn.spacing($value); } @mixin pr($value) { - padding-right: spacing($value); + padding-right: fn.spacing($value); } @mixin pb($value) { - padding-bottom: spacing($value); + padding-bottom: fn.spacing($value); } @mixin pl($value) { - padding-left: spacing($value); + padding-left: fn.spacing($value); } @mixin m($value) { - margin: spacing($value); + margin: fn.spacing($value); } @mixin mx($value) { - margin-left: spacing($value); - margin-right: spacing($value); + margin-left: fn.spacing($value); + margin-right: fn.spacing($value); } @mixin my($value) { - margin-top: spacing($value); - margin-bottom: spacing($value); + margin-top: fn.spacing($value); + margin-bottom: fn.spacing($value); } @mixin mt($value) { - margin-top: spacing($value); + margin-top: fn.spacing($value); } @mixin mr($value) { - margin-right: spacing($value); + margin-right: fn.spacing($value); } @mixin mb($value) { - margin-bottom: spacing($value); + margin-bottom: fn.spacing($value); } @mixin ml($value) { - margin-left: spacing($value); + margin-left: fn.spacing($value); } // Gap mixin @mixin gap($value) { - gap: spacing($value); + gap: fn.spacing($value); } // Border radius mixin @mixin rounded($value: base) { - border-radius: radius($value); + border-radius: fn.radius($value); } // Typography mixins @mixin text($size) { - font-size: font-size($size); + font-size: fn.font-size($size); } @mixin font($weight) { - font-weight: font-weight($weight); + font-weight: fn.font-weight($weight); } // Responsive breakpoint mixin @mixin respond-to($breakpoint) { - $size: breakpoint($breakpoint); + $size: fn.breakpoint($breakpoint); @media (min-width: $size) { @content; } @@ -124,7 +127,7 @@ display: inline-flex; align-items: center; justify-content: center; - gap: spacing(2); + gap: fn.spacing(2); cursor: pointer; transition: all 0.2s ease; border: none; @@ -138,9 +141,9 @@ // Card mixin @mixin card { - background: $card; - color: $card-foreground; - border: 1px solid $border; + background: vars.$card; + color: vars.$card-foreground; + border: 1px solid vars.$border; @include rounded(lg); @include p(6); } @@ -206,7 +209,7 @@ // Focus ring @mixin focus-ring { &:focus-visible { - outline: 2px solid $ring; + outline: 2px solid vars.$ring; outline-offset: 2px; } } diff --git a/src/styles/abstracts/_variables.scss b/src/styles/abstracts/_variables.scss index f80ea5e..8ff78f9 100644 --- a/src/styles/abstracts/_variables.scss +++ b/src/styles/abstracts/_variables.scss @@ -95,7 +95,7 @@ $font-weights: ( semibold: 600, bold: 700, extrabold: 800, - black: 900, + "black": 900, ); // Breakpoints diff --git a/src/styles/utilities/_utilities.scss b/src/styles/utilities/_utilities.scss index 68958dc..d9ada1b 100644 --- a/src/styles/utilities/_utilities.scss +++ b/src/styles/utilities/_utilities.scss @@ -1,7 +1,9 @@ -@import '../abstracts'; +@use '../abstracts' as *; +@use '../abstracts/functions' as fn; +@use '../abstracts/variables' as vars; // Utility classes generator -@each $name, $value in $spacing { +@each $name, $value in vars.$spacing { .p-#{$name} { padding: $value !important; } .px-#{$name} { padding-left: $value !important; padding-right: $value !important; } .py-#{$name} { padding-top: $value !important; padding-bottom: $value !important; } @@ -51,17 +53,17 @@ .grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)) !important; } // Border radius -@each $name, $value in $radius { +@each $name, $value in vars.$radius { .rounded-#{$name} { border-radius: $value !important; } } // Text sizes -@each $name, $value in $font-sizes { +@each $name, $value in vars.$font-sizes { .text-#{$name} { font-size: $value !important; } } // Font weights -@each $name, $value in $font-weights { +@each $name, $value in vars.$font-weights { .font-#{$name} { font-weight: $value !important; } } @@ -71,26 +73,26 @@ .text-right { text-align: right !important; } // Colors -.text-foreground { color: $foreground !important; } -.text-muted-foreground { color: $muted-foreground !important; } -.text-primary { color: $primary !important; } -.text-destructive { color: $destructive !important; } -.text-accent { color: $accent !important; } +.text-foreground { color: vars.$foreground !important; } +.text-muted-foreground { color: vars.$muted-foreground !important; } +.text-primary { color: vars.$primary !important; } +.text-destructive { color: vars.$destructive !important; } +.text-accent { color: vars.$accent !important; } -.bg-background { background-color: $background !important; } -.bg-card { background-color: $card !important; } -.bg-primary { background-color: $primary !important; } -.bg-secondary { background-color: $secondary !important; } -.bg-muted { background-color: $muted !important; } -.bg-accent { background-color: $accent !important; } -.bg-destructive { background-color: $destructive !important; } +.bg-background { background-color: vars.$background !important; } +.bg-card { background-color: vars.$card !important; } +.bg-primary { background-color: vars.$primary !important; } +.bg-secondary { background-color: vars.$secondary !important; } +.bg-muted { background-color: vars.$muted !important; } +.bg-accent { background-color: vars.$accent !important; } +.bg-destructive { background-color: vars.$destructive !important; } // Border -.border { border: 1px solid $border !important; } -.border-b { border-bottom: 1px solid $border !important; } -.border-t { border-top: 1px solid $border !important; } -.border-l { border-left: 1px solid $border !important; } -.border-r { border-right: 1px solid $border !important; } +.border { border: 1px solid vars.$border !important; } +.border-b { border-bottom: 1px solid vars.$border !important; } +.border-t { border-top: 1px solid vars.$border !important; } +.border-l { border-left: 1px solid vars.$border !important; } +.border-r { border-right: 1px solid vars.$border !important; } // Width & Height .w-full { width: 100% !important; } @@ -137,6 +139,6 @@ // Space between children - DRY loop $space-values: (2, 3, 4, 6, 8); @each $value in $space-values { - .space-y-#{$value} > * + * { margin-top: spacing($value) !important; } - .space-x-#{$value} > * + * { margin-left: spacing($value) !important; } + .space-y-#{$value} > * + * { margin-top: fn.spacing($value) !important; } + .space-x-#{$value} > * + * { margin-left: fn.spacing($value) !important; } } diff --git a/src/vite-end.d.ts b/src/vite-end.d.ts index 164be3b..f680266 100644 --- a/src/vite-end.d.ts +++ b/src/vite-end.d.ts @@ -4,6 +4,7 @@ declare const BASE_KV_SERVICE_URL: string interface ImportMetaEnv { readonly VITE_FLASK_BACKEND_URL?: string + readonly DEV?: boolean } interface ImportMeta {