@eagami/ui 5.24.0 → 5.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, makeEnvironmentProviders, provideEnvironmentInitializer, inject, CSP_NONCE, signal, effect, computed, Injectable, input, ChangeDetectionStrategy, Component, HostBinding, Directive, model, output, Injector, afterNextRender, DestroyRef, viewChild, ElementRef, HostListener, forwardRef, Renderer2, ViewContainerRef, TemplateRef, untracked, ViewEncapsulation, contentChild, viewChildren, PLATFORM_ID, afterRenderEffect } from '@angular/core';
2
+ import { InjectionToken, makeEnvironmentProviders, provideEnvironmentInitializer, inject, CSP_NONCE, signal, effect, computed, Injectable, input, ChangeDetectionStrategy, Component, HostBinding, Directive, model, output, Injector, afterNextRender, DestroyRef, viewChild, ElementRef, HostListener, forwardRef, Renderer2, ViewContainerRef, TemplateRef, RendererStyleFlags2, untracked, ViewEncapsulation, contentChild, viewChildren, PLATFORM_ID, afterRenderEffect } from '@angular/core';
3
3
  import { NgClass, NgComponentOutlet, NgTemplateOutlet, isPlatformBrowser } from '@angular/common';
4
4
  import { NgControl, NG_VALUE_ACCESSOR } from '@angular/forms';
5
5
 
@@ -5645,6 +5645,14 @@ function resolveAriaTarget(host) {
5645
5645
  return host.querySelector(INTERACTIVE_SELECTOR) ?? host;
5646
5646
  }
5647
5647
 
5648
+ /** Gap between the trigger and the bubble. */
5649
+ const TRIGGER_GAP = 8;
5650
+ /** Matches the `--ea-tooltip-viewport-margin` fallback in `_tooltip.scss`. */
5651
+ const DEFAULT_VIEWPORT_MARGIN = 8;
5652
+ /** Keeps one axis inside the viewport, leaving `margin` at each edge. */
5653
+ function clampToViewport(value, size, viewport, margin) {
5654
+ return Math.min(Math.max(value, margin), Math.max(margin, viewport - size - margin));
5655
+ }
5648
5656
  /**
5649
5657
  * Attaches a positioned tooltip to its host element. Shows on hover and
5650
5658
  * focus, hides on leave/blur or Escape, and wires up `aria-describedby` so
@@ -5657,6 +5665,13 @@ function resolveAriaTarget(host) {
5657
5665
  * descendant of the host as well as the host itself. A host listener paired
5658
5666
  * with `eaTooltip` has to use `focusin` for the same reason: `focus` does not
5659
5667
  * bubble, so it never fires when the focus lands on a child.
5668
+ *
5669
+ * Bubbles never grow past the viewport: they clamp to it, minus
5670
+ * `--ea-tooltip-viewport-margin` on each side, and scroll whatever the clamp
5671
+ * cuts off. A clamped bubble takes pointer events so that scrollbar is
5672
+ * reachable, which also means it waits `dismissDelay` before hiding rather than
5673
+ * going the moment the pointer leaves the trigger. Bubbles that fit stay
5674
+ * display-only.
5660
5675
  */
5661
5676
  class TooltipDirective {
5662
5677
  el = inject(ElementRef);
@@ -5666,11 +5681,23 @@ class TooltipDirective {
5666
5681
  ...(ngDevMode ? [{ debugName: "eaTooltip" }] : /* istanbul ignore next */ []));
5667
5682
  tooltipPosition = input('top', /* @ts-ignore */
5668
5683
  ...(ngDevMode ? [{ debugName: "tooltipPosition" }] : /* istanbul ignore next */ []));
5669
- /** Max width in px; the text wraps at this width. Clamped to a 50px floor. */
5684
+ /**
5685
+ * Max width in px; the text wraps at this width. Clamped to a 50px floor, and
5686
+ * to the viewport, which no value can push the bubble past.
5687
+ */
5670
5688
  maxWidth = input(200, /* @ts-ignore */
5671
5689
  ...(ngDevMode ? [{ debugName: "maxWidth" }] : /* istanbul ignore next */ []));
5690
+ /**
5691
+ * Grace period in ms before a bubble the viewport clamp made scrollable hides
5692
+ * after the pointer leaves, long enough to cross the gap onto the bubble and
5693
+ * reach its scrollbar. Bubbles that fit hide immediately.
5694
+ */
5695
+ dismissDelay = input(150, /* @ts-ignore */
5696
+ ...(ngDevMode ? [{ debugName: "dismissDelay" }] : /* istanbul ignore next */ []));
5672
5697
  tooltipEl = null;
5673
5698
  templateView = null;
5699
+ scrollable = false;
5700
+ hideTimer = null;
5674
5701
  tooltipId = `ea-tooltip-${Math.random().toString(36).slice(2, 9)}`;
5675
5702
  // Touch devices fire `mouseenter` on tap but never fire `mouseleave` until
5676
5703
  // the user taps elsewhere, leaving hover-driven tooltips latched open. Track
@@ -5681,7 +5708,8 @@ class TooltipDirective {
5681
5708
  ? window.matchMedia('(hover: hover)')
5682
5709
  : null;
5683
5710
  showHandler = () => this.show();
5684
- hideHandler = () => this.hide();
5711
+ hideHandler = () => this.requestHide();
5712
+ bubbleEnterHandler = () => this.cancelPendingHide();
5685
5713
  /* `:focus-visible` is supported in every targeted browser (Chrome, Firefox,
5686
5714
  Safari, Edge). Feature-detect so non-browser test environments (jsdom)
5687
5715
  fall back to always-on-focus behaviour rather than never showing. */
@@ -5765,7 +5793,12 @@ class TooltipDirective {
5765
5793
  }
5766
5794
  }
5767
5795
  show() {
5768
- if (this.tooltipEl || !this.eaTooltip()) {
5796
+ if (this.tooltipEl) {
5797
+ // The pointer came back to the trigger before a scheduled hide fired
5798
+ this.cancelPendingHide();
5799
+ return;
5800
+ }
5801
+ if (!this.eaTooltip()) {
5769
5802
  return;
5770
5803
  }
5771
5804
  this.tooltipEl = this.renderer.createElement('div');
@@ -5786,10 +5819,13 @@ class TooltipDirective {
5786
5819
  }
5787
5820
  const maxWidth = this.maxWidth();
5788
5821
  if (maxWidth != null) {
5789
- this.renderer.setStyle(this.tooltipEl, 'max-width', `${Math.max(50, maxWidth)}px`);
5790
- this.renderer.setStyle(this.tooltipEl, 'white-space', 'normal');
5822
+ this.renderer.setStyle(this.tooltipEl, '--ea-tooltip-max-width', `${Math.max(50, maxWidth)}px`, RendererStyleFlags2.DashCase);
5823
+ this.renderer.addClass(this.tooltipEl, 'ea-tooltip--wrapping');
5791
5824
  }
5792
5825
  this.renderer.appendChild(document.body, this.tooltipEl);
5826
+ // Inert until the bubble turns out to be scrollable and takes the pointer
5827
+ this.tooltipEl.addEventListener('mouseenter', this.bubbleEnterHandler);
5828
+ this.tooltipEl.addEventListener('mouseleave', this.hideHandler);
5793
5829
  // Before any measuring below: a trigger inside a modal needs its bubble in
5794
5830
  // the top layer to be visible at all, and a promoted bubble only has layout
5795
5831
  // once shown.
@@ -5816,15 +5852,38 @@ class TooltipDirective {
5816
5852
  return;
5817
5853
  }
5818
5854
  const style = getComputedStyle(this.tooltipEl);
5855
+ const borders = parseFloat(style.borderLeftWidth) + parseFloat(style.borderRightWidth);
5856
+ // Whatever the border box holds beyond its content box: the borders, plus a
5857
+ // scrollbar if the height clamp put one there. Both have to stay outside the
5858
+ // width we pin to the text, or the text reflows and overflows sideways
5859
+ const outsideContent = Math.max(0, this.tooltipEl.offsetWidth - this.tooltipEl.clientWidth);
5819
5860
  const horizontalChrome = style.boxSizing === 'border-box'
5820
- ? parseFloat(style.paddingLeft) +
5821
- parseFloat(style.paddingRight) +
5822
- parseFloat(style.borderLeftWidth) +
5823
- parseFloat(style.borderRightWidth)
5824
- : 0;
5861
+ ? parseFloat(style.paddingLeft) + parseFloat(style.paddingRight) + outsideContent
5862
+ : Math.max(0, outsideContent - borders);
5825
5863
  this.renderer.setStyle(this.tooltipEl, 'width', `${Math.ceil(textWidth + horizontalChrome)}px`);
5826
5864
  }
5865
+ /* A scrollable bubble has to be reachable, so leaving the trigger only
5866
+ schedules the hide and moving onto the bubble in time cancels it. A bubble
5867
+ that fits shows nothing the pointer needs, so it goes straight away. */
5868
+ requestHide() {
5869
+ if (!this.scrollable) {
5870
+ this.hide();
5871
+ return;
5872
+ }
5873
+ this.cancelPendingHide();
5874
+ this.hideTimer = setTimeout(() => {
5875
+ this.hideTimer = null;
5876
+ this.hide();
5877
+ }, Math.max(0, this.dismissDelay()));
5878
+ }
5879
+ cancelPendingHide() {
5880
+ if (this.hideTimer !== null) {
5881
+ clearTimeout(this.hideTimer);
5882
+ this.hideTimer = null;
5883
+ }
5884
+ }
5827
5885
  hide() {
5886
+ this.cancelPendingHide();
5828
5887
  this.detachRepositionListeners();
5829
5888
  if (this.rafId !== null) {
5830
5889
  cancelAnimationFrame(this.rafId);
@@ -5835,6 +5894,7 @@ class TooltipDirective {
5835
5894
  leaveTopLayer(this.tooltipEl);
5836
5895
  this.tooltipEl.remove();
5837
5896
  this.tooltipEl = null;
5897
+ this.scrollable = false;
5838
5898
  this.templateView?.destroy();
5839
5899
  this.templateView = null;
5840
5900
  this.removeDescribedBy();
@@ -5894,18 +5954,21 @@ class TooltipDirective {
5894
5954
  const hostRect = this.el.nativeElement.getBoundingClientRect();
5895
5955
  /* Hide if the trigger itself has scrolled behind a sticky/fixed ancestor
5896
5956
  (typical app-header pattern) to keep the tooltip from tracking the
5897
- trigger's coordinates into the header chrome. `elementFromPoint`
5898
- ignores the tooltip (it sets `pointer-events: none`), so the hit-test
5899
- reflects what the user actually sees at the trigger's centre. Also
5900
- covers fully off-screen triggers without a separate viewport check.
5901
- Feature-detected so jsdom (no `elementFromPoint`) and SSR skip the
5902
- check rather than erroring. */
5957
+ trigger's coordinates into the header chrome. A display-only bubble is
5958
+ invisible to `elementFromPoint` (`pointer-events: none`), so the hit-test
5959
+ reflects what the user actually sees at the trigger's centre; a scrollable
5960
+ one is not, and finding it there means the trigger is still on screen with
5961
+ its own bubble over it, not chrome. Also covers fully off-screen triggers
5962
+ without a separate viewport check. Feature-detected so jsdom (no
5963
+ `elementFromPoint`) and SSR skip the check rather than erroring. */
5903
5964
  const canHitTest = typeof document?.elementFromPoint === 'function';
5904
5965
  if (canHitTest) {
5905
5966
  const cx = hostRect.left + hostRect.width / 2;
5906
5967
  const cy = hostRect.top + hostRect.height / 2;
5907
5968
  const topmost = document.elementFromPoint(cx, cy);
5908
- if (!topmost || !this.el.nativeElement.contains(topmost)) {
5969
+ const visible = topmost &&
5970
+ (this.el.nativeElement.contains(topmost) || this.tooltipEl.contains(topmost));
5971
+ if (!visible) {
5909
5972
  this.hide();
5910
5973
  return;
5911
5974
  }
@@ -5913,17 +5976,25 @@ class TooltipDirective {
5913
5976
  // The bubble lives on <body>, escaping the host's dir context, so mirror
5914
5977
  // the host's resolved direction onto it.
5915
5978
  this.renderer.setAttribute(this.tooltipEl, 'dir', isRtl(this.el.nativeElement) ? 'rtl' : 'ltr');
5979
+ // Read after the stylesheet's clamp has applied, so a bubble the viewport cut
5980
+ // down is placed at the size it actually renders at
5916
5981
  const tooltipRect = this.tooltipEl.getBoundingClientRect();
5917
- /* Defer placement math to the shared popover positioning helper. `flip:
5918
- false` keeps the tooltip on the requested side, only nudging inward at
5919
- the edges: the caret is centered on the host and would point at empty
5920
- space if we flipped. `margin: 8` keeps breathing room between the bubble
5921
- and the viewport edge. */
5922
- const placed = computePopoverPosition(hostRect, { width: tooltipRect.width, height: tooltipRect.height }, {
5982
+ const viewport = {
5923
5983
  width: document.documentElement.clientWidth,
5924
5984
  height: document.documentElement.clientHeight,
5925
- }, { placement: this.tooltipPosition(), offset: 8, flip: false, margin: 8 });
5926
- const { top, left } = placed;
5985
+ };
5986
+ const margin = this.viewportMargin();
5987
+ /* Defer placement math to the shared popover positioning helper. `flip:
5988
+ false` keeps the tooltip on the side the consumer asked for, nudging it
5989
+ inward at the edges rather than jumping across the trigger mid-hover. */
5990
+ const placed = computePopoverPosition(hostRect, { width: tooltipRect.width, height: tooltipRect.height }, viewport, { placement: this.tooltipPosition(), offset: TRIGGER_GAP, flip: false, margin });
5991
+ /* The helper leaves the placement axis alone so a panel too tall for the
5992
+ space beside its anchor can overflow and scroll with the page. A bubble
5993
+ cannot: it is clamped to the viewport and fixed there, so anything pushed
5994
+ past an edge is simply unreachable. Pin both axes and accept that a bubble
5995
+ as tall as the viewport ends up over its own trigger. */
5996
+ const left = clampToViewport(placed.left, tooltipRect.width, viewport.width, margin);
5997
+ const top = clampToViewport(placed.top, tooltipRect.height, viewport.height, margin);
5927
5998
  /* Hide if the calculated bubble would render on top of a sticky/fixed
5928
5999
  overlay (typically the app header). Catches the case where the trigger
5929
6000
  is visible just below the header but a `position: top` tooltip would
@@ -5935,7 +6006,9 @@ class TooltipDirective {
5935
6006
  const tcx = left + tooltipRect.width / 2;
5936
6007
  const tcy = top + tooltipRect.height / 2;
5937
6008
  const underBubble = document.elementFromPoint(tcx, tcy);
5938
- if (underBubble && !this.el.nativeElement.contains(underBubble)) {
6009
+ if (underBubble &&
6010
+ !this.el.nativeElement.contains(underBubble) &&
6011
+ !this.tooltipEl.contains(underBubble)) {
5939
6012
  let cursor = underBubble;
5940
6013
  while (cursor && cursor !== document.body) {
5941
6014
  /* A fixed / sticky container that also holds the trigger (a modal
@@ -5955,16 +6028,47 @@ class TooltipDirective {
5955
6028
  }
5956
6029
  this.renderer.setStyle(this.tooltipEl, 'top', `${top}px`);
5957
6030
  this.renderer.setStyle(this.tooltipEl, 'left', `${left}px`);
6031
+ this.syncScrollable();
6032
+ }
6033
+ /* The stylesheet's viewport cap and the margin the bubble is placed against
6034
+ have to agree, so both read the same token. */
6035
+ viewportMargin() {
6036
+ if (!this.tooltipEl) {
6037
+ return DEFAULT_VIEWPORT_MARGIN;
6038
+ }
6039
+ const declared = parseFloat(getComputedStyle(this.tooltipEl).getPropertyValue('--ea-tooltip-viewport-margin'));
6040
+ return Number.isFinite(declared) ? declared : DEFAULT_VIEWPORT_MARGIN;
6041
+ }
6042
+ /* Content the clamp cut off is only reachable once the bubble takes the
6043
+ pointer. Re-checked on every reposition, since a resize can bring the cap
6044
+ into play or take it back out under a bubble that is already open. */
6045
+ syncScrollable() {
6046
+ if (!this.tooltipEl) {
6047
+ return;
6048
+ }
6049
+ // A pixel of slack: sub-pixel content rounds `scrollHeight` up on a box that fits
6050
+ const scrollable = this.tooltipEl.scrollHeight > this.tooltipEl.clientHeight + 1 ||
6051
+ this.tooltipEl.scrollWidth > this.tooltipEl.clientWidth + 1;
6052
+ if (scrollable === this.scrollable) {
6053
+ return;
6054
+ }
6055
+ this.scrollable = scrollable;
6056
+ if (scrollable) {
6057
+ this.renderer.addClass(this.tooltipEl, 'ea-tooltip--scrollable');
6058
+ }
6059
+ else {
6060
+ this.renderer.removeClass(this.tooltipEl, 'ea-tooltip--scrollable');
6061
+ }
5958
6062
  }
5959
6063
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: TooltipDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
5960
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.8", type: TooltipDirective, isStandalone: true, selector: "[eaTooltip]", inputs: { eaTooltip: { classPropertyName: "eaTooltip", publicName: "eaTooltip", isSignal: true, isRequired: true, transformFunction: null }, tooltipPosition: { classPropertyName: "tooltipPosition", publicName: "tooltipPosition", isSignal: true, isRequired: false, transformFunction: null }, maxWidth: { classPropertyName: "maxWidth", publicName: "maxWidth", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
6064
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.8", type: TooltipDirective, isStandalone: true, selector: "[eaTooltip]", inputs: { eaTooltip: { classPropertyName: "eaTooltip", publicName: "eaTooltip", isSignal: true, isRequired: true, transformFunction: null }, tooltipPosition: { classPropertyName: "tooltipPosition", publicName: "tooltipPosition", isSignal: true, isRequired: false, transformFunction: null }, maxWidth: { classPropertyName: "maxWidth", publicName: "maxWidth", isSignal: true, isRequired: false, transformFunction: null }, dismissDelay: { classPropertyName: "dismissDelay", publicName: "dismissDelay", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
5961
6065
  }
5962
6066
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: TooltipDirective, decorators: [{
5963
6067
  type: Directive,
5964
6068
  args: [{
5965
6069
  selector: '[eaTooltip]',
5966
6070
  }]
5967
- }], ctorParameters: () => [], propDecorators: { eaTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "eaTooltip", required: true }] }], tooltipPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooltipPosition", required: false }] }], maxWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxWidth", required: false }] }] } });
6071
+ }], ctorParameters: () => [], propDecorators: { eaTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "eaTooltip", required: true }] }], tooltipPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooltipPosition", required: false }] }], maxWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxWidth", required: false }] }], dismissDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissDelay", required: false }] }] } });
5968
6072
 
5969
6073
  const ZOOM_TOLERANCE = 1e-3;
5970
6074
  const OFFSET_TOLERANCE = 0.5;
@@ -6596,7 +6700,7 @@ class AvatarEditorComponent {
6596
6700
  ctx.clearRect(0, 0, canvas.width, canvas.height);
6597
6701
  }
6598
6702
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AvatarEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6599
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AvatarEditorComponent, isStandalone: true, selector: "ea-avatar-editor", inputs: { shape: { classPropertyName: "shape", publicName: "shape", isSignal: true, isRequired: false, transformFunction: null }, canvasSize: { classPropertyName: "canvasSize", publicName: "canvasSize", isSignal: true, isRequired: false, transformFunction: null }, currentSrc: { classPropertyName: "currentSrc", publicName: "currentSrc", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, maxFileSize: { classPropertyName: "maxFileSize", publicName: "maxFileSize", isSignal: true, isRequired: false, transformFunction: null }, minZoom: { classPropertyName: "minZoom", publicName: "minZoom", isSignal: true, isRequired: false, transformFunction: null }, maxZoom: { classPropertyName: "maxZoom", publicName: "maxZoom", isSignal: true, isRequired: false, transformFunction: null }, exportQuality: { classPropertyName: "exportQuality", publicName: "exportQuality", isSignal: true, isRequired: false, transformFunction: null }, exportType: { classPropertyName: "exportType", publicName: "exportType", isSignal: true, isRequired: false, transformFunction: null }, cropState: { classPropertyName: "cropState", publicName: "cropState", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { cropped: "cropped", fileSelected: "fileSelected", removed: "removed", errored: "errored", cropStateChanged: "cropStateChanged" }, viewQueries: [{ propertyName: "canvasEl", first: true, predicate: ["canvasEl"], descendants: true, isSignal: true }, { propertyName: "fileInputEl", first: true, predicate: ["fileInputEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"ea-avatar-editor\"\n [ngClass]=\"hostClasses()\"\n [style.--ea-avatar-editor-canvas.px]=\"canvasSize()\">\n <input\n #fileInputEl\n type=\"file\"\n class=\"ea-avatar-editor__file-input\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n [accept]=\"accept()\"\n (change)=\"onFileSelected($event)\" />\n\n <span\n class=\"ea-avatar-editor__visually-hidden\"\n [id]=\"instructionsId\">\n {{ i18n.messages().avatarEditor.canvasInstructions }}\n </span>\n\n <span\n class=\"ea-avatar-editor__visually-hidden\"\n role=\"alert\">\n {{ lastError() }}\n </span>\n\n @if (!hasImage() && !isLoading()) {\n <button\n type=\"button\"\n class=\"ea-avatar-editor__dropzone\"\n [style.width.px]=\"canvasSize()\"\n [style.height.px]=\"canvasSize()\"\n (click)=\"openFilePicker()\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\">\n <ea-icon-upload class=\"ea-avatar-editor__upload-icon\" />\n <span class=\"ea-avatar-editor__dropzone-text\">\n {{ i18n.messages().avatarEditor.dropzone }}\n </span>\n </button>\n }\n\n @if (hasImage() || isLoading()) {\n <div\n class=\"ea-avatar-editor__canvas-wrapper\"\n [style.width.px]=\"canvasSize()\"\n [style.height.px]=\"canvasSize()\"\n [attr.aria-busy]=\"isLoading() || null\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\">\n @if (isLoading()) {\n <ea-skeleton\n [variant]=\"shape() === 'circle' ? 'circle' : 'rect'\"\n [width]=\"canvasSize() + 'px'\"\n [height]=\"canvasSize() + 'px'\" />\n }\n\n @if (hasImage()) {\n <canvas\n #canvasEl\n class=\"ea-avatar-editor__canvas\"\n role=\"application\"\n tabindex=\"0\"\n [attr.aria-label]=\"i18n.messages().avatarEditor.canvas\"\n [attr.aria-describedby]=\"instructionsId\"\n [style.display]=\"isLoading() ? 'none' : 'block'\"\n [width]=\"canvasSize()\"\n [height]=\"canvasSize()\"\n (mousedown)=\"onMouseDown($event)\"\n (touchstart)=\"onTouchStart($event)\"\n (keydown)=\"onCanvasKeydown($event)\"></canvas>\n\n @if (!isLoading()) {\n <div\n class=\"ea-avatar-editor__canvas-overlay\"\n [class.ea-avatar-editor__canvas-overlay--on-light]=\"!isImageDark()\">\n <ea-icon-camera class=\"ea-avatar-editor__overlay-icon\" />\n <span>{{ i18n.messages().avatarEditor.change }}</span>\n </div>\n }\n }\n </div>\n }\n\n <div class=\"ea-avatar-editor__controls\">\n <button\n type=\"button\"\n class=\"ea-avatar-editor__icon-btn\"\n [eaTooltip]=\"i18n.messages().avatarEditor.revert\"\n [attr.aria-label]=\"i18n.messages().avatarEditor.revert\"\n [disabled]=\"!canRevert() || isLoading()\"\n (click)=\"revertImage()\">\n <ea-icon-rotate-ccw />\n </button>\n\n <button\n type=\"button\"\n class=\"ea-avatar-editor__icon-btn\"\n [eaTooltip]=\"i18n.messages().avatarEditor.zoomOut\"\n [attr.aria-label]=\"i18n.messages().avatarEditor.zoomOut\"\n [disabled]=\"!hasImage() || isLoading() || zoom() <= minZoom()\"\n (click)=\"setZoom(zoom() - 0.1)\">\n <ea-icon-minus />\n </button>\n\n <input\n type=\"range\"\n class=\"ea-avatar-editor__zoom-slider\"\n [min]=\"minZoom()\"\n [max]=\"maxZoom()\"\n step=\"0.01\"\n [value]=\"zoom()\"\n [disabled]=\"!hasImage() || isLoading()\"\n [attr.aria-label]=\"i18n.messages().avatarEditor.zoom\"\n (input)=\"onZoomInput($event)\" />\n\n <button\n type=\"button\"\n class=\"ea-avatar-editor__icon-btn\"\n [eaTooltip]=\"i18n.messages().avatarEditor.zoomIn\"\n [attr.aria-label]=\"i18n.messages().avatarEditor.zoomIn\"\n [disabled]=\"!hasImage() || isLoading() || zoom() >= maxZoom()\"\n (click)=\"setZoom(zoom() + 0.1)\">\n <ea-icon-plus />\n </button>\n\n <button\n type=\"button\"\n class=\"ea-avatar-editor__icon-btn ea-avatar-editor__icon-btn--danger\"\n [eaTooltip]=\"i18n.messages().avatarEditor.remove\"\n [attr.aria-label]=\"i18n.messages().avatarEditor.remove\"\n [disabled]=\"!hasImage() || isLoading()\"\n (click)=\"removeImage()\">\n <ea-icon-trash />\n </button>\n </div>\n</div>\n", styles: [".ea-avatar-editor{display:inline-flex;flex-direction:column;align-items:center;gap:.75em;font-family:var(--font-family-sans);font-size:clamp(.625rem,var(--ea-avatar-editor-canvas, 200px) * .075,.875rem)}.ea-avatar-editor__file-input,.ea-avatar-editor__visually-hidden{position:absolute;overflow:hidden;clip:rect(0,0,0,0);clip-path:inset(50%);width:1px;height:1px;padding:0;margin:-1px;white-space:nowrap;border:0}.ea-avatar-editor__dropzone{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5em;padding:1em;font-family:inherit;font-size:inherit;line-height:var(--line-height-normal);border:2px dashed var(--color-border-default);border-radius:var(--radius-lg);background-color:var(--color-bg-subtle);color:var(--color-text-tertiary);cursor:pointer;transition:var(--transition-colors)}.ea-avatar-editor__dropzone:hover{border-color:var(--color-border-focus);background-color:var(--color-state-hover);color:var(--color-text-secondary)}.ea-avatar-editor__dropzone:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}@media(forced-colors:active){.ea-avatar-editor__dropzone:focus-visible{outline:2px solid Highlight;outline-offset:2px}}.ea-avatar-editor--drag-over .ea-avatar-editor__dropzone{border-color:var(--color-border-focus);background-color:var(--color-brand-subtle);color:var(--color-brand-default)}.ea-avatar-editor--circle .ea-avatar-editor__dropzone{border-radius:var(--radius-full)}.ea-avatar-editor__upload-icon{width:2.25em;height:2.25em;opacity:.6}.ea-avatar-editor__dropzone-text{text-align:center}.ea-avatar-editor__canvas-wrapper{position:relative;overflow:hidden;border-radius:var(--radius-lg)}.ea-avatar-editor--circle .ea-avatar-editor__canvas-wrapper{border-radius:var(--radius-full)}.ea-avatar-editor__canvas{display:block;cursor:grab}.ea-avatar-editor__canvas:active{cursor:grabbing}.ea-avatar-editor__canvas-overlay{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-1);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--color-neutral-0);opacity:0;pointer-events:none;transition:opacity var(--duration-fast) var(--easing-default),color var(--duration-fast) var(--easing-default)}.ea-avatar-editor__canvas-overlay--on-light{color:var(--color-neutral-950)}.ea-avatar-editor__overlay-icon{width:1.75em;height:1.75em}.ea-avatar-editor__canvas-wrapper:hover .ea-avatar-editor__canvas-overlay{opacity:1}.ea-avatar-editor__controls{display:flex;align-items:center;gap:.5em}.ea-avatar-editor__icon-btn{position:relative;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:var(--ea-icon-button-size, 1.75em);height:var(--ea-icon-button-size, 1.75em);padding:0;border:none;border-radius:var(--radius-sm);background:none;color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-colors)}.ea-avatar-editor__icon-btn>*{font-size:1.25em}.ea-avatar-editor__icon-btn:after{content:\"\";position:absolute;top:50%;left:50%;width:max(100%,var(--ea-icon-button-target, 24px));height:max(100%,var(--ea-icon-button-target, 24px));transform:translate(-50%,-50%)}.ea-avatar-editor__icon-btn:hover{background-color:var(--color-state-hover);color:var(--color-text-primary)}.ea-avatar-editor__icon-btn:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}@media(forced-colors:active){.ea-avatar-editor__icon-btn:focus-visible{outline:2px solid Highlight;outline-offset:2px}}.ea-avatar-editor__icon-btn:disabled{cursor:not-allowed;opacity:.5}.ea-avatar-editor__icon-btn{border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);background-color:var(--color-bg-base);color:var(--color-text-primary)}.ea-avatar-editor__icon-btn:hover:not(:disabled){border-color:var(--color-border-focus)}.ea-avatar-editor__icon-btn--danger{color:var(--color-error-default)}.ea-avatar-editor__icon-btn--danger:hover:not(:disabled){border-color:var(--color-error-default);color:var(--color-error-default)}.ea-avatar-editor__zoom-slider{width:8em;height:.3em;border-radius:var(--radius-full);background:var(--color-neutral-200);appearance:none;cursor:pointer}.ea-avatar-editor__zoom-slider::-webkit-slider-thumb{width:1.15em;height:1.15em;border:2px solid var(--color-brand-default);border-radius:var(--radius-full);background:var(--color-bg-base);appearance:none;cursor:grab}.ea-avatar-editor__zoom-slider::-webkit-slider-thumb:active{cursor:grabbing}.ea-avatar-editor__zoom-slider::-moz-range-thumb{width:1.15em;height:1.15em;border:2px solid var(--color-brand-default);border-radius:var(--radius-full);background:var(--color-bg-base);cursor:grab}.ea-avatar-editor__zoom-slider::-moz-range-thumb:active{cursor:grabbing}.ea-avatar-editor__zoom-slider:focus-visible{outline:none}.ea-avatar-editor__zoom-slider:focus-visible::-webkit-slider-thumb{box-shadow:var(--shadow-focus-ring)}@media(forced-colors:active){.ea-avatar-editor__zoom-slider:focus-visible{outline:2px solid Highlight;outline-offset:2px}}.ea-avatar-editor__zoom-slider:disabled{opacity:.4;cursor:not-allowed}\n"], dependencies: [{ kind: "component", type: CameraIconComponent, selector: "ea-icon-camera" }, { kind: "component", type: MinusIconComponent, selector: "ea-icon-minus" }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: PlusIconComponent, selector: "ea-icon-plus" }, { kind: "component", type: RotateCcwIconComponent, selector: "ea-icon-rotate-ccw" }, { kind: "component", type: SkeletonComponent, selector: "ea-skeleton", inputs: ["variant", "width", "height", "animated"] }, { kind: "directive", type: TooltipDirective, selector: "[eaTooltip]", inputs: ["eaTooltip", "tooltipPosition", "maxWidth"] }, { kind: "component", type: TrashIconComponent, selector: "ea-icon-trash" }, { kind: "component", type: UploadIconComponent, selector: "ea-icon-upload" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
6703
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AvatarEditorComponent, isStandalone: true, selector: "ea-avatar-editor", inputs: { shape: { classPropertyName: "shape", publicName: "shape", isSignal: true, isRequired: false, transformFunction: null }, canvasSize: { classPropertyName: "canvasSize", publicName: "canvasSize", isSignal: true, isRequired: false, transformFunction: null }, currentSrc: { classPropertyName: "currentSrc", publicName: "currentSrc", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, maxFileSize: { classPropertyName: "maxFileSize", publicName: "maxFileSize", isSignal: true, isRequired: false, transformFunction: null }, minZoom: { classPropertyName: "minZoom", publicName: "minZoom", isSignal: true, isRequired: false, transformFunction: null }, maxZoom: { classPropertyName: "maxZoom", publicName: "maxZoom", isSignal: true, isRequired: false, transformFunction: null }, exportQuality: { classPropertyName: "exportQuality", publicName: "exportQuality", isSignal: true, isRequired: false, transformFunction: null }, exportType: { classPropertyName: "exportType", publicName: "exportType", isSignal: true, isRequired: false, transformFunction: null }, cropState: { classPropertyName: "cropState", publicName: "cropState", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { cropped: "cropped", fileSelected: "fileSelected", removed: "removed", errored: "errored", cropStateChanged: "cropStateChanged" }, viewQueries: [{ propertyName: "canvasEl", first: true, predicate: ["canvasEl"], descendants: true, isSignal: true }, { propertyName: "fileInputEl", first: true, predicate: ["fileInputEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"ea-avatar-editor\"\n [ngClass]=\"hostClasses()\"\n [style.--ea-avatar-editor-canvas.px]=\"canvasSize()\">\n <input\n #fileInputEl\n type=\"file\"\n class=\"ea-avatar-editor__file-input\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n [accept]=\"accept()\"\n (change)=\"onFileSelected($event)\" />\n\n <span\n class=\"ea-avatar-editor__visually-hidden\"\n [id]=\"instructionsId\">\n {{ i18n.messages().avatarEditor.canvasInstructions }}\n </span>\n\n <span\n class=\"ea-avatar-editor__visually-hidden\"\n role=\"alert\">\n {{ lastError() }}\n </span>\n\n @if (!hasImage() && !isLoading()) {\n <button\n type=\"button\"\n class=\"ea-avatar-editor__dropzone\"\n [style.width.px]=\"canvasSize()\"\n [style.height.px]=\"canvasSize()\"\n (click)=\"openFilePicker()\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\">\n <ea-icon-upload class=\"ea-avatar-editor__upload-icon\" />\n <span class=\"ea-avatar-editor__dropzone-text\">\n {{ i18n.messages().avatarEditor.dropzone }}\n </span>\n </button>\n }\n\n @if (hasImage() || isLoading()) {\n <div\n class=\"ea-avatar-editor__canvas-wrapper\"\n [style.width.px]=\"canvasSize()\"\n [style.height.px]=\"canvasSize()\"\n [attr.aria-busy]=\"isLoading() || null\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\">\n @if (isLoading()) {\n <ea-skeleton\n [variant]=\"shape() === 'circle' ? 'circle' : 'rect'\"\n [width]=\"canvasSize() + 'px'\"\n [height]=\"canvasSize() + 'px'\" />\n }\n\n @if (hasImage()) {\n <canvas\n #canvasEl\n class=\"ea-avatar-editor__canvas\"\n role=\"application\"\n tabindex=\"0\"\n [attr.aria-label]=\"i18n.messages().avatarEditor.canvas\"\n [attr.aria-describedby]=\"instructionsId\"\n [style.display]=\"isLoading() ? 'none' : 'block'\"\n [width]=\"canvasSize()\"\n [height]=\"canvasSize()\"\n (mousedown)=\"onMouseDown($event)\"\n (touchstart)=\"onTouchStart($event)\"\n (keydown)=\"onCanvasKeydown($event)\"></canvas>\n\n @if (!isLoading()) {\n <div\n class=\"ea-avatar-editor__canvas-overlay\"\n [class.ea-avatar-editor__canvas-overlay--on-light]=\"!isImageDark()\">\n <ea-icon-camera class=\"ea-avatar-editor__overlay-icon\" />\n <span>{{ i18n.messages().avatarEditor.change }}</span>\n </div>\n }\n }\n </div>\n }\n\n <div class=\"ea-avatar-editor__controls\">\n <button\n type=\"button\"\n class=\"ea-avatar-editor__icon-btn\"\n [eaTooltip]=\"i18n.messages().avatarEditor.revert\"\n [attr.aria-label]=\"i18n.messages().avatarEditor.revert\"\n [disabled]=\"!canRevert() || isLoading()\"\n (click)=\"revertImage()\">\n <ea-icon-rotate-ccw />\n </button>\n\n <button\n type=\"button\"\n class=\"ea-avatar-editor__icon-btn\"\n [eaTooltip]=\"i18n.messages().avatarEditor.zoomOut\"\n [attr.aria-label]=\"i18n.messages().avatarEditor.zoomOut\"\n [disabled]=\"!hasImage() || isLoading() || zoom() <= minZoom()\"\n (click)=\"setZoom(zoom() - 0.1)\">\n <ea-icon-minus />\n </button>\n\n <input\n type=\"range\"\n class=\"ea-avatar-editor__zoom-slider\"\n [min]=\"minZoom()\"\n [max]=\"maxZoom()\"\n step=\"0.01\"\n [value]=\"zoom()\"\n [disabled]=\"!hasImage() || isLoading()\"\n [attr.aria-label]=\"i18n.messages().avatarEditor.zoom\"\n (input)=\"onZoomInput($event)\" />\n\n <button\n type=\"button\"\n class=\"ea-avatar-editor__icon-btn\"\n [eaTooltip]=\"i18n.messages().avatarEditor.zoomIn\"\n [attr.aria-label]=\"i18n.messages().avatarEditor.zoomIn\"\n [disabled]=\"!hasImage() || isLoading() || zoom() >= maxZoom()\"\n (click)=\"setZoom(zoom() + 0.1)\">\n <ea-icon-plus />\n </button>\n\n <button\n type=\"button\"\n class=\"ea-avatar-editor__icon-btn ea-avatar-editor__icon-btn--danger\"\n [eaTooltip]=\"i18n.messages().avatarEditor.remove\"\n [attr.aria-label]=\"i18n.messages().avatarEditor.remove\"\n [disabled]=\"!hasImage() || isLoading()\"\n (click)=\"removeImage()\">\n <ea-icon-trash />\n </button>\n </div>\n</div>\n", styles: [".ea-avatar-editor{display:inline-flex;flex-direction:column;align-items:center;gap:.75em;font-family:var(--font-family-sans);font-size:clamp(.625rem,var(--ea-avatar-editor-canvas, 200px) * .075,.875rem)}.ea-avatar-editor__file-input,.ea-avatar-editor__visually-hidden{position:absolute;overflow:hidden;clip:rect(0,0,0,0);clip-path:inset(50%);width:1px;height:1px;padding:0;margin:-1px;white-space:nowrap;border:0}.ea-avatar-editor__dropzone{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5em;padding:1em;font-family:inherit;font-size:inherit;line-height:var(--line-height-normal);border:2px dashed var(--color-border-default);border-radius:var(--radius-lg);background-color:var(--color-bg-subtle);color:var(--color-text-tertiary);cursor:pointer;transition:var(--transition-colors)}.ea-avatar-editor__dropzone:hover{border-color:var(--color-border-focus);background-color:var(--color-state-hover);color:var(--color-text-secondary)}.ea-avatar-editor__dropzone:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}@media(forced-colors:active){.ea-avatar-editor__dropzone:focus-visible{outline:2px solid Highlight;outline-offset:2px}}.ea-avatar-editor--drag-over .ea-avatar-editor__dropzone{border-color:var(--color-border-focus);background-color:var(--color-brand-subtle);color:var(--color-brand-default)}.ea-avatar-editor--circle .ea-avatar-editor__dropzone{border-radius:var(--radius-full)}.ea-avatar-editor__upload-icon{width:2.25em;height:2.25em;opacity:.6}.ea-avatar-editor__dropzone-text{text-align:center}.ea-avatar-editor__canvas-wrapper{position:relative;overflow:hidden;border-radius:var(--radius-lg)}.ea-avatar-editor--circle .ea-avatar-editor__canvas-wrapper{border-radius:var(--radius-full)}.ea-avatar-editor__canvas{display:block;cursor:grab}.ea-avatar-editor__canvas:active{cursor:grabbing}.ea-avatar-editor__canvas-overlay{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-1);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--color-neutral-0);opacity:0;pointer-events:none;transition:opacity var(--duration-fast) var(--easing-default),color var(--duration-fast) var(--easing-default)}.ea-avatar-editor__canvas-overlay--on-light{color:var(--color-neutral-950)}.ea-avatar-editor__overlay-icon{width:1.75em;height:1.75em}.ea-avatar-editor__canvas-wrapper:hover .ea-avatar-editor__canvas-overlay{opacity:1}.ea-avatar-editor__controls{display:flex;align-items:center;gap:.5em}.ea-avatar-editor__icon-btn{position:relative;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:var(--ea-icon-button-size, 1.75em);height:var(--ea-icon-button-size, 1.75em);padding:0;border:none;border-radius:var(--radius-sm);background:none;color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-colors)}.ea-avatar-editor__icon-btn>*{font-size:1.25em}.ea-avatar-editor__icon-btn:after{content:\"\";position:absolute;top:50%;left:50%;width:max(100%,var(--ea-icon-button-target, 24px));height:max(100%,var(--ea-icon-button-target, 24px));transform:translate(-50%,-50%)}.ea-avatar-editor__icon-btn:hover{background-color:var(--color-state-hover);color:var(--color-text-primary)}.ea-avatar-editor__icon-btn:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}@media(forced-colors:active){.ea-avatar-editor__icon-btn:focus-visible{outline:2px solid Highlight;outline-offset:2px}}.ea-avatar-editor__icon-btn:disabled{cursor:not-allowed;opacity:.5}.ea-avatar-editor__icon-btn{border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);background-color:var(--color-bg-base);color:var(--color-text-primary)}.ea-avatar-editor__icon-btn:hover:not(:disabled){border-color:var(--color-border-focus)}.ea-avatar-editor__icon-btn--danger{color:var(--color-error-default)}.ea-avatar-editor__icon-btn--danger:hover:not(:disabled){border-color:var(--color-error-default);color:var(--color-error-default)}.ea-avatar-editor__zoom-slider{width:8em;height:.3em;border-radius:var(--radius-full);background:var(--color-neutral-200);appearance:none;cursor:pointer}.ea-avatar-editor__zoom-slider::-webkit-slider-thumb{width:1.15em;height:1.15em;border:2px solid var(--color-brand-default);border-radius:var(--radius-full);background:var(--color-bg-base);appearance:none;cursor:grab}.ea-avatar-editor__zoom-slider::-webkit-slider-thumb:active{cursor:grabbing}.ea-avatar-editor__zoom-slider::-moz-range-thumb{width:1.15em;height:1.15em;border:2px solid var(--color-brand-default);border-radius:var(--radius-full);background:var(--color-bg-base);cursor:grab}.ea-avatar-editor__zoom-slider::-moz-range-thumb:active{cursor:grabbing}.ea-avatar-editor__zoom-slider:focus-visible{outline:none}.ea-avatar-editor__zoom-slider:focus-visible::-webkit-slider-thumb{box-shadow:var(--shadow-focus-ring)}@media(forced-colors:active){.ea-avatar-editor__zoom-slider:focus-visible{outline:2px solid Highlight;outline-offset:2px}}.ea-avatar-editor__zoom-slider:disabled{opacity:.4;cursor:not-allowed}\n"], dependencies: [{ kind: "component", type: CameraIconComponent, selector: "ea-icon-camera" }, { kind: "component", type: MinusIconComponent, selector: "ea-icon-minus" }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: PlusIconComponent, selector: "ea-icon-plus" }, { kind: "component", type: RotateCcwIconComponent, selector: "ea-icon-rotate-ccw" }, { kind: "component", type: SkeletonComponent, selector: "ea-skeleton", inputs: ["variant", "width", "height", "animated"] }, { kind: "directive", type: TooltipDirective, selector: "[eaTooltip]", inputs: ["eaTooltip", "tooltipPosition", "maxWidth", "dismissDelay"] }, { kind: "component", type: TrashIconComponent, selector: "ea-icon-trash" }, { kind: "component", type: UploadIconComponent, selector: "ea-icon-upload" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
6600
6704
  }
6601
6705
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AvatarEditorComponent, decorators: [{
6602
6706
  type: Component,
@@ -13167,7 +13271,7 @@ class TagComponent {
13167
13271
  }
13168
13272
  }
13169
13273
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: TagComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
13170
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: TagComponent, isStandalone: true, selector: "ea-tag", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, removable: { classPropertyName: "removable", publicName: "removable", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, removeLabel: { classPropertyName: "removeLabel", publicName: "removeLabel", isSignal: true, isRequired: false, transformFunction: null }, maxWidth: { classPropertyName: "maxWidth", publicName: "maxWidth", isSignal: true, isRequired: false, transformFunction: null }, tooltip: { classPropertyName: "tooltip", publicName: "tooltip", isSignal: true, isRequired: false, transformFunction: null }, removeTabbable: { classPropertyName: "removeTabbable", publicName: "removeTabbable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { removed: "removed" }, viewQueries: [{ propertyName: "labelEl", first: true, predicate: ["labelEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<span\n class=\"ea-tag\"\n [ngClass]=\"hostClasses()\"\n [style.max-width.px]=\"maxWidth()\"\n [eaTooltip]=\"labelTooltip()\"\n [tooltipPosition]=\"tooltipPosition()\">\n <span\n #labelEl\n class=\"ea-tag__label\">\n <ng-content />\n </span>\n @if (removable()) {\n <button\n type=\"button\"\n class=\"ea-tag__remove\"\n [disabled]=\"disabled() || null\"\n [attr.tabindex]=\"removeTabbable() ? null : -1\"\n [attr.aria-label]=\"resolvedRemoveLabel()\"\n (click)=\"onRemove($event)\">\n <ea-icon-x />\n </button>\n }\n</span>\n", styles: ["ea-tag{display:inline-flex;vertical-align:middle;line-height:1}.ea-tag{display:inline-flex;align-items:center;gap:.25em;max-width:var(--ea-tag-max-width, none);padding:var(--ea-tag-padding-block, .25em) .5em;font-weight:var(--font-weight-medium);line-height:var(--line-height-none);white-space:nowrap;font-family:var(--font-family-sans);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-lg);background-color:var(--color-bg-subtle);color:var(--color-text-secondary);forced-color-adjust:none}.ea-tag--2xs{font-size:var(--font-size-2xs)}.ea-tag--xs{font-size:var(--font-size-xs)}.ea-tag--sm{font-size:var(--font-size-sm)}.ea-tag--md{font-size:var(--font-size-md)}.ea-tag--lg{font-size:var(--font-size-lg)}.ea-tag--xl{font-size:var(--font-size-xl)}.ea-tag--success{border-color:var(--color-success-muted);background-color:var(--color-success-subtle);color:var(--color-success-text)}.ea-tag--warning{border-color:var(--color-warning-muted);background-color:var(--color-warning-subtle);color:var(--color-warning-text)}.ea-tag--error{border-color:var(--color-error-muted);background-color:var(--color-error-subtle);color:var(--color-error-text)}.ea-tag--info{border-color:var(--color-info-muted);background-color:var(--color-info-subtle);color:var(--color-info-text)}.ea-tag--disabled{opacity:.6;cursor:not-allowed}.ea-tag__label{overflow:hidden;min-width:0;padding-block:.25em;margin-block:-.25em;text-overflow:ellipsis;white-space:nowrap}.ea-tag__remove{position:relative;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:var(--ea-icon-button-size, 1.75em);height:var(--ea-icon-button-size, 1.75em);padding:0;border:none;border-radius:var(--radius-sm);background:none;color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-colors)}.ea-tag__remove>*{font-size:1.25em}.ea-tag__remove:after{content:\"\";position:absolute;top:50%;left:50%;width:max(100%,var(--ea-icon-button-target, 24px));height:max(100%,var(--ea-icon-button-target, 24px));transform:translate(-50%,-50%)}.ea-tag__remove:hover{background-color:var(--color-state-hover);color:var(--color-text-primary)}.ea-tag__remove:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}@media(forced-colors:active){.ea-tag__remove:focus-visible{outline:2px solid Highlight;outline-offset:2px}}.ea-tag__remove:disabled{cursor:not-allowed;opacity:.5}.ea-tag__remove,.ea-tag__remove:hover{color:inherit}.ea-tag__remove ea-icon-x{pointer-events:none}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: TooltipDirective, selector: "[eaTooltip]", inputs: ["eaTooltip", "tooltipPosition", "maxWidth"] }, { kind: "component", type: XIconComponent, selector: "ea-icon-x" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
13274
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: TagComponent, isStandalone: true, selector: "ea-tag", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, removable: { classPropertyName: "removable", publicName: "removable", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, removeLabel: { classPropertyName: "removeLabel", publicName: "removeLabel", isSignal: true, isRequired: false, transformFunction: null }, maxWidth: { classPropertyName: "maxWidth", publicName: "maxWidth", isSignal: true, isRequired: false, transformFunction: null }, tooltip: { classPropertyName: "tooltip", publicName: "tooltip", isSignal: true, isRequired: false, transformFunction: null }, removeTabbable: { classPropertyName: "removeTabbable", publicName: "removeTabbable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { removed: "removed" }, viewQueries: [{ propertyName: "labelEl", first: true, predicate: ["labelEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<span\n class=\"ea-tag\"\n [ngClass]=\"hostClasses()\"\n [style.max-width.px]=\"maxWidth()\"\n [eaTooltip]=\"labelTooltip()\"\n [tooltipPosition]=\"tooltipPosition()\">\n <span\n #labelEl\n class=\"ea-tag__label\">\n <ng-content />\n </span>\n @if (removable()) {\n <button\n type=\"button\"\n class=\"ea-tag__remove\"\n [disabled]=\"disabled() || null\"\n [attr.tabindex]=\"removeTabbable() ? null : -1\"\n [attr.aria-label]=\"resolvedRemoveLabel()\"\n (click)=\"onRemove($event)\">\n <ea-icon-x />\n </button>\n }\n</span>\n", styles: ["ea-tag{display:inline-flex;vertical-align:middle;line-height:1}.ea-tag{display:inline-flex;align-items:center;gap:.25em;max-width:var(--ea-tag-max-width, none);padding:var(--ea-tag-padding-block, .25em) .5em;font-weight:var(--font-weight-medium);line-height:var(--line-height-none);white-space:nowrap;font-family:var(--font-family-sans);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-lg);background-color:var(--color-bg-subtle);color:var(--color-text-secondary);forced-color-adjust:none}.ea-tag--2xs{font-size:var(--font-size-2xs)}.ea-tag--xs{font-size:var(--font-size-xs)}.ea-tag--sm{font-size:var(--font-size-sm)}.ea-tag--md{font-size:var(--font-size-md)}.ea-tag--lg{font-size:var(--font-size-lg)}.ea-tag--xl{font-size:var(--font-size-xl)}.ea-tag--success{border-color:var(--color-success-muted);background-color:var(--color-success-subtle);color:var(--color-success-text)}.ea-tag--warning{border-color:var(--color-warning-muted);background-color:var(--color-warning-subtle);color:var(--color-warning-text)}.ea-tag--error{border-color:var(--color-error-muted);background-color:var(--color-error-subtle);color:var(--color-error-text)}.ea-tag--info{border-color:var(--color-info-muted);background-color:var(--color-info-subtle);color:var(--color-info-text)}.ea-tag--disabled{opacity:.6;cursor:not-allowed}.ea-tag__label{overflow:hidden;min-width:0;padding-block:.25em;margin-block:-.25em;text-overflow:ellipsis;white-space:nowrap}.ea-tag__remove{position:relative;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:var(--ea-icon-button-size, 1.75em);height:var(--ea-icon-button-size, 1.75em);padding:0;border:none;border-radius:var(--radius-sm);background:none;color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-colors)}.ea-tag__remove>*{font-size:1.25em}.ea-tag__remove:after{content:\"\";position:absolute;top:50%;left:50%;width:max(100%,var(--ea-icon-button-target, 24px));height:max(100%,var(--ea-icon-button-target, 24px));transform:translate(-50%,-50%)}.ea-tag__remove:hover{background-color:var(--color-state-hover);color:var(--color-text-primary)}.ea-tag__remove:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}@media(forced-colors:active){.ea-tag__remove:focus-visible{outline:2px solid Highlight;outline-offset:2px}}.ea-tag__remove:disabled{cursor:not-allowed;opacity:.5}.ea-tag__remove,.ea-tag__remove:hover{color:inherit}.ea-tag__remove ea-icon-x{pointer-events:none}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: TooltipDirective, selector: "[eaTooltip]", inputs: ["eaTooltip", "tooltipPosition", "maxWidth", "dismissDelay"] }, { kind: "component", type: XIconComponent, selector: "ea-icon-x" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
13171
13275
  }
13172
13276
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: TagComponent, decorators: [{
13173
13277
  type: Component,
@@ -13691,7 +13795,7 @@ class MultiSelectComponent {
13691
13795
  useExisting: forwardRef(() => MultiSelectComponent),
13692
13796
  multi: true,
13693
13797
  },
13694
- ], viewQueries: [{ propertyName: "wrapperEl", first: true, predicate: ["wrapperEl"], descendants: true, isSignal: true }, { propertyName: "triggerEl", first: true, predicate: ["triggerEl"], descendants: true, isSignal: true }, { propertyName: "searchEl", first: true, predicate: ["searchEl"], descendants: true, isSignal: true }, { propertyName: "listEl", first: true, predicate: ["listEl"], descendants: true, isSignal: true }, { propertyName: "optionLabelEls", predicate: ["optionLabelEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"ea-multi-select-field ea-multi-select-field--{{ size() }}\">\n @if (label(); as labelText) {\n <ea-field-label\n [text]=\"labelText\"\n [forId]=\"id()\"\n [labelId]=\"id() + '-label'\"\n [required]=\"required()\" />\n }\n\n <div class=\"ea-multi-select\">\n <div\n #wrapperEl\n class=\"ea-multi-select__trigger-wrapper\"\n [ngClass]=\"wrapperClasses()\"\n (click)=\"onTriggerAreaClick()\">\n <div\n #triggerEl\n class=\"ea-multi-select__trigger\"\n [ngClass]=\"triggerClasses()\"\n [id]=\"id()\"\n role=\"combobox\"\n [attr.tabindex]=\"isDisabled() ? -1 : 0\"\n [attr.aria-labelledby]=\"label() ? id() + '-label' : null\"\n [attr.aria-label]=\"label() ? null : (ariaLabel() ?? null)\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-controls]=\"isOpen() ? listboxId() : null\"\n [attr.aria-activedescendant]=\"isOpen() && !searchable() ? activeOptionId() : null\"\n [attr.aria-disabled]=\"isDisabled() || null\"\n [attr.aria-required]=\"required() || null\"\n [attr.aria-invalid]=\"hasError() || null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \"\n (keydown)=\"handleTriggerKeydown($event)\">\n <span class=\"ea-multi-select__trigger-content\">\n @if (!hasValue()) {\n <span class=\"ea-multi-select__trigger-placeholder\">\n <bdi>{{ resolvedPlaceholder() }}</bdi>\n </span>\n } @else {\n @for (opt of visibleChips(); track opt.value) {\n <ea-tag\n [size]=\"size()\"\n variant=\"default\"\n [maxWidth]=\"maxChipWidth()\"\n [removable]=\"!isDisabled() && !readonly()\"\n [removeTabbable]=\"false\"\n [removeLabel]=\"i18n.messages().multiSelect.removeOption(opt.label)\"\n (removed)=\"removeChip(opt)\">\n <span>{{ opt.label }}</span>\n </ea-tag>\n }\n @if (hiddenChipCount() > 0) {\n <span class=\"ea-multi-select__more\">+{{ hiddenChipCount() }}</span>\n }\n }\n </span>\n </div>\n @if (hasValue() && !isDisabled() && !readonly()) {\n <button\n type=\"button\"\n class=\"ea-multi-select__clear\"\n [attr.aria-label]=\"i18n.messages().multiSelect.clearAll\"\n (click)=\"clear($event)\">\n <ea-icon-x\n class=\"ea-multi-select__clear-icon\"\n aria-hidden=\"true\" />\n </button>\n }\n <ea-icon-chevron-down\n class=\"ea-multi-select__trigger-icon\"\n aria-hidden=\"true\" />\n </div>\n\n <ea-popover\n [anchor]=\"wrapperEl\"\n [open]=\"isOpen()\"\n placement=\"bottom-start\"\n [aria-label]=\"i18n.messages().multiSelect.dialogLabel\"\n [matchAnchorWidth]=\"true\"\n [maxWidth]=\"popoverMaxWidth()\"\n [closeOnEscape]=\"false\"\n scrollBehavior=\"reposition\"\n (closeRequested)=\"onPopoverCloseRequested()\">\n <div\n class=\"ea-multi-select__popover\"\n [ngClass]=\"menuClasses()\">\n @if (searchable()) {\n <div class=\"ea-multi-select__search\">\n <ea-icon-search\n class=\"ea-multi-select__search-icon\"\n aria-hidden=\"true\" />\n <input\n #searchEl\n type=\"text\"\n dir=\"auto\"\n class=\"ea-multi-select__search-input\"\n autocomplete=\"off\"\n [placeholder]=\"resolvedSearchPlaceholder()\"\n [value]=\"searchTerm()\"\n [attr.aria-controls]=\"listboxId()\"\n [attr.aria-activedescendant]=\"activeOptionId()\"\n (input)=\"onSearchInput($event)\"\n (keydown)=\"handlePopoverKeydown($event)\" />\n </div>\n }\n\n <ul\n #listEl\n class=\"ea-multi-select__list\"\n role=\"listbox\"\n aria-multiselectable=\"true\"\n [id]=\"listboxId()\"\n [attr.aria-label]=\"label() ?? ariaLabel() ?? null\">\n @if (selectAllVisible()) {\n <li\n class=\"ea-multi-select__option ea-multi-select__option--select-all\"\n [class.ea-multi-select__option--focused]=\"focusedIndex() === 0\"\n [id]=\"id() + '-opt-0'\"\n role=\"option\"\n [attr.aria-selected]=\"selectAllState() === 'all'\"\n [attr.aria-checked]=\"selectAllAriaChecked()\"\n (click)=\"onSelectAllClick()\">\n <ea-checkbox\n size=\"sm\"\n inert\n aria-hidden=\"true\"\n [checked]=\"selectAllState() === 'all'\"\n [indeterminate]=\"selectAllState() === 'some'\" />\n <span class=\"ea-multi-select__option-label\">\n {{ i18n.messages().multiSelect.selectAll }}\n </span>\n </li>\n }\n @for (group of renderedGroups(); track $index) {\n <li\n class=\"ea-multi-select__group\"\n [class.ea-multi-select__group--ruled]=\"group.rule\"\n role=\"presentation\">\n @if (group.label; as groupLabel) {\n <span\n class=\"ea-multi-select__group-label\"\n aria-hidden=\"true\">\n {{ groupLabel }}\n </span>\n }\n <ul\n class=\"ea-multi-select__group-options\"\n [attr.role]=\"grouped() ? 'group' : 'presentation'\"\n [attr.aria-label]=\"group.label ?? null\">\n @for (entry of group.options; track entry.option.value) {\n <li\n class=\"ea-multi-select__option\"\n [class.ea-multi-select__option--focused]=\"\n focusedIndex() === entry.index + selectAllOffset()\n \"\n [class.ea-multi-select__option--disabled]=\"entry.option.disabled\"\n [id]=\"id() + '-opt-' + (entry.index + selectAllOffset())\"\n role=\"option\"\n [attr.aria-selected]=\"selectedSet().has(entry.option.value)\"\n [attr.aria-disabled]=\"entry.option.disabled || null\"\n (click)=\"onOptionClick(entry.option, entry.index)\">\n <ea-checkbox\n size=\"sm\"\n inert\n aria-hidden=\"true\"\n [checked]=\"selectedSet().has(entry.option.value)\"\n [disabled]=\"!!entry.option.disabled\" />\n <span\n #optionLabelEl\n class=\"ea-multi-select__option-label\"\n [attr.data-value]=\"entry.option.value\"\n [eaTooltip]=\"\n clippedOptions().has(entry.option.value) ? entry.option.label : ''\n \">\n {{ entry.option.label }}\n </span>\n </li>\n }\n </ul>\n </li>\n }\n </ul>\n @if (filteredOptions().length === 0) {\n <div\n class=\"ea-multi-select__empty\"\n role=\"status\">\n {{ i18n.messages().multiSelect.searchEmpty }}\n </div>\n }\n </div>\n </ea-popover>\n </div>\n\n <ea-field-messages\n [id]=\"id()\"\n [error]=\"errorText()\"\n [hint]=\"showHint() ? hint() : null\" />\n</div>\n", styles: [".ea-multi-select-field{display:flex;flex-direction:column;gap:.375em;--ea-field-label-size: .875em;--ea-field-messages-size: .8125em}.ea-multi-select-field--2xs{font-size:var(--font-size-2xs)}.ea-multi-select-field--xs{font-size:var(--font-size-xs)}.ea-multi-select-field--sm{font-size:var(--font-size-sm)}.ea-multi-select-field--md{font-size:var(--font-size-md)}.ea-multi-select-field--lg{font-size:var(--font-size-lg)}.ea-multi-select-field--xl{font-size:var(--font-size-xl)}.ea-multi-select{position:relative}.ea-multi-select__trigger-wrapper{position:relative;display:flex;align-items:center;gap:.5em;width:100%;min-height:2.5em;padding:.375em .75em;border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);background-color:var(--color-bg-base);color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors),var(--transition-shadow)}.ea-multi-select__trigger-wrapper:has(ea-tag){padding-block:.125em}.ea-multi-select__trigger-wrapper:has(.ea-multi-select__trigger:focus-visible){box-shadow:var(--shadow-focus-ring)}@media(forced-colors:active){.ea-multi-select__trigger-wrapper:has(.ea-multi-select__trigger:focus-visible){outline:2px solid Highlight;outline-offset:2px}}.ea-multi-select__trigger-wrapper:has(.ea-multi-select__trigger--open){border-color:var(--color-border-focus);box-shadow:var(--shadow-focus-ring)}@media(forced-colors:active){.ea-multi-select__trigger-wrapper:has(.ea-multi-select__trigger--open){outline:2px solid Highlight;outline-offset:2px}}.ea-multi-select__trigger-wrapper:has(.ea-multi-select__trigger--error){border-color:var(--color-error-default)}.ea-multi-select__trigger-wrapper:has(.ea-multi-select__trigger--error.ea-multi-select__trigger--open){box-shadow:var(--shadow-focus-ring-error)}@media(forced-colors:active){.ea-multi-select__trigger-wrapper:has(.ea-multi-select__trigger--error.ea-multi-select__trigger--open){outline:2px solid Highlight;outline-offset:2px}}.ea-multi-select__trigger-wrapper:has(.ea-multi-select__trigger--disabled){background-color:var(--color-bg-muted);opacity:.6;cursor:not-allowed}.ea-multi-select__trigger-wrapper:has(.ea-multi-select__trigger--readonly){cursor:default}.ea-multi-select__trigger-wrapper:has(.ea-multi-select__trigger--readonly:focus-visible){border-color:var(--color-border-focus);box-shadow:none}@media(forced-colors:active){.ea-multi-select__trigger-wrapper:has(.ea-multi-select__trigger--readonly:focus-visible){outline:2px solid Highlight;outline-offset:2px}}.ea-multi-select__trigger{display:flex;align-items:center;flex:1;min-width:0;text-align:start;font-family:var(--font-family-sans);cursor:pointer}.ea-multi-select__trigger:focus-visible{outline:none}.ea-multi-select__trigger--disabled{cursor:not-allowed}.ea-multi-select__trigger--readonly{cursor:default}.ea-multi-select__trigger-content{display:flex;flex-wrap:nowrap;align-items:center;gap:var(--space-1);flex:1;min-width:0;overflow-x:auto;scrollbar-width:thin}.ea-multi-select__trigger-content ea-tag{flex-shrink:0;--ea-tag-padding-block: 0}.ea-multi-select__trigger-placeholder{color:var(--color-text-tertiary)}.ea-multi-select__trigger-icon{flex-shrink:0;width:1em;height:1em;color:var(--color-text-secondary);transition:var(--transition-transform)}.ea-multi-select__trigger-wrapper:has(.ea-multi-select__trigger--open) .ea-multi-select__trigger-icon{transform:rotate(180deg)}.ea-multi-select__more{display:inline-flex;flex-shrink:0;align-items:center;padding:0 var(--space-1-5);border-radius:var(--radius-lg);background-color:var(--color-bg-muted);font-size:.85em;font-weight:var(--font-weight-medium);color:var(--color-text-secondary)}.ea-multi-select__clear{position:relative;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:var(--ea-icon-button-size, 1.75em);height:var(--ea-icon-button-size, 1.75em);padding:0;border:none;border-radius:var(--radius-sm);background:none;color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-colors)}.ea-multi-select__clear>*{font-size:1.25em}.ea-multi-select__clear:after{content:\"\";position:absolute;top:50%;left:50%;width:max(100%,var(--ea-icon-button-target, 24px));height:max(100%,var(--ea-icon-button-target, 24px));transform:translate(-50%,-50%)}.ea-multi-select__clear:hover{background-color:var(--color-state-hover);color:var(--color-text-primary)}.ea-multi-select__clear:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}@media(forced-colors:active){.ea-multi-select__clear:focus-visible{outline:2px solid Highlight;outline-offset:2px}}.ea-multi-select__clear:disabled{cursor:not-allowed;opacity:.5}.ea-multi-select__clear{flex-shrink:0}.ea-multi-select__popover{display:flex;flex-direction:column;overflow:hidden;max-height:20rem;border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);box-shadow:var(--shadow-lg);background-color:var(--ea-multi-select-popover-background-color, var(--color-bg-elevated))}@media(forced-colors:active){.ea-multi-select__popover{border:1px solid CanvasText}}.ea-multi-select__popover--2xs{font-size:var(--font-size-2xs)}.ea-multi-select__popover--xs{font-size:var(--font-size-xs)}.ea-multi-select__popover--sm{font-size:var(--font-size-sm)}.ea-multi-select__popover--md{font-size:var(--font-size-md)}.ea-multi-select__popover--lg{font-size:var(--font-size-lg)}.ea-multi-select__popover--xl{font-size:var(--font-size-xl)}.ea-multi-select__search{display:flex;align-items:center;gap:var(--space-2);flex-shrink:0;padding:var(--space-2) var(--space-3);border-bottom:var(--border-width-thin) solid var(--color-border-default)}.ea-multi-select__search-icon{flex-shrink:0;width:1em;height:1em;color:var(--color-text-tertiary)}.ea-multi-select__search-input{flex:1;min-width:0;padding:0;border:none;background:none;font-family:var(--font-family-sans);font-size:inherit;color:var(--color-text-primary)}.ea-multi-select__search-input::placeholder{color:var(--color-text-tertiary);opacity:1}.ea-multi-select__search-input:focus{outline:none}.ea-multi-select__list{overflow-y:auto;overscroll-behavior:none;flex:1;margin:0;padding:var(--space-1) 0;list-style:none}.ea-multi-select__group{position:relative}.ea-multi-select__group--ruled{padding-top:.25em;margin-top:.25em}.ea-multi-select__group--ruled:before{position:absolute;top:0;inset-inline-end:0;inset-inline-start:0;height:var(--border-width-thin);background-color:var(--color-border-default);content:\"\"}.ea-multi-select__group-options{padding:0;margin:0;list-style:none}.ea-multi-select__group-label{display:block;padding:.5em .75em .125em;font-size:.8125em;font-weight:var(--font-weight-semibold);text-transform:uppercase;letter-spacing:.08em;color:var(--color-text-tertiary);-webkit-user-select:none;user-select:none}.ea-multi-select__option{display:flex;align-items:center;gap:.5em;padding:.375em .75em;font-size:inherit;font-family:var(--font-family-sans);color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors)}.ea-multi-select__option--focused{background-color:var(--color-state-hover)}@media(forced-colors:active){.ea-multi-select__option--focused{background-color:Highlight;color:HighlightText}}.ea-multi-select__option--disabled{color:var(--color-text-disabled);cursor:not-allowed}@media(forced-colors:active){.ea-multi-select__option--disabled{color:GrayText}}.ea-multi-select__option--select-all{border-bottom:var(--border-width-thin) solid var(--color-border-default);font-weight:var(--font-weight-medium)}.ea-multi-select__option:hover:not(.ea-multi-select__option--disabled){background-color:var(--color-state-hover)}@media(forced-colors:active){.ea-multi-select__option:hover:not(.ea-multi-select__option--disabled){background-color:Highlight;color:HighlightText}}.ea-multi-select__option ea-checkbox{pointer-events:none;display:inline-flex;align-items:center;line-height:1}.ea-multi-select__option-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ea-multi-select__empty{padding:var(--space-3);font-size:inherit;text-align:center;color:var(--color-text-tertiary);list-style:none}\n"], dependencies: [{ kind: "component", type: CheckboxComponent, selector: "ea-checkbox", inputs: ["label", "count", "hint", "errorMsg", "errorMessages", "size", "disabled", "required", "indeterminate", "aria-label", "id", "checked"], outputs: ["checkedChange", "changed"] }, { kind: "component", type: ChevronDownIconComponent, selector: "ea-icon-chevron-down" }, { kind: "component", type: FieldLabelComponent, selector: "ea-field-label", inputs: ["text", "forId", "required", "labelId"] }, { kind: "component", type: FieldMessagesComponent, selector: "ea-field-messages", inputs: ["id", "error", "hint"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: PopoverComponent, selector: "ea-popover", inputs: ["anchor", "open", "placement", "role", "aria-label", "aria-labelledby", "trapFocus", "surfaceId", "offset", "flip", "clamp", "matchAnchorWidth", "maxWidth", "closeOnOutsideClick", "closeOnEscape", "scrollBehavior"], outputs: ["closeRequested"] }, { kind: "component", type: SearchIconComponent, selector: "ea-icon-search" }, { kind: "component", type: TagComponent, selector: "ea-tag", inputs: ["variant", "size", "removable", "disabled", "removeLabel", "maxWidth", "tooltip", "removeTabbable"], outputs: ["removed"] }, { kind: "directive", type: TooltipDirective, selector: "[eaTooltip]", inputs: ["eaTooltip", "tooltipPosition", "maxWidth"] }, { kind: "component", type: XIconComponent, selector: "ea-icon-x" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
13798
+ ], viewQueries: [{ propertyName: "wrapperEl", first: true, predicate: ["wrapperEl"], descendants: true, isSignal: true }, { propertyName: "triggerEl", first: true, predicate: ["triggerEl"], descendants: true, isSignal: true }, { propertyName: "searchEl", first: true, predicate: ["searchEl"], descendants: true, isSignal: true }, { propertyName: "listEl", first: true, predicate: ["listEl"], descendants: true, isSignal: true }, { propertyName: "optionLabelEls", predicate: ["optionLabelEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"ea-multi-select-field ea-multi-select-field--{{ size() }}\">\n @if (label(); as labelText) {\n <ea-field-label\n [text]=\"labelText\"\n [forId]=\"id()\"\n [labelId]=\"id() + '-label'\"\n [required]=\"required()\" />\n }\n\n <div class=\"ea-multi-select\">\n <div\n #wrapperEl\n class=\"ea-multi-select__trigger-wrapper\"\n [ngClass]=\"wrapperClasses()\"\n (click)=\"onTriggerAreaClick()\">\n <div\n #triggerEl\n class=\"ea-multi-select__trigger\"\n [ngClass]=\"triggerClasses()\"\n [id]=\"id()\"\n role=\"combobox\"\n [attr.tabindex]=\"isDisabled() ? -1 : 0\"\n [attr.aria-labelledby]=\"label() ? id() + '-label' : null\"\n [attr.aria-label]=\"label() ? null : (ariaLabel() ?? null)\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-controls]=\"isOpen() ? listboxId() : null\"\n [attr.aria-activedescendant]=\"isOpen() && !searchable() ? activeOptionId() : null\"\n [attr.aria-disabled]=\"isDisabled() || null\"\n [attr.aria-required]=\"required() || null\"\n [attr.aria-invalid]=\"hasError() || null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \"\n (keydown)=\"handleTriggerKeydown($event)\">\n <span class=\"ea-multi-select__trigger-content\">\n @if (!hasValue()) {\n <span class=\"ea-multi-select__trigger-placeholder\">\n <bdi>{{ resolvedPlaceholder() }}</bdi>\n </span>\n } @else {\n @for (opt of visibleChips(); track opt.value) {\n <ea-tag\n [size]=\"size()\"\n variant=\"default\"\n [maxWidth]=\"maxChipWidth()\"\n [removable]=\"!isDisabled() && !readonly()\"\n [removeTabbable]=\"false\"\n [removeLabel]=\"i18n.messages().multiSelect.removeOption(opt.label)\"\n (removed)=\"removeChip(opt)\">\n <span>{{ opt.label }}</span>\n </ea-tag>\n }\n @if (hiddenChipCount() > 0) {\n <span class=\"ea-multi-select__more\">+{{ hiddenChipCount() }}</span>\n }\n }\n </span>\n </div>\n @if (hasValue() && !isDisabled() && !readonly()) {\n <button\n type=\"button\"\n class=\"ea-multi-select__clear\"\n [attr.aria-label]=\"i18n.messages().multiSelect.clearAll\"\n (click)=\"clear($event)\">\n <ea-icon-x\n class=\"ea-multi-select__clear-icon\"\n aria-hidden=\"true\" />\n </button>\n }\n <ea-icon-chevron-down\n class=\"ea-multi-select__trigger-icon\"\n aria-hidden=\"true\" />\n </div>\n\n <ea-popover\n [anchor]=\"wrapperEl\"\n [open]=\"isOpen()\"\n placement=\"bottom-start\"\n [aria-label]=\"i18n.messages().multiSelect.dialogLabel\"\n [matchAnchorWidth]=\"true\"\n [maxWidth]=\"popoverMaxWidth()\"\n [closeOnEscape]=\"false\"\n scrollBehavior=\"reposition\"\n (closeRequested)=\"onPopoverCloseRequested()\">\n <div\n class=\"ea-multi-select__popover\"\n [ngClass]=\"menuClasses()\">\n @if (searchable()) {\n <div class=\"ea-multi-select__search\">\n <ea-icon-search\n class=\"ea-multi-select__search-icon\"\n aria-hidden=\"true\" />\n <input\n #searchEl\n type=\"text\"\n dir=\"auto\"\n class=\"ea-multi-select__search-input\"\n autocomplete=\"off\"\n [placeholder]=\"resolvedSearchPlaceholder()\"\n [value]=\"searchTerm()\"\n [attr.aria-controls]=\"listboxId()\"\n [attr.aria-activedescendant]=\"activeOptionId()\"\n (input)=\"onSearchInput($event)\"\n (keydown)=\"handlePopoverKeydown($event)\" />\n </div>\n }\n\n <ul\n #listEl\n class=\"ea-multi-select__list\"\n role=\"listbox\"\n aria-multiselectable=\"true\"\n [id]=\"listboxId()\"\n [attr.aria-label]=\"label() ?? ariaLabel() ?? null\">\n @if (selectAllVisible()) {\n <li\n class=\"ea-multi-select__option ea-multi-select__option--select-all\"\n [class.ea-multi-select__option--focused]=\"focusedIndex() === 0\"\n [id]=\"id() + '-opt-0'\"\n role=\"option\"\n [attr.aria-selected]=\"selectAllState() === 'all'\"\n [attr.aria-checked]=\"selectAllAriaChecked()\"\n (click)=\"onSelectAllClick()\">\n <ea-checkbox\n size=\"sm\"\n inert\n aria-hidden=\"true\"\n [checked]=\"selectAllState() === 'all'\"\n [indeterminate]=\"selectAllState() === 'some'\" />\n <span class=\"ea-multi-select__option-label\">\n {{ i18n.messages().multiSelect.selectAll }}\n </span>\n </li>\n }\n @for (group of renderedGroups(); track $index) {\n <li\n class=\"ea-multi-select__group\"\n [class.ea-multi-select__group--ruled]=\"group.rule\"\n role=\"presentation\">\n @if (group.label; as groupLabel) {\n <span\n class=\"ea-multi-select__group-label\"\n aria-hidden=\"true\">\n {{ groupLabel }}\n </span>\n }\n <ul\n class=\"ea-multi-select__group-options\"\n [attr.role]=\"grouped() ? 'group' : 'presentation'\"\n [attr.aria-label]=\"group.label ?? null\">\n @for (entry of group.options; track entry.option.value) {\n <li\n class=\"ea-multi-select__option\"\n [class.ea-multi-select__option--focused]=\"\n focusedIndex() === entry.index + selectAllOffset()\n \"\n [class.ea-multi-select__option--disabled]=\"entry.option.disabled\"\n [id]=\"id() + '-opt-' + (entry.index + selectAllOffset())\"\n role=\"option\"\n [attr.aria-selected]=\"selectedSet().has(entry.option.value)\"\n [attr.aria-disabled]=\"entry.option.disabled || null\"\n (click)=\"onOptionClick(entry.option, entry.index)\">\n <ea-checkbox\n size=\"sm\"\n inert\n aria-hidden=\"true\"\n [checked]=\"selectedSet().has(entry.option.value)\"\n [disabled]=\"!!entry.option.disabled\" />\n <span\n #optionLabelEl\n class=\"ea-multi-select__option-label\"\n [attr.data-value]=\"entry.option.value\"\n [eaTooltip]=\"\n clippedOptions().has(entry.option.value) ? entry.option.label : ''\n \">\n {{ entry.option.label }}\n </span>\n </li>\n }\n </ul>\n </li>\n }\n </ul>\n @if (filteredOptions().length === 0) {\n <div\n class=\"ea-multi-select__empty\"\n role=\"status\">\n {{ i18n.messages().multiSelect.searchEmpty }}\n </div>\n }\n </div>\n </ea-popover>\n </div>\n\n <ea-field-messages\n [id]=\"id()\"\n [error]=\"errorText()\"\n [hint]=\"showHint() ? hint() : null\" />\n</div>\n", styles: [".ea-multi-select-field{display:flex;flex-direction:column;gap:.375em;--ea-field-label-size: .875em;--ea-field-messages-size: .8125em}.ea-multi-select-field--2xs{font-size:var(--font-size-2xs)}.ea-multi-select-field--xs{font-size:var(--font-size-xs)}.ea-multi-select-field--sm{font-size:var(--font-size-sm)}.ea-multi-select-field--md{font-size:var(--font-size-md)}.ea-multi-select-field--lg{font-size:var(--font-size-lg)}.ea-multi-select-field--xl{font-size:var(--font-size-xl)}.ea-multi-select{position:relative}.ea-multi-select__trigger-wrapper{position:relative;display:flex;align-items:center;gap:.5em;width:100%;min-height:2.5em;padding:.375em .75em;border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);background-color:var(--color-bg-base);color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors),var(--transition-shadow)}.ea-multi-select__trigger-wrapper:has(ea-tag){padding-block:.125em}.ea-multi-select__trigger-wrapper:has(.ea-multi-select__trigger:focus-visible){box-shadow:var(--shadow-focus-ring)}@media(forced-colors:active){.ea-multi-select__trigger-wrapper:has(.ea-multi-select__trigger:focus-visible){outline:2px solid Highlight;outline-offset:2px}}.ea-multi-select__trigger-wrapper:has(.ea-multi-select__trigger--open){border-color:var(--color-border-focus);box-shadow:var(--shadow-focus-ring)}@media(forced-colors:active){.ea-multi-select__trigger-wrapper:has(.ea-multi-select__trigger--open){outline:2px solid Highlight;outline-offset:2px}}.ea-multi-select__trigger-wrapper:has(.ea-multi-select__trigger--error){border-color:var(--color-error-default)}.ea-multi-select__trigger-wrapper:has(.ea-multi-select__trigger--error.ea-multi-select__trigger--open){box-shadow:var(--shadow-focus-ring-error)}@media(forced-colors:active){.ea-multi-select__trigger-wrapper:has(.ea-multi-select__trigger--error.ea-multi-select__trigger--open){outline:2px solid Highlight;outline-offset:2px}}.ea-multi-select__trigger-wrapper:has(.ea-multi-select__trigger--disabled){background-color:var(--color-bg-muted);opacity:.6;cursor:not-allowed}.ea-multi-select__trigger-wrapper:has(.ea-multi-select__trigger--readonly){cursor:default}.ea-multi-select__trigger-wrapper:has(.ea-multi-select__trigger--readonly:focus-visible){border-color:var(--color-border-focus);box-shadow:none}@media(forced-colors:active){.ea-multi-select__trigger-wrapper:has(.ea-multi-select__trigger--readonly:focus-visible){outline:2px solid Highlight;outline-offset:2px}}.ea-multi-select__trigger{display:flex;align-items:center;flex:1;min-width:0;text-align:start;font-family:var(--font-family-sans);cursor:pointer}.ea-multi-select__trigger:focus-visible{outline:none}.ea-multi-select__trigger--disabled{cursor:not-allowed}.ea-multi-select__trigger--readonly{cursor:default}.ea-multi-select__trigger-content{display:flex;flex-wrap:nowrap;align-items:center;gap:var(--space-1);flex:1;min-width:0;overflow-x:auto;scrollbar-width:thin}.ea-multi-select__trigger-content ea-tag{flex-shrink:0;--ea-tag-padding-block: 0}.ea-multi-select__trigger-placeholder{color:var(--color-text-tertiary)}.ea-multi-select__trigger-icon{flex-shrink:0;width:1em;height:1em;color:var(--color-text-secondary);transition:var(--transition-transform)}.ea-multi-select__trigger-wrapper:has(.ea-multi-select__trigger--open) .ea-multi-select__trigger-icon{transform:rotate(180deg)}.ea-multi-select__more{display:inline-flex;flex-shrink:0;align-items:center;padding:0 var(--space-1-5);border-radius:var(--radius-lg);background-color:var(--color-bg-muted);font-size:.85em;font-weight:var(--font-weight-medium);color:var(--color-text-secondary)}.ea-multi-select__clear{position:relative;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:var(--ea-icon-button-size, 1.75em);height:var(--ea-icon-button-size, 1.75em);padding:0;border:none;border-radius:var(--radius-sm);background:none;color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-colors)}.ea-multi-select__clear>*{font-size:1.25em}.ea-multi-select__clear:after{content:\"\";position:absolute;top:50%;left:50%;width:max(100%,var(--ea-icon-button-target, 24px));height:max(100%,var(--ea-icon-button-target, 24px));transform:translate(-50%,-50%)}.ea-multi-select__clear:hover{background-color:var(--color-state-hover);color:var(--color-text-primary)}.ea-multi-select__clear:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}@media(forced-colors:active){.ea-multi-select__clear:focus-visible{outline:2px solid Highlight;outline-offset:2px}}.ea-multi-select__clear:disabled{cursor:not-allowed;opacity:.5}.ea-multi-select__clear{flex-shrink:0}.ea-multi-select__popover{display:flex;flex-direction:column;overflow:hidden;max-height:20rem;border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);box-shadow:var(--shadow-lg);background-color:var(--ea-multi-select-popover-background-color, var(--color-bg-elevated))}@media(forced-colors:active){.ea-multi-select__popover{border:1px solid CanvasText}}.ea-multi-select__popover--2xs{font-size:var(--font-size-2xs)}.ea-multi-select__popover--xs{font-size:var(--font-size-xs)}.ea-multi-select__popover--sm{font-size:var(--font-size-sm)}.ea-multi-select__popover--md{font-size:var(--font-size-md)}.ea-multi-select__popover--lg{font-size:var(--font-size-lg)}.ea-multi-select__popover--xl{font-size:var(--font-size-xl)}.ea-multi-select__search{display:flex;align-items:center;gap:var(--space-2);flex-shrink:0;padding:var(--space-2) var(--space-3);border-bottom:var(--border-width-thin) solid var(--color-border-default)}.ea-multi-select__search-icon{flex-shrink:0;width:1em;height:1em;color:var(--color-text-tertiary)}.ea-multi-select__search-input{flex:1;min-width:0;padding:0;border:none;background:none;font-family:var(--font-family-sans);font-size:inherit;color:var(--color-text-primary)}.ea-multi-select__search-input::placeholder{color:var(--color-text-tertiary);opacity:1}.ea-multi-select__search-input:focus{outline:none}.ea-multi-select__list{overflow-y:auto;overscroll-behavior:none;flex:1;margin:0;padding:var(--space-1) 0;list-style:none}.ea-multi-select__group{position:relative}.ea-multi-select__group--ruled{padding-top:.25em;margin-top:.25em}.ea-multi-select__group--ruled:before{position:absolute;top:0;inset-inline-end:0;inset-inline-start:0;height:var(--border-width-thin);background-color:var(--color-border-default);content:\"\"}.ea-multi-select__group-options{padding:0;margin:0;list-style:none}.ea-multi-select__group-label{display:block;padding:.5em .75em .125em;font-size:.8125em;font-weight:var(--font-weight-semibold);text-transform:uppercase;letter-spacing:.08em;color:var(--color-text-tertiary);-webkit-user-select:none;user-select:none}.ea-multi-select__option{display:flex;align-items:center;gap:.5em;padding:.375em .75em;font-size:inherit;font-family:var(--font-family-sans);color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors)}.ea-multi-select__option--focused{background-color:var(--color-state-hover)}@media(forced-colors:active){.ea-multi-select__option--focused{background-color:Highlight;color:HighlightText}}.ea-multi-select__option--disabled{color:var(--color-text-disabled);cursor:not-allowed}@media(forced-colors:active){.ea-multi-select__option--disabled{color:GrayText}}.ea-multi-select__option--select-all{border-bottom:var(--border-width-thin) solid var(--color-border-default);font-weight:var(--font-weight-medium)}.ea-multi-select__option:hover:not(.ea-multi-select__option--disabled){background-color:var(--color-state-hover)}@media(forced-colors:active){.ea-multi-select__option:hover:not(.ea-multi-select__option--disabled){background-color:Highlight;color:HighlightText}}.ea-multi-select__option ea-checkbox{pointer-events:none;display:inline-flex;align-items:center;line-height:1}.ea-multi-select__option-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ea-multi-select__empty{padding:var(--space-3);font-size:inherit;text-align:center;color:var(--color-text-tertiary);list-style:none}\n"], dependencies: [{ kind: "component", type: CheckboxComponent, selector: "ea-checkbox", inputs: ["label", "count", "hint", "errorMsg", "errorMessages", "size", "disabled", "required", "indeterminate", "aria-label", "id", "checked"], outputs: ["checkedChange", "changed"] }, { kind: "component", type: ChevronDownIconComponent, selector: "ea-icon-chevron-down" }, { kind: "component", type: FieldLabelComponent, selector: "ea-field-label", inputs: ["text", "forId", "required", "labelId"] }, { kind: "component", type: FieldMessagesComponent, selector: "ea-field-messages", inputs: ["id", "error", "hint"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: PopoverComponent, selector: "ea-popover", inputs: ["anchor", "open", "placement", "role", "aria-label", "aria-labelledby", "trapFocus", "surfaceId", "offset", "flip", "clamp", "matchAnchorWidth", "maxWidth", "closeOnOutsideClick", "closeOnEscape", "scrollBehavior"], outputs: ["closeRequested"] }, { kind: "component", type: SearchIconComponent, selector: "ea-icon-search" }, { kind: "component", type: TagComponent, selector: "ea-tag", inputs: ["variant", "size", "removable", "disabled", "removeLabel", "maxWidth", "tooltip", "removeTabbable"], outputs: ["removed"] }, { kind: "directive", type: TooltipDirective, selector: "[eaTooltip]", inputs: ["eaTooltip", "tooltipPosition", "maxWidth", "dismissDelay"] }, { kind: "component", type: XIconComponent, selector: "ea-icon-x" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
13695
13799
  }
13696
13800
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: MultiSelectComponent, decorators: [{
13697
13801
  type: Component,