@ultrst-armada/floks 1.2.2 → 1.2.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 +1 -1
- package/packages/canvas-ui/dist/index.js +6 -6
- package/packages/ui/dist/chunk-2SFOC7KZ.js +266 -0
- package/packages/ui/dist/{chunk-ELZOBTWX.js → chunk-DT6DZU63.js} +145 -119
- package/packages/ui/dist/components/auth/index.d.ts +35 -1
- package/packages/ui/dist/components/auth/index.js +3 -1
- package/packages/ui/dist/components/workspace/index.d.ts +34 -8
- package/packages/ui/dist/components/workspace/index.js +1 -1
- package/packages/ui/dist/index.d.ts +1 -1
- package/packages/ui/dist/index.js +17 -15
- package/packages/ui/floks.manifest.json +10 -1
- package/packages/ui/dist/chunk-S227WJ5E.js +0 -152
package/package.json
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CanvasViewport,
|
|
3
|
+
InfiniteCanvas,
|
|
4
|
+
MiniMap,
|
|
5
|
+
useCanvas
|
|
6
|
+
} from "./chunk-34YRDZPJ.js";
|
|
1
7
|
import {
|
|
2
8
|
DockBar,
|
|
3
9
|
DockItem,
|
|
@@ -19,12 +25,6 @@ import {
|
|
|
19
25
|
useCanvas2DCoordinates,
|
|
20
26
|
useCanvas2DMagnetic
|
|
21
27
|
} from "./chunk-XVAHT5WE.js";
|
|
22
|
-
import {
|
|
23
|
-
CanvasViewport,
|
|
24
|
-
InfiniteCanvas,
|
|
25
|
-
MiniMap,
|
|
26
|
-
useCanvas
|
|
27
|
-
} from "./chunk-34YRDZPJ.js";
|
|
28
28
|
import {
|
|
29
29
|
MonacoEditor,
|
|
30
30
|
skipoDarkTheme,
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BaseInput
|
|
3
|
+
} from "./chunk-W42SJGOJ.js";
|
|
4
|
+
import {
|
|
5
|
+
BaseButton
|
|
6
|
+
} from "./chunk-A2CDQISJ.js";
|
|
7
|
+
|
|
8
|
+
// src/components/auth/AuthPage.tsx
|
|
9
|
+
import { useState } from "react";
|
|
10
|
+
import { LogIn, UserPlus, Eye, EyeOff, Shield, ArrowRight, AlertCircle } from "lucide-react";
|
|
11
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
+
var AuthPage = ({
|
|
13
|
+
appName = "SKIPO",
|
|
14
|
+
appSubtitle = "WORKSPACE",
|
|
15
|
+
footerText,
|
|
16
|
+
onLogin,
|
|
17
|
+
onRegister,
|
|
18
|
+
onSuccess,
|
|
19
|
+
onSwitchToAdmin
|
|
20
|
+
}) => {
|
|
21
|
+
const [mode, setMode] = useState("login");
|
|
22
|
+
const [name, setName] = useState("");
|
|
23
|
+
const [email, setEmail] = useState("");
|
|
24
|
+
const [password, setPassword] = useState("");
|
|
25
|
+
const [showPassword, setShowPassword] = useState(false);
|
|
26
|
+
const [loading, setLoading] = useState(false);
|
|
27
|
+
const [error, setError] = useState(null);
|
|
28
|
+
const submit = async (e) => {
|
|
29
|
+
e.preventDefault();
|
|
30
|
+
setError(null);
|
|
31
|
+
const cleanEmail = email.trim();
|
|
32
|
+
if (!cleanEmail) return setError("Email address is required.");
|
|
33
|
+
if (!password) return setError("Password is required.");
|
|
34
|
+
if (mode === "register" && !name.trim()) return setError("Please enter your full name or display name.");
|
|
35
|
+
if (mode === "register" && password.length < 4) return setError("Password must be at least 4 characters long.");
|
|
36
|
+
setLoading(true);
|
|
37
|
+
try {
|
|
38
|
+
const result = mode === "login" ? await onLogin(cleanEmail, password) : await onRegister({ name: name.trim(), email: cleanEmail, password });
|
|
39
|
+
if (!result.success) throw new Error(result.error || "Authentication failed.");
|
|
40
|
+
onSuccess?.(result);
|
|
41
|
+
} catch (err) {
|
|
42
|
+
setError(err?.message || "An unexpected error occurred.");
|
|
43
|
+
} finally {
|
|
44
|
+
setLoading(false);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
return /* @__PURE__ */ jsxs("div", { className: "min-h-screen w-full bg-[var(--skipo-bg)] text-[var(--skipo-text)] font-mono flex flex-col justify-between select-none", children: [
|
|
48
|
+
/* @__PURE__ */ jsxs("header", { className: "border-b-2 border-[var(--skipo-border-color)] bg-[var(--skipo-surface)] px-6 py-3.5 flex items-center justify-between", children: [
|
|
49
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
50
|
+
/* @__PURE__ */ jsx("div", { className: "w-8 h-8 bg-[var(--skipo-accent)] text-black font-black flex items-center justify-center border border-[var(--skipo-border-color)]", children: "\u25B2" }),
|
|
51
|
+
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
52
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-black uppercase tracking-wider", children: appName }),
|
|
53
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] text-[var(--skipo-text-muted)] font-bold", children: appSubtitle })
|
|
54
|
+
] }) })
|
|
55
|
+
] }),
|
|
56
|
+
onSwitchToAdmin && /* @__PURE__ */ jsxs("button", { type: "button", onClick: onSwitchToAdmin, className: "px-3 py-1.5 text-xs font-black uppercase tracking-wider border-2 border-[#D4AF37] bg-[#D4AF37]/10 text-[#D4AF37] hover:bg-[#D4AF37] hover:text-black flex items-center gap-1.5 shadow-[2px_2px_0px_#D4AF37]", children: [
|
|
57
|
+
/* @__PURE__ */ jsx(Shield, { size: 13 }),
|
|
58
|
+
" ADMIN LOGIN ",
|
|
59
|
+
/* @__PURE__ */ jsx(ArrowRight, { size: 13 })
|
|
60
|
+
] })
|
|
61
|
+
] }),
|
|
62
|
+
/* @__PURE__ */ jsx("main", { className: "flex-1 flex items-center justify-center p-4", children: /* @__PURE__ */ jsxs("div", { className: "w-full max-w-md border-2 border-[var(--skipo-border-color)] bg-[var(--skipo-surface)] shadow-[6px_6px_0px_var(--skipo-border-color)] p-6", children: [
|
|
63
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-2 mb-6 border-b border-[var(--skipo-border-color)] pb-3", children: ["login", "register"].map((next) => /* @__PURE__ */ jsxs(
|
|
64
|
+
"button",
|
|
65
|
+
{
|
|
66
|
+
type: "button",
|
|
67
|
+
onClick: () => {
|
|
68
|
+
setMode(next);
|
|
69
|
+
setError(null);
|
|
70
|
+
},
|
|
71
|
+
className: `py-2 text-xs font-black uppercase tracking-wider flex items-center justify-center gap-1.5 border ${mode === next ? "bg-[var(--skipo-accent)] text-black border-[var(--skipo-border-color)]" : "bg-[var(--skipo-bg)] text-[var(--skipo-text-muted)] border-transparent"}`,
|
|
72
|
+
children: [
|
|
73
|
+
next === "login" ? /* @__PURE__ */ jsx(LogIn, { size: 13 }) : /* @__PURE__ */ jsx(UserPlus, { size: 13 }),
|
|
74
|
+
next === "login" ? "SIGN IN" : "CREATE ACCOUNT"
|
|
75
|
+
]
|
|
76
|
+
},
|
|
77
|
+
next
|
|
78
|
+
)) }),
|
|
79
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
80
|
+
/* @__PURE__ */ jsx("h2", { className: "text-sm font-black uppercase tracking-wider", children: mode === "login" ? "WORKSPACE SIGN IN" : "NEW DEVELOPER ACCOUNT" }),
|
|
81
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-[var(--skipo-text-muted)] mt-1", children: mode === "login" ? "Sign in to access your workspaces and application control plane." : "Create an account to manage your workspaces and applications." })
|
|
82
|
+
] }),
|
|
83
|
+
error && /* @__PURE__ */ jsxs("div", { className: "mb-4 p-3 border-2 border-red-500/80 bg-red-950/40 text-red-300 text-xs flex items-start gap-2", children: [
|
|
84
|
+
/* @__PURE__ */ jsx(AlertCircle, { size: 15, className: "shrink-0 mt-0.5" }),
|
|
85
|
+
/* @__PURE__ */ jsx("div", { children: error })
|
|
86
|
+
] }),
|
|
87
|
+
/* @__PURE__ */ jsxs("form", { onSubmit: submit, className: "space-y-4", children: [
|
|
88
|
+
mode === "register" && /* @__PURE__ */ jsxs("div", { children: [
|
|
89
|
+
/* @__PURE__ */ jsx("label", { className: "block text-[11px] font-bold text-[var(--skipo-text-muted)] uppercase tracking-wider mb-1", children: "Full Name" }),
|
|
90
|
+
/* @__PURE__ */ jsx("input", { value: name, onChange: (e) => setName(e.target.value), placeholder: "e.g. Jane Developer", required: true, className: "w-full bg-[var(--skipo-bg)] border border-[var(--skipo-border-color)] focus:border-[var(--skipo-accent)] text-[var(--skipo-text)] text-xs px-3 py-2.5 outline-none font-mono" })
|
|
91
|
+
] }),
|
|
92
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
93
|
+
/* @__PURE__ */ jsx("label", { className: "block text-[11px] font-bold text-[var(--skipo-text-muted)] uppercase tracking-wider mb-1", children: "Email Address or Username" }),
|
|
94
|
+
/* @__PURE__ */ jsx("input", { value: email, onChange: (e) => setEmail(e.target.value), placeholder: "e.g. developer@example.com", autoComplete: "username", required: true, className: "w-full bg-[var(--skipo-bg)] border border-[var(--skipo-border-color)] focus:border-[var(--skipo-accent)] text-[var(--skipo-text)] text-xs px-3 py-2.5 outline-none font-mono" })
|
|
95
|
+
] }),
|
|
96
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
97
|
+
/* @__PURE__ */ jsx("label", { className: "block text-[11px] font-bold text-[var(--skipo-text-muted)] uppercase tracking-wider mb-1", children: "Password" }),
|
|
98
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
99
|
+
/* @__PURE__ */ jsx("input", { type: showPassword ? "text" : "password", value: password, onChange: (e) => setPassword(e.target.value), autoComplete: mode === "login" ? "current-password" : "new-password", required: true, className: "w-full bg-[var(--skipo-bg)] border border-[var(--skipo-border-color)] focus:border-[var(--skipo-accent)] text-[var(--skipo-text)] text-xs px-3 py-2.5 outline-none font-mono pr-10" }),
|
|
100
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => setShowPassword((v) => !v), className: "absolute right-3 top-2.5 text-[var(--skipo-text-muted)]", children: showPassword ? /* @__PURE__ */ jsx(EyeOff, { size: 14 }) : /* @__PURE__ */ jsx(Eye, { size: 14 }) })
|
|
101
|
+
] })
|
|
102
|
+
] }),
|
|
103
|
+
/* @__PURE__ */ jsxs("button", { type: "submit", disabled: loading, className: "w-full py-2.5 bg-[var(--skipo-accent)] hover:opacity-90 text-black font-black text-xs uppercase tracking-wider flex items-center justify-center gap-2 shadow-[2px_2px_0px_#000] disabled:opacity-50", children: [
|
|
104
|
+
/* @__PURE__ */ jsx(LogIn, { size: 14 }),
|
|
105
|
+
" ",
|
|
106
|
+
loading ? "PROCESSING..." : mode === "login" ? "SIGN IN TO WORKSPACE" : "CREATE ACCOUNT"
|
|
107
|
+
] })
|
|
108
|
+
] }),
|
|
109
|
+
onSwitchToAdmin && /* @__PURE__ */ jsxs("div", { className: "mt-6 pt-4 border-t border-[var(--skipo-border-color)] flex items-center justify-between text-[11px] text-[var(--skipo-text-muted)]", children: [
|
|
110
|
+
/* @__PURE__ */ jsx("span", { children: "System Administrator?" }),
|
|
111
|
+
/* @__PURE__ */ jsxs("button", { type: "button", onClick: onSwitchToAdmin, className: "text-[#D4AF37] hover:underline font-bold flex items-center gap-1", children: [
|
|
112
|
+
"Switch to Admin Portal ",
|
|
113
|
+
/* @__PURE__ */ jsx(ArrowRight, { size: 11 })
|
|
114
|
+
] })
|
|
115
|
+
] })
|
|
116
|
+
] }) }),
|
|
117
|
+
/* @__PURE__ */ jsx("footer", { className: "border-t border-[var(--skipo-border-color)] py-2 px-4 text-center text-[10px] text-[var(--skipo-text-muted)]", children: footerText || `${appName} WORKSPACE SYSTEM` })
|
|
118
|
+
] });
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
// src/components/auth/LoginModal.tsx
|
|
122
|
+
import { useState as useState2 } from "react";
|
|
123
|
+
import { ArrowRight as ArrowRight2, ShieldCheck, AlertCircle as AlertCircle2 } from "lucide-react";
|
|
124
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
125
|
+
var LoginModal = ({
|
|
126
|
+
appName = "Ecosystem App",
|
|
127
|
+
onSuccess,
|
|
128
|
+
defaultEmail = ""
|
|
129
|
+
}) => {
|
|
130
|
+
const [email, setEmail] = useState2(defaultEmail);
|
|
131
|
+
const [password, setPassword] = useState2("");
|
|
132
|
+
const [isRegister, setIsRegister] = useState2(false);
|
|
133
|
+
const [name, setName] = useState2("");
|
|
134
|
+
const [loading, setLoading] = useState2(false);
|
|
135
|
+
const [error, setError] = useState2(null);
|
|
136
|
+
const handleSubmit = async (e) => {
|
|
137
|
+
e.preventDefault();
|
|
138
|
+
setError(null);
|
|
139
|
+
setLoading(true);
|
|
140
|
+
try {
|
|
141
|
+
const endpoint = isRegister ? "/api/auth/register" : "/api/auth/login";
|
|
142
|
+
const payload = isRegister ? { email, password, name } : { email, password };
|
|
143
|
+
const res = await fetch(endpoint, {
|
|
144
|
+
method: "POST",
|
|
145
|
+
headers: { "Content-Type": "application/json" },
|
|
146
|
+
body: JSON.stringify(payload)
|
|
147
|
+
});
|
|
148
|
+
const data = await res.json().catch(() => ({}));
|
|
149
|
+
if (!res.ok || !data.success || !data.user) {
|
|
150
|
+
throw new Error(data.error || "Authentication failed. Please verify credentials.");
|
|
151
|
+
}
|
|
152
|
+
const token = data.token || `usr_${Date.now()}`;
|
|
153
|
+
if (typeof window !== "undefined") {
|
|
154
|
+
localStorage.setItem("skipo_auth_token", token);
|
|
155
|
+
localStorage.setItem("skipo_user", JSON.stringify(data.user));
|
|
156
|
+
}
|
|
157
|
+
onSuccess(data.user, token);
|
|
158
|
+
} catch (err) {
|
|
159
|
+
setError(err.message || "Server error. Authentication failed.");
|
|
160
|
+
} finally {
|
|
161
|
+
setLoading(false);
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
return /* @__PURE__ */ jsx2(
|
|
165
|
+
"div",
|
|
166
|
+
{
|
|
167
|
+
className: "fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-xs font-mono p-4",
|
|
168
|
+
onWheel: (e) => e.stopPropagation(),
|
|
169
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
170
|
+
children: /* @__PURE__ */ jsxs2("div", { className: "w-full max-w-md p-6 border-2 border-[var(--skipo-border-color)] bg-[var(--skipo-surface)] text-[var(--skipo-text)] shadow-2xl rounded-lg space-y-4", children: [
|
|
171
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex items-center justify-between pb-3 border-b border-[var(--skipo-border-color)]", children: [
|
|
172
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2", children: [
|
|
173
|
+
/* @__PURE__ */ jsx2("div", { className: "w-7 h-7 bg-[var(--skipo-accent)] text-black font-black flex items-center justify-center text-xs rounded", children: "\u25B2" }),
|
|
174
|
+
/* @__PURE__ */ jsxs2("span", { className: "font-black text-sm tracking-wider uppercase text-[var(--skipo-text)]", children: [
|
|
175
|
+
appName,
|
|
176
|
+
" Authentication"
|
|
177
|
+
] })
|
|
178
|
+
] }),
|
|
179
|
+
/* @__PURE__ */ jsxs2("span", { className: "text-[9px] px-2 py-0.5 border border-emerald-500/50 bg-emerald-500/10 text-emerald-300 font-bold rounded flex items-center gap-1", children: [
|
|
180
|
+
/* @__PURE__ */ jsx2(ShieldCheck, { size: 10 }),
|
|
181
|
+
" SYSTEM DB"
|
|
182
|
+
] })
|
|
183
|
+
] }),
|
|
184
|
+
error && /* @__PURE__ */ jsxs2("div", { className: "p-3 border border-red-500/60 bg-red-500/10 text-red-300 text-xs rounded flex items-start gap-2", children: [
|
|
185
|
+
/* @__PURE__ */ jsx2(AlertCircle2, { size: 14, className: "shrink-0 mt-0.5" }),
|
|
186
|
+
/* @__PURE__ */ jsx2("span", { children: error })
|
|
187
|
+
] }),
|
|
188
|
+
/* @__PURE__ */ jsxs2("form", { onSubmit: handleSubmit, className: "space-y-3", children: [
|
|
189
|
+
isRegister && /* @__PURE__ */ jsxs2("div", { children: [
|
|
190
|
+
/* @__PURE__ */ jsx2("label", { className: "block text-[10px] font-black uppercase mb-1", children: "Full Name *" }),
|
|
191
|
+
/* @__PURE__ */ jsx2(
|
|
192
|
+
BaseInput,
|
|
193
|
+
{
|
|
194
|
+
type: "text",
|
|
195
|
+
value: name,
|
|
196
|
+
onChange: (e) => setName(e.target.value),
|
|
197
|
+
placeholder: "Developer Name",
|
|
198
|
+
required: isRegister
|
|
199
|
+
}
|
|
200
|
+
)
|
|
201
|
+
] }),
|
|
202
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
203
|
+
/* @__PURE__ */ jsx2("label", { className: "block text-[10px] font-black uppercase mb-1", children: "Email Address *" }),
|
|
204
|
+
/* @__PURE__ */ jsx2(
|
|
205
|
+
BaseInput,
|
|
206
|
+
{
|
|
207
|
+
type: "email",
|
|
208
|
+
value: email,
|
|
209
|
+
onChange: (e) => setEmail(e.target.value),
|
|
210
|
+
placeholder: "user@example.com",
|
|
211
|
+
required: true
|
|
212
|
+
}
|
|
213
|
+
)
|
|
214
|
+
] }),
|
|
215
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
216
|
+
/* @__PURE__ */ jsx2("label", { className: "block text-[10px] font-black uppercase mb-1", children: "Password *" }),
|
|
217
|
+
/* @__PURE__ */ jsx2(
|
|
218
|
+
BaseInput,
|
|
219
|
+
{
|
|
220
|
+
type: "password",
|
|
221
|
+
value: password,
|
|
222
|
+
onChange: (e) => setPassword(e.target.value),
|
|
223
|
+
placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022",
|
|
224
|
+
required: true
|
|
225
|
+
}
|
|
226
|
+
)
|
|
227
|
+
] }),
|
|
228
|
+
/* @__PURE__ */ jsx2("div", { className: "pt-2", children: /* @__PURE__ */ jsxs2(
|
|
229
|
+
BaseButton,
|
|
230
|
+
{
|
|
231
|
+
variant: "accent",
|
|
232
|
+
size: "md",
|
|
233
|
+
type: "submit",
|
|
234
|
+
disabled: loading,
|
|
235
|
+
className: "w-full flex items-center justify-center gap-2",
|
|
236
|
+
children: [
|
|
237
|
+
/* @__PURE__ */ jsx2("span", { children: loading ? "AUTHENTICATING..." : isRegister ? "REGISTER & ENTER" : "SIGN IN" }),
|
|
238
|
+
/* @__PURE__ */ jsx2(ArrowRight2, { size: 14 })
|
|
239
|
+
]
|
|
240
|
+
}
|
|
241
|
+
) })
|
|
242
|
+
] }),
|
|
243
|
+
/* @__PURE__ */ jsxs2("div", { className: "pt-2 border-t border-[var(--skipo-border-color)]/60 flex items-center justify-between text-[11px]", children: [
|
|
244
|
+
/* @__PURE__ */ jsx2(
|
|
245
|
+
"button",
|
|
246
|
+
{
|
|
247
|
+
type: "button",
|
|
248
|
+
onClick: () => {
|
|
249
|
+
setIsRegister(!isRegister);
|
|
250
|
+
setError(null);
|
|
251
|
+
},
|
|
252
|
+
className: "text-[var(--skipo-accent)] hover:underline cursor-pointer",
|
|
253
|
+
children: isRegister ? "Already have an account? Sign In" : "Create new account"
|
|
254
|
+
}
|
|
255
|
+
),
|
|
256
|
+
/* @__PURE__ */ jsx2("span", { className: "text-[10px] text-[var(--skipo-text-muted)]", children: "ULTRST Identity" })
|
|
257
|
+
] })
|
|
258
|
+
] })
|
|
259
|
+
}
|
|
260
|
+
);
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
export {
|
|
264
|
+
AuthPage,
|
|
265
|
+
LoginModal
|
|
266
|
+
};
|
|
@@ -415,140 +415,166 @@ var WorkspaceSecondaryClonesPanel = ({ workspace, onClonesUpdated, onClose }) =>
|
|
|
415
415
|
|
|
416
416
|
// src/components/workspace/WorkspaceTilesMenu.tsx
|
|
417
417
|
import React5 from "react";
|
|
418
|
+
import { Search, Plus as Plus2, Trash2 as Trash22, Edit3, LogOut, ArrowRight, FolderOpen, Cloud as Cloud5, HardDrive as HardDrive5, FolderPlus, X } from "lucide-react";
|
|
418
419
|
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
419
420
|
var WorkspaceTilesMenu = ({
|
|
420
421
|
workspaces,
|
|
421
|
-
activeWorkspaceId,
|
|
422
|
+
activeWorkspaceId = null,
|
|
423
|
+
currentUser = null,
|
|
422
424
|
onSelectWorkspace,
|
|
423
425
|
onCreateWorkspace,
|
|
426
|
+
onUpdateWorkspace,
|
|
424
427
|
onDeleteWorkspace,
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
mode = "working-workspace"
|
|
428
|
+
onLogout,
|
|
429
|
+
appName = "APP",
|
|
430
|
+
mode = "working-workspace",
|
|
431
|
+
loading = false,
|
|
432
|
+
error = null,
|
|
433
|
+
onDismissError
|
|
428
434
|
}) => {
|
|
429
|
-
const [
|
|
430
|
-
const [
|
|
431
|
-
const [
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
});
|
|
435
|
-
const
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
const
|
|
435
|
+
const [search, setSearch] = React5.useState("");
|
|
436
|
+
const [creating, setCreating] = React5.useState(false);
|
|
437
|
+
const [editing, setEditing] = React5.useState(null);
|
|
438
|
+
const [name, setName] = React5.useState("");
|
|
439
|
+
const [description, setDescription] = React5.useState("");
|
|
440
|
+
const [storage, setStorage] = React5.useState({ provider: "local_fs", localFolderName: "Local-Vault" });
|
|
441
|
+
const filtered = workspaces.filter(
|
|
442
|
+
(w) => w.name.toLowerCase().includes(search.toLowerCase()) || (w.description || "").toLowerCase().includes(search.toLowerCase())
|
|
443
|
+
);
|
|
444
|
+
const create = async (e) => {
|
|
439
445
|
e.preventDefault();
|
|
440
|
-
if (!
|
|
441
|
-
await onCreateWorkspace(
|
|
442
|
-
|
|
443
|
-
|
|
446
|
+
if (!name.trim()) return;
|
|
447
|
+
await onCreateWorkspace({ name: name.trim(), description: description.trim(), storage });
|
|
448
|
+
setName("");
|
|
449
|
+
setDescription("");
|
|
450
|
+
setCreating(false);
|
|
444
451
|
};
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
+
const update = async (e) => {
|
|
453
|
+
e.preventDefault();
|
|
454
|
+
if (!editing || !onUpdateWorkspace || !name.trim()) return;
|
|
455
|
+
await onUpdateWorkspace(editing.id, { name: name.trim(), description: description.trim() });
|
|
456
|
+
setEditing(null);
|
|
457
|
+
};
|
|
458
|
+
const beginEdit = (w) => {
|
|
459
|
+
setEditing(w);
|
|
460
|
+
setName(w.name);
|
|
461
|
+
setDescription(w.description || "");
|
|
462
|
+
};
|
|
463
|
+
return /* @__PURE__ */ jsxs6("div", { className: "fixed inset-0 z-50 overflow-y-auto bg-black/85 p-4 sm:p-8 backdrop-blur-md font-mono flex flex-col items-center select-none", children: [
|
|
464
|
+
/* @__PURE__ */ jsxs6("div", { className: "w-full max-w-5xl my-4 sm:my-8", children: [
|
|
465
|
+
/* @__PURE__ */ jsxs6("div", { className: "p-4 sm:p-5 mb-5 border-2 border-[var(--skipo-border-color)] bg-[var(--skipo-surface)] rounded-lg shadow-2xl", children: [
|
|
466
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between gap-4", children: [
|
|
467
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2.5", children: [
|
|
468
|
+
/* @__PURE__ */ jsx6("div", { className: "w-8 h-8 rounded bg-[var(--skipo-accent)] text-black font-black flex items-center justify-center text-sm", children: appName.slice(0, 2).toUpperCase() }),
|
|
469
|
+
/* @__PURE__ */ jsxs6("div", { children: [
|
|
470
|
+
/* @__PURE__ */ jsxs6("span", { className: "text-lg sm:text-xl font-black text-[var(--skipo-accent)] tracking-wider", children: [
|
|
471
|
+
appName.toUpperCase(),
|
|
472
|
+
" WORKSPACES"
|
|
473
|
+
] }),
|
|
474
|
+
/* @__PURE__ */ jsxs6("div", { className: "text-[10px] text-[var(--skipo-text-muted)]", children: [
|
|
475
|
+
currentUser?.email || "user",
|
|
476
|
+
" \xB7 ",
|
|
477
|
+
mode
|
|
478
|
+
] })
|
|
479
|
+
] })
|
|
480
|
+
] }),
|
|
481
|
+
onLogout && /* @__PURE__ */ jsxs6("button", { type: "button", onClick: onLogout, className: "text-xs flex items-center gap-1.5 text-red-400 hover:bg-red-500/20 border border-red-500/50 px-2.5 py-1.5 rounded", children: [
|
|
482
|
+
/* @__PURE__ */ jsx6(LogOut, { size: 14 }),
|
|
483
|
+
" LOGOUT"
|
|
484
|
+
] })
|
|
452
485
|
] }),
|
|
453
|
-
/* @__PURE__ */ jsxs6("
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
486
|
+
/* @__PURE__ */ jsxs6("div", { className: "mt-4 pt-4 border-t border-[var(--skipo-border-color)] flex flex-col sm:flex-row gap-3", children: [
|
|
487
|
+
/* @__PURE__ */ jsxs6("div", { className: "relative flex-1", children: [
|
|
488
|
+
/* @__PURE__ */ jsx6(Search, { size: 14, className: "absolute left-3 top-1/2 -translate-y-1/2 text-[var(--skipo-text-muted)]" }),
|
|
489
|
+
/* @__PURE__ */ jsx6("input", { value: search, onChange: (e) => setSearch(e.target.value), placeholder: "Search workspaces by name or description...", className: "w-full bg-[var(--skipo-bg)] border border-[var(--skipo-border-color)] rounded pl-9 pr-3 py-1.5 text-xs text-[var(--skipo-text)] outline-none focus:border-[var(--skipo-accent)]" })
|
|
490
|
+
] }),
|
|
491
|
+
/* @__PURE__ */ jsxs6("button", { type: "button", onClick: () => {
|
|
492
|
+
setName("");
|
|
493
|
+
setDescription("");
|
|
494
|
+
setCreating(true);
|
|
495
|
+
}, className: "text-xs flex items-center justify-center gap-1.5 font-bold px-3 py-1.5 bg-[var(--skipo-accent)] text-black rounded", children: [
|
|
496
|
+
/* @__PURE__ */ jsx6(Plus2, { size: 14 }),
|
|
497
|
+
" NEW WORKSPACE"
|
|
498
|
+
] })
|
|
457
499
|
] })
|
|
458
500
|
] }),
|
|
459
|
-
/* @__PURE__ */ jsxs6("div", {
|
|
460
|
-
/* @__PURE__ */ jsx6(
|
|
461
|
-
|
|
462
|
-
{
|
|
463
|
-
onClick: () => setActiveTab("workspaces"),
|
|
464
|
-
style: { padding: "6px 14px", borderRadius: "6px", border: "1px solid #334155", background: activeTab === "workspaces" ? "#38bdf8" : "transparent", color: activeTab === "workspaces" ? "#0f172a" : "inherit", cursor: "pointer" },
|
|
465
|
-
children: "List"
|
|
466
|
-
}
|
|
467
|
-
),
|
|
468
|
-
activeWs && /* @__PURE__ */ jsxs6(
|
|
469
|
-
"button",
|
|
470
|
-
{
|
|
471
|
-
onClick: () => {
|
|
472
|
-
setActiveWorkspaceForClones(activeWs);
|
|
473
|
-
setActiveTab("clones");
|
|
474
|
-
},
|
|
475
|
-
style: { padding: "6px 14px", borderRadius: "6px", border: "1px solid #334155", background: activeTab === "clones" ? "#38bdf8" : "transparent", color: activeTab === "clones" ? "#0f172a" : "inherit", cursor: "pointer" },
|
|
476
|
-
children: [
|
|
477
|
-
"Clones (",
|
|
478
|
-
activeWs.secondaryClones?.length || 0,
|
|
479
|
-
")"
|
|
480
|
-
]
|
|
481
|
-
}
|
|
482
|
-
),
|
|
483
|
-
/* @__PURE__ */ jsx6(
|
|
484
|
-
"button",
|
|
485
|
-
{
|
|
486
|
-
onClick: () => setIsCreating(!isCreating),
|
|
487
|
-
style: { padding: "6px 14px", borderRadius: "6px", border: "1px solid #38bdf8", background: isCreating ? "transparent" : "#38bdf8", color: isCreating ? "#38bdf8" : "#0f172a", cursor: "pointer" },
|
|
488
|
-
children: isCreating ? "Cancel" : "+ New Workspace"
|
|
489
|
-
}
|
|
490
|
-
)
|
|
491
|
-
] })
|
|
492
|
-
] }),
|
|
493
|
-
isCreating ? /* @__PURE__ */ jsxs6("form", { onSubmit: handleCreate, style: { display: "flex", flexDirection: "column", gap: "16px", background: "#1e293b", padding: "20px", borderRadius: "8px" }, children: [
|
|
494
|
-
/* @__PURE__ */ jsxs6("div", { children: [
|
|
495
|
-
/* @__PURE__ */ jsx6("label", { style: { display: "block", fontSize: "12px", marginBottom: "6px", color: "#94a3b8" }, children: "Workspace Name" }),
|
|
496
|
-
/* @__PURE__ */ jsx6(
|
|
497
|
-
"input",
|
|
498
|
-
{
|
|
499
|
-
type: "text",
|
|
500
|
-
value: newWsName,
|
|
501
|
-
onChange: (e) => setNewWsName(e.target.value),
|
|
502
|
-
placeholder: "e.g. Production Vault",
|
|
503
|
-
style: { width: "100%", padding: "8px 12px", background: "#0f172a", border: "1px solid #334155", borderRadius: "6px", color: "#fff" },
|
|
504
|
-
autoFocus: true
|
|
505
|
-
}
|
|
506
|
-
)
|
|
501
|
+
error && /* @__PURE__ */ jsxs6("div", { className: "mb-4 p-3 bg-red-500/15 border-2 border-red-500 text-red-400 text-xs flex items-center justify-between rounded", children: [
|
|
502
|
+
/* @__PURE__ */ jsx6("b", { children: error }),
|
|
503
|
+
onDismissError && /* @__PURE__ */ jsx6("button", { type: "button", onClick: onDismissError, className: "underline", children: "DISMISS" })
|
|
507
504
|
] }),
|
|
508
|
-
/* @__PURE__ */ jsx6(
|
|
509
|
-
/* @__PURE__ */
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
] }),
|
|
532
|
-
isActive && /* @__PURE__ */ jsx6("span", { style: { fontSize: "10px", padding: "2px 6px", borderRadius: "4px", background: "#38bdf8", color: "#0f172a", fontWeight: 600 }, children: "ACTIVE" })
|
|
505
|
+
loading && /* @__PURE__ */ jsx6("div", { className: "mb-4 p-8 border border-dashed border-[var(--skipo-border-color)] text-center text-xs text-[var(--skipo-text-muted)]", children: "LOADING WORKSPACES..." }),
|
|
506
|
+
/* @__PURE__ */ jsxs6("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-4", children: [
|
|
507
|
+
filtered.map((w) => {
|
|
508
|
+
const active = w.id === activeWorkspaceId;
|
|
509
|
+
const isB2 = w.storageProvider === "backblaze_b2";
|
|
510
|
+
return /* @__PURE__ */ jsxs6("div", { onClick: () => onSelectWorkspace(w), className: `group p-4 border-2 bg-[var(--skipo-surface)] rounded-lg transition-all cursor-pointer ${active ? "border-[var(--skipo-accent)] shadow-[4px_4px_0px_var(--skipo-accent)]" : "border-[var(--skipo-border-color)] hover:border-[var(--skipo-accent)]"}`, children: [
|
|
511
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between gap-2", children: [
|
|
512
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2 text-[10px] font-bold uppercase text-[var(--skipo-text-muted)]", children: [
|
|
513
|
+
isB2 ? /* @__PURE__ */ jsx6(Cloud5, { size: 12 }) : /* @__PURE__ */ jsx6(HardDrive5, { size: 12 }),
|
|
514
|
+
" ",
|
|
515
|
+
w.storageProvider || "local_fs",
|
|
516
|
+
" ",
|
|
517
|
+
active && /* @__PURE__ */ jsx6("span", { className: "text-[var(--skipo-accent)]", children: "\u2605 ACTIVE" })
|
|
518
|
+
] }),
|
|
519
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex gap-1", children: [
|
|
520
|
+
onUpdateWorkspace && /* @__PURE__ */ jsx6("button", { type: "button", onClick: (e) => {
|
|
521
|
+
e.stopPropagation();
|
|
522
|
+
beginEdit(w);
|
|
523
|
+
}, className: "p-1.5 border border-[var(--skipo-border-color)] rounded hover:bg-[var(--skipo-accent)] hover:text-black", children: /* @__PURE__ */ jsx6(Edit3, { size: 13 }) }),
|
|
524
|
+
onDeleteWorkspace && /* @__PURE__ */ jsx6("button", { type: "button", onClick: (e) => {
|
|
525
|
+
e.stopPropagation();
|
|
526
|
+
if (confirm(`Delete workspace "${w.name}"?`)) onDeleteWorkspace(w.id);
|
|
527
|
+
}, className: "p-1.5 border border-[var(--skipo-border-color)] rounded hover:bg-red-600 hover:text-white", children: /* @__PURE__ */ jsx6(Trash22, { size: 13 }) })
|
|
533
528
|
] })
|
|
534
529
|
] }),
|
|
535
|
-
/* @__PURE__ */ jsx6("
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
530
|
+
/* @__PURE__ */ jsx6("h3", { className: "mt-3 text-sm font-black uppercase text-[var(--skipo-text)] truncate", children: w.name }),
|
|
531
|
+
/* @__PURE__ */ jsxs6("div", { className: "mt-1 text-[10px] text-[var(--skipo-accent)] flex items-center gap-1 truncate", children: [
|
|
532
|
+
/* @__PURE__ */ jsx6(FolderOpen, { size: 11 }),
|
|
533
|
+
w.workspacePath || w.localFolderName || w.b2BucketName || w.id
|
|
534
|
+
] }),
|
|
535
|
+
/* @__PURE__ */ jsx6("p", { className: "text-xs text-[var(--skipo-text-muted)] mt-2 line-clamp-2", children: w.description || "Workspace deployment and application control plane." }),
|
|
536
|
+
/* @__PURE__ */ jsx6("div", { className: "mt-3 pt-3 border-t border-[var(--skipo-border-color)]", children: /* @__PURE__ */ jsx6(WorkspaceStorageReadonlyPanel, { workspace: w }) }),
|
|
537
|
+
/* @__PURE__ */ jsx6("div", { className: "mt-3 flex justify-end", children: /* @__PURE__ */ jsxs6("button", { type: "button", onClick: (e) => {
|
|
538
|
+
e.stopPropagation();
|
|
539
|
+
onSelectWorkspace(w);
|
|
540
|
+
}, className: "flex items-center gap-1.5 px-3 py-1.5 text-xs font-black uppercase border rounded bg-[var(--skipo-bg)] hover:bg-[var(--skipo-accent)] hover:text-black", children: [
|
|
541
|
+
/* @__PURE__ */ jsx6("span", { children: "ENTER WORKSPACE" }),
|
|
542
|
+
/* @__PURE__ */ jsx6(ArrowRight, { size: 14 })
|
|
543
|
+
] }) })
|
|
544
|
+
] }, w.id);
|
|
545
|
+
}),
|
|
546
|
+
/* @__PURE__ */ jsxs6("button", { type: "button", onClick: () => {
|
|
547
|
+
setName("");
|
|
548
|
+
setDescription("");
|
|
549
|
+
setCreating(true);
|
|
550
|
+
}, className: "min-h-[220px] flex flex-col items-center justify-center p-6 border-2 border-dashed border-[var(--skipo-border-color)] bg-[var(--skipo-surface)]/50 hover:border-[var(--skipo-accent)] rounded-lg", children: [
|
|
551
|
+
/* @__PURE__ */ jsx6(FolderPlus, { size: 22, className: "mb-3 text-[var(--skipo-accent)]" }),
|
|
552
|
+
/* @__PURE__ */ jsx6("b", { className: "text-xs", children: "ADD NEW WORKSPACE" }),
|
|
553
|
+
/* @__PURE__ */ jsx6("span", { className: "text-[11px] text-[var(--skipo-text-muted)] mt-1 text-center", children: "Create an isolated workspace with dedicated storage." })
|
|
554
|
+
] })
|
|
555
|
+
] })
|
|
556
|
+
] }),
|
|
557
|
+
(creating || editing) && /* @__PURE__ */ jsx6("div", { className: "fixed inset-0 z-[60] flex items-center justify-center bg-black/75 p-4 backdrop-blur-sm", children: /* @__PURE__ */ jsxs6("div", { className: "w-full max-w-2xl p-6 border-2 border-[var(--skipo-border-color)] bg-[var(--skipo-surface)] rounded-lg shadow-2xl font-mono", children: [
|
|
558
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between pb-3 border-b border-[var(--skipo-border-color)] mb-4", children: [
|
|
559
|
+
/* @__PURE__ */ jsx6("b", { className: "text-sm uppercase", children: creating ? "CREATE NEW WORKSPACE" : "EDIT WORKSPACE SETTINGS" }),
|
|
560
|
+
/* @__PURE__ */ jsx6("button", { type: "button", onClick: () => {
|
|
561
|
+
setCreating(false);
|
|
562
|
+
setEditing(null);
|
|
563
|
+
}, children: /* @__PURE__ */ jsx6(X, { size: 16 }) })
|
|
564
|
+
] }),
|
|
565
|
+
/* @__PURE__ */ jsxs6("form", { onSubmit: creating ? create : update, className: "space-y-4", children: [
|
|
566
|
+
/* @__PURE__ */ jsx6("input", { value: name, onChange: (e) => setName(e.target.value), placeholder: "Workspace Name", required: true, className: "w-full bg-[var(--skipo-bg)] border border-[var(--skipo-border-color)] rounded px-3 py-2 text-xs" }),
|
|
567
|
+
/* @__PURE__ */ jsx6("textarea", { value: description, onChange: (e) => setDescription(e.target.value), placeholder: "Description", rows: 2, className: "w-full bg-[var(--skipo-bg)] border border-[var(--skipo-border-color)] rounded px-3 py-2 text-xs" }),
|
|
568
|
+
creating && /* @__PURE__ */ jsx6(StorageOptionTiles, { currentUser, onSelectStorage: setStorage }),
|
|
569
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex justify-end gap-2", children: [
|
|
570
|
+
/* @__PURE__ */ jsx6("button", { type: "button", onClick: () => {
|
|
571
|
+
setCreating(false);
|
|
572
|
+
setEditing(null);
|
|
573
|
+
}, className: "px-3 py-1.5 text-xs border rounded", children: "CANCEL" }),
|
|
574
|
+
/* @__PURE__ */ jsx6("button", { type: "submit", className: "px-3 py-1.5 text-xs font-black bg-[var(--skipo-accent)] text-black rounded", children: creating ? "CREATE & ENTER WORKSPACE" : "SAVE SETTINGS" })
|
|
575
|
+
] })
|
|
576
|
+
] })
|
|
577
|
+
] }) })
|
|
552
578
|
] });
|
|
553
579
|
};
|
|
554
580
|
|
|
@@ -1,5 +1,39 @@
|
|
|
1
1
|
import React__default from 'react';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* @public
|
|
5
|
+
* Canonical Auth Result contract.
|
|
6
|
+
*/
|
|
7
|
+
interface AuthResult {
|
|
8
|
+
success: boolean;
|
|
9
|
+
error?: string;
|
|
10
|
+
user?: unknown;
|
|
11
|
+
token?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* @public
|
|
15
|
+
* Canonical AuthPage Props for FLOKS reusable authentication page.
|
|
16
|
+
*/
|
|
17
|
+
interface AuthPageProps {
|
|
18
|
+
appName?: string;
|
|
19
|
+
appSubtitle?: string;
|
|
20
|
+
footerText?: string;
|
|
21
|
+
onLogin: (email: string, password: string) => Promise<AuthResult>;
|
|
22
|
+
onRegister: (input: {
|
|
23
|
+
name: string;
|
|
24
|
+
email: string;
|
|
25
|
+
password: string;
|
|
26
|
+
}) => Promise<AuthResult>;
|
|
27
|
+
onSuccess?: (result: AuthResult) => void;
|
|
28
|
+
onSwitchToAdmin?: () => void;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* @public
|
|
32
|
+
* Canonical FLOKS AuthPage section/page component.
|
|
33
|
+
* Single source of truth for login/registration across DEPM, KRUSBL, and SKIPO apps.
|
|
34
|
+
*/
|
|
35
|
+
declare const AuthPage: React__default.FC<AuthPageProps>;
|
|
36
|
+
|
|
3
37
|
interface LoginModalProps {
|
|
4
38
|
appName?: string;
|
|
5
39
|
onSuccess: (user: any, token: string) => void;
|
|
@@ -7,4 +41,4 @@ interface LoginModalProps {
|
|
|
7
41
|
}
|
|
8
42
|
declare const LoginModal: React__default.FC<LoginModalProps>;
|
|
9
43
|
|
|
10
|
-
export { LoginModal, type LoginModalProps };
|
|
44
|
+
export { AuthPage, type AuthPageProps, type AuthResult, LoginModal, type LoginModalProps };
|
|
@@ -72,30 +72,56 @@ interface Props {
|
|
|
72
72
|
}
|
|
73
73
|
declare const WorkspaceSecondaryClonesPanel: React__default.FC<Props>;
|
|
74
74
|
|
|
75
|
+
/**
|
|
76
|
+
* @public
|
|
77
|
+
* Canonical Workspace Record contract.
|
|
78
|
+
*/
|
|
75
79
|
interface WorkspaceRecord {
|
|
76
80
|
id: string;
|
|
77
81
|
name: string;
|
|
82
|
+
description?: string;
|
|
83
|
+
workspacePath?: string;
|
|
78
84
|
storageProvider?: string;
|
|
79
85
|
localFolderName?: string;
|
|
86
|
+
localFolderKey?: string;
|
|
80
87
|
b2BucketName?: string;
|
|
81
|
-
secondaryClones?:
|
|
82
|
-
createdAt?: string;
|
|
83
|
-
updatedAt?: string;
|
|
88
|
+
secondaryClones?: unknown[];
|
|
84
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* @public
|
|
92
|
+
* Canonical WorkspaceTilesMenu Props.
|
|
93
|
+
*/
|
|
85
94
|
interface WorkspaceTilesMenuProps {
|
|
86
95
|
workspaces: WorkspaceRecord[];
|
|
87
|
-
activeWorkspaceId
|
|
88
|
-
onSelectWorkspace: (workspace: WorkspaceRecord) => void;
|
|
89
|
-
onCreateWorkspace: (name: string, storage: StorageSelection) => Promise<void>;
|
|
90
|
-
onDeleteWorkspace?: (workspaceId: string) => Promise<void>;
|
|
91
|
-
appName?: string;
|
|
96
|
+
activeWorkspaceId?: string | null;
|
|
92
97
|
currentUser?: {
|
|
93
98
|
id: string;
|
|
94
99
|
email: string;
|
|
95
100
|
name?: string;
|
|
96
101
|
} | null;
|
|
102
|
+
onSelectWorkspace: (workspace: WorkspaceRecord) => void;
|
|
103
|
+
onCreateWorkspace: (input: {
|
|
104
|
+
name: string;
|
|
105
|
+
description?: string;
|
|
106
|
+
storage: StorageSelection;
|
|
107
|
+
}) => Promise<void>;
|
|
108
|
+
onUpdateWorkspace?: (workspaceId: string, patch: {
|
|
109
|
+
name: string;
|
|
110
|
+
description?: string;
|
|
111
|
+
}) => Promise<void>;
|
|
112
|
+
onDeleteWorkspace?: (workspaceId: string) => Promise<void>;
|
|
113
|
+
onLogout?: () => void;
|
|
114
|
+
appName?: string;
|
|
97
115
|
mode?: 'direct-vault' | 'working-workspace';
|
|
116
|
+
loading?: boolean;
|
|
117
|
+
error?: string | null;
|
|
118
|
+
onDismissError?: () => void;
|
|
98
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* @public
|
|
122
|
+
* Canonical FLOKS WorkspaceTilesMenu section/modal component.
|
|
123
|
+
* Single source of truth for workspace isolation, selection, and creation across DEPM, KRUSBL, and SKIPO apps.
|
|
124
|
+
*/
|
|
99
125
|
declare const WorkspaceTilesMenu: React__default.FC<WorkspaceTilesMenuProps>;
|
|
100
126
|
|
|
101
127
|
export { type SrklBackblazeAccount, SrklBackblazeTile, StorageOptionTiles, StoragePresetTile, type StorageSelection, type WorkspaceRecord, type WorkspaceSecondaryClone, WorkspaceSecondaryClonesPanel, WorkspaceStorageReadonlyPanel, WorkspaceTilesMenu, type WorkspaceTilesMenuProps };
|
|
@@ -7,7 +7,7 @@ export { AppShell, AppShellProps, BreadcrumbNav, BreadcrumbNavProps, HeaderBar,
|
|
|
7
7
|
export { ApiCallIndicator, ApiCallIndicatorProps, AutoSaveStatus, AutoSaveToggle, AutoSaveToggleProps, BottomStripContextValue, BottomStripProvider, BottomStripProviderProps, StatusLight, StatusLightProps, SystemMessage, SystemMessageDisplay, SystemMessageDisplayProps, SystemMessageType, useBottomStrip } from './components/bottom-strip/index.js';
|
|
8
8
|
export { B as BottomStrip, a as BottomStripProps } from './BottomStrip-DYhAUQR4.js';
|
|
9
9
|
export { AccountsSettingsSection, AccountsSettingsSectionProps, SettingsTab, SettingsTabProps, ThemeSettingsSection } from './components/settings/index.js';
|
|
10
|
-
export { LoginModal, LoginModalProps } from './components/auth/index.js';
|
|
10
|
+
export { AuthPage, AuthPageProps, AuthResult, LoginModal, LoginModalProps } from './components/auth/index.js';
|
|
11
11
|
export { SrklBackblazeAccount, SrklBackblazeTile, StorageOptionTiles, StoragePresetTile, StorageSelection, WorkspaceRecord, WorkspaceSecondaryClone, WorkspaceSecondaryClonesPanel, WorkspaceStorageReadonlyPanel, WorkspaceTilesMenu, WorkspaceTilesMenuProps } from './components/workspace/index.js';
|
|
12
12
|
export { DEFAULT_PALETTE_ID, THEME_STORAGE_KEY, ThemeContextValue, ThemeProvider, ThemeProviderProps, applyPaletteToDocument, getActivePalette, paletteToSkipoThemePack, subscribeToPalette, usePalette, useTheme } from './palette/index.js';
|
|
13
13
|
export { ActionButton, Badge, BadgeModel, BadgeProps, BadgeTone, ButtonModel, ButtonParent, ButtonParentProps, ButtonProps, ButtonSize, ButtonVariant, CardPanel, CategoryCardTile, ChannelStripTile, ClipCardTile, DangerButton, GhostButton, IconButton, InputModel, InspectorPanel, ModalPanel, PanelModel, PanelParent, PanelParentProps, PanelProps, PanelVariant, SelectInput, SelectInputProps, SliderInput, SliderInputProps, SpawnOptionTile, StatusDot, StatusDotProps, TelemetryPill, TelemetryPillProps, TextInput, TextInputProps, TileModel, TileParent, TileParentProps, TileVariant, ToggleButton, ToggleInput, ToggleInputProps, ToolbarPanel, TooltipDirection, UIBaseProps, UIElementBase, UIInteractionState, UIModel, UIParent, UIParentProps, UIProps, UIRole, UISize, UIStyleTokens, UIVariant, registerPaletteResolver } from './hierarchy/index.js';
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AppShell,
|
|
3
|
+
BreadcrumbNav,
|
|
4
|
+
HeaderBar,
|
|
5
|
+
TopToolbar
|
|
6
|
+
} from "./chunk-GWW3BGOB.js";
|
|
1
7
|
import {
|
|
2
8
|
DEFAULT_PANEL_GEOMETRY,
|
|
3
9
|
DrawerContainer,
|
|
@@ -12,12 +18,6 @@ import {
|
|
|
12
18
|
usePanelGeometry,
|
|
13
19
|
usePanelInteraction
|
|
14
20
|
} from "./chunk-TXKLROFC.js";
|
|
15
|
-
import {
|
|
16
|
-
AppShell,
|
|
17
|
-
BreadcrumbNav,
|
|
18
|
-
HeaderBar,
|
|
19
|
-
TopToolbar
|
|
20
|
-
} from "./chunk-GWW3BGOB.js";
|
|
21
21
|
import {
|
|
22
22
|
AccountsSettingsSection,
|
|
23
23
|
SettingsTab,
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
WorkspaceSecondaryClonesPanel,
|
|
31
31
|
WorkspaceStorageReadonlyPanel,
|
|
32
32
|
WorkspaceTilesMenu
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-DT6DZU63.js";
|
|
34
34
|
import {
|
|
35
35
|
ActionButton,
|
|
36
36
|
Badge,
|
|
@@ -128,15 +128,9 @@ import {
|
|
|
128
128
|
BUILTIN_PALETTES
|
|
129
129
|
} from "./chunk-XXIH2HWI.js";
|
|
130
130
|
import {
|
|
131
|
+
AuthPage,
|
|
131
132
|
LoginModal
|
|
132
|
-
} from "./chunk-
|
|
133
|
-
import {
|
|
134
|
-
BaseSelect,
|
|
135
|
-
BaseTextarea,
|
|
136
|
-
BaseToggle,
|
|
137
|
-
CredentialField,
|
|
138
|
-
KNOWN_CREDENTIAL_URLS
|
|
139
|
-
} from "./chunk-KIFQA7L6.js";
|
|
133
|
+
} from "./chunk-2SFOC7KZ.js";
|
|
140
134
|
import "./chunk-5ZMXFCD4.js";
|
|
141
135
|
import {
|
|
142
136
|
ApiCallIndicator,
|
|
@@ -145,6 +139,13 @@ import {
|
|
|
145
139
|
StatusLight,
|
|
146
140
|
SystemMessageDisplay
|
|
147
141
|
} from "./chunk-C3L53YN4.js";
|
|
142
|
+
import {
|
|
143
|
+
BaseSelect,
|
|
144
|
+
BaseTextarea,
|
|
145
|
+
BaseToggle,
|
|
146
|
+
CredentialField,
|
|
147
|
+
KNOWN_CREDENTIAL_URLS
|
|
148
|
+
} from "./chunk-KIFQA7L6.js";
|
|
148
149
|
import {
|
|
149
150
|
ConfirmDialog,
|
|
150
151
|
CopyableErrorAlert,
|
|
@@ -184,6 +185,7 @@ export {
|
|
|
184
185
|
ActionButton,
|
|
185
186
|
ApiCallIndicator,
|
|
186
187
|
AppShell,
|
|
188
|
+
AuthPage,
|
|
187
189
|
AutoSaveToggle,
|
|
188
190
|
BUILTIN_PALETTES,
|
|
189
191
|
Badge,
|
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://skipo.dev/schemas/floks-manifest.v1.json",
|
|
3
|
-
"package": "@floks/ui",
|
|
3
|
+
"package": "@ultrst-armada/floks/ui",
|
|
4
|
+
"alias": "@floks/ui",
|
|
5
|
+
"packageType": "frontend",
|
|
4
6
|
"version": "1.0.0",
|
|
5
7
|
"components": [
|
|
8
|
+
{
|
|
9
|
+
"id": "AuthPage",
|
|
10
|
+
"name": "AuthPage",
|
|
11
|
+
"export": "AuthPage",
|
|
12
|
+
"subpath": "auth",
|
|
13
|
+
"targetTypes": ["App.auth", "App.main-content"]
|
|
14
|
+
},
|
|
6
15
|
{
|
|
7
16
|
"id": "AppShell",
|
|
8
17
|
"name": "AppShell",
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
BaseInput
|
|
3
|
-
} from "./chunk-W42SJGOJ.js";
|
|
4
|
-
import {
|
|
5
|
-
BaseButton
|
|
6
|
-
} from "./chunk-A2CDQISJ.js";
|
|
7
|
-
|
|
8
|
-
// src/components/auth/LoginModal.tsx
|
|
9
|
-
import { useState } from "react";
|
|
10
|
-
import { ArrowRight, ShieldCheck, AlertCircle } from "lucide-react";
|
|
11
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
-
var LoginModal = ({
|
|
13
|
-
appName = "Ecosystem App",
|
|
14
|
-
onSuccess,
|
|
15
|
-
defaultEmail = ""
|
|
16
|
-
}) => {
|
|
17
|
-
const [email, setEmail] = useState(defaultEmail);
|
|
18
|
-
const [password, setPassword] = useState("");
|
|
19
|
-
const [isRegister, setIsRegister] = useState(false);
|
|
20
|
-
const [name, setName] = useState("");
|
|
21
|
-
const [loading, setLoading] = useState(false);
|
|
22
|
-
const [error, setError] = useState(null);
|
|
23
|
-
const handleSubmit = async (e) => {
|
|
24
|
-
e.preventDefault();
|
|
25
|
-
setError(null);
|
|
26
|
-
setLoading(true);
|
|
27
|
-
try {
|
|
28
|
-
const endpoint = isRegister ? "/api/auth/register" : "/api/auth/login";
|
|
29
|
-
const payload = isRegister ? { email, password, name } : { email, password };
|
|
30
|
-
const res = await fetch(endpoint, {
|
|
31
|
-
method: "POST",
|
|
32
|
-
headers: { "Content-Type": "application/json" },
|
|
33
|
-
body: JSON.stringify(payload)
|
|
34
|
-
});
|
|
35
|
-
const data = await res.json().catch(() => ({}));
|
|
36
|
-
if (!res.ok || !data.success || !data.user) {
|
|
37
|
-
throw new Error(data.error || "Authentication failed. Please verify credentials.");
|
|
38
|
-
}
|
|
39
|
-
const token = data.token || `usr_${Date.now()}`;
|
|
40
|
-
if (typeof window !== "undefined") {
|
|
41
|
-
localStorage.setItem("skipo_auth_token", token);
|
|
42
|
-
localStorage.setItem("skipo_user", JSON.stringify(data.user));
|
|
43
|
-
}
|
|
44
|
-
onSuccess(data.user, token);
|
|
45
|
-
} catch (err) {
|
|
46
|
-
setError(err.message || "Server error. Authentication failed.");
|
|
47
|
-
} finally {
|
|
48
|
-
setLoading(false);
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
return /* @__PURE__ */ jsx(
|
|
52
|
-
"div",
|
|
53
|
-
{
|
|
54
|
-
className: "fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-xs font-mono p-4",
|
|
55
|
-
onWheel: (e) => e.stopPropagation(),
|
|
56
|
-
onPointerDown: (e) => e.stopPropagation(),
|
|
57
|
-
children: /* @__PURE__ */ jsxs("div", { className: "w-full max-w-md p-6 border-2 border-[var(--skipo-border-color)] bg-[var(--skipo-surface)] text-[var(--skipo-text)] shadow-2xl rounded-lg space-y-4", children: [
|
|
58
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between pb-3 border-b border-[var(--skipo-border-color)]", children: [
|
|
59
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
60
|
-
/* @__PURE__ */ jsx("div", { className: "w-7 h-7 bg-[var(--skipo-accent)] text-black font-black flex items-center justify-center text-xs rounded", children: "\u25B2" }),
|
|
61
|
-
/* @__PURE__ */ jsxs("span", { className: "font-black text-sm tracking-wider uppercase text-[var(--skipo-text)]", children: [
|
|
62
|
-
appName,
|
|
63
|
-
" Authentication"
|
|
64
|
-
] })
|
|
65
|
-
] }),
|
|
66
|
-
/* @__PURE__ */ jsxs("span", { className: "text-[9px] px-2 py-0.5 border border-emerald-500/50 bg-emerald-500/10 text-emerald-300 font-bold rounded flex items-center gap-1", children: [
|
|
67
|
-
/* @__PURE__ */ jsx(ShieldCheck, { size: 10 }),
|
|
68
|
-
" SYSTEM DB"
|
|
69
|
-
] })
|
|
70
|
-
] }),
|
|
71
|
-
error && /* @__PURE__ */ jsxs("div", { className: "p-3 border border-red-500/60 bg-red-500/10 text-red-300 text-xs rounded flex items-start gap-2", children: [
|
|
72
|
-
/* @__PURE__ */ jsx(AlertCircle, { size: 14, className: "shrink-0 mt-0.5" }),
|
|
73
|
-
/* @__PURE__ */ jsx("span", { children: error })
|
|
74
|
-
] }),
|
|
75
|
-
/* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: "space-y-3", children: [
|
|
76
|
-
isRegister && /* @__PURE__ */ jsxs("div", { children: [
|
|
77
|
-
/* @__PURE__ */ jsx("label", { className: "block text-[10px] font-black uppercase mb-1", children: "Full Name *" }),
|
|
78
|
-
/* @__PURE__ */ jsx(
|
|
79
|
-
BaseInput,
|
|
80
|
-
{
|
|
81
|
-
type: "text",
|
|
82
|
-
value: name,
|
|
83
|
-
onChange: (e) => setName(e.target.value),
|
|
84
|
-
placeholder: "Developer Name",
|
|
85
|
-
required: isRegister
|
|
86
|
-
}
|
|
87
|
-
)
|
|
88
|
-
] }),
|
|
89
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
90
|
-
/* @__PURE__ */ jsx("label", { className: "block text-[10px] font-black uppercase mb-1", children: "Email Address *" }),
|
|
91
|
-
/* @__PURE__ */ jsx(
|
|
92
|
-
BaseInput,
|
|
93
|
-
{
|
|
94
|
-
type: "email",
|
|
95
|
-
value: email,
|
|
96
|
-
onChange: (e) => setEmail(e.target.value),
|
|
97
|
-
placeholder: "user@example.com",
|
|
98
|
-
required: true
|
|
99
|
-
}
|
|
100
|
-
)
|
|
101
|
-
] }),
|
|
102
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
103
|
-
/* @__PURE__ */ jsx("label", { className: "block text-[10px] font-black uppercase mb-1", children: "Password *" }),
|
|
104
|
-
/* @__PURE__ */ jsx(
|
|
105
|
-
BaseInput,
|
|
106
|
-
{
|
|
107
|
-
type: "password",
|
|
108
|
-
value: password,
|
|
109
|
-
onChange: (e) => setPassword(e.target.value),
|
|
110
|
-
placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022",
|
|
111
|
-
required: true
|
|
112
|
-
}
|
|
113
|
-
)
|
|
114
|
-
] }),
|
|
115
|
-
/* @__PURE__ */ jsx("div", { className: "pt-2", children: /* @__PURE__ */ jsxs(
|
|
116
|
-
BaseButton,
|
|
117
|
-
{
|
|
118
|
-
variant: "accent",
|
|
119
|
-
size: "md",
|
|
120
|
-
type: "submit",
|
|
121
|
-
disabled: loading,
|
|
122
|
-
className: "w-full flex items-center justify-center gap-2",
|
|
123
|
-
children: [
|
|
124
|
-
/* @__PURE__ */ jsx("span", { children: loading ? "AUTHENTICATING..." : isRegister ? "REGISTER & ENTER" : "SIGN IN" }),
|
|
125
|
-
/* @__PURE__ */ jsx(ArrowRight, { size: 14 })
|
|
126
|
-
]
|
|
127
|
-
}
|
|
128
|
-
) })
|
|
129
|
-
] }),
|
|
130
|
-
/* @__PURE__ */ jsxs("div", { className: "pt-2 border-t border-[var(--skipo-border-color)]/60 flex items-center justify-between text-[11px]", children: [
|
|
131
|
-
/* @__PURE__ */ jsx(
|
|
132
|
-
"button",
|
|
133
|
-
{
|
|
134
|
-
type: "button",
|
|
135
|
-
onClick: () => {
|
|
136
|
-
setIsRegister(!isRegister);
|
|
137
|
-
setError(null);
|
|
138
|
-
},
|
|
139
|
-
className: "text-[var(--skipo-accent)] hover:underline cursor-pointer",
|
|
140
|
-
children: isRegister ? "Already have an account? Sign In" : "Create new account"
|
|
141
|
-
}
|
|
142
|
-
),
|
|
143
|
-
/* @__PURE__ */ jsx("span", { className: "text-[10px] text-[var(--skipo-text-muted)]", children: "ULTRST Identity" })
|
|
144
|
-
] })
|
|
145
|
-
] })
|
|
146
|
-
}
|
|
147
|
-
);
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
export {
|
|
151
|
-
LoginModal
|
|
152
|
-
};
|