@progressive-development/pd-spa-helper 0.0.1 → 0.0.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/dist/src/InitApplicationData.d.ts +3 -0
- package/dist/src/InitApplicationData.js +8 -0
- package/dist/src/InitApplicationData.js.map +1 -0
- package/dist/src/PdSpaHelper.d.ts +111 -6
- package/dist/src/PdSpaHelper.js +410 -12
- package/dist/src/PdSpaHelper.js.map +1 -1
- package/dist/src/defaultpage/default-login.d.ts +5 -0
- package/dist/src/defaultpage/default-login.js +16 -0
- package/dist/src/defaultpage/default-login.js.map +1 -0
- package/dist/src/firebase/auth.d.ts +4 -0
- package/dist/src/firebase/auth.js +28 -0
- package/dist/src/firebase/auth.js.map +1 -0
- package/dist/src/firebase/firestore-client.d.ts +9 -0
- package/dist/src/firebase/firestore-client.js +19 -0
- package/dist/src/firebase/firestore-client.js.map +1 -0
- package/dist/src/firebase/functions-client.d.ts +31 -0
- package/dist/src/firebase/functions-client.js +70 -0
- package/dist/src/firebase/functions-client.js.map +1 -0
- package/dist/src/pd-spa-helper.d.ts +0 -1
- package/dist/src/pd-spa-helper.js +4 -2
- package/dist/src/pd-spa-helper.js.map +1 -1
- package/dist/src/router/AppMain.d.ts +6 -0
- package/dist/src/router/AppMain.js +14 -0
- package/dist/src/router/AppMain.js.map +1 -0
- package/dist/src/service-call-controller2.d.ts +16 -0
- package/dist/src/service-call-controller2.js +43 -0
- package/dist/src/service-call-controller2.js.map +1 -0
- package/dist/src/tmpown/pd-login.d.ts +14 -0
- package/dist/src/tmpown/pd-login.js +118 -0
- package/dist/src/tmpown/pd-login.js.map +1 -0
- package/dist/src/tmpown/pd-panel-viewer.d.ts +18 -0
- package/dist/src/tmpown/pd-panel-viewer.js +187 -0
- package/dist/src/tmpown/pd-panel-viewer.js.map +1 -0
- package/dist/src/tmpown/pd-panel.d.ts +5 -0
- package/dist/src/tmpown/pd-panel.js +41 -0
- package/dist/src/tmpown/pd-panel.js.map +1 -0
- package/dist/src/tmpown/pd-toast.d.ts +12 -0
- package/dist/src/tmpown/pd-toast.js +114 -0
- package/dist/src/tmpown/pd-toast.js.map +1 -0
- package/dist/test/pd-spa-helper.test.js +2 -2
- package/dist/test/pd-spa-helper.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -1
- package/pd-spa-helper.iml +9 -0
- package/src/InitApplicationData.ts +9 -0
- package/src/PdSpaHelper.ts +490 -16
- package/src/defaultpage/default-login.ts +15 -0
- package/src/firebase/auth.ts +30 -0
- package/src/firebase/firestore-client.ts +21 -0
- package/src/firebase/functions-client.ts +103 -0
- package/src/pd-spa-helper.ts +3 -3
- package/src/router/AppMain.ts +10 -0
- package/src/service-call-controller2.ts +67 -0
- package/src/tmpown/pd-login.ts +126 -0
- package/src/tmpown/pd-panel-viewer.ts +193 -0
- package/src/tmpown/pd-panel.ts +43 -0
- package/src/tmpown/pd-toast.ts +114 -0
- package/test/pd-spa-helper.test.ts +2 -2
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import {LitElement, html} from 'lit';
|
|
2
|
+
import {customElement} from 'lit/decorators.js';
|
|
3
|
+
import {outlet} from 'lit-element-router';
|
|
4
|
+
|
|
5
|
+
@customElement('app-main')
|
|
6
|
+
export class AppMain extends outlet(LitElement) {
|
|
7
|
+
render() {
|
|
8
|
+
return html` <slot></slot> `;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import {ReactiveControllerHost} from 'lit';
|
|
2
|
+
import {initialState, StatusRenderer, Task} from '@lit-labs/task';
|
|
3
|
+
|
|
4
|
+
import { FunctionDefinition, FunctionResult, initController } from './firebase/functions-client.js';
|
|
5
|
+
|
|
6
|
+
export interface ServiceControllerInput {
|
|
7
|
+
promise: Promise<FunctionResult>,
|
|
8
|
+
func: FunctionDefinition,
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export class ServiceCallController {
|
|
12
|
+
|
|
13
|
+
host: ReactiveControllerHost;
|
|
14
|
+
|
|
15
|
+
private task!: Task;
|
|
16
|
+
|
|
17
|
+
private _callDataPromise!: ServiceControllerInput;
|
|
18
|
+
|
|
19
|
+
constructor(host: ReactiveControllerHost) {
|
|
20
|
+
this.host = host;
|
|
21
|
+
this.task = new Task<[ServiceControllerInput], FunctionResult>(host,
|
|
22
|
+
|
|
23
|
+
async ([callDataPromise]: [ServiceControllerInput]) => {
|
|
24
|
+
if (!callDataPromise) {
|
|
25
|
+
return initialState;
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
const result = await callDataPromise.promise;
|
|
29
|
+
return result as FunctionResult;
|
|
30
|
+
} catch (e) {
|
|
31
|
+
console.error("Error: ", e);
|
|
32
|
+
throw new Error(`Failed call function "${callDataPromise.func.name}"`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
}, () => [this.callDataPromise]
|
|
36
|
+
|
|
37
|
+
);
|
|
38
|
+
initController(this);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/*
|
|
42
|
+
set callData(value: FunctionParam) {
|
|
43
|
+
this._callData = value;
|
|
44
|
+
this.host.requestUpdate();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
get callData(): FunctionParam { return this._callData; }
|
|
48
|
+
*/
|
|
49
|
+
|
|
50
|
+
set callDataPromise(value: ServiceControllerInput) {
|
|
51
|
+
this._callDataPromise = value;
|
|
52
|
+
this.host.requestUpdate();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
get callDataPromise(): ServiceControllerInput { return this._callDataPromise; }
|
|
56
|
+
|
|
57
|
+
clear() {
|
|
58
|
+
this.task.status = 0;
|
|
59
|
+
this.host.requestUpdate();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// TODO: Type definition FunctionResult do not work, but work in Homepage Project...
|
|
63
|
+
render(renderFunctions: any) {
|
|
64
|
+
return this.task.render(renderFunctions);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { LitElement, css, html } from 'lit';
|
|
2
|
+
import { customElement } from 'lit/decorators.js';
|
|
3
|
+
|
|
4
|
+
import '@progressive-development/pd-forms/pd-form-container.js';
|
|
5
|
+
import '@progressive-development/pd-forms/pd-form-row.js';
|
|
6
|
+
import '@progressive-development/pd-forms/pd-input.js';
|
|
7
|
+
import '@progressive-development/pd-forms/pd-button.js';
|
|
8
|
+
|
|
9
|
+
import { login } from '../firebase/auth.js';
|
|
10
|
+
|
|
11
|
+
@customElement("pd-login")
|
|
12
|
+
export class PdLogin extends LitElement {
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @event login-success fired when login was successfully
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
static get styles() {
|
|
19
|
+
return [
|
|
20
|
+
css`
|
|
21
|
+
:host {
|
|
22
|
+
display: flex;
|
|
23
|
+
justify-content: center;
|
|
24
|
+
/*min-height: 100vh;
|
|
25
|
+
min-width: 100vh;*/
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.login-form {
|
|
29
|
+
display: flex;
|
|
30
|
+
flex-flow: column;
|
|
31
|
+
justify-content: center;
|
|
32
|
+
--pd-form-row-allign: center;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
`,
|
|
36
|
+
];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
render() {
|
|
40
|
+
return html`
|
|
41
|
+
<div class="login-form">
|
|
42
|
+
<pd-form-container id="loginFormId">
|
|
43
|
+
|
|
44
|
+
<pd-form-row>
|
|
45
|
+
<pd-input
|
|
46
|
+
id="eMail"
|
|
47
|
+
class="quarter3"
|
|
48
|
+
maxlength="250"
|
|
49
|
+
field-type="mail"
|
|
50
|
+
valueName="email"
|
|
51
|
+
label="E-mail"
|
|
52
|
+
autoCompleteName="email"
|
|
53
|
+
required
|
|
54
|
+
@enter-pressed="${this._accessLogin}"
|
|
55
|
+
></pd-input>
|
|
56
|
+
</pd-form-row>
|
|
57
|
+
|
|
58
|
+
<pd-form-row>
|
|
59
|
+
<pd-input
|
|
60
|
+
id="pWord"
|
|
61
|
+
class="quarter3"
|
|
62
|
+
secret
|
|
63
|
+
maxlength="30"
|
|
64
|
+
label="Password"
|
|
65
|
+
required
|
|
66
|
+
@enter-pressed="${this._accessLogin}"
|
|
67
|
+
></pd-input>
|
|
68
|
+
</pd-form-row>
|
|
69
|
+
|
|
70
|
+
<pd-form-row>
|
|
71
|
+
<pd-button class="quarter3" primary text="Login" @click="${this._accessLogin}"></pd-button>
|
|
72
|
+
</pd-form-row>
|
|
73
|
+
|
|
74
|
+
</pd-form-container>
|
|
75
|
+
</div>
|
|
76
|
+
|
|
77
|
+
`;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
_accessLogin() {
|
|
81
|
+
|
|
82
|
+
// validate form
|
|
83
|
+
const detail = {
|
|
84
|
+
errorMap: new Map()
|
|
85
|
+
};
|
|
86
|
+
this.shadowRoot?.getElementById("loginFormId")?.dispatchEvent(
|
|
87
|
+
new CustomEvent("validate-form", {detail}));
|
|
88
|
+
|
|
89
|
+
if (detail.errorMap.size === 0) {
|
|
90
|
+
|
|
91
|
+
// get form elements as input elements (for value access)
|
|
92
|
+
const elMail = this.shadowRoot?.getElementById('eMail') as HTMLInputElement;
|
|
93
|
+
const elSec = this.shadowRoot?.getElementById('pWord') as HTMLInputElement;
|
|
94
|
+
|
|
95
|
+
login(elMail?.value, elSec?.value)
|
|
96
|
+
.then(() => {
|
|
97
|
+
this.dispatchEvent(new CustomEvent("login-success"));
|
|
98
|
+
}).catch(error => {
|
|
99
|
+
switch (error.code) {
|
|
100
|
+
case 'auth/invalid-email':
|
|
101
|
+
// returnError.eType = 'user';
|
|
102
|
+
// returnError.logMsg = 'Invalid mail format';
|
|
103
|
+
this._dispatchToastEvent("E-Mail Format für Benutzer ist ungültig.");
|
|
104
|
+
break;
|
|
105
|
+
case 'auth/wrong-password':
|
|
106
|
+
case 'auth/user-not-found':
|
|
107
|
+
this._dispatchToastEvent("Anmeldung fehlgeschlagen, ungültige Benutzerdaten.");
|
|
108
|
+
break;
|
|
109
|
+
default:
|
|
110
|
+
this._dispatchToastEvent("Technisches Problem aufgetreten, die Anmeldung kann leider aktuell nicht durchgeführt werden.");
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
_dispatchToastEvent(txt: string) {
|
|
117
|
+
this.dispatchEvent(new CustomEvent("toast-event",{
|
|
118
|
+
detail: {
|
|
119
|
+
txt, isError: true,
|
|
120
|
+
},
|
|
121
|
+
bubbles: true,
|
|
122
|
+
composed: true
|
|
123
|
+
}));
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/* eslint-disable lit-a11y/click-events-have-key-events */
|
|
2
|
+
// https://stackblitz.com/edit/lit-story-viewer?file=story-viewer.ts
|
|
3
|
+
|
|
4
|
+
import { html, css, LitElement } from 'lit';
|
|
5
|
+
import { customElement, property } from 'lit/decorators.js';
|
|
6
|
+
import { classMap } from 'lit/directives/class-map.js';
|
|
7
|
+
|
|
8
|
+
import 'hammerjs';
|
|
9
|
+
|
|
10
|
+
import '@progressive-development/pd-icon/pd-icon.js';
|
|
11
|
+
|
|
12
|
+
let timer:any;
|
|
13
|
+
|
|
14
|
+
@customElement("pd-panel-viewer")
|
|
15
|
+
export class PdPanelViewer extends LitElement {
|
|
16
|
+
|
|
17
|
+
@property({type: Boolean})
|
|
18
|
+
withProgress = false;
|
|
19
|
+
|
|
20
|
+
@property({type: Number})
|
|
21
|
+
deltaCalc = 3;
|
|
22
|
+
|
|
23
|
+
@property({type: Number, state: true})
|
|
24
|
+
_index = 0;
|
|
25
|
+
|
|
26
|
+
@property({type: Object, state: true})
|
|
27
|
+
// eslint-disable-next-line no-undef
|
|
28
|
+
_panData:any = {};
|
|
29
|
+
|
|
30
|
+
@property({type: Boolean, state: true})
|
|
31
|
+
_update = {};
|
|
32
|
+
|
|
33
|
+
static styles = css`
|
|
34
|
+
|
|
35
|
+
:host {
|
|
36
|
+
display: flex;
|
|
37
|
+
flex-direction: column;
|
|
38
|
+
width: 100%;
|
|
39
|
+
max-width: var(--pd-panel-width, 1170px);
|
|
40
|
+
overflow: var(--pd-panel-overflow, hidden);
|
|
41
|
+
background-color: var(--pd-panel-viewer-bg-col);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.panel-container {
|
|
45
|
+
position: relative;
|
|
46
|
+
height: var(--pd-panel-height, 60vh);
|
|
47
|
+
width: 100%;
|
|
48
|
+
display: flex;
|
|
49
|
+
flex-direction: column;
|
|
50
|
+
padding: 0 2rem;
|
|
51
|
+
box-sizing: border-box;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
pd-icon {
|
|
55
|
+
position: absolute;
|
|
56
|
+
top: calc(50% - 25px);
|
|
57
|
+
height: 50px;
|
|
58
|
+
cursor: pointer;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
#prev {
|
|
62
|
+
left: 0;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
#next {
|
|
66
|
+
right: 0;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
#progress {
|
|
70
|
+
position: relative;
|
|
71
|
+
height: 20px;
|
|
72
|
+
width: 50%;
|
|
73
|
+
margin: .5rem auto;
|
|
74
|
+
display: grid;
|
|
75
|
+
grid-auto-flow: column;
|
|
76
|
+
grid-auto-columns: 1fr;
|
|
77
|
+
grid-gap: 10px;
|
|
78
|
+
align-content: center;
|
|
79
|
+
align-self: flex-end;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
#progress > div {
|
|
83
|
+
background: var(--pd-panel-progress-col, grey);
|
|
84
|
+
height: 4px;
|
|
85
|
+
transition: background 0.3s linear;
|
|
86
|
+
cursor: pointer;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
#progress > div.watched {
|
|
90
|
+
background: var(--pd-panel-progress-col, yellow);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
::slotted(*) {
|
|
94
|
+
position: absolute;
|
|
95
|
+
width: 100%;
|
|
96
|
+
height: calc(100%);
|
|
97
|
+
transition: transform 0.35s ease-out;
|
|
98
|
+
left: 0;
|
|
99
|
+
}
|
|
100
|
+
`;
|
|
101
|
+
|
|
102
|
+
get index() {
|
|
103
|
+
return this._index;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
set index(value) {
|
|
107
|
+
this.children[this._index].dispatchEvent(new CustomEvent('exited'));
|
|
108
|
+
this.children[value].dispatchEvent(new CustomEvent('entered'));
|
|
109
|
+
this._index = value;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
render() {
|
|
113
|
+
return html`
|
|
114
|
+
<div class="panel-container">
|
|
115
|
+
<slot></slot>
|
|
116
|
+
<pd-icon id="prev" icon="previousArrow" activeIcon ?disabled="${this.index <= 0}" @click=${this.previous}></pd-icon>
|
|
117
|
+
<pd-icon id="next" icon="nextArrow" activeIcon ?disabled="${this.index === (this.children.length - 1)}" @click=${this.next}></pd-icon>
|
|
118
|
+
</div>
|
|
119
|
+
${this.withProgress ? html`
|
|
120
|
+
<div id="progress">
|
|
121
|
+
${Array.from(this.children).map((childEl, i) => html`
|
|
122
|
+
<div @click="${() => {this._index = i;}}" class=${classMap({watched: i <= this.index})}></div>`)}
|
|
123
|
+
</div>` : ''}
|
|
124
|
+
`;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
firstUpdated() {
|
|
129
|
+
const hammerVal = new Hammer(this);
|
|
130
|
+
// listen to events
|
|
131
|
+
hammerVal.on('pan', (panEvent: any) => {
|
|
132
|
+
this._panData = panEvent;
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// Do updates to rerender panel viewer, timeout to reduce updates
|
|
136
|
+
// https://web.dev/resize-observer/
|
|
137
|
+
const ro = new ResizeObserver(entries => {
|
|
138
|
+
entries.forEach(() => {
|
|
139
|
+
window.clearTimeout(timer);
|
|
140
|
+
timer = setTimeout(() => {
|
|
141
|
+
this.requestUpdate();
|
|
142
|
+
}, 100);
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
ro.observe(this);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
update(changedProperties:any) {
|
|
149
|
+
const {isFinal = false} = this._panData;
|
|
150
|
+
let {deltaX = 0} = this._panData;
|
|
151
|
+
|
|
152
|
+
const width = this.clientWidth;
|
|
153
|
+
const minScale = 0.8;
|
|
154
|
+
|
|
155
|
+
// Guard against an infinite loop by looking for index.
|
|
156
|
+
if (!changedProperties.has("_index") && isFinal) {
|
|
157
|
+
if ( deltaX > (width / this.deltaCalc)) {
|
|
158
|
+
this.previous();
|
|
159
|
+
} else if(deltaX < (-width / this.deltaCalc)) {
|
|
160
|
+
this.next();
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// We don't want the latent deltaX when releasing a pan.
|
|
165
|
+
deltaX = (isFinal ? 0 : deltaX);
|
|
166
|
+
|
|
167
|
+
Array.from(this.children).forEach((el:any, i) => {
|
|
168
|
+
const x = (i - this.index) * width + deltaX;
|
|
169
|
+
// Piecewise scale(deltaX), looks like: __/\__
|
|
170
|
+
const u = deltaX / width + (i - this.index);
|
|
171
|
+
const v = -Math.abs(u * (1 - minScale)) + 1;
|
|
172
|
+
const scale = Math.max(v, minScale);
|
|
173
|
+
// eslint-disable-next-line no-param-reassign
|
|
174
|
+
el.style.transform = `translate3d(${x}px,0,0) scale(${scale})`;
|
|
175
|
+
// eslint-disable-next-line no-param-reassign
|
|
176
|
+
el.style.opacity = scale;
|
|
177
|
+
});
|
|
178
|
+
super.update(changedProperties);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/* Advance to the next story card if possible */
|
|
182
|
+
next() {
|
|
183
|
+
this.index = Math.max(0, Math.min(this.children.length - 1, this.index + 1));
|
|
184
|
+
this._update = false;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/* Go back to the previous story card if possible */
|
|
188
|
+
previous() {
|
|
189
|
+
this.index = Math.max(0, Math.min(this.children.length - 1, this.index - 1));
|
|
190
|
+
this._update = false;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// https://stackblitz.com/edit/lit-story-viewer?file=story-viewer.ts
|
|
2
|
+
|
|
3
|
+
import { html, LitElement, css } from 'lit';
|
|
4
|
+
import { customElement } from 'lit/decorators.js';
|
|
5
|
+
|
|
6
|
+
@customElement("pd-panel")
|
|
7
|
+
export class PdPanel extends LitElement {
|
|
8
|
+
|
|
9
|
+
static styles =
|
|
10
|
+
css`
|
|
11
|
+
:host {
|
|
12
|
+
background: var(--pd-panel-bg, #AFC1D2);
|
|
13
|
+
border-radius: var(--pd-panel-border-radius, 0.2em);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/* Default styles for content */
|
|
17
|
+
#content {
|
|
18
|
+
position: absolute;
|
|
19
|
+
top: 0;
|
|
20
|
+
right: 0;
|
|
21
|
+
bottom: 0;
|
|
22
|
+
left: 0;
|
|
23
|
+
padding: 2rem;
|
|
24
|
+
display: flex;
|
|
25
|
+
flex-direction: column;
|
|
26
|
+
align-items: center;
|
|
27
|
+
justify-content: flex-start;
|
|
28
|
+
}
|
|
29
|
+
#content > slot::slotted(*) {
|
|
30
|
+
margin: 0;
|
|
31
|
+
}
|
|
32
|
+
`;
|
|
33
|
+
|
|
34
|
+
render() {
|
|
35
|
+
return html`
|
|
36
|
+
<div id="content">
|
|
37
|
+
<slot></slot>
|
|
38
|
+
</div>
|
|
39
|
+
`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/* eslint-disable wc/no-self-class */
|
|
2
|
+
import { LitElement, html, css } from 'lit';
|
|
3
|
+
import { customElement, property } from 'lit/decorators.js';
|
|
4
|
+
|
|
5
|
+
@customElement("pd-toast")
|
|
6
|
+
export class PdToast extends LitElement {
|
|
7
|
+
|
|
8
|
+
@property({type: Boolean, reflect: true})
|
|
9
|
+
isError: boolean = false;
|
|
10
|
+
|
|
11
|
+
@property({type: Boolean, reflect: true})
|
|
12
|
+
isSuccess: boolean = false;
|
|
13
|
+
|
|
14
|
+
@property({type: Number})
|
|
15
|
+
duration: number = -100;
|
|
16
|
+
|
|
17
|
+
static styles =
|
|
18
|
+
css`
|
|
19
|
+
:host {
|
|
20
|
+
--pd-icon-size: 1rem;
|
|
21
|
+
|
|
22
|
+
transform: translateX(-150%);
|
|
23
|
+
transition: transform 1s;
|
|
24
|
+
|
|
25
|
+
/* Other styles */
|
|
26
|
+
position: fixed;
|
|
27
|
+
bottom: 30px;
|
|
28
|
+
left: 30px;
|
|
29
|
+
width: calc(100% - 60px);
|
|
30
|
+
max-width: 400px;
|
|
31
|
+
|
|
32
|
+
z-index: 5;
|
|
33
|
+
|
|
34
|
+
background: var(--app-primary-color, #ebcf57);
|
|
35
|
+
color: #0A3A48;
|
|
36
|
+
padding: .5rem;
|
|
37
|
+
border-radius: var(--item-border-radius, 2px);
|
|
38
|
+
box-shadow: 3px 5px 5px 3px lightgrey;
|
|
39
|
+
display: flex;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
:host([isError]) {
|
|
43
|
+
background: darkred;
|
|
44
|
+
color: #fff;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
:host([isSuccess]) {
|
|
48
|
+
background: green;
|
|
49
|
+
color: #fff;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
:host(.show) {
|
|
53
|
+
transform: translateX(0%);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.close-link {
|
|
57
|
+
margin-left: auto;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
`;
|
|
61
|
+
|
|
62
|
+
render() {
|
|
63
|
+
return html`
|
|
64
|
+
<slot></slot>
|
|
65
|
+
<pd-icon @click="${this._close}" icon="closeLink" class="close-link"></pd-icon>
|
|
66
|
+
`;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
connectedCallback() {
|
|
70
|
+
// eslint-disable-next-line wc/guard-super-call
|
|
71
|
+
super.connectedCallback();
|
|
72
|
+
this.setAttribute('aria-live', 'polite');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
updated(changedProps:any) {
|
|
76
|
+
if (changedProps.has('duration')) {
|
|
77
|
+
if (this.duration === -100) {
|
|
78
|
+
this._close();
|
|
79
|
+
} else {
|
|
80
|
+
this._show();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
_show() {
|
|
86
|
+
return new Promise((resolve) => {
|
|
87
|
+
if (this.className === 'show') {
|
|
88
|
+
// Do nothing, prevent spamming
|
|
89
|
+
} else {
|
|
90
|
+
// 1000ms to not overlap fadein and fadeout animations
|
|
91
|
+
if (this.duration >= 1000) {
|
|
92
|
+
this.style.animation = `fadein 0.5s, fadeout 0.5s ${this.duration - 500}ms`;
|
|
93
|
+
}
|
|
94
|
+
this.className = 'show';
|
|
95
|
+
|
|
96
|
+
if (this.duration > 0) {
|
|
97
|
+
setTimeout(
|
|
98
|
+
() => {
|
|
99
|
+
this._close();
|
|
100
|
+
resolve("Ok");
|
|
101
|
+
},
|
|
102
|
+
this.duration >= 1000 ? this.duration : 3000
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
_close() {
|
|
110
|
+
this.style.animation = '';
|
|
111
|
+
this.className = this.className.replace('show', '');
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
@@ -8,14 +8,14 @@ describe('PdSpaHelper', () => {
|
|
|
8
8
|
const el = await fixture<PdSpaHelper>(html`<pd-spa-helper></pd-spa-helper>`);
|
|
9
9
|
|
|
10
10
|
expect(el.title).to.equal('Hey there');
|
|
11
|
-
expect(el.counter).to.equal(5);
|
|
11
|
+
// expect(el.counter).to.equal(5);
|
|
12
12
|
});
|
|
13
13
|
|
|
14
14
|
it('increases the counter on button click', async () => {
|
|
15
15
|
const el = await fixture<PdSpaHelper>(html`<pd-spa-helper></pd-spa-helper>`);
|
|
16
16
|
el.shadowRoot!.querySelector('button')!.click();
|
|
17
17
|
|
|
18
|
-
expect(el.counter).to.equal(6);
|
|
18
|
+
// expect(el.counter).to.equal(6);
|
|
19
19
|
});
|
|
20
20
|
|
|
21
21
|
it('can override the title via attribute', async () => {
|