@designbasekorea/figma-ui 0.1.49 → 0.1.50

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.esm.js CHANGED
@@ -110,31 +110,23 @@ const FigmaSection = ({ title, dataCategory, iconButton, children, marginBottom,
110
110
  .filter(Boolean)
111
111
  .join(' ');
112
112
  useEffect(() => {
113
- if (!enableScrollNavigation || !onActiveSectionChange)
113
+ if (!enableScrollNavigation || !onActiveSectionChange || !sectionRef.current)
114
114
  return;
115
- let scrollTimeout;
116
- const handleScroll = () => {
117
- if (scrollTimeout) {
118
- clearTimeout(scrollTimeout);
119
- }
120
- scrollTimeout = setTimeout(() => {
121
- if (!sectionRef.current)
122
- return;
123
- const scrollPosition = window.scrollY + headerHeight;
124
- const sectionTop = sectionRef.current.getBoundingClientRect().top + window.scrollY - headerHeight;
125
- const sectionBottom = sectionRef.current.getBoundingClientRect().bottom + window.scrollY - headerHeight;
126
- if (scrollPosition >= sectionTop && scrollPosition < sectionBottom) {
115
+ const observerOptions = {
116
+ root: null,
117
+ rootMargin: `-${headerHeight}px 0px -50% 0px`,
118
+ threshold: 0
119
+ };
120
+ const observer = new IntersectionObserver((entries) => {
121
+ entries.forEach((entry) => {
122
+ if (entry.isIntersecting) {
127
123
  onActiveSectionChange(dataCategory);
128
124
  }
129
- }, 50);
130
- };
131
- window.addEventListener('scroll', handleScroll);
132
- handleScroll();
125
+ });
126
+ }, observerOptions);
127
+ observer.observe(sectionRef.current);
133
128
  return () => {
134
- window.removeEventListener('scroll', handleScroll);
135
- if (scrollTimeout) {
136
- clearTimeout(scrollTimeout);
137
- }
129
+ observer.disconnect();
138
130
  };
139
131
  }, [enableScrollNavigation, dataCategory, headerHeight, onActiveSectionChange]);
140
132
  return (React.createElement("section", { ref: sectionRef, className: classes, ...(dataCategory ? { 'data-category': dataCategory } : {}), style: sectionStyle },
@@ -226,56 +218,37 @@ const FigmaSidebar = ({ categories, categoryGroups = {}, categoryLabels = {}, ac
226
218
  }
227
219
  }, [currentActiveCategory, scrollPadding]);
228
220
  useEffect(() => {
229
- let scrollTimeout;
230
- const scrollContainer = scrollContainerId
231
- ? document.getElementById(scrollContainerId)
232
- : window;
233
- const handleScroll = () => {
234
- if (scrollTimeout) {
235
- clearTimeout(scrollTimeout);
236
- }
237
- scrollTimeout = setTimeout(() => {
238
- const sections = document.querySelectorAll('section[data-category]');
239
- let activeSection = null;
240
- if (scrollContainer && scrollContainer !== window) {
241
- const containerElement = scrollContainer;
242
- const containerRect = containerElement.getBoundingClientRect();
243
- const scrollPosition = containerElement.scrollTop + headerHeight;
244
- for (const section of Array.from(sections)) {
245
- const category = section.getAttribute('data-category');
246
- if (!category)
247
- continue;
248
- const sectionRect = section.getBoundingClientRect();
249
- const sectionTop = sectionRect.top - containerRect.top + containerElement.scrollTop - headerHeight;
250
- const sectionBottom = sectionTop + section.clientHeight;
251
- if (scrollPosition >= sectionTop && scrollPosition < sectionBottom) {
252
- activeSection = category;
253
- break;
254
- }
221
+ const sections = document.querySelectorAll('section[data-category]');
222
+ if (sections.length === 0)
223
+ return;
224
+ const observerOptions = {
225
+ root: scrollContainerId ? document.getElementById(scrollContainerId) : null,
226
+ rootMargin: `-${headerHeight}px 0px -50% 0px`,
227
+ threshold: 0
228
+ };
229
+ const observer = new IntersectionObserver((entries) => {
230
+ let maxRatio = 0;
231
+ let activeSection = null;
232
+ entries.forEach((entry) => {
233
+ if (entry.isIntersecting && entry.intersectionRatio > maxRatio) {
234
+ maxRatio = entry.intersectionRatio;
235
+ const category = entry.target.getAttribute('data-category');
236
+ if (category) {
237
+ activeSection = category;
255
238
  }
256
239
  }
257
- else {
258
- activeSection = getActiveSection(headerHeight);
259
- }
260
- if (activeSection && activeSection !== currentActiveCategory) {
261
- setInternalActiveCategory(activeSection);
262
- onCategoryClick?.(activeSection);
263
- }
264
- }, 50);
265
- };
266
- if (scrollContainer) {
267
- scrollContainer.addEventListener('scroll', handleScroll);
268
- handleScroll();
269
- }
270
- return () => {
271
- if (scrollContainer) {
272
- scrollContainer.removeEventListener('scroll', handleScroll);
273
- }
274
- if (scrollTimeout) {
275
- clearTimeout(scrollTimeout);
240
+ });
241
+ if (activeSection && activeSection !== currentActiveCategory) {
242
+ setInternalActiveCategory(activeSection);
276
243
  }
244
+ }, observerOptions);
245
+ sections.forEach((section) => {
246
+ observer.observe(section);
247
+ });
248
+ return () => {
249
+ observer.disconnect();
277
250
  };
278
- }, [currentActiveCategory, headerHeight, onCategoryClick, scrollContainerId]);
251
+ }, [currentActiveCategory, headerHeight, scrollContainerId]);
279
252
  const classes = [
280
253
  'designbase-figma-sidebar',
281
254
  className,