@helloleo/plugins 0.1.14 → 0.1.16

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 (125) hide show
  1. package/dist/index.js +197 -469
  2. package/dist/templates/tanstack-router-2026-06-15/components.json +22 -0
  3. package/dist/templates/tanstack-router-2026-06-15/index.html +13 -0
  4. package/dist/templates/tanstack-router-2026-06-15/package.json +94 -0
  5. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/accordion.tsx +51 -0
  6. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/alert-dialog.tsx +115 -0
  7. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/alert.tsx +49 -0
  8. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/aspect-ratio.tsx +5 -0
  9. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/avatar.tsx +47 -0
  10. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/badge.tsx +32 -0
  11. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/breadcrumb.tsx +101 -0
  12. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/button.tsx +49 -0
  13. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/calendar.tsx +177 -0
  14. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/card.tsx +55 -0
  15. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/carousel.tsx +240 -0
  16. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/chart.tsx +331 -0
  17. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/checkbox.tsx +26 -0
  18. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/collapsible.tsx +11 -0
  19. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/command.tsx +143 -0
  20. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/context-menu.tsx +187 -0
  21. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/dialog.tsx +104 -0
  22. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/drawer.tsx +98 -0
  23. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/dropdown-menu.tsx +188 -0
  24. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/form.tsx +171 -0
  25. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/hover-card.tsx +27 -0
  26. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/input-otp.tsx +69 -0
  27. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/input.tsx +22 -0
  28. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/label.tsx +21 -0
  29. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/menubar.tsx +229 -0
  30. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/navigation-menu.tsx +120 -0
  31. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/pagination.tsx +98 -0
  32. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/popover.tsx +31 -0
  33. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/progress.tsx +25 -0
  34. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/radio-group.tsx +36 -0
  35. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/resizable.tsx +37 -0
  36. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/scroll-area.tsx +44 -0
  37. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/select.tsx +152 -0
  38. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/separator.tsx +24 -0
  39. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/sheet.tsx +122 -0
  40. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/sidebar.tsx +744 -0
  41. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/skeleton.tsx +7 -0
  42. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/slider.tsx +23 -0
  43. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/sonner.tsx +23 -0
  44. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/switch.tsx +27 -0
  45. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/table.tsx +94 -0
  46. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/tabs.tsx +53 -0
  47. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/textarea.tsx +21 -0
  48. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/toggle-group.tsx +57 -0
  49. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/toggle.tsx +42 -0
  50. package/dist/templates/tanstack-router-2026-06-15/src/components/ui/tooltip.tsx +32 -0
  51. package/dist/templates/tanstack-router-2026-06-15/src/hooks/use-mobile.tsx +19 -0
  52. package/dist/templates/tanstack-router-2026-06-15/src/lib/proxy.ts +83 -0
  53. package/dist/templates/tanstack-router-2026-06-15/src/lib/utils.ts +6 -0
  54. package/dist/templates/tanstack-router-2026-06-15/src/main.tsx +33 -0
  55. package/dist/templates/tanstack-router-2026-06-15/src/routeTree.gen.ts +59 -0
  56. package/dist/templates/tanstack-router-2026-06-15/src/router.tsx +23 -0
  57. package/dist/templates/tanstack-router-2026-06-15/src/routes/__root.tsx +16 -0
  58. package/dist/templates/tanstack-router-2026-06-15/src/routes/index.tsx +14 -0
  59. package/dist/templates/tanstack-router-2026-06-15/src/styles.css +214 -0
  60. package/dist/templates/tanstack-router-2026-06-15/tsconfig.json +27 -0
  61. package/dist/templates/tanstack-router-2026-06-15/vite.config.ts +24 -0
  62. package/package.json +3 -2
  63. package/src/template-render.ts +48 -0
  64. package/src/templates/tanstack-router-2026-06-15/components.json +22 -0
  65. package/src/templates/tanstack-router-2026-06-15/index.html +13 -0
  66. package/src/templates/tanstack-router-2026-06-15/package.json +94 -0
  67. package/src/templates/tanstack-router-2026-06-15/src/components/ui/accordion.tsx +51 -0
  68. package/src/templates/tanstack-router-2026-06-15/src/components/ui/alert-dialog.tsx +115 -0
  69. package/src/templates/tanstack-router-2026-06-15/src/components/ui/alert.tsx +49 -0
  70. package/src/templates/tanstack-router-2026-06-15/src/components/ui/aspect-ratio.tsx +5 -0
  71. package/src/templates/tanstack-router-2026-06-15/src/components/ui/avatar.tsx +47 -0
  72. package/src/templates/tanstack-router-2026-06-15/src/components/ui/badge.tsx +32 -0
  73. package/src/templates/tanstack-router-2026-06-15/src/components/ui/breadcrumb.tsx +101 -0
  74. package/src/templates/tanstack-router-2026-06-15/src/components/ui/button.tsx +49 -0
  75. package/src/templates/tanstack-router-2026-06-15/src/components/ui/calendar.tsx +177 -0
  76. package/src/templates/tanstack-router-2026-06-15/src/components/ui/card.tsx +55 -0
  77. package/src/templates/tanstack-router-2026-06-15/src/components/ui/carousel.tsx +240 -0
  78. package/src/templates/tanstack-router-2026-06-15/src/components/ui/chart.tsx +331 -0
  79. package/src/templates/tanstack-router-2026-06-15/src/components/ui/checkbox.tsx +26 -0
  80. package/src/templates/tanstack-router-2026-06-15/src/components/ui/collapsible.tsx +11 -0
  81. package/src/templates/tanstack-router-2026-06-15/src/components/ui/command.tsx +143 -0
  82. package/src/templates/tanstack-router-2026-06-15/src/components/ui/context-menu.tsx +187 -0
  83. package/src/templates/tanstack-router-2026-06-15/src/components/ui/dialog.tsx +104 -0
  84. package/src/templates/tanstack-router-2026-06-15/src/components/ui/drawer.tsx +98 -0
  85. package/src/templates/tanstack-router-2026-06-15/src/components/ui/dropdown-menu.tsx +188 -0
  86. package/src/templates/tanstack-router-2026-06-15/src/components/ui/form.tsx +171 -0
  87. package/src/templates/tanstack-router-2026-06-15/src/components/ui/hover-card.tsx +27 -0
  88. package/src/templates/tanstack-router-2026-06-15/src/components/ui/input-otp.tsx +69 -0
  89. package/src/templates/tanstack-router-2026-06-15/src/components/ui/input.tsx +22 -0
  90. package/src/templates/tanstack-router-2026-06-15/src/components/ui/label.tsx +21 -0
  91. package/src/templates/tanstack-router-2026-06-15/src/components/ui/menubar.tsx +229 -0
  92. package/src/templates/tanstack-router-2026-06-15/src/components/ui/navigation-menu.tsx +120 -0
  93. package/src/templates/tanstack-router-2026-06-15/src/components/ui/pagination.tsx +98 -0
  94. package/src/templates/tanstack-router-2026-06-15/src/components/ui/popover.tsx +31 -0
  95. package/src/templates/tanstack-router-2026-06-15/src/components/ui/progress.tsx +25 -0
  96. package/src/templates/tanstack-router-2026-06-15/src/components/ui/radio-group.tsx +36 -0
  97. package/src/templates/tanstack-router-2026-06-15/src/components/ui/resizable.tsx +37 -0
  98. package/src/templates/tanstack-router-2026-06-15/src/components/ui/scroll-area.tsx +44 -0
  99. package/src/templates/tanstack-router-2026-06-15/src/components/ui/select.tsx +152 -0
  100. package/src/templates/tanstack-router-2026-06-15/src/components/ui/separator.tsx +24 -0
  101. package/src/templates/tanstack-router-2026-06-15/src/components/ui/sheet.tsx +122 -0
  102. package/src/templates/tanstack-router-2026-06-15/src/components/ui/sidebar.tsx +744 -0
  103. package/src/templates/tanstack-router-2026-06-15/src/components/ui/skeleton.tsx +7 -0
  104. package/src/templates/tanstack-router-2026-06-15/src/components/ui/slider.tsx +23 -0
  105. package/src/templates/tanstack-router-2026-06-15/src/components/ui/sonner.tsx +23 -0
  106. package/src/templates/tanstack-router-2026-06-15/src/components/ui/switch.tsx +27 -0
  107. package/src/templates/tanstack-router-2026-06-15/src/components/ui/table.tsx +94 -0
  108. package/src/templates/tanstack-router-2026-06-15/src/components/ui/tabs.tsx +53 -0
  109. package/src/templates/tanstack-router-2026-06-15/src/components/ui/textarea.tsx +21 -0
  110. package/src/templates/tanstack-router-2026-06-15/src/components/ui/toggle-group.tsx +57 -0
  111. package/src/templates/tanstack-router-2026-06-15/src/components/ui/toggle.tsx +42 -0
  112. package/src/templates/tanstack-router-2026-06-15/src/components/ui/tooltip.tsx +32 -0
  113. package/src/templates/tanstack-router-2026-06-15/src/hooks/use-mobile.tsx +19 -0
  114. package/src/templates/tanstack-router-2026-06-15/src/lib/proxy.ts +83 -0
  115. package/src/templates/tanstack-router-2026-06-15/src/lib/utils.ts +6 -0
  116. package/src/templates/tanstack-router-2026-06-15/src/main.tsx +33 -0
  117. package/src/templates/tanstack-router-2026-06-15/src/routeTree.gen.ts +59 -0
  118. package/src/templates/tanstack-router-2026-06-15/src/router.tsx +23 -0
  119. package/src/templates/tanstack-router-2026-06-15/src/routes/__root.tsx +16 -0
  120. package/src/templates/tanstack-router-2026-06-15/src/routes/index.tsx +14 -0
  121. package/src/templates/tanstack-router-2026-06-15/src/styles.css +214 -0
  122. package/src/templates/tanstack-router-2026-06-15/tsconfig.json +27 -0
  123. package/src/templates/tanstack-router-2026-06-15/vite.config.ts +24 -0
  124. package/src/tools/scaffold.ts +51 -444
  125. package/src/tools/setup-netsuite.ts +161 -80
@@ -0,0 +1,214 @@
1
+ /*
2
+ * HelloLeo Design System -- READ BEFORE STYLING.
3
+ *
4
+ * Design tokens are the single source of truth and power the no-code Design
5
+ * panel (the user edits colors / fonts / radius visually). Conventions:
6
+ * - Raw tokens live in :root (light) and .dark (dark). The @media
7
+ * (prefers-color-scheme: dark) block mirrors .dark so apps follow the OS
8
+ * by default; adding the `dark` class still forces dark explicitly.
9
+ * - @theme inline maps each raw token to a Tailwind utility
10
+ * (bg-background, text-foreground, rounded-lg, ...). Edit the raw token,
11
+ * not the component class. Never hardcode #hex in components.
12
+ * - When you add a color token, add it to :root, .dark, AND the media block,
13
+ * or one theme breaks.
14
+ *
15
+ * UI primitives live in src/components/ui (shadcn/ui) and consume these
16
+ * tokens. One responsibility per file.
17
+ */
18
+
19
+ @import "tailwindcss" source(none);
20
+ @source "../src";
21
+ @import "tw-animate-css";
22
+
23
+ @custom-variant dark (&:is(.dark *));
24
+
25
+ @theme inline {
26
+ --radius-sm: calc(var(--radius) - 4px);
27
+ --radius-md: calc(var(--radius) - 2px);
28
+ --radius-lg: var(--radius);
29
+ --radius-xl: calc(var(--radius) + 4px);
30
+ --color-background: var(--background);
31
+ --color-foreground: var(--foreground);
32
+ --color-card: var(--card);
33
+ --color-card-foreground: var(--card-foreground);
34
+ --color-popover: var(--popover);
35
+ --color-popover-foreground: var(--popover-foreground);
36
+ --color-primary: var(--primary);
37
+ --color-primary-foreground: var(--primary-foreground);
38
+ --color-secondary: var(--secondary);
39
+ --color-secondary-foreground: var(--secondary-foreground);
40
+ --color-muted: var(--muted);
41
+ --color-muted-foreground: var(--muted-foreground);
42
+ --color-accent: var(--accent);
43
+ --color-accent-foreground: var(--accent-foreground);
44
+ --color-destructive: var(--destructive);
45
+ --color-destructive-foreground: var(--destructive-foreground);
46
+ --color-border: var(--border);
47
+ --color-input: var(--input);
48
+ --color-ring: var(--ring);
49
+ --color-chart-1: var(--chart-1);
50
+ --color-chart-2: var(--chart-2);
51
+ --color-chart-3: var(--chart-3);
52
+ --color-chart-4: var(--chart-4);
53
+ --color-chart-5: var(--chart-5);
54
+ --color-sidebar: var(--sidebar);
55
+ --color-sidebar-foreground: var(--sidebar-foreground);
56
+ --color-sidebar-primary: var(--sidebar-primary);
57
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
58
+ --color-sidebar-accent: var(--sidebar-accent);
59
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
60
+ --color-sidebar-border: var(--sidebar-border);
61
+ --color-sidebar-ring: var(--sidebar-ring);
62
+ --font-sans: "Inter", system-ui, sans-serif;
63
+ --font-display: "Space Grotesk", "Inter", sans-serif;
64
+ }
65
+
66
+ :root {
67
+ --radius: 0.625rem;
68
+ --background: oklch(1 0 0);
69
+ --foreground: oklch(0.145 0 0);
70
+ --card: oklch(1 0 0);
71
+ --card-foreground: oklch(0.145 0 0);
72
+ --popover: oklch(1 0 0);
73
+ --popover-foreground: oklch(0.145 0 0);
74
+ --primary: oklch(0.205 0 0);
75
+ --primary-foreground: oklch(0.985 0 0);
76
+ --secondary: oklch(0.97 0 0);
77
+ --secondary-foreground: oklch(0.205 0 0);
78
+ --muted: oklch(0.97 0 0);
79
+ --muted-foreground: oklch(0.556 0 0);
80
+ --accent: oklch(0.97 0 0);
81
+ --accent-foreground: oklch(0.205 0 0);
82
+ --destructive: oklch(0.577 0.245 27.325);
83
+ --destructive-foreground: oklch(0.985 0 0);
84
+ --border: oklch(0.922 0 0);
85
+ --input: oklch(0.922 0 0);
86
+ --ring: oklch(0.708 0 0);
87
+ --chart-1: oklch(0.646 0.222 41.116);
88
+ --chart-2: oklch(0.6 0.118 184.704);
89
+ --chart-3: oklch(0.398 0.07 227.392);
90
+ --chart-4: oklch(0.828 0.189 84.429);
91
+ --chart-5: oklch(0.769 0.188 70.08);
92
+ --sidebar: oklch(0.985 0 0);
93
+ --sidebar-foreground: oklch(0.145 0 0);
94
+ --sidebar-primary: oklch(0.205 0 0);
95
+ --sidebar-primary-foreground: oklch(0.985 0 0);
96
+ --sidebar-accent: oklch(0.97 0 0);
97
+ --sidebar-accent-foreground: oklch(0.205 0 0);
98
+ --sidebar-border: oklch(0.922 0 0);
99
+ --sidebar-ring: oklch(0.708 0 0);
100
+ }
101
+
102
+ /* Dark palette -- kept identical in .dark (explicit) and the media block
103
+ * (system default). Edit BOTH when changing a token. */
104
+ .dark {
105
+ --background: oklch(0.145 0 0);
106
+ --foreground: oklch(0.985 0 0);
107
+ --card: oklch(0.205 0 0);
108
+ --card-foreground: oklch(0.985 0 0);
109
+ --popover: oklch(0.205 0 0);
110
+ --popover-foreground: oklch(0.985 0 0);
111
+ --primary: oklch(0.922 0 0);
112
+ --primary-foreground: oklch(0.205 0 0);
113
+ --secondary: oklch(0.269 0 0);
114
+ --secondary-foreground: oklch(0.985 0 0);
115
+ --muted: oklch(0.269 0 0);
116
+ --muted-foreground: oklch(0.708 0 0);
117
+ --accent: oklch(0.269 0 0);
118
+ --accent-foreground: oklch(0.985 0 0);
119
+ --destructive: oklch(0.704 0.191 22.216);
120
+ --destructive-foreground: oklch(0.985 0 0);
121
+ --border: oklch(1 0 0 / 10%);
122
+ --input: oklch(1 0 0 / 15%);
123
+ --ring: oklch(0.556 0 0);
124
+ --chart-1: oklch(0.488 0.243 264.376);
125
+ --chart-2: oklch(0.696 0.17 162.48);
126
+ --chart-3: oklch(0.769 0.188 70.08);
127
+ --chart-4: oklch(0.627 0.265 303.9);
128
+ --chart-5: oklch(0.645 0.246 16.439);
129
+ --sidebar: oklch(0.205 0 0);
130
+ --sidebar-foreground: oklch(0.985 0 0);
131
+ --sidebar-primary: oklch(0.488 0.243 264.376);
132
+ --sidebar-primary-foreground: oklch(0.985 0 0);
133
+ --sidebar-accent: oklch(0.269 0 0);
134
+ --sidebar-accent-foreground: oklch(0.985 0 0);
135
+ --sidebar-border: oklch(1 0 0 / 10%);
136
+ --sidebar-ring: oklch(0.556 0 0);
137
+ }
138
+
139
+ @media (prefers-color-scheme: dark) {
140
+ :root {
141
+ --background: oklch(0.145 0 0);
142
+ --foreground: oklch(0.985 0 0);
143
+ --card: oklch(0.205 0 0);
144
+ --card-foreground: oklch(0.985 0 0);
145
+ --popover: oklch(0.205 0 0);
146
+ --popover-foreground: oklch(0.985 0 0);
147
+ --primary: oklch(0.922 0 0);
148
+ --primary-foreground: oklch(0.205 0 0);
149
+ --secondary: oklch(0.269 0 0);
150
+ --secondary-foreground: oklch(0.985 0 0);
151
+ --muted: oklch(0.269 0 0);
152
+ --muted-foreground: oklch(0.708 0 0);
153
+ --accent: oklch(0.269 0 0);
154
+ --accent-foreground: oklch(0.985 0 0);
155
+ --destructive: oklch(0.704 0.191 22.216);
156
+ --destructive-foreground: oklch(0.985 0 0);
157
+ --border: oklch(1 0 0 / 10%);
158
+ --input: oklch(1 0 0 / 15%);
159
+ --ring: oklch(0.556 0 0);
160
+ --chart-1: oklch(0.488 0.243 264.376);
161
+ --chart-2: oklch(0.696 0.17 162.48);
162
+ --chart-3: oklch(0.769 0.188 70.08);
163
+ --chart-4: oklch(0.627 0.265 303.9);
164
+ --chart-5: oklch(0.645 0.246 16.439);
165
+ --sidebar: oklch(0.205 0 0);
166
+ --sidebar-foreground: oklch(0.985 0 0);
167
+ --sidebar-primary: oklch(0.488 0.243 264.376);
168
+ --sidebar-primary-foreground: oklch(0.985 0 0);
169
+ --sidebar-accent: oklch(0.269 0 0);
170
+ --sidebar-accent-foreground: oklch(0.985 0 0);
171
+ --sidebar-border: oklch(1 0 0 / 10%);
172
+ --sidebar-ring: oklch(0.556 0 0);
173
+ }
174
+ }
175
+
176
+ @layer base {
177
+ * {
178
+ border-color: var(--color-border);
179
+ }
180
+ html,
181
+ body {
182
+ font-family: var(--font-sans);
183
+ }
184
+ body {
185
+ background-color: var(--color-background);
186
+ color: var(--color-foreground);
187
+ min-height: 100vh;
188
+ }
189
+ h1, h2, h3, h4 {
190
+ font-family: var(--font-display);
191
+ letter-spacing: -0.02em;
192
+ }
193
+ }
194
+
195
+ @layer utilities {
196
+ .prose-note {
197
+ color: var(--color-foreground);
198
+ }
199
+ .prose-note h1 { font-size: 1.875rem; font-weight: 700; margin: 1.25rem 0 0.75rem; font-family: var(--font-display); }
200
+ .prose-note h2 { font-size: 1.5rem; font-weight: 600; margin: 1rem 0 0.5rem; font-family: var(--font-display); }
201
+ .prose-note h3 { font-size: 1.25rem; font-weight: 600; margin: 0.875rem 0 0.5rem; }
202
+ .prose-note p { margin: 0.5rem 0; line-height: 1.7; }
203
+ .prose-note ul { list-style: disc; padding-left: 1.5rem; margin: 0.5rem 0; }
204
+ .prose-note ol { list-style: decimal; padding-left: 1.5rem; margin: 0.5rem 0; }
205
+ .prose-note li { margin: 0.25rem 0; }
206
+ .prose-note a { color: var(--color-primary); text-decoration: underline; }
207
+ .prose-note code { background: var(--color-muted); padding: 0.125rem 0.375rem; border-radius: 0.25rem; font-size: 0.875em; }
208
+ .prose-note pre { background: var(--color-muted); padding: 1rem; border-radius: 0.5rem; overflow-x: auto; margin: 0.75rem 0; }
209
+ .prose-note pre code { background: transparent; padding: 0; }
210
+ .prose-note blockquote { border-left: 3px solid var(--color-primary); padding-left: 1rem; margin: 0.75rem 0; color: var(--color-muted-foreground); }
211
+ .prose-note hr { border-color: var(--color-border); margin: 1.5rem 0; }
212
+ .prose-note table { border-collapse: collapse; margin: 0.75rem 0; }
213
+ .prose-note th, .prose-note td { border: 1px solid var(--color-border); padding: 0.375rem 0.75rem; }
214
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "include": ["**/*.ts", "**/*.tsx"],
3
+ "compilerOptions": {
4
+ "target": "ES2022",
5
+ "jsx": "react-jsx",
6
+ "module": "ESNext",
7
+ "paths": {
8
+ "#/*": ["./src/*"],
9
+ "@/*": ["./src/*"]
10
+ },
11
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
12
+ "types": ["vite/client"],
13
+
14
+ /* Bundler mode */
15
+ "moduleResolution": "bundler",
16
+ "allowImportingTsExtensions": true,
17
+ "noEmit": true,
18
+
19
+ /* Linting */
20
+ "skipLibCheck": true,
21
+ "strict": true,
22
+ "noUnusedLocals": true,
23
+ "noUnusedParameters": true,
24
+ "noFallthroughCasesInSwitch": true,
25
+ "noUncheckedSideEffectImports": true
26
+ }
27
+ }
@@ -0,0 +1,24 @@
1
+ import { defineConfig } from 'vite'
2
+ import { devtools } from '@tanstack/devtools-vite'
3
+
4
+ import { tanstackRouter } from '@tanstack/router-plugin/vite'
5
+
6
+ import viteReact from '@vitejs/plugin-react'
7
+ import tailwindcss from '@tailwindcss/vite'
8
+
9
+ const config = defineConfig({
10
+ // Vite 8 resolves tsconfig `paths` (#/* and @/*) natively.
11
+ resolve: { tsconfigPaths: true },
12
+ server: {
13
+ allowedHosts: true,
14
+ hmr: { clientPort: 443, protocol: 'wss' },
15
+ },
16
+ plugins: [
17
+ devtools(),
18
+ tailwindcss(),
19
+ tanstackRouter({ target: 'react', autoCodeSplitting: true }),
20
+ viteReact(),
21
+ ],
22
+ })
23
+
24
+ export default config
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@helloleo/plugins",
3
- "version": "0.1.14",
3
+ "version": "0.1.16",
4
4
  "description": "OpenCode plugins for HelloLeo",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -16,10 +16,11 @@
16
16
  "access": "public"
17
17
  },
18
18
  "scripts": {
19
- "build": "bun build src/index.ts --outdir dist --target bun --format esm",
19
+ "build": "rm -rf dist && bun build src/index.ts --outdir dist --target bun --format esm && cp -R src/templates dist/templates",
20
20
  "format": "bunx --bun @biomejs/biome format --write src",
21
21
  "lint": "bunx --bun @biomejs/biome lint --write src",
22
22
  "check": "bunx --bun @biomejs/biome check --write src",
23
+ "sync-container": "bun run scripts/sync-container.ts",
23
24
  "prepublishOnly": "bun run check && bun run build"
24
25
  },
25
26
  "dependencies": {
@@ -0,0 +1,48 @@
1
+ import path from "node:path";
2
+ import { Glob } from "bun";
3
+
4
+ /**
5
+ * Scaffold templates live under src/templates/<template-id>/ as a real,
6
+ * editable file tree that mirrors the generated project 1:1 (open them, lint
7
+ * them, even `vite build` one directly). Files may contain {{LEO_*}} tokens
8
+ * that renderTemplate() substitutes at scaffold time. The token format is
9
+ * deliberately prefixed + UPPER_SNAKE so it never collides with JSX's `{{ }}`
10
+ * (which is always `{{ ` followed by a property, never `{{LEO_FOO}}`).
11
+ */
12
+
13
+ const TEMPLATES_ROOT = path.join(import.meta.dir, "templates");
14
+
15
+ export type TemplateVars = Record<string, string>;
16
+
17
+ const TOKEN_RE = /\{\{(LEO_[A-Z0-9_]+)\}\}/g;
18
+
19
+ // Never render generated/installed artifacts even if they leak into a template
20
+ // dir (e.g. a stray `bun install` there). Templates ship source only.
21
+ const SKIP =
22
+ /(^|\/)(node_modules|dist|dist-ssr|\.tanstack|\.output|bun\.lock|bun\.lockb|package-lock\.json|yarn\.lock|pnpm-lock\.yaml)(\/|$)/;
23
+
24
+ /**
25
+ * Copy a template tree into destDir, substituting {{LEO_*}} tokens. Returns
26
+ * the relative paths written (sorted). Bun.write creates parent dirs.
27
+ */
28
+ export async function renderTemplate(
29
+ templateId: string,
30
+ vars: TemplateVars,
31
+ destDir: string,
32
+ ): Promise<string[]> {
33
+ const root = path.join(TEMPLATES_ROOT, templateId);
34
+ const glob = new Glob("**/*");
35
+ const created: string[] = [];
36
+ for await (const rel of glob.scan({
37
+ cwd: root,
38
+ dot: true,
39
+ onlyFiles: true,
40
+ })) {
41
+ if (SKIP.test(rel)) continue;
42
+ const raw = await Bun.file(path.join(root, rel)).text();
43
+ const content = raw.replace(TOKEN_RE, (_m, key: string) => vars[key] ?? "");
44
+ await Bun.write(path.join(destDir, rel), content);
45
+ created.push(rel);
46
+ }
47
+ return created.sort();
48
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema.json",
3
+ "style": "new-york",
4
+ "rsc": false,
5
+ "tsx": true,
6
+ "tailwind": {
7
+ "css": "src/styles.css",
8
+ "baseColor": "slate",
9
+ "cssVariables": true,
10
+ "prefix": ""
11
+ },
12
+ "iconLibrary": "lucide",
13
+ "rtl": false,
14
+ "aliases": {
15
+ "components": "@/components",
16
+ "utils": "@/lib/utils",
17
+ "ui": "@/components/ui",
18
+ "lib": "@/lib",
19
+ "hooks": "@/hooks"
20
+ },
21
+ "registries": {}
22
+ }
@@ -0,0 +1,13 @@
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>{{LEO_NAME}}</title>
8
+ </head>
9
+ <body>
10
+ <div id="app"></div>
11
+ <script type="module" src="/src/main.tsx"></script>
12
+ </body>
13
+ </html>
@@ -0,0 +1,94 @@
1
+ {
2
+ "name": "{{LEO_NAME}}",
3
+ "private": true,
4
+ "type": "module",
5
+ "imports": {
6
+ "#/*": "./src/*"
7
+ },
8
+ "scripts": {
9
+ "dev": "vite dev",
10
+ "generate-routes": "tsr generate",
11
+ "build": "oxlint --fix && vite build",
12
+ "preview": "vite preview",
13
+ "lint": "oxlint --fix",
14
+ "test": "vitest run"
15
+ },
16
+ "dependencies": {
17
+ "@hookform/resolvers": "^5.2.2",
18
+ "@radix-ui/react-accordion": "^1.2.12",
19
+ "@radix-ui/react-alert-dialog": "^1.1.15",
20
+ "@radix-ui/react-aspect-ratio": "^1.1.8",
21
+ "@radix-ui/react-avatar": "^1.1.11",
22
+ "@radix-ui/react-checkbox": "^1.3.3",
23
+ "@radix-ui/react-collapsible": "^1.1.12",
24
+ "@radix-ui/react-context-menu": "^2.2.16",
25
+ "@radix-ui/react-dialog": "^1.1.15",
26
+ "@radix-ui/react-dropdown-menu": "^2.1.16",
27
+ "@radix-ui/react-hover-card": "^1.1.15",
28
+ "@radix-ui/react-label": "^2.1.8",
29
+ "@radix-ui/react-menubar": "^1.1.16",
30
+ "@radix-ui/react-navigation-menu": "^1.2.14",
31
+ "@radix-ui/react-popover": "^1.1.15",
32
+ "@radix-ui/react-progress": "^1.1.8",
33
+ "@radix-ui/react-radio-group": "^1.3.8",
34
+ "@radix-ui/react-scroll-area": "^1.2.10",
35
+ "@radix-ui/react-select": "^2.2.6",
36
+ "@radix-ui/react-separator": "^1.1.8",
37
+ "@radix-ui/react-slider": "^1.3.6",
38
+ "@radix-ui/react-slot": "^1.2.4",
39
+ "@radix-ui/react-switch": "^1.2.6",
40
+ "@radix-ui/react-tabs": "^1.1.13",
41
+ "@radix-ui/react-toggle": "^1.1.10",
42
+ "@radix-ui/react-toggle-group": "^1.1.11",
43
+ "@radix-ui/react-tooltip": "^1.2.8",
44
+ "@tailwindcss/vite": "^4.1.18",
45
+ "@tanstack/react-devtools": "latest",
46
+ "@tanstack/react-query": "^5.90.0",
47
+ "@tanstack/react-query-devtools": "^5.90.0",
48
+ "@tanstack/react-router": "latest",
49
+ "@tanstack/react-router-devtools": "latest",
50
+ "@tanstack/router-plugin": "^1.132.0",
51
+ "class-variance-authority": "^0.7.1",
52
+ "clsx": "^2.1.1",
53
+ "cmdk": "^1.1.1",
54
+ "date-fns": "^4.1.0",
55
+ "embla-carousel-react": "^8.6.0",
56
+ "input-otp": "^1.4.2",
57
+ "lucide-react": "^0.575.0",
58
+ "react": "^19.2.0",
59
+ "react-day-picker": "^9.14.0",
60
+ "react-dom": "^19.2.0",
61
+ "react-hook-form": "^7.71.2",
62
+ "react-resizable-panels": "^4.6.5",
63
+ "recharts": "^2.15.4",
64
+ "sonner": "^2.0.7",
65
+ "tailwind-merge": "^3.5.0",
66
+ "tailwindcss": "^4.1.18",
67
+ "tw-animate-css": "^1.3.4",
68
+ "vaul": "^1.1.2",
69
+ "zod": "^3.24.2"
70
+ },
71
+ "devDependencies": {
72
+ "@tailwindcss/typography": "^0.5.16",
73
+ "@tanstack/devtools-vite": "latest",
74
+ "@tanstack/router-cli": "^1.132.0",
75
+ "@tanstack/router-plugin": "latest",
76
+ "@testing-library/dom": "^10.4.1",
77
+ "@testing-library/react": "^16.3.0",
78
+ "@types/node": "^22.10.2",
79
+ "@types/react": "^19.2.0",
80
+ "@types/react-dom": "^19.2.0",
81
+ "@vitejs/plugin-react": "^6.0.1",
82
+ "jsdom": "^28.1.0",
83
+ "oxlint": "^1.69.0",
84
+ "typescript": "^6.0.2",
85
+ "vite": "^8.0.0",
86
+ "vitest": "^4.1.5"
87
+ },
88
+ "pnpm": {
89
+ "onlyBuiltDependencies": [
90
+ "esbuild",
91
+ "lightningcss"
92
+ ]
93
+ }
94
+ }
@@ -0,0 +1,51 @@
1
+ import * as React from "react";
2
+ import * as AccordionPrimitive from "@radix-ui/react-accordion";
3
+ import { ChevronDown } from "lucide-react";
4
+
5
+ import { cn } from "@/lib/utils";
6
+
7
+ const Accordion = AccordionPrimitive.Root;
8
+
9
+ const AccordionItem = React.forwardRef<
10
+ React.ElementRef<typeof AccordionPrimitive.Item>,
11
+ React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
12
+ >(({ className, ...props }, ref) => (
13
+ <AccordionPrimitive.Item ref={ref} className={cn("border-b", className)} {...props} />
14
+ ));
15
+ AccordionItem.displayName = "AccordionItem";
16
+
17
+ const AccordionTrigger = React.forwardRef<
18
+ React.ElementRef<typeof AccordionPrimitive.Trigger>,
19
+ React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
20
+ >(({ className, children, ...props }, ref) => (
21
+ <AccordionPrimitive.Header className="flex">
22
+ <AccordionPrimitive.Trigger
23
+ ref={ref}
24
+ className={cn(
25
+ "flex flex-1 items-center justify-between py-4 text-sm font-medium cursor-pointer transition-all hover:underline text-left [&[data-state=open]>svg]:rotate-180",
26
+ className,
27
+ )}
28
+ {...props}
29
+ >
30
+ {children}
31
+ <ChevronDown className="h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-200" />
32
+ </AccordionPrimitive.Trigger>
33
+ </AccordionPrimitive.Header>
34
+ ));
35
+ AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;
36
+
37
+ const AccordionContent = React.forwardRef<
38
+ React.ElementRef<typeof AccordionPrimitive.Content>,
39
+ React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
40
+ >(({ className, children, ...props }, ref) => (
41
+ <AccordionPrimitive.Content
42
+ ref={ref}
43
+ className="overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
44
+ {...props}
45
+ >
46
+ <div className={cn("pb-4 pt-0", className)}>{children}</div>
47
+ </AccordionPrimitive.Content>
48
+ ));
49
+ AccordionContent.displayName = AccordionPrimitive.Content.displayName;
50
+
51
+ export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };
@@ -0,0 +1,115 @@
1
+ import * as React from "react";
2
+ import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
3
+
4
+ import { cn } from "@/lib/utils";
5
+ import { buttonVariants } from "@/components/ui/button";
6
+
7
+ const AlertDialog = AlertDialogPrimitive.Root;
8
+
9
+ const AlertDialogTrigger = AlertDialogPrimitive.Trigger;
10
+
11
+ const AlertDialogPortal = AlertDialogPrimitive.Portal;
12
+
13
+ const AlertDialogOverlay = React.forwardRef<
14
+ React.ElementRef<typeof AlertDialogPrimitive.Overlay>,
15
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>
16
+ >(({ className, ...props }, ref) => (
17
+ <AlertDialogPrimitive.Overlay
18
+ className={cn(
19
+ "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
20
+ className,
21
+ )}
22
+ {...props}
23
+ ref={ref}
24
+ />
25
+ ));
26
+ AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;
27
+
28
+ const AlertDialogContent = React.forwardRef<
29
+ React.ElementRef<typeof AlertDialogPrimitive.Content>,
30
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>
31
+ >(({ className, ...props }, ref) => (
32
+ <AlertDialogPortal>
33
+ <AlertDialogOverlay />
34
+ <AlertDialogPrimitive.Content
35
+ ref={ref}
36
+ className={cn(
37
+ "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 sm:rounded-lg",
38
+ className,
39
+ )}
40
+ {...props}
41
+ />
42
+ </AlertDialogPortal>
43
+ ));
44
+ AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;
45
+
46
+ const AlertDialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
47
+ <div className={cn("flex flex-col space-y-2 text-center sm:text-left", className)} {...props} />
48
+ );
49
+ AlertDialogHeader.displayName = "AlertDialogHeader";
50
+
51
+ const AlertDialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
52
+ <div
53
+ className={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className)}
54
+ {...props}
55
+ />
56
+ );
57
+ AlertDialogFooter.displayName = "AlertDialogFooter";
58
+
59
+ const AlertDialogTitle = React.forwardRef<
60
+ React.ElementRef<typeof AlertDialogPrimitive.Title>,
61
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>
62
+ >(({ className, ...props }, ref) => (
63
+ <AlertDialogPrimitive.Title
64
+ ref={ref}
65
+ className={cn("text-lg font-semibold", className)}
66
+ {...props}
67
+ />
68
+ ));
69
+ AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;
70
+
71
+ const AlertDialogDescription = React.forwardRef<
72
+ React.ElementRef<typeof AlertDialogPrimitive.Description>,
73
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>
74
+ >(({ className, ...props }, ref) => (
75
+ <AlertDialogPrimitive.Description
76
+ ref={ref}
77
+ className={cn("text-sm text-muted-foreground", className)}
78
+ {...props}
79
+ />
80
+ ));
81
+ AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName;
82
+
83
+ const AlertDialogAction = React.forwardRef<
84
+ React.ElementRef<typeof AlertDialogPrimitive.Action>,
85
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>
86
+ >(({ className, ...props }, ref) => (
87
+ <AlertDialogPrimitive.Action ref={ref} className={cn(buttonVariants(), className)} {...props} />
88
+ ));
89
+ AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;
90
+
91
+ const AlertDialogCancel = React.forwardRef<
92
+ React.ElementRef<typeof AlertDialogPrimitive.Cancel>,
93
+ React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>
94
+ >(({ className, ...props }, ref) => (
95
+ <AlertDialogPrimitive.Cancel
96
+ ref={ref}
97
+ className={cn(buttonVariants({ variant: "outline" }), "mt-2 sm:mt-0", className)}
98
+ {...props}
99
+ />
100
+ ));
101
+ AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;
102
+
103
+ export {
104
+ AlertDialog,
105
+ AlertDialogPortal,
106
+ AlertDialogOverlay,
107
+ AlertDialogTrigger,
108
+ AlertDialogContent,
109
+ AlertDialogHeader,
110
+ AlertDialogFooter,
111
+ AlertDialogTitle,
112
+ AlertDialogDescription,
113
+ AlertDialogAction,
114
+ AlertDialogCancel,
115
+ };