import { h } from './index-fe9aece8.js';
import { c as closestElementCrossShadowBoundary } from './utils-5982bee2.js';

/** Checks if component has checked property. */
function canBeCheckable(component) {
  return 'checked' in component;
}
/** Checks if component has indeterminate property. */
function canBeIndeterminate(component) {
  return 'indeterminate' in component;
}
/** Checks if component has default selected index */
function hasDefaultSelectedIndex(component) {
  return 'defaultSelectedIndex' in component;
}
const onFormResetMap = new WeakMap();
const formComponentSet = new WeakSet();
/**
 * Checks if a given component is registered to a different form than the given one.
 * @function
 * @param {HTMLFormElement} form - The form to check against.
 * @param {HTMLElement} formComponentEl - The element to check for.
 * @return {boolean} element registered to a different form.
 */
function hasRegisteredFormComponentParent(form, formComponentEl) {
  // we use events as a way to test for nested form-associated components across shadow bounds
  const formComponentRegisterEventName = 'internalFormComponentRegister';
  let isRegistered = false;
  form.addEventListener(formComponentRegisterEventName, (event) => {
    isRegistered = event.composedPath().some((element) => formComponentSet.has(element));
    event.stopPropagation();
  }, { once: true });
  formComponentEl.dispatchEvent(new CustomEvent(formComponentRegisterEventName, {
    bubbles: true,
    composed: true,
  }));
  return isRegistered;
}
/** Reset properties of a form component to their defaults. */
function onFormReset() {
  if (hasDefaultSelectedIndex(this))
    this.onFormReset();
  else
    this.value = this.defaultValue;
  if (canBeCheckable(this))
    this.checked = this.defaultChecked;
  if (canBeIndeterminate(this))
    this.indeterminate = this.defaultIndeterminate;
}
/** Helper to set up form interactions on connectedCallback. */
function connectForm(component) {
  const { host, value } = component;
  const form = closestElementCrossShadowBoundary(host, 'form');
  const boundOnFormReset = (component.onFormReset || onFormReset).bind(component);
  if (!form || hasRegisteredFormComponentParent(form, host))
    return;
  form.addEventListener('reset', boundOnFormReset);
  formComponentSet.add(host);
  component.formEl = form;
  component.defaultValue = value;
  if (canBeCheckable(component))
    component.defaultChecked = component.checked;
  if (canBeIndeterminate(component))
    component.defaultIndeterminate = component.indeterminate;
  if (hasDefaultSelectedIndex(component))
    component.defaultSelectedIndex = component.defaultSelectedIndex;
}
/** Helper to tear down form interactions on disconnectedCallback. */
function disconnectForm(component) {
  const { host, formEl } = component;
  const boundOnFormReset = onFormResetMap.get(host);
  if (!formEl)
    return;
  formEl.removeEventListener('reset', boundOnFormReset);
  onFormResetMap.delete(host);
  component.formEl = null;
  formComponentSet.delete(host);
}
/**
 * Helper for maintaining a form-associated's hidden input in sync with the component.
 *
 * Based on Ionic's approach: https://github.com/ionic-team/ionic-framework/blob/e4bf052794af9aac07f887013b9250d2a045eba3/core/src/utils/helpers.ts#L198
 */
const HiddenFormInputSlot = ({ component, type }) => {
  const { disabled, hiddenInput, host, max, maxlength, min, minlength, name, pattern, readonly, required, value } = component;
  const hiddenFormInputSlotName = 'hidden-form-input';
  let input = host.querySelector(`input[slot="${hiddenFormInputSlotName}"]`);
  if (!input) {
    input = host.ownerDocument.createElement('input');
    if (name)
      input.name = name;
    if (!hiddenInput)
      component.hiddenInput = input;
    input.tabIndex = -1;
    input.slot = hiddenFormInputSlotName;
    input.style.opacity = '0';
    input.style.position = 'absolute';
    input.style.zIndex = '-1';
    input.addEventListener('invalid', (event) => event.preventDefault());
    input.setAttribute('aria-hidden', 'true');
    if (max)
      input.setAttribute('max', max);
    if (maxlength)
      input.setAttribute('maxlength', maxlength);
    if (min)
      input.setAttribute('min', min);
    if (minlength)
      input.setAttribute('minlength', minlength);
    if (pattern)
      input.setAttribute('pattern', pattern);
    if (type)
      input.setAttribute('type', type);
    if (readonly)
      input.readOnly = readonly;
    host.appendChild(input);
  }
  if (canBeCheckable(component))
    input.checked = component.checked;
  if (canBeIndeterminate(component))
    input.indeterminate = component.indeterminate;
  input.disabled = disabled;
  input.required = required;
  input.value = value;
  return h("slot", { name: hiddenFormInputSlotName });
};

export { HiddenFormInputSlot as H, connectForm as c, disconnectForm as d };

//# sourceMappingURL=form-9dbf1e1f.js.map