codexly-ui 0.6.3 → 0.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, computed, ChangeDetectionStrategy, ViewEncapsulation, Component, InjectionToken, inject, PLATFORM_ID, signal, effect, Injectable, ElementRef, HostAttributeToken, output, Directive, forwardRef, contentChild, Renderer2, ApplicationRef, EnvironmentInjector, DestroyRef, createComponent, untracked, HostListener, viewChild, ViewChild, Injector, ChangeDetectorRef, NgZone, model, contentChildren, ContentChildren, ViewChildren, Input, numberAttribute, booleanAttribute } from '@angular/core';
2
+ import { input, computed, ChangeDetectionStrategy, ViewEncapsulation, Component, InjectionToken, inject, PLATFORM_ID, signal, effect, Injectable, ElementRef, HostAttributeToken, output, Directive, forwardRef, contentChild, Renderer2, ApplicationRef, EnvironmentInjector, DestroyRef, createComponent, untracked, HostListener, viewChild, ViewChild, Injector, ChangeDetectorRef, NgZone, model, contentChildren, ContentChildren, ViewChildren, numberAttribute, booleanAttribute, DOCUMENT as DOCUMENT$1, Input } from '@angular/core';
3
3
  import { isPlatformBrowser, NgTemplateOutlet, DOCUMENT, NgStyle, CurrencyPipe, DecimalPipe } from '@angular/common';
4
4
  import * as i1$1 from '@angular/forms';
5
5
  import { NG_VALUE_ACCESSOR, FormControl, NgControl, ReactiveFormsModule, FormGroup, Validators, FormsModule } from '@angular/forms';
@@ -12198,6 +12198,398 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
12198
12198
  `, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["clx-carousel{display:block;width:100%}\n"] }]
12199
12199
  }], ctorParameters: () => [], propDecorators: { clxColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "clxColor", required: false }] }], autoPlay: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoPlay", required: false }] }], interval: [{ type: i0.Input, args: [{ isSignal: true, alias: "interval", required: false }] }], loop: [{ type: i0.Input, args: [{ isSignal: true, alias: "loop", required: false }] }], aspectRatio: [{ type: i0.Input, args: [{ isSignal: true, alias: "aspectRatio", required: false }] }], transparent: [{ type: i0.Input, args: [{ isSignal: true, alias: "transparent", required: false }] }], _slides: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => ClxCarouselDirective), { isSignal: true }] }] } });
12200
12200
 
12201
+ class ClxAnimateDirective {
12202
+ // ─── Inputs ───────────────────────────────────────────────────────────────
12203
+ clxAnimate = input.required(...(ngDevMode ? [{ debugName: "clxAnimate" }] : /* istanbul ignore next */ []));
12204
+ trigger = input('manual', ...(ngDevMode ? [{ debugName: "trigger" }] : /* istanbul ignore next */ []));
12205
+ duration = input(undefined, { ...(ngDevMode ? { debugName: "duration" } : /* istanbul ignore next */ {}), transform: numberAttribute });
12206
+ delay = input(undefined, { ...(ngDevMode ? { debugName: "delay" } : /* istanbul ignore next */ {}), transform: numberAttribute });
12207
+ repeat = input(...(ngDevMode ? [undefined, { debugName: "repeat" }] : /* istanbul ignore next */ []));
12208
+ easing = input(...(ngDevMode ? [undefined, { debugName: "easing" }] : /* istanbul ignore next */ []));
12209
+ fillMode = input(...(ngDevMode ? [undefined, { debugName: "fillMode" }] : /* istanbul ignore next */ []));
12210
+ once = input(false, { ...(ngDevMode ? { debugName: "once" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
12211
+ threshold = input(undefined, { ...(ngDevMode ? { debugName: "threshold" } : /* istanbul ignore next */ {}), transform: numberAttribute });
12212
+ // ─── Outputs ──────────────────────────────────────────────────────────────
12213
+ animationStart = output();
12214
+ animationEnd = output();
12215
+ // ─── Dependencias ─────────────────────────────────────────────────────────
12216
+ el = inject(ElementRef);
12217
+ service = inject(ClxAnimateService);
12218
+ platformId = inject(PLATFORM_ID);
12219
+ destroyRef = inject(DestroyRef);
12220
+ // ─── Estado interno ───────────────────────────────────────────────────────
12221
+ _abortCtrl;
12222
+ _unobserve;
12223
+ _hasPlayed = false;
12224
+ _initialized = false;
12225
+ _destroyed = false;
12226
+ get nativeElement() { return this.el.nativeElement; }
12227
+ // ─── Ciclo de vida ────────────────────────────────────────────────────────
12228
+ ngOnInit() {
12229
+ if (!isPlatformBrowser(this.platformId))
12230
+ return;
12231
+ this._initialized = true;
12232
+ this._bindTrigger(this.trigger());
12233
+ this.destroyRef.onDestroy(() => {
12234
+ this._destroyed = true;
12235
+ this._teardown();
12236
+ });
12237
+ }
12238
+ ngOnChanges(changes) {
12239
+ if (!this._initialized)
12240
+ return;
12241
+ if ('trigger' in changes) {
12242
+ this._unbindTrigger();
12243
+ this._bindTrigger(this.trigger());
12244
+ }
12245
+ }
12246
+ // ─── API pública ──────────────────────────────────────────────────────────
12247
+ /**
12248
+ * Ejecuta la animación. Retorna una Promise que resuelve al terminar.
12249
+ * El output animationEnd se emite al resolverse la Promise.
12250
+ */
12251
+ play(overrides) {
12252
+ this.animationStart.emit();
12253
+ return this.service
12254
+ .runAnimation(this.nativeElement, this._buildConfig(overrides))
12255
+ .then(() => {
12256
+ if (this._destroyed)
12257
+ return;
12258
+ this.animationEnd.emit({
12259
+ element: this.nativeElement,
12260
+ animation: this.clxAnimate(),
12261
+ timestamp: Date.now(),
12262
+ });
12263
+ });
12264
+ }
12265
+ stop() {
12266
+ this.service.stop(this.nativeElement);
12267
+ }
12268
+ // ─── Privado ──────────────────────────────────────────────────────────────
12269
+ _buildConfig(overrides) {
12270
+ return this.service.buildConfig({
12271
+ animation: this.clxAnimate(),
12272
+ trigger: this.trigger(),
12273
+ ...(this.duration() !== undefined && { duration: this.duration() }),
12274
+ ...(this.delay() !== undefined && { delay: this.delay() }),
12275
+ ...(this.repeat() !== undefined && { repeat: this.repeat() }),
12276
+ ...(this.easing() !== undefined && { easing: this.easing() }),
12277
+ ...(this.fillMode() !== undefined && { fillMode: this.fillMode() }),
12278
+ ...(this.threshold() !== undefined && { threshold: this.threshold() }),
12279
+ once: this.once(),
12280
+ }, overrides ?? {});
12281
+ }
12282
+ _bindTrigger(trigger) {
12283
+ const el = this.nativeElement;
12284
+ this._abortCtrl = new AbortController();
12285
+ const { signal } = this._abortCtrl;
12286
+ switch (trigger) {
12287
+ case 'click':
12288
+ el.addEventListener('click', () => this.play(), { signal });
12289
+ break;
12290
+ case 'hover':
12291
+ el.addEventListener('mouseenter', () => this.play(), { signal });
12292
+ break;
12293
+ case 'hoverLeave':
12294
+ el.addEventListener('mouseleave', () => this.play(), { signal });
12295
+ break;
12296
+ case 'onEnter':
12297
+ this._bindIntersection(true);
12298
+ break;
12299
+ case 'onLeave':
12300
+ this._bindIntersection(false);
12301
+ break;
12302
+ case 'manual':
12303
+ break;
12304
+ }
12305
+ }
12306
+ _bindIntersection(playOnEnter) {
12307
+ const config = this._buildConfig();
12308
+ const threshold = config.threshold ?? 0.1;
12309
+ this._unobserve = this.service.observe(this.nativeElement, threshold, (isIntersecting) => {
12310
+ const shouldPlay = playOnEnter ? isIntersecting : !isIntersecting;
12311
+ if (!shouldPlay)
12312
+ return;
12313
+ if (this._hasPlayed && config.once)
12314
+ return;
12315
+ this._hasPlayed = true;
12316
+ this.play();
12317
+ if (config.once) {
12318
+ this._unobserve?.();
12319
+ this._unobserve = undefined;
12320
+ }
12321
+ });
12322
+ }
12323
+ _unbindTrigger() {
12324
+ this._abortCtrl?.abort();
12325
+ this._abortCtrl = undefined;
12326
+ this._unobserve?.();
12327
+ this._unobserve = undefined;
12328
+ this._hasPlayed = false;
12329
+ }
12330
+ _teardown() {
12331
+ this._unbindTrigger();
12332
+ this.service.stop(this.nativeElement);
12333
+ }
12334
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxAnimateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
12335
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.15", type: ClxAnimateDirective, isStandalone: true, selector: "[clxAnimate]", inputs: { clxAnimate: { classPropertyName: "clxAnimate", publicName: "clxAnimate", isSignal: true, isRequired: true, transformFunction: null }, trigger: { classPropertyName: "trigger", publicName: "trigger", isSignal: true, isRequired: false, transformFunction: null }, duration: { classPropertyName: "duration", publicName: "duration", isSignal: true, isRequired: false, transformFunction: null }, delay: { classPropertyName: "delay", publicName: "delay", isSignal: true, isRequired: false, transformFunction: null }, repeat: { classPropertyName: "repeat", publicName: "repeat", isSignal: true, isRequired: false, transformFunction: null }, easing: { classPropertyName: "easing", publicName: "easing", isSignal: true, isRequired: false, transformFunction: null }, fillMode: { classPropertyName: "fillMode", publicName: "fillMode", isSignal: true, isRequired: false, transformFunction: null }, once: { classPropertyName: "once", publicName: "once", isSignal: true, isRequired: false, transformFunction: null }, threshold: { classPropertyName: "threshold", publicName: "threshold", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { animationStart: "animationStart", animationEnd: "animationEnd" }, exportAs: ["clxAnimate"], usesOnChanges: true, ngImport: i0 });
12336
+ }
12337
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxAnimateDirective, decorators: [{
12338
+ type: Directive,
12339
+ args: [{
12340
+ selector: '[clxAnimate]',
12341
+ standalone: true,
12342
+ exportAs: 'clxAnimate',
12343
+ }]
12344
+ }], propDecorators: { clxAnimate: [{ type: i0.Input, args: [{ isSignal: true, alias: "clxAnimate", required: true }] }], trigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "trigger", required: false }] }], duration: [{ type: i0.Input, args: [{ isSignal: true, alias: "duration", required: false }] }], delay: [{ type: i0.Input, args: [{ isSignal: true, alias: "delay", required: false }] }], repeat: [{ type: i0.Input, args: [{ isSignal: true, alias: "repeat", required: false }] }], easing: [{ type: i0.Input, args: [{ isSignal: true, alias: "easing", required: false }] }], fillMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "fillMode", required: false }] }], once: [{ type: i0.Input, args: [{ isSignal: true, alias: "once", required: false }] }], threshold: [{ type: i0.Input, args: [{ isSignal: true, alias: "threshold", required: false }] }], animationStart: [{ type: i0.Output, args: ["animationStart"] }], animationEnd: [{ type: i0.Output, args: ["animationEnd"] }] } });
12345
+
12346
+ const SHADOW_CLASS_MAP = {
12347
+ none: '',
12348
+ sm: 'shadow-sm',
12349
+ md: 'shadow-md',
12350
+ lg: 'shadow-lg',
12351
+ xl: 'shadow-xl',
12352
+ '2xl': 'shadow-2xl',
12353
+ };
12354
+ const DEFAULT_POSITION = { right: 24, bottom: 24 };
12355
+ /** Movement below this, in pixels, is treated as a click rather than a drag. */
12356
+ const DRAG_THRESHOLD = 4;
12357
+ class ClxFabComponent {
12358
+ // ── Inputs — personalización tipo clx-button ─────────────────────────────────
12359
+ items = input([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
12360
+ icon = input('apps', ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
12361
+ color = input(undefined, ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
12362
+ variant = input('solid', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
12363
+ size = input('lg', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
12364
+ shadow = input('lg', ...(ngDevMode ? [{ debugName: "shadow" }] : /* istanbul ignore next */ []));
12365
+ triggerLabel = input('Accesos directos', ...(ngDevMode ? [{ debugName: "triggerLabel" }] : /* istanbul ignore next */ []));
12366
+ /** Saved position (e.g. from user preferences). Takes precedence over defaultPosition when present. */
12367
+ position = input(undefined, ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
12368
+ /** Initial corner used only when the user hasn't dragged/saved a position yet. */
12369
+ defaultPosition = input(DEFAULT_POSITION, ...(ngDevMode ? [{ debugName: "defaultPosition" }] : /* istanbul ignore next */ []));
12370
+ // ── Outputs ─────────────────────────────────────────────────────────────────
12371
+ itemClick = output();
12372
+ /** Emitted once, after a drag ends, with the new position to persist. */
12373
+ positionChange = output();
12374
+ _themeSvc = inject(ClxThemeService);
12375
+ _document = inject(DOCUMENT$1);
12376
+ _elementRef = inject((ElementRef));
12377
+ _color = computed(() => this.color() ?? this._themeSvc.config().primaryColor, ...(ngDevMode ? [{ debugName: "_color" }] : /* istanbul ignore next */ []));
12378
+ _draggedPosition = signal(null, ...(ngDevMode ? [{ debugName: "_draggedPosition" }] : /* istanbul ignore next */ []));
12379
+ _position = computed(() => this._draggedPosition() ?? this.position() ?? this.defaultPosition(), ...(ngDevMode ? [{ debugName: "_position" }] : /* istanbul ignore next */ []));
12380
+ _triggerClass = computed(() => `transition-transform duration-200 hover:scale-110 ${SHADOW_CLASS_MAP[this.shadow()]}`.trim(), ...(ngDevMode ? [{ debugName: "_triggerClass" }] : /* istanbul ignore next */ []));
12381
+ /** Los botones de la pila de accesos van un paso más pequeños que el trigger. */
12382
+ _itemSize = computed(() => {
12383
+ const map = {
12384
+ sm: 'xxs', md: 'xs', lg: 'sm',
12385
+ };
12386
+ return map[this.size()] ?? 'sm';
12387
+ }, ...(ngDevMode ? [{ debugName: "_itemSize" }] : /* istanbul ignore next */ []));
12388
+ // ── CDK Overlay ─────────────────────────────────────────────────────────────
12389
+ _sso = inject(ScrollStrategyOptions);
12390
+ _scrollStrategy = this._sso.reposition();
12391
+ _positions = [
12392
+ { originX: 'end', originY: 'top', overlayX: 'end', overlayY: 'bottom', offsetY: -8 },
12393
+ { originX: 'end', originY: 'bottom', overlayX: 'end', overlayY: 'top', offsetY: 8 },
12394
+ ];
12395
+ // ── State ────────────────────────────────────────────────────────────────────
12396
+ _isOpen = signal(false, ...(ngDevMode ? [{ debugName: "_isOpen" }] : /* istanbul ignore next */ []));
12397
+ // ── Drag ─────────────────────────────────────────────────────────────────────
12398
+ _dragging = false;
12399
+ _dragMoved = false;
12400
+ _dragStartX = 0;
12401
+ _dragStartY = 0;
12402
+ _dragStartRight = 0;
12403
+ _dragStartBottom = 0;
12404
+ _onPointerDown(event) {
12405
+ if (event.button !== 0 && event.pointerType === 'mouse')
12406
+ return;
12407
+ this._dragging = true;
12408
+ this._dragMoved = false;
12409
+ this._dragStartX = event.clientX;
12410
+ this._dragStartY = event.clientY;
12411
+ const current = this._position();
12412
+ this._dragStartRight = current.right;
12413
+ this._dragStartBottom = current.bottom;
12414
+ const wrapper = this._elementRef.nativeElement.querySelector('[cdkOverlayOrigin]');
12415
+ wrapper?.setPointerCapture(event.pointerId);
12416
+ const onMove = (e) => this._onPointerMove(e);
12417
+ const onUp = (e) => {
12418
+ this._onPointerUp(e);
12419
+ this._document.removeEventListener('pointermove', onMove);
12420
+ this._document.removeEventListener('pointerup', onUp);
12421
+ };
12422
+ this._document.addEventListener('pointermove', onMove);
12423
+ this._document.addEventListener('pointerup', onUp);
12424
+ }
12425
+ _onPointerMove(event) {
12426
+ if (!this._dragging)
12427
+ return;
12428
+ const dx = event.clientX - this._dragStartX;
12429
+ const dy = event.clientY - this._dragStartY;
12430
+ if (!this._dragMoved && Math.hypot(dx, dy) < DRAG_THRESHOLD)
12431
+ return;
12432
+ this._dragMoved = true;
12433
+ const win = this._document.defaultView;
12434
+ const maxRight = win ? win.innerWidth - 56 : Infinity;
12435
+ const maxBottom = win ? win.innerHeight - 56 : Infinity;
12436
+ const right = Math.min(Math.max(this._dragStartRight - dx, 8), maxRight);
12437
+ const bottom = Math.min(Math.max(this._dragStartBottom - dy, 8), maxBottom);
12438
+ this._draggedPosition.set({ right, bottom });
12439
+ }
12440
+ _onPointerUp(_event) {
12441
+ this._dragging = false;
12442
+ if (this._dragMoved) {
12443
+ this.positionChange.emit(this._position());
12444
+ }
12445
+ this._dragMoved = false;
12446
+ }
12447
+ _onTriggerClick() {
12448
+ if (this._dragMoved)
12449
+ return;
12450
+ this._toggle();
12451
+ }
12452
+ _toggle() { this._isOpen.update(v => !v); }
12453
+ _close() { this._isOpen.set(false); }
12454
+ _onKeydown(event) {
12455
+ if (event.key === 'Escape')
12456
+ this._close();
12457
+ }
12458
+ _onItemClick(item) {
12459
+ this.itemClick.emit(item);
12460
+ this._close();
12461
+ }
12462
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxFabComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
12463
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ClxFabComponent, isStandalone: true, selector: "clx-fab", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, shadow: { classPropertyName: "shadow", publicName: "shadow", isSignal: true, isRequired: false, transformFunction: null }, triggerLabel: { classPropertyName: "triggerLabel", publicName: "triggerLabel", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, defaultPosition: { classPropertyName: "defaultPosition", publicName: "defaultPosition", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemClick: "itemClick", positionChange: "positionChange" }, ngImport: i0, template: `
12464
+ <!-- ── Trigger (this wrapper owns the fixed positioning + drag; the button inside stays a plain clx-button) ── -->
12465
+ <div
12466
+ #wrapper
12467
+ #origin="cdkOverlayOrigin"
12468
+ cdkOverlayOrigin
12469
+ class="fixed z-40 select-none"
12470
+ [style.right.px]="_position().right"
12471
+ [style.bottom.px]="_position().bottom"
12472
+ [style.touchAction]="'none'"
12473
+ (pointerdown)="_onPointerDown($event)">
12474
+ <button
12475
+ clx-button
12476
+ type="button"
12477
+ [variant]="variant()"
12478
+ shape="circle"
12479
+ [iconOnly]="true"
12480
+ [icon]="_isOpen() ? 'close' : icon()"
12481
+ [color]="_color()"
12482
+ [size]="size()"
12483
+ [class]="_triggerClass()"
12484
+ [attr.aria-label]="triggerLabel()"
12485
+ [attr.aria-expanded]="_isOpen()"
12486
+ (click)="_onTriggerClick()">
12487
+ </button>
12488
+ </div>
12489
+
12490
+ <!-- ── Overlay panel: vertical stack expanding upward ────────────────── -->
12491
+ <ng-template
12492
+ cdkConnectedOverlay
12493
+ [cdkConnectedOverlayOrigin]="origin"
12494
+ [cdkConnectedOverlayOpen]="_isOpen()"
12495
+ [cdkConnectedOverlayPositions]="_positions"
12496
+ [cdkConnectedOverlayScrollStrategy]="_scrollStrategy"
12497
+ [cdkConnectedOverlayPush]="true"
12498
+ (overlayOutsideClick)="_close()"
12499
+ (overlayKeydown)="_onKeydown($event)">
12500
+
12501
+ <div class="flex flex-col items-end gap-2 mb-2" role="menu">
12502
+ @for (item of items(); track item.key; let i = $index) {
12503
+ <div
12504
+ clxAnimate="fadeInUp"
12505
+ trigger="onEnter"
12506
+ [delay]="i * 60"
12507
+ [duration]="220"
12508
+ class="flex items-center gap-2">
12509
+ <span class="px-2.5 py-1 rounded-lg bg-clx-surface border border-clx-border shadow-sm text-xs font-medium text-clx-text-label whitespace-nowrap">
12510
+ {{ item.label }}
12511
+ </span>
12512
+ <button clx-button type="button" shape="circle" [iconOnly]="true" [icon]="item.icon"
12513
+ variant="light" [color]="_color()" [size]="_itemSize()" class="shadow-md"
12514
+ [attr.aria-label]="item.label"
12515
+ (click)="_onItemClick(item)">
12516
+ </button>
12517
+ </div>
12518
+ }
12519
+ </div>
12520
+ </ng-template>
12521
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i1.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "component", type: ClxButtonComponent, selector: "button[clx-button], a[clx-button]", inputs: ["variant", "color", "size", "shape", "loading", "disabled", "block", "icon", "iconPosition", "iconOnly", "badge", "badgeColor"] }, { kind: "directive", type: ClxAnimateDirective, selector: "[clxAnimate]", inputs: ["clxAnimate", "trigger", "duration", "delay", "repeat", "easing", "fillMode", "once", "threshold"], outputs: ["animationStart", "animationEnd"], exportAs: ["clxAnimate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
12522
+ }
12523
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxFabComponent, decorators: [{
12524
+ type: Component,
12525
+ args: [{
12526
+ selector: 'clx-fab',
12527
+ standalone: true,
12528
+ imports: [OverlayModule, ClxButtonComponent, ClxAnimateDirective],
12529
+ template: `
12530
+ <!-- ── Trigger (this wrapper owns the fixed positioning + drag; the button inside stays a plain clx-button) ── -->
12531
+ <div
12532
+ #wrapper
12533
+ #origin="cdkOverlayOrigin"
12534
+ cdkOverlayOrigin
12535
+ class="fixed z-40 select-none"
12536
+ [style.right.px]="_position().right"
12537
+ [style.bottom.px]="_position().bottom"
12538
+ [style.touchAction]="'none'"
12539
+ (pointerdown)="_onPointerDown($event)">
12540
+ <button
12541
+ clx-button
12542
+ type="button"
12543
+ [variant]="variant()"
12544
+ shape="circle"
12545
+ [iconOnly]="true"
12546
+ [icon]="_isOpen() ? 'close' : icon()"
12547
+ [color]="_color()"
12548
+ [size]="size()"
12549
+ [class]="_triggerClass()"
12550
+ [attr.aria-label]="triggerLabel()"
12551
+ [attr.aria-expanded]="_isOpen()"
12552
+ (click)="_onTriggerClick()">
12553
+ </button>
12554
+ </div>
12555
+
12556
+ <!-- ── Overlay panel: vertical stack expanding upward ────────────────── -->
12557
+ <ng-template
12558
+ cdkConnectedOverlay
12559
+ [cdkConnectedOverlayOrigin]="origin"
12560
+ [cdkConnectedOverlayOpen]="_isOpen()"
12561
+ [cdkConnectedOverlayPositions]="_positions"
12562
+ [cdkConnectedOverlayScrollStrategy]="_scrollStrategy"
12563
+ [cdkConnectedOverlayPush]="true"
12564
+ (overlayOutsideClick)="_close()"
12565
+ (overlayKeydown)="_onKeydown($event)">
12566
+
12567
+ <div class="flex flex-col items-end gap-2 mb-2" role="menu">
12568
+ @for (item of items(); track item.key; let i = $index) {
12569
+ <div
12570
+ clxAnimate="fadeInUp"
12571
+ trigger="onEnter"
12572
+ [delay]="i * 60"
12573
+ [duration]="220"
12574
+ class="flex items-center gap-2">
12575
+ <span class="px-2.5 py-1 rounded-lg bg-clx-surface border border-clx-border shadow-sm text-xs font-medium text-clx-text-label whitespace-nowrap">
12576
+ {{ item.label }}
12577
+ </span>
12578
+ <button clx-button type="button" shape="circle" [iconOnly]="true" [icon]="item.icon"
12579
+ variant="light" [color]="_color()" [size]="_itemSize()" class="shadow-md"
12580
+ [attr.aria-label]="item.label"
12581
+ (click)="_onItemClick(item)">
12582
+ </button>
12583
+ </div>
12584
+ }
12585
+ </div>
12586
+ </ng-template>
12587
+ `,
12588
+ encapsulation: ViewEncapsulation.None,
12589
+ changeDetection: ChangeDetectionStrategy.OnPush,
12590
+ }]
12591
+ }], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], shadow: [{ type: i0.Input, args: [{ isSignal: true, alias: "shadow", required: false }] }], triggerLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerLabel", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], defaultPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultPosition", required: false }] }], itemClick: [{ type: i0.Output, args: ["itemClick"] }], positionChange: [{ type: i0.Output, args: ["positionChange"] }] } });
12592
+
12201
12593
  // ── Base classes ─────────────────────────────────────────────────────────────
12202
12594
  const TABLE_BASE_CLASS = 'w-full text-left border-collapse text-sm';
12203
12595
  const TABLE_HEADER_CELL_CLASS = 'px-4 py-3 font-semibold whitespace-nowrap';
@@ -15025,151 +15417,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
15025
15417
  }]
15026
15418
  }] });
15027
15419
 
15028
- class ClxAnimateDirective {
15029
- // ─── Inputs ───────────────────────────────────────────────────────────────
15030
- clxAnimate = input.required(...(ngDevMode ? [{ debugName: "clxAnimate" }] : /* istanbul ignore next */ []));
15031
- trigger = input('manual', ...(ngDevMode ? [{ debugName: "trigger" }] : /* istanbul ignore next */ []));
15032
- duration = input(undefined, { ...(ngDevMode ? { debugName: "duration" } : /* istanbul ignore next */ {}), transform: numberAttribute });
15033
- delay = input(undefined, { ...(ngDevMode ? { debugName: "delay" } : /* istanbul ignore next */ {}), transform: numberAttribute });
15034
- repeat = input(...(ngDevMode ? [undefined, { debugName: "repeat" }] : /* istanbul ignore next */ []));
15035
- easing = input(...(ngDevMode ? [undefined, { debugName: "easing" }] : /* istanbul ignore next */ []));
15036
- fillMode = input(...(ngDevMode ? [undefined, { debugName: "fillMode" }] : /* istanbul ignore next */ []));
15037
- once = input(false, { ...(ngDevMode ? { debugName: "once" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
15038
- threshold = input(undefined, { ...(ngDevMode ? { debugName: "threshold" } : /* istanbul ignore next */ {}), transform: numberAttribute });
15039
- // ─── Outputs ──────────────────────────────────────────────────────────────
15040
- animationStart = output();
15041
- animationEnd = output();
15042
- // ─── Dependencias ─────────────────────────────────────────────────────────
15043
- el = inject(ElementRef);
15044
- service = inject(ClxAnimateService);
15045
- platformId = inject(PLATFORM_ID);
15046
- destroyRef = inject(DestroyRef);
15047
- // ─── Estado interno ───────────────────────────────────────────────────────
15048
- _abortCtrl;
15049
- _unobserve;
15050
- _hasPlayed = false;
15051
- _initialized = false;
15052
- _destroyed = false;
15053
- get nativeElement() { return this.el.nativeElement; }
15054
- // ─── Ciclo de vida ────────────────────────────────────────────────────────
15055
- ngOnInit() {
15056
- if (!isPlatformBrowser(this.platformId))
15057
- return;
15058
- this._initialized = true;
15059
- this._bindTrigger(this.trigger());
15060
- this.destroyRef.onDestroy(() => {
15061
- this._destroyed = true;
15062
- this._teardown();
15063
- });
15064
- }
15065
- ngOnChanges(changes) {
15066
- if (!this._initialized)
15067
- return;
15068
- if ('trigger' in changes) {
15069
- this._unbindTrigger();
15070
- this._bindTrigger(this.trigger());
15071
- }
15072
- }
15073
- // ─── API pública ──────────────────────────────────────────────────────────
15074
- /**
15075
- * Ejecuta la animación. Retorna una Promise que resuelve al terminar.
15076
- * El output animationEnd se emite al resolverse la Promise.
15077
- */
15078
- play(overrides) {
15079
- this.animationStart.emit();
15080
- return this.service
15081
- .runAnimation(this.nativeElement, this._buildConfig(overrides))
15082
- .then(() => {
15083
- if (this._destroyed)
15084
- return;
15085
- this.animationEnd.emit({
15086
- element: this.nativeElement,
15087
- animation: this.clxAnimate(),
15088
- timestamp: Date.now(),
15089
- });
15090
- });
15091
- }
15092
- stop() {
15093
- this.service.stop(this.nativeElement);
15094
- }
15095
- // ─── Privado ──────────────────────────────────────────────────────────────
15096
- _buildConfig(overrides) {
15097
- return this.service.buildConfig({
15098
- animation: this.clxAnimate(),
15099
- trigger: this.trigger(),
15100
- ...(this.duration() !== undefined && { duration: this.duration() }),
15101
- ...(this.delay() !== undefined && { delay: this.delay() }),
15102
- ...(this.repeat() !== undefined && { repeat: this.repeat() }),
15103
- ...(this.easing() !== undefined && { easing: this.easing() }),
15104
- ...(this.fillMode() !== undefined && { fillMode: this.fillMode() }),
15105
- ...(this.threshold() !== undefined && { threshold: this.threshold() }),
15106
- once: this.once(),
15107
- }, overrides ?? {});
15108
- }
15109
- _bindTrigger(trigger) {
15110
- const el = this.nativeElement;
15111
- this._abortCtrl = new AbortController();
15112
- const { signal } = this._abortCtrl;
15113
- switch (trigger) {
15114
- case 'click':
15115
- el.addEventListener('click', () => this.play(), { signal });
15116
- break;
15117
- case 'hover':
15118
- el.addEventListener('mouseenter', () => this.play(), { signal });
15119
- break;
15120
- case 'hoverLeave':
15121
- el.addEventListener('mouseleave', () => this.play(), { signal });
15122
- break;
15123
- case 'onEnter':
15124
- this._bindIntersection(true);
15125
- break;
15126
- case 'onLeave':
15127
- this._bindIntersection(false);
15128
- break;
15129
- case 'manual':
15130
- break;
15131
- }
15132
- }
15133
- _bindIntersection(playOnEnter) {
15134
- const config = this._buildConfig();
15135
- const threshold = config.threshold ?? 0.1;
15136
- this._unobserve = this.service.observe(this.nativeElement, threshold, (isIntersecting) => {
15137
- const shouldPlay = playOnEnter ? isIntersecting : !isIntersecting;
15138
- if (!shouldPlay)
15139
- return;
15140
- if (this._hasPlayed && config.once)
15141
- return;
15142
- this._hasPlayed = true;
15143
- this.play();
15144
- if (config.once) {
15145
- this._unobserve?.();
15146
- this._unobserve = undefined;
15147
- }
15148
- });
15149
- }
15150
- _unbindTrigger() {
15151
- this._abortCtrl?.abort();
15152
- this._abortCtrl = undefined;
15153
- this._unobserve?.();
15154
- this._unobserve = undefined;
15155
- this._hasPlayed = false;
15156
- }
15157
- _teardown() {
15158
- this._unbindTrigger();
15159
- this.service.stop(this.nativeElement);
15160
- }
15161
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxAnimateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
15162
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.15", type: ClxAnimateDirective, isStandalone: true, selector: "[clxAnimate]", inputs: { clxAnimate: { classPropertyName: "clxAnimate", publicName: "clxAnimate", isSignal: true, isRequired: true, transformFunction: null }, trigger: { classPropertyName: "trigger", publicName: "trigger", isSignal: true, isRequired: false, transformFunction: null }, duration: { classPropertyName: "duration", publicName: "duration", isSignal: true, isRequired: false, transformFunction: null }, delay: { classPropertyName: "delay", publicName: "delay", isSignal: true, isRequired: false, transformFunction: null }, repeat: { classPropertyName: "repeat", publicName: "repeat", isSignal: true, isRequired: false, transformFunction: null }, easing: { classPropertyName: "easing", publicName: "easing", isSignal: true, isRequired: false, transformFunction: null }, fillMode: { classPropertyName: "fillMode", publicName: "fillMode", isSignal: true, isRequired: false, transformFunction: null }, once: { classPropertyName: "once", publicName: "once", isSignal: true, isRequired: false, transformFunction: null }, threshold: { classPropertyName: "threshold", publicName: "threshold", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { animationStart: "animationStart", animationEnd: "animationEnd" }, exportAs: ["clxAnimate"], usesOnChanges: true, ngImport: i0 });
15163
- }
15164
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxAnimateDirective, decorators: [{
15165
- type: Directive,
15166
- args: [{
15167
- selector: '[clxAnimate]',
15168
- standalone: true,
15169
- exportAs: 'clxAnimate',
15170
- }]
15171
- }], propDecorators: { clxAnimate: [{ type: i0.Input, args: [{ isSignal: true, alias: "clxAnimate", required: true }] }], trigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "trigger", required: false }] }], duration: [{ type: i0.Input, args: [{ isSignal: true, alias: "duration", required: false }] }], delay: [{ type: i0.Input, args: [{ isSignal: true, alias: "delay", required: false }] }], repeat: [{ type: i0.Input, args: [{ isSignal: true, alias: "repeat", required: false }] }], easing: [{ type: i0.Input, args: [{ isSignal: true, alias: "easing", required: false }] }], fillMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "fillMode", required: false }] }], once: [{ type: i0.Input, args: [{ isSignal: true, alias: "once", required: false }] }], threshold: [{ type: i0.Input, args: [{ isSignal: true, alias: "threshold", required: false }] }], animationStart: [{ type: i0.Output, args: ["animationStart"] }], animationEnd: [{ type: i0.Output, args: ["animationEnd"] }] } });
15172
-
15173
15420
  class ClxAnimateGroupDirective {
15174
15421
  stagger = input(100, { ...(ngDevMode ? { debugName: "stagger" } : /* istanbul ignore next */ {}), transform: numberAttribute });
15175
15422
  children;
@@ -15439,5 +15686,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
15439
15686
  * Generated bundle index. Do not edit.
15440
15687
  */
15441
15688
 
15442
- export { CLX_ADDON_BORDER, CLX_ADDON_TEXT, CLX_ALERT_OPTIONS, CLX_ALERT_RESOLVE, CLX_BG_ADDON, CLX_BG_DISABLED, CLX_BG_ICON_WRAP, CLX_BG_SECTION, CLX_BG_SURFACE, CLX_BORDER_DEFAULT, CLX_BORDER_DISABLED, CLX_BORDER_MEDIUM, CLX_COLOR_HEX, CLX_COLOR_HEX_100, CLX_COLOR_MAP, CLX_FONT_CATALOG, CLX_MODAL_ANIM_CONFIG, CLX_MODAL_DATA, CLX_MODAL_REF, CLX_OPTION_DISABLED, CLX_PLACEHOLDER, CLX_RADIO_GROUP, CLX_RADIUS_MAP, CLX_TEXT_BODY, CLX_TEXT_DISABLED, CLX_TEXT_HEADING, CLX_TEXT_HINT, CLX_TEXT_IDLE, CLX_TEXT_INPUT, CLX_TEXT_LABEL, CLX_TEXT_OPTION, CLX_TEXT_SUBTITLE, CLX_TEXT_TITLE, CLX_THEME_CONFIG, CLX_THEME_DEFAULTS, CLX_TOAST_DEFAULTS, ClxAlertComponent, ClxAlertService, ClxAnimateDirective, ClxAnimateGroupDirective, ClxAnimateService, ClxAppLayoutComponent, ClxAvatarComponent, ClxBadgeComponent, ClxBrandComponent, ClxButtonComponent, ClxButtonGroupComponent, ClxCardBodyDirective, ClxCardComponent, ClxCardFooterDirective, ClxCardHeaderDirective, ClxCarouselComponent, ClxCarouselDirective, ClxCartComponent, ClxCartSummaryDrawer, ClxCellDirective, ClxCheckboxComponent, ClxColorPickerComponent, ClxColumnDefDirective, ClxDateRangePickerComponent, ClxDatepickerComponent, ClxDrawerComponent, ClxDrawerService, ClxEditorComponent, ClxEditorLinkModalComponent, ClxFilterPanelComponent, ClxHeaderCellDirective, ClxIconComponent, ClxInputComponent, ClxListComponent, ClxListItemComponent, ClxMenuComponent, ClxMenuItemComponent, ClxModalComponent, ClxModalService, ClxNavGroupComponent, ClxNumberComponent, ClxPageEmptyComponent, ClxPageNotFoundComponent, ClxPageServerErrorComponent, ClxPageUnauthorizedComponent, ClxPaginationComponent, ClxProductComponent, ClxProductDetailComponent, ClxProfileComponent, ClxProgressBarComponent, ClxRadioComponent, ClxRadioGroupComponent, ClxRatingComponent, ClxSelectComponent, ClxSkeletonComponent, ClxSliderComponent, ClxSpinnerComponent, ClxStatCardComponent, ClxStepComponent, ClxStepperComponent, ClxSwitchComponent, ClxTabDirective, ClxTableComponent, ClxTabsComponent, ClxTagComponent, ClxTextareaComponent, ClxThemeService, ClxTimelineComponent, ClxTimelineItemComponent, ClxTimepickerComponent, ClxToastComponent, ClxToastContainerComponent, ClxToastService, ClxTooltipComponent, ClxTooltipDirective, ClxTreeComponent, ClxUploadComponent, ClxWishlistComponent, ClxWizardComponent, TIMEPICKER_SIZE_MAP, parseColorInput, provideCodexlyTheme, resolveColor, resolveContainerRadius, resolveRadius };
15689
+ export { CLX_ADDON_BORDER, CLX_ADDON_TEXT, CLX_ALERT_OPTIONS, CLX_ALERT_RESOLVE, CLX_BG_ADDON, CLX_BG_DISABLED, CLX_BG_ICON_WRAP, CLX_BG_SECTION, CLX_BG_SURFACE, CLX_BORDER_DEFAULT, CLX_BORDER_DISABLED, CLX_BORDER_MEDIUM, CLX_COLOR_HEX, CLX_COLOR_HEX_100, CLX_COLOR_MAP, CLX_FONT_CATALOG, CLX_MODAL_ANIM_CONFIG, CLX_MODAL_DATA, CLX_MODAL_REF, CLX_OPTION_DISABLED, CLX_PLACEHOLDER, CLX_RADIO_GROUP, CLX_RADIUS_MAP, CLX_TEXT_BODY, CLX_TEXT_DISABLED, CLX_TEXT_HEADING, CLX_TEXT_HINT, CLX_TEXT_IDLE, CLX_TEXT_INPUT, CLX_TEXT_LABEL, CLX_TEXT_OPTION, CLX_TEXT_SUBTITLE, CLX_TEXT_TITLE, CLX_THEME_CONFIG, CLX_THEME_DEFAULTS, CLX_TOAST_DEFAULTS, ClxAlertComponent, ClxAlertService, ClxAnimateDirective, ClxAnimateGroupDirective, ClxAnimateService, ClxAppLayoutComponent, ClxAvatarComponent, ClxBadgeComponent, ClxBrandComponent, ClxButtonComponent, ClxButtonGroupComponent, ClxCardBodyDirective, ClxCardComponent, ClxCardFooterDirective, ClxCardHeaderDirective, ClxCarouselComponent, ClxCarouselDirective, ClxCartComponent, ClxCartSummaryDrawer, ClxCellDirective, ClxCheckboxComponent, ClxColorPickerComponent, ClxColumnDefDirective, ClxDateRangePickerComponent, ClxDatepickerComponent, ClxDrawerComponent, ClxDrawerService, ClxEditorComponent, ClxEditorLinkModalComponent, ClxFabComponent, ClxFilterPanelComponent, ClxHeaderCellDirective, ClxIconComponent, ClxInputComponent, ClxListComponent, ClxListItemComponent, ClxMenuComponent, ClxMenuItemComponent, ClxModalComponent, ClxModalService, ClxNavGroupComponent, ClxNumberComponent, ClxPageEmptyComponent, ClxPageNotFoundComponent, ClxPageServerErrorComponent, ClxPageUnauthorizedComponent, ClxPaginationComponent, ClxProductComponent, ClxProductDetailComponent, ClxProfileComponent, ClxProgressBarComponent, ClxRadioComponent, ClxRadioGroupComponent, ClxRatingComponent, ClxSelectComponent, ClxSkeletonComponent, ClxSliderComponent, ClxSpinnerComponent, ClxStatCardComponent, ClxStepComponent, ClxStepperComponent, ClxSwitchComponent, ClxTabDirective, ClxTableComponent, ClxTabsComponent, ClxTagComponent, ClxTextareaComponent, ClxThemeService, ClxTimelineComponent, ClxTimelineItemComponent, ClxTimepickerComponent, ClxToastComponent, ClxToastContainerComponent, ClxToastService, ClxTooltipComponent, ClxTooltipDirective, ClxTreeComponent, ClxUploadComponent, ClxWishlistComponent, ClxWizardComponent, TIMEPICKER_SIZE_MAP, parseColorInput, provideCodexlyTheme, resolveColor, resolveContainerRadius, resolveRadius };
15443
15690
  //# sourceMappingURL=codexly-ui.mjs.map