# All files / draggable useLocalStorageDraggable.ts

100% Statements 92/92
100% Branches 5/5
66.66% Functions 2/3
100% Lines 92/92

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    931x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    4x
    4x
    4x
    4x
    4x
    4x
    4x
    4x
    4x
    4x
    4x
    4x
    4x
    4x
    4x
    4x
    4x
    4x
    4x
    4x
    3x
    1x
    1x
    4x
    4x
    4x
    4x
    4x
    4x
    4x
    4x
    4x
    4x
    4x
     "use client";
    import { useEffect, useState } from "react";
    import type { UseStateInitializer, UseStateSetter } from "../types";
    import type {
      LocalStorageHookOptions,
      LocalStorageHookReturnValue,
    } from "../useLocalStorage";
    import { useLocalStorage } from "../useLocalStorage";
    import type {
      BaseDraggableOptions,
      ControlledDraggableImplementation,
    } from "./useControlledDraggable";
    import { useControlledDraggable } from "./useControlledDraggable";
    import { deserializeDraggableValue, getDraggableDefaultValue } from "./utils";

    /**
     * @remarks \@since 6.0.0
     */
    export interface LocalStorageDraggableOptions<E extends HTMLElement>
      extends BaseDraggableOptions<E>,
        Pick<LocalStorageHookOptions<E>, "key" | "manual"> {
      /**
       * @defaultValue `Math.ceil((max - min) / 2)`
       */
      defaultValue?: UseStateInitializer<number>;
    }

    /**
     * @remarks \@since 6.0.0
     */
    export interface LocalStorageDraggableImplementation<E extends HTMLElement>
      extends ControlledDraggableImplementation<E>,
        Pick<LocalStorageHookReturnValue<E>, "persist" | "remove"> {
      /**
       * The current drag distance in pixels.
       */
      value: number;

      /**
       * This can be used to manually set the {@link value} if that is needed for
       * some custom behavior.
       */
      setValue: UseStateSetter<number>;

      /**
       * This will be `true` when the user is dragging the element through mouse or
       * touch.
       */
      dragging: boolean;
    }

    /**
     * An implementation of the {@link useControlledDraggable} hook that uses
     * `localStorage` for state.
     *
     * @remarks \@since 6.0.0
     */
    export function useLocalStorageDraggable<E extends HTMLElement>(
      options: LocalStorageDraggableOptions<E>
    ): LocalStorageDraggableImplementation<E> {
      const { key, manual, min, max, defaultValue, ...dragOptions } = options;
      const [dragging, setDragging] = useState(false);
      const { value, setValue, persist, remove } = useLocalStorage({
        key,
        manual: manual || dragging,
        defaultValue: () => getDraggableDefaultValue({ min, max, defaultValue }),
        deserializer: (item) => deserializeDraggableValue({ min, max, item }),
      });
      const draggable = useControlledDraggable({
        ...dragOptions,
        min,
        max,
        setValue,
        dragging,
        setDragging,
      });
      const { draggedOnce } = draggable;
      useEffect(() => {
        if (!dragging && draggedOnce.current) {
          persist();
        }
      }, [draggedOnce, dragging, persist]);

      return {
        ...draggable,
        value,
        setValue,
        dragging,
        persist,
        remove,
      };
    }