@filip.mazev/blocks 1.4.15 → 1.4.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,14 +1,14 @@
1
1
  import { BxSurfaceDirective } from "@filip.mazev/blocks/effects";
2
2
  import * as i0 from "@angular/core";
3
- import { ChangeDetectionStrategy, Component, DestroyRef, Directive, ElementRef, HostListener, InjectionToken, NgZone, PLATFORM_ID, TemplateRef, ViewContainerRef, afterNextRender, afterRenderEffect, booleanAttribute, computed, contentChild, contentChildren, effect, forwardRef, inject, input, model, output, signal, viewChild, viewChildren } from "@angular/core";
4
- import { BX_I18N, BxA11yService, BxOverlayPositionService, BxShortcutService, inheritOverlayTheme, isTextWithKey, resolveTokenToCssVar, trackOverlayOrigin, uuidv4 } from "@filip.mazev/blocks/core";
3
+ import { ChangeDetectionStrategy, Component, DestroyRef, Directive, ElementRef, HostListener, InjectionToken, NgZone, PLATFORM_ID, Pipe, TemplateRef, ViewContainerRef, afterEveryRender, afterNextRender, afterRenderEffect, booleanAttribute, computed, contentChild, contentChildren, effect, forwardRef, inject, input, model, output, signal, viewChild, viewChildren } from "@angular/core";
4
+ import { BX_I18N, BxA11yService, BxOverlayPositionService, BxShortcutService, inheritOverlayTheme, isTextWithKey, resolveText, resolveTokenToCssVar, trackOverlayOrigin, uuidv4 } from "@filip.mazev/blocks/core";
5
5
  import { Icon } from "@filip.mazev/blocks/icons";
6
- import { NgTemplateOutlet, isPlatformBrowser } from "@angular/common";
7
6
  import { AriaDescriber, FocusMonitor } from "@angular/cdk/a11y";
8
7
  import { Overlay } from "@angular/cdk/overlay";
9
8
  import { ComponentPortal, TemplatePortal } from "@angular/cdk/portal";
10
9
  import { createGlassTransition, inheritGlassLighting } from "@filip.mazev/blocks/effects/runtime";
11
10
  import { Subscription } from "rxjs";
11
+ import { NgTemplateOutlet, isPlatformBrowser } from "@angular/common";
12
12
  var Tooltip = class Tooltip {
13
13
  i18n = inject(BX_I18N, { optional: true });
14
14
  a11y = inject(BxA11yService);
@@ -125,190 +125,1160 @@ i0.ɵɵngDeclareClassMetadata({
125
125
  }]
126
126
  }]
127
127
  });
128
- var MenuItem = class MenuItem {
129
- i18n = inject(BX_I18N, { optional: true });
128
+ const BX_OVERLAY_CONTEXT = new InjectionToken("BX_OVERLAY_CONTEXT");
129
+ var ContextMenuDirective = class ContextMenuDirective {
130
+ overlay = inject(Overlay);
131
+ positionBuilder = inject(BxOverlayPositionService);
132
+ overlayContext = inject(BX_OVERLAY_CONTEXT, { optional: true });
133
+ elementRef = inject(ElementRef);
130
134
  a11y = inject(BxA11yService);
131
- bxShortcutService = inject(BxShortcutService);
132
- resolvedLabel = computed(() => {
133
- this.i18n?.version?.();
134
- const label = this.label();
135
- if (!label) return void 0;
136
- if (isTextWithKey(label)) return this.i18n?.translate(label.key) ?? label.key;
137
- return label;
138
- }, ...ngDevMode ? [{ debugName: "resolvedLabel" }] : /* istanbul ignore next */ []);
139
- resolvedShortcut = computed(() => {
140
- return this.bxShortcutService.resolve(this.shortcut());
141
- }, ...ngDevMode ? [{ debugName: "resolvedShortcut" }] : /* istanbul ignore next */ []);
142
- isAnimated = computed(() => !this.a11y.isReducedMotion(), ...ngDevMode ? [{ debugName: "isAnimated" }] : /* istanbul ignore next */ []);
143
- icon = input(void 0, ...ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []);
144
- endIcon = input(void 0, ...ngDevMode ? [{ debugName: "endIcon" }] : /* istanbul ignore next */ []);
145
- label = input(void 0, ...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
146
- wrapLabel = input(false, ...ngDevMode ? [{ debugName: "wrapLabel" }] : /* istanbul ignore next */ []);
147
- disabled = input(false, ...ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []);
148
- danger = input(false, ...ngDevMode ? [{ debugName: "danger" }] : /* istanbul ignore next */ []);
149
- shortcut = input(void 0, ...ngDevMode ? [{ debugName: "shortcut" }] : /* istanbul ignore next */ []);
150
- action = output();
151
- onClick(event) {
152
- if (this.disabled()) {
135
+ zone = inject(NgZone);
136
+ vcr = inject(ViewContainerRef);
137
+ bxContextMenu = input.required(...ngDevMode ? [{ debugName: "bxContextMenu" }] : /* istanbul ignore next */ []);
138
+ bxContextMenuLongPress = input(true, {
139
+ ...ngDevMode ? { debugName: "bxContextMenuLongPress" } : /* istanbul ignore next */ {},
140
+ transform: booleanAttribute
141
+ });
142
+ onPointerDown = (event) => {
143
+ this.lastPointerType = event.pointerType;
144
+ this.cancelTouchPress();
145
+ if (event.isPrimary) this.clearTouchGuard();
146
+ if (event.pointerType !== "touch" || !event.isPrimary || event.button !== 0 || !this.bxContextMenuLongPress() || this.hasNativeTouchAction(event)) return;
147
+ const doc = this.elementRef.nativeElement.ownerDocument;
148
+ const win = doc.defaultView;
149
+ if (!win || this.hasTextSelection()) return;
150
+ const press = {
151
+ pointerId: event.pointerId,
152
+ x: event.clientX,
153
+ y: event.clientY,
154
+ timer: 0,
155
+ opened: false,
156
+ events: new AbortController()
157
+ };
158
+ this.touchPress = press;
159
+ const options = {
160
+ capture: true,
161
+ passive: true,
162
+ signal: press.events.signal
163
+ };
164
+ const finish = () => this.cancelTouchPress();
165
+ doc.addEventListener("pointermove", (move) => {
166
+ if (move.pointerId === press.pointerId && !press.opened && Math.hypot(move.clientX - press.x, move.clientY - press.y) > 10) finish();
167
+ }, options);
168
+ for (const type of ["pointerup", "pointercancel"]) doc.addEventListener(type, (end) => {
169
+ if (end.pointerId === press.pointerId) finish();
170
+ }, options);
171
+ doc.addEventListener("pointerdown", (next) => {
172
+ if (next.pointerId !== press.pointerId) finish();
173
+ }, options);
174
+ doc.addEventListener("scroll", finish, options);
175
+ doc.addEventListener("visibilitychange", () => {
176
+ if (doc.hidden) finish();
177
+ }, options);
178
+ win.addEventListener("blur", finish, { signal: press.events.signal });
179
+ press.timer = win.setTimeout(() => this.zone.run(() => this.openTouchMenu(press)), 500);
180
+ };
181
+ overlayRef = null;
182
+ transition;
183
+ point;
184
+ disconnectTheme;
185
+ disconnectLighting;
186
+ subscriptions = new Subscription();
187
+ revision = 0;
188
+ touchPress;
189
+ touchGuard;
190
+ touchGuardTimer;
191
+ lastPointerType = "";
192
+ constructor() {
193
+ const source = this.elementRef.nativeElement;
194
+ if (source.ownerDocument.defaultView) this.zone.runOutsideAngular(() => source.addEventListener("pointerdown", this.onPointerDown, { passive: true }));
195
+ inject(DestroyRef).onDestroy(() => {
196
+ ++this.revision;
197
+ source.removeEventListener("pointerdown", this.onPointerDown);
198
+ this.cancelTouchPress();
199
+ this.clearTouchGuard();
200
+ this.dispose();
201
+ });
202
+ }
203
+ open(event) {
204
+ if (event.type === "contextmenu" && this.lastPointerType === "touch") {
205
+ const press = this.touchPress;
206
+ if (!press) return;
207
+ if (!this.bxContextMenuLongPress() || this.hasNativeTouchAction(event) || this.hasTextSelection()) {
208
+ this.cancelTouchPress();
209
+ return;
210
+ }
153
211
  event.preventDefault();
154
- event.stopPropagation();
212
+ this.openTouchMenu(press);
155
213
  return;
156
214
  }
157
- this.action.emit(event);
215
+ event.preventDefault();
216
+ this.cancelTouchPress();
217
+ this.clearTouchGuard();
218
+ this.openAt(event.clientX, event.clientY);
158
219
  }
159
- static ɵfac = i0.ɵɵngDeclareFactory({
160
- minVersion: "12.0.0",
161
- version: "22.2.3",
162
- ngImport: i0,
163
- type: MenuItem,
164
- deps: [],
165
- target: i0.ɵɵFactoryTarget.Component
166
- });
167
- static ɵcmp = i0.ɵɵngDeclareComponent({
168
- minVersion: "17.0.0",
169
- version: "22.2.3",
170
- type: MenuItem,
171
- isStandalone: true,
172
- selector: "bx-menu-item",
173
- inputs: {
174
- icon: {
175
- classPropertyName: "icon",
176
- publicName: "icon",
177
- isSignal: true,
178
- isRequired: false,
179
- transformFunction: null
180
- },
181
- endIcon: {
182
- classPropertyName: "endIcon",
183
- publicName: "endIcon",
184
- isSignal: true,
185
- isRequired: false,
186
- transformFunction: null
187
- },
188
- label: {
189
- classPropertyName: "label",
190
- publicName: "label",
191
- isSignal: true,
192
- isRequired: false,
193
- transformFunction: null
194
- },
195
- wrapLabel: {
196
- classPropertyName: "wrapLabel",
197
- publicName: "wrapLabel",
198
- isSignal: true,
199
- isRequired: false,
200
- transformFunction: null
201
- },
202
- disabled: {
203
- classPropertyName: "disabled",
204
- publicName: "disabled",
205
- isSignal: true,
206
- isRequired: false,
207
- transformFunction: null
208
- },
209
- danger: {
210
- classPropertyName: "danger",
211
- publicName: "danger",
212
- isSignal: true,
213
- isRequired: false,
214
- transformFunction: null
215
- },
216
- shortcut: {
217
- classPropertyName: "shortcut",
218
- publicName: "shortcut",
219
- isSignal: true,
220
- isRequired: false,
221
- transformFunction: null
222
- }
223
- },
224
- outputs: { action: "action" },
225
- ngImport: i0,
226
- template: "<button bxSurface [bxSurfaceEmission]=\"danger() ? 'var(--bx-text-danger)' : 'var(--bx-primary)'\" type=\"button\" role=\"menuitem\" [disabled]=\"disabled()\" class=\"bx-menu-item-btn\" [class.is-disabled]=\"disabled()\" [class.is-danger]=\"danger()\"\n [class.bx-menu-item-animated]=\"isAnimated()\" (click)=\"onClick($event)\">\n\n @if (icon()) {\n <bx-icon class=\"bx-icon-pos-start\" [name]=\"icon()!\" size=\"20\" />\n }\n\n <span class=\"bx-menu-item-content\" [class.bx-menu-item-content-wrapped]=\"wrapLabel()\">\n @if (resolvedLabel()) {\n {{ resolvedLabel() }}\n } @else {\n <ng-content></ng-content>\n }\n </span>\n\n @if (resolvedShortcut()) {\n <span class=\"bx-menu-item-shortcut\">\n @for (key of resolvedShortcut(); track $index) {\n <kbd>{{ key }}</kbd>\n }\n </span>\n }\n\n @if (endIcon()) {\n <bx-icon class=\"bx-icon-pos-end\" [name]=\"endIcon()!\" size=\"20\" />\n }\n</button>\n",
227
- styles: [":host{display:block;width:100%}.bx-menu-item-btn{width:100%;display:flex;align-items:center;background:transparent!important;border:none;padding:.5rem .75rem;cursor:pointer;font-family:inherit;font-size:.875rem;text-align:left;border-radius:max(0px,var(--bx-glass-radius, var(--bx-rounded-lg, .75rem)) - .25rem);color:var(--bx-text-primary);--bx-glass-decoration-opacity: 0;--bx-glass-rim-visibility: 0;-webkit-backdrop-filter:none;backdrop-filter:none;box-shadow:none}.bx-menu-item-btn:focus-visible{outline:2px solid var(--bx-border-brand);outline-offset:-2px}.bx-menu-item-btn.bx-menu-item-animated{transition:background-color .1s ease-in-out,color .1s ease-in-out}.bx-menu-item-btn.bx-menu-item-animated .bx-menu-item-shortcut{transition:color .1s ease-in-out}.bx-menu-item-btn:hover:not(.is-disabled){background:var(--bx-bg-element-hover)!important}.bx-menu-item-btn:hover:not(.is-disabled) .bx-menu-item-shortcut{color:inherit;opacity:1}.bx-menu-item-btn:active:not(.is-disabled){background:var(--bx-bg-element-active)!important}.bx-menu-item-btn:active:not(.is-disabled) .bx-menu-item-shortcut{color:inherit;opacity:1}.bx-menu-item-btn.is-danger{color:var(--bx-text-danger)}.bx-menu-item-btn.is-danger .bx-menu-item-shortcut{color:var(--bx-text-danger);opacity:.7}.bx-menu-item-btn.is-danger:hover:not(.is-disabled){background:var(--bx-bg-danger-hover)!important}.bx-menu-item-btn.is-danger:active:not(.is-disabled){background:var(--bx-bg-danger-active)!important}.bx-menu-item-btn.is-disabled{opacity:.4;cursor:not-allowed;pointer-events:none}.bx-menu-item-content{flex:1 1 auto;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.4;text-align:left}.bx-menu-item-content-wrapped{white-space:normal;overflow:visible;text-overflow:clip;overflow-wrap:anywhere}.bx-menu-item-shortcut{display:flex;align-items:center;gap:.15rem;margin-left:1.5rem;color:var(--bx-text-secondary);font-size:.875rem}.bx-menu-item-shortcut kbd{font-family:inherit;background:transparent;border:none;box-shadow:none;padding:0;margin:0;color:inherit}\n"],
228
- dependencies: [{
229
- kind: "component",
230
- type: Icon,
231
- selector: "bx-icon",
232
- inputs: [
233
- "name",
234
- "size",
235
- "color",
236
- "bgColor",
237
- "strokeWidth",
238
- "decorative",
239
- "ariaLabel"
240
- ]
241
- }, {
242
- kind: "directive",
243
- type: BxSurfaceDirective,
244
- selector: "[bxSurface]",
245
- inputs: [
246
- "bxSurfaceInteractive",
247
- "bxSurfaceGlassiness",
248
- "bxSurfaceEmission",
249
- "bxSurfaceFocusEmission",
250
- "bxReducedTransparency"
251
- ],
252
- exportAs: ["bxSurface"]
253
- }],
254
- changeDetection: i0.ChangeDetectionStrategy.OnPush
255
- });
256
- };
257
- i0.ɵɵngDeclareClassMetadata({
258
- minVersion: "12.0.0",
259
- version: "22.2.3",
260
- ngImport: i0,
261
- type: MenuItem,
262
- decorators: [{
263
- type: Component,
264
- args: [{
265
- selector: "bx-menu-item",
266
- imports: [Icon, BxSurfaceDirective],
267
- changeDetection: ChangeDetectionStrategy.OnPush,
268
- template: "<button bxSurface [bxSurfaceEmission]=\"danger() ? 'var(--bx-text-danger)' : 'var(--bx-primary)'\" type=\"button\" role=\"menuitem\" [disabled]=\"disabled()\" class=\"bx-menu-item-btn\" [class.is-disabled]=\"disabled()\" [class.is-danger]=\"danger()\"\n [class.bx-menu-item-animated]=\"isAnimated()\" (click)=\"onClick($event)\">\n\n @if (icon()) {\n <bx-icon class=\"bx-icon-pos-start\" [name]=\"icon()!\" size=\"20\" />\n }\n\n <span class=\"bx-menu-item-content\" [class.bx-menu-item-content-wrapped]=\"wrapLabel()\">\n @if (resolvedLabel()) {\n {{ resolvedLabel() }}\n } @else {\n <ng-content></ng-content>\n }\n </span>\n\n @if (resolvedShortcut()) {\n <span class=\"bx-menu-item-shortcut\">\n @for (key of resolvedShortcut(); track $index) {\n <kbd>{{ key }}</kbd>\n }\n </span>\n }\n\n @if (endIcon()) {\n <bx-icon class=\"bx-icon-pos-end\" [name]=\"endIcon()!\" size=\"20\" />\n }\n</button>\n",
269
- styles: [":host{display:block;width:100%}.bx-menu-item-btn{width:100%;display:flex;align-items:center;background:transparent!important;border:none;padding:.5rem .75rem;cursor:pointer;font-family:inherit;font-size:.875rem;text-align:left;border-radius:max(0px,var(--bx-glass-radius, var(--bx-rounded-lg, .75rem)) - .25rem);color:var(--bx-text-primary);--bx-glass-decoration-opacity: 0;--bx-glass-rim-visibility: 0;-webkit-backdrop-filter:none;backdrop-filter:none;box-shadow:none}.bx-menu-item-btn:focus-visible{outline:2px solid var(--bx-border-brand);outline-offset:-2px}.bx-menu-item-btn.bx-menu-item-animated{transition:background-color .1s ease-in-out,color .1s ease-in-out}.bx-menu-item-btn.bx-menu-item-animated .bx-menu-item-shortcut{transition:color .1s ease-in-out}.bx-menu-item-btn:hover:not(.is-disabled){background:var(--bx-bg-element-hover)!important}.bx-menu-item-btn:hover:not(.is-disabled) .bx-menu-item-shortcut{color:inherit;opacity:1}.bx-menu-item-btn:active:not(.is-disabled){background:var(--bx-bg-element-active)!important}.bx-menu-item-btn:active:not(.is-disabled) .bx-menu-item-shortcut{color:inherit;opacity:1}.bx-menu-item-btn.is-danger{color:var(--bx-text-danger)}.bx-menu-item-btn.is-danger .bx-menu-item-shortcut{color:var(--bx-text-danger);opacity:.7}.bx-menu-item-btn.is-danger:hover:not(.is-disabled){background:var(--bx-bg-danger-hover)!important}.bx-menu-item-btn.is-danger:active:not(.is-disabled){background:var(--bx-bg-danger-active)!important}.bx-menu-item-btn.is-disabled{opacity:.4;cursor:not-allowed;pointer-events:none}.bx-menu-item-content{flex:1 1 auto;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.4;text-align:left}.bx-menu-item-content-wrapped{white-space:normal;overflow:visible;text-overflow:clip;overflow-wrap:anywhere}.bx-menu-item-shortcut{display:flex;align-items:center;gap:.15rem;margin-left:1.5rem;color:var(--bx-text-secondary);font-size:.875rem}.bx-menu-item-shortcut kbd{font-family:inherit;background:transparent;border:none;box-shadow:none;padding:0;margin:0;color:inherit}\n"]
270
- }]
271
- }],
272
- propDecorators: {
273
- icon: [{
274
- type: i0.Input,
275
- args: [{
276
- isSignal: true,
277
- alias: "icon",
278
- required: false
279
- }]
280
- }],
281
- endIcon: [{
282
- type: i0.Input,
283
- args: [{
284
- isSignal: true,
285
- alias: "endIcon",
286
- required: false
287
- }]
288
- }],
289
- label: [{
290
- type: i0.Input,
291
- args: [{
292
- isSignal: true,
293
- alias: "label",
294
- required: false
295
- }]
296
- }],
297
- wrapLabel: [{
298
- type: i0.Input,
299
- args: [{
300
- isSignal: true,
301
- alias: "wrapLabel",
302
- required: false
303
- }]
304
- }],
305
- disabled: [{
306
- type: i0.Input,
307
- args: [{
308
- isSignal: true,
309
- alias: "disabled",
310
- required: false
311
- }]
220
+ close(restoreFocus = false) {
221
+ if (!this.overlayRef) return;
222
+ const revision = ++this.revision;
223
+ if (restoreFocus || this.overlayRef.overlayElement.contains(this.elementRef.nativeElement.ownerDocument.activeElement)) this.elementRef.nativeElement.focus({ preventScroll: true });
224
+ this.overlayRef.overlayElement.inert = true;
225
+ const transition = this.transition;
226
+ if (transition && !this.a11y.isReducedMotion()) this.zone.runOutsideAngular(() => transition.exit()).then(() => {
227
+ if (revision === this.revision) this.dispose();
228
+ }).catch(() => {
229
+ if (revision === this.revision) this.dispose();
230
+ });
231
+ else this.dispose();
232
+ }
233
+ onKey(event) {
234
+ if (event.key !== "ContextMenu" && !(event.shiftKey && event.key === "F10")) return;
235
+ event.preventDefault();
236
+ this.lastPointerType = "";
237
+ this.cancelTouchPress();
238
+ this.clearTouchGuard();
239
+ const rect = this.elementRef.nativeElement.getBoundingClientRect();
240
+ this.openAt(rect.left + Math.min(24, rect.width / 2), rect.bottom);
241
+ this.items()[0]?.focus();
242
+ }
243
+ onDocumentClick(event) {
244
+ const target = event.target;
245
+ if (target && this.overlayRef?.overlayElement.contains(target) && target.closest("button, a, [role=\"menuitem\"]")) this.close();
246
+ }
247
+ hasNativeTouchAction(event) {
248
+ const source = this.elementRef.nativeElement;
249
+ for (const node of event.composedPath()) if (node instanceof HTMLElement) {
250
+ if (node.isContentEditable || node.matches("input, textarea, select, :disabled, [aria-disabled=\"true\"], [inert]")) return true;
251
+ if (node === source) break;
252
+ }
253
+ return !!source.closest(":disabled, [aria-disabled=\"true\"], [inert]");
254
+ }
255
+ hasTextSelection() {
256
+ const source = this.elementRef.nativeElement;
257
+ const selection = source.ownerDocument.getSelection();
258
+ return !!selection && !selection.isCollapsed && (source.contains(selection.anchorNode) || source.contains(selection.focusNode));
259
+ }
260
+ openTouchMenu(press) {
261
+ if (this.touchPress !== press || press.opened) return;
262
+ const source = this.elementRef.nativeElement;
263
+ if (!this.bxContextMenuLongPress() || !source.isConnected || source.isContentEditable || source.closest(":disabled, [aria-disabled=\"true\"], [inert]") || this.hasTextSelection()) {
264
+ this.cancelTouchPress();
265
+ return;
266
+ }
267
+ press.opened = true;
268
+ this.elementRef.nativeElement.ownerDocument.defaultView?.clearTimeout(press.timer);
269
+ this.guardTouchRelease();
270
+ this.openAt(press.x, press.y + 12);
271
+ }
272
+ cancelTouchPress() {
273
+ const press = this.touchPress;
274
+ if (!press) return;
275
+ this.touchPress = void 0;
276
+ const win = this.elementRef.nativeElement.ownerDocument.defaultView;
277
+ win?.clearTimeout(press.timer);
278
+ press.events.abort();
279
+ if (press.opened && win) this.touchGuardTimer = win.setTimeout(() => this.clearTouchGuard(), 800);
280
+ }
281
+ guardTouchRelease() {
282
+ this.clearTouchGuard();
283
+ const doc = this.elementRef.nativeElement.ownerDocument;
284
+ const guard = new AbortController();
285
+ this.touchGuard = guard;
286
+ const options = {
287
+ capture: true,
288
+ signal: guard.signal
289
+ };
290
+ doc.addEventListener("click", (event) => {
291
+ if (event.detail === 0) return;
292
+ event.preventDefault();
293
+ event.stopImmediatePropagation();
294
+ this.clearTouchGuard();
295
+ }, options);
296
+ doc.addEventListener("contextmenu", (event) => {
297
+ event.preventDefault();
298
+ event.stopImmediatePropagation();
299
+ }, options);
300
+ doc.addEventListener("pointerdown", (event) => {
301
+ if (event.isPrimary) this.clearTouchGuard();
302
+ }, {
303
+ ...options,
304
+ passive: true
305
+ });
306
+ doc.addEventListener("keydown", () => this.clearTouchGuard(), options);
307
+ }
308
+ clearTouchGuard() {
309
+ this.touchGuard?.abort();
310
+ this.touchGuard = void 0;
311
+ this.elementRef.nativeElement.ownerDocument.defaultView?.clearTimeout(this.touchGuardTimer);
312
+ this.touchGuardTimer = void 0;
313
+ }
314
+ openAt(x, y) {
315
+ this.dispose();
316
+ ++this.revision;
317
+ const source = this.elementRef.nativeElement;
318
+ this.overlayRef = this.overlay.create({
319
+ positionStrategy: this.positionBuilder.getCoordinateStrategy(x, y),
320
+ scrollStrategy: this.overlay.scrollStrategies.noop(),
321
+ usePopover: !!this.overlayContext?.useTopLayer || !!source.closest("dialog, [role=\"dialog\"], [role=\"alertdialog\"], bx-modal, bx-modal-core, [popover]"),
322
+ hasBackdrop: true,
323
+ backdropClass: "cdk-overlay-transparent-backdrop"
324
+ });
325
+ this.subscriptions = new Subscription();
326
+ const win = source.ownerDocument.defaultView;
327
+ if (win) this.zone.runOutsideAngular(() => {
328
+ const closeOnScroll = (event) => {
329
+ const target = event.target;
330
+ if (this.overlayRef?.overlayElement.inert) return;
331
+ if (target === win || target instanceof Node && target.contains(source)) this.zone.run(() => this.close());
332
+ };
333
+ win.addEventListener("scroll", closeOnScroll, {
334
+ capture: true,
335
+ passive: true
336
+ });
337
+ this.subscriptions.add(() => win.removeEventListener("scroll", closeOnScroll, true));
338
+ });
339
+ this.subscriptions.add(this.overlayRef.backdropClick().subscribe(() => this.close()));
340
+ this.subscriptions.add(this.overlayRef.detachments().subscribe(() => this.dispose()));
341
+ this.subscriptions.add(this.overlayRef.keydownEvents().subscribe((event) => this.onMenuKey(event)));
342
+ const pane = this.overlayRef.overlayElement;
343
+ this.disconnectTheme = this.zone.runOutsideAngular(() => inheritOverlayTheme(source, pane));
344
+ this.disconnectLighting = inheritGlassLighting(pane, source);
345
+ this.overlayRef.attach(new TemplatePortal(this.bxContextMenu(), this.vcr)).detectChanges();
346
+ this.overlayRef.updatePosition();
347
+ if (!this.a11y.isReducedMotion()) {
348
+ const point = source.ownerDocument.createElement("span");
349
+ point.setAttribute("aria-hidden", "true");
350
+ Object.assign(point.style, {
351
+ position: "fixed",
352
+ left: `${x}px`,
353
+ top: `${y}px`,
354
+ width: "1px",
355
+ height: "1px",
356
+ pointerEvents: "none"
357
+ });
358
+ source.ownerDocument.body.append(point);
359
+ this.point = point;
360
+ const transition = this.zone.runOutsideAngular(() => createGlassTransition(point, pane));
361
+ this.transition = transition;
362
+ this.zone.runOutsideAngular(() => transition.enter()).catch(() => {
363
+ this.transition?.destroy();
364
+ this.transition = void 0;
365
+ });
366
+ }
367
+ }
368
+ items() {
369
+ return Array.from(this.overlayRef?.overlayElement.querySelectorAll("button:not(:disabled), a[href], [role=\"menuitem\"]") ?? []).filter((item) => !item.matches("[disabled], [aria-disabled=\"true\"]") && !item.closest("[hidden], [inert]"));
370
+ }
371
+ onMenuKey(event) {
372
+ if (event.key === "Escape") {
373
+ event.preventDefault();
374
+ event.stopPropagation();
375
+ this.close(true);
376
+ return;
377
+ }
378
+ if (event.target?.closest("input,textarea,[contenteditable=\"true\"]")) return;
379
+ if (![
380
+ "ArrowDown",
381
+ "ArrowUp",
382
+ "Home",
383
+ "End"
384
+ ].includes(event.key)) return;
385
+ const items = this.items();
386
+ if (!items.length) return;
387
+ event.preventDefault();
388
+ const current = items.indexOf(this.elementRef.nativeElement.ownerDocument.activeElement);
389
+ items[event.key === "Home" ? 0 : event.key === "End" ? items.length - 1 : event.key === "ArrowDown" ? (current + 1) % items.length : current < 0 ? items.length - 1 : (current - 1 + items.length) % items.length].focus();
390
+ }
391
+ dispose() {
392
+ this.subscriptions.unsubscribe();
393
+ this.disconnectTheme?.();
394
+ this.disconnectTheme = void 0;
395
+ this.transition?.destroy();
396
+ this.transition = void 0;
397
+ this.point?.remove();
398
+ this.point = void 0;
399
+ const overlay = this.overlayRef;
400
+ this.overlayRef = null;
401
+ overlay?.dispose();
402
+ this.disconnectLighting?.();
403
+ this.disconnectLighting = void 0;
404
+ }
405
+ static ɵfac = i0.ɵɵngDeclareFactory({
406
+ minVersion: "12.0.0",
407
+ version: "22.2.3",
408
+ ngImport: i0,
409
+ type: ContextMenuDirective,
410
+ deps: [],
411
+ target: i0.ɵɵFactoryTarget.Directive
412
+ });
413
+ static ɵdir = i0.ɵɵngDeclareDirective({
414
+ minVersion: "17.1.0",
415
+ version: "22.2.3",
416
+ type: ContextMenuDirective,
417
+ isStandalone: true,
418
+ selector: "[bxContextMenu]",
419
+ inputs: {
420
+ bxContextMenu: {
421
+ classPropertyName: "bxContextMenu",
422
+ publicName: "bxContextMenu",
423
+ isSignal: true,
424
+ isRequired: true,
425
+ transformFunction: null
426
+ },
427
+ bxContextMenuLongPress: {
428
+ classPropertyName: "bxContextMenuLongPress",
429
+ publicName: "bxContextMenuLongPress",
430
+ isSignal: true,
431
+ isRequired: false,
432
+ transformFunction: null
433
+ }
434
+ },
435
+ host: { listeners: {
436
+ "contextmenu": "open($event)",
437
+ "keydown": "onKey($event)",
438
+ "document:click": "onDocumentClick($event)"
439
+ } },
440
+ ngImport: i0
441
+ });
442
+ };
443
+ i0.ɵɵngDeclareClassMetadata({
444
+ minVersion: "12.0.0",
445
+ version: "22.2.3",
446
+ ngImport: i0,
447
+ type: ContextMenuDirective,
448
+ decorators: [{
449
+ type: Directive,
450
+ args: [{ selector: "[bxContextMenu]" }]
451
+ }],
452
+ ctorParameters: () => [],
453
+ propDecorators: {
454
+ bxContextMenu: [{
455
+ type: i0.Input,
456
+ args: [{
457
+ isSignal: true,
458
+ alias: "bxContextMenu",
459
+ required: true
460
+ }]
461
+ }],
462
+ bxContextMenuLongPress: [{
463
+ type: i0.Input,
464
+ args: [{
465
+ isSignal: true,
466
+ alias: "bxContextMenuLongPress",
467
+ required: false
468
+ }]
469
+ }],
470
+ open: [{
471
+ type: HostListener,
472
+ args: ["contextmenu", ["$event"]]
473
+ }],
474
+ onKey: [{
475
+ type: HostListener,
476
+ args: ["keydown", ["$event"]]
477
+ }],
478
+ onDocumentClick: [{
479
+ type: HostListener,
480
+ args: ["document:click", ["$event"]]
481
+ }]
482
+ }
483
+ });
484
+ var TooltipDirective = class TooltipDirective {
485
+ elementRef = inject(ElementRef);
486
+ overlay = inject(Overlay);
487
+ positionBuilder = inject(BxOverlayPositionService);
488
+ a11y = inject(BxA11yService);
489
+ zone = inject(NgZone);
490
+ focusMonitor = inject(FocusMonitor);
491
+ describer = inject(AriaDescriber);
492
+ i18n = inject(BX_I18N, { optional: true });
493
+ contextMenu = inject(ContextMenuDirective, { optional: true });
494
+ id = `bx-tooltip-${uuidv4()}`;
495
+ bxTooltip = input.required(...ngDevMode ? [{ debugName: "bxTooltip" }] : /* istanbul ignore next */ []);
496
+ placement = input("bottom", ...ngDevMode ? [{ debugName: "placement" }] : /* istanbul ignore next */ []);
497
+ bxTooltipTouch = input("none", ...ngDevMode ? [{ debugName: "bxTooltipTouch" }] : /* istanbul ignore next */ []);
498
+ bxTooltipHover = input(true, ...ngDevMode ? [{ debugName: "bxTooltipHover" }] : /* istanbul ignore next */ []);
499
+ overlayRef = null;
500
+ tooltipComponent;
501
+ transition;
502
+ disconnectTheme;
503
+ disconnectLighting;
504
+ positionSubscription;
505
+ keyboardSubscription;
506
+ revision = 0;
507
+ hovered = false;
508
+ focused = false;
509
+ lastPointerType = "";
510
+ touchEvents;
511
+ holdTimer;
512
+ touchHideTimer;
513
+ touchVisible = false;
514
+ closeTouchTap = false;
515
+ constructor() {
516
+ const source = this.elementRef.nativeElement;
517
+ const focus = source.ownerDocument.defaultView ? this.focusMonitor.monitor(source, true).subscribe((origin) => this.zone.run(() => {
518
+ this.focused = origin === "keyboard";
519
+ if (this.focused) {
520
+ this.clearTouchInteraction();
521
+ this.show();
522
+ } else if (!this.hovered && !this.touchEvents) this.hide();
523
+ })) : void 0;
524
+ effect((onCleanup) => {
525
+ this.i18n?.version?.();
526
+ const text = this.bxTooltip();
527
+ const description = isTextWithKey(text) ? this.i18n?.translate(text.key) ?? text.key : text;
528
+ if (!description) {
529
+ if (this.overlayRef) this.hide();
530
+ return;
531
+ }
532
+ this.tooltipComponent?.setInput("text", text);
533
+ if (this.hovered || this.focused) this.show();
534
+ this.describer.describe(source, description, "tooltip");
535
+ onCleanup(() => this.describer.removeDescription(source, description, "tooltip"));
536
+ });
537
+ inject(DestroyRef).onDestroy(() => {
538
+ ++this.revision;
539
+ focus?.unsubscribe();
540
+ if (focus) this.focusMonitor.stopMonitoring(source);
541
+ this.clearTouchInteraction();
542
+ this.dispose();
543
+ });
544
+ }
545
+ show() {
546
+ if (!this.bxTooltip()) return;
547
+ const revision = ++this.revision;
548
+ if (!this.overlayRef) {
549
+ const strategy = this.positionBuilder.getElementStrategy(this.elementRef.nativeElement, this.placement()).withFlexibleDimensions(false);
550
+ this.overlayRef = this.overlay.create({
551
+ positionStrategy: strategy,
552
+ scrollStrategy: this.overlay.scrollStrategies.reposition(),
553
+ hasBackdrop: false,
554
+ panelClass: "bx-tooltip-pane"
555
+ });
556
+ const pane = this.overlayRef.overlayElement;
557
+ pane.id = this.id;
558
+ pane.setAttribute("role", "tooltip");
559
+ pane.setAttribute("aria-hidden", "true");
560
+ this.disconnectTheme = this.zone.runOutsideAngular(() => inheritOverlayTheme(this.elementRef.nativeElement, pane));
561
+ this.disconnectLighting = inheritGlassLighting(pane, this.elementRef.nativeElement);
562
+ const component = this.overlayRef.attach(new ComponentPortal(Tooltip));
563
+ this.tooltipComponent = component;
564
+ pane.style.pointerEvents = "none";
565
+ this.keyboardSubscription = this.overlayRef.keydownEvents().subscribe((event) => this.onEscape(event));
566
+ component.setInput("text", this.bxTooltip());
567
+ component.changeDetectorRef.detectChanges();
568
+ const positionArrow = () => {
569
+ const trigger = this.elementRef.nativeElement.getBoundingClientRect();
570
+ const bounds = pane.getBoundingClientRect();
571
+ pane.style.setProperty("--bx-tooltip-arrow-x", `${trigger.left + trigger.width / 2 - bounds.left}px`);
572
+ pane.style.setProperty("--bx-tooltip-arrow-y", `${trigger.top + trigger.height / 2 - bounds.top}px`);
573
+ this.transition?.refresh();
574
+ };
575
+ this.positionSubscription = strategy.positionChanges.subscribe(positionArrow);
576
+ this.overlayRef.updatePosition();
577
+ positionArrow();
578
+ if (!this.a11y.isReducedMotion()) this.transition = this.zone.runOutsideAngular(() => createGlassTransition(this.elementRef.nativeElement, pane));
579
+ }
580
+ Promise.resolve(this.zone.runOutsideAngular(() => this.transition?.enter())).catch(() => {
581
+ if (revision === this.revision) {
582
+ this.transition?.destroy();
583
+ this.transition = void 0;
584
+ }
585
+ });
586
+ }
587
+ hide() {
588
+ this.clearTouchInteraction();
589
+ const revision = ++this.revision;
590
+ if (!this.overlayRef) return;
591
+ const transition = this.transition;
592
+ if (transition && !this.a11y.isReducedMotion()) this.zone.runOutsideAngular(() => transition.exit()).then(() => {
593
+ if (revision === this.revision) this.dispose();
594
+ }).catch(() => {
595
+ if (revision === this.revision) this.dispose();
596
+ });
597
+ else this.dispose();
598
+ }
599
+ onEnter(event) {
600
+ if (event.pointerType !== "mouse" || !this.bxTooltipHover()) return;
601
+ this.clearTouchInteraction();
602
+ this.hovered = true;
603
+ this.show();
604
+ }
605
+ onLeave(event) {
606
+ if (event.pointerType !== "mouse") return;
607
+ this.hovered = false;
608
+ if (!this.focused) this.hide();
609
+ }
610
+ onPointerDown(event) {
611
+ this.lastPointerType = event.pointerType;
612
+ if (event.pointerType !== "touch") return;
613
+ this.closeTouchTap = this.touchVisible && this.bxTooltipTouch() === "tap";
614
+ this.hovered = false;
615
+ this.focused = false;
616
+ this.hide();
617
+ if (this.bxTooltipTouch() !== "longpress" || !event.isPrimary || event.button !== 0 || !this.canUseTouch(event)) return;
618
+ this.zone.runOutsideAngular(() => this.startTouchInteraction(event));
619
+ }
620
+ onClick(event) {
621
+ if (event.detail === 0 || this.lastPointerType !== "touch" || this.bxTooltipTouch() !== "tap" || !this.canUseTouch(event)) return;
622
+ if (this.closeTouchTap) {
623
+ this.closeTouchTap = false;
624
+ return;
625
+ }
626
+ this.zone.runOutsideAngular(() => this.startTouchInteraction());
627
+ }
628
+ onEscape(event) {
629
+ if (event.key === "Escape" && this.overlayRef) {
630
+ event.stopPropagation();
631
+ this.hovered = false;
632
+ this.focused = false;
633
+ this.hide();
634
+ }
635
+ }
636
+ canUseTouch(event) {
637
+ if (this.contextMenu && this.bxTooltipTouch() === "longpress") return false;
638
+ if (this.elementRef.nativeElement.closest(":disabled, [aria-disabled=\"true\"], [inert]")) return false;
639
+ return !event.composedPath().some((node) => node instanceof HTMLElement && (node.isContentEditable || node.matches("input, textarea, select")));
640
+ }
641
+ hasTextSelection() {
642
+ const source = this.elementRef.nativeElement;
643
+ const selection = source.ownerDocument.getSelection();
644
+ return !!selection && !selection.isCollapsed && (source.contains(selection.anchorNode) || source.contains(selection.focusNode));
645
+ }
646
+ startTouchInteraction(press) {
647
+ const source = this.elementRef.nativeElement;
648
+ const doc = source.ownerDocument;
649
+ const win = doc.defaultView;
650
+ if (!win || this.hasTextSelection()) return;
651
+ this.clearTouchInteraction();
652
+ const events = new AbortController();
653
+ this.touchEvents = events;
654
+ const options = {
655
+ capture: true,
656
+ passive: true,
657
+ signal: events.signal
658
+ };
659
+ const dismiss = () => this.zone.run(() => this.hide());
660
+ let suppressReleaseClick = false;
661
+ doc.addEventListener("pointerdown", (event) => {
662
+ if (!press && event.target instanceof Node && source.contains(event.target)) return;
663
+ dismiss();
664
+ }, options);
665
+ doc.addEventListener("scroll", dismiss, options);
666
+ doc.addEventListener("visibilitychange", () => {
667
+ if (doc.hidden) dismiss();
668
+ }, options);
669
+ win.addEventListener("blur", dismiss, { signal: events.signal });
670
+ if (!press) {
671
+ this.touchVisible = true;
672
+ this.zone.run(() => this.show());
673
+ return;
674
+ }
675
+ doc.addEventListener("pointermove", (event) => {
676
+ if (event.pointerId === press.pointerId && !this.touchVisible && Math.hypot(event.clientX - press.clientX, event.clientY - press.clientY) > 10) dismiss();
677
+ }, options);
678
+ doc.addEventListener("pointerup", (event) => {
679
+ if (event.pointerId !== press.pointerId) return;
680
+ if (!this.touchVisible) dismiss();
681
+ else this.touchHideTimer = win.setTimeout(dismiss, 1500);
682
+ }, options);
683
+ doc.addEventListener("pointercancel", (event) => {
684
+ if (event.pointerId === press.pointerId) dismiss();
685
+ }, options);
686
+ doc.addEventListener("click", (event) => {
687
+ if (!suppressReleaseClick || event.detail === 0) return;
688
+ event.preventDefault();
689
+ event.stopImmediatePropagation();
690
+ suppressReleaseClick = false;
691
+ }, {
692
+ ...options,
693
+ passive: false
694
+ });
695
+ doc.addEventListener("contextmenu", (event) => {
696
+ if (event.target instanceof Node && source.contains(event.target) && !this.hasTextSelection()) event.preventDefault();
697
+ }, {
698
+ ...options,
699
+ passive: false
700
+ });
701
+ this.holdTimer = win.setTimeout(() => {
702
+ if (this.bxTooltipTouch() !== "longpress" || !source.isConnected || source.closest(":disabled, [aria-disabled=\"true\"], [inert]") || this.hasTextSelection()) {
703
+ dismiss();
704
+ return;
705
+ }
706
+ this.touchVisible = true;
707
+ suppressReleaseClick = true;
708
+ this.zone.run(() => this.show());
709
+ }, 500);
710
+ }
711
+ clearTouchInteraction() {
712
+ this.touchEvents?.abort();
713
+ this.touchEvents = void 0;
714
+ const win = this.elementRef.nativeElement.ownerDocument.defaultView;
715
+ win?.clearTimeout(this.holdTimer);
716
+ win?.clearTimeout(this.touchHideTimer);
717
+ this.holdTimer = void 0;
718
+ this.touchHideTimer = void 0;
719
+ this.touchVisible = false;
720
+ }
721
+ dispose() {
722
+ this.keyboardSubscription?.unsubscribe();
723
+ this.keyboardSubscription = void 0;
724
+ this.positionSubscription?.unsubscribe();
725
+ this.positionSubscription = void 0;
726
+ this.disconnectTheme?.();
727
+ this.disconnectTheme = void 0;
728
+ this.transition?.destroy();
729
+ this.transition = void 0;
730
+ this.overlayRef?.dispose();
731
+ this.overlayRef = null;
732
+ this.tooltipComponent = void 0;
733
+ this.disconnectLighting?.();
734
+ this.disconnectLighting = void 0;
735
+ }
736
+ static ɵfac = i0.ɵɵngDeclareFactory({
737
+ minVersion: "12.0.0",
738
+ version: "22.2.3",
739
+ ngImport: i0,
740
+ type: TooltipDirective,
741
+ deps: [],
742
+ target: i0.ɵɵFactoryTarget.Directive
743
+ });
744
+ static ɵdir = i0.ɵɵngDeclareDirective({
745
+ minVersion: "17.1.0",
746
+ version: "22.2.3",
747
+ type: TooltipDirective,
748
+ isStandalone: true,
749
+ selector: "[bxTooltip]",
750
+ inputs: {
751
+ bxTooltip: {
752
+ classPropertyName: "bxTooltip",
753
+ publicName: "bxTooltip",
754
+ isSignal: true,
755
+ isRequired: true,
756
+ transformFunction: null
757
+ },
758
+ placement: {
759
+ classPropertyName: "placement",
760
+ publicName: "placement",
761
+ isSignal: true,
762
+ isRequired: false,
763
+ transformFunction: null
764
+ },
765
+ bxTooltipTouch: {
766
+ classPropertyName: "bxTooltipTouch",
767
+ publicName: "bxTooltipTouch",
768
+ isSignal: true,
769
+ isRequired: false,
770
+ transformFunction: null
771
+ },
772
+ bxTooltipHover: {
773
+ classPropertyName: "bxTooltipHover",
774
+ publicName: "bxTooltipHover",
775
+ isSignal: true,
776
+ isRequired: false,
777
+ transformFunction: null
778
+ }
779
+ },
780
+ host: { listeners: {
781
+ "pointerenter": "onEnter($event)",
782
+ "pointerleave": "onLeave($event)",
783
+ "pointerdown": "onPointerDown($event)",
784
+ "click": "onClick($event)",
785
+ "document:keydown": "onEscape($event)"
786
+ } },
787
+ ngImport: i0
788
+ });
789
+ };
790
+ i0.ɵɵngDeclareClassMetadata({
791
+ minVersion: "12.0.0",
792
+ version: "22.2.3",
793
+ ngImport: i0,
794
+ type: TooltipDirective,
795
+ decorators: [{
796
+ type: Directive,
797
+ args: [{ selector: "[bxTooltip]" }]
798
+ }],
799
+ ctorParameters: () => [],
800
+ propDecorators: {
801
+ bxTooltip: [{
802
+ type: i0.Input,
803
+ args: [{
804
+ isSignal: true,
805
+ alias: "bxTooltip",
806
+ required: true
807
+ }]
808
+ }],
809
+ placement: [{
810
+ type: i0.Input,
811
+ args: [{
812
+ isSignal: true,
813
+ alias: "placement",
814
+ required: false
815
+ }]
816
+ }],
817
+ bxTooltipTouch: [{
818
+ type: i0.Input,
819
+ args: [{
820
+ isSignal: true,
821
+ alias: "bxTooltipTouch",
822
+ required: false
823
+ }]
824
+ }],
825
+ bxTooltipHover: [{
826
+ type: i0.Input,
827
+ args: [{
828
+ isSignal: true,
829
+ alias: "bxTooltipHover",
830
+ required: false
831
+ }]
832
+ }],
833
+ onEnter: [{
834
+ type: HostListener,
835
+ args: ["pointerenter", ["$event"]]
836
+ }],
837
+ onLeave: [{
838
+ type: HostListener,
839
+ args: ["pointerleave", ["$event"]]
840
+ }],
841
+ onPointerDown: [{
842
+ type: HostListener,
843
+ args: ["pointerdown", ["$event"]]
844
+ }],
845
+ onClick: [{
846
+ type: HostListener,
847
+ args: ["click", ["$event"]]
848
+ }],
849
+ onEscape: [{
850
+ type: HostListener,
851
+ args: ["document:keydown", ["$event"]]
852
+ }]
853
+ }
854
+ });
855
+ var TruncateDirective = class TruncateDirective {
856
+ element = inject(ElementRef).nativeElement;
857
+ destroyRef = inject(DestroyRef);
858
+ zone = inject(NgZone);
859
+ clipped = signal(false, ...ngDevMode ? [{ debugName: "clipped" }] : /* istanbul ignore next */ []);
860
+ content = signal("", ...ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []);
861
+ enabled = input(true, {
862
+ ...ngDevMode ? { debugName: "enabled" } : /* istanbul ignore next */ {},
863
+ alias: "bxTruncate",
864
+ transform: booleanAttribute
865
+ });
866
+ truncated = this.clipped.asReadonly();
867
+ text = this.content.asReadonly();
868
+ truncatedChange = output();
869
+ rendered = false;
870
+ frame;
871
+ resize;
872
+ mutations;
873
+ listeners;
874
+ textContext;
875
+ constructor() {
876
+ afterNextRender(() => this.observeLayout());
877
+ afterEveryRender(() => this.scheduleMeasure());
878
+ this.destroyRef.onDestroy(() => {
879
+ if (this.frame !== void 0) this.element.ownerDocument.defaultView?.cancelAnimationFrame(this.frame);
880
+ this.resize?.disconnect();
881
+ this.mutations?.disconnect();
882
+ this.listeners?.abort();
883
+ });
884
+ }
885
+ refresh() {
886
+ if (!this.rendered || this.destroyRef.destroyed) return;
887
+ const text = this.element.tagName === "INPUT" ? this.element.value || this.element.placeholder : this.element.textContent ?? "";
888
+ const clipped = this.enabled() && this.element.getClientRects().length > 0 && this.measureOverflow(text);
889
+ if (clipped === this.clipped() && text === this.content()) return;
890
+ this.zone.run(() => {
891
+ this.content.set(text);
892
+ if (clipped !== this.clipped()) {
893
+ this.clipped.set(clipped);
894
+ this.truncatedChange.emit(clipped);
895
+ }
896
+ });
897
+ }
898
+ measureOverflow(text) {
899
+ if (this.element.tagName !== "INPUT") return this.element.scrollWidth > this.element.clientWidth || this.element.scrollHeight > this.element.clientHeight;
900
+ if (!text) return false;
901
+ const style = this.element.ownerDocument.defaultView?.getComputedStyle(this.element);
902
+ this.textContext ??= this.element.ownerDocument.createElement("canvas").getContext("2d");
903
+ if (!style || !this.textContext) return this.element.scrollWidth > this.element.clientWidth;
904
+ this.textContext.font = style.font || `${style.fontWeight} ${style.fontSize} ${style.fontFamily}`;
905
+ const letterSpacing = parseFloat(style.letterSpacing) || 0;
906
+ const wordSpacing = parseFloat(style.wordSpacing) || 0;
907
+ return this.textContext.measureText(text).width + letterSpacing * Math.max(0, [...text].length - 1) + wordSpacing * (text.match(/\s/g)?.length ?? 0) > this.element.clientWidth - (parseFloat(style.paddingInlineStart) || 0) - (parseFloat(style.paddingInlineEnd) || 0) + .5;
908
+ }
909
+ observeLayout() {
910
+ const view = this.element.ownerDocument.defaultView;
911
+ if (!view) return;
912
+ this.rendered = true;
913
+ this.zone.runOutsideAngular(() => {
914
+ if (typeof ResizeObserver !== "undefined") {
915
+ this.resize = new ResizeObserver(() => this.scheduleMeasure());
916
+ this.resize.observe(this.element);
917
+ }
918
+ if (typeof MutationObserver !== "undefined") {
919
+ this.mutations = new MutationObserver(() => this.scheduleMeasure());
920
+ this.mutations.observe(this.element, {
921
+ childList: true,
922
+ characterData: true,
923
+ subtree: true
924
+ });
925
+ }
926
+ const listeners = new AbortController();
927
+ this.listeners = listeners;
928
+ const options = {
929
+ passive: true,
930
+ signal: listeners.signal
931
+ };
932
+ view.addEventListener("resize", () => this.scheduleMeasure(), options);
933
+ view.visualViewport?.addEventListener("resize", () => this.scheduleMeasure(), options);
934
+ const fonts = this.element.ownerDocument.fonts;
935
+ fonts?.addEventListener("loadingdone", () => this.scheduleMeasure(), options);
936
+ fonts?.ready.then(() => this.scheduleMeasure());
937
+ this.scheduleMeasure();
938
+ });
939
+ }
940
+ scheduleMeasure() {
941
+ const view = this.element.ownerDocument.defaultView;
942
+ if (!this.rendered || this.destroyRef.destroyed || !view || this.frame !== void 0) return;
943
+ this.zone.runOutsideAngular(() => {
944
+ this.frame = view.requestAnimationFrame(() => {
945
+ this.frame = void 0;
946
+ this.refresh();
947
+ });
948
+ });
949
+ }
950
+ static ɵfac = i0.ɵɵngDeclareFactory({
951
+ minVersion: "12.0.0",
952
+ version: "22.2.3",
953
+ ngImport: i0,
954
+ type: TruncateDirective,
955
+ deps: [],
956
+ target: i0.ɵɵFactoryTarget.Directive
957
+ });
958
+ static ɵdir = i0.ɵɵngDeclareDirective({
959
+ minVersion: "17.1.0",
960
+ version: "22.2.3",
961
+ type: TruncateDirective,
962
+ isStandalone: true,
963
+ selector: "[bxTruncate]",
964
+ inputs: { enabled: {
965
+ classPropertyName: "enabled",
966
+ publicName: "bxTruncate",
967
+ isSignal: true,
968
+ isRequired: false,
969
+ transformFunction: null
970
+ } },
971
+ outputs: { truncatedChange: "truncatedChange" },
972
+ host: { properties: {
973
+ "style.display": "enabled() ? \"block\" : null",
974
+ "class.bx-truncate": "enabled()"
975
+ } },
976
+ exportAs: ["bxTruncate"],
977
+ ngImport: i0
978
+ });
979
+ };
980
+ i0.ɵɵngDeclareClassMetadata({
981
+ minVersion: "12.0.0",
982
+ version: "22.2.3",
983
+ ngImport: i0,
984
+ type: TruncateDirective,
985
+ decorators: [{
986
+ type: Directive,
987
+ args: [{
988
+ selector: "[bxTruncate]",
989
+ exportAs: "bxTruncate",
990
+ host: {
991
+ "[style.display]": "enabled() ? \"block\" : null",
992
+ "[class.bx-truncate]": "enabled()"
993
+ }
994
+ }]
995
+ }],
996
+ ctorParameters: () => [],
997
+ propDecorators: {
998
+ enabled: [{
999
+ type: i0.Input,
1000
+ args: [{
1001
+ isSignal: true,
1002
+ alias: "bxTruncate",
1003
+ required: false
1004
+ }]
1005
+ }],
1006
+ truncatedChange: [{
1007
+ type: i0.Output,
1008
+ args: ["truncatedChange"]
1009
+ }]
1010
+ }
1011
+ });
1012
+ function truncatedText(text, truncated, enabled = true) {
1013
+ return enabled && truncated ? text ?? "" : "";
1014
+ }
1015
+ var TruncatedTextPipe = class TruncatedTextPipe {
1016
+ transform(text, truncated, enabled = true) {
1017
+ return truncatedText(text, truncated, enabled);
1018
+ }
1019
+ static ɵfac = i0.ɵɵngDeclareFactory({
1020
+ minVersion: "12.0.0",
1021
+ version: "22.2.3",
1022
+ ngImport: i0,
1023
+ type: TruncatedTextPipe,
1024
+ deps: [],
1025
+ target: i0.ɵɵFactoryTarget.Pipe
1026
+ });
1027
+ static ɵpipe = i0.ɵɵngDeclarePipe({
1028
+ minVersion: "14.0.0",
1029
+ version: "22.2.3",
1030
+ ngImport: i0,
1031
+ type: TruncatedTextPipe,
1032
+ isStandalone: true,
1033
+ name: "bxTruncatedText"
1034
+ });
1035
+ };
1036
+ i0.ɵɵngDeclareClassMetadata({
1037
+ minVersion: "12.0.0",
1038
+ version: "22.2.3",
1039
+ ngImport: i0,
1040
+ type: TruncatedTextPipe,
1041
+ decorators: [{
1042
+ type: Pipe,
1043
+ args: [{ name: "bxTruncatedText" }]
1044
+ }]
1045
+ });
1046
+ var MenuItem = class MenuItem {
1047
+ i18n = inject(BX_I18N, { optional: true });
1048
+ a11y = inject(BxA11yService);
1049
+ bxShortcutService = inject(BxShortcutService);
1050
+ resolvedLabel = computed(() => {
1051
+ this.i18n?.version?.();
1052
+ const label = this.label();
1053
+ if (!label) return void 0;
1054
+ if (isTextWithKey(label)) return this.i18n?.translate(label.key) ?? label.key;
1055
+ return label;
1056
+ }, ...ngDevMode ? [{ debugName: "resolvedLabel" }] : /* istanbul ignore next */ []);
1057
+ resolvedShortcut = computed(() => {
1058
+ return this.bxShortcutService.resolve(this.shortcut());
1059
+ }, ...ngDevMode ? [{ debugName: "resolvedShortcut" }] : /* istanbul ignore next */ []);
1060
+ isAnimated = computed(() => !this.a11y.isReducedMotion(), ...ngDevMode ? [{ debugName: "isAnimated" }] : /* istanbul ignore next */ []);
1061
+ icon = input(void 0, ...ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []);
1062
+ endIcon = input(void 0, ...ngDevMode ? [{ debugName: "endIcon" }] : /* istanbul ignore next */ []);
1063
+ label = input(void 0, ...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
1064
+ wrapLabel = input(false, ...ngDevMode ? [{ debugName: "wrapLabel" }] : /* istanbul ignore next */ []);
1065
+ tooltipOnTruncate = input(true, {
1066
+ ...ngDevMode ? { debugName: "tooltipOnTruncate" } : /* istanbul ignore next */ {},
1067
+ transform: booleanAttribute
1068
+ });
1069
+ disabled = input(false, ...ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []);
1070
+ danger = input(false, ...ngDevMode ? [{ debugName: "danger" }] : /* istanbul ignore next */ []);
1071
+ shortcut = input(void 0, ...ngDevMode ? [{ debugName: "shortcut" }] : /* istanbul ignore next */ []);
1072
+ action = output();
1073
+ onClick(event) {
1074
+ if (this.disabled()) {
1075
+ event.preventDefault();
1076
+ event.stopPropagation();
1077
+ return;
1078
+ }
1079
+ this.action.emit(event);
1080
+ }
1081
+ static ɵfac = i0.ɵɵngDeclareFactory({
1082
+ minVersion: "12.0.0",
1083
+ version: "22.2.3",
1084
+ ngImport: i0,
1085
+ type: MenuItem,
1086
+ deps: [],
1087
+ target: i0.ɵɵFactoryTarget.Component
1088
+ });
1089
+ static ɵcmp = i0.ɵɵngDeclareComponent({
1090
+ minVersion: "17.0.0",
1091
+ version: "22.2.3",
1092
+ type: MenuItem,
1093
+ isStandalone: true,
1094
+ selector: "bx-menu-item",
1095
+ inputs: {
1096
+ icon: {
1097
+ classPropertyName: "icon",
1098
+ publicName: "icon",
1099
+ isSignal: true,
1100
+ isRequired: false,
1101
+ transformFunction: null
1102
+ },
1103
+ endIcon: {
1104
+ classPropertyName: "endIcon",
1105
+ publicName: "endIcon",
1106
+ isSignal: true,
1107
+ isRequired: false,
1108
+ transformFunction: null
1109
+ },
1110
+ label: {
1111
+ classPropertyName: "label",
1112
+ publicName: "label",
1113
+ isSignal: true,
1114
+ isRequired: false,
1115
+ transformFunction: null
1116
+ },
1117
+ wrapLabel: {
1118
+ classPropertyName: "wrapLabel",
1119
+ publicName: "wrapLabel",
1120
+ isSignal: true,
1121
+ isRequired: false,
1122
+ transformFunction: null
1123
+ },
1124
+ tooltipOnTruncate: {
1125
+ classPropertyName: "tooltipOnTruncate",
1126
+ publicName: "tooltipOnTruncate",
1127
+ isSignal: true,
1128
+ isRequired: false,
1129
+ transformFunction: null
1130
+ },
1131
+ disabled: {
1132
+ classPropertyName: "disabled",
1133
+ publicName: "disabled",
1134
+ isSignal: true,
1135
+ isRequired: false,
1136
+ transformFunction: null
1137
+ },
1138
+ danger: {
1139
+ classPropertyName: "danger",
1140
+ publicName: "danger",
1141
+ isSignal: true,
1142
+ isRequired: false,
1143
+ transformFunction: null
1144
+ },
1145
+ shortcut: {
1146
+ classPropertyName: "shortcut",
1147
+ publicName: "shortcut",
1148
+ isSignal: true,
1149
+ isRequired: false,
1150
+ transformFunction: null
1151
+ }
1152
+ },
1153
+ outputs: { action: "action" },
1154
+ ngImport: i0,
1155
+ template: "<button bxSurface [bxSurfaceEmission]=\"danger() ? 'var(--bx-text-danger)' : 'var(--bx-primary)'\" type=\"button\" role=\"menuitem\" [disabled]=\"disabled()\" class=\"bx-menu-item-btn\" [class.is-disabled]=\"disabled()\" [class.is-danger]=\"danger()\"\n [class.bx-menu-item-animated]=\"isAnimated()\" (click)=\"onClick($event)\"\n [bxTooltip]=\"(resolvedLabel() ?? menuText.text().trim()) | bxTruncatedText: menuText.truncated(): tooltipOnTruncate()\" bxTooltipTouch=\"longpress\">\n\n @if (icon()) {\n <bx-icon class=\"bx-icon-pos-start\" [name]=\"icon()!\" size=\"20\" />\n }\n\n <span class=\"bx-menu-item-content\" [bxTruncate]=\"!wrapLabel()\" #menuText=\"bxTruncate\" [class.bx-menu-item-content-wrapped]=\"wrapLabel()\">\n @if (resolvedLabel()) {\n {{ resolvedLabel() }}\n } @else {\n <ng-content></ng-content>\n }\n </span>\n\n @if (resolvedShortcut()) {\n <span class=\"bx-menu-item-shortcut\">\n @for (key of resolvedShortcut(); track $index) {\n <kbd>{{ key }}</kbd>\n }\n </span>\n }\n\n @if (endIcon()) {\n <bx-icon class=\"bx-icon-pos-end\" [name]=\"endIcon()!\" size=\"20\" />\n }\n</button>\n",
1156
+ styles: [":host{display:block;width:100%}.bx-menu-item-btn{width:100%;display:flex;align-items:center;background:transparent!important;border:none;padding:.5rem .75rem;cursor:pointer;font-family:inherit;font-size:.875rem;text-align:left;border-radius:max(0px,var(--bx-glass-radius, var(--bx-rounded-lg, .75rem)) - .25rem);color:var(--bx-text-primary);--bx-glass-decoration-opacity: 0;--bx-glass-rim-visibility: 0;-webkit-backdrop-filter:none;backdrop-filter:none;box-shadow:none}.bx-menu-item-btn:focus-visible{outline:2px solid var(--bx-border-brand);outline-offset:-2px}.bx-menu-item-btn.bx-menu-item-animated{transition:background-color .1s ease-in-out,color .1s ease-in-out}.bx-menu-item-btn.bx-menu-item-animated .bx-menu-item-shortcut{transition:color .1s ease-in-out}.bx-menu-item-btn:hover:not(.is-disabled){background:var(--bx-bg-element-hover)!important}.bx-menu-item-btn:hover:not(.is-disabled) .bx-menu-item-shortcut{color:inherit;opacity:1}.bx-menu-item-btn:active:not(.is-disabled){background:var(--bx-bg-element-active)!important}.bx-menu-item-btn:active:not(.is-disabled) .bx-menu-item-shortcut{color:inherit;opacity:1}.bx-menu-item-btn.is-danger{color:var(--bx-text-danger)}.bx-menu-item-btn.is-danger .bx-menu-item-shortcut{color:var(--bx-text-danger);opacity:.7}.bx-menu-item-btn.is-danger:hover:not(.is-disabled){background:var(--bx-bg-danger-hover)!important}.bx-menu-item-btn.is-danger:active:not(.is-disabled){background:var(--bx-bg-danger-active)!important}.bx-menu-item-btn.is-disabled{opacity:.4;cursor:not-allowed;pointer-events:none}.bx-menu-item-content{flex:1 1 auto;min-width:0;line-height:1.4;text-align:left}.bx-menu-item-content-wrapped{white-space:normal;overflow-wrap:anywhere}.bx-menu-item-shortcut{display:flex;align-items:center;gap:.15rem;margin-left:1.5rem;color:var(--bx-text-secondary);font-size:.875rem}.bx-menu-item-shortcut kbd{font-family:inherit;background:transparent;border:none;box-shadow:none;padding:0;margin:0;color:inherit}\n"],
1157
+ dependencies: [
1158
+ {
1159
+ kind: "component",
1160
+ type: Icon,
1161
+ selector: "bx-icon",
1162
+ inputs: [
1163
+ "name",
1164
+ "size",
1165
+ "color",
1166
+ "bgColor",
1167
+ "strokeWidth",
1168
+ "decorative",
1169
+ "ariaLabel"
1170
+ ]
1171
+ },
1172
+ {
1173
+ kind: "directive",
1174
+ type: BxSurfaceDirective,
1175
+ selector: "[bxSurface]",
1176
+ inputs: [
1177
+ "bxSurfaceInteractive",
1178
+ "bxSurfaceGlassiness",
1179
+ "bxSurfaceEmission",
1180
+ "bxSurfaceFocusEmission",
1181
+ "bxReducedTransparency"
1182
+ ],
1183
+ exportAs: ["bxSurface"]
1184
+ },
1185
+ {
1186
+ kind: "directive",
1187
+ type: TooltipDirective,
1188
+ selector: "[bxTooltip]",
1189
+ inputs: [
1190
+ "bxTooltip",
1191
+ "placement",
1192
+ "bxTooltipTouch",
1193
+ "bxTooltipHover"
1194
+ ]
1195
+ },
1196
+ {
1197
+ kind: "directive",
1198
+ type: TruncateDirective,
1199
+ selector: "[bxTruncate]",
1200
+ inputs: ["bxTruncate"],
1201
+ outputs: ["truncatedChange"],
1202
+ exportAs: ["bxTruncate"]
1203
+ },
1204
+ {
1205
+ kind: "pipe",
1206
+ type: TruncatedTextPipe,
1207
+ name: "bxTruncatedText"
1208
+ }
1209
+ ],
1210
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
1211
+ });
1212
+ };
1213
+ i0.ɵɵngDeclareClassMetadata({
1214
+ minVersion: "12.0.0",
1215
+ version: "22.2.3",
1216
+ ngImport: i0,
1217
+ type: MenuItem,
1218
+ decorators: [{
1219
+ type: Component,
1220
+ args: [{
1221
+ selector: "bx-menu-item",
1222
+ imports: [
1223
+ Icon,
1224
+ BxSurfaceDirective,
1225
+ TooltipDirective,
1226
+ TruncateDirective,
1227
+ TruncatedTextPipe
1228
+ ],
1229
+ changeDetection: ChangeDetectionStrategy.OnPush,
1230
+ template: "<button bxSurface [bxSurfaceEmission]=\"danger() ? 'var(--bx-text-danger)' : 'var(--bx-primary)'\" type=\"button\" role=\"menuitem\" [disabled]=\"disabled()\" class=\"bx-menu-item-btn\" [class.is-disabled]=\"disabled()\" [class.is-danger]=\"danger()\"\n [class.bx-menu-item-animated]=\"isAnimated()\" (click)=\"onClick($event)\"\n [bxTooltip]=\"(resolvedLabel() ?? menuText.text().trim()) | bxTruncatedText: menuText.truncated(): tooltipOnTruncate()\" bxTooltipTouch=\"longpress\">\n\n @if (icon()) {\n <bx-icon class=\"bx-icon-pos-start\" [name]=\"icon()!\" size=\"20\" />\n }\n\n <span class=\"bx-menu-item-content\" [bxTruncate]=\"!wrapLabel()\" #menuText=\"bxTruncate\" [class.bx-menu-item-content-wrapped]=\"wrapLabel()\">\n @if (resolvedLabel()) {\n {{ resolvedLabel() }}\n } @else {\n <ng-content></ng-content>\n }\n </span>\n\n @if (resolvedShortcut()) {\n <span class=\"bx-menu-item-shortcut\">\n @for (key of resolvedShortcut(); track $index) {\n <kbd>{{ key }}</kbd>\n }\n </span>\n }\n\n @if (endIcon()) {\n <bx-icon class=\"bx-icon-pos-end\" [name]=\"endIcon()!\" size=\"20\" />\n }\n</button>\n",
1231
+ styles: [":host{display:block;width:100%}.bx-menu-item-btn{width:100%;display:flex;align-items:center;background:transparent!important;border:none;padding:.5rem .75rem;cursor:pointer;font-family:inherit;font-size:.875rem;text-align:left;border-radius:max(0px,var(--bx-glass-radius, var(--bx-rounded-lg, .75rem)) - .25rem);color:var(--bx-text-primary);--bx-glass-decoration-opacity: 0;--bx-glass-rim-visibility: 0;-webkit-backdrop-filter:none;backdrop-filter:none;box-shadow:none}.bx-menu-item-btn:focus-visible{outline:2px solid var(--bx-border-brand);outline-offset:-2px}.bx-menu-item-btn.bx-menu-item-animated{transition:background-color .1s ease-in-out,color .1s ease-in-out}.bx-menu-item-btn.bx-menu-item-animated .bx-menu-item-shortcut{transition:color .1s ease-in-out}.bx-menu-item-btn:hover:not(.is-disabled){background:var(--bx-bg-element-hover)!important}.bx-menu-item-btn:hover:not(.is-disabled) .bx-menu-item-shortcut{color:inherit;opacity:1}.bx-menu-item-btn:active:not(.is-disabled){background:var(--bx-bg-element-active)!important}.bx-menu-item-btn:active:not(.is-disabled) .bx-menu-item-shortcut{color:inherit;opacity:1}.bx-menu-item-btn.is-danger{color:var(--bx-text-danger)}.bx-menu-item-btn.is-danger .bx-menu-item-shortcut{color:var(--bx-text-danger);opacity:.7}.bx-menu-item-btn.is-danger:hover:not(.is-disabled){background:var(--bx-bg-danger-hover)!important}.bx-menu-item-btn.is-danger:active:not(.is-disabled){background:var(--bx-bg-danger-active)!important}.bx-menu-item-btn.is-disabled{opacity:.4;cursor:not-allowed;pointer-events:none}.bx-menu-item-content{flex:1 1 auto;min-width:0;line-height:1.4;text-align:left}.bx-menu-item-content-wrapped{white-space:normal;overflow-wrap:anywhere}.bx-menu-item-shortcut{display:flex;align-items:center;gap:.15rem;margin-left:1.5rem;color:var(--bx-text-secondary);font-size:.875rem}.bx-menu-item-shortcut kbd{font-family:inherit;background:transparent;border:none;box-shadow:none;padding:0;margin:0;color:inherit}\n"]
1232
+ }]
1233
+ }],
1234
+ propDecorators: {
1235
+ icon: [{
1236
+ type: i0.Input,
1237
+ args: [{
1238
+ isSignal: true,
1239
+ alias: "icon",
1240
+ required: false
1241
+ }]
1242
+ }],
1243
+ endIcon: [{
1244
+ type: i0.Input,
1245
+ args: [{
1246
+ isSignal: true,
1247
+ alias: "endIcon",
1248
+ required: false
1249
+ }]
1250
+ }],
1251
+ label: [{
1252
+ type: i0.Input,
1253
+ args: [{
1254
+ isSignal: true,
1255
+ alias: "label",
1256
+ required: false
1257
+ }]
1258
+ }],
1259
+ wrapLabel: [{
1260
+ type: i0.Input,
1261
+ args: [{
1262
+ isSignal: true,
1263
+ alias: "wrapLabel",
1264
+ required: false
1265
+ }]
1266
+ }],
1267
+ tooltipOnTruncate: [{
1268
+ type: i0.Input,
1269
+ args: [{
1270
+ isSignal: true,
1271
+ alias: "tooltipOnTruncate",
1272
+ required: false
1273
+ }]
1274
+ }],
1275
+ disabled: [{
1276
+ type: i0.Input,
1277
+ args: [{
1278
+ isSignal: true,
1279
+ alias: "disabled",
1280
+ required: false
1281
+ }]
312
1282
  }],
313
1283
  danger: [{
314
1284
  type: i0.Input,
@@ -550,1329 +1520,1438 @@ i0.ɵɵngDeclareClassMetadata({
550
1520
  value: [{
551
1521
  type: i0.Input,
552
1522
  args: [{
553
- isSignal: true,
554
- alias: "value",
555
- required: false
556
- }]
557
- }],
558
- disabled: [{
559
- type: i0.Input,
560
- args: [{
561
- isSignal: true,
562
- alias: "disabled",
563
- required: false
564
- }]
565
- }],
566
- color: [{
567
- type: i0.Input,
568
- args: [{
569
- isSignal: true,
570
- alias: "color",
571
- required: false
572
- }]
573
- }],
574
- textColor: [{
575
- type: i0.Input,
576
- args: [{
577
- isSignal: true,
578
- alias: "textColor",
579
- required: false
580
- }]
581
- }],
582
- highlightColor: [{
583
- type: i0.Input,
584
- args: [{
585
- isSignal: true,
586
- alias: "highlightColor",
587
- required: false
588
- }]
589
- }],
590
- contentColor: [{
591
- type: i0.Input,
592
- args: [{
593
- isSignal: true,
594
- alias: "contentColor",
595
- required: false
596
- }]
597
- }],
598
- icon: [{
599
- type: i0.Input,
600
- args: [{
601
- isSignal: true,
602
- alias: "icon",
603
- required: false
604
- }]
605
- }],
606
- endIcon: [{
607
- type: i0.Input,
608
- args: [{
609
- isSignal: true,
610
- alias: "endIcon",
611
- required: false
612
- }]
613
- }]
614
- }
615
- });
616
- var Tabs = class Tabs {
617
- i18n = inject(BX_I18N, { optional: true });
618
- triggers = viewChildren("trigger", ...ngDevMode ? [{ debugName: "triggers" }] : /* istanbul ignore next */ []);
619
- a11y = inject(BxA11yService);
620
- hasRendered = signal(false, ...ngDevMode ? [{ debugName: "hasRendered" }] : /* istanbul ignore next */ []);
621
- tabs = contentChildren(Tab, ...ngDevMode ? [{ debugName: "tabs" }] : /* istanbul ignore next */ []);
622
- activeTab = computed(() => {
623
- const enabled = this.tabs().filter((tab) => !tab.disabled());
624
- return enabled.find((tab) => tab.value() === this.selectedValue()) ?? enabled[0];
625
- }, ...ngDevMode ? [{ debugName: "activeTab" }] : /* istanbul ignore next */ []);
626
- resolvedLabel = computed(() => resolveTabText(this.ariaLabel(), this.i18n), ...ngDevMode ? [{ debugName: "resolvedLabel" }] : /* istanbul ignore next */ []);
627
- variant = input(DEFAULT_TABS_VARIANT, ...ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []);
628
- ariaLabel = input(DEFAULT_TABS_LABEL, ...ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []);
629
- selectedValue = model(null, ...ngDevMode ? [{ debugName: "selectedValue" }] : /* istanbul ignore next */ []);
630
- constructor() {
631
- afterNextRender(() => this.hasRendered.set(true));
632
- afterRenderEffect(() => {
633
- const value = this.activeTab()?.value() ?? null;
634
- if (this.selectedValue() !== value) this.selectedValue.set(value);
635
- });
636
- }
637
- select(value) {
638
- if (this.tabs().find((item) => item.value() === value && !item.disabled())) this.selectedValue.set(value);
639
- }
640
- onTabKey(event, tab) {
641
- if (event.altKey || event.ctrlKey || event.metaKey || !TAB_NAVIGATION_KEYS.has(event.key)) return;
642
- const enabled = this.tabs().filter((item) => !item.disabled());
643
- const current = enabled.indexOf(tab);
644
- if (current < 0) return;
645
- event.preventDefault();
646
- event.stopPropagation();
647
- const button = event.currentTarget;
648
- const rtl = button.ownerDocument.defaultView?.getComputedStyle(button).direction === "rtl";
649
- const direction = (event.key === "ArrowRight" ? 1 : -1) * (rtl ? -1 : 1);
650
- const next = enabled[event.key === "Home" ? 0 : event.key === "End" ? enabled.length - 1 : (current + direction + enabled.length) % enabled.length];
651
- this.select(next.value());
652
- const trigger = this.triggers().find((item) => item.nativeElement.id === next.triggerId)?.nativeElement;
653
- trigger?.focus({ preventScroll: true });
654
- trigger?.scrollIntoView({
655
- block: "nearest",
656
- inline: "nearest"
657
- });
658
- }
659
- static ɵfac = i0.ɵɵngDeclareFactory({
660
- minVersion: "12.0.0",
661
- version: "22.2.3",
662
- ngImport: i0,
663
- type: Tabs,
664
- deps: [],
665
- target: i0.ɵɵFactoryTarget.Component
666
- });
667
- static ɵcmp = i0.ɵɵngDeclareComponent({
668
- minVersion: "17.0.0",
669
- version: "22.2.3",
670
- type: Tabs,
671
- isStandalone: true,
672
- selector: "bx-tabs",
673
- inputs: {
674
- variant: {
675
- classPropertyName: "variant",
676
- publicName: "variant",
677
- isSignal: true,
678
- isRequired: false,
679
- transformFunction: null
680
- },
681
- ariaLabel: {
682
- classPropertyName: "ariaLabel",
683
- publicName: "ariaLabel",
684
- isSignal: true,
685
- isRequired: false,
686
- transformFunction: null
687
- },
688
- selectedValue: {
689
- classPropertyName: "selectedValue",
690
- publicName: "selectedValue",
691
- isSignal: true,
692
- isRequired: false,
693
- transformFunction: null
694
- }
695
- },
696
- outputs: { selectedValue: "selectedValueChange" },
697
- host: { properties: {
698
- "class.bx-tabs-underline": "variant() === \"underline\"",
699
- "class.bx-tabs-animated": "hasRendered() && !a11y.isReducedMotion()"
700
- } },
701
- queries: [{
702
- propertyName: "tabs",
703
- predicate: Tab,
704
- isSignal: true
705
- }],
706
- viewQueries: [{
707
- propertyName: "triggers",
708
- predicate: ["trigger"],
709
- descendants: true,
710
- isSignal: true
711
- }],
712
- ngImport: i0,
713
- template: "<ng-content select=\"bx-tab\"></ng-content>\n\n<div bxSurface data-bx-surface=\"glass\" class=\"bx-tab-header\" role=\"tablist\" [attr.aria-label]=\"resolvedLabel()\" aria-orientation=\"horizontal\">\n<div class=\"bx-tab-list\">\n @for (tab of tabs(); track tab) {\n <button #trigger bxSurface data-bx-surface=\"glass\" class=\"bx-tab-trigger\" type=\"button\" role=\"tab\"\n [bxSurfaceEmission]=\"tab.resolvedEmission()\"\n [style.--bx-tab-highlight]=\"tab.resolvedHighlight()\" [style.--bx-tab-text]=\"tab.resolvedTextColor()\"\n [style.--bx-tab-selected-text]=\"tab.resolvedSelectedText()\"\n [id]=\"tab.triggerId\" [attr.aria-controls]=\"tab.panelId\" [attr.aria-selected]=\"tab === activeTab()\"\n [attr.tabindex]=\"tab === activeTab() ? 0 : -1\" [disabled]=\"tab.disabled()\"\n [class.is-selected]=\"tab === activeTab()\" (click)=\"select(tab.value())\" (keydown)=\"onTabKey($event, tab)\">\n @if (tab.icon()) { <bx-icon [name]=\"tab.icon()!\" size=\"16\" /> }\n <span>{{ tab.resolvedLabel() }}</span>\n @if (tab.endIcon()) { <bx-icon [name]=\"tab.endIcon()!\" size=\"16\" /> }\n </button>\n }\n</div>\n</div>\n\n<div class=\"bx-tab-panels\">\n @for (tab of tabs(); track tab) {\n <div class=\"bx-tab-panel\" role=\"tabpanel\" tabindex=\"0\" [id]=\"tab.panelId\"\n [style.color]=\"tab.resolvedContentColor()\"\n [attr.aria-labelledby]=\"tab.triggerId\" [hidden]=\"tab !== activeTab()\">\n @if (tab === activeTab()) {\n <ng-container [ngTemplateOutlet]=\"tab.template()\"></ng-container>\n }\n </div>\n }\n</div>\n",
714
- styles: [":host{display:flex;flex-direction:column;min-width:0;min-height:0;box-sizing:border-box;width:100%;max-width:100%;gap:var(--bx-tabs-panel-gap, 1.5rem)}.bx-tab-header{--bx-glass-surface: var(--bx-bg-surface-alt);--bx-glass-edge: var(--bx-border-default);--bx-glass-shadow: none;--bx-glass-opacity: calc(.1 + .25 * var(--bx-glassiness, .5));--bx-glass-radius: .5rem;display:flex;align-self:flex-start;flex:none;box-sizing:border-box;width:fit-content;max-width:100%;padding:.25rem;border:1px solid var(--bx-border-default);border-radius:.5rem}.bx-tab-list{display:flex;flex:1 1 auto;gap:.25rem;min-width:0;padding:1px;overflow:auto hidden;overscroll-behavior-x:contain;scrollbar-width:thin}.bx-tab-trigger{--bx-glass-surface: var(--bx-bg-surface);--bx-glass-text: var(--bx-tab-text, var(--bx-text-secondary));--bx-glass-edge: transparent;--bx-glass-radius: .25rem;--bx-glass-opacity: 0;--bx-glass-decoration-opacity: 0;--bx-glass-rim-visibility: 0;--bx-glass-shadow: none;display:inline-flex;align-items:center;gap:.5rem;flex:none;padding:.5rem .75rem;border:1px solid transparent;border-radius:.25rem;font:inherit;font-size:.875rem;white-space:nowrap;cursor:pointer}.bx-tab-trigger:hover:not(:disabled,.is-selected){--bx-glass-text: var(--bx-tab-text, var(--bx-text-primary));--bx-glass-opacity: .15}.bx-tab-trigger.is-selected{--bx-glass-surface: color-mix( in srgb, var(--bx-tab-highlight, var(--bx-primary)) 35%, var(--bx-bg-surface) );--bx-glass-text: var(--bx-tab-selected-text, var(--bx-text-brand));--bx-glass-edge: color-mix( in srgb, var(--bx-tab-highlight, var(--bx-primary)) 35%, transparent );--bx-glass-opacity: .45;--bx-glass-decoration-opacity: .5;--bx-glass-rim-visibility: .65;--bx-glass-shadow: 0 2px 4px 0 rgba(0, 0, 0, .1), 0 1px 2px -1px rgba(0, 0, 0, .1)}.bx-tab-trigger:disabled{opacity:.4;cursor:not-allowed}.bx-tab-trigger:focus-visible{outline:2px solid var(--bx-tab-highlight, var(--bx-border-brand));outline-offset:-2px}.bx-tab-panels{flex:1 1 auto;min-width:0;min-height:0;max-height:var(--bx-tabs-max-panel-height, none);overflow:var(--bx-tabs-panel-overflow, visible)}.bx-tab-panel{min-width:0}.bx-tab-panel:focus-visible{outline:2px solid var(--bx-border-brand);outline-offset:-2px}:host(.bx-tabs-animated) .bx-tab-trigger{transition:background-color .1s ease-in-out,color .1s ease-in-out,box-shadow .1s ease-in-out}:host(.bx-tabs-underline){gap:var(--bx-tabs-panel-gap, 0)}:host(.bx-tabs-underline) .bx-tab-header{align-self:stretch;width:auto;padding:0;border:0;border-bottom:1px solid var(--bx-border-default);border-radius:0}:host(.bx-tabs-underline) .bx-tab-list{gap:0}:host(.bx-tabs-underline) .bx-tab-trigger{padding:.75rem 1rem;border-inline-end:1px solid var(--bx-border-default);border-radius:0;font-size:.8rem}:host(.bx-tabs-underline) .bx-tab-trigger.is-selected{--bx-glass-shadow: inset 0 -2px 0 var(--bx-tab-highlight, var(--bx-border-brand))}@media(forced-colors:active){.bx-tab-trigger.is-selected{outline:2px solid Highlight;outline-offset:-2px}}\n"],
715
- dependencies: [
716
- {
717
- kind: "directive",
718
- type: NgTemplateOutlet,
719
- selector: "[ngTemplateOutlet]",
720
- inputs: [
721
- "ngTemplateOutletContext",
722
- "ngTemplateOutlet",
723
- "ngTemplateOutletInjector"
724
- ]
725
- },
726
- {
727
- kind: "directive",
728
- type: BxSurfaceDirective,
729
- selector: "[bxSurface]",
730
- inputs: [
731
- "bxSurfaceInteractive",
732
- "bxSurfaceGlassiness",
733
- "bxSurfaceEmission",
734
- "bxSurfaceFocusEmission",
735
- "bxReducedTransparency"
736
- ],
737
- exportAs: ["bxSurface"]
738
- },
739
- {
740
- kind: "component",
741
- type: Icon,
742
- selector: "bx-icon",
743
- inputs: [
744
- "name",
745
- "size",
746
- "color",
747
- "bgColor",
748
- "strokeWidth",
749
- "decorative",
750
- "ariaLabel"
751
- ]
752
- }
753
- ],
754
- changeDetection: i0.ChangeDetectionStrategy.OnPush
755
- });
756
- };
757
- i0.ɵɵngDeclareClassMetadata({
758
- minVersion: "12.0.0",
759
- version: "22.2.3",
760
- ngImport: i0,
761
- type: Tabs,
762
- decorators: [{
763
- type: Component,
764
- args: [{
765
- selector: "bx-tabs",
766
- standalone: true,
767
- imports: [
768
- NgTemplateOutlet,
769
- BxSurfaceDirective,
770
- Icon
771
- ],
772
- changeDetection: ChangeDetectionStrategy.OnPush,
773
- host: {
774
- "[class.bx-tabs-underline]": "variant() === \"underline\"",
775
- "[class.bx-tabs-animated]": "hasRendered() && !a11y.isReducedMotion()"
776
- },
777
- template: "<ng-content select=\"bx-tab\"></ng-content>\n\n<div bxSurface data-bx-surface=\"glass\" class=\"bx-tab-header\" role=\"tablist\" [attr.aria-label]=\"resolvedLabel()\" aria-orientation=\"horizontal\">\n<div class=\"bx-tab-list\">\n @for (tab of tabs(); track tab) {\n <button #trigger bxSurface data-bx-surface=\"glass\" class=\"bx-tab-trigger\" type=\"button\" role=\"tab\"\n [bxSurfaceEmission]=\"tab.resolvedEmission()\"\n [style.--bx-tab-highlight]=\"tab.resolvedHighlight()\" [style.--bx-tab-text]=\"tab.resolvedTextColor()\"\n [style.--bx-tab-selected-text]=\"tab.resolvedSelectedText()\"\n [id]=\"tab.triggerId\" [attr.aria-controls]=\"tab.panelId\" [attr.aria-selected]=\"tab === activeTab()\"\n [attr.tabindex]=\"tab === activeTab() ? 0 : -1\" [disabled]=\"tab.disabled()\"\n [class.is-selected]=\"tab === activeTab()\" (click)=\"select(tab.value())\" (keydown)=\"onTabKey($event, tab)\">\n @if (tab.icon()) { <bx-icon [name]=\"tab.icon()!\" size=\"16\" /> }\n <span>{{ tab.resolvedLabel() }}</span>\n @if (tab.endIcon()) { <bx-icon [name]=\"tab.endIcon()!\" size=\"16\" /> }\n </button>\n }\n</div>\n</div>\n\n<div class=\"bx-tab-panels\">\n @for (tab of tabs(); track tab) {\n <div class=\"bx-tab-panel\" role=\"tabpanel\" tabindex=\"0\" [id]=\"tab.panelId\"\n [style.color]=\"tab.resolvedContentColor()\"\n [attr.aria-labelledby]=\"tab.triggerId\" [hidden]=\"tab !== activeTab()\">\n @if (tab === activeTab()) {\n <ng-container [ngTemplateOutlet]=\"tab.template()\"></ng-container>\n }\n </div>\n }\n</div>\n",
778
- styles: [":host{display:flex;flex-direction:column;min-width:0;min-height:0;box-sizing:border-box;width:100%;max-width:100%;gap:var(--bx-tabs-panel-gap, 1.5rem)}.bx-tab-header{--bx-glass-surface: var(--bx-bg-surface-alt);--bx-glass-edge: var(--bx-border-default);--bx-glass-shadow: none;--bx-glass-opacity: calc(.1 + .25 * var(--bx-glassiness, .5));--bx-glass-radius: .5rem;display:flex;align-self:flex-start;flex:none;box-sizing:border-box;width:fit-content;max-width:100%;padding:.25rem;border:1px solid var(--bx-border-default);border-radius:.5rem}.bx-tab-list{display:flex;flex:1 1 auto;gap:.25rem;min-width:0;padding:1px;overflow:auto hidden;overscroll-behavior-x:contain;scrollbar-width:thin}.bx-tab-trigger{--bx-glass-surface: var(--bx-bg-surface);--bx-glass-text: var(--bx-tab-text, var(--bx-text-secondary));--bx-glass-edge: transparent;--bx-glass-radius: .25rem;--bx-glass-opacity: 0;--bx-glass-decoration-opacity: 0;--bx-glass-rim-visibility: 0;--bx-glass-shadow: none;display:inline-flex;align-items:center;gap:.5rem;flex:none;padding:.5rem .75rem;border:1px solid transparent;border-radius:.25rem;font:inherit;font-size:.875rem;white-space:nowrap;cursor:pointer}.bx-tab-trigger:hover:not(:disabled,.is-selected){--bx-glass-text: var(--bx-tab-text, var(--bx-text-primary));--bx-glass-opacity: .15}.bx-tab-trigger.is-selected{--bx-glass-surface: color-mix( in srgb, var(--bx-tab-highlight, var(--bx-primary)) 35%, var(--bx-bg-surface) );--bx-glass-text: var(--bx-tab-selected-text, var(--bx-text-brand));--bx-glass-edge: color-mix( in srgb, var(--bx-tab-highlight, var(--bx-primary)) 35%, transparent );--bx-glass-opacity: .45;--bx-glass-decoration-opacity: .5;--bx-glass-rim-visibility: .65;--bx-glass-shadow: 0 2px 4px 0 rgba(0, 0, 0, .1), 0 1px 2px -1px rgba(0, 0, 0, .1)}.bx-tab-trigger:disabled{opacity:.4;cursor:not-allowed}.bx-tab-trigger:focus-visible{outline:2px solid var(--bx-tab-highlight, var(--bx-border-brand));outline-offset:-2px}.bx-tab-panels{flex:1 1 auto;min-width:0;min-height:0;max-height:var(--bx-tabs-max-panel-height, none);overflow:var(--bx-tabs-panel-overflow, visible)}.bx-tab-panel{min-width:0}.bx-tab-panel:focus-visible{outline:2px solid var(--bx-border-brand);outline-offset:-2px}:host(.bx-tabs-animated) .bx-tab-trigger{transition:background-color .1s ease-in-out,color .1s ease-in-out,box-shadow .1s ease-in-out}:host(.bx-tabs-underline){gap:var(--bx-tabs-panel-gap, 0)}:host(.bx-tabs-underline) .bx-tab-header{align-self:stretch;width:auto;padding:0;border:0;border-bottom:1px solid var(--bx-border-default);border-radius:0}:host(.bx-tabs-underline) .bx-tab-list{gap:0}:host(.bx-tabs-underline) .bx-tab-trigger{padding:.75rem 1rem;border-inline-end:1px solid var(--bx-border-default);border-radius:0;font-size:.8rem}:host(.bx-tabs-underline) .bx-tab-trigger.is-selected{--bx-glass-shadow: inset 0 -2px 0 var(--bx-tab-highlight, var(--bx-border-brand))}@media(forced-colors:active){.bx-tab-trigger.is-selected{outline:2px solid Highlight;outline-offset:-2px}}\n"]
779
- }]
780
- }],
781
- ctorParameters: () => [],
782
- propDecorators: {
783
- triggers: [{
784
- type: i0.ViewChildren,
785
- args: ["trigger", { isSignal: true }]
1523
+ isSignal: true,
1524
+ alias: "value",
1525
+ required: false
1526
+ }]
786
1527
  }],
787
- tabs: [{
788
- type: i0.ContentChildren,
789
- args: [i0.forwardRef(() => Tab), { isSignal: true }]
1528
+ disabled: [{
1529
+ type: i0.Input,
1530
+ args: [{
1531
+ isSignal: true,
1532
+ alias: "disabled",
1533
+ required: false
1534
+ }]
790
1535
  }],
791
- variant: [{
1536
+ color: [{
792
1537
  type: i0.Input,
793
1538
  args: [{
794
1539
  isSignal: true,
795
- alias: "variant",
1540
+ alias: "color",
796
1541
  required: false
797
1542
  }]
798
1543
  }],
799
- ariaLabel: [{
1544
+ textColor: [{
800
1545
  type: i0.Input,
801
1546
  args: [{
802
1547
  isSignal: true,
803
- alias: "ariaLabel",
1548
+ alias: "textColor",
804
1549
  required: false
805
1550
  }]
806
1551
  }],
807
- selectedValue: [{
1552
+ highlightColor: [{
808
1553
  type: i0.Input,
809
1554
  args: [{
810
1555
  isSignal: true,
811
- alias: "selectedValue",
1556
+ alias: "highlightColor",
812
1557
  required: false
813
1558
  }]
814
- }, {
815
- type: i0.Output,
816
- args: ["selectedValueChange"]
817
- }]
818
- }
819
- });
820
- const BX_OVERLAY_CONTEXT = new InjectionToken("BX_OVERLAY_CONTEXT");
821
- var ContextMenuDirective = class ContextMenuDirective {
822
- overlay = inject(Overlay);
823
- positionBuilder = inject(BxOverlayPositionService);
824
- overlayContext = inject(BX_OVERLAY_CONTEXT, { optional: true });
825
- elementRef = inject(ElementRef);
826
- a11y = inject(BxA11yService);
827
- zone = inject(NgZone);
828
- vcr = inject(ViewContainerRef);
829
- bxContextMenu = input.required(...ngDevMode ? [{ debugName: "bxContextMenu" }] : /* istanbul ignore next */ []);
830
- bxContextMenuLongPress = input(true, {
831
- ...ngDevMode ? { debugName: "bxContextMenuLongPress" } : /* istanbul ignore next */ {},
832
- transform: booleanAttribute
833
- });
834
- onPointerDown = (event) => {
835
- this.lastPointerType = event.pointerType;
836
- this.cancelTouchPress();
837
- if (event.isPrimary) this.clearTouchGuard();
838
- if (event.pointerType !== "touch" || !event.isPrimary || event.button !== 0 || !this.bxContextMenuLongPress() || this.hasNativeTouchAction(event)) return;
839
- const doc = this.elementRef.nativeElement.ownerDocument;
840
- const win = doc.defaultView;
841
- if (!win || this.hasTextSelection()) return;
842
- const press = {
843
- pointerId: event.pointerId,
844
- x: event.clientX,
845
- y: event.clientY,
846
- timer: 0,
847
- opened: false,
848
- events: new AbortController()
849
- };
850
- this.touchPress = press;
851
- const options = {
852
- capture: true,
853
- passive: true,
854
- signal: press.events.signal
855
- };
856
- const finish = () => this.cancelTouchPress();
857
- doc.addEventListener("pointermove", (move) => {
858
- if (move.pointerId === press.pointerId && !press.opened && Math.hypot(move.clientX - press.x, move.clientY - press.y) > 10) finish();
859
- }, options);
860
- for (const type of ["pointerup", "pointercancel"]) doc.addEventListener(type, (end) => {
861
- if (end.pointerId === press.pointerId) finish();
862
- }, options);
863
- doc.addEventListener("pointerdown", (next) => {
864
- if (next.pointerId !== press.pointerId) finish();
865
- }, options);
866
- doc.addEventListener("scroll", finish, options);
867
- doc.addEventListener("visibilitychange", () => {
868
- if (doc.hidden) finish();
869
- }, options);
870
- win.addEventListener("blur", finish, { signal: press.events.signal });
871
- press.timer = win.setTimeout(() => this.zone.run(() => this.openTouchMenu(press)), 500);
872
- };
873
- overlayRef = null;
874
- transition;
875
- point;
876
- disconnectTheme;
877
- disconnectLighting;
878
- subscriptions = new Subscription();
879
- revision = 0;
880
- touchPress;
881
- touchGuard;
882
- touchGuardTimer;
883
- lastPointerType = "";
884
- constructor() {
885
- const source = this.elementRef.nativeElement;
886
- if (source.ownerDocument.defaultView) this.zone.runOutsideAngular(() => source.addEventListener("pointerdown", this.onPointerDown, { passive: true }));
887
- inject(DestroyRef).onDestroy(() => {
888
- ++this.revision;
889
- source.removeEventListener("pointerdown", this.onPointerDown);
890
- this.cancelTouchPress();
891
- this.clearTouchGuard();
892
- this.dispose();
893
- });
894
- }
895
- open(event) {
896
- if (event.type === "contextmenu" && this.lastPointerType === "touch") {
897
- const press = this.touchPress;
898
- if (!press) return;
899
- if (!this.bxContextMenuLongPress() || this.hasNativeTouchAction(event) || this.hasTextSelection()) {
900
- this.cancelTouchPress();
901
- return;
902
- }
903
- event.preventDefault();
904
- this.openTouchMenu(press);
905
- return;
906
- }
907
- event.preventDefault();
908
- this.cancelTouchPress();
909
- this.clearTouchGuard();
910
- this.openAt(event.clientX, event.clientY);
911
- }
912
- close(restoreFocus = false) {
913
- if (!this.overlayRef) return;
914
- const revision = ++this.revision;
915
- if (restoreFocus || this.overlayRef.overlayElement.contains(this.elementRef.nativeElement.ownerDocument.activeElement)) this.elementRef.nativeElement.focus({ preventScroll: true });
916
- this.overlayRef.overlayElement.inert = true;
917
- const transition = this.transition;
918
- if (transition && !this.a11y.isReducedMotion()) this.zone.runOutsideAngular(() => transition.exit()).then(() => {
919
- if (revision === this.revision) this.dispose();
920
- }).catch(() => {
921
- if (revision === this.revision) this.dispose();
922
- });
923
- else this.dispose();
924
- }
925
- onKey(event) {
926
- if (event.key !== "ContextMenu" && !(event.shiftKey && event.key === "F10")) return;
927
- event.preventDefault();
928
- this.lastPointerType = "";
929
- this.cancelTouchPress();
930
- this.clearTouchGuard();
931
- const rect = this.elementRef.nativeElement.getBoundingClientRect();
932
- this.openAt(rect.left + Math.min(24, rect.width / 2), rect.bottom);
933
- this.items()[0]?.focus();
934
- }
935
- onDocumentClick(event) {
936
- const target = event.target;
937
- if (target && this.overlayRef?.overlayElement.contains(target) && target.closest("button, a, [role=\"menuitem\"]")) this.close();
938
- }
939
- hasNativeTouchAction(event) {
940
- const source = this.elementRef.nativeElement;
941
- for (const node of event.composedPath()) if (node instanceof HTMLElement) {
942
- if (node.isContentEditable || node.matches("input, textarea, select, :disabled, [aria-disabled=\"true\"], [inert]")) return true;
943
- if (node === source) break;
944
- }
945
- return !!source.closest(":disabled, [aria-disabled=\"true\"], [inert]");
946
- }
947
- hasTextSelection() {
948
- const source = this.elementRef.nativeElement;
949
- const selection = source.ownerDocument.getSelection();
950
- return !!selection && !selection.isCollapsed && (source.contains(selection.anchorNode) || source.contains(selection.focusNode));
951
- }
952
- openTouchMenu(press) {
953
- if (this.touchPress !== press || press.opened) return;
954
- const source = this.elementRef.nativeElement;
955
- if (!this.bxContextMenuLongPress() || !source.isConnected || source.isContentEditable || source.closest(":disabled, [aria-disabled=\"true\"], [inert]") || this.hasTextSelection()) {
956
- this.cancelTouchPress();
957
- return;
958
- }
959
- press.opened = true;
960
- this.elementRef.nativeElement.ownerDocument.defaultView?.clearTimeout(press.timer);
961
- this.guardTouchRelease();
962
- this.openAt(press.x, press.y + 12);
963
- }
964
- cancelTouchPress() {
965
- const press = this.touchPress;
966
- if (!press) return;
967
- this.touchPress = void 0;
968
- const win = this.elementRef.nativeElement.ownerDocument.defaultView;
969
- win?.clearTimeout(press.timer);
970
- press.events.abort();
971
- if (press.opened && win) this.touchGuardTimer = win.setTimeout(() => this.clearTouchGuard(), 800);
972
- }
973
- guardTouchRelease() {
974
- this.clearTouchGuard();
975
- const doc = this.elementRef.nativeElement.ownerDocument;
976
- const guard = new AbortController();
977
- this.touchGuard = guard;
978
- const options = {
979
- capture: true,
980
- signal: guard.signal
981
- };
982
- doc.addEventListener("click", (event) => {
983
- if (event.detail === 0) return;
984
- event.preventDefault();
985
- event.stopImmediatePropagation();
986
- this.clearTouchGuard();
987
- }, options);
988
- doc.addEventListener("contextmenu", (event) => {
989
- event.preventDefault();
990
- event.stopImmediatePropagation();
991
- }, options);
992
- doc.addEventListener("pointerdown", (event) => {
993
- if (event.isPrimary) this.clearTouchGuard();
994
- }, {
995
- ...options,
996
- passive: true
997
- });
998
- doc.addEventListener("keydown", () => this.clearTouchGuard(), options);
999
- }
1000
- clearTouchGuard() {
1001
- this.touchGuard?.abort();
1002
- this.touchGuard = void 0;
1003
- this.elementRef.nativeElement.ownerDocument.defaultView?.clearTimeout(this.touchGuardTimer);
1004
- this.touchGuardTimer = void 0;
1005
- }
1006
- openAt(x, y) {
1007
- this.dispose();
1008
- ++this.revision;
1009
- const source = this.elementRef.nativeElement;
1010
- this.overlayRef = this.overlay.create({
1011
- positionStrategy: this.positionBuilder.getCoordinateStrategy(x, y),
1012
- scrollStrategy: this.overlay.scrollStrategies.noop(),
1013
- usePopover: !!this.overlayContext?.useTopLayer || !!source.closest("dialog, [role=\"dialog\"], [role=\"alertdialog\"], bx-modal, bx-modal-core, [popover]"),
1014
- hasBackdrop: true,
1015
- backdropClass: "cdk-overlay-transparent-backdrop"
1016
- });
1017
- this.subscriptions = new Subscription();
1018
- const win = source.ownerDocument.defaultView;
1019
- if (win) this.zone.runOutsideAngular(() => {
1020
- const closeOnScroll = (event) => {
1021
- const target = event.target;
1022
- if (this.overlayRef?.overlayElement.inert) return;
1023
- if (target === win || target instanceof Node && target.contains(source)) this.zone.run(() => this.close());
1024
- };
1025
- win.addEventListener("scroll", closeOnScroll, {
1026
- capture: true,
1027
- passive: true
1028
- });
1029
- this.subscriptions.add(() => win.removeEventListener("scroll", closeOnScroll, true));
1559
+ }],
1560
+ contentColor: [{
1561
+ type: i0.Input,
1562
+ args: [{
1563
+ isSignal: true,
1564
+ alias: "contentColor",
1565
+ required: false
1566
+ }]
1567
+ }],
1568
+ icon: [{
1569
+ type: i0.Input,
1570
+ args: [{
1571
+ isSignal: true,
1572
+ alias: "icon",
1573
+ required: false
1574
+ }]
1575
+ }],
1576
+ endIcon: [{
1577
+ type: i0.Input,
1578
+ args: [{
1579
+ isSignal: true,
1580
+ alias: "endIcon",
1581
+ required: false
1582
+ }]
1583
+ }]
1584
+ }
1585
+ });
1586
+ var Tabs = class Tabs {
1587
+ i18n = inject(BX_I18N, { optional: true });
1588
+ triggers = viewChildren("trigger", ...ngDevMode ? [{ debugName: "triggers" }] : /* istanbul ignore next */ []);
1589
+ a11y = inject(BxA11yService);
1590
+ hasRendered = signal(false, ...ngDevMode ? [{ debugName: "hasRendered" }] : /* istanbul ignore next */ []);
1591
+ tabs = contentChildren(Tab, ...ngDevMode ? [{ debugName: "tabs" }] : /* istanbul ignore next */ []);
1592
+ activeTab = computed(() => {
1593
+ const enabled = this.tabs().filter((tab) => !tab.disabled());
1594
+ return enabled.find((tab) => tab.value() === this.selectedValue()) ?? enabled[0];
1595
+ }, ...ngDevMode ? [{ debugName: "activeTab" }] : /* istanbul ignore next */ []);
1596
+ resolvedLabel = computed(() => resolveTabText(this.ariaLabel(), this.i18n), ...ngDevMode ? [{ debugName: "resolvedLabel" }] : /* istanbul ignore next */ []);
1597
+ variant = input(DEFAULT_TABS_VARIANT, ...ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []);
1598
+ ariaLabel = input(DEFAULT_TABS_LABEL, ...ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []);
1599
+ selectedValue = model(null, ...ngDevMode ? [{ debugName: "selectedValue" }] : /* istanbul ignore next */ []);
1600
+ constructor() {
1601
+ afterNextRender(() => this.hasRendered.set(true));
1602
+ afterRenderEffect(() => {
1603
+ const value = this.activeTab()?.value() ?? null;
1604
+ if (this.selectedValue() !== value) this.selectedValue.set(value);
1030
1605
  });
1031
- this.subscriptions.add(this.overlayRef.backdropClick().subscribe(() => this.close()));
1032
- this.subscriptions.add(this.overlayRef.detachments().subscribe(() => this.dispose()));
1033
- this.subscriptions.add(this.overlayRef.keydownEvents().subscribe((event) => this.onMenuKey(event)));
1034
- const pane = this.overlayRef.overlayElement;
1035
- this.disconnectTheme = this.zone.runOutsideAngular(() => inheritOverlayTheme(source, pane));
1036
- this.disconnectLighting = inheritGlassLighting(pane, source);
1037
- this.overlayRef.attach(new TemplatePortal(this.bxContextMenu(), this.vcr)).detectChanges();
1038
- this.overlayRef.updatePosition();
1039
- if (!this.a11y.isReducedMotion()) {
1040
- const point = source.ownerDocument.createElement("span");
1041
- point.setAttribute("aria-hidden", "true");
1042
- Object.assign(point.style, {
1043
- position: "fixed",
1044
- left: `${x}px`,
1045
- top: `${y}px`,
1046
- width: "1px",
1047
- height: "1px",
1048
- pointerEvents: "none"
1049
- });
1050
- source.ownerDocument.body.append(point);
1051
- this.point = point;
1052
- const transition = this.zone.runOutsideAngular(() => createGlassTransition(point, pane));
1053
- this.transition = transition;
1054
- this.zone.runOutsideAngular(() => transition.enter()).catch(() => {
1055
- this.transition?.destroy();
1056
- this.transition = void 0;
1057
- });
1058
- }
1059
1606
  }
1060
- items() {
1061
- return Array.from(this.overlayRef?.overlayElement.querySelectorAll("button:not(:disabled), a[href], [role=\"menuitem\"]") ?? []).filter((item) => !item.matches("[disabled], [aria-disabled=\"true\"]") && !item.closest("[hidden], [inert]"));
1607
+ select(value) {
1608
+ if (this.tabs().find((item) => item.value() === value && !item.disabled())) this.selectedValue.set(value);
1062
1609
  }
1063
- onMenuKey(event) {
1064
- if (event.key === "Escape") {
1065
- event.preventDefault();
1066
- event.stopPropagation();
1067
- this.close(true);
1068
- return;
1069
- }
1070
- if (event.target?.closest("input,textarea,[contenteditable=\"true\"]")) return;
1071
- if (![
1072
- "ArrowDown",
1073
- "ArrowUp",
1074
- "Home",
1075
- "End"
1076
- ].includes(event.key)) return;
1077
- const items = this.items();
1078
- if (!items.length) return;
1610
+ onTabKey(event, tab) {
1611
+ if (event.altKey || event.ctrlKey || event.metaKey || !TAB_NAVIGATION_KEYS.has(event.key)) return;
1612
+ const enabled = this.tabs().filter((item) => !item.disabled());
1613
+ const current = enabled.indexOf(tab);
1614
+ if (current < 0) return;
1079
1615
  event.preventDefault();
1080
- const current = items.indexOf(this.elementRef.nativeElement.ownerDocument.activeElement);
1081
- items[event.key === "Home" ? 0 : event.key === "End" ? items.length - 1 : event.key === "ArrowDown" ? (current + 1) % items.length : current < 0 ? items.length - 1 : (current - 1 + items.length) % items.length].focus();
1082
- }
1083
- dispose() {
1084
- this.subscriptions.unsubscribe();
1085
- this.disconnectTheme?.();
1086
- this.disconnectTheme = void 0;
1087
- this.transition?.destroy();
1088
- this.transition = void 0;
1089
- this.point?.remove();
1090
- this.point = void 0;
1091
- const overlay = this.overlayRef;
1092
- this.overlayRef = null;
1093
- overlay?.dispose();
1094
- this.disconnectLighting?.();
1095
- this.disconnectLighting = void 0;
1616
+ event.stopPropagation();
1617
+ const button = event.currentTarget;
1618
+ const rtl = button.ownerDocument.defaultView?.getComputedStyle(button).direction === "rtl";
1619
+ const direction = (event.key === "ArrowRight" ? 1 : -1) * (rtl ? -1 : 1);
1620
+ const next = enabled[event.key === "Home" ? 0 : event.key === "End" ? enabled.length - 1 : (current + direction + enabled.length) % enabled.length];
1621
+ this.select(next.value());
1622
+ const trigger = this.triggers().find((item) => item.nativeElement.id === next.triggerId)?.nativeElement;
1623
+ trigger?.focus({ preventScroll: true });
1624
+ trigger?.scrollIntoView({
1625
+ block: "nearest",
1626
+ inline: "nearest"
1627
+ });
1096
1628
  }
1097
1629
  static ɵfac = i0.ɵɵngDeclareFactory({
1098
1630
  minVersion: "12.0.0",
1099
1631
  version: "22.2.3",
1100
1632
  ngImport: i0,
1101
- type: ContextMenuDirective,
1633
+ type: Tabs,
1102
1634
  deps: [],
1103
- target: i0.ɵɵFactoryTarget.Directive
1635
+ target: i0.ɵɵFactoryTarget.Component
1104
1636
  });
1105
- static ɵdir = i0.ɵɵngDeclareDirective({
1106
- minVersion: "17.1.0",
1637
+ static ɵcmp = i0.ɵɵngDeclareComponent({
1638
+ minVersion: "17.0.0",
1107
1639
  version: "22.2.3",
1108
- type: ContextMenuDirective,
1640
+ type: Tabs,
1109
1641
  isStandalone: true,
1110
- selector: "[bxContextMenu]",
1642
+ selector: "bx-tabs",
1111
1643
  inputs: {
1112
- bxContextMenu: {
1113
- classPropertyName: "bxContextMenu",
1114
- publicName: "bxContextMenu",
1644
+ variant: {
1645
+ classPropertyName: "variant",
1646
+ publicName: "variant",
1115
1647
  isSignal: true,
1116
- isRequired: true,
1648
+ isRequired: false,
1117
1649
  transformFunction: null
1118
1650
  },
1119
- bxContextMenuLongPress: {
1120
- classPropertyName: "bxContextMenuLongPress",
1121
- publicName: "bxContextMenuLongPress",
1651
+ ariaLabel: {
1652
+ classPropertyName: "ariaLabel",
1653
+ publicName: "ariaLabel",
1654
+ isSignal: true,
1655
+ isRequired: false,
1656
+ transformFunction: null
1657
+ },
1658
+ selectedValue: {
1659
+ classPropertyName: "selectedValue",
1660
+ publicName: "selectedValue",
1122
1661
  isSignal: true,
1123
1662
  isRequired: false,
1124
1663
  transformFunction: null
1125
1664
  }
1126
1665
  },
1127
- host: { listeners: {
1128
- "contextmenu": "open($event)",
1129
- "keydown": "onKey($event)",
1130
- "document:click": "onDocumentClick($event)"
1666
+ outputs: { selectedValue: "selectedValueChange" },
1667
+ host: { properties: {
1668
+ "class.bx-tabs-underline": "variant() === \"underline\"",
1669
+ "class.bx-tabs-animated": "hasRendered() && !a11y.isReducedMotion()"
1131
1670
  } },
1132
- ngImport: i0
1671
+ queries: [{
1672
+ propertyName: "tabs",
1673
+ predicate: Tab,
1674
+ isSignal: true
1675
+ }],
1676
+ viewQueries: [{
1677
+ propertyName: "triggers",
1678
+ predicate: ["trigger"],
1679
+ descendants: true,
1680
+ isSignal: true
1681
+ }],
1682
+ ngImport: i0,
1683
+ template: "<ng-content select=\"bx-tab\"></ng-content>\n\n<div bxSurface data-bx-surface=\"glass\" class=\"bx-tab-header\" role=\"tablist\" [attr.aria-label]=\"resolvedLabel()\" aria-orientation=\"horizontal\">\n<div class=\"bx-tab-list\">\n @for (tab of tabs(); track tab) {\n <button #trigger bxSurface data-bx-surface=\"glass\" class=\"bx-tab-trigger\" type=\"button\" role=\"tab\"\n [bxSurfaceEmission]=\"tab.resolvedEmission()\"\n [style.--bx-tab-highlight]=\"tab.resolvedHighlight()\" [style.--bx-tab-text]=\"tab.resolvedTextColor()\"\n [style.--bx-tab-selected-text]=\"tab.resolvedSelectedText()\"\n [id]=\"tab.triggerId\" [attr.aria-controls]=\"tab.panelId\" [attr.aria-selected]=\"tab === activeTab()\"\n [attr.tabindex]=\"tab === activeTab() ? 0 : -1\" [disabled]=\"tab.disabled()\"\n [class.is-selected]=\"tab === activeTab()\" (click)=\"select(tab.value())\" (keydown)=\"onTabKey($event, tab)\">\n @if (tab.icon()) { <bx-icon [name]=\"tab.icon()!\" size=\"16\" /> }\n <span>{{ tab.resolvedLabel() }}</span>\n @if (tab.endIcon()) { <bx-icon [name]=\"tab.endIcon()!\" size=\"16\" /> }\n </button>\n }\n</div>\n</div>\n\n<div class=\"bx-tab-panels\">\n @for (tab of tabs(); track tab) {\n <div class=\"bx-tab-panel\" role=\"tabpanel\" tabindex=\"0\" [id]=\"tab.panelId\"\n [style.color]=\"tab.resolvedContentColor()\"\n [attr.aria-labelledby]=\"tab.triggerId\" [hidden]=\"tab !== activeTab()\">\n @if (tab === activeTab()) {\n <ng-container [ngTemplateOutlet]=\"tab.template()\"></ng-container>\n }\n </div>\n }\n</div>\n",
1684
+ styles: [":host{display:flex;flex-direction:column;min-width:0;min-height:0;box-sizing:border-box;width:100%;max-width:100%;gap:var(--bx-tabs-panel-gap, 1.5rem)}.bx-tab-header{--bx-glass-surface: var(--bx-bg-surface-alt);--bx-glass-edge: var(--bx-border-default);--bx-glass-shadow: none;--bx-glass-opacity: calc(.1 + .25 * var(--bx-glassiness, .5));--bx-glass-radius: .5rem;display:flex;align-self:flex-start;flex:none;box-sizing:border-box;width:fit-content;max-width:100%;padding:.25rem;border:1px solid var(--bx-border-default);border-radius:.5rem}.bx-tab-list{display:flex;flex:1 1 auto;gap:.25rem;min-width:0;padding:1px;overflow:auto hidden;overscroll-behavior-x:contain;scrollbar-width:thin}.bx-tab-trigger{--bx-glass-surface: var(--bx-bg-surface);--bx-glass-text: var(--bx-tab-text, var(--bx-text-secondary));--bx-glass-edge: transparent;--bx-glass-radius: .25rem;--bx-glass-opacity: 0;--bx-glass-decoration-opacity: 0;--bx-glass-rim-visibility: 0;--bx-glass-shadow: none;display:inline-flex;align-items:center;gap:.5rem;flex:none;padding:.5rem .75rem;border:1px solid transparent;border-radius:.25rem;font:inherit;font-size:.875rem;white-space:nowrap;cursor:pointer}.bx-tab-trigger:hover:not(:disabled,.is-selected){--bx-glass-text: var(--bx-tab-text, var(--bx-text-primary));--bx-glass-opacity: .15}.bx-tab-trigger.is-selected{--bx-glass-surface: color-mix( in srgb, var(--bx-tab-highlight, var(--bx-primary)) 35%, var(--bx-bg-surface) );--bx-glass-text: var(--bx-tab-selected-text, var(--bx-text-brand));--bx-glass-edge: color-mix( in srgb, var(--bx-tab-highlight, var(--bx-primary)) 35%, transparent );--bx-glass-opacity: .45;--bx-glass-decoration-opacity: .5;--bx-glass-rim-visibility: .65;--bx-glass-shadow: 0 2px 4px 0 rgba(0, 0, 0, .1), 0 1px 2px -1px rgba(0, 0, 0, .1)}.bx-tab-trigger:disabled{opacity:.4;cursor:not-allowed}.bx-tab-trigger:focus-visible{outline:2px solid var(--bx-tab-highlight, var(--bx-border-brand));outline-offset:-2px}.bx-tab-panels{flex:1 1 auto;min-width:0;min-height:0;max-height:var(--bx-tabs-max-panel-height, none);overflow:var(--bx-tabs-panel-overflow, visible)}.bx-tab-panel{min-width:0}.bx-tab-panel:focus-visible{outline:2px solid var(--bx-border-brand);outline-offset:-2px}:host(.bx-tabs-animated) .bx-tab-trigger{transition:background-color .1s ease-in-out,color .1s ease-in-out,box-shadow .1s ease-in-out}:host(.bx-tabs-underline){gap:var(--bx-tabs-panel-gap, 0)}:host(.bx-tabs-underline) .bx-tab-header{align-self:stretch;width:auto;padding:0;border:0;border-bottom:1px solid var(--bx-border-default);border-radius:0}:host(.bx-tabs-underline) .bx-tab-list{gap:0}:host(.bx-tabs-underline) .bx-tab-trigger{padding:.75rem 1rem;border-inline-end:1px solid var(--bx-border-default);border-radius:0;font-size:.8rem}:host(.bx-tabs-underline) .bx-tab-trigger.is-selected{--bx-glass-shadow: inset 0 -2px 0 var(--bx-tab-highlight, var(--bx-border-brand))}@media(forced-colors:active){.bx-tab-trigger.is-selected{outline:2px solid Highlight;outline-offset:-2px}}\n"],
1685
+ dependencies: [
1686
+ {
1687
+ kind: "directive",
1688
+ type: NgTemplateOutlet,
1689
+ selector: "[ngTemplateOutlet]",
1690
+ inputs: [
1691
+ "ngTemplateOutletContext",
1692
+ "ngTemplateOutlet",
1693
+ "ngTemplateOutletInjector"
1694
+ ]
1695
+ },
1696
+ {
1697
+ kind: "directive",
1698
+ type: BxSurfaceDirective,
1699
+ selector: "[bxSurface]",
1700
+ inputs: [
1701
+ "bxSurfaceInteractive",
1702
+ "bxSurfaceGlassiness",
1703
+ "bxSurfaceEmission",
1704
+ "bxSurfaceFocusEmission",
1705
+ "bxReducedTransparency"
1706
+ ],
1707
+ exportAs: ["bxSurface"]
1708
+ },
1709
+ {
1710
+ kind: "component",
1711
+ type: Icon,
1712
+ selector: "bx-icon",
1713
+ inputs: [
1714
+ "name",
1715
+ "size",
1716
+ "color",
1717
+ "bgColor",
1718
+ "strokeWidth",
1719
+ "decorative",
1720
+ "ariaLabel"
1721
+ ]
1722
+ }
1723
+ ],
1724
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
1133
1725
  });
1134
1726
  };
1135
1727
  i0.ɵɵngDeclareClassMetadata({
1136
1728
  minVersion: "12.0.0",
1137
1729
  version: "22.2.3",
1138
1730
  ngImport: i0,
1139
- type: ContextMenuDirective,
1731
+ type: Tabs,
1140
1732
  decorators: [{
1141
- type: Directive,
1142
- args: [{ selector: "[bxContextMenu]" }]
1733
+ type: Component,
1734
+ args: [{
1735
+ selector: "bx-tabs",
1736
+ standalone: true,
1737
+ imports: [
1738
+ NgTemplateOutlet,
1739
+ BxSurfaceDirective,
1740
+ Icon
1741
+ ],
1742
+ changeDetection: ChangeDetectionStrategy.OnPush,
1743
+ host: {
1744
+ "[class.bx-tabs-underline]": "variant() === \"underline\"",
1745
+ "[class.bx-tabs-animated]": "hasRendered() && !a11y.isReducedMotion()"
1746
+ },
1747
+ template: "<ng-content select=\"bx-tab\"></ng-content>\n\n<div bxSurface data-bx-surface=\"glass\" class=\"bx-tab-header\" role=\"tablist\" [attr.aria-label]=\"resolvedLabel()\" aria-orientation=\"horizontal\">\n<div class=\"bx-tab-list\">\n @for (tab of tabs(); track tab) {\n <button #trigger bxSurface data-bx-surface=\"glass\" class=\"bx-tab-trigger\" type=\"button\" role=\"tab\"\n [bxSurfaceEmission]=\"tab.resolvedEmission()\"\n [style.--bx-tab-highlight]=\"tab.resolvedHighlight()\" [style.--bx-tab-text]=\"tab.resolvedTextColor()\"\n [style.--bx-tab-selected-text]=\"tab.resolvedSelectedText()\"\n [id]=\"tab.triggerId\" [attr.aria-controls]=\"tab.panelId\" [attr.aria-selected]=\"tab === activeTab()\"\n [attr.tabindex]=\"tab === activeTab() ? 0 : -1\" [disabled]=\"tab.disabled()\"\n [class.is-selected]=\"tab === activeTab()\" (click)=\"select(tab.value())\" (keydown)=\"onTabKey($event, tab)\">\n @if (tab.icon()) { <bx-icon [name]=\"tab.icon()!\" size=\"16\" /> }\n <span>{{ tab.resolvedLabel() }}</span>\n @if (tab.endIcon()) { <bx-icon [name]=\"tab.endIcon()!\" size=\"16\" /> }\n </button>\n }\n</div>\n</div>\n\n<div class=\"bx-tab-panels\">\n @for (tab of tabs(); track tab) {\n <div class=\"bx-tab-panel\" role=\"tabpanel\" tabindex=\"0\" [id]=\"tab.panelId\"\n [style.color]=\"tab.resolvedContentColor()\"\n [attr.aria-labelledby]=\"tab.triggerId\" [hidden]=\"tab !== activeTab()\">\n @if (tab === activeTab()) {\n <ng-container [ngTemplateOutlet]=\"tab.template()\"></ng-container>\n }\n </div>\n }\n</div>\n",
1748
+ styles: [":host{display:flex;flex-direction:column;min-width:0;min-height:0;box-sizing:border-box;width:100%;max-width:100%;gap:var(--bx-tabs-panel-gap, 1.5rem)}.bx-tab-header{--bx-glass-surface: var(--bx-bg-surface-alt);--bx-glass-edge: var(--bx-border-default);--bx-glass-shadow: none;--bx-glass-opacity: calc(.1 + .25 * var(--bx-glassiness, .5));--bx-glass-radius: .5rem;display:flex;align-self:flex-start;flex:none;box-sizing:border-box;width:fit-content;max-width:100%;padding:.25rem;border:1px solid var(--bx-border-default);border-radius:.5rem}.bx-tab-list{display:flex;flex:1 1 auto;gap:.25rem;min-width:0;padding:1px;overflow:auto hidden;overscroll-behavior-x:contain;scrollbar-width:thin}.bx-tab-trigger{--bx-glass-surface: var(--bx-bg-surface);--bx-glass-text: var(--bx-tab-text, var(--bx-text-secondary));--bx-glass-edge: transparent;--bx-glass-radius: .25rem;--bx-glass-opacity: 0;--bx-glass-decoration-opacity: 0;--bx-glass-rim-visibility: 0;--bx-glass-shadow: none;display:inline-flex;align-items:center;gap:.5rem;flex:none;padding:.5rem .75rem;border:1px solid transparent;border-radius:.25rem;font:inherit;font-size:.875rem;white-space:nowrap;cursor:pointer}.bx-tab-trigger:hover:not(:disabled,.is-selected){--bx-glass-text: var(--bx-tab-text, var(--bx-text-primary));--bx-glass-opacity: .15}.bx-tab-trigger.is-selected{--bx-glass-surface: color-mix( in srgb, var(--bx-tab-highlight, var(--bx-primary)) 35%, var(--bx-bg-surface) );--bx-glass-text: var(--bx-tab-selected-text, var(--bx-text-brand));--bx-glass-edge: color-mix( in srgb, var(--bx-tab-highlight, var(--bx-primary)) 35%, transparent );--bx-glass-opacity: .45;--bx-glass-decoration-opacity: .5;--bx-glass-rim-visibility: .65;--bx-glass-shadow: 0 2px 4px 0 rgba(0, 0, 0, .1), 0 1px 2px -1px rgba(0, 0, 0, .1)}.bx-tab-trigger:disabled{opacity:.4;cursor:not-allowed}.bx-tab-trigger:focus-visible{outline:2px solid var(--bx-tab-highlight, var(--bx-border-brand));outline-offset:-2px}.bx-tab-panels{flex:1 1 auto;min-width:0;min-height:0;max-height:var(--bx-tabs-max-panel-height, none);overflow:var(--bx-tabs-panel-overflow, visible)}.bx-tab-panel{min-width:0}.bx-tab-panel:focus-visible{outline:2px solid var(--bx-border-brand);outline-offset:-2px}:host(.bx-tabs-animated) .bx-tab-trigger{transition:background-color .1s ease-in-out,color .1s ease-in-out,box-shadow .1s ease-in-out}:host(.bx-tabs-underline){gap:var(--bx-tabs-panel-gap, 0)}:host(.bx-tabs-underline) .bx-tab-header{align-self:stretch;width:auto;padding:0;border:0;border-bottom:1px solid var(--bx-border-default);border-radius:0}:host(.bx-tabs-underline) .bx-tab-list{gap:0}:host(.bx-tabs-underline) .bx-tab-trigger{padding:.75rem 1rem;border-inline-end:1px solid var(--bx-border-default);border-radius:0;font-size:.8rem}:host(.bx-tabs-underline) .bx-tab-trigger.is-selected{--bx-glass-shadow: inset 0 -2px 0 var(--bx-tab-highlight, var(--bx-border-brand))}@media(forced-colors:active){.bx-tab-trigger.is-selected{outline:2px solid Highlight;outline-offset:-2px}}\n"]
1749
+ }]
1143
1750
  }],
1144
1751
  ctorParameters: () => [],
1145
1752
  propDecorators: {
1146
- bxContextMenu: [{
1753
+ triggers: [{
1754
+ type: i0.ViewChildren,
1755
+ args: ["trigger", { isSignal: true }]
1756
+ }],
1757
+ tabs: [{
1758
+ type: i0.ContentChildren,
1759
+ args: [i0.forwardRef(() => Tab), { isSignal: true }]
1760
+ }],
1761
+ variant: [{
1147
1762
  type: i0.Input,
1148
1763
  args: [{
1149
1764
  isSignal: true,
1150
- alias: "bxContextMenu",
1151
- required: true
1765
+ alias: "variant",
1766
+ required: false
1152
1767
  }]
1153
1768
  }],
1154
- bxContextMenuLongPress: [{
1769
+ ariaLabel: [{
1155
1770
  type: i0.Input,
1156
1771
  args: [{
1157
1772
  isSignal: true,
1158
- alias: "bxContextMenuLongPress",
1773
+ alias: "ariaLabel",
1159
1774
  required: false
1160
1775
  }]
1161
1776
  }],
1162
- open: [{
1163
- type: HostListener,
1164
- args: ["contextmenu", ["$event"]]
1165
- }],
1166
- onKey: [{
1167
- type: HostListener,
1168
- args: ["keydown", ["$event"]]
1169
- }],
1170
- onDocumentClick: [{
1171
- type: HostListener,
1172
- args: ["document:click", ["$event"]]
1777
+ selectedValue: [{
1778
+ type: i0.Input,
1779
+ args: [{
1780
+ isSignal: true,
1781
+ alias: "selectedValue",
1782
+ required: false
1783
+ }]
1784
+ }, {
1785
+ type: i0.Output,
1786
+ args: ["selectedValueChange"]
1173
1787
  }]
1174
1788
  }
1175
1789
  });
1176
- var TooltipDirective = class TooltipDirective {
1790
+ var DropdownDirective = class DropdownDirective {
1177
1791
  elementRef = inject(ElementRef);
1178
1792
  overlay = inject(Overlay);
1179
1793
  positionBuilder = inject(BxOverlayPositionService);
1794
+ overlayContext = inject(BX_OVERLAY_CONTEXT, { optional: true });
1180
1795
  a11y = inject(BxA11yService);
1181
1796
  zone = inject(NgZone);
1182
- focusMonitor = inject(FocusMonitor);
1183
- describer = inject(AriaDescriber);
1184
- i18n = inject(BX_I18N, { optional: true });
1185
- contextMenu = inject(ContextMenuDirective, { optional: true });
1186
- id = `bx-tooltip-${uuidv4()}`;
1187
- bxTooltip = input.required(...ngDevMode ? [{ debugName: "bxTooltip" }] : /* istanbul ignore next */ []);
1797
+ vcr = inject(ViewContainerRef);
1798
+ isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
1799
+ _isOpen = signal(false, ...ngDevMode ? [{ debugName: "_isOpen" }] : /* istanbul ignore next */ []);
1800
+ overlayId = signal(null, ...ngDevMode ? [{ debugName: "overlayId" }] : /* istanbul ignore next */ []);
1801
+ isOpen = this._isOpen.asReadonly();
1802
+ _state = signal("closed", ...ngDevMode ? [{ debugName: "_state" }] : /* istanbul ignore next */ []);
1803
+ state = this._state.asReadonly();
1804
+ bxDropdown = input.required(...ngDevMode ? [{ debugName: "bxDropdown" }] : /* istanbul ignore next */ []);
1188
1805
  placement = input("bottom", ...ngDevMode ? [{ debugName: "placement" }] : /* istanbul ignore next */ []);
1189
- bxTooltipTouch = input("none", ...ngDevMode ? [{ debugName: "bxTooltipTouch" }] : /* istanbul ignore next */ []);
1806
+ bxTransition = input("fade", ...ngDevMode ? [{ debugName: "bxTransition" }] : /* istanbul ignore next */ []);
1190
1807
  overlayRef = null;
1191
- transition;
1808
+ transition = null;
1809
+ subscriptions = new Subscription();
1810
+ revision = 0;
1192
1811
  disconnectTheme;
1193
1812
  disconnectLighting;
1194
- positionSubscription;
1195
- keyboardSubscription;
1196
- revision = 0;
1197
- hovered = false;
1198
- focused = false;
1199
- lastPointerType = "";
1200
- touchEvents;
1201
- holdTimer;
1202
- touchHideTimer;
1203
- touchVisible = false;
1204
- closeTouchTap = false;
1205
1813
  constructor() {
1206
- const source = this.elementRef.nativeElement;
1207
- const focus = source.ownerDocument.defaultView ? this.focusMonitor.monitor(source, true).subscribe((origin) => this.zone.run(() => {
1208
- this.focused = origin === "keyboard";
1209
- if (this.focused) {
1210
- this.clearTouchInteraction();
1211
- this.show();
1212
- } else if (!this.hovered && !this.touchEvents) this.hide();
1213
- })) : void 0;
1214
- effect((onCleanup) => {
1215
- this.i18n?.version?.();
1216
- const text = this.bxTooltip();
1217
- const description = isTextWithKey(text) ? this.i18n?.translate(text.key) ?? text.key : text;
1218
- if (!description) return;
1219
- this.describer.describe(source, description, "tooltip");
1220
- onCleanup(() => this.describer.removeDescription(source, description, "tooltip"));
1221
- });
1222
1814
  inject(DestroyRef).onDestroy(() => {
1223
1815
  ++this.revision;
1224
- focus?.unsubscribe();
1225
- if (focus) this.focusMonitor.stopMonitoring(source);
1226
- this.clearTouchInteraction();
1227
1816
  this.dispose();
1228
1817
  });
1229
- }
1230
- show() {
1231
- if (!this.bxTooltip()) return;
1232
- const revision = ++this.revision;
1233
- if (!this.overlayRef) {
1234
- const strategy = this.positionBuilder.getElementStrategy(this.elementRef.nativeElement, this.placement()).withFlexibleDimensions(false);
1235
- this.overlayRef = this.overlay.create({
1236
- positionStrategy: strategy,
1237
- scrollStrategy: this.overlay.scrollStrategies.reposition(),
1238
- hasBackdrop: false,
1239
- panelClass: "bx-tooltip-pane"
1240
- });
1241
- const pane = this.overlayRef.overlayElement;
1242
- pane.id = this.id;
1243
- pane.setAttribute("role", "tooltip");
1244
- pane.setAttribute("aria-hidden", "true");
1245
- this.disconnectTheme = this.zone.runOutsideAngular(() => inheritOverlayTheme(this.elementRef.nativeElement, pane));
1246
- this.disconnectLighting = inheritGlassLighting(pane, this.elementRef.nativeElement);
1247
- const component = this.overlayRef.attach(new ComponentPortal(Tooltip));
1248
- pane.style.pointerEvents = "none";
1249
- this.keyboardSubscription = this.overlayRef.keydownEvents().subscribe((event) => this.onEscape(event));
1250
- component.setInput("text", this.bxTooltip());
1251
- component.changeDetectorRef.detectChanges();
1252
- const positionArrow = () => {
1253
- const trigger = this.elementRef.nativeElement.getBoundingClientRect();
1254
- const bounds = pane.getBoundingClientRect();
1255
- pane.style.setProperty("--bx-tooltip-arrow-x", `${trigger.left + trigger.width / 2 - bounds.left}px`);
1256
- pane.style.setProperty("--bx-tooltip-arrow-y", `${trigger.top + trigger.height / 2 - bounds.top}px`);
1257
- this.transition?.refresh();
1258
- };
1259
- this.positionSubscription = strategy.positionChanges.subscribe(positionArrow);
1260
- this.overlayRef.updatePosition();
1261
- positionArrow();
1262
- if (!this.a11y.isReducedMotion()) this.transition = this.zone.runOutsideAngular(() => createGlassTransition(this.elementRef.nativeElement, pane));
1263
- }
1264
- Promise.resolve(this.zone.runOutsideAngular(() => this.transition?.enter())).catch(() => {
1265
- if (revision === this.revision) {
1266
- this.transition?.destroy();
1267
- this.transition = void 0;
1818
+ effect(() => {
1819
+ if (this.a11y.isReducedMotion() && this.transition) {
1820
+ ++this.revision;
1821
+ this.transition.destroy();
1822
+ this.transition = null;
1823
+ if (this.isOpen()) this._state.set("open");
1824
+ else this.dispose();
1268
1825
  }
1269
1826
  });
1270
1827
  }
1271
- hide() {
1272
- this.clearTouchInteraction();
1273
- const revision = ++this.revision;
1274
- if (!this.overlayRef) return;
1275
- const transition = this.transition;
1276
- if (transition && !this.a11y.isReducedMotion()) this.zone.runOutsideAngular(() => transition.exit()).then(() => {
1277
- if (revision === this.revision) this.dispose();
1278
- }).catch(() => {
1279
- if (revision === this.revision) this.dispose();
1280
- });
1281
- else this.dispose();
1282
- }
1283
- onEnter(event) {
1284
- if (event.pointerType !== "mouse") return;
1285
- this.clearTouchInteraction();
1286
- this.hovered = true;
1287
- this.show();
1288
- }
1289
- onLeave(event) {
1290
- if (event.pointerType !== "mouse") return;
1291
- this.hovered = false;
1292
- if (!this.focused) this.hide();
1293
- }
1294
- onPointerDown(event) {
1295
- this.lastPointerType = event.pointerType;
1296
- if (event.pointerType !== "touch") return;
1297
- this.closeTouchTap = this.touchVisible && this.bxTooltipTouch() === "tap";
1298
- this.hovered = false;
1299
- this.focused = false;
1300
- this.hide();
1301
- if (this.bxTooltipTouch() !== "longpress" || !event.isPrimary || event.button !== 0 || !this.canUseTouch(event)) return;
1302
- this.zone.runOutsideAngular(() => this.startTouchInteraction(event));
1303
- }
1304
- onClick(event) {
1305
- if (event.detail === 0 || this.lastPointerType !== "touch" || this.bxTooltipTouch() !== "tap" || !this.canUseTouch(event)) return;
1306
- if (this.closeTouchTap) {
1307
- this.closeTouchTap = false;
1308
- return;
1309
- }
1310
- this.zone.runOutsideAngular(() => this.startTouchInteraction());
1311
- }
1312
- onEscape(event) {
1313
- if (event.key === "Escape" && this.overlayRef) {
1314
- event.stopPropagation();
1315
- this.hovered = false;
1316
- this.focused = false;
1317
- this.hide();
1318
- }
1828
+ toggle(event) {
1829
+ if (this.isDisabled()) return;
1830
+ event?.stopPropagation();
1831
+ if (this.isOpen()) this.close();
1832
+ else this.open();
1319
1833
  }
1320
- canUseTouch(event) {
1321
- if (this.contextMenu && this.bxTooltipTouch() === "longpress") return false;
1322
- if (this.elementRef.nativeElement.closest(":disabled, [aria-disabled=\"true\"], [inert]")) return false;
1323
- return !event.composedPath().some((node) => node instanceof HTMLElement && (node.isContentEditable || node.matches("input, textarea, select")));
1834
+ onTriggerKeydown(event) {
1835
+ if (this.bxTransition() === "none" || this.isDisabled() || this.isEditing(event.target)) return;
1836
+ if (event.key !== "ArrowDown" && event.key !== "ArrowUp") return;
1837
+ event.preventDefault();
1838
+ event.stopPropagation();
1839
+ this.open();
1840
+ const items = this.menuItems();
1841
+ (event.key === "ArrowUp" ? items[items.length - 1] : items[0])?.focus({ preventScroll: true });
1324
1842
  }
1325
- hasTextSelection() {
1326
- const source = this.elementRef.nativeElement;
1327
- const selection = source.ownerDocument.getSelection();
1328
- return !!selection && !selection.isCollapsed && (source.contains(selection.anchorNode) || source.contains(selection.focusNode));
1843
+ open() {
1844
+ if (!this.isBrowser || this.isOpen() || this.isDisabled()) return;
1845
+ const revision = ++this.revision;
1846
+ this._isOpen.set(true);
1847
+ this._state.set("opening");
1848
+ if (!this.overlayRef) this.attachOverlay();
1849
+ const overlay = this.overlayRef;
1850
+ if (!overlay) return;
1851
+ overlay.overlayElement.inert = false;
1852
+ overlay.overlayElement.style.removeProperty("pointer-events");
1853
+ if (this.bxTransition() !== "none" && !this.a11y.isReducedMotion()) {
1854
+ const transition = this.transition ??= this.zone.runOutsideAngular(() => createGlassTransition(this.elementRef.nativeElement, overlay.overlayElement));
1855
+ this.zone.runOutsideAngular(() => transition.enter()).then(() => {
1856
+ if (revision === this.revision && this.isOpen()) this.zone.run(() => this._state.set("open"));
1857
+ }).catch(() => {
1858
+ if (revision === this.revision && this.isOpen()) {
1859
+ this.transition?.destroy();
1860
+ this.transition = null;
1861
+ this._state.set("open");
1862
+ }
1863
+ });
1864
+ } else this._state.set("open");
1329
1865
  }
1330
- startTouchInteraction(press) {
1331
- const source = this.elementRef.nativeElement;
1332
- const doc = source.ownerDocument;
1333
- const win = doc.defaultView;
1334
- if (!win || this.hasTextSelection()) return;
1335
- this.clearTouchInteraction();
1336
- const events = new AbortController();
1337
- this.touchEvents = events;
1338
- const options = {
1339
- capture: true,
1340
- passive: true,
1341
- signal: events.signal
1342
- };
1343
- const dismiss = () => this.zone.run(() => this.hide());
1344
- let suppressReleaseClick = false;
1345
- doc.addEventListener("pointerdown", (event) => {
1346
- if (!press && event.target instanceof Node && source.contains(event.target)) return;
1347
- dismiss();
1348
- }, options);
1349
- doc.addEventListener("scroll", dismiss, options);
1350
- doc.addEventListener("visibilitychange", () => {
1351
- if (doc.hidden) dismiss();
1352
- }, options);
1353
- win.addEventListener("blur", dismiss, { signal: events.signal });
1354
- if (!press) {
1355
- this.touchVisible = true;
1356
- this.zone.run(() => this.show());
1357
- return;
1358
- }
1359
- doc.addEventListener("pointermove", (event) => {
1360
- if (event.pointerId === press.pointerId && !this.touchVisible && Math.hypot(event.clientX - press.clientX, event.clientY - press.clientY) > 10) dismiss();
1361
- }, options);
1362
- doc.addEventListener("pointerup", (event) => {
1363
- if (event.pointerId !== press.pointerId) return;
1364
- if (!this.touchVisible) dismiss();
1365
- else this.touchHideTimer = win.setTimeout(dismiss, 1500);
1366
- }, options);
1367
- doc.addEventListener("pointercancel", (event) => {
1368
- if (event.pointerId === press.pointerId) dismiss();
1369
- }, options);
1370
- doc.addEventListener("click", (event) => {
1371
- if (!suppressReleaseClick || event.detail === 0) return;
1372
- event.preventDefault();
1373
- event.stopImmediatePropagation();
1374
- suppressReleaseClick = false;
1375
- }, {
1376
- ...options,
1377
- passive: false
1866
+ close(restoreFocus = false) {
1867
+ if (!this.overlayRef || !this.isOpen()) return;
1868
+ const revision = ++this.revision;
1869
+ const overlay = this.overlayRef;
1870
+ this._isOpen.set(false);
1871
+ this._state.set("closing");
1872
+ const source = this.elementRef.nativeElement;
1873
+ if (restoreFocus || overlay.overlayElement.contains(source.ownerDocument.activeElement)) source.focus({ preventScroll: true });
1874
+ overlay.overlayElement.inert = true;
1875
+ overlay.overlayElement.style.pointerEvents = "none";
1876
+ const transition = this.transition;
1877
+ if (transition && !this.a11y.isReducedMotion()) this.zone.runOutsideAngular(() => transition.exit()).then(() => {
1878
+ if (revision === this.revision && !this.isOpen()) this.zone.run(() => this.dispose());
1879
+ }).catch(() => {
1880
+ if (revision === this.revision && !this.isOpen()) this.dispose();
1378
1881
  });
1379
- doc.addEventListener("contextmenu", (event) => {
1380
- if (event.target instanceof Node && source.contains(event.target) && !this.hasTextSelection()) event.preventDefault();
1381
- }, {
1382
- ...options,
1383
- passive: false
1882
+ else this.dispose();
1883
+ }
1884
+ onDocumentClick(event) {
1885
+ if (!this.overlayRef?.hasAttached() || !this.isOpen()) return;
1886
+ const target = event.target;
1887
+ if (!target || this.elementRef.nativeElement.contains(target)) return;
1888
+ if (!this.overlayRef.overlayElement.contains(target) || this.bxTransition() === "none" || target instanceof Element && target.closest("button, a, [role=\"menuitem\"]")) this.close();
1889
+ }
1890
+ attachOverlay() {
1891
+ const positionStrategy = this.positionBuilder.getElementStrategy(this.elementRef.nativeElement, this.placement(), 4);
1892
+ const overlay = this.overlay.create({
1893
+ positionStrategy,
1894
+ scrollStrategy: this.overlay.scrollStrategies.noop(),
1895
+ usePopover: !!this.overlayContext?.useTopLayer || !!this.elementRef.nativeElement.closest("dialog, [role=\"dialog\"], [role=\"alertdialog\"], bx-modal, bx-modal-core, [popover]"),
1896
+ hasBackdrop: this.bxTransition() === "none",
1897
+ backdropClass: "cdk-overlay-transparent-backdrop"
1384
1898
  });
1385
- this.holdTimer = win.setTimeout(() => {
1386
- if (this.bxTooltipTouch() !== "longpress" || !source.isConnected || source.closest(":disabled, [aria-disabled=\"true\"], [inert]") || this.hasTextSelection()) {
1387
- dismiss();
1388
- return;
1389
- }
1390
- this.touchVisible = true;
1391
- suppressReleaseClick = true;
1392
- this.zone.run(() => this.show());
1393
- }, 500);
1899
+ this.overlayRef = overlay;
1900
+ this.overlayId.set(overlay.overlayElement.id || null);
1901
+ this.disconnectTheme = this.zone.runOutsideAngular(() => inheritOverlayTheme(this.elementRef.nativeElement, overlay.overlayElement));
1902
+ this.disconnectLighting = inheritGlassLighting(overlay.overlayElement, this.elementRef.nativeElement);
1903
+ this.subscriptions = new Subscription();
1904
+ this.subscriptions.add(this.zone.runOutsideAngular(() => trackOverlayOrigin(overlay, this.elementRef.nativeElement)));
1905
+ this.subscriptions.add(overlay.backdropClick().subscribe(() => this.close()));
1906
+ this.subscriptions.add(overlay.outsidePointerEvents().subscribe((event) => {
1907
+ if (!this.elementRef.nativeElement.contains(event.target)) this.close();
1908
+ }));
1909
+ this.subscriptions.add(overlay.keydownEvents().subscribe((event) => {
1910
+ if (event.key === "Escape" && this.isOpen()) {
1911
+ event.preventDefault();
1912
+ event.stopPropagation();
1913
+ this.close(true);
1914
+ } else if (!event.defaultPrevented && this.bxTransition() !== "none" && this.isOpen()) this.navigateMenu(event);
1915
+ }));
1916
+ this.subscriptions.add(positionStrategy.positionChanges.subscribe(() => {
1917
+ this.zone.runOutsideAngular(() => this.transition?.refresh());
1918
+ }));
1919
+ overlay.attach(new TemplatePortal(this.bxDropdown(), this.vcr)).detectChanges();
1920
+ overlay.updatePosition();
1394
1921
  }
1395
- clearTouchInteraction() {
1396
- this.touchEvents?.abort();
1397
- this.touchEvents = void 0;
1398
- const win = this.elementRef.nativeElement.ownerDocument.defaultView;
1399
- win?.clearTimeout(this.holdTimer);
1400
- win?.clearTimeout(this.touchHideTimer);
1401
- this.holdTimer = void 0;
1402
- this.touchHideTimer = void 0;
1403
- this.touchVisible = false;
1922
+ isDisabled() {
1923
+ const element = this.elementRef.nativeElement;
1924
+ return element.hasAttribute("disabled") || element.getAttribute("aria-disabled") === "true";
1925
+ }
1926
+ menuItems() {
1927
+ const pane = this.overlayRef?.overlayElement;
1928
+ if (!pane) return [];
1929
+ return Array.from(pane.querySelectorAll("button, a[href], [role=\"menuitem\"]")).filter((item) => {
1930
+ if (item.matches(":disabled, [disabled], [aria-disabled=\"true\"]") || item.closest("[aria-disabled=\"true\"]")) return false;
1931
+ if (item.closest("[hidden], [inert], [aria-hidden=\"true\"]")) return false;
1932
+ if (item.tabIndex < 0 && !item.hasAttribute("tabindex")) return false;
1933
+ const style = item.ownerDocument.defaultView?.getComputedStyle(item);
1934
+ return !!style && style.display !== "none" && style.visibility !== "hidden" && item.getClientRects().length > 0;
1935
+ });
1936
+ }
1937
+ navigateMenu(event) {
1938
+ if (this.isEditing(event.target) || !(event.target instanceof Node) || !this.overlayRef?.overlayElement.contains(event.target)) return;
1939
+ if (![
1940
+ "ArrowDown",
1941
+ "ArrowUp",
1942
+ "Home",
1943
+ "End"
1944
+ ].includes(event.key)) return;
1945
+ const items = this.menuItems();
1946
+ if (!items.length) return;
1947
+ const current = items.indexOf(this.elementRef.nativeElement.ownerDocument.activeElement);
1948
+ let index;
1949
+ if (event.key === "Home") index = 0;
1950
+ else if (event.key === "End") index = items.length - 1;
1951
+ else if (event.key === "ArrowDown") index = current < 0 ? 0 : (current + 1) % items.length;
1952
+ else index = current < 0 ? items.length - 1 : (current - 1 + items.length) % items.length;
1953
+ event.preventDefault();
1954
+ event.stopPropagation();
1955
+ items[index].focus({ preventScroll: true });
1956
+ }
1957
+ isEditing(target) {
1958
+ return target instanceof Element && !!target.closest("input, textarea, select, [contenteditable]:not([contenteditable=\"false\"]), [role=\"textbox\"]");
1404
1959
  }
1405
1960
  dispose() {
1406
- this.keyboardSubscription?.unsubscribe();
1407
- this.keyboardSubscription = void 0;
1408
- this.positionSubscription?.unsubscribe();
1409
- this.positionSubscription = void 0;
1410
1961
  this.disconnectTheme?.();
1411
1962
  this.disconnectTheme = void 0;
1412
1963
  this.transition?.destroy();
1413
- this.transition = void 0;
1964
+ this.transition = null;
1965
+ this.subscriptions.unsubscribe();
1414
1966
  this.overlayRef?.dispose();
1415
1967
  this.overlayRef = null;
1416
1968
  this.disconnectLighting?.();
1417
1969
  this.disconnectLighting = void 0;
1970
+ this.overlayId.set(null);
1971
+ this._isOpen.set(false);
1972
+ this._state.set("closed");
1973
+ }
1974
+ static ɵfac = i0.ɵɵngDeclareFactory({
1975
+ minVersion: "12.0.0",
1976
+ version: "22.2.3",
1977
+ ngImport: i0,
1978
+ type: DropdownDirective,
1979
+ deps: [],
1980
+ target: i0.ɵɵFactoryTarget.Directive
1981
+ });
1982
+ static ɵdir = i0.ɵɵngDeclareDirective({
1983
+ minVersion: "17.1.0",
1984
+ version: "22.2.3",
1985
+ type: DropdownDirective,
1986
+ isStandalone: true,
1987
+ selector: "[bxDropdown]",
1988
+ inputs: {
1989
+ bxDropdown: {
1990
+ classPropertyName: "bxDropdown",
1991
+ publicName: "bxDropdown",
1992
+ isSignal: true,
1993
+ isRequired: true,
1994
+ transformFunction: null
1995
+ },
1996
+ placement: {
1997
+ classPropertyName: "placement",
1998
+ publicName: "placement",
1999
+ isSignal: true,
2000
+ isRequired: false,
2001
+ transformFunction: null
2002
+ },
2003
+ bxTransition: {
2004
+ classPropertyName: "bxTransition",
2005
+ publicName: "bxTransition",
2006
+ isSignal: true,
2007
+ isRequired: false,
2008
+ transformFunction: null
2009
+ }
2010
+ },
2011
+ host: {
2012
+ listeners: {
2013
+ "click": "toggle($event)",
2014
+ "keydown": "onTriggerKeydown($event)",
2015
+ "document:click": "onDocumentClick($event)"
2016
+ },
2017
+ properties: {
2018
+ "attr.aria-expanded": "isOpen()",
2019
+ "attr.aria-haspopup": "\"menu\"",
2020
+ "attr.aria-controls": "overlayId()"
2021
+ }
2022
+ },
2023
+ exportAs: ["bxDropdown"],
2024
+ ngImport: i0
2025
+ });
2026
+ };
2027
+ i0.ɵɵngDeclareClassMetadata({
2028
+ minVersion: "12.0.0",
2029
+ version: "22.2.3",
2030
+ ngImport: i0,
2031
+ type: DropdownDirective,
2032
+ decorators: [{
2033
+ type: Directive,
2034
+ args: [{
2035
+ selector: "[bxDropdown]",
2036
+ exportAs: "bxDropdown",
2037
+ standalone: true,
2038
+ host: {
2039
+ "[attr.aria-expanded]": "isOpen()",
2040
+ "[attr.aria-haspopup]": "\"menu\"",
2041
+ "[attr.aria-controls]": "overlayId()"
2042
+ }
2043
+ }]
2044
+ }],
2045
+ ctorParameters: () => [],
2046
+ propDecorators: {
2047
+ bxDropdown: [{
2048
+ type: i0.Input,
2049
+ args: [{
2050
+ isSignal: true,
2051
+ alias: "bxDropdown",
2052
+ required: true
2053
+ }]
2054
+ }],
2055
+ placement: [{
2056
+ type: i0.Input,
2057
+ args: [{
2058
+ isSignal: true,
2059
+ alias: "placement",
2060
+ required: false
2061
+ }]
2062
+ }],
2063
+ bxTransition: [{
2064
+ type: i0.Input,
2065
+ args: [{
2066
+ isSignal: true,
2067
+ alias: "bxTransition",
2068
+ required: false
2069
+ }]
2070
+ }],
2071
+ toggle: [{
2072
+ type: HostListener,
2073
+ args: ["click", ["$event"]]
2074
+ }],
2075
+ onTriggerKeydown: [{
2076
+ type: HostListener,
2077
+ args: ["keydown", ["$event"]]
2078
+ }],
2079
+ onDocumentClick: [{
2080
+ type: HostListener,
2081
+ args: ["document:click", ["$event"]]
2082
+ }]
2083
+ }
2084
+ });
2085
+ var BxOverlayContextDirective = class BxOverlayContextDirective {
2086
+ bxOverlayContext = input({}, ...ngDevMode ? [{ debugName: "bxOverlayContext" }] : /* istanbul ignore next */ []);
2087
+ get useTopLayer() {
2088
+ return this.bxOverlayContext().useTopLayer;
1418
2089
  }
1419
2090
  static ɵfac = i0.ɵɵngDeclareFactory({
1420
2091
  minVersion: "12.0.0",
1421
2092
  version: "22.2.3",
1422
2093
  ngImport: i0,
1423
- type: TooltipDirective,
2094
+ type: BxOverlayContextDirective,
2095
+ deps: [],
2096
+ target: i0.ɵɵFactoryTarget.Directive
2097
+ });
2098
+ static ɵdir = i0.ɵɵngDeclareDirective({
2099
+ minVersion: "17.1.0",
2100
+ version: "22.2.3",
2101
+ type: BxOverlayContextDirective,
2102
+ isStandalone: true,
2103
+ selector: "[bxOverlayContext]",
2104
+ inputs: { bxOverlayContext: {
2105
+ classPropertyName: "bxOverlayContext",
2106
+ publicName: "bxOverlayContext",
2107
+ isSignal: true,
2108
+ isRequired: false,
2109
+ transformFunction: null
2110
+ } },
2111
+ providers: [{
2112
+ provide: BX_OVERLAY_CONTEXT,
2113
+ useExisting: forwardRef(() => BxOverlayContextDirective)
2114
+ }],
2115
+ ngImport: i0
2116
+ });
2117
+ };
2118
+ i0.ɵɵngDeclareClassMetadata({
2119
+ minVersion: "12.0.0",
2120
+ version: "22.2.3",
2121
+ ngImport: i0,
2122
+ type: BxOverlayContextDirective,
2123
+ decorators: [{
2124
+ type: Directive,
2125
+ args: [{
2126
+ selector: "[bxOverlayContext]",
2127
+ standalone: true,
2128
+ providers: [{
2129
+ provide: BX_OVERLAY_CONTEXT,
2130
+ useExisting: forwardRef(() => BxOverlayContextDirective)
2131
+ }]
2132
+ }]
2133
+ }],
2134
+ propDecorators: { bxOverlayContext: [{
2135
+ type: i0.Input,
2136
+ args: [{
2137
+ isSignal: true,
2138
+ alias: "bxOverlayContext",
2139
+ required: false
2140
+ }]
2141
+ }] }
2142
+ });
2143
+ var LoadingSpinner = class LoadingSpinner {
2144
+ i18n = inject(BX_I18N, { optional: true });
2145
+ a11y = inject(BxA11yService);
2146
+ resolvedLabel = computed(() => resolveText(this.label(), this.i18n), ...ngDevMode ? [{ debugName: "resolvedLabel" }] : /* istanbul ignore next */ []);
2147
+ size = input(20, ...ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []);
2148
+ decorative = input(false, ...ngDevMode ? [{ debugName: "decorative" }] : /* istanbul ignore next */ []);
2149
+ label = input("Loading", ...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
2150
+ static ɵfac = i0.ɵɵngDeclareFactory({
2151
+ minVersion: "12.0.0",
2152
+ version: "22.2.3",
2153
+ ngImport: i0,
2154
+ type: LoadingSpinner,
1424
2155
  deps: [],
1425
- target: i0.ɵɵFactoryTarget.Directive
2156
+ target: i0.ɵɵFactoryTarget.Component
1426
2157
  });
1427
- static ɵdir = i0.ɵɵngDeclareDirective({
2158
+ static ɵcmp = i0.ɵɵngDeclareComponent({
1428
2159
  minVersion: "17.1.0",
1429
2160
  version: "22.2.3",
1430
- type: TooltipDirective,
2161
+ type: LoadingSpinner,
1431
2162
  isStandalone: true,
1432
- selector: "[bxTooltip]",
2163
+ selector: "bx-loading-spinner",
1433
2164
  inputs: {
1434
- bxTooltip: {
1435
- classPropertyName: "bxTooltip",
1436
- publicName: "bxTooltip",
2165
+ size: {
2166
+ classPropertyName: "size",
2167
+ publicName: "size",
1437
2168
  isSignal: true,
1438
- isRequired: true,
2169
+ isRequired: false,
1439
2170
  transformFunction: null
1440
2171
  },
1441
- placement: {
1442
- classPropertyName: "placement",
1443
- publicName: "placement",
2172
+ decorative: {
2173
+ classPropertyName: "decorative",
2174
+ publicName: "decorative",
1444
2175
  isSignal: true,
1445
2176
  isRequired: false,
1446
2177
  transformFunction: null
1447
2178
  },
1448
- bxTooltipTouch: {
1449
- classPropertyName: "bxTooltipTouch",
1450
- publicName: "bxTooltipTouch",
2179
+ label: {
2180
+ classPropertyName: "label",
2181
+ publicName: "label",
1451
2182
  isSignal: true,
1452
2183
  isRequired: false,
1453
2184
  transformFunction: null
1454
2185
  }
1455
2186
  },
1456
- host: { listeners: {
1457
- "pointerenter": "onEnter($event)",
1458
- "pointerleave": "onLeave($event)",
1459
- "pointerdown": "onPointerDown($event)",
1460
- "click": "onClick($event)",
1461
- "document:keydown": "onEscape($event)"
2187
+ host: { properties: {
2188
+ "style.--bx-spinner-size": "size() + \"px\"",
2189
+ "attr.role": "decorative() ? null : \"status\"",
2190
+ "attr.aria-label": "decorative() ? null : resolvedLabel()",
2191
+ "attr.aria-hidden": "decorative() ? \"true\" : null",
2192
+ "class.is-reduced-motion": "a11y.isReducedMotion()"
1462
2193
  } },
1463
- ngImport: i0
2194
+ ngImport: i0,
2195
+ template: "<span class=\"bx-spinner-ring\"></span>\n",
2196
+ styles: [":host{display:inline-flex;flex:0 0 auto;inline-size:var(--bx-spinner-size, 20px);block-size:var(--bx-spinner-size, 20px);color:var(--bx-spinner-color, currentColor);vertical-align:middle}.bx-spinner-ring{box-sizing:border-box;inline-size:100%;block-size:100%;border:var(--bx-spinner-stroke, 2px) solid currentcolor;border-inline-end-color:transparent;border-radius:50%;animation:bx-spinner-turn .75s linear infinite}:host(.is-reduced-motion) .bx-spinner-ring{animation:none;border-style:dotted}@keyframes bx-spinner-turn{to{transform:rotate(360deg)}}\n"],
2197
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
1464
2198
  });
1465
2199
  };
1466
2200
  i0.ɵɵngDeclareClassMetadata({
1467
2201
  minVersion: "12.0.0",
1468
2202
  version: "22.2.3",
1469
2203
  ngImport: i0,
1470
- type: TooltipDirective,
2204
+ type: LoadingSpinner,
1471
2205
  decorators: [{
1472
- type: Directive,
1473
- args: [{ selector: "[bxTooltip]" }]
2206
+ type: Component,
2207
+ args: [{
2208
+ selector: "bx-loading-spinner",
2209
+ changeDetection: ChangeDetectionStrategy.OnPush,
2210
+ host: {
2211
+ "[style.--bx-spinner-size]": "size() + \"px\"",
2212
+ "[attr.role]": "decorative() ? null : \"status\"",
2213
+ "[attr.aria-label]": "decorative() ? null : resolvedLabel()",
2214
+ "[attr.aria-hidden]": "decorative() ? \"true\" : null",
2215
+ "[class.is-reduced-motion]": "a11y.isReducedMotion()"
2216
+ },
2217
+ template: "<span class=\"bx-spinner-ring\"></span>\n",
2218
+ styles: [":host{display:inline-flex;flex:0 0 auto;inline-size:var(--bx-spinner-size, 20px);block-size:var(--bx-spinner-size, 20px);color:var(--bx-spinner-color, currentColor);vertical-align:middle}.bx-spinner-ring{box-sizing:border-box;inline-size:100%;block-size:100%;border:var(--bx-spinner-stroke, 2px) solid currentcolor;border-inline-end-color:transparent;border-radius:50%;animation:bx-spinner-turn .75s linear infinite}:host(.is-reduced-motion) .bx-spinner-ring{animation:none;border-style:dotted}@keyframes bx-spinner-turn{to{transform:rotate(360deg)}}\n"]
2219
+ }]
1474
2220
  }],
1475
- ctorParameters: () => [],
1476
2221
  propDecorators: {
1477
- bxTooltip: [{
2222
+ size: [{
1478
2223
  type: i0.Input,
1479
2224
  args: [{
1480
2225
  isSignal: true,
1481
- alias: "bxTooltip",
1482
- required: true
2226
+ alias: "size",
2227
+ required: false
1483
2228
  }]
1484
2229
  }],
1485
- placement: [{
2230
+ decorative: [{
1486
2231
  type: i0.Input,
1487
2232
  args: [{
1488
2233
  isSignal: true,
1489
- alias: "placement",
2234
+ alias: "decorative",
1490
2235
  required: false
1491
2236
  }]
1492
2237
  }],
1493
- bxTooltipTouch: [{
2238
+ label: [{
1494
2239
  type: i0.Input,
1495
2240
  args: [{
1496
2241
  isSignal: true,
1497
- alias: "bxTooltipTouch",
2242
+ alias: "label",
1498
2243
  required: false
1499
2244
  }]
1500
- }],
1501
- onEnter: [{
1502
- type: HostListener,
1503
- args: ["pointerenter", ["$event"]]
1504
- }],
1505
- onLeave: [{
1506
- type: HostListener,
1507
- args: ["pointerleave", ["$event"]]
1508
- }],
1509
- onPointerDown: [{
1510
- type: HostListener,
1511
- args: ["pointerdown", ["$event"]]
1512
- }],
1513
- onClick: [{
1514
- type: HostListener,
1515
- args: ["click", ["$event"]]
1516
- }],
1517
- onEscape: [{
1518
- type: HostListener,
1519
- args: ["document:keydown", ["$event"]]
1520
2245
  }]
1521
2246
  }
1522
2247
  });
1523
- var DropdownDirective = class DropdownDirective {
1524
- elementRef = inject(ElementRef);
1525
- overlay = inject(Overlay);
1526
- positionBuilder = inject(BxOverlayPositionService);
1527
- overlayContext = inject(BX_OVERLAY_CONTEXT, { optional: true });
1528
- a11y = inject(BxA11yService);
1529
- zone = inject(NgZone);
1530
- vcr = inject(ViewContainerRef);
1531
- isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
1532
- _isOpen = signal(false, ...ngDevMode ? [{ debugName: "_isOpen" }] : /* istanbul ignore next */ []);
1533
- overlayId = signal(null, ...ngDevMode ? [{ debugName: "overlayId" }] : /* istanbul ignore next */ []);
1534
- isOpen = this._isOpen.asReadonly();
1535
- _state = signal("closed", ...ngDevMode ? [{ debugName: "_state" }] : /* istanbul ignore next */ []);
1536
- state = this._state.asReadonly();
1537
- bxDropdown = input.required(...ngDevMode ? [{ debugName: "bxDropdown" }] : /* istanbul ignore next */ []);
1538
- placement = input("bottom", ...ngDevMode ? [{ debugName: "placement" }] : /* istanbul ignore next */ []);
1539
- bxTransition = input("fade", ...ngDevMode ? [{ debugName: "bxTransition" }] : /* istanbul ignore next */ []);
1540
- overlayRef = null;
1541
- transition = null;
1542
- subscriptions = new Subscription();
1543
- revision = 0;
1544
- disconnectTheme;
1545
- disconnectLighting;
1546
- constructor() {
1547
- inject(DestroyRef).onDestroy(() => {
1548
- ++this.revision;
1549
- this.dispose();
1550
- });
1551
- effect(() => {
1552
- if (this.a11y.isReducedMotion() && this.transition) {
1553
- ++this.revision;
1554
- this.transition.destroy();
1555
- this.transition = null;
1556
- if (this.isOpen()) this._state.set("open");
1557
- else this.dispose();
1558
- }
1559
- });
1560
- }
1561
- toggle(event) {
1562
- if (this.isDisabled()) return;
1563
- event?.stopPropagation();
1564
- if (this.isOpen()) this.close();
1565
- else this.open();
1566
- }
1567
- onTriggerKeydown(event) {
1568
- if (this.bxTransition() === "none" || this.isDisabled() || this.isEditing(event.target)) return;
1569
- if (event.key !== "ArrowDown" && event.key !== "ArrowUp") return;
1570
- event.preventDefault();
1571
- event.stopPropagation();
1572
- this.open();
1573
- const items = this.menuItems();
1574
- (event.key === "ArrowUp" ? items[items.length - 1] : items[0])?.focus({ preventScroll: true });
1575
- }
1576
- open() {
1577
- if (!this.isBrowser || this.isOpen() || this.isDisabled()) return;
1578
- const revision = ++this.revision;
1579
- this._isOpen.set(true);
1580
- this._state.set("opening");
1581
- if (!this.overlayRef) this.attachOverlay();
1582
- const overlay = this.overlayRef;
1583
- if (!overlay) return;
1584
- overlay.overlayElement.inert = false;
1585
- overlay.overlayElement.style.removeProperty("pointer-events");
1586
- if (this.bxTransition() !== "none" && !this.a11y.isReducedMotion()) {
1587
- const transition = this.transition ??= this.zone.runOutsideAngular(() => createGlassTransition(this.elementRef.nativeElement, overlay.overlayElement));
1588
- this.zone.runOutsideAngular(() => transition.enter()).then(() => {
1589
- if (revision === this.revision && this.isOpen()) this.zone.run(() => this._state.set("open"));
1590
- }).catch(() => {
1591
- if (revision === this.revision && this.isOpen()) {
1592
- this.transition?.destroy();
1593
- this.transition = null;
1594
- this._state.set("open");
1595
- }
1596
- });
1597
- } else this._state.set("open");
1598
- }
1599
- close(restoreFocus = false) {
1600
- if (!this.overlayRef || !this.isOpen()) return;
1601
- const revision = ++this.revision;
1602
- const overlay = this.overlayRef;
1603
- this._isOpen.set(false);
1604
- this._state.set("closing");
1605
- const source = this.elementRef.nativeElement;
1606
- if (restoreFocus || overlay.overlayElement.contains(source.ownerDocument.activeElement)) source.focus({ preventScroll: true });
1607
- overlay.overlayElement.inert = true;
1608
- overlay.overlayElement.style.pointerEvents = "none";
1609
- const transition = this.transition;
1610
- if (transition && !this.a11y.isReducedMotion()) this.zone.runOutsideAngular(() => transition.exit()).then(() => {
1611
- if (revision === this.revision && !this.isOpen()) this.zone.run(() => this.dispose());
1612
- }).catch(() => {
1613
- if (revision === this.revision && !this.isOpen()) this.dispose();
1614
- });
1615
- else this.dispose();
1616
- }
1617
- onDocumentClick(event) {
1618
- if (!this.overlayRef?.hasAttached() || !this.isOpen()) return;
1619
- const target = event.target;
1620
- if (!target || this.elementRef.nativeElement.contains(target)) return;
1621
- if (!this.overlayRef.overlayElement.contains(target) || this.bxTransition() === "none" || target instanceof Element && target.closest("button, a, [role=\"menuitem\"]")) this.close();
1622
- }
1623
- attachOverlay() {
1624
- const positionStrategy = this.positionBuilder.getElementStrategy(this.elementRef.nativeElement, this.placement(), 4);
1625
- const overlay = this.overlay.create({
1626
- positionStrategy,
1627
- scrollStrategy: this.overlay.scrollStrategies.noop(),
1628
- usePopover: !!this.overlayContext?.useTopLayer || !!this.elementRef.nativeElement.closest("dialog, [role=\"dialog\"], [role=\"alertdialog\"], bx-modal, bx-modal-core, [popover]"),
1629
- hasBackdrop: this.bxTransition() === "none",
1630
- backdropClass: "cdk-overlay-transparent-backdrop"
1631
- });
1632
- this.overlayRef = overlay;
1633
- this.overlayId.set(overlay.overlayElement.id || null);
1634
- this.disconnectTheme = this.zone.runOutsideAngular(() => inheritOverlayTheme(this.elementRef.nativeElement, overlay.overlayElement));
1635
- this.disconnectLighting = inheritGlassLighting(overlay.overlayElement, this.elementRef.nativeElement);
1636
- this.subscriptions = new Subscription();
1637
- this.subscriptions.add(this.zone.runOutsideAngular(() => trackOverlayOrigin(overlay, this.elementRef.nativeElement)));
1638
- this.subscriptions.add(overlay.backdropClick().subscribe(() => this.close()));
1639
- this.subscriptions.add(overlay.outsidePointerEvents().subscribe((event) => {
1640
- if (!this.elementRef.nativeElement.contains(event.target)) this.close();
1641
- }));
1642
- this.subscriptions.add(overlay.keydownEvents().subscribe((event) => {
1643
- if (event.key === "Escape" && this.isOpen()) {
1644
- event.preventDefault();
1645
- event.stopPropagation();
1646
- this.close(true);
1647
- } else if (!event.defaultPrevented && this.bxTransition() !== "none" && this.isOpen()) this.navigateMenu(event);
1648
- }));
1649
- this.subscriptions.add(positionStrategy.positionChanges.subscribe(() => {
1650
- this.zone.runOutsideAngular(() => this.transition?.refresh());
1651
- }));
1652
- overlay.attach(new TemplatePortal(this.bxDropdown(), this.vcr)).detectChanges();
1653
- overlay.updatePosition();
1654
- }
1655
- isDisabled() {
1656
- const element = this.elementRef.nativeElement;
1657
- return element.hasAttribute("disabled") || element.getAttribute("aria-disabled") === "true";
1658
- }
1659
- menuItems() {
1660
- const pane = this.overlayRef?.overlayElement;
1661
- if (!pane) return [];
1662
- return Array.from(pane.querySelectorAll("button, a[href], [role=\"menuitem\"]")).filter((item) => {
1663
- if (item.matches(":disabled, [disabled], [aria-disabled=\"true\"]") || item.closest("[aria-disabled=\"true\"]")) return false;
1664
- if (item.closest("[hidden], [inert], [aria-hidden=\"true\"]")) return false;
1665
- if (item.tabIndex < 0 && !item.hasAttribute("tabindex")) return false;
1666
- const style = item.ownerDocument.defaultView?.getComputedStyle(item);
1667
- return !!style && style.display !== "none" && style.visibility !== "hidden" && item.getClientRects().length > 0;
1668
- });
2248
+ var LoadingIndicator = class LoadingIndicator {
2249
+ i18n = inject(BX_I18N, { optional: true });
2250
+ resolvedLabel = computed(() => resolveText(this.label(), this.i18n), ...ngDevMode ? [{ debugName: "resolvedLabel" }] : /* istanbul ignore next */ []);
2251
+ label = input("Loading", ...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
2252
+ size = input(20, ...ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []);
2253
+ static ɵfac = i0.ɵɵngDeclareFactory({
2254
+ minVersion: "12.0.0",
2255
+ version: "22.2.3",
2256
+ ngImport: i0,
2257
+ type: LoadingIndicator,
2258
+ deps: [],
2259
+ target: i0.ɵɵFactoryTarget.Component
2260
+ });
2261
+ static ɵcmp = i0.ɵɵngDeclareComponent({
2262
+ minVersion: "17.1.0",
2263
+ version: "22.2.3",
2264
+ type: LoadingIndicator,
2265
+ isStandalone: true,
2266
+ selector: "bx-loading-indicator",
2267
+ inputs: {
2268
+ label: {
2269
+ classPropertyName: "label",
2270
+ publicName: "label",
2271
+ isSignal: true,
2272
+ isRequired: false,
2273
+ transformFunction: null
2274
+ },
2275
+ size: {
2276
+ classPropertyName: "size",
2277
+ publicName: "size",
2278
+ isSignal: true,
2279
+ isRequired: false,
2280
+ transformFunction: null
2281
+ }
2282
+ },
2283
+ host: { attributes: {
2284
+ "role": "status",
2285
+ "aria-live": "polite",
2286
+ "aria-busy": "true"
2287
+ } },
2288
+ ngImport: i0,
2289
+ template: "<bx-loading-spinner [size]=\"size()\" [decorative]=\"true\" />\n<span>{{ resolvedLabel() }}</span>\n<ng-content />\n",
2290
+ styles: [":host{display:inline-flex;align-items:center;gap:var(--bx-loading-gap, .5rem);color:var(--bx-loading-color, var(--bx-text-secondary));font:inherit;overflow-wrap:anywhere}\n"],
2291
+ dependencies: [{
2292
+ kind: "component",
2293
+ type: LoadingSpinner,
2294
+ selector: "bx-loading-spinner",
2295
+ inputs: [
2296
+ "size",
2297
+ "decorative",
2298
+ "label"
2299
+ ]
2300
+ }],
2301
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
2302
+ });
2303
+ };
2304
+ i0.ɵɵngDeclareClassMetadata({
2305
+ minVersion: "12.0.0",
2306
+ version: "22.2.3",
2307
+ ngImport: i0,
2308
+ type: LoadingIndicator,
2309
+ decorators: [{
2310
+ type: Component,
2311
+ args: [{
2312
+ selector: "bx-loading-indicator",
2313
+ imports: [LoadingSpinner],
2314
+ changeDetection: ChangeDetectionStrategy.OnPush,
2315
+ host: {
2316
+ role: "status",
2317
+ "aria-live": "polite",
2318
+ "aria-busy": "true"
2319
+ },
2320
+ template: "<bx-loading-spinner [size]=\"size()\" [decorative]=\"true\" />\n<span>{{ resolvedLabel() }}</span>\n<ng-content />\n",
2321
+ styles: [":host{display:inline-flex;align-items:center;gap:var(--bx-loading-gap, .5rem);color:var(--bx-loading-color, var(--bx-text-secondary));font:inherit;overflow-wrap:anywhere}\n"]
2322
+ }]
2323
+ }],
2324
+ propDecorators: {
2325
+ label: [{
2326
+ type: i0.Input,
2327
+ args: [{
2328
+ isSignal: true,
2329
+ alias: "label",
2330
+ required: false
2331
+ }]
2332
+ }],
2333
+ size: [{
2334
+ type: i0.Input,
2335
+ args: [{
2336
+ isSignal: true,
2337
+ alias: "size",
2338
+ required: false
2339
+ }]
2340
+ }]
1669
2341
  }
1670
- navigateMenu(event) {
1671
- if (this.isEditing(event.target) || !(event.target instanceof Node) || !this.overlayRef?.overlayElement.contains(event.target)) return;
1672
- if (![
1673
- "ArrowDown",
1674
- "ArrowUp",
1675
- "Home",
1676
- "End"
1677
- ].includes(event.key)) return;
1678
- const items = this.menuItems();
1679
- if (!items.length) return;
1680
- const current = items.indexOf(this.elementRef.nativeElement.ownerDocument.activeElement);
1681
- let index;
1682
- if (event.key === "Home") index = 0;
1683
- else if (event.key === "End") index = items.length - 1;
1684
- else if (event.key === "ArrowDown") index = current < 0 ? 0 : (current + 1) % items.length;
1685
- else index = current < 0 ? items.length - 1 : (current - 1 + items.length) % items.length;
1686
- event.preventDefault();
1687
- event.stopPropagation();
1688
- items[index].focus({ preventScroll: true });
2342
+ });
2343
+ var ProgressBar = class ProgressBar {
2344
+ i18n = inject(BX_I18N, { optional: true });
2345
+ a11y = inject(BxA11yService);
2346
+ resolvedLabel = computed(() => resolveText(this.label(), this.i18n), ...ngDevMode ? [{ debugName: "resolvedLabel" }] : /* istanbul ignore next */ []);
2347
+ progress = computed(() => Number.isFinite(this.value()) ? Math.min(100, Math.max(0, this.value())) : 0, ...ngDevMode ? [{ debugName: "progress" }] : /* istanbul ignore next */ []);
2348
+ buffer = computed(() => Math.max(this.progress(), Number.isFinite(this.bufferValue()) ? Math.min(100, Math.max(0, this.bufferValue())) : 0), ...ngDevMode ? [{ debugName: "buffer" }] : /* istanbul ignore next */ []);
2349
+ indeterminate = computed(() => this.mode() === "indeterminate" || this.mode() === "query", ...ngDevMode ? [{ debugName: "indeterminate" }] : /* istanbul ignore next */ []);
2350
+ mode = input("determinate", ...ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []);
2351
+ value = input(0, ...ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []);
2352
+ bufferValue = input(100, ...ngDevMode ? [{ debugName: "bufferValue" }] : /* istanbul ignore next */ []);
2353
+ label = input("Progress", ...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
2354
+ static ɵfac = i0.ɵɵngDeclareFactory({
2355
+ minVersion: "12.0.0",
2356
+ version: "22.2.3",
2357
+ ngImport: i0,
2358
+ type: ProgressBar,
2359
+ deps: [],
2360
+ target: i0.ɵɵFactoryTarget.Component
2361
+ });
2362
+ static ɵcmp = i0.ɵɵngDeclareComponent({
2363
+ minVersion: "17.0.0",
2364
+ version: "22.2.3",
2365
+ type: ProgressBar,
2366
+ isStandalone: true,
2367
+ selector: "bx-progress-bar",
2368
+ inputs: {
2369
+ mode: {
2370
+ classPropertyName: "mode",
2371
+ publicName: "mode",
2372
+ isSignal: true,
2373
+ isRequired: false,
2374
+ transformFunction: null
2375
+ },
2376
+ value: {
2377
+ classPropertyName: "value",
2378
+ publicName: "value",
2379
+ isSignal: true,
2380
+ isRequired: false,
2381
+ transformFunction: null
2382
+ },
2383
+ bufferValue: {
2384
+ classPropertyName: "bufferValue",
2385
+ publicName: "bufferValue",
2386
+ isSignal: true,
2387
+ isRequired: false,
2388
+ transformFunction: null
2389
+ },
2390
+ label: {
2391
+ classPropertyName: "label",
2392
+ publicName: "label",
2393
+ isSignal: true,
2394
+ isRequired: false,
2395
+ transformFunction: null
2396
+ }
2397
+ },
2398
+ host: {
2399
+ attributes: {
2400
+ "role": "progressbar",
2401
+ "aria-valuemin": "0",
2402
+ "aria-valuemax": "100"
2403
+ },
2404
+ properties: {
2405
+ "attr.aria-valuenow": "indeterminate() ? null : progress()",
2406
+ "attr.aria-label": "resolvedLabel()",
2407
+ "class.is-indeterminate": "indeterminate()",
2408
+ "class.is-reduced-motion": "a11y.isReducedMotion()",
2409
+ "class.is-query": "mode() === \"query\""
2410
+ }
2411
+ },
2412
+ ngImport: i0,
2413
+ template: "@if (mode() === 'buffer') {\n<span class=\"bx-progress-buffer\" [style.width.%]=\"buffer()\"></span>\n}\n<span class=\"bx-progress-value\" [style.width.%]=\"indeterminate() ? 40 : progress()\"></span>\n",
2414
+ styles: [":host{display:block;position:relative;inline-size:100%;block-size:var(--bx-progress-height, 4px);overflow:hidden;border-radius:var(--bx-progress-radius, 9999px);background:var(--bx-progress-track, var(--bx-bg-element))}.bx-progress-value,.bx-progress-buffer{display:block;position:absolute;inset-block:0;inset-inline-start:0;background:var(--bx-progress-color, var(--bx-accent))}.bx-progress-buffer{opacity:.3}:host(.is-indeterminate) .bx-progress-value{animation:bx-progress-travel 1.3s ease-in-out infinite}:host(.is-query){transform:scaleX(-1)}:host(:dir(rtl)) .bx-progress-value{animation-direction:reverse}:host(.is-reduced-motion) .bx-progress-value{animation:none}@media(forced-colors:active){:host{background:Canvas;outline:1px solid CanvasText}.bx-progress-value,.bx-progress-buffer{background:Highlight}}@keyframes bx-progress-travel{0%{inset-inline-start:-40%}to{inset-inline-start:100%}}\n"],
2415
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
2416
+ });
2417
+ };
2418
+ i0.ɵɵngDeclareClassMetadata({
2419
+ minVersion: "12.0.0",
2420
+ version: "22.2.3",
2421
+ ngImport: i0,
2422
+ type: ProgressBar,
2423
+ decorators: [{
2424
+ type: Component,
2425
+ args: [{
2426
+ selector: "bx-progress-bar",
2427
+ changeDetection: ChangeDetectionStrategy.OnPush,
2428
+ host: {
2429
+ role: "progressbar",
2430
+ "aria-valuemin": "0",
2431
+ "aria-valuemax": "100",
2432
+ "[attr.aria-valuenow]": "indeterminate() ? null : progress()",
2433
+ "[attr.aria-label]": "resolvedLabel()",
2434
+ "[class.is-indeterminate]": "indeterminate()",
2435
+ "[class.is-reduced-motion]": "a11y.isReducedMotion()",
2436
+ "[class.is-query]": "mode() === \"query\""
2437
+ },
2438
+ template: "@if (mode() === 'buffer') {\n<span class=\"bx-progress-buffer\" [style.width.%]=\"buffer()\"></span>\n}\n<span class=\"bx-progress-value\" [style.width.%]=\"indeterminate() ? 40 : progress()\"></span>\n",
2439
+ styles: [":host{display:block;position:relative;inline-size:100%;block-size:var(--bx-progress-height, 4px);overflow:hidden;border-radius:var(--bx-progress-radius, 9999px);background:var(--bx-progress-track, var(--bx-bg-element))}.bx-progress-value,.bx-progress-buffer{display:block;position:absolute;inset-block:0;inset-inline-start:0;background:var(--bx-progress-color, var(--bx-accent))}.bx-progress-buffer{opacity:.3}:host(.is-indeterminate) .bx-progress-value{animation:bx-progress-travel 1.3s ease-in-out infinite}:host(.is-query){transform:scaleX(-1)}:host(:dir(rtl)) .bx-progress-value{animation-direction:reverse}:host(.is-reduced-motion) .bx-progress-value{animation:none}@media(forced-colors:active){:host{background:Canvas;outline:1px solid CanvasText}.bx-progress-value,.bx-progress-buffer{background:Highlight}}@keyframes bx-progress-travel{0%{inset-inline-start:-40%}to{inset-inline-start:100%}}\n"]
2440
+ }]
2441
+ }],
2442
+ propDecorators: {
2443
+ mode: [{
2444
+ type: i0.Input,
2445
+ args: [{
2446
+ isSignal: true,
2447
+ alias: "mode",
2448
+ required: false
2449
+ }]
2450
+ }],
2451
+ value: [{
2452
+ type: i0.Input,
2453
+ args: [{
2454
+ isSignal: true,
2455
+ alias: "value",
2456
+ required: false
2457
+ }]
2458
+ }],
2459
+ bufferValue: [{
2460
+ type: i0.Input,
2461
+ args: [{
2462
+ isSignal: true,
2463
+ alias: "bufferValue",
2464
+ required: false
2465
+ }]
2466
+ }],
2467
+ label: [{
2468
+ type: i0.Input,
2469
+ args: [{
2470
+ isSignal: true,
2471
+ alias: "label",
2472
+ required: false
2473
+ }]
2474
+ }]
1689
2475
  }
1690
- isEditing(target) {
1691
- return target instanceof Element && !!target.closest("input, textarea, select, [contenteditable]:not([contenteditable=\"false\"]), [role=\"textbox\"]");
2476
+ });
2477
+ const TAG_PALETTES = {
2478
+ primary: {
2479
+ text: "var(--bx-text-brand)",
2480
+ fill: "var(--bx-primary)",
2481
+ onFill: "var(--bx-on-primary)",
2482
+ tonal: "var(--bx-primary-subtle)",
2483
+ border: "var(--bx-border-brand)"
2484
+ },
2485
+ accent: {
2486
+ text: "var(--bx-text-accent)",
2487
+ fill: "var(--bx-accent)",
2488
+ onFill: "var(--bx-on-accent)",
2489
+ tonal: "var(--bx-accent-subtle)",
2490
+ border: "var(--bx-border-accent)"
2491
+ },
2492
+ neutral: {
2493
+ text: "var(--bx-text-primary)",
2494
+ fill: "var(--bx-bg-element-active)",
2495
+ onFill: "var(--bx-text-primary)",
2496
+ tonal: "var(--bx-bg-element)",
2497
+ border: "var(--bx-border-strong)"
2498
+ },
2499
+ success: {
2500
+ text: "var(--bx-text-success)",
2501
+ fill: "var(--bx-bg-success)",
2502
+ onFill: "var(--bx-text-success)",
2503
+ tonal: "var(--bx-bg-success-subtle)",
2504
+ border: "var(--bx-border-success)"
2505
+ },
2506
+ danger: {
2507
+ text: "var(--bx-text-danger)",
2508
+ fill: "var(--bx-bg-danger)",
2509
+ onFill: "var(--bx-text-danger)",
2510
+ tonal: "var(--bx-bg-danger-subtle)",
2511
+ border: "var(--bx-border-danger)"
2512
+ },
2513
+ info: {
2514
+ text: "var(--bx-text-info)",
2515
+ fill: "var(--bx-bg-info)",
2516
+ onFill: "var(--bx-text-info)",
2517
+ tonal: "var(--bx-bg-info-subtle)",
2518
+ border: "var(--bx-border-info)"
2519
+ },
2520
+ warn: {
2521
+ text: "var(--bx-text-warn)",
2522
+ fill: "var(--bx-bg-warn)",
2523
+ onFill: "var(--bx-text-warn)",
2524
+ tonal: "var(--bx-bg-warn-subtle)",
2525
+ border: "var(--bx-border-warn)"
1692
2526
  }
1693
- dispose() {
1694
- this.disconnectTheme?.();
1695
- this.disconnectTheme = void 0;
1696
- this.transition?.destroy();
1697
- this.transition = null;
1698
- this.subscriptions.unsubscribe();
1699
- this.overlayRef?.dispose();
1700
- this.overlayRef = null;
1701
- this.disconnectLighting?.();
1702
- this.disconnectLighting = void 0;
1703
- this.overlayId.set(null);
1704
- this._isOpen.set(false);
1705
- this._state.set("closed");
2527
+ };
2528
+ function formatTagNumber(value, locale) {
2529
+ if (value === void 0 || value === null) return "";
2530
+ if (typeof value === "string") return value;
2531
+ if (!Number.isFinite(value)) return "";
2532
+ try {
2533
+ return new Intl.NumberFormat(locale).format(value);
2534
+ } catch {
2535
+ return String(value);
1706
2536
  }
2537
+ }
2538
+ var Tag = class Tag {
2539
+ i18n = inject(BX_I18N, { optional: true });
2540
+ textOverflow = viewChild(TruncateDirective, ...ngDevMode ? [{ debugName: "textOverflow" }] : /* istanbul ignore next */ []);
2541
+ resolvedText = computed(() => resolveText(this.text(), this.i18n), ...ngDevMode ? [{ debugName: "resolvedText" }] : /* istanbul ignore next */ []);
2542
+ resolvedTooltip = computed(() => {
2543
+ const tooltip = this.tooltip() ?? this.config().tooltip;
2544
+ return tooltip !== void 0 ? resolveText(tooltip, this.i18n) : truncatedText(this.resolvedText(), this.textOverflow()?.truncated() ?? false, this.tooltipOnTruncate() ?? this.config().tooltipOnTruncate ?? true);
2545
+ }, ...ngDevMode ? [{ debugName: "resolvedTooltip" }] : /* istanbul ignore next */ []);
2546
+ resolvedAriaLabel = computed(() => resolveText(this.ariaLabel(), this.i18n), ...ngDevMode ? [{ debugName: "resolvedAriaLabel" }] : /* istanbul ignore next */ []);
2547
+ resolvedVariant = computed(() => this.variant() ?? this.config().variant ?? "tonal", ...ngDevMode ? [{ debugName: "resolvedVariant" }] : /* istanbul ignore next */ []);
2548
+ resolvedSize = computed(() => this.size() ?? this.config().size ?? "medium", ...ngDevMode ? [{ debugName: "resolvedSize" }] : /* istanbul ignore next */ []);
2549
+ resolvedLeadingIcon = computed(() => this.leadingIcon() ?? this.config().leadingIcon, ...ngDevMode ? [{ debugName: "resolvedLeadingIcon" }] : /* istanbul ignore next */ []);
2550
+ resolvedTrailingIcon = computed(() => this.trailingIcon() ?? this.config().trailingIcon, ...ngDevMode ? [{ debugName: "resolvedTrailingIcon" }] : /* istanbul ignore next */ []);
2551
+ resolvedIconSize = computed(() => this.iconSize() ?? this.config().iconSize ?? "16", ...ngDevMode ? [{ debugName: "resolvedIconSize" }] : /* istanbul ignore next */ []);
2552
+ resolvedLeadingNumber = computed(() => {
2553
+ this.i18n?.version?.();
2554
+ return formatTagNumber(this.leadingNumber() === void 0 ? this.config().leadingNumber : this.leadingNumber(), this.locale());
2555
+ }, ...ngDevMode ? [{ debugName: "resolvedLeadingNumber" }] : /* istanbul ignore next */ []);
2556
+ resolvedTrailingNumber = computed(() => {
2557
+ this.i18n?.version?.();
2558
+ return formatTagNumber(this.trailingNumber() === void 0 ? this.config().trailingNumber : this.trailingNumber(), this.locale());
2559
+ }, ...ngDevMode ? [{ debugName: "resolvedTrailingNumber" }] : /* istanbul ignore next */ []);
2560
+ palette = computed(() => TAG_PALETTES[this.color() ?? this.config().color ?? "accent"], ...ngDevMode ? [{ debugName: "palette" }] : /* istanbul ignore next */ []);
2561
+ isNumberOnly = computed(() => !this.resolvedText() && !this.resolvedLeadingIcon() && !this.resolvedTrailingIcon() && !!this.resolvedLeadingNumber() !== !!this.resolvedTrailingNumber(), ...ngDevMode ? [{ debugName: "isNumberOnly" }] : /* istanbul ignore next */ []);
2562
+ text = input(void 0, ...ngDevMode ? [{ debugName: "text" }] : /* istanbul ignore next */ []);
2563
+ config = input({}, ...ngDevMode ? [{ debugName: "config" }] : /* istanbul ignore next */ []);
2564
+ color = input(void 0, ...ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []);
2565
+ variant = input(void 0, ...ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []);
2566
+ size = input(void 0, ...ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []);
2567
+ disabled = input(false, {
2568
+ ...ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {},
2569
+ transform: booleanAttribute
2570
+ });
2571
+ leadingIcon = input(void 0, ...ngDevMode ? [{ debugName: "leadingIcon" }] : /* istanbul ignore next */ []);
2572
+ trailingIcon = input(void 0, ...ngDevMode ? [{ debugName: "trailingIcon" }] : /* istanbul ignore next */ []);
2573
+ iconSize = input(void 0, ...ngDevMode ? [{ debugName: "iconSize" }] : /* istanbul ignore next */ []);
2574
+ leadingNumber = input(void 0, ...ngDevMode ? [{ debugName: "leadingNumber" }] : /* istanbul ignore next */ []);
2575
+ trailingNumber = input(void 0, ...ngDevMode ? [{ debugName: "trailingNumber" }] : /* istanbul ignore next */ []);
2576
+ locale = input(void 0, ...ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []);
2577
+ tooltip = input(void 0, ...ngDevMode ? [{ debugName: "tooltip" }] : /* istanbul ignore next */ []);
2578
+ tooltipOnTruncate = input(void 0, ...ngDevMode ? [{ debugName: "tooltipOnTruncate" }] : /* istanbul ignore next */ []);
2579
+ tooltipPlacement = input("top", ...ngDevMode ? [{ debugName: "tooltipPlacement" }] : /* istanbul ignore next */ []);
2580
+ ariaLabel = input(void 0, ...ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []);
2581
+ focusable = input(true, ...ngDevMode ? [{ debugName: "focusable" }] : /* istanbul ignore next */ []);
1707
2582
  static ɵfac = i0.ɵɵngDeclareFactory({
1708
2583
  minVersion: "12.0.0",
1709
2584
  version: "22.2.3",
1710
2585
  ngImport: i0,
1711
- type: DropdownDirective,
2586
+ type: Tag,
1712
2587
  deps: [],
1713
- target: i0.ɵɵFactoryTarget.Directive
2588
+ target: i0.ɵɵFactoryTarget.Component
1714
2589
  });
1715
- static ɵdir = i0.ɵɵngDeclareDirective({
1716
- minVersion: "17.1.0",
2590
+ static ɵcmp = i0.ɵɵngDeclareComponent({
2591
+ minVersion: "17.0.0",
1717
2592
  version: "22.2.3",
1718
- type: DropdownDirective,
2593
+ type: Tag,
1719
2594
  isStandalone: true,
1720
- selector: "[bxDropdown]",
2595
+ selector: "bx-tag",
1721
2596
  inputs: {
1722
- bxDropdown: {
1723
- classPropertyName: "bxDropdown",
1724
- publicName: "bxDropdown",
2597
+ text: {
2598
+ classPropertyName: "text",
2599
+ publicName: "text",
2600
+ isSignal: true,
2601
+ isRequired: false,
2602
+ transformFunction: null
2603
+ },
2604
+ config: {
2605
+ classPropertyName: "config",
2606
+ publicName: "config",
2607
+ isSignal: true,
2608
+ isRequired: false,
2609
+ transformFunction: null
2610
+ },
2611
+ color: {
2612
+ classPropertyName: "color",
2613
+ publicName: "color",
2614
+ isSignal: true,
2615
+ isRequired: false,
2616
+ transformFunction: null
2617
+ },
2618
+ variant: {
2619
+ classPropertyName: "variant",
2620
+ publicName: "variant",
2621
+ isSignal: true,
2622
+ isRequired: false,
2623
+ transformFunction: null
2624
+ },
2625
+ size: {
2626
+ classPropertyName: "size",
2627
+ publicName: "size",
2628
+ isSignal: true,
2629
+ isRequired: false,
2630
+ transformFunction: null
2631
+ },
2632
+ disabled: {
2633
+ classPropertyName: "disabled",
2634
+ publicName: "disabled",
2635
+ isSignal: true,
2636
+ isRequired: false,
2637
+ transformFunction: null
2638
+ },
2639
+ leadingIcon: {
2640
+ classPropertyName: "leadingIcon",
2641
+ publicName: "leadingIcon",
2642
+ isSignal: true,
2643
+ isRequired: false,
2644
+ transformFunction: null
2645
+ },
2646
+ trailingIcon: {
2647
+ classPropertyName: "trailingIcon",
2648
+ publicName: "trailingIcon",
2649
+ isSignal: true,
2650
+ isRequired: false,
2651
+ transformFunction: null
2652
+ },
2653
+ iconSize: {
2654
+ classPropertyName: "iconSize",
2655
+ publicName: "iconSize",
2656
+ isSignal: true,
2657
+ isRequired: false,
2658
+ transformFunction: null
2659
+ },
2660
+ leadingNumber: {
2661
+ classPropertyName: "leadingNumber",
2662
+ publicName: "leadingNumber",
2663
+ isSignal: true,
2664
+ isRequired: false,
2665
+ transformFunction: null
2666
+ },
2667
+ trailingNumber: {
2668
+ classPropertyName: "trailingNumber",
2669
+ publicName: "trailingNumber",
2670
+ isSignal: true,
2671
+ isRequired: false,
2672
+ transformFunction: null
2673
+ },
2674
+ locale: {
2675
+ classPropertyName: "locale",
2676
+ publicName: "locale",
2677
+ isSignal: true,
2678
+ isRequired: false,
2679
+ transformFunction: null
2680
+ },
2681
+ tooltip: {
2682
+ classPropertyName: "tooltip",
2683
+ publicName: "tooltip",
1725
2684
  isSignal: true,
1726
- isRequired: true,
2685
+ isRequired: false,
1727
2686
  transformFunction: null
1728
2687
  },
1729
- placement: {
1730
- classPropertyName: "placement",
1731
- publicName: "placement",
2688
+ tooltipOnTruncate: {
2689
+ classPropertyName: "tooltipOnTruncate",
2690
+ publicName: "tooltipOnTruncate",
1732
2691
  isSignal: true,
1733
2692
  isRequired: false,
1734
2693
  transformFunction: null
1735
2694
  },
1736
- bxTransition: {
1737
- classPropertyName: "bxTransition",
1738
- publicName: "bxTransition",
2695
+ tooltipPlacement: {
2696
+ classPropertyName: "tooltipPlacement",
2697
+ publicName: "tooltipPlacement",
2698
+ isSignal: true,
2699
+ isRequired: false,
2700
+ transformFunction: null
2701
+ },
2702
+ ariaLabel: {
2703
+ classPropertyName: "ariaLabel",
2704
+ publicName: "ariaLabel",
2705
+ isSignal: true,
2706
+ isRequired: false,
2707
+ transformFunction: null
2708
+ },
2709
+ focusable: {
2710
+ classPropertyName: "focusable",
2711
+ publicName: "focusable",
1739
2712
  isSignal: true,
1740
2713
  isRequired: false,
1741
2714
  transformFunction: null
1742
2715
  }
1743
2716
  },
1744
- host: {
1745
- listeners: {
1746
- "click": "toggle($event)",
1747
- "keydown": "onTriggerKeydown($event)",
1748
- "document:click": "onDocumentClick($event)"
2717
+ host: { properties: {
2718
+ "style.--bx-tag-role-text": "palette().text",
2719
+ "style.--bx-tag-role-fill": "palette().fill",
2720
+ "style.--bx-tag-role-on-fill": "palette().onFill",
2721
+ "style.--bx-tag-role-tonal": "palette().tonal",
2722
+ "style.--bx-tag-role-border": "palette().border"
2723
+ } },
2724
+ viewQueries: [{
2725
+ propertyName: "textOverflow",
2726
+ first: true,
2727
+ predicate: TruncateDirective,
2728
+ descendants: true,
2729
+ isSignal: true
2730
+ }],
2731
+ ngImport: i0,
2732
+ template: "<span class=\"bx-tag\" bxSurface [bxSurfaceInteractive]=\"false\"\n [class.is-filled]=\"resolvedVariant() === 'filled'\" [class.is-outlined]=\"resolvedVariant() === 'outlined'\"\n [class.is-small]=\"resolvedSize() === 'small'\" [class.is-disabled]=\"disabled()\" [class.is-number-only]=\"isNumberOnly()\"\n [attr.aria-disabled]=\"disabled() ? 'true' : null\" [attr.role]=\"resolvedAriaLabel() ? 'group' : null\" [attr.aria-label]=\"resolvedAriaLabel() || null\"\n [attr.tabindex]=\"resolvedTooltip() && focusable() ? 0 : null\" [bxTooltip]=\"resolvedTooltip()\" [placement]=\"tooltipPlacement()\" bxTooltipTouch=\"longpress\">\n @if (resolvedLeadingIcon(); as icon) { <bx-icon [name]=\"icon\" [size]=\"resolvedIconSize()\" /> }\n @if (resolvedLeadingNumber()) { <span class=\"bx-tag-number\">{{ resolvedLeadingNumber() }}</span> }\n @if (resolvedText()) { <span class=\"bx-tag-text\" bxTruncate>{{ resolvedText() }}</span> }\n @if (resolvedTrailingNumber()) { <span class=\"bx-tag-number\">{{ resolvedTrailingNumber() }}</span> }\n @if (resolvedTrailingIcon(); as icon) { <bx-icon [name]=\"icon\" [size]=\"resolvedIconSize()\" /> }\n</span>\n",
2733
+ styles: [":host{display:inline-flex;min-inline-size:0;max-inline-size:100%;vertical-align:middle}.bx-tag{--bx-glass-surface: var(--bx-tag-background, var(--bx-tag-role-tonal));--bx-glass-text: var(--bx-tag-color, var(--bx-tag-role-text));--bx-glass-edge: var(--bx-tag-border, var(--bx-tag-role-border));--bx-glass-radius: var(--bx-tag-radius, .25rem);--bx-glass-shadow: var(--bx-tag-shadow, none);position:relative;display:inline-flex;align-items:center;justify-content:center;min-inline-size:0;max-inline-size:100%;box-sizing:border-box;gap:var(--bx-tag-gap, .25rem);padding:var(--bx-tag-padding, .25rem .5rem);border:1px solid var(--bx-glass-edge);border-radius:var(--bx-glass-radius);background:var(--bx-glass-surface);color:var(--bx-glass-text);font:inherit;font-size:var(--bx-tag-font-size, .8125rem);line-height:1.4;white-space:nowrap}.bx-tag.is-filled{--bx-glass-surface: var(--bx-tag-background, var(--bx-tag-role-fill));--bx-glass-text: var(--bx-tag-color, var(--bx-tag-role-on-fill));--bx-glass-min-opacity: var(--bx-tag-fill-opacity, .85)}.bx-tag.is-outlined{--bx-glass-surface: var(--bx-tag-background, var(--bx-bg-surface));--bx-glass-opacity: var(--bx-tag-outline-opacity, .12)}.bx-tag.is-small{font-size:var(--bx-tag-font-size, .75rem);padding-block:.125rem}.bx-tag.is-disabled{opacity:var(--bx-tag-disabled-opacity, .5)}.bx-tag.is-number-only{--bx-glass-radius: 50%;inline-size:max-content;min-inline-size:var(--bx-tag-number-size, 1.875rem);aspect-ratio:1;padding:var(--bx-tag-number-padding, .35em)}.bx-tag.is-number-only.is-small{min-inline-size:var(--bx-tag-number-size, 1.5rem)}.bx-tag:focus-visible{outline:2px solid var(--bx-border-brand);outline-offset:2px}.bx-tag-number{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;min-inline-size:1.1em;padding-inline:.25em;border-radius:var(--bx-tag-counter-radius, .25rem);background:var(--bx-tag-counter-background, color-mix(in srgb, currentcolor 12%, transparent));font-variant-numeric:tabular-nums}.is-number-only .bx-tag-number{background:transparent;padding:0}@media(forced-colors:active){.bx-tag.is-disabled{color:GrayText;border-color:GrayText;opacity:1}}\n"],
2734
+ dependencies: [
2735
+ {
2736
+ kind: "component",
2737
+ type: Icon,
2738
+ selector: "bx-icon",
2739
+ inputs: [
2740
+ "name",
2741
+ "size",
2742
+ "color",
2743
+ "bgColor",
2744
+ "strokeWidth",
2745
+ "decorative",
2746
+ "ariaLabel"
2747
+ ]
1749
2748
  },
1750
- properties: {
1751
- "attr.aria-expanded": "isOpen()",
1752
- "attr.aria-haspopup": "\"menu\"",
1753
- "attr.aria-controls": "overlayId()"
2749
+ {
2750
+ kind: "directive",
2751
+ type: TooltipDirective,
2752
+ selector: "[bxTooltip]",
2753
+ inputs: [
2754
+ "bxTooltip",
2755
+ "placement",
2756
+ "bxTooltipTouch",
2757
+ "bxTooltipHover"
2758
+ ]
2759
+ },
2760
+ {
2761
+ kind: "directive",
2762
+ type: TruncateDirective,
2763
+ selector: "[bxTruncate]",
2764
+ inputs: ["bxTruncate"],
2765
+ outputs: ["truncatedChange"],
2766
+ exportAs: ["bxTruncate"]
2767
+ },
2768
+ {
2769
+ kind: "directive",
2770
+ type: BxSurfaceDirective,
2771
+ selector: "[bxSurface]",
2772
+ inputs: [
2773
+ "bxSurfaceInteractive",
2774
+ "bxSurfaceGlassiness",
2775
+ "bxSurfaceEmission",
2776
+ "bxSurfaceFocusEmission",
2777
+ "bxReducedTransparency"
2778
+ ],
2779
+ exportAs: ["bxSurface"]
1754
2780
  }
1755
- },
1756
- exportAs: ["bxDropdown"],
1757
- ngImport: i0
2781
+ ],
2782
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
1758
2783
  });
1759
2784
  };
1760
2785
  i0.ɵɵngDeclareClassMetadata({
1761
2786
  minVersion: "12.0.0",
1762
2787
  version: "22.2.3",
1763
2788
  ngImport: i0,
1764
- type: DropdownDirective,
2789
+ type: Tag,
1765
2790
  decorators: [{
1766
- type: Directive,
2791
+ type: Component,
1767
2792
  args: [{
1768
- selector: "[bxDropdown]",
1769
- exportAs: "bxDropdown",
1770
- standalone: true,
2793
+ selector: "bx-tag",
2794
+ imports: [
2795
+ Icon,
2796
+ TooltipDirective,
2797
+ TruncateDirective,
2798
+ BxSurfaceDirective
2799
+ ],
2800
+ changeDetection: ChangeDetectionStrategy.OnPush,
1771
2801
  host: {
1772
- "[attr.aria-expanded]": "isOpen()",
1773
- "[attr.aria-haspopup]": "\"menu\"",
1774
- "[attr.aria-controls]": "overlayId()"
1775
- }
2802
+ "[style.--bx-tag-role-text]": "palette().text",
2803
+ "[style.--bx-tag-role-fill]": "palette().fill",
2804
+ "[style.--bx-tag-role-on-fill]": "palette().onFill",
2805
+ "[style.--bx-tag-role-tonal]": "palette().tonal",
2806
+ "[style.--bx-tag-role-border]": "palette().border"
2807
+ },
2808
+ template: "<span class=\"bx-tag\" bxSurface [bxSurfaceInteractive]=\"false\"\n [class.is-filled]=\"resolvedVariant() === 'filled'\" [class.is-outlined]=\"resolvedVariant() === 'outlined'\"\n [class.is-small]=\"resolvedSize() === 'small'\" [class.is-disabled]=\"disabled()\" [class.is-number-only]=\"isNumberOnly()\"\n [attr.aria-disabled]=\"disabled() ? 'true' : null\" [attr.role]=\"resolvedAriaLabel() ? 'group' : null\" [attr.aria-label]=\"resolvedAriaLabel() || null\"\n [attr.tabindex]=\"resolvedTooltip() && focusable() ? 0 : null\" [bxTooltip]=\"resolvedTooltip()\" [placement]=\"tooltipPlacement()\" bxTooltipTouch=\"longpress\">\n @if (resolvedLeadingIcon(); as icon) { <bx-icon [name]=\"icon\" [size]=\"resolvedIconSize()\" /> }\n @if (resolvedLeadingNumber()) { <span class=\"bx-tag-number\">{{ resolvedLeadingNumber() }}</span> }\n @if (resolvedText()) { <span class=\"bx-tag-text\" bxTruncate>{{ resolvedText() }}</span> }\n @if (resolvedTrailingNumber()) { <span class=\"bx-tag-number\">{{ resolvedTrailingNumber() }}</span> }\n @if (resolvedTrailingIcon(); as icon) { <bx-icon [name]=\"icon\" [size]=\"resolvedIconSize()\" /> }\n</span>\n",
2809
+ styles: [":host{display:inline-flex;min-inline-size:0;max-inline-size:100%;vertical-align:middle}.bx-tag{--bx-glass-surface: var(--bx-tag-background, var(--bx-tag-role-tonal));--bx-glass-text: var(--bx-tag-color, var(--bx-tag-role-text));--bx-glass-edge: var(--bx-tag-border, var(--bx-tag-role-border));--bx-glass-radius: var(--bx-tag-radius, .25rem);--bx-glass-shadow: var(--bx-tag-shadow, none);position:relative;display:inline-flex;align-items:center;justify-content:center;min-inline-size:0;max-inline-size:100%;box-sizing:border-box;gap:var(--bx-tag-gap, .25rem);padding:var(--bx-tag-padding, .25rem .5rem);border:1px solid var(--bx-glass-edge);border-radius:var(--bx-glass-radius);background:var(--bx-glass-surface);color:var(--bx-glass-text);font:inherit;font-size:var(--bx-tag-font-size, .8125rem);line-height:1.4;white-space:nowrap}.bx-tag.is-filled{--bx-glass-surface: var(--bx-tag-background, var(--bx-tag-role-fill));--bx-glass-text: var(--bx-tag-color, var(--bx-tag-role-on-fill));--bx-glass-min-opacity: var(--bx-tag-fill-opacity, .85)}.bx-tag.is-outlined{--bx-glass-surface: var(--bx-tag-background, var(--bx-bg-surface));--bx-glass-opacity: var(--bx-tag-outline-opacity, .12)}.bx-tag.is-small{font-size:var(--bx-tag-font-size, .75rem);padding-block:.125rem}.bx-tag.is-disabled{opacity:var(--bx-tag-disabled-opacity, .5)}.bx-tag.is-number-only{--bx-glass-radius: 50%;inline-size:max-content;min-inline-size:var(--bx-tag-number-size, 1.875rem);aspect-ratio:1;padding:var(--bx-tag-number-padding, .35em)}.bx-tag.is-number-only.is-small{min-inline-size:var(--bx-tag-number-size, 1.5rem)}.bx-tag:focus-visible{outline:2px solid var(--bx-border-brand);outline-offset:2px}.bx-tag-number{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;min-inline-size:1.1em;padding-inline:.25em;border-radius:var(--bx-tag-counter-radius, .25rem);background:var(--bx-tag-counter-background, color-mix(in srgb, currentcolor 12%, transparent));font-variant-numeric:tabular-nums}.is-number-only .bx-tag-number{background:transparent;padding:0}@media(forced-colors:active){.bx-tag.is-disabled{color:GrayText;border-color:GrayText;opacity:1}}\n"]
1776
2810
  }]
1777
2811
  }],
1778
- ctorParameters: () => [],
1779
2812
  propDecorators: {
1780
- bxDropdown: [{
2813
+ textOverflow: [{
2814
+ type: i0.ViewChild,
2815
+ args: [i0.forwardRef(() => TruncateDirective), { isSignal: true }]
2816
+ }],
2817
+ text: [{
1781
2818
  type: i0.Input,
1782
2819
  args: [{
1783
2820
  isSignal: true,
1784
- alias: "bxDropdown",
1785
- required: true
2821
+ alias: "text",
2822
+ required: false
1786
2823
  }]
1787
2824
  }],
1788
- placement: [{
2825
+ config: [{
1789
2826
  type: i0.Input,
1790
2827
  args: [{
1791
2828
  isSignal: true,
1792
- alias: "placement",
2829
+ alias: "config",
1793
2830
  required: false
1794
2831
  }]
1795
2832
  }],
1796
- bxTransition: [{
2833
+ color: [{
1797
2834
  type: i0.Input,
1798
2835
  args: [{
1799
2836
  isSignal: true,
1800
- alias: "bxTransition",
2837
+ alias: "color",
1801
2838
  required: false
1802
2839
  }]
1803
2840
  }],
1804
- toggle: [{
1805
- type: HostListener,
1806
- args: ["click", ["$event"]]
2841
+ variant: [{
2842
+ type: i0.Input,
2843
+ args: [{
2844
+ isSignal: true,
2845
+ alias: "variant",
2846
+ required: false
2847
+ }]
1807
2848
  }],
1808
- onTriggerKeydown: [{
1809
- type: HostListener,
1810
- args: ["keydown", ["$event"]]
2849
+ size: [{
2850
+ type: i0.Input,
2851
+ args: [{
2852
+ isSignal: true,
2853
+ alias: "size",
2854
+ required: false
2855
+ }]
1811
2856
  }],
1812
- onDocumentClick: [{
1813
- type: HostListener,
1814
- args: ["document:click", ["$event"]]
1815
- }]
1816
- }
1817
- });
1818
- var BxOverlayContextDirective = class BxOverlayContextDirective {
1819
- bxOverlayContext = input({}, ...ngDevMode ? [{ debugName: "bxOverlayContext" }] : /* istanbul ignore next */ []);
1820
- get useTopLayer() {
1821
- return this.bxOverlayContext().useTopLayer;
1822
- }
1823
- static ɵfac = i0.ɵɵngDeclareFactory({
1824
- minVersion: "12.0.0",
1825
- version: "22.2.3",
1826
- ngImport: i0,
1827
- type: BxOverlayContextDirective,
1828
- deps: [],
1829
- target: i0.ɵɵFactoryTarget.Directive
1830
- });
1831
- static ɵdir = i0.ɵɵngDeclareDirective({
1832
- minVersion: "17.1.0",
1833
- version: "22.2.3",
1834
- type: BxOverlayContextDirective,
1835
- isStandalone: true,
1836
- selector: "[bxOverlayContext]",
1837
- inputs: { bxOverlayContext: {
1838
- classPropertyName: "bxOverlayContext",
1839
- publicName: "bxOverlayContext",
1840
- isSignal: true,
1841
- isRequired: false,
1842
- transformFunction: null
1843
- } },
1844
- providers: [{
1845
- provide: BX_OVERLAY_CONTEXT,
1846
- useExisting: forwardRef(() => BxOverlayContextDirective)
2857
+ disabled: [{
2858
+ type: i0.Input,
2859
+ args: [{
2860
+ isSignal: true,
2861
+ alias: "disabled",
2862
+ required: false
2863
+ }]
1847
2864
  }],
1848
- ngImport: i0
1849
- });
1850
- };
1851
- i0.ɵɵngDeclareClassMetadata({
1852
- minVersion: "12.0.0",
1853
- version: "22.2.3",
1854
- ngImport: i0,
1855
- type: BxOverlayContextDirective,
1856
- decorators: [{
1857
- type: Directive,
1858
- args: [{
1859
- selector: "[bxOverlayContext]",
1860
- standalone: true,
1861
- providers: [{
1862
- provide: BX_OVERLAY_CONTEXT,
1863
- useExisting: forwardRef(() => BxOverlayContextDirective)
2865
+ leadingIcon: [{
2866
+ type: i0.Input,
2867
+ args: [{
2868
+ isSignal: true,
2869
+ alias: "leadingIcon",
2870
+ required: false
2871
+ }]
2872
+ }],
2873
+ trailingIcon: [{
2874
+ type: i0.Input,
2875
+ args: [{
2876
+ isSignal: true,
2877
+ alias: "trailingIcon",
2878
+ required: false
2879
+ }]
2880
+ }],
2881
+ iconSize: [{
2882
+ type: i0.Input,
2883
+ args: [{
2884
+ isSignal: true,
2885
+ alias: "iconSize",
2886
+ required: false
2887
+ }]
2888
+ }],
2889
+ leadingNumber: [{
2890
+ type: i0.Input,
2891
+ args: [{
2892
+ isSignal: true,
2893
+ alias: "leadingNumber",
2894
+ required: false
2895
+ }]
2896
+ }],
2897
+ trailingNumber: [{
2898
+ type: i0.Input,
2899
+ args: [{
2900
+ isSignal: true,
2901
+ alias: "trailingNumber",
2902
+ required: false
2903
+ }]
2904
+ }],
2905
+ locale: [{
2906
+ type: i0.Input,
2907
+ args: [{
2908
+ isSignal: true,
2909
+ alias: "locale",
2910
+ required: false
2911
+ }]
2912
+ }],
2913
+ tooltip: [{
2914
+ type: i0.Input,
2915
+ args: [{
2916
+ isSignal: true,
2917
+ alias: "tooltip",
2918
+ required: false
2919
+ }]
2920
+ }],
2921
+ tooltipOnTruncate: [{
2922
+ type: i0.Input,
2923
+ args: [{
2924
+ isSignal: true,
2925
+ alias: "tooltipOnTruncate",
2926
+ required: false
2927
+ }]
2928
+ }],
2929
+ tooltipPlacement: [{
2930
+ type: i0.Input,
2931
+ args: [{
2932
+ isSignal: true,
2933
+ alias: "tooltipPlacement",
2934
+ required: false
2935
+ }]
2936
+ }],
2937
+ ariaLabel: [{
2938
+ type: i0.Input,
2939
+ args: [{
2940
+ isSignal: true,
2941
+ alias: "ariaLabel",
2942
+ required: false
2943
+ }]
2944
+ }],
2945
+ focusable: [{
2946
+ type: i0.Input,
2947
+ args: [{
2948
+ isSignal: true,
2949
+ alias: "focusable",
2950
+ required: false
1864
2951
  }]
1865
2952
  }]
1866
- }],
1867
- propDecorators: { bxOverlayContext: [{
1868
- type: i0.Input,
1869
- args: [{
1870
- isSignal: true,
1871
- alias: "bxOverlayContext",
1872
- required: false
1873
- }]
1874
- }] }
2953
+ }
1875
2954
  });
1876
- export { BX_OVERLAY_CONTEXT, BxOverlayContextDirective, ContextMenuDirective, DropdownDirective, Menu, MenuItem, Tab, TabContentDirective, Tabs, Tooltip, TooltipDirective };
2955
+ export { BX_OVERLAY_CONTEXT, BxOverlayContextDirective, ContextMenuDirective, DropdownDirective, LoadingIndicator, LoadingSpinner, Menu, MenuItem, ProgressBar, Tab, TabContentDirective, Tabs, Tag, Tooltip, TooltipDirective, TruncateDirective, TruncatedTextPipe, truncatedText };
1877
2956
 
1878
2957
  //# sourceMappingURL=filip.mazev-blocks-primitives.mjs.map