@retinalabsllc/zairusjs 0.2.1 → 0.2.3
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/dist/index.d.mts +178 -3
- package/dist/index.d.ts +178 -3
- package/dist/index.js +1253 -168
- package/dist/index.mjs +1248 -157
- package/package.json +2 -1
package/dist/index.mjs
CHANGED
|
@@ -109,8 +109,335 @@ var ThreeDButton = ({
|
|
|
109
109
|
);
|
|
110
110
|
};
|
|
111
111
|
|
|
112
|
-
// src/components/
|
|
112
|
+
// src/components/ThreeDActionButton.tsx
|
|
113
113
|
import React3 from "react";
|
|
114
|
+
import { HugeiconsIcon as HugeiconsIcon2 } from "@hugeicons/react";
|
|
115
|
+
import { Loading03Icon } from "@hugeicons/core-free-icons";
|
|
116
|
+
var ThreeDActionButton = ({
|
|
117
|
+
type = "button",
|
|
118
|
+
onClick,
|
|
119
|
+
disabled = false,
|
|
120
|
+
isLoading = false,
|
|
121
|
+
children,
|
|
122
|
+
className = "",
|
|
123
|
+
ariaLabel
|
|
124
|
+
}) => {
|
|
125
|
+
const isInteractionDisabled = disabled || isLoading;
|
|
126
|
+
const baseShadow = `
|
|
127
|
+
inset 0 1.5px 0 0 rgba(255, 255, 255, 0.3),
|
|
128
|
+
inset 0 -2px 0 0 rgba(0, 0, 0, 0.5),
|
|
129
|
+
0 3px 0 0 #0c0c0c,
|
|
130
|
+
0 6px 10px rgba(0, 0, 0, 0.3)
|
|
131
|
+
`;
|
|
132
|
+
const hoverShadow = `
|
|
133
|
+
inset 0 1.5px 0 0 rgba(255, 255, 255, 0.35),
|
|
134
|
+
inset 0 -2px 0 0 rgba(0, 0, 0, 0.5),
|
|
135
|
+
0 4px 0 0 #0c0c0c,
|
|
136
|
+
0 8px 12px rgba(0, 0, 0, 0.35)
|
|
137
|
+
`;
|
|
138
|
+
const activeShadow = `
|
|
139
|
+
inset 0 1px 0 0 rgba(255, 255, 255, 0.1),
|
|
140
|
+
inset 0 -1px 0 0 rgba(0, 0, 0, 0.5),
|
|
141
|
+
0 1px 0 0 #0c0c0c,
|
|
142
|
+
0 2px 4px rgba(0, 0, 0, 0.2)
|
|
143
|
+
`;
|
|
144
|
+
const disabledShadow = `
|
|
145
|
+
inset 0 1px 0 0 rgba(255, 255, 255, 0.15),
|
|
146
|
+
inset 0 -1px 0 0 rgba(0, 0, 0, 0.3),
|
|
147
|
+
0 1px 0 0 #1c1c1c
|
|
148
|
+
`;
|
|
149
|
+
return /* @__PURE__ */ React3.createElement(
|
|
150
|
+
"button",
|
|
151
|
+
{
|
|
152
|
+
type,
|
|
153
|
+
disabled: isInteractionDisabled,
|
|
154
|
+
onClick,
|
|
155
|
+
"aria-label": ariaLabel,
|
|
156
|
+
className: `
|
|
157
|
+
relative inline-flex items-center justify-center py-2.5 px-8 rounded-full
|
|
158
|
+
bg-neutral-950 text-white text-xs tracking-widest
|
|
159
|
+
transition-all duration-150 select-none group outline-none
|
|
160
|
+
${isInteractionDisabled ? "opacity-50 cursor-not-allowed" : "active:translate-y-0.5"}
|
|
161
|
+
${className}
|
|
162
|
+
`,
|
|
163
|
+
style: { boxShadow: isInteractionDisabled ? disabledShadow : baseShadow },
|
|
164
|
+
onMouseEnter: (e) => {
|
|
165
|
+
if (isInteractionDisabled) return;
|
|
166
|
+
e.currentTarget.style.boxShadow = hoverShadow;
|
|
167
|
+
e.currentTarget.style.transform = "translateY(-1px)";
|
|
168
|
+
},
|
|
169
|
+
onMouseLeave: (e) => {
|
|
170
|
+
if (isInteractionDisabled) return;
|
|
171
|
+
e.currentTarget.style.boxShadow = baseShadow;
|
|
172
|
+
e.currentTarget.style.transform = "translateY(0px)";
|
|
173
|
+
},
|
|
174
|
+
onMouseDown: (e) => {
|
|
175
|
+
if (isInteractionDisabled) return;
|
|
176
|
+
e.currentTarget.style.boxShadow = activeShadow;
|
|
177
|
+
e.currentTarget.style.transform = "translateY(2px)";
|
|
178
|
+
},
|
|
179
|
+
onMouseUp: (e) => {
|
|
180
|
+
if (isInteractionDisabled) return;
|
|
181
|
+
e.currentTarget.style.transform = "translateY(-1px)";
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
/* @__PURE__ */ React3.createElement("span", { className: "absolute inset-0 rounded-full bg-linear-to-b from-white/10 via-white/5 to-transparent pointer-events-none" }),
|
|
185
|
+
/* @__PURE__ */ React3.createElement("span", { className: "relative z-10 flex items-center justify-center gap-2 leading-none" }, isLoading ? /* @__PURE__ */ React3.createElement(HugeiconsIcon2, { icon: Loading03Icon, size: 16, className: "animate-spin text-white" }) : children)
|
|
186
|
+
);
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
// src/components/ZairusAuth.tsx
|
|
190
|
+
import React4, { useState as useState2, useRef, useEffect, Suspense } from "react";
|
|
191
|
+
import { useSearchParams } from "next/navigation";
|
|
192
|
+
import toast from "react-hot-toast";
|
|
193
|
+
import { useGoogleReCaptcha, GoogleReCaptchaProvider } from "react-google-recaptcha-v3";
|
|
194
|
+
var InputSpinner = () => /* @__PURE__ */ React4.createElement("svg", { className: "animate-spin h-4 w-4 text-neutral-400", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24" }, /* @__PURE__ */ React4.createElement("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), /* @__PURE__ */ React4.createElement("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" }));
|
|
195
|
+
function AuthFormInner({
|
|
196
|
+
companyName,
|
|
197
|
+
workspaceLabel = "Workspace",
|
|
198
|
+
termsUrl = "https://retinalabs.company/terms-of-service",
|
|
199
|
+
privacyUrl = "https://retinalabs.company/privacy-policy",
|
|
200
|
+
requireNames = true,
|
|
201
|
+
requireOrganization = true,
|
|
202
|
+
useRecaptcha = false,
|
|
203
|
+
defaultRedirectPath = "/app",
|
|
204
|
+
onAuthRequest,
|
|
205
|
+
onVerifyOtp
|
|
206
|
+
}) {
|
|
207
|
+
const searchParams = useSearchParams();
|
|
208
|
+
const redirectUrl = searchParams.get("redirect") || defaultRedirectPath;
|
|
209
|
+
const captchaContext = useRecaptcha ? useGoogleReCaptcha() : null;
|
|
210
|
+
const [mode, setMode] = useState2("LOGIN");
|
|
211
|
+
const [step, setStep] = useState2("INPUT");
|
|
212
|
+
const getInitialSignupStep = () => {
|
|
213
|
+
if (requireNames) return "NAME";
|
|
214
|
+
if (requireOrganization) return "ORGANIZATION";
|
|
215
|
+
return "EMAIL_ID";
|
|
216
|
+
};
|
|
217
|
+
const [signupStep, setSignupStep] = useState2(getInitialSignupStep());
|
|
218
|
+
const [isSubmitting, setIsSubmitting] = useState2(false);
|
|
219
|
+
const [countdown, setCountdown] = useState2(0);
|
|
220
|
+
const [emailId, setEmailId] = useState2("");
|
|
221
|
+
const [firstName, setFirstName] = useState2("");
|
|
222
|
+
const [lastName, setLastName] = useState2("");
|
|
223
|
+
const [orgName, setOrgName] = useState2("");
|
|
224
|
+
const [agreedToTerms, setAgreedToTerms] = useState2(false);
|
|
225
|
+
const [otp, setOtp] = useState2(["", "", "", "", "", ""]);
|
|
226
|
+
const inputRefs = useRef([]);
|
|
227
|
+
const cleanAlpha = (val) => val.replace(/[^a-zA-Z\s-]/g, "");
|
|
228
|
+
const cleanOrgName = (val) => val.replace(/[^a-zA-Z0-9\s]/g, "").substring(0, 50);
|
|
229
|
+
const cleanEmailId = (val) => val.toLowerCase().replace(/[^a-z0-9@._-]/g, "");
|
|
230
|
+
useEffect(() => {
|
|
231
|
+
if (countdown > 0) {
|
|
232
|
+
const timer = setTimeout(() => setCountdown(countdown - 1), 1e3);
|
|
233
|
+
return () => clearTimeout(timer);
|
|
234
|
+
}
|
|
235
|
+
}, [countdown]);
|
|
236
|
+
const handleOtpChange = (index, value) => {
|
|
237
|
+
const cleanValue = value.replace(/[^0-9]/g, "");
|
|
238
|
+
if (!cleanValue && value !== "") return;
|
|
239
|
+
const newOtp = [...otp];
|
|
240
|
+
newOtp[index] = cleanValue.slice(-1);
|
|
241
|
+
setOtp(newOtp);
|
|
242
|
+
if (cleanValue && index < 5) {
|
|
243
|
+
inputRefs.current[index + 1]?.focus();
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
const handlePaste = (e) => {
|
|
247
|
+
e.preventDefault();
|
|
248
|
+
const pastedData = e.clipboardData.getData("text/plain");
|
|
249
|
+
const numbersOnly = pastedData.replace(/[^0-9]/g, "");
|
|
250
|
+
if (!numbersOnly) return;
|
|
251
|
+
const newOtp = [...otp];
|
|
252
|
+
const length = Math.min(numbersOnly.length, 6);
|
|
253
|
+
for (let i = 0; i < length; i++) {
|
|
254
|
+
newOtp[i] = numbersOnly[i];
|
|
255
|
+
}
|
|
256
|
+
setOtp(newOtp);
|
|
257
|
+
if (length < 6) {
|
|
258
|
+
inputRefs.current[length]?.focus();
|
|
259
|
+
} else {
|
|
260
|
+
inputRefs.current[5]?.focus();
|
|
261
|
+
verifyOtpCode(newOtp.join(""));
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
const handleAuthRequestSubmit = async (e) => {
|
|
265
|
+
if (e) e.preventDefault();
|
|
266
|
+
if (mode === "SIGNUP" && !agreedToTerms) {
|
|
267
|
+
toast.error("You must agree to the Terms and Privacy Policy.");
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
if (isSubmitting || countdown > 0) return;
|
|
271
|
+
setIsSubmitting(true);
|
|
272
|
+
try {
|
|
273
|
+
let recaptchaToken = void 0;
|
|
274
|
+
if (useRecaptcha && captchaContext?.executeRecaptcha) {
|
|
275
|
+
recaptchaToken = await captchaContext.executeRecaptcha("auth_request");
|
|
276
|
+
}
|
|
277
|
+
const res = await onAuthRequest({
|
|
278
|
+
email: emailId,
|
|
279
|
+
firstName: mode === "SIGNUP" && requireNames ? firstName : void 0,
|
|
280
|
+
lastName: mode === "SIGNUP" && requireNames ? lastName : void 0,
|
|
281
|
+
organizationName: mode === "SIGNUP" && requireOrganization ? orgName : void 0,
|
|
282
|
+
mode,
|
|
283
|
+
recaptchaToken
|
|
284
|
+
});
|
|
285
|
+
if (res.success) {
|
|
286
|
+
toast.success("Verification code sent");
|
|
287
|
+
setStep("OTP");
|
|
288
|
+
setCountdown(60);
|
|
289
|
+
} else {
|
|
290
|
+
toast.error(res.error || "Authentication failed.");
|
|
291
|
+
}
|
|
292
|
+
} catch {
|
|
293
|
+
toast.error("Service unavailable. Try again later.");
|
|
294
|
+
} finally {
|
|
295
|
+
setIsSubmitting(false);
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
const verifyOtpCode = async (codeToVerify) => {
|
|
299
|
+
if (codeToVerify.length !== 6 || isSubmitting) return;
|
|
300
|
+
setIsSubmitting(true);
|
|
301
|
+
try {
|
|
302
|
+
const res = await onVerifyOtp({ email: emailId, code: codeToVerify });
|
|
303
|
+
if (res.success) {
|
|
304
|
+
window.location.href = redirectUrl;
|
|
305
|
+
} else {
|
|
306
|
+
toast.error(res.error || "Invalid code.");
|
|
307
|
+
setOtp(["", "", "", "", "", ""]);
|
|
308
|
+
inputRefs.current[0]?.focus();
|
|
309
|
+
}
|
|
310
|
+
} catch {
|
|
311
|
+
toast.error("Verification failed.");
|
|
312
|
+
} finally {
|
|
313
|
+
setIsSubmitting(false);
|
|
314
|
+
}
|
|
315
|
+
};
|
|
316
|
+
const handleNextSignupStep = () => {
|
|
317
|
+
if (signupStep === "NAME") {
|
|
318
|
+
if (requireOrganization) setSignupStep("ORGANIZATION");
|
|
319
|
+
else setSignupStep("EMAIL_ID");
|
|
320
|
+
} else if (signupStep === "ORGANIZATION") {
|
|
321
|
+
setSignupStep("EMAIL_ID");
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
const isContinueDisabled = () => {
|
|
325
|
+
if (isSubmitting) return true;
|
|
326
|
+
if (mode === "LOGIN") return emailId.length < 3;
|
|
327
|
+
if (mode === "SIGNUP") {
|
|
328
|
+
if (signupStep === "NAME") return firstName.trim() === "" || lastName.trim() === "";
|
|
329
|
+
if (signupStep === "ORGANIZATION") return orgName.trim().length < 3;
|
|
330
|
+
if (signupStep === "EMAIL_ID") return emailId.length < 3 || !agreedToTerms;
|
|
331
|
+
}
|
|
332
|
+
return false;
|
|
333
|
+
};
|
|
334
|
+
return /* @__PURE__ */ React4.createElement("div", { className: "w-full max-w-md mx-auto border border-neutral-100 flex flex-col relative z-10 animate-in fade-in duration-300 rounded-2xl bg-white shadow-xs" }, /* @__PURE__ */ React4.createElement("div", { className: "p-8 md:p-12" }, step === "INPUT" && /* @__PURE__ */ React4.createElement("div", { className: "animate-in fade-in duration-300" }, /* @__PURE__ */ React4.createElement("div", { className: "mb-12 text-center mt-2" }, /* @__PURE__ */ React4.createElement("h2", { className: "text-xl text-black mb-2 tracking-tight " }, mode === "LOGIN" ? `${companyName} ${workspaceLabel}` : "Create Account"), /* @__PURE__ */ React4.createElement("div", { className: "text-[13px] text-neutral-500" }, mode === "LOGIN" ? /* @__PURE__ */ React4.createElement(React4.Fragment, null, "Don't have an account? ", /* @__PURE__ */ React4.createElement("button", { type: "button", onClick: () => {
|
|
335
|
+
setMode("SIGNUP");
|
|
336
|
+
setSignupStep(getInitialSignupStep());
|
|
337
|
+
}, className: "text-black transition-colors ml-1" }, "Sign up")) : /* @__PURE__ */ React4.createElement(React4.Fragment, null, "Already have an account? ", /* @__PURE__ */ React4.createElement("button", { type: "button", onClick: () => setMode("LOGIN"), className: "text-black transition-colors ml-1" }, "Log in")))), /* @__PURE__ */ React4.createElement("form", { className: "space-y-6", autoComplete: "off", onSubmit: (e) => {
|
|
338
|
+
e.preventDefault();
|
|
339
|
+
if (mode === "SIGNUP" && signupStep === "NAME") handleNextSignupStep();
|
|
340
|
+
else if (mode === "SIGNUP" && signupStep === "ORGANIZATION") handleNextSignupStep();
|
|
341
|
+
else handleAuthRequestSubmit();
|
|
342
|
+
} }, mode === "SIGNUP" && signupStep === "NAME" && requireNames && /* @__PURE__ */ React4.createElement("div", { className: "flex flex-col gap-6" }, /* @__PURE__ */ React4.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React4.createElement("label", { className: "text-[10px] text-neutral-400 tracking-[0.2em] block uppercase" }, "First Name"), /* @__PURE__ */ React4.createElement(
|
|
343
|
+
"input",
|
|
344
|
+
{
|
|
345
|
+
type: "text",
|
|
346
|
+
value: firstName,
|
|
347
|
+
onChange: (e) => setFirstName(cleanAlpha(e.target.value)),
|
|
348
|
+
required: true,
|
|
349
|
+
autoFocus: true,
|
|
350
|
+
className: "w-full px-2 py-3 text-sm bg-transparent border-b border-neutral-200 text-black outline-none focus:border-black transition-all duration-300",
|
|
351
|
+
placeholder: "First name"
|
|
352
|
+
}
|
|
353
|
+
)), /* @__PURE__ */ React4.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React4.createElement("label", { className: "text-[10px] text-neutral-400 tracking-[0.2em] block uppercase" }, "Last Name"), /* @__PURE__ */ React4.createElement(
|
|
354
|
+
"input",
|
|
355
|
+
{
|
|
356
|
+
type: "text",
|
|
357
|
+
value: lastName,
|
|
358
|
+
onChange: (e) => setLastName(cleanAlpha(e.target.value)),
|
|
359
|
+
required: true,
|
|
360
|
+
className: "w-full px-2 py-3 bg-transparent text-sm border-b border-neutral-200 text-black outline-none focus:border-black transition-all duration-300",
|
|
361
|
+
placeholder: "Last name"
|
|
362
|
+
}
|
|
363
|
+
))), mode === "SIGNUP" && signupStep === "ORGANIZATION" && requireOrganization && /* @__PURE__ */ React4.createElement("div", { className: "flex flex-col gap-6" }, /* @__PURE__ */ React4.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ React4.createElement("label", { className: "text-[10px] text-neutral-400 tracking-[0.2em] block uppercase" }, "Organization Name"), /* @__PURE__ */ React4.createElement(
|
|
364
|
+
"input",
|
|
365
|
+
{
|
|
366
|
+
type: "text",
|
|
367
|
+
value: orgName,
|
|
368
|
+
onChange: (e) => setOrgName(cleanOrgName(e.target.value)),
|
|
369
|
+
required: true,
|
|
370
|
+
autoFocus: true,
|
|
371
|
+
className: "w-full px-2 py-3 text-sm bg-transparent border-b border-neutral-200 text-black outline-none focus:border-black transition-all duration-300",
|
|
372
|
+
placeholder: "Acme Corporation"
|
|
373
|
+
}
|
|
374
|
+
))), (mode === "LOGIN" || mode === "SIGNUP" && signupStep === "EMAIL_ID") && /* @__PURE__ */ React4.createElement("div", { className: "space-y-6" }, /* @__PURE__ */ React4.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React4.createElement("label", { className: "text-[10px] text-neutral-400 tracking-[0.2em] block uppercase" }, "Email ID"), /* @__PURE__ */ React4.createElement(
|
|
375
|
+
"input",
|
|
376
|
+
{
|
|
377
|
+
type: "email",
|
|
378
|
+
value: emailId,
|
|
379
|
+
onChange: (e) => setEmailId(cleanEmailId(e.target.value)),
|
|
380
|
+
required: true,
|
|
381
|
+
autoFocus: true,
|
|
382
|
+
className: "w-full px-2 py-3 bg-transparent text-sm border-b border-neutral-200 text-black outline-none focus:border-black transition-all duration-300",
|
|
383
|
+
placeholder: "name@company.com"
|
|
384
|
+
}
|
|
385
|
+
)), mode === "SIGNUP" && /* @__PURE__ */ React4.createElement("div", { className: "flex items-start gap-3 mt-4" }, /* @__PURE__ */ React4.createElement(
|
|
386
|
+
"input",
|
|
387
|
+
{
|
|
388
|
+
type: "checkbox",
|
|
389
|
+
id: "zairus-terms",
|
|
390
|
+
checked: agreedToTerms,
|
|
391
|
+
onChange: (e) => setAgreedToTerms(e.target.checked),
|
|
392
|
+
className: "mt-0.5 w-4 h-4 bg-white border-neutral-300 rounded text-black focus:ring-black cursor-pointer",
|
|
393
|
+
required: true
|
|
394
|
+
}
|
|
395
|
+
), /* @__PURE__ */ React4.createElement("label", { htmlFor: "zairus-terms", className: "text-[11px] text-neutral-500 cursor-pointer leading-snug" }, "I agree to ", companyName, "'s ", /* @__PURE__ */ React4.createElement("a", { href: termsUrl, target: "_blank", rel: "noreferrer", className: "text-black underline font-medium" }, "Terms of Service"), " and ", /* @__PURE__ */ React4.createElement("a", { href: privacyUrl, target: "_blank", rel: "noreferrer", className: "text-black underline font-medium" }, "Privacy Policy"), "."))), /* @__PURE__ */ React4.createElement(
|
|
396
|
+
ThreeDActionButton,
|
|
397
|
+
{
|
|
398
|
+
type: "submit",
|
|
399
|
+
disabled: isContinueDisabled(),
|
|
400
|
+
isLoading: isSubmitting,
|
|
401
|
+
className: "w-full mt-10"
|
|
402
|
+
},
|
|
403
|
+
"Continue"
|
|
404
|
+
))), step === "OTP" && /* @__PURE__ */ React4.createElement("div", { className: "animate-in fade-in duration-300" }, /* @__PURE__ */ React4.createElement("div", { className: "text-center mb-10 mt-2" }, /* @__PURE__ */ React4.createElement("h2", { className: "text-xl text-black mb-2 tracking-tight " }, "Security Check"), /* @__PURE__ */ React4.createElement("p", { className: "text-[13px] text-neutral-500" }, "Enter the code sent to ", /* @__PURE__ */ React4.createElement("br", null), /* @__PURE__ */ React4.createElement("span", { className: "text-black font-medium" }, emailId))), /* @__PURE__ */ React4.createElement("form", { className: "space-y-10", autoComplete: "off", onSubmit: (e) => {
|
|
405
|
+
e.preventDefault();
|
|
406
|
+
verifyOtpCode(otp.join(""));
|
|
407
|
+
} }, /* @__PURE__ */ React4.createElement("div", { className: "flex justify-between gap-2", onPaste: handlePaste }, otp.map((digit, index) => /* @__PURE__ */ React4.createElement(
|
|
408
|
+
"input",
|
|
409
|
+
{
|
|
410
|
+
key: index,
|
|
411
|
+
ref: (el) => {
|
|
412
|
+
inputRefs.current[index] = el;
|
|
413
|
+
},
|
|
414
|
+
type: "text",
|
|
415
|
+
inputMode: "numeric",
|
|
416
|
+
maxLength: 1,
|
|
417
|
+
value: digit,
|
|
418
|
+
onChange: (e) => handleOtpChange(index, e.target.value),
|
|
419
|
+
className: "w-10 h-10 text-center text-xl bg-transparent border-b-2 border-neutral-200 text-black outline-none focus:border-black transition-all duration-300"
|
|
420
|
+
}
|
|
421
|
+
))), /* @__PURE__ */ React4.createElement(
|
|
422
|
+
ThreeDActionButton,
|
|
423
|
+
{
|
|
424
|
+
type: "submit",
|
|
425
|
+
disabled: otp.join("").length < 6,
|
|
426
|
+
isLoading: isSubmitting,
|
|
427
|
+
className: "w-full"
|
|
428
|
+
},
|
|
429
|
+
"Verify Code"
|
|
430
|
+
)))));
|
|
431
|
+
}
|
|
432
|
+
var ZairusAuth = (props) => {
|
|
433
|
+
if (props.useRecaptcha && props.recaptchaSiteKey) {
|
|
434
|
+
return /* @__PURE__ */ React4.createElement(GoogleReCaptchaProvider, { reCaptchaKey: props.recaptchaSiteKey }, /* @__PURE__ */ React4.createElement(Suspense, { fallback: /* @__PURE__ */ React4.createElement("div", { className: "h-64 flex items-center justify-center" }, /* @__PURE__ */ React4.createElement(InputSpinner, null)) }, /* @__PURE__ */ React4.createElement(AuthFormInner, { ...props })));
|
|
435
|
+
}
|
|
436
|
+
return /* @__PURE__ */ React4.createElement(Suspense, { fallback: /* @__PURE__ */ React4.createElement("div", { className: "h-64 flex items-center justify-center" }, /* @__PURE__ */ React4.createElement(InputSpinner, null)) }, /* @__PURE__ */ React4.createElement(AuthFormInner, { ...props }));
|
|
437
|
+
};
|
|
438
|
+
|
|
439
|
+
// src/components/Header.tsx
|
|
440
|
+
import React5 from "react";
|
|
114
441
|
import Link2 from "next/link";
|
|
115
442
|
import Image from "next/image";
|
|
116
443
|
import { usePathname } from "next/navigation";
|
|
@@ -124,7 +451,7 @@ var NavLink = ({
|
|
|
124
451
|
const isActive = pathname === href;
|
|
125
452
|
const activeClass = light ? "text-neutral-950 font-medium" : "text-white font-medium";
|
|
126
453
|
const inactiveClass = light ? "text-neutral-600 hover:text-neutral-950" : "text-neutral-400 hover:text-white";
|
|
127
|
-
return /* @__PURE__ */
|
|
454
|
+
return /* @__PURE__ */ React5.createElement(
|
|
128
455
|
Link2,
|
|
129
456
|
{
|
|
130
457
|
href,
|
|
@@ -151,7 +478,7 @@ var Header = ({
|
|
|
151
478
|
const titleColor = light ? "text-black" : "text-white";
|
|
152
479
|
const subtitleColor = light ? "text-neutral-500" : "text-neutral-400";
|
|
153
480
|
const hasBrandSection = showLogo || !hideHeaderText;
|
|
154
|
-
return /* @__PURE__ */
|
|
481
|
+
return /* @__PURE__ */ React5.createElement("div", { className: "absolute inset-x-0 top-0 w-full z-50 pointer-events-none px-4 pt-4 sm:pt-6" }, /* @__PURE__ */ React5.createElement("div", { className: "max-w-5xl mx-auto w-full pointer-events-auto flex justify-center" }, /* @__PURE__ */ React5.createElement("header", { className: `${headerLayoutWidth} ${headerBgStyle} backdrop-blur-md rounded-full py-2 px-6 flex items-center border transition-all duration-300` }, hasBrandSection && /* @__PURE__ */ React5.createElement("div", { className: "flex items-center shrink-0" }, /* @__PURE__ */ React5.createElement(Link2, { href: "/", className: "flex items-center gap-3 transition-opacity hover:opacity-70" }, showLogo && /* @__PURE__ */ React5.createElement(
|
|
155
482
|
Image,
|
|
156
483
|
{
|
|
157
484
|
src: logoSrc,
|
|
@@ -161,7 +488,7 @@ var Header = ({
|
|
|
161
488
|
className: `object-contain w-5 h-auto ${invert ? "invert" : ""}`,
|
|
162
489
|
priority: true
|
|
163
490
|
}
|
|
164
|
-
), !hideHeaderText && /* @__PURE__ */
|
|
491
|
+
), !hideHeaderText && /* @__PURE__ */ React5.createElement("div", { className: "flex flex-col justify-center" }, /* @__PURE__ */ React5.createElement("span", { className: `text-[12px] leading-none tracking-wide mb-1 transition-colors ${titleColor}` }, companyName), subtitle && /* @__PURE__ */ React5.createElement("span", { className: `text-[9px] tracking-widest leading-none transition-colors ${subtitleColor}` }, subtitle)))), /* @__PURE__ */ React5.createElement("nav", { className: "flex items-center gap-1 md:gap-2 shrink-0" }, links.map((link, index) => /* @__PURE__ */ React5.createElement(
|
|
165
492
|
NavLink,
|
|
166
493
|
{
|
|
167
494
|
key: index,
|
|
@@ -174,9 +501,9 @@ var Header = ({
|
|
|
174
501
|
};
|
|
175
502
|
|
|
176
503
|
// src/components/Footer.tsx
|
|
177
|
-
import
|
|
504
|
+
import React6, { useState as useState3 } from "react";
|
|
178
505
|
import Link3 from "next/link";
|
|
179
|
-
import { HugeiconsIcon as
|
|
506
|
+
import { HugeiconsIcon as HugeiconsIcon3 } from "@hugeicons/react";
|
|
180
507
|
var Footer = ({
|
|
181
508
|
description,
|
|
182
509
|
columns,
|
|
@@ -184,20 +511,20 @@ var Footer = ({
|
|
|
184
511
|
copyrightText,
|
|
185
512
|
topSection
|
|
186
513
|
}) => {
|
|
187
|
-
const [openCol, setOpenCol] =
|
|
514
|
+
const [openCol, setOpenCol] = useState3(null);
|
|
188
515
|
const toggleColumn = (idx) => {
|
|
189
516
|
setOpenCol(openCol === idx ? null : idx);
|
|
190
517
|
};
|
|
191
|
-
return /* @__PURE__ */
|
|
518
|
+
return /* @__PURE__ */ React6.createElement("div", { className: "" }, topSection && topSection, /* @__PURE__ */ React6.createElement("footer", { className: "relative px-6 overflow-hidden flex flex-col" }, /* @__PURE__ */ React6.createElement("div", { className: "relative w-full max-w-7xl mx-auto z-20 flex flex-col" }, /* @__PURE__ */ React6.createElement("div", { className: "relative py-12 md:py-16" }, /* @__PURE__ */ React6.createElement("div", { className: "flex flex-col lg:flex-row justify-between items-start gap-12 lg:gap-16 mb-12 text-left" }, /* @__PURE__ */ React6.createElement("div", { className: "w-full lg:max-w-sm flex flex-col items-start justify-between shrink-0" }, /* @__PURE__ */ React6.createElement("div", null, /* @__PURE__ */ React6.createElement("p", { className: "text-[12px] font-serif text-neutral-600 leading-relaxed pr-4" }, description))), /* @__PURE__ */ React6.createElement("div", { className: "w-full lg:flex-1 lg:max-w-2xl" }, /* @__PURE__ */ React6.createElement("div", { className: "hidden md:grid grid-cols-2 gap-x-16 lg:gap-x-24 gap-y-12" }, columns.map((col, idx) => /* @__PURE__ */ React6.createElement("div", { key: idx, className: "flex flex-col" }, /* @__PURE__ */ React6.createElement("h4", { className: "text-[11px] tracking-[0.2em] text-black mb-6 uppercase" }, col.title), /* @__PURE__ */ React6.createElement("ul", { className: "space-y-4 text-[13px] text-neutral-500" }, col.links.map((link, lIdx) => /* @__PURE__ */ React6.createElement("li", { key: lIdx }, link.isExternal ? /* @__PURE__ */ React6.createElement("a", { href: link.href, target: "_blank", rel: "noopener noreferrer", className: "hover:text-black transition-colors block truncate" }, link.label) : /* @__PURE__ */ React6.createElement(Link3, { href: link.href, className: "hover:text-black transition-colors block truncate" }, link.label))))))), /* @__PURE__ */ React6.createElement("div", { className: "flex flex-col md:hidden w-full border-t border-neutral-200 mt-4" }, columns.map((col, idx) => {
|
|
192
519
|
const isOpen = openCol === idx;
|
|
193
|
-
return /* @__PURE__ */
|
|
520
|
+
return /* @__PURE__ */ React6.createElement("div", { key: idx, className: "border-b border-neutral-200" }, /* @__PURE__ */ React6.createElement(
|
|
194
521
|
"button",
|
|
195
522
|
{
|
|
196
523
|
onClick: () => toggleColumn(idx),
|
|
197
524
|
className: "w-full flex items-center justify-between py-5 text-left outline-none"
|
|
198
525
|
},
|
|
199
|
-
/* @__PURE__ */
|
|
200
|
-
/* @__PURE__ */
|
|
526
|
+
/* @__PURE__ */ React6.createElement("span", { className: "text-[11px] tracking-[0.2em] text-black uppercase" }, col.title),
|
|
527
|
+
/* @__PURE__ */ React6.createElement(
|
|
201
528
|
"svg",
|
|
202
529
|
{
|
|
203
530
|
className: `w-4 h-4 text-neutral-400 transition-transform duration-300 ${isOpen ? "rotate-180" : ""}`,
|
|
@@ -205,10 +532,10 @@ var Footer = ({
|
|
|
205
532
|
viewBox: "0 0 24 24",
|
|
206
533
|
stroke: "currentColor"
|
|
207
534
|
},
|
|
208
|
-
/* @__PURE__ */
|
|
535
|
+
/* @__PURE__ */ React6.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M19 9l-7 7-7-7" })
|
|
209
536
|
)
|
|
210
|
-
), /* @__PURE__ */
|
|
211
|
-
})))), /* @__PURE__ */
|
|
537
|
+
), /* @__PURE__ */ React6.createElement("div", { className: `grid transition-all duration-300 ease-in-out ${isOpen ? "grid-rows-[1fr] pb-6 opacity-100" : "grid-rows-[0fr] opacity-0"}` }, /* @__PURE__ */ React6.createElement("div", { className: "overflow-hidden" }, /* @__PURE__ */ React6.createElement("ul", { className: "space-y-4 text-[13px] text-neutral-500 pt-2" }, col.links.map((link, lIdx) => /* @__PURE__ */ React6.createElement("li", { key: lIdx }, link.isExternal ? /* @__PURE__ */ React6.createElement("a", { href: link.href, target: "_blank", rel: "noopener noreferrer", className: "hover:text-black transition-colors" }, link.label) : /* @__PURE__ */ React6.createElement(Link3, { href: link.href, className: "hover:text-black transition-colors" }, link.label)))))));
|
|
538
|
+
})))), /* @__PURE__ */ React6.createElement("div", { className: "pt-8 mt-4 border-t border-neutral-200 flex flex-col-reverse md:flex-row justify-between items-start md:items-center gap-6 relative z-20" }, /* @__PURE__ */ React6.createElement("p", { className: "text-[11px] text-neutral-400 tracking-widest text-left" }, copyrightText), socialLinks && socialLinks.length > 0 && /* @__PURE__ */ React6.createElement("div", { className: "flex items-center gap-6" }, socialLinks.map((social, idx) => /* @__PURE__ */ React6.createElement(
|
|
212
539
|
"a",
|
|
213
540
|
{
|
|
214
541
|
key: idx,
|
|
@@ -218,12 +545,12 @@ var Footer = ({
|
|
|
218
545
|
className: "text-neutral-400 hover:text-black transition-colors",
|
|
219
546
|
"aria-label": social.name
|
|
220
547
|
},
|
|
221
|
-
/* @__PURE__ */
|
|
548
|
+
/* @__PURE__ */ React6.createElement(HugeiconsIcon3, { icon: social.icon, size: 20 })
|
|
222
549
|
))))))));
|
|
223
550
|
};
|
|
224
551
|
|
|
225
552
|
// src/components/HeroSection.tsx
|
|
226
|
-
import
|
|
553
|
+
import React7 from "react";
|
|
227
554
|
import Link4 from "next/link";
|
|
228
555
|
import Image2 from "next/image";
|
|
229
556
|
var HeroSection = ({
|
|
@@ -239,7 +566,7 @@ var HeroSection = ({
|
|
|
239
566
|
showImage = false,
|
|
240
567
|
imageSrc = "/assets/ai.avif"
|
|
241
568
|
}) => {
|
|
242
|
-
return /* @__PURE__ */
|
|
569
|
+
return /* @__PURE__ */ React7.createElement("section", { className: "relative pt-32 sm:pt-40 pb-16 flex flex-col items-center overflow-hidden w-full" }, /* @__PURE__ */ React7.createElement(
|
|
243
570
|
"div",
|
|
244
571
|
{
|
|
245
572
|
className: "absolute inset-0 w-full h-full pointer-events-none z-0",
|
|
@@ -247,7 +574,7 @@ var HeroSection = ({
|
|
|
247
574
|
background: `radial-gradient(120% 100% at 50% 0%, #043324 0%, #21a473 45%, #e0f6ce 80%, #f5f5f5 100%)`
|
|
248
575
|
}
|
|
249
576
|
}
|
|
250
|
-
), /* @__PURE__ */
|
|
577
|
+
), /* @__PURE__ */ React7.createElement(
|
|
251
578
|
"div",
|
|
252
579
|
{
|
|
253
580
|
className: "absolute inset-0 w-full h-full pointer-events-none z-0 opacity-[0.25] mix-blend-overlay",
|
|
@@ -255,14 +582,14 @@ var HeroSection = ({
|
|
|
255
582
|
backgroundImage: `url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E")`
|
|
256
583
|
}
|
|
257
584
|
}
|
|
258
|
-
), /* @__PURE__ */
|
|
585
|
+
), /* @__PURE__ */ React7.createElement("div", { className: "relative max-w-5xl mx-auto px-4 sm:px-6 w-full flex flex-col items-center text-center z-10" }, badgeText && /* @__PURE__ */ React7.createElement("div", { className: "inline-flex items-center gap-1.5 mb-6 px-4 py-1.5 rounded-full bg-white/10 backdrop-blur-md shadow-xs" }, /* @__PURE__ */ React7.createElement("span", { className: "text-[10px] tracking-[0.4em] text-white uppercase" }, badgeText)), /* @__PURE__ */ React7.createElement("h1", { className: "text-[40px] md:text-5xl lg:text-7xl text-white tracking-tight leading-[1.05] max-w-4xl mb-4" }, titlePrefix), /* @__PURE__ */ React7.createElement("div", { className: "flex justify-center mt-2 mb-10 md:mb-14" }, /* @__PURE__ */ React7.createElement("span", { className: "relative inline-block mx-1.5 px-4 py-2 md:py-3 bg-[#21a473]/25 border border-[#3ae9a8] rounded-sm text-white select-none font-serif text-4xl lg:text-6xl tracking-tight" }, /* @__PURE__ */ React7.createElement("span", { className: "absolute top-[-3.5px] left-[-3.5px] w-2 h-2 bg-white border border-[#21a473] rounded-[1px] z-10" }), /* @__PURE__ */ React7.createElement("span", { className: "absolute top-[-3.5px] right-[-3.5px] w-2 h-2 bg-white border border-[#21a473] rounded-[1px] z-10" }), /* @__PURE__ */ React7.createElement("span", { className: "absolute bottom-[-3.5px] left-[-3.5px] w-2 h-2 bg-white border border-[#21a473] rounded-[1px] z-10" }), /* @__PURE__ */ React7.createElement("span", { className: "absolute bottom-[-3.5px] right-[-3.5px] w-2 h-2 bg-white border border-[#21a473] rounded-[1px] z-10" }), highlightText, /* @__PURE__ */ React7.createElement("span", { className: "absolute -bottom-5 -right-5 flex items-center z-20 pointer-events-none select-none filter drop-shadow-[0_2px_4px_rgba(0,0,0,0.25)]" }, /* @__PURE__ */ React7.createElement("svg", { width: "18", height: "22", viewBox: "0 0 16 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", className: "transform -rotate-12" }, /* @__PURE__ */ React7.createElement("path", { d: "M1 1V17.8L5.8 13.1H12.8L1 1Z", fill: "#21a473", stroke: "white", strokeWidth: "1.8", strokeLinejoin: "round" })), /* @__PURE__ */ React7.createElement("span", { className: "ml-1 bg-[#21a473] text-[10px] text-white px-2 py-0.5 rounded-full border border-white tracking-wide" }, cursorLabel)))), subtitle && /* @__PURE__ */ React7.createElement("p", { className: "text-[13px] md:text-[15px] text-[#bbf7df]/90 max-w-xl mx-auto mb-10 font-light leading-relaxed" }, subtitle), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col sm:flex-row gap-4 justify-center items-center w-full px-2 sm:px-0 mx-auto mb-10" }, ctaText && ctaHref && /* @__PURE__ */ React7.createElement("div", { className: "w-full sm:w-60 flex justify-center *:w-full" }, /* @__PURE__ */ React7.createElement(ThreeDButton, { href: ctaHref }, ctaText)), secondaryCtaText && secondaryCtaHref && /* @__PURE__ */ React7.createElement(
|
|
259
586
|
Link4,
|
|
260
587
|
{
|
|
261
588
|
href: secondaryCtaHref,
|
|
262
589
|
className: "w-full sm:w-60 inline-flex items-center justify-center text-[12px] tracking-widest rounded-full px-8 py-2.5 bg-white text-black transition-colors hover:bg-neutral-200 outline-none"
|
|
263
590
|
},
|
|
264
591
|
secondaryCtaText
|
|
265
|
-
)), showImage && /* @__PURE__ */
|
|
592
|
+
)), showImage && /* @__PURE__ */ React7.createElement("div", { className: "w-full max-w-4xl mx-auto px-2 sm:px-6" }, /* @__PURE__ */ React7.createElement("div", { className: "relative w-full flex flex-col items-center" }, /* @__PURE__ */ React7.createElement("div", { className: "relative w-full rounded-t-xl overflow-hidden border-[5px] border-[#1c1c1e] bg-[#1c1c1e] shadow-2xl aspect-video" }, /* @__PURE__ */ React7.createElement("div", { className: "absolute top-1.5 left-1/2 -translate-x-1/2 w-2.5 h-2.5 bg-[#0a0a0b] rounded-full flex items-center justify-center z-30" }, /* @__PURE__ */ React7.createElement("div", { className: "w-1 h-1 bg-[#1a2d42] rounded-full" })), /* @__PURE__ */ React7.createElement("div", { className: "relative w-full h-full rounded-sm overflow-hidden" }, /* @__PURE__ */ React7.createElement(
|
|
266
593
|
Image2,
|
|
267
594
|
{
|
|
268
595
|
src: imageSrc,
|
|
@@ -272,14 +599,14 @@ var HeroSection = ({
|
|
|
272
599
|
className: "object-cover object-top",
|
|
273
600
|
priority: true
|
|
274
601
|
}
|
|
275
|
-
))), /* @__PURE__ */
|
|
602
|
+
))), /* @__PURE__ */ React7.createElement("div", { className: "relative w-[105%] h-2 md:h-2.5 bg-linear-to-b from-[#e2e8f0] via-[#cbd5e1] to-[#94a3b8] rounded-b-xl border-t border-slate-300 shadow-xl flex justify-center" }, /* @__PURE__ */ React7.createElement("div", { className: "w-16 md:w-24 h-1 md:h-1.5 bg-slate-400/30 rounded-b-md" }))))));
|
|
276
603
|
};
|
|
277
604
|
|
|
278
605
|
// src/components/AppBento2.tsx
|
|
279
|
-
import
|
|
280
|
-
import { HugeiconsIcon as
|
|
606
|
+
import React8 from "react";
|
|
607
|
+
import { HugeiconsIcon as HugeiconsIcon4 } from "@hugeicons/react";
|
|
281
608
|
var AppBento2 = ({ tagline, headline, features }) => {
|
|
282
|
-
return /* @__PURE__ */
|
|
609
|
+
return /* @__PURE__ */ React8.createElement("div", { className: "w-full py-16" }, /* @__PURE__ */ React8.createElement("div", { className: "w-full flex justify-center px-4" }, /* @__PURE__ */ React8.createElement("div", { className: "max-w-6xl w-full" }, /* @__PURE__ */ React8.createElement("div", { className: "relative overflow-hidden mb-12 text-left" }, /* @__PURE__ */ React8.createElement("div", { className: "relative z-10" }, /* @__PURE__ */ React8.createElement("span", { className: "text-[10px] tracking-[0.4em] text-neutral-500 block mb-4 uppercase" }, tagline), /* @__PURE__ */ React8.createElement("h2", { className: "text-3xl font-serif md:text-4xl tracking-tight text-black leading-[1.1]" }, headline))), /* @__PURE__ */ React8.createElement("div", { className: "grid grid-cols-1 lg:grid-cols-6 gap-6" }, features.map((f, i) => {
|
|
283
610
|
const isWhite = i === 0;
|
|
284
611
|
const isBlack = i === 1;
|
|
285
612
|
const isNeutral = i === 2;
|
|
@@ -301,35 +628,35 @@ var AppBento2 = ({ tagline, headline, features }) => {
|
|
|
301
628
|
const textColor = isBlack ? "text-white" : "text-black";
|
|
302
629
|
const subTextColor = isBlack ? "text-neutral-300" : "text-neutral-600";
|
|
303
630
|
const labelColor = isBlack ? "text-neutral-400" : "text-neutral-500";
|
|
304
|
-
return /* @__PURE__ */
|
|
631
|
+
return /* @__PURE__ */ React8.createElement(
|
|
305
632
|
"div",
|
|
306
633
|
{
|
|
307
634
|
key: i,
|
|
308
635
|
className: `relative rounded-2xl overflow-hidden p-8 flex flex-col min-h-75 transition-all duration-500 group text-left ${getBgStyle()} ${f.size}`,
|
|
309
636
|
style: { boxShadow: getShadowStyle() }
|
|
310
637
|
},
|
|
311
|
-
/* @__PURE__ */
|
|
638
|
+
/* @__PURE__ */ React8.createElement(
|
|
312
639
|
"div",
|
|
313
640
|
{
|
|
314
641
|
className: "absolute inset-0 pointer-events-none opacity-[0.03] z-0",
|
|
315
642
|
style: { backgroundImage: `url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E")` }
|
|
316
643
|
}
|
|
317
644
|
),
|
|
318
|
-
isBlack && /* @__PURE__ */
|
|
319
|
-
/* @__PURE__ */
|
|
320
|
-
/* @__PURE__ */
|
|
645
|
+
isBlack && /* @__PURE__ */ React8.createElement("span", { className: "absolute inset-0 rounded-2xl bg-linear-to-b from-white/10 via-white/5 to-transparent pointer-events-none z-10" }),
|
|
646
|
+
/* @__PURE__ */ React8.createElement("div", { className: "absolute inset-0 overflow-hidden pointer-events-none z-0" }, /* @__PURE__ */ React8.createElement("div", { className: `absolute -bottom-8 -right-8 transform group-hover:scale-110 transition-transform duration-700 ease-out ${isBlack ? "text-white/5" : "text-black/5"}` }, /* @__PURE__ */ React8.createElement(HugeiconsIcon4, { icon: f.icon, size: 180 }))),
|
|
647
|
+
/* @__PURE__ */ React8.createElement("div", { className: "relative z-10 w-full h-full flex flex-col pointer-events-auto" }, /* @__PURE__ */ React8.createElement("div", { className: "flex items-center justify-between mb-8" }, /* @__PURE__ */ React8.createElement("span", { className: `text-[9px] uppercase tracking-widest ${labelColor}` }, f.label), /* @__PURE__ */ React8.createElement("div", { className: `p-2 rounded-full transition-colors ${isBlack ? "bg-white/10" : "bg-white/50 backdrop-blur-sm"}` }, /* @__PURE__ */ React8.createElement(HugeiconsIcon4, { icon: f.icon, size: 20, className: textColor }))), /* @__PURE__ */ React8.createElement("div", { className: "mt-auto" }, /* @__PURE__ */ React8.createElement("h3", { className: `text-xl font-serif mb-2 tracking-tight ${textColor}` }, f.title), /* @__PURE__ */ React8.createElement("p", { className: `text-[13px] leading-relaxed max-w-sm ${subTextColor}` }, f.desc)))
|
|
321
648
|
);
|
|
322
649
|
})))));
|
|
323
650
|
};
|
|
324
651
|
|
|
325
652
|
// src/components/FeatureScroll.tsx
|
|
326
|
-
import
|
|
653
|
+
import React9, { useRef as useRef2, useState as useState4, useEffect as useEffect2 } from "react";
|
|
327
654
|
import Image3 from "next/image";
|
|
328
|
-
import { HugeiconsIcon as
|
|
329
|
-
import { ArrowLeft01Icon, ArrowRight01Icon, Loading03Icon } from "@hugeicons/core-free-icons";
|
|
655
|
+
import { HugeiconsIcon as HugeiconsIcon5 } from "@hugeicons/react";
|
|
656
|
+
import { ArrowLeft01Icon, ArrowRight01Icon, Loading03Icon as Loading03Icon2 } from "@hugeicons/core-free-icons";
|
|
330
657
|
var FeatureCard = ({ feature }) => {
|
|
331
|
-
const [isLoading, setIsLoading] =
|
|
332
|
-
return /* @__PURE__ */
|
|
658
|
+
const [isLoading, setIsLoading] = useState4(!!feature.image);
|
|
659
|
+
return /* @__PURE__ */ React9.createElement("div", { className: "flex flex-col shrink-0 w-[90vw] sm:w-150 snap-center md:snap-start group cursor-grab active:cursor-grabbing" }, /* @__PURE__ */ React9.createElement("div", { className: "relative w-full aspect-16/10 bg-neutral-100 rounded-2xl overflow-hidden mb-6 flex items-center justify-center" }, /* @__PURE__ */ React9.createElement(
|
|
333
660
|
"div",
|
|
334
661
|
{
|
|
335
662
|
className: "absolute inset-0 pointer-events-none opacity-[0.03] z-20 mix-blend-overlay",
|
|
@@ -338,7 +665,7 @@ var FeatureCard = ({ feature }) => {
|
|
|
338
665
|
backgroundRepeat: "repeat"
|
|
339
666
|
}
|
|
340
667
|
}
|
|
341
|
-
), isLoading && feature.image && /* @__PURE__ */
|
|
668
|
+
), isLoading && feature.image && /* @__PURE__ */ React9.createElement("div", { className: "absolute inset-0 flex items-center justify-center z-10 bg-neutral-50/50 backdrop-blur-sm" }, /* @__PURE__ */ React9.createElement(HugeiconsIcon5, { icon: Loading03Icon2, size: 32, className: "animate-spin text-neutral-400" })), feature.image ? /* @__PURE__ */ React9.createElement(
|
|
342
669
|
Image3,
|
|
343
670
|
{
|
|
344
671
|
src: feature.image,
|
|
@@ -352,12 +679,12 @@ var FeatureCard = ({ feature }) => {
|
|
|
352
679
|
group-hover:scale-105
|
|
353
680
|
`
|
|
354
681
|
}
|
|
355
|
-
) : /* @__PURE__ */
|
|
682
|
+
) : /* @__PURE__ */ React9.createElement("div", { className: "absolute inset-0 bg-white z-0 transition-transform duration-700 ease-out group-hover:scale-105" })), /* @__PURE__ */ React9.createElement("div", { className: "flex flex-col text-left pr-4" }, /* @__PURE__ */ React9.createElement("h3", { className: "text-xl tracking-tight text-black mb-2" }, feature.title), /* @__PURE__ */ React9.createElement("p", { className: "text-[13px] leading-relaxed text-neutral-600 max-w-[90%]" }, feature.desc)));
|
|
356
683
|
};
|
|
357
684
|
var FeatureScroll = ({ tagline, headline, features }) => {
|
|
358
|
-
const scrollRef =
|
|
359
|
-
const [canScrollLeft, setCanScrollLeft] =
|
|
360
|
-
const [canScrollRight, setCanScrollRight] =
|
|
685
|
+
const scrollRef = useRef2(null);
|
|
686
|
+
const [canScrollLeft, setCanScrollLeft] = useState4(false);
|
|
687
|
+
const [canScrollRight, setCanScrollRight] = useState4(true);
|
|
361
688
|
const checkScroll = () => {
|
|
362
689
|
if (scrollRef.current) {
|
|
363
690
|
const { scrollLeft, scrollWidth, clientWidth } = scrollRef.current;
|
|
@@ -365,7 +692,7 @@ var FeatureScroll = ({ tagline, headline, features }) => {
|
|
|
365
692
|
setCanScrollRight(scrollLeft < scrollWidth - clientWidth - 2);
|
|
366
693
|
}
|
|
367
694
|
};
|
|
368
|
-
|
|
695
|
+
useEffect2(() => {
|
|
369
696
|
checkScroll();
|
|
370
697
|
window.addEventListener("resize", checkScroll);
|
|
371
698
|
return () => window.removeEventListener("resize", checkScroll);
|
|
@@ -376,7 +703,7 @@ var FeatureScroll = ({ tagline, headline, features }) => {
|
|
|
376
703
|
scrollRef.current.scrollBy({ left: scrollAmount, behavior: "smooth" });
|
|
377
704
|
}
|
|
378
705
|
};
|
|
379
|
-
return /* @__PURE__ */
|
|
706
|
+
return /* @__PURE__ */ React9.createElement("section", { className: "py-24 w-full flex justify-center relative z-10 overflow-hidden" }, /* @__PURE__ */ React9.createElement("div", { className: "max-w-6xl w-full flex flex-col px-4 md:px-8" }, /* @__PURE__ */ React9.createElement("div", { className: "flex flex-col md:flex-row md:items-end justify-between gap-6 mb-12" }, /* @__PURE__ */ React9.createElement("div", { className: "relative z-10 text-left" }, /* @__PURE__ */ React9.createElement("span", { className: "text-[10px] tracking-[0.4em] text-neutral-500 block mb-4" }, tagline), /* @__PURE__ */ React9.createElement("h2", { className: "text-3xl font-serif md:text-5xl tracking-tight text-black leading-[1.05]" }, headline)), /* @__PURE__ */ React9.createElement("div", { className: "hidden md:flex items-center gap-3" }, /* @__PURE__ */ React9.createElement(
|
|
380
707
|
"button",
|
|
381
708
|
{
|
|
382
709
|
onClick: () => scroll("left"),
|
|
@@ -384,8 +711,8 @@ var FeatureScroll = ({ tagline, headline, features }) => {
|
|
|
384
711
|
className: "p-4 border border-neutral-200 rounded-full text-neutral-500 hover:text-black hover:border-black disabled:opacity-30 disabled:hover:border-neutral-200 disabled:hover:text-neutral-500 disabled:cursor-not-allowed transition-all outline-none",
|
|
385
712
|
"aria-label": "Previous feature"
|
|
386
713
|
},
|
|
387
|
-
/* @__PURE__ */
|
|
388
|
-
), /* @__PURE__ */
|
|
714
|
+
/* @__PURE__ */ React9.createElement(HugeiconsIcon5, { icon: ArrowLeft01Icon, size: 20 })
|
|
715
|
+
), /* @__PURE__ */ React9.createElement(
|
|
389
716
|
"button",
|
|
390
717
|
{
|
|
391
718
|
onClick: () => scroll("right"),
|
|
@@ -393,39 +720,39 @@ var FeatureScroll = ({ tagline, headline, features }) => {
|
|
|
393
720
|
className: "p-4 border border-neutral-200 rounded-full text-neutral-500 hover:text-black hover:border-black disabled:opacity-30 disabled:hover:border-neutral-200 disabled:hover:text-neutral-500 disabled:cursor-not-allowed transition-all outline-none",
|
|
394
721
|
"aria-label": "Next feature"
|
|
395
722
|
},
|
|
396
|
-
/* @__PURE__ */
|
|
397
|
-
))), /* @__PURE__ */
|
|
723
|
+
/* @__PURE__ */ React9.createElement(HugeiconsIcon5, { icon: ArrowRight01Icon, size: 20 })
|
|
724
|
+
))), /* @__PURE__ */ React9.createElement(
|
|
398
725
|
"div",
|
|
399
726
|
{
|
|
400
727
|
ref: scrollRef,
|
|
401
728
|
onScroll: checkScroll,
|
|
402
729
|
className: "flex gap-6 overflow-x-auto snap-x snap-mandatory [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] scrollbar-none pb-8 -mx-4 px-4 md:mx-0 md:px-0"
|
|
403
730
|
},
|
|
404
|
-
features.map((feature, idx) => /* @__PURE__ */
|
|
405
|
-
), /* @__PURE__ */
|
|
731
|
+
features.map((feature, idx) => /* @__PURE__ */ React9.createElement(FeatureCard, { key: idx, feature }))
|
|
732
|
+
), /* @__PURE__ */ React9.createElement("div", { className: "flex md:hidden items-center justify-center gap-4 mt-2" }, /* @__PURE__ */ React9.createElement(
|
|
406
733
|
"button",
|
|
407
734
|
{
|
|
408
735
|
onClick: () => scroll("left"),
|
|
409
736
|
disabled: !canScrollLeft,
|
|
410
737
|
className: "p-4 border border-neutral-200 rounded-full text-neutral-500 hover:text-black hover:border-black disabled:opacity-30 transition-all outline-none"
|
|
411
738
|
},
|
|
412
|
-
/* @__PURE__ */
|
|
413
|
-
), /* @__PURE__ */
|
|
739
|
+
/* @__PURE__ */ React9.createElement(HugeiconsIcon5, { icon: ArrowLeft01Icon, size: 20 })
|
|
740
|
+
), /* @__PURE__ */ React9.createElement(
|
|
414
741
|
"button",
|
|
415
742
|
{
|
|
416
743
|
onClick: () => scroll("right"),
|
|
417
744
|
disabled: !canScrollRight,
|
|
418
745
|
className: "p-4 border border-neutral-200 rounded-full text-neutral-500 hover:text-black hover:border-black disabled:opacity-30 transition-all outline-none"
|
|
419
746
|
},
|
|
420
|
-
/* @__PURE__ */
|
|
747
|
+
/* @__PURE__ */ React9.createElement(HugeiconsIcon5, { icon: ArrowRight01Icon, size: 20 })
|
|
421
748
|
))));
|
|
422
749
|
};
|
|
423
750
|
|
|
424
751
|
// src/components/AITranscriptionFeature.tsx
|
|
425
|
-
import
|
|
752
|
+
import React10, { useState as useState5 } from "react";
|
|
426
753
|
import Image4 from "next/image";
|
|
427
|
-
import { HugeiconsIcon as
|
|
428
|
-
import { Loading03Icon as
|
|
754
|
+
import { HugeiconsIcon as HugeiconsIcon6 } from "@hugeicons/react";
|
|
755
|
+
import { Loading03Icon as Loading03Icon3 } from "@hugeicons/core-free-icons";
|
|
429
756
|
var AITranscriptionFeature = ({
|
|
430
757
|
tagline,
|
|
431
758
|
headline,
|
|
@@ -436,8 +763,8 @@ var AITranscriptionFeature = ({
|
|
|
436
763
|
cursorLabel,
|
|
437
764
|
detailTextSuffix
|
|
438
765
|
}) => {
|
|
439
|
-
const [isLoading, setIsLoading] =
|
|
440
|
-
return /* @__PURE__ */
|
|
766
|
+
const [isLoading, setIsLoading] = useState5(!!imagePath);
|
|
767
|
+
return /* @__PURE__ */ React10.createElement("section", { className: "py-24 w-full flex justify-center relative z-10" }, /* @__PURE__ */ React10.createElement("div", { className: "max-w-6xl w-full flex flex-col px-4 md:px-8" }, /* @__PURE__ */ React10.createElement("div", { className: "flex flex-col items-center text-center mb-12 relative z-10 animate-in fade-in slide-in-from-bottom-4 duration-700" }, /* @__PURE__ */ React10.createElement("span", { className: "text-[10px] tracking-[0.4em] text-neutral-500 block mb-4" }, tagline), /* @__PURE__ */ React10.createElement("h2", { className: "text-3xl font-serif md:text-5xl tracking-tight animate-gradient-wipe leading-[1.05] mb-4" }, headline), /* @__PURE__ */ React10.createElement("p", { className: "text-[15px] md:text-[16px] leading-[1.8] text-neutral-600 max-w-xl mx-auto" }, description)), /* @__PURE__ */ React10.createElement("div", { className: "relative w-full max-w-5xl mx-auto aspect-video sm:aspect-21/9 bg-neutral-100 rounded-2xl overflow-hidden mb-12 flex items-center justify-center shadow-[0_0_40px_rgba(0,0,0,0.03)] animate-in fade-in zoom-in-95 duration-700 delay-150 fill-mode-both" }, /* @__PURE__ */ React10.createElement(
|
|
441
768
|
"div",
|
|
442
769
|
{
|
|
443
770
|
className: "absolute inset-0 pointer-events-none opacity-[0.03] z-20 mix-blend-overlay",
|
|
@@ -446,7 +773,7 @@ var AITranscriptionFeature = ({
|
|
|
446
773
|
backgroundRepeat: "repeat"
|
|
447
774
|
}
|
|
448
775
|
}
|
|
449
|
-
), isLoading && imagePath && /* @__PURE__ */
|
|
776
|
+
), isLoading && imagePath && /* @__PURE__ */ React10.createElement("div", { className: "absolute inset-0 flex items-center justify-center z-10 bg-neutral-50/50 backdrop-blur-sm transition-opacity duration-300" }, /* @__PURE__ */ React10.createElement(HugeiconsIcon6, { icon: Loading03Icon3, size: 32, className: "animate-spin text-neutral-400" })), imagePath ? /* @__PURE__ */ React10.createElement(
|
|
450
777
|
Image4,
|
|
451
778
|
{
|
|
452
779
|
src: imagePath,
|
|
@@ -459,32 +786,32 @@ var AITranscriptionFeature = ({
|
|
|
459
786
|
${isLoading ? "scale-105 blur-2xl opacity-0" : "scale-100 blur-0 opacity-100"}
|
|
460
787
|
`
|
|
461
788
|
}
|
|
462
|
-
) : /* @__PURE__ */
|
|
789
|
+
) : /* @__PURE__ */ React10.createElement("div", { className: "absolute inset-0 bg-white z-0" })), /* @__PURE__ */ React10.createElement("div", { className: "max-w-3xl mx-auto text-center animate-in fade-in slide-in-from-bottom-4 duration-700 delay-300 fill-mode-both" }, /* @__PURE__ */ React10.createElement("p", { className: "text-[18px] sm:text-[22px] md:text-[25px] leading-[1.8] text-neutral-800" }, detailTextPrefix, " ", /* @__PURE__ */ React10.createElement("span", { className: "relative font-serif inline-block mx-1 px-2.5 py-0.5 bg-[#20A272]/10 border border-[#20A272] rounded-[3px] text-[#1C3D36] transition-all duration-300 max-w-full wrap-break-word" }, /* @__PURE__ */ React10.createElement("span", { className: "absolute top-[-3.5px] left-[-3.5px] w-2 h-2 bg-white border border-[#20A272] rounded-[1px] z-10" }), /* @__PURE__ */ React10.createElement("span", { className: "absolute top-[-3.5px] right-[-3.5px] w-2 h-2 bg-white border border-[#20A272] rounded-[1px] z-10" }), /* @__PURE__ */ React10.createElement("span", { className: "absolute bottom-[-3.5px] left-[-3.5px] w-2 h-2 bg-white border border-[#20A272] rounded-[1px] z-10" }), /* @__PURE__ */ React10.createElement("span", { className: "absolute bottom-[-3.5px] right-[-3.5px] w-2 h-2 bg-white border border-[#20A272] rounded-[1px] z-10" }), highlightText, /* @__PURE__ */ React10.createElement("span", { className: "absolute -bottom-6 -right-4 sm:-right-6 flex items-center z-20 pointer-events-none select-none filter drop-shadow-[0_2px_4px_rgba(0,0,0,0.15)]" }, /* @__PURE__ */ React10.createElement("svg", { width: "16", height: "20", viewBox: "0 0 16 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", className: "transform -rotate-12" }, /* @__PURE__ */ React10.createElement("path", { d: "M1 1V17.8L5.8 13.1H12.8L1 1Z", fill: "#20A272", stroke: "white", strokeWidth: "1.8", strokeLinejoin: "round" })), /* @__PURE__ */ React10.createElement("span", { className: "ml-1 bg-[#20A272] text-[10px] text-white font-mono px-2 py-0.5 rounded-full border border-white tracking-wide" }, cursorLabel))), " ", detailTextSuffix))));
|
|
463
790
|
};
|
|
464
791
|
|
|
465
792
|
// src/components/PlatformFeatures.tsx
|
|
466
|
-
import
|
|
467
|
-
import { HugeiconsIcon as
|
|
793
|
+
import React11 from "react";
|
|
794
|
+
import { HugeiconsIcon as HugeiconsIcon7 } from "@hugeicons/react";
|
|
468
795
|
var PlatformFeatures = ({
|
|
469
796
|
tagline,
|
|
470
797
|
headline,
|
|
471
798
|
description,
|
|
472
799
|
features
|
|
473
800
|
}) => {
|
|
474
|
-
return /* @__PURE__ */
|
|
801
|
+
return /* @__PURE__ */ React11.createElement("section", { className: "w-full flex justify-center mb-15 relative z-10" }, /* @__PURE__ */ React11.createElement("div", { className: "max-w-6xl w-full flex flex-col px-4 md:px-8" }, /* @__PURE__ */ React11.createElement("div", { className: "flex flex-col items-start mb-16 relative z-10" }, /* @__PURE__ */ React11.createElement("span", { className: "text-[10px] tracking-[0.4em] text-neutral-500 block mb-4" }, tagline), /* @__PURE__ */ React11.createElement("h2", { className: "text-3xl font-serif md:text-5xl tracking-tight text-black leading-[1.05] mb-6" }, headline), /* @__PURE__ */ React11.createElement("p", { className: "text-[15px] md:text-[16px] leading-[1.8] text-neutral-600 max-w-2xl" }, description)), /* @__PURE__ */ React11.createElement("div", { className: "w-full h-px bg-neutral-100 mb-16", "aria-hidden": "true" }), /* @__PURE__ */ React11.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-x-8 gap-y-12" }, features.map((feature, idx) => /* @__PURE__ */ React11.createElement(
|
|
475
802
|
"div",
|
|
476
803
|
{
|
|
477
804
|
key: idx,
|
|
478
805
|
className: "flex flex-col group animate-in fade-in slide-in-from-bottom-4 duration-700 fill-mode-both",
|
|
479
806
|
style: { animationDelay: feature.delay || "0ms" }
|
|
480
807
|
},
|
|
481
|
-
/* @__PURE__ */
|
|
482
|
-
/* @__PURE__ */
|
|
808
|
+
/* @__PURE__ */ React11.createElement("div", { className: "w-12 h-12 rounded-full bg-neutral-100 flex items-center justify-center text-neutral-600 mb-5 transition-colors duration-300" }, /* @__PURE__ */ React11.createElement(HugeiconsIcon7, { icon: feature.icon, size: 24 })),
|
|
809
|
+
/* @__PURE__ */ React11.createElement("div", null, /* @__PURE__ */ React11.createElement("h3", { className: "text-xl tracking-tight text-black mb-2" }, feature.title), /* @__PURE__ */ React11.createElement("p", { className: "text-[13px] leading-relaxed text-neutral-600 pr-4" }, feature.desc))
|
|
483
810
|
)))));
|
|
484
811
|
};
|
|
485
812
|
|
|
486
813
|
// src/components/ManagedDocument.tsx
|
|
487
|
-
import
|
|
814
|
+
import React12 from "react";
|
|
488
815
|
var ManagedDocument = ({
|
|
489
816
|
tagline,
|
|
490
817
|
title,
|
|
@@ -494,7 +821,7 @@ var ManagedDocument = ({
|
|
|
494
821
|
}) => {
|
|
495
822
|
return (
|
|
496
823
|
// Outer layout wrapper (takes up available space, adds padding)
|
|
497
|
-
/* @__PURE__ */
|
|
824
|
+
/* @__PURE__ */ React12.createElement("div", { className: "grow pt-28 px-3 md:px-8 w-full flex justify-center z-10 relative" }, /* @__PURE__ */ React12.createElement("div", { className: "relative bg-white rounded-2xl w-full max-w-7xl mx-auto overflow-hidden" }, /* @__PURE__ */ React12.createElement("div", { className: "relative z-10" }, /* @__PURE__ */ React12.createElement("div", { className: "relative px-5 md:px-12 py-8 md:py-10" }, tagline && /* @__PURE__ */ React12.createElement("span", { className: "text-[10px] tracking-[0.4em] text-neutral-500 text-left block uppercase" }, tagline), /* @__PURE__ */ React12.createElement("h1", { className: "text-4xl font-serif md:text-5xl mt-4 text-black tracking-tight text-left" }, title)), sections.map((section, index) => /* @__PURE__ */ React12.createElement("div", { key: index, className: "relative px-5 md:px-12 py-8 md:py-10" }, section.heading && /* @__PURE__ */ React12.createElement("h2", { className: "text-[11px] tracking-[0.2em] text-black mb-4 text-left uppercase" }, section.heading), section.paragraphs && section.paragraphs.length > 0 && /* @__PURE__ */ React12.createElement("div", { className: "text-[14px] leading-[1.8] text-neutral-700 space-y-4 text-left font-light" }, section.paragraphs.map((text, pIndex) => /* @__PURE__ */ React12.createElement("p", { key: pIndex }, text))), section.quote && /* @__PURE__ */ React12.createElement("div", { className: `bg-neutral-100 rounded-xl p-6 ${section.paragraphs && section.paragraphs.length > 0 ? "mt-6" : ""}` }, /* @__PURE__ */ React12.createElement("p", { className: "italic text-neutral-900 text-[13px] md:text-[14px] leading-relaxed" }, '"', section.quote, '"')))), (contactText || contactEmail) && /* @__PURE__ */ React12.createElement("div", { className: "relative px-5 md:px-12 py-8 md:py-10 pb-12 md:pb-14" }, /* @__PURE__ */ React12.createElement("p", { className: "text-[12px] text-neutral-600 text-left" }, contactText, contactEmail && /* @__PURE__ */ React12.createElement(
|
|
498
825
|
"a",
|
|
499
826
|
{
|
|
500
827
|
href: `mailto:${contactEmail}`,
|
|
@@ -506,18 +833,18 @@ var ManagedDocument = ({
|
|
|
506
833
|
};
|
|
507
834
|
|
|
508
835
|
// src/components/ManagedContactBlock.tsx
|
|
509
|
-
import
|
|
510
|
-
import { HugeiconsIcon as
|
|
836
|
+
import React13, { useState as useState6, useEffect as useEffect3 } from "react";
|
|
837
|
+
import { HugeiconsIcon as HugeiconsIcon8 } from "@hugeicons/react";
|
|
511
838
|
var SecureEmail = ({ user, domain, className }) => {
|
|
512
|
-
const [isMounted, setIsMounted] =
|
|
513
|
-
|
|
839
|
+
const [isMounted, setIsMounted] = useState6(false);
|
|
840
|
+
useEffect3(() => {
|
|
514
841
|
setIsMounted(true);
|
|
515
842
|
}, []);
|
|
516
843
|
if (!isMounted) {
|
|
517
|
-
return /* @__PURE__ */
|
|
844
|
+
return /* @__PURE__ */ React13.createElement("span", { className, style: { opacity: 0 } }, "Loading");
|
|
518
845
|
}
|
|
519
846
|
const email = `${user}@${domain}`;
|
|
520
|
-
return /* @__PURE__ */
|
|
847
|
+
return /* @__PURE__ */ React13.createElement("a", { href: `mailto:${email}`, className }, email);
|
|
521
848
|
};
|
|
522
849
|
var ManagedContactBlock = ({
|
|
523
850
|
tagline,
|
|
@@ -526,7 +853,7 @@ var ManagedContactBlock = ({
|
|
|
526
853
|
emails,
|
|
527
854
|
socials
|
|
528
855
|
}) => {
|
|
529
|
-
return /* @__PURE__ */
|
|
856
|
+
return /* @__PURE__ */ React13.createElement("div", { className: "grow pt-28 pb-20 px-4 md:px-8 w-full flex justify-center z-10 relative" }, /* @__PURE__ */ React13.createElement("div", { className: "relative bg-white rounded-2xl w-full max-w-7xl mx-auto overflow-hidden" }, /* @__PURE__ */ React13.createElement(
|
|
530
857
|
"div",
|
|
531
858
|
{
|
|
532
859
|
className: "absolute inset-0 pointer-events-none opacity-[0.03] z-0",
|
|
@@ -535,21 +862,21 @@ var ManagedContactBlock = ({
|
|
|
535
862
|
backgroundRepeat: "repeat"
|
|
536
863
|
}
|
|
537
864
|
}
|
|
538
|
-
), /* @__PURE__ */
|
|
865
|
+
), /* @__PURE__ */ React13.createElement("div", { className: "relative z-10" }, /* @__PURE__ */ React13.createElement("div", { className: "relative px-8 md:px-12 py-10" }, tagline && /* @__PURE__ */ React13.createElement("span", { className: "text-[10px] tracking-[0.4em] text-neutral-500 text-left block uppercase" }, tagline), /* @__PURE__ */ React13.createElement("h1", { className: "text-4xl font-serif md:text-5xl mt-4 text-black tracking-tight text-left" }, title)), /* @__PURE__ */ React13.createElement("div", { className: "relative px-8 md:px-12 py-8 pb-14" }, /* @__PURE__ */ React13.createElement("div", { className: "flex flex-wrap gap-12 lg:gap-16 w-full" }, company && /* @__PURE__ */ React13.createElement("div", { className: "flex-1 min-w-65 space-y-6" }, /* @__PURE__ */ React13.createElement("h2", { className: "text-[11px] tracking-[0.2em] text-black mb-4 uppercase" }, "Contact Details"), /* @__PURE__ */ React13.createElement("div", { className: "space-y-3 text-[13px] text-neutral-600 leading-[1.8]" }, company.name && /* @__PURE__ */ React13.createElement("p", { className: "text-black" }, company.name), company.lines && company.lines.map((line, idx) => /* @__PURE__ */ React13.createElement("p", { key: idx }, line)), company.phone && /* @__PURE__ */ React13.createElement("p", { className: "pt-2" }, /* @__PURE__ */ React13.createElement(
|
|
539
866
|
"a",
|
|
540
867
|
{
|
|
541
868
|
href: `tel:${company.phone.replace(/\s+/g, "")}`,
|
|
542
869
|
className: "transition-colors hover:text-black"
|
|
543
870
|
},
|
|
544
871
|
company.phone
|
|
545
|
-
)))), emails && emails.length > 0 && /* @__PURE__ */
|
|
872
|
+
)))), emails && emails.length > 0 && /* @__PURE__ */ React13.createElement("div", { className: "flex-1 min-w-65 space-y-6" }, /* @__PURE__ */ React13.createElement("h2", { className: "text-[11px] tracking-[0.2em] text-black mb-4 uppercase" }, "Email Directory"), /* @__PURE__ */ React13.createElement("div", { className: "space-y-6 text-[13px]" }, emails.map((email, idx) => /* @__PURE__ */ React13.createElement("div", { key: idx }, /* @__PURE__ */ React13.createElement("p", { className: "text-[10px] tracking-[0.2em] mb-1.5 text-neutral-500 uppercase" }, email.label), /* @__PURE__ */ React13.createElement(
|
|
546
873
|
SecureEmail,
|
|
547
874
|
{
|
|
548
875
|
user: email.user,
|
|
549
876
|
domain: email.domain,
|
|
550
877
|
className: "text-neutral-600 transition-colors hover:text-black"
|
|
551
878
|
}
|
|
552
|
-
))))), socials && socials.length > 0 && /* @__PURE__ */
|
|
879
|
+
))))), socials && socials.length > 0 && /* @__PURE__ */ React13.createElement("div", { className: "flex-1 min-w-65 space-y-6" }, /* @__PURE__ */ React13.createElement("h2", { className: "text-[11px] tracking-[0.2em] text-black mb-4 uppercase" }, "Find Us Online"), /* @__PURE__ */ React13.createElement("div", { className: "flex flex-col space-y-5 pt-1" }, socials.map((social, idx) => /* @__PURE__ */ React13.createElement(
|
|
553
880
|
"a",
|
|
554
881
|
{
|
|
555
882
|
key: idx,
|
|
@@ -559,29 +886,29 @@ var ManagedContactBlock = ({
|
|
|
559
886
|
className: "flex items-center gap-3 transition-colors group text-neutral-600 hover:text-black",
|
|
560
887
|
"aria-label": social.label
|
|
561
888
|
},
|
|
562
|
-
/* @__PURE__ */
|
|
563
|
-
/* @__PURE__ */
|
|
889
|
+
/* @__PURE__ */ React13.createElement(HugeiconsIcon8, { icon: social.icon, size: 18 }),
|
|
890
|
+
/* @__PURE__ */ React13.createElement("span", { className: "text-[13px]" }, social.label)
|
|
564
891
|
)))))))));
|
|
565
892
|
};
|
|
566
893
|
|
|
567
894
|
// src/components/ManagedPricingBlock.tsx
|
|
568
|
-
import
|
|
895
|
+
import React14 from "react";
|
|
569
896
|
import Link5 from "next/link";
|
|
570
|
-
var CheckIcon = ({ className = "" }) => /* @__PURE__ */
|
|
571
|
-
var CrossIcon = ({ className = "" }) => /* @__PURE__ */
|
|
897
|
+
var CheckIcon = ({ className = "" }) => /* @__PURE__ */ React14.createElement("svg", { viewBox: "0 0 24 24", fill: "none", className: `w-4 h-4 shrink-0 ${className}`, xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ React14.createElement("circle", { cx: "12", cy: "12", r: "10", fill: "black" }), /* @__PURE__ */ React14.createElement("path", { d: "M8 12L11 15L16 9", stroke: "white", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }));
|
|
898
|
+
var CrossIcon = ({ className = "" }) => /* @__PURE__ */ React14.createElement("svg", { viewBox: "0 0 24 24", fill: "none", className: `w-4 h-4 shrink-0 ${className}`, xmlns: "http://www.w3.org/2000/svg" }, /* @__PURE__ */ React14.createElement("circle", { cx: "12", cy: "12", r: "10", fill: "#F5F5F5" }), /* @__PURE__ */ React14.createElement("path", { d: "M15 9L9 15M9 9l6 6", stroke: "#D4D4D4", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }));
|
|
572
899
|
var ManagedPricingBlock = ({
|
|
573
900
|
tagline,
|
|
574
901
|
title,
|
|
575
902
|
plans
|
|
576
903
|
}) => {
|
|
577
|
-
return /* @__PURE__ */
|
|
904
|
+
return /* @__PURE__ */ React14.createElement("div", { className: "grow pt-40 pb-20 px-4 md:px-8 w-full flex justify-center z-10 relative" }, /* @__PURE__ */ React14.createElement("div", { className: "w-full max-w-5xl mx-auto flex flex-col items-center" }, /* @__PURE__ */ React14.createElement("div", { className: "w-full flex flex-col items-center text-center mb-12" }, tagline && /* @__PURE__ */ React14.createElement("span", { className: "text-[9px] tracking-[0.4em] text-black block uppercase" }, tagline), /* @__PURE__ */ React14.createElement("h1", { className: "text-2xl font-serif sm:text-3xl mt-3 text-black tracking-tight" }, title)), /* @__PURE__ */ React14.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-5 w-full max-w-3xl" }, plans.map((plan, planIdx) => /* @__PURE__ */ React14.createElement(
|
|
578
905
|
"div",
|
|
579
906
|
{
|
|
580
907
|
key: planIdx,
|
|
581
908
|
className: `bg-white rounded-3xl p-6 flex flex-col relative overflow-hidden ${plan.isPremium ? "border border-neutral-100" : ""}`
|
|
582
909
|
},
|
|
583
|
-
/* @__PURE__ */
|
|
584
|
-
plan.isPremium ? /* @__PURE__ */
|
|
910
|
+
/* @__PURE__ */ React14.createElement("div", { className: "mb-6" }, /* @__PURE__ */ React14.createElement("span", { className: "text-black text-base block mb-1" }, plan.name), /* @__PURE__ */ React14.createElement("div", { className: "flex items-baseline gap-1" }, /* @__PURE__ */ React14.createElement("span", { className: "text-3xl text-black" }, plan.price), plan.period && /* @__PURE__ */ React14.createElement("span", { className: "text-xs text-neutral-500" }, plan.period)), /* @__PURE__ */ React14.createElement("p", { className: "text-xs text-neutral-500 mt-2" }, plan.description)),
|
|
911
|
+
plan.isPremium ? /* @__PURE__ */ React14.createElement(ThreeDButton, { href: plan.ctaHref, className: "mb-6 w-full" }, plan.ctaText) : /* @__PURE__ */ React14.createElement(
|
|
585
912
|
Link5,
|
|
586
913
|
{
|
|
587
914
|
href: plan.ctaHref,
|
|
@@ -589,20 +916,20 @@ var ManagedPricingBlock = ({
|
|
|
589
916
|
},
|
|
590
917
|
plan.ctaText
|
|
591
918
|
),
|
|
592
|
-
/* @__PURE__ */
|
|
919
|
+
/* @__PURE__ */ React14.createElement("div", { className: "flex flex-col gap-3" }, plan.features.map((feature, featureIdx) => {
|
|
593
920
|
const isAvailable = feature.value !== false;
|
|
594
921
|
const valueText = typeof feature.value === "string" ? feature.value : "";
|
|
595
|
-
return /* @__PURE__ */
|
|
922
|
+
return /* @__PURE__ */ React14.createElement("div", { key: featureIdx, className: "flex items-center gap-2.5" }, isAvailable ? /* @__PURE__ */ React14.createElement(CheckIcon, null) : /* @__PURE__ */ React14.createElement(CrossIcon, null), /* @__PURE__ */ React14.createElement("span", { className: `text-xs ${isAvailable ? "text-neutral-800" : "text-neutral-400"}` }, feature.name, valueText && /* @__PURE__ */ React14.createElement("span", { className: "text-neutral-500 ml-1" }, "(", valueText, ")")));
|
|
596
923
|
}))
|
|
597
924
|
)))));
|
|
598
925
|
};
|
|
599
926
|
|
|
600
927
|
// src/components/ManagedBoardBlock.tsx
|
|
601
|
-
import
|
|
928
|
+
import React15 from "react";
|
|
602
929
|
import Image5 from "next/image";
|
|
603
|
-
import { HugeiconsIcon as
|
|
930
|
+
import { HugeiconsIcon as HugeiconsIcon9 } from "@hugeicons/react";
|
|
604
931
|
import { TwitterIcon, LinkedinIcon } from "@hugeicons/core-free-icons";
|
|
605
|
-
var MemberSocialLink = ({ href, icon, label, name }) => /* @__PURE__ */
|
|
932
|
+
var MemberSocialLink = ({ href, icon, label, name }) => /* @__PURE__ */ React15.createElement(
|
|
606
933
|
"a",
|
|
607
934
|
{
|
|
608
935
|
href,
|
|
@@ -611,7 +938,7 @@ var MemberSocialLink = ({ href, icon, label, name }) => /* @__PURE__ */ React13.
|
|
|
611
938
|
className: "text-neutral-400 hover:text-black transition-colors",
|
|
612
939
|
"aria-label": `${name} on ${label}`
|
|
613
940
|
},
|
|
614
|
-
/* @__PURE__ */
|
|
941
|
+
/* @__PURE__ */ React15.createElement(HugeiconsIcon9, { icon, size: 16 })
|
|
615
942
|
);
|
|
616
943
|
var ManagedBoardBlock = ({
|
|
617
944
|
tagline,
|
|
@@ -620,7 +947,7 @@ var ManagedBoardBlock = ({
|
|
|
620
947
|
contactText,
|
|
621
948
|
contactEmail
|
|
622
949
|
}) => {
|
|
623
|
-
return /* @__PURE__ */
|
|
950
|
+
return /* @__PURE__ */ React15.createElement("div", { className: "grow pt-28 pb-20 px-3 md:px-8 w-full flex justify-center z-10 relative" }, /* @__PURE__ */ React15.createElement("div", { className: "relative w-full mx-auto overflow-hidden max-w-7xl" }, /* @__PURE__ */ React15.createElement(
|
|
624
951
|
"div",
|
|
625
952
|
{
|
|
626
953
|
className: "absolute inset-0 pointer-events-none opacity-[0.03] z-0",
|
|
@@ -629,7 +956,7 @@ var ManagedBoardBlock = ({
|
|
|
629
956
|
backgroundRepeat: "repeat"
|
|
630
957
|
}
|
|
631
958
|
}
|
|
632
|
-
), /* @__PURE__ */
|
|
959
|
+
), /* @__PURE__ */ React15.createElement("div", { className: "relative z-10" }, /* @__PURE__ */ React15.createElement("div", { className: "relative px-5 md:px-12 py-8 md:py-10" }, tagline && /* @__PURE__ */ React15.createElement("span", { className: "text-[10px] tracking-[0.4em] text-neutral-500 text-left block uppercase" }, tagline), /* @__PURE__ */ React15.createElement("h1", { className: "text-4xl font-serif md:text-5xl mt-4 text-black tracking-tight text-left" }, title)), /* @__PURE__ */ React15.createElement("div", { className: "relative px-5 md:px-12 py-4 md:py-8" }, /* @__PURE__ */ React15.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-5 md:gap-8" }, members.map((member, idx) => /* @__PURE__ */ React15.createElement("div", { key: idx, className: "relative p-6 md:p-8 rounded-2xl bg-white flex flex-col transition-all group" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-start space-x-4 md:space-x-5 mb-5 md:mb-6" }, /* @__PURE__ */ React15.createElement("div", { className: "relative w-14 h-14 md:w-16 md:h-16 shrink-0 bg-white overflow-hidden rounded-xl" }, /* @__PURE__ */ React15.createElement(
|
|
633
960
|
Image5,
|
|
634
961
|
{
|
|
635
962
|
src: member.imageSrc,
|
|
@@ -638,7 +965,7 @@ var ManagedBoardBlock = ({
|
|
|
638
965
|
sizes: "(max-width: 768px) 56px, 64px",
|
|
639
966
|
className: "object-cover grayscale opacity-100 transition-opacity"
|
|
640
967
|
}
|
|
641
|
-
)), /* @__PURE__ */
|
|
968
|
+
)), /* @__PURE__ */ React15.createElement("div", { className: "pt-1" }, /* @__PURE__ */ React15.createElement("h3", { className: "text-[14px] md:text-[15px] text-black tracking-tight" }, member.name), /* @__PURE__ */ React15.createElement("p", { className: "text-[10px] tracking-[0.2em] text-neutral-500 mt-1.5 uppercase" }, member.title))), /* @__PURE__ */ React15.createElement("p", { className: "text-[13px] leading-[1.8] text-neutral-600 text-left grow mb-8" }, member.bio), /* @__PURE__ */ React15.createElement("div", { className: "space-y-6 mt-auto" }, /* @__PURE__ */ React15.createElement("div", { className: "w-full *:w-full" }, /* @__PURE__ */ React15.createElement(ThreeDButton, { href: member.website }, "Visit Website")), /* @__PURE__ */ React15.createElement("div", { className: "flex space-x-4 pt-5" }, member.twitterHandle && member.twitterHandle.length > 0 && /* @__PURE__ */ React15.createElement(
|
|
642
969
|
MemberSocialLink,
|
|
643
970
|
{
|
|
644
971
|
href: `https://x.com/${member.twitterHandle}`,
|
|
@@ -646,7 +973,7 @@ var ManagedBoardBlock = ({
|
|
|
646
973
|
label: "X",
|
|
647
974
|
name: member.name
|
|
648
975
|
}
|
|
649
|
-
), member.linkedinHandle && member.linkedinHandle.length > 0 && /* @__PURE__ */
|
|
976
|
+
), member.linkedinHandle && member.linkedinHandle.length > 0 && /* @__PURE__ */ React15.createElement(
|
|
650
977
|
MemberSocialLink,
|
|
651
978
|
{
|
|
652
979
|
href: member.linkedinHandle,
|
|
@@ -654,23 +981,23 @@ var ManagedBoardBlock = ({
|
|
|
654
981
|
label: "LinkedIn",
|
|
655
982
|
name: member.name
|
|
656
983
|
}
|
|
657
|
-
))))))), (contactText || contactEmail) && /* @__PURE__ */
|
|
984
|
+
))))))), (contactText || contactEmail) && /* @__PURE__ */ React15.createElement("div", { className: "relative px-5 md:px-12 py-8 md:py-10 pb-12 md:pb-14" }, /* @__PURE__ */ React15.createElement("p", { className: "text-[12px] text-neutral-600 text-left" }, contactText, contactEmail && /* @__PURE__ */ React15.createElement("a", { href: `mailto:${contactEmail}`, className: "text-black decoration-black decoration-2 underline-offset-4 ml-1 transition-colors" }, contactEmail))))));
|
|
658
985
|
};
|
|
659
986
|
|
|
660
987
|
// src/components/ManagedProjectsBlock.tsx
|
|
661
|
-
import
|
|
988
|
+
import React16 from "react";
|
|
662
989
|
import Link6 from "next/link";
|
|
663
990
|
var GridSection = ({
|
|
664
991
|
children,
|
|
665
992
|
isLast = false,
|
|
666
993
|
className = "py-8 md:py-10"
|
|
667
|
-
}) => /* @__PURE__ */
|
|
994
|
+
}) => /* @__PURE__ */ React16.createElement("div", { className: `relative px-5 md:px-12 ${className} ${!isLast ? "border-b border-neutral-100" : ""}` }, children);
|
|
668
995
|
var ManagedProjectsBlock = ({
|
|
669
996
|
tagline,
|
|
670
997
|
title,
|
|
671
998
|
projects
|
|
672
999
|
}) => {
|
|
673
|
-
return /* @__PURE__ */
|
|
1000
|
+
return /* @__PURE__ */ React16.createElement("div", { className: "grow pt-28 pb-20 px-3 md:px-8 w-full flex justify-center z-10 relative" }, /* @__PURE__ */ React16.createElement("div", { className: "relative bg-white rounded-2xl w-full max-w-5xl mx-auto overflow-hidden" }, /* @__PURE__ */ React16.createElement(
|
|
674
1001
|
"div",
|
|
675
1002
|
{
|
|
676
1003
|
className: "absolute inset-0 pointer-events-none opacity-[0.03] z-0",
|
|
@@ -679,15 +1006,15 @@ var ManagedProjectsBlock = ({
|
|
|
679
1006
|
backgroundRepeat: "repeat"
|
|
680
1007
|
}
|
|
681
1008
|
}
|
|
682
|
-
), /* @__PURE__ */
|
|
1009
|
+
), /* @__PURE__ */ React16.createElement("div", { className: "relative z-10" }, /* @__PURE__ */ React16.createElement(GridSection, null, tagline && /* @__PURE__ */ React16.createElement("span", { className: "text-[10px] tracking-[0.4em] text-neutral-500 text-left block uppercase" }, tagline), /* @__PURE__ */ React16.createElement("h1", { className: "text-4xl font-serif md:text-5xl mt-4 text-black tracking-tight text-left" }, title)), projects.map((project, index) => {
|
|
683
1010
|
const isLast = index === projects.length - 1;
|
|
684
|
-
const projectContent = /* @__PURE__ */
|
|
685
|
-
return /* @__PURE__ */
|
|
1011
|
+
const projectContent = /* @__PURE__ */ React16.createElement("div", { className: "group block w-full" }, /* @__PURE__ */ React16.createElement("div", { className: "flex flex-col md:flex-row md:items-center justify-between gap-3 md:gap-4 mb-4 md:mb-5" }, /* @__PURE__ */ React16.createElement("div", { className: "flex items-center gap-3 md:gap-4" }, /* @__PURE__ */ React16.createElement("h2", { className: "text-[16px] text-black transition-all flex items-center gap-2" }, project.title, /* @__PURE__ */ React16.createElement("span", { className: "text-[12px] opacity-0 -translate-x-2 group-hover:opacity-100 group-hover:translate-x-0 transition-all duration-300" }, project.isExternal ? "\u2197" : "\u2192")), /* @__PURE__ */ React16.createElement("span", { className: `text-[9px] px-2.5 py-1 rounded-full tracking-[0.15em] uppercase transition-colors ${project.status.toLowerCase() === "production" ? "bg-black text-white" : "bg-neutral-100 text-neutral-500 group-hover:bg-neutral-200 group-hover:text-black"}` }, project.status)), /* @__PURE__ */ React16.createElement("span", { className: "text-[10px] tracking-[0.2em] text-neutral-500 shrink-0 uppercase" }, project.date)), /* @__PURE__ */ React16.createElement("p", { className: "text-[13px] leading-[1.8] text-neutral-600 max-w-4xl text-left transition-colors group-hover:text-black" }, project.description));
|
|
1012
|
+
return /* @__PURE__ */ React16.createElement(GridSection, { key: project.id || index, isLast, className: isLast ? "py-8 md:py-10 pb-12 md:pb-14" : "py-8 md:py-10" }, project.isExternal ? /* @__PURE__ */ React16.createElement("a", { href: project.link, target: "_blank", rel: "noopener noreferrer", className: "block outline-none" }, projectContent) : /* @__PURE__ */ React16.createElement(Link6, { href: project.link, className: "block outline-none" }, projectContent));
|
|
686
1013
|
}))));
|
|
687
1014
|
};
|
|
688
1015
|
|
|
689
1016
|
// src/components/ManagedNotFoundBlock.tsx
|
|
690
|
-
import
|
|
1017
|
+
import React17 from "react";
|
|
691
1018
|
import Link7 from "next/link";
|
|
692
1019
|
var ManagedNotFoundBlock = ({
|
|
693
1020
|
title = "404 - Page Not Found",
|
|
@@ -695,15 +1022,15 @@ var ManagedNotFoundBlock = ({
|
|
|
695
1022
|
backLinkText = "\u2190 Go back to Homepage",
|
|
696
1023
|
backLinkHref = "/"
|
|
697
1024
|
}) => {
|
|
698
|
-
return /* @__PURE__ */
|
|
1025
|
+
return /* @__PURE__ */ React17.createElement("main", { className: "min-h-screen flex items-center justify-center relative z-20 bg-transparent" }, /* @__PURE__ */ React17.createElement("div", { className: "p-6 w-full max-w-md mx-auto text-center" }, /* @__PURE__ */ React17.createElement("div", { className: "mb-8 flex justify-center" }, /* @__PURE__ */ React17.createElement(
|
|
699
1026
|
"svg",
|
|
700
1027
|
{
|
|
701
1028
|
xmlns: "http://www.w3.org/2000/svg",
|
|
702
1029
|
viewBox: "0 0 24 24",
|
|
703
1030
|
className: "w-12 h-12 fill-neutral-200"
|
|
704
1031
|
},
|
|
705
|
-
/* @__PURE__ */
|
|
706
|
-
)), /* @__PURE__ */
|
|
1032
|
+
/* @__PURE__ */ React17.createElement("path", { fillRule: "evenodd", d: "M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12zM12 8.25a.75.75 0 01.75.75v3.75a.75.75 0 01-1.5 0V9a.75.75 0 01.75-.75zm0 8.25a.75.75 0 100-1.5.75.75 0 000 1.5z", clipRule: "evenodd" })
|
|
1033
|
+
)), /* @__PURE__ */ React17.createElement("h1", { className: "text-xl font-serif md:text-3xl text-black tracking-tight mb-4" }, title), /* @__PURE__ */ React17.createElement("p", { className: "text-[13px] leading-[1.8] text-neutral-600 mb-12" }, description), /* @__PURE__ */ React17.createElement(
|
|
707
1034
|
Link7,
|
|
708
1035
|
{
|
|
709
1036
|
href: backLinkHref,
|
|
@@ -714,9 +1041,9 @@ var ManagedNotFoundBlock = ({
|
|
|
714
1041
|
};
|
|
715
1042
|
|
|
716
1043
|
// src/components/PageSpinner.tsx
|
|
717
|
-
import
|
|
718
|
-
import { HugeiconsIcon as
|
|
719
|
-
import { Loading03Icon as
|
|
1044
|
+
import React18 from "react";
|
|
1045
|
+
import { HugeiconsIcon as HugeiconsIcon10 } from "@hugeicons/react";
|
|
1046
|
+
import { Loading03Icon as Loading03Icon4 } from "@hugeicons/core-free-icons";
|
|
720
1047
|
var PageSpinner = ({
|
|
721
1048
|
className = "",
|
|
722
1049
|
iconClassName = "text-black",
|
|
@@ -724,10 +1051,10 @@ var PageSpinner = ({
|
|
|
724
1051
|
}) => {
|
|
725
1052
|
return (
|
|
726
1053
|
// z-[100] ensures it sits above absolute headers and modals
|
|
727
|
-
/* @__PURE__ */
|
|
728
|
-
|
|
1054
|
+
/* @__PURE__ */ React18.createElement("div", { className: `fixed inset-0 z-100 flex flex-col items-center justify-center w-full h-full pointer-events-none ${className}` }, /* @__PURE__ */ React18.createElement(
|
|
1055
|
+
HugeiconsIcon10,
|
|
729
1056
|
{
|
|
730
|
-
icon:
|
|
1057
|
+
icon: Loading03Icon4,
|
|
731
1058
|
size,
|
|
732
1059
|
className: `animate-spin mb-4 ${iconClassName}`
|
|
733
1060
|
}
|
|
@@ -736,14 +1063,13 @@ var PageSpinner = ({
|
|
|
736
1063
|
};
|
|
737
1064
|
|
|
738
1065
|
// src/components/ManagedToaster.tsx
|
|
739
|
-
import
|
|
1066
|
+
import React19 from "react";
|
|
740
1067
|
import { Toaster } from "react-hot-toast";
|
|
741
|
-
var ManagedToaster = (
|
|
742
|
-
return /* @__PURE__ */
|
|
1068
|
+
var ManagedToaster = () => {
|
|
1069
|
+
return /* @__PURE__ */ React19.createElement(
|
|
743
1070
|
Toaster,
|
|
744
1071
|
{
|
|
745
1072
|
position: "top-right",
|
|
746
|
-
...props,
|
|
747
1073
|
toastOptions: {
|
|
748
1074
|
style: {
|
|
749
1075
|
background: "#171717",
|
|
@@ -765,16 +1091,14 @@ var ManagedToaster = (props) => {
|
|
|
765
1091
|
primary: "#fafafa",
|
|
766
1092
|
secondary: "#171717"
|
|
767
1093
|
}
|
|
768
|
-
}
|
|
769
|
-
...props.toastOptions
|
|
770
|
-
// Allows overriding specific toast styles if needed
|
|
1094
|
+
}
|
|
771
1095
|
}
|
|
772
1096
|
}
|
|
773
1097
|
);
|
|
774
1098
|
};
|
|
775
1099
|
|
|
776
1100
|
// src/components/ManagedNewsletterSplitBlock.tsx
|
|
777
|
-
import
|
|
1101
|
+
import React20 from "react";
|
|
778
1102
|
import Image6 from "next/image";
|
|
779
1103
|
var ManagedNewsletterSplitBlock = ({
|
|
780
1104
|
tagline,
|
|
@@ -788,7 +1112,7 @@ var ManagedNewsletterSplitBlock = ({
|
|
|
788
1112
|
ctaHref = "/contact-us",
|
|
789
1113
|
children
|
|
790
1114
|
}) => {
|
|
791
|
-
return /* @__PURE__ */
|
|
1115
|
+
return /* @__PURE__ */ React20.createElement("div", { className: "grow flex flex-col md:flex-row relative w-full pt-32 md:pt-0" }, /* @__PURE__ */ React20.createElement("div", { className: "hidden md:block md:w-1/2 relative min-h-screen overflow-hidden" }, /* @__PURE__ */ React20.createElement(
|
|
792
1116
|
Image6,
|
|
793
1117
|
{
|
|
794
1118
|
src: imageSrc,
|
|
@@ -798,7 +1122,7 @@ var ManagedNewsletterSplitBlock = ({
|
|
|
798
1122
|
className: "object-cover object-top grayscale opacity-60",
|
|
799
1123
|
quality: 100
|
|
800
1124
|
}
|
|
801
|
-
), /* @__PURE__ */
|
|
1125
|
+
), /* @__PURE__ */ React20.createElement(
|
|
802
1126
|
"div",
|
|
803
1127
|
{
|
|
804
1128
|
className: "absolute inset-0 z-10 pointer-events-none",
|
|
@@ -806,7 +1130,7 @@ var ManagedNewsletterSplitBlock = ({
|
|
|
806
1130
|
background: "linear-gradient(to right, rgba(255,255,255,0) 30%, #ffffff 100%)"
|
|
807
1131
|
}
|
|
808
1132
|
}
|
|
809
|
-
), /* @__PURE__ */
|
|
1133
|
+
), /* @__PURE__ */ React20.createElement(
|
|
810
1134
|
"div",
|
|
811
1135
|
{
|
|
812
1136
|
className: "absolute inset-x-0 bottom-0 h-40 z-10 pointer-events-none",
|
|
@@ -814,7 +1138,7 @@ var ManagedNewsletterSplitBlock = ({
|
|
|
814
1138
|
background: "linear-gradient(to bottom, rgba(255,255,255,0) 0%, #ffffff 100%)"
|
|
815
1139
|
}
|
|
816
1140
|
}
|
|
817
|
-
)), /* @__PURE__ */
|
|
1141
|
+
)), /* @__PURE__ */ React20.createElement("div", { className: "w-full md:w-1/2 flex mt-22 flex-col items-center justify-center p-4 md:p-12 relative z-20" }, /* @__PURE__ */ React20.createElement("div", { className: "relative w-full max-w-lg p-8 md:p-12 text-center md:text-left transition-all duration-700 ease-out" }, /* @__PURE__ */ React20.createElement(
|
|
818
1142
|
"div",
|
|
819
1143
|
{
|
|
820
1144
|
className: "absolute inset-0 pointer-events-none opacity-[0.03] z-0",
|
|
@@ -823,7 +1147,7 @@ var ManagedNewsletterSplitBlock = ({
|
|
|
823
1147
|
backgroundRepeat: "repeat"
|
|
824
1148
|
}
|
|
825
1149
|
}
|
|
826
|
-
), /* @__PURE__ */
|
|
1150
|
+
), /* @__PURE__ */ React20.createElement("div", { className: "relative z-10" }, /* @__PURE__ */ React20.createElement("div", { className: "mb-10 border-b border-neutral-200 pb-8 text-center md:text-left" }, tagline && /* @__PURE__ */ React20.createElement("span", { className: "text-[10px] tracking-[0.4em] text-neutral-500 uppercase" }, tagline), /* @__PURE__ */ React20.createElement("h1", { className: "text-4xl font-serif md:text-5xl mt-4 text-black tracking-tight mb-4" }, title), subtitle && /* @__PURE__ */ React20.createElement("p", { className: "text-[11px] tracking-[0.2em] text-neutral-500 uppercase" }, subtitle)), /* @__PURE__ */ React20.createElement("p", { className: "text-[13px] leading-[1.8] text-neutral-600 mb-10 text-center md:text-left" }, description), children && /* @__PURE__ */ React20.createElement("div", { className: "mb-8 text-left" }, children), /* @__PURE__ */ React20.createElement("div", { className: "text-center md:text-left mt-10 space-y-6" }, dividerText && /* @__PURE__ */ React20.createElement("div", { className: "flex items-center" }, /* @__PURE__ */ React20.createElement("div", { className: "grow h-px bg-neutral-200" }), /* @__PURE__ */ React20.createElement("span", { className: "shrink mx-4 text-[10px] tracking-[0.2em] text-neutral-400 uppercase" }, dividerText), /* @__PURE__ */ React20.createElement("div", { className: "grow h-px bg-neutral-200" })), ctaText && ctaHref && /* @__PURE__ */ React20.createElement("div", { className: "w-full *:w-full" }, /* @__PURE__ */ React20.createElement(
|
|
827
1151
|
ThreeDButton,
|
|
828
1152
|
{
|
|
829
1153
|
href: ctaHref,
|
|
@@ -834,7 +1158,7 @@ var ManagedNewsletterSplitBlock = ({
|
|
|
834
1158
|
};
|
|
835
1159
|
|
|
836
1160
|
// src/components/ReusableInputs.tsx
|
|
837
|
-
import
|
|
1161
|
+
import React21 from "react";
|
|
838
1162
|
var TextInput = ({
|
|
839
1163
|
label,
|
|
840
1164
|
value,
|
|
@@ -844,7 +1168,7 @@ var TextInput = ({
|
|
|
844
1168
|
disabled,
|
|
845
1169
|
readOnly,
|
|
846
1170
|
onClick
|
|
847
|
-
}) => /* @__PURE__ */
|
|
1171
|
+
}) => /* @__PURE__ */ React21.createElement("div", { className: "space-y-2 flex-1 w-full", onClick }, /* @__PURE__ */ React21.createElement("label", { className: "text-[10px] text-neutral-400 tracking-[0.2em] block uppercase" }, label), /* @__PURE__ */ React21.createElement(
|
|
848
1172
|
"input",
|
|
849
1173
|
{
|
|
850
1174
|
type: "text",
|
|
@@ -865,7 +1189,7 @@ var NumberInput = ({
|
|
|
865
1189
|
placeholder,
|
|
866
1190
|
maxLength,
|
|
867
1191
|
disabled
|
|
868
|
-
}) => /* @__PURE__ */
|
|
1192
|
+
}) => /* @__PURE__ */ React21.createElement("div", { className: "space-y-2 flex-1 w-full" }, /* @__PURE__ */ React21.createElement("label", { className: "text-[10px] text-neutral-400 tracking-[0.2em] block uppercase" }, label), /* @__PURE__ */ React21.createElement(
|
|
869
1193
|
"input",
|
|
870
1194
|
{
|
|
871
1195
|
type: "text",
|
|
@@ -883,14 +1207,14 @@ var NumberInput = ({
|
|
|
883
1207
|
));
|
|
884
1208
|
|
|
885
1209
|
// src/components/PortfolioHero.tsx
|
|
886
|
-
import
|
|
1210
|
+
import React22, { useEffect as useEffect4, useRef as useRef3 } from "react";
|
|
887
1211
|
import Link8 from "next/link";
|
|
888
1212
|
import Image7 from "next/image";
|
|
889
|
-
import { HugeiconsIcon as
|
|
1213
|
+
import { HugeiconsIcon as HugeiconsIcon11 } from "@hugeicons/react";
|
|
890
1214
|
import { ArrowRight01Icon as ArrowRight01Icon2 } from "@hugeicons/core-free-icons";
|
|
891
1215
|
var useScrollAnimation = () => {
|
|
892
|
-
const elementRef =
|
|
893
|
-
|
|
1216
|
+
const elementRef = useRef3(null);
|
|
1217
|
+
useEffect4(() => {
|
|
894
1218
|
const el = elementRef.current;
|
|
895
1219
|
if (!el) return;
|
|
896
1220
|
const observer = new IntersectionObserver(
|
|
@@ -926,13 +1250,13 @@ var PortfolioHero = ({
|
|
|
926
1250
|
secondaryCtaHref
|
|
927
1251
|
}) => {
|
|
928
1252
|
const heroContentRef = useScrollAnimation();
|
|
929
|
-
return /* @__PURE__ */
|
|
1253
|
+
return /* @__PURE__ */ React22.createElement("section", { className: "pt-44 md:pt-52 pb-16 px-6 md:px-12 flex flex-col relative overflow-hidden z-10 w-full" }, /* @__PURE__ */ React22.createElement(
|
|
930
1254
|
"div",
|
|
931
1255
|
{
|
|
932
1256
|
ref: heroContentRef,
|
|
933
1257
|
className: "w-full opacity-0 translate-y-5 transition-all duration-1000 ease-out relative z-10"
|
|
934
1258
|
},
|
|
935
|
-
/* @__PURE__ */
|
|
1259
|
+
/* @__PURE__ */ React22.createElement("div", { className: "flex flex-col sm:flex-row sm:items-center gap-5 sm:gap-8 mb-10" }, /* @__PURE__ */ React22.createElement("div", { className: "relative w-20 h-20 sm:w-32 sm:h-32 rounded-full overflow-hidden border border-neutral-200 shrink-0 shadow-sm" }, /* @__PURE__ */ React22.createElement(
|
|
936
1260
|
Image7,
|
|
937
1261
|
{
|
|
938
1262
|
src: imageSrc,
|
|
@@ -943,7 +1267,7 @@ var PortfolioHero = ({
|
|
|
943
1267
|
sizes: "(max-width: 640px) 80px, 128px",
|
|
944
1268
|
quality: 100
|
|
945
1269
|
}
|
|
946
|
-
)), /* @__PURE__ */
|
|
1270
|
+
)), /* @__PURE__ */ React22.createElement("div", { className: "flex flex-col text-left" }, /* @__PURE__ */ React22.createElement("h1", { className: "text-3xl font-serif sm:text-5xl animate-gradient-wipe lg:text-6xl tracking-tight text-black leading-none mb-3" }, name), socialLabel && /* @__PURE__ */ React22.createElement("span", { className: "text-[10px] tracking-[0.2em] text-neutral-500 uppercase" }, socialLabel), socialLinkText && socialLinkHref && /* @__PURE__ */ React22.createElement(
|
|
947
1271
|
"a",
|
|
948
1272
|
{
|
|
949
1273
|
href: socialLinkHref,
|
|
@@ -953,28 +1277,28 @@ var PortfolioHero = ({
|
|
|
953
1277
|
},
|
|
954
1278
|
socialLinkText
|
|
955
1279
|
))),
|
|
956
|
-
/* @__PURE__ */
|
|
957
|
-
/* @__PURE__ */
|
|
1280
|
+
/* @__PURE__ */ React22.createElement("p", { className: "text-[13px] md:text-[16px] leading-[1.8] max-w-4xl mb-12 text-neutral-600" }, bio),
|
|
1281
|
+
/* @__PURE__ */ React22.createElement("div", { className: "flex flex-col sm:flex-row gap-4 w-full sm:w-auto" }, primaryCtaText && primaryCtaHref && /* @__PURE__ */ React22.createElement("div", { className: "w-full sm:w-auto *:w-full" }, /* @__PURE__ */ React22.createElement(
|
|
958
1282
|
ThreeDButton,
|
|
959
1283
|
{
|
|
960
1284
|
href: primaryCtaHref,
|
|
961
1285
|
className: "py-3 uppercase tracking-widest text-[11px]"
|
|
962
1286
|
},
|
|
963
1287
|
primaryCtaText
|
|
964
|
-
)), secondaryCtaText && secondaryCtaHref && /* @__PURE__ */
|
|
1288
|
+
)), secondaryCtaText && secondaryCtaHref && /* @__PURE__ */ React22.createElement(
|
|
965
1289
|
Link8,
|
|
966
1290
|
{
|
|
967
1291
|
href: secondaryCtaHref,
|
|
968
1292
|
className: "w-full sm:w-auto inline-flex items-center justify-center gap-3 text-[11px] tracking-[0.2em] uppercase rounded-full px-8 py-3.5 bg-neutral-200 transition-colors text-black hover:bg-neutral-200 outline-none"
|
|
969
1293
|
},
|
|
970
1294
|
secondaryCtaText,
|
|
971
|
-
/* @__PURE__ */
|
|
1295
|
+
/* @__PURE__ */ React22.createElement(HugeiconsIcon11, { icon: ArrowRight01Icon2, size: 16 })
|
|
972
1296
|
))
|
|
973
1297
|
));
|
|
974
1298
|
};
|
|
975
1299
|
|
|
976
1300
|
// src/components/ProductHero.tsx
|
|
977
|
-
import
|
|
1301
|
+
import React23, { useState as useState7, useEffect as useEffect5, useCallback } from "react";
|
|
978
1302
|
import Link9 from "next/link";
|
|
979
1303
|
import Image8 from "next/image";
|
|
980
1304
|
var ProductHero = ({
|
|
@@ -988,14 +1312,14 @@ var ProductHero = ({
|
|
|
988
1312
|
secondaryCtaHref,
|
|
989
1313
|
images
|
|
990
1314
|
}) => {
|
|
991
|
-
const [currentIndex, setCurrentIndex] =
|
|
1315
|
+
const [currentIndex, setCurrentIndex] = useState7(0);
|
|
992
1316
|
const nextSlide = useCallback(() => {
|
|
993
1317
|
setCurrentIndex((prev) => (prev + 1) % images.length);
|
|
994
1318
|
}, [images.length]);
|
|
995
1319
|
const prevSlide = useCallback(() => {
|
|
996
1320
|
setCurrentIndex((prev) => (prev - 1 + images.length) % images.length);
|
|
997
1321
|
}, [images.length]);
|
|
998
|
-
|
|
1322
|
+
useEffect5(() => {
|
|
999
1323
|
const timer = setInterval(() => {
|
|
1000
1324
|
nextSlide();
|
|
1001
1325
|
}, 5e3);
|
|
@@ -1014,12 +1338,12 @@ var ProductHero = ({
|
|
|
1014
1338
|
}
|
|
1015
1339
|
return "opacity-0 z-0 scale-75 pointer-events-none";
|
|
1016
1340
|
};
|
|
1017
|
-
return /* @__PURE__ */
|
|
1341
|
+
return /* @__PURE__ */ React23.createElement("section", { className: "relative pt-32 sm:pt-40 pb-0 flex flex-col items-center overflow-hidden w-full bg-[#f5f5f5]" }, /* @__PURE__ */ React23.createElement(
|
|
1018
1342
|
"div",
|
|
1019
1343
|
{
|
|
1020
1344
|
className: "absolute inset-0 w-full h-full pointer-events-none z-0 bg-linear-to-b from-white via-white to-[#f5f5f5]"
|
|
1021
1345
|
}
|
|
1022
|
-
), /* @__PURE__ */
|
|
1346
|
+
), /* @__PURE__ */ React23.createElement(
|
|
1023
1347
|
"div",
|
|
1024
1348
|
{
|
|
1025
1349
|
className: "absolute inset-0 w-full h-full pointer-events-none z-0 opacity-[0.3] mix-blend-overlay",
|
|
@@ -1027,14 +1351,14 @@ var ProductHero = ({
|
|
|
1027
1351
|
backgroundImage: `url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E")`
|
|
1028
1352
|
}
|
|
1029
1353
|
}
|
|
1030
|
-
), /* @__PURE__ */
|
|
1354
|
+
), /* @__PURE__ */ React23.createElement("div", { className: "relative max-w-5xl mx-auto px-4 sm:px-6 w-full flex flex-col items-center text-center z-10" }, badgeText && /* @__PURE__ */ React23.createElement("div", { className: "inline-flex items-center gap-1.5 mb-6 px-4 py-1.5 rounded-full bg-neutral-100 border border-neutral-200 backdrop-blur-md shadow-xs" }, /* @__PURE__ */ React23.createElement("span", { className: "text-[10px] tracking-[0.4em] text-neutral-600 uppercase font-medium" }, badgeText)), /* @__PURE__ */ React23.createElement("h1", { className: "text-[40px] md:text-5xl lg:text-7xl text-black tracking-tight leading-[1.05] max-w-4xl mb-4" }, titlePrefix, " ", /* @__PURE__ */ React23.createElement("span", { className: "bg-linear-to-r from-[#043324] to-[#21a473] bg-clip-text text-transparent font-serif italic pr-2" }, highlightText)), subtitle && /* @__PURE__ */ React23.createElement("p", { className: "text-[13px] md:text-[16px] text-neutral-600 max-w-xl mx-auto mb-10 font-light leading-relaxed" }, subtitle), /* @__PURE__ */ React23.createElement("div", { className: "flex flex-col sm:flex-row gap-4 justify-center items-center w-full px-2 sm:px-0 mx-auto mb-12 relative z-30" }, ctaText && ctaHref && /* @__PURE__ */ React23.createElement("div", { className: "w-full sm:w-60 flex justify-center *:w-full" }, /* @__PURE__ */ React23.createElement(ThreeDButton, { href: ctaHref }, ctaText)), secondaryCtaText && secondaryCtaHref && /* @__PURE__ */ React23.createElement(
|
|
1031
1355
|
Link9,
|
|
1032
1356
|
{
|
|
1033
1357
|
href: secondaryCtaHref,
|
|
1034
1358
|
className: "w-full sm:w-60 inline-flex items-center justify-center text-[12px] tracking-widest rounded-full px-8 py-2.5 bg-white text-black border border-neutral-200 transition-colors hover:bg-neutral-50 outline-none shadow-sm"
|
|
1035
1359
|
},
|
|
1036
1360
|
secondaryCtaText
|
|
1037
|
-
)), /* @__PURE__ */
|
|
1361
|
+
)), /* @__PURE__ */ React23.createElement("div", { className: "relative w-full max-w-4xl mx-auto px-2 sm:px-6 mt-8 z-20" }, /* @__PURE__ */ React23.createElement("div", { className: "relative w-full aspect-4/3 md:aspect-video flex items-center justify-center" }, /* @__PURE__ */ React23.createElement("button", { onClick: prevSlide, className: "absolute left-0 sm:-left-12 z-40 p-2 text-neutral-400 hover:text-black transition-colors outline-none", "aria-label": "Previous image" }, /* @__PURE__ */ React23.createElement("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React23.createElement("path", { d: "M15 18l-6-6 6-6" }))), /* @__PURE__ */ React23.createElement("button", { onClick: nextSlide, className: "absolute right-0 sm:-right-12 z-40 p-2 text-neutral-400 hover:text-black transition-colors outline-none", "aria-label": "Next image" }, /* @__PURE__ */ React23.createElement("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React23.createElement("path", { d: "M9 18l6-6-6-6" }))), images.map((src, idx) => /* @__PURE__ */ React23.createElement(
|
|
1038
1362
|
"div",
|
|
1039
1363
|
{
|
|
1040
1364
|
key: idx,
|
|
@@ -1043,7 +1367,7 @@ var ProductHero = ({
|
|
|
1043
1367
|
},
|
|
1044
1368
|
className: `absolute inset-0 transition-all duration-700 ease-out transform ${getCarouselClasses(idx)}`
|
|
1045
1369
|
},
|
|
1046
|
-
/* @__PURE__ */
|
|
1370
|
+
/* @__PURE__ */ React23.createElement("div", { className: "relative w-full h-full rounded-2xl overflow-hidden shadow-xl" }, /* @__PURE__ */ React23.createElement(
|
|
1047
1371
|
Image8,
|
|
1048
1372
|
{
|
|
1049
1373
|
src,
|
|
@@ -1054,14 +1378,14 @@ var ProductHero = ({
|
|
|
1054
1378
|
priority: idx === 0
|
|
1055
1379
|
}
|
|
1056
1380
|
))
|
|
1057
|
-
)), /* @__PURE__ */
|
|
1381
|
+
)), /* @__PURE__ */ React23.createElement("div", { className: "absolute inset-x-0 bottom-0 h-1/3 sm:h-1/2 bg-linear-to-t from-[#f5f5f5] to-transparent z-40 pointer-events-none" })))));
|
|
1058
1382
|
};
|
|
1059
1383
|
|
|
1060
1384
|
// src/components/GifFeatureCard.tsx
|
|
1061
|
-
import
|
|
1385
|
+
import React24, { useState as useState8 } from "react";
|
|
1062
1386
|
import Image9 from "next/image";
|
|
1063
|
-
import { HugeiconsIcon as
|
|
1064
|
-
import { Loading03Icon as
|
|
1387
|
+
import { HugeiconsIcon as HugeiconsIcon12 } from "@hugeicons/react";
|
|
1388
|
+
import { Loading03Icon as Loading03Icon5 } from "@hugeicons/core-free-icons";
|
|
1065
1389
|
var GifFeatureCard = ({
|
|
1066
1390
|
gifSrc,
|
|
1067
1391
|
title,
|
|
@@ -1069,20 +1393,20 @@ var GifFeatureCard = ({
|
|
|
1069
1393
|
alt = "Feature animation",
|
|
1070
1394
|
className = "aspect-video"
|
|
1071
1395
|
}) => {
|
|
1072
|
-
const [isLoading, setIsLoading] =
|
|
1073
|
-
return /* @__PURE__ */
|
|
1074
|
-
|
|
1396
|
+
const [isLoading, setIsLoading] = useState8(true);
|
|
1397
|
+
return /* @__PURE__ */ React24.createElement("div", { className: `relative w-full bg-black overflow-hidden shadow-2xl ${className}` }, isLoading && /* @__PURE__ */ React24.createElement("div", { className: "absolute inset-0 flex items-center justify-center z-20 bg-black" }, /* @__PURE__ */ React24.createElement(
|
|
1398
|
+
HugeiconsIcon12,
|
|
1075
1399
|
{
|
|
1076
|
-
icon:
|
|
1400
|
+
icon: Loading03Icon5,
|
|
1077
1401
|
size: 32,
|
|
1078
1402
|
className: "animate-spin text-white"
|
|
1079
1403
|
}
|
|
1080
|
-
)), /* @__PURE__ */
|
|
1404
|
+
)), /* @__PURE__ */ React24.createElement(
|
|
1081
1405
|
"div",
|
|
1082
1406
|
{
|
|
1083
1407
|
className: `absolute inset-0 z-0 transition-all duration-1000 ease-out ${isLoading ? "scale-105 blur-2xl opacity-0" : "scale-100 blur-0 opacity-100"}`
|
|
1084
1408
|
},
|
|
1085
|
-
/* @__PURE__ */
|
|
1409
|
+
/* @__PURE__ */ React24.createElement(
|
|
1086
1410
|
Image9,
|
|
1087
1411
|
{
|
|
1088
1412
|
src: gifSrc,
|
|
@@ -1093,12 +1417,772 @@ var GifFeatureCard = ({
|
|
|
1093
1417
|
className: "object-cover object-center pointer-events-none"
|
|
1094
1418
|
}
|
|
1095
1419
|
)
|
|
1096
|
-
), /* @__PURE__ */
|
|
1420
|
+
), /* @__PURE__ */ React24.createElement(
|
|
1097
1421
|
"div",
|
|
1098
1422
|
{
|
|
1099
1423
|
className: "absolute inset-x-0 bottom-0 h-1/2 sm:h-2/3 bg-linear-to-t from-black/95 via-black/40 to-transparent z-10 pointer-events-none transition-opacity duration-700"
|
|
1100
1424
|
}
|
|
1101
|
-
), /* @__PURE__ */
|
|
1425
|
+
), /* @__PURE__ */ React24.createElement("div", { className: "absolute inset-x-0 bottom-0 p-6 sm:p-8 z-30 flex flex-col justify-end text-left pointer-events-none" }, title && /* @__PURE__ */ React24.createElement("h3", { className: "text-xl sm:text-2xl md:text-3xl font-medium text-white tracking-tight mb-2 sm:mb-3 drop-shadow-md" }, title), subtitle && /* @__PURE__ */ React24.createElement("p", { className: "text-[13px] sm:text-[15px] leading-relaxed text-neutral-300 max-w-2xl drop-shadow-sm" }, subtitle)));
|
|
1426
|
+
};
|
|
1427
|
+
|
|
1428
|
+
// src/components/UniversalSidebar.tsx
|
|
1429
|
+
import React25, { useState as useState9, useEffect as useEffect6 } from "react";
|
|
1430
|
+
import Link10 from "next/link";
|
|
1431
|
+
import { HugeiconsIcon as HugeiconsIcon13 } from "@hugeicons/react";
|
|
1432
|
+
import { SidebarLeft01Icon, Cancel01Icon } from "@hugeicons/core-free-icons";
|
|
1433
|
+
var UniversalSidebar = ({
|
|
1434
|
+
navItems,
|
|
1435
|
+
currentPath,
|
|
1436
|
+
isMobileOpen,
|
|
1437
|
+
closeMobile,
|
|
1438
|
+
onNavClick,
|
|
1439
|
+
showInterceptDialog = false,
|
|
1440
|
+
onCancelIntercept,
|
|
1441
|
+
onConfirmIntercept,
|
|
1442
|
+
interceptTitle = "Discard Changes",
|
|
1443
|
+
interceptMessage = "Are you sure you want to leave? All unsaved changes will be lost."
|
|
1444
|
+
}) => {
|
|
1445
|
+
const [isCollapsed, setIsCollapsed] = useState9(false);
|
|
1446
|
+
useEffect6(() => {
|
|
1447
|
+
if (isMobileOpen) {
|
|
1448
|
+
closeMobile();
|
|
1449
|
+
}
|
|
1450
|
+
}, [currentPath]);
|
|
1451
|
+
return /* @__PURE__ */ React25.createElement(React25.Fragment, null, /* @__PURE__ */ React25.createElement(
|
|
1452
|
+
"div",
|
|
1453
|
+
{
|
|
1454
|
+
className: `fixed inset-0 bg-black/30 shadow-2xl transition-opacity duration-300 md:hidden z-90 ${isMobileOpen ? "opacity-100 pointer-events-auto" : "opacity-0 pointer-events-none"}`,
|
|
1455
|
+
onClick: closeMobile
|
|
1456
|
+
}
|
|
1457
|
+
), /* @__PURE__ */ React25.createElement(
|
|
1458
|
+
"aside",
|
|
1459
|
+
{
|
|
1460
|
+
className: `
|
|
1461
|
+
fixed md:relative top-0 left-0 h-full bg-white
|
|
1462
|
+
transition-all duration-300 ease-in-out shrink-0 flex flex-col z-100 md:z-10
|
|
1463
|
+
${isMobileOpen ? "translate-x-0" : "-translate-x-full md:translate-x-0"}
|
|
1464
|
+
${isCollapsed ? "md:w-16 w-64" : "w-64"}
|
|
1465
|
+
`
|
|
1466
|
+
},
|
|
1467
|
+
/* @__PURE__ */ React25.createElement("div", { className: "md:hidden flex justify-end p-4 shrink-0" }, /* @__PURE__ */ React25.createElement(
|
|
1468
|
+
"button",
|
|
1469
|
+
{
|
|
1470
|
+
onClick: closeMobile,
|
|
1471
|
+
className: "text-neutral-400 hover:text-black transition-colors outline-none",
|
|
1472
|
+
"aria-label": "Close Menu"
|
|
1473
|
+
},
|
|
1474
|
+
/* @__PURE__ */ React25.createElement(HugeiconsIcon13, { icon: Cancel01Icon, size: 24 })
|
|
1475
|
+
)),
|
|
1476
|
+
/* @__PURE__ */ React25.createElement("nav", { className: "flex-1 py-6 flex flex-col gap-1.5 px-3 overflow-y-auto custom-scrollbar" }, navItems.map((item) => {
|
|
1477
|
+
const isCurrentRoute = item.path === "/mod" || item.path === "/app" ? currentPath === item.path : currentPath === item.path || currentPath?.startsWith(`${item.path}/`);
|
|
1478
|
+
return /* @__PURE__ */ React25.createElement(
|
|
1479
|
+
Link10,
|
|
1480
|
+
{
|
|
1481
|
+
key: item.name,
|
|
1482
|
+
href: item.path,
|
|
1483
|
+
onClick: (e) => onNavClick ? onNavClick(e, item.path) : void 0,
|
|
1484
|
+
className: `flex items-center gap-3 px-3 py-2 rounded-full transition-all outline-none group ${isCurrentRoute ? "bg-neutral-100 text-black " : "text-neutral-500 hover:text-black hover:bg-neutral-50"}`,
|
|
1485
|
+
title: isCollapsed && !isMobileOpen ? item.name : void 0
|
|
1486
|
+
},
|
|
1487
|
+
/* @__PURE__ */ React25.createElement(
|
|
1488
|
+
HugeiconsIcon13,
|
|
1489
|
+
{
|
|
1490
|
+
icon: item.icon,
|
|
1491
|
+
size: 18,
|
|
1492
|
+
className: `shrink-0 transition-colors ${isCurrentRoute ? "text-black" : "text-neutral-400 group-hover:text-black"}`
|
|
1493
|
+
}
|
|
1494
|
+
),
|
|
1495
|
+
(!isCollapsed || isMobileOpen) && /* @__PURE__ */ React25.createElement("span", { className: "text-xs tracking-wide truncate" }, item.name)
|
|
1496
|
+
);
|
|
1497
|
+
})),
|
|
1498
|
+
/* @__PURE__ */ React25.createElement("div", { className: "p-4 hidden md:block shrink-0" }, /* @__PURE__ */ React25.createElement(
|
|
1499
|
+
"button",
|
|
1500
|
+
{
|
|
1501
|
+
onClick: () => setIsCollapsed(!isCollapsed),
|
|
1502
|
+
className: "flex items-center justify-center md:justify-start gap-3 w-full p-2.5 rounded-full text-neutral-500 hover:text-black hover:bg-neutral-50 transition-colors outline-none"
|
|
1503
|
+
},
|
|
1504
|
+
/* @__PURE__ */ React25.createElement(HugeiconsIcon13, { icon: SidebarLeft01Icon, size: 18, className: "shrink-0 text-neutral-400" }),
|
|
1505
|
+
!isCollapsed && /* @__PURE__ */ React25.createElement("span", { className: "text-xs" }, "Collapse")
|
|
1506
|
+
))
|
|
1507
|
+
), showInterceptDialog && /* @__PURE__ */ React25.createElement("div", { className: "fixed inset-0 z-110 flex items-center justify-center p-4 pointer-events-auto" }, /* @__PURE__ */ React25.createElement(
|
|
1508
|
+
"div",
|
|
1509
|
+
{
|
|
1510
|
+
className: "absolute inset-0 bg-black/30",
|
|
1511
|
+
onClick: onCancelIntercept
|
|
1512
|
+
}
|
|
1513
|
+
), /* @__PURE__ */ React25.createElement("div", { className: "relative w-72 bg-white rounded-2xl flex flex-col items-center overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ React25.createElement("div", { className: "p-6 text-center w-full" }, /* @__PURE__ */ React25.createElement("h3", { className: "text-[14px] text-black tracking-tight mb-1" }, interceptTitle), /* @__PURE__ */ React25.createElement("p", { className: "text-[12px] text-neutral-500 leading-snug mt-2" }, interceptMessage)), /* @__PURE__ */ React25.createElement("div", { className: "w-full flex" }, /* @__PURE__ */ React25.createElement(
|
|
1514
|
+
"button",
|
|
1515
|
+
{
|
|
1516
|
+
onClick: onCancelIntercept,
|
|
1517
|
+
className: "flex-1 py-2 text-[13px] text-neutral-600 hover:bg-neutral-50 transition-colors outline-none"
|
|
1518
|
+
},
|
|
1519
|
+
"Cancel"
|
|
1520
|
+
), /* @__PURE__ */ React25.createElement(
|
|
1521
|
+
"button",
|
|
1522
|
+
{
|
|
1523
|
+
onClick: onConfirmIntercept,
|
|
1524
|
+
className: "flex-1 py-2 text-[13px] text-[#F16A50] hover:bg-neutral-50 transition-colors flex justify-center items-center outline-none"
|
|
1525
|
+
},
|
|
1526
|
+
"Leave"
|
|
1527
|
+
)))));
|
|
1528
|
+
};
|
|
1529
|
+
|
|
1530
|
+
// src/components/UniversalHeader.tsx
|
|
1531
|
+
import React26, { useState as useState10 } from "react";
|
|
1532
|
+
import Link11 from "next/link";
|
|
1533
|
+
import { HugeiconsIcon as HugeiconsIcon14 } from "@hugeicons/react";
|
|
1534
|
+
import {
|
|
1535
|
+
ArrowDataTransferHorizontalIcon,
|
|
1536
|
+
SidebarLeft01Icon as SidebarLeft01Icon2,
|
|
1537
|
+
CheckmarkCircle01Icon,
|
|
1538
|
+
LogoutCircle02Icon,
|
|
1539
|
+
ArrowLeft01Icon as ArrowLeft01Icon2
|
|
1540
|
+
} from "@hugeicons/core-free-icons";
|
|
1541
|
+
var ButtonSpinner = () => /* @__PURE__ */ React26.createElement("svg", { className: "animate-spin h-4 w-4 text-neutral-400", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24" }, /* @__PURE__ */ React26.createElement("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), /* @__PURE__ */ React26.createElement("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" }));
|
|
1542
|
+
var UniversalHeader = ({
|
|
1543
|
+
onOpenMobile,
|
|
1544
|
+
title,
|
|
1545
|
+
subtitle,
|
|
1546
|
+
homeUrl = "/app",
|
|
1547
|
+
showBackButton = false,
|
|
1548
|
+
backUrl = "/app",
|
|
1549
|
+
showWorkspaceSwitcher = false,
|
|
1550
|
+
workspaces = [],
|
|
1551
|
+
activeWorkspaceId,
|
|
1552
|
+
onSwitchWorkspace,
|
|
1553
|
+
showLogoutAction = false,
|
|
1554
|
+
onLogout
|
|
1555
|
+
}) => {
|
|
1556
|
+
const [showSwitcherDialog, setShowSwitcherDialog] = useState10(false);
|
|
1557
|
+
const [showLogoutDialog, setShowLogoutDialog] = useState10(false);
|
|
1558
|
+
const [isLoggingOut, setIsLoggingOut] = useState10(false);
|
|
1559
|
+
const handleLogoutInitiation = async () => {
|
|
1560
|
+
if (isLoggingOut || !onLogout) return;
|
|
1561
|
+
setIsLoggingOut(true);
|
|
1562
|
+
try {
|
|
1563
|
+
await onLogout();
|
|
1564
|
+
} catch (error) {
|
|
1565
|
+
setIsLoggingOut(false);
|
|
1566
|
+
setShowLogoutDialog(false);
|
|
1567
|
+
}
|
|
1568
|
+
};
|
|
1569
|
+
return /* @__PURE__ */ React26.createElement("div", { className: "w-full shrink-0 z-50 flex flex-col relative pointer-events-none" }, /* @__PURE__ */ React26.createElement("div", { className: "w-full pointer-events-auto relative z-20" }, /* @__PURE__ */ React26.createElement("header", { className: "w-full bg-white pt-6 pb-3" }, /* @__PURE__ */ React26.createElement("div", { className: "max-w-7xl mx-auto px-6 flex justify-between items-center" }, /* @__PURE__ */ React26.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ React26.createElement(
|
|
1570
|
+
"button",
|
|
1571
|
+
{
|
|
1572
|
+
className: "md:hidden text-neutral-500 hover:text-black transition-colors outline-none",
|
|
1573
|
+
onClick: onOpenMobile,
|
|
1574
|
+
"aria-label": "Open Menu"
|
|
1575
|
+
},
|
|
1576
|
+
/* @__PURE__ */ React26.createElement(HugeiconsIcon14, { icon: SidebarLeft01Icon2, size: 24 })
|
|
1577
|
+
), /* @__PURE__ */ React26.createElement(Link11, { href: homeUrl, className: "flex items-center gap-3 transition-opacity hover:opacity-70 outline-none" }, /* @__PURE__ */ React26.createElement("div", { className: "flex flex-col justify-center" }, /* @__PURE__ */ React26.createElement("span", { className: "text-[13px] text-black leading-none truncate tracking-wide mb-1" }, title), subtitle && /* @__PURE__ */ React26.createElement("span", { className: "text-[9px] text-neutral-500 truncate tracking-[0.2em] leading-none" }, subtitle)))), /* @__PURE__ */ React26.createElement("div", { className: "flex items-center gap-3" }, showWorkspaceSwitcher && workspaces.length > 0 && /* @__PURE__ */ React26.createElement(
|
|
1578
|
+
"button",
|
|
1579
|
+
{
|
|
1580
|
+
onClick: () => setShowSwitcherDialog(true),
|
|
1581
|
+
className: "w-10 h-10 rounded-full border border-neutral-200 bg-white flex items-center justify-center text-neutral-500 hover:text-black hover:border-black hover:bg-neutral-50 transition-all group outline-none",
|
|
1582
|
+
"aria-label": "Switch Workspace"
|
|
1583
|
+
},
|
|
1584
|
+
/* @__PURE__ */ React26.createElement(HugeiconsIcon14, { icon: ArrowDataTransferHorizontalIcon, size: 16, className: "transition-transform group-hover:-translate-x-0.5" })
|
|
1585
|
+
), showLogoutAction && /* @__PURE__ */ React26.createElement(
|
|
1586
|
+
"button",
|
|
1587
|
+
{
|
|
1588
|
+
onClick: () => setShowLogoutDialog(true),
|
|
1589
|
+
className: "w-10 h-10 rounded-full border border-neutral-200 bg-white flex items-center justify-center text-neutral-500 hover:text-black hover:border-black hover:bg-neutral-50 transition-all group outline-none",
|
|
1590
|
+
"aria-label": "Secure Logout"
|
|
1591
|
+
},
|
|
1592
|
+
/* @__PURE__ */ React26.createElement(HugeiconsIcon14, { icon: LogoutCircle02Icon, size: 16, className: "transition-transform group-hover:-translate-x-0.5" })
|
|
1593
|
+
), showBackButton && /* @__PURE__ */ React26.createElement(
|
|
1594
|
+
Link11,
|
|
1595
|
+
{
|
|
1596
|
+
href: backUrl,
|
|
1597
|
+
className: "flex items-center justify-center w-10 h-10 border border-neutral-200 bg-white rounded-full text-neutral-500 hover:text-black hover:border-black hover:bg-neutral-50 transition-all group outline-none",
|
|
1598
|
+
"aria-label": "Go Back"
|
|
1599
|
+
},
|
|
1600
|
+
/* @__PURE__ */ React26.createElement(HugeiconsIcon14, { icon: ArrowLeft01Icon2, size: 16, className: "transition-transform group-hover:-translate-x-0.5" })
|
|
1601
|
+
))))), showSwitcherDialog && showWorkspaceSwitcher && workspaces.length > 0 && /* @__PURE__ */ React26.createElement("div", { className: "fixed inset-0 z-110 flex items-center justify-center p-4 pointer-events-auto" }, /* @__PURE__ */ React26.createElement(
|
|
1602
|
+
"div",
|
|
1603
|
+
{
|
|
1604
|
+
className: "absolute inset-0 bg-black/30",
|
|
1605
|
+
onClick: () => setShowSwitcherDialog(false)
|
|
1606
|
+
}
|
|
1607
|
+
), /* @__PURE__ */ React26.createElement("div", { className: "relative w-full max-w-sm bg-white rounded-2xl flex flex-col overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ React26.createElement("div", { className: "p-5 text-center w-full" }, /* @__PURE__ */ React26.createElement("h3", { className: "text-[14px] text-black tracking-tight mb-1" }, "Switch Workspace"), /* @__PURE__ */ React26.createElement("p", { className: "text-[11px] text-neutral-500 leading-snug" }, "Select an organization to switch your current context.")), /* @__PURE__ */ React26.createElement("div", { className: "max-h-75 overflow-y-auto w-full custom-scrollbar" }, workspaces.map((org) => /* @__PURE__ */ React26.createElement(
|
|
1608
|
+
"button",
|
|
1609
|
+
{
|
|
1610
|
+
key: org.id,
|
|
1611
|
+
onClick: () => {
|
|
1612
|
+
if (onSwitchWorkspace) onSwitchWorkspace(org.id);
|
|
1613
|
+
setShowSwitcherDialog(false);
|
|
1614
|
+
},
|
|
1615
|
+
className: "w-full text-left px-5 py-4 flex items-center justify-between hover:bg-neutral-50 transition-colors group outline-none last:border-0"
|
|
1616
|
+
},
|
|
1617
|
+
/* @__PURE__ */ React26.createElement("div", { className: "flex flex-col truncate pr-4" }, /* @__PURE__ */ React26.createElement("span", { className: `text-[13px] truncate ${activeWorkspaceId === org.id ? "text-black" : "text-neutral-600 group-hover:text-black"}` }, org.name), /* @__PURE__ */ React26.createElement("span", { className: "text-[9px] text-neutral-400 tracking-[0.2em] mt-1" }, "Role: ", org.role)),
|
|
1618
|
+
activeWorkspaceId === org.id && /* @__PURE__ */ React26.createElement(HugeiconsIcon14, { icon: CheckmarkCircle01Icon, size: 18, className: "text-black shrink-0" })
|
|
1619
|
+
))), /* @__PURE__ */ React26.createElement("div", { className: "w-full flex mt-auto" }, /* @__PURE__ */ React26.createElement(
|
|
1620
|
+
"button",
|
|
1621
|
+
{
|
|
1622
|
+
onClick: () => setShowSwitcherDialog(false),
|
|
1623
|
+
className: "w-full py-2.5 text-[13px] text-neutral-600 hover:bg-neutral-50 transition-colors outline-none"
|
|
1624
|
+
},
|
|
1625
|
+
"Cancel"
|
|
1626
|
+
)))), showLogoutDialog && showLogoutAction && /* @__PURE__ */ React26.createElement("div", { className: "fixed inset-0 z-110 flex items-center justify-center p-4 pointer-events-auto" }, /* @__PURE__ */ React26.createElement(
|
|
1627
|
+
"div",
|
|
1628
|
+
{
|
|
1629
|
+
className: "absolute inset-0 bg-black/30",
|
|
1630
|
+
onClick: () => !isLoggingOut && setShowLogoutDialog(false)
|
|
1631
|
+
}
|
|
1632
|
+
), /* @__PURE__ */ React26.createElement("div", { className: "relative w-72 bg-white rounded-2xl flex flex-col items-center overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ React26.createElement("div", { className: "p-6 text-center w-full" }, /* @__PURE__ */ React26.createElement("h3", { className: "text-[14px] text-black tracking-tight mb-1" }, "Secure Logout"), /* @__PURE__ */ React26.createElement("p", { className: "text-[12px] text-neutral-500 leading-snug mt-2" }, "Are you sure you want to log out? You will need to authenticate to return.")), /* @__PURE__ */ React26.createElement("div", { className: "w-full flex" }, /* @__PURE__ */ React26.createElement(
|
|
1633
|
+
"button",
|
|
1634
|
+
{
|
|
1635
|
+
onClick: () => setShowLogoutDialog(false),
|
|
1636
|
+
disabled: isLoggingOut,
|
|
1637
|
+
className: "flex-1 py-2 text-[13px] text-neutral-600 hover:bg-neutral-50 transition-colors disabled:opacity-50 outline-none"
|
|
1638
|
+
},
|
|
1639
|
+
"Cancel"
|
|
1640
|
+
), /* @__PURE__ */ React26.createElement(
|
|
1641
|
+
"button",
|
|
1642
|
+
{
|
|
1643
|
+
onClick: handleLogoutInitiation,
|
|
1644
|
+
disabled: isLoggingOut,
|
|
1645
|
+
className: "flex-1 py-2 text-[13px] text-[#F16A50] hover:bg-neutral-50 transition-colors disabled:opacity-50 flex justify-center items-center outline-none"
|
|
1646
|
+
},
|
|
1647
|
+
isLoggingOut ? /* @__PURE__ */ React26.createElement(ButtonSpinner, null) : "Log Out"
|
|
1648
|
+
)))));
|
|
1649
|
+
};
|
|
1650
|
+
|
|
1651
|
+
// src/components/UniversalOrganizationPage.tsx
|
|
1652
|
+
import React27, { useState as useState11, useEffect as useEffect8 } from "react";
|
|
1653
|
+
import toast2 from "react-hot-toast";
|
|
1654
|
+
var InputSpinner2 = () => /* @__PURE__ */ React27.createElement("svg", { className: "animate-spin h-4 w-4 text-neutral-400", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24" }, /* @__PURE__ */ React27.createElement("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), /* @__PURE__ */ React27.createElement("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" }));
|
|
1655
|
+
var UniversalOrganizationPage = ({
|
|
1656
|
+
initialOrgName,
|
|
1657
|
+
initialSlug,
|
|
1658
|
+
orgId,
|
|
1659
|
+
isReadOnly = false,
|
|
1660
|
+
slugPrefixUrl = "ecosystem.com/org/",
|
|
1661
|
+
onSaveConfiguration,
|
|
1662
|
+
onCheckSlugAvailability
|
|
1663
|
+
}) => {
|
|
1664
|
+
const [orgName, setOrgName] = useState11(initialOrgName);
|
|
1665
|
+
const [slug, setSlug] = useState11(initialSlug);
|
|
1666
|
+
const [isCheckingSlug, setIsCheckingSlug] = useState11(false);
|
|
1667
|
+
const [slugAvailable, setSlugAvailable] = useState11(null);
|
|
1668
|
+
const [isSubmitting, setIsSubmitting] = useState11(false);
|
|
1669
|
+
useEffect8(() => {
|
|
1670
|
+
setOrgName(initialOrgName || "");
|
|
1671
|
+
setSlug(initialSlug || "");
|
|
1672
|
+
}, [initialOrgName, initialSlug]);
|
|
1673
|
+
const handleOrgNameChange = (val) => {
|
|
1674
|
+
setOrgName(val.replace(/[^a-zA-Z0-9\s-]/g, "").substring(0, 50));
|
|
1675
|
+
};
|
|
1676
|
+
const handleSlugChange = (val) => {
|
|
1677
|
+
setSlug(val.toLowerCase().replace(/[^a-z0-9-]/g, "").replace(/-+/g, "-").substring(0, 50));
|
|
1678
|
+
};
|
|
1679
|
+
useEffect8(() => {
|
|
1680
|
+
if (!slug || slug === initialSlug) {
|
|
1681
|
+
setSlugAvailable(null);
|
|
1682
|
+
setIsCheckingSlug(false);
|
|
1683
|
+
return;
|
|
1684
|
+
}
|
|
1685
|
+
if (slug.length < 3) {
|
|
1686
|
+
setSlugAvailable(false);
|
|
1687
|
+
setIsCheckingSlug(false);
|
|
1688
|
+
return;
|
|
1689
|
+
}
|
|
1690
|
+
setIsCheckingSlug(true);
|
|
1691
|
+
setSlugAvailable(null);
|
|
1692
|
+
const checkTimer = setTimeout(async () => {
|
|
1693
|
+
try {
|
|
1694
|
+
const res = await onCheckSlugAvailability(slug);
|
|
1695
|
+
setSlugAvailable(res.available);
|
|
1696
|
+
} catch (error) {
|
|
1697
|
+
setSlugAvailable(null);
|
|
1698
|
+
} finally {
|
|
1699
|
+
setIsCheckingSlug(false);
|
|
1700
|
+
}
|
|
1701
|
+
}, 1500);
|
|
1702
|
+
return () => clearTimeout(checkTimer);
|
|
1703
|
+
}, [slug, initialSlug, onCheckSlugAvailability]);
|
|
1704
|
+
const handleSave = async (e) => {
|
|
1705
|
+
e.preventDefault();
|
|
1706
|
+
if (isSubmitting || isCheckingSlug || isReadOnly) return;
|
|
1707
|
+
if (slug !== initialSlug && slugAvailable === false) {
|
|
1708
|
+
toast2.error("Please select an available workspace URL.");
|
|
1709
|
+
return;
|
|
1710
|
+
}
|
|
1711
|
+
setIsSubmitting(true);
|
|
1712
|
+
try {
|
|
1713
|
+
const payload = {
|
|
1714
|
+
organizationId: orgId,
|
|
1715
|
+
organizationName: orgName !== initialOrgName ? orgName : void 0,
|
|
1716
|
+
slug: slug !== initialSlug ? slug : void 0
|
|
1717
|
+
};
|
|
1718
|
+
const responseData = await onSaveConfiguration(payload);
|
|
1719
|
+
if (responseData.success) {
|
|
1720
|
+
toast2.success("Organization updated successfully.");
|
|
1721
|
+
setTimeout(() => window.location.reload(), 1e3);
|
|
1722
|
+
} else {
|
|
1723
|
+
toast2.error(responseData.error || "Failed to update organization.");
|
|
1724
|
+
setIsSubmitting(false);
|
|
1725
|
+
}
|
|
1726
|
+
} catch (error) {
|
|
1727
|
+
toast2.error("Service unavailable. Try again later.");
|
|
1728
|
+
setIsSubmitting(false);
|
|
1729
|
+
}
|
|
1730
|
+
};
|
|
1731
|
+
const hasChanges = orgName !== initialOrgName || slug !== initialSlug;
|
|
1732
|
+
const isSaveDisabled = isSubmitting || isReadOnly || isCheckingSlug || !hasChanges || orgName.length < 3 || slug.length < 3 || slug !== initialSlug && slugAvailable === false;
|
|
1733
|
+
return /* @__PURE__ */ React27.createElement("div", { className: "flex flex-col gap-8 animate-in max-w-3xl rounded-2xl p-6 bg-white fade-in duration-300 min-h-full" }, /* @__PURE__ */ React27.createElement(ManagedToaster, null), /* @__PURE__ */ React27.createElement("div", { className: "flex items-start justify-between gap-4" }, /* @__PURE__ */ React27.createElement("div", null, /* @__PURE__ */ React27.createElement("h1", { className: "text-xl text-black mb-1 tracking-tight" }, "Organization"), /* @__PURE__ */ React27.createElement("p", { className: "text-xs text-neutral-500" }, "Manage your tenant workspace details and identity.")), isReadOnly && /* @__PURE__ */ React27.createElement("span", { className: "px-3 py-1 bg-neutral-50 text-neutral-500 rounded-full text-[10px] tracking-[0.2em] shrink-0" }, "Read Only Access")), /* @__PURE__ */ React27.createElement("div", { className: "w-full max-w-2xl" }, /* @__PURE__ */ React27.createElement("form", { className: "flex flex-col gap-8", onSubmit: handleSave, autoComplete: "off" }, /* @__PURE__ */ React27.createElement(
|
|
1734
|
+
TextInput,
|
|
1735
|
+
{
|
|
1736
|
+
label: "Organization Name",
|
|
1737
|
+
value: orgName,
|
|
1738
|
+
onChange: handleOrgNameChange,
|
|
1739
|
+
disabled: isReadOnly || isSubmitting,
|
|
1740
|
+
placeholder: "Acme Corporation",
|
|
1741
|
+
maxLength: 50
|
|
1742
|
+
}
|
|
1743
|
+
), /* @__PURE__ */ React27.createElement("div", { className: "space-y-2 relative w-full" }, /* @__PURE__ */ React27.createElement("label", { className: "text-[10px] text-neutral-400 tracking-[0.2em] block uppercase" }, "Organization Slug"), /* @__PURE__ */ React27.createElement("div", { className: "flex items-center relative w-full" }, /* @__PURE__ */ React27.createElement("span", { className: "text-neutral-400 text-sm py-3 pr-2 border-b border-neutral-200 shrink-0" }, slugPrefixUrl), /* @__PURE__ */ React27.createElement(
|
|
1744
|
+
"input",
|
|
1745
|
+
{
|
|
1746
|
+
type: "text",
|
|
1747
|
+
value: slug,
|
|
1748
|
+
disabled: isReadOnly || isSubmitting,
|
|
1749
|
+
onChange: (e) => handleSlugChange(e.target.value),
|
|
1750
|
+
spellCheck: "false",
|
|
1751
|
+
autoComplete: "off",
|
|
1752
|
+
className: "w-full px-2 py-3 text-sm bg-transparent border-b border-neutral-200 text-black transition-all outline-none focus:border-black pr-8 disabled:opacity-50 disabled:cursor-not-allowed",
|
|
1753
|
+
placeholder: "acme-corp"
|
|
1754
|
+
}
|
|
1755
|
+
), /* @__PURE__ */ React27.createElement("div", { className: "absolute right-2 top-1/2 -translate-y-1/2" }, isCheckingSlug && /* @__PURE__ */ React27.createElement(InputSpinner2, null), !isCheckingSlug && !isReadOnly && slug !== initialSlug && slug.length >= 3 && slugAvailable === false && /* @__PURE__ */ React27.createElement("span", { className: "inline-flex items-center justify-center w-4 h-4 rounded-full bg-red-100" }, /* @__PURE__ */ React27.createElement("svg", { className: "w-2 h-2 text-red-600", viewBox: "0 0 20 20", fill: "currentColor" }, /* @__PURE__ */ React27.createElement("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" }))), !isCheckingSlug && !isReadOnly && slug !== initialSlug && slug.length >= 3 && slugAvailable === true && /* @__PURE__ */ React27.createElement("span", { className: "inline-flex items-center justify-center w-4 h-4 rounded-full bg-green-100" }, /* @__PURE__ */ React27.createElement("svg", { className: "w-2 h-2 text-green-600", viewBox: "0 0 20 20", fill: "currentColor" }, /* @__PURE__ */ React27.createElement("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M16.707 5.293a1 1 0 00-1.414 0L8 12.586 4.707 9.293a1 1 0 10-1.414 1.414l4 4a1 1 0 001.414 0l8-8a1 1 0 000-1.414z" })))))), /* @__PURE__ */ React27.createElement("div", { className: "pt-8 mt-2 flex items-center gap-4" }, /* @__PURE__ */ React27.createElement(
|
|
1756
|
+
ThreeDActionButton,
|
|
1757
|
+
{
|
|
1758
|
+
type: "submit",
|
|
1759
|
+
disabled: isSaveDisabled,
|
|
1760
|
+
isLoading: isSubmitting,
|
|
1761
|
+
className: "min-w-32"
|
|
1762
|
+
},
|
|
1763
|
+
"Save Changes"
|
|
1764
|
+
), hasChanges && !isSubmitting && !isReadOnly && /* @__PURE__ */ React27.createElement(
|
|
1765
|
+
"button",
|
|
1766
|
+
{
|
|
1767
|
+
type: "button",
|
|
1768
|
+
onClick: () => {
|
|
1769
|
+
setOrgName(initialOrgName);
|
|
1770
|
+
setSlug(initialSlug);
|
|
1771
|
+
},
|
|
1772
|
+
className: "text-[11px] tracking-widest text-neutral-500 hover:text-black transition-colors outline-none"
|
|
1773
|
+
},
|
|
1774
|
+
"Cancel"
|
|
1775
|
+
)))));
|
|
1776
|
+
};
|
|
1777
|
+
|
|
1778
|
+
// src/components/UniversalIdentityPage.tsx
|
|
1779
|
+
import React28, { useState as useState12, useEffect as useEffect9 } from "react";
|
|
1780
|
+
import toast3 from "react-hot-toast";
|
|
1781
|
+
var ButtonSpinner2 = () => /* @__PURE__ */ React28.createElement("svg", { className: "animate-spin h-4 w-4 text-neutral-400", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24" }, /* @__PURE__ */ React28.createElement("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), /* @__PURE__ */ React28.createElement("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" }));
|
|
1782
|
+
var UniversalIdentityPage = ({
|
|
1783
|
+
headerTitle,
|
|
1784
|
+
headerDescription,
|
|
1785
|
+
primaryInputLabel,
|
|
1786
|
+
secondaryInputLabel,
|
|
1787
|
+
initialPrimaryValue,
|
|
1788
|
+
initialSecondaryValue = "",
|
|
1789
|
+
resourceId,
|
|
1790
|
+
isReadOnly = false,
|
|
1791
|
+
allowDeletion = false,
|
|
1792
|
+
deleteWarningText = "This action will permanently delete all records and data for this entity.",
|
|
1793
|
+
onSaveIdentity,
|
|
1794
|
+
onDeleteResource,
|
|
1795
|
+
onSuccessfulDeleteRedirect = "/app"
|
|
1796
|
+
}) => {
|
|
1797
|
+
const [primaryValue, setPrimaryValue] = useState12(initialPrimaryValue);
|
|
1798
|
+
const [secondaryValue, setSecondaryValue] = useState12(initialSecondaryValue);
|
|
1799
|
+
const [isSubmitting, setIsSubmitting] = useState12(false);
|
|
1800
|
+
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState12(false);
|
|
1801
|
+
const [isDeleting, setIsDeleting] = useState12(false);
|
|
1802
|
+
useEffect9(() => {
|
|
1803
|
+
setPrimaryValue(initialPrimaryValue || "");
|
|
1804
|
+
setSecondaryValue(initialSecondaryValue || "");
|
|
1805
|
+
}, [initialPrimaryValue, initialSecondaryValue]);
|
|
1806
|
+
const handlePrimaryChange = (val) => {
|
|
1807
|
+
setPrimaryValue(val.replace(/[^a-zA-Z0-9\s-]/g, "").substring(0, 50));
|
|
1808
|
+
};
|
|
1809
|
+
const handleSecondaryChange = (val) => {
|
|
1810
|
+
setSecondaryValue(val.replace(/[^a-zA-Z0-9\s.,!-]/g, "").substring(0, 150));
|
|
1811
|
+
};
|
|
1812
|
+
const handleSave = async (e) => {
|
|
1813
|
+
e.preventDefault();
|
|
1814
|
+
if (isSubmitting || isReadOnly) return;
|
|
1815
|
+
setIsSubmitting(true);
|
|
1816
|
+
try {
|
|
1817
|
+
const res = await onSaveIdentity({
|
|
1818
|
+
resourceId,
|
|
1819
|
+
primaryValue: primaryValue !== initialPrimaryValue ? primaryValue : void 0,
|
|
1820
|
+
secondaryValue: secondaryValue !== initialSecondaryValue ? secondaryValue : void 0
|
|
1821
|
+
});
|
|
1822
|
+
if (res.success) {
|
|
1823
|
+
toast3.success("Update successful.");
|
|
1824
|
+
} else {
|
|
1825
|
+
toast3.error(res.error || "Update failed.");
|
|
1826
|
+
}
|
|
1827
|
+
} catch (error) {
|
|
1828
|
+
toast3.error("Service unavailable.");
|
|
1829
|
+
} finally {
|
|
1830
|
+
setIsSubmitting(false);
|
|
1831
|
+
}
|
|
1832
|
+
};
|
|
1833
|
+
const handleDelete = async () => {
|
|
1834
|
+
if (isDeleting || isReadOnly || !onDeleteResource) return;
|
|
1835
|
+
setIsDeleting(true);
|
|
1836
|
+
try {
|
|
1837
|
+
const res = await onDeleteResource(resourceId);
|
|
1838
|
+
if (res.success) {
|
|
1839
|
+
toast3.success("Deletion permanent.");
|
|
1840
|
+
setIsDeleteModalOpen(false);
|
|
1841
|
+
window.location.href = onSuccessfulDeleteRedirect;
|
|
1842
|
+
} else {
|
|
1843
|
+
toast3.error(res.error || "Failed to delete.");
|
|
1844
|
+
setIsDeleting(false);
|
|
1845
|
+
}
|
|
1846
|
+
} catch (error) {
|
|
1847
|
+
toast3.error("Network error occurred.");
|
|
1848
|
+
setIsDeleting(false);
|
|
1849
|
+
}
|
|
1850
|
+
};
|
|
1851
|
+
const hasChanges = primaryValue !== initialPrimaryValue || secondaryValue !== initialSecondaryValue;
|
|
1852
|
+
const isSaveDisabled = isSubmitting || isReadOnly || !hasChanges || primaryValue.trim().length < 3;
|
|
1853
|
+
return /* @__PURE__ */ React28.createElement("div", { className: "flex flex-col gap-8 animate-in max-w-3xl rounded-2xl p-6 bg-white fade-in duration-300 min-h-full" }, /* @__PURE__ */ React28.createElement(ManagedToaster, null), /* @__PURE__ */ React28.createElement("div", { className: "flex items-start justify-between gap-4" }, /* @__PURE__ */ React28.createElement("div", null, /* @__PURE__ */ React28.createElement("h1", { className: "text-xl text-black mb-1 tracking-tight" }, headerTitle), /* @__PURE__ */ React28.createElement("p", { className: "text-xs text-neutral-500" }, headerDescription)), isReadOnly && /* @__PURE__ */ React28.createElement("span", { className: "px-3 py-1 bg-neutral-50 text-neutral-500 rounded-full text-[10px] tracking-[0.2em] shrink-0" }, "Read Only Access")), /* @__PURE__ */ React28.createElement("div", { className: "w-full max-w-2xl" }, /* @__PURE__ */ React28.createElement("form", { className: "flex flex-col gap-8", onSubmit: handleSave, autoComplete: "off" }, /* @__PURE__ */ React28.createElement(
|
|
1854
|
+
TextInput,
|
|
1855
|
+
{
|
|
1856
|
+
label: primaryInputLabel,
|
|
1857
|
+
value: primaryValue,
|
|
1858
|
+
onChange: handlePrimaryChange,
|
|
1859
|
+
disabled: isReadOnly || isSubmitting,
|
|
1860
|
+
maxLength: 50
|
|
1861
|
+
}
|
|
1862
|
+
), secondaryInputLabel && /* @__PURE__ */ React28.createElement(
|
|
1863
|
+
TextInput,
|
|
1864
|
+
{
|
|
1865
|
+
label: secondaryInputLabel,
|
|
1866
|
+
value: secondaryValue,
|
|
1867
|
+
onChange: handleSecondaryChange,
|
|
1868
|
+
disabled: isReadOnly || isSubmitting,
|
|
1869
|
+
maxLength: 150
|
|
1870
|
+
}
|
|
1871
|
+
), !isReadOnly && /* @__PURE__ */ React28.createElement("div", { className: "pt-8 mt-2 flex flex-col sm:flex-row sm:items-center justify-between gap-6" }, /* @__PURE__ */ React28.createElement("div", { className: "flex items-center gap-4 w-full sm:w-auto" }, /* @__PURE__ */ React28.createElement(
|
|
1872
|
+
ThreeDActionButton,
|
|
1873
|
+
{
|
|
1874
|
+
type: "submit",
|
|
1875
|
+
disabled: isSaveDisabled,
|
|
1876
|
+
isLoading: isSubmitting,
|
|
1877
|
+
className: "min-w-32 w-full sm:w-auto"
|
|
1878
|
+
},
|
|
1879
|
+
"Save Changes"
|
|
1880
|
+
), hasChanges && !isSubmitting && /* @__PURE__ */ React28.createElement(
|
|
1881
|
+
"button",
|
|
1882
|
+
{
|
|
1883
|
+
type: "button",
|
|
1884
|
+
onClick: () => {
|
|
1885
|
+
setPrimaryValue(initialPrimaryValue);
|
|
1886
|
+
setSecondaryValue(initialSecondaryValue);
|
|
1887
|
+
},
|
|
1888
|
+
className: "text-[11px] tracking-widest text-neutral-500 hover:text-black transition-colors w-full sm:w-auto py-2 sm:py-0 outline-none"
|
|
1889
|
+
},
|
|
1890
|
+
"Cancel"
|
|
1891
|
+
)), allowDeletion && /* @__PURE__ */ React28.createElement(
|
|
1892
|
+
"button",
|
|
1893
|
+
{
|
|
1894
|
+
type: "button",
|
|
1895
|
+
onClick: () => setIsDeleteModalOpen(true),
|
|
1896
|
+
className: "px-6 py-2 text-[11px] tracking-widest text-red-400 border border-red-200 hover:border-red-400 rounded-full transition-all w-full sm:w-auto outline-none"
|
|
1897
|
+
},
|
|
1898
|
+
"Delete ",
|
|
1899
|
+
headerTitle.split(" ")[0]
|
|
1900
|
+
)))), isDeleteModalOpen && !isReadOnly && allowDeletion && /* @__PURE__ */ React28.createElement("div", { className: "fixed inset-0 z-110 flex items-center justify-center p-4" }, /* @__PURE__ */ React28.createElement("div", { className: "absolute inset-0 bg-black/30 shadow-2xl", onClick: () => !isDeleting && setIsDeleteModalOpen(false) }), /* @__PURE__ */ React28.createElement("div", { className: "relative w-72 bg-white shadow-2xl rounded-2xl flex flex-col items-center overflow-hidden animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ React28.createElement("div", { className: "p-6 text-center w-full" }, /* @__PURE__ */ React28.createElement("h3", { className: "text-[14px] text-black tracking-tight mb-1" }, "Confirm Deletion"), /* @__PURE__ */ React28.createElement("p", { className: "text-[12px] text-neutral-500 leading-snug mt-2" }, deleteWarningText)), /* @__PURE__ */ React28.createElement("div", { className: "w-full flex" }, /* @__PURE__ */ React28.createElement(
|
|
1901
|
+
"button",
|
|
1902
|
+
{
|
|
1903
|
+
type: "button",
|
|
1904
|
+
onClick: () => setIsDeleteModalOpen(false),
|
|
1905
|
+
disabled: isDeleting,
|
|
1906
|
+
className: "flex-1 py-2 text-[13px] text-neutral-600 hover:bg-neutral-50 transition-colors disabled:opacity-50 outline-none"
|
|
1907
|
+
},
|
|
1908
|
+
"Cancel"
|
|
1909
|
+
), /* @__PURE__ */ React28.createElement(
|
|
1910
|
+
"button",
|
|
1911
|
+
{
|
|
1912
|
+
type: "button",
|
|
1913
|
+
onClick: handleDelete,
|
|
1914
|
+
disabled: isDeleting,
|
|
1915
|
+
className: "flex-1 py-2 text-[13px] text-red-600 hover:bg-neutral-50 transition-colors disabled:opacity-50 flex justify-center items-center outline-none"
|
|
1916
|
+
},
|
|
1917
|
+
isDeleting ? /* @__PURE__ */ React28.createElement(ButtonSpinner2, null) : "Delete"
|
|
1918
|
+
)))));
|
|
1919
|
+
};
|
|
1920
|
+
|
|
1921
|
+
// src/components/UniversalMembersPage.tsx
|
|
1922
|
+
import React29, { useState as useState13, useEffect as useEffect10, useRef as useRef4 } from "react";
|
|
1923
|
+
import toast4 from "react-hot-toast";
|
|
1924
|
+
import { HugeiconsIcon as HugeiconsIcon15 } from "@hugeicons/react";
|
|
1925
|
+
import {
|
|
1926
|
+
UserAdd01Icon,
|
|
1927
|
+
ArrowLeft01Icon as ArrowLeft01Icon3,
|
|
1928
|
+
ArrowRight01Icon as ArrowRight01Icon3,
|
|
1929
|
+
Delete01Icon,
|
|
1930
|
+
ArrowDown01Icon as ArrowDown01Icon2,
|
|
1931
|
+
Loading03Icon as Loading03Icon6
|
|
1932
|
+
} from "@hugeicons/core-free-icons";
|
|
1933
|
+
var ButtonSpinner3 = () => /* @__PURE__ */ React29.createElement(HugeiconsIcon15, { icon: Loading03Icon6, size: 16, className: "animate-spin text-white" });
|
|
1934
|
+
var PageSpinner2 = () => /* @__PURE__ */ React29.createElement("div", { className: "flex justify-center items-center py-12" }, /* @__PURE__ */ React29.createElement(HugeiconsIcon15, { icon: Loading03Icon6, size: 32, className: "animate-spin mb-4 text-black" }));
|
|
1935
|
+
var getInitials = (name) => {
|
|
1936
|
+
if (!name) return "U";
|
|
1937
|
+
const parts = name.trim().split(" ");
|
|
1938
|
+
if (parts.length >= 2) return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
|
|
1939
|
+
return parts[0].substring(0, 2).toUpperCase();
|
|
1940
|
+
};
|
|
1941
|
+
var resolveThemeColor = (colorCode) => {
|
|
1942
|
+
switch (colorCode) {
|
|
1943
|
+
case "COLOR_A":
|
|
1944
|
+
return "bg-blue-100 border-blue-200";
|
|
1945
|
+
case "COLOR_B":
|
|
1946
|
+
return "bg-emerald-100 border-emerald-200";
|
|
1947
|
+
case "COLOR_C":
|
|
1948
|
+
return "bg-rose-100 border-rose-200";
|
|
1949
|
+
case "COLOR_D":
|
|
1950
|
+
return "bg-amber-100 border-amber-200";
|
|
1951
|
+
case "COLOR_E":
|
|
1952
|
+
return "bg-purple-100 border-purple-200";
|
|
1953
|
+
case "COLOR_F":
|
|
1954
|
+
return "bg-pink-100 border-pink-200";
|
|
1955
|
+
default:
|
|
1956
|
+
return "bg-neutral-100 border-neutral-200";
|
|
1957
|
+
}
|
|
1958
|
+
};
|
|
1959
|
+
var cleanName = (val) => val.replace(/[^a-zA-Z\s-]/g, "").substring(0, 50);
|
|
1960
|
+
var UniversalMembersPage = ({
|
|
1961
|
+
headerTitle,
|
|
1962
|
+
headerDescription,
|
|
1963
|
+
currentUserId,
|
|
1964
|
+
members,
|
|
1965
|
+
isLoading,
|
|
1966
|
+
currentPage,
|
|
1967
|
+
totalPages,
|
|
1968
|
+
onPageChange,
|
|
1969
|
+
canManage,
|
|
1970
|
+
canChangeRoles,
|
|
1971
|
+
availableRoles,
|
|
1972
|
+
requireNamesForInvite,
|
|
1973
|
+
onInviteMember,
|
|
1974
|
+
onRemoveMember,
|
|
1975
|
+
onUpdateRole
|
|
1976
|
+
}) => {
|
|
1977
|
+
const [currentView, setCurrentView] = useState13("list");
|
|
1978
|
+
const [selectedMember, setSelectedMember] = useState13(null);
|
|
1979
|
+
const [inviteEmail, setInviteEmail] = useState13("");
|
|
1980
|
+
const [inviteFirst, setInviteFirst] = useState13("");
|
|
1981
|
+
const [inviteLast, setInviteLast] = useState13("");
|
|
1982
|
+
const [isInviting, setIsInviting] = useState13(false);
|
|
1983
|
+
const [isRoleModalOpen, setIsRoleModalOpen] = useState13(false);
|
|
1984
|
+
const [isUpdatingRole, setIsUpdatingRole] = useState13(false);
|
|
1985
|
+
const [memberToDelete, setMemberToDelete] = useState13(null);
|
|
1986
|
+
const [isDeleting, setIsDeleting] = useState13(false);
|
|
1987
|
+
const dropdownRef = useRef4(null);
|
|
1988
|
+
useEffect10(() => {
|
|
1989
|
+
function handleClickOutside(event) {
|
|
1990
|
+
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
|
1991
|
+
setIsRoleModalOpen(false);
|
|
1992
|
+
}
|
|
1993
|
+
}
|
|
1994
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1995
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
1996
|
+
}, []);
|
|
1997
|
+
const handleInvite = async (e) => {
|
|
1998
|
+
e.preventDefault();
|
|
1999
|
+
if (isInviting || !canManage) return;
|
|
2000
|
+
setIsInviting(true);
|
|
2001
|
+
try {
|
|
2002
|
+
const res = await onInviteMember(inviteEmail, inviteFirst, inviteLast);
|
|
2003
|
+
if (res.success) {
|
|
2004
|
+
toast4.success("Member added successfully.");
|
|
2005
|
+
setInviteEmail("");
|
|
2006
|
+
setInviteFirst("");
|
|
2007
|
+
setInviteLast("");
|
|
2008
|
+
setCurrentView("list");
|
|
2009
|
+
} else {
|
|
2010
|
+
toast4.error(res.error || "Failed to add member.");
|
|
2011
|
+
}
|
|
2012
|
+
} catch (error) {
|
|
2013
|
+
toast4.error("Service unavailable.");
|
|
2014
|
+
} finally {
|
|
2015
|
+
setIsInviting(false);
|
|
2016
|
+
}
|
|
2017
|
+
};
|
|
2018
|
+
const handleDelete = async () => {
|
|
2019
|
+
if (!memberToDelete || isDeleting || !canManage) return;
|
|
2020
|
+
setIsDeleting(true);
|
|
2021
|
+
try {
|
|
2022
|
+
const res = await onRemoveMember(memberToDelete);
|
|
2023
|
+
if (res.success) {
|
|
2024
|
+
toast4.success("Member removed successfully.");
|
|
2025
|
+
setMemberToDelete(null);
|
|
2026
|
+
setCurrentView("list");
|
|
2027
|
+
} else {
|
|
2028
|
+
toast4.error(res.error || "Failed to remove member.");
|
|
2029
|
+
}
|
|
2030
|
+
} catch (error) {
|
|
2031
|
+
toast4.error("Service unavailable.");
|
|
2032
|
+
} finally {
|
|
2033
|
+
setIsDeleting(false);
|
|
2034
|
+
}
|
|
2035
|
+
};
|
|
2036
|
+
const handleRoleUpdate = async (newRole) => {
|
|
2037
|
+
if (!selectedMember || isUpdatingRole || selectedMember.role === newRole || !canChangeRoles) {
|
|
2038
|
+
setIsRoleModalOpen(false);
|
|
2039
|
+
return;
|
|
2040
|
+
}
|
|
2041
|
+
setIsRoleModalOpen(false);
|
|
2042
|
+
setIsUpdatingRole(true);
|
|
2043
|
+
try {
|
|
2044
|
+
const res = await onUpdateRole(selectedMember, newRole);
|
|
2045
|
+
if (res.success) {
|
|
2046
|
+
toast4.success("Role updated successfully.");
|
|
2047
|
+
setSelectedMember({ ...selectedMember, role: newRole });
|
|
2048
|
+
} else {
|
|
2049
|
+
toast4.error(res.error || "Failed to update role.");
|
|
2050
|
+
}
|
|
2051
|
+
} catch (error) {
|
|
2052
|
+
toast4.error("Service unavailable.");
|
|
2053
|
+
} finally {
|
|
2054
|
+
setIsUpdatingRole(false);
|
|
2055
|
+
}
|
|
2056
|
+
};
|
|
2057
|
+
const goBack = () => {
|
|
2058
|
+
setCurrentView("list");
|
|
2059
|
+
setSelectedMember(null);
|
|
2060
|
+
setIsRoleModalOpen(false);
|
|
2061
|
+
};
|
|
2062
|
+
return /* @__PURE__ */ React29.createElement("div", { className: "flex flex-col gap-8 animate-in max-w-3xl fade-in duration-300 p-6 rounded-2xl bg-white min-h-full" }, /* @__PURE__ */ React29.createElement(ManagedToaster, null), /* @__PURE__ */ React29.createElement("div", { className: "flex flex-col sm:flex-row sm:items-start justify-between gap-4" }, currentView === "list" && /* @__PURE__ */ React29.createElement(React29.Fragment, null, /* @__PURE__ */ React29.createElement("div", null, /* @__PURE__ */ React29.createElement("h1", { className: "text-xl text-black mb-1 tracking-tight" }, headerTitle), /* @__PURE__ */ React29.createElement("p", { className: "text-xs text-neutral-500" }, headerDescription)), canManage && /* @__PURE__ */ React29.createElement(
|
|
2063
|
+
ThreeDActionButton,
|
|
2064
|
+
{
|
|
2065
|
+
onClick: () => setCurrentView("invite"),
|
|
2066
|
+
className: "w-fit shrink-0 gap-2"
|
|
2067
|
+
},
|
|
2068
|
+
/* @__PURE__ */ React29.createElement(HugeiconsIcon15, { icon: UserAdd01Icon, size: 12 }),
|
|
2069
|
+
"Add Member"
|
|
2070
|
+
)), currentView !== "list" && /* @__PURE__ */ React29.createElement("div", { className: "flex flex-col items-start gap-3" }, /* @__PURE__ */ React29.createElement("button", { onClick: goBack, className: "text-[10px] text-neutral-400 hover:text-black tracking-[0.2em] flex items-center gap-1.5 transition-colors outline-none" }, /* @__PURE__ */ React29.createElement(HugeiconsIcon15, { icon: ArrowLeft01Icon3, size: 12 }), " Back"), /* @__PURE__ */ React29.createElement("h1", { className: "text-lg text-black tracking-tight" }, currentView === "invite" ? "Add New Member" : "Member Profile"))), currentView === "list" && /* @__PURE__ */ React29.createElement("div", { className: "w-full overflow-hidden" }, isLoading ? /* @__PURE__ */ React29.createElement(PageSpinner2, null) : /* @__PURE__ */ React29.createElement("div", { className: "flex flex-col min-w-0" }, /* @__PURE__ */ React29.createElement("div", { className: "divide-y divide-neutral-100" }, members.map((member) => /* @__PURE__ */ React29.createElement(
|
|
2071
|
+
"div",
|
|
2072
|
+
{
|
|
2073
|
+
key: member.id,
|
|
2074
|
+
onClick: () => {
|
|
2075
|
+
setSelectedMember(member);
|
|
2076
|
+
setCurrentView("details");
|
|
2077
|
+
},
|
|
2078
|
+
className: "flex items-center justify-between p-4 sm:p-5 hover:bg-neutral-50/50 transition-colors cursor-pointer group min-w-0"
|
|
2079
|
+
},
|
|
2080
|
+
/* @__PURE__ */ React29.createElement("div", { className: "flex items-center gap-3 sm:gap-4 min-w-0 flex-1" }, member.displayImage && member.displayImage !== "NO_IMAGE" ? /* @__PURE__ */ React29.createElement("div", { className: "w-10 h-10 shrink-0 rounded-full overflow-hidden bg-neutral-100" }, /* @__PURE__ */ React29.createElement(
|
|
2081
|
+
"img",
|
|
2082
|
+
{
|
|
2083
|
+
src: member.displayImage,
|
|
2084
|
+
alt: member.fullName,
|
|
2085
|
+
className: "w-full h-full object-cover blur-sm transition-all duration-300",
|
|
2086
|
+
onLoad: (e) => e.currentTarget.classList.remove("blur-sm")
|
|
2087
|
+
}
|
|
2088
|
+
)) : /* @__PURE__ */ React29.createElement("div", { className: `w-10 h-10 shrink-0 rounded-full flex items-center justify-center text-black text-xs ${resolveThemeColor(member.profileColor)}` }, getInitials(member.fullName)), /* @__PURE__ */ React29.createElement("div", { className: "min-w-0 flex-1" }, /* @__PURE__ */ React29.createElement("p", { className: "text-sm text-black truncate pr-2 sm:pr-4" }, member.fullName, " ", member.userId === currentUserId && /* @__PURE__ */ React29.createElement("span", { className: "text-neutral-400 ml-1 sm:ml-2" }, "(You)")), /* @__PURE__ */ React29.createElement("p", { className: "text-xs text-neutral-500 truncate pr-2 sm:pr-4 mt-0.5" }, member.email))),
|
|
2089
|
+
/* @__PURE__ */ React29.createElement("div", { className: `shrink-0 pl-2 sm:pl-4 transition-opacity hidden sm:block ${canManage ? "opacity-0 group-hover:opacity-100" : "opacity-100"}` }, /* @__PURE__ */ React29.createElement("span", { className: "text-[10px] tracking-[0.2em] text-black border border-neutral-200 px-4 py-2 rounded-full bg-white whitespace-nowrap" }, canManage ? "Manage" : "View"))
|
|
2090
|
+
))), /* @__PURE__ */ React29.createElement("div", { className: "flex items-center justify-between p-4 sm:p-5" }, /* @__PURE__ */ React29.createElement("span", { className: "text-[10px] text-neutral-400 tracking-[0.2em]" }, "Page ", currentPage, " of ", totalPages), /* @__PURE__ */ React29.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React29.createElement(
|
|
2091
|
+
"button",
|
|
2092
|
+
{
|
|
2093
|
+
onClick: () => onPageChange(currentPage - 1),
|
|
2094
|
+
disabled: currentPage === 1 || isLoading,
|
|
2095
|
+
className: "p-2 border border-neutral-200 rounded-full bg-white text-neutral-500 hover:text-black hover:border-black disabled:opacity-30 disabled:cursor-not-allowed transition-all outline-none"
|
|
2096
|
+
},
|
|
2097
|
+
/* @__PURE__ */ React29.createElement(HugeiconsIcon15, { icon: ArrowLeft01Icon3, size: 14 })
|
|
2098
|
+
), /* @__PURE__ */ React29.createElement(
|
|
2099
|
+
"button",
|
|
2100
|
+
{
|
|
2101
|
+
onClick: () => onPageChange(currentPage + 1),
|
|
2102
|
+
disabled: currentPage >= totalPages || isLoading,
|
|
2103
|
+
className: "p-2 border border-neutral-200 rounded-full bg-white text-neutral-500 hover:text-black hover:border-black disabled:opacity-30 disabled:cursor-not-allowed transition-all outline-none"
|
|
2104
|
+
},
|
|
2105
|
+
/* @__PURE__ */ React29.createElement(HugeiconsIcon15, { icon: ArrowRight01Icon3, size: 14 })
|
|
2106
|
+
))))), currentView === "details" && selectedMember && /* @__PURE__ */ React29.createElement("div", { className: "w-full max-w-2xl text-left" }, /* @__PURE__ */ React29.createElement("div", { className: "flex flex-col gap-8" }, /* @__PURE__ */ React29.createElement("div", { className: "flex items-center gap-5" }, selectedMember.displayImage && selectedMember.displayImage !== "NO_IMAGE" ? /* @__PURE__ */ React29.createElement("div", { className: "w-16 h-16 shrink-0 rounded-full overflow-hidden bg-neutral-100" }, /* @__PURE__ */ React29.createElement(
|
|
2107
|
+
"img",
|
|
2108
|
+
{
|
|
2109
|
+
src: selectedMember.displayImage,
|
|
2110
|
+
alt: selectedMember.fullName,
|
|
2111
|
+
className: "w-full h-full object-cover blur-sm transition-all duration-300",
|
|
2112
|
+
onLoad: (e) => e.currentTarget.classList.remove("blur-sm")
|
|
2113
|
+
}
|
|
2114
|
+
)) : /* @__PURE__ */ React29.createElement("div", { className: `w-16 h-16 shrink-0 rounded-full flex items-center justify-center text-black text-sm ${resolveThemeColor(selectedMember.profileColor)}` }, getInitials(selectedMember.fullName)), /* @__PURE__ */ React29.createElement("div", null, /* @__PURE__ */ React29.createElement("h2", { className: "text-lg text-black" }, selectedMember.fullName), /* @__PURE__ */ React29.createElement("p", { className: "text-sm text-neutral-500 mt-1" }, selectedMember.email))), /* @__PURE__ */ React29.createElement("div", { className: "grid grid-cols-2 gap-6 border-t border-neutral-200 pt-8" }, /* @__PURE__ */ React29.createElement("div", null, /* @__PURE__ */ React29.createElement("span", { className: "text-[10px] tracking-[0.2em] text-neutral-400 block mb-3" }, "Role"), canChangeRoles && selectedMember.userId !== currentUserId ? /* @__PURE__ */ React29.createElement(
|
|
2115
|
+
"button",
|
|
2116
|
+
{
|
|
2117
|
+
onClick: () => !isUpdatingRole && setIsRoleModalOpen(true),
|
|
2118
|
+
disabled: isUpdatingRole,
|
|
2119
|
+
className: `flex items-center gap-3 text-xs text-black pl-4 pr-3 py-2 border rounded-full transition-colors disabled:opacity-50 outline-none ${isRoleModalOpen ? "bg-neutral-50 border-neutral-300" : "bg-white border-neutral-200 hover:bg-neutral-50"}`
|
|
2120
|
+
},
|
|
2121
|
+
selectedMember.role,
|
|
2122
|
+
isUpdatingRole ? /* @__PURE__ */ React29.createElement(ButtonSpinner3, null) : /* @__PURE__ */ React29.createElement(HugeiconsIcon15, { icon: ArrowDown01Icon2, size: 14, className: "text-neutral-400" })
|
|
2123
|
+
) : /* @__PURE__ */ React29.createElement("span", { className: "text-xs text-black bg-neutral-50 px-4 py-2 rounded-full inline-block" }, selectedMember.role)), /* @__PURE__ */ React29.createElement("div", null, /* @__PURE__ */ React29.createElement("span", { className: "text-[10px] tracking-[0.2em] text-neutral-400 block mb-3" }, "Joined Date"), /* @__PURE__ */ React29.createElement("span", { className: "text-sm text-black" }, new Date(selectedMember.joinedAt).toLocaleDateString()))), canManage && selectedMember.userId !== currentUserId && /* @__PURE__ */ React29.createElement("div", { className: "pt-8 mt-2 border-t border-neutral-200" }, /* @__PURE__ */ React29.createElement(
|
|
2124
|
+
"button",
|
|
2125
|
+
{
|
|
2126
|
+
onClick: () => setMemberToDelete(selectedMember),
|
|
2127
|
+
className: "flex items-center gap-2 text-[11px] tracking-widest text-red-600 hover:text-red-700 transition-colors w-fit outline-none"
|
|
2128
|
+
},
|
|
2129
|
+
/* @__PURE__ */ React29.createElement(HugeiconsIcon15, { icon: Delete01Icon, size: 14 }),
|
|
2130
|
+
" Remove Member"
|
|
2131
|
+
)))), currentView === "invite" && canManage && /* @__PURE__ */ React29.createElement("div", { className: "w-full max-w-2xl text-left" }, /* @__PURE__ */ React29.createElement("form", { onSubmit: handleInvite, className: "space-y-8", autoComplete: "off" }, /* @__PURE__ */ React29.createElement(
|
|
2132
|
+
TextInput,
|
|
2133
|
+
{
|
|
2134
|
+
label: "Email Address",
|
|
2135
|
+
value: inviteEmail,
|
|
2136
|
+
onChange: (val) => setInviteEmail(val.toLowerCase()),
|
|
2137
|
+
disabled: isInviting,
|
|
2138
|
+
placeholder: "developer@acme.com"
|
|
2139
|
+
}
|
|
2140
|
+
), requireNamesForInvite && /* @__PURE__ */ React29.createElement("div", { className: "flex flex-col sm:flex-row gap-6" }, /* @__PURE__ */ React29.createElement(
|
|
2141
|
+
TextInput,
|
|
2142
|
+
{
|
|
2143
|
+
label: "First Name",
|
|
2144
|
+
value: inviteFirst,
|
|
2145
|
+
onChange: (val) => setInviteFirst(cleanName(val)),
|
|
2146
|
+
disabled: isInviting,
|
|
2147
|
+
placeholder: "Jane"
|
|
2148
|
+
}
|
|
2149
|
+
), /* @__PURE__ */ React29.createElement(
|
|
2150
|
+
TextInput,
|
|
2151
|
+
{
|
|
2152
|
+
label: "Last Name",
|
|
2153
|
+
value: inviteLast,
|
|
2154
|
+
onChange: (val) => setInviteLast(cleanName(val)),
|
|
2155
|
+
disabled: isInviting,
|
|
2156
|
+
placeholder: "Doe"
|
|
2157
|
+
}
|
|
2158
|
+
)), /* @__PURE__ */ React29.createElement("div", { className: "pt-8 mt-2" }, /* @__PURE__ */ React29.createElement(
|
|
2159
|
+
ThreeDActionButton,
|
|
2160
|
+
{
|
|
2161
|
+
type: "submit",
|
|
2162
|
+
disabled: isInviting || !inviteEmail || requireNamesForInvite && (!inviteFirst || !inviteLast),
|
|
2163
|
+
isLoading: isInviting,
|
|
2164
|
+
className: "min-w-40"
|
|
2165
|
+
},
|
|
2166
|
+
"Send Invitation"
|
|
2167
|
+
)))), isRoleModalOpen && canChangeRoles && /* @__PURE__ */ React29.createElement("div", { className: "fixed inset-0 z-110 flex items-center justify-center p-4" }, /* @__PURE__ */ React29.createElement("div", { className: "absolute inset-0 bg-black/30", onClick: () => !isUpdatingRole && setIsRoleModalOpen(false) }), /* @__PURE__ */ React29.createElement("div", { ref: dropdownRef, className: "relative w-72 bg-white shadow-2xl rounded-2xl flex flex-col items-center overflow-hidden animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ React29.createElement("div", { className: "p-6 text-center w-full" }, /* @__PURE__ */ React29.createElement("h3", { className: "text-[14px] text-black tracking-tight" }, "Update Role")), /* @__PURE__ */ React29.createElement("div", { className: "w-full flex flex-col pl-2 pr-2" }, availableRoles.map((roleOption) => /* @__PURE__ */ React29.createElement(
|
|
2168
|
+
"button",
|
|
2169
|
+
{
|
|
2170
|
+
key: roleOption,
|
|
2171
|
+
onClick: () => handleRoleUpdate(roleOption),
|
|
2172
|
+
disabled: isUpdatingRole,
|
|
2173
|
+
className: `text-left px-4 py-3 text-[12px] tracking-wide transition-colors rounded-full flex items-center justify-between outline-none ${selectedMember?.role === roleOption ? "bg-neutral-100 text-black" : "text-neutral-500 hover:bg-neutral-50 hover:text-black"}`
|
|
2174
|
+
},
|
|
2175
|
+
/* @__PURE__ */ React29.createElement("span", { className: "truncate pr-2" }, roleOption),
|
|
2176
|
+
selectedMember?.role === roleOption && /* @__PURE__ */ React29.createElement("div", { className: "w-1.5 h-1.5 rounded-full shrink-0 bg-black" })
|
|
2177
|
+
))), /* @__PURE__ */ React29.createElement("div", { className: "w-full flex" }, /* @__PURE__ */ React29.createElement(
|
|
2178
|
+
"button",
|
|
2179
|
+
{
|
|
2180
|
+
onClick: () => setIsRoleModalOpen(false),
|
|
2181
|
+
disabled: isUpdatingRole,
|
|
2182
|
+
className: "w-full py-2.5 text-[13px] text-neutral-600 hover:bg-neutral-50 transition-colors disabled:opacity-50 outline-none"
|
|
2183
|
+
},
|
|
2184
|
+
"Cancel"
|
|
2185
|
+
)))), memberToDelete && canManage && /* @__PURE__ */ React29.createElement("div", { className: "fixed inset-0 z-110 flex items-center justify-center p-4" }, /* @__PURE__ */ React29.createElement("div", { className: "absolute inset-0 bg-black/30", onClick: () => !isDeleting && setMemberToDelete(null) }), /* @__PURE__ */ React29.createElement("div", { className: "relative w-72 bg-white shadow-2xl rounded-2xl flex flex-col items-center overflow-hidden animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ React29.createElement("div", { className: "p-6 text-center w-full" }, /* @__PURE__ */ React29.createElement("h3", { className: "text-[14px] text-black tracking-tight mb-1" }, "Remove Member"), /* @__PURE__ */ React29.createElement("p", { className: "text-[12px] text-neutral-500 leading-snug mt-2" }, "Are you sure you want to remove this member? They will lose access instantly.")), /* @__PURE__ */ React29.createElement("div", { className: "w-full flex" }, /* @__PURE__ */ React29.createElement("button", { onClick: () => setMemberToDelete(null), disabled: isDeleting, className: "flex-1 py-2 text-[13px] text-neutral-600 hover:bg-neutral-50 transition-colors disabled:opacity-50 outline-none" }, "Cancel"), /* @__PURE__ */ React29.createElement("button", { onClick: handleDelete, disabled: isDeleting, className: "flex-1 py-2 text-[13px] text-red-600 hover:bg-neutral-50 transition-colors disabled:opacity-50 flex justify-center outline-none" }, isDeleting ? /* @__PURE__ */ React29.createElement(ButtonSpinner3, null) : "Remove")))));
|
|
1102
2186
|
};
|
|
1103
2187
|
export {
|
|
1104
2188
|
AITranscriptionFeature,
|
|
@@ -1123,5 +2207,12 @@ export {
|
|
|
1123
2207
|
PortfolioHero,
|
|
1124
2208
|
ProductHero,
|
|
1125
2209
|
TextInput,
|
|
1126
|
-
|
|
2210
|
+
ThreeDActionButton,
|
|
2211
|
+
ThreeDButton,
|
|
2212
|
+
UniversalHeader,
|
|
2213
|
+
UniversalIdentityPage,
|
|
2214
|
+
UniversalMembersPage,
|
|
2215
|
+
UniversalOrganizationPage,
|
|
2216
|
+
UniversalSidebar,
|
|
2217
|
+
ZairusAuth
|
|
1127
2218
|
};
|