@loomweaver/shell 0.7.6 → 0.7.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/loomweaver-shell.mjs +395 -70
- package/fesm2022/loomweaver-shell.mjs.map +1 -1
- package/i18n/de.json +4 -3
- package/i18n/en.json +3 -2
- package/package.json +2 -2
- package/styles/shell.css +1 -1
- package/styles/theme.css +34 -2
- package/types/loomweaver-shell.d.ts +49 -4
- package/types/loomweaver-shell.d.ts.map +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, signal, computed, Service, inject, makeEnvironmentProviders, ApplicationRef, Injector, effect, untracked, provideEnvironmentInitializer, ErrorHandler,
|
|
2
|
+
import { InjectionToken, isDevMode, signal, computed, Service, inject, makeEnvironmentProviders, ApplicationRef, Injector, effect, untracked, provideEnvironmentInitializer, ErrorHandler, ElementRef, input, booleanAttribute, Directive, CUSTOM_ELEMENTS_SCHEMA, Component, output, EnvironmentInjector, DestroyRef, viewChild, afterRenderEffect, afterNextRender, createComponent, forwardRef, ViewEncapsulation, viewChildren, Injectable, provideZonelessChangeDetection, provideBrowserGlobalErrorListeners, provideAppInitializer } from '@angular/core';
|
|
3
3
|
import { ChildrenOutletContexts, Router, NavigationEnd, ActivatedRoute, convertToParamMap, UrlSegment, RouterOutlet, RouteReuseStrategy, provideRouter, withDisabledInitialNavigation } from '@angular/router';
|
|
4
4
|
import { TranslocoService, TranslocoPipe, provideTransloco, provideTranslocoMissingHandler } from '@jsverse/transloco';
|
|
5
5
|
import { DOCUMENT, NgComponentOutlet, Location, NgTemplateOutlet } from '@angular/common';
|
|
@@ -43,6 +43,40 @@ function provideLayout(layout) {
|
|
|
43
43
|
return { provide: SHELL_LAYOUT, useValue: layout };
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
const warned = new Set();
|
|
47
|
+
function menuOnActivate(item) {
|
|
48
|
+
if (!item.menu || item.menuTrigger === undefined || item.menuTrigger === 'context') {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
return item.workspace === undefined ? item.menu : undefined;
|
|
52
|
+
}
|
|
53
|
+
function menuOnContext(item) {
|
|
54
|
+
if (!item.menu) {
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
return menuOnActivate(item) && item.menuTrigger === 'primary'
|
|
58
|
+
? undefined
|
|
59
|
+
: item.menu;
|
|
60
|
+
}
|
|
61
|
+
function warnMenuTriggerConflict(item) {
|
|
62
|
+
if (!isDevMode() || warned.has(item.id)) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (item.workspace !== undefined && item.menuTrigger !== undefined && item.menuTrigger !== 'context') {
|
|
66
|
+
warned.add(item.id);
|
|
67
|
+
console.warn(`Item "${item.id}" switches to workspace "${item.workspace}" and asks for its menu on ` +
|
|
68
|
+
`activation — activating it is the switch, so the menu "${item.menu}" stays on the ` +
|
|
69
|
+
`right-click.`);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (menuOnActivate(item) && (item.command !== undefined || item.run !== undefined)) {
|
|
73
|
+
warned.add(item.id);
|
|
74
|
+
console.warn(`Item "${item.id}" opens the menu "${item.menu}" on activation, so its ` +
|
|
75
|
+
`${item.command === undefined ? 'inline behaviour' : `command "${item.command}"`} is ` +
|
|
76
|
+
`never run from here. Reach it from a menu entry, a shortcut or the palette instead.`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
46
80
|
const PRIMARY_PANE = 'main';
|
|
47
81
|
const VIEW_PANE_PREFIX = 'view:';
|
|
48
82
|
const CONTENT_DOCK = 'content';
|
|
@@ -2495,8 +2529,24 @@ function reflectAttribute(element, name, value) {
|
|
|
2495
2529
|
const LW_MENU_TAG = 'lw-menu';
|
|
2496
2530
|
const LW_MENU_ITEM_TAG = 'lw-menu-item';
|
|
2497
2531
|
const VIEWPORT_MARGIN$1 = 4;
|
|
2532
|
+
const MENU_ANCHOR_GAP = 4;
|
|
2498
2533
|
const LW_MENU_SELECT = 'lw-menu-select';
|
|
2499
2534
|
const LW_MENU_DISMISS = 'lw-menu-dismiss';
|
|
2535
|
+
function fits(start, size, limit) {
|
|
2536
|
+
return start >= VIEWPORT_MARGIN$1 && start + size <= limit - VIEWPORT_MARGIN$1;
|
|
2537
|
+
}
|
|
2538
|
+
function clamp(start, size, limit) {
|
|
2539
|
+
return Math.max(VIEWPORT_MARGIN$1, Math.min(start, limit - size - VIEWPORT_MARGIN$1));
|
|
2540
|
+
}
|
|
2541
|
+
function beside(preferred, opposite, size, limit) {
|
|
2542
|
+
if (fits(preferred, size, limit)) {
|
|
2543
|
+
return preferred;
|
|
2544
|
+
}
|
|
2545
|
+
return fits(opposite, size, limit) ? opposite : clamp(preferred, size, limit);
|
|
2546
|
+
}
|
|
2547
|
+
function aligned(near, far, size, limit) {
|
|
2548
|
+
return fits(near, size, limit) ? near : clamp(far - size, size, limit);
|
|
2549
|
+
}
|
|
2500
2550
|
class LwMenuItemElement extends HTMLElement {
|
|
2501
2551
|
static observedAttributes = [
|
|
2502
2552
|
'label',
|
|
@@ -2590,10 +2640,26 @@ class LwMenuElement extends HTMLElement {
|
|
|
2590
2640
|
}
|
|
2591
2641
|
openAt(x, y) {
|
|
2592
2642
|
const { width, height } = this.getBoundingClientRect();
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2643
|
+
this.place(clamp(x, width, window.innerWidth), clamp(y, height, window.innerHeight));
|
|
2644
|
+
}
|
|
2645
|
+
openBeside(rect, side) {
|
|
2646
|
+
const { width, height } = this.getBoundingClientRect();
|
|
2647
|
+
const viewportWidth = window.innerWidth;
|
|
2648
|
+
const viewportHeight = window.innerHeight;
|
|
2649
|
+
const after = { x: rect.right + MENU_ANCHOR_GAP, y: rect.bottom + MENU_ANCHOR_GAP };
|
|
2650
|
+
const before = {
|
|
2651
|
+
x: rect.left - MENU_ANCHOR_GAP - width,
|
|
2652
|
+
y: rect.top - MENU_ANCHOR_GAP - height,
|
|
2653
|
+
};
|
|
2654
|
+
if (side === 'left' || side === 'right') {
|
|
2655
|
+
const preferred = side === 'right' ? after.x : before.x;
|
|
2656
|
+
const opposite = side === 'right' ? before.x : after.x;
|
|
2657
|
+
this.place(beside(preferred, opposite, width, viewportWidth), aligned(rect.top, rect.bottom, height, viewportHeight));
|
|
2658
|
+
return;
|
|
2659
|
+
}
|
|
2660
|
+
const preferred = side === 'bottom' ? after.y : before.y;
|
|
2661
|
+
const opposite = side === 'bottom' ? before.y : after.y;
|
|
2662
|
+
this.place(aligned(rect.left, rect.right, width, viewportWidth), beside(preferred, opposite, height, viewportHeight));
|
|
2597
2663
|
}
|
|
2598
2664
|
onKeydown = (event) => this.handleKeydown(event);
|
|
2599
2665
|
onClick = (event) => {
|
|
@@ -2602,6 +2668,10 @@ class LwMenuElement extends HTMLElement {
|
|
|
2602
2668
|
this.select(item);
|
|
2603
2669
|
}
|
|
2604
2670
|
};
|
|
2671
|
+
place(left, top) {
|
|
2672
|
+
this.style.left = `${left}px`;
|
|
2673
|
+
this.style.top = `${top}px`;
|
|
2674
|
+
}
|
|
2605
2675
|
items() {
|
|
2606
2676
|
return [...this.querySelectorAll('[role^="menuitem"]')].filter((item) => !this.isDisabled(item));
|
|
2607
2677
|
}
|
|
@@ -2678,28 +2748,30 @@ function defineLwMenu() {
|
|
|
2678
2748
|
}
|
|
2679
2749
|
}
|
|
2680
2750
|
|
|
2681
|
-
const MENU_ANCHOR_GAP = 4;
|
|
2682
2751
|
class MenuService {
|
|
2683
2752
|
registry = inject(ContributionRegistry);
|
|
2684
2753
|
commands = inject(CommandService);
|
|
2685
2754
|
transloco = inject(TranslocoService);
|
|
2755
|
+
trigger = signal(null, /* @ts-ignore */
|
|
2756
|
+
...(ngDevMode ? [{ debugName: "trigger" }] : /* istanbul ignore next */ []));
|
|
2686
2757
|
current;
|
|
2687
|
-
|
|
2758
|
+
openTrigger = this.trigger.asReadonly();
|
|
2759
|
+
open(menuId, context, at, options = {}) {
|
|
2688
2760
|
this.close();
|
|
2689
2761
|
const resolved = this.resolve(typeof menuId === 'string' ? [menuId] : menuId, context);
|
|
2690
2762
|
if (resolved.length === 0) {
|
|
2691
2763
|
return;
|
|
2692
2764
|
}
|
|
2693
|
-
const menu = this.createMenu(resolved);
|
|
2765
|
+
const menu = this.createMenu(resolved, options.header);
|
|
2694
2766
|
const byKey = new Map(resolved.map((entry) => [entry.key, entry.item]));
|
|
2695
2767
|
this.present(menu, at, (key) => {
|
|
2696
2768
|
const item = key === null ? undefined : byKey.get(key);
|
|
2697
2769
|
if (item) {
|
|
2698
2770
|
this.run(item, context);
|
|
2699
2771
|
}
|
|
2700
|
-
});
|
|
2772
|
+
}, options.trigger);
|
|
2701
2773
|
}
|
|
2702
|
-
openList(entries, at, onPick) {
|
|
2774
|
+
openList(entries, at, onPick, trigger) {
|
|
2703
2775
|
this.close();
|
|
2704
2776
|
if (entries.length === 0) {
|
|
2705
2777
|
return;
|
|
@@ -2709,7 +2781,7 @@ class MenuService {
|
|
|
2709
2781
|
if (key !== null) {
|
|
2710
2782
|
onPick(key);
|
|
2711
2783
|
}
|
|
2712
|
-
});
|
|
2784
|
+
}, trigger);
|
|
2713
2785
|
}
|
|
2714
2786
|
close() {
|
|
2715
2787
|
const open = this.current;
|
|
@@ -2717,13 +2789,14 @@ class MenuService {
|
|
|
2717
2789
|
return;
|
|
2718
2790
|
}
|
|
2719
2791
|
this.current = undefined;
|
|
2792
|
+
this.trigger.set(null);
|
|
2720
2793
|
clearTimeout(open.listenTimer);
|
|
2721
2794
|
document.removeEventListener('pointerdown', open.onOutside, true);
|
|
2722
2795
|
document.body.classList.remove('lw-menu-open');
|
|
2723
2796
|
open.menu.remove();
|
|
2724
2797
|
open.restore?.focus?.();
|
|
2725
2798
|
}
|
|
2726
|
-
present(menu, at, onSelect) {
|
|
2799
|
+
present(menu, at, onSelect, trigger) {
|
|
2727
2800
|
const restore = document.activeElement;
|
|
2728
2801
|
menu.addEventListener(LW_MENU_SELECT, (event) => {
|
|
2729
2802
|
const key = event.detail
|
|
@@ -2739,7 +2812,13 @@ class MenuService {
|
|
|
2739
2812
|
};
|
|
2740
2813
|
document.body.append(menu);
|
|
2741
2814
|
document.body.classList.add('lw-menu-open');
|
|
2742
|
-
|
|
2815
|
+
if ('rect' in at) {
|
|
2816
|
+
menu.openBeside(at.rect, at.side);
|
|
2817
|
+
}
|
|
2818
|
+
else {
|
|
2819
|
+
menu.openAt(at.x, at.y);
|
|
2820
|
+
}
|
|
2821
|
+
this.trigger.set(trigger ?? null);
|
|
2743
2822
|
const listenTimer = setTimeout(() => document.addEventListener('pointerdown', onOutside, { capture: true }), 0);
|
|
2744
2823
|
this.current = { menu, onOutside, restore, listenTimer };
|
|
2745
2824
|
}
|
|
@@ -2775,11 +2854,14 @@ class MenuService {
|
|
|
2775
2854
|
.filter((entry) => entry !== null)
|
|
2776
2855
|
.toSorted((a, b) => a.group.localeCompare(b.group) || a.order - b.order);
|
|
2777
2856
|
}
|
|
2778
|
-
createMenu(resolved) {
|
|
2857
|
+
createMenu(resolved, header) {
|
|
2779
2858
|
const menu = document.createElement(LW_MENU_TAG);
|
|
2780
2859
|
if (resolved.some((entry) => entry.icon || entry.checkbox)) {
|
|
2781
2860
|
menu.classList.add('lw-menu--leading');
|
|
2782
2861
|
}
|
|
2862
|
+
if (header) {
|
|
2863
|
+
menu.append(this.createHeader(header, menu));
|
|
2864
|
+
}
|
|
2783
2865
|
let lastGroup;
|
|
2784
2866
|
for (const entry of resolved) {
|
|
2785
2867
|
if (lastGroup !== undefined && entry.group !== lastGroup) {
|
|
@@ -2808,6 +2890,66 @@ class MenuService {
|
|
|
2808
2890
|
}
|
|
2809
2891
|
return menu;
|
|
2810
2892
|
}
|
|
2893
|
+
createHeader(header, menu) {
|
|
2894
|
+
const title = this.transloco.translate(header.title);
|
|
2895
|
+
const detail = header.detail
|
|
2896
|
+
? this.transloco.translate(header.detail)
|
|
2897
|
+
: undefined;
|
|
2898
|
+
menu.setAttribute('aria-label', detail ? `${title}, ${detail}` : title);
|
|
2899
|
+
const element = document.createElement('div');
|
|
2900
|
+
element.className = 'lw-menu-header';
|
|
2901
|
+
element.setAttribute('aria-hidden', 'true');
|
|
2902
|
+
const mark = this.createHeaderMark(header);
|
|
2903
|
+
if (mark) {
|
|
2904
|
+
element.append(mark);
|
|
2905
|
+
}
|
|
2906
|
+
const lines = document.createElement('span');
|
|
2907
|
+
lines.className = 'lw-menu-header-lines';
|
|
2908
|
+
const name = document.createElement('span');
|
|
2909
|
+
name.className = 'lw-menu-header-title';
|
|
2910
|
+
name.textContent = title;
|
|
2911
|
+
lines.append(name);
|
|
2912
|
+
if (detail) {
|
|
2913
|
+
const second = document.createElement('span');
|
|
2914
|
+
second.className = 'lw-menu-header-detail';
|
|
2915
|
+
second.textContent = detail;
|
|
2916
|
+
lines.append(second);
|
|
2917
|
+
}
|
|
2918
|
+
element.append(lines);
|
|
2919
|
+
return element;
|
|
2920
|
+
}
|
|
2921
|
+
createHeaderMark(header) {
|
|
2922
|
+
if (!header.image && !header.initials && !header.icon) {
|
|
2923
|
+
return undefined;
|
|
2924
|
+
}
|
|
2925
|
+
const mark = document.createElement('span');
|
|
2926
|
+
mark.className = 'lw-menu-header-mark';
|
|
2927
|
+
mark.append(...this.markContent(header));
|
|
2928
|
+
if (header.image) {
|
|
2929
|
+
const picture = mark.firstElementChild;
|
|
2930
|
+
picture.addEventListener('error', () => mark.replaceChildren(...this.markContent({ ...header, image: undefined })));
|
|
2931
|
+
}
|
|
2932
|
+
return mark;
|
|
2933
|
+
}
|
|
2934
|
+
markContent(header) {
|
|
2935
|
+
if (header.image) {
|
|
2936
|
+
const picture = document.createElement('img');
|
|
2937
|
+
picture.src = header.image;
|
|
2938
|
+
picture.alt = '';
|
|
2939
|
+
picture.className = 'lw-menu-header-picture';
|
|
2940
|
+
return [picture];
|
|
2941
|
+
}
|
|
2942
|
+
if (header.initials) {
|
|
2943
|
+
return [document.createTextNode(header.initials)];
|
|
2944
|
+
}
|
|
2945
|
+
if (header.icon) {
|
|
2946
|
+
const icon = document.createElement('lw-icon');
|
|
2947
|
+
icon.setAttribute('name', header.icon);
|
|
2948
|
+
icon.setAttribute('size', '1rem');
|
|
2949
|
+
return [icon];
|
|
2950
|
+
}
|
|
2951
|
+
return [];
|
|
2952
|
+
}
|
|
2811
2953
|
createListMenu(entries) {
|
|
2812
2954
|
const menu = document.createElement(LW_MENU_TAG);
|
|
2813
2955
|
if (entries.some((entry) => entry.icon || entry.active || entry.checked !== undefined)) {
|
|
@@ -2859,35 +3001,74 @@ function whenMatches(when, context) {
|
|
|
2859
3001
|
return Object.entries(when).every(([key, value]) => context[key] === value);
|
|
2860
3002
|
}
|
|
2861
3003
|
|
|
2862
|
-
|
|
3004
|
+
function names(slots) {
|
|
3005
|
+
return slots !== undefined && slots.length > 0;
|
|
3006
|
+
}
|
|
3007
|
+
class MenuTriggerDirective {
|
|
2863
3008
|
menus = inject(MenuService);
|
|
2864
|
-
|
|
2865
|
-
|
|
3009
|
+
host = inject(ElementRef);
|
|
3010
|
+
menu = input(undefined, { ...(ngDevMode ? { debugName: "menu" } : /* istanbul ignore next */ {}), alias: 'lwMenu' });
|
|
3011
|
+
onActivateMenu = input(undefined, { ...(ngDevMode ? { debugName: "onActivateMenu" } : /* istanbul ignore next */ {}), alias: 'lwMenuOnActivate' });
|
|
3012
|
+
context = input({}, { ...(ngDevMode ? { debugName: "context" } : /* istanbul ignore next */ {}), alias: 'lwMenuContext' });
|
|
3013
|
+
side = input('bottom', { ...(ngDevMode ? { debugName: "side" } : /* istanbul ignore next */ {}), alias: 'lwMenuSide' });
|
|
3014
|
+
header = input(undefined, { ...(ngDevMode ? { debugName: "header" } : /* istanbul ignore next */ {}), alias: 'lwMenuHeader' });
|
|
3015
|
+
state = input(false, { ...(ngDevMode ? { debugName: "state" } : /* istanbul ignore next */ {}), alias: 'lwMenuState',
|
|
3016
|
+
transform: booleanAttribute });
|
|
3017
|
+
announces = computed(() => this.state() || names(this.onActivateMenu()), /* @ts-ignore */
|
|
3018
|
+
...(ngDevMode ? [{ debugName: "announces" }] : /* istanbul ignore next */ []));
|
|
3019
|
+
hasPopup = computed(() => this.announces() ? 'menu' : null, /* @ts-ignore */
|
|
3020
|
+
...(ngDevMode ? [{ debugName: "hasPopup" }] : /* istanbul ignore next */ []));
|
|
3021
|
+
expanded = computed(() => this.announces()
|
|
3022
|
+
? String(this.menus.openTrigger() === this.host.nativeElement)
|
|
3023
|
+
: null, /* @ts-ignore */
|
|
3024
|
+
...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
|
|
2866
3025
|
onContextMenu(event) {
|
|
2867
|
-
const
|
|
2868
|
-
if (!
|
|
3026
|
+
const slots = this.menu();
|
|
3027
|
+
if (!names(slots)) {
|
|
2869
3028
|
return;
|
|
2870
3029
|
}
|
|
2871
3030
|
event.preventDefault();
|
|
2872
3031
|
event.stopPropagation();
|
|
2873
|
-
this.menus.open(
|
|
3032
|
+
this.menus.open(slots, this.context(), {
|
|
2874
3033
|
x: event.clientX,
|
|
2875
3034
|
y: event.clientY,
|
|
2876
3035
|
});
|
|
2877
3036
|
}
|
|
2878
|
-
|
|
2879
|
-
|
|
3037
|
+
onActivate(event) {
|
|
3038
|
+
const slots = this.onActivateMenu();
|
|
3039
|
+
if (!names(slots)) {
|
|
3040
|
+
return;
|
|
3041
|
+
}
|
|
3042
|
+
event.preventDefault();
|
|
3043
|
+
event.stopPropagation();
|
|
3044
|
+
const control = this.host.nativeElement;
|
|
3045
|
+
this.menus.open(slots, this.context(), { rect: control.getBoundingClientRect(), side: this.side() }, { trigger: control, header: this.header() });
|
|
3046
|
+
}
|
|
3047
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: MenuTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
3048
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.0", type: MenuTriggerDirective, isStandalone: true, selector: "[lwMenu], [lwMenuOnActivate], [lwMenuState]", inputs: { menu: { classPropertyName: "menu", publicName: "lwMenu", isSignal: true, isRequired: false, transformFunction: null }, onActivateMenu: { classPropertyName: "onActivateMenu", publicName: "lwMenuOnActivate", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "lwMenuContext", isSignal: true, isRequired: false, transformFunction: null }, side: { classPropertyName: "side", publicName: "lwMenuSide", isSignal: true, isRequired: false, transformFunction: null }, header: { classPropertyName: "header", publicName: "lwMenuHeader", isSignal: true, isRequired: false, transformFunction: null }, state: { classPropertyName: "state", publicName: "lwMenuState", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "contextmenu": "onContextMenu($event)", "click": "onActivate($event)" }, properties: { "attr.aria-haspopup": "hasPopup()", "attr.aria-expanded": "expanded()" } }, ngImport: i0 });
|
|
2880
3049
|
}
|
|
2881
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type:
|
|
3050
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: MenuTriggerDirective, decorators: [{
|
|
2882
3051
|
type: Directive,
|
|
2883
3052
|
args: [{
|
|
2884
|
-
selector: '[
|
|
2885
|
-
host: {
|
|
3053
|
+
selector: '[lwMenu], [lwMenuOnActivate], [lwMenuState]',
|
|
3054
|
+
host: {
|
|
3055
|
+
'(contextmenu)': 'onContextMenu($event)',
|
|
3056
|
+
'(click)': 'onActivate($event)',
|
|
3057
|
+
'[attr.aria-haspopup]': 'hasPopup()',
|
|
3058
|
+
'[attr.aria-expanded]': 'expanded()',
|
|
3059
|
+
},
|
|
2886
3060
|
}]
|
|
2887
|
-
}], propDecorators: { menu: [{ type: i0.Input, args: [{ isSignal: true, alias: "
|
|
3061
|
+
}], propDecorators: { menu: [{ type: i0.Input, args: [{ isSignal: true, alias: "lwMenu", required: false }] }], onActivateMenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "lwMenuOnActivate", required: false }] }], context: [{ type: i0.Input, args: [{ isSignal: true, alias: "lwMenuContext", required: false }] }], side: [{ type: i0.Input, args: [{ isSignal: true, alias: "lwMenuSide", required: false }] }], header: [{ type: i0.Input, args: [{ isSignal: true, alias: "lwMenuHeader", required: false }] }], state: [{ type: i0.Input, args: [{ isSignal: true, alias: "lwMenuState", required: false }] }] } });
|
|
2888
3062
|
|
|
2889
3063
|
const BAR_CONTEXT = new InjectionToken('BAR_CONTEXT');
|
|
2890
3064
|
|
|
3065
|
+
const MENU_SIDE_BY_DOCK = {
|
|
3066
|
+
top: 'bottom',
|
|
3067
|
+
bottom: 'top',
|
|
3068
|
+
left: 'right',
|
|
3069
|
+
right: 'left',
|
|
3070
|
+
center: 'bottom',
|
|
3071
|
+
};
|
|
2891
3072
|
class ShellBarItem {
|
|
2892
3073
|
item = input.required(/* @ts-ignore */
|
|
2893
3074
|
...(ngDevMode ? [{ debugName: "item" }] : /* istanbul ignore next */ []));
|
|
@@ -2906,8 +3087,22 @@ class ShellBarItem {
|
|
|
2906
3087
|
return 'component' in item ? null : item;
|
|
2907
3088
|
}, /* @ts-ignore */
|
|
2908
3089
|
...(ngDevMode ? [{ debugName: "asButton" }] : /* istanbul ignore next */ []));
|
|
3090
|
+
brokenPicture = signal(false, /* @ts-ignore */
|
|
3091
|
+
...(ngDevMode ? [{ debugName: "brokenPicture" }] : /* istanbul ignore next */ []));
|
|
2909
3092
|
tooltipPosition = computed(() => this.dock() === 'bottom' ? 'top' : 'bottom', /* @ts-ignore */
|
|
2910
3093
|
...(ngDevMode ? [{ debugName: "tooltipPosition" }] : /* istanbul ignore next */ []));
|
|
3094
|
+
menuSide = computed(() => MENU_SIDE_BY_DOCK[this.dock()], /* @ts-ignore */
|
|
3095
|
+
...(ngDevMode ? [{ debugName: "menuSide" }] : /* istanbul ignore next */ []));
|
|
3096
|
+
contextMenu = computed(() => {
|
|
3097
|
+
const button = this.asButton();
|
|
3098
|
+
return button ? menuOnContext(button) : undefined;
|
|
3099
|
+
}, /* @ts-ignore */
|
|
3100
|
+
...(ngDevMode ? [{ debugName: "contextMenu" }] : /* istanbul ignore next */ []));
|
|
3101
|
+
activateMenu = computed(() => {
|
|
3102
|
+
const button = this.asButton();
|
|
3103
|
+
return button ? menuOnActivate(button) : undefined;
|
|
3104
|
+
}, /* @ts-ignore */
|
|
3105
|
+
...(ngDevMode ? [{ debugName: "activateMenu" }] : /* istanbul ignore next */ []));
|
|
2911
3106
|
componentInjector = computed(() => {
|
|
2912
3107
|
const item = this.item();
|
|
2913
3108
|
return Injector.create({
|
|
@@ -2931,17 +3126,27 @@ class ShellBarItem {
|
|
|
2931
3126
|
return this.commands.shortcutOf(this.commands.commands().find((entry) => entry.id === button.command));
|
|
2932
3127
|
}, /* @ts-ignore */
|
|
2933
3128
|
...(ngDevMode ? [{ debugName: "shortcut" }] : /* istanbul ignore next */ []));
|
|
3129
|
+
pictureOf(button) {
|
|
3130
|
+
return this.brokenPicture() ? undefined : button.image;
|
|
3131
|
+
}
|
|
3132
|
+
onPictureError() {
|
|
3133
|
+
this.brokenPicture.set(true);
|
|
3134
|
+
}
|
|
2934
3135
|
run(button) {
|
|
2935
3136
|
if (this.disabled())
|
|
2936
3137
|
return;
|
|
3138
|
+
warnMenuTriggerConflict(button);
|
|
3139
|
+
if (menuOnActivate(button)) {
|
|
3140
|
+
return;
|
|
3141
|
+
}
|
|
2937
3142
|
this.commands.trigger(button);
|
|
2938
3143
|
}
|
|
2939
3144
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: ShellBarItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2940
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: ShellBarItem, isStandalone: true, selector: "lw-shell-bar-item", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null }, dock: { classPropertyName: "dock", publicName: "dock", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "@if (asButton(); as btn) {\n <button\n type=\"button\"\n (click)=\"run(btn)\"\n [disabled]=\"disabled()\"\n [
|
|
3145
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: ShellBarItem, isStandalone: true, selector: "lw-shell-bar-item", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null }, dock: { classPropertyName: "dock", publicName: "dock", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "@if (asButton(); as btn) {\n <button\n type=\"button\"\n (click)=\"run(btn)\"\n [disabled]=\"disabled()\"\n [lwMenu]=\"contextMenu()\"\n [lwMenuOnActivate]=\"activateMenu()\"\n [lwMenuHeader]=\"btn.menuHeader\"\n [lwMenuSide]=\"menuSide()\"\n [lwMenuContext]=\"{ targetKind: 'bar-item', id: btn.id, bar: btn.bar }\"\n class=\"relative flex items-center gap-1 rounded px-1.5 py-0.5 text-content-faint transition-colors hover:bg-surface-overlay hover:text-content disabled:pointer-events-none disabled:opacity-40\"\n [attr.aria-label]=\"(btn.tooltip ?? btn.label ?? '') | transloco\"\n >\n @if (pictureOf(btn); as picture) {\n <img\n [src]=\"picture\"\n alt=\"\"\n aria-hidden=\"true\"\n data-testid=\"bar-picture\"\n class=\"lw-chrome-picture h-5 w-5\"\n (error)=\"onPictureError()\"\n />\n } @else if (btn.initials) {\n <span aria-hidden=\"true\" data-testid=\"bar-initials\" class=\"lw-rail-initials\">{{\n btn.initials\n }}</span>\n } @else if (btn.icon; as icon) {\n <lw-icon [name]=\"icon\" size=\"1rem\" />\n }\n @if (btn.label; as label) {\n <span>{{ label | transloco }}</span>\n }\n @if (shortcut(); as chord) {\n <kbd\n class=\"rounded border border-border bg-surface-overlay px-1 text-[0.6875rem] leading-tight text-content-muted\"\n >{{ chord }}</kbd\n >\n }\n @if (btn.tooltip ?? btn.label; as tip) {\n <lw-tooltip [text]=\"tip | transloco\" [position]=\"tooltipPosition()\" />\n }\n </button>\n} @else if (asComponent(); as comp) {\n <ng-container\n *ngComponentOutlet=\"comp.component; injector: componentInjector()\"\n ></ng-container>\n}\n", dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "directive", type: MenuTriggerDirective, selector: "[lwMenu], [lwMenuOnActivate], [lwMenuState]", inputs: ["lwMenu", "lwMenuOnActivate", "lwMenuContext", "lwMenuSide", "lwMenuHeader", "lwMenuState"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
|
|
2941
3146
|
}
|
|
2942
3147
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: ShellBarItem, decorators: [{
|
|
2943
3148
|
type: Component,
|
|
2944
|
-
args: [{ selector: 'lw-shell-bar-item', imports: [NgComponentOutlet, TranslocoPipe,
|
|
3149
|
+
args: [{ selector: 'lw-shell-bar-item', imports: [NgComponentOutlet, TranslocoPipe, MenuTriggerDirective], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "@if (asButton(); as btn) {\n <button\n type=\"button\"\n (click)=\"run(btn)\"\n [disabled]=\"disabled()\"\n [lwMenu]=\"contextMenu()\"\n [lwMenuOnActivate]=\"activateMenu()\"\n [lwMenuHeader]=\"btn.menuHeader\"\n [lwMenuSide]=\"menuSide()\"\n [lwMenuContext]=\"{ targetKind: 'bar-item', id: btn.id, bar: btn.bar }\"\n class=\"relative flex items-center gap-1 rounded px-1.5 py-0.5 text-content-faint transition-colors hover:bg-surface-overlay hover:text-content disabled:pointer-events-none disabled:opacity-40\"\n [attr.aria-label]=\"(btn.tooltip ?? btn.label ?? '') | transloco\"\n >\n @if (pictureOf(btn); as picture) {\n <img\n [src]=\"picture\"\n alt=\"\"\n aria-hidden=\"true\"\n data-testid=\"bar-picture\"\n class=\"lw-chrome-picture h-5 w-5\"\n (error)=\"onPictureError()\"\n />\n } @else if (btn.initials) {\n <span aria-hidden=\"true\" data-testid=\"bar-initials\" class=\"lw-rail-initials\">{{\n btn.initials\n }}</span>\n } @else if (btn.icon; as icon) {\n <lw-icon [name]=\"icon\" size=\"1rem\" />\n }\n @if (btn.label; as label) {\n <span>{{ label | transloco }}</span>\n }\n @if (shortcut(); as chord) {\n <kbd\n class=\"rounded border border-border bg-surface-overlay px-1 text-[0.6875rem] leading-tight text-content-muted\"\n >{{ chord }}</kbd\n >\n }\n @if (btn.tooltip ?? btn.label; as tip) {\n <lw-tooltip [text]=\"tip | transloco\" [position]=\"tooltipPosition()\" />\n }\n </button>\n} @else if (asComponent(); as comp) {\n <ng-container\n *ngComponentOutlet=\"comp.component; injector: componentInjector()\"\n ></ng-container>\n}\n" }]
|
|
2945
3150
|
}], propDecorators: { item: [{ type: i0.Input, args: [{ isSignal: true, alias: "item", required: true }] }], dock: [{ type: i0.Input, args: [{ isSignal: true, alias: "dock", required: true }] }] } });
|
|
2946
3151
|
|
|
2947
3152
|
class ShellBar {
|
|
@@ -2965,7 +3170,9 @@ class ShellBar {
|
|
|
2965
3170
|
.barItems()
|
|
2966
3171
|
.filter((item) => item.bar === this.region().id && item.slot === slot)
|
|
2967
3172
|
.filter((item) => this.auth.visible(item.access))
|
|
2968
|
-
.filter((item) => 'component' in item ||
|
|
3173
|
+
.filter((item) => 'component' in item ||
|
|
3174
|
+
menuOnActivate(item) !== undefined ||
|
|
3175
|
+
this.commands.triggerable(item))
|
|
2969
3176
|
.toSorted((a, b) => (a.order ?? 0) - (b.order ?? 0));
|
|
2970
3177
|
}
|
|
2971
3178
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: ShellBar, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
@@ -4300,6 +4507,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
4300
4507
|
type: Service
|
|
4301
4508
|
}], ctorParameters: () => [] });
|
|
4302
4509
|
|
|
4510
|
+
function popoutNavigationRefusal(path) {
|
|
4511
|
+
return (`Content navigation to "${path}" was ignored: this is a pop-out window, which shows one ` +
|
|
4512
|
+
`surface and has no content area to navigate. A command reaches a pop-out's palette only ` +
|
|
4513
|
+
`if it declares popout: true, so leave that off anything that navigates.`);
|
|
4514
|
+
}
|
|
4515
|
+
|
|
4303
4516
|
class OpenTabsService {
|
|
4304
4517
|
router = inject(Router);
|
|
4305
4518
|
registry = inject(ContributionRegistry);
|
|
@@ -4438,9 +4651,11 @@ class OpenTabsService {
|
|
|
4438
4651
|
this.paneTree.hydrated();
|
|
4439
4652
|
untracked(() => {
|
|
4440
4653
|
if (url !== this.lastUrl) {
|
|
4654
|
+
const previous = this.lastUrl;
|
|
4441
4655
|
this.lastUrl = url;
|
|
4442
4656
|
if (this.ownNavigation !== normalizePath(url)) {
|
|
4443
4657
|
this.viewTabSelection.set(null);
|
|
4658
|
+
this.focusHolderOf(path, this.rootFor(previous).root);
|
|
4444
4659
|
}
|
|
4445
4660
|
this.ownNavigation = null;
|
|
4446
4661
|
}
|
|
@@ -4459,14 +4674,12 @@ class OpenTabsService {
|
|
|
4459
4674
|
navigate(path) {
|
|
4460
4675
|
if (this.inPopout) {
|
|
4461
4676
|
if (isDevMode()) {
|
|
4462
|
-
console.warn(
|
|
4463
|
-
`surface and has no content area to navigate. A command reaches a pop-out's palette only ` +
|
|
4464
|
-
`if it declares popout: true, so leave that off anything that navigates.`);
|
|
4677
|
+
console.warn(popoutNavigationRefusal(path));
|
|
4465
4678
|
}
|
|
4466
4679
|
return Promise.resolve(false);
|
|
4467
4680
|
}
|
|
4468
4681
|
const target = normalizePath(path);
|
|
4469
|
-
this.focusHolderOf(target);
|
|
4682
|
+
this.focusHolderOf(target, this.activeTabRoot());
|
|
4470
4683
|
this.ownNavigation = target;
|
|
4471
4684
|
this.viewTabSelection.set(null);
|
|
4472
4685
|
return this.router.navigateByUrl('/' + target + suffixOf(path));
|
|
@@ -4522,7 +4735,7 @@ class OpenTabsService {
|
|
|
4522
4735
|
return (owner.rest === true ||
|
|
4523
4736
|
segmentsOf(owner.path).length === segmentsOf(address).length);
|
|
4524
4737
|
}
|
|
4525
|
-
focusHolderOf(target) {
|
|
4738
|
+
focusHolderOf(target, previousContent) {
|
|
4526
4739
|
const routes = this.registry.contentRoutes();
|
|
4527
4740
|
const root = tabRootOf(routes, target);
|
|
4528
4741
|
if (root === '') {
|
|
@@ -4540,7 +4753,7 @@ class OpenTabsService {
|
|
|
4540
4753
|
return;
|
|
4541
4754
|
}
|
|
4542
4755
|
this.paneTree.setActiveTab(CONTENT_DOCK, holder.id, held.path);
|
|
4543
|
-
this.paneTree.focusPane(CONTENT_DOCK, holder.id,
|
|
4756
|
+
this.paneTree.focusPane(CONTENT_DOCK, holder.id, previousContent);
|
|
4544
4757
|
}
|
|
4545
4758
|
stampActive(root) {
|
|
4546
4759
|
const next = new Map(this.lastActive());
|
|
@@ -6149,13 +6362,17 @@ class ShellRail {
|
|
|
6149
6362
|
...(ngDevMode ? [{ debugName: "connectedRails" }] : /* istanbul ignore next */ []));
|
|
6150
6363
|
labelKey = computed(() => this.region().dock === 'right' ? 'rail.labelRight' : 'rail.label', /* @ts-ignore */
|
|
6151
6364
|
...(ngDevMode ? [{ debugName: "labelKey" }] : /* istanbul ignore next */ []));
|
|
6365
|
+
menuSide = computed(() => this.region().dock === 'right' ? 'left' : 'right', /* @ts-ignore */
|
|
6366
|
+
...(ngDevMode ? [{ debugName: "menuSide" }] : /* istanbul ignore next */ []));
|
|
6152
6367
|
reorderable = this.features.reorder;
|
|
6153
6368
|
draggable = this.features.reorder || this.features.moveItems;
|
|
6154
6369
|
registered = computed(() => this.registry
|
|
6155
6370
|
.railItems()
|
|
6156
6371
|
.filter((item) => this.railItems.regionOf(item.id, item.rail) === this.region().id)
|
|
6157
6372
|
.filter((item) => this.auth.visible(item.access))
|
|
6158
|
-
.filter((item) => item.workspace !== undefined ||
|
|
6373
|
+
.filter((item) => item.workspace !== undefined ||
|
|
6374
|
+
menuOnActivate(item) !== undefined ||
|
|
6375
|
+
this.commands.triggerable(item))
|
|
6159
6376
|
.toSorted((a, b) => (a.order ?? 0) - (b.order ?? 0)), /* @ts-ignore */
|
|
6160
6377
|
...(ngDevMode ? [{ debugName: "registered" }] : /* istanbul ignore next */ []));
|
|
6161
6378
|
items = computed(() => {
|
|
@@ -6168,16 +6385,26 @@ class ShellRail {
|
|
|
6168
6385
|
return [...top, ...bottom];
|
|
6169
6386
|
}, /* @ts-ignore */
|
|
6170
6387
|
...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
6388
|
+
brokenPictures = signal(new Set(), /* @ts-ignore */
|
|
6389
|
+
...(ngDevMode ? [{ debugName: "brokenPictures" }] : /* istanbul ignore next */ []));
|
|
6171
6390
|
firstBottomId = computed(() => this.items().find((item) => item.anchor === 'bottom')?.id, /* @ts-ignore */
|
|
6172
6391
|
...(ngDevMode ? [{ debugName: "firstBottomId" }] : /* istanbul ignore next */ []));
|
|
6173
6392
|
enterPredicate = (_drag, list) => list.id === this.dropListId() ? this.reorderable : this.features.moveItems;
|
|
6393
|
+
pictureOf(item) {
|
|
6394
|
+
return this.brokenPictures().has(item.id) ? undefined : item.image;
|
|
6395
|
+
}
|
|
6396
|
+
onPictureError(item) {
|
|
6397
|
+
this.brokenPictures.update((broken) => new Set(broken).add(item.id));
|
|
6398
|
+
}
|
|
6174
6399
|
disabled(item) {
|
|
6175
6400
|
return this.auth.disabled(item.access);
|
|
6176
6401
|
}
|
|
6177
6402
|
menusFor(item) {
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
|
|
6403
|
+
const own = menuOnContext(item);
|
|
6404
|
+
return own ? [RAIL_ITEM_CONTEXT_MENU, own] : [RAIL_ITEM_CONTEXT_MENU];
|
|
6405
|
+
}
|
|
6406
|
+
activateMenuFor(item) {
|
|
6407
|
+
return menuOnActivate(item);
|
|
6181
6408
|
}
|
|
6182
6409
|
onKeydown(event) {
|
|
6183
6410
|
const dock = this.dockForChord(event);
|
|
@@ -6199,6 +6426,10 @@ class ShellRail {
|
|
|
6199
6426
|
run(item) {
|
|
6200
6427
|
if (this.disabled(item))
|
|
6201
6428
|
return;
|
|
6429
|
+
warnMenuTriggerConflict(item);
|
|
6430
|
+
if (menuOnActivate(item)) {
|
|
6431
|
+
return;
|
|
6432
|
+
}
|
|
6202
6433
|
const workspace = item.workspace;
|
|
6203
6434
|
if (workspace !== undefined) {
|
|
6204
6435
|
void this.workspaces.switchTo(workspace);
|
|
@@ -6236,7 +6467,7 @@ class ShellRail {
|
|
|
6236
6467
|
return event.key === 'ArrowLeft' ? 'left' : null;
|
|
6237
6468
|
}
|
|
6238
6469
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: ShellRail, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6239
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: ShellRail, isStandalone: true, selector: "lw-shell-rail", inputs: { region: { classPropertyName: "region", publicName: "region", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<nav\n class=\"flex h-full w-10 shrink-0 flex-col items-center gap-1 bg-surface py-2\"\n [attr.aria-label]=\"labelKey() | transloco\"\n cdkDropList\n cdkDropListOrientation=\"vertical\"\n [id]=\"dropListId()\"\n [cdkDropListConnectedTo]=\"connectedRails()\"\n [cdkDropListDisabled]=\"!draggable\"\n [cdkDropListSortingDisabled]=\"!reorderable\"\n [cdkDropListEnterPredicate]=\"enterPredicate\"\n [cdkDropListSortPredicate]=\"sortPredicate\"\n (cdkDropListDropped)=\"onDrop($event)\"\n [lwReorderable]=\"containerId()\"\n [lwReorderableEnabled]=\"reorderable\"\n (reorder)=\"onReorder($event)\"\n [
|
|
6470
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: ShellRail, isStandalone: true, selector: "lw-shell-rail", inputs: { region: { classPropertyName: "region", publicName: "region", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<nav\n class=\"flex h-full w-10 shrink-0 flex-col items-center gap-1 bg-surface py-2\"\n [attr.aria-label]=\"labelKey() | transloco\"\n cdkDropList\n cdkDropListOrientation=\"vertical\"\n [id]=\"dropListId()\"\n [cdkDropListConnectedTo]=\"connectedRails()\"\n [cdkDropListDisabled]=\"!draggable\"\n [cdkDropListSortingDisabled]=\"!reorderable\"\n [cdkDropListEnterPredicate]=\"enterPredicate\"\n [cdkDropListSortPredicate]=\"sortPredicate\"\n (cdkDropListDropped)=\"onDrop($event)\"\n [lwReorderable]=\"containerId()\"\n [lwReorderableEnabled]=\"reorderable\"\n (reorder)=\"onReorder($event)\"\n [lwMenu]=\"railMenu\"\n>\n @for (item of items(); track item.id) {\n <button\n type=\"button\"\n cdkDrag\n [cdkDragData]=\"item.id\"\n [cdkDragDisabled]=\"!draggable\"\n [disabled]=\"disabled(item)\"\n (click)=\"run(item)\"\n (keydown)=\"onKeydown($event)\"\n [lwMenu]=\"menusFor(item)\"\n [lwMenuOnActivate]=\"activateMenuFor(item)\"\n [lwMenuHeader]=\"item.menuHeader\"\n [lwMenuSide]=\"menuSide()\"\n [lwMenuContext]=\"{ targetKind: 'rail-item', id: item.id, region: region().id }\"\n [attr.aria-label]=\"item.title | transloco\"\n [attr.aria-current]=\"current(item) ? 'true' : null\"\n [attr.data-rail-item]=\"item.id\"\n [attr.data-reorder-id]=\"reorderable ? item.id : null\"\n [attr.data-reorder-band]=\"item.anchor ?? 'top'\"\n [class.mt-auto]=\"item.id === firstBottomId()\"\n [class.text-content]=\"current(item)\"\n [class.bg-surface-overlay]=\"current(item)\"\n class=\"relative flex h-9 w-9 items-center justify-center rounded-lg text-content-faint transition-colors hover:bg-surface-overlay hover:text-content disabled:pointer-events-none disabled:opacity-40\"\n >\n @if (current(item)) {\n <span\n aria-hidden=\"true\"\n class=\"absolute inset-y-1 w-0.5 rounded-full bg-brand\"\n [class.left-0]=\"region().dock !== 'right'\"\n [class.right-0]=\"region().dock === 'right'\"\n ></span>\n }\n @if (pictureOf(item); as picture) {\n <img\n [src]=\"picture\"\n alt=\"\"\n aria-hidden=\"true\"\n data-testid=\"rail-picture\"\n class=\"lw-chrome-picture h-6 w-6\"\n (error)=\"onPictureError(item)\"\n />\n } @else if (item.initials) {\n <span\n aria-hidden=\"true\"\n data-testid=\"rail-initials\"\n class=\"lw-rail-initials\"\n >{{ item.initials }}</span\n >\n } @else {\n <lw-icon [name]=\"item.icon\" size=\"1rem\" />\n }\n <lw-tooltip [text]=\"item.title | transloco\" [position]=\"region().dock === 'right' ? 'left' : 'right'\" />\n </button>\n }\n</nav>\n", dependencies: [{ kind: "directive", type: Reorderable, selector: "[lwReorderable]", inputs: ["lwReorderable", "lwReorderableEnabled"], outputs: ["reorder"] }, { kind: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: MenuTriggerDirective, selector: "[lwMenu], [lwMenuOnActivate], [lwMenuState]", inputs: ["lwMenu", "lwMenuOnActivate", "lwMenuContext", "lwMenuSide", "lwMenuHeader", "lwMenuState"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
|
|
6240
6471
|
}
|
|
6241
6472
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: ShellRail, decorators: [{
|
|
6242
6473
|
type: Component,
|
|
@@ -6245,8 +6476,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
6245
6476
|
Reorderable,
|
|
6246
6477
|
CdkDropList,
|
|
6247
6478
|
CdkDrag,
|
|
6248
|
-
|
|
6249
|
-
], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "<nav\n class=\"flex h-full w-10 shrink-0 flex-col items-center gap-1 bg-surface py-2\"\n [attr.aria-label]=\"labelKey() | transloco\"\n cdkDropList\n cdkDropListOrientation=\"vertical\"\n [id]=\"dropListId()\"\n [cdkDropListConnectedTo]=\"connectedRails()\"\n [cdkDropListDisabled]=\"!draggable\"\n [cdkDropListSortingDisabled]=\"!reorderable\"\n [cdkDropListEnterPredicate]=\"enterPredicate\"\n [cdkDropListSortPredicate]=\"sortPredicate\"\n (cdkDropListDropped)=\"onDrop($event)\"\n [lwReorderable]=\"containerId()\"\n [lwReorderableEnabled]=\"reorderable\"\n (reorder)=\"onReorder($event)\"\n [
|
|
6479
|
+
MenuTriggerDirective,
|
|
6480
|
+
], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "<nav\n class=\"flex h-full w-10 shrink-0 flex-col items-center gap-1 bg-surface py-2\"\n [attr.aria-label]=\"labelKey() | transloco\"\n cdkDropList\n cdkDropListOrientation=\"vertical\"\n [id]=\"dropListId()\"\n [cdkDropListConnectedTo]=\"connectedRails()\"\n [cdkDropListDisabled]=\"!draggable\"\n [cdkDropListSortingDisabled]=\"!reorderable\"\n [cdkDropListEnterPredicate]=\"enterPredicate\"\n [cdkDropListSortPredicate]=\"sortPredicate\"\n (cdkDropListDropped)=\"onDrop($event)\"\n [lwReorderable]=\"containerId()\"\n [lwReorderableEnabled]=\"reorderable\"\n (reorder)=\"onReorder($event)\"\n [lwMenu]=\"railMenu\"\n>\n @for (item of items(); track item.id) {\n <button\n type=\"button\"\n cdkDrag\n [cdkDragData]=\"item.id\"\n [cdkDragDisabled]=\"!draggable\"\n [disabled]=\"disabled(item)\"\n (click)=\"run(item)\"\n (keydown)=\"onKeydown($event)\"\n [lwMenu]=\"menusFor(item)\"\n [lwMenuOnActivate]=\"activateMenuFor(item)\"\n [lwMenuHeader]=\"item.menuHeader\"\n [lwMenuSide]=\"menuSide()\"\n [lwMenuContext]=\"{ targetKind: 'rail-item', id: item.id, region: region().id }\"\n [attr.aria-label]=\"item.title | transloco\"\n [attr.aria-current]=\"current(item) ? 'true' : null\"\n [attr.data-rail-item]=\"item.id\"\n [attr.data-reorder-id]=\"reorderable ? item.id : null\"\n [attr.data-reorder-band]=\"item.anchor ?? 'top'\"\n [class.mt-auto]=\"item.id === firstBottomId()\"\n [class.text-content]=\"current(item)\"\n [class.bg-surface-overlay]=\"current(item)\"\n class=\"relative flex h-9 w-9 items-center justify-center rounded-lg text-content-faint transition-colors hover:bg-surface-overlay hover:text-content disabled:pointer-events-none disabled:opacity-40\"\n >\n @if (current(item)) {\n <span\n aria-hidden=\"true\"\n class=\"absolute inset-y-1 w-0.5 rounded-full bg-brand\"\n [class.left-0]=\"region().dock !== 'right'\"\n [class.right-0]=\"region().dock === 'right'\"\n ></span>\n }\n @if (pictureOf(item); as picture) {\n <img\n [src]=\"picture\"\n alt=\"\"\n aria-hidden=\"true\"\n data-testid=\"rail-picture\"\n class=\"lw-chrome-picture h-6 w-6\"\n (error)=\"onPictureError(item)\"\n />\n } @else if (item.initials) {\n <span\n aria-hidden=\"true\"\n data-testid=\"rail-initials\"\n class=\"lw-rail-initials\"\n >{{ item.initials }}</span\n >\n } @else {\n <lw-icon [name]=\"item.icon\" size=\"1rem\" />\n }\n <lw-tooltip [text]=\"item.title | transloco\" [position]=\"region().dock === 'right' ? 'left' : 'right'\" />\n </button>\n }\n</nav>\n" }]
|
|
6250
6481
|
}], propDecorators: { region: [{ type: i0.Input, args: [{ isSignal: true, alias: "region", required: true }] }] } });
|
|
6251
6482
|
|
|
6252
6483
|
const STORAGE_PREFIX$2 = 'lw.shell.view-state:';
|
|
@@ -6561,8 +6792,9 @@ class ViewInstanceSwitcher {
|
|
|
6561
6792
|
if (!this.viewInstances.isDefault(viewId, activeId)) {
|
|
6562
6793
|
entries.push({ key: 'rename', label: t('viewInstance.rename') }, { key: 'delete', label: t('viewInstance.delete') });
|
|
6563
6794
|
}
|
|
6564
|
-
const
|
|
6565
|
-
|
|
6795
|
+
const control = event.currentTarget;
|
|
6796
|
+
const rect = control.getBoundingClientRect();
|
|
6797
|
+
this.menu.openList(entries, { x: rect.left, y: rect.bottom + MENU_ANCHOR_GAP }, (key) => this.onPick(key), control);
|
|
6566
6798
|
}
|
|
6567
6799
|
onPick(key) {
|
|
6568
6800
|
const viewId = this.view().id;
|
|
@@ -6635,11 +6867,11 @@ class ViewInstanceSwitcher {
|
|
|
6635
6867
|
};
|
|
6636
6868
|
}
|
|
6637
6869
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: ViewInstanceSwitcher, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6638
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.0", type: ViewInstanceSwitcher, isStandalone: true, selector: "lw-view-instance-switcher", inputs: { view: { classPropertyName: "view", publicName: "view", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { beforeSwitch: "beforeSwitch" }, host: { classAttribute: "flex min-w-0 flex-1" }, ngImport: i0, template: "<button\n type=\"button\"\n class=\"flex min-w-0 flex-1 items-center gap-1 truncate rounded px-1 py-0.5 text-left text-xs font-semibold tracking-wide text-content-faint uppercase transition-colors hover:bg-surface-overlay hover:text-content\"\n (click)=\"openSwitcher($event)\"\n [attr.aria-label]=\"'viewInstance.switcher' | transloco\"\n data-testid=\"view-switcher\"\n>\n <span class=\"truncate\">{{ activeName() || ('viewInstance.default' | transloco) }}</span>\n <lw-icon name=\"chevronDown\" size=\"0.85rem\" class=\"shrink-0\" />\n</button>\n", dependencies: [{ kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
|
|
6870
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.0", type: ViewInstanceSwitcher, isStandalone: true, selector: "lw-view-instance-switcher", inputs: { view: { classPropertyName: "view", publicName: "view", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { beforeSwitch: "beforeSwitch" }, host: { classAttribute: "flex min-w-0 flex-1" }, ngImport: i0, template: "<button\n type=\"button\"\n class=\"flex min-w-0 flex-1 items-center gap-1 truncate rounded px-1 py-0.5 text-left text-xs font-semibold tracking-wide text-content-faint uppercase transition-colors hover:bg-surface-overlay hover:text-content\"\n (click)=\"openSwitcher($event)\"\n lwMenuState\n [attr.aria-label]=\"'viewInstance.switcher' | transloco\"\n data-testid=\"view-switcher\"\n>\n <span class=\"truncate\">{{ activeName() || ('viewInstance.default' | transloco) }}</span>\n <lw-icon name=\"chevronDown\" size=\"0.85rem\" class=\"shrink-0\" />\n</button>\n", dependencies: [{ kind: "directive", type: MenuTriggerDirective, selector: "[lwMenu], [lwMenuOnActivate], [lwMenuState]", inputs: ["lwMenu", "lwMenuOnActivate", "lwMenuContext", "lwMenuSide", "lwMenuHeader", "lwMenuState"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
|
|
6639
6871
|
}
|
|
6640
6872
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: ViewInstanceSwitcher, decorators: [{
|
|
6641
6873
|
type: Component,
|
|
6642
|
-
args: [{ selector: 'lw-view-instance-switcher', imports: [TranslocoPipe], schemas: [CUSTOM_ELEMENTS_SCHEMA], host: { class: 'flex min-w-0 flex-1' }, template: "<button\n type=\"button\"\n class=\"flex min-w-0 flex-1 items-center gap-1 truncate rounded px-1 py-0.5 text-left text-xs font-semibold tracking-wide text-content-faint uppercase transition-colors hover:bg-surface-overlay hover:text-content\"\n (click)=\"openSwitcher($event)\"\n [attr.aria-label]=\"'viewInstance.switcher' | transloco\"\n data-testid=\"view-switcher\"\n>\n <span class=\"truncate\">{{ activeName() || ('viewInstance.default' | transloco) }}</span>\n <lw-icon name=\"chevronDown\" size=\"0.85rem\" class=\"shrink-0\" />\n</button>\n" }]
|
|
6874
|
+
args: [{ selector: 'lw-view-instance-switcher', imports: [TranslocoPipe, MenuTriggerDirective], schemas: [CUSTOM_ELEMENTS_SCHEMA], host: { class: 'flex min-w-0 flex-1' }, template: "<button\n type=\"button\"\n class=\"flex min-w-0 flex-1 items-center gap-1 truncate rounded px-1 py-0.5 text-left text-xs font-semibold tracking-wide text-content-faint uppercase transition-colors hover:bg-surface-overlay hover:text-content\"\n (click)=\"openSwitcher($event)\"\n lwMenuState\n [attr.aria-label]=\"'viewInstance.switcher' | transloco\"\n data-testid=\"view-switcher\"\n>\n <span class=\"truncate\">{{ activeName() || ('viewInstance.default' | transloco) }}</span>\n <lw-icon name=\"chevronDown\" size=\"0.85rem\" class=\"shrink-0\" />\n</button>\n" }]
|
|
6643
6875
|
}], propDecorators: { view: [{ type: i0.Input, args: [{ isSignal: true, alias: "view", required: true }] }], beforeSwitch: [{ type: i0.Output, args: ["beforeSwitch"] }] } });
|
|
6644
6876
|
|
|
6645
6877
|
class PaneChromeService {
|
|
@@ -7166,7 +7398,8 @@ class PaneTabStrip {
|
|
|
7166
7398
|
this.paneDrag.stop();
|
|
7167
7399
|
}
|
|
7168
7400
|
openOverflow(event) {
|
|
7169
|
-
const
|
|
7401
|
+
const control = event.currentTarget;
|
|
7402
|
+
const anchor = control.getBoundingClientRect();
|
|
7170
7403
|
const entries = this.tabs().map((tab) => ({
|
|
7171
7404
|
key: tab.path,
|
|
7172
7405
|
label: this.label(tab),
|
|
@@ -7178,7 +7411,7 @@ class PaneTabStrip {
|
|
|
7178
7411
|
if (tab) {
|
|
7179
7412
|
this.selectTab.emit(tab);
|
|
7180
7413
|
}
|
|
7181
|
-
});
|
|
7414
|
+
}, control);
|
|
7182
7415
|
}
|
|
7183
7416
|
onSelectTab(tab) {
|
|
7184
7417
|
if (tab.path !== this.activeId()) {
|
|
@@ -7291,19 +7524,19 @@ class PaneTabStrip {
|
|
|
7291
7524
|
return resolveTitle(tab, (key) => this.transloco.translate(key));
|
|
7292
7525
|
}
|
|
7293
7526
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: PaneTabStrip, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7294
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: PaneTabStrip, isStandalone: true, selector: "lw-pane-tab-strip", inputs: { tabs: { classPropertyName: "tabs", publicName: "tabs", isSignal: true, isRequired: true, transformFunction: null }, activeId: { classPropertyName: "activeId", publicName: "activeId", isSignal: true, isRequired: true, transformFunction: null }, reorderable: { classPropertyName: "reorderable", publicName: "reorderable", isSignal: true, isRequired: false, transformFunction: null }, draggable: { classPropertyName: "draggable", publicName: "draggable", isSignal: true, isRequired: false, transformFunction: null }, acceptsTabs: { classPropertyName: "acceptsTabs", publicName: "acceptsTabs", isSignal: true, isRequired: false, transformFunction: null }, source: { classPropertyName: "source", publicName: "source", isSignal: true, isRequired: true, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, urlDriven: { classPropertyName: "urlDriven", publicName: "urlDriven", isSignal: true, isRequired: false, transformFunction: null }, contextMenuSlot: { classPropertyName: "contextMenuSlot", publicName: "contextMenuSlot", isSignal: true, isRequired: false, transformFunction: null }, viewContextMenuSlot: { classPropertyName: "viewContextMenuSlot", publicName: "viewContextMenuSlot", isSignal: true, isRequired: false, transformFunction: null }, contextGroup: { classPropertyName: "contextGroup", publicName: "contextGroup", isSignal: true, isRequired: false, transformFunction: null }, overflow: { classPropertyName: "overflow", publicName: "overflow", isSignal: true, isRequired: false, transformFunction: null }, canAddTab: { classPropertyName: "canAddTab", publicName: "canAddTab", isSignal: true, isRequired: false, transformFunction: null }, paneActions: { classPropertyName: "paneActions", publicName: "paneActions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectTab: "selectTab", escalate: "escalate", closeTab: "closeTab", unpinTab: "unpinTab", reorderTabs: "reorderTabs", runAction: "runAction", addTab: "addTab", revealRequest: "revealRequest" }, viewQueries: [{ propertyName: "strip", first: true, predicate: ["tabStrip"], descendants: true, isSignal: true }], ngImport: i0, template: "<div [class]=\"bandClass()\">\n <div\n #tabStrip\n class=\"flex min-w-0 flex-1 items-center gap-0.5 overflow-hidden\"\n [class.px-2]=\"!icons()\"\n [class.px-1]=\"icons()\"\n role=\"tablist\"\n cdkDropList\n cdkDropListOrientation=\"horizontal\"\n [id]=\"stripId()\"\n [cdkDropListSortingDisabled]=\"!reorderable()\"\n [cdkDropListEnterPredicate]=\"enterPredicate\"\n [cdkDropListConnectedTo]=\"dragZoneIds()\"\n [cdkDropListSortPredicate]=\"sortPredicate\"\n (cdkDropListDropped)=\"onDrop($event)\"\n [lwReorderable]=\"stripId()\"\n [lwReorderableEnabled]=\"reorderable()\"\n (reorder)=\"reorderTabs.emit($event)\"\n >\n @for (tab of tabs(); track tab.path) {\n @let title = tab.literalTitle ? tab.title : (tab.title | transloco);\n @if (icons()) {\n <button\n type=\"button\"\n role=\"tab\"\n cdkDrag\n [cdkDragData]=\"tab.path\"\n [cdkDragDisabled]=\"!canDrag(tab)\"\n (cdkDragStarted)=\"onDragStarted(tab)\"\n (cdkDragEnded)=\"onDragEnded()\"\n [lwContextMenu]=\"menuSlotFor(tab)\"\n [lwContextMenuContext]=\"tabContext(tab)\"\n [attr.aria-selected]=\"isActive(tab)\"\n [attr.aria-label]=\"title\"\n [attr.data-reorder-id]=\"canReorder(tab) ? tab.path : null\"\n [attr.data-reorder-band]=\"tab.pinned ? 'pinned' : 'dynamic'\"\n [attr.data-tab-path]=\"tab.path\"\n (click)=\"onSelectTab(tab)\"\n (dblclick)=\"escalate.emit(tab)\"\n class=\"lw-icon-btn h-10 w-10 rounded-md md:h-7 md:w-7\"\n [class.bg-surface-overlay]=\"isActive(tab)\"\n [class.text-content]=\"isActive(tab)\"\n >\n <lw-icon [name]=\"tab.icon ?? 'document'\" size=\"1rem\" />\n <lw-tooltip [text]=\"title\" position=\"bottom\" />\n </button>\n } @else {\n <div\n class=\"flex max-w-52 min-w-28 items-center border-b-2 transition-colors\"\n cdkDrag\n [cdkDragData]=\"tab.path\"\n [cdkDragDisabled]=\"!canDrag(tab)\"\n (cdkDragStarted)=\"onDragStarted(tab)\"\n (cdkDragEnded)=\"onDragEnded()\"\n [class.border-brand]=\"isActive(tab) && urlDriven()\"\n [class.border-content-faint]=\"isActive(tab) && !urlDriven()\"\n [class.border-transparent]=\"!isActive(tab)\"\n [lwContextMenu]=\"menuSlotFor(tab)\"\n [lwContextMenuContext]=\"tabContext(tab)\"\n >\n <button\n type=\"button\"\n role=\"tab\"\n cdkDragHandle\n [attr.aria-selected]=\"isActive(tab)\"\n [attr.aria-label]=\"title\"\n [attr.data-reorder-id]=\"canReorder(tab) ? tab.path : null\"\n [attr.data-reorder-band]=\"tab.pinned ? 'pinned' : 'dynamic'\"\n [attr.data-tab-path]=\"tab.path\"\n [attr.aria-keyshortcuts]=\"tab.closable && !tab.pinned ? 'Delete' : null\"\n (click)=\"onSelectTab(tab)\"\n (dblclick)=\"escalate.emit(tab)\"\n (keydown)=\"onTabKeydown($event, tab)\"\n class=\"relative flex min-w-0 items-center gap-1.5 py-2 pr-1 pl-3 text-sm transition-colors\"\n [class.text-content]=\"isActive(tab)\"\n [class.text-content-faint]=\"!isActive(tab)\"\n [class.italic]=\"tab.preview\"\n >\n @if (tab.preview) {\n <lw-icon name=\"preview\" size=\"1rem\" />\n } @else if (tab.icon) {\n <lw-icon [name]=\"tab.icon\" size=\"1rem\" />\n }\n <span class=\"min-w-0 truncate\">{{ title }}</span>\n\n <lw-tooltip\n [text]=\"\n tab.preview && escalatable\n ? title + ' \u2014 ' + ('content.previewHint' | transloco)\n : title\n \"\n position=\"bottom\"\n />\n </button>\n\n @if (tab.pinned) {\n <span\n aria-hidden=\"true\"\n data-testid=\"tab-unpin\"\n (click)=\"onUnpin($event, tab)\"\n class=\"relative mr-1 flex h-6 w-6 cursor-pointer items-center justify-center rounded text-brand opacity-90 transition-colors hover:bg-surface-overlay hover:opacity-100\"\n >\n <lw-icon name=\"pin\" size=\"0.85rem\" />\n <lw-tooltip [text]=\"'content.pinnedHint' | transloco\" position=\"bottom\" />\n </span>\n } @else if (tab.closable) {\n <span\n aria-hidden=\"true\"\n data-testid=\"tab-close\"\n (click)=\"onClose($event, tab)\"\n class=\"lw-icon-btn mr-1 h-6 w-6 cursor-pointer opacity-70 hover:opacity-100\"\n >\n <lw-icon name=\"close\" size=\"0.85rem\" />\n <lw-tooltip [text]=\"'content.closeTab' | transloco\" position=\"bottom\" />\n </span>\n }\n </div>\n }\n }\n </div>\n\n @if (canAddTab()) {\n <button\n type=\"button\"\n (click)=\"addTab.emit($event)\"\n class=\"lw-icon-btn w-8\"\n [class.self-stretch]=\"icons()\"\n [attr.aria-label]=\"'content.split.newTab' | transloco\"\n data-testid=\"pane-add-tab\"\n >\n <lw-icon name=\"add\" size=\"1rem\" />\n <lw-tooltip [text]=\"'content.split.newTab' | transloco\" position=\"bottom\" />\n </button>\n }\n\n @if (overflow() && overflowing()) {\n <button\n type=\"button\"\n (click)=\"openOverflow($event)\"\n class=\"lw-icon-btn w-8\"\n [class.self-stretch]=\"icons()\"\n [attr.aria-label]=\"'content.moreTabs' | transloco\"\n >\n <lw-icon name=\"chevronDown\" size=\"1rem\" />\n <lw-tooltip [text]=\"'content.moreTabs' | transloco\" position=\"bottom\" />\n </button>\n }\n\n @if (paneActions(); as actions) {\n <ng-container [ngTemplateOutlet]=\"actions\" />\n }\n @if (activeActions().length) {\n <div class=\"flex shrink-0 items-center gap-0.5 border-l border-border px-2\">\n @for (action of activeActions(); track action.id) {\n <button\n type=\"button\"\n (click)=\"runAction.emit(action)\"\n class=\"lw-icon-btn h-8 w-8 rounded-md\"\n [attr.aria-label]=\"action.title | transloco\"\n >\n <lw-icon [name]=\"action.icon\" size=\"1rem\" />\n <lw-tooltip [text]=\"action.title | transloco\" position=\"bottom\" />\n </button>\n }\n </div>\n }\n</div>\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: ContextMenuDirective, selector: "[lwContextMenu]", inputs: ["lwContextMenu", "lwContextMenuContext"] }, { kind: "directive", type: Reorderable, selector: "[lwReorderable]", inputs: ["lwReorderable", "lwReorderableEnabled"], outputs: ["reorder"] }, { kind: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
|
|
7527
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: PaneTabStrip, isStandalone: true, selector: "lw-pane-tab-strip", inputs: { tabs: { classPropertyName: "tabs", publicName: "tabs", isSignal: true, isRequired: true, transformFunction: null }, activeId: { classPropertyName: "activeId", publicName: "activeId", isSignal: true, isRequired: true, transformFunction: null }, reorderable: { classPropertyName: "reorderable", publicName: "reorderable", isSignal: true, isRequired: false, transformFunction: null }, draggable: { classPropertyName: "draggable", publicName: "draggable", isSignal: true, isRequired: false, transformFunction: null }, acceptsTabs: { classPropertyName: "acceptsTabs", publicName: "acceptsTabs", isSignal: true, isRequired: false, transformFunction: null }, source: { classPropertyName: "source", publicName: "source", isSignal: true, isRequired: true, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, urlDriven: { classPropertyName: "urlDriven", publicName: "urlDriven", isSignal: true, isRequired: false, transformFunction: null }, contextMenuSlot: { classPropertyName: "contextMenuSlot", publicName: "contextMenuSlot", isSignal: true, isRequired: false, transformFunction: null }, viewContextMenuSlot: { classPropertyName: "viewContextMenuSlot", publicName: "viewContextMenuSlot", isSignal: true, isRequired: false, transformFunction: null }, contextGroup: { classPropertyName: "contextGroup", publicName: "contextGroup", isSignal: true, isRequired: false, transformFunction: null }, overflow: { classPropertyName: "overflow", publicName: "overflow", isSignal: true, isRequired: false, transformFunction: null }, canAddTab: { classPropertyName: "canAddTab", publicName: "canAddTab", isSignal: true, isRequired: false, transformFunction: null }, paneActions: { classPropertyName: "paneActions", publicName: "paneActions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectTab: "selectTab", escalate: "escalate", closeTab: "closeTab", unpinTab: "unpinTab", reorderTabs: "reorderTabs", runAction: "runAction", addTab: "addTab", revealRequest: "revealRequest" }, viewQueries: [{ propertyName: "strip", first: true, predicate: ["tabStrip"], descendants: true, isSignal: true }], ngImport: i0, template: "<div [class]=\"bandClass()\">\n <div\n #tabStrip\n class=\"flex min-w-0 flex-1 items-center gap-0.5 overflow-hidden\"\n [class.px-2]=\"!icons()\"\n [class.px-1]=\"icons()\"\n role=\"tablist\"\n cdkDropList\n cdkDropListOrientation=\"horizontal\"\n [id]=\"stripId()\"\n [cdkDropListSortingDisabled]=\"!reorderable()\"\n [cdkDropListEnterPredicate]=\"enterPredicate\"\n [cdkDropListConnectedTo]=\"dragZoneIds()\"\n [cdkDropListSortPredicate]=\"sortPredicate\"\n (cdkDropListDropped)=\"onDrop($event)\"\n [lwReorderable]=\"stripId()\"\n [lwReorderableEnabled]=\"reorderable()\"\n (reorder)=\"reorderTabs.emit($event)\"\n >\n @for (tab of tabs(); track tab.path) {\n @let title = tab.literalTitle ? tab.title : (tab.title | transloco);\n @if (icons()) {\n <button\n type=\"button\"\n role=\"tab\"\n cdkDrag\n [cdkDragData]=\"tab.path\"\n [cdkDragDisabled]=\"!canDrag(tab)\"\n (cdkDragStarted)=\"onDragStarted(tab)\"\n (cdkDragEnded)=\"onDragEnded()\"\n [lwMenu]=\"menuSlotFor(tab)\"\n [lwMenuContext]=\"tabContext(tab)\"\n [attr.aria-selected]=\"isActive(tab)\"\n [attr.aria-label]=\"title\"\n [attr.data-reorder-id]=\"canReorder(tab) ? tab.path : null\"\n [attr.data-reorder-band]=\"tab.pinned ? 'pinned' : 'dynamic'\"\n [attr.data-tab-path]=\"tab.path\"\n (click)=\"onSelectTab(tab)\"\n (dblclick)=\"escalate.emit(tab)\"\n class=\"lw-icon-btn h-10 w-10 rounded-md md:h-7 md:w-7\"\n [class.bg-surface-overlay]=\"isActive(tab)\"\n [class.text-content]=\"isActive(tab)\"\n >\n <lw-icon [name]=\"tab.icon ?? 'document'\" size=\"1rem\" />\n <lw-tooltip [text]=\"title\" position=\"bottom\" />\n </button>\n } @else {\n <div\n class=\"flex max-w-52 min-w-28 items-center border-b-2 transition-colors\"\n cdkDrag\n [cdkDragData]=\"tab.path\"\n [cdkDragDisabled]=\"!canDrag(tab)\"\n (cdkDragStarted)=\"onDragStarted(tab)\"\n (cdkDragEnded)=\"onDragEnded()\"\n [class.border-brand]=\"isActive(tab) && urlDriven()\"\n [class.border-content-faint]=\"isActive(tab) && !urlDriven()\"\n [class.border-transparent]=\"!isActive(tab)\"\n [lwMenu]=\"menuSlotFor(tab)\"\n [lwMenuContext]=\"tabContext(tab)\"\n >\n <button\n type=\"button\"\n role=\"tab\"\n cdkDragHandle\n [attr.aria-selected]=\"isActive(tab)\"\n [attr.aria-label]=\"title\"\n [attr.data-reorder-id]=\"canReorder(tab) ? tab.path : null\"\n [attr.data-reorder-band]=\"tab.pinned ? 'pinned' : 'dynamic'\"\n [attr.data-tab-path]=\"tab.path\"\n [attr.aria-keyshortcuts]=\"tab.closable && !tab.pinned ? 'Delete' : null\"\n (click)=\"onSelectTab(tab)\"\n (dblclick)=\"escalate.emit(tab)\"\n (keydown)=\"onTabKeydown($event, tab)\"\n class=\"relative flex min-w-0 items-center gap-1.5 py-2 pr-1 pl-3 text-sm transition-colors\"\n [class.text-content]=\"isActive(tab)\"\n [class.text-content-faint]=\"!isActive(tab)\"\n [class.italic]=\"tab.preview\"\n >\n @if (tab.preview) {\n <lw-icon name=\"preview\" size=\"1rem\" />\n } @else if (tab.icon) {\n <lw-icon [name]=\"tab.icon\" size=\"1rem\" />\n }\n <span class=\"min-w-0 truncate\">{{ title }}</span>\n\n <lw-tooltip\n [text]=\"\n tab.preview && escalatable\n ? title + ' \u2014 ' + ('content.previewHint' | transloco)\n : title\n \"\n position=\"bottom\"\n />\n </button>\n\n @if (tab.pinned) {\n <span\n aria-hidden=\"true\"\n data-testid=\"tab-unpin\"\n (click)=\"onUnpin($event, tab)\"\n class=\"relative mr-1 flex h-6 w-6 cursor-pointer items-center justify-center rounded text-brand opacity-90 transition-colors hover:bg-surface-overlay hover:opacity-100\"\n >\n <lw-icon name=\"pin\" size=\"0.85rem\" />\n <lw-tooltip [text]=\"'content.pinnedHint' | transloco\" position=\"bottom\" />\n </span>\n } @else if (tab.closable) {\n <span\n aria-hidden=\"true\"\n data-testid=\"tab-close\"\n (click)=\"onClose($event, tab)\"\n class=\"lw-icon-btn mr-1 h-6 w-6 cursor-pointer opacity-70 hover:opacity-100\"\n >\n <lw-icon name=\"close\" size=\"0.85rem\" />\n <lw-tooltip [text]=\"'content.closeTab' | transloco\" position=\"bottom\" />\n </span>\n }\n </div>\n }\n }\n </div>\n\n @if (canAddTab()) {\n <button\n type=\"button\"\n (click)=\"addTab.emit($event)\"\n lwMenuState\n class=\"lw-icon-btn w-8\"\n [class.self-stretch]=\"icons()\"\n [attr.aria-label]=\"'content.split.newTab' | transloco\"\n data-testid=\"pane-add-tab\"\n >\n <lw-icon name=\"add\" size=\"1rem\" />\n <lw-tooltip [text]=\"'content.split.newTab' | transloco\" position=\"bottom\" />\n </button>\n }\n\n @if (overflow() && overflowing()) {\n <button\n type=\"button\"\n (click)=\"openOverflow($event)\"\n lwMenuState\n class=\"lw-icon-btn w-8\"\n [class.self-stretch]=\"icons()\"\n [attr.aria-label]=\"'content.moreTabs' | transloco\"\n >\n <lw-icon name=\"chevronDown\" size=\"1rem\" />\n <lw-tooltip [text]=\"'content.moreTabs' | transloco\" position=\"bottom\" />\n </button>\n }\n\n @if (paneActions(); as actions) {\n <ng-container [ngTemplateOutlet]=\"actions\" />\n }\n @if (activeActions().length) {\n <div class=\"flex shrink-0 items-center gap-0.5 border-l border-border px-2\">\n @for (action of activeActions(); track action.id) {\n <button\n type=\"button\"\n (click)=\"runAction.emit(action)\"\n class=\"lw-icon-btn h-8 w-8 rounded-md\"\n [attr.aria-label]=\"action.title | transloco\"\n >\n <lw-icon [name]=\"action.icon\" size=\"1rem\" />\n <lw-tooltip [text]=\"action.title | transloco\" position=\"bottom\" />\n </button>\n }\n </div>\n }\n</div>\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: MenuTriggerDirective, selector: "[lwMenu], [lwMenuOnActivate], [lwMenuState]", inputs: ["lwMenu", "lwMenuOnActivate", "lwMenuContext", "lwMenuSide", "lwMenuHeader", "lwMenuState"] }, { kind: "directive", type: Reorderable, selector: "[lwReorderable]", inputs: ["lwReorderable", "lwReorderableEnabled"], outputs: ["reorder"] }, { kind: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
|
|
7295
7528
|
}
|
|
7296
7529
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: PaneTabStrip, decorators: [{
|
|
7297
7530
|
type: Component,
|
|
7298
7531
|
args: [{ selector: 'lw-pane-tab-strip', imports: [
|
|
7299
7532
|
NgTemplateOutlet,
|
|
7300
7533
|
TranslocoPipe,
|
|
7301
|
-
|
|
7534
|
+
MenuTriggerDirective,
|
|
7302
7535
|
Reorderable,
|
|
7303
7536
|
CdkDropList,
|
|
7304
7537
|
CdkDrag,
|
|
7305
7538
|
CdkDragHandle,
|
|
7306
|
-
], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "<div [class]=\"bandClass()\">\n <div\n #tabStrip\n class=\"flex min-w-0 flex-1 items-center gap-0.5 overflow-hidden\"\n [class.px-2]=\"!icons()\"\n [class.px-1]=\"icons()\"\n role=\"tablist\"\n cdkDropList\n cdkDropListOrientation=\"horizontal\"\n [id]=\"stripId()\"\n [cdkDropListSortingDisabled]=\"!reorderable()\"\n [cdkDropListEnterPredicate]=\"enterPredicate\"\n [cdkDropListConnectedTo]=\"dragZoneIds()\"\n [cdkDropListSortPredicate]=\"sortPredicate\"\n (cdkDropListDropped)=\"onDrop($event)\"\n [lwReorderable]=\"stripId()\"\n [lwReorderableEnabled]=\"reorderable()\"\n (reorder)=\"reorderTabs.emit($event)\"\n >\n @for (tab of tabs(); track tab.path) {\n @let title = tab.literalTitle ? tab.title : (tab.title | transloco);\n @if (icons()) {\n <button\n type=\"button\"\n role=\"tab\"\n cdkDrag\n [cdkDragData]=\"tab.path\"\n [cdkDragDisabled]=\"!canDrag(tab)\"\n (cdkDragStarted)=\"onDragStarted(tab)\"\n (cdkDragEnded)=\"onDragEnded()\"\n [
|
|
7539
|
+
], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "<div [class]=\"bandClass()\">\n <div\n #tabStrip\n class=\"flex min-w-0 flex-1 items-center gap-0.5 overflow-hidden\"\n [class.px-2]=\"!icons()\"\n [class.px-1]=\"icons()\"\n role=\"tablist\"\n cdkDropList\n cdkDropListOrientation=\"horizontal\"\n [id]=\"stripId()\"\n [cdkDropListSortingDisabled]=\"!reorderable()\"\n [cdkDropListEnterPredicate]=\"enterPredicate\"\n [cdkDropListConnectedTo]=\"dragZoneIds()\"\n [cdkDropListSortPredicate]=\"sortPredicate\"\n (cdkDropListDropped)=\"onDrop($event)\"\n [lwReorderable]=\"stripId()\"\n [lwReorderableEnabled]=\"reorderable()\"\n (reorder)=\"reorderTabs.emit($event)\"\n >\n @for (tab of tabs(); track tab.path) {\n @let title = tab.literalTitle ? tab.title : (tab.title | transloco);\n @if (icons()) {\n <button\n type=\"button\"\n role=\"tab\"\n cdkDrag\n [cdkDragData]=\"tab.path\"\n [cdkDragDisabled]=\"!canDrag(tab)\"\n (cdkDragStarted)=\"onDragStarted(tab)\"\n (cdkDragEnded)=\"onDragEnded()\"\n [lwMenu]=\"menuSlotFor(tab)\"\n [lwMenuContext]=\"tabContext(tab)\"\n [attr.aria-selected]=\"isActive(tab)\"\n [attr.aria-label]=\"title\"\n [attr.data-reorder-id]=\"canReorder(tab) ? tab.path : null\"\n [attr.data-reorder-band]=\"tab.pinned ? 'pinned' : 'dynamic'\"\n [attr.data-tab-path]=\"tab.path\"\n (click)=\"onSelectTab(tab)\"\n (dblclick)=\"escalate.emit(tab)\"\n class=\"lw-icon-btn h-10 w-10 rounded-md md:h-7 md:w-7\"\n [class.bg-surface-overlay]=\"isActive(tab)\"\n [class.text-content]=\"isActive(tab)\"\n >\n <lw-icon [name]=\"tab.icon ?? 'document'\" size=\"1rem\" />\n <lw-tooltip [text]=\"title\" position=\"bottom\" />\n </button>\n } @else {\n <div\n class=\"flex max-w-52 min-w-28 items-center border-b-2 transition-colors\"\n cdkDrag\n [cdkDragData]=\"tab.path\"\n [cdkDragDisabled]=\"!canDrag(tab)\"\n (cdkDragStarted)=\"onDragStarted(tab)\"\n (cdkDragEnded)=\"onDragEnded()\"\n [class.border-brand]=\"isActive(tab) && urlDriven()\"\n [class.border-content-faint]=\"isActive(tab) && !urlDriven()\"\n [class.border-transparent]=\"!isActive(tab)\"\n [lwMenu]=\"menuSlotFor(tab)\"\n [lwMenuContext]=\"tabContext(tab)\"\n >\n <button\n type=\"button\"\n role=\"tab\"\n cdkDragHandle\n [attr.aria-selected]=\"isActive(tab)\"\n [attr.aria-label]=\"title\"\n [attr.data-reorder-id]=\"canReorder(tab) ? tab.path : null\"\n [attr.data-reorder-band]=\"tab.pinned ? 'pinned' : 'dynamic'\"\n [attr.data-tab-path]=\"tab.path\"\n [attr.aria-keyshortcuts]=\"tab.closable && !tab.pinned ? 'Delete' : null\"\n (click)=\"onSelectTab(tab)\"\n (dblclick)=\"escalate.emit(tab)\"\n (keydown)=\"onTabKeydown($event, tab)\"\n class=\"relative flex min-w-0 items-center gap-1.5 py-2 pr-1 pl-3 text-sm transition-colors\"\n [class.text-content]=\"isActive(tab)\"\n [class.text-content-faint]=\"!isActive(tab)\"\n [class.italic]=\"tab.preview\"\n >\n @if (tab.preview) {\n <lw-icon name=\"preview\" size=\"1rem\" />\n } @else if (tab.icon) {\n <lw-icon [name]=\"tab.icon\" size=\"1rem\" />\n }\n <span class=\"min-w-0 truncate\">{{ title }}</span>\n\n <lw-tooltip\n [text]=\"\n tab.preview && escalatable\n ? title + ' \u2014 ' + ('content.previewHint' | transloco)\n : title\n \"\n position=\"bottom\"\n />\n </button>\n\n @if (tab.pinned) {\n <span\n aria-hidden=\"true\"\n data-testid=\"tab-unpin\"\n (click)=\"onUnpin($event, tab)\"\n class=\"relative mr-1 flex h-6 w-6 cursor-pointer items-center justify-center rounded text-brand opacity-90 transition-colors hover:bg-surface-overlay hover:opacity-100\"\n >\n <lw-icon name=\"pin\" size=\"0.85rem\" />\n <lw-tooltip [text]=\"'content.pinnedHint' | transloco\" position=\"bottom\" />\n </span>\n } @else if (tab.closable) {\n <span\n aria-hidden=\"true\"\n data-testid=\"tab-close\"\n (click)=\"onClose($event, tab)\"\n class=\"lw-icon-btn mr-1 h-6 w-6 cursor-pointer opacity-70 hover:opacity-100\"\n >\n <lw-icon name=\"close\" size=\"0.85rem\" />\n <lw-tooltip [text]=\"'content.closeTab' | transloco\" position=\"bottom\" />\n </span>\n }\n </div>\n }\n }\n </div>\n\n @if (canAddTab()) {\n <button\n type=\"button\"\n (click)=\"addTab.emit($event)\"\n lwMenuState\n class=\"lw-icon-btn w-8\"\n [class.self-stretch]=\"icons()\"\n [attr.aria-label]=\"'content.split.newTab' | transloco\"\n data-testid=\"pane-add-tab\"\n >\n <lw-icon name=\"add\" size=\"1rem\" />\n <lw-tooltip [text]=\"'content.split.newTab' | transloco\" position=\"bottom\" />\n </button>\n }\n\n @if (overflow() && overflowing()) {\n <button\n type=\"button\"\n (click)=\"openOverflow($event)\"\n lwMenuState\n class=\"lw-icon-btn w-8\"\n [class.self-stretch]=\"icons()\"\n [attr.aria-label]=\"'content.moreTabs' | transloco\"\n >\n <lw-icon name=\"chevronDown\" size=\"1rem\" />\n <lw-tooltip [text]=\"'content.moreTabs' | transloco\" position=\"bottom\" />\n </button>\n }\n\n @if (paneActions(); as actions) {\n <ng-container [ngTemplateOutlet]=\"actions\" />\n }\n @if (activeActions().length) {\n <div class=\"flex shrink-0 items-center gap-0.5 border-l border-border px-2\">\n @for (action of activeActions(); track action.id) {\n <button\n type=\"button\"\n (click)=\"runAction.emit(action)\"\n class=\"lw-icon-btn h-8 w-8 rounded-md\"\n [attr.aria-label]=\"action.title | transloco\"\n >\n <lw-icon [name]=\"action.icon\" size=\"1rem\" />\n <lw-tooltip [text]=\"action.title | transloco\" position=\"bottom\" />\n </button>\n }\n </div>\n }\n</div>\n" }]
|
|
7307
7540
|
}], ctorParameters: () => [], propDecorators: { tabs: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabs", required: true }] }], activeId: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeId", required: true }] }], reorderable: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderable", required: false }] }], draggable: [{ type: i0.Input, args: [{ isSignal: true, alias: "draggable", required: false }] }], acceptsTabs: [{ type: i0.Input, args: [{ isSignal: true, alias: "acceptsTabs", required: false }] }], source: [{ type: i0.Input, args: [{ isSignal: true, alias: "source", required: true }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], urlDriven: [{ type: i0.Input, args: [{ isSignal: true, alias: "urlDriven", required: false }] }], contextMenuSlot: [{ type: i0.Input, args: [{ isSignal: true, alias: "contextMenuSlot", required: false }] }], viewContextMenuSlot: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewContextMenuSlot", required: false }] }], contextGroup: [{ type: i0.Input, args: [{ isSignal: true, alias: "contextGroup", required: false }] }], overflow: [{ type: i0.Input, args: [{ isSignal: true, alias: "overflow", required: false }] }], canAddTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "canAddTab", required: false }] }], paneActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "paneActions", required: false }] }], selectTab: [{ type: i0.Output, args: ["selectTab"] }], escalate: [{ type: i0.Output, args: ["escalate"] }], closeTab: [{ type: i0.Output, args: ["closeTab"] }], unpinTab: [{ type: i0.Output, args: ["unpinTab"] }], reorderTabs: [{ type: i0.Output, args: ["reorderTabs"] }], runAction: [{ type: i0.Output, args: ["runAction"] }], addTab: [{ type: i0.Output, args: ["addTab"] }], revealRequest: [{ type: i0.Output, args: ["revealRequest"] }], strip: [{ type: i0.ViewChild, args: ['tabStrip', { isSignal: true }] }] } });
|
|
7308
7541
|
|
|
7309
7542
|
class PaneToolbar {
|
|
@@ -8862,7 +9095,7 @@ class PaneTargetPicker {
|
|
|
8862
9095
|
present(targets, anchor, onPick) {
|
|
8863
9096
|
const rect = anchor.getBoundingClientRect();
|
|
8864
9097
|
const entries = paneTargetEntries(targets, (key) => this.transloco.translate(key));
|
|
8865
|
-
this.menu.openList(entries, { x: rect.left, y: rect.bottom + MENU_ANCHOR_GAP }, onPick);
|
|
9098
|
+
this.menu.openList(entries, { x: rect.left, y: rect.bottom + MENU_ANCHOR_GAP }, onPick, anchor);
|
|
8866
9099
|
}
|
|
8867
9100
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: PaneTargetPicker, deps: [], target: i0.ɵɵFactoryTarget.Service });
|
|
8868
9101
|
static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.1.0", ngImport: i0, type: PaneTargetPicker });
|
|
@@ -10069,11 +10302,11 @@ class ShellSidebarHeader {
|
|
|
10069
10302
|
return this.layout.regions.find((r) => r.type === 'panel' && r.dock === dock && r.id !== this.region().id);
|
|
10070
10303
|
}
|
|
10071
10304
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: ShellSidebarHeader, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
10072
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: ShellSidebarHeader, isStandalone: true, selector: "lw-shell-sidebar-header", inputs: { region: { classPropertyName: "region", publicName: "region", isSignal: true, isRequired: true, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (showHamburger()) {\n\n <div\n class=\"flex h-12 w-10 shrink-0 items-center justify-center border-b border-border bg-surface\"\n >\n <button\n type=\"button\"\n (click)=\"open()\"\n class=\"lw-icon-btn h-9 w-9 rounded-md\"\n [attr.aria-label]=\"'panel.open' | transloco\"\n >\n <lw-icon name=\"menu\" size=\"1rem\" />\n <lw-tooltip [text]=\"'panel.open' | transloco\" position=\"bottom\" />\n </button>\n </div>\n} @else if (showExpand()) {\n\n <div\n class=\"flex h-12 items-center overflow-hidden border-b border-border bg-surface px-1.5\"\n >\n <button\n type=\"button\"\n (click)=\"expand()\"\n class=\"lw-icon-btn h-7 w-7 rounded-md\"\n [attr.aria-label]=\"'panel.expand' | transloco\"\n >\n <lw-icon [name]=\"expandIcon()\" size=\"1rem\" />\n <lw-tooltip [text]=\"'panel.expand' | transloco\" position=\"bottom\" />\n </button>\n </div>\n} @else if (!collapsed()) {\n\n <lw-pane-tab-strip\n class=\"block h-12\"\n [id]=\"hostId()\"\n variant=\"icons\"\n [tabs]=\"stripTabs()\"\n [activeId]=\"activeTabPath()\"\n [source]=\"source()\"\n [reorderable]=\"viewsReorderable\"\n [draggable]=\"viewsDraggable\"\n [acceptsTabs]=\"acceptsTab\"\n [viewContextMenuSlot]=\"viewContextMenu\"\n [contextGroup]=\"region().id\"\n [overflow]=\"true\"\n [paneActions]=\"trailing\"\n (selectTab)=\"select($event)\"\n (reorderTabs)=\"onReorder($event)\"\n (keydown)=\"onStripKeydown($event)\"\n [
|
|
10305
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: ShellSidebarHeader, isStandalone: true, selector: "lw-shell-sidebar-header", inputs: { region: { classPropertyName: "region", publicName: "region", isSignal: true, isRequired: true, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (showHamburger()) {\n\n <div\n class=\"flex h-12 w-10 shrink-0 items-center justify-center border-b border-border bg-surface\"\n >\n <button\n type=\"button\"\n (click)=\"open()\"\n class=\"lw-icon-btn h-9 w-9 rounded-md\"\n [attr.aria-label]=\"'panel.open' | transloco\"\n >\n <lw-icon name=\"menu\" size=\"1rem\" />\n <lw-tooltip [text]=\"'panel.open' | transloco\" position=\"bottom\" />\n </button>\n </div>\n} @else if (showExpand()) {\n\n <div\n class=\"flex h-12 items-center overflow-hidden border-b border-border bg-surface px-1.5\"\n >\n <button\n type=\"button\"\n (click)=\"expand()\"\n class=\"lw-icon-btn h-7 w-7 rounded-md\"\n [attr.aria-label]=\"'panel.expand' | transloco\"\n >\n <lw-icon [name]=\"expandIcon()\" size=\"1rem\" />\n <lw-tooltip [text]=\"'panel.expand' | transloco\" position=\"bottom\" />\n </button>\n </div>\n} @else if (!collapsed()) {\n\n <lw-pane-tab-strip\n class=\"block h-12\"\n [id]=\"hostId()\"\n variant=\"icons\"\n [tabs]=\"stripTabs()\"\n [activeId]=\"activeTabPath()\"\n [source]=\"source()\"\n [reorderable]=\"viewsReorderable\"\n [draggable]=\"viewsDraggable\"\n [acceptsTabs]=\"acceptsTab\"\n [viewContextMenuSlot]=\"viewContextMenu\"\n [contextGroup]=\"region().id\"\n [overflow]=\"true\"\n [paneActions]=\"trailing\"\n (selectTab)=\"select($event)\"\n (reorderTabs)=\"onReorder($event)\"\n (keydown)=\"onStripKeydown($event)\"\n [lwMenu]=\"stripMenu\"\n />\n <ng-template #trailing>\n @if (canCollapse()) {\n <button\n type=\"button\"\n (click)=\"trailingAction()\"\n class=\"lw-icon-btn h-10 w-10 self-center rounded-md md:h-7 md:w-7\"\n [attr.aria-label]=\"(viewport.compact() ? 'panel.close' : 'panel.collapse') | transloco\"\n >\n <lw-icon [name]=\"viewport.compact() ? 'close' : collapseIcon()\" size=\"1rem\" />\n <lw-tooltip [text]=\"(viewport.compact() ? 'panel.close' : 'panel.collapse') | transloco\" position=\"bottom\" />\n </button>\n }\n </ng-template>\n}\n", dependencies: [{ kind: "component", type: PaneTabStrip, selector: "lw-pane-tab-strip", inputs: ["tabs", "activeId", "reorderable", "draggable", "acceptsTabs", "source", "variant", "urlDriven", "contextMenuSlot", "viewContextMenuSlot", "contextGroup", "overflow", "canAddTab", "paneActions"], outputs: ["selectTab", "escalate", "closeTab", "unpinTab", "reorderTabs", "runAction", "addTab", "revealRequest"] }, { kind: "directive", type: MenuTriggerDirective, selector: "[lwMenu], [lwMenuOnActivate], [lwMenuState]", inputs: ["lwMenu", "lwMenuOnActivate", "lwMenuContext", "lwMenuSide", "lwMenuHeader", "lwMenuState"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
|
|
10073
10306
|
}
|
|
10074
10307
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: ShellSidebarHeader, decorators: [{
|
|
10075
10308
|
type: Component,
|
|
10076
|
-
args: [{ selector: 'lw-shell-sidebar-header', imports: [TranslocoPipe, PaneTabStrip,
|
|
10309
|
+
args: [{ selector: 'lw-shell-sidebar-header', imports: [TranslocoPipe, PaneTabStrip, MenuTriggerDirective], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "@if (showHamburger()) {\n\n <div\n class=\"flex h-12 w-10 shrink-0 items-center justify-center border-b border-border bg-surface\"\n >\n <button\n type=\"button\"\n (click)=\"open()\"\n class=\"lw-icon-btn h-9 w-9 rounded-md\"\n [attr.aria-label]=\"'panel.open' | transloco\"\n >\n <lw-icon name=\"menu\" size=\"1rem\" />\n <lw-tooltip [text]=\"'panel.open' | transloco\" position=\"bottom\" />\n </button>\n </div>\n} @else if (showExpand()) {\n\n <div\n class=\"flex h-12 items-center overflow-hidden border-b border-border bg-surface px-1.5\"\n >\n <button\n type=\"button\"\n (click)=\"expand()\"\n class=\"lw-icon-btn h-7 w-7 rounded-md\"\n [attr.aria-label]=\"'panel.expand' | transloco\"\n >\n <lw-icon [name]=\"expandIcon()\" size=\"1rem\" />\n <lw-tooltip [text]=\"'panel.expand' | transloco\" position=\"bottom\" />\n </button>\n </div>\n} @else if (!collapsed()) {\n\n <lw-pane-tab-strip\n class=\"block h-12\"\n [id]=\"hostId()\"\n variant=\"icons\"\n [tabs]=\"stripTabs()\"\n [activeId]=\"activeTabPath()\"\n [source]=\"source()\"\n [reorderable]=\"viewsReorderable\"\n [draggable]=\"viewsDraggable\"\n [acceptsTabs]=\"acceptsTab\"\n [viewContextMenuSlot]=\"viewContextMenu\"\n [contextGroup]=\"region().id\"\n [overflow]=\"true\"\n [paneActions]=\"trailing\"\n (selectTab)=\"select($event)\"\n (reorderTabs)=\"onReorder($event)\"\n (keydown)=\"onStripKeydown($event)\"\n [lwMenu]=\"stripMenu\"\n />\n <ng-template #trailing>\n @if (canCollapse()) {\n <button\n type=\"button\"\n (click)=\"trailingAction()\"\n class=\"lw-icon-btn h-10 w-10 self-center rounded-md md:h-7 md:w-7\"\n [attr.aria-label]=\"(viewport.compact() ? 'panel.close' : 'panel.collapse') | transloco\"\n >\n <lw-icon [name]=\"viewport.compact() ? 'close' : collapseIcon()\" size=\"1rem\" />\n <lw-tooltip [text]=\"(viewport.compact() ? 'panel.close' : 'panel.collapse') | transloco\" position=\"bottom\" />\n </button>\n }\n </ng-template>\n}\n" }]
|
|
10077
10310
|
}], propDecorators: { region: [{ type: i0.Input, args: [{ isSignal: true, alias: "region", required: true }] }], context: [{ type: i0.Input, args: [{ isSignal: true, alias: "context", required: false }] }] } });
|
|
10078
10311
|
|
|
10079
10312
|
const TAB_CONTEXT_MENU = 'content/tab/context';
|
|
@@ -11363,7 +11596,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
11363
11596
|
// GENERATED — do not edit by hand.
|
|
11364
11597
|
// Written by tools/stamp-version.mjs from <Version> in Directory.Build.props.
|
|
11365
11598
|
// Single source of truth: Directory.Build.props (bump via scripts/bump-version.sh).
|
|
11366
|
-
const APP_VERSION = '0.7.
|
|
11599
|
+
const APP_VERSION = '0.7.8';
|
|
11367
11600
|
|
|
11368
11601
|
/**
|
|
11369
11602
|
* The running build's version, sourced from `<Version>` in Directory.Build.props
|
|
@@ -13380,6 +13613,37 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
13380
13613
|
args: [{ selector: 'lw-text-size-toggle', imports: [TranslocoPipe], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "<fieldset class=\"lw-segmented\" [attr.aria-label]=\"'textSize.label' | transloco\">\n @for (s of scales; track s) {\n <button\n type=\"button\"\n (click)=\"select(s)\"\n [attr.aria-pressed]=\"scale() === s\"\n [attr.aria-label]=\"'textSize.' + s | transloco\"\n class=\"lw-segmented-item font-semibold\"\n >\n <span [class]=\"glyphClass(s)\" aria-hidden=\"true\">A</span>\n <lw-tooltip [text]=\"'textSize.' + s | transloco\" position=\"bottom\" />\n </button>\n }\n</fieldset>\n" }]
|
|
13381
13614
|
}] });
|
|
13382
13615
|
|
|
13616
|
+
/**
|
|
13617
|
+
* The plugins this distribution declared not optional. Defaults to **none** — every plugin is the
|
|
13618
|
+
* user's to switch off until a distribution says otherwise.
|
|
13619
|
+
*/
|
|
13620
|
+
const REQUIRED_PLUGINS = new InjectionToken('REQUIRED_PLUGINS', { providedIn: 'root', factory: () => [] });
|
|
13621
|
+
/**
|
|
13622
|
+
* A distribution declares which of the plugins it composes its application cannot run without. Such
|
|
13623
|
+
* a plugin is listed in the permissions settings with what it holds, and **without a switch to turn
|
|
13624
|
+
* it off**; it stays active whatever the user chose before.
|
|
13625
|
+
*
|
|
13626
|
+
* This is the distribution's statement and not the plugin's, and deliberately so: everything a plugin
|
|
13627
|
+
* declares about itself is a request the distribution grants, so a manifest field here would be the
|
|
13628
|
+
* one exemption a plugin could award itself.
|
|
13629
|
+
*
|
|
13630
|
+
* It withholds the plugin's own switch and nothing else. The capabilities such a plugin was granted
|
|
13631
|
+
* stay revocable, because needing a plugin says nothing about needing everything it asked for — which
|
|
13632
|
+
* is what distinguishes this from a plugin the operator deployed, where both are withheld.
|
|
13633
|
+
*
|
|
13634
|
+
* Naming a plugin this distribution does not compose — neither one it provides in-process nor an
|
|
13635
|
+
* isolated one it declares — is a composition mistake, not a failure: it is reported in development
|
|
13636
|
+
* and otherwise ignored, the same way a capability granted to a plugin that never declared it is. The
|
|
13637
|
+
* report happens once the composed plugins are registered, which is the only moment that set is
|
|
13638
|
+
* settled: a plugin the store installs arrives later and is the user's to switch off in any case.
|
|
13639
|
+
*
|
|
13640
|
+
* @example
|
|
13641
|
+
* provideRequiredPlugins('sign-in')
|
|
13642
|
+
*/
|
|
13643
|
+
function provideRequiredPlugins(...pluginIds) {
|
|
13644
|
+
return { provide: REQUIRED_PLUGINS, useValue: pluginIds };
|
|
13645
|
+
}
|
|
13646
|
+
|
|
13383
13647
|
const STORAGE_KEY$3 = 'lw.shell.disabled-plugins';
|
|
13384
13648
|
/**
|
|
13385
13649
|
* Whether each plugin is turned on — plugin enable/disable, distinct from capability revocation. Disabling a plugin is coarse: it does not restrict a power, it unloads the
|
|
@@ -13393,15 +13657,27 @@ const STORAGE_KEY$3 = 'lw.shell.disabled-plugins';
|
|
|
13393
13657
|
class PluginEnablementService {
|
|
13394
13658
|
store = inject(SETTINGS_STORE);
|
|
13395
13659
|
sync = inject(StateSyncService);
|
|
13660
|
+
required = new Set(inject(REQUIRED_PLUGINS));
|
|
13396
13661
|
disabledSet = signal(parseIdSet(this.store.peek?.(STORAGE_KEY$3)), /* @ts-ignore */
|
|
13397
13662
|
...(ngDevMode ? [{ debugName: "disabledSet" }] : /* istanbul ignore next */ []));
|
|
13398
13663
|
names = signal(new Map(), /* @ts-ignore */
|
|
13399
13664
|
...(ngDevMode ? [{ debugName: "names" }] : /* istanbul ignore next */ []));
|
|
13400
|
-
/**
|
|
13401
|
-
|
|
13665
|
+
/**
|
|
13666
|
+
* The disabled plugin ids (reactive) — a runtime reconciles activation against this. A plugin the
|
|
13667
|
+
* distribution declared its application cannot run without never appears here, whatever is stored,
|
|
13668
|
+
* so the runtime and the permissions surface read one answer rather than two.
|
|
13669
|
+
*/
|
|
13670
|
+
disabled = computed(() => {
|
|
13671
|
+
const stored = this.disabledSet();
|
|
13672
|
+
if (this.required.size === 0) {
|
|
13673
|
+
return stored;
|
|
13674
|
+
}
|
|
13675
|
+
return new Set([...stored].filter((id) => !this.required.has(id)));
|
|
13676
|
+
}, /* @ts-ignore */
|
|
13677
|
+
...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
13402
13678
|
/** Every known plugin with its enabled state, for the permissions settings surface. */
|
|
13403
13679
|
plugins = computed(() => {
|
|
13404
|
-
const disabled = this.
|
|
13680
|
+
const disabled = this.disabled();
|
|
13405
13681
|
return [...this.names().entries()]
|
|
13406
13682
|
.map(([id, name]) => ({ id, name, enabled: !disabled.has(id) }))
|
|
13407
13683
|
.toSorted((a, b) => a.name.localeCompare(b.name));
|
|
@@ -13411,6 +13687,10 @@ class PluginEnablementService {
|
|
|
13411
13687
|
hydrateAsync(this.store, STORAGE_KEY$3, (raw) => this.disabledSet.set(parseIdSet(raw)));
|
|
13412
13688
|
this.sync.register('settings', STORAGE_KEY$3, (raw) => this.disabledSet.set(parseIdSet(raw)));
|
|
13413
13689
|
}
|
|
13690
|
+
/** Whether the distribution declared it cannot run without this plugin. */
|
|
13691
|
+
isRequired(id) {
|
|
13692
|
+
return this.required.has(id);
|
|
13693
|
+
}
|
|
13414
13694
|
/** Records a plugin so the permissions surface can list it (enabled or not). Idempotent. A runtime calls it for every plugin it knows. */
|
|
13415
13695
|
register(id, name) {
|
|
13416
13696
|
this.names.update((map) => map.has(id) ? map : new Map(map).set(id, name));
|
|
@@ -13428,10 +13708,17 @@ class PluginEnablementService {
|
|
|
13428
13708
|
}
|
|
13429
13709
|
/** Whether `id` is currently enabled (default: yes — a plugin is on until the user turns it off). */
|
|
13430
13710
|
isEnabled(id) {
|
|
13431
|
-
return !this.
|
|
13711
|
+
return !this.disabled().has(id);
|
|
13432
13712
|
}
|
|
13433
|
-
/**
|
|
13713
|
+
/**
|
|
13714
|
+
* Turns a whole plugin on or off (persisted). The runtimes react by loading/unloading it. Turning
|
|
13715
|
+
* off a plugin the distribution declared it cannot run without does nothing: the surface offers no
|
|
13716
|
+
* switch for one, and this is the same answer read from anywhere else.
|
|
13717
|
+
*/
|
|
13434
13718
|
setEnabled(id, enabled) {
|
|
13719
|
+
if (!enabled && this.required.has(id)) {
|
|
13720
|
+
return;
|
|
13721
|
+
}
|
|
13435
13722
|
const next = toggledIdSet(this.disabledSet(), id, !enabled);
|
|
13436
13723
|
this.disabledSet.set(next);
|
|
13437
13724
|
void this.store.set(STORAGE_KEY$3, JSON.stringify([...next]));
|
|
@@ -13645,10 +13932,12 @@ class PermissionsSettings {
|
|
|
13645
13932
|
const caps = this.grants.permissions();
|
|
13646
13933
|
return this.enablement.plugins().map((plugin) => {
|
|
13647
13934
|
const provided = this.deployment.isDeployed(plugin.id);
|
|
13935
|
+
const required = this.enablement.isRequired(plugin.id);
|
|
13648
13936
|
return {
|
|
13649
13937
|
...plugin,
|
|
13650
13938
|
enabled: provided || plugin.enabled,
|
|
13651
13939
|
provided,
|
|
13940
|
+
required,
|
|
13652
13941
|
rungNote: rungNoteKey(this.isolation.rungOf(plugin.id)),
|
|
13653
13942
|
capabilities: caps.find((entry) => entry.pluginId === plugin.id)?.capabilities ??
|
|
13654
13943
|
[],
|
|
@@ -13663,11 +13952,11 @@ class PermissionsSettings {
|
|
|
13663
13952
|
this.grants.setGranted(pluginId, capability, event.target.checked);
|
|
13664
13953
|
}
|
|
13665
13954
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: PermissionsSettings, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
13666
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: PermissionsSettings, isStandalone: true, selector: "lw-permissions-settings", ngImport: i0, template: "<p class=\"mb-4 text-sm text-content-muted\">\n {{ 'settings.permissionsDesc' | transloco }}\n</p>\n@if (plugins().length === 0) {\n <p class=\"text-sm text-content-muted\">\n {{ 'settings.permissionsEmpty' | transloco }}\n </p>\n} @else {\n <div class=\"flex flex-col gap-6\">\n @for (plugin of plugins(); track plugin.id) {\n <section class=\"flex flex-col gap-3\">\n <div class=\"flex items-center justify-between gap-4\">\n <h3 class=\"text-sm font-semibold text-content\">\n {{ plugin.name }}\n </h3>\n @if (!plugin.provided) {\n <input\n type=\"checkbox\"\n role=\"switch\"\n class=\"lw-switch shrink-0\"\n [checked]=\"plugin.enabled\"\n [attr.aria-checked]=\"plugin.enabled\"\n [attr.aria-label]=\"'settings.pluginEnabled' | transloco\"\n [attr.data-testid]=\"'plugin-enabled-' + plugin.id\"\n (change)=\"togglePlugin(plugin.id, $event)\"\n />\n }\n </div>\n @if (plugin.rungNote; as rungNote) {\n <p\n class=\"text-xs text-content-muted\"\n [attr.data-testid]=\"'perm-level-' + plugin.id\"\n >\n {{ rungNote | transloco }}\n </p>\n }\n @if (plugin.provided) {\n <p\n class=\"text-xs text-content-muted\"\n [attr.data-testid]=\"'perm-provided-' + plugin.id\"\n >\n {{ 'settings.permissionsProvided' | transloco }}\n </p>\n }\n @if (plugin.enabled) {\n <ul class=\"flex flex-col gap-3\">\n @for (cap of plugin.capabilities; track cap.capability) {\n <li class=\"flex items-start justify-between gap-4\">\n <div class=\"flex flex-col\">\n <span class=\"text-sm text-content\">{{\n 'settings.capability.' + cap.capability | transloco\n }}</span>\n <span class=\"text-xs text-content-muted\">{{\n 'settings.capabilityDesc.' + cap.capability | transloco\n }}</span>\n </div>\n @if (!plugin.provided) {\n <input\n type=\"checkbox\"\n role=\"switch\"\n class=\"lw-switch shrink-0\"\n [checked]=\"cap.effective\"\n [attr.aria-checked]=\"cap.effective\"\n [attr.aria-label]=\"\n 'settings.capability.' + cap.capability | transloco\n \"\n [attr.data-testid]=\"\n 'perm-' + plugin.id + '-' + cap.capability\n \"\n (change)=\"\n toggleCapability(plugin.id, cap.capability, $event)\n \"\n />\n }\n </li>\n }\n </ul>\n } @else {\n <p class=\"text-xs text-content-muted\">\n {{ 'settings.pluginDisabled' | transloco }}\n </p>\n }\n </section>\n }\n </div>\n}\n", dependencies: [{ kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
|
|
13955
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: PermissionsSettings, isStandalone: true, selector: "lw-permissions-settings", ngImport: i0, template: "<p class=\"mb-4 text-sm text-content-muted\">\n {{ 'settings.permissionsDesc' | transloco }}\n</p>\n@if (plugins().length === 0) {\n <p class=\"text-sm text-content-muted\">\n {{ 'settings.permissionsEmpty' | transloco }}\n </p>\n} @else {\n <div class=\"flex flex-col gap-6\">\n @for (plugin of plugins(); track plugin.id) {\n <section class=\"flex flex-col gap-3\">\n <div class=\"flex items-center justify-between gap-4\">\n <h3 class=\"text-sm font-semibold text-content\">\n {{ plugin.name }}\n </h3>\n @if (!plugin.provided && !plugin.required) {\n <input\n type=\"checkbox\"\n role=\"switch\"\n class=\"lw-switch shrink-0\"\n [checked]=\"plugin.enabled\"\n [attr.aria-checked]=\"plugin.enabled\"\n [attr.aria-label]=\"'settings.pluginEnabled' | transloco\"\n [attr.data-testid]=\"'plugin-enabled-' + plugin.id\"\n (change)=\"togglePlugin(plugin.id, $event)\"\n />\n }\n </div>\n @if (plugin.rungNote; as rungNote) {\n <p\n class=\"text-xs text-content-muted\"\n [attr.data-testid]=\"'perm-level-' + plugin.id\"\n >\n {{ rungNote | transloco }}\n </p>\n }\n @if (plugin.provided) {\n <p\n class=\"text-xs text-content-muted\"\n [attr.data-testid]=\"'perm-provided-' + plugin.id\"\n >\n {{ 'settings.permissionsProvided' | transloco }}\n </p>\n } @else if (plugin.required) {\n <p\n class=\"text-xs text-content-muted\"\n [attr.data-testid]=\"'perm-required-' + plugin.id\"\n >\n {{ 'settings.permissionsRequired' | transloco }}\n </p>\n }\n @if (plugin.enabled) {\n <ul class=\"flex flex-col gap-3\">\n @for (cap of plugin.capabilities; track cap.capability) {\n <li class=\"flex items-start justify-between gap-4\">\n <div class=\"flex flex-col\">\n <span class=\"text-sm text-content\">{{\n 'settings.capability.' + cap.capability | transloco\n }}</span>\n <span class=\"text-xs text-content-muted\">{{\n 'settings.capabilityDesc.' + cap.capability | transloco\n }}</span>\n </div>\n @if (!plugin.provided) {\n <input\n type=\"checkbox\"\n role=\"switch\"\n class=\"lw-switch shrink-0\"\n [checked]=\"cap.effective\"\n [attr.aria-checked]=\"cap.effective\"\n [attr.aria-label]=\"\n 'settings.capability.' + cap.capability | transloco\n \"\n [attr.data-testid]=\"\n 'perm-' + plugin.id + '-' + cap.capability\n \"\n (change)=\"\n toggleCapability(plugin.id, cap.capability, $event)\n \"\n />\n }\n </li>\n }\n </ul>\n } @else {\n <p class=\"text-xs text-content-muted\">\n {{ 'settings.pluginDisabled' | transloco }}\n </p>\n }\n </section>\n }\n </div>\n}\n", dependencies: [{ kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
|
|
13667
13956
|
}
|
|
13668
13957
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: PermissionsSettings, decorators: [{
|
|
13669
13958
|
type: Component,
|
|
13670
|
-
args: [{ selector: 'lw-permissions-settings', imports: [TranslocoPipe], template: "<p class=\"mb-4 text-sm text-content-muted\">\n {{ 'settings.permissionsDesc' | transloco }}\n</p>\n@if (plugins().length === 0) {\n <p class=\"text-sm text-content-muted\">\n {{ 'settings.permissionsEmpty' | transloco }}\n </p>\n} @else {\n <div class=\"flex flex-col gap-6\">\n @for (plugin of plugins(); track plugin.id) {\n <section class=\"flex flex-col gap-3\">\n <div class=\"flex items-center justify-between gap-4\">\n <h3 class=\"text-sm font-semibold text-content\">\n {{ plugin.name }}\n </h3>\n @if (!plugin.provided) {\n <input\n type=\"checkbox\"\n role=\"switch\"\n class=\"lw-switch shrink-0\"\n [checked]=\"plugin.enabled\"\n [attr.aria-checked]=\"plugin.enabled\"\n [attr.aria-label]=\"'settings.pluginEnabled' | transloco\"\n [attr.data-testid]=\"'plugin-enabled-' + plugin.id\"\n (change)=\"togglePlugin(plugin.id, $event)\"\n />\n }\n </div>\n @if (plugin.rungNote; as rungNote) {\n <p\n class=\"text-xs text-content-muted\"\n [attr.data-testid]=\"'perm-level-' + plugin.id\"\n >\n {{ rungNote | transloco }}\n </p>\n }\n @if (plugin.provided) {\n <p\n class=\"text-xs text-content-muted\"\n [attr.data-testid]=\"'perm-provided-' + plugin.id\"\n >\n {{ 'settings.permissionsProvided' | transloco }}\n </p>\n }\n @if (plugin.enabled) {\n <ul class=\"flex flex-col gap-3\">\n @for (cap of plugin.capabilities; track cap.capability) {\n <li class=\"flex items-start justify-between gap-4\">\n <div class=\"flex flex-col\">\n <span class=\"text-sm text-content\">{{\n 'settings.capability.' + cap.capability | transloco\n }}</span>\n <span class=\"text-xs text-content-muted\">{{\n 'settings.capabilityDesc.' + cap.capability | transloco\n }}</span>\n </div>\n @if (!plugin.provided) {\n <input\n type=\"checkbox\"\n role=\"switch\"\n class=\"lw-switch shrink-0\"\n [checked]=\"cap.effective\"\n [attr.aria-checked]=\"cap.effective\"\n [attr.aria-label]=\"\n 'settings.capability.' + cap.capability | transloco\n \"\n [attr.data-testid]=\"\n 'perm-' + plugin.id + '-' + cap.capability\n \"\n (change)=\"\n toggleCapability(plugin.id, cap.capability, $event)\n \"\n />\n }\n </li>\n }\n </ul>\n } @else {\n <p class=\"text-xs text-content-muted\">\n {{ 'settings.pluginDisabled' | transloco }}\n </p>\n }\n </section>\n }\n </div>\n}\n" }]
|
|
13959
|
+
args: [{ selector: 'lw-permissions-settings', imports: [TranslocoPipe], template: "<p class=\"mb-4 text-sm text-content-muted\">\n {{ 'settings.permissionsDesc' | transloco }}\n</p>\n@if (plugins().length === 0) {\n <p class=\"text-sm text-content-muted\">\n {{ 'settings.permissionsEmpty' | transloco }}\n </p>\n} @else {\n <div class=\"flex flex-col gap-6\">\n @for (plugin of plugins(); track plugin.id) {\n <section class=\"flex flex-col gap-3\">\n <div class=\"flex items-center justify-between gap-4\">\n <h3 class=\"text-sm font-semibold text-content\">\n {{ plugin.name }}\n </h3>\n @if (!plugin.provided && !plugin.required) {\n <input\n type=\"checkbox\"\n role=\"switch\"\n class=\"lw-switch shrink-0\"\n [checked]=\"plugin.enabled\"\n [attr.aria-checked]=\"plugin.enabled\"\n [attr.aria-label]=\"'settings.pluginEnabled' | transloco\"\n [attr.data-testid]=\"'plugin-enabled-' + plugin.id\"\n (change)=\"togglePlugin(plugin.id, $event)\"\n />\n }\n </div>\n @if (plugin.rungNote; as rungNote) {\n <p\n class=\"text-xs text-content-muted\"\n [attr.data-testid]=\"'perm-level-' + plugin.id\"\n >\n {{ rungNote | transloco }}\n </p>\n }\n @if (plugin.provided) {\n <p\n class=\"text-xs text-content-muted\"\n [attr.data-testid]=\"'perm-provided-' + plugin.id\"\n >\n {{ 'settings.permissionsProvided' | transloco }}\n </p>\n } @else if (plugin.required) {\n <p\n class=\"text-xs text-content-muted\"\n [attr.data-testid]=\"'perm-required-' + plugin.id\"\n >\n {{ 'settings.permissionsRequired' | transloco }}\n </p>\n }\n @if (plugin.enabled) {\n <ul class=\"flex flex-col gap-3\">\n @for (cap of plugin.capabilities; track cap.capability) {\n <li class=\"flex items-start justify-between gap-4\">\n <div class=\"flex flex-col\">\n <span class=\"text-sm text-content\">{{\n 'settings.capability.' + cap.capability | transloco\n }}</span>\n <span class=\"text-xs text-content-muted\">{{\n 'settings.capabilityDesc.' + cap.capability | transloco\n }}</span>\n </div>\n @if (!plugin.provided) {\n <input\n type=\"checkbox\"\n role=\"switch\"\n class=\"lw-switch shrink-0\"\n [checked]=\"cap.effective\"\n [attr.aria-checked]=\"cap.effective\"\n [attr.aria-label]=\"\n 'settings.capability.' + cap.capability | transloco\n \"\n [attr.data-testid]=\"\n 'perm-' + plugin.id + '-' + cap.capability\n \"\n (change)=\"\n toggleCapability(plugin.id, cap.capability, $event)\n \"\n />\n }\n </li>\n }\n </ul>\n } @else {\n <p class=\"text-xs text-content-muted\">\n {{ 'settings.pluginDisabled' | transloco }}\n </p>\n }\n </section>\n }\n </div>\n}\n" }]
|
|
13671
13960
|
}] });
|
|
13672
13961
|
|
|
13673
13962
|
function registerDefaultSettings(settings) {
|
|
@@ -13861,6 +14150,8 @@ class CommandPalette {
|
|
|
13861
14150
|
? 'tabs'
|
|
13862
14151
|
: 'commands', /* @ts-ignore */
|
|
13863
14152
|
...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
|
|
14153
|
+
title = computed(() => this.mode() === 'tabs' ? 'palette.quickOpenTitle' : 'palette.title', /* @ts-ignore */
|
|
14154
|
+
...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
13864
14155
|
query = signal('', /* @ts-ignore */
|
|
13865
14156
|
...(ngDevMode ? [{ debugName: "query" }] : /* istanbul ignore next */ []));
|
|
13866
14157
|
rawIndex = signal(0, /* @ts-ignore */
|
|
@@ -14026,11 +14317,11 @@ class CommandPalette {
|
|
|
14026
14317
|
}
|
|
14027
14318
|
}
|
|
14028
14319
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: CommandPalette, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
14029
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: CommandPalette, isStandalone: true, selector: "lw-command-palette", ngImport: i0, template: "<div class=\"flex max-h-[60vh] w-full flex-col overflow-hidden\">\n <div class=\"flex items-center gap-2 border-b border-border px-4\">\n <lw-icon name=\"search\" size=\"1.1rem\" class=\"text-content-muted\" />\n <input\n data-lw-autofocus\n type=\"text\"\n role=\"combobox\"\n aria-controls=\"lw-palette-list\"\n [attr.aria-expanded]=\"true\"\n [attr.aria-activedescendant]=\"activeId()\"\n [attr.aria-label]=\"
|
|
14320
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: CommandPalette, isStandalone: true, selector: "lw-command-palette", ngImport: i0, template: "<div class=\"flex max-h-[60vh] w-full flex-col overflow-hidden\">\n <div class=\"flex items-center gap-2 border-b border-border px-4\">\n <lw-icon name=\"search\" size=\"1.1rem\" class=\"text-content-muted\" />\n <input\n data-lw-autofocus\n type=\"text\"\n role=\"combobox\"\n aria-controls=\"lw-palette-list\"\n [attr.aria-expanded]=\"true\"\n [attr.aria-activedescendant]=\"activeId()\"\n [attr.aria-label]=\"title() | transloco\"\n [value]=\"query()\"\n [placeholder]=\"\n (mode() === 'tabs' ? 'palette.tabsPlaceholder' : 'palette.placeholder')\n | transloco\n \"\n class=\"flex-1 bg-transparent py-3 text-sm text-content outline-none placeholder:text-content-faint\"\n (input)=\"onQuery($event)\"\n (keydown.arrowdown)=\"move($event, 1)\"\n (keydown.arrowup)=\"move($event, -1)\"\n (keydown.arrowright)=\"openTabActions($event)\"\n (keydown.enter)=\"runActive($event)\"\n />\n </div>\n\n <ul\n id=\"lw-palette-list\"\n role=\"listbox\"\n class=\"min-h-0 flex-1 overflow-y-auto p-1\"\n >\n @for (entry of results(); track entry.id; let i = $index) {\n @if (recentCount() > 0 && i === 0) {\n <li\n role=\"presentation\"\n data-testid=\"palette-section-recent\"\n class=\"px-3 pt-2 pb-1 text-xs font-medium text-content-faint\"\n >\n {{ 'palette.recent' | transloco }}\n </li>\n }\n @if (recentCount() > 0 && i === recentCount()) {\n <li\n role=\"presentation\"\n data-testid=\"palette-section-all\"\n class=\"px-3 pt-2 pb-1 text-xs font-medium text-content-faint\"\n >\n {{ 'palette.all' | transloco }}\n </li>\n }\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <li\n role=\"option\"\n [id]=\"optionId(i)\"\n [attr.aria-selected]=\"i === activeIndex()\"\n class=\"flex cursor-pointer items-center gap-3 rounded-md px-3 py-2 text-sm\"\n [class]=\"\n i === activeIndex()\n ? 'bg-brand/10 text-brand-text'\n : 'text-content hover:bg-surface-overlay'\n \"\n (click)=\"select(entry)\"\n (mouseenter)=\"setActive(i)\"\n >\n @if (entry.icon; as icon) {\n <lw-icon [name]=\"icon\" size=\"1rem\" class=\"text-content-muted\" />\n }\n <span class=\"flex-1 truncate\">{{ entry.label }}</span>\n @if (timeOf(entry); as time) {\n <span class=\"shrink-0 text-xs text-content-faint\">{{ time }}</span>\n }\n @if (shortcutOf(entry); as shortcut) {\n <kbd\n class=\"rounded border border-border px-1.5 py-0.5 text-xs text-content-muted\"\n >{{ shortcut }}</kbd\n >\n }\n </li>\n } @empty {\n <li class=\"px-3 py-6 text-center text-sm text-content-muted\">\n {{\n (mode() === 'tabs' ? 'palette.tabsEmpty' : 'palette.empty') | transloco\n }}\n </li>\n }\n </ul>\n\n <div\n data-testid=\"palette-footer\"\n class=\"flex items-center gap-4 border-t border-border px-4 py-2 text-xs text-content-faint\"\n >\n <span class=\"flex items-center gap-1.5\">\n <kbd class=\"rounded border border-border px-1 py-0.5\">\u2191\u2193</kbd>\n {{ 'palette.hint.navigate' | transloco }}\n </span>\n <span class=\"flex items-center gap-1.5\">\n <kbd class=\"rounded border border-border px-1 py-0.5\">\u21B5</kbd>\n {{ 'palette.hint.run' | transloco }}\n </span>\n @if (mode() === 'tabs') {\n <span class=\"flex items-center gap-1.5\" data-testid=\"palette-hint-actions\">\n <kbd class=\"rounded border border-border px-1 py-0.5\">\u2192</kbd>\n {{ 'palette.hint.actions' | transloco }}\n </span>\n }\n <span class=\"ml-auto flex items-center gap-1.5\">\n <kbd class=\"rounded border border-border px-1 py-0.5\">Esc</kbd>\n {{ 'palette.hint.close' | transloco }}\n </span>\n </div>\n</div>\n", dependencies: [{ kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
|
|
14030
14321
|
}
|
|
14031
14322
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: CommandPalette, decorators: [{
|
|
14032
14323
|
type: Component,
|
|
14033
|
-
args: [{ selector: 'lw-command-palette', schemas: [CUSTOM_ELEMENTS_SCHEMA], imports: [TranslocoPipe], template: "<div class=\"flex max-h-[60vh] w-full flex-col overflow-hidden\">\n <div class=\"flex items-center gap-2 border-b border-border px-4\">\n <lw-icon name=\"search\" size=\"1.1rem\" class=\"text-content-muted\" />\n <input\n data-lw-autofocus\n type=\"text\"\n role=\"combobox\"\n aria-controls=\"lw-palette-list\"\n [attr.aria-expanded]=\"true\"\n [attr.aria-activedescendant]=\"activeId()\"\n [attr.aria-label]=\"
|
|
14324
|
+
args: [{ selector: 'lw-command-palette', schemas: [CUSTOM_ELEMENTS_SCHEMA], imports: [TranslocoPipe], template: "<div class=\"flex max-h-[60vh] w-full flex-col overflow-hidden\">\n <div class=\"flex items-center gap-2 border-b border-border px-4\">\n <lw-icon name=\"search\" size=\"1.1rem\" class=\"text-content-muted\" />\n <input\n data-lw-autofocus\n type=\"text\"\n role=\"combobox\"\n aria-controls=\"lw-palette-list\"\n [attr.aria-expanded]=\"true\"\n [attr.aria-activedescendant]=\"activeId()\"\n [attr.aria-label]=\"title() | transloco\"\n [value]=\"query()\"\n [placeholder]=\"\n (mode() === 'tabs' ? 'palette.tabsPlaceholder' : 'palette.placeholder')\n | transloco\n \"\n class=\"flex-1 bg-transparent py-3 text-sm text-content outline-none placeholder:text-content-faint\"\n (input)=\"onQuery($event)\"\n (keydown.arrowdown)=\"move($event, 1)\"\n (keydown.arrowup)=\"move($event, -1)\"\n (keydown.arrowright)=\"openTabActions($event)\"\n (keydown.enter)=\"runActive($event)\"\n />\n </div>\n\n <ul\n id=\"lw-palette-list\"\n role=\"listbox\"\n class=\"min-h-0 flex-1 overflow-y-auto p-1\"\n >\n @for (entry of results(); track entry.id; let i = $index) {\n @if (recentCount() > 0 && i === 0) {\n <li\n role=\"presentation\"\n data-testid=\"palette-section-recent\"\n class=\"px-3 pt-2 pb-1 text-xs font-medium text-content-faint\"\n >\n {{ 'palette.recent' | transloco }}\n </li>\n }\n @if (recentCount() > 0 && i === recentCount()) {\n <li\n role=\"presentation\"\n data-testid=\"palette-section-all\"\n class=\"px-3 pt-2 pb-1 text-xs font-medium text-content-faint\"\n >\n {{ 'palette.all' | transloco }}\n </li>\n }\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <li\n role=\"option\"\n [id]=\"optionId(i)\"\n [attr.aria-selected]=\"i === activeIndex()\"\n class=\"flex cursor-pointer items-center gap-3 rounded-md px-3 py-2 text-sm\"\n [class]=\"\n i === activeIndex()\n ? 'bg-brand/10 text-brand-text'\n : 'text-content hover:bg-surface-overlay'\n \"\n (click)=\"select(entry)\"\n (mouseenter)=\"setActive(i)\"\n >\n @if (entry.icon; as icon) {\n <lw-icon [name]=\"icon\" size=\"1rem\" class=\"text-content-muted\" />\n }\n <span class=\"flex-1 truncate\">{{ entry.label }}</span>\n @if (timeOf(entry); as time) {\n <span class=\"shrink-0 text-xs text-content-faint\">{{ time }}</span>\n }\n @if (shortcutOf(entry); as shortcut) {\n <kbd\n class=\"rounded border border-border px-1.5 py-0.5 text-xs text-content-muted\"\n >{{ shortcut }}</kbd\n >\n }\n </li>\n } @empty {\n <li class=\"px-3 py-6 text-center text-sm text-content-muted\">\n {{\n (mode() === 'tabs' ? 'palette.tabsEmpty' : 'palette.empty') | transloco\n }}\n </li>\n }\n </ul>\n\n <div\n data-testid=\"palette-footer\"\n class=\"flex items-center gap-4 border-t border-border px-4 py-2 text-xs text-content-faint\"\n >\n <span class=\"flex items-center gap-1.5\">\n <kbd class=\"rounded border border-border px-1 py-0.5\">\u2191\u2193</kbd>\n {{ 'palette.hint.navigate' | transloco }}\n </span>\n <span class=\"flex items-center gap-1.5\">\n <kbd class=\"rounded border border-border px-1 py-0.5\">\u21B5</kbd>\n {{ 'palette.hint.run' | transloco }}\n </span>\n @if (mode() === 'tabs') {\n <span class=\"flex items-center gap-1.5\" data-testid=\"palette-hint-actions\">\n <kbd class=\"rounded border border-border px-1 py-0.5\">\u2192</kbd>\n {{ 'palette.hint.actions' | transloco }}\n </span>\n }\n <span class=\"ml-auto flex items-center gap-1.5\">\n <kbd class=\"rounded border border-border px-1 py-0.5\">Esc</kbd>\n {{ 'palette.hint.close' | transloco }}\n </span>\n </div>\n</div>\n" }]
|
|
14034
14325
|
}] });
|
|
14035
14326
|
|
|
14036
14327
|
class WorkspaceDialog {
|
|
@@ -14264,7 +14555,12 @@ function seedHostCommands(registry, layout, deps) {
|
|
|
14264
14555
|
shortcut: 'mod+k',
|
|
14265
14556
|
popout: true,
|
|
14266
14557
|
run: () => {
|
|
14267
|
-
dialogs.open(CommandPalette, {
|
|
14558
|
+
dialogs.open(CommandPalette, {
|
|
14559
|
+
bare: true,
|
|
14560
|
+
size: 'lg',
|
|
14561
|
+
align: 'top',
|
|
14562
|
+
title: 'palette.title',
|
|
14563
|
+
});
|
|
14268
14564
|
},
|
|
14269
14565
|
});
|
|
14270
14566
|
registry.addCommand({
|
|
@@ -14289,6 +14585,7 @@ function seedHostCommands(registry, layout, deps) {
|
|
|
14289
14585
|
bare: true,
|
|
14290
14586
|
size: 'lg',
|
|
14291
14587
|
align: 'top',
|
|
14588
|
+
title: 'palette.quickOpenTitle',
|
|
14292
14589
|
data: { mode: 'tabs' },
|
|
14293
14590
|
});
|
|
14294
14591
|
},
|
|
@@ -14801,6 +15098,16 @@ function accessCanMatch(access) {
|
|
|
14801
15098
|
};
|
|
14802
15099
|
}
|
|
14803
15100
|
|
|
15101
|
+
const keepPopout = (_route, state) => {
|
|
15102
|
+
if (!isPopoutUrl(inject(BootAddress).path)) {
|
|
15103
|
+
return true;
|
|
15104
|
+
}
|
|
15105
|
+
if (isDevMode()) {
|
|
15106
|
+
console.warn(popoutNavigationRefusal(normalizePath(state.url)));
|
|
15107
|
+
}
|
|
15108
|
+
return false;
|
|
15109
|
+
};
|
|
15110
|
+
|
|
14804
15111
|
const settleWorkspace = async (_route, state) => {
|
|
14805
15112
|
const claims = inject(WORKSPACE_CLAIMS);
|
|
14806
15113
|
await claims.settle(normalizePath(state.url));
|
|
@@ -14841,6 +15148,7 @@ function buildContentRoutes(contentRoutes, omitted = [], retention = 'destroy')
|
|
|
14841
15148
|
const placeholders = omitted.map((route) => ({
|
|
14842
15149
|
path: route.path,
|
|
14843
15150
|
component: RouteUnavailableView,
|
|
15151
|
+
canActivate: [keepPopout],
|
|
14844
15152
|
data: { content: true, routePlaceholder: true },
|
|
14845
15153
|
}));
|
|
14846
15154
|
return [...buildRegisteredRoutes(contentRoutes, retention), ...placeholders];
|
|
@@ -14886,7 +15194,7 @@ function buildRegisteredRoutes(contentRoutes, retention) {
|
|
|
14886
15194
|
const angular = {
|
|
14887
15195
|
path: route.path,
|
|
14888
15196
|
...surfaceRoute(route, retained),
|
|
14889
|
-
canActivate: [settleWorkspace],
|
|
15197
|
+
canActivate: [keepPopout, settleWorkspace],
|
|
14890
15198
|
data: {
|
|
14891
15199
|
content: true,
|
|
14892
15200
|
chromeless: route.chromeless,
|
|
@@ -14905,6 +15213,7 @@ function buildRegisteredRoutes(contentRoutes, retention) {
|
|
|
14905
15213
|
const placeholder = {
|
|
14906
15214
|
path: route.path,
|
|
14907
15215
|
component: AuthRequiredView,
|
|
15216
|
+
canActivate: [keepPopout],
|
|
14908
15217
|
data: {
|
|
14909
15218
|
content: true,
|
|
14910
15219
|
authPlaceholder: true,
|
|
@@ -15733,6 +16042,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
15733
16042
|
type: Service
|
|
15734
16043
|
}] });
|
|
15735
16044
|
|
|
16045
|
+
/** Multi-provider token: each contribution adds one sandboxed plugin to load. */
|
|
16046
|
+
const FRAME_PLUGIN = new InjectionToken('FRAME_PLUGIN');
|
|
16047
|
+
|
|
15736
16048
|
/** Multi-provider token: each contribution adds one plugin to load. */
|
|
15737
16049
|
const PLUGIN = new InjectionToken('PLUGIN');
|
|
15738
16050
|
/**
|
|
@@ -15743,6 +16055,8 @@ const PLUGIN = new InjectionToken('PLUGIN');
|
|
|
15743
16055
|
class PluginRuntime {
|
|
15744
16056
|
grants = inject(CapabilityGrantService);
|
|
15745
16057
|
enablement = inject(PluginEnablementService);
|
|
16058
|
+
required = inject(REQUIRED_PLUGINS);
|
|
16059
|
+
framePlugins = inject(FRAME_PLUGIN, { optional: true }) ?? [];
|
|
15746
16060
|
factory = inject(HostContextFactory);
|
|
15747
16061
|
injector = inject(EnvironmentInjector);
|
|
15748
16062
|
plugins = inject(PLUGIN, { optional: true }) ?? [];
|
|
@@ -15756,6 +16070,7 @@ class PluginRuntime {
|
|
|
15756
16070
|
for (const plugin of this.plugins) {
|
|
15757
16071
|
this.enablement.register(plugin.manifest.id, plugin.manifest.name ?? plugin.manifest.id);
|
|
15758
16072
|
}
|
|
16073
|
+
this.reportUncomposedRequirements();
|
|
15759
16074
|
this.reconcile(this.enablement.disabled());
|
|
15760
16075
|
effect(() => {
|
|
15761
16076
|
const disabled = this.enablement.disabled();
|
|
@@ -15822,6 +16137,19 @@ class PluginRuntime {
|
|
|
15822
16137
|
this.active.delete(id);
|
|
15823
16138
|
console.error(`Plugin "${id}" activation failed`, error);
|
|
15824
16139
|
}
|
|
16140
|
+
reportUncomposedRequirements() {
|
|
16141
|
+
if (!isDevMode()) {
|
|
16142
|
+
return;
|
|
16143
|
+
}
|
|
16144
|
+
const composed = new Set([
|
|
16145
|
+
...this.plugins.map((plugin) => plugin.manifest.id),
|
|
16146
|
+
...this.framePlugins.map((plugin) => plugin.id),
|
|
16147
|
+
]);
|
|
16148
|
+
const missing = this.required.filter((id) => !composed.has(id));
|
|
16149
|
+
if (missing.length > 0) {
|
|
16150
|
+
console.warn(`provideRequiredPlugins names ${missing.join(', ')}, which this distribution does not compose — ignored.`);
|
|
16151
|
+
}
|
|
16152
|
+
}
|
|
15825
16153
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: PluginRuntime, deps: [], target: i0.ɵɵFactoryTarget.Service });
|
|
15826
16154
|
static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.1.0", ngImport: i0, type: PluginRuntime });
|
|
15827
16155
|
}
|
|
@@ -15840,9 +16168,6 @@ function providePlugins(...plugins) {
|
|
|
15840
16168
|
];
|
|
15841
16169
|
}
|
|
15842
16170
|
|
|
15843
|
-
/** Multi-provider token: each contribution adds one sandboxed plugin to load. */
|
|
15844
|
-
const FRAME_PLUGIN = new InjectionToken('FRAME_PLUGIN');
|
|
15845
|
-
|
|
15846
16171
|
const STORAGE_KEY = 'lw.shell.installed-plugins';
|
|
15847
16172
|
/**
|
|
15848
16173
|
* The user's installed community plugins. Holds only the state: which catalog entries the
|
|
@@ -17246,5 +17571,5 @@ function provideIcons(icons) {
|
|
|
17246
17571
|
* Generated bundle index. Do not edit.
|
|
17247
17572
|
*/
|
|
17248
17573
|
|
|
17249
|
-
export { AUTH_SOURCE, AuthContext, BAR_ITEM, CAPABILITY_GRANTS, COMMAND_INVOKER, CapabilityGrantService, CommandInvocationService, CommandService, ContentTabsService, ContributionRegistry, DEFAULT_LAYOUT, DEFAULT_SHELL_FEATURES, DEVICE_LEVEL_KEYS, DialogOutlet, DialogService, FRAME_PLUGIN, FramePluginRuntime, KeybindingService, LW_BUTTON_TAG, LW_ICON_TAG, LW_MARKDOWN_TAG, LW_TOOLTIP_TAG, LocalStorageStore, LwButton, LwButtonElement, LwIconElement, LwMarkdownElement, LwSettingRow, LwSpinner, LwTooltipElement, LwVersion, NotificationService, PLUGIN, PLUGIN_CATALOG, PluginEnablementService, PluginInstallService, PluginRuntime, PopoutService, RAIL_ITEM, SETTINGS_STORE, SHELL_FEATURES, SHELL_LAYOUT, SettingsService, Shell, StateSyncService, TRANSLATION_NAMESPACES, TRANSLATION_OVERRIDES, ThemeService, ToastOutlet, UpdateBadge, UpdateService, VIEW, VersionService, WORKING_STATE_STORE, WORKSPACE_DEFINITIONS, defineLwButton, defineLwIcon, defineLwMarkdown, defineLwTooltip, effectiveCapabilities, formatChord, provideAuthSource, provideBarItems, provideCapabilityGrants, provideCommandPaletteEntry, provideFramePlugins, provideIcons, provideIdentityScopedStores, provideLayout, providePluginCatalog, providePlugins, provideQuickOpenEntry, provideRailItems, provideSettingsStore, provideShell, provideShellFeatures, provideShellRouter, provideTabAddressResolver, provideTranslationNamespaces, provideTranslationOverrides, provideUnauthorizedRedirect, provideViews, provideWorkingStateStore, provideWorkspaces, urlPluginCatalog };
|
|
17574
|
+
export { AUTH_SOURCE, AuthContext, BAR_ITEM, CAPABILITY_GRANTS, COMMAND_INVOKER, CapabilityGrantService, CommandInvocationService, CommandService, ContentTabsService, ContributionRegistry, DEFAULT_LAYOUT, DEFAULT_SHELL_FEATURES, DEVICE_LEVEL_KEYS, DialogOutlet, DialogService, FRAME_PLUGIN, FramePluginRuntime, KeybindingService, LW_BUTTON_TAG, LW_ICON_TAG, LW_MARKDOWN_TAG, LW_TOOLTIP_TAG, LocalStorageStore, LwButton, LwButtonElement, LwIconElement, LwMarkdownElement, LwSettingRow, LwSpinner, LwTooltipElement, LwVersion, NotificationService, PLUGIN, PLUGIN_CATALOG, PluginEnablementService, PluginInstallService, PluginRuntime, PopoutService, RAIL_ITEM, REQUIRED_PLUGINS, SETTINGS_STORE, SHELL_FEATURES, SHELL_LAYOUT, SettingsService, Shell, StateSyncService, TRANSLATION_NAMESPACES, TRANSLATION_OVERRIDES, ThemeService, ToastOutlet, UpdateBadge, UpdateService, VIEW, VersionService, WORKING_STATE_STORE, WORKSPACE_DEFINITIONS, defineLwButton, defineLwIcon, defineLwMarkdown, defineLwTooltip, effectiveCapabilities, formatChord, provideAuthSource, provideBarItems, provideCapabilityGrants, provideCommandPaletteEntry, provideFramePlugins, provideIcons, provideIdentityScopedStores, provideLayout, providePluginCatalog, providePlugins, provideQuickOpenEntry, provideRailItems, provideRequiredPlugins, provideSettingsStore, provideShell, provideShellFeatures, provideShellRouter, provideTabAddressResolver, provideTranslationNamespaces, provideTranslationOverrides, provideUnauthorizedRedirect, provideViews, provideWorkingStateStore, provideWorkspaces, urlPluginCatalog };
|
|
17250
17575
|
//# sourceMappingURL=loomweaver-shell.mjs.map
|