@jump-section/core 1.0.22 → 1.0.24

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/dist/index.d.mts CHANGED
@@ -7,6 +7,10 @@ interface ScrollOptions {
7
7
  root?: HTMLElement | null;
8
8
  /** Alt+ArrowDown/Up 키보드 네비게이션을 활성화합니다 */
9
9
  keyboard?: boolean;
10
+ /** 디버그 모드를 활성화하여 섹션 경계 및 상태를 시각화합니다 */
11
+ debug?: boolean;
12
+ /** IntersectionObserver의 rootMargin을 커스터마이징합니다. 기본값: "-20% 0px -60% 0px" */
13
+ rootMargin?: string;
10
14
  }
11
15
  interface ActiveChangeMeta {
12
16
  /** 이전에 활성화된 섹션 ID */
@@ -32,6 +36,7 @@ declare class ScrollManager {
32
36
  private scrollHandler;
33
37
  private popstateHandler;
34
38
  private notifyScheduled;
39
+ private debugElements;
35
40
  constructor(options?: ScrollOptions);
36
41
  private get scrollRoot();
37
42
  private get currentScrollTop();
@@ -42,7 +47,14 @@ declare class ScrollManager {
42
47
  private handleIntersection;
43
48
  private scheduleNotify;
44
49
  private updateProgress;
45
- /** 섹션을 등록하고 IntersectionObserver로 감시합니다 */
50
+ private createDebugOverlay;
51
+ private updateDebugOverlays;
52
+ private updateDebugActiveState;
53
+ private removeDebugOverlay;
54
+ /**
55
+ * 섹션을 등록하고 IntersectionObserver로 감시합니다.
56
+ * @note `debug: true` 옵션 활성화 시, 오버레이 표시를 위해 `position` 스타일이 `relative`로 변경될 수 있습니다.
57
+ */
46
58
  registerSection(id: string, element: HTMLElement): void;
47
59
  /** 섹션 등록을 해제하고 감시를 중지합니다 */
48
60
  unregisterSection(id: string): void;
@@ -66,9 +78,13 @@ declare class ScrollManager {
66
78
  scrollToLast(): Promise<void>;
67
79
  /** 활성 섹션 변경 이벤트를 구독합니다 */
68
80
  onActiveChange(callback: ActiveChangeCallback): () => void;
81
+ /** 활성 섹션 변경 구독을 해제합니다 */
82
+ offActiveChange(callback: ActiveChangeCallback): void;
69
83
  private notifyListeners;
70
- /** 특정 섹션의 스크롤 진행률 이벤트를 구독합니다 */
84
+ /** 특정 섹션의 스크롤 진행률(0~1) 변경 호출될 콜백을 등록합니다 */
71
85
  onProgressChange(sectionId: string, callback: ProgressCallback): () => void;
86
+ /** 특정 섹션의 스크롤 진행률 구독을 해제합니다 */
87
+ offProgressChange(sectionId: string, callback: ProgressCallback): void;
72
88
  /** 등록된 모든 이벤트 리스너와 Observer를 해제하고 정리합니다 */
73
89
  destroy(): void;
74
90
  }
package/dist/index.d.ts CHANGED
@@ -7,6 +7,10 @@ interface ScrollOptions {
7
7
  root?: HTMLElement | null;
8
8
  /** Alt+ArrowDown/Up 키보드 네비게이션을 활성화합니다 */
9
9
  keyboard?: boolean;
10
+ /** 디버그 모드를 활성화하여 섹션 경계 및 상태를 시각화합니다 */
11
+ debug?: boolean;
12
+ /** IntersectionObserver의 rootMargin을 커스터마이징합니다. 기본값: "-20% 0px -60% 0px" */
13
+ rootMargin?: string;
10
14
  }
11
15
  interface ActiveChangeMeta {
12
16
  /** 이전에 활성화된 섹션 ID */
@@ -32,6 +36,7 @@ declare class ScrollManager {
32
36
  private scrollHandler;
33
37
  private popstateHandler;
34
38
  private notifyScheduled;
39
+ private debugElements;
35
40
  constructor(options?: ScrollOptions);
36
41
  private get scrollRoot();
37
42
  private get currentScrollTop();
@@ -42,7 +47,14 @@ declare class ScrollManager {
42
47
  private handleIntersection;
43
48
  private scheduleNotify;
44
49
  private updateProgress;
45
- /** 섹션을 등록하고 IntersectionObserver로 감시합니다 */
50
+ private createDebugOverlay;
51
+ private updateDebugOverlays;
52
+ private updateDebugActiveState;
53
+ private removeDebugOverlay;
54
+ /**
55
+ * 섹션을 등록하고 IntersectionObserver로 감시합니다.
56
+ * @note `debug: true` 옵션 활성화 시, 오버레이 표시를 위해 `position` 스타일이 `relative`로 변경될 수 있습니다.
57
+ */
46
58
  registerSection(id: string, element: HTMLElement): void;
47
59
  /** 섹션 등록을 해제하고 감시를 중지합니다 */
48
60
  unregisterSection(id: string): void;
@@ -66,9 +78,13 @@ declare class ScrollManager {
66
78
  scrollToLast(): Promise<void>;
67
79
  /** 활성 섹션 변경 이벤트를 구독합니다 */
68
80
  onActiveChange(callback: ActiveChangeCallback): () => void;
81
+ /** 활성 섹션 변경 구독을 해제합니다 */
82
+ offActiveChange(callback: ActiveChangeCallback): void;
69
83
  private notifyListeners;
70
- /** 특정 섹션의 스크롤 진행률 이벤트를 구독합니다 */
84
+ /** 특정 섹션의 스크롤 진행률(0~1) 변경 호출될 콜백을 등록합니다 */
71
85
  onProgressChange(sectionId: string, callback: ProgressCallback): () => void;
86
+ /** 특정 섹션의 스크롤 진행률 구독을 해제합니다 */
87
+ offProgressChange(sectionId: string, callback: ProgressCallback): void;
72
88
  /** 등록된 모든 이벤트 리스너와 Observer를 해제하고 정리합니다 */
73
89
  destroy(): void;
74
90
  }
package/dist/index.js CHANGED
@@ -1 +1,24 @@
1
- 'use strict';var b=Object.defineProperty;var u=Object.getOwnPropertySymbols;var w=Object.prototype.hasOwnProperty,S=Object.prototype.propertyIsEnumerable;var p=(l,e,t)=>e in l?b(l,e,{enumerable:true,configurable:true,writable:true,value:t}):l[e]=t,v=(l,e)=>{for(var t in e||(e={}))w.call(e,t)&&p(l,t,e[t]);if(u)for(var t of u(e))S.call(e,t)&&p(l,t,e[t]);return l};var r=(l,e,t)=>p(l,typeof e!="symbol"?e+"":e,t);var f=class{constructor(e={}){r(this,"sections",new Map);r(this,"disabledSections",new Set);r(this,"observer",null);r(this,"resizeObserver",null);r(this,"activeId",null);r(this,"previousId",null);r(this,"lastScrollY",0);r(this,"scrollDirection",null);r(this,"listeners",new Set);r(this,"progressListeners",new Map);r(this,"options");r(this,"keyboardHandler",null);r(this,"scrollHandler",null);r(this,"popstateHandler",null);r(this,"notifyScheduled",false);r(this,"handleIntersection",e=>{let t=e.filter(o=>o.isIntersecting);if(t.length===0){this.activeId!==null&&(this.previousId=this.activeId,this.activeId=null,this.scheduleNotify());return}let s=t.reduce((o,n)=>o.intersectionRatio>n.intersectionRatio?o:n),i;for(let[o,n]of this.sections)if(n===s.target){i=o;break}i=i!=null?i:s.target.id,!(!i||i===this.activeId||this.disabledSections.has(i))&&(this.previousId=this.activeId,this.activeId=i,this.scheduleNotify(),this.options.hash&&history.replaceState(null,"",`#${i}`));});this.options=v({offset:0,behavior:"smooth",hash:false,root:null,keyboard:false},e),this.initObserver(),this.initScrollListener(),this.options.hash&&this.initHashSync(),this.options.keyboard&&this.initKeyboard();}get scrollRoot(){var e;return (e=this.options.root)!=null?e:window}get currentScrollTop(){return this.options.root?this.options.root.scrollTop:window.scrollY}initObserver(){var e;typeof window!="undefined"&&(this.observer=new IntersectionObserver(this.handleIntersection,{root:(e=this.options.root)!=null?e:null,rootMargin:"-20% 0px -60% 0px",threshold:[0,.1,.5,1]}),typeof ResizeObserver!="undefined"&&(this.resizeObserver=new ResizeObserver(()=>{this.sections.forEach(t=>{var s,i;(s=this.observer)==null||s.unobserve(t),(i=this.observer)==null||i.observe(t);});})));}initScrollListener(){typeof window!="undefined"&&(this.scrollHandler=()=>{let e=this.currentScrollTop;e!==this.lastScrollY&&(this.scrollDirection=e>this.lastScrollY?"down":"up",this.lastScrollY=e),this.updateProgress();},this.scrollRoot.addEventListener("scroll",this.scrollHandler,{passive:true}));}initHashSync(){typeof window!="undefined"&&(this.popstateHandler=()=>{let e=window.location.hash.slice(1);e&&this.sections.has(e)&&this.scrollTo(e);},window.addEventListener("popstate",this.popstateHandler));}initKeyboard(){typeof window!="undefined"&&(this.keyboardHandler=e=>{e.altKey&&(e.key==="ArrowDown"?(e.preventDefault(),this.scrollToNext()):e.key==="ArrowUp"&&(e.preventDefault(),this.scrollToPrev()));},document.addEventListener("keydown",this.keyboardHandler));}scheduleNotify(){this.notifyScheduled||(this.notifyScheduled=true,queueMicrotask(()=>{this.notifyScheduled=false,this.notifyListeners();}));}updateProgress(){if(this.progressListeners.size===0)return;let e=this.currentScrollTop,t=this.options.root?this.options.root.clientHeight:window.innerHeight;this.progressListeners.forEach((s,i)=>{if(s.size===0)return;let o=this.sections.get(i);if(!o)return;let n=o.getBoundingClientRect(),a=this.options.root?n.top-this.options.root.getBoundingClientRect().top+this.options.root.scrollTop:n.top+e,c=o.offsetHeight||n.height;if(c===0)return;let h=(e-a+t*.2)/c,d=Math.max(0,Math.min(1,h));s.forEach(g=>g(d));});}registerSection(e,t){var s,i;typeof window!="undefined"&&t&&(this.sections.set(e,t),t.id||(t.id=e),(s=this.observer)==null||s.observe(t),(i=this.resizeObserver)==null||i.observe(t),this.options.hash&&window.location.hash===`#${e}`&&setTimeout(()=>this.scrollTo(e),0));}unregisterSection(e){var s,i;let t=this.sections.get(e);t&&((s=this.observer)==null||s.unobserve(t),(i=this.resizeObserver)==null||i.unobserve(t)),this.sections.delete(e),this.disabledSections.delete(e),this.progressListeners.delete(e),this.activeId===e&&(this.previousId=this.activeId,this.activeId=null,this.scheduleNotify());}disableSection(e){this.disabledSections.add(e),this.activeId===e&&(this.previousId=this.activeId,this.activeId=null,this.scheduleNotify());}enableSection(e){this.disabledSections.delete(e);}getSections(){return [...this.sections.entries()].filter(([e])=>!this.disabledSections.has(e)).sort(([,e],[,t])=>{let s=e.getBoundingClientRect().top,i=t.getBoundingClientRect().top;return s-i}).map(([e])=>e)}getActiveId(){return this.activeId}scrollTo(e){var a;if(typeof window=="undefined")return Promise.resolve();let t=this.sections.get(e);if(!t)return console.warn(`[ScrollManager] Section with id "${e}" not found. Available sections: ${Array.from(this.sections.keys()).join(", ")}`),Promise.resolve();let s=t.getBoundingClientRect(),i=((a=this.options.root)==null?void 0:a.getBoundingClientRect())||{top:0},o=s.top+this.currentScrollTop-i.top+this.options.offset,n=this.options.root||window;return new Promise(c=>{let h=()=>{(Math.abs(this.currentScrollTop-o)<1||n===window&&window.innerHeight+window.scrollY>=document.body.offsetHeight||this.options.root&&this.options.root.clientHeight+this.options.root.scrollTop>=this.options.root.scrollHeight)&&(n.removeEventListener("scroll",h),clearTimeout(d),c());},d=setTimeout(()=>{n.removeEventListener("scroll",h),c();},1e3);this.options.behavior==="smooth"?n.addEventListener("scroll",h,{passive:true}):(clearTimeout(d),c()),this.options.root?this.options.root.scrollTo({top:o,behavior:this.options.behavior}):window.scrollTo({top:o,behavior:this.options.behavior});})}scrollToNext(){let e=this.getSections(),s=(this.activeId?e.indexOf(this.activeId):-1)+1;return s<e.length?this.scrollTo(e[s]):Promise.resolve()}scrollToPrev(){let e=this.getSections(),s=(this.activeId?e.indexOf(this.activeId):-1)-1;return s>=0?this.scrollTo(e[s]):Promise.resolve()}scrollToFirst(){let e=this.getSections();return e.length>0?this.scrollTo(e[0]):Promise.resolve()}scrollToLast(){let e=this.getSections();return e.length>0?this.scrollTo(e[e.length-1]):Promise.resolve()}onActiveChange(e){return this.listeners.add(e),e(this.activeId,{previous:this.previousId,direction:this.scrollDirection}),()=>{this.listeners.delete(e);}}notifyListeners(){let e={previous:this.previousId,direction:this.scrollDirection};this.listeners.forEach(t=>t(this.activeId,e));}onProgressChange(e,t){var s;return this.progressListeners.has(e)||this.progressListeners.set(e,new Set),(s=this.progressListeners.get(e))==null||s.add(t),this.updateProgress(),()=>{var i;(i=this.progressListeners.get(e))==null||i.delete(t);}}destroy(){var e,t;(e=this.observer)==null||e.disconnect(),(t=this.resizeObserver)==null||t.disconnect(),this.sections.forEach(s=>{var i,o;(i=this.observer)==null||i.unobserve(s),(o=this.resizeObserver)==null||o.unobserve(s);}),this.sections.clear(),this.disabledSections.clear(),this.listeners.clear(),this.progressListeners.clear(),this.scrollHandler&&this.scrollRoot.removeEventListener("scroll",this.scrollHandler),this.popstateHandler&&window.removeEventListener("popstate",this.popstateHandler),this.keyboardHandler&&document.removeEventListener("keydown",this.keyboardHandler);}};exports.ScrollManager=f;
1
+ 'use strict';var f=Object.defineProperty;var v=Object.getOwnPropertySymbols;var y=Object.prototype.hasOwnProperty,m=Object.prototype.propertyIsEnumerable;var u=(l,e,t)=>e in l?f(l,e,{enumerable:true,configurable:true,writable:true,value:t}):l[e]=t,g=(l,e)=>{for(var t in e||(e={}))y.call(e,t)&&u(l,t,e[t]);if(v)for(var t of v(e))m.call(e,t)&&u(l,t,e[t]);return l};var o=(l,e,t)=>u(l,typeof e!="symbol"?e+"":e,t);var b=class{constructor(e={}){o(this,"sections",new Map);o(this,"disabledSections",new Set);o(this,"observer",null);o(this,"resizeObserver",null);o(this,"activeId",null);o(this,"previousId",null);o(this,"lastScrollY",0);o(this,"scrollDirection",null);o(this,"listeners",new Set);o(this,"progressListeners",new Map);o(this,"options");o(this,"keyboardHandler",null);o(this,"scrollHandler",null);o(this,"popstateHandler",null);o(this,"notifyScheduled",false);o(this,"debugElements",new Map);o(this,"handleIntersection",e=>{this.options.debug&&this.updateDebugOverlays(e);let t=e.filter(r=>r.isIntersecting);if(t.length===0){this.activeId!==null&&(this.previousId=this.activeId,this.activeId=null,this.scheduleNotify());return}let s=t.reduce((r,n)=>r.intersectionRatio>n.intersectionRatio?r:n),i;for(let[r,n]of this.sections)if(n===s.target){i=r;break}i=i!=null?i:s.target.id,!(!i||i===this.activeId||this.disabledSections.has(i))&&(this.previousId=this.activeId,this.activeId=i,this.scheduleNotify(),this.options.hash&&history.replaceState(null,"",`#${i}`));});this.options=g({offset:0,behavior:"smooth",hash:false,root:null,keyboard:false,debug:false,rootMargin:"-20% 0px -60% 0px"},e),this.initObserver(),this.initScrollListener(),this.options.hash&&this.initHashSync(),this.options.keyboard&&this.initKeyboard();}get scrollRoot(){var e;return (e=this.options.root)!=null?e:window}get currentScrollTop(){return this.options.root?this.options.root.scrollTop:window.scrollY}initObserver(){var e;typeof window!="undefined"&&(this.observer=new IntersectionObserver(this.handleIntersection,{root:(e=this.options.root)!=null?e:null,rootMargin:this.options.rootMargin,threshold:[0,.1,.5,1]}),typeof ResizeObserver!="undefined"&&(this.resizeObserver=new ResizeObserver(()=>{this.sections.forEach(t=>{var s,i;(s=this.observer)==null||s.unobserve(t),(i=this.observer)==null||i.observe(t);});})));}initScrollListener(){typeof window!="undefined"&&(this.scrollHandler=()=>{let e=this.currentScrollTop;e!==this.lastScrollY&&(this.scrollDirection=e>this.lastScrollY?"down":"up",this.lastScrollY=e),this.updateProgress();},this.scrollRoot.addEventListener("scroll",this.scrollHandler,{passive:true}));}initHashSync(){typeof window!="undefined"&&(this.popstateHandler=()=>{let e=window.location.hash.slice(1);e&&this.sections.has(e)&&this.scrollTo(e);},window.addEventListener("popstate",this.popstateHandler));}initKeyboard(){typeof window!="undefined"&&(this.keyboardHandler=e=>{e.altKey&&(e.key==="ArrowDown"?(e.preventDefault(),this.scrollToNext()):e.key==="ArrowUp"&&(e.preventDefault(),this.scrollToPrev()));},document.addEventListener("keydown",this.keyboardHandler));}scheduleNotify(){this.notifyScheduled||(this.notifyScheduled=true,queueMicrotask(()=>{this.notifyScheduled=false,this.notifyListeners(),this.options.debug&&this.updateDebugActiveState();}));}updateProgress(){if(this.progressListeners.size===0)return;let e=this.currentScrollTop,t=this.options.root?this.options.root.clientHeight:window.innerHeight;this.progressListeners.forEach((s,i)=>{if(s.size===0)return;let r=this.sections.get(i);if(!r)return;let n=r.getBoundingClientRect(),c=this.options.root?n.top-this.options.root.getBoundingClientRect().top+this.options.root.scrollTop:n.top+e,a=r.offsetHeight||n.height;if(a===0)return;let h=(e-c+t*.2)/a,d=Math.max(0,Math.min(1,h));s.forEach(p=>p(d));});}createDebugOverlay(e,t){let s=document.createElement("div");s.id=`jump-section-debug-${e}`,s.style.cssText=`
2
+ position: absolute;
3
+ top: 0;
4
+ left: 0;
5
+ width: 100%;
6
+ height: 100%;
7
+ pointer-events: none;
8
+ box-sizing: border-box;
9
+ border: 2px solid rgba(0, 100, 255, 0.5);
10
+ background: rgba(0, 100, 255, 0.1);
11
+ z-index: 9999;
12
+ display: flex;
13
+ align-items: center;
14
+ justify-content: center;
15
+ font-family: monospace;
16
+ font-size: 12px;
17
+ color: white;
18
+ text-shadow: 1px 1px 2px rgba(0,0,0,0.8);
19
+ overflow: hidden;
20
+ `,t.style.position=t.style.position==="static"?"relative":t.style.position;let i=document.createElement("span");return i.style.cssText=`
21
+ padding: 2px 5px;
22
+ background: rgba(0, 100, 255, 0.7);
23
+ border-radius: 3px;
24
+ `,i.textContent=`ID: ${e}`,s.appendChild(i),s}updateDebugOverlays(e){e.forEach(t=>{var h,d;let s=t.target,i=(d=(h=[...this.sections.entries()].find(([,p])=>p===s))==null?void 0:h[0])!=null?d:s.id;if(!i)return;let r=this.debugElements.get(i);r||(r=this.createDebugOverlay(i,s),s.appendChild(r),this.debugElements.set(i,r));let n=Math.round(t.intersectionRatio*100),c=i===this.activeId;r.style.borderColor=c?"rgba(0, 255, 0, 0.8)":t.isIntersecting?"rgba(255, 165, 0, 0.8)":"rgba(0, 100, 255, 0.5)",r.style.background=c?"rgba(0, 255, 0, 0.1)":t.isIntersecting?"rgba(255, 165, 0, 0.1)":"rgba(0, 100, 255, 0.1)";let a=r.querySelector("span");a&&(a.textContent=`ID: ${i} | Ratio: ${n}% ${c?"| ACTIVE":""}`,a.style.background=c?"rgba(0, 255, 0, 0.7)":t.isIntersecting?"rgba(255, 165, 0, 0.7)":"rgba(0, 100, 255, 0.7)");});}updateDebugActiveState(){this.debugElements.forEach((e,t)=>{let s=t===this.activeId,i=e.querySelector("span"),r=i.textContent||"",n=s?r.includes("| ACTIVE")?r:`${r} | ACTIVE`:r.replace(" | ACTIVE","");i&&(i.textContent=n,i.style.background=s?"rgba(0, 255, 0, 0.7)":"rgba(0, 100, 255, 0.7)"),e.style.borderColor=s?"rgba(0, 255, 0, 0.8)":"rgba(0, 100, 255, 0.5)",e.style.background=s?"rgba(0, 255, 0, 0.1)":"rgba(0, 100, 255, 0.1)";});}removeDebugOverlay(e){let t=this.debugElements.get(e);t&&(t.remove(),this.debugElements.delete(e));}registerSection(e,t){var s,i;if(typeof window!="undefined"&&t){if(this.sections.set(e,t),t.id||(t.id=e),(s=this.observer)==null||s.observe(t),(i=this.resizeObserver)==null||i.observe(t),this.options.debug){let r=this.createDebugOverlay(e,t);t.appendChild(r),this.debugElements.set(e,r);}this.options.hash&&window.location.hash===`#${e}`&&setTimeout(()=>this.scrollTo(e),0);}}unregisterSection(e){var s,i;let t=this.sections.get(e);t&&((s=this.observer)==null||s.unobserve(t),(i=this.resizeObserver)==null||i.unobserve(t)),this.sections.delete(e),this.disabledSections.delete(e),this.progressListeners.delete(e),this.options.debug&&this.removeDebugOverlay(e),this.activeId===e&&(this.previousId=this.activeId,this.activeId=null,this.scheduleNotify());}disableSection(e){var t;if(this.disabledSections.add(e),this.options.debug){let s=this.debugElements.get(e);if(s){s.style.borderStyle="dashed";let i=s.querySelector("span");i&&!((t=i.textContent)!=null&&t.includes("| DISABLED"))&&(i.textContent+=" | DISABLED");}}this.activeId===e&&(this.previousId=this.activeId,this.activeId=null,this.scheduleNotify());}enableSection(e){var t;if(this.disabledSections.delete(e),this.options.debug){let s=this.debugElements.get(e);if(s){s.style.borderStyle="solid";let i=s.querySelector("span");i&&(i.textContent=((t=i.textContent)==null?void 0:t.replace(" | DISABLED",""))||"");}}}getSections(){return [...this.sections.entries()].filter(([e])=>!this.disabledSections.has(e)).sort(([,e],[,t])=>{let s=e.getBoundingClientRect().top,i=t.getBoundingClientRect().top;return s-i}).map(([e])=>e)}getActiveId(){return this.activeId}scrollTo(e){var c;if(typeof window=="undefined")return Promise.resolve();let t=this.sections.get(e);if(!t)return console.warn(`[ScrollManager] Section with id "${e}" not found. Available sections: ${Array.from(this.sections.keys()).join(", ")}`),Promise.resolve();let s=t.getBoundingClientRect(),i=((c=this.options.root)==null?void 0:c.getBoundingClientRect())||{top:0},r=s.top+this.currentScrollTop-i.top+this.options.offset,n=this.options.root||window;return new Promise(a=>{let h=()=>{Math.abs(this.currentScrollTop-r)<1&&(n.removeEventListener("scroll",h),clearTimeout(d),a());},d=setTimeout(()=>{n.removeEventListener("scroll",h),a();},1e3);this.options.behavior==="smooth"?n.addEventListener("scroll",h,{passive:true}):(clearTimeout(d),a()),this.options.root?this.options.root.scrollTo({top:r,behavior:this.options.behavior}):window.scrollTo({top:r,behavior:this.options.behavior});})}scrollToNext(){let e=this.getSections(),s=(this.activeId?e.indexOf(this.activeId):-1)+1;return s<e.length?this.scrollTo(e[s]):Promise.resolve()}scrollToPrev(){let e=this.getSections(),s=(this.activeId?e.indexOf(this.activeId):e.length)-1;return s>=0?this.scrollTo(e[s]):Promise.resolve()}scrollToFirst(){let e=this.getSections();return e.length>0?this.scrollTo(e[0]):Promise.resolve()}scrollToLast(){let e=this.getSections();return e.length>0?this.scrollTo(e[e.length-1]):Promise.resolve()}onActiveChange(e){return this.listeners.add(e),e(this.activeId,{previous:this.previousId,direction:this.scrollDirection}),()=>{this.listeners.delete(e);}}offActiveChange(e){this.listeners.delete(e);}notifyListeners(){if(this.activeId===null&&this.previousId===null)return;let e={previous:this.previousId,direction:this.scrollDirection};this.listeners.forEach(t=>t(this.activeId,e));}onProgressChange(e,t){var s;return this.progressListeners.has(e)||this.progressListeners.set(e,new Set),(s=this.progressListeners.get(e))==null||s.add(t),this.updateProgress(),()=>{var i;(i=this.progressListeners.get(e))==null||i.delete(t);}}offProgressChange(e,t){var s,i;(s=this.progressListeners.get(e))==null||s.delete(t),((i=this.progressListeners.get(e))==null?void 0:i.size)===0&&this.progressListeners.delete(e);}destroy(){var e,t;(e=this.observer)==null||e.disconnect(),(t=this.resizeObserver)==null||t.disconnect(),this.sections.forEach(s=>{var i,r;(i=this.observer)==null||i.unobserve(s),(r=this.resizeObserver)==null||r.unobserve(s);}),this.sections.clear(),this.disabledSections.clear(),this.listeners.clear(),this.progressListeners.clear(),this.debugElements.forEach(s=>s.remove()),this.debugElements.clear(),this.scrollHandler&&this.scrollRoot.removeEventListener("scroll",this.scrollHandler),this.popstateHandler&&window.removeEventListener("popstate",this.popstateHandler),this.keyboardHandler&&document.removeEventListener("keydown",this.keyboardHandler);}};exports.ScrollManager=b;
package/dist/index.mjs CHANGED
@@ -1 +1,24 @@
1
- var b=Object.defineProperty;var u=Object.getOwnPropertySymbols;var w=Object.prototype.hasOwnProperty,S=Object.prototype.propertyIsEnumerable;var p=(l,e,t)=>e in l?b(l,e,{enumerable:true,configurable:true,writable:true,value:t}):l[e]=t,v=(l,e)=>{for(var t in e||(e={}))w.call(e,t)&&p(l,t,e[t]);if(u)for(var t of u(e))S.call(e,t)&&p(l,t,e[t]);return l};var r=(l,e,t)=>p(l,typeof e!="symbol"?e+"":e,t);var f=class{constructor(e={}){r(this,"sections",new Map);r(this,"disabledSections",new Set);r(this,"observer",null);r(this,"resizeObserver",null);r(this,"activeId",null);r(this,"previousId",null);r(this,"lastScrollY",0);r(this,"scrollDirection",null);r(this,"listeners",new Set);r(this,"progressListeners",new Map);r(this,"options");r(this,"keyboardHandler",null);r(this,"scrollHandler",null);r(this,"popstateHandler",null);r(this,"notifyScheduled",false);r(this,"handleIntersection",e=>{let t=e.filter(o=>o.isIntersecting);if(t.length===0){this.activeId!==null&&(this.previousId=this.activeId,this.activeId=null,this.scheduleNotify());return}let s=t.reduce((o,n)=>o.intersectionRatio>n.intersectionRatio?o:n),i;for(let[o,n]of this.sections)if(n===s.target){i=o;break}i=i!=null?i:s.target.id,!(!i||i===this.activeId||this.disabledSections.has(i))&&(this.previousId=this.activeId,this.activeId=i,this.scheduleNotify(),this.options.hash&&history.replaceState(null,"",`#${i}`));});this.options=v({offset:0,behavior:"smooth",hash:false,root:null,keyboard:false},e),this.initObserver(),this.initScrollListener(),this.options.hash&&this.initHashSync(),this.options.keyboard&&this.initKeyboard();}get scrollRoot(){var e;return (e=this.options.root)!=null?e:window}get currentScrollTop(){return this.options.root?this.options.root.scrollTop:window.scrollY}initObserver(){var e;typeof window!="undefined"&&(this.observer=new IntersectionObserver(this.handleIntersection,{root:(e=this.options.root)!=null?e:null,rootMargin:"-20% 0px -60% 0px",threshold:[0,.1,.5,1]}),typeof ResizeObserver!="undefined"&&(this.resizeObserver=new ResizeObserver(()=>{this.sections.forEach(t=>{var s,i;(s=this.observer)==null||s.unobserve(t),(i=this.observer)==null||i.observe(t);});})));}initScrollListener(){typeof window!="undefined"&&(this.scrollHandler=()=>{let e=this.currentScrollTop;e!==this.lastScrollY&&(this.scrollDirection=e>this.lastScrollY?"down":"up",this.lastScrollY=e),this.updateProgress();},this.scrollRoot.addEventListener("scroll",this.scrollHandler,{passive:true}));}initHashSync(){typeof window!="undefined"&&(this.popstateHandler=()=>{let e=window.location.hash.slice(1);e&&this.sections.has(e)&&this.scrollTo(e);},window.addEventListener("popstate",this.popstateHandler));}initKeyboard(){typeof window!="undefined"&&(this.keyboardHandler=e=>{e.altKey&&(e.key==="ArrowDown"?(e.preventDefault(),this.scrollToNext()):e.key==="ArrowUp"&&(e.preventDefault(),this.scrollToPrev()));},document.addEventListener("keydown",this.keyboardHandler));}scheduleNotify(){this.notifyScheduled||(this.notifyScheduled=true,queueMicrotask(()=>{this.notifyScheduled=false,this.notifyListeners();}));}updateProgress(){if(this.progressListeners.size===0)return;let e=this.currentScrollTop,t=this.options.root?this.options.root.clientHeight:window.innerHeight;this.progressListeners.forEach((s,i)=>{if(s.size===0)return;let o=this.sections.get(i);if(!o)return;let n=o.getBoundingClientRect(),a=this.options.root?n.top-this.options.root.getBoundingClientRect().top+this.options.root.scrollTop:n.top+e,c=o.offsetHeight||n.height;if(c===0)return;let h=(e-a+t*.2)/c,d=Math.max(0,Math.min(1,h));s.forEach(g=>g(d));});}registerSection(e,t){var s,i;typeof window!="undefined"&&t&&(this.sections.set(e,t),t.id||(t.id=e),(s=this.observer)==null||s.observe(t),(i=this.resizeObserver)==null||i.observe(t),this.options.hash&&window.location.hash===`#${e}`&&setTimeout(()=>this.scrollTo(e),0));}unregisterSection(e){var s,i;let t=this.sections.get(e);t&&((s=this.observer)==null||s.unobserve(t),(i=this.resizeObserver)==null||i.unobserve(t)),this.sections.delete(e),this.disabledSections.delete(e),this.progressListeners.delete(e),this.activeId===e&&(this.previousId=this.activeId,this.activeId=null,this.scheduleNotify());}disableSection(e){this.disabledSections.add(e),this.activeId===e&&(this.previousId=this.activeId,this.activeId=null,this.scheduleNotify());}enableSection(e){this.disabledSections.delete(e);}getSections(){return [...this.sections.entries()].filter(([e])=>!this.disabledSections.has(e)).sort(([,e],[,t])=>{let s=e.getBoundingClientRect().top,i=t.getBoundingClientRect().top;return s-i}).map(([e])=>e)}getActiveId(){return this.activeId}scrollTo(e){var a;if(typeof window=="undefined")return Promise.resolve();let t=this.sections.get(e);if(!t)return console.warn(`[ScrollManager] Section with id "${e}" not found. Available sections: ${Array.from(this.sections.keys()).join(", ")}`),Promise.resolve();let s=t.getBoundingClientRect(),i=((a=this.options.root)==null?void 0:a.getBoundingClientRect())||{top:0},o=s.top+this.currentScrollTop-i.top+this.options.offset,n=this.options.root||window;return new Promise(c=>{let h=()=>{(Math.abs(this.currentScrollTop-o)<1||n===window&&window.innerHeight+window.scrollY>=document.body.offsetHeight||this.options.root&&this.options.root.clientHeight+this.options.root.scrollTop>=this.options.root.scrollHeight)&&(n.removeEventListener("scroll",h),clearTimeout(d),c());},d=setTimeout(()=>{n.removeEventListener("scroll",h),c();},1e3);this.options.behavior==="smooth"?n.addEventListener("scroll",h,{passive:true}):(clearTimeout(d),c()),this.options.root?this.options.root.scrollTo({top:o,behavior:this.options.behavior}):window.scrollTo({top:o,behavior:this.options.behavior});})}scrollToNext(){let e=this.getSections(),s=(this.activeId?e.indexOf(this.activeId):-1)+1;return s<e.length?this.scrollTo(e[s]):Promise.resolve()}scrollToPrev(){let e=this.getSections(),s=(this.activeId?e.indexOf(this.activeId):-1)-1;return s>=0?this.scrollTo(e[s]):Promise.resolve()}scrollToFirst(){let e=this.getSections();return e.length>0?this.scrollTo(e[0]):Promise.resolve()}scrollToLast(){let e=this.getSections();return e.length>0?this.scrollTo(e[e.length-1]):Promise.resolve()}onActiveChange(e){return this.listeners.add(e),e(this.activeId,{previous:this.previousId,direction:this.scrollDirection}),()=>{this.listeners.delete(e);}}notifyListeners(){let e={previous:this.previousId,direction:this.scrollDirection};this.listeners.forEach(t=>t(this.activeId,e));}onProgressChange(e,t){var s;return this.progressListeners.has(e)||this.progressListeners.set(e,new Set),(s=this.progressListeners.get(e))==null||s.add(t),this.updateProgress(),()=>{var i;(i=this.progressListeners.get(e))==null||i.delete(t);}}destroy(){var e,t;(e=this.observer)==null||e.disconnect(),(t=this.resizeObserver)==null||t.disconnect(),this.sections.forEach(s=>{var i,o;(i=this.observer)==null||i.unobserve(s),(o=this.resizeObserver)==null||o.unobserve(s);}),this.sections.clear(),this.disabledSections.clear(),this.listeners.clear(),this.progressListeners.clear(),this.scrollHandler&&this.scrollRoot.removeEventListener("scroll",this.scrollHandler),this.popstateHandler&&window.removeEventListener("popstate",this.popstateHandler),this.keyboardHandler&&document.removeEventListener("keydown",this.keyboardHandler);}};export{f as ScrollManager};
1
+ var f=Object.defineProperty;var v=Object.getOwnPropertySymbols;var y=Object.prototype.hasOwnProperty,m=Object.prototype.propertyIsEnumerable;var u=(l,e,t)=>e in l?f(l,e,{enumerable:true,configurable:true,writable:true,value:t}):l[e]=t,g=(l,e)=>{for(var t in e||(e={}))y.call(e,t)&&u(l,t,e[t]);if(v)for(var t of v(e))m.call(e,t)&&u(l,t,e[t]);return l};var o=(l,e,t)=>u(l,typeof e!="symbol"?e+"":e,t);var b=class{constructor(e={}){o(this,"sections",new Map);o(this,"disabledSections",new Set);o(this,"observer",null);o(this,"resizeObserver",null);o(this,"activeId",null);o(this,"previousId",null);o(this,"lastScrollY",0);o(this,"scrollDirection",null);o(this,"listeners",new Set);o(this,"progressListeners",new Map);o(this,"options");o(this,"keyboardHandler",null);o(this,"scrollHandler",null);o(this,"popstateHandler",null);o(this,"notifyScheduled",false);o(this,"debugElements",new Map);o(this,"handleIntersection",e=>{this.options.debug&&this.updateDebugOverlays(e);let t=e.filter(r=>r.isIntersecting);if(t.length===0){this.activeId!==null&&(this.previousId=this.activeId,this.activeId=null,this.scheduleNotify());return}let s=t.reduce((r,n)=>r.intersectionRatio>n.intersectionRatio?r:n),i;for(let[r,n]of this.sections)if(n===s.target){i=r;break}i=i!=null?i:s.target.id,!(!i||i===this.activeId||this.disabledSections.has(i))&&(this.previousId=this.activeId,this.activeId=i,this.scheduleNotify(),this.options.hash&&history.replaceState(null,"",`#${i}`));});this.options=g({offset:0,behavior:"smooth",hash:false,root:null,keyboard:false,debug:false,rootMargin:"-20% 0px -60% 0px"},e),this.initObserver(),this.initScrollListener(),this.options.hash&&this.initHashSync(),this.options.keyboard&&this.initKeyboard();}get scrollRoot(){var e;return (e=this.options.root)!=null?e:window}get currentScrollTop(){return this.options.root?this.options.root.scrollTop:window.scrollY}initObserver(){var e;typeof window!="undefined"&&(this.observer=new IntersectionObserver(this.handleIntersection,{root:(e=this.options.root)!=null?e:null,rootMargin:this.options.rootMargin,threshold:[0,.1,.5,1]}),typeof ResizeObserver!="undefined"&&(this.resizeObserver=new ResizeObserver(()=>{this.sections.forEach(t=>{var s,i;(s=this.observer)==null||s.unobserve(t),(i=this.observer)==null||i.observe(t);});})));}initScrollListener(){typeof window!="undefined"&&(this.scrollHandler=()=>{let e=this.currentScrollTop;e!==this.lastScrollY&&(this.scrollDirection=e>this.lastScrollY?"down":"up",this.lastScrollY=e),this.updateProgress();},this.scrollRoot.addEventListener("scroll",this.scrollHandler,{passive:true}));}initHashSync(){typeof window!="undefined"&&(this.popstateHandler=()=>{let e=window.location.hash.slice(1);e&&this.sections.has(e)&&this.scrollTo(e);},window.addEventListener("popstate",this.popstateHandler));}initKeyboard(){typeof window!="undefined"&&(this.keyboardHandler=e=>{e.altKey&&(e.key==="ArrowDown"?(e.preventDefault(),this.scrollToNext()):e.key==="ArrowUp"&&(e.preventDefault(),this.scrollToPrev()));},document.addEventListener("keydown",this.keyboardHandler));}scheduleNotify(){this.notifyScheduled||(this.notifyScheduled=true,queueMicrotask(()=>{this.notifyScheduled=false,this.notifyListeners(),this.options.debug&&this.updateDebugActiveState();}));}updateProgress(){if(this.progressListeners.size===0)return;let e=this.currentScrollTop,t=this.options.root?this.options.root.clientHeight:window.innerHeight;this.progressListeners.forEach((s,i)=>{if(s.size===0)return;let r=this.sections.get(i);if(!r)return;let n=r.getBoundingClientRect(),c=this.options.root?n.top-this.options.root.getBoundingClientRect().top+this.options.root.scrollTop:n.top+e,a=r.offsetHeight||n.height;if(a===0)return;let h=(e-c+t*.2)/a,d=Math.max(0,Math.min(1,h));s.forEach(p=>p(d));});}createDebugOverlay(e,t){let s=document.createElement("div");s.id=`jump-section-debug-${e}`,s.style.cssText=`
2
+ position: absolute;
3
+ top: 0;
4
+ left: 0;
5
+ width: 100%;
6
+ height: 100%;
7
+ pointer-events: none;
8
+ box-sizing: border-box;
9
+ border: 2px solid rgba(0, 100, 255, 0.5);
10
+ background: rgba(0, 100, 255, 0.1);
11
+ z-index: 9999;
12
+ display: flex;
13
+ align-items: center;
14
+ justify-content: center;
15
+ font-family: monospace;
16
+ font-size: 12px;
17
+ color: white;
18
+ text-shadow: 1px 1px 2px rgba(0,0,0,0.8);
19
+ overflow: hidden;
20
+ `,t.style.position=t.style.position==="static"?"relative":t.style.position;let i=document.createElement("span");return i.style.cssText=`
21
+ padding: 2px 5px;
22
+ background: rgba(0, 100, 255, 0.7);
23
+ border-radius: 3px;
24
+ `,i.textContent=`ID: ${e}`,s.appendChild(i),s}updateDebugOverlays(e){e.forEach(t=>{var h,d;let s=t.target,i=(d=(h=[...this.sections.entries()].find(([,p])=>p===s))==null?void 0:h[0])!=null?d:s.id;if(!i)return;let r=this.debugElements.get(i);r||(r=this.createDebugOverlay(i,s),s.appendChild(r),this.debugElements.set(i,r));let n=Math.round(t.intersectionRatio*100),c=i===this.activeId;r.style.borderColor=c?"rgba(0, 255, 0, 0.8)":t.isIntersecting?"rgba(255, 165, 0, 0.8)":"rgba(0, 100, 255, 0.5)",r.style.background=c?"rgba(0, 255, 0, 0.1)":t.isIntersecting?"rgba(255, 165, 0, 0.1)":"rgba(0, 100, 255, 0.1)";let a=r.querySelector("span");a&&(a.textContent=`ID: ${i} | Ratio: ${n}% ${c?"| ACTIVE":""}`,a.style.background=c?"rgba(0, 255, 0, 0.7)":t.isIntersecting?"rgba(255, 165, 0, 0.7)":"rgba(0, 100, 255, 0.7)");});}updateDebugActiveState(){this.debugElements.forEach((e,t)=>{let s=t===this.activeId,i=e.querySelector("span"),r=i.textContent||"",n=s?r.includes("| ACTIVE")?r:`${r} | ACTIVE`:r.replace(" | ACTIVE","");i&&(i.textContent=n,i.style.background=s?"rgba(0, 255, 0, 0.7)":"rgba(0, 100, 255, 0.7)"),e.style.borderColor=s?"rgba(0, 255, 0, 0.8)":"rgba(0, 100, 255, 0.5)",e.style.background=s?"rgba(0, 255, 0, 0.1)":"rgba(0, 100, 255, 0.1)";});}removeDebugOverlay(e){let t=this.debugElements.get(e);t&&(t.remove(),this.debugElements.delete(e));}registerSection(e,t){var s,i;if(typeof window!="undefined"&&t){if(this.sections.set(e,t),t.id||(t.id=e),(s=this.observer)==null||s.observe(t),(i=this.resizeObserver)==null||i.observe(t),this.options.debug){let r=this.createDebugOverlay(e,t);t.appendChild(r),this.debugElements.set(e,r);}this.options.hash&&window.location.hash===`#${e}`&&setTimeout(()=>this.scrollTo(e),0);}}unregisterSection(e){var s,i;let t=this.sections.get(e);t&&((s=this.observer)==null||s.unobserve(t),(i=this.resizeObserver)==null||i.unobserve(t)),this.sections.delete(e),this.disabledSections.delete(e),this.progressListeners.delete(e),this.options.debug&&this.removeDebugOverlay(e),this.activeId===e&&(this.previousId=this.activeId,this.activeId=null,this.scheduleNotify());}disableSection(e){var t;if(this.disabledSections.add(e),this.options.debug){let s=this.debugElements.get(e);if(s){s.style.borderStyle="dashed";let i=s.querySelector("span");i&&!((t=i.textContent)!=null&&t.includes("| DISABLED"))&&(i.textContent+=" | DISABLED");}}this.activeId===e&&(this.previousId=this.activeId,this.activeId=null,this.scheduleNotify());}enableSection(e){var t;if(this.disabledSections.delete(e),this.options.debug){let s=this.debugElements.get(e);if(s){s.style.borderStyle="solid";let i=s.querySelector("span");i&&(i.textContent=((t=i.textContent)==null?void 0:t.replace(" | DISABLED",""))||"");}}}getSections(){return [...this.sections.entries()].filter(([e])=>!this.disabledSections.has(e)).sort(([,e],[,t])=>{let s=e.getBoundingClientRect().top,i=t.getBoundingClientRect().top;return s-i}).map(([e])=>e)}getActiveId(){return this.activeId}scrollTo(e){var c;if(typeof window=="undefined")return Promise.resolve();let t=this.sections.get(e);if(!t)return console.warn(`[ScrollManager] Section with id "${e}" not found. Available sections: ${Array.from(this.sections.keys()).join(", ")}`),Promise.resolve();let s=t.getBoundingClientRect(),i=((c=this.options.root)==null?void 0:c.getBoundingClientRect())||{top:0},r=s.top+this.currentScrollTop-i.top+this.options.offset,n=this.options.root||window;return new Promise(a=>{let h=()=>{Math.abs(this.currentScrollTop-r)<1&&(n.removeEventListener("scroll",h),clearTimeout(d),a());},d=setTimeout(()=>{n.removeEventListener("scroll",h),a();},1e3);this.options.behavior==="smooth"?n.addEventListener("scroll",h,{passive:true}):(clearTimeout(d),a()),this.options.root?this.options.root.scrollTo({top:r,behavior:this.options.behavior}):window.scrollTo({top:r,behavior:this.options.behavior});})}scrollToNext(){let e=this.getSections(),s=(this.activeId?e.indexOf(this.activeId):-1)+1;return s<e.length?this.scrollTo(e[s]):Promise.resolve()}scrollToPrev(){let e=this.getSections(),s=(this.activeId?e.indexOf(this.activeId):e.length)-1;return s>=0?this.scrollTo(e[s]):Promise.resolve()}scrollToFirst(){let e=this.getSections();return e.length>0?this.scrollTo(e[0]):Promise.resolve()}scrollToLast(){let e=this.getSections();return e.length>0?this.scrollTo(e[e.length-1]):Promise.resolve()}onActiveChange(e){return this.listeners.add(e),e(this.activeId,{previous:this.previousId,direction:this.scrollDirection}),()=>{this.listeners.delete(e);}}offActiveChange(e){this.listeners.delete(e);}notifyListeners(){if(this.activeId===null&&this.previousId===null)return;let e={previous:this.previousId,direction:this.scrollDirection};this.listeners.forEach(t=>t(this.activeId,e));}onProgressChange(e,t){var s;return this.progressListeners.has(e)||this.progressListeners.set(e,new Set),(s=this.progressListeners.get(e))==null||s.add(t),this.updateProgress(),()=>{var i;(i=this.progressListeners.get(e))==null||i.delete(t);}}offProgressChange(e,t){var s,i;(s=this.progressListeners.get(e))==null||s.delete(t),((i=this.progressListeners.get(e))==null?void 0:i.size)===0&&this.progressListeners.delete(e);}destroy(){var e,t;(e=this.observer)==null||e.disconnect(),(t=this.resizeObserver)==null||t.disconnect(),this.sections.forEach(s=>{var i,r;(i=this.observer)==null||i.unobserve(s),(r=this.resizeObserver)==null||r.unobserve(s);}),this.sections.clear(),this.disabledSections.clear(),this.listeners.clear(),this.progressListeners.clear(),this.debugElements.forEach(s=>s.remove()),this.debugElements.clear(),this.scrollHandler&&this.scrollRoot.removeEventListener("scroll",this.scrollHandler),this.popstateHandler&&window.removeEventListener("popstate",this.popstateHandler),this.keyboardHandler&&document.removeEventListener("keydown",this.keyboardHandler);}};export{b as ScrollManager};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jump-section/core",
3
- "version": "1.0.22",
3
+ "version": "1.0.24",
4
4
  "description": "Core scroll management library for jump-section",
5
5
  "keywords": [
6
6
  "scroll",