@inf-monkeys-tech/monkeys-design 0.4.36 → 0.4.37

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 CHANGED
@@ -68,6 +68,109 @@ export function Example() {
68
68
  | `@inf-monkeys-tech/monkeys-design/palette` | palette 工具 |
69
69
  | `@inf-monkeys-tech/monkeys-design/theme-system` | 主题解析与应用工具 |
70
70
 
71
+ ## LoginPage
72
+
73
+ `LoginPage` 是通用登录页 UI 组件。组件库只负责页面结构和样式契约,不包含登录请求、OAuth、路由、租户判断、i18n 初始化或租户定制样式。
74
+
75
+ ```tsx
76
+ import {
77
+ LoginPage,
78
+ type LoginPageMethodConfig,
79
+ } from '@inf-monkeys-tech/monkeys-design/components/login';
80
+ import '@inf-monkeys-tech/monkeys-design/styles/login-page.scss';
81
+
82
+ const methods: LoginPageMethodConfig[] = [
83
+ {
84
+ id: 'email',
85
+ label: 'Email',
86
+ fields: [],
87
+ submitLabel: 'Login',
88
+ onSubmit: (event) => event.preventDefault(),
89
+ },
90
+ ];
91
+
92
+ export function Example() {
93
+ return (
94
+ <LoginPage
95
+ background={{ imageUrl: '', gradient: '' }}
96
+ logo={{ url: '', position: 'bottom', scale: 1 }}
97
+ primaryColor="#4D8F9D"
98
+ radius="12px"
99
+ toolbar={<div />}
100
+ title="Welcome"
101
+ methods={methods}
102
+ />
103
+ );
104
+ }
105
+ ```
106
+
107
+ 默认背景规则:
108
+
109
+ - 配置了 `background.imageUrl` 或 `background.gradient` 时,使用配置背景。
110
+ - 未配置背景时,浅色模式使用白色和主题色渐变。
111
+ - 未配置背景时,`.dark` 深色模式使用黑色和主题色渐变。
112
+
113
+ 宿主应用负责把全局主题传入 `primaryColor` 和 `radius`,组件会把它们作为 `--login-page-theme-primary-color` 和 `--login-page-theme-radius` 默认来源;页面级 `customCss` 仍可通过公开的 `--login-page-*` 变量做租户级覆盖。深浅色切换、语言切换等应用级控件通过 `toolbar` 传入。
114
+
115
+ ### LoginPage CSS 契约
116
+
117
+ 页面级自定义样式只能依赖 `data-login-page`、`data-login-part` 和公开 CSS 变量。不要依赖租户 id,不要新增登录页代码分支。
118
+
119
+ 推荐优先覆盖变量:
120
+
121
+ ```css
122
+ [data-login-page] {
123
+ --login-page-panel-bg: rgb(255 255 255 / 0.92);
124
+ --login-page-panel-border: rgb(17 17 17 / 0.08);
125
+ --login-page-panel-shadow: 0 24px 60px rgb(0 0 0 / 0.08);
126
+ --login-page-control-bg: #ffffff;
127
+ --login-page-control-border: rgb(17 17 17 / 0.12);
128
+ --login-page-control-text: #111111;
129
+ --login-page-control-placeholder: #9f9fa9;
130
+ --login-page-form-width: 500px;
131
+ }
132
+
133
+ .dark [data-login-page] {
134
+ --login-page-panel-bg: rgb(12 12 12 / 0.9);
135
+ --login-page-control-bg: #111111;
136
+ }
137
+ ```
138
+
139
+ 公开部件:
140
+
141
+ ```css
142
+ [data-login-part='root'] {}
143
+ [data-login-part='background'] {}
144
+ [data-login-part='toolbar'] {}
145
+ [data-login-part='logo'] {}
146
+ [data-login-part='logo-image'] {}
147
+ [data-login-part='panel'] {}
148
+ [data-login-part='back'] {}
149
+ [data-login-part='back-icon'] {}
150
+ [data-login-part='title'] {}
151
+ [data-login-part='tabs'] {}
152
+ [data-login-part='tab'] {}
153
+ [data-login-part='tab-icon'] {}
154
+ [data-login-part='form'] {}
155
+ [data-login-part='field'] {}
156
+ [data-login-part='input'] {}
157
+ [data-login-part='checkbox-label'] {}
158
+ [data-login-part='checkbox'] {}
159
+ [data-login-part='method-footer'] {}
160
+ [data-login-part='method-footer-action'] {}
161
+ [data-login-part='submit-button'] {}
162
+ [data-login-part='callout'] {}
163
+ [data-login-part='callout-title'] {}
164
+ [data-login-part='callout-description'] {}
165
+ [data-login-part='callout-detail'] {}
166
+ [data-login-part='callout-action'] {}
167
+ [data-login-part='external-methods'] {}
168
+ [data-login-part='external-label'] {}
169
+ [data-login-part='external-list'] {}
170
+ [data-login-part='external-button'] {}
171
+ [data-login-part='external-icon'] {}
172
+ ```
173
+
71
174
  ## 基础组件
72
175
 
73
176
  基础组件从 `components/base` 子路径导入:
@@ -1,5 +1,99 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
1
2
  import React__default from 'react';
2
3
 
4
+ type LoginPageLogoLocation = 'top' | 'middle' | 'bottom';
5
+ interface LoginPageBackgroundConfig {
6
+ imageUrl?: string;
7
+ gradient?: string;
8
+ }
9
+ interface LoginPageLogoConfig {
10
+ url?: string;
11
+ alt?: string;
12
+ position?: LoginPageLogoLocation;
13
+ scale?: number;
14
+ }
15
+ interface LoginPageFieldConfig {
16
+ id?: string;
17
+ name: string;
18
+ type?: React__default.HTMLInputTypeAttribute;
19
+ value: string;
20
+ placeholder?: string;
21
+ autoComplete?: string;
22
+ inputMode?: React__default.HTMLAttributes<HTMLInputElement>['inputMode'];
23
+ maxLength?: number;
24
+ pattern?: string;
25
+ required?: boolean;
26
+ disabled?: boolean;
27
+ onChange: (value: string) => void;
28
+ }
29
+ interface LoginPageCheckboxConfig {
30
+ id: string;
31
+ label: React__default.ReactNode;
32
+ checked: boolean;
33
+ disabled?: boolean;
34
+ onChange: (checked: boolean) => void;
35
+ }
36
+ interface LoginPageMethodConfig {
37
+ id: string;
38
+ label: React__default.ReactNode;
39
+ icon?: React__default.ReactNode;
40
+ fields: LoginPageFieldConfig[];
41
+ submitLabel: React__default.ReactNode;
42
+ loadingLabel?: React__default.ReactNode;
43
+ isLoading?: boolean;
44
+ disabled?: boolean;
45
+ hidden?: boolean;
46
+ checkbox?: LoginPageCheckboxConfig;
47
+ footer?: React__default.ReactNode;
48
+ footerAction?: {
49
+ label: React__default.ReactNode;
50
+ disabled?: boolean;
51
+ onClick: () => void;
52
+ };
53
+ onSubmit: (event: React__default.FormEvent<HTMLFormElement>) => void;
54
+ }
55
+ interface LoginPageExternalMethodConfig {
56
+ id: string;
57
+ label: React__default.ReactNode;
58
+ icon?: React__default.ReactNode;
59
+ disabled?: boolean;
60
+ onClick?: () => void;
61
+ render?: (button: React__default.ReactElement) => React__default.ReactNode;
62
+ }
63
+ interface LoginPageCalloutConfig {
64
+ tone?: 'info' | 'warning' | 'success' | 'danger';
65
+ title: React__default.ReactNode;
66
+ description?: React__default.ReactNode;
67
+ detail?: React__default.ReactNode;
68
+ action?: {
69
+ label: React__default.ReactNode;
70
+ disabled?: boolean;
71
+ onClick: () => void;
72
+ };
73
+ }
74
+ interface LoginPageProps {
75
+ className?: string;
76
+ style?: React__default.CSSProperties;
77
+ background?: LoginPageBackgroundConfig;
78
+ logo?: LoginPageLogoConfig;
79
+ primaryColor?: string;
80
+ radius?: string;
81
+ customCss?: string;
82
+ toolbar?: React__default.ReactNode;
83
+ title?: React__default.ReactNode;
84
+ backAction?: {
85
+ label: React__default.ReactNode;
86
+ icon?: React__default.ReactNode;
87
+ onClick: () => void;
88
+ };
89
+ methods: LoginPageMethodConfig[];
90
+ activeMethodId?: string;
91
+ defaultMethodId?: string;
92
+ onMethodChange?: (methodId: string) => void;
93
+ externalLabel?: React__default.ReactNode;
94
+ externalMethods?: LoginPageExternalMethodConfig[];
95
+ callout?: LoginPageCalloutConfig;
96
+ }
3
97
  interface LoginLayoutProps {
4
98
  className?: string;
5
99
  style?: React__default.CSSProperties;
@@ -76,6 +170,8 @@ interface PendingApprovalProps {
76
170
  onBack?: () => void;
77
171
  }
78
172
 
173
+ declare function LoginPage({ className, style, background, logo, primaryColor, radius, customCss, toolbar, title, backAction, methods, activeMethodId, defaultMethodId, onMethodChange, externalLabel, externalMethods, callout, }: LoginPageProps): react_jsx_runtime.JSX.Element;
174
+
79
175
  declare const LoginLayout: React__default.FC<LoginLayoutProps>;
80
176
 
81
177
  declare const EmailAuth: React__default.ForwardRefExoticComponent<EmailAuthProps & React__default.RefAttributes<HTMLFormElement>>;
@@ -88,4 +184,4 @@ declare const AuthDivider: React__default.FC<AuthDividerProps>;
88
184
 
89
185
  declare const PendingApproval: React__default.FC<PendingApprovalProps>;
90
186
 
91
- export { AuthDivider, type AuthDividerProps, EmailAuth, type EmailAuthProps, LoginLayout, type LoginLayoutProps, OAuthButton, type OAuthButtonProps, OIDCButton, type OIDCButtonProps, PendingApproval, type PendingApprovalProps };
187
+ export { AuthDivider, type AuthDividerProps, EmailAuth, type EmailAuthProps, LoginLayout, type LoginLayoutProps, LoginPage, type LoginPageBackgroundConfig, type LoginPageCalloutConfig, type LoginPageCheckboxConfig, type LoginPageExternalMethodConfig, type LoginPageFieldConfig, type LoginPageLogoConfig, type LoginPageLogoLocation, type LoginPageMethodConfig, type LoginPageProps, OAuthButton, type OAuthButtonProps, OIDCButton, type OIDCButtonProps, PendingApproval, type PendingApprovalProps };
@@ -1,5 +1,99 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
1
2
  import React__default from 'react';
2
3
 
4
+ type LoginPageLogoLocation = 'top' | 'middle' | 'bottom';
5
+ interface LoginPageBackgroundConfig {
6
+ imageUrl?: string;
7
+ gradient?: string;
8
+ }
9
+ interface LoginPageLogoConfig {
10
+ url?: string;
11
+ alt?: string;
12
+ position?: LoginPageLogoLocation;
13
+ scale?: number;
14
+ }
15
+ interface LoginPageFieldConfig {
16
+ id?: string;
17
+ name: string;
18
+ type?: React__default.HTMLInputTypeAttribute;
19
+ value: string;
20
+ placeholder?: string;
21
+ autoComplete?: string;
22
+ inputMode?: React__default.HTMLAttributes<HTMLInputElement>['inputMode'];
23
+ maxLength?: number;
24
+ pattern?: string;
25
+ required?: boolean;
26
+ disabled?: boolean;
27
+ onChange: (value: string) => void;
28
+ }
29
+ interface LoginPageCheckboxConfig {
30
+ id: string;
31
+ label: React__default.ReactNode;
32
+ checked: boolean;
33
+ disabled?: boolean;
34
+ onChange: (checked: boolean) => void;
35
+ }
36
+ interface LoginPageMethodConfig {
37
+ id: string;
38
+ label: React__default.ReactNode;
39
+ icon?: React__default.ReactNode;
40
+ fields: LoginPageFieldConfig[];
41
+ submitLabel: React__default.ReactNode;
42
+ loadingLabel?: React__default.ReactNode;
43
+ isLoading?: boolean;
44
+ disabled?: boolean;
45
+ hidden?: boolean;
46
+ checkbox?: LoginPageCheckboxConfig;
47
+ footer?: React__default.ReactNode;
48
+ footerAction?: {
49
+ label: React__default.ReactNode;
50
+ disabled?: boolean;
51
+ onClick: () => void;
52
+ };
53
+ onSubmit: (event: React__default.FormEvent<HTMLFormElement>) => void;
54
+ }
55
+ interface LoginPageExternalMethodConfig {
56
+ id: string;
57
+ label: React__default.ReactNode;
58
+ icon?: React__default.ReactNode;
59
+ disabled?: boolean;
60
+ onClick?: () => void;
61
+ render?: (button: React__default.ReactElement) => React__default.ReactNode;
62
+ }
63
+ interface LoginPageCalloutConfig {
64
+ tone?: 'info' | 'warning' | 'success' | 'danger';
65
+ title: React__default.ReactNode;
66
+ description?: React__default.ReactNode;
67
+ detail?: React__default.ReactNode;
68
+ action?: {
69
+ label: React__default.ReactNode;
70
+ disabled?: boolean;
71
+ onClick: () => void;
72
+ };
73
+ }
74
+ interface LoginPageProps {
75
+ className?: string;
76
+ style?: React__default.CSSProperties;
77
+ background?: LoginPageBackgroundConfig;
78
+ logo?: LoginPageLogoConfig;
79
+ primaryColor?: string;
80
+ radius?: string;
81
+ customCss?: string;
82
+ toolbar?: React__default.ReactNode;
83
+ title?: React__default.ReactNode;
84
+ backAction?: {
85
+ label: React__default.ReactNode;
86
+ icon?: React__default.ReactNode;
87
+ onClick: () => void;
88
+ };
89
+ methods: LoginPageMethodConfig[];
90
+ activeMethodId?: string;
91
+ defaultMethodId?: string;
92
+ onMethodChange?: (methodId: string) => void;
93
+ externalLabel?: React__default.ReactNode;
94
+ externalMethods?: LoginPageExternalMethodConfig[];
95
+ callout?: LoginPageCalloutConfig;
96
+ }
3
97
  interface LoginLayoutProps {
4
98
  className?: string;
5
99
  style?: React__default.CSSProperties;
@@ -76,6 +170,8 @@ interface PendingApprovalProps {
76
170
  onBack?: () => void;
77
171
  }
78
172
 
173
+ declare function LoginPage({ className, style, background, logo, primaryColor, radius, customCss, toolbar, title, backAction, methods, activeMethodId, defaultMethodId, onMethodChange, externalLabel, externalMethods, callout, }: LoginPageProps): react_jsx_runtime.JSX.Element;
174
+
79
175
  declare const LoginLayout: React__default.FC<LoginLayoutProps>;
80
176
 
81
177
  declare const EmailAuth: React__default.ForwardRefExoticComponent<EmailAuthProps & React__default.RefAttributes<HTMLFormElement>>;
@@ -88,4 +184,4 @@ declare const AuthDivider: React__default.FC<AuthDividerProps>;
88
184
 
89
185
  declare const PendingApproval: React__default.FC<PendingApprovalProps>;
90
186
 
91
- export { AuthDivider, type AuthDividerProps, EmailAuth, type EmailAuthProps, LoginLayout, type LoginLayoutProps, OAuthButton, type OAuthButtonProps, OIDCButton, type OIDCButtonProps, PendingApproval, type PendingApprovalProps };
187
+ export { AuthDivider, type AuthDividerProps, EmailAuth, type EmailAuthProps, LoginLayout, type LoginLayoutProps, LoginPage, type LoginPageBackgroundConfig, type LoginPageCalloutConfig, type LoginPageCheckboxConfig, type LoginPageExternalMethodConfig, type LoginPageFieldConfig, type LoginPageLogoConfig, type LoginPageLogoLocation, type LoginPageMethodConfig, type LoginPageProps, OAuthButton, type OAuthButtonProps, OIDCButton, type OIDCButtonProps, PendingApproval, type PendingApprovalProps };
@@ -1,13 +1,272 @@
1
1
  'use strict';
2
2
 
3
- var jsxRuntime = require('react/jsx-runtime');
4
3
  var React = require('react');
4
+ var jsxRuntime = require('react/jsx-runtime');
5
5
 
6
6
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
7
7
 
8
8
  var React__default = /*#__PURE__*/_interopDefault(React);
9
9
 
10
- // src/components/login/LoginLayout.tsx
10
+ // src/components/login/LoginPage.tsx
11
+ var LOGIN_LOGO_POSITIONS = ["top", "middle", "bottom"];
12
+ var normalizeCssValue = (value) => {
13
+ const trimmed = value?.trim();
14
+ return trimmed || void 0;
15
+ };
16
+ var createBackgroundImage = (gradient, imageUrl) => {
17
+ const resolvedGradient = normalizeCssValue(gradient);
18
+ const resolvedImageUrl = normalizeCssValue(imageUrl);
19
+ return [resolvedGradient, resolvedImageUrl ? `url(${JSON.stringify(resolvedImageUrl)})` : void 0].filter(Boolean).join(", ");
20
+ };
21
+ var normalizeLogoPosition = (position) => position && LOGIN_LOGO_POSITIONS.includes(position) ? position : "bottom";
22
+ var normalizeLogoScale = (scale) => typeof scale === "number" && Number.isFinite(scale) && scale > 0 ? scale : void 0;
23
+ function LoginPage({
24
+ className,
25
+ style,
26
+ background,
27
+ logo,
28
+ primaryColor,
29
+ radius,
30
+ customCss,
31
+ toolbar,
32
+ title,
33
+ backAction,
34
+ methods,
35
+ activeMethodId,
36
+ defaultMethodId,
37
+ onMethodChange,
38
+ externalLabel,
39
+ externalMethods = [],
40
+ callout
41
+ }) {
42
+ const availableMethods = React.useMemo(() => methods.filter((method) => !method.hidden), [methods]);
43
+ const fallbackMethodId = defaultMethodId ?? availableMethods[0]?.id;
44
+ const [internalMethodId, setInternalMethodId] = React.useState(fallbackMethodId);
45
+ const currentMethodId = activeMethodId ?? internalMethodId;
46
+ const activeMethod = availableMethods.find((method) => method.id === currentMethodId) ?? availableMethods[0];
47
+ const hasTabs = availableMethods.length > 1;
48
+ const backgroundImage = createBackgroundImage(background?.gradient, background?.imageUrl);
49
+ const backgroundMode = backgroundImage ? "custom" : "default";
50
+ const logoPosition = normalizeLogoPosition(logo?.position);
51
+ const logoScale = normalizeLogoScale(logo?.scale);
52
+ React.useEffect(() => {
53
+ if (!availableMethods.length) {
54
+ setInternalMethodId(void 0);
55
+ return;
56
+ }
57
+ if (!currentMethodId || !availableMethods.some((method) => method.id === currentMethodId)) {
58
+ setInternalMethodId(fallbackMethodId ?? availableMethods[0]?.id);
59
+ }
60
+ }, [availableMethods, currentMethodId, fallbackMethodId]);
61
+ const rootStyle = React.useMemo(
62
+ () => ({
63
+ ...primaryColor ? { ["--login-page-theme-primary-color"]: primaryColor } : null,
64
+ ...radius ? { ["--login-page-theme-radius"]: radius } : null,
65
+ ...style
66
+ }),
67
+ [primaryColor, radius, style]
68
+ );
69
+ const handleMethodChange = (methodId) => {
70
+ if (activeMethodId === void 0) {
71
+ setInternalMethodId(methodId);
72
+ }
73
+ onMethodChange?.(methodId);
74
+ };
75
+ const renderExternalMethod = (method) => {
76
+ const button = /* @__PURE__ */ jsxRuntime.jsxs(
77
+ "button",
78
+ {
79
+ type: "button",
80
+ className: "login-page__oauth-button",
81
+ "data-login-part": "external-button",
82
+ "data-login-method-id": method.id,
83
+ onClick: method.onClick,
84
+ disabled: method.disabled,
85
+ children: [
86
+ method.icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "login-page__oauth-icon", "data-login-part": "external-icon", children: method.icon }) : null,
87
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: method.label })
88
+ ]
89
+ }
90
+ );
91
+ return /* @__PURE__ */ jsxRuntime.jsx(React__default.default.Fragment, { children: method.render ? method.render(button) : button }, method.id);
92
+ };
93
+ return /* @__PURE__ */ jsxRuntime.jsxs(
94
+ "main",
95
+ {
96
+ className: ["login-page", className].filter(Boolean).join(" "),
97
+ "data-login-page": true,
98
+ "data-login-part": "root",
99
+ "data-login-background": backgroundMode,
100
+ style: rootStyle,
101
+ children: [
102
+ customCss ? /* @__PURE__ */ jsxRuntime.jsx("style", { "data-login-page-custom-css": true, children: customCss }) : null,
103
+ /* @__PURE__ */ jsxRuntime.jsx(
104
+ "div",
105
+ {
106
+ className: "login-page__background",
107
+ "data-login-part": "background",
108
+ "data-login-background": backgroundMode,
109
+ style: backgroundImage ? { backgroundImage } : void 0,
110
+ "aria-hidden": "true"
111
+ }
112
+ ),
113
+ toolbar ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "login-page__toolbar", "data-login-part": "toolbar", children: toolbar }) : null,
114
+ logo?.url ? /* @__PURE__ */ jsxRuntime.jsx(
115
+ "div",
116
+ {
117
+ className: `login-page__logo login-page__logo--${logoPosition}`,
118
+ "data-login-part": "logo",
119
+ "data-logo-position": logoPosition,
120
+ children: /* @__PURE__ */ jsxRuntime.jsx(
121
+ "img",
122
+ {
123
+ className: "login-page__logo-image",
124
+ "data-login-part": "logo-image",
125
+ src: logo.url,
126
+ alt: logo.alt ?? "",
127
+ style: logoScale ? { transform: `scale(${logoScale})` } : void 0
128
+ }
129
+ )
130
+ }
131
+ ) : null,
132
+ /* @__PURE__ */ jsxRuntime.jsxs(
133
+ "section",
134
+ {
135
+ className: "login-page__form",
136
+ "data-login-part": "panel",
137
+ "aria-label": typeof title === "string" ? title : void 0,
138
+ children: [
139
+ backAction ? /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "login-page__back", "data-login-part": "back", onClick: backAction.onClick, children: [
140
+ backAction.icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "login-page__back-icon", "data-login-part": "back-icon", children: backAction.icon }) : null,
141
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: backAction.label })
142
+ ] }) : null,
143
+ title ? /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "login-page__title", "data-login-part": "title", children: title }) : null,
144
+ hasTabs ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "login-page__tabs", "data-login-part": "tabs", role: "tablist", children: availableMethods.map((method) => {
145
+ const selected = method.id === activeMethod?.id;
146
+ return /* @__PURE__ */ jsxRuntime.jsxs(
147
+ "button",
148
+ {
149
+ type: "button",
150
+ role: "tab",
151
+ "aria-selected": selected,
152
+ className: `login-page__tab ${selected ? "login-page__tab--active" : ""}`,
153
+ "data-login-part": "tab",
154
+ "data-login-method-id": method.id,
155
+ "data-active": selected ? "true" : "false",
156
+ onClick: () => handleMethodChange(method.id),
157
+ children: [
158
+ method.icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "login-page__tab-icon", "data-login-part": "tab-icon", children: method.icon }) : null,
159
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: method.label })
160
+ ]
161
+ },
162
+ method.id
163
+ );
164
+ }) }) : null,
165
+ activeMethod ? /* @__PURE__ */ jsxRuntime.jsxs(
166
+ "form",
167
+ {
168
+ className: "login-page__form-fields",
169
+ "data-login-part": "form",
170
+ "data-login-method-id": activeMethod.id,
171
+ onSubmit: activeMethod.onSubmit,
172
+ children: [
173
+ activeMethod.fields.map((field) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "login-page__field", "data-login-part": "field", "data-login-field-name": field.name, children: /* @__PURE__ */ jsxRuntime.jsx(
174
+ "input",
175
+ {
176
+ id: field.id,
177
+ name: field.name,
178
+ type: field.type ?? "text",
179
+ value: field.value,
180
+ placeholder: field.placeholder,
181
+ autoComplete: field.autoComplete,
182
+ inputMode: field.inputMode,
183
+ maxLength: field.maxLength,
184
+ pattern: field.pattern,
185
+ disabled: activeMethod.disabled || activeMethod.isLoading || field.disabled,
186
+ required: field.required,
187
+ className: "login-page__input",
188
+ "data-login-part": "input",
189
+ onChange: (event) => field.onChange(event.target.value)
190
+ }
191
+ ) }, field.name)),
192
+ activeMethod.checkbox ? /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "login-page__remember", "data-login-part": "checkbox-label", htmlFor: activeMethod.checkbox.id, children: [
193
+ /* @__PURE__ */ jsxRuntime.jsx(
194
+ "input",
195
+ {
196
+ id: activeMethod.checkbox.id,
197
+ type: "checkbox",
198
+ className: "login-page__checkbox",
199
+ "data-login-part": "checkbox",
200
+ checked: activeMethod.checkbox.checked,
201
+ disabled: activeMethod.disabled || activeMethod.isLoading || activeMethod.checkbox.disabled,
202
+ onChange: (event) => activeMethod.checkbox?.onChange(event.target.checked)
203
+ }
204
+ ),
205
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: activeMethod.checkbox.label })
206
+ ] }) : null,
207
+ activeMethod.footer || activeMethod.footerAction ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "login-page__method-footer", "data-login-part": "method-footer", children: [
208
+ activeMethod.footer,
209
+ activeMethod.footerAction ? /* @__PURE__ */ jsxRuntime.jsx(
210
+ "button",
211
+ {
212
+ type: "button",
213
+ className: "login-page__method-footer-action",
214
+ "data-login-part": "method-footer-action",
215
+ "data-login-method-id": activeMethod.id,
216
+ onClick: activeMethod.footerAction.onClick,
217
+ disabled: activeMethod.disabled || activeMethod.isLoading || activeMethod.footerAction.disabled,
218
+ children: activeMethod.footerAction.label
219
+ }
220
+ ) : null
221
+ ] }) : null,
222
+ /* @__PURE__ */ jsxRuntime.jsx(
223
+ "button",
224
+ {
225
+ type: "submit",
226
+ className: "login-page__submit",
227
+ "data-login-part": "submit-button",
228
+ disabled: activeMethod.disabled || activeMethod.isLoading,
229
+ children: activeMethod.isLoading && activeMethod.loadingLabel ? activeMethod.loadingLabel : activeMethod.submitLabel
230
+ }
231
+ )
232
+ ]
233
+ }
234
+ ) : null,
235
+ callout ? /* @__PURE__ */ jsxRuntime.jsxs(
236
+ "div",
237
+ {
238
+ className: `login-page__callout login-page__callout--${callout.tone ?? "info"}`,
239
+ "data-login-part": "callout",
240
+ "data-tone": callout.tone ?? "info",
241
+ children: [
242
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "login-page__callout-title", "data-login-part": "callout-title", children: callout.title }),
243
+ callout.description ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "login-page__callout-description", "data-login-part": "callout-description", children: callout.description }) : null,
244
+ callout.detail ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "login-page__callout-detail", "data-login-part": "callout-detail", children: callout.detail }) : null,
245
+ callout.action ? /* @__PURE__ */ jsxRuntime.jsx(
246
+ "button",
247
+ {
248
+ type: "button",
249
+ className: "login-page__callout-action",
250
+ "data-login-part": "callout-action",
251
+ onClick: callout.action.onClick,
252
+ disabled: callout.action.disabled,
253
+ children: callout.action.label
254
+ }
255
+ ) : null
256
+ ]
257
+ }
258
+ ) : null,
259
+ externalMethods.length ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "login-page__oauth-section", "data-login-part": "external-methods", children: [
260
+ externalLabel ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "login-page__oauth-label", "data-login-part": "external-label", children: externalLabel }) : null,
261
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "login-page__oauth-list", "data-login-part": "external-list", children: externalMethods.map(renderExternalMethod) })
262
+ ] }) : null
263
+ ]
264
+ }
265
+ )
266
+ ]
267
+ }
268
+ );
269
+ }
11
270
  var containerStyle = {
12
271
  display: "flex",
13
272
  alignItems: "center",
@@ -308,6 +567,7 @@ var PendingApproval = ({
308
567
  exports.AuthDivider = AuthDivider;
309
568
  exports.EmailAuth = EmailAuth;
310
569
  exports.LoginLayout = LoginLayout;
570
+ exports.LoginPage = LoginPage;
311
571
  exports.OAuthButton = OAuthButton;
312
572
  exports.OIDCButton = OIDCButton;
313
573
  exports.PendingApproval = PendingApproval;