@cdevhub/ngx-tw 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +78 -15
- package/fesm2022/cdevhub-ngx-tw-accordion.mjs +16 -5
- package/fesm2022/cdevhub-ngx-tw-accordion.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-avatar.mjs +26 -15
- package/fesm2022/cdevhub-ngx-tw-avatar.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-badge.mjs +17 -5
- package/fesm2022/cdevhub-ngx-tw-badge.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs +27 -6
- package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-button.mjs +23 -11
- package/fesm2022/cdevhub-ngx-tw-button.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs +5 -5
- package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-calendar-testing.mjs +3 -3
- package/fesm2022/cdevhub-ngx-tw-calendar-testing.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-calendar.mjs +427 -122
- package/fesm2022/cdevhub-ngx-tw-calendar.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-card.mjs +21 -11
- package/fesm2022/cdevhub-ngx-tw-card.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-carousel.mjs +215 -96
- package/fesm2022/cdevhub-ngx-tw-carousel.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-checkbox.mjs +108 -64
- package/fesm2022/cdevhub-ngx-tw-checkbox.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-code-block.mjs +18 -6
- package/fesm2022/cdevhub-ngx-tw-code-block.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-collapsible.mjs +55 -30
- package/fesm2022/cdevhub-ngx-tw-collapsible.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-combobox-testing.mjs +218 -0
- package/fesm2022/cdevhub-ngx-tw-combobox-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-combobox.mjs +236 -211
- package/fesm2022/cdevhub-ngx-tw-combobox.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-command-palette-testing.mjs +200 -0
- package/fesm2022/cdevhub-ngx-tw-command-palette-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-command-palette.mjs +34 -7
- package/fesm2022/cdevhub-ngx-tw-command-palette.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-core.mjs +135 -15
- package/fesm2022/cdevhub-ngx-tw-core.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-date-picker-testing.mjs +203 -0
- package/fesm2022/cdevhub-ngx-tw-date-picker-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-date-picker.mjs +160 -102
- package/fesm2022/cdevhub-ngx-tw-date-picker.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-date-range-picker-testing.mjs +209 -0
- package/fesm2022/cdevhub-ngx-tw-date-range-picker-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs +182 -107
- package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-dialog-testing.mjs +122 -0
- package/fesm2022/cdevhub-ngx-tw-dialog-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-dialog.mjs +11 -2
- package/fesm2022/cdevhub-ngx-tw-dialog.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-empty-state.mjs +1 -1
- package/fesm2022/cdevhub-ngx-tw-empty-state.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-file-upload-testing.mjs +149 -0
- package/fesm2022/cdevhub-ngx-tw-file-upload-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-file-upload.mjs +57 -67
- package/fesm2022/cdevhub-ngx-tw-file-upload.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-flip-card.mjs +42 -24
- package/fesm2022/cdevhub-ngx-tw-flip-card.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-form-field.mjs +114 -21
- package/fesm2022/cdevhub-ngx-tw-form-field.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-icon.mjs +16 -6
- package/fesm2022/cdevhub-ngx-tw-icon.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-input.mjs +52 -61
- package/fesm2022/cdevhub-ngx-tw-input.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-item.mjs +18 -3
- package/fesm2022/cdevhub-ngx-tw-item.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-menu-testing.mjs +168 -0
- package/fesm2022/cdevhub-ngx-tw-menu-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-menu.mjs +58 -21
- package/fesm2022/cdevhub-ngx-tw-menu.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-number-input.mjs +34 -1
- package/fesm2022/cdevhub-ngx-tw-number-input.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-paginator.mjs +95 -45
- package/fesm2022/cdevhub-ngx-tw-paginator.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-popover.mjs +81 -32
- package/fesm2022/cdevhub-ngx-tw-popover.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs +1 -1
- package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-radio.mjs +131 -98
- package/fesm2022/cdevhub-ngx-tw-radio.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs +207 -42
- package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-select-testing.mjs +165 -0
- package/fesm2022/cdevhub-ngx-tw-select-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-select.mjs +386 -210
- package/fesm2022/cdevhub-ngx-tw-select.mjs.map +1 -1
- package/fesm2022/{cdevhub-ngx-tw-sheet-sheet-renderer-ByyNluUd.mjs → cdevhub-ngx-tw-sheet-sheet-renderer-CqVJwgmp.mjs} +3 -3
- package/fesm2022/cdevhub-ngx-tw-sheet-sheet-renderer-CqVJwgmp.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-sheet-testing.mjs +129 -0
- package/fesm2022/cdevhub-ngx-tw-sheet-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-sheet.mjs +23 -7
- package/fesm2022/cdevhub-ngx-tw-sheet.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-slider.mjs +89 -54
- package/fesm2022/cdevhub-ngx-tw-slider.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-sort.mjs +122 -17
- package/fesm2022/cdevhub-ngx-tw-sort.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-split.mjs +72 -19
- package/fesm2022/cdevhub-ngx-tw-split.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-stat.mjs +63 -25
- package/fesm2022/cdevhub-ngx-tw-stat.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-stepper.mjs +35 -8
- package/fesm2022/cdevhub-ngx-tw-stepper.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-switch.mjs +54 -48
- package/fesm2022/cdevhub-ngx-tw-switch.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs +12 -15
- package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-table.mjs +74 -13
- package/fesm2022/cdevhub-ngx-tw-table.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-tabs.mjs +84 -30
- package/fesm2022/cdevhub-ngx-tw-tabs.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-tags-input-testing.mjs +172 -0
- package/fesm2022/cdevhub-ngx-tw-tags-input-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-tags-input.mjs +107 -71
- package/fesm2022/cdevhub-ngx-tw-tags-input.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-textarea.mjs +41 -9
- package/fesm2022/cdevhub-ngx-tw-textarea.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-theme.mjs +257 -45
- package/fesm2022/cdevhub-ngx-tw-theme.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-time-picker-testing.mjs +201 -0
- package/fesm2022/cdevhub-ngx-tw-time-picker-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-time-picker.mjs +184 -77
- package/fesm2022/cdevhub-ngx-tw-time-picker.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-timeline.mjs +110 -27
- package/fesm2022/cdevhub-ngx-tw-timeline.mjs.map +1 -1
- package/fesm2022/{cdevhub-ngx-tw-toast-toast-renderer-DSu4YoTy.mjs → cdevhub-ngx-tw-toast-toast-renderer-BlDxemsU.mjs} +107 -19
- package/fesm2022/cdevhub-ngx-tw-toast-toast-renderer-BlDxemsU.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-toast.mjs +21 -13
- package/fesm2022/cdevhub-ngx-tw-toast.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-tooltip.mjs +102 -15
- package/fesm2022/cdevhub-ngx-tw-tooltip.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-transfer-testing.mjs +219 -0
- package/fesm2022/cdevhub-ngx-tw-transfer-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-transfer.mjs +88 -69
- package/fesm2022/cdevhub-ngx-tw-transfer.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-tree.mjs +68 -19
- package/fesm2022/cdevhub-ngx-tw-tree.mjs.map +1 -1
- package/index.json +1 -1
- package/package.json +63 -2
- package/theme/_base.css +13 -0
- package/theme/_dark.css +110 -36
- package/theme/_high-contrast-dark.css +367 -0
- package/theme/_high-contrast.css +13 -2
- package/theme/_light.css +276 -0
- package/theme/_semantic.css +47 -12
- package/theme/_typography.css +17 -0
- package/theme/index.css +86 -7
- package/types/cdevhub-ngx-tw-accordion.d.ts +12 -4
- package/types/cdevhub-ngx-tw-avatar.d.ts +10 -3
- package/types/cdevhub-ngx-tw-button.d.ts +1 -0
- package/types/cdevhub-ngx-tw-calendar-luxon.d.ts +2 -2
- package/types/cdevhub-ngx-tw-calendar-testing.d.ts +1 -1
- package/types/cdevhub-ngx-tw-calendar.d.ts +179 -73
- package/types/cdevhub-ngx-tw-card.d.ts +11 -3
- package/types/cdevhub-ngx-tw-carousel.d.ts +89 -20
- package/types/cdevhub-ngx-tw-checkbox.d.ts +40 -12
- package/types/cdevhub-ngx-tw-code-block.d.ts +11 -2
- package/types/cdevhub-ngx-tw-collapsible.d.ts +32 -5
- package/types/cdevhub-ngx-tw-combobox-testing.d.ts +157 -0
- package/types/cdevhub-ngx-tw-combobox.d.ts +94 -53
- package/types/cdevhub-ngx-tw-command-palette-testing.d.ts +136 -0
- package/types/cdevhub-ngx-tw-command-palette.d.ts +33 -5
- package/types/cdevhub-ngx-tw-core.d.ts +152 -21
- package/types/cdevhub-ngx-tw-date-picker-testing.d.ts +141 -0
- package/types/cdevhub-ngx-tw-date-picker.d.ts +37 -29
- package/types/cdevhub-ngx-tw-date-range-picker-testing.d.ts +148 -0
- package/types/cdevhub-ngx-tw-date-range-picker.d.ts +36 -29
- package/types/cdevhub-ngx-tw-dialog-testing.d.ts +98 -0
- package/types/cdevhub-ngx-tw-dialog.d.ts +12 -3
- package/types/cdevhub-ngx-tw-file-upload-testing.d.ts +120 -0
- package/types/cdevhub-ngx-tw-file-upload.d.ts +8 -10
- package/types/cdevhub-ngx-tw-flip-card.d.ts +18 -11
- package/types/cdevhub-ngx-tw-form-field.d.ts +19 -2
- package/types/cdevhub-ngx-tw-icon.d.ts +3 -3
- package/types/cdevhub-ngx-tw-input.d.ts +5 -8
- package/types/cdevhub-ngx-tw-item.d.ts +2 -0
- package/types/cdevhub-ngx-tw-menu-testing.d.ts +131 -0
- package/types/cdevhub-ngx-tw-menu.d.ts +2 -2
- package/types/cdevhub-ngx-tw-number-input.d.ts +20 -0
- package/types/cdevhub-ngx-tw-paginator.d.ts +58 -24
- package/types/cdevhub-ngx-tw-popover.d.ts +41 -10
- package/types/cdevhub-ngx-tw-progress-bar.d.ts +1 -1
- package/types/cdevhub-ngx-tw-radio.d.ts +68 -25
- package/types/cdevhub-ngx-tw-segmented-control.d.ts +79 -16
- package/types/cdevhub-ngx-tw-select-testing.d.ts +114 -0
- package/types/cdevhub-ngx-tw-select.d.ts +104 -33
- package/types/cdevhub-ngx-tw-sheet-testing.d.ts +104 -0
- package/types/cdevhub-ngx-tw-sheet.d.ts +19 -3
- package/types/cdevhub-ngx-tw-slider.d.ts +79 -25
- package/types/cdevhub-ngx-tw-sort.d.ts +45 -4
- package/types/cdevhub-ngx-tw-split.d.ts +32 -2
- package/types/cdevhub-ngx-tw-stat.d.ts +14 -4
- package/types/cdevhub-ngx-tw-stepper.d.ts +16 -2
- package/types/cdevhub-ngx-tw-switch.d.ts +35 -13
- package/types/cdevhub-ngx-tw-tab-nav.d.ts +7 -6
- package/types/cdevhub-ngx-tw-table.d.ts +53 -10
- package/types/cdevhub-ngx-tw-tabs.d.ts +41 -10
- package/types/cdevhub-ngx-tw-tags-input-testing.d.ts +135 -0
- package/types/cdevhub-ngx-tw-tags-input.d.ts +26 -11
- package/types/cdevhub-ngx-tw-textarea.d.ts +3 -2
- package/types/cdevhub-ngx-tw-theme.d.ts +245 -39
- package/types/cdevhub-ngx-tw-time-picker-testing.d.ts +129 -0
- package/types/cdevhub-ngx-tw-time-picker.d.ts +76 -19
- package/types/cdevhub-ngx-tw-timeline.d.ts +36 -12
- package/types/cdevhub-ngx-tw-toast.d.ts +20 -6
- package/types/cdevhub-ngx-tw-tooltip.d.ts +28 -6
- package/types/cdevhub-ngx-tw-transfer-testing.d.ts +152 -0
- package/types/cdevhub-ngx-tw-transfer.d.ts +21 -8
- package/types/cdevhub-ngx-tw-tree.d.ts +6 -1
- package/fesm2022/cdevhub-ngx-tw-sheet-sheet-renderer-ByyNluUd.mjs.map +0 -1
- package/fesm2022/cdevhub-ngx-tw-toast-toast-renderer-DSu4YoTy.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cdevhub-ngx-tw-tooltip.mjs","sources":["../../../projects/ngx-tw/tooltip/tooltip.ts","../../../projects/ngx-tw/tooltip/cdevhub-ngx-tw-tooltip.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n DestroyRef,\n Directive,\n effect,\n ElementRef,\n inject,\n input,\n output,\n signal,\n TemplateRef,\n} from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport {\n type ConnectedPosition,\n Overlay,\n type OverlayRef,\n} from '@angular/cdk/overlay';\nimport { ComponentPortal } from '@angular/cdk/portal';\nimport { AriaDescriber } from '@angular/cdk/a11y';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { tv } from 'tailwind-variants';\nimport type { TwColor, TwSize } from '@cdevhub/ngx-tw/core';\n\n/** Placement position of the tooltip relative to its trigger element. */\nexport type TooltipPosition =\n | 'top'\n | 'top-start'\n | 'top-end'\n | 'bottom'\n | 'bottom-start'\n | 'bottom-end'\n | 'left'\n | 'left-start'\n | 'left-end'\n | 'right'\n | 'right-start'\n | 'right-end';\n\n/** Direction the arrow points toward (derived from resolved overlay position). */\ntype ArrowDirection = 'top' | 'bottom' | 'left' | 'right';\n\n// ── Variant config ──\n\nconst tooltipVariants = tv(\n {\n slots: {\n wrapper: 'relative pointer-events-none',\n panel: 'rounded-md shadow-md',\n arrow: 'absolute size-2 rotate-45',\n },\n variants: {\n color: {\n primary: {\n panel: 'bg-primary-700 text-on-primary',\n arrow: 'bg-primary-700',\n },\n secondary: {\n panel: 'bg-secondary-700 text-on-secondary',\n arrow: 'bg-secondary-700',\n },\n accent: {\n panel: 'bg-accent-700 text-on-accent',\n arrow: 'bg-accent-700',\n },\n neutral: {\n wrapper: 'drop-shadow-[0_0_0.5px_var(--color-border)] drop-shadow-sm',\n panel: 'bg-surface-overlay text-fg',\n arrow: 'bg-surface-overlay',\n },\n info: {\n panel: 'bg-info-700 text-on-info',\n arrow: 'bg-info-700',\n },\n success: {\n panel: 'bg-success-700 text-on-success',\n arrow: 'bg-success-700',\n },\n warning: {\n panel: 'bg-warning-700 text-on-warning',\n arrow: 'bg-warning-700',\n },\n error: {\n panel: 'bg-error-700 text-on-error',\n arrow: 'bg-error-700',\n },\n },\n size: {\n xs: {\n panel: 'px-1.5 py-0.5 text-2xs max-w-40',\n },\n sm: {\n panel: 'px-2 py-1 text-xs max-w-48',\n },\n md: {\n panel: 'px-3 py-1.5 text-sm max-w-xs',\n },\n lg: {\n panel: 'px-4 py-2 text-sm max-w-sm',\n },\n xl: {\n panel: 'px-4 py-2 text-base max-w-md',\n },\n },\n },\n defaultVariants: {\n color: 'neutral',\n size: 'md',\n },\n },\n { twMerge: true },\n);\n\n// ── Position mappings ──\n\nconst POSITION_MAP: Record<TooltipPosition, ConnectedPosition> = {\n top: {\n originX: 'center',\n originY: 'top',\n overlayX: 'center',\n overlayY: 'bottom',\n offsetY: -8,\n },\n 'top-start': {\n originX: 'start',\n originY: 'top',\n overlayX: 'start',\n overlayY: 'bottom',\n offsetY: -8,\n },\n 'top-end': {\n originX: 'end',\n originY: 'top',\n overlayX: 'end',\n overlayY: 'bottom',\n offsetY: -8,\n },\n bottom: {\n originX: 'center',\n originY: 'bottom',\n overlayX: 'center',\n overlayY: 'top',\n offsetY: 8,\n },\n 'bottom-start': {\n originX: 'start',\n originY: 'bottom',\n overlayX: 'start',\n overlayY: 'top',\n offsetY: 8,\n },\n 'bottom-end': {\n originX: 'end',\n originY: 'bottom',\n overlayX: 'end',\n overlayY: 'top',\n offsetY: 8,\n },\n left: {\n originX: 'start',\n originY: 'center',\n overlayX: 'end',\n overlayY: 'center',\n offsetX: -8,\n },\n 'left-start': {\n originX: 'start',\n originY: 'top',\n overlayX: 'end',\n overlayY: 'top',\n offsetX: -8,\n },\n 'left-end': {\n originX: 'start',\n originY: 'bottom',\n overlayX: 'end',\n overlayY: 'bottom',\n offsetX: -8,\n },\n right: {\n originX: 'end',\n originY: 'center',\n overlayX: 'start',\n overlayY: 'center',\n offsetX: 8,\n },\n 'right-start': {\n originX: 'end',\n originY: 'top',\n overlayX: 'start',\n overlayY: 'top',\n offsetX: 8,\n },\n 'right-end': {\n originX: 'end',\n originY: 'bottom',\n overlayX: 'start',\n overlayY: 'bottom',\n offsetX: 8,\n },\n};\n\nconst FALLBACK_ORDER: Record<string, TooltipPosition[]> = {\n top: ['bottom', 'left', 'right'],\n bottom: ['top', 'left', 'right'],\n left: ['right', 'top', 'bottom'],\n right: ['left', 'top', 'bottom'],\n};\n\nfunction buildPositions(preferred: TooltipPosition): ConnectedPosition[] {\n const primary = preferred.split('-')[0];\n const positions = [POSITION_MAP[preferred]];\n const fallbacks = FALLBACK_ORDER[primary] ?? FALLBACK_ORDER['top'];\n for (const fb of fallbacks) {\n positions.push(POSITION_MAP[fb]);\n }\n return positions;\n}\n\nfunction resolveArrowDirection(position: ConnectedPosition): ArrowDirection {\n if (position.overlayY === 'bottom') return 'bottom';\n if (position.overlayY === 'top') return 'top';\n if (position.overlayX === 'end') return 'right';\n return 'left';\n}\n\n/** Arrow position classes keyed by which side the arrow sits on. */\nconst ARROW_POSITION_CLASSES: Record<ArrowDirection, string> = {\n bottom: 'left-1/2 -translate-x-1/2 bottom-0 translate-y-1/2',\n top: 'left-1/2 -translate-x-1/2 top-0 -translate-y-1/2',\n right: 'top-1/2 -translate-y-1/2 right-0 translate-x-1/2',\n left: 'top-1/2 -translate-y-1/2 left-0 -translate-x-1/2',\n};\n\n// ── Internal overlay component (not exported) ──\n\nlet nextTooltipId = 0;\n\n@Component({\n selector: 'tw-tooltip-overlay',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n role: 'tooltip',\n '[id]': 'id',\n '[animate.enter]': '\"fade-in\"',\n '[animate.leave]': '\"fade-out\"',\n },\n imports: [NgTemplateOutlet],\n template: `\n <div [class]=\"wrapperClasses()\">\n <div [class]=\"panelClasses()\">\n @if (isTemplate()) {\n <ng-container *ngTemplateOutlet=\"templateContent()\" />\n } @else {\n {{ textContent() }}\n }\n </div>\n @if (showArrow()) {\n <span [class]=\"arrowClasses()\" aria-hidden=\"true\"></span>\n }\n </div>\n `,\n})\nclass TooltipOverlayComponent {\n readonly id = `tw-tooltip-${nextTooltipId++}`;\n\n readonly content = signal<string | TemplateRef<void>>('');\n readonly color = signal<TwColor>('neutral');\n readonly size = signal<TwSize>('md');\n readonly showArrow = signal(true);\n readonly arrowDirection = signal<ArrowDirection>('bottom');\n readonly panelClass = signal<string>('');\n\n readonly isTemplate = computed(\n () => this.content() instanceof TemplateRef,\n );\n readonly templateContent = computed(\n () => this.content() as TemplateRef<void>,\n );\n readonly textContent = computed(() => this.content() as string);\n\n private readonly variantResult = computed(() =>\n tooltipVariants({ color: this.color(), size: this.size() }),\n );\n\n readonly wrapperClasses = computed(() => this.variantResult().wrapper());\n readonly panelClasses = computed(() => {\n const consumer = this.panelClass();\n return this.variantResult().panel({ class: consumer });\n });\n readonly arrowClasses = computed(() => {\n const base = this.variantResult().arrow();\n const position = ARROW_POSITION_CLASSES[this.arrowDirection()];\n return `${base} ${position}`;\n });\n}\n\n// ── Tooltip directive ──\n\n@Directive({\n selector: '[twTooltip]',\n exportAs: 'twTooltip',\n host: {\n '(mouseenter)': 'onMouseEnter()',\n '(mouseleave)': 'onMouseLeave()',\n '(focusin)': 'onFocusIn()',\n '(focusout)': 'onFocusOut()',\n '(keydown.escape)': 'onEscape()',\n '(touchstart)': 'onTouchStart()',\n '(touchend)': 'onTouchEnd()',\n },\n})\nexport class TooltipDirective {\n /** The tooltip content. Strings render as text; TemplateRef renders via ngTemplateOutlet. */\n readonly twTooltip = input.required<string | TemplateRef<void>>();\n\n /** Preferred placement relative to the trigger. CDK handles fallback. Defaults to `'top'`. */\n readonly twTooltipPosition = input<TooltipPosition>('top');\n\n /** Semantic color palette for the tooltip. Defaults to `'neutral'`. */\n readonly twTooltipColor = input<TwColor>('neutral');\n\n /** Controls padding, font size, and maximum width. Defaults to `'md'`. */\n readonly twTooltipSize = input<TwSize>('md');\n\n /**\n * Milliseconds to wait before showing after trigger. Defaults to `200` — an\n * intent threshold: the trigger must be held long enough that the user reads\n * as \"wants the tooltip\" rather than a passing graze with the pointer.\n */\n readonly twTooltipShowDelay = input(200);\n\n /**\n * Milliseconds to wait before hiding after trigger ends. Defaults to `0`\n * (immediate dismiss). The asymmetry with `twTooltipShowDelay` is\n * intentional — show is gated to filter noise, hide is instant so the\n * tooltip never lingers over content the user has moved on from.\n */\n readonly twTooltipHideDelay = input(0);\n\n /** When true, tooltip never shows. Defaults to `false`. */\n readonly twTooltipDisabled = input(false);\n\n // Arrows reinforce the visual association between the floating panel and its trigger\n // and match every other ngx-tw overlay (popover/menu); opt-out is for compact iconic\n // contexts only.\n /** When true, renders an arrow pointing to the trigger. Defaults to `true`. */\n readonly twTooltipArrow = input(true);\n\n /** Optional class string (space-separated) merged into the panel slot for consumer customization. */\n readonly twTooltipPanelClass = input<string>('');\n\n /** Fires when the tooltip becomes visible. */\n readonly twTooltipShown = output<void>();\n\n /** Fires when the tooltip is fully hidden. */\n readonly twTooltipHidden = output<void>();\n\n private readonly overlay = inject(Overlay);\n private readonly elementRef = inject(ElementRef<HTMLElement>);\n private readonly destroyRef = inject(DestroyRef);\n // CDK `AriaDescriber` owns a single hidden message-container on the document\n // and dedupes identical description strings — if two tooltips on the same\n // trigger advertise the same message, only one `aria-describedby` id is\n // appended. Mirrors the `sort-header` pattern.\n private readonly ariaDescriber = inject(AriaDescriber, { optional: true });\n\n private overlayRef: OverlayRef | null = null;\n private tooltipInstance: TooltipOverlayComponent | null = null;\n private showTimer: ReturnType<typeof setTimeout> | null = null;\n private hideTimer: ReturnType<typeof setTimeout> | null = null;\n /** Last description string handed to `AriaDescriber.describe` — required so the symmetrical `removeDescription` call passes the same key. */\n private _describedBy: string | null = null;\n /** True when the trigger's `aria-describedby` was set directly to the overlay id (TemplateRef fallback path); used by `removeAriaDescription` to choose the symmetrical teardown. */\n private _templateDescribedBy = false;\n\n constructor() {\n // Hide immediately when disabled changes to true\n effect(() => {\n if (this.twTooltipDisabled()) {\n this.detach();\n }\n });\n\n this.destroyRef.onDestroy(() => {\n this.clearTimers();\n this.removeAriaDescription();\n this.disposeOverlay();\n });\n }\n\n /** Programmatically show the tooltip. */\n show(): void {\n if (this.twTooltipDisabled() || !this.twTooltip()) return;\n this.clearTimers();\n this.showTimer = setTimeout(\n () => this.createAndShow(),\n this.twTooltipShowDelay(),\n );\n }\n\n /** Programmatically hide the tooltip. */\n hide(): void {\n this.clearTimers();\n this.hideTimer = setTimeout(\n () => this.detach(),\n this.twTooltipHideDelay(),\n );\n }\n\n /** Toggle tooltip visibility. */\n toggle(): void {\n if (this.tooltipInstance) {\n this.hide();\n } else {\n this.show();\n }\n }\n\n // ── Host event handlers ──\n\n protected onMouseEnter(): void {\n this.show();\n }\n\n protected onMouseLeave(): void {\n this.hide();\n }\n\n protected onFocusIn(): void {\n this.show();\n }\n\n protected onFocusOut(): void {\n this.hide();\n }\n\n protected onEscape(): void {\n if (this.tooltipInstance) {\n this.detach();\n }\n }\n\n protected onTouchStart(): void {\n this.show();\n }\n\n protected onTouchEnd(): void {\n this.hide();\n }\n\n // ── Private ──\n\n private createAndShow(): void {\n if (this.tooltipInstance) {\n this.updateTooltip();\n this.applyAriaDescription();\n return;\n }\n\n this.createOverlay();\n const portal = new ComponentPortal(TooltipOverlayComponent);\n const componentRef = this.overlayRef!.attach(portal);\n this.tooltipInstance = componentRef.instance;\n\n this.updateTooltip();\n this.applyAriaDescription();\n\n this.twTooltipShown.emit();\n }\n\n private createOverlay(): void {\n if (this.overlayRef) return;\n\n const positions = buildPositions(this.twTooltipPosition());\n const positionStrategy = this.overlay\n .position()\n .flexibleConnectedTo(this.elementRef)\n .withPositions(positions)\n .withPush(true)\n .withViewportMargin(8);\n\n this.overlayRef = this.overlay.create({\n positionStrategy,\n // Close on ancestor scroll — tooltips are transient and should not chase a\n // moving trigger across a scrolling viewport.\n scrollStrategy: this.overlay.scrollStrategies.close(),\n panelClass: 'tw-tooltip-panel',\n });\n\n positionStrategy.positionChanges\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe((change) => {\n if (this.tooltipInstance) {\n const dir = resolveArrowDirection(change.connectionPair);\n this.tooltipInstance.arrowDirection.set(dir);\n }\n });\n }\n\n private updateTooltip(): void {\n if (!this.tooltipInstance) return;\n this.tooltipInstance.content.set(this.twTooltip());\n this.tooltipInstance.color.set(this.twTooltipColor());\n this.tooltipInstance.size.set(this.twTooltipSize());\n this.tooltipInstance.showArrow.set(this.twTooltipArrow());\n this.tooltipInstance.panelClass.set(this.twTooltipPanelClass());\n }\n\n private detach(): void {\n this.clearTimers();\n if (this.overlayRef?.hasAttached()) {\n this.overlayRef.detach();\n }\n if (this.tooltipInstance) {\n this.removeAriaDescription();\n this.tooltipInstance = null;\n this.twTooltipHidden.emit();\n }\n }\n\n /**\n * Push the current tooltip content as an `aria-describedby` link on the\n * trigger element. Dual-mode wiring:\n *\n * - **String content**: routed through CDK `AriaDescriber.describe`, which\n * maintains a single hidden message-container on the document and dedupes\n * identical strings across all describers.\n * - **TemplateRef content**: AriaDescriber's dedup table is keyed by string,\n * so we fall back to a direct `setAttribute('aria-describedby', overlayId)`\n * pointing at the `role=\"tooltip\"` overlay. Without this fallback,\n * assistive tech would have no description link for templated tooltip\n * content.\n *\n * `_describedBy` tracks the string handed to `AriaDescriber`;\n * `_templateDescribedBy` is `true` when the fallback path is active so\n * `removeAriaDescription` can take the symmetrical teardown branch.\n */\n private applyAriaDescription(): void {\n const el = this.elementRef.nativeElement;\n const content = this.twTooltip();\n\n if (typeof content === 'string' && content.length > 0 && this.ariaDescriber) {\n // If we previously wired the template fallback (rare — content can swap\n // at runtime), tear it down before swapping to the describer path.\n if (this._templateDescribedBy) {\n el.removeAttribute('aria-describedby');\n this._templateDescribedBy = false;\n }\n if (this._describedBy && this._describedBy !== content) {\n this.ariaDescriber.removeDescription(el, this._describedBy);\n this._describedBy = null;\n }\n if (this._describedBy === content) return;\n this.ariaDescriber.describe(el, content);\n this._describedBy = content;\n return;\n }\n\n // Template / non-string fallback.\n if (this._describedBy && this.ariaDescriber) {\n this.ariaDescriber.removeDescription(el, this._describedBy);\n this._describedBy = null;\n }\n if (this.tooltipInstance) {\n el.setAttribute('aria-describedby', this.tooltipInstance.id);\n this._templateDescribedBy = true;\n }\n }\n\n private removeAriaDescription(): void {\n const el = this.elementRef.nativeElement;\n if (this._describedBy && this.ariaDescriber) {\n this.ariaDescriber.removeDescription(el, this._describedBy);\n this._describedBy = null;\n }\n if (this._templateDescribedBy) {\n el.removeAttribute('aria-describedby');\n this._templateDescribedBy = false;\n }\n }\n\n private disposeOverlay(): void {\n if (this.overlayRef) {\n this.overlayRef.dispose();\n this.overlayRef = null;\n }\n this.tooltipInstance = null;\n }\n\n private clearTimers(): void {\n if (this.showTimer !== null) {\n clearTimeout(this.showTimer);\n this.showTimer = null;\n }\n if (this.hideTimer !== null) {\n clearTimeout(this.hideTimer);\n this.hideTimer = null;\n }\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;;;AA4CA;AAEA,MAAM,eAAe,GAAG,EAAE,CACxB;AACE,IAAA,KAAK,EAAE;AACL,QAAA,OAAO,EAAE,8BAA8B;AACvC,QAAA,KAAK,EAAE,sBAAsB;AAC7B,QAAA,KAAK,EAAE,2BAA2B;AACnC,KAAA;AACD,IAAA,QAAQ,EAAE;AACR,QAAA,KAAK,EAAE;AACL,YAAA,OAAO,EAAE;AACP,gBAAA,KAAK,EAAE,gCAAgC;AACvC,gBAAA,KAAK,EAAE,gBAAgB;AACxB,aAAA;AACD,YAAA,SAAS,EAAE;AACT,gBAAA,KAAK,EAAE,oCAAoC;AAC3C,gBAAA,KAAK,EAAE,kBAAkB;AAC1B,aAAA;AACD,YAAA,MAAM,EAAE;AACN,gBAAA,KAAK,EAAE,8BAA8B;AACrC,gBAAA,KAAK,EAAE,eAAe;AACvB,aAAA;AACD,YAAA,OAAO,EAAE;AACP,gBAAA,OAAO,EAAE,4DAA4D;AACrE,gBAAA,KAAK,EAAE,4BAA4B;AACnC,gBAAA,KAAK,EAAE,oBAAoB;AAC5B,aAAA;AACD,YAAA,IAAI,EAAE;AACJ,gBAAA,KAAK,EAAE,0BAA0B;AACjC,gBAAA,KAAK,EAAE,aAAa;AACrB,aAAA;AACD,YAAA,OAAO,EAAE;AACP,gBAAA,KAAK,EAAE,gCAAgC;AACvC,gBAAA,KAAK,EAAE,gBAAgB;AACxB,aAAA;AACD,YAAA,OAAO,EAAE;AACP,gBAAA,KAAK,EAAE,gCAAgC;AACvC,gBAAA,KAAK,EAAE,gBAAgB;AACxB,aAAA;AACD,YAAA,KAAK,EAAE;AACL,gBAAA,KAAK,EAAE,4BAA4B;AACnC,gBAAA,KAAK,EAAE,cAAc;AACtB,aAAA;AACF,SAAA;AACD,QAAA,IAAI,EAAE;AACJ,YAAA,EAAE,EAAE;AACF,gBAAA,KAAK,EAAE,iCAAiC;AACzC,aAAA;AACD,YAAA,EAAE,EAAE;AACF,gBAAA,KAAK,EAAE,4BAA4B;AACpC,aAAA;AACD,YAAA,EAAE,EAAE;AACF,gBAAA,KAAK,EAAE,8BAA8B;AACtC,aAAA;AACD,YAAA,EAAE,EAAE;AACF,gBAAA,KAAK,EAAE,4BAA4B;AACpC,aAAA;AACD,YAAA,EAAE,EAAE;AACF,gBAAA,KAAK,EAAE,8BAA8B;AACtC,aAAA;AACF,SAAA;AACF,KAAA;AACD,IAAA,eAAe,EAAE;AACf,QAAA,KAAK,EAAE,SAAS;AAChB,QAAA,IAAI,EAAE,IAAI;AACX,KAAA;AACF,CAAA,EACD,EAAE,OAAO,EAAE,IAAI,EAAE,CAClB;AAED;AAEA,MAAM,YAAY,GAA+C;AAC/D,IAAA,GAAG,EAAE;AACH,QAAA,OAAO,EAAE,QAAQ;AACjB,QAAA,OAAO,EAAE,KAAK;AACd,QAAA,QAAQ,EAAE,QAAQ;AAClB,QAAA,QAAQ,EAAE,QAAQ;QAClB,OAAO,EAAE,CAAC,CAAC;AACZ,KAAA;AACD,IAAA,WAAW,EAAE;AACX,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,OAAO,EAAE,KAAK;AACd,QAAA,QAAQ,EAAE,OAAO;AACjB,QAAA,QAAQ,EAAE,QAAQ;QAClB,OAAO,EAAE,CAAC,CAAC;AACZ,KAAA;AACD,IAAA,SAAS,EAAE;AACT,QAAA,OAAO,EAAE,KAAK;AACd,QAAA,OAAO,EAAE,KAAK;AACd,QAAA,QAAQ,EAAE,KAAK;AACf,QAAA,QAAQ,EAAE,QAAQ;QAClB,OAAO,EAAE,CAAC,CAAC;AACZ,KAAA;AACD,IAAA,MAAM,EAAE;AACN,QAAA,OAAO,EAAE,QAAQ;AACjB,QAAA,OAAO,EAAE,QAAQ;AACjB,QAAA,QAAQ,EAAE,QAAQ;AAClB,QAAA,QAAQ,EAAE,KAAK;AACf,QAAA,OAAO,EAAE,CAAC;AACX,KAAA;AACD,IAAA,cAAc,EAAE;AACd,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,OAAO,EAAE,QAAQ;AACjB,QAAA,QAAQ,EAAE,OAAO;AACjB,QAAA,QAAQ,EAAE,KAAK;AACf,QAAA,OAAO,EAAE,CAAC;AACX,KAAA;AACD,IAAA,YAAY,EAAE;AACZ,QAAA,OAAO,EAAE,KAAK;AACd,QAAA,OAAO,EAAE,QAAQ;AACjB,QAAA,QAAQ,EAAE,KAAK;AACf,QAAA,QAAQ,EAAE,KAAK;AACf,QAAA,OAAO,EAAE,CAAC;AACX,KAAA;AACD,IAAA,IAAI,EAAE;AACJ,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,OAAO,EAAE,QAAQ;AACjB,QAAA,QAAQ,EAAE,KAAK;AACf,QAAA,QAAQ,EAAE,QAAQ;QAClB,OAAO,EAAE,CAAC,CAAC;AACZ,KAAA;AACD,IAAA,YAAY,EAAE;AACZ,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,OAAO,EAAE,KAAK;AACd,QAAA,QAAQ,EAAE,KAAK;AACf,QAAA,QAAQ,EAAE,KAAK;QACf,OAAO,EAAE,CAAC,CAAC;AACZ,KAAA;AACD,IAAA,UAAU,EAAE;AACV,QAAA,OAAO,EAAE,OAAO;AAChB,QAAA,OAAO,EAAE,QAAQ;AACjB,QAAA,QAAQ,EAAE,KAAK;AACf,QAAA,QAAQ,EAAE,QAAQ;QAClB,OAAO,EAAE,CAAC,CAAC;AACZ,KAAA;AACD,IAAA,KAAK,EAAE;AACL,QAAA,OAAO,EAAE,KAAK;AACd,QAAA,OAAO,EAAE,QAAQ;AACjB,QAAA,QAAQ,EAAE,OAAO;AACjB,QAAA,QAAQ,EAAE,QAAQ;AAClB,QAAA,OAAO,EAAE,CAAC;AACX,KAAA;AACD,IAAA,aAAa,EAAE;AACb,QAAA,OAAO,EAAE,KAAK;AACd,QAAA,OAAO,EAAE,KAAK;AACd,QAAA,QAAQ,EAAE,OAAO;AACjB,QAAA,QAAQ,EAAE,KAAK;AACf,QAAA,OAAO,EAAE,CAAC;AACX,KAAA;AACD,IAAA,WAAW,EAAE;AACX,QAAA,OAAO,EAAE,KAAK;AACd,QAAA,OAAO,EAAE,QAAQ;AACjB,QAAA,QAAQ,EAAE,OAAO;AACjB,QAAA,QAAQ,EAAE,QAAQ;AAClB,QAAA,OAAO,EAAE,CAAC;AACX,KAAA;CACF;AAED,MAAM,cAAc,GAAsC;AACxD,IAAA,GAAG,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC;AAChC,IAAA,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC;AAChC,IAAA,IAAI,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC;AAChC,IAAA,KAAK,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC;CACjC;AAED,SAAS,cAAc,CAAC,SAA0B,EAAA;IAChD,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;IAC3C,MAAM,SAAS,GAAG,cAAc,CAAC,OAAO,CAAC,IAAI,cAAc,CAAC,KAAK,CAAC;AAClE,IAAA,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE;QAC1B,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IAClC;AACA,IAAA,OAAO,SAAS;AAClB;AAEA,SAAS,qBAAqB,CAAC,QAA2B,EAAA;AACxD,IAAA,IAAI,QAAQ,CAAC,QAAQ,KAAK,QAAQ;AAAE,QAAA,OAAO,QAAQ;AACnD,IAAA,IAAI,QAAQ,CAAC,QAAQ,KAAK,KAAK;AAAE,QAAA,OAAO,KAAK;AAC7C,IAAA,IAAI,QAAQ,CAAC,QAAQ,KAAK,KAAK;AAAE,QAAA,OAAO,OAAO;AAC/C,IAAA,OAAO,MAAM;AACf;AAEA;AACA,MAAM,sBAAsB,GAAmC;AAC7D,IAAA,MAAM,EAAE,oDAAoD;AAC5D,IAAA,GAAG,EAAE,kDAAkD;AACvD,IAAA,KAAK,EAAE,kDAAkD;AACzD,IAAA,IAAI,EAAE,kDAAkD;CACzD;AAED;AAEA,IAAI,aAAa,GAAG,CAAC;AAErB,MAyBM,uBAAuB,CAAA;AAClB,IAAA,EAAE,GAAG,CAAA,WAAA,EAAc,aAAa,EAAE,EAAE;IAEpC,OAAO,GAAG,MAAM,CAA6B,EAAE;gFAAC;IAChD,KAAK,GAAG,MAAM,CAAU,SAAS;8EAAC;IAClC,IAAI,GAAG,MAAM,CAAS,IAAI;6EAAC;IAC3B,SAAS,GAAG,MAAM,CAAC,IAAI;kFAAC;IACxB,cAAc,GAAG,MAAM,CAAiB,QAAQ;uFAAC;IACjD,UAAU,GAAG,MAAM,CAAS,EAAE;mFAAC;IAE/B,UAAU,GAAG,QAAQ,CAC5B,MAAM,IAAI,CAAC,OAAO,EAAE,YAAY,WAAW;mFAC5C;IACQ,eAAe,GAAG,QAAQ,CACjC,MAAM,IAAI,CAAC,OAAO,EAAuB;wFAC1C;IACQ,WAAW,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,EAAY;oFAAC;IAE9C,aAAa,GAAG,QAAQ,CAAC,MACxC,eAAe,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;sFAC5D;AAEQ,IAAA,cAAc,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC,OAAO,EAAE;uFAAC;AAC/D,IAAA,YAAY,GAAG,QAAQ,CAAC,MAAK;AACpC,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAE;AAClC,QAAA,OAAO,IAAI,CAAC,aAAa,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;IACxD,CAAC;qFAAC;AACO,IAAA,YAAY,GAAG,QAAQ,CAAC,MAAK;QACpC,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE;QACzC,MAAM,QAAQ,GAAG,sBAAsB,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;AAC9D,QAAA,OAAO,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,QAAQ,EAAE;IAC9B,CAAC;qFAAC;uGA/BE,uBAAuB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAvB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,uBAAuB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,oBAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,MAAA,EAAA,SAAA,EAAA,EAAA,UAAA,EAAA,EAAA,IAAA,EAAA,IAAA,EAAA,eAAA,EAAA,aAAA,EAAA,eAAA,EAAA,cAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAfjB;;;;;;;;;;;;;AAaT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAdS,gBAAgB,EAAA,QAAA,EAAA,oBAAA,EAAA,MAAA,EAAA,CAAA,yBAAA,EAAA,kBAAA,EAAA,0BAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAgBtB,uBAAuB,EAAA,UAAA,EAAA,CAAA;kBAzB5B,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,oBAAoB;oBAC9B,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAC/C,oBAAA,IAAI,EAAE;AACJ,wBAAA,IAAI,EAAE,SAAS;AACf,wBAAA,MAAM,EAAE,IAAI;AACZ,wBAAA,iBAAiB,EAAE,WAAW;AAC9B,wBAAA,iBAAiB,EAAE,YAAY;AAChC,qBAAA;oBACD,OAAO,EAAE,CAAC,gBAAgB,CAAC;AAC3B,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;AAaT,EAAA,CAAA;AACF,iBAAA;;AAmCD;MAea,gBAAgB,CAAA;;IAElB,SAAS,GAAG,KAAK,CAAC,QAAQ;kFAA8B;;IAGxD,iBAAiB,GAAG,KAAK,CAAkB,KAAK;0FAAC;;IAGjD,cAAc,GAAG,KAAK,CAAU,SAAS;uFAAC;;IAG1C,aAAa,GAAG,KAAK,CAAS,IAAI;sFAAC;AAE5C;;;;AAIG;IACM,kBAAkB,GAAG,KAAK,CAAC,GAAG;2FAAC;AAExC;;;;;AAKG;IACM,kBAAkB,GAAG,KAAK,CAAC,CAAC;2FAAC;;IAG7B,iBAAiB,GAAG,KAAK,CAAC,KAAK;0FAAC;;;;;IAMhC,cAAc,GAAG,KAAK,CAAC,IAAI;uFAAC;;IAG5B,mBAAmB,GAAG,KAAK,CAAS,EAAE;4FAAC;;IAGvC,cAAc,GAAG,MAAM,EAAQ;;IAG/B,eAAe,GAAG,MAAM,EAAQ;AAExB,IAAA,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;AACzB,IAAA,UAAU,GAAG,MAAM,EAAC,UAAuB,EAAC;AAC5C,IAAA,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;;;;;IAK/B,aAAa,GAAG,MAAM,CAAC,aAAa,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAElE,UAAU,GAAsB,IAAI;IACpC,eAAe,GAAmC,IAAI;IACtD,SAAS,GAAyC,IAAI;IACtD,SAAS,GAAyC,IAAI;;IAEtD,YAAY,GAAkB,IAAI;;IAElC,oBAAoB,GAAG,KAAK;AAEpC,IAAA,WAAA,GAAA;;QAEE,MAAM,CAAC,MAAK;AACV,YAAA,IAAI,IAAI,CAAC,iBAAiB,EAAE,EAAE;gBAC5B,IAAI,CAAC,MAAM,EAAE;YACf;AACF,QAAA,CAAC,CAAC;AAEF,QAAA,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,MAAK;YAC7B,IAAI,CAAC,WAAW,EAAE;YAClB,IAAI,CAAC,qBAAqB,EAAE;YAC5B,IAAI,CAAC,cAAc,EAAE;AACvB,QAAA,CAAC,CAAC;IACJ;;IAGA,IAAI,GAAA;QACF,IAAI,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;YAAE;QACnD,IAAI,CAAC,WAAW,EAAE;AAClB,QAAA,IAAI,CAAC,SAAS,GAAG,UAAU,CACzB,MAAM,IAAI,CAAC,aAAa,EAAE,EAC1B,IAAI,CAAC,kBAAkB,EAAE,CAC1B;IACH;;IAGA,IAAI,GAAA;QACF,IAAI,CAAC,WAAW,EAAE;AAClB,QAAA,IAAI,CAAC,SAAS,GAAG,UAAU,CACzB,MAAM,IAAI,CAAC,MAAM,EAAE,EACnB,IAAI,CAAC,kBAAkB,EAAE,CAC1B;IACH;;IAGA,MAAM,GAAA;AACJ,QAAA,IAAI,IAAI,CAAC,eAAe,EAAE;YACxB,IAAI,CAAC,IAAI,EAAE;QACb;aAAO;YACL,IAAI,CAAC,IAAI,EAAE;QACb;IACF;;IAIU,YAAY,GAAA;QACpB,IAAI,CAAC,IAAI,EAAE;IACb;IAEU,YAAY,GAAA;QACpB,IAAI,CAAC,IAAI,EAAE;IACb;IAEU,SAAS,GAAA;QACjB,IAAI,CAAC,IAAI,EAAE;IACb;IAEU,UAAU,GAAA;QAClB,IAAI,CAAC,IAAI,EAAE;IACb;IAEU,QAAQ,GAAA;AAChB,QAAA,IAAI,IAAI,CAAC,eAAe,EAAE;YACxB,IAAI,CAAC,MAAM,EAAE;QACf;IACF;IAEU,YAAY,GAAA;QACpB,IAAI,CAAC,IAAI,EAAE;IACb;IAEU,UAAU,GAAA;QAClB,IAAI,CAAC,IAAI,EAAE;IACb;;IAIQ,aAAa,GAAA;AACnB,QAAA,IAAI,IAAI,CAAC,eAAe,EAAE;YACxB,IAAI,CAAC,aAAa,EAAE;YACpB,IAAI,CAAC,oBAAoB,EAAE;YAC3B;QACF;QAEA,IAAI,CAAC,aAAa,EAAE;AACpB,QAAA,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,uBAAuB,CAAC;QAC3D,MAAM,YAAY,GAAG,IAAI,CAAC,UAAW,CAAC,MAAM,CAAC,MAAM,CAAC;AACpD,QAAA,IAAI,CAAC,eAAe,GAAG,YAAY,CAAC,QAAQ;QAE5C,IAAI,CAAC,aAAa,EAAE;QACpB,IAAI,CAAC,oBAAoB,EAAE;AAE3B,QAAA,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE;IAC5B;IAEQ,aAAa,GAAA;QACnB,IAAI,IAAI,CAAC,UAAU;YAAE;QAErB,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC;AAC1D,QAAA,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAC3B,aAAA,QAAQ;AACR,aAAA,mBAAmB,CAAC,IAAI,CAAC,UAAU;aACnC,aAAa,CAAC,SAAS;aACvB,QAAQ,CAAC,IAAI;aACb,kBAAkB,CAAC,CAAC,CAAC;QAExB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;YACpC,gBAAgB;;;YAGhB,cAAc,EAAE,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,KAAK,EAAE;AACrD,YAAA,UAAU,EAAE,kBAAkB;AAC/B,SAAA,CAAC;AAEF,QAAA,gBAAgB,CAAC;AACd,aAAA,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,UAAU,CAAC;AACxC,aAAA,SAAS,CAAC,CAAC,MAAM,KAAI;AACpB,YAAA,IAAI,IAAI,CAAC,eAAe,EAAE;gBACxB,MAAM,GAAG,GAAG,qBAAqB,CAAC,MAAM,CAAC,cAAc,CAAC;gBACxD,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC;YAC9C;AACF,QAAA,CAAC,CAAC;IACN;IAEQ,aAAa,GAAA;QACnB,IAAI,CAAC,IAAI,CAAC,eAAe;YAAE;AAC3B,QAAA,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;AAClD,QAAA,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;AACrD,QAAA,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;AACnD,QAAA,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;AACzD,QAAA,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC;IACjE;IAEQ,MAAM,GAAA;QACZ,IAAI,CAAC,WAAW,EAAE;AAClB,QAAA,IAAI,IAAI,CAAC,UAAU,EAAE,WAAW,EAAE,EAAE;AAClC,YAAA,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE;QAC1B;AACA,QAAA,IAAI,IAAI,CAAC,eAAe,EAAE;YACxB,IAAI,CAAC,qBAAqB,EAAE;AAC5B,YAAA,IAAI,CAAC,eAAe,GAAG,IAAI;AAC3B,YAAA,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE;QAC7B;IACF;AAEA;;;;;;;;;;;;;;;;AAgBG;IACK,oBAAoB,GAAA;AAC1B,QAAA,MAAM,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa;AACxC,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE;AAEhC,QAAA,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,aAAa,EAAE;;;AAG3E,YAAA,IAAI,IAAI,CAAC,oBAAoB,EAAE;AAC7B,gBAAA,EAAE,CAAC,eAAe,CAAC,kBAAkB,CAAC;AACtC,gBAAA,IAAI,CAAC,oBAAoB,GAAG,KAAK;YACnC;YACA,IAAI,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,YAAY,KAAK,OAAO,EAAE;gBACtD,IAAI,CAAC,aAAa,CAAC,iBAAiB,CAAC,EAAE,EAAE,IAAI,CAAC,YAAY,CAAC;AAC3D,gBAAA,IAAI,CAAC,YAAY,GAAG,IAAI;YAC1B;AACA,YAAA,IAAI,IAAI,CAAC,YAAY,KAAK,OAAO;gBAAE;YACnC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;AACxC,YAAA,IAAI,CAAC,YAAY,GAAG,OAAO;YAC3B;QACF;;QAGA,IAAI,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,aAAa,EAAE;YAC3C,IAAI,CAAC,aAAa,CAAC,iBAAiB,CAAC,EAAE,EAAE,IAAI,CAAC,YAAY,CAAC;AAC3D,YAAA,IAAI,CAAC,YAAY,GAAG,IAAI;QAC1B;AACA,QAAA,IAAI,IAAI,CAAC,eAAe,EAAE;YACxB,EAAE,CAAC,YAAY,CAAC,kBAAkB,EAAE,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC;AAC5D,YAAA,IAAI,CAAC,oBAAoB,GAAG,IAAI;QAClC;IACF;IAEQ,qBAAqB,GAAA;AAC3B,QAAA,MAAM,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa;QACxC,IAAI,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,aAAa,EAAE;YAC3C,IAAI,CAAC,aAAa,CAAC,iBAAiB,CAAC,EAAE,EAAE,IAAI,CAAC,YAAY,CAAC;AAC3D,YAAA,IAAI,CAAC,YAAY,GAAG,IAAI;QAC1B;AACA,QAAA,IAAI,IAAI,CAAC,oBAAoB,EAAE;AAC7B,YAAA,EAAE,CAAC,eAAe,CAAC,kBAAkB,CAAC;AACtC,YAAA,IAAI,CAAC,oBAAoB,GAAG,KAAK;QACnC;IACF;IAEQ,cAAc,GAAA;AACpB,QAAA,IAAI,IAAI,CAAC,UAAU,EAAE;AACnB,YAAA,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE;AACzB,YAAA,IAAI,CAAC,UAAU,GAAG,IAAI;QACxB;AACA,QAAA,IAAI,CAAC,eAAe,GAAG,IAAI;IAC7B;IAEQ,WAAW,GAAA;AACjB,QAAA,IAAI,IAAI,CAAC,SAAS,KAAK,IAAI,EAAE;AAC3B,YAAA,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC;AAC5B,YAAA,IAAI,CAAC,SAAS,GAAG,IAAI;QACvB;AACA,QAAA,IAAI,IAAI,CAAC,SAAS,KAAK,IAAI,EAAE;AAC3B,YAAA,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC;AAC5B,YAAA,IAAI,CAAC,SAAS,GAAG,IAAI;QACvB;IACF;uGA/RW,gBAAgB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAAhB,gBAAgB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,EAAA,iBAAA,EAAA,mBAAA,EAAA,UAAA,EAAA,mBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,gBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,aAAA,EAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,UAAA,EAAA,eAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,kBAAA,EAAA,EAAA,iBAAA,EAAA,oBAAA,EAAA,UAAA,EAAA,oBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,kBAAA,EAAA,EAAA,iBAAA,EAAA,oBAAA,EAAA,UAAA,EAAA,oBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,EAAA,iBAAA,EAAA,mBAAA,EAAA,UAAA,EAAA,mBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,gBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,mBAAA,EAAA,EAAA,iBAAA,EAAA,qBAAA,EAAA,UAAA,EAAA,qBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,cAAA,EAAA,gBAAA,EAAA,eAAA,EAAA,iBAAA,EAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,YAAA,EAAA,gBAAA,EAAA,YAAA,EAAA,gBAAA,EAAA,SAAA,EAAA,aAAA,EAAA,UAAA,EAAA,cAAA,EAAA,gBAAA,EAAA,YAAA,EAAA,YAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,cAAA,EAAA,EAAA,EAAA,QAAA,EAAA,CAAA,WAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA;;2FAAhB,gBAAgB,EAAA,UAAA,EAAA,CAAA;kBAb5B,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,aAAa;AACvB,oBAAA,QAAQ,EAAE,WAAW;AACrB,oBAAA,IAAI,EAAE;AACJ,wBAAA,cAAc,EAAE,gBAAgB;AAChC,wBAAA,cAAc,EAAE,gBAAgB;AAChC,wBAAA,WAAW,EAAE,aAAa;AAC1B,wBAAA,YAAY,EAAE,cAAc;AAC5B,wBAAA,kBAAkB,EAAE,YAAY;AAChC,wBAAA,cAAc,EAAE,gBAAgB;AAChC,wBAAA,YAAY,EAAE,cAAc;AAC7B,qBAAA;AACF,iBAAA;;;ACzTD;;AAEG;;;;"}
|
|
1
|
+
{"version":3,"file":"cdevhub-ngx-tw-tooltip.mjs","sources":["../../../projects/ngx-tw/tooltip/tooltip.ts","../../../projects/ngx-tw/tooltip/cdevhub-ngx-tw-tooltip.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n DestroyRef,\n Directive,\n effect,\n ElementRef,\n inject,\n input,\n output,\n signal,\n TemplateRef,\n} from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport {\n type ConnectedPosition,\n type FlexibleConnectedPositionStrategy,\n Overlay,\n type OverlayRef,\n} from '@angular/cdk/overlay';\nimport { ESCAPE, hasModifierKey } from '@angular/cdk/keycodes';\nimport { ComponentPortal } from '@angular/cdk/portal';\nimport { AriaDescriber } from '@angular/cdk/a11y';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { tv } from 'tailwind-variants';\nimport type { TwColor, TwSize } from '@cdevhub/ngx-tw/core';\n\n/** Placement position of the tooltip relative to its trigger element. */\nexport type TooltipPosition =\n | 'top'\n | 'top-start'\n | 'top-end'\n | 'bottom'\n | 'bottom-start'\n | 'bottom-end'\n | 'left'\n | 'left-start'\n | 'left-end'\n | 'right'\n | 'right-start'\n | 'right-end';\n\n/** Direction the arrow points toward (derived from resolved overlay position). */\ntype ArrowDirection = 'top' | 'bottom' | 'left' | 'right';\n\n// ── Variant config ──\n\nconst tooltipVariants = tv(\n {\n slots: {\n // No `pointer-events-none`: WCAG 2.1 SC 1.4.13 requires hover content to\n // be *hoverable* — the pointer must be able to travel from the trigger\n // onto the tooltip without dismissing it. The directive re-arms the hide\n // timer on the panel's own `mouseleave`, so the panel is only pointer-\n // opaque for as long as the user is actually pointing at it.\n wrapper: 'relative',\n panel: 'rounded-md shadow-md',\n arrow: 'absolute size-2 rotate-45',\n },\n variants: {\n color: {\n primary: {\n panel: 'bg-primary-700 text-on-primary',\n arrow: 'bg-primary-700',\n },\n secondary: {\n panel: 'bg-secondary-700 text-on-secondary',\n arrow: 'bg-secondary-700',\n },\n accent: {\n panel: 'bg-accent-700 text-on-accent',\n arrow: 'bg-accent-700',\n },\n neutral: {\n wrapper: 'drop-shadow-[0_0_0.5px_var(--color-border)] drop-shadow-sm',\n panel: 'bg-surface-overlay text-fg',\n arrow: 'bg-surface-overlay',\n },\n info: {\n panel: 'bg-info-700 text-on-info',\n arrow: 'bg-info-700',\n },\n success: {\n panel: 'bg-success-700 text-on-success',\n arrow: 'bg-success-700',\n },\n warning: {\n panel: 'bg-warning-700 text-on-warning',\n arrow: 'bg-warning-700',\n },\n error: {\n panel: 'bg-error-700 text-on-error',\n arrow: 'bg-error-700',\n },\n },\n size: {\n xs: {\n panel: 'px-1.5 py-0.5 text-2xs max-w-40',\n },\n sm: {\n panel: 'px-2 py-1 text-xs max-w-48',\n },\n md: {\n panel: 'px-3 py-1.5 text-sm max-w-xs',\n },\n lg: {\n panel: 'px-4 py-2 text-sm max-w-sm',\n },\n xl: {\n panel: 'px-4 py-2 text-base max-w-md',\n },\n },\n },\n defaultVariants: {\n color: 'neutral',\n size: 'md',\n },\n },\n { twMerge: true },\n);\n\n// ── Position mappings ──\n\nconst POSITION_MAP: Record<TooltipPosition, ConnectedPosition> = {\n top: {\n originX: 'center',\n originY: 'top',\n overlayX: 'center',\n overlayY: 'bottom',\n offsetY: -8,\n },\n 'top-start': {\n originX: 'start',\n originY: 'top',\n overlayX: 'start',\n overlayY: 'bottom',\n offsetY: -8,\n },\n 'top-end': {\n originX: 'end',\n originY: 'top',\n overlayX: 'end',\n overlayY: 'bottom',\n offsetY: -8,\n },\n bottom: {\n originX: 'center',\n originY: 'bottom',\n overlayX: 'center',\n overlayY: 'top',\n offsetY: 8,\n },\n 'bottom-start': {\n originX: 'start',\n originY: 'bottom',\n overlayX: 'start',\n overlayY: 'top',\n offsetY: 8,\n },\n 'bottom-end': {\n originX: 'end',\n originY: 'bottom',\n overlayX: 'end',\n overlayY: 'top',\n offsetY: 8,\n },\n left: {\n originX: 'start',\n originY: 'center',\n overlayX: 'end',\n overlayY: 'center',\n offsetX: -8,\n },\n 'left-start': {\n originX: 'start',\n originY: 'top',\n overlayX: 'end',\n overlayY: 'top',\n offsetX: -8,\n },\n 'left-end': {\n originX: 'start',\n originY: 'bottom',\n overlayX: 'end',\n overlayY: 'bottom',\n offsetX: -8,\n },\n right: {\n originX: 'end',\n originY: 'center',\n overlayX: 'start',\n overlayY: 'center',\n offsetX: 8,\n },\n 'right-start': {\n originX: 'end',\n originY: 'top',\n overlayX: 'start',\n overlayY: 'top',\n offsetX: 8,\n },\n 'right-end': {\n originX: 'end',\n originY: 'bottom',\n overlayX: 'start',\n overlayY: 'bottom',\n offsetX: 8,\n },\n};\n\nconst FALLBACK_ORDER: Record<string, TooltipPosition[]> = {\n top: ['bottom', 'left', 'right'],\n bottom: ['top', 'left', 'right'],\n left: ['right', 'top', 'bottom'],\n right: ['left', 'top', 'bottom'],\n};\n\nfunction buildPositions(preferred: TooltipPosition): ConnectedPosition[] {\n const primary = preferred.split('-')[0];\n const positions = [POSITION_MAP[preferred]];\n const fallbacks = FALLBACK_ORDER[primary] ?? FALLBACK_ORDER['top'];\n for (const fb of fallbacks) {\n positions.push(POSITION_MAP[fb]);\n }\n return positions;\n}\n\nfunction resolveArrowDirection(position: ConnectedPosition): ArrowDirection {\n if (position.overlayY === 'bottom') return 'bottom';\n if (position.overlayY === 'top') return 'top';\n if (position.overlayX === 'end') return 'right';\n return 'left';\n}\n\n/** Arrow position classes keyed by which side the arrow sits on. */\nconst ARROW_POSITION_CLASSES: Record<ArrowDirection, string> = {\n bottom: 'left-1/2 -translate-x-1/2 bottom-0 translate-y-1/2',\n top: 'left-1/2 -translate-x-1/2 top-0 -translate-y-1/2',\n right: 'top-1/2 -translate-y-1/2 right-0 translate-x-1/2',\n left: 'top-1/2 -translate-y-1/2 left-0 -translate-x-1/2',\n};\n\n// ── Internal overlay component (not exported) ──\n\nlet nextTooltipId = 0;\n\n@Component({\n selector: 'tw-tooltip-overlay',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n role: 'tooltip',\n '[id]': 'id',\n '[animate.enter]': '\"fade-in\"',\n '[animate.leave]': '\"fade-out\"',\n },\n imports: [NgTemplateOutlet],\n template: `\n <div [class]=\"wrapperClasses()\">\n <div [class]=\"panelClasses()\">\n @if (isTemplate()) {\n <ng-container *ngTemplateOutlet=\"templateContent()\" />\n } @else {\n {{ textContent() }}\n }\n </div>\n @if (showArrow()) {\n <span [class]=\"arrowClasses()\" aria-hidden=\"true\"></span>\n }\n </div>\n `,\n})\nclass TooltipOverlayComponent {\n readonly id = `tw-tooltip-${nextTooltipId++}`;\n\n readonly content = signal<string | TemplateRef<void>>('');\n readonly color = signal<TwColor>('neutral');\n readonly size = signal<TwSize>('md');\n readonly showArrow = signal(true);\n readonly arrowDirection = signal<ArrowDirection>('bottom');\n readonly panelClass = signal<string>('');\n\n readonly isTemplate = computed(\n () => this.content() instanceof TemplateRef,\n );\n readonly templateContent = computed(\n () => this.content() as TemplateRef<void>,\n );\n readonly textContent = computed(() => this.content() as string);\n\n private readonly variantResult = computed(() =>\n tooltipVariants({ color: this.color(), size: this.size() }),\n );\n\n readonly wrapperClasses = computed(() => this.variantResult().wrapper());\n readonly panelClasses = computed(() => {\n const consumer = this.panelClass();\n return this.variantResult().panel({ class: consumer });\n });\n readonly arrowClasses = computed(() => {\n const base = this.variantResult().arrow();\n const position = ARROW_POSITION_CLASSES[this.arrowDirection()];\n return `${base} ${position}`;\n });\n}\n\n// ── Tooltip directive ──\n\n@Directive({\n selector: '[twTooltip]',\n exportAs: 'twTooltip',\n host: {\n // Static marker so the directive is locatable in tests and by consumers.\n // Its own selector is not usable for that: `[twTooltip]` takes a required\n // `TemplateRef`, so it is ALWAYS property-bound and Angular emits no\n // attribute for a bound input. Material solves this with a class\n // (`.mat-mdc-menu-trigger`); `data-tw-*` is this repo's existing convention\n // (see `data-tw-table-loading`, `data-tw-sort-arrow`) and carries no styling.\n 'data-tw-tooltip-trigger': '',\n '(mouseenter)': 'onMouseEnter()',\n '(mouseleave)': 'onMouseLeave()',\n '(focusin)': 'onFocusIn()',\n '(focusout)': 'onFocusOut()',\n '(keydown.escape)': 'onEscape()',\n '(touchstart)': 'onTouchStart()',\n '(touchend)': 'onTouchEnd()',\n },\n})\nexport class TooltipDirective {\n /** The tooltip content. Strings render as text; TemplateRef renders via ngTemplateOutlet. */\n readonly twTooltip = input.required<string | TemplateRef<void>>();\n\n /** Preferred placement relative to the trigger. CDK handles fallback. Defaults to `'top'`. */\n readonly twTooltipPosition = input<TooltipPosition>('top');\n\n /** Semantic color palette for the tooltip. Defaults to `'neutral'`. */\n readonly twTooltipColor = input<TwColor>('neutral');\n\n /** Controls padding, font size, and maximum width. Defaults to `'md'`. */\n readonly twTooltipSize = input<TwSize>('md');\n\n /**\n * Milliseconds to wait before showing after trigger. Defaults to `200` — an\n * intent threshold: the trigger must be held long enough that the user reads\n * as \"wants the tooltip\" rather than a passing graze with the pointer.\n */\n readonly twTooltipShowDelay = input(200);\n\n /**\n * Milliseconds to wait before hiding after the trigger is left. Defaults to\n * `150` — a grace period, not a lingering delay: WCAG 2.1 SC 1.4.13 requires\n * the tooltip to be hoverable, and the panel sits 8px clear of its trigger,\n * so the pointer needs a window in which to cross that gap. Hovering the\n * panel itself cancels the pending hide entirely. Set `0` to opt out (the\n * tooltip is then dismissible by Escape but not reachable by pointer).\n */\n readonly twTooltipHideDelay = input(150);\n\n /** When true, tooltip never shows. Defaults to `false`. */\n readonly twTooltipDisabled = input(false);\n\n /** When true, renders an arrow pointing to the trigger. Defaults to `true` — arrows reinforce the visual association between the floating panel and its trigger and match every other ngx-tw overlay (popover, menu); the special case is a compact iconic context. */\n readonly twTooltipArrow = input(true);\n\n /** Optional class string (space-separated) merged into the panel slot for consumer customization. Defaults to an empty string. */\n readonly twTooltipPanelClass = input<string>('');\n\n /** Fires when the tooltip becomes visible. */\n readonly twTooltipShown = output<void>();\n\n /** Fires when the tooltip is fully hidden. */\n readonly twTooltipHidden = output<void>();\n\n private readonly overlay = inject(Overlay);\n private readonly elementRef = inject(ElementRef<HTMLElement>);\n private readonly destroyRef = inject(DestroyRef);\n // CDK `AriaDescriber` owns a single hidden message-container on the document\n // and dedupes identical description strings — if two tooltips on the same\n // trigger advertise the same message, only one `aria-describedby` id is\n // appended. Mirrors the `sort-header` pattern.\n private readonly ariaDescriber = inject(AriaDescriber, { optional: true });\n\n private overlayRef: OverlayRef | null = null;\n /**\n * The live position strategy. Held as a field so every show can re-apply\n * `twTooltipPosition` onto it — see `applyPositions`.\n */\n private positionStrategy: FlexibleConnectedPositionStrategy | null = null;\n /** The `twTooltipPosition` value currently baked into `positionStrategy`. */\n private appliedPosition: TooltipPosition | null = null;\n private tooltipInstance: TooltipOverlayComponent | null = null;\n private showTimer: ReturnType<typeof setTimeout> | null = null;\n private hideTimer: ReturnType<typeof setTimeout> | null = null;\n /** Removes the panel's hover listeners. Set in `createOverlay`, invoked from `disposeOverlay`. */\n private overlayHoverCleanup: (() => void) | null = null;\n /** Last description string handed to `AriaDescriber.describe` — required so the symmetrical `removeDescription` call passes the same key. */\n private _describedBy: string | null = null;\n /** True when the trigger's `aria-describedby` was set directly to the overlay id (TemplateRef fallback path); used by `removeAriaDescription` to choose the symmetrical teardown. */\n private _templateDescribedBy = false;\n\n constructor() {\n // Hide immediately when disabled changes to true\n effect(() => {\n if (this.twTooltipDisabled()) {\n this.detach();\n }\n });\n\n this.destroyRef.onDestroy(() => {\n this.clearTimers();\n this.removeAriaDescription();\n this.disposeOverlay();\n });\n }\n\n /** Programmatically show the tooltip. */\n show(): void {\n if (this.twTooltipDisabled() || !this.twTooltip()) return;\n this.clearTimers();\n this.showTimer = setTimeout(\n () => this.createAndShow(),\n this.twTooltipShowDelay(),\n );\n }\n\n /** Programmatically hide the tooltip. */\n hide(): void {\n this.clearTimers();\n this.hideTimer = setTimeout(\n () => this.detach(),\n this.twTooltipHideDelay(),\n );\n }\n\n /** Toggle tooltip visibility. */\n toggle(): void {\n if (this.tooltipInstance) {\n this.hide();\n } else {\n this.show();\n }\n }\n\n // ── Host event handlers ──\n\n protected onMouseEnter(): void {\n this.show();\n }\n\n protected onMouseLeave(): void {\n this.hide();\n }\n\n protected onFocusIn(): void {\n this.show();\n }\n\n protected onFocusOut(): void {\n this.hide();\n }\n\n protected onEscape(): void {\n if (this.tooltipInstance) {\n this.detach();\n }\n }\n\n protected onTouchStart(): void {\n this.show();\n }\n\n protected onTouchEnd(): void {\n this.hide();\n }\n\n // ── Private ──\n\n private createAndShow(): void {\n // Called before the `tooltipInstance` check so that a tooltip already on\n // screen also picks up a changed `twTooltipPosition`.\n this.createOverlay();\n\n if (this.tooltipInstance) {\n this.updateTooltip();\n this.applyAriaDescription();\n return;\n }\n\n const portal = new ComponentPortal(TooltipOverlayComponent);\n const componentRef = this.overlayRef!.attach(portal);\n this.tooltipInstance = componentRef.instance;\n\n this.updateTooltip();\n this.applyAriaDescription();\n\n this.twTooltipShown.emit();\n }\n\n private createOverlay(): void {\n if (this.overlayRef) {\n // The OverlayRef is built once per directive lifetime (hiding only\n // detaches), so `twTooltipPosition` has to be re-applied on every show or\n // a binding like `[twTooltipPosition]=\"isMobile() ? 'bottom' : 'right'\"`\n // stays frozen at whatever it read on the first hover.\n this.applyPositions();\n return;\n }\n\n this.appliedPosition = this.twTooltipPosition();\n const positions = buildPositions(this.appliedPosition);\n const positionStrategy = this.overlay\n .position()\n .flexibleConnectedTo(this.elementRef)\n .withPositions(positions)\n .withPush(true)\n .withViewportMargin(8);\n this.positionStrategy = positionStrategy;\n\n this.overlayRef = this.overlay.create({\n positionStrategy,\n // Close on ancestor scroll — tooltips are transient and should not chase a\n // moving trigger across a scrolling viewport.\n scrollStrategy: this.overlay.scrollStrategies.close(),\n panelClass: 'tw-tooltip-panel',\n });\n\n positionStrategy.positionChanges\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe((change) => {\n if (this.tooltipInstance) {\n const dir = resolveArrowDirection(change.connectionPair);\n this.tooltipInstance.arrowDirection.set(dir);\n }\n });\n\n // SC 1.4.13 \"Dismissible\": Escape must dismiss the tooltip wherever focus\n // currently is, not only when the trigger itself has it — a tooltip shown\n // by hover while focus sits in an unrelated field was previously\n // undismissable without moving the pointer. CDK's OverlayKeyboardDispatcher\n // listens on `body` and forwards keydowns to the top-most attached overlay\n // with subscribers, which is this tooltip whenever it is showing. The\n // trigger's own `(keydown.escape)` binding stays as the direct path; the\n // second `detach()` is a no-op.\n this.overlayRef\n .keydownEvents()\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe((event) => {\n if (event.keyCode === ESCAPE && !hasModifierKey(event)) {\n this.detach();\n }\n });\n\n // SC 1.4.13 \"Hoverable\" / \"Persistent\": entering the panel cancels the\n // pending hide so the tooltip survives the trip across the 8px offset;\n // leaving it re-arms the hide exactly as leaving the trigger does. Wired\n // on the overlay element rather than the portal component because this\n // element outlives every attach/detach cycle of a given overlayRef, so the\n // listeners are added once and removed once.\n const panel = this.overlayRef.overlayElement;\n const onEnter = () => this.clearTimers();\n const onLeave = () => this.hide();\n panel.addEventListener('mouseenter', onEnter);\n panel.addEventListener('mouseleave', onLeave);\n this.overlayHoverCleanup = () => {\n panel.removeEventListener('mouseenter', onEnter);\n panel.removeEventListener('mouseleave', onLeave);\n this.overlayHoverCleanup = null;\n };\n }\n\n /**\n * Pushes the current `twTooltipPosition` onto the live position strategy.\n *\n * Updating the strategy in place rather than disposing the `OverlayRef` on\n * hide is not just the cheaper option — it is the correct one. `createOverlay`\n * subscribes to `positionStrategy.positionChanges` exactly once, and that feed\n * is what drives the arrow direction; `FlexibleConnectedPositionStrategy`\n * completes that subject in `dispose()`, so a dispose-on-hide would silently\n * kill arrow placement from the second show onward.\n */\n private applyPositions(): void {\n const position = this.twTooltipPosition();\n if (!this.positionStrategy || position === this.appliedPosition) return;\n this.appliedPosition = position;\n this.positionStrategy.withPositions(buildPositions(position));\n // `withPositions` only stores the list; a tooltip that is currently on\n // screen needs an explicit reflow. (Attaching later applies it anyway.)\n if (this.overlayRef?.hasAttached()) this.overlayRef.updatePosition();\n }\n\n private updateTooltip(): void {\n if (!this.tooltipInstance) return;\n this.tooltipInstance.content.set(this.twTooltip());\n this.tooltipInstance.color.set(this.twTooltipColor());\n this.tooltipInstance.size.set(this.twTooltipSize());\n this.tooltipInstance.showArrow.set(this.twTooltipArrow());\n this.tooltipInstance.panelClass.set(this.twTooltipPanelClass());\n }\n\n private detach(): void {\n this.clearTimers();\n if (this.overlayRef?.hasAttached()) {\n this.overlayRef.detach();\n }\n if (this.tooltipInstance) {\n this.removeAriaDescription();\n this.tooltipInstance = null;\n this.twTooltipHidden.emit();\n }\n }\n\n /**\n * Push the current tooltip content as an `aria-describedby` link on the\n * trigger element. Dual-mode wiring:\n *\n * - **String content**: routed through CDK `AriaDescriber.describe`, which\n * maintains a single hidden message-container on the document and dedupes\n * identical strings across all describers.\n * - **TemplateRef content**: AriaDescriber's dedup table is keyed by string,\n * so we fall back to a direct `setAttribute('aria-describedby', overlayId)`\n * pointing at the `role=\"tooltip\"` overlay. Without this fallback,\n * assistive tech would have no description link for templated tooltip\n * content.\n *\n * `_describedBy` tracks the string handed to `AriaDescriber`;\n * `_templateDescribedBy` is `true` when the fallback path is active so\n * `removeAriaDescription` can take the symmetrical teardown branch.\n */\n private applyAriaDescription(): void {\n const el = this.elementRef.nativeElement;\n const content = this.twTooltip();\n\n if (typeof content === 'string' && content.length > 0 && this.ariaDescriber) {\n // If we previously wired the template fallback (rare — content can swap\n // at runtime), tear it down before swapping to the describer path.\n if (this._templateDescribedBy) {\n el.removeAttribute('aria-describedby');\n this._templateDescribedBy = false;\n }\n if (this._describedBy && this._describedBy !== content) {\n this.ariaDescriber.removeDescription(el, this._describedBy);\n this._describedBy = null;\n }\n if (this._describedBy === content) return;\n this.ariaDescriber.describe(el, content);\n this._describedBy = content;\n return;\n }\n\n // Template / non-string fallback.\n if (this._describedBy && this.ariaDescriber) {\n this.ariaDescriber.removeDescription(el, this._describedBy);\n this._describedBy = null;\n }\n if (this.tooltipInstance) {\n el.setAttribute('aria-describedby', this.tooltipInstance.id);\n this._templateDescribedBy = true;\n }\n }\n\n private removeAriaDescription(): void {\n const el = this.elementRef.nativeElement;\n if (this._describedBy && this.ariaDescriber) {\n this.ariaDescriber.removeDescription(el, this._describedBy);\n this._describedBy = null;\n }\n if (this._templateDescribedBy) {\n el.removeAttribute('aria-describedby');\n this._templateDescribedBy = false;\n }\n }\n\n private disposeOverlay(): void {\n this.overlayHoverCleanup?.();\n if (this.overlayRef) {\n this.overlayRef.dispose();\n this.overlayRef = null;\n }\n this.positionStrategy = null;\n this.appliedPosition = null;\n this.tooltipInstance = null;\n }\n\n private clearTimers(): void {\n if (this.showTimer !== null) {\n clearTimeout(this.showTimer);\n this.showTimer = null;\n }\n if (this.hideTimer !== null) {\n clearTimeout(this.hideTimer);\n this.hideTimer = null;\n }\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { ComponentHarness, HarnessPredicate } from '@angular/cdk/testing';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Harness for a single row inside one of a `tw-transfer`'s two panels.
|
|
5
|
+
*
|
|
6
|
+
* Rows are `CdkOption`s, so the harness reads ARIA that CDK owns rather than
|
|
7
|
+
* anything ngx-tw renders: `aria-selected` for the ticked state and
|
|
8
|
+
* `aria-disabled` for the per-item disable predicate.
|
|
9
|
+
*
|
|
10
|
+
* "Checked" here is the *ephemeral pending-move* state — which rows the next
|
|
11
|
+
* move button press will shuttle — not membership of a side. Membership is the
|
|
12
|
+
* component's value; read it by asking {@link TransferHarness} which panel a
|
|
13
|
+
* row is in.
|
|
14
|
+
*
|
|
15
|
+
* Reach these through {@link TransferHarness.getItems}: located from a document
|
|
16
|
+
* root the selector would match every listbox option on the page.
|
|
17
|
+
*/
|
|
18
|
+
class TransferItemHarness extends ComponentHarness {
|
|
19
|
+
static hostSelector = '[role="option"]';
|
|
20
|
+
/** Predicate for `locatorFor` / `locatorForAll`. */
|
|
21
|
+
static with(options = {}) {
|
|
22
|
+
return new HarnessPredicate(TransferItemHarness, options)
|
|
23
|
+
.addOption('text', options.text, async (h, text) => HarnessPredicate.stringMatches(await h.getText(), text))
|
|
24
|
+
.addOption('checked', options.checked, async (h, checked) => (await h.isChecked()) === checked)
|
|
25
|
+
.addOption('disabled', options.disabled, async (h, disabled) => (await h.isDisabled()) === disabled);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The row's rendered text, trimmed. With the default row rendering this is
|
|
29
|
+
* `labelFn(item)`; a projected `*twTransferItem` template makes it whatever
|
|
30
|
+
* that template renders.
|
|
31
|
+
*/
|
|
32
|
+
async getText() {
|
|
33
|
+
return (await (await this.host()).text()).trim();
|
|
34
|
+
}
|
|
35
|
+
/** Whether the row is ticked for the next move, from `aria-selected`. */
|
|
36
|
+
async isChecked() {
|
|
37
|
+
return (await (await this.host()).getAttribute('aria-selected')) === 'true';
|
|
38
|
+
}
|
|
39
|
+
/** Whether the row reports `aria-disabled="true"` (`behavior.disabledItem`). */
|
|
40
|
+
async isDisabled() {
|
|
41
|
+
return (await (await this.host()).getAttribute('aria-disabled')) === 'true';
|
|
42
|
+
}
|
|
43
|
+
/** Ticks the row for the next move. No-op when already ticked. */
|
|
44
|
+
async check() {
|
|
45
|
+
if (await this.isChecked())
|
|
46
|
+
return;
|
|
47
|
+
await (await this.host()).click();
|
|
48
|
+
}
|
|
49
|
+
/** Unticks the row. No-op when already unticked. */
|
|
50
|
+
async uncheck() {
|
|
51
|
+
if (!(await this.isChecked()))
|
|
52
|
+
return;
|
|
53
|
+
await (await this.host()).click();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Harness for `tw-transfer`.
|
|
59
|
+
*
|
|
60
|
+
* ## How the two panels are told apart
|
|
61
|
+
*
|
|
62
|
+
* The panels are one `ng-template` instantiated twice, and neither the panel
|
|
63
|
+
* element nor its list carries a side marker. The only per-side hook the
|
|
64
|
+
* component renders is the auto-generated panel-title id — `…-source-title` /
|
|
65
|
+
* `…-target-title` — which the listbox references through `aria-labelledby`
|
|
66
|
+
* and which the component's own `focusDestination()` already matches on for
|
|
67
|
+
* the same reason. This harness scopes every per-side query with a suffix
|
|
68
|
+
* match on that id.
|
|
69
|
+
*
|
|
70
|
+
* Two consequences worth knowing:
|
|
71
|
+
*
|
|
72
|
+
* - Ordering is never assumed, so a panel that has emptied (its listbox is
|
|
73
|
+
* removed entirely — an empty `role="listbox"` violates
|
|
74
|
+
* `aria-required-children`) does not shift the other panel's identity.
|
|
75
|
+
* {@link getItems} simply returns `[]` for the empty side.
|
|
76
|
+
* - The hook is a derived id, not a declared contract. If the panels ever gain
|
|
77
|
+
* a real marker attribute, this is the code that should move onto it.
|
|
78
|
+
*
|
|
79
|
+
* The whole control lives inside the `tw-transfer` host — there is no CDK
|
|
80
|
+
* overlay — so the ordinary fixture loader is enough.
|
|
81
|
+
*/
|
|
82
|
+
class TransferHarness extends ComponentHarness {
|
|
83
|
+
static hostSelector = 'tw-transfer';
|
|
84
|
+
/**
|
|
85
|
+
* The move buttons, in DOM order: `[0]` shuttles source → target and `[1]`
|
|
86
|
+
* target → source (absent under `behavior.oneWay`).
|
|
87
|
+
*
|
|
88
|
+
* The `:not()` excludes buttons a consumer projected into a
|
|
89
|
+
* `*twTransferItem` template, which would otherwise be picked up ahead of
|
|
90
|
+
* the real controls — rows render before the button column.
|
|
91
|
+
*/
|
|
92
|
+
moveButtons = this.locatorForAll('button:not([role="listbox"] *)');
|
|
93
|
+
/** Predicate for `locatorFor` / `locatorForAll`. */
|
|
94
|
+
static with(options = {}) {
|
|
95
|
+
return new HarnessPredicate(TransferHarness, options)
|
|
96
|
+
.addOption('label', options.label, async (h, label) => HarnessPredicate.stringMatches(await h.getLabel(), label))
|
|
97
|
+
.addOption('disabled', options.disabled, async (h, disabled) => (await h.isDisabled()) === disabled);
|
|
98
|
+
}
|
|
99
|
+
/** The control's accessible name, from `aria-label` when one is set. */
|
|
100
|
+
async getLabel() {
|
|
101
|
+
return (await this.host()).getAttribute('aria-label');
|
|
102
|
+
}
|
|
103
|
+
/** Whether the control reports `aria-disabled="true"`. */
|
|
104
|
+
async isDisabled() {
|
|
105
|
+
return (await (await this.host()).getAttribute('aria-disabled')) === 'true';
|
|
106
|
+
}
|
|
107
|
+
/** The title rendered in a panel's header. */
|
|
108
|
+
async getTitle(side) {
|
|
109
|
+
return (await (await this.locatorFor(titleSelector(side))()).text()).trim();
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Every visible row in a panel, in render order. Returns `[]` for a panel
|
|
113
|
+
* with nothing in it — including one hidden behind a search query, since
|
|
114
|
+
* filtering removes rows from the DOM rather than hiding them.
|
|
115
|
+
*
|
|
116
|
+
* `filters.ancestor` is ignored: picking the side *is* the ancestor.
|
|
117
|
+
*/
|
|
118
|
+
async getItems(side, filters = {}) {
|
|
119
|
+
return this.locatorForAll(TransferItemHarness.with({ ...filters, ancestor: listSelector(side) }))();
|
|
120
|
+
}
|
|
121
|
+
/** The visible text of every row in a panel, in render order. */
|
|
122
|
+
async getItemTexts(side) {
|
|
123
|
+
const items = await this.getItems(side);
|
|
124
|
+
return Promise.all(items.map((item) => item.getText()));
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* How many rows a panel is showing. This is the number the panel header's
|
|
128
|
+
* count also reports, so it tracks the search query rather than total
|
|
129
|
+
* membership.
|
|
130
|
+
*/
|
|
131
|
+
async getItemCount(side) {
|
|
132
|
+
return (await this.getItems(side)).length;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Ticks the first row in a panel whose text matches, staging it for the next
|
|
136
|
+
* move. Throws when nothing matches, rather than failing silently.
|
|
137
|
+
*/
|
|
138
|
+
async checkItem(side, text) {
|
|
139
|
+
const matches = await this.getItems(side, { text });
|
|
140
|
+
if (matches.length === 0) {
|
|
141
|
+
throw new Error(`TransferHarness.checkItem: no ${side} item matching ${String(text)}.`);
|
|
142
|
+
}
|
|
143
|
+
await matches[0].check();
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Drives a panel's header select-all checkbox to `checked`, ticking or
|
|
147
|
+
* clearing every enabled visible row in one gesture. This is how "move
|
|
148
|
+
* everything" is expressed: `setAllChecked('source', true)` then
|
|
149
|
+
* {@link moveToTarget}.
|
|
150
|
+
*
|
|
151
|
+
* The checkbox is tri-state. From `mixed` a single click resolves to
|
|
152
|
+
* *checked*, the way a native indeterminate checkbox does, so clearing from
|
|
153
|
+
* a partial selection takes two clicks — which is what a user does too, and
|
|
154
|
+
* what this method issues. Everything is ticked in between.
|
|
155
|
+
*
|
|
156
|
+
* Throws when the checkbox is not rendered (`display.showSelectAll: false`).
|
|
157
|
+
*/
|
|
158
|
+
async setAllChecked(side, checked) {
|
|
159
|
+
const checkbox = await this.locatorForOptional(selectAllSelector(side))();
|
|
160
|
+
if (!checkbox) {
|
|
161
|
+
throw new Error(`TransferHarness.setAllChecked: the ${side} panel has no select-all checkbox. It is hidden by \`display.showSelectAll: false\`.`);
|
|
162
|
+
}
|
|
163
|
+
const want = String(checked);
|
|
164
|
+
if ((await checkbox.getAttribute('aria-checked')) === want)
|
|
165
|
+
return;
|
|
166
|
+
await checkbox.click();
|
|
167
|
+
// The second click of the `mixed` → `false` path.
|
|
168
|
+
if ((await checkbox.getAttribute('aria-checked')) !== want) {
|
|
169
|
+
await checkbox.click();
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Presses the → button, shuttling the source panel's ticked rows to the
|
|
174
|
+
* target. Rows that are disabled are skipped by the component.
|
|
175
|
+
*/
|
|
176
|
+
async moveToTarget() {
|
|
177
|
+
const buttons = await this.moveButtons();
|
|
178
|
+
if (buttons.length === 0) {
|
|
179
|
+
throw new Error('TransferHarness.moveToTarget: no → button was found.');
|
|
180
|
+
}
|
|
181
|
+
await buttons[0].click();
|
|
182
|
+
await this.waitForTasksOutsideAngular();
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Presses the ← button, shuttling the target panel's ticked rows back to the
|
|
186
|
+
* source. Throws under `behavior.oneWay`, where that button is not rendered.
|
|
187
|
+
*/
|
|
188
|
+
async moveToSource() {
|
|
189
|
+
const buttons = await this.moveButtons();
|
|
190
|
+
if (buttons.length < 2) {
|
|
191
|
+
throw new Error('TransferHarness.moveToSource: no ← button is rendered. `behavior.oneWay` removes it.');
|
|
192
|
+
}
|
|
193
|
+
await buttons[1].click();
|
|
194
|
+
await this.waitForTasksOutsideAngular();
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/** The panel-title element for a side. */
|
|
198
|
+
function titleSelector(side) {
|
|
199
|
+
return `[id$="-${side}-title"]`;
|
|
200
|
+
}
|
|
201
|
+
/** The panel's listbox, matched through the title it is labelled by. */
|
|
202
|
+
function listSelector(side) {
|
|
203
|
+
return `[role="listbox"][aria-labelledby$="-${side}-title"]`;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* The panel header's select-all checkbox. The header is the element that has
|
|
207
|
+
* the title as a *direct* child, which distinguishes it from the panel wrapper
|
|
208
|
+
* around it; the checkbox is the header's sibling of that title.
|
|
209
|
+
*/
|
|
210
|
+
function selectAllSelector(side) {
|
|
211
|
+
return `div:has(> [id$="-${side}-title"]) > [role="checkbox"]`;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Generated bundle index. Do not edit.
|
|
216
|
+
*/
|
|
217
|
+
|
|
218
|
+
export { TransferHarness, TransferItemHarness };
|
|
219
|
+
//# sourceMappingURL=cdevhub-ngx-tw-transfer-testing.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cdevhub-ngx-tw-transfer-testing.mjs","sources":["../../../projects/ngx-tw/transfer/testing/transfer-item-harness.ts","../../../projects/ngx-tw/transfer/testing/transfer-harness.ts","../../../projects/ngx-tw/transfer/testing/cdevhub-ngx-tw-transfer-testing.ts"],"sourcesContent":["import { ComponentHarness, HarnessPredicate } from '@angular/cdk/testing';\nimport type { BaseHarnessFilters } from '@angular/cdk/testing';\n\n/** Filters accepted by `TransferItemHarness.with`. */\nexport interface TransferItemHarnessFilters extends BaseHarnessFilters {\n /** Match by the row's visible text. */\n text?: string | RegExp;\n /** Match ticked / unticked rows. */\n checked?: boolean;\n /** Match disabled / enabled rows. */\n disabled?: boolean;\n}\n\n/**\n * Harness for a single row inside one of a `tw-transfer`'s two panels.\n *\n * Rows are `CdkOption`s, so the harness reads ARIA that CDK owns rather than\n * anything ngx-tw renders: `aria-selected` for the ticked state and\n * `aria-disabled` for the per-item disable predicate.\n *\n * \"Checked\" here is the *ephemeral pending-move* state — which rows the next\n * move button press will shuttle — not membership of a side. Membership is the\n * component's value; read it by asking {@link TransferHarness} which panel a\n * row is in.\n *\n * Reach these through {@link TransferHarness.getItems}: located from a document\n * root the selector would match every listbox option on the page.\n */\nexport class TransferItemHarness extends ComponentHarness {\n static hostSelector = '[role=\"option\"]';\n\n /** Predicate for `locatorFor` / `locatorForAll`. */\n static with(\n options: TransferItemHarnessFilters = {},\n ): HarnessPredicate<TransferItemHarness> {\n return new HarnessPredicate(TransferItemHarness, options)\n .addOption('text', options.text, async (h, text) =>\n HarnessPredicate.stringMatches(await h.getText(), text),\n )\n .addOption(\n 'checked',\n options.checked,\n async (h, checked) => (await h.isChecked()) === checked,\n )\n .addOption(\n 'disabled',\n options.disabled,\n async (h, disabled) => (await h.isDisabled()) === disabled,\n );\n }\n\n /**\n * The row's rendered text, trimmed. With the default row rendering this is\n * `labelFn(item)`; a projected `*twTransferItem` template makes it whatever\n * that template renders.\n */\n async getText(): Promise<string> {\n return (await (await this.host()).text()).trim();\n }\n\n /** Whether the row is ticked for the next move, from `aria-selected`. */\n async isChecked(): Promise<boolean> {\n return (await (await this.host()).getAttribute('aria-selected')) === 'true';\n }\n\n /** Whether the row reports `aria-disabled=\"true\"` (`behavior.disabledItem`). */\n async isDisabled(): Promise<boolean> {\n return (await (await this.host()).getAttribute('aria-disabled')) === 'true';\n }\n\n /** Ticks the row for the next move. No-op when already ticked. */\n async check(): Promise<void> {\n if (await this.isChecked()) return;\n await (await this.host()).click();\n }\n\n /** Unticks the row. No-op when already unticked. */\n async uncheck(): Promise<void> {\n if (!(await this.isChecked())) return;\n await (await this.host()).click();\n }\n}\n","import { ComponentHarness, HarnessPredicate } from '@angular/cdk/testing';\nimport type { BaseHarnessFilters } from '@angular/cdk/testing';\nimport {\n TransferItemHarness,\n type TransferItemHarnessFilters,\n} from './transfer-item-harness';\n\n/**\n * Which panel of a `tw-transfer` a call addresses. Structurally identical to\n * the component's own `TwTransferSide`, redeclared here so the testing entry\n * point stays free of any import from the component entry point.\n */\nexport type TransferHarnessSide = 'source' | 'target';\n\n/** Filters accepted by `TransferHarness.with`. */\nexport interface TransferHarnessFilters extends BaseHarnessFilters {\n /** Match by the control's accessible name (its `aria-label`). */\n label?: string | RegExp;\n /** Match disabled / enabled controls. */\n disabled?: boolean;\n}\n\n/**\n * Harness for `tw-transfer`.\n *\n * ## How the two panels are told apart\n *\n * The panels are one `ng-template` instantiated twice, and neither the panel\n * element nor its list carries a side marker. The only per-side hook the\n * component renders is the auto-generated panel-title id — `…-source-title` /\n * `…-target-title` — which the listbox references through `aria-labelledby`\n * and which the component's own `focusDestination()` already matches on for\n * the same reason. This harness scopes every per-side query with a suffix\n * match on that id.\n *\n * Two consequences worth knowing:\n *\n * - Ordering is never assumed, so a panel that has emptied (its listbox is\n * removed entirely — an empty `role=\"listbox\"` violates\n * `aria-required-children`) does not shift the other panel's identity.\n * {@link getItems} simply returns `[]` for the empty side.\n * - The hook is a derived id, not a declared contract. If the panels ever gain\n * a real marker attribute, this is the code that should move onto it.\n *\n * The whole control lives inside the `tw-transfer` host — there is no CDK\n * overlay — so the ordinary fixture loader is enough.\n */\nexport class TransferHarness extends ComponentHarness {\n static hostSelector = 'tw-transfer';\n\n /**\n * The move buttons, in DOM order: `[0]` shuttles source → target and `[1]`\n * target → source (absent under `behavior.oneWay`).\n *\n * The `:not()` excludes buttons a consumer projected into a\n * `*twTransferItem` template, which would otherwise be picked up ahead of\n * the real controls — rows render before the button column.\n */\n private readonly moveButtons = this.locatorForAll(\n 'button:not([role=\"listbox\"] *)',\n );\n\n /** Predicate for `locatorFor` / `locatorForAll`. */\n static with(options: TransferHarnessFilters = {}): HarnessPredicate<TransferHarness> {\n return new HarnessPredicate(TransferHarness, options)\n .addOption('label', options.label, async (h, label) =>\n HarnessPredicate.stringMatches(await h.getLabel(), label),\n )\n .addOption(\n 'disabled',\n options.disabled,\n async (h, disabled) => (await h.isDisabled()) === disabled,\n );\n }\n\n /** The control's accessible name, from `aria-label` when one is set. */\n async getLabel(): Promise<string | null> {\n return (await this.host()).getAttribute('aria-label');\n }\n\n /** Whether the control reports `aria-disabled=\"true\"`. */\n async isDisabled(): Promise<boolean> {\n return (await (await this.host()).getAttribute('aria-disabled')) === 'true';\n }\n\n /** The title rendered in a panel's header. */\n async getTitle(side: TransferHarnessSide): Promise<string> {\n return (await (await this.locatorFor(titleSelector(side))()).text()).trim();\n }\n\n /**\n * Every visible row in a panel, in render order. Returns `[]` for a panel\n * with nothing in it — including one hidden behind a search query, since\n * filtering removes rows from the DOM rather than hiding them.\n *\n * `filters.ancestor` is ignored: picking the side *is* the ancestor.\n */\n async getItems(\n side: TransferHarnessSide,\n filters: TransferItemHarnessFilters = {},\n ): Promise<TransferItemHarness[]> {\n return this.locatorForAll(\n TransferItemHarness.with({ ...filters, ancestor: listSelector(side) }),\n )();\n }\n\n /** The visible text of every row in a panel, in render order. */\n async getItemTexts(side: TransferHarnessSide): Promise<string[]> {\n const items = await this.getItems(side);\n return Promise.all(items.map((item) => item.getText()));\n }\n\n /**\n * How many rows a panel is showing. This is the number the panel header's\n * count also reports, so it tracks the search query rather than total\n * membership.\n */\n async getItemCount(side: TransferHarnessSide): Promise<number> {\n return (await this.getItems(side)).length;\n }\n\n /**\n * Ticks the first row in a panel whose text matches, staging it for the next\n * move. Throws when nothing matches, rather than failing silently.\n */\n async checkItem(side: TransferHarnessSide, text: string | RegExp): Promise<void> {\n const matches = await this.getItems(side, { text });\n if (matches.length === 0) {\n throw new Error(\n `TransferHarness.checkItem: no ${side} item matching ${String(text)}.`,\n );\n }\n await matches[0].check();\n }\n\n /**\n * Drives a panel's header select-all checkbox to `checked`, ticking or\n * clearing every enabled visible row in one gesture. This is how \"move\n * everything\" is expressed: `setAllChecked('source', true)` then\n * {@link moveToTarget}.\n *\n * The checkbox is tri-state. From `mixed` a single click resolves to\n * *checked*, the way a native indeterminate checkbox does, so clearing from\n * a partial selection takes two clicks — which is what a user does too, and\n * what this method issues. Everything is ticked in between.\n *\n * Throws when the checkbox is not rendered (`display.showSelectAll: false`).\n */\n async setAllChecked(side: TransferHarnessSide, checked: boolean): Promise<void> {\n const checkbox = await this.locatorForOptional(selectAllSelector(side))();\n if (!checkbox) {\n throw new Error(\n `TransferHarness.setAllChecked: the ${side} panel has no select-all checkbox. It is hidden by \\`display.showSelectAll: false\\`.`,\n );\n }\n const want = String(checked);\n if ((await checkbox.getAttribute('aria-checked')) === want) return;\n await checkbox.click();\n // The second click of the `mixed` → `false` path.\n if ((await checkbox.getAttribute('aria-checked')) !== want) {\n await checkbox.click();\n }\n }\n\n /**\n * Presses the → button, shuttling the source panel's ticked rows to the\n * target. Rows that are disabled are skipped by the component.\n */\n async moveToTarget(): Promise<void> {\n const buttons = await this.moveButtons();\n if (buttons.length === 0) {\n throw new Error('TransferHarness.moveToTarget: no → button was found.');\n }\n await buttons[0].click();\n await this.waitForTasksOutsideAngular();\n }\n\n /**\n * Presses the ← button, shuttling the target panel's ticked rows back to the\n * source. Throws under `behavior.oneWay`, where that button is not rendered.\n */\n async moveToSource(): Promise<void> {\n const buttons = await this.moveButtons();\n if (buttons.length < 2) {\n throw new Error(\n 'TransferHarness.moveToSource: no ← button is rendered. `behavior.oneWay` removes it.',\n );\n }\n await buttons[1].click();\n await this.waitForTasksOutsideAngular();\n }\n}\n\n/** The panel-title element for a side. */\nfunction titleSelector(side: TransferHarnessSide): string {\n return `[id$=\"-${side}-title\"]`;\n}\n\n/** The panel's listbox, matched through the title it is labelled by. */\nfunction listSelector(side: TransferHarnessSide): string {\n return `[role=\"listbox\"][aria-labelledby$=\"-${side}-title\"]`;\n}\n\n/**\n * The panel header's select-all checkbox. The header is the element that has\n * the title as a *direct* child, which distinguishes it from the panel wrapper\n * around it; the checkbox is the header's sibling of that title.\n */\nfunction selectAllSelector(side: TransferHarnessSide): string {\n return `div:has(> [id$=\"-${side}-title\"]) > [role=\"checkbox\"]`;\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|