duck-dev-lib 0.0.44 → 0.0.46

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,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, HostBinding, Directive, computed, Component, output, signal, viewChildren, effect, inject, Injectable, afterNextRender, ElementRef, ChangeDetectionStrategy, ChangeDetectorRef, PLATFORM_ID, viewChild, ContentChildren } from '@angular/core';
2
+ import { input, HostBinding, Directive, computed, Component, output, signal, viewChildren, effect, inject, DestroyRef, Injectable, afterNextRender, ElementRef, ChangeDetectionStrategy, ChangeDetectorRef, PLATFORM_ID, viewChild, ContentChildren, afterRenderEffect } from '@angular/core';
3
3
  import * as i1 from '@angular/common';
4
- import { NgStyle, CommonModule, JsonPipe, NgTemplateOutlet, isPlatformBrowser } from '@angular/common';
4
+ import { NgStyle, CommonModule, JsonPipe, NgTemplateOutlet, isPlatformBrowser, DOCUMENT } from '@angular/common';
5
5
  import * as i1$3 from '@jsverse/transloco';
6
6
  import { TranslocoPipe, TranslocoService, TranslocoModule } from '@jsverse/transloco';
7
7
  import * as i1$1 from '@angular/forms';
@@ -773,7 +773,16 @@ function getNeobrutalCardStyle(color) {
773
773
  }
774
774
  }
775
775
 
776
+ const RETURN_TRANSITION$1 = 'transform 180ms cubic-bezier(0.22, 1, 0.36, 1)';
777
+ const EXIT_TRANSITION$1 = 'transform 220ms cubic-bezier(0.22, 1, 0.36, 1)';
776
778
  class DuckDevCardNeobrutalPoster {
779
+ destroyRef = inject(DestroyRef);
780
+ activePointerId = null;
781
+ dragAxis = null;
782
+ dragStartX = 0;
783
+ dragStartY = 0;
784
+ cardWidth = 0;
785
+ swipeEmitTimeoutId = null;
777
786
  color = input(AccentEnumColor.Dark, { ...(ngDevMode ? { debugName: "color" } : {}) });
778
787
  railTop = input.required({ ...(ngDevMode ? { debugName: "railTop" } : {}) });
779
788
  railMiddle = input.required({ ...(ngDevMode ? { debugName: "railMiddle" } : {}) });
@@ -784,26 +793,269 @@ class DuckDevCardNeobrutalPoster {
784
793
  badge = input.required({ ...(ngDevMode ? { debugName: "badge" } : {}) });
785
794
  metricLabel = input.required({ ...(ngDevMode ? { debugName: "metricLabel" } : {}) });
786
795
  metric = input.required({ ...(ngDevMode ? { debugName: "metric" } : {}) });
796
+ swipeable = input(false, { ...(ngDevMode ? { debugName: "swipeable" } : {}) });
797
+ swipeThreshold = input(96, { ...(ngDevMode ? { debugName: "swipeThreshold" } : {}) });
798
+ swipedLeft = output();
799
+ swipedRight = output();
787
800
  cardStyle = computed(() => getNeobrutalCardStyle(this.color()), { ...(ngDevMode ? { debugName: "cardStyle" } : {}) });
801
+ isDragging = signal(false, { ...(ngDevMode ? { debugName: "isDragging" } : {}) });
802
+ dragOffsetX = signal(0, { ...(ngDevMode ? { debugName: "dragOffsetX" } : {}) });
803
+ dragTransition = signal(RETURN_TRANSITION$1, { ...(ngDevMode ? { debugName: "dragTransition" } : {}) });
804
+ rotationDeg = computed(() => this.clamp(this.dragOffsetX() / 18, -14, 14), { ...(ngDevMode ? { debugName: "rotationDeg" } : {}) });
805
+ transformStyle = computed(() => `translate3d(${this.dragOffsetX()}px, 0, 0) rotate(${this.rotationDeg()}deg)`, { ...(ngDevMode ? { debugName: "transformStyle" } : {}) });
806
+ cursorStyle = computed(() => {
807
+ if (!this.swipeable()) {
808
+ return 'default';
809
+ }
810
+ return this.isDragging() ? 'grabbing' : 'grab';
811
+ }, { ...(ngDevMode ? { debugName: "cursorStyle" } : {}) });
812
+ touchActionStyle = computed(() => (this.swipeable() ? 'pan-y' : 'auto'), { ...(ngDevMode ? { debugName: "touchActionStyle" } : {}) });
813
+ constructor() {
814
+ this.destroyRef.onDestroy(() => this.clearSwipeEmitTimeout());
815
+ }
816
+ onPointerDown(event) {
817
+ if (!this.swipeable() || this.activePointerId !== null) {
818
+ return;
819
+ }
820
+ if (event.pointerType === 'mouse' && event.button !== 0) {
821
+ return;
822
+ }
823
+ const card = event.currentTarget;
824
+ if (!(card instanceof HTMLElement)) {
825
+ return;
826
+ }
827
+ this.clearSwipeEmitTimeout();
828
+ this.activePointerId = event.pointerId;
829
+ this.dragAxis = null;
830
+ this.dragStartX = event.clientX;
831
+ this.dragStartY = event.clientY;
832
+ this.cardWidth = card.offsetWidth;
833
+ this.dragTransition.set('none');
834
+ card.setPointerCapture(event.pointerId);
835
+ }
836
+ onPointerMove(event) {
837
+ if (event.pointerId !== this.activePointerId) {
838
+ return;
839
+ }
840
+ const deltaX = event.clientX - this.dragStartX;
841
+ const deltaY = event.clientY - this.dragStartY;
842
+ if (this.dragAxis === null) {
843
+ if (Math.abs(deltaX) < 10 && Math.abs(deltaY) < 10) {
844
+ return;
845
+ }
846
+ this.dragAxis = Math.abs(deltaX) >= Math.abs(deltaY) ? 'x' : 'y';
847
+ if (this.dragAxis !== 'x') {
848
+ this.releasePointer(event);
849
+ this.resetPosition();
850
+ return;
851
+ }
852
+ }
853
+ event.preventDefault();
854
+ this.isDragging.set(true);
855
+ this.dragOffsetX.set(deltaX);
856
+ }
857
+ onPointerUp(event) {
858
+ if (event.pointerId !== this.activePointerId) {
859
+ return;
860
+ }
861
+ const deltaX = this.dragOffsetX();
862
+ const threshold = Math.max(24, this.swipeThreshold());
863
+ const shouldDismiss = this.dragAxis === 'x' && Math.abs(deltaX) >= threshold;
864
+ this.releasePointer(event);
865
+ this.dragAxis = null;
866
+ this.isDragging.set(false);
867
+ if (!shouldDismiss) {
868
+ this.resetPosition();
869
+ return;
870
+ }
871
+ const direction = deltaX >= 0 ? 1 : -1;
872
+ const exitDistance = Math.max(this.cardWidth * 1.35, 420);
873
+ this.dragTransition.set(EXIT_TRANSITION$1);
874
+ this.dragOffsetX.set(direction * exitDistance);
875
+ this.swipeEmitTimeoutId = window.setTimeout(() => {
876
+ this.swipeEmitTimeoutId = null;
877
+ if (direction > 0) {
878
+ this.swipedRight.emit();
879
+ return;
880
+ }
881
+ this.swipedLeft.emit();
882
+ }, 180);
883
+ }
884
+ onPointerCancel(event) {
885
+ if (event.pointerId !== this.activePointerId) {
886
+ return;
887
+ }
888
+ this.releasePointer(event);
889
+ this.resetPosition();
890
+ }
891
+ releasePointer(event) {
892
+ const card = event.currentTarget;
893
+ if (card instanceof HTMLElement && card.hasPointerCapture(event.pointerId)) {
894
+ card.releasePointerCapture(event.pointerId);
895
+ }
896
+ this.activePointerId = null;
897
+ }
898
+ resetPosition() {
899
+ this.dragAxis = null;
900
+ this.isDragging.set(false);
901
+ this.dragTransition.set(RETURN_TRANSITION$1);
902
+ this.dragOffsetX.set(0);
903
+ }
904
+ clearSwipeEmitTimeout() {
905
+ if (this.swipeEmitTimeoutId === null) {
906
+ return;
907
+ }
908
+ window.clearTimeout(this.swipeEmitTimeoutId);
909
+ this.swipeEmitTimeoutId = null;
910
+ }
911
+ clamp(value, min, max) {
912
+ return Math.min(Math.max(value, min), max);
913
+ }
788
914
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: DuckDevCardNeobrutalPoster, deps: [], target: i0.ɵɵFactoryTarget.Component });
789
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.1", type: DuckDevCardNeobrutalPoster, isStandalone: true, selector: "dd-card-neobrutal-poster", inputs: { color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, railTop: { classPropertyName: "railTop", publicName: "railTop", isSignal: true, isRequired: true, transformFunction: null }, railMiddle: { classPropertyName: "railMiddle", publicName: "railMiddle", isSignal: true, isRequired: true, transformFunction: null }, railBottom: { classPropertyName: "railBottom", publicName: "railBottom", isSignal: true, isRequired: true, transformFunction: null }, eyebrow: { classPropertyName: "eyebrow", publicName: "eyebrow", isSignal: true, isRequired: true, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: true, transformFunction: null }, badge: { classPropertyName: "badge", publicName: "badge", isSignal: true, isRequired: true, transformFunction: null }, metricLabel: { classPropertyName: "metricLabel", publicName: "metricLabel", isSignal: true, isRequired: true, transformFunction: null }, metric: { classPropertyName: "metric", publicName: "metric", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<article class=\"dd-card-neo-poster\" [ngStyle]=\"cardStyle()\">\n <div class=\"dd-card-neo-poster__panel\">\n <div class=\"dd-card-neo-poster__meta\">\n <p class=\"dd-card-neo-poster__eyebrow\">{{ eyebrow() }}</p>\n <p class=\"dd-card-neo-poster__badge\">{{ badge() }}</p>\n </div>\n\n <div class=\"dd-card-neo-poster__content\">\n <h3 class=\"dd-card-neo-poster__title\">{{ title() }}</h3>\n <p class=\"dd-card-neo-poster__description\">{{ description() }}</p>\n </div>\n\n <div class=\"dd-card-neo-poster__metric\">\n <span class=\"dd-card-neo-poster__metric-label\">{{ metricLabel() }}</span>\n <strong class=\"dd-card-neo-poster__metric-value\">{{ metric() }}</strong>\n </div>\n </div>\n</article>\n", styles: [".dd-card-neo-poster{display:grid;grid-template-columns:92px minmax(0,1fr);background:var(--dd-neo-card-surface);border:4px solid var(--dd-neo-card-border);box-shadow:12px 12px 0 var(--dd-neo-card-shadow);color:var(--dd-neo-card-text);overflow:clip}.dd-card-neo-poster__headline span:last-child{border-bottom:0}.dd-card-neo-poster__panel{position:relative;display:grid;gap:18px;padding:24px 24px 24px 28px;background:linear-gradient(135deg,color-mix(in srgb,var(--dd-neo-card-accent) 20%,transparent) 0 17%,transparent 17% 100%),repeating-linear-gradient(-45deg,color-mix(in srgb,var(--dd-neo-card-border) 9%,transparent) 0 10px,transparent 10px 22px),var(--dd-neo-card-panel)}.dd-card-neo-poster__panel:before{content:\"\";position:absolute;top:0;bottom:0;left:0;width:8px;background:var(--dd-neo-card-border)}.dd-card-neo-poster__content{display:grid;gap:10px}.dd-card-neo-poster__meta{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.dd-card-neo-poster__eyebrow,.dd-card-neo-poster__badge,.dd-card-neo-poster__title,.dd-card-neo-poster__description,.dd-card-neo-poster__metric-label,.dd-card-neo-poster__metric-value{margin:0}.dd-card-neo-poster__eyebrow,.dd-card-neo-poster__metric-label{font-size:12px;font-weight:900;letter-spacing:.18em;line-height:1.1;text-transform:uppercase}.dd-card-neo-poster__badge{padding:7px 10px 5px;border:4px solid var(--dd-neo-card-border);background:var(--dd-neo-card-accent);box-shadow:4px 4px 0 var(--dd-neo-card-shadow);font-size:12px;font-weight:900;letter-spacing:.14em;line-height:1;text-transform:uppercase}.dd-card-neo-poster__title{max-width:11ch;font-size:clamp(30px,5vw,44px);font-weight:1000;line-height:.9;letter-spacing:-.05em;text-transform:uppercase;text-wrap:balance}.dd-card-neo-poster__description{max-width:38ch;font-size:15px;line-height:1.5;font-weight:800}.dd-card-neo-poster__metric{display:grid;justify-items:start;gap:6px;width:fit-content;padding:12px 14px 10px;border:4px solid var(--dd-neo-card-border);background:var(--dd-neo-card-surface);box-shadow:7px 7px 0 var(--dd-neo-card-shadow)}.dd-card-neo-poster__metric-value{font-size:clamp(28px,5vw,52px);font-weight:1000;line-height:.9;letter-spacing:-.07em}@media(max-width:640px){.dd-card-neo-poster{grid-template-columns:1fr;box-shadow:8px 8px 0 var(--dd-neo-card-shadow)}.dd-card-neo-poster__headline{grid-template-columns:repeat(3,1fr);border-right:0;border-bottom:4px solid var(--dd-neo-card-border)}.dd-card-neo-poster__headline span{min-height:auto;writing-mode:horizontal-tb;transform:none;border-right:4px solid var(--dd-neo-card-border);border-bottom:0}.dd-card-neo-poster__headline span:last-child{border-right:0}.dd-card-neo-poster__panel{padding:20px 20px 20px 24px}.dd-card-neo-poster__meta{flex-direction:column;align-items:flex-start}.dd-card-neo-poster__title{max-width:none}}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
915
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.1", type: DuckDevCardNeobrutalPoster, isStandalone: true, selector: "dd-card-neobrutal-poster", inputs: { color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, railTop: { classPropertyName: "railTop", publicName: "railTop", isSignal: true, isRequired: true, transformFunction: null }, railMiddle: { classPropertyName: "railMiddle", publicName: "railMiddle", isSignal: true, isRequired: true, transformFunction: null }, railBottom: { classPropertyName: "railBottom", publicName: "railBottom", isSignal: true, isRequired: true, transformFunction: null }, eyebrow: { classPropertyName: "eyebrow", publicName: "eyebrow", isSignal: true, isRequired: true, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: true, transformFunction: null }, badge: { classPropertyName: "badge", publicName: "badge", isSignal: true, isRequired: true, transformFunction: null }, metricLabel: { classPropertyName: "metricLabel", publicName: "metricLabel", isSignal: true, isRequired: true, transformFunction: null }, metric: { classPropertyName: "metric", publicName: "metric", isSignal: true, isRequired: true, transformFunction: null }, swipeable: { classPropertyName: "swipeable", publicName: "swipeable", isSignal: true, isRequired: false, transformFunction: null }, swipeThreshold: { classPropertyName: "swipeThreshold", publicName: "swipeThreshold", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { swipedLeft: "swipedLeft", swipedRight: "swipedRight" }, ngImport: i0, template: "<article\n class=\"dd-card-neo-poster\"\n [class.dd-card-neo-poster--dragging]=\"isDragging()\"\n [class.dd-card-neo-poster--swipeable]=\"swipeable()\"\n [ngStyle]=\"cardStyle()\"\n [style.cursor]=\"cursorStyle()\"\n [style.touch-action]=\"touchActionStyle()\"\n [style.transform]=\"transformStyle()\"\n [style.transition]=\"dragTransition()\"\n (pointercancel)=\"onPointerCancel($event)\"\n (pointerdown)=\"onPointerDown($event)\"\n (pointermove)=\"onPointerMove($event)\"\n (pointerup)=\"onPointerUp($event)\"\n>\n <div class=\"dd-card-neo-poster__panel\">\n <div class=\"dd-card-neo-poster__meta\">\n <p class=\"dd-card-neo-poster__eyebrow\">{{ eyebrow() }}</p>\n <p class=\"dd-card-neo-poster__badge\">{{ badge() }}</p>\n </div>\n\n <div class=\"dd-card-neo-poster__content\">\n <h3 class=\"dd-card-neo-poster__title\">{{ title() }}</h3>\n <p class=\"dd-card-neo-poster__description\">{{ description() }}</p>\n </div>\n\n <div class=\"dd-card-neo-poster__metric\">\n <span class=\"dd-card-neo-poster__metric-label\">{{ metricLabel() }}</span>\n <strong class=\"dd-card-neo-poster__metric-value\">{{ metric() }}</strong>\n </div>\n </div>\n</article>\n", styles: [".dd-card-neo-poster{display:grid;grid-template-columns:92px minmax(0,1fr);background:var(--dd-neo-card-surface);border:4px solid var(--dd-neo-card-border);box-shadow:12px 12px 0 var(--dd-neo-card-shadow);color:var(--dd-neo-card-text);overflow:clip;transform-origin:center bottom;will-change:transform}.dd-card-neo-poster.dd-card-neo-poster--swipeable{-webkit-user-select:none;user-select:none}.dd-card-neo-poster.dd-card-neo-poster--dragging{z-index:1}.dd-card-neo-poster__headline span:last-child{border-bottom:0}.dd-card-neo-poster__panel{position:relative;display:grid;gap:18px;padding:24px 24px 24px 28px;background:linear-gradient(135deg,color-mix(in srgb,var(--dd-neo-card-accent) 20%,transparent) 0 17%,transparent 17% 100%),repeating-linear-gradient(-45deg,color-mix(in srgb,var(--dd-neo-card-border) 9%,transparent) 0 10px,transparent 10px 22px),var(--dd-neo-card-panel)}.dd-card-neo-poster__panel:before{content:\"\";position:absolute;top:0;bottom:0;left:0;width:8px;background:var(--dd-neo-card-border)}.dd-card-neo-poster__content{display:grid;gap:10px}.dd-card-neo-poster__meta{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.dd-card-neo-poster__eyebrow,.dd-card-neo-poster__badge,.dd-card-neo-poster__title,.dd-card-neo-poster__description,.dd-card-neo-poster__metric-label,.dd-card-neo-poster__metric-value{margin:0}.dd-card-neo-poster__eyebrow,.dd-card-neo-poster__metric-label{font-size:12px;font-weight:900;letter-spacing:.18em;line-height:1.1;text-transform:uppercase}.dd-card-neo-poster__badge{padding:7px 10px 5px;border:4px solid var(--dd-neo-card-border);background:var(--dd-neo-card-accent);box-shadow:4px 4px 0 var(--dd-neo-card-shadow);font-size:12px;font-weight:900;letter-spacing:.14em;line-height:1;text-transform:uppercase}.dd-card-neo-poster__title{max-width:11ch;font-size:clamp(30px,5vw,44px);font-weight:1000;line-height:.9;letter-spacing:-.05em;text-transform:uppercase;text-wrap:balance}.dd-card-neo-poster__description{max-width:38ch;font-size:15px;line-height:1.5;font-weight:800}.dd-card-neo-poster__metric{display:grid;justify-items:start;gap:6px;width:fit-content;padding:12px 14px 10px;border:4px solid var(--dd-neo-card-border);background:var(--dd-neo-card-surface);box-shadow:7px 7px 0 var(--dd-neo-card-shadow)}.dd-card-neo-poster__metric-value{font-size:clamp(28px,5vw,52px);font-weight:1000;line-height:.9;letter-spacing:-.07em}@media(max-width:640px){.dd-card-neo-poster{grid-template-columns:1fr;box-shadow:8px 8px 0 var(--dd-neo-card-shadow)}.dd-card-neo-poster__headline{grid-template-columns:repeat(3,1fr);border-right:0;border-bottom:4px solid var(--dd-neo-card-border)}.dd-card-neo-poster__headline span{min-height:auto;writing-mode:horizontal-tb;transform:none;border-right:4px solid var(--dd-neo-card-border);border-bottom:0}.dd-card-neo-poster__headline span:last-child{border-right:0}.dd-card-neo-poster__panel{padding:20px 20px 20px 24px}.dd-card-neo-poster__meta{flex-direction:column;align-items:flex-start}.dd-card-neo-poster__title{max-width:none}}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
790
916
  }
791
917
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: DuckDevCardNeobrutalPoster, decorators: [{
792
918
  type: Component,
793
- args: [{ selector: 'dd-card-neobrutal-poster', standalone: true, imports: [NgStyle], template: "<article class=\"dd-card-neo-poster\" [ngStyle]=\"cardStyle()\">\n <div class=\"dd-card-neo-poster__panel\">\n <div class=\"dd-card-neo-poster__meta\">\n <p class=\"dd-card-neo-poster__eyebrow\">{{ eyebrow() }}</p>\n <p class=\"dd-card-neo-poster__badge\">{{ badge() }}</p>\n </div>\n\n <div class=\"dd-card-neo-poster__content\">\n <h3 class=\"dd-card-neo-poster__title\">{{ title() }}</h3>\n <p class=\"dd-card-neo-poster__description\">{{ description() }}</p>\n </div>\n\n <div class=\"dd-card-neo-poster__metric\">\n <span class=\"dd-card-neo-poster__metric-label\">{{ metricLabel() }}</span>\n <strong class=\"dd-card-neo-poster__metric-value\">{{ metric() }}</strong>\n </div>\n </div>\n</article>\n", styles: [".dd-card-neo-poster{display:grid;grid-template-columns:92px minmax(0,1fr);background:var(--dd-neo-card-surface);border:4px solid var(--dd-neo-card-border);box-shadow:12px 12px 0 var(--dd-neo-card-shadow);color:var(--dd-neo-card-text);overflow:clip}.dd-card-neo-poster__headline span:last-child{border-bottom:0}.dd-card-neo-poster__panel{position:relative;display:grid;gap:18px;padding:24px 24px 24px 28px;background:linear-gradient(135deg,color-mix(in srgb,var(--dd-neo-card-accent) 20%,transparent) 0 17%,transparent 17% 100%),repeating-linear-gradient(-45deg,color-mix(in srgb,var(--dd-neo-card-border) 9%,transparent) 0 10px,transparent 10px 22px),var(--dd-neo-card-panel)}.dd-card-neo-poster__panel:before{content:\"\";position:absolute;top:0;bottom:0;left:0;width:8px;background:var(--dd-neo-card-border)}.dd-card-neo-poster__content{display:grid;gap:10px}.dd-card-neo-poster__meta{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.dd-card-neo-poster__eyebrow,.dd-card-neo-poster__badge,.dd-card-neo-poster__title,.dd-card-neo-poster__description,.dd-card-neo-poster__metric-label,.dd-card-neo-poster__metric-value{margin:0}.dd-card-neo-poster__eyebrow,.dd-card-neo-poster__metric-label{font-size:12px;font-weight:900;letter-spacing:.18em;line-height:1.1;text-transform:uppercase}.dd-card-neo-poster__badge{padding:7px 10px 5px;border:4px solid var(--dd-neo-card-border);background:var(--dd-neo-card-accent);box-shadow:4px 4px 0 var(--dd-neo-card-shadow);font-size:12px;font-weight:900;letter-spacing:.14em;line-height:1;text-transform:uppercase}.dd-card-neo-poster__title{max-width:11ch;font-size:clamp(30px,5vw,44px);font-weight:1000;line-height:.9;letter-spacing:-.05em;text-transform:uppercase;text-wrap:balance}.dd-card-neo-poster__description{max-width:38ch;font-size:15px;line-height:1.5;font-weight:800}.dd-card-neo-poster__metric{display:grid;justify-items:start;gap:6px;width:fit-content;padding:12px 14px 10px;border:4px solid var(--dd-neo-card-border);background:var(--dd-neo-card-surface);box-shadow:7px 7px 0 var(--dd-neo-card-shadow)}.dd-card-neo-poster__metric-value{font-size:clamp(28px,5vw,52px);font-weight:1000;line-height:.9;letter-spacing:-.07em}@media(max-width:640px){.dd-card-neo-poster{grid-template-columns:1fr;box-shadow:8px 8px 0 var(--dd-neo-card-shadow)}.dd-card-neo-poster__headline{grid-template-columns:repeat(3,1fr);border-right:0;border-bottom:4px solid var(--dd-neo-card-border)}.dd-card-neo-poster__headline span{min-height:auto;writing-mode:horizontal-tb;transform:none;border-right:4px solid var(--dd-neo-card-border);border-bottom:0}.dd-card-neo-poster__headline span:last-child{border-right:0}.dd-card-neo-poster__panel{padding:20px 20px 20px 24px}.dd-card-neo-poster__meta{flex-direction:column;align-items:flex-start}.dd-card-neo-poster__title{max-width:none}}\n"] }]
794
- }], propDecorators: { color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], railTop: [{ type: i0.Input, args: [{ isSignal: true, alias: "railTop", required: true }] }], railMiddle: [{ type: i0.Input, args: [{ isSignal: true, alias: "railMiddle", required: true }] }], railBottom: [{ type: i0.Input, args: [{ isSignal: true, alias: "railBottom", required: true }] }], eyebrow: [{ type: i0.Input, args: [{ isSignal: true, alias: "eyebrow", required: true }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: true }] }], badge: [{ type: i0.Input, args: [{ isSignal: true, alias: "badge", required: true }] }], metricLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "metricLabel", required: true }] }], metric: [{ type: i0.Input, args: [{ isSignal: true, alias: "metric", required: true }] }] } });
919
+ args: [{ selector: 'dd-card-neobrutal-poster', standalone: true, imports: [NgStyle], template: "<article\n class=\"dd-card-neo-poster\"\n [class.dd-card-neo-poster--dragging]=\"isDragging()\"\n [class.dd-card-neo-poster--swipeable]=\"swipeable()\"\n [ngStyle]=\"cardStyle()\"\n [style.cursor]=\"cursorStyle()\"\n [style.touch-action]=\"touchActionStyle()\"\n [style.transform]=\"transformStyle()\"\n [style.transition]=\"dragTransition()\"\n (pointercancel)=\"onPointerCancel($event)\"\n (pointerdown)=\"onPointerDown($event)\"\n (pointermove)=\"onPointerMove($event)\"\n (pointerup)=\"onPointerUp($event)\"\n>\n <div class=\"dd-card-neo-poster__panel\">\n <div class=\"dd-card-neo-poster__meta\">\n <p class=\"dd-card-neo-poster__eyebrow\">{{ eyebrow() }}</p>\n <p class=\"dd-card-neo-poster__badge\">{{ badge() }}</p>\n </div>\n\n <div class=\"dd-card-neo-poster__content\">\n <h3 class=\"dd-card-neo-poster__title\">{{ title() }}</h3>\n <p class=\"dd-card-neo-poster__description\">{{ description() }}</p>\n </div>\n\n <div class=\"dd-card-neo-poster__metric\">\n <span class=\"dd-card-neo-poster__metric-label\">{{ metricLabel() }}</span>\n <strong class=\"dd-card-neo-poster__metric-value\">{{ metric() }}</strong>\n </div>\n </div>\n</article>\n", styles: [".dd-card-neo-poster{display:grid;grid-template-columns:92px minmax(0,1fr);background:var(--dd-neo-card-surface);border:4px solid var(--dd-neo-card-border);box-shadow:12px 12px 0 var(--dd-neo-card-shadow);color:var(--dd-neo-card-text);overflow:clip;transform-origin:center bottom;will-change:transform}.dd-card-neo-poster.dd-card-neo-poster--swipeable{-webkit-user-select:none;user-select:none}.dd-card-neo-poster.dd-card-neo-poster--dragging{z-index:1}.dd-card-neo-poster__headline span:last-child{border-bottom:0}.dd-card-neo-poster__panel{position:relative;display:grid;gap:18px;padding:24px 24px 24px 28px;background:linear-gradient(135deg,color-mix(in srgb,var(--dd-neo-card-accent) 20%,transparent) 0 17%,transparent 17% 100%),repeating-linear-gradient(-45deg,color-mix(in srgb,var(--dd-neo-card-border) 9%,transparent) 0 10px,transparent 10px 22px),var(--dd-neo-card-panel)}.dd-card-neo-poster__panel:before{content:\"\";position:absolute;top:0;bottom:0;left:0;width:8px;background:var(--dd-neo-card-border)}.dd-card-neo-poster__content{display:grid;gap:10px}.dd-card-neo-poster__meta{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.dd-card-neo-poster__eyebrow,.dd-card-neo-poster__badge,.dd-card-neo-poster__title,.dd-card-neo-poster__description,.dd-card-neo-poster__metric-label,.dd-card-neo-poster__metric-value{margin:0}.dd-card-neo-poster__eyebrow,.dd-card-neo-poster__metric-label{font-size:12px;font-weight:900;letter-spacing:.18em;line-height:1.1;text-transform:uppercase}.dd-card-neo-poster__badge{padding:7px 10px 5px;border:4px solid var(--dd-neo-card-border);background:var(--dd-neo-card-accent);box-shadow:4px 4px 0 var(--dd-neo-card-shadow);font-size:12px;font-weight:900;letter-spacing:.14em;line-height:1;text-transform:uppercase}.dd-card-neo-poster__title{max-width:11ch;font-size:clamp(30px,5vw,44px);font-weight:1000;line-height:.9;letter-spacing:-.05em;text-transform:uppercase;text-wrap:balance}.dd-card-neo-poster__description{max-width:38ch;font-size:15px;line-height:1.5;font-weight:800}.dd-card-neo-poster__metric{display:grid;justify-items:start;gap:6px;width:fit-content;padding:12px 14px 10px;border:4px solid var(--dd-neo-card-border);background:var(--dd-neo-card-surface);box-shadow:7px 7px 0 var(--dd-neo-card-shadow)}.dd-card-neo-poster__metric-value{font-size:clamp(28px,5vw,52px);font-weight:1000;line-height:.9;letter-spacing:-.07em}@media(max-width:640px){.dd-card-neo-poster{grid-template-columns:1fr;box-shadow:8px 8px 0 var(--dd-neo-card-shadow)}.dd-card-neo-poster__headline{grid-template-columns:repeat(3,1fr);border-right:0;border-bottom:4px solid var(--dd-neo-card-border)}.dd-card-neo-poster__headline span{min-height:auto;writing-mode:horizontal-tb;transform:none;border-right:4px solid var(--dd-neo-card-border);border-bottom:0}.dd-card-neo-poster__headline span:last-child{border-right:0}.dd-card-neo-poster__panel{padding:20px 20px 20px 24px}.dd-card-neo-poster__meta{flex-direction:column;align-items:flex-start}.dd-card-neo-poster__title{max-width:none}}\n"] }]
920
+ }], ctorParameters: () => [], propDecorators: { color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], railTop: [{ type: i0.Input, args: [{ isSignal: true, alias: "railTop", required: true }] }], railMiddle: [{ type: i0.Input, args: [{ isSignal: true, alias: "railMiddle", required: true }] }], railBottom: [{ type: i0.Input, args: [{ isSignal: true, alias: "railBottom", required: true }] }], eyebrow: [{ type: i0.Input, args: [{ isSignal: true, alias: "eyebrow", required: true }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: true }] }], badge: [{ type: i0.Input, args: [{ isSignal: true, alias: "badge", required: true }] }], metricLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "metricLabel", required: true }] }], metric: [{ type: i0.Input, args: [{ isSignal: true, alias: "metric", required: true }] }], swipeable: [{ type: i0.Input, args: [{ isSignal: true, alias: "swipeable", required: false }] }], swipeThreshold: [{ type: i0.Input, args: [{ isSignal: true, alias: "swipeThreshold", required: false }] }], swipedLeft: [{ type: i0.Output, args: ["swipedLeft"] }], swipedRight: [{ type: i0.Output, args: ["swipedRight"] }] } });
795
921
 
922
+ const RETURN_TRANSITION = 'transform 180ms cubic-bezier(0.22, 1, 0.36, 1)';
923
+ const EXIT_TRANSITION = 'transform 220ms cubic-bezier(0.22, 1, 0.36, 1)';
796
924
  class DuckDevCardNeobrutalSlab {
925
+ destroyRef = inject(DestroyRef);
926
+ activePointerId = null;
927
+ dragAxis = null;
928
+ dragStartX = 0;
929
+ dragStartY = 0;
930
+ cardWidth = 0;
931
+ swipeEmitTimeoutId = null;
797
932
  color = input(AccentEnumColor.White, { ...(ngDevMode ? { debugName: "color" } : {}) });
798
933
  strapLabel = input.required({ ...(ngDevMode ? { debugName: "strapLabel" } : {}) });
934
+ swipeable = input(false, { ...(ngDevMode ? { debugName: "swipeable" } : {}) });
935
+ swipeThreshold = input(96, { ...(ngDevMode ? { debugName: "swipeThreshold" } : {}) });
936
+ swipedLeft = output();
937
+ swipedRight = output();
799
938
  cardStyle = computed(() => getNeobrutalCardStyle(this.color()), { ...(ngDevMode ? { debugName: "cardStyle" } : {}) });
939
+ isDragging = signal(false, { ...(ngDevMode ? { debugName: "isDragging" } : {}) });
940
+ dragOffsetX = signal(0, { ...(ngDevMode ? { debugName: "dragOffsetX" } : {}) });
941
+ dragTransition = signal(RETURN_TRANSITION, { ...(ngDevMode ? { debugName: "dragTransition" } : {}) });
942
+ rotationDeg = computed(() => this.clamp(this.dragOffsetX() / 18, -14, 14), { ...(ngDevMode ? { debugName: "rotationDeg" } : {}) });
943
+ transformStyle = computed(() => `translate3d(${this.dragOffsetX()}px, 0, 0) rotate(${this.rotationDeg()}deg)`, { ...(ngDevMode ? { debugName: "transformStyle" } : {}) });
944
+ cursorStyle = computed(() => {
945
+ if (!this.swipeable()) {
946
+ return 'default';
947
+ }
948
+ return this.isDragging() ? 'grabbing' : 'grab';
949
+ }, { ...(ngDevMode ? { debugName: "cursorStyle" } : {}) });
950
+ touchActionStyle = computed(() => (this.swipeable() ? 'pan-y' : 'auto'), { ...(ngDevMode ? { debugName: "touchActionStyle" } : {}) });
951
+ constructor() {
952
+ this.destroyRef.onDestroy(() => this.clearSwipeEmitTimeout());
953
+ }
954
+ onPointerDown(event) {
955
+ if (!this.swipeable() || this.activePointerId !== null) {
956
+ return;
957
+ }
958
+ if (event.pointerType === 'mouse' && event.button !== 0) {
959
+ return;
960
+ }
961
+ const card = event.currentTarget;
962
+ if (!(card instanceof HTMLElement)) {
963
+ return;
964
+ }
965
+ this.clearSwipeEmitTimeout();
966
+ this.activePointerId = event.pointerId;
967
+ this.dragAxis = null;
968
+ this.dragStartX = event.clientX;
969
+ this.dragStartY = event.clientY;
970
+ this.cardWidth = card.offsetWidth;
971
+ this.dragTransition.set('none');
972
+ card.setPointerCapture(event.pointerId);
973
+ }
974
+ onPointerMove(event) {
975
+ if (event.pointerId !== this.activePointerId) {
976
+ return;
977
+ }
978
+ const deltaX = event.clientX - this.dragStartX;
979
+ const deltaY = event.clientY - this.dragStartY;
980
+ if (this.dragAxis === null) {
981
+ if (Math.abs(deltaX) < 10 && Math.abs(deltaY) < 10) {
982
+ return;
983
+ }
984
+ this.dragAxis = Math.abs(deltaX) >= Math.abs(deltaY) ? 'x' : 'y';
985
+ if (this.dragAxis !== 'x') {
986
+ this.releasePointer(event);
987
+ this.resetPosition();
988
+ return;
989
+ }
990
+ }
991
+ event.preventDefault();
992
+ this.isDragging.set(true);
993
+ this.dragOffsetX.set(deltaX);
994
+ }
995
+ onPointerUp(event) {
996
+ if (event.pointerId !== this.activePointerId) {
997
+ return;
998
+ }
999
+ const deltaX = this.dragOffsetX();
1000
+ const threshold = Math.max(24, this.swipeThreshold());
1001
+ const shouldDismiss = this.dragAxis === 'x' && Math.abs(deltaX) >= threshold;
1002
+ this.releasePointer(event);
1003
+ this.dragAxis = null;
1004
+ this.isDragging.set(false);
1005
+ if (!shouldDismiss) {
1006
+ this.resetPosition();
1007
+ return;
1008
+ }
1009
+ const direction = deltaX >= 0 ? 1 : -1;
1010
+ const exitDistance = Math.max(this.cardWidth * 1.35, 420);
1011
+ this.dragTransition.set(EXIT_TRANSITION);
1012
+ this.dragOffsetX.set(direction * exitDistance);
1013
+ this.swipeEmitTimeoutId = window.setTimeout(() => {
1014
+ this.swipeEmitTimeoutId = null;
1015
+ if (direction > 0) {
1016
+ this.swipedRight.emit();
1017
+ return;
1018
+ }
1019
+ this.swipedLeft.emit();
1020
+ }, 180);
1021
+ }
1022
+ onPointerCancel(event) {
1023
+ if (event.pointerId !== this.activePointerId) {
1024
+ return;
1025
+ }
1026
+ this.releasePointer(event);
1027
+ this.resetPosition();
1028
+ }
1029
+ releasePointer(event) {
1030
+ const card = event.currentTarget;
1031
+ if (card instanceof HTMLElement && card.hasPointerCapture(event.pointerId)) {
1032
+ card.releasePointerCapture(event.pointerId);
1033
+ }
1034
+ this.activePointerId = null;
1035
+ }
1036
+ resetPosition() {
1037
+ this.dragAxis = null;
1038
+ this.isDragging.set(false);
1039
+ this.dragTransition.set(RETURN_TRANSITION);
1040
+ this.dragOffsetX.set(0);
1041
+ }
1042
+ clearSwipeEmitTimeout() {
1043
+ if (this.swipeEmitTimeoutId === null) {
1044
+ return;
1045
+ }
1046
+ window.clearTimeout(this.swipeEmitTimeoutId);
1047
+ this.swipeEmitTimeoutId = null;
1048
+ }
1049
+ clamp(value, min, max) {
1050
+ return Math.min(Math.max(value, min), max);
1051
+ }
800
1052
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: DuckDevCardNeobrutalSlab, deps: [], target: i0.ɵɵFactoryTarget.Component });
801
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.1", type: DuckDevCardNeobrutalSlab, isStandalone: true, selector: "dd-card-neobrutal-slab", inputs: { color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, strapLabel: { classPropertyName: "strapLabel", publicName: "strapLabel", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<article class=\"dd-card-neo-slab\" [ngStyle]=\"cardStyle()\">\n <div class=\"dd-card-neo-slab__strap\" aria-hidden=\"true\">{{ strapLabel() }}</div>\n <div class=\"dd-card-neo-slab__panel\">\n <div class=\"dd-card-neo-slab__marker\" aria-hidden=\"true\"></div>\n <div class=\"dd-card-neo-slab__content\">\n <ng-content />\n </div>\n </div>\n</article>\n", styles: [".dd-card-neo-slab{position:relative;display:block;background:var(--dd-neo-card-surface);border:4px solid var(--dd-neo-card-border);box-shadow:10px 10px 0 var(--dd-neo-card-shadow);color:var(--dd-neo-card-text)}.dd-card-neo-slab__strap{position:absolute;top:-22px;left:18px;display:inline-flex;align-items:center;justify-content:center;padding:7px 12px;border:3px solid var(--dd-neo-card-border);background:var(--dd-neo-card-accent);box-shadow:4px 4px 0 var(--dd-neo-card-border);font-size:11px;font-weight:900;letter-spacing:.16em;line-height:1;text-transform:uppercase;transform:rotate(-3deg)}.dd-card-neo-slab__panel{position:relative;padding:28px 22px 22px;background:linear-gradient(135deg,color-mix(in srgb,var(--dd-neo-card-accent) 28%,transparent) 0 16%,transparent 16% 100%),var(--dd-neo-card-panel)}.dd-card-neo-slab__marker{position:absolute;top:0;right:0;width:26px;height:26px;border-left:4px solid var(--dd-neo-card-border);border-bottom:4px solid var(--dd-neo-card-border);background:var(--dd-neo-card-accent)}.dd-card-neo-slab__content{position:relative;font-size:15px;line-height:1.6;font-weight:700}.dd-card-neo-slab__content :first-child{margin-top:0}.dd-card-neo-slab__content :last-child{margin-bottom:0}@media(max-width:640px){.dd-card-neo-slab{box-shadow:7px 7px 0 var(--dd-neo-card-shadow)}}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
1053
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.1", type: DuckDevCardNeobrutalSlab, isStandalone: true, selector: "dd-card-neobrutal-slab", inputs: { color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, strapLabel: { classPropertyName: "strapLabel", publicName: "strapLabel", isSignal: true, isRequired: true, transformFunction: null }, swipeable: { classPropertyName: "swipeable", publicName: "swipeable", isSignal: true, isRequired: false, transformFunction: null }, swipeThreshold: { classPropertyName: "swipeThreshold", publicName: "swipeThreshold", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { swipedLeft: "swipedLeft", swipedRight: "swipedRight" }, ngImport: i0, template: "<article\n class=\"dd-card-neo-slab\"\n [class.dd-card-neo-slab--dragging]=\"isDragging()\"\n [class.dd-card-neo-slab--swipeable]=\"swipeable()\"\n [ngStyle]=\"cardStyle()\"\n [style.cursor]=\"cursorStyle()\"\n [style.touch-action]=\"touchActionStyle()\"\n [style.transform]=\"transformStyle()\"\n [style.transition]=\"dragTransition()\"\n (pointercancel)=\"onPointerCancel($event)\"\n (pointerdown)=\"onPointerDown($event)\"\n (pointermove)=\"onPointerMove($event)\"\n (pointerup)=\"onPointerUp($event)\"\n>\n <div class=\"dd-card-neo-slab__strap\" aria-hidden=\"true\">{{ strapLabel() }}</div>\n <div class=\"dd-card-neo-slab__panel\">\n <div class=\"dd-card-neo-slab__marker\" aria-hidden=\"true\"></div>\n <div class=\"dd-card-neo-slab__content\">\n <ng-content />\n </div>\n </div>\n</article>\n", styles: [".dd-card-neo-slab{position:relative;display:block;background:var(--dd-neo-card-surface);border:4px solid var(--dd-neo-card-border);box-shadow:10px 10px 0 var(--dd-neo-card-shadow);color:var(--dd-neo-card-text);transform-origin:center bottom;will-change:transform}.dd-card-neo-slab.dd-card-neo-slab--swipeable{-webkit-user-select:none;user-select:none}.dd-card-neo-slab.dd-card-neo-slab--dragging{z-index:1}.dd-card-neo-slab__strap{position:absolute;top:-22px;left:18px;display:inline-flex;align-items:center;justify-content:center;padding:7px 12px;border:3px solid var(--dd-neo-card-border);background:var(--dd-neo-card-accent);box-shadow:4px 4px 0 var(--dd-neo-card-border);font-size:11px;font-weight:900;letter-spacing:.16em;line-height:1;text-transform:uppercase;transform:rotate(-3deg)}.dd-card-neo-slab__panel{position:relative;padding:28px 22px 22px;background:linear-gradient(135deg,color-mix(in srgb,var(--dd-neo-card-accent) 28%,transparent) 0 16%,transparent 16% 100%),var(--dd-neo-card-panel)}.dd-card-neo-slab__marker{position:absolute;top:0;right:0;width:26px;height:26px;border-left:4px solid var(--dd-neo-card-border);border-bottom:4px solid var(--dd-neo-card-border);background:var(--dd-neo-card-accent)}.dd-card-neo-slab__content{position:relative;font-size:15px;line-height:1.6;font-weight:700}.dd-card-neo-slab__content :first-child{margin-top:0}.dd-card-neo-slab__content :last-child{margin-bottom:0}@media(max-width:640px){.dd-card-neo-slab{box-shadow:7px 7px 0 var(--dd-neo-card-shadow)}}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
802
1054
  }
803
1055
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: DuckDevCardNeobrutalSlab, decorators: [{
804
1056
  type: Component,
805
- args: [{ selector: 'dd-card-neobrutal-slab', standalone: true, imports: [NgStyle], template: "<article class=\"dd-card-neo-slab\" [ngStyle]=\"cardStyle()\">\n <div class=\"dd-card-neo-slab__strap\" aria-hidden=\"true\">{{ strapLabel() }}</div>\n <div class=\"dd-card-neo-slab__panel\">\n <div class=\"dd-card-neo-slab__marker\" aria-hidden=\"true\"></div>\n <div class=\"dd-card-neo-slab__content\">\n <ng-content />\n </div>\n </div>\n</article>\n", styles: [".dd-card-neo-slab{position:relative;display:block;background:var(--dd-neo-card-surface);border:4px solid var(--dd-neo-card-border);box-shadow:10px 10px 0 var(--dd-neo-card-shadow);color:var(--dd-neo-card-text)}.dd-card-neo-slab__strap{position:absolute;top:-22px;left:18px;display:inline-flex;align-items:center;justify-content:center;padding:7px 12px;border:3px solid var(--dd-neo-card-border);background:var(--dd-neo-card-accent);box-shadow:4px 4px 0 var(--dd-neo-card-border);font-size:11px;font-weight:900;letter-spacing:.16em;line-height:1;text-transform:uppercase;transform:rotate(-3deg)}.dd-card-neo-slab__panel{position:relative;padding:28px 22px 22px;background:linear-gradient(135deg,color-mix(in srgb,var(--dd-neo-card-accent) 28%,transparent) 0 16%,transparent 16% 100%),var(--dd-neo-card-panel)}.dd-card-neo-slab__marker{position:absolute;top:0;right:0;width:26px;height:26px;border-left:4px solid var(--dd-neo-card-border);border-bottom:4px solid var(--dd-neo-card-border);background:var(--dd-neo-card-accent)}.dd-card-neo-slab__content{position:relative;font-size:15px;line-height:1.6;font-weight:700}.dd-card-neo-slab__content :first-child{margin-top:0}.dd-card-neo-slab__content :last-child{margin-bottom:0}@media(max-width:640px){.dd-card-neo-slab{box-shadow:7px 7px 0 var(--dd-neo-card-shadow)}}\n"] }]
806
- }], propDecorators: { color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], strapLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "strapLabel", required: true }] }] } });
1057
+ args: [{ selector: 'dd-card-neobrutal-slab', standalone: true, imports: [NgStyle], template: "<article\n class=\"dd-card-neo-slab\"\n [class.dd-card-neo-slab--dragging]=\"isDragging()\"\n [class.dd-card-neo-slab--swipeable]=\"swipeable()\"\n [ngStyle]=\"cardStyle()\"\n [style.cursor]=\"cursorStyle()\"\n [style.touch-action]=\"touchActionStyle()\"\n [style.transform]=\"transformStyle()\"\n [style.transition]=\"dragTransition()\"\n (pointercancel)=\"onPointerCancel($event)\"\n (pointerdown)=\"onPointerDown($event)\"\n (pointermove)=\"onPointerMove($event)\"\n (pointerup)=\"onPointerUp($event)\"\n>\n <div class=\"dd-card-neo-slab__strap\" aria-hidden=\"true\">{{ strapLabel() }}</div>\n <div class=\"dd-card-neo-slab__panel\">\n <div class=\"dd-card-neo-slab__marker\" aria-hidden=\"true\"></div>\n <div class=\"dd-card-neo-slab__content\">\n <ng-content />\n </div>\n </div>\n</article>\n", styles: [".dd-card-neo-slab{position:relative;display:block;background:var(--dd-neo-card-surface);border:4px solid var(--dd-neo-card-border);box-shadow:10px 10px 0 var(--dd-neo-card-shadow);color:var(--dd-neo-card-text);transform-origin:center bottom;will-change:transform}.dd-card-neo-slab.dd-card-neo-slab--swipeable{-webkit-user-select:none;user-select:none}.dd-card-neo-slab.dd-card-neo-slab--dragging{z-index:1}.dd-card-neo-slab__strap{position:absolute;top:-22px;left:18px;display:inline-flex;align-items:center;justify-content:center;padding:7px 12px;border:3px solid var(--dd-neo-card-border);background:var(--dd-neo-card-accent);box-shadow:4px 4px 0 var(--dd-neo-card-border);font-size:11px;font-weight:900;letter-spacing:.16em;line-height:1;text-transform:uppercase;transform:rotate(-3deg)}.dd-card-neo-slab__panel{position:relative;padding:28px 22px 22px;background:linear-gradient(135deg,color-mix(in srgb,var(--dd-neo-card-accent) 28%,transparent) 0 16%,transparent 16% 100%),var(--dd-neo-card-panel)}.dd-card-neo-slab__marker{position:absolute;top:0;right:0;width:26px;height:26px;border-left:4px solid var(--dd-neo-card-border);border-bottom:4px solid var(--dd-neo-card-border);background:var(--dd-neo-card-accent)}.dd-card-neo-slab__content{position:relative;font-size:15px;line-height:1.6;font-weight:700}.dd-card-neo-slab__content :first-child{margin-top:0}.dd-card-neo-slab__content :last-child{margin-bottom:0}@media(max-width:640px){.dd-card-neo-slab{box-shadow:7px 7px 0 var(--dd-neo-card-shadow)}}\n"] }]
1058
+ }], ctorParameters: () => [], propDecorators: { color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], strapLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "strapLabel", required: true }] }], swipeable: [{ type: i0.Input, args: [{ isSignal: true, alias: "swipeable", required: false }] }], swipeThreshold: [{ type: i0.Input, args: [{ isSignal: true, alias: "swipeThreshold", required: false }] }], swipedLeft: [{ type: i0.Output, args: ["swipedLeft"] }], swipedRight: [{ type: i0.Output, args: ["swipedRight"] }] } });
807
1059
 
808
1060
  class DuckDevCardNeobrutalStamp {
809
1061
  color = input(AccentEnumColor.Violet, { ...(ngDevMode ? { debugName: "color" } : {}) });
@@ -3450,11 +3702,71 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImpor
3450
3702
 
3451
3703
  class CardBlock {
3452
3704
  t = inject(TranslocoService);
3705
+ neobrutalSwipeDeck = [
3706
+ {
3707
+ strapLabel: 'Swipe deck',
3708
+ title: 'Launch queue',
3709
+ description: 'Swipe right to keep this release in the active sprint stack.',
3710
+ },
3711
+ {
3712
+ strapLabel: 'Triage',
3713
+ title: 'Bug backlog',
3714
+ description: 'Swipe left to skip noisy work and move to the next candidate.',
3715
+ },
3716
+ {
3717
+ strapLabel: 'Hot drop',
3718
+ title: 'Design sync',
3719
+ description: 'The demo loops through cards so the gesture can be tested repeatedly.',
3720
+ },
3721
+ ];
3722
+ neobrutalPosterSwipeDeck = [
3723
+ {
3724
+ railTop: 'Neo',
3725
+ railMiddle: 'Brut',
3726
+ railBottom: 'Keep',
3727
+ eyebrow: 'Ops bulletin',
3728
+ badge: 'Live',
3729
+ title: 'System pulse',
3730
+ description: 'Swipe right to keep this alert in the active deck.',
3731
+ metricLabel: 'Signal',
3732
+ metric: '99%',
3733
+ },
3734
+ {
3735
+ railTop: 'Skip',
3736
+ railMiddle: 'Noise',
3737
+ railBottom: 'Drop',
3738
+ eyebrow: 'Queue filter',
3739
+ badge: 'Muted',
3740
+ title: 'Alert noise',
3741
+ description: 'Swipe left to discard low-priority cards from triage.',
3742
+ metricLabel: 'Load',
3743
+ metric: '23%',
3744
+ },
3745
+ {
3746
+ railTop: 'Deck',
3747
+ railMiddle: 'Loops',
3748
+ railBottom: 'On',
3749
+ eyebrow: 'Demo mode',
3750
+ badge: 'Next',
3751
+ title: 'Preview flow',
3752
+ description: 'The example restores the next poster card after each swipe.',
3753
+ metricLabel: 'Stack',
3754
+ metric: '3',
3755
+ },
3756
+ ];
3453
3757
  colorViolet = AccentEnumColor.Violet;
3454
3758
  colorOrange = AccentEnumColor.Orange;
3455
3759
  colorWhite = AccentEnumColor.White;
3456
3760
  colorGray = AccentEnumColor.Gray;
3457
3761
  colorDark = AccentEnumColor.Dark;
3762
+ neobrutalSwipeIndex = signal(0, { ...(ngDevMode ? { debugName: "neobrutalSwipeIndex" } : {}) });
3763
+ neobrutalSwipeVisible = signal(true, { ...(ngDevMode ? { debugName: "neobrutalSwipeVisible" } : {}) });
3764
+ neobrutalSwipeStatus = signal('Swipe right to keep, swipe left to skip.', { ...(ngDevMode ? { debugName: "neobrutalSwipeStatus" } : {}) });
3765
+ neobrutalSwipeCard = computed(() => this.neobrutalSwipeDeck[this.neobrutalSwipeIndex()], { ...(ngDevMode ? { debugName: "neobrutalSwipeCard" } : {}) });
3766
+ neobrutalPosterSwipeIndex = signal(0, { ...(ngDevMode ? { debugName: "neobrutalPosterSwipeIndex" } : {}) });
3767
+ neobrutalPosterSwipeVisible = signal(true, { ...(ngDevMode ? { debugName: "neobrutalPosterSwipeVisible" } : {}) });
3768
+ neobrutalPosterSwipeStatus = signal('Poster also supports right/left swipe.', { ...(ngDevMode ? { debugName: "neobrutalPosterSwipeStatus" } : {}) });
3769
+ neobrutalPosterSwipeCard = computed(() => this.neobrutalPosterSwipeDeck[this.neobrutalPosterSwipeIndex()], { ...(ngDevMode ? { debugName: "neobrutalPosterSwipeCard" } : {}) });
3458
3770
  styleTabs = [
3459
3771
  { id: 'classic', label: this.t.translate('documentationStyleTabs.classic') },
3460
3772
  { id: 'neobrutalism', label: this.t.translate('documentationStyleTabs.neobrutalism') },
@@ -3511,13 +3823,33 @@ class CardBlock {
3511
3823
  onStyleTabChange(tab) {
3512
3824
  this.activeStyleTab.set(tab);
3513
3825
  }
3826
+ onNeobrutalSlabSwipe(direction) {
3827
+ this.neobrutalSwipeStatus.set(direction === 'right'
3828
+ ? 'Right swipe emitted `swipedRight`.'
3829
+ : 'Left swipe emitted `swipedLeft`.');
3830
+ this.neobrutalSwipeVisible.set(false);
3831
+ window.setTimeout(() => {
3832
+ this.neobrutalSwipeIndex.update((index) => (index + 1) % this.neobrutalSwipeDeck.length);
3833
+ this.neobrutalSwipeVisible.set(true);
3834
+ });
3835
+ }
3836
+ onNeobrutalPosterSwipe(direction) {
3837
+ this.neobrutalPosterSwipeStatus.set(direction === 'right'
3838
+ ? 'Poster emitted `swipedRight`.'
3839
+ : 'Poster emitted `swipedLeft`.');
3840
+ this.neobrutalPosterSwipeVisible.set(false);
3841
+ window.setTimeout(() => {
3842
+ this.neobrutalPosterSwipeIndex.update((index) => (index + 1) % this.neobrutalPosterSwipeDeck.length);
3843
+ this.neobrutalPosterSwipeVisible.set(true);
3844
+ });
3845
+ }
3514
3846
  createEl(html) {
3515
3847
  const el = document.createElement('div');
3516
3848
  el.innerHTML = html;
3517
3849
  return el;
3518
3850
  }
3519
3851
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: CardBlock, deps: [], target: i0.ɵɵFactoryTarget.Component });
3520
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.1", type: CardBlock, isStandalone: true, selector: "app-card-block", ngImport: i0, template: "<div class=\"demo-container\">\n <h1>{{ 'cardDoc.title' | transloco }}</h1>\n <duck-dev-tab [tabs]=\"styleTabs\" (tabChange)=\"onStyleTabChange($event)\">\n @if (activeStyleTab().id === 'classic') {\n\n <dd-card-section>\n <h2>{{ 'cardDoc.basic.title' | transloco }}</h2>\n <p class=\"description\">{{ 'cardDoc.basic.description' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'cardDoc.basic.usage' | transloco }}</h3>\n <pre><code>&lt;dd-card-accent [color]=\"colorWhite\"&gt;\n &lt;div [innerHTML]=\"exampleDefault.innerHTML\"&gt;&lt;/div&gt;\n &lt;/dd-card-accent&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'cardDoc.basic.inputs' | transloco }}</h3>\n <ul>\n <li>\n <dd-card-accent [color]=\"colorWhite\">\n <div [innerHTML]=\"inputContentEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n <li>\n <dd-card-accent [color]=\"colorViolet\">\n <div [innerHTML]=\"inputColorEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'cardDoc.basic.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.defaultWhite' | transloco }}</p>\n <dd-card-accent [color]=\"colorWhite\">\n <div [innerHTML]=\"exampleDefault.innerHTML\"></div>\n </dd-card-accent>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.violet' | transloco }}</p>\n <dd-card-accent [color]=\"colorViolet\">\n <div [innerHTML]=\"exampleViolet.innerHTML\"></div>\n </dd-card-accent>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.orange' | transloco }}</p>\n <dd-card-accent [color]=\"colorOrange\">\n <div [innerHTML]=\"exampleOrange.innerHTML\"></div>\n </dd-card-accent>\n </div>\n </div>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.gray' | transloco }}</p>\n <dd-card-accent [color]=\"colorGray\">\n <div [innerHTML]=\"exampleGray.innerHTML\"></div>\n </dd-card-accent>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.dark' | transloco }}</p>\n <dd-card-accent [color]=\"colorDark\">\n <div [innerHTML]=\"exampleDark.innerHTML\"></div>\n </dd-card-accent>\n </div>\n </div>\n </div>\n </dd-card-section>\n\n <dd-card-section>\n <h2>{{ 'cardDoc.minimal.title' | transloco }}</h2>\n <p class=\"description\">{{ 'cardDoc.minimal.description' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'cardDoc.minimal.usage' | transloco }}</h3>\n <pre><code>&lt;dd-card-minimal [color]=\"colorWhite\"&gt;\n &lt;div [innerHTML]=\"minimalExampleDefault.innerHTML\"&gt;&lt;/div&gt;\n &lt;/dd-card-minimal&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'cardDoc.minimal.inputs' | transloco }}</h3>\n <ul>\n <li>\n <dd-card-minimal [color]=\"colorWhite\">\n <div [innerHTML]=\"inputContentEl.innerHTML\"></div>\n </dd-card-minimal>\n </li>\n <li>\n <dd-card-minimal [color]=\"colorViolet\">\n <div [innerHTML]=\"inputColorEl.innerHTML\"></div>\n </dd-card-minimal>\n </li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'cardDoc.minimal.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.defaultWhite' | transloco }}</p>\n <dd-card-minimal [color]=\"colorWhite\">\n <div [innerHTML]=\"minimalExampleDefault.innerHTML\"></div>\n </dd-card-minimal>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.violet' | transloco }}</p>\n <dd-card-minimal [color]=\"colorViolet\">\n <div [innerHTML]=\"minimalExampleViolet.innerHTML\"></div>\n </dd-card-minimal>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.orange' | transloco }}</p>\n <dd-card-minimal [color]=\"colorOrange\">\n <div [innerHTML]=\"minimalExampleOrange.innerHTML\"></div>\n </dd-card-minimal>\n </div>\n </div>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.gray' | transloco }}</p>\n <dd-card-minimal [color]=\"colorGray\">\n <div [innerHTML]=\"minimalExampleGray.innerHTML\"></div>\n </dd-card-minimal>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.dark' | transloco }}</p>\n <dd-card-minimal [color]=\"colorDark\">\n <div [innerHTML]=\"minimalExampleDark.innerHTML\"></div>\n </dd-card-minimal>\n </div>\n </div>\n </div>\n </dd-card-section>\n\n <dd-card-section>\n <h2>{{ 'cardDoc.outline.title' | transloco }}</h2>\n <p class=\"description\">{{ 'cardDoc.outline.description' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'cardDoc.outline.usage' | transloco }}</h3>\n <pre><code>&lt;dd-card-outline [color]=\"colorWhite\"&gt;\n &lt;div [innerHTML]=\"outlineExampleDefault.innerHTML\"&gt;&lt;/div&gt;\n &lt;/dd-card-outline&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'cardDoc.outline.inputs' | transloco }}</h3>\n <ul>\n <li>\n <dd-card-outline [color]=\"colorWhite\">\n <div [innerHTML]=\"inputContentEl.innerHTML\"></div>\n </dd-card-outline>\n </li>\n <li>\n <dd-card-outline [color]=\"colorViolet\">\n <div [innerHTML]=\"inputColorEl.innerHTML\"></div>\n </dd-card-outline>\n </li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'cardDoc.outline.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.defaultWhite' | transloco }}</p>\n <dd-card-outline [color]=\"colorWhite\">\n <div [innerHTML]=\"outlineExampleDefault.innerHTML\"></div>\n </dd-card-outline>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.violet' | transloco }}</p>\n <dd-card-outline [color]=\"colorViolet\">\n <div [innerHTML]=\"outlineExampleViolet.innerHTML\"></div>\n </dd-card-outline>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.orange' | transloco }}</p>\n <dd-card-outline [color]=\"colorOrange\">\n <div [innerHTML]=\"outlineExampleOrange.innerHTML\"></div>\n </dd-card-outline>\n </div>\n </div>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.gray' | transloco }}</p>\n <dd-card-outline [color]=\"colorGray\">\n <div [innerHTML]=\"outlineExampleGray.innerHTML\"></div>\n </dd-card-outline>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.dark' | transloco }}</p>\n <dd-card-outline [color]=\"colorDark\">\n <div [innerHTML]=\"outlineExampleDark.innerHTML\"></div>\n </dd-card-outline>\n </div>\n </div>\n </div>\n </dd-card-section>\n\n <dd-card-section>\n <h2>{{ 'cardDoc.signal.title' | transloco }}</h2>\n <p class=\"description\">{{ 'cardDoc.signal.description' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'cardDoc.signal.usage' | transloco }}</h3>\n <pre><code>&lt;dd-card-signal [color]=\"colorWhite\"&gt;\n &lt;div [innerHTML]=\"signalExampleDefault.innerHTML\"&gt;&lt;/div&gt;\n &lt;/dd-card-signal&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'cardDoc.signal.inputs' | transloco }}</h3>\n <ul>\n <li>\n <dd-card-signal [color]=\"colorWhite\">\n <div [innerHTML]=\"inputContentEl.innerHTML\"></div>\n </dd-card-signal>\n </li>\n <li>\n <dd-card-signal [color]=\"colorViolet\">\n <div [innerHTML]=\"inputColorEl.innerHTML\"></div>\n </dd-card-signal>\n </li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'cardDoc.signal.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.defaultWhite' | transloco }}</p>\n <dd-card-signal [color]=\"colorWhite\">\n <div [innerHTML]=\"signalExampleDefault.innerHTML\"></div>\n </dd-card-signal>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.violet' | transloco }}</p>\n <dd-card-signal [color]=\"colorViolet\">\n <div [innerHTML]=\"signalExampleViolet.innerHTML\"></div>\n </dd-card-signal>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.orange' | transloco }}</p>\n <dd-card-signal [color]=\"colorOrange\">\n <div [innerHTML]=\"signalExampleOrange.innerHTML\"></div>\n </dd-card-signal>\n </div>\n </div>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.gray' | transloco }}</p>\n <dd-card-signal [color]=\"colorGray\">\n <div [innerHTML]=\"signalExampleGray.innerHTML\"></div>\n </dd-card-signal>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.dark' | transloco }}</p>\n <dd-card-signal [color]=\"colorDark\">\n <div [innerHTML]=\"signalExampleDark.innerHTML\"></div>\n </dd-card-signal>\n </div>\n </div>\n </div>\n </dd-card-section>\n } @else {\n <dd-card-section>\n <h2>Neobrutalism Cards</h2>\n <p class=\"description\">\n Bold card variants with hard borders, loud shadows and poster-like composition. They keep the\n same simple API: pass `[color]` and project any content through `ng-content`.\n </p>\n\n <div class=\"usage-block\">\n <h3>Neobrutalism usage</h3>\n <pre><code>&lt;dd-card-neobrutal-slab [color]=\"colorOrange\" strapLabel=\"Duck Dev\"&gt;\n &lt;h4&gt;Launch queue&lt;/h4&gt;\n &lt;p&gt;Three releases are waiting for approval.&lt;/p&gt;\n&lt;/dd-card-neobrutal-slab&gt;</code></pre>\n </div>\n\n <div class=\"examples-block\">\n <h3>Neobrutalism examples</h3>\n <div class=\"example-row\">\n <div class=\"example-item example-item--neobrutal\">\n <p class=\"example-label\">Slab / Orange</p>\n <dd-card-neobrutal-slab [color]=\"colorOrange\" strapLabel=\"Duck Dev\">\n <h4>Launch queue</h4>\n <p>Three releases are waiting for approval and one build is blocked by QA.</p>\n </dd-card-neobrutal-slab>\n </div>\n <div class=\"example-item example-item--neobrutal\">\n <p class=\"example-label\">Stamp / Violet</p>\n <dd-card-neobrutal-stamp\n [color]=\"colorViolet\"\n chromeStart=\"Fresh UI\"\n chromeEnd=\"Duck Dev\"\n sealLabel=\"Seal\"\n >\n <h4>Design drop</h4>\n <p>Fresh visual assets landed in the library and need review before sync.</p>\n </dd-card-neobrutal-stamp>\n </div>\n <div class=\"example-item example-item--neobrutal\">\n <p class=\"example-label\">Poster / Dark</p>\n <dd-card-neobrutal-poster\n [color]=\"colorDark\"\n railTop=\"Neo\"\n railMiddle=\"Brut\"\n railBottom=\"Alert\"\n eyebrow=\"Ops bulletin\"\n badge=\"Live\"\n title=\"System pulse\"\n description=\"Telemetry is clean, rate limits are stable and the service window is open.\"\n metricLabel=\"Signal\"\n metric=\"99%\"\n />\n </div>\n <app-neobrutal-ticket-card-block />\n </div>\n </div>\n </dd-card-section>\n }\n </duck-dev-tab>\n</div>\n", styles: [".demo-container{max-width:1200px;margin:0 auto;padding:40px 20px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif}.demo-container h1{font-size:36px;font-weight:700;color:var(--dd-base-600);margin-bottom:40px;text-align:center;border-bottom:3px solid var(--dd-base-accent-blue);padding-bottom:20px}.demo-container h2{font-size:28px;font-weight:600;color:var(--dd-base-500);margin-bottom:15px;border-left:4px solid var(--dd-base-accent-blue);padding-left:15px}.demo-container .description{font-size:16px;line-height:1.6;color:var(--dd-base-400);margin-bottom:25px;padding:15px;background:var(--dd-base-100);border-radius:8px;border-left:3px solid var(--dd-base-300)}.demo-container h3{font-size:20px;font-weight:600;color:var(--dd-base-500);margin-bottom:15px;margin-top:25px}.demo-container .usage-block{margin-bottom:25px}.demo-container .usage-block pre{background:var(--dd-base-600);color:var(--dd-base-100);padding:20px;border-radius:8px;overflow-x:auto;margin:0}.demo-container .usage-block pre code{font-family:Courier New,Courier,monospace;font-size:14px;line-height:1.5}.demo-container .inputs-block{margin-bottom:25px}.demo-container .inputs-block ul{list-style:none;padding:0;margin:0}.demo-container .inputs-block ul li{padding:0;margin-bottom:8px;background:transparent;border-radius:0;border:none}.demo-container .examples-block .example-row{display:flex;gap:20px;margin-bottom:20px;flex-wrap:wrap}.demo-container .examples-block .example-row .example-item{flex:1;min-width:250px;padding:20px;background:var(--dd-base-100);border-radius:8px;border:2px solid var(--dd-base-300);display:flex;flex-direction:column;align-items:stretch;gap:15px;transition:all .3s ease}.demo-container .examples-block .example-row .example-item:hover{border-color:var(--dd-base-accent-blue);box-shadow:0 4px 12px var(--dd-base-300)}.demo-container .examples-block .example-row .example-item.example-item--neobrutal{background:linear-gradient(135deg,color-mix(in srgb,var(--dd-base-accent-yellow) 24%,transparent) 0 15%,transparent 15% 100%),var(--dd-base-0);border:4px solid var(--dd-base-600);border-radius:0;box-shadow:8px 8px 0 var(--dd-base-accent-blue)}.demo-container .examples-block .example-row .example-item.example-item--neobrutal:hover{border-color:var(--dd-base-600);box-shadow:10px 10px 0 var(--dd-base-accent-orange)}.demo-container .examples-block .example-row .example-item .example-label{font-size:14px;font-weight:600;color:var(--dd-base-400);margin:0;text-align:left}@media(max-width:768px){.demo-container{padding:20px 15px}.demo-container h1{font-size:28px}.demo-container h2{font-size:24px}.demo-container .examples-block .example-row{flex-direction:column}}\n"], dependencies: [{ kind: "component", type: DuckDevCardAccent, selector: "dd-card-accent", inputs: ["color"] }, { kind: "component", type: DuckDevCardMinimal, selector: "dd-card-minimal", inputs: ["color"] }, { kind: "component", type: DuckDevCardNeobrutalPoster, selector: "dd-card-neobrutal-poster", inputs: ["color", "railTop", "railMiddle", "railBottom", "eyebrow", "title", "description", "badge", "metricLabel", "metric"] }, { kind: "component", type: DuckDevCardNeobrutalSlab, selector: "dd-card-neobrutal-slab", inputs: ["color", "strapLabel"] }, { kind: "component", type: DuckDevCardNeobrutalStamp, selector: "dd-card-neobrutal-stamp", inputs: ["color", "chromeStart", "chromeEnd", "sealLabel"] }, { kind: "component", type: DuckDevCardOutline, selector: "dd-card-outline", inputs: ["color"] }, { kind: "component", type: DuckDevCardSignal, selector: "dd-card-signal", inputs: ["color"] }, { kind: "component", type: DuckDevCardSection, selector: "dd-card-section" }, { kind: "component", type: NeobrutalTicketCardBlock, selector: "app-neobrutal-ticket-card-block" }, { kind: "component", type: DuckDevTab, selector: "duck-dev-tab", inputs: ["tabs"], outputs: ["tabChange"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
3852
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.1", type: CardBlock, isStandalone: true, selector: "app-card-block", ngImport: i0, template: "<div class=\"demo-container\">\n <h1>{{ 'cardDoc.title' | transloco }}</h1>\n <duck-dev-tab [tabs]=\"styleTabs\" (tabChange)=\"onStyleTabChange($event)\">\n @if (activeStyleTab().id === 'classic') {\n\n <dd-card-section>\n <h2>{{ 'cardDoc.basic.title' | transloco }}</h2>\n <p class=\"description\">{{ 'cardDoc.basic.description' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'cardDoc.basic.usage' | transloco }}</h3>\n <pre><code>&lt;dd-card-accent [color]=\"colorWhite\"&gt;\n &lt;div [innerHTML]=\"exampleDefault.innerHTML\"&gt;&lt;/div&gt;\n &lt;/dd-card-accent&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'cardDoc.basic.inputs' | transloco }}</h3>\n <ul>\n <li>\n <dd-card-accent [color]=\"colorWhite\">\n <div [innerHTML]=\"inputContentEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n <li>\n <dd-card-accent [color]=\"colorViolet\">\n <div [innerHTML]=\"inputColorEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'cardDoc.basic.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.defaultWhite' | transloco }}</p>\n <dd-card-accent [color]=\"colorWhite\">\n <div [innerHTML]=\"exampleDefault.innerHTML\"></div>\n </dd-card-accent>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.violet' | transloco }}</p>\n <dd-card-accent [color]=\"colorViolet\">\n <div [innerHTML]=\"exampleViolet.innerHTML\"></div>\n </dd-card-accent>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.orange' | transloco }}</p>\n <dd-card-accent [color]=\"colorOrange\">\n <div [innerHTML]=\"exampleOrange.innerHTML\"></div>\n </dd-card-accent>\n </div>\n </div>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.gray' | transloco }}</p>\n <dd-card-accent [color]=\"colorGray\">\n <div [innerHTML]=\"exampleGray.innerHTML\"></div>\n </dd-card-accent>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.dark' | transloco }}</p>\n <dd-card-accent [color]=\"colorDark\">\n <div [innerHTML]=\"exampleDark.innerHTML\"></div>\n </dd-card-accent>\n </div>\n </div>\n </div>\n </dd-card-section>\n\n <dd-card-section>\n <h2>{{ 'cardDoc.minimal.title' | transloco }}</h2>\n <p class=\"description\">{{ 'cardDoc.minimal.description' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'cardDoc.minimal.usage' | transloco }}</h3>\n <pre><code>&lt;dd-card-minimal [color]=\"colorWhite\"&gt;\n &lt;div [innerHTML]=\"minimalExampleDefault.innerHTML\"&gt;&lt;/div&gt;\n &lt;/dd-card-minimal&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'cardDoc.minimal.inputs' | transloco }}</h3>\n <ul>\n <li>\n <dd-card-minimal [color]=\"colorWhite\">\n <div [innerHTML]=\"inputContentEl.innerHTML\"></div>\n </dd-card-minimal>\n </li>\n <li>\n <dd-card-minimal [color]=\"colorViolet\">\n <div [innerHTML]=\"inputColorEl.innerHTML\"></div>\n </dd-card-minimal>\n </li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'cardDoc.minimal.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.defaultWhite' | transloco }}</p>\n <dd-card-minimal [color]=\"colorWhite\">\n <div [innerHTML]=\"minimalExampleDefault.innerHTML\"></div>\n </dd-card-minimal>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.violet' | transloco }}</p>\n <dd-card-minimal [color]=\"colorViolet\">\n <div [innerHTML]=\"minimalExampleViolet.innerHTML\"></div>\n </dd-card-minimal>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.orange' | transloco }}</p>\n <dd-card-minimal [color]=\"colorOrange\">\n <div [innerHTML]=\"minimalExampleOrange.innerHTML\"></div>\n </dd-card-minimal>\n </div>\n </div>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.gray' | transloco }}</p>\n <dd-card-minimal [color]=\"colorGray\">\n <div [innerHTML]=\"minimalExampleGray.innerHTML\"></div>\n </dd-card-minimal>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.dark' | transloco }}</p>\n <dd-card-minimal [color]=\"colorDark\">\n <div [innerHTML]=\"minimalExampleDark.innerHTML\"></div>\n </dd-card-minimal>\n </div>\n </div>\n </div>\n </dd-card-section>\n\n <dd-card-section>\n <h2>{{ 'cardDoc.outline.title' | transloco }}</h2>\n <p class=\"description\">{{ 'cardDoc.outline.description' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'cardDoc.outline.usage' | transloco }}</h3>\n <pre><code>&lt;dd-card-outline [color]=\"colorWhite\"&gt;\n &lt;div [innerHTML]=\"outlineExampleDefault.innerHTML\"&gt;&lt;/div&gt;\n &lt;/dd-card-outline&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'cardDoc.outline.inputs' | transloco }}</h3>\n <ul>\n <li>\n <dd-card-outline [color]=\"colorWhite\">\n <div [innerHTML]=\"inputContentEl.innerHTML\"></div>\n </dd-card-outline>\n </li>\n <li>\n <dd-card-outline [color]=\"colorViolet\">\n <div [innerHTML]=\"inputColorEl.innerHTML\"></div>\n </dd-card-outline>\n </li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'cardDoc.outline.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.defaultWhite' | transloco }}</p>\n <dd-card-outline [color]=\"colorWhite\">\n <div [innerHTML]=\"outlineExampleDefault.innerHTML\"></div>\n </dd-card-outline>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.violet' | transloco }}</p>\n <dd-card-outline [color]=\"colorViolet\">\n <div [innerHTML]=\"outlineExampleViolet.innerHTML\"></div>\n </dd-card-outline>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.orange' | transloco }}</p>\n <dd-card-outline [color]=\"colorOrange\">\n <div [innerHTML]=\"outlineExampleOrange.innerHTML\"></div>\n </dd-card-outline>\n </div>\n </div>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.gray' | transloco }}</p>\n <dd-card-outline [color]=\"colorGray\">\n <div [innerHTML]=\"outlineExampleGray.innerHTML\"></div>\n </dd-card-outline>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.dark' | transloco }}</p>\n <dd-card-outline [color]=\"colorDark\">\n <div [innerHTML]=\"outlineExampleDark.innerHTML\"></div>\n </dd-card-outline>\n </div>\n </div>\n </div>\n </dd-card-section>\n\n <dd-card-section>\n <h2>{{ 'cardDoc.signal.title' | transloco }}</h2>\n <p class=\"description\">{{ 'cardDoc.signal.description' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'cardDoc.signal.usage' | transloco }}</h3>\n <pre><code>&lt;dd-card-signal [color]=\"colorWhite\"&gt;\n &lt;div [innerHTML]=\"signalExampleDefault.innerHTML\"&gt;&lt;/div&gt;\n &lt;/dd-card-signal&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'cardDoc.signal.inputs' | transloco }}</h3>\n <ul>\n <li>\n <dd-card-signal [color]=\"colorWhite\">\n <div [innerHTML]=\"inputContentEl.innerHTML\"></div>\n </dd-card-signal>\n </li>\n <li>\n <dd-card-signal [color]=\"colorViolet\">\n <div [innerHTML]=\"inputColorEl.innerHTML\"></div>\n </dd-card-signal>\n </li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'cardDoc.signal.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.defaultWhite' | transloco }}</p>\n <dd-card-signal [color]=\"colorWhite\">\n <div [innerHTML]=\"signalExampleDefault.innerHTML\"></div>\n </dd-card-signal>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.violet' | transloco }}</p>\n <dd-card-signal [color]=\"colorViolet\">\n <div [innerHTML]=\"signalExampleViolet.innerHTML\"></div>\n </dd-card-signal>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.orange' | transloco }}</p>\n <dd-card-signal [color]=\"colorOrange\">\n <div [innerHTML]=\"signalExampleOrange.innerHTML\"></div>\n </dd-card-signal>\n </div>\n </div>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.gray' | transloco }}</p>\n <dd-card-signal [color]=\"colorGray\">\n <div [innerHTML]=\"signalExampleGray.innerHTML\"></div>\n </dd-card-signal>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.dark' | transloco }}</p>\n <dd-card-signal [color]=\"colorDark\">\n <div [innerHTML]=\"signalExampleDark.innerHTML\"></div>\n </dd-card-signal>\n </div>\n </div>\n </div>\n </dd-card-section>\n } @else {\n <dd-card-section>\n <h2>Neobrutalism Cards</h2>\n <p class=\"description\">\n Bold card variants with hard borders, loud shadows and poster-like composition. They keep the\n same simple API: pass `[color]` and project any content through `ng-content`.\n </p>\n\n <div class=\"usage-block\">\n <h3>Neobrutalism usage</h3>\n <pre><code>&lt;dd-card-neobrutal-slab\n [color]=\"colorOrange\"\n strapLabel=\"Swipe deck\"\n [swipeable]=\"true\"\n [swipeThreshold]=\"112\"\n (swipedLeft)=\"onNeobrutalSlabSwipe('left')\"\n (swipedRight)=\"onNeobrutalSlabSwipe('right')\"\n&gt;\n &lt;h4&gt;Launch queue&lt;/h4&gt;\n &lt;p&gt;Swipe right to keep the card, swipe left to skip it.&lt;/p&gt;\n&lt;/dd-card-neobrutal-slab&gt;</code></pre>\n <pre><code>&lt;dd-card-neobrutal-poster\n [color]=\"colorDark\"\n railTop=\"Neo\"\n railMiddle=\"Brut\"\n railBottom=\"Alert\"\n eyebrow=\"Ops bulletin\"\n badge=\"Live\"\n title=\"System pulse\"\n description=\"Swipe right to keep this card in the active deck.\"\n metricLabel=\"Signal\"\n metric=\"99%\"\n [swipeable]=\"true\"\n [swipeThreshold]=\"112\"\n (swipedLeft)=\"onNeobrutalPosterSwipe('left')\"\n (swipedRight)=\"onNeobrutalPosterSwipe('right')\"\n/&gt;</code></pre>\n </div>\n\n <div class=\"examples-block\">\n <h3>Neobrutalism examples</h3>\n <div class=\"example-row\">\n <div class=\"example-item example-item--neobrutal\">\n <p class=\"example-label\">Slab / Swipe</p>\n @if (neobrutalSwipeVisible()) {\n <dd-card-neobrutal-slab\n [color]=\"colorOrange\"\n [swipeable]=\"true\"\n [swipeThreshold]=\"112\"\n [strapLabel]=\"neobrutalSwipeCard().strapLabel\"\n (swipedLeft)=\"onNeobrutalSlabSwipe('left')\"\n (swipedRight)=\"onNeobrutalSlabSwipe('right')\"\n >\n <h4>{{ neobrutalSwipeCard().title }}</h4>\n <p>{{ neobrutalSwipeCard().description }}</p>\n </dd-card-neobrutal-slab>\n }\n <p class=\"example-note\">{{ neobrutalSwipeStatus() }}</p>\n </div>\n <div class=\"example-item example-item--neobrutal\">\n <p class=\"example-label\">Slab / Orange</p>\n <dd-card-neobrutal-slab [color]=\"colorOrange\" strapLabel=\"Duck Dev\">\n <h4>Launch queue</h4>\n <p>Three releases are waiting for approval and one build is blocked by QA.</p>\n </dd-card-neobrutal-slab>\n </div>\n <div class=\"example-item example-item--neobrutal\">\n <p class=\"example-label\">Stamp / Violet</p>\n <dd-card-neobrutal-stamp\n [color]=\"colorViolet\"\n chromeStart=\"Fresh UI\"\n chromeEnd=\"Duck Dev\"\n sealLabel=\"Seal\"\n >\n <h4>Design drop</h4>\n <p>Fresh visual assets landed in the library and need review before sync.</p>\n </dd-card-neobrutal-stamp>\n </div>\n <div class=\"example-item example-item--neobrutal\">\n <p class=\"example-label\">Poster / Swipe</p>\n @if (neobrutalPosterSwipeVisible()) {\n <dd-card-neobrutal-poster\n [color]=\"colorDark\"\n [railTop]=\"neobrutalPosterSwipeCard().railTop\"\n [railMiddle]=\"neobrutalPosterSwipeCard().railMiddle\"\n [railBottom]=\"neobrutalPosterSwipeCard().railBottom\"\n [eyebrow]=\"neobrutalPosterSwipeCard().eyebrow\"\n [badge]=\"neobrutalPosterSwipeCard().badge\"\n [title]=\"neobrutalPosterSwipeCard().title\"\n [description]=\"neobrutalPosterSwipeCard().description\"\n [metricLabel]=\"neobrutalPosterSwipeCard().metricLabel\"\n [metric]=\"neobrutalPosterSwipeCard().metric\"\n [swipeable]=\"true\"\n [swipeThreshold]=\"112\"\n (swipedLeft)=\"onNeobrutalPosterSwipe('left')\"\n (swipedRight)=\"onNeobrutalPosterSwipe('right')\"\n />\n }\n <p class=\"example-note\">{{ neobrutalPosterSwipeStatus() }}</p>\n </div>\n <div class=\"example-item example-item--neobrutal\">\n <p class=\"example-label\">Poster / Dark</p>\n <dd-card-neobrutal-poster\n [color]=\"colorDark\"\n railTop=\"Neo\"\n railMiddle=\"Brut\"\n railBottom=\"Alert\"\n eyebrow=\"Ops bulletin\"\n badge=\"Live\"\n title=\"System pulse\"\n description=\"Telemetry is clean, rate limits are stable and the service window is open.\"\n metricLabel=\"Signal\"\n metric=\"99%\"\n />\n </div>\n <app-neobrutal-ticket-card-block />\n </div>\n </div>\n </dd-card-section>\n }\n </duck-dev-tab>\n</div>\n", styles: [".demo-container{max-width:1200px;margin:0 auto;padding:40px 20px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif}.demo-container h1{font-size:36px;font-weight:700;color:var(--dd-base-600);margin-bottom:40px;text-align:center;border-bottom:3px solid var(--dd-base-accent-blue);padding-bottom:20px}.demo-container h2{font-size:28px;font-weight:600;color:var(--dd-base-500);margin-bottom:15px;border-left:4px solid var(--dd-base-accent-blue);padding-left:15px}.demo-container .description{font-size:16px;line-height:1.6;color:var(--dd-base-400);margin-bottom:25px;padding:15px;background:var(--dd-base-100);border-radius:8px;border-left:3px solid var(--dd-base-300)}.demo-container h3{font-size:20px;font-weight:600;color:var(--dd-base-500);margin-bottom:15px;margin-top:25px}.demo-container .usage-block{margin-bottom:25px}.demo-container .usage-block pre{background:var(--dd-base-600);color:var(--dd-base-100);padding:20px;border-radius:8px;overflow-x:auto;margin:0}.demo-container .usage-block pre code{font-family:Courier New,Courier,monospace;font-size:14px;line-height:1.5}.demo-container .inputs-block{margin-bottom:25px}.demo-container .inputs-block ul{list-style:none;padding:0;margin:0}.demo-container .inputs-block ul li{padding:0;margin-bottom:8px;background:transparent;border-radius:0;border:none}.demo-container .examples-block .example-row{display:flex;gap:20px;margin-bottom:20px;flex-wrap:wrap}.demo-container .examples-block .example-row .example-item{flex:1;min-width:250px;padding:20px;background:var(--dd-base-100);border-radius:8px;border:2px solid var(--dd-base-300);display:flex;flex-direction:column;align-items:stretch;gap:15px;transition:all .3s ease}.demo-container .examples-block .example-row .example-item:hover{border-color:var(--dd-base-accent-blue);box-shadow:0 4px 12px var(--dd-base-300)}.demo-container .examples-block .example-row .example-item.example-item--neobrutal{background:linear-gradient(135deg,color-mix(in srgb,var(--dd-base-accent-yellow) 24%,transparent) 0 15%,transparent 15% 100%),var(--dd-base-0);border:4px solid var(--dd-base-600);border-radius:0;box-shadow:8px 8px 0 var(--dd-base-accent-blue)}.demo-container .examples-block .example-row .example-item.example-item--neobrutal:hover{border-color:var(--dd-base-600);box-shadow:10px 10px 0 var(--dd-base-accent-orange)}.demo-container .examples-block .example-row .example-item .example-label{font-size:14px;font-weight:600;color:var(--dd-base-400);margin:0;text-align:left}.demo-container .examples-block .example-row .example-item .example-note{margin:0;padding:10px 12px;border:2px solid var(--dd-base-600);background:color-mix(in srgb,var(--dd-base-accent-yellow) 20%,var(--dd-base-0));font-size:13px;font-weight:700;line-height:1.4;color:var(--dd-base-600)}@media(max-width:768px){.demo-container{padding:20px 15px}.demo-container h1{font-size:28px}.demo-container h2{font-size:24px}.demo-container .examples-block .example-row{flex-direction:column}}\n"], dependencies: [{ kind: "component", type: DuckDevCardAccent, selector: "dd-card-accent", inputs: ["color"] }, { kind: "component", type: DuckDevCardMinimal, selector: "dd-card-minimal", inputs: ["color"] }, { kind: "component", type: DuckDevCardNeobrutalPoster, selector: "dd-card-neobrutal-poster", inputs: ["color", "railTop", "railMiddle", "railBottom", "eyebrow", "title", "description", "badge", "metricLabel", "metric", "swipeable", "swipeThreshold"], outputs: ["swipedLeft", "swipedRight"] }, { kind: "component", type: DuckDevCardNeobrutalSlab, selector: "dd-card-neobrutal-slab", inputs: ["color", "strapLabel", "swipeable", "swipeThreshold"], outputs: ["swipedLeft", "swipedRight"] }, { kind: "component", type: DuckDevCardNeobrutalStamp, selector: "dd-card-neobrutal-stamp", inputs: ["color", "chromeStart", "chromeEnd", "sealLabel"] }, { kind: "component", type: DuckDevCardOutline, selector: "dd-card-outline", inputs: ["color"] }, { kind: "component", type: DuckDevCardSignal, selector: "dd-card-signal", inputs: ["color"] }, { kind: "component", type: DuckDevCardSection, selector: "dd-card-section" }, { kind: "component", type: NeobrutalTicketCardBlock, selector: "app-neobrutal-ticket-card-block" }, { kind: "component", type: DuckDevTab, selector: "duck-dev-tab", inputs: ["tabs"], outputs: ["tabChange"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
3521
3853
  }
3522
3854
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: CardBlock, decorators: [{
3523
3855
  type: Component,
@@ -3533,7 +3865,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImpor
3533
3865
  DuckDevCardSection,
3534
3866
  NeobrutalTicketCardBlock,
3535
3867
  DuckDevTab,
3536
- ], template: "<div class=\"demo-container\">\n <h1>{{ 'cardDoc.title' | transloco }}</h1>\n <duck-dev-tab [tabs]=\"styleTabs\" (tabChange)=\"onStyleTabChange($event)\">\n @if (activeStyleTab().id === 'classic') {\n\n <dd-card-section>\n <h2>{{ 'cardDoc.basic.title' | transloco }}</h2>\n <p class=\"description\">{{ 'cardDoc.basic.description' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'cardDoc.basic.usage' | transloco }}</h3>\n <pre><code>&lt;dd-card-accent [color]=\"colorWhite\"&gt;\n &lt;div [innerHTML]=\"exampleDefault.innerHTML\"&gt;&lt;/div&gt;\n &lt;/dd-card-accent&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'cardDoc.basic.inputs' | transloco }}</h3>\n <ul>\n <li>\n <dd-card-accent [color]=\"colorWhite\">\n <div [innerHTML]=\"inputContentEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n <li>\n <dd-card-accent [color]=\"colorViolet\">\n <div [innerHTML]=\"inputColorEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'cardDoc.basic.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.defaultWhite' | transloco }}</p>\n <dd-card-accent [color]=\"colorWhite\">\n <div [innerHTML]=\"exampleDefault.innerHTML\"></div>\n </dd-card-accent>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.violet' | transloco }}</p>\n <dd-card-accent [color]=\"colorViolet\">\n <div [innerHTML]=\"exampleViolet.innerHTML\"></div>\n </dd-card-accent>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.orange' | transloco }}</p>\n <dd-card-accent [color]=\"colorOrange\">\n <div [innerHTML]=\"exampleOrange.innerHTML\"></div>\n </dd-card-accent>\n </div>\n </div>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.gray' | transloco }}</p>\n <dd-card-accent [color]=\"colorGray\">\n <div [innerHTML]=\"exampleGray.innerHTML\"></div>\n </dd-card-accent>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.dark' | transloco }}</p>\n <dd-card-accent [color]=\"colorDark\">\n <div [innerHTML]=\"exampleDark.innerHTML\"></div>\n </dd-card-accent>\n </div>\n </div>\n </div>\n </dd-card-section>\n\n <dd-card-section>\n <h2>{{ 'cardDoc.minimal.title' | transloco }}</h2>\n <p class=\"description\">{{ 'cardDoc.minimal.description' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'cardDoc.minimal.usage' | transloco }}</h3>\n <pre><code>&lt;dd-card-minimal [color]=\"colorWhite\"&gt;\n &lt;div [innerHTML]=\"minimalExampleDefault.innerHTML\"&gt;&lt;/div&gt;\n &lt;/dd-card-minimal&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'cardDoc.minimal.inputs' | transloco }}</h3>\n <ul>\n <li>\n <dd-card-minimal [color]=\"colorWhite\">\n <div [innerHTML]=\"inputContentEl.innerHTML\"></div>\n </dd-card-minimal>\n </li>\n <li>\n <dd-card-minimal [color]=\"colorViolet\">\n <div [innerHTML]=\"inputColorEl.innerHTML\"></div>\n </dd-card-minimal>\n </li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'cardDoc.minimal.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.defaultWhite' | transloco }}</p>\n <dd-card-minimal [color]=\"colorWhite\">\n <div [innerHTML]=\"minimalExampleDefault.innerHTML\"></div>\n </dd-card-minimal>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.violet' | transloco }}</p>\n <dd-card-minimal [color]=\"colorViolet\">\n <div [innerHTML]=\"minimalExampleViolet.innerHTML\"></div>\n </dd-card-minimal>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.orange' | transloco }}</p>\n <dd-card-minimal [color]=\"colorOrange\">\n <div [innerHTML]=\"minimalExampleOrange.innerHTML\"></div>\n </dd-card-minimal>\n </div>\n </div>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.gray' | transloco }}</p>\n <dd-card-minimal [color]=\"colorGray\">\n <div [innerHTML]=\"minimalExampleGray.innerHTML\"></div>\n </dd-card-minimal>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.dark' | transloco }}</p>\n <dd-card-minimal [color]=\"colorDark\">\n <div [innerHTML]=\"minimalExampleDark.innerHTML\"></div>\n </dd-card-minimal>\n </div>\n </div>\n </div>\n </dd-card-section>\n\n <dd-card-section>\n <h2>{{ 'cardDoc.outline.title' | transloco }}</h2>\n <p class=\"description\">{{ 'cardDoc.outline.description' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'cardDoc.outline.usage' | transloco }}</h3>\n <pre><code>&lt;dd-card-outline [color]=\"colorWhite\"&gt;\n &lt;div [innerHTML]=\"outlineExampleDefault.innerHTML\"&gt;&lt;/div&gt;\n &lt;/dd-card-outline&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'cardDoc.outline.inputs' | transloco }}</h3>\n <ul>\n <li>\n <dd-card-outline [color]=\"colorWhite\">\n <div [innerHTML]=\"inputContentEl.innerHTML\"></div>\n </dd-card-outline>\n </li>\n <li>\n <dd-card-outline [color]=\"colorViolet\">\n <div [innerHTML]=\"inputColorEl.innerHTML\"></div>\n </dd-card-outline>\n </li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'cardDoc.outline.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.defaultWhite' | transloco }}</p>\n <dd-card-outline [color]=\"colorWhite\">\n <div [innerHTML]=\"outlineExampleDefault.innerHTML\"></div>\n </dd-card-outline>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.violet' | transloco }}</p>\n <dd-card-outline [color]=\"colorViolet\">\n <div [innerHTML]=\"outlineExampleViolet.innerHTML\"></div>\n </dd-card-outline>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.orange' | transloco }}</p>\n <dd-card-outline [color]=\"colorOrange\">\n <div [innerHTML]=\"outlineExampleOrange.innerHTML\"></div>\n </dd-card-outline>\n </div>\n </div>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.gray' | transloco }}</p>\n <dd-card-outline [color]=\"colorGray\">\n <div [innerHTML]=\"outlineExampleGray.innerHTML\"></div>\n </dd-card-outline>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.dark' | transloco }}</p>\n <dd-card-outline [color]=\"colorDark\">\n <div [innerHTML]=\"outlineExampleDark.innerHTML\"></div>\n </dd-card-outline>\n </div>\n </div>\n </div>\n </dd-card-section>\n\n <dd-card-section>\n <h2>{{ 'cardDoc.signal.title' | transloco }}</h2>\n <p class=\"description\">{{ 'cardDoc.signal.description' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'cardDoc.signal.usage' | transloco }}</h3>\n <pre><code>&lt;dd-card-signal [color]=\"colorWhite\"&gt;\n &lt;div [innerHTML]=\"signalExampleDefault.innerHTML\"&gt;&lt;/div&gt;\n &lt;/dd-card-signal&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'cardDoc.signal.inputs' | transloco }}</h3>\n <ul>\n <li>\n <dd-card-signal [color]=\"colorWhite\">\n <div [innerHTML]=\"inputContentEl.innerHTML\"></div>\n </dd-card-signal>\n </li>\n <li>\n <dd-card-signal [color]=\"colorViolet\">\n <div [innerHTML]=\"inputColorEl.innerHTML\"></div>\n </dd-card-signal>\n </li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'cardDoc.signal.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.defaultWhite' | transloco }}</p>\n <dd-card-signal [color]=\"colorWhite\">\n <div [innerHTML]=\"signalExampleDefault.innerHTML\"></div>\n </dd-card-signal>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.violet' | transloco }}</p>\n <dd-card-signal [color]=\"colorViolet\">\n <div [innerHTML]=\"signalExampleViolet.innerHTML\"></div>\n </dd-card-signal>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.orange' | transloco }}</p>\n <dd-card-signal [color]=\"colorOrange\">\n <div [innerHTML]=\"signalExampleOrange.innerHTML\"></div>\n </dd-card-signal>\n </div>\n </div>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.gray' | transloco }}</p>\n <dd-card-signal [color]=\"colorGray\">\n <div [innerHTML]=\"signalExampleGray.innerHTML\"></div>\n </dd-card-signal>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.dark' | transloco }}</p>\n <dd-card-signal [color]=\"colorDark\">\n <div [innerHTML]=\"signalExampleDark.innerHTML\"></div>\n </dd-card-signal>\n </div>\n </div>\n </div>\n </dd-card-section>\n } @else {\n <dd-card-section>\n <h2>Neobrutalism Cards</h2>\n <p class=\"description\">\n Bold card variants with hard borders, loud shadows and poster-like composition. They keep the\n same simple API: pass `[color]` and project any content through `ng-content`.\n </p>\n\n <div class=\"usage-block\">\n <h3>Neobrutalism usage</h3>\n <pre><code>&lt;dd-card-neobrutal-slab [color]=\"colorOrange\" strapLabel=\"Duck Dev\"&gt;\n &lt;h4&gt;Launch queue&lt;/h4&gt;\n &lt;p&gt;Three releases are waiting for approval.&lt;/p&gt;\n&lt;/dd-card-neobrutal-slab&gt;</code></pre>\n </div>\n\n <div class=\"examples-block\">\n <h3>Neobrutalism examples</h3>\n <div class=\"example-row\">\n <div class=\"example-item example-item--neobrutal\">\n <p class=\"example-label\">Slab / Orange</p>\n <dd-card-neobrutal-slab [color]=\"colorOrange\" strapLabel=\"Duck Dev\">\n <h4>Launch queue</h4>\n <p>Three releases are waiting for approval and one build is blocked by QA.</p>\n </dd-card-neobrutal-slab>\n </div>\n <div class=\"example-item example-item--neobrutal\">\n <p class=\"example-label\">Stamp / Violet</p>\n <dd-card-neobrutal-stamp\n [color]=\"colorViolet\"\n chromeStart=\"Fresh UI\"\n chromeEnd=\"Duck Dev\"\n sealLabel=\"Seal\"\n >\n <h4>Design drop</h4>\n <p>Fresh visual assets landed in the library and need review before sync.</p>\n </dd-card-neobrutal-stamp>\n </div>\n <div class=\"example-item example-item--neobrutal\">\n <p class=\"example-label\">Poster / Dark</p>\n <dd-card-neobrutal-poster\n [color]=\"colorDark\"\n railTop=\"Neo\"\n railMiddle=\"Brut\"\n railBottom=\"Alert\"\n eyebrow=\"Ops bulletin\"\n badge=\"Live\"\n title=\"System pulse\"\n description=\"Telemetry is clean, rate limits are stable and the service window is open.\"\n metricLabel=\"Signal\"\n metric=\"99%\"\n />\n </div>\n <app-neobrutal-ticket-card-block />\n </div>\n </div>\n </dd-card-section>\n }\n </duck-dev-tab>\n</div>\n", styles: [".demo-container{max-width:1200px;margin:0 auto;padding:40px 20px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif}.demo-container h1{font-size:36px;font-weight:700;color:var(--dd-base-600);margin-bottom:40px;text-align:center;border-bottom:3px solid var(--dd-base-accent-blue);padding-bottom:20px}.demo-container h2{font-size:28px;font-weight:600;color:var(--dd-base-500);margin-bottom:15px;border-left:4px solid var(--dd-base-accent-blue);padding-left:15px}.demo-container .description{font-size:16px;line-height:1.6;color:var(--dd-base-400);margin-bottom:25px;padding:15px;background:var(--dd-base-100);border-radius:8px;border-left:3px solid var(--dd-base-300)}.demo-container h3{font-size:20px;font-weight:600;color:var(--dd-base-500);margin-bottom:15px;margin-top:25px}.demo-container .usage-block{margin-bottom:25px}.demo-container .usage-block pre{background:var(--dd-base-600);color:var(--dd-base-100);padding:20px;border-radius:8px;overflow-x:auto;margin:0}.demo-container .usage-block pre code{font-family:Courier New,Courier,monospace;font-size:14px;line-height:1.5}.demo-container .inputs-block{margin-bottom:25px}.demo-container .inputs-block ul{list-style:none;padding:0;margin:0}.demo-container .inputs-block ul li{padding:0;margin-bottom:8px;background:transparent;border-radius:0;border:none}.demo-container .examples-block .example-row{display:flex;gap:20px;margin-bottom:20px;flex-wrap:wrap}.demo-container .examples-block .example-row .example-item{flex:1;min-width:250px;padding:20px;background:var(--dd-base-100);border-radius:8px;border:2px solid var(--dd-base-300);display:flex;flex-direction:column;align-items:stretch;gap:15px;transition:all .3s ease}.demo-container .examples-block .example-row .example-item:hover{border-color:var(--dd-base-accent-blue);box-shadow:0 4px 12px var(--dd-base-300)}.demo-container .examples-block .example-row .example-item.example-item--neobrutal{background:linear-gradient(135deg,color-mix(in srgb,var(--dd-base-accent-yellow) 24%,transparent) 0 15%,transparent 15% 100%),var(--dd-base-0);border:4px solid var(--dd-base-600);border-radius:0;box-shadow:8px 8px 0 var(--dd-base-accent-blue)}.demo-container .examples-block .example-row .example-item.example-item--neobrutal:hover{border-color:var(--dd-base-600);box-shadow:10px 10px 0 var(--dd-base-accent-orange)}.demo-container .examples-block .example-row .example-item .example-label{font-size:14px;font-weight:600;color:var(--dd-base-400);margin:0;text-align:left}@media(max-width:768px){.demo-container{padding:20px 15px}.demo-container h1{font-size:28px}.demo-container h2{font-size:24px}.demo-container .examples-block .example-row{flex-direction:column}}\n"] }]
3868
+ ], template: "<div class=\"demo-container\">\n <h1>{{ 'cardDoc.title' | transloco }}</h1>\n <duck-dev-tab [tabs]=\"styleTabs\" (tabChange)=\"onStyleTabChange($event)\">\n @if (activeStyleTab().id === 'classic') {\n\n <dd-card-section>\n <h2>{{ 'cardDoc.basic.title' | transloco }}</h2>\n <p class=\"description\">{{ 'cardDoc.basic.description' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'cardDoc.basic.usage' | transloco }}</h3>\n <pre><code>&lt;dd-card-accent [color]=\"colorWhite\"&gt;\n &lt;div [innerHTML]=\"exampleDefault.innerHTML\"&gt;&lt;/div&gt;\n &lt;/dd-card-accent&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'cardDoc.basic.inputs' | transloco }}</h3>\n <ul>\n <li>\n <dd-card-accent [color]=\"colorWhite\">\n <div [innerHTML]=\"inputContentEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n <li>\n <dd-card-accent [color]=\"colorViolet\">\n <div [innerHTML]=\"inputColorEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'cardDoc.basic.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.defaultWhite' | transloco }}</p>\n <dd-card-accent [color]=\"colorWhite\">\n <div [innerHTML]=\"exampleDefault.innerHTML\"></div>\n </dd-card-accent>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.violet' | transloco }}</p>\n <dd-card-accent [color]=\"colorViolet\">\n <div [innerHTML]=\"exampleViolet.innerHTML\"></div>\n </dd-card-accent>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.orange' | transloco }}</p>\n <dd-card-accent [color]=\"colorOrange\">\n <div [innerHTML]=\"exampleOrange.innerHTML\"></div>\n </dd-card-accent>\n </div>\n </div>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.gray' | transloco }}</p>\n <dd-card-accent [color]=\"colorGray\">\n <div [innerHTML]=\"exampleGray.innerHTML\"></div>\n </dd-card-accent>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.dark' | transloco }}</p>\n <dd-card-accent [color]=\"colorDark\">\n <div [innerHTML]=\"exampleDark.innerHTML\"></div>\n </dd-card-accent>\n </div>\n </div>\n </div>\n </dd-card-section>\n\n <dd-card-section>\n <h2>{{ 'cardDoc.minimal.title' | transloco }}</h2>\n <p class=\"description\">{{ 'cardDoc.minimal.description' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'cardDoc.minimal.usage' | transloco }}</h3>\n <pre><code>&lt;dd-card-minimal [color]=\"colorWhite\"&gt;\n &lt;div [innerHTML]=\"minimalExampleDefault.innerHTML\"&gt;&lt;/div&gt;\n &lt;/dd-card-minimal&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'cardDoc.minimal.inputs' | transloco }}</h3>\n <ul>\n <li>\n <dd-card-minimal [color]=\"colorWhite\">\n <div [innerHTML]=\"inputContentEl.innerHTML\"></div>\n </dd-card-minimal>\n </li>\n <li>\n <dd-card-minimal [color]=\"colorViolet\">\n <div [innerHTML]=\"inputColorEl.innerHTML\"></div>\n </dd-card-minimal>\n </li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'cardDoc.minimal.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.defaultWhite' | transloco }}</p>\n <dd-card-minimal [color]=\"colorWhite\">\n <div [innerHTML]=\"minimalExampleDefault.innerHTML\"></div>\n </dd-card-minimal>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.violet' | transloco }}</p>\n <dd-card-minimal [color]=\"colorViolet\">\n <div [innerHTML]=\"minimalExampleViolet.innerHTML\"></div>\n </dd-card-minimal>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.orange' | transloco }}</p>\n <dd-card-minimal [color]=\"colorOrange\">\n <div [innerHTML]=\"minimalExampleOrange.innerHTML\"></div>\n </dd-card-minimal>\n </div>\n </div>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.gray' | transloco }}</p>\n <dd-card-minimal [color]=\"colorGray\">\n <div [innerHTML]=\"minimalExampleGray.innerHTML\"></div>\n </dd-card-minimal>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.dark' | transloco }}</p>\n <dd-card-minimal [color]=\"colorDark\">\n <div [innerHTML]=\"minimalExampleDark.innerHTML\"></div>\n </dd-card-minimal>\n </div>\n </div>\n </div>\n </dd-card-section>\n\n <dd-card-section>\n <h2>{{ 'cardDoc.outline.title' | transloco }}</h2>\n <p class=\"description\">{{ 'cardDoc.outline.description' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'cardDoc.outline.usage' | transloco }}</h3>\n <pre><code>&lt;dd-card-outline [color]=\"colorWhite\"&gt;\n &lt;div [innerHTML]=\"outlineExampleDefault.innerHTML\"&gt;&lt;/div&gt;\n &lt;/dd-card-outline&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'cardDoc.outline.inputs' | transloco }}</h3>\n <ul>\n <li>\n <dd-card-outline [color]=\"colorWhite\">\n <div [innerHTML]=\"inputContentEl.innerHTML\"></div>\n </dd-card-outline>\n </li>\n <li>\n <dd-card-outline [color]=\"colorViolet\">\n <div [innerHTML]=\"inputColorEl.innerHTML\"></div>\n </dd-card-outline>\n </li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'cardDoc.outline.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.defaultWhite' | transloco }}</p>\n <dd-card-outline [color]=\"colorWhite\">\n <div [innerHTML]=\"outlineExampleDefault.innerHTML\"></div>\n </dd-card-outline>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.violet' | transloco }}</p>\n <dd-card-outline [color]=\"colorViolet\">\n <div [innerHTML]=\"outlineExampleViolet.innerHTML\"></div>\n </dd-card-outline>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.orange' | transloco }}</p>\n <dd-card-outline [color]=\"colorOrange\">\n <div [innerHTML]=\"outlineExampleOrange.innerHTML\"></div>\n </dd-card-outline>\n </div>\n </div>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.gray' | transloco }}</p>\n <dd-card-outline [color]=\"colorGray\">\n <div [innerHTML]=\"outlineExampleGray.innerHTML\"></div>\n </dd-card-outline>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.dark' | transloco }}</p>\n <dd-card-outline [color]=\"colorDark\">\n <div [innerHTML]=\"outlineExampleDark.innerHTML\"></div>\n </dd-card-outline>\n </div>\n </div>\n </div>\n </dd-card-section>\n\n <dd-card-section>\n <h2>{{ 'cardDoc.signal.title' | transloco }}</h2>\n <p class=\"description\">{{ 'cardDoc.signal.description' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'cardDoc.signal.usage' | transloco }}</h3>\n <pre><code>&lt;dd-card-signal [color]=\"colorWhite\"&gt;\n &lt;div [innerHTML]=\"signalExampleDefault.innerHTML\"&gt;&lt;/div&gt;\n &lt;/dd-card-signal&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'cardDoc.signal.inputs' | transloco }}</h3>\n <ul>\n <li>\n <dd-card-signal [color]=\"colorWhite\">\n <div [innerHTML]=\"inputContentEl.innerHTML\"></div>\n </dd-card-signal>\n </li>\n <li>\n <dd-card-signal [color]=\"colorViolet\">\n <div [innerHTML]=\"inputColorEl.innerHTML\"></div>\n </dd-card-signal>\n </li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'cardDoc.signal.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.defaultWhite' | transloco }}</p>\n <dd-card-signal [color]=\"colorWhite\">\n <div [innerHTML]=\"signalExampleDefault.innerHTML\"></div>\n </dd-card-signal>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.violet' | transloco }}</p>\n <dd-card-signal [color]=\"colorViolet\">\n <div [innerHTML]=\"signalExampleViolet.innerHTML\"></div>\n </dd-card-signal>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.orange' | transloco }}</p>\n <dd-card-signal [color]=\"colorOrange\">\n <div [innerHTML]=\"signalExampleOrange.innerHTML\"></div>\n </dd-card-signal>\n </div>\n </div>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.gray' | transloco }}</p>\n <dd-card-signal [color]=\"colorGray\">\n <div [innerHTML]=\"signalExampleGray.innerHTML\"></div>\n </dd-card-signal>\n </div>\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'cardDoc.examples.dark' | transloco }}</p>\n <dd-card-signal [color]=\"colorDark\">\n <div [innerHTML]=\"signalExampleDark.innerHTML\"></div>\n </dd-card-signal>\n </div>\n </div>\n </div>\n </dd-card-section>\n } @else {\n <dd-card-section>\n <h2>Neobrutalism Cards</h2>\n <p class=\"description\">\n Bold card variants with hard borders, loud shadows and poster-like composition. They keep the\n same simple API: pass `[color]` and project any content through `ng-content`.\n </p>\n\n <div class=\"usage-block\">\n <h3>Neobrutalism usage</h3>\n <pre><code>&lt;dd-card-neobrutal-slab\n [color]=\"colorOrange\"\n strapLabel=\"Swipe deck\"\n [swipeable]=\"true\"\n [swipeThreshold]=\"112\"\n (swipedLeft)=\"onNeobrutalSlabSwipe('left')\"\n (swipedRight)=\"onNeobrutalSlabSwipe('right')\"\n&gt;\n &lt;h4&gt;Launch queue&lt;/h4&gt;\n &lt;p&gt;Swipe right to keep the card, swipe left to skip it.&lt;/p&gt;\n&lt;/dd-card-neobrutal-slab&gt;</code></pre>\n <pre><code>&lt;dd-card-neobrutal-poster\n [color]=\"colorDark\"\n railTop=\"Neo\"\n railMiddle=\"Brut\"\n railBottom=\"Alert\"\n eyebrow=\"Ops bulletin\"\n badge=\"Live\"\n title=\"System pulse\"\n description=\"Swipe right to keep this card in the active deck.\"\n metricLabel=\"Signal\"\n metric=\"99%\"\n [swipeable]=\"true\"\n [swipeThreshold]=\"112\"\n (swipedLeft)=\"onNeobrutalPosterSwipe('left')\"\n (swipedRight)=\"onNeobrutalPosterSwipe('right')\"\n/&gt;</code></pre>\n </div>\n\n <div class=\"examples-block\">\n <h3>Neobrutalism examples</h3>\n <div class=\"example-row\">\n <div class=\"example-item example-item--neobrutal\">\n <p class=\"example-label\">Slab / Swipe</p>\n @if (neobrutalSwipeVisible()) {\n <dd-card-neobrutal-slab\n [color]=\"colorOrange\"\n [swipeable]=\"true\"\n [swipeThreshold]=\"112\"\n [strapLabel]=\"neobrutalSwipeCard().strapLabel\"\n (swipedLeft)=\"onNeobrutalSlabSwipe('left')\"\n (swipedRight)=\"onNeobrutalSlabSwipe('right')\"\n >\n <h4>{{ neobrutalSwipeCard().title }}</h4>\n <p>{{ neobrutalSwipeCard().description }}</p>\n </dd-card-neobrutal-slab>\n }\n <p class=\"example-note\">{{ neobrutalSwipeStatus() }}</p>\n </div>\n <div class=\"example-item example-item--neobrutal\">\n <p class=\"example-label\">Slab / Orange</p>\n <dd-card-neobrutal-slab [color]=\"colorOrange\" strapLabel=\"Duck Dev\">\n <h4>Launch queue</h4>\n <p>Three releases are waiting for approval and one build is blocked by QA.</p>\n </dd-card-neobrutal-slab>\n </div>\n <div class=\"example-item example-item--neobrutal\">\n <p class=\"example-label\">Stamp / Violet</p>\n <dd-card-neobrutal-stamp\n [color]=\"colorViolet\"\n chromeStart=\"Fresh UI\"\n chromeEnd=\"Duck Dev\"\n sealLabel=\"Seal\"\n >\n <h4>Design drop</h4>\n <p>Fresh visual assets landed in the library and need review before sync.</p>\n </dd-card-neobrutal-stamp>\n </div>\n <div class=\"example-item example-item--neobrutal\">\n <p class=\"example-label\">Poster / Swipe</p>\n @if (neobrutalPosterSwipeVisible()) {\n <dd-card-neobrutal-poster\n [color]=\"colorDark\"\n [railTop]=\"neobrutalPosterSwipeCard().railTop\"\n [railMiddle]=\"neobrutalPosterSwipeCard().railMiddle\"\n [railBottom]=\"neobrutalPosterSwipeCard().railBottom\"\n [eyebrow]=\"neobrutalPosterSwipeCard().eyebrow\"\n [badge]=\"neobrutalPosterSwipeCard().badge\"\n [title]=\"neobrutalPosterSwipeCard().title\"\n [description]=\"neobrutalPosterSwipeCard().description\"\n [metricLabel]=\"neobrutalPosterSwipeCard().metricLabel\"\n [metric]=\"neobrutalPosterSwipeCard().metric\"\n [swipeable]=\"true\"\n [swipeThreshold]=\"112\"\n (swipedLeft)=\"onNeobrutalPosterSwipe('left')\"\n (swipedRight)=\"onNeobrutalPosterSwipe('right')\"\n />\n }\n <p class=\"example-note\">{{ neobrutalPosterSwipeStatus() }}</p>\n </div>\n <div class=\"example-item example-item--neobrutal\">\n <p class=\"example-label\">Poster / Dark</p>\n <dd-card-neobrutal-poster\n [color]=\"colorDark\"\n railTop=\"Neo\"\n railMiddle=\"Brut\"\n railBottom=\"Alert\"\n eyebrow=\"Ops bulletin\"\n badge=\"Live\"\n title=\"System pulse\"\n description=\"Telemetry is clean, rate limits are stable and the service window is open.\"\n metricLabel=\"Signal\"\n metric=\"99%\"\n />\n </div>\n <app-neobrutal-ticket-card-block />\n </div>\n </div>\n </dd-card-section>\n }\n </duck-dev-tab>\n</div>\n", styles: [".demo-container{max-width:1200px;margin:0 auto;padding:40px 20px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif}.demo-container h1{font-size:36px;font-weight:700;color:var(--dd-base-600);margin-bottom:40px;text-align:center;border-bottom:3px solid var(--dd-base-accent-blue);padding-bottom:20px}.demo-container h2{font-size:28px;font-weight:600;color:var(--dd-base-500);margin-bottom:15px;border-left:4px solid var(--dd-base-accent-blue);padding-left:15px}.demo-container .description{font-size:16px;line-height:1.6;color:var(--dd-base-400);margin-bottom:25px;padding:15px;background:var(--dd-base-100);border-radius:8px;border-left:3px solid var(--dd-base-300)}.demo-container h3{font-size:20px;font-weight:600;color:var(--dd-base-500);margin-bottom:15px;margin-top:25px}.demo-container .usage-block{margin-bottom:25px}.demo-container .usage-block pre{background:var(--dd-base-600);color:var(--dd-base-100);padding:20px;border-radius:8px;overflow-x:auto;margin:0}.demo-container .usage-block pre code{font-family:Courier New,Courier,monospace;font-size:14px;line-height:1.5}.demo-container .inputs-block{margin-bottom:25px}.demo-container .inputs-block ul{list-style:none;padding:0;margin:0}.demo-container .inputs-block ul li{padding:0;margin-bottom:8px;background:transparent;border-radius:0;border:none}.demo-container .examples-block .example-row{display:flex;gap:20px;margin-bottom:20px;flex-wrap:wrap}.demo-container .examples-block .example-row .example-item{flex:1;min-width:250px;padding:20px;background:var(--dd-base-100);border-radius:8px;border:2px solid var(--dd-base-300);display:flex;flex-direction:column;align-items:stretch;gap:15px;transition:all .3s ease}.demo-container .examples-block .example-row .example-item:hover{border-color:var(--dd-base-accent-blue);box-shadow:0 4px 12px var(--dd-base-300)}.demo-container .examples-block .example-row .example-item.example-item--neobrutal{background:linear-gradient(135deg,color-mix(in srgb,var(--dd-base-accent-yellow) 24%,transparent) 0 15%,transparent 15% 100%),var(--dd-base-0);border:4px solid var(--dd-base-600);border-radius:0;box-shadow:8px 8px 0 var(--dd-base-accent-blue)}.demo-container .examples-block .example-row .example-item.example-item--neobrutal:hover{border-color:var(--dd-base-600);box-shadow:10px 10px 0 var(--dd-base-accent-orange)}.demo-container .examples-block .example-row .example-item .example-label{font-size:14px;font-weight:600;color:var(--dd-base-400);margin:0;text-align:left}.demo-container .examples-block .example-row .example-item .example-note{margin:0;padding:10px 12px;border:2px solid var(--dd-base-600);background:color-mix(in srgb,var(--dd-base-accent-yellow) 20%,var(--dd-base-0));font-size:13px;font-weight:700;line-height:1.4;color:var(--dd-base-600)}@media(max-width:768px){.demo-container{padding:20px 15px}.demo-container h1{font-size:28px}.demo-container h2{font-size:24px}.demo-container .examples-block .example-row{flex-direction:column}}\n"] }]
3537
3869
  }], ctorParameters: () => [] });
3538
3870
 
3539
3871
  class DuckDevTooltip {
@@ -3759,18 +4091,144 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImpor
3759
4091
  args: [DuckDevSegmentButton]
3760
4092
  }], buttonsContainer: [{ type: i0.ViewChild, args: ['buttonsContainer', { isSignal: true }] }] } });
3761
4093
 
4094
+ class DuckDevSegmentNeobrutal {
4095
+ cdr = inject(ChangeDetectorRef);
4096
+ value = input(undefined, { ...(ngDevMode ? { debugName: "value" } : {}) });
4097
+ color = input(AccentEnumColor.White, { ...(ngDevMode ? { debugName: "color" } : {}) });
4098
+ valueChange = output();
4099
+ ionChange = output();
4100
+ segmentButtons;
4101
+ buttonsContainer = viewChild.required('buttonsContainer');
4102
+ buttons = [];
4103
+ selectedValue;
4104
+ indicatorPosition = 0;
4105
+ indicatorWidth = 0;
4106
+ segmentStyle = computed(() => this.getSegmentStyle(this.color()), { ...(ngDevMode ? { debugName: "segmentStyle" } : {}) });
4107
+ constructor() {
4108
+ afterNextRender(() => {
4109
+ this.rebuildButtons();
4110
+ if (!this.selectedValue && this.buttons.length > 0) {
4111
+ this.selectedValue = this.buttons[0].value;
4112
+ }
4113
+ this.updateIndicator(this.getSelectedIndex());
4114
+ this.cdr.markForCheck();
4115
+ });
4116
+ }
4117
+ ngAfterContentInit() {
4118
+ this.rebuildButtons();
4119
+ const incoming = this.value();
4120
+ this.selectedValue = incoming ?? this.selectedValue;
4121
+ this.segmentButtons.changes.subscribe(() => {
4122
+ this.rebuildButtons();
4123
+ setTimeout(() => this.updateIndicator(this.getSelectedIndex()));
4124
+ });
4125
+ }
4126
+ selectButton(value, index) {
4127
+ if (this.selectedValue === value) {
4128
+ this.updateIndicator(index);
4129
+ return;
4130
+ }
4131
+ this.selectedValue = value;
4132
+ this.valueChange.emit(value);
4133
+ this.ionChange.emit({ detail: { value } });
4134
+ this.updateIndicator(index);
4135
+ }
4136
+ rebuildButtons() {
4137
+ const btns = this.segmentButtons?.toArray() ?? [];
4138
+ this.buttons = btns.map((button) => ({
4139
+ value: button.value(),
4140
+ contentId: button.contentId(),
4141
+ template: button.templateRef(),
4142
+ }));
4143
+ }
4144
+ getSelectedIndex() {
4145
+ return Math.max(0, this.buttons.findIndex((button) => button.value === this.selectedValue));
4146
+ }
4147
+ updateIndicator(index) {
4148
+ const container = this.buttonsContainer().nativeElement;
4149
+ const buttonElements = container.querySelectorAll('.dd-segment-neo__button');
4150
+ if (buttonElements[index]) {
4151
+ const button = buttonElements[index];
4152
+ this.indicatorWidth = button.offsetWidth;
4153
+ this.indicatorPosition = button.offsetLeft;
4154
+ }
4155
+ }
4156
+ getSegmentStyle(color) {
4157
+ switch (color) {
4158
+ case AccentEnumColor.Violet:
4159
+ return {
4160
+ '--dd-segment-neo-surface': 'var(--dd-base-secondary)',
4161
+ '--dd-segment-neo-panel': 'color-mix(in srgb, var(--dd-base-secondary) 84%, var(--dd-base-0))',
4162
+ '--dd-segment-neo-accent': 'var(--dd-base-accent-yellow)',
4163
+ '--dd-segment-neo-shadow': 'var(--dd-base-accent-blue)',
4164
+ '--dd-segment-neo-text': 'var(--dd-base-0)',
4165
+ '--dd-segment-neo-muted': 'color-mix(in srgb, var(--dd-base-0) 74%, transparent)',
4166
+ };
4167
+ case AccentEnumColor.Orange:
4168
+ return {
4169
+ '--dd-segment-neo-surface': 'var(--dd-base-accent-orange)',
4170
+ '--dd-segment-neo-panel': 'color-mix(in srgb, var(--dd-base-accent-yellow) 68%, var(--dd-base-0))',
4171
+ '--dd-segment-neo-accent': 'var(--dd-base-accent-pink)',
4172
+ '--dd-segment-neo-shadow': 'var(--dd-base-accent-yellow)',
4173
+ '--dd-segment-neo-text': 'var(--dd-base-600)',
4174
+ '--dd-segment-neo-muted': 'color-mix(in srgb, var(--dd-base-600) 66%, transparent)',
4175
+ };
4176
+ case AccentEnumColor.Gray:
4177
+ return {
4178
+ '--dd-segment-neo-surface': 'var(--dd-base-100)',
4179
+ '--dd-segment-neo-panel': 'var(--dd-base-0)',
4180
+ '--dd-segment-neo-accent': 'var(--dd-base-accent-blue)',
4181
+ '--dd-segment-neo-shadow': 'var(--dd-base-400)',
4182
+ '--dd-segment-neo-text': 'var(--dd-base-600)',
4183
+ '--dd-segment-neo-muted': 'color-mix(in srgb, var(--dd-base-600) 58%, transparent)',
4184
+ };
4185
+ case AccentEnumColor.Dark:
4186
+ return {
4187
+ '--dd-segment-neo-surface': 'var(--dd-base-600)',
4188
+ '--dd-segment-neo-panel': 'color-mix(in srgb, var(--dd-base-600) 92%, var(--dd-base-500))',
4189
+ '--dd-segment-neo-accent': 'var(--dd-base-accent-yellow)',
4190
+ '--dd-segment-neo-shadow': 'var(--dd-base-accent-orange)',
4191
+ '--dd-segment-neo-text': 'var(--dd-base-0)',
4192
+ '--dd-segment-neo-muted': 'color-mix(in srgb, var(--dd-base-0) 68%, transparent)',
4193
+ };
4194
+ case AccentEnumColor.White:
4195
+ default:
4196
+ return {
4197
+ '--dd-segment-neo-surface': 'var(--dd-base-0)',
4198
+ '--dd-segment-neo-panel': 'var(--dd-base-100)',
4199
+ '--dd-segment-neo-accent': 'var(--dd-base-accent-orange)',
4200
+ '--dd-segment-neo-shadow': 'var(--dd-base-accent-blue)',
4201
+ '--dd-segment-neo-text': 'var(--dd-base-600)',
4202
+ '--dd-segment-neo-muted': 'color-mix(in srgb, var(--dd-base-600) 58%, transparent)',
4203
+ };
4204
+ }
4205
+ }
4206
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: DuckDevSegmentNeobrutal, deps: [], target: i0.ɵɵFactoryTarget.Component });
4207
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.1", type: DuckDevSegmentNeobrutal, isStandalone: true, selector: "duck-dev-segment-neobrutal", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", ionChange: "ionChange" }, queries: [{ propertyName: "segmentButtons", predicate: DuckDevSegmentButton }], viewQueries: [{ propertyName: "buttonsContainer", first: true, predicate: ["buttonsContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"dd-segment-neo\" [ngStyle]=\"segmentStyle()\">\n <div class=\"dd-segment-neo__indicator-shell\">\n <div\n class=\"dd-segment-neo__indicator\"\n [style.transform]=\"'translateX(' + indicatorPosition + 'px)'\"\n [style.width.px]=\"indicatorWidth\"\n >\n <span class=\"dd-segment-neo__indicator-notch\"></span>\n </div>\n </div>\n\n <div class=\"dd-segment-neo__buttons\" #buttonsContainer>\n @for (button of buttons; track button.value; let i = $index) {\n <button\n class=\"dd-segment-neo__button\"\n [class.dd-segment-neo__button--checked]=\"selectedValue === button.value\"\n (click)=\"selectButton(button.value, i)\"\n type=\"button\"\n >\n <span class=\"dd-segment-neo__button-copy\">\n <ng-container *ngTemplateOutlet=\"button.template\" />\n </span>\n </button>\n }\n </div>\n</div>\n", styles: [":host{display:block;width:100%}.dd-segment-neo{--dd-segment-neo-surface: var(--dd-base-0);--dd-segment-neo-panel: var(--dd-base-100);--dd-segment-neo-accent: var(--dd-base-accent-orange);--dd-segment-neo-shadow: var(--dd-base-accent-blue);--dd-segment-neo-text: var(--dd-base-600);--dd-segment-neo-muted: color-mix(in srgb, var(--dd-base-600) 58%, transparent);position:relative;display:block;width:100%;padding:10px;border:4px solid var(--dd-base-600);background:linear-gradient(135deg,color-mix(in srgb,var(--dd-segment-neo-accent) 24%,transparent) 0 12%,transparent 12% 100%),var(--dd-segment-neo-surface);box-shadow:8px 8px 0 var(--dd-segment-neo-shadow);overflow:clip}.dd-segment-neo:before,.dd-segment-neo:after{content:\"\";position:absolute;width:18px;height:18px;background:var(--dd-segment-neo-accent);border:3px solid var(--dd-base-600);z-index:0}.dd-segment-neo:before{top:-7px;right:18px;transform:rotate(10deg)}.dd-segment-neo:after{left:20px;bottom:-9px;transform:rotate(-9deg)}.dd-segment-neo__indicator-shell{position:absolute;inset:10px;z-index:1}.dd-segment-neo__indicator{position:absolute;top:0;bottom:0;left:0;border:3px solid var(--dd-base-600);background:linear-gradient(135deg,color-mix(in srgb,var(--dd-segment-neo-accent) 36%,transparent) 0 18%,transparent 18% 100%),var(--dd-segment-neo-panel);box-shadow:4px 4px 0 var(--dd-base-600);transition:transform .26s cubic-bezier(.22,1,.36,1),width .26s cubic-bezier(.22,1,.36,1)}.dd-segment-neo__indicator-notch{position:absolute;top:-3px;right:14px;width:16px;height:16px;border-left:3px solid var(--dd-base-600);border-bottom:3px solid var(--dd-base-600);background:var(--dd-segment-neo-accent)}.dd-segment-neo__buttons{position:relative;z-index:2;display:flex;width:100%;gap:6px}.dd-segment-neo__button{position:relative;display:flex;flex:1 1 0;align-items:center;justify-content:center;min-height:64px;padding:14px 18px 12px;border:0;background:transparent;color:var(--dd-segment-neo-muted);cursor:pointer;text-align:center;font:inherit;transition:transform .18s ease,color .18s ease;-webkit-tap-highlight-color:transparent}.dd-segment-neo__button:hover{transform:translateY(-1px)}.dd-segment-neo__button:focus-visible{outline:3px solid var(--dd-segment-neo-accent);outline-offset:-3px}.dd-segment-neo__button-copy{position:relative;display:inline-flex;align-items:center;justify-content:center;min-width:0;font-size:.78rem;font-weight:1000;letter-spacing:.14em;line-height:1.1;text-transform:uppercase;text-wrap:balance}.dd-segment-neo__button--checked{color:var(--dd-segment-neo-text)}@media(max-width:640px){.dd-segment-neo{padding:8px;box-shadow:6px 6px 0 var(--dd-segment-neo-shadow)}.dd-segment-neo__indicator-shell{inset:8px}.dd-segment-neo__buttons{gap:2px}.dd-segment-neo__button{min-height:56px;padding-inline:12px}.dd-segment-neo__button-copy{font-size:.72rem;letter-spacing:.11em}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
4208
+ }
4209
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: DuckDevSegmentNeobrutal, decorators: [{
4210
+ type: Component,
4211
+ args: [{ selector: 'duck-dev-segment-neobrutal', imports: [NgTemplateOutlet, NgStyle], template: "<div class=\"dd-segment-neo\" [ngStyle]=\"segmentStyle()\">\n <div class=\"dd-segment-neo__indicator-shell\">\n <div\n class=\"dd-segment-neo__indicator\"\n [style.transform]=\"'translateX(' + indicatorPosition + 'px)'\"\n [style.width.px]=\"indicatorWidth\"\n >\n <span class=\"dd-segment-neo__indicator-notch\"></span>\n </div>\n </div>\n\n <div class=\"dd-segment-neo__buttons\" #buttonsContainer>\n @for (button of buttons; track button.value; let i = $index) {\n <button\n class=\"dd-segment-neo__button\"\n [class.dd-segment-neo__button--checked]=\"selectedValue === button.value\"\n (click)=\"selectButton(button.value, i)\"\n type=\"button\"\n >\n <span class=\"dd-segment-neo__button-copy\">\n <ng-container *ngTemplateOutlet=\"button.template\" />\n </span>\n </button>\n }\n </div>\n</div>\n", styles: [":host{display:block;width:100%}.dd-segment-neo{--dd-segment-neo-surface: var(--dd-base-0);--dd-segment-neo-panel: var(--dd-base-100);--dd-segment-neo-accent: var(--dd-base-accent-orange);--dd-segment-neo-shadow: var(--dd-base-accent-blue);--dd-segment-neo-text: var(--dd-base-600);--dd-segment-neo-muted: color-mix(in srgb, var(--dd-base-600) 58%, transparent);position:relative;display:block;width:100%;padding:10px;border:4px solid var(--dd-base-600);background:linear-gradient(135deg,color-mix(in srgb,var(--dd-segment-neo-accent) 24%,transparent) 0 12%,transparent 12% 100%),var(--dd-segment-neo-surface);box-shadow:8px 8px 0 var(--dd-segment-neo-shadow);overflow:clip}.dd-segment-neo:before,.dd-segment-neo:after{content:\"\";position:absolute;width:18px;height:18px;background:var(--dd-segment-neo-accent);border:3px solid var(--dd-base-600);z-index:0}.dd-segment-neo:before{top:-7px;right:18px;transform:rotate(10deg)}.dd-segment-neo:after{left:20px;bottom:-9px;transform:rotate(-9deg)}.dd-segment-neo__indicator-shell{position:absolute;inset:10px;z-index:1}.dd-segment-neo__indicator{position:absolute;top:0;bottom:0;left:0;border:3px solid var(--dd-base-600);background:linear-gradient(135deg,color-mix(in srgb,var(--dd-segment-neo-accent) 36%,transparent) 0 18%,transparent 18% 100%),var(--dd-segment-neo-panel);box-shadow:4px 4px 0 var(--dd-base-600);transition:transform .26s cubic-bezier(.22,1,.36,1),width .26s cubic-bezier(.22,1,.36,1)}.dd-segment-neo__indicator-notch{position:absolute;top:-3px;right:14px;width:16px;height:16px;border-left:3px solid var(--dd-base-600);border-bottom:3px solid var(--dd-base-600);background:var(--dd-segment-neo-accent)}.dd-segment-neo__buttons{position:relative;z-index:2;display:flex;width:100%;gap:6px}.dd-segment-neo__button{position:relative;display:flex;flex:1 1 0;align-items:center;justify-content:center;min-height:64px;padding:14px 18px 12px;border:0;background:transparent;color:var(--dd-segment-neo-muted);cursor:pointer;text-align:center;font:inherit;transition:transform .18s ease,color .18s ease;-webkit-tap-highlight-color:transparent}.dd-segment-neo__button:hover{transform:translateY(-1px)}.dd-segment-neo__button:focus-visible{outline:3px solid var(--dd-segment-neo-accent);outline-offset:-3px}.dd-segment-neo__button-copy{position:relative;display:inline-flex;align-items:center;justify-content:center;min-width:0;font-size:.78rem;font-weight:1000;letter-spacing:.14em;line-height:1.1;text-transform:uppercase;text-wrap:balance}.dd-segment-neo__button--checked{color:var(--dd-segment-neo-text)}@media(max-width:640px){.dd-segment-neo{padding:8px;box-shadow:6px 6px 0 var(--dd-segment-neo-shadow)}.dd-segment-neo__indicator-shell{inset:8px}.dd-segment-neo__buttons{gap:2px}.dd-segment-neo__button{min-height:56px;padding-inline:12px}.dd-segment-neo__button-copy{font-size:.72rem;letter-spacing:.11em}}\n"] }]
4212
+ }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], ionChange: [{ type: i0.Output, args: ["ionChange"] }], segmentButtons: [{
4213
+ type: ContentChildren,
4214
+ args: [DuckDevSegmentButton]
4215
+ }], buttonsContainer: [{ type: i0.ViewChild, args: ['buttonsContainer', { isSignal: true }] }] } });
4216
+
3762
4217
  class SegmentBlock {
3763
4218
  selected = signal('all', { ...(ngDevMode ? { debugName: "selected" } : {}) });
4219
+ neobrutalSelected = signal('rush', { ...(ngDevMode ? { debugName: "neobrutalSelected" } : {}) });
3764
4220
  lastEvent = signal('', { ...(ngDevMode ? { debugName: "lastEvent" } : {}) });
4221
+ colorViolet = AccentEnumColor.Violet;
4222
+ colorOrange = AccentEnumColor.Orange;
3765
4223
  onIonChange(e) {
3766
4224
  this.lastEvent.set(e.detail.value);
3767
4225
  }
3768
4226
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: SegmentBlock, deps: [], target: i0.ɵɵFactoryTarget.Component });
3769
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.1", type: SegmentBlock, isStandalone: true, selector: "app-segment-block", ngImport: i0, template: "<div class=\"demo-container\">\n <h1>{{ 'segmentDoc.title' | transloco }}</h1>\n\n <dd-card-section>\n <h2>{{ 'segmentDoc.basic.title' | transloco }}</h2>\n <p class=\"description\">{{ 'segmentDoc.basic.description' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'segmentDoc.basic.usage' | transloco }}</h3>\n <pre><code>&lt;dd-segment-classic [value]=\"selected\" (valueChange)=\"onChange($event)\"&gt;\n &lt;dd-segment-button value=\"all\"&gt;All&lt;/dd-segment-button&gt;\n &lt;dd-segment-button value=\"articles\"&gt;Articles&lt;/dd-segment-button&gt;\n &lt;dd-segment-button value=\"videos\"&gt;Videos&lt;/dd-segment-button&gt;\n&lt;/dd-segment-classic&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'segmentDoc.basic.inputs' | transloco }}</h3>\n <ul>\n <li><strong>value</strong> \u2014 {{ 'segmentDoc.inputsDesc.value' | transloco }}</li>\n <li><strong>valueChange</strong> \u2014 {{ 'segmentDoc.inputsDesc.valueChange' | transloco }}</li>\n <li><strong>ionChange</strong> \u2014 {{ 'segmentDoc.inputsDesc.ionChange' | transloco }}</li>\n <li><strong>dd-segment-button[value]</strong> \u2014 {{ 'segmentDoc.inputsDesc.buttonValue' | transloco }}</li>\n <li><strong>dd-segment-button</strong> \u2014 {{ 'segmentDoc.inputsDesc.buttonContent' | transloco }}</li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'segmentDoc.basic.examples' | transloco }}</h3>\n\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'segmentDoc.examples.basic' | transloco }}</p>\n <dd-segment-classic>\n <dd-segment-button value=\"all\">{{ 'segmentDoc.labels.all' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"articles\">{{ 'segmentDoc.labels.articles' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"videos\">{{ 'segmentDoc.labels.videos' | transloco }}</dd-segment-button>\n </dd-segment-classic>\n </div>\n\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'segmentDoc.examples.withBinding' | transloco }}</p>\n <dd-segment-classic [value]=\"selected()\" (valueChange)=\"selected.set($event)\" (ionChange)=\"onIonChange($event)\">\n <dd-segment-button value=\"all\">{{ 'segmentDoc.labels.all' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"articles\">{{ 'segmentDoc.labels.articles' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"videos\">{{ 'segmentDoc.labels.videos' | transloco }}</dd-segment-button>\n </dd-segment-classic>\n <div class=\"state-hint\">\n <span>{{ 'segmentDoc.labels.selected' | transloco }}: </span>\n <b>{{ selected() }}</b>\n <span class=\"divider\">|</span>\n <span>ionChange: <b>{{ lastEvent() }}</b></span>\n </div>\n </div>\n </div>\n\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'segmentDoc.examples.filters' | transloco }}</p>\n <dd-segment-classic [value]=\"'all'\">\n <dd-segment-button value=\"all\">{{ 'segmentDoc.labels.all' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"articles\">{{ 'segmentDoc.labels.articles' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"videos\">{{ 'segmentDoc.labels.videos' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"photos\">{{ 'segmentDoc.labels.photos' | transloco }}</dd-segment-button>\n </dd-segment-classic>\n </div>\n </div>\n </div>\n </dd-card-section>\n</div>\n", styles: [".demo-container{max-width:1200px;margin:0 auto;padding:40px 20px}.demo-container h1{font-size:36px;font-weight:700;color:var(--dd-base-600);margin-bottom:40px;text-align:center;border-bottom:3px solid var(--dd-base-accent-blue);padding-bottom:20px}.demo-container h2{font-size:28px;font-weight:600;color:var(--dd-base-500);margin-bottom:15px;border-left:4px solid var(--dd-base-accent-blue);padding-left:15px}.demo-container .description{font-size:16px;line-height:1.6;color:var(--dd-base-400);margin-bottom:25px;padding:15px;background:var(--dd-base-100);border-radius:8px;border-left:3px solid var(--dd-base-300)}.demo-container h3{font-size:20px;font-weight:600;color:var(--dd-base-500);margin-bottom:15px;margin-top:25px}.demo-container .usage-block{margin-bottom:25px}.demo-container .usage-block pre{background:var(--dd-base-600);color:var(--dd-base-100);padding:20px;border-radius:8px;overflow-x:auto;margin:0}.demo-container .usage-block pre code{font-family:Courier New,Courier,monospace;font-size:14px;line-height:1.5}.demo-container .inputs-block{margin-bottom:25px}.demo-container .inputs-block ul{list-style:none;padding:0;margin:0}.demo-container .inputs-block ul li{padding:12px 15px;margin-bottom:8px;background:var(--dd-base-100);border-radius:6px;border-left:3px solid var(--dd-base-accent-blue);font-size:15px;line-height:1.5;color:var(--dd-base-500)}.demo-container .inputs-block ul li strong{color:var(--dd-base-accent-blue);font-weight:600}.demo-container .examples-block .example-row{display:flex;gap:20px;margin-bottom:20px;flex-wrap:wrap}.demo-container .examples-block .example-row .example-item{flex:1;min-width:280px;padding:20px;background:var(--dd-base-100);border-radius:8px;border:2px solid var(--dd-base-300);display:flex;flex-direction:column;align-items:stretch;gap:15px;transition:all .3s ease}.demo-container .examples-block .example-row .example-item:hover{border-color:var(--dd-base-accent-blue);box-shadow:0 4px 12px var(--dd-base-300)}.demo-container .examples-block .example-row .example-item .example-label{font-size:14px;font-weight:600;color:var(--dd-base-400);margin:0;text-align:left}.demo-container .examples-block .example-row .example-item .state-hint{font-size:14px;color:var(--dd-base-400)}.demo-container .examples-block .example-row .example-item .state-hint .divider{margin:0 8px;color:var(--dd-base-300)}@media(max-width:768px){.demo-container{padding:20px 15px}.demo-container h1{font-size:28px}.demo-container .examples-block .example-row{flex-direction:column}.demo-container .examples-block .example-row .example-item{min-width:100%}}\n"], dependencies: [{ kind: "component", type: DuckDevCardSection, selector: "dd-card-section" }, { kind: "component", type: DuckDevSegmentClassic, selector: "dd-segment-classic", inputs: ["value"], outputs: ["valueChange", "ionChange"] }, { kind: "component", type: DuckDevSegmentButton, selector: "dd-segment-button", inputs: ["value", "contentId"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
4227
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.1", type: SegmentBlock, isStandalone: true, selector: "app-segment-block", ngImport: i0, template: "<div class=\"demo-container\">\n <h1>{{ 'segmentDoc.title' | transloco }}</h1>\n\n <dd-card-section>\n <h2>{{ 'segmentDoc.basic.title' | transloco }}</h2>\n <p class=\"description\">{{ 'segmentDoc.basic.description' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'segmentDoc.basic.usage' | transloco }}</h3>\n <pre><code>&lt;dd-segment-classic [value]=\"selected\" (valueChange)=\"onChange($event)\"&gt;\n &lt;dd-segment-button value=\"all\"&gt;All&lt;/dd-segment-button&gt;\n &lt;dd-segment-button value=\"articles\"&gt;Articles&lt;/dd-segment-button&gt;\n &lt;dd-segment-button value=\"videos\"&gt;Videos&lt;/dd-segment-button&gt;\n&lt;/dd-segment-classic&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'segmentDoc.basic.inputs' | transloco }}</h3>\n <ul>\n <li><strong>value</strong> \u2014 {{ 'segmentDoc.inputsDesc.value' | transloco }}</li>\n <li><strong>valueChange</strong> \u2014 {{ 'segmentDoc.inputsDesc.valueChange' | transloco }}</li>\n <li><strong>ionChange</strong> \u2014 {{ 'segmentDoc.inputsDesc.ionChange' | transloco }}</li>\n <li><strong>color</strong> \u2014 {{ 'segmentDoc.inputsDesc.color' | transloco }}</li>\n <li><strong>dd-segment-button[value]</strong> \u2014 {{ 'segmentDoc.inputsDesc.buttonValue' | transloco }}</li>\n <li><strong>dd-segment-button</strong> \u2014 {{ 'segmentDoc.inputsDesc.buttonContent' | transloco }}</li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'segmentDoc.basic.examples' | transloco }}</h3>\n\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'segmentDoc.examples.basic' | transloco }}</p>\n <dd-segment-classic>\n <dd-segment-button value=\"all\">{{ 'segmentDoc.labels.all' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"articles\">{{ 'segmentDoc.labels.articles' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"videos\">{{ 'segmentDoc.labels.videos' | transloco }}</dd-segment-button>\n </dd-segment-classic>\n </div>\n\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'segmentDoc.examples.withBinding' | transloco }}</p>\n <dd-segment-classic [value]=\"selected()\" (valueChange)=\"selected.set($event)\" (ionChange)=\"onIonChange($event)\">\n <dd-segment-button value=\"all\">{{ 'segmentDoc.labels.all' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"articles\">{{ 'segmentDoc.labels.articles' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"videos\">{{ 'segmentDoc.labels.videos' | transloco }}</dd-segment-button>\n </dd-segment-classic>\n <div class=\"state-hint\">\n <span>{{ 'segmentDoc.labels.selected' | transloco }}: </span>\n <b>{{ selected() }}</b>\n <span class=\"divider\">|</span>\n <span>ionChange: <b>{{ lastEvent() }}</b></span>\n </div>\n </div>\n </div>\n\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'segmentDoc.examples.filters' | transloco }}</p>\n <dd-segment-classic [value]=\"'all'\">\n <dd-segment-button value=\"all\">{{ 'segmentDoc.labels.all' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"articles\">{{ 'segmentDoc.labels.articles' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"videos\">{{ 'segmentDoc.labels.videos' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"photos\">{{ 'segmentDoc.labels.photos' | transloco }}</dd-segment-button>\n </dd-segment-classic>\n </div>\n </div>\n\n <div class=\"example-row\">\n <div class=\"example-item example-item--neobrutal\">\n <p class=\"example-label\">{{ 'segmentDoc.examples.neobrutalViolet' | transloco }}</p>\n <duck-dev-segment-neobrutal\n [value]=\"neobrutalSelected()\"\n [color]=\"colorViolet\"\n (valueChange)=\"neobrutalSelected.set($event)\"\n >\n <dd-segment-button value=\"rush\">{{ 'segmentDoc.labels.rush' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"review\">{{ 'segmentDoc.labels.review' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"drop\">{{ 'segmentDoc.labels.drop' | transloco }}</dd-segment-button>\n </duck-dev-segment-neobrutal>\n <div class=\"state-hint state-hint--neobrutal\">\n <span>{{ 'segmentDoc.labels.selected' | transloco }}: </span>\n <b>{{ neobrutalSelected() }}</b>\n </div>\n </div>\n\n <div class=\"example-item example-item--neobrutal\">\n <p class=\"example-label\">{{ 'segmentDoc.examples.neobrutalOrange' | transloco }}</p>\n <duck-dev-segment-neobrutal [value]=\"'launch'\" [color]=\"colorOrange\">\n <dd-segment-button value=\"draft\">{{ 'segmentDoc.labels.draft' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"launch\">{{ 'segmentDoc.labels.launch' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"archive\">{{ 'segmentDoc.labels.archive' | transloco }}</dd-segment-button>\n </duck-dev-segment-neobrutal>\n </div>\n </div>\n </div>\n </dd-card-section>\n</div>\n", styles: [".demo-container{max-width:1200px;margin:0 auto;padding:40px 20px}.demo-container h1{font-size:36px;font-weight:700;color:var(--dd-base-600);margin-bottom:40px;text-align:center;border-bottom:3px solid var(--dd-base-accent-blue);padding-bottom:20px}.demo-container h2{font-size:28px;font-weight:600;color:var(--dd-base-500);margin-bottom:15px;border-left:4px solid var(--dd-base-accent-blue);padding-left:15px}.demo-container .description{font-size:16px;line-height:1.6;color:var(--dd-base-400);margin-bottom:25px;padding:15px;background:var(--dd-base-100);border-radius:8px;border-left:3px solid var(--dd-base-300)}.demo-container h3{font-size:20px;font-weight:600;color:var(--dd-base-500);margin-bottom:15px;margin-top:25px}.demo-container .usage-block{margin-bottom:25px}.demo-container .usage-block pre{background:var(--dd-base-600);color:var(--dd-base-100);padding:20px;border-radius:8px;overflow-x:auto;margin:0}.demo-container .usage-block pre code{font-family:Courier New,Courier,monospace;font-size:14px;line-height:1.5}.demo-container .inputs-block{margin-bottom:25px}.demo-container .inputs-block ul{list-style:none;padding:0;margin:0}.demo-container .inputs-block ul li{padding:12px 15px;margin-bottom:8px;background:var(--dd-base-100);border-radius:6px;border-left:3px solid var(--dd-base-accent-blue);font-size:15px;line-height:1.5;color:var(--dd-base-500)}.demo-container .inputs-block ul li strong{color:var(--dd-base-accent-blue);font-weight:600}.demo-container .examples-block .example-row{display:flex;gap:20px;margin-bottom:20px;flex-wrap:wrap}.demo-container .examples-block .example-row .example-item{flex:1;min-width:280px;padding:20px;background:var(--dd-base-100);border-radius:8px;border:2px solid var(--dd-base-300);display:flex;flex-direction:column;align-items:stretch;gap:15px;transition:all .3s ease}.demo-container .examples-block .example-row .example-item:hover{border-color:var(--dd-base-accent-blue);box-shadow:0 4px 12px var(--dd-base-300)}.demo-container .examples-block .example-row .example-item .example-label{font-size:14px;font-weight:600;color:var(--dd-base-400);margin:0;text-align:left}.demo-container .examples-block .example-row .example-item .state-hint{font-size:14px;color:var(--dd-base-400)}.demo-container .examples-block .example-row .example-item .state-hint .divider{margin:0 8px;color:var(--dd-base-300)}.demo-container .examples-block .example-row .example-item.example-item--neobrutal{gap:18px;border-radius:0;border-width:3px;border-color:var(--dd-base-600);background:linear-gradient(135deg,color-mix(in srgb,var(--dd-base-accent-yellow) 18%,transparent) 0 14%,transparent 14% 100%),var(--dd-base-0);box-shadow:8px 8px 0 var(--dd-base-accent-blue)}.demo-container .examples-block .example-row .example-item .state-hint--neobrutal{display:inline-flex;width:fit-content;align-items:center;gap:8px;padding:6px 10px;border:2px solid var(--dd-base-600);background:var(--dd-base-accent-yellow);color:var(--dd-base-600);font-size:11px;font-weight:900;letter-spacing:.12em;text-transform:uppercase}@media(max-width:768px){.demo-container{padding:20px 15px}.demo-container h1{font-size:28px}.demo-container .examples-block .example-row{flex-direction:column}.demo-container .examples-block .example-row .example-item{min-width:100%}}\n"], dependencies: [{ kind: "component", type: DuckDevCardSection, selector: "dd-card-section" }, { kind: "component", type: DuckDevSegmentClassic, selector: "dd-segment-classic", inputs: ["value"], outputs: ["valueChange", "ionChange"] }, { kind: "component", type: DuckDevSegmentButton, selector: "dd-segment-button", inputs: ["value", "contentId"] }, { kind: "component", type: DuckDevSegmentNeobrutal, selector: "duck-dev-segment-neobrutal", inputs: ["value", "color"], outputs: ["valueChange", "ionChange"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
3770
4228
  }
3771
4229
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: SegmentBlock, decorators: [{
3772
4230
  type: Component,
3773
- args: [{ selector: 'app-segment-block', imports: [TranslocoPipe, DuckDevCardSection, DuckDevSegmentClassic, DuckDevSegmentButton], template: "<div class=\"demo-container\">\n <h1>{{ 'segmentDoc.title' | transloco }}</h1>\n\n <dd-card-section>\n <h2>{{ 'segmentDoc.basic.title' | transloco }}</h2>\n <p class=\"description\">{{ 'segmentDoc.basic.description' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'segmentDoc.basic.usage' | transloco }}</h3>\n <pre><code>&lt;dd-segment-classic [value]=\"selected\" (valueChange)=\"onChange($event)\"&gt;\n &lt;dd-segment-button value=\"all\"&gt;All&lt;/dd-segment-button&gt;\n &lt;dd-segment-button value=\"articles\"&gt;Articles&lt;/dd-segment-button&gt;\n &lt;dd-segment-button value=\"videos\"&gt;Videos&lt;/dd-segment-button&gt;\n&lt;/dd-segment-classic&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'segmentDoc.basic.inputs' | transloco }}</h3>\n <ul>\n <li><strong>value</strong> \u2014 {{ 'segmentDoc.inputsDesc.value' | transloco }}</li>\n <li><strong>valueChange</strong> \u2014 {{ 'segmentDoc.inputsDesc.valueChange' | transloco }}</li>\n <li><strong>ionChange</strong> \u2014 {{ 'segmentDoc.inputsDesc.ionChange' | transloco }}</li>\n <li><strong>dd-segment-button[value]</strong> \u2014 {{ 'segmentDoc.inputsDesc.buttonValue' | transloco }}</li>\n <li><strong>dd-segment-button</strong> \u2014 {{ 'segmentDoc.inputsDesc.buttonContent' | transloco }}</li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'segmentDoc.basic.examples' | transloco }}</h3>\n\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'segmentDoc.examples.basic' | transloco }}</p>\n <dd-segment-classic>\n <dd-segment-button value=\"all\">{{ 'segmentDoc.labels.all' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"articles\">{{ 'segmentDoc.labels.articles' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"videos\">{{ 'segmentDoc.labels.videos' | transloco }}</dd-segment-button>\n </dd-segment-classic>\n </div>\n\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'segmentDoc.examples.withBinding' | transloco }}</p>\n <dd-segment-classic [value]=\"selected()\" (valueChange)=\"selected.set($event)\" (ionChange)=\"onIonChange($event)\">\n <dd-segment-button value=\"all\">{{ 'segmentDoc.labels.all' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"articles\">{{ 'segmentDoc.labels.articles' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"videos\">{{ 'segmentDoc.labels.videos' | transloco }}</dd-segment-button>\n </dd-segment-classic>\n <div class=\"state-hint\">\n <span>{{ 'segmentDoc.labels.selected' | transloco }}: </span>\n <b>{{ selected() }}</b>\n <span class=\"divider\">|</span>\n <span>ionChange: <b>{{ lastEvent() }}</b></span>\n </div>\n </div>\n </div>\n\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'segmentDoc.examples.filters' | transloco }}</p>\n <dd-segment-classic [value]=\"'all'\">\n <dd-segment-button value=\"all\">{{ 'segmentDoc.labels.all' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"articles\">{{ 'segmentDoc.labels.articles' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"videos\">{{ 'segmentDoc.labels.videos' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"photos\">{{ 'segmentDoc.labels.photos' | transloco }}</dd-segment-button>\n </dd-segment-classic>\n </div>\n </div>\n </div>\n </dd-card-section>\n</div>\n", styles: [".demo-container{max-width:1200px;margin:0 auto;padding:40px 20px}.demo-container h1{font-size:36px;font-weight:700;color:var(--dd-base-600);margin-bottom:40px;text-align:center;border-bottom:3px solid var(--dd-base-accent-blue);padding-bottom:20px}.demo-container h2{font-size:28px;font-weight:600;color:var(--dd-base-500);margin-bottom:15px;border-left:4px solid var(--dd-base-accent-blue);padding-left:15px}.demo-container .description{font-size:16px;line-height:1.6;color:var(--dd-base-400);margin-bottom:25px;padding:15px;background:var(--dd-base-100);border-radius:8px;border-left:3px solid var(--dd-base-300)}.demo-container h3{font-size:20px;font-weight:600;color:var(--dd-base-500);margin-bottom:15px;margin-top:25px}.demo-container .usage-block{margin-bottom:25px}.demo-container .usage-block pre{background:var(--dd-base-600);color:var(--dd-base-100);padding:20px;border-radius:8px;overflow-x:auto;margin:0}.demo-container .usage-block pre code{font-family:Courier New,Courier,monospace;font-size:14px;line-height:1.5}.demo-container .inputs-block{margin-bottom:25px}.demo-container .inputs-block ul{list-style:none;padding:0;margin:0}.demo-container .inputs-block ul li{padding:12px 15px;margin-bottom:8px;background:var(--dd-base-100);border-radius:6px;border-left:3px solid var(--dd-base-accent-blue);font-size:15px;line-height:1.5;color:var(--dd-base-500)}.demo-container .inputs-block ul li strong{color:var(--dd-base-accent-blue);font-weight:600}.demo-container .examples-block .example-row{display:flex;gap:20px;margin-bottom:20px;flex-wrap:wrap}.demo-container .examples-block .example-row .example-item{flex:1;min-width:280px;padding:20px;background:var(--dd-base-100);border-radius:8px;border:2px solid var(--dd-base-300);display:flex;flex-direction:column;align-items:stretch;gap:15px;transition:all .3s ease}.demo-container .examples-block .example-row .example-item:hover{border-color:var(--dd-base-accent-blue);box-shadow:0 4px 12px var(--dd-base-300)}.demo-container .examples-block .example-row .example-item .example-label{font-size:14px;font-weight:600;color:var(--dd-base-400);margin:0;text-align:left}.demo-container .examples-block .example-row .example-item .state-hint{font-size:14px;color:var(--dd-base-400)}.demo-container .examples-block .example-row .example-item .state-hint .divider{margin:0 8px;color:var(--dd-base-300)}@media(max-width:768px){.demo-container{padding:20px 15px}.demo-container h1{font-size:28px}.demo-container .examples-block .example-row{flex-direction:column}.demo-container .examples-block .example-row .example-item{min-width:100%}}\n"] }]
4231
+ args: [{ selector: 'app-segment-block', imports: [TranslocoPipe, DuckDevCardSection, DuckDevSegmentClassic, DuckDevSegmentButton, DuckDevSegmentNeobrutal], template: "<div class=\"demo-container\">\n <h1>{{ 'segmentDoc.title' | transloco }}</h1>\n\n <dd-card-section>\n <h2>{{ 'segmentDoc.basic.title' | transloco }}</h2>\n <p class=\"description\">{{ 'segmentDoc.basic.description' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'segmentDoc.basic.usage' | transloco }}</h3>\n <pre><code>&lt;dd-segment-classic [value]=\"selected\" (valueChange)=\"onChange($event)\"&gt;\n &lt;dd-segment-button value=\"all\"&gt;All&lt;/dd-segment-button&gt;\n &lt;dd-segment-button value=\"articles\"&gt;Articles&lt;/dd-segment-button&gt;\n &lt;dd-segment-button value=\"videos\"&gt;Videos&lt;/dd-segment-button&gt;\n&lt;/dd-segment-classic&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'segmentDoc.basic.inputs' | transloco }}</h3>\n <ul>\n <li><strong>value</strong> \u2014 {{ 'segmentDoc.inputsDesc.value' | transloco }}</li>\n <li><strong>valueChange</strong> \u2014 {{ 'segmentDoc.inputsDesc.valueChange' | transloco }}</li>\n <li><strong>ionChange</strong> \u2014 {{ 'segmentDoc.inputsDesc.ionChange' | transloco }}</li>\n <li><strong>color</strong> \u2014 {{ 'segmentDoc.inputsDesc.color' | transloco }}</li>\n <li><strong>dd-segment-button[value]</strong> \u2014 {{ 'segmentDoc.inputsDesc.buttonValue' | transloco }}</li>\n <li><strong>dd-segment-button</strong> \u2014 {{ 'segmentDoc.inputsDesc.buttonContent' | transloco }}</li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'segmentDoc.basic.examples' | transloco }}</h3>\n\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'segmentDoc.examples.basic' | transloco }}</p>\n <dd-segment-classic>\n <dd-segment-button value=\"all\">{{ 'segmentDoc.labels.all' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"articles\">{{ 'segmentDoc.labels.articles' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"videos\">{{ 'segmentDoc.labels.videos' | transloco }}</dd-segment-button>\n </dd-segment-classic>\n </div>\n\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'segmentDoc.examples.withBinding' | transloco }}</p>\n <dd-segment-classic [value]=\"selected()\" (valueChange)=\"selected.set($event)\" (ionChange)=\"onIonChange($event)\">\n <dd-segment-button value=\"all\">{{ 'segmentDoc.labels.all' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"articles\">{{ 'segmentDoc.labels.articles' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"videos\">{{ 'segmentDoc.labels.videos' | transloco }}</dd-segment-button>\n </dd-segment-classic>\n <div class=\"state-hint\">\n <span>{{ 'segmentDoc.labels.selected' | transloco }}: </span>\n <b>{{ selected() }}</b>\n <span class=\"divider\">|</span>\n <span>ionChange: <b>{{ lastEvent() }}</b></span>\n </div>\n </div>\n </div>\n\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'segmentDoc.examples.filters' | transloco }}</p>\n <dd-segment-classic [value]=\"'all'\">\n <dd-segment-button value=\"all\">{{ 'segmentDoc.labels.all' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"articles\">{{ 'segmentDoc.labels.articles' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"videos\">{{ 'segmentDoc.labels.videos' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"photos\">{{ 'segmentDoc.labels.photos' | transloco }}</dd-segment-button>\n </dd-segment-classic>\n </div>\n </div>\n\n <div class=\"example-row\">\n <div class=\"example-item example-item--neobrutal\">\n <p class=\"example-label\">{{ 'segmentDoc.examples.neobrutalViolet' | transloco }}</p>\n <duck-dev-segment-neobrutal\n [value]=\"neobrutalSelected()\"\n [color]=\"colorViolet\"\n (valueChange)=\"neobrutalSelected.set($event)\"\n >\n <dd-segment-button value=\"rush\">{{ 'segmentDoc.labels.rush' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"review\">{{ 'segmentDoc.labels.review' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"drop\">{{ 'segmentDoc.labels.drop' | transloco }}</dd-segment-button>\n </duck-dev-segment-neobrutal>\n <div class=\"state-hint state-hint--neobrutal\">\n <span>{{ 'segmentDoc.labels.selected' | transloco }}: </span>\n <b>{{ neobrutalSelected() }}</b>\n </div>\n </div>\n\n <div class=\"example-item example-item--neobrutal\">\n <p class=\"example-label\">{{ 'segmentDoc.examples.neobrutalOrange' | transloco }}</p>\n <duck-dev-segment-neobrutal [value]=\"'launch'\" [color]=\"colorOrange\">\n <dd-segment-button value=\"draft\">{{ 'segmentDoc.labels.draft' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"launch\">{{ 'segmentDoc.labels.launch' | transloco }}</dd-segment-button>\n <dd-segment-button value=\"archive\">{{ 'segmentDoc.labels.archive' | transloco }}</dd-segment-button>\n </duck-dev-segment-neobrutal>\n </div>\n </div>\n </div>\n </dd-card-section>\n</div>\n", styles: [".demo-container{max-width:1200px;margin:0 auto;padding:40px 20px}.demo-container h1{font-size:36px;font-weight:700;color:var(--dd-base-600);margin-bottom:40px;text-align:center;border-bottom:3px solid var(--dd-base-accent-blue);padding-bottom:20px}.demo-container h2{font-size:28px;font-weight:600;color:var(--dd-base-500);margin-bottom:15px;border-left:4px solid var(--dd-base-accent-blue);padding-left:15px}.demo-container .description{font-size:16px;line-height:1.6;color:var(--dd-base-400);margin-bottom:25px;padding:15px;background:var(--dd-base-100);border-radius:8px;border-left:3px solid var(--dd-base-300)}.demo-container h3{font-size:20px;font-weight:600;color:var(--dd-base-500);margin-bottom:15px;margin-top:25px}.demo-container .usage-block{margin-bottom:25px}.demo-container .usage-block pre{background:var(--dd-base-600);color:var(--dd-base-100);padding:20px;border-radius:8px;overflow-x:auto;margin:0}.demo-container .usage-block pre code{font-family:Courier New,Courier,monospace;font-size:14px;line-height:1.5}.demo-container .inputs-block{margin-bottom:25px}.demo-container .inputs-block ul{list-style:none;padding:0;margin:0}.demo-container .inputs-block ul li{padding:12px 15px;margin-bottom:8px;background:var(--dd-base-100);border-radius:6px;border-left:3px solid var(--dd-base-accent-blue);font-size:15px;line-height:1.5;color:var(--dd-base-500)}.demo-container .inputs-block ul li strong{color:var(--dd-base-accent-blue);font-weight:600}.demo-container .examples-block .example-row{display:flex;gap:20px;margin-bottom:20px;flex-wrap:wrap}.demo-container .examples-block .example-row .example-item{flex:1;min-width:280px;padding:20px;background:var(--dd-base-100);border-radius:8px;border:2px solid var(--dd-base-300);display:flex;flex-direction:column;align-items:stretch;gap:15px;transition:all .3s ease}.demo-container .examples-block .example-row .example-item:hover{border-color:var(--dd-base-accent-blue);box-shadow:0 4px 12px var(--dd-base-300)}.demo-container .examples-block .example-row .example-item .example-label{font-size:14px;font-weight:600;color:var(--dd-base-400);margin:0;text-align:left}.demo-container .examples-block .example-row .example-item .state-hint{font-size:14px;color:var(--dd-base-400)}.demo-container .examples-block .example-row .example-item .state-hint .divider{margin:0 8px;color:var(--dd-base-300)}.demo-container .examples-block .example-row .example-item.example-item--neobrutal{gap:18px;border-radius:0;border-width:3px;border-color:var(--dd-base-600);background:linear-gradient(135deg,color-mix(in srgb,var(--dd-base-accent-yellow) 18%,transparent) 0 14%,transparent 14% 100%),var(--dd-base-0);box-shadow:8px 8px 0 var(--dd-base-accent-blue)}.demo-container .examples-block .example-row .example-item .state-hint--neobrutal{display:inline-flex;width:fit-content;align-items:center;gap:8px;padding:6px 10px;border:2px solid var(--dd-base-600);background:var(--dd-base-accent-yellow);color:var(--dd-base-600);font-size:11px;font-weight:900;letter-spacing:.12em;text-transform:uppercase}@media(max-width:768px){.demo-container{padding:20px 15px}.demo-container h1{font-size:28px}.demo-container .examples-block .example-row{flex-direction:column}.demo-container .examples-block .example-row .example-item{min-width:100%}}\n"] }]
3774
4232
  }] });
3775
4233
 
3776
4234
  function clampProgress(value) {
@@ -3910,6 +4368,1310 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImpor
3910
4368
  ], template: "<div class=\"demo-container\">\n <h1>{{ 'progressDoc.title' | transloco }}</h1>\n\n <duck-dev-tab [tabs]=\"styleTabs\" (tabChange)=\"onStyleTabChange($event)\">\n @if (activeStyleTab().id === 'classic') {\n <section class=\"component-section\">\n <h2>{{ 'progressDoc.classic.line.title' | transloco }}</h2>\n <p class=\"description\">{{ 'progressDoc.classic.line.description' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'progressDoc.usage' | transloco }}</h3>\n <pre><code>&lt;duck-dev-progress-line\n label=\"Release sync\"\n [value]=\"72\"\n subtext=\"API schema is aligned\"\n [color]=\"colorViolet\"\n/&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'progressDoc.inputs' | transloco }}</h3>\n <ul>\n <li [innerHTML]=\"'progressDoc.inputsDesc.label' | transloco\"></li>\n <li [innerHTML]=\"'progressDoc.inputsDesc.value' | transloco\"></li>\n <li [innerHTML]=\"'progressDoc.inputsDesc.subtext' | transloco\"></li>\n <li [innerHTML]=\"'progressDoc.inputsDesc.color' | transloco\"></li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'progressDoc.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'progressDoc.classic.line.example' | transloco }}</p>\n <duck-dev-progress-line\n label=\"Release sync\"\n [value]=\"lineProgress\"\n subtext=\"API schema is aligned\"\n [color]=\"colorViolet\"\n />\n </div>\n </div>\n </div>\n </section>\n\n <section class=\"component-section\">\n <h2>{{ 'progressDoc.classic.stack.title' | transloco }}</h2>\n <p class=\"description\">{{ 'progressDoc.classic.stack.description' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'progressDoc.usage' | transloco }}</h3>\n <pre><code>&lt;duck-dev-progress-stack\n label=\"Content migration\"\n [value]=\"56\"\n subtext=\"6 of 10 blocks shipped\"\n [segmentCount]=\"10\"\n [color]=\"colorOrange\"\n/&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'progressDoc.inputs' | transloco }}</h3>\n <ul>\n <li [innerHTML]=\"'progressDoc.inputsDesc.label' | transloco\"></li>\n <li [innerHTML]=\"'progressDoc.inputsDesc.value' | transloco\"></li>\n <li [innerHTML]=\"'progressDoc.inputsDesc.subtext' | transloco\"></li>\n <li [innerHTML]=\"'progressDoc.inputsDesc.segmentCount' | transloco\"></li>\n <li [innerHTML]=\"'progressDoc.inputsDesc.color' | transloco\"></li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'progressDoc.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'progressDoc.classic.stack.example' | transloco }}</p>\n <duck-dev-progress-stack\n label=\"Content migration\"\n [value]=\"stackProgress\"\n subtext=\"6 of 10 blocks shipped\"\n [segmentCount]=\"10\"\n [color]=\"colorOrange\"\n />\n </div>\n </div>\n </div>\n </section>\n\n <section class=\"component-section\">\n <h2>{{ 'progressDoc.classic.meter.title' | transloco }}</h2>\n <p class=\"description\">{{ 'progressDoc.classic.meter.description' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'progressDoc.usage' | transloco }}</h3>\n <pre><code>&lt;duck-dev-progress-meter\n label=\"Regression sweep\"\n [value]=\"84\"\n subtext=\"Visual QA is nearly done\"\n [color]=\"colorGray\"\n/&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'progressDoc.inputs' | transloco }}</h3>\n <ul>\n <li [innerHTML]=\"'progressDoc.inputsDesc.label' | transloco\"></li>\n <li [innerHTML]=\"'progressDoc.inputsDesc.value' | transloco\"></li>\n <li [innerHTML]=\"'progressDoc.inputsDesc.subtext' | transloco\"></li>\n <li [innerHTML]=\"'progressDoc.inputsDesc.color' | transloco\"></li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'progressDoc.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'progressDoc.classic.meter.example' | transloco }}</p>\n <duck-dev-progress-meter\n label=\"Regression sweep\"\n [value]=\"meterProgress\"\n subtext=\"Visual QA is nearly done\"\n [color]=\"colorGray\"\n />\n </div>\n </div>\n </div>\n </section>\n } @else {\n <section class=\"component-section component-section--neobrutal\">\n <h2>{{ 'progressDoc.neobrutal.slab.title' | transloco }}</h2>\n <p class=\"description\">{{ 'progressDoc.neobrutal.slab.description' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'progressDoc.usage' | transloco }}</h3>\n <pre><code>&lt;duck-dev-progress-neobrutal-slab\n label=\"Build queue\"\n [value]=\"68\"\n subtext=\"Artifact pack is cooking\"\n [color]=\"colorOrange\"\n/&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'progressDoc.inputs' | transloco }}</h3>\n <ul>\n <li [innerHTML]=\"'progressDoc.inputsDesc.label' | transloco\"></li>\n <li [innerHTML]=\"'progressDoc.inputsDesc.value' | transloco\"></li>\n <li [innerHTML]=\"'progressDoc.inputsDesc.subtext' | transloco\"></li>\n <li [innerHTML]=\"'progressDoc.inputsDesc.color' | transloco\"></li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'progressDoc.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item example-item--neobrutal\">\n <p class=\"example-label\">{{ 'progressDoc.neobrutal.slab.example' | transloco }}</p>\n <duck-dev-progress-neobrutal-slab\n label=\"Build queue\"\n [value]=\"slabProgress\"\n subtext=\"Artifact pack is cooking\"\n [color]=\"colorOrange\"\n />\n </div>\n </div>\n </div>\n </section>\n\n <section class=\"component-section component-section--neobrutal\">\n <h2>{{ 'progressDoc.neobrutal.stamp.title' | transloco }}</h2>\n <p class=\"description\">{{ 'progressDoc.neobrutal.stamp.description' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'progressDoc.usage' | transloco }}</h3>\n <pre><code>&lt;duck-dev-progress-neobrutal-stamp\n kicker=\"Duck Dev\"\n label=\"Verification pass\"\n [value]=\"91\"\n [color]=\"colorViolet\"\n/&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'progressDoc.inputs' | transloco }}</h3>\n <ul>\n <li [innerHTML]=\"'progressDoc.inputsDesc.kicker' | transloco\"></li>\n <li [innerHTML]=\"'progressDoc.inputsDesc.label' | transloco\"></li>\n <li [innerHTML]=\"'progressDoc.inputsDesc.value' | transloco\"></li>\n <li [innerHTML]=\"'progressDoc.inputsDesc.color' | transloco\"></li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'progressDoc.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item example-item--neobrutal\">\n <p class=\"example-label\">{{ 'progressDoc.neobrutal.stamp.example' | transloco }}</p>\n <duck-dev-progress-neobrutal-stamp\n kicker=\"Duck Dev\"\n label=\"Verification pass\"\n [value]=\"stampProgress\"\n [color]=\"colorViolet\"\n />\n </div>\n </div>\n </div>\n </section>\n\n <section class=\"component-section component-section--neobrutal\">\n <h2>{{ 'progressDoc.neobrutal.ticket.title' | transloco }}</h2>\n <p class=\"description\">{{ 'progressDoc.neobrutal.ticket.description' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'progressDoc.usage' | transloco }}</h3>\n <pre><code>&lt;duck-dev-progress-neobrutal-ticket\n leftTag=\"phase 02\"\n rightTag=\"ui sync\"\n label=\"Neobrutal rollout\"\n [value]=\"47\"\n [color]=\"colorDark\"\n/&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'progressDoc.inputs' | transloco }}</h3>\n <ul>\n <li [innerHTML]=\"'progressDoc.inputsDesc.leftTag' | transloco\"></li>\n <li [innerHTML]=\"'progressDoc.inputsDesc.rightTag' | transloco\"></li>\n <li [innerHTML]=\"'progressDoc.inputsDesc.label' | transloco\"></li>\n <li [innerHTML]=\"'progressDoc.inputsDesc.value' | transloco\"></li>\n <li [innerHTML]=\"'progressDoc.inputsDesc.color' | transloco\"></li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'progressDoc.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item example-item--neobrutal\">\n <p class=\"example-label\">{{ 'progressDoc.neobrutal.ticket.example' | transloco }}</p>\n <duck-dev-progress-neobrutal-ticket\n leftTag=\"phase 02\"\n rightTag=\"ui sync\"\n label=\"Neobrutal rollout\"\n [value]=\"ticketProgress\"\n [color]=\"colorDark\"\n />\n </div>\n </div>\n </div>\n </section>\n }\n </duck-dev-tab>\n</div>\n", styles: [":root{--dd-appear-time: .5s;--dd-gray-0: #ffffff;--dd-gray-100: #f8f5f6;--dd-gray-200: #f2f4f5;--dd-gray-300: #eaeaea;--dd-gray-400: #999999;--dd-gray-500: #252525;--dd-gray-600: #121312;--dd-success: #a7ffb5ba;--dd-secondary: #6829ff;--dd-accent-orange: #fe7b20;--dd-orange-active: #e5350f;--dd-accent-pink: #fd6ca9;--dd-accent-yellow: #ffd027;--dd-accent-blue: #3254f3;--dd-base-0: var(--dd-gray-0);--dd-base-100: var(--dd-gray-100);--dd-base-200: var(--dd-gray-200);--dd-base-300: var(--dd-gray-300);--dd-base-400: var(--dd-gray-400);--dd-base-500: var(--dd-gray-500);--dd-base-600: var(--dd-gray-600);--dd-background: var(--dd-gray-200);--dd-base-success: var(--dd-success);--dd-base-secondary: var(--dd-secondary);--dd-base-accent-orange: var(--dd-accent-orange);--dd-base-active-orange: var(--dd-orange-active);--dd-base-accent-pink: var(--dd-accent-pink);--dd-base-accent-yellow: var(--dd-accent-yellow);--dd-base-accent-blue: var(--dd-accent-blue)}[ddTheme=dark]{--dd-base-0: var(--dd-gray-600);--dd-base-100: var(--dd-gray-500);--dd-base-200: var(--dd-gray-400);--dd-base-300: var(--dd-gray-300);--dd-base-400: var(--dd-gray-200);--dd-base-500: var(--dd-gray-100);--dd-base-600: var(--dd-gray-0);--dd-background: var(--dd-gray-500)}[ddTheme=violet]{--dd-base-50: var(--dd-magenta-500)}.demo-container{max-width:1200px;margin:0 auto;padding:40px 20px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif}.demo-container h1{font-size:36px;font-weight:700;color:var(--dd-base-600);margin-bottom:40px;text-align:center;border-bottom:3px solid var(--dd-base-accent-blue);padding-bottom:20px}.demo-container h2{font-size:28px;font-weight:600;color:var(--dd-base-500);margin-bottom:15px;border-left:4px solid var(--dd-base-accent-blue);padding-left:15px}.demo-container .component-section{margin-bottom:40px}.demo-container .description{font-size:16px;line-height:1.6;color:var(--dd-base-400);margin-bottom:25px;padding:15px;background:var(--dd-base-100);border-radius:8px;border-left:3px solid var(--dd-base-300)}.demo-container h3{font-size:20px;font-weight:600;color:var(--dd-base-500);margin-bottom:15px;margin-top:25px}.demo-container .usage-block{margin-bottom:25px}.demo-container .usage-block pre{background:var(--dd-base-600);color:var(--dd-base-100);padding:20px;border-radius:8px;overflow-x:auto;margin:0}.demo-container .usage-block pre code{font-family:Courier New,Courier,monospace;font-size:14px;line-height:1.5}.demo-container .inputs-block{margin-bottom:25px}.demo-container .inputs-block ul{list-style:none;padding:0;margin:0}.demo-container .inputs-block ul li{margin-bottom:8px}.demo-container .examples-block .example-row{display:flex;gap:20px;margin-bottom:20px;flex-wrap:wrap}.demo-container .examples-block .example-item{flex:1;min-width:280px;padding:20px;background:var(--dd-base-100);border-radius:8px;border:2px solid var(--dd-base-300);display:flex;flex-direction:column;gap:16px;transition:all .3s ease}.demo-container .examples-block .example-item:hover{border-color:var(--dd-base-accent-blue);box-shadow:0 4px 12px var(--dd-base-300)}.demo-container .examples-block .example-item--neobrutal{background:linear-gradient(135deg,color-mix(in srgb,var(--dd-base-accent-yellow) 24%,transparent) 0 15%,transparent 15% 100%),var(--dd-base-0);border:4px solid var(--dd-base-600);border-radius:0;box-shadow:8px 8px 0 var(--dd-base-accent-blue)}.demo-container .examples-block .example-item--neobrutal:hover{border-color:var(--dd-base-600);box-shadow:10px 10px 0 var(--dd-base-accent-orange)}.demo-container .examples-block .example-label{font-size:14px;font-weight:600;color:var(--dd-base-400);margin:0}@media(max-width:768px){.demo-container{padding:20px 15px}.demo-container h1{font-size:28px}.demo-container h2{font-size:24px}.demo-container .examples-block .example-row{flex-direction:column}.demo-container .examples-block .example-item{min-width:100%}}\n"] }]
3911
4369
  }] });
3912
4370
 
4371
+ function getClassicSpeakerBubbleStyle(color) {
4372
+ switch (color) {
4373
+ case AccentEnumColor.Violet:
4374
+ return {
4375
+ '--dd-speaker-surface': 'color-mix(in srgb, var(--dd-base-secondary) 12%, var(--dd-base-0))',
4376
+ '--dd-speaker-surface-muted': 'color-mix(in srgb, var(--dd-base-secondary) 18%, var(--dd-base-0))',
4377
+ '--dd-speaker-text': 'var(--dd-base-600)',
4378
+ '--dd-speaker-border': 'color-mix(in srgb, var(--dd-base-secondary) 42%, var(--dd-base-300))',
4379
+ '--dd-speaker-accent': 'var(--dd-base-secondary)',
4380
+ '--dd-speaker-shadow': 'color-mix(in srgb, var(--dd-base-secondary) 32%, var(--dd-base-accent-blue))',
4381
+ };
4382
+ case AccentEnumColor.Orange:
4383
+ return {
4384
+ '--dd-speaker-surface': 'color-mix(in srgb, var(--dd-base-accent-orange) 14%, var(--dd-base-0))',
4385
+ '--dd-speaker-surface-muted': 'color-mix(in srgb, var(--dd-base-accent-yellow) 24%, var(--dd-base-0))',
4386
+ '--dd-speaker-text': 'var(--dd-base-600)',
4387
+ '--dd-speaker-border': 'color-mix(in srgb, var(--dd-base-accent-orange) 45%, var(--dd-base-300))',
4388
+ '--dd-speaker-accent': 'var(--dd-base-accent-orange)',
4389
+ '--dd-speaker-shadow': 'color-mix(in srgb, var(--dd-base-accent-orange) 42%, var(--dd-base-accent-yellow))',
4390
+ };
4391
+ case AccentEnumColor.Gray:
4392
+ return {
4393
+ '--dd-speaker-surface': 'var(--dd-base-0)',
4394
+ '--dd-speaker-surface-muted': 'var(--dd-base-100)',
4395
+ '--dd-speaker-text': 'var(--dd-base-500)',
4396
+ '--dd-speaker-border': 'var(--dd-base-300)',
4397
+ '--dd-speaker-accent': 'var(--dd-base-400)',
4398
+ '--dd-speaker-shadow': 'var(--dd-base-300)',
4399
+ };
4400
+ case AccentEnumColor.Dark:
4401
+ return {
4402
+ '--dd-speaker-surface': 'color-mix(in srgb, var(--dd-base-600) 94%, var(--dd-base-500))',
4403
+ '--dd-speaker-surface-muted': 'color-mix(in srgb, var(--dd-base-600) 88%, var(--dd-base-500))',
4404
+ '--dd-speaker-text': 'var(--dd-base-0)',
4405
+ '--dd-speaker-border': 'var(--dd-base-400)',
4406
+ '--dd-speaker-accent': 'var(--dd-base-accent-yellow)',
4407
+ '--dd-speaker-shadow': 'color-mix(in srgb, var(--dd-base-accent-orange) 44%, var(--dd-base-600))',
4408
+ };
4409
+ case AccentEnumColor.White:
4410
+ default:
4411
+ return {
4412
+ '--dd-speaker-surface': 'var(--dd-base-0)',
4413
+ '--dd-speaker-surface-muted': 'var(--dd-base-100)',
4414
+ '--dd-speaker-text': 'var(--dd-base-600)',
4415
+ '--dd-speaker-border': 'var(--dd-base-300)',
4416
+ '--dd-speaker-accent': 'var(--dd-base-accent-blue)',
4417
+ '--dd-speaker-shadow': 'color-mix(in srgb, var(--dd-base-accent-blue) 26%, var(--dd-base-300))',
4418
+ };
4419
+ }
4420
+ }
4421
+ function getNeobrutalSpeakerBubbleStyle(color) {
4422
+ switch (color) {
4423
+ case AccentEnumColor.Violet:
4424
+ return {
4425
+ '--dd-speaker-surface': 'color-mix(in srgb, var(--dd-base-accent-blue) 16%, var(--dd-base-0))',
4426
+ '--dd-speaker-surface-muted': 'color-mix(in srgb, var(--dd-base-accent-yellow) 20%, var(--dd-base-0))',
4427
+ '--dd-speaker-text': 'var(--dd-base-600)',
4428
+ '--dd-speaker-border': 'var(--dd-base-600)',
4429
+ '--dd-speaker-accent': 'var(--dd-base-accent-yellow)',
4430
+ '--dd-speaker-shadow': 'var(--dd-base-accent-blue)',
4431
+ };
4432
+ case AccentEnumColor.Orange:
4433
+ return {
4434
+ '--dd-speaker-surface': 'color-mix(in srgb, var(--dd-base-accent-orange) 20%, var(--dd-base-0))',
4435
+ '--dd-speaker-surface-muted': 'color-mix(in srgb, var(--dd-base-accent-pink) 18%, var(--dd-base-0))',
4436
+ '--dd-speaker-text': 'var(--dd-base-600)',
4437
+ '--dd-speaker-border': 'var(--dd-base-600)',
4438
+ '--dd-speaker-accent': 'var(--dd-base-accent-pink)',
4439
+ '--dd-speaker-shadow': 'var(--dd-base-accent-orange)',
4440
+ };
4441
+ case AccentEnumColor.Gray:
4442
+ return {
4443
+ '--dd-speaker-surface': 'var(--dd-base-100)',
4444
+ '--dd-speaker-surface-muted': 'var(--dd-base-0)',
4445
+ '--dd-speaker-text': 'var(--dd-base-600)',
4446
+ '--dd-speaker-border': 'var(--dd-base-600)',
4447
+ '--dd-speaker-accent': 'var(--dd-base-accent-blue)',
4448
+ '--dd-speaker-shadow': 'var(--dd-base-400)',
4449
+ };
4450
+ case AccentEnumColor.Dark:
4451
+ return {
4452
+ '--dd-speaker-surface': 'var(--dd-base-600)',
4453
+ '--dd-speaker-surface-muted': 'color-mix(in srgb, var(--dd-base-600) 90%, var(--dd-base-500))',
4454
+ '--dd-speaker-text': 'var(--dd-base-0)',
4455
+ '--dd-speaker-border': 'var(--dd-base-0)',
4456
+ '--dd-speaker-accent': 'var(--dd-base-accent-yellow)',
4457
+ '--dd-speaker-shadow': 'var(--dd-base-accent-orange)',
4458
+ };
4459
+ case AccentEnumColor.White:
4460
+ default:
4461
+ return {
4462
+ '--dd-speaker-surface': 'var(--dd-base-0)',
4463
+ '--dd-speaker-surface-muted': 'color-mix(in srgb, var(--dd-base-accent-yellow) 14%, var(--dd-base-0))',
4464
+ '--dd-speaker-text': 'var(--dd-base-600)',
4465
+ '--dd-speaker-border': 'var(--dd-base-600)',
4466
+ '--dd-speaker-accent': 'var(--dd-base-accent-orange)',
4467
+ '--dd-speaker-shadow': 'var(--dd-base-accent-blue)',
4468
+ };
4469
+ }
4470
+ }
4471
+
4472
+ const DEFAULT_BUBBLE_GEOMETRY$2 = {
4473
+ side: 'left',
4474
+ style: {
4475
+ left: '0px',
4476
+ top: '0px',
4477
+ width: '1px',
4478
+ height: '1px',
4479
+ },
4480
+ viewBox: '0 0 1 1',
4481
+ path: '',
4482
+ };
4483
+ function clamp$3(value, min, max) {
4484
+ return Math.min(Math.max(value, min), max);
4485
+ }
4486
+ function serializePoint$3(point) {
4487
+ return `${point.x.toFixed(2)} ${point.y.toFixed(2)}`;
4488
+ }
4489
+ function closestPointOnRect$3(rect, point) {
4490
+ return {
4491
+ x: clamp$3(point.x, rect.left, rect.right),
4492
+ y: clamp$3(point.y, rect.top, rect.bottom),
4493
+ };
4494
+ }
4495
+ function resolveTargetElement$3(source, hostElement, documentRef) {
4496
+ if (!source) {
4497
+ return null;
4498
+ }
4499
+ if (source instanceof Element) {
4500
+ return source;
4501
+ }
4502
+ try {
4503
+ const localMatch = hostElement.parentElement?.querySelector(source);
4504
+ if (localMatch) {
4505
+ return localMatch;
4506
+ }
4507
+ return documentRef.querySelector(source);
4508
+ }
4509
+ catch {
4510
+ return null;
4511
+ }
4512
+ }
4513
+ function getBubbleElement$3(hostElement) {
4514
+ return hostElement.firstElementChild instanceof HTMLElement ? hostElement.firstElementChild : null;
4515
+ }
4516
+ function createUnifiedBubblePath$2(width, height, radius, baseStartX, baseEndX, tipX, tipY, offsetX, offsetY) {
4517
+ const left = offsetX;
4518
+ const top = offsetY;
4519
+ const right = offsetX + width;
4520
+ const bottom = offsetY + height;
4521
+ const start = { x: left + radius, y: top };
4522
+ const bottomRight = { x: right, y: bottom - radius };
4523
+ const bottomRightArcEnd = { x: right - radius, y: bottom };
4524
+ const baseStart = { x: offsetX + baseStartX, y: bottom };
4525
+ const baseEnd = { x: offsetX + baseEndX, y: bottom };
4526
+ const tip = { x: offsetX + tipX, y: offsetY + tipY };
4527
+ const bottomLeftArcStart = { x: left + radius, y: bottom };
4528
+ const leftBottom = { x: left, y: bottom - radius };
4529
+ const leftTop = { x: left, y: top + radius };
4530
+ return [
4531
+ `M ${serializePoint$3(start)}`,
4532
+ `H ${(right - radius).toFixed(2)}`,
4533
+ `A ${radius} ${radius} 0 0 1 ${right.toFixed(2)} ${(top + radius).toFixed(2)}`,
4534
+ `V ${bottomRight.y.toFixed(2)}`,
4535
+ `A ${radius} ${radius} 0 0 1 ${serializePoint$3(bottomRightArcEnd)}`,
4536
+ `H ${baseEnd.x.toFixed(2)}`,
4537
+ `L ${serializePoint$3(tip)}`,
4538
+ `L ${serializePoint$3(baseStart)}`,
4539
+ `H ${bottomLeftArcStart.x.toFixed(2)}`,
4540
+ `A ${radius} ${radius} 0 0 1 ${serializePoint$3(leftBottom)}`,
4541
+ `V ${leftTop.y.toFixed(2)}`,
4542
+ `A ${radius} ${radius} 0 0 1 ${serializePoint$3(start)}`,
4543
+ 'Z',
4544
+ ].join(' ');
4545
+ }
4546
+ class DuckDevSpeakerBubbleClassic {
4547
+ color = input(AccentEnumColor.White, { ...(ngDevMode ? { debugName: "color" } : {}) });
4548
+ tail = input('left', { ...(ngDevMode ? { debugName: "tail" } : {}) });
4549
+ target = input(null, { ...(ngDevMode ? { debugName: "target" } : {}) });
4550
+ hostRef = inject((ElementRef));
4551
+ documentRef = inject(DOCUMENT);
4552
+ destroyRef = inject(DestroyRef);
4553
+ platformId = inject(PLATFORM_ID);
4554
+ isBrowser = isPlatformBrowser(this.platformId);
4555
+ bubbleGeometry = signal(DEFAULT_BUBBLE_GEOMETRY$2, { ...(ngDevMode ? { debugName: "bubbleGeometry" } : {}) });
4556
+ animationFrameId = -1;
4557
+ resizeObserver = null;
4558
+ observedTarget = null;
4559
+ observersInitialized = false;
4560
+ bubbleStyle = computed(() => getClassicSpeakerBubbleStyle(this.color()), { ...(ngDevMode ? { debugName: "bubbleStyle" } : {}) });
4561
+ resolvedTail = computed(() => this.bubbleGeometry().side, { ...(ngDevMode ? { debugName: "resolvedTail" } : {}) });
4562
+ shapeStyle = computed(() => this.bubbleGeometry().style, { ...(ngDevMode ? { debugName: "shapeStyle" } : {}) });
4563
+ shapeViewBox = computed(() => this.bubbleGeometry().viewBox, { ...(ngDevMode ? { debugName: "shapeViewBox" } : {}) });
4564
+ shapePath = computed(() => this.bubbleGeometry().path, { ...(ngDevMode ? { debugName: "shapePath" } : {}) });
4565
+ constructor() {
4566
+ afterNextRender(() => {
4567
+ this.setupObservers();
4568
+ this.scheduleRefresh();
4569
+ });
4570
+ afterRenderEffect(() => {
4571
+ this.tail();
4572
+ this.target();
4573
+ this.setupObservers();
4574
+ this.scheduleRefresh();
4575
+ });
4576
+ this.destroyRef.onDestroy(() => {
4577
+ this.documentRef.defaultView?.removeEventListener('resize', this.scheduleRefresh);
4578
+ this.documentRef.removeEventListener('scroll', this.scheduleRefresh, true);
4579
+ if (this.animationFrameId !== -1) {
4580
+ cancelAnimationFrame(this.animationFrameId);
4581
+ }
4582
+ this.resizeObserver?.disconnect();
4583
+ this.resizeObserver = null;
4584
+ this.observedTarget = null;
4585
+ });
4586
+ }
4587
+ scheduleRefresh = () => {
4588
+ if (!this.isBrowser || this.animationFrameId !== -1) {
4589
+ return;
4590
+ }
4591
+ this.animationFrameId = requestAnimationFrame(() => {
4592
+ this.animationFrameId = -1;
4593
+ this.refreshShape();
4594
+ });
4595
+ };
4596
+ setupObservers() {
4597
+ if (!this.isBrowser || this.observersInitialized) {
4598
+ return;
4599
+ }
4600
+ const bubbleElement = getBubbleElement$3(this.hostRef.nativeElement);
4601
+ if (!bubbleElement) {
4602
+ return;
4603
+ }
4604
+ if (typeof ResizeObserver !== 'undefined') {
4605
+ this.resizeObserver = new ResizeObserver(() => this.scheduleRefresh());
4606
+ this.resizeObserver.observe(bubbleElement);
4607
+ }
4608
+ const targetElement = resolveTargetElement$3(this.target(), this.hostRef.nativeElement, this.documentRef);
4609
+ if (targetElement) {
4610
+ this.resizeObserver?.observe(targetElement);
4611
+ this.observedTarget = targetElement;
4612
+ }
4613
+ this.documentRef.defaultView?.addEventListener('resize', this.scheduleRefresh);
4614
+ this.documentRef.addEventListener('scroll', this.scheduleRefresh, true);
4615
+ this.observersInitialized = true;
4616
+ }
4617
+ refreshShape() {
4618
+ if (!this.isBrowser) {
4619
+ return;
4620
+ }
4621
+ const bubbleElement = getBubbleElement$3(this.hostRef.nativeElement);
4622
+ if (!bubbleElement) {
4623
+ return;
4624
+ }
4625
+ const targetElement = resolveTargetElement$3(this.target(), this.hostRef.nativeElement, this.documentRef);
4626
+ if (this.resizeObserver && targetElement !== this.observedTarget) {
4627
+ if (this.observedTarget) {
4628
+ this.resizeObserver.unobserve(this.observedTarget);
4629
+ }
4630
+ if (targetElement) {
4631
+ this.resizeObserver.observe(targetElement);
4632
+ }
4633
+ this.observedTarget = targetElement;
4634
+ }
4635
+ const bubbleRect = bubbleElement.getBoundingClientRect();
4636
+ const targetRect = targetElement?.getBoundingClientRect() ?? null;
4637
+ const side = this.resolveTailSide(bubbleRect, targetRect);
4638
+ const seventh = bubbleRect.width / 7;
4639
+ const baseStartX = side === 'left'
4640
+ ? clamp$3(seventh, 20, bubbleRect.width - 56)
4641
+ : clamp$3(bubbleRect.width - seventh * 2, 20, bubbleRect.width - 56);
4642
+ const baseEndX = side === 'left'
4643
+ ? clamp$3(seventh * 2, baseStartX + 22, bubbleRect.width - 20)
4644
+ : clamp$3(bubbleRect.width - seventh, baseStartX + 22, bubbleRect.width - 20);
4645
+ const anchor = {
4646
+ x: bubbleRect.left + (baseStartX + baseEndX) / 2,
4647
+ y: bubbleRect.bottom,
4648
+ };
4649
+ const targetPoint = targetRect
4650
+ ? closestPointOnRect$3(targetRect, anchor)
4651
+ : {
4652
+ x: bubbleRect.left + (side === 'left' ? baseStartX : baseEndX),
4653
+ y: bubbleRect.bottom + Math.max(24, bubbleRect.height / 4),
4654
+ };
4655
+ const tipX = clamp$3(targetPoint.x - bubbleRect.left, -48, bubbleRect.width + 48);
4656
+ const tipY = Math.max(targetPoint.y - bubbleRect.top, bubbleRect.height + 22);
4657
+ const minX = Math.min(0, tipX);
4658
+ const maxX = Math.max(bubbleRect.width, tipX);
4659
+ const maxY = Math.max(bubbleRect.height, tipY);
4660
+ const padding = 10;
4661
+ const offsetX = padding - minX;
4662
+ const offsetY = padding;
4663
+ const width = maxX - minX + padding * 2;
4664
+ const height = maxY + padding * 2;
4665
+ this.bubbleGeometry.set({
4666
+ side,
4667
+ style: {
4668
+ left: `${minX - padding}px`,
4669
+ top: `${-padding}px`,
4670
+ width: `${width}px`,
4671
+ height: `${height}px`,
4672
+ },
4673
+ viewBox: `0 0 ${width.toFixed(2)} ${height.toFixed(2)}`,
4674
+ path: createUnifiedBubblePath$2(bubbleRect.width, bubbleRect.height, 18, baseStartX, baseEndX, tipX, tipY, offsetX, offsetY),
4675
+ });
4676
+ }
4677
+ resolveTailSide(bubbleRect, targetRect) {
4678
+ const tail = this.tail();
4679
+ if (tail === 'left' || tail === 'right') {
4680
+ return tail;
4681
+ }
4682
+ const targetCenterX = targetRect
4683
+ ? targetRect.left + targetRect.width / 2
4684
+ : bubbleRect.left + bubbleRect.width / 2;
4685
+ return targetCenterX < bubbleRect.left + bubbleRect.width / 2 ? 'left' : 'right';
4686
+ }
4687
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: DuckDevSpeakerBubbleClassic, deps: [], target: i0.ɵɵFactoryTarget.Component });
4688
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.1", type: DuckDevSpeakerBubbleClassic, isStandalone: true, selector: "dd-speaker-bubble-classic", inputs: { color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, tail: { classPropertyName: "tail", publicName: "tail", isSignal: true, isRequired: false, transformFunction: null }, target: { classPropertyName: "target", publicName: "target", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\n class=\"dd-speaker-bubble-classic\"\n [attr.data-tail]=\"resolvedTail()\"\n [ngStyle]=\"bubbleStyle()\"\n>\n <svg\n class=\"dd-speaker-bubble-classic__shape\"\n aria-hidden=\"true\"\n [ngStyle]=\"shapeStyle()\"\n [attr.viewBox]=\"shapeViewBox()\"\n preserveAspectRatio=\"none\"\n focusable=\"false\"\n >\n <path\n class=\"dd-speaker-bubble-classic__shape-path\"\n [attr.d]=\"shapePath()\"\n />\n </svg>\n <div class=\"dd-speaker-bubble-classic__content\">\n <ng-content />\n </div>\n</div>\n", styles: [":host{display:block;width:fit-content;max-width:min(100%,36rem)}.dd-speaker-bubble-classic{position:relative;isolation:isolate;overflow:visible;padding:18px 20px 17px;color:var(--dd-speaker-text)}.dd-speaker-bubble-classic__shape{position:absolute;z-index:0;pointer-events:none;filter:drop-shadow(6px 6px 0 color-mix(in srgb,var(--dd-speaker-shadow) 36%,transparent))}.dd-speaker-bubble-classic__shape-path{fill:var(--dd-speaker-surface);stroke:color-mix(in srgb,var(--dd-speaker-border) 90%,var(--dd-speaker-text));stroke-width:2;stroke-linecap:round;stroke-linejoin:round}.dd-speaker-bubble-classic__content{display:block;position:relative;z-index:1}.dd-speaker-bubble-classic__content :first-child{margin-top:0}.dd-speaker-bubble-classic__content :last-child{margin-bottom:0}.dd-speaker-bubble-classic__content strong{color:var(--dd-speaker-accent)}.dd-speaker-bubble-classic__content small{display:block;margin-bottom:6px;color:color-mix(in srgb,var(--dd-speaker-text) 72%,transparent);font-size:12px;font-weight:600;letter-spacing:.05em;text-transform:uppercase}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
4689
+ }
4690
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: DuckDevSpeakerBubbleClassic, decorators: [{
4691
+ type: Component,
4692
+ args: [{ selector: 'dd-speaker-bubble-classic', standalone: true, imports: [NgStyle], template: "<div\n class=\"dd-speaker-bubble-classic\"\n [attr.data-tail]=\"resolvedTail()\"\n [ngStyle]=\"bubbleStyle()\"\n>\n <svg\n class=\"dd-speaker-bubble-classic__shape\"\n aria-hidden=\"true\"\n [ngStyle]=\"shapeStyle()\"\n [attr.viewBox]=\"shapeViewBox()\"\n preserveAspectRatio=\"none\"\n focusable=\"false\"\n >\n <path\n class=\"dd-speaker-bubble-classic__shape-path\"\n [attr.d]=\"shapePath()\"\n />\n </svg>\n <div class=\"dd-speaker-bubble-classic__content\">\n <ng-content />\n </div>\n</div>\n", styles: [":host{display:block;width:fit-content;max-width:min(100%,36rem)}.dd-speaker-bubble-classic{position:relative;isolation:isolate;overflow:visible;padding:18px 20px 17px;color:var(--dd-speaker-text)}.dd-speaker-bubble-classic__shape{position:absolute;z-index:0;pointer-events:none;filter:drop-shadow(6px 6px 0 color-mix(in srgb,var(--dd-speaker-shadow) 36%,transparent))}.dd-speaker-bubble-classic__shape-path{fill:var(--dd-speaker-surface);stroke:color-mix(in srgb,var(--dd-speaker-border) 90%,var(--dd-speaker-text));stroke-width:2;stroke-linecap:round;stroke-linejoin:round}.dd-speaker-bubble-classic__content{display:block;position:relative;z-index:1}.dd-speaker-bubble-classic__content :first-child{margin-top:0}.dd-speaker-bubble-classic__content :last-child{margin-bottom:0}.dd-speaker-bubble-classic__content strong{color:var(--dd-speaker-accent)}.dd-speaker-bubble-classic__content small{display:block;margin-bottom:6px;color:color-mix(in srgb,var(--dd-speaker-text) 72%,transparent);font-size:12px;font-weight:600;letter-spacing:.05em;text-transform:uppercase}\n"] }]
4693
+ }], ctorParameters: () => [], propDecorators: { color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], tail: [{ type: i0.Input, args: [{ isSignal: true, alias: "tail", required: false }] }], target: [{ type: i0.Input, args: [{ isSignal: true, alias: "target", required: false }] }] } });
4694
+
4695
+ const TAIL_VARIANT_METRICS = {
4696
+ classic: {
4697
+ fallbackDy: 24,
4698
+ padding: 18,
4699
+ },
4700
+ soft: {
4701
+ fallbackDy: 28,
4702
+ padding: 20,
4703
+ },
4704
+ outline: {
4705
+ fallbackDy: 22,
4706
+ padding: 16,
4707
+ },
4708
+ 'neobrutal-slab': {
4709
+ fallbackDy: 28,
4710
+ padding: 22,
4711
+ },
4712
+ 'neobrutal-ticket': {
4713
+ fallbackDy: 28,
4714
+ padding: 22,
4715
+ },
4716
+ };
4717
+ function clamp$2(value, min, max) {
4718
+ return Math.min(Math.max(value, min), max);
4719
+ }
4720
+ function lerpPoint(from, to, t) {
4721
+ return {
4722
+ x: from.x + (to.x - from.x) * t,
4723
+ y: from.y + (to.y - from.y) * t,
4724
+ };
4725
+ }
4726
+ function serializePoint$2(point) {
4727
+ return `${point.x.toFixed(2)} ${point.y.toFixed(2)}`;
4728
+ }
4729
+ function toPath(points, close = true) {
4730
+ if (points.length === 0) {
4731
+ return '';
4732
+ }
4733
+ const [first, ...rest] = points;
4734
+ const path = [`M ${serializePoint$2(first)}`];
4735
+ for (const point of rest) {
4736
+ path.push(`L ${serializePoint$2(point)}`);
4737
+ }
4738
+ if (close) {
4739
+ path.push('Z');
4740
+ }
4741
+ return path.join(' ');
4742
+ }
4743
+ function getBubbleElement$2(hostElement) {
4744
+ return hostElement.firstElementChild instanceof HTMLElement ? hostElement.firstElementChild : null;
4745
+ }
4746
+ function closestPointOnRect$2(rect, point) {
4747
+ return {
4748
+ x: clamp$2(point.x, rect.left, rect.right),
4749
+ y: clamp$2(point.y, rect.top, rect.bottom),
4750
+ };
4751
+ }
4752
+ function resolveTargetElement$2(source, hostElement, documentRef) {
4753
+ if (!source) {
4754
+ return null;
4755
+ }
4756
+ if (source instanceof Element) {
4757
+ return source;
4758
+ }
4759
+ try {
4760
+ const scopedMatch = hostElement.parentElement?.querySelector(source);
4761
+ if (scopedMatch) {
4762
+ return scopedMatch;
4763
+ }
4764
+ return documentRef.querySelector(source);
4765
+ }
4766
+ catch {
4767
+ return null;
4768
+ }
4769
+ }
4770
+ function getTailBasePoints(bubbleRect, side) {
4771
+ const seventh = bubbleRect.width / 7;
4772
+ const baseStartX = side === 'left'
4773
+ ? clamp$2(seventh, 20, bubbleRect.width - 56)
4774
+ : clamp$2(bubbleRect.width - seventh * 2, 20, bubbleRect.width - 56);
4775
+ const baseEndX = side === 'left'
4776
+ ? clamp$2(seventh * 2, baseStartX + 22, bubbleRect.width - 20)
4777
+ : clamp$2(bubbleRect.width - seventh, baseStartX + 22, bubbleRect.width - 20);
4778
+ const baseY = bubbleRect.height;
4779
+ return {
4780
+ baseStart: { x: baseStartX, y: baseY },
4781
+ baseEnd: { x: baseEndX, y: baseY },
4782
+ anchor: { x: (baseStartX + baseEndX) / 2, y: baseY },
4783
+ };
4784
+ }
4785
+ function resolveTailSide(bubbleRect, targetRect, preferredTail) {
4786
+ if (preferredTail === 'left' || preferredTail === 'right') {
4787
+ return preferredTail;
4788
+ }
4789
+ const targetCenterX = targetRect
4790
+ ? targetRect.left + targetRect.width / 2
4791
+ : bubbleRect.left + bubbleRect.width / 2;
4792
+ return targetCenterX < bubbleRect.left + bubbleRect.width / 2 ? 'left' : 'right';
4793
+ }
4794
+ function buildClassicTail(baseStart, baseEnd, anchor, tip, side) {
4795
+ const dir = side === 'left' ? -1 : 1;
4796
+ const outer = side === 'left' ? baseStart : baseEnd;
4797
+ const inner = side === 'left' ? baseEnd : baseStart;
4798
+ const c1 = { x: outer.x + dir * 8, y: outer.y + 7 };
4799
+ const c2 = { x: anchor.x + (tip.x - anchor.x) * 0.34 + dir * 7, y: anchor.y + (tip.y - anchor.y) * 0.2 };
4800
+ const c3 = { x: tip.x - (tip.x - anchor.x) * 0.08 + dir * 6, y: tip.y - (tip.y - anchor.y) * 0.08 };
4801
+ const c4 = { x: tip.x - (tip.x - anchor.x) * 0.16 - dir * 4, y: tip.y - (tip.y - anchor.y) * 0.02 };
4802
+ const c5 = { x: anchor.x + (tip.x - anchor.x) * 0.72 - dir * 8, y: anchor.y + (tip.y - anchor.y) * 0.76 };
4803
+ const c6 = { x: inner.x - dir * 2, y: inner.y + 10 };
4804
+ const seam = { x: anchor.x + dir * 2, y: anchor.y + 2 };
4805
+ return {
4806
+ path: [
4807
+ `M ${serializePoint$2(outer)}`,
4808
+ `C ${serializePoint$2(c1)} ${serializePoint$2(c2)} ${serializePoint$2(c3)} ${serializePoint$2(tip)}`,
4809
+ `C ${serializePoint$2(c4)} ${serializePoint$2(c5)} ${serializePoint$2(c6)} ${serializePoint$2(inner)}`,
4810
+ `Q ${serializePoint$2(seam)} ${serializePoint$2(outer)}`,
4811
+ 'Z',
4812
+ ].join(' '),
4813
+ secondaryPath: null,
4814
+ points: [outer, inner, tip, c1, c2, c3, c4, c5, c6, seam, baseStart, baseEnd],
4815
+ };
4816
+ }
4817
+ function buildSoftTail(baseStart, baseEnd, anchor, tip, side) {
4818
+ const dir = side === 'left' ? -1 : 1;
4819
+ const outer = side === 'left' ? baseStart : baseEnd;
4820
+ const inner = side === 'left' ? baseEnd : baseStart;
4821
+ const c1 = { x: outer.x + dir * 10, y: outer.y + 10 };
4822
+ const c2 = { x: anchor.x + (tip.x - anchor.x) * 0.3 + dir * 8, y: anchor.y + (tip.y - anchor.y) * 0.18 };
4823
+ const c3 = { x: tip.x - (tip.x - anchor.x) * 0.05 + dir * 6, y: tip.y - (tip.y - anchor.y) * 0.08 };
4824
+ const c4 = { x: tip.x - (tip.x - anchor.x) * 0.18 - dir * 7, y: tip.y + (anchor.y - tip.y) * 0.06 };
4825
+ const c5 = { x: anchor.x + (tip.x - anchor.x) * 0.68 - dir * 10, y: anchor.y + (tip.y - anchor.y) * 0.74 };
4826
+ const c6 = { x: inner.x - dir * 3, y: inner.y + 12 };
4827
+ const seam = { x: anchor.x + dir * 1.5, y: anchor.y + 3 };
4828
+ const shineStart = lerpPoint(outer, tip, 0.16);
4829
+ const shineControl = {
4830
+ x: anchor.x + (tip.x - anchor.x) * 0.42,
4831
+ y: anchor.y + (tip.y - anchor.y) * 0.34 - 5,
4832
+ };
4833
+ const shineEnd = lerpPoint(inner, tip, 0.58);
4834
+ return {
4835
+ path: [
4836
+ `M ${serializePoint$2(outer)}`,
4837
+ `C ${serializePoint$2(c1)} ${serializePoint$2(c2)} ${serializePoint$2(c3)} ${serializePoint$2(tip)}`,
4838
+ `C ${serializePoint$2(c4)} ${serializePoint$2(c5)} ${serializePoint$2(c6)} ${serializePoint$2(inner)}`,
4839
+ `Q ${serializePoint$2(seam)} ${serializePoint$2(outer)}`,
4840
+ 'Z',
4841
+ ].join(' '),
4842
+ secondaryPath: `M ${serializePoint$2(shineStart)} Q ${serializePoint$2(shineControl)} ${serializePoint$2(shineEnd)}`,
4843
+ points: [
4844
+ outer,
4845
+ inner,
4846
+ tip,
4847
+ c1,
4848
+ c2,
4849
+ c3,
4850
+ c4,
4851
+ c5,
4852
+ c6,
4853
+ seam,
4854
+ shineStart,
4855
+ shineControl,
4856
+ shineEnd,
4857
+ baseStart,
4858
+ baseEnd,
4859
+ ],
4860
+ };
4861
+ }
4862
+ function buildOutlineTail(baseStart, baseEnd, anchor, tip, side) {
4863
+ const dir = side === 'left' ? -1 : 1;
4864
+ const outer = side === 'left' ? baseStart : baseEnd;
4865
+ const inner = side === 'left' ? baseEnd : baseStart;
4866
+ const elbowA = {
4867
+ x: anchor.x + (tip.x - anchor.x) * 0.26 + dir * 8,
4868
+ y: anchor.y + (tip.y - anchor.y) * 0.2,
4869
+ };
4870
+ const elbowB = {
4871
+ x: anchor.x + (tip.x - anchor.x) * 0.58 + dir * 3,
4872
+ y: anchor.y + (tip.y - anchor.y) * 0.7,
4873
+ };
4874
+ return {
4875
+ path: toPath([outer, elbowA, tip, elbowB, inner]),
4876
+ secondaryPath: null,
4877
+ points: [outer, inner, tip, elbowA, elbowB, baseStart, baseEnd],
4878
+ };
4879
+ }
4880
+ function buildNeobrutalSlabTail(baseStart, baseEnd, anchor, tip, side) {
4881
+ const dir = side === 'left' ? -1 : 1;
4882
+ const topOuter = {
4883
+ x: (side === 'left' ? baseStart.x : baseEnd.x) + dir * 4,
4884
+ y: anchor.y - 6,
4885
+ };
4886
+ const topInner = {
4887
+ x: (side === 'left' ? baseEnd.x : baseStart.x) - dir * 4,
4888
+ y: anchor.y - 6,
4889
+ };
4890
+ const hip = { x: anchor.x - dir * 14, y: anchor.y + 9 };
4891
+ const midA = {
4892
+ x: anchor.x + (tip.x - anchor.x) * 0.24 + dir * 10,
4893
+ y: anchor.y + (tip.y - anchor.y) * 0.2,
4894
+ };
4895
+ const midB = {
4896
+ x: anchor.x + (tip.x - anchor.x) * 0.56 + dir * 4,
4897
+ y: anchor.y + (tip.y - anchor.y) * 0.64,
4898
+ };
4899
+ const accentA = lerpPoint(topInner, tip, 0.18);
4900
+ const accentB = lerpPoint(topOuter, tip, 0.36);
4901
+ const accentC = lerpPoint(hip, tip, 0.58);
4902
+ return {
4903
+ path: toPath([topOuter, topInner, midA, tip, midB, hip]),
4904
+ secondaryPath: toPath([accentA, accentB, tip, accentC]),
4905
+ points: [
4906
+ topOuter,
4907
+ topInner,
4908
+ midA,
4909
+ tip,
4910
+ midB,
4911
+ hip,
4912
+ accentA,
4913
+ accentB,
4914
+ accentC,
4915
+ baseStart,
4916
+ baseEnd,
4917
+ ],
4918
+ };
4919
+ }
4920
+ function buildNeobrutalTicketTail(baseStart, baseEnd, anchor, tip, side) {
4921
+ const dir = side === 'left' ? -1 : 1;
4922
+ const topOuter = {
4923
+ x: (side === 'left' ? baseStart.x : baseEnd.x) + dir * 4,
4924
+ y: anchor.y - 6,
4925
+ };
4926
+ const topInner = {
4927
+ x: (side === 'left' ? baseEnd.x : baseStart.x) - dir * 4,
4928
+ y: anchor.y - 6,
4929
+ };
4930
+ const hip = { x: anchor.x - dir * 12, y: anchor.y + 10 };
4931
+ const midA = {
4932
+ x: anchor.x + (tip.x - anchor.x) * 0.26 + dir * 10,
4933
+ y: anchor.y + (tip.y - anchor.y) * 0.18,
4934
+ };
4935
+ const midB = {
4936
+ x: anchor.x + (tip.x - anchor.x) * 0.58 + dir * 3,
4937
+ y: anchor.y + (tip.y - anchor.y) * 0.62,
4938
+ };
4939
+ const notchStart = {
4940
+ x: anchor.x + dir * 7,
4941
+ y: anchor.y - 5,
4942
+ };
4943
+ const notchMiddle = {
4944
+ x: anchor.x + dir * 7,
4945
+ y: anchor.y + 8,
4946
+ };
4947
+ const notchEnd = {
4948
+ x: anchor.x + (tip.x - anchor.x) * 0.22,
4949
+ y: anchor.y + (tip.y - anchor.y) * 0.34,
4950
+ };
4951
+ return {
4952
+ path: toPath([topOuter, topInner, midA, tip, midB, hip]),
4953
+ secondaryPath: `M ${serializePoint$2(notchStart)} L ${serializePoint$2(notchMiddle)} L ${serializePoint$2(notchEnd)}`,
4954
+ points: [
4955
+ topOuter,
4956
+ topInner,
4957
+ midA,
4958
+ tip,
4959
+ midB,
4960
+ hip,
4961
+ notchStart,
4962
+ notchMiddle,
4963
+ notchEnd,
4964
+ baseStart,
4965
+ baseEnd,
4966
+ ],
4967
+ };
4968
+ }
4969
+ function buildTailPathBundle(variant, baseStart, baseEnd, anchor, tip, side) {
4970
+ switch (variant) {
4971
+ case 'soft':
4972
+ return buildSoftTail(baseStart, baseEnd, anchor, tip, side);
4973
+ case 'outline':
4974
+ return buildOutlineTail(baseStart, baseEnd, anchor, tip, side);
4975
+ case 'neobrutal-slab':
4976
+ return buildNeobrutalSlabTail(baseStart, baseEnd, anchor, tip, side);
4977
+ case 'neobrutal-ticket':
4978
+ return buildNeobrutalTicketTail(baseStart, baseEnd, anchor, tip, side);
4979
+ case 'classic':
4980
+ default:
4981
+ return buildClassicTail(baseStart, baseEnd, anchor, tip, side);
4982
+ }
4983
+ }
4984
+ function buildTailRenderModel(variant, bubbleRect, targetRect, preferredTail) {
4985
+ const metrics = TAIL_VARIANT_METRICS[variant];
4986
+ const side = resolveTailSide(bubbleRect, targetRect, preferredTail);
4987
+ const { baseStart, baseEnd, anchor } = getTailBasePoints(bubbleRect, side);
4988
+ const anchorViewport = {
4989
+ x: bubbleRect.left + anchor.x,
4990
+ y: bubbleRect.top + anchor.y,
4991
+ };
4992
+ const targetPoint = targetRect
4993
+ ? closestPointOnRect$2(targetRect, anchorViewport)
4994
+ : {
4995
+ x: bubbleRect.left + (side === 'left' ? baseStart.x : baseEnd.x),
4996
+ y: anchorViewport.y + metrics.fallbackDy,
4997
+ };
4998
+ const tip = {
4999
+ x: clamp$2(targetPoint.x - bubbleRect.left, -48, bubbleRect.width + 48),
5000
+ y: Math.max(targetPoint.y - bubbleRect.top, bubbleRect.height + metrics.fallbackDy),
5001
+ };
5002
+ const bundle = buildTailPathBundle(variant, baseStart, baseEnd, anchor, tip, side);
5003
+ const bounds = bundle.points.reduce((acc, point) => ({
5004
+ minX: Math.min(acc.minX, point.x),
5005
+ minY: Math.min(acc.minY, point.y),
5006
+ maxX: Math.max(acc.maxX, point.x),
5007
+ maxY: Math.max(acc.maxY, point.y),
5008
+ }), {
5009
+ minX: Number.POSITIVE_INFINITY,
5010
+ minY: Number.POSITIVE_INFINITY,
5011
+ maxX: Number.NEGATIVE_INFINITY,
5012
+ maxY: Number.NEGATIVE_INFINITY,
5013
+ });
5014
+ const translateX = metrics.padding - bounds.minX;
5015
+ const translateY = metrics.padding - bounds.minY;
5016
+ const width = Math.max(1, bounds.maxX - bounds.minX + metrics.padding * 2);
5017
+ const height = Math.max(1, bounds.maxY - bounds.minY + metrics.padding * 2);
5018
+ const translatePath = (path) => path
5019
+ ?.replace(/-?\d+(?:\.\d+)? -?\d+(?:\.\d+)?/g, (match) => {
5020
+ const [x, y] = match.split(' ').map(Number);
5021
+ return `${(x + translateX).toFixed(2)} ${(y + translateY).toFixed(2)}`;
5022
+ })
5023
+ .trim() ?? null;
5024
+ return {
5025
+ side,
5026
+ style: {
5027
+ left: `${bounds.minX - metrics.padding}px`,
5028
+ top: `${bounds.minY - metrics.padding}px`,
5029
+ width: `${width}px`,
5030
+ height: `${height}px`,
5031
+ },
5032
+ viewBox: `0 0 ${width.toFixed(2)} ${height.toFixed(2)}`,
5033
+ path: translatePath(bundle.path) ?? '',
5034
+ secondaryPath: translatePath(bundle.secondaryPath),
5035
+ };
5036
+ }
5037
+ function useSpeakerBubbleTail(variant, tail, target) {
5038
+ const hostRef = inject((ElementRef));
5039
+ const documentRef = inject(DOCUMENT);
5040
+ const destroyRef = inject(DestroyRef);
5041
+ const platformId = inject(PLATFORM_ID);
5042
+ const isBrowser = isPlatformBrowser(platformId);
5043
+ const renderModel = signal({
5044
+ side: 'left',
5045
+ style: {
5046
+ left: '0px',
5047
+ top: '0px',
5048
+ width: '1px',
5049
+ height: '1px',
5050
+ },
5051
+ viewBox: '0 0 1 1',
5052
+ path: '',
5053
+ secondaryPath: null,
5054
+ }, { ...(ngDevMode ? { debugName: "renderModel" } : {}) });
5055
+ let animationFrameId = -1;
5056
+ let resizeObserver = null;
5057
+ let observedTarget = null;
5058
+ let isInitialized = false;
5059
+ const cleanupObservers = () => {
5060
+ if (animationFrameId !== -1) {
5061
+ cancelAnimationFrame(animationFrameId);
5062
+ animationFrameId = -1;
5063
+ }
5064
+ resizeObserver?.disconnect();
5065
+ resizeObserver = null;
5066
+ observedTarget = null;
5067
+ };
5068
+ const refreshTail = () => {
5069
+ if (!isBrowser) {
5070
+ return;
5071
+ }
5072
+ const bubbleElement = getBubbleElement$2(hostRef.nativeElement);
5073
+ if (!bubbleElement) {
5074
+ return;
5075
+ }
5076
+ const targetElement = resolveTargetElement$2(target(), hostRef.nativeElement, documentRef);
5077
+ if (resizeObserver && targetElement !== observedTarget) {
5078
+ if (observedTarget) {
5079
+ resizeObserver.unobserve(observedTarget);
5080
+ }
5081
+ if (targetElement) {
5082
+ resizeObserver.observe(targetElement);
5083
+ }
5084
+ observedTarget = targetElement;
5085
+ }
5086
+ renderModel.set(buildTailRenderModel(variant, bubbleElement.getBoundingClientRect(), targetElement?.getBoundingClientRect() ?? null, tail()));
5087
+ };
5088
+ const scheduleRefresh = () => {
5089
+ if (!isBrowser || animationFrameId !== -1) {
5090
+ return;
5091
+ }
5092
+ animationFrameId = requestAnimationFrame(() => {
5093
+ animationFrameId = -1;
5094
+ refreshTail();
5095
+ });
5096
+ };
5097
+ const setupObservers = () => {
5098
+ if (!isBrowser || isInitialized) {
5099
+ return;
5100
+ }
5101
+ const bubbleElement = getBubbleElement$2(hostRef.nativeElement);
5102
+ if (!bubbleElement) {
5103
+ return;
5104
+ }
5105
+ resizeObserver = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(scheduleRefresh);
5106
+ resizeObserver?.observe(bubbleElement);
5107
+ const targetElement = resolveTargetElement$2(target(), hostRef.nativeElement, documentRef);
5108
+ if (targetElement) {
5109
+ resizeObserver?.observe(targetElement);
5110
+ observedTarget = targetElement;
5111
+ }
5112
+ documentRef.defaultView?.addEventListener('resize', scheduleRefresh);
5113
+ documentRef.addEventListener('scroll', scheduleRefresh, true);
5114
+ destroyRef.onDestroy(() => {
5115
+ documentRef.defaultView?.removeEventListener('resize', scheduleRefresh);
5116
+ documentRef.removeEventListener('scroll', scheduleRefresh, true);
5117
+ cleanupObservers();
5118
+ });
5119
+ isInitialized = true;
5120
+ scheduleRefresh();
5121
+ };
5122
+ afterNextRender(() => {
5123
+ setupObservers();
5124
+ scheduleRefresh();
5125
+ });
5126
+ afterRenderEffect(() => {
5127
+ if (!isBrowser) {
5128
+ return;
5129
+ }
5130
+ tail();
5131
+ target();
5132
+ setupObservers();
5133
+ scheduleRefresh();
5134
+ });
5135
+ return {
5136
+ resolvedTail: computed(() => renderModel().side),
5137
+ tailStyle: computed(() => renderModel().style),
5138
+ tailViewBox: computed(() => renderModel().viewBox),
5139
+ tailPath: computed(() => renderModel().path),
5140
+ tailSecondaryPath: computed(() => renderModel().secondaryPath),
5141
+ };
5142
+ }
5143
+
5144
+ class DuckDevSpeakerBubbleSoft {
5145
+ color = input(AccentEnumColor.Violet, { ...(ngDevMode ? { debugName: "color" } : {}) });
5146
+ tail = input('left', { ...(ngDevMode ? { debugName: "tail" } : {}) });
5147
+ target = input(null, { ...(ngDevMode ? { debugName: "target" } : {}) });
5148
+ tailController = useSpeakerBubbleTail('soft', this.tail, this.target);
5149
+ bubbleStyle = computed(() => getClassicSpeakerBubbleStyle(this.color()), { ...(ngDevMode ? { debugName: "bubbleStyle" } : {}) });
5150
+ resolvedTail = this.tailController.resolvedTail;
5151
+ tailStyle = this.tailController.tailStyle;
5152
+ tailViewBox = this.tailController.tailViewBox;
5153
+ tailPath = this.tailController.tailPath;
5154
+ tailSecondaryPath = this.tailController.tailSecondaryPath;
5155
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: DuckDevSpeakerBubbleSoft, deps: [], target: i0.ɵɵFactoryTarget.Component });
5156
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.1", type: DuckDevSpeakerBubbleSoft, isStandalone: true, selector: "dd-speaker-bubble-soft", inputs: { color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, tail: { classPropertyName: "tail", publicName: "tail", isSignal: true, isRequired: false, transformFunction: null }, target: { classPropertyName: "target", publicName: "target", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"dd-speaker-bubble-soft\" [attr.data-tail]=\"resolvedTail()\" [ngStyle]=\"bubbleStyle()\">\n <span class=\"dd-speaker-bubble-soft__tail\" aria-hidden=\"true\" [ngStyle]=\"tailStyle()\">\n <svg\n [attr.viewBox]=\"tailViewBox()\"\n preserveAspectRatio=\"none\"\n focusable=\"false\"\n aria-hidden=\"true\"\n >\n <path\n class=\"dd-speaker-bubble-soft__tail-path\"\n [attr.d]=\"tailPath()\"\n />\n <path\n class=\"dd-speaker-bubble-soft__tail-shine\"\n [attr.d]=\"tailSecondaryPath()\"\n />\n </svg>\n </span>\n <div class=\"dd-speaker-bubble-soft__content\">\n <ng-content />\n </div>\n</div>\n", styles: [":host{display:block;width:fit-content;max-width:min(100%,36rem)}.dd-speaker-bubble-soft{position:relative;isolation:isolate;overflow:visible;padding:19px 21px 18px;border:1px solid color-mix(in srgb,var(--dd-speaker-border) 78%,var(--dd-speaker-accent));border-radius:28px 28px 28px 18px;background:radial-gradient(circle at top right,color-mix(in srgb,var(--dd-speaker-accent) 22%,transparent) 0,transparent 38%),radial-gradient(circle at 24% 18%,color-mix(in srgb,white 42%,transparent) 0,transparent 22%),linear-gradient(180deg,color-mix(in srgb,var(--dd-speaker-surface-muted) 82%,var(--dd-speaker-surface)) 0,var(--dd-speaker-surface) 100%);box-shadow:inset 0 1px color-mix(in srgb,var(--dd-speaker-surface) 85%,white),0 16px 30px color-mix(in srgb,var(--dd-speaker-shadow) 16%,transparent),0 4px 14px color-mix(in srgb,var(--dd-speaker-accent) 10%,transparent);color:var(--dd-speaker-text);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.dd-speaker-bubble-soft[data-tail=right]{border-radius:28px 28px 18px}.dd-speaker-bubble-soft__tail{position:absolute;z-index:-1;filter:drop-shadow(0 12px 18px color-mix(in srgb,var(--dd-speaker-shadow) 14%,transparent)) drop-shadow(0 2px 3px color-mix(in srgb,white 24%,transparent));pointer-events:none}.dd-speaker-bubble-soft__tail svg{display:block;width:100%;height:100%;overflow:visible}.dd-speaker-bubble-soft__tail-path{fill:color-mix(in srgb,var(--dd-speaker-surface-muted) 84%,var(--dd-speaker-surface));stroke:color-mix(in srgb,var(--dd-speaker-border) 72%,var(--dd-speaker-accent));stroke-width:1.3;stroke-linecap:round;stroke-linejoin:round}.dd-speaker-bubble-soft__tail-shine{fill:none;stroke:color-mix(in srgb,white 48%,var(--dd-speaker-accent));stroke-width:1.6;stroke-linecap:round;opacity:.72}.dd-speaker-bubble-soft__content :first-child{margin-top:0}.dd-speaker-bubble-soft__content :last-child{margin-bottom:0}.dd-speaker-bubble-soft__content strong{color:var(--dd-speaker-accent)}.dd-speaker-bubble-soft__content small{display:block;margin-bottom:8px;color:color-mix(in srgb,var(--dd-speaker-text) 72%,transparent);font-size:12px;letter-spacing:.05em;text-transform:uppercase}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
5157
+ }
5158
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: DuckDevSpeakerBubbleSoft, decorators: [{
5159
+ type: Component,
5160
+ args: [{ selector: 'dd-speaker-bubble-soft', standalone: true, imports: [NgStyle], template: "<div class=\"dd-speaker-bubble-soft\" [attr.data-tail]=\"resolvedTail()\" [ngStyle]=\"bubbleStyle()\">\n <span class=\"dd-speaker-bubble-soft__tail\" aria-hidden=\"true\" [ngStyle]=\"tailStyle()\">\n <svg\n [attr.viewBox]=\"tailViewBox()\"\n preserveAspectRatio=\"none\"\n focusable=\"false\"\n aria-hidden=\"true\"\n >\n <path\n class=\"dd-speaker-bubble-soft__tail-path\"\n [attr.d]=\"tailPath()\"\n />\n <path\n class=\"dd-speaker-bubble-soft__tail-shine\"\n [attr.d]=\"tailSecondaryPath()\"\n />\n </svg>\n </span>\n <div class=\"dd-speaker-bubble-soft__content\">\n <ng-content />\n </div>\n</div>\n", styles: [":host{display:block;width:fit-content;max-width:min(100%,36rem)}.dd-speaker-bubble-soft{position:relative;isolation:isolate;overflow:visible;padding:19px 21px 18px;border:1px solid color-mix(in srgb,var(--dd-speaker-border) 78%,var(--dd-speaker-accent));border-radius:28px 28px 28px 18px;background:radial-gradient(circle at top right,color-mix(in srgb,var(--dd-speaker-accent) 22%,transparent) 0,transparent 38%),radial-gradient(circle at 24% 18%,color-mix(in srgb,white 42%,transparent) 0,transparent 22%),linear-gradient(180deg,color-mix(in srgb,var(--dd-speaker-surface-muted) 82%,var(--dd-speaker-surface)) 0,var(--dd-speaker-surface) 100%);box-shadow:inset 0 1px color-mix(in srgb,var(--dd-speaker-surface) 85%,white),0 16px 30px color-mix(in srgb,var(--dd-speaker-shadow) 16%,transparent),0 4px 14px color-mix(in srgb,var(--dd-speaker-accent) 10%,transparent);color:var(--dd-speaker-text);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.dd-speaker-bubble-soft[data-tail=right]{border-radius:28px 28px 18px}.dd-speaker-bubble-soft__tail{position:absolute;z-index:-1;filter:drop-shadow(0 12px 18px color-mix(in srgb,var(--dd-speaker-shadow) 14%,transparent)) drop-shadow(0 2px 3px color-mix(in srgb,white 24%,transparent));pointer-events:none}.dd-speaker-bubble-soft__tail svg{display:block;width:100%;height:100%;overflow:visible}.dd-speaker-bubble-soft__tail-path{fill:color-mix(in srgb,var(--dd-speaker-surface-muted) 84%,var(--dd-speaker-surface));stroke:color-mix(in srgb,var(--dd-speaker-border) 72%,var(--dd-speaker-accent));stroke-width:1.3;stroke-linecap:round;stroke-linejoin:round}.dd-speaker-bubble-soft__tail-shine{fill:none;stroke:color-mix(in srgb,white 48%,var(--dd-speaker-accent));stroke-width:1.6;stroke-linecap:round;opacity:.72}.dd-speaker-bubble-soft__content :first-child{margin-top:0}.dd-speaker-bubble-soft__content :last-child{margin-bottom:0}.dd-speaker-bubble-soft__content strong{color:var(--dd-speaker-accent)}.dd-speaker-bubble-soft__content small{display:block;margin-bottom:8px;color:color-mix(in srgb,var(--dd-speaker-text) 72%,transparent);font-size:12px;letter-spacing:.05em;text-transform:uppercase}\n"] }]
5161
+ }], propDecorators: { color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], tail: [{ type: i0.Input, args: [{ isSignal: true, alias: "tail", required: false }] }], target: [{ type: i0.Input, args: [{ isSignal: true, alias: "target", required: false }] }] } });
5162
+
5163
+ class DuckDevSpeakerBubbleOutline {
5164
+ color = input(AccentEnumColor.Gray, { ...(ngDevMode ? { debugName: "color" } : {}) });
5165
+ tail = input('left', { ...(ngDevMode ? { debugName: "tail" } : {}) });
5166
+ target = input(null, { ...(ngDevMode ? { debugName: "target" } : {}) });
5167
+ tailController = useSpeakerBubbleTail('outline', this.tail, this.target);
5168
+ bubbleStyle = computed(() => getClassicSpeakerBubbleStyle(this.color()), { ...(ngDevMode ? { debugName: "bubbleStyle" } : {}) });
5169
+ resolvedTail = this.tailController.resolvedTail;
5170
+ tailStyle = this.tailController.tailStyle;
5171
+ tailViewBox = this.tailController.tailViewBox;
5172
+ tailPath = this.tailController.tailPath;
5173
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: DuckDevSpeakerBubbleOutline, deps: [], target: i0.ɵɵFactoryTarget.Component });
5174
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.1", type: DuckDevSpeakerBubbleOutline, isStandalone: true, selector: "dd-speaker-bubble-outline", inputs: { color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, tail: { classPropertyName: "tail", publicName: "tail", isSignal: true, isRequired: false, transformFunction: null }, target: { classPropertyName: "target", publicName: "target", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\n class=\"dd-speaker-bubble-outline\"\n [attr.data-tail]=\"resolvedTail()\"\n [ngStyle]=\"bubbleStyle()\"\n>\n <span class=\"dd-speaker-bubble-outline__tail\" aria-hidden=\"true\" [ngStyle]=\"tailStyle()\">\n <svg\n [attr.viewBox]=\"tailViewBox()\"\n preserveAspectRatio=\"none\"\n focusable=\"false\"\n aria-hidden=\"true\"\n >\n <path\n class=\"dd-speaker-bubble-outline__tail-path\"\n [attr.d]=\"tailPath()\"\n />\n </svg>\n </span>\n <div class=\"dd-speaker-bubble-outline__content\">\n <ng-content />\n </div>\n</div>\n", styles: [":host{display:block;width:fit-content;max-width:min(100%,36rem)}.dd-speaker-bubble-outline{position:relative;isolation:isolate;overflow:visible;padding:17px 19px 16px;border:2px solid var(--dd-speaker-border);border-radius:22px 22px 22px 10px;outline:1px dashed color-mix(in srgb,var(--dd-speaker-accent) 45%,transparent);outline-offset:-8px;background:linear-gradient(90deg,var(--dd-speaker-accent),var(--dd-speaker-accent)) 14px calc(100% - 12px) /28px 3px no-repeat,linear-gradient(180deg,color-mix(in srgb,var(--dd-speaker-accent) 8%,transparent) 0,transparent 52%),var(--dd-speaker-surface);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--dd-speaker-surface) 50%,white),6px 6px color-mix(in srgb,var(--dd-speaker-accent) 18%,transparent);color:var(--dd-speaker-text)}.dd-speaker-bubble-outline[data-tail=right]{border-radius:22px 22px 10px;background-position:calc(100% - 14px) calc(100% - 12px),0 0,0 0}.dd-speaker-bubble-outline__tail{position:absolute;z-index:-1;filter:drop-shadow(3px 4px 0 color-mix(in srgb,var(--dd-speaker-accent) 14%,transparent));pointer-events:none}.dd-speaker-bubble-outline__tail svg{display:block;width:100%;height:100%;overflow:visible}.dd-speaker-bubble-outline__tail-path{fill:var(--dd-speaker-surface);stroke:var(--dd-speaker-border);stroke-width:2;stroke-linecap:square;stroke-linejoin:miter}.dd-speaker-bubble-outline__content :first-child{margin-top:0}.dd-speaker-bubble-outline__content :last-child{margin-bottom:0}.dd-speaker-bubble-outline__content strong{color:var(--dd-speaker-accent)}.dd-speaker-bubble-outline__content small{display:block;margin-bottom:8px;color:color-mix(in srgb,var(--dd-speaker-text) 72%,transparent);font-size:12px;letter-spacing:.08em;text-transform:uppercase}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
5175
+ }
5176
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: DuckDevSpeakerBubbleOutline, decorators: [{
5177
+ type: Component,
5178
+ args: [{ selector: 'dd-speaker-bubble-outline', standalone: true, imports: [NgStyle], template: "<div\n class=\"dd-speaker-bubble-outline\"\n [attr.data-tail]=\"resolvedTail()\"\n [ngStyle]=\"bubbleStyle()\"\n>\n <span class=\"dd-speaker-bubble-outline__tail\" aria-hidden=\"true\" [ngStyle]=\"tailStyle()\">\n <svg\n [attr.viewBox]=\"tailViewBox()\"\n preserveAspectRatio=\"none\"\n focusable=\"false\"\n aria-hidden=\"true\"\n >\n <path\n class=\"dd-speaker-bubble-outline__tail-path\"\n [attr.d]=\"tailPath()\"\n />\n </svg>\n </span>\n <div class=\"dd-speaker-bubble-outline__content\">\n <ng-content />\n </div>\n</div>\n", styles: [":host{display:block;width:fit-content;max-width:min(100%,36rem)}.dd-speaker-bubble-outline{position:relative;isolation:isolate;overflow:visible;padding:17px 19px 16px;border:2px solid var(--dd-speaker-border);border-radius:22px 22px 22px 10px;outline:1px dashed color-mix(in srgb,var(--dd-speaker-accent) 45%,transparent);outline-offset:-8px;background:linear-gradient(90deg,var(--dd-speaker-accent),var(--dd-speaker-accent)) 14px calc(100% - 12px) /28px 3px no-repeat,linear-gradient(180deg,color-mix(in srgb,var(--dd-speaker-accent) 8%,transparent) 0,transparent 52%),var(--dd-speaker-surface);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--dd-speaker-surface) 50%,white),6px 6px color-mix(in srgb,var(--dd-speaker-accent) 18%,transparent);color:var(--dd-speaker-text)}.dd-speaker-bubble-outline[data-tail=right]{border-radius:22px 22px 10px;background-position:calc(100% - 14px) calc(100% - 12px),0 0,0 0}.dd-speaker-bubble-outline__tail{position:absolute;z-index:-1;filter:drop-shadow(3px 4px 0 color-mix(in srgb,var(--dd-speaker-accent) 14%,transparent));pointer-events:none}.dd-speaker-bubble-outline__tail svg{display:block;width:100%;height:100%;overflow:visible}.dd-speaker-bubble-outline__tail-path{fill:var(--dd-speaker-surface);stroke:var(--dd-speaker-border);stroke-width:2;stroke-linecap:square;stroke-linejoin:miter}.dd-speaker-bubble-outline__content :first-child{margin-top:0}.dd-speaker-bubble-outline__content :last-child{margin-bottom:0}.dd-speaker-bubble-outline__content strong{color:var(--dd-speaker-accent)}.dd-speaker-bubble-outline__content small{display:block;margin-bottom:8px;color:color-mix(in srgb,var(--dd-speaker-text) 72%,transparent);font-size:12px;letter-spacing:.08em;text-transform:uppercase}\n"] }]
5179
+ }], propDecorators: { color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], tail: [{ type: i0.Input, args: [{ isSignal: true, alias: "tail", required: false }] }], target: [{ type: i0.Input, args: [{ isSignal: true, alias: "target", required: false }] }] } });
5180
+
5181
+ const DEFAULT_BUBBLE_GEOMETRY$1 = {
5182
+ side: 'left',
5183
+ style: {
5184
+ left: '0px',
5185
+ top: '0px',
5186
+ width: '1px',
5187
+ height: '1px',
5188
+ },
5189
+ viewBox: '0 0 1 1',
5190
+ path: '',
5191
+ };
5192
+ function clamp$1(value, min, max) {
5193
+ return Math.min(Math.max(value, min), max);
5194
+ }
5195
+ function serializePoint$1(point) {
5196
+ return `${point.x.toFixed(2)} ${point.y.toFixed(2)}`;
5197
+ }
5198
+ function closestPointOnRect$1(rect, point) {
5199
+ return {
5200
+ x: clamp$1(point.x, rect.left, rect.right),
5201
+ y: clamp$1(point.y, rect.top, rect.bottom),
5202
+ };
5203
+ }
5204
+ function resolveTargetElement$1(source, hostElement, documentRef) {
5205
+ if (!source) {
5206
+ return null;
5207
+ }
5208
+ if (source instanceof Element) {
5209
+ return source;
5210
+ }
5211
+ try {
5212
+ const localMatch = hostElement.parentElement?.querySelector(source);
5213
+ if (localMatch) {
5214
+ return localMatch;
5215
+ }
5216
+ return documentRef.querySelector(source);
5217
+ }
5218
+ catch {
5219
+ return null;
5220
+ }
5221
+ }
5222
+ function getBubbleElement$1(hostElement) {
5223
+ return hostElement.firstElementChild instanceof HTMLElement ? hostElement.firstElementChild : null;
5224
+ }
5225
+ function createUnifiedBubblePath$1(width, height, radius, baseStartX, baseEndX, tipX, tipY, offsetX, offsetY) {
5226
+ const left = offsetX;
5227
+ const top = offsetY;
5228
+ const right = offsetX + width;
5229
+ const bottom = offsetY + height;
5230
+ const start = { x: left + radius, y: top };
5231
+ const bottomRight = { x: right, y: bottom - radius };
5232
+ const bottomRightArcEnd = { x: right - radius, y: bottom };
5233
+ const baseStart = { x: offsetX + baseStartX, y: bottom };
5234
+ const baseEnd = { x: offsetX + baseEndX, y: bottom };
5235
+ const tip = { x: offsetX + tipX, y: offsetY + tipY };
5236
+ const bottomLeftArcStart = { x: left + radius, y: bottom };
5237
+ const leftBottom = { x: left, y: bottom - radius };
5238
+ const leftTop = { x: left, y: top + radius };
5239
+ return [
5240
+ `M ${serializePoint$1(start)}`,
5241
+ `H ${(right - radius).toFixed(2)}`,
5242
+ `A ${radius} ${radius} 0 0 1 ${right.toFixed(2)} ${(top + radius).toFixed(2)}`,
5243
+ `V ${bottomRight.y.toFixed(2)}`,
5244
+ `A ${radius} ${radius} 0 0 1 ${serializePoint$1(bottomRightArcEnd)}`,
5245
+ `H ${baseEnd.x.toFixed(2)}`,
5246
+ `L ${serializePoint$1(tip)}`,
5247
+ `L ${serializePoint$1(baseStart)}`,
5248
+ `H ${bottomLeftArcStart.x.toFixed(2)}`,
5249
+ `A ${radius} ${radius} 0 0 1 ${serializePoint$1(leftBottom)}`,
5250
+ `V ${leftTop.y.toFixed(2)}`,
5251
+ `A ${radius} ${radius} 0 0 1 ${serializePoint$1(start)}`,
5252
+ 'Z',
5253
+ ].join(' ');
5254
+ }
5255
+ class DuckDevSpeakerBubbleNeobrutalSlab {
5256
+ color = input(AccentEnumColor.Orange, { ...(ngDevMode ? { debugName: "color" } : {}) });
5257
+ tail = input('left', { ...(ngDevMode ? { debugName: "tail" } : {}) });
5258
+ target = input(null, { ...(ngDevMode ? { debugName: "target" } : {}) });
5259
+ hostRef = inject((ElementRef));
5260
+ documentRef = inject(DOCUMENT);
5261
+ destroyRef = inject(DestroyRef);
5262
+ platformId = inject(PLATFORM_ID);
5263
+ isBrowser = isPlatformBrowser(this.platformId);
5264
+ bubbleGeometry = signal(DEFAULT_BUBBLE_GEOMETRY$1, { ...(ngDevMode ? { debugName: "bubbleGeometry" } : {}) });
5265
+ animationFrameId = -1;
5266
+ resizeObserver = null;
5267
+ observedTarget = null;
5268
+ observersInitialized = false;
5269
+ bubbleStyle = computed(() => getNeobrutalSpeakerBubbleStyle(this.color()), { ...(ngDevMode ? { debugName: "bubbleStyle" } : {}) });
5270
+ resolvedTail = computed(() => this.bubbleGeometry().side, { ...(ngDevMode ? { debugName: "resolvedTail" } : {}) });
5271
+ shapeStyle = computed(() => this.bubbleGeometry().style, { ...(ngDevMode ? { debugName: "shapeStyle" } : {}) });
5272
+ shapeViewBox = computed(() => this.bubbleGeometry().viewBox, { ...(ngDevMode ? { debugName: "shapeViewBox" } : {}) });
5273
+ shapePath = computed(() => this.bubbleGeometry().path, { ...(ngDevMode ? { debugName: "shapePath" } : {}) });
5274
+ constructor() {
5275
+ afterNextRender(() => {
5276
+ this.setupObservers();
5277
+ this.scheduleRefresh();
5278
+ });
5279
+ afterRenderEffect(() => {
5280
+ this.tail();
5281
+ this.target();
5282
+ this.setupObservers();
5283
+ this.scheduleRefresh();
5284
+ });
5285
+ this.destroyRef.onDestroy(() => {
5286
+ this.documentRef.defaultView?.removeEventListener('resize', this.scheduleRefresh);
5287
+ this.documentRef.removeEventListener('scroll', this.scheduleRefresh, true);
5288
+ if (this.animationFrameId !== -1) {
5289
+ cancelAnimationFrame(this.animationFrameId);
5290
+ }
5291
+ this.resizeObserver?.disconnect();
5292
+ this.resizeObserver = null;
5293
+ this.observedTarget = null;
5294
+ });
5295
+ }
5296
+ scheduleRefresh = () => {
5297
+ if (!this.isBrowser || this.animationFrameId !== -1) {
5298
+ return;
5299
+ }
5300
+ this.animationFrameId = requestAnimationFrame(() => {
5301
+ this.animationFrameId = -1;
5302
+ this.refreshShape();
5303
+ });
5304
+ };
5305
+ setupObservers() {
5306
+ if (!this.isBrowser || this.observersInitialized) {
5307
+ return;
5308
+ }
5309
+ const bubbleElement = getBubbleElement$1(this.hostRef.nativeElement);
5310
+ if (!bubbleElement) {
5311
+ return;
5312
+ }
5313
+ if (typeof ResizeObserver !== 'undefined') {
5314
+ this.resizeObserver = new ResizeObserver(() => this.scheduleRefresh());
5315
+ this.resizeObserver.observe(bubbleElement);
5316
+ }
5317
+ const targetElement = resolveTargetElement$1(this.target(), this.hostRef.nativeElement, this.documentRef);
5318
+ if (targetElement) {
5319
+ this.resizeObserver?.observe(targetElement);
5320
+ this.observedTarget = targetElement;
5321
+ }
5322
+ this.documentRef.defaultView?.addEventListener('resize', this.scheduleRefresh);
5323
+ this.documentRef.addEventListener('scroll', this.scheduleRefresh, true);
5324
+ this.observersInitialized = true;
5325
+ }
5326
+ refreshShape() {
5327
+ if (!this.isBrowser) {
5328
+ return;
5329
+ }
5330
+ const bubbleElement = getBubbleElement$1(this.hostRef.nativeElement);
5331
+ if (!bubbleElement) {
5332
+ return;
5333
+ }
5334
+ const targetElement = resolveTargetElement$1(this.target(), this.hostRef.nativeElement, this.documentRef);
5335
+ if (this.resizeObserver && targetElement !== this.observedTarget) {
5336
+ if (this.observedTarget) {
5337
+ this.resizeObserver.unobserve(this.observedTarget);
5338
+ }
5339
+ if (targetElement) {
5340
+ this.resizeObserver.observe(targetElement);
5341
+ }
5342
+ this.observedTarget = targetElement;
5343
+ }
5344
+ const bubbleRect = bubbleElement.getBoundingClientRect();
5345
+ const targetRect = targetElement?.getBoundingClientRect() ?? null;
5346
+ const side = this.resolveTailSide(bubbleRect, targetRect);
5347
+ const seventh = bubbleRect.width / 7;
5348
+ const baseStartX = side === 'left'
5349
+ ? clamp$1(seventh, 24, bubbleRect.width - 64)
5350
+ : clamp$1(bubbleRect.width - seventh * 2, 24, bubbleRect.width - 64);
5351
+ const baseEndX = side === 'left'
5352
+ ? clamp$1(seventh * 2, baseStartX + 24, bubbleRect.width - 24)
5353
+ : clamp$1(bubbleRect.width - seventh, baseStartX + 24, bubbleRect.width - 24);
5354
+ const anchor = {
5355
+ x: bubbleRect.left + (baseStartX + baseEndX) / 2,
5356
+ y: bubbleRect.bottom,
5357
+ };
5358
+ const targetPoint = targetRect
5359
+ ? closestPointOnRect$1(targetRect, anchor)
5360
+ : {
5361
+ x: bubbleRect.left + (side === 'left' ? baseStartX : baseEndX),
5362
+ y: bubbleRect.bottom + Math.max(28, bubbleRect.height / 4),
5363
+ };
5364
+ const tipX = clamp$1(targetPoint.x - bubbleRect.left, -52, bubbleRect.width + 52);
5365
+ const tipY = Math.max(targetPoint.y - bubbleRect.top, bubbleRect.height + 24);
5366
+ const minX = Math.min(0, tipX);
5367
+ const maxX = Math.max(bubbleRect.width, tipX);
5368
+ const maxY = Math.max(bubbleRect.height, tipY);
5369
+ const padding = 12;
5370
+ const offsetX = padding - minX;
5371
+ const offsetY = padding;
5372
+ const width = maxX - minX + padding * 2;
5373
+ const height = maxY + padding * 2;
5374
+ this.bubbleGeometry.set({
5375
+ side,
5376
+ style: {
5377
+ left: `${minX - padding}px`,
5378
+ top: `${-padding}px`,
5379
+ width: `${width}px`,
5380
+ height: `${height}px`,
5381
+ },
5382
+ viewBox: `0 0 ${width.toFixed(2)} ${height.toFixed(2)}`,
5383
+ path: createUnifiedBubblePath$1(bubbleRect.width, bubbleRect.height, 8, baseStartX, baseEndX, tipX, tipY, offsetX, offsetY),
5384
+ });
5385
+ }
5386
+ resolveTailSide(bubbleRect, targetRect) {
5387
+ const tail = this.tail();
5388
+ if (tail === 'left' || tail === 'right') {
5389
+ return tail;
5390
+ }
5391
+ const targetCenterX = targetRect
5392
+ ? targetRect.left + targetRect.width / 2
5393
+ : bubbleRect.left + bubbleRect.width / 2;
5394
+ return targetCenterX < bubbleRect.left + bubbleRect.width / 2 ? 'left' : 'right';
5395
+ }
5396
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: DuckDevSpeakerBubbleNeobrutalSlab, deps: [], target: i0.ɵɵFactoryTarget.Component });
5397
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.1", type: DuckDevSpeakerBubbleNeobrutalSlab, isStandalone: true, selector: "dd-speaker-bubble-neobrutal-slab", inputs: { color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, tail: { classPropertyName: "tail", publicName: "tail", isSignal: true, isRequired: false, transformFunction: null }, target: { classPropertyName: "target", publicName: "target", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\n class=\"dd-speaker-bubble-neo-slab\"\n [attr.data-tail]=\"resolvedTail()\"\n [ngStyle]=\"bubbleStyle()\"\n>\n <svg\n class=\"dd-speaker-bubble-neo-slab__shape\"\n aria-hidden=\"true\"\n [ngStyle]=\"shapeStyle()\"\n [attr.viewBox]=\"shapeViewBox()\"\n preserveAspectRatio=\"none\"\n focusable=\"false\"\n >\n <path\n class=\"dd-speaker-bubble-neo-slab__shape-path\"\n [attr.d]=\"shapePath()\"\n />\n </svg>\n <span class=\"dd-speaker-bubble-neo-slab__pin\" aria-hidden=\"true\"></span>\n <span class=\"dd-speaker-bubble-neo-slab__corner\" aria-hidden=\"true\"></span>\n <div class=\"dd-speaker-bubble-neo-slab__content\">\n <ng-content />\n </div>\n</div>\n", styles: [":host{display:block;width:fit-content;max-width:min(100%,38rem)}.dd-speaker-bubble-neo-slab{position:relative;isolation:isolate;overflow:visible;padding:28px 22px 18px;color:var(--dd-speaker-text)}.dd-speaker-bubble-neo-slab__shape{position:absolute;inset:0;z-index:0;pointer-events:none}.dd-speaker-bubble-neo-slab__shape-path{fill:var(--dd-speaker-surface);stroke:var(--dd-speaker-border);stroke-width:4;stroke-linecap:square;stroke-linejoin:miter;filter:drop-shadow(8px 8px 0 var(--dd-speaker-shadow))}.dd-speaker-bubble-neo-slab__pin{position:absolute;top:-16px;left:18px;width:46px;height:18px;border:4px solid var(--dd-speaker-border);background:var(--dd-speaker-accent);box-shadow:4px 4px 0 var(--dd-speaker-border);transform:rotate(-4deg)}.dd-speaker-bubble-neo-slab__corner{position:absolute;top:0;right:0;width:24px;height:24px;border-left:4px solid var(--dd-speaker-border);border-bottom:4px solid var(--dd-speaker-border);background:color-mix(in srgb,var(--dd-speaker-accent) 74%,white)}.dd-speaker-bubble-neo-slab[data-tail=right] .dd-speaker-bubble-neo-slab__pin{right:18px;left:auto;transform:rotate(4deg)}.dd-speaker-bubble-neo-slab[data-tail=right] .dd-speaker-bubble-neo-slab__corner{right:auto;left:0;border-right:4px solid var(--dd-speaker-border);border-left:0}.dd-speaker-bubble-neo-slab__content{position:relative;z-index:1;font-size:15px;font-weight:800;line-height:1.55;background:linear-gradient(135deg,color-mix(in srgb,var(--dd-speaker-accent) 28%,transparent) 0 18px,transparent 18px 100%),linear-gradient(180deg,color-mix(in srgb,var(--dd-speaker-surface-muted) 84%,var(--dd-speaker-surface)) 0,var(--dd-speaker-surface) 100%)}.dd-speaker-bubble-neo-slab__content :first-child{margin-top:0}.dd-speaker-bubble-neo-slab__content :last-child{margin-bottom:0}.dd-speaker-bubble-neo-slab__content strong{color:var(--dd-speaker-accent)}.dd-speaker-bubble-neo-slab__content small{display:inline-flex;align-items:center;gap:8px;margin-bottom:10px;padding:6px 10px 5px;border:3px solid var(--dd-speaker-border);background:color-mix(in srgb,var(--dd-speaker-accent) 20%,var(--dd-speaker-surface));box-shadow:3px 3px 0 var(--dd-speaker-shadow);color:var(--dd-speaker-text);font-size:11px;font-weight:1000;letter-spacing:.12em;line-height:1;text-transform:uppercase;white-space:nowrap}.dd-speaker-bubble-neo-slab__content small:before{content:\"\";width:10px;height:10px;flex:0 0 auto;border:3px solid var(--dd-speaker-border);background:var(--dd-speaker-accent)}.dd-speaker-bubble-neo-slab[data-tail=right] .dd-speaker-bubble-neo-slab__content{background:linear-gradient(225deg,color-mix(in srgb,var(--dd-speaker-accent) 28%,transparent) 0 18px,transparent 18px 100%),linear-gradient(180deg,color-mix(in srgb,var(--dd-speaker-surface-muted) 84%,var(--dd-speaker-surface)) 0,var(--dd-speaker-surface) 100%)}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
5398
+ }
5399
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: DuckDevSpeakerBubbleNeobrutalSlab, decorators: [{
5400
+ type: Component,
5401
+ args: [{ selector: 'dd-speaker-bubble-neobrutal-slab', standalone: true, imports: [NgStyle], template: "<div\n class=\"dd-speaker-bubble-neo-slab\"\n [attr.data-tail]=\"resolvedTail()\"\n [ngStyle]=\"bubbleStyle()\"\n>\n <svg\n class=\"dd-speaker-bubble-neo-slab__shape\"\n aria-hidden=\"true\"\n [ngStyle]=\"shapeStyle()\"\n [attr.viewBox]=\"shapeViewBox()\"\n preserveAspectRatio=\"none\"\n focusable=\"false\"\n >\n <path\n class=\"dd-speaker-bubble-neo-slab__shape-path\"\n [attr.d]=\"shapePath()\"\n />\n </svg>\n <span class=\"dd-speaker-bubble-neo-slab__pin\" aria-hidden=\"true\"></span>\n <span class=\"dd-speaker-bubble-neo-slab__corner\" aria-hidden=\"true\"></span>\n <div class=\"dd-speaker-bubble-neo-slab__content\">\n <ng-content />\n </div>\n</div>\n", styles: [":host{display:block;width:fit-content;max-width:min(100%,38rem)}.dd-speaker-bubble-neo-slab{position:relative;isolation:isolate;overflow:visible;padding:28px 22px 18px;color:var(--dd-speaker-text)}.dd-speaker-bubble-neo-slab__shape{position:absolute;inset:0;z-index:0;pointer-events:none}.dd-speaker-bubble-neo-slab__shape-path{fill:var(--dd-speaker-surface);stroke:var(--dd-speaker-border);stroke-width:4;stroke-linecap:square;stroke-linejoin:miter;filter:drop-shadow(8px 8px 0 var(--dd-speaker-shadow))}.dd-speaker-bubble-neo-slab__pin{position:absolute;top:-16px;left:18px;width:46px;height:18px;border:4px solid var(--dd-speaker-border);background:var(--dd-speaker-accent);box-shadow:4px 4px 0 var(--dd-speaker-border);transform:rotate(-4deg)}.dd-speaker-bubble-neo-slab__corner{position:absolute;top:0;right:0;width:24px;height:24px;border-left:4px solid var(--dd-speaker-border);border-bottom:4px solid var(--dd-speaker-border);background:color-mix(in srgb,var(--dd-speaker-accent) 74%,white)}.dd-speaker-bubble-neo-slab[data-tail=right] .dd-speaker-bubble-neo-slab__pin{right:18px;left:auto;transform:rotate(4deg)}.dd-speaker-bubble-neo-slab[data-tail=right] .dd-speaker-bubble-neo-slab__corner{right:auto;left:0;border-right:4px solid var(--dd-speaker-border);border-left:0}.dd-speaker-bubble-neo-slab__content{position:relative;z-index:1;font-size:15px;font-weight:800;line-height:1.55;background:linear-gradient(135deg,color-mix(in srgb,var(--dd-speaker-accent) 28%,transparent) 0 18px,transparent 18px 100%),linear-gradient(180deg,color-mix(in srgb,var(--dd-speaker-surface-muted) 84%,var(--dd-speaker-surface)) 0,var(--dd-speaker-surface) 100%)}.dd-speaker-bubble-neo-slab__content :first-child{margin-top:0}.dd-speaker-bubble-neo-slab__content :last-child{margin-bottom:0}.dd-speaker-bubble-neo-slab__content strong{color:var(--dd-speaker-accent)}.dd-speaker-bubble-neo-slab__content small{display:inline-flex;align-items:center;gap:8px;margin-bottom:10px;padding:6px 10px 5px;border:3px solid var(--dd-speaker-border);background:color-mix(in srgb,var(--dd-speaker-accent) 20%,var(--dd-speaker-surface));box-shadow:3px 3px 0 var(--dd-speaker-shadow);color:var(--dd-speaker-text);font-size:11px;font-weight:1000;letter-spacing:.12em;line-height:1;text-transform:uppercase;white-space:nowrap}.dd-speaker-bubble-neo-slab__content small:before{content:\"\";width:10px;height:10px;flex:0 0 auto;border:3px solid var(--dd-speaker-border);background:var(--dd-speaker-accent)}.dd-speaker-bubble-neo-slab[data-tail=right] .dd-speaker-bubble-neo-slab__content{background:linear-gradient(225deg,color-mix(in srgb,var(--dd-speaker-accent) 28%,transparent) 0 18px,transparent 18px 100%),linear-gradient(180deg,color-mix(in srgb,var(--dd-speaker-surface-muted) 84%,var(--dd-speaker-surface)) 0,var(--dd-speaker-surface) 100%)}\n"] }]
5402
+ }], ctorParameters: () => [], propDecorators: { color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], tail: [{ type: i0.Input, args: [{ isSignal: true, alias: "tail", required: false }] }], target: [{ type: i0.Input, args: [{ isSignal: true, alias: "target", required: false }] }] } });
5403
+
5404
+ const DEFAULT_BUBBLE_GEOMETRY = {
5405
+ side: 'left',
5406
+ style: {
5407
+ left: '0px',
5408
+ top: '0px',
5409
+ width: '1px',
5410
+ height: '1px',
5411
+ },
5412
+ viewBox: '0 0 1 1',
5413
+ path: '',
5414
+ };
5415
+ function clamp(value, min, max) {
5416
+ return Math.min(Math.max(value, min), max);
5417
+ }
5418
+ function serializePoint(point) {
5419
+ return `${point.x.toFixed(2)} ${point.y.toFixed(2)}`;
5420
+ }
5421
+ function closestPointOnRect(rect, point) {
5422
+ return {
5423
+ x: clamp(point.x, rect.left, rect.right),
5424
+ y: clamp(point.y, rect.top, rect.bottom),
5425
+ };
5426
+ }
5427
+ function resolveTargetElement(source, hostElement, documentRef) {
5428
+ if (!source) {
5429
+ return null;
5430
+ }
5431
+ if (source instanceof Element) {
5432
+ return source;
5433
+ }
5434
+ try {
5435
+ const localMatch = hostElement.parentElement?.querySelector(source);
5436
+ if (localMatch) {
5437
+ return localMatch;
5438
+ }
5439
+ return documentRef.querySelector(source);
5440
+ }
5441
+ catch {
5442
+ return null;
5443
+ }
5444
+ }
5445
+ function getBubbleElement(hostElement) {
5446
+ return hostElement.firstElementChild instanceof HTMLElement ? hostElement.firstElementChild : null;
5447
+ }
5448
+ function createUnifiedBubblePath(width, height, radius, baseStartX, baseEndX, tipX, tipY, offsetX, offsetY) {
5449
+ const left = offsetX;
5450
+ const top = offsetY;
5451
+ const right = offsetX + width;
5452
+ const bottom = offsetY + height;
5453
+ const start = { x: left + radius, y: top };
5454
+ const bottomRight = { x: right, y: bottom - radius };
5455
+ const bottomRightArcEnd = { x: right - radius, y: bottom };
5456
+ const baseStart = { x: offsetX + baseStartX, y: bottom };
5457
+ const baseEnd = { x: offsetX + baseEndX, y: bottom };
5458
+ const tip = { x: offsetX + tipX, y: offsetY + tipY };
5459
+ const bottomLeftArcStart = { x: left + radius, y: bottom };
5460
+ const leftBottom = { x: left, y: bottom - radius };
5461
+ const leftTop = { x: left, y: top + radius };
5462
+ return [
5463
+ `M ${serializePoint(start)}`,
5464
+ `H ${(right - radius).toFixed(2)}`,
5465
+ `A ${radius} ${radius} 0 0 1 ${right.toFixed(2)} ${(top + radius).toFixed(2)}`,
5466
+ `V ${bottomRight.y.toFixed(2)}`,
5467
+ `A ${radius} ${radius} 0 0 1 ${serializePoint(bottomRightArcEnd)}`,
5468
+ `H ${baseEnd.x.toFixed(2)}`,
5469
+ `L ${serializePoint(tip)}`,
5470
+ `L ${serializePoint(baseStart)}`,
5471
+ `H ${bottomLeftArcStart.x.toFixed(2)}`,
5472
+ `A ${radius} ${radius} 0 0 1 ${serializePoint(leftBottom)}`,
5473
+ `V ${leftTop.y.toFixed(2)}`,
5474
+ `A ${radius} ${radius} 0 0 1 ${serializePoint(start)}`,
5475
+ 'Z',
5476
+ ].join(' ');
5477
+ }
5478
+ class DuckDevSpeakerBubbleNeobrutalTicket {
5479
+ color = input(AccentEnumColor.Dark, { ...(ngDevMode ? { debugName: "color" } : {}) });
5480
+ tail = input('left', { ...(ngDevMode ? { debugName: "tail" } : {}) });
5481
+ target = input(null, { ...(ngDevMode ? { debugName: "target" } : {}) });
5482
+ hostRef = inject((ElementRef));
5483
+ documentRef = inject(DOCUMENT);
5484
+ destroyRef = inject(DestroyRef);
5485
+ platformId = inject(PLATFORM_ID);
5486
+ isBrowser = isPlatformBrowser(this.platformId);
5487
+ bubbleGeometry = signal(DEFAULT_BUBBLE_GEOMETRY, { ...(ngDevMode ? { debugName: "bubbleGeometry" } : {}) });
5488
+ animationFrameId = -1;
5489
+ resizeObserver = null;
5490
+ observedTarget = null;
5491
+ observersInitialized = false;
5492
+ bubbleStyle = computed(() => getNeobrutalSpeakerBubbleStyle(this.color()), { ...(ngDevMode ? { debugName: "bubbleStyle" } : {}) });
5493
+ resolvedTail = computed(() => this.bubbleGeometry().side, { ...(ngDevMode ? { debugName: "resolvedTail" } : {}) });
5494
+ shapeStyle = computed(() => this.bubbleGeometry().style, { ...(ngDevMode ? { debugName: "shapeStyle" } : {}) });
5495
+ shapeViewBox = computed(() => this.bubbleGeometry().viewBox, { ...(ngDevMode ? { debugName: "shapeViewBox" } : {}) });
5496
+ shapePath = computed(() => this.bubbleGeometry().path, { ...(ngDevMode ? { debugName: "shapePath" } : {}) });
5497
+ constructor() {
5498
+ afterNextRender(() => {
5499
+ this.setupObservers();
5500
+ this.scheduleRefresh();
5501
+ });
5502
+ afterRenderEffect(() => {
5503
+ this.tail();
5504
+ this.target();
5505
+ this.setupObservers();
5506
+ this.scheduleRefresh();
5507
+ });
5508
+ this.destroyRef.onDestroy(() => {
5509
+ this.documentRef.defaultView?.removeEventListener('resize', this.scheduleRefresh);
5510
+ this.documentRef.removeEventListener('scroll', this.scheduleRefresh, true);
5511
+ if (this.animationFrameId !== -1) {
5512
+ cancelAnimationFrame(this.animationFrameId);
5513
+ }
5514
+ this.resizeObserver?.disconnect();
5515
+ this.resizeObserver = null;
5516
+ this.observedTarget = null;
5517
+ });
5518
+ }
5519
+ scheduleRefresh = () => {
5520
+ if (!this.isBrowser || this.animationFrameId !== -1) {
5521
+ return;
5522
+ }
5523
+ this.animationFrameId = requestAnimationFrame(() => {
5524
+ this.animationFrameId = -1;
5525
+ this.refreshShape();
5526
+ });
5527
+ };
5528
+ setupObservers() {
5529
+ if (!this.isBrowser || this.observersInitialized) {
5530
+ return;
5531
+ }
5532
+ const bubbleElement = getBubbleElement(this.hostRef.nativeElement);
5533
+ if (!bubbleElement) {
5534
+ return;
5535
+ }
5536
+ if (typeof ResizeObserver !== 'undefined') {
5537
+ this.resizeObserver = new ResizeObserver(() => this.scheduleRefresh());
5538
+ this.resizeObserver.observe(bubbleElement);
5539
+ }
5540
+ const targetElement = resolveTargetElement(this.target(), this.hostRef.nativeElement, this.documentRef);
5541
+ if (targetElement) {
5542
+ this.resizeObserver?.observe(targetElement);
5543
+ this.observedTarget = targetElement;
5544
+ }
5545
+ this.documentRef.defaultView?.addEventListener('resize', this.scheduleRefresh);
5546
+ this.documentRef.addEventListener('scroll', this.scheduleRefresh, true);
5547
+ this.observersInitialized = true;
5548
+ }
5549
+ refreshShape() {
5550
+ if (!this.isBrowser) {
5551
+ return;
5552
+ }
5553
+ const bubbleElement = getBubbleElement(this.hostRef.nativeElement);
5554
+ if (!bubbleElement) {
5555
+ return;
5556
+ }
5557
+ const targetElement = resolveTargetElement(this.target(), this.hostRef.nativeElement, this.documentRef);
5558
+ if (this.resizeObserver && targetElement !== this.observedTarget) {
5559
+ if (this.observedTarget) {
5560
+ this.resizeObserver.unobserve(this.observedTarget);
5561
+ }
5562
+ if (targetElement) {
5563
+ this.resizeObserver.observe(targetElement);
5564
+ }
5565
+ this.observedTarget = targetElement;
5566
+ }
5567
+ const bubbleRect = bubbleElement.getBoundingClientRect();
5568
+ const targetRect = targetElement?.getBoundingClientRect() ?? null;
5569
+ const side = this.resolveTailSide(bubbleRect, targetRect);
5570
+ const seventh = bubbleRect.width / 7;
5571
+ const baseStartX = side === 'left'
5572
+ ? clamp(seventh, 26, bubbleRect.width - 72)
5573
+ : clamp(bubbleRect.width - seventh * 2, 26, bubbleRect.width - 72);
5574
+ const baseEndX = side === 'left'
5575
+ ? clamp(seventh * 2, baseStartX + 24, bubbleRect.width - 26)
5576
+ : clamp(bubbleRect.width - seventh, baseStartX + 24, bubbleRect.width - 26);
5577
+ const anchor = {
5578
+ x: bubbleRect.left + (baseStartX + baseEndX) / 2,
5579
+ y: bubbleRect.bottom,
5580
+ };
5581
+ const targetPoint = targetRect
5582
+ ? closestPointOnRect(targetRect, anchor)
5583
+ : {
5584
+ x: bubbleRect.left + (side === 'left' ? baseStartX : baseEndX),
5585
+ y: bubbleRect.bottom + Math.max(28, bubbleRect.height / 4),
5586
+ };
5587
+ const tipX = clamp(targetPoint.x - bubbleRect.left, -56, bubbleRect.width + 56);
5588
+ const tipY = Math.max(targetPoint.y - bubbleRect.top, bubbleRect.height + 24);
5589
+ const minX = Math.min(0, tipX);
5590
+ const maxX = Math.max(bubbleRect.width, tipX);
5591
+ const maxY = Math.max(bubbleRect.height, tipY);
5592
+ const padding = 12;
5593
+ const offsetX = padding - minX;
5594
+ const offsetY = padding;
5595
+ const width = maxX - minX + padding * 2;
5596
+ const height = maxY + padding * 2;
5597
+ this.bubbleGeometry.set({
5598
+ side,
5599
+ style: {
5600
+ left: `${minX - padding}px`,
5601
+ top: `${-padding}px`,
5602
+ width: `${width}px`,
5603
+ height: `${height}px`,
5604
+ },
5605
+ viewBox: `0 0 ${width.toFixed(2)} ${height.toFixed(2)}`,
5606
+ path: createUnifiedBubblePath(bubbleRect.width, bubbleRect.height, 6, baseStartX, baseEndX, tipX, tipY, offsetX, offsetY),
5607
+ });
5608
+ }
5609
+ resolveTailSide(bubbleRect, targetRect) {
5610
+ const tail = this.tail();
5611
+ if (tail === 'left' || tail === 'right') {
5612
+ return tail;
5613
+ }
5614
+ const targetCenterX = targetRect
5615
+ ? targetRect.left + targetRect.width / 2
5616
+ : bubbleRect.left + bubbleRect.width / 2;
5617
+ return targetCenterX < bubbleRect.left + bubbleRect.width / 2 ? 'left' : 'right';
5618
+ }
5619
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: DuckDevSpeakerBubbleNeobrutalTicket, deps: [], target: i0.ɵɵFactoryTarget.Component });
5620
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.1", type: DuckDevSpeakerBubbleNeobrutalTicket, isStandalone: true, selector: "dd-speaker-bubble-neobrutal-ticket", inputs: { color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, tail: { classPropertyName: "tail", publicName: "tail", isSignal: true, isRequired: false, transformFunction: null }, target: { classPropertyName: "target", publicName: "target", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\n class=\"dd-speaker-bubble-neo-ticket\"\n [attr.data-tail]=\"resolvedTail()\"\n [ngStyle]=\"bubbleStyle()\"\n>\n <svg\n class=\"dd-speaker-bubble-neo-ticket__shape\"\n aria-hidden=\"true\"\n [ngStyle]=\"shapeStyle()\"\n [attr.viewBox]=\"shapeViewBox()\"\n preserveAspectRatio=\"none\"\n focusable=\"false\"\n >\n <path\n class=\"dd-speaker-bubble-neo-ticket__shape-path\"\n [attr.d]=\"shapePath()\"\n />\n </svg>\n\n <div class=\"dd-speaker-bubble-neo-ticket__shell\">\n <div class=\"dd-speaker-bubble-neo-ticket__body\">\n <span class=\"dd-speaker-bubble-neo-ticket__flash\" aria-hidden=\"true\"></span>\n\n <div class=\"dd-speaker-bubble-neo-ticket__content\">\n <ng-content />\n </div>\n </div>\n\n <span class=\"dd-speaker-bubble-neo-ticket__stub\" aria-hidden=\"true\">\n <span></span>\n <span></span>\n <span></span>\n </span>\n </div>\n</div>\n", styles: [":host{display:block;width:fit-content;max-width:min(100%,40rem)}.dd-speaker-bubble-neo-ticket{position:relative;isolation:isolate;overflow:visible;color:var(--dd-speaker-text)}.dd-speaker-bubble-neo-ticket__shape{position:absolute;inset:0;z-index:0;pointer-events:none}.dd-speaker-bubble-neo-ticket__shape-path{fill:var(--dd-speaker-surface);stroke:var(--dd-speaker-border);stroke-width:4;stroke-linecap:square;stroke-linejoin:miter;filter:drop-shadow(10px 10px 0 var(--dd-speaker-shadow))}.dd-speaker-bubble-neo-ticket__shell{position:relative;z-index:1;display:grid;grid-template-columns:minmax(0,1fr) 58px;grid-template-areas:\"body stub\";padding:4px}.dd-speaker-bubble-neo-ticket[data-tail=right] .dd-speaker-bubble-neo-ticket__shell{grid-template-columns:58px minmax(0,1fr);grid-template-areas:\"stub body\"}.dd-speaker-bubble-neo-ticket__body{grid-area:body;position:relative;padding:22px 22px 18px;background:linear-gradient(135deg,color-mix(in srgb,var(--dd-speaker-accent) 20%,transparent) 0 16px,transparent 16px 100%),repeating-linear-gradient(90deg,transparent 0 14px,color-mix(in srgb,var(--dd-speaker-border) 8%,transparent) 14px 16px),color-mix(in srgb,var(--dd-speaker-surface-muted) 78%,var(--dd-speaker-surface))}.dd-speaker-bubble-neo-ticket__body:before,.dd-speaker-bubble-neo-ticket__body:after{content:\"\";position:absolute;top:18px;right:-18px;width:28px;height:28px;border:4px solid var(--dd-speaker-border);border-radius:999px;background:var(--dd-speaker-surface)}.dd-speaker-bubble-neo-ticket__body:after{top:auto;bottom:18px}.dd-speaker-bubble-neo-ticket[data-tail=right] .dd-speaker-bubble-neo-ticket__body:before,.dd-speaker-bubble-neo-ticket[data-tail=right] .dd-speaker-bubble-neo-ticket__body:after{right:auto;left:-18px}.dd-speaker-bubble-neo-ticket__flash{position:absolute;top:14px;left:18px;width:30px;height:12px;border:3px solid var(--dd-speaker-border);background:var(--dd-speaker-accent);box-shadow:4px 4px 0 var(--dd-speaker-shadow);transform:rotate(-7deg)}.dd-speaker-bubble-neo-ticket[data-tail=right] .dd-speaker-bubble-neo-ticket__flash{left:auto;right:18px;transform:rotate(7deg)}.dd-speaker-bubble-neo-ticket__content{position:relative;z-index:1;padding-top:18px;font-size:15px;font-weight:800;line-height:1.55}.dd-speaker-bubble-neo-ticket__content :first-child{margin-top:0}.dd-speaker-bubble-neo-ticket__content :last-child{margin-bottom:0}.dd-speaker-bubble-neo-ticket__content strong{color:var(--dd-speaker-accent)}.dd-speaker-bubble-neo-ticket__content small{display:inline-flex;margin-bottom:10px;padding:5px 8px 4px;border:3px solid var(--dd-speaker-border);background:var(--dd-speaker-accent);color:var(--dd-speaker-border);font-size:11px;font-weight:1000;letter-spacing:.14em;line-height:1;text-transform:uppercase;white-space:nowrap}.dd-speaker-bubble-neo-ticket__stub{grid-area:stub;display:grid;align-content:center;justify-items:center;gap:10px;padding:16px 8px;border-left:4px dashed var(--dd-speaker-border);background:color-mix(in srgb,var(--dd-speaker-accent) 70%,var(--dd-speaker-surface))}.dd-speaker-bubble-neo-ticket[data-tail=right] .dd-speaker-bubble-neo-ticket__stub{border-right:4px dashed var(--dd-speaker-border);border-left:0}.dd-speaker-bubble-neo-ticket__stub span{width:18px;height:18px;border:4px solid var(--dd-speaker-border);border-radius:999px;background:color-mix(in srgb,var(--dd-speaker-surface) 80%,white)}@media(max-width:640px){.dd-speaker-bubble-neo-ticket__shape-path{filter:drop-shadow(8px 8px 0 var(--dd-speaker-shadow))}.dd-speaker-bubble-neo-ticket__shell,.dd-speaker-bubble-neo-ticket[data-tail=right] .dd-speaker-bubble-neo-ticket__shell{grid-template-columns:1fr;grid-template-areas:\"body\" \"stub\"}.dd-speaker-bubble-neo-ticket__body:before,.dd-speaker-bubble-neo-ticket__body:after,.dd-speaker-bubble-neo-ticket[data-tail=right] .dd-speaker-bubble-neo-ticket__body:before,.dd-speaker-bubble-neo-ticket[data-tail=right] .dd-speaker-bubble-neo-ticket__body:after{inset:auto auto -18px 22px;width:24px;height:24px}.dd-speaker-bubble-neo-ticket__body:after,.dd-speaker-bubble-neo-ticket[data-tail=right] .dd-speaker-bubble-neo-ticket__body:after{left:auto;right:22px}.dd-speaker-bubble-neo-ticket__stub,.dd-speaker-bubble-neo-ticket[data-tail=right] .dd-speaker-bubble-neo-ticket__stub{grid-template-columns:repeat(3,minmax(0,1fr));gap:0;padding:12px 14px;border-top:4px dashed var(--dd-speaker-border);border-right:0;border-left:0}}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
5621
+ }
5622
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: DuckDevSpeakerBubbleNeobrutalTicket, decorators: [{
5623
+ type: Component,
5624
+ args: [{ selector: 'dd-speaker-bubble-neobrutal-ticket', standalone: true, imports: [NgStyle], template: "<div\n class=\"dd-speaker-bubble-neo-ticket\"\n [attr.data-tail]=\"resolvedTail()\"\n [ngStyle]=\"bubbleStyle()\"\n>\n <svg\n class=\"dd-speaker-bubble-neo-ticket__shape\"\n aria-hidden=\"true\"\n [ngStyle]=\"shapeStyle()\"\n [attr.viewBox]=\"shapeViewBox()\"\n preserveAspectRatio=\"none\"\n focusable=\"false\"\n >\n <path\n class=\"dd-speaker-bubble-neo-ticket__shape-path\"\n [attr.d]=\"shapePath()\"\n />\n </svg>\n\n <div class=\"dd-speaker-bubble-neo-ticket__shell\">\n <div class=\"dd-speaker-bubble-neo-ticket__body\">\n <span class=\"dd-speaker-bubble-neo-ticket__flash\" aria-hidden=\"true\"></span>\n\n <div class=\"dd-speaker-bubble-neo-ticket__content\">\n <ng-content />\n </div>\n </div>\n\n <span class=\"dd-speaker-bubble-neo-ticket__stub\" aria-hidden=\"true\">\n <span></span>\n <span></span>\n <span></span>\n </span>\n </div>\n</div>\n", styles: [":host{display:block;width:fit-content;max-width:min(100%,40rem)}.dd-speaker-bubble-neo-ticket{position:relative;isolation:isolate;overflow:visible;color:var(--dd-speaker-text)}.dd-speaker-bubble-neo-ticket__shape{position:absolute;inset:0;z-index:0;pointer-events:none}.dd-speaker-bubble-neo-ticket__shape-path{fill:var(--dd-speaker-surface);stroke:var(--dd-speaker-border);stroke-width:4;stroke-linecap:square;stroke-linejoin:miter;filter:drop-shadow(10px 10px 0 var(--dd-speaker-shadow))}.dd-speaker-bubble-neo-ticket__shell{position:relative;z-index:1;display:grid;grid-template-columns:minmax(0,1fr) 58px;grid-template-areas:\"body stub\";padding:4px}.dd-speaker-bubble-neo-ticket[data-tail=right] .dd-speaker-bubble-neo-ticket__shell{grid-template-columns:58px minmax(0,1fr);grid-template-areas:\"stub body\"}.dd-speaker-bubble-neo-ticket__body{grid-area:body;position:relative;padding:22px 22px 18px;background:linear-gradient(135deg,color-mix(in srgb,var(--dd-speaker-accent) 20%,transparent) 0 16px,transparent 16px 100%),repeating-linear-gradient(90deg,transparent 0 14px,color-mix(in srgb,var(--dd-speaker-border) 8%,transparent) 14px 16px),color-mix(in srgb,var(--dd-speaker-surface-muted) 78%,var(--dd-speaker-surface))}.dd-speaker-bubble-neo-ticket__body:before,.dd-speaker-bubble-neo-ticket__body:after{content:\"\";position:absolute;top:18px;right:-18px;width:28px;height:28px;border:4px solid var(--dd-speaker-border);border-radius:999px;background:var(--dd-speaker-surface)}.dd-speaker-bubble-neo-ticket__body:after{top:auto;bottom:18px}.dd-speaker-bubble-neo-ticket[data-tail=right] .dd-speaker-bubble-neo-ticket__body:before,.dd-speaker-bubble-neo-ticket[data-tail=right] .dd-speaker-bubble-neo-ticket__body:after{right:auto;left:-18px}.dd-speaker-bubble-neo-ticket__flash{position:absolute;top:14px;left:18px;width:30px;height:12px;border:3px solid var(--dd-speaker-border);background:var(--dd-speaker-accent);box-shadow:4px 4px 0 var(--dd-speaker-shadow);transform:rotate(-7deg)}.dd-speaker-bubble-neo-ticket[data-tail=right] .dd-speaker-bubble-neo-ticket__flash{left:auto;right:18px;transform:rotate(7deg)}.dd-speaker-bubble-neo-ticket__content{position:relative;z-index:1;padding-top:18px;font-size:15px;font-weight:800;line-height:1.55}.dd-speaker-bubble-neo-ticket__content :first-child{margin-top:0}.dd-speaker-bubble-neo-ticket__content :last-child{margin-bottom:0}.dd-speaker-bubble-neo-ticket__content strong{color:var(--dd-speaker-accent)}.dd-speaker-bubble-neo-ticket__content small{display:inline-flex;margin-bottom:10px;padding:5px 8px 4px;border:3px solid var(--dd-speaker-border);background:var(--dd-speaker-accent);color:var(--dd-speaker-border);font-size:11px;font-weight:1000;letter-spacing:.14em;line-height:1;text-transform:uppercase;white-space:nowrap}.dd-speaker-bubble-neo-ticket__stub{grid-area:stub;display:grid;align-content:center;justify-items:center;gap:10px;padding:16px 8px;border-left:4px dashed var(--dd-speaker-border);background:color-mix(in srgb,var(--dd-speaker-accent) 70%,var(--dd-speaker-surface))}.dd-speaker-bubble-neo-ticket[data-tail=right] .dd-speaker-bubble-neo-ticket__stub{border-right:4px dashed var(--dd-speaker-border);border-left:0}.dd-speaker-bubble-neo-ticket__stub span{width:18px;height:18px;border:4px solid var(--dd-speaker-border);border-radius:999px;background:color-mix(in srgb,var(--dd-speaker-surface) 80%,white)}@media(max-width:640px){.dd-speaker-bubble-neo-ticket__shape-path{filter:drop-shadow(8px 8px 0 var(--dd-speaker-shadow))}.dd-speaker-bubble-neo-ticket__shell,.dd-speaker-bubble-neo-ticket[data-tail=right] .dd-speaker-bubble-neo-ticket__shell{grid-template-columns:1fr;grid-template-areas:\"body\" \"stub\"}.dd-speaker-bubble-neo-ticket__body:before,.dd-speaker-bubble-neo-ticket__body:after,.dd-speaker-bubble-neo-ticket[data-tail=right] .dd-speaker-bubble-neo-ticket__body:before,.dd-speaker-bubble-neo-ticket[data-tail=right] .dd-speaker-bubble-neo-ticket__body:after{inset:auto auto -18px 22px;width:24px;height:24px}.dd-speaker-bubble-neo-ticket__body:after,.dd-speaker-bubble-neo-ticket[data-tail=right] .dd-speaker-bubble-neo-ticket__body:after{left:auto;right:22px}.dd-speaker-bubble-neo-ticket__stub,.dd-speaker-bubble-neo-ticket[data-tail=right] .dd-speaker-bubble-neo-ticket__stub{grid-template-columns:repeat(3,minmax(0,1fr));gap:0;padding:12px 14px;border-top:4px dashed var(--dd-speaker-border);border-right:0;border-left:0}}\n"] }]
5625
+ }], ctorParameters: () => [], propDecorators: { color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], tail: [{ type: i0.Input, args: [{ isSignal: true, alias: "tail", required: false }] }], target: [{ type: i0.Input, args: [{ isSignal: true, alias: "target", required: false }] }] } });
5626
+
5627
+ class SpeakerBubbleBlock {
5628
+ t = inject(TranslocoService);
5629
+ colorViolet = AccentEnumColor.Violet;
5630
+ colorOrange = AccentEnumColor.Orange;
5631
+ colorWhite = AccentEnumColor.White;
5632
+ colorGray = AccentEnumColor.Gray;
5633
+ colorDark = AccentEnumColor.Dark;
5634
+ styleTabs = [
5635
+ { id: 'classic', label: this.t.translate('documentationStyleTabs.classic') },
5636
+ { id: 'neobrutalism', label: this.t.translate('documentationStyleTabs.neobrutalism') },
5637
+ ];
5638
+ activeStyleTab = signal(this.styleTabs[0], { ...(ngDevMode ? { debugName: "activeStyleTab" } : {}) });
5639
+ introEl;
5640
+ inputContentEl;
5641
+ inputColorEl;
5642
+ inputTailEl;
5643
+ constructor() {
5644
+ this.introEl = this.createEl(this.t.translate('speakerBubbleDoc.intro'));
5645
+ this.inputContentEl = this.createEl(this.t.translate('speakerBubbleDoc.inputsDesc.content'));
5646
+ this.inputColorEl = this.createEl(this.t.translate('speakerBubbleDoc.inputsDesc.color'));
5647
+ this.inputTailEl = this.createEl(this.t.translate('speakerBubbleDoc.inputsDesc.tail'));
5648
+ }
5649
+ onStyleTabChange(tab) {
5650
+ this.activeStyleTab.set(tab);
5651
+ }
5652
+ createEl(html) {
5653
+ const el = document.createElement('div');
5654
+ el.innerHTML = html;
5655
+ return el;
5656
+ }
5657
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: SpeakerBubbleBlock, deps: [], target: i0.ɵɵFactoryTarget.Component });
5658
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.1", type: SpeakerBubbleBlock, isStandalone: true, selector: "app-speaker-bubble-block", ngImport: i0, template: "<div class=\"demo-container\">\n <h1>{{ 'speakerBubbleDoc.title' | transloco }}</h1>\n\n <dd-card-accent [color]=\"colorWhite\">\n <div [innerHTML]=\"introEl.innerHTML\"></div>\n </dd-card-accent>\n\n <duck-dev-tab [tabs]=\"styleTabs\" (tabChange)=\"onStyleTabChange($event)\">\n @if (activeStyleTab().id === 'classic') {\n <dd-card-section>\n <h2>{{ 'speakerBubbleDoc.classic.bubbleTitle' | transloco }}</h2>\n <p class=\"description\">{{ 'speakerBubbleDoc.classic.bubbleDescription' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'speakerBubbleDoc.common.usage' | transloco }}</h3>\n <pre><code>&lt;dd-speaker-bubble-classic [color]=\"colorWhite\" [tail]=\"'left'\"&gt;\n &lt;small&gt;Product team&lt;/small&gt;\n &lt;p&gt;Can we move the onboarding review to Thursday?&lt;/p&gt;\n&lt;/dd-speaker-bubble-classic&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'speakerBubbleDoc.common.inputs' | transloco }}</h3>\n <ul>\n <li>\n <dd-card-accent [color]=\"colorWhite\">\n <div [innerHTML]=\"inputContentEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n <li>\n <dd-card-accent [color]=\"colorViolet\">\n <div [innerHTML]=\"inputColorEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n <li>\n <dd-card-accent [color]=\"colorOrange\">\n <div [innerHTML]=\"inputTailEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'speakerBubbleDoc.common.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'speakerBubbleDoc.labels.leftTail' | transloco }}</p>\n <div class=\"bubble-preview\">\n <dd-speaker-bubble-classic\n [color]=\"colorWhite\"\n [tail]=\"'left'\"\n [target]=\"classicLeftTarget\"\n >\n <small>Design sync</small>\n <p>Can we keep the hero copy shorter on mobile?</p>\n </dd-speaker-bubble-classic>\n <span class=\"bubble-target\" #classicLeftTarget aria-hidden=\"true\"></span>\n </div>\n </div>\n\n <div class=\"example-item example-item--right\">\n <p class=\"example-label\">{{ 'speakerBubbleDoc.labels.rightTail' | transloco }}</p>\n <div class=\"bubble-preview bubble-preview--end\">\n <dd-speaker-bubble-classic\n [color]=\"colorViolet\"\n [tail]=\"'right'\"\n [target]=\"classicRightTarget\"\n >\n <small>Frontend</small>\n <p><strong>Yes</strong>, the block can keep a CTA and badge inside projected content.</p>\n </dd-speaker-bubble-classic>\n <span\n class=\"bubble-target bubble-target--violet\"\n #classicRightTarget\n aria-hidden=\"true\"\n ></span>\n </div>\n </div>\n </div>\n </div>\n </dd-card-section>\n\n <dd-card-section>\n <h2>{{ 'speakerBubbleDoc.classic.softTitle' | transloco }}</h2>\n <p class=\"description\">{{ 'speakerBubbleDoc.classic.softDescription' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'speakerBubbleDoc.common.usage' | transloco }}</h3>\n <pre><code>&lt;dd-speaker-bubble-soft [color]=\"colorOrange\" [tail]=\"'right'\"&gt;\n &lt;small&gt;Assistant&lt;/small&gt;\n &lt;p&gt;Projected markup can include &lt;strong&gt;inline emphasis&lt;/strong&gt; and metadata.&lt;/p&gt;\n&lt;/dd-speaker-bubble-soft&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'speakerBubbleDoc.common.inputs' | transloco }}</h3>\n <ul>\n <li>\n <dd-card-accent [color]=\"colorWhite\">\n <div [innerHTML]=\"inputContentEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n <li>\n <dd-card-accent [color]=\"colorViolet\">\n <div [innerHTML]=\"inputColorEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n <li>\n <dd-card-accent [color]=\"colorOrange\">\n <div [innerHTML]=\"inputTailEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'speakerBubbleDoc.common.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'speakerBubbleDoc.labels.richContent' | transloco }}</p>\n <div class=\"bubble-preview\">\n <dd-speaker-bubble-soft\n [color]=\"colorOrange\"\n [tail]=\"'left'\"\n [target]=\"softLeftTarget\"\n >\n <small>Release note</small>\n <p>Bubble keeps a softer glassy surface for editorial comments and gentle callouts.</p>\n </dd-speaker-bubble-soft>\n <span\n class=\"bubble-target bubble-target--orange\"\n #softLeftTarget\n aria-hidden=\"true\"\n ></span>\n </div>\n </div>\n\n <div class=\"example-item example-item--right\">\n <p class=\"example-label\">{{ 'speakerBubbleDoc.labels.darkMode' | transloco }}</p>\n <div class=\"bubble-preview bubble-preview--end\">\n <dd-speaker-bubble-soft\n [color]=\"colorDark\"\n [tail]=\"'right'\"\n [target]=\"softRightTarget\"\n >\n <small>Night queue</small>\n <p>Rich content can stay readable even on dark palette variants.</p>\n </dd-speaker-bubble-soft>\n <span\n class=\"bubble-target bubble-target--dark\"\n #softRightTarget\n aria-hidden=\"true\"\n ></span>\n </div>\n </div>\n </div>\n </div>\n </dd-card-section>\n\n <dd-card-section>\n <h2>{{ 'speakerBubbleDoc.classic.outlineTitle' | transloco }}</h2>\n <p class=\"description\">{{ 'speakerBubbleDoc.classic.outlineDescription' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'speakerBubbleDoc.common.usage' | transloco }}</h3>\n <pre><code>&lt;dd-speaker-bubble-outline [color]=\"colorGray\" [tail]=\"'left'\"&gt;\n &lt;small&gt;System&lt;/small&gt;\n &lt;p&gt;Outline variants work well for neutral hints and documentation notes.&lt;/p&gt;\n&lt;/dd-speaker-bubble-outline&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'speakerBubbleDoc.common.inputs' | transloco }}</h3>\n <ul>\n <li>\n <dd-card-accent [color]=\"colorWhite\">\n <div [innerHTML]=\"inputContentEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n <li>\n <dd-card-accent [color]=\"colorViolet\">\n <div [innerHTML]=\"inputColorEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n <li>\n <dd-card-accent [color]=\"colorOrange\">\n <div [innerHTML]=\"inputTailEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'speakerBubbleDoc.common.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'speakerBubbleDoc.labels.note' | transloco }}</p>\n <div class=\"bubble-preview\">\n <dd-speaker-bubble-outline\n [color]=\"colorGray\"\n [tail]=\"'left'\"\n [target]=\"outlineLeftTarget\"\n >\n <small>Documentation</small>\n <p>Outlined speaker bubbles are useful for neutral side notes in dense layouts.</p>\n </dd-speaker-bubble-outline>\n <span class=\"bubble-target\" #outlineLeftTarget aria-hidden=\"true\"></span>\n </div>\n </div>\n\n <div class=\"example-item example-item--right\">\n <p class=\"example-label\">{{ 'speakerBubbleDoc.labels.replyRight' | transloco }}</p>\n <div class=\"bubble-preview bubble-preview--end\">\n <dd-speaker-bubble-outline\n [color]=\"colorWhite\"\n [tail]=\"'right'\"\n [target]=\"outlineRightTarget\"\n >\n <small>QA</small>\n <p>Tail position still flips while content remains projected markup.</p>\n </dd-speaker-bubble-outline>\n <span class=\"bubble-target\" #outlineRightTarget aria-hidden=\"true\"></span>\n </div>\n </div>\n </div>\n </div>\n </dd-card-section>\n } @else {\n <dd-card-section>\n <h2>{{ 'speakerBubbleDoc.neobrutal.slabTitle' | transloco }}</h2>\n <p class=\"description\">{{ 'speakerBubbleDoc.neobrutal.slabDescription' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'speakerBubbleDoc.common.usage' | transloco }}</h3>\n <pre><code>&lt;dd-speaker-bubble-neobrutal-slab [color]=\"colorOrange\" [tail]=\"'left'\"&gt;\n &lt;small&gt;Live drop&lt;/small&gt;\n &lt;p&gt;Use ng-content for bold labels, paragraphs and inline status chips.&lt;/p&gt;\n&lt;/dd-speaker-bubble-neobrutal-slab&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'speakerBubbleDoc.common.inputs' | transloco }}</h3>\n <ul>\n <li>\n <dd-card-accent [color]=\"colorWhite\">\n <div [innerHTML]=\"inputContentEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n <li>\n <dd-card-accent [color]=\"colorViolet\">\n <div [innerHTML]=\"inputColorEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n <li>\n <dd-card-accent [color]=\"colorOrange\">\n <div [innerHTML]=\"inputTailEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'speakerBubbleDoc.common.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item example-item--neobrutal\">\n <p class=\"example-label\">{{ 'speakerBubbleDoc.labels.livePanel' | transloco }}</p>\n <div class=\"bubble-preview\">\n <dd-speaker-bubble-neobrutal-slab\n [color]=\"colorOrange\"\n [tail]=\"'left'\"\n [target]=\"slabLeftTarget\"\n >\n <small>Queue A</small>\n <p><strong>Live</strong> release banner for dashboards, status walls and loud interface narration.</p>\n </dd-speaker-bubble-neobrutal-slab>\n <span\n class=\"bubble-target bubble-target--orange\"\n #slabLeftTarget\n aria-hidden=\"true\"\n ></span>\n </div>\n </div>\n\n <div class=\"example-item example-item--neobrutal example-item--right\">\n <p class=\"example-label\">{{ 'speakerBubbleDoc.labels.hotReply' | transloco }}</p>\n <div class=\"bubble-preview bubble-preview--end\">\n <dd-speaker-bubble-neobrutal-slab\n [color]=\"colorViolet\"\n [tail]=\"'right'\"\n [target]=\"slabRightTarget\"\n >\n <small>Ops</small>\n <p>The slab version keeps a heavy tail and rigid geometry for louder chat layouts.</p>\n </dd-speaker-bubble-neobrutal-slab>\n <span\n class=\"bubble-target bubble-target--violet\"\n #slabRightTarget\n aria-hidden=\"true\"\n ></span>\n </div>\n </div>\n </div>\n </div>\n </dd-card-section>\n\n <dd-card-section>\n <h2>{{ 'speakerBubbleDoc.neobrutal.ticketTitle' | transloco }}</h2>\n <p class=\"description\">{{ 'speakerBubbleDoc.neobrutal.ticketDescription' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'speakerBubbleDoc.common.usage' | transloco }}</h3>\n <pre><code>&lt;dd-speaker-bubble-neobrutal-ticket [color]=\"colorDark\" [tail]=\"'right'\"&gt;\n &lt;small&gt;Alert feed&lt;/small&gt;\n &lt;p&gt;Projected content stays flexible while the component provides the ticket shell.&lt;/p&gt;\n&lt;/dd-speaker-bubble-neobrutal-ticket&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'speakerBubbleDoc.common.inputs' | transloco }}</h3>\n <ul>\n <li>\n <dd-card-accent [color]=\"colorWhite\">\n <div [innerHTML]=\"inputContentEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n <li>\n <dd-card-accent [color]=\"colorViolet\">\n <div [innerHTML]=\"inputColorEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n <li>\n <dd-card-accent [color]=\"colorOrange\">\n <div [innerHTML]=\"inputTailEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'speakerBubbleDoc.common.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item example-item--neobrutal\">\n <p class=\"example-label\">{{ 'speakerBubbleDoc.labels.alertTicket' | transloco }}</p>\n <div class=\"bubble-preview\">\n <dd-speaker-bubble-neobrutal-ticket\n [color]=\"colorDark\"\n [tail]=\"'left'\"\n [target]=\"ticketLeftTarget\"\n >\n <small>Alert feed</small>\n <p>Ticket framing works for warning streams, operations chatter and serialized event logs.</p>\n </dd-speaker-bubble-neobrutal-ticket>\n <span\n class=\"bubble-target bubble-target--dark\"\n #ticketLeftTarget\n aria-hidden=\"true\"\n ></span>\n </div>\n </div>\n\n <div class=\"example-item example-item--neobrutal example-item--right\">\n <p class=\"example-label\">{{ 'speakerBubbleDoc.labels.ticketReply' | transloco }}</p>\n <div class=\"bubble-preview bubble-preview--end\">\n <dd-speaker-bubble-neobrutal-ticket\n [color]=\"colorWhite\"\n [tail]=\"'right'\"\n [target]=\"ticketRightTarget\"\n >\n <small>Review</small>\n <p><strong>Approved</strong> for launch preview, keep the counter-note visible in the timeline.</p>\n </dd-speaker-bubble-neobrutal-ticket>\n <span\n class=\"bubble-target bubble-target--orange\"\n #ticketRightTarget\n aria-hidden=\"true\"\n ></span>\n </div>\n </div>\n </div>\n </div>\n </dd-card-section>\n }\n </duck-dev-tab>\n</div>\n", styles: [".demo-container{max-width:1200px;margin:0 auto;padding:40px 20px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif}.demo-container h1{font-size:36px;font-weight:700;color:var(--dd-base-600);margin-bottom:30px;text-align:center;border-bottom:3px solid var(--dd-base-accent-blue);padding-bottom:20px}.demo-container h2{font-size:28px;font-weight:600;color:var(--dd-base-500);margin-bottom:15px;border-left:4px solid var(--dd-base-accent-blue);padding-left:15px}.demo-container .description{font-size:16px;line-height:1.6;color:var(--dd-base-400);margin-bottom:25px;padding:15px;background:var(--dd-base-100);border-radius:8px;border-left:3px solid var(--dd-base-300)}.demo-container h3{font-size:20px;font-weight:600;color:var(--dd-base-500);margin-bottom:15px;margin-top:25px}.demo-container .usage-block{margin-bottom:25px}.demo-container .usage-block pre{background:var(--dd-base-600);color:var(--dd-base-100);padding:20px;border-radius:8px;overflow-x:auto;margin:0}.demo-container .usage-block pre code{font-family:Courier New,Courier,monospace;font-size:14px;line-height:1.5}.demo-container .inputs-block{margin-bottom:25px}.demo-container .inputs-block ul{list-style:none;padding:0;margin:0}.demo-container .inputs-block ul li{margin-bottom:8px}.demo-container .examples-block .example-row{display:flex;gap:20px;margin-bottom:20px;flex-wrap:wrap}.demo-container .examples-block .example-item{flex:1;min-width:280px;padding:20px;background:var(--dd-base-100);border-radius:8px;border:2px solid var(--dd-base-300);display:flex;flex-direction:column;gap:15px;transition:all .3s ease}.demo-container .examples-block .example-item:hover{border-color:var(--dd-base-accent-blue);box-shadow:0 4px 12px var(--dd-base-300)}.demo-container .examples-block .example-item--right .example-label{text-align:right}.demo-container .examples-block .example-item--neobrutal{background:linear-gradient(135deg,color-mix(in srgb,var(--dd-base-accent-yellow) 24%,transparent) 0 15%,transparent 15% 100%),var(--dd-base-0);border:4px solid var(--dd-base-600);border-radius:0;box-shadow:8px 8px 0 var(--dd-base-accent-blue)}.demo-container .examples-block .example-item--neobrutal:hover{border-color:var(--dd-base-600);box-shadow:10px 10px 0 var(--dd-base-accent-orange)}.demo-container .examples-block .example-label{font-size:14px;font-weight:600;color:var(--dd-base-400);margin:0;text-align:left}.demo-container .bubble-preview{width:100%;display:flex;flex-direction:column;align-items:flex-start;gap:16px}.demo-container .bubble-preview--end{align-items:flex-end}.demo-container .bubble-target{position:relative;width:54px;height:54px;border:2px solid var(--dd-base-300);border-radius:18px;background:radial-gradient(circle at 34% 34%,var(--dd-base-0) 0 18%,transparent 18% 100%),linear-gradient(145deg,color-mix(in srgb,var(--dd-base-accent-blue) 16%,transparent) 0,transparent 52%),var(--dd-base-100);box-shadow:0 10px 18px color-mix(in srgb,var(--dd-base-400) 24%,transparent);flex:0 0 auto}.demo-container .bubble-target:before{content:\"\";position:absolute;inset:11px 13px 17px;border-radius:999px;background:color-mix(in srgb,var(--dd-base-accent-blue) 22%,var(--dd-base-0))}.demo-container .bubble-target:after{content:\"\";position:absolute;left:17px;right:17px;bottom:10px;height:10px;border-radius:999px;background:color-mix(in srgb,var(--dd-base-300) 85%,var(--dd-base-0))}.demo-container .bubble-target--violet{border-color:color-mix(in srgb,var(--dd-base-secondary) 42%,var(--dd-base-300));background:radial-gradient(circle at 34% 34%,var(--dd-base-0) 0 18%,transparent 18% 100%),linear-gradient(145deg,color-mix(in srgb,var(--dd-base-secondary) 18%,transparent) 0,transparent 52%),color-mix(in srgb,var(--dd-base-secondary) 10%,var(--dd-base-0))}.demo-container .bubble-target--orange{border-color:color-mix(in srgb,var(--dd-base-accent-orange) 46%,var(--dd-base-300));background:radial-gradient(circle at 34% 34%,var(--dd-base-0) 0 18%,transparent 18% 100%),linear-gradient(145deg,color-mix(in srgb,var(--dd-base-accent-orange) 22%,transparent) 0,transparent 52%),color-mix(in srgb,var(--dd-base-accent-yellow) 18%,var(--dd-base-0))}.demo-container .bubble-target--dark{border-color:var(--dd-base-500);background:radial-gradient(circle at 34% 34%,color-mix(in srgb,var(--dd-base-0) 88%,transparent) 0 18%,transparent 18% 100%),linear-gradient(145deg,color-mix(in srgb,var(--dd-base-accent-yellow) 16%,transparent) 0,transparent 52%),color-mix(in srgb,var(--dd-base-600) 92%,var(--dd-base-500))}.demo-container .bubble-target--dark:before{background:color-mix(in srgb,var(--dd-base-accent-yellow) 18%,var(--dd-base-0))}.demo-container .bubble-target--dark:after{background:color-mix(in srgb,var(--dd-base-400) 80%,var(--dd-base-600))}.demo-container .example-item--neobrutal .bubble-target{border-width:4px;border-color:var(--dd-base-600);border-radius:0;box-shadow:6px 6px 0 var(--dd-base-600)}@media(max-width:768px){.demo-container{padding:20px 15px}.demo-container h1{font-size:28px}.demo-container h2{font-size:24px}.demo-container .examples-block .example-row{flex-direction:column}}\n"], dependencies: [{ kind: "component", type: DuckDevCardAccent, selector: "dd-card-accent", inputs: ["color"] }, { kind: "component", type: DuckDevCardSection, selector: "dd-card-section" }, { kind: "component", type: DuckDevSpeakerBubbleClassic, selector: "dd-speaker-bubble-classic", inputs: ["color", "tail", "target"] }, { kind: "component", type: DuckDevSpeakerBubbleSoft, selector: "dd-speaker-bubble-soft", inputs: ["color", "tail", "target"] }, { kind: "component", type: DuckDevSpeakerBubbleOutline, selector: "dd-speaker-bubble-outline", inputs: ["color", "tail", "target"] }, { kind: "component", type: DuckDevSpeakerBubbleNeobrutalSlab, selector: "dd-speaker-bubble-neobrutal-slab", inputs: ["color", "tail", "target"] }, { kind: "component", type: DuckDevSpeakerBubbleNeobrutalTicket, selector: "dd-speaker-bubble-neobrutal-ticket", inputs: ["color", "tail", "target"] }, { kind: "component", type: DuckDevTab, selector: "duck-dev-tab", inputs: ["tabs"], outputs: ["tabChange"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }] });
5659
+ }
5660
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: SpeakerBubbleBlock, decorators: [{
5661
+ type: Component,
5662
+ args: [{ selector: 'app-speaker-bubble-block', standalone: true, imports: [
5663
+ TranslocoPipe,
5664
+ DuckDevCardAccent,
5665
+ DuckDevCardSection,
5666
+ DuckDevSpeakerBubbleClassic,
5667
+ DuckDevSpeakerBubbleSoft,
5668
+ DuckDevSpeakerBubbleOutline,
5669
+ DuckDevSpeakerBubbleNeobrutalSlab,
5670
+ DuckDevSpeakerBubbleNeobrutalTicket,
5671
+ DuckDevTab,
5672
+ ], template: "<div class=\"demo-container\">\n <h1>{{ 'speakerBubbleDoc.title' | transloco }}</h1>\n\n <dd-card-accent [color]=\"colorWhite\">\n <div [innerHTML]=\"introEl.innerHTML\"></div>\n </dd-card-accent>\n\n <duck-dev-tab [tabs]=\"styleTabs\" (tabChange)=\"onStyleTabChange($event)\">\n @if (activeStyleTab().id === 'classic') {\n <dd-card-section>\n <h2>{{ 'speakerBubbleDoc.classic.bubbleTitle' | transloco }}</h2>\n <p class=\"description\">{{ 'speakerBubbleDoc.classic.bubbleDescription' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'speakerBubbleDoc.common.usage' | transloco }}</h3>\n <pre><code>&lt;dd-speaker-bubble-classic [color]=\"colorWhite\" [tail]=\"'left'\"&gt;\n &lt;small&gt;Product team&lt;/small&gt;\n &lt;p&gt;Can we move the onboarding review to Thursday?&lt;/p&gt;\n&lt;/dd-speaker-bubble-classic&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'speakerBubbleDoc.common.inputs' | transloco }}</h3>\n <ul>\n <li>\n <dd-card-accent [color]=\"colorWhite\">\n <div [innerHTML]=\"inputContentEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n <li>\n <dd-card-accent [color]=\"colorViolet\">\n <div [innerHTML]=\"inputColorEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n <li>\n <dd-card-accent [color]=\"colorOrange\">\n <div [innerHTML]=\"inputTailEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'speakerBubbleDoc.common.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'speakerBubbleDoc.labels.leftTail' | transloco }}</p>\n <div class=\"bubble-preview\">\n <dd-speaker-bubble-classic\n [color]=\"colorWhite\"\n [tail]=\"'left'\"\n [target]=\"classicLeftTarget\"\n >\n <small>Design sync</small>\n <p>Can we keep the hero copy shorter on mobile?</p>\n </dd-speaker-bubble-classic>\n <span class=\"bubble-target\" #classicLeftTarget aria-hidden=\"true\"></span>\n </div>\n </div>\n\n <div class=\"example-item example-item--right\">\n <p class=\"example-label\">{{ 'speakerBubbleDoc.labels.rightTail' | transloco }}</p>\n <div class=\"bubble-preview bubble-preview--end\">\n <dd-speaker-bubble-classic\n [color]=\"colorViolet\"\n [tail]=\"'right'\"\n [target]=\"classicRightTarget\"\n >\n <small>Frontend</small>\n <p><strong>Yes</strong>, the block can keep a CTA and badge inside projected content.</p>\n </dd-speaker-bubble-classic>\n <span\n class=\"bubble-target bubble-target--violet\"\n #classicRightTarget\n aria-hidden=\"true\"\n ></span>\n </div>\n </div>\n </div>\n </div>\n </dd-card-section>\n\n <dd-card-section>\n <h2>{{ 'speakerBubbleDoc.classic.softTitle' | transloco }}</h2>\n <p class=\"description\">{{ 'speakerBubbleDoc.classic.softDescription' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'speakerBubbleDoc.common.usage' | transloco }}</h3>\n <pre><code>&lt;dd-speaker-bubble-soft [color]=\"colorOrange\" [tail]=\"'right'\"&gt;\n &lt;small&gt;Assistant&lt;/small&gt;\n &lt;p&gt;Projected markup can include &lt;strong&gt;inline emphasis&lt;/strong&gt; and metadata.&lt;/p&gt;\n&lt;/dd-speaker-bubble-soft&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'speakerBubbleDoc.common.inputs' | transloco }}</h3>\n <ul>\n <li>\n <dd-card-accent [color]=\"colorWhite\">\n <div [innerHTML]=\"inputContentEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n <li>\n <dd-card-accent [color]=\"colorViolet\">\n <div [innerHTML]=\"inputColorEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n <li>\n <dd-card-accent [color]=\"colorOrange\">\n <div [innerHTML]=\"inputTailEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'speakerBubbleDoc.common.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'speakerBubbleDoc.labels.richContent' | transloco }}</p>\n <div class=\"bubble-preview\">\n <dd-speaker-bubble-soft\n [color]=\"colorOrange\"\n [tail]=\"'left'\"\n [target]=\"softLeftTarget\"\n >\n <small>Release note</small>\n <p>Bubble keeps a softer glassy surface for editorial comments and gentle callouts.</p>\n </dd-speaker-bubble-soft>\n <span\n class=\"bubble-target bubble-target--orange\"\n #softLeftTarget\n aria-hidden=\"true\"\n ></span>\n </div>\n </div>\n\n <div class=\"example-item example-item--right\">\n <p class=\"example-label\">{{ 'speakerBubbleDoc.labels.darkMode' | transloco }}</p>\n <div class=\"bubble-preview bubble-preview--end\">\n <dd-speaker-bubble-soft\n [color]=\"colorDark\"\n [tail]=\"'right'\"\n [target]=\"softRightTarget\"\n >\n <small>Night queue</small>\n <p>Rich content can stay readable even on dark palette variants.</p>\n </dd-speaker-bubble-soft>\n <span\n class=\"bubble-target bubble-target--dark\"\n #softRightTarget\n aria-hidden=\"true\"\n ></span>\n </div>\n </div>\n </div>\n </div>\n </dd-card-section>\n\n <dd-card-section>\n <h2>{{ 'speakerBubbleDoc.classic.outlineTitle' | transloco }}</h2>\n <p class=\"description\">{{ 'speakerBubbleDoc.classic.outlineDescription' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'speakerBubbleDoc.common.usage' | transloco }}</h3>\n <pre><code>&lt;dd-speaker-bubble-outline [color]=\"colorGray\" [tail]=\"'left'\"&gt;\n &lt;small&gt;System&lt;/small&gt;\n &lt;p&gt;Outline variants work well for neutral hints and documentation notes.&lt;/p&gt;\n&lt;/dd-speaker-bubble-outline&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'speakerBubbleDoc.common.inputs' | transloco }}</h3>\n <ul>\n <li>\n <dd-card-accent [color]=\"colorWhite\">\n <div [innerHTML]=\"inputContentEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n <li>\n <dd-card-accent [color]=\"colorViolet\">\n <div [innerHTML]=\"inputColorEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n <li>\n <dd-card-accent [color]=\"colorOrange\">\n <div [innerHTML]=\"inputTailEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'speakerBubbleDoc.common.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item\">\n <p class=\"example-label\">{{ 'speakerBubbleDoc.labels.note' | transloco }}</p>\n <div class=\"bubble-preview\">\n <dd-speaker-bubble-outline\n [color]=\"colorGray\"\n [tail]=\"'left'\"\n [target]=\"outlineLeftTarget\"\n >\n <small>Documentation</small>\n <p>Outlined speaker bubbles are useful for neutral side notes in dense layouts.</p>\n </dd-speaker-bubble-outline>\n <span class=\"bubble-target\" #outlineLeftTarget aria-hidden=\"true\"></span>\n </div>\n </div>\n\n <div class=\"example-item example-item--right\">\n <p class=\"example-label\">{{ 'speakerBubbleDoc.labels.replyRight' | transloco }}</p>\n <div class=\"bubble-preview bubble-preview--end\">\n <dd-speaker-bubble-outline\n [color]=\"colorWhite\"\n [tail]=\"'right'\"\n [target]=\"outlineRightTarget\"\n >\n <small>QA</small>\n <p>Tail position still flips while content remains projected markup.</p>\n </dd-speaker-bubble-outline>\n <span class=\"bubble-target\" #outlineRightTarget aria-hidden=\"true\"></span>\n </div>\n </div>\n </div>\n </div>\n </dd-card-section>\n } @else {\n <dd-card-section>\n <h2>{{ 'speakerBubbleDoc.neobrutal.slabTitle' | transloco }}</h2>\n <p class=\"description\">{{ 'speakerBubbleDoc.neobrutal.slabDescription' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'speakerBubbleDoc.common.usage' | transloco }}</h3>\n <pre><code>&lt;dd-speaker-bubble-neobrutal-slab [color]=\"colorOrange\" [tail]=\"'left'\"&gt;\n &lt;small&gt;Live drop&lt;/small&gt;\n &lt;p&gt;Use ng-content for bold labels, paragraphs and inline status chips.&lt;/p&gt;\n&lt;/dd-speaker-bubble-neobrutal-slab&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'speakerBubbleDoc.common.inputs' | transloco }}</h3>\n <ul>\n <li>\n <dd-card-accent [color]=\"colorWhite\">\n <div [innerHTML]=\"inputContentEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n <li>\n <dd-card-accent [color]=\"colorViolet\">\n <div [innerHTML]=\"inputColorEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n <li>\n <dd-card-accent [color]=\"colorOrange\">\n <div [innerHTML]=\"inputTailEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'speakerBubbleDoc.common.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item example-item--neobrutal\">\n <p class=\"example-label\">{{ 'speakerBubbleDoc.labels.livePanel' | transloco }}</p>\n <div class=\"bubble-preview\">\n <dd-speaker-bubble-neobrutal-slab\n [color]=\"colorOrange\"\n [tail]=\"'left'\"\n [target]=\"slabLeftTarget\"\n >\n <small>Queue A</small>\n <p><strong>Live</strong> release banner for dashboards, status walls and loud interface narration.</p>\n </dd-speaker-bubble-neobrutal-slab>\n <span\n class=\"bubble-target bubble-target--orange\"\n #slabLeftTarget\n aria-hidden=\"true\"\n ></span>\n </div>\n </div>\n\n <div class=\"example-item example-item--neobrutal example-item--right\">\n <p class=\"example-label\">{{ 'speakerBubbleDoc.labels.hotReply' | transloco }}</p>\n <div class=\"bubble-preview bubble-preview--end\">\n <dd-speaker-bubble-neobrutal-slab\n [color]=\"colorViolet\"\n [tail]=\"'right'\"\n [target]=\"slabRightTarget\"\n >\n <small>Ops</small>\n <p>The slab version keeps a heavy tail and rigid geometry for louder chat layouts.</p>\n </dd-speaker-bubble-neobrutal-slab>\n <span\n class=\"bubble-target bubble-target--violet\"\n #slabRightTarget\n aria-hidden=\"true\"\n ></span>\n </div>\n </div>\n </div>\n </div>\n </dd-card-section>\n\n <dd-card-section>\n <h2>{{ 'speakerBubbleDoc.neobrutal.ticketTitle' | transloco }}</h2>\n <p class=\"description\">{{ 'speakerBubbleDoc.neobrutal.ticketDescription' | transloco }}</p>\n\n <div class=\"usage-block\">\n <h3>{{ 'speakerBubbleDoc.common.usage' | transloco }}</h3>\n <pre><code>&lt;dd-speaker-bubble-neobrutal-ticket [color]=\"colorDark\" [tail]=\"'right'\"&gt;\n &lt;small&gt;Alert feed&lt;/small&gt;\n &lt;p&gt;Projected content stays flexible while the component provides the ticket shell.&lt;/p&gt;\n&lt;/dd-speaker-bubble-neobrutal-ticket&gt;</code></pre>\n </div>\n\n <div class=\"inputs-block\">\n <h3>{{ 'speakerBubbleDoc.common.inputs' | transloco }}</h3>\n <ul>\n <li>\n <dd-card-accent [color]=\"colorWhite\">\n <div [innerHTML]=\"inputContentEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n <li>\n <dd-card-accent [color]=\"colorViolet\">\n <div [innerHTML]=\"inputColorEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n <li>\n <dd-card-accent [color]=\"colorOrange\">\n <div [innerHTML]=\"inputTailEl.innerHTML\"></div>\n </dd-card-accent>\n </li>\n </ul>\n </div>\n\n <div class=\"examples-block\">\n <h3>{{ 'speakerBubbleDoc.common.examples' | transloco }}</h3>\n <div class=\"example-row\">\n <div class=\"example-item example-item--neobrutal\">\n <p class=\"example-label\">{{ 'speakerBubbleDoc.labels.alertTicket' | transloco }}</p>\n <div class=\"bubble-preview\">\n <dd-speaker-bubble-neobrutal-ticket\n [color]=\"colorDark\"\n [tail]=\"'left'\"\n [target]=\"ticketLeftTarget\"\n >\n <small>Alert feed</small>\n <p>Ticket framing works for warning streams, operations chatter and serialized event logs.</p>\n </dd-speaker-bubble-neobrutal-ticket>\n <span\n class=\"bubble-target bubble-target--dark\"\n #ticketLeftTarget\n aria-hidden=\"true\"\n ></span>\n </div>\n </div>\n\n <div class=\"example-item example-item--neobrutal example-item--right\">\n <p class=\"example-label\">{{ 'speakerBubbleDoc.labels.ticketReply' | transloco }}</p>\n <div class=\"bubble-preview bubble-preview--end\">\n <dd-speaker-bubble-neobrutal-ticket\n [color]=\"colorWhite\"\n [tail]=\"'right'\"\n [target]=\"ticketRightTarget\"\n >\n <small>Review</small>\n <p><strong>Approved</strong> for launch preview, keep the counter-note visible in the timeline.</p>\n </dd-speaker-bubble-neobrutal-ticket>\n <span\n class=\"bubble-target bubble-target--orange\"\n #ticketRightTarget\n aria-hidden=\"true\"\n ></span>\n </div>\n </div>\n </div>\n </div>\n </dd-card-section>\n }\n </duck-dev-tab>\n</div>\n", styles: [".demo-container{max-width:1200px;margin:0 auto;padding:40px 20px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif}.demo-container h1{font-size:36px;font-weight:700;color:var(--dd-base-600);margin-bottom:30px;text-align:center;border-bottom:3px solid var(--dd-base-accent-blue);padding-bottom:20px}.demo-container h2{font-size:28px;font-weight:600;color:var(--dd-base-500);margin-bottom:15px;border-left:4px solid var(--dd-base-accent-blue);padding-left:15px}.demo-container .description{font-size:16px;line-height:1.6;color:var(--dd-base-400);margin-bottom:25px;padding:15px;background:var(--dd-base-100);border-radius:8px;border-left:3px solid var(--dd-base-300)}.demo-container h3{font-size:20px;font-weight:600;color:var(--dd-base-500);margin-bottom:15px;margin-top:25px}.demo-container .usage-block{margin-bottom:25px}.demo-container .usage-block pre{background:var(--dd-base-600);color:var(--dd-base-100);padding:20px;border-radius:8px;overflow-x:auto;margin:0}.demo-container .usage-block pre code{font-family:Courier New,Courier,monospace;font-size:14px;line-height:1.5}.demo-container .inputs-block{margin-bottom:25px}.demo-container .inputs-block ul{list-style:none;padding:0;margin:0}.demo-container .inputs-block ul li{margin-bottom:8px}.demo-container .examples-block .example-row{display:flex;gap:20px;margin-bottom:20px;flex-wrap:wrap}.demo-container .examples-block .example-item{flex:1;min-width:280px;padding:20px;background:var(--dd-base-100);border-radius:8px;border:2px solid var(--dd-base-300);display:flex;flex-direction:column;gap:15px;transition:all .3s ease}.demo-container .examples-block .example-item:hover{border-color:var(--dd-base-accent-blue);box-shadow:0 4px 12px var(--dd-base-300)}.demo-container .examples-block .example-item--right .example-label{text-align:right}.demo-container .examples-block .example-item--neobrutal{background:linear-gradient(135deg,color-mix(in srgb,var(--dd-base-accent-yellow) 24%,transparent) 0 15%,transparent 15% 100%),var(--dd-base-0);border:4px solid var(--dd-base-600);border-radius:0;box-shadow:8px 8px 0 var(--dd-base-accent-blue)}.demo-container .examples-block .example-item--neobrutal:hover{border-color:var(--dd-base-600);box-shadow:10px 10px 0 var(--dd-base-accent-orange)}.demo-container .examples-block .example-label{font-size:14px;font-weight:600;color:var(--dd-base-400);margin:0;text-align:left}.demo-container .bubble-preview{width:100%;display:flex;flex-direction:column;align-items:flex-start;gap:16px}.demo-container .bubble-preview--end{align-items:flex-end}.demo-container .bubble-target{position:relative;width:54px;height:54px;border:2px solid var(--dd-base-300);border-radius:18px;background:radial-gradient(circle at 34% 34%,var(--dd-base-0) 0 18%,transparent 18% 100%),linear-gradient(145deg,color-mix(in srgb,var(--dd-base-accent-blue) 16%,transparent) 0,transparent 52%),var(--dd-base-100);box-shadow:0 10px 18px color-mix(in srgb,var(--dd-base-400) 24%,transparent);flex:0 0 auto}.demo-container .bubble-target:before{content:\"\";position:absolute;inset:11px 13px 17px;border-radius:999px;background:color-mix(in srgb,var(--dd-base-accent-blue) 22%,var(--dd-base-0))}.demo-container .bubble-target:after{content:\"\";position:absolute;left:17px;right:17px;bottom:10px;height:10px;border-radius:999px;background:color-mix(in srgb,var(--dd-base-300) 85%,var(--dd-base-0))}.demo-container .bubble-target--violet{border-color:color-mix(in srgb,var(--dd-base-secondary) 42%,var(--dd-base-300));background:radial-gradient(circle at 34% 34%,var(--dd-base-0) 0 18%,transparent 18% 100%),linear-gradient(145deg,color-mix(in srgb,var(--dd-base-secondary) 18%,transparent) 0,transparent 52%),color-mix(in srgb,var(--dd-base-secondary) 10%,var(--dd-base-0))}.demo-container .bubble-target--orange{border-color:color-mix(in srgb,var(--dd-base-accent-orange) 46%,var(--dd-base-300));background:radial-gradient(circle at 34% 34%,var(--dd-base-0) 0 18%,transparent 18% 100%),linear-gradient(145deg,color-mix(in srgb,var(--dd-base-accent-orange) 22%,transparent) 0,transparent 52%),color-mix(in srgb,var(--dd-base-accent-yellow) 18%,var(--dd-base-0))}.demo-container .bubble-target--dark{border-color:var(--dd-base-500);background:radial-gradient(circle at 34% 34%,color-mix(in srgb,var(--dd-base-0) 88%,transparent) 0 18%,transparent 18% 100%),linear-gradient(145deg,color-mix(in srgb,var(--dd-base-accent-yellow) 16%,transparent) 0,transparent 52%),color-mix(in srgb,var(--dd-base-600) 92%,var(--dd-base-500))}.demo-container .bubble-target--dark:before{background:color-mix(in srgb,var(--dd-base-accent-yellow) 18%,var(--dd-base-0))}.demo-container .bubble-target--dark:after{background:color-mix(in srgb,var(--dd-base-400) 80%,var(--dd-base-600))}.demo-container .example-item--neobrutal .bubble-target{border-width:4px;border-color:var(--dd-base-600);border-radius:0;box-shadow:6px 6px 0 var(--dd-base-600)}@media(max-width:768px){.demo-container{padding:20px 15px}.demo-container h1{font-size:28px}.demo-container h2{font-size:24px}.demo-container .examples-block .example-row{flex-direction:column}}\n"] }]
5673
+ }], ctorParameters: () => [] });
5674
+
3913
5675
  class MainDocumentationPage {
3914
5676
  translocoService = inject(TranslocoService);
3915
5677
  title = signal('demo', { ...(ngDevMode ? { debugName: "title" } : {}) });
@@ -3924,6 +5686,7 @@ class MainDocumentationPage {
3924
5686
  { id: 'badge', label: this.translocoService.translate('tabs.badge') },
3925
5687
  { id: 'directives', label: this.translocoService.translate('tabs.directives') },
3926
5688
  { id: 'card', label: this.translocoService.translate('tabs.card') },
5689
+ { id: 'speaker-bubble', label: this.translocoService.translate('tabs.speakerBubble') },
3927
5690
  { id: 'input', label: this.translocoService.translate('tabs.input') },
3928
5691
  { id: 'modal', label: this.translocoService.translate('tabs.modal') },
3929
5692
  { id: 'notifications', label: this.translocoService.translate('tabs.notifications') },
@@ -3936,7 +5699,7 @@ class MainDocumentationPage {
3936
5699
  this.activeTab.set(tab);
3937
5700
  }
3938
5701
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: MainDocumentationPage, deps: [], target: i0.ɵɵFactoryTarget.Component });
3939
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.1", type: MainDocumentationPage, isStandalone: true, selector: "duck-dev-main-documentation-page", ngImport: i0, template: "<duck-dev-tab-vertical [tabs]=\"tabs\" (tabChange)=\"onTabChange($event)\">\n @switch (activeTab().id) {\n @case ('quick-start') {\n <app-quick-start-block />\n }\n @case ('accordion') {\n <app-accordion-block />\n }\n @case ('buttons') {\n <app-button-block />\n }\n @case ('loaders') {\n <app-loader-block />\n }\n @case ('progress') {\n <app-progress-bar-block />\n }\n @case ('tabs') {\n <app-tabs-block />\n }\n @case ('tooltip') {\n <app-tooltip-block />\n }\n @case ('badge') {\n <app-badge-block />\n }\n @case ('directives') {\n <app-directive-block />\n }\n @case ('card') {\n <app-card-block />\n }\n @case ('modal') {\n <app-modal-block />\n }\n @case ('input') {\n <app-input-block />\n }\n @case ('notifications') {\n <app-notification-block />\n }\n @case ('slider') {\n <app-slider-block />\n }\n @case ('segment') {\n <app-segment-block />\n }\n @case ('svg') {\n <app-duck-dev-svg-block />\n }\n }\n</duck-dev-tab-vertical>\n<duck-dev-notification-container />\n", styles: [":host{display:block;height:100%}\n"], dependencies: [{ kind: "component", type: ButtonBlock, selector: "app-button-block" }, { kind: "component", type: LoaderBlock, selector: "app-loader-block" }, { kind: "component", type: TabsBlock, selector: "app-tabs-block" }, { kind: "component", type: DuckDevSvgBlock, selector: "app-duck-dev-svg-block" }, { kind: "component", type: DuckDevTabVertical, selector: "duck-dev-tab-vertical", inputs: ["tabs"], outputs: ["tabChange"] }, { kind: "component", type: InputBlock, selector: "app-input-block" }, { kind: "component", type: NotificationBlock, selector: "app-notification-block" }, { kind: "component", type: DuckDevNotificationContainer, selector: "duck-dev-notification-container" }, { kind: "component", type: BadgeBlock, selector: "app-badge-block" }, { kind: "component", type: DirectiveBlock, selector: "app-directive-block" }, { kind: "component", type: AccordionBlock, selector: "app-accordion-block" }, { kind: "component", type: SliderBlock, selector: "app-slider-block" }, { kind: "component", type: CardBlock, selector: "app-card-block" }, { kind: "component", type: TooltipBlock, selector: "app-tooltip-block" }, { kind: "component", type: QuickStartBlock, selector: "app-quick-start-block" }, { kind: "component", type: ModalBlock, selector: "app-modal-block" }, { kind: "component", type: SegmentBlock, selector: "app-segment-block" }, { kind: "component", type: ProgressBarBlock, selector: "app-progress-bar-block" }] });
5702
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.1", type: MainDocumentationPage, isStandalone: true, selector: "duck-dev-main-documentation-page", ngImport: i0, template: "<duck-dev-tab-vertical [tabs]=\"tabs\" (tabChange)=\"onTabChange($event)\">\n @switch (activeTab().id) {\n @case ('quick-start') {\n <app-quick-start-block />\n }\n @case ('accordion') {\n <app-accordion-block />\n }\n @case ('buttons') {\n <app-button-block />\n }\n @case ('loaders') {\n <app-loader-block />\n }\n @case ('progress') {\n <app-progress-bar-block />\n }\n @case ('tabs') {\n <app-tabs-block />\n }\n @case ('tooltip') {\n <app-tooltip-block />\n }\n @case ('badge') {\n <app-badge-block />\n }\n @case ('directives') {\n <app-directive-block />\n }\n @case ('card') {\n <app-card-block />\n }\n @case ('speaker-bubble') {\n <app-speaker-bubble-block />\n }\n @case ('modal') {\n <app-modal-block />\n }\n @case ('input') {\n <app-input-block />\n }\n @case ('notifications') {\n <app-notification-block />\n }\n @case ('slider') {\n <app-slider-block />\n }\n @case ('segment') {\n <app-segment-block />\n }\n @case ('svg') {\n <app-duck-dev-svg-block />\n }\n }\n</duck-dev-tab-vertical>\n<duck-dev-notification-container />\n", styles: [":host{display:block;height:100%}\n"], dependencies: [{ kind: "component", type: ButtonBlock, selector: "app-button-block" }, { kind: "component", type: LoaderBlock, selector: "app-loader-block" }, { kind: "component", type: TabsBlock, selector: "app-tabs-block" }, { kind: "component", type: DuckDevSvgBlock, selector: "app-duck-dev-svg-block" }, { kind: "component", type: DuckDevTabVertical, selector: "duck-dev-tab-vertical", inputs: ["tabs"], outputs: ["tabChange"] }, { kind: "component", type: InputBlock, selector: "app-input-block" }, { kind: "component", type: NotificationBlock, selector: "app-notification-block" }, { kind: "component", type: DuckDevNotificationContainer, selector: "duck-dev-notification-container" }, { kind: "component", type: BadgeBlock, selector: "app-badge-block" }, { kind: "component", type: DirectiveBlock, selector: "app-directive-block" }, { kind: "component", type: AccordionBlock, selector: "app-accordion-block" }, { kind: "component", type: SliderBlock, selector: "app-slider-block" }, { kind: "component", type: CardBlock, selector: "app-card-block" }, { kind: "component", type: TooltipBlock, selector: "app-tooltip-block" }, { kind: "component", type: QuickStartBlock, selector: "app-quick-start-block" }, { kind: "component", type: ModalBlock, selector: "app-modal-block" }, { kind: "component", type: SegmentBlock, selector: "app-segment-block" }, { kind: "component", type: ProgressBarBlock, selector: "app-progress-bar-block" }, { kind: "component", type: SpeakerBubbleBlock, selector: "app-speaker-bubble-block" }] });
3940
5703
  }
3941
5704
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: MainDocumentationPage, decorators: [{
3942
5705
  type: Component,
@@ -3959,12 +5722,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImpor
3959
5722
  ModalBlock,
3960
5723
  SegmentBlock,
3961
5724
  ProgressBarBlock,
3962
- ], template: "<duck-dev-tab-vertical [tabs]=\"tabs\" (tabChange)=\"onTabChange($event)\">\n @switch (activeTab().id) {\n @case ('quick-start') {\n <app-quick-start-block />\n }\n @case ('accordion') {\n <app-accordion-block />\n }\n @case ('buttons') {\n <app-button-block />\n }\n @case ('loaders') {\n <app-loader-block />\n }\n @case ('progress') {\n <app-progress-bar-block />\n }\n @case ('tabs') {\n <app-tabs-block />\n }\n @case ('tooltip') {\n <app-tooltip-block />\n }\n @case ('badge') {\n <app-badge-block />\n }\n @case ('directives') {\n <app-directive-block />\n }\n @case ('card') {\n <app-card-block />\n }\n @case ('modal') {\n <app-modal-block />\n }\n @case ('input') {\n <app-input-block />\n }\n @case ('notifications') {\n <app-notification-block />\n }\n @case ('slider') {\n <app-slider-block />\n }\n @case ('segment') {\n <app-segment-block />\n }\n @case ('svg') {\n <app-duck-dev-svg-block />\n }\n }\n</duck-dev-tab-vertical>\n<duck-dev-notification-container />\n", styles: [":host{display:block;height:100%}\n"] }]
5725
+ SpeakerBubbleBlock,
5726
+ ], template: "<duck-dev-tab-vertical [tabs]=\"tabs\" (tabChange)=\"onTabChange($event)\">\n @switch (activeTab().id) {\n @case ('quick-start') {\n <app-quick-start-block />\n }\n @case ('accordion') {\n <app-accordion-block />\n }\n @case ('buttons') {\n <app-button-block />\n }\n @case ('loaders') {\n <app-loader-block />\n }\n @case ('progress') {\n <app-progress-bar-block />\n }\n @case ('tabs') {\n <app-tabs-block />\n }\n @case ('tooltip') {\n <app-tooltip-block />\n }\n @case ('badge') {\n <app-badge-block />\n }\n @case ('directives') {\n <app-directive-block />\n }\n @case ('card') {\n <app-card-block />\n }\n @case ('speaker-bubble') {\n <app-speaker-bubble-block />\n }\n @case ('modal') {\n <app-modal-block />\n }\n @case ('input') {\n <app-input-block />\n }\n @case ('notifications') {\n <app-notification-block />\n }\n @case ('slider') {\n <app-slider-block />\n }\n @case ('segment') {\n <app-segment-block />\n }\n @case ('svg') {\n <app-duck-dev-svg-block />\n }\n }\n</duck-dev-tab-vertical>\n<duck-dev-notification-container />\n", styles: [":host{display:block;height:100%}\n"] }]
3963
5727
  }] });
3964
5728
 
3965
5729
  const DuckDevLibTranslations = {
3966
- en: import('./duck-dev-lib-en-Ax8ROq2-.mjs'),
3967
- ru: import('./duck-dev-lib-ru-yHcUp82C.mjs'),
5730
+ en: import('./duck-dev-lib-en-VOJz-IcV.mjs'),
5731
+ ru: import('./duck-dev-lib-ru-COyomsqL.mjs'),
3968
5732
  };
3969
5733
 
3970
5734
  /*
@@ -3975,5 +5739,5 @@ const DuckDevLibTranslations = {
3975
5739
  * Generated bundle index. Do not edit.
3976
5740
  */
3977
5741
 
3978
- export { AccentEnumColor, Badge, BadgeNeobrutalSlab, BadgeNeobrutalStamp, BadgeNeobrutalTicket, ButtonBlurLift, ButtonCasper, ButtonFlip, ButtonGlideOver, ButtonNeobrutalBurst, ButtonNeobrutalSlab, ButtonNeobrutalTag, DdFlexDirectionDirective, DuckDevAccordionComponent as DuckDevAccordion, DuckDevAccordionNeobrutalComponent as DuckDevAccordionNeobrutal, DuckDevCardAccent, DuckDevCardMinimal, DuckDevCardNeobrutalPoster, DuckDevCardNeobrutalSlab, DuckDevCardNeobrutalStamp, DuckDevCardNeobrutalTicket, DuckDevCardOutline, DuckDevCardSection, DuckDevCardSignal, DuckDevIcon, DuckDevInput, DuckDevInputNeobrutalPoster, DuckDevInputNeobrutalRadio, DuckDevInputNeobrutalSlab, DuckDevInputNeobrutalStrip, DuckDevInputNeobrutalToggle, DuckDevLibTranslations, DuckDevModalClassic, DuckDevNotification, DuckDevNotificationContainer, DuckDevNotificationService, DuckDevProgressLine, DuckDevProgressMeter, DuckDevProgressNeobrutalSlab, DuckDevProgressNeobrutalStamp, DuckDevProgressNeobrutalTicket, DuckDevProgressStack, DuckDevTab, DuckDevTabVertical, DuckDevTooltip, DuckDevTooltipNeobrutalComponent, LoaderClassic, LoaderLoadingBubble, LoaderNeobrutalBars, LoaderNeobrutalMarquee, LoaderNeobrutalStamp, LoaderThreeDots, MainDocumentationPage, SliderClassic };
5742
+ export { AccentEnumColor, Badge, BadgeNeobrutalSlab, BadgeNeobrutalStamp, BadgeNeobrutalTicket, ButtonBlurLift, ButtonCasper, ButtonFlip, ButtonGlideOver, ButtonNeobrutalBurst, ButtonNeobrutalSlab, ButtonNeobrutalTag, DdFlexDirectionDirective, DuckDevAccordionComponent as DuckDevAccordion, DuckDevAccordionNeobrutalComponent as DuckDevAccordionNeobrutal, DuckDevCardAccent, DuckDevCardMinimal, DuckDevCardNeobrutalPoster, DuckDevCardNeobrutalSlab, DuckDevCardNeobrutalStamp, DuckDevCardNeobrutalTicket, DuckDevCardOutline, DuckDevCardSection, DuckDevCardSignal, DuckDevIcon, DuckDevInput, DuckDevInputNeobrutalPoster, DuckDevInputNeobrutalRadio, DuckDevInputNeobrutalSlab, DuckDevInputNeobrutalStrip, DuckDevInputNeobrutalToggle, DuckDevLibTranslations, DuckDevModalClassic, DuckDevNotification, DuckDevNotificationContainer, DuckDevNotificationService, DuckDevProgressLine, DuckDevProgressMeter, DuckDevProgressNeobrutalSlab, DuckDevProgressNeobrutalStamp, DuckDevProgressNeobrutalTicket, DuckDevProgressStack, DuckDevSegmentButton, DuckDevSegmentClassic, DuckDevSegmentNeobrutal, DuckDevSpeakerBubbleClassic, DuckDevSpeakerBubbleNeobrutalSlab, DuckDevSpeakerBubbleNeobrutalTicket, DuckDevSpeakerBubbleOutline, DuckDevSpeakerBubbleSoft, DuckDevTab, DuckDevTabVertical, DuckDevTooltip, DuckDevTooltipNeobrutalComponent, LoaderClassic, LoaderLoadingBubble, LoaderNeobrutalBars, LoaderNeobrutalMarquee, LoaderNeobrutalStamp, LoaderThreeDots, MainDocumentationPage, SliderClassic, getClassicSpeakerBubbleStyle, getNeobrutalSpeakerBubbleStyle, useSpeakerBubbleTail };
3979
5743
  //# sourceMappingURL=duck-dev-lib.mjs.map