web-mojo 2.1.1100 → 2.1.1101

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/admin.cjs.js +1 -1
  2. package/dist/admin.es.js +7 -7
  3. package/dist/auth.cjs.js +1 -1
  4. package/dist/auth.es.js +1 -1
  5. package/dist/charts.cjs.js +1 -1
  6. package/dist/charts.es.js +3 -3
  7. package/dist/chunks/{ChatView-D5QdhLLu.js → ChatView-ZqTCdUZP.js} +2 -2
  8. package/dist/chunks/{ChatView-D5QdhLLu.js.map → ChatView-ZqTCdUZP.js.map} +1 -1
  9. package/dist/chunks/{ChatView-SeOtA6Ln.js → ChatView-oka6O6VS.js} +3 -3
  10. package/dist/chunks/{ChatView-SeOtA6Ln.js.map → ChatView-oka6O6VS.js.map} +1 -1
  11. package/dist/chunks/{Dialog-DhUxk9f6.js → Dialog-DRf1-ZSd.js} +3 -3
  12. package/dist/chunks/{Dialog-DhUxk9f6.js.map → Dialog-DRf1-ZSd.js.map} +1 -1
  13. package/dist/chunks/{Dialog-Ba8-_bwZ.js → Dialog-DwgF3hri.js} +2 -2
  14. package/dist/chunks/{Dialog-Ba8-_bwZ.js.map → Dialog-DwgF3hri.js.map} +1 -1
  15. package/dist/chunks/{FormView-BhNE8_ux.js → FormView-DJBMpeMY.js} +2 -1
  16. package/dist/chunks/{FormView-BhNE8_ux.js.map → FormView-DJBMpeMY.js.map} +1 -1
  17. package/dist/chunks/{FormView-6msHIICZ.js → FormView-DkBylHdd.js} +2 -2
  18. package/dist/chunks/{FormView-6msHIICZ.js.map → FormView-DkBylHdd.js.map} +1 -1
  19. package/dist/chunks/{MetricsMiniChartWidget-jCLMh6Bm.js → MetricsMiniChartWidget-DRIJwI91.js} +2 -2
  20. package/dist/chunks/{MetricsMiniChartWidget-jCLMh6Bm.js.map → MetricsMiniChartWidget-DRIJwI91.js.map} +1 -1
  21. package/dist/chunks/{MetricsMiniChartWidget-DpdCMZZq.js → MetricsMiniChartWidget-DlmsNmJy.js} +2 -2
  22. package/dist/chunks/{MetricsMiniChartWidget-DpdCMZZq.js.map → MetricsMiniChartWidget-DlmsNmJy.js.map} +1 -1
  23. package/dist/chunks/{PDFViewer-Daqgh9u9.js → PDFViewer-BRy3UHth.js} +2 -2
  24. package/dist/chunks/{PDFViewer-Daqgh9u9.js.map → PDFViewer-BRy3UHth.js.map} +1 -1
  25. package/dist/chunks/{PDFViewer-kcsI_Orb.js → PDFViewer-Cx3C0CHL.js} +2 -2
  26. package/dist/chunks/{PDFViewer-kcsI_Orb.js.map → PDFViewer-Cx3C0CHL.js.map} +1 -1
  27. package/dist/chunks/{TokenManager-B8v1e48O.js → TokenManager-CWi9-XBF.js} +2 -2
  28. package/dist/chunks/{TokenManager-B8v1e48O.js.map → TokenManager-CWi9-XBF.js.map} +1 -1
  29. package/dist/chunks/{TokenManager-_H9DetR8.js → TokenManager-DVrApE_3.js} +2 -2
  30. package/dist/chunks/{TokenManager-_H9DetR8.js.map → TokenManager-DVrApE_3.js.map} +1 -1
  31. package/dist/chunks/{version-DMeIxex5.js → version-Be_W-mxT.js} +4 -4
  32. package/dist/chunks/{version-DMeIxex5.js.map → version-Be_W-mxT.js.map} +1 -1
  33. package/dist/chunks/{version-DQJsIARK.js → version-Ce-8QdEq.js} +2 -2
  34. package/dist/chunks/{version-DQJsIARK.js.map → version-Ce-8QdEq.js.map} +1 -1
  35. package/dist/docit.cjs.js +1 -1
  36. package/dist/docit.es.js +3 -3
  37. package/dist/index.cjs.js +1 -1
  38. package/dist/index.es.js +7 -7
  39. package/dist/lightbox.cjs.js +1 -1
  40. package/dist/lightbox.es.js +4 -4
  41. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"FormView-BhNE8_ux.js","sources":["../../src/core/forms/FormPlugins.js","../../src/core/forms/FormBuilder.js","../../src/core/mixins/FileDropMixin.js","../../src/core/forms/inputs/TagInput.js","../../src/core/forms/inputs/CollectionSelect.js","../../src/core/forms/inputs/CollectionMultiSelect.js","../../src/core/forms/inputs/DatePicker.js","../../src/core/forms/inputs/DateRangePicker.js","../../src/core/forms/inputs/ComboInput.js","../../src/core/forms/FormView.js"],"sourcesContent":["/**\n * FormPlugins - Lightweight, pluggable registry for FormView/FormBuilder extensions\n *\n * Goals:\n * - Zero hard dependency on any single extension; core remains stable\n * - Extensions opt-in by calling FormPlugins.register(plugin)\n * - If no plugin is loaded, nothing changes\n *\n * A plugin is a plain object:\n * {\n * id: 'location', // required, unique\n * // Optional: custom field renderers by type\n * fieldTypes: {\n * 'address': (builder, fieldConfig) => stringHTML\n * },\n * // Optional lifecycle hooks\n * onFormBuilderInit(builder) {},\n * onFormViewInit(formView) {},\n * onAfterRender(formView) {},\n * onFieldInit(formView, fieldEl, fieldConfig) {},\n * onFieldChange(formView, fieldName, value) {}\n * }\n *\n * Usage (in an extension):\n * import { FormPlugins } from '@core/forms/FormPlugins.js';\n * const unregister = FormPlugins.register(myPlugin);\n * // later (optional)\n * unregister();\n */\n\nexport class FormPlugins {\n // Registered plugins\n static _plugins = [];\n // Map of field type => { renderer: Function, pluginId: string }\n static _renderers = new Map();\n\n /**\n * Register a plugin. If a plugin with the same id exists, it's replaced.\n * @param {object} plugin - Plugin definition (see header)\n * @returns {Function} unregister function\n */\n static register(plugin) {\n if (!plugin || typeof plugin !== 'object') {\n console.warn('[FormPlugins] register called with invalid plugin:', plugin);\n return () => {};\n }\n if (!plugin.id || typeof plugin.id !== 'string') {\n console.warn('[FormPlugins] plugin must have a unique string \"id\"', plugin);\n return () => {};\n }\n\n // Remove any previous plugin with same id\n this.unregister(plugin.id);\n\n // Register field renderers (if any)\n if (plugin.fieldTypes && typeof plugin.fieldTypes === 'object') {\n Object.entries(plugin.fieldTypes).forEach(([type, renderer]) => {\n if (typeof renderer === 'function') {\n this._renderers.set(type, { renderer, pluginId: plugin.id });\n } else {\n console.warn(`[FormPlugins] renderer for type \"${type}\" is not a function`);\n }\n });\n }\n\n // Store plugin\n this._plugins.push(plugin);\n\n // Return disposer\n return () => this.unregister(plugin.id);\n }\n\n /**\n * Unregister a plugin by id. Removes its field renderers as well.\n * @param {string} id - Plugin id\n */\n static unregister(id) {\n if (!id) return;\n\n // Remove from plugin list\n this._plugins = this._plugins.filter(p => p.id !== id);\n\n // Remove its renderers\n for (const [type, meta] of this._renderers.entries()) {\n if (meta?.pluginId === id) {\n this._renderers.delete(type);\n }\n }\n }\n\n /**\n * Get a custom field renderer by type (if registered).\n * @param {string} type - Field type\n * @returns {(builder: any, fieldConfig: object) => string | null}\n */\n static getRenderer(type) {\n const meta = this._renderers.get(type);\n return meta?.renderer || null;\n }\n\n /**\n * Returns true if a renderer exists for a field type\n */\n static hasRenderer(type) {\n return this._renderers.has(type);\n }\n\n /**\n * Get a shallow copy of registered plugins (read-only use).\n */\n static getPlugins() {\n return [...this._plugins];\n }\n\n // -----------------------------\n // Safe dispatch to plugin hooks\n // -----------------------------\n\n static _invoke(plugin, hook, ...args) {\n const fn = plugin?.[hook];\n if (typeof fn !== 'function') return;\n try {\n return fn.apply(plugin, args);\n } catch (err) {\n console.error(`[FormPlugins] ${hook} error from plugin \"${plugin.id}\":`, err);\n }\n }\n\n /**\n * Called by FormBuilder (e.g., in ctor or initializeTemplates)\n * @param {any} builder\n */\n static onFormBuilderInit(builder) {\n this._plugins.forEach(p => this._invoke(p, 'onFormBuilderInit', builder));\n }\n\n /**\n * Called by FormView constructor or early init\n * @param {any} formView\n */\n static onFormViewInit(formView) {\n this._plugins.forEach(p => this._invoke(p, 'onFormViewInit', formView));\n }\n\n /**\n * Called by FormView.onAfterRender\n * @param {any} formView\n */\n static onFormViewAfterRender(formView) {\n this._plugins.forEach(p => this._invoke(p, 'onAfterRender', formView));\n }\n\n /**\n * Called when a specific field element is initialized (after DOM exists)\n * @param {any} formView\n * @param {HTMLElement} fieldEl\n * @param {object} fieldConfig\n */\n static onFieldInit(formView, fieldEl, fieldConfig) {\n this._plugins.forEach(p => this._invoke(p, 'onFieldInit', formView, fieldEl, fieldConfig));\n }\n\n /**\n * Called when a field value changes (normalized point)\n * @param {any} formView\n * @param {string} fieldName\n * @param {any} value\n */\n static onFieldChange(formView, fieldName, value) {\n this._plugins.forEach(p => this._invoke(p, 'onFieldChange', formView, fieldName, value));\n }\n}\n\nexport default FormPlugins;","/**\n * FormBuilder - Pure HTML form generator for MOJO framework\n * Generates form HTML from field definitions with Bootstrap 5 grid layout support\n * NO event handling, lifecycle, or mounting - pure HTML generation only\n */\n\nimport Mustache from '@core/utils/mustache.js';\nimport MOJOUtils from '@core/utils/MOJOUtils.js';\nimport { FormPlugins } from '@core/forms/FormPlugins.js';\n\nclass FormBuilder {\n constructor(config = {}) {\n this.fields = config.fields || [];\n this.structureOnly = config.structureOnly || false; // New option\n\n // Convert cols to columns for all fields\n this.fields.forEach(field => {\n if (field.cols && !field.columns) {\n field.columns = field.cols;\n delete field.cols;\n } else if (!field.columns) {\n field.columns = 12;\n }\n\n // Handle nested fields in groups\n if (field.type === 'group' && field.fields) {\n field.fields.forEach(groupField => {\n if (groupField.cols && !groupField.columns) {\n groupField.columns = groupField.cols;\n delete groupField.cols;\n } else if (!groupField.columns) {\n groupField.columns = 12;\n }\n });\n }\n });\n\n this.options = {\n formClass: 'needs-validation',\n formMethod: 'POST',\n formAction: '',\n groupClass: 'row mb-3',\n fieldWrapper: '',\n labelClass: 'form-label',\n inputClass: 'form-control',\n errorClass: 'invalid-feedback',\n helpClass: 'form-text',\n submitButton: false,\n resetButton: false,\n ...config.options\n };\n this.buttons = config.buttons || [];\n this.data = config.data || {};\n this.errors = config.errors || {};\n this.initializeTemplates();\n }\n\n /**\n * Initialize field templates\n */\n initializeTemplates() {\n FormPlugins.onFormBuilderInit?.(this);\n this.templates = {\n input: `\n <div class=\"mojo-form-control\">\n {{#label}}\n <label for=\"{{fieldId}}\" class=\"{{labelClass}}\">\n {{label}}{{#required}}<span class=\"text-danger\">*</span>{{/required}}\n </label>\n {{/label}}\n <input type=\"{{type}}\" id=\"{{fieldId}}\" name=\"{{name}}\"\n class=\"{{inputClass}}{{#error}} is-invalid{{/error}}\"\n value=\"{{fieldValue}}\" {{#placeholder}}placeholder=\"{{placeholder}}\"{{/placeholder}}\n {{#required}}required{{/required}} {{#disabled}}disabled{{/disabled}}\n {{#readonly}}readonly{{/readonly}} {{{attrs}}}>\n {{#help}}<div class=\"{{helpClass}}\">{{help}}</div>{{/help}}\n {{#error}}<div class=\"{{errorClass}}\">{{error}}</div>{{/error}}\n </div>\n `,\n\n password: `\n <div class=\"mojo-form-control\">\n {{#label}}\n <label for=\"{{fieldId}}\" class=\"{{labelClass}}\">\n {{label}}{{#required}}<span class=\"text-danger\">*</span>{{/required}}\n </label>\n {{/label}}\n <div class=\"input-group\">\n <input type=\"password\" id=\"{{fieldId}}\" name=\"{{name}}\"\n class=\"{{inputClass}}{{#error}} is-invalid{{/error}}\"\n value=\"{{fieldValue}}\" {{#placeholder}}placeholder=\"{{placeholder}}\"{{/placeholder}}\n {{#required}}required{{/required}} {{#disabled}}disabled{{/disabled}}\n {{#readonly}}readonly{{/readonly}}\n data-field-type=\"password\" {{{attrs}}}>\n {{#showToggle}}\n <button type=\"button\" class=\"btn btn-outline-secondary\"\n data-action=\"toggle-password\"\n data-target=\"{{fieldId}}\"\n aria-label=\"Show password\" aria-pressed=\"false\">\n <i class=\"bi bi-eye\"></i>\n </button>\n {{/showToggle}}\n </div>\n {{#strengthMeter}}\n <div class=\"mt-2\">\n <div class=\"progress\" style=\"height: 4px;\">\n <div class=\"progress-bar bg-secondary\" role=\"progressbar\"\n style=\"width: 0%;\" aria-valuenow=\"0\" aria-valuemin=\"0\" aria-valuemax=\"100\"\n id=\"{{fieldId}}_strength_bar\"></div>\n </div>\n <small class=\"{{helpClass}}\" id=\"{{fieldId}}_strength_text\">Strength</small>\n </div>\n {{/strengthMeter}}\n {{#capsLockWarning}}\n <div class=\"{{helpClass}} text-warning d-none\" id=\"{{fieldId}}_caps_warning\">\n Caps Lock is on\n </div>\n {{/capsLockWarning}}\n {{#help}}<div class=\"{{helpClass}}\">{{help}}</div>{{/help}}\n {{#error}}<div class=\"{{errorClass}}\">{{error}}</div>{{/error}}\n </div>\n `,\n\n\n\n textarea: `\n <div class=\"mojo-form-control\">\n {{#label}}\n <label for=\"{{fieldId}}\" class=\"{{labelClass}}\">\n {{label}}{{#required}}<span class=\"text-danger\">*</span>{{/required}}\n </label>\n {{/label}}\n <textarea id=\"{{fieldId}}\" name=\"{{name}}\" class=\"{{inputClass}}{{#error}} is-invalid{{/error}}\"\n rows=\"{{rows}}\" {{#placeholder}}placeholder=\"{{placeholder}}\"{{/placeholder}}\n {{#required}}required{{/required}} {{#disabled}}disabled{{/disabled}}\n {{#readonly}}readonly{{/readonly}} {{{attrs}}}>{{fieldValue}}</textarea>\n {{#help}}<div class=\"{{helpClass}}\">{{help}}</div>{{/help}}\n {{#error}}<div class=\"{{errorClass}}\">{{error}}</div>{{/error}}\n </div>\n `,\n\n select: `\n <div class=\"mojo-form-control\">\n {{#label}}\n <label for=\"{{fieldId}}\" class=\"{{labelClass}}\">\n {{label}}{{#required}}<span class=\"text-danger\">*</span>{{/required}}\n </label>\n {{/label}}\n {{#searchInput}}{{{searchInput}}}{{/searchInput}}\n <select id=\"{{fieldId}}\" name=\"{{name}}\" class=\"{{inputClass}}{{#error}} is-invalid{{/error}}\"\n {{#required}}required{{/required}} {{#disabled}}disabled{{/disabled}}\n {{#multiple}}multiple{{/multiple}} {{{attrs}}}>\n {{{optionsHTML}}}\n </select>\n {{#help}}<div class=\"{{helpClass}}\">{{help}}</div>{{/help}}\n {{#error}}<div class=\"{{errorClass}}\">{{error}}</div>{{/error}}\n </div>\n `,\n\n checkbox: `\n <div class=\"mojo-form-control\">\n <div class=\"form-check {{fieldClass}}\">\n <input type=\"checkbox\" id=\"{{fieldId}}\" name=\"{{name}}\"\n class=\"form-check-input{{#error}} is-invalid{{/error}}\" value=\"{{value}}\"\n {{#checked}}checked{{/checked}} {{#required}}required{{/required}}\n {{#disabled}}disabled{{/disabled}} {{{attrs}}}>\n <label class=\"form-check-label\" for=\"{{fieldId}}\">{{label}}</label>\n </div>\n {{#help}}<div class=\"{{helpClass}}\">{{help}}</div>{{/help}}\n {{#error}}<div class=\"{{errorClass}}\">{{error}}</div>{{/error}}\n </div>\n </div>\n `,\n\n switch: `\n <div class=\"mojo-form-control\">\n <div class=\"form-check form-switch {{sizeClass}} {{fieldClass}}\">\n <input type=\"checkbox\" id=\"{{fieldId}}\" name=\"{{name}}\" role=\"switch\"\n class=\"form-check-input{{#error}} is-invalid{{/error}}\" value=\"{{value}}\"\n {{#checked}}checked{{/checked}} {{#required}}required{{/required}}\n {{#disabled}}disabled{{/disabled}} data-change-action=\"toggle-switch\"\n data-field=\"{{name}}\" {{{attrs}}}>\n <label class=\"form-check-label\" for=\"{{fieldId}}\">{{label}}</label>\n </div>\n {{#help}}<div class=\"{{helpClass}}\">{{help}}</div>{{/help}}\n {{#error}}<div class=\"{{errorClass}}\">{{error}}</div>{{/error}}\n </div>\n `,\n\n image: `\n <div class=\"mojo-form-control\">\n {{#label}}\n <label for=\"{{fieldId}}\" class=\"{{labelClass}}\">\n {{label}}{{#required}}<span class=\"text-danger\">*</span>{{/required}}\n </label>\n {{/label}}\n <div class=\"image-field-container {{containerClass}}\" id=\"{{dropZoneId}}\" style=\"width: {{width}}px; height: {{height}}px;\">\n <input type=\"file\" id=\"{{fieldId}}\" name=\"{{name}}\" class=\"{{inputClass}} d-none{{#error}} is-invalid{{/error}}\"\n accept=\"{{accept}}\" {{#required}}required{{/required}} {{#disabled}}disabled{{/disabled}}\n data-change-action=\"image-selected\" data-field=\"{{name}}\" {{{attrs}}}>\n <div class=\"image-drop-zone{{#allowDrop}} droppable{{/allowDrop}}\" data-action=\"click-image-upload\"\n data-field-id=\"{{fieldId}}\" data-field=\"{{name}}\" style=\"width: 100%; height: 100%; cursor: {{cursor}};\">\n {{#imageUrl}}\n <img id=\"{{previewId}}\" src=\"{{imageUrl}}\" alt=\"Preview\" class=\"img-thumbnail w-100 h-100\" style=\"object-fit: cover;\">\n {{#showRemove}}\n <button type=\"button\" class=\"btn btn-sm btn-danger position-absolute top-0 end-0 m-1\"\n data-action=\"remove-image\" data-field-id=\"{{fieldId}}\" data-field=\"{{name}}\" style=\"opacity: 0.8;\">\n <i class=\"bi bi-x\"></i>\n </button>\n {{/showRemove}}\n {{/imageUrl}}\n {{^imageUrl}}\n <div class=\"d-flex flex-column align-items-center justify-content-center h-100 text-muted border border-2 border-dashed\">\n <i class=\"bi bi-image fs-1 mb-2\"></i>\n <small class=\"text-center px-2\">{{placeholderText}}</small>\n </div>\n {{/imageUrl}}\n </div>\n </div>\n {{#help}}<div class=\"{{helpClass}}\">{{help}}</div>{{/help}}\n {{#error}}<div class=\"{{errorClass}}\">{{error}}</div>{{/error}}\n </div>\n `,\n\n range: `\n <div class=\"mojo-form-control\">\n {{#label}}\n <label for=\"{{fieldId}}\" class=\"{{labelClass}}\">\n {{label}}: <span id=\"{{fieldId}}_value\">{{fieldValue}}</span>\n </label>\n {{/label}}\n <input type=\"range\" id=\"{{fieldId}}\" name=\"{{name}}\" class=\"{{inputClass}}{{#error}} is-invalid{{/error}}\"\n min=\"{{min}}\" max=\"{{max}}\" step=\"{{step}}\" value=\"{{fieldValue}}\" {{#disabled}}disabled{{/disabled}}\n data-change-action=\"range-changed\" data-target=\"{{fieldId}}_value\" {{{attrs}}}>\n {{#help}}<div class=\"{{helpClass}}\">{{help}}</div>{{/help}}\n {{#error}}<div class=\"{{errorClass}}\">{{error}}</div>{{/error}}\n </div>\n `,\n\n file: `\n <div class=\"mojo-form-control\">\n {{#label}}\n <label for=\"{{fieldId}}\" class=\"{{labelClass}}\">\n {{label}}{{#required}}<span class=\"text-danger\">*</span>{{/required}}\n </label>\n {{/label}}\n <input type=\"file\" id=\"{{fieldId}}\" name=\"{{name}}\" class=\"{{inputClass}}{{#error}} is-invalid{{/error}}\"\n accept=\"{{accept}}\" {{#required}}required{{/required}} {{#disabled}}disabled{{/disabled}}\n {{#multiple}}multiple{{/multiple}} data-change-action=\"file-selected\" {{{attrs}}}>\n {{#help}}<div class=\"{{helpClass}}\">{{help}}</div>{{/help}}\n {{#error}}<div class=\"{{errorClass}}\">{{error}}</div>{{/error}}\n </div>\n `,\n\n radio: `\n <div class=\"mojo-form-control\">\n {{#label}}<div class=\"{{labelClass}}\">{{label}}{{#required}}<span class=\"text-danger\">*</span>{{/required}}</div>{{/label}}\n {{#options}}\n <div class=\"form-check\">\n <input type=\"radio\" id=\"{{fieldId}}_{{value}}\" name=\"{{name}}\" value=\"{{value}}\"\n class=\"form-check-input{{#error}} is-invalid{{/error}}\" {{#checked}}checked{{/checked}}\n {{#required}}required{{/required}} {{#disabled}}disabled{{/disabled}}\n {{{attrs}}}>\n <label class=\"form-check-label\" for=\"{{fieldId}}_{{value}}\">{{text}}</label>\n </div>\n {{/options}}\n {{#help}}<div class=\"{{helpClass}}\">{{help}}</div>{{/help}}\n {{#error}}<div class=\"{{errorClass}}\">{{error}}</div>{{/error}}\n </div>\n `,\n\n button: `\n <button type=\"button\" {{#name}}name=\"{{name}}\"{{/name}} class=\"btn {{fieldClass}}\"\n {{#action}}data-action=\"{{action}}\"{{/action}} {{#disabled}}disabled{{/disabled}} {{{attrs}}}>\n {{label}}\n </button>\n `,\n\n divider: `\n <hr class=\"{{dividerClass}}\">\n `,\n\n html: `\n <div class=\"form-html {{fieldClass}}\">{{{html}}}</div>\n `,\n\n header: `\n <h{{level}} {{#id}}id=\"{{id}}\"{{/id}} class=\"text-primary mb-3 {{fieldClass}}\">{{text}}</h{{level}}>\n `,\n\n hidden: `\n <input type=\"hidden\" id=\"{{fieldId}}\" name=\"{{name}}\" value=\"{{fieldValue}}\">\n `,\n\n checklistdropdown: `\n <div class=\"dropdown\">\n <button class=\"{{buttonClass}}\" type=\"button\" data-bs-toggle=\"dropdown\">\n <i class=\"{{buttonIcon}} me-1\"></i> {{buttonText}}\n </button>\n <div class=\"{{dropdownClass}}\" style=\"min-width: {{minWidth}};\">\n {{#options}}\n <div class=\"form-check\">\n <input class=\"form-check-input\" type=\"checkbox\"\n value=\"{{value}}\"\n id=\"{{id}}\"\n {{#checked}}checked{{/checked}}\n data-change-action=\"update-checklist\"\n data-field=\"{{fieldName}}\">\n <label class=\"form-check-label\" for=\"{{id}}\">\n {{label}}\n </label>\n </div>\n {{/options}}\n <hr class=\"my-2\">\n <button class=\"btn btn-sm btn-primary w-100\" data-action=\"apply-filter\">\n Apply\n </button>\n </div>\n </div>\n `,\n\n buttongroup: `\n <div class=\"btn-group btn-group-{{size}}\" role=\"group\">\n {{#options}}\n <button type=\"button\" class=\"{{buttonClass}} {{#active}}active{{/active}}\"\n {{^action}}\n data-action=\"select-button-option\"\n {{/action}}\n {{#action}}\n data-action='{{action}}'\n {{/action}}\n data-field=\"{{fieldName}}\"\n data-value=\"{{value}}\">\n {{#icon}}<i class=\"{{icon}} me-1\"></i> {{/icon}} {{label}}\n </button>\n {{/options}}\n </div>\n `,\n\n toolbarform: `\n <div class=\"mojo-toolbar-form\">\n <div class=\"row g-2 align-items-center\">\n {{#fields}}\n <div class=\"{{containerClass}}\">\n {{#label}}<label class=\"form-label-sm mb-1\">{{label}}</label>{{/label}}\n {{{fieldHtml}}}\n </div>\n {{/fields}}\n </div>\n </div>\n `,\n\n color: `\n <div class=\"mojo-form-control\">\n {{#label}}\n <label for=\"{{fieldId}}\" class=\"{{labelClass}}\">\n {{label}}{{#required}}<span class=\"text-danger\">*</span>{{/required}}\n </label>\n {{/label}}\n <div class=\"d-flex align-items-center gap-2\">\n <input type=\"color\" id=\"{{fieldId}}\" name=\"{{name}}\"\n class=\"{{inputClass}}{{#error}} is-invalid{{/error}}\"\n value=\"{{fieldValue}}\"\n {{#required}}required{{/required}} {{#disabled}}disabled{{/disabled}}\n {{#readonly}}readonly{{/readonly}} {{{attrs}}}>\n <button type=\"button\" class=\"btn-sm text-muted border-0 bg-transparent p-1\"\n data-action=\"clear-color\" data-field=\"{{name}}\"\n title=\"Clear color\">\n <i class=\"bi bi-x fs-5\"></i>\n </button>\n </div>\n {{#help}}<div class=\"{{helpClass}}\">{{help}}</div>{{/help}}\n {{#error}}<div class=\"{{errorClass}}\">{{error}}</div>{{/error}}\n </div>\n `\n };\n }\n\n /**\n * Generate complete form HTML\n * @returns {string} Complete form HTML\n */\n buildFormHTML() {\n const fieldsHTML = this.buildFieldsHTML();\n const buttonsHTML = this.buildButtonsHTML();\n\n return `\n <form class=\"${this.options.formClass}\" novalidate>\n ${fieldsHTML}\n ${buttonsHTML}\n </form>\n `;\n }\n\n /**\n * Generate HTML for all fields\n * @returns {string} Fields HTML\n */\n /**\n * Check if field should use auto-sizing columns (class=\"col\")\n * @param {object} field - Field configuration\n * @returns {boolean}\n */\n isAutoSizingField(field) {\n return !field.columns || field.columns === 'auto' || field.columns === '';\n }\n\n buildFieldsHTML() {\n const result = [];\n let i = 0;\n\n while (i < this.fields.length) {\n const field = this.fields[i];\n field.columns = field.columns || field.cols;\n\n if (field.type === 'group') {\n // Collect consecutive groups that should be in a row\n const groupsInRow = [field];\n let totalColumns = field.columns || 12;\n\n // Handle responsive columns - use md breakpoint for calculation, fallback to largest available\n if (typeof totalColumns === 'object' && totalColumns !== null) {\n totalColumns = totalColumns.md || totalColumns.sm || totalColumns.xs || 12;\n }\n\n let j = i + 1;\n\n // Look ahead for more groups that can fit in the same row\n while (j < this.fields.length &&\n this.fields[j].type === 'group' &&\n totalColumns < 12) {\n const nextGroup = this.fields[j];\n let nextColumns = nextGroup.columns || 12;\n\n // Handle responsive columns - use md breakpoint for calculation, fallback to largest available\n if (typeof nextColumns === 'object' && nextColumns !== null) {\n nextColumns = nextColumns.md || nextColumns.sm || nextColumns.xs || 12;\n }\n\n if (totalColumns + nextColumns <= 12) {\n groupsInRow.push(nextGroup);\n totalColumns += nextColumns;\n j++;\n } else {\n break;\n }\n }\n\n // If we have multiple groups or a single group with specific columns, wrap in row\n let shouldWrap = groupsInRow.length > 1;\n\n // Check if single group has specific columns (not full width)\n if (groupsInRow.length === 1 && field.columns) {\n let cols = field.columns;\n if (typeof cols === 'object' && cols !== null) {\n cols = cols.md || cols.sm || cols.xs || 12;\n }\n shouldWrap = shouldWrap || cols < 12;\n }\n\n if (shouldWrap) {\n const groupsHTML = groupsInRow.map(group => this.buildGroupHTML(group)).join('');\n result.push(`<div class=\"row\">${groupsHTML}</div>`);\n } else {\n result.push(this.buildGroupHTML(field));\n }\n\n i = j;\n } else if (field.columns && field.columns < 12) {\n // Collect consecutive fields with columns that should be in a row\n const fieldsInRow = [field];\n let totalColumns = field.columns || 12;\n\n // Handle responsive columns - use md breakpoint for calculation, fallback to largest available\n if (typeof totalColumns === 'object' && totalColumns !== null) {\n totalColumns = totalColumns.md || totalColumns.sm || totalColumns.xs || 12;\n }\n\n let j = i + 1;\n\n // Look ahead for more fields that can fit in the same row\n while (j < this.fields.length &&\n this.fields[j].columns &&\n totalColumns < 12) {\n const nextField = this.fields[j];\n let nextColumns = nextField.columns || 12;\n\n // Handle responsive columns - use md breakpoint for calculation, fallback to largest available\n if (typeof nextColumns === 'object' && nextColumns !== null) {\n nextColumns = nextColumns.md || nextColumns.sm || nextColumns.xs || 12;\n }\n\n if (totalColumns + nextColumns <= 12) {\n fieldsInRow.push(nextField);\n totalColumns += nextColumns;\n j++;\n } else {\n break;\n }\n }\n\n // Wrap fields in a row\n const fieldsHTML = fieldsInRow.map(f => this.buildFieldHTML(f)).join('');\n result.push(`<div class=\"row\">${fieldsHTML}</div>`);\n\n i = j;\n } else if (this.isAutoSizingField(field)) {\n // Collect consecutive auto-sizing fields that should be in a row\n const fieldsInRow = [field];\n let j = i + 1;\n\n // Look ahead for more auto-sizing fields\n while (j < this.fields.length) {\n const nextField = this.fields[j];\n if (this.isAutoSizingField(nextField)) {\n fieldsInRow.push(nextField);\n j++;\n } else {\n break;\n }\n }\n\n // If we have multiple auto-sizing fields, wrap them in a row\n if (fieldsInRow.length > 1) {\n const fieldsHTML = fieldsInRow.map(f => this.buildFieldHTML(f)).join('');\n result.push(`<div class=\"row\">${fieldsHTML}</div>`);\n } else {\n // Single auto-sizing field, still wrap in row for consistency\n result.push(`<div class=\"row\">${this.buildFieldHTML(field)}</div>`);\n }\n\n i = j;\n } else {\n result.push(this.buildFieldHTML(field));\n i++;\n }\n }\n\n return result.join('');\n }\n\n /**\n * Generate HTML for a field group with column layout\n * @param {Object} group - Group configuration\n * @returns {string} Group HTML\n */\n buildGroupHTML(group) {\n const {\n columns = 12,\n title,\n fields = [],\n class: groupClass = '',\n titleClass = 'h6 mb-3',\n responsive = {}\n } = group;\n\n // Build responsive column classes\n let colClasses = [];\n\n // Handle columns as object (responsive) or number (legacy)\n if (typeof columns === 'object' && columns !== null) {\n // New responsive syntax: columns: { xs: 12, sm: 6, md: 4, lg: 3 }\n if (columns.xs) colClasses.push(`col-${columns.xs}`);\n if (columns.sm) colClasses.push(`col-sm-${columns.sm}`);\n if (columns.md) colClasses.push(`col-md-${columns.md}`);\n if (columns.lg) colClasses.push(`col-lg-${columns.lg}`);\n if (columns.xl) colClasses.push(`col-xl-${columns.xl}`);\n if (columns.xxl) colClasses.push(`col-xxl-${columns.xxl}`);\n\n // If no md is specified but xs/sm are, use xs or sm as fallback for md\n if (!columns.md && (columns.xs || columns.sm)) {\n const fallback = columns.sm || columns.xs;\n colClasses.push(`col-md-${fallback}`);\n }\n\n // If no breakpoints specified at all, default to col-md-12\n if (colClasses.length === 0) {\n colClasses.push('col-md-12');\n }\n } else {\n // Legacy syntax: columns: 6\n colClasses.push(`col-md-${columns}`);\n }\n\n // Support legacy responsive property (for backward compatibility)\n if (responsive.xs) colClasses.push(`col-${responsive.xs}`);\n if (responsive.sm) colClasses.push(`col-sm-${responsive.sm}`);\n if (responsive.lg) colClasses.push(`col-lg-${responsive.lg}`);\n if (responsive.xl) colClasses.push(`col-xl-${responsive.xl}`);\n\n const colClass = colClasses.join(' ');\n const fieldsHTML = fields.map(field => {\n if (field.type === 'group') {\n // Nested groups (limited depth)\n return this.buildGroupHTML(field);\n }\n return this.buildFieldHTML(field);\n }).join('');\n\n return `\n <div class=\"${colClass}\">\n <div class=\"mojo-form-group ${groupClass}\">\n ${title ? `<div class=\"${titleClass}\">${this.escapeHtml(title)}</div>` : ''}\n <div class=\"row\">\n ${fieldsHTML}\n </div>\n </div>\n </div>\n `;\n }\n\n /**\n * Generate HTML for a single field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n buildFieldHTML(field) {\n const { type, columns, class: fieldClass = '' } = field;\n\n let fieldHTML = '';\n // If a plugin registered a custom renderer for this field type, use it\n const customRenderer = (FormPlugins && typeof FormPlugins.getRenderer === 'function')\n ? FormPlugins.getRenderer(type)\n : null;\n if (typeof customRenderer === 'function') {\n try {\n const custom = customRenderer(this, field);\n if (custom !== undefined && custom !== null) {\n fieldHTML = String(custom);\n }\n } catch (err) {\n console.error('FormPlugins custom renderer error:', err);\n }\n }\n if (!fieldHTML) {\n console.log('buildFieldHTML - Processing field type:', type, 'for field:', field.name);\n switch (type) {\n case 'text':\n fieldHTML = this.renderTextField(field);\n break;\n case 'email':\n fieldHTML = this.renderEmailField(field);\n break;\n case 'password':\n fieldHTML = this.renderPasswordField(field);\n break;\n case 'number':\n fieldHTML = this.renderNumberField(field);\n break;\n case 'tel':\n fieldHTML = this.renderTelField(field);\n break;\n case 'url':\n fieldHTML = this.renderUrlField(field);\n break;\n case 'search':\n fieldHTML = this.renderSearchField(field);\n break;\n case 'hex':\n fieldHTML = this.renderHexField(field);\n break;\n case 'textarea':\n fieldHTML = this.renderTextareaField(field);\n break;\n case 'json':\n fieldHTML = this.renderJsonField(field);\n break;\n case 'select':\n fieldHTML = this.renderSelectField(field);\n break;\n case 'checkbox':\n fieldHTML = this.renderCheckboxField(field);\n break;\n case 'toggle':\n case 'switch':\n fieldHTML = this.renderSwitchField(field);\n break;\n case 'radio':\n fieldHTML = this.renderRadioField(field);\n break;\n case 'date':\n fieldHTML = this.renderDateField(field);\n break;\n case 'datetime':\n fieldHTML = this.renderDateTimeField(field);\n break;\n case 'time':\n fieldHTML = this.renderTimeField(field);\n break;\n case 'file':\n fieldHTML = this.renderFileField(field);\n break;\n case 'image':\n fieldHTML = this.renderImageField(field);\n break;\n case 'color':\n fieldHTML = this.renderColorField(field);\n break;\n case 'range':\n fieldHTML = this.renderRangeField(field);\n break;\n case 'hidden':\n fieldHTML = this.renderHiddenField(field);\n break;\n case 'button':\n fieldHTML = this.renderButton(field);\n break;\n case 'divider':\n fieldHTML = this.renderDivider(field);\n break;\n case 'html':\n fieldHTML = this.renderHtmlField(field);\n break;\n case 'heading':\n case 'header':\n fieldHTML = this.renderHeaderField(field);\n break;\n case 'tag':\n case 'tags':\n fieldHTML = this.renderTagField(field);\n break;\n case 'collection':\n fieldHTML = this.renderCollectionField(field);\n break;\n case 'collectionmultiselect':\n case 'collection-multiselect':\n fieldHTML = this.renderCollectionMultiSelectField(field);\n break;\n case 'datepicker':\n fieldHTML = this.renderDatePickerField(field);\n break;\n case 'daterange':\n fieldHTML = this.renderDateRangeField(field);\n break;\n case 'checklistdropdown':\n fieldHTML = this.renderChecklistDropdownField(field);\n break;\n case 'buttongroup':\n fieldHTML = this.renderButtonGroupField(field);\n break;\n case 'combo':\n case 'combobox':\n case 'autocomplete':\n fieldHTML = this.renderComboField(field);\n break;\n case 'tabset':\n fieldHTML = this.renderTabsetField(field);\n break;\n default:\n console.warn(`Unknown field type: ${type}`);\n fieldHTML = this.renderTextField(field);\n }\n }\n\n // Wrap field in column - handle auto-sizing columns\n let colClass;\n if (this.isAutoSizingField(field)) {\n colClass = `col ${fieldClass}`.trim();\n } else {\n colClass = `col-${columns} ${fieldClass}`.trim();\n }\n return `<div class=\"${colClass}\">${fieldHTML}</div>`;\n }\n\n /**\n * Generate field ID\n * @param {string} name - Field name\n * @returns {string} Unique field ID\n */\n getFieldId(name) {\n // Replace dots, spaces, and special characters with underscores for valid HTML IDs\n if (!name) {\n return `field_${Math.random().toString(36).substr(2, 9)}`;\n }\n const safeName = name.replace(/[.\\s\\[\\]]/g, '_');\n return `field_${safeName}`;\n }\n\n /**\n * Render text input field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderTextField(field) {\n return this.renderInputField(field, 'text');\n }\n\n /**\n * Render email input field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderEmailField(field) {\n return this.renderInputField(field, 'email');\n }\n\n /**\n * Render password input field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderPasswordField(field) {\n const passwordUsage = field.passwordUsage || 'current';\n const inferredAutocomplete =\n passwordUsage === 'new' || passwordUsage === 'new-password'\n ? 'new-password'\n : 'current-password';\n\n const attributes = {\n ...(field.attributes || {}),\n autocomplete: (field.attributes && field.attributes.autocomplete) || inferredAutocomplete\n };\n\n return this.renderInputField(\n {\n ...field,\n showToggle: field.showToggle !== false, // default to showing the toggle unless explicitly disabled\n attributes\n },\n 'password'\n );\n }\n\n /**\n * Render number input field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderNumberField(field) {\n const {\n min,\n max,\n step = 1,\n ...baseField\n } = field;\n\n const attrs = [];\n if (min !== undefined) attrs.push(`min=\"${min}\"`);\n if (max !== undefined) attrs.push(`max=\"${max}\"`);\n if (step !== undefined) attrs.push(`step=\"${step}\"`);\n\n return this.renderInputField({\n ...baseField,\n attributes: { ...baseField.attributes, ...attrs.reduce((obj, attr) => {\n const [key, value] = attr.split('=');\n obj[key] = value.replace(/\"/g, '');\n return obj;\n }, {}) }\n }, 'number');\n }\n\n /**\n * Render tel input field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderTelField(field) {\n return this.renderInputField(field, 'tel');\n }\n\n /**\n * Render URL input field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderUrlField(field) {\n return this.renderInputField(field, 'url');\n }\n\n /**\n * Render search input field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderSearchField(field) {\n const searchField = {\n ...field,\n attributes: {\n 'data-filter': 'live-search',\n 'data-change-action': 'filter-search',\n 'data-filter-debounce': field.debounce || '300',\n ...field.attributes\n }\n };\n return this.renderInputField(searchField, 'search');\n }\n\n /**\n * Render hex input field with validation\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderHexField(field) {\n const {\n hexType = 'color', // 'color', 'string', 'any'\n allowPrefix = true,\n minLength: originalMinLength,\n maxLength: originalMaxLength,\n ...baseField\n } = field;\n\n let pattern, minLength, maxLength, placeholder, help;\n\n switch (hexType) {\n case 'color':\n // Hex color: #RRGGBB or RRGGBB\n pattern = allowPrefix ? '^#?[0-9A-Fa-f]{6}$' : '^[0-9A-Fa-f]{6}$';\n minLength = allowPrefix ? 6 : 6;\n maxLength = allowPrefix ? 7 : 6;\n placeholder = allowPrefix ? '#FF0000' : 'FF0000';\n help = help || 'Enter a valid hex color (e.g., ' + placeholder + ')';\n break;\n\n case 'color-short':\n // Hex color: #RGB or RGB, #RRGGBB or RRGGBB\n pattern = allowPrefix ? '^#?[0-9A-Fa-f]{3}([0-9A-Fa-f]{3})?$' : '^[0-9A-Fa-f]{3}([0-9A-Fa-f]{3})?$';\n minLength = allowPrefix ? 4 : 3;\n maxLength = allowPrefix ? 7 : 6;\n placeholder = allowPrefix ? '#F00 or #FF0000' : 'F00 or FF0000';\n help = help || 'Enter a valid hex color (3 or 6 digits)';\n break;\n\n case 'string':\n // General hex string\n pattern = '^[0-9A-Fa-f]+$';\n minLength = originalMinLength || 1;\n maxLength = originalMaxLength || 64;\n placeholder = 'ABCDEF123456';\n help = help || 'Only hexadecimal characters (0-9, A-F) allowed';\n break;\n\n default:\n // Any hex format\n pattern = allowPrefix ? '^#?[0-9A-Fa-f]+$' : '^[0-9A-Fa-f]+$';\n minLength = originalMinLength || 1;\n maxLength = originalMaxLength || 64;\n placeholder = allowPrefix ? '#ABCDEF or ABCDEF' : 'ABCDEF';\n help = help || 'Enter hexadecimal characters only';\n }\n\n const hexField = {\n ...baseField,\n pattern,\n minLength,\n maxLength,\n placeholder: baseField.placeholder || placeholder,\n help: baseField.help || help,\n attributes: {\n 'data-hex-type': hexType,\n 'data-allow-prefix': allowPrefix,\n 'style': 'text-transform: uppercase;',\n ...baseField.attributes\n }\n };\n\n return this.renderInputField(hexField, 'text');\n }\n\n /**\n * Render generic input field\n * @param {Object} field - Field configuration\n * @param {string} type - Input type\n * @returns {string} Field HTML\n */\n renderInputField(field, type = 'text') {\n const {\n name,\n label,\n value = '',\n placeholder = '',\n required = false,\n disabled = false,\n readonly = false,\n class: fieldClass = '',\n attributes = {},\n help = field.helpText || field.help || ''\n } = field;\n\n const inputClass = `${this.options.inputClass} ${fieldClass}`.trim();\n const error = this.errors[name];\n const fieldValue = (this.getFieldValue(name) ?? value);\n\n const attrs = Object.entries(attributes).map(([key, val]) => `${key}=\"${this.escapeHtml(val)}\"`).join(' ');\n const fieldId = this.getFieldId(name);\n\n const context = {\n labelClass: this.options.labelClass,\n inputClass: inputClass,\n helpClass: this.options.helpClass,\n errorClass: this.options.errorClass,\n fieldId,\n name,\n type,\n fieldValue: this.escapeHtml(fieldValue),\n label: label ? this.escapeHtml(label) : null,\n placeholder: placeholder ? this.escapeHtml(placeholder) : null,\n help: help ? this.escapeHtml(help) : null,\n error: error ? this.escapeHtml(error) : null,\n required,\n disabled,\n readonly,\n attrs\n };\n\n if (type === 'password' && (field.showToggle || field.strengthMeter || field.capsLockWarning)) {\n const enhancedContext = {\n ...context,\n showToggle: !!field.showToggle,\n strengthMeter: !!field.strengthMeter,\n capsLockWarning: !!field.capsLockWarning\n };\n return Mustache.render(this.templates.password, enhancedContext);\n }\n if (type === 'password') {\n const enhancedContext = {\n ...context,\n showToggle: field.showToggle !== false,\n strengthMeter: !!field.strengthMeter,\n capsLockWarning: !!field.capsLockWarning\n };\n return Mustache.render(this.templates.password, enhancedContext);\n }\n return Mustache.render(this.templates.input, context);\n }\n\n /**\n * Render textarea field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderTextareaField(field) {\n const {\n name,\n label,\n value = '',\n placeholder = '',\n required = false,\n disabled = false,\n readonly = false,\n rows = 3,\n cols: _cols,\n class: fieldClass = '',\n attributes = {},\n help = field.helpText || field.help || ''\n } = field;\n\n const inputClass = `${this.options.inputClass} ${fieldClass}`.trim();\n const error = this.errors[name];\n const fieldValue = (this.getFieldValue(name) ?? value);\n\n const attrs = Object.entries(attributes).map(([key, val]) => `${key}=\"${this.escapeHtml(val)}\"`).join(' ');\n const fieldId = this.getFieldId(name);\n\n const context = {\n labelClass: this.options.labelClass,\n inputClass: inputClass,\n helpClass: this.options.helpClass,\n errorClass: this.options.errorClass,\n fieldId,\n name,\n fieldValue: fieldValue, // Pass raw value to template for correct rendering\n label: label ? this.escapeHtml(label) : null,\n placeholder: placeholder ? this.escapeHtml(placeholder) : null,\n help: help ? this.escapeHtml(help) : null,\n error: error ? this.escapeHtml(error) : null,\n rows: rows || 3,\n required,\n disabled,\n readonly,\n attrs\n };\n\n return Mustache.render(this.templates.textarea, context);\n }\n\n /**\n * Render JSON field as a textarea\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderJsonField(field) {\n const {\n name,\n label,\n placeholder = '',\n required = false,\n disabled = false,\n readonly = false,\n rows = 3,\n class: fieldClass = '',\n attributes = {},\n help = field.helpText || field.help || ''\n } = field;\n\n const rawValue = this.getFieldValue(field.name) ?? field.value ?? {};\n let formattedValue = rawValue;\n\n if (typeof rawValue === 'object' && rawValue !== null) {\n try {\n formattedValue = JSON.stringify(rawValue, null, 2);\n } catch (e) {\n formattedValue = \"{}\";\n }\n } else if (typeof rawValue !== 'string') {\n formattedValue = String(rawValue);\n }\n\n const inputClass = `${this.options.inputClass} ${fieldClass}`.trim();\n const error = this.errors[name];\n const fieldId = this.getFieldId(name);\n\n const attrs = Object.entries({\n ...attributes,\n 'data-field-type': 'json'\n }).map(([key, val]) => `${key}=\"${this.escapeHtml(val)}\"`).join(' ');\n\n const context = {\n labelClass: this.options.labelClass,\n inputClass: inputClass,\n helpClass: this.options.helpClass,\n errorClass: this.options.errorClass,\n fieldId,\n name,\n fieldValue: formattedValue, // Use the formatted JSON string directly\n label: label ? this.escapeHtml(label) : null,\n placeholder: placeholder ? this.escapeHtml(placeholder) : null,\n help: help ? this.escapeHtml(help) : null,\n error: error ? this.escapeHtml(error) : null,\n rows: rows || 3,\n required,\n disabled,\n readonly,\n attrs\n };\n\n return Mustache.render(this.templates.textarea, context);\n }\n\n\n\n /**\n * Render select field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderSelectField(field) {\n const {\n name,\n label,\n options = [],\n value = '',\n required = false,\n disabled = false,\n multiple = false,\n searchable = false,\n class: fieldClass = '',\n attributes = {},\n help = field.helpText || field.help || '',\n // Auto-generation parameters\n start = field.start,\n end = field.end,\n step = field.step,\n format = field.format,\n prefix = field.prefix,\n suffix = field.suffix\n } = field;\n\n const inputClass = `form-select ${fieldClass}`.trim();\n const error = this.errors[name];\n const dataValue = this.getFieldValue(name);\n const fieldValue = (dataValue ?? value);\n\n const attrs = Object.entries(attributes).map(([key, val]) => `${key}=\"${this.escapeHtml(val)}\"`).join(' ');\n const fieldId = this.getFieldId(name);\n\n // Generate options automatically if start/end are provided\n let generatedOptions = [...options];\n if (start !== undefined && end !== undefined) {\n const stepValue = step !== undefined ? step : 1;\n const autoOptions = this.generateSelectOptions(start, end, stepValue, { format, prefix, suffix });\n // Append auto-generated options after any manually specified ones\n generatedOptions = [...generatedOptions, ...autoOptions];\n }\n\n let optionsHTML = '';\n if (Array.isArray(generatedOptions)) {\n optionsHTML = generatedOptions.map(option => {\n if (typeof option === 'string') {\n const selected = option === fieldValue ? 'selected' : '';\n return `<option value=\"${this.escapeHtml(option)}\" ${selected}>${this.escapeHtml(option)}</option>`;\n } else if (option && typeof option === 'object') {\n // Use loose equality (==) to handle string/number type coercion\n const selected = option.value == fieldValue ? 'selected' : '';\n return `<option value=\"${this.escapeHtml(option.value)}\" ${selected}>${this.escapeHtml(option.label || option.text || option.value)}</option>`;\n }\n return '';\n }).join('');\n }\n\n const searchInput = searchable ? `\n <input type=\"text\"\n class=\"form-control form-control-sm mb-2\"\n placeholder=\"Search options...\"\n data-filter=\"live-search\"\n data-change-action=\"filter-select-options\"\n data-target=\"${fieldId}\">\n ` : '';\n\n const context = {\n labelClass: this.options.labelClass,\n inputClass: inputClass,\n helpClass: this.options.helpClass,\n errorClass: this.options.errorClass,\n fieldId,\n name,\n label: label ? this.escapeHtml(label) : null,\n help: help ? this.escapeHtml(help) : null,\n error: error ? this.escapeHtml(error) : null,\n searchInput: searchable ? searchInput : null,\n optionsHTML,\n required,\n disabled,\n multiple,\n attrs\n };\n\n return Mustache.render(this.templates.select, context);\n }\n\n /**\n * Render checkbox field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderCheckboxField(field) {\n const {\n name,\n label,\n value = false,\n required = false,\n disabled = false,\n class: fieldClass = '',\n attributes = {},\n help = field.helpText || field.help || ''\n } = field;\n\n const error = this.errors[name];\n const fieldValue = (this.getFieldValue(name) ?? value);\n const checked = fieldValue === true || fieldValue === 'true' || fieldValue === '1';\n\n const attrs = Object.entries(attributes).map(([key, val]) => `${key}=\"${this.escapeHtml(val)}\"`).join(' ');\n const fieldId = this.getFieldId(name);\n\n const context = {\n helpClass: this.options.helpClass,\n errorClass: this.options.errorClass,\n fieldId,\n name,\n label: this.escapeHtml(label),\n help: help ? this.escapeHtml(help) : null,\n error: error ? this.escapeHtml(error) : null,\n value: this.escapeHtml(value),\n fieldClass,\n checked,\n required,\n disabled,\n attrs\n };\n\n return Mustache.render(this.templates.checkbox, context);\n }\n\n /**\n * Render switch field (enhanced checkbox)\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderSwitchField(field) {\n const {\n name,\n label,\n value = false,\n required = false,\n disabled = false,\n size = 'md',\n class: fieldClass = '',\n attributes = {},\n help = field.helpText || field.help || ''\n } = field;\n\n const error = this.errors[name];\n const fieldValue = (this.getFieldValue(name) ?? value);\n const checked = fieldValue === true || fieldValue === 'true' || fieldValue === '1';\n\n const attrs = Object.entries(attributes).map(([key, val]) => `${key}=\"${this.escapeHtml(val)}\"`).join(' ');\n const fieldId = this.getFieldId(name);\n const sizeClass = size !== 'md' ? `form-switch-${size}` : '';\n\n const context = {\n helpClass: this.options.helpClass,\n errorClass: this.options.errorClass,\n fieldId,\n name,\n label: this.escapeHtml(label),\n help: help ? this.escapeHtml(help) : null,\n error: error ? this.escapeHtml(error) : null,\n value: this.escapeHtml(value),\n sizeClass,\n fieldClass,\n checked,\n required,\n disabled,\n attrs\n };\n\n return Mustache.render(this.templates.switch, context);\n }\n\n /**\n * Render radio field group\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderRadioField(field) {\n const {\n name,\n label,\n options = [],\n value = '',\n disabled = false,\n inline = false,\n class: fieldClass = '',\n attributes = {},\n help = field.helpText || field.help || ''\n } = field;\n\n const error = this.errors[name];\n const fieldValue = (this.getFieldValue(name) ?? value);\n\n const attrs = Object.entries(attributes).map(([key, val]) => `${key}=\"${this.escapeHtml(val)}\"`).join(' ');\n\n let optionsHTML = '';\n if (Array.isArray(options)) {\n optionsHTML = options.map((option, index) => {\n const radioId = `${name}_${index}`;\n const radioValue = typeof option === 'string' ? option : option.value;\n const radioLabel = typeof option === 'string' ? option : option.label || option.text || option.value;\n const checked = radioValue === fieldValue ? 'checked' : '';\n const inlineClass = inline ? 'form-check-inline' : '';\n\n return `\n <div class=\"form-check ${inlineClass}\">\n <input\n type=\"radio\"\n id=\"${radioId}\"\n name=\"${name}\"\n class=\"form-check-input ${error ? 'is-invalid' : ''}\"\n value=\"${this.escapeHtml(radioValue)}\"\n ${checked}\n ${disabled ? 'disabled' : ''}\n\n ${attrs}\n >\n <label class=\"form-check-label\" for=\"${radioId}\">\n ${this.escapeHtml(radioLabel)}\n </label>\n </div>\n `;\n }).join('');\n }\n\n return `\n <div class=\"mojo-form-control\">\n ${label ? `<fieldset>\n <legend class=\"${this.options.labelClass}\">${this.escapeHtml(label)}</legend>\n <div class=\"${fieldClass}\">\n ${optionsHTML}\n </div>\n </fieldset>` : `<div class=\"${fieldClass}\">${optionsHTML}</div>`}\n ${help ? `<div class=\"${this.options.helpClass}\">${this.escapeHtml(help)}</div>` : ''}\n ${error ? `<div class=\"${this.options.errorClass}\">${this.escapeHtml(error)}</div>` : ''}\n </div>\n `;\n }\n\n /**\n * Render date field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderDateField(field) {\n return this.renderInputField(field, 'date');\n }\n\n /**\n * Render datetime field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderDateTimeField(field) {\n return this.renderInputField(field, 'datetime-local');\n }\n\n /**\n * Render time field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderTimeField(field) {\n return this.renderInputField(field, 'time');\n }\n\n /**\n * Render file field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderFileField(field) {\n const {\n name,\n label,\n required = false,\n disabled = false,\n multiple = false,\n accept = '*/*',\n class: fieldClass = '',\n attributes = {},\n help = field.helpText || field.help || ''\n } = field;\n\n const inputClass = `${this.options.inputClass} ${fieldClass}`.trim();\n const error = this.errors[name];\n\n const attrs = Object.entries(attributes).map(([key, val]) => `${key}=\"${this.escapeHtml(val)}\"`).join(' ');\n const fieldId = this.getFieldId(name);\n\n const context = {\n labelClass: this.options.labelClass,\n inputClass: inputClass,\n helpClass: this.options.helpClass,\n errorClass: this.options.errorClass,\n fieldId,\n name,\n label: label ? this.escapeHtml(label) : null,\n help: help ? this.escapeHtml(help) : null,\n error: error ? this.escapeHtml(error) : null,\n accept,\n required,\n disabled,\n multiple,\n attrs\n };\n\n return Mustache.render(this.templates.file, context);\n }\n\n /**\n * Render enhanced image field with drag & drop support\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderImageField(field) {\n const {\n name,\n label,\n required = false,\n disabled = false,\n accept = 'image/*',\n class: fieldClass = '',\n attributes = {},\n help = field.helpText || field.help || '',\n size = 'md',\n allowDrop = true,\n placeholder = 'Drop image here or click to upload'\n } = field;\n\n const inputClass = `${this.options.inputClass} ${fieldClass}`.trim();\n const error = this.errors[name];\n const fieldId = this.getFieldId(name);\n const dropZoneId = `${fieldId}_dropzone`;\n const previewId = `${fieldId}_preview`;\n\n // Size configurations\n const sizeMap = {\n xs: { width: 48, height: 48, containerClass: 'image-field-xs' },\n sm: { width: 96, height: 96, containerClass: 'image-field-sm' },\n md: { width: 150, height: 150, containerClass: 'image-field-md' },\n lg: { width: 200, height: 200, containerClass: 'image-field-lg' },\n xl: { width: 300, height: 300, containerClass: 'image-field-xl' }\n };\n\n const sizeConfig = sizeMap[size] || sizeMap.md;\n const attrs = Object.entries(attributes).map(([key, val]) => `${key}=\"${this.escapeHtml(val)}\"`).join(' ');\n\n // Get current value (could be URL string or file object)\n const currentValue = this.getFieldValue(name);\n const imageUrl = this.extractImageUrl(currentValue, size);\n\n const context = {\n labelClass: this.options.labelClass,\n inputClass: inputClass,\n helpClass: this.options.helpClass,\n errorClass: this.options.errorClass,\n fieldId,\n name,\n label: label ? this.escapeHtml(label) : null,\n help: help ? this.escapeHtml(help) : null,\n error: error ? this.escapeHtml(error) : null,\n dropZoneId,\n previewId,\n containerClass: sizeConfig.containerClass,\n width: sizeConfig.width,\n height: sizeConfig.height,\n accept,\n imageUrl,\n placeholderText: disabled ? 'No image' : this.escapeHtml(placeholder),\n cursor: disabled ? 'default' : 'pointer',\n allowDrop,\n showRemove: !disabled,\n required,\n disabled,\n attrs\n };\n\n return Mustache.render(this.templates.image, context);\n }\n\n /**\n * Extract image URL from field value (handles both URL strings and file objects)\n * @param {string|Object} value - Field value\n * @param {string} size - Requested size (xs, sm, md, lg, xl)\n * @returns {string|null} Image URL or null\n */\n extractImageUrl(value, size = 'md') {\n if (!value) return null;\n\n // If it's already a URL string\n if (typeof value === 'string') {\n return value;\n }\n\n // If it's a file object with renditions\n if (typeof value === 'object' && value.url) {\n // Try to get appropriate rendition based on size\n if (value.renditions) {\n const sizeMap = {\n xs: ['thumbnail_sm', 'thumbnail', 'square_sm'],\n sm: ['thumbnail', 'thumbnail_sm', 'square_sm'],\n md: ['thumbnail_md', 'thumbnail', 'thumbnail_lg'],\n lg: ['thumbnail_lg', 'thumbnail_md', 'thumbnail'],\n xl: ['original', 'thumbnail_lg']\n };\n\n const preferredSizes = sizeMap[size] || sizeMap.md;\n\n for (const renditionName of preferredSizes) {\n if (value.renditions[renditionName] && value.renditions[renditionName].url) {\n return value.renditions[renditionName].url;\n }\n }\n }\n\n // Fall back to original URL\n return value.url;\n }\n\n return null;\n }\n\n /**\n * Render color field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderColorField(field) {\n const {\n name,\n label,\n value = '',\n placeholder = '',\n required = false,\n disabled = false,\n readonly = false,\n class: fieldClass = '',\n attributes = {},\n help = field.helpText || field.help || ''\n } = field;\n\n const inputClass = `${this.options.inputClass} ${fieldClass}`.trim();\n const error = this.errors[name];\n const fieldValue = (this.getFieldValue(name) ?? value);\n\n const attrs = Object.entries(attributes).map(([key, val]) => `${key}=\"${this.escapeHtml(val)}\"`).join(' ');\n const fieldId = this.getFieldId(name);\n\n const context = {\n labelClass: this.options.labelClass,\n inputClass: inputClass,\n helpClass: this.options.helpClass,\n errorClass: this.options.errorClass,\n fieldId,\n name,\n fieldValue: this.escapeHtml(fieldValue),\n label: label ? this.escapeHtml(label) : null,\n placeholder: placeholder ? this.escapeHtml(placeholder) : null,\n help: help ? this.escapeHtml(help) : null,\n error: error ? this.escapeHtml(error) : null,\n required,\n disabled,\n readonly,\n attrs\n };\n\n return Mustache.render(this.templates.color, context);\n }\n\n /**\n * Render range field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderRangeField(field) {\n const {\n name,\n label,\n min = 0,\n max = 100,\n step = 1,\n value = min,\n disabled = false,\n class: fieldClass = '',\n attributes = {},\n help = field.helpText || field.help || ''\n } = field;\n\n const inputClass = `${this.options.inputClass} ${fieldClass}`.trim();\n const error = this.errors[name];\n const fieldValue = (this.getFieldValue(name) ?? value);\n\n const attrs = Object.entries(attributes).map(([key, val]) => `${key}=\"${this.escapeHtml(val)}\"`).join(' ');\n const fieldId = this.getFieldId(name);\n\n const context = {\n labelClass: this.options.labelClass,\n inputClass: inputClass,\n helpClass: this.options.helpClass,\n errorClass: this.options.errorClass,\n fieldId,\n name,\n label: label ? this.escapeHtml(label) : null,\n help: help ? this.escapeHtml(help) : null,\n error: error ? this.escapeHtml(error) : null,\n min,\n max,\n step,\n fieldValue,\n disabled,\n attrs\n };\n\n return Mustache.render(this.templates.range, context);\n }\n\n /**\n * Render hidden field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderHiddenField(field) {\n const { name, value = '' } = field;\n const fieldValue = (this.getFieldValue(name) ?? value);\n\n return `<input type=\"hidden\" name=\"${name}\" value=\"${this.escapeHtml(fieldValue)}\">`;\n }\n\n /**\n * Render button field\n * @param {Object} field - Field configuration\n * @returns {string} Button HTML\n */\n renderButton(field) {\n const {\n name = '',\n label = 'Button',\n type = 'button',\n action = '',\n class: fieldClass = 'btn-secondary',\n disabled = false,\n attributes = {}\n } = field;\n\n // Auto-assign actions for submit/reset types\n let buttonAction = action;\n if (!buttonAction) {\n if (type === 'submit') {\n buttonAction = 'submit-form';\n } else if (type === 'reset') {\n buttonAction = 'reset-form';\n }\n }\n\n const attrs = Object.entries(attributes).map(([key, val]) => `${key}=\"${this.escapeHtml(val)}\"`).join(' ');\n\n return `\n <button\n type=\"button\"\n ${name ? `name=\"${name}\"` : ''}\n class=\"btn ${fieldClass}\"\n ${buttonAction ? `data-action=\"${buttonAction}\"` : ''}\n ${disabled ? 'disabled' : ''}\n ${attrs}\n >\n ${this.escapeHtml(label)}\n </button>\n `;\n }\n\n /**\n * Render divider field\n * @param {Object} field - Field configuration\n * @returns {string} Divider HTML\n */\n renderDivider(field) {\n const { label = '', class: fieldClass = '' } = field;\n\n return `\n <div class=\"form-divider ${fieldClass}\">\n <hr>\n ${label ? `<div class=\"form-divider-label\">${this.escapeHtml(label)}</div>` : ''}\n </div>\n `;\n }\n\n /**\n * Render HTML field\n * @param {Object} field - Field configuration\n * @returns {string} HTML content\n */\n renderHtmlField(field) {\n const { html = '', class: fieldClass = '' } = field;\n\n return `\n <div class=\"form-html ${fieldClass}\">\n ${html}\n </div>\n `;\n }\n\n /**\n * Render header field\n * @param {Object} field - Field configuration\n * @returns {string} Header HTML\n */\n renderHeaderField(field) {\n const {\n text = '',\n level = 3,\n class: fieldClass = '',\n id = ''\n } = field;\n\n const headerLevel = Math.max(1, Math.min(6, parseInt(level)));\n const headerId = id ? ` id=\"${this.escapeHtml(id)}\"` : '';\n const headerClass = fieldClass ? ` class=\"${this.escapeHtml(fieldClass)}\"` : '';\n\n return `<h${headerLevel}${headerId}${headerClass}>${this.escapeHtml(text)}</h${headerLevel}>`;\n }\n\n /**\n * Generate buttons HTML\n * @returns {string} Buttons HTML\n */\n buildButtonsHTML() {\n if (!this.options.submitButton && !this.options.resetButton && !this.buttons.length) {\n return '';\n }\n\n let buttonsHTML = '';\n\n // Custom buttons\n this.buttons.forEach(button => {\n buttonsHTML += this.renderButton(button) + ' ';\n });\n\n // Default submit button\n if (this.options.submitButton) {\n let submitLabel = 'Submit';\n if (typeof this.options.submitButton === 'string') {\n submitLabel = this.options.submitButton;\n } else if (this.options.submitButton === true) {\n submitLabel = 'Submit';\n }\n buttonsHTML += `<button type=\"submit\" class=\"btn btn-primary me-2\" data-action=\"submit-form\">${submitLabel}</button>`;\n }\n\n // Default reset button\n if (this.options.resetButton) {\n let resetLabel = 'Reset';\n if (typeof this.options.resetButton === 'string') {\n resetLabel = this.options.resetButton;\n } else if (this.options.resetButton === true) {\n resetLabel = 'Reset';\n }\n buttonsHTML += `<button type=\"button\" class=\"btn btn-secondary\" data-action=\"reset-form\">${resetLabel}</button>`;\n }\n\n return buttonsHTML ? `\n <div class=\"form-actions mt-3\">\n ${buttonsHTML}\n </div>\n ` : '';\n }\n\n /**\n * Get field value from data\n * @param {string} name - Field name\n * @returns {*} Field value\n */\n getFieldValue(name) {\n // If in structure-only mode, return empty value\n if (this.structureOnly) {\n return '';\n }\n const value = MOJOUtils.getContextData(this.data, name);\n return value;\n }\n\n /**\n * Render tag input field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderTagField(field) {\n const {\n name,\n label,\n value = '',\n placeholder = 'Add tags...',\n required = false,\n disabled = false,\n readonly = false,\n maxTags = 50,\n allowDuplicates = false,\n separator = ',',\n help = field.helpText || field.help || ''\n } = field;\n\n const fieldId = this.getFieldId(name);\n const error = this.errors[name];\n const fieldValue = (this.getFieldValue(name) ?? value);\n\n return `\n <div class=\"mojo-form-control\">\n ${label ? `<label for=\"${fieldId}\" class=\"${this.options.labelClass}\">${this.escapeHtml(label)}${required ? '<span class=\"text-danger\">*</span>' : ''}</label>` : ''}\n <div class=\"tag-input-placeholder\"\n data-field-name=\"${name}\"\n data-field-type=\"tag\"\n data-field-config='${JSON.stringify({\n name,\n value: fieldValue,\n placeholder,\n maxTags,\n allowDuplicates,\n separator,\n disabled,\n readonly,\n required\n })}'>\n <input type=\"text\"\n id=\"${fieldId}\"\n name=\"${name}_display\"\n class=\"${this.options.inputClass}${error ? ' is-invalid' : ''}\"\n placeholder=\"${this.escapeHtml(placeholder)}\"\n ${disabled ? 'disabled' : ''}\n ${readonly ? 'readonly' : ''}\n\n <input type=\"hidden\" name=\"${name}\" value=\"${this.escapeHtml(fieldValue)}\">\n <small class=\"form-text text-muted\">This will be enhanced with TagInput component</small>\n </div>\n ${help ? `<div class=\"${this.options.helpClass}\">${this.escapeHtml(help)}</div>` : ''}\n ${error ? `<div class=\"${this.options.errorClass}\">${this.escapeHtml(error)}</div>` : ''}\n </div>\n `;\n }\n\n /**\n * Render collection select field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderCollectionField(field) {\n const {\n name,\n label,\n value = '',\n placeholder = 'Search...',\n required = false,\n disabled = false,\n readonly = false,\n Collection: _Collection,\n labelField = 'name',\n valueField = 'id',\n maxItems = 10,\n emptyFetch = false,\n debounceMs = 300,\n requiresActiveGroup = false,\n help = field.helpText || field.help || ''\n } = field;\n\n const fieldId = this.getFieldId(name);\n const error = this.errors[name];\n const fieldValue = (this.getFieldValue(name) ?? value);\n\n return `\n <div class=\"mojo-form-control\">\n ${label ? `<label for=\"${fieldId}\" class=\"${this.options.labelClass}\">${this.escapeHtml(label)}${required ? '<span class=\"text-danger\">*</span>' : ''}</label>` : ''}\n <div class=\"collection-select-placeholder\"\n data-field-name=\"${name}\"\n data-field-type=\"collection\"\n data-field-config='${JSON.stringify({\n name,\n value: fieldValue,\n placeholder,\n labelField,\n valueField,\n maxItems,\n emptyFetch,\n debounceMs,\n disabled,\n readonly,\n required,\n requiresActiveGroup\n })}'>\n <input type=\"text\"\n id=\"${fieldId}\"\n name=\"${name}_display\"\n class=\"${this.options.inputClass}${error ? ' is-invalid' : ''}\"\n placeholder=\"${this.escapeHtml(placeholder)}\"\n ${disabled ? 'disabled' : ''}\n ${readonly ? 'readonly' : ''}\n\n <input type=\"hidden\" name=\"${name}\" value=\"${this.escapeHtml(fieldValue)}\">\n <small class=\"form-text text-muted\">This will be enhanced with CollectionSelect component</small>\n </div>\n ${help ? `<div class=\"${this.options.helpClass}\">${this.escapeHtml(help)}</div>` : ''}\n ${error ? `<div class=\"${this.options.errorClass}\">${this.escapeHtml(error)}</div>` : ''}\n </div>\n `;\n }\n\n /**\n * Render collection multiselect field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderCollectionMultiSelectField(field) {\n const {\n name,\n label,\n value = [],\n required = false,\n disabled = false,\n Collection: _Collection,\n collectionParams = {},\n labelField = 'name',\n valueField = 'id',\n excludeIds = [],\n ignoreIds = [],\n size = 8,\n maxHeight = null,\n showSelectAll = true,\n enableSearch = false,\n searchPlaceholder = 'Search...',\n searchDebounce = 400,\n requiresActiveGroup = false,\n help = field.helpText || field.help || ''\n } = field;\n\n const fieldId = this.getFieldId(name);\n const error = this.errors[name];\n const fieldValue = this.getFieldValue(name) ?? value;\n\n return `\n <div class=\"mojo-form-control\">\n ${label ? `<label class=\"${this.options.labelClass}\">${this.escapeHtml(label)}${required ? '<span class=\"text-danger\">*</span>' : ''}</label>` : ''}\n <div class=\"collection-multiselect-placeholder\"\n data-field-name=\"${name}\"\n data-field-type=\"collectionmultiselect\"\n data-field-config='${JSON.stringify({\n name,\n value: fieldValue,\n labelField,\n valueField,\n excludeIds,\n ignoreIds,\n size,\n maxHeight,\n showSelectAll,\n enableSearch,\n searchPlaceholder,\n searchDebounce,\n disabled,\n required,\n requiresActiveGroup\n })}'>\n <input type=\"hidden\" name=\"${name}\" value=\"${this.escapeHtml(JSON.stringify(fieldValue))}\">\n <small class=\"form-text text-muted\">This will be enhanced with CollectionMultiSelect component</small>\n </div>\n ${help ? `<div class=\"${this.options.helpClass}\">${this.escapeHtml(help)}</div>` : ''}\n ${error ? `<div class=\"${this.options.errorClass}\">${this.escapeHtml(error)}</div>` : ''}\n </div>\n `;\n }\n\n /**\n * Render enhanced date picker field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderDatePickerField(field) {\n const {\n name,\n label,\n value = '',\n placeholder = 'Select date...',\n required = false,\n disabled = false,\n readonly = false,\n min = null,\n max = null,\n format = 'YYYY-MM-DD',\n displayFormat = 'MMM DD, YYYY',\n help = field.helpText || field.help || ''\n } = field;\n\n const fieldId = this.getFieldId(name);\n const error = this.errors[name];\n const fieldValue = (this.getFieldValue(name) ?? value);\n\n return `\n <div class=\"mojo-form-control\">\n ${label ? `<label for=\"${fieldId}\" class=\"${this.options.labelClass}\">${this.escapeHtml(label)}${required ? '<span class=\"text-danger\">*</span>' : ''}</label>` : ''}\n <div class=\"date-picker-placeholder\"\n data-field-name=\"${name}\"\n data-field-type=\"datepicker\"\n data-field-config='${JSON.stringify({\n name,\n value: fieldValue,\n placeholder,\n min,\n max,\n format,\n displayFormat,\n disabled,\n readonly,\n required\n })}'>\n <input type=\"date\"\n id=\"${fieldId}\"\n name=\"${name}\"\n class=\"${this.options.inputClass}${error ? ' is-invalid' : ''}\"\n value=\"${this.escapeHtml(fieldValue)}\"\n placeholder=\"${this.escapeHtml(placeholder)}\"\n ${min ? `min=\"${min}\"` : ''}\n ${max ? `max=\"${max}\"` : ''}\n ${disabled ? 'disabled' : ''}\n ${readonly ? 'readonly' : ''}\n ${required ? 'required' : ''}\n\n <small class=\"form-text text-muted\">This will be enhanced with Easepick DatePicker</small>\n </div>\n ${help ? `<div class=\"${this.options.helpClass}\">${this.escapeHtml(help)}</div>` : ''}\n ${error ? `<div class=\"${this.options.errorClass}\">${this.escapeHtml(error)}</div>` : ''}\n </div>\n `;\n }\n\n /**\n * Render date range picker field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderDateRangeField(field) {\n const {\n name,\n startName,\n endName,\n fieldName,\n label,\n startDate = '',\n endDate = '',\n placeholder = 'Select date range...',\n required = false,\n disabled = false,\n readonly = false,\n min = null,\n max = null,\n format = 'YYYY-MM-DD',\n displayFormat = 'MMM DD, YYYY',\n outputFormat = 'date',\n separator = ' - ',\n help = field.helpText || field.help || ''\n } = field;\n\n const fieldId = this.getFieldId(name || startName || 'daterange');\n const error = this.errors[name];\n const startFieldName = startName || (name ? name + '_start' : '');\n const endFieldName = endName || (name ? name + '_end' : '');\n const startValue = this.getFieldValue(startFieldName) || startDate;\n const endValue = this.getFieldValue(endFieldName) || endDate;\n\n return `\n <div class=\"mojo-form-control\">\n ${label ? `<label for=\"${fieldId}\" class=\"${this.options.labelClass}\">${this.escapeHtml(label)}${required ? '<span class=\"text-danger\">*</span>' : ''}</label>` : ''}\n <div class=\"date-range-picker-placeholder\"\n data-field-name=\"${name || startName || 'daterange'}\"\n data-field-type=\"daterange\"\n data-field-config='${JSON.stringify({\n name,\n startName,\n endName,\n fieldName,\n startDate: startValue,\n endDate: endValue,\n placeholder,\n min,\n max,\n format,\n displayFormat,\n outputFormat,\n separator,\n disabled,\n readonly,\n required\n })}'>\n <div class=\"row g-2\">\n <div class=\"col\">\n <input type=\"date\"\n id=\"${fieldId}_start\"\n name=\"${name}_start\"\n class=\"${this.options.inputClass}${error ? ' is-invalid' : ''}\"\n value=\"${this.escapeHtml(startValue)}\"\n placeholder=\"Start date...\"\n ${min ? `min=\"${min}\"` : ''}\n ${max ? `max=\"${max}\"` : ''}\n ${disabled ? 'disabled' : ''}\n ${readonly ? 'readonly' : ''}\n ${required ? 'required' : ''}\n\n </div>\n <div class=\"col-auto d-flex align-items-center\">\n <span class=\"text-muted\">${this.escapeHtml(separator.trim())}</span>\n </div>\n <div class=\"col\">\n <input type=\"date\"\n id=\"${fieldId}_end\"\n name=\"${name}_end\"\n class=\"${this.options.inputClass}${error ? ' is-invalid' : ''}\"\n value=\"${this.escapeHtml(endValue)}\"\n placeholder=\"End date...\"\n ${min ? `min=\"${min}\"` : ''}\n ${max ? `max=\"${max}\"` : ''}\n ${disabled ? 'disabled' : ''}\n ${readonly ? 'readonly' : ''}\n ${required ? 'required' : ''}\n\n </div>\n </div>\n <small class=\"form-text text-muted\">This will be enhanced with Easepick DateRangePicker</small>\n </div>\n ${help ? `<div class=\"${this.options.helpClass}\">${this.escapeHtml(help)}</div>` : ''}\n ${error ? `<div class=\"${this.options.errorClass}\">${this.escapeHtml(error)}</div>` : ''}\n </div>\n `;\n }\n\n /**\n * Render checklistdropdown field\n * @param {Object} field - Field configuration\n * @returns {string} Rendered HTML\n */\n renderChecklistDropdownField(field) {\n const fieldId = this.getFieldId(field.name);\n const selectedValues = (this.getFieldValue(field.name) ?? []);\n\n // Prepare data for Mustache template\n const templateData = {\n fieldId,\n fieldName: field.name,\n buttonText: field.buttonText || 'Select Options',\n buttonIcon: field.buttonIcon || 'bi-chevron-down',\n buttonClass: field.buttonClass || 'btn btn-outline-secondary btn-sm dropdown-toggle',\n dropdownClass: field.dropdownClass || 'dropdown-menu p-2',\n minWidth: field.minWidth || '200px',\n options: field.options.map(option => ({\n value: option.value,\n label: option.label,\n id: `${field.name}-${option.value}`,\n checked: selectedValues.includes(option.value)\n }))\n };\n\n return Mustache.render(this.templates.checklistdropdown, templateData);\n }\n\n /**\n * Render buttongroup field\n * @param {Object} field - Field configuration\n * @returns {string} Rendered HTML\n */\n renderButtonGroupField(field) {\n const fieldId = this.getFieldId(field.name);\n const selectedValue = (this.getFieldValue(field.name) ?? field.value);\n\n // Prepare data for Mustache template\n const templateData = {\n fieldId,\n fieldName: field.name,\n size: field.size || 'sm',\n variant: field.variant || 'outline-primary',\n options: field.options.map(option => ({\n value: option.value,\n label: option.label,\n action: option.action,\n active: option.value === selectedValue,\n buttonClass: this.getButtonClass(option.value === selectedValue, field.variant)\n }))\n };\n\n return Mustache.render(this.templates.buttongroup, templateData);\n }\n\n /**\n * Get button class based on active state and variant\n * @param {boolean} isActive - Whether button is active\n * @param {string} variant - Button variant\n * @returns {string} Button class\n */\n getButtonClass(isActive, variant = 'outline-primary') {\n if (isActive) {\n // Remove 'outline-' prefix for active buttons\n const activeVariant = variant.replace('outline-', '');\n return `btn btn-${activeVariant}`;\n }\n return `btn btn-${variant}`;\n }\n\n /**\n * Render combo input field (editable select/autocomplete)\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderComboField(field) {\n const {\n name,\n label,\n value = '',\n placeholder = 'Select or type...',\n options = [],\n required = false,\n disabled = false,\n readonly = false,\n allowCustom = true,\n showDescription = true,\n minChars = 0,\n maxSuggestions = 10,\n help = field.helpText || field.help || ''\n } = field;\n\n const fieldId = this.getFieldId(name);\n const error = this.errors[name];\n const fieldValue = (this.getFieldValue(name) ?? value);\n\n return `\n <div class=\"mojo-form-control\">\n ${label ? `<label for=\"${fieldId}\" class=\"${this.options.labelClass}\">${this.escapeHtml(label)}${required ? '<span class=\"text-danger\">*</span>' : ''}</label>` : ''}\n <div class=\"combo-input-placeholder\"\n data-field-name=\"${name}\"\n data-field-type=\"combo\"\n data-field-config='${JSON.stringify({\n name,\n value: fieldValue,\n placeholder,\n options,\n allowCustom,\n showDescription,\n minChars,\n maxSuggestions,\n disabled,\n readonly,\n required\n })}'>\n <input type=\"text\"\n id=\"${fieldId}\"\n name=\"${name}_display\"\n class=\"${this.options.inputClass}${error ? ' is-invalid' : ''}\"\n placeholder=\"${this.escapeHtml(placeholder)}\"\n value=\"${this.escapeHtml(fieldValue)}\"\n ${disabled ? 'disabled' : ''}\n ${readonly ? 'readonly' : ''}\n ${required ? 'required' : ''}>\n <input type=\"hidden\" name=\"${name}\" value=\"${this.escapeHtml(fieldValue)}\">\n <small class=\"form-text text-muted\">This will be enhanced with ComboInput component</small>\n </div>\n ${help ? `<div class=\"${this.options.helpClass}\">${this.escapeHtml(help)}</div>` : ''}\n ${error ? `<div class=\"${this.options.errorClass}\">${this.escapeHtml(error)}</div>` : ''}\n </div>\n `;\n }\n\n /**\n * Render a tabset field consisting of Bootstrap nav tabs and tab panes.\n * Each pane's fields are rendered using existing field rendering,\n * wrapped in a row so column layouts work as expected.\n * @param {Object} field - Tabset configuration\n * @param {Array} field.tabs - Array of tabs: [{ label, fields }]\n * @param {string} [field.name] - Optional name used to generate stable IDs\n * @param {string} [field.navClass] - CSS classes for the tabs nav\n * @param {string} [field.contentClass] - CSS classes for the tab content container\n * @returns {string} HTML\n */\n renderTabsetField(field) {\n const {\n tabs = [],\n name = `tabset-${Date.now()}`,\n navClass = 'nav nav-tabs mb-3',\n contentClass = 'tab-content'\n } = field;\n\n const safe = String(name).toLowerCase().replace(/[^a-z0-9]/g, '-');\n\n const nav = tabs.map((t, i) => {\n const id = `${safe}-pane-${i}`;\n const isActive = i === 0;\n return `\n <li class=\"nav-item\" role=\"presentation\">\n <button class=\"nav-link ${isActive ? 'active' : ''}\"\n id=\"${id}-tab\"\n data-bs-toggle=\"tab\"\n data-bs-target=\"#${id}\"\n type=\"button\"\n role=\"tab\"\n aria-controls=\"${id}\"\n aria-selected=\"${isActive}\">\n ${this.escapeHtml(t.label || `Tab ${i + 1}`)}\n </button>\n </li>\n `;\n }).join('');\n\n const panes = tabs.map((t, i) => {\n const id = `${safe}-pane-${i}`;\n const isActive = i === 0;\n const fieldsHTML = (t.fields || []).map(f => this.buildFieldHTML(f)).join('');\n return `\n <div class=\"tab-pane fade ${isActive ? 'show active' : ''}\"\n id=\"${id}\"\n role=\"tabpanel\"\n aria-labelledby=\"${id}-tab\"\n data-tab-index=\"${i}\">\n <div class=\"row\">\n ${fieldsHTML}\n </div>\n </div>\n `;\n }).join('');\n\n return `\n <div class=\"mojo-form-tabset\">\n <ul class=\"${navClass}\" role=\"tablist\">\n ${nav}\n </ul>\n <div class=\"${contentClass}\">\n ${panes}\n </div>\n </div>\n `;\n }\n\n /**\n * Generate select options automatically from numeric range or patterns\n * Supports multiple generation modes:\n * - Numeric ranges: start, end, step\n * - Formatting: format function, prefix, suffix\n *\n * @param {number} start - Start value (inclusive)\n * @param {number} end - End value (inclusive)\n * @param {number} step - Step increment (default: 1)\n * @param {Object} options - Additional options\n * @param {Function|string} options.format - Format function or preset ('padded', 'ordinal')\n * @param {string} options.prefix - Prefix for label\n * @param {string} options.suffix - Suffix for label\n * @returns {Array} Array of option objects {value, label}\n *\n * @example\n * // Hours 1-24\n * generateSelectOptions(1, 24, 1)\n *\n * // Minutes in 15-min increments with padding\n * generateSelectOptions(0, 45, 15, { format: 'padded' })\n *\n * // Days with ordinal suffix\n * generateSelectOptions(1, 31, 1, { format: 'ordinal' })\n *\n * // Years with prefix\n * generateSelectOptions(2020, 2030, 1, { prefix: 'Year ' })\n *\n * // Percentages\n * generateSelectOptions(0, 100, 10, { suffix: '%' })\n *\n * // Custom formatter\n * generateSelectOptions(1, 12, 1, {\n * format: (v) => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\n * 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][v-1]\n * })\n */\n generateSelectOptions(start, end, step = 1, options = {}) {\n const { format, prefix = '', suffix = '' } = options;\n const results = [];\n\n // Determine direction (ascending or descending)\n const increment = start <= end ? Math.abs(step) : -Math.abs(step);\n\n // Generate options\n for (let i = start; start <= end ? i <= end : i >= end; i += increment) {\n let label = String(i);\n\n // Apply formatting\n if (typeof format === 'function') {\n label = format(i);\n } else if (format === 'padded' || format === 'pad') {\n // Pad with zeros to match end value length\n const maxLength = String(Math.max(Math.abs(start), Math.abs(end))).length;\n label = String(i).padStart(maxLength, '0');\n } else if (format === 'ordinal') {\n label = this.formatOrdinal(i);\n }\n\n // Apply prefix/suffix\n label = `${prefix}${label}${suffix}`;\n\n results.push({\n value: i,\n label: label\n });\n }\n\n return results;\n }\n\n /**\n * Format number with ordinal suffix (1st, 2nd, 3rd, etc.)\n * @param {number} num - Number to format\n * @returns {string} Formatted ordinal string\n */\n formatOrdinal(num) {\n const j = num % 10;\n const k = num % 100;\n\n if (j === 1 && k !== 11) return num + 'st';\n if (j === 2 && k !== 12) return num + 'nd';\n if (j === 3 && k !== 13) return num + 'rd';\n return num + 'th';\n }\n\n /**\n * Escape HTML characters to prevent XSS\n * @param {string} str - String to escape\n * @returns {string} Escaped string\n */\n escapeHtml(str) {\n if (str == null) return '';\n const div = document.createElement('div');\n div.textContent = String(str);\n return div.innerHTML;\n }\n}\n\n// Export for use in MOJO framework\nexport { FormBuilder };\nexport default FormBuilder;\n","/**\n * FileDropMixin - Adds drag and drop file functionality to Views\n * Provides configurable file drop handling with validation and callbacks\n */\n\nconst FileDropMixin = {\n /**\n * Enable drag and drop file functionality on this view\n * @param {Object} config - Configuration options\n */\n enableFileDrop(config = {}) {\n // Store configuration\n this._fileDropConfig = {\n acceptedTypes: config.acceptedTypes || ['*/*'],\n maxFileSize: config.maxFileSize || 10 * 1024 * 1024, // 10MB\n dropZoneSelector: config.dropZoneSelector || null, // defaults to view element\n visualFeedback: config.visualFeedback !== false, // default true\n multiple: config.multiple || false,\n validateOnDrop: config.validateOnDrop !== false, // default true\n dragOverClass: config.dragOverClass || 'drag-over',\n dragActiveClass: config.dragActiveClass || 'drag-active'\n };\n\n // Initialize drag/drop state\n this._fileDropState = {\n isDragActive: false,\n dragCounter: 0\n };\n\n // Bind event handlers\n this._boundFileDropHandlers = {\n dragEnter: this._onFileDropDragEnter.bind(this),\n dragOver: this._onFileDropDragOver.bind(this),\n dragLeave: this._onFileDropDragLeave.bind(this),\n drop: this._onFileDropDrop.bind(this),\n preventDefault: this._onFileDropPreventDefault.bind(this)\n };\n\n // Set up event listeners after render\n if (this.element) {\n this._setupFileDropListeners();\n } else {\n // If not rendered yet, set up in onAfterRender\n const originalOnAfterRender = this.onAfterRender.bind(this);\n this.onAfterRender = async () => {\n await originalOnAfterRender();\n this._setupFileDropListeners();\n };\n }\n\n // Hook into cleanup\n const originalOnBeforeDestroy = this.onBeforeDestroy.bind(this);\n this.onBeforeDestroy = async () => {\n this._cleanupFileDropListeners();\n await originalOnBeforeDestroy();\n };\n },\n\n /**\n * Set up drag and drop event listeners\n * @private\n */\n _setupFileDropListeners() {\n if (!this._fileDropConfig) return;\n\n // Get drop zone element\n const dropZone = this._getFileDropZone();\n if (!dropZone) {\n console.warn('FileDropMixin: Drop zone not found');\n return;\n }\n\n this._fileDropZone = dropZone;\n\n // Add event listeners to drop zone\n dropZone.addEventListener('dragenter', this._boundFileDropHandlers.dragEnter);\n dropZone.addEventListener('dragover', this._boundFileDropHandlers.dragOver);\n dropZone.addEventListener('dragleave', this._boundFileDropHandlers.dragLeave);\n dropZone.addEventListener('drop', this._boundFileDropHandlers.drop);\n\n // Prevent default drag behaviors on document to avoid browser's default file handling\n ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {\n document.addEventListener(eventName, this._boundFileDropHandlers.preventDefault);\n });\n },\n\n /**\n * Clean up drag and drop event listeners\n * @private\n */\n _cleanupFileDropListeners() {\n if (!this._boundFileDropHandlers) return;\n\n // Remove from drop zone\n if (this._fileDropZone) {\n this._fileDropZone.removeEventListener('dragenter', this._boundFileDropHandlers.dragEnter);\n this._fileDropZone.removeEventListener('dragover', this._boundFileDropHandlers.dragOver);\n this._fileDropZone.removeEventListener('dragleave', this._boundFileDropHandlers.dragLeave);\n this._fileDropZone.removeEventListener('drop', this._boundFileDropHandlers.drop);\n }\n\n // Remove from document\n ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {\n document.removeEventListener(eventName, this._boundFileDropHandlers.preventDefault);\n });\n\n // Clear references\n this._fileDropZone = null;\n this._boundFileDropHandlers = null;\n this._fileDropConfig = null;\n this._fileDropState = null;\n },\n\n /**\n * Get the drop zone element\n * @returns {Element} The drop zone element\n * @private\n */\n _getFileDropZone() {\n if (this._fileDropConfig.dropZoneSelector) {\n return this.element.querySelector(this._fileDropConfig.dropZoneSelector);\n }\n return this.element;\n },\n\n /**\n * Prevent default drag behaviors\n * @param {Event} e - Drag event\n * @private\n */\n _onFileDropPreventDefault(e) {\n e.preventDefault();\n e.stopPropagation();\n },\n\n /**\n * Handle drag enter event\n * @param {DragEvent} e - Drag event\n * @private\n */\n _onFileDropDragEnter(e) {\n this._onFileDropPreventDefault(e);\n \n this._fileDropState.dragCounter++;\n \n if (!this._fileDropState.isDragActive) {\n this._fileDropState.isDragActive = true;\n this._applyFileDropVisualFeedback(true);\n }\n },\n\n /**\n * Handle drag over event\n * @param {DragEvent} e - Drag event\n * @private\n */\n _onFileDropDragOver(e) {\n this._onFileDropPreventDefault(e);\n e.dataTransfer.dropEffect = 'copy';\n },\n\n /**\n * Handle drag leave event\n * @param {DragEvent} e - Drag event\n * @private\n */\n _onFileDropDragLeave(e) {\n this._onFileDropPreventDefault(e);\n \n this._fileDropState.dragCounter--;\n \n if (this._fileDropState.dragCounter <= 0) {\n this._fileDropState.isDragActive = false;\n this._fileDropState.dragCounter = 0;\n this._applyFileDropVisualFeedback(false);\n }\n },\n\n /**\n * Handle drop event\n * @param {DragEvent} e - Drag event\n * @private\n */\n async _onFileDropDrop(e) {\n this._onFileDropPreventDefault(e);\n \n // Reset drag state\n this._fileDropState.isDragActive = false;\n this._fileDropState.dragCounter = 0;\n this._applyFileDropVisualFeedback(false);\n \n // Get files from drop\n const files = Array.from(e.dataTransfer.files);\n \n if (files.length === 0) return;\n \n // Handle single vs multiple files\n const filesToProcess = this._fileDropConfig.multiple ? files : [files[0]];\n \n // Validate files if enabled\n let validation = { valid: true, errors: [] };\n if (this._fileDropConfig.validateOnDrop) {\n validation = this._validateFileDropFiles(filesToProcess);\n \n if (!validation.valid) {\n if (typeof this.onFileDropError === 'function') {\n await this.onFileDropError(new Error(validation.errors.join(', ')), e, filesToProcess);\n }\n return;\n }\n }\n \n // Call the view's onFileDrop method\n if (typeof this.onFileDrop === 'function') {\n try {\n await this.onFileDrop(filesToProcess, e, validation);\n } catch (error) {\n if (typeof this.onFileDropError === 'function') {\n await this.onFileDropError(error, e, filesToProcess);\n } else {\n console.error('FileDropMixin: Error in onFileDrop callback:', error);\n }\n }\n } else {\n console.warn('FileDropMixin: No onFileDrop method found on view');\n }\n },\n\n /**\n * Apply visual feedback during drag operations\n * @param {boolean} isDragActive - Whether drag is active\n * @private\n */\n _applyFileDropVisualFeedback(isDragActive) {\n if (!this._fileDropConfig.visualFeedback || !this._fileDropZone) return;\n \n const { dragOverClass, dragActiveClass } = this._fileDropConfig;\n \n if (isDragActive) {\n this._fileDropZone.classList.add(dragOverClass, dragActiveClass);\n } else {\n this._fileDropZone.classList.remove(dragOverClass, dragActiveClass);\n }\n },\n\n /**\n * Validate dropped files\n * @param {File[]} files - Files to validate\n * @returns {Object} Validation result\n * @private\n */\n _validateFileDropFiles(files) {\n const errors = [];\n const config = this._fileDropConfig;\n \n for (const file of files) {\n // Check file type\n if (!this._isFileDropTypeAccepted(file.type)) {\n errors.push(`File type \"${file.type}\" is not accepted for file \"${file.name}\"`);\n continue;\n }\n \n // Check file size\n if (file.size > config.maxFileSize) {\n errors.push(`File \"${file.name}\" (${this._formatFileDropSize(file.size)}) exceeds maximum size (${this._formatFileDropSize(config.maxFileSize)})`);\n }\n }\n \n return {\n valid: errors.length === 0,\n errors\n };\n },\n\n /**\n * Check if file type is accepted\n * @param {string} fileType - MIME type of the file\n * @returns {boolean} Whether the file type is accepted\n * @private\n */\n _isFileDropTypeAccepted(fileType) {\n const { acceptedTypes } = this._fileDropConfig;\n \n // Allow all types if wildcard\n if (acceptedTypes.includes('*/*')) return true;\n \n return acceptedTypes.some(acceptedType => {\n // Exact match\n if (acceptedType === fileType) return true;\n \n // Wildcard match (e.g., \"image/*\")\n if (acceptedType.endsWith('/*')) {\n const category = acceptedType.split('/')[0];\n return fileType.startsWith(category + '/');\n }\n \n return false;\n });\n },\n\n /**\n * Format file size for display\n * @param {number} bytes - File size in bytes\n * @returns {string} Formatted file size\n * @private\n */\n _formatFileDropSize(bytes) {\n if (bytes === 0) return '0 Bytes';\n const k = 1024;\n const sizes = ['Bytes', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];\n }\n};\n\n// Apply mixin to View prototype\nexport default function applyFileDropMixin(ViewClass) {\n Object.assign(ViewClass.prototype, FileDropMixin);\n}\n\n// Export the mixin for manual application\nexport { FileDropMixin };","/**\n * TagInputView - Advanced tag input component for MOJO framework\n * Allows users to add/remove tags with keyboard and mouse interaction\n * Integrates with FormView and uses EventDelegate patterns\n *\n * Features:\n * - Add tags via Enter, comma, or Tab key\n * - Remove tags with click or keyboard\n * - Duplicate prevention\n * - Bootstrap 5 styling\n * - Accessibility support\n * - Form integration with hidden input\n *\n * Example Usage:\n * ```javascript\n * const tagInput = new TagInputView({\n * name: 'tags',\n * value: 'javascript,react,node', // Initial tags\n * placeholder: 'Add tags...',\n * maxTags: 10,\n * allowDuplicates: false\n * });\n * ```\n */\n\nimport View from '@core/View.js';\n\nclass TagInputView extends View {\n constructor(options = {}) {\n const {\n name,\n value = '',\n placeholder = 'Add tags...',\n maxTags = 50,\n allowDuplicates = false,\n separator = ',',\n trimTags = true,\n minLength = 1,\n maxLength = 50,\n disabled = false,\n readonly = false,\n class: containerClass = '',\n tagClass = 'badge bg-primary',\n inputClass = 'form-control',\n ...viewOptions\n } = options;\n\n super({\n tagName: 'div',\n className: `tag-input-view ${containerClass}`,\n ...viewOptions\n });\n\n // Configuration\n this.name = name;\n this.placeholder = placeholder;\n this.maxTags = maxTags;\n this.allowDuplicates = allowDuplicates;\n this.separator = separator;\n this.trimTags = trimTags;\n this.minLength = minLength;\n this.maxLength = maxLength;\n this.disabled = disabled;\n this.readonly = readonly;\n this.tagClass = tagClass;\n this.inputClass = inputClass;\n\n // State\n this.tags = [];\n this.focusedTagIndex = -1;\n\n // Parse initial value\n if (value) {\n this.tags = this.parseTagString(value);\n }\n }\n\n /**\n * Render the tag input component\n */\n async renderTemplate() {\n const tagsHTML = this.renderTags();\n const hiddenInputHTML = this.renderHiddenInput();\n const inputHTML = this.renderInput();\n\n return `\n <div class=\"tag-input-container\">\n <div class=\"tag-input-wrapper border rounded p-2\"\n data-action=\"focus-input\"\n tabindex=\"0\"\n role=\"combobox\"\n aria-expanded=\"false\"\n aria-label=\"Tag input\">\n <div class=\"tags-container d-flex flex-wrap gap-1 mb-2\">\n ${tagsHTML}\n </div>\n ${inputHTML}\n </div>\n ${hiddenInputHTML}\n <div class=\"tag-input-feedback small text-muted mt-1\">\n <span class=\"tag-count\">${this.tags.length}</span>/${this.maxTags} tags\n </div>\n </div>\n `;\n }\n\n /**\n * Render individual tags\n */\n renderTags() {\n return this.tags.map((tag, index) => `\n <span class=\"${this.tagClass} tag-item\"\n data-tag-index=\"${index}\"\n tabindex=\"0\"\n role=\"button\"\n aria-label=\"Tag: ${this.escapeHtml(tag)}. Press Delete or Backspace to remove.\">\n <span class=\"tag-text\">${this.escapeHtml(tag)}</span>\n ${!this.readonly && !this.disabled ? `\n <i class=\"bi bi-x tag-remove ms-1\"\n data-action=\"remove-tag\"\n data-tag-index=\"${index}\"\n aria-label=\"Remove tag\"></i>\n ` : ''}\n </span>\n `).join('');\n }\n\n /**\n * Render the input field\n */\n renderInput() {\n if (this.readonly) {\n return '';\n }\n\n return `\n <input type=\"text\"\n class=\"${this.inputClass} tag-input-field border-0 p-0\"\n placeholder=\"${this.escapeHtml(this.placeholder)}\"\n ${this.disabled ? 'disabled' : ''}\n data-change-action=\"input-change\"\n style=\"outline: none; box-shadow: none; min-width: 120px;\"\n autocomplete=\"off\">\n `;\n }\n\n /**\n * Render hidden input for form submission\n */\n renderHiddenInput() {\n if (!this.name) return '';\n\n return `\n <input type=\"hidden\"\n name=\"${this.name}\"\n value=\"${this.escapeHtml(this.getTagString())}\"\n class=\"tag-input-hidden\">\n `;\n }\n\n /**\n * Handle component initialization after render\n */\n async onAfterRender() {\n await super.onAfterRender();\n this.updateTagCount();\n }\n\n // ========================================\n // EventDelegate Action Handlers\n // ========================================\n\n /**\n * Handle focus on container\n */\n async onActionFocusInput(_event, _element) {\n this.focus();\n }\n\n focus() {\n const input = this.element.querySelector('.tag-input-field');\n if (input && !this.disabled) {\n input.focus();\n }\n this.focusedTagIndex = -1;\n }\n\n /**\n * Handle tag removal\n */\n async onActionRemoveTag(event, element) {\n event.stopPropagation();\n\n const tagIndex = parseInt(element.getAttribute('data-tag-index'));\n if (tagIndex >= 0 && tagIndex < this.tags.length) {\n await this.removeTag(tagIndex);\n }\n }\n\n /**\n * Handle input changes (for adding tags)\n */\n async onChangeInputChange(event, element) {\n const value = element.value;\n const lastChar = value.slice(-1);\n\n // Check for separator keys\n if (lastChar === this.separator || lastChar === '\\n') {\n event.preventDefault();\n const tagText = value.slice(0, -1);\n if (tagText.trim()) {\n await this.addTag(tagText);\n element.value = '';\n }\n return;\n }\n\n // Handle other trigger keys via keydown\n\n }\n\n bindEvents() {\n if (!this.__bnd_keydown) this.__bnd_keydown = this.handleInputKeydown.bind(this);\n this.element.addEventListener('keydown', this.__bnd_keydown);\n this.events.bind(this.element);\n }\n\n unbindEvents() {\n if (this.__bnd_keydown)this.element.removeEventListener('keydown', this.__bnd_keydown);\n this.events.unbind();\n }\n\n /**\n * Handle keyboard interactions\n */\n handleInputKeydown(event) {\n const input = event.target;\n const value = input.value || '';\n switch (event.key) {\n case 'Enter':\n case 'Tab':\n case ',':\n if (value.trim()) {\n event.preventDefault();\n this.addTag(value);\n input.value = '';\n }\n break;\n\n case 'Backspace':\n if (value === '' && this.tags.length > 0) {\n event.preventDefault();\n if (this.focusedTagIndex >= 0) {\n this.removeTag(this.focusedTagIndex);\n if (this.focusedTagIndex == 0) {\n this.focus();\n } else {\n this.focusTag(this.focusedTagIndex - 1);\n }\n } else {\n this.removeTag(this.tags.length - 1);\n }\n }\n break;\n\n case 'ArrowLeft':\n if (value === '' && this.tags.length > 0) {\n event.preventDefault();\n if (this.focusedTagIndex >= 0) {\n const newIndex = this.focusedTagIndex - 1;\n if (newIndex >= 0) {\n this.focusTag(newIndex);\n } else {\n this.focus();\n }\n } else {\n this.focusTag(this.tags.length - 1);\n }\n }\n break;\n\n case 'ArrowRight':\n if (value === '' && this.tags.length > 0) {\n event.preventDefault();\n if (this.focusedTagIndex >= 0) {\n const newIndex = this.focusedTagIndex + 1;\n if (newIndex < this.tags.length) {\n this.focusTag(newIndex);\n } else {\n this.focus();\n }\n } else {\n this.focusTag(0);\n }\n }\n break;\n\n case 'Escape':\n input.value = '';\n input.blur();\n break;\n }\n }\n\n // ========================================\n // Tag Management Methods\n // ========================================\n\n /**\n * Add a new tag\n */\n async addTag(tagText) {\n if (this.readonly || this.disabled) return false;\n\n const cleanTag = this.trimTags ? tagText.trim() : tagText;\n\n // Validation\n if (!this.isValidTag(cleanTag)) {\n return false;\n }\n\n // Check for duplicates\n if (!this.allowDuplicates && this.tags.includes(cleanTag)) {\n this.showTagError(`Tag \"${cleanTag}\" already exists`);\n return false;\n }\n\n // Check max tags limit\n if (this.tags.length >= this.maxTags) {\n this.showTagError(`Maximum ${this.maxTags} tags allowed`);\n return false;\n }\n\n // Add the tag\n this.tags.push(cleanTag);\n await this.updateDisplay();\n\n // Emit events\n this.emit('tag:added', { tag: cleanTag, tags: this.tags });\n this.emit('change', { value: this.getTagString(), tags: this.tags });\n\n return true;\n }\n\n /**\n * Remove a tag by index\n */\n async removeTag(index) {\n if (this.readonly || this.disabled) return false;\n\n if (index >= 0 && index < this.tags.length) {\n const removedTag = this.tags[index];\n this.tags.splice(index, 1);\n await this.updateDisplay();\n\n // Emit events\n this.emit('tag:removed', { tag: removedTag, tags: this.tags });\n this.emit('change', { value: this.getTagString(), tags: this.tags });\n\n return true;\n }\n\n return false;\n }\n\n /**\n * Remove a tag by value\n */\n async removeTagByValue(tagValue) {\n const index = this.tags.indexOf(tagValue);\n if (index >= 0) {\n return await this.removeTag(index);\n }\n return false;\n }\n\n /**\n * Clear all tags\n */\n async clearTags() {\n if (this.readonly || this.disabled) return false;\n\n const oldTags = [...this.tags];\n this.tags = [];\n await this.updateDisplay();\n\n this.emit('tags:cleared', { oldTags });\n this.emit('change', { value: '', tags: [] });\n\n return true;\n }\n\n /**\n * Set tags from array or string\n */\n async setTags(tagsInput) {\n let newTags = [];\n\n if (Array.isArray(tagsInput)) {\n newTags = tagsInput;\n } else if (typeof tagsInput === 'string') {\n newTags = this.parseTagString(tagsInput);\n }\n\n // Validate and filter tags\n newTags = newTags\n .filter(tag => this.isValidTag(tag))\n .slice(0, this.maxTags);\n\n // Remove duplicates if not allowed\n if (!this.allowDuplicates) {\n newTags = [...new Set(newTags)];\n }\n\n this.tags = newTags;\n await this.updateDisplay();\n\n this.emit('tags:set', { tags: this.tags });\n this.emit('change', { value: this.getTagString(), tags: this.tags });\n }\n\n // ========================================\n // Utility Methods\n // ========================================\n\n /**\n * Validate a tag\n */\n isValidTag(tag) {\n if (typeof tag !== 'string') return false;\n if (tag.length < this.minLength) return false;\n if (tag.length > this.maxLength) return false;\n if (tag.trim() === '') return false;\n return true;\n }\n\n /**\n * Parse tag string into array\n */\n parseTagString(tagString) {\n if (!tagString) return [];\n\n return tagString\n .split(this.separator)\n .map(tag => this.trimTags ? tag.trim() : tag)\n .filter(tag => tag.length > 0);\n }\n\n /**\n * Get tags as a string\n */\n getTagString() {\n return this.tags.join(this.separator);\n }\n\n /**\n * Get tags as array\n */\n getTags() {\n return [...this.tags];\n }\n\n /**\n * Focus a specific tag\n */\n focusTag(index) {\n const tagElements = this.element.querySelectorAll('.tag-item');\n if (tagElements[index]) {\n this.focusedTagIndex = index;\n console.log(`Focused tag index: ${index}`);\n tagElements[index].focus();\n }\n }\n\n /**\n * Update the display after changes\n */\n async updateDisplay() {\n // Re-render tags container\n const tagsContainer = this.element.querySelector('.tags-container');\n if (tagsContainer) {\n tagsContainer.innerHTML = this.renderTags();\n }\n\n // Update hidden input\n const hiddenInput = this.element.querySelector('.tag-input-hidden');\n if (hiddenInput) {\n hiddenInput.value = this.getTagString();\n }\n\n // Update tag count\n this.updateTagCount();\n }\n\n /**\n * Update tag count display\n */\n updateTagCount() {\n const tagCountElement = this.element.querySelector('.tag-count');\n if (tagCountElement) {\n tagCountElement.textContent = this.tags.length;\n }\n }\n\n /**\n * Show tag error message\n */\n showTagError(message) {\n // Create or update error message\n let errorElement = this.element.querySelector('.tag-error');\n\n if (!errorElement) {\n errorElement = document.createElement('div');\n errorElement.className = 'tag-error small text-danger mt-1';\n\n const feedback = this.element.querySelector('.tag-input-feedback');\n if (feedback) {\n feedback.parentNode.insertBefore(errorElement, feedback.nextSibling);\n }\n }\n\n errorElement.textContent = message;\n\n // Auto-hide after 3 seconds\n setTimeout(() => {\n if (errorElement.parentNode) {\n errorElement.remove();\n }\n }, 3000);\n }\n\n /**\n * Enable/disable the component\n */\n setEnabled(enabled) {\n this.disabled = !enabled;\n\n const input = this.element.querySelector('.tag-input-field');\n if (input) {\n input.disabled = this.disabled;\n }\n\n const container = this.element.querySelector('.tag-input-wrapper');\n if (container) {\n container.classList.toggle('disabled', this.disabled);\n }\n }\n\n /**\n * Set readonly state\n */\n setReadonly(readonly) {\n this.readonly = readonly;\n\n const input = this.element.querySelector('.tag-input-field');\n if (input) {\n input.style.display = readonly ? 'none' : '';\n }\n\n // Hide remove buttons\n const removeButtons = this.element.querySelectorAll('.tag-remove');\n removeButtons.forEach(btn => {\n btn.style.display = readonly ? 'none' : '';\n });\n }\n\n /**\n * Escape HTML to prevent XSS\n */\n escapeHtml(str) {\n if (str == null) return '';\n const div = document.createElement('div');\n div.textContent = String(str);\n return div.innerHTML;\n }\n\n /**\n * Get form value (for integration with forms)\n */\n getFormValue() {\n return this.getTagString();\n }\n\n /**\n * Set form value (for integration with forms)\n */\n async setFormValue(value) {\n await this.setTags(value);\n }\n\n /**\n * Static factory method\n */\n static create(options = {}) {\n return new TagInputView(options);\n }\n}\n\nexport default TagInputView;\n","/**\n * CollectionSelectView - A searchable dropdown component for selecting items from a Collection\n *\n * This component uses a parent-child architecture to prevent input focus loss:\n * - CollectionSelectView (parent): Manages input and coordination\n * - CollectionDropdownView (child): Handles dropdown rendering only\n */\n\nimport { View } from '@core/View.js';\nimport MOJOUtils from '@core/utils/MOJOUtils.js';\n\n/**\n * CollectionDropdownView - Child component for dropdown results only\n */\nclass CollectionDropdownView extends View {\n constructor(options = {}) {\n super({\n tagName: 'div',\n className: 'collection-dropdown-view dropdown-menu show w-100 position-absolute',\n style: 'max-height: 250px; overflow-y: auto; z-index: 1000;',\n template: `\n {{#data.loading}}\n <div class=\"dropdown-item text-center\">\n <div class=\"spinner-border spinner-border-sm\" role=\"status\">\n <span class=\"visually-hidden\">Loading...</span>\n </div>\n </div>\n {{/data.loading}}\n\n {{^data.loading}}\n {{#data.items}}\n <button type=\"button\"\n class=\"dropdown-item {{#isSelected}}active{{/isSelected}} {{#isFocused}}bg-light{{/isFocused}}\"\n data-action=\"select-item\"\n data-value=\"{{valueField}}\"\n data-label=\"{{labelField}}\"\n data-index=\"{{index}}\">\n {{labelField}}\n </button>\n {{/data.items}}\n\n {{#data.showNoResults}}\n <div class=\"dropdown-item text-muted\">\n {{#data.hasSearched}}No results found{{/data.hasSearched}}\n {{^data.hasSearched}}Start typing to search...{{/data.hasSearched}}\n </div>\n {{/data.showNoResults}}\n {{/data.loading}}\n `,\n ...options\n });\n\n this.collection = options.collection;\n this.labelField = options.labelField || 'name';\n this.valueField = options.valueField || 'id';\n this.selectedValue = options.selectedValue || '';\n this.loading = options.loading || false;\n this.hasSearched = options.hasSearched || false;\n this.focusedIndex = options.focusedIndex || -1;\n }\n\n async getViewData() {\n const items = this.collection ? this.collection.toJSON().map((item, index) => {\n const labelValue = MOJOUtils.getNestedValue(item, this.labelField);\n const fieldValue = MOJOUtils.getNestedValue(item, this.valueField);\n\n return {\n ...item,\n labelField: labelValue,\n valueField: fieldValue,\n isSelected: fieldValue == this.selectedValue,\n isFocused: index === this.focusedIndex,\n index\n };\n }) : [];\n\n return {\n loading: this.loading,\n hasSearched: this.hasSearched,\n showNoResults: !this.loading && this.hasSearched && items.length === 0,\n items\n };\n }\n\n async handleActionSelectItem(event, element) {\n event.preventDefault();\n const value = element.getAttribute('data-value');\n const label = element.getAttribute('data-label');\n this.emit('item-selected', { value, label });\n }\n\n updateState(state) {\n Object.assign(this, state);\n }\n\n updateFocusedItem(newIndex) {\n this.focusedIndex = newIndex;\n const items = this.element?.querySelectorAll('.dropdown-item[data-action=\"select-item\"]');\n items?.forEach((item, index) => {\n item.classList.toggle('bg-light', index === this.focusedIndex);\n });\n }\n\n getItemCount() {\n return this.collection ? this.collection.length() : 0;\n }\n\n getFocusedItem() {\n if (this.focusedIndex >= 0 && this.collection) {\n const items = this.collection.toJSON();\n return items[this.focusedIndex] || null;\n }\n return null;\n }\n}\n\n/**\n * CollectionSelectView - Main component with stable input\n */\nclass CollectionSelectView extends View {\n constructor(options = {}) {\n super({\n className: 'collection-select-view',\n template: `\n <div class=\"position-relative\">\n <input type=\"text\"\n class=\"form-control {{#data.hasError}}is-invalid{{/data.hasError}} {{#data.showClear}}pe-5{{/data.showClear}}\"\n placeholder=\"{{data.placeholder}}\"\n value=\"{{data.displayValue}}\"\n autocomplete=\"off\" />\n\n <input type=\"hidden\"\n name=\"{{data.name}}\"\n value=\"{{data.selectedValue}}\" />\n\n {{#data.showClear}}\n <button type=\"button\"\n class=\"btn btn-link position-absolute top-50 end-0 translate-middle-y me-2 p-0 border-0\"\n style=\"z-index: 10; color: #6c757d;\"\n data-action=\"clear-selection\"\n title=\"Clear selection\">\n <i class=\"bi bi-x-circle\"></i>\n </button>\n {{/data.showClear}}\n\n <div class=\"dropdown-container\"></div>\n\n {{#data.hasError}}\n <div class=\"invalid-feedback\">{{data.errorMessage}}</div>\n {{/data.hasError}}\n </div>\n `,\n ...options\n });\n\n // Configuration\n this.collection = options.collection;\n this.labelField = options.labelField || 'name';\n this.valueField = options.valueField || 'id';\n this.maxItems = options.maxItems || 10;\n this.placeholder = options.placeholder || 'Search...';\n this.debounceMs = options.debounceMs || 400;\n this.name = options.name || 'collection_select';\n this.emptyFetch = options.emptyFetch !== false;\n this.requiresActiveGroup = options.requiresActiveGroup || false;\n\n // State\n this.selectedValue = options.value || '0';\n this.selectedLabel = '';\n this.searchValue = '';\n this.showDropdown = false;\n this.loading = false;\n this.hasSearched = false;\n this.focusedIndex = -1;\n this.hasError = false;\n this.errorMessage = '';\n\n if (this.selectedValue && typeof this.selectedValue === 'object') {\n // Support dot notation in labelField and valueField\n this.selectedLabel = MOJOUtils.getNestedValue(this.selectedValue, this.labelField) || '';\n this.selectedValue = MOJOUtils.getNestedValue(this.selectedValue, this.valueField) || '0';\n }\n\n // Internal\n this.searchTimer = null;\n this.dropdownView = null;\n this.defaultParams = {};\n this.defaultParamsOption = options.defaultParams || null; // Can be dict or callback\n\n // Bind methods\n this.handleDocumentClick = this.handleDocumentClick.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n this.handleInputEvents = this.handleInputEvents.bind(this);\n\n }\n\n onInit() {\n if (this.collection) {\n this.setupCollection();\n }\n }\n\n setupCollection() {\n this.defaultParams = { ...this.collection.params };\n this.collection.params.size = this.maxItems;\n this.defaultParams.size = this.maxItems;\n\n // Merge defaultParams from options (dict or callback)\n if (this.defaultParamsOption) {\n const extraParams = typeof this.defaultParamsOption === 'function' \n ? this.defaultParamsOption() \n : this.defaultParamsOption;\n \n if (extraParams && typeof extraParams === 'object') {\n Object.assign(this.defaultParams, extraParams);\n Object.assign(this.collection.params, extraParams);\n }\n }\n\n // Add active group filter if required\n if (this.requiresActiveGroup) {\n const app = this.getApp();\n if (app && app.activeGroup && app.activeGroup.id) {\n this.collection.params.group = app.activeGroup.id;\n this.defaultParams.group = app.activeGroup.id;\n }\n }\n\n this.collection.on('fetch:start', () => {\n this.loading = true;\n this.showDropdown = true;\n this.updateDropdown();\n });\n\n this.collection.on('fetch:end', () => {\n this.loading = false;\n this.showDropdown = true;\n this.updateDropdown();\n });\n\n if (this.selectedValue) {\n this.loadSelectedItem();\n }\n\n if (this.emptyFetch && this.collection.isEmpty()) {\n this.performInitialFetch();\n }\n }\n\n async performInitialFetch() {\n if (!this.collection) return;\n\n try {\n const fetchParams = { ...this.defaultParams };\n delete fetchParams.search;\n await this.collection.updateParams(fetchParams, true);\n } catch (error) {\n console.error('Initial fetch error:', error);\n }\n }\n\n async loadSelectedItem() {\n try {\n if (!this.selectedValue || this.selectedValue == '0') return;\n if (this.selectedLabel) return;\n const selectedModel = this.collection?.get(this.selectedValue);\n if (selectedModel) {\n // Support dot notation in labelField\n this.selectedLabel = this.getFieldValue(selectedModel, this.labelField);\n this.render(false);\n return;\n }\n\n let model = await this.collection.fetchOne(this.selectedValue);\n if (model) {\n // Support dot notation in labelField\n this.selectedLabel = this.getFieldValue(model, this.labelField) || `${model.constructor.name} #${model.id}`;\n this.render(false);\n }\n } catch (error) {\n console.error('Error loading selected item:', error);\n }\n }\n\n async getViewData() {\n let displayValue = '';\n if (this.showDropdown && this.hasSearched) {\n displayValue = this.searchValue;\n } else if (this.selectedValue && this.selectedLabel) {\n displayValue = this.selectedLabel;\n }\n\n return {\n name: this.name,\n placeholder: this.placeholder,\n displayValue: displayValue,\n selectedValue: this.selectedValue,\n showClear: !!(this.selectedValue && this.selectedValue !== '0' && this.selectedLabel),\n hasError: this.hasError,\n errorMessage: this.errorMessage\n };\n }\n\n async onAfterRender() {\n await super.onAfterRender();\n\n // Set up stable event listeners on input\n const input = this.getInput();\n if (input) {\n input.addEventListener('input', this.handleInputEvents);\n input.addEventListener('focus', this.handleInputEvents);\n input.addEventListener('keydown', this.handleKeyDown);\n }\n\n document.addEventListener('click', this.handleDocumentClick);\n\n // Create dropdown view\n this.createDropdownView();\n }\n\n async onBeforeDestroy() {\n await super.onBeforeDestroy();\n\n const input = this.getInput();\n if (input) {\n input.removeEventListener('input', this.handleInputEvents);\n input.removeEventListener('focus', this.handleInputEvents);\n input.removeEventListener('keydown', this.handleKeyDown);\n }\n\n document.removeEventListener('click', this.handleDocumentClick);\n\n if (this.searchTimer) {\n clearTimeout(this.searchTimer);\n }\n\n if (this.dropdownView) {\n this.dropdownView.destroy();\n }\n }\n\n createDropdownView() {\n if (this.dropdownView) {\n this.dropdownView.destroy();\n }\n\n this.dropdownView = new CollectionDropdownView({\n collection: this.collection,\n labelField: this.labelField,\n valueField: this.valueField,\n selectedValue: this.selectedValue,\n loading: this.loading,\n hasSearched: this.hasSearched,\n focusedIndex: this.focusedIndex\n });\n\n this.dropdownView.on('item-selected', (data) => {\n this.selectItem(data.value, data.label);\n });\n }\n\n async handleInputEvents(event) {\n const input = event.target;\n\n if (event.type === 'focus') {\n this.showDropdown = true;\n if (!this.hasSearched && this.emptyFetch && this.collection?.isEmpty()) {\n this.performInitialFetch();\n }\n this.updateDropdown();\n } else if (event.type === 'input') {\n this.searchValue = input.value;\n this.showDropdown = true;\n this.hasSearched = true;\n this.focusedIndex = -1;\n\n if (this.searchValue !== this.selectedLabel) {\n this.selectedValue = '0';\n this.selectedLabel = '';\n this.emit('change', { value: '0', label: '' });\n }\n\n if (this.searchTimer) {\n clearTimeout(this.searchTimer);\n }\n\n this.searchTimer = setTimeout(() => {\n this.performSearch();\n }, this.debounceMs);\n\n this.updateDropdown();\n }\n }\n\n async handleActionClearSelection(event, _element) {\n event.preventDefault();\n event.stopPropagation();\n\n this.clearSelection();\n }\n\n clearSelection() {\n this.selectedValue = '0';\n this.selectedLabel = '';\n this.searchValue = '';\n this.showDropdown = false;\n this.hasError = false;\n this.focusedIndex = -1;\n this.hasSearched = false;\n\n // Update input display\n const input = this.getInput();\n if (input) {\n input.value = '';\n input.focus(); // Focus back on input after clearing\n }\n\n // Update hidden input\n const hiddenInput = this.getHiddenInput();\n if (hiddenInput) {\n hiddenInput.value = '0';\n }\n\n this.updateDropdown();\n this.render(); // Re-render to hide clear button\n this.emit('change', { value: '0', label: '' });\n }\n\n async performSearch() {\n if (!this.collection) return;\n\n // this.loading = true;\n // this.updateDropdown();\n\n try {\n const searchParams = { ...this.defaultParams };\n if (this.searchValue && this.searchValue.trim()) {\n searchParams.search = this.searchValue.trim();\n }\n await this.collection.updateParams(searchParams, true);\n } catch (error) {\n console.error('Search error:', error);\n this.loading = false;\n this.updateDropdown();\n }\n }\n\n updateDropdown() {\n if (!this.dropdownView) return;\n\n this.dropdownView.updateState({\n selectedValue: this.selectedValue,\n loading: this.loading,\n hasSearched: this.hasSearched,\n focusedIndex: this.focusedIndex\n });\n\n if (this.showDropdown) {\n if (!this.dropdownView.isMounted()) {\n const container = this.element?.querySelector('.dropdown-container');\n if (container) {\n this.dropdownView.render(true, container);\n }\n } else {\n this.dropdownView.render();\n }\n } else if (this.dropdownView.isMounted()) {\n this.dropdownView.destroy();\n this.createDropdownView();\n }\n }\n\n selectItem(value, label) {\n this.selectedValue = value;\n this.selectedLabel = label;\n this.searchValue = '';\n this.showDropdown = false;\n this.hasError = false;\n this.focusedIndex = -1;\n this.hasSearched = false;\n\n // Update input display\n const input = this.getInput();\n if (input) {\n input.value = label;\n }\n\n // Update hidden input\n const hiddenInput = this.getHiddenInput();\n if (hiddenInput) {\n hiddenInput.value = value;\n }\n\n this.updateDropdown();\n this.emit('change', { value, label });\n }\n\n handleDocumentClick(event) {\n if (!this.element?.contains(event.target)) {\n this.showDropdown = false;\n this.focusedIndex = -1;\n this.updateDropdown();\n }\n }\n\n handleKeyDown(event) {\n if (!this.showDropdown || !this.collection) return;\n\n const itemCount = this.dropdownView?.getItemCount() || 0;\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n this.focusedIndex = Math.min(this.focusedIndex + 1, itemCount - 1);\n this.dropdownView?.updateFocusedItem(this.focusedIndex);\n break;\n\n case 'ArrowUp':\n event.preventDefault();\n this.focusedIndex = Math.max(this.focusedIndex - 1, 0);\n this.dropdownView?.updateFocusedItem(this.focusedIndex);\n break;\n\n case 'Enter': {\n event.preventDefault();\n const focusedItem = this.dropdownView?.getFocusedItem();\n if (focusedItem) {\n this.selectItem(focusedItem[this.valueField], focusedItem[this.labelField]);\n }\n break;\n }\n\n case 'Escape':\n event.preventDefault();\n this.showDropdown = false;\n this.focusedIndex = -1;\n this.updateDropdown();\n break;\n }\n }\n\n // Helper methods\n getInput() {\n return this.element?.querySelector('input[type=\"text\"]');\n }\n\n getHiddenInput() {\n return this.element?.querySelector('input[type=\"hidden\"]');\n }\n\n // Public API\n setValue(value, label = '') {\n this.selectedValue = value;\n this.selectedLabel = label;\n this.searchValue = '';\n this.hasError = false;\n this.hasSearched = false;\n\n const input = this.getInput();\n if (input) {\n input.value = label;\n }\n\n const hiddenInput = this.getHiddenInput();\n if (hiddenInput) {\n hiddenInput.value = value;\n }\n }\n\n getValue() {\n // Return null if value is 0 or '0' (no selection)\n if (this.selectedValue === 0 || this.selectedValue === '0') {\n return null;\n }\n return this.selectedValue;\n }\n\n getLabel() {\n return this.selectedLabel;\n }\n\n setError(message) {\n this.hasError = true;\n this.errorMessage = message;\n this.render();\n }\n\n clearError() {\n this.hasError = false;\n this.errorMessage = '';\n this.render();\n }\n\n focus() {\n const input = this.getInput();\n if (input) {\n input.focus();\n }\n }\n\n // FormBuilder integration\n getFormValue() {\n // Return null if value is 0 or '0' (no selection)\n if (this.selectedValue === 0 || this.selectedValue === '0') {\n return null;\n }\n return this.selectedValue;\n }\n\n setFormValue(value) {\n let newValue = value;\n let newLabel = '';\n\n if (newValue && typeof newValue === 'object') {\n // Support dot notation in labelField and valueField\n newLabel = MOJOUtils.getNestedValue(newValue, this.labelField) || '';\n newValue = MOJOUtils.getNestedValue(newValue, this.valueField);\n }\n\n newValue = newValue || '0';\n\n if (newValue == this.selectedValue) {\n return;\n }\n\n this.selectedValue = newValue;\n this.selectedLabel = newLabel;\n this.searchValue = '';\n this.hasSearched = false;\n this.showDropdown = false;\n this.hasError = false;\n\n if (this.selectedValue && this.selectedValue !== '0') {\n if (!this.selectedLabel) {\n this.selectedLabel = `${this.collection.getModelName()} #${this.selectedValue}`;\n }\n this.loadSelectedItem();\n } else {\n this.render();\n }\n }\n\n /**\n * Helper method to get field value from model or plain object with dot notation support\n * @param {Object|Model} item - The item to get value from\n * @param {string} fieldPath - The field path (supports dot notation)\n * @returns {*} The field value\n */\n getFieldValue(item, fieldPath) {\n if (!item || !fieldPath) return undefined;\n\n // If item has a get() method (Model instance), try using it first\n if (typeof item.get === 'function') {\n // Try to get the value using Model's get() method\n const value = item.get(fieldPath);\n // If get() returns undefined and path has dots, fall back to MOJOUtils\n if (value === undefined && fieldPath.includes('.')) {\n return MOJOUtils.getNestedValue(item, fieldPath);\n }\n return value;\n }\n\n // For plain objects, use MOJOUtils for dot notation support\n return MOJOUtils.getNestedValue(item, fieldPath);\n }\n\n}\n\nexport default CollectionSelectView;\n","/**\n * CollectionMultiSelect - MVC multi-select component\n * \n * Architecture:\n * - CollectionMultiSelectView (parent) - Coordinates child views\n * - SearchView (child) - Search input with live search\n * - ListItemsView (child) - Checkbox list display\n */\n\nimport { View } from '@core/View.js';\nimport MOJOUtils from '@core/utils/MOJOUtils.js';\n\n/**\n * SearchView - Search input child view\n */\nclass SearchView extends View {\n constructor(options = {}) {\n super({\n tagName: 'div',\n className: 'collection-multiselect-search',\n template: `\n <input type=\"text\" \n class=\"form-control form-control-sm mb-2\" \n placeholder=\"{{placeholder}}\"\n data-change-action=\"search\"\n data-filter=\"live-search\"\n data-filter-debounce=\"{{debounce}}\" />\n `,\n ...options\n });\n\n this.placeholder = options.placeholder || 'Search...';\n this.debounce = options.debounce || 400;\n }\n\n async onChangeSearch(event, element) {\n const searchValue = element.value.trim();\n this.emit('search', searchValue);\n }\n\n getValue() {\n return this.element?.querySelector('input')?.value || '';\n }\n\n clear() {\n const input = this.element?.querySelector('input');\n if (input) input.value = '';\n }\n}\n\n/**\n * ListItemsView - Checkbox list child view\n */\nclass ListItemsView extends View {\n constructor(options = {}) {\n // Build item template based on whether custom template is provided\n const hasCustomTemplate = !!options.customItemTemplate;\n const itemContentTemplate = hasCustomTemplate \n ? `{{{customContent}}}` \n : `<span {{#disabled}}class=\"text-muted\"{{/disabled}}>{{label}}</span>`;\n\n super({\n tagName: 'div',\n className: 'collection-multiselect-items',\n template: `\n {{#loading}}\n <div class=\"text-center py-3\">\n <div class=\"spinner-border spinner-border-sm\" role=\"status\">\n <span class=\"visually-hidden\">Loading...</span>\n </div>\n </div>\n {{/loading}}\n\n {{^loading}}\n {{#items.length}}\n {{#showSelectAll}}\n <div class=\"collection-multiselect-actions d-flex justify-content-between align-items-center mb-2 py-1\">\n <button type=\"button\" \n class=\"btn btn-link btn-sm text-decoration-none p-0 {{#allSelected}}text-muted{{/allSelected}}\" \n data-action=\"select-all\"\n {{#allSelected}}disabled{{/allSelected}}>\n <i class=\"bi bi-check-square me-1\"></i>\n SELECT {{#unselectedCount}}({{unselectedCount}}){{/unselectedCount}}\n </button>\n <button type=\"button\" \n class=\"btn btn-link btn-sm text-decoration-none p-0 {{#noneSelected}}text-muted{{/noneSelected}}\" \n data-action=\"deselect-all\"\n {{#noneSelected}}disabled{{/noneSelected}}>\n DESELECT {{#selectedCount}}({{selectedCount}}){{/selectedCount}}\n <i class=\"bi bi-square ms-1\"></i>\n </button>\n </div>\n {{/showSelectAll}}\n \n <div class=\"collection-multiselect-list border rounded\" \n style=\"max-height: {{maxHeight}}px; overflow-y: auto;\">\n {{#items}}\n <div class=\"collection-multiselect-item d-flex align-items-center py-2 px-3 {{^disabled}}clickable{{/disabled}}\" \n data-action=\"{{^disabled}}toggle{{/disabled}}\"\n data-value=\"{{value}}\"\n data-index=\"{{index}}\">\n <i class=\"bi {{#selected}}bi-check-square-fill text-primary{{/selected}}{{^selected}}bi-square{{/selected}} me-2\" \n style=\"font-size: 1.1rem;\"></i>\n ${itemContentTemplate}\n </div>\n {{/items}}\n </div>\n {{/items.length}}\n\n {{^items.length}}\n <div class=\"collection-multiselect-empty text-muted text-center py-4 border rounded\">\n <i class=\"bi bi-inbox fs-3 d-block mb-2 opacity-50\"></i>\n <div>No items available</div>\n </div>\n {{/^items.length}}\n {{/loading}}\n `,\n ...options\n });\n\n this.items = options.items || [];\n this.loading = options.loading || false;\n this.maxHeight = options.maxHeight || 336;\n this.showSelectAll = options.showSelectAll !== false;\n this.selectedCount = options.selectedCount || 0;\n this.totalCount = options.totalCount || 0;\n this.unselectedCount = options.unselectedCount || 0;\n this.allSelected = options.allSelected || false;\n this.noneSelected = options.noneSelected || true;\n this.customItemTemplate = options.customItemTemplate || null;\n this.lastClickedIndex = -1;\n }\n\n handleActionToggle(event, element) {\n const value = element.getAttribute('data-value');\n const index = parseInt(element.getAttribute('data-index'), 10);\n this.emit('toggle', { value, index, shiftKey: event.shiftKey });\n this.lastClickedIndex = index;\n }\n\n async handleActionSelectAll(event) {\n event.preventDefault();\n this.emit('select-all');\n }\n\n async handleActionDeselectAll(event) {\n event.preventDefault();\n this.emit('deselect-all');\n }\n\n updateState(state) {\n Object.assign(this, state);\n }\n}\n\n/**\n * CollectionMultiSelectView - Parent coordinator view\n */\nclass CollectionMultiSelectView extends View {\n constructor(options = {}) {\n super({\n tagName: 'div',\n className: 'collection-multiselect-view',\n template: `\n <div class=\"mojo-form-control\">\n {{#label}}\n <label class=\"form-label\">\n {{label}}{{#required}}<span class=\"text-danger\">*</span>{{/required}}\n </label>\n {{/label}}\n \n <div class=\"collection-multiselect-search-container\"></div>\n <div class=\"collection-multiselect-list-container\"></div>\n\n {{#help}}\n <div class=\"form-text\">{{help}}</div>\n {{/help}}\n {{#error}}\n <div class=\"invalid-feedback d-block\">{{error}}</div>\n {{/error}}\n </div>\n `,\n ...options\n });\n\n // Basic config\n this.name = options.name || 'collection_multiselect';\n this.label = options.label || '';\n this.help = options.help || '';\n this.error = options.error || '';\n this.required = options.required || false;\n this.disabled = options.disabled || false;\n\n // Collection\n this.collection = options.collection;\n this.labelField = options.labelField || 'name';\n this.valueField = options.valueField || 'id';\n this.excludeIds = options.excludeIds || []; // Server-side filtering (deprecated)\n this.ignoreIds = options.ignoreIds || []; // Client-side filtering\n this.itemTemplate = options.itemTemplate || null; // Custom mustache template for items\n \n // Params\n this.collectionParams = options.collectionParams || {};\n this.defaultParamsOption = options.defaultParams || null;\n this.baseParams = {};\n this.requiresActiveGroup = options.requiresActiveGroup || false;\n\n // UI\n this.size = options.size || 8;\n this.maxHeight = options.maxHeight || (this.size * 42);\n this.showSelectAll = options.showSelectAll !== false;\n this.enableSearch = options.enableSearch || false;\n this.searchPlaceholder = options.searchPlaceholder || 'Search...';\n this.searchDebounce = options.searchDebounce || 400;\n\n // State\n this.selectedValues = Array.isArray(options.value) ? options.value : [];\n this.loading = false;\n this.items = [];\n\n // Child views\n this.searchView = null;\n this.listView = null;\n }\n\n onInit() {\n if (this.collection) {\n this.setupCollection();\n }\n }\n\n setupCollection() {\n // Store base params\n this.baseParams = { ...this.collection.params };\n\n // Apply collectionParams\n if (Object.keys(this.collectionParams).length > 0) {\n Object.assign(this.baseParams, this.collectionParams);\n Object.assign(this.collection.params, this.collectionParams);\n }\n\n // Apply defaultParams (dict or callback)\n if (this.defaultParamsOption) {\n const extraParams = typeof this.defaultParamsOption === 'function' \n ? this.defaultParamsOption() \n : this.defaultParamsOption;\n \n if (extraParams) {\n Object.assign(this.baseParams, extraParams);\n Object.assign(this.collection.params, extraParams);\n }\n }\n\n // Active group filter\n if (this.requiresActiveGroup) {\n const app = this.getApp();\n if (app?.activeGroup?.id) {\n this.baseParams.group = app.activeGroup.id;\n this.collection.params.group = app.activeGroup.id;\n }\n }\n\n // Collection events\n this.collection.on('fetch:start', () => {\n this.loading = true;\n this.updateListView();\n });\n\n this.collection.on('fetch:end', () => {\n this.loading = false;\n this.buildItems();\n this.updateListView();\n });\n\n // Use existing data if available\n if (!this.collection.isEmpty()) {\n this.buildItems();\n }\n }\n\n async onAfterRender() {\n await super.onAfterRender();\n\n // Create child views\n if (this.enableSearch) {\n this.createSearchView();\n }\n this.createListView();\n\n // Fetch if empty\n if (this.collection?.isEmpty()) {\n this.collection.fetch();\n }\n }\n\n createSearchView() {\n const container = this.element?.querySelector('.collection-multiselect-search-container');\n if (!container) return;\n\n this.searchView = new SearchView({\n placeholder: this.searchPlaceholder,\n debounce: this.searchDebounce\n });\n\n this.searchView.on('search', (searchValue) => {\n this.handleSearch(searchValue);\n });\n\n this.searchView.render(true, container);\n }\n\n createListView() {\n const container = this.element?.querySelector('.collection-multiselect-list-container');\n if (!container) return;\n\n const selectedCount = this.selectedValues.length;\n const totalCount = this.items.length;\n const unselectedCount = totalCount - selectedCount;\n\n this.listView = new ListItemsView({\n items: this.items,\n loading: this.loading,\n maxHeight: this.maxHeight,\n showSelectAll: this.showSelectAll,\n selectedCount,\n totalCount,\n unselectedCount,\n allSelected: selectedCount === totalCount && totalCount > 0,\n noneSelected: selectedCount === 0,\n customItemTemplate: this.itemTemplate\n });\n\n this.listView.on('toggle', (data) => {\n this.handleToggle(data);\n });\n\n this.listView.on('select-all', () => {\n this.selectAll();\n });\n\n this.listView.on('deselect-all', () => {\n this.deselectAll();\n });\n\n this.listView.render(true, container);\n }\n\n updateListView() {\n if (this.listView) {\n const selectedCount = this.selectedValues.length;\n const totalCount = this.items.length;\n const unselectedCount = totalCount - selectedCount;\n\n this.listView.updateState({\n items: this.items,\n loading: this.loading,\n selectedCount,\n totalCount,\n unselectedCount,\n allSelected: selectedCount === totalCount && totalCount > 0,\n noneSelected: selectedCount === 0\n });\n this.listView.render(false);\n }\n }\n\n // Build items array from collection\n buildItems() {\n const models = this.collection.models.filter(model => {\n const id = this.getFieldValue(model, this.valueField);\n if (id == null) return false;\n \n // Filter out excludeIds (legacy support)\n if (this.excludeIds.includes(id)) return false;\n \n // Filter out ignoreIds (client-side filtering)\n if (this.ignoreIds.some(ignoreId => ignoreId == id)) return false;\n \n return true;\n });\n\n this.items = models.map((model, index) => {\n const modelData = model.toJSON ? model.toJSON() : model;\n const value = this.getFieldValue(model, this.valueField);\n \n const item = {\n label: this.getFieldValue(model, this.labelField),\n value,\n index,\n selected: this.selectedValues.some(v => v == value),\n disabled: this.disabled,\n model: modelData // All model data nested under 'model' context\n };\n\n // Render custom template if provided\n if (this.itemTemplate) {\n item.customContent = this.renderItemTemplate(item);\n }\n\n return item;\n });\n }\n\n // Render custom item template\n renderItemTemplate(itemData) {\n if (!this.itemTemplate) return '';\n \n try {\n const Mustache = window.Mustache || this.constructor.Mustache;\n if (!Mustache) {\n console.warn('Mustache not available for item template rendering');\n return itemData.label;\n }\n return Mustache.render(this.itemTemplate, itemData);\n } catch (error) {\n console.error('Error rendering item template:', error);\n return itemData.label;\n }\n }\n\n // Get field value (supports dot notation)\n getFieldValue(item, field) {\n if (!item || !field) return undefined;\n \n if (typeof item.get === 'function') {\n return item.get(field) ?? MOJOUtils.getNestedValue(item, field);\n }\n \n return MOJOUtils.getNestedValue(item, field);\n }\n\n // Handle search\n handleSearch(searchValue) {\n const params = { ...this.baseParams };\n if (searchValue) {\n params.search = searchValue;\n }\n this.collection.updateParams(params, true);\n }\n\n // Handle item toggle\n handleToggle({ value, index, shiftKey }) {\n // Shift-click range selection\n if (shiftKey && this.listView.lastClickedIndex >= 0) {\n const start = Math.min(this.listView.lastClickedIndex, index);\n const end = Math.max(this.listView.lastClickedIndex, index);\n const shouldSelect = !this.items[index].selected;\n \n for (let i = start; i <= end; i++) {\n const item = this.items[i];\n if (!item.disabled) {\n if (shouldSelect) {\n if (!this.selectedValues.includes(item.value)) {\n this.selectedValues.push(item.value);\n }\n } else {\n this.selectedValues = this.selectedValues.filter(v => v != item.value);\n }\n item.selected = shouldSelect;\n }\n }\n } else {\n // Normal toggle\n const item = this.items[index];\n if (item.selected) {\n this.selectedValues = this.selectedValues.filter(v => v != value);\n item.selected = false;\n } else {\n this.selectedValues.push(value);\n item.selected = true;\n }\n }\n\n this.updateListView();\n this.emit('change', { value: this.selectedValues, name: this.name });\n }\n\n // Select all\n selectAll() {\n this.selectedValues = this.items.filter(i => !i.disabled).map(i => i.value);\n this.items.forEach(i => { if (!i.disabled) i.selected = true; });\n this.updateListView();\n this.emit('change', { value: this.selectedValues, name: this.name });\n }\n\n // Deselect all\n deselectAll() {\n this.selectedValues = [];\n this.items.forEach(i => i.selected = false);\n this.updateListView();\n this.emit('change', { value: this.selectedValues, name: this.name });\n }\n\n async onBeforeDestroy() {\n await super.onBeforeDestroy();\n \n if (this.searchView) {\n this.searchView.destroy();\n }\n if (this.listView) {\n this.listView.destroy();\n }\n }\n\n // Public API\n getValue() { return this.selectedValues; }\n \n setValue(values) {\n this.selectedValues = Array.isArray(values) ? values : [];\n this.buildItems();\n this.updateListView();\n }\n\n setExcludeIds(ids) {\n this.excludeIds = Array.isArray(ids) ? ids : [];\n this.buildItems();\n this.updateListView();\n }\n\n setIgnoreIds(ids) {\n this.ignoreIds = Array.isArray(ids) ? ids : [];\n this.buildItems();\n this.updateListView();\n }\n\n async refresh() {\n await this.collection.fetch();\n }\n\n getFormValue() { return this.selectedValues; }\n setFormValue(value) { this.setValue(value); }\n}\n\nexport default CollectionMultiSelectView;\n","/**\n * DatePicker - Enhanced date picker input with Easepick integration\n * Falls back to native HTML5 date input if Easepick is unavailable\n * \n * Features:\n * - Dynamic CDN loading of Easepick\n * - Configurable date formats and constraints\n * - Keyboard navigation and accessibility\n * - Form integration with FormBuilder\n * - Graceful fallback to native date input\n * \n * Example Usage:\n * ```javascript\n * const datePicker = new DatePicker({\n * name: 'birth_date',\n * value: '2023-01-15',\n * format: 'YYYY-MM-DD',\n * min: '1900-01-01',\n * max: '2030-12-31',\n * placeholder: 'Select date...'\n * });\n * ```\n */\n\nimport View from '@core/View.js';\n\nclass DatePicker extends View {\n constructor(options = {}) {\n const {\n name,\n value = '',\n format = 'YYYY-MM-DD',\n displayFormat = 'MMM DD, YYYY',\n min = null,\n max = null,\n placeholder = 'Select date...',\n disabled = false,\n readonly = false,\n required = false,\n class: containerClass = '',\n inputClass = 'form-control',\n autoApply = true,\n inline = false,\n ...viewOptions\n } = options;\n\n super({\n tagName: 'div',\n className: `date-picker-view ${containerClass}`,\n ...viewOptions\n });\n\n // Configuration\n this.name = name;\n this.format = format;\n this.displayFormat = displayFormat;\n this.min = min;\n this.max = max;\n this.placeholder = placeholder;\n this.disabled = disabled;\n this.readonly = readonly;\n this.required = required;\n this.inputClass = inputClass;\n this.autoApply = autoApply;\n this.inline = inline;\n\n // State\n this.currentValue = value;\n this.picker = null;\n this.useNative = false;\n this.easepickLoaded = false;\n\n // Check if Easepick is available\n this.checkEasepickAvailability();\n }\n\n /**\n * Check if Easepick is available and load if needed\n */\n async checkEasepickAvailability() {\n if (typeof window !== 'undefined' && window.easepick) {\n this.easepickLoaded = true;\n return true;\n }\n\n // Try to load Easepick from CDN\n try {\n await this.loadEasepick();\n this.easepickLoaded = true;\n return true;\n } catch (error) {\n console.warn('Easepick failed to load, falling back to native date input:', error);\n this.useNative = true;\n return false;\n }\n }\n\n /**\n * Dynamically load Easepick from CDN\n */\n async loadEasepick() {\n return new Promise((resolve, reject) => {\n // Check if already loaded\n if (window.easepick) {\n resolve();\n return;\n }\n\n // Load CSS first\n const css = document.createElement('link');\n css.rel = 'stylesheet';\n css.href = 'https://cdn.jsdelivr.net/npm/@easepick/bundle@1.2.1/dist/index.css';\n document.head.appendChild(css);\n\n // Load JavaScript\n const script = document.createElement('script');\n script.src = 'https://cdn.jsdelivr.net/npm/@easepick/bundle@1.2.1/dist/index.umd.min.js';\n script.onload = () => {\n if (window.easepick) {\n resolve();\n } else {\n reject(new Error('Easepick not available after loading'));\n }\n };\n script.onerror = () => reject(new Error('Failed to load Easepick script'));\n document.head.appendChild(script);\n });\n }\n\n /**\n * Render the date picker component\n */\n async renderTemplate() {\n const inputId = this.getInputId();\n const inputType = this.useNative ? 'date' : 'text';\n const inputValue = this.formatValueForInput(this.currentValue);\n \n return `\n <div class=\"date-picker-container\">\n <input \n type=\"${inputType}\"\n id=\"${inputId}\"\n name=\"${this.name || ''}\"\n class=\"${this.inputClass}${this.hasError() ? ' is-invalid' : ''}\"\n value=\"${this.escapeHtml(inputValue)}\"\n placeholder=\"${this.escapeHtml(this.placeholder)}\"\n ${this.min ? `min=\"${this.min}\"` : ''}\n ${this.max ? `max=\"${this.max}\"` : ''}\n ${this.disabled ? 'disabled' : ''}\n ${this.readonly ? 'readonly' : ''}\n ${this.required ? 'required' : ''}\n autocomplete=\"off\"\n data-change-action=\"date-changed\"\n />\n <div class=\"date-picker-feedback\"></div>\n </div>\n `;\n }\n\n /**\n * Initialize after render\n */\n async onAfterRender() {\n await super.onAfterRender();\n \n if (this.easepickLoaded && !this.useNative) {\n await this.initializeEasepick();\n } else {\n this.initializeNativeFallback();\n }\n }\n\n /**\n * Initialize Easepick date picker\n */\n async initializeEasepick() {\n const input = this.getInputElement();\n if (!input || !window.easepick) return;\n\n try {\n const config = {\n element: input,\n css: [\n 'https://cdn.jsdelivr.net/npm/@easepick/bundle@1.2.1/dist/index.css',\n ],\n format: this.displayFormat,\n lang: 'en-US',\n autoApply: this.autoApply,\n inline: this.inline,\n readonly: this.readonly,\n zIndex: 9999,\n };\n\n // Add date constraints\n if (this.min) {\n config.minDate = new Date(this.min);\n }\n if (this.max) {\n config.maxDate = new Date(this.max);\n }\n\n // Add event handlers\n config.setup = (picker) => {\n picker.on('select', (e) => {\n const date = e.detail.date;\n this.handleDateChange(date ? this.formatDate(date, this.format) : '');\n });\n\n picker.on('clear', () => {\n this.handleDateChange('');\n });\n\n picker.on('show', () => {\n this.emit('picker:show');\n });\n\n picker.on('hide', () => {\n this.emit('picker:hide');\n });\n };\n\n this.picker = new window.easepick.create(config);\n\n // Set initial value if provided\n if (this.currentValue) {\n this.picker.setDate(this.currentValue);\n }\n\n } catch (error) {\n console.error('Failed to initialize Easepick:', error);\n this.useNative = true;\n this.initializeNativeFallback();\n }\n }\n\n /**\n * Initialize native HTML5 date input fallback\n */\n initializeNativeFallback() {\n const input = this.getInputElement();\n if (!input) return;\n\n // Convert to HTML5 date format if needed\n input.type = 'date';\n if (this.currentValue) {\n input.value = this.formatDate(this.currentValue, 'YYYY-MM-DD');\n }\n }\n\n // ========================================\n // Event Handlers\n // ========================================\n\n /**\n * Handle date change from input\n */\n async onChangeDateChanged(action, event, element) {\n const value = element.value;\n this.handleDateChange(value);\n }\n\n /**\n * Handle date change logic\n */\n handleDateChange(value) {\n const oldValue = this.currentValue;\n this.currentValue = value;\n\n // Update hidden input if exists\n this.updateHiddenInput();\n\n // Emit change events\n if (oldValue !== value) {\n this.emit('change', { \n value: value, \n formatted: this.formatValueForDisplay(value),\n oldValue: oldValue \n });\n this.emit('date:changed', { value, oldValue });\n }\n }\n\n // ========================================\n // Utility Methods\n // ========================================\n\n /**\n * Format date for different contexts\n */\n formatDate(date, format = this.format) {\n if (!date) return '';\n \n // Simple date formatting (can be enhanced)\n const d = new Date(date);\n if (isNaN(d.getTime())) return '';\n\n const year = d.getFullYear();\n const month = String(d.getMonth() + 1).padStart(2, '0');\n const day = String(d.getDate()).padStart(2, '0');\n \n switch (format) {\n case 'YYYY-MM-DD':\n return `${year}-${month}-${day}`;\n case 'MM/DD/YYYY':\n return `${month}/${day}/${year}`;\n case 'DD/MM/YYYY':\n return `${day}/${month}/${year}`;\n case 'MMM DD, YYYY':\n const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\n 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\n return `${monthNames[d.getMonth()]} ${day}, ${year}`;\n default:\n return `${year}-${month}-${day}`;\n }\n }\n\n /**\n * Format value for input display\n */\n formatValueForInput(value) {\n if (!value) return '';\n return this.useNative ? this.formatDate(value, 'YYYY-MM-DD') : value;\n }\n\n /**\n * Format value for display\n */\n formatValueForDisplay(value) {\n if (!value) return '';\n return this.formatDate(value, this.displayFormat);\n }\n\n /**\n * Get unique input ID\n */\n getInputId() {\n return this.name ? `datepicker_${this.name}_${Date.now()}` : `datepicker_${Date.now()}`;\n }\n\n /**\n * Get input element\n */\n getInputElement() {\n return this.element?.querySelector('input');\n }\n\n /**\n * Update hidden input for form submission\n */\n updateHiddenInput() {\n // This method can be used if we need a separate hidden input\n // for form submission with a different format\n }\n\n /**\n * Check if field has error\n */\n hasError() {\n return false; // Can be enhanced with validation\n }\n\n /**\n * Escape HTML to prevent XSS\n */\n escapeHtml(str) {\n if (str == null) return '';\n const div = document.createElement('div');\n div.textContent = String(str);\n return div.innerHTML;\n }\n\n // ========================================\n // Public API Methods\n // ========================================\n\n /**\n * Set the date value\n */\n setValue(value) {\n this.currentValue = value;\n \n if (this.picker && this.easepickLoaded) {\n this.picker.setDate(value || null);\n } else {\n const input = this.getInputElement();\n if (input) {\n input.value = this.formatValueForInput(value);\n }\n }\n \n this.emit('value:set', { value });\n }\n\n /**\n * Get the current date value\n */\n getValue() {\n return this.currentValue;\n }\n\n /**\n * Get formatted date value\n */\n getFormattedValue(format = this.displayFormat) {\n return this.formatDate(this.currentValue, format);\n }\n\n /**\n * Clear the date value\n */\n clear() {\n this.setValue('');\n }\n\n /**\n * Set min date constraint\n */\n setMin(minDate) {\n this.min = minDate;\n if (this.picker && this.easepickLoaded) {\n this.picker.options.minDate = new Date(minDate);\n } else {\n const input = this.getInputElement();\n if (input) {\n input.min = minDate;\n }\n }\n }\n\n /**\n * Set max date constraint\n */\n setMax(maxDate) {\n this.max = maxDate;\n if (this.picker && this.easepickLoaded) {\n this.picker.options.maxDate = new Date(maxDate);\n } else {\n const input = this.getInputElement();\n if (input) {\n input.max = maxDate;\n }\n }\n }\n\n /**\n * Enable/disable the picker\n */\n setEnabled(enabled) {\n this.disabled = !enabled;\n const input = this.getInputElement();\n if (input) {\n input.disabled = this.disabled;\n }\n if (this.picker && this.easepickLoaded) {\n // Easepick doesn't have direct disable method, so we handle it via input\n if (this.disabled) {\n this.picker.hide();\n }\n }\n }\n\n /**\n * Set readonly state\n */\n setReadonly(readonly) {\n this.readonly = readonly;\n const input = this.getInputElement();\n if (input) {\n input.readonly = readonly;\n }\n }\n\n /**\n * Focus the input\n */\n focus() {\n const input = this.getInputElement();\n if (input) {\n input.focus();\n }\n }\n\n /**\n * Show the picker (if using Easepick)\n */\n show() {\n if (this.picker && this.easepickLoaded) {\n this.picker.show();\n }\n }\n\n /**\n * Hide the picker (if using Easepick)\n */\n hide() {\n if (this.picker && this.easepickLoaded) {\n this.picker.hide();\n }\n }\n\n // ========================================\n // FormBuilder Integration\n // ========================================\n\n /**\n * Get form value (for FormBuilder integration)\n */\n getFormValue() {\n return this.getValue();\n }\n\n /**\n * Set form value (for FormBuilder integration)\n */\n async setFormValue(value) {\n this.setValue(value);\n }\n\n // ========================================\n // Lifecycle Methods\n // ========================================\n\n /**\n * Cleanup when component is destroyed\n */\n async onBeforeDestroy() {\n if (this.picker && this.easepickLoaded) {\n try {\n this.picker.destroy();\n } catch (error) {\n console.warn('Error destroying Easepick instance:', error);\n }\n }\n \n this.picker = null;\n await super.onBeforeDestroy();\n }\n\n /**\n * Static factory method\n */\n static create(options = {}) {\n return new DatePicker(options);\n }\n}\n\nexport default DatePicker;","/**\n * DateRangePicker - Enhanced date range picker with Easepick integration\n * Falls back to two native HTML5 date inputs if Easepick is unavailable\n * \n * Features:\n * - Dynamic CDN loading of Easepick\n * - Start and end date validation\n * - Configurable date formats and constraints\n * - Keyboard navigation and accessibility\n * - Form integration with FormBuilder\n * - Graceful fallback to native date inputs\n * \n * Example Usage:\n * ```javascript\n * const dateRangePicker = new DateRangePicker({\n * name: 'date_range',\n * startDate: '2023-01-01',\n * endDate: '2023-01-31',\n * format: 'YYYY-MM-DD',\n * min: '2020-01-01',\n * max: '2030-12-31',\n * placeholder: 'Select date range...'\n * });\n * ```\n */\n\nimport View from '@core/View.js';\n\nclass DateRangePicker extends View {\n constructor(options = {}) {\n const {\n name,\n startName,\n endName,\n fieldName,\n startDate = '',\n endDate = '',\n format = 'YYYY-MM-DD',\n displayFormat = 'MMM DD, YYYY',\n outputFormat = 'date', // 'date', 'epoch', 'iso'\n min = null,\n max = null,\n placeholder = 'Select date range...',\n startPlaceholder = 'Start date...',\n endPlaceholder = 'End date...',\n disabled = false,\n readonly = false,\n required = false,\n class: containerClass = '',\n inputClass = 'form-control',\n autoApply = true,\n inline = false,\n separator = ' - ',\n ...viewOptions\n } = options;\n\n super({\n tagName: 'div',\n className: `date-range-picker-view ${containerClass}`,\n ...viewOptions\n });\n\n // Configuration\n this.name = name;\n this.startName = startName;\n this.endName = endName;\n this.fieldName = fieldName;\n this.format = format;\n this.displayFormat = displayFormat;\n this.outputFormat = outputFormat;\n this.min = min;\n this.max = max;\n this.placeholder = placeholder;\n this.startPlaceholder = startPlaceholder;\n this.endPlaceholder = endPlaceholder;\n this.disabled = disabled;\n this.readonly = readonly;\n this.required = required;\n this.inputClass = inputClass;\n this.autoApply = autoApply;\n this.inline = inline;\n this.separator = separator;\n\n // State\n this.currentStartDate = startDate;\n this.currentEndDate = endDate;\n this.picker = null;\n this.useNative = false;\n this.easepickLoaded = false;\n\n // Check if Easepick is available\n this.checkEasepickAvailability();\n }\n\n /**\n * Check if Easepick is available and load if needed\n */\n async checkEasepickAvailability() {\n if (typeof window !== 'undefined' && window.easepick) {\n this.easepickLoaded = true;\n return true;\n }\n\n // Try to load Easepick from CDN\n try {\n await this.loadEasepick();\n this.easepickLoaded = true;\n return true;\n } catch (error) {\n console.warn('Easepick failed to load, falling back to native date inputs:', error);\n this.useNative = true;\n return false;\n }\n }\n\n /**\n * Dynamically load Easepick from CDN\n */\n async loadEasepick() {\n return new Promise((resolve, reject) => {\n // Check if already loaded\n if (window.easepick) {\n resolve();\n return;\n }\n\n // Load CSS first\n const css = document.createElement('link');\n css.rel = 'stylesheet';\n css.href = 'https://cdn.jsdelivr.net/npm/@easepick/bundle@1.2.1/dist/index.css';\n document.head.appendChild(css);\n\n // Load JavaScript\n const script = document.createElement('script');\n script.src = 'https://cdn.jsdelivr.net/npm/@easepick/bundle@1.2.1/dist/index.umd.min.js';\n script.onload = () => {\n if (window.easepick) {\n resolve();\n } else {\n reject(new Error('Easepick not available after loading'));\n }\n };\n script.onerror = () => reject(new Error('Failed to load Easepick script'));\n document.head.appendChild(script);\n });\n }\n\n /**\n * Render the date range picker component\n */\n async renderTemplate() {\n const inputId = this.getInputId();\n const displayValue = this.getDisplayValue();\n \n if (this.useNative) {\n // Render two separate date inputs for native fallback\n return this.renderNativeTemplate(inputId);\n }\n\n // Determine field names\n const startFieldName = this.startName || (this.name ? `${this.name}_start` : '');\n const endFieldName = this.endName || (this.name ? `${this.name}_end` : '');\n \n // Get formatted values for output\n const startValue = this.currentStartDate ? this.formatForOutput(this.currentStartDate) : '';\n const endValue = this.currentEndDate ? this.formatForOutput(this.currentEndDate) : '';\n\n return `\n <div class=\"date-range-picker-container\">\n <input \n type=\"text\"\n id=\"${inputId}\"\n ${this.name ? `name=\"${this.name}\"` : ''}\n class=\"${this.inputClass} date-range-picker-input${this.hasError() ? ' is-invalid' : ''}\"\n value=\"${this.escapeHtml(displayValue)}\"\n placeholder=\"${this.escapeHtml(this.placeholder)}\"\n ${this.disabled ? 'disabled' : ''}\n ${this.readonly ? 'readonly' : ''}\n ${this.required ? 'required' : ''}\n autocomplete=\"off\"\n data-change-action=\"range-changed\"\n style=\"background-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 16 16%22><path fill=%22%236c757d%22 fill-rule=%22evenodd%22 d=%22M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z%22/></svg>'); background-repeat: no-repeat; background-position: right 0.75rem center; background-size: 16px 12px; padding-right: 2.25rem; cursor: pointer;\"\n />\n \n <!-- Hidden inputs for form submission -->\n ${startFieldName ? `<input type=\"hidden\" name=\"${startFieldName}\" value=\"${this.escapeHtml(startValue)}\" />` : ''}\n ${endFieldName ? `<input type=\"hidden\" name=\"${endFieldName}\" value=\"${this.escapeHtml(endValue)}\" />` : ''}\n ${this.fieldName ? `<input type=\"hidden\" name=\"${this.fieldName}\" value=\"${this.escapeHtml(this.name || '')}\" />` : ''}\n \n <div class=\"date-range-picker-feedback\"></div>\n </div>\n `;\n }\n\n /**\n * Render native fallback template with two date inputs\n */\n renderNativeTemplate(inputId) {\n return `\n <div class=\"date-range-picker-container date-range-native\">\n <div class=\"row g-2\">\n <div class=\"col\">\n <input \n type=\"date\"\n id=\"${inputId}_start\"\n name=\"${this.name}_start\"\n class=\"${this.inputClass}${this.hasError() ? ' is-invalid' : ''}\"\n value=\"${this.escapeHtml(this.formatDate(this.currentStartDate, 'YYYY-MM-DD'))}\"\n placeholder=\"${this.escapeHtml(this.startPlaceholder)}\"\n ${this.min ? `min=\"${this.min}\"` : ''}\n ${this.max ? `max=\"${this.max}\"` : ''}\n ${this.disabled ? 'disabled' : ''}\n ${this.readonly ? 'readonly' : ''}\n ${this.required ? 'required' : ''}\n data-change-action=\"start-date-changed\"\n />\n </div>\n <div class=\"col-auto d-flex align-items-center\">\n <span class=\"text-muted\">${this.escapeHtml(this.separator.trim())}</span>\n </div>\n <div class=\"col\">\n <input \n type=\"date\"\n id=\"${inputId}_end\"\n name=\"${this.name}_end\"\n class=\"${this.inputClass}${this.hasError() ? ' is-invalid' : ''}\"\n value=\"${this.escapeHtml(this.formatDate(this.currentEndDate, 'YYYY-MM-DD'))}\"\n placeholder=\"${this.escapeHtml(this.endPlaceholder)}\"\n ${this.min ? `min=\"${this.min}\"` : ''}\n ${this.max ? `max=\"${this.max}\"` : ''}\n ${this.disabled ? 'disabled' : ''}\n ${this.readonly ? 'readonly' : ''}\n ${this.required ? 'required' : ''}\n data-change-action=\"end-date-changed\"\n />\n </div>\n </div>\n \n <!-- Hidden input for combined value -->\n <input type=\"hidden\" name=\"${this.name}\" value=\"${this.escapeHtml(this.getCombinedValue())}\" />\n ${this.fieldName ? `<input type=\"hidden\" name=\"${this.fieldName}\" value=\"${this.escapeHtml(this.name || '')}\" />` : ''}\n \n <div class=\"date-range-picker-feedback\"></div>\n </div>\n `;\n }\n\n /**\n * Initialize after render\n */\n async onAfterRender() {\n await super.onAfterRender();\n \n if (this.easepickLoaded && !this.useNative) {\n await this.initializeEasepick();\n } else {\n this.initializeNativeFallback();\n }\n }\n\n /**\n * Initialize Easepick date range picker\n */\n async initializeEasepick() {\n const input = this.getInputElement();\n if (!input || !window.easepick) return;\n\n try {\n const config = {\n element: input,\n css: [\n 'https://cdn.jsdelivr.net/npm/@easepick/bundle@1.2.1/dist/index.css',\n ],\n format: this.displayFormat,\n lang: 'en-US',\n autoApply: this.autoApply,\n inline: this.inline,\n readonly: this.readonly,\n zIndex: 9999,\n plugins: ['RangePlugin'],\n RangePlugin: {\n tooltip: true,\n locale: {\n one: 'day',\n other: 'days'\n }\n }\n };\n\n // Add date constraints\n if (this.min) {\n config.minDate = new Date(this.min);\n }\n if (this.max) {\n config.maxDate = new Date(this.max);\n }\n\n // Add event handlers\n config.setup = (picker) => {\n picker.on('select', (e) => {\n const { start, end } = e.detail;\n // Easepick returns DateTime objects, convert to local date strings\n const startDate = start ? this.normalizeDateFromPicker(start) : '';\n const endDate = end ? this.normalizeDateFromPicker(end) : '';\n this.handleRangeChange(startDate, endDate);\n });\n\n picker.on('clear', () => {\n this.handleRangeChange('', '');\n });\n\n picker.on('show', () => {\n this.emit('picker:show');\n });\n\n picker.on('hide', () => {\n this.emit('picker:hide');\n });\n };\n\n this.picker = new window.easepick.create(config);\n\n // Set initial value if provided\n if (this.currentStartDate && this.currentEndDate) {\n this.picker.setDateRange(this.currentStartDate, this.currentEndDate);\n }\n\n } catch (error) {\n console.error('Failed to initialize Easepick range picker:', error);\n this.useNative = true;\n await this.render(); // Re-render with native template\n this.initializeNativeFallback();\n }\n }\n\n /**\n * Initialize native HTML5 date inputs fallback\n */\n initializeNativeFallback() {\n // Native inputs are already set up in template\n // Just ensure proper constraint relationships\n this.updateConstraints();\n }\n\n // ========================================\n // Event Handlers\n // ========================================\n\n /**\n * Handle range change from Easepick\n */\n async onChangeRangeChanged(_action, _event, _element) {\n // This is handled by Easepick setup callback\n }\n\n /**\n * Handle start date change in native mode\n */\n async onChangeStartDateChanged(action, event, element) {\n const startDate = element.value;\n this.handleRangeChange(startDate, this.currentEndDate);\n this.updateConstraints();\n }\n\n /**\n * Handle end date change in native mode\n */\n async onChangeEndDateChanged(action, event, element) {\n const endDate = element.value;\n this.handleRangeChange(this.currentStartDate, endDate);\n this.updateConstraints();\n }\n\n /**\n * Handle date range change logic\n */\n handleRangeChange(startDate, endDate) {\n const oldStartDate = this.currentStartDate;\n const oldEndDate = this.currentEndDate;\n \n this.currentStartDate = startDate;\n this.currentEndDate = endDate;\n\n // Update hidden inputs\n this.updateHiddenInputs();\n\n // Emit change events\n if (oldStartDate !== startDate || oldEndDate !== endDate) {\n this.emit('change', {\n startDate,\n endDate,\n combined: this.getCombinedValue(),\n formatted: this.getDisplayValue(),\n oldStartDate,\n oldEndDate\n });\n \n this.emit('range:changed', {\n startDate,\n endDate,\n oldStartDate,\n oldEndDate\n });\n }\n }\n\n /**\n * Update constraints for native inputs\n */\n updateConstraints() {\n if (!this.useNative) return;\n\n const startInput = this.element?.querySelector(`[name=\"${this.name}_start\"]`);\n const endInput = this.element?.querySelector(`[name=\"${this.name}_end\"]`);\n\n if (startInput && endInput) {\n // End date should be >= start date\n if (this.currentStartDate) {\n endInput.min = this.currentStartDate;\n }\n \n // Start date should be <= end date\n if (this.currentEndDate) {\n startInput.max = this.currentEndDate;\n }\n }\n }\n\n // ========================================\n // Utility Methods\n // ========================================\n\n /**\n * Normalize date from Easepick DateTime object\n * Easepick DateTime objects may have timezone issues, so extract the date components directly\n */\n normalizeDateFromPicker(dateObj) {\n if (!dateObj) return '';\n \n // If it's an Easepick DateTime object, it has a toJSDate() method\n if (typeof dateObj.toJSDate === 'function') {\n const jsDate = dateObj.toJSDate();\n return this.formatDate(jsDate, this.format);\n }\n \n // If it has getFullYear/getMonth/getDate methods (like DateTime)\n if (typeof dateObj.getFullYear === 'function') {\n const year = dateObj.getFullYear();\n const month = String(dateObj.getMonth() + 1).padStart(2, '0');\n const day = String(dateObj.getDate()).padStart(2, '0');\n \n switch (this.format) {\n case 'YYYY-MM-DD':\n return `${year}-${month}-${day}`;\n case 'MM/DD/YYYY':\n return `${month}/${day}/${year}`;\n case 'DD/MM/YYYY':\n return `${day}/${month}/${year}`;\n default:\n return `${year}-${month}-${day}`;\n }\n }\n \n // Fallback to formatDate\n return this.formatDate(dateObj, this.format);\n }\n\n /**\n * Format date for different contexts\n */\n formatDate(date, format = this.format) {\n if (!date) return '';\n \n let year, month, day, d;\n \n // If date is a YYYY-MM-DD string, parse it manually to avoid timezone issues\n if (typeof date === 'string' && /^\\d{4}-\\d{2}-\\d{2}$/.test(date)) {\n const parts = date.split('-');\n year = parseInt(parts[0]);\n month = String(parseInt(parts[1])).padStart(2, '0');\n day = String(parseInt(parts[2])).padStart(2, '0');\n } else {\n // Handle Date objects or other string formats\n if (date instanceof Date) {\n d = date;\n } else {\n d = new Date(date);\n }\n \n if (isNaN(d.getTime())) return '';\n\n // Use getFullYear, getMonth, getDate (local time methods)\n year = d.getFullYear();\n month = String(d.getMonth() + 1).padStart(2, '0');\n day = String(d.getDate()).padStart(2, '0');\n }\n \n switch (format) {\n case 'YYYY-MM-DD':\n return `${year}-${month}-${day}`;\n case 'MM/DD/YYYY':\n return `${month}/${day}/${year}`;\n case 'DD/MM/YYYY':\n return `${day}/${month}/${year}`;\n case 'MMM DD, YYYY': {\n const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\n 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\n const monthIndex = parseInt(month) - 1;\n return `${monthNames[monthIndex]} ${day}, ${year}`;\n }\n default:\n return `${year}-${month}-${day}`;\n }\n }\n\n /**\n * Format date for output based on outputFormat setting\n */\n formatForOutput(date) {\n if (!date) return '';\n \n // If date is already a string in YYYY-MM-DD format, don't re-parse it\n // to avoid timezone issues\n if (typeof date === 'string' && /^\\d{4}-\\d{2}-\\d{2}$/.test(date)) {\n switch (this.outputFormat) {\n case 'epoch':\n // For epoch, we need to parse but use local midnight\n const parts = date.split('-');\n const d = new Date(parseInt(parts[0]), parseInt(parts[1]) - 1, parseInt(parts[2]));\n return Math.floor(d.getTime() / 1000).toString();\n case 'iso':\n return new Date(date + 'T00:00:00').toISOString();\n case 'date':\n default:\n return date; // Already in the correct format\n }\n }\n \n // For Date objects or other formats, parse and convert\n const d = new Date(date);\n if (isNaN(d.getTime())) return '';\n\n switch (this.outputFormat) {\n case 'epoch':\n return Math.floor(d.getTime() / 1000).toString();\n case 'iso':\n return d.toISOString();\n case 'date':\n default:\n return this.formatDate(date, this.format);\n }\n }\n\n /**\n * Get display value for the input\n */\n getDisplayValue() {\n if (!this.currentStartDate && !this.currentEndDate) return '';\n \n const startFormatted = this.currentStartDate ? \n this.formatDate(this.currentStartDate, this.displayFormat) : '';\n const endFormatted = this.currentEndDate ? \n this.formatDate(this.currentEndDate, this.displayFormat) : '';\n\n if (startFormatted && endFormatted) {\n return `${startFormatted}${this.separator}${endFormatted}`;\n } else if (startFormatted) {\n return startFormatted;\n } else if (endFormatted) {\n return endFormatted;\n }\n \n return '';\n }\n\n /**\n * Get combined value for form submission\n */\n getCombinedValue() {\n if (!this.currentStartDate && !this.currentEndDate) return '';\n \n return JSON.stringify({\n start: this.currentStartDate,\n end: this.currentEndDate\n });\n }\n\n /**\n * Get unique input ID\n */\n getInputId() {\n return this.name ? `daterange_${this.name}_${Date.now()}` : `daterange_${Date.now()}`;\n }\n\n /**\n * Get main input element\n */\n getInputElement() {\n return this.element?.querySelector('input[type=\"text\"], input[name=\"' + this.name + '\"]');\n }\n\n /**\n * Update hidden inputs for form submission\n */\n updateHiddenInputs() {\n const startFieldName = this.startName || (this.name ? `${this.name}_start` : '');\n const endFieldName = this.endName || (this.name ? `${this.name}_end` : '');\n \n const startInput = startFieldName ? this.element?.querySelector(`[name=\"${startFieldName}\"]`) : null;\n const endInput = endFieldName ? this.element?.querySelector(`[name=\"${endFieldName}\"]`) : null;\n const combinedInput = this.name ? this.element?.querySelector(`[name=\"${this.name}\"]`) : null;\n const fieldNameInput = this.fieldName ? this.element?.querySelector(`[name=\"${this.fieldName}\"]`) : null;\n\n const startValue = this.currentStartDate ? this.formatForOutput(this.currentStartDate) : '';\n const endValue = this.currentEndDate ? this.formatForOutput(this.currentEndDate) : '';\n \n if (startInput) startInput.value = startValue;\n if (endInput) endInput.value = endValue;\n if (combinedInput) combinedInput.value = this.getDisplayValue();\n if (fieldNameInput) fieldNameInput.value = this.name || '';\n }\n\n /**\n * Check if field has error\n */\n hasError() {\n // Basic validation: end date should be after start date\n if (this.currentStartDate && this.currentEndDate) {\n return new Date(this.currentEndDate) < new Date(this.currentStartDate);\n }\n return false;\n }\n\n /**\n * Escape HTML to prevent XSS\n */\n escapeHtml(str) {\n if (str == null) return '';\n const div = document.createElement('div');\n div.textContent = String(str);\n return div.innerHTML;\n }\n\n // ========================================\n // Public API Methods\n // ========================================\n\n /**\n * Set the date range values\n */\n setRange(startDate, endDate) {\n this.currentStartDate = startDate;\n this.currentEndDate = endDate;\n \n if (this.picker && this.easepickLoaded) {\n this.picker.setDateRange(startDate || null, endDate || null);\n } else if (this.useNative) {\n const startInput = this.element?.querySelector(`[name=\"${this.name}_start\"]`);\n const endInput = this.element?.querySelector(`[name=\"${this.name}_end\"]`);\n \n if (startInput) startInput.value = this.formatDate(startDate, 'YYYY-MM-DD');\n if (endInput) endInput.value = this.formatDate(endDate, 'YYYY-MM-DD');\n } else {\n const input = this.getInputElement();\n if (input) {\n input.value = this.getDisplayValue();\n }\n }\n \n this.updateHiddenInputs();\n this.emit('range:set', { startDate, endDate });\n }\n\n /**\n * Get the current date range\n */\n getRange() {\n return {\n start: this.currentStartDate,\n end: this.currentEndDate,\n combined: this.getCombinedValue()\n };\n }\n\n /**\n * Clear the date range\n */\n clear() {\n this.setRange('', '');\n }\n\n /**\n * Set start date only\n */\n setStartDate(startDate) {\n this.setRange(startDate, this.currentEndDate);\n }\n\n /**\n * Set end date only\n */\n setEndDate(endDate) {\n this.setRange(this.currentStartDate, endDate);\n }\n\n /**\n * Get start date\n */\n getStartDate() {\n return this.currentStartDate;\n }\n\n /**\n * Get end date\n */\n getEndDate() {\n return this.currentEndDate;\n }\n\n /**\n * Enable/disable the picker\n */\n setEnabled(enabled) {\n this.disabled = !enabled;\n const inputs = this.element?.querySelectorAll('input');\n inputs?.forEach(input => {\n input.disabled = this.disabled;\n });\n }\n\n /**\n * Set readonly state\n */\n setReadonly(readonly) {\n this.readonly = readonly;\n const inputs = this.element?.querySelectorAll('input:not([type=\"hidden\"])');\n inputs?.forEach(input => {\n input.readonly = readonly;\n });\n }\n\n /**\n * Focus the input\n */\n focus() {\n const input = this.getInputElement();\n if (input) {\n input.focus();\n }\n }\n\n /**\n * Show the picker (if using Easepick)\n */\n show() {\n if (this.picker && this.easepickLoaded) {\n this.picker.show();\n }\n }\n\n /**\n * Hide the picker (if using Easepick)\n */\n hide() {\n if (this.picker && this.easepickLoaded) {\n this.picker.hide();\n }\n }\n\n // ========================================\n // FormBuilder Integration\n // ========================================\n\n /**\n * Get form value (for FormBuilder integration)\n */\n getFormValue() {\n return this.getRange();\n }\n\n /**\n * Set form value (for FormBuilder integration)\n */\n async setFormValue(value) {\n if (typeof value === 'string') {\n try {\n const parsed = JSON.parse(value);\n this.setRange(parsed.start, parsed.end);\n } catch {\n // If not JSON, treat as start date only\n this.setRange(value, '');\n }\n } else if (value && typeof value === 'object') {\n this.setRange(value.start || '', value.end || '');\n }\n }\n\n // ========================================\n // Lifecycle Methods\n // ========================================\n\n /**\n * Cleanup when component is destroyed\n */\n async onBeforeDestroy() {\n if (this.picker && this.easepickLoaded) {\n try {\n this.picker.destroy();\n } catch (error) {\n console.warn('Error destroying Easepick range picker instance:', error);\n }\n }\n \n this.picker = null;\n await super.onBeforeDestroy();\n }\n\n /**\n * Static factory method\n */\n static create(options = {}) {\n return new DateRangePicker(options);\n }\n}\n\nexport default DateRangePicker;","/**\n * ComboInput - Editable select/autocomplete component for MOJO framework\n * Combines a text input with a dropdown of suggestions\n * Users can either select from the dropdown or type custom values\n *\n * Features:\n * - Autocomplete with filtering\n * - Keyboard navigation (Arrow keys, Enter, Escape)\n * - Custom value entry\n * - Bootstrap 5 styling\n * - Form integration\n * - Optional metadata support (display label but store value)\n *\n * Example Usage:\n * ```javascript\n * const comboInput = new ComboInput({\n * name: 'field_name',\n * value: 'level',\n * placeholder: 'Select or enter field name...',\n * options: [\n * { value: 'level', label: 'Level (error, warning, info)', meta: { type: 'str' } },\n * { value: 'source_ip', label: 'Source IP Address', meta: { type: 'str' } }\n * ],\n * allowCustom: true,\n * showDescription: true\n * });\n * ```\n */\n\nimport View from '@core/View.js';\n\nclass ComboInput extends View {\n constructor(options = {}) {\n const {\n name,\n value = '',\n placeholder = 'Select or type...',\n options: optionsList = [],\n allowCustom = true,\n showDescription = true,\n minChars = 0, // Minimum characters before showing suggestions\n maxSuggestions = 10,\n disabled = false,\n readonly = false,\n required = false,\n class: containerClass = '',\n inputClass = 'form-control',\n onSelect = null, // Callback when option is selected\n onChange = null, // Callback when value changes\n ...viewOptions\n } = options;\n\n super({\n tagName: 'div',\n className: `combo-input ${containerClass}`,\n ...viewOptions\n });\n\n // Configuration\n this.name = name;\n this.placeholder = placeholder;\n this.options = this.normalizeOptions(optionsList);\n this.allowCustom = allowCustom;\n this.showDescription = showDescription;\n this.minChars = minChars;\n this.maxSuggestions = maxSuggestions;\n this.disabled = disabled;\n this.readonly = readonly;\n this.required = required;\n this.inputClass = inputClass;\n this.onSelectCallback = onSelect;\n this.onChangeCallback = onChange;\n\n // State\n this.currentValue = value;\n this.inputValue = this.getDisplayValue(value);\n this.filteredOptions = [];\n this.highlightedIndex = -1;\n this.isOpen = false;\n this.selectedOption = this.findOptionByValue(value);\n }\n\n /**\n * Normalize options to consistent format\n */\n normalizeOptions(options) {\n if (!Array.isArray(options)) return [];\n\n return options.map(opt => {\n if (typeof opt === 'string') {\n return { value: opt, label: opt };\n } else if (typeof opt === 'object' && opt.value !== undefined) {\n return {\n value: opt.value,\n label: opt.label || String(opt.value),\n description: opt.description || opt.label || '',\n meta: opt.meta || {}\n };\n }\n return null;\n }).filter(opt => opt !== null);\n }\n\n /**\n * Find option by value\n */\n findOptionByValue(value) {\n return this.options.find(opt => opt.value === value) || null;\n }\n\n /**\n * Get display value for a given value\n */\n getDisplayValue(value) {\n const option = this.findOptionByValue(value);\n return option ? option.label : value;\n }\n\n /**\n * Render the combo input component\n */\n async renderTemplate() {\n return `\n <div class=\"combo-input-container position-relative\">\n <div class=\"input-wrapper position-relative\">\n ${this.renderInput()}\n ${this.renderDropdownToggle()}\n </div>\n ${this.renderHiddenInput()}\n ${this.renderDropdown()}\n </div>\n `;\n }\n\n /**\n * Render the input field\n */\n renderInput() {\n return `\n <input type=\"text\"\n class=\"${this.inputClass} combo-input-field\"\n placeholder=\"${this.escapeHtml(this.placeholder)}\"\n value=\"${this.escapeHtml(this.inputValue)}\"\n ${this.disabled ? 'disabled' : ''}\n ${this.readonly ? 'readonly' : ''}\n ${this.required ? 'required' : ''}\n data-change-action=\"input-change\"\n data-action=\"input-keydown\"\n autocomplete=\"off\"\n role=\"combobox\"\n aria-expanded=\"${this.isOpen}\"\n aria-autocomplete=\"list\"\n aria-controls=\"combo-dropdown-${this.cid}\">\n `;\n }\n\n /**\n * Render dropdown toggle button\n */\n renderDropdownToggle() {\n if (this.readonly || this.disabled) return '';\n\n return `\n <button type=\"button\"\n class=\"btn btn-sm combo-toggle position-absolute top-50 end-0 translate-middle-y border-0\"\n data-action=\"toggle-dropdown\"\n tabindex=\"-1\"\n aria-label=\"Toggle dropdown\"\n style=\"padding: 0.25rem 0.5rem;\">\n <i class=\"bi bi-chevron-down\"></i>\n </button>\n `;\n }\n\n /**\n * Render hidden input for form submission\n */\n renderHiddenInput() {\n if (!this.name) return '';\n\n return `\n <input type=\"hidden\"\n name=\"${this.name}\"\n value=\"${this.escapeHtml(this.currentValue)}\"\n class=\"combo-input-hidden\">\n `;\n }\n\n /**\n * Render dropdown menu\n */\n renderDropdown() {\n return `\n <div id=\"combo-dropdown-${this.cid}\"\n class=\"combo-dropdown dropdown-menu position-absolute w-100 ${this.isOpen ? 'show' : ''}\"\n role=\"listbox\"\n style=\"max-height: 300px; overflow-y: auto; z-index: 1050;\">\n ${this.renderDropdownContent()}\n </div>\n `;\n }\n\n /**\n * Render dropdown content based on filtered options\n */\n renderDropdownContent() {\n if (this.filteredOptions.length === 0) {\n return this.renderNoResults();\n }\n\n return this.filteredOptions\n .slice(0, this.maxSuggestions)\n .map((option, index) => this.renderOption(option, index))\n .join('');\n }\n\n /**\n * Render a single option\n */\n renderOption(option, index) {\n const isHighlighted = index === this.highlightedIndex;\n const isSelected = option.value === this.currentValue;\n\n return `\n <div class=\"dropdown-item combo-option ${isHighlighted ? 'active' : ''} ${isSelected ? 'selected' : ''}\"\n data-action=\"select-option\"\n data-option-index=\"${index}\"\n role=\"option\"\n aria-selected=\"${isSelected}\"\n style=\"cursor: pointer;\">\n <div class=\"d-flex justify-content-between align-items-start\">\n <div class=\"flex-grow-1\">\n <div class=\"combo-option-label fw-semibold\">${this.highlightMatch(option.label)}</div>\n ${this.showDescription && option.description ? `\n <div class=\"combo-option-description small text-muted\">${this.escapeHtml(option.description)}</div>\n ` : ''}\n </div>\n ${isSelected ? '<i class=\"bi bi-check text-primary ms-2\"></i>' : ''}\n </div>\n </div>\n `;\n }\n\n /**\n * Render no results message\n */\n renderNoResults() {\n if (this.allowCustom && this.inputValue.length >= this.minChars) {\n return `\n <div class=\"dropdown-item-text text-muted small\">\n <i class=\"bi bi-info-circle me-1\"></i>\n ${this.inputValue ? 'No matches found. Press Enter to use custom value.' : 'Start typing to see suggestions...'}\n </div>\n `;\n }\n\n return `\n <div class=\"dropdown-item-text text-muted small\">\n <i class=\"bi bi-search me-1\"></i>\n No matching options found.\n </div>\n `;\n }\n\n /**\n * Highlight matching text in option label\n */\n highlightMatch(label) {\n if (!this.inputValue) return this.escapeHtml(label);\n\n const escaped = this.escapeHtml(label);\n const pattern = new RegExp(`(${this.escapeRegex(this.inputValue)})`, 'gi');\n return escaped.replace(pattern, '<mark class=\"bg-warning bg-opacity-25\">$1</mark>');\n }\n\n /**\n * Handle component initialization after render\n */\n async onAfterRender() {\n await super.onAfterRender();\n this.updateFilteredOptions();\n\n // Close dropdown when clicking outside\n this.handleOutsideClick = (event) => {\n if (this.element && !this.element.contains(event.target)) {\n this.closeDropdown();\n }\n };\n\n document.addEventListener('click', this.handleOutsideClick);\n }\n\n // ========================================\n // EventDelegate Action Handlers\n // ========================================\n\n /**\n * Handle input changes (typing)\n */\n async onChangeInputChange(event, element) {\n this.inputValue = element.value;\n this.updateFilteredOptions();\n\n if (this.inputValue.length >= this.minChars) {\n this.openDropdown();\n } else {\n this.closeDropdown();\n }\n\n // Reset highlighted index when filtering\n this.highlightedIndex = -1;\n await this.updateDropdownDisplay();\n }\n\n /**\n * Handle input keydown for navigation\n */\n async onActionInputKeydown(event, _element) {\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n if (!this.isOpen) {\n this.openDropdown();\n } else {\n this.highlightNext();\n }\n await this.updateDropdownDisplay();\n break;\n\n case 'ArrowUp':\n event.preventDefault();\n if (this.isOpen) {\n this.highlightPrevious();\n await this.updateDropdownDisplay();\n }\n break;\n\n case 'Enter':\n event.preventDefault();\n if (this.isOpen && this.highlightedIndex >= 0) {\n await this.selectHighlightedOption();\n } else if (this.allowCustom && this.inputValue) {\n await this.selectCustomValue(this.inputValue);\n }\n break;\n\n case 'Escape':\n event.preventDefault();\n this.closeDropdown();\n // Restore previous value\n const input = this.element.querySelector('.combo-input-field');\n if (input) {\n input.value = this.getDisplayValue(this.currentValue);\n this.inputValue = input.value;\n }\n break;\n\n case 'Tab':\n // Allow tab to close dropdown and move focus\n if (this.isOpen) {\n this.closeDropdown();\n }\n break;\n }\n }\n\n /**\n * Handle toggle dropdown button click\n */\n async onActionToggleDropdown(event, _element) {\n event.preventDefault();\n event.stopPropagation();\n\n if (this.isOpen) {\n this.closeDropdown();\n } else {\n // Show all options when toggle is clicked\n this.inputValue = '';\n const input = this.element.querySelector('.combo-input-field');\n if (input) {\n input.value = '';\n input.focus();\n }\n this.updateFilteredOptions();\n this.openDropdown();\n await this.updateDropdownDisplay();\n }\n }\n\n /**\n * Handle option selection\n */\n async onActionSelectOption(event, element) {\n event.preventDefault();\n event.stopPropagation();\n\n const index = parseInt(element.getAttribute('data-option-index'));\n if (index >= 0 && index < this.filteredOptions.length) {\n await this.selectOption(this.filteredOptions[index]);\n }\n }\n\n // ========================================\n // Dropdown Management\n // ========================================\n\n /**\n * Open dropdown\n */\n openDropdown() {\n this.isOpen = true;\n const dropdown = this.element?.querySelector('.combo-dropdown');\n if (dropdown) {\n dropdown.classList.add('show');\n }\n\n const input = this.element?.querySelector('.combo-input-field');\n if (input) {\n input.setAttribute('aria-expanded', 'true');\n }\n }\n\n /**\n * Close dropdown\n */\n closeDropdown() {\n this.isOpen = false;\n this.highlightedIndex = -1;\n\n const dropdown = this.element?.querySelector('.combo-dropdown');\n if (dropdown) {\n dropdown.classList.remove('show');\n }\n\n const input = this.element?.querySelector('.combo-input-field');\n if (input) {\n input.setAttribute('aria-expanded', 'false');\n }\n }\n\n /**\n * Update filtered options based on input\n */\n updateFilteredOptions() {\n const query = this.inputValue.toLowerCase().trim();\n\n if (!query) {\n this.filteredOptions = [...this.options];\n return;\n }\n\n this.filteredOptions = this.options.filter(option => {\n const labelMatch = option.label.toLowerCase().includes(query);\n const valueMatch = String(option.value).toLowerCase().includes(query);\n const descMatch = option.description?.toLowerCase().includes(query);\n return labelMatch || valueMatch || descMatch;\n });\n\n // Sort by relevance (exact matches first)\n this.filteredOptions.sort((a, b) => {\n const aLabelExact = a.label.toLowerCase() === query;\n const bLabelExact = b.label.toLowerCase() === query;\n if (aLabelExact && !bLabelExact) return -1;\n if (!aLabelExact && bLabelExact) return 1;\n\n const aLabelStarts = a.label.toLowerCase().startsWith(query);\n const bLabelStarts = b.label.toLowerCase().startsWith(query);\n if (aLabelStarts && !bLabelStarts) return -1;\n if (!aLabelStarts && bLabelStarts) return 1;\n\n return 0;\n });\n }\n\n /**\n * Update dropdown display\n */\n async updateDropdownDisplay() {\n const dropdown = this.element?.querySelector('.combo-dropdown');\n if (!dropdown) return;\n\n dropdown.innerHTML = this.renderDropdownContent();\n\n // Scroll highlighted option into view\n if (this.highlightedIndex >= 0) {\n const highlightedElement = dropdown.querySelector('.combo-option.active');\n if (highlightedElement) {\n highlightedElement.scrollIntoView({ block: 'nearest' });\n }\n }\n }\n\n /**\n * Highlight next option\n */\n highlightNext() {\n if (this.filteredOptions.length === 0) return;\n\n this.highlightedIndex = (this.highlightedIndex + 1) % Math.min(this.filteredOptions.length, this.maxSuggestions);\n }\n\n /**\n * Highlight previous option\n */\n highlightPrevious() {\n if (this.filteredOptions.length === 0) return;\n\n this.highlightedIndex = this.highlightedIndex <= 0\n ? Math.min(this.filteredOptions.length, this.maxSuggestions) - 1\n : this.highlightedIndex - 1;\n }\n\n /**\n * Select highlighted option\n */\n async selectHighlightedOption() {\n if (this.highlightedIndex >= 0 && this.highlightedIndex < this.filteredOptions.length) {\n await this.selectOption(this.filteredOptions[this.highlightedIndex]);\n }\n }\n\n /**\n * Select an option\n */\n async selectOption(option) {\n this.currentValue = option.value;\n this.inputValue = option.label;\n this.selectedOption = option;\n\n // Update input display\n const input = this.element?.querySelector('.combo-input-field');\n if (input) {\n input.value = option.label;\n }\n\n // Update hidden input\n const hiddenInput = this.element?.querySelector('.combo-input-hidden');\n if (hiddenInput) {\n hiddenInput.value = option.value;\n }\n\n this.closeDropdown();\n\n // Emit events\n this.emit('select', { option, value: option.value, meta: option.meta });\n this.emit('change', { value: option.value, option, meta: option.meta });\n\n // Call callbacks\n if (typeof this.onSelectCallback === 'function') {\n this.onSelectCallback(option);\n }\n if (typeof this.onChangeCallback === 'function') {\n this.onChangeCallback(option.value);\n }\n }\n\n /**\n * Select custom value (not in options)\n */\n async selectCustomValue(value) {\n if (!this.allowCustom) return;\n\n this.currentValue = value;\n this.inputValue = value;\n this.selectedOption = null;\n\n // Update hidden input\n const hiddenInput = this.element?.querySelector('.combo-input-hidden');\n if (hiddenInput) {\n hiddenInput.value = value;\n }\n\n this.closeDropdown();\n\n // Emit events\n this.emit('custom', { value });\n this.emit('change', { value, custom: true });\n\n // Call callback\n if (typeof this.onChangeCallback === 'function') {\n this.onChangeCallback(value);\n }\n }\n\n // ========================================\n // Public API Methods\n // ========================================\n\n /**\n * Get current value\n */\n getValue() {\n return this.currentValue;\n }\n\n /**\n * Set value programmatically\n */\n async setValue(value) {\n this.currentValue = value;\n this.selectedOption = this.findOptionByValue(value);\n this.inputValue = this.getDisplayValue(value);\n\n const input = this.element?.querySelector('.combo-input-field');\n if (input) {\n input.value = this.inputValue;\n }\n\n const hiddenInput = this.element?.querySelector('.combo-input-hidden');\n if (hiddenInput) {\n hiddenInput.value = value;\n }\n\n this.updateFilteredOptions();\n }\n\n /**\n * Get selected option with metadata\n */\n getSelectedOption() {\n return this.selectedOption;\n }\n\n /**\n * Update options\n */\n async setOptions(options) {\n this.options = this.normalizeOptions(options);\n this.updateFilteredOptions();\n\n if (this.isOpen) {\n await this.updateDropdownDisplay();\n }\n }\n\n /**\n * Enable/disable the component\n */\n setEnabled(enabled) {\n this.disabled = !enabled;\n\n const input = this.element?.querySelector('.combo-input-field');\n if (input) {\n input.disabled = this.disabled;\n }\n\n const toggle = this.element?.querySelector('.combo-toggle');\n if (toggle) {\n toggle.disabled = this.disabled;\n }\n }\n\n /**\n * Set readonly state\n */\n setReadonly(readonly) {\n this.readonly = readonly;\n\n const input = this.element?.querySelector('.combo-input-field');\n if (input) {\n if (readonly) {\n input.setAttribute('readonly', '');\n } else {\n input.removeAttribute('readonly');\n }\n }\n }\n\n /**\n * Focus the input\n */\n focus() {\n const input = this.element?.querySelector('.combo-input-field');\n if (input) {\n input.focus();\n }\n }\n\n /**\n * Clear the input\n */\n async clear() {\n await this.setValue('');\n this.inputValue = '';\n\n const input = this.element?.querySelector('.combo-input-field');\n if (input) {\n input.value = '';\n }\n\n this.emit('clear');\n }\n\n // ========================================\n // Form Integration\n // ========================================\n\n /**\n * Get form value (for FormView integration)\n */\n getFormValue() {\n // If allowCustom is enabled and user has typed a value that hasn't been committed,\n // return the typed value instead of the last committed value\n if (this.allowCustom && this.inputValue && this.inputValue !== this.getDisplayValue(this.currentValue)) {\n return this.inputValue;\n }\n return this.currentValue;\n }\n\n /**\n * Set form value (for FormView integration)\n */\n async setFormValue(value) {\n await this.setValue(value);\n }\n\n // ========================================\n // Utility Methods\n // ========================================\n\n /**\n * Escape HTML to prevent XSS\n */\n escapeHtml(str) {\n if (str == null) return '';\n const div = document.createElement('div');\n div.textContent = String(str);\n return div.innerHTML;\n }\n\n /**\n * Escape regex special characters\n */\n escapeRegex(str) {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n }\n\n /**\n * Cleanup on destroy\n */\n async onBeforeDestroy() {\n if (this.handleOutsideClick) {\n document.removeEventListener('click', this.handleOutsideClick);\n }\n await super.onBeforeDestroy();\n }\n\n /**\n * Static factory method\n */\n static create(options = {}) {\n return new ComboInput(options);\n }\n}\n\nexport default ComboInput;\n","/**\n * FormView - Complete form component for MOJO framework\n * Uses FormBuilder for HTML generation and EventDelegate for event handling\n * Handles form lifecycle, validation, data management, and component integration\n */\n\nimport View from '@core/View.js';\nimport FormBuilder from './FormBuilder.js';\nimport applyFileDropMixin from '@core/mixins/FileDropMixin.js';\nimport MOJOUtils from '@core/utils/MOJOUtils.js';\nimport { FormPlugins } from '@core/forms/FormPlugins.js';\n\nimport { TagInput, CollectionSelect, CollectionMultiSelect, DatePicker, DateRangePicker, ComboInput } from './inputs/index.js';\n\nclass FormView extends View {\n constructor(options = {}) {\n const {\n formConfig = options.config,\n fields,\n model = null,\n data = {},\n defaults = null,\n errors = {},\n fileHandling = 'base64', // 'base64' | 'multipart'\n autosaveModelField = false, // Auto-save model on field changes\n ...viewOptions\n } = options;\n\n super({\n tagName: 'div',\n className: 'form-view',\n ...viewOptions\n });\n\n // Notify plugins this FormView is initializing\n FormPlugins.onFormViewInit?.(this);\n\n // Store data sources\n this.model = model;\n this.defaults = defaults || data;\n this._originalData = data;\n this.errors = errors;\n this.loading = false;\n this.fileHandling = fileHandling;\n this.autosaveModelField = autosaveModelField;\n this.customComponents = new Map();\n this.fieldStatusManagers = new Map(); // Track field status managers\n this.saveTimeouts = new Map(); // Debouncing timeouts for autosave\n this.pendingSaveFields = new Map(); // Track fields pending save (for batching)\n this.batchSaveTimeout = null; // Global timeout for batch saving\n this.isSaving = false; // Prevent save loops\n\n // Prepare combined data for FormBuilder\n this.data = this.prepareFormData();\n\n // Form configuration\n this.formConfig = formConfig || { fields: fields || [] };\n this.formBuilder = new FormBuilder({\n ...this.getFormConfig(),\n data: this.data, // Pass data so field.value defaults work\n errors\n });\n }\n\n /**\n * Prepare form data by combining defaults, model, and data in priority order\n * Priority: data > model > defaults\n * @returns {Object} Combined data object for FormBuilder\n */\n prepareFormData() {\n const formData = { ...this.defaults };\n\n // Add model data if available\n if (this.model) {\n if (this.model.attributes && typeof this.model.attributes === 'object') {\n Object.assign(formData, this.model.attributes);\n } else if (typeof this.model.toJSON === 'function') {\n const modelData = this.model.toJSON();\n Object.assign(formData, modelData);\n } else if (typeof this.model === 'object' && this.model.constructor === Object) {\n Object.assign(formData, this.model);\n }\n }\n\n // Original data takes highest priority\n if (this._originalData) {\n Object.assign(formData, this._originalData);\n }\n\n return formData;\n }\n\n getFormConfig() {\n const config = { ...this.formConfig };\n const app = this.getApp();\n\n // Handle case where fields might not be defined\n if (this.formConfig.fields && Array.isArray(this.formConfig.fields)) {\n config.fields = this.formConfig.fields.filter(field => {\n if (!field.permissions) return true;\n return app.activeUser?.hasPermission(field.permissions);\n });\n } else {\n config.fields = [];\n }\n\n return config;\n }\n\n /**\n * Use FormBuilder for template generation\n */\n async renderTemplate() {\n return this.formBuilder.buildFormHTML();\n }\n\n /**\n * Called after form is rendered to populate values and initialize\n */\n async onAfterRender() {\n await super.onAfterRender();\n\n this.data = this.prepareFormData();\n // Populate form with current data\n this.populateFormValues();\n\n // Initialize form components\n this.initializeFormComponents();\n\n // Add generic change handlers for all form inputs\n this.initializeChangeHandlers();\n\n // Prevent form submission on Enter key\n const form = this.getFormElement();\n if (form) {\n form.addEventListener('submit', (e) => {\n e.preventDefault();\n return false;\n });\n }\n\n // Allow plugins to run after the form renders and initializes\n FormPlugins.onFormViewAfterRender?.(this);\n }\n\n /**\n * Populate all form fields with current data values\n */\n populateFormValues() {\n if (!this.element || !this.formConfig?.fields) return;\n\n // Disable autosave during form population\n this._isPopulating = true;\n\n try {\n this.formConfig.fields.forEach(field => {\n if (field.type === 'group' && field.fields) {\n // Handle group fields\n field.fields.forEach(groupField => {\n this.populateFieldValue(groupField);\n });\n } else {\n this.populateFieldValue(field);\n }\n });\n } finally {\n // Always re-enable autosave\n this._isPopulating = false;\n }\n }\n\n /**\n * Populate a single field with its value from data\n */\n populateFieldValue(fieldConfig) {\n if (!fieldConfig.name || !this.element) return;\n\n const fieldElement = this.element.querySelector(`[name=\"${fieldConfig.name}\"]`);\n if (!fieldElement) return;\n\n // Use MOJOUtils to handle nested properties like 'permissions.manage_users'\n const value = MOJOUtils.getContextData(this.data, fieldConfig.name);\n\n // Only set value if we have actual data - don't overwrite field defaults with undefined\n if (value !== undefined && value !== null) {\n this.setFieldValue(fieldElement, fieldConfig, value);\n }\n }\n\n /**\n * Initialize form components after rendering\n */\n initializeFormComponents() {\n this.initializeImageFields();\n this.initializeCustomComponents();\n this.initializeTagInputs();\n this.initializeCollectionSelects();\n this.initializeCollectionMultiSelects();\n this.initializeDatePickers();\n this.initializeDateRangePickers();\n this.initializePasswordFields();\n }\n\n\n\n /**\n * Initialize image fields with FileDropMixin\n */\n initializeImageFields() {\n const imageFields = this.element.querySelectorAll('.image-drop-zone.droppable');\n\n if (imageFields.length > 0) {\n // Enable file drop functionality (mixin already applied at module level)\n this.enableFileDrop({\n acceptedTypes: ['image/*'],\n maxFileSize: 10 * 1024 * 1024, // 10MB\n multiple: false,\n dropZoneSelector: '.image-drop-zone.droppable',\n visualFeedback: true,\n dragOverClass: 'drag-over',\n dragActiveClass: 'drag-active'\n });\n }\n }\n\n /**\n * Initialize custom components (tags, collection selects, enhanced date pickers, etc.)\n */\n initializeCustomComponents() {\n // Initialize enhanced input components\n this.initializeTagInputs();\n this.initializeCollectionSelects();\n this.initializeCollectionMultiSelects();\n this.initializeDatePickers();\n this.initializeDateRangePickers();\n this.initializeComboInputs();\n\n // Give plugins a chance to initialize fields (autocomplete, masks, etc.)\n try {\n const visitFields = (fields = []) => {\n fields.forEach(f => {\n if (f && f.type === 'group' && Array.isArray(f.fields)) {\n visitFields(f.fields);\n } else if (f && f.name) {\n const el = this.element.querySelector(`[name=\"${f.name}\"], #${f.id || f.name}`);\n if (el) {\n FormPlugins.onFieldInit?.(this, el, f);\n }\n }\n });\n };\n visitFields(this.formConfig?.fields || []);\n } catch (err) {\n console.warn('FormPlugins.onFieldInit error:', err);\n }\n\n // Find containers for other custom components\n const componentContainers = this.element.querySelectorAll('[data-component]');\n\n componentContainers.forEach(container => {\n const componentType = container.getAttribute('data-component');\n const fieldName = container.getAttribute('data-field');\n\n if (componentType && fieldName) {\n\n }\n });\n }\n\n /**\n * Initialize generic change handlers for all form inputs\n */\n initializeChangeHandlers() {\n if (!this.element) return;\n\n // Add change listeners to all form inputs that don't already have specific handlers\n const inputs = this.element.querySelectorAll('input:not([data-action]), select:not([data-action]), textarea:not([data-action])');\n\n console.log('FormView: initializeChangeHandlers - found', inputs.length, 'inputs');\n\n inputs.forEach(input => {\n console.log('FormView: Processing input:', input.type, input.name, input.getAttribute('data-change-action'));\n // Skip inputs that already have specific handlers or are handled by custom components\n if (input.hasAttribute('data-component') || input.classList.contains('form-check-input')) {\n return;\n }\n\n // Add change event listener\n input.addEventListener('change', (event) => {\n // Skip autosave during form population\n if (this._isPopulating) return;\n\n const fieldName = input.name;\n if (fieldName) {\n let value = input.value;\n\n // Handle different input types\n if (input.type === 'checkbox') {\n value = input.checked;\n } else if (input.type === 'radio') {\n // Only process if this radio is checked\n if (!input.checked) return;\n } else if (input.multiple && input.selectedOptions) {\n // Handle multi-select\n value = Array.from(input.selectedOptions).map(opt => opt.value);\n } else if (input.type === 'file') {\n // Handle file inputs (including images)\n const changeAction = input.getAttribute('data-change-action');\n if (changeAction === 'image-selected') {\n this.onChangeImageSelected(event, input);\n return; // Don't call handleFieldChange for images\n } else if (changeAction === 'file-selected') {\n this.onChangeFileSelected(event, input);\n return; // Don't call handleFieldChange for files\n }\n }\n\n this.handleFieldChange(fieldName, value);\n }\n });\n\n // Also add input event for text inputs for more responsive autosave\n if (input.type === 'text' || input.type === 'email' || input.type === 'url' || input.tagName === 'TEXTAREA') {\n input.addEventListener('input', (event) => {\n // Skip autosave during form population\n if (this._isPopulating) return;\n\n const fieldName = input.name;\n if (fieldName) {\n this.handleFieldChange(fieldName, input.value);\n }\n });\n }\n });\n }\n\n /**\n * Initialize TagInput components\n */\n initializeTagInputs() {\n const tagPlaceholders = this.element.querySelectorAll('[data-field-type=\"tag\"]');\n\n tagPlaceholders.forEach(placeholder => {\n try {\n const fieldName = placeholder.getAttribute('data-field-name');\n const configData = placeholder.getAttribute('data-field-config');\n const config = JSON.parse(configData);\n\n // Create TagInput component\n const tagInput = new TagInput({\n ...config,\n containerId: null // We'll mount directly\n });\n\n // Replace placeholder with TagInput\n tagInput.render(true, placeholder);\n\n // Store reference for cleanup\n this.customComponents.set(fieldName, tagInput);\n\n // Listen for changes\n tagInput.on('change', (data) => {\n this.handleFieldChange(fieldName, data.value);\n });\n\n } catch (error) {\n // TagInput initialization failed\n }\n });\n }\n\n /**\n * Initialize CollectionSelect components\n */\n initializeCollectionSelects() {\n const collectionPlaceholders = this.element.querySelectorAll('[data-field-type=\"collection\"]');\n\n collectionPlaceholders.forEach(placeholder => {\n try {\n const fieldName = placeholder.getAttribute('data-field-name');\n const configData = placeholder.getAttribute('data-field-config');\n const config = JSON.parse(configData);\n\n // Get Collection class from field config\n const fieldConfig = this.getFormFieldConfig(fieldName); // this.formConfig.fields.find(f => f.name === fieldName);\n if (!fieldConfig || !fieldConfig.Collection) {\n\n return;\n }\n\n // Create collection instance\n const collection = new fieldConfig.Collection();\n if (fieldConfig.collectionParams) {\n collection.params = {...collection.params, ...fieldConfig.collectionParams};\n }\n\n // Create CollectionSelect component\n const collectionSelect = new CollectionSelect({\n ...config,\n collection,\n defaultParams: fieldConfig.defaultParams || null, // Can be dict or callback\n containerId: null // We'll mount directly\n });\n\n let value = MOJOUtils.getContextData(this.data, fieldName);\n if (value) {\n collectionSelect.setFormValue(value);\n }\n\n // Replace placeholder with CollectionSelect\n collectionSelect.render(true, placeholder);\n\n // Store reference for cleanup\n this.customComponents.set(fieldName, collectionSelect);\n\n // Listen for changes\n collectionSelect.on('change', (data) => {\n this.handleFieldChange(fieldName, data.value);\n });\n\n } catch (error) {\n // CollectionSelect initialization failed\n }\n });\n }\n\n /**\n * Initialize CollectionMultiSelect components\n */\n initializeCollectionMultiSelects() {\n const collectionMultiSelectPlaceholders = this.element.querySelectorAll('[data-field-type=\"collectionmultiselect\"]');\n\n collectionMultiSelectPlaceholders.forEach(placeholder => {\n try {\n const fieldName = placeholder.getAttribute('data-field-name');\n const configData = placeholder.getAttribute('data-field-config');\n const config = JSON.parse(configData);\n\n // Get Collection class from field config\n const fieldConfig = this.getFormFieldConfig(fieldName);\n if (!fieldConfig || !fieldConfig.Collection) {\n return;\n }\n\n // Create collection instance\n const collection = new fieldConfig.Collection();\n if (fieldConfig.collectionParams) {\n collection.params = {...collection.params, ...fieldConfig.collectionParams};\n }\n\n // Create CollectionMultiSelect component\n const collectionMultiSelect = new CollectionMultiSelect({\n ...config,\n collection,\n defaultParams: fieldConfig.defaultParams || null, // Can be dict or callback\n itemTemplate: fieldConfig.itemTemplate || null, // Custom item template\n containerId: null // We'll mount directly\n });\n\n let value = MOJOUtils.getContextData(this.data, fieldName);\n if (value) {\n collectionMultiSelect.setFormValue(value);\n }\n\n // Replace placeholder with CollectionMultiSelect\n collectionMultiSelect.render(true, placeholder);\n\n // Store reference for cleanup\n this.customComponents.set(fieldName, collectionMultiSelect);\n\n // Listen for changes\n collectionMultiSelect.on('change', (data) => {\n this.handleFieldChange(fieldName, data.value);\n });\n\n } catch (error) {\n console.error('CollectionMultiSelect initialization failed:', error);\n }\n });\n }\n\n /**\n * Initialize DatePicker components\n */\n initializeDatePickers() {\n const datePickerPlaceholders = this.element.querySelectorAll('[data-field-type=\"datepicker\"]');\n\n datePickerPlaceholders.forEach(placeholder => {\n try {\n const fieldName = placeholder.getAttribute('data-field-name');\n const configData = placeholder.getAttribute('data-field-config');\n const config = JSON.parse(configData);\n\n // Create DatePicker component\n const datePicker = new DatePicker({\n ...config,\n containerId: null // We'll mount directly\n });\n\n // Replace placeholder with DatePicker\n datePicker.render(true, placeholder);\n\n // Store reference for cleanup\n this.customComponents.set(fieldName, datePicker);\n\n // Listen for changes\n datePicker.on('change', (data) => {\n this.handleFieldChange(fieldName, data.value);\n });\n\n } catch (error) {\n // DatePicker initialization failed\n }\n });\n }\n\n /**\n * Initialize DateRangePicker components\n */\n initializeDateRangePickers() {\n const dateRangePlaceholders = this.element.querySelectorAll('[data-field-type=\"daterange\"]');\n\n dateRangePlaceholders.forEach(placeholder => {\n try {\n const fieldName = placeholder.getAttribute('data-field-name');\n const configData = placeholder.getAttribute('data-field-config');\n const config = JSON.parse(configData);\n\n // Create DateRangePicker component\n const dateRangePicker = new DateRangePicker({\n ...config,\n containerId: null // We'll mount directly\n });\n\n // Replace placeholder with DateRangePicker\n dateRangePicker.render(true, placeholder);\n\n // Store reference for cleanup\n this.customComponents.set(fieldName, dateRangePicker);\n\n // Listen for changes\n dateRangePicker.on('change', (data) => {\n this.handleFieldChange(fieldName, data.combined);\n });\n\n } catch (error) {\n // DateRangePicker initialization failed\n }\n });\n }\n\n /**\n * Initialize ComboInput components\n */\n initializeComboInputs() {\n const comboPlaceholders = this.element.querySelectorAll('[data-field-type=\"combo\"]');\n\n comboPlaceholders.forEach(placeholder => {\n try {\n const fieldName = placeholder.getAttribute('data-field-name');\n const configData = placeholder.getAttribute('data-field-config');\n const config = JSON.parse(configData);\n\n // Create ComboInput component\n const comboInput = new ComboInput({\n ...config,\n containerId: null // We'll mount directly\n });\n\n let value = MOJOUtils.getContextData(this.data, fieldName);\n if (value) {\n comboInput.setValue(value);\n }\n\n // Replace placeholder with ComboInput\n comboInput.render(true, placeholder);\n\n // Store reference for cleanup\n this.customComponents.set(fieldName, comboInput);\n\n // Listen for changes\n comboInput.on('change', (data) => {\n this.handleFieldChange(fieldName, data.value);\n });\n\n // Listen for selection with metadata\n comboInput.on('select', (data) => {\n // Emit additional event with metadata for custom handling\n this.emit('field:select', {\n field: fieldName,\n value: data.value,\n option: data.option,\n meta: data.meta\n });\n });\n\n } catch (error) {\n console.error('ComboInput initialization failed:', error);\n }\n });\n }\n\n /**\n * Handle field changes from custom components\n */\n handleFieldChange(fieldName, value) {\n // Update internal data\n this.data[fieldName] = value;\n\n // Handle autosave or regular model update\n if (this.autosaveModelField && this.model) {\n // Auto-save individual field to model\n this.handleFieldSave(fieldName, value);\n } else if (this.model && this.options.allowModelChange) {\n // Regular model update without save\n this._isFormDrivenChange = true;\n this.model.set(fieldName, value);\n }\n\n // Emit change event\n this.emit('field:change', { field: fieldName, value });\n\n // Notify plugins of the field change\n FormPlugins.onFieldChange?.(this, fieldName, value);\n }\n\n /**\n * Handle saving field changes to the model with intelligent batching\n * When multiple fields change within a short time (e.g., autofill), they are batched together\n * @param {string} fieldName - Name of the field being saved\n * @param {*} value - New value to save\n */\n async handleFieldSave(fieldName, value) {\n if (!this.model) return;\n\n // Add field to pending save queue\n this.pendingSaveFields.set(fieldName, value);\n\n // Show saving status for this field\n const statusManager = this.getFieldStatusManager(fieldName);\n statusManager.showStatus('saving');\n\n // Clear existing batch timeout\n if (this.batchSaveTimeout) {\n clearTimeout(this.batchSaveTimeout);\n }\n\n // Set new batch timeout - if no more changes come in 300ms, save all pending fields\n this.batchSaveTimeout = setTimeout(async () => {\n await this.executeBatchSave();\n }, 300);\n }\n\n /**\n * Execute a batch save of all pending field changes\n * This sends all changed fields in a single request to avoid race conditions\n * @private\n */\n async executeBatchSave() {\n if (this.isSaving || this.pendingSaveFields.size === 0) return;\n\n // Collect all pending changes BEFORE clearing\n const changes = Object.fromEntries(this.pendingSaveFields);\n const fieldNames = Array.from(this.pendingSaveFields.keys());\n\n try {\n this.isSaving = true;\n\n // Clear pending fields before save\n this.pendingSaveFields.clear();\n this.batchSaveTimeout = null;\n\n // Mark as form-driven change to prevent sync back\n this._isFormDrivenChange = true;\n\n // Save all changes in a single request\n if (typeof this.model.save === 'function') {\n const resp = await this.model.save(changes);\n \n // Check if save was successful\n if (!resp || !resp.success || (resp.data && !resp.data.status)) {\n const errorMsg = resp?.data?.error || resp?.error || resp?.message || 'Save failed';\n \n // Show error toast\n this.getApp()?.toast?.error(errorMsg);\n \n // Revert fields to their original values\n this.revertFields(fieldNames);\n \n // Show error status for all fields\n fieldNames.forEach(fieldName => {\n const statusManager = this.getFieldStatusManager(fieldName);\n statusManager.showStatus('error', { message: errorMsg });\n });\n \n return; // Exit early, don't show success\n }\n } else {\n // Just update model attributes if no save method\n Object.entries(changes).forEach(([key, val]) => {\n this.model.set(key, val);\n });\n }\n\n // Show success status for all saved fields (only if we didn't return early)\n fieldNames.forEach(fieldName => {\n const statusManager = this.getFieldStatusManager(fieldName);\n statusManager.showStatus('saved');\n });\n\n } catch (error) {\n console.error('Batch save error:', error);\n\n // Show error toast\n this.getApp()?.toast?.error(error.message || 'An error occurred while saving');\n\n // Revert fields to their original values\n this.revertFields(fieldNames);\n\n // Show error status for all fields that were attempted\n fieldNames.forEach(fieldName => {\n const statusManager = this.getFieldStatusManager(fieldName);\n statusManager.showStatus('error', { message: error.message });\n });\n } finally {\n this.isSaving = false;\n }\n }\n\n /**\n * Revert form fields to their original model values\n * Called when save fails to keep UI in sync with server state\n * @param {Array<string>} fieldNames - Names of fields to revert\n * @private\n */\n revertFields(fieldNames) {\n if (!this.model) return;\n\n // Temporarily disable autosave during revert\n const wasPopulating = this._isPopulating;\n this._isPopulating = true;\n\n try {\n fieldNames.forEach(fieldName => {\n // Get original value from model\n const originalValue = this.model.get(fieldName);\n \n // Update internal data\n this.data[fieldName] = originalValue;\n \n // Find the field element and revert its value\n const fieldElement = this.element?.querySelector(`[name=\"${fieldName}\"]`);\n if (fieldElement) {\n const fieldConfig = this.getFormFieldConfig(fieldName);\n if (fieldConfig) {\n this.setFieldValue(fieldElement, fieldConfig, originalValue);\n } else {\n // Fallback if no config found\n if (fieldElement.type === 'checkbox') {\n fieldElement.checked = Boolean(originalValue);\n } else {\n fieldElement.value = originalValue ?? '';\n }\n }\n }\n });\n } finally {\n // Re-enable autosave\n this._isPopulating = wasPopulating;\n }\n }\n\n /**\n * Get or create a field status manager for a specific field\n * @param {string} fieldName - Name of the field\n * @returns {FieldStatusManager} Status manager instance\n */\n getFieldStatusManager(fieldName) {\n if (!this.fieldStatusManagers.has(fieldName)) {\n const fieldElement = this.element.querySelector(`[name=\"${fieldName}\"]`);\n if (fieldElement) {\n const statusManager = new FieldStatusManager(fieldElement);\n this.fieldStatusManagers.set(fieldName, statusManager);\n }\n }\n return this.fieldStatusManagers.get(fieldName);\n }\n\n /**\n * Refresh form data and repopulate values\n * Call this when model or data changes externally\n */\n refreshForm() {\n this.data = this.prepareFormData();\n\n // If mounted, repopulate form values\n if (this.element) {\n this.populateFormValues();\n }\n }\n\n /**\n * Get reason why a field is considered changed\n * @param {*} newValue - New value from form\n * @param {*} originalValue - Original value from model\n * @returns {string} Reason for change\n */\n getChangeReason(newValue, originalValue) {\n if (newValue instanceof File) {\n if (newValue.size === 0 || newValue.name === '' || newValue.name === 'blob') {\n return 'empty file, no change';\n }\n return `file upload: ${newValue.name}, ${newValue.size} bytes`;\n }\n\n if (typeof newValue === 'string' && newValue.startsWith('data:image/')) {\n return 'base64 image upload';\n }\n\n if (typeof newValue === 'boolean' || typeof originalValue === 'boolean') {\n const newBool = Boolean(newValue);\n const originalBool = originalValue === null || originalValue === undefined ? false : Boolean(originalValue);\n return `boolean: ${originalBool} → ${newBool}`;\n }\n\n const newStr = newValue === null || newValue === undefined ? '' : String(newValue).trim();\n const originalStr = originalValue === null || originalValue === undefined ? '' : String(originalValue).trim();\n\n if (originalValue === null || originalValue === undefined) {\n return 'was null/undefined, now has value';\n }\n\n if (newValue === null || newValue === undefined) {\n return 'was value, now null/undefined';\n }\n\n return 'text content changed';\n }\n\n /**\n * Set form data (updates the data property and rebuilds form)\n * @param {Object} newData - Data to set\n */\n setFormData(newData) {\n this._originalData = { ...this._originalData, ...newData };\n this.refreshForm();\n }\n\n\n\n // ========================================\n // EventDelegate Action Handlers\n // ========================================\n\n /**\n * Handle form submission\n */\n async onActionSubmitForm(event, element) {\n event.preventDefault();\n\n const result = await this.handleSubmit();\n\n if (result.success) {\n // Update internal data\n this.data = result.data;\n\n // Emit success event\n this.emit('submit', {\n data: result.data,\n result: result.result,\n form: this,\n event\n });\n\n // Call submit handler if provided (for non-model forms)\n if (!this.model && this.formConfig.onSubmit && typeof this.formConfig.onSubmit === 'function') {\n await this.formConfig.onSubmit(result.data, this);\n }\n } else {\n // Emit error event\n this.emit('error', {\n error: result.error,\n result: result,\n form: this\n });\n }\n }\n\n /**\n * Handle form reset\n */\n async onActionResetForm(event, _element) {\n const form = this.getFormElement();\n if (form) {\n form.reset();\n this.data = {};\n this.clearAllErrors();\n\n this.emit('reset', {\n form: this,\n event\n });\n }\n }\n\n /**\n * Handle image upload click\n */\n async onActionClickImageUpload(event, element) {\n console.log('FormView: onActionClickImageUpload called');\n console.log('FormView: element:', element);\n\n const fieldId = element.getAttribute('data-field-id');\n console.log('FormView: fieldId:', fieldId);\n\n if (!fieldId) {\n console.error('FormView: No fieldId attribute found');\n return;\n }\n\n const fileInput = this.element.querySelector(`#${fieldId}`);\n console.log('FormView: fileInput:', fileInput);\n\n if (fileInput && !fileInput.disabled) {\n fileInput.click();\n console.log('FormView: fileInput.click() called');\n } else if (!fileInput) {\n console.error('FormView: fileInput not found for fieldId:', fieldId);\n } else {\n console.log('FormView: fileInput is disabled');\n }\n }\n\n /**\n * Handle image removal\n */\n async onActionRemoveImage(event, element) {\n const fieldName = element.getAttribute('data-field');\n if (!fieldName) return;\n\n // Clear the field value\n const fileInput = this.element.querySelector(`input[name=\"${fieldName}\"]`);\n if (fileInput) {\n fileInput.value = '';\n fileInput.dispatchEvent(new Event('change', { bubbles: true }));\n }\n\n // Update data and re-render\n delete this.data[fieldName];\n this.emit('change', { field: fieldName, value: null, form: this });\n await this.updateField(fieldName);\n }\n\n /**\n * Handle clear color action\n */\n async onActionClearColor(event, element) {\n const fieldName = element.getAttribute('data-field');\n if (!fieldName) return;\n\n // Clear the color input value\n const colorInput = this.element.querySelector(`input[name=\"${fieldName}\"]`);\n if (colorInput) {\n colorInput.value = '';\n\n // Trigger field change handling (for autosave if enabled)\n this.handleFieldChange(fieldName, '');\n\n // Update the field to hide the clear button\n await this.updateField(fieldName);\n }\n }\n\n /**\n * Handle button group selection\n */\n async onActionSelectButtonOption(event, element) {\n const fieldName = element.getAttribute('data-field');\n const value = element.getAttribute('data-value');\n\n if (!fieldName || !value) return;\n\n // Update form data\n this.data[fieldName] = value;\n\n // Update UI - remove active class from siblings and add to this button\n const buttonGroup = element.closest('.btn-group');\n if (buttonGroup) {\n const buttons = buttonGroup.querySelectorAll('button');\n buttons.forEach(btn => {\n btn.classList.remove('active');\n btn.classList.add('btn-outline-primary');\n btn.classList.remove('btn-primary');\n });\n\n element.classList.add('active');\n element.classList.remove('btn-outline-primary');\n element.classList.add('btn-primary');\n }\n\n // Emit field change event\n this.emit('field:changed', {\n field: fieldName,\n value: value,\n form: this\n });\n\n this.emit('change', {\n field: fieldName,\n value: value,\n form: this\n });\n\n // Emit general form change event\n this.emit('form:changed', await this.getFormData());\n }\n\n /**\n * Handle checklist dropdown filter apply\n */\n async onActionApplyFilter(event, element) {\n const dropdown = element.closest('.dropdown');\n const checkboxes = dropdown?.querySelectorAll('input[type=\"checkbox\"]');\n\n if (!checkboxes || checkboxes.length === 0) return;\n\n const fieldName = checkboxes[0].getAttribute('data-field');\n if (!fieldName) return;\n\n // Collect checked values\n const selectedValues = [];\n checkboxes.forEach(checkbox => {\n if (checkbox.checked) {\n selectedValues.push(checkbox.value);\n }\n });\n\n // Update form data\n this.data[fieldName] = selectedValues;\n\n // Close dropdown\n const dropdownBtn = dropdown.querySelector('[data-bs-toggle=\"dropdown\"]');\n if (dropdownBtn && window.bootstrap?.Dropdown) {\n const dropdownInstance = window.bootstrap.Dropdown.getInstance(dropdownBtn);\n dropdownInstance?.hide();\n }\n\n // Emit field change event\n this.emit('field:changed', {\n field: fieldName,\n value: selectedValues,\n form: this\n });\n\n this.emit('change', {\n field: fieldName,\n value: selectedValues,\n form: this\n });\n\n // Emit general form change event\n this.emit('form:changed', await this.getFormData());\n }\n\n // ========================================\n // EventDelegate Change Handlers\n // ========================================\n\n /**\n * Handle field validation on change\n */\n async onChangeValidateField(event, element) {\n const fieldName = element.name;\n if (fieldName) {\n const value = element.value;\n\n // Use handleFieldChange for consistent processing\n this.handleFieldChange(fieldName, value);\n\n // Validate the field\n this.validateField(fieldName);\n }\n }\n\n /**\n * Handle switch toggle\n */\n async onChangeToggleSwitch(event, element) {\n const fieldName = element.getAttribute('data-field');\n if (fieldName) {\n const value = element.checked;\n\n // Use handleFieldChange for consistent processing\n this.handleFieldChange(fieldName, value);\n\n // Emit specific switch events for backward compatibility\n this.emit('switch:toggle', {\n field: fieldName,\n checked: value,\n form: this\n });\n }\n }\n\n /**\n * Handle image selection\n */\n async onChangeImageSelected(event, element) {\n console.log('FormView: onChangeImageSelected called');\n console.log('FormView: element:', element);\n console.log('FormView: element.files:', element.files);\n\n const fieldName = element.getAttribute('data-field');\n const file = element.files[0];\n\n console.log('FormView: fieldName:', fieldName);\n console.log('FormView: file:', file);\n\n if (fieldName && file) {\n console.log('FormView: fieldName and file exist, processing...');\n\n // Find the field configuration to check for imageSize\n const fieldConfig = this.findFieldConfig(fieldName);\n console.log('FormView: fieldConfig:', fieldConfig);\n\n // Create temporary preview URL\n const previewUrl = URL.createObjectURL(file);\n console.log('FormView: previewUrl created:', previewUrl);\n\n // Check if image cropping is required\n if (fieldConfig && fieldConfig.imageSize) {\n console.log('FormView: Image cropping is required, imageSize:', fieldConfig.imageSize);\n try {\n // Check if lightbox extension is available for image cropping\n const ImageCropView = window.MOJO?.plugins?.ImageCropView;\n console.log('FormView: ImageCropView available?', !!ImageCropView);\n\n if (!ImageCropView) {\n // ImageCropView not available - fall back to normal handling without cropping\n console.log('FormView: ImageCropView not available, falling back to normal handling');\n this.data[fieldName] = file;\n await this.updateImagePreview(fieldName, previewUrl);\n this.emit('image:selected', { field: fieldName, file: file, form: this });\n return;\n }\n\n // Open crop dialog with crop and scale\n const result = await ImageCropView.showDialog(previewUrl, {\n title: `Crop ${fieldConfig.label || fieldName}`,\n cropAndScale: fieldConfig.imageSize,\n size: 'lg'\n });\n\n if (result.action === 'crop' && result.data) {\n // Convert data URL to blob\n const response = await fetch(result.data);\n const croppedBlob = await response.blob();\n\n // Create a new File object with the original name\n const croppedFile = new File([croppedBlob], file.name, {\n type: file.type || 'image/png'\n });\n\n this.data[fieldName] = croppedFile;\n\n // Update preview with cropped image\n await this.updateImagePreview(fieldName, result.data);\n\n this.emit('image:selected', {\n field: fieldName,\n file: croppedFile,\n originalFile: file,\n cropped: true,\n cropData: result.cropData,\n form: this\n });\n\n this.emit('change', {\n field: fieldName,\n value: croppedFile,\n form: this\n });\n } else {\n // User cancelled cropping, don't update the field\n element.value = ''; // Clear the input\n }\n } catch (error) {\n // Error during image cropping\n console.error('FormView: Error during image cropping:', error);\n // Fall back to normal image handling\n console.log('FormView: Falling back to normal image handling after error');\n this.data[fieldName] = file;\n await this.updateImagePreview(fieldName, previewUrl);\n\n this.emit('image:selected', {\n field: fieldName,\n file: file,\n form: this\n });\n\n this.emit('change', {\n field: fieldName,\n value: file,\n form: this\n });\n }\n } else {\n // Normal image handling without cropping\n console.log('FormView: Normal image handling (no cropping)');\n this.data[fieldName] = file;\n console.log('FormView: File stored in this.data[' + fieldName + ']');\n\n await this.updateImagePreview(fieldName, previewUrl);\n console.log('FormView: updateImagePreview completed');\n\n this.emit('image:selected', {\n field: fieldName,\n file: file,\n form: this\n });\n console.log('FormView: image:selected event emitted');\n }\n } else {\n console.log('FormView: Missing fieldName or file - not processing');\n }\n }\n\n /**\n * Handle file selection\n */\n async onChangeFileSelected(event, element) {\n const files = Array.from(element.files);\n\n // Store the file(s) in this.data so getFormData() can access them\n if (element.multiple) {\n this.data[element.name] = element.files; // Store as FileList for multiple\n } else {\n this.data[element.name] = files[0] || null; // Store single File object\n }\n\n this.emit('file:selected', {\n field: element.name,\n files: files,\n form: this\n });\n\n this.emit('change', {\n field: element.name,\n value: files,\n form: this\n });\n }\n\n /**\n * Handle range value changes\n */\n async onChangeRangeChanged(event, element) {\n const fieldName = element.name;\n const value = element.value;\n\n // Update display target if specified\n const targetId = element.getAttribute('data-target');\n if (targetId) {\n const valueDisplay = this.element.querySelector(`#${targetId}`);\n if (valueDisplay) {\n valueDisplay.textContent = value;\n }\n }\n\n // Use handleFieldChange for consistent processing\n if (fieldName) {\n this.handleFieldChange(fieldName, value);\n }\n\n // Emit specific range event for backward compatibility\n this.emit('range:changed', {\n field: fieldName,\n value: value,\n form: this\n });\n }\n\n /**\n * Handle search/filter operations\n */\n async onChangeFilterSearch(event, element) {\n const query = element.value;\n this.emit('search', {\n query: query,\n field: element.name,\n form: this\n });\n }\n\n /**\n * Handle select option filtering\n */\n async onChangeFilterSelectOptions(event, element) {\n const query = element.value.toLowerCase();\n const targetId = element.getAttribute('data-target');\n const select = targetId ? this.element.querySelector(`#${targetId}`) : null;\n\n if (select) {\n const options = select.querySelectorAll('option');\n options.forEach(option => {\n const text = option.textContent.toLowerCase();\n option.style.display = text.includes(query) ? '' : 'none';\n });\n }\n }\n\n // ========================================\n // FileDropMixin Integration\n // ========================================\n\n /**\n * Handle file drop on image fields\n */\n async onFileDrop(files, event, _validation) {\n const dropZone = event.target.closest('.image-drop-zone');\n if (!dropZone) return;\n\n const fieldName = dropZone.getAttribute('data-field');\n if (!fieldName) return;\n\n const file = files[0];\n\n // Update file input\n const fileInput = this.element.querySelector(`input[name=\"${fieldName}\"]`);\n if (fileInput) {\n const dataTransfer = new DataTransfer();\n dataTransfer.items.add(file);\n fileInput.files = dataTransfer.files;\n fileInput.dispatchEvent(new Event('change', { bubbles: true }));\n }\n\n // Update data and preview\n this.data[fieldName] = file;\n const previewUrl = URL.createObjectURL(file);\n await this.updateImagePreview(fieldName, previewUrl);\n\n this.emit('image:dropped', {\n field: fieldName,\n file: file,\n form: this\n });\n }\n\n /**\n * Handle file drop errors\n */\n async onFileDropError(error, event, files) {\n // File drop error\n this.showError(`File upload error: ${error.message}`);\n\n this.emit('file:error', {\n error: error,\n files: files,\n form: this\n });\n }\n\n // ========================================\n // Form Management Methods\n // ========================================\n\n /**\n * Get form element\n */\n getFormElement() {\n return this.element ? this.element.querySelector('form') : null;\n }\n\n getFormFieldConfig(name) {\n const searchInFields = (fields) => {\n for (const field of fields) {\n if (field.name === name) {\n return field;\n }\n // Search in nested fields recursively\n if (field.fields && Array.isArray(field.fields)) {\n const found = searchInFields(field.fields);\n if (found) return found;\n }\n }\n return null;\n };\n\n return searchInFields(this.formConfig.fields || []);\n }\n\n /**\n * Get all form data\n * Returns JSON object for base64 mode, FormData for multipart mode\n */\n async getFormData() {\n const form = this.getFormElement();\n if (!form) return this.fileHandling === 'multipart' ? new FormData() : {};\n\n if (this.fileHandling === 'multipart') {\n // Return FormData object with files as File objects\n const formData = new FormData(form);\n\n // Add files from this.data to FormData\n for (const [key, value] of Object.entries(this.data)) {\n if (value instanceof File) {\n formData.set(key, value);\n } else if (value instanceof FileList) {\n for (let i = 0; i < value.length; i++) {\n formData.append(`${key}[${i}]`, value[i]);\n }\n }\n }\n\n return formData;\n } else {\n // Return JSON object with files converted to base64\n const formData = new FormData(form);\n const data = {};\n\n // Handle regular form fields\n for (const [key, value] of formData.entries()) {\n if (data[key]) {\n // Handle multiple values\n if (!Array.isArray(data[key])) {\n data[key] = [data[key]];\n }\n data[key].push(value);\n } else {\n data[key] = value;\n }\n }\n\n // Handle checkboxes and switches to ensure correct boolean values\n const checkboxes = form.querySelectorAll('input[type=\"checkbox\"]');\n checkboxes.forEach(checkbox => {\n data[checkbox.name] = checkbox.checked;\n });\n\n // Convert number fields to actual numbers\n const numberInputs = form.querySelectorAll('input[type=\"number\"]');\n numberInputs.forEach(input => {\n if (input.name && data[input.name] !== undefined && data[input.name] !== '') {\n const num = Number(data[input.name]);\n if (!isNaN(num)) {\n data[input.name] = num;\n }\n }\n });\n\n // Convert select fields with numeric values based on field config\n this.formConfig.fields?.forEach(field => {\n if (field.type === 'select' && field.name && data[field.name] !== undefined) {\n const fieldConfig = this.getFormFieldConfig(field.name);\n // Check if all option values are numeric\n if (fieldConfig?.options && Array.isArray(fieldConfig.options)) {\n const allNumeric = fieldConfig.options.every(opt => {\n const val = typeof opt === 'object' ? opt.value : opt;\n return val === '' || !isNaN(Number(val));\n });\n\n if (allNumeric && data[field.name] !== '') {\n const num = Number(data[field.name]);\n if (!isNaN(num)) {\n data[field.name] = num;\n }\n }\n }\n }\n });\n\n // Handle JSON fields\n const jsonFields = form.querySelectorAll('[data-field-type=\"json\"]');\n jsonFields.forEach(textarea => {\n try {\n data[textarea.name] = JSON.parse(textarea.value);\n } catch (e) {\n // Invalid JSON in field\n data[textarea.name] = textarea.value; // Keep as string if invalid\n }\n });\n\n // Handle custom components (TagInput, CollectionSelect, DatePicker, etc.)\n this.customComponents.forEach((component, fieldName) => {\n if (component.getFormValue) {\n data[fieldName] = component.getFormValue();\n } else if (component.getValue) {\n data[fieldName] = component.getValue();\n }\n });\n\n // Convert files to base64 and add to data\n for (const [key, value] of Object.entries(this.data)) {\n if (value instanceof File) {\n try {\n data[key] = await this.fileToBase64(value);\n } catch (error) {\n // Failed to convert file to base64\n data[key] = null;\n }\n } else if (value instanceof FileList) {\n const base64Files = [];\n for (let i = 0; i < value.length; i++) {\n try {\n base64Files.push(await this.fileToBase64(value[i]));\n } catch (error) {\n // Failed to convert file to base64\n base64Files.push(null);\n }\n }\n data[key] = base64Files;\n }\n }\n\n return data;\n }\n }\n\n _onModelChange() {\n // Don't sync during save operations to prevent loops\n if (this.isSaving) return;\n\n // Always update internal data\n this.data = this.prepareFormData();\n\n if (this.isMounted()) {\n // Only sync if the change wasn't initiated by this form\n if (!this._isFormDrivenChange) {\n this.syncFormWithModel();\n }\n // Reset the flag\n this._isFormDrivenChange = false;\n }\n }\n\n /**\n * Sync form field values with current model data without full rebuild\n */\n syncFormWithModel() {\n if (!this.model || !this.element) return;\n\n // Check if form data actually differs from current displayed values\n if (this.formDataMatchesModelData(this.data)) {\n return; // No sync needed - data is already in sync\n }\n\n // Re-populate form values with updated data\n this.populateFormValues();\n }\n\n /**\n * Compare current form values with new model data\n * @param {Object} newModelData - New data from model\n * @returns {boolean} True if form and model data match\n */\n formDataMatchesModelData(newModelData) {\n if (!this.formConfig?.fields || !this.element) return true;\n\n for (const field of this.formConfig.fields) {\n if (field.type === 'group' && field.fields) {\n // Check group fields\n for (const groupField of field.fields) {\n if (!this.fieldValueMatchesModel(groupField, newModelData)) {\n return false;\n }\n }\n } else {\n if (!this.fieldValueMatchesModel(field, newModelData)) {\n return false;\n }\n }\n }\n return true;\n }\n\n /**\n * Check if a single field's current value matches the model data\n * @param {Object} fieldConfig - Field configuration\n * @param {Object} modelData - Model data to compare against\n * @returns {boolean} True if field value matches model\n */\n fieldValueMatchesModel(fieldConfig, modelData) {\n if (!fieldConfig.name) return true;\n\n const fieldElement = this.element.querySelector(`[name=\"${fieldConfig.name}\"]`);\n if (!fieldElement) return true;\n\n const currentValue = this.getFieldCurrentValue(fieldElement, fieldConfig);\n // Use MOJOUtils to handle nested properties like 'permissions.manage_users'\n const modelValue = MOJOUtils.getContextData(modelData, fieldConfig.name);\n\n return this.valuesAreDifferent(currentValue, modelValue) === false;\n }\n\n\n\n /**\n * Get current value from a form field element\n */\n getFieldCurrentValue(fieldElement, fieldConfig) {\n switch (fieldConfig.type) {\n case 'checkbox':\n case 'toggle':\n case 'switch':\n return fieldElement.checked;\n case 'radio':\n const checkedRadio = this.element.querySelector(`[name=\"${fieldConfig.name}\"]:checked`);\n return checkedRadio ? checkedRadio.value : '';\n case 'select':\n return fieldElement.multiple ?\n Array.from(fieldElement.selectedOptions).map(opt => opt.value) :\n fieldElement.value;\n case 'file':\n case 'image':\n return null; // Don't sync file fields\n case 'json':\n // Parse JSON string back to object\n try {\n return fieldElement.value ? JSON.parse(fieldElement.value) : null;\n } catch (e) {\n return fieldElement.value; // Return raw string if invalid JSON\n }\n default:\n return fieldElement.value;\n }\n }\n\n /**\n * Set value on a form field element\n */\n setFieldValue(fieldElement, fieldConfig, newValue) {\n switch (fieldConfig.type) {\n case 'checkbox':\n case 'toggle':\n case 'switch':\n fieldElement.checked = Boolean(newValue);\n break;\n case 'radio':\n const radioOption = this.element.querySelector(`[name=\"${fieldConfig.name}\"][value=\"${newValue}\"]`);\n if (radioOption) {\n radioOption.checked = true;\n }\n break;\n case 'select':\n if (fieldElement.multiple && Array.isArray(newValue)) {\n Array.from(fieldElement.options).forEach(option => {\n option.selected = newValue.includes(option.value);\n });\n } else {\n // Use nullish coalescing to preserve falsy values like 0\n fieldElement.value = newValue ?? '';\n }\n break;\n case 'file':\n case 'image':\n // Don't programmatically set file fields\n break;\n case 'json':\n // Convert objects to formatted JSON strings\n if (typeof newValue === 'object' && newValue !== null) {\n try {\n fieldElement.value = JSON.stringify(newValue, null, 2);\n } catch (e) {\n fieldElement.value = '{}';\n }\n } else if (typeof newValue === 'string') {\n fieldElement.value = newValue;\n } else {\n fieldElement.value = String(newValue || '');\n }\n break;\n default:\n fieldElement.value = newValue || '';\n break;\n }\n\n // Trigger change event for any field listeners\n fieldElement.dispatchEvent(new Event('change', { bubbles: true }));\n }\n\n /**\n * Set defaults (updates defaults and rebuilds form)\n * @param {Object} newDefaults - Default values to set\n */\n setDefaults(newDefaults) {\n this.defaults = { ...this.defaults, ...newDefaults };\n this.refreshForm();\n }\n\n /**\n * Handle form submission with validation, saving, and error handling\n * @returns {Promise<Object>} Submission result {success: boolean, data: Object, result?: Object, error?: string}\n */\n async handleSubmit() {\n try {\n // Get form data (async for base64 conversion)\n const formData = await this.getFormData();\n\n // Validate if needed\n if (this.formConfig.validateOnSubmit !== false) {\n const isValid = this.validate();\n if (!isValid) {\n this.focusFirstError();\n return {\n success: false,\n data: formData,\n error: 'Form validation failed'\n };\n }\n }\n\n // If there's a model, save via model\n if (this.model && typeof this.model.save === 'function') {\n const result = await this.saveModel(formData);\n\n // Check if save was successful\n if (result && result.success !== false) {\n return {\n success: true,\n data: formData,\n result: result\n };\n } else {\n const errorMsg = result?.message || result?.error || 'Save failed. Please try again.';\n return {\n success: false,\n data: formData,\n result: result,\n error: errorMsg\n };\n }\n } else {\n // No model - just return form data\n return formData;\n }\n\n } catch (error) {\n // Form submission error\n\n return {\n success: false,\n error: error.message || 'An error occurred while submitting the form'\n };\n }\n }\n\n /**\n * Save form data via model\n * Uses auto-detection for multipart vs JSON based on form data type\n * Only saves changed data for efficiency\n * @returns {Promise<Object>} Save result from model\n */\n async saveModel(formData = null) {\n if (!this.model || typeof this.model.save !== 'function') {\n throw new Error('No model available for saving');\n }\n\n // Get form data (auto-detects FormData vs Object)\n if (!formData) formData = await this.getFormData();\n\n // Check for changes before saving\n const changes = this.getChangedData(formData);\n\n if (!changes || Object.keys(changes).length === 0) {\n // No changes detected\n return {\n success: true,\n message: 'No changes to save',\n data: formData\n };\n }\n\n\n\n try {\n // Mark this as a form-driven change to prevent sync back\n this._isFormDrivenChange = true;\n\n // Model.save with only changed data\n const result = await this.model.save(changes);\n\n\n return result;\n } catch (error) {\n // Model save error\n throw error;\n }\n }\n\n /**\n * Compare current form data with original model data to detect changes\n * @param {Object|FormData} currentData - Current form data\n * @returns {Object|FormData|null} Changed data only, or null if no changes\n */\n getChangedData(currentData) {\n if (!this.model) return currentData;\n\n // Get original data from model\n const originalData = this.getOriginalModelData();\n\n\n let changes;\n if (currentData instanceof FormData) {\n // Handle FormData comparison\n\n changes = this.getChangedFormData(currentData, originalData);\n } else {\n // Handle Object comparison\n\n changes = this.getChangedObjectData(currentData, originalData);\n }\n\n\n return changes;\n }\n\n /**\n * Get original data from model for comparison\n * @returns {Object} Original model data\n */\n getOriginalModelData() {\n if (this.model.attributes) {\n return this.model.attributes;\n } else if (typeof this.model.toJSON === 'function') {\n return this.model.toJSON();\n } else {\n return {};\n }\n }\n\n /**\n * Compare FormData with original data\n * @param {FormData} currentData - Current form data\n * @param {Object} originalData - Original model data\n * @returns {FormData|null} FormData with only changed fields, or null if no changes\n */\n getChangedFormData(currentData, originalData) {\n const changedData = new FormData();\n let hasChanges = false;\n\n // Compare each form field\n for (const [key, value] of currentData.entries()) {\n if (value instanceof File) {\n // Check if file has actual content\n if (value.size === 0 || value.name === '' || value.name === 'blob') {\n\n } else {\n\n changedData.set(key, value);\n hasChanges = true;\n }\n } else {\n // Compare text values\n const originalValue = originalData[key];\n if (value !== originalValue && value !== String(originalValue)) {\n\n changedData.set(key, value);\n hasChanges = true;\n } else {\n\n }\n }\n }\n\n return hasChanges ? changedData : null;\n }\n\n /**\n * Compare Object data with original data\n * @param {Object} currentData - Current form data\n * @param {Object} originalData - Original model data\n * @returns {Object|null} Object with only changed fields, or null if no changes\n */\n getChangedObjectData(currentData, originalData) {\n const changedData = {};\n let hasChanges = false;\n const allKeys = new Set([...Object.keys(originalData), ...Object.keys(currentData)]);\n\n const resolveDotNotation = (obj, path) => path.split('.').reduce((o, i) => (o && typeof o === 'object' ? o[i] : undefined), obj);\n\n for (const key of allKeys) {\n const fieldConfig = this.findFieldConfig(key);\n // Only process fields that are actually defined in the form's schema.\n if (!fieldConfig) {\n continue;\n }\n\n const newValue = currentData[key];\n const originalValue = resolveDotNotation(originalData, key);\n\n const fieldType = fieldConfig.type || 'text';\n\n if (this.valuesAreDifferent(newValue, originalValue, fieldType, fieldConfig)) {\n changedData[key] = newValue;\n hasChanges = true;\n }\n }\n\n return hasChanges ? changedData : null;\n }\n\n /**\n * Compare two values to determine if they're different\n * @param {*} newValue - New value from form\n * @param {*} originalValue - Original value from model\n * @param {string} fieldType - The type of the field from the form config\n * @param {object} fieldConfig - The configuration of the field from the form config\n * @returns {boolean} True if values are different\n */\n valuesAreDifferent(newValue, originalValue, fieldType = 'text', fieldConfig = {}) {\n // Handle File objects (new uploads vs existing)\n if (newValue instanceof File) {\n return newValue.size > 0 && newValue.name !== '' && newValue.name !== 'blob';\n }\n\n // Handle base64 images (always considered changed if present)\n if (typeof newValue === 'string' && newValue.startsWith('data:image/')) {\n return true;\n }\n\n if (fieldType === \"collection\") {\n // this is the collection select, the field will typically be an ID or \"0\" for null;\n if (typeof originalValue === 'object' && originalValue !== null && originalValue !== undefined && typeof newValue === 'string') {\n // we really need to field config here if fieldKey is not id\n if (newValue === '0') {\n return originalValue !== null;\n }\n const valueField = fieldConfig.valueField || 'id';\n // we compare (str to int)\n if (originalValue[valueField] == newValue) {\n return false;\n }\n }\n }\n\n // For switches and checkboxes, perform a strict boolean comparison\n if (fieldType === 'switch' || fieldType === 'checkbox' || fieldType === 'toggle') {\n const newBool = !!newValue;\n const originalBool = !!originalValue;\n return newBool !== originalBool;\n }\n\n // For all other fields, compare their string representations\n const newStr = newValue === null || newValue === undefined ? '' : String(newValue).trim();\n const originalStr = originalValue === null || originalValue === undefined ? '' : String(originalValue).trim();\n\n return newStr !== originalStr;\n }\n\n /**\n * Validate entire form\n */\n validate() {\n const form = this.getFormElement();\n if (!form) return false;\n\n const isValid = form.checkValidity();\n\n if (!isValid) {\n form.classList.add('was-validated');\n }\n\n return isValid;\n }\n\n /**\n * Validate single field\n */\n validateField(fieldName) {\n const form = this.getFormElement();\n if (!form) return false;\n\n const field = form.elements[fieldName];\n if (!field) return false;\n\n const isValid = field.checkValidity();\n\n if (isValid) {\n field.classList.remove('is-invalid');\n field.classList.add('is-valid');\n delete this.errors[fieldName];\n } else {\n field.classList.remove('is-valid');\n field.classList.add('is-invalid');\n this.errors[fieldName] = field.validationMessage;\n }\n\n return isValid;\n }\n\n /**\n * Focus first error\n * If the invalid field is inside a hidden tab pane, activate that tab first.\n */\n focusFirstError() {\n const form = this.getFormElement();\n if (!form) return;\n\n const firstInvalid = form.querySelector(':invalid');\n if (!firstInvalid) return;\n\n // If inside a Bootstrap tab pane and not active, activate the corresponding tab\n const tabPane = firstInvalid.closest('.tab-pane');\n if (tabPane && !tabPane.classList.contains('active')) {\n const tabId = tabPane.id;\n\n // Find the tab trigger button (support aria-controls or data-bs-target)\n const trigger = form.querySelector(`[role=\"tab\"][aria-controls=\"${tabId}\"], [data-bs-target=\"#${tabId}\"]`);\n if (trigger) {\n // Prefer Bootstrap API if available\n const bsTab = window.bootstrap?.Tab?.getOrCreateInstance\n ? window.bootstrap.Tab.getOrCreateInstance(trigger)\n : null;\n\n if (bsTab && typeof bsTab.show === 'function') {\n bsTab.show();\n } else {\n // Fallback: manually toggle classes\n const navLinks = form.querySelectorAll('[role=\"tab\"].nav-link');\n navLinks.forEach(link => {\n const isActive = link === trigger;\n link.classList.toggle('active', isActive);\n link.setAttribute('aria-selected', isActive ? 'true' : 'false');\n });\n\n const panes = form.querySelectorAll('.tab-pane');\n panes.forEach(p => p.classList.remove('show', 'active'));\n tabPane.classList.add('show', 'active');\n }\n }\n }\n\n firstInvalid.focus();\n firstInvalid.scrollIntoView({ behavior: 'smooth', block: 'center' });\n }\n\n /**\n * Clear all errors\n */\n clearAllErrors() {\n const form = this.getFormElement();\n if (!form) return;\n\n this.errors = {};\n form.classList.remove('was-validated');\n\n const invalidElements = form.querySelectorAll('.is-invalid');\n invalidElements.forEach(el => el.classList.remove('is-invalid'));\n\n const validElements = form.querySelectorAll('.is-valid');\n validElements.forEach(el => el.classList.remove('is-valid'));\n }\n\n /**\n * Set loading state\n */\n setLoading(loading) {\n this.loading = loading;\n\n const form = this.getFormElement();\n if (!form) return;\n\n const fields = form.querySelectorAll('input, select, textarea, button');\n const submitBtn = form.querySelector('button[type=\"submit\"]');\n\n if (loading) {\n // Disable all fields\n fields.forEach(field => field.disabled = true);\n\n // Update submit button\n if (submitBtn) {\n submitBtn.innerHTML = '<span class=\"spinner-border spinner-border-sm me-2\"></span>Loading...';\n }\n } else {\n // Enable all fields\n fields.forEach(field => field.disabled = false);\n\n // Restore submit button\n if (submitBtn) {\n const submitLabel = this.formConfig.options?.submitButton || 'Submit';\n submitBtn.innerHTML = typeof submitLabel === 'string' ? submitLabel : 'Submit';\n }\n }\n }\n\n /**\n * Show error message\n */\n showError(message) {\n // Form error\n\n this.emit('error', { message, form: this });\n\n // Show alert in form\n if (this.element) {\n // Remove existing alerts\n const existingAlerts = this.element.querySelectorAll('.alert');\n existingAlerts.forEach(alert => alert.remove());\n\n const alertDiv = document.createElement('div');\n alertDiv.className = 'alert alert-danger alert-dismissible fade show';\n alertDiv.innerHTML = `\n ${message}\n <button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" aria-label=\"Close\"></button>\n `;\n\n this.element.insertBefore(alertDiv, this.element.firstChild);\n\n // Auto-remove after 5 seconds\n setTimeout(() => {\n if (alertDiv.parentNode) {\n alertDiv.remove();\n }\n }, 5000);\n }\n }\n\n /**\n * Update a specific field\n */\n async updateField(_fieldName) {\n // Re-create FormBuilder with updated data\n this.formBuilder = new FormBuilder({\n ...this.getFormConfig(),\n data: this.data,\n errors: this.errors\n });\n\n // Re-render the form\n await this.render();\n }\n\n /**\n * Update image preview\n */\n async updateImagePreview(fieldName, imageUrl) {\n const dropZone = this.element.querySelector(`[data-field=\"${fieldName}\"].image-drop-zone`);\n\n if (!dropZone) {\n // Drop zone not found for field\n return;\n }\n\n // Check if there's already a preview image\n let preview = dropZone.querySelector('img');\n const placeholder = dropZone.querySelector('.bi-image')?.parentElement;\n const fieldId = dropZone.getAttribute('data-field-id');\n\n if (imageUrl) {\n if (preview) {\n // Update existing preview\n preview.src = imageUrl;\n } else {\n // Create new preview image\n const previewId = `${fieldId}_preview`;\n dropZone.innerHTML = `\n <img id=\"${previewId}\"\n src=\"${imageUrl}\"\n alt=\"Preview\"\n class=\"img-thumbnail w-100 h-100\"\n style=\"object-fit: cover;\">\n <button type=\"button\"\n class=\"btn btn-sm btn-danger position-absolute top-0 end-0 m-1\"\n data-action=\"remove-image\"\n data-field-id=\"${fieldId}\"\n data-field=\"${fieldName}\"\n style=\"opacity: 0.8;\">\n <i class=\"bi bi-x\"></i>\n </button>\n `;\n }\n\n // Hide placeholder if it exists\n if (placeholder) {\n placeholder.style.display = 'none';\n }\n }\n }\n\n /**\n * Find field configuration by name\n * @param {string} fieldName - Field name to find\n * @returns {Object|null} Field configuration\n */\n findFieldConfig(fieldName) {\n const searchInFields = (fields) => {\n for (const field of fields) {\n if (field.name === fieldName) {\n return field;\n }\n\n // Search in nested field structures\n // Groups: { type: 'group', fields: [...] }\n if (field.fields && Array.isArray(field.fields)) {\n const found = searchInFields(field.fields);\n if (found) return found;\n }\n\n // Tabsets: { type: 'tabset', tabs: [{ fields: [...] }] }\n if (field.tabs && Array.isArray(field.tabs)) {\n for (const tab of field.tabs) {\n if (tab.fields && Array.isArray(tab.fields)) {\n const found = searchInFields(tab.fields);\n if (found) return found;\n }\n }\n }\n }\n return null;\n };\n\n return searchInFields(this.formConfig.fields || []);\n }\n\n /**\n * Convert File object to base64 string\n * @param {File} file - File to convert\n * @returns {Promise<string>} Base64 encoded string\n */\n async fileToBase64(file) {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => resolve(reader.result);\n reader.onerror = reject;\n reader.readAsDataURL(file);\n });\n }\n\n /**\n * Check if form data contains any File objects\n * @param {Object|FormData} data - Form data to check\n * @returns {boolean} True if contains files\n */\n hasFiles(data) {\n if (data instanceof FormData) {\n for (const [key, value] of data.entries()) {\n if (value instanceof File) {\n return true;\n }\n }\n return false;\n } else {\n for (const value of Object.values(data)) {\n if (value instanceof File) {\n return true;\n }\n if (Array.isArray(value) && value.some(v => v instanceof File)) {\n return true;\n }\n }\n return false;\n }\n }\n\n /**\n * Reset form\n */\n reset() {\n const form = this.getFormElement();\n if (form) {\n form.reset();\n }\n\n this.data = {};\n this.errors = {};\n this.clearAllErrors();\n\n this.emit('reset', { form: this });\n }\n\n /**\n * Update form configuration\n */\n async updateConfig(newConfig) {\n this.formConfig = { ...this.formConfig, ...newConfig };\n this.formBuilder = new FormBuilder({\n ...this.getFormConfig(),\n data: this.data,\n errors: this.errors\n });\n\n await this.render();\n }\n\n /**\n * Clean up when destroying\n */\n async onBeforeDestroy() {\n // Clean up custom components\n const destroyPromises = [];\n for (const component of this.customComponents.values()) {\n if (component.destroy) {\n destroyPromises.push(component.destroy());\n }\n }\n await Promise.all(destroyPromises);\n this.customComponents.clear();\n\n // Clean up temporary URLs\n Object.values(this.data).forEach(value => {\n if (typeof value === 'string' && value.startsWith('blob:')) {\n URL.revokeObjectURL(value);\n }\n });\n\n await super.onBeforeDestroy();\n }\n /**\n * Initialize password fields: strength meter, caps lock warning, and hold-to-reveal\n */\n initializePasswordFields() {\n if (!this.element) return;\n\n // Find password inputs (either explicit data-field-type=\"password\" or native type=\"password\")\n const inputs = this.element.querySelectorAll('input[data-field-type=\"password\"], input[type=\"password\"]');\n\n inputs.forEach((input) => {\n // Initialize strength UI once\n this.updatePasswordStrengthUI(input);\n\n // Wire strength meter updates\n const onInput = (e) => {\n this.updatePasswordStrengthUI(e.target);\n };\n input.addEventListener('input', onInput);\n\n // Caps lock warning on key events\n const capsHandler = (e) => {\n if (typeof e.getModifierState === 'function') {\n const caps = e.getModifierState('CapsLock');\n this.updateCapsLockWarning(input, !!caps);\n }\n };\n input.addEventListener('keydown', capsHandler);\n input.addEventListener('keyup', capsHandler);\n\n // Initialize caps lock hidden state\n this.updateCapsLockWarning(input, false);\n });\n\n // Simple click toggle is handled by onActionTogglePassword; no extra listeners needed.\n }\n\n /**\n * Toggle password visibility on click (persistent toggle)\n * Ignored if currently in press-and-hold mode.\n */\n async onActionTogglePassword(event, element) {\n event.preventDefault();\n\n const targetId = element.getAttribute('data-target');\n let input = null;\n if (targetId) {\n input = this.element.querySelector('#' + targetId);\n }\n if (!input) {\n const group = element.closest('.input-group');\n if (group) {\n input = group.querySelector('input[type=\"password\"], input[data-field-type=\"password\"], input[type=\"text\"]');\n }\n }\n if (!input) return;\n\n const isHidden = input.type === 'password';\n input.type = isHidden ? 'text' : 'password';\n\n // Update button state and icon\n element.setAttribute('aria-pressed', isHidden ? 'true' : 'false');\n element.setAttribute('aria-label', isHidden ? 'Hide password' : 'Show password');\n const icon = element.querySelector('i');\n if (icon) {\n icon.classList.toggle('bi-eye', !isHidden);\n icon.classList.toggle('bi-eye-slash', isHidden);\n }\n\n // Keep focus on input and move caret to end\n input.focus();\n try {\n const len = input.value?.length ?? 0;\n input.setSelectionRange(len, len);\n } catch (_e) {\n // Not all input types support setSelectionRange; safe to ignore\n }\n }\n\n /**\n * Compute a simple password strength score and associated UI metadata\n */\n computePasswordStrength(password = '') {\n const len = password.length;\n let score = 0;\n\n // Length-based scoring\n if (len >= 6) score++;\n if (len >= 8) score++;\n if (len >= 12) score++;\n\n // Character variety\n const hasLower = /[a-z]/.test(password);\n const hasUpper = /[A-Z]/.test(password);\n const hasDigit = /\\d/.test(password);\n const hasSymbol = /[^A-Za-z0-9]/.test(password);\n\n const variety = [hasLower, hasUpper, hasDigit, hasSymbol].filter(Boolean).length;\n if (variety >= 2) score++;\n if (variety >= 3) score++;\n\n // Cap score between 0-4\n score = Math.max(0, Math.min(4, score));\n\n // Map to percent/label/class\n const map = [\n { percent: 0, label: 'Too short', barClass: 'bg-secondary' },\n { percent: 25, label: 'Weak', barClass: 'bg-danger' },\n { percent: 50, label: 'Fair', barClass: 'bg-warning' },\n { percent: 75, label: 'Good', barClass: 'bg-info' },\n { percent: 100, label: 'Strong', barClass: 'bg-success' }\n ];\n\n return map[score];\n }\n\n /**\n * Update strength meter UI if present for a given password input\n */\n updatePasswordStrengthUI(input) {\n if (!input || !input.id) return;\n\n const bar = this.element.querySelector(`#${input.id}_strength_bar`);\n const text = this.element.querySelector(`#${input.id}_strength_text`);\n if (!bar && !text) return;\n\n const { percent, label, barClass } = this.computePasswordStrength(input.value || '');\n\n if (bar) {\n // Reset to base class and apply strength color\n bar.className = `progress-bar ${barClass}`;\n bar.style.width = `${percent}%`;\n bar.setAttribute('aria-valuenow', String(percent));\n }\n if (text) {\n text.textContent = label;\n }\n }\n\n /**\n * Show/Hide a caps lock warning element if present for the given input\n */\n updateCapsLockWarning(input, capsOn) {\n if (!input || !input.id) return;\n const warn = this.element.querySelector(`#${input.id}_caps_warning`);\n if (!warn) return;\n\n if (capsOn) {\n warn.classList.remove('d-none');\n } else {\n warn.classList.add('d-none');\n }\n }\n}\n\n// Export for use in MOJO framework\n/**\n * FieldStatusManager - Manages save status indicators for form fields\n */\nclass FieldStatusManager {\n constructor(fieldElement) {\n this.fieldElement = fieldElement;\n this.statusContainer = this.findOrCreateStatusContainer();\n this.timeouts = new Map(); // Track active timeouts\n }\n\n /**\n * Find existing status container or create one based on field type\n */\n findOrCreateStatusContainer() {\n // Look for existing status container (check parent and labels)\n let container = this.fieldElement.parentElement.querySelector('.field-status-label-inline');\n\n // Also check within the field's label\n if (!container) {\n const label = this.findFieldLabel();\n if (label) {\n container = label.querySelector('.field-status-label-inline');\n }\n }\n\n if (!container) {\n container = this.createStatusContainer();\n }\n\n return container;\n }\n\n /**\n * Create appropriate status container based on field type\n */\n createStatusContainer() {\n const fieldType = this.getFieldType();\n const placement = this.getPlacementStrategy(fieldType);\n\n const container = document.createElement('div');\n\n // Since we only use label-inline now, simplify\n return this.createLabelInlineContainer(container);\n }\n\n /**\n * Determine field type from element\n */\n getFieldType() {\n const tagName = this.fieldElement.tagName.toLowerCase();\n const type = this.fieldElement.type?.toLowerCase();\n const classes = this.fieldElement.className;\n\n if (type === 'checkbox' || classes.includes('form-check-input') || classes.includes('form-switch')) {\n return 'toggle';\n } else if (tagName === 'select') {\n return 'select';\n } else if (tagName === 'textarea') {\n return 'textarea';\n } else if (tagName === 'input') {\n return 'input';\n }\n\n return 'input'; // default\n }\n\n /**\n * Determine placement strategy for field type\n */\n getPlacementStrategy(fieldType) {\n // Use label-inline for all field types - cleanest approach\n return 'label-inline';\n }\n\n /**\n * Create inline label status container (for all input types)\n */\n createLabelInlineContainer(container) {\n container.className = 'field-status-label-inline';\n container.innerHTML = this.getStatusHTML();\n\n // Find the associated label\n const label = this.findFieldLabel();\n if (label) {\n // Insert status container at the end of the label\n label.appendChild(container);\n } else {\n // Fallback to parent element if no label found\n this.fieldElement.parentElement.appendChild(container);\n }\n\n return container;\n }\n\n /**\n * Find the label associated with any field type\n */\n findFieldLabel() {\n // Try to find label by 'for' attribute matching field id\n if (this.fieldElement.id) {\n const label = document.querySelector(`label[for=\"${this.fieldElement.id}\"]`);\n if (label) return label;\n }\n\n // Look for label as sibling (common in Bootstrap form-check)\n const label = this.fieldElement.parentElement.querySelector('label');\n if (label) return label;\n\n // Look for label as parent (less common)\n const parentLabel = this.fieldElement.closest('label');\n if (parentLabel) return parentLabel;\n\n return null;\n }\n\n /**\n * Create input overlay container (for text inputs/selects)\n */\n createInputOverlayContainer(container) {\n container.className = 'field-status-overlay';\n container.innerHTML = this.getStatusHTML();\n\n // Make parent position relative if not already\n const parent = this.fieldElement.parentElement;\n if (getComputedStyle(parent).position === 'static') {\n parent.style.position = 'relative';\n }\n\n parent.appendChild(container);\n return container;\n }\n\n /**\n * Create full overlay container (for textareas/large inputs)\n */\n createFullOverlayContainer(container) {\n container.className = 'field-status-full-overlay d-none';\n container.innerHTML = `\n <div class=\"saving-indicator\">\n <div class=\"spinner-border spinner-border-sm text-primary\" role=\"status\">\n <span class=\"visually-hidden\">Saving...</span>\n </div>\n <span class=\"ms-2\">Saving...</span>\n </div>\n <div class=\"success-indicator d-none\">\n <i class=\"bi bi-check-circle text-success\"></i>\n <span class=\"ms-2\">Saved</span>\n </div>\n <div class=\"error-indicator d-none\">\n <i class=\"bi bi-exclamation-circle text-danger\"></i>\n <span class=\"ms-2\">Error saving</span>\n </div>\n `;\n\n // Make parent position relative if not already\n const parent = this.fieldElement.parentElement;\n if (getComputedStyle(parent).position === 'static') {\n parent.style.position = 'relative';\n }\n\n parent.appendChild(container);\n return container;\n }\n\n /**\n * Get standard status HTML for simple containers\n */\n getStatusHTML() {\n return `\n <div class=\"spinner-border spinner-border-sm text-primary d-none\" data-status=\"saving\" role=\"status\">\n <span class=\"visually-hidden\">Saving...</span>\n </div>\n <i class=\"bi bi-check-circle text-success d-none\" data-status=\"saved\"></i>\n <i class=\"bi bi-exclamation-circle text-danger d-none\" data-status=\"error\"></i>\n `;\n }\n\n /**\n * Show a status indicator\n * @param {string} type - Status type: 'saving', 'saved', 'error'\n * @param {object} options - Additional options\n */\n showStatus(type, options = {}) {\n // Clear any existing timeouts for this field\n this.clearTimeout(type);\n\n // Since we only use label-inline now, always use standard status\n this.showStandardStatus(type, options);\n }\n\n /**\n * Show status for standard containers (right-side, input-overlay)\n */\n showStandardStatus(type, options = {}) {\n // Hide all status indicators\n this.hideAllStatuses();\n\n // Show the requested status\n const indicator = this.statusContainer.querySelector(`[data-status=\"${type}\"]`);\n if (indicator) {\n indicator.classList.remove('d-none');\n indicator.classList.add('d-inline-block', 'show');\n\n // Set auto-hide timeout for temporary states\n if (type === 'saved') {\n this.setTimeout(type, () => this.hideStatus(type), 2500);\n } else if (type === 'error') {\n // Show error message in title if provided\n if (options.message) {\n indicator.title = options.message;\n }\n this.setTimeout(type, () => this.hideStatus(type), 6000);\n }\n }\n }\n\n /**\n * Show status for full overlay containers (textareas)\n */\n showFullOverlayStatus(type, options = {}) {\n // Hide all indicators first\n const indicators = this.statusContainer.querySelectorAll('.saving-indicator, .success-indicator, .error-indicator');\n indicators.forEach(ind => ind.classList.add('d-none'));\n\n // Show the container\n this.statusContainer.classList.remove('d-none');\n\n // Show specific indicator\n let indicatorClass;\n switch (type) {\n case 'saving':\n indicatorClass = '.saving-indicator';\n break;\n case 'saved':\n indicatorClass = '.success-indicator';\n this.setTimeout(type, () => this.hideStatus(type), 2500);\n break;\n case 'error':\n indicatorClass = '.error-indicator';\n if (options.message) {\n const errorSpan = this.statusContainer.querySelector('.error-indicator span');\n if (errorSpan) errorSpan.textContent = options.message;\n }\n this.setTimeout(type, () => this.hideStatus(type), 6000);\n break;\n }\n\n if (indicatorClass) {\n const indicator = this.statusContainer.querySelector(indicatorClass);\n if (indicator) {\n indicator.classList.remove('d-none');\n }\n }\n }\n\n /**\n * Hide a specific status indicator\n * @param {string} type - Status type to hide\n */\n hideStatus(type) {\n const indicator = this.statusContainer.querySelector(`[data-status=\"${type}\"]`);\n if (indicator) {\n indicator.classList.remove('show');\n indicator.classList.add('hide');\n\n // Actually hide after animation\n setTimeout(() => {\n indicator.classList.add('d-none');\n indicator.classList.remove('d-inline-block', 'hide');\n indicator.title = ''; // Clear any error message\n }, 300);\n }\n }\n\n /**\n * Hide all status indicators\n */\n hideAllStatuses() {\n const indicators = this.statusContainer.querySelectorAll('[data-status]');\n indicators.forEach(indicator => {\n indicator.classList.add('d-none');\n indicator.classList.remove('d-inline-block', 'show', 'hide');\n indicator.title = '';\n });\n }\n\n /**\n * Set a timeout for auto-hiding status\n * @param {string} type - Status type\n * @param {function} callback - Callback to execute\n * @param {number} delay - Delay in milliseconds\n */\n setTimeout(type, callback, delay) {\n const timeoutId = setTimeout(callback, delay);\n this.timeouts.set(type, timeoutId);\n }\n\n /**\n * Clear a specific timeout\n * @param {string} type - Status type\n */\n clearTimeout(type) {\n if (this.timeouts.has(type)) {\n clearTimeout(this.timeouts.get(type));\n this.timeouts.delete(type);\n }\n }\n\n /**\n * Clean up all timeouts\n */\n destroy() {\n this.timeouts.forEach(timeoutId => clearTimeout(timeoutId));\n this.timeouts.clear();\n }\n}\n\n// Apply FileDropMixin to FormView class\napplyFileDropMixin(FormView);\n\nexport default FormView;\nexport { FormView };\n"],"names":["Mustache","d","TagInput","CollectionSelect","CollectionMultiSelect","label"],"mappings":"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"}
1
+ {"version":3,"file":"FormView-DJBMpeMY.js","sources":["../../src/core/forms/FormPlugins.js","../../src/core/forms/FormBuilder.js","../../src/core/mixins/FileDropMixin.js","../../src/core/forms/inputs/TagInput.js","../../src/core/forms/inputs/CollectionSelect.js","../../src/core/forms/inputs/CollectionMultiSelect.js","../../src/core/forms/inputs/DatePicker.js","../../src/core/forms/inputs/DateRangePicker.js","../../src/core/forms/inputs/ComboInput.js","../../src/core/forms/FormView.js"],"sourcesContent":["/**\n * FormPlugins - Lightweight, pluggable registry for FormView/FormBuilder extensions\n *\n * Goals:\n * - Zero hard dependency on any single extension; core remains stable\n * - Extensions opt-in by calling FormPlugins.register(plugin)\n * - If no plugin is loaded, nothing changes\n *\n * A plugin is a plain object:\n * {\n * id: 'location', // required, unique\n * // Optional: custom field renderers by type\n * fieldTypes: {\n * 'address': (builder, fieldConfig) => stringHTML\n * },\n * // Optional lifecycle hooks\n * onFormBuilderInit(builder) {},\n * onFormViewInit(formView) {},\n * onAfterRender(formView) {},\n * onFieldInit(formView, fieldEl, fieldConfig) {},\n * onFieldChange(formView, fieldName, value) {}\n * }\n *\n * Usage (in an extension):\n * import { FormPlugins } from '@core/forms/FormPlugins.js';\n * const unregister = FormPlugins.register(myPlugin);\n * // later (optional)\n * unregister();\n */\n\nexport class FormPlugins {\n // Registered plugins\n static _plugins = [];\n // Map of field type => { renderer: Function, pluginId: string }\n static _renderers = new Map();\n\n /**\n * Register a plugin. If a plugin with the same id exists, it's replaced.\n * @param {object} plugin - Plugin definition (see header)\n * @returns {Function} unregister function\n */\n static register(plugin) {\n if (!plugin || typeof plugin !== 'object') {\n console.warn('[FormPlugins] register called with invalid plugin:', plugin);\n return () => {};\n }\n if (!plugin.id || typeof plugin.id !== 'string') {\n console.warn('[FormPlugins] plugin must have a unique string \"id\"', plugin);\n return () => {};\n }\n\n // Remove any previous plugin with same id\n this.unregister(plugin.id);\n\n // Register field renderers (if any)\n if (plugin.fieldTypes && typeof plugin.fieldTypes === 'object') {\n Object.entries(plugin.fieldTypes).forEach(([type, renderer]) => {\n if (typeof renderer === 'function') {\n this._renderers.set(type, { renderer, pluginId: plugin.id });\n } else {\n console.warn(`[FormPlugins] renderer for type \"${type}\" is not a function`);\n }\n });\n }\n\n // Store plugin\n this._plugins.push(plugin);\n\n // Return disposer\n return () => this.unregister(plugin.id);\n }\n\n /**\n * Unregister a plugin by id. Removes its field renderers as well.\n * @param {string} id - Plugin id\n */\n static unregister(id) {\n if (!id) return;\n\n // Remove from plugin list\n this._plugins = this._plugins.filter(p => p.id !== id);\n\n // Remove its renderers\n for (const [type, meta] of this._renderers.entries()) {\n if (meta?.pluginId === id) {\n this._renderers.delete(type);\n }\n }\n }\n\n /**\n * Get a custom field renderer by type (if registered).\n * @param {string} type - Field type\n * @returns {(builder: any, fieldConfig: object) => string | null}\n */\n static getRenderer(type) {\n const meta = this._renderers.get(type);\n return meta?.renderer || null;\n }\n\n /**\n * Returns true if a renderer exists for a field type\n */\n static hasRenderer(type) {\n return this._renderers.has(type);\n }\n\n /**\n * Get a shallow copy of registered plugins (read-only use).\n */\n static getPlugins() {\n return [...this._plugins];\n }\n\n // -----------------------------\n // Safe dispatch to plugin hooks\n // -----------------------------\n\n static _invoke(plugin, hook, ...args) {\n const fn = plugin?.[hook];\n if (typeof fn !== 'function') return;\n try {\n return fn.apply(plugin, args);\n } catch (err) {\n console.error(`[FormPlugins] ${hook} error from plugin \"${plugin.id}\":`, err);\n }\n }\n\n /**\n * Called by FormBuilder (e.g., in ctor or initializeTemplates)\n * @param {any} builder\n */\n static onFormBuilderInit(builder) {\n this._plugins.forEach(p => this._invoke(p, 'onFormBuilderInit', builder));\n }\n\n /**\n * Called by FormView constructor or early init\n * @param {any} formView\n */\n static onFormViewInit(formView) {\n this._plugins.forEach(p => this._invoke(p, 'onFormViewInit', formView));\n }\n\n /**\n * Called by FormView.onAfterRender\n * @param {any} formView\n */\n static onFormViewAfterRender(formView) {\n this._plugins.forEach(p => this._invoke(p, 'onAfterRender', formView));\n }\n\n /**\n * Called when a specific field element is initialized (after DOM exists)\n * @param {any} formView\n * @param {HTMLElement} fieldEl\n * @param {object} fieldConfig\n */\n static onFieldInit(formView, fieldEl, fieldConfig) {\n this._plugins.forEach(p => this._invoke(p, 'onFieldInit', formView, fieldEl, fieldConfig));\n }\n\n /**\n * Called when a field value changes (normalized point)\n * @param {any} formView\n * @param {string} fieldName\n * @param {any} value\n */\n static onFieldChange(formView, fieldName, value) {\n this._plugins.forEach(p => this._invoke(p, 'onFieldChange', formView, fieldName, value));\n }\n}\n\nexport default FormPlugins;","/**\n * FormBuilder - Pure HTML form generator for MOJO framework\n * Generates form HTML from field definitions with Bootstrap 5 grid layout support\n * NO event handling, lifecycle, or mounting - pure HTML generation only\n */\n\nimport Mustache from '@core/utils/mustache.js';\nimport MOJOUtils from '@core/utils/MOJOUtils.js';\nimport { FormPlugins } from '@core/forms/FormPlugins.js';\n\nclass FormBuilder {\n constructor(config = {}) {\n this.fields = config.fields || [];\n this.structureOnly = config.structureOnly || false; // New option\n\n // Convert cols to columns for all fields\n this.fields.forEach(field => {\n if (field.cols && !field.columns) {\n field.columns = field.cols;\n delete field.cols;\n } else if (!field.columns) {\n field.columns = 12;\n }\n\n // Handle nested fields in groups\n if (field.type === 'group' && field.fields) {\n field.fields.forEach(groupField => {\n if (groupField.cols && !groupField.columns) {\n groupField.columns = groupField.cols;\n delete groupField.cols;\n } else if (!groupField.columns) {\n groupField.columns = 12;\n }\n });\n }\n });\n\n this.options = {\n formClass: 'needs-validation',\n formMethod: 'POST',\n formAction: '',\n groupClass: 'row mb-3',\n fieldWrapper: '',\n labelClass: 'form-label',\n inputClass: 'form-control',\n errorClass: 'invalid-feedback',\n helpClass: 'form-text',\n submitButton: false,\n resetButton: false,\n ...config.options\n };\n this.buttons = config.buttons || [];\n this.data = config.data || {};\n this.errors = config.errors || {};\n this.initializeTemplates();\n }\n\n /**\n * Initialize field templates\n */\n initializeTemplates() {\n FormPlugins.onFormBuilderInit?.(this);\n this.templates = {\n input: `\n <div class=\"mojo-form-control\">\n {{#label}}\n <label for=\"{{fieldId}}\" class=\"{{labelClass}}\">\n {{label}}{{#required}}<span class=\"text-danger\">*</span>{{/required}}\n </label>\n {{/label}}\n <input type=\"{{type}}\" id=\"{{fieldId}}\" name=\"{{name}}\"\n class=\"{{inputClass}}{{#error}} is-invalid{{/error}}\"\n value=\"{{fieldValue}}\" {{#placeholder}}placeholder=\"{{placeholder}}\"{{/placeholder}}\n {{#required}}required{{/required}} {{#disabled}}disabled{{/disabled}}\n {{#readonly}}readonly{{/readonly}} {{{attrs}}}>\n {{#help}}<div class=\"{{helpClass}}\">{{help}}</div>{{/help}}\n {{#error}}<div class=\"{{errorClass}}\">{{error}}</div>{{/error}}\n </div>\n `,\n\n password: `\n <div class=\"mojo-form-control\">\n {{#label}}\n <label for=\"{{fieldId}}\" class=\"{{labelClass}}\">\n {{label}}{{#required}}<span class=\"text-danger\">*</span>{{/required}}\n </label>\n {{/label}}\n <div class=\"input-group\">\n <input type=\"password\" id=\"{{fieldId}}\" name=\"{{name}}\"\n class=\"{{inputClass}}{{#error}} is-invalid{{/error}}\"\n value=\"{{fieldValue}}\" {{#placeholder}}placeholder=\"{{placeholder}}\"{{/placeholder}}\n {{#required}}required{{/required}} {{#disabled}}disabled{{/disabled}}\n {{#readonly}}readonly{{/readonly}}\n data-field-type=\"password\" {{{attrs}}}>\n {{#showToggle}}\n <button type=\"button\" class=\"btn btn-outline-secondary\"\n data-action=\"toggle-password\"\n data-target=\"{{fieldId}}\"\n aria-label=\"Show password\" aria-pressed=\"false\">\n <i class=\"bi bi-eye\"></i>\n </button>\n {{/showToggle}}\n </div>\n {{#strengthMeter}}\n <div class=\"mt-2\">\n <div class=\"progress\" style=\"height: 4px;\">\n <div class=\"progress-bar bg-secondary\" role=\"progressbar\"\n style=\"width: 0%;\" aria-valuenow=\"0\" aria-valuemin=\"0\" aria-valuemax=\"100\"\n id=\"{{fieldId}}_strength_bar\"></div>\n </div>\n <small class=\"{{helpClass}}\" id=\"{{fieldId}}_strength_text\">Strength</small>\n </div>\n {{/strengthMeter}}\n {{#capsLockWarning}}\n <div class=\"{{helpClass}} text-warning d-none\" id=\"{{fieldId}}_caps_warning\">\n Caps Lock is on\n </div>\n {{/capsLockWarning}}\n {{#help}}<div class=\"{{helpClass}}\">{{help}}</div>{{/help}}\n {{#error}}<div class=\"{{errorClass}}\">{{error}}</div>{{/error}}\n </div>\n `,\n\n\n\n textarea: `\n <div class=\"mojo-form-control\">\n {{#label}}\n <label for=\"{{fieldId}}\" class=\"{{labelClass}}\">\n {{label}}{{#required}}<span class=\"text-danger\">*</span>{{/required}}\n </label>\n {{/label}}\n <textarea id=\"{{fieldId}}\" name=\"{{name}}\" class=\"{{inputClass}}{{#error}} is-invalid{{/error}}\"\n rows=\"{{rows}}\" {{#placeholder}}placeholder=\"{{placeholder}}\"{{/placeholder}}\n {{#required}}required{{/required}} {{#disabled}}disabled{{/disabled}}\n {{#readonly}}readonly{{/readonly}} {{{attrs}}}>{{fieldValue}}</textarea>\n {{#help}}<div class=\"{{helpClass}}\">{{help}}</div>{{/help}}\n {{#error}}<div class=\"{{errorClass}}\">{{error}}</div>{{/error}}\n </div>\n `,\n\n select: `\n <div class=\"mojo-form-control\">\n {{#label}}\n <label for=\"{{fieldId}}\" class=\"{{labelClass}}\">\n {{label}}{{#required}}<span class=\"text-danger\">*</span>{{/required}}\n </label>\n {{/label}}\n {{#searchInput}}{{{searchInput}}}{{/searchInput}}\n <select id=\"{{fieldId}}\" name=\"{{name}}\" class=\"{{inputClass}}{{#error}} is-invalid{{/error}}\"\n {{#required}}required{{/required}} {{#disabled}}disabled{{/disabled}}\n {{#multiple}}multiple{{/multiple}} {{{attrs}}}>\n {{{optionsHTML}}}\n </select>\n {{#help}}<div class=\"{{helpClass}}\">{{help}}</div>{{/help}}\n {{#error}}<div class=\"{{errorClass}}\">{{error}}</div>{{/error}}\n </div>\n `,\n\n checkbox: `\n <div class=\"mojo-form-control\">\n <div class=\"form-check {{fieldClass}}\">\n <input type=\"checkbox\" id=\"{{fieldId}}\" name=\"{{name}}\"\n class=\"form-check-input{{#error}} is-invalid{{/error}}\" value=\"{{value}}\"\n {{#checked}}checked{{/checked}} {{#required}}required{{/required}}\n {{#disabled}}disabled{{/disabled}} {{{attrs}}}>\n <label class=\"form-check-label\" for=\"{{fieldId}}\">{{label}}</label>\n </div>\n {{#help}}<div class=\"{{helpClass}}\">{{help}}</div>{{/help}}\n {{#error}}<div class=\"{{errorClass}}\">{{error}}</div>{{/error}}\n </div>\n </div>\n `,\n\n switch: `\n <div class=\"mojo-form-control\">\n <div class=\"form-check form-switch {{sizeClass}} {{fieldClass}}\">\n <input type=\"checkbox\" id=\"{{fieldId}}\" name=\"{{name}}\" role=\"switch\"\n class=\"form-check-input{{#error}} is-invalid{{/error}}\" value=\"{{value}}\"\n {{#checked}}checked{{/checked}} {{#required}}required{{/required}}\n {{#disabled}}disabled{{/disabled}} data-change-action=\"toggle-switch\"\n data-field=\"{{name}}\" {{{attrs}}}>\n <label class=\"form-check-label\" for=\"{{fieldId}}\">{{label}}</label>\n </div>\n {{#help}}<div class=\"{{helpClass}}\">{{help}}</div>{{/help}}\n {{#error}}<div class=\"{{errorClass}}\">{{error}}</div>{{/error}}\n </div>\n `,\n\n image: `\n <div class=\"mojo-form-control\">\n {{#label}}\n <label for=\"{{fieldId}}\" class=\"{{labelClass}}\">\n {{label}}{{#required}}<span class=\"text-danger\">*</span>{{/required}}\n </label>\n {{/label}}\n <div class=\"image-field-container {{containerClass}}\" id=\"{{dropZoneId}}\" style=\"width: {{width}}px; height: {{height}}px;\">\n <input type=\"file\" id=\"{{fieldId}}\" name=\"{{name}}\" class=\"{{inputClass}} d-none{{#error}} is-invalid{{/error}}\"\n accept=\"{{accept}}\" {{#required}}required{{/required}} {{#disabled}}disabled{{/disabled}}\n data-change-action=\"image-selected\" data-field=\"{{name}}\" {{{attrs}}}>\n <div class=\"image-drop-zone{{#allowDrop}} droppable{{/allowDrop}}\" data-action=\"click-image-upload\"\n data-field-id=\"{{fieldId}}\" data-field=\"{{name}}\" style=\"width: 100%; height: 100%; cursor: {{cursor}};\">\n {{#imageUrl}}\n <img id=\"{{previewId}}\" src=\"{{imageUrl}}\" alt=\"Preview\" class=\"img-thumbnail w-100 h-100\" style=\"object-fit: cover;\">\n {{#showRemove}}\n <button type=\"button\" class=\"btn btn-sm btn-danger position-absolute top-0 end-0 m-1\"\n data-action=\"remove-image\" data-field-id=\"{{fieldId}}\" data-field=\"{{name}}\" style=\"opacity: 0.8;\">\n <i class=\"bi bi-x\"></i>\n </button>\n {{/showRemove}}\n {{/imageUrl}}\n {{^imageUrl}}\n <div class=\"d-flex flex-column align-items-center justify-content-center h-100 text-muted border border-2 border-dashed\">\n <i class=\"bi bi-image fs-1 mb-2\"></i>\n <small class=\"text-center px-2\">{{placeholderText}}</small>\n </div>\n {{/imageUrl}}\n </div>\n </div>\n {{#help}}<div class=\"{{helpClass}}\">{{help}}</div>{{/help}}\n {{#error}}<div class=\"{{errorClass}}\">{{error}}</div>{{/error}}\n </div>\n `,\n\n range: `\n <div class=\"mojo-form-control\">\n {{#label}}\n <label for=\"{{fieldId}}\" class=\"{{labelClass}}\">\n {{label}}: <span id=\"{{fieldId}}_value\">{{fieldValue}}</span>\n </label>\n {{/label}}\n <input type=\"range\" id=\"{{fieldId}}\" name=\"{{name}}\" class=\"{{inputClass}}{{#error}} is-invalid{{/error}}\"\n min=\"{{min}}\" max=\"{{max}}\" step=\"{{step}}\" value=\"{{fieldValue}}\" {{#disabled}}disabled{{/disabled}}\n data-change-action=\"range-changed\" data-target=\"{{fieldId}}_value\" {{{attrs}}}>\n {{#help}}<div class=\"{{helpClass}}\">{{help}}</div>{{/help}}\n {{#error}}<div class=\"{{errorClass}}\">{{error}}</div>{{/error}}\n </div>\n `,\n\n file: `\n <div class=\"mojo-form-control\">\n {{#label}}\n <label for=\"{{fieldId}}\" class=\"{{labelClass}}\">\n {{label}}{{#required}}<span class=\"text-danger\">*</span>{{/required}}\n </label>\n {{/label}}\n <input type=\"file\" id=\"{{fieldId}}\" name=\"{{name}}\" class=\"{{inputClass}}{{#error}} is-invalid{{/error}}\"\n accept=\"{{accept}}\" {{#required}}required{{/required}} {{#disabled}}disabled{{/disabled}}\n {{#multiple}}multiple{{/multiple}} data-change-action=\"file-selected\" {{{attrs}}}>\n {{#help}}<div class=\"{{helpClass}}\">{{help}}</div>{{/help}}\n {{#error}}<div class=\"{{errorClass}}\">{{error}}</div>{{/error}}\n </div>\n `,\n\n radio: `\n <div class=\"mojo-form-control\">\n {{#label}}<div class=\"{{labelClass}}\">{{label}}{{#required}}<span class=\"text-danger\">*</span>{{/required}}</div>{{/label}}\n {{#options}}\n <div class=\"form-check\">\n <input type=\"radio\" id=\"{{fieldId}}_{{value}}\" name=\"{{name}}\" value=\"{{value}}\"\n class=\"form-check-input{{#error}} is-invalid{{/error}}\" {{#checked}}checked{{/checked}}\n {{#required}}required{{/required}} {{#disabled}}disabled{{/disabled}}\n {{{attrs}}}>\n <label class=\"form-check-label\" for=\"{{fieldId}}_{{value}}\">{{text}}</label>\n </div>\n {{/options}}\n {{#help}}<div class=\"{{helpClass}}\">{{help}}</div>{{/help}}\n {{#error}}<div class=\"{{errorClass}}\">{{error}}</div>{{/error}}\n </div>\n `,\n\n button: `\n <button type=\"button\" {{#name}}name=\"{{name}}\"{{/name}} class=\"btn {{fieldClass}}\"\n {{#action}}data-action=\"{{action}}\"{{/action}} {{#disabled}}disabled{{/disabled}} {{{attrs}}}>\n {{label}}\n </button>\n `,\n\n divider: `\n <hr class=\"{{dividerClass}}\">\n `,\n\n html: `\n <div class=\"form-html {{fieldClass}}\">{{{html}}}</div>\n `,\n\n header: `\n <h{{level}} {{#id}}id=\"{{id}}\"{{/id}} class=\"text-primary mb-3 {{fieldClass}}\">{{text}}</h{{level}}>\n `,\n\n hidden: `\n <input type=\"hidden\" id=\"{{fieldId}}\" name=\"{{name}}\" value=\"{{fieldValue}}\">\n `,\n\n checklistdropdown: `\n <div class=\"dropdown\">\n <button class=\"{{buttonClass}}\" type=\"button\" data-bs-toggle=\"dropdown\">\n <i class=\"{{buttonIcon}} me-1\"></i> {{buttonText}}\n </button>\n <div class=\"{{dropdownClass}}\" style=\"min-width: {{minWidth}};\">\n {{#options}}\n <div class=\"form-check\">\n <input class=\"form-check-input\" type=\"checkbox\"\n value=\"{{value}}\"\n id=\"{{id}}\"\n {{#checked}}checked{{/checked}}\n data-change-action=\"update-checklist\"\n data-field=\"{{fieldName}}\">\n <label class=\"form-check-label\" for=\"{{id}}\">\n {{label}}\n </label>\n </div>\n {{/options}}\n <hr class=\"my-2\">\n <button class=\"btn btn-sm btn-primary w-100\" data-action=\"apply-filter\">\n Apply\n </button>\n </div>\n </div>\n `,\n\n buttongroup: `\n <div class=\"btn-group btn-group-{{size}}\" role=\"group\">\n {{#options}}\n <button type=\"button\" class=\"{{buttonClass}} {{#active}}active{{/active}}\"\n {{^action}}\n data-action=\"select-button-option\"\n {{/action}}\n {{#action}}\n data-action='{{action}}'\n {{/action}}\n data-field=\"{{fieldName}}\"\n data-value=\"{{value}}\">\n {{#icon}}<i class=\"{{icon}} me-1\"></i> {{/icon}} {{label}}\n </button>\n {{/options}}\n </div>\n `,\n\n toolbarform: `\n <div class=\"mojo-toolbar-form\">\n <div class=\"row g-2 align-items-center\">\n {{#fields}}\n <div class=\"{{containerClass}}\">\n {{#label}}<label class=\"form-label-sm mb-1\">{{label}}</label>{{/label}}\n {{{fieldHtml}}}\n </div>\n {{/fields}}\n </div>\n </div>\n `,\n\n color: `\n <div class=\"mojo-form-control\">\n {{#label}}\n <label for=\"{{fieldId}}\" class=\"{{labelClass}}\">\n {{label}}{{#required}}<span class=\"text-danger\">*</span>{{/required}}\n </label>\n {{/label}}\n <div class=\"d-flex align-items-center gap-2\">\n <input type=\"color\" id=\"{{fieldId}}\" name=\"{{name}}\"\n class=\"{{inputClass}}{{#error}} is-invalid{{/error}}\"\n value=\"{{fieldValue}}\"\n {{#required}}required{{/required}} {{#disabled}}disabled{{/disabled}}\n {{#readonly}}readonly{{/readonly}} {{{attrs}}}>\n <button type=\"button\" class=\"btn-sm text-muted border-0 bg-transparent p-1\"\n data-action=\"clear-color\" data-field=\"{{name}}\"\n title=\"Clear color\">\n <i class=\"bi bi-x fs-5\"></i>\n </button>\n </div>\n {{#help}}<div class=\"{{helpClass}}\">{{help}}</div>{{/help}}\n {{#error}}<div class=\"{{errorClass}}\">{{error}}</div>{{/error}}\n </div>\n `\n };\n }\n\n /**\n * Generate complete form HTML\n * @returns {string} Complete form HTML\n */\n buildFormHTML() {\n const fieldsHTML = this.buildFieldsHTML();\n const buttonsHTML = this.buildButtonsHTML();\n\n return `\n <form class=\"${this.options.formClass}\" novalidate>\n ${fieldsHTML}\n ${buttonsHTML}\n </form>\n `;\n }\n\n /**\n * Generate HTML for all fields\n * @returns {string} Fields HTML\n */\n /**\n * Check if field should use auto-sizing columns (class=\"col\")\n * @param {object} field - Field configuration\n * @returns {boolean}\n */\n isAutoSizingField(field) {\n return !field.columns || field.columns === 'auto' || field.columns === '';\n }\n\n buildFieldsHTML() {\n const result = [];\n let i = 0;\n\n while (i < this.fields.length) {\n const field = this.fields[i];\n field.columns = field.columns || field.cols;\n\n if (field.type === 'group') {\n // Collect consecutive groups that should be in a row\n const groupsInRow = [field];\n let totalColumns = field.columns || 12;\n\n // Handle responsive columns - use md breakpoint for calculation, fallback to largest available\n if (typeof totalColumns === 'object' && totalColumns !== null) {\n totalColumns = totalColumns.md || totalColumns.sm || totalColumns.xs || 12;\n }\n\n let j = i + 1;\n\n // Look ahead for more groups that can fit in the same row\n while (j < this.fields.length &&\n this.fields[j].type === 'group' &&\n totalColumns < 12) {\n const nextGroup = this.fields[j];\n let nextColumns = nextGroup.columns || 12;\n\n // Handle responsive columns - use md breakpoint for calculation, fallback to largest available\n if (typeof nextColumns === 'object' && nextColumns !== null) {\n nextColumns = nextColumns.md || nextColumns.sm || nextColumns.xs || 12;\n }\n\n if (totalColumns + nextColumns <= 12) {\n groupsInRow.push(nextGroup);\n totalColumns += nextColumns;\n j++;\n } else {\n break;\n }\n }\n\n // If we have multiple groups or a single group with specific columns, wrap in row\n let shouldWrap = groupsInRow.length > 1;\n\n // Check if single group has specific columns (not full width)\n if (groupsInRow.length === 1 && field.columns) {\n let cols = field.columns;\n if (typeof cols === 'object' && cols !== null) {\n cols = cols.md || cols.sm || cols.xs || 12;\n }\n shouldWrap = shouldWrap || cols < 12;\n }\n\n if (shouldWrap) {\n const groupsHTML = groupsInRow.map(group => this.buildGroupHTML(group)).join('');\n result.push(`<div class=\"row\">${groupsHTML}</div>`);\n } else {\n result.push(this.buildGroupHTML(field));\n }\n\n i = j;\n } else if (field.columns && field.columns < 12) {\n // Collect consecutive fields with columns that should be in a row\n const fieldsInRow = [field];\n let totalColumns = field.columns || 12;\n\n // Handle responsive columns - use md breakpoint for calculation, fallback to largest available\n if (typeof totalColumns === 'object' && totalColumns !== null) {\n totalColumns = totalColumns.md || totalColumns.sm || totalColumns.xs || 12;\n }\n\n let j = i + 1;\n\n // Look ahead for more fields that can fit in the same row\n while (j < this.fields.length &&\n this.fields[j].columns &&\n totalColumns < 12) {\n const nextField = this.fields[j];\n let nextColumns = nextField.columns || 12;\n\n // Handle responsive columns - use md breakpoint for calculation, fallback to largest available\n if (typeof nextColumns === 'object' && nextColumns !== null) {\n nextColumns = nextColumns.md || nextColumns.sm || nextColumns.xs || 12;\n }\n\n if (totalColumns + nextColumns <= 12) {\n fieldsInRow.push(nextField);\n totalColumns += nextColumns;\n j++;\n } else {\n break;\n }\n }\n\n // Wrap fields in a row\n const fieldsHTML = fieldsInRow.map(f => this.buildFieldHTML(f)).join('');\n result.push(`<div class=\"row\">${fieldsHTML}</div>`);\n\n i = j;\n } else if (this.isAutoSizingField(field)) {\n // Collect consecutive auto-sizing fields that should be in a row\n const fieldsInRow = [field];\n let j = i + 1;\n\n // Look ahead for more auto-sizing fields\n while (j < this.fields.length) {\n const nextField = this.fields[j];\n if (this.isAutoSizingField(nextField)) {\n fieldsInRow.push(nextField);\n j++;\n } else {\n break;\n }\n }\n\n // If we have multiple auto-sizing fields, wrap them in a row\n if (fieldsInRow.length > 1) {\n const fieldsHTML = fieldsInRow.map(f => this.buildFieldHTML(f)).join('');\n result.push(`<div class=\"row\">${fieldsHTML}</div>`);\n } else {\n // Single auto-sizing field, still wrap in row for consistency\n result.push(`<div class=\"row\">${this.buildFieldHTML(field)}</div>`);\n }\n\n i = j;\n } else {\n result.push(this.buildFieldHTML(field));\n i++;\n }\n }\n\n return result.join('');\n }\n\n /**\n * Generate HTML for a field group with column layout\n * @param {Object} group - Group configuration\n * @returns {string} Group HTML\n */\n buildGroupHTML(group) {\n const {\n columns = 12,\n title,\n fields = [],\n class: groupClass = '',\n titleClass = 'h6 mb-3',\n responsive = {}\n } = group;\n\n // Build responsive column classes\n let colClasses = [];\n\n // Handle columns as object (responsive) or number (legacy)\n if (typeof columns === 'object' && columns !== null) {\n // New responsive syntax: columns: { xs: 12, sm: 6, md: 4, lg: 3 }\n if (columns.xs) colClasses.push(`col-${columns.xs}`);\n if (columns.sm) colClasses.push(`col-sm-${columns.sm}`);\n if (columns.md) colClasses.push(`col-md-${columns.md}`);\n if (columns.lg) colClasses.push(`col-lg-${columns.lg}`);\n if (columns.xl) colClasses.push(`col-xl-${columns.xl}`);\n if (columns.xxl) colClasses.push(`col-xxl-${columns.xxl}`);\n\n // If no md is specified but xs/sm are, use xs or sm as fallback for md\n if (!columns.md && (columns.xs || columns.sm)) {\n const fallback = columns.sm || columns.xs;\n colClasses.push(`col-md-${fallback}`);\n }\n\n // If no breakpoints specified at all, default to col-md-12\n if (colClasses.length === 0) {\n colClasses.push('col-md-12');\n }\n } else {\n // Legacy syntax: columns: 6\n colClasses.push(`col-md-${columns}`);\n }\n\n // Support legacy responsive property (for backward compatibility)\n if (responsive.xs) colClasses.push(`col-${responsive.xs}`);\n if (responsive.sm) colClasses.push(`col-sm-${responsive.sm}`);\n if (responsive.lg) colClasses.push(`col-lg-${responsive.lg}`);\n if (responsive.xl) colClasses.push(`col-xl-${responsive.xl}`);\n\n const colClass = colClasses.join(' ');\n const fieldsHTML = fields.map(field => {\n if (field.type === 'group') {\n // Nested groups (limited depth)\n return this.buildGroupHTML(field);\n }\n return this.buildFieldHTML(field);\n }).join('');\n\n return `\n <div class=\"${colClass}\">\n <div class=\"mojo-form-group ${groupClass}\">\n ${title ? `<div class=\"${titleClass}\">${this.escapeHtml(title)}</div>` : ''}\n <div class=\"row\">\n ${fieldsHTML}\n </div>\n </div>\n </div>\n `;\n }\n\n /**\n * Generate HTML for a single field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n buildFieldHTML(field) {\n const { type, columns, class: fieldClass = '' } = field;\n\n let fieldHTML = '';\n // If a plugin registered a custom renderer for this field type, use it\n const customRenderer = (FormPlugins && typeof FormPlugins.getRenderer === 'function')\n ? FormPlugins.getRenderer(type)\n : null;\n if (typeof customRenderer === 'function') {\n try {\n const custom = customRenderer(this, field);\n if (custom !== undefined && custom !== null) {\n fieldHTML = String(custom);\n }\n } catch (err) {\n console.error('FormPlugins custom renderer error:', err);\n }\n }\n if (!fieldHTML) {\n console.log('buildFieldHTML - Processing field type:', type, 'for field:', field.name);\n switch (type) {\n case 'text':\n fieldHTML = this.renderTextField(field);\n break;\n case 'email':\n fieldHTML = this.renderEmailField(field);\n break;\n case 'password':\n fieldHTML = this.renderPasswordField(field);\n break;\n case 'number':\n fieldHTML = this.renderNumberField(field);\n break;\n case 'tel':\n fieldHTML = this.renderTelField(field);\n break;\n case 'url':\n fieldHTML = this.renderUrlField(field);\n break;\n case 'search':\n fieldHTML = this.renderSearchField(field);\n break;\n case 'hex':\n fieldHTML = this.renderHexField(field);\n break;\n case 'textarea':\n fieldHTML = this.renderTextareaField(field);\n break;\n case 'json':\n fieldHTML = this.renderJsonField(field);\n break;\n case 'select':\n fieldHTML = this.renderSelectField(field);\n break;\n case 'checkbox':\n fieldHTML = this.renderCheckboxField(field);\n break;\n case 'toggle':\n case 'switch':\n fieldHTML = this.renderSwitchField(field);\n break;\n case 'radio':\n fieldHTML = this.renderRadioField(field);\n break;\n case 'date':\n fieldHTML = this.renderDateField(field);\n break;\n case 'datetime':\n fieldHTML = this.renderDateTimeField(field);\n break;\n case 'time':\n fieldHTML = this.renderTimeField(field);\n break;\n case 'file':\n fieldHTML = this.renderFileField(field);\n break;\n case 'image':\n fieldHTML = this.renderImageField(field);\n break;\n case 'color':\n fieldHTML = this.renderColorField(field);\n break;\n case 'range':\n fieldHTML = this.renderRangeField(field);\n break;\n case 'hidden':\n fieldHTML = this.renderHiddenField(field);\n break;\n case 'button':\n fieldHTML = this.renderButton(field);\n break;\n case 'divider':\n fieldHTML = this.renderDivider(field);\n break;\n case 'html':\n fieldHTML = this.renderHtmlField(field);\n break;\n case 'heading':\n case 'header':\n fieldHTML = this.renderHeaderField(field);\n break;\n case 'tag':\n case 'tags':\n fieldHTML = this.renderTagField(field);\n break;\n case 'collection':\n fieldHTML = this.renderCollectionField(field);\n break;\n case 'collectionmultiselect':\n case 'collection-multiselect':\n fieldHTML = this.renderCollectionMultiSelectField(field);\n break;\n case 'datepicker':\n fieldHTML = this.renderDatePickerField(field);\n break;\n case 'daterange':\n fieldHTML = this.renderDateRangeField(field);\n break;\n case 'checklistdropdown':\n fieldHTML = this.renderChecklistDropdownField(field);\n break;\n case 'buttongroup':\n fieldHTML = this.renderButtonGroupField(field);\n break;\n case 'combo':\n case 'combobox':\n case 'autocomplete':\n fieldHTML = this.renderComboField(field);\n break;\n case 'tabset':\n fieldHTML = this.renderTabsetField(field);\n break;\n default:\n console.warn(`Unknown field type: ${type}`);\n fieldHTML = this.renderTextField(field);\n }\n }\n\n // Wrap field in column - handle auto-sizing columns\n let colClass;\n if (this.isAutoSizingField(field)) {\n colClass = `col ${fieldClass}`.trim();\n } else {\n colClass = `col-${columns} ${fieldClass}`.trim();\n }\n return `<div class=\"${colClass}\">${fieldHTML}</div>`;\n }\n\n /**\n * Generate field ID\n * @param {string} name - Field name\n * @returns {string} Unique field ID\n */\n getFieldId(name) {\n // Replace dots, spaces, and special characters with underscores for valid HTML IDs\n if (!name) {\n return `field_${Math.random().toString(36).substr(2, 9)}`;\n }\n const safeName = name.replace(/[.\\s\\[\\]]/g, '_');\n return `field_${safeName}`;\n }\n\n /**\n * Render text input field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderTextField(field) {\n return this.renderInputField(field, 'text');\n }\n\n /**\n * Render email input field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderEmailField(field) {\n return this.renderInputField(field, 'email');\n }\n\n /**\n * Render password input field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderPasswordField(field) {\n const passwordUsage = field.passwordUsage || 'current';\n const inferredAutocomplete =\n passwordUsage === 'new' || passwordUsage === 'new-password'\n ? 'new-password'\n : 'current-password';\n\n const attributes = {\n ...(field.attributes || {}),\n autocomplete: (field.attributes && field.attributes.autocomplete) || inferredAutocomplete\n };\n\n return this.renderInputField(\n {\n ...field,\n showToggle: field.showToggle !== false, // default to showing the toggle unless explicitly disabled\n attributes\n },\n 'password'\n );\n }\n\n /**\n * Render number input field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderNumberField(field) {\n const {\n min,\n max,\n step = 1,\n ...baseField\n } = field;\n\n const attrs = [];\n if (min !== undefined) attrs.push(`min=\"${min}\"`);\n if (max !== undefined) attrs.push(`max=\"${max}\"`);\n if (step !== undefined) attrs.push(`step=\"${step}\"`);\n\n return this.renderInputField({\n ...baseField,\n attributes: { ...baseField.attributes, ...attrs.reduce((obj, attr) => {\n const [key, value] = attr.split('=');\n obj[key] = value.replace(/\"/g, '');\n return obj;\n }, {}) }\n }, 'number');\n }\n\n /**\n * Render tel input field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderTelField(field) {\n return this.renderInputField(field, 'tel');\n }\n\n /**\n * Render URL input field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderUrlField(field) {\n return this.renderInputField(field, 'url');\n }\n\n /**\n * Render search input field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderSearchField(field) {\n const searchField = {\n ...field,\n attributes: {\n 'data-filter': 'live-search',\n 'data-change-action': 'filter-search',\n 'data-filter-debounce': field.debounce || '300',\n ...field.attributes\n }\n };\n return this.renderInputField(searchField, 'search');\n }\n\n /**\n * Render hex input field with validation\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderHexField(field) {\n const {\n hexType = 'color', // 'color', 'string', 'any'\n allowPrefix = true,\n minLength: originalMinLength,\n maxLength: originalMaxLength,\n ...baseField\n } = field;\n\n let pattern, minLength, maxLength, placeholder, help;\n\n switch (hexType) {\n case 'color':\n // Hex color: #RRGGBB or RRGGBB\n pattern = allowPrefix ? '^#?[0-9A-Fa-f]{6}$' : '^[0-9A-Fa-f]{6}$';\n minLength = allowPrefix ? 6 : 6;\n maxLength = allowPrefix ? 7 : 6;\n placeholder = allowPrefix ? '#FF0000' : 'FF0000';\n help = help || 'Enter a valid hex color (e.g., ' + placeholder + ')';\n break;\n\n case 'color-short':\n // Hex color: #RGB or RGB, #RRGGBB or RRGGBB\n pattern = allowPrefix ? '^#?[0-9A-Fa-f]{3}([0-9A-Fa-f]{3})?$' : '^[0-9A-Fa-f]{3}([0-9A-Fa-f]{3})?$';\n minLength = allowPrefix ? 4 : 3;\n maxLength = allowPrefix ? 7 : 6;\n placeholder = allowPrefix ? '#F00 or #FF0000' : 'F00 or FF0000';\n help = help || 'Enter a valid hex color (3 or 6 digits)';\n break;\n\n case 'string':\n // General hex string\n pattern = '^[0-9A-Fa-f]+$';\n minLength = originalMinLength || 1;\n maxLength = originalMaxLength || 64;\n placeholder = 'ABCDEF123456';\n help = help || 'Only hexadecimal characters (0-9, A-F) allowed';\n break;\n\n default:\n // Any hex format\n pattern = allowPrefix ? '^#?[0-9A-Fa-f]+$' : '^[0-9A-Fa-f]+$';\n minLength = originalMinLength || 1;\n maxLength = originalMaxLength || 64;\n placeholder = allowPrefix ? '#ABCDEF or ABCDEF' : 'ABCDEF';\n help = help || 'Enter hexadecimal characters only';\n }\n\n const hexField = {\n ...baseField,\n pattern,\n minLength,\n maxLength,\n placeholder: baseField.placeholder || placeholder,\n help: baseField.help || help,\n attributes: {\n 'data-hex-type': hexType,\n 'data-allow-prefix': allowPrefix,\n 'style': 'text-transform: uppercase;',\n ...baseField.attributes\n }\n };\n\n return this.renderInputField(hexField, 'text');\n }\n\n /**\n * Render generic input field\n * @param {Object} field - Field configuration\n * @param {string} type - Input type\n * @returns {string} Field HTML\n */\n renderInputField(field, type = 'text') {\n const {\n name,\n label,\n value = '',\n placeholder = '',\n required = false,\n disabled = false,\n readonly = false,\n class: fieldClass = '',\n attributes = {},\n help = field.helpText || field.help || ''\n } = field;\n\n const inputClass = `${this.options.inputClass} ${fieldClass}`.trim();\n const error = this.errors[name];\n const fieldValue = (this.getFieldValue(name) ?? value);\n\n const attrs = Object.entries(attributes).map(([key, val]) => `${key}=\"${this.escapeHtml(val)}\"`).join(' ');\n const fieldId = this.getFieldId(name);\n\n const context = {\n labelClass: this.options.labelClass,\n inputClass: inputClass,\n helpClass: this.options.helpClass,\n errorClass: this.options.errorClass,\n fieldId,\n name,\n type,\n fieldValue: this.escapeHtml(fieldValue),\n label: label ? this.escapeHtml(label) : null,\n placeholder: placeholder ? this.escapeHtml(placeholder) : null,\n help: help ? this.escapeHtml(help) : null,\n error: error ? this.escapeHtml(error) : null,\n required,\n disabled,\n readonly,\n attrs\n };\n\n if (type === 'password' && (field.showToggle || field.strengthMeter || field.capsLockWarning)) {\n const enhancedContext = {\n ...context,\n showToggle: !!field.showToggle,\n strengthMeter: !!field.strengthMeter,\n capsLockWarning: !!field.capsLockWarning\n };\n return Mustache.render(this.templates.password, enhancedContext);\n }\n if (type === 'password') {\n const enhancedContext = {\n ...context,\n showToggle: field.showToggle !== false,\n strengthMeter: !!field.strengthMeter,\n capsLockWarning: !!field.capsLockWarning\n };\n return Mustache.render(this.templates.password, enhancedContext);\n }\n return Mustache.render(this.templates.input, context);\n }\n\n /**\n * Render textarea field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderTextareaField(field) {\n const {\n name,\n label,\n value = '',\n placeholder = '',\n required = false,\n disabled = false,\n readonly = false,\n rows = 3,\n cols: _cols,\n class: fieldClass = '',\n attributes = {},\n help = field.helpText || field.help || ''\n } = field;\n\n const inputClass = `${this.options.inputClass} ${fieldClass}`.trim();\n const error = this.errors[name];\n const fieldValue = (this.getFieldValue(name) ?? value);\n\n const attrs = Object.entries(attributes).map(([key, val]) => `${key}=\"${this.escapeHtml(val)}\"`).join(' ');\n const fieldId = this.getFieldId(name);\n\n const context = {\n labelClass: this.options.labelClass,\n inputClass: inputClass,\n helpClass: this.options.helpClass,\n errorClass: this.options.errorClass,\n fieldId,\n name,\n fieldValue: fieldValue, // Pass raw value to template for correct rendering\n label: label ? this.escapeHtml(label) : null,\n placeholder: placeholder ? this.escapeHtml(placeholder) : null,\n help: help ? this.escapeHtml(help) : null,\n error: error ? this.escapeHtml(error) : null,\n rows: rows || 3,\n required,\n disabled,\n readonly,\n attrs\n };\n\n return Mustache.render(this.templates.textarea, context);\n }\n\n /**\n * Render JSON field as a textarea\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderJsonField(field) {\n const {\n name,\n label,\n placeholder = '',\n required = false,\n disabled = false,\n readonly = false,\n rows = 3,\n class: fieldClass = '',\n attributes = {},\n help = field.helpText || field.help || ''\n } = field;\n\n const rawValue = this.getFieldValue(field.name) ?? field.value ?? {};\n let formattedValue = rawValue;\n\n if (typeof rawValue === 'object' && rawValue !== null) {\n try {\n formattedValue = JSON.stringify(rawValue, null, 2);\n } catch (e) {\n formattedValue = \"{}\";\n }\n } else if (typeof rawValue !== 'string') {\n formattedValue = String(rawValue);\n }\n\n const inputClass = `${this.options.inputClass} ${fieldClass}`.trim();\n const error = this.errors[name];\n const fieldId = this.getFieldId(name);\n\n const attrs = Object.entries({\n ...attributes,\n 'data-field-type': 'json'\n }).map(([key, val]) => `${key}=\"${this.escapeHtml(val)}\"`).join(' ');\n\n const context = {\n labelClass: this.options.labelClass,\n inputClass: inputClass,\n helpClass: this.options.helpClass,\n errorClass: this.options.errorClass,\n fieldId,\n name,\n fieldValue: formattedValue, // Use the formatted JSON string directly\n label: label ? this.escapeHtml(label) : null,\n placeholder: placeholder ? this.escapeHtml(placeholder) : null,\n help: help ? this.escapeHtml(help) : null,\n error: error ? this.escapeHtml(error) : null,\n rows: rows || 3,\n required,\n disabled,\n readonly,\n attrs\n };\n\n return Mustache.render(this.templates.textarea, context);\n }\n\n\n\n /**\n * Render select field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderSelectField(field) {\n const {\n name,\n label,\n options = [],\n value = '',\n required = false,\n disabled = false,\n multiple = false,\n searchable = false,\n class: fieldClass = '',\n attributes = {},\n help = field.helpText || field.help || '',\n // Auto-generation parameters\n start = field.start,\n end = field.end,\n step = field.step,\n format = field.format,\n prefix = field.prefix,\n suffix = field.suffix\n } = field;\n\n const inputClass = `form-select ${fieldClass}`.trim();\n const error = this.errors[name];\n const dataValue = this.getFieldValue(name);\n const fieldValue = (dataValue ?? value);\n\n const attrs = Object.entries(attributes).map(([key, val]) => `${key}=\"${this.escapeHtml(val)}\"`).join(' ');\n const fieldId = this.getFieldId(name);\n\n // Generate options automatically if start/end are provided\n let generatedOptions = [...options];\n if (start !== undefined && end !== undefined) {\n const stepValue = step !== undefined ? step : 1;\n const autoOptions = this.generateSelectOptions(start, end, stepValue, { format, prefix, suffix });\n // Append auto-generated options after any manually specified ones\n generatedOptions = [...generatedOptions, ...autoOptions];\n }\n\n let optionsHTML = '';\n if (Array.isArray(generatedOptions)) {\n optionsHTML = generatedOptions.map(option => {\n if (typeof option === 'string') {\n const selected = option === fieldValue ? 'selected' : '';\n return `<option value=\"${this.escapeHtml(option)}\" ${selected}>${this.escapeHtml(option)}</option>`;\n } else if (option && typeof option === 'object') {\n // Use loose equality (==) to handle string/number type coercion\n const selected = option.value == fieldValue ? 'selected' : '';\n return `<option value=\"${this.escapeHtml(option.value)}\" ${selected}>${this.escapeHtml(option.label || option.text || option.value)}</option>`;\n }\n return '';\n }).join('');\n }\n\n const searchInput = searchable ? `\n <input type=\"text\"\n class=\"form-control form-control-sm mb-2\"\n placeholder=\"Search options...\"\n data-filter=\"live-search\"\n data-change-action=\"filter-select-options\"\n data-target=\"${fieldId}\">\n ` : '';\n\n const context = {\n labelClass: this.options.labelClass,\n inputClass: inputClass,\n helpClass: this.options.helpClass,\n errorClass: this.options.errorClass,\n fieldId,\n name,\n label: label ? this.escapeHtml(label) : null,\n help: help ? this.escapeHtml(help) : null,\n error: error ? this.escapeHtml(error) : null,\n searchInput: searchable ? searchInput : null,\n optionsHTML,\n required,\n disabled,\n multiple,\n attrs\n };\n\n return Mustache.render(this.templates.select, context);\n }\n\n /**\n * Render checkbox field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderCheckboxField(field) {\n const {\n name,\n label,\n value = false,\n required = false,\n disabled = false,\n class: fieldClass = '',\n attributes = {},\n help = field.helpText || field.help || ''\n } = field;\n\n const error = this.errors[name];\n const fieldValue = (this.getFieldValue(name) ?? value);\n const checked = fieldValue === true || fieldValue === 'true' || fieldValue === '1';\n\n const attrs = Object.entries(attributes).map(([key, val]) => `${key}=\"${this.escapeHtml(val)}\"`).join(' ');\n const fieldId = this.getFieldId(name);\n\n const context = {\n helpClass: this.options.helpClass,\n errorClass: this.options.errorClass,\n fieldId,\n name,\n label: this.escapeHtml(label),\n help: help ? this.escapeHtml(help) : null,\n error: error ? this.escapeHtml(error) : null,\n value: this.escapeHtml(value),\n fieldClass,\n checked,\n required,\n disabled,\n attrs\n };\n\n return Mustache.render(this.templates.checkbox, context);\n }\n\n /**\n * Render switch field (enhanced checkbox)\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderSwitchField(field) {\n const {\n name,\n label,\n value = false,\n required = false,\n disabled = false,\n size = 'md',\n class: fieldClass = '',\n attributes = {},\n help = field.helpText || field.help || ''\n } = field;\n\n const error = this.errors[name];\n const fieldValue = (this.getFieldValue(name) ?? value);\n const checked = fieldValue === true || fieldValue === 'true' || fieldValue === '1';\n\n const attrs = Object.entries(attributes).map(([key, val]) => `${key}=\"${this.escapeHtml(val)}\"`).join(' ');\n const fieldId = this.getFieldId(name);\n const sizeClass = size !== 'md' ? `form-switch-${size}` : '';\n\n const context = {\n helpClass: this.options.helpClass,\n errorClass: this.options.errorClass,\n fieldId,\n name,\n label: this.escapeHtml(label),\n help: help ? this.escapeHtml(help) : null,\n error: error ? this.escapeHtml(error) : null,\n value: this.escapeHtml(value),\n sizeClass,\n fieldClass,\n checked,\n required,\n disabled,\n attrs\n };\n\n return Mustache.render(this.templates.switch, context);\n }\n\n /**\n * Render radio field group\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderRadioField(field) {\n const {\n name,\n label,\n options = [],\n value = '',\n disabled = false,\n inline = false,\n class: fieldClass = '',\n attributes = {},\n help = field.helpText || field.help || ''\n } = field;\n\n const error = this.errors[name];\n const fieldValue = (this.getFieldValue(name) ?? value);\n\n const attrs = Object.entries(attributes).map(([key, val]) => `${key}=\"${this.escapeHtml(val)}\"`).join(' ');\n\n let optionsHTML = '';\n if (Array.isArray(options)) {\n optionsHTML = options.map((option, index) => {\n const radioId = `${name}_${index}`;\n const radioValue = typeof option === 'string' ? option : option.value;\n const radioLabel = typeof option === 'string' ? option : option.label || option.text || option.value;\n const checked = radioValue === fieldValue ? 'checked' : '';\n const inlineClass = inline ? 'form-check-inline' : '';\n\n return `\n <div class=\"form-check ${inlineClass}\">\n <input\n type=\"radio\"\n id=\"${radioId}\"\n name=\"${name}\"\n class=\"form-check-input ${error ? 'is-invalid' : ''}\"\n value=\"${this.escapeHtml(radioValue)}\"\n ${checked}\n ${disabled ? 'disabled' : ''}\n\n ${attrs}\n >\n <label class=\"form-check-label\" for=\"${radioId}\">\n ${this.escapeHtml(radioLabel)}\n </label>\n </div>\n `;\n }).join('');\n }\n\n return `\n <div class=\"mojo-form-control\">\n ${label ? `<fieldset>\n <legend class=\"${this.options.labelClass}\">${this.escapeHtml(label)}</legend>\n <div class=\"${fieldClass}\">\n ${optionsHTML}\n </div>\n </fieldset>` : `<div class=\"${fieldClass}\">${optionsHTML}</div>`}\n ${help ? `<div class=\"${this.options.helpClass}\">${this.escapeHtml(help)}</div>` : ''}\n ${error ? `<div class=\"${this.options.errorClass}\">${this.escapeHtml(error)}</div>` : ''}\n </div>\n `;\n }\n\n /**\n * Render date field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderDateField(field) {\n return this.renderInputField(field, 'date');\n }\n\n /**\n * Render datetime field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderDateTimeField(field) {\n return this.renderInputField(field, 'datetime-local');\n }\n\n /**\n * Render time field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderTimeField(field) {\n return this.renderInputField(field, 'time');\n }\n\n /**\n * Render file field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderFileField(field) {\n const {\n name,\n label,\n required = false,\n disabled = false,\n multiple = false,\n accept = '*/*',\n class: fieldClass = '',\n attributes = {},\n help = field.helpText || field.help || ''\n } = field;\n\n const inputClass = `${this.options.inputClass} ${fieldClass}`.trim();\n const error = this.errors[name];\n\n const attrs = Object.entries(attributes).map(([key, val]) => `${key}=\"${this.escapeHtml(val)}\"`).join(' ');\n const fieldId = this.getFieldId(name);\n\n const context = {\n labelClass: this.options.labelClass,\n inputClass: inputClass,\n helpClass: this.options.helpClass,\n errorClass: this.options.errorClass,\n fieldId,\n name,\n label: label ? this.escapeHtml(label) : null,\n help: help ? this.escapeHtml(help) : null,\n error: error ? this.escapeHtml(error) : null,\n accept,\n required,\n disabled,\n multiple,\n attrs\n };\n\n return Mustache.render(this.templates.file, context);\n }\n\n /**\n * Render enhanced image field with drag & drop support\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderImageField(field) {\n const {\n name,\n label,\n required = false,\n disabled = false,\n accept = 'image/*',\n class: fieldClass = '',\n attributes = {},\n help = field.helpText || field.help || '',\n size = 'md',\n allowDrop = true,\n placeholder = 'Drop image here or click to upload'\n } = field;\n\n const inputClass = `${this.options.inputClass} ${fieldClass}`.trim();\n const error = this.errors[name];\n const fieldId = this.getFieldId(name);\n const dropZoneId = `${fieldId}_dropzone`;\n const previewId = `${fieldId}_preview`;\n\n // Size configurations\n const sizeMap = {\n xs: { width: 48, height: 48, containerClass: 'image-field-xs' },\n sm: { width: 96, height: 96, containerClass: 'image-field-sm' },\n md: { width: 150, height: 150, containerClass: 'image-field-md' },\n lg: { width: 200, height: 200, containerClass: 'image-field-lg' },\n xl: { width: 300, height: 300, containerClass: 'image-field-xl' }\n };\n\n const sizeConfig = sizeMap[size] || sizeMap.md;\n const attrs = Object.entries(attributes).map(([key, val]) => `${key}=\"${this.escapeHtml(val)}\"`).join(' ');\n\n // Get current value (could be URL string or file object)\n const currentValue = this.getFieldValue(name);\n const imageUrl = this.extractImageUrl(currentValue, size);\n\n const context = {\n labelClass: this.options.labelClass,\n inputClass: inputClass,\n helpClass: this.options.helpClass,\n errorClass: this.options.errorClass,\n fieldId,\n name,\n label: label ? this.escapeHtml(label) : null,\n help: help ? this.escapeHtml(help) : null,\n error: error ? this.escapeHtml(error) : null,\n dropZoneId,\n previewId,\n containerClass: sizeConfig.containerClass,\n width: sizeConfig.width,\n height: sizeConfig.height,\n accept,\n imageUrl,\n placeholderText: disabled ? 'No image' : this.escapeHtml(placeholder),\n cursor: disabled ? 'default' : 'pointer',\n allowDrop,\n showRemove: !disabled,\n required,\n disabled,\n attrs\n };\n\n return Mustache.render(this.templates.image, context);\n }\n\n /**\n * Extract image URL from field value (handles both URL strings and file objects)\n * @param {string|Object} value - Field value\n * @param {string} size - Requested size (xs, sm, md, lg, xl)\n * @returns {string|null} Image URL or null\n */\n extractImageUrl(value, size = 'md') {\n if (!value) return null;\n\n // If it's already a URL string\n if (typeof value === 'string') {\n return value;\n }\n\n // If it's a file object with renditions\n if (typeof value === 'object' && value.url) {\n // Try to get appropriate rendition based on size\n if (value.renditions) {\n const sizeMap = {\n xs: ['thumbnail_sm', 'thumbnail', 'square_sm'],\n sm: ['thumbnail', 'thumbnail_sm', 'square_sm'],\n md: ['thumbnail_md', 'thumbnail', 'thumbnail_lg'],\n lg: ['thumbnail_lg', 'thumbnail_md', 'thumbnail'],\n xl: ['original', 'thumbnail_lg']\n };\n\n const preferredSizes = sizeMap[size] || sizeMap.md;\n\n for (const renditionName of preferredSizes) {\n if (value.renditions[renditionName] && value.renditions[renditionName].url) {\n return value.renditions[renditionName].url;\n }\n }\n }\n\n // Fall back to original URL\n return value.url;\n }\n\n return null;\n }\n\n /**\n * Render color field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderColorField(field) {\n const {\n name,\n label,\n value = '',\n placeholder = '',\n required = false,\n disabled = false,\n readonly = false,\n class: fieldClass = '',\n attributes = {},\n help = field.helpText || field.help || ''\n } = field;\n\n const inputClass = `${this.options.inputClass} ${fieldClass}`.trim();\n const error = this.errors[name];\n const fieldValue = (this.getFieldValue(name) ?? value);\n\n const attrs = Object.entries(attributes).map(([key, val]) => `${key}=\"${this.escapeHtml(val)}\"`).join(' ');\n const fieldId = this.getFieldId(name);\n\n const context = {\n labelClass: this.options.labelClass,\n inputClass: inputClass,\n helpClass: this.options.helpClass,\n errorClass: this.options.errorClass,\n fieldId,\n name,\n fieldValue: this.escapeHtml(fieldValue),\n label: label ? this.escapeHtml(label) : null,\n placeholder: placeholder ? this.escapeHtml(placeholder) : null,\n help: help ? this.escapeHtml(help) : null,\n error: error ? this.escapeHtml(error) : null,\n required,\n disabled,\n readonly,\n attrs\n };\n\n return Mustache.render(this.templates.color, context);\n }\n\n /**\n * Render range field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderRangeField(field) {\n const {\n name,\n label,\n min = 0,\n max = 100,\n step = 1,\n value = min,\n disabled = false,\n class: fieldClass = '',\n attributes = {},\n help = field.helpText || field.help || ''\n } = field;\n\n const inputClass = `${this.options.inputClass} ${fieldClass}`.trim();\n const error = this.errors[name];\n const fieldValue = (this.getFieldValue(name) ?? value);\n\n const attrs = Object.entries(attributes).map(([key, val]) => `${key}=\"${this.escapeHtml(val)}\"`).join(' ');\n const fieldId = this.getFieldId(name);\n\n const context = {\n labelClass: this.options.labelClass,\n inputClass: inputClass,\n helpClass: this.options.helpClass,\n errorClass: this.options.errorClass,\n fieldId,\n name,\n label: label ? this.escapeHtml(label) : null,\n help: help ? this.escapeHtml(help) : null,\n error: error ? this.escapeHtml(error) : null,\n min,\n max,\n step,\n fieldValue,\n disabled,\n attrs\n };\n\n return Mustache.render(this.templates.range, context);\n }\n\n /**\n * Render hidden field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderHiddenField(field) {\n const { name, value = '' } = field;\n const fieldValue = (this.getFieldValue(name) ?? value);\n\n return `<input type=\"hidden\" name=\"${name}\" value=\"${this.escapeHtml(fieldValue)}\">`;\n }\n\n /**\n * Render button field\n * @param {Object} field - Field configuration\n * @returns {string} Button HTML\n */\n renderButton(field) {\n const {\n name = '',\n label = 'Button',\n type = 'button',\n action = '',\n class: fieldClass = 'btn-secondary',\n disabled = false,\n attributes = {}\n } = field;\n\n // Auto-assign actions for submit/reset types\n let buttonAction = action;\n if (!buttonAction) {\n if (type === 'submit') {\n buttonAction = 'submit-form';\n } else if (type === 'reset') {\n buttonAction = 'reset-form';\n }\n }\n\n const attrs = Object.entries(attributes).map(([key, val]) => `${key}=\"${this.escapeHtml(val)}\"`).join(' ');\n\n return `\n <button\n type=\"button\"\n ${name ? `name=\"${name}\"` : ''}\n class=\"btn ${fieldClass}\"\n ${buttonAction ? `data-action=\"${buttonAction}\"` : ''}\n ${disabled ? 'disabled' : ''}\n ${attrs}\n >\n ${this.escapeHtml(label)}\n </button>\n `;\n }\n\n /**\n * Render divider field\n * @param {Object} field - Field configuration\n * @returns {string} Divider HTML\n */\n renderDivider(field) {\n const { label = '', class: fieldClass = '' } = field;\n\n return `\n <div class=\"form-divider ${fieldClass}\">\n <hr>\n ${label ? `<div class=\"form-divider-label\">${this.escapeHtml(label)}</div>` : ''}\n </div>\n `;\n }\n\n /**\n * Render HTML field\n * @param {Object} field - Field configuration\n * @returns {string} HTML content\n */\n renderHtmlField(field) {\n const { html = '', class: fieldClass = '' } = field;\n\n return `\n <div class=\"form-html ${fieldClass}\">\n ${html}\n </div>\n `;\n }\n\n /**\n * Render header field\n * @param {Object} field - Field configuration\n * @returns {string} Header HTML\n */\n renderHeaderField(field) {\n const {\n text = '',\n level = 3,\n class: fieldClass = '',\n id = ''\n } = field;\n\n const headerLevel = Math.max(1, Math.min(6, parseInt(level)));\n const headerId = id ? ` id=\"${this.escapeHtml(id)}\"` : '';\n const headerClass = fieldClass ? ` class=\"${this.escapeHtml(fieldClass)}\"` : '';\n\n return `<h${headerLevel}${headerId}${headerClass}>${this.escapeHtml(text)}</h${headerLevel}>`;\n }\n\n /**\n * Generate buttons HTML\n * @returns {string} Buttons HTML\n */\n buildButtonsHTML() {\n if (!this.options.submitButton && !this.options.resetButton && !this.buttons.length) {\n return '';\n }\n\n let buttonsHTML = '';\n\n // Custom buttons\n this.buttons.forEach(button => {\n buttonsHTML += this.renderButton(button) + ' ';\n });\n\n // Default submit button\n if (this.options.submitButton) {\n let submitLabel = 'Submit';\n if (typeof this.options.submitButton === 'string') {\n submitLabel = this.options.submitButton;\n } else if (this.options.submitButton === true) {\n submitLabel = 'Submit';\n }\n buttonsHTML += `<button type=\"submit\" class=\"btn btn-primary me-2\" data-action=\"submit-form\">${submitLabel}</button>`;\n }\n\n // Default reset button\n if (this.options.resetButton) {\n let resetLabel = 'Reset';\n if (typeof this.options.resetButton === 'string') {\n resetLabel = this.options.resetButton;\n } else if (this.options.resetButton === true) {\n resetLabel = 'Reset';\n }\n buttonsHTML += `<button type=\"button\" class=\"btn btn-secondary\" data-action=\"reset-form\">${resetLabel}</button>`;\n }\n\n return buttonsHTML ? `\n <div class=\"form-actions mt-3\">\n ${buttonsHTML}\n </div>\n ` : '';\n }\n\n /**\n * Get field value from data\n * @param {string} name - Field name\n * @returns {*} Field value\n */\n getFieldValue(name) {\n // If in structure-only mode, return empty value\n if (this.structureOnly) {\n return '';\n }\n const value = MOJOUtils.getContextData(this.data, name);\n return value;\n }\n\n /**\n * Render tag input field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderTagField(field) {\n const {\n name,\n label,\n value = '',\n placeholder = 'Add tags...',\n required = false,\n disabled = false,\n readonly = false,\n maxTags = 50,\n allowDuplicates = false,\n separator = ',',\n help = field.helpText || field.help || ''\n } = field;\n\n const fieldId = this.getFieldId(name);\n const error = this.errors[name];\n const fieldValue = (this.getFieldValue(name) ?? value);\n\n return `\n <div class=\"mojo-form-control\">\n ${label ? `<label for=\"${fieldId}\" class=\"${this.options.labelClass}\">${this.escapeHtml(label)}${required ? '<span class=\"text-danger\">*</span>' : ''}</label>` : ''}\n <div class=\"tag-input-placeholder\"\n data-field-name=\"${name}\"\n data-field-type=\"tag\"\n data-field-config='${JSON.stringify({\n name,\n value: fieldValue,\n placeholder,\n maxTags,\n allowDuplicates,\n separator,\n disabled,\n readonly,\n required\n })}'>\n <input type=\"text\"\n id=\"${fieldId}\"\n name=\"${name}_display\"\n class=\"${this.options.inputClass}${error ? ' is-invalid' : ''}\"\n placeholder=\"${this.escapeHtml(placeholder)}\"\n ${disabled ? 'disabled' : ''}\n ${readonly ? 'readonly' : ''}\n\n <input type=\"hidden\" name=\"${name}\" value=\"${this.escapeHtml(fieldValue)}\">\n <small class=\"form-text text-muted\">This will be enhanced with TagInput component</small>\n </div>\n ${help ? `<div class=\"${this.options.helpClass}\">${this.escapeHtml(help)}</div>` : ''}\n ${error ? `<div class=\"${this.options.errorClass}\">${this.escapeHtml(error)}</div>` : ''}\n </div>\n `;\n }\n\n /**\n * Render collection select field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderCollectionField(field) {\n const {\n name,\n label,\n value = '',\n placeholder = 'Search...',\n required = false,\n disabled = false,\n readonly = false,\n Collection: _Collection,\n labelField = 'name',\n valueField = 'id',\n maxItems = 10,\n emptyFetch = false,\n debounceMs = 300,\n requiresActiveGroup = false,\n help = field.helpText || field.help || ''\n } = field;\n\n const fieldId = this.getFieldId(name);\n const error = this.errors[name];\n const fieldValue = (this.getFieldValue(name) ?? value);\n\n return `\n <div class=\"mojo-form-control\">\n ${label ? `<label for=\"${fieldId}\" class=\"${this.options.labelClass}\">${this.escapeHtml(label)}${required ? '<span class=\"text-danger\">*</span>' : ''}</label>` : ''}\n <div class=\"collection-select-placeholder\"\n data-field-name=\"${name}\"\n data-field-type=\"collection\"\n data-field-config='${JSON.stringify({\n name,\n value: fieldValue,\n placeholder,\n labelField,\n valueField,\n maxItems,\n emptyFetch,\n debounceMs,\n disabled,\n readonly,\n required,\n requiresActiveGroup\n })}'>\n <input type=\"text\"\n id=\"${fieldId}\"\n name=\"${name}_display\"\n class=\"${this.options.inputClass}${error ? ' is-invalid' : ''}\"\n placeholder=\"${this.escapeHtml(placeholder)}\"\n ${disabled ? 'disabled' : ''}\n ${readonly ? 'readonly' : ''}\n\n <input type=\"hidden\" name=\"${name}\" value=\"${this.escapeHtml(fieldValue)}\">\n <small class=\"form-text text-muted\">This will be enhanced with CollectionSelect component</small>\n </div>\n ${help ? `<div class=\"${this.options.helpClass}\">${this.escapeHtml(help)}</div>` : ''}\n ${error ? `<div class=\"${this.options.errorClass}\">${this.escapeHtml(error)}</div>` : ''}\n </div>\n `;\n }\n\n /**\n * Render collection multiselect field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderCollectionMultiSelectField(field) {\n const {\n name,\n label,\n value = [],\n required = false,\n disabled = false,\n Collection: _Collection,\n collectionParams = {},\n labelField = 'name',\n valueField = 'id',\n excludeIds = [],\n ignoreIds = [],\n size = 8,\n maxHeight = null,\n showSelectAll = true,\n enableSearch = false,\n searchPlaceholder = 'Search...',\n searchDebounce = 400,\n requiresActiveGroup = false,\n help = field.helpText || field.help || ''\n } = field;\n\n const fieldId = this.getFieldId(name);\n const error = this.errors[name];\n const fieldValue = this.getFieldValue(name) ?? value;\n\n return `\n <div class=\"mojo-form-control\">\n ${label ? `<label class=\"${this.options.labelClass}\">${this.escapeHtml(label)}${required ? '<span class=\"text-danger\">*</span>' : ''}</label>` : ''}\n <div class=\"collection-multiselect-placeholder\"\n data-field-name=\"${name}\"\n data-field-type=\"collectionmultiselect\"\n data-field-config='${JSON.stringify({\n name,\n value: fieldValue,\n labelField,\n valueField,\n excludeIds,\n ignoreIds,\n size,\n maxHeight,\n showSelectAll,\n enableSearch,\n searchPlaceholder,\n searchDebounce,\n disabled,\n required,\n requiresActiveGroup\n })}'>\n <input type=\"hidden\" name=\"${name}\" value=\"${this.escapeHtml(JSON.stringify(fieldValue))}\">\n <small class=\"form-text text-muted\">This will be enhanced with CollectionMultiSelect component</small>\n </div>\n ${help ? `<div class=\"${this.options.helpClass}\">${this.escapeHtml(help)}</div>` : ''}\n ${error ? `<div class=\"${this.options.errorClass}\">${this.escapeHtml(error)}</div>` : ''}\n </div>\n `;\n }\n\n /**\n * Render enhanced date picker field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderDatePickerField(field) {\n const {\n name,\n label,\n value = '',\n placeholder = 'Select date...',\n required = false,\n disabled = false,\n readonly = false,\n min = null,\n max = null,\n format = 'YYYY-MM-DD',\n displayFormat = 'MMM DD, YYYY',\n help = field.helpText || field.help || ''\n } = field;\n\n const fieldId = this.getFieldId(name);\n const error = this.errors[name];\n const fieldValue = (this.getFieldValue(name) ?? value);\n\n return `\n <div class=\"mojo-form-control\">\n ${label ? `<label for=\"${fieldId}\" class=\"${this.options.labelClass}\">${this.escapeHtml(label)}${required ? '<span class=\"text-danger\">*</span>' : ''}</label>` : ''}\n <div class=\"date-picker-placeholder\"\n data-field-name=\"${name}\"\n data-field-type=\"datepicker\"\n data-field-config='${JSON.stringify({\n name,\n value: fieldValue,\n placeholder,\n min,\n max,\n format,\n displayFormat,\n disabled,\n readonly,\n required\n })}'>\n <input type=\"date\"\n id=\"${fieldId}\"\n name=\"${name}\"\n class=\"${this.options.inputClass}${error ? ' is-invalid' : ''}\"\n value=\"${this.escapeHtml(fieldValue)}\"\n placeholder=\"${this.escapeHtml(placeholder)}\"\n ${min ? `min=\"${min}\"` : ''}\n ${max ? `max=\"${max}\"` : ''}\n ${disabled ? 'disabled' : ''}\n ${readonly ? 'readonly' : ''}\n ${required ? 'required' : ''}\n\n <small class=\"form-text text-muted\">This will be enhanced with Easepick DatePicker</small>\n </div>\n ${help ? `<div class=\"${this.options.helpClass}\">${this.escapeHtml(help)}</div>` : ''}\n ${error ? `<div class=\"${this.options.errorClass}\">${this.escapeHtml(error)}</div>` : ''}\n </div>\n `;\n }\n\n /**\n * Render date range picker field\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderDateRangeField(field) {\n const {\n name,\n startName,\n endName,\n fieldName,\n label,\n startDate = '',\n endDate = '',\n placeholder = 'Select date range...',\n required = false,\n disabled = false,\n readonly = false,\n min = null,\n max = null,\n format = 'YYYY-MM-DD',\n displayFormat = 'MMM DD, YYYY',\n outputFormat = 'date',\n separator = ' - ',\n help = field.helpText || field.help || ''\n } = field;\n\n const fieldId = this.getFieldId(name || startName || 'daterange');\n const error = this.errors[name];\n const startFieldName = startName || (name ? name + '_start' : '');\n const endFieldName = endName || (name ? name + '_end' : '');\n const startValue = this.getFieldValue(startFieldName) || startDate;\n const endValue = this.getFieldValue(endFieldName) || endDate;\n\n return `\n <div class=\"mojo-form-control\">\n ${label ? `<label for=\"${fieldId}\" class=\"${this.options.labelClass}\">${this.escapeHtml(label)}${required ? '<span class=\"text-danger\">*</span>' : ''}</label>` : ''}\n <div class=\"date-range-picker-placeholder\"\n data-field-name=\"${name || startName || 'daterange'}\"\n data-field-type=\"daterange\"\n data-field-config='${JSON.stringify({\n name,\n startName,\n endName,\n fieldName,\n startDate: startValue,\n endDate: endValue,\n placeholder,\n min,\n max,\n format,\n displayFormat,\n outputFormat,\n separator,\n disabled,\n readonly,\n required\n })}'>\n <div class=\"row g-2\">\n <div class=\"col\">\n <input type=\"date\"\n id=\"${fieldId}_start\"\n name=\"${name}_start\"\n class=\"${this.options.inputClass}${error ? ' is-invalid' : ''}\"\n value=\"${this.escapeHtml(startValue)}\"\n placeholder=\"Start date...\"\n ${min ? `min=\"${min}\"` : ''}\n ${max ? `max=\"${max}\"` : ''}\n ${disabled ? 'disabled' : ''}\n ${readonly ? 'readonly' : ''}\n ${required ? 'required' : ''}\n\n </div>\n <div class=\"col-auto d-flex align-items-center\">\n <span class=\"text-muted\">${this.escapeHtml(separator.trim())}</span>\n </div>\n <div class=\"col\">\n <input type=\"date\"\n id=\"${fieldId}_end\"\n name=\"${name}_end\"\n class=\"${this.options.inputClass}${error ? ' is-invalid' : ''}\"\n value=\"${this.escapeHtml(endValue)}\"\n placeholder=\"End date...\"\n ${min ? `min=\"${min}\"` : ''}\n ${max ? `max=\"${max}\"` : ''}\n ${disabled ? 'disabled' : ''}\n ${readonly ? 'readonly' : ''}\n ${required ? 'required' : ''}\n\n </div>\n </div>\n <small class=\"form-text text-muted\">This will be enhanced with Easepick DateRangePicker</small>\n </div>\n ${help ? `<div class=\"${this.options.helpClass}\">${this.escapeHtml(help)}</div>` : ''}\n ${error ? `<div class=\"${this.options.errorClass}\">${this.escapeHtml(error)}</div>` : ''}\n </div>\n `;\n }\n\n /**\n * Render checklistdropdown field\n * @param {Object} field - Field configuration\n * @returns {string} Rendered HTML\n */\n renderChecklistDropdownField(field) {\n const fieldId = this.getFieldId(field.name);\n const selectedValues = (this.getFieldValue(field.name) ?? []);\n\n // Prepare data for Mustache template\n const templateData = {\n fieldId,\n fieldName: field.name,\n buttonText: field.buttonText || 'Select Options',\n buttonIcon: field.buttonIcon || 'bi-chevron-down',\n buttonClass: field.buttonClass || 'btn btn-outline-secondary btn-sm dropdown-toggle',\n dropdownClass: field.dropdownClass || 'dropdown-menu p-2',\n minWidth: field.minWidth || '200px',\n options: field.options.map(option => ({\n value: option.value,\n label: option.label,\n id: `${field.name}-${option.value}`,\n checked: selectedValues.includes(option.value)\n }))\n };\n\n return Mustache.render(this.templates.checklistdropdown, templateData);\n }\n\n /**\n * Render buttongroup field\n * @param {Object} field - Field configuration\n * @returns {string} Rendered HTML\n */\n renderButtonGroupField(field) {\n const fieldId = this.getFieldId(field.name);\n const selectedValue = (this.getFieldValue(field.name) ?? field.value);\n\n // Prepare data for Mustache template\n const templateData = {\n fieldId,\n fieldName: field.name,\n size: field.size || 'sm',\n variant: field.variant || 'outline-primary',\n options: field.options.map(option => ({\n value: option.value,\n label: option.label,\n action: option.action,\n active: option.value === selectedValue,\n buttonClass: this.getButtonClass(option.value === selectedValue, field.variant)\n }))\n };\n\n return Mustache.render(this.templates.buttongroup, templateData);\n }\n\n /**\n * Get button class based on active state and variant\n * @param {boolean} isActive - Whether button is active\n * @param {string} variant - Button variant\n * @returns {string} Button class\n */\n getButtonClass(isActive, variant = 'outline-primary') {\n if (isActive) {\n // Remove 'outline-' prefix for active buttons\n const activeVariant = variant.replace('outline-', '');\n return `btn btn-${activeVariant}`;\n }\n return `btn btn-${variant}`;\n }\n\n /**\n * Render combo input field (editable select/autocomplete)\n * @param {Object} field - Field configuration\n * @returns {string} Field HTML\n */\n renderComboField(field) {\n const {\n name,\n label,\n value = '',\n placeholder = 'Select or type...',\n options = [],\n required = false,\n disabled = false,\n readonly = false,\n allowCustom = true,\n showDescription = true,\n minChars = 0,\n maxSuggestions = 10,\n help = field.helpText || field.help || ''\n } = field;\n\n const fieldId = this.getFieldId(name);\n const error = this.errors[name];\n const fieldValue = (this.getFieldValue(name) ?? value);\n\n return `\n <div class=\"mojo-form-control\">\n ${label ? `<label for=\"${fieldId}\" class=\"${this.options.labelClass}\">${this.escapeHtml(label)}${required ? '<span class=\"text-danger\">*</span>' : ''}</label>` : ''}\n <div class=\"combo-input-placeholder\"\n data-field-name=\"${name}\"\n data-field-type=\"combo\"\n data-field-config='${JSON.stringify({\n name,\n value: fieldValue,\n placeholder,\n options,\n allowCustom,\n showDescription,\n minChars,\n maxSuggestions,\n disabled,\n readonly,\n required\n })}'>\n <input type=\"text\"\n id=\"${fieldId}\"\n name=\"${name}_display\"\n class=\"${this.options.inputClass}${error ? ' is-invalid' : ''}\"\n placeholder=\"${this.escapeHtml(placeholder)}\"\n value=\"${this.escapeHtml(fieldValue)}\"\n ${disabled ? 'disabled' : ''}\n ${readonly ? 'readonly' : ''}\n ${required ? 'required' : ''}>\n <input type=\"hidden\" name=\"${name}\" value=\"${this.escapeHtml(fieldValue)}\">\n <small class=\"form-text text-muted\">This will be enhanced with ComboInput component</small>\n </div>\n ${help ? `<div class=\"${this.options.helpClass}\">${this.escapeHtml(help)}</div>` : ''}\n ${error ? `<div class=\"${this.options.errorClass}\">${this.escapeHtml(error)}</div>` : ''}\n </div>\n `;\n }\n\n /**\n * Render a tabset field consisting of Bootstrap nav tabs and tab panes.\n * Each pane's fields are rendered using existing field rendering,\n * wrapped in a row so column layouts work as expected.\n * @param {Object} field - Tabset configuration\n * @param {Array} field.tabs - Array of tabs: [{ label, fields }]\n * @param {string} [field.name] - Optional name used to generate stable IDs\n * @param {string} [field.navClass] - CSS classes for the tabs nav\n * @param {string} [field.contentClass] - CSS classes for the tab content container\n * @returns {string} HTML\n */\n renderTabsetField(field) {\n const {\n tabs = [],\n name = `tabset-${Date.now()}`,\n navClass = 'nav nav-tabs mb-3',\n contentClass = 'tab-content'\n } = field;\n\n const safe = String(name).toLowerCase().replace(/[^a-z0-9]/g, '-');\n\n const nav = tabs.map((t, i) => {\n const id = `${safe}-pane-${i}`;\n const isActive = i === 0;\n return `\n <li class=\"nav-item\" role=\"presentation\">\n <button class=\"nav-link ${isActive ? 'active' : ''}\"\n id=\"${id}-tab\"\n data-bs-toggle=\"tab\"\n data-bs-target=\"#${id}\"\n type=\"button\"\n role=\"tab\"\n aria-controls=\"${id}\"\n aria-selected=\"${isActive}\">\n ${this.escapeHtml(t.label || `Tab ${i + 1}`)}\n </button>\n </li>\n `;\n }).join('');\n\n const panes = tabs.map((t, i) => {\n const id = `${safe}-pane-${i}`;\n const isActive = i === 0;\n const fieldsHTML = (t.fields || []).map(f => this.buildFieldHTML(f)).join('');\n return `\n <div class=\"tab-pane fade ${isActive ? 'show active' : ''}\"\n id=\"${id}\"\n role=\"tabpanel\"\n aria-labelledby=\"${id}-tab\"\n data-tab-index=\"${i}\">\n <div class=\"row\">\n ${fieldsHTML}\n </div>\n </div>\n `;\n }).join('');\n\n return `\n <div class=\"mojo-form-tabset\">\n <ul class=\"${navClass}\" role=\"tablist\">\n ${nav}\n </ul>\n <div class=\"${contentClass}\">\n ${panes}\n </div>\n </div>\n `;\n }\n\n /**\n * Generate select options automatically from numeric range or patterns\n * Supports multiple generation modes:\n * - Numeric ranges: start, end, step\n * - Formatting: format function, prefix, suffix\n *\n * @param {number} start - Start value (inclusive)\n * @param {number} end - End value (inclusive)\n * @param {number} step - Step increment (default: 1)\n * @param {Object} options - Additional options\n * @param {Function|string} options.format - Format function or preset ('padded', 'ordinal')\n * @param {string} options.prefix - Prefix for label\n * @param {string} options.suffix - Suffix for label\n * @returns {Array} Array of option objects {value, label}\n *\n * @example\n * // Hours 1-24\n * generateSelectOptions(1, 24, 1)\n *\n * // Minutes in 15-min increments with padding\n * generateSelectOptions(0, 45, 15, { format: 'padded' })\n *\n * // Days with ordinal suffix\n * generateSelectOptions(1, 31, 1, { format: 'ordinal' })\n *\n * // Years with prefix\n * generateSelectOptions(2020, 2030, 1, { prefix: 'Year ' })\n *\n * // Percentages\n * generateSelectOptions(0, 100, 10, { suffix: '%' })\n *\n * // Custom formatter\n * generateSelectOptions(1, 12, 1, {\n * format: (v) => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\n * 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][v-1]\n * })\n */\n generateSelectOptions(start, end, step = 1, options = {}) {\n const { format, prefix = '', suffix = '' } = options;\n const results = [];\n\n // Determine direction (ascending or descending)\n const increment = start <= end ? Math.abs(step) : -Math.abs(step);\n\n // Generate options\n for (let i = start; start <= end ? i <= end : i >= end; i += increment) {\n let label = String(i);\n\n // Apply formatting\n if (typeof format === 'function') {\n label = format(i);\n } else if (format === 'padded' || format === 'pad') {\n // Pad with zeros to match end value length\n const maxLength = String(Math.max(Math.abs(start), Math.abs(end))).length;\n label = String(i).padStart(maxLength, '0');\n } else if (format === 'ordinal') {\n label = this.formatOrdinal(i);\n }\n\n // Apply prefix/suffix\n label = `${prefix}${label}${suffix}`;\n\n results.push({\n value: i,\n label: label\n });\n }\n\n return results;\n }\n\n /**\n * Format number with ordinal suffix (1st, 2nd, 3rd, etc.)\n * @param {number} num - Number to format\n * @returns {string} Formatted ordinal string\n */\n formatOrdinal(num) {\n const j = num % 10;\n const k = num % 100;\n\n if (j === 1 && k !== 11) return num + 'st';\n if (j === 2 && k !== 12) return num + 'nd';\n if (j === 3 && k !== 13) return num + 'rd';\n return num + 'th';\n }\n\n /**\n * Escape HTML characters to prevent XSS\n * @param {string} str - String to escape\n * @returns {string} Escaped string\n */\n escapeHtml(str) {\n if (str == null) return '';\n const div = document.createElement('div');\n div.textContent = String(str);\n return div.innerHTML;\n }\n}\n\n// Export for use in MOJO framework\nexport { FormBuilder };\nexport default FormBuilder;\n","/**\n * FileDropMixin - Adds drag and drop file functionality to Views\n * Provides configurable file drop handling with validation and callbacks\n */\n\nconst FileDropMixin = {\n /**\n * Enable drag and drop file functionality on this view\n * @param {Object} config - Configuration options\n */\n enableFileDrop(config = {}) {\n // Store configuration\n this._fileDropConfig = {\n acceptedTypes: config.acceptedTypes || ['*/*'],\n maxFileSize: config.maxFileSize || 10 * 1024 * 1024, // 10MB\n dropZoneSelector: config.dropZoneSelector || null, // defaults to view element\n visualFeedback: config.visualFeedback !== false, // default true\n multiple: config.multiple || false,\n validateOnDrop: config.validateOnDrop !== false, // default true\n dragOverClass: config.dragOverClass || 'drag-over',\n dragActiveClass: config.dragActiveClass || 'drag-active'\n };\n\n // Initialize drag/drop state\n this._fileDropState = {\n isDragActive: false,\n dragCounter: 0\n };\n\n // Bind event handlers\n this._boundFileDropHandlers = {\n dragEnter: this._onFileDropDragEnter.bind(this),\n dragOver: this._onFileDropDragOver.bind(this),\n dragLeave: this._onFileDropDragLeave.bind(this),\n drop: this._onFileDropDrop.bind(this),\n preventDefault: this._onFileDropPreventDefault.bind(this)\n };\n\n // Set up event listeners after render\n if (this.element) {\n this._setupFileDropListeners();\n } else {\n // If not rendered yet, set up in onAfterRender\n const originalOnAfterRender = this.onAfterRender.bind(this);\n this.onAfterRender = async () => {\n await originalOnAfterRender();\n this._setupFileDropListeners();\n };\n }\n\n // Hook into cleanup\n const originalOnBeforeDestroy = this.onBeforeDestroy.bind(this);\n this.onBeforeDestroy = async () => {\n this._cleanupFileDropListeners();\n await originalOnBeforeDestroy();\n };\n },\n\n /**\n * Set up drag and drop event listeners\n * @private\n */\n _setupFileDropListeners() {\n if (!this._fileDropConfig) return;\n\n // Get drop zone element\n const dropZone = this._getFileDropZone();\n if (!dropZone) {\n console.warn('FileDropMixin: Drop zone not found');\n return;\n }\n\n this._fileDropZone = dropZone;\n\n // Add event listeners to drop zone\n dropZone.addEventListener('dragenter', this._boundFileDropHandlers.dragEnter);\n dropZone.addEventListener('dragover', this._boundFileDropHandlers.dragOver);\n dropZone.addEventListener('dragleave', this._boundFileDropHandlers.dragLeave);\n dropZone.addEventListener('drop', this._boundFileDropHandlers.drop);\n\n // Prevent default drag behaviors on document to avoid browser's default file handling\n ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {\n document.addEventListener(eventName, this._boundFileDropHandlers.preventDefault);\n });\n },\n\n /**\n * Clean up drag and drop event listeners\n * @private\n */\n _cleanupFileDropListeners() {\n if (!this._boundFileDropHandlers) return;\n\n // Remove from drop zone\n if (this._fileDropZone) {\n this._fileDropZone.removeEventListener('dragenter', this._boundFileDropHandlers.dragEnter);\n this._fileDropZone.removeEventListener('dragover', this._boundFileDropHandlers.dragOver);\n this._fileDropZone.removeEventListener('dragleave', this._boundFileDropHandlers.dragLeave);\n this._fileDropZone.removeEventListener('drop', this._boundFileDropHandlers.drop);\n }\n\n // Remove from document\n ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {\n document.removeEventListener(eventName, this._boundFileDropHandlers.preventDefault);\n });\n\n // Clear references\n this._fileDropZone = null;\n this._boundFileDropHandlers = null;\n this._fileDropConfig = null;\n this._fileDropState = null;\n },\n\n /**\n * Get the drop zone element\n * @returns {Element} The drop zone element\n * @private\n */\n _getFileDropZone() {\n if (this._fileDropConfig.dropZoneSelector) {\n return this.element.querySelector(this._fileDropConfig.dropZoneSelector);\n }\n return this.element;\n },\n\n /**\n * Prevent default drag behaviors\n * @param {Event} e - Drag event\n * @private\n */\n _onFileDropPreventDefault(e) {\n e.preventDefault();\n e.stopPropagation();\n },\n\n /**\n * Handle drag enter event\n * @param {DragEvent} e - Drag event\n * @private\n */\n _onFileDropDragEnter(e) {\n this._onFileDropPreventDefault(e);\n \n this._fileDropState.dragCounter++;\n \n if (!this._fileDropState.isDragActive) {\n this._fileDropState.isDragActive = true;\n this._applyFileDropVisualFeedback(true);\n }\n },\n\n /**\n * Handle drag over event\n * @param {DragEvent} e - Drag event\n * @private\n */\n _onFileDropDragOver(e) {\n this._onFileDropPreventDefault(e);\n e.dataTransfer.dropEffect = 'copy';\n },\n\n /**\n * Handle drag leave event\n * @param {DragEvent} e - Drag event\n * @private\n */\n _onFileDropDragLeave(e) {\n this._onFileDropPreventDefault(e);\n \n this._fileDropState.dragCounter--;\n \n if (this._fileDropState.dragCounter <= 0) {\n this._fileDropState.isDragActive = false;\n this._fileDropState.dragCounter = 0;\n this._applyFileDropVisualFeedback(false);\n }\n },\n\n /**\n * Handle drop event\n * @param {DragEvent} e - Drag event\n * @private\n */\n async _onFileDropDrop(e) {\n this._onFileDropPreventDefault(e);\n \n // Reset drag state\n this._fileDropState.isDragActive = false;\n this._fileDropState.dragCounter = 0;\n this._applyFileDropVisualFeedback(false);\n \n // Get files from drop\n const files = Array.from(e.dataTransfer.files);\n \n if (files.length === 0) return;\n \n // Handle single vs multiple files\n const filesToProcess = this._fileDropConfig.multiple ? files : [files[0]];\n \n // Validate files if enabled\n let validation = { valid: true, errors: [] };\n if (this._fileDropConfig.validateOnDrop) {\n validation = this._validateFileDropFiles(filesToProcess);\n \n if (!validation.valid) {\n if (typeof this.onFileDropError === 'function') {\n await this.onFileDropError(new Error(validation.errors.join(', ')), e, filesToProcess);\n }\n return;\n }\n }\n \n // Call the view's onFileDrop method\n if (typeof this.onFileDrop === 'function') {\n try {\n await this.onFileDrop(filesToProcess, e, validation);\n } catch (error) {\n if (typeof this.onFileDropError === 'function') {\n await this.onFileDropError(error, e, filesToProcess);\n } else {\n console.error('FileDropMixin: Error in onFileDrop callback:', error);\n }\n }\n } else {\n console.warn('FileDropMixin: No onFileDrop method found on view');\n }\n },\n\n /**\n * Apply visual feedback during drag operations\n * @param {boolean} isDragActive - Whether drag is active\n * @private\n */\n _applyFileDropVisualFeedback(isDragActive) {\n if (!this._fileDropConfig.visualFeedback || !this._fileDropZone) return;\n \n const { dragOverClass, dragActiveClass } = this._fileDropConfig;\n \n if (isDragActive) {\n this._fileDropZone.classList.add(dragOverClass, dragActiveClass);\n } else {\n this._fileDropZone.classList.remove(dragOverClass, dragActiveClass);\n }\n },\n\n /**\n * Validate dropped files\n * @param {File[]} files - Files to validate\n * @returns {Object} Validation result\n * @private\n */\n _validateFileDropFiles(files) {\n const errors = [];\n const config = this._fileDropConfig;\n \n for (const file of files) {\n // Check file type\n if (!this._isFileDropTypeAccepted(file.type)) {\n errors.push(`File type \"${file.type}\" is not accepted for file \"${file.name}\"`);\n continue;\n }\n \n // Check file size\n if (file.size > config.maxFileSize) {\n errors.push(`File \"${file.name}\" (${this._formatFileDropSize(file.size)}) exceeds maximum size (${this._formatFileDropSize(config.maxFileSize)})`);\n }\n }\n \n return {\n valid: errors.length === 0,\n errors\n };\n },\n\n /**\n * Check if file type is accepted\n * @param {string} fileType - MIME type of the file\n * @returns {boolean} Whether the file type is accepted\n * @private\n */\n _isFileDropTypeAccepted(fileType) {\n const { acceptedTypes } = this._fileDropConfig;\n \n // Allow all types if wildcard\n if (acceptedTypes.includes('*/*')) return true;\n \n return acceptedTypes.some(acceptedType => {\n // Exact match\n if (acceptedType === fileType) return true;\n \n // Wildcard match (e.g., \"image/*\")\n if (acceptedType.endsWith('/*')) {\n const category = acceptedType.split('/')[0];\n return fileType.startsWith(category + '/');\n }\n \n return false;\n });\n },\n\n /**\n * Format file size for display\n * @param {number} bytes - File size in bytes\n * @returns {string} Formatted file size\n * @private\n */\n _formatFileDropSize(bytes) {\n if (bytes === 0) return '0 Bytes';\n const k = 1024;\n const sizes = ['Bytes', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];\n }\n};\n\n// Apply mixin to View prototype\nexport default function applyFileDropMixin(ViewClass) {\n Object.assign(ViewClass.prototype, FileDropMixin);\n}\n\n// Export the mixin for manual application\nexport { FileDropMixin };","/**\n * TagInputView - Advanced tag input component for MOJO framework\n * Allows users to add/remove tags with keyboard and mouse interaction\n * Integrates with FormView and uses EventDelegate patterns\n *\n * Features:\n * - Add tags via Enter, comma, or Tab key\n * - Remove tags with click or keyboard\n * - Duplicate prevention\n * - Bootstrap 5 styling\n * - Accessibility support\n * - Form integration with hidden input\n *\n * Example Usage:\n * ```javascript\n * const tagInput = new TagInputView({\n * name: 'tags',\n * value: 'javascript,react,node', // Initial tags\n * placeholder: 'Add tags...',\n * maxTags: 10,\n * allowDuplicates: false\n * });\n * ```\n */\n\nimport View from '@core/View.js';\n\nclass TagInputView extends View {\n constructor(options = {}) {\n const {\n name,\n value = '',\n placeholder = 'Add tags...',\n maxTags = 50,\n allowDuplicates = false,\n separator = ',',\n trimTags = true,\n minLength = 1,\n maxLength = 50,\n disabled = false,\n readonly = false,\n class: containerClass = '',\n tagClass = 'badge bg-primary',\n inputClass = 'form-control',\n ...viewOptions\n } = options;\n\n super({\n tagName: 'div',\n className: `tag-input-view ${containerClass}`,\n ...viewOptions\n });\n\n // Configuration\n this.name = name;\n this.placeholder = placeholder;\n this.maxTags = maxTags;\n this.allowDuplicates = allowDuplicates;\n this.separator = separator;\n this.trimTags = trimTags;\n this.minLength = minLength;\n this.maxLength = maxLength;\n this.disabled = disabled;\n this.readonly = readonly;\n this.tagClass = tagClass;\n this.inputClass = inputClass;\n\n // State\n this.tags = [];\n this.focusedTagIndex = -1;\n\n // Parse initial value\n if (value) {\n this.tags = this.parseTagString(value);\n }\n }\n\n /**\n * Render the tag input component\n */\n async renderTemplate() {\n const tagsHTML = this.renderTags();\n const hiddenInputHTML = this.renderHiddenInput();\n const inputHTML = this.renderInput();\n\n return `\n <div class=\"tag-input-container\">\n <div class=\"tag-input-wrapper border rounded p-2\"\n data-action=\"focus-input\"\n tabindex=\"0\"\n role=\"combobox\"\n aria-expanded=\"false\"\n aria-label=\"Tag input\">\n <div class=\"tags-container d-flex flex-wrap gap-1 mb-2\">\n ${tagsHTML}\n </div>\n ${inputHTML}\n </div>\n ${hiddenInputHTML}\n <div class=\"tag-input-feedback small text-muted mt-1\">\n <span class=\"tag-count\">${this.tags.length}</span>/${this.maxTags} tags\n </div>\n </div>\n `;\n }\n\n /**\n * Render individual tags\n */\n renderTags() {\n return this.tags.map((tag, index) => `\n <span class=\"${this.tagClass} tag-item\"\n data-tag-index=\"${index}\"\n tabindex=\"0\"\n role=\"button\"\n aria-label=\"Tag: ${this.escapeHtml(tag)}. Press Delete or Backspace to remove.\">\n <span class=\"tag-text\">${this.escapeHtml(tag)}</span>\n ${!this.readonly && !this.disabled ? `\n <i class=\"bi bi-x tag-remove ms-1\"\n data-action=\"remove-tag\"\n data-tag-index=\"${index}\"\n aria-label=\"Remove tag\"></i>\n ` : ''}\n </span>\n `).join('');\n }\n\n /**\n * Render the input field\n */\n renderInput() {\n if (this.readonly) {\n return '';\n }\n\n return `\n <input type=\"text\"\n class=\"${this.inputClass} tag-input-field border-0 p-0\"\n placeholder=\"${this.escapeHtml(this.placeholder)}\"\n ${this.disabled ? 'disabled' : ''}\n data-change-action=\"input-change\"\n style=\"outline: none; box-shadow: none; min-width: 120px;\"\n autocomplete=\"off\">\n `;\n }\n\n /**\n * Render hidden input for form submission\n */\n renderHiddenInput() {\n if (!this.name) return '';\n\n return `\n <input type=\"hidden\"\n name=\"${this.name}\"\n value=\"${this.escapeHtml(this.getTagString())}\"\n class=\"tag-input-hidden\">\n `;\n }\n\n /**\n * Handle component initialization after render\n */\n async onAfterRender() {\n await super.onAfterRender();\n this.updateTagCount();\n }\n\n // ========================================\n // EventDelegate Action Handlers\n // ========================================\n\n /**\n * Handle focus on container\n */\n async onActionFocusInput(_event, _element) {\n this.focus();\n }\n\n focus() {\n const input = this.element.querySelector('.tag-input-field');\n if (input && !this.disabled) {\n input.focus();\n }\n this.focusedTagIndex = -1;\n }\n\n /**\n * Handle tag removal\n */\n async onActionRemoveTag(event, element) {\n event.stopPropagation();\n\n const tagIndex = parseInt(element.getAttribute('data-tag-index'));\n if (tagIndex >= 0 && tagIndex < this.tags.length) {\n await this.removeTag(tagIndex);\n }\n }\n\n /**\n * Handle input changes (for adding tags)\n */\n async onChangeInputChange(event, element) {\n const value = element.value;\n const lastChar = value.slice(-1);\n\n // Check for separator keys\n if (lastChar === this.separator || lastChar === '\\n') {\n event.preventDefault();\n const tagText = value.slice(0, -1);\n if (tagText.trim()) {\n await this.addTag(tagText);\n element.value = '';\n }\n return;\n }\n\n // Handle other trigger keys via keydown\n\n }\n\n bindEvents() {\n if (!this.__bnd_keydown) this.__bnd_keydown = this.handleInputKeydown.bind(this);\n this.element.addEventListener('keydown', this.__bnd_keydown);\n this.events.bind(this.element);\n }\n\n unbindEvents() {\n if (this.__bnd_keydown)this.element.removeEventListener('keydown', this.__bnd_keydown);\n this.events.unbind();\n }\n\n /**\n * Handle keyboard interactions\n */\n handleInputKeydown(event) {\n const input = event.target;\n const value = input.value || '';\n switch (event.key) {\n case 'Enter':\n case 'Tab':\n case ',':\n if (value.trim()) {\n event.preventDefault();\n this.addTag(value);\n input.value = '';\n }\n break;\n\n case 'Backspace':\n if (value === '' && this.tags.length > 0) {\n event.preventDefault();\n if (this.focusedTagIndex >= 0) {\n this.removeTag(this.focusedTagIndex);\n if (this.focusedTagIndex == 0) {\n this.focus();\n } else {\n this.focusTag(this.focusedTagIndex - 1);\n }\n } else {\n this.removeTag(this.tags.length - 1);\n }\n }\n break;\n\n case 'ArrowLeft':\n if (value === '' && this.tags.length > 0) {\n event.preventDefault();\n if (this.focusedTagIndex >= 0) {\n const newIndex = this.focusedTagIndex - 1;\n if (newIndex >= 0) {\n this.focusTag(newIndex);\n } else {\n this.focus();\n }\n } else {\n this.focusTag(this.tags.length - 1);\n }\n }\n break;\n\n case 'ArrowRight':\n if (value === '' && this.tags.length > 0) {\n event.preventDefault();\n if (this.focusedTagIndex >= 0) {\n const newIndex = this.focusedTagIndex + 1;\n if (newIndex < this.tags.length) {\n this.focusTag(newIndex);\n } else {\n this.focus();\n }\n } else {\n this.focusTag(0);\n }\n }\n break;\n\n case 'Escape':\n input.value = '';\n input.blur();\n break;\n }\n }\n\n // ========================================\n // Tag Management Methods\n // ========================================\n\n /**\n * Add a new tag\n */\n async addTag(tagText) {\n if (this.readonly || this.disabled) return false;\n\n const cleanTag = this.trimTags ? tagText.trim() : tagText;\n\n // Validation\n if (!this.isValidTag(cleanTag)) {\n return false;\n }\n\n // Check for duplicates\n if (!this.allowDuplicates && this.tags.includes(cleanTag)) {\n this.showTagError(`Tag \"${cleanTag}\" already exists`);\n return false;\n }\n\n // Check max tags limit\n if (this.tags.length >= this.maxTags) {\n this.showTagError(`Maximum ${this.maxTags} tags allowed`);\n return false;\n }\n\n // Add the tag\n this.tags.push(cleanTag);\n await this.updateDisplay();\n\n // Emit events\n this.emit('tag:added', { tag: cleanTag, tags: this.tags });\n this.emit('change', { value: this.getTagString(), tags: this.tags });\n\n return true;\n }\n\n /**\n * Remove a tag by index\n */\n async removeTag(index) {\n if (this.readonly || this.disabled) return false;\n\n if (index >= 0 && index < this.tags.length) {\n const removedTag = this.tags[index];\n this.tags.splice(index, 1);\n await this.updateDisplay();\n\n // Emit events\n this.emit('tag:removed', { tag: removedTag, tags: this.tags });\n this.emit('change', { value: this.getTagString(), tags: this.tags });\n\n return true;\n }\n\n return false;\n }\n\n /**\n * Remove a tag by value\n */\n async removeTagByValue(tagValue) {\n const index = this.tags.indexOf(tagValue);\n if (index >= 0) {\n return await this.removeTag(index);\n }\n return false;\n }\n\n /**\n * Clear all tags\n */\n async clearTags() {\n if (this.readonly || this.disabled) return false;\n\n const oldTags = [...this.tags];\n this.tags = [];\n await this.updateDisplay();\n\n this.emit('tags:cleared', { oldTags });\n this.emit('change', { value: '', tags: [] });\n\n return true;\n }\n\n /**\n * Set tags from array or string\n */\n async setTags(tagsInput) {\n let newTags = [];\n\n if (Array.isArray(tagsInput)) {\n newTags = tagsInput;\n } else if (typeof tagsInput === 'string') {\n newTags = this.parseTagString(tagsInput);\n }\n\n // Validate and filter tags\n newTags = newTags\n .filter(tag => this.isValidTag(tag))\n .slice(0, this.maxTags);\n\n // Remove duplicates if not allowed\n if (!this.allowDuplicates) {\n newTags = [...new Set(newTags)];\n }\n\n this.tags = newTags;\n await this.updateDisplay();\n\n this.emit('tags:set', { tags: this.tags });\n this.emit('change', { value: this.getTagString(), tags: this.tags });\n }\n\n // ========================================\n // Utility Methods\n // ========================================\n\n /**\n * Validate a tag\n */\n isValidTag(tag) {\n if (typeof tag !== 'string') return false;\n if (tag.length < this.minLength) return false;\n if (tag.length > this.maxLength) return false;\n if (tag.trim() === '') return false;\n return true;\n }\n\n /**\n * Parse tag string into array\n */\n parseTagString(tagString) {\n if (!tagString) return [];\n\n return tagString\n .split(this.separator)\n .map(tag => this.trimTags ? tag.trim() : tag)\n .filter(tag => tag.length > 0);\n }\n\n /**\n * Get tags as a string\n */\n getTagString() {\n return this.tags.join(this.separator);\n }\n\n /**\n * Get tags as array\n */\n getTags() {\n return [...this.tags];\n }\n\n /**\n * Focus a specific tag\n */\n focusTag(index) {\n const tagElements = this.element.querySelectorAll('.tag-item');\n if (tagElements[index]) {\n this.focusedTagIndex = index;\n console.log(`Focused tag index: ${index}`);\n tagElements[index].focus();\n }\n }\n\n /**\n * Update the display after changes\n */\n async updateDisplay() {\n // Re-render tags container\n const tagsContainer = this.element.querySelector('.tags-container');\n if (tagsContainer) {\n tagsContainer.innerHTML = this.renderTags();\n }\n\n // Update hidden input\n const hiddenInput = this.element.querySelector('.tag-input-hidden');\n if (hiddenInput) {\n hiddenInput.value = this.getTagString();\n }\n\n // Update tag count\n this.updateTagCount();\n }\n\n /**\n * Update tag count display\n */\n updateTagCount() {\n const tagCountElement = this.element.querySelector('.tag-count');\n if (tagCountElement) {\n tagCountElement.textContent = this.tags.length;\n }\n }\n\n /**\n * Show tag error message\n */\n showTagError(message) {\n // Create or update error message\n let errorElement = this.element.querySelector('.tag-error');\n\n if (!errorElement) {\n errorElement = document.createElement('div');\n errorElement.className = 'tag-error small text-danger mt-1';\n\n const feedback = this.element.querySelector('.tag-input-feedback');\n if (feedback) {\n feedback.parentNode.insertBefore(errorElement, feedback.nextSibling);\n }\n }\n\n errorElement.textContent = message;\n\n // Auto-hide after 3 seconds\n setTimeout(() => {\n if (errorElement.parentNode) {\n errorElement.remove();\n }\n }, 3000);\n }\n\n /**\n * Enable/disable the component\n */\n setEnabled(enabled) {\n this.disabled = !enabled;\n\n const input = this.element.querySelector('.tag-input-field');\n if (input) {\n input.disabled = this.disabled;\n }\n\n const container = this.element.querySelector('.tag-input-wrapper');\n if (container) {\n container.classList.toggle('disabled', this.disabled);\n }\n }\n\n /**\n * Set readonly state\n */\n setReadonly(readonly) {\n this.readonly = readonly;\n\n const input = this.element.querySelector('.tag-input-field');\n if (input) {\n input.style.display = readonly ? 'none' : '';\n }\n\n // Hide remove buttons\n const removeButtons = this.element.querySelectorAll('.tag-remove');\n removeButtons.forEach(btn => {\n btn.style.display = readonly ? 'none' : '';\n });\n }\n\n /**\n * Escape HTML to prevent XSS\n */\n escapeHtml(str) {\n if (str == null) return '';\n const div = document.createElement('div');\n div.textContent = String(str);\n return div.innerHTML;\n }\n\n /**\n * Get form value (for integration with forms)\n */\n getFormValue() {\n return this.getTagString();\n }\n\n /**\n * Set form value (for integration with forms)\n */\n async setFormValue(value) {\n await this.setTags(value);\n }\n\n /**\n * Static factory method\n */\n static create(options = {}) {\n return new TagInputView(options);\n }\n}\n\nexport default TagInputView;\n","/**\n * CollectionSelectView - A searchable dropdown component for selecting items from a Collection\n *\n * This component uses a parent-child architecture to prevent input focus loss:\n * - CollectionSelectView (parent): Manages input and coordination\n * - CollectionDropdownView (child): Handles dropdown rendering only\n */\n\nimport { View } from '@core/View.js';\nimport MOJOUtils from '@core/utils/MOJOUtils.js';\n\n/**\n * CollectionDropdownView - Child component for dropdown results only\n */\nclass CollectionDropdownView extends View {\n constructor(options = {}) {\n super({\n tagName: 'div',\n className: 'collection-dropdown-view dropdown-menu show w-100 position-absolute',\n style: 'max-height: 250px; overflow-y: auto; z-index: 1000;',\n template: `\n {{#data.loading}}\n <div class=\"dropdown-item text-center\">\n <div class=\"spinner-border spinner-border-sm\" role=\"status\">\n <span class=\"visually-hidden\">Loading...</span>\n </div>\n </div>\n {{/data.loading}}\n\n {{^data.loading}}\n {{#data.items}}\n <button type=\"button\"\n class=\"dropdown-item {{#isSelected}}active{{/isSelected}} {{#isFocused}}bg-light{{/isFocused}}\"\n data-action=\"select-item\"\n data-value=\"{{valueField}}\"\n data-label=\"{{labelField}}\"\n data-index=\"{{index}}\">\n {{labelField}}\n </button>\n {{/data.items}}\n\n {{#data.showNoResults}}\n <div class=\"dropdown-item text-muted\">\n {{#data.hasSearched}}No results found{{/data.hasSearched}}\n {{^data.hasSearched}}Start typing to search...{{/data.hasSearched}}\n </div>\n {{/data.showNoResults}}\n {{/data.loading}}\n `,\n ...options\n });\n\n this.collection = options.collection;\n this.labelField = options.labelField || 'name';\n this.valueField = options.valueField || 'id';\n this.selectedValue = options.selectedValue || '';\n this.loading = options.loading || false;\n this.hasSearched = options.hasSearched || false;\n this.focusedIndex = options.focusedIndex || -1;\n }\n\n async getViewData() {\n const items = this.collection ? this.collection.toJSON().map((item, index) => {\n const labelValue = MOJOUtils.getNestedValue(item, this.labelField);\n const fieldValue = MOJOUtils.getNestedValue(item, this.valueField);\n\n return {\n ...item,\n labelField: labelValue,\n valueField: fieldValue,\n isSelected: fieldValue == this.selectedValue,\n isFocused: index === this.focusedIndex,\n index\n };\n }) : [];\n\n return {\n loading: this.loading,\n hasSearched: this.hasSearched,\n showNoResults: !this.loading && this.hasSearched && items.length === 0,\n items\n };\n }\n\n async handleActionSelectItem(event, element) {\n event.preventDefault();\n const value = element.getAttribute('data-value');\n const label = element.getAttribute('data-label');\n this.emit('item-selected', { value, label });\n }\n\n updateState(state) {\n Object.assign(this, state);\n }\n\n updateFocusedItem(newIndex) {\n this.focusedIndex = newIndex;\n const items = this.element?.querySelectorAll('.dropdown-item[data-action=\"select-item\"]');\n items?.forEach((item, index) => {\n item.classList.toggle('bg-light', index === this.focusedIndex);\n });\n }\n\n getItemCount() {\n return this.collection ? this.collection.length() : 0;\n }\n\n getFocusedItem() {\n if (this.focusedIndex >= 0 && this.collection) {\n const items = this.collection.toJSON();\n return items[this.focusedIndex] || null;\n }\n return null;\n }\n}\n\n/**\n * CollectionSelectView - Main component with stable input\n */\nclass CollectionSelectView extends View {\n constructor(options = {}) {\n super({\n className: 'collection-select-view',\n template: `\n <div class=\"position-relative\">\n <input type=\"text\"\n class=\"form-control {{#data.hasError}}is-invalid{{/data.hasError}} {{#data.showClear}}pe-5{{/data.showClear}}\"\n placeholder=\"{{data.placeholder}}\"\n value=\"{{data.displayValue}}\"\n autocomplete=\"off\" />\n\n <input type=\"hidden\"\n name=\"{{data.name}}\"\n value=\"{{data.selectedValue}}\" />\n\n {{#data.showClear}}\n <button type=\"button\"\n class=\"btn btn-link position-absolute top-50 end-0 translate-middle-y me-2 p-0 border-0\"\n style=\"z-index: 10; color: #6c757d;\"\n data-action=\"clear-selection\"\n title=\"Clear selection\">\n <i class=\"bi bi-x-circle\"></i>\n </button>\n {{/data.showClear}}\n\n <div class=\"dropdown-container\"></div>\n\n {{#data.hasError}}\n <div class=\"invalid-feedback\">{{data.errorMessage}}</div>\n {{/data.hasError}}\n </div>\n `,\n ...options\n });\n\n // Configuration\n this.collection = options.collection;\n this.labelField = options.labelField || 'name';\n this.valueField = options.valueField || 'id';\n this.maxItems = options.maxItems || 10;\n this.placeholder = options.placeholder || 'Search...';\n this.debounceMs = options.debounceMs || 400;\n this.name = options.name || 'collection_select';\n this.emptyFetch = options.emptyFetch !== false;\n this.requiresActiveGroup = options.requiresActiveGroup || false;\n\n // State\n this.selectedValue = options.value || '0';\n this.selectedLabel = '';\n this.searchValue = '';\n this.showDropdown = false;\n this.loading = false;\n this.hasSearched = false;\n this.focusedIndex = -1;\n this.hasError = false;\n this.errorMessage = '';\n\n if (this.selectedValue && typeof this.selectedValue === 'object') {\n // Support dot notation in labelField and valueField\n this.selectedLabel = MOJOUtils.getNestedValue(this.selectedValue, this.labelField) || '';\n this.selectedValue = MOJOUtils.getNestedValue(this.selectedValue, this.valueField) || '0';\n }\n\n // Internal\n this.searchTimer = null;\n this.dropdownView = null;\n this.defaultParams = {};\n this.defaultParamsOption = options.defaultParams || null; // Can be dict or callback\n\n // Bind methods\n this.handleDocumentClick = this.handleDocumentClick.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n this.handleInputEvents = this.handleInputEvents.bind(this);\n\n }\n\n onInit() {\n if (this.collection) {\n this.setupCollection();\n }\n }\n\n setupCollection() {\n this.defaultParams = { ...this.collection.params };\n this.collection.params.size = this.maxItems;\n this.defaultParams.size = this.maxItems;\n\n // Merge defaultParams from options (dict or callback)\n if (this.defaultParamsOption) {\n const extraParams = typeof this.defaultParamsOption === 'function' \n ? this.defaultParamsOption() \n : this.defaultParamsOption;\n \n if (extraParams && typeof extraParams === 'object') {\n Object.assign(this.defaultParams, extraParams);\n Object.assign(this.collection.params, extraParams);\n }\n }\n\n // Add active group filter if required\n if (this.requiresActiveGroup) {\n const app = this.getApp();\n if (app && app.activeGroup && app.activeGroup.id) {\n this.collection.params.group = app.activeGroup.id;\n this.defaultParams.group = app.activeGroup.id;\n }\n }\n\n this.collection.on('fetch:start', () => {\n this.loading = true;\n this.showDropdown = true;\n this.updateDropdown();\n });\n\n this.collection.on('fetch:end', () => {\n this.loading = false;\n this.showDropdown = true;\n this.updateDropdown();\n });\n\n if (this.selectedValue) {\n this.loadSelectedItem();\n }\n\n if (this.emptyFetch && this.collection.isEmpty()) {\n this.performInitialFetch();\n }\n }\n\n async performInitialFetch() {\n if (!this.collection) return;\n\n try {\n const fetchParams = { ...this.defaultParams };\n delete fetchParams.search;\n await this.collection.updateParams(fetchParams, true);\n } catch (error) {\n console.error('Initial fetch error:', error);\n }\n }\n\n async loadSelectedItem() {\n try {\n if (!this.selectedValue || this.selectedValue == '0') return;\n if (this.selectedLabel) return;\n const selectedModel = this.collection?.get(this.selectedValue);\n if (selectedModel) {\n // Support dot notation in labelField\n this.selectedLabel = this.getFieldValue(selectedModel, this.labelField);\n this.render(false);\n return;\n }\n\n let model = await this.collection.fetchOne(this.selectedValue);\n if (model) {\n // Support dot notation in labelField\n this.selectedLabel = this.getFieldValue(model, this.labelField) || `${model.constructor.name} #${model.id}`;\n this.render(false);\n }\n } catch (error) {\n console.error('Error loading selected item:', error);\n }\n }\n\n async getViewData() {\n let displayValue = '';\n if (this.showDropdown && this.hasSearched) {\n displayValue = this.searchValue;\n } else if (this.selectedValue && this.selectedLabel) {\n displayValue = this.selectedLabel;\n }\n\n return {\n name: this.name,\n placeholder: this.placeholder,\n displayValue: displayValue,\n selectedValue: this.selectedValue,\n showClear: !!(this.selectedValue && this.selectedValue !== '0' && this.selectedLabel),\n hasError: this.hasError,\n errorMessage: this.errorMessage\n };\n }\n\n async onAfterRender() {\n await super.onAfterRender();\n\n // Set up stable event listeners on input\n const input = this.getInput();\n if (input) {\n input.addEventListener('input', this.handleInputEvents);\n input.addEventListener('focus', this.handleInputEvents);\n input.addEventListener('keydown', this.handleKeyDown);\n }\n\n document.addEventListener('click', this.handleDocumentClick);\n\n // Create dropdown view\n this.createDropdownView();\n }\n\n async onBeforeDestroy() {\n await super.onBeforeDestroy();\n\n const input = this.getInput();\n if (input) {\n input.removeEventListener('input', this.handleInputEvents);\n input.removeEventListener('focus', this.handleInputEvents);\n input.removeEventListener('keydown', this.handleKeyDown);\n }\n\n document.removeEventListener('click', this.handleDocumentClick);\n\n if (this.searchTimer) {\n clearTimeout(this.searchTimer);\n }\n\n if (this.dropdownView) {\n this.dropdownView.destroy();\n }\n }\n\n createDropdownView() {\n if (this.dropdownView) {\n this.dropdownView.destroy();\n }\n\n this.dropdownView = new CollectionDropdownView({\n collection: this.collection,\n labelField: this.labelField,\n valueField: this.valueField,\n selectedValue: this.selectedValue,\n loading: this.loading,\n hasSearched: this.hasSearched,\n focusedIndex: this.focusedIndex\n });\n\n this.dropdownView.on('item-selected', (data) => {\n this.selectItem(data.value, data.label);\n });\n }\n\n async handleInputEvents(event) {\n const input = event.target;\n\n if (event.type === 'focus') {\n this.showDropdown = true;\n if (!this.hasSearched && this.emptyFetch && this.collection?.isEmpty()) {\n this.performInitialFetch();\n }\n this.updateDropdown();\n } else if (event.type === 'input') {\n this.searchValue = input.value;\n this.showDropdown = true;\n this.hasSearched = true;\n this.focusedIndex = -1;\n\n if (this.searchValue !== this.selectedLabel) {\n this.selectedValue = '0';\n this.selectedLabel = '';\n this.emit('change', { value: '0', label: '' });\n }\n\n if (this.searchTimer) {\n clearTimeout(this.searchTimer);\n }\n\n this.searchTimer = setTimeout(() => {\n this.performSearch();\n }, this.debounceMs);\n\n this.updateDropdown();\n }\n }\n\n async handleActionClearSelection(event, _element) {\n event.preventDefault();\n event.stopPropagation();\n\n this.clearSelection();\n }\n\n clearSelection() {\n this.selectedValue = '0';\n this.selectedLabel = '';\n this.searchValue = '';\n this.showDropdown = false;\n this.hasError = false;\n this.focusedIndex = -1;\n this.hasSearched = false;\n\n // Update input display\n const input = this.getInput();\n if (input) {\n input.value = '';\n input.focus(); // Focus back on input after clearing\n }\n\n // Update hidden input\n const hiddenInput = this.getHiddenInput();\n if (hiddenInput) {\n hiddenInput.value = '0';\n }\n\n this.updateDropdown();\n this.render(); // Re-render to hide clear button\n this.emit('change', { value: '0', label: '' });\n }\n\n async performSearch() {\n if (!this.collection) return;\n\n // this.loading = true;\n // this.updateDropdown();\n\n try {\n const searchParams = { ...this.defaultParams };\n if (this.searchValue && this.searchValue.trim()) {\n searchParams.search = this.searchValue.trim();\n }\n await this.collection.updateParams(searchParams, true);\n } catch (error) {\n console.error('Search error:', error);\n this.loading = false;\n this.updateDropdown();\n }\n }\n\n updateDropdown() {\n if (!this.dropdownView) return;\n\n this.dropdownView.updateState({\n selectedValue: this.selectedValue,\n loading: this.loading,\n hasSearched: this.hasSearched,\n focusedIndex: this.focusedIndex\n });\n\n if (this.showDropdown) {\n if (!this.dropdownView.isMounted()) {\n const container = this.element?.querySelector('.dropdown-container');\n if (container) {\n this.dropdownView.render(true, container);\n }\n } else {\n this.dropdownView.render();\n }\n } else if (this.dropdownView.isMounted()) {\n this.dropdownView.destroy();\n this.createDropdownView();\n }\n }\n\n selectItem(value, label) {\n this.selectedValue = value;\n this.selectedLabel = label;\n this.searchValue = '';\n this.showDropdown = false;\n this.hasError = false;\n this.focusedIndex = -1;\n this.hasSearched = false;\n\n // Update input display\n const input = this.getInput();\n if (input) {\n input.value = label;\n }\n\n // Update hidden input\n const hiddenInput = this.getHiddenInput();\n if (hiddenInput) {\n hiddenInput.value = value;\n }\n\n this.updateDropdown();\n this.emit('change', { value, label });\n }\n\n handleDocumentClick(event) {\n if (!this.element?.contains(event.target)) {\n this.showDropdown = false;\n this.focusedIndex = -1;\n this.updateDropdown();\n }\n }\n\n handleKeyDown(event) {\n if (!this.showDropdown || !this.collection) return;\n\n const itemCount = this.dropdownView?.getItemCount() || 0;\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n this.focusedIndex = Math.min(this.focusedIndex + 1, itemCount - 1);\n this.dropdownView?.updateFocusedItem(this.focusedIndex);\n break;\n\n case 'ArrowUp':\n event.preventDefault();\n this.focusedIndex = Math.max(this.focusedIndex - 1, 0);\n this.dropdownView?.updateFocusedItem(this.focusedIndex);\n break;\n\n case 'Enter': {\n event.preventDefault();\n const focusedItem = this.dropdownView?.getFocusedItem();\n if (focusedItem) {\n this.selectItem(focusedItem[this.valueField], focusedItem[this.labelField]);\n }\n break;\n }\n\n case 'Escape':\n event.preventDefault();\n this.showDropdown = false;\n this.focusedIndex = -1;\n this.updateDropdown();\n break;\n }\n }\n\n // Helper methods\n getInput() {\n return this.element?.querySelector('input[type=\"text\"]');\n }\n\n getHiddenInput() {\n return this.element?.querySelector('input[type=\"hidden\"]');\n }\n\n // Public API\n setValue(value, label = '') {\n this.selectedValue = value;\n this.selectedLabel = label;\n this.searchValue = '';\n this.hasError = false;\n this.hasSearched = false;\n\n const input = this.getInput();\n if (input) {\n input.value = label;\n }\n\n const hiddenInput = this.getHiddenInput();\n if (hiddenInput) {\n hiddenInput.value = value;\n }\n }\n\n getValue() {\n // Return null if value is 0 or '0' (no selection)\n if (this.selectedValue === 0 || this.selectedValue === '0') {\n return null;\n }\n return this.selectedValue;\n }\n\n getLabel() {\n return this.selectedLabel;\n }\n\n setError(message) {\n this.hasError = true;\n this.errorMessage = message;\n this.render();\n }\n\n clearError() {\n this.hasError = false;\n this.errorMessage = '';\n this.render();\n }\n\n focus() {\n const input = this.getInput();\n if (input) {\n input.focus();\n }\n }\n\n // FormBuilder integration\n getFormValue() {\n // Return null if value is 0 or '0' (no selection)\n if (this.selectedValue === 0 || this.selectedValue === '0') {\n return null;\n }\n return this.selectedValue;\n }\n\n setFormValue(value) {\n let newValue = value;\n let newLabel = '';\n\n if (newValue && typeof newValue === 'object') {\n // Support dot notation in labelField and valueField\n newLabel = MOJOUtils.getNestedValue(newValue, this.labelField) || '';\n newValue = MOJOUtils.getNestedValue(newValue, this.valueField);\n }\n\n newValue = newValue || '0';\n\n if (newValue == this.selectedValue) {\n return;\n }\n\n this.selectedValue = newValue;\n this.selectedLabel = newLabel;\n this.searchValue = '';\n this.hasSearched = false;\n this.showDropdown = false;\n this.hasError = false;\n\n if (this.selectedValue && this.selectedValue !== '0') {\n if (!this.selectedLabel) {\n this.selectedLabel = `${this.collection.getModelName()} #${this.selectedValue}`;\n }\n this.loadSelectedItem();\n } else {\n this.render();\n }\n }\n\n /**\n * Helper method to get field value from model or plain object with dot notation support\n * @param {Object|Model} item - The item to get value from\n * @param {string} fieldPath - The field path (supports dot notation)\n * @returns {*} The field value\n */\n getFieldValue(item, fieldPath) {\n if (!item || !fieldPath) return undefined;\n\n // If item has a get() method (Model instance), try using it first\n if (typeof item.get === 'function') {\n // Try to get the value using Model's get() method\n const value = item.get(fieldPath);\n // If get() returns undefined and path has dots, fall back to MOJOUtils\n if (value === undefined && fieldPath.includes('.')) {\n return MOJOUtils.getNestedValue(item, fieldPath);\n }\n return value;\n }\n\n // For plain objects, use MOJOUtils for dot notation support\n return MOJOUtils.getNestedValue(item, fieldPath);\n }\n\n}\n\nexport default CollectionSelectView;\n","/**\n * CollectionMultiSelect - MVC multi-select component\n * \n * Architecture:\n * - CollectionMultiSelectView (parent) - Coordinates child views\n * - SearchView (child) - Search input with live search\n * - ListItemsView (child) - Checkbox list display\n */\n\nimport { View } from '@core/View.js';\nimport MOJOUtils from '@core/utils/MOJOUtils.js';\n\n/**\n * SearchView - Search input child view\n */\nclass SearchView extends View {\n constructor(options = {}) {\n super({\n tagName: 'div',\n className: 'collection-multiselect-search',\n template: `\n <input type=\"text\" \n class=\"form-control form-control-sm mb-2\" \n placeholder=\"{{placeholder}}\"\n data-change-action=\"search\"\n data-filter=\"live-search\"\n data-filter-debounce=\"{{debounce}}\" />\n `,\n ...options\n });\n\n this.placeholder = options.placeholder || 'Search...';\n this.debounce = options.debounce || 400;\n }\n\n async onChangeSearch(event, element) {\n const searchValue = element.value.trim();\n this.emit('search', searchValue);\n }\n\n getValue() {\n return this.element?.querySelector('input')?.value || '';\n }\n\n clear() {\n const input = this.element?.querySelector('input');\n if (input) input.value = '';\n }\n}\n\n/**\n * ListItemsView - Checkbox list child view\n */\nclass ListItemsView extends View {\n constructor(options = {}) {\n // Build item template based on whether custom template is provided\n const hasCustomTemplate = !!options.customItemTemplate;\n const itemContentTemplate = hasCustomTemplate \n ? `{{{customContent}}}` \n : `<span {{#disabled}}class=\"text-muted\"{{/disabled}}>{{label}}</span>`;\n\n super({\n tagName: 'div',\n className: 'collection-multiselect-items',\n template: `\n {{#loading}}\n <div class=\"text-center py-3\">\n <div class=\"spinner-border spinner-border-sm\" role=\"status\">\n <span class=\"visually-hidden\">Loading...</span>\n </div>\n </div>\n {{/loading}}\n\n {{^loading}}\n {{#items.length}}\n {{#showSelectAll}}\n <div class=\"collection-multiselect-actions d-flex justify-content-between align-items-center mb-2 py-1\">\n <button type=\"button\" \n class=\"btn btn-link btn-sm text-decoration-none p-0 {{#allSelected}}text-muted{{/allSelected}}\" \n data-action=\"select-all\"\n {{#allSelected}}disabled{{/allSelected}}>\n <i class=\"bi bi-check-square me-1\"></i>\n SELECT {{#unselectedCount}}({{unselectedCount}}){{/unselectedCount}}\n </button>\n <button type=\"button\" \n class=\"btn btn-link btn-sm text-decoration-none p-0 {{#noneSelected}}text-muted{{/noneSelected}}\" \n data-action=\"deselect-all\"\n {{#noneSelected}}disabled{{/noneSelected}}>\n DESELECT {{#selectedCount}}({{selectedCount}}){{/selectedCount}}\n <i class=\"bi bi-square ms-1\"></i>\n </button>\n </div>\n {{/showSelectAll}}\n \n <div class=\"collection-multiselect-list border rounded\" \n style=\"max-height: {{maxHeight}}px; overflow-y: auto;\">\n {{#items}}\n <div class=\"collection-multiselect-item d-flex align-items-center py-2 px-3 {{^disabled}}clickable{{/disabled}}\" \n data-action=\"{{^disabled}}toggle{{/disabled}}\"\n data-value=\"{{value}}\"\n data-index=\"{{index}}\">\n <i class=\"bi {{#selected}}bi-check-square-fill text-primary{{/selected}}{{^selected}}bi-square{{/selected}} me-2\" \n style=\"font-size: 1.1rem;\"></i>\n ${itemContentTemplate}\n </div>\n {{/items}}\n </div>\n {{/items.length}}\n\n {{^items.length}}\n <div class=\"collection-multiselect-empty text-muted text-center py-4 border rounded\">\n <i class=\"bi bi-inbox fs-3 d-block mb-2 opacity-50\"></i>\n <div>No items available</div>\n </div>\n {{/^items.length}}\n {{/loading}}\n `,\n ...options\n });\n\n this.items = options.items || [];\n this.loading = options.loading || false;\n this.maxHeight = options.maxHeight || 336;\n this.showSelectAll = options.showSelectAll !== false;\n this.selectedCount = options.selectedCount || 0;\n this.totalCount = options.totalCount || 0;\n this.unselectedCount = options.unselectedCount || 0;\n this.allSelected = options.allSelected || false;\n this.noneSelected = options.noneSelected || true;\n this.customItemTemplate = options.customItemTemplate || null;\n this.lastClickedIndex = -1;\n }\n\n handleActionToggle(event, element) {\n const value = element.getAttribute('data-value');\n const index = parseInt(element.getAttribute('data-index'), 10);\n this.emit('toggle', { value, index, shiftKey: event.shiftKey });\n this.lastClickedIndex = index;\n }\n\n async handleActionSelectAll(event) {\n event.preventDefault();\n this.emit('select-all');\n }\n\n async handleActionDeselectAll(event) {\n event.preventDefault();\n this.emit('deselect-all');\n }\n\n updateState(state) {\n Object.assign(this, state);\n }\n}\n\n/**\n * CollectionMultiSelectView - Parent coordinator view\n */\nclass CollectionMultiSelectView extends View {\n constructor(options = {}) {\n super({\n tagName: 'div',\n className: 'collection-multiselect-view',\n template: `\n <div class=\"mojo-form-control\">\n {{#label}}\n <label class=\"form-label\">\n {{label}}{{#required}}<span class=\"text-danger\">*</span>{{/required}}\n </label>\n {{/label}}\n \n <div class=\"collection-multiselect-search-container\"></div>\n <div class=\"collection-multiselect-list-container\"></div>\n\n {{#help}}\n <div class=\"form-text\">{{help}}</div>\n {{/help}}\n {{#error}}\n <div class=\"invalid-feedback d-block\">{{error}}</div>\n {{/error}}\n </div>\n `,\n ...options\n });\n\n // Basic config\n this.name = options.name || 'collection_multiselect';\n this.label = options.label || '';\n this.help = options.help || '';\n this.error = options.error || '';\n this.required = options.required || false;\n this.disabled = options.disabled || false;\n\n // Collection\n this.collection = options.collection;\n this.labelField = options.labelField || 'name';\n this.valueField = options.valueField || 'id';\n this.excludeIds = options.excludeIds || []; // Server-side filtering (deprecated)\n this.ignoreIds = options.ignoreIds || []; // Client-side filtering\n this.itemTemplate = options.itemTemplate || null; // Custom mustache template for items\n \n // Params\n this.collectionParams = options.collectionParams || {};\n this.defaultParamsOption = options.defaultParams || null;\n this.baseParams = {};\n this.requiresActiveGroup = options.requiresActiveGroup || false;\n\n // UI\n this.size = options.size || 8;\n this.maxHeight = options.maxHeight || (this.size * 42);\n this.showSelectAll = options.showSelectAll !== false;\n this.enableSearch = options.enableSearch || false;\n this.searchPlaceholder = options.searchPlaceholder || 'Search...';\n this.searchDebounce = options.searchDebounce || 400;\n\n // State\n this.selectedValues = Array.isArray(options.value) ? options.value : [];\n this.loading = false;\n this.items = [];\n\n // Child views\n this.searchView = null;\n this.listView = null;\n }\n\n onInit() {\n if (this.collection) {\n this.setupCollection();\n }\n }\n\n setupCollection() {\n // Store base params\n this.baseParams = { ...this.collection.params };\n\n // Apply collectionParams\n if (Object.keys(this.collectionParams).length > 0) {\n Object.assign(this.baseParams, this.collectionParams);\n Object.assign(this.collection.params, this.collectionParams);\n }\n\n // Apply defaultParams (dict or callback)\n if (this.defaultParamsOption) {\n const extraParams = typeof this.defaultParamsOption === 'function' \n ? this.defaultParamsOption() \n : this.defaultParamsOption;\n \n if (extraParams) {\n Object.assign(this.baseParams, extraParams);\n Object.assign(this.collection.params, extraParams);\n }\n }\n\n // Active group filter\n if (this.requiresActiveGroup) {\n const app = this.getApp();\n if (app?.activeGroup?.id) {\n this.baseParams.group = app.activeGroup.id;\n this.collection.params.group = app.activeGroup.id;\n }\n }\n\n // Collection events\n this.collection.on('fetch:start', () => {\n this.loading = true;\n this.updateListView();\n });\n\n this.collection.on('fetch:end', () => {\n this.loading = false;\n this.buildItems();\n this.updateListView();\n });\n\n // Use existing data if available\n if (!this.collection.isEmpty()) {\n this.buildItems();\n }\n }\n\n async onAfterRender() {\n await super.onAfterRender();\n\n // Create child views\n if (this.enableSearch) {\n this.createSearchView();\n }\n this.createListView();\n\n // Fetch if empty\n if (this.collection?.isEmpty()) {\n this.collection.fetch();\n }\n }\n\n createSearchView() {\n const container = this.element?.querySelector('.collection-multiselect-search-container');\n if (!container) return;\n\n this.searchView = new SearchView({\n placeholder: this.searchPlaceholder,\n debounce: this.searchDebounce\n });\n\n this.searchView.on('search', (searchValue) => {\n this.handleSearch(searchValue);\n });\n\n this.searchView.render(true, container);\n }\n\n createListView() {\n const container = this.element?.querySelector('.collection-multiselect-list-container');\n if (!container) return;\n\n const selectedCount = this.selectedValues.length;\n const totalCount = this.items.length;\n const unselectedCount = totalCount - selectedCount;\n\n this.listView = new ListItemsView({\n items: this.items,\n loading: this.loading,\n maxHeight: this.maxHeight,\n showSelectAll: this.showSelectAll,\n selectedCount,\n totalCount,\n unselectedCount,\n allSelected: selectedCount === totalCount && totalCount > 0,\n noneSelected: selectedCount === 0,\n customItemTemplate: this.itemTemplate\n });\n\n this.listView.on('toggle', (data) => {\n this.handleToggle(data);\n });\n\n this.listView.on('select-all', () => {\n this.selectAll();\n });\n\n this.listView.on('deselect-all', () => {\n this.deselectAll();\n });\n\n this.listView.render(true, container);\n }\n\n updateListView() {\n if (this.listView) {\n const selectedCount = this.selectedValues.length;\n const totalCount = this.items.length;\n const unselectedCount = totalCount - selectedCount;\n\n this.listView.updateState({\n items: this.items,\n loading: this.loading,\n selectedCount,\n totalCount,\n unselectedCount,\n allSelected: selectedCount === totalCount && totalCount > 0,\n noneSelected: selectedCount === 0\n });\n this.listView.render(false);\n }\n }\n\n // Build items array from collection\n buildItems() {\n const models = this.collection.models.filter(model => {\n const id = this.getFieldValue(model, this.valueField);\n if (id == null) return false;\n \n // Filter out excludeIds (legacy support)\n if (this.excludeIds.includes(id)) return false;\n \n // Filter out ignoreIds (client-side filtering)\n if (this.ignoreIds.some(ignoreId => ignoreId == id)) return false;\n \n return true;\n });\n\n this.items = models.map((model, index) => {\n const modelData = model.toJSON ? model.toJSON() : model;\n const value = this.getFieldValue(model, this.valueField);\n \n const item = {\n label: this.getFieldValue(model, this.labelField),\n value,\n index,\n selected: this.selectedValues.some(v => v == value),\n disabled: this.disabled,\n model: modelData // All model data nested under 'model' context\n };\n\n // Render custom template if provided\n if (this.itemTemplate) {\n item.customContent = this.renderItemTemplate(item);\n }\n\n return item;\n });\n }\n\n // Render custom item template\n renderItemTemplate(itemData) {\n if (!this.itemTemplate) return '';\n \n try {\n const Mustache = window.Mustache || this.constructor.Mustache;\n if (!Mustache) {\n console.warn('Mustache not available for item template rendering');\n return itemData.label;\n }\n return Mustache.render(this.itemTemplate, itemData);\n } catch (error) {\n console.error('Error rendering item template:', error);\n return itemData.label;\n }\n }\n\n // Get field value (supports dot notation)\n getFieldValue(item, field) {\n if (!item || !field) return undefined;\n \n if (typeof item.get === 'function') {\n return item.get(field) ?? MOJOUtils.getNestedValue(item, field);\n }\n \n return MOJOUtils.getNestedValue(item, field);\n }\n\n // Handle search\n handleSearch(searchValue) {\n const params = { ...this.baseParams };\n if (searchValue) {\n params.search = searchValue;\n }\n this.collection.updateParams(params, true);\n }\n\n // Handle item toggle\n handleToggle({ value, index, shiftKey }) {\n // Shift-click range selection\n if (shiftKey && this.listView.lastClickedIndex >= 0) {\n const start = Math.min(this.listView.lastClickedIndex, index);\n const end = Math.max(this.listView.lastClickedIndex, index);\n const shouldSelect = !this.items[index].selected;\n \n for (let i = start; i <= end; i++) {\n const item = this.items[i];\n if (!item.disabled) {\n if (shouldSelect) {\n if (!this.selectedValues.includes(item.value)) {\n this.selectedValues.push(item.value);\n }\n } else {\n this.selectedValues = this.selectedValues.filter(v => v != item.value);\n }\n item.selected = shouldSelect;\n }\n }\n } else {\n // Normal toggle\n const item = this.items[index];\n if (item.selected) {\n this.selectedValues = this.selectedValues.filter(v => v != value);\n item.selected = false;\n } else {\n this.selectedValues.push(value);\n item.selected = true;\n }\n }\n\n this.updateListView();\n this.emit('change', { value: this.selectedValues, name: this.name });\n }\n\n // Select all\n selectAll() {\n this.selectedValues = this.items.filter(i => !i.disabled).map(i => i.value);\n this.items.forEach(i => { if (!i.disabled) i.selected = true; });\n this.updateListView();\n this.emit('change', { value: this.selectedValues, name: this.name });\n }\n\n // Deselect all\n deselectAll() {\n this.selectedValues = [];\n this.items.forEach(i => i.selected = false);\n this.updateListView();\n this.emit('change', { value: this.selectedValues, name: this.name });\n }\n\n async onBeforeDestroy() {\n await super.onBeforeDestroy();\n \n if (this.searchView) {\n this.searchView.destroy();\n }\n if (this.listView) {\n this.listView.destroy();\n }\n }\n\n // Public API\n getValue() { return this.selectedValues; }\n \n setValue(values) {\n this.selectedValues = Array.isArray(values) ? values : [];\n this.buildItems();\n this.updateListView();\n }\n\n setExcludeIds(ids) {\n this.excludeIds = Array.isArray(ids) ? ids : [];\n this.buildItems();\n this.updateListView();\n }\n\n setIgnoreIds(ids) {\n this.ignoreIds = Array.isArray(ids) ? ids : [];\n this.buildItems();\n this.updateListView();\n }\n\n async refresh() {\n await this.collection.fetch();\n }\n\n getFormValue() { return this.selectedValues; }\n setFormValue(value) { this.setValue(value); }\n}\n\nexport default CollectionMultiSelectView;\n","/**\n * DatePicker - Enhanced date picker input with Easepick integration\n * Falls back to native HTML5 date input if Easepick is unavailable\n * \n * Features:\n * - Dynamic CDN loading of Easepick\n * - Configurable date formats and constraints\n * - Keyboard navigation and accessibility\n * - Form integration with FormBuilder\n * - Graceful fallback to native date input\n * \n * Example Usage:\n * ```javascript\n * const datePicker = new DatePicker({\n * name: 'birth_date',\n * value: '2023-01-15',\n * format: 'YYYY-MM-DD',\n * min: '1900-01-01',\n * max: '2030-12-31',\n * placeholder: 'Select date...'\n * });\n * ```\n */\n\nimport View from '@core/View.js';\n\nclass DatePicker extends View {\n constructor(options = {}) {\n const {\n name,\n value = '',\n format = 'YYYY-MM-DD',\n displayFormat = 'MMM DD, YYYY',\n min = null,\n max = null,\n placeholder = 'Select date...',\n disabled = false,\n readonly = false,\n required = false,\n class: containerClass = '',\n inputClass = 'form-control',\n autoApply = true,\n inline = false,\n ...viewOptions\n } = options;\n\n super({\n tagName: 'div',\n className: `date-picker-view ${containerClass}`,\n ...viewOptions\n });\n\n // Configuration\n this.name = name;\n this.format = format;\n this.displayFormat = displayFormat;\n this.min = min;\n this.max = max;\n this.placeholder = placeholder;\n this.disabled = disabled;\n this.readonly = readonly;\n this.required = required;\n this.inputClass = inputClass;\n this.autoApply = autoApply;\n this.inline = inline;\n\n // State\n this.currentValue = value;\n this.picker = null;\n this.useNative = false;\n this.easepickLoaded = false;\n\n // Check if Easepick is available\n this.checkEasepickAvailability();\n }\n\n /**\n * Check if Easepick is available and load if needed\n */\n async checkEasepickAvailability() {\n if (typeof window !== 'undefined' && window.easepick) {\n this.easepickLoaded = true;\n return true;\n }\n\n // Try to load Easepick from CDN\n try {\n await this.loadEasepick();\n this.easepickLoaded = true;\n return true;\n } catch (error) {\n console.warn('Easepick failed to load, falling back to native date input:', error);\n this.useNative = true;\n return false;\n }\n }\n\n /**\n * Dynamically load Easepick from CDN\n */\n async loadEasepick() {\n return new Promise((resolve, reject) => {\n // Check if already loaded\n if (window.easepick) {\n resolve();\n return;\n }\n\n // Load CSS first\n const css = document.createElement('link');\n css.rel = 'stylesheet';\n css.href = 'https://cdn.jsdelivr.net/npm/@easepick/bundle@1.2.1/dist/index.css';\n document.head.appendChild(css);\n\n // Load JavaScript\n const script = document.createElement('script');\n script.src = 'https://cdn.jsdelivr.net/npm/@easepick/bundle@1.2.1/dist/index.umd.min.js';\n script.onload = () => {\n if (window.easepick) {\n resolve();\n } else {\n reject(new Error('Easepick not available after loading'));\n }\n };\n script.onerror = () => reject(new Error('Failed to load Easepick script'));\n document.head.appendChild(script);\n });\n }\n\n /**\n * Render the date picker component\n */\n async renderTemplate() {\n const inputId = this.getInputId();\n const inputType = this.useNative ? 'date' : 'text';\n const inputValue = this.formatValueForInput(this.currentValue);\n \n return `\n <div class=\"date-picker-container\">\n <input \n type=\"${inputType}\"\n id=\"${inputId}\"\n name=\"${this.name || ''}\"\n class=\"${this.inputClass}${this.hasError() ? ' is-invalid' : ''}\"\n value=\"${this.escapeHtml(inputValue)}\"\n placeholder=\"${this.escapeHtml(this.placeholder)}\"\n ${this.min ? `min=\"${this.min}\"` : ''}\n ${this.max ? `max=\"${this.max}\"` : ''}\n ${this.disabled ? 'disabled' : ''}\n ${this.readonly ? 'readonly' : ''}\n ${this.required ? 'required' : ''}\n autocomplete=\"off\"\n data-change-action=\"date-changed\"\n />\n <div class=\"date-picker-feedback\"></div>\n </div>\n `;\n }\n\n /**\n * Initialize after render\n */\n async onAfterRender() {\n await super.onAfterRender();\n \n if (this.easepickLoaded && !this.useNative) {\n await this.initializeEasepick();\n } else {\n this.initializeNativeFallback();\n }\n }\n\n /**\n * Initialize Easepick date picker\n */\n async initializeEasepick() {\n const input = this.getInputElement();\n if (!input || !window.easepick) return;\n\n try {\n const config = {\n element: input,\n css: [\n 'https://cdn.jsdelivr.net/npm/@easepick/bundle@1.2.1/dist/index.css',\n ],\n format: this.displayFormat,\n lang: 'en-US',\n autoApply: this.autoApply,\n inline: this.inline,\n readonly: this.readonly,\n zIndex: 9999,\n };\n\n // Add date constraints\n if (this.min) {\n config.minDate = new Date(this.min);\n }\n if (this.max) {\n config.maxDate = new Date(this.max);\n }\n\n // Add event handlers\n config.setup = (picker) => {\n picker.on('select', (e) => {\n const date = e.detail.date;\n this.handleDateChange(date ? this.formatDate(date, this.format) : '');\n });\n\n picker.on('clear', () => {\n this.handleDateChange('');\n });\n\n picker.on('show', () => {\n this.emit('picker:show');\n });\n\n picker.on('hide', () => {\n this.emit('picker:hide');\n });\n };\n\n this.picker = new window.easepick.create(config);\n\n // Set initial value if provided\n if (this.currentValue) {\n this.picker.setDate(this.currentValue);\n }\n\n } catch (error) {\n console.error('Failed to initialize Easepick:', error);\n this.useNative = true;\n this.initializeNativeFallback();\n }\n }\n\n /**\n * Initialize native HTML5 date input fallback\n */\n initializeNativeFallback() {\n const input = this.getInputElement();\n if (!input) return;\n\n // Convert to HTML5 date format if needed\n input.type = 'date';\n if (this.currentValue) {\n input.value = this.formatDate(this.currentValue, 'YYYY-MM-DD');\n }\n }\n\n // ========================================\n // Event Handlers\n // ========================================\n\n /**\n * Handle date change from input\n */\n async onChangeDateChanged(action, event, element) {\n const value = element.value;\n this.handleDateChange(value);\n }\n\n /**\n * Handle date change logic\n */\n handleDateChange(value) {\n const oldValue = this.currentValue;\n this.currentValue = value;\n\n // Update hidden input if exists\n this.updateHiddenInput();\n\n // Emit change events\n if (oldValue !== value) {\n this.emit('change', { \n value: value, \n formatted: this.formatValueForDisplay(value),\n oldValue: oldValue \n });\n this.emit('date:changed', { value, oldValue });\n }\n }\n\n // ========================================\n // Utility Methods\n // ========================================\n\n /**\n * Format date for different contexts\n */\n formatDate(date, format = this.format) {\n if (!date) return '';\n \n // Simple date formatting (can be enhanced)\n const d = new Date(date);\n if (isNaN(d.getTime())) return '';\n\n const year = d.getFullYear();\n const month = String(d.getMonth() + 1).padStart(2, '0');\n const day = String(d.getDate()).padStart(2, '0');\n \n switch (format) {\n case 'YYYY-MM-DD':\n return `${year}-${month}-${day}`;\n case 'MM/DD/YYYY':\n return `${month}/${day}/${year}`;\n case 'DD/MM/YYYY':\n return `${day}/${month}/${year}`;\n case 'MMM DD, YYYY':\n const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\n 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\n return `${monthNames[d.getMonth()]} ${day}, ${year}`;\n default:\n return `${year}-${month}-${day}`;\n }\n }\n\n /**\n * Format value for input display\n */\n formatValueForInput(value) {\n if (!value) return '';\n return this.useNative ? this.formatDate(value, 'YYYY-MM-DD') : value;\n }\n\n /**\n * Format value for display\n */\n formatValueForDisplay(value) {\n if (!value) return '';\n return this.formatDate(value, this.displayFormat);\n }\n\n /**\n * Get unique input ID\n */\n getInputId() {\n return this.name ? `datepicker_${this.name}_${Date.now()}` : `datepicker_${Date.now()}`;\n }\n\n /**\n * Get input element\n */\n getInputElement() {\n return this.element?.querySelector('input');\n }\n\n /**\n * Update hidden input for form submission\n */\n updateHiddenInput() {\n // This method can be used if we need a separate hidden input\n // for form submission with a different format\n }\n\n /**\n * Check if field has error\n */\n hasError() {\n return false; // Can be enhanced with validation\n }\n\n /**\n * Escape HTML to prevent XSS\n */\n escapeHtml(str) {\n if (str == null) return '';\n const div = document.createElement('div');\n div.textContent = String(str);\n return div.innerHTML;\n }\n\n // ========================================\n // Public API Methods\n // ========================================\n\n /**\n * Set the date value\n */\n setValue(value) {\n this.currentValue = value;\n \n if (this.picker && this.easepickLoaded) {\n this.picker.setDate(value || null);\n } else {\n const input = this.getInputElement();\n if (input) {\n input.value = this.formatValueForInput(value);\n }\n }\n \n this.emit('value:set', { value });\n }\n\n /**\n * Get the current date value\n */\n getValue() {\n return this.currentValue;\n }\n\n /**\n * Get formatted date value\n */\n getFormattedValue(format = this.displayFormat) {\n return this.formatDate(this.currentValue, format);\n }\n\n /**\n * Clear the date value\n */\n clear() {\n this.setValue('');\n }\n\n /**\n * Set min date constraint\n */\n setMin(minDate) {\n this.min = minDate;\n if (this.picker && this.easepickLoaded) {\n this.picker.options.minDate = new Date(minDate);\n } else {\n const input = this.getInputElement();\n if (input) {\n input.min = minDate;\n }\n }\n }\n\n /**\n * Set max date constraint\n */\n setMax(maxDate) {\n this.max = maxDate;\n if (this.picker && this.easepickLoaded) {\n this.picker.options.maxDate = new Date(maxDate);\n } else {\n const input = this.getInputElement();\n if (input) {\n input.max = maxDate;\n }\n }\n }\n\n /**\n * Enable/disable the picker\n */\n setEnabled(enabled) {\n this.disabled = !enabled;\n const input = this.getInputElement();\n if (input) {\n input.disabled = this.disabled;\n }\n if (this.picker && this.easepickLoaded) {\n // Easepick doesn't have direct disable method, so we handle it via input\n if (this.disabled) {\n this.picker.hide();\n }\n }\n }\n\n /**\n * Set readonly state\n */\n setReadonly(readonly) {\n this.readonly = readonly;\n const input = this.getInputElement();\n if (input) {\n input.readonly = readonly;\n }\n }\n\n /**\n * Focus the input\n */\n focus() {\n const input = this.getInputElement();\n if (input) {\n input.focus();\n }\n }\n\n /**\n * Show the picker (if using Easepick)\n */\n show() {\n if (this.picker && this.easepickLoaded) {\n this.picker.show();\n }\n }\n\n /**\n * Hide the picker (if using Easepick)\n */\n hide() {\n if (this.picker && this.easepickLoaded) {\n this.picker.hide();\n }\n }\n\n // ========================================\n // FormBuilder Integration\n // ========================================\n\n /**\n * Get form value (for FormBuilder integration)\n */\n getFormValue() {\n return this.getValue();\n }\n\n /**\n * Set form value (for FormBuilder integration)\n */\n async setFormValue(value) {\n this.setValue(value);\n }\n\n // ========================================\n // Lifecycle Methods\n // ========================================\n\n /**\n * Cleanup when component is destroyed\n */\n async onBeforeDestroy() {\n if (this.picker && this.easepickLoaded) {\n try {\n this.picker.destroy();\n } catch (error) {\n console.warn('Error destroying Easepick instance:', error);\n }\n }\n \n this.picker = null;\n await super.onBeforeDestroy();\n }\n\n /**\n * Static factory method\n */\n static create(options = {}) {\n return new DatePicker(options);\n }\n}\n\nexport default DatePicker;","/**\n * DateRangePicker - Enhanced date range picker with Easepick integration\n * Falls back to two native HTML5 date inputs if Easepick is unavailable\n * \n * Features:\n * - Dynamic CDN loading of Easepick\n * - Start and end date validation\n * - Configurable date formats and constraints\n * - Keyboard navigation and accessibility\n * - Form integration with FormBuilder\n * - Graceful fallback to native date inputs\n * \n * Example Usage:\n * ```javascript\n * const dateRangePicker = new DateRangePicker({\n * name: 'date_range',\n * startDate: '2023-01-01',\n * endDate: '2023-01-31',\n * format: 'YYYY-MM-DD',\n * min: '2020-01-01',\n * max: '2030-12-31',\n * placeholder: 'Select date range...'\n * });\n * ```\n */\n\nimport View from '@core/View.js';\n\nclass DateRangePicker extends View {\n constructor(options = {}) {\n const {\n name,\n startName,\n endName,\n fieldName,\n startDate = '',\n endDate = '',\n format = 'YYYY-MM-DD',\n displayFormat = 'MMM DD, YYYY',\n outputFormat = 'date', // 'date', 'epoch', 'iso'\n min = null,\n max = null,\n placeholder = 'Select date range...',\n startPlaceholder = 'Start date...',\n endPlaceholder = 'End date...',\n disabled = false,\n readonly = false,\n required = false,\n class: containerClass = '',\n inputClass = 'form-control',\n autoApply = true,\n inline = false,\n separator = ' - ',\n ...viewOptions\n } = options;\n\n super({\n tagName: 'div',\n className: `date-range-picker-view ${containerClass}`,\n ...viewOptions\n });\n\n // Configuration\n this.name = name;\n this.startName = startName;\n this.endName = endName;\n this.fieldName = fieldName;\n this.format = format;\n this.displayFormat = displayFormat;\n this.outputFormat = outputFormat;\n this.min = min;\n this.max = max;\n this.placeholder = placeholder;\n this.startPlaceholder = startPlaceholder;\n this.endPlaceholder = endPlaceholder;\n this.disabled = disabled;\n this.readonly = readonly;\n this.required = required;\n this.inputClass = inputClass;\n this.autoApply = autoApply;\n this.inline = inline;\n this.separator = separator;\n\n // State\n this.currentStartDate = startDate;\n this.currentEndDate = endDate;\n this.picker = null;\n this.useNative = false;\n this.easepickLoaded = false;\n\n // Check if Easepick is available\n this.checkEasepickAvailability();\n }\n\n /**\n * Check if Easepick is available and load if needed\n */\n async checkEasepickAvailability() {\n if (typeof window !== 'undefined' && window.easepick) {\n this.easepickLoaded = true;\n return true;\n }\n\n // Try to load Easepick from CDN\n try {\n await this.loadEasepick();\n this.easepickLoaded = true;\n return true;\n } catch (error) {\n console.warn('Easepick failed to load, falling back to native date inputs:', error);\n this.useNative = true;\n return false;\n }\n }\n\n /**\n * Dynamically load Easepick from CDN\n */\n async loadEasepick() {\n return new Promise((resolve, reject) => {\n // Check if already loaded\n if (window.easepick) {\n resolve();\n return;\n }\n\n // Load CSS first\n const css = document.createElement('link');\n css.rel = 'stylesheet';\n css.href = 'https://cdn.jsdelivr.net/npm/@easepick/bundle@1.2.1/dist/index.css';\n document.head.appendChild(css);\n\n // Load JavaScript\n const script = document.createElement('script');\n script.src = 'https://cdn.jsdelivr.net/npm/@easepick/bundle@1.2.1/dist/index.umd.min.js';\n script.onload = () => {\n if (window.easepick) {\n resolve();\n } else {\n reject(new Error('Easepick not available after loading'));\n }\n };\n script.onerror = () => reject(new Error('Failed to load Easepick script'));\n document.head.appendChild(script);\n });\n }\n\n /**\n * Render the date range picker component\n */\n async renderTemplate() {\n const inputId = this.getInputId();\n const displayValue = this.getDisplayValue();\n \n if (this.useNative) {\n // Render two separate date inputs for native fallback\n return this.renderNativeTemplate(inputId);\n }\n\n // Determine field names\n const startFieldName = this.startName || (this.name ? `${this.name}_start` : '');\n const endFieldName = this.endName || (this.name ? `${this.name}_end` : '');\n \n // Get formatted values for output\n const startValue = this.currentStartDate ? this.formatForOutput(this.currentStartDate) : '';\n const endValue = this.currentEndDate ? this.formatForOutput(this.currentEndDate) : '';\n\n return `\n <div class=\"date-range-picker-container\">\n <input \n type=\"text\"\n id=\"${inputId}\"\n ${this.name ? `name=\"${this.name}\"` : ''}\n class=\"${this.inputClass} date-range-picker-input${this.hasError() ? ' is-invalid' : ''}\"\n value=\"${this.escapeHtml(displayValue)}\"\n placeholder=\"${this.escapeHtml(this.placeholder)}\"\n ${this.disabled ? 'disabled' : ''}\n ${this.readonly ? 'readonly' : ''}\n ${this.required ? 'required' : ''}\n autocomplete=\"off\"\n data-change-action=\"range-changed\"\n style=\"background-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 16 16%22><path fill=%22%236c757d%22 fill-rule=%22evenodd%22 d=%22M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z%22/></svg>'); background-repeat: no-repeat; background-position: right 0.75rem center; background-size: 16px 12px; padding-right: 2.25rem; cursor: pointer;\"\n />\n \n <!-- Hidden inputs for form submission -->\n ${startFieldName ? `<input type=\"hidden\" name=\"${startFieldName}\" value=\"${this.escapeHtml(startValue)}\" />` : ''}\n ${endFieldName ? `<input type=\"hidden\" name=\"${endFieldName}\" value=\"${this.escapeHtml(endValue)}\" />` : ''}\n ${this.fieldName ? `<input type=\"hidden\" name=\"${this.fieldName}\" value=\"${this.escapeHtml(this.name || '')}\" />` : ''}\n \n <div class=\"date-range-picker-feedback\"></div>\n </div>\n `;\n }\n\n /**\n * Render native fallback template with two date inputs\n */\n renderNativeTemplate(inputId) {\n return `\n <div class=\"date-range-picker-container date-range-native\">\n <div class=\"row g-2\">\n <div class=\"col\">\n <input \n type=\"date\"\n id=\"${inputId}_start\"\n name=\"${this.name}_start\"\n class=\"${this.inputClass}${this.hasError() ? ' is-invalid' : ''}\"\n value=\"${this.escapeHtml(this.formatDate(this.currentStartDate, 'YYYY-MM-DD'))}\"\n placeholder=\"${this.escapeHtml(this.startPlaceholder)}\"\n ${this.min ? `min=\"${this.min}\"` : ''}\n ${this.max ? `max=\"${this.max}\"` : ''}\n ${this.disabled ? 'disabled' : ''}\n ${this.readonly ? 'readonly' : ''}\n ${this.required ? 'required' : ''}\n data-change-action=\"start-date-changed\"\n />\n </div>\n <div class=\"col-auto d-flex align-items-center\">\n <span class=\"text-muted\">${this.escapeHtml(this.separator.trim())}</span>\n </div>\n <div class=\"col\">\n <input \n type=\"date\"\n id=\"${inputId}_end\"\n name=\"${this.name}_end\"\n class=\"${this.inputClass}${this.hasError() ? ' is-invalid' : ''}\"\n value=\"${this.escapeHtml(this.formatDate(this.currentEndDate, 'YYYY-MM-DD'))}\"\n placeholder=\"${this.escapeHtml(this.endPlaceholder)}\"\n ${this.min ? `min=\"${this.min}\"` : ''}\n ${this.max ? `max=\"${this.max}\"` : ''}\n ${this.disabled ? 'disabled' : ''}\n ${this.readonly ? 'readonly' : ''}\n ${this.required ? 'required' : ''}\n data-change-action=\"end-date-changed\"\n />\n </div>\n </div>\n \n <!-- Hidden input for combined value -->\n <input type=\"hidden\" name=\"${this.name}\" value=\"${this.escapeHtml(this.getCombinedValue())}\" />\n ${this.fieldName ? `<input type=\"hidden\" name=\"${this.fieldName}\" value=\"${this.escapeHtml(this.name || '')}\" />` : ''}\n \n <div class=\"date-range-picker-feedback\"></div>\n </div>\n `;\n }\n\n /**\n * Initialize after render\n */\n async onAfterRender() {\n await super.onAfterRender();\n \n if (this.easepickLoaded && !this.useNative) {\n await this.initializeEasepick();\n } else {\n this.initializeNativeFallback();\n }\n }\n\n /**\n * Initialize Easepick date range picker\n */\n async initializeEasepick() {\n const input = this.getInputElement();\n if (!input || !window.easepick) return;\n\n try {\n const config = {\n element: input,\n css: [\n 'https://cdn.jsdelivr.net/npm/@easepick/bundle@1.2.1/dist/index.css',\n ],\n format: this.displayFormat,\n lang: 'en-US',\n autoApply: this.autoApply,\n inline: this.inline,\n readonly: this.readonly,\n zIndex: 9999,\n plugins: ['RangePlugin'],\n RangePlugin: {\n tooltip: true,\n locale: {\n one: 'day',\n other: 'days'\n }\n }\n };\n\n // Add date constraints\n if (this.min) {\n config.minDate = new Date(this.min);\n }\n if (this.max) {\n config.maxDate = new Date(this.max);\n }\n\n // Add event handlers\n config.setup = (picker) => {\n picker.on('select', (e) => {\n const { start, end } = e.detail;\n // Easepick returns DateTime objects, convert to local date strings\n const startDate = start ? this.normalizeDateFromPicker(start) : '';\n const endDate = end ? this.normalizeDateFromPicker(end) : '';\n this.handleRangeChange(startDate, endDate);\n });\n\n picker.on('clear', () => {\n this.handleRangeChange('', '');\n });\n\n picker.on('show', () => {\n this.emit('picker:show');\n });\n\n picker.on('hide', () => {\n this.emit('picker:hide');\n });\n };\n\n this.picker = new window.easepick.create(config);\n\n // Set initial value if provided\n if (this.currentStartDate && this.currentEndDate) {\n this.picker.setDateRange(this.currentStartDate, this.currentEndDate);\n }\n\n } catch (error) {\n console.error('Failed to initialize Easepick range picker:', error);\n this.useNative = true;\n await this.render(); // Re-render with native template\n this.initializeNativeFallback();\n }\n }\n\n /**\n * Initialize native HTML5 date inputs fallback\n */\n initializeNativeFallback() {\n // Native inputs are already set up in template\n // Just ensure proper constraint relationships\n this.updateConstraints();\n }\n\n // ========================================\n // Event Handlers\n // ========================================\n\n /**\n * Handle range change from Easepick\n */\n async onChangeRangeChanged(_action, _event, _element) {\n // This is handled by Easepick setup callback\n }\n\n /**\n * Handle start date change in native mode\n */\n async onChangeStartDateChanged(action, event, element) {\n const startDate = element.value;\n this.handleRangeChange(startDate, this.currentEndDate);\n this.updateConstraints();\n }\n\n /**\n * Handle end date change in native mode\n */\n async onChangeEndDateChanged(action, event, element) {\n const endDate = element.value;\n this.handleRangeChange(this.currentStartDate, endDate);\n this.updateConstraints();\n }\n\n /**\n * Handle date range change logic\n */\n handleRangeChange(startDate, endDate) {\n const oldStartDate = this.currentStartDate;\n const oldEndDate = this.currentEndDate;\n \n this.currentStartDate = startDate;\n this.currentEndDate = endDate;\n\n // Update hidden inputs\n this.updateHiddenInputs();\n\n // Emit change events\n if (oldStartDate !== startDate || oldEndDate !== endDate) {\n this.emit('change', {\n startDate,\n endDate,\n combined: this.getCombinedValue(),\n formatted: this.getDisplayValue(),\n oldStartDate,\n oldEndDate\n });\n \n this.emit('range:changed', {\n startDate,\n endDate,\n oldStartDate,\n oldEndDate\n });\n }\n }\n\n /**\n * Update constraints for native inputs\n */\n updateConstraints() {\n if (!this.useNative) return;\n\n const startInput = this.element?.querySelector(`[name=\"${this.name}_start\"]`);\n const endInput = this.element?.querySelector(`[name=\"${this.name}_end\"]`);\n\n if (startInput && endInput) {\n // End date should be >= start date\n if (this.currentStartDate) {\n endInput.min = this.currentStartDate;\n }\n \n // Start date should be <= end date\n if (this.currentEndDate) {\n startInput.max = this.currentEndDate;\n }\n }\n }\n\n // ========================================\n // Utility Methods\n // ========================================\n\n /**\n * Normalize date from Easepick DateTime object\n * Easepick DateTime objects may have timezone issues, so extract the date components directly\n */\n normalizeDateFromPicker(dateObj) {\n if (!dateObj) return '';\n \n // If it's an Easepick DateTime object, it has a toJSDate() method\n if (typeof dateObj.toJSDate === 'function') {\n const jsDate = dateObj.toJSDate();\n return this.formatDate(jsDate, this.format);\n }\n \n // If it has getFullYear/getMonth/getDate methods (like DateTime)\n if (typeof dateObj.getFullYear === 'function') {\n const year = dateObj.getFullYear();\n const month = String(dateObj.getMonth() + 1).padStart(2, '0');\n const day = String(dateObj.getDate()).padStart(2, '0');\n \n switch (this.format) {\n case 'YYYY-MM-DD':\n return `${year}-${month}-${day}`;\n case 'MM/DD/YYYY':\n return `${month}/${day}/${year}`;\n case 'DD/MM/YYYY':\n return `${day}/${month}/${year}`;\n default:\n return `${year}-${month}-${day}`;\n }\n }\n \n // Fallback to formatDate\n return this.formatDate(dateObj, this.format);\n }\n\n /**\n * Format date for different contexts\n */\n formatDate(date, format = this.format) {\n if (!date) return '';\n \n let year, month, day, d;\n \n // If date is a YYYY-MM-DD string, parse it manually to avoid timezone issues\n if (typeof date === 'string' && /^\\d{4}-\\d{2}-\\d{2}$/.test(date)) {\n const parts = date.split('-');\n year = parseInt(parts[0]);\n month = String(parseInt(parts[1])).padStart(2, '0');\n day = String(parseInt(parts[2])).padStart(2, '0');\n } else {\n // Handle Date objects or other string formats\n if (date instanceof Date) {\n d = date;\n } else {\n d = new Date(date);\n }\n \n if (isNaN(d.getTime())) return '';\n\n // Use getFullYear, getMonth, getDate (local time methods)\n year = d.getFullYear();\n month = String(d.getMonth() + 1).padStart(2, '0');\n day = String(d.getDate()).padStart(2, '0');\n }\n \n switch (format) {\n case 'YYYY-MM-DD':\n return `${year}-${month}-${day}`;\n case 'MM/DD/YYYY':\n return `${month}/${day}/${year}`;\n case 'DD/MM/YYYY':\n return `${day}/${month}/${year}`;\n case 'MMM DD, YYYY': {\n const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\n 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\n const monthIndex = parseInt(month) - 1;\n return `${monthNames[monthIndex]} ${day}, ${year}`;\n }\n default:\n return `${year}-${month}-${day}`;\n }\n }\n\n /**\n * Format date for output based on outputFormat setting\n */\n formatForOutput(date) {\n if (!date) return '';\n \n // If date is already a string in YYYY-MM-DD format, don't re-parse it\n // to avoid timezone issues\n if (typeof date === 'string' && /^\\d{4}-\\d{2}-\\d{2}$/.test(date)) {\n switch (this.outputFormat) {\n case 'epoch':\n // For epoch, we need to parse but use local midnight\n const parts = date.split('-');\n const d = new Date(parseInt(parts[0]), parseInt(parts[1]) - 1, parseInt(parts[2]));\n return Math.floor(d.getTime() / 1000).toString();\n case 'iso':\n return new Date(date + 'T00:00:00').toISOString();\n case 'date':\n default:\n return date; // Already in the correct format\n }\n }\n \n // For Date objects or other formats, parse and convert\n const d = new Date(date);\n if (isNaN(d.getTime())) return '';\n\n switch (this.outputFormat) {\n case 'epoch':\n return Math.floor(d.getTime() / 1000).toString();\n case 'iso':\n return d.toISOString();\n case 'date':\n default:\n return this.formatDate(date, this.format);\n }\n }\n\n /**\n * Get display value for the input\n */\n getDisplayValue() {\n if (!this.currentStartDate && !this.currentEndDate) return '';\n \n const startFormatted = this.currentStartDate ? \n this.formatDate(this.currentStartDate, this.displayFormat) : '';\n const endFormatted = this.currentEndDate ? \n this.formatDate(this.currentEndDate, this.displayFormat) : '';\n\n if (startFormatted && endFormatted) {\n return `${startFormatted}${this.separator}${endFormatted}`;\n } else if (startFormatted) {\n return startFormatted;\n } else if (endFormatted) {\n return endFormatted;\n }\n \n return '';\n }\n\n /**\n * Get combined value for form submission\n */\n getCombinedValue() {\n if (!this.currentStartDate && !this.currentEndDate) return '';\n \n return JSON.stringify({\n start: this.currentStartDate,\n end: this.currentEndDate\n });\n }\n\n /**\n * Get unique input ID\n */\n getInputId() {\n return this.name ? `daterange_${this.name}_${Date.now()}` : `daterange_${Date.now()}`;\n }\n\n /**\n * Get main input element\n */\n getInputElement() {\n return this.element?.querySelector('input[type=\"text\"], input[name=\"' + this.name + '\"]');\n }\n\n /**\n * Update hidden inputs for form submission\n */\n updateHiddenInputs() {\n const startFieldName = this.startName || (this.name ? `${this.name}_start` : '');\n const endFieldName = this.endName || (this.name ? `${this.name}_end` : '');\n \n const startInput = startFieldName ? this.element?.querySelector(`[name=\"${startFieldName}\"]`) : null;\n const endInput = endFieldName ? this.element?.querySelector(`[name=\"${endFieldName}\"]`) : null;\n const combinedInput = this.name ? this.element?.querySelector(`[name=\"${this.name}\"]`) : null;\n const fieldNameInput = this.fieldName ? this.element?.querySelector(`[name=\"${this.fieldName}\"]`) : null;\n\n const startValue = this.currentStartDate ? this.formatForOutput(this.currentStartDate) : '';\n const endValue = this.currentEndDate ? this.formatForOutput(this.currentEndDate) : '';\n \n if (startInput) startInput.value = startValue;\n if (endInput) endInput.value = endValue;\n if (combinedInput) combinedInput.value = this.getDisplayValue();\n if (fieldNameInput) fieldNameInput.value = this.name || '';\n }\n\n /**\n * Check if field has error\n */\n hasError() {\n // Basic validation: end date should be after start date\n if (this.currentStartDate && this.currentEndDate) {\n return new Date(this.currentEndDate) < new Date(this.currentStartDate);\n }\n return false;\n }\n\n /**\n * Escape HTML to prevent XSS\n */\n escapeHtml(str) {\n if (str == null) return '';\n const div = document.createElement('div');\n div.textContent = String(str);\n return div.innerHTML;\n }\n\n // ========================================\n // Public API Methods\n // ========================================\n\n /**\n * Set the date range values\n */\n setRange(startDate, endDate) {\n this.currentStartDate = startDate;\n this.currentEndDate = endDate;\n \n if (this.picker && this.easepickLoaded) {\n this.picker.setDateRange(startDate || null, endDate || null);\n } else if (this.useNative) {\n const startInput = this.element?.querySelector(`[name=\"${this.name}_start\"]`);\n const endInput = this.element?.querySelector(`[name=\"${this.name}_end\"]`);\n \n if (startInput) startInput.value = this.formatDate(startDate, 'YYYY-MM-DD');\n if (endInput) endInput.value = this.formatDate(endDate, 'YYYY-MM-DD');\n } else {\n const input = this.getInputElement();\n if (input) {\n input.value = this.getDisplayValue();\n }\n }\n \n this.updateHiddenInputs();\n this.emit('range:set', { startDate, endDate });\n }\n\n /**\n * Get the current date range\n */\n getRange() {\n return {\n start: this.currentStartDate,\n end: this.currentEndDate,\n combined: this.getCombinedValue()\n };\n }\n\n /**\n * Clear the date range\n */\n clear() {\n this.setRange('', '');\n }\n\n /**\n * Set start date only\n */\n setStartDate(startDate) {\n this.setRange(startDate, this.currentEndDate);\n }\n\n /**\n * Set end date only\n */\n setEndDate(endDate) {\n this.setRange(this.currentStartDate, endDate);\n }\n\n /**\n * Get start date\n */\n getStartDate() {\n return this.currentStartDate;\n }\n\n /**\n * Get end date\n */\n getEndDate() {\n return this.currentEndDate;\n }\n\n /**\n * Enable/disable the picker\n */\n setEnabled(enabled) {\n this.disabled = !enabled;\n const inputs = this.element?.querySelectorAll('input');\n inputs?.forEach(input => {\n input.disabled = this.disabled;\n });\n }\n\n /**\n * Set readonly state\n */\n setReadonly(readonly) {\n this.readonly = readonly;\n const inputs = this.element?.querySelectorAll('input:not([type=\"hidden\"])');\n inputs?.forEach(input => {\n input.readonly = readonly;\n });\n }\n\n /**\n * Focus the input\n */\n focus() {\n const input = this.getInputElement();\n if (input) {\n input.focus();\n }\n }\n\n /**\n * Show the picker (if using Easepick)\n */\n show() {\n if (this.picker && this.easepickLoaded) {\n this.picker.show();\n }\n }\n\n /**\n * Hide the picker (if using Easepick)\n */\n hide() {\n if (this.picker && this.easepickLoaded) {\n this.picker.hide();\n }\n }\n\n // ========================================\n // FormBuilder Integration\n // ========================================\n\n /**\n * Get form value (for FormBuilder integration)\n */\n getFormValue() {\n return this.getRange();\n }\n\n /**\n * Set form value (for FormBuilder integration)\n */\n async setFormValue(value) {\n if (typeof value === 'string') {\n try {\n const parsed = JSON.parse(value);\n this.setRange(parsed.start, parsed.end);\n } catch {\n // If not JSON, treat as start date only\n this.setRange(value, '');\n }\n } else if (value && typeof value === 'object') {\n this.setRange(value.start || '', value.end || '');\n }\n }\n\n // ========================================\n // Lifecycle Methods\n // ========================================\n\n /**\n * Cleanup when component is destroyed\n */\n async onBeforeDestroy() {\n if (this.picker && this.easepickLoaded) {\n try {\n this.picker.destroy();\n } catch (error) {\n console.warn('Error destroying Easepick range picker instance:', error);\n }\n }\n \n this.picker = null;\n await super.onBeforeDestroy();\n }\n\n /**\n * Static factory method\n */\n static create(options = {}) {\n return new DateRangePicker(options);\n }\n}\n\nexport default DateRangePicker;","/**\n * ComboInput - Editable select/autocomplete component for MOJO framework\n * Combines a text input with a dropdown of suggestions\n * Users can either select from the dropdown or type custom values\n *\n * Features:\n * - Autocomplete with filtering\n * - Keyboard navigation (Arrow keys, Enter, Escape)\n * - Custom value entry\n * - Bootstrap 5 styling\n * - Form integration\n * - Optional metadata support (display label but store value)\n *\n * Example Usage:\n * ```javascript\n * const comboInput = new ComboInput({\n * name: 'field_name',\n * value: 'level',\n * placeholder: 'Select or enter field name...',\n * options: [\n * { value: 'level', label: 'Level (error, warning, info)', meta: { type: 'str' } },\n * { value: 'source_ip', label: 'Source IP Address', meta: { type: 'str' } }\n * ],\n * allowCustom: true,\n * showDescription: true\n * });\n * ```\n */\n\nimport View from '@core/View.js';\n\nclass ComboInput extends View {\n constructor(options = {}) {\n const {\n name,\n value = '',\n placeholder = 'Select or type...',\n options: optionsList = [],\n allowCustom = true,\n showDescription = true,\n minChars = 0, // Minimum characters before showing suggestions\n maxSuggestions = 10,\n disabled = false,\n readonly = false,\n required = false,\n class: containerClass = '',\n inputClass = 'form-control',\n onSelect = null, // Callback when option is selected\n onChange = null, // Callback when value changes\n ...viewOptions\n } = options;\n\n super({\n tagName: 'div',\n className: `combo-input ${containerClass}`,\n ...viewOptions\n });\n\n // Configuration\n this.name = name;\n this.placeholder = placeholder;\n this.options = this.normalizeOptions(optionsList);\n this.allowCustom = allowCustom;\n this.showDescription = showDescription;\n this.minChars = minChars;\n this.maxSuggestions = maxSuggestions;\n this.disabled = disabled;\n this.readonly = readonly;\n this.required = required;\n this.inputClass = inputClass;\n this.onSelectCallback = onSelect;\n this.onChangeCallback = onChange;\n\n // State\n this.currentValue = value;\n this.inputValue = this.getDisplayValue(value);\n this.filteredOptions = [];\n this.highlightedIndex = -1;\n this.isOpen = false;\n this.selectedOption = this.findOptionByValue(value);\n }\n\n /**\n * Normalize options to consistent format\n */\n normalizeOptions(options) {\n if (!Array.isArray(options)) return [];\n\n return options.map(opt => {\n if (typeof opt === 'string') {\n return { value: opt, label: opt };\n } else if (typeof opt === 'object' && opt.value !== undefined) {\n return {\n value: opt.value,\n label: opt.label || String(opt.value),\n description: opt.description || opt.label || '',\n meta: opt.meta || {}\n };\n }\n return null;\n }).filter(opt => opt !== null);\n }\n\n /**\n * Find option by value\n */\n findOptionByValue(value) {\n return this.options.find(opt => opt.value === value) || null;\n }\n\n /**\n * Get display value for a given value\n */\n getDisplayValue(value) {\n const option = this.findOptionByValue(value);\n return option ? option.label : value;\n }\n\n /**\n * Render the combo input component\n */\n async renderTemplate() {\n return `\n <div class=\"combo-input-container position-relative\">\n <div class=\"input-wrapper position-relative\">\n ${this.renderInput()}\n ${this.renderDropdownToggle()}\n </div>\n ${this.renderHiddenInput()}\n ${this.renderDropdown()}\n </div>\n `;\n }\n\n /**\n * Render the input field\n */\n renderInput() {\n return `\n <input type=\"text\"\n class=\"${this.inputClass} combo-input-field\"\n placeholder=\"${this.escapeHtml(this.placeholder)}\"\n value=\"${this.escapeHtml(this.inputValue)}\"\n ${this.disabled ? 'disabled' : ''}\n ${this.readonly ? 'readonly' : ''}\n ${this.required ? 'required' : ''}\n data-change-action=\"input-change\"\n data-action=\"input-keydown\"\n autocomplete=\"off\"\n role=\"combobox\"\n aria-expanded=\"${this.isOpen}\"\n aria-autocomplete=\"list\"\n aria-controls=\"combo-dropdown-${this.cid}\">\n `;\n }\n\n /**\n * Render dropdown toggle button\n */\n renderDropdownToggle() {\n if (this.readonly || this.disabled) return '';\n\n return `\n <button type=\"button\"\n class=\"btn btn-sm combo-toggle position-absolute top-50 end-0 translate-middle-y border-0\"\n data-action=\"toggle-dropdown\"\n tabindex=\"-1\"\n aria-label=\"Toggle dropdown\"\n style=\"padding: 0.25rem 0.5rem;\">\n <i class=\"bi bi-chevron-down\"></i>\n </button>\n `;\n }\n\n /**\n * Render hidden input for form submission\n */\n renderHiddenInput() {\n if (!this.name) return '';\n\n return `\n <input type=\"hidden\"\n name=\"${this.name}\"\n value=\"${this.escapeHtml(this.currentValue)}\"\n class=\"combo-input-hidden\">\n `;\n }\n\n /**\n * Render dropdown menu\n */\n renderDropdown() {\n return `\n <div id=\"combo-dropdown-${this.cid}\"\n class=\"combo-dropdown dropdown-menu position-absolute w-100 ${this.isOpen ? 'show' : ''}\"\n role=\"listbox\"\n style=\"max-height: 300px; overflow-y: auto; z-index: 1050;\">\n ${this.renderDropdownContent()}\n </div>\n `;\n }\n\n /**\n * Render dropdown content based on filtered options\n */\n renderDropdownContent() {\n if (this.filteredOptions.length === 0) {\n return this.renderNoResults();\n }\n\n return this.filteredOptions\n .slice(0, this.maxSuggestions)\n .map((option, index) => this.renderOption(option, index))\n .join('');\n }\n\n /**\n * Render a single option\n */\n renderOption(option, index) {\n const isHighlighted = index === this.highlightedIndex;\n const isSelected = option.value === this.currentValue;\n\n return `\n <div class=\"dropdown-item combo-option ${isHighlighted ? 'active' : ''} ${isSelected ? 'selected' : ''}\"\n data-action=\"select-option\"\n data-option-index=\"${index}\"\n role=\"option\"\n aria-selected=\"${isSelected}\"\n style=\"cursor: pointer;\">\n <div class=\"d-flex justify-content-between align-items-start\">\n <div class=\"flex-grow-1\">\n <div class=\"combo-option-label fw-semibold\">${this.highlightMatch(option.label)}</div>\n ${this.showDescription && option.description ? `\n <div class=\"combo-option-description small text-muted\">${this.escapeHtml(option.description)}</div>\n ` : ''}\n </div>\n ${isSelected ? '<i class=\"bi bi-check text-primary ms-2\"></i>' : ''}\n </div>\n </div>\n `;\n }\n\n /**\n * Render no results message\n */\n renderNoResults() {\n if (this.allowCustom && this.inputValue.length >= this.minChars) {\n return `\n <div class=\"dropdown-item-text text-muted small\">\n <i class=\"bi bi-info-circle me-1\"></i>\n ${this.inputValue ? 'No matches found. Press Enter to use custom value.' : 'Start typing to see suggestions...'}\n </div>\n `;\n }\n\n return `\n <div class=\"dropdown-item-text text-muted small\">\n <i class=\"bi bi-search me-1\"></i>\n No matching options found.\n </div>\n `;\n }\n\n /**\n * Highlight matching text in option label\n */\n highlightMatch(label) {\n if (!this.inputValue) return this.escapeHtml(label);\n\n const escaped = this.escapeHtml(label);\n const pattern = new RegExp(`(${this.escapeRegex(this.inputValue)})`, 'gi');\n return escaped.replace(pattern, '<mark class=\"bg-warning bg-opacity-25\">$1</mark>');\n }\n\n /**\n * Handle component initialization after render\n */\n async onAfterRender() {\n await super.onAfterRender();\n this.updateFilteredOptions();\n\n // Close dropdown when clicking outside\n this.handleOutsideClick = (event) => {\n if (this.element && !this.element.contains(event.target)) {\n this.closeDropdown();\n }\n };\n\n document.addEventListener('click', this.handleOutsideClick);\n }\n\n // ========================================\n // EventDelegate Action Handlers\n // ========================================\n\n /**\n * Handle input changes (typing)\n */\n async onChangeInputChange(event, element) {\n this.inputValue = element.value;\n this.updateFilteredOptions();\n\n if (this.inputValue.length >= this.minChars) {\n this.openDropdown();\n } else {\n this.closeDropdown();\n }\n\n // Reset highlighted index when filtering\n this.highlightedIndex = -1;\n await this.updateDropdownDisplay();\n }\n\n /**\n * Handle input keydown for navigation\n */\n async onActionInputKeydown(event, _element) {\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n if (!this.isOpen) {\n this.openDropdown();\n } else {\n this.highlightNext();\n }\n await this.updateDropdownDisplay();\n break;\n\n case 'ArrowUp':\n event.preventDefault();\n if (this.isOpen) {\n this.highlightPrevious();\n await this.updateDropdownDisplay();\n }\n break;\n\n case 'Enter':\n event.preventDefault();\n if (this.isOpen && this.highlightedIndex >= 0) {\n await this.selectHighlightedOption();\n } else if (this.allowCustom && this.inputValue) {\n await this.selectCustomValue(this.inputValue);\n }\n break;\n\n case 'Escape':\n event.preventDefault();\n this.closeDropdown();\n // Restore previous value\n const input = this.element.querySelector('.combo-input-field');\n if (input) {\n input.value = this.getDisplayValue(this.currentValue);\n this.inputValue = input.value;\n }\n break;\n\n case 'Tab':\n // Allow tab to close dropdown and move focus\n if (this.isOpen) {\n this.closeDropdown();\n }\n break;\n }\n }\n\n /**\n * Handle toggle dropdown button click\n */\n async onActionToggleDropdown(event, _element) {\n event.preventDefault();\n event.stopPropagation();\n\n if (this.isOpen) {\n this.closeDropdown();\n } else {\n // Show all options when toggle is clicked\n this.inputValue = '';\n const input = this.element.querySelector('.combo-input-field');\n if (input) {\n input.value = '';\n input.focus();\n }\n this.updateFilteredOptions();\n this.openDropdown();\n await this.updateDropdownDisplay();\n }\n }\n\n /**\n * Handle option selection\n */\n async onActionSelectOption(event, element) {\n event.preventDefault();\n event.stopPropagation();\n\n const index = parseInt(element.getAttribute('data-option-index'));\n if (index >= 0 && index < this.filteredOptions.length) {\n await this.selectOption(this.filteredOptions[index]);\n }\n }\n\n // ========================================\n // Dropdown Management\n // ========================================\n\n /**\n * Open dropdown\n */\n openDropdown() {\n this.isOpen = true;\n const dropdown = this.element?.querySelector('.combo-dropdown');\n if (dropdown) {\n dropdown.classList.add('show');\n }\n\n const input = this.element?.querySelector('.combo-input-field');\n if (input) {\n input.setAttribute('aria-expanded', 'true');\n }\n }\n\n /**\n * Close dropdown\n */\n closeDropdown() {\n this.isOpen = false;\n this.highlightedIndex = -1;\n\n const dropdown = this.element?.querySelector('.combo-dropdown');\n if (dropdown) {\n dropdown.classList.remove('show');\n }\n\n const input = this.element?.querySelector('.combo-input-field');\n if (input) {\n input.setAttribute('aria-expanded', 'false');\n }\n }\n\n /**\n * Update filtered options based on input\n */\n updateFilteredOptions() {\n const query = this.inputValue.toLowerCase().trim();\n\n if (!query) {\n this.filteredOptions = [...this.options];\n return;\n }\n\n this.filteredOptions = this.options.filter(option => {\n const labelMatch = option.label.toLowerCase().includes(query);\n const valueMatch = String(option.value).toLowerCase().includes(query);\n const descMatch = option.description?.toLowerCase().includes(query);\n return labelMatch || valueMatch || descMatch;\n });\n\n // Sort by relevance (exact matches first)\n this.filteredOptions.sort((a, b) => {\n const aLabelExact = a.label.toLowerCase() === query;\n const bLabelExact = b.label.toLowerCase() === query;\n if (aLabelExact && !bLabelExact) return -1;\n if (!aLabelExact && bLabelExact) return 1;\n\n const aLabelStarts = a.label.toLowerCase().startsWith(query);\n const bLabelStarts = b.label.toLowerCase().startsWith(query);\n if (aLabelStarts && !bLabelStarts) return -1;\n if (!aLabelStarts && bLabelStarts) return 1;\n\n return 0;\n });\n }\n\n /**\n * Update dropdown display\n */\n async updateDropdownDisplay() {\n const dropdown = this.element?.querySelector('.combo-dropdown');\n if (!dropdown) return;\n\n dropdown.innerHTML = this.renderDropdownContent();\n\n // Scroll highlighted option into view\n if (this.highlightedIndex >= 0) {\n const highlightedElement = dropdown.querySelector('.combo-option.active');\n if (highlightedElement) {\n highlightedElement.scrollIntoView({ block: 'nearest' });\n }\n }\n }\n\n /**\n * Highlight next option\n */\n highlightNext() {\n if (this.filteredOptions.length === 0) return;\n\n this.highlightedIndex = (this.highlightedIndex + 1) % Math.min(this.filteredOptions.length, this.maxSuggestions);\n }\n\n /**\n * Highlight previous option\n */\n highlightPrevious() {\n if (this.filteredOptions.length === 0) return;\n\n this.highlightedIndex = this.highlightedIndex <= 0\n ? Math.min(this.filteredOptions.length, this.maxSuggestions) - 1\n : this.highlightedIndex - 1;\n }\n\n /**\n * Select highlighted option\n */\n async selectHighlightedOption() {\n if (this.highlightedIndex >= 0 && this.highlightedIndex < this.filteredOptions.length) {\n await this.selectOption(this.filteredOptions[this.highlightedIndex]);\n }\n }\n\n /**\n * Select an option\n */\n async selectOption(option) {\n this.currentValue = option.value;\n this.inputValue = option.label;\n this.selectedOption = option;\n\n // Update input display\n const input = this.element?.querySelector('.combo-input-field');\n if (input) {\n input.value = option.label;\n }\n\n // Update hidden input\n const hiddenInput = this.element?.querySelector('.combo-input-hidden');\n if (hiddenInput) {\n hiddenInput.value = option.value;\n }\n\n this.closeDropdown();\n\n // Emit events\n this.emit('select', { option, value: option.value, meta: option.meta });\n this.emit('change', { value: option.value, option, meta: option.meta });\n\n // Call callbacks\n if (typeof this.onSelectCallback === 'function') {\n this.onSelectCallback(option);\n }\n if (typeof this.onChangeCallback === 'function') {\n this.onChangeCallback(option.value);\n }\n }\n\n /**\n * Select custom value (not in options)\n */\n async selectCustomValue(value) {\n if (!this.allowCustom) return;\n\n this.currentValue = value;\n this.inputValue = value;\n this.selectedOption = null;\n\n // Update hidden input\n const hiddenInput = this.element?.querySelector('.combo-input-hidden');\n if (hiddenInput) {\n hiddenInput.value = value;\n }\n\n this.closeDropdown();\n\n // Emit events\n this.emit('custom', { value });\n this.emit('change', { value, custom: true });\n\n // Call callback\n if (typeof this.onChangeCallback === 'function') {\n this.onChangeCallback(value);\n }\n }\n\n // ========================================\n // Public API Methods\n // ========================================\n\n /**\n * Get current value\n */\n getValue() {\n return this.currentValue;\n }\n\n /**\n * Set value programmatically\n */\n async setValue(value) {\n this.currentValue = value;\n this.selectedOption = this.findOptionByValue(value);\n this.inputValue = this.getDisplayValue(value);\n\n const input = this.element?.querySelector('.combo-input-field');\n if (input) {\n input.value = this.inputValue;\n }\n\n const hiddenInput = this.element?.querySelector('.combo-input-hidden');\n if (hiddenInput) {\n hiddenInput.value = value;\n }\n\n this.updateFilteredOptions();\n }\n\n /**\n * Get selected option with metadata\n */\n getSelectedOption() {\n return this.selectedOption;\n }\n\n /**\n * Update options\n */\n async setOptions(options) {\n this.options = this.normalizeOptions(options);\n this.updateFilteredOptions();\n\n if (this.isOpen) {\n await this.updateDropdownDisplay();\n }\n }\n\n /**\n * Enable/disable the component\n */\n setEnabled(enabled) {\n this.disabled = !enabled;\n\n const input = this.element?.querySelector('.combo-input-field');\n if (input) {\n input.disabled = this.disabled;\n }\n\n const toggle = this.element?.querySelector('.combo-toggle');\n if (toggle) {\n toggle.disabled = this.disabled;\n }\n }\n\n /**\n * Set readonly state\n */\n setReadonly(readonly) {\n this.readonly = readonly;\n\n const input = this.element?.querySelector('.combo-input-field');\n if (input) {\n if (readonly) {\n input.setAttribute('readonly', '');\n } else {\n input.removeAttribute('readonly');\n }\n }\n }\n\n /**\n * Focus the input\n */\n focus() {\n const input = this.element?.querySelector('.combo-input-field');\n if (input) {\n input.focus();\n }\n }\n\n /**\n * Clear the input\n */\n async clear() {\n await this.setValue('');\n this.inputValue = '';\n\n const input = this.element?.querySelector('.combo-input-field');\n if (input) {\n input.value = '';\n }\n\n this.emit('clear');\n }\n\n // ========================================\n // Form Integration\n // ========================================\n\n /**\n * Get form value (for FormView integration)\n */\n getFormValue() {\n // If allowCustom is enabled and user has typed a value that hasn't been committed,\n // return the typed value instead of the last committed value\n if (this.allowCustom && this.inputValue && this.inputValue !== this.getDisplayValue(this.currentValue)) {\n return this.inputValue;\n }\n return this.currentValue;\n }\n\n /**\n * Set form value (for FormView integration)\n */\n async setFormValue(value) {\n await this.setValue(value);\n }\n\n // ========================================\n // Utility Methods\n // ========================================\n\n /**\n * Escape HTML to prevent XSS\n */\n escapeHtml(str) {\n if (str == null) return '';\n const div = document.createElement('div');\n div.textContent = String(str);\n return div.innerHTML;\n }\n\n /**\n * Escape regex special characters\n */\n escapeRegex(str) {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n }\n\n /**\n * Cleanup on destroy\n */\n async onBeforeDestroy() {\n if (this.handleOutsideClick) {\n document.removeEventListener('click', this.handleOutsideClick);\n }\n await super.onBeforeDestroy();\n }\n\n /**\n * Static factory method\n */\n static create(options = {}) {\n return new ComboInput(options);\n }\n}\n\nexport default ComboInput;\n","/**\n * FormView - Complete form component for MOJO framework\n * Uses FormBuilder for HTML generation and EventDelegate for event handling\n * Handles form lifecycle, validation, data management, and component integration\n */\n\nimport View from '@core/View.js';\nimport FormBuilder from './FormBuilder.js';\nimport applyFileDropMixin from '@core/mixins/FileDropMixin.js';\nimport MOJOUtils from '@core/utils/MOJOUtils.js';\nimport { FormPlugins } from '@core/forms/FormPlugins.js';\n\nimport { TagInput, CollectionSelect, CollectionMultiSelect, DatePicker, DateRangePicker, ComboInput } from './inputs/index.js';\n\nclass FormView extends View {\n constructor(options = {}) {\n const {\n formConfig = options.config,\n fields,\n model = null,\n data = {},\n defaults = null,\n errors = {},\n fileHandling = 'base64', // 'base64' | 'multipart'\n autosaveModelField = false, // Auto-save model on field changes\n ...viewOptions\n } = options;\n\n super({\n tagName: 'div',\n className: 'form-view',\n ...viewOptions\n });\n\n // Notify plugins this FormView is initializing\n FormPlugins.onFormViewInit?.(this);\n\n // Store data sources\n this.model = model;\n this.defaults = defaults || data;\n this._originalData = data;\n this.errors = errors;\n this.loading = false;\n this.fileHandling = fileHandling;\n this.autosaveModelField = autosaveModelField;\n this.customComponents = new Map();\n this.fieldStatusManagers = new Map(); // Track field status managers\n this.saveTimeouts = new Map(); // Debouncing timeouts for autosave\n this.pendingSaveFields = new Map(); // Track fields pending save (for batching)\n this.batchSaveTimeout = null; // Global timeout for batch saving\n this.isSaving = false; // Prevent save loops\n\n // Prepare combined data for FormBuilder\n this.data = this.prepareFormData();\n\n // Form configuration\n this.formConfig = formConfig || { fields: fields || [] };\n this.formBuilder = new FormBuilder({\n ...this.getFormConfig(),\n data: this.data, // Pass data so field.value defaults work\n errors\n });\n }\n\n /**\n * Prepare form data by combining defaults, model, and data in priority order\n * Priority: data > model > defaults\n * @returns {Object} Combined data object for FormBuilder\n */\n prepareFormData() {\n const formData = { ...this.defaults };\n\n // Add model data if available\n if (this.model) {\n if (this.model.attributes && typeof this.model.attributes === 'object') {\n Object.assign(formData, this.model.attributes);\n } else if (typeof this.model.toJSON === 'function') {\n const modelData = this.model.toJSON();\n Object.assign(formData, modelData);\n } else if (typeof this.model === 'object' && this.model.constructor === Object) {\n Object.assign(formData, this.model);\n }\n }\n\n // Original data takes highest priority\n if (this._originalData) {\n Object.assign(formData, this._originalData);\n }\n\n return formData;\n }\n\n getFormConfig() {\n const config = { ...this.formConfig };\n const app = this.getApp();\n\n // Handle case where fields might not be defined\n if (this.formConfig.fields && Array.isArray(this.formConfig.fields)) {\n config.fields = this.formConfig.fields.filter(field => {\n if (!field.permissions) return true;\n return app.activeUser?.hasPermission(field.permissions);\n });\n } else {\n config.fields = [];\n }\n\n return config;\n }\n\n /**\n * Use FormBuilder for template generation\n */\n async renderTemplate() {\n return this.formBuilder.buildFormHTML();\n }\n\n /**\n * Called after form is rendered to populate values and initialize\n */\n async onAfterRender() {\n await super.onAfterRender();\n\n this.data = this.prepareFormData();\n // Populate form with current data\n this.populateFormValues();\n\n // Initialize form components\n this.initializeFormComponents();\n\n // Add generic change handlers for all form inputs\n this.initializeChangeHandlers();\n\n // Prevent form submission on Enter key\n const form = this.getFormElement();\n if (form) {\n form.addEventListener('submit', (e) => {\n e.preventDefault();\n return false;\n });\n }\n\n // Allow plugins to run after the form renders and initializes\n FormPlugins.onFormViewAfterRender?.(this);\n }\n\n /**\n * Populate all form fields with current data values\n */\n populateFormValues() {\n if (!this.element || !this.formConfig?.fields) return;\n\n // Disable autosave during form population\n this._isPopulating = true;\n\n try {\n this.formConfig.fields.forEach(field => {\n if (field.type === 'group' && field.fields) {\n // Handle group fields\n field.fields.forEach(groupField => {\n this.populateFieldValue(groupField);\n });\n } else {\n this.populateFieldValue(field);\n }\n });\n } finally {\n // Always re-enable autosave\n this._isPopulating = false;\n }\n }\n\n /**\n * Populate a single field with its value from data\n */\n populateFieldValue(fieldConfig) {\n if (!fieldConfig.name || !this.element) return;\n\n const fieldElement = this.element.querySelector(`[name=\"${fieldConfig.name}\"]`);\n if (!fieldElement) return;\n\n // Use MOJOUtils to handle nested properties like 'permissions.manage_users'\n const value = MOJOUtils.getContextData(this.data, fieldConfig.name);\n\n // Only set value if we have actual data - don't overwrite field defaults with undefined\n if (value !== undefined && value !== null) {\n this.setFieldValue(fieldElement, fieldConfig, value);\n }\n }\n\n /**\n * Initialize form components after rendering\n */\n initializeFormComponents() {\n this.initializeImageFields();\n this.initializeCustomComponents();\n this.initializeTagInputs();\n this.initializeCollectionSelects();\n this.initializeCollectionMultiSelects();\n this.initializeDatePickers();\n this.initializeDateRangePickers();\n this.initializePasswordFields();\n }\n\n\n\n /**\n * Initialize image fields with FileDropMixin\n */\n initializeImageFields() {\n const imageFields = this.element.querySelectorAll('.image-drop-zone.droppable');\n\n if (imageFields.length > 0) {\n // Enable file drop functionality (mixin already applied at module level)\n this.enableFileDrop({\n acceptedTypes: ['image/*'],\n maxFileSize: 10 * 1024 * 1024, // 10MB\n multiple: false,\n dropZoneSelector: '.image-drop-zone.droppable',\n visualFeedback: true,\n dragOverClass: 'drag-over',\n dragActiveClass: 'drag-active'\n });\n }\n }\n\n /**\n * Initialize custom components (tags, collection selects, enhanced date pickers, etc.)\n */\n initializeCustomComponents() {\n // Initialize enhanced input components\n this.initializeTagInputs();\n this.initializeCollectionSelects();\n this.initializeCollectionMultiSelects();\n this.initializeDatePickers();\n this.initializeDateRangePickers();\n this.initializeComboInputs();\n\n // Give plugins a chance to initialize fields (autocomplete, masks, etc.)\n try {\n const visitFields = (fields = []) => {\n fields.forEach(f => {\n if (f && f.type === 'group' && Array.isArray(f.fields)) {\n visitFields(f.fields);\n } else if (f && f.name) {\n const el = this.element.querySelector(`[name=\"${f.name}\"], #${f.id || f.name}`);\n if (el) {\n FormPlugins.onFieldInit?.(this, el, f);\n }\n }\n });\n };\n visitFields(this.formConfig?.fields || []);\n } catch (err) {\n console.warn('FormPlugins.onFieldInit error:', err);\n }\n\n // Find containers for other custom components\n const componentContainers = this.element.querySelectorAll('[data-component]');\n\n componentContainers.forEach(container => {\n const componentType = container.getAttribute('data-component');\n const fieldName = container.getAttribute('data-field');\n\n if (componentType && fieldName) {\n\n }\n });\n }\n\n /**\n * Initialize generic change handlers for all form inputs\n */\n initializeChangeHandlers() {\n if (!this.element) return;\n\n // Add change listeners to all form inputs that don't already have specific handlers\n const inputs = this.element.querySelectorAll('input:not([data-action]), select:not([data-action]), textarea:not([data-action])');\n\n console.log('FormView: initializeChangeHandlers - found', inputs.length, 'inputs');\n\n inputs.forEach(input => {\n console.log('FormView: Processing input:', input.type, input.name, input.getAttribute('data-change-action'));\n // Skip inputs that already have specific handlers or are handled by custom components\n if (input.hasAttribute('data-component') || input.classList.contains('form-check-input')) {\n return;\n }\n\n // Add change event listener\n input.addEventListener('change', (event) => {\n // Skip autosave during form population\n if (this._isPopulating) return;\n\n const fieldName = input.name;\n if (fieldName) {\n let value = input.value;\n\n // Handle different input types\n if (input.type === 'checkbox') {\n value = input.checked;\n } else if (input.type === 'radio') {\n // Only process if this radio is checked\n if (!input.checked) return;\n } else if (input.multiple && input.selectedOptions) {\n // Handle multi-select\n value = Array.from(input.selectedOptions).map(opt => opt.value);\n } else if (input.type === 'file') {\n // Handle file inputs (including images)\n const changeAction = input.getAttribute('data-change-action');\n if (changeAction === 'image-selected') {\n this.onChangeImageSelected(event, input);\n return; // Don't call handleFieldChange for images\n } else if (changeAction === 'file-selected') {\n this.onChangeFileSelected(event, input);\n return; // Don't call handleFieldChange for files\n }\n }\n\n this.handleFieldChange(fieldName, value);\n }\n });\n\n // Also add input event for text inputs for more responsive autosave\n if (input.type === 'text' || input.type === 'email' || input.type === 'url' || input.tagName === 'TEXTAREA') {\n input.addEventListener('input', (event) => {\n // Skip autosave during form population\n if (this._isPopulating) return;\n\n const fieldName = input.name;\n if (fieldName) {\n this.handleFieldChange(fieldName, input.value);\n }\n });\n }\n });\n }\n\n /**\n * Initialize TagInput components\n */\n initializeTagInputs() {\n const tagPlaceholders = this.element.querySelectorAll('[data-field-type=\"tag\"]');\n\n tagPlaceholders.forEach(placeholder => {\n try {\n const fieldName = placeholder.getAttribute('data-field-name');\n const configData = placeholder.getAttribute('data-field-config');\n const config = JSON.parse(configData);\n\n // Create TagInput component\n const tagInput = new TagInput({\n ...config,\n containerId: null // We'll mount directly\n });\n\n // Replace placeholder with TagInput\n tagInput.render(true, placeholder);\n\n // Store reference for cleanup\n this.customComponents.set(fieldName, tagInput);\n\n // Listen for changes\n tagInput.on('change', (data) => {\n this.handleFieldChange(fieldName, data.value);\n });\n\n } catch (error) {\n // TagInput initialization failed\n }\n });\n }\n\n /**\n * Initialize CollectionSelect components\n */\n initializeCollectionSelects() {\n const collectionPlaceholders = this.element.querySelectorAll('[data-field-type=\"collection\"]');\n\n collectionPlaceholders.forEach(placeholder => {\n try {\n const fieldName = placeholder.getAttribute('data-field-name');\n const configData = placeholder.getAttribute('data-field-config');\n const config = JSON.parse(configData);\n\n // Get Collection class from field config\n const fieldConfig = this.getFormFieldConfig(fieldName); // this.formConfig.fields.find(f => f.name === fieldName);\n if (!fieldConfig || !fieldConfig.Collection) {\n\n return;\n }\n\n // Create collection instance\n const collection = new fieldConfig.Collection();\n if (fieldConfig.collectionParams) {\n collection.params = {...collection.params, ...fieldConfig.collectionParams};\n }\n\n // Create CollectionSelect component\n const collectionSelect = new CollectionSelect({\n ...config,\n collection,\n defaultParams: fieldConfig.defaultParams || null, // Can be dict or callback\n containerId: null // We'll mount directly\n });\n\n let value = MOJOUtils.getContextData(this.data, fieldName);\n if (value) {\n collectionSelect.setFormValue(value);\n }\n\n // Replace placeholder with CollectionSelect\n collectionSelect.render(true, placeholder);\n\n // Store reference for cleanup\n this.customComponents.set(fieldName, collectionSelect);\n\n // Listen for changes\n collectionSelect.on('change', (data) => {\n this.handleFieldChange(fieldName, data.value);\n });\n\n } catch (error) {\n // CollectionSelect initialization failed\n }\n });\n }\n\n /**\n * Initialize CollectionMultiSelect components\n */\n initializeCollectionMultiSelects() {\n const collectionMultiSelectPlaceholders = this.element.querySelectorAll('[data-field-type=\"collectionmultiselect\"]');\n\n collectionMultiSelectPlaceholders.forEach(placeholder => {\n try {\n const fieldName = placeholder.getAttribute('data-field-name');\n const configData = placeholder.getAttribute('data-field-config');\n const config = JSON.parse(configData);\n\n // Get Collection class from field config\n const fieldConfig = this.getFormFieldConfig(fieldName);\n if (!fieldConfig || !fieldConfig.Collection) {\n return;\n }\n\n // Create collection instance\n const collection = new fieldConfig.Collection();\n if (fieldConfig.collectionParams) {\n collection.params = {...collection.params, ...fieldConfig.collectionParams};\n }\n\n // Create CollectionMultiSelect component\n const collectionMultiSelect = new CollectionMultiSelect({\n ...config,\n collection,\n defaultParams: fieldConfig.defaultParams || null, // Can be dict or callback\n itemTemplate: fieldConfig.itemTemplate || null, // Custom item template\n containerId: null // We'll mount directly\n });\n\n let value = MOJOUtils.getContextData(this.data, fieldName);\n if (value) {\n collectionMultiSelect.setFormValue(value);\n }\n\n // Replace placeholder with CollectionMultiSelect\n collectionMultiSelect.render(true, placeholder);\n\n // Store reference for cleanup\n this.customComponents.set(fieldName, collectionMultiSelect);\n\n // Listen for changes\n collectionMultiSelect.on('change', (data) => {\n this.handleFieldChange(fieldName, data.value);\n });\n\n } catch (error) {\n console.error('CollectionMultiSelect initialization failed:', error);\n }\n });\n }\n\n /**\n * Initialize DatePicker components\n */\n initializeDatePickers() {\n const datePickerPlaceholders = this.element.querySelectorAll('[data-field-type=\"datepicker\"]');\n\n datePickerPlaceholders.forEach(placeholder => {\n try {\n const fieldName = placeholder.getAttribute('data-field-name');\n const configData = placeholder.getAttribute('data-field-config');\n const config = JSON.parse(configData);\n\n // Create DatePicker component\n const datePicker = new DatePicker({\n ...config,\n containerId: null // We'll mount directly\n });\n\n // Replace placeholder with DatePicker\n datePicker.render(true, placeholder);\n\n // Store reference for cleanup\n this.customComponents.set(fieldName, datePicker);\n\n // Listen for changes\n datePicker.on('change', (data) => {\n this.handleFieldChange(fieldName, data.value);\n });\n\n } catch (error) {\n // DatePicker initialization failed\n }\n });\n }\n\n /**\n * Initialize DateRangePicker components\n */\n initializeDateRangePickers() {\n const dateRangePlaceholders = this.element.querySelectorAll('[data-field-type=\"daterange\"]');\n\n dateRangePlaceholders.forEach(placeholder => {\n try {\n const fieldName = placeholder.getAttribute('data-field-name');\n const configData = placeholder.getAttribute('data-field-config');\n const config = JSON.parse(configData);\n\n // Create DateRangePicker component\n const dateRangePicker = new DateRangePicker({\n ...config,\n containerId: null // We'll mount directly\n });\n\n // Replace placeholder with DateRangePicker\n dateRangePicker.render(true, placeholder);\n\n // Store reference for cleanup\n this.customComponents.set(fieldName, dateRangePicker);\n\n // Listen for changes\n dateRangePicker.on('change', (data) => {\n this.handleFieldChange(fieldName, data.combined);\n });\n\n } catch (error) {\n // DateRangePicker initialization failed\n }\n });\n }\n\n /**\n * Initialize ComboInput components\n */\n initializeComboInputs() {\n const comboPlaceholders = this.element.querySelectorAll('[data-field-type=\"combo\"]');\n\n comboPlaceholders.forEach(placeholder => {\n try {\n const fieldName = placeholder.getAttribute('data-field-name');\n const configData = placeholder.getAttribute('data-field-config');\n const config = JSON.parse(configData);\n\n // Create ComboInput component\n const comboInput = new ComboInput({\n ...config,\n containerId: null // We'll mount directly\n });\n\n let value = MOJOUtils.getContextData(this.data, fieldName);\n if (value) {\n comboInput.setValue(value);\n }\n\n // Replace placeholder with ComboInput\n comboInput.render(true, placeholder);\n\n // Store reference for cleanup\n this.customComponents.set(fieldName, comboInput);\n\n // Listen for changes\n comboInput.on('change', (data) => {\n this.handleFieldChange(fieldName, data.value);\n });\n\n // Listen for selection with metadata\n comboInput.on('select', (data) => {\n // Emit additional event with metadata for custom handling\n this.emit('field:select', {\n field: fieldName,\n value: data.value,\n option: data.option,\n meta: data.meta\n });\n });\n\n } catch (error) {\n console.error('ComboInput initialization failed:', error);\n }\n });\n }\n\n /**\n * Handle field changes from custom components\n */\n handleFieldChange(fieldName, value) {\n // Skip autosave during form population or field revert\n if (this._isPopulating) return;\n\n // Update internal data\n this.data[fieldName] = value;\n\n // Handle autosave or regular model update\n if (this.autosaveModelField && this.model) {\n // Auto-save individual field to model\n this.handleFieldSave(fieldName, value);\n } else if (this.model && this.options.allowModelChange) {\n // Regular model update without save\n this._isFormDrivenChange = true;\n this.model.set(fieldName, value);\n }\n\n // Emit change event\n this.emit('field:change', { field: fieldName, value });\n\n // Notify plugins of the field change\n FormPlugins.onFieldChange?.(this, fieldName, value);\n }\n\n /**\n * Handle saving field changes to the model with intelligent batching\n * When multiple fields change within a short time (e.g., autofill), they are batched together\n * @param {string} fieldName - Name of the field being saved\n * @param {*} value - New value to save\n */\n async handleFieldSave(fieldName, value) {\n if (!this.model) return;\n\n // Add field to pending save queue\n this.pendingSaveFields.set(fieldName, value);\n\n // Show saving status for this field\n const statusManager = this.getFieldStatusManager(fieldName);\n statusManager.showStatus('saving');\n\n // Clear existing batch timeout\n if (this.batchSaveTimeout) {\n clearTimeout(this.batchSaveTimeout);\n }\n\n // Set new batch timeout - if no more changes come in 300ms, save all pending fields\n this.batchSaveTimeout = setTimeout(async () => {\n await this.executeBatchSave();\n }, 300);\n }\n\n /**\n * Execute a batch save of all pending field changes\n * This sends all changed fields in a single request to avoid race conditions\n * @private\n */\n async executeBatchSave() {\n if (this.isSaving || this.pendingSaveFields.size === 0) return;\n\n // Collect all pending changes BEFORE clearing\n const changes = Object.fromEntries(this.pendingSaveFields);\n const fieldNames = Array.from(this.pendingSaveFields.keys());\n\n try {\n this.isSaving = true;\n\n // Clear pending fields before save\n this.pendingSaveFields.clear();\n this.batchSaveTimeout = null;\n\n // Mark as form-driven change to prevent sync back\n this._isFormDrivenChange = true;\n\n // Save all changes in a single request\n if (typeof this.model.save === 'function') {\n const resp = await this.model.save(changes);\n \n // Check if save was successful\n if (!resp || !resp.success || (resp.data && !resp.data.status)) {\n const errorMsg = resp?.data?.error || resp?.error || resp?.message || 'Save failed';\n \n // Show error toast\n this.getApp()?.toast?.error(errorMsg);\n \n // Revert fields to their original values\n this.revertFields(fieldNames);\n \n // Show error status for all fields\n fieldNames.forEach(fieldName => {\n const statusManager = this.getFieldStatusManager(fieldName);\n statusManager.showStatus('error', { message: errorMsg });\n });\n \n return; // Exit early, don't show success\n }\n } else {\n // Just update model attributes if no save method\n Object.entries(changes).forEach(([key, val]) => {\n this.model.set(key, val);\n });\n }\n\n // Show success status for all saved fields (only if we didn't return early)\n fieldNames.forEach(fieldName => {\n const statusManager = this.getFieldStatusManager(fieldName);\n statusManager.showStatus('saved');\n });\n\n } catch (error) {\n console.error('Batch save error:', error);\n\n // Show error toast\n this.getApp()?.toast?.error(error.message || 'An error occurred while saving');\n\n // Revert fields to their original values\n this.revertFields(fieldNames);\n\n // Show error status for all fields that were attempted\n fieldNames.forEach(fieldName => {\n const statusManager = this.getFieldStatusManager(fieldName);\n statusManager.showStatus('error', { message: error.message });\n });\n } finally {\n this.isSaving = false;\n }\n }\n\n /**\n * Revert form fields to their original model values\n * Called when save fails to keep UI in sync with server state\n * @param {Array<string>} fieldNames - Names of fields to revert\n * @private\n */\n revertFields(fieldNames) {\n if (!this.model) return;\n\n // Temporarily disable autosave during revert\n const wasPopulating = this._isPopulating;\n this._isPopulating = true;\n\n try {\n fieldNames.forEach(fieldName => {\n // Get original value from model\n const originalValue = this.model.get(fieldName);\n \n // Update internal data\n this.data[fieldName] = originalValue;\n \n // Find the field element and revert its value\n const fieldElement = this.element?.querySelector(`[name=\"${fieldName}\"]`);\n if (fieldElement) {\n const fieldConfig = this.getFormFieldConfig(fieldName);\n if (fieldConfig) {\n this.setFieldValue(fieldElement, fieldConfig, originalValue);\n } else {\n // Fallback if no config found\n if (fieldElement.type === 'checkbox') {\n fieldElement.checked = Boolean(originalValue);\n } else {\n fieldElement.value = originalValue ?? '';\n }\n }\n }\n });\n } finally {\n // Re-enable autosave\n this._isPopulating = wasPopulating;\n }\n }\n\n /**\n * Get or create a field status manager for a specific field\n * @param {string} fieldName - Name of the field\n * @returns {FieldStatusManager} Status manager instance\n */\n getFieldStatusManager(fieldName) {\n if (!this.fieldStatusManagers.has(fieldName)) {\n const fieldElement = this.element.querySelector(`[name=\"${fieldName}\"]`);\n if (fieldElement) {\n const statusManager = new FieldStatusManager(fieldElement);\n this.fieldStatusManagers.set(fieldName, statusManager);\n }\n }\n return this.fieldStatusManagers.get(fieldName);\n }\n\n /**\n * Refresh form data and repopulate values\n * Call this when model or data changes externally\n */\n refreshForm() {\n this.data = this.prepareFormData();\n\n // If mounted, repopulate form values\n if (this.element) {\n this.populateFormValues();\n }\n }\n\n /**\n * Get reason why a field is considered changed\n * @param {*} newValue - New value from form\n * @param {*} originalValue - Original value from model\n * @returns {string} Reason for change\n */\n getChangeReason(newValue, originalValue) {\n if (newValue instanceof File) {\n if (newValue.size === 0 || newValue.name === '' || newValue.name === 'blob') {\n return 'empty file, no change';\n }\n return `file upload: ${newValue.name}, ${newValue.size} bytes`;\n }\n\n if (typeof newValue === 'string' && newValue.startsWith('data:image/')) {\n return 'base64 image upload';\n }\n\n if (typeof newValue === 'boolean' || typeof originalValue === 'boolean') {\n const newBool = Boolean(newValue);\n const originalBool = originalValue === null || originalValue === undefined ? false : Boolean(originalValue);\n return `boolean: ${originalBool} → ${newBool}`;\n }\n\n const newStr = newValue === null || newValue === undefined ? '' : String(newValue).trim();\n const originalStr = originalValue === null || originalValue === undefined ? '' : String(originalValue).trim();\n\n if (originalValue === null || originalValue === undefined) {\n return 'was null/undefined, now has value';\n }\n\n if (newValue === null || newValue === undefined) {\n return 'was value, now null/undefined';\n }\n\n return 'text content changed';\n }\n\n /**\n * Set form data (updates the data property and rebuilds form)\n * @param {Object} newData - Data to set\n */\n setFormData(newData) {\n this._originalData = { ...this._originalData, ...newData };\n this.refreshForm();\n }\n\n\n\n // ========================================\n // EventDelegate Action Handlers\n // ========================================\n\n /**\n * Handle form submission\n */\n async onActionSubmitForm(event, element) {\n event.preventDefault();\n\n const result = await this.handleSubmit();\n\n if (result.success) {\n // Update internal data\n this.data = result.data;\n\n // Emit success event\n this.emit('submit', {\n data: result.data,\n result: result.result,\n form: this,\n event\n });\n\n // Call submit handler if provided (for non-model forms)\n if (!this.model && this.formConfig.onSubmit && typeof this.formConfig.onSubmit === 'function') {\n await this.formConfig.onSubmit(result.data, this);\n }\n } else {\n // Emit error event\n this.emit('error', {\n error: result.error,\n result: result,\n form: this\n });\n }\n }\n\n /**\n * Handle form reset\n */\n async onActionResetForm(event, _element) {\n const form = this.getFormElement();\n if (form) {\n form.reset();\n this.data = {};\n this.clearAllErrors();\n\n this.emit('reset', {\n form: this,\n event\n });\n }\n }\n\n /**\n * Handle image upload click\n */\n async onActionClickImageUpload(event, element) {\n console.log('FormView: onActionClickImageUpload called');\n console.log('FormView: element:', element);\n\n const fieldId = element.getAttribute('data-field-id');\n console.log('FormView: fieldId:', fieldId);\n\n if (!fieldId) {\n console.error('FormView: No fieldId attribute found');\n return;\n }\n\n const fileInput = this.element.querySelector(`#${fieldId}`);\n console.log('FormView: fileInput:', fileInput);\n\n if (fileInput && !fileInput.disabled) {\n fileInput.click();\n console.log('FormView: fileInput.click() called');\n } else if (!fileInput) {\n console.error('FormView: fileInput not found for fieldId:', fieldId);\n } else {\n console.log('FormView: fileInput is disabled');\n }\n }\n\n /**\n * Handle image removal\n */\n async onActionRemoveImage(event, element) {\n const fieldName = element.getAttribute('data-field');\n if (!fieldName) return;\n\n // Clear the field value\n const fileInput = this.element.querySelector(`input[name=\"${fieldName}\"]`);\n if (fileInput) {\n fileInput.value = '';\n fileInput.dispatchEvent(new Event('change', { bubbles: true }));\n }\n\n // Update data and re-render\n delete this.data[fieldName];\n this.emit('change', { field: fieldName, value: null, form: this });\n await this.updateField(fieldName);\n }\n\n /**\n * Handle clear color action\n */\n async onActionClearColor(event, element) {\n const fieldName = element.getAttribute('data-field');\n if (!fieldName) return;\n\n // Clear the color input value\n const colorInput = this.element.querySelector(`input[name=\"${fieldName}\"]`);\n if (colorInput) {\n colorInput.value = '';\n\n // Trigger field change handling (for autosave if enabled)\n this.handleFieldChange(fieldName, '');\n\n // Update the field to hide the clear button\n await this.updateField(fieldName);\n }\n }\n\n /**\n * Handle button group selection\n */\n async onActionSelectButtonOption(event, element) {\n const fieldName = element.getAttribute('data-field');\n const value = element.getAttribute('data-value');\n\n if (!fieldName || !value) return;\n\n // Update form data\n this.data[fieldName] = value;\n\n // Update UI - remove active class from siblings and add to this button\n const buttonGroup = element.closest('.btn-group');\n if (buttonGroup) {\n const buttons = buttonGroup.querySelectorAll('button');\n buttons.forEach(btn => {\n btn.classList.remove('active');\n btn.classList.add('btn-outline-primary');\n btn.classList.remove('btn-primary');\n });\n\n element.classList.add('active');\n element.classList.remove('btn-outline-primary');\n element.classList.add('btn-primary');\n }\n\n // Emit field change event\n this.emit('field:changed', {\n field: fieldName,\n value: value,\n form: this\n });\n\n this.emit('change', {\n field: fieldName,\n value: value,\n form: this\n });\n\n // Emit general form change event\n this.emit('form:changed', await this.getFormData());\n }\n\n /**\n * Handle checklist dropdown filter apply\n */\n async onActionApplyFilter(event, element) {\n const dropdown = element.closest('.dropdown');\n const checkboxes = dropdown?.querySelectorAll('input[type=\"checkbox\"]');\n\n if (!checkboxes || checkboxes.length === 0) return;\n\n const fieldName = checkboxes[0].getAttribute('data-field');\n if (!fieldName) return;\n\n // Collect checked values\n const selectedValues = [];\n checkboxes.forEach(checkbox => {\n if (checkbox.checked) {\n selectedValues.push(checkbox.value);\n }\n });\n\n // Update form data\n this.data[fieldName] = selectedValues;\n\n // Close dropdown\n const dropdownBtn = dropdown.querySelector('[data-bs-toggle=\"dropdown\"]');\n if (dropdownBtn && window.bootstrap?.Dropdown) {\n const dropdownInstance = window.bootstrap.Dropdown.getInstance(dropdownBtn);\n dropdownInstance?.hide();\n }\n\n // Emit field change event\n this.emit('field:changed', {\n field: fieldName,\n value: selectedValues,\n form: this\n });\n\n this.emit('change', {\n field: fieldName,\n value: selectedValues,\n form: this\n });\n\n // Emit general form change event\n this.emit('form:changed', await this.getFormData());\n }\n\n // ========================================\n // EventDelegate Change Handlers\n // ========================================\n\n /**\n * Handle field validation on change\n */\n async onChangeValidateField(event, element) {\n const fieldName = element.name;\n if (fieldName) {\n const value = element.value;\n\n // Use handleFieldChange for consistent processing\n this.handleFieldChange(fieldName, value);\n\n // Validate the field\n this.validateField(fieldName);\n }\n }\n\n /**\n * Handle switch toggle\n */\n async onChangeToggleSwitch(event, element) {\n const fieldName = element.getAttribute('data-field');\n if (fieldName) {\n const value = element.checked;\n\n // Use handleFieldChange for consistent processing\n this.handleFieldChange(fieldName, value);\n\n // Emit specific switch events for backward compatibility\n this.emit('switch:toggle', {\n field: fieldName,\n checked: value,\n form: this\n });\n }\n }\n\n /**\n * Handle image selection\n */\n async onChangeImageSelected(event, element) {\n console.log('FormView: onChangeImageSelected called');\n console.log('FormView: element:', element);\n console.log('FormView: element.files:', element.files);\n\n const fieldName = element.getAttribute('data-field');\n const file = element.files[0];\n\n console.log('FormView: fieldName:', fieldName);\n console.log('FormView: file:', file);\n\n if (fieldName && file) {\n console.log('FormView: fieldName and file exist, processing...');\n\n // Find the field configuration to check for imageSize\n const fieldConfig = this.findFieldConfig(fieldName);\n console.log('FormView: fieldConfig:', fieldConfig);\n\n // Create temporary preview URL\n const previewUrl = URL.createObjectURL(file);\n console.log('FormView: previewUrl created:', previewUrl);\n\n // Check if image cropping is required\n if (fieldConfig && fieldConfig.imageSize) {\n console.log('FormView: Image cropping is required, imageSize:', fieldConfig.imageSize);\n try {\n // Check if lightbox extension is available for image cropping\n const ImageCropView = window.MOJO?.plugins?.ImageCropView;\n console.log('FormView: ImageCropView available?', !!ImageCropView);\n\n if (!ImageCropView) {\n // ImageCropView not available - fall back to normal handling without cropping\n console.log('FormView: ImageCropView not available, falling back to normal handling');\n this.data[fieldName] = file;\n await this.updateImagePreview(fieldName, previewUrl);\n this.emit('image:selected', { field: fieldName, file: file, form: this });\n return;\n }\n\n // Open crop dialog with crop and scale\n const result = await ImageCropView.showDialog(previewUrl, {\n title: `Crop ${fieldConfig.label || fieldName}`,\n cropAndScale: fieldConfig.imageSize,\n size: 'lg'\n });\n\n if (result.action === 'crop' && result.data) {\n // Convert data URL to blob\n const response = await fetch(result.data);\n const croppedBlob = await response.blob();\n\n // Create a new File object with the original name\n const croppedFile = new File([croppedBlob], file.name, {\n type: file.type || 'image/png'\n });\n\n this.data[fieldName] = croppedFile;\n\n // Update preview with cropped image\n await this.updateImagePreview(fieldName, result.data);\n\n this.emit('image:selected', {\n field: fieldName,\n file: croppedFile,\n originalFile: file,\n cropped: true,\n cropData: result.cropData,\n form: this\n });\n\n this.emit('change', {\n field: fieldName,\n value: croppedFile,\n form: this\n });\n } else {\n // User cancelled cropping, don't update the field\n element.value = ''; // Clear the input\n }\n } catch (error) {\n // Error during image cropping\n console.error('FormView: Error during image cropping:', error);\n // Fall back to normal image handling\n console.log('FormView: Falling back to normal image handling after error');\n this.data[fieldName] = file;\n await this.updateImagePreview(fieldName, previewUrl);\n\n this.emit('image:selected', {\n field: fieldName,\n file: file,\n form: this\n });\n\n this.emit('change', {\n field: fieldName,\n value: file,\n form: this\n });\n }\n } else {\n // Normal image handling without cropping\n console.log('FormView: Normal image handling (no cropping)');\n this.data[fieldName] = file;\n console.log('FormView: File stored in this.data[' + fieldName + ']');\n\n await this.updateImagePreview(fieldName, previewUrl);\n console.log('FormView: updateImagePreview completed');\n\n this.emit('image:selected', {\n field: fieldName,\n file: file,\n form: this\n });\n console.log('FormView: image:selected event emitted');\n }\n } else {\n console.log('FormView: Missing fieldName or file - not processing');\n }\n }\n\n /**\n * Handle file selection\n */\n async onChangeFileSelected(event, element) {\n const files = Array.from(element.files);\n\n // Store the file(s) in this.data so getFormData() can access them\n if (element.multiple) {\n this.data[element.name] = element.files; // Store as FileList for multiple\n } else {\n this.data[element.name] = files[0] || null; // Store single File object\n }\n\n this.emit('file:selected', {\n field: element.name,\n files: files,\n form: this\n });\n\n this.emit('change', {\n field: element.name,\n value: files,\n form: this\n });\n }\n\n /**\n * Handle range value changes\n */\n async onChangeRangeChanged(event, element) {\n const fieldName = element.name;\n const value = element.value;\n\n // Update display target if specified\n const targetId = element.getAttribute('data-target');\n if (targetId) {\n const valueDisplay = this.element.querySelector(`#${targetId}`);\n if (valueDisplay) {\n valueDisplay.textContent = value;\n }\n }\n\n // Use handleFieldChange for consistent processing\n if (fieldName) {\n this.handleFieldChange(fieldName, value);\n }\n\n // Emit specific range event for backward compatibility\n this.emit('range:changed', {\n field: fieldName,\n value: value,\n form: this\n });\n }\n\n /**\n * Handle search/filter operations\n */\n async onChangeFilterSearch(event, element) {\n const query = element.value;\n this.emit('search', {\n query: query,\n field: element.name,\n form: this\n });\n }\n\n /**\n * Handle select option filtering\n */\n async onChangeFilterSelectOptions(event, element) {\n const query = element.value.toLowerCase();\n const targetId = element.getAttribute('data-target');\n const select = targetId ? this.element.querySelector(`#${targetId}`) : null;\n\n if (select) {\n const options = select.querySelectorAll('option');\n options.forEach(option => {\n const text = option.textContent.toLowerCase();\n option.style.display = text.includes(query) ? '' : 'none';\n });\n }\n }\n\n // ========================================\n // FileDropMixin Integration\n // ========================================\n\n /**\n * Handle file drop on image fields\n */\n async onFileDrop(files, event, _validation) {\n const dropZone = event.target.closest('.image-drop-zone');\n if (!dropZone) return;\n\n const fieldName = dropZone.getAttribute('data-field');\n if (!fieldName) return;\n\n const file = files[0];\n\n // Update file input\n const fileInput = this.element.querySelector(`input[name=\"${fieldName}\"]`);\n if (fileInput) {\n const dataTransfer = new DataTransfer();\n dataTransfer.items.add(file);\n fileInput.files = dataTransfer.files;\n fileInput.dispatchEvent(new Event('change', { bubbles: true }));\n }\n\n // Update data and preview\n this.data[fieldName] = file;\n const previewUrl = URL.createObjectURL(file);\n await this.updateImagePreview(fieldName, previewUrl);\n\n this.emit('image:dropped', {\n field: fieldName,\n file: file,\n form: this\n });\n }\n\n /**\n * Handle file drop errors\n */\n async onFileDropError(error, event, files) {\n // File drop error\n this.showError(`File upload error: ${error.message}`);\n\n this.emit('file:error', {\n error: error,\n files: files,\n form: this\n });\n }\n\n // ========================================\n // Form Management Methods\n // ========================================\n\n /**\n * Get form element\n */\n getFormElement() {\n return this.element ? this.element.querySelector('form') : null;\n }\n\n getFormFieldConfig(name) {\n const searchInFields = (fields) => {\n for (const field of fields) {\n if (field.name === name) {\n return field;\n }\n // Search in nested fields recursively\n if (field.fields && Array.isArray(field.fields)) {\n const found = searchInFields(field.fields);\n if (found) return found;\n }\n }\n return null;\n };\n\n return searchInFields(this.formConfig.fields || []);\n }\n\n /**\n * Get all form data\n * Returns JSON object for base64 mode, FormData for multipart mode\n */\n async getFormData() {\n const form = this.getFormElement();\n if (!form) return this.fileHandling === 'multipart' ? new FormData() : {};\n\n if (this.fileHandling === 'multipart') {\n // Return FormData object with files as File objects\n const formData = new FormData(form);\n\n // Add files from this.data to FormData\n for (const [key, value] of Object.entries(this.data)) {\n if (value instanceof File) {\n formData.set(key, value);\n } else if (value instanceof FileList) {\n for (let i = 0; i < value.length; i++) {\n formData.append(`${key}[${i}]`, value[i]);\n }\n }\n }\n\n return formData;\n } else {\n // Return JSON object with files converted to base64\n const formData = new FormData(form);\n const data = {};\n\n // Handle regular form fields\n for (const [key, value] of formData.entries()) {\n if (data[key]) {\n // Handle multiple values\n if (!Array.isArray(data[key])) {\n data[key] = [data[key]];\n }\n data[key].push(value);\n } else {\n data[key] = value;\n }\n }\n\n // Handle checkboxes and switches to ensure correct boolean values\n const checkboxes = form.querySelectorAll('input[type=\"checkbox\"]');\n checkboxes.forEach(checkbox => {\n data[checkbox.name] = checkbox.checked;\n });\n\n // Convert number fields to actual numbers\n const numberInputs = form.querySelectorAll('input[type=\"number\"]');\n numberInputs.forEach(input => {\n if (input.name && data[input.name] !== undefined && data[input.name] !== '') {\n const num = Number(data[input.name]);\n if (!isNaN(num)) {\n data[input.name] = num;\n }\n }\n });\n\n // Convert select fields with numeric values based on field config\n this.formConfig.fields?.forEach(field => {\n if (field.type === 'select' && field.name && data[field.name] !== undefined) {\n const fieldConfig = this.getFormFieldConfig(field.name);\n // Check if all option values are numeric\n if (fieldConfig?.options && Array.isArray(fieldConfig.options)) {\n const allNumeric = fieldConfig.options.every(opt => {\n const val = typeof opt === 'object' ? opt.value : opt;\n return val === '' || !isNaN(Number(val));\n });\n\n if (allNumeric && data[field.name] !== '') {\n const num = Number(data[field.name]);\n if (!isNaN(num)) {\n data[field.name] = num;\n }\n }\n }\n }\n });\n\n // Handle JSON fields\n const jsonFields = form.querySelectorAll('[data-field-type=\"json\"]');\n jsonFields.forEach(textarea => {\n try {\n data[textarea.name] = JSON.parse(textarea.value);\n } catch (e) {\n // Invalid JSON in field\n data[textarea.name] = textarea.value; // Keep as string if invalid\n }\n });\n\n // Handle custom components (TagInput, CollectionSelect, DatePicker, etc.)\n this.customComponents.forEach((component, fieldName) => {\n if (component.getFormValue) {\n data[fieldName] = component.getFormValue();\n } else if (component.getValue) {\n data[fieldName] = component.getValue();\n }\n });\n\n // Convert files to base64 and add to data\n for (const [key, value] of Object.entries(this.data)) {\n if (value instanceof File) {\n try {\n data[key] = await this.fileToBase64(value);\n } catch (error) {\n // Failed to convert file to base64\n data[key] = null;\n }\n } else if (value instanceof FileList) {\n const base64Files = [];\n for (let i = 0; i < value.length; i++) {\n try {\n base64Files.push(await this.fileToBase64(value[i]));\n } catch (error) {\n // Failed to convert file to base64\n base64Files.push(null);\n }\n }\n data[key] = base64Files;\n }\n }\n\n return data;\n }\n }\n\n _onModelChange() {\n // Don't sync during save operations to prevent loops\n if (this.isSaving) return;\n\n // Always update internal data\n this.data = this.prepareFormData();\n\n if (this.isMounted()) {\n // Only sync if the change wasn't initiated by this form\n if (!this._isFormDrivenChange) {\n this.syncFormWithModel();\n }\n // Reset the flag\n this._isFormDrivenChange = false;\n }\n }\n\n /**\n * Sync form field values with current model data without full rebuild\n */\n syncFormWithModel() {\n if (!this.model || !this.element) return;\n\n // Check if form data actually differs from current displayed values\n if (this.formDataMatchesModelData(this.data)) {\n return; // No sync needed - data is already in sync\n }\n\n // Re-populate form values with updated data\n this.populateFormValues();\n }\n\n /**\n * Compare current form values with new model data\n * @param {Object} newModelData - New data from model\n * @returns {boolean} True if form and model data match\n */\n formDataMatchesModelData(newModelData) {\n if (!this.formConfig?.fields || !this.element) return true;\n\n for (const field of this.formConfig.fields) {\n if (field.type === 'group' && field.fields) {\n // Check group fields\n for (const groupField of field.fields) {\n if (!this.fieldValueMatchesModel(groupField, newModelData)) {\n return false;\n }\n }\n } else {\n if (!this.fieldValueMatchesModel(field, newModelData)) {\n return false;\n }\n }\n }\n return true;\n }\n\n /**\n * Check if a single field's current value matches the model data\n * @param {Object} fieldConfig - Field configuration\n * @param {Object} modelData - Model data to compare against\n * @returns {boolean} True if field value matches model\n */\n fieldValueMatchesModel(fieldConfig, modelData) {\n if (!fieldConfig.name) return true;\n\n const fieldElement = this.element.querySelector(`[name=\"${fieldConfig.name}\"]`);\n if (!fieldElement) return true;\n\n const currentValue = this.getFieldCurrentValue(fieldElement, fieldConfig);\n // Use MOJOUtils to handle nested properties like 'permissions.manage_users'\n const modelValue = MOJOUtils.getContextData(modelData, fieldConfig.name);\n\n return this.valuesAreDifferent(currentValue, modelValue) === false;\n }\n\n\n\n /**\n * Get current value from a form field element\n */\n getFieldCurrentValue(fieldElement, fieldConfig) {\n switch (fieldConfig.type) {\n case 'checkbox':\n case 'toggle':\n case 'switch':\n return fieldElement.checked;\n case 'radio':\n const checkedRadio = this.element.querySelector(`[name=\"${fieldConfig.name}\"]:checked`);\n return checkedRadio ? checkedRadio.value : '';\n case 'select':\n return fieldElement.multiple ?\n Array.from(fieldElement.selectedOptions).map(opt => opt.value) :\n fieldElement.value;\n case 'file':\n case 'image':\n return null; // Don't sync file fields\n case 'json':\n // Parse JSON string back to object\n try {\n return fieldElement.value ? JSON.parse(fieldElement.value) : null;\n } catch (e) {\n return fieldElement.value; // Return raw string if invalid JSON\n }\n default:\n return fieldElement.value;\n }\n }\n\n /**\n * Set value on a form field element\n */\n setFieldValue(fieldElement, fieldConfig, newValue) {\n switch (fieldConfig.type) {\n case 'checkbox':\n case 'toggle':\n case 'switch':\n fieldElement.checked = Boolean(newValue);\n break;\n case 'radio':\n const radioOption = this.element.querySelector(`[name=\"${fieldConfig.name}\"][value=\"${newValue}\"]`);\n if (radioOption) {\n radioOption.checked = true;\n }\n break;\n case 'select':\n if (fieldElement.multiple && Array.isArray(newValue)) {\n Array.from(fieldElement.options).forEach(option => {\n option.selected = newValue.includes(option.value);\n });\n } else {\n // Use nullish coalescing to preserve falsy values like 0\n fieldElement.value = newValue ?? '';\n }\n break;\n case 'file':\n case 'image':\n // Don't programmatically set file fields\n break;\n case 'json':\n // Convert objects to formatted JSON strings\n if (typeof newValue === 'object' && newValue !== null) {\n try {\n fieldElement.value = JSON.stringify(newValue, null, 2);\n } catch (e) {\n fieldElement.value = '{}';\n }\n } else if (typeof newValue === 'string') {\n fieldElement.value = newValue;\n } else {\n fieldElement.value = String(newValue || '');\n }\n break;\n default:\n fieldElement.value = newValue || '';\n break;\n }\n\n // Trigger change event for any field listeners\n fieldElement.dispatchEvent(new Event('change', { bubbles: true }));\n }\n\n /**\n * Set defaults (updates defaults and rebuilds form)\n * @param {Object} newDefaults - Default values to set\n */\n setDefaults(newDefaults) {\n this.defaults = { ...this.defaults, ...newDefaults };\n this.refreshForm();\n }\n\n /**\n * Handle form submission with validation, saving, and error handling\n * @returns {Promise<Object>} Submission result {success: boolean, data: Object, result?: Object, error?: string}\n */\n async handleSubmit() {\n try {\n // Get form data (async for base64 conversion)\n const formData = await this.getFormData();\n\n // Validate if needed\n if (this.formConfig.validateOnSubmit !== false) {\n const isValid = this.validate();\n if (!isValid) {\n this.focusFirstError();\n return {\n success: false,\n data: formData,\n error: 'Form validation failed'\n };\n }\n }\n\n // If there's a model, save via model\n if (this.model && typeof this.model.save === 'function') {\n const result = await this.saveModel(formData);\n\n // Check if save was successful\n if (result && result.success !== false) {\n return {\n success: true,\n data: formData,\n result: result\n };\n } else {\n const errorMsg = result?.message || result?.error || 'Save failed. Please try again.';\n return {\n success: false,\n data: formData,\n result: result,\n error: errorMsg\n };\n }\n } else {\n // No model - just return form data\n return formData;\n }\n\n } catch (error) {\n // Form submission error\n\n return {\n success: false,\n error: error.message || 'An error occurred while submitting the form'\n };\n }\n }\n\n /**\n * Save form data via model\n * Uses auto-detection for multipart vs JSON based on form data type\n * Only saves changed data for efficiency\n * @returns {Promise<Object>} Save result from model\n */\n async saveModel(formData = null) {\n if (!this.model || typeof this.model.save !== 'function') {\n throw new Error('No model available for saving');\n }\n\n // Get form data (auto-detects FormData vs Object)\n if (!formData) formData = await this.getFormData();\n\n // Check for changes before saving\n const changes = this.getChangedData(formData);\n\n if (!changes || Object.keys(changes).length === 0) {\n // No changes detected\n return {\n success: true,\n message: 'No changes to save',\n data: formData\n };\n }\n\n\n\n try {\n // Mark this as a form-driven change to prevent sync back\n this._isFormDrivenChange = true;\n\n // Model.save with only changed data\n const result = await this.model.save(changes);\n\n\n return result;\n } catch (error) {\n // Model save error\n throw error;\n }\n }\n\n /**\n * Compare current form data with original model data to detect changes\n * @param {Object|FormData} currentData - Current form data\n * @returns {Object|FormData|null} Changed data only, or null if no changes\n */\n getChangedData(currentData) {\n if (!this.model) return currentData;\n\n // Get original data from model\n const originalData = this.getOriginalModelData();\n\n\n let changes;\n if (currentData instanceof FormData) {\n // Handle FormData comparison\n\n changes = this.getChangedFormData(currentData, originalData);\n } else {\n // Handle Object comparison\n\n changes = this.getChangedObjectData(currentData, originalData);\n }\n\n\n return changes;\n }\n\n /**\n * Get original data from model for comparison\n * @returns {Object} Original model data\n */\n getOriginalModelData() {\n if (this.model.attributes) {\n return this.model.attributes;\n } else if (typeof this.model.toJSON === 'function') {\n return this.model.toJSON();\n } else {\n return {};\n }\n }\n\n /**\n * Compare FormData with original data\n * @param {FormData} currentData - Current form data\n * @param {Object} originalData - Original model data\n * @returns {FormData|null} FormData with only changed fields, or null if no changes\n */\n getChangedFormData(currentData, originalData) {\n const changedData = new FormData();\n let hasChanges = false;\n\n // Compare each form field\n for (const [key, value] of currentData.entries()) {\n if (value instanceof File) {\n // Check if file has actual content\n if (value.size === 0 || value.name === '' || value.name === 'blob') {\n\n } else {\n\n changedData.set(key, value);\n hasChanges = true;\n }\n } else {\n // Compare text values\n const originalValue = originalData[key];\n if (value !== originalValue && value !== String(originalValue)) {\n\n changedData.set(key, value);\n hasChanges = true;\n } else {\n\n }\n }\n }\n\n return hasChanges ? changedData : null;\n }\n\n /**\n * Compare Object data with original data\n * @param {Object} currentData - Current form data\n * @param {Object} originalData - Original model data\n * @returns {Object|null} Object with only changed fields, or null if no changes\n */\n getChangedObjectData(currentData, originalData) {\n const changedData = {};\n let hasChanges = false;\n const allKeys = new Set([...Object.keys(originalData), ...Object.keys(currentData)]);\n\n const resolveDotNotation = (obj, path) => path.split('.').reduce((o, i) => (o && typeof o === 'object' ? o[i] : undefined), obj);\n\n for (const key of allKeys) {\n const fieldConfig = this.findFieldConfig(key);\n // Only process fields that are actually defined in the form's schema.\n if (!fieldConfig) {\n continue;\n }\n\n const newValue = currentData[key];\n const originalValue = resolveDotNotation(originalData, key);\n\n const fieldType = fieldConfig.type || 'text';\n\n if (this.valuesAreDifferent(newValue, originalValue, fieldType, fieldConfig)) {\n changedData[key] = newValue;\n hasChanges = true;\n }\n }\n\n return hasChanges ? changedData : null;\n }\n\n /**\n * Compare two values to determine if they're different\n * @param {*} newValue - New value from form\n * @param {*} originalValue - Original value from model\n * @param {string} fieldType - The type of the field from the form config\n * @param {object} fieldConfig - The configuration of the field from the form config\n * @returns {boolean} True if values are different\n */\n valuesAreDifferent(newValue, originalValue, fieldType = 'text', fieldConfig = {}) {\n // Handle File objects (new uploads vs existing)\n if (newValue instanceof File) {\n return newValue.size > 0 && newValue.name !== '' && newValue.name !== 'blob';\n }\n\n // Handle base64 images (always considered changed if present)\n if (typeof newValue === 'string' && newValue.startsWith('data:image/')) {\n return true;\n }\n\n if (fieldType === \"collection\") {\n // this is the collection select, the field will typically be an ID or \"0\" for null;\n if (typeof originalValue === 'object' && originalValue !== null && originalValue !== undefined && typeof newValue === 'string') {\n // we really need to field config here if fieldKey is not id\n if (newValue === '0') {\n return originalValue !== null;\n }\n const valueField = fieldConfig.valueField || 'id';\n // we compare (str to int)\n if (originalValue[valueField] == newValue) {\n return false;\n }\n }\n }\n\n // For switches and checkboxes, perform a strict boolean comparison\n if (fieldType === 'switch' || fieldType === 'checkbox' || fieldType === 'toggle') {\n const newBool = !!newValue;\n const originalBool = !!originalValue;\n return newBool !== originalBool;\n }\n\n // For all other fields, compare their string representations\n const newStr = newValue === null || newValue === undefined ? '' : String(newValue).trim();\n const originalStr = originalValue === null || originalValue === undefined ? '' : String(originalValue).trim();\n\n return newStr !== originalStr;\n }\n\n /**\n * Validate entire form\n */\n validate() {\n const form = this.getFormElement();\n if (!form) return false;\n\n const isValid = form.checkValidity();\n\n if (!isValid) {\n form.classList.add('was-validated');\n }\n\n return isValid;\n }\n\n /**\n * Validate single field\n */\n validateField(fieldName) {\n const form = this.getFormElement();\n if (!form) return false;\n\n const field = form.elements[fieldName];\n if (!field) return false;\n\n const isValid = field.checkValidity();\n\n if (isValid) {\n field.classList.remove('is-invalid');\n field.classList.add('is-valid');\n delete this.errors[fieldName];\n } else {\n field.classList.remove('is-valid');\n field.classList.add('is-invalid');\n this.errors[fieldName] = field.validationMessage;\n }\n\n return isValid;\n }\n\n /**\n * Focus first error\n * If the invalid field is inside a hidden tab pane, activate that tab first.\n */\n focusFirstError() {\n const form = this.getFormElement();\n if (!form) return;\n\n const firstInvalid = form.querySelector(':invalid');\n if (!firstInvalid) return;\n\n // If inside a Bootstrap tab pane and not active, activate the corresponding tab\n const tabPane = firstInvalid.closest('.tab-pane');\n if (tabPane && !tabPane.classList.contains('active')) {\n const tabId = tabPane.id;\n\n // Find the tab trigger button (support aria-controls or data-bs-target)\n const trigger = form.querySelector(`[role=\"tab\"][aria-controls=\"${tabId}\"], [data-bs-target=\"#${tabId}\"]`);\n if (trigger) {\n // Prefer Bootstrap API if available\n const bsTab = window.bootstrap?.Tab?.getOrCreateInstance\n ? window.bootstrap.Tab.getOrCreateInstance(trigger)\n : null;\n\n if (bsTab && typeof bsTab.show === 'function') {\n bsTab.show();\n } else {\n // Fallback: manually toggle classes\n const navLinks = form.querySelectorAll('[role=\"tab\"].nav-link');\n navLinks.forEach(link => {\n const isActive = link === trigger;\n link.classList.toggle('active', isActive);\n link.setAttribute('aria-selected', isActive ? 'true' : 'false');\n });\n\n const panes = form.querySelectorAll('.tab-pane');\n panes.forEach(p => p.classList.remove('show', 'active'));\n tabPane.classList.add('show', 'active');\n }\n }\n }\n\n firstInvalid.focus();\n firstInvalid.scrollIntoView({ behavior: 'smooth', block: 'center' });\n }\n\n /**\n * Clear all errors\n */\n clearAllErrors() {\n const form = this.getFormElement();\n if (!form) return;\n\n this.errors = {};\n form.classList.remove('was-validated');\n\n const invalidElements = form.querySelectorAll('.is-invalid');\n invalidElements.forEach(el => el.classList.remove('is-invalid'));\n\n const validElements = form.querySelectorAll('.is-valid');\n validElements.forEach(el => el.classList.remove('is-valid'));\n }\n\n /**\n * Set loading state\n */\n setLoading(loading) {\n this.loading = loading;\n\n const form = this.getFormElement();\n if (!form) return;\n\n const fields = form.querySelectorAll('input, select, textarea, button');\n const submitBtn = form.querySelector('button[type=\"submit\"]');\n\n if (loading) {\n // Disable all fields\n fields.forEach(field => field.disabled = true);\n\n // Update submit button\n if (submitBtn) {\n submitBtn.innerHTML = '<span class=\"spinner-border spinner-border-sm me-2\"></span>Loading...';\n }\n } else {\n // Enable all fields\n fields.forEach(field => field.disabled = false);\n\n // Restore submit button\n if (submitBtn) {\n const submitLabel = this.formConfig.options?.submitButton || 'Submit';\n submitBtn.innerHTML = typeof submitLabel === 'string' ? submitLabel : 'Submit';\n }\n }\n }\n\n /**\n * Show error message\n */\n showError(message) {\n // Form error\n\n this.emit('error', { message, form: this });\n\n // Show alert in form\n if (this.element) {\n // Remove existing alerts\n const existingAlerts = this.element.querySelectorAll('.alert');\n existingAlerts.forEach(alert => alert.remove());\n\n const alertDiv = document.createElement('div');\n alertDiv.className = 'alert alert-danger alert-dismissible fade show';\n alertDiv.innerHTML = `\n ${message}\n <button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"alert\" aria-label=\"Close\"></button>\n `;\n\n this.element.insertBefore(alertDiv, this.element.firstChild);\n\n // Auto-remove after 5 seconds\n setTimeout(() => {\n if (alertDiv.parentNode) {\n alertDiv.remove();\n }\n }, 5000);\n }\n }\n\n /**\n * Update a specific field\n */\n async updateField(_fieldName) {\n // Re-create FormBuilder with updated data\n this.formBuilder = new FormBuilder({\n ...this.getFormConfig(),\n data: this.data,\n errors: this.errors\n });\n\n // Re-render the form\n await this.render();\n }\n\n /**\n * Update image preview\n */\n async updateImagePreview(fieldName, imageUrl) {\n const dropZone = this.element.querySelector(`[data-field=\"${fieldName}\"].image-drop-zone`);\n\n if (!dropZone) {\n // Drop zone not found for field\n return;\n }\n\n // Check if there's already a preview image\n let preview = dropZone.querySelector('img');\n const placeholder = dropZone.querySelector('.bi-image')?.parentElement;\n const fieldId = dropZone.getAttribute('data-field-id');\n\n if (imageUrl) {\n if (preview) {\n // Update existing preview\n preview.src = imageUrl;\n } else {\n // Create new preview image\n const previewId = `${fieldId}_preview`;\n dropZone.innerHTML = `\n <img id=\"${previewId}\"\n src=\"${imageUrl}\"\n alt=\"Preview\"\n class=\"img-thumbnail w-100 h-100\"\n style=\"object-fit: cover;\">\n <button type=\"button\"\n class=\"btn btn-sm btn-danger position-absolute top-0 end-0 m-1\"\n data-action=\"remove-image\"\n data-field-id=\"${fieldId}\"\n data-field=\"${fieldName}\"\n style=\"opacity: 0.8;\">\n <i class=\"bi bi-x\"></i>\n </button>\n `;\n }\n\n // Hide placeholder if it exists\n if (placeholder) {\n placeholder.style.display = 'none';\n }\n }\n }\n\n /**\n * Find field configuration by name\n * @param {string} fieldName - Field name to find\n * @returns {Object|null} Field configuration\n */\n findFieldConfig(fieldName) {\n const searchInFields = (fields) => {\n for (const field of fields) {\n if (field.name === fieldName) {\n return field;\n }\n\n // Search in nested field structures\n // Groups: { type: 'group', fields: [...] }\n if (field.fields && Array.isArray(field.fields)) {\n const found = searchInFields(field.fields);\n if (found) return found;\n }\n\n // Tabsets: { type: 'tabset', tabs: [{ fields: [...] }] }\n if (field.tabs && Array.isArray(field.tabs)) {\n for (const tab of field.tabs) {\n if (tab.fields && Array.isArray(tab.fields)) {\n const found = searchInFields(tab.fields);\n if (found) return found;\n }\n }\n }\n }\n return null;\n };\n\n return searchInFields(this.formConfig.fields || []);\n }\n\n /**\n * Convert File object to base64 string\n * @param {File} file - File to convert\n * @returns {Promise<string>} Base64 encoded string\n */\n async fileToBase64(file) {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => resolve(reader.result);\n reader.onerror = reject;\n reader.readAsDataURL(file);\n });\n }\n\n /**\n * Check if form data contains any File objects\n * @param {Object|FormData} data - Form data to check\n * @returns {boolean} True if contains files\n */\n hasFiles(data) {\n if (data instanceof FormData) {\n for (const [key, value] of data.entries()) {\n if (value instanceof File) {\n return true;\n }\n }\n return false;\n } else {\n for (const value of Object.values(data)) {\n if (value instanceof File) {\n return true;\n }\n if (Array.isArray(value) && value.some(v => v instanceof File)) {\n return true;\n }\n }\n return false;\n }\n }\n\n /**\n * Reset form\n */\n reset() {\n const form = this.getFormElement();\n if (form) {\n form.reset();\n }\n\n this.data = {};\n this.errors = {};\n this.clearAllErrors();\n\n this.emit('reset', { form: this });\n }\n\n /**\n * Update form configuration\n */\n async updateConfig(newConfig) {\n this.formConfig = { ...this.formConfig, ...newConfig };\n this.formBuilder = new FormBuilder({\n ...this.getFormConfig(),\n data: this.data,\n errors: this.errors\n });\n\n await this.render();\n }\n\n /**\n * Clean up when destroying\n */\n async onBeforeDestroy() {\n // Clean up custom components\n const destroyPromises = [];\n for (const component of this.customComponents.values()) {\n if (component.destroy) {\n destroyPromises.push(component.destroy());\n }\n }\n await Promise.all(destroyPromises);\n this.customComponents.clear();\n\n // Clean up temporary URLs\n Object.values(this.data).forEach(value => {\n if (typeof value === 'string' && value.startsWith('blob:')) {\n URL.revokeObjectURL(value);\n }\n });\n\n await super.onBeforeDestroy();\n }\n /**\n * Initialize password fields: strength meter, caps lock warning, and hold-to-reveal\n */\n initializePasswordFields() {\n if (!this.element) return;\n\n // Find password inputs (either explicit data-field-type=\"password\" or native type=\"password\")\n const inputs = this.element.querySelectorAll('input[data-field-type=\"password\"], input[type=\"password\"]');\n\n inputs.forEach((input) => {\n // Initialize strength UI once\n this.updatePasswordStrengthUI(input);\n\n // Wire strength meter updates\n const onInput = (e) => {\n this.updatePasswordStrengthUI(e.target);\n };\n input.addEventListener('input', onInput);\n\n // Caps lock warning on key events\n const capsHandler = (e) => {\n if (typeof e.getModifierState === 'function') {\n const caps = e.getModifierState('CapsLock');\n this.updateCapsLockWarning(input, !!caps);\n }\n };\n input.addEventListener('keydown', capsHandler);\n input.addEventListener('keyup', capsHandler);\n\n // Initialize caps lock hidden state\n this.updateCapsLockWarning(input, false);\n });\n\n // Simple click toggle is handled by onActionTogglePassword; no extra listeners needed.\n }\n\n /**\n * Toggle password visibility on click (persistent toggle)\n * Ignored if currently in press-and-hold mode.\n */\n async onActionTogglePassword(event, element) {\n event.preventDefault();\n\n const targetId = element.getAttribute('data-target');\n let input = null;\n if (targetId) {\n input = this.element.querySelector('#' + targetId);\n }\n if (!input) {\n const group = element.closest('.input-group');\n if (group) {\n input = group.querySelector('input[type=\"password\"], input[data-field-type=\"password\"], input[type=\"text\"]');\n }\n }\n if (!input) return;\n\n const isHidden = input.type === 'password';\n input.type = isHidden ? 'text' : 'password';\n\n // Update button state and icon\n element.setAttribute('aria-pressed', isHidden ? 'true' : 'false');\n element.setAttribute('aria-label', isHidden ? 'Hide password' : 'Show password');\n const icon = element.querySelector('i');\n if (icon) {\n icon.classList.toggle('bi-eye', !isHidden);\n icon.classList.toggle('bi-eye-slash', isHidden);\n }\n\n // Keep focus on input and move caret to end\n input.focus();\n try {\n const len = input.value?.length ?? 0;\n input.setSelectionRange(len, len);\n } catch (_e) {\n // Not all input types support setSelectionRange; safe to ignore\n }\n }\n\n /**\n * Compute a simple password strength score and associated UI metadata\n */\n computePasswordStrength(password = '') {\n const len = password.length;\n let score = 0;\n\n // Length-based scoring\n if (len >= 6) score++;\n if (len >= 8) score++;\n if (len >= 12) score++;\n\n // Character variety\n const hasLower = /[a-z]/.test(password);\n const hasUpper = /[A-Z]/.test(password);\n const hasDigit = /\\d/.test(password);\n const hasSymbol = /[^A-Za-z0-9]/.test(password);\n\n const variety = [hasLower, hasUpper, hasDigit, hasSymbol].filter(Boolean).length;\n if (variety >= 2) score++;\n if (variety >= 3) score++;\n\n // Cap score between 0-4\n score = Math.max(0, Math.min(4, score));\n\n // Map to percent/label/class\n const map = [\n { percent: 0, label: 'Too short', barClass: 'bg-secondary' },\n { percent: 25, label: 'Weak', barClass: 'bg-danger' },\n { percent: 50, label: 'Fair', barClass: 'bg-warning' },\n { percent: 75, label: 'Good', barClass: 'bg-info' },\n { percent: 100, label: 'Strong', barClass: 'bg-success' }\n ];\n\n return map[score];\n }\n\n /**\n * Update strength meter UI if present for a given password input\n */\n updatePasswordStrengthUI(input) {\n if (!input || !input.id) return;\n\n const bar = this.element.querySelector(`#${input.id}_strength_bar`);\n const text = this.element.querySelector(`#${input.id}_strength_text`);\n if (!bar && !text) return;\n\n const { percent, label, barClass } = this.computePasswordStrength(input.value || '');\n\n if (bar) {\n // Reset to base class and apply strength color\n bar.className = `progress-bar ${barClass}`;\n bar.style.width = `${percent}%`;\n bar.setAttribute('aria-valuenow', String(percent));\n }\n if (text) {\n text.textContent = label;\n }\n }\n\n /**\n * Show/Hide a caps lock warning element if present for the given input\n */\n updateCapsLockWarning(input, capsOn) {\n if (!input || !input.id) return;\n const warn = this.element.querySelector(`#${input.id}_caps_warning`);\n if (!warn) return;\n\n if (capsOn) {\n warn.classList.remove('d-none');\n } else {\n warn.classList.add('d-none');\n }\n }\n}\n\n// Export for use in MOJO framework\n/**\n * FieldStatusManager - Manages save status indicators for form fields\n */\nclass FieldStatusManager {\n constructor(fieldElement) {\n this.fieldElement = fieldElement;\n this.statusContainer = this.findOrCreateStatusContainer();\n this.timeouts = new Map(); // Track active timeouts\n }\n\n /**\n * Find existing status container or create one based on field type\n */\n findOrCreateStatusContainer() {\n // Look for existing status container (check parent and labels)\n let container = this.fieldElement.parentElement.querySelector('.field-status-label-inline');\n\n // Also check within the field's label\n if (!container) {\n const label = this.findFieldLabel();\n if (label) {\n container = label.querySelector('.field-status-label-inline');\n }\n }\n\n if (!container) {\n container = this.createStatusContainer();\n }\n\n return container;\n }\n\n /**\n * Create appropriate status container based on field type\n */\n createStatusContainer() {\n const fieldType = this.getFieldType();\n const placement = this.getPlacementStrategy(fieldType);\n\n const container = document.createElement('div');\n\n // Since we only use label-inline now, simplify\n return this.createLabelInlineContainer(container);\n }\n\n /**\n * Determine field type from element\n */\n getFieldType() {\n const tagName = this.fieldElement.tagName.toLowerCase();\n const type = this.fieldElement.type?.toLowerCase();\n const classes = this.fieldElement.className;\n\n if (type === 'checkbox' || classes.includes('form-check-input') || classes.includes('form-switch')) {\n return 'toggle';\n } else if (tagName === 'select') {\n return 'select';\n } else if (tagName === 'textarea') {\n return 'textarea';\n } else if (tagName === 'input') {\n return 'input';\n }\n\n return 'input'; // default\n }\n\n /**\n * Determine placement strategy for field type\n */\n getPlacementStrategy(fieldType) {\n // Use label-inline for all field types - cleanest approach\n return 'label-inline';\n }\n\n /**\n * Create inline label status container (for all input types)\n */\n createLabelInlineContainer(container) {\n container.className = 'field-status-label-inline';\n container.innerHTML = this.getStatusHTML();\n\n // Find the associated label\n const label = this.findFieldLabel();\n if (label) {\n // Insert status container at the end of the label\n label.appendChild(container);\n } else {\n // Fallback to parent element if no label found\n this.fieldElement.parentElement.appendChild(container);\n }\n\n return container;\n }\n\n /**\n * Find the label associated with any field type\n */\n findFieldLabel() {\n // Try to find label by 'for' attribute matching field id\n if (this.fieldElement.id) {\n const label = document.querySelector(`label[for=\"${this.fieldElement.id}\"]`);\n if (label) return label;\n }\n\n // Look for label as sibling (common in Bootstrap form-check)\n const label = this.fieldElement.parentElement.querySelector('label');\n if (label) return label;\n\n // Look for label as parent (less common)\n const parentLabel = this.fieldElement.closest('label');\n if (parentLabel) return parentLabel;\n\n return null;\n }\n\n /**\n * Create input overlay container (for text inputs/selects)\n */\n createInputOverlayContainer(container) {\n container.className = 'field-status-overlay';\n container.innerHTML = this.getStatusHTML();\n\n // Make parent position relative if not already\n const parent = this.fieldElement.parentElement;\n if (getComputedStyle(parent).position === 'static') {\n parent.style.position = 'relative';\n }\n\n parent.appendChild(container);\n return container;\n }\n\n /**\n * Create full overlay container (for textareas/large inputs)\n */\n createFullOverlayContainer(container) {\n container.className = 'field-status-full-overlay d-none';\n container.innerHTML = `\n <div class=\"saving-indicator\">\n <div class=\"spinner-border spinner-border-sm text-primary\" role=\"status\">\n <span class=\"visually-hidden\">Saving...</span>\n </div>\n <span class=\"ms-2\">Saving...</span>\n </div>\n <div class=\"success-indicator d-none\">\n <i class=\"bi bi-check-circle text-success\"></i>\n <span class=\"ms-2\">Saved</span>\n </div>\n <div class=\"error-indicator d-none\">\n <i class=\"bi bi-exclamation-circle text-danger\"></i>\n <span class=\"ms-2\">Error saving</span>\n </div>\n `;\n\n // Make parent position relative if not already\n const parent = this.fieldElement.parentElement;\n if (getComputedStyle(parent).position === 'static') {\n parent.style.position = 'relative';\n }\n\n parent.appendChild(container);\n return container;\n }\n\n /**\n * Get standard status HTML for simple containers\n */\n getStatusHTML() {\n return `\n <div class=\"spinner-border spinner-border-sm text-primary d-none\" data-status=\"saving\" role=\"status\">\n <span class=\"visually-hidden\">Saving...</span>\n </div>\n <i class=\"bi bi-check-circle text-success d-none\" data-status=\"saved\"></i>\n <i class=\"bi bi-exclamation-circle text-danger d-none\" data-status=\"error\"></i>\n `;\n }\n\n /**\n * Show a status indicator\n * @param {string} type - Status type: 'saving', 'saved', 'error'\n * @param {object} options - Additional options\n */\n showStatus(type, options = {}) {\n // Clear any existing timeouts for this field\n this.clearTimeout(type);\n\n // Since we only use label-inline now, always use standard status\n this.showStandardStatus(type, options);\n }\n\n /**\n * Show status for standard containers (right-side, input-overlay)\n */\n showStandardStatus(type, options = {}) {\n // Hide all status indicators\n this.hideAllStatuses();\n\n // Show the requested status\n const indicator = this.statusContainer.querySelector(`[data-status=\"${type}\"]`);\n if (indicator) {\n indicator.classList.remove('d-none');\n indicator.classList.add('d-inline-block', 'show');\n\n // Set auto-hide timeout for temporary states\n if (type === 'saved') {\n this.setTimeout(type, () => this.hideStatus(type), 2500);\n } else if (type === 'error') {\n // Show error message in title if provided\n if (options.message) {\n indicator.title = options.message;\n }\n this.setTimeout(type, () => this.hideStatus(type), 6000);\n }\n }\n }\n\n /**\n * Show status for full overlay containers (textareas)\n */\n showFullOverlayStatus(type, options = {}) {\n // Hide all indicators first\n const indicators = this.statusContainer.querySelectorAll('.saving-indicator, .success-indicator, .error-indicator');\n indicators.forEach(ind => ind.classList.add('d-none'));\n\n // Show the container\n this.statusContainer.classList.remove('d-none');\n\n // Show specific indicator\n let indicatorClass;\n switch (type) {\n case 'saving':\n indicatorClass = '.saving-indicator';\n break;\n case 'saved':\n indicatorClass = '.success-indicator';\n this.setTimeout(type, () => this.hideStatus(type), 2500);\n break;\n case 'error':\n indicatorClass = '.error-indicator';\n if (options.message) {\n const errorSpan = this.statusContainer.querySelector('.error-indicator span');\n if (errorSpan) errorSpan.textContent = options.message;\n }\n this.setTimeout(type, () => this.hideStatus(type), 6000);\n break;\n }\n\n if (indicatorClass) {\n const indicator = this.statusContainer.querySelector(indicatorClass);\n if (indicator) {\n indicator.classList.remove('d-none');\n }\n }\n }\n\n /**\n * Hide a specific status indicator\n * @param {string} type - Status type to hide\n */\n hideStatus(type) {\n const indicator = this.statusContainer.querySelector(`[data-status=\"${type}\"]`);\n if (indicator) {\n indicator.classList.remove('show');\n indicator.classList.add('hide');\n\n // Actually hide after animation\n setTimeout(() => {\n indicator.classList.add('d-none');\n indicator.classList.remove('d-inline-block', 'hide');\n indicator.title = ''; // Clear any error message\n }, 300);\n }\n }\n\n /**\n * Hide all status indicators\n */\n hideAllStatuses() {\n const indicators = this.statusContainer.querySelectorAll('[data-status]');\n indicators.forEach(indicator => {\n indicator.classList.add('d-none');\n indicator.classList.remove('d-inline-block', 'show', 'hide');\n indicator.title = '';\n });\n }\n\n /**\n * Set a timeout for auto-hiding status\n * @param {string} type - Status type\n * @param {function} callback - Callback to execute\n * @param {number} delay - Delay in milliseconds\n */\n setTimeout(type, callback, delay) {\n const timeoutId = setTimeout(callback, delay);\n this.timeouts.set(type, timeoutId);\n }\n\n /**\n * Clear a specific timeout\n * @param {string} type - Status type\n */\n clearTimeout(type) {\n if (this.timeouts.has(type)) {\n clearTimeout(this.timeouts.get(type));\n this.timeouts.delete(type);\n }\n }\n\n /**\n * Clean up all timeouts\n */\n destroy() {\n this.timeouts.forEach(timeoutId => clearTimeout(timeoutId));\n this.timeouts.clear();\n }\n}\n\n// Apply FileDropMixin to FormView class\napplyFileDropMixin(FormView);\n\nexport default FormView;\nexport { FormView };\n"],"names":["Mustache","d","TagInput","CollectionSelect","CollectionMultiSelect","label"],"mappings":"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"}