getlotui 0.1.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.
- package/README.md +78 -0
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +5 -0
- package/dist/commands/add.d.ts +1 -0
- package/dist/commands/add.js +37 -0
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.js +93 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +22 -0
- package/dist/templates/expo/Accordion.d.ts +14 -0
- package/dist/templates/expo/Accordion.js +118 -0
- package/dist/templates/expo/Accordion.tsx +152 -0
- package/dist/templates/expo/AlertDialog.d.ts +12 -0
- package/dist/templates/expo/AlertDialog.js +126 -0
- package/dist/templates/expo/AlertDialog.tsx +147 -0
- package/dist/templates/expo/Avatar.d.ts +8 -0
- package/dist/templates/expo/Avatar.js +81 -0
- package/dist/templates/expo/Avatar.tsx +78 -0
- package/dist/templates/expo/Badge.d.ts +6 -0
- package/dist/templates/expo/Badge.js +60 -0
- package/dist/templates/expo/Badge.tsx +67 -0
- package/dist/templates/expo/Button.d.ts +9 -0
- package/dist/templates/expo/Button.js +37 -0
- package/dist/templates/expo/Button.tsx +53 -0
- package/dist/templates/expo/Dropdown.d.ts +12 -0
- package/dist/templates/expo/Dropdown.js +91 -0
- package/dist/templates/expo/Dropdown.tsx +100 -0
- package/dist/templates/expo/Input.d.ts +11 -0
- package/dist/templates/expo/Input.js +43 -0
- package/dist/templates/expo/Input.tsx +67 -0
- package/dist/templates/expo/Toast.d.ts +16 -0
- package/dist/templates/expo/Toast.js +142 -0
- package/dist/templates/expo/Toast.tsx +161 -0
- package/dist/templates/expo/utils.d.ts +4 -0
- package/dist/templates/expo/utils.js +10 -0
- package/dist/templates/expo/utils.ts +8 -0
- package/dist/templates/flutter/Accordion.dart +142 -0
- package/dist/templates/flutter/Alert.dart +96 -0
- package/dist/templates/flutter/AlertDialog.dart +175 -0
- package/dist/templates/flutter/Avatar.dart +82 -0
- package/dist/templates/flutter/Badge.dart +89 -0
- package/dist/templates/flutter/Button.dart +116 -0
- package/dist/templates/flutter/Card.dart +91 -0
- package/dist/templates/flutter/Input.dart +73 -0
- package/dist/templates/flutter/Text.dart +87 -0
- package/dist/templates/flutter/utils.dart +13 -0
- package/dist/templates/templates/expo/Button.tsx +50 -0
- package/dist/templates/templates/expo/Input.tsx +67 -0
- package/dist/templates/web/Accordion.d.ts +7 -0
- package/dist/templates/web/Accordion.js +59 -0
- package/dist/templates/web/Accordion.tsx +64 -0
- package/dist/templates/web/Alert.d.ts +9 -0
- package/dist/templates/web/Alert.js +64 -0
- package/dist/templates/web/Alert.tsx +71 -0
- package/dist/templates/web/AlertDialog.d.ts +14 -0
- package/dist/templates/web/AlertDialog.js +85 -0
- package/dist/templates/web/AlertDialog.tsx +164 -0
- package/dist/templates/web/Avatar.d.ts +6 -0
- package/dist/templates/web/Avatar.js +50 -0
- package/dist/templates/web/Avatar.tsx +51 -0
- package/dist/templates/web/Badge.d.ts +9 -0
- package/dist/templates/web/Badge.js +59 -0
- package/dist/templates/web/Badge.tsx +38 -0
- package/dist/templates/web/Button.d.ts +10 -0
- package/dist/templates/web/Button.js +70 -0
- package/dist/templates/web/Button.tsx +60 -0
- package/dist/templates/web/Card.d.ts +9 -0
- package/dist/templates/web/Card.js +65 -0
- package/dist/templates/web/Card.tsx +92 -0
- package/dist/templates/web/Dropdown.d.ts +27 -0
- package/dist/templates/web/Dropdown.js +95 -0
- package/dist/templates/web/Dropdown.tsx +198 -0
- package/dist/templates/web/Input.d.ts +3 -0
- package/dist/templates/web/Input.js +41 -0
- package/dist/templates/web/Input.tsx +21 -0
- package/dist/templates/web/Tabs.d.ts +7 -0
- package/dist/templates/web/Tabs.js +55 -0
- package/dist/templates/web/Tabs.tsx +66 -0
- package/dist/templates/web/Toast.d.ts +15 -0
- package/dist/templates/web/Toast.js +75 -0
- package/dist/templates/web/Toast.tsx +126 -0
- package/dist/templates/web/utils.d.ts +2 -0
- package/dist/templates/web/utils.js +8 -0
- package/dist/templates/web/utils.ts +6 -0
- package/dist/utils/detect.d.ts +19 -0
- package/dist/utils/detect.js +90 -0
- package/dist/utils/fs.d.ts +5 -0
- package/dist/utils/fs.js +35 -0
- package/getlotui.config.json +4 -0
- package/package.json +31 -0
- package/src/bin.ts +5 -0
- package/src/commands/add.ts +50 -0
- package/src/commands/init.ts +108 -0
- package/src/index.ts +23 -0
- package/src/templates/expo/Accordion.tsx +152 -0
- package/src/templates/expo/AlertDialog.tsx +147 -0
- package/src/templates/expo/Avatar.tsx +78 -0
- package/src/templates/expo/Badge.tsx +67 -0
- package/src/templates/expo/Button.tsx +53 -0
- package/src/templates/expo/Dropdown.tsx +100 -0
- package/src/templates/expo/Input.tsx +67 -0
- package/src/templates/expo/Toast.tsx +161 -0
- package/src/templates/expo/utils.ts +8 -0
- package/src/templates/flutter/Accordion.dart +142 -0
- package/src/templates/flutter/Alert.dart +96 -0
- package/src/templates/flutter/AlertDialog.dart +175 -0
- package/src/templates/flutter/Avatar.dart +82 -0
- package/src/templates/flutter/Badge.dart +89 -0
- package/src/templates/flutter/Button.dart +116 -0
- package/src/templates/flutter/Card.dart +91 -0
- package/src/templates/flutter/Input.dart +73 -0
- package/src/templates/flutter/Text.dart +87 -0
- package/src/templates/flutter/utils.dart +13 -0
- package/src/templates/web/Accordion.tsx +64 -0
- package/src/templates/web/Alert.tsx +71 -0
- package/src/templates/web/AlertDialog.tsx +164 -0
- package/src/templates/web/Avatar.tsx +51 -0
- package/src/templates/web/Badge.tsx +38 -0
- package/src/templates/web/Button.tsx +60 -0
- package/src/templates/web/Card.tsx +92 -0
- package/src/templates/web/Dropdown.tsx +198 -0
- package/src/templates/web/Input.tsx +21 -0
- package/src/templates/web/Tabs.tsx +66 -0
- package/src/templates/web/Toast.tsx +126 -0
- package/src/templates/web/utils.ts +6 -0
- package/src/utils/detect.ts +81 -0
- package/src/utils/fs.ts +32 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1,66 @@
|
|
|
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
|
+
function Tabs({
|
|
9
|
+
className,
|
|
10
|
+
...props
|
|
11
|
+
}: React.ComponentProps<typeof TabsPrimitive.Root>) {
|
|
12
|
+
return (
|
|
13
|
+
<TabsPrimitive.Root
|
|
14
|
+
data-slot="tabs"
|
|
15
|
+
className={cn('flex flex-col gap-2', className)}
|
|
16
|
+
{...props}
|
|
17
|
+
/>
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function TabsList({
|
|
22
|
+
className,
|
|
23
|
+
...props
|
|
24
|
+
}: React.ComponentProps<typeof TabsPrimitive.List>) {
|
|
25
|
+
return (
|
|
26
|
+
<TabsPrimitive.List
|
|
27
|
+
data-slot="tabs-list"
|
|
28
|
+
className={cn(
|
|
29
|
+
'bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]',
|
|
30
|
+
className,
|
|
31
|
+
)}
|
|
32
|
+
{...props}
|
|
33
|
+
/>
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function TabsTrigger({
|
|
38
|
+
className,
|
|
39
|
+
...props
|
|
40
|
+
}: React.ComponentProps<typeof TabsPrimitive.Trigger>) {
|
|
41
|
+
return (
|
|
42
|
+
<TabsPrimitive.Trigger
|
|
43
|
+
data-slot="tabs-trigger"
|
|
44
|
+
className={cn(
|
|
45
|
+
"data-[state=active]:bg-background dark:data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
46
|
+
className,
|
|
47
|
+
)}
|
|
48
|
+
{...props}
|
|
49
|
+
/>
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function TabsContent({
|
|
54
|
+
className,
|
|
55
|
+
...props
|
|
56
|
+
}: React.ComponentProps<typeof TabsPrimitive.Content>) {
|
|
57
|
+
return (
|
|
58
|
+
<TabsPrimitive.Content
|
|
59
|
+
data-slot="tabs-content"
|
|
60
|
+
className={cn('flex-1 outline-none', className)}
|
|
61
|
+
{...props}
|
|
62
|
+
/>
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export { Tabs, TabsList, TabsTrigger, TabsContent }
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as ToastPrimitive from "@radix-ui/react-toast";
|
|
3
|
+
import { type VariantProps } from "class-variance-authority";
|
|
4
|
+
declare const ToastProvider: React.FC<ToastPrimitive.ToastProviderProps>;
|
|
5
|
+
declare const ToastViewport: React.ForwardRefExoticComponent<Omit<ToastPrimitive.ToastViewportProps & React.RefAttributes<HTMLOListElement>, "ref"> & React.RefAttributes<HTMLOListElement>>;
|
|
6
|
+
declare const Toast: React.ForwardRefExoticComponent<Omit<ToastPrimitive.ToastProps & React.RefAttributes<HTMLLIElement>, "ref"> & VariantProps<(props?: ({
|
|
7
|
+
variant?: "default" | "destructive" | null | undefined;
|
|
8
|
+
} & import("class-variance-authority/dist/types").ClassProp) | undefined) => string> & React.RefAttributes<HTMLLIElement>>;
|
|
9
|
+
declare const ToastAction: React.ForwardRefExoticComponent<Omit<ToastPrimitive.ToastActionProps & React.RefAttributes<HTMLButtonElement>, "ref"> & React.RefAttributes<HTMLButtonElement>>;
|
|
10
|
+
declare const ToastClose: React.ForwardRefExoticComponent<Omit<ToastPrimitive.ToastCloseProps & React.RefAttributes<HTMLButtonElement>, "ref"> & React.RefAttributes<HTMLButtonElement>>;
|
|
11
|
+
declare const ToastTitle: React.ForwardRefExoticComponent<Omit<ToastPrimitive.ToastTitleProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
12
|
+
declare const ToastDescription: React.ForwardRefExoticComponent<Omit<ToastPrimitive.ToastDescriptionProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
13
|
+
type ToastProps = React.ComponentPropsWithoutRef<typeof Toast>;
|
|
14
|
+
type ToastActionElement = React.ReactElement<typeof ToastAction>;
|
|
15
|
+
export { type ToastProps, type ToastActionElement, ToastProvider, ToastViewport, Toast, ToastTitle, ToastDescription, ToastClose, ToastAction, };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.ToastAction = exports.ToastClose = exports.ToastDescription = exports.ToastTitle = exports.Toast = exports.ToastViewport = exports.ToastProvider = void 0;
|
|
37
|
+
const React = __importStar(require("react"));
|
|
38
|
+
const ToastPrimitive = __importStar(require("@radix-ui/react-toast"));
|
|
39
|
+
const class_variance_authority_1 = require("class-variance-authority");
|
|
40
|
+
const lucide_react_1 = require("lucide-react");
|
|
41
|
+
const utils_1 = require("./utils");
|
|
42
|
+
const ToastProvider = ToastPrimitive.Provider;
|
|
43
|
+
exports.ToastProvider = ToastProvider;
|
|
44
|
+
const ToastViewport = React.forwardRef(({ className, ...props }, ref) => (React.createElement(ToastPrimitive.Viewport, { ref: ref, className: (0, utils_1.cn)("fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]", className), ...props })));
|
|
45
|
+
exports.ToastViewport = ToastViewport;
|
|
46
|
+
ToastViewport.displayName = ToastPrimitive.Viewport.displayName;
|
|
47
|
+
const toastVariants = (0, class_variance_authority_1.cva)("group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[animated=true]:duration-300 data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full", {
|
|
48
|
+
variants: {
|
|
49
|
+
variant: {
|
|
50
|
+
default: "border bg-background text-foreground",
|
|
51
|
+
destructive: "destructive group border-destructive bg-destructive text-destructive-foreground",
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
defaultVariants: {
|
|
55
|
+
variant: "default",
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
const Toast = React.forwardRef(({ className, variant, ...props }, ref) => {
|
|
59
|
+
return (React.createElement(ToastPrimitive.Root, { ref: ref, className: (0, utils_1.cn)(toastVariants({ variant }), className), ...props }));
|
|
60
|
+
});
|
|
61
|
+
exports.Toast = Toast;
|
|
62
|
+
Toast.displayName = ToastPrimitive.Root.displayName;
|
|
63
|
+
const ToastAction = React.forwardRef(({ className, ...props }, ref) => (React.createElement(ToastPrimitive.Action, { ref: ref, className: (0, utils_1.cn)("inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium ring-offset-background transition-colors hover:bg-secondary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive", className), ...props })));
|
|
64
|
+
exports.ToastAction = ToastAction;
|
|
65
|
+
ToastAction.displayName = ToastPrimitive.Action.displayName;
|
|
66
|
+
const ToastClose = React.forwardRef(({ className, ...props }, ref) => (React.createElement(ToastPrimitive.Close, { ref: ref, className: (0, utils_1.cn)("absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50; group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600", className), "toast-close": "", ...props },
|
|
67
|
+
React.createElement(lucide_react_1.X, { className: "h-4 w-4" }))));
|
|
68
|
+
exports.ToastClose = ToastClose;
|
|
69
|
+
ToastClose.displayName = ToastPrimitive.Close.displayName;
|
|
70
|
+
const ToastTitle = React.forwardRef(({ className, ...props }, ref) => (React.createElement(ToastPrimitive.Title, { ref: ref, className: (0, utils_1.cn)("text-sm font-semibold", className), ...props })));
|
|
71
|
+
exports.ToastTitle = ToastTitle;
|
|
72
|
+
ToastTitle.displayName = ToastPrimitive.Title.displayName;
|
|
73
|
+
const ToastDescription = React.forwardRef(({ className, ...props }, ref) => (React.createElement(ToastPrimitive.Description, { ref: ref, className: (0, utils_1.cn)("text-sm opacity-90", className), ...props })));
|
|
74
|
+
exports.ToastDescription = ToastDescription;
|
|
75
|
+
ToastDescription.displayName = ToastPrimitive.Description.displayName;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as ToastPrimitive from "@radix-ui/react-toast";
|
|
3
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
4
|
+
import { X } from "lucide-react";
|
|
5
|
+
import { cn } from "./utils";
|
|
6
|
+
|
|
7
|
+
const ToastProvider = ToastPrimitive.Provider;
|
|
8
|
+
|
|
9
|
+
const ToastViewport = React.forwardRef<
|
|
10
|
+
React.ElementRef<typeof ToastPrimitive.Viewport>,
|
|
11
|
+
React.ComponentPropsWithoutRef<typeof ToastPrimitive.Viewport>
|
|
12
|
+
>(({ className, ...props }, ref) => (
|
|
13
|
+
<ToastPrimitive.Viewport
|
|
14
|
+
ref={ref}
|
|
15
|
+
className={cn(
|
|
16
|
+
"fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]",
|
|
17
|
+
className
|
|
18
|
+
)}
|
|
19
|
+
{...props}
|
|
20
|
+
/>
|
|
21
|
+
));
|
|
22
|
+
ToastViewport.displayName = ToastPrimitive.Viewport.displayName;
|
|
23
|
+
|
|
24
|
+
const toastVariants = cva(
|
|
25
|
+
"group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[animated=true]:duration-300 data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full",
|
|
26
|
+
{
|
|
27
|
+
variants: {
|
|
28
|
+
variant: {
|
|
29
|
+
default: "border bg-background text-foreground",
|
|
30
|
+
destructive:
|
|
31
|
+
"destructive group border-destructive bg-destructive text-destructive-foreground",
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
defaultVariants: {
|
|
35
|
+
variant: "default",
|
|
36
|
+
},
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
const Toast = React.forwardRef<
|
|
41
|
+
React.ElementRef<typeof ToastPrimitive.Root>,
|
|
42
|
+
React.ComponentPropsWithoutRef<typeof ToastPrimitive.Root> &
|
|
43
|
+
VariantProps<typeof toastVariants>
|
|
44
|
+
>(({ className, variant, ...props }, ref) => {
|
|
45
|
+
return (
|
|
46
|
+
<ToastPrimitive.Root
|
|
47
|
+
ref={ref}
|
|
48
|
+
className={cn(toastVariants({ variant }), className)}
|
|
49
|
+
{...props}
|
|
50
|
+
/>
|
|
51
|
+
);
|
|
52
|
+
});
|
|
53
|
+
Toast.displayName = ToastPrimitive.Root.displayName;
|
|
54
|
+
|
|
55
|
+
const ToastAction = React.forwardRef<
|
|
56
|
+
React.ElementRef<typeof ToastPrimitive.Action>,
|
|
57
|
+
React.ComponentPropsWithoutRef<typeof ToastPrimitive.Action>
|
|
58
|
+
>(({ className, ...props }, ref) => (
|
|
59
|
+
<ToastPrimitive.Action
|
|
60
|
+
ref={ref}
|
|
61
|
+
className={cn(
|
|
62
|
+
"inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium ring-offset-background transition-colors hover:bg-secondary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive",
|
|
63
|
+
className
|
|
64
|
+
)}
|
|
65
|
+
{...props}
|
|
66
|
+
/>
|
|
67
|
+
));
|
|
68
|
+
ToastAction.displayName = ToastPrimitive.Action.displayName;
|
|
69
|
+
|
|
70
|
+
const ToastClose = React.forwardRef<
|
|
71
|
+
React.ElementRef<typeof ToastPrimitive.Close>,
|
|
72
|
+
React.ComponentPropsWithoutRef<typeof ToastPrimitive.Close>
|
|
73
|
+
>(({ className, ...props }, ref) => (
|
|
74
|
+
<ToastPrimitive.Close
|
|
75
|
+
ref={ref}
|
|
76
|
+
className={cn(
|
|
77
|
+
"absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50; group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600",
|
|
78
|
+
className
|
|
79
|
+
)}
|
|
80
|
+
toast-close=""
|
|
81
|
+
{...props}
|
|
82
|
+
>
|
|
83
|
+
<X className="h-4 w-4" />
|
|
84
|
+
</ToastPrimitive.Close>
|
|
85
|
+
));
|
|
86
|
+
ToastClose.displayName = ToastPrimitive.Close.displayName;
|
|
87
|
+
|
|
88
|
+
const ToastTitle = React.forwardRef<
|
|
89
|
+
React.ElementRef<typeof ToastPrimitive.Title>,
|
|
90
|
+
React.ComponentPropsWithoutRef<typeof ToastPrimitive.Title>
|
|
91
|
+
>(({ className, ...props }, ref) => (
|
|
92
|
+
<ToastPrimitive.Title
|
|
93
|
+
ref={ref}
|
|
94
|
+
className={cn("text-sm font-semibold", className)}
|
|
95
|
+
{...props}
|
|
96
|
+
/>
|
|
97
|
+
));
|
|
98
|
+
ToastTitle.displayName = ToastPrimitive.Title.displayName;
|
|
99
|
+
|
|
100
|
+
const ToastDescription = React.forwardRef<
|
|
101
|
+
React.ElementRef<typeof ToastPrimitive.Description>,
|
|
102
|
+
React.ComponentPropsWithoutRef<typeof ToastPrimitive.Description>
|
|
103
|
+
>(({ className, ...props }, ref) => (
|
|
104
|
+
<ToastPrimitive.Description
|
|
105
|
+
ref={ref}
|
|
106
|
+
className={cn("text-sm opacity-90", className)}
|
|
107
|
+
{...props}
|
|
108
|
+
/>
|
|
109
|
+
));
|
|
110
|
+
ToastDescription.displayName = ToastPrimitive.Description.displayName;
|
|
111
|
+
|
|
112
|
+
type ToastProps = React.ComponentPropsWithoutRef<typeof Toast>;
|
|
113
|
+
|
|
114
|
+
type ToastActionElement = React.ReactElement<typeof ToastAction>;
|
|
115
|
+
|
|
116
|
+
export {
|
|
117
|
+
type ToastProps,
|
|
118
|
+
type ToastActionElement,
|
|
119
|
+
ToastProvider,
|
|
120
|
+
ToastViewport,
|
|
121
|
+
Toast,
|
|
122
|
+
ToastTitle,
|
|
123
|
+
ToastDescription,
|
|
124
|
+
ToastClose,
|
|
125
|
+
ToastAction,
|
|
126
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.cn = cn;
|
|
4
|
+
const clsx_1 = require("clsx");
|
|
5
|
+
const tailwind_merge_1 = require("tailwind-merge");
|
|
6
|
+
function cn(...inputs) {
|
|
7
|
+
return (0, tailwind_merge_1.twMerge)((0, clsx_1.clsx)(inputs));
|
|
8
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detect if the current project is an Expo project.
|
|
3
|
+
* Checks for presence of `expo` dependency in package.json
|
|
4
|
+
* or existence of `app.json` / `app.config.js`.
|
|
5
|
+
*/
|
|
6
|
+
export declare function detectExpoProject(cwd: string): Promise<boolean>;
|
|
7
|
+
/**
|
|
8
|
+
* Detect if the current project is a Flutter project.
|
|
9
|
+
* Checks for existence of `pubspec.yaml`.
|
|
10
|
+
*/
|
|
11
|
+
export declare function detectFlutterProject(cwd: string): Promise<boolean>;
|
|
12
|
+
/**
|
|
13
|
+
* Detect if the current project is a Web project (React/Next.js/Vite).
|
|
14
|
+
*/
|
|
15
|
+
export declare function detectWebProject(cwd: string): Promise<boolean>;
|
|
16
|
+
/**
|
|
17
|
+
* Detect the package manager used in the current directory.
|
|
18
|
+
*/
|
|
19
|
+
export declare function detectPackageManager(cwd: string): Promise<"npm" | "pnpm" | "yarn" | "bun">;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.detectExpoProject = detectExpoProject;
|
|
7
|
+
exports.detectFlutterProject = detectFlutterProject;
|
|
8
|
+
exports.detectWebProject = detectWebProject;
|
|
9
|
+
exports.detectPackageManager = detectPackageManager;
|
|
10
|
+
const fs_1 = __importDefault(require("fs"));
|
|
11
|
+
const path_1 = __importDefault(require("path"));
|
|
12
|
+
/**
|
|
13
|
+
* Detect if the current project is an Expo project.
|
|
14
|
+
* Checks for presence of `expo` dependency in package.json
|
|
15
|
+
* or existence of `app.json` / `app.config.js`.
|
|
16
|
+
*/
|
|
17
|
+
async function detectExpoProject(cwd) {
|
|
18
|
+
// Check package.json dependencies
|
|
19
|
+
try {
|
|
20
|
+
const pkgPath = path_1.default.join(cwd, "package.json");
|
|
21
|
+
const pkgContent = await fs_1.default.promises.readFile(pkgPath, "utf8");
|
|
22
|
+
const pkg = JSON.parse(pkgContent);
|
|
23
|
+
const deps = {
|
|
24
|
+
...(pkg.dependencies || {}),
|
|
25
|
+
...(pkg.devDependencies || {}),
|
|
26
|
+
};
|
|
27
|
+
if (deps["expo"])
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
// ignore errors, continue detection
|
|
32
|
+
}
|
|
33
|
+
// Check for app.json or app.config.js
|
|
34
|
+
const possibleFiles = ["app.json", "app.config.js", "app.config.ts"];
|
|
35
|
+
for (const file of possibleFiles) {
|
|
36
|
+
if (fs_1.default.existsSync(path_1.default.join(cwd, file)))
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Detect if the current project is a Flutter project.
|
|
43
|
+
* Checks for existence of `pubspec.yaml`.
|
|
44
|
+
*/
|
|
45
|
+
async function detectFlutterProject(cwd) {
|
|
46
|
+
return fs_1.default.existsSync(path_1.default.join(cwd, "pubspec.yaml"));
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Detect if the current project is a Web project (React/Next.js/Vite).
|
|
50
|
+
*/
|
|
51
|
+
async function detectWebProject(cwd) {
|
|
52
|
+
const possibleFiles = [
|
|
53
|
+
"next.config.js",
|
|
54
|
+
"next.config.ts",
|
|
55
|
+
"vite.config.js",
|
|
56
|
+
"vite.config.ts",
|
|
57
|
+
"package.json",
|
|
58
|
+
];
|
|
59
|
+
for (const file of possibleFiles) {
|
|
60
|
+
if (fs_1.default.existsSync(path_1.default.join(cwd, file))) {
|
|
61
|
+
if (file === "package.json") {
|
|
62
|
+
try {
|
|
63
|
+
const pkg = JSON.parse(fs_1.default.readFileSync(path_1.default.join(cwd, file), "utf8"));
|
|
64
|
+
const deps = {
|
|
65
|
+
...(pkg.dependencies || {}),
|
|
66
|
+
...(pkg.devDependencies || {}),
|
|
67
|
+
};
|
|
68
|
+
return !!(deps["next"] || deps["react-dom"] || deps["vite"]);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Detect the package manager used in the current directory.
|
|
81
|
+
*/
|
|
82
|
+
async function detectPackageManager(cwd) {
|
|
83
|
+
if (fs_1.default.existsSync(path_1.default.join(cwd, "pnpm-lock.yaml")))
|
|
84
|
+
return "pnpm";
|
|
85
|
+
if (fs_1.default.existsSync(path_1.default.join(cwd, "yarn.lock")))
|
|
86
|
+
return "yarn";
|
|
87
|
+
if (fs_1.default.existsSync(path_1.default.join(cwd, "bun.lockb")))
|
|
88
|
+
return "bun";
|
|
89
|
+
return "npm";
|
|
90
|
+
}
|
package/dist/utils/fs.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.copyComponent = copyComponent;
|
|
7
|
+
const fs_1 = require("fs");
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
10
|
+
/**
|
|
11
|
+
* Safely copy a component template to the destination.
|
|
12
|
+
* If the destination file already exists, it will be skipped and a warning shown.
|
|
13
|
+
*/
|
|
14
|
+
async function copyComponent(src, dest) {
|
|
15
|
+
try {
|
|
16
|
+
// Ensure source exists
|
|
17
|
+
await fs_1.promises.access(src);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
console.error(chalk_1.default.red(`Template not found at ${src}`));
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
await fs_1.promises.access(dest);
|
|
25
|
+
console.log(chalk_1.default.yellow(`File ${path_1.default.basename(dest)} already exists. Skipping copy.`));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
// dest does not exist, proceed
|
|
30
|
+
}
|
|
31
|
+
// Ensure destination directory exists
|
|
32
|
+
await fs_1.promises.mkdir(path_1.default.dirname(dest), { recursive: true });
|
|
33
|
+
await fs_1.promises.copyFile(src, dest);
|
|
34
|
+
console.log(chalk_1.default.green(`Copied ${path_1.default.basename(src)} to ${dest}`));
|
|
35
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "getlotui",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "CLI for GetLotUI component scaffolding",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"getlotui": "dist/bin.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc -p . && node -e \"require('fs-extra').copySync('src/templates', 'dist/templates')\"",
|
|
11
|
+
"prepare": "npm run build"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"getlotui",
|
|
15
|
+
"cli",
|
|
16
|
+
"component",
|
|
17
|
+
"scaffold"
|
|
18
|
+
],
|
|
19
|
+
"author": "",
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"chalk": "^5.3.0",
|
|
23
|
+
"commander": "^11.1.0",
|
|
24
|
+
"fs-extra": "^11.2.0"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/node": "^25.0.3",
|
|
28
|
+
"ts-node": "^10.9.2",
|
|
29
|
+
"typescript": "^5.4.5"
|
|
30
|
+
}
|
|
31
|
+
}
|
package/src/bin.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { promises as fs } from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
import { copyComponent } from "../utils/fs";
|
|
5
|
+
|
|
6
|
+
export async function addCommand(component: string) {
|
|
7
|
+
try {
|
|
8
|
+
const cwd = process.cwd();
|
|
9
|
+
const configPath = path.join(cwd, "getlotui.config.json");
|
|
10
|
+
// Ensure config exists
|
|
11
|
+
let config;
|
|
12
|
+
try {
|
|
13
|
+
const configContent = await fs.readFile(configPath, "utf8");
|
|
14
|
+
config = JSON.parse(configContent);
|
|
15
|
+
} catch {
|
|
16
|
+
console.error(
|
|
17
|
+
chalk.red("getlotui.config.json not found. Run `getlotui init` first.")
|
|
18
|
+
);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const adapter = config.adapter || "expo";
|
|
23
|
+
const extension = adapter === "flutter" ? "dart" : "tsx";
|
|
24
|
+
const componentsDir = path.resolve(
|
|
25
|
+
cwd,
|
|
26
|
+
config.componentsDir ||
|
|
27
|
+
(adapter === "flutter" ? "lib/components/ui" : "components/ui")
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
const componentName =
|
|
31
|
+
component.charAt(0).toUpperCase() + component.slice(1);
|
|
32
|
+
const templatePath = path.resolve(
|
|
33
|
+
__dirname,
|
|
34
|
+
"..",
|
|
35
|
+
"templates",
|
|
36
|
+
adapter,
|
|
37
|
+
`${componentName}.${extension}`
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
await copyComponent(
|
|
41
|
+
templatePath,
|
|
42
|
+
path.join(componentsDir, `${componentName}.${extension}`)
|
|
43
|
+
);
|
|
44
|
+
console.log(
|
|
45
|
+
chalk.green(`Component ${componentName} added to ${componentsDir}`)
|
|
46
|
+
);
|
|
47
|
+
} catch (err) {
|
|
48
|
+
console.error(chalk.red("Failed to add component:"), err);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { promises as fs } from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
import {
|
|
5
|
+
detectExpoProject,
|
|
6
|
+
detectFlutterProject,
|
|
7
|
+
detectWebProject,
|
|
8
|
+
detectPackageManager,
|
|
9
|
+
} from "../utils/detect";
|
|
10
|
+
|
|
11
|
+
export async function initCommand() {
|
|
12
|
+
try {
|
|
13
|
+
const cwd = process.cwd();
|
|
14
|
+
const configPath = path.join(cwd, "getlotui.config.json");
|
|
15
|
+
// Check if config already exists
|
|
16
|
+
try {
|
|
17
|
+
await fs.access(configPath);
|
|
18
|
+
console.log(
|
|
19
|
+
chalk.yellow("getlotui.config.json already exists. Skipping creation.")
|
|
20
|
+
);
|
|
21
|
+
return;
|
|
22
|
+
} catch {
|
|
23
|
+
// file does not exist, continue
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Detect adapter
|
|
27
|
+
let adapter: string = "unknown";
|
|
28
|
+
if (await detectExpoProject(cwd)) {
|
|
29
|
+
adapter = "expo";
|
|
30
|
+
} else if (await detectFlutterProject(cwd)) {
|
|
31
|
+
adapter = "flutter";
|
|
32
|
+
} else if (await detectWebProject(cwd)) {
|
|
33
|
+
adapter = "web";
|
|
34
|
+
}
|
|
35
|
+
// Detect package manager
|
|
36
|
+
const packageManager = await detectPackageManager(cwd);
|
|
37
|
+
|
|
38
|
+
const defaultConfig = {
|
|
39
|
+
adapter,
|
|
40
|
+
packageManager,
|
|
41
|
+
componentsDir:
|
|
42
|
+
adapter === "flutter" ? "lib/components/ui" : "components/ui",
|
|
43
|
+
themeDir: adapter === "flutter" ? "lib/theme" : "theme",
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
await fs.writeFile(
|
|
47
|
+
configPath,
|
|
48
|
+
JSON.stringify(defaultConfig, null, 2),
|
|
49
|
+
"utf8"
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
// Create theme directory
|
|
53
|
+
const fullThemeDir = path.join(cwd, defaultConfig.themeDir);
|
|
54
|
+
try {
|
|
55
|
+
await fs.mkdir(fullThemeDir, { recursive: true });
|
|
56
|
+
const isFlutter = adapter === "flutter";
|
|
57
|
+
const themeFileName = isFlutter ? "config.dart" : "config.ts";
|
|
58
|
+
const themeFilePath = path.join(fullThemeDir, themeFileName);
|
|
59
|
+
|
|
60
|
+
const themeContent = isFlutter
|
|
61
|
+
? `import 'package:flutter/material.dart';
|
|
62
|
+
|
|
63
|
+
class GetLotUITheme {
|
|
64
|
+
static const colors = {
|
|
65
|
+
'primary': Color(0xFF6366F1),
|
|
66
|
+
'background': Color(0xFFFFFFFF),
|
|
67
|
+
'foreground': Color(0xFF0F172A),
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
static const radius = {
|
|
71
|
+
'sm': 4.0,
|
|
72
|
+
'md': 8.0,
|
|
73
|
+
'lg': 12.0,
|
|
74
|
+
};
|
|
75
|
+
}`
|
|
76
|
+
: `export const theme = {
|
|
77
|
+
colors: {
|
|
78
|
+
primary: '#6366f1',
|
|
79
|
+
background: '#ffffff',
|
|
80
|
+
foreground: '#0f172a',
|
|
81
|
+
},
|
|
82
|
+
radius: {
|
|
83
|
+
sm: 4,
|
|
84
|
+
md: 8,
|
|
85
|
+
lg: 12,
|
|
86
|
+
},
|
|
87
|
+
spacing: {
|
|
88
|
+
unit: 8,
|
|
89
|
+
}
|
|
90
|
+
};`;
|
|
91
|
+
|
|
92
|
+
await fs.writeFile(themeFilePath, themeContent, "utf8");
|
|
93
|
+
console.log(
|
|
94
|
+
chalk.green(`Created ${defaultConfig.themeDir}/${themeFileName}`)
|
|
95
|
+
);
|
|
96
|
+
} catch (err) {
|
|
97
|
+
console.warn(chalk.yellow("Could not create theme directory:"), err);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
console.log(
|
|
101
|
+
chalk.green(
|
|
102
|
+
`Created getlotui.config.json with ${adapter} (${packageManager}) defaults.`
|
|
103
|
+
)
|
|
104
|
+
);
|
|
105
|
+
} catch (err) {
|
|
106
|
+
console.error(chalk.red("Failed to initialize GetLotUI config:"), err);
|
|
107
|
+
}
|
|
108
|
+
}
|