@kodaris/krubble-app-components 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/shell.js ADDED
@@ -0,0 +1,860 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { LitElement, html, css, nothing } from 'lit';
8
+ import { customElement, property, state } from 'lit/decorators.js';
9
+ import { classMap } from 'lit/directives/class-map.js';
10
+ import { unsafeHTML } from 'lit/directives/unsafe-html.js';
11
+ /**
12
+ * Global shell component with app bar for app switching.
13
+ *
14
+ * The shell provides a horizontal app bar across the top of the viewport containing:
15
+ * - Logo/home link on the left
16
+ * - App switcher icons in the middle
17
+ * - User avatar/menu on the right
18
+ *
19
+ * This allows individual apps (using kr-scaffold) to utilize the full width
20
+ * of the browser window while maintaining consistent global navigation.
21
+ *
22
+ * @slot - The main content (typically kr-scaffold with the app)
23
+ *
24
+ * @property {string} logo - URL for the logo image
25
+ * @property {KRApp[]} apps - Available applications for the switcher
26
+ * @property {string} activeAppId - ID of the currently active app
27
+ * @property {KRShellUser} user - User profile data
28
+ * @property {KRShellMenuItem[]} menuItems - Custom menu items for user menu
29
+ *
30
+ * @fires app-click - When an app icon is clicked. Detail: { app: KRApp }
31
+ * @fires menu-item-click - When a menu item is clicked. Detail: { item: KRShellMenuItem }
32
+ * @fires logout - When logout is clicked
33
+ */
34
+ let KRShell = class KRShell extends LitElement {
35
+ constructor() {
36
+ super(...arguments);
37
+ this.logo = 'https://s3.amazonaws.com/kodariscom/kodariscom/content/website/kodaris-logo-icon-light-53.png';
38
+ this.apps = [];
39
+ this.activeAppId = '';
40
+ this.user = null;
41
+ this.menuItems = [];
42
+ this.isUserMenuOpen = false;
43
+ this.isAppsMenuOpen = false;
44
+ this.pendingRequests = 0;
45
+ this.originalFetch = null;
46
+ this.originalXhrOpen = null;
47
+ // Default icons
48
+ this.defaultLogoutIcon = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M17 7l-1.41 1.41L18.17 11H8v2h10.17l-2.58 2.58L17 17l5-5zM4 5h8V3H4c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h8v-2H4V5z"/></svg>';
49
+ this.appsGridIcon = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M4 8h4V4H4v4zm6 12h4v-4h-4v4zm-6 0h4v-4H4v4zm0-6h4v-4H4v4zm6 0h4v-4h-4v4zm6-10v4h4V4h-4zm-6 4h4V4h-4v4zm6 6h4v-4h-4v4zm0 6h4v-4h-4v4z"/></svg>';
50
+ this.closeIcon = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>';
51
+ }
52
+ connectedCallback() {
53
+ super.connectedCallback();
54
+ this.installFetchInterceptor();
55
+ }
56
+ disconnectedCallback() {
57
+ super.disconnectedCallback();
58
+ this.uninstallFetchInterceptor();
59
+ }
60
+ /**
61
+ * Installs global interceptors for fetch and XMLHttpRequest to track pending HTTP requests.
62
+ * Updates `pendingRequests` state when requests start/complete.
63
+ */
64
+ installFetchInterceptor() {
65
+ if (this.originalFetch)
66
+ return;
67
+ const shell = this;
68
+ // Intercept fetch
69
+ this.originalFetch = window.fetch.bind(window);
70
+ const originalFetch = this.originalFetch;
71
+ window.fetch = function (...args) {
72
+ shell.pendingRequests++;
73
+ return originalFetch(...args).finally(() => {
74
+ shell.pendingRequests--;
75
+ });
76
+ };
77
+ // Intercept XMLHttpRequest
78
+ this.originalXhrOpen = XMLHttpRequest.prototype.open;
79
+ const originalXhrOpen = this.originalXhrOpen;
80
+ XMLHttpRequest.prototype.open = function (method, url, async = true, username, password) {
81
+ shell.pendingRequests++;
82
+ this.addEventListener('loadend', () => {
83
+ shell.pendingRequests--;
84
+ }, { once: true });
85
+ return originalXhrOpen.call(this, method, url, async, username, password);
86
+ };
87
+ }
88
+ /**
89
+ * Restores the original fetch and XMLHttpRequest functions.
90
+ */
91
+ uninstallFetchInterceptor() {
92
+ if (this.originalFetch) {
93
+ window.fetch = this.originalFetch;
94
+ this.originalFetch = null;
95
+ }
96
+ if (this.originalXhrOpen) {
97
+ XMLHttpRequest.prototype.open = this.originalXhrOpen;
98
+ this.originalXhrOpen = null;
99
+ }
100
+ }
101
+ handleLogoClick() {
102
+ this.dispatchEvent(new CustomEvent('logo-click', {
103
+ bubbles: true,
104
+ composed: true,
105
+ }));
106
+ }
107
+ toggleUserMenu() {
108
+ this.isUserMenuOpen = !this.isUserMenuOpen;
109
+ this.isAppsMenuOpen = false;
110
+ }
111
+ closeUserMenu() {
112
+ this.isUserMenuOpen = false;
113
+ }
114
+ toggleAppsMenu() {
115
+ this.isAppsMenuOpen = !this.isAppsMenuOpen;
116
+ this.isUserMenuOpen = false;
117
+ }
118
+ closeAppsMenu() {
119
+ this.isAppsMenuOpen = false;
120
+ }
121
+ handleMenuItemClick(item) {
122
+ this.closeUserMenu();
123
+ this.dispatchEvent(new CustomEvent('menu-item-click', {
124
+ detail: { item },
125
+ bubbles: true,
126
+ composed: true,
127
+ }));
128
+ }
129
+ handleLogout() {
130
+ this.closeUserMenu();
131
+ this.dispatchEvent(new CustomEvent('logout', {
132
+ bubbles: true,
133
+ composed: true,
134
+ }));
135
+ }
136
+ renderAppsMenu() {
137
+ return html `
138
+ <div class="appbar-apps">
139
+ ${this.isAppsMenuOpen ? html `
140
+ <div class="menu-backdrop" @click=${this.closeAppsMenu}></div>
141
+ ` : nothing}
142
+
143
+ <button
144
+ class=${classMap({
145
+ 'appbar-apps-btn': true,
146
+ 'appbar-apps-btn--open': this.isAppsMenuOpen,
147
+ })}
148
+ @click=${this.toggleAppsMenu}
149
+ >
150
+ <span class="appbar-apps-btn__icon">${unsafeHTML(this.appsGridIcon)}</span>
151
+ </button>
152
+
153
+ <div class=${classMap({
154
+ 'appbar-apps-menu': true,
155
+ 'appbar-apps-menu--open': this.isAppsMenuOpen,
156
+ })}>
157
+ <div class="appbar-apps-menu__header">
158
+ <h2 class="appbar-apps-menu__title">Applications</h2>
159
+ <button class="appbar-apps-menu__close" @click=${this.closeAppsMenu}>
160
+ ${unsafeHTML(this.closeIcon)}
161
+ </button>
162
+ </div>
163
+ <div class="appbar-apps-menu__content">
164
+ <div class="appbar-apps-menu__list">
165
+ ${this.apps.map((app) => html `
166
+ <a
167
+ class="appbar-apps-menu__item"
168
+ href=${app.url}
169
+ @click=${(e) => {
170
+ this.closeAppsMenu();
171
+ const event = new CustomEvent('app-click', {
172
+ detail: { app },
173
+ bubbles: true,
174
+ composed: true,
175
+ cancelable: true,
176
+ });
177
+ this.dispatchEvent(event);
178
+ if (event.defaultPrevented) {
179
+ e.preventDefault();
180
+ }
181
+ }}
182
+ >
183
+ ${app.name}
184
+ </a>
185
+ `)}
186
+ </div>
187
+ </div>
188
+ </div>
189
+ </div>
190
+ `;
191
+ }
192
+ renderUserMenu() {
193
+ if (!this.user)
194
+ return nothing;
195
+ const initials = this.user.name
196
+ .split(' ')
197
+ .map((part) => part[0])
198
+ .join('')
199
+ .toUpperCase()
200
+ .slice(0, 2);
201
+ return html `
202
+ <div class="appbar-user">
203
+ ${this.isUserMenuOpen ? html `
204
+ <div class="menu-backdrop" @click=${this.closeUserMenu}></div>
205
+ ` : nothing}
206
+
207
+ <div
208
+ class="appbar-user__avatar"
209
+ @click=${this.toggleUserMenu}
210
+ >
211
+ ${this.user.avatar
212
+ ? html `<img src=${this.user.avatar} alt=${this.user.name} />`
213
+ : initials}
214
+ </div>
215
+
216
+ <div class=${classMap({
217
+ 'appbar-user__menu': true,
218
+ 'appbar-user__menu--open': this.isUserMenuOpen,
219
+ })}>
220
+ <div class="appbar-user__header">
221
+ <p class="appbar-user__name">${this.user.name}</p>
222
+ ${this.user.email ? html `
223
+ <p class="appbar-user__email">${this.user.email}</p>
224
+ ` : nothing}
225
+ </div>
226
+
227
+ ${this.menuItems.map((item) => item.divider
228
+ ? html `<div class="appbar-user__menu-divider"></div>`
229
+ : html `
230
+ <button
231
+ class="appbar-user__menu-item"
232
+ @click=${() => this.handleMenuItemClick(item)}
233
+ >
234
+ ${item.icon ? html `
235
+ <span class="appbar-user__menu-item__icon">${unsafeHTML(item.icon)}</span>
236
+ ` : nothing}
237
+ ${item.label}
238
+ </button>
239
+ `)}
240
+
241
+ ${this.menuItems.length > 0 ? html `
242
+ <div class="appbar-user__menu-divider"></div>
243
+ ` : nothing}
244
+
245
+ <button
246
+ class="appbar-user__menu-item appbar-user__menu-item--danger"
247
+ @click=${this.handleLogout}
248
+ >
249
+ <span class="appbar-user__menu-item__icon">${unsafeHTML(this.defaultLogoutIcon)}</span>
250
+ Sign Out
251
+ </button>
252
+ </div>
253
+ </div>
254
+ `;
255
+ }
256
+ render() {
257
+ return html `
258
+ <div class=${classMap({
259
+ 'progress': true,
260
+ 'progress--loading': this.pendingRequests > 0,
261
+ })}>
262
+ <div class="progress__track"></div>
263
+ <div class="progress__bar progress__bar--primary">
264
+ <span class="progress__bar-inner"></span>
265
+ </div>
266
+ <div class="progress__bar progress__bar--secondary">
267
+ <span class="progress__bar-inner"></span>
268
+ </div>
269
+ </div>
270
+
271
+ <header class="appbar">
272
+ <!-- Logo -->
273
+ ${this.logo ? html `
274
+ <div class="appbar-logo" @click=${this.handleLogoClick}>
275
+ <img src=${this.logo} alt="Home" />
276
+ </div>
277
+ <div class="appbar-divider"></div>
278
+ ` : nothing}
279
+
280
+ <!-- App Switcher -->
281
+ ${this.renderAppsMenu()}
282
+
283
+ <div class="appbar-spacer"></div>
284
+
285
+ <!-- User -->
286
+ ${this.renderUserMenu()}
287
+ </header>
288
+
289
+ <div class="subbar">
290
+ <nav class="breadcrumbs">
291
+ <a href="#">Home</a>
292
+ <span class="breadcrumbs__separator">/</span>
293
+ <a href="#">Companies</a>
294
+ <span class="breadcrumbs__separator">/</span>
295
+ <span>Acme Corp</span>
296
+ </nav>
297
+ </div>
298
+
299
+ <main class="main">
300
+ <slot></slot>
301
+ </main>
302
+ `;
303
+ }
304
+ };
305
+ KRShell.styles = css `
306
+ :host {
307
+ display: flex;
308
+ flex-direction: column;
309
+ height: 100vh;
310
+ width: 100vw;
311
+ --kr-shell-bar-height: 48px;
312
+ --kr-shell-bar-bg: #10172a; /* matches scaffold nav-bg */
313
+ /* --kr-shell-bar-bg: #0a0f1a; */ /* original darker bg */
314
+ --kr-shell-bar-border: rgba(255, 255, 255, 0.08);
315
+ --kr-shell-icon-size: 36px;
316
+ --kr-shell-icon-color: rgba(255, 255, 255, 0.7);
317
+ --kr-shell-icon-color-hover: rgba(255, 255, 255, 1);
318
+ --kr-shell-icon-color-active: #beea4e;
319
+ --kr-shell-icon-bg-hover: rgba(255, 255, 255, 0.08);
320
+ --kr-shell-icon-bg-active: rgba(190, 234, 78, 0.15);
321
+ --kr-shell-tooltip-bg: #1a2332;
322
+ --kr-shell-tooltip-color: #ffffff;
323
+ --kr-shell-menu-bg: #1a2332;
324
+ --kr-shell-menu-border: rgba(255, 255, 255, 0.1);
325
+ --kr-shell-menu-hover: rgba(255, 255, 255, 0.08);
326
+ }
327
+
328
+ *,
329
+ *::before,
330
+ *::after {
331
+ box-sizing: border-box;
332
+ }
333
+
334
+ /* App Bar */
335
+ .appbar {
336
+ height: var(--kr-shell-bar-height);
337
+ background: var(--kr-shell-bar-bg);
338
+ border-bottom: 1px solid var(--kr-shell-bar-border);
339
+ display: flex;
340
+ align-items: center;
341
+ padding: 0 16px;
342
+ flex-shrink: 0;
343
+ z-index: 100;
344
+ }
345
+
346
+ /* Logo */
347
+ .appbar-logo {
348
+ cursor: pointer;
349
+ margin-right: 8px;
350
+ }
351
+
352
+ .appbar-logo img {
353
+ display: block;
354
+ max-width: 24px;
355
+ max-height: 24px;
356
+ object-fit: contain;
357
+ }
358
+
359
+ /* Divider */
360
+ .appbar-divider {
361
+ width: 1px;
362
+ height: 24px;
363
+ background: #ffffff4f;
364
+ margin: 0 10px;
365
+ }
366
+
367
+ /* Apps Button */
368
+ .appbar-apps {
369
+ position: relative;
370
+ }
371
+
372
+ .appbar-apps-btn {
373
+ width: var(--kr-shell-icon-size);
374
+ height: var(--kr-shell-icon-size);
375
+ display: flex;
376
+ align-items: center;
377
+ justify-content: center;
378
+ border-radius: 6px;
379
+ cursor: pointer;
380
+ color: var(--kr-shell-icon-color);
381
+ background: transparent;
382
+ border: none;
383
+ padding: 0;
384
+ transition: all 0.15s ease;
385
+ }
386
+
387
+ .appbar-apps-btn:hover {
388
+ color: var(--kr-shell-icon-color-hover);
389
+ background: var(--kr-shell-icon-bg-hover);
390
+ }
391
+
392
+ .appbar-apps-btn--open {
393
+ color: var(--kr-shell-icon-color-hover);
394
+ background: var(--kr-shell-icon-bg-hover);
395
+ }
396
+
397
+ .appbar-apps-btn__icon {
398
+ width: 24px;
399
+ height: 24px;
400
+ display: flex;
401
+ align-items: center;
402
+ justify-content: center;
403
+ color: #ffffff;
404
+ }
405
+
406
+ .appbar-apps-btn__icon svg {
407
+ width: 100%;
408
+ height: 100%;
409
+ fill: currentColor;
410
+ }
411
+
412
+ /* Apps Megamenu */
413
+ .appbar-apps-menu {
414
+ position: absolute;
415
+ left: 0;
416
+ top: 100%;
417
+ margin-top: 6px;
418
+ min-width: 320px;
419
+ min-height: 90vh;
420
+ max-height: calc(100vh - var(--kr-shell-bar-height));
421
+ background: #10172a;
422
+ border: 1px solid var(--kr-shell-menu-border);
423
+ border-top: none;
424
+ border-radius: 0 0 8px 8px;
425
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
426
+ z-index: 1000;
427
+ opacity: 0;
428
+ visibility: hidden;
429
+ transform: translateY(-10px);
430
+ transition: all 0.15s ease;
431
+ overflow-y: auto;
432
+ }
433
+
434
+ .appbar-apps-menu--open {
435
+ opacity: 1;
436
+ visibility: visible;
437
+ transform: translateY(0);
438
+ }
439
+
440
+ .appbar-apps-menu__header {
441
+ display: flex;
442
+ align-items: center;
443
+ justify-content: space-between;
444
+ padding: 16px 16px 16px 24px;
445
+ border-bottom: 1px solid var(--kr-shell-menu-border);
446
+ }
447
+
448
+ .appbar-apps-menu__title {
449
+ font-size: 16px;
450
+ font-weight: 500;
451
+ color: #ffffff;
452
+ margin: 0;
453
+ }
454
+
455
+ .appbar-apps-menu__close {
456
+ width: 32px;
457
+ height: 32px;
458
+ display: flex;
459
+ align-items: center;
460
+ justify-content: center;
461
+ background: none;
462
+ border: none;
463
+ color: rgba(255, 255, 255, 0.6);
464
+ cursor: pointer;
465
+ border-radius: 6px;
466
+ transition: all 0.15s ease;
467
+ }
468
+
469
+ .appbar-apps-menu__close:hover {
470
+ background: var(--kr-shell-menu-hover);
471
+ color: #ffffff;
472
+ }
473
+
474
+ .appbar-apps-menu__close svg {
475
+ width: 24px;
476
+ height: 24px;
477
+ fill: #ffffff;
478
+ }
479
+
480
+ .appbar-apps-menu__content {
481
+ padding: 16px 8px;
482
+ }
483
+
484
+ .appbar-apps-menu__list {
485
+ display: flex;
486
+ flex-direction: column;
487
+ gap: 2px;
488
+ max-width: 320px;
489
+ }
490
+
491
+ .appbar-apps-menu__item {
492
+ display: block;
493
+ width: 100%;
494
+ padding: 12px 16px;
495
+ background: none;
496
+ border: none;
497
+ color: #ffffff;
498
+ font-size: 14px;
499
+ font-family: inherit;
500
+ text-align: left;
501
+ text-decoration: none;
502
+ cursor: pointer;
503
+ border-radius: 6px;
504
+ transition: all 0.15s ease;
505
+ }
506
+
507
+ .appbar-apps-menu__item:hover {
508
+ background: var(--kr-shell-menu-hover);
509
+ }
510
+
511
+ .appbar-apps-menu__item--active,
512
+ .appbar-apps-menu__item--active:hover {
513
+ color: var(--kr-shell-icon-color-active);
514
+ }
515
+
516
+ /* Spacer to push user to the right */
517
+ .appbar-spacer {
518
+ flex: 1;
519
+ }
520
+
521
+ /* User Section */
522
+ .appbar-user {
523
+ position: relative;
524
+ margin-left: 8px;
525
+ }
526
+
527
+ .appbar-user__avatar {
528
+ width: 32px;
529
+ height: 32px;
530
+ border-radius: 50%;
531
+ background: #beea4e;
532
+ color: #0a0f1a;
533
+ display: flex;
534
+ align-items: center;
535
+ justify-content: center;
536
+ font-size: 12px;
537
+ font-weight: 600;
538
+ cursor: pointer;
539
+ overflow: hidden;
540
+ border: 2px solid transparent;
541
+ transition: border-color 0.15s ease;
542
+ }
543
+
544
+ .appbar-user__avatar:hover {
545
+ border-color: rgba(255, 255, 255, 0.3);
546
+ }
547
+
548
+ .appbar-user__avatar img {
549
+ width: 100%;
550
+ height: 100%;
551
+ object-fit: cover;
552
+ }
553
+
554
+ /* User Menu */
555
+ .appbar-user__menu {
556
+ position: absolute;
557
+ right: 0;
558
+ top: calc(100% + 8px);
559
+ min-width: 200px;
560
+ background: var(--kr-shell-menu-bg);
561
+ border: 1px solid var(--kr-shell-menu-border);
562
+ border-radius: 8px;
563
+ padding: 8px;
564
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
565
+ z-index: 1000;
566
+ opacity: 0;
567
+ visibility: hidden;
568
+ transform: translateY(-8px);
569
+ transition: all 0.15s ease;
570
+ }
571
+
572
+ .appbar-user__menu--open {
573
+ opacity: 1;
574
+ visibility: visible;
575
+ transform: translateY(0);
576
+ }
577
+
578
+ .appbar-user__header {
579
+ padding: 8px 12px 12px;
580
+ border-bottom: 1px solid var(--kr-shell-menu-border);
581
+ margin-bottom: 8px;
582
+ }
583
+
584
+ .appbar-user__name {
585
+ font-size: 14px;
586
+ font-weight: 600;
587
+ color: #ffffff;
588
+ margin: 0 0 2px;
589
+ }
590
+
591
+ .appbar-user__email {
592
+ font-size: 12px;
593
+ color: rgba(255, 255, 255, 0.6);
594
+ margin: 0;
595
+ }
596
+
597
+ .appbar-user__menu-item {
598
+ display: flex;
599
+ align-items: center;
600
+ gap: 10px;
601
+ width: 100%;
602
+ padding: 10px 12px;
603
+ background: none;
604
+ border: none;
605
+ color: rgba(255, 255, 255, 0.8);
606
+ font-size: 13px;
607
+ font-family: inherit;
608
+ text-align: left;
609
+ cursor: pointer;
610
+ border-radius: 6px;
611
+ transition: all 0.15s ease;
612
+ }
613
+
614
+ .appbar-user__menu-item:hover {
615
+ background: var(--kr-shell-menu-hover);
616
+ color: #ffffff;
617
+ }
618
+
619
+ .appbar-user__menu-item--danger {
620
+ color: #f87171;
621
+ }
622
+
623
+ .appbar-user__menu-item--danger:hover {
624
+ background: rgba(248, 113, 113, 0.1);
625
+ color: #f87171;
626
+ }
627
+
628
+ .appbar-user__menu-item__icon {
629
+ width: 16px;
630
+ height: 16px;
631
+ display: flex;
632
+ align-items: center;
633
+ justify-content: center;
634
+ flex-shrink: 0;
635
+ }
636
+
637
+ .appbar-user__menu-item__icon svg {
638
+ width: 100%;
639
+ height: 100%;
640
+ fill: currentColor;
641
+ }
642
+
643
+ .appbar-user__menu-divider {
644
+ height: 1px;
645
+ background: var(--kr-shell-menu-border);
646
+ margin: 8px 0;
647
+ }
648
+
649
+ /* Secondary App Bar */
650
+ .subbar {
651
+ height: 30px;
652
+ background: #364365;
653
+ border-bottom: 1px solid rgba(255, 255, 255, 0.08);
654
+ display: flex;
655
+ align-items: center;
656
+ padding: 0 16px;
657
+ flex-shrink: 0;
658
+ }
659
+
660
+ .breadcrumbs {
661
+ display: flex;
662
+ align-items: center;
663
+ gap: 8px;
664
+ font-size: 12px;
665
+ color: #ffffff;
666
+ }
667
+
668
+ .breadcrumbs a {
669
+ color: #ffffff;
670
+ text-decoration: none;
671
+ }
672
+
673
+ .breadcrumbs a:hover {
674
+ text-decoration: underline;
675
+ }
676
+
677
+ .breadcrumbs__separator {
678
+ color: #ffffff;
679
+ }
680
+
681
+ /* Main Content */
682
+ .main {
683
+ flex: 1;
684
+ min-height: 0;
685
+ display: flex;
686
+ flex-direction: column;
687
+ overflow: hidden;
688
+ position: relative;
689
+ }
690
+
691
+ /* Click outside overlay */
692
+ .menu-backdrop {
693
+ position: fixed;
694
+ inset: 0;
695
+ z-index: 999;
696
+ }
697
+
698
+ /* Progress bar */
699
+ .progress {
700
+ position: fixed;
701
+ top: 0;
702
+ left: 0;
703
+ right: 0;
704
+ height: 4px;
705
+ overflow-x: hidden;
706
+ z-index: 1000;
707
+ display: none;
708
+ }
709
+
710
+ .progress--loading {
711
+ display: block;
712
+ }
713
+
714
+ .progress__track {
715
+ position: absolute;
716
+ top: 0;
717
+ bottom: 0;
718
+ width: 100%;
719
+ background: rgb(190 234 78 / 50%); // rgba(190, 234, 78, 0.3);
720
+ }
721
+
722
+ .progress__bar {
723
+ position: absolute;
724
+ top: 0;
725
+ bottom: 0;
726
+ width: 100%;
727
+ transform-origin: left center;
728
+ }
729
+
730
+ .progress__bar-inner {
731
+ display: inline-block;
732
+ position: absolute;
733
+ width: 100%;
734
+ height: 100%;
735
+ background: #beea4e;
736
+ }
737
+
738
+ .progress__bar--primary {
739
+ left: -145.166611%;
740
+ }
741
+
742
+ .progress--loading .progress__bar--primary {
743
+ animation: progress-primary-translate 2s infinite linear;
744
+ }
745
+
746
+ .progress--loading .progress__bar--primary .progress__bar-inner {
747
+ animation: progress-primary-scale 2s infinite linear;
748
+ }
749
+
750
+ .progress__bar--secondary {
751
+ left: -54.888891%;
752
+ }
753
+
754
+ .progress--loading .progress__bar--secondary {
755
+ animation: progress-secondary-translate 2s infinite linear;
756
+ }
757
+
758
+ .progress--loading .progress__bar--secondary .progress__bar-inner {
759
+ animation: progress-secondary-scale 2s infinite linear;
760
+ }
761
+
762
+ @keyframes progress-primary-translate {
763
+ 0% {
764
+ transform: translateX(0);
765
+ }
766
+ 20% {
767
+ animation-timing-function: cubic-bezier(0.5, 0, 0.701732, 0.495819);
768
+ transform: translateX(0);
769
+ }
770
+ 59.15% {
771
+ animation-timing-function: cubic-bezier(0.302435, 0.381352, 0.55, 0.956352);
772
+ transform: translateX(83.67142%);
773
+ }
774
+ 100% {
775
+ transform: translateX(200.611057%);
776
+ }
777
+ }
778
+
779
+ @keyframes progress-primary-scale {
780
+ 0% {
781
+ transform: scaleX(0.08);
782
+ }
783
+ 36.65% {
784
+ animation-timing-function: cubic-bezier(0.334731, 0.12482, 0.785844, 1);
785
+ transform: scaleX(0.08);
786
+ }
787
+ 69.15% {
788
+ animation-timing-function: cubic-bezier(0.06, 0.11, 0.6, 1);
789
+ transform: scaleX(0.661479);
790
+ }
791
+ 100% {
792
+ transform: scaleX(0.08);
793
+ }
794
+ }
795
+
796
+ @keyframes progress-secondary-translate {
797
+ 0% {
798
+ animation-timing-function: cubic-bezier(0.15, 0, 0.515058, 0.409685);
799
+ transform: translateX(0);
800
+ }
801
+ 25% {
802
+ animation-timing-function: cubic-bezier(0.31033, 0.284058, 0.8, 0.733712);
803
+ transform: translateX(37.651913%);
804
+ }
805
+ 48.35% {
806
+ animation-timing-function: cubic-bezier(0.4, 0.627035, 0.6, 0.902026);
807
+ transform: translateX(84.386165%);
808
+ }
809
+ 100% {
810
+ transform: translateX(160.277782%);
811
+ }
812
+ }
813
+
814
+ @keyframes progress-secondary-scale {
815
+ 0% {
816
+ animation-timing-function: cubic-bezier(0.205028, 0.057051, 0.57661, 0.453971);
817
+ transform: scaleX(0.08);
818
+ }
819
+ 19.15% {
820
+ animation-timing-function: cubic-bezier(0.152313, 0.196432, 0.648374, 1.004315);
821
+ transform: scaleX(0.457104);
822
+ }
823
+ 44.15% {
824
+ animation-timing-function: cubic-bezier(0.257759, -0.003163, 0.211762, 1.38179);
825
+ transform: scaleX(0.72796);
826
+ }
827
+ 100% {
828
+ transform: scaleX(0.08);
829
+ }
830
+ }
831
+ `;
832
+ __decorate([
833
+ property({ type: String })
834
+ ], KRShell.prototype, "logo", void 0);
835
+ __decorate([
836
+ property({ type: Array })
837
+ ], KRShell.prototype, "apps", void 0);
838
+ __decorate([
839
+ property({ type: String, attribute: 'active-app-id' })
840
+ ], KRShell.prototype, "activeAppId", void 0);
841
+ __decorate([
842
+ property({ type: Object })
843
+ ], KRShell.prototype, "user", void 0);
844
+ __decorate([
845
+ property({ type: Array, attribute: 'menu-items' })
846
+ ], KRShell.prototype, "menuItems", void 0);
847
+ __decorate([
848
+ state()
849
+ ], KRShell.prototype, "isUserMenuOpen", void 0);
850
+ __decorate([
851
+ state()
852
+ ], KRShell.prototype, "isAppsMenuOpen", void 0);
853
+ __decorate([
854
+ state()
855
+ ], KRShell.prototype, "pendingRequests", void 0);
856
+ KRShell = __decorate([
857
+ customElement('kr-shell')
858
+ ], KRShell);
859
+ export { KRShell };
860
+ //# sourceMappingURL=shell.js.map