codexly-ui 0.6.8 → 0.6.10

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, numberAttribute, booleanAttribute, DOCUMENT as DOCUMENT$1, Input } 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, 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';
@@ -12352,8 +12352,6 @@ const SHADOW_CLASS_MAP = {
12352
12352
  '2xl': 'shadow-2xl',
12353
12353
  };
12354
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
12355
  class ClxFabComponent {
12358
12356
  // ── Inputs — personalización tipo clx-button ─────────────────────────────────
12359
12357
  items = input([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
@@ -12363,21 +12361,13 @@ class ClxFabComponent {
12363
12361
  size = input('sm', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
12364
12362
  shadow = input('lg', ...(ngDevMode ? [{ debugName: "shadow" }] : /* istanbul ignore next */ []));
12365
12363
  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
- /** Direction the shortcut stack expands toward. */
12371
- expandDirection = input('up', ...(ngDevMode ? [{ debugName: "expandDirection" }] : /* istanbul ignore next */ []));
12364
+ /** Fixed offset from the bottom-right corner of the viewport. */
12365
+ position = input(DEFAULT_POSITION, ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
12372
12366
  // ── Outputs ─────────────────────────────────────────────────────────────────
12373
12367
  itemClick = output();
12374
- /** Emitted once, after a drag ends, with the new position to persist. */
12375
- positionChange = output();
12376
12368
  _themeSvc = inject(ClxThemeService);
12377
- _document = inject(DOCUMENT$1);
12378
12369
  _color = computed(() => this.color() ?? this._themeSvc.config().primaryColor, ...(ngDevMode ? [{ debugName: "_color" }] : /* istanbul ignore next */ []));
12379
- _draggedPosition = signal(null, ...(ngDevMode ? [{ debugName: "_draggedPosition" }] : /* istanbul ignore next */ []));
12380
- _position = computed(() => this._draggedPosition() ?? this.position() ?? this.defaultPosition(), ...(ngDevMode ? [{ debugName: "_position" }] : /* istanbul ignore next */ []));
12370
+ _position = computed(() => this.position() ?? DEFAULT_POSITION, ...(ngDevMode ? [{ debugName: "_position" }] : /* istanbul ignore next */ []));
12381
12371
  _triggerClass = computed(() => `transition-transform duration-200 hover:scale-110 ${SHADOW_CLASS_MAP[this.shadow()]}`.trim(), ...(ngDevMode ? [{ debugName: "_triggerClass" }] : /* istanbul ignore next */ []));
12382
12372
  /** Los botones de la pila de accesos van un paso más pequeños que el trigger. */
12383
12373
  _itemSize = computed(() => {
@@ -12386,104 +12376,15 @@ class ClxFabComponent {
12386
12376
  };
12387
12377
  return map[this.size()] ?? 'sm';
12388
12378
  }, ...(ngDevMode ? [{ debugName: "_itemSize" }] : /* istanbul ignore next */ []));
12389
- // ── CDK Overlay ─────────────────────────────────────────────────────────────
12379
+ // ── CDK Overlay — always expands upward from the trigger ────────────────────
12390
12380
  _sso = inject(ScrollStrategyOptions);
12391
12381
  _scrollStrategy = this._sso.reposition();
12392
- static POSITIONS_BY_DIRECTION = {
12393
- up: [
12394
- { originX: 'end', originY: 'top', overlayX: 'end', overlayY: 'bottom', offsetY: -8 },
12395
- { originX: 'end', originY: 'bottom', overlayX: 'end', overlayY: 'top', offsetY: 8 },
12396
- ],
12397
- down: [
12398
- { originX: 'end', originY: 'bottom', overlayX: 'end', overlayY: 'top', offsetY: 8 },
12399
- { originX: 'end', originY: 'top', overlayX: 'end', overlayY: 'bottom', offsetY: -8 },
12400
- ],
12401
- left: [
12402
- { originX: 'start', originY: 'center', overlayX: 'end', overlayY: 'center', offsetX: -8 },
12403
- { originX: 'end', originY: 'center', overlayX: 'start', overlayY: 'center', offsetX: 8 },
12404
- ],
12405
- right: [
12406
- { originX: 'end', originY: 'center', overlayX: 'start', overlayY: 'center', offsetX: 8 },
12407
- { originX: 'start', originY: 'center', overlayX: 'end', overlayY: 'center', offsetX: -8 },
12408
- ],
12409
- };
12410
- _positions = computed(() => ClxFabComponent.POSITIONS_BY_DIRECTION[this.expandDirection()], ...(ngDevMode ? [{ debugName: "_positions" }] : /* istanbul ignore next */ []));
12411
- static STACK_CLASS_BY_DIRECTION = {
12412
- up: 'flex-col items-end mb-2',
12413
- down: 'flex-col-reverse items-end mt-2',
12414
- left: 'flex-row items-center mr-2',
12415
- right: 'flex-row-reverse items-center ml-2',
12416
- };
12417
- _stackClass = computed(() => `flex gap-2 ${ClxFabComponent.STACK_CLASS_BY_DIRECTION[this.expandDirection()]}`, ...(ngDevMode ? [{ debugName: "_stackClass" }] : /* istanbul ignore next */ []));
12418
- static ITEM_CLASS_BY_DIRECTION = {
12419
- up: 'flex items-center gap-2',
12420
- down: 'flex items-center gap-2',
12421
- left: 'flex items-center gap-2 flex-row-reverse',
12422
- right: 'flex items-center gap-2',
12423
- };
12424
- _itemClass = computed(() => ClxFabComponent.ITEM_CLASS_BY_DIRECTION[this.expandDirection()], ...(ngDevMode ? [{ debugName: "_itemClass" }] : /* istanbul ignore next */ []));
12425
- static ANIMATION_BY_DIRECTION = {
12426
- up: 'fadeInUp',
12427
- down: 'fadeInDown',
12428
- left: 'fadeInLeft',
12429
- right: 'fadeInRight',
12430
- };
12431
- _itemAnimation = computed(() => ClxFabComponent.ANIMATION_BY_DIRECTION[this.expandDirection()], ...(ngDevMode ? [{ debugName: "_itemAnimation" }] : /* istanbul ignore next */ []));
12382
+ _positions = [
12383
+ { originX: 'center', originY: 'top', overlayX: 'center', overlayY: 'bottom', offsetY: -8 },
12384
+ { originX: 'center', originY: 'bottom', overlayX: 'center', overlayY: 'top', offsetY: 8 },
12385
+ ];
12432
12386
  // ── State ────────────────────────────────────────────────────────────────────
12433
12387
  _isOpen = signal(false, ...(ngDevMode ? [{ debugName: "_isOpen" }] : /* istanbul ignore next */ []));
12434
- // ── Drag ─────────────────────────────────────────────────────────────────────
12435
- _dragging = false;
12436
- _dragMoved = false;
12437
- _dragStartX = 0;
12438
- _dragStartY = 0;
12439
- _dragStartRight = 0;
12440
- _dragStartBottom = 0;
12441
- _onPointerDown(event) {
12442
- if (event.button !== 0 && event.pointerType === 'mouse')
12443
- return;
12444
- this._dragging = true;
12445
- this._dragMoved = false;
12446
- this._dragStartX = event.clientX;
12447
- this._dragStartY = event.clientY;
12448
- const current = this._position();
12449
- this._dragStartRight = current.right;
12450
- this._dragStartBottom = current.bottom;
12451
- const onMove = (e) => this._onPointerMove(e);
12452
- const onUp = (e) => {
12453
- this._onPointerUp(e);
12454
- this._document.removeEventListener('pointermove', onMove);
12455
- this._document.removeEventListener('pointerup', onUp);
12456
- };
12457
- this._document.addEventListener('pointermove', onMove);
12458
- this._document.addEventListener('pointerup', onUp);
12459
- }
12460
- _onPointerMove(event) {
12461
- if (!this._dragging)
12462
- return;
12463
- const dx = event.clientX - this._dragStartX;
12464
- const dy = event.clientY - this._dragStartY;
12465
- if (!this._dragMoved && Math.hypot(dx, dy) < DRAG_THRESHOLD)
12466
- return;
12467
- this._dragMoved = true;
12468
- const win = this._document.defaultView;
12469
- const maxRight = win ? win.innerWidth - 56 : Infinity;
12470
- const maxBottom = win ? win.innerHeight - 56 : Infinity;
12471
- const right = Math.min(Math.max(this._dragStartRight - dx, 8), maxRight);
12472
- const bottom = Math.min(Math.max(this._dragStartBottom - dy, 8), maxBottom);
12473
- this._draggedPosition.set({ right, bottom });
12474
- }
12475
- _onPointerUp(_event) {
12476
- this._dragging = false;
12477
- if (this._dragMoved) {
12478
- this.positionChange.emit(this._position());
12479
- }
12480
- this._dragMoved = false;
12481
- }
12482
- _onTriggerClick() {
12483
- if (this._dragMoved)
12484
- return;
12485
- this._toggle();
12486
- }
12487
12388
  _toggle() { this._isOpen.update(v => !v); }
12488
12389
  _close() { this._isOpen.set(false); }
12489
12390
  _onKeydown(event) {
@@ -12495,125 +12396,101 @@ class ClxFabComponent {
12495
12396
  this._close();
12496
12397
  }
12497
12398
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxFabComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
12498
- 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 }, expandDirection: { classPropertyName: "expandDirection", publicName: "expandDirection", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemClick: "itemClick", positionChange: "positionChange" }, ngImport: i0, template: `
12499
- <!-- ── Trigger (this wrapper owns the fixed positioning + drag; the button inside stays a plain clx-button) ── -->
12500
- <div
12399
+ 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 } }, outputs: { itemClick: "itemClick" }, ngImport: i0, template: `
12400
+ <!-- ── Trigger, fixed to the bottom-right corner (offset configurable via position()) ── -->
12401
+ <button
12501
12402
  #origin="cdkOverlayOrigin"
12502
12403
  cdkOverlayOrigin
12503
- class="fixed z-40 select-none"
12404
+ clx-button
12405
+ type="button"
12406
+ class="fixed z-40"
12407
+ [variant]="variant()"
12408
+ shape="circle"
12409
+ [iconOnly]="true"
12410
+ [icon]="_isOpen() ? 'close' : icon()"
12411
+ [color]="_color()"
12412
+ [size]="size()"
12413
+ [class]="_triggerClass()"
12504
12414
  [style.right.px]="_position().right"
12505
12415
  [style.bottom.px]="_position().bottom"
12506
- [style.touchAction]="'none'"
12507
- (pointerdown)="_onPointerDown($event)">
12508
- <button
12509
- clx-button
12510
- type="button"
12511
- [variant]="variant()"
12512
- shape="circle"
12513
- [iconOnly]="true"
12514
- [icon]="_isOpen() ? 'close' : icon()"
12515
- [color]="_color()"
12516
- [size]="size()"
12517
- [class]="_triggerClass()"
12518
- [attr.aria-label]="triggerLabel()"
12519
- [attr.aria-expanded]="_isOpen()"
12520
- (click)="_onTriggerClick()">
12521
- </button>
12522
- </div>
12416
+ [attr.aria-label]="triggerLabel()"
12417
+ [attr.aria-expanded]="_isOpen()"
12418
+ (click)="_toggle()">
12419
+ </button>
12523
12420
 
12524
- <!-- ── Overlay panel: stack expanding toward expandDirection() ────────────────── -->
12421
+ <!-- ── Overlay panel: accordion-style stack expanding upward from the trigger ── -->
12525
12422
  <ng-template
12526
12423
  cdkConnectedOverlay
12527
12424
  [cdkConnectedOverlayOrigin]="origin"
12528
12425
  [cdkConnectedOverlayOpen]="_isOpen()"
12529
- [cdkConnectedOverlayPositions]="_positions()"
12426
+ [cdkConnectedOverlayPositions]="_positions"
12530
12427
  [cdkConnectedOverlayScrollStrategy]="_scrollStrategy"
12531
12428
  [cdkConnectedOverlayPush]="true"
12532
12429
  (overlayOutsideClick)="_close()"
12533
12430
  (overlayKeydown)="_onKeydown($event)">
12534
12431
 
12535
- <div [class]="_stackClass()" role="menu">
12432
+ <div class="flex flex-col items-center gap-2 mb-2" role="menu">
12536
12433
  @for (item of items(); track item.key; let i = $index) {
12537
- <div
12538
- [clxAnimate]="_itemAnimation()"
12539
- trigger="onEnter"
12540
- [delay]="i * 60"
12541
- [duration]="220"
12542
- [class]="_itemClass()">
12543
- <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">
12544
- {{ item.label }}
12545
- </span>
12546
- <button clx-button type="button" shape="circle" [iconOnly]="true" [icon]="item.icon"
12547
- variant="light" [color]="_color()" [size]="_itemSize()" class="shadow-md"
12548
- [attr.aria-label]="item.label"
12549
- (click)="_onItemClick(item)">
12550
- </button>
12551
- </div>
12434
+ <button clx-button type="button" shape="circle" [iconOnly]="true" [icon]="item.icon"
12435
+ variant="solid" [color]="item.color ?? _color()" [size]="_itemSize()" class="shadow-md"
12436
+ clxAnimate="slideInUp" trigger="onEnter" [delay]="i * 60" [duration]="220"
12437
+ [clxTooltip]="item.label" clxTooltipPosition="right"
12438
+ [attr.aria-label]="item.label"
12439
+ (click)="_onItemClick(item)">
12440
+ </button>
12552
12441
  }
12553
12442
  </div>
12554
12443
  </ng-template>
12555
- `, 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 });
12444
+ `, 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"] }, { kind: "directive", type: ClxTooltipDirective, selector: "[clxTooltip]", inputs: ["clxTooltip", "clxTooltipPosition", "clxTooltipColor", "clxTooltipSize", "clxTooltipDelay"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
12556
12445
  }
12557
12446
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxFabComponent, decorators: [{
12558
12447
  type: Component,
12559
12448
  args: [{
12560
12449
  selector: 'clx-fab',
12561
12450
  standalone: true,
12562
- imports: [OverlayModule, ClxButtonComponent, ClxAnimateDirective],
12451
+ imports: [OverlayModule, ClxButtonComponent, ClxAnimateDirective, ClxTooltipDirective],
12563
12452
  template: `
12564
- <!-- ── Trigger (this wrapper owns the fixed positioning + drag; the button inside stays a plain clx-button) ── -->
12565
- <div
12453
+ <!-- ── Trigger, fixed to the bottom-right corner (offset configurable via position()) ── -->
12454
+ <button
12566
12455
  #origin="cdkOverlayOrigin"
12567
12456
  cdkOverlayOrigin
12568
- class="fixed z-40 select-none"
12457
+ clx-button
12458
+ type="button"
12459
+ class="fixed z-40"
12460
+ [variant]="variant()"
12461
+ shape="circle"
12462
+ [iconOnly]="true"
12463
+ [icon]="_isOpen() ? 'close' : icon()"
12464
+ [color]="_color()"
12465
+ [size]="size()"
12466
+ [class]="_triggerClass()"
12569
12467
  [style.right.px]="_position().right"
12570
12468
  [style.bottom.px]="_position().bottom"
12571
- [style.touchAction]="'none'"
12572
- (pointerdown)="_onPointerDown($event)">
12573
- <button
12574
- clx-button
12575
- type="button"
12576
- [variant]="variant()"
12577
- shape="circle"
12578
- [iconOnly]="true"
12579
- [icon]="_isOpen() ? 'close' : icon()"
12580
- [color]="_color()"
12581
- [size]="size()"
12582
- [class]="_triggerClass()"
12583
- [attr.aria-label]="triggerLabel()"
12584
- [attr.aria-expanded]="_isOpen()"
12585
- (click)="_onTriggerClick()">
12586
- </button>
12587
- </div>
12469
+ [attr.aria-label]="triggerLabel()"
12470
+ [attr.aria-expanded]="_isOpen()"
12471
+ (click)="_toggle()">
12472
+ </button>
12588
12473
 
12589
- <!-- ── Overlay panel: stack expanding toward expandDirection() ────────────────── -->
12474
+ <!-- ── Overlay panel: accordion-style stack expanding upward from the trigger ── -->
12590
12475
  <ng-template
12591
12476
  cdkConnectedOverlay
12592
12477
  [cdkConnectedOverlayOrigin]="origin"
12593
12478
  [cdkConnectedOverlayOpen]="_isOpen()"
12594
- [cdkConnectedOverlayPositions]="_positions()"
12479
+ [cdkConnectedOverlayPositions]="_positions"
12595
12480
  [cdkConnectedOverlayScrollStrategy]="_scrollStrategy"
12596
12481
  [cdkConnectedOverlayPush]="true"
12597
12482
  (overlayOutsideClick)="_close()"
12598
12483
  (overlayKeydown)="_onKeydown($event)">
12599
12484
 
12600
- <div [class]="_stackClass()" role="menu">
12485
+ <div class="flex flex-col items-center gap-2 mb-2" role="menu">
12601
12486
  @for (item of items(); track item.key; let i = $index) {
12602
- <div
12603
- [clxAnimate]="_itemAnimation()"
12604
- trigger="onEnter"
12605
- [delay]="i * 60"
12606
- [duration]="220"
12607
- [class]="_itemClass()">
12608
- <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">
12609
- {{ item.label }}
12610
- </span>
12611
- <button clx-button type="button" shape="circle" [iconOnly]="true" [icon]="item.icon"
12612
- variant="light" [color]="_color()" [size]="_itemSize()" class="shadow-md"
12613
- [attr.aria-label]="item.label"
12614
- (click)="_onItemClick(item)">
12615
- </button>
12616
- </div>
12487
+ <button clx-button type="button" shape="circle" [iconOnly]="true" [icon]="item.icon"
12488
+ variant="solid" [color]="item.color ?? _color()" [size]="_itemSize()" class="shadow-md"
12489
+ clxAnimate="slideInUp" trigger="onEnter" [delay]="i * 60" [duration]="220"
12490
+ [clxTooltip]="item.label" clxTooltipPosition="right"
12491
+ [attr.aria-label]="item.label"
12492
+ (click)="_onItemClick(item)">
12493
+ </button>
12617
12494
  }
12618
12495
  </div>
12619
12496
  </ng-template>
@@ -12621,7 +12498,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
12621
12498
  encapsulation: ViewEncapsulation.None,
12622
12499
  changeDetection: ChangeDetectionStrategy.OnPush,
12623
12500
  }]
12624
- }], 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 }] }], expandDirection: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandDirection", required: false }] }], itemClick: [{ type: i0.Output, args: ["itemClick"] }], positionChange: [{ type: i0.Output, args: ["positionChange"] }] } });
12501
+ }], 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 }] }], itemClick: [{ type: i0.Output, args: ["itemClick"] }] } });
12625
12502
 
12626
12503
  // ── Base classes ─────────────────────────────────────────────────────────────
12627
12504
  const TABLE_BASE_CLASS = 'w-full text-left border-collapse text-sm';