@mohamedatia/fly-design-system 1.3.8 → 1.4.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.
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, signal, computed, Injectable, inject, ErrorHandler, Pipe } from '@angular/core';
|
|
2
|
+
import { InjectionToken, signal, computed, Injectable, inject, ErrorHandler, Pipe, input, output, HostListener, ViewChild, ChangeDetectionStrategy, Component, ElementRef } from '@angular/core';
|
|
3
3
|
import { Router } from '@angular/router';
|
|
4
4
|
import { of } from 'rxjs';
|
|
5
5
|
|
|
@@ -345,12 +345,12 @@ class MockAuthService {
|
|
|
345
345
|
currentUser;
|
|
346
346
|
accessToken;
|
|
347
347
|
/** Always false in mock mode — 2FA is handled entirely by the STS. */
|
|
348
|
-
hasPendingTwoFactor
|
|
348
|
+
hasPendingTwoFactor;
|
|
349
349
|
/** Always false in mock mode — auth is pre-populated synchronously. */
|
|
350
|
-
initializing
|
|
350
|
+
initializing;
|
|
351
351
|
constructor() {
|
|
352
|
-
//
|
|
353
|
-
//
|
|
352
|
+
// All signal/computed calls are inside the constructor body so Angular's
|
|
353
|
+
// injection context and ngDevMode are fully set up before they execute.
|
|
354
354
|
this._config = this.getConfig();
|
|
355
355
|
this._session = signal({
|
|
356
356
|
accessToken: this._config.token ?? 'mock-token',
|
|
@@ -363,6 +363,8 @@ class MockAuthService {
|
|
|
363
363
|
}, ...(ngDevMode ? [{ debugName: "isAuthenticated" }] : /* istanbul ignore next */ []));
|
|
364
364
|
this.currentUser = computed(() => this._session()?.user ?? null, ...(ngDevMode ? [{ debugName: "currentUser" }] : /* istanbul ignore next */ []));
|
|
365
365
|
this.accessToken = computed(() => this._session()?.accessToken ?? null, ...(ngDevMode ? [{ debugName: "accessToken" }] : /* istanbul ignore next */ []));
|
|
366
|
+
this.hasPendingTwoFactor = computed(() => false, ...(ngDevMode ? [{ debugName: "hasPendingTwoFactor" }] : /* istanbul ignore next */ []));
|
|
367
|
+
this.initializing = signal(false).asReadonly();
|
|
366
368
|
}
|
|
367
369
|
/** Override in subclass to supply app-specific mock data. */
|
|
368
370
|
getConfig() {
|
|
@@ -413,6 +415,271 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
413
415
|
type: Injectable
|
|
414
416
|
}], ctorParameters: () => [] });
|
|
415
417
|
|
|
418
|
+
class ContextMenuComponent {
|
|
419
|
+
menuEl;
|
|
420
|
+
x = input.required(...(ngDevMode ? [{ debugName: "x" }] : /* istanbul ignore next */ []));
|
|
421
|
+
y = input.required(...(ngDevMode ? [{ debugName: "y" }] : /* istanbul ignore next */ []));
|
|
422
|
+
sections = input.required(...(ngDevMode ? [{ debugName: "sections" }] : /* istanbul ignore next */ []));
|
|
423
|
+
action = output();
|
|
424
|
+
closed = output();
|
|
425
|
+
menuWidth = signal(220, ...(ngDevMode ? [{ debugName: "menuWidth" }] : /* istanbul ignore next */ []));
|
|
426
|
+
menuHeight = signal(200, ...(ngDevMode ? [{ debugName: "menuHeight" }] : /* istanbul ignore next */ []));
|
|
427
|
+
previouslyFocused = null;
|
|
428
|
+
clampedPos = computed(() => {
|
|
429
|
+
const vw = window.innerWidth;
|
|
430
|
+
const vh = window.innerHeight;
|
|
431
|
+
return {
|
|
432
|
+
x: Math.min(this.x(), vw - this.menuWidth()),
|
|
433
|
+
y: Math.min(this.y(), vh - this.menuHeight()),
|
|
434
|
+
};
|
|
435
|
+
}, ...(ngDevMode ? [{ debugName: "clampedPos" }] : /* istanbul ignore next */ []));
|
|
436
|
+
ngAfterViewInit() {
|
|
437
|
+
const el = this.menuEl?.nativeElement;
|
|
438
|
+
if (el) {
|
|
439
|
+
this.menuWidth.set(el.offsetWidth);
|
|
440
|
+
this.menuHeight.set(el.offsetHeight);
|
|
441
|
+
}
|
|
442
|
+
// Store focus origin and move focus to first menu item
|
|
443
|
+
this.previouslyFocused = document.activeElement;
|
|
444
|
+
this.focusItem(0);
|
|
445
|
+
}
|
|
446
|
+
onAction(id) {
|
|
447
|
+
this.action.emit(id);
|
|
448
|
+
this.close();
|
|
449
|
+
}
|
|
450
|
+
onClickOutside(event) {
|
|
451
|
+
if (!this.menuEl?.nativeElement.contains(event.target)) {
|
|
452
|
+
this.close();
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
onEscape() {
|
|
456
|
+
this.close();
|
|
457
|
+
}
|
|
458
|
+
onContextMenu(event) {
|
|
459
|
+
if (!this.menuEl?.nativeElement.contains(event.target)) {
|
|
460
|
+
this.close();
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
onKeydown(event) {
|
|
464
|
+
const items = this.getMenuItems();
|
|
465
|
+
if (!items.length)
|
|
466
|
+
return;
|
|
467
|
+
const focused = document.activeElement;
|
|
468
|
+
const idx = items.indexOf(focused);
|
|
469
|
+
if (event.key === 'ArrowDown') {
|
|
470
|
+
event.preventDefault();
|
|
471
|
+
this.focusItem(idx < items.length - 1 ? idx + 1 : 0);
|
|
472
|
+
}
|
|
473
|
+
else if (event.key === 'ArrowUp') {
|
|
474
|
+
event.preventDefault();
|
|
475
|
+
this.focusItem(idx > 0 ? idx - 1 : items.length - 1);
|
|
476
|
+
}
|
|
477
|
+
else if (event.key === 'Home') {
|
|
478
|
+
event.preventDefault();
|
|
479
|
+
this.focusItem(0);
|
|
480
|
+
}
|
|
481
|
+
else if (event.key === 'End') {
|
|
482
|
+
event.preventDefault();
|
|
483
|
+
this.focusItem(items.length - 1);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
close() {
|
|
487
|
+
this.restoreFocus();
|
|
488
|
+
this.closed.emit();
|
|
489
|
+
}
|
|
490
|
+
getMenuItems() {
|
|
491
|
+
return Array.from(this.menuEl?.nativeElement.querySelectorAll('[role="menuitem"]') ?? []);
|
|
492
|
+
}
|
|
493
|
+
focusItem(index) {
|
|
494
|
+
const items = this.getMenuItems();
|
|
495
|
+
items[index]?.focus();
|
|
496
|
+
}
|
|
497
|
+
restoreFocus() {
|
|
498
|
+
if (this.previouslyFocused instanceof HTMLElement) {
|
|
499
|
+
this.previouslyFocused.focus();
|
|
500
|
+
}
|
|
501
|
+
this.previouslyFocused = null;
|
|
502
|
+
}
|
|
503
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ContextMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
504
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: ContextMenuComponent, isStandalone: true, selector: "fly-context-menu", inputs: { x: { classPropertyName: "x", publicName: "x", isSignal: true, isRequired: true, transformFunction: null }, y: { classPropertyName: "y", publicName: "y", isSignal: true, isRequired: true, transformFunction: null }, sections: { classPropertyName: "sections", publicName: "sections", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { action: "action", closed: "closed" }, host: { listeners: { "document:mousedown": "onClickOutside($event)", "document:keydown.escape": "onEscape()", "document:contextmenu": "onContextMenu($event)", "keydown": "onKeydown($event)" } }, viewQueries: [{ propertyName: "menuEl", first: true, predicate: ["contextMenu"], descendants: true }], ngImport: i0, template: "<div\n #contextMenu\n class=\"context-menu\"\n [style.left.px]=\"clampedPos().x\"\n [style.top.px]=\"clampedPos().y\"\n role=\"menu\"\n [attr.aria-label]=\"'shell.context_menu' | translate\">\n\n @for (section of sections(); track $index) {\n @if ($index > 0) {\n <div class=\"menu-divider\"></div>\n }\n @if (section.label) {\n <div class=\"menu-section-label\">{{ section.label }}</div>\n }\n @for (item of section.items; track item.id) {\n <button\n type=\"button\"\n class=\"vos-btn sm rect menu-item\"\n role=\"menuitem\"\n (click)=\"onAction(item.id)\">\n <i [class]=\"'pi ' + item.icon\" aria-hidden=\"true\"></i>\n <span>{{ item.label }}</span>\n </button>\n }\n }\n</div>\n", styles: [":host{position:fixed;inset:0;z-index:9500}.context-menu{position:fixed;min-width:200px;padding:6px;border-radius:14px;background:var(--glass-bg, rgba(30, 30, 34, .72));backdrop-filter:blur(40px) saturate(180%);-webkit-backdrop-filter:blur(40px) saturate(180%);border:1px solid var(--glass-border, rgba(255, 255, 255, .15));box-shadow:0 12px 40px #00000059,0 2px 8px #0003,inset 0 .5px #ffffff1a;animation:menuEnter .18s cubic-bezier(.22,1,.36,1) both;transform-origin:top left}@keyframes menuEnter{0%{opacity:0;transform:scale(.92)}to{opacity:1;transform:scale(1)}}.menu-section-label{padding:6px 12px 4px;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.6px;color:var(--text-color-secondary, rgba(255, 255, 255, .45));pointer-events:none}.menu-item{gap:10px;width:100%;padding:8px 12px;color:var(--text-color, #fff);font-size:var(--link-font-size, 13px);font-weight:var(--btn-symbol-font-weight, 510);justify-content:flex-start}.menu-item i{font-size:14px;width:18px;text-align:center;opacity:.7}.menu-item:hover{background:var(--primary-color, #E8732A);color:#fff}.menu-item:hover i{opacity:1}.menu-item:focus-visible{background:var(--primary-color, #E8732A);outline:2px solid var(--focus-ring);outline-offset:-2px}.menu-divider{height:1px;margin:4px 8px;background:var(--glass-border, rgba(255, 255, 255, .12))}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
505
|
+
}
|
|
506
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ContextMenuComponent, decorators: [{
|
|
507
|
+
type: Component,
|
|
508
|
+
args: [{ selector: 'fly-context-menu', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n #contextMenu\n class=\"context-menu\"\n [style.left.px]=\"clampedPos().x\"\n [style.top.px]=\"clampedPos().y\"\n role=\"menu\"\n [attr.aria-label]=\"'shell.context_menu' | translate\">\n\n @for (section of sections(); track $index) {\n @if ($index > 0) {\n <div class=\"menu-divider\"></div>\n }\n @if (section.label) {\n <div class=\"menu-section-label\">{{ section.label }}</div>\n }\n @for (item of section.items; track item.id) {\n <button\n type=\"button\"\n class=\"vos-btn sm rect menu-item\"\n role=\"menuitem\"\n (click)=\"onAction(item.id)\">\n <i [class]=\"'pi ' + item.icon\" aria-hidden=\"true\"></i>\n <span>{{ item.label }}</span>\n </button>\n }\n }\n</div>\n", styles: [":host{position:fixed;inset:0;z-index:9500}.context-menu{position:fixed;min-width:200px;padding:6px;border-radius:14px;background:var(--glass-bg, rgba(30, 30, 34, .72));backdrop-filter:blur(40px) saturate(180%);-webkit-backdrop-filter:blur(40px) saturate(180%);border:1px solid var(--glass-border, rgba(255, 255, 255, .15));box-shadow:0 12px 40px #00000059,0 2px 8px #0003,inset 0 .5px #ffffff1a;animation:menuEnter .18s cubic-bezier(.22,1,.36,1) both;transform-origin:top left}@keyframes menuEnter{0%{opacity:0;transform:scale(.92)}to{opacity:1;transform:scale(1)}}.menu-section-label{padding:6px 12px 4px;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.6px;color:var(--text-color-secondary, rgba(255, 255, 255, .45));pointer-events:none}.menu-item{gap:10px;width:100%;padding:8px 12px;color:var(--text-color, #fff);font-size:var(--link-font-size, 13px);font-weight:var(--btn-symbol-font-weight, 510);justify-content:flex-start}.menu-item i{font-size:14px;width:18px;text-align:center;opacity:.7}.menu-item:hover{background:var(--primary-color, #E8732A);color:#fff}.menu-item:hover i{opacity:1}.menu-item:focus-visible{background:var(--primary-color, #E8732A);outline:2px solid var(--focus-ring);outline-offset:-2px}.menu-divider{height:1px;margin:4px 8px;background:var(--glass-border, rgba(255, 255, 255, .12))}\n"] }]
|
|
509
|
+
}], propDecorators: { menuEl: [{
|
|
510
|
+
type: ViewChild,
|
|
511
|
+
args: ['contextMenu']
|
|
512
|
+
}], x: [{ type: i0.Input, args: [{ isSignal: true, alias: "x", required: true }] }], y: [{ type: i0.Input, args: [{ isSignal: true, alias: "y", required: true }] }], sections: [{ type: i0.Input, args: [{ isSignal: true, alias: "sections", required: true }] }], action: [{ type: i0.Output, args: ["action"] }], closed: [{ type: i0.Output, args: ["closed"] }], onClickOutside: [{
|
|
513
|
+
type: HostListener,
|
|
514
|
+
args: ['document:mousedown', ['$event']]
|
|
515
|
+
}], onEscape: [{
|
|
516
|
+
type: HostListener,
|
|
517
|
+
args: ['document:keydown.escape']
|
|
518
|
+
}], onContextMenu: [{
|
|
519
|
+
type: HostListener,
|
|
520
|
+
args: ['document:contextmenu', ['$event']]
|
|
521
|
+
}], onKeydown: [{
|
|
522
|
+
type: HostListener,
|
|
523
|
+
args: ['keydown', ['$event']]
|
|
524
|
+
}] } });
|
|
525
|
+
|
|
526
|
+
var MessageBoxButtons;
|
|
527
|
+
(function (MessageBoxButtons) {
|
|
528
|
+
MessageBoxButtons[MessageBoxButtons["OK"] = 0] = "OK";
|
|
529
|
+
MessageBoxButtons[MessageBoxButtons["OKCancel"] = 1] = "OKCancel";
|
|
530
|
+
MessageBoxButtons[MessageBoxButtons["YesNo"] = 2] = "YesNo";
|
|
531
|
+
MessageBoxButtons[MessageBoxButtons["YesNoCancel"] = 3] = "YesNoCancel";
|
|
532
|
+
MessageBoxButtons[MessageBoxButtons["RetryCancel"] = 4] = "RetryCancel";
|
|
533
|
+
MessageBoxButtons[MessageBoxButtons["AbortRetryIgnore"] = 5] = "AbortRetryIgnore";
|
|
534
|
+
})(MessageBoxButtons || (MessageBoxButtons = {}));
|
|
535
|
+
var MessageBoxIcon;
|
|
536
|
+
(function (MessageBoxIcon) {
|
|
537
|
+
MessageBoxIcon[MessageBoxIcon["None"] = 0] = "None";
|
|
538
|
+
MessageBoxIcon[MessageBoxIcon["Information"] = 1] = "Information";
|
|
539
|
+
MessageBoxIcon[MessageBoxIcon["Warning"] = 2] = "Warning";
|
|
540
|
+
MessageBoxIcon[MessageBoxIcon["Error"] = 3] = "Error";
|
|
541
|
+
MessageBoxIcon[MessageBoxIcon["Question"] = 4] = "Question";
|
|
542
|
+
})(MessageBoxIcon || (MessageBoxIcon = {}));
|
|
543
|
+
var DialogResult;
|
|
544
|
+
(function (DialogResult) {
|
|
545
|
+
DialogResult[DialogResult["None"] = 0] = "None";
|
|
546
|
+
DialogResult[DialogResult["OK"] = 1] = "OK";
|
|
547
|
+
DialogResult[DialogResult["Cancel"] = 2] = "Cancel";
|
|
548
|
+
DialogResult[DialogResult["Yes"] = 3] = "Yes";
|
|
549
|
+
DialogResult[DialogResult["No"] = 4] = "No";
|
|
550
|
+
DialogResult[DialogResult["Retry"] = 5] = "Retry";
|
|
551
|
+
DialogResult[DialogResult["Abort"] = 6] = "Abort";
|
|
552
|
+
DialogResult[DialogResult["Ignore"] = 7] = "Ignore";
|
|
553
|
+
})(DialogResult || (DialogResult = {}));
|
|
554
|
+
class MessageBoxService {
|
|
555
|
+
i18n = inject(I18nService);
|
|
556
|
+
visible = signal(false, ...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
557
|
+
title = signal('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
558
|
+
message = signal('', ...(ngDevMode ? [{ debugName: "message" }] : /* istanbul ignore next */ []));
|
|
559
|
+
icon = signal(MessageBoxIcon.None, ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
|
|
560
|
+
buttons = signal([], ...(ngDevMode ? [{ debugName: "buttons" }] : /* istanbul ignore next */ []));
|
|
561
|
+
resolver = null;
|
|
562
|
+
show(options) {
|
|
563
|
+
// Dismiss any pending dialog so its Promise resolves rather than leaking
|
|
564
|
+
if (this.resolver) {
|
|
565
|
+
this.resolver(DialogResult.None);
|
|
566
|
+
this.resolver = null;
|
|
567
|
+
}
|
|
568
|
+
this.title.set(options.title);
|
|
569
|
+
this.message.set(options.message);
|
|
570
|
+
this.icon.set(options.icon ?? MessageBoxIcon.None);
|
|
571
|
+
this.buttons.set(this.resolveButtons(options.buttons ?? MessageBoxButtons.OK));
|
|
572
|
+
this.visible.set(true);
|
|
573
|
+
return new Promise((resolve) => {
|
|
574
|
+
this.resolver = resolve;
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
resolve(result) {
|
|
578
|
+
this.visible.set(false);
|
|
579
|
+
if (this.resolver) {
|
|
580
|
+
this.resolver(result);
|
|
581
|
+
this.resolver = null;
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
resolveButtons(buttons) {
|
|
585
|
+
const t = (key) => this.i18n.t(key);
|
|
586
|
+
switch (buttons) {
|
|
587
|
+
case MessageBoxButtons.OK:
|
|
588
|
+
return [{ label: t('common.ok'), result: DialogResult.OK, variant: 'primary' }];
|
|
589
|
+
case MessageBoxButtons.OKCancel:
|
|
590
|
+
return [
|
|
591
|
+
{ label: t('common.cancel'), result: DialogResult.Cancel, variant: 'default' },
|
|
592
|
+
{ label: t('common.ok'), result: DialogResult.OK, variant: 'primary' },
|
|
593
|
+
];
|
|
594
|
+
case MessageBoxButtons.YesNo:
|
|
595
|
+
return [
|
|
596
|
+
{ label: t('common.no'), result: DialogResult.No, variant: 'default' },
|
|
597
|
+
{ label: t('common.yes'), result: DialogResult.Yes, variant: 'primary' },
|
|
598
|
+
];
|
|
599
|
+
case MessageBoxButtons.YesNoCancel:
|
|
600
|
+
return [
|
|
601
|
+
{ label: t('common.cancel'), result: DialogResult.Cancel, variant: 'default' },
|
|
602
|
+
{ label: t('common.no'), result: DialogResult.No, variant: 'default' },
|
|
603
|
+
{ label: t('common.yes'), result: DialogResult.Yes, variant: 'primary' },
|
|
604
|
+
];
|
|
605
|
+
case MessageBoxButtons.RetryCancel:
|
|
606
|
+
return [
|
|
607
|
+
{ label: t('common.cancel'), result: DialogResult.Cancel, variant: 'default' },
|
|
608
|
+
{ label: t('common.retry'), result: DialogResult.Retry, variant: 'primary' },
|
|
609
|
+
];
|
|
610
|
+
case MessageBoxButtons.AbortRetryIgnore:
|
|
611
|
+
return [
|
|
612
|
+
{ label: t('common.abort'), result: DialogResult.Abort, variant: 'danger' },
|
|
613
|
+
{ label: t('common.retry'), result: DialogResult.Retry, variant: 'default' },
|
|
614
|
+
{ label: t('common.ignore'), result: DialogResult.Ignore, variant: 'default' },
|
|
615
|
+
];
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageBoxService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
619
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageBoxService, providedIn: 'root' });
|
|
620
|
+
}
|
|
621
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageBoxService, decorators: [{
|
|
622
|
+
type: Injectable,
|
|
623
|
+
args: [{ providedIn: 'root' }]
|
|
624
|
+
}] });
|
|
625
|
+
|
|
626
|
+
class MessageBoxComponent {
|
|
627
|
+
service = inject(MessageBoxService);
|
|
628
|
+
elRef = inject(ElementRef);
|
|
629
|
+
MessageBoxIcon = MessageBoxIcon;
|
|
630
|
+
DialogResult = DialogResult;
|
|
631
|
+
previouslyFocused = null;
|
|
632
|
+
ngAfterViewInit() {
|
|
633
|
+
// Store focus origin so we can restore it on close
|
|
634
|
+
this.previouslyFocused = document.activeElement;
|
|
635
|
+
this.focusPrimaryButton();
|
|
636
|
+
}
|
|
637
|
+
onEscape() {
|
|
638
|
+
if (this.service.visible()) {
|
|
639
|
+
this.service.resolve(DialogResult.Cancel);
|
|
640
|
+
this.restoreFocus();
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
onBackdropClick() {
|
|
644
|
+
this.service.resolve(DialogResult.Cancel);
|
|
645
|
+
this.restoreFocus();
|
|
646
|
+
}
|
|
647
|
+
onButtonClick(result) {
|
|
648
|
+
this.service.resolve(result);
|
|
649
|
+
this.restoreFocus();
|
|
650
|
+
}
|
|
651
|
+
iconClass() {
|
|
652
|
+
switch (this.service.icon()) {
|
|
653
|
+
case MessageBoxIcon.Information: return 'pi pi-info-circle';
|
|
654
|
+
case MessageBoxIcon.Warning: return 'pi pi-exclamation-triangle';
|
|
655
|
+
case MessageBoxIcon.Error: return 'pi pi-times-circle';
|
|
656
|
+
case MessageBoxIcon.Question: return 'pi pi-question-circle';
|
|
657
|
+
default: return '';
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
focusPrimaryButton() {
|
|
661
|
+
// Focus the primary (last) button, which is the default action
|
|
662
|
+
const buttons = this.elRef.nativeElement.querySelectorAll('.mb-btn');
|
|
663
|
+
const last = buttons[buttons.length - 1];
|
|
664
|
+
last?.focus();
|
|
665
|
+
}
|
|
666
|
+
restoreFocus() {
|
|
667
|
+
if (this.previouslyFocused instanceof HTMLElement) {
|
|
668
|
+
this.previouslyFocused.focus();
|
|
669
|
+
}
|
|
670
|
+
this.previouslyFocused = null;
|
|
671
|
+
}
|
|
672
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageBoxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
673
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: MessageBoxComponent, isStandalone: true, selector: "fly-message-box", host: { listeners: { "document:keydown.escape": "onEscape()" } }, ngImport: i0, template: "@if (service.visible()) {\n <div\n class=\"mb-backdrop\"\n (click)=\"onBackdropClick()\"\n role=\"presentation\">\n <div\n class=\"mb-dialog\"\n [class.mb-info]=\"service.icon() === MessageBoxIcon.Information\"\n [class.mb-warning]=\"service.icon() === MessageBoxIcon.Warning\"\n [class.mb-danger]=\"service.icon() === MessageBoxIcon.Error\"\n [class.mb-question]=\"service.icon() === MessageBoxIcon.Question\"\n (click)=\"$event.stopPropagation()\"\n role=\"alertdialog\"\n aria-modal=\"true\"\n aria-labelledby=\"mb-title\"\n aria-describedby=\"mb-message\">\n\n @if (iconClass()) {\n <div class=\"mb-icon-wrap\">\n <i [class]=\"iconClass() + ' mb-icon'\" aria-hidden=\"true\"></i>\n </div>\n }\n\n <div class=\"mb-title\" id=\"mb-title\">{{ service.title() }}</div>\n <div class=\"mb-message\" id=\"mb-message\">{{ service.message() }}</div>\n\n <div class=\"mb-actions\">\n @for (btn of service.buttons(); track btn.result) {\n <button\n type=\"button\"\n class=\"vos-btn sm mb-btn\"\n [class.mb-btn--primary]=\"btn.variant === 'primary'\"\n [class.mb-btn--danger]=\"btn.variant === 'danger'\"\n (click)=\"onButtonClick(btn.result)\">\n {{ btn.label }}\n </button>\n }\n </div>\n\n </div>\n </div>\n}\n", styles: [".mb-backdrop{position:absolute;inset:0;z-index:5100;background:#00000073;display:flex;align-items:center;justify-content:center;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);animation:mbFadeIn .15s ease both}@keyframes mbFadeIn{0%{opacity:0}to{opacity:1}}.mb-dialog{background:var(--surface-card, rgba(30, 30, 30, .98));border:1px solid var(--surface-border);border-radius:16px;padding:28px 28px 20px;width:400px;max-width:90%;display:flex;flex-direction:column;align-items:center;text-align:center;gap:6px;box-shadow:0 20px 60px #0006;animation:mbScaleIn .2s cubic-bezier(.22,1,.36,1) both}@keyframes mbScaleIn{0%{opacity:0;transform:scale(.92)}to{opacity:1;transform:scale(1)}}.mb-icon-wrap{width:52px;height:52px;border-radius:50%;display:flex;align-items:center;justify-content:center;margin-bottom:6px}.mb-icon{font-size:24px}.mb-info .mb-icon-wrap{background:#3b82f61f}.mb-info .mb-icon{color:#3b82f6}.mb-warning .mb-icon-wrap{background:#f59e0b1f}.mb-warning .mb-icon{color:#f59e0b}.mb-danger .mb-icon-wrap{background:#ef44441f}.mb-danger .mb-icon{color:#ef4444}.mb-question .mb-icon-wrap{background:#8b5cf61f}.mb-question .mb-icon{color:#8b5cf6}.mb-title{font-size:15px;font-weight:700;color:var(--text-color)}.mb-message{font-size:13px;color:var(--text-color-secondary);line-height:1.55;max-width:340px;white-space:pre-line}.mb-actions{display:flex;gap:10px;margin-top:16px;width:100%;justify-content:center;flex-wrap:wrap}.mb-btn{min-width:90px}.mb-btn--primary{background:var(--primary-color, #E8732A);color:#fff}.mb-btn--primary:hover{filter:brightness(1.1)}.mb-btn--danger{background:#ef4444;color:#fff}.mb-btn--danger:hover{background:#dc2626}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
674
|
+
}
|
|
675
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageBoxComponent, decorators: [{
|
|
676
|
+
type: Component,
|
|
677
|
+
args: [{ selector: 'fly-message-box', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (service.visible()) {\n <div\n class=\"mb-backdrop\"\n (click)=\"onBackdropClick()\"\n role=\"presentation\">\n <div\n class=\"mb-dialog\"\n [class.mb-info]=\"service.icon() === MessageBoxIcon.Information\"\n [class.mb-warning]=\"service.icon() === MessageBoxIcon.Warning\"\n [class.mb-danger]=\"service.icon() === MessageBoxIcon.Error\"\n [class.mb-question]=\"service.icon() === MessageBoxIcon.Question\"\n (click)=\"$event.stopPropagation()\"\n role=\"alertdialog\"\n aria-modal=\"true\"\n aria-labelledby=\"mb-title\"\n aria-describedby=\"mb-message\">\n\n @if (iconClass()) {\n <div class=\"mb-icon-wrap\">\n <i [class]=\"iconClass() + ' mb-icon'\" aria-hidden=\"true\"></i>\n </div>\n }\n\n <div class=\"mb-title\" id=\"mb-title\">{{ service.title() }}</div>\n <div class=\"mb-message\" id=\"mb-message\">{{ service.message() }}</div>\n\n <div class=\"mb-actions\">\n @for (btn of service.buttons(); track btn.result) {\n <button\n type=\"button\"\n class=\"vos-btn sm mb-btn\"\n [class.mb-btn--primary]=\"btn.variant === 'primary'\"\n [class.mb-btn--danger]=\"btn.variant === 'danger'\"\n (click)=\"onButtonClick(btn.result)\">\n {{ btn.label }}\n </button>\n }\n </div>\n\n </div>\n </div>\n}\n", styles: [".mb-backdrop{position:absolute;inset:0;z-index:5100;background:#00000073;display:flex;align-items:center;justify-content:center;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);animation:mbFadeIn .15s ease both}@keyframes mbFadeIn{0%{opacity:0}to{opacity:1}}.mb-dialog{background:var(--surface-card, rgba(30, 30, 30, .98));border:1px solid var(--surface-border);border-radius:16px;padding:28px 28px 20px;width:400px;max-width:90%;display:flex;flex-direction:column;align-items:center;text-align:center;gap:6px;box-shadow:0 20px 60px #0006;animation:mbScaleIn .2s cubic-bezier(.22,1,.36,1) both}@keyframes mbScaleIn{0%{opacity:0;transform:scale(.92)}to{opacity:1;transform:scale(1)}}.mb-icon-wrap{width:52px;height:52px;border-radius:50%;display:flex;align-items:center;justify-content:center;margin-bottom:6px}.mb-icon{font-size:24px}.mb-info .mb-icon-wrap{background:#3b82f61f}.mb-info .mb-icon{color:#3b82f6}.mb-warning .mb-icon-wrap{background:#f59e0b1f}.mb-warning .mb-icon{color:#f59e0b}.mb-danger .mb-icon-wrap{background:#ef44441f}.mb-danger .mb-icon{color:#ef4444}.mb-question .mb-icon-wrap{background:#8b5cf61f}.mb-question .mb-icon{color:#8b5cf6}.mb-title{font-size:15px;font-weight:700;color:var(--text-color)}.mb-message{font-size:13px;color:var(--text-color-secondary);line-height:1.55;max-width:340px;white-space:pre-line}.mb-actions{display:flex;gap:10px;margin-top:16px;width:100%;justify-content:center;flex-wrap:wrap}.mb-btn{min-width:90px}.mb-btn--primary{background:var(--primary-color, #E8732A);color:#fff}.mb-btn--primary:hover{filter:brightness(1.1)}.mb-btn--danger{background:#ef4444;color:#fff}.mb-btn--danger:hover{background:#dc2626}\n"] }]
|
|
678
|
+
}], propDecorators: { onEscape: [{
|
|
679
|
+
type: HostListener,
|
|
680
|
+
args: ['document:keydown.escape']
|
|
681
|
+
}] } });
|
|
682
|
+
|
|
416
683
|
/*
|
|
417
684
|
* @mohamedatia/fly-design-system — Public API
|
|
418
685
|
* https://www.npmjs.com/package/@mohamedatia/fly-design-system
|
|
@@ -430,6 +697,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
430
697
|
* User model extended with optional avatar, source, twoFactorEnabled, createdAt fields.
|
|
431
698
|
* v1.3.8: AuthService.init() no-op added so Business Apps can call init() in APP_INITIALIZER
|
|
432
699
|
* without branching between standalone and embedded modes.
|
|
700
|
+
* v1.3.9: MockAuthService field initializers moved into constructor to fix ngDevMode ReferenceError
|
|
701
|
+
* when the package is loaded in a production-mode bundle (no ngDevMode global defined).
|
|
702
|
+
* v1.4.0: ContextMenuComponent (positioned menu, keyboard nav, focus management) moved from desktop
|
|
703
|
+
* shell to design system. MessageBoxService + MessageBoxComponent added (Windows Forms-style
|
|
704
|
+
* modal dialogs with localized button labels, focus management, and Escape key support).
|
|
705
|
+
* MessageBoxButtons, MessageBoxIcon, DialogResult, MessageBoxOptions, MessageBoxButton exported.
|
|
433
706
|
* See BusinessAppsGuide/03-frontend-app.md.
|
|
434
707
|
*/
|
|
435
708
|
|
|
@@ -437,5 +710,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
437
710
|
* Generated bundle index. Do not edit.
|
|
438
711
|
*/
|
|
439
712
|
|
|
440
|
-
export { AuthService, FlyThemeService, I18nService, MockAuthService, RTL_LOCALE_SET, StandaloneWindowManagerService, TranslatePipe, WINDOW_DATA, WindowManagerService, isRtlLocale };
|
|
713
|
+
export { AuthService, ContextMenuComponent, DialogResult, FlyThemeService, I18nService, MessageBoxButtons, MessageBoxComponent, MessageBoxIcon, MessageBoxService, MockAuthService, RTL_LOCALE_SET, StandaloneWindowManagerService, TranslatePipe, WINDOW_DATA, WindowManagerService, isRtlLocale };
|
|
441
714
|
//# sourceMappingURL=mohamedatia-fly-design-system.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mohamedatia-fly-design-system.mjs","sources":["../../../projects/design-system/src/lib/models/window.model.ts","../../../projects/design-system/src/lib/services/auth.service.ts","../../../projects/design-system/src/lib/services/i18n.service.ts","../../../projects/design-system/src/lib/services/fly-theme.service.ts","../../../projects/design-system/src/lib/services/window-manager.service.ts","../../../projects/design-system/src/lib/pipes/translate.pipe.ts","../../../projects/design-system/src/lib/services/auth.service.mock.ts","../../../projects/design-system/src/public-api.ts","../../../projects/design-system/src/mohamedatia-fly-design-system.ts"],"sourcesContent":["import { InjectionToken, Type } from '@angular/core';\r\n\r\nexport type WindowState = 'normal' | 'minimized' | 'maximized';\r\n\r\nexport interface ChildWindowData {\r\n childComponent: Type<unknown>;\r\n [key: string]: unknown;\r\n}\r\n\r\nexport interface WindowInstance {\r\n id: string;\r\n appId: string;\r\n title: string;\r\n icon: string;\r\n iconBg: string;\r\n state: WindowState;\r\n position: { x: number; y: number };\r\n size: { width: number; height: number };\r\n zIndex: number;\r\n isFocused: boolean;\r\n isClosing?: boolean;\r\n isMinimizing?: boolean;\r\n isRestoring?: boolean;\r\n isMaximizing?: boolean;\r\n isUnmaximizing?: boolean;\r\n parentWindowId?: string;\r\n childData?: ChildWindowData;\r\n /** Populated when remote `loadComponent()` fails (e.g. federation). */\r\n remoteLoadError?: string;\r\n}\r\n\r\nexport const WINDOW_DATA = new InjectionToken<WindowInstance>('WINDOW_DATA');\r\n","import { Injectable, computed, signal } from '@angular/core';\nimport { User } from '../models/user.model';\n\ninterface AuthSession {\n user: User;\n accessToken: string;\n expiresAt: number;\n}\n\n/**\n * Shared AuthService for Business Apps.\n *\n * This is a **read-only signal store** — Business Apps inject it to read the\n * current user and access token. The FlyOS shell populates it after PKCE login\n * and silent refresh. Business Apps must never call setSession() directly.\n *\n * When running as a Module Federation remote, the shell and the Business App\n * share this singleton via the `@mohamedatia/fly-design-system` shared mapping\n * in federation.config.js — so the shell's populated instance is the same\n * object the Business App reads.\n *\n * When running standalone (without the shell), call initFromToken() with a\n * JWT stored in localStorage to hydrate the user.\n */\n@Injectable({ providedIn: 'root' })\nexport class AuthService {\n private _session = signal<AuthSession | null>(null);\n\n readonly currentUser = computed(() => this._session()?.user ?? null);\n readonly accessToken = computed(() => this._session()?.accessToken ?? null);\n readonly isAuthenticated = computed(() => {\n const s = this._session();\n return s !== null && s.expiresAt > Date.now();\n });\n\n /**\n * No-op when running as a Module Federation remote — the shell has already\n * initialised the session before the remote bootstraps. Business Apps call\n * this in their APP_INITIALIZER so the same code works in both standalone\n * and embedded modes without branching.\n */\n async init(): Promise<void> {}\n\n /**\n * Called by the shell after a successful login or silent refresh.\n * Business Apps should not call this directly.\n */\n setSession(user: User, accessToken: string, expiresAt: number): void {\n this._session.set({ user, accessToken, expiresAt });\n }\n\n /** Clears the in-memory session (called by the shell on logout). */\n clearSession(): void {\n this._session.set(null);\n }\n\n /**\n * Standalone mode: parse a JWT from localStorage and hydrate the user.\n * Pass the storage key your app uses; embedded remotes typically set this in `APP_INITIALIZER`.\n */\n initFromToken(storageKey = 'circles_token'): void {\n const token = localStorage.getItem(storageKey);\n if (!token) return;\n try {\n const base64 = token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/');\n const payload = JSON.parse(decodeURIComponent(\n atob(base64).split('').map(c => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)).join('')\n )) as Record<string, unknown>;\n\n const rawRole = payload['role'];\n const roles = Array.isArray(rawRole) ? rawRole as string[] : rawRole ? [rawRole as string] : [];\n const rawApps = payload['apps'];\n const apps = Array.isArray(rawApps) ? rawApps as string[] : rawApps ? [rawApps as string] : [];\n const name = (payload['name'] as string) ?? '';\n const nameParts = name.split(' ');\n\n const user: User = {\n id: (payload['sub'] as string) ?? '',\n tenantId: (payload['tenant_id'] as string) ?? (payload['tid'] as string) ?? null,\n email: (payload['email'] as string) ?? '',\n fullName: name,\n firstName: nameParts[0] ?? '',\n lastName: nameParts.slice(1).join(' '),\n preferredLocale: (payload['locale'] as string) ?? 'en',\n roles,\n apps,\n ou: payload['ou'] as string | undefined,\n };\n\n const expiresAt = ((payload['exp'] as number) ?? 0) * 1000;\n this.setSession(user, token, expiresAt);\n } catch {\n // Invalid token — stay unauthenticated\n }\n }\n}\n","import { Injectable, computed, signal, inject, ErrorHandler } from '@angular/core';\n\n/** Locales that use RTL layout for `dir` and DS `isRtl` / `direction`. */\nexport const RTL_LOCALE_SET: ReadonlySet<string> = new Set(['ar', 'ur']);\n\nexport function isRtlLocale(lang: string): boolean {\n return RTL_LOCALE_SET.has(lang);\n}\n\nfunction escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/** Accepts flat or nested JSON objects; nested keys become dot paths. Rejects arrays and non-string leaves. */\nfunction normalizeLocaleJson(raw: unknown): Record<string, string> {\n if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {\n throw new Error('Locale bundle must be a JSON object');\n }\n const out: Record<string, string> = {};\n const walk = (obj: Record<string, unknown>, prefix: string): void => {\n for (const [k, v] of Object.entries(obj)) {\n const path = prefix ? `${prefix}.${k}` : k;\n if (typeof v === 'string') {\n out[path] = v;\n } else if (v !== null && typeof v === 'object' && !Array.isArray(v)) {\n walk(v as Record<string, unknown>, path);\n } else {\n throw new Error(`Locale bundle invalid value at \"${path}\" (expected string or nested object)`);\n }\n }\n };\n walk(raw as Record<string, unknown>, '');\n return out;\n}\n\n/** Options for loading a remote or standalone locale JSON bundle. */\nexport interface LoadBundleOptions {\n /** Stable id (e.g. app id from manifest); later loads replace this bundle only. */\n id: string;\n /** Base URL ending with `/`, e.g. `https://app.example.com/locale/` or `/my-remote/locale/` */\n baseUrl: string;\n lang: string;\n /** When aborted, failures are ignored (e.g. superseded language load). */\n signal?: AbortSignal;\n /**\n * When true, fetch/parse failures are not reported via Angular `ErrorHandler`.\n * Use for optional remote locale bundles (e.g. federated apps that may be offline).\n */\n silent?: boolean;\n}\n\n/**\n * Shared I18nService for the shell and Business Apps.\n *\n * **Merge order** (later keys win): shell layer → remote bundles in registration order.\n *\n * - Shell: `setShellTranslations()` after loading `locale/{lang}.json` and API overrides.\n * - Remotes: `loadBundle()` per manifest `localeBaseUrl`.\n */\n@Injectable({ providedIn: 'root' })\nexport class I18nService {\n private readonly errorHandler = inject(ErrorHandler, { optional: true });\n\n private readonly _shell = signal<Record<string, string>>({});\n private readonly _bundles = signal<Record<string, Record<string, string>>>({});\n private readonly _bundleOrder = signal<string[]>([]);\n private readonly _locale = signal<string>('en');\n private readonly _version = signal(0);\n\n private readonly _merged = computed(() => {\n const shell = this._shell();\n const order = this._bundleOrder();\n const bundles = this._bundles();\n let out: Record<string, string> = { ...shell };\n for (const id of order) {\n const b = bundles[id];\n if (b) out = { ...out, ...b };\n }\n return out;\n });\n\n readonly locale = this._locale.asReadonly();\n readonly version = this._version.asReadonly();\n readonly isRtl = computed(() => isRtlLocale(this._locale()));\n readonly direction = computed(() => (isRtlLocale(this._locale()) ? 'rtl' : 'ltr'));\n\n private bump(): void {\n this._version.update((v) => v + 1);\n }\n\n /** Replace shell strings (desktop `locale/*.json` + `/api/i18n/desktop-shell/{lang}` merged by the shell). */\n setShellTranslations(data: Record<string, string>, lang: string): void {\n this._shell.set(data);\n this._locale.set(lang);\n this.bump();\n }\n\n setLanguage(lang: string): void {\n this._locale.set(lang);\n this.bump();\n }\n\n /**\n * Fetch `{baseUrl}{lang}.json` and store under `id`. New ids are appended to the merge order.\n * @returns whether the bundle was loaded successfully.\n */\n async loadBundle(opts: LoadBundleOptions): Promise<boolean> {\n const { id, baseUrl, lang, signal: abortSignal, silent } = opts;\n try {\n const base = baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`;\n const url = `${base}${lang}.json`;\n const resp = await fetch(url, { signal: abortSignal });\n if (!resp.ok) throw new Error(`HTTP ${resp.status}`);\n const data = normalizeLocaleJson(await resp.json());\n if (abortSignal?.aborted) return false;\n this._bundles.update((b) => ({ ...b, [id]: data }));\n this._bundleOrder.update((order) => (order.includes(id) ? order : [...order, id]));\n this._locale.set(lang);\n this.bump();\n return true;\n } catch (e) {\n if (abortSignal?.aborted) return false;\n if (!silent) this.errorHandler?.handleError(e);\n return false;\n }\n }\n\n removeBundle(id: string): void {\n this._bundles.update((b) => {\n const next = { ...b };\n delete next[id];\n return next;\n });\n this._bundleOrder.update((order) => order.filter((x) => x !== id));\n this.bump();\n }\n\n clearRemoteBundles(): void {\n this._bundles.set({});\n this._bundleOrder.set([]);\n this.bump();\n }\n\n t(key: string, params?: Record<string, string | number>): string {\n const val = this._merged()[key] ?? key;\n if (!params) return val;\n return Object.entries(params).reduce((result, [k, v]) => {\n const safe = escapeRegExp(k);\n return result.replace(new RegExp(`{{\\\\s*${safe}\\\\s*}}`, 'g'), String(v));\n }, val);\n }\n}\n","import { Injectable, signal } from '@angular/core';\n\nexport type FlyThemeMode = 'light' | 'dark' | 'transparent';\n\n/**\n * Applies `html.light-theme` / `html.dark-theme` / `html.transparent-theme` for DS SCSS.\n * Shell and standalone Business Apps use the same service (federation singleton when shared).\n */\n@Injectable({ providedIn: 'root' })\nexport class FlyThemeService {\n readonly theme = signal<FlyThemeMode>('light');\n\n applyTheme(mode: FlyThemeMode): void {\n this.theme.set(mode);\n const html = document.documentElement;\n html.classList.remove('dark-theme', 'light-theme', 'transparent-theme');\n if (mode === 'dark') {\n html.classList.add('dark-theme');\n } else if (mode === 'transparent') {\n html.classList.add('transparent-theme');\n } else {\n html.classList.add('light-theme');\n }\n }\n}\n","import { Injectable } from '@angular/core';\n\n/** Options for opening a child window. */\nexport interface OpenWindowOptions {\n /** Unique identifier for the window instance. */\n windowId: string;\n /** Display title shown in the window chrome. */\n title: string;\n /** Route path or URL to load inside the window. */\n route: string;\n /** Initial width in pixels. Defaults to 900. */\n width?: number;\n /** Initial height in pixels. Defaults to 600. */\n height?: number;\n /** Whether the window can be resized. Defaults to true. */\n resizable?: boolean;\n /** Whether the window can be maximised. Defaults to true. */\n maximizable?: boolean;\n /** Arbitrary data passed to the child window via WINDOW_DATA. */\n data?: unknown;\n}\n\n/**\n * Abstract interface for the WindowManager.\n * The FlyOS shell provides the concrete implementation; Business Apps\n * inject this token to open, close, and focus windows without depending\n * on the shell's internal implementation.\n */\nexport abstract class WindowManagerService {\n abstract openChildWindow(options: OpenWindowOptions): void;\n abstract closeWindow(windowId: string): void;\n abstract focusWindow(windowId: string): void;\n}\n\n/**\n * No-op fallback implementation used when running a Business App in\n * standalone mode (outside the FlyOS shell). Logs a warning instead of\n * throwing so standalone dev/test flows are not broken.\n */\n@Injectable()\nexport class StandaloneWindowManagerService extends WindowManagerService {\n openChildWindow(options: OpenWindowOptions): void {\n console.warn('[WindowManagerService] openChildWindow called in standalone mode — no shell available.', options);\n }\n\n closeWindow(windowId: string): void {\n console.warn('[WindowManagerService] closeWindow called in standalone mode — no shell available.', windowId);\n }\n\n focusWindow(windowId: string): void {\n console.warn('[WindowManagerService] focusWindow called in standalone mode — no shell available.', windowId);\n }\n}\n\n","import { Pipe, PipeTransform, inject } from '@angular/core';\nimport { I18nService } from '../services/i18n.service';\n\n/**\n * Translates a key using the shared I18nService.\n *\n * @example\n * {{ 'myApp.section.title' | translate }}\n * {{ 'myApp.items_count' | translate:{ n: count() } }}\n */\n@Pipe({\n name: 'translate',\n standalone: true,\n pure: false,\n})\nexport class TranslatePipe implements PipeTransform {\n private readonly i18n = inject(I18nService);\n\n transform(key: string, params?: Record<string, string | number>): string {\n // Read version so template CD re-runs when bundles load (merged translations updated).\n void this.i18n.version();\n return this.i18n.t(key, params);\n }\n}\n","import { Injectable, Signal, computed, inject, signal } from '@angular/core';\nimport { Router } from '@angular/router';\nimport { Observable, of } from 'rxjs';\nimport { User } from '../models/user.model';\n\nexport interface MockAuthConfig {\n user: User;\n token?: string;\n loginRedirect?: string[];\n logoutRedirect?: string[];\n}\n\ninterface MockSession {\n accessToken: string;\n user: User;\n expiresAt: number;\n}\n\n/**\n * Shared mock AuthService base class for Business App developers.\n *\n * Extend this class in your app's `auth.service.mock.ts` and override\n * `getConfig()` to supply app-specific mock user data and navigation paths.\n * The subclass must be decorated with `@Injectable({ providedIn: 'root' })`\n * and exported as `AuthService` so Angular's `fileReplacements` swap works.\n *\n * @example\n * ```typescript\n * // src/app/core/services/auth.service.mock.ts\n * import { Injectable } from '@angular/core';\n * import { MockAuthService, type MockAuthConfig } from '@mohamedatia/fly-design-system';\n *\n * @Injectable({ providedIn: 'root' })\n * export class AuthService extends MockAuthService {\n * protected override getConfig(): MockAuthConfig {\n * return {\n * user: { id: 'dev-001', tenantId: 'dev-tenant', email: 'dev@example.com',\n * firstName: 'Dev', lastName: 'User', fullName: 'Dev User',\n * preferredLocale: 'en', roles: ['admin'], apps: ['my-app'] },\n * token: 'my-mock-token',\n * loginRedirect: ['/app'],\n * };\n * }\n * }\n * ```\n */\n@Injectable()\nexport class MockAuthService {\n private readonly router = inject(Router);\n\n protected readonly _session: ReturnType<typeof signal<MockSession | null>>;\n\n private readonly _config: MockAuthConfig;\n\n readonly isAuthenticated: Signal<boolean>;\n readonly currentUser: Signal<User | null>;\n readonly accessToken: Signal<string | null>;\n /** Always false in mock mode — 2FA is handled entirely by the STS. */\n readonly hasPendingTwoFactor = computed(() => false);\n /** Always false in mock mode — auth is pre-populated synchronously. */\n readonly initializing = signal(false).asReadonly();\n\n constructor() {\n // getConfig() is called inside the constructor body (not as a field initializer)\n // to avoid the \"virtual method call during field initialization\" anti-pattern.\n this._config = this.getConfig();\n\n this._session = signal<MockSession | null>({\n accessToken: this._config.token ?? 'mock-token',\n user: this._config.user,\n expiresAt: Date.now() + 24 * 60 * 60 * 1000,\n });\n\n this.isAuthenticated = computed(() => {\n const s = this._session();\n return s !== null && s.expiresAt > Date.now();\n });\n\n this.currentUser = computed(() => this._session()?.user ?? null);\n this.accessToken = computed(() => this._session()?.accessToken ?? null);\n }\n\n /** Override in subclass to supply app-specific mock data. */\n protected getConfig(): MockAuthConfig {\n return {\n user: {\n id: 'mock-user-001',\n tenantId: 'mock-tenant-001',\n email: 'developer@fly.local',\n firstName: 'UI',\n lastName: 'Developer',\n fullName: 'UI Developer',\n preferredLocale: 'en',\n roles: ['admin'],\n apps: [],\n },\n };\n }\n\n async init(): Promise<void> {\n // Mock mode: already authenticated, nothing to initialize.\n }\n\n startLogin(): void {\n this.router.navigate(this._config.loginRedirect ?? ['/']);\n }\n\n handleCallback(_code: string, _state?: string): Observable<User> {\n return of(this._config.user);\n }\n\n async forceRefresh(): Promise<void> {\n // No-op in mock mode — token never expires.\n }\n\n patchSessionPreferredLocale(locale: string): void {\n const session = this._session();\n if (!session?.user) return;\n this._session.set({ ...session, user: { ...session.user, preferredLocale: locale } });\n }\n\n /** Parameter order matches the real AuthService: (user, accessToken, expiresAt). */\n setSession(_user: User, _accessToken: string, _expiresAt: number): void {\n // No-op in mock mode — session is hardcoded.\n }\n\n logout(): void {\n this._session.set(null);\n this.router.navigate(this._config.logoutRedirect ?? ['/']);\n }\n}\n","/*\r\n * @mohamedatia/fly-design-system — Public API\r\n * https://www.npmjs.com/package/@mohamedatia/fly-design-system\r\n *\r\n * This is the single entry point for Business App developers.\r\n * Import everything from '@mohamedatia/fly-design-system' — never from relative shell paths.\r\n *\r\n * NOTE: This package is published under @mohamedatia/fly-design-system until the @fly\r\n * npm org is created. It will be republished as @fly/design-system once available.\r\n *\r\n * v1.3.0: FlyThemeService (html theme classes), hardened I18nService (AbortSignal, ErrorHandler, RTL helpers).\r\n * v1.3.1: loadBundle normalizes locale JSON (flat or nested objects; rejects invalid leaves).\r\n * v1.3.2: loadBundle returns boolean; LoadBundleOptions.silent skips ErrorHandler on failure.\r\n * v1.3.7: MockAuthService base class + MockAuthConfig for Business App mock auth via fileReplacements.\r\n * User model extended with optional avatar, source, twoFactorEnabled, createdAt fields.\r\n * v1.3.8: AuthService.init() no-op added so Business Apps can call init() in APP_INITIALIZER\r\n * without branching between standalone and embedded modes.\r\n * See BusinessAppsGuide/03-frontend-app.md.\r\n */\r\n\r\n// ─── Models ──────────────────────────────────────────────────────────────────\r\nexport type { DesktopApp } from './lib/models/app.model';\r\nexport type {\r\n WindowInstance,\r\n WindowState,\r\n ChildWindowData,\r\n} from './lib/models/window.model';\r\nexport { WINDOW_DATA } from './lib/models/window.model';\r\nexport type { User } from './lib/models/user.model';\r\n\r\n// ─── Remote App Registration ─────────────────────────────────────────────────\r\nexport type { RemoteAppDef } from './lib/models/remote-app.model';\r\n\r\n// ─── Services ────────────────────────────────────────────────────────────────\r\nexport { AuthService } from './lib/services/auth.service';\r\nexport type { LoadBundleOptions } from './lib/services/i18n.service';\r\nexport { I18nService, RTL_LOCALE_SET, isRtlLocale } from './lib/services/i18n.service';\r\nexport { FlyThemeService, type FlyThemeMode } from './lib/services/fly-theme.service';\r\nexport {\r\n WindowManagerService,\r\n StandaloneWindowManagerService,\r\n type OpenWindowOptions,\r\n} from './lib/services/window-manager.service';\r\n\r\n// ─── Pipes ───────────────────────────────────────────────────────────────────\r\nexport { TranslatePipe } from './lib/pipes/translate.pipe';\r\n\r\n// ─── Mock Auth (for fileReplacements in dev/mock builds) ─────────────────────\r\nexport { MockAuthService, type MockAuthConfig } from './lib/services/auth.service.mock';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mohamedatia-fly-design-system.mjs","sources":["../../../projects/design-system/src/lib/models/window.model.ts","../../../projects/design-system/src/lib/services/auth.service.ts","../../../projects/design-system/src/lib/services/i18n.service.ts","../../../projects/design-system/src/lib/services/fly-theme.service.ts","../../../projects/design-system/src/lib/services/window-manager.service.ts","../../../projects/design-system/src/lib/pipes/translate.pipe.ts","../../../projects/design-system/src/lib/services/auth.service.mock.ts","../../../projects/design-system/src/lib/components/context-menu/context-menu.component.ts","../../../projects/design-system/src/lib/components/context-menu/context-menu.component.html","../../../projects/design-system/src/lib/components/message-box/message-box.service.ts","../../../projects/design-system/src/lib/components/message-box/message-box.component.ts","../../../projects/design-system/src/lib/components/message-box/message-box.component.html","../../../projects/design-system/src/public-api.ts","../../../projects/design-system/src/mohamedatia-fly-design-system.ts"],"sourcesContent":["import { InjectionToken, Type } from '@angular/core';\r\n\r\nexport type WindowState = 'normal' | 'minimized' | 'maximized';\r\n\r\nexport interface ChildWindowData {\r\n childComponent: Type<unknown>;\r\n [key: string]: unknown;\r\n}\r\n\r\nexport interface WindowInstance {\r\n id: string;\r\n appId: string;\r\n title: string;\r\n icon: string;\r\n iconBg: string;\r\n state: WindowState;\r\n position: { x: number; y: number };\r\n size: { width: number; height: number };\r\n zIndex: number;\r\n isFocused: boolean;\r\n isClosing?: boolean;\r\n isMinimizing?: boolean;\r\n isRestoring?: boolean;\r\n isMaximizing?: boolean;\r\n isUnmaximizing?: boolean;\r\n parentWindowId?: string;\r\n childData?: ChildWindowData;\r\n /** Populated when remote `loadComponent()` fails (e.g. federation). */\r\n remoteLoadError?: string;\r\n}\r\n\r\nexport const WINDOW_DATA = new InjectionToken<WindowInstance>('WINDOW_DATA');\r\n","import { Injectable, computed, signal } from '@angular/core';\nimport { User } from '../models/user.model';\n\ninterface AuthSession {\n user: User;\n accessToken: string;\n expiresAt: number;\n}\n\n/**\n * Shared AuthService for Business Apps.\n *\n * This is a **read-only signal store** — Business Apps inject it to read the\n * current user and access token. The FlyOS shell populates it after PKCE login\n * and silent refresh. Business Apps must never call setSession() directly.\n *\n * When running as a Module Federation remote, the shell and the Business App\n * share this singleton via the `@mohamedatia/fly-design-system` shared mapping\n * in federation.config.js — so the shell's populated instance is the same\n * object the Business App reads.\n *\n * When running standalone (without the shell), call initFromToken() with a\n * JWT stored in localStorage to hydrate the user.\n */\n@Injectable({ providedIn: 'root' })\nexport class AuthService {\n private _session = signal<AuthSession | null>(null);\n\n readonly currentUser = computed(() => this._session()?.user ?? null);\n readonly accessToken = computed(() => this._session()?.accessToken ?? null);\n readonly isAuthenticated = computed(() => {\n const s = this._session();\n return s !== null && s.expiresAt > Date.now();\n });\n\n /**\n * No-op when running as a Module Federation remote — the shell has already\n * initialised the session before the remote bootstraps. Business Apps call\n * this in their APP_INITIALIZER so the same code works in both standalone\n * and embedded modes without branching.\n */\n async init(): Promise<void> {}\n\n /**\n * Called by the shell after a successful login or silent refresh.\n * Business Apps should not call this directly.\n */\n setSession(user: User, accessToken: string, expiresAt: number): void {\n this._session.set({ user, accessToken, expiresAt });\n }\n\n /** Clears the in-memory session (called by the shell on logout). */\n clearSession(): void {\n this._session.set(null);\n }\n\n /**\n * Standalone mode: parse a JWT from localStorage and hydrate the user.\n * Pass the storage key your app uses; embedded remotes typically set this in `APP_INITIALIZER`.\n */\n initFromToken(storageKey = 'circles_token'): void {\n const token = localStorage.getItem(storageKey);\n if (!token) return;\n try {\n const base64 = token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/');\n const payload = JSON.parse(decodeURIComponent(\n atob(base64).split('').map(c => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)).join('')\n )) as Record<string, unknown>;\n\n const rawRole = payload['role'];\n const roles = Array.isArray(rawRole) ? rawRole as string[] : rawRole ? [rawRole as string] : [];\n const rawApps = payload['apps'];\n const apps = Array.isArray(rawApps) ? rawApps as string[] : rawApps ? [rawApps as string] : [];\n const name = (payload['name'] as string) ?? '';\n const nameParts = name.split(' ');\n\n const user: User = {\n id: (payload['sub'] as string) ?? '',\n tenantId: (payload['tenant_id'] as string) ?? (payload['tid'] as string) ?? null,\n email: (payload['email'] as string) ?? '',\n fullName: name,\n firstName: nameParts[0] ?? '',\n lastName: nameParts.slice(1).join(' '),\n preferredLocale: (payload['locale'] as string) ?? 'en',\n roles,\n apps,\n ou: payload['ou'] as string | undefined,\n };\n\n const expiresAt = ((payload['exp'] as number) ?? 0) * 1000;\n this.setSession(user, token, expiresAt);\n } catch {\n // Invalid token — stay unauthenticated\n }\n }\n}\n","import { Injectable, computed, signal, inject, ErrorHandler } from '@angular/core';\n\n/** Locales that use RTL layout for `dir` and DS `isRtl` / `direction`. */\nexport const RTL_LOCALE_SET: ReadonlySet<string> = new Set(['ar', 'ur']);\n\nexport function isRtlLocale(lang: string): boolean {\n return RTL_LOCALE_SET.has(lang);\n}\n\nfunction escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/** Accepts flat or nested JSON objects; nested keys become dot paths. Rejects arrays and non-string leaves. */\nfunction normalizeLocaleJson(raw: unknown): Record<string, string> {\n if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {\n throw new Error('Locale bundle must be a JSON object');\n }\n const out: Record<string, string> = {};\n const walk = (obj: Record<string, unknown>, prefix: string): void => {\n for (const [k, v] of Object.entries(obj)) {\n const path = prefix ? `${prefix}.${k}` : k;\n if (typeof v === 'string') {\n out[path] = v;\n } else if (v !== null && typeof v === 'object' && !Array.isArray(v)) {\n walk(v as Record<string, unknown>, path);\n } else {\n throw new Error(`Locale bundle invalid value at \"${path}\" (expected string or nested object)`);\n }\n }\n };\n walk(raw as Record<string, unknown>, '');\n return out;\n}\n\n/** Options for loading a remote or standalone locale JSON bundle. */\nexport interface LoadBundleOptions {\n /** Stable id (e.g. app id from manifest); later loads replace this bundle only. */\n id: string;\n /** Base URL ending with `/`, e.g. `https://app.example.com/locale/` or `/my-remote/locale/` */\n baseUrl: string;\n lang: string;\n /** When aborted, failures are ignored (e.g. superseded language load). */\n signal?: AbortSignal;\n /**\n * When true, fetch/parse failures are not reported via Angular `ErrorHandler`.\n * Use for optional remote locale bundles (e.g. federated apps that may be offline).\n */\n silent?: boolean;\n}\n\n/**\n * Shared I18nService for the shell and Business Apps.\n *\n * **Merge order** (later keys win): shell layer → remote bundles in registration order.\n *\n * - Shell: `setShellTranslations()` after loading `locale/{lang}.json` and API overrides.\n * - Remotes: `loadBundle()` per manifest `localeBaseUrl`.\n */\n@Injectable({ providedIn: 'root' })\nexport class I18nService {\n private readonly errorHandler = inject(ErrorHandler, { optional: true });\n\n private readonly _shell = signal<Record<string, string>>({});\n private readonly _bundles = signal<Record<string, Record<string, string>>>({});\n private readonly _bundleOrder = signal<string[]>([]);\n private readonly _locale = signal<string>('en');\n private readonly _version = signal(0);\n\n private readonly _merged = computed(() => {\n const shell = this._shell();\n const order = this._bundleOrder();\n const bundles = this._bundles();\n let out: Record<string, string> = { ...shell };\n for (const id of order) {\n const b = bundles[id];\n if (b) out = { ...out, ...b };\n }\n return out;\n });\n\n readonly locale = this._locale.asReadonly();\n readonly version = this._version.asReadonly();\n readonly isRtl = computed(() => isRtlLocale(this._locale()));\n readonly direction = computed(() => (isRtlLocale(this._locale()) ? 'rtl' : 'ltr'));\n\n private bump(): void {\n this._version.update((v) => v + 1);\n }\n\n /** Replace shell strings (desktop `locale/*.json` + `/api/i18n/desktop-shell/{lang}` merged by the shell). */\n setShellTranslations(data: Record<string, string>, lang: string): void {\n this._shell.set(data);\n this._locale.set(lang);\n this.bump();\n }\n\n setLanguage(lang: string): void {\n this._locale.set(lang);\n this.bump();\n }\n\n /**\n * Fetch `{baseUrl}{lang}.json` and store under `id`. New ids are appended to the merge order.\n * @returns whether the bundle was loaded successfully.\n */\n async loadBundle(opts: LoadBundleOptions): Promise<boolean> {\n const { id, baseUrl, lang, signal: abortSignal, silent } = opts;\n try {\n const base = baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`;\n const url = `${base}${lang}.json`;\n const resp = await fetch(url, { signal: abortSignal });\n if (!resp.ok) throw new Error(`HTTP ${resp.status}`);\n const data = normalizeLocaleJson(await resp.json());\n if (abortSignal?.aborted) return false;\n this._bundles.update((b) => ({ ...b, [id]: data }));\n this._bundleOrder.update((order) => (order.includes(id) ? order : [...order, id]));\n this._locale.set(lang);\n this.bump();\n return true;\n } catch (e) {\n if (abortSignal?.aborted) return false;\n if (!silent) this.errorHandler?.handleError(e);\n return false;\n }\n }\n\n removeBundle(id: string): void {\n this._bundles.update((b) => {\n const next = { ...b };\n delete next[id];\n return next;\n });\n this._bundleOrder.update((order) => order.filter((x) => x !== id));\n this.bump();\n }\n\n clearRemoteBundles(): void {\n this._bundles.set({});\n this._bundleOrder.set([]);\n this.bump();\n }\n\n t(key: string, params?: Record<string, string | number>): string {\n const val = this._merged()[key] ?? key;\n if (!params) return val;\n return Object.entries(params).reduce((result, [k, v]) => {\n const safe = escapeRegExp(k);\n return result.replace(new RegExp(`{{\\\\s*${safe}\\\\s*}}`, 'g'), String(v));\n }, val);\n }\n}\n","import { Injectable, signal } from '@angular/core';\n\nexport type FlyThemeMode = 'light' | 'dark' | 'transparent';\n\n/**\n * Applies `html.light-theme` / `html.dark-theme` / `html.transparent-theme` for DS SCSS.\n * Shell and standalone Business Apps use the same service (federation singleton when shared).\n */\n@Injectable({ providedIn: 'root' })\nexport class FlyThemeService {\n readonly theme = signal<FlyThemeMode>('light');\n\n applyTheme(mode: FlyThemeMode): void {\n this.theme.set(mode);\n const html = document.documentElement;\n html.classList.remove('dark-theme', 'light-theme', 'transparent-theme');\n if (mode === 'dark') {\n html.classList.add('dark-theme');\n } else if (mode === 'transparent') {\n html.classList.add('transparent-theme');\n } else {\n html.classList.add('light-theme');\n }\n }\n}\n","import { Injectable } from '@angular/core';\n\n/** Options for opening a child window. */\nexport interface OpenWindowOptions {\n /** Unique identifier for the window instance. */\n windowId: string;\n /** Display title shown in the window chrome. */\n title: string;\n /** Route path or URL to load inside the window. */\n route: string;\n /** Initial width in pixels. Defaults to 900. */\n width?: number;\n /** Initial height in pixels. Defaults to 600. */\n height?: number;\n /** Whether the window can be resized. Defaults to true. */\n resizable?: boolean;\n /** Whether the window can be maximised. Defaults to true. */\n maximizable?: boolean;\n /** Arbitrary data passed to the child window via WINDOW_DATA. */\n data?: unknown;\n}\n\n/**\n * Abstract interface for the WindowManager.\n * The FlyOS shell provides the concrete implementation; Business Apps\n * inject this token to open, close, and focus windows without depending\n * on the shell's internal implementation.\n */\nexport abstract class WindowManagerService {\n abstract openChildWindow(options: OpenWindowOptions): void;\n abstract closeWindow(windowId: string): void;\n abstract focusWindow(windowId: string): void;\n}\n\n/**\n * No-op fallback implementation used when running a Business App in\n * standalone mode (outside the FlyOS shell). Logs a warning instead of\n * throwing so standalone dev/test flows are not broken.\n */\n@Injectable()\nexport class StandaloneWindowManagerService extends WindowManagerService {\n openChildWindow(options: OpenWindowOptions): void {\n console.warn('[WindowManagerService] openChildWindow called in standalone mode — no shell available.', options);\n }\n\n closeWindow(windowId: string): void {\n console.warn('[WindowManagerService] closeWindow called in standalone mode — no shell available.', windowId);\n }\n\n focusWindow(windowId: string): void {\n console.warn('[WindowManagerService] focusWindow called in standalone mode — no shell available.', windowId);\n }\n}\n\n","import { Pipe, PipeTransform, inject } from '@angular/core';\nimport { I18nService } from '../services/i18n.service';\n\n/**\n * Translates a key using the shared I18nService.\n *\n * @example\n * {{ 'myApp.section.title' | translate }}\n * {{ 'myApp.items_count' | translate:{ n: count() } }}\n */\n@Pipe({\n name: 'translate',\n standalone: true,\n pure: false,\n})\nexport class TranslatePipe implements PipeTransform {\n private readonly i18n = inject(I18nService);\n\n transform(key: string, params?: Record<string, string | number>): string {\n // Read version so template CD re-runs when bundles load (merged translations updated).\n void this.i18n.version();\n return this.i18n.t(key, params);\n }\n}\n","import { Injectable, Signal, computed, inject, signal } from '@angular/core';\nimport { Router } from '@angular/router';\nimport { Observable, of } from 'rxjs';\nimport { User } from '../models/user.model';\n\nexport interface MockAuthConfig {\n user: User;\n token?: string;\n loginRedirect?: string[];\n logoutRedirect?: string[];\n}\n\ninterface MockSession {\n accessToken: string;\n user: User;\n expiresAt: number;\n}\n\n/**\n * Shared mock AuthService base class for Business App developers.\n *\n * Extend this class in your app's `auth.service.mock.ts` and override\n * `getConfig()` to supply app-specific mock user data and navigation paths.\n * The subclass must be decorated with `@Injectable({ providedIn: 'root' })`\n * and exported as `AuthService` so Angular's `fileReplacements` swap works.\n *\n * @example\n * ```typescript\n * // src/app/core/services/auth.service.mock.ts\n * import { Injectable } from '@angular/core';\n * import { MockAuthService, type MockAuthConfig } from '@mohamedatia/fly-design-system';\n *\n * @Injectable({ providedIn: 'root' })\n * export class AuthService extends MockAuthService {\n * protected override getConfig(): MockAuthConfig {\n * return {\n * user: { id: 'dev-001', tenantId: 'dev-tenant', email: 'dev@example.com',\n * firstName: 'Dev', lastName: 'User', fullName: 'Dev User',\n * preferredLocale: 'en', roles: ['admin'], apps: ['my-app'] },\n * token: 'my-mock-token',\n * loginRedirect: ['/app'],\n * };\n * }\n * }\n * ```\n */\n@Injectable()\nexport class MockAuthService {\n private readonly router = inject(Router);\n\n protected readonly _session: ReturnType<typeof signal<MockSession | null>>;\n\n private readonly _config: MockAuthConfig;\n\n readonly isAuthenticated: Signal<boolean>;\n readonly currentUser: Signal<User | null>;\n readonly accessToken: Signal<string | null>;\n /** Always false in mock mode — 2FA is handled entirely by the STS. */\n readonly hasPendingTwoFactor: Signal<boolean>;\n /** Always false in mock mode — auth is pre-populated synchronously. */\n readonly initializing: Signal<boolean>;\n\n constructor() {\n // All signal/computed calls are inside the constructor body so Angular's\n // injection context and ngDevMode are fully set up before they execute.\n this._config = this.getConfig();\n\n this._session = signal<MockSession | null>({\n accessToken: this._config.token ?? 'mock-token',\n user: this._config.user,\n expiresAt: Date.now() + 24 * 60 * 60 * 1000,\n });\n\n this.isAuthenticated = computed(() => {\n const s = this._session();\n return s !== null && s.expiresAt > Date.now();\n });\n\n this.currentUser = computed(() => this._session()?.user ?? null);\n this.accessToken = computed(() => this._session()?.accessToken ?? null);\n this.hasPendingTwoFactor = computed(() => false);\n this.initializing = signal(false).asReadonly();\n }\n\n /** Override in subclass to supply app-specific mock data. */\n protected getConfig(): MockAuthConfig {\n return {\n user: {\n id: 'mock-user-001',\n tenantId: 'mock-tenant-001',\n email: 'developer@fly.local',\n firstName: 'UI',\n lastName: 'Developer',\n fullName: 'UI Developer',\n preferredLocale: 'en',\n roles: ['admin'],\n apps: [],\n },\n };\n }\n\n async init(): Promise<void> {\n // Mock mode: already authenticated, nothing to initialize.\n }\n\n startLogin(): void {\n this.router.navigate(this._config.loginRedirect ?? ['/']);\n }\n\n handleCallback(_code: string, _state?: string): Observable<User> {\n return of(this._config.user);\n }\n\n async forceRefresh(): Promise<void> {\n // No-op in mock mode — token never expires.\n }\n\n patchSessionPreferredLocale(locale: string): void {\n const session = this._session();\n if (!session?.user) return;\n this._session.set({ ...session, user: { ...session.user, preferredLocale: locale } });\n }\n\n /** Parameter order matches the real AuthService: (user, accessToken, expiresAt). */\n setSession(_user: User, _accessToken: string, _expiresAt: number): void {\n // No-op in mock mode — session is hardcoded.\n }\n\n logout(): void {\n this._session.set(null);\n this.router.navigate(this._config.logoutRedirect ?? ['/']);\n }\n}\n","import {\n Component, input, output, HostListener, ViewChild, ElementRef,\n computed, signal, AfterViewInit, ChangeDetectionStrategy,\n} from '@angular/core';\nimport { TranslatePipe } from '../../pipes/translate.pipe';\n\nexport interface ContextMenuItem {\n id: string;\n label: string;\n icon: string;\n}\n\nexport interface ContextMenuSection {\n label?: string;\n items: ContextMenuItem[];\n}\n\n@Component({\n selector: 'fly-context-menu',\n standalone: true,\n imports: [TranslatePipe],\n templateUrl: './context-menu.component.html',\n styleUrl: './context-menu.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ContextMenuComponent implements AfterViewInit {\n @ViewChild('contextMenu') private menuEl?: ElementRef<HTMLElement>;\n\n x = input.required<number>();\n y = input.required<number>();\n sections = input.required<ContextMenuSection[]>();\n action = output<string>();\n closed = output<void>();\n\n private menuWidth = signal(220);\n private menuHeight = signal(200);\n\n private previouslyFocused: Element | null = null;\n\n clampedPos = computed(() => {\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n return {\n x: Math.min(this.x(), vw - this.menuWidth()),\n y: Math.min(this.y(), vh - this.menuHeight()),\n };\n });\n\n ngAfterViewInit(): void {\n const el = this.menuEl?.nativeElement;\n if (el) {\n this.menuWidth.set(el.offsetWidth);\n this.menuHeight.set(el.offsetHeight);\n }\n // Store focus origin and move focus to first menu item\n this.previouslyFocused = document.activeElement;\n this.focusItem(0);\n }\n\n onAction(id: string): void {\n this.action.emit(id);\n this.close();\n }\n\n @HostListener('document:mousedown', ['$event'])\n onClickOutside(event: MouseEvent): void {\n if (!this.menuEl?.nativeElement.contains(event.target as Node)) {\n this.close();\n }\n }\n\n @HostListener('document:keydown.escape')\n onEscape(): void {\n this.close();\n }\n\n @HostListener('document:contextmenu', ['$event'])\n onContextMenu(event: MouseEvent): void {\n if (!this.menuEl?.nativeElement.contains(event.target as Node)) {\n this.close();\n }\n }\n\n @HostListener('keydown', ['$event'])\n onKeydown(event: KeyboardEvent): void {\n const items = this.getMenuItems();\n if (!items.length) return;\n const focused = document.activeElement as HTMLElement;\n const idx = items.indexOf(focused);\n\n if (event.key === 'ArrowDown') {\n event.preventDefault();\n this.focusItem(idx < items.length - 1 ? idx + 1 : 0);\n } else if (event.key === 'ArrowUp') {\n event.preventDefault();\n this.focusItem(idx > 0 ? idx - 1 : items.length - 1);\n } else if (event.key === 'Home') {\n event.preventDefault();\n this.focusItem(0);\n } else if (event.key === 'End') {\n event.preventDefault();\n this.focusItem(items.length - 1);\n }\n }\n\n private close(): void {\n this.restoreFocus();\n this.closed.emit();\n }\n\n private getMenuItems(): HTMLElement[] {\n return Array.from(\n this.menuEl?.nativeElement.querySelectorAll<HTMLElement>('[role=\"menuitem\"]') ?? [],\n );\n }\n\n private focusItem(index: number): void {\n const items = this.getMenuItems();\n items[index]?.focus();\n }\n\n private restoreFocus(): void {\n if (this.previouslyFocused instanceof HTMLElement) {\n this.previouslyFocused.focus();\n }\n this.previouslyFocused = null;\n }\n}\n","<div\n #contextMenu\n class=\"context-menu\"\n [style.left.px]=\"clampedPos().x\"\n [style.top.px]=\"clampedPos().y\"\n role=\"menu\"\n [attr.aria-label]=\"'shell.context_menu' | translate\">\n\n @for (section of sections(); track $index) {\n @if ($index > 0) {\n <div class=\"menu-divider\"></div>\n }\n @if (section.label) {\n <div class=\"menu-section-label\">{{ section.label }}</div>\n }\n @for (item of section.items; track item.id) {\n <button\n type=\"button\"\n class=\"vos-btn sm rect menu-item\"\n role=\"menuitem\"\n (click)=\"onAction(item.id)\">\n <i [class]=\"'pi ' + item.icon\" aria-hidden=\"true\"></i>\n <span>{{ item.label }}</span>\n </button>\n }\n }\n</div>\n","import { Injectable, inject, signal } from '@angular/core';\nimport { I18nService } from '../../services/i18n.service';\n\nexport enum MessageBoxButtons {\n OK,\n OKCancel,\n YesNo,\n YesNoCancel,\n RetryCancel,\n AbortRetryIgnore,\n}\n\nexport enum MessageBoxIcon {\n None,\n Information,\n Warning,\n Error,\n Question,\n}\n\nexport enum DialogResult {\n None,\n OK,\n Cancel,\n Yes,\n No,\n Retry,\n Abort,\n Ignore,\n}\n\nexport interface MessageBoxOptions {\n title: string;\n message: string;\n buttons?: MessageBoxButtons;\n icon?: MessageBoxIcon;\n}\n\nexport interface MessageBoxButton {\n label: string;\n result: DialogResult;\n variant?: 'primary' | 'danger' | 'default';\n}\n\n@Injectable({ providedIn: 'root' })\nexport class MessageBoxService {\n private readonly i18n = inject(I18nService);\n\n readonly visible = signal(false);\n readonly title = signal('');\n readonly message = signal('');\n readonly icon = signal<MessageBoxIcon>(MessageBoxIcon.None);\n readonly buttons = signal<MessageBoxButton[]>([]);\n\n private resolver: ((value: DialogResult) => void) | null = null;\n\n show(options: MessageBoxOptions): Promise<DialogResult> {\n // Dismiss any pending dialog so its Promise resolves rather than leaking\n if (this.resolver) {\n this.resolver(DialogResult.None);\n this.resolver = null;\n }\n\n this.title.set(options.title);\n this.message.set(options.message);\n this.icon.set(options.icon ?? MessageBoxIcon.None);\n this.buttons.set(this.resolveButtons(options.buttons ?? MessageBoxButtons.OK));\n this.visible.set(true);\n\n return new Promise<DialogResult>((resolve) => {\n this.resolver = resolve;\n });\n }\n\n resolve(result: DialogResult): void {\n this.visible.set(false);\n if (this.resolver) {\n this.resolver(result);\n this.resolver = null;\n }\n }\n\n private resolveButtons(buttons: MessageBoxButtons): MessageBoxButton[] {\n const t = (key: string) => this.i18n.t(key);\n switch (buttons) {\n case MessageBoxButtons.OK:\n return [{ label: t('common.ok'), result: DialogResult.OK, variant: 'primary' }];\n\n case MessageBoxButtons.OKCancel:\n return [\n { label: t('common.cancel'), result: DialogResult.Cancel, variant: 'default' },\n { label: t('common.ok'), result: DialogResult.OK, variant: 'primary' },\n ];\n\n case MessageBoxButtons.YesNo:\n return [\n { label: t('common.no'), result: DialogResult.No, variant: 'default' },\n { label: t('common.yes'), result: DialogResult.Yes, variant: 'primary' },\n ];\n\n case MessageBoxButtons.YesNoCancel:\n return [\n { label: t('common.cancel'), result: DialogResult.Cancel, variant: 'default' },\n { label: t('common.no'), result: DialogResult.No, variant: 'default' },\n { label: t('common.yes'), result: DialogResult.Yes, variant: 'primary' },\n ];\n\n case MessageBoxButtons.RetryCancel:\n return [\n { label: t('common.cancel'), result: DialogResult.Cancel, variant: 'default' },\n { label: t('common.retry'), result: DialogResult.Retry, variant: 'primary' },\n ];\n\n case MessageBoxButtons.AbortRetryIgnore:\n return [\n { label: t('common.abort'), result: DialogResult.Abort, variant: 'danger' },\n { label: t('common.retry'), result: DialogResult.Retry, variant: 'default' },\n { label: t('common.ignore'), result: DialogResult.Ignore, variant: 'default' },\n ];\n }\n }\n}\n","import {\n Component, inject, ChangeDetectionStrategy,\n HostListener, ElementRef, AfterViewInit,\n} from '@angular/core';\nimport { MessageBoxService, MessageBoxIcon, DialogResult } from './message-box.service';\n\n@Component({\n selector: 'fly-message-box',\n standalone: true,\n templateUrl: './message-box.component.html',\n styleUrl: './message-box.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class MessageBoxComponent implements AfterViewInit {\n service = inject(MessageBoxService);\n private elRef = inject(ElementRef);\n\n readonly MessageBoxIcon = MessageBoxIcon;\n readonly DialogResult = DialogResult;\n\n private previouslyFocused: Element | null = null;\n\n ngAfterViewInit(): void {\n // Store focus origin so we can restore it on close\n this.previouslyFocused = document.activeElement;\n this.focusPrimaryButton();\n }\n\n @HostListener('document:keydown.escape')\n onEscape(): void {\n if (this.service.visible()) {\n this.service.resolve(DialogResult.Cancel);\n this.restoreFocus();\n }\n }\n\n onBackdropClick(): void {\n this.service.resolve(DialogResult.Cancel);\n this.restoreFocus();\n }\n\n onButtonClick(result: DialogResult): void {\n this.service.resolve(result);\n this.restoreFocus();\n }\n\n iconClass(): string {\n switch (this.service.icon()) {\n case MessageBoxIcon.Information: return 'pi pi-info-circle';\n case MessageBoxIcon.Warning: return 'pi pi-exclamation-triangle';\n case MessageBoxIcon.Error: return 'pi pi-times-circle';\n case MessageBoxIcon.Question: return 'pi pi-question-circle';\n default: return '';\n }\n }\n\n private focusPrimaryButton(): void {\n // Focus the primary (last) button, which is the default action\n const buttons = this.elRef.nativeElement.querySelectorAll('.mb-btn') as NodeListOf<HTMLButtonElement>;\n const last = buttons[buttons.length - 1];\n last?.focus();\n }\n\n private restoreFocus(): void {\n if (this.previouslyFocused instanceof HTMLElement) {\n this.previouslyFocused.focus();\n }\n this.previouslyFocused = null;\n }\n}\n","@if (service.visible()) {\n <div\n class=\"mb-backdrop\"\n (click)=\"onBackdropClick()\"\n role=\"presentation\">\n <div\n class=\"mb-dialog\"\n [class.mb-info]=\"service.icon() === MessageBoxIcon.Information\"\n [class.mb-warning]=\"service.icon() === MessageBoxIcon.Warning\"\n [class.mb-danger]=\"service.icon() === MessageBoxIcon.Error\"\n [class.mb-question]=\"service.icon() === MessageBoxIcon.Question\"\n (click)=\"$event.stopPropagation()\"\n role=\"alertdialog\"\n aria-modal=\"true\"\n aria-labelledby=\"mb-title\"\n aria-describedby=\"mb-message\">\n\n @if (iconClass()) {\n <div class=\"mb-icon-wrap\">\n <i [class]=\"iconClass() + ' mb-icon'\" aria-hidden=\"true\"></i>\n </div>\n }\n\n <div class=\"mb-title\" id=\"mb-title\">{{ service.title() }}</div>\n <div class=\"mb-message\" id=\"mb-message\">{{ service.message() }}</div>\n\n <div class=\"mb-actions\">\n @for (btn of service.buttons(); track btn.result) {\n <button\n type=\"button\"\n class=\"vos-btn sm mb-btn\"\n [class.mb-btn--primary]=\"btn.variant === 'primary'\"\n [class.mb-btn--danger]=\"btn.variant === 'danger'\"\n (click)=\"onButtonClick(btn.result)\">\n {{ btn.label }}\n </button>\n }\n </div>\n\n </div>\n </div>\n}\n","/*\r\n * @mohamedatia/fly-design-system — Public API\r\n * https://www.npmjs.com/package/@mohamedatia/fly-design-system\r\n *\r\n * This is the single entry point for Business App developers.\r\n * Import everything from '@mohamedatia/fly-design-system' — never from relative shell paths.\r\n *\r\n * NOTE: This package is published under @mohamedatia/fly-design-system until the @fly\r\n * npm org is created. It will be republished as @fly/design-system once available.\r\n *\r\n * v1.3.0: FlyThemeService (html theme classes), hardened I18nService (AbortSignal, ErrorHandler, RTL helpers).\r\n * v1.3.1: loadBundle normalizes locale JSON (flat or nested objects; rejects invalid leaves).\r\n * v1.3.2: loadBundle returns boolean; LoadBundleOptions.silent skips ErrorHandler on failure.\r\n * v1.3.7: MockAuthService base class + MockAuthConfig for Business App mock auth via fileReplacements.\r\n * User model extended with optional avatar, source, twoFactorEnabled, createdAt fields.\r\n * v1.3.8: AuthService.init() no-op added so Business Apps can call init() in APP_INITIALIZER\r\n * without branching between standalone and embedded modes.\r\n * v1.3.9: MockAuthService field initializers moved into constructor to fix ngDevMode ReferenceError\r\n * when the package is loaded in a production-mode bundle (no ngDevMode global defined).\r\n * v1.4.0: ContextMenuComponent (positioned menu, keyboard nav, focus management) moved from desktop\r\n * shell to design system. MessageBoxService + MessageBoxComponent added (Windows Forms-style\r\n * modal dialogs with localized button labels, focus management, and Escape key support).\r\n * MessageBoxButtons, MessageBoxIcon, DialogResult, MessageBoxOptions, MessageBoxButton exported.\r\n * See BusinessAppsGuide/03-frontend-app.md.\r\n */\r\n\r\n// ─── Models ──────────────────────────────────────────────────────────────────\r\nexport type { DesktopApp } from './lib/models/app.model';\r\nexport type {\r\n WindowInstance,\r\n WindowState,\r\n ChildWindowData,\r\n} from './lib/models/window.model';\r\nexport { WINDOW_DATA } from './lib/models/window.model';\r\nexport type { User } from './lib/models/user.model';\r\n\r\n// ─── Remote App Registration ─────────────────────────────────────────────────\r\nexport type { RemoteAppDef } from './lib/models/remote-app.model';\r\n\r\n// ─── Services ────────────────────────────────────────────────────────────────\r\nexport { AuthService } from './lib/services/auth.service';\r\nexport type { LoadBundleOptions } from './lib/services/i18n.service';\r\nexport { I18nService, RTL_LOCALE_SET, isRtlLocale } from './lib/services/i18n.service';\r\nexport { FlyThemeService, type FlyThemeMode } from './lib/services/fly-theme.service';\r\nexport {\r\n WindowManagerService,\r\n StandaloneWindowManagerService,\r\n type OpenWindowOptions,\r\n} from './lib/services/window-manager.service';\r\n\r\n// ─── Pipes ───────────────────────────────────────────────────────────────────\r\nexport { TranslatePipe } from './lib/pipes/translate.pipe';\r\n\r\n// ─── Mock Auth (for fileReplacements in dev/mock builds) ─────────────────────\r\nexport { MockAuthService, type MockAuthConfig } from './lib/services/auth.service.mock';\r\n\r\n// ─── Components ──────────────────────────────────────────────────────────────\r\nexport {\r\n ContextMenuComponent,\r\n type ContextMenuItem,\r\n type ContextMenuSection,\r\n} from './lib/components/context-menu/context-menu.component';\r\n\r\nexport {\r\n MessageBoxComponent,\r\n} from './lib/components/message-box/message-box.component';\r\n\r\nexport {\r\n MessageBoxService,\r\n MessageBoxButtons,\r\n MessageBoxIcon,\r\n DialogResult,\r\n type MessageBoxOptions,\r\n type MessageBoxButton,\r\n} from './lib/components/message-box/message-box.service';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import { Type, InjectionToken, PipeTransform, signal, Signal } from '@angular/core';
|
|
1
|
+
import * as _angular_core from '@angular/core';
|
|
2
|
+
import { Type, InjectionToken, PipeTransform, signal, Signal, AfterViewInit } from '@angular/core';
|
|
3
3
|
import { Observable } from 'rxjs';
|
|
4
4
|
|
|
5
5
|
interface DesktopApp {
|
|
@@ -122,9 +122,9 @@ interface RemoteAppDef {
|
|
|
122
122
|
*/
|
|
123
123
|
declare class AuthService {
|
|
124
124
|
private _session;
|
|
125
|
-
readonly currentUser:
|
|
126
|
-
readonly accessToken:
|
|
127
|
-
readonly isAuthenticated:
|
|
125
|
+
readonly currentUser: _angular_core.Signal<User | null>;
|
|
126
|
+
readonly accessToken: _angular_core.Signal<string | null>;
|
|
127
|
+
readonly isAuthenticated: _angular_core.Signal<boolean>;
|
|
128
128
|
/**
|
|
129
129
|
* No-op when running as a Module Federation remote — the shell has already
|
|
130
130
|
* initialised the session before the remote bootstraps. Business Apps call
|
|
@@ -144,8 +144,8 @@ declare class AuthService {
|
|
|
144
144
|
* Pass the storage key your app uses; embedded remotes typically set this in `APP_INITIALIZER`.
|
|
145
145
|
*/
|
|
146
146
|
initFromToken(storageKey?: string): void;
|
|
147
|
-
static ɵfac:
|
|
148
|
-
static ɵprov:
|
|
147
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<AuthService, never>;
|
|
148
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<AuthService>;
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
/** Locales that use RTL layout for `dir` and DS `isRtl` / `direction`. */
|
|
@@ -182,10 +182,10 @@ declare class I18nService {
|
|
|
182
182
|
private readonly _locale;
|
|
183
183
|
private readonly _version;
|
|
184
184
|
private readonly _merged;
|
|
185
|
-
readonly locale:
|
|
186
|
-
readonly version:
|
|
187
|
-
readonly isRtl:
|
|
188
|
-
readonly direction:
|
|
185
|
+
readonly locale: _angular_core.Signal<string>;
|
|
186
|
+
readonly version: _angular_core.Signal<number>;
|
|
187
|
+
readonly isRtl: _angular_core.Signal<boolean>;
|
|
188
|
+
readonly direction: _angular_core.Signal<"rtl" | "ltr">;
|
|
189
189
|
private bump;
|
|
190
190
|
/** Replace shell strings (desktop `locale/*.json` + `/api/i18n/desktop-shell/{lang}` merged by the shell). */
|
|
191
191
|
setShellTranslations(data: Record<string, string>, lang: string): void;
|
|
@@ -198,8 +198,8 @@ declare class I18nService {
|
|
|
198
198
|
removeBundle(id: string): void;
|
|
199
199
|
clearRemoteBundles(): void;
|
|
200
200
|
t(key: string, params?: Record<string, string | number>): string;
|
|
201
|
-
static ɵfac:
|
|
202
|
-
static ɵprov:
|
|
201
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<I18nService, never>;
|
|
202
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<I18nService>;
|
|
203
203
|
}
|
|
204
204
|
|
|
205
205
|
type FlyThemeMode = 'light' | 'dark' | 'transparent';
|
|
@@ -208,10 +208,10 @@ type FlyThemeMode = 'light' | 'dark' | 'transparent';
|
|
|
208
208
|
* Shell and standalone Business Apps use the same service (federation singleton when shared).
|
|
209
209
|
*/
|
|
210
210
|
declare class FlyThemeService {
|
|
211
|
-
readonly theme:
|
|
211
|
+
readonly theme: _angular_core.WritableSignal<FlyThemeMode>;
|
|
212
212
|
applyTheme(mode: FlyThemeMode): void;
|
|
213
|
-
static ɵfac:
|
|
214
|
-
static ɵprov:
|
|
213
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<FlyThemeService, never>;
|
|
214
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<FlyThemeService>;
|
|
215
215
|
}
|
|
216
216
|
|
|
217
217
|
/** Options for opening a child window. */
|
|
@@ -253,8 +253,8 @@ declare class StandaloneWindowManagerService extends WindowManagerService {
|
|
|
253
253
|
openChildWindow(options: OpenWindowOptions): void;
|
|
254
254
|
closeWindow(windowId: string): void;
|
|
255
255
|
focusWindow(windowId: string): void;
|
|
256
|
-
static ɵfac:
|
|
257
|
-
static ɵprov:
|
|
256
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<StandaloneWindowManagerService, never>;
|
|
257
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<StandaloneWindowManagerService>;
|
|
258
258
|
}
|
|
259
259
|
|
|
260
260
|
/**
|
|
@@ -267,8 +267,8 @@ declare class StandaloneWindowManagerService extends WindowManagerService {
|
|
|
267
267
|
declare class TranslatePipe implements PipeTransform {
|
|
268
268
|
private readonly i18n;
|
|
269
269
|
transform(key: string, params?: Record<string, string | number>): string;
|
|
270
|
-
static ɵfac:
|
|
271
|
-
static ɵpipe:
|
|
270
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<TranslatePipe, never>;
|
|
271
|
+
static ɵpipe: _angular_core.ɵɵPipeDeclaration<TranslatePipe, "translate", true>;
|
|
272
272
|
}
|
|
273
273
|
|
|
274
274
|
interface MockAuthConfig {
|
|
@@ -332,10 +332,115 @@ declare class MockAuthService {
|
|
|
332
332
|
/** Parameter order matches the real AuthService: (user, accessToken, expiresAt). */
|
|
333
333
|
setSession(_user: User, _accessToken: string, _expiresAt: number): void;
|
|
334
334
|
logout(): void;
|
|
335
|
-
static ɵfac:
|
|
336
|
-
static ɵprov:
|
|
335
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<MockAuthService, never>;
|
|
336
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<MockAuthService>;
|
|
337
337
|
}
|
|
338
338
|
|
|
339
|
-
|
|
340
|
-
|
|
339
|
+
interface ContextMenuItem {
|
|
340
|
+
id: string;
|
|
341
|
+
label: string;
|
|
342
|
+
icon: string;
|
|
343
|
+
}
|
|
344
|
+
interface ContextMenuSection {
|
|
345
|
+
label?: string;
|
|
346
|
+
items: ContextMenuItem[];
|
|
347
|
+
}
|
|
348
|
+
declare class ContextMenuComponent implements AfterViewInit {
|
|
349
|
+
private menuEl?;
|
|
350
|
+
x: _angular_core.InputSignal<number>;
|
|
351
|
+
y: _angular_core.InputSignal<number>;
|
|
352
|
+
sections: _angular_core.InputSignal<ContextMenuSection[]>;
|
|
353
|
+
action: _angular_core.OutputEmitterRef<string>;
|
|
354
|
+
closed: _angular_core.OutputEmitterRef<void>;
|
|
355
|
+
private menuWidth;
|
|
356
|
+
private menuHeight;
|
|
357
|
+
private previouslyFocused;
|
|
358
|
+
clampedPos: _angular_core.Signal<{
|
|
359
|
+
x: number;
|
|
360
|
+
y: number;
|
|
361
|
+
}>;
|
|
362
|
+
ngAfterViewInit(): void;
|
|
363
|
+
onAction(id: string): void;
|
|
364
|
+
onClickOutside(event: MouseEvent): void;
|
|
365
|
+
onEscape(): void;
|
|
366
|
+
onContextMenu(event: MouseEvent): void;
|
|
367
|
+
onKeydown(event: KeyboardEvent): void;
|
|
368
|
+
private close;
|
|
369
|
+
private getMenuItems;
|
|
370
|
+
private focusItem;
|
|
371
|
+
private restoreFocus;
|
|
372
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ContextMenuComponent, never>;
|
|
373
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<ContextMenuComponent, "fly-context-menu", never, { "x": { "alias": "x"; "required": true; "isSignal": true; }; "y": { "alias": "y"; "required": true; "isSignal": true; }; "sections": { "alias": "sections"; "required": true; "isSignal": true; }; }, { "action": "action"; "closed": "closed"; }, never, never, true, never>;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
declare enum MessageBoxButtons {
|
|
377
|
+
OK = 0,
|
|
378
|
+
OKCancel = 1,
|
|
379
|
+
YesNo = 2,
|
|
380
|
+
YesNoCancel = 3,
|
|
381
|
+
RetryCancel = 4,
|
|
382
|
+
AbortRetryIgnore = 5
|
|
383
|
+
}
|
|
384
|
+
declare enum MessageBoxIcon {
|
|
385
|
+
None = 0,
|
|
386
|
+
Information = 1,
|
|
387
|
+
Warning = 2,
|
|
388
|
+
Error = 3,
|
|
389
|
+
Question = 4
|
|
390
|
+
}
|
|
391
|
+
declare enum DialogResult {
|
|
392
|
+
None = 0,
|
|
393
|
+
OK = 1,
|
|
394
|
+
Cancel = 2,
|
|
395
|
+
Yes = 3,
|
|
396
|
+
No = 4,
|
|
397
|
+
Retry = 5,
|
|
398
|
+
Abort = 6,
|
|
399
|
+
Ignore = 7
|
|
400
|
+
}
|
|
401
|
+
interface MessageBoxOptions {
|
|
402
|
+
title: string;
|
|
403
|
+
message: string;
|
|
404
|
+
buttons?: MessageBoxButtons;
|
|
405
|
+
icon?: MessageBoxIcon;
|
|
406
|
+
}
|
|
407
|
+
interface MessageBoxButton {
|
|
408
|
+
label: string;
|
|
409
|
+
result: DialogResult;
|
|
410
|
+
variant?: 'primary' | 'danger' | 'default';
|
|
411
|
+
}
|
|
412
|
+
declare class MessageBoxService {
|
|
413
|
+
private readonly i18n;
|
|
414
|
+
readonly visible: _angular_core.WritableSignal<boolean>;
|
|
415
|
+
readonly title: _angular_core.WritableSignal<string>;
|
|
416
|
+
readonly message: _angular_core.WritableSignal<string>;
|
|
417
|
+
readonly icon: _angular_core.WritableSignal<MessageBoxIcon>;
|
|
418
|
+
readonly buttons: _angular_core.WritableSignal<MessageBoxButton[]>;
|
|
419
|
+
private resolver;
|
|
420
|
+
show(options: MessageBoxOptions): Promise<DialogResult>;
|
|
421
|
+
resolve(result: DialogResult): void;
|
|
422
|
+
private resolveButtons;
|
|
423
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<MessageBoxService, never>;
|
|
424
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<MessageBoxService>;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
declare class MessageBoxComponent implements AfterViewInit {
|
|
428
|
+
service: MessageBoxService;
|
|
429
|
+
private elRef;
|
|
430
|
+
readonly MessageBoxIcon: typeof MessageBoxIcon;
|
|
431
|
+
readonly DialogResult: typeof DialogResult;
|
|
432
|
+
private previouslyFocused;
|
|
433
|
+
ngAfterViewInit(): void;
|
|
434
|
+
onEscape(): void;
|
|
435
|
+
onBackdropClick(): void;
|
|
436
|
+
onButtonClick(result: DialogResult): void;
|
|
437
|
+
iconClass(): string;
|
|
438
|
+
private focusPrimaryButton;
|
|
439
|
+
private restoreFocus;
|
|
440
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<MessageBoxComponent, never>;
|
|
441
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<MessageBoxComponent, "fly-message-box", never, {}, {}, never, never, true, never>;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
export { AuthService, ContextMenuComponent, DialogResult, FlyThemeService, I18nService, MessageBoxButtons, MessageBoxComponent, MessageBoxIcon, MessageBoxService, MockAuthService, RTL_LOCALE_SET, StandaloneWindowManagerService, TranslatePipe, WINDOW_DATA, WindowManagerService, isRtlLocale };
|
|
445
|
+
export type { ChildWindowData, ContextMenuItem, ContextMenuSection, DesktopApp, FlyThemeMode, LoadBundleOptions, MessageBoxButton, MessageBoxOptions, MockAuthConfig, OpenWindowOptions, RemoteAppDef, User, WindowInstance, WindowState };
|
|
341
446
|
//# sourceMappingURL=mohamedatia-fly-design-system.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mohamedatia-fly-design-system.d.ts","sources":["../../../projects/design-system/src/lib/models/app.model.ts","../../../projects/design-system/src/lib/models/window.model.ts","../../../projects/design-system/src/lib/models/user.model.ts","../../../projects/design-system/src/lib/models/remote-app.model.ts","../../../projects/design-system/src/lib/services/auth.service.ts","../../../projects/design-system/src/lib/services/i18n.service.ts","../../../projects/design-system/src/lib/services/fly-theme.service.ts","../../../projects/design-system/src/lib/services/window-manager.service.ts","../../../projects/design-system/src/lib/pipes/translate.pipe.ts","../../../projects/design-system/src/lib/services/auth.service.mock.ts"],"mappings":";;;;UAEiB,UAAU;;;;;;yBAMJ,OAAO,CAAC,IAAI;AACjC;;;;AACA;;;;;;;AAID;;ACZK,KAAM,WAAW;UAEN,eAAe;AAC9B,oBAAgB,IAAI;AACpB;AACD;UAEgB,cAAc;;;;;;WAMtB,WAAW;AAClB;;;;AACA;;;;;;;;;;;;gBASY,eAAe;;;AAG5B;AAED,cAAa,WAAW,EAAA,cAAA,CAAA,cAAA;;UC/BP,IAAI;;AAEnB;;;;;;;;AAQA;;;;;;gBAMY,IAAI;AACjB;;ACfD;;;;AAIG;UACc,YAAY;;;;;;;;;;;;AAY3B;;;;AACA;;;;;AAEA,cAAU,UAAU;;AAErB;;ACfD;;;;;;;;;;;;;;AAcG;AACH,cACa,WAAW;;
|
|
1
|
+
{"version":3,"file":"mohamedatia-fly-design-system.d.ts","sources":["../../../projects/design-system/src/lib/models/app.model.ts","../../../projects/design-system/src/lib/models/window.model.ts","../../../projects/design-system/src/lib/models/user.model.ts","../../../projects/design-system/src/lib/models/remote-app.model.ts","../../../projects/design-system/src/lib/services/auth.service.ts","../../../projects/design-system/src/lib/services/i18n.service.ts","../../../projects/design-system/src/lib/services/fly-theme.service.ts","../../../projects/design-system/src/lib/services/window-manager.service.ts","../../../projects/design-system/src/lib/pipes/translate.pipe.ts","../../../projects/design-system/src/lib/services/auth.service.mock.ts","../../../projects/design-system/src/lib/components/context-menu/context-menu.component.ts","../../../projects/design-system/src/lib/components/message-box/message-box.service.ts","../../../projects/design-system/src/lib/components/message-box/message-box.component.ts"],"mappings":"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","names":[]}
|