@serve.zone/catalog 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/dist_ts_web/00_commitinfo_data.d.ts +8 -0
  2. package/dist_ts_web/00_commitinfo_data.js +9 -0
  3. package/dist_ts_web/elements/index.d.ts +33 -0
  4. package/dist_ts_web/elements/index.js +45 -0
  5. package/dist_ts_web/elements/sz-certificates-card.d.ts +14 -0
  6. package/dist_ts_web/elements/sz-certificates-card.js +210 -0
  7. package/dist_ts_web/elements/sz-dashboard-view.d.ts +33 -0
  8. package/dist_ts_web/elements/sz-dashboard-view.js +242 -0
  9. package/dist_ts_web/elements/sz-demo-view-dashboard.d.ts +18 -0
  10. package/dist_ts_web/elements/sz-demo-view-dashboard.js +184 -0
  11. package/dist_ts_web/elements/sz-demo-view-network.d.ts +32 -0
  12. package/dist_ts_web/elements/sz-demo-view-network.js +384 -0
  13. package/dist_ts_web/elements/sz-demo-view-registries.d.ts +22 -0
  14. package/dist_ts_web/elements/sz-demo-view-registries.js +240 -0
  15. package/dist_ts_web/elements/sz-demo-view-services.d.ts +32 -0
  16. package/dist_ts_web/elements/sz-demo-view-services.js +468 -0
  17. package/dist_ts_web/elements/sz-demo-view-settings.d.ts +19 -0
  18. package/dist_ts_web/elements/sz-demo-view-settings.js +151 -0
  19. package/dist_ts_web/elements/sz-demo-view-tokens.d.ts +20 -0
  20. package/dist_ts_web/elements/sz-demo-view-tokens.js +141 -0
  21. package/dist_ts_web/elements/sz-dns-ssl-card.d.ts +13 -0
  22. package/dist_ts_web/elements/sz-dns-ssl-card.js +180 -0
  23. package/dist_ts_web/elements/sz-domain-detail-view.d.ts +48 -0
  24. package/dist_ts_web/elements/sz-domain-detail-view.js +789 -0
  25. package/dist_ts_web/elements/sz-login-view.d.ts +18 -0
  26. package/dist_ts_web/elements/sz-login-view.js +384 -0
  27. package/dist_ts_web/elements/sz-network-dns-view.d.ts +20 -0
  28. package/dist_ts_web/elements/sz-network-dns-view.js +244 -0
  29. package/dist_ts_web/elements/sz-network-domains-view.d.ts +28 -0
  30. package/dist_ts_web/elements/sz-network-domains-view.js +312 -0
  31. package/dist_ts_web/elements/sz-network-proxy-view.d.ts +39 -0
  32. package/dist_ts_web/elements/sz-network-proxy-view.js +510 -0
  33. package/dist_ts_web/elements/sz-platform-service-detail-view.d.ts +49 -0
  34. package/dist_ts_web/elements/sz-platform-service-detail-view.js +733 -0
  35. package/dist_ts_web/elements/sz-platform-services-card.d.ts +19 -0
  36. package/dist_ts_web/elements/sz-platform-services-card.js +196 -0
  37. package/dist_ts_web/elements/sz-quick-actions-card.d.ts +19 -0
  38. package/dist_ts_web/elements/sz-quick-actions-card.js +194 -0
  39. package/dist_ts_web/elements/sz-registry-external-view.d.ts +22 -0
  40. package/dist_ts_web/elements/sz-registry-external-view.js +313 -0
  41. package/dist_ts_web/elements/sz-registry-onebox-view.d.ts +14 -0
  42. package/dist_ts_web/elements/sz-registry-onebox-view.js +307 -0
  43. package/dist_ts_web/elements/sz-resource-usage-card.d.ts +25 -0
  44. package/dist_ts_web/elements/sz-resource-usage-card.js +323 -0
  45. package/dist_ts_web/elements/sz-reverse-proxy-card.d.ts +16 -0
  46. package/dist_ts_web/elements/sz-reverse-proxy-card.js +216 -0
  47. package/dist_ts_web/elements/sz-service-create-view.d.ts +67 -0
  48. package/dist_ts_web/elements/sz-service-create-view.js +828 -0
  49. package/dist_ts_web/elements/sz-service-detail-view.d.ts +57 -0
  50. package/dist_ts_web/elements/sz-service-detail-view.js +728 -0
  51. package/dist_ts_web/elements/sz-services-backups-view.d.ts +37 -0
  52. package/dist_ts_web/elements/sz-services-backups-view.js +413 -0
  53. package/dist_ts_web/elements/sz-services-list-view.d.ts +20 -0
  54. package/dist_ts_web/elements/sz-services-list-view.js +272 -0
  55. package/dist_ts_web/elements/sz-settings-view.d.ts +30 -0
  56. package/dist_ts_web/elements/sz-settings-view.js +448 -0
  57. package/dist_ts_web/elements/sz-stat-card.d.ts +17 -0
  58. package/dist_ts_web/elements/sz-stat-card.js +249 -0
  59. package/dist_ts_web/elements/sz-status-grid-cluster.d.ts +19 -0
  60. package/dist_ts_web/elements/sz-status-grid-cluster.js +142 -0
  61. package/dist_ts_web/elements/sz-status-grid-infra.d.ts +17 -0
  62. package/dist_ts_web/elements/sz-status-grid-infra.js +140 -0
  63. package/dist_ts_web/elements/sz-status-grid-network.d.ts +30 -0
  64. package/dist_ts_web/elements/sz-status-grid-network.js +190 -0
  65. package/dist_ts_web/elements/sz-status-grid-services.d.ts +17 -0
  66. package/dist_ts_web/elements/sz-status-grid-services.js +145 -0
  67. package/dist_ts_web/elements/sz-tokens-view.d.ts +26 -0
  68. package/dist_ts_web/elements/sz-tokens-view.js +344 -0
  69. package/dist_ts_web/elements/sz-traffic-card.d.ts +24 -0
  70. package/dist_ts_web/elements/sz-traffic-card.js +255 -0
  71. package/dist_ts_web/index.d.ts +2 -0
  72. package/dist_ts_web/index.js +3 -0
  73. package/dist_ts_web/pages/index.d.ts +3 -0
  74. package/dist_ts_web/pages/index.js +4 -0
  75. package/dist_ts_web/pages/mainpage.d.ts +1 -0
  76. package/dist_ts_web/pages/mainpage.js +46 -0
  77. package/dist_ts_web/pages/sz-demo-app-shell.d.ts +13 -0
  78. package/dist_ts_web/pages/sz-demo-app-shell.js +212 -0
  79. package/dist_ts_web/pages/sz-demo-app.d.ts +2 -0
  80. package/dist_ts_web/pages/sz-demo-app.js +20 -0
  81. package/npmextra.json +24 -0
  82. package/package.json +45 -0
  83. package/ts_web/00_commitinfo_data.ts +8 -0
  84. package/ts_web/elements/index.ts +54 -0
  85. package/ts_web/elements/sz-certificates-card.ts +155 -0
  86. package/ts_web/elements/sz-dashboard-view.ts +217 -0
  87. package/ts_web/elements/sz-demo-view-dashboard.ts +150 -0
  88. package/ts_web/elements/sz-demo-view-network.ts +354 -0
  89. package/ts_web/elements/sz-demo-view-registries.ts +206 -0
  90. package/ts_web/elements/sz-demo-view-services.ts +434 -0
  91. package/ts_web/elements/sz-demo-view-settings.ts +118 -0
  92. package/ts_web/elements/sz-demo-view-tokens.ts +109 -0
  93. package/ts_web/elements/sz-dns-ssl-card.ts +130 -0
  94. package/ts_web/elements/sz-domain-detail-view.ts +766 -0
  95. package/ts_web/elements/sz-login-view.ts +329 -0
  96. package/ts_web/elements/sz-network-dns-view.ts +208 -0
  97. package/ts_web/elements/sz-network-domains-view.ts +273 -0
  98. package/ts_web/elements/sz-network-proxy-view.ts +456 -0
  99. package/ts_web/elements/sz-platform-service-detail-view.ts +714 -0
  100. package/ts_web/elements/sz-platform-services-card.ts +163 -0
  101. package/ts_web/elements/sz-quick-actions-card.ts +161 -0
  102. package/ts_web/elements/sz-registry-external-view.ts +279 -0
  103. package/ts_web/elements/sz-registry-onebox-view.ts +258 -0
  104. package/ts_web/elements/sz-resource-usage-card.ts +284 -0
  105. package/ts_web/elements/sz-reverse-proxy-card.ts +151 -0
  106. package/ts_web/elements/sz-service-create-view.ts +773 -0
  107. package/ts_web/elements/sz-service-detail-view.ts +710 -0
  108. package/ts_web/elements/sz-services-backups-view.ts +390 -0
  109. package/ts_web/elements/sz-services-list-view.ts +237 -0
  110. package/ts_web/elements/sz-settings-view.ts +417 -0
  111. package/ts_web/elements/sz-stat-card.ts +187 -0
  112. package/ts_web/elements/sz-status-grid-cluster.ts +105 -0
  113. package/ts_web/elements/sz-status-grid-infra.ts +88 -0
  114. package/ts_web/elements/sz-status-grid-network.ts +152 -0
  115. package/ts_web/elements/sz-status-grid-services.ts +99 -0
  116. package/ts_web/elements/sz-tokens-view.ts +308 -0
  117. package/ts_web/elements/sz-traffic-card.ts +222 -0
  118. package/ts_web/index.ts +2 -0
  119. package/ts_web/pages/index.ts +3 -0
  120. package/ts_web/pages/mainpage.ts +46 -0
  121. package/ts_web/pages/sz-demo-app-shell.ts +179 -0
  122. package/ts_web/pages/sz-demo-app.ts +20 -0
@@ -0,0 +1,417 @@
1
+ import {
2
+ DeesElement,
3
+ customElement,
4
+ html,
5
+ css,
6
+ cssManager,
7
+ property,
8
+ type TemplateResult,
9
+ } from '@design.estate/dees-element';
10
+
11
+ declare global {
12
+ interface HTMLElementTagNameMap {
13
+ 'sz-settings-view': SzSettingsView;
14
+ }
15
+ }
16
+
17
+ export interface ISettings {
18
+ darkMode: boolean;
19
+ cloudflareToken: string;
20
+ cloudflareZoneId: string;
21
+ autoRenewCerts: boolean;
22
+ renewalThreshold: number;
23
+ acmeEmail: string;
24
+ httpPort: number;
25
+ httpsPort: number;
26
+ forceHttps: boolean;
27
+ }
28
+
29
+ @customElement('sz-settings-view')
30
+ export class SzSettingsView extends DeesElement {
31
+ public static demo = () => html`
32
+ <div style="padding: 24px; max-width: 800px;">
33
+ <sz-settings-view
34
+ .settings=${{
35
+ darkMode: true,
36
+ cloudflareToken: '',
37
+ cloudflareZoneId: '',
38
+ autoRenewCerts: true,
39
+ renewalThreshold: 30,
40
+ acmeEmail: 'certs@example.com',
41
+ httpPort: 80,
42
+ httpsPort: 443,
43
+ forceHttps: true,
44
+ }}
45
+ currentUser="admin"
46
+ ></sz-settings-view>
47
+ </div>
48
+ `;
49
+
50
+ @property({ type: Object })
51
+ public accessor settings: ISettings = {
52
+ darkMode: false,
53
+ cloudflareToken: '',
54
+ cloudflareZoneId: '',
55
+ autoRenewCerts: true,
56
+ renewalThreshold: 30,
57
+ acmeEmail: '',
58
+ httpPort: 80,
59
+ httpsPort: 443,
60
+ forceHttps: true,
61
+ };
62
+
63
+ @property({ type: String })
64
+ public accessor currentUser: string = '';
65
+
66
+ public static styles = [
67
+ cssManager.defaultStyles,
68
+ css`
69
+ :host {
70
+ display: block;
71
+ }
72
+
73
+ .section {
74
+ background: ${cssManager.bdTheme('#ffffff', '#09090b')};
75
+ border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
76
+ border-radius: 8px;
77
+ padding: 20px;
78
+ margin-bottom: 24px;
79
+ }
80
+
81
+ .section-header {
82
+ margin-bottom: 16px;
83
+ }
84
+
85
+ .section-title {
86
+ font-size: 16px;
87
+ font-weight: 600;
88
+ color: ${cssManager.bdTheme('#18181b', '#fafafa')};
89
+ }
90
+
91
+ .section-subtitle {
92
+ font-size: 13px;
93
+ color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
94
+ margin-top: 2px;
95
+ }
96
+
97
+ .form-group {
98
+ margin-bottom: 16px;
99
+ }
100
+
101
+ .form-group:last-child {
102
+ margin-bottom: 0;
103
+ }
104
+
105
+ .form-row {
106
+ display: flex;
107
+ justify-content: space-between;
108
+ align-items: center;
109
+ padding: 12px 0;
110
+ border-bottom: 1px solid ${cssManager.bdTheme('#f4f4f5', '#27272a')};
111
+ }
112
+
113
+ .form-row:last-child {
114
+ border-bottom: none;
115
+ }
116
+
117
+ .form-label-group {
118
+ display: flex;
119
+ flex-direction: column;
120
+ gap: 2px;
121
+ }
122
+
123
+ .form-label {
124
+ font-size: 14px;
125
+ font-weight: 500;
126
+ color: ${cssManager.bdTheme('#18181b', '#fafafa')};
127
+ }
128
+
129
+ .form-hint {
130
+ font-size: 12px;
131
+ color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
132
+ }
133
+
134
+ .input-group {
135
+ display: flex;
136
+ flex-direction: column;
137
+ gap: 8px;
138
+ }
139
+
140
+ .input-row {
141
+ display: grid;
142
+ grid-template-columns: 1fr 1fr;
143
+ gap: 16px;
144
+ }
145
+
146
+ input[type="text"],
147
+ input[type="password"],
148
+ input[type="email"],
149
+ input[type="number"] {
150
+ width: 100%;
151
+ padding: 8px 12px;
152
+ background: ${cssManager.bdTheme('#ffffff', '#09090b')};
153
+ border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
154
+ border-radius: 6px;
155
+ font-size: 14px;
156
+ color: ${cssManager.bdTheme('#18181b', '#fafafa')};
157
+ outline: none;
158
+ transition: border-color 200ms ease;
159
+ box-sizing: border-box;
160
+ }
161
+
162
+ input:focus {
163
+ border-color: ${cssManager.bdTheme('#3b82f6', '#60a5fa')};
164
+ }
165
+
166
+ input::placeholder {
167
+ color: ${cssManager.bdTheme('#a1a1aa', '#52525b')};
168
+ }
169
+
170
+ .toggle-switch {
171
+ position: relative;
172
+ width: 44px;
173
+ height: 24px;
174
+ background: ${cssManager.bdTheme('#e4e4e7', '#27272a')};
175
+ border-radius: 9999px;
176
+ cursor: pointer;
177
+ transition: background 200ms ease;
178
+ }
179
+
180
+ .toggle-switch.active {
181
+ background: ${cssManager.bdTheme('#2563eb', '#3b82f6')};
182
+ }
183
+
184
+ .toggle-switch::after {
185
+ content: '';
186
+ position: absolute;
187
+ top: 2px;
188
+ left: 2px;
189
+ width: 20px;
190
+ height: 20px;
191
+ background: white;
192
+ border-radius: 50%;
193
+ transition: transform 200ms ease;
194
+ }
195
+
196
+ .toggle-switch.active::after {
197
+ transform: translateX(20px);
198
+ }
199
+
200
+ .password-section {
201
+ margin-top: 16px;
202
+ padding-top: 16px;
203
+ border-top: 1px solid ${cssManager.bdTheme('#f4f4f5', '#27272a')};
204
+ }
205
+
206
+ .password-title {
207
+ font-size: 14px;
208
+ font-weight: 600;
209
+ color: ${cssManager.bdTheme('#18181b', '#fafafa')};
210
+ margin-bottom: 12px;
211
+ }
212
+
213
+ .password-fields {
214
+ display: flex;
215
+ flex-direction: column;
216
+ gap: 12px;
217
+ }
218
+
219
+ .field-label {
220
+ font-size: 13px;
221
+ color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
222
+ margin-bottom: 4px;
223
+ }
224
+
225
+ .actions {
226
+ display: flex;
227
+ justify-content: flex-end;
228
+ gap: 12px;
229
+ padding-top: 16px;
230
+ border-top: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
231
+ margin-top: 24px;
232
+ }
233
+
234
+ .button {
235
+ padding: 10px 20px;
236
+ border-radius: 6px;
237
+ font-size: 14px;
238
+ font-weight: 500;
239
+ cursor: pointer;
240
+ transition: all 200ms ease;
241
+ }
242
+
243
+ .button.secondary {
244
+ background: ${cssManager.bdTheme('#ffffff', '#09090b')};
245
+ border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
246
+ color: ${cssManager.bdTheme('#18181b', '#fafafa')};
247
+ }
248
+
249
+ .button.secondary:hover {
250
+ background: ${cssManager.bdTheme('#f4f4f5', '#18181b')};
251
+ }
252
+
253
+ .button.primary {
254
+ background: ${cssManager.bdTheme('#18181b', '#fafafa')};
255
+ border: none;
256
+ color: ${cssManager.bdTheme('#fafafa', '#18181b')};
257
+ }
258
+
259
+ .button.primary:hover {
260
+ opacity: 0.9;
261
+ }
262
+ `,
263
+ ];
264
+
265
+ public render(): TemplateResult {
266
+ return html`
267
+ <div class="section">
268
+ <div class="section-header">
269
+ <div class="section-title">Appearance</div>
270
+ <div class="section-subtitle">Customize the look and feel</div>
271
+ </div>
272
+ <div class="form-row">
273
+ <div class="form-label-group">
274
+ <span class="form-label">Dark Mode</span>
275
+ <span class="form-hint">Toggle dark mode on or off</span>
276
+ </div>
277
+ <div class="toggle-switch ${this.settings.darkMode ? 'active' : ''}" @click=${() => this.toggleDarkMode()}></div>
278
+ </div>
279
+ </div>
280
+
281
+ <div class="section">
282
+ <div class="section-header">
283
+ <div class="section-title">Cloudflare Integration</div>
284
+ <div class="section-subtitle">Configure Cloudflare API for DNS management</div>
285
+ </div>
286
+ <div class="input-group">
287
+ <div class="form-group">
288
+ <div class="field-label">API Token</div>
289
+ <input type="password" placeholder="Enter Cloudflare API token" .value=${this.settings.cloudflareToken} @input=${(e: Event) => this.updateSetting('cloudflareToken', (e.target as HTMLInputElement).value)}>
290
+ </div>
291
+ <div class="form-group">
292
+ <div class="field-label">Zone ID (Optional)</div>
293
+ <input type="text" placeholder="Default zone ID" .value=${this.settings.cloudflareZoneId} @input=${(e: Event) => this.updateSetting('cloudflareZoneId', (e.target as HTMLInputElement).value)}>
294
+ </div>
295
+ <div class="form-hint">Get your API token from the Cloudflare dashboard with DNS edit permissions.</div>
296
+ </div>
297
+ </div>
298
+
299
+ <div class="section">
300
+ <div class="section-header">
301
+ <div class="section-title">SSL/TLS Settings</div>
302
+ <div class="section-subtitle">Configure certificate management</div>
303
+ </div>
304
+ <div class="form-row">
305
+ <div class="form-label-group">
306
+ <span class="form-label">Auto-Renew Certificates</span>
307
+ <span class="form-hint">Automatically renew certificates before expiry</span>
308
+ </div>
309
+ <div class="toggle-switch ${this.settings.autoRenewCerts ? 'active' : ''}" @click=${() => this.toggleSetting('autoRenewCerts')}></div>
310
+ </div>
311
+ <div class="form-group" style="margin-top: 16px;">
312
+ <div class="field-label">Renewal Threshold (days)</div>
313
+ <input type="number" .value=${String(this.settings.renewalThreshold)} @input=${(e: Event) => this.updateSetting('renewalThreshold', parseInt((e.target as HTMLInputElement).value))}>
314
+ <div class="form-hint">Renew certificates when they have fewer than this many days remaining.</div>
315
+ </div>
316
+ <div class="form-group">
317
+ <div class="field-label">ACME Email</div>
318
+ <input type="email" placeholder="admin@example.com" .value=${this.settings.acmeEmail} @input=${(e: Event) => this.updateSetting('acmeEmail', (e.target as HTMLInputElement).value)}>
319
+ <div class="form-hint">Email address for Let's Encrypt notifications.</div>
320
+ </div>
321
+ </div>
322
+
323
+ <div class="section">
324
+ <div class="section-header">
325
+ <div class="section-title">Network Settings</div>
326
+ <div class="section-subtitle">Configure network and proxy settings</div>
327
+ </div>
328
+ <div class="input-row">
329
+ <div class="form-group">
330
+ <div class="field-label">HTTP Port</div>
331
+ <input type="number" .value=${String(this.settings.httpPort)} @input=${(e: Event) => this.updateSetting('httpPort', parseInt((e.target as HTMLInputElement).value))}>
332
+ </div>
333
+ <div class="form-group">
334
+ <div class="field-label">HTTPS Port</div>
335
+ <input type="number" .value=${String(this.settings.httpsPort)} @input=${(e: Event) => this.updateSetting('httpsPort', parseInt((e.target as HTMLInputElement).value))}>
336
+ </div>
337
+ </div>
338
+ <div class="form-row">
339
+ <div class="form-label-group">
340
+ <span class="form-label">Force HTTPS</span>
341
+ <span class="form-hint">Redirect all HTTP traffic to HTTPS</span>
342
+ </div>
343
+ <div class="toggle-switch ${this.settings.forceHttps ? 'active' : ''}" @click=${() => this.toggleSetting('forceHttps')}></div>
344
+ </div>
345
+ </div>
346
+
347
+ <div class="section">
348
+ <div class="section-header">
349
+ <div class="section-title">Account</div>
350
+ <div class="section-subtitle">Manage your account settings</div>
351
+ </div>
352
+ <div class="form-group">
353
+ <div class="field-label">Current User</div>
354
+ <div style="font-size: 14px; color: ${cssManager.bdTheme('#18181b', '#fafafa')};">${this.currentUser || 'Unknown'}</div>
355
+ </div>
356
+ <div class="password-section">
357
+ <div class="password-title">Change Password</div>
358
+ <div class="password-fields">
359
+ <div>
360
+ <div class="field-label">Current Password</div>
361
+ <input type="password" id="currentPassword">
362
+ </div>
363
+ <div>
364
+ <div class="field-label">New Password</div>
365
+ <input type="password" id="newPassword">
366
+ </div>
367
+ <div>
368
+ <div class="field-label">Confirm Password</div>
369
+ <input type="password" id="confirmPassword">
370
+ </div>
371
+ <button class="button secondary" style="width: fit-content;" @click=${() => this.handleChangePassword()}>Update Password</button>
372
+ </div>
373
+ </div>
374
+ </div>
375
+
376
+ <div class="actions">
377
+ <button class="button secondary" @click=${() => this.handleReset()}>Reset</button>
378
+ <button class="button primary" @click=${() => this.handleSave()}>Save Settings</button>
379
+ </div>
380
+ `;
381
+ }
382
+
383
+ private toggleDarkMode() {
384
+ this.settings = { ...this.settings, darkMode: !this.settings.darkMode };
385
+ this.dispatchEvent(new CustomEvent('setting-change', { detail: { key: 'darkMode', value: this.settings.darkMode }, bubbles: true, composed: true }));
386
+ }
387
+
388
+ private toggleSetting(key: keyof ISettings) {
389
+ (this.settings as any)[key] = !(this.settings as any)[key];
390
+ this.settings = { ...this.settings };
391
+ }
392
+
393
+ private updateSetting(key: keyof ISettings, value: any) {
394
+ (this.settings as any)[key] = value;
395
+ this.settings = { ...this.settings };
396
+ }
397
+
398
+ private handleChangePassword() {
399
+ const currentPassword = (this.shadowRoot?.getElementById('currentPassword') as HTMLInputElement)?.value;
400
+ const newPassword = (this.shadowRoot?.getElementById('newPassword') as HTMLInputElement)?.value;
401
+ const confirmPassword = (this.shadowRoot?.getElementById('confirmPassword') as HTMLInputElement)?.value;
402
+
403
+ this.dispatchEvent(new CustomEvent('change-password', {
404
+ detail: { currentPassword, newPassword, confirmPassword },
405
+ bubbles: true,
406
+ composed: true
407
+ }));
408
+ }
409
+
410
+ private handleReset() {
411
+ this.dispatchEvent(new CustomEvent('reset', { bubbles: true, composed: true }));
412
+ }
413
+
414
+ private handleSave() {
415
+ this.dispatchEvent(new CustomEvent('save', { detail: this.settings, bubbles: true, composed: true }));
416
+ }
417
+ }
@@ -0,0 +1,187 @@
1
+ import {
2
+ DeesElement,
3
+ customElement,
4
+ html,
5
+ css,
6
+ cssManager,
7
+ property,
8
+ type TemplateResult,
9
+ } from '@design.estate/dees-element';
10
+
11
+ declare global {
12
+ interface HTMLElementTagNameMap {
13
+ 'sz-stat-card': SzStatCard;
14
+ }
15
+ }
16
+
17
+ @customElement('sz-stat-card')
18
+ export class SzStatCard extends DeesElement {
19
+ public static demo = () => html`
20
+ <style>
21
+ .demo-grid {
22
+ display: grid;
23
+ grid-template-columns: repeat(2, 1fr);
24
+ gap: 16px;
25
+ padding: 24px;
26
+ max-width: 800px;
27
+ }
28
+ </style>
29
+ <div class="demo-grid">
30
+ <sz-stat-card
31
+ label="Total Services"
32
+ value="7"
33
+ icon="server"
34
+ ></sz-stat-card>
35
+ <sz-stat-card
36
+ label="Running"
37
+ value="7"
38
+ icon="check"
39
+ variant="success"
40
+ ></sz-stat-card>
41
+ <sz-stat-card
42
+ label="Stopped"
43
+ value="0"
44
+ icon="stop"
45
+ ></sz-stat-card>
46
+ <sz-stat-card
47
+ label="Docker"
48
+ value="Running"
49
+ icon="container"
50
+ variant="success"
51
+ valueBadge
52
+ ></sz-stat-card>
53
+ </div>
54
+ `;
55
+
56
+ @property({ type: String })
57
+ public accessor label: string = '';
58
+
59
+ @property({ type: String })
60
+ public accessor value: string = '';
61
+
62
+ @property({ type: String })
63
+ public accessor icon: string = '';
64
+
65
+ @property({ type: String })
66
+ public accessor variant: 'default' | 'success' | 'warning' | 'error' = 'default';
67
+
68
+ @property({ type: Boolean })
69
+ public accessor valueBadge: boolean = false;
70
+
71
+ public static styles = [
72
+ cssManager.defaultStyles,
73
+ css`
74
+ :host {
75
+ display: block;
76
+ height: 100%;
77
+ }
78
+
79
+ .card {
80
+ background: ${cssManager.bdTheme('#ffffff', '#09090b')};
81
+ border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
82
+ border-radius: 8px;
83
+ padding: 20px;
84
+ transition: all 200ms ease;
85
+ height: 100%;
86
+ box-sizing: border-box;
87
+ }
88
+
89
+ .card:hover {
90
+ border-color: ${cssManager.bdTheme('#d4d4d8', '#3f3f46')};
91
+ box-shadow: 0 4px 12px ${cssManager.bdTheme('rgba(0,0,0,0.05)', 'rgba(0,0,0,0.2)')};
92
+ }
93
+
94
+ .header {
95
+ display: flex;
96
+ justify-content: space-between;
97
+ align-items: center;
98
+ margin-bottom: 8px;
99
+ }
100
+
101
+ .label {
102
+ font-size: 14px;
103
+ font-weight: 500;
104
+ color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
105
+ }
106
+
107
+ .icon {
108
+ width: 20px;
109
+ height: 20px;
110
+ color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
111
+ }
112
+
113
+ .value {
114
+ font-size: 28px;
115
+ font-weight: 700;
116
+ color: ${cssManager.bdTheme('#18181b', '#fafafa')};
117
+ line-height: 1.2;
118
+ }
119
+
120
+ .value.success {
121
+ color: ${cssManager.bdTheme('#16a34a', '#22c55e')};
122
+ }
123
+
124
+ .value.warning {
125
+ color: ${cssManager.bdTheme('#ca8a04', '#facc15')};
126
+ }
127
+
128
+ .value.error {
129
+ color: ${cssManager.bdTheme('#dc2626', '#ef4444')};
130
+ }
131
+
132
+ .badge {
133
+ display: inline-flex;
134
+ align-items: center;
135
+ padding: 4px 12px;
136
+ border-radius: 9999px;
137
+ font-size: 14px;
138
+ font-weight: 500;
139
+ }
140
+
141
+ .badge.success {
142
+ background: ${cssManager.bdTheme('#dcfce7', 'rgba(34, 197, 94, 0.2)')};
143
+ color: ${cssManager.bdTheme('#16a34a', '#22c55e')};
144
+ }
145
+
146
+ .badge.warning {
147
+ background: ${cssManager.bdTheme('#fef9c3', 'rgba(250, 204, 21, 0.2)')};
148
+ color: ${cssManager.bdTheme('#ca8a04', '#facc15')};
149
+ }
150
+
151
+ .badge.error {
152
+ background: ${cssManager.bdTheme('#fee2e2', 'rgba(239, 68, 68, 0.2)')};
153
+ color: ${cssManager.bdTheme('#dc2626', '#ef4444')};
154
+ }
155
+
156
+ .badge.default {
157
+ background: ${cssManager.bdTheme('#f4f4f5', '#27272a')};
158
+ color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
159
+ }
160
+ `,
161
+ ];
162
+
163
+ public render(): TemplateResult {
164
+ const valueClass = this.valueBadge ? `badge ${this.variant}` : `value ${this.variant}`;
165
+
166
+ return html`
167
+ <div class="card">
168
+ <div class="header">
169
+ <span class="label">${this.label}</span>
170
+ ${this.renderIcon()}
171
+ </div>
172
+ <div class="${valueClass}">${this.value}</div>
173
+ </div>
174
+ `;
175
+ }
176
+
177
+ private renderIcon(): TemplateResult {
178
+ const icons: Record<string, TemplateResult> = {
179
+ server: html`<svg class="icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><rect x="2" y="2" width="20" height="8" rx="2" ry="2"></rect><rect x="2" y="14" width="20" height="8" rx="2" ry="2"></rect><line x1="6" y1="6" x2="6.01" y2="6"></line><line x1="6" y1="18" x2="6.01" y2="18"></line></svg>`,
180
+ check: html`<svg class="icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"></polyline></svg>`,
181
+ stop: html`<svg class="icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"></circle><line x1="10" y1="15" x2="10" y2="9"></line><line x1="14" y1="15" x2="14" y2="9"></line></svg>`,
182
+ container: html`<svg class="icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path></svg>`,
183
+ };
184
+
185
+ return icons[this.icon] || html``;
186
+ }
187
+ }
@@ -0,0 +1,105 @@
1
+ import {
2
+ DeesElement,
3
+ customElement,
4
+ html,
5
+ css,
6
+ cssManager,
7
+ property,
8
+ type TemplateResult,
9
+ } from '@design.estate/dees-element';
10
+
11
+ import './sz-stat-card.js';
12
+
13
+ declare global {
14
+ interface HTMLElementTagNameMap {
15
+ 'sz-status-grid-cluster': SzStatusGridCluster;
16
+ }
17
+ }
18
+
19
+ export interface IClusterStats {
20
+ totalServices: number;
21
+ running: number;
22
+ stopped: number;
23
+ dockerStatus: 'running' | 'stopped';
24
+ }
25
+
26
+ @customElement('sz-status-grid-cluster')
27
+ export class SzStatusGridCluster extends DeesElement {
28
+ public static demo = () => html`
29
+ <div style="padding: 24px; max-width: 900px;">
30
+ <sz-status-grid-cluster
31
+ .stats=${{
32
+ totalServices: 7,
33
+ running: 7,
34
+ stopped: 0,
35
+ dockerStatus: 'running',
36
+ }}
37
+ ></sz-status-grid-cluster>
38
+ </div>
39
+ `;
40
+
41
+ @property({ type: Object })
42
+ public accessor stats: IClusterStats = {
43
+ totalServices: 0,
44
+ running: 0,
45
+ stopped: 0,
46
+ dockerStatus: 'stopped',
47
+ };
48
+
49
+ public static styles = [
50
+ cssManager.defaultStyles,
51
+ css`
52
+ :host {
53
+ display: block;
54
+ }
55
+
56
+ .grid {
57
+ display: grid;
58
+ grid-template-columns: repeat(2, 1fr);
59
+ gap: 16px;
60
+ align-items: stretch;
61
+ }
62
+
63
+ .grid > * {
64
+ height: 100%;
65
+ }
66
+
67
+ @media (min-width: 768px) {
68
+ .grid {
69
+ grid-template-columns: repeat(4, 1fr);
70
+ }
71
+ }
72
+ `,
73
+ ];
74
+
75
+ public render(): TemplateResult {
76
+ return html`
77
+ <div class="grid">
78
+ <sz-stat-card
79
+ label="Total Services"
80
+ value="${this.stats.totalServices}"
81
+ icon="server"
82
+ ></sz-stat-card>
83
+ <sz-stat-card
84
+ label="Running"
85
+ value="${this.stats.running}"
86
+ icon="check"
87
+ variant="success"
88
+ ></sz-stat-card>
89
+ <sz-stat-card
90
+ label="Stopped"
91
+ value="${this.stats.stopped}"
92
+ icon="stop"
93
+ variant="${this.stats.stopped > 0 ? 'warning' : 'default'}"
94
+ ></sz-stat-card>
95
+ <sz-stat-card
96
+ label="Docker"
97
+ value="${this.stats.dockerStatus === 'running' ? 'Running' : 'Stopped'}"
98
+ icon="container"
99
+ variant="${this.stats.dockerStatus === 'running' ? 'success' : 'error'}"
100
+ valueBadge
101
+ ></sz-stat-card>
102
+ </div>
103
+ `;
104
+ }
105
+ }