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.
Files changed (128) hide show
  1. package/README.md +78 -0
  2. package/dist/bin.d.ts +2 -0
  3. package/dist/bin.js +5 -0
  4. package/dist/commands/add.d.ts +1 -0
  5. package/dist/commands/add.js +37 -0
  6. package/dist/commands/init.d.ts +1 -0
  7. package/dist/commands/init.js +93 -0
  8. package/dist/index.d.ts +1 -0
  9. package/dist/index.js +22 -0
  10. package/dist/templates/expo/Accordion.d.ts +14 -0
  11. package/dist/templates/expo/Accordion.js +118 -0
  12. package/dist/templates/expo/Accordion.tsx +152 -0
  13. package/dist/templates/expo/AlertDialog.d.ts +12 -0
  14. package/dist/templates/expo/AlertDialog.js +126 -0
  15. package/dist/templates/expo/AlertDialog.tsx +147 -0
  16. package/dist/templates/expo/Avatar.d.ts +8 -0
  17. package/dist/templates/expo/Avatar.js +81 -0
  18. package/dist/templates/expo/Avatar.tsx +78 -0
  19. package/dist/templates/expo/Badge.d.ts +6 -0
  20. package/dist/templates/expo/Badge.js +60 -0
  21. package/dist/templates/expo/Badge.tsx +67 -0
  22. package/dist/templates/expo/Button.d.ts +9 -0
  23. package/dist/templates/expo/Button.js +37 -0
  24. package/dist/templates/expo/Button.tsx +53 -0
  25. package/dist/templates/expo/Dropdown.d.ts +12 -0
  26. package/dist/templates/expo/Dropdown.js +91 -0
  27. package/dist/templates/expo/Dropdown.tsx +100 -0
  28. package/dist/templates/expo/Input.d.ts +11 -0
  29. package/dist/templates/expo/Input.js +43 -0
  30. package/dist/templates/expo/Input.tsx +67 -0
  31. package/dist/templates/expo/Toast.d.ts +16 -0
  32. package/dist/templates/expo/Toast.js +142 -0
  33. package/dist/templates/expo/Toast.tsx +161 -0
  34. package/dist/templates/expo/utils.d.ts +4 -0
  35. package/dist/templates/expo/utils.js +10 -0
  36. package/dist/templates/expo/utils.ts +8 -0
  37. package/dist/templates/flutter/Accordion.dart +142 -0
  38. package/dist/templates/flutter/Alert.dart +96 -0
  39. package/dist/templates/flutter/AlertDialog.dart +175 -0
  40. package/dist/templates/flutter/Avatar.dart +82 -0
  41. package/dist/templates/flutter/Badge.dart +89 -0
  42. package/dist/templates/flutter/Button.dart +116 -0
  43. package/dist/templates/flutter/Card.dart +91 -0
  44. package/dist/templates/flutter/Input.dart +73 -0
  45. package/dist/templates/flutter/Text.dart +87 -0
  46. package/dist/templates/flutter/utils.dart +13 -0
  47. package/dist/templates/templates/expo/Button.tsx +50 -0
  48. package/dist/templates/templates/expo/Input.tsx +67 -0
  49. package/dist/templates/web/Accordion.d.ts +7 -0
  50. package/dist/templates/web/Accordion.js +59 -0
  51. package/dist/templates/web/Accordion.tsx +64 -0
  52. package/dist/templates/web/Alert.d.ts +9 -0
  53. package/dist/templates/web/Alert.js +64 -0
  54. package/dist/templates/web/Alert.tsx +71 -0
  55. package/dist/templates/web/AlertDialog.d.ts +14 -0
  56. package/dist/templates/web/AlertDialog.js +85 -0
  57. package/dist/templates/web/AlertDialog.tsx +164 -0
  58. package/dist/templates/web/Avatar.d.ts +6 -0
  59. package/dist/templates/web/Avatar.js +50 -0
  60. package/dist/templates/web/Avatar.tsx +51 -0
  61. package/dist/templates/web/Badge.d.ts +9 -0
  62. package/dist/templates/web/Badge.js +59 -0
  63. package/dist/templates/web/Badge.tsx +38 -0
  64. package/dist/templates/web/Button.d.ts +10 -0
  65. package/dist/templates/web/Button.js +70 -0
  66. package/dist/templates/web/Button.tsx +60 -0
  67. package/dist/templates/web/Card.d.ts +9 -0
  68. package/dist/templates/web/Card.js +65 -0
  69. package/dist/templates/web/Card.tsx +92 -0
  70. package/dist/templates/web/Dropdown.d.ts +27 -0
  71. package/dist/templates/web/Dropdown.js +95 -0
  72. package/dist/templates/web/Dropdown.tsx +198 -0
  73. package/dist/templates/web/Input.d.ts +3 -0
  74. package/dist/templates/web/Input.js +41 -0
  75. package/dist/templates/web/Input.tsx +21 -0
  76. package/dist/templates/web/Tabs.d.ts +7 -0
  77. package/dist/templates/web/Tabs.js +55 -0
  78. package/dist/templates/web/Tabs.tsx +66 -0
  79. package/dist/templates/web/Toast.d.ts +15 -0
  80. package/dist/templates/web/Toast.js +75 -0
  81. package/dist/templates/web/Toast.tsx +126 -0
  82. package/dist/templates/web/utils.d.ts +2 -0
  83. package/dist/templates/web/utils.js +8 -0
  84. package/dist/templates/web/utils.ts +6 -0
  85. package/dist/utils/detect.d.ts +19 -0
  86. package/dist/utils/detect.js +90 -0
  87. package/dist/utils/fs.d.ts +5 -0
  88. package/dist/utils/fs.js +35 -0
  89. package/getlotui.config.json +4 -0
  90. package/package.json +31 -0
  91. package/src/bin.ts +5 -0
  92. package/src/commands/add.ts +50 -0
  93. package/src/commands/init.ts +108 -0
  94. package/src/index.ts +23 -0
  95. package/src/templates/expo/Accordion.tsx +152 -0
  96. package/src/templates/expo/AlertDialog.tsx +147 -0
  97. package/src/templates/expo/Avatar.tsx +78 -0
  98. package/src/templates/expo/Badge.tsx +67 -0
  99. package/src/templates/expo/Button.tsx +53 -0
  100. package/src/templates/expo/Dropdown.tsx +100 -0
  101. package/src/templates/expo/Input.tsx +67 -0
  102. package/src/templates/expo/Toast.tsx +161 -0
  103. package/src/templates/expo/utils.ts +8 -0
  104. package/src/templates/flutter/Accordion.dart +142 -0
  105. package/src/templates/flutter/Alert.dart +96 -0
  106. package/src/templates/flutter/AlertDialog.dart +175 -0
  107. package/src/templates/flutter/Avatar.dart +82 -0
  108. package/src/templates/flutter/Badge.dart +89 -0
  109. package/src/templates/flutter/Button.dart +116 -0
  110. package/src/templates/flutter/Card.dart +91 -0
  111. package/src/templates/flutter/Input.dart +73 -0
  112. package/src/templates/flutter/Text.dart +87 -0
  113. package/src/templates/flutter/utils.dart +13 -0
  114. package/src/templates/web/Accordion.tsx +64 -0
  115. package/src/templates/web/Alert.tsx +71 -0
  116. package/src/templates/web/AlertDialog.tsx +164 -0
  117. package/src/templates/web/Avatar.tsx +51 -0
  118. package/src/templates/web/Badge.tsx +38 -0
  119. package/src/templates/web/Button.tsx +60 -0
  120. package/src/templates/web/Card.tsx +92 -0
  121. package/src/templates/web/Dropdown.tsx +198 -0
  122. package/src/templates/web/Input.tsx +21 -0
  123. package/src/templates/web/Tabs.tsx +66 -0
  124. package/src/templates/web/Toast.tsx +126 -0
  125. package/src/templates/web/utils.ts +6 -0
  126. package/src/utils/detect.ts +81 -0
  127. package/src/utils/fs.ts +32 -0
  128. 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,2 @@
1
+ import { type ClassValue } from "clsx";
2
+ export declare function cn(...inputs: ClassValue[]): string;
@@ -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,6 @@
1
+ import { clsx, type ClassValue } from "clsx";
2
+ import { twMerge } from "tailwind-merge";
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs));
6
+ }
@@ -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
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Safely copy a component template to the destination.
3
+ * If the destination file already exists, it will be skipped and a warning shown.
4
+ */
5
+ export declare function copyComponent(src: string, dest: string): Promise<void>;
@@ -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
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "adapter": "unknown",
3
+ "componentsDir": "components/ui"
4
+ }
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,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { runCLI } from "./index";
4
+
5
+ runCLI();
@@ -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
+ }