@n3wth/ui 0.4.1 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +79 -27
- package/dist/index.js +840 -823
- package/dist/index.js.map +1 -1
- package/dist/molecules/NavLink/NavLink.d.ts.map +1 -1
- package/dist/organisms/Nav/Nav.d.ts +2 -1
- package/dist/organisms/Nav/Nav.d.ts.map +1 -1
- package/dist/r/button.json +15 -0
- package/dist/r/card.json +12 -0
- package/dist/r/hero.json +12 -0
- package/dist/r/registry.json +38 -0
- package/dist/styles.css +2 -4
- package/package.json +3 -2
- package/public/r/button.json +15 -0
- package/public/r/card.json +12 -0
- package/public/r/hero.json +12 -0
- package/public/r/registry.json +38 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NavLink.d.ts","sourceRoot":"","sources":["../../../src/molecules/NavLink/NavLink.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,oBAAoB,EAAE,KAAK,SAAS,EAAc,MAAM,OAAO,CAAA;AAG7E,MAAM,WAAW,YAAa,SAAQ,oBAAoB,CAAC,iBAAiB,CAAC;IAC3E,OAAO,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,MAAM,CAAA;IAC1C,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED,eAAO,MAAM,OAAO,
|
|
1
|
+
{"version":3,"file":"NavLink.d.ts","sourceRoot":"","sources":["../../../src/molecules/NavLink/NavLink.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,oBAAoB,EAAE,KAAK,SAAS,EAAc,MAAM,OAAO,CAAA;AAG7E,MAAM,WAAW,YAAa,SAAQ,oBAAoB,CAAC,iBAAiB,CAAC;IAC3E,OAAO,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,MAAM,CAAA;IAC1C,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED,eAAO,MAAM,OAAO,4GAuCnB,CAAA"}
|
|
@@ -13,6 +13,7 @@ export interface NavProps extends HTMLAttributes<HTMLElement> {
|
|
|
13
13
|
onThemeToggle?: () => void;
|
|
14
14
|
showThemeToggle?: boolean;
|
|
15
15
|
fixed?: boolean;
|
|
16
|
+
hideOnScroll?: boolean;
|
|
16
17
|
}
|
|
17
|
-
export declare function Nav({ logo, logoHref, items, theme, onThemeToggle, showThemeToggle, fixed, className, ...props }: NavProps): import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
export declare function Nav({ logo, logoHref, items, theme, onThemeToggle, showThemeToggle, fixed, hideOnScroll, className, ...props }: NavProps): import("react/jsx-runtime").JSX.Element;
|
|
18
19
|
//# sourceMappingURL=Nav.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Nav.d.ts","sourceRoot":"","sources":["../../../src/organisms/Nav/Nav.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,SAAS,
|
|
1
|
+
{"version":3,"file":"Nav.d.ts","sourceRoot":"","sources":["../../../src/organisms/Nav/Nav.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,SAAS,EAA4C,MAAM,OAAO,CAAA;AAMrG,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,MAAM,WAAW,QAAS,SAAQ,cAAc,CAAC,WAAW,CAAC;IAC3D,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,OAAO,EAAE,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IACxB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAA;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB;AAED,wBAAgB,GAAG,CAAC,EAClB,IAAI,EACJ,QAAc,EACd,KAAU,EACV,KAAc,EACd,aAAa,EACb,eAAsB,EACtB,KAAa,EACb,YAAoB,EACpB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,QAAQ,2CAoLV"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
+
"name": "button",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"lucide-react"
|
|
6
|
+
],
|
|
7
|
+
"files": [
|
|
8
|
+
{
|
|
9
|
+
"path": "src/atoms/Button/Button.tsx",
|
|
10
|
+
"content": "import {\n forwardRef,\n type ButtonHTMLAttributes,\n type ReactNode,\n cloneElement,\n isValidElement,\n} from 'react'\nimport { cn } from '../../utils/cn'\n\nexport type ButtonSize = 'sm' | 'md' | 'lg'\n\nexport interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: 'primary' | 'secondary' | 'ghost' | 'glass'\n /** Size of the button. Can be a single value or responsive object */\n size?: ButtonSize | { base?: ButtonSize; md?: ButtonSize; lg?: ButtonSize }\n children: ReactNode\n isLoading?: boolean\n leftIcon?: ReactNode\n rightIcon?: ReactNode\n asChild?: boolean\n /** Ensures minimum 44px touch target for accessibility (WCAG 2.5.5) */\n touchTarget?: boolean\n}\n\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n variant = 'primary',\n size = 'md',\n children,\n isLoading = false,\n leftIcon,\n rightIcon,\n className,\n disabled,\n asChild = false,\n touchTarget = false,\n ...props\n },\n ref\n ) => {\n const baseStyles = [\n 'inline-flex items-center justify-center gap-2',\n 'font-medium',\n 'border',\n 'rounded-full',\n 'transition-[transform,background-color,border-color,color,opacity] duration-200 ease-out',\n 'focus-ring',\n 'disabled:opacity-50 disabled:cursor-not-allowed disabled:pointer-events-none',\n // Active state for touch feedback\n 'active:scale-[0.96]',\n ]\n\n const variants = {\n primary: [\n 'bg-[var(--color-white)] text-[var(--color-bg)]',\n 'border-[var(--color-white)]',\n 'hover:scale-[1.02]',\n 'glow-white',\n ],\n secondary: [\n 'bg-transparent text-[var(--color-white)]',\n 'border-[var(--glass-border)]',\n 'hover:border-[var(--glass-highlight)] hover:bg-[var(--glass-bg)]',\n ],\n ghost: [\n 'bg-transparent text-[var(--color-grey-400)]',\n 'border-transparent',\n 'hover:text-[var(--color-white)] hover:bg-[var(--glass-bg)]',\n ],\n glass: [\n 'bg-[var(--glass-bg)] text-[var(--color-white)]',\n 'border-[var(--glass-border)]',\n 'backdrop-blur-lg',\n 'hover:bg-[rgba(255,255,255,0.1)] hover:border-[var(--glass-highlight)]',\n 'hover:scale-[1.02]',\n ],\n }\n\n const sizes = {\n sm: 'px-3 py-1.5 text-xs',\n md: 'px-4 py-2 text-sm',\n lg: 'px-6 py-3 text-base',\n }\n\n // Handle responsive size prop\n const getSizeClasses = () => {\n if (typeof size === 'string') {\n return sizes[size]\n }\n\n // Responsive size object\n const classes: string[] = []\n if (size.base) classes.push(sizes[size.base])\n if (size.md) classes.push(`md:${sizes[size.md].split(' ').join(' md:')}`)\n if (size.lg) classes.push(`lg:${sizes[size.lg].split(' ').join(' lg:')}`)\n\n // If no base specified, default to sm for mobile-first\n if (!size.base && (size.md || size.lg)) {\n classes.unshift(sizes.sm)\n }\n\n return classes.join(' ')\n }\n\n const touchTargetStyles = touchTarget ? 'min-w-[44px] min-h-[44px]' : ''\n\n const buttonClassName = cn(\n baseStyles,\n variants[variant],\n getSizeClasses(),\n touchTargetStyles,\n className\n )\n\n type ChildProps = { children?: ReactNode; className?: string }\n const childElement = isValidElement<ChildProps>(children) ? children : null\n\n const content = (\n <>\n {isLoading ? (\n <span className=\"w-4 h-4 border-2 border-current border-t-transparent rounded-full animate-spin\" />\n ) : (\n leftIcon\n )}\n {asChild && childElement ? childElement.props.children : children}\n {!isLoading && rightIcon}\n </>\n )\n\n if (asChild && childElement) {\n return cloneElement(childElement, {\n className: cn(buttonClassName, childElement.props.className),\n ref,\n children: content,\n } as ChildProps)\n }\n\n return (\n <button\n ref={ref}\n className={buttonClassName}\n disabled={disabled || isLoading}\n {...props}\n >\n {content}\n </button>\n )\n }\n)\n\nButton.displayName = 'Button'\n",
|
|
11
|
+
"type": "registry:ui"
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"type": "registry:ui"
|
|
15
|
+
}
|
package/dist/r/card.json
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
+
"name": "card",
|
|
4
|
+
"files": [
|
|
5
|
+
{
|
|
6
|
+
"path": "src/molecules/Card/Card.tsx",
|
|
7
|
+
"content": "import { type HTMLAttributes, type ReactNode } from 'react'\nimport { cn } from '../../utils/cn'\n\nexport interface CardProps extends HTMLAttributes<HTMLDivElement> {\n variant?: 'default' | 'glass' | 'interactive'\n padding?: 'none' | 'sm' | 'md' | 'lg'\n children: ReactNode\n}\n\nexport function Card({\n variant = 'default',\n padding = 'md',\n children,\n className,\n ...props\n}: CardProps) {\n const baseStyles = [\n 'rounded-2xl',\n 'border',\n 'transition-[background-color,border-color] duration-300 ease-out',\n ]\n\n const variants = {\n default: [\n 'bg-transparent',\n 'border-[var(--glass-border)]',\n ],\n glass: [\n 'bg-[var(--glass-bg)]',\n 'backdrop-blur-lg',\n 'border-[var(--glass-border)]',\n ],\n interactive: [\n 'bg-transparent',\n 'border-[var(--glass-border)]',\n 'hover:border-[var(--glass-highlight)]',\n 'hover:bg-[var(--glass-bg)]',\n 'cursor-pointer',\n 'gradient-border shine-sweep',\n ],\n }\n\n const paddings = {\n none: '',\n sm: 'p-3',\n md: 'p-5',\n lg: 'p-8',\n }\n\n return (\n <div\n className={cn(baseStyles, variants[variant], paddings[padding], className)}\n {...props}\n >\n {children}\n </div>\n )\n}\n\nexport interface CardHeaderProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode\n}\n\nexport function CardHeader({ children, className, ...props }: CardHeaderProps) {\n return (\n <div className={cn('flex flex-col gap-1.5', className)} {...props}>\n {children}\n </div>\n )\n}\n\nexport interface CardTitleProps extends HTMLAttributes<HTMLHeadingElement> {\n children: ReactNode\n as?: 'h1' | 'h2' | 'h3' | 'h4'\n}\n\nexport function CardTitle({ children, as: Tag = 'h3', className, ...props }: CardTitleProps) {\n return (\n <Tag\n className={cn(\n 'font-display text-base font-semibold text-[var(--color-white)]',\n 'tracking-tight',\n className\n )}\n {...props}\n >\n {children}\n </Tag>\n )\n}\n\nexport interface CardDescriptionProps extends HTMLAttributes<HTMLParagraphElement> {\n children: ReactNode\n}\n\nexport function CardDescription({ children, className, ...props }: CardDescriptionProps) {\n return (\n <p\n className={cn(\n 'text-sm text-[var(--color-grey-400)]',\n 'line-clamp-2',\n className\n )}\n {...props}\n >\n {children}\n </p>\n )\n}\n\nexport interface CardContentProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode\n}\n\nexport function CardContent({ children, className, ...props }: CardContentProps) {\n return (\n <div className={cn('mt-4', className)} {...props}>\n {children}\n </div>\n )\n}\n\nexport interface CardFooterProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode\n}\n\nexport function CardFooter({ children, className, ...props }: CardFooterProps) {\n return (\n <div\n className={cn(\n 'mt-4 pt-4',\n 'border-t border-[var(--glass-border)]',\n 'flex items-center gap-3',\n className\n )}\n {...props}\n >\n {children}\n </div>\n )\n}\n",
|
|
8
|
+
"type": "registry:ui"
|
|
9
|
+
}
|
|
10
|
+
],
|
|
11
|
+
"type": "registry:ui"
|
|
12
|
+
}
|
package/dist/r/hero.json
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
+
"name": "hero",
|
|
4
|
+
"files": [
|
|
5
|
+
{
|
|
6
|
+
"path": "src/organisms/Hero/Hero.tsx",
|
|
7
|
+
"content": "import { type HTMLAttributes, type ReactNode } from 'react'\nimport { cn } from '../../utils/cn'\nimport { Badge } from '../../atoms/Badge'\nimport { Button } from '../../atoms/Button'\n\nexport interface HeroCTA {\n label: string\n href: string\n variant?: 'primary' | 'secondary' | 'ghost'\n}\n\nexport interface HeroProps extends Omit<HTMLAttributes<HTMLElement>, 'title'> {\n badge?: string\n title: ReactNode\n description?: ReactNode\n ctas?: HeroCTA[]\n align?: 'left' | 'center'\n size?: 'default' | 'large'\n gradient?: boolean\n}\n\nexport function Hero({\n badge,\n title,\n description,\n ctas = [],\n align = 'center',\n size = 'default',\n gradient = true,\n className,\n ...props\n}: HeroProps) {\n const alignments = {\n left: 'text-left items-start',\n center: 'text-center items-center',\n }\n\n const titleSizes = {\n default: 'text-4xl sm:text-5xl md:text-6xl',\n large: 'text-5xl sm:text-6xl md:text-7xl lg:text-8xl',\n }\n\n return (\n <section\n className={cn(\n 'relative',\n 'px-6 py-24 md:py-32 lg:py-40',\n className\n )}\n {...props}\n >\n <div\n className={cn(\n 'mx-auto max-w-4xl',\n 'flex flex-col gap-6',\n alignments[align]\n )}\n >\n {badge && (\n <Badge variant=\"default\" size=\"md\" className=\"animate-in\">\n {badge}\n </Badge>\n )}\n\n <h1\n className={cn(\n 'font-display font-semibold tracking-tight',\n titleSizes[size],\n gradient ? 'hero-gradient-text' : 'text-[var(--color-white)]',\n 'animate-in'\n )}\n style={{ animationDelay: '0.1s', textAlign: align === 'center' ? 'center' : 'left', width: '100%', display: 'block' }}\n >\n {title}\n </h1>\n\n {description && (\n <p\n className={cn(\n 'text-lg md:text-xl',\n 'text-[var(--color-grey-400)]',\n 'max-w-2xl leading-relaxed',\n 'animate-in'\n )}\n style={{ animationDelay: '0.2s' }}\n >\n {description}\n </p>\n )}\n\n {ctas.length > 0 && (\n <div\n className={cn(\n 'flex flex-wrap gap-4 mt-4',\n align === 'center' ? 'justify-center' : 'justify-start',\n 'animate-in'\n )}\n style={{ animationDelay: '0.3s' }}\n >\n {ctas.map((cta, index) => (\n <Button\n key={cta.href}\n variant={cta.variant || (index === 0 ? 'primary' : 'secondary')}\n size=\"lg\"\n asChild\n >\n <a href={cta.href}>{cta.label}</a>\n </Button>\n ))}\n </div>\n )}\n </div>\n </section>\n )\n}\n",
|
|
8
|
+
"type": "registry:ui"
|
|
9
|
+
}
|
|
10
|
+
],
|
|
11
|
+
"type": "registry:ui"
|
|
12
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema/registry.json",
|
|
3
|
+
"name": "n3wth-ui",
|
|
4
|
+
"homepage": "https://ui.newth.ai",
|
|
5
|
+
"items": [
|
|
6
|
+
{
|
|
7
|
+
"name": "button",
|
|
8
|
+
"type": "registry:ui",
|
|
9
|
+
"dependencies": ["lucide-react"],
|
|
10
|
+
"files": [
|
|
11
|
+
{
|
|
12
|
+
"path": "src/atoms/Button/Button.tsx",
|
|
13
|
+
"type": "registry:ui"
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "card",
|
|
19
|
+
"type": "registry:ui",
|
|
20
|
+
"files": [
|
|
21
|
+
{
|
|
22
|
+
"path": "src/molecules/Card/Card.tsx",
|
|
23
|
+
"type": "registry:ui"
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"name": "hero",
|
|
29
|
+
"type": "registry:ui",
|
|
30
|
+
"files": [
|
|
31
|
+
{
|
|
32
|
+
"path": "src/organisms/Hero/Hero.tsx",
|
|
33
|
+
"type": "registry:ui"
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
}
|
package/dist/styles.css
CHANGED
|
@@ -323,13 +323,11 @@ body {
|
|
|
323
323
|
|
|
324
324
|
/* Glass Nav */
|
|
325
325
|
.glass-nav {
|
|
326
|
-
background:
|
|
327
|
-
backdrop-filter: blur(20px) saturate(180%);
|
|
328
|
-
-webkit-backdrop-filter: blur(20px) saturate(180%);
|
|
326
|
+
background: var(--color-bg);
|
|
329
327
|
}
|
|
330
328
|
|
|
331
329
|
[data-theme='light'] .glass-nav {
|
|
332
|
-
background:
|
|
330
|
+
background: var(--color-bg);
|
|
333
331
|
}
|
|
334
332
|
|
|
335
333
|
/* Glass Pill */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@n3wth/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "Atomic design system for Newth sites - flat, minimal, iOS-inspired",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -26,7 +26,8 @@
|
|
|
26
26
|
"build": "tsc && vite build && node -e \"const fs=require('fs');const css=fs.readFileSync('src/styles.css','utf8').replace(/@import 'tailwindcss';\\n\\n/,'');fs.writeFileSync('dist/styles.css',css)\"",
|
|
27
27
|
"lint": "eslint src",
|
|
28
28
|
"prepublishOnly": "npm run build",
|
|
29
|
-
"release:patch": "npm version patch -m 'chore: bump version to %s' && git add . && git commit -m 'chore:
|
|
29
|
+
"release:patch": "npm version patch -m 'chore: bump version to %s' && npm run registry:build && git add . && git commit -m 'chore: update registry' && git push && git push --tags && gh release create v$(node -p \"require('./package.json').version\") --generate-notes",
|
|
30
|
+
"registry:build": "npx shadcn@latest build",
|
|
30
31
|
"release:minor": "npm version minor -m 'chore: bump version to %s' && git push && git push --tags && gh release create v$(node -p \"require('./package.json').version\") --generate-notes",
|
|
31
32
|
"release:major": "npm version major -m 'chore: bump version to %s' && git push && git push --tags && gh release create v$(node -p \"require('./package.json').version\") --generate-notes"
|
|
32
33
|
},
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
+
"name": "button",
|
|
4
|
+
"dependencies": [
|
|
5
|
+
"lucide-react"
|
|
6
|
+
],
|
|
7
|
+
"files": [
|
|
8
|
+
{
|
|
9
|
+
"path": "src/atoms/Button/Button.tsx",
|
|
10
|
+
"content": "import {\n forwardRef,\n type ButtonHTMLAttributes,\n type ReactNode,\n cloneElement,\n isValidElement,\n} from 'react'\nimport { cn } from '../../utils/cn'\n\nexport type ButtonSize = 'sm' | 'md' | 'lg'\n\nexport interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: 'primary' | 'secondary' | 'ghost' | 'glass'\n /** Size of the button. Can be a single value or responsive object */\n size?: ButtonSize | { base?: ButtonSize; md?: ButtonSize; lg?: ButtonSize }\n children: ReactNode\n isLoading?: boolean\n leftIcon?: ReactNode\n rightIcon?: ReactNode\n asChild?: boolean\n /** Ensures minimum 44px touch target for accessibility (WCAG 2.5.5) */\n touchTarget?: boolean\n}\n\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n variant = 'primary',\n size = 'md',\n children,\n isLoading = false,\n leftIcon,\n rightIcon,\n className,\n disabled,\n asChild = false,\n touchTarget = false,\n ...props\n },\n ref\n ) => {\n const baseStyles = [\n 'inline-flex items-center justify-center gap-2',\n 'font-medium',\n 'border',\n 'rounded-full',\n 'transition-[transform,background-color,border-color,color,opacity] duration-200 ease-out',\n 'focus-ring',\n 'disabled:opacity-50 disabled:cursor-not-allowed disabled:pointer-events-none',\n // Active state for touch feedback\n 'active:scale-[0.96]',\n ]\n\n const variants = {\n primary: [\n 'bg-[var(--color-white)] text-[var(--color-bg)]',\n 'border-[var(--color-white)]',\n 'hover:scale-[1.02]',\n 'glow-white',\n ],\n secondary: [\n 'bg-transparent text-[var(--color-white)]',\n 'border-[var(--glass-border)]',\n 'hover:border-[var(--glass-highlight)] hover:bg-[var(--glass-bg)]',\n ],\n ghost: [\n 'bg-transparent text-[var(--color-grey-400)]',\n 'border-transparent',\n 'hover:text-[var(--color-white)] hover:bg-[var(--glass-bg)]',\n ],\n glass: [\n 'bg-[var(--glass-bg)] text-[var(--color-white)]',\n 'border-[var(--glass-border)]',\n 'backdrop-blur-lg',\n 'hover:bg-[rgba(255,255,255,0.1)] hover:border-[var(--glass-highlight)]',\n 'hover:scale-[1.02]',\n ],\n }\n\n const sizes = {\n sm: 'px-3 py-1.5 text-xs',\n md: 'px-4 py-2 text-sm',\n lg: 'px-6 py-3 text-base',\n }\n\n // Handle responsive size prop\n const getSizeClasses = () => {\n if (typeof size === 'string') {\n return sizes[size]\n }\n\n // Responsive size object\n const classes: string[] = []\n if (size.base) classes.push(sizes[size.base])\n if (size.md) classes.push(`md:${sizes[size.md].split(' ').join(' md:')}`)\n if (size.lg) classes.push(`lg:${sizes[size.lg].split(' ').join(' lg:')}`)\n\n // If no base specified, default to sm for mobile-first\n if (!size.base && (size.md || size.lg)) {\n classes.unshift(sizes.sm)\n }\n\n return classes.join(' ')\n }\n\n const touchTargetStyles = touchTarget ? 'min-w-[44px] min-h-[44px]' : ''\n\n const buttonClassName = cn(\n baseStyles,\n variants[variant],\n getSizeClasses(),\n touchTargetStyles,\n className\n )\n\n type ChildProps = { children?: ReactNode; className?: string }\n const childElement = isValidElement<ChildProps>(children) ? children : null\n\n const content = (\n <>\n {isLoading ? (\n <span className=\"w-4 h-4 border-2 border-current border-t-transparent rounded-full animate-spin\" />\n ) : (\n leftIcon\n )}\n {asChild && childElement ? childElement.props.children : children}\n {!isLoading && rightIcon}\n </>\n )\n\n if (asChild && childElement) {\n return cloneElement(childElement, {\n className: cn(buttonClassName, childElement.props.className),\n ref,\n children: content,\n } as ChildProps)\n }\n\n return (\n <button\n ref={ref}\n className={buttonClassName}\n disabled={disabled || isLoading}\n {...props}\n >\n {content}\n </button>\n )\n }\n)\n\nButton.displayName = 'Button'\n",
|
|
11
|
+
"type": "registry:ui"
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"type": "registry:ui"
|
|
15
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
+
"name": "card",
|
|
4
|
+
"files": [
|
|
5
|
+
{
|
|
6
|
+
"path": "src/molecules/Card/Card.tsx",
|
|
7
|
+
"content": "import { type HTMLAttributes, type ReactNode } from 'react'\nimport { cn } from '../../utils/cn'\n\nexport interface CardProps extends HTMLAttributes<HTMLDivElement> {\n variant?: 'default' | 'glass' | 'interactive'\n padding?: 'none' | 'sm' | 'md' | 'lg'\n children: ReactNode\n}\n\nexport function Card({\n variant = 'default',\n padding = 'md',\n children,\n className,\n ...props\n}: CardProps) {\n const baseStyles = [\n 'rounded-2xl',\n 'border',\n 'transition-[background-color,border-color] duration-300 ease-out',\n ]\n\n const variants = {\n default: [\n 'bg-transparent',\n 'border-[var(--glass-border)]',\n ],\n glass: [\n 'bg-[var(--glass-bg)]',\n 'backdrop-blur-lg',\n 'border-[var(--glass-border)]',\n ],\n interactive: [\n 'bg-transparent',\n 'border-[var(--glass-border)]',\n 'hover:border-[var(--glass-highlight)]',\n 'hover:bg-[var(--glass-bg)]',\n 'cursor-pointer',\n 'gradient-border shine-sweep',\n ],\n }\n\n const paddings = {\n none: '',\n sm: 'p-3',\n md: 'p-5',\n lg: 'p-8',\n }\n\n return (\n <div\n className={cn(baseStyles, variants[variant], paddings[padding], className)}\n {...props}\n >\n {children}\n </div>\n )\n}\n\nexport interface CardHeaderProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode\n}\n\nexport function CardHeader({ children, className, ...props }: CardHeaderProps) {\n return (\n <div className={cn('flex flex-col gap-1.5', className)} {...props}>\n {children}\n </div>\n )\n}\n\nexport interface CardTitleProps extends HTMLAttributes<HTMLHeadingElement> {\n children: ReactNode\n as?: 'h1' | 'h2' | 'h3' | 'h4'\n}\n\nexport function CardTitle({ children, as: Tag = 'h3', className, ...props }: CardTitleProps) {\n return (\n <Tag\n className={cn(\n 'font-display text-base font-semibold text-[var(--color-white)]',\n 'tracking-tight',\n className\n )}\n {...props}\n >\n {children}\n </Tag>\n )\n}\n\nexport interface CardDescriptionProps extends HTMLAttributes<HTMLParagraphElement> {\n children: ReactNode\n}\n\nexport function CardDescription({ children, className, ...props }: CardDescriptionProps) {\n return (\n <p\n className={cn(\n 'text-sm text-[var(--color-grey-400)]',\n 'line-clamp-2',\n className\n )}\n {...props}\n >\n {children}\n </p>\n )\n}\n\nexport interface CardContentProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode\n}\n\nexport function CardContent({ children, className, ...props }: CardContentProps) {\n return (\n <div className={cn('mt-4', className)} {...props}>\n {children}\n </div>\n )\n}\n\nexport interface CardFooterProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode\n}\n\nexport function CardFooter({ children, className, ...props }: CardFooterProps) {\n return (\n <div\n className={cn(\n 'mt-4 pt-4',\n 'border-t border-[var(--glass-border)]',\n 'flex items-center gap-3',\n className\n )}\n {...props}\n >\n {children}\n </div>\n )\n}\n",
|
|
8
|
+
"type": "registry:ui"
|
|
9
|
+
}
|
|
10
|
+
],
|
|
11
|
+
"type": "registry:ui"
|
|
12
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
+
"name": "hero",
|
|
4
|
+
"files": [
|
|
5
|
+
{
|
|
6
|
+
"path": "src/organisms/Hero/Hero.tsx",
|
|
7
|
+
"content": "import { type HTMLAttributes, type ReactNode } from 'react'\nimport { cn } from '../../utils/cn'\nimport { Badge } from '../../atoms/Badge'\nimport { Button } from '../../atoms/Button'\n\nexport interface HeroCTA {\n label: string\n href: string\n variant?: 'primary' | 'secondary' | 'ghost'\n}\n\nexport interface HeroProps extends Omit<HTMLAttributes<HTMLElement>, 'title'> {\n badge?: string\n title: ReactNode\n description?: ReactNode\n ctas?: HeroCTA[]\n align?: 'left' | 'center'\n size?: 'default' | 'large'\n gradient?: boolean\n}\n\nexport function Hero({\n badge,\n title,\n description,\n ctas = [],\n align = 'center',\n size = 'default',\n gradient = true,\n className,\n ...props\n}: HeroProps) {\n const alignments = {\n left: 'text-left items-start',\n center: 'text-center items-center',\n }\n\n const titleSizes = {\n default: 'text-4xl sm:text-5xl md:text-6xl',\n large: 'text-5xl sm:text-6xl md:text-7xl lg:text-8xl',\n }\n\n return (\n <section\n className={cn(\n 'relative',\n 'px-6 py-24 md:py-32 lg:py-40',\n className\n )}\n {...props}\n >\n <div\n className={cn(\n 'mx-auto max-w-4xl',\n 'flex flex-col gap-6',\n alignments[align]\n )}\n >\n {badge && (\n <Badge variant=\"default\" size=\"md\" className=\"animate-in\">\n {badge}\n </Badge>\n )}\n\n <h1\n className={cn(\n 'font-display font-semibold tracking-tight',\n titleSizes[size],\n gradient ? 'hero-gradient-text' : 'text-[var(--color-white)]',\n 'animate-in'\n )}\n style={{ animationDelay: '0.1s', textAlign: align === 'center' ? 'center' : 'left', width: '100%', display: 'block' }}\n >\n {title}\n </h1>\n\n {description && (\n <p\n className={cn(\n 'text-lg md:text-xl',\n 'text-[var(--color-grey-400)]',\n 'max-w-2xl leading-relaxed',\n 'animate-in'\n )}\n style={{ animationDelay: '0.2s' }}\n >\n {description}\n </p>\n )}\n\n {ctas.length > 0 && (\n <div\n className={cn(\n 'flex flex-wrap gap-4 mt-4',\n align === 'center' ? 'justify-center' : 'justify-start',\n 'animate-in'\n )}\n style={{ animationDelay: '0.3s' }}\n >\n {ctas.map((cta, index) => (\n <Button\n key={cta.href}\n variant={cta.variant || (index === 0 ? 'primary' : 'secondary')}\n size=\"lg\"\n asChild\n >\n <a href={cta.href}>{cta.label}</a>\n </Button>\n ))}\n </div>\n )}\n </div>\n </section>\n )\n}\n",
|
|
8
|
+
"type": "registry:ui"
|
|
9
|
+
}
|
|
10
|
+
],
|
|
11
|
+
"type": "registry:ui"
|
|
12
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema/registry.json",
|
|
3
|
+
"name": "n3wth-ui",
|
|
4
|
+
"homepage": "https://ui.newth.ai",
|
|
5
|
+
"items": [
|
|
6
|
+
{
|
|
7
|
+
"name": "button",
|
|
8
|
+
"type": "registry:ui",
|
|
9
|
+
"dependencies": ["lucide-react"],
|
|
10
|
+
"files": [
|
|
11
|
+
{
|
|
12
|
+
"path": "src/atoms/Button/Button.tsx",
|
|
13
|
+
"type": "registry:ui"
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "card",
|
|
19
|
+
"type": "registry:ui",
|
|
20
|
+
"files": [
|
|
21
|
+
{
|
|
22
|
+
"path": "src/molecules/Card/Card.tsx",
|
|
23
|
+
"type": "registry:ui"
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"name": "hero",
|
|
29
|
+
"type": "registry:ui",
|
|
30
|
+
"files": [
|
|
31
|
+
{
|
|
32
|
+
"path": "src/organisms/Hero/Hero.tsx",
|
|
33
|
+
"type": "registry:ui"
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
}
|