@acorex/cdk 22.1.8 → 22.2.0-next.1
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/auto-follow-scroll/README.md +9 -0
- package/fesm2022/acorex-cdk-accordion.mjs +19 -19
- package/fesm2022/acorex-cdk-accordion.mjs.map +1 -1
- package/fesm2022/acorex-cdk-auto-follow-scroll.mjs +187 -0
- package/fesm2022/acorex-cdk-auto-follow-scroll.mjs.map +1 -0
- package/fesm2022/acorex-cdk-carousel.mjs +25 -7
- package/fesm2022/acorex-cdk-carousel.mjs.map +1 -1
- package/fesm2022/acorex-cdk-clipboard.mjs +6 -6
- package/fesm2022/acorex-cdk-clipboard.mjs.map +1 -1
- package/fesm2022/acorex-cdk-common.mjs +223 -108
- package/fesm2022/acorex-cdk-common.mjs.map +1 -1
- package/fesm2022/acorex-cdk-dom.mjs +3 -3
- package/fesm2022/acorex-cdk-dom.mjs.map +1 -1
- package/fesm2022/acorex-cdk-drag-drop.mjs +158 -68
- package/fesm2022/acorex-cdk-drag-drop.mjs.map +1 -1
- package/fesm2022/acorex-cdk-drawer.mjs +15 -13
- package/fesm2022/acorex-cdk-drawer.mjs.map +1 -1
- package/fesm2022/acorex-cdk-focus-trap.mjs +3 -3
- package/fesm2022/acorex-cdk-focus-trap.mjs.map +1 -1
- package/fesm2022/acorex-cdk-full-screen.mjs +26 -147
- package/fesm2022/acorex-cdk-full-screen.mjs.map +1 -1
- package/fesm2022/acorex-cdk-gesture.mjs +30 -4
- package/fesm2022/acorex-cdk-gesture.mjs.map +1 -1
- package/fesm2022/acorex-cdk-highlight.mjs +8 -78
- package/fesm2022/acorex-cdk-highlight.mjs.map +1 -1
- package/fesm2022/acorex-cdk-horizontal-scroll.mjs +37 -14
- package/fesm2022/acorex-cdk-horizontal-scroll.mjs.map +1 -1
- package/fesm2022/acorex-cdk-input-mask.mjs +3 -3
- package/fesm2022/acorex-cdk-input-mask.mjs.map +1 -1
- package/fesm2022/acorex-cdk-list-navigation.mjs +21 -10
- package/fesm2022/acorex-cdk-list-navigation.mjs.map +1 -1
- package/fesm2022/acorex-cdk-outline.mjs +277 -74
- package/fesm2022/acorex-cdk-outline.mjs.map +1 -1
- package/fesm2022/acorex-cdk-overlay-scrollbar.mjs +903 -0
- package/fesm2022/acorex-cdk-overlay-scrollbar.mjs.map +1 -0
- package/fesm2022/acorex-cdk-overlay.mjs +259 -25
- package/fesm2022/acorex-cdk-overlay.mjs.map +1 -1
- package/fesm2022/acorex-cdk-pan-view.mjs +3 -3
- package/fesm2022/acorex-cdk-pan-view.mjs.map +1 -1
- package/fesm2022/acorex-cdk-qrcode.mjs.map +1 -1
- package/fesm2022/acorex-cdk-resizable.mjs +483 -200
- package/fesm2022/acorex-cdk-resizable.mjs.map +1 -1
- package/fesm2022/acorex-cdk-selection.mjs +10 -10
- package/fesm2022/acorex-cdk-selection.mjs.map +1 -1
- package/fesm2022/acorex-cdk-shimmer.mjs +220 -0
- package/fesm2022/acorex-cdk-shimmer.mjs.map +1 -0
- package/fesm2022/acorex-cdk-sliding-item.mjs +3 -3
- package/fesm2022/acorex-cdk-sliding-item.mjs.map +1 -1
- package/fesm2022/acorex-cdk-sticky.mjs +3 -3
- package/fesm2022/acorex-cdk-sticky.mjs.map +1 -1
- package/fesm2022/acorex-cdk-text-editor.mjs +942 -0
- package/fesm2022/acorex-cdk-text-editor.mjs.map +1 -0
- package/fesm2022/acorex-cdk-uploader.mjs +9 -9
- package/fesm2022/acorex-cdk-uploader.mjs.map +1 -1
- package/fesm2022/acorex-cdk-viewport-guard.mjs +616 -0
- package/fesm2022/acorex-cdk-viewport-guard.mjs.map +1 -0
- package/fesm2022/acorex-cdk-virtual-scroll.mjs +10 -10
- package/fesm2022/acorex-cdk-virtual-scroll.mjs.map +1 -1
- package/fesm2022/acorex-cdk-wysiwyg.mjs +694 -37
- package/fesm2022/acorex-cdk-wysiwyg.mjs.map +1 -1
- package/fesm2022/acorex-cdk-z-index.mjs +3 -3
- package/fesm2022/acorex-cdk-z-index.mjs.map +1 -1
- package/fesm2022/acorex-cdk.mjs.map +1 -1
- package/overlay-scrollbar/README.md +54 -0
- package/package.json +33 -7
- package/shimmer/README.md +11 -0
- package/text-editor/README.md +5 -0
- package/types/acorex-cdk-auto-follow-scroll.d.ts +72 -0
- package/types/acorex-cdk-carousel.d.ts +2 -0
- package/types/acorex-cdk-clipboard.d.ts +1 -1
- package/types/acorex-cdk-common.d.ts +46 -19
- package/types/acorex-cdk-drag-drop.d.ts +43 -17
- package/types/acorex-cdk-full-screen.d.ts +18 -43
- package/types/acorex-cdk-gesture.d.ts +11 -1
- package/types/acorex-cdk-highlight.d.ts +1 -28
- package/types/acorex-cdk-horizontal-scroll.d.ts +3 -0
- package/types/acorex-cdk-list-navigation.d.ts +5 -0
- package/types/acorex-cdk-outline.d.ts +20 -0
- package/types/acorex-cdk-overlay-scrollbar.d.ts +155 -0
- package/types/acorex-cdk-overlay.d.ts +60 -4
- package/types/acorex-cdk-resizable.d.ts +80 -38
- package/types/acorex-cdk-shimmer.d.ts +68 -0
- package/types/acorex-cdk-text-editor.d.ts +156 -0
- package/types/acorex-cdk-uploader.d.ts +1 -1
- package/types/acorex-cdk-viewport-guard.d.ts +99 -0
- package/types/acorex-cdk-wysiwyg.d.ts +121 -14
- package/wysiwyg/README.md +3 -1
- package/fesm2022/acorex-cdk-double-click.mjs +0 -178
- package/fesm2022/acorex-cdk-double-click.mjs.map +0 -1
- package/types/acorex-cdk-double-click.d.ts +0 -66
|
@@ -100,10 +100,21 @@ class AXListNavigationDirective {
|
|
|
100
100
|
});
|
|
101
101
|
e.itemElem.nativeElement.scrollIntoView(this.scrollOption);
|
|
102
102
|
}
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
/**
|
|
104
|
+
* Highlights a list option on pointer hover without moving focus.
|
|
105
|
+
* Use when focus must stay on an external trigger (e.g. searchable lookup input).
|
|
106
|
+
*/
|
|
107
|
+
highlightItem(item) {
|
|
108
|
+
const items = this.childElem();
|
|
109
|
+
this.activeIndex.set(item.index());
|
|
110
|
+
for (const child of items) {
|
|
111
|
+
child.isActive.set(child === item);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: AXListNavigationDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
115
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "22.1.6", type: AXListNavigationDirective, isStandalone: true, selector: "[axListNavigation]", inputs: { orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onNavigationChanged: "onNavigationChanged", onKeypress: "onKeypress" }, queries: [{ propertyName: "childElem", predicate: AXListNavigationItemDirective, descendants: true, isSignal: true }], exportAs: ["axListNavigation"], ngImport: i0 }); }
|
|
105
116
|
}
|
|
106
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
117
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: AXListNavigationDirective, decorators: [{
|
|
107
118
|
type: Directive,
|
|
108
119
|
args: [{
|
|
109
120
|
selector: '[axListNavigation]',
|
|
@@ -141,10 +152,10 @@ class AXListNavigationItemDirective {
|
|
|
141
152
|
});
|
|
142
153
|
}
|
|
143
154
|
#init;
|
|
144
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.
|
|
145
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.
|
|
155
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: AXListNavigationItemDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
156
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.6", type: AXListNavigationItemDirective, isStandalone: true, selector: "[axListNavigationItem]", outputs: { onKeypress: "onKeypress" }, exportAs: ["axListNavigationItem"], ngImport: i0 }); }
|
|
146
157
|
}
|
|
147
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
158
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: AXListNavigationItemDirective, decorators: [{
|
|
148
159
|
type: Directive,
|
|
149
160
|
args: [{
|
|
150
161
|
selector: '[axListNavigationItem]',
|
|
@@ -155,11 +166,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
155
166
|
const COMPONENT = [AXListNavigationDirective, AXListNavigationItemDirective];
|
|
156
167
|
const MODULES = [CommonModule];
|
|
157
168
|
class AXListNavigationModule {
|
|
158
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.
|
|
159
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.
|
|
160
|
-
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.
|
|
169
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: AXListNavigationModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
170
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.1.6", ngImport: i0, type: AXListNavigationModule, imports: [CommonModule, AXListNavigationDirective, AXListNavigationItemDirective], exports: [AXListNavigationDirective, AXListNavigationItemDirective] }); }
|
|
171
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: AXListNavigationModule, imports: [MODULES] }); }
|
|
161
172
|
}
|
|
162
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
173
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: AXListNavigationModule, decorators: [{
|
|
163
174
|
type: NgModule,
|
|
164
175
|
args: [{
|
|
165
176
|
imports: [...MODULES, ...COMPONENT],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"acorex-cdk-list-navigation.mjs","sources":["../../../../packages/cdk/list-navigation/src/lib/list-navigation.directive.ts","../../../../packages/cdk/list-navigation/src/lib/list-navigation-item.directive.ts","../../../../packages/cdk/list-navigation/src/lib/list-navigation.module.ts","../../../../packages/cdk/list-navigation/src/acorex-cdk-list-navigation.ts"],"sourcesContent":["import { AXHtmlEvent } from '@acorex/cdk/common';\nimport {\n afterNextRender,\n contentChildren,\n Directive,\n effect,\n ElementRef,\n inject,\n input,\n output,\n signal,\n} from '@angular/core';\nimport { AXListNavigationItemDirective } from './list-navigation-item.directive';\n\n@Directive({\n selector: '[axListNavigation]',\n exportAs: 'axListNavigation',\n})\nexport class AXListNavigationDirective {\n private childElem = contentChildren(AXListNavigationItemDirective, { descendants: true });\n private elementRef = inject(ElementRef);\n activeIndex = signal(0);\n onNavigationChanged = output<{ sender: AXListNavigationDirective }>();\n onKeypress = output<AXHtmlEvent<KeyboardEvent>>();\n orientation = input<'horizontal' | 'vertical'>('vertical');\n\n private scrollOption: ScrollIntoViewOptions = {\n behavior: 'smooth',\n block: 'nearest',\n };\n\n #eff = effect(() => {\n this.childElem().forEach((item, index) => {\n (item.itemElem.nativeElement as HTMLElement).tabIndex = 0;\n item.index.set(index);\n });\n });\n\n #init = afterNextRender(() => {\n (this.elementRef.nativeElement as HTMLElement).tabIndex = -1;\n\n (this.elementRef.nativeElement as HTMLElement).onkeydown = (e: KeyboardEvent) => {\n this.onKeypress.emit({ component: this, nativeEvent: e });\n\n if (e.key === 'Tab') {\n this.onNavigationChanged.emit({ sender: this });\n }\n\n if (this.orientation() === 'vertical') {\n switch (e.key) {\n case 'ArrowDown':\n this.navigationHandler('ArrowDown');\n break;\n case 'ArrowUp':\n this.navigationHandler('ArrowUp');\n break;\n case 'ArrowLeft':\n this.parentNavigationHandler();\n break;\n }\n } else if (this.orientation() === 'horizontal') {\n switch (e.key) {\n case 'ArrowRight':\n this.navigationHandler('ArrowDown');\n break;\n case 'ArrowLeft':\n this.navigationHandler('ArrowUp');\n break;\n case 'ArrowUp':\n this.parentNavigationHandler();\n break;\n }\n }\n };\n });\n\n private navigationHandler(e: string) {\n this.onNavigationChanged.emit({ sender: this });\n\n if (e === 'ArrowUp' && this.activeIndex() > 0) {\n this.activeIndex.update((prev) => prev - 1);\n this.focusOnIndex(this.activeIndex());\n } else if (e === 'ArrowDown' && this.activeIndex() < this.childElem().length - 1) {\n this.activeIndex.update((prev) => prev + 1);\n this.focusOnIndex(this.activeIndex());\n }\n }\n\n private parentNavigationHandler() {\n this.onNavigationChanged.emit({ sender: this });\n\n const selectedItemParentKey = this.childElem()[this.activeIndex()].navigationParentItemKey();\n if (!selectedItemParentKey) return;\n const parentElem = this.childElem().find((item) => item.navigationItemKey === selectedItemParentKey);\n if (!parentElem) return;\n setTimeout(() => {\n (parentElem.itemElem.nativeElement as HTMLAreaElement).focus();\n });\n (parentElem.itemElem.nativeElement as HTMLAreaElement).scrollIntoView(this.scrollOption);\n }\n\n focusOnIndex(index: number) {\n const selectedItem = this.childElem()[index]?.itemElem.nativeElement as HTMLElement;\n if (!selectedItem) return;\n setTimeout(() => {\n selectedItem.focus();\n });\n selectedItem.scrollIntoView(this.scrollOption);\n }\n\n navigateTo(e: AXListNavigationItemDirective) {\n setTimeout(() => {\n (e.itemElem.nativeElement as HTMLElement).focus();\n });\n (e.itemElem.nativeElement as HTMLElement).scrollIntoView(this.scrollOption);\n }\n}\n","import { AXHtmlEvent } from '@acorex/cdk/common';\nimport { afterNextRender, Directive, ElementRef, inject, output, signal } from '@angular/core';\nimport { AXListNavigationDirective } from './list-navigation.directive';\n\n@Directive({\n selector: '[axListNavigationItem]',\n exportAs: 'axListNavigationItem',\n})\nexport class AXListNavigationItemDirective {\n itemElem = inject(ElementRef);\n isActive = signal(false);\n index = signal(0);\n navigationItemKey = Math.random();\n navigationParentItemKey = signal(null);\n onKeypress = output<AXHtmlEvent<KeyboardEvent>>();\n\n private parent = inject(AXListNavigationDirective);\n private injectItemInsideItem = inject(AXListNavigationItemDirective, { optional: true, skipSelf: true });\n\n #init = afterNextRender(() => {\n (this.itemElem.nativeElement as HTMLElement).onkeydown = (e: KeyboardEvent) => {\n this.onKeypress.emit({ component: this, nativeEvent: e });\n };\n\n (this.itemElem.nativeElement as HTMLElement).onfocus = () => {\n this.isActive.set(true);\n this.parent.activeIndex.set(this.index());\n };\n\n (this.itemElem.nativeElement as HTMLElement).onblur = () => {\n this.isActive.set(false);\n };\n\n if (!this.injectItemInsideItem?.navigationItemKey) return;\n this.navigationParentItemKey.set(this.injectItemInsideItem.navigationItemKey);\n });\n}\n","import { CommonModule } from '@angular/common';\nimport { NgModule } from '@angular/core';\nimport { AXListNavigationItemDirective } from './list-navigation-item.directive';\nimport { AXListNavigationDirective } from './list-navigation.directive';\n\nconst COMPONENT = [AXListNavigationDirective, AXListNavigationItemDirective];\n\nconst MODULES = [CommonModule];\n\n@NgModule({\n imports: [...MODULES, ...COMPONENT],\n exports: [...COMPONENT],\n providers: [],\n})\nexport class AXListNavigationModule {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;MAkBa,yBAAyB,CAAA;AAJtC,IAAA,WAAA,GAAA;QAKU,IAAA,CAAA,SAAS,GAAG,eAAe,CAAC,6BAA6B,iFAAI,WAAW,EAAE,IAAI,EAAA,CAAG;AACjF,QAAA,IAAA,CAAA,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;QACvC,IAAA,CAAA,WAAW,GAAG,MAAM,CAAC,CAAC;wFAAC;QACvB,IAAA,CAAA,mBAAmB,GAAG,MAAM,EAAyC;QACrE,IAAA,CAAA,UAAU,GAAG,MAAM,EAA8B;QACjD,IAAA,CAAA,WAAW,GAAG,KAAK,CAA4B,UAAU;wFAAC;AAElD,QAAA,IAAA,CAAA,YAAY,GAA0B;AAC5C,YAAA,QAAQ,EAAE,QAAQ;AAClB,YAAA,KAAK,EAAE,SAAS;SACjB;AAED,QAAA,IAAA,CAAA,IAAI,GAAG,MAAM,CAAC,MAAK;YACjB,IAAI,CAAC,SAAS,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,KAAI;gBACtC,IAAI,CAAC,QAAQ,CAAC,aAA6B,CAAC,QAAQ,GAAG,CAAC;AACzD,gBAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC;AACvB,YAAA,CAAC,CAAC;QACJ,CAAC;iFAAC;AAEF,QAAA,IAAA,CAAA,KAAK,GAAG,eAAe,CAAC,MAAK;YAC1B,IAAI,CAAC,UAAU,CAAC,aAA6B,CAAC,QAAQ,GAAG,CAAC,CAAC;YAE3D,IAAI,CAAC,UAAU,CAAC,aAA6B,CAAC,SAAS,GAAG,CAAC,CAAgB,KAAI;AAC9E,gBAAA,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;AAEzD,gBAAA,IAAI,CAAC,CAAC,GAAG,KAAK,KAAK,EAAE;oBACnB,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;gBACjD;AAEA,gBAAA,IAAI,IAAI,CAAC,WAAW,EAAE,KAAK,UAAU,EAAE;AACrC,oBAAA,QAAQ,CAAC,CAAC,GAAG;AACX,wBAAA,KAAK,WAAW;AACd,4BAAA,IAAI,CAAC,iBAAiB,CAAC,WAAW,CAAC;4BACnC;AACF,wBAAA,KAAK,SAAS;AACZ,4BAAA,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC;4BACjC;AACF,wBAAA,KAAK,WAAW;4BACd,IAAI,CAAC,uBAAuB,EAAE;4BAC9B;;gBAEN;AAAO,qBAAA,IAAI,IAAI,CAAC,WAAW,EAAE,KAAK,YAAY,EAAE;AAC9C,oBAAA,QAAQ,CAAC,CAAC,GAAG;AACX,wBAAA,KAAK,YAAY;AACf,4BAAA,IAAI,CAAC,iBAAiB,CAAC,WAAW,CAAC;4BACnC;AACF,wBAAA,KAAK,WAAW;AACd,4BAAA,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC;4BACjC;AACF,wBAAA,KAAK,SAAS;4BACZ,IAAI,CAAC,uBAAuB,EAAE;4BAC9B;;gBAEN;AACF,YAAA,CAAC;AACH,QAAA,CAAC,CAAC;AA0CH,IAAA;AArFC,IAAA,IAAI;AAOJ,IAAA,KAAK;AAsCG,IAAA,iBAAiB,CAAC,CAAS,EAAA;QACjC,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QAE/C,IAAI,CAAC,KAAK,SAAS,IAAI,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,EAAE;AAC7C,YAAA,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,IAAI,GAAG,CAAC,CAAC;YAC3C,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QACvC;AAAO,aAAA,IAAI,CAAC,KAAK,WAAW,IAAI,IAAI,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE;AAChF,YAAA,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,IAAI,GAAG,CAAC,CAAC;YAC3C,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QACvC;IACF;IAEQ,uBAAuB,GAAA;QAC7B,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AAE/C,QAAA,MAAM,qBAAqB,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,uBAAuB,EAAE;AAC5F,QAAA,IAAI,CAAC,qBAAqB;YAAE;QAC5B,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,iBAAiB,KAAK,qBAAqB,CAAC;AACpG,QAAA,IAAI,CAAC,UAAU;YAAE;QACjB,UAAU,CAAC,MAAK;AACb,YAAA,UAAU,CAAC,QAAQ,CAAC,aAAiC,CAAC,KAAK,EAAE;AAChE,QAAA,CAAC,CAAC;QACD,UAAU,CAAC,QAAQ,CAAC,aAAiC,CAAC,cAAc,CAAC,IAAI,CAAC,YAAY,CAAC;IAC1F;AAEA,IAAA,YAAY,CAAC,KAAa,EAAA;AACxB,QAAA,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,aAA4B;AACnF,QAAA,IAAI,CAAC,YAAY;YAAE;QACnB,UAAU,CAAC,MAAK;YACd,YAAY,CAAC,KAAK,EAAE;AACtB,QAAA,CAAC,CAAC;AACF,QAAA,YAAY,CAAC,cAAc,CAAC,IAAI,CAAC,YAAY,CAAC;IAChD;AAEA,IAAA,UAAU,CAAC,CAAgC,EAAA;QACzC,UAAU,CAAC,MAAK;AACb,YAAA,CAAC,CAAC,QAAQ,CAAC,aAA6B,CAAC,KAAK,EAAE;AACnD,QAAA,CAAC,CAAC;QACD,CAAC,CAAC,QAAQ,CAAC,aAA6B,CAAC,cAAc,CAAC,IAAI,CAAC,YAAY,CAAC;IAC7E;8GAjGW,yBAAyB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAAzB,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,yBAAyB,iVACA,6BAA6B,EAAA,WAAA,EAAA,IAAA,EAAA,QAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,CAAA,kBAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA,CAAA;;2FADtD,yBAAyB,EAAA,UAAA,EAAA,CAAA;kBAJrC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,oBAAoB;AAC9B,oBAAA,QAAQ,EAAE,kBAAkB;AAC7B,iBAAA;AAEqC,SAAA,CAAA,EAAA,cAAA,EAAA,EAAA,SAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,IAAA,EAAA,CAAA,EAAA,CAAA,UAAA,CAAA,MAAA,6BAA6B,CAAA,EAAA,EAAA,GAAE,EAAE,WAAW,EAAE,IAAI,EAAE,EAAA,QAAA,EAAA,IAAA,EAAA,CAAA,EAAA,CAAA,EAAA,mBAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,MAAA,EAAA,IAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,CAAA,EAAA,UAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,MAAA,EAAA,IAAA,EAAA,CAAA,YAAA,CAAA,EAAA,CAAA,EAAA,WAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,KAAA,EAAA,aAAA,EAAA,QAAA,EAAA,KAAA,EAAA,CAAA,EAAA,CAAA,EAAA,EAAA,CAAA;;MCX7E,6BAA6B,CAAA;AAJ1C,IAAA,WAAA,GAAA;AAKE,QAAA,IAAA,CAAA,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC;QAC7B,IAAA,CAAA,QAAQ,GAAG,MAAM,CAAC,KAAK;qFAAC;QACxB,IAAA,CAAA,KAAK,GAAG,MAAM,CAAC,CAAC;kFAAC;AACjB,QAAA,IAAA,CAAA,iBAAiB,GAAG,IAAI,CAAC,MAAM,EAAE;QACjC,IAAA,CAAA,uBAAuB,GAAG,MAAM,CAAC,IAAI;oGAAC;QACtC,IAAA,CAAA,UAAU,GAAG,MAAM,EAA8B;AAEzC,QAAA,IAAA,CAAA,MAAM,GAAG,MAAM,CAAC,yBAAyB,CAAC;AAC1C,QAAA,IAAA,CAAA,oBAAoB,GAAG,MAAM,CAAC,6BAA6B,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AAExG,QAAA,IAAA,CAAA,KAAK,GAAG,eAAe,CAAC,MAAK;YAC1B,IAAI,CAAC,QAAQ,CAAC,aAA6B,CAAC,SAAS,GAAG,CAAC,CAAgB,KAAI;AAC5E,gBAAA,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;AAC3D,YAAA,CAAC;YAEA,IAAI,CAAC,QAAQ,CAAC,aAA6B,CAAC,OAAO,GAAG,MAAK;AAC1D,gBAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;AACvB,gBAAA,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;AAC3C,YAAA,CAAC;YAEA,IAAI,CAAC,QAAQ,CAAC,aAA6B,CAAC,MAAM,GAAG,MAAK;AACzD,gBAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC;AAC1B,YAAA,CAAC;AAED,YAAA,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,iBAAiB;gBAAE;YACnD,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC;AAC/E,QAAA,CAAC,CAAC;AACH,IAAA;AAjBC,IAAA,KAAK;8GAXM,6BAA6B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;kGAA7B,6BAA6B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,wBAAA,EAAA,OAAA,EAAA,EAAA,UAAA,EAAA,YAAA,EAAA,EAAA,QAAA,EAAA,CAAA,sBAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA,CAAA;;2FAA7B,6BAA6B,EAAA,UAAA,EAAA,CAAA;kBAJzC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,wBAAwB;AAClC,oBAAA,QAAQ,EAAE,sBAAsB;AACjC,iBAAA;;;ACFD,MAAM,SAAS,GAAG,CAAC,yBAAyB,EAAE,6BAA6B,CAAC;AAE5E,MAAM,OAAO,GAAG,CAAC,YAAY,CAAC;MAOjB,sBAAsB,CAAA;8GAAtB,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,QAAA,EAAA,CAAA,CAAA;+GAAtB,sBAAsB,EAAA,OAAA,EAAA,CAPlB,YAAY,EAFV,yBAAyB,EAAE,6BAA6B,CAAA,EAAA,OAAA,EAAA,CAAxD,yBAAyB,EAAE,6BAA6B,CAAA,EAAA,CAAA,CAAA;AAS9D,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,mBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,sBAAsB,YAJpB,OAAO,CAAA,EAAA,CAAA,CAAA;;2FAIT,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBALlC,QAAQ;AAAC,YAAA,IAAA,EAAA,CAAA;AACR,oBAAA,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,GAAG,SAAS,CAAC;AACnC,oBAAA,OAAO,EAAE,CAAC,GAAG,SAAS,CAAC;AACvB,oBAAA,SAAS,EAAE,EAAE;AACd,iBAAA;;;ACbD;;AAEG;;;;"}
|
|
1
|
+
{"version":3,"file":"acorex-cdk-list-navigation.mjs","sources":["../../../../packages/cdk/list-navigation/src/lib/list-navigation.directive.ts","../../../../packages/cdk/list-navigation/src/lib/list-navigation-item.directive.ts","../../../../packages/cdk/list-navigation/src/lib/list-navigation.module.ts","../../../../packages/cdk/list-navigation/src/acorex-cdk-list-navigation.ts"],"sourcesContent":["import { AXHtmlEvent } from '@acorex/cdk/common';\nimport {\n afterNextRender,\n contentChildren,\n Directive,\n effect,\n ElementRef,\n inject,\n input,\n output,\n signal,\n} from '@angular/core';\nimport { AXListNavigationItemDirective } from './list-navigation-item.directive';\n\n@Directive({\n selector: '[axListNavigation]',\n exportAs: 'axListNavigation',\n})\nexport class AXListNavigationDirective {\n private childElem = contentChildren(AXListNavigationItemDirective, { descendants: true });\n private elementRef = inject(ElementRef);\n activeIndex = signal(0);\n onNavigationChanged = output<{ sender: AXListNavigationDirective }>();\n onKeypress = output<AXHtmlEvent<KeyboardEvent>>();\n orientation = input<'horizontal' | 'vertical'>('vertical');\n\n private scrollOption: ScrollIntoViewOptions = {\n behavior: 'smooth',\n block: 'nearest',\n };\n\n #eff = effect(() => {\n this.childElem().forEach((item, index) => {\n (item.itemElem.nativeElement as HTMLElement).tabIndex = 0;\n item.index.set(index);\n });\n });\n\n #init = afterNextRender(() => {\n (this.elementRef.nativeElement as HTMLElement).tabIndex = -1;\n\n (this.elementRef.nativeElement as HTMLElement).onkeydown = (e: KeyboardEvent) => {\n this.onKeypress.emit({ component: this, nativeEvent: e });\n\n if (e.key === 'Tab') {\n this.onNavigationChanged.emit({ sender: this });\n }\n\n if (this.orientation() === 'vertical') {\n switch (e.key) {\n case 'ArrowDown':\n this.navigationHandler('ArrowDown');\n break;\n case 'ArrowUp':\n this.navigationHandler('ArrowUp');\n break;\n case 'ArrowLeft':\n this.parentNavigationHandler();\n break;\n }\n } else if (this.orientation() === 'horizontal') {\n switch (e.key) {\n case 'ArrowRight':\n this.navigationHandler('ArrowDown');\n break;\n case 'ArrowLeft':\n this.navigationHandler('ArrowUp');\n break;\n case 'ArrowUp':\n this.parentNavigationHandler();\n break;\n }\n }\n };\n });\n\n private navigationHandler(e: string) {\n this.onNavigationChanged.emit({ sender: this });\n\n if (e === 'ArrowUp' && this.activeIndex() > 0) {\n this.activeIndex.update((prev) => prev - 1);\n this.focusOnIndex(this.activeIndex());\n } else if (e === 'ArrowDown' && this.activeIndex() < this.childElem().length - 1) {\n this.activeIndex.update((prev) => prev + 1);\n this.focusOnIndex(this.activeIndex());\n }\n }\n\n private parentNavigationHandler() {\n this.onNavigationChanged.emit({ sender: this });\n\n const selectedItemParentKey = this.childElem()[this.activeIndex()].navigationParentItemKey();\n if (!selectedItemParentKey) return;\n const parentElem = this.childElem().find((item) => item.navigationItemKey === selectedItemParentKey);\n if (!parentElem) return;\n setTimeout(() => {\n (parentElem.itemElem.nativeElement as HTMLAreaElement).focus();\n });\n (parentElem.itemElem.nativeElement as HTMLAreaElement).scrollIntoView(this.scrollOption);\n }\n\n focusOnIndex(index: number) {\n const selectedItem = this.childElem()[index]?.itemElem.nativeElement as HTMLElement;\n if (!selectedItem) return;\n setTimeout(() => {\n selectedItem.focus();\n });\n selectedItem.scrollIntoView(this.scrollOption);\n }\n\n navigateTo(e: AXListNavigationItemDirective) {\n setTimeout(() => {\n (e.itemElem.nativeElement as HTMLElement).focus();\n });\n (e.itemElem.nativeElement as HTMLElement).scrollIntoView(this.scrollOption);\n }\n\n /**\n * Highlights a list option on pointer hover without moving focus.\n * Use when focus must stay on an external trigger (e.g. searchable lookup input).\n */\n highlightItem(item: AXListNavigationItemDirective): void {\n const items = this.childElem();\n this.activeIndex.set(item.index());\n for (const child of items) {\n child.isActive.set(child === item);\n }\n }\n}\n","import { AXHtmlEvent } from '@acorex/cdk/common';\nimport { afterNextRender, Directive, ElementRef, inject, output, signal } from '@angular/core';\nimport { AXListNavigationDirective } from './list-navigation.directive';\n\n@Directive({\n selector: '[axListNavigationItem]',\n exportAs: 'axListNavigationItem',\n})\nexport class AXListNavigationItemDirective {\n itemElem = inject(ElementRef);\n isActive = signal(false);\n index = signal(0);\n navigationItemKey = Math.random();\n navigationParentItemKey = signal(null);\n onKeypress = output<AXHtmlEvent<KeyboardEvent>>();\n\n private parent = inject(AXListNavigationDirective);\n private injectItemInsideItem = inject(AXListNavigationItemDirective, { optional: true, skipSelf: true });\n\n #init = afterNextRender(() => {\n (this.itemElem.nativeElement as HTMLElement).onkeydown = (e: KeyboardEvent) => {\n this.onKeypress.emit({ component: this, nativeEvent: e });\n };\n\n (this.itemElem.nativeElement as HTMLElement).onfocus = () => {\n this.isActive.set(true);\n this.parent.activeIndex.set(this.index());\n };\n\n (this.itemElem.nativeElement as HTMLElement).onblur = () => {\n this.isActive.set(false);\n };\n\n if (!this.injectItemInsideItem?.navigationItemKey) return;\n this.navigationParentItemKey.set(this.injectItemInsideItem.navigationItemKey);\n });\n}\n","import { CommonModule } from '@angular/common';\nimport { NgModule } from '@angular/core';\nimport { AXListNavigationItemDirective } from './list-navigation-item.directive';\nimport { AXListNavigationDirective } from './list-navigation.directive';\n\nconst COMPONENT = [AXListNavigationDirective, AXListNavigationItemDirective];\n\nconst MODULES = [CommonModule];\n\n@NgModule({\n imports: [...MODULES, ...COMPONENT],\n exports: [...COMPONENT],\n providers: [],\n})\nexport class AXListNavigationModule {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -31,6 +31,8 @@ class AXOutlineContainerDirective {
|
|
|
31
31
|
...(ngDevMode ? [{ debugName: "scrollTop" }] : /* istanbul ignore next */ []));
|
|
32
32
|
this.outlineItems = signal([], /* @ts-ignore */
|
|
33
33
|
...(ngDevMode ? [{ debugName: "outlineItems" }] : /* istanbul ignore next */ []));
|
|
34
|
+
this.lastScrollSpyIndex = 0;
|
|
35
|
+
this.heldActiveIndex = null;
|
|
34
36
|
this.scrollableElement = computed(() => {
|
|
35
37
|
const scrollableElementId = this.scrollableElementId();
|
|
36
38
|
if (scrollableElementId) {
|
|
@@ -51,12 +53,12 @@ class AXOutlineContainerDirective {
|
|
|
51
53
|
this.scrollableElement().style.scrollBehavior = 'smooth';
|
|
52
54
|
}
|
|
53
55
|
this.zone.runOutsideAngular(() => {
|
|
54
|
-
const scrollable = this.
|
|
56
|
+
const scrollable = this.resolveScrollEventTarget();
|
|
55
57
|
fromEvent(scrollable, 'scroll')
|
|
56
|
-
.pipe(this.unsubscriber.takeUntilDestroy, map(() => this.
|
|
58
|
+
.pipe(this.unsubscriber.takeUntilDestroy, map(() => this.readScrollTop()))
|
|
57
59
|
.subscribe((scrollTop) => {
|
|
58
60
|
this.scrollTop.set(scrollTop);
|
|
59
|
-
this.scrollChanged(scrollTop);
|
|
61
|
+
this.zone.run(() => this.scrollChanged(scrollTop));
|
|
60
62
|
});
|
|
61
63
|
this.mutationObserver = new MutationObserver((mutationsList) => {
|
|
62
64
|
const relevantMutation = mutationsList.some((mutation) => mutation.type === 'childList' && (mutation.addedNodes.length > 0 || mutation.removedNodes.length > 0));
|
|
@@ -68,12 +70,36 @@ class AXOutlineContainerDirective {
|
|
|
68
70
|
childList: true,
|
|
69
71
|
subtree: true,
|
|
70
72
|
});
|
|
73
|
+
this.bindUserScrollIntent(scrollable);
|
|
71
74
|
});
|
|
75
|
+
fromEvent(this.el.nativeElement, 'click', { capture: true })
|
|
76
|
+
.pipe(this.unsubscriber.takeUntilDestroy)
|
|
77
|
+
.subscribe((event) => {
|
|
78
|
+
if (event instanceof MouseEvent) {
|
|
79
|
+
this.handleInContentOutlineLinkClick(event);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
const view = this.document.defaultView;
|
|
83
|
+
if (view) {
|
|
84
|
+
fromEvent(view, 'hashchange')
|
|
85
|
+
.pipe(this.unsubscriber.takeUntilDestroy)
|
|
86
|
+
.subscribe(() => {
|
|
87
|
+
const id = decodeURIComponent(view.location.hash?.slice(1) ?? '');
|
|
88
|
+
if (!id || !this.outlineItems().some((item) => item.id === id)) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
this.heldActiveIndex = null;
|
|
92
|
+
const index = this.outlineItems().findIndex((item) => item.id === id);
|
|
93
|
+
this.lastScrollSpyIndex = index;
|
|
94
|
+
this.applyActiveIndex(index);
|
|
95
|
+
});
|
|
96
|
+
}
|
|
72
97
|
this.mutationSubject
|
|
73
98
|
.pipe(debounceTime(this.MUTATION_DEBOUNCE_TIME), this.unsubscriber.takeUntilDestroy)
|
|
74
99
|
.subscribe(() => {
|
|
75
100
|
this.refreshOutlineItems();
|
|
76
101
|
});
|
|
102
|
+
this.zone.run(() => this.scrollChanged(this.readScrollTop()));
|
|
77
103
|
});
|
|
78
104
|
}
|
|
79
105
|
#anr;
|
|
@@ -87,68 +113,236 @@ class AXOutlineContainerDirective {
|
|
|
87
113
|
this.refreshOutlineItems();
|
|
88
114
|
}
|
|
89
115
|
}
|
|
90
|
-
|
|
91
|
-
this.
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
116
|
+
scrollToItem(id) {
|
|
117
|
+
this.scrollToItemFromHash(true, id);
|
|
118
|
+
}
|
|
119
|
+
resolveScrollEventTarget() {
|
|
120
|
+
const scrollable = this.scrollableElement();
|
|
121
|
+
if (scrollable === this.document.documentElement || scrollable.tagName === 'HTML') {
|
|
122
|
+
return this.document.defaultView ?? scrollable;
|
|
123
|
+
}
|
|
124
|
+
return scrollable;
|
|
125
|
+
}
|
|
126
|
+
readScrollTop() {
|
|
127
|
+
const scrollable = this.scrollableElement();
|
|
128
|
+
if (scrollable === this.document.documentElement || scrollable.tagName === 'HTML') {
|
|
129
|
+
return this.document.defaultView?.scrollY ?? scrollable.scrollTop;
|
|
130
|
+
}
|
|
131
|
+
return scrollable.scrollTop;
|
|
132
|
+
}
|
|
133
|
+
handleInContentOutlineLinkClick(event) {
|
|
134
|
+
const target = event.target;
|
|
135
|
+
if (!(target instanceof Element)) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const anchor = target.closest('a');
|
|
139
|
+
if (!anchor || anchor.classList.contains('ax-outline-hash-link')) {
|
|
140
|
+
if (anchor?.classList.contains('ax-outline-hash-link')) {
|
|
141
|
+
const id = this.getOutlineIdFromHref(anchor.getAttribute('href'));
|
|
142
|
+
if (id) {
|
|
143
|
+
event.preventDefault();
|
|
144
|
+
this.scrollToItem(id);
|
|
106
145
|
}
|
|
107
146
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const id = this.getOutlineIdFromHref(anchor.getAttribute('href'));
|
|
150
|
+
if (!id || !this.outlineItems().some((item) => item.id === id)) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
event.preventDefault();
|
|
154
|
+
this.scrollToItem(id);
|
|
155
|
+
}
|
|
156
|
+
scrollToItemFromHash(scrollToTarget, explicitId) {
|
|
157
|
+
const id = explicitId ?? decodeURIComponent(this.document.defaultView?.location.hash?.slice(1) ?? '');
|
|
158
|
+
if (!id) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const item = this.outlineItems().find((entry) => entry.id === id);
|
|
162
|
+
if (!item) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const activeIndex = this.outlineItems().findIndex((entry) => entry.id === id);
|
|
166
|
+
if (activeIndex < 0) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
this.heldActiveIndex = activeIndex;
|
|
170
|
+
this.lastScrollSpyIndex = activeIndex;
|
|
171
|
+
this.applyActiveIndex(activeIndex);
|
|
172
|
+
if (!scrollToTarget) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
this.syncLocationHash(id);
|
|
176
|
+
const offset = this.activationOffset();
|
|
177
|
+
const scrollable = this.scrollableElement();
|
|
178
|
+
const isWindow = scrollable === this.document.documentElement ||
|
|
179
|
+
scrollable.tagName === 'HTML' ||
|
|
180
|
+
this.resolveScrollEventTarget() === this.document.defaultView;
|
|
181
|
+
const itemRect = item.el.getBoundingClientRect();
|
|
182
|
+
if (isWindow) {
|
|
183
|
+
const top = itemRect.top + (this.document.defaultView?.scrollY ?? 0) - offset;
|
|
184
|
+
this.document.defaultView?.scrollTo({
|
|
185
|
+
top: Math.max(0, top),
|
|
186
|
+
behavior: this.smoothScroll() ? 'smooth' : 'auto',
|
|
187
|
+
});
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
const scrollableRect = scrollable.getBoundingClientRect();
|
|
191
|
+
const top = scrollable.scrollTop + (itemRect.top - scrollableRect.top) - offset;
|
|
192
|
+
const maxScrollTop = Math.max(0, scrollable.scrollHeight - scrollable.clientHeight);
|
|
193
|
+
scrollable.scrollTo({
|
|
194
|
+
top: Math.max(0, Math.min(top, maxScrollTop)),
|
|
195
|
+
behavior: this.smoothScroll() ? 'smooth' : 'auto',
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
releaseHeldActiveIndex() {
|
|
199
|
+
if (this.heldActiveIndex === null) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
this.stopOngoingSmoothScroll();
|
|
203
|
+
this.heldActiveIndex = null;
|
|
204
|
+
this.scrollChanged(this.readScrollTop());
|
|
205
|
+
}
|
|
206
|
+
stopOngoingSmoothScroll() {
|
|
207
|
+
const scrollable = this.scrollableElement();
|
|
208
|
+
const isWindow = scrollable === this.document.documentElement ||
|
|
209
|
+
scrollable.tagName === 'HTML' ||
|
|
210
|
+
this.resolveScrollEventTarget() === this.document.defaultView;
|
|
211
|
+
if (isWindow) {
|
|
212
|
+
const view = this.document.defaultView;
|
|
213
|
+
view?.scrollTo({ top: view.scrollY, behavior: 'auto' });
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
scrollable.scrollTo({ top: scrollable.scrollTop, behavior: 'auto' });
|
|
217
|
+
}
|
|
218
|
+
getOutlineIdFromHref(href) {
|
|
219
|
+
if (!href || !href.includes('#')) {
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
const id = decodeURIComponent(href.split('#')[1] ?? '');
|
|
223
|
+
return id || null;
|
|
224
|
+
}
|
|
225
|
+
syncLocationHash(id) {
|
|
226
|
+
const view = this.document.defaultView;
|
|
227
|
+
if (!view || view.location.hash === `#${id}`) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
view.history.pushState(null, '', `#${id}`);
|
|
231
|
+
}
|
|
232
|
+
scrollChanged(scrollTop) {
|
|
233
|
+
if (this.heldActiveIndex !== null) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
const activeIndex = this.resolveActiveIndex(scrollTop);
|
|
237
|
+
if (activeIndex === this.lastScrollSpyIndex) {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
this.lastScrollSpyIndex = activeIndex;
|
|
241
|
+
this.applyActiveIndex(activeIndex);
|
|
242
|
+
}
|
|
243
|
+
bindUserScrollIntent(scrollable) {
|
|
244
|
+
const releaseHold = () => {
|
|
245
|
+
this.zone.run(() => this.releaseHeldActiveIndex());
|
|
246
|
+
};
|
|
247
|
+
fromEvent(scrollable, 'wheel', { passive: true }).pipe(this.unsubscriber.takeUntilDestroy).subscribe(releaseHold);
|
|
248
|
+
fromEvent(scrollable, 'touchmove', { passive: true })
|
|
249
|
+
.pipe(this.unsubscriber.takeUntilDestroy)
|
|
250
|
+
.subscribe(releaseHold);
|
|
251
|
+
fromEvent(scrollable, 'pointerdown', { passive: true })
|
|
252
|
+
.pipe(this.unsubscriber.takeUntilDestroy)
|
|
253
|
+
.subscribe(releaseHold);
|
|
254
|
+
fromEvent(scrollable, 'keydown')
|
|
255
|
+
.pipe(this.unsubscriber.takeUntilDestroy)
|
|
256
|
+
.subscribe((event) => {
|
|
257
|
+
if (!(event instanceof KeyboardEvent)) {
|
|
258
|
+
return;
|
|
118
259
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
activeIndex = i;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
const lastReachableIndex = firstUnreachableIndex - 1;
|
|
126
|
-
const zoneStart = lastReachableIndex >= 0 ? prevItems[lastReachableIndex].scrollY - offset : 0;
|
|
127
|
-
const zoneRange = maxScrollTop - zoneStart;
|
|
128
|
-
if (zoneRange <= 0) {
|
|
129
|
-
activeIndex = this.activateLastAtBottom()
|
|
130
|
-
? prevItems.length - 1
|
|
131
|
-
: Math.max(0, lastReachableIndex);
|
|
132
|
-
}
|
|
133
|
-
else if (scrollTop >= zoneStart) {
|
|
134
|
-
// Map the remaining scroll range across the last reachable item and all
|
|
135
|
-
// unreachable trailing items so short end sections are not skipped.
|
|
136
|
-
const progress = Math.min(1, Math.max(0, (scrollTop - zoneStart) / zoneRange));
|
|
137
|
-
const startIndex = Math.max(0, lastReachableIndex);
|
|
138
|
-
const span = prevItems.length - 1 - startIndex;
|
|
139
|
-
if (progress >= 1 || (isAtBottom && this.activateLastAtBottom())) {
|
|
140
|
-
activeIndex = prevItems.length - 1;
|
|
141
|
-
}
|
|
142
|
-
else {
|
|
143
|
-
activeIndex = startIndex + Math.floor(progress * span);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
260
|
+
const scrollKeys = ['ArrowUp', 'ArrowDown', 'PageUp', 'PageDown', 'Home', 'End', ' '];
|
|
261
|
+
if (scrollKeys.includes(event.key)) {
|
|
262
|
+
releaseHold();
|
|
146
263
|
}
|
|
147
|
-
return prevItems.map((item, index) => ({
|
|
148
|
-
...item,
|
|
149
|
-
active: index === activeIndex,
|
|
150
|
-
}));
|
|
151
264
|
});
|
|
265
|
+
}
|
|
266
|
+
resolveActiveIndex(scrollTop) {
|
|
267
|
+
const prevItems = this.outlineItems();
|
|
268
|
+
if (prevItems.length === 0) {
|
|
269
|
+
return -1;
|
|
270
|
+
}
|
|
271
|
+
if (prevItems.length === 1) {
|
|
272
|
+
return 0;
|
|
273
|
+
}
|
|
274
|
+
const scrollable = this.scrollableElement();
|
|
275
|
+
const offset = this.activationOffset();
|
|
276
|
+
const maxScrollTop = Math.max(0, scrollable.scrollHeight - scrollable.clientHeight);
|
|
277
|
+
const scrollableRect = scrollable.getBoundingClientRect();
|
|
278
|
+
const activationScrollTops = prevItems.map((item) => {
|
|
279
|
+
const itemTop = item.el.getBoundingClientRect().top;
|
|
280
|
+
return scrollTop + (itemTop - scrollableRect.top) - offset;
|
|
281
|
+
});
|
|
282
|
+
const count = prevItems.length;
|
|
283
|
+
if (this.activateLastAtBottom() && maxScrollTop > 0 && scrollTop >= maxScrollTop - 1) {
|
|
284
|
+
return count - 1;
|
|
285
|
+
}
|
|
286
|
+
let thresholdIndex = 0;
|
|
287
|
+
for (let i = 0; i < count; i++) {
|
|
288
|
+
if (activationScrollTops[i] <= scrollTop) {
|
|
289
|
+
thresholdIndex = i;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
const slotIndex = this.resolveByScrollSlots(scrollTop, activationScrollTops, maxScrollTop);
|
|
293
|
+
if (slotIndex <= thresholdIndex) {
|
|
294
|
+
return thresholdIndex;
|
|
295
|
+
}
|
|
296
|
+
const minSlot = Math.max(1, maxScrollTop / Math.max(count * 6, 1));
|
|
297
|
+
const slotActivation = activationScrollTops[slotIndex];
|
|
298
|
+
if (scrollTop >= slotActivation - minSlot) {
|
|
299
|
+
return slotIndex;
|
|
300
|
+
}
|
|
301
|
+
return thresholdIndex;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Maps scroll position to the active outline item. Sections with little content often
|
|
305
|
+
* have overlapping activation thresholds; each section gets a minimum scroll slot so
|
|
306
|
+
* short blocks are not skipped while scrolling.
|
|
307
|
+
*/
|
|
308
|
+
resolveByScrollSlots(scrollTop, activationScrollTops, maxScrollTop) {
|
|
309
|
+
const count = activationScrollTops.length;
|
|
310
|
+
if (maxScrollTop <= 0) {
|
|
311
|
+
return 0;
|
|
312
|
+
}
|
|
313
|
+
const minSlot = Math.max(1, maxScrollTop / Math.max(count * 6, 1));
|
|
314
|
+
const weights = [];
|
|
315
|
+
for (let i = 0; i < count; i++) {
|
|
316
|
+
const sectionStart = Math.max(0, Math.min(activationScrollTops[i], maxScrollTop));
|
|
317
|
+
let sectionEnd = maxScrollTop;
|
|
318
|
+
if (i < count - 1) {
|
|
319
|
+
sectionEnd = Math.max(sectionStart, Math.min(activationScrollTops[i + 1], maxScrollTop));
|
|
320
|
+
}
|
|
321
|
+
weights.push(Math.max(minSlot, sectionEnd - sectionStart));
|
|
322
|
+
}
|
|
323
|
+
const totalWeight = weights.reduce((sum, weight) => sum + weight, 0);
|
|
324
|
+
const scaledPosition = (scrollTop / maxScrollTop) * totalWeight;
|
|
325
|
+
let consumed = 0;
|
|
326
|
+
for (let i = 0; i < count; i++) {
|
|
327
|
+
consumed += weights[i];
|
|
328
|
+
if (scaledPosition <= consumed || i === count - 1) {
|
|
329
|
+
return i;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return count - 1;
|
|
333
|
+
}
|
|
334
|
+
applyActiveIndex(activeIndex) {
|
|
335
|
+
if (activeIndex < 0) {
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
const current = this.outlineItems();
|
|
339
|
+
if (current.length > 0 && current.every((item, index) => item.active === (index === activeIndex))) {
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
this.outlineItems.update((prevItems) => prevItems.map((item, index) => ({
|
|
343
|
+
...item,
|
|
344
|
+
active: index === activeIndex,
|
|
345
|
+
})));
|
|
152
346
|
this.outlineItems$.next(this.outlineItems());
|
|
153
347
|
}
|
|
154
348
|
setOutlineItems() {
|
|
@@ -168,7 +362,7 @@ class AXOutlineContainerDirective {
|
|
|
168
362
|
const htmlEl = el;
|
|
169
363
|
let fragment = htmlEl.id;
|
|
170
364
|
if (!fragment) {
|
|
171
|
-
const textContentForId = htmlEl.textContent?.trim() ?? '';
|
|
365
|
+
const textContentForId = htmlEl.textContent?.trim() ?? '';
|
|
172
366
|
if (textContentForId) {
|
|
173
367
|
fragment = `${textContentForId.toLowerCase().replace(/\s+/g, '-')}`;
|
|
174
368
|
let counter = 1;
|
|
@@ -181,7 +375,7 @@ class AXOutlineContainerDirective {
|
|
|
181
375
|
else {
|
|
182
376
|
fragment = `ax-outline-${Math.random().toString(36).slice(2, 7)}`;
|
|
183
377
|
}
|
|
184
|
-
htmlEl.id = fragment;
|
|
378
|
+
htmlEl.id = fragment;
|
|
185
379
|
}
|
|
186
380
|
htmlEl.style.scrollMargin = `${this.activationOffset()}px`;
|
|
187
381
|
const existingLink = htmlEl.querySelector('a.ax-outline-hash-link');
|
|
@@ -193,8 +387,7 @@ class AXOutlineContainerDirective {
|
|
|
193
387
|
anchor.textContent = '#';
|
|
194
388
|
anchor.href = `${window.location.pathname}${window.location.search}#${fragment}`;
|
|
195
389
|
anchor.classList.add('ax-outline-hash-link');
|
|
196
|
-
|
|
197
|
-
anchor.style.paddingInlineStart = '0.5rem'; // Adjust as needed
|
|
390
|
+
anchor.style.paddingInlineStart = '0.5rem';
|
|
198
391
|
anchor.style.opacity = '0';
|
|
199
392
|
anchor.style.transition = 'opacity 0.2s ease-in-out';
|
|
200
393
|
anchor.style.cursor = 'pointer';
|
|
@@ -206,7 +399,10 @@ class AXOutlineContainerDirective {
|
|
|
206
399
|
htmlEl.addEventListener('mouseleave', leaveListener);
|
|
207
400
|
htmlEl.appendChild(anchor);
|
|
208
401
|
if (this.copyUrlOnClick()) {
|
|
209
|
-
anchor.addEventListener('click', async () => {
|
|
402
|
+
anchor.addEventListener('click', async (event) => {
|
|
403
|
+
event.preventDefault();
|
|
404
|
+
event.stopPropagation();
|
|
405
|
+
this.scrollToItem(fragment);
|
|
210
406
|
try {
|
|
211
407
|
await this.clipboardService.copy(anchor.href);
|
|
212
408
|
}
|
|
@@ -217,7 +413,6 @@ class AXOutlineContainerDirective {
|
|
|
217
413
|
}
|
|
218
414
|
}
|
|
219
415
|
const parentId = htmlEl.getAttribute('data-parent') ?? undefined;
|
|
220
|
-
// Calculate position relative to the scrollable element
|
|
221
416
|
const scrollableElement = this.scrollableElement();
|
|
222
417
|
const scrollableRect = scrollableElement?.getBoundingClientRect() ?? { top: 0 };
|
|
223
418
|
const elementRect = htmlEl.getBoundingClientRect();
|
|
@@ -233,7 +428,15 @@ class AXOutlineContainerDirective {
|
|
|
233
428
|
})
|
|
234
429
|
.sort((a, b) => a.scrollY - b.scrollY);
|
|
235
430
|
this.outlineItems.set(outlineItems);
|
|
236
|
-
|
|
431
|
+
const hashId = decodeURIComponent(this.document.defaultView?.location.hash?.slice(1) ?? '');
|
|
432
|
+
if (hashId && outlineItems.some((item) => item.id === hashId)) {
|
|
433
|
+
const hashIndex = outlineItems.findIndex((item) => item.id === hashId);
|
|
434
|
+
this.lastScrollSpyIndex = hashIndex;
|
|
435
|
+
this.applyActiveIndex(hashIndex);
|
|
436
|
+
}
|
|
437
|
+
else {
|
|
438
|
+
this.scrollChanged(this.readScrollTop());
|
|
439
|
+
}
|
|
237
440
|
if (this.mutationObserver) {
|
|
238
441
|
this.mutationObserver.observe(this.el.nativeElement, {
|
|
239
442
|
childList: true,
|
|
@@ -245,10 +448,10 @@ class AXOutlineContainerDirective {
|
|
|
245
448
|
refreshOutlineItems() {
|
|
246
449
|
this.setOutlineItems();
|
|
247
450
|
}
|
|
248
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.
|
|
249
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.
|
|
451
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: AXOutlineContainerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
452
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.6", type: AXOutlineContainerDirective, isStandalone: true, selector: "[axOutlineContainer]", inputs: { target: { classPropertyName: "target", publicName: "target", isSignal: true, isRequired: false, transformFunction: null }, smoothScroll: { classPropertyName: "smoothScroll", publicName: "smoothScroll", isSignal: true, isRequired: false, transformFunction: null }, showHashItem: { classPropertyName: "showHashItem", publicName: "showHashItem", isSignal: true, isRequired: false, transformFunction: null }, activationOffset: { classPropertyName: "activationOffset", publicName: "activationOffset", isSignal: true, isRequired: false, transformFunction: null }, copyUrlOnClick: { classPropertyName: "copyUrlOnClick", publicName: "copyUrlOnClick", isSignal: true, isRequired: false, transformFunction: null }, activateLastAtBottom: { classPropertyName: "activateLastAtBottom", publicName: "activateLastAtBottom", isSignal: true, isRequired: false, transformFunction: null }, scrollableElementId: { classPropertyName: "scrollableElementId", publicName: "scrollableElementId", isSignal: true, isRequired: false, transformFunction: null } }, providers: [AXUnsubscriber, AXClipBoardService], exportAs: ["axOutlineContainer"], ngImport: i0 }); }
|
|
250
453
|
}
|
|
251
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
454
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: AXOutlineContainerDirective, decorators: [{
|
|
252
455
|
type: Directive,
|
|
253
456
|
args: [{
|
|
254
457
|
selector: '[axOutlineContainer]',
|
|
@@ -271,7 +474,7 @@ class AXOutlineItemDirective {
|
|
|
271
474
|
if (!this.id()) {
|
|
272
475
|
const textContent = this.el.nativeElement.textContent.trim();
|
|
273
476
|
if (textContent) {
|
|
274
|
-
newId = `${textContent.replace(/\s+/g, '-')}`;
|
|
477
|
+
newId = `${textContent.toLowerCase().replace(/\s+/g, '-')}`;
|
|
275
478
|
}
|
|
276
479
|
else {
|
|
277
480
|
newId = `${Math.random().toString(36).slice(2, 7)}`;
|
|
@@ -281,10 +484,10 @@ class AXOutlineItemDirective {
|
|
|
281
484
|
});
|
|
282
485
|
}
|
|
283
486
|
#anr;
|
|
284
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.
|
|
285
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.
|
|
487
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: AXOutlineItemDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
488
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.6", type: AXOutlineItemDirective, isStandalone: true, selector: "[axOutlineItem]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, exportAs: ["axOutlineItem"], ngImport: i0 }); }
|
|
286
489
|
}
|
|
287
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
490
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: AXOutlineItemDirective, decorators: [{
|
|
288
491
|
type: Directive,
|
|
289
492
|
args: [{
|
|
290
493
|
selector: '[axOutlineItem]',
|