@roots/bud-client 0.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.md +19 -0
- package/README.md +77 -0
- package/lib/hot/client.d.ts +6 -0
- package/lib/hot/client.d.ts.map +1 -0
- package/lib/hot/client.js +143 -0
- package/lib/hot/components/index.d.ts +2 -0
- package/lib/hot/components/index.d.ts.map +1 -0
- package/lib/hot/components/index.js +32 -0
- package/lib/hot/components/indicator/index.d.ts +4 -0
- package/lib/hot/components/indicator/index.d.ts.map +1 -0
- package/lib/hot/components/indicator/index.js +17 -0
- package/lib/hot/components/indicator/indicator.component.d.ts +84 -0
- package/lib/hot/components/indicator/indicator.component.d.ts.map +1 -0
- package/lib/hot/components/indicator/indicator.component.js +175 -0
- package/lib/hot/components/indicator/indicator.controller.d.ts +45 -0
- package/lib/hot/components/indicator/indicator.controller.d.ts.map +1 -0
- package/lib/hot/components/indicator/indicator.controller.js +54 -0
- package/lib/hot/components/indicator/indicator.pulse.d.ts +9 -0
- package/lib/hot/components/indicator/indicator.pulse.d.ts.map +1 -0
- package/lib/hot/components/indicator/indicator.pulse.js +36 -0
- package/lib/hot/components/overlay/index.d.ts +4 -0
- package/lib/hot/components/overlay/index.d.ts.map +1 -0
- package/lib/hot/components/overlay/index.js +17 -0
- package/lib/hot/components/overlay/overlay.component.d.ts +20 -0
- package/lib/hot/components/overlay/overlay.component.d.ts.map +1 -0
- package/lib/hot/components/overlay/overlay.component.js +146 -0
- package/lib/hot/components/overlay/overlay.controller.d.ts +46 -0
- package/lib/hot/components/overlay/overlay.controller.d.ts.map +1 -0
- package/lib/hot/components/overlay/overlay.controller.js +70 -0
- package/lib/hot/events.d.ts +98 -0
- package/lib/hot/events.d.ts.map +1 -0
- package/lib/hot/events.js +89 -0
- package/lib/hot/index.cjs +5 -0
- package/lib/hot/index.d.cts +2 -0
- package/lib/hot/index.d.cts.map +1 -0
- package/lib/hot/index.d.mts +2 -0
- package/lib/hot/index.d.mts.map +1 -0
- package/lib/hot/index.mjs +17 -0
- package/lib/hot/log.d.ts +11 -0
- package/lib/hot/log.d.ts.map +1 -0
- package/lib/hot/log.js +37 -0
- package/lib/hot/options.d.ts +17 -0
- package/lib/hot/options.d.ts.map +1 -0
- package/lib/hot/options.js +33 -0
- package/lib/index.cjs +3 -0
- package/lib/index.d.cts +13 -0
- package/lib/index.d.cts.map +1 -0
- package/lib/index.d.mts +13 -0
- package/lib/index.d.mts.map +1 -0
- package/lib/index.mjs +3 -0
- package/lib/intercept/index.d.ts +3 -0
- package/lib/intercept/index.d.ts.map +1 -0
- package/lib/intercept/index.js +18 -0
- package/lib/intercept/proxy-click-interceptor.d.ts +2 -0
- package/lib/intercept/proxy-click-interceptor.d.ts.map +1 -0
- package/lib/intercept/proxy-click-interceptor.js +26 -0
- package/package.json +79 -0
- package/src/hot/client.test.ts +78 -0
- package/src/hot/client.ts +156 -0
- package/src/hot/components/index.ts +33 -0
- package/src/hot/components/indicator/index.ts +11 -0
- package/src/hot/components/indicator/indicator.component.ts +216 -0
- package/src/hot/components/indicator/indicator.controller.ts +76 -0
- package/src/hot/components/indicator/indicator.pulse.ts +43 -0
- package/src/hot/components/overlay/index.ts +12 -0
- package/src/hot/components/overlay/overlay.component.ts +165 -0
- package/src/hot/components/overlay/overlay.controller.ts +86 -0
- package/src/hot/events.ts +93 -0
- package/src/hot/index.cts +7 -0
- package/src/hot/index.mts +9 -0
- package/src/hot/log.ts +42 -0
- package/src/hot/options.ts +40 -0
- package/src/index.cts +16 -0
- package/src/index.mts +16 -0
- package/src/intercept/index.ts +33 -0
- package/src/intercept/proxy-click-interceptor.ts +18 -0
- package/src/types/index.d.ts +54 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import {pulse} from './indicator.pulse.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Indicator web component
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
export class Component extends HTMLElement {
|
|
8
|
+
/**
|
|
9
|
+
* Has component rendered
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
public rendered: boolean
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Component name
|
|
16
|
+
* @public
|
|
17
|
+
*/
|
|
18
|
+
public name: string = `bud-activity-indicator`
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Root div querySelector selector
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
public get selector() {
|
|
25
|
+
return `.${this.name}`
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Timer
|
|
30
|
+
* @public
|
|
31
|
+
*/
|
|
32
|
+
public hideTimeout: NodeJS.Timer
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Get accessor: has errors
|
|
36
|
+
* @public
|
|
37
|
+
*/
|
|
38
|
+
public get hasErrors(): boolean {
|
|
39
|
+
return this.getAttribute(`has-errors`) == `true`
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Get accessor: has warnings
|
|
44
|
+
* @public
|
|
45
|
+
*/
|
|
46
|
+
public get hasWarnings(): boolean {
|
|
47
|
+
return this.getAttribute(`has-warnings`) == `true`
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Status indicator colors
|
|
52
|
+
* @public
|
|
53
|
+
*/
|
|
54
|
+
public colors: Record<string, [number, number, number, number]> = {
|
|
55
|
+
success: [4, 120, 87, 1],
|
|
56
|
+
error: [220, 38, 38, 1],
|
|
57
|
+
warn: [252, 211, 77, 1],
|
|
58
|
+
pending: [59, 130, 246, 1],
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Class constructor
|
|
63
|
+
* @public
|
|
64
|
+
*/
|
|
65
|
+
public constructor() {
|
|
66
|
+
super()
|
|
67
|
+
this.renderShadow()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Render status indicator
|
|
72
|
+
* @public
|
|
73
|
+
*/
|
|
74
|
+
public renderShadow() {
|
|
75
|
+
const container = document.createElement(`div`)
|
|
76
|
+
container.classList.add(this.name)
|
|
77
|
+
container.innerHTML = `
|
|
78
|
+
<style>
|
|
79
|
+
.bud-activity-indicator {
|
|
80
|
+
position: fixed;
|
|
81
|
+
width: 10px;
|
|
82
|
+
height: 10px;
|
|
83
|
+
left: 10px;
|
|
84
|
+
bottom: 10px;
|
|
85
|
+
z-index: 9999;
|
|
86
|
+
margin: 5px;
|
|
87
|
+
padding: 5px;
|
|
88
|
+
-webkit-transition:
|
|
89
|
+
all .6s ease-in-out,
|
|
90
|
+
transition:
|
|
91
|
+
all .6s ease-in-out;
|
|
92
|
+
animation-fill-mode: forwards;
|
|
93
|
+
pointer-events: none;
|
|
94
|
+
border-radius: 50%;
|
|
95
|
+
transform: scale(0);
|
|
96
|
+
opacity: 0;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.show {
|
|
100
|
+
opacity: 1;
|
|
101
|
+
background-color: rgba(255, 255, 255, 1);
|
|
102
|
+
transform: scale(1);
|
|
103
|
+
transition:
|
|
104
|
+
all .6s ease-in-out;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
${pulse(`success`, this.colors.success)}
|
|
108
|
+
${pulse(`error`, this.colors.error)}
|
|
109
|
+
${pulse(`warning`, this.colors.warn)}
|
|
110
|
+
${pulse(`pending`, this.colors.pending)}
|
|
111
|
+
|
|
112
|
+
</style>
|
|
113
|
+
`
|
|
114
|
+
|
|
115
|
+
this.attachShadow({mode: `open`}).appendChild(container)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Show status indicator
|
|
120
|
+
* @public
|
|
121
|
+
*/
|
|
122
|
+
public show() {
|
|
123
|
+
this.hideTimeout && clearTimeout(this.hideTimeout)
|
|
124
|
+
this.shadowRoot.querySelector(this.selector).classList.add(`show`)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Hide status indicator
|
|
129
|
+
*/
|
|
130
|
+
public hide() {
|
|
131
|
+
this.hideTimeout = setTimeout(() => {
|
|
132
|
+
this.shadowRoot.querySelector(this.selector).classList.remove(`show`)
|
|
133
|
+
}, 2000)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Status is pending
|
|
138
|
+
* @public
|
|
139
|
+
*/
|
|
140
|
+
public onPending() {
|
|
141
|
+
this.show()
|
|
142
|
+
|
|
143
|
+
this.shadowRoot
|
|
144
|
+
.querySelector(this.selector)
|
|
145
|
+
.classList.remove(`error`, `warning`, `success`)
|
|
146
|
+
|
|
147
|
+
this.shadowRoot.querySelector(this.selector).classList.add(`pending`)
|
|
148
|
+
|
|
149
|
+
this.hide()
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Status is success
|
|
154
|
+
* @public
|
|
155
|
+
*/
|
|
156
|
+
public onSuccess() {
|
|
157
|
+
this.show()
|
|
158
|
+
|
|
159
|
+
this.shadowRoot
|
|
160
|
+
.querySelector(this.selector)
|
|
161
|
+
.classList.remove(`error`, `warning`, `pending`)
|
|
162
|
+
|
|
163
|
+
this.shadowRoot.querySelector(this.selector).classList.add(`success`)
|
|
164
|
+
|
|
165
|
+
this.hide()
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Status is error
|
|
170
|
+
* @public
|
|
171
|
+
*/
|
|
172
|
+
public onError() {
|
|
173
|
+
this.show()
|
|
174
|
+
|
|
175
|
+
this.shadowRoot
|
|
176
|
+
.querySelector(this.selector)
|
|
177
|
+
.classList.remove(`warning`, `success`, `pending`)
|
|
178
|
+
this.shadowRoot.querySelector(this.selector).classList.add(`error`)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Status is warning
|
|
183
|
+
* @public
|
|
184
|
+
*/
|
|
185
|
+
public onWarning() {
|
|
186
|
+
this.show()
|
|
187
|
+
|
|
188
|
+
this.shadowRoot
|
|
189
|
+
.querySelector(this.selector)
|
|
190
|
+
.classList.remove(`error`, `success`, `pending`)
|
|
191
|
+
|
|
192
|
+
this.shadowRoot.querySelector(this.selector).classList.add(`warning`)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
public static get observedAttributes() {
|
|
196
|
+
return [`has-errors`, `has-warnings`, `action`]
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
public attributeChangedCallback() {
|
|
200
|
+
if (this.hasAttribute(`has-errors`)) return this.onError()
|
|
201
|
+
if (this.hasAttribute(`has-warnings`)) return this.onWarning()
|
|
202
|
+
|
|
203
|
+
if (
|
|
204
|
+
!this.hasAttribute(`has-errors`) &&
|
|
205
|
+
!this.hasAttribute(`has-warnings`) &&
|
|
206
|
+
this.getAttribute(`action`) === `built`
|
|
207
|
+
)
|
|
208
|
+
return this.onSuccess()
|
|
209
|
+
|
|
210
|
+
if (
|
|
211
|
+
this.getAttribute(`action`) == `building` ||
|
|
212
|
+
this.getAttribute(`action`) == `sync`
|
|
213
|
+
)
|
|
214
|
+
return this.onPending()
|
|
215
|
+
}
|
|
216
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Activity indicator controller
|
|
3
|
+
* @public
|
|
4
|
+
*/
|
|
5
|
+
export class Controller {
|
|
6
|
+
/**
|
|
7
|
+
* DOM node
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
public node: HTMLElement
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Active WHM payload
|
|
14
|
+
* @public
|
|
15
|
+
*/
|
|
16
|
+
public payload = null
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Timer handler
|
|
20
|
+
* @public
|
|
21
|
+
*/
|
|
22
|
+
public timer: NodeJS.Timeout
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Initialization
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
28
|
+
public constructor() {
|
|
29
|
+
this.node = document.createElement(`bud-activity-indicator`)
|
|
30
|
+
this.update = this.update.bind(this)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Append `bud-error` element to the DOM
|
|
35
|
+
*
|
|
36
|
+
* @public
|
|
37
|
+
*/
|
|
38
|
+
public addNode() {
|
|
39
|
+
if (document.body.querySelector(`bud-activity-indicator`)) {
|
|
40
|
+
if (typeof this.timer.unref === `function`) this.timer.unref()
|
|
41
|
+
this.removeNode()
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
document.body?.appendChild(this.node)
|
|
45
|
+
this.timer = setTimeout(this.removeNode, 3000)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Remove `bud-error` element from the DOM (if present)
|
|
50
|
+
*
|
|
51
|
+
* @public
|
|
52
|
+
*/
|
|
53
|
+
public removeNode() {
|
|
54
|
+
document.body.querySelector(`bud-activity-indicator`)?.remove()
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Update activity indicator
|
|
59
|
+
* @public
|
|
60
|
+
*/
|
|
61
|
+
public update(payload: Payload) {
|
|
62
|
+
this.node.toggleAttribute(
|
|
63
|
+
`has-errors`,
|
|
64
|
+
payload.errors?.length ? true : false,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
this.node.toggleAttribute(
|
|
68
|
+
`has-warnings`,
|
|
69
|
+
payload.warnings?.length ? true : false,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
this.node.setAttribute(`action`, payload.action)
|
|
73
|
+
|
|
74
|
+
this.addNode()
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export interface pulse {
|
|
2
|
+
(name: string, color: [number, number, number]): string
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* CSS animation for reload indicator
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
export const pulse = (
|
|
10
|
+
name: string,
|
|
11
|
+
color: [number, number, number, number],
|
|
12
|
+
): string => `
|
|
13
|
+
.${name} {
|
|
14
|
+
box-shadow: 0 0 0 0 rgba(${color[0]}, ${color[1]}, ${color[2]}, ${color[3]});
|
|
15
|
+
animation: ${name}__pulse 2s infinite;
|
|
16
|
+
transition: all 0.4s ease-in-out;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.${name}:not(.show) {
|
|
20
|
+
background-color: rgba(${color[0]}, ${color[1]}, ${color[2]}, 0);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.${name}.show {
|
|
24
|
+
background-color: rgba(${color[0]}, ${color[1]}, ${color[2]}, ${color[3]});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@keyframes ${name}__pulse {
|
|
28
|
+
0% {
|
|
29
|
+
transform: scale(0.95);
|
|
30
|
+
box-shadow: 0 0 0 0 rgba(${color[0]}, ${color[1]}, ${color[2]}, 0.7);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
70% {
|
|
34
|
+
transform: scale(1);
|
|
35
|
+
box-shadow: 0 0 0 10px rgba(${color[0]}, ${color[1]}, ${color[2]}, 0);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
100% {
|
|
39
|
+
transform: scale(0.95);
|
|
40
|
+
box-shadow: 0 0 0 0 rgba(${color[0]}, ${color[1]}, ${color[2]}, 0);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
`
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import {Component} from './overlay.component.js'
|
|
2
|
+
import {Controller} from './overlay.controller.js'
|
|
3
|
+
|
|
4
|
+
export const make = async (): Promise<{
|
|
5
|
+
update: (data: Payload) => void
|
|
6
|
+
}> => {
|
|
7
|
+
if (customElements.get(`bud-error`)) return
|
|
8
|
+
|
|
9
|
+
customElements.define(`bud-error`, Component)
|
|
10
|
+
|
|
11
|
+
return new Controller()
|
|
12
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component container
|
|
3
|
+
*/
|
|
4
|
+
export class Component extends HTMLElement {
|
|
5
|
+
public name: string = `bud-overlay`
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* WHM payload
|
|
9
|
+
*
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
public payload: any
|
|
13
|
+
|
|
14
|
+
public documentBodyStyle: any
|
|
15
|
+
|
|
16
|
+
public get message() {
|
|
17
|
+
return this.getAttribute(`message`)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public constructor() {
|
|
21
|
+
super()
|
|
22
|
+
this.renderShadow()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public renderShadow(): void {
|
|
26
|
+
const container = document.createElement(`div`)
|
|
27
|
+
container.classList.add(`overlay`)
|
|
28
|
+
container.innerHTML = `
|
|
29
|
+
<style>
|
|
30
|
+
.overlay {
|
|
31
|
+
width: 100vw;
|
|
32
|
+
backdrop-filter: blur(10px);
|
|
33
|
+
display: flex;
|
|
34
|
+
height: 100vh;
|
|
35
|
+
border-top: 2px solid transparent;
|
|
36
|
+
overflow-x: hidden;
|
|
37
|
+
overflow-y: scroll;
|
|
38
|
+
position: absolute;
|
|
39
|
+
top: -1000px;
|
|
40
|
+
left: 0;
|
|
41
|
+
right: 0;
|
|
42
|
+
bottom: 0;
|
|
43
|
+
opacity: 0;
|
|
44
|
+
transition: opacity 0.2s ease-in-out, border 0.4s ease-in-out;
|
|
45
|
+
justify-content: center;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.visible {
|
|
49
|
+
position: fixed;
|
|
50
|
+
top: 0;
|
|
51
|
+
z-index: 9998;
|
|
52
|
+
opacity: 1;
|
|
53
|
+
border-top: 5px solid red;
|
|
54
|
+
transition: opacity 0.2s ease-in-out, border 0.4s ease-in-out;
|
|
55
|
+
max-width: 100vw;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.messages {
|
|
59
|
+
background-color: white;
|
|
60
|
+
border-radius: 5px;
|
|
61
|
+
filter: drop-shadow(0 1px 2px rgb(0 0 0 / 0.1)) drop-shadow(0 1px 1px rgb(0 0 0 / 0.06));
|
|
62
|
+
display: flex;
|
|
63
|
+
align-self: center;
|
|
64
|
+
width: 800px;
|
|
65
|
+
max-width: 90vw;
|
|
66
|
+
margin-left: auto;
|
|
67
|
+
margin-right: auto;
|
|
68
|
+
flex-direction: column;
|
|
69
|
+
flex-wrap: wrap;
|
|
70
|
+
align-items: center;
|
|
71
|
+
align-content: center;
|
|
72
|
+
padding: 2rem 2rem 0rem 2rem;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.visible .messages > div {
|
|
76
|
+
position: relative;
|
|
77
|
+
top: 0;
|
|
78
|
+
opacity: 1;
|
|
79
|
+
transition: all: 0.2s ease-in-out;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.messages > div {
|
|
83
|
+
position: relative;
|
|
84
|
+
top: 20px;
|
|
85
|
+
opacity: 0;
|
|
86
|
+
transition: all: 0.2s ease-in-out;
|
|
87
|
+
align-items: center;
|
|
88
|
+
align-content: center;
|
|
89
|
+
color: rgba(0, 0, 0, 0.87);
|
|
90
|
+
flex-direction: column;
|
|
91
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
|
92
|
+
padding: 0rem 2rem 2rem 2rem;
|
|
93
|
+
width: 100%;
|
|
94
|
+
max-width:95vw;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.messages > div > pre {
|
|
98
|
+
font-weight: 300;
|
|
99
|
+
font-size: 0.8rem;
|
|
100
|
+
overflow-x: scroll;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
pre {
|
|
104
|
+
background: #303030;
|
|
105
|
+
color: #f1f1f1;
|
|
106
|
+
padding: 10px 16px;
|
|
107
|
+
border-radius: 2px;
|
|
108
|
+
border-top: 4px solid #dd0303;
|
|
109
|
+
-moz-box-shadow: inset 0 0 10px #000;
|
|
110
|
+
box-shadow: inset 0 0 10px #000;
|
|
111
|
+
counter-reset: line;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
pre span {
|
|
115
|
+
display: block;
|
|
116
|
+
line-height: 1.5rem;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
pre span:before {
|
|
120
|
+
counter-increment: line;
|
|
121
|
+
content: counter(line);
|
|
122
|
+
display: inline-block;
|
|
123
|
+
border-right: 1px solid #ddd;
|
|
124
|
+
padding: 0 .5em;
|
|
125
|
+
margin-right: .5em;
|
|
126
|
+
color: #888;
|
|
127
|
+
width: 30px;
|
|
128
|
+
}
|
|
129
|
+
</style>
|
|
130
|
+
<div class="messages"></div>
|
|
131
|
+
`
|
|
132
|
+
|
|
133
|
+
this.attachShadow({mode: `open`}).appendChild(container)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
public static get observedAttributes() {
|
|
137
|
+
return [`message`]
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
public attributeChangedCallback() {
|
|
141
|
+
if (!this.documentBodyStyle)
|
|
142
|
+
this.documentBodyStyle = document.body?.style
|
|
143
|
+
|
|
144
|
+
if (this.getAttribute(`message`)) {
|
|
145
|
+
document.body.style.overflow = `hidden`
|
|
146
|
+
|
|
147
|
+
this.shadowRoot.querySelector(`.overlay`).classList.add(`visible`)
|
|
148
|
+
|
|
149
|
+
this.shadowRoot.querySelector(`.messages`).innerHTML =
|
|
150
|
+
this.getAttribute(`message`)
|
|
151
|
+
|
|
152
|
+
return
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (this.documentBodyStyle?.overflow && document?.body?.style) {
|
|
156
|
+
document.body.style.overflow = this.documentBodyStyle.overflow
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
this.shadowRoot.querySelector(`.overlay`).classList.remove(`visible`)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
public connectedCallback() {
|
|
163
|
+
if (document.body?.style) this.documentBodyStyle = document.body.style
|
|
164
|
+
}
|
|
165
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
const ansiPattern = [
|
|
2
|
+
`[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)`,
|
|
3
|
+
`(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))`,
|
|
4
|
+
].join(`|`)
|
|
5
|
+
|
|
6
|
+
const stripAnsi = (body: string) =>
|
|
7
|
+
body?.replace?.(new RegExp(ansiPattern, `g`), ``) ?? body
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Overlay controller
|
|
11
|
+
* @public
|
|
12
|
+
*/
|
|
13
|
+
export class Controller {
|
|
14
|
+
/**
|
|
15
|
+
* Element
|
|
16
|
+
* @public
|
|
17
|
+
*/
|
|
18
|
+
public element: HTMLElement
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* HMR update
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
public payload: Payload
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Formatted error message
|
|
28
|
+
* @public
|
|
29
|
+
*/
|
|
30
|
+
public get message(): string {
|
|
31
|
+
return this.payload.errors?.reduce((a, c) => {
|
|
32
|
+
const msg = c?.message ?? c?.error ?? c
|
|
33
|
+
if (!msg) return a
|
|
34
|
+
return `${a}
|
|
35
|
+
<div>
|
|
36
|
+
<pre>${stripAnsi(msg)}</pre>
|
|
37
|
+
</div>`
|
|
38
|
+
}, ``)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Class constructor
|
|
43
|
+
*
|
|
44
|
+
* @public
|
|
45
|
+
*/
|
|
46
|
+
public constructor() {
|
|
47
|
+
this.update = this.update.bind(this)
|
|
48
|
+
this.element = document.createElement(`bud-error`)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Append `bud-error` element to the DOM
|
|
53
|
+
*
|
|
54
|
+
* @public
|
|
55
|
+
*/
|
|
56
|
+
public createError() {
|
|
57
|
+
!document.body.querySelector(`bud-error`) &&
|
|
58
|
+
document.body?.appendChild(this.element)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Remove `bud-error` element from the DOM (if present)
|
|
63
|
+
*
|
|
64
|
+
* @public
|
|
65
|
+
*/
|
|
66
|
+
public removeError() {
|
|
67
|
+
document.body.querySelector(`bud-error`)?.remove()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Update DOM
|
|
72
|
+
*
|
|
73
|
+
* @public
|
|
74
|
+
*/
|
|
75
|
+
public update(payload: Payload): void {
|
|
76
|
+
this.payload = payload
|
|
77
|
+
|
|
78
|
+
this.element.setAttribute(`message`, this.message ?? ``)
|
|
79
|
+
|
|
80
|
+
if (this.payload.errors?.length > 0) {
|
|
81
|
+
return this.createError()
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
this.removeError()
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
|
|
3
|
+
export const injectEvents = (
|
|
4
|
+
eventSource: new (path: string) => EventSource,
|
|
5
|
+
) => {
|
|
6
|
+
/**
|
|
7
|
+
* EventSource wrapper
|
|
8
|
+
*
|
|
9
|
+
* @remarks
|
|
10
|
+
* wraps EventSource in a function to allow for
|
|
11
|
+
* mocking in tests
|
|
12
|
+
*
|
|
13
|
+
* @public
|
|
14
|
+
*/
|
|
15
|
+
return class Events extends eventSource {
|
|
16
|
+
/**
|
|
17
|
+
* Registered listeners
|
|
18
|
+
*
|
|
19
|
+
* @public
|
|
20
|
+
*/
|
|
21
|
+
public listeners: Set<Listener> = new Set<Listener>()
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Class constructor
|
|
25
|
+
*
|
|
26
|
+
* @remarks
|
|
27
|
+
* Singleton interface, so this is private.
|
|
28
|
+
*
|
|
29
|
+
* @public
|
|
30
|
+
*/
|
|
31
|
+
private constructor(
|
|
32
|
+
public options: Partial<Options> & {name: string; path: string},
|
|
33
|
+
) {
|
|
34
|
+
super(options.path)
|
|
35
|
+
|
|
36
|
+
this.onopen = this.onopen.bind(this)
|
|
37
|
+
this.onmessage = this.onmessage.bind(this)
|
|
38
|
+
this.addListener = this.addListener.bind(this)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Singleton constructor
|
|
43
|
+
*
|
|
44
|
+
* @public
|
|
45
|
+
*/
|
|
46
|
+
public static make(
|
|
47
|
+
options: Partial<Options> & {name: string; path: string},
|
|
48
|
+
): Events {
|
|
49
|
+
if (typeof window.bud.hmr[options.name] === `undefined`)
|
|
50
|
+
Object.assign(window.bud.hmr, {
|
|
51
|
+
[options.name]: new Events(options),
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
return window.bud.hmr[options.name]
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* EventSource `onopen` handler
|
|
59
|
+
* @public
|
|
60
|
+
*/
|
|
61
|
+
public override onopen = function () {}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* EventSource `onmessage` handler
|
|
65
|
+
* @public
|
|
66
|
+
*/
|
|
67
|
+
public override onmessage = async function (payload: MessageEvent) {
|
|
68
|
+
if (!payload?.data || payload.data == `\uD83D\uDC93`) {
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
const data = JSON.parse(payload.data)
|
|
74
|
+
if (!data) return
|
|
75
|
+
|
|
76
|
+
await Promise.all(
|
|
77
|
+
[...this.listeners].map(async listener => {
|
|
78
|
+
return await listener(data)
|
|
79
|
+
}),
|
|
80
|
+
)
|
|
81
|
+
} catch (ex) {}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* EventSource `addMessageListener` handler
|
|
86
|
+
* @public
|
|
87
|
+
*/
|
|
88
|
+
public addListener(listener: Listener): this {
|
|
89
|
+
this.listeners.add(listener)
|
|
90
|
+
return this
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|