@memberjunction/ng-ui-components 5.51.0 → 6.1.0-edge.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +51 -2
  3. package/dist/lib/bottom-sheet/bottom-sheet.component.d.ts +96 -0
  4. package/dist/lib/bottom-sheet/bottom-sheet.component.d.ts.map +1 -0
  5. package/dist/lib/bottom-sheet/bottom-sheet.component.js +300 -0
  6. package/dist/lib/bottom-sheet/bottom-sheet.component.js.map +1 -0
  7. package/dist/lib/left-nav/left-nav.component.d.ts +142 -3
  8. package/dist/lib/left-nav/left-nav.component.d.ts.map +1 -1
  9. package/dist/lib/left-nav/left-nav.component.js +391 -117
  10. package/dist/lib/left-nav/left-nav.component.js.map +1 -1
  11. package/dist/lib/slide-panel/slide-panel.component.js +6 -6
  12. package/dist/lib/slide-panel/slide-panel.component.js.map +1 -1
  13. package/dist/lib/tabs/tab-chrome-guard.d.ts +14 -0
  14. package/dist/lib/tabs/tab-chrome-guard.d.ts.map +1 -0
  15. package/dist/lib/tabs/tab-chrome-guard.js +36 -0
  16. package/dist/lib/tabs/tab-chrome-guard.js.map +1 -0
  17. package/dist/lib/tabs/tab-list.directive.d.ts +93 -0
  18. package/dist/lib/tabs/tab-list.directive.d.ts.map +1 -0
  19. package/dist/lib/tabs/tab-list.directive.js +202 -0
  20. package/dist/lib/tabs/tab-list.directive.js.map +1 -0
  21. package/dist/lib/tabs/tabs.scss +242 -0
  22. package/dist/lib/workspace-tabs/workspace-card.component.d.ts +63 -0
  23. package/dist/lib/workspace-tabs/workspace-card.component.d.ts.map +1 -0
  24. package/dist/lib/workspace-tabs/workspace-card.component.js +256 -0
  25. package/dist/lib/workspace-tabs/workspace-card.component.js.map +1 -0
  26. package/dist/lib/workspace-tabs/workspace-tab-store.d.ts +47 -0
  27. package/dist/lib/workspace-tabs/workspace-tab-store.d.ts.map +1 -0
  28. package/dist/lib/workspace-tabs/workspace-tab-store.js +112 -0
  29. package/dist/lib/workspace-tabs/workspace-tab-store.js.map +1 -0
  30. package/dist/lib/workspace-tabs/workspace-tab-strip.component.d.ts +75 -0
  31. package/dist/lib/workspace-tabs/workspace-tab-strip.component.d.ts.map +1 -0
  32. package/dist/lib/workspace-tabs/workspace-tab-strip.component.js +252 -0
  33. package/dist/lib/workspace-tabs/workspace-tab-strip.component.js.map +1 -0
  34. package/dist/lib/workspace-tabs/workspace-tabs.types.d.ts +40 -0
  35. package/dist/lib/workspace-tabs/workspace-tabs.types.d.ts.map +1 -0
  36. package/dist/lib/workspace-tabs/workspace-tabs.types.js +13 -0
  37. package/dist/lib/workspace-tabs/workspace-tabs.types.js.map +1 -0
  38. package/dist/lib/workspace-tabs/workspace-tip.directive.d.ts +34 -0
  39. package/dist/lib/workspace-tabs/workspace-tip.directive.d.ts.map +1 -0
  40. package/dist/lib/workspace-tabs/workspace-tip.directive.js +123 -0
  41. package/dist/lib/workspace-tabs/workspace-tip.directive.js.map +1 -0
  42. package/dist/public-api.d.ts +8 -0
  43. package/dist/public-api.d.ts.map +1 -1
  44. package/dist/public-api.js +8 -0
  45. package/dist/public-api.js.map +1 -1
  46. package/package.json +14 -12
@@ -0,0 +1,252 @@
1
+ import { Component, ChangeDetectionStrategy, ElementRef, EventEmitter, Input, Output, inject } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { CdkDropList, CdkDrag } from '@angular/cdk/drag-drop';
4
+ import { MJWorkspaceTipDirective } from './workspace-tip.directive';
5
+ import { MJTabListDirective } from '../tabs/tab-list.directive';
6
+ import { warnIfTabChromeMissing } from '../tabs/tab-chrome-guard';
7
+ import * as i0 from "@angular/core";
8
+ const _forTrack0 = ($index, $item) => $item.Id;
9
+ function MJWorkspaceTabStripComponent_For_3_Conditional_1_Template(rf, ctx) { if (rf & 1) {
10
+ i0.ɵɵelement(0, "i", 11);
11
+ } if (rf & 2) {
12
+ const tab_r2 = i0.ɵɵnextContext().$implicit;
13
+ i0.ɵɵclassMap(tab_r2.Icon);
14
+ } }
15
+ function MJWorkspaceTabStripComponent_For_3_Conditional_2_Template(rf, ctx) { if (rf & 1) {
16
+ i0.ɵɵelement(0, "i", 6);
17
+ } }
18
+ function MJWorkspaceTabStripComponent_For_3_Conditional_5_Template(rf, ctx) { if (rf & 1) {
19
+ i0.ɵɵelementStart(0, "span", 8);
20
+ i0.ɵɵtext(1, "\u2022");
21
+ i0.ɵɵelementEnd();
22
+ } }
23
+ function MJWorkspaceTabStripComponent_For_3_Template(rf, ctx) { if (rf & 1) {
24
+ const _r1 = i0.ɵɵgetCurrentView();
25
+ i0.ɵɵelementStart(0, "div", 4);
26
+ i0.ɵɵlistener("click", function MJWorkspaceTabStripComponent_For_3_Template_div_click_0_listener() { const tab_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.TabSelected.emit(tab_r2.Id)); });
27
+ i0.ɵɵconditionalCreate(1, MJWorkspaceTabStripComponent_For_3_Conditional_1_Template, 1, 2, "i", 5);
28
+ i0.ɵɵconditionalCreate(2, MJWorkspaceTabStripComponent_For_3_Conditional_2_Template, 1, 0, "i", 6);
29
+ i0.ɵɵelementStart(3, "span", 7);
30
+ i0.ɵɵtext(4);
31
+ i0.ɵɵelementEnd();
32
+ i0.ɵɵconditionalCreate(5, MJWorkspaceTabStripComponent_For_3_Conditional_5_Template, 2, 0, "span", 8);
33
+ i0.ɵɵelementStart(6, "button", 9);
34
+ i0.ɵɵlistener("click", function MJWorkspaceTabStripComponent_For_3_Template_button_click_6_listener($event) { const tab_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onCloseClick($event, tab_r2.Id)); });
35
+ i0.ɵɵelement(7, "i", 10);
36
+ i0.ɵɵelementEnd()();
37
+ } if (rf & 2) {
38
+ const tab_r2 = ctx.$implicit;
39
+ const ctx_r2 = i0.ɵɵnextContext();
40
+ i0.ɵɵclassProp("mj-tabs__tab--active", tab_r2.Id === ctx_r2.ActiveId)("mj-tabs__tab--rejected", tab_r2.Status === "rejected")("mj-tabs__tab--complete", tab_r2.Status === "complete");
41
+ i0.ɵɵproperty("cdkDragDisabled", !ctx_r2.AllowReorder)("cdkDragStartDelay", ctx_r2.DragStartDelay);
42
+ i0.ɵɵattribute("aria-selected", tab_r2.Id === ctx_r2.ActiveId)("aria-label", ctx_r2.tabAccessibleName(tab_r2));
43
+ i0.ɵɵadvance();
44
+ i0.ɵɵconditional(tab_r2.Icon ? 1 : -1);
45
+ i0.ɵɵadvance();
46
+ i0.ɵɵconditional(tab_r2.Status === "rejected" ? 2 : -1);
47
+ i0.ɵɵadvance();
48
+ i0.ɵɵproperty("mjTip", tab_r2.Label);
49
+ i0.ɵɵadvance();
50
+ i0.ɵɵtextInterpolate(tab_r2.Label);
51
+ i0.ɵɵadvance();
52
+ i0.ɵɵconditional(tab_r2.Dirty ? 5 : -1);
53
+ i0.ɵɵadvance();
54
+ i0.ɵɵattribute("aria-label", "Close " + tab_r2.Label);
55
+ } }
56
+ function MJWorkspaceTabStripComponent_Conditional_4_Template(rf, ctx) { if (rf & 1) {
57
+ const _r4 = i0.ɵɵgetCurrentView();
58
+ i0.ɵɵelementStart(0, "button", 12);
59
+ i0.ɵɵlistener("click", function MJWorkspaceTabStripComponent_Conditional_4_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r4); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.NewTabRequested.emit()); });
60
+ i0.ɵɵelement(1, "i", 13);
61
+ i0.ɵɵelementStart(2, "span");
62
+ i0.ɵɵtext(3);
63
+ i0.ɵɵelementEnd()();
64
+ } if (rf & 2) {
65
+ const ctx_r2 = i0.ɵɵnextContext();
66
+ i0.ɵɵattribute("aria-label", ctx_r2.NewTabLabel);
67
+ i0.ɵɵadvance(3);
68
+ i0.ɵɵtextInterpolate(ctx_r2.NewTabLabel);
69
+ } }
70
+ /**
71
+ * `<mj-workspace-tab-strip>` — browser-style draft tabs, presentation over `MJWorkspaceTabStore`.
72
+ *
73
+ * Dumb by design: it renders the tabs it is handed and emits intent. The store holds the state
74
+ * machine; the host owns what a tab's payload means. That split keeps it app-agnostic.
75
+ *
76
+ * **Browser-tab behavior lives HERE** so every consumer inherits it:
77
+ * - pinned new-tab button; the tab LIST scrolls horizontally *behind* it on overflow;
78
+ * - tabs size to their text up to `--mj-tab-max`, then ellipsize; the inline unsaved-dot pushes the label;
79
+ * - the tab body keeps the default arrow cursor (like browser tabs);
80
+ * - the full label shows via the reusable `mjTip` tooltip when a tab is truncated (delayed, non-interactive);
81
+ * - drag-reorder via CDK, emitted as intent for the host to apply to its store.
82
+ *
83
+ * **Appearance and keyboard behaviour are NOT owned here.** The look comes from the global
84
+ * `.mj-tabs*` chrome in `tabs.scss`, and the ARIA tabs keyboard contract from `mjTabList` — both
85
+ * shared with `mj-tabstrip`, so the two strips cannot drift apart visually or behaviourally even
86
+ * though they keep different state models.
87
+ */
88
+ export class MJWorkspaceTabStripComponent {
89
+ elementRef = inject(ElementRef);
90
+ ngAfterViewInit() {
91
+ warnIfTabChromeMissing(this.elementRef.nativeElement);
92
+ }
93
+ Tabs = [];
94
+ ActiveId = null;
95
+ ShowNewTab = true;
96
+ NewTabLabel = 'New';
97
+ /**
98
+ * Whether tabs can be drag-reordered at all. The escape hatch for hosts where even long-press
99
+ * dragging is wrong (a kiosk surface, a read-only review screen) — reorder simply isn't offered
100
+ * and every touch gesture belongs to scrolling.
101
+ */
102
+ AllowReorder = true;
103
+ /**
104
+ * Per-pointer-type drag threshold, resolving the touch conflict between REORDER and SCROLL: an
105
+ * overflowing tab list scrolls by horizontal swipe, and a swipe starts on a tab — with an
106
+ * immediate drag threshold, CDK claims that touch and the list becomes unscrollable on phones.
107
+ * A hold-to-drag delay is the platform idiom for exactly this (iOS home screen, mobile browser
108
+ * tabs): a moving finger within the delay window is a SCROLL and CDK lets it through natively; a
109
+ * still finger past it is a DRAG. Mouse stays immediate — pointer users scroll with the wheel or
110
+ * scrollbar, so there is no gesture to disambiguate and a delay would just feel laggy.
111
+ */
112
+ DragStartDelay = { touch: 400, mouse: 0 };
113
+ TabSelected = new EventEmitter();
114
+ TabClosed = new EventEmitter();
115
+ NewTabRequested = new EventEmitter();
116
+ TabReordered = new EventEmitter();
117
+ /** CDK drop — emit the reorder intent; the host applies it to the store (the strip stays dumb). */
118
+ onDrop(event) {
119
+ if (event.previousIndex !== event.currentIndex) {
120
+ this.TabReordered.emit({ previousIndex: event.previousIndex, currentIndex: event.currentIndex });
121
+ }
122
+ }
123
+ /**
124
+ * The tab's accessible name. The dirty dot and the rejected colour/icon are the only signals for
125
+ * those states, and neither survives being read aloud — so they are spelled out here instead.
126
+ */
127
+ tabAccessibleName(tab) {
128
+ const parts = [tab.Label];
129
+ if (tab.Status === 'rejected')
130
+ parts.push('(rejected)');
131
+ if (tab.Dirty)
132
+ parts.push('(unsaved changes)');
133
+ return parts.join(' ');
134
+ }
135
+ /** Keyboard arrow/Home/End/Enter from `mjTabList` — map the position back onto our id. */
136
+ onActivateRequested(request) {
137
+ const tab = this.Tabs[request.Index];
138
+ if (tab) {
139
+ this.TabSelected.emit(tab.Id);
140
+ }
141
+ }
142
+ /** Delete/Backspace on a focused tab — the APG close gesture for a closeable tab. */
143
+ onCloseRequested(request) {
144
+ const tab = this.Tabs[request.Index];
145
+ if (tab) {
146
+ this.TabClosed.emit(tab.Id);
147
+ }
148
+ }
149
+ /** The close button sits inside the tab, so its click would otherwise also select the tab. */
150
+ onCloseClick(event, id) {
151
+ event.stopPropagation();
152
+ this.TabClosed.emit(id);
153
+ }
154
+ static ɵfac = function MJWorkspaceTabStripComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MJWorkspaceTabStripComponent)(); };
155
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJWorkspaceTabStripComponent, selectors: [["mj-workspace-tab-strip"]], inputs: { Tabs: "Tabs", ActiveId: "ActiveId", ShowNewTab: "ShowNewTab", NewTabLabel: "NewTabLabel", AllowReorder: "AllowReorder" }, outputs: { TabSelected: "TabSelected", TabClosed: "TabClosed", NewTabRequested: "NewTabRequested", TabReordered: "TabReordered" }, decls: 5, vars: 1, consts: [[1, "mj-tabs", "mj-tabs__bar"], ["mjTabList", "", "cdkDropList", "", "cdkDropListOrientation", "horizontal", 1, "mj-tabs__list", 3, "TabActivateRequested", "TabCloseRequested", "cdkDropListDropped"], ["cdkDrag", "", "role", "tab", 1, "mj-tabs__tab", 3, "cdkDragDisabled", "cdkDragStartDelay", "mj-tabs__tab--active", "mj-tabs__tab--rejected", "mj-tabs__tab--complete"], ["type", "button", 1, "mj-tabs__new"], ["cdkDrag", "", "role", "tab", 1, "mj-tabs__tab", 3, "click", "cdkDragDisabled", "cdkDragStartDelay"], ["aria-hidden", "true", 1, "mj-tabs__icon", 3, "class"], ["aria-hidden", "true", 1, "fa-solid", "fa-triangle-exclamation", "mj-tabs__status-icon"], [1, "mj-tabs__label", 3, "mjTip"], ["aria-hidden", "true", 1, "mj-tabs__dirty"], ["type", "button", "tabindex", "-1", 1, "mj-tabs__close", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-xmark"], ["aria-hidden", "true", 1, "mj-tabs__icon"], ["type", "button", 1, "mj-tabs__new", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-plus"]], template: function MJWorkspaceTabStripComponent_Template(rf, ctx) { if (rf & 1) {
156
+ i0.ɵɵelementStart(0, "div", 0)(1, "div", 1);
157
+ i0.ɵɵlistener("TabActivateRequested", function MJWorkspaceTabStripComponent_Template_div_TabActivateRequested_1_listener($event) { return ctx.onActivateRequested($event); })("TabCloseRequested", function MJWorkspaceTabStripComponent_Template_div_TabCloseRequested_1_listener($event) { return ctx.onCloseRequested($event); })("cdkDropListDropped", function MJWorkspaceTabStripComponent_Template_div_cdkDropListDropped_1_listener($event) { return ctx.onDrop($event); });
158
+ i0.ɵɵrepeaterCreate(2, MJWorkspaceTabStripComponent_For_3_Template, 8, 16, "div", 2, _forTrack0);
159
+ i0.ɵɵelementEnd();
160
+ i0.ɵɵconditionalCreate(4, MJWorkspaceTabStripComponent_Conditional_4_Template, 4, 2, "button", 3);
161
+ i0.ɵɵelementEnd();
162
+ } if (rf & 2) {
163
+ i0.ɵɵadvance(2);
164
+ i0.ɵɵrepeater(ctx.Tabs);
165
+ i0.ɵɵadvance(2);
166
+ i0.ɵɵconditional(ctx.ShowNewTab ? 4 : -1);
167
+ } }, dependencies: [CommonModule, CdkDropList, CdkDrag, MJWorkspaceTipDirective, MJTabListDirective], styles: ["\n\n\n\n\n\n[_nghost-%COMP%] {\n display: block;\n}\n\n\n\n\n\n\n.mj-tabs__tab.cdk-drag[_ngcontent-%COMP%] {\n cursor: default;\n}\n\n\n\n\n.cdk-drag-preview.mj-tabs__tab[_ngcontent-%COMP%] {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.22);\n border-radius: 8px 8px 0 0;\n}\n\n\n\n.mj-tabs__tab.cdk-drag-placeholder[_ngcontent-%COMP%] {\n opacity: 0.35;\n}\n\n\n\n.cdk-drag-animating[_ngcontent-%COMP%], \n.mj-tabs__list.cdk-drop-list-dragging[_ngcontent-%COMP%] .mj-tabs__tab[_ngcontent-%COMP%]:not(.cdk-drag-placeholder) {\n transition: transform 180ms cubic-bezier(0, 0, 0.2, 1);\n}"], changeDetection: 0 });
168
+ }
169
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MJWorkspaceTabStripComponent, [{
170
+ type: Component,
171
+ args: [{ standalone: true, selector: 'mj-workspace-tab-strip', imports: [CommonModule, CdkDropList, CdkDrag, MJWorkspaceTipDirective, MJTabListDirective], changeDetection: ChangeDetectionStrategy.OnPush, template: `
172
+ <div class="mj-tabs mj-tabs__bar">
173
+ <div
174
+ class="mj-tabs__list"
175
+ mjTabList
176
+ (TabActivateRequested)="onActivateRequested($event)"
177
+ (TabCloseRequested)="onCloseRequested($event)"
178
+ cdkDropList
179
+ cdkDropListOrientation="horizontal"
180
+ (cdkDropListDropped)="onDrop($event)">
181
+ @for (tab of Tabs; track tab.Id) {
182
+ <!-- role="tab" sits on the FOCUSABLE element, not on a wrapper around one. tabindex is
183
+ owned by mjTabList (roving), so it is deliberately not bound here. The accessible
184
+ name folds in the unsaved/rejected state, because those are conveyed visually by a
185
+ dot and a colour that a screen reader cannot see. -->
186
+ <div
187
+ class="mj-tabs__tab"
188
+ cdkDrag
189
+ [cdkDragDisabled]="!AllowReorder"
190
+ [cdkDragStartDelay]="DragStartDelay"
191
+ [class.mj-tabs__tab--active]="tab.Id === ActiveId"
192
+ [class.mj-tabs__tab--rejected]="tab.Status === 'rejected'"
193
+ [class.mj-tabs__tab--complete]="tab.Status === 'complete'"
194
+ role="tab"
195
+ [attr.aria-selected]="tab.Id === ActiveId"
196
+ [attr.aria-label]="tabAccessibleName(tab)"
197
+ (click)="TabSelected.emit(tab.Id)">
198
+ @if (tab.Icon) {
199
+ <i [class]="tab.Icon" class="mj-tabs__icon" aria-hidden="true"></i>
200
+ }
201
+ @if (tab.Status === 'rejected') {
202
+ <i class="fa-solid fa-triangle-exclamation mj-tabs__status-icon" aria-hidden="true"></i>
203
+ }
204
+ <span class="mj-tabs__label" [mjTip]="tab.Label">{{ tab.Label }}</span>
205
+ @if (tab.Dirty) {
206
+ <!-- Inline dot (no reserved slot): it PUSHES the label, so the ellipsis shifts left on
207
+ a capped tab and a short tab grows by the dot's width. Silent to assistive tech —
208
+ the state is already in the tab's accessible name. -->
209
+ <span class="mj-tabs__dirty" aria-hidden="true">&bull;</span>
210
+ }
211
+ <!-- tabindex="-1": the TAB is the focus stop and Delete closes it, so a second stop per
212
+ tab would double the length of the strip in the page tab order. -->
213
+ <button
214
+ type="button"
215
+ class="mj-tabs__close"
216
+ tabindex="-1"
217
+ [attr.aria-label]="'Close ' + tab.Label"
218
+ (click)="onCloseClick($event, tab.Id)">
219
+ <i class="fa-solid fa-xmark" aria-hidden="true"></i>
220
+ </button>
221
+ </div>
222
+ }
223
+ </div>
224
+ @if (ShowNewTab) {
225
+ <button type="button" class="mj-tabs__new" (click)="NewTabRequested.emit()" [attr.aria-label]="NewTabLabel">
226
+ <i class="fa-solid fa-plus" aria-hidden="true"></i>
227
+ <span>{{ NewTabLabel }}</span>
228
+ </button>
229
+ }
230
+ </div>
231
+ `, styles: ["/* Only what is LOCAL to this strip. The tab chrome \u2014 bar, tabs, active accent, label ellipsis,\n dirty dot, close button, pinned new-tab control \u2014 lives in the global `.mj-tabs*` stylesheet\n (ui-components `lib/tabs/tabs.scss`) so this strip and `mj-tabstrip` cannot drift apart.\n Anything added here is, by definition, a claim that this strip should look DIFFERENT. */\n\n:host {\n display: block;\n}\n\n/* \u2500\u2500\u2500 Drag-reorder (CDK) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n Specific to this strip: `mj-tabstrip` has no reorder capability, so these affordances would be\n dead weight in the shared sheet. Default arrow cursor over tabs \u2014 not a grab hand \u2014 matching\n browser tab convention. */\n.mj-tabs__tab.cdk-drag {\n cursor: default;\n}\n\n/* The floating clone while dragging \u2014 still reads as a tab, plus a lift shadow. Neutral rgba so it\n reads as a shadow in both themes; a token-tinted shadow glows in dark. */\n.cdk-drag-preview.mj-tabs__tab {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.22);\n border-radius: 8px 8px 0 0;\n}\n\n/* The gap the tab leaves behind \u2014 a faded outline, not a solid block. */\n.mj-tabs__tab.cdk-drag-placeholder {\n opacity: 0.35;\n}\n\n/* Smooth settle on drop, and neighbours sliding aside during a drag. */\n.cdk-drag-animating,\n.mj-tabs__list.cdk-drop-list-dragging .mj-tabs__tab:not(.cdk-drag-placeholder) {\n transition: transform 180ms cubic-bezier(0, 0, 0.2, 1);\n}\n"] }]
232
+ }], null, { Tabs: [{
233
+ type: Input
234
+ }], ActiveId: [{
235
+ type: Input
236
+ }], ShowNewTab: [{
237
+ type: Input
238
+ }], NewTabLabel: [{
239
+ type: Input
240
+ }], AllowReorder: [{
241
+ type: Input
242
+ }], TabSelected: [{
243
+ type: Output
244
+ }], TabClosed: [{
245
+ type: Output
246
+ }], NewTabRequested: [{
247
+ type: Output
248
+ }], TabReordered: [{
249
+ type: Output
250
+ }] }); })();
251
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJWorkspaceTabStripComponent, { className: "MJWorkspaceTabStripComponent", filePath: "lib/workspace-tabs/workspace-tab-strip.component.ts", lineNumber: 101 }); })();
252
+ //# sourceMappingURL=workspace-tab-strip.component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-tab-strip.component.js","sourceRoot":"","sources":["../../../src/lib/workspace-tabs/workspace-tab-strip.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { AfterViewInit, Component, ChangeDetectionStrategy, ElementRef, EventEmitter, Input, Output, inject } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { CdkDropList, CdkDrag, CdkDragDrop } from '@angular/cdk/drag-drop';\nimport { MJWorkspaceTab } from './workspace-tabs.types';\nimport { MJWorkspaceTipDirective } from './workspace-tip.directive';\nimport { MJTabListDirective, MJTabListRequest } from '../tabs/tab-list.directive';\nimport { warnIfTabChromeMissing } from '../tabs/tab-chrome-guard';\n\n/** A drag-reorder request from the strip: move the tab at `previousIndex` to `currentIndex`. */\nexport interface MJTabReorder {\n previousIndex: number;\n currentIndex: number;\n}\n\n/**\n * `<mj-workspace-tab-strip>` — browser-style draft tabs, presentation over `MJWorkspaceTabStore`.\n *\n * Dumb by design: it renders the tabs it is handed and emits intent. The store holds the state\n * machine; the host owns what a tab's payload means. That split keeps it app-agnostic.\n *\n * **Browser-tab behavior lives HERE** so every consumer inherits it:\n * - pinned new-tab button; the tab LIST scrolls horizontally *behind* it on overflow;\n * - tabs size to their text up to `--mj-tab-max`, then ellipsize; the inline unsaved-dot pushes the label;\n * - the tab body keeps the default arrow cursor (like browser tabs);\n * - the full label shows via the reusable `mjTip` tooltip when a tab is truncated (delayed, non-interactive);\n * - drag-reorder via CDK, emitted as intent for the host to apply to its store.\n *\n * **Appearance and keyboard behaviour are NOT owned here.** The look comes from the global\n * `.mj-tabs*` chrome in `tabs.scss`, and the ARIA tabs keyboard contract from `mjTabList` — both\n * shared with `mj-tabstrip`, so the two strips cannot drift apart visually or behaviourally even\n * though they keep different state models.\n */\n@Component({\n standalone: true,\n selector: 'mj-workspace-tab-strip',\n imports: [CommonModule, CdkDropList, CdkDrag, MJWorkspaceTipDirective, MJTabListDirective],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <div class=\"mj-tabs mj-tabs__bar\">\n <div\n class=\"mj-tabs__list\"\n mjTabList\n (TabActivateRequested)=\"onActivateRequested($event)\"\n (TabCloseRequested)=\"onCloseRequested($event)\"\n cdkDropList\n cdkDropListOrientation=\"horizontal\"\n (cdkDropListDropped)=\"onDrop($event)\">\n @for (tab of Tabs; track tab.Id) {\n <!-- role=\"tab\" sits on the FOCUSABLE element, not on a wrapper around one. tabindex is\n owned by mjTabList (roving), so it is deliberately not bound here. The accessible\n name folds in the unsaved/rejected state, because those are conveyed visually by a\n dot and a colour that a screen reader cannot see. -->\n <div\n class=\"mj-tabs__tab\"\n cdkDrag\n [cdkDragDisabled]=\"!AllowReorder\"\n [cdkDragStartDelay]=\"DragStartDelay\"\n [class.mj-tabs__tab--active]=\"tab.Id === ActiveId\"\n [class.mj-tabs__tab--rejected]=\"tab.Status === 'rejected'\"\n [class.mj-tabs__tab--complete]=\"tab.Status === 'complete'\"\n role=\"tab\"\n [attr.aria-selected]=\"tab.Id === ActiveId\"\n [attr.aria-label]=\"tabAccessibleName(tab)\"\n (click)=\"TabSelected.emit(tab.Id)\">\n @if (tab.Icon) {\n <i [class]=\"tab.Icon\" class=\"mj-tabs__icon\" aria-hidden=\"true\"></i>\n }\n @if (tab.Status === 'rejected') {\n <i class=\"fa-solid fa-triangle-exclamation mj-tabs__status-icon\" aria-hidden=\"true\"></i>\n }\n <span class=\"mj-tabs__label\" [mjTip]=\"tab.Label\">{{ tab.Label }}</span>\n @if (tab.Dirty) {\n <!-- Inline dot (no reserved slot): it PUSHES the label, so the ellipsis shifts left on\n a capped tab and a short tab grows by the dot's width. Silent to assistive tech —\n the state is already in the tab's accessible name. -->\n <span class=\"mj-tabs__dirty\" aria-hidden=\"true\">&bull;</span>\n }\n <!-- tabindex=\"-1\": the TAB is the focus stop and Delete closes it, so a second stop per\n tab would double the length of the strip in the page tab order. -->\n <button\n type=\"button\"\n class=\"mj-tabs__close\"\n tabindex=\"-1\"\n [attr.aria-label]=\"'Close ' + tab.Label\"\n (click)=\"onCloseClick($event, tab.Id)\">\n <i class=\"fa-solid fa-xmark\" aria-hidden=\"true\"></i>\n </button>\n </div>\n }\n </div>\n @if (ShowNewTab) {\n <button type=\"button\" class=\"mj-tabs__new\" (click)=\"NewTabRequested.emit()\" [attr.aria-label]=\"NewTabLabel\">\n <i class=\"fa-solid fa-plus\" aria-hidden=\"true\"></i>\n <span>{{ NewTabLabel }}</span>\n </button>\n }\n </div>\n `,\n styleUrls: ['./workspace-tab-strip.component.css'],\n})\nexport class MJWorkspaceTabStripComponent implements AfterViewInit {\n private readonly elementRef = inject(ElementRef);\n\n ngAfterViewInit(): void {\n warnIfTabChromeMissing(this.elementRef.nativeElement);\n }\n\n @Input() Tabs: MJWorkspaceTab[] = [];\n @Input() ActiveId: string | null = null;\n @Input() ShowNewTab = true;\n @Input() NewTabLabel = 'New';\n\n /**\n * Whether tabs can be drag-reordered at all. The escape hatch for hosts where even long-press\n * dragging is wrong (a kiosk surface, a read-only review screen) — reorder simply isn't offered\n * and every touch gesture belongs to scrolling.\n */\n @Input() AllowReorder = true;\n\n /**\n * Per-pointer-type drag threshold, resolving the touch conflict between REORDER and SCROLL: an\n * overflowing tab list scrolls by horizontal swipe, and a swipe starts on a tab — with an\n * immediate drag threshold, CDK claims that touch and the list becomes unscrollable on phones.\n * A hold-to-drag delay is the platform idiom for exactly this (iOS home screen, mobile browser\n * tabs): a moving finger within the delay window is a SCROLL and CDK lets it through natively; a\n * still finger past it is a DRAG. Mouse stays immediate — pointer users scroll with the wheel or\n * scrollbar, so there is no gesture to disambiguate and a delay would just feel laggy.\n */\n public readonly DragStartDelay = { touch: 400, mouse: 0 };\n\n @Output() TabSelected = new EventEmitter<string>();\n @Output() TabClosed = new EventEmitter<string>();\n @Output() NewTabRequested = new EventEmitter<void>();\n @Output() TabReordered = new EventEmitter<MJTabReorder>();\n\n /** CDK drop — emit the reorder intent; the host applies it to the store (the strip stays dumb). */\n public onDrop(event: CdkDragDrop<MJWorkspaceTab[]>): void {\n if (event.previousIndex !== event.currentIndex) {\n this.TabReordered.emit({ previousIndex: event.previousIndex, currentIndex: event.currentIndex });\n }\n }\n\n /**\n * The tab's accessible name. The dirty dot and the rejected colour/icon are the only signals for\n * those states, and neither survives being read aloud — so they are spelled out here instead.\n */\n public tabAccessibleName(tab: MJWorkspaceTab): string {\n const parts = [tab.Label];\n if (tab.Status === 'rejected') parts.push('(rejected)');\n if (tab.Dirty) parts.push('(unsaved changes)');\n return parts.join(' ');\n }\n\n /** Keyboard arrow/Home/End/Enter from `mjTabList` — map the position back onto our id. */\n public onActivateRequested(request: MJTabListRequest): void {\n const tab = this.Tabs[request.Index];\n if (tab) {\n this.TabSelected.emit(tab.Id);\n }\n }\n\n /** Delete/Backspace on a focused tab — the APG close gesture for a closeable tab. */\n public onCloseRequested(request: MJTabListRequest): void {\n const tab = this.Tabs[request.Index];\n if (tab) {\n this.TabClosed.emit(tab.Id);\n }\n }\n\n /** The close button sits inside the tab, so its click would otherwise also select the tab. */\n public onCloseClick(event: MouseEvent, id: string): void {\n event.stopPropagation();\n this.TabClosed.emit(id);\n }\n}\n"]}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Workspace-tab framework contract.
3
+ *
4
+ * A "workspace" is a screen where the user builds several drafts in parallel — each draft lives in
5
+ * a tab (browser-tab semantics: open, switch, drag-reorder, close, dirty-dot). Originated in the
6
+ * BizApps accounting JE/batch workspaces and hoisted here as the canonical implementation.
7
+ *
8
+ * v1 is **session-scoped**: a tab's state lives until the tab is closed or the session ends, and is
9
+ * deliberately **NOT DB-persisted** (DB persistence is the v2 fork). App types never appear here; a
10
+ * tab carries an opaque `State` the host owns.
11
+ */
12
+ /** Lifecycle state of a draft tab. */
13
+ export type MJWorkspaceTabState =
14
+ /** Normal in-progress draft. */
15
+ 'draft'
16
+ /** Round-tripped after a rejection — the tab returns for rework carrying its rejection context. */
17
+ | 'rejected'
18
+ /** Committed/built — kept open read-only until the user closes it. */
19
+ | 'complete';
20
+ /**
21
+ * One workspace tab. `State` is intentionally `unknown`: the framework moves tabs around and never
22
+ * inspects their payload, which is what keeps it app-agnostic. Hosts narrow it themselves — this is
23
+ * the layer boundary, not weak typing.
24
+ */
25
+ export interface MJWorkspaceTab<TState = unknown> {
26
+ /** Stable identity within the strip. */
27
+ Id: string;
28
+ /** Tab caption. */
29
+ Label: string;
30
+ /** Optional Font Awesome class rendered before the label. */
31
+ Icon?: string;
32
+ Status: MJWorkspaceTabState;
33
+ /** Host-owned payload — the in-progress draft. */
34
+ State: TState;
35
+ /** Set when Status is 'rejected'; surfaced as the tab tooltip so the reason travels with the tab. */
36
+ RejectionReason?: string | null;
37
+ /** True when the tab has unsaved edits — drives the discard confirm. */
38
+ Dirty?: boolean;
39
+ }
40
+ //# sourceMappingURL=workspace-tabs.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-tabs.types.d.ts","sourceRoot":"","sources":["../../../src/lib/workspace-tabs/workspace-tabs.types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,sCAAsC;AACtC,MAAM,MAAM,mBAAmB;AAC7B,gCAAgC;AAC9B,OAAO;AACT,mGAAmG;GACjG,UAAU;AACZ,sEAAsE;GACpE,UAAU,CAAC;AAEf;;;;GAIG;AACH,MAAM,WAAW,cAAc,CAAC,MAAM,GAAG,OAAO;IAC9C,wCAAwC;IACxC,EAAE,EAAE,MAAM,CAAC;IACX,mBAAmB;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,mBAAmB,CAAC;IAC5B,kDAAkD;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,qGAAqG;IACrG,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,wEAAwE;IACxE,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Workspace-tab framework contract.
3
+ *
4
+ * A "workspace" is a screen where the user builds several drafts in parallel — each draft lives in
5
+ * a tab (browser-tab semantics: open, switch, drag-reorder, close, dirty-dot). Originated in the
6
+ * BizApps accounting JE/batch workspaces and hoisted here as the canonical implementation.
7
+ *
8
+ * v1 is **session-scoped**: a tab's state lives until the tab is closed or the session ends, and is
9
+ * deliberately **NOT DB-persisted** (DB persistence is the v2 fork). App types never appear here; a
10
+ * tab carries an opaque `State` the host owns.
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=workspace-tabs.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-tabs.types.js","sourceRoot":"","sources":["../../../src/lib/workspace-tabs/workspace-tabs.types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG","sourcesContent":["/**\n * Workspace-tab framework contract.\n *\n * A \"workspace\" is a screen where the user builds several drafts in parallel — each draft lives in\n * a tab (browser-tab semantics: open, switch, drag-reorder, close, dirty-dot). Originated in the\n * BizApps accounting JE/batch workspaces and hoisted here as the canonical implementation.\n *\n * v1 is **session-scoped**: a tab's state lives until the tab is closed or the session ends, and is\n * deliberately **NOT DB-persisted** (DB persistence is the v2 fork). App types never appear here; a\n * tab carries an opaque `State` the host owns.\n */\n\n/** Lifecycle state of a draft tab. */\nexport type MJWorkspaceTabState =\n /** Normal in-progress draft. */\n | 'draft'\n /** Round-tripped after a rejection — the tab returns for rework carrying its rejection context. */\n | 'rejected'\n /** Committed/built — kept open read-only until the user closes it. */\n | 'complete';\n\n/**\n * One workspace tab. `State` is intentionally `unknown`: the framework moves tabs around and never\n * inspects their payload, which is what keeps it app-agnostic. Hosts narrow it themselves — this is\n * the layer boundary, not weak typing.\n */\nexport interface MJWorkspaceTab<TState = unknown> {\n /** Stable identity within the strip. */\n Id: string;\n /** Tab caption. */\n Label: string;\n /** Optional Font Awesome class rendered before the label. */\n Icon?: string;\n Status: MJWorkspaceTabState;\n /** Host-owned payload — the in-progress draft. */\n State: TState;\n /** Set when Status is 'rejected'; surfaced as the tab tooltip so the reason travels with the tab. */\n RejectionReason?: string | null;\n /** True when the tab has unsaved edits — drives the discard confirm. */\n Dirty?: boolean;\n}\n"]}
@@ -0,0 +1,34 @@
1
+ import { OnDestroy } from '@angular/core';
2
+ import * as i0 from "@angular/core";
3
+ /**
4
+ * `mjTip` — a small, reusable, THEMED hover tooltip for dense surfaces (tab labels, truncated
5
+ * selects, …). Behavior:
6
+ * - shows the full text only after the pointer holds STILL over the host (~450ms);
7
+ * - NON-INTERACTIVE (`pointer-events:none`) so it never blocks a click, and leaves on the next mousemove;
8
+ * - by default shows ONLY when the host is truncated (`scrollWidth > clientWidth`) — pass `mjTipAlways`
9
+ * for hosts whose truncation can't be measured (a native `<select>`), so the full value shows regardless;
10
+ * - themed via design tokens (inline `var()` styles, since it is appended to `<body>`), with a NEUTRAL
11
+ * `rgba(0,0,0,…)` shadow so it reads as a shadow in BOTH light and dark mode (a token-tinted shadow
12
+ * glows in dark). Capped at ~1.5 tab-widths × 3 lines — never a screen-wide banner.
13
+ */
14
+ export declare class MJWorkspaceTipDirective implements OnDestroy {
15
+ private host;
16
+ private r;
17
+ Text: string;
18
+ /** Show even when the host isn't measurably truncated (e.g. a native <select>). */
19
+ Always: boolean;
20
+ private timer;
21
+ private tip;
22
+ onEnter(): void;
23
+ onMove(): void;
24
+ onLeave(): void;
25
+ ngOnDestroy(): void;
26
+ private arm;
27
+ private clear;
28
+ private show;
29
+ private styleTip;
30
+ private hide;
31
+ static ɵfac: i0.ɵɵFactoryDeclaration<MJWorkspaceTipDirective, never>;
32
+ static ɵdir: i0.ɵɵDirectiveDeclaration<MJWorkspaceTipDirective, "[mjTip]", never, { "Text": { "alias": "mjTip"; "required": false; }; "Always": { "alias": "mjTipAlways"; "required": false; }; }, {}, never, never, true, never>;
33
+ }
34
+ //# sourceMappingURL=workspace-tip.directive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-tip.directive.d.ts","sourceRoot":"","sources":["../../../src/lib/workspace-tabs/workspace-tip.directive.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8C,SAAS,EAAqB,MAAM,eAAe,CAAC;;AAKzG;;;;;;;;;;GAUG;AACH,qBACa,uBAAwB,YAAW,SAAS;IACvD,OAAO,CAAC,IAAI,CAAmD;IAC/D,OAAO,CAAC,CAAC,CAAqB;IAEd,IAAI,SAAM;IAC1B,mFAAmF;IAC7D,MAAM,UAAS;IAErC,OAAO,CAAC,KAAK,CAA8C;IAC3D,OAAO,CAAC,GAAG,CAA4B;IAEX,OAAO,IAAI,IAAI;IAGhB,MAAM,IAAI,IAAI;IAIb,OAAO,IAAI,IAAI;IAI3C,WAAW,IAAI,IAAI;IAKnB,OAAO,CAAC,GAAG;IAIX,OAAO,CAAC,KAAK;IAOb,OAAO,CAAC,IAAI;IAqBZ,OAAO,CAAC,QAAQ;IAuBhB,OAAO,CAAC,IAAI;yCAlFD,uBAAuB;2CAAvB,uBAAuB;CAwFnC"}
@@ -0,0 +1,123 @@
1
+ import { Directive, ElementRef, HostListener, Input, Renderer2, inject } from '@angular/core';
2
+ import * as i0 from "@angular/core";
3
+ const DELAY_MS = 450;
4
+ const MAX_WIDTH = 300; // ~1.5 tab-widths; height is capped at 3 lines below.
5
+ /**
6
+ * `mjTip` — a small, reusable, THEMED hover tooltip for dense surfaces (tab labels, truncated
7
+ * selects, …). Behavior:
8
+ * - shows the full text only after the pointer holds STILL over the host (~450ms);
9
+ * - NON-INTERACTIVE (`pointer-events:none`) so it never blocks a click, and leaves on the next mousemove;
10
+ * - by default shows ONLY when the host is truncated (`scrollWidth > clientWidth`) — pass `mjTipAlways`
11
+ * for hosts whose truncation can't be measured (a native `<select>`), so the full value shows regardless;
12
+ * - themed via design tokens (inline `var()` styles, since it is appended to `<body>`), with a NEUTRAL
13
+ * `rgba(0,0,0,…)` shadow so it reads as a shadow in BOTH light and dark mode (a token-tinted shadow
14
+ * glows in dark). Capped at ~1.5 tab-widths × 3 lines — never a screen-wide banner.
15
+ */
16
+ export class MJWorkspaceTipDirective {
17
+ host = inject(ElementRef).nativeElement;
18
+ r = inject(Renderer2);
19
+ Text = '';
20
+ /** Show even when the host isn't measurably truncated (e.g. a native <select>). */
21
+ Always = false;
22
+ timer = null;
23
+ tip = null;
24
+ onEnter() {
25
+ this.arm();
26
+ }
27
+ onMove() {
28
+ this.hide();
29
+ this.arm();
30
+ }
31
+ onLeave() {
32
+ this.clear();
33
+ this.hide();
34
+ }
35
+ ngOnDestroy() {
36
+ this.clear();
37
+ this.hide();
38
+ }
39
+ arm() {
40
+ this.clear();
41
+ this.timer = setTimeout(() => this.show(), DELAY_MS);
42
+ }
43
+ clear() {
44
+ if (this.timer) {
45
+ clearTimeout(this.timer);
46
+ this.timer = null;
47
+ }
48
+ }
49
+ show() {
50
+ this.timer = null;
51
+ const text = (this.Text ?? '').trim();
52
+ if (!text)
53
+ return;
54
+ if (!this.Always && this.host.scrollWidth <= this.host.clientWidth + 1)
55
+ return;
56
+ const rect = this.host.getBoundingClientRect();
57
+ const el = this.r.createElement('div');
58
+ this.r.setProperty(el, 'textContent', text);
59
+ this.r.setAttribute(el, 'role', 'tooltip');
60
+ this.styleTip(el.style);
61
+ this.r.appendChild(document.body, el);
62
+ this.tip = el;
63
+ // Keep it on-screen (measured after append) — clamp right, flip above if it would overflow bottom.
64
+ const left = Math.max(4, Math.min(Math.round(rect.left), window.innerWidth - el.offsetWidth - 4));
65
+ let top = Math.round(rect.bottom + 4);
66
+ if (top + el.offsetHeight > window.innerHeight - 4)
67
+ top = Math.max(4, Math.round(rect.top - el.offsetHeight - 4));
68
+ el.style.left = `${left}px`;
69
+ el.style.top = `${top}px`;
70
+ }
71
+ styleTip(s) {
72
+ s.position = 'fixed';
73
+ s.left = '0';
74
+ s.top = '0';
75
+ s.zIndex = '1000';
76
+ s.pointerEvents = 'none';
77
+ s.maxWidth = `${MAX_WIDTH}px`;
78
+ s.overflow = 'hidden';
79
+ s.display = '-webkit-box';
80
+ s.setProperty('-webkit-line-clamp', '3');
81
+ s.setProperty('-webkit-box-orient', 'vertical');
82
+ s.padding = '5px 9px';
83
+ s.borderRadius = '6px';
84
+ s.background = 'var(--mj-bg-surface-elevated, var(--mj-bg-surface))';
85
+ s.border = '1px solid var(--mj-border-default)';
86
+ s.boxShadow = '0 2px 8px rgba(0, 0, 0, 0.18)';
87
+ s.color = 'var(--mj-text-primary)';
88
+ s.fontSize = '12px';
89
+ s.lineHeight = '1.35';
90
+ s.whiteSpace = 'normal';
91
+ s.wordBreak = 'break-word';
92
+ }
93
+ hide() {
94
+ if (this.tip) {
95
+ this.r.removeChild(document.body, this.tip);
96
+ this.tip = null;
97
+ }
98
+ }
99
+ static ɵfac = function MJWorkspaceTipDirective_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MJWorkspaceTipDirective)(); };
100
+ static ɵdir = /*@__PURE__*/ i0.ɵɵdefineDirective({ type: MJWorkspaceTipDirective, selectors: [["", "mjTip", ""]], hostBindings: function MJWorkspaceTipDirective_HostBindings(rf, ctx) { if (rf & 1) {
101
+ i0.ɵɵlistener("mouseenter", function MJWorkspaceTipDirective_mouseenter_HostBindingHandler() { return ctx.onEnter(); })("mousemove", function MJWorkspaceTipDirective_mousemove_HostBindingHandler() { return ctx.onMove(); })("mouseleave", function MJWorkspaceTipDirective_mouseleave_HostBindingHandler() { return ctx.onLeave(); });
102
+ } }, inputs: { Text: [0, "mjTip", "Text"], Always: [0, "mjTipAlways", "Always"] } });
103
+ }
104
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MJWorkspaceTipDirective, [{
105
+ type: Directive,
106
+ args: [{ selector: '[mjTip]', standalone: true }]
107
+ }], null, { Text: [{
108
+ type: Input,
109
+ args: ['mjTip']
110
+ }], Always: [{
111
+ type: Input,
112
+ args: ['mjTipAlways']
113
+ }], onEnter: [{
114
+ type: HostListener,
115
+ args: ['mouseenter']
116
+ }], onMove: [{
117
+ type: HostListener,
118
+ args: ['mousemove']
119
+ }], onLeave: [{
120
+ type: HostListener,
121
+ args: ['mouseleave']
122
+ }] }); })();
123
+ //# sourceMappingURL=workspace-tip.directive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-tip.directive.js","sourceRoot":"","sources":["../../../src/lib/workspace-tabs/workspace-tip.directive.ts"],"names":[],"mappings":"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","sourcesContent":["import { Directive, ElementRef, HostListener, Input, OnDestroy, Renderer2, inject } from '@angular/core';\n\nconst DELAY_MS = 450;\nconst MAX_WIDTH = 300; // ~1.5 tab-widths; height is capped at 3 lines below.\n\n/**\n * `mjTip` — a small, reusable, THEMED hover tooltip for dense surfaces (tab labels, truncated\n * selects, …). Behavior:\n * - shows the full text only after the pointer holds STILL over the host (~450ms);\n * - NON-INTERACTIVE (`pointer-events:none`) so it never blocks a click, and leaves on the next mousemove;\n * - by default shows ONLY when the host is truncated (`scrollWidth > clientWidth`) — pass `mjTipAlways`\n * for hosts whose truncation can't be measured (a native `<select>`), so the full value shows regardless;\n * - themed via design tokens (inline `var()` styles, since it is appended to `<body>`), with a NEUTRAL\n * `rgba(0,0,0,…)` shadow so it reads as a shadow in BOTH light and dark mode (a token-tinted shadow\n * glows in dark). Capped at ~1.5 tab-widths × 3 lines — never a screen-wide banner.\n */\n@Directive({ selector: '[mjTip]', standalone: true })\nexport class MJWorkspaceTipDirective implements OnDestroy {\n private host = inject(ElementRef).nativeElement as HTMLElement;\n private r = inject(Renderer2);\n\n @Input('mjTip') Text = '';\n /** Show even when the host isn't measurably truncated (e.g. a native <select>). */\n @Input('mjTipAlways') Always = false;\n\n private timer: ReturnType<typeof setTimeout> | null = null;\n private tip: HTMLElement | null = null;\n\n @HostListener('mouseenter') onEnter(): void {\n this.arm();\n }\n @HostListener('mousemove') onMove(): void {\n this.hide();\n this.arm();\n }\n @HostListener('mouseleave') onLeave(): void {\n this.clear();\n this.hide();\n }\n ngOnDestroy(): void {\n this.clear();\n this.hide();\n }\n\n private arm(): void {\n this.clear();\n this.timer = setTimeout(() => this.show(), DELAY_MS);\n }\n private clear(): void {\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n }\n\n private show(): void {\n this.timer = null;\n const text = (this.Text ?? '').trim();\n if (!text) return;\n if (!this.Always && this.host.scrollWidth <= this.host.clientWidth + 1) return;\n\n const rect = this.host.getBoundingClientRect();\n const el = this.r.createElement('div') as HTMLElement;\n this.r.setProperty(el, 'textContent', text);\n this.r.setAttribute(el, 'role', 'tooltip');\n this.styleTip(el.style);\n this.r.appendChild(document.body, el);\n this.tip = el;\n // Keep it on-screen (measured after append) — clamp right, flip above if it would overflow bottom.\n const left = Math.max(4, Math.min(Math.round(rect.left), window.innerWidth - el.offsetWidth - 4));\n let top = Math.round(rect.bottom + 4);\n if (top + el.offsetHeight > window.innerHeight - 4) top = Math.max(4, Math.round(rect.top - el.offsetHeight - 4));\n el.style.left = `${left}px`;\n el.style.top = `${top}px`;\n }\n\n private styleTip(s: CSSStyleDeclaration): void {\n s.position = 'fixed';\n s.left = '0';\n s.top = '0';\n s.zIndex = '1000';\n s.pointerEvents = 'none';\n s.maxWidth = `${MAX_WIDTH}px`;\n s.overflow = 'hidden';\n s.display = '-webkit-box';\n s.setProperty('-webkit-line-clamp', '3');\n s.setProperty('-webkit-box-orient', 'vertical');\n s.padding = '5px 9px';\n s.borderRadius = '6px';\n s.background = 'var(--mj-bg-surface-elevated, var(--mj-bg-surface))';\n s.border = '1px solid var(--mj-border-default)';\n s.boxShadow = '0 2px 8px rgba(0, 0, 0, 0.18)';\n s.color = 'var(--mj-text-primary)';\n s.fontSize = '12px';\n s.lineHeight = '1.35';\n s.whiteSpace = 'normal';\n s.wordBreak = 'break-word';\n }\n\n private hide(): void {\n if (this.tip) {\n this.r.removeChild(document.body, this.tip);\n this.tip = null;\n }\n }\n}\n"]}
@@ -15,6 +15,7 @@ export * from './lib/accordion/accordion.component';
15
15
  export * from './lib/alert/alert.component';
16
16
  export * from './lib/window/window.component';
17
17
  export * from './lib/slide-panel/slide-panel.component';
18
+ export * from './lib/bottom-sheet/bottom-sheet.component';
18
19
  export * from './lib/combobox/combobox.component';
19
20
  export * from './lib/page-header/page-header.component';
20
21
  export * from './lib/page-layout/page-layout.component';
@@ -27,6 +28,13 @@ export * from './lib/filter-chip/filter-chip.component';
27
28
  export * from './lib/filter-field/filter-field.component';
28
29
  export * from './lib/filter-panel/filter-panel.component';
29
30
  export * from './lib/tab-nav/tab-nav.component';
31
+ export * from './lib/tabs/tab-list.directive';
32
+ export * from './lib/tabs/tab-chrome-guard';
33
+ export * from './lib/workspace-tabs/workspace-tabs.types';
34
+ export * from './lib/workspace-tabs/workspace-tab-store';
35
+ export * from './lib/workspace-tabs/workspace-tab-strip.component';
36
+ export * from './lib/workspace-tabs/workspace-card.component';
37
+ export * from './lib/workspace-tabs/workspace-tip.directive';
30
38
  export * from './lib/view-toggle/view-toggle.component';
31
39
  export * from './lib/left-nav/left-nav.component';
32
40
  export * from './lib/left-nav/left-nav-content.component';
@@ -1 +1 @@
1
- {"version":3,"file":"public-api.d.ts","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAGA,cAAc,+BAA+B,CAAC;AAC9C,cAAc,qCAAqC,CAAC;AACpD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+CAA+C,CAAC;AAC9D,cAAc,6CAA6C,CAAC;AAC5D,cAAc,mCAAmC,CAAC;AAClD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6CAA6C,CAAC;AAC5D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uCAAuC,CAAC;AACtD,cAAc,mCAAmC,CAAC;AAClD,cAAc,qCAAqC,CAAC;AACpD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,yCAAyC,CAAC;AACxD,cAAc,mCAAmC,CAAC;AAClD,cAAc,yCAAyC,CAAC;AACxD,cAAc,yCAAyC,CAAC;AACxD,cAAc,qCAAqC,CAAC;AACpD,cAAc,uCAAuC,CAAC;AACtD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,+CAA+C,CAAC;AAC9D,cAAc,yCAAyC,CAAC;AACxD,cAAc,yCAAyC,CAAC;AACxD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,iCAAiC,CAAC;AAChD,cAAc,yCAAyC,CAAC;AACxD,cAAc,mCAAmC,CAAC;AAClD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,2DAA2D,CAAC;AAC1E,cAAc,uDAAuD,CAAC;AACtE,cAAc,yCAAyC,CAAC"}
1
+ {"version":3,"file":"public-api.d.ts","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAGA,cAAc,+BAA+B,CAAC;AAC9C,cAAc,qCAAqC,CAAC;AACpD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+CAA+C,CAAC;AAC9D,cAAc,6CAA6C,CAAC;AAC5D,cAAc,mCAAmC,CAAC;AAClD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6CAA6C,CAAC;AAC5D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uCAAuC,CAAC;AACtD,cAAc,mCAAmC,CAAC;AAClD,cAAc,qCAAqC,CAAC;AACpD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,yCAAyC,CAAC;AACxD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,mCAAmC,CAAC;AAClD,cAAc,yCAAyC,CAAC;AACxD,cAAc,yCAAyC,CAAC;AACxD,cAAc,qCAAqC,CAAC;AACpD,cAAc,uCAAuC,CAAC;AACtD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,+CAA+C,CAAC;AAC9D,cAAc,yCAAyC,CAAC;AACxD,cAAc,yCAAyC,CAAC;AACxD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,iCAAiC,CAAC;AAChD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2CAA2C,CAAC;AAC1D,cAAc,0CAA0C,CAAC;AACzD,cAAc,oDAAoD,CAAC;AACnE,cAAc,+CAA+C,CAAC;AAC9D,cAAc,8CAA8C,CAAC;AAC7D,cAAc,yCAAyC,CAAC;AACxD,cAAc,mCAAmC,CAAC;AAClD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,2DAA2D,CAAC;AAC1E,cAAc,uDAAuD,CAAC;AACtE,cAAc,yCAAyC,CAAC"}
@@ -17,6 +17,7 @@ export * from './lib/accordion/accordion.component';
17
17
  export * from './lib/alert/alert.component';
18
18
  export * from './lib/window/window.component';
19
19
  export * from './lib/slide-panel/slide-panel.component';
20
+ export * from './lib/bottom-sheet/bottom-sheet.component';
20
21
  export * from './lib/combobox/combobox.component';
21
22
  export * from './lib/page-header/page-header.component';
22
23
  export * from './lib/page-layout/page-layout.component';
@@ -29,6 +30,13 @@ export * from './lib/filter-chip/filter-chip.component';
29
30
  export * from './lib/filter-field/filter-field.component';
30
31
  export * from './lib/filter-panel/filter-panel.component';
31
32
  export * from './lib/tab-nav/tab-nav.component';
33
+ export * from './lib/tabs/tab-list.directive';
34
+ export * from './lib/tabs/tab-chrome-guard';
35
+ export * from './lib/workspace-tabs/workspace-tabs.types';
36
+ export * from './lib/workspace-tabs/workspace-tab-store';
37
+ export * from './lib/workspace-tabs/workspace-tab-strip.component';
38
+ export * from './lib/workspace-tabs/workspace-card.component';
39
+ export * from './lib/workspace-tabs/workspace-tip.directive';
32
40
  export * from './lib/view-toggle/view-toggle.component';
33
41
  export * from './lib/left-nav/left-nav.component';
34
42
  export * from './lib/left-nav/left-nav-content.component';
@@ -1 +1 @@
1
- {"version":3,"file":"public-api.js","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,+DAA+D;AAE/D,cAAc,+BAA+B,CAAC;AAC9C,cAAc,qCAAqC,CAAC;AACpD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+CAA+C,CAAC;AAC9D,cAAc,6CAA6C,CAAC;AAC5D,cAAc,mCAAmC,CAAC;AAClD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6CAA6C,CAAC;AAC5D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uCAAuC,CAAC;AACtD,cAAc,mCAAmC,CAAC;AAClD,cAAc,qCAAqC,CAAC;AACpD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,yCAAyC,CAAC;AACxD,cAAc,mCAAmC,CAAC;AAClD,cAAc,yCAAyC,CAAC;AACxD,cAAc,yCAAyC,CAAC;AACxD,cAAc,qCAAqC,CAAC;AACpD,cAAc,uCAAuC,CAAC;AACtD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,+CAA+C,CAAC;AAC9D,cAAc,yCAAyC,CAAC;AACxD,cAAc,yCAAyC,CAAC;AACxD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,iCAAiC,CAAC;AAChD,cAAc,yCAAyC,CAAC;AACxD,cAAc,mCAAmC,CAAC;AAClD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,2DAA2D,CAAC;AAC1E,cAAc,uDAAuD,CAAC;AACtE,cAAc,yCAAyC,CAAC","sourcesContent":["// @memberjunction/ng-ui-components\n// Reusable standalone Angular UI components for MemberJunction\n\nexport * from './lib/button/button.directive';\nexport * from './lib/clickable/clickable.directive';\nexport * from './lib/dialog/dialog.component';\nexport * from './lib/dialog/dialog.service';\nexport * from './lib/confirm-dialog/confirm-dialog.component';\nexport * from './lib/confirm-dialog/confirm-dialog.service';\nexport * from './lib/dropdown/dropdown.component';\nexport * from './lib/switch/switch.component';\nexport * from './lib/numeric-input/numeric-input.component';\nexport * from './lib/progress-bar/progress-bar.component';\nexport * from './lib/calendar/calendar-utils';\nexport * from './lib/datepicker/datepicker.component';\nexport * from './lib/splitter/splitter.component';\nexport * from './lib/accordion/accordion.component';\nexport * from './lib/alert/alert.component';\nexport * from './lib/window/window.component';\nexport * from './lib/slide-panel/slide-panel.component';\nexport * from './lib/combobox/combobox.component';\nexport * from './lib/page-header/page-header.component';\nexport * from './lib/page-layout/page-layout.component';\nexport * from './lib/page-body/page-body.component';\nexport * from './lib/stat-badge/stat-badge.component';\nexport * from './lib/refresh-button/refresh-button.component';\nexport * from './lib/filter-popover/filter-popover.component';\nexport * from './lib/page-search/page-search.component';\nexport * from './lib/filter-chip/filter-chip.component';\nexport * from './lib/filter-field/filter-field.component';\nexport * from './lib/filter-panel/filter-panel.component';\nexport * from './lib/tab-nav/tab-nav.component';\nexport * from './lib/view-toggle/view-toggle.component';\nexport * from './lib/left-nav/left-nav.component';\nexport * from './lib/left-nav/left-nav-content.component';\nexport * from './lib/page-header-interior/page-header-interior.component';\nexport * from './lib/page-body-interior/page-body-interior.component';\nexport * from './lib/empty-state/empty-state.component';\n"]}
1
+ {"version":3,"file":"public-api.js","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,+DAA+D;AAE/D,cAAc,+BAA+B,CAAC;AAC9C,cAAc,qCAAqC,CAAC;AACpD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+CAA+C,CAAC;AAC9D,cAAc,6CAA6C,CAAC;AAC5D,cAAc,mCAAmC,CAAC;AAClD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6CAA6C,CAAC;AAC5D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uCAAuC,CAAC;AACtD,cAAc,mCAAmC,CAAC;AAClD,cAAc,qCAAqC,CAAC;AACpD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,yCAAyC,CAAC;AACxD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,mCAAmC,CAAC;AAClD,cAAc,yCAAyC,CAAC;AACxD,cAAc,yCAAyC,CAAC;AACxD,cAAc,qCAAqC,CAAC;AACpD,cAAc,uCAAuC,CAAC;AACtD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,+CAA+C,CAAC;AAC9D,cAAc,yCAAyC,CAAC;AACxD,cAAc,yCAAyC,CAAC;AACxD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,iCAAiC,CAAC;AAChD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2CAA2C,CAAC;AAC1D,cAAc,0CAA0C,CAAC;AACzD,cAAc,oDAAoD,CAAC;AACnE,cAAc,+CAA+C,CAAC;AAC9D,cAAc,8CAA8C,CAAC;AAC7D,cAAc,yCAAyC,CAAC;AACxD,cAAc,mCAAmC,CAAC;AAClD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,2DAA2D,CAAC;AAC1E,cAAc,uDAAuD,CAAC;AACtE,cAAc,yCAAyC,CAAC","sourcesContent":["// @memberjunction/ng-ui-components\n// Reusable standalone Angular UI components for MemberJunction\n\nexport * from './lib/button/button.directive';\nexport * from './lib/clickable/clickable.directive';\nexport * from './lib/dialog/dialog.component';\nexport * from './lib/dialog/dialog.service';\nexport * from './lib/confirm-dialog/confirm-dialog.component';\nexport * from './lib/confirm-dialog/confirm-dialog.service';\nexport * from './lib/dropdown/dropdown.component';\nexport * from './lib/switch/switch.component';\nexport * from './lib/numeric-input/numeric-input.component';\nexport * from './lib/progress-bar/progress-bar.component';\nexport * from './lib/calendar/calendar-utils';\nexport * from './lib/datepicker/datepicker.component';\nexport * from './lib/splitter/splitter.component';\nexport * from './lib/accordion/accordion.component';\nexport * from './lib/alert/alert.component';\nexport * from './lib/window/window.component';\nexport * from './lib/slide-panel/slide-panel.component';\nexport * from './lib/bottom-sheet/bottom-sheet.component';\nexport * from './lib/combobox/combobox.component';\nexport * from './lib/page-header/page-header.component';\nexport * from './lib/page-layout/page-layout.component';\nexport * from './lib/page-body/page-body.component';\nexport * from './lib/stat-badge/stat-badge.component';\nexport * from './lib/refresh-button/refresh-button.component';\nexport * from './lib/filter-popover/filter-popover.component';\nexport * from './lib/page-search/page-search.component';\nexport * from './lib/filter-chip/filter-chip.component';\nexport * from './lib/filter-field/filter-field.component';\nexport * from './lib/filter-panel/filter-panel.component';\nexport * from './lib/tab-nav/tab-nav.component';\nexport * from './lib/tabs/tab-list.directive';\nexport * from './lib/tabs/tab-chrome-guard';\nexport * from './lib/workspace-tabs/workspace-tabs.types';\nexport * from './lib/workspace-tabs/workspace-tab-store';\nexport * from './lib/workspace-tabs/workspace-tab-strip.component';\nexport * from './lib/workspace-tabs/workspace-card.component';\nexport * from './lib/workspace-tabs/workspace-tip.directive';\nexport * from './lib/view-toggle/view-toggle.component';\nexport * from './lib/left-nav/left-nav.component';\nexport * from './lib/left-nav/left-nav-content.component';\nexport * from './lib/page-header-interior/page-header-interior.component';\nexport * from './lib/page-body-interior/page-body-interior.component';\nexport * from './lib/empty-state/empty-state.component';\n"]}