CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-mantine--hooks

A comprehensive collection of 75+ React hooks for state and UI management including storage, events, browser APIs, and performance optimizations

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

observers.mddocs/

Observers & Detection

Observer-based hooks for intersection detection, resize monitoring, mutation tracking, and viewport visibility using modern browser Observer APIs.

Capabilities

useIntersection

Intersection Observer API integration for detecting when elements enter/leave the viewport.

/**
 * Intersection Observer API integration
 * @param options - IntersectionObserver configuration options
 * @returns Object with ref callback and intersection entry
 */
function useIntersection<T extends HTMLElement = any>(
  options?: IntersectionObserverInit
): UseIntersectionReturnValue<T>;

interface UseIntersectionReturnValue<T> {
  ref: React.RefCallback<T | null>;
  entry: IntersectionObserverEntry | null;
}

Usage Examples:

import { useIntersection } from "@mantine/hooks";

// Basic intersection detection
function LazyImage({ src, alt }: { src: string; alt: string }) {
  const { ref, entry } = useIntersection({
    threshold: 0.1,
  });
  
  const isVisible = entry?.isIntersecting;
  
  return (
    <div ref={ref}>
      {isVisible ? (
        <img src={src} alt={alt} />
      ) : (
        <div style={{ height: '200px', background: '#f0f0f0' }}>
          Loading...
        </div>
      )}
    </div>
  );
}

// Infinite scrolling
function InfiniteList({ items, onLoadMore }: Props) {
  const { ref, entry } = useIntersection({
    threshold: 1.0,
  });
  
  useEffect(() => {
    if (entry?.isIntersecting) {
      onLoadMore();
    }
  }, [entry?.isIntersecting, onLoadMore]);
  
  return (
    <div>
      {items.map(item => <Item key={item.id} {...item} />)}
      <div ref={ref}>Loading more...</div>
    </div>
  );
}

useResizeObserver

Resize Observer API for monitoring element size changes.

/**
 * Resize Observer API for element size monitoring
 * @param callback - Function called when element resizes
 * @returns Ref callback to attach to target element
 */
function useResizeObserver<T extends HTMLElement = any>(
  callback: (entries: ResizeObserverEntry[], observer: ResizeObserver) => void
): React.RefCallback<T | null>;

Usage Examples:

import { useResizeObserver } from "@mantine/hooks";

function ResponsiveComponent() {
  const [size, setSize] = useState({ width: 0, height: 0 });
  
  const ref = useResizeObserver<HTMLDivElement>((entries) => {
    const entry = entries[0];
    if (entry) {
      setSize({
        width: entry.contentRect.width,
        height: entry.contentRect.height,
      });
    }
  });
  
  return (
    <div ref={ref} style={{ resize: 'both', overflow: 'auto', border: '1px solid' }}>
      <p>Size: {size.width} × {size.height}</p>
      <p>Resize me!</p>
    </div>
  );
}

useElementSize

Convenience hook for tracking element dimensions.

/**
 * Track element dimensions
 * @returns Object with ref, width, and height
 */
function useElementSize<T extends HTMLElement = any>(): {
  ref: React.RefCallback<T | null>;
  width: number;
  height: number;
};

Usage Examples:

import { useElementSize } from "@mantine/hooks";

function SizeAwareComponent() {
  const { ref, width, height } = useElementSize();
  
  return (
    <div ref={ref}>
      <p>Element size: {width} × {height}</p>
      {width < 300 && <div>Mobile layout</div>}
      {width >= 300 && width < 768 && <div>Tablet layout</div>}
      {width >= 768 && <div>Desktop layout</div>}
    </div>
  );
}

useMutationObserver

Mutation Observer API for monitoring DOM changes.

/**
 * Mutation Observer API for DOM change monitoring
 * @param callback - Function called when mutations occur
 * @param options - MutationObserver configuration options
 * @returns Ref callback to attach to target element
 */
function useMutationObserver<T extends HTMLElement = any>(
  callback: MutationCallback,
  options?: MutationObserverInit
): React.RefCallback<T | null>;

Usage Examples:

import { useMutationObserver } from "@mantine/hooks";

function DynamicContentWatcher() {
  const [changeCount, setChangeCount] = useState(0);
  
  const ref = useMutationObserver<HTMLDivElement>(
    (mutations) => {
      setChangeCount(prev => prev + mutations.length);
    },
    {
      childList: true,
      subtree: true,
      attributes: true,
      characterData: true,
    }
  );
  
  const addContent = () => {
    const element = ref.current;
    if (element) {
      const newElement = document.createElement('p');
      newElement.textContent = `Added at ${new Date().toLocaleTimeString()}`;
      element.appendChild(newElement);
    }
  };
  
  return (
    <div>
      <button onClick={addContent}>Add Content</button>
      <p>Changes detected: {changeCount}</p>
      <div ref={ref}>
        <p>Original content</p>
      </div>
    </div>
  );
}

useInViewport

Simple viewport visibility detection.

/**
 * Simple viewport visibility detection
 * @param options - IntersectionObserver options
 * @returns Object with ref and visibility state
 */
function useInViewport<T extends HTMLElement = any>(
  options?: IntersectionObserverInit
): UseInViewportReturnValue<T>;

interface UseInViewportReturnValue<T extends HTMLElement = any> {
  ref: React.RefCallback<T | null>;
  inViewport: boolean;
}

Usage Examples:

import { useInViewport } from "@mantine/hooks";

function FadeInOnScroll({ children }: { children: React.ReactNode }) {
  const { ref, inViewport } = useInViewport({
    threshold: 0.3,
  });
  
  return (
    <div
      ref={ref}
      style={{
        opacity: inViewport ? 1 : 0,
        transform: inViewport ? 'translateY(0)' : 'translateY(20px)',
        transition: 'opacity 0.6s ease, transform 0.6s ease',
      }}
    >
      {children}
    </div>
  );
}

// Analytics tracking
function AnalyticsTracker({ eventName }: { eventName: string }) {
  const { ref, inViewport } = useInViewport({
    threshold: 0.5,
  });
  
  useEffect(() => {
    if (inViewport) {
      analytics.track(`${eventName}_viewed`);
    }
  }, [inViewport, eventName]);
  
  return <div ref={ref}>Tracked content</div>;
}

Observer Patterns

Lazy Loading with Intersection Observer

import { useIntersection } from "@mantine/hooks";

function LazyLoadContainer({ items }: { items: any[] }) {
  const [visibleItems, setVisibleItems] = useState(items.slice(0, 10));
  const { ref, entry } = useIntersection({
    threshold: 0.1,
    rootMargin: '100px', // Load before reaching the bottom
  });
  
  useEffect(() => {
    if (entry?.isIntersecting && visibleItems.length < items.length) {
      setVisibleItems(prev => [
        ...prev,
        ...items.slice(prev.length, prev.length + 10)
      ]);
    }
  }, [entry?.isIntersecting, visibleItems.length, items]);
  
  return (
    <div>
      {visibleItems.map((item, index) => (
        <ItemComponent key={item.id} {...item} />
      ))}
      {visibleItems.length < items.length && (
        <div ref={ref} style={{ height: '50px', textAlign: 'center' }}>
          Loading more items...
        </div>
      )}
    </div>
  );
}

Responsive Layout with Size Observer

import { useElementSize } from "@mantine/hooks";

function ResponsiveGrid({ items }: { items: any[] }) {
  const { ref, width } = useElementSize();
  
  const getColumns = (containerWidth: number) => {
    if (containerWidth < 600) return 1;
    if (containerWidth < 900) return 2;
    if (containerWidth < 1200) return 3;
    return 4;
  };
  
  const columns = getColumns(width);
  
  return (
    <div
      ref={ref}
      style={{
        display: 'grid',
        gridTemplateColumns: `repeat(${columns}, 1fr)`,
        gap: '16px',
      }}
    >
      {items.map(item => (
        <GridItem key={item.id} {...item} />
      ))}
    </div>
  );
}

Content Change Detection

import { useMutationObserver } from "@mantine/hooks";

function ContentChangeTracker({ children }: { children: React.ReactNode }) {
  const [lastChange, setLastChange] = useState<Date | null>(null);
  const [changeLog, setChangeLog] = useState<string[]>([]);
  
  const ref = useMutationObserver<HTMLDivElement>(
    (mutations) => {
      const now = new Date();
      setLastChange(now);
      
      const changes = mutations.map(mutation => {
        switch (mutation.type) {
          case 'childList':
            return `Child nodes changed: +${mutation.addedNodes.length} -${mutation.removedNodes.length}`;
          case 'attributes':
            return `Attribute "${mutation.attributeName}" changed`;
          case 'characterData':
            return 'Text content changed';
          default:
            return 'Unknown change';
        }
      });
      
      setChangeLog(prev => [...prev.slice(-9), ...changes]);
    },
    {
      childList: true,
      attributes: true,
      characterData: true,
      subtree: true,
    }
  );
  
  return (
    <div>
      <div style={{ marginBottom: '16px', padding: '8px', background: '#f5f5f5' }}>
        <h3>Change Log</h3>
        <p>Last change: {lastChange?.toLocaleTimeString() || 'None'}</p>
        <ul style={{ maxHeight: '100px', overflow: 'auto' }}>
          {changeLog.map((change, index) => (
            <li key={index}>{change}</li>
          ))}
        </ul>
      </div>
      
      <div ref={ref}>
        {children}
      </div>
    </div>
  );
}

docs

browser-apis.md

device.md

dom-events.md

index.md

navigation.md

network.md

observers.md

specialized.md

state-management.md

storage.md

timing.md

utilities.md

tile.json