@wippy-fe/loading 0.0.34 → 0.0.36

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.
@@ -0,0 +1,24 @@
1
+ declare class WippyErrorElement extends HTMLElement {
2
+ static observedAttributes: string[];
3
+ private _iconEl;
4
+ private _titleEl;
5
+ private _messageEl;
6
+ connectedCallback(): void;
7
+ disconnectedCallback(): void;
8
+ attributeChangedCallback(): void;
9
+ private _update;
10
+ }
11
+
12
+ declare class WippyLoadingElement extends HTMLElement {
13
+ static observedAttributes: string[];
14
+ private _titleEl;
15
+ private _subtitleEl;
16
+ connectedCallback(): void;
17
+ disconnectedCallback(): void;
18
+ attributeChangedCallback(): void;
19
+ private _updateText;
20
+ }
21
+
22
+ declare function register(): void;
23
+
24
+ export { WippyErrorElement, WippyLoadingElement, register };
package/dist/index.js ADDED
@@ -0,0 +1,326 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+
5
+ // src/wippy-error.ts
6
+ var ICON_CIRCLE = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle cx="18" cy="26.06" r="1.33" fill="currentColor"/><path fill="currentColor" d="M18 22.61a1 1 0 0 1-1-1v-12a1 1 0 1 1 2 0v12a1 1 0 0 1-1 1"/><path fill="currentColor" d="M18 34a16 16 0 1 1 16-16a16 16 0 0 1-16 16m0-30a14 14 0 1 0 14 14A14 14 0 0 0 18 4"/></svg>';
7
+ var ICON_TRIANGLE = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle cx="18" cy="26.06" r="1.33" fill="currentColor"/><path fill="currentColor" d="M18 22.61a1 1 0 0 1-1-1v-12a1 1 0 1 1 2 0v12a1 1 0 0 1-1 1"/><path fill="currentColor" d="M15.062 1.681a3.221 3.221 0 0 1 5.647.002l13.89 25.56A3.22 3.22 0 0 1 31.77 32H4.022a3.22 3.22 0 0 1-2.9-4.759zM2.88 28.198A1.22 1.22 0 0 0 4 30h27.77a1.22 1.22 0 0 0 1.071-1.803L18.954 2.642a1.22 1.22 0 0 0-2.137-.001z"/></svg>';
8
+ var ICON_SAD = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="currentColor" d="M18 2a16 16 0 1 0 16 16A16 16 0 0 0 18 2m0 30a14 14 0 1 1 14-14a14 14 0 0 1-14 14"/><circle cx="25.16" cy="14.28" r="1.8" fill="currentColor"/><circle cx="11.41" cy="14.28" r="1.8" fill="currentColor"/><path fill="currentColor" d="M18.16 20a9 9 0 0 0-7.33 3.78a1 1 0 1 0 1.63 1.16a7 7 0 0 1 11.31-.13a1 1 0 0 0 1.6-1.2A9 9 0 0 0 18.16 20"/></svg>';
9
+ var ICONS = {
10
+ circle: ICON_CIRCLE,
11
+ triangle: ICON_TRIANGLE,
12
+ sad: ICON_SAD
13
+ };
14
+ var STYLES = `
15
+ *, *::before, *::after { box-sizing: border-box; }
16
+
17
+ :host {
18
+ display: block;
19
+ width: 100%;
20
+ height: 100%;
21
+ min-height: 120px;
22
+ overflow: hidden;
23
+ }
24
+
25
+ :host(:only-child) {
26
+ height: 100vh;
27
+ height: 100dvh;
28
+ }
29
+
30
+ :host([no-bg]) .container { background: transparent; }
31
+
32
+ .container {
33
+ display: flex;
34
+ flex-direction: column;
35
+ align-items: center;
36
+ justify-content: center;
37
+ width: 100%;
38
+ height: 100%;
39
+ background: var(--p-surface-0, #fff);
40
+ font-family: system-ui, -apple-system, sans-serif;
41
+ }
42
+
43
+ .icon {
44
+ width: 48px;
45
+ height: 48px;
46
+ margin-bottom: 16px;
47
+ }
48
+
49
+ .icon svg {
50
+ width: 100%;
51
+ height: 100%;
52
+ }
53
+
54
+ :host([severity="warning"]) .icon,
55
+ :host([severity="warning"]) .title {
56
+ color: var(--p-warn-500, rgb(249, 115, 22));
57
+ }
58
+
59
+ :host(:not([severity="warning"])) .icon,
60
+ :host(:not([severity="warning"])) .title {
61
+ color: var(--p-danger-500, rgb(239, 68, 68));
62
+ }
63
+
64
+ .title {
65
+ font-size: 16px;
66
+ font-weight: 600;
67
+ text-align: center;
68
+ padding: 0 16px;
69
+ }
70
+
71
+ .title:empty { display: none; }
72
+
73
+ .message {
74
+ font-size: 13px;
75
+ color: var(--p-text-muted-color, #71717a);
76
+ margin-top: 6px;
77
+ text-align: center;
78
+ padding: 0 16px;
79
+ max-width: 480px;
80
+ line-height: 1.4;
81
+ }
82
+
83
+ .message:empty { display: none; }
84
+
85
+ @media (prefers-color-scheme: dark) {
86
+ .container {
87
+ background: var(--p-surface-900, #1c1a19);
88
+ }
89
+ :host([severity="warning"]) .icon,
90
+ :host([severity="warning"]) .title {
91
+ color: var(--p-warn-400, color-mix(in srgb, rgb(249, 115, 22) 40%, white));
92
+ }
93
+ :host(:not([severity="warning"])) .icon,
94
+ :host(:not([severity="warning"])) .title {
95
+ color: var(--p-danger-400, color-mix(in srgb, rgb(239, 68, 68) 40%, white));
96
+ }
97
+ .message {
98
+ color: var(--p-text-muted-color, #a1a1aa);
99
+ }
100
+ }
101
+ `;
102
+ var WippyErrorElement = class extends HTMLElement {
103
+ constructor() {
104
+ super(...arguments);
105
+ __publicField(this, "_iconEl", null);
106
+ __publicField(this, "_titleEl", null);
107
+ __publicField(this, "_messageEl", null);
108
+ }
109
+ connectedCallback() {
110
+ const shadow = this.shadowRoot ?? this.attachShadow({ mode: "open" });
111
+ shadow.textContent = "";
112
+ const style = document.createElement("style");
113
+ style.textContent = STYLES;
114
+ shadow.appendChild(style);
115
+ const container = document.createElement("div");
116
+ container.className = "container";
117
+ this._iconEl = document.createElement("div");
118
+ this._iconEl.className = "icon";
119
+ this._iconEl.setAttribute("part", "icon");
120
+ this._titleEl = document.createElement("div");
121
+ this._titleEl.className = "title";
122
+ this._titleEl.setAttribute("part", "title");
123
+ this._messageEl = document.createElement("div");
124
+ this._messageEl.className = "message";
125
+ this._messageEl.setAttribute("part", "message");
126
+ this._update();
127
+ container.append(this._iconEl, this._titleEl, this._messageEl);
128
+ shadow.appendChild(container);
129
+ }
130
+ disconnectedCallback() {
131
+ this._iconEl = null;
132
+ this._titleEl = null;
133
+ this._messageEl = null;
134
+ }
135
+ attributeChangedCallback() {
136
+ this._update();
137
+ }
138
+ _update() {
139
+ if (this._iconEl) {
140
+ const iconKey = this.getAttribute("icon") ?? "circle";
141
+ this._iconEl.innerHTML = ICONS[iconKey] ?? ICONS.circle;
142
+ }
143
+ if (this._titleEl)
144
+ this._titleEl.textContent = this.getAttribute("title") ?? "Something went wrong";
145
+ if (this._messageEl)
146
+ this._messageEl.textContent = this.getAttribute("message") ?? "";
147
+ }
148
+ };
149
+ __publicField(WippyErrorElement, "observedAttributes", ["title", "message", "icon", "severity"]);
150
+
151
+ // src/wippy-loading.ts
152
+ var OUTER_DURATION = 3e3;
153
+ var INNER_DURATION = 2e3;
154
+ var STYLES2 = `
155
+ *, *::before, *::after { box-sizing: border-box; }
156
+
157
+ :host {
158
+ display: block;
159
+ width: 100%;
160
+ height: 100%;
161
+ min-height: 120px;
162
+ overflow: hidden;
163
+ }
164
+
165
+ :host(:only-child) {
166
+ height: 100vh;
167
+ height: 100dvh;
168
+ }
169
+
170
+ :host([no-bg]) .container { background: transparent; }
171
+
172
+ .container {
173
+ display: flex;
174
+ flex-direction: column;
175
+ align-items: center;
176
+ justify-content: center;
177
+ width: 100%;
178
+ height: 100%;
179
+ background: var(--p-surface-0, #fff);
180
+ font-family: system-ui, -apple-system, sans-serif;
181
+ }
182
+
183
+ .spinner {
184
+ position: relative;
185
+ width: 48px;
186
+ height: 48px;
187
+ margin-bottom: 16px;
188
+ }
189
+
190
+ .ring {
191
+ position: absolute;
192
+ border-radius: 50%;
193
+ box-sizing: border-box;
194
+ }
195
+
196
+ .ring.outer {
197
+ width: 48px;
198
+ height: 48px;
199
+ border: 3px solid var(--p-surface-300, #d4d4d8);
200
+ animation: spin-outer ${OUTER_DURATION}ms linear infinite;
201
+ }
202
+
203
+ .ring.inner {
204
+ width: 56px;
205
+ height: 56px;
206
+ top: 50%;
207
+ left: 50%;
208
+ border: 3px solid transparent;
209
+ border-top-color: var(--p-primary, rgb(0, 95, 178));
210
+ border-bottom-color: var(--p-primary, rgb(0, 95, 178));
211
+ animation: spin-inner ${INNER_DURATION}ms linear infinite;
212
+ }
213
+
214
+ .title {
215
+ font-size: 14px;
216
+ font-weight: 500;
217
+ color: var(--p-text-color, #3f3f46);
218
+ text-align: center;
219
+ padding: 0 16px;
220
+ }
221
+
222
+ .title:empty { display: none; }
223
+
224
+ .subtitle {
225
+ font-size: 12px;
226
+ color: var(--p-text-muted-color, #71717a);
227
+ margin-top: 4px;
228
+ text-align: center;
229
+ padding: 0 16px;
230
+ }
231
+
232
+ .subtitle:empty { display: none; }
233
+
234
+ @media (prefers-color-scheme: dark) {
235
+ .container {
236
+ background: var(--p-surface-900, #1c1a19);
237
+ }
238
+ .ring.outer {
239
+ border-color: var(--p-surface-500, #71717a);
240
+ }
241
+ .ring.inner {
242
+ border-top-color: var(--p-primary, rgb(0, 125, 178));
243
+ border-bottom-color: var(--p-primary, rgb(0, 125, 178));
244
+ }
245
+ .title {
246
+ color: var(--p-text-color, #fff);
247
+ }
248
+ .subtitle {
249
+ color: var(--p-text-muted-color, #a1a1aa);
250
+ }
251
+ }
252
+
253
+ @keyframes spin-outer {
254
+ from { transform: rotate(0deg); }
255
+ to { transform: rotate(360deg); }
256
+ }
257
+
258
+ @keyframes spin-inner {
259
+ from { transform: translate(-50%, -50%) rotate(0deg); }
260
+ to { transform: translate(-50%, -50%) rotate(-360deg); }
261
+ }
262
+ `;
263
+ var WippyLoadingElement = class extends HTMLElement {
264
+ constructor() {
265
+ super(...arguments);
266
+ __publicField(this, "_titleEl", null);
267
+ __publicField(this, "_subtitleEl", null);
268
+ }
269
+ connectedCallback() {
270
+ const shadow = this.shadowRoot ?? this.attachShadow({ mode: "open" });
271
+ shadow.textContent = "";
272
+ const style = document.createElement("style");
273
+ style.textContent = STYLES2;
274
+ shadow.appendChild(style);
275
+ const container = document.createElement("div");
276
+ container.className = "container";
277
+ const spinner = document.createElement("div");
278
+ spinner.className = "spinner";
279
+ const outer = document.createElement("div");
280
+ outer.className = "ring outer";
281
+ const inner = document.createElement("div");
282
+ inner.className = "ring inner";
283
+ spinner.append(outer, inner);
284
+ this._titleEl = document.createElement("div");
285
+ this._titleEl.className = "title";
286
+ this._titleEl.setAttribute("part", "title");
287
+ this._subtitleEl = document.createElement("div");
288
+ this._subtitleEl.className = "subtitle";
289
+ this._subtitleEl.setAttribute("part", "subtitle");
290
+ this._updateText();
291
+ container.append(spinner, this._titleEl, this._subtitleEl);
292
+ shadow.appendChild(container);
293
+ const now = Date.now();
294
+ outer.style.animationDelay = `-${now % OUTER_DURATION}ms`;
295
+ inner.style.animationDelay = `-${now % INNER_DURATION}ms`;
296
+ }
297
+ disconnectedCallback() {
298
+ this._titleEl = null;
299
+ this._subtitleEl = null;
300
+ }
301
+ attributeChangedCallback() {
302
+ this._updateText();
303
+ }
304
+ _updateText() {
305
+ if (this._titleEl)
306
+ this._titleEl.textContent = this.getAttribute("title") ?? "";
307
+ if (this._subtitleEl)
308
+ this._subtitleEl.textContent = this.getAttribute("subtitle") ?? "";
309
+ }
310
+ };
311
+ __publicField(WippyLoadingElement, "observedAttributes", ["title", "subtitle"]);
312
+
313
+ // src/index.ts
314
+ function register() {
315
+ if (!customElements.get("wippy-loading"))
316
+ customElements.define("wippy-loading", WippyLoadingElement);
317
+ if (!customElements.get("wippy-error"))
318
+ customElements.define("wippy-error", WippyErrorElement);
319
+ }
320
+ register();
321
+ export {
322
+ WippyErrorElement,
323
+ WippyLoadingElement,
324
+ register
325
+ };
326
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/wippy-error.ts","../src/wippy-loading.ts","../src/index.ts"],"sourcesContent":["const ICON_CIRCLE = '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 36 36\"><circle cx=\"18\" cy=\"26.06\" r=\"1.33\" fill=\"currentColor\"/><path fill=\"currentColor\" d=\"M18 22.61a1 1 0 0 1-1-1v-12a1 1 0 1 1 2 0v12a1 1 0 0 1-1 1\"/><path fill=\"currentColor\" d=\"M18 34a16 16 0 1 1 16-16a16 16 0 0 1-16 16m0-30a14 14 0 1 0 14 14A14 14 0 0 0 18 4\"/></svg>'\n\nconst ICON_TRIANGLE = '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 36 36\"><circle cx=\"18\" cy=\"26.06\" r=\"1.33\" fill=\"currentColor\"/><path fill=\"currentColor\" d=\"M18 22.61a1 1 0 0 1-1-1v-12a1 1 0 1 1 2 0v12a1 1 0 0 1-1 1\"/><path fill=\"currentColor\" d=\"M15.062 1.681a3.221 3.221 0 0 1 5.647.002l13.89 25.56A3.22 3.22 0 0 1 31.77 32H4.022a3.22 3.22 0 0 1-2.9-4.759zM2.88 28.198A1.22 1.22 0 0 0 4 30h27.77a1.22 1.22 0 0 0 1.071-1.803L18.954 2.642a1.22 1.22 0 0 0-2.137-.001z\"/></svg>'\n\nconst ICON_SAD = '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 36 36\"><path fill=\"currentColor\" d=\"M18 2a16 16 0 1 0 16 16A16 16 0 0 0 18 2m0 30a14 14 0 1 1 14-14a14 14 0 0 1-14 14\"/><circle cx=\"25.16\" cy=\"14.28\" r=\"1.8\" fill=\"currentColor\"/><circle cx=\"11.41\" cy=\"14.28\" r=\"1.8\" fill=\"currentColor\"/><path fill=\"currentColor\" d=\"M18.16 20a9 9 0 0 0-7.33 3.78a1 1 0 1 0 1.63 1.16a7 7 0 0 1 11.31-.13a1 1 0 0 0 1.6-1.2A9 9 0 0 0 18.16 20\"/></svg>'\n\nconst ICONS: Record<string, string> = {\n circle: ICON_CIRCLE,\n triangle: ICON_TRIANGLE,\n sad: ICON_SAD,\n}\n\nconst STYLES = `\n *, *::before, *::after { box-sizing: border-box; }\n\n :host {\n display: block;\n width: 100%;\n height: 100%;\n min-height: 120px;\n overflow: hidden;\n }\n\n :host(:only-child) {\n height: 100vh;\n height: 100dvh;\n }\n\n :host([no-bg]) .container { background: transparent; }\n\n .container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n background: var(--p-surface-0, #fff);\n font-family: system-ui, -apple-system, sans-serif;\n }\n\n .icon {\n width: 48px;\n height: 48px;\n margin-bottom: 16px;\n }\n\n .icon svg {\n width: 100%;\n height: 100%;\n }\n\n :host([severity=\"warning\"]) .icon,\n :host([severity=\"warning\"]) .title {\n color: var(--p-warn-500, rgb(249, 115, 22));\n }\n\n :host(:not([severity=\"warning\"])) .icon,\n :host(:not([severity=\"warning\"])) .title {\n color: var(--p-danger-500, rgb(239, 68, 68));\n }\n\n .title {\n font-size: 16px;\n font-weight: 600;\n text-align: center;\n padding: 0 16px;\n }\n\n .title:empty { display: none; }\n\n .message {\n font-size: 13px;\n color: var(--p-text-muted-color, #71717a);\n margin-top: 6px;\n text-align: center;\n padding: 0 16px;\n max-width: 480px;\n line-height: 1.4;\n }\n\n .message:empty { display: none; }\n\n @media (prefers-color-scheme: dark) {\n .container {\n background: var(--p-surface-900, #1c1a19);\n }\n :host([severity=\"warning\"]) .icon,\n :host([severity=\"warning\"]) .title {\n color: var(--p-warn-400, color-mix(in srgb, rgb(249, 115, 22) 40%, white));\n }\n :host(:not([severity=\"warning\"])) .icon,\n :host(:not([severity=\"warning\"])) .title {\n color: var(--p-danger-400, color-mix(in srgb, rgb(239, 68, 68) 40%, white));\n }\n .message {\n color: var(--p-text-muted-color, #a1a1aa);\n }\n }\n`\n\nexport class WippyErrorElement extends HTMLElement {\n static observedAttributes = ['title', 'message', 'icon', 'severity']\n\n private _iconEl: HTMLElement | null = null\n private _titleEl: HTMLElement | null = null\n private _messageEl: HTMLElement | null = null\n\n connectedCallback() {\n const shadow = this.shadowRoot ?? this.attachShadow({ mode: 'open' })\n shadow.textContent = ''\n\n const style = document.createElement('style')\n style.textContent = STYLES\n shadow.appendChild(style)\n\n const container = document.createElement('div')\n container.className = 'container'\n\n this._iconEl = document.createElement('div')\n this._iconEl.className = 'icon'\n this._iconEl.setAttribute('part', 'icon')\n\n this._titleEl = document.createElement('div')\n this._titleEl.className = 'title'\n this._titleEl.setAttribute('part', 'title')\n\n this._messageEl = document.createElement('div')\n this._messageEl.className = 'message'\n this._messageEl.setAttribute('part', 'message')\n\n this._update()\n\n container.append(this._iconEl, this._titleEl, this._messageEl)\n shadow.appendChild(container)\n }\n\n disconnectedCallback() {\n this._iconEl = null\n this._titleEl = null\n this._messageEl = null\n }\n\n attributeChangedCallback() {\n this._update()\n }\n\n private _update() {\n if (this._iconEl) {\n const iconKey = this.getAttribute('icon') ?? 'circle'\n this._iconEl.innerHTML = ICONS[iconKey] ?? ICONS.circle\n }\n if (this._titleEl)\n this._titleEl.textContent = this.getAttribute('title') ?? 'Something went wrong'\n if (this._messageEl)\n this._messageEl.textContent = this.getAttribute('message') ?? ''\n }\n}\n","const OUTER_DURATION = 3000\nconst INNER_DURATION = 2000\n\nconst STYLES = `\n *, *::before, *::after { box-sizing: border-box; }\n\n :host {\n display: block;\n width: 100%;\n height: 100%;\n min-height: 120px;\n overflow: hidden;\n }\n\n :host(:only-child) {\n height: 100vh;\n height: 100dvh;\n }\n\n :host([no-bg]) .container { background: transparent; }\n\n .container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n background: var(--p-surface-0, #fff);\n font-family: system-ui, -apple-system, sans-serif;\n }\n\n .spinner {\n position: relative;\n width: 48px;\n height: 48px;\n margin-bottom: 16px;\n }\n\n .ring {\n position: absolute;\n border-radius: 50%;\n box-sizing: border-box;\n }\n\n .ring.outer {\n width: 48px;\n height: 48px;\n border: 3px solid var(--p-surface-300, #d4d4d8);\n animation: spin-outer ${OUTER_DURATION}ms linear infinite;\n }\n\n .ring.inner {\n width: 56px;\n height: 56px;\n top: 50%;\n left: 50%;\n border: 3px solid transparent;\n border-top-color: var(--p-primary, rgb(0, 95, 178));\n border-bottom-color: var(--p-primary, rgb(0, 95, 178));\n animation: spin-inner ${INNER_DURATION}ms linear infinite;\n }\n\n .title {\n font-size: 14px;\n font-weight: 500;\n color: var(--p-text-color, #3f3f46);\n text-align: center;\n padding: 0 16px;\n }\n\n .title:empty { display: none; }\n\n .subtitle {\n font-size: 12px;\n color: var(--p-text-muted-color, #71717a);\n margin-top: 4px;\n text-align: center;\n padding: 0 16px;\n }\n\n .subtitle:empty { display: none; }\n\n @media (prefers-color-scheme: dark) {\n .container {\n background: var(--p-surface-900, #1c1a19);\n }\n .ring.outer {\n border-color: var(--p-surface-500, #71717a);\n }\n .ring.inner {\n border-top-color: var(--p-primary, rgb(0, 125, 178));\n border-bottom-color: var(--p-primary, rgb(0, 125, 178));\n }\n .title {\n color: var(--p-text-color, #fff);\n }\n .subtitle {\n color: var(--p-text-muted-color, #a1a1aa);\n }\n }\n\n @keyframes spin-outer {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n }\n\n @keyframes spin-inner {\n from { transform: translate(-50%, -50%) rotate(0deg); }\n to { transform: translate(-50%, -50%) rotate(-360deg); }\n }\n`\n\nexport class WippyLoadingElement extends HTMLElement {\n static observedAttributes = ['title', 'subtitle']\n\n private _titleEl: HTMLElement | null = null\n private _subtitleEl: HTMLElement | null = null\n\n connectedCallback() {\n const shadow = this.shadowRoot ?? this.attachShadow({ mode: 'open' })\n shadow.textContent = ''\n\n const style = document.createElement('style')\n style.textContent = STYLES\n shadow.appendChild(style)\n\n const container = document.createElement('div')\n container.className = 'container'\n\n const spinner = document.createElement('div')\n spinner.className = 'spinner'\n\n const outer = document.createElement('div')\n outer.className = 'ring outer'\n\n const inner = document.createElement('div')\n inner.className = 'ring inner'\n\n spinner.append(outer, inner)\n\n this._titleEl = document.createElement('div')\n this._titleEl.className = 'title'\n this._titleEl.setAttribute('part', 'title')\n\n this._subtitleEl = document.createElement('div')\n this._subtitleEl.className = 'subtitle'\n this._subtitleEl.setAttribute('part', 'subtitle')\n\n this._updateText()\n\n container.append(spinner, this._titleEl, this._subtitleEl)\n shadow.appendChild(container)\n\n // Time-synced animation — phase matches wall-clock time\n const now = Date.now()\n outer.style.animationDelay = `-${now % OUTER_DURATION}ms`\n inner.style.animationDelay = `-${now % INNER_DURATION}ms`\n }\n\n disconnectedCallback() {\n this._titleEl = null\n this._subtitleEl = null\n }\n\n attributeChangedCallback() {\n this._updateText()\n }\n\n private _updateText() {\n if (this._titleEl)\n this._titleEl.textContent = this.getAttribute('title') ?? ''\n if (this._subtitleEl)\n this._subtitleEl.textContent = this.getAttribute('subtitle') ?? ''\n }\n}\n","import { WippyErrorElement } from './wippy-error'\nimport { WippyLoadingElement } from './wippy-loading'\n\nexport { WippyErrorElement, WippyLoadingElement }\n\nexport function register() {\n if (!customElements.get('wippy-loading'))\n customElements.define('wippy-loading', WippyLoadingElement)\n if (!customElements.get('wippy-error'))\n customElements.define('wippy-error', WippyErrorElement)\n}\n\n// Auto-register when loaded as a script\nregister()\n"],"mappings":"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","names":["STYLES"]}
package/package.json CHANGED
@@ -1,13 +1,25 @@
1
1
  {
2
2
  "name": "@wippy-fe/loading",
3
- "version": "0.0.34",
3
+ "version": "0.0.36",
4
4
  "description": "Zero-dependency loading and error screen web components for the Wippy platform",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
7
- "main": "src/index.ts",
8
- "types": "src/index.ts",
7
+ "main": "dist/index.js",
8
+ "module": "dist/index.js",
9
+ "types": "dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js"
14
+ },
15
+ "./package.json": "./package.json"
16
+ },
9
17
  "files": [
10
- "src/",
11
- "package.json"
12
- ]
18
+ "package.json",
19
+ "dist/"
20
+ ],
21
+ "scripts": {
22
+ "build": "tsup",
23
+ "clean": "rimraf dist"
24
+ }
13
25
  }
package/src/index.ts DELETED
@@ -1,14 +0,0 @@
1
- import { WippyErrorElement } from './wippy-error'
2
- import { WippyLoadingElement } from './wippy-loading'
3
-
4
- export { WippyErrorElement, WippyLoadingElement }
5
-
6
- export function register() {
7
- if (!customElements.get('wippy-loading'))
8
- customElements.define('wippy-loading', WippyLoadingElement)
9
- if (!customElements.get('wippy-error'))
10
- customElements.define('wippy-error', WippyErrorElement)
11
- }
12
-
13
- // Auto-register when loaded as a script
14
- register()
@@ -1,158 +0,0 @@
1
- const ICON_CIRCLE = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle cx="18" cy="26.06" r="1.33" fill="currentColor"/><path fill="currentColor" d="M18 22.61a1 1 0 0 1-1-1v-12a1 1 0 1 1 2 0v12a1 1 0 0 1-1 1"/><path fill="currentColor" d="M18 34a16 16 0 1 1 16-16a16 16 0 0 1-16 16m0-30a14 14 0 1 0 14 14A14 14 0 0 0 18 4"/></svg>'
2
-
3
- const ICON_TRIANGLE = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle cx="18" cy="26.06" r="1.33" fill="currentColor"/><path fill="currentColor" d="M18 22.61a1 1 0 0 1-1-1v-12a1 1 0 1 1 2 0v12a1 1 0 0 1-1 1"/><path fill="currentColor" d="M15.062 1.681a3.221 3.221 0 0 1 5.647.002l13.89 25.56A3.22 3.22 0 0 1 31.77 32H4.022a3.22 3.22 0 0 1-2.9-4.759zM2.88 28.198A1.22 1.22 0 0 0 4 30h27.77a1.22 1.22 0 0 0 1.071-1.803L18.954 2.642a1.22 1.22 0 0 0-2.137-.001z"/></svg>'
4
-
5
- const ICON_SAD = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="currentColor" d="M18 2a16 16 0 1 0 16 16A16 16 0 0 0 18 2m0 30a14 14 0 1 1 14-14a14 14 0 0 1-14 14"/><circle cx="25.16" cy="14.28" r="1.8" fill="currentColor"/><circle cx="11.41" cy="14.28" r="1.8" fill="currentColor"/><path fill="currentColor" d="M18.16 20a9 9 0 0 0-7.33 3.78a1 1 0 1 0 1.63 1.16a7 7 0 0 1 11.31-.13a1 1 0 0 0 1.6-1.2A9 9 0 0 0 18.16 20"/></svg>'
6
-
7
- const ICONS: Record<string, string> = {
8
- circle: ICON_CIRCLE,
9
- triangle: ICON_TRIANGLE,
10
- sad: ICON_SAD,
11
- }
12
-
13
- const STYLES = `
14
- *, *::before, *::after { box-sizing: border-box; }
15
-
16
- :host {
17
- display: block;
18
- width: 100%;
19
- height: 100%;
20
- min-height: 120px;
21
- overflow: hidden;
22
- }
23
-
24
- :host(:only-child) {
25
- height: 100vh;
26
- height: 100dvh;
27
- }
28
-
29
- :host([no-bg]) .container { background: transparent; }
30
-
31
- .container {
32
- display: flex;
33
- flex-direction: column;
34
- align-items: center;
35
- justify-content: center;
36
- width: 100%;
37
- height: 100%;
38
- background: var(--p-surface-0, #fff);
39
- font-family: system-ui, -apple-system, sans-serif;
40
- }
41
-
42
- .icon {
43
- width: 48px;
44
- height: 48px;
45
- margin-bottom: 16px;
46
- }
47
-
48
- .icon svg {
49
- width: 100%;
50
- height: 100%;
51
- }
52
-
53
- :host([severity="warning"]) .icon,
54
- :host([severity="warning"]) .title {
55
- color: var(--p-warn-500, rgb(249, 115, 22));
56
- }
57
-
58
- :host(:not([severity="warning"])) .icon,
59
- :host(:not([severity="warning"])) .title {
60
- color: var(--p-danger-500, rgb(239, 68, 68));
61
- }
62
-
63
- .title {
64
- font-size: 16px;
65
- font-weight: 600;
66
- text-align: center;
67
- padding: 0 16px;
68
- }
69
-
70
- .title:empty { display: none; }
71
-
72
- .message {
73
- font-size: 13px;
74
- color: var(--p-text-muted-color, #71717a);
75
- margin-top: 6px;
76
- text-align: center;
77
- padding: 0 16px;
78
- max-width: 480px;
79
- line-height: 1.4;
80
- }
81
-
82
- .message:empty { display: none; }
83
-
84
- @media (prefers-color-scheme: dark) {
85
- .container {
86
- background: var(--p-surface-900, #1c1a19);
87
- }
88
- :host([severity="warning"]) .icon,
89
- :host([severity="warning"]) .title {
90
- color: var(--p-warn-400, color-mix(in srgb, rgb(249, 115, 22) 40%, white));
91
- }
92
- :host(:not([severity="warning"])) .icon,
93
- :host(:not([severity="warning"])) .title {
94
- color: var(--p-danger-400, color-mix(in srgb, rgb(239, 68, 68) 40%, white));
95
- }
96
- .message {
97
- color: var(--p-text-muted-color, #a1a1aa);
98
- }
99
- }
100
- `
101
-
102
- export class WippyErrorElement extends HTMLElement {
103
- static observedAttributes = ['title', 'message', 'icon', 'severity']
104
-
105
- private _iconEl: HTMLElement | null = null
106
- private _titleEl: HTMLElement | null = null
107
- private _messageEl: HTMLElement | null = null
108
-
109
- connectedCallback() {
110
- const shadow = this.shadowRoot ?? this.attachShadow({ mode: 'open' })
111
- shadow.textContent = ''
112
-
113
- const style = document.createElement('style')
114
- style.textContent = STYLES
115
- shadow.appendChild(style)
116
-
117
- const container = document.createElement('div')
118
- container.className = 'container'
119
-
120
- this._iconEl = document.createElement('div')
121
- this._iconEl.className = 'icon'
122
- this._iconEl.setAttribute('part', 'icon')
123
-
124
- this._titleEl = document.createElement('div')
125
- this._titleEl.className = 'title'
126
- this._titleEl.setAttribute('part', 'title')
127
-
128
- this._messageEl = document.createElement('div')
129
- this._messageEl.className = 'message'
130
- this._messageEl.setAttribute('part', 'message')
131
-
132
- this._update()
133
-
134
- container.append(this._iconEl, this._titleEl, this._messageEl)
135
- shadow.appendChild(container)
136
- }
137
-
138
- disconnectedCallback() {
139
- this._iconEl = null
140
- this._titleEl = null
141
- this._messageEl = null
142
- }
143
-
144
- attributeChangedCallback() {
145
- this._update()
146
- }
147
-
148
- private _update() {
149
- if (this._iconEl) {
150
- const iconKey = this.getAttribute('icon') ?? 'circle'
151
- this._iconEl.innerHTML = ICONS[iconKey] ?? ICONS.circle
152
- }
153
- if (this._titleEl)
154
- this._titleEl.textContent = this.getAttribute('title') ?? 'Something went wrong'
155
- if (this._messageEl)
156
- this._messageEl.textContent = this.getAttribute('message') ?? ''
157
- }
158
- }
@@ -1,176 +0,0 @@
1
- const OUTER_DURATION = 3000
2
- const INNER_DURATION = 2000
3
-
4
- const STYLES = `
5
- *, *::before, *::after { box-sizing: border-box; }
6
-
7
- :host {
8
- display: block;
9
- width: 100%;
10
- height: 100%;
11
- min-height: 120px;
12
- overflow: hidden;
13
- }
14
-
15
- :host(:only-child) {
16
- height: 100vh;
17
- height: 100dvh;
18
- }
19
-
20
- :host([no-bg]) .container { background: transparent; }
21
-
22
- .container {
23
- display: flex;
24
- flex-direction: column;
25
- align-items: center;
26
- justify-content: center;
27
- width: 100%;
28
- height: 100%;
29
- background: var(--p-surface-0, #fff);
30
- font-family: system-ui, -apple-system, sans-serif;
31
- }
32
-
33
- .spinner {
34
- position: relative;
35
- width: 48px;
36
- height: 48px;
37
- margin-bottom: 16px;
38
- }
39
-
40
- .ring {
41
- position: absolute;
42
- border-radius: 50%;
43
- box-sizing: border-box;
44
- }
45
-
46
- .ring.outer {
47
- width: 48px;
48
- height: 48px;
49
- border: 3px solid var(--p-surface-300, #d4d4d8);
50
- animation: spin-outer ${OUTER_DURATION}ms linear infinite;
51
- }
52
-
53
- .ring.inner {
54
- width: 56px;
55
- height: 56px;
56
- top: 50%;
57
- left: 50%;
58
- border: 3px solid transparent;
59
- border-top-color: var(--p-primary, rgb(0, 95, 178));
60
- border-bottom-color: var(--p-primary, rgb(0, 95, 178));
61
- animation: spin-inner ${INNER_DURATION}ms linear infinite;
62
- }
63
-
64
- .title {
65
- font-size: 14px;
66
- font-weight: 500;
67
- color: var(--p-text-color, #3f3f46);
68
- text-align: center;
69
- padding: 0 16px;
70
- }
71
-
72
- .title:empty { display: none; }
73
-
74
- .subtitle {
75
- font-size: 12px;
76
- color: var(--p-text-muted-color, #71717a);
77
- margin-top: 4px;
78
- text-align: center;
79
- padding: 0 16px;
80
- }
81
-
82
- .subtitle:empty { display: none; }
83
-
84
- @media (prefers-color-scheme: dark) {
85
- .container {
86
- background: var(--p-surface-900, #1c1a19);
87
- }
88
- .ring.outer {
89
- border-color: var(--p-surface-500, #71717a);
90
- }
91
- .ring.inner {
92
- border-top-color: var(--p-primary, rgb(0, 125, 178));
93
- border-bottom-color: var(--p-primary, rgb(0, 125, 178));
94
- }
95
- .title {
96
- color: var(--p-text-color, #fff);
97
- }
98
- .subtitle {
99
- color: var(--p-text-muted-color, #a1a1aa);
100
- }
101
- }
102
-
103
- @keyframes spin-outer {
104
- from { transform: rotate(0deg); }
105
- to { transform: rotate(360deg); }
106
- }
107
-
108
- @keyframes spin-inner {
109
- from { transform: translate(-50%, -50%) rotate(0deg); }
110
- to { transform: translate(-50%, -50%) rotate(-360deg); }
111
- }
112
- `
113
-
114
- export class WippyLoadingElement extends HTMLElement {
115
- static observedAttributes = ['title', 'subtitle']
116
-
117
- private _titleEl: HTMLElement | null = null
118
- private _subtitleEl: HTMLElement | null = null
119
-
120
- connectedCallback() {
121
- const shadow = this.shadowRoot ?? this.attachShadow({ mode: 'open' })
122
- shadow.textContent = ''
123
-
124
- const style = document.createElement('style')
125
- style.textContent = STYLES
126
- shadow.appendChild(style)
127
-
128
- const container = document.createElement('div')
129
- container.className = 'container'
130
-
131
- const spinner = document.createElement('div')
132
- spinner.className = 'spinner'
133
-
134
- const outer = document.createElement('div')
135
- outer.className = 'ring outer'
136
-
137
- const inner = document.createElement('div')
138
- inner.className = 'ring inner'
139
-
140
- spinner.append(outer, inner)
141
-
142
- this._titleEl = document.createElement('div')
143
- this._titleEl.className = 'title'
144
- this._titleEl.setAttribute('part', 'title')
145
-
146
- this._subtitleEl = document.createElement('div')
147
- this._subtitleEl.className = 'subtitle'
148
- this._subtitleEl.setAttribute('part', 'subtitle')
149
-
150
- this._updateText()
151
-
152
- container.append(spinner, this._titleEl, this._subtitleEl)
153
- shadow.appendChild(container)
154
-
155
- // Time-synced animation — phase matches wall-clock time
156
- const now = Date.now()
157
- outer.style.animationDelay = `-${now % OUTER_DURATION}ms`
158
- inner.style.animationDelay = `-${now % INNER_DURATION}ms`
159
- }
160
-
161
- disconnectedCallback() {
162
- this._titleEl = null
163
- this._subtitleEl = null
164
- }
165
-
166
- attributeChangedCallback() {
167
- this._updateText()
168
- }
169
-
170
- private _updateText() {
171
- if (this._titleEl)
172
- this._titleEl.textContent = this.getAttribute('title') ?? ''
173
- if (this._subtitleEl)
174
- this._subtitleEl.textContent = this.getAttribute('subtitle') ?? ''
175
- }
176
- }