@progressive-development/pd-page 0.9.1 → 1.0.0
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 -134
- 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-content/dist/pd-notice-box/PdNoticeBox.js +224 -0
- package/dist/pd-content/dist/pd-notice-box/pd-notice-box.js +8 -0
- 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 -74
- 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 -276
- 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 +14 -8
|
@@ -1,28 +1,111 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { css, LitElement, nothing, html } from 'lit';
|
|
2
2
|
import { property } from 'lit/decorators.js';
|
|
3
|
-
import {
|
|
3
|
+
import { localized, msg } from '@lit/localize';
|
|
4
4
|
|
|
5
5
|
var __defProp = Object.defineProperty;
|
|
6
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
7
|
var __decorateClass = (decorators, target, key, kind) => {
|
|
7
|
-
var result = void 0 ;
|
|
8
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
8
9
|
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
9
10
|
if (decorator = decorators[i])
|
|
10
|
-
result = (decorator(target, key, result) ) || result;
|
|
11
|
-
if (result) __defProp(target, key, result);
|
|
11
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
12
|
+
if (kind && result) __defProp(target, key, result);
|
|
12
13
|
return result;
|
|
13
14
|
};
|
|
14
|
-
|
|
15
|
+
let PdFooter = class extends LitElement {
|
|
15
16
|
constructor() {
|
|
16
17
|
super(...arguments);
|
|
17
18
|
this.copyright = "";
|
|
18
19
|
this.version = "";
|
|
19
20
|
this.footerLinks = [];
|
|
20
21
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
render() {
|
|
23
|
+
return html`
|
|
24
|
+
<nav
|
|
25
|
+
class="footer-links"
|
|
26
|
+
aria-label="${msg("Footer Navigation", { id: "pd.footer.nav.aria" })}"
|
|
27
|
+
>
|
|
28
|
+
<ul role="list">
|
|
29
|
+
${this.footerLinks?.map(
|
|
30
|
+
(link) => html`
|
|
31
|
+
<li
|
|
32
|
+
role="button"
|
|
33
|
+
tabindex="0"
|
|
34
|
+
data-link="${link.key}"
|
|
35
|
+
@click="${this._footerLinkClicked}"
|
|
36
|
+
@keydown="${this._handleLinkKeydown}"
|
|
37
|
+
>
|
|
38
|
+
${link.name}
|
|
39
|
+
</li>
|
|
40
|
+
`
|
|
41
|
+
)}
|
|
42
|
+
</ul>
|
|
43
|
+
</nav>
|
|
44
|
+
|
|
45
|
+
<div class="bottom-line">
|
|
46
|
+
<div>
|
|
47
|
+
${this.copyright ? html`<span class="copyright">© ${this.copyright}, </span>` : nothing}
|
|
48
|
+
${this.version ? html`<span class="version">${this.version}</span>` : nothing}
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
${this.madeBy ? html`<span
|
|
52
|
+
class="made-by"
|
|
53
|
+
role="button"
|
|
54
|
+
tabindex="0"
|
|
55
|
+
@click="${this._clickMadeBy}"
|
|
56
|
+
@keydown="${this._handleMadeByKeydown}"
|
|
57
|
+
>${this.madeBy.txt}</span
|
|
58
|
+
>` : nothing}
|
|
59
|
+
</div>
|
|
60
|
+
`;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Handles keyboard events on footer links.
|
|
64
|
+
* Activates on Enter or Space key.
|
|
65
|
+
*/
|
|
66
|
+
_handleLinkKeydown(e) {
|
|
67
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
68
|
+
e.preventDefault();
|
|
69
|
+
this._footerLinkClicked(e);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Handles keyboard events on madeBy element.
|
|
74
|
+
* Activates on Enter or Space key.
|
|
75
|
+
*/
|
|
76
|
+
_handleMadeByKeydown(e) {
|
|
77
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
78
|
+
e.preventDefault();
|
|
79
|
+
this._clickMadeBy();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
_clickMadeBy() {
|
|
83
|
+
if (this.madeBy?.email) {
|
|
84
|
+
window.location.href = `mailto:${this.madeBy.email}`;
|
|
85
|
+
} else if (this.madeBy?.link) {
|
|
86
|
+
const url = this.madeBy.link;
|
|
87
|
+
if (url.startsWith("https://") || url.startsWith("http://")) {
|
|
88
|
+
window.open(url, "_blank", "noopener,noreferrer");
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
_footerLinkClicked(e) {
|
|
93
|
+
const target = e.currentTarget;
|
|
94
|
+
const linkKey = target.dataset.link;
|
|
95
|
+
const linkObj = this.footerLinks?.find((fl) => fl.key === linkKey);
|
|
96
|
+
if (linkObj) {
|
|
97
|
+
this.dispatchEvent(
|
|
98
|
+
new CustomEvent("footer-link", {
|
|
99
|
+
detail: { linkObj },
|
|
100
|
+
bubbles: true,
|
|
101
|
+
composed: true
|
|
102
|
+
})
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
PdFooter.styles = [
|
|
108
|
+
css`
|
|
26
109
|
:host {
|
|
27
110
|
display: flex;
|
|
28
111
|
flex-flow: column;
|
|
@@ -37,7 +120,7 @@ class PdFooter extends LitElement {
|
|
|
37
120
|
align-items: center;
|
|
38
121
|
justify-content: right;
|
|
39
122
|
height: 100%;
|
|
40
|
-
color: var(--pd-footer-font-col, var(--pd-
|
|
123
|
+
color: var(--pd-footer-font-col, var(--pd-on-primary-col));
|
|
41
124
|
font-family: var(
|
|
42
125
|
--pd-footer-font-family,
|
|
43
126
|
var(--pd-default-font-link-family)
|
|
@@ -49,9 +132,9 @@ class PdFooter extends LitElement {
|
|
|
49
132
|
display: flex;
|
|
50
133
|
flex-wrap: wrap;
|
|
51
134
|
list-style: none;
|
|
52
|
-
gap:
|
|
135
|
+
gap: var(--pd-spacing-lg);
|
|
53
136
|
margin: 0;
|
|
54
|
-
padding:
|
|
137
|
+
padding: var(--pd-spacing-lg);
|
|
55
138
|
}
|
|
56
139
|
|
|
57
140
|
.footer-links li {
|
|
@@ -62,6 +145,12 @@ class PdFooter extends LitElement {
|
|
|
62
145
|
color: var(--pd-default-hover-col);
|
|
63
146
|
}
|
|
64
147
|
|
|
148
|
+
.footer-links li:focus-visible {
|
|
149
|
+
outline: 2px solid var(--pd-focus-ring-col, var(--pd-default-col));
|
|
150
|
+
outline-offset: 2px;
|
|
151
|
+
border-radius: var(--pd-radius-sm);
|
|
152
|
+
}
|
|
153
|
+
|
|
65
154
|
.bottom-line {
|
|
66
155
|
background-color: var(
|
|
67
156
|
--pd-footer-bottom-col,
|
|
@@ -69,9 +158,9 @@ class PdFooter extends LitElement {
|
|
|
69
158
|
);
|
|
70
159
|
font-size: var(--pd-footer-bottom-font-size, 0.9em);
|
|
71
160
|
color: var(--pd-footer-bottom-font-col, var(--pd-default-dark-col));
|
|
72
|
-
padding:
|
|
161
|
+
padding: var(--pd-spacing-sm);
|
|
73
162
|
display: flex;
|
|
74
|
-
gap:
|
|
163
|
+
gap: var(--pd-spacing-md);
|
|
75
164
|
flex-wrap: wrap;
|
|
76
165
|
justify-content: space-between;
|
|
77
166
|
align-items: center;
|
|
@@ -85,78 +174,37 @@ class PdFooter extends LitElement {
|
|
|
85
174
|
font-weight: normal;
|
|
86
175
|
}
|
|
87
176
|
|
|
88
|
-
.
|
|
177
|
+
.made-by {
|
|
89
178
|
cursor: pointer;
|
|
90
179
|
font-style: italic;
|
|
180
|
+
white-space: normal;
|
|
91
181
|
}
|
|
92
182
|
|
|
93
|
-
.
|
|
183
|
+
.made-by:hover {
|
|
94
184
|
color: var(--pd-default-col);
|
|
95
185
|
}
|
|
96
|
-
`
|
|
97
|
-
];
|
|
98
|
-
}
|
|
99
|
-
render() {
|
|
100
|
-
return html`
|
|
101
|
-
<div class="footer-links">
|
|
102
|
-
<ul>
|
|
103
|
-
${this.footerLinks?.map(
|
|
104
|
-
(link) => html`
|
|
105
|
-
<li>
|
|
106
|
-
<a @click=${this._footerLinkClicked} data-link=${link.key}
|
|
107
|
-
>${link.name}</a
|
|
108
|
-
>
|
|
109
|
-
</li>
|
|
110
|
-
`
|
|
111
|
-
)}
|
|
112
|
-
</ul>
|
|
113
|
-
</div>
|
|
114
186
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
>${this.madeBy.txt}</span
|
|
123
|
-
>` : nothing}
|
|
124
|
-
</div>
|
|
125
|
-
`;
|
|
126
|
-
}
|
|
127
|
-
_clickMadeBy() {
|
|
128
|
-
if (this.madeBy?.email) {
|
|
129
|
-
window.location.href = `mailto:${this.madeBy.email}`;
|
|
130
|
-
} else if (this.madeBy?.link) {
|
|
131
|
-
window.open(this.madeBy.link, "_blank");
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
_footerLinkClicked(e) {
|
|
135
|
-
const target = e.currentTarget;
|
|
136
|
-
const linkKey = target.dataset.link;
|
|
137
|
-
const linkObj = this.footerLinks?.find((fl) => fl.key === linkKey);
|
|
138
|
-
if (linkObj) {
|
|
139
|
-
this.dispatchEvent(
|
|
140
|
-
new CustomEvent("footer-link", {
|
|
141
|
-
detail: { linkObj },
|
|
142
|
-
bubbles: true,
|
|
143
|
-
composed: true
|
|
144
|
-
})
|
|
145
|
-
);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
187
|
+
.made-by:focus-visible {
|
|
188
|
+
outline: 2px solid var(--pd-focus-ring-col, var(--pd-default-col));
|
|
189
|
+
outline-offset: 2px;
|
|
190
|
+
border-radius: var(--pd-radius-sm);
|
|
191
|
+
}
|
|
192
|
+
`
|
|
193
|
+
];
|
|
149
194
|
__decorateClass([
|
|
150
195
|
property({ type: String })
|
|
151
|
-
], PdFooter.prototype, "copyright");
|
|
196
|
+
], PdFooter.prototype, "copyright", 2);
|
|
152
197
|
__decorateClass([
|
|
153
198
|
property({ type: String })
|
|
154
|
-
], PdFooter.prototype, "version");
|
|
199
|
+
], PdFooter.prototype, "version", 2);
|
|
155
200
|
__decorateClass([
|
|
156
201
|
property({ type: Object })
|
|
157
|
-
], PdFooter.prototype, "madeBy");
|
|
202
|
+
], PdFooter.prototype, "madeBy", 2);
|
|
158
203
|
__decorateClass([
|
|
159
204
|
property({ type: Array })
|
|
160
|
-
], PdFooter.prototype, "footerLinks");
|
|
205
|
+
], PdFooter.prototype, "footerLinks", 2);
|
|
206
|
+
PdFooter = __decorateClass([
|
|
207
|
+
localized()
|
|
208
|
+
], PdFooter);
|
|
161
209
|
|
|
162
210
|
export { PdFooter };
|
|
@@ -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 '../pd-content/dist/pd-notice-box/pd-notice-box.js';
|
|
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"}
|