/**********************************
 *  SLIDE UP
 * Animates an element to collapse by gradually changing its height,
 * padding, and margin to 0 over a specified duration.
 **********************************/

let slideUp = (target, duration = 500) => {
  // Initialize the transition properties for a smooth animation.
  target.style.transitionProperty = "height, margin, padding";
  target.style.transitionDuration = duration + "ms";

  // Set the element's height to its current offsetHeight to fix the height,
  // which is necessary to animate from a specific height to 0.
  target.style.height = target.offsetHeight + "px";
  target.offsetHeight; // Trigger a reflow, ensuring the height is applied.

  // Collapse the element by setting its height, padding, and margin to 0.
  target.style.overflow = "hidden";
  target.style.height = 0;
  target.style.paddingTop = 0;
  target.style.paddingBottom = 0;
  target.style.marginTop = 0;
  target.style.marginBottom = 0;

  // After the animation duration, hide the element and reset its styles.
  window.setTimeout(() => {
    target.style.display = "none";
    // Remove the properties to return to the element's original CSS values.
    [
      "height",
      "padding-top",
      "padding-bottom",
      "margin-top",
      "margin-bottom",
      "overflow",
      "transition-duration",
      "transition-property",
    ].forEach((property) => {
      target.style.removeProperty(property);
    });
  }, duration);
};

/**********************************
 *  SLIDE DOWN
 * Animates an element to expand by dynamically setting its height,
 * and then gradually changing it to the target height over a specified duration.
 **********************************/

let slideDown = (target, duration = 500) => {
  // Ensure the element is visible to calculate its target height.
  target.style.removeProperty("display");
  let display = window.getComputedStyle(target).display;

  // If the element was not displayed, set it to block to measure its height.
  if (display === "none") display = "block";
  target.style.display = display;

  // Measure the height that the element should animate to.
  let height = target.offsetHeight;
  target.style.overflow = "hidden";
  target.style.height = 0; // Start the animation from 0 height.

  // Reset padding and margin to ensure they're included in the height calculation.
  target.style.paddingTop = 0;
  target.style.paddingBottom = 0;
  target.style.marginTop = 0;
  target.style.marginBottom = 0;
  target.offsetHeight; // Trigger a reflow.

  // Initialize the transition and set the target height to animate to.
  target.style.transitionProperty = "height, margin, padding";
  target.style.transitionDuration = duration + "ms";
  target.style.height = height + "px";

  // After the animation, reset properties to allow the element to layout naturally.
  window.setTimeout(() => {
    [
      "height",
      "overflow",
      "transition-duration",
      "transition-property",
    ].forEach((property) => {
      target.style.removeProperty(property);
    });
  }, duration);
};

// /**********************************
//  *  SLIDE TOGGLE
//  * Toggles the visibility of an element by animating its height,
//  * effectively combining slideUp and slideDown functionalities based on the element's current state.
//  **********************************/

// let slideToggle = (target, duration = 500) => {
//   // Determine the current display state and apply the appropriate animation.
//   window.getComputedStyle(target).display === "none"
//     ? slideDown(target, duration)
//     : slideUp(target, duration);
// };