luxlabs 1.0.2 → 1.0.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "luxlabs",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "CLI tool for Lux - Upload and deploy interfaces from your terminal",
5
5
  "author": "Jason Henkel <jason@uselux.ai>",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -3,6 +3,9 @@
3
3
  import { useEffect } from "react";
4
4
  import { useSession, signOut } from "@/lib/auth-client";
5
5
  import { useRouter } from "next/navigation";
6
+ import { createLux } from "@/lib/lux";
7
+
8
+ const lux = createLux("Dashboard");
6
9
 
7
10
  export default function DashboardPage() {
8
11
  const { data: session, isPending } = useSession();
@@ -16,7 +19,7 @@ export default function DashboardPage() {
16
19
 
17
20
  if (isPending) {
18
21
  return (
19
- <div className="min-h-screen flex items-center justify-center">
22
+ <div className="min-h-screen flex items-center justify-center" data-lux={lux("loading")}>
20
23
  <p>Loading...</p>
21
24
  </div>
22
25
  );
@@ -32,17 +35,18 @@ export default function DashboardPage() {
32
35
  }
33
36
 
34
37
  return (
35
- <div className="min-h-screen bg-zinc-50 p-8">
36
- <div className="max-w-2xl mx-auto bg-white p-8 rounded-lg shadow-md">
37
- <h1 className="text-2xl font-semibold mb-4">Dashboard</h1>
38
- <p className="text-zinc-600 mb-2">
38
+ <div className="min-h-screen bg-zinc-50 p-8" data-lux={lux("container")}>
39
+ <div className="max-w-2xl mx-auto bg-white p-8 rounded-lg shadow-md" data-lux={lux("card")}>
40
+ <h1 className="text-2xl font-semibold mb-4" data-lux={lux("title")}>Dashboard</h1>
41
+ <p className="text-zinc-600 mb-2" data-lux={lux("welcome")}>
39
42
  Welcome, <span className="font-medium">{session.user.name}</span>!
40
43
  </p>
41
- <p className="text-zinc-600 mb-6">
44
+ <p className="text-zinc-600 mb-6" data-lux={lux("email")}>
42
45
  Email: {session.user.email}
43
46
  </p>
44
47
  <button
45
48
  onClick={handleSignOut}
49
+ data-lux={lux("signout-button")}
46
50
  className="px-4 py-2 bg-black text-white rounded-md hover:bg-zinc-800"
47
51
  >
48
52
  Sign Out
@@ -1,36 +1,41 @@
1
1
  import Link from "next/link";
2
+ import { createLux } from "@/lib/lux";
3
+
4
+ const lux = createLux("Home");
2
5
 
3
6
  export default function Home() {
4
7
  return (
5
- <div className="min-h-screen flex flex-col bg-white">
8
+ <div className="min-h-screen flex flex-col bg-white" data-lux={lux("container")}>
6
9
  <main className="flex-1 flex flex-col items-center justify-center px-6">
7
10
  <div className="max-w-2xl w-full text-center">
8
- <p className="text-sm font-medium tracking-widest text-zinc-400 uppercase mb-4">
11
+ <p className="text-sm font-medium tracking-widest text-zinc-400 uppercase mb-4" data-lux={lux("tagline")}>
9
12
  Boilerplate
10
13
  </p>
11
- <h1 className="text-6xl font-semibold tracking-tight text-black mb-6">
14
+ <h1 className="text-6xl font-semibold tracking-tight text-black mb-6" data-lux={lux("title")}>
12
15
  Lux
13
16
  </h1>
14
- <p className="text-lg text-zinc-500 mb-12 max-w-md mx-auto">
17
+ <p className="text-lg text-zinc-500 mb-12 max-w-md mx-auto" data-lux={lux("description")}>
15
18
  Authentication, database, and UI components. Everything you need to start building.
16
19
  </p>
17
20
 
18
21
  <div className="flex gap-4 justify-center mb-16">
19
22
  <Link
20
23
  href="/sign-in"
24
+ data-lux={lux("signin-button")}
21
25
  className="px-8 py-3 bg-black text-white text-sm font-medium rounded-full hover:bg-zinc-800 transition-colors"
22
26
  >
23
27
  Sign In
24
28
  </Link>
25
29
  <Link
26
30
  href="/sign-up"
31
+ data-lux={lux("signup-button")}
27
32
  className="px-8 py-3 border border-zinc-200 text-black text-sm font-medium rounded-full hover:bg-zinc-50 transition-colors"
28
33
  >
29
34
  Sign Up
30
35
  </Link>
31
36
  </div>
32
37
 
33
- <div className="flex items-center justify-center gap-8 text-sm text-zinc-400">
38
+ <div className="flex items-center justify-center gap-8 text-sm text-zinc-400" data-lux={lux("features")}>
34
39
  <span>Next.js</span>
35
40
  <span className="w-1 h-1 bg-zinc-300 rounded-full" />
36
41
  <span>Auth</span>
@@ -42,7 +47,7 @@ export default function Home() {
42
47
  </div>
43
48
  </main>
44
49
 
45
- <footer className="py-6 text-center text-sm text-zinc-400">
50
+ <footer className="py-6 text-center text-sm text-zinc-400" data-lux={lux("footer")}>
46
51
  <p>Ready to ship.</p>
47
52
  </footer>
48
53
  </div>
@@ -3,6 +3,9 @@
3
3
  import { useSession, signOut } from "@/lib/auth-client";
4
4
  import { useRouter } from "next/navigation";
5
5
  import { useEffect } from "react";
6
+ import { createLux } from "@/lib/lux";
7
+
8
+ const lux = createLux("Settings");
6
9
 
7
10
  export default function SettingsPage() {
8
11
  const { data: session, isPending } = useSession();
@@ -16,7 +19,7 @@ export default function SettingsPage() {
16
19
 
17
20
  if (isPending) {
18
21
  return (
19
- <div className="min-h-screen flex items-center justify-center">
22
+ <div className="min-h-screen flex items-center justify-center" data-lux={lux("loading")}>
20
23
  <div className="text-gray-500">Loading...</div>
21
24
  </div>
22
25
  );
@@ -32,25 +35,25 @@ export default function SettingsPage() {
32
35
  };
33
36
 
34
37
  return (
35
- <div className="min-h-screen bg-gray-50">
38
+ <div className="min-h-screen bg-gray-50" data-lux={lux("container")}>
36
39
  <div className="max-w-2xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
37
40
  <div className="mb-8">
38
- <h1 className="text-3xl font-bold text-gray-900">Settings</h1>
39
- <p className="mt-2 text-sm text-gray-600">
41
+ <h1 className="text-3xl font-bold text-gray-900" data-lux={lux("title")}>Settings</h1>
42
+ <p className="mt-2 text-sm text-gray-600" data-lux={lux("subtitle")}>
40
43
  Manage your account settings
41
44
  </p>
42
45
  </div>
43
46
 
44
- <div className="bg-white shadow rounded-lg p-6">
45
- <h2 className="text-lg font-medium text-gray-900 mb-4">Account</h2>
47
+ <div className="bg-white shadow rounded-lg p-6" data-lux={lux("card")}>
48
+ <h2 className="text-lg font-medium text-gray-900 mb-4" data-lux={lux("section-title")}>Account</h2>
46
49
 
47
50
  <div className="space-y-4">
48
- <div>
51
+ <div data-lux={lux("name-field")}>
49
52
  <label className="block text-sm font-medium text-gray-700">Name</label>
50
53
  <p className="mt-1 text-sm text-gray-900">{session.user.name}</p>
51
54
  </div>
52
55
 
53
- <div>
56
+ <div data-lux={lux("email-field")}>
54
57
  <label className="block text-sm font-medium text-gray-700">Email</label>
55
58
  <p className="mt-1 text-sm text-gray-900">{session.user.email}</p>
56
59
  </div>
@@ -59,6 +62,7 @@ export default function SettingsPage() {
59
62
  <div className="mt-6 pt-6 border-t border-gray-200">
60
63
  <button
61
64
  onClick={handleSignOut}
65
+ data-lux={lux("signout-button")}
62
66
  className="px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700 transition-colors"
63
67
  >
64
68
  Sign Out
@@ -3,6 +3,9 @@
3
3
  import { useState } from "react";
4
4
  import { authClient } from "@/lib/auth-client";
5
5
  import { useRouter } from "next/navigation";
6
+ import { createLux } from "@/lib/lux";
7
+
8
+ const lux = createLux("SignInForm");
6
9
 
7
10
  export function SignInForm() {
8
11
  const router = useRouter();
@@ -44,10 +47,11 @@ export function SignInForm() {
44
47
  };
45
48
 
46
49
  return (
47
- <div className="space-y-6">
50
+ <div className="space-y-6" data-lux={lux("container")}>
48
51
  {/* Google Sign In */}
49
52
  <button
50
53
  onClick={handleGoogleSignIn}
54
+ data-lux={lux("google-button")}
51
55
  className="w-full flex items-center justify-center gap-3 px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors"
52
56
  >
53
57
  <svg className="w-5 h-5" viewBox="0 0 24 24">
@@ -81,7 +85,7 @@ export function SignInForm() {
81
85
  </div>
82
86
 
83
87
  {/* Email/Password Form */}
84
- <form onSubmit={handleEmailPassword} className="space-y-4">
88
+ <form onSubmit={handleEmailPassword} className="space-y-4" data-lux={lux("form")}>
85
89
  <div>
86
90
  <label className="block text-sm font-medium text-gray-700 mb-1">
87
91
  Email
@@ -91,6 +95,7 @@ export function SignInForm() {
91
95
  value={email}
92
96
  onChange={(e) => setEmail(e.target.value)}
93
97
  required
98
+ data-lux={lux("email-input")}
94
99
  className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-gray-900 focus:border-gray-900"
95
100
  placeholder="you@example.com"
96
101
  />
@@ -105,13 +110,14 @@ export function SignInForm() {
105
110
  value={password}
106
111
  onChange={(e) => setPassword(e.target.value)}
107
112
  required
113
+ data-lux={lux("password-input")}
108
114
  className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-gray-900 focus:border-gray-900"
109
115
  placeholder="••••••••"
110
116
  />
111
117
  </div>
112
118
 
113
119
  {error && (
114
- <div className="text-sm text-red-600 bg-red-50 border border-red-200 rounded px-3 py-2">
120
+ <div className="text-sm text-red-600 bg-red-50 border border-red-200 rounded px-3 py-2" data-lux={lux("error")}>
115
121
  {error}
116
122
  </div>
117
123
  )}
@@ -119,6 +125,7 @@ export function SignInForm() {
119
125
  <button
120
126
  type="submit"
121
127
  disabled={isLoading}
128
+ data-lux={lux("submit-button")}
122
129
  className="w-full px-4 py-2 bg-gray-900 text-white rounded-lg hover:bg-gray-800 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
123
130
  >
124
131
  {isLoading ? "Signing in..." : "Sign in"}
@@ -128,7 +135,7 @@ export function SignInForm() {
128
135
  {/* Sign Up Link */}
129
136
  <div className="text-center text-sm text-gray-600">
130
137
  Don&apos;t have an account?{" "}
131
- <a href="/sign-up" className="text-gray-900 hover:underline font-medium">
138
+ <a href="/sign-up" className="text-gray-900 hover:underline font-medium" data-lux={lux("signup-link")}>
132
139
  Sign up
133
140
  </a>
134
141
  </div>
@@ -3,6 +3,9 @@
3
3
  import { useState } from "react";
4
4
  import { authClient } from "@/lib/auth-client";
5
5
  import { useRouter } from "next/navigation";
6
+ import { createLux } from "@/lib/lux";
7
+
8
+ const lux = createLux("SignUpForm");
6
9
 
7
10
  export function SignUpForm() {
8
11
  const router = useRouter();
@@ -63,10 +66,11 @@ export function SignUpForm() {
63
66
  };
64
67
 
65
68
  return (
66
- <div className="space-y-6">
69
+ <div className="space-y-6" data-lux={lux("container")}>
67
70
  {/* Google Sign Up */}
68
71
  <button
69
72
  onClick={handleGoogleSignUp}
73
+ data-lux={lux("google-button")}
70
74
  className="w-full flex items-center justify-center gap-3 px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors"
71
75
  >
72
76
  <svg className="w-5 h-5" viewBox="0 0 24 24">
@@ -100,7 +104,7 @@ export function SignUpForm() {
100
104
  </div>
101
105
 
102
106
  {/* Sign Up Form */}
103
- <form onSubmit={handleAccountSubmit} className="space-y-4">
107
+ <form onSubmit={handleAccountSubmit} className="space-y-4" data-lux={lux("form")}>
104
108
  <div>
105
109
  <label className="block text-sm font-medium text-gray-700 mb-1">
106
110
  Name
@@ -110,6 +114,7 @@ export function SignUpForm() {
110
114
  value={name}
111
115
  onChange={(e) => setName(e.target.value)}
112
116
  required
117
+ data-lux={lux("name-input")}
113
118
  className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-gray-900 focus:border-gray-900"
114
119
  placeholder="John Doe"
115
120
  />
@@ -124,6 +129,7 @@ export function SignUpForm() {
124
129
  value={email}
125
130
  onChange={(e) => setEmail(e.target.value)}
126
131
  required
132
+ data-lux={lux("email-input")}
127
133
  className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-gray-900 focus:border-gray-900"
128
134
  placeholder="you@example.com"
129
135
  />
@@ -140,12 +146,14 @@ export function SignUpForm() {
140
146
  onChange={(e) => setPassword(e.target.value)}
141
147
  required
142
148
  minLength={8}
149
+ data-lux={lux("password-input")}
143
150
  className="w-full px-3 py-2 pr-10 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-gray-900 focus:border-gray-900"
144
151
  placeholder="••••••••"
145
152
  />
146
153
  <button
147
154
  type="button"
148
155
  onClick={() => setShowPassword(!showPassword)}
156
+ data-lux={lux("toggle-password")}
149
157
  className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-gray-600"
150
158
  >
151
159
  {showPassword ? (
@@ -176,12 +184,14 @@ export function SignUpForm() {
176
184
  onChange={(e) => setConfirmPassword(e.target.value)}
177
185
  required
178
186
  minLength={8}
187
+ data-lux={lux("confirm-password-input")}
179
188
  className="w-full px-3 py-2 pr-10 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-gray-900 focus:border-gray-900"
180
189
  placeholder="••••••••"
181
190
  />
182
191
  <button
183
192
  type="button"
184
193
  onClick={() => setShowConfirmPassword(!showConfirmPassword)}
194
+ data-lux={lux("toggle-confirm-password")}
185
195
  className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-gray-600"
186
196
  >
187
197
  {showConfirmPassword ? (
@@ -199,7 +209,7 @@ export function SignUpForm() {
199
209
  </div>
200
210
 
201
211
  {error && (
202
- <div className="text-sm text-red-600 bg-red-50 border border-red-200 rounded px-3 py-2">
212
+ <div className="text-sm text-red-600 bg-red-50 border border-red-200 rounded px-3 py-2" data-lux={lux("error")}>
203
213
  {error}
204
214
  </div>
205
215
  )}
@@ -207,6 +217,7 @@ export function SignUpForm() {
207
217
  <button
208
218
  type="submit"
209
219
  disabled={isLoading}
220
+ data-lux={lux("submit-button")}
210
221
  className="w-full px-4 py-2 bg-gray-900 text-white rounded-lg hover:bg-gray-800 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
211
222
  >
212
223
  {isLoading ? "Creating account..." : "Sign Up"}
@@ -216,7 +227,7 @@ export function SignUpForm() {
216
227
  {/* Sign In Link */}
217
228
  <div className="text-center text-sm text-gray-600">
218
229
  Already have an account?{" "}
219
- <a href="/sign-in" className="text-gray-900 hover:underline font-medium">
230
+ <a href="/sign-in" className="text-gray-900 hover:underline font-medium" data-lux={lux("signin-link")}>
220
231
  Sign in
221
232
  </a>
222
233
  </div>
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Creates a lux helper for generating data-lux attribute values
3
+ * @param componentName - The name of the component
4
+ * @returns A function that generates prefixed element IDs
5
+ */
6
+ export function createLux(componentName: string) {
7
+ return (elementId: string) => `${componentName}__${elementId}`;
8
+ }