uibee 1.6.12 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/Readme.md +0 -1
  2. package/dist/globals.css +710 -8
  3. package/dist/src/components/index.d.ts +10 -2
  4. package/dist/src/components/index.js +13 -2
  5. package/dist/src/components/login/loginPage.js +5 -6
  6. package/dist/src/components/logo/logo.d.ts +5 -0
  7. package/dist/src/components/logo/logo.js +6 -0
  8. package/dist/src/components/logo/logoSmall.d.ts +1 -0
  9. package/dist/src/components/logo/logoSmall.js +6 -0
  10. package/dist/src/components/navbar/navbar.d.ts +10 -0
  11. package/dist/src/components/navbar/navbar.js +36 -0
  12. package/dist/src/components/navbar/navbarDropdown.d.ts +6 -0
  13. package/dist/src/components/navbar/navbarDropdown.js +21 -0
  14. package/dist/src/components/navbar/navbarItem.d.ts +11 -0
  15. package/dist/src/components/navbar/navbarItem.js +12 -0
  16. package/dist/src/components/toggle/language.d.ts +4 -0
  17. package/dist/src/components/toggle/language.js +29 -0
  18. package/dist/src/components/toggle/theme.d.ts +3 -0
  19. package/dist/src/components/toggle/theme.js +30 -0
  20. package/dist/src/components/version/version.d.ts +7 -0
  21. package/dist/src/components/version/version.js +12 -0
  22. package/dist/src/scripts/rewriteAlias.js +17 -17
  23. package/package.json +8 -6
  24. package/src/components/index.ts +17 -3
  25. package/src/components/login/loginPage.tsx +8 -14
  26. package/src/components/logo/logo.tsx +45 -0
  27. package/src/components/logo/logoSmall.tsx +19 -0
  28. package/src/components/navbar/navbar.tsx +130 -0
  29. package/src/components/navbar/navbarDropdown.tsx +77 -0
  30. package/src/components/navbar/navbarItem.tsx +47 -0
  31. package/src/components/toggle/language.tsx +45 -0
  32. package/src/components/toggle/theme.tsx +150 -0
  33. package/src/components/version/version.tsx +34 -0
  34. package/src/globals.css +47 -0
  35. package/src/scripts/rewriteAlias.ts +19 -17
  36. package/src/types/components.d.ts +4 -0
  37. package/tsconfig.json +8 -2
  38. package/dist/images/logo-tekst-white.svg +0 -171
  39. package/dist/src/types/svg.d.ts +0 -4
  40. package/dist/src/types/svg.js +0 -1
  41. package/images/logo-tekst-white.svg +0 -171
  42. package/src/types/svg.ts +0 -4
@@ -0,0 +1,130 @@
1
+ 'use client'
2
+
3
+ import React, { useState } from 'react'
4
+ import Link from 'next/link'
5
+ import LogoSmall from '@components/logo/logoSmall'
6
+ import LanguageToggle from '@components/toggle/language'
7
+ import ThemeToggle from '@components/toggle/theme'
8
+ import { Language } from 'uibee/components'
9
+ import { LogOut } from 'lucide-react'
10
+
11
+
12
+ function hamburgerStyle (isOpen: boolean, isSecond?: boolean) {
13
+ return `bg-login-50 h-0.5 absolute w-8 transition-all duration-[400ms] left-2 ${
14
+ isOpen
15
+ ? `top-6 ${isSecond ? 'rotate-45' : '-rotate-45'}`
16
+ : isSecond ? 'top-7' : 'top-4'
17
+ }`
18
+ }
19
+
20
+ export type NavbarProps = {
21
+ lang: Language
22
+ onlyLogo?: boolean
23
+ theme: string
24
+ token: string | null
25
+ children: React.ReactNode
26
+ }
27
+
28
+ export default function Navbar({ lang, onlyLogo, token, children }: NavbarProps) {
29
+ const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false)
30
+
31
+ return (
32
+ <div className={`${isMobileMenuOpen ? 'bg-[#181818f0]' : 'bg-[#18181899]'} backdrop-blur-xl fixed top-0 z-900 w-full`}>
33
+ <div className={`flex w-full max-w-6xl m-auto p-2 transition duration-500 800px:justify-between 800px:p-4 ${
34
+ isMobileMenuOpen ? 'h-screen bg-login-900/20 800px:h-20' : ''
35
+ }`}>
36
+ {/* Logo */}
37
+ <div className='block h-12 p-1 800px:p-0'>
38
+ <Link
39
+ href='/'
40
+ onClick={() => setIsMobileMenuOpen(false)}
41
+ >
42
+ <LogoSmall />
43
+ </Link>
44
+ </div>
45
+
46
+ {onlyLogo ? null : (
47
+ <>
48
+ {/* Desktop Navigation */}
49
+ <nav className='hidden 800px:flex 800px:justify-between 800px:items-center 800px:w-fill max-w-[50rem]'>
50
+ {children}
51
+ </nav>
52
+
53
+ {/* Controls */}
54
+ <nav className='flex w-[calc(100vw-8rem)] justify-end h-12 800px:w-fit'>
55
+ <ThemeToggle />
56
+ <LanguageToggle language={lang} />
57
+ <AuthButton token={token} />
58
+ </nav>
59
+
60
+ {/* Mobile Menu Button */}
61
+ <button
62
+ className='w-12 h-12 relative cursor-pointer bg-none border-none 800px:hidden'
63
+ onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
64
+ >
65
+ <div className={hamburgerStyle(isMobileMenuOpen)} />
66
+ <div className={hamburgerStyle(isMobileMenuOpen, true)} />
67
+ </button>
68
+
69
+ {/* Mobile Navigation */}
70
+ <nav className={`fixed top-16 w-[calc(100%-2rem)] max-w-[35rem] mx-auto left-0 right-0 800px:hidden
71
+ transition-all duration-500 ease-in-out overflow-hidden
72
+ ${isMobileMenuOpen ? 'max-h-[calc(100vh-4rem)] opacity-100' : 'max-h-0 opacity-0'}`}
73
+ onClick={() => setIsMobileMenuOpen(false)}>
74
+ {React.Children.map(children, (child, index) => (
75
+ <div
76
+ key={index}
77
+ className={`transition-all duration-500 ease-out ${
78
+ isMobileMenuOpen
79
+ ? 'opacity-100 transform translate-y-0'
80
+ : 'opacity-0 transform -translate-y-4'
81
+ }`}
82
+ style={{
83
+ transitionDelay: isMobileMenuOpen ? `${index * 80}ms` : '0ms'
84
+ }}
85
+ >
86
+ {child}
87
+ </div>
88
+ ))}
89
+ </nav>
90
+ </>
91
+ )}
92
+ </div>
93
+ </div>
94
+ )
95
+ }
96
+
97
+ function AuthButton({ token }: { token: string | null }) {
98
+ return (
99
+ <div className='rounded-[0.3rem] hover:bg-[#6464641a] h-12 w-12'>
100
+ {token ? (
101
+ <Link
102
+ href='/api/logout'
103
+ prefetch={false}
104
+ onClick={(e) => {
105
+ e.preventDefault()
106
+ window.location.href = '/api/logout'
107
+ }}
108
+ className='grid items-center justify-center h-full w-full'
109
+ >
110
+ <LogOut size={24} />
111
+ </Link>
112
+ ) : (
113
+ <Link
114
+ href='/api/login'
115
+ className='grid items-center justify-center h-full w-full'
116
+ >
117
+ <div className={`relative w-[30px] h-5
118
+ before:content-[""] before:absolute before:top-0 before:left-1/2 before:-translate-x-1/2
119
+ before:w-[10px] before:h-[10px] before:border-2 before:border-login-50
120
+ before:rounded-full before:bg-transparent
121
+ after:content-[""] after:absolute after:bottom-0 after:left-1/2 after:-translate-x-1/2
122
+ after:w-[18px] after:h-2 after:border-2 after:border-login-50
123
+ after:rounded-t-[22px] after:border-b-0 after:bg-transparent
124
+ `}
125
+ />
126
+ </Link>
127
+ )}
128
+ </div>
129
+ )
130
+ }
@@ -0,0 +1,77 @@
1
+ 'use client'
2
+
3
+ import { ChevronDown } from 'lucide-react'
4
+ import React, { ReactNode, useRef, useState } from 'react'
5
+
6
+ export type NavDropdownProps = {
7
+ children: ReactNode
8
+ title: string
9
+ }
10
+
11
+ export default function NavDropdown({ children, title }: NavDropdownProps) {
12
+ const [isMobileDropdownOpen, setIsMobileDropdownOpen] = useState(false)
13
+ const navItemRef = useRef<HTMLDivElement>(null)
14
+
15
+ return (
16
+ <>
17
+ {/* Desktop Dropdown */}
18
+ <div className={'relative group hidden 800px:block'}>
19
+ <div className='outline-none' tabIndex={0} ref={navItemRef}>
20
+ <div className={`list-none no-underline text-base leading-4 p-3 font-bold cursor-pointer flex flex-row items-center
21
+ transition-colors`
22
+ }>
23
+ {title}
24
+ <ChevronDown className={'w-6 h-6 stroke-login ml-1 text-2xl transition-transform duration-300 ease-in-out'} />
25
+ </div>
26
+ <div className={`absolute pt-2 -ml-4 -translate-y-4 opacity-0 pointer-events-none
27
+ transition-all duration-200 ease-in-out z-10
28
+ group-hover:opacity-100 group-hover:pointer-events-auto group-hover:translate-y-0
29
+ group-focus-within:opacity-100 group-focus-within:pointer-events-auto group-focus-within:translate-y-0`}
30
+ >
31
+ <ul className={'p-3 px-6 pb-4 rounded-[0.4rem] shadow-[0_0.1rem_0.5rem_rgba(3,3,3,0.5)] bg-login-700/98'}>
32
+ {React.Children.map(children, (child, index) => (
33
+ <div
34
+ key={index}
35
+ onClick={() => navItemRef.current?.blur()}
36
+ className='group dropdown'
37
+ >
38
+ {child}
39
+ </div>
40
+ ))}
41
+ </ul>
42
+ </div>
43
+ </div>
44
+ </div>
45
+
46
+ {/* Mobile Dropdown */}
47
+ <div className={'block 800px:hidden'}>
48
+ <button
49
+ className={'bg-none border-none cursor-pointer w-full text-left'}
50
+ onClick={(e) => {
51
+ e.stopPropagation()
52
+ setIsMobileDropdownOpen(!isMobileDropdownOpen)
53
+ }}
54
+ >
55
+ <li className={`list-none no-underline text-2xl leading-6 overflow-hidden
56
+ w-full pl-4 pr-4 rounded-[0.3rem] transition-all duration-[600ms]
57
+ flex items-center gap-2 opacity-100 min-h-16 py-5 `}
58
+ >
59
+ <span>{title}</span>
60
+ <ChevronDown className={`w-6 h-6 transition-transform duration-400 flex-shrink-0
61
+ ${isMobileDropdownOpen ? 'rotate-180' : ''}`}
62
+ />
63
+ </li>
64
+ </button>
65
+ <div className={`list-none no-underline text-xl px-6 ${isMobileDropdownOpen ? 'pb-4' : ''}`}>
66
+ {React.Children.map(children, (child, index) => (
67
+ <div key={index} className={`leading-6 transition-all duration-500 group dropdown
68
+ ${isMobileDropdownOpen ? 'h-11 opacity-100' : 'h-0 opacity-0'}
69
+ `}>
70
+ {child}
71
+ </div>
72
+ ))}
73
+ </div>
74
+ </div>
75
+ </>
76
+ )
77
+ }
@@ -0,0 +1,47 @@
1
+ 'use client'
2
+
3
+ import { ArrowUpRight } from 'lucide-react'
4
+ import Link from 'next/link'
5
+ import { ReactNode } from 'react'
6
+
7
+ export type NavItemProps = {
8
+ href: string
9
+ children: ReactNode
10
+ external?: boolean
11
+ target?: string
12
+ rel?: string
13
+ title?: string
14
+ icon?: ReactNode
15
+ }
16
+
17
+ const commonStyling = 'list-none flex no-underline items-center gap-2 whitespace-nowrap cursor-pointer'
18
+
19
+ export default function NavItem({ href, children, external = false, target, rel, title, icon }: NavItemProps) {
20
+ const linkProps = { href, target, rel, title }
21
+
22
+ return (
23
+ <>
24
+ {/* Desktop version */}
25
+ <Link {...linkProps} className='hidden 800px:block'>
26
+ <li className={`${commonStyling} text-base leading-4 p-3 font-bold transition-colors link-corner-hover
27
+ group-[.dropdown]:p-2.5 group-[.dropdown]:pr-3 group-[.dropdown]:pl-1`
28
+ }>
29
+ {icon}
30
+ {children}
31
+ {external && <ArrowUpRight className='w-6 h-6 stroke-login' />}
32
+ </li>
33
+ </Link>
34
+
35
+ {/* Mobile version */}
36
+ <Link {...linkProps} className='block 800px:hidden'>
37
+ <li className={`${commonStyling} text-2xl leading-6 overflow-hidden w-auto pl-4 rounded-[0.3rem] transition-all
38
+ duration-[600ms] opacity-100 h-16 py-5 group-[.dropdown]:p-0 group-[.dropdown]:text-lg group-[.dropdown]:h-auto
39
+ group-[.dropdown]:py-2.5 group-[.dropdown]:pl-4`
40
+ }>
41
+ {children}
42
+ {external && <ArrowUpRight className='w-6 h-6 stroke-login' />}
43
+ </li>
44
+ </Link>
45
+ </>
46
+ )
47
+ }
@@ -0,0 +1,45 @@
1
+ 'use client'
2
+
3
+ import { useEffect, useState } from 'react'
4
+ import { getCookie, setCookie } from '@utils/cookies/cookies'
5
+ import { useRouter } from 'next/navigation'
6
+ import { Language } from 'uibee/components'
7
+ import { Globe } from 'lucide-react'
8
+
9
+ export default function LanguageToggle({language}: {language: Language}) {
10
+ const [lang, setLang] = useState<Language>(language)
11
+ const [jump, setJump] = useState(false)
12
+
13
+ const router = useRouter()
14
+
15
+ useEffect(() => {
16
+ const savedLang = getCookie('lang') as Language
17
+ if (savedLang) {
18
+ setLang(savedLang)
19
+ }
20
+ }, [])
21
+
22
+ function handleClick() {
23
+ const newLang = lang === 'no' ? 'en' : 'no'
24
+ setCookie('lang', newLang)
25
+ setLang(newLang)
26
+ language = newLang
27
+ setJump(true)
28
+ setTimeout(() => setJump(false), 400)
29
+ router.refresh()
30
+ }
31
+
32
+ const buttonClasses = `cursor-pointer p-2 leading-8 text-base w-[4.3rem] text-center rounded
33
+ bg-transparent border-none hover:bg-gray-400/10 flex flex-row items-center justify-center gap-1`
34
+
35
+ return(
36
+ <button
37
+ value={lang}
38
+ onClick={handleClick}
39
+ className={buttonClasses}
40
+ >
41
+ <Globe className={`text-xl leading-8 -mt-0.5 ${jump ? 'animate-jump' : ''}`}/>
42
+ {' ' + lang}
43
+ </button>
44
+ )
45
+ }
@@ -0,0 +1,150 @@
1
+ 'use client'
2
+
3
+ import { useEffect, useState } from 'react'
4
+ import { getCookie, setCookie } from '@utils/cookies/cookies'
5
+ import { useRouter } from 'next/navigation'
6
+
7
+ export default function ThemeToggle({className}: {className?: string}) {
8
+ const router = useRouter()
9
+ const [theme, setTheme] = useState<'dark' | 'light'>('dark')
10
+
11
+ useEffect(() => {
12
+ const savedTheme = getCookie('theme') as 'dark' | 'light'
13
+ if (savedTheme) {
14
+ setTheme(savedTheme)
15
+ }
16
+
17
+ document.documentElement.classList.remove('dark', 'light')
18
+ document.documentElement.classList.add(theme)
19
+ }, [theme])
20
+
21
+ function toggleTheme() {
22
+ const newTheme = theme === 'dark' ? 'light' : 'dark'
23
+ setCookie('theme', newTheme)
24
+ setTheme(newTheme)
25
+ router.refresh()
26
+ }
27
+
28
+ return (
29
+ <div className={`grid place-items-center justify-end rounded-md hover:bg-login-300/20 w-fit ${className}`}>
30
+ <label className='cursor-pointer'>
31
+ <input
32
+ type='checkbox'
33
+ checked={theme === 'light'}
34
+ onChange={toggleTheme}
35
+ className='sr-only'
36
+ />
37
+ <ThemeIcon theme={theme} />
38
+ </label>
39
+ </div>
40
+ )
41
+ }
42
+
43
+ function ThemeIcon({ theme }: { theme: 'dark' | 'light' }) {
44
+ const sunrayClass = `fill-white transition-opacity duration-400 ${
45
+ theme === 'light' ? 'opacity-0' : 'opacity-100'
46
+ }`
47
+
48
+ return (
49
+ <svg
50
+ className='h-12 p-3'
51
+ viewBox='0 0 100 100'
52
+ xmlns='http://www.w3.org/2000/svg'
53
+ >
54
+ {/* Sun */}
55
+ <defs>
56
+ <mask id='theme-toggle_clip-path'>
57
+ <rect x='0' y='0' width='100' height='100' fill='white' />
58
+ <circle
59
+ className={`transition-transform duration-400 ${
60
+ theme === 'dark' ? 'translate-x-8 -translate-y-4' : ''
61
+ }`}
62
+ cx='68'
63
+ cy='40'
64
+ r='18'
65
+ />
66
+ </mask>
67
+ </defs>
68
+ {/* Moon */}
69
+ <circle
70
+ className={`origin-center transition-all duration-400 ${
71
+ theme === 'light'
72
+ ? 'scale-[1.9] fill-black'
73
+ : 'scale-100 fill-white'
74
+ }`}
75
+ mask={'url(#theme-toggle_clip-path)'}
76
+ cx='50'
77
+ cy='50'
78
+ r='23'
79
+ />
80
+ {/* Sunrays */}
81
+ <rect
82
+ className={sunrayClass}
83
+ x='86'
84
+ y='47'
85
+ width='14'
86
+ height='6'
87
+ rx='3'
88
+ />
89
+ <rect
90
+ className={sunrayClass}
91
+ y='47'
92
+ width='14'
93
+ height='6'
94
+ rx='3'
95
+ />
96
+ <rect
97
+ className={sunrayClass}
98
+ x='47'
99
+ y='86'
100
+ width='6'
101
+ height='14'
102
+ rx='3'
103
+ />
104
+ <rect
105
+ className={sunrayClass}
106
+ x='75'
107
+ y='75'
108
+ width='6'
109
+ height='14'
110
+ rx='3'
111
+ transform='rotate(-45 78 78)'
112
+ />
113
+ <rect
114
+ className={sunrayClass}
115
+ x='84.8995'
116
+ y='12'
117
+ width='6'
118
+ height='14'
119
+ rx='3'
120
+ transform='rotate(45 84.8995 12)'
121
+ />
122
+ <rect
123
+ className={sunrayClass}
124
+ x='22.8995'
125
+ y='74'
126
+ width='6'
127
+ height='14'
128
+ rx='3'
129
+ transform='rotate(45 22.8995 74)'
130
+ />
131
+ <rect
132
+ className={sunrayClass}
133
+ x='13'
134
+ y='16.2426'
135
+ width='6'
136
+ height='14'
137
+ rx='3'
138
+ transform='rotate(-45 13 16.2426)'
139
+ />
140
+ <rect
141
+ className={sunrayClass}
142
+ x='47'
143
+ y='0'
144
+ width='6'
145
+ height='14'
146
+ rx='3'
147
+ />
148
+ </svg>
149
+ )
150
+ }
@@ -0,0 +1,34 @@
1
+ import Link from 'next/link'
2
+
3
+ type VersionTagProps = {
4
+ version?: string
5
+ url?: string
6
+ className?: string
7
+ }
8
+
9
+ export default function VersionTag({version, url, className}: VersionTagProps) {
10
+ if (!version) {
11
+ return
12
+ }
13
+
14
+ const style =
15
+ `w-fit bg-login-600 px-2 py-1 rounded-md text-white tracking-[0.05em] font-semibold text-lg ${className}`
16
+
17
+ if (url) {
18
+ return (
19
+ <Link
20
+ className={style}
21
+ target='_blank'
22
+ href={url}
23
+ >
24
+ v{version}
25
+ </Link>
26
+ )
27
+ }
28
+
29
+ return (
30
+ <div className={style}>
31
+ v{version}
32
+ </div>
33
+ )
34
+ }
package/src/globals.css CHANGED
@@ -3,6 +3,21 @@
3
3
  @config '../tailwind.config.ts';
4
4
 
5
5
  @theme {
6
+ --breakpoint-100px: 100px;
7
+ --breakpoint-200px: 200px;
8
+ --breakpoint-300px: 300px;
9
+ --breakpoint-432px: 432px;
10
+ --breakpoint-350px: 350px;
11
+ --breakpoint-400px: 400px;
12
+ --breakpoint-450px: 450px;
13
+ --breakpoint-500px: 500px;
14
+ --breakpoint-600px: 600px;
15
+ --breakpoint-700px: 700px;
16
+ --breakpoint-800px: 800px;
17
+ --breakpoint-900px: 900px;
18
+ --breakpoint-1000px: 1000px;
19
+ --breakpoint-1200px: 1200px;
20
+
6
21
  --breakpoint-xs: 30rem;
7
22
  --breakpoint-2xl: 100rem;
8
23
  --breakpoint-3xl: 120rem;
@@ -82,3 +97,35 @@ body {
82
97
  background: var(--background);
83
98
  font-family: Arial, Helvetica, sans-serif;
84
99
  }
100
+
101
+ @keyframes jump {
102
+ 40% {
103
+ transform: translateY(-0.3rem);
104
+ }
105
+ }
106
+
107
+ @utility animate-jump {
108
+ animation: jump 0.4s 1;
109
+ }
110
+
111
+ @utility link-corner-hover {
112
+ position: relative;
113
+
114
+ &::after {
115
+ content: ' ';
116
+ position: absolute;
117
+ width: .8em;
118
+ height: .8em;
119
+ bottom: .4em;
120
+ right: .4em;
121
+ border-right: .2em solid transparent;
122
+ border-bottom: .2em solid transparent;
123
+ transition: .2s;
124
+ }
125
+
126
+ &:hover::after {
127
+ border-color: var(--color-login);
128
+ right: 0;
129
+ bottom: 0;
130
+ }
131
+ }
@@ -3,35 +3,37 @@ import path from 'path'
3
3
  import { globSync } from 'glob'
4
4
 
5
5
  const DIST_DIR = path.resolve('dist')
6
- const IMAGES_DIR = path.join(DIST_DIR, 'images')
6
+ const SRC_DIR = path.join(DIST_DIR, 'src')
7
7
 
8
8
  const jsFiles = globSync(`${DIST_DIR}/**/*.js`, { nodir: true })
9
9
 
10
10
  jsFiles.forEach((file) => {
11
11
  let content = fs.readFileSync(file, 'utf-8')
12
12
  const fileDir = path.dirname(file)
13
- content = content.replace(/from ['"]@images\/(.*?)['"]/g, (_, p1) => {
14
- const targetPath = path.join(IMAGES_DIR, p1)
13
+
14
+ // Handle @utils/* imports
15
+ content = content.replace(/from ['"]@utils\/(.*?)['"]/g, (_, p1) => {
16
+ const targetPath = path.join(SRC_DIR, 'utils', p1)
17
+ const relative = path.relative(fileDir, targetPath).replace(/\\/g, '/')
18
+ return `from '${relative}'`
19
+ })
20
+
21
+ // Handle @components/* imports
22
+ content = content.replace(/from ['"]@components\/(.*?)['"]/g, (_, p1) => {
23
+ const targetPath = path.join(SRC_DIR, 'components', p1)
15
24
  const relative = path.relative(fileDir, targetPath).replace(/\\/g, '/')
16
25
  return `from '${relative}'`
17
26
  })
18
27
 
19
- const inlineImages = content.match(/src: ['"]images\/(.*?)['"]/g)
20
- if (inlineImages) {
21
- inlineImages.forEach((match) => {
22
- const imgPathMatch = match.match(/src: ['"]images\/(.*?)['"]/)
23
- if (imgPathMatch) {
24
- const imgRelativePath = imgPathMatch[1]
25
- const resolvedPath = path.join(IMAGES_DIR, imgRelativePath)
26
- console.error(`⚠️ Detected inline image in ${file}: ${match}`)
27
- console.error(` Resolved file path: ${resolvedPath}`)
28
- console.error(` This is not allowed. Use 'import image from '@images/${imgRelativePath}'' instead.`)
29
- }
30
- })
31
- }
28
+ // Handle @hooks/* imports
29
+ content = content.replace(/from ['"]@hooks\/(.*?)['"]/g, (_, p1) => {
30
+ const targetPath = path.join(SRC_DIR, 'hooks', p1)
31
+ const relative = path.relative(fileDir, targetPath).replace(/\\/g, '/')
32
+ return `from '${relative}'`
33
+ })
32
34
 
33
35
  fs.writeFileSync(file, content, 'utf-8')
34
36
  })
35
37
 
36
- console.log('🐝 Image imports rewritten')
38
+ console.log('🐝 All path aliases rewritten')
37
39
  console.log('🐝 Build complete')
@@ -27,6 +27,10 @@ declare module 'uibee/components' {
27
27
  (event: ToastEventProps): void
28
28
  }
29
29
 
30
+ export type Language = 'no' | 'en'
31
+
30
32
  export default function LoginPage(props: LoginPageProps): JSX.Element;
31
33
  export default function Toaster(props: { toasts: ToastProps[] }): JSX.Element;
34
+ export default function LanguageToggle(props: { lang: Language }): JSX.Element;
35
+ export default function ThemeSwitch(props: { className?: string }): JSX.Element;
32
36
  }
package/tsconfig.json CHANGED
@@ -13,8 +13,14 @@
13
13
  "jsx": "react-jsx",
14
14
  "resolveJsonModule": true,
15
15
  "paths": {
16
- "@images/*": [
17
- "./images/*"
16
+ "@components/*": [
17
+ "./src/components/*"
18
+ ],
19
+ "@utils/*": [
20
+ "./src/utils/*"
21
+ ],
22
+ "@hooks/*": [
23
+ "./src/hooks/*"
18
24
  ]
19
25
  }
20
26
  },