{
  "version": 3,
  "sources": ["../src/tomselect-init.js"],
  "sourcesContent": [
    "/**\n * Auto-initialise TomSelect on data-tomselect-prefilled attribute on <select> and <input>\n * Relies on window.TomSelect being loaded by django-tomselect middleware.\n *\n * Example usage:\n  * <select data-tomselect-prefilled='{\"placeholder\": \"Select an option\", \"maxItems\": 3, \"plugins\": [\"clear_button\"]}'>\n  *   <option value=\"1\">Option 1</option>\n  *   <option value=\"2\">Option 2</option>\n  * </select>\n */\n(function () {\n  /** Default render templates — DaisyUI badge items for multi-select */\n  /* Make sure it is kept in sync with templates/django_tomselect/render/item.html */\n  var defaultRender = {\n    item: function (data, escape) {\n      const safeText = escape(data.text);\n      if (this.settings.maxItems !== 1) {\n        return `<div class=\"badge badge-secondary badge-soft\" role=\"option\" title=\"${safeText}\"><span>${safeText}</span></div>`;\n      }\n      return `<div role=\"option\" title=\"${safeText}\">${safeText}</div>`;\n    },\n    // escape() skips ', so spots only in text or \"double-quoted\" attrs\n    option: function (data, escape) {\n      var template = this.settings.optionTemplate;\n      if (!template) return `<div>${escape(data.text)}</div>`;\n      return template.replace(/\\$\\{data\\.(\\w+)\\}/g, (_, field) =>\n        escape(data[field] ?? \"\"),\n      );\n    },\n  };\n\n  /** Plugin-level defaults that require JS functions */\n  /* Make sure it is kept in sync with templates/django_tomselect/render/clear_button.html */\n  var pluginDefaults = {\n    clear_button: {\n      html: function (data) {\n        return `<div class=\"ts-clear-button-wrapper tooltip tooltip-top\" data-tip=\"${data.title}\">\n          <button type=\"button\" class=\"${data.className}\" title=\"${data.title}\" aria-label=\"${data.title}\"></button>\n        </div>`;\n      },\n      get title() {\n        return gettext(\"Clear selection\");\n      },\n      className:\n        \"ts-clear-button btn btn-xs btn-circle btn-ghost btn-info outline-primary -outline-offset-4 hover:bg-transparent hover:border-transparent hover:outline-2 focus-visible:outline-2 focus-visible:border-transparent\",\n    },\n    remove_button: {\n      label: \"\",\n    },\n  };\n\n  /**\n   * Build the final TomSelect config from the raw JSON attribute value.\n   * - Render: defaultRender provides fallbacks; user config takes precedence.\n   * - Plugins: normalises array form [\"remove_button\", …] to the expected form.\n   * - Null-safe: null is valid JSON so any field could be null; normalise to {}\n   *   so Object.assign merges are always safe and TomSelect never receives null.\n   */\n  function buildConfig(raw) {\n    if (raw === null || typeof raw !== \"object\") raw = {};\n\n    var render = Object.assign({}, defaultRender, raw.render || {});\n\n    var plugins = raw.plugins;\n    if (Array.isArray(plugins)) {\n      var obj = {};\n      plugins.forEach(function (p) {\n        obj[p] = {};\n      });\n      plugins = obj;\n    }\n    if (plugins && typeof plugins === \"object\") {\n      Object.keys(plugins).forEach(function (name) {\n        if (pluginDefaults[name]) {\n          plugins[name] = Object.assign(\n            {},\n            pluginDefaults[name],\n            plugins[name] || {},\n          );\n        }\n      });\n    } else {\n      plugins = undefined;\n    }\n\n    return Object.assign(\n      {},\n      raw,\n      { render: render },\n      plugins ? { plugins: plugins } : {},\n    );\n  }\n\n  function applyMultiOverflowCount(ts) {\n    var control = ts.control;\n    if (!control) return;\n\n    var selectedItems = control.querySelectorAll('.item[data-value]');\n    var overflowCount = control.querySelector('.ts-overflow-count');\n    var count = selectedItems.length;\n\n    selectedItems.forEach(function (item, index) {\n      item.style.display = index === 0 ? '' : 'none';\n    });\n\n    if (count <= 1) {\n      if (overflowCount) overflowCount.remove();\n      return;\n    }\n\n    if (!overflowCount) {\n      overflowCount = document.createElement('span');\n      overflowCount.className = 'ts-overflow-count badge badge-soft badge-secondary';\n      control.appendChild(overflowCount);\n    }\n\n    overflowCount.textContent = '+ ' + (count - 1);\n  }\n\n  function setupMultiOverflowCount(ts, rawConfig) {\n    if (!rawConfig || !rawConfig.overflowCount) return;\n    if (!ts.settings || ts.settings.maxItems === 1) return;\n\n    ts.wrapper.classList.add(\"plugin-overflow_count\");\n\n    var refreshOverflowCount = function () {\n      applyMultiOverflowCount(ts);\n    };\n\n    ts.on('initialize', refreshOverflowCount);\n    ts.on('clear', refreshOverflowCount);\n    ts.on('change', refreshOverflowCount);\n\n    refreshOverflowCount();\n  }\n\n  // TODO: Remove when we use Popover API for tom-select CRM-793\n  /* Inside a <dialog>, hang the dropdown on the dialog itself, so the\n     modal-box's scroll can't clip it. TomSelect only positions for \"body\". */\n  function attachToDialog(ts) {\n    var dialog = ts.wrapper.closest(\"dialog\");\n    if (!dialog) return;\n    dialog.append(ts.dropdown);\n    dialog.addEventListener(\"close\", () => ts.dropdown.remove(), { once: true });\n    ts.positionDropdown = function () {\n      var rect = ts.control.getBoundingClientRect();\n      Object.assign(ts.dropdown.style, {\n        position: \"fixed\",\n        top: `${rect.bottom}px`,\n        left: `${rect.left}px`,\n        width: `${rect.width}px`,\n      });\n    };\n  }\n\n  function initTomSelects(root) {\n    if (!window.TomSelect) return;\n    var selects = (root || document).querySelectorAll(\n      \"select[data-tomselect-prefilled], input[data-tomselect-prefilled]\",\n    );\n    selects.forEach(function (el) {\n      if (el.tomselect) return; // already initialised\n      // Skip elements managed by django-tomselect's AJAX widgets — they\n      // use `data-tomselect` and initialise themselves via inline <script>.\n      if (el.hasAttribute(\"data-tomselect\")) return;\n      // Strip any stale TomSelect classes that may remain on the element after\n      // an HTMX swap (e.g. when form.media re-executes tomselect-init.js during\n      // the settle phase). If these are present when the TomSelect constructor\n      // reads el.className, they get copied onto the ts-wrapper, which then\n      // receives ts-hidden-accessible and becomes invisible.\n      // Fixes bug where TomSelect fails to initialise on HTMX swap after form_invalid.\n      el.classList.remove(\"tomselected\", \"ts-hidden-accessible\");\n      var raw = {};\n      try {\n        raw = JSON.parse(el.getAttribute(\"data-tomselect-prefilled\"));\n        // Attribute can receive a config object\n        // E.g '{\"placeholder\": \"Select an option\", \"maxItems\": 3, \"plugins\": [\"clear_button\"]}'\n      } catch (_) {}\n      var tomSelect = new TomSelect(el, buildConfig(raw));\n      setupMultiOverflowCount(tomSelect, raw);\n      attachToDialog(tomSelect);\n    });\n  }\n\n  // Init on page load\n  if (document.readyState === \"loading\") {\n    document.addEventListener(\"DOMContentLoaded\", function () {\n      initTomSelects();\n    });\n  } else {\n    initTomSelects();\n  }\n\n  // Re-init after HTMX swaps\n  document.addEventListener(\"htmx:afterSettle\", function (event) {\n    initTomSelects(event.detail.target);\n  });\n})();\n"
  ],
  "mappings": "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",
  "debugId": "3F8975DEC9FE1D5264756E2164756E21",
  "names": []
}