hazo_auth 1.6.0 → 1.6.2
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/README.md +191 -19
- package/SETUP_CHECKLIST.md +190 -65
- package/dist/app/api/hazo_auth/library_photo/[category]/[filename]/route.d.ts +9 -0
- package/dist/app/api/hazo_auth/library_photo/[category]/[filename]/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/library_photo/[category]/[filename]/route.js +82 -0
- package/dist/app/api/hazo_auth/library_photos/route.d.ts +9 -0
- package/dist/app/api/hazo_auth/library_photos/route.d.ts.map +1 -1
- package/dist/app/api/hazo_auth/library_photos/route.js +31 -6
- package/dist/cli/generate.d.ts +6 -1
- package/dist/cli/generate.d.ts.map +1 -1
- package/dist/cli/generate.js +101 -34
- package/dist/cli/index.js +64 -11
- package/dist/cli/init.d.ts +2 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +206 -0
- package/dist/client.d.ts +8 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +25 -0
- package/dist/components/layouts/email_verification/index.d.ts +2 -1
- package/dist/components/layouts/email_verification/index.d.ts.map +1 -1
- package/dist/components/layouts/email_verification/index.js +3 -2
- package/dist/components/layouts/forgot_password/index.d.ts +3 -1
- package/dist/components/layouts/forgot_password/index.d.ts.map +1 -1
- package/dist/components/layouts/forgot_password/index.js +3 -2
- package/dist/components/layouts/my_settings/components/editable_field.js +1 -1
- package/dist/components/layouts/my_settings/components/password_change_dialog.js +1 -1
- package/dist/components/layouts/my_settings/components/profile_picture_display.js +1 -1
- package/dist/components/layouts/my_settings/components/profile_picture_gravatar_tab.js +1 -1
- package/dist/components/layouts/my_settings/components/profile_picture_library_tab.js +4 -4
- package/dist/components/layouts/my_settings/components/profile_picture_upload_tab.js +4 -4
- package/dist/components/layouts/my_settings/index.js +1 -1
- package/dist/components/layouts/shared/components/profile_pic_menu.js +2 -2
- package/dist/lib/auth_utility_config.server.js +2 -2
- package/dist/lib/services/profile_picture_service.d.ts +34 -2
- package/dist/lib/services/profile_picture_service.d.ts.map +1 -1
- package/dist/lib/services/profile_picture_service.js +157 -15
- package/dist/lib/services/user_profiles_cache.d.ts +76 -0
- package/dist/lib/services/user_profiles_cache.d.ts.map +1 -0
- package/dist/lib/services/user_profiles_cache.js +141 -0
- package/dist/lib/services/user_profiles_service.d.ts +17 -0
- package/dist/lib/services/user_profiles_service.d.ts.map +1 -1
- package/dist/lib/services/user_profiles_service.js +136 -44
- package/dist/lib/user_profiles_config.server.d.ts +15 -0
- package/dist/lib/user_profiles_config.server.d.ts.map +1 -0
- package/dist/lib/user_profiles_config.server.js +23 -0
- package/dist/page_components/forgot_password.d.ts +19 -0
- package/dist/page_components/forgot_password.d.ts.map +1 -0
- package/dist/page_components/forgot_password.js +36 -0
- package/dist/page_components/index.d.ts +7 -0
- package/dist/page_components/index.d.ts.map +1 -0
- package/dist/page_components/index.js +9 -0
- package/dist/page_components/login.d.ts +26 -0
- package/dist/page_components/login.d.ts.map +1 -0
- package/dist/page_components/login.js +40 -0
- package/dist/page_components/my_settings.d.ts +64 -0
- package/dist/page_components/my_settings.d.ts.map +1 -0
- package/dist/page_components/my_settings.js +67 -0
- package/dist/page_components/register.d.ts +25 -0
- package/dist/page_components/register.d.ts.map +1 -0
- package/dist/page_components/register.js +43 -0
- package/dist/page_components/reset_password.d.ts +25 -0
- package/dist/page_components/reset_password.d.ts.map +1 -0
- package/dist/page_components/reset_password.js +43 -0
- package/dist/page_components/verify_email.d.ts +21 -0
- package/dist/page_components/verify_email.d.ts.map +1 -0
- package/dist/page_components/verify_email.js +36 -0
- package/dist/server/routes/index.d.ts +1 -0
- package/dist/server/routes/index.d.ts.map +1 -1
- package/dist/server/routes/index.js +1 -0
- package/dist/server/routes/library_photo.d.ts +2 -0
- package/dist/server/routes/library_photo.d.ts.map +1 -0
- package/dist/server/routes/library_photo.js +3 -0
- package/hazo_auth_config.example.ini +25 -5
- package/package.json +33 -1
package/dist/client.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// file_description: client-safe exports for hazo_auth package
|
|
2
|
+
// This file exports only modules that are safe to use in client components (browser)
|
|
3
|
+
// It excludes any server-side Node.js dependencies (fs, path, database, etc.)
|
|
4
|
+
//
|
|
5
|
+
// USAGE:
|
|
6
|
+
// import { ProfilePicMenu, use_auth_status, cn } from "hazo_auth/client";
|
|
7
|
+
//
|
|
8
|
+
// For server-side code (API routes, Server Components), use:
|
|
9
|
+
// import { hazo_get_auth, get_config_value } from "hazo_auth";
|
|
10
|
+
// section: component_exports
|
|
11
|
+
// All UI and layout components are client-safe
|
|
12
|
+
export * from "./components/index";
|
|
13
|
+
// section: utility_exports
|
|
14
|
+
// CSS utility functions
|
|
15
|
+
export { cn, merge_class_names } from "./lib/utils";
|
|
16
|
+
// section: type_exports
|
|
17
|
+
// Type definitions are always safe (erased at runtime)
|
|
18
|
+
export * from "./lib/auth/auth_types";
|
|
19
|
+
// section: client_hook_exports
|
|
20
|
+
// Re-export from shared hooks (these are already "use client" components)
|
|
21
|
+
export { use_auth_status, trigger_auth_status_refresh } from "./components/layouts/shared/hooks/use_auth_status";
|
|
22
|
+
export { use_hazo_auth, trigger_hazo_auth_refresh } from "./components/layouts/shared/hooks/use_hazo_auth";
|
|
23
|
+
// section: validation_exports
|
|
24
|
+
// Client-side validation utilities
|
|
25
|
+
export * from "./components/layouts/shared/utils/validation";
|
|
@@ -12,6 +12,7 @@ export type EmailVerificationLayoutProps<TClient = unknown> = {
|
|
|
12
12
|
error_labels?: Partial<EmailVerificationErrorLabels>;
|
|
13
13
|
redirect_delay?: number;
|
|
14
14
|
login_path?: string;
|
|
15
|
+
sign_in_label?: string;
|
|
15
16
|
already_logged_in_message?: string;
|
|
16
17
|
showLogoutButton?: boolean;
|
|
17
18
|
showReturnHomeButton?: boolean;
|
|
@@ -19,5 +20,5 @@ export type EmailVerificationLayoutProps<TClient = unknown> = {
|
|
|
19
20
|
returnHomePath?: string;
|
|
20
21
|
data_client: LayoutDataClient<TClient>;
|
|
21
22
|
};
|
|
22
|
-
export default function email_verification_layout<TClient>({ image_src, image_alt, image_background_color, field_overrides, labels, button_colors, success_labels, error_labels, redirect_delay, login_path, data_client, already_logged_in_message, showLogoutButton, showReturnHomeButton, returnHomeButtonLabel, returnHomePath, }: EmailVerificationLayoutProps<TClient>): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
export default function email_verification_layout<TClient>({ image_src, image_alt, image_background_color, field_overrides, labels, button_colors, success_labels, error_labels, redirect_delay, login_path, sign_in_label, data_client, already_logged_in_message, showLogoutButton, showReturnHomeButton, returnHomeButtonLabel, returnHomePath, }: EmailVerificationLayoutProps<TClient>): import("react/jsx-runtime").JSX.Element;
|
|
23
24
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/layouts/email_verification/index.tsx"],"names":[],"mappings":"AAWA,OAAO,EACL,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EAC1B,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAOL,KAAK,8BAA8B,EACnC,KAAK,4BAA4B,EAClC,MAAM,0CAA0C,CAAC;AAKlD,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/layouts/email_verification/index.tsx"],"names":[],"mappings":"AAWA,OAAO,EACL,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EAC1B,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAOL,KAAK,8BAA8B,EACnC,KAAK,4BAA4B,EAClC,MAAM,0CAA0C,CAAC;AAKlD,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAM1E,MAAM,MAAM,4BAA4B,CAAC,OAAO,GAAG,OAAO,IAAI;IAC5D,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,eAAe,CAAC,EAAE,uBAAuB,CAAC;IAC1C,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B,aAAa,CAAC,EAAE,sBAAsB,CAAC;IACvC,cAAc,CAAC,EAAE,OAAO,CAAC,8BAA8B,CAAC,CAAC;IACzD,YAAY,CAAC,EAAE,OAAO,CAAC,4BAA4B,CAAC,CAAC;IACrD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;CACxC,CAAC;AASF,MAAM,CAAC,OAAO,UAAU,yBAAyB,CAAC,OAAO,EAAE,EACzD,SAAS,EACT,SAAS,EACT,sBAAkC,EAClC,eAAe,EACf,MAAM,EACN,aAAa,EACb,cAAc,EACd,YAAY,EACZ,cAAkB,EAClB,UAA+B,EAC/B,aAAyB,EACzB,WAAW,EACX,yBAAyB,EACzB,gBAAuB,EACvB,oBAA4B,EAC5B,qBAAqC,EACrC,cAAoB,GACrB,EAAE,4BAA4B,CAAC,OAAO,CAAC,2CAkOvC"}
|
|
@@ -13,11 +13,12 @@ import { EMAIL_VERIFICATION_FIELD_IDS, createEmailVerificationFieldDefinitions,
|
|
|
13
13
|
import { use_email_verification, } from "./hooks/use_email_verification";
|
|
14
14
|
import { CheckCircle, XCircle, Loader2 } from "lucide-react";
|
|
15
15
|
import { AlreadyLoggedInGuard } from "../shared/components/already_logged_in_guard";
|
|
16
|
+
import Link from "next/link";
|
|
16
17
|
const ORDERED_FIELDS = [
|
|
17
18
|
EMAIL_VERIFICATION_FIELD_IDS.EMAIL,
|
|
18
19
|
];
|
|
19
20
|
// section: component
|
|
20
|
-
export default function email_verification_layout({ image_src, image_alt, image_background_color = "#f1f5f9", field_overrides, labels, button_colors, success_labels, error_labels, redirect_delay = 5, login_path = "/hazo_auth/login", data_client, already_logged_in_message, showLogoutButton = true, showReturnHomeButton = false, returnHomeButtonLabel = "Return home", returnHomePath = "/", }) {
|
|
21
|
+
export default function email_verification_layout({ image_src, image_alt, image_background_color = "#f1f5f9", field_overrides, labels, button_colors, success_labels, error_labels, redirect_delay = 5, login_path = "/hazo_auth/login", sign_in_label = "Sign in", data_client, already_logged_in_message, showLogoutButton = true, showReturnHomeButton = false, returnHomeButtonLabel = "Return home", returnHomePath = "/", }) {
|
|
21
22
|
const fieldDefinitions = createEmailVerificationFieldDefinitions(field_overrides);
|
|
22
23
|
const resolvedLabels = resolveEmailVerificationLabels(labels);
|
|
23
24
|
const resolvedButtonPalette = resolveEmailVerificationButtonPalette(button_colors);
|
|
@@ -57,5 +58,5 @@ export default function email_verification_layout({ image_src, image_alt, image_
|
|
|
57
58
|
}, children: resolvedSuccessLabels.goToLoginButton }) })] }) }) }));
|
|
58
59
|
}
|
|
59
60
|
// Error state with resend form
|
|
60
|
-
return (_jsx(AlreadyLoggedInGuard, { image_src: image_src, image_alt: image_alt, image_background_color: image_background_color, message: already_logged_in_message, showLogoutButton: showLogoutButton, showReturnHomeButton: showReturnHomeButton, returnHomeButtonLabel: returnHomeButtonLabel, returnHomePath: returnHomePath, requireEmailVerified: false, children: _jsx(TwoColumnAuthLayout, { imageSrc: image_src, imageAlt: image_alt, imageBackgroundColor: image_background_color, formContent: _jsxs(_Fragment, { children: [_jsxs("div", { className: "cls_email_verification_error_header flex flex-col items-center gap-4 text-center", children: [_jsx(XCircle, { className: "h-12 w-12 text-red-600", "aria-hidden": "true" }), _jsxs("div", { className: "cls_email_verification_error_text", children: [_jsx("h1", { className: "cls_email_verification_error_heading text-2xl font-semibold text-slate-900", children: resolvedErrorLabels.heading }), _jsx("p", { className: "cls_email_verification_error_message mt-2 text-sm text-slate-600", children: verification.errorMessage || resolvedErrorLabels.message })] })] }), _jsxs("div", { className: "cls_email_verification_resend_form", children: [_jsx(FormHeader, { heading: resolvedErrorLabels.resendFormHeading, subHeading: "Enter your email address to receive a new verification link." }), _jsxs("form", { className: "cls_email_verification_layout_form_fields flex flex-col gap-5", onSubmit: verification.handleResendSubmit, "aria-label": "Resend verification email form", children: [renderFields(verification), _jsx(FormActionButtons, { submitLabel: resolvedLabels.submitButton, cancelLabel: resolvedLabels.cancelButton, buttonPalette: resolvedButtonPalette, isSubmitDisabled: verification.isSubmitDisabled, onCancel: verification.handleCancel, submitAriaLabel: "Submit resend verification email form", cancelAriaLabel: "Cancel resend verification email form" }), verification.isSubmitting && (_jsx("div", { className: "cls_email_verification_submitting_indicator text-sm text-slate-600 text-center", children: "Sending verification email..." }))] })] })] }) }) }));
|
|
61
|
+
return (_jsx(AlreadyLoggedInGuard, { image_src: image_src, image_alt: image_alt, image_background_color: image_background_color, message: already_logged_in_message, showLogoutButton: showLogoutButton, showReturnHomeButton: showReturnHomeButton, returnHomeButtonLabel: returnHomeButtonLabel, returnHomePath: returnHomePath, requireEmailVerified: false, children: _jsx(TwoColumnAuthLayout, { imageSrc: image_src, imageAlt: image_alt, imageBackgroundColor: image_background_color, formContent: _jsxs(_Fragment, { children: [_jsxs("div", { className: "cls_email_verification_error_header flex flex-col items-center gap-4 text-center", children: [_jsx(XCircle, { className: "h-12 w-12 text-red-600", "aria-hidden": "true" }), _jsxs("div", { className: "cls_email_verification_error_text", children: [_jsx("h1", { className: "cls_email_verification_error_heading text-2xl font-semibold text-slate-900", children: resolvedErrorLabels.heading }), _jsx("p", { className: "cls_email_verification_error_message mt-2 text-sm text-slate-600", children: verification.errorMessage || resolvedErrorLabels.message })] })] }), _jsxs("div", { className: "cls_email_verification_resend_form", children: [_jsx(FormHeader, { heading: resolvedErrorLabels.resendFormHeading, subHeading: "Enter your email address to receive a new verification link." }), _jsxs("form", { className: "cls_email_verification_layout_form_fields flex flex-col gap-5", onSubmit: verification.handleResendSubmit, "aria-label": "Resend verification email form", children: [renderFields(verification), _jsx(FormActionButtons, { submitLabel: resolvedLabels.submitButton, cancelLabel: resolvedLabels.cancelButton, buttonPalette: resolvedButtonPalette, isSubmitDisabled: verification.isSubmitDisabled, onCancel: verification.handleCancel, submitAriaLabel: "Submit resend verification email form", cancelAriaLabel: "Cancel resend verification email form" }), verification.isSubmitting && (_jsx("div", { className: "cls_email_verification_submitting_indicator text-sm text-slate-600 text-center", children: "Sending verification email..." }))] }), _jsxs("div", { className: "cls_email_verification_sign_in_link mt-4 text-center text-sm text-slate-600", children: ["Already verified?", " ", _jsx(Link, { href: login_path, className: "font-medium text-slate-900 hover:underline", children: sign_in_label })] })] })] }) }) }));
|
|
61
62
|
}
|
|
@@ -8,11 +8,13 @@ export type ForgotPasswordLayoutProps<TClient = unknown> = {
|
|
|
8
8
|
labels?: LayoutLabelOverrides;
|
|
9
9
|
button_colors?: ButtonPaletteOverrides;
|
|
10
10
|
data_client: LayoutDataClient<TClient>;
|
|
11
|
+
sign_in_path?: string;
|
|
12
|
+
sign_in_label?: string;
|
|
11
13
|
alreadyLoggedInMessage?: string;
|
|
12
14
|
showLogoutButton?: boolean;
|
|
13
15
|
showReturnHomeButton?: boolean;
|
|
14
16
|
returnHomeButtonLabel?: string;
|
|
15
17
|
returnHomePath?: string;
|
|
16
18
|
};
|
|
17
|
-
export default function forgot_password_layout<TClient>({ image_src, image_alt, image_background_color, field_overrides, labels, button_colors, data_client, alreadyLoggedInMessage, showLogoutButton, showReturnHomeButton, returnHomeButtonLabel, returnHomePath, }: ForgotPasswordLayoutProps<TClient>): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export default function forgot_password_layout<TClient>({ image_src, image_alt, image_background_color, field_overrides, labels, button_colors, data_client, sign_in_path, sign_in_label, alreadyLoggedInMessage, showLogoutButton, showReturnHomeButton, returnHomeButtonLabel, returnHomePath, }: ForgotPasswordLayoutProps<TClient>): import("react/jsx-runtime").JSX.Element;
|
|
18
20
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/layouts/forgot_password/index.tsx"],"names":[],"mappings":"AAWA,OAAO,EACL,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EAC1B,MAAM,uCAAuC,CAAC;AAW/C,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/layouts/forgot_password/index.tsx"],"names":[],"mappings":"AAWA,OAAO,EACL,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EAC1B,MAAM,uCAAuC,CAAC;AAW/C,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAI1E,MAAM,MAAM,yBAAyB,CAAC,OAAO,GAAG,OAAO,IAAI;IACzD,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,eAAe,CAAC,EAAE,uBAAuB,CAAC;IAC1C,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B,aAAa,CAAC,EAAE,sBAAsB,CAAC;IACvC,WAAW,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACvC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AASF,MAAM,CAAC,OAAO,UAAU,sBAAsB,CAAC,OAAO,EAAE,EACtD,SAAS,EACT,SAAS,EACT,sBAAkC,EAClC,eAAe,EACf,MAAM,EACN,aAAa,EACb,WAAW,EACX,YAAiC,EACjC,aAAyB,EACzB,sBAAoD,EACpD,gBAAuB,EACvB,oBAA4B,EAC5B,qBAAqC,EACrC,cAAoB,GACrB,EAAE,yBAAyB,CAAC,OAAO,CAAC,2CA+GpC"}
|
|
@@ -11,11 +11,12 @@ import { TwoColumnAuthLayout } from "../shared/components/two_column_auth_layout
|
|
|
11
11
|
import { AlreadyLoggedInGuard } from "../shared/components/already_logged_in_guard";
|
|
12
12
|
import { FORGOT_PASSWORD_FIELD_IDS, createForgotPasswordFieldDefinitions, resolveForgotPasswordButtonPalette, resolveForgotPasswordLabels, } from "./config/forgot_password_field_config";
|
|
13
13
|
import { use_forgot_password_form, } from "./hooks/use_forgot_password_form";
|
|
14
|
+
import Link from "next/link";
|
|
14
15
|
const ORDERED_FIELDS = [
|
|
15
16
|
FORGOT_PASSWORD_FIELD_IDS.EMAIL,
|
|
16
17
|
];
|
|
17
18
|
// section: component
|
|
18
|
-
export default function forgot_password_layout({ image_src, image_alt, image_background_color = "#f1f5f9", field_overrides, labels, button_colors, data_client, alreadyLoggedInMessage = "You are already logged in", showLogoutButton = true, showReturnHomeButton = false, returnHomeButtonLabel = "Return home", returnHomePath = "/", }) {
|
|
19
|
+
export default function forgot_password_layout({ image_src, image_alt, image_background_color = "#f1f5f9", field_overrides, labels, button_colors, data_client, sign_in_path = "/hazo_auth/login", sign_in_label = "Sign in", alreadyLoggedInMessage = "You are already logged in", showLogoutButton = true, showReturnHomeButton = false, returnHomeButtonLabel = "Return home", returnHomePath = "/", }) {
|
|
19
20
|
const fieldDefinitions = createForgotPasswordFieldDefinitions(field_overrides);
|
|
20
21
|
const resolvedLabels = resolveForgotPasswordLabels(labels);
|
|
21
22
|
const resolvedButtonPalette = resolveForgotPasswordButtonPalette(button_colors);
|
|
@@ -39,5 +40,5 @@ export default function forgot_password_layout({ image_src, image_alt, image_bac
|
|
|
39
40
|
return (_jsx(FormFieldWrapper, { fieldId: fieldDefinition.id, label: fieldDefinition.label, input: inputElement, errorMessage: shouldShowError }, fieldId));
|
|
40
41
|
});
|
|
41
42
|
};
|
|
42
|
-
return (_jsx(AlreadyLoggedInGuard, { image_src: image_src, image_alt: image_alt, image_background_color: image_background_color, message: alreadyLoggedInMessage, showLogoutButton: showLogoutButton, showReturnHomeButton: showReturnHomeButton, returnHomeButtonLabel: returnHomeButtonLabel, returnHomePath: returnHomePath, children: _jsx(TwoColumnAuthLayout, { imageSrc: image_src, imageAlt: image_alt, imageBackgroundColor: image_background_color, formContent: _jsxs(_Fragment, { children: [_jsx(FormHeader, { heading: resolvedLabels.heading, subHeading: resolvedLabels.subHeading }), _jsxs("form", { className: "cls_forgot_password_layout_form_fields flex flex-col gap-5", onSubmit: form.handleSubmit, "aria-label": "Forgot password form", children: [renderFields(form), _jsx(FormActionButtons, { submitLabel: resolvedLabels.submitButton, cancelLabel: resolvedLabels.cancelButton, buttonPalette: resolvedButtonPalette, isSubmitDisabled: form.isSubmitDisabled, onCancel: form.handleCancel, submitAriaLabel: "Submit forgot password form", cancelAriaLabel: "Cancel forgot password form" }), form.isSubmitting && (_jsx("div", { className: "cls_forgot_password_submitting_indicator text-sm text-slate-600 text-center", children: "Sending reset link..." }))] })] }) }) }));
|
|
43
|
+
return (_jsx(AlreadyLoggedInGuard, { image_src: image_src, image_alt: image_alt, image_background_color: image_background_color, message: alreadyLoggedInMessage, showLogoutButton: showLogoutButton, showReturnHomeButton: showReturnHomeButton, returnHomeButtonLabel: returnHomeButtonLabel, returnHomePath: returnHomePath, children: _jsx(TwoColumnAuthLayout, { imageSrc: image_src, imageAlt: image_alt, imageBackgroundColor: image_background_color, formContent: _jsxs(_Fragment, { children: [_jsx(FormHeader, { heading: resolvedLabels.heading, subHeading: resolvedLabels.subHeading }), _jsxs("form", { className: "cls_forgot_password_layout_form_fields flex flex-col gap-5", onSubmit: form.handleSubmit, "aria-label": "Forgot password form", children: [renderFields(form), _jsx(FormActionButtons, { submitLabel: resolvedLabels.submitButton, cancelLabel: resolvedLabels.cancelButton, buttonPalette: resolvedButtonPalette, isSubmitDisabled: form.isSubmitDisabled, onCancel: form.handleCancel, submitAriaLabel: "Submit forgot password form", cancelAriaLabel: "Cancel forgot password form" }), form.isSubmitting && (_jsx("div", { className: "cls_forgot_password_submitting_indicator text-sm text-slate-600 text-center", children: "Sending reset link..." }))] }), _jsxs("div", { className: "cls_forgot_password_sign_in_link mt-4 text-center text-sm text-slate-600", children: ["Remember your password?", " ", _jsx(Link, { href: sign_in_path, className: "font-medium text-slate-900 hover:underline", children: sign_in_label })] })] }) }) }));
|
|
43
44
|
}
|
|
@@ -69,5 +69,5 @@ export function EditableField({ label, value, type = "text", placeholder, onSave
|
|
|
69
69
|
handleCancel();
|
|
70
70
|
}
|
|
71
71
|
};
|
|
72
|
-
return (_jsxs("div", { className: "cls_editable_field flex flex-col gap-2", children: [_jsx(Label, { htmlFor: `editable-field-${label}`, className: "cls_editable_field_label text-sm font-medium text-
|
|
72
|
+
return (_jsxs("div", { className: "cls_editable_field flex flex-col gap-2", children: [_jsx(Label, { htmlFor: `editable-field-${label}`, className: "cls_editable_field_label text-sm font-medium text-[var(--hazo-text-secondary)]", children: label }), _jsx("div", { className: "cls_editable_field_input_container flex items-center gap-2", children: isEditing ? (_jsxs(_Fragment, { children: [_jsx(Input, { id: `editable-field-${label}`, type: type, value: editValue, onChange: (e) => setEditValue(e.target.value), onKeyDown: handleKeyDown, placeholder: placeholder, disabled: isSaving, "aria-label": ariaLabel || label, className: "cls_editable_field_input flex-1" }), _jsx(Button, { type: "button", onClick: handleSave, disabled: isSaving, variant: "ghost", size: "icon", className: "cls_editable_field_save_button text-green-600 hover:text-green-700 hover:bg-green-50", "aria-label": "Save changes", children: _jsx(CheckCircle2, { className: "h-5 w-5", "aria-hidden": "true" }) }), _jsx(Button, { type: "button", onClick: handleCancel, disabled: isSaving, variant: "ghost", size: "icon", className: "cls_editable_field_cancel_button text-red-600 hover:text-red-700 hover:bg-red-50", "aria-label": "Cancel editing", children: _jsx(XCircle, { className: "h-5 w-5", "aria-hidden": "true" }) })] })) : (_jsxs(_Fragment, { children: [_jsx(Input, { id: `editable-field-${label}`, type: type, value: value || "", readOnly: true, disabled: true, placeholder: value ? undefined : placeholder || "Not set", "aria-label": ariaLabel || label, className: "cls_editable_field_display flex-1 bg-[var(--hazo-bg-subtle)] cursor-not-allowed" }), !disabled && (_jsx(Button, { type: "button", onClick: handleEdit, variant: "ghost", size: "icon", className: "cls_editable_field_edit_button text-[var(--hazo-text-muted)] hover:text-[var(--hazo-text-secondary)] hover:bg-[var(--hazo-bg-subtle)]", "aria-label": `Edit ${label}`, children: _jsx(Pencil, { className: "h-5 w-5", "aria-hidden": "true" }) }))] })) }), error && (_jsx("p", { className: "cls_editable_field_error text-sm text-red-600", role: "alert", children: error }))] }));
|
|
73
73
|
}
|
|
@@ -123,7 +123,7 @@ export function PasswordChangeDialog({ open, onOpenChange, onSave, passwordRequi
|
|
|
123
123
|
if (errors.newPassword) {
|
|
124
124
|
setErrors(Object.assign(Object.assign({}, errors), { newPassword: undefined }));
|
|
125
125
|
}
|
|
126
|
-
}, onToggleVisibility: () => setNewPasswordVisible(!newPasswordVisible), errorMessage: errors.newPassword }) }), passwordRequirementsList.length > 0 && (_jsxs("div", { className: "cls_password_change_dialog_requirements text-xs text-
|
|
126
|
+
}, onToggleVisibility: () => setNewPasswordVisible(!newPasswordVisible), errorMessage: errors.newPassword }) }), passwordRequirementsList.length > 0 && (_jsxs("div", { className: "cls_password_change_dialog_requirements text-xs text-[var(--hazo-text-muted)]", children: [_jsx("p", { className: "cls_password_change_dialog_requirements_label font-medium mb-1", children: "Password requirements:" }), _jsx("ul", { className: "cls_password_change_dialog_requirements_list list-disc list-inside space-y-0.5", children: passwordRequirementsList.map((req, index) => (_jsx("li", { children: req }, index))) })] })), _jsx(FormFieldWrapper, { fieldId: "confirm-password", label: confirmPasswordLabel, input: _jsx(PasswordField, { inputId: "confirm-password", ariaLabel: confirmPasswordLabel, value: confirmPassword, placeholder: "Confirm your new password", autoComplete: "new-password", isVisible: confirmPasswordVisible, onChange: (value) => {
|
|
127
127
|
setConfirmPassword(value);
|
|
128
128
|
if (errors.confirmPassword) {
|
|
129
129
|
setErrors(Object.assign(Object.assign({}, errors), { confirmPassword: undefined }));
|
|
@@ -29,5 +29,5 @@ export function ProfilePictureDisplay({ profilePictureUrl, name, email, onEdit,
|
|
|
29
29
|
return "?";
|
|
30
30
|
};
|
|
31
31
|
const initials = getInitials();
|
|
32
|
-
return (_jsx("div", { className: "cls_profile_picture_display", children: _jsxs(Avatar, { className: "cls_profile_picture_display_avatar h-32 w-32", children: [_jsx(AvatarImage, { src: profilePictureUrl, alt: name ? `Profile picture of ${name}` : "Profile picture", className: "cls_profile_picture_display_image" }), _jsx(AvatarFallback, { className: "cls_profile_picture_display_fallback bg-
|
|
32
|
+
return (_jsx("div", { className: "cls_profile_picture_display", children: _jsxs(Avatar, { className: "cls_profile_picture_display_avatar h-32 w-32", children: [_jsx(AvatarImage, { src: profilePictureUrl, alt: name ? `Profile picture of ${name}` : "Profile picture", className: "cls_profile_picture_display_image" }), _jsx(AvatarFallback, { className: "cls_profile_picture_display_fallback bg-[var(--hazo-bg-emphasis)] text-[var(--hazo-text-muted)] text-3xl", children: initials })] }) }));
|
|
33
33
|
}
|
|
@@ -44,5 +44,5 @@ export function ProfilePictureGravatarTab({ email, useGravatar, onUseGravatarCha
|
|
|
44
44
|
}
|
|
45
45
|
return "?";
|
|
46
46
|
};
|
|
47
|
-
return (_jsxs("div", { className: "cls_profile_picture_gravatar_tab flex flex-col gap-4", children: [_jsxs("div", { className: "cls_profile_picture_gravatar_tab_switch flex items-center gap-3", children: [_jsx(Switch, { id: "use-gravatar", checked: useGravatar, onCheckedChange: onUseGravatarChange, disabled: disabled, className: "cls_profile_picture_gravatar_tab_switch_input", "aria-label": "Use Gravatar photo" }), _jsx(Label, { htmlFor: "use-gravatar", className: "cls_profile_picture_gravatar_tab_switch_label text-sm font-medium text-
|
|
47
|
+
return (_jsxs("div", { className: "cls_profile_picture_gravatar_tab flex flex-col gap-4", children: [_jsxs("div", { className: "cls_profile_picture_gravatar_tab_switch flex items-center gap-3", children: [_jsx(Switch, { id: "use-gravatar", checked: useGravatar, onCheckedChange: onUseGravatarChange, disabled: disabled, className: "cls_profile_picture_gravatar_tab_switch_input", "aria-label": "Use Gravatar photo" }), _jsx(Label, { htmlFor: "use-gravatar", className: "cls_profile_picture_gravatar_tab_switch_label text-sm font-medium text-[var(--hazo-text-secondary)] cursor-pointer", children: "Use Gravatar photo" })] }), _jsx("div", { className: "cls_profile_picture_gravatar_tab_preview flex flex-col items-center gap-4 p-6 border border-[var(--hazo-border)] rounded-lg bg-[var(--hazo-bg-subtle)]", children: gravatarExists === true ? (_jsxs(_Fragment, { children: [_jsxs(Avatar, { className: "cls_profile_picture_gravatar_tab_avatar h-32 w-32", children: [_jsx(AvatarImage, { src: gravatarUrlState, alt: "Gravatar profile picture", className: "cls_profile_picture_gravatar_tab_avatar_image" }), _jsx(AvatarFallback, { className: "cls_profile_picture_gravatar_tab_avatar_fallback bg-[var(--hazo-bg-emphasis)] text-[var(--hazo-text-muted)] text-3xl", children: getInitials() })] }), _jsx("p", { className: "cls_profile_picture_gravatar_tab_success_text text-sm text-[var(--hazo-text-muted)] text-center", children: "Your Gravatar is available and will be used as your profile picture." })] })) : gravatarExists === false ? (_jsx(_Fragment, { children: _jsxs("div", { className: "cls_profile_picture_gravatar_tab_no_gravatar flex flex-col items-center gap-4", children: [_jsx("div", { className: "cls_profile_picture_gravatar_tab_no_gravatar_icon flex items-center justify-center w-16 h-16 rounded-full bg-[var(--hazo-bg-muted)]", children: _jsx(Info, { className: "h-8 w-8 text-[var(--hazo-text-subtle)]", "aria-hidden": "true" }) }), _jsxs("div", { className: "cls_profile_picture_gravatar_tab_no_gravatar_content flex flex-col gap-2 text-center", children: [_jsx("p", { className: "cls_profile_picture_gravatar_tab_no_gravatar_title text-sm font-medium text-[var(--hazo-text-primary)]", children: "No Gravatar found" }), _jsxs("p", { className: "cls_profile_picture_gravatar_tab_no_gravatar_message text-sm text-[var(--hazo-text-muted)]", children: [gravatarSetupMessage, " ", _jsx("span", { className: "font-semibold", children: email }), ":"] }), _jsxs("ol", { className: "cls_profile_picture_gravatar_tab_no_gravatar_steps text-sm text-[var(--hazo-text-muted)] list-decimal list-inside space-y-1 mt-2", children: [_jsxs("li", { children: ["Visit ", _jsx("a", { href: "https://gravatar.com", target: "_blank", rel: "noopener noreferrer", className: "text-blue-600 hover:text-blue-700 underline", children: "gravatar.com" })] }), _jsxs("li", { children: ["Sign up or log in with your email: ", _jsx("span", { className: "font-mono text-xs", children: email })] }), _jsx("li", { children: "Upload a profile picture" }), _jsx("li", { children: "Return here and refresh to see your Gravatar" })] })] })] }) })) : (_jsx(_Fragment, { children: _jsx("div", { className: "cls_profile_picture_gravatar_tab_loading flex items-center justify-center", children: _jsx("p", { className: "cls_profile_picture_gravatar_tab_loading_text text-sm text-[var(--hazo-text-muted)]", children: "Checking Gravatar..." }) }) })) })] }));
|
|
48
48
|
}
|
|
@@ -124,15 +124,15 @@ export function ProfilePictureLibraryTab({ useLibrary, onUseLibraryChange, onPho
|
|
|
124
124
|
};
|
|
125
125
|
return columnMap[columns] || "grid-cols-4";
|
|
126
126
|
};
|
|
127
|
-
return (_jsxs("div", { className: "cls_profile_picture_library_tab flex flex-col gap-4", children: [_jsxs("div", { className: "cls_profile_picture_library_tab_switch flex items-center gap-3", children: [_jsx(Switch, { id: "use-library", checked: useLibrary, onCheckedChange: onUseLibraryChange, disabled: disabled, className: "cls_profile_picture_library_tab_switch_input", "aria-label": "Use library photo" }), _jsxs(Label, { htmlFor: "use-library", className: "cls_profile_picture_library_tab_switch_label text-sm font-medium text-
|
|
127
|
+
return (_jsxs("div", { className: "cls_profile_picture_library_tab flex flex-col gap-4", children: [_jsxs("div", { className: "cls_profile_picture_library_tab_switch flex items-center gap-3", children: [_jsx(Switch, { id: "use-library", checked: useLibrary, onCheckedChange: onUseLibraryChange, disabled: disabled, className: "cls_profile_picture_library_tab_switch_input", "aria-label": "Use library photo" }), _jsxs(Label, { htmlFor: "use-library", className: "cls_profile_picture_library_tab_switch_label text-sm font-medium text-[var(--hazo-text-secondary)] cursor-pointer", children: ["Use library photo", _jsx(HazoUITooltip, { message: libraryTooltipMessage, iconSize: tooltipIconSizeSmall, side: "top" })] })] }), _jsxs("div", { className: "cls_profile_picture_library_tab_content grid grid-cols-12 gap-4", children: [_jsxs("div", { className: "cls_profile_picture_library_tab_categories_container flex flex-col gap-2 col-span-3", children: [_jsx(Label, { className: "cls_profile_picture_library_tab_categories_label text-sm font-medium text-[var(--hazo-text-secondary)]", children: "Categories" }), loadingCategories ? (_jsx("div", { className: "cls_profile_picture_library_tab_loading flex items-center justify-center p-8 border border-[var(--hazo-border)] rounded-lg bg-[var(--hazo-bg-subtle)] min-h-[400px]", children: _jsx(Loader2, { className: "h-6 w-6 text-[var(--hazo-text-subtle)] animate-spin", "aria-hidden": "true" }) })) : categories.length > 0 ? (_jsx(VerticalTabs, { value: selectedCategory || categories[0], onValueChange: setSelectedCategory, className: "cls_profile_picture_library_tab_vertical_tabs", children: _jsx(VerticalTabsList, { className: "cls_profile_picture_library_tab_vertical_tabs_list w-full", children: categories.map((category) => (_jsx(VerticalTabsTrigger, { value: category, className: "cls_profile_picture_library_tab_vertical_tabs_trigger w-full justify-start", children: category }, category))) }) })) : (_jsx("div", { className: "cls_profile_picture_library_tab_no_categories flex items-center justify-center p-8 border border-[var(--hazo-border)] rounded-lg bg-[var(--hazo-bg-subtle)] min-h-[400px]", children: _jsx("p", { className: "cls_profile_picture_library_tab_no_categories_text text-sm text-[var(--hazo-text-muted)]", children: "No categories available" }) }))] }), _jsxs("div", { className: "cls_profile_picture_library_tab_photos_container flex flex-col gap-2 col-span-6", children: [_jsx(Label, { className: "cls_profile_picture_library_tab_photos_label text-sm font-medium text-[var(--hazo-text-secondary)]", children: "Photos" }), loadingPhotos ? (_jsx("div", { className: "cls_profile_picture_library_tab_photos_loading flex items-center justify-center p-8 border border-[var(--hazo-border)] rounded-lg bg-[var(--hazo-bg-subtle)] min-h-[400px]", children: _jsx(Loader2, { className: "h-6 w-6 text-[var(--hazo-text-subtle)] animate-spin", "aria-hidden": "true" }) })) : photos.length > 0 ? (_jsx("div", { className: `cls_profile_picture_library_tab_photos_grid grid ${getGridColumnsClass(libraryPhotoGridColumns)} gap-3 overflow-y-auto p-4 border border-[var(--hazo-border)] rounded-lg bg-[var(--hazo-bg-subtle)] min-h-[400px] max-h-[400px]`, children: photos.map((photoUrl) => (_jsx("button", { type: "button", onClick: () => handlePhotoClick(photoUrl), className: `
|
|
128
128
|
cls_profile_picture_library_tab_photo_thumbnail
|
|
129
129
|
aspect-square rounded-lg overflow-hidden border-2 transition-colors cursor-pointer
|
|
130
|
-
${selectedPhoto === photoUrl ? "border-blue-500 ring-2 ring-blue-200" : "border-
|
|
130
|
+
${selectedPhoto === photoUrl ? "border-blue-500 ring-2 ring-blue-200" : "border-[var(--hazo-border)] hover:border-[var(--hazo-border-emphasis)]"}
|
|
131
131
|
`, "aria-label": `Select photo ${photoUrl.split('/').pop()}`, children: _jsx("img", { src: photoUrl, alt: `Library photo ${photoUrl.split('/').pop()}`, className: "cls_profile_picture_library_tab_photo_thumbnail_image w-full h-full object-cover", loading: "lazy", onError: (e) => {
|
|
132
132
|
// Fallback if image fails to load
|
|
133
133
|
const target = e.target;
|
|
134
134
|
target.style.display = 'none';
|
|
135
|
-
} }) }, photoUrl))) })) : (_jsx("div", { className: "cls_profile_picture_library_tab_no_photos flex items-center justify-center p-8 border border-
|
|
135
|
+
} }) }, photoUrl))) })) : (_jsx("div", { className: "cls_profile_picture_library_tab_no_photos flex items-center justify-center p-8 border border-[var(--hazo-border)] rounded-lg bg-[var(--hazo-bg-subtle)] min-h-[400px]", children: _jsx("p", { className: "cls_profile_picture_library_tab_no_photos_text text-sm text-[var(--hazo-text-muted)]", children: "No photos in this category" }) }))] }), _jsxs("div", { className: "cls_profile_picture_library_tab_preview_container flex flex-col gap-2 col-span-3", children: [_jsx(Label, { className: "cls_profile_picture_library_tab_preview_label text-sm font-medium text-[var(--hazo-text-secondary)]", children: "Preview" }), selectedPhoto ? (_jsxs("div", { className: "cls_profile_picture_library_tab_preview flex flex-col items-center gap-4 p-4 border border-[var(--hazo-border)] rounded-lg bg-[var(--hazo-bg-subtle)] min-h-[400px] justify-center", children: [_jsx("div", { className: "cls_profile_picture_library_tab_preview_image_wrapper w-full flex items-center justify-center", children: _jsx("img", { src: selectedPhoto, alt: "Selected library photo preview", className: "cls_profile_picture_library_tab_preview_image max-w-full max-h-[350px] rounded-lg object-contain", onError: (e) => {
|
|
136
136
|
// Fallback if preview image fails to load
|
|
137
137
|
const target = e.target;
|
|
138
138
|
target.style.display = 'none';
|
|
@@ -140,5 +140,5 @@ export function ProfilePictureLibraryTab({ useLibrary, onUseLibraryChange, onPho
|
|
|
140
140
|
if (wrapper) {
|
|
141
141
|
wrapper.innerHTML = '<p class="text-sm text-red-500">Failed to load preview</p>';
|
|
142
142
|
}
|
|
143
|
-
} }) }), _jsx("p", { className: "cls_profile_picture_library_tab_preview_text text-sm text-
|
|
143
|
+
} }) }), _jsx("p", { className: "cls_profile_picture_library_tab_preview_text text-sm text-[var(--hazo-text-muted)] text-center", children: "Selected photo preview" })] })) : (_jsxs("div", { className: "cls_profile_picture_library_tab_preview_empty flex flex-col items-center justify-center gap-2 p-8 border border-[var(--hazo-border)] rounded-lg bg-[var(--hazo-bg-subtle)] min-h-[400px]", children: [_jsx(Avatar, { className: "cls_profile_picture_library_tab_preview_empty_avatar h-32 w-32", children: _jsx(AvatarFallback, { className: "cls_profile_picture_library_tab_preview_empty_avatar_fallback bg-[var(--hazo-bg-emphasis)] text-[var(--hazo-text-muted)] text-3xl", children: getInitials() }) }), _jsx("p", { className: "cls_profile_picture_library_tab_preview_empty_text text-sm text-[var(--hazo-text-muted)] text-center", children: "Select a photo to see preview" })] }))] })] })] }));
|
|
144
144
|
}
|
|
@@ -153,17 +153,17 @@ allowedImageMimeTypes = ["image/jpeg", "image/jpg", "image/png"], }) {
|
|
|
153
153
|
const getInitials = () => {
|
|
154
154
|
return "U";
|
|
155
155
|
};
|
|
156
|
-
return (_jsxs("div", { className: "cls_profile_picture_upload_tab flex flex-col gap-4", children: [_jsxs("div", { className: "cls_profile_picture_upload_tab_switch flex items-center gap-3", children: [_jsx(Switch, { id: "use-upload", checked: useUpload, onCheckedChange: onUseUploadChange, disabled: disabled || !uploadEnabled, className: "cls_profile_picture_upload_tab_switch_input", "aria-label": "Use uploaded photo" }), _jsx(Label, { htmlFor: "use-upload", className: "cls_profile_picture_upload_tab_switch_label text-sm font-medium text-
|
|
156
|
+
return (_jsxs("div", { className: "cls_profile_picture_upload_tab flex flex-col gap-4", children: [_jsxs("div", { className: "cls_profile_picture_upload_tab_switch flex items-center gap-3", children: [_jsx(Switch, { id: "use-upload", checked: useUpload, onCheckedChange: onUseUploadChange, disabled: disabled || !uploadEnabled, className: "cls_profile_picture_upload_tab_switch_input", "aria-label": "Use uploaded photo" }), _jsx(Label, { htmlFor: "use-upload", className: "cls_profile_picture_upload_tab_switch_label text-sm font-medium text-[var(--hazo-text-secondary)] cursor-pointer", children: "Use uploaded photo" })] }), !uploadEnabled && (_jsxs("div", { className: "cls_profile_picture_upload_tab_disabled flex items-center gap-2 p-3 bg-yellow-50 border border-yellow-200 rounded-lg", children: [_jsx(Info, { className: "h-4 w-4 text-yellow-600", "aria-hidden": "true" }), _jsx("p", { className: "cls_profile_picture_upload_tab_disabled_text text-sm text-yellow-800", children: photoUploadDisabledMessage })] })), _jsxs("div", { className: "cls_profile_picture_upload_tab_content grid grid-cols-1 md:grid-cols-2 gap-6", children: [_jsxs("div", { className: "cls_profile_picture_upload_tab_dropzone_container flex flex-col gap-2", children: [_jsx(Label, { className: "cls_profile_picture_upload_tab_dropzone_label text-sm font-medium text-[var(--hazo-text-secondary)]", children: "Upload Photo" }), _jsxs("div", { className: `
|
|
157
157
|
cls_profile_picture_upload_tab_dropzone
|
|
158
158
|
flex flex-col items-center justify-center
|
|
159
159
|
border-2 border-dashed rounded-lg p-8
|
|
160
160
|
transition-colors
|
|
161
|
-
${dragActive ? "border-blue-500 bg-blue-50" : "border-
|
|
162
|
-
${disabled || !uploadEnabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer hover:border-
|
|
161
|
+
${dragActive ? "border-blue-500 bg-blue-50" : "border-[var(--hazo-border-emphasis)] bg-[var(--hazo-bg-subtle)]"}
|
|
162
|
+
${disabled || !uploadEnabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer hover:border-[var(--hazo-border-emphasis)]"}
|
|
163
163
|
`, onDragEnter: handleDrag, onDragLeave: handleDrag, onDragOver: handleDrag, onDrop: handleDrop, onClick: () => {
|
|
164
164
|
var _a;
|
|
165
165
|
if (!disabled && uploadEnabled) {
|
|
166
166
|
(_a = document.getElementById("file-upload-input")) === null || _a === void 0 ? void 0 : _a.click();
|
|
167
167
|
}
|
|
168
|
-
}, children: [_jsx("input", { id: "file-upload-input", type: "file", accept: allowedImageMimeTypes.join(","), onChange: handleChange, disabled: disabled || !uploadEnabled, className: "hidden", "aria-label": "Upload profile picture" }), _jsx(Upload, { className: "h-8 w-8 text-
|
|
168
|
+
}, children: [_jsx("input", { id: "file-upload-input", type: "file", accept: allowedImageMimeTypes.join(","), onChange: handleChange, disabled: disabled || !uploadEnabled, className: "hidden", "aria-label": "Upload profile picture" }), _jsx(Upload, { className: "h-8 w-8 text-[var(--hazo-text-subtle)] mb-2", "aria-hidden": "true" }), _jsx("p", { className: "cls_profile_picture_upload_tab_dropzone_text text-sm text-[var(--hazo-text-muted)] text-center", children: "Drag and drop an image here, or click to select" }), _jsxs("p", { className: "cls_profile_picture_upload_tab_dropzone_hint text-xs text-[var(--hazo-text-muted)] text-center mt-1", children: ["JPG or PNG, max ", Math.round(maxSize / 1024), "KB"] })] }), error && (_jsx("p", { className: "cls_profile_picture_upload_tab_error text-sm text-red-600", role: "alert", children: error }))] }), _jsxs("div", { className: "cls_profile_picture_upload_tab_preview_container flex flex-col gap-2", children: [_jsx(Label, { className: "cls_profile_picture_upload_tab_preview_label text-sm font-medium text-[var(--hazo-text-secondary)]", children: isNewImage ? "Preview (new)" : "Preview (current)" }), _jsx("div", { className: "cls_profile_picture_upload_tab_preview_content flex flex-col items-center justify-center border border-[var(--hazo-border)] rounded-lg p-6 bg-[var(--hazo-bg-subtle)] min-h-[200px]", children: compressing ? (_jsxs("div", { className: "cls_profile_picture_upload_tab_compressing flex flex-col items-center gap-2", children: [_jsx(Loader2, { className: "h-8 w-8 text-[var(--hazo-text-subtle)] animate-spin", "aria-hidden": "true" }), _jsx("p", { className: "cls_profile_picture_upload_tab_compressing_text text-sm text-[var(--hazo-text-muted)]", children: "Compressing image..." })] })) : uploading ? (_jsxs("div", { className: "cls_profile_picture_upload_tab_uploading flex flex-col items-center gap-2", children: [_jsx(Loader2, { className: "h-8 w-8 text-[var(--hazo-text-subtle)] animate-spin", "aria-hidden": "true" }), _jsx("p", { className: "cls_profile_picture_upload_tab_uploading_text text-sm text-[var(--hazo-text-muted)]", children: "Uploading..." })] })) : preview ? (_jsxs("div", { className: "cls_profile_picture_upload_tab_preview_image_container flex flex-col items-center gap-4", children: [_jsxs("div", { className: "cls_profile_picture_upload_tab_preview_image_wrapper relative", children: [_jsxs(Avatar, { className: "cls_profile_picture_upload_tab_preview_avatar h-32 w-32", children: [_jsx(AvatarImage, { src: preview, alt: "Uploaded profile picture preview", className: "cls_profile_picture_upload_tab_preview_avatar_image" }), _jsx(AvatarFallback, { className: "cls_profile_picture_upload_tab_preview_avatar_fallback bg-[var(--hazo-bg-emphasis)] text-[var(--hazo-text-muted)] text-3xl", children: getInitials() })] }), _jsx(Button, { type: "button", onClick: handleRemove, variant: "ghost", size: "icon", className: "cls_profile_picture_upload_tab_preview_remove absolute -top-2 -right-2 rounded-full h-6 w-6 border border-[var(--hazo-border-emphasis)] bg-white hover:bg-[var(--hazo-bg-subtle)]", "aria-label": "Remove preview", children: _jsx(X, { className: "h-4 w-4", "aria-hidden": "true" }) })] }), _jsx("p", { className: "cls_profile_picture_upload_tab_preview_success_text text-sm text-[var(--hazo-text-muted)] text-center", children: "Preview of your uploaded photo" })] })) : (_jsxs("div", { className: "cls_profile_picture_upload_tab_preview_empty flex flex-col items-center gap-2", children: [_jsx(Avatar, { className: "cls_profile_picture_upload_tab_preview_empty_avatar h-32 w-32", children: _jsx(AvatarFallback, { className: "cls_profile_picture_upload_tab_preview_empty_avatar_fallback bg-[var(--hazo-bg-emphasis)] text-[var(--hazo-text-muted)] text-3xl", children: getInitials() }) }), _jsx("p", { className: "cls_profile_picture_upload_tab_preview_empty_text text-sm text-[var(--hazo-text-muted)] text-center", children: "Upload an image to see preview" })] })) })] })] })] }));
|
|
169
169
|
}
|
|
@@ -28,7 +28,7 @@ export default function my_settings_layout({ labels, button_colors, password_req
|
|
|
28
28
|
const settings = use_my_settings({
|
|
29
29
|
passwordRequirements: password_requirements,
|
|
30
30
|
});
|
|
31
|
-
return (_jsx(UnauthorizedGuard, { message: unauthorizedMessage, loginButtonLabel: loginButtonLabel, loginPath: loginPath, children: _jsxs("div", { className: "cls_my_settings_layout flex flex-col gap-6 p-6 max-w-4xl mx-auto min-h-screen bg-
|
|
31
|
+
return (_jsx(UnauthorizedGuard, { message: unauthorizedMessage, loginButtonLabel: loginButtonLabel, loginPath: loginPath, children: _jsxs("div", { className: "cls_my_settings_layout flex flex-col gap-6 p-6 max-w-4xl mx-auto min-h-screen bg-[var(--hazo-bg-subtle)]", children: [_jsxs("div", { className: "cls_my_settings_layout_header flex flex-col gap-2", children: [_jsx("h1", { className: "cls_my_settings_layout_heading text-3xl font-bold text-[var(--hazo-text-primary)]", children: heading }), _jsx("p", { className: "cls_my_settings_layout_subheading text-[var(--hazo-text-muted)]", children: subHeading })] }), _jsxs("div", { className: "cls_my_settings_layout_profile_photo_section bg-white rounded-lg border border-[var(--hazo-border)] p-6", children: [_jsx("h2", { className: "cls_my_settings_layout_section_heading text-lg font-semibold text-[var(--hazo-text-primary)] mb-4", children: profilePhotoLabel }), _jsx("div", { className: "cls_my_settings_layout_profile_photo_content flex flex-col items-center", children: _jsxs("div", { className: "cls_my_settings_layout_profile_photo_display relative", children: [_jsx(ProfilePictureDisplay, { profilePictureUrl: settings.profilePictureUrl, name: settings.name, email: settings.email, onEdit: settings.handleProfilePictureEdit }), _jsxs("div", { className: "cls_my_settings_layout_profile_photo_actions absolute left-0 right-0 flex items-center justify-between px-2", style: { bottom: '-20px' }, children: [_jsx(Button, { type: "button", onClick: settings.handleProfilePictureEdit, disabled: settings.loading, variant: "ghost", size: "icon", className: "cls_my_settings_layout_upload_photo_button", "aria-label": uploadPhotoButtonLabel, children: _jsx(Pencil, { className: "h-4 w-4", "aria-hidden": "true" }) }), _jsx(Button, { type: "button", onClick: settings.handleProfilePictureRemove, disabled: settings.loading || !settings.profilePictureUrl, variant: "ghost", size: "icon", className: "cls_my_settings_layout_remove_photo_button text-red-600 hover:text-red-700 hover:bg-red-50", "aria-label": removePhotoButtonLabel, children: _jsx(Trash2, { className: "h-4 w-4", "aria-hidden": "true" }) })] })] }) })] }), _jsxs("div", { className: "cls_my_settings_layout_profile_information_section bg-white rounded-lg border border-[var(--hazo-border)] p-6", children: [_jsx("h2", { className: "cls_my_settings_layout_section_heading text-lg font-semibold text-[var(--hazo-text-primary)] mb-4", children: profileInformationLabel }), _jsxs("div", { className: "cls_my_settings_layout_profile_information_fields grid grid-cols-1 md:grid-cols-2 gap-6", children: [userFields.show_name_field && (_jsx(EditableField, { label: "Full Name", value: settings.name, type: "text", placeholder: "Enter your full name", onSave: settings.handleNameSave, validation: validateName, disabled: settings.loading, ariaLabel: "Full name input field" })), userFields.show_email_field && (_jsx(EditableField, { label: "Email Address", value: settings.email, type: "email", placeholder: "Enter your email address", onSave: settings.handleEmailSave, validation: validateEmail, disabled: settings.loading, ariaLabel: "Email address input field" }))] })] }), userFields.show_password_field && (_jsxs("div", { className: "cls_my_settings_layout_password_section bg-white rounded-lg border border-[var(--hazo-border)] p-6", children: [_jsx("h2", { className: "cls_my_settings_layout_section_heading text-lg font-semibold text-[var(--hazo-text-primary)] mb-4", children: passwordLabel }), _jsxs("div", { className: "cls_my_settings_layout_password_fields flex flex-col gap-6", children: [_jsx(FormFieldWrapper, { fieldId: "current-password", label: currentPasswordLabel, input: _jsx(PasswordField, { inputId: "current-password", ariaLabel: currentPasswordLabel, value: ((_a = settings.passwordFields) === null || _a === void 0 ? void 0 : _a.currentPassword) || "", placeholder: "Enter your current password", autoComplete: "current-password", isVisible: ((_b = settings.passwordFields) === null || _b === void 0 ? void 0 : _b.currentPasswordVisible) || false, onChange: (value) => settings.handlePasswordFieldChange("currentPassword", value), onToggleVisibility: () => settings.togglePasswordVisibility("currentPassword"), errorMessage: (_d = (_c = settings.passwordFields) === null || _c === void 0 ? void 0 : _c.errors) === null || _d === void 0 ? void 0 : _d.currentPassword }) }), _jsxs("div", { className: "cls_my_settings_layout_password_fields_row grid grid-cols-1 md:grid-cols-2 gap-6", children: [_jsx(FormFieldWrapper, { fieldId: "new-password", label: newPasswordLabel, input: _jsx(PasswordField, { inputId: "new-password", ariaLabel: newPasswordLabel, value: ((_e = settings.passwordFields) === null || _e === void 0 ? void 0 : _e.newPassword) || "", placeholder: "Enter your new password", autoComplete: "new-password", isVisible: ((_f = settings.passwordFields) === null || _f === void 0 ? void 0 : _f.newPasswordVisible) || false, onChange: (value) => settings.handlePasswordFieldChange("newPassword", value), onToggleVisibility: () => settings.togglePasswordVisibility("newPassword"), errorMessage: (_h = (_g = settings.passwordFields) === null || _g === void 0 ? void 0 : _g.errors) === null || _h === void 0 ? void 0 : _h.newPassword }) }), _jsx(FormFieldWrapper, { fieldId: "confirm-password", label: confirmPasswordLabel, input: _jsx(PasswordField, { inputId: "confirm-password", ariaLabel: confirmPasswordLabel, value: ((_j = settings.passwordFields) === null || _j === void 0 ? void 0 : _j.confirmPassword) || "", placeholder: "Confirm your new password", autoComplete: "new-password", isVisible: ((_k = settings.passwordFields) === null || _k === void 0 ? void 0 : _k.confirmPasswordVisible) || false, onChange: (value) => settings.handlePasswordFieldChange("confirmPassword", value), onToggleVisibility: () => settings.togglePasswordVisibility("confirmPassword"), errorMessage: (_m = (_l = settings.passwordFields) === null || _l === void 0 ? void 0 : _l.errors) === null || _m === void 0 ? void 0 : _m.confirmPassword }) })] })] }), _jsx("div", { className: "cls_my_settings_layout_password_actions flex justify-end mt-4", children: _jsx(Button, { type: "button", onClick: settings.handlePasswordSave, disabled: settings.loading || settings.isPasswordSaveDisabled, className: "cls_my_settings_layout_save_password_button", style: {
|
|
32
32
|
backgroundColor: resolvedButtonPalette.submitBackground,
|
|
33
33
|
color: resolvedButtonPalette.submitText,
|
|
34
34
|
}, "aria-label": "Save password", children: "Save Password" }) })] })), _jsx(ProfilePictureDialog, { open: settings.profilePictureDialogOpen, onOpenChange: (open) => {
|
|
@@ -138,14 +138,14 @@ export function ProfilePicMenu({ show_single_button = false, sign_up_label = "Si
|
|
|
138
138
|
};
|
|
139
139
|
// Show loading state
|
|
140
140
|
if (authStatus.loading) {
|
|
141
|
-
return (_jsx("div", { className: `cls_profile_pic_menu ${className || ""}`, children: _jsx("div", { className: "h-10 w-10 rounded-full bg-
|
|
141
|
+
return (_jsx("div", { className: `cls_profile_pic_menu ${className || ""}`, children: _jsx("div", { className: "h-10 w-10 rounded-full bg-[var(--hazo-bg-emphasis)] animate-pulse" }) }));
|
|
142
142
|
}
|
|
143
143
|
// Not authenticated - show sign up/sign in buttons
|
|
144
144
|
if (!authStatus.authenticated) {
|
|
145
145
|
return (_jsx("div", { className: `cls_profile_pic_menu flex items-center gap-2 ${className || ""}`, children: show_single_button ? (_jsx(Button, { asChild: true, variant: "default", size: "sm", children: _jsx(Link, { href: register_path, className: "cls_profile_pic_menu_sign_up", children: sign_up_label }) })) : (_jsxs(_Fragment, { children: [_jsx(Button, { asChild: true, variant: "outline", size: "sm", children: _jsx(Link, { href: register_path, className: "cls_profile_pic_menu_sign_up", children: sign_up_label }) }), _jsx(Button, { asChild: true, variant: "default", size: "sm", children: _jsx(Link, { href: login_path, className: "cls_profile_pic_menu_sign_in", children: sign_in_label }) })] })) }));
|
|
146
146
|
}
|
|
147
147
|
// Authenticated - show profile picture with dropdown menu
|
|
148
|
-
return (_jsx("div", { className: `cls_profile_pic_menu ${className || ""}`, children: _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx("button", { className: "cls_profile_pic_menu_trigger focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary rounded-full", "aria-label": "Profile menu", children: _jsxs(Avatar, { className: `cls_profile_pic_menu_avatar ${avatarSizeClasses[avatar_size]} cursor-pointer`, children: [_jsx(AvatarImage, { src: authStatus.profile_picture_url, alt: authStatus.name ? `Profile picture of ${authStatus.name}` : "Profile picture", className: "cls_profile_pic_menu_image" }), _jsx(AvatarFallback, { className: "cls_profile_pic_menu_fallback bg-
|
|
148
|
+
return (_jsx("div", { className: `cls_profile_pic_menu ${className || ""}`, children: _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx("button", { className: "cls_profile_pic_menu_trigger focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary rounded-full", "aria-label": "Profile menu", children: _jsxs(Avatar, { className: `cls_profile_pic_menu_avatar ${avatarSizeClasses[avatar_size]} cursor-pointer`, children: [_jsx(AvatarImage, { src: authStatus.profile_picture_url, alt: authStatus.name ? `Profile picture of ${authStatus.name}` : "Profile picture", className: "cls_profile_pic_menu_image" }), _jsx(AvatarFallback, { className: "cls_profile_pic_menu_fallback bg-[var(--hazo-bg-emphasis)] text-[var(--hazo-text-muted)]", children: getInitials() })] }) }) }), _jsx(DropdownMenuContent, { align: "end", className: "cls_profile_pic_menu_dropdown w-56", children: menuItems.map((item) => {
|
|
149
149
|
if (item.type === "separator") {
|
|
150
150
|
return _jsx(DropdownMenuSeparator, { className: "cls_profile_pic_menu_separator" }, item.id);
|
|
151
151
|
}
|
|
@@ -40,8 +40,8 @@ export function get_auth_utility_config() {
|
|
|
40
40
|
const section_name = "hazo_auth__auth_utility";
|
|
41
41
|
// Cache settings
|
|
42
42
|
const cache_max_users = get_config_number(section_name, "cache_max_users", 10000);
|
|
43
|
-
const cache_ttl_minutes = get_config_number(section_name, "cache_ttl_minutes",
|
|
44
|
-
const cache_max_age_minutes = get_config_number(section_name, "cache_max_age_minutes",
|
|
43
|
+
const cache_ttl_minutes = get_config_number(section_name, "cache_ttl_minutes", 5);
|
|
44
|
+
const cache_max_age_minutes = get_config_number(section_name, "cache_max_age_minutes", 10);
|
|
45
45
|
// Rate limiting
|
|
46
46
|
const rate_limit_per_user = get_config_number(section_name, "rate_limit_per_user", 100);
|
|
47
47
|
const rate_limit_per_ip = get_config_number(section_name, "rate_limit_per_ip", 200);
|
|
@@ -5,6 +5,14 @@ export type DefaultProfilePictureResult = {
|
|
|
5
5
|
profile_picture_url: string;
|
|
6
6
|
profile_source: ProfilePictureSource;
|
|
7
7
|
};
|
|
8
|
+
export type LibraryPhotosResult = {
|
|
9
|
+
photos: string[];
|
|
10
|
+
total: number;
|
|
11
|
+
page: number;
|
|
12
|
+
page_size: number;
|
|
13
|
+
has_more: boolean;
|
|
14
|
+
source: "project" | "node_modules";
|
|
15
|
+
};
|
|
8
16
|
/**
|
|
9
17
|
* Generates Gravatar URL from email address
|
|
10
18
|
* @param email - User's email address
|
|
@@ -18,11 +26,35 @@ export declare function get_gravatar_url(email: string, size?: number): string;
|
|
|
18
26
|
*/
|
|
19
27
|
export declare function get_library_categories(): string[];
|
|
20
28
|
/**
|
|
21
|
-
* Gets photos in a specific library category
|
|
29
|
+
* Gets photos in a specific library category with pagination support
|
|
30
|
+
* @param category - Category name
|
|
31
|
+
* @param page - Page number (1-indexed, default 1)
|
|
32
|
+
* @param page_size - Number of photos per page (default 20, max 100)
|
|
33
|
+
* @returns Object with photos array and pagination info
|
|
34
|
+
*/
|
|
35
|
+
export declare function get_library_photos_paginated(category: string, page?: number, page_size?: number): LibraryPhotosResult;
|
|
36
|
+
/**
|
|
37
|
+
* Gets photos in a specific library category (legacy non-paginated version)
|
|
22
38
|
* @param category - Category name
|
|
23
|
-
* @returns Array of photo URLs (relative to public directory)
|
|
39
|
+
* @returns Array of photo URLs (relative to public directory or API route)
|
|
24
40
|
*/
|
|
25
41
|
export declare function get_library_photos(category: string): string[];
|
|
42
|
+
/**
|
|
43
|
+
* Gets the physical file path for a library photo (used for serving from node_modules)
|
|
44
|
+
* @param category - Category name
|
|
45
|
+
* @param filename - Photo filename
|
|
46
|
+
* @returns Full file path or null if not found
|
|
47
|
+
*/
|
|
48
|
+
export declare function get_library_photo_path(category: string, filename: string): string | null;
|
|
49
|
+
/**
|
|
50
|
+
* Gets the source of library photos (for diagnostic purposes)
|
|
51
|
+
* @returns Source type or null if no library found
|
|
52
|
+
*/
|
|
53
|
+
export declare function get_library_source(): "project" | "node_modules" | null;
|
|
54
|
+
/**
|
|
55
|
+
* Clears the library path cache (useful for testing or after copying files)
|
|
56
|
+
*/
|
|
57
|
+
export declare function clear_library_cache(): void;
|
|
26
58
|
/**
|
|
27
59
|
* Gets default profile picture based on configuration priority
|
|
28
60
|
* @param user_email - User's email address
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profile_picture_service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/profile_picture_service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AASvD,OAAO,EAAuB,KAAK,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAGnG,MAAM,MAAM,oBAAoB,GAAG,sBAAsB,CAAC;AAE1D,MAAM,MAAM,2BAA2B,GAAG;IACxC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,cAAc,EAAE,oBAAoB,CAAC;CACtC,CAAC;
|
|
1
|
+
{"version":3,"file":"profile_picture_service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/profile_picture_service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AASvD,OAAO,EAAuB,KAAK,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAGnG,MAAM,MAAM,oBAAoB,GAAG,sBAAsB,CAAC;AAE1D,MAAM,MAAM,2BAA2B,GAAG;IACxC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,cAAc,EAAE,oBAAoB,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,SAAS,GAAG,cAAc,CAAC;CACpC,CAAC;AA2DF;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAOrE;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,EAAE,CAyBjD;AAED;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,MAAU,EAChB,SAAS,GAAE,MAAW,GACrB,mBAAmB,CA6FrB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAI7D;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAcxF;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,SAAS,GAAG,cAAc,GAAG,IAAI,CAGtE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAG1C;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,GACjB,2BAA2B,GAAG,IAAI,CA2DpC;AAED;;;;;;;GAOG;AACH,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,kBAAkB,EAC3B,OAAO,EAAE,MAAM,EACf,mBAAmB,EAAE,MAAM,EAC3B,cAAc,EAAE,oBAAoB,GACnC,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAsB/C"}
|