@progressive-development/pd-page 0.9.2 → 1.0.1
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/LICENSE +21 -2
- package/README.md +34 -57
- package/dist/generated/locales/be.d.ts +19 -1
- package/dist/generated/locales/be.d.ts.map +1 -1
- package/dist/generated/locales/de.d.ts +19 -1
- package/dist/generated/locales/de.d.ts.map +1 -1
- package/dist/generated/locales/en.d.ts +19 -1
- package/dist/generated/locales/en.d.ts.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/locales/be.js +19 -1
- package/dist/locales/de.js +19 -1
- package/dist/locales/en.js +19 -1
- package/dist/pd-contact-us/PdContactUs.d.ts +15 -5
- package/dist/pd-contact-us/PdContactUs.d.ts.map +1 -1
- package/dist/pd-contact-us/PdContactUs.js +94 -131
- package/dist/pd-contact-us/pd-contact-us.stories.d.ts +36 -5
- package/dist/pd-contact-us/pd-contact-us.stories.d.ts.map +1 -1
- package/dist/pd-footer/PdFooter.d.ts +27 -15
- package/dist/pd-footer/PdFooter.d.ts.map +1 -1
- package/dist/pd-footer/PdFooter.js +122 -71
- package/dist/pd-footer/pd-footer.stories.d.ts +47 -7
- package/dist/pd-footer/pd-footer.stories.d.ts.map +1 -1
- package/dist/pd-login/PdLogin.d.ts +59 -0
- package/dist/pd-login/PdLogin.d.ts.map +1 -0
- package/dist/pd-login/PdLogin.js +292 -0
- package/dist/pd-login/pd-login.d.ts +3 -0
- package/dist/pd-login/pd-login.d.ts.map +1 -0
- package/dist/pd-login/pd-login.stories.d.ts +55 -0
- package/dist/pd-login/pd-login.stories.d.ts.map +1 -0
- package/dist/pd-login.d.ts +2 -0
- package/dist/pd-login.js +8 -0
- package/dist/pd-menu/PdMenu.d.ts +72 -40
- package/dist/pd-menu/PdMenu.d.ts.map +1 -1
- package/dist/pd-menu/PdMenu.js +384 -273
- package/dist/pd-menu/pd-menu.stories.d.ts +59 -17
- package/dist/pd-menu/pd-menu.stories.d.ts.map +1 -1
- package/dist/pd-socialmedia/PdSocialmedia.d.ts +56 -0
- package/dist/pd-socialmedia/PdSocialmedia.d.ts.map +1 -0
- package/dist/pd-socialmedia/PdSocialmedia.js +426 -0
- package/dist/pd-socialmedia/pd-socialmedia-model.d.ts +16 -0
- package/dist/pd-socialmedia/pd-socialmedia-model.d.ts.map +1 -0
- package/dist/pd-socialmedia/pd-socialmedia-model.js +240 -0
- package/dist/pd-socialmedia/pd-socialmedia.d.ts +3 -0
- package/dist/pd-socialmedia/pd-socialmedia.d.ts.map +1 -0
- package/dist/pd-socialmedia/pd-socialmedia.stories.d.ts +53 -0
- package/dist/pd-socialmedia/pd-socialmedia.stories.d.ts.map +1 -0
- package/dist/pd-socialmedia.d.ts +2 -0
- package/dist/pd-socialmedia.js +7 -0
- package/dist/pd-toast/PdToast.d.ts +23 -0
- package/dist/pd-toast/PdToast.d.ts.map +1 -0
- package/dist/pd-toast/PdToast.js +222 -0
- package/dist/pd-toast/pd-toast.d.ts +3 -0
- package/dist/pd-toast/pd-toast.d.ts.map +1 -0
- package/dist/pd-toast/pd-toast.stories.d.ts +47 -0
- package/dist/pd-toast/pd-toast.stories.d.ts.map +1 -0
- package/dist/pd-toast.d.ts +2 -0
- package/dist/pd-toast.js +8 -0
- package/dist/stories/01_index.stories.d.ts +36 -4
- package/dist/stories/01_index.stories.d.ts.map +1 -1
- package/dist/toast-bus/toast-bus.d.ts +61 -0
- package/dist/toast-bus/toast-bus.d.ts.map +1 -0
- package/dist/toast-bus/toast-bus.js +42 -0
- package/dist/types.d.ts +18 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +31 -24
|
@@ -1,8 +1,48 @@
|
|
|
1
|
-
import { Meta,
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/web-components-vite';
|
|
2
|
+
import { PdFooterLink, PdFooterMadeBy } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Story arguments interface for pd-footer component.
|
|
5
|
+
* Maps to the component's public API.
|
|
6
|
+
*/
|
|
7
|
+
interface PdFooterArgs {
|
|
8
|
+
/** Footer navigation links */
|
|
9
|
+
footerLinks: PdFooterLink[];
|
|
10
|
+
/** Copyright text */
|
|
11
|
+
copyright: string;
|
|
12
|
+
/** Version string */
|
|
13
|
+
version: string;
|
|
14
|
+
/** Developer/agency reference */
|
|
15
|
+
madeBy?: PdFooterMadeBy;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* ## pd-footer
|
|
19
|
+
*
|
|
20
|
+
* Application footer with navigation links, copyright info, version display, and developer reference.
|
|
21
|
+
*
|
|
22
|
+
* ### Features
|
|
23
|
+
* - Configurable footer links with click events
|
|
24
|
+
* - Copyright text and version string display
|
|
25
|
+
* - Developer/agency reference with email (mailto:) or external link
|
|
26
|
+
* - Responsive layout with flex-wrap for links
|
|
27
|
+
* - Full keyboard accessibility (Tab, Enter, Space on links and madeBy)
|
|
28
|
+
*
|
|
29
|
+
* ### Accessibility
|
|
30
|
+
* - Uses `<nav>` element with `aria-label` for footer navigation landmark
|
|
31
|
+
* - Footer links use `role="button"` and `tabindex="0"`
|
|
32
|
+
* - Focus-visible styling for keyboard users
|
|
33
|
+
* - Made-by link opens in new tab with noopener,noreferrer for security
|
|
34
|
+
*/
|
|
35
|
+
declare const meta: Meta<PdFooterArgs>;
|
|
36
|
+
export default meta;
|
|
37
|
+
type Story = StoryObj<PdFooterArgs>;
|
|
38
|
+
/** Default footer with links, copyright, and version. Interactive via Controls panel. */
|
|
39
|
+
export declare const Default: Story;
|
|
40
|
+
/** Footer with developer/agency reference — email opens mailto:, link opens in new tab. */
|
|
41
|
+
export declare const WithMadeBy: Story;
|
|
42
|
+
/** Minimal footer configurations — different content combinations. */
|
|
43
|
+
export declare const MinimalConfigurations: Story;
|
|
44
|
+
/** Overview of all footer configurations at a glance. */
|
|
45
|
+
export declare const AllVariants: Story;
|
|
46
|
+
/** CSS Custom Properties -- Branded and Redesigned variants. */
|
|
47
|
+
export declare const CustomStyling: Story;
|
|
8
48
|
//# sourceMappingURL=pd-footer.stories.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pd-footer.stories.d.ts","sourceRoot":"","sources":["../../src/pd-footer/pd-footer.stories.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pd-footer.stories.d.ts","sourceRoot":"","sources":["../../src/pd-footer/pd-footer.stories.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAErE,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEhE,OAAO,gBAAgB,CAAC;AAMxB;;;GAGG;AACH,UAAU,YAAY;IACpB,8BAA8B;IAC9B,WAAW,EAAE,YAAY,EAAE,CAAC;IAC5B,qBAAqB;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,qBAAqB;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,MAAM,CAAC,EAAE,cAAc,CAAC;CACzB;AA+BD;;;;;;;;;;;;;;;;;GAiBG;AACH,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,YAAY,CA8E5B,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC;AAMpC,yFAAyF;AACzF,eAAO,MAAM,OAAO,EAAE,KAAU,CAAC;AAMjC,2FAA2F;AAC3F,eAAO,MAAM,UAAU,EAAE,KA0CxB,CAAC;AAMF,sEAAsE;AACtE,eAAO,MAAM,qBAAqB,EAAE,KAkCnC,CAAC;AAMF,yDAAyD;AACzD,eAAO,MAAM,WAAW,EAAE,KA8CzB,CAAC;AAMF,gEAAgE;AAChE,eAAO,MAAM,aAAa,EAAE,KAgF3B,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { LitElement, CSSResultGroup } from 'lit';
|
|
2
|
+
/**
|
|
3
|
+
* Login form component for email/password authentication.
|
|
4
|
+
*
|
|
5
|
+
* This is a pure UI component that emits events for login attempts.
|
|
6
|
+
* The actual authentication logic should be handled by the parent component.
|
|
7
|
+
*
|
|
8
|
+
* Supports two views:
|
|
9
|
+
* - **login**: Default login form with email and password fields.
|
|
10
|
+
* - **forgot-password**: Password reset request form with email field only.
|
|
11
|
+
*
|
|
12
|
+
* @summary Login form with email and password fields, including forgot password flow.
|
|
13
|
+
*
|
|
14
|
+
* @tagname pd-login
|
|
15
|
+
*
|
|
16
|
+
* @event login-attempt - Fired when user submits valid credentials. Detail: `LoginAttemptDetail`.
|
|
17
|
+
* @event forgot-password-attempt - Fired when user requests password reset. Detail: `ForgotPasswordAttemptDetail`.
|
|
18
|
+
*
|
|
19
|
+
* @cssprop --pd-login-bg-color - Form background color. Default: `var(--pd-default-bg-light-col)`.
|
|
20
|
+
* @cssprop --pd-login-border-radius - Form border radius. Default: `var(--pd-radius-md)`.
|
|
21
|
+
* @cssprop --pd-login-max-width - Maximum width of the form. Default: `500px`.
|
|
22
|
+
* @cssprop --pd-login-padding - Form padding. Default: `1rem 0 1rem 1rem`.
|
|
23
|
+
*/
|
|
24
|
+
export declare class PdLogin extends LitElement {
|
|
25
|
+
/** Shows loading state on the submit button. */
|
|
26
|
+
loading: boolean;
|
|
27
|
+
/** Error message to display. */
|
|
28
|
+
errorMessage: string;
|
|
29
|
+
/** Success message to display (e.g., after password reset request). */
|
|
30
|
+
successMessage: string;
|
|
31
|
+
/** Hide the forgot password link. */
|
|
32
|
+
hideForgotPassword: boolean;
|
|
33
|
+
/** Current view: login form or forgot password form (internal). */
|
|
34
|
+
private _view;
|
|
35
|
+
private _validForm;
|
|
36
|
+
private _forgotPasswordValidForm;
|
|
37
|
+
private _prefillEmail;
|
|
38
|
+
/** @ignore */
|
|
39
|
+
private _formElement;
|
|
40
|
+
/** @ignore */
|
|
41
|
+
private _forgotPasswordFormElement;
|
|
42
|
+
static styles: CSSResultGroup;
|
|
43
|
+
render(): import('lit').TemplateResult<1>;
|
|
44
|
+
private _renderLoginView;
|
|
45
|
+
private _renderForgotPasswordView;
|
|
46
|
+
/** Clears the form and resets validation state. */
|
|
47
|
+
clear(): void;
|
|
48
|
+
private _handleFormChange;
|
|
49
|
+
private _handleSubmit;
|
|
50
|
+
private _handleForgotPassword;
|
|
51
|
+
private _handleForgotPasswordFormChange;
|
|
52
|
+
private _handleForgotPasswordSubmit;
|
|
53
|
+
private _handleBackToLogin;
|
|
54
|
+
/** Switch to forgot password view. */
|
|
55
|
+
showForgotPassword(): void;
|
|
56
|
+
/** Switch back to login view. */
|
|
57
|
+
showLogin(): void;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=PdLogin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PdLogin.d.ts","sourceRoot":"","sources":["../../src/pd-login/PdLogin.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAa,cAAc,EAAE,MAAM,KAAK,CAAC;AAI5D,OAAO,qDAAqD,CAAC;AAC7D,OAAO,+CAA+C,CAAC;AACvD,OAAO,4CAA4C,CAAC;AACpD,OAAO,mDAAmD,CAAC;AAC3D,OAAO,mDAAmD,CAAC;AAS3D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBACa,OAAQ,SAAQ,UAAU;IACrC,gDAAgD;IAEhD,OAAO,UAAS;IAEhB,gCAAgC;IAEhC,YAAY,SAAM;IAElB,uEAAuE;IAEvE,cAAc,SAAM;IAEpB,qCAAqC;IAErC,kBAAkB,UAAS;IAE3B,mEAAmE;IAEnE,OAAO,CAAC,KAAK,CAAwC;IAGrD,OAAO,CAAC,UAAU,CAAS;IAG3B,OAAO,CAAC,wBAAwB,CAAS;IAGzC,OAAO,CAAC,aAAa,CAAM;IAE3B,cAAc;IAEd,OAAO,CAAC,YAAY,CAAmB;IAEvC,cAAc;IAEd,OAAO,CAAC,0BAA0B,CAAmB;IAErD,OAAgB,MAAM,EAAE,cAAc,CA0CpC;IAEF,MAAM;IAMN,OAAO,CAAC,gBAAgB;IAgExB,OAAO,CAAC,yBAAyB;IAqDjC,mDAAmD;IACnD,KAAK,IAAI,IAAI;IAKb,OAAO,CAAC,iBAAiB;IAKzB,OAAO,CAAC,aAAa;IAoBrB,OAAO,CAAC,qBAAqB;IAQ7B,OAAO,CAAC,+BAA+B;IAKvC,OAAO,CAAC,2BAA2B;IAsBnC,OAAO,CAAC,kBAAkB;IAK1B,sCAAsC;IACtC,kBAAkB,IAAI,IAAI;IAM1B,iCAAiC;IACjC,SAAS,IAAI,IAAI;CAGlB"}
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import { css, LitElement, html } from 'lit';
|
|
2
|
+
import { localized, msg } from '@lit/localize';
|
|
3
|
+
import { property, state, query } from 'lit/decorators.js';
|
|
4
|
+
import '@progressive-development/pd-forms/pd-form-container';
|
|
5
|
+
import '@progressive-development/pd-forms/pd-form-row';
|
|
6
|
+
import '@progressive-development/pd-forms/pd-input';
|
|
7
|
+
import '@progressive-development/pd-forms/pd-panel-button';
|
|
8
|
+
import '@progressive-development/pd-content/pd-notice-box';
|
|
9
|
+
import { pdIcons } from '@progressive-development/pd-icon';
|
|
10
|
+
|
|
11
|
+
var __defProp = Object.defineProperty;
|
|
12
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
13
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
14
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
15
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
16
|
+
if (decorator = decorators[i])
|
|
17
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
18
|
+
if (kind && result) __defProp(target, key, result);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
let PdLogin = class extends LitElement {
|
|
22
|
+
constructor() {
|
|
23
|
+
super(...arguments);
|
|
24
|
+
this.loading = false;
|
|
25
|
+
this.errorMessage = "";
|
|
26
|
+
this.successMessage = "";
|
|
27
|
+
this.hideForgotPassword = false;
|
|
28
|
+
this._view = "login";
|
|
29
|
+
this._validForm = false;
|
|
30
|
+
this._forgotPasswordValidForm = false;
|
|
31
|
+
this._prefillEmail = "";
|
|
32
|
+
}
|
|
33
|
+
render() {
|
|
34
|
+
return this._view === "login" ? this._renderLoginView() : this._renderForgotPasswordView();
|
|
35
|
+
}
|
|
36
|
+
_renderLoginView() {
|
|
37
|
+
return html`
|
|
38
|
+
<div class="login-form">
|
|
39
|
+
${this.successMessage ? html`<pd-notice-box type="success" variant="sidebar"
|
|
40
|
+
>${this.successMessage}</pd-notice-box
|
|
41
|
+
>` : ""}
|
|
42
|
+
|
|
43
|
+
<pd-form-container
|
|
44
|
+
id="loginFormId"
|
|
45
|
+
@pd-form-change="${this._handleFormChange}"
|
|
46
|
+
commonError="${this.errorMessage}"
|
|
47
|
+
>
|
|
48
|
+
<pd-form-row>
|
|
49
|
+
<pd-input
|
|
50
|
+
id="eMail"
|
|
51
|
+
maxlength="250"
|
|
52
|
+
fieldType="mail"
|
|
53
|
+
valueName="email"
|
|
54
|
+
label="${msg("E-Mail", { id: "pd.login.email.label" })}"
|
|
55
|
+
autoCompleteName="email"
|
|
56
|
+
required
|
|
57
|
+
@enter-pressed="${this._handleSubmit}"
|
|
58
|
+
></pd-input>
|
|
59
|
+
</pd-form-row>
|
|
60
|
+
|
|
61
|
+
<pd-form-row>
|
|
62
|
+
<pd-input
|
|
63
|
+
id="pWord"
|
|
64
|
+
secret
|
|
65
|
+
maxlength="30"
|
|
66
|
+
label="${msg("Passwort", { id: "pd.login.password.label" })}"
|
|
67
|
+
valueName="password"
|
|
68
|
+
autoCompleteName="current-password"
|
|
69
|
+
required
|
|
70
|
+
@enter-pressed="${this._handleSubmit}"
|
|
71
|
+
></pd-input>
|
|
72
|
+
|
|
73
|
+
${!this.hideForgotPassword ? html`<span class="pwd-link"
|
|
74
|
+
><a href="#" @click="${this._handleForgotPassword}"
|
|
75
|
+
>${msg("Passwort vergessen?", {
|
|
76
|
+
id: "pd.login.forgot.password"
|
|
77
|
+
})}</a
|
|
78
|
+
></span
|
|
79
|
+
>` : ""}
|
|
80
|
+
</pd-form-row>
|
|
81
|
+
</pd-form-container>
|
|
82
|
+
|
|
83
|
+
<pd-form-row>
|
|
84
|
+
<pd-button
|
|
85
|
+
text="${msg("Anmelden", { id: "pd.login.submit" })}"
|
|
86
|
+
icon="${pdIcons.ICON_USER}"
|
|
87
|
+
?disabled="${!this._validForm || this.loading}"
|
|
88
|
+
?loading="${this.loading}"
|
|
89
|
+
@button-clicked="${this._handleSubmit}"
|
|
90
|
+
></pd-button>
|
|
91
|
+
</pd-form-row>
|
|
92
|
+
</div>
|
|
93
|
+
`;
|
|
94
|
+
}
|
|
95
|
+
_renderForgotPasswordView() {
|
|
96
|
+
return html`
|
|
97
|
+
<div class="login-form">
|
|
98
|
+
<pd-notice-box type="info" variant="sidebar">
|
|
99
|
+
${msg(
|
|
100
|
+
"Geben Sie Ihre E-Mail-Adresse ein. Sie erhalten einen Link zum Zurücksetzen Ihres Passworts.",
|
|
101
|
+
{
|
|
102
|
+
id: "pd.login.forgot.info"
|
|
103
|
+
}
|
|
104
|
+
)}
|
|
105
|
+
</pd-notice-box>
|
|
106
|
+
|
|
107
|
+
<pd-form-container
|
|
108
|
+
id="forgotPasswordFormId"
|
|
109
|
+
@pd-form-change="${this._handleForgotPasswordFormChange}"
|
|
110
|
+
commonError="${this.errorMessage}"
|
|
111
|
+
>
|
|
112
|
+
<pd-form-row>
|
|
113
|
+
<pd-input
|
|
114
|
+
id="forgotEmail"
|
|
115
|
+
maxlength="250"
|
|
116
|
+
fieldType="mail"
|
|
117
|
+
valueName="email"
|
|
118
|
+
label="${msg("E-Mail", { id: "pd.login.email.label" })}"
|
|
119
|
+
autoCompleteName="email"
|
|
120
|
+
.value="${this._prefillEmail}"
|
|
121
|
+
required
|
|
122
|
+
@enter-pressed="${this._handleForgotPasswordSubmit}"
|
|
123
|
+
></pd-input>
|
|
124
|
+
|
|
125
|
+
<span class="pwd-link">
|
|
126
|
+
<a href="#" @click="${this._handleBackToLogin}"
|
|
127
|
+
>${msg("Zurück zur Anmeldung", {
|
|
128
|
+
id: "pd.login.forgot.back"
|
|
129
|
+
})}</a
|
|
130
|
+
>
|
|
131
|
+
</span>
|
|
132
|
+
</pd-form-row>
|
|
133
|
+
</pd-form-container>
|
|
134
|
+
|
|
135
|
+
<pd-form-row>
|
|
136
|
+
<pd-button
|
|
137
|
+
text="${msg("Link anfordern", { id: "pd.login.forgot.submit" })}"
|
|
138
|
+
icon="${pdIcons.ICON_MAIL}"
|
|
139
|
+
?disabled="${!this._forgotPasswordValidForm || this.loading}"
|
|
140
|
+
?loading="${this.loading}"
|
|
141
|
+
@button-clicked="${this._handleForgotPasswordSubmit}"
|
|
142
|
+
></pd-button>
|
|
143
|
+
</pd-form-row>
|
|
144
|
+
</div>
|
|
145
|
+
`;
|
|
146
|
+
}
|
|
147
|
+
/** Clears the form and resets validation state. */
|
|
148
|
+
clear() {
|
|
149
|
+
this._formElement?.clear();
|
|
150
|
+
this._validForm = false;
|
|
151
|
+
}
|
|
152
|
+
_handleFormChange(e) {
|
|
153
|
+
this._validForm = e.detail.overallValidity;
|
|
154
|
+
e.stopPropagation();
|
|
155
|
+
}
|
|
156
|
+
_handleSubmit() {
|
|
157
|
+
if (!this._formElement?.valid || this.loading) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
const formValues = this._formElement.getValues().origin;
|
|
161
|
+
const detail = {
|
|
162
|
+
email: formValues.email,
|
|
163
|
+
password: formValues.password
|
|
164
|
+
};
|
|
165
|
+
this.dispatchEvent(
|
|
166
|
+
new CustomEvent("login-attempt", {
|
|
167
|
+
detail,
|
|
168
|
+
bubbles: true,
|
|
169
|
+
composed: true
|
|
170
|
+
})
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
_handleForgotPassword(e) {
|
|
174
|
+
e.preventDefault();
|
|
175
|
+
const formValues = this._formElement?.getValues()?.origin;
|
|
176
|
+
this._prefillEmail = formValues?.email || "";
|
|
177
|
+
this._view = "forgot-password";
|
|
178
|
+
}
|
|
179
|
+
_handleForgotPasswordFormChange(e) {
|
|
180
|
+
this._forgotPasswordValidForm = e.detail.overallValidity;
|
|
181
|
+
e.stopPropagation();
|
|
182
|
+
}
|
|
183
|
+
_handleForgotPasswordSubmit() {
|
|
184
|
+
if (!this._forgotPasswordFormElement?.valid || this.loading) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const formValues = this._forgotPasswordFormElement.getValues().origin;
|
|
188
|
+
const detail = {
|
|
189
|
+
email: formValues.email
|
|
190
|
+
};
|
|
191
|
+
this.dispatchEvent(
|
|
192
|
+
new CustomEvent("forgot-password-attempt", {
|
|
193
|
+
detail,
|
|
194
|
+
bubbles: true,
|
|
195
|
+
composed: true
|
|
196
|
+
})
|
|
197
|
+
);
|
|
198
|
+
this._view = "login";
|
|
199
|
+
}
|
|
200
|
+
_handleBackToLogin(e) {
|
|
201
|
+
e.preventDefault();
|
|
202
|
+
this.showLogin();
|
|
203
|
+
}
|
|
204
|
+
/** Switch to forgot password view. */
|
|
205
|
+
showForgotPassword() {
|
|
206
|
+
const formValues = this._formElement?.getValues()?.origin;
|
|
207
|
+
this._prefillEmail = formValues?.email || "";
|
|
208
|
+
this._view = "forgot-password";
|
|
209
|
+
}
|
|
210
|
+
/** Switch back to login view. */
|
|
211
|
+
showLogin() {
|
|
212
|
+
this._view = "login";
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
PdLogin.styles = [
|
|
216
|
+
css`
|
|
217
|
+
:host {
|
|
218
|
+
display: flex;
|
|
219
|
+
justify-content: center;
|
|
220
|
+
width: 100%;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.login-form {
|
|
224
|
+
display: flex;
|
|
225
|
+
flex-flow: column;
|
|
226
|
+
justify-content: center;
|
|
227
|
+
background-color: var(
|
|
228
|
+
--pd-login-bg-color,
|
|
229
|
+
var(--pd-default-bg-light-col)
|
|
230
|
+
);
|
|
231
|
+
padding: var(--pd-login-padding, 1rem 0 1rem 1rem);
|
|
232
|
+
border-radius: var(--pd-login-border-radius, var(--pd-radius-md));
|
|
233
|
+
max-width: var(--pd-login-max-width, 500px);
|
|
234
|
+
width: 100%;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.pwd-link {
|
|
238
|
+
display: block;
|
|
239
|
+
padding-bottom: 0.5em;
|
|
240
|
+
text-align: right;
|
|
241
|
+
font-size: 0.8em;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.pwd-link a {
|
|
245
|
+
color: var(--pd-default-link-col, inherit);
|
|
246
|
+
text-decoration: none;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.pwd-link a:hover {
|
|
250
|
+
text-decoration: underline;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
pd-notice-box {
|
|
254
|
+
margin-bottom: var(--pd-spacing-md, 1rem);
|
|
255
|
+
}
|
|
256
|
+
`
|
|
257
|
+
];
|
|
258
|
+
__decorateClass([
|
|
259
|
+
property({ type: Boolean })
|
|
260
|
+
], PdLogin.prototype, "loading", 2);
|
|
261
|
+
__decorateClass([
|
|
262
|
+
property({ type: String })
|
|
263
|
+
], PdLogin.prototype, "errorMessage", 2);
|
|
264
|
+
__decorateClass([
|
|
265
|
+
property({ type: String })
|
|
266
|
+
], PdLogin.prototype, "successMessage", 2);
|
|
267
|
+
__decorateClass([
|
|
268
|
+
property({ type: Boolean })
|
|
269
|
+
], PdLogin.prototype, "hideForgotPassword", 2);
|
|
270
|
+
__decorateClass([
|
|
271
|
+
state()
|
|
272
|
+
], PdLogin.prototype, "_view", 2);
|
|
273
|
+
__decorateClass([
|
|
274
|
+
state()
|
|
275
|
+
], PdLogin.prototype, "_validForm", 2);
|
|
276
|
+
__decorateClass([
|
|
277
|
+
state()
|
|
278
|
+
], PdLogin.prototype, "_forgotPasswordValidForm", 2);
|
|
279
|
+
__decorateClass([
|
|
280
|
+
state()
|
|
281
|
+
], PdLogin.prototype, "_prefillEmail", 2);
|
|
282
|
+
__decorateClass([
|
|
283
|
+
query("#loginFormId")
|
|
284
|
+
], PdLogin.prototype, "_formElement", 2);
|
|
285
|
+
__decorateClass([
|
|
286
|
+
query("#forgotPasswordFormId")
|
|
287
|
+
], PdLogin.prototype, "_forgotPasswordFormElement", 2);
|
|
288
|
+
PdLogin = __decorateClass([
|
|
289
|
+
localized()
|
|
290
|
+
], PdLogin);
|
|
291
|
+
|
|
292
|
+
export { PdLogin };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pd-login.d.ts","sourceRoot":"","sources":["../../src/pd-login/pd-login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAOvC,OAAO,EAAE,OAAO,EAAE,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/web-components-vite';
|
|
2
|
+
/**
|
|
3
|
+
* Story arguments interface for pd-login component.
|
|
4
|
+
* Maps to the component's public API.
|
|
5
|
+
*/
|
|
6
|
+
interface PdLoginArgs {
|
|
7
|
+
/** Shows loading state on the submit button */
|
|
8
|
+
loading: boolean;
|
|
9
|
+
/** Error message to display above the form */
|
|
10
|
+
errorMessage: string;
|
|
11
|
+
/** Success message to display above the form */
|
|
12
|
+
successMessage: string;
|
|
13
|
+
/** Hide the forgot password link */
|
|
14
|
+
hideForgotPassword: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* ## pd-login
|
|
18
|
+
*
|
|
19
|
+
* Login form component for email/password authentication with a built-in forgot password flow.
|
|
20
|
+
*
|
|
21
|
+
* ### Features
|
|
22
|
+
* - Email and password fields with built-in validation (via pd-form-container)
|
|
23
|
+
* - Loading state that disables the submit button and shows a spinner
|
|
24
|
+
* - Error and success message display via pd-notice-box
|
|
25
|
+
* - Built-in forgot password view with automatic email prefill
|
|
26
|
+
* - Enter key submits the form from any input field
|
|
27
|
+
* - Localized labels via @lit/localize
|
|
28
|
+
*
|
|
29
|
+
* ### Views
|
|
30
|
+
* - **login**: Default form with email, password, and forgot password link
|
|
31
|
+
* - **forgot-password**: Password reset form with email field only
|
|
32
|
+
*
|
|
33
|
+
* ### Accessibility
|
|
34
|
+
* - Uses pd-form-container for proper form semantics and validation
|
|
35
|
+
* - Submit button disabled until form is valid (prevents empty submissions)
|
|
36
|
+
* - Loading state uses aria-busy on the button
|
|
37
|
+
* - Error messages displayed in pd-notice-box for screen reader visibility
|
|
38
|
+
*/
|
|
39
|
+
declare const meta: Meta<PdLoginArgs>;
|
|
40
|
+
export default meta;
|
|
41
|
+
type Story = StoryObj<PdLoginArgs>;
|
|
42
|
+
/** Default login form with standard labels. Interactive via Controls panel. */
|
|
43
|
+
export declare const Default: Story;
|
|
44
|
+
/** Overview of all login form states — default, loading, error, success, and no forgot password. */
|
|
45
|
+
export declare const AllStates: Story;
|
|
46
|
+
/** Forgot password view — demonstrates the built-in password reset flow. */
|
|
47
|
+
export declare const ForgotPasswordFlow: Story;
|
|
48
|
+
/**
|
|
49
|
+
* Interactive login with simulated authentication.
|
|
50
|
+
* Use test@example.com / password123 for success, anything else for error.
|
|
51
|
+
*/
|
|
52
|
+
export declare const InteractiveDemo: Story;
|
|
53
|
+
/** CSS Custom Properties -- Branded and Redesigned variants. */
|
|
54
|
+
export declare const CustomStyling: Story;
|
|
55
|
+
//# sourceMappingURL=pd-login.stories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pd-login.stories.d.ts","sourceRoot":"","sources":["../../src/pd-login/pd-login.stories.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAOrE,OAAO,eAAe,CAAC;AAMvB;;;GAGG;AACH,UAAU,WAAW;IACnB,+CAA+C;IAC/C,OAAO,EAAE,OAAO,CAAC;IACjB,8CAA8C;IAC9C,YAAY,EAAE,MAAM,CAAC;IACrB,gDAAgD;IAChD,cAAc,EAAE,MAAM,CAAC;IACvB,oCAAoC;IACpC,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AA8BD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,WAAW,CAsF3B,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC;AAMnC,+EAA+E;AAC/E,eAAO,MAAM,OAAO,EAAE,KAAU,CAAC;AAMjC,oGAAoG;AACpG,eAAO,MAAM,SAAS,EAAE,KAkDvB,CAAC;AAMF,4EAA4E;AAC5E,eAAO,MAAM,kBAAkB,EAAE,KAwChC,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,KA+C7B,CAAC;AAMF,gEAAgE;AAChE,eAAO,MAAM,aAAa,EAAE,KAkE3B,CAAC"}
|
package/dist/pd-login.js
ADDED
package/dist/pd-menu/PdMenu.d.ts
CHANGED
|
@@ -1,70 +1,102 @@
|
|
|
1
1
|
import { LitElement, CSSResultGroup } from 'lit';
|
|
2
2
|
import { PdMenuItem } from '../types.js';
|
|
3
|
+
import { ButtonData } from '@progressive-development/pd-forms';
|
|
3
4
|
/**
|
|
4
|
-
*
|
|
5
|
+
* Application navigation menu with responsive burger menu.
|
|
5
6
|
*
|
|
6
|
-
* @
|
|
7
|
-
* @fires locale-change – Wird ausgelöst, wenn die Sprache gewechselt wird
|
|
7
|
+
* @summary Responsive navigation menu with scroll-to-section and language selector.
|
|
8
8
|
*
|
|
9
|
-
* @slot slotLogo – Slot für das App-Logo
|
|
10
9
|
* @tagname pd-menu
|
|
10
|
+
*
|
|
11
|
+
* @event route-event - Fired when a menu item with route is clicked.
|
|
12
|
+
* @event locale-change - Fired when language is changed.
|
|
13
|
+
* @event section-activated - Fired when the active section changes during scroll. Detail: `{ sectionId }`.
|
|
14
|
+
*
|
|
15
|
+
* @slot slotLogo - Slot for application logo.
|
|
16
|
+
*
|
|
17
|
+
* @cssprop --pd-menu-height - Menu height. Default: `100px`.
|
|
18
|
+
* @cssprop --pd-menu-bg-col - Menu background. Default: `var(--pd-default-col)`.
|
|
19
|
+
* @cssprop --pd-menu-shadow - Menu shadow. Default: `var(--pd-shadow-lg)`.
|
|
20
|
+
* @cssprop --pd-menu-border-radius - Menu border radius. Default: `0`.
|
|
21
|
+
* @cssprop --pd-menu-max-width - Max menu container width. Default: `var(--pd-content-max-width, 1170px)`.
|
|
22
|
+
* @cssprop --pd-menu-font-col - Menu text color. Default: `var(--pd-default-bg-col)`.
|
|
23
|
+
* @cssprop --pd-menu-font-family - Menu font family. Default: `var(--pd-default-font-title-family)`.
|
|
24
|
+
* @cssprop --pd-menu-font-size - Menu font size. Default: `1.2em`.
|
|
25
|
+
* @cssprop --pd-menu-font-weight - Menu font weight. Default: `bold`.
|
|
26
|
+
* @cssprop --pd-menu-item-padding - Menu item padding. Default: `0.6em`.
|
|
27
|
+
* @cssprop --pd-menu-item-bg-hover-col - Item hover background.
|
|
28
|
+
* @cssprop --pd-menu-burger-bg-col - Burger menu background. Default: `var(--pd-default-bg-col)`.
|
|
29
|
+
* @cssprop --pd-menu-burger-bottomborder - Burger menu bottom border.
|
|
30
|
+
* @cssprop --pd-menu-burger-top - Burger menu top offset. Default: `var(--pd-menu-height)`.
|
|
31
|
+
* @cssprop --pd-menu-burger-font-col - Burger menu text color. Default: `var(--pd-default-font-link-col)`.
|
|
32
|
+
* @cssprop --pd-menu-logo-maxwidth - Logo max width. Default: `8rem`.
|
|
33
|
+
* @cssprop --pd-menu-logo-padding - Logo padding. Default: `2em`.
|
|
34
|
+
* @cssprop --pd-menu-logo-color - Logo fill color. Default: `#067394`.
|
|
11
35
|
*/
|
|
12
36
|
export declare class PdMenu extends LitElement {
|
|
13
|
-
/**
|
|
14
|
-
* Aktuelle aktive Route (zur Hervorhebung)
|
|
15
|
-
*/
|
|
37
|
+
/** Currently active route for highlighting. */
|
|
16
38
|
activeRoute: string;
|
|
17
|
-
/**
|
|
18
|
-
* Aktuell ausgewählte Sprache
|
|
19
|
-
*/
|
|
39
|
+
/** Currently selected language (value from ButtonData). */
|
|
20
40
|
selectedLocale: string;
|
|
21
|
-
/**
|
|
22
|
-
* Aktuell ausgewählte Sprache
|
|
23
|
-
*/
|
|
41
|
+
/** Route to navigate on logo click. */
|
|
24
42
|
logoRoute?: string;
|
|
25
|
-
/**
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
locales: string[];
|
|
29
|
-
/**
|
|
30
|
-
* Hauptmenüeinträge
|
|
31
|
-
*/
|
|
43
|
+
/** Available language options with text (display) and value (locale code). */
|
|
44
|
+
locales: ButtonData[];
|
|
45
|
+
/** Main menu entries. */
|
|
32
46
|
menuItems: PdMenuItem[];
|
|
33
|
-
/**
|
|
34
|
-
* Zusätzliche Einträge in der oberen Menüzeile
|
|
35
|
-
*/
|
|
47
|
+
/** Additional entries in top menu. */
|
|
36
48
|
topMenuItems: PdMenuItem[];
|
|
37
|
-
/**
|
|
38
|
-
* Flag, ob Burger-Menü deaktiviert ist
|
|
39
|
-
*/
|
|
49
|
+
/** Disable responsive burger menu. */
|
|
40
50
|
noBurgerMenu: boolean;
|
|
41
|
-
/**
|
|
42
|
-
* Größe des Headers (für Scroll-Berechnung)
|
|
43
|
-
*/
|
|
44
|
-
headerSize: number;
|
|
45
51
|
/**
|
|
46
52
|
* Index des aktiven Inhaltsbereichs (bei Scroll)
|
|
47
|
-
*/
|
|
53
|
+
* @ignore */
|
|
48
54
|
private _activeSecIndex;
|
|
49
55
|
/**
|
|
50
56
|
* Burger-Menü aktiv?
|
|
51
|
-
*/
|
|
57
|
+
* @ignore */
|
|
52
58
|
private _activeBurgerMenu;
|
|
53
|
-
/**
|
|
54
|
-
* Sprachmenü aktiv?
|
|
55
|
-
*/
|
|
56
|
-
private _activeLocaleMenu;
|
|
57
59
|
/**
|
|
58
60
|
* Zeige mobile Ansicht?
|
|
59
|
-
*/
|
|
61
|
+
* @ignore */
|
|
60
62
|
private _smallScreen;
|
|
63
|
+
/** @ignore */
|
|
64
|
+
private _mediaQueryList?;
|
|
65
|
+
/** @ignore */
|
|
66
|
+
private _boundScrollHandler;
|
|
67
|
+
/** @ignore */
|
|
68
|
+
private _boundMediaQueryHandler;
|
|
61
69
|
static styles: CSSResultGroup;
|
|
62
|
-
|
|
70
|
+
connectedCallback(): void;
|
|
71
|
+
disconnectedCallback(): void;
|
|
72
|
+
private _ticking;
|
|
73
|
+
private _handleScroll;
|
|
74
|
+
private _handleMediaQuery;
|
|
75
|
+
private _updateActiveSection;
|
|
63
76
|
render(): import('lit').TemplateResult<1>;
|
|
64
77
|
private _renderItems;
|
|
78
|
+
/**
|
|
79
|
+
* Handles keyboard events on menu items.
|
|
80
|
+
*/
|
|
81
|
+
private _handleMenuItemKeydown;
|
|
82
|
+
/**
|
|
83
|
+
* Handles keyboard events on burger menu toggle.
|
|
84
|
+
*/
|
|
85
|
+
private _handleBurgerKeydown;
|
|
65
86
|
private _toggleBurgerMenu;
|
|
66
|
-
|
|
67
|
-
|
|
87
|
+
/**
|
|
88
|
+
* Returns the index of the currently selected locale in the locales array.
|
|
89
|
+
*/
|
|
90
|
+
private _getSelectedLocaleIndex;
|
|
91
|
+
/**
|
|
92
|
+
* Returns compact locale options for mobile display.
|
|
93
|
+
* Uses shortText if available, otherwise falls back to text.
|
|
94
|
+
*/
|
|
95
|
+
private _getCompactLocales;
|
|
96
|
+
/**
|
|
97
|
+
* Handles locale selection change from PdButtonSelectGroup.
|
|
98
|
+
*/
|
|
99
|
+
private _handleLocaleChange;
|
|
68
100
|
private _menuItemClicked;
|
|
69
101
|
private _logoClicked;
|
|
70
102
|
private static _scrollToTop;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PdMenu.d.ts","sourceRoot":"","sources":["../../src/pd-menu/PdMenu.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,cAAc,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"PdMenu.d.ts","sourceRoot":"","sources":["../../src/pd-menu/PdMenu.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,cAAc,EAAE,MAAM,KAAK,CAAC;AAO5D,OAAO,0CAA0C,CAAC;AAClD,OAAO,0DAA0D,CAAC;AAElE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAEpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,qBACa,MAAO,SAAQ,UAAU;IACpC,+CAA+C;IAE/C,WAAW,SAAM;IAEjB,2DAA2D;IAE3D,cAAc,SAAM;IAEpB,uCAAuC;IAEvC,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,8EAA8E;IAE9E,OAAO,EAAE,UAAU,EAAE,CAAM;IAE3B,yBAAyB;IAEzB,SAAS,EAAE,UAAU,EAAE,CAAM;IAE7B,sCAAsC;IAEtC,YAAY,EAAE,UAAU,EAAE,CAAM;IAEhC,sCAAsC;IAEtC,YAAY,UAAS;IAErB;;iBAEa;IAEb,OAAO,CAAC,eAAe,CAAK;IAE5B;;iBAEa;IAEb,OAAO,CAAC,iBAAiB,CAAS;IAElC;;iBAEa;IAEb,OAAO,CAAC,YAAY,CAAS;IAE7B,cAAc;IACd,OAAO,CAAC,eAAe,CAAC,CAAiB;IAEzC,cAAc;IACd,OAAO,CAAC,mBAAmB,CAAiC;IAE5D,cAAc;IACd,OAAO,CAAC,uBAAuB,CAAqC;IAEpE,OAAgB,MAAM,EAAE,cAAc,CAgOpC;IAEO,iBAAiB;IAiBjB,oBAAoB;IAe7B,OAAO,CAAC,QAAQ,CAAS;IAEzB,OAAO,CAAC,aAAa;IAWrB,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,oBAAoB;IA0D5B,MAAM;IAqFN,OAAO,CAAC,YAAY;IAgCpB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAO9B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAU5B,OAAO,CAAC,iBAAiB;IAIzB;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAI/B;;;OAGG;IACH,OAAO,CAAC,kBAAkB;IAO1B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAc3B,OAAO,CAAC,gBAAgB;IA8CxB,OAAO,CAAC,YAAY;IAgBpB,OAAO,CAAC,MAAM,CAAC,YAAY;CAG5B"}
|