"use strict"; /** * Modal_Abstract - Base class for modal orchestration classes * * **Philosophy**: * Modal classes are orchestration layers that manage the lifecycle of showing * a modal, collecting user input, and returning results. They do NOT contain * form validation or business logic - that belongs in jqhtml components and * controller endpoints. * * **Purpose**: * - Provides a common base class for type identification * - Enforces file naming conventions (modal classes end with _Modal) * - Documents the modal class pattern * - Enables framework-level features (future: discovery, validation) * * **Responsibilities of Modal Classes**: * - Invoke Modal.form() / Modal.show() / Modal.confirm() with appropriate configuration * - Handle modal lifecycle (show, submit, cancel, errors) * - Return Promise that resolves with data or false * - Encapsulate modal-specific UI logic * * **Contract**: * All modal classes extending Modal_Abstract must implement: * - `static async show(params)`: Primary entry point, returns Promise * * **Return Values**: * - Success: Resolve with data object (e.g., created user record) * - Cancel/Close: Resolve with false * - Error: Show error in modal, keep open, don't resolve until user acts * * **Integration**: * Modal classes use Modal.js static API (Modal.form(), Modal.show(), etc.) * as building blocks. Form validation handled by Rsx_Form and Form_Utils. * Page JS orchestrates modal flow but doesn't contain modal UI logic. * * **Pattern Examples**: * * Simple form modal: * ``` * class Add_User_Modal extends Modal_Abstract { * static async show() { * const result = await Modal.form({ * title: 'Add User', * component: 'Add_User_Modal_Form', * on_submit: async (form) => { * try { * const values = form.vals(); * const result = await Controller.add_user(values); * return result; // Close modal, return data * } catch (error) { * await form.render_error(error); * return false; // Keep modal open * } * }, * }); * return result || false; * } * } * ``` * * Custom content modal: * ``` * class Confirm_Delete_Modal extends Modal_Abstract { * static async show({item_name}) { * return await Modal.confirm( * 'Confirm Delete', * `Are you sure you want to delete ${item_name}?` * ); * } * } * ``` * * Modal with backend call: * ``` * class Send_Invite_Modal extends Modal_Abstract { * static async show(user_id) { * const result = await Controller.send_invite({user_id}); * if (result.invite_url) { * await Modal.alert('Invite Sent', result.invite_url); * } * return result; * } * } * ``` * * **Usage Pattern**: * ``` * // Page JS orchestrates flow, modals handle UI * const user = await Add_User_Modal.show(); * if (user) { * $('.Users_DataGrid').component().reload(); * await Send_User_Invite_Modal.show(user.id); * } * ``` * * **Best Practices**: * - Keep modal classes focused: one modal = one class * - Page JS orchestrates sequence, modal classes handle individual modals * - Modal classes don't call each other directly * - Modal classes don't update UI (grids, lists) - page JS does that * - Use descriptive names ending in _Modal (Add_User_Modal, Send_Invite_Modal) * - Place feature-specific modals in feature directory * - Place reusable modals in theme/components/modal/ * * **When to Use Modal Classes**: * - Multi-step forms * - Forms with complex validation * - Modals called from multiple places * - Modals with backend interactions * * **When NOT to Use Modal Classes**: * - Simple alerts: `await Modal.alert('Saved!')` * - Simple confirmations: `if (await Modal.confirm('Delete?')) {...}` * - One-off prompts: `const name = await Modal.prompt('Enter name:')` */ class Modal_Abstract { // This class provides structure and documentation for modal patterns. // Concrete modal classes extend this and implement static show() method. } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJNb2RhbF9BYnN0cmFjdCJdLCJzb3VyY2VzIjpbInJzeC90aGVtZS9jb21wb25lbnRzL21vZGFsL21vZGFsX2Fic3RyYWN0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogTW9kYWxfQWJzdHJhY3QgLSBCYXNlIGNsYXNzIGZvciBtb2RhbCBvcmNoZXN0cmF0aW9uIGNsYXNzZXNcbiAqXG4gKiAqKlBoaWxvc29waHkqKjpcbiAqIE1vZGFsIGNsYXNzZXMgYXJlIG9yY2hlc3RyYXRpb24gbGF5ZXJzIHRoYXQgbWFuYWdlIHRoZSBsaWZlY3ljbGUgb2Ygc2hvd2luZ1xuICogYSBtb2RhbCwgY29sbGVjdGluZyB1c2VyIGlucHV0LCBhbmQgcmV0dXJuaW5nIHJlc3VsdHMuIFRoZXkgZG8gTk9UIGNvbnRhaW5cbiAqIGZvcm0gdmFsaWRhdGlvbiBvciBidXNpbmVzcyBsb2dpYyAtIHRoYXQgYmVsb25ncyBpbiBqcWh0bWwgY29tcG9uZW50cyBhbmRcbiAqIGNvbnRyb2xsZXIgZW5kcG9pbnRzLlxuICpcbiAqICoqUHVycG9zZSoqOlxuICogLSBQcm92aWRlcyBhIGNvbW1vbiBiYXNlIGNsYXNzIGZvciB0eXBlIGlkZW50aWZpY2F0aW9uXG4gKiAtIEVuZm9yY2VzIGZpbGUgbmFtaW5nIGNvbnZlbnRpb25zIChtb2RhbCBjbGFzc2VzIGVuZCB3aXRoIF9Nb2RhbClcbiAqIC0gRG9jdW1lbnRzIHRoZSBtb2RhbCBjbGFzcyBwYXR0ZXJuXG4gKiAtIEVuYWJsZXMgZnJhbWV3b3JrLWxldmVsIGZlYXR1cmVzIChmdXR1cmU6IGRpc2NvdmVyeSwgdmFsaWRhdGlvbilcbiAqXG4gKiAqKlJlc3BvbnNpYmlsaXRpZXMgb2YgTW9kYWwgQ2xhc3NlcyoqOlxuICogLSBJbnZva2UgTW9kYWwuZm9ybSgpIC8gTW9kYWwuc2hvdygpIC8gTW9kYWwuY29uZmlybSgpIHdpdGggYXBwcm9wcmlhdGUgY29uZmlndXJhdGlvblxuICogLSBIYW5kbGUgbW9kYWwgbGlmZWN5Y2xlIChzaG93LCBzdWJtaXQsIGNhbmNlbCwgZXJyb3JzKVxuICogLSBSZXR1cm4gUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggZGF0YSBvciBmYWxzZVxuICogLSBFbmNhcHN1bGF0ZSBtb2RhbC1zcGVjaWZpYyBVSSBsb2dpY1xuICpcbiAqICoqQ29udHJhY3QqKjpcbiAqIEFsbCBtb2RhbCBjbGFzc2VzIGV4dGVuZGluZyBNb2RhbF9BYnN0cmFjdCBtdXN0IGltcGxlbWVudDpcbiAqIC0gYHN0YXRpYyBhc3luYyBzaG93KHBhcmFtcylgOiBQcmltYXJ5IGVudHJ5IHBvaW50LCByZXR1cm5zIFByb21pc2VcbiAqXG4gKiAqKlJldHVybiBWYWx1ZXMqKjpcbiAqIC0gU3VjY2VzczogUmVzb2x2ZSB3aXRoIGRhdGEgb2JqZWN0IChlLmcuLCBjcmVhdGVkIHVzZXIgcmVjb3JkKVxuICogLSBDYW5jZWwvQ2xvc2U6IFJlc29sdmUgd2l0aCBmYWxzZVxuICogLSBFcnJvcjogU2hvdyBlcnJvciBpbiBtb2RhbCwga2VlcCBvcGVuLCBkb24ndCByZXNvbHZlIHVudGlsIHVzZXIgYWN0c1xuICpcbiAqICoqSW50ZWdyYXRpb24qKjpcbiAqIE1vZGFsIGNsYXNzZXMgdXNlIE1vZGFsLmpzIHN0YXRpYyBBUEkgKE1vZGFsLmZvcm0oKSwgTW9kYWwuc2hvdygpLCBldGMuKVxuICogYXMgYnVpbGRpbmcgYmxvY2tzLiBGb3JtIHZhbGlkYXRpb24gaGFuZGxlZCBieSBSc3hfRm9ybSBhbmQgRm9ybV9VdGlscy5cbiAqIFBhZ2UgSlMgb3JjaGVzdHJhdGVzIG1vZGFsIGZsb3cgYnV0IGRvZXNuJ3QgY29udGFpbiBtb2RhbCBVSSBsb2dpYy5cbiAqXG4gKiAqKlBhdHRlcm4gRXhhbXBsZXMqKjpcbiAqXG4gKiBTaW1wbGUgZm9ybSBtb2RhbDpcbiAqIGBgYFxuICogY2xhc3MgQWRkX1VzZXJfTW9kYWwgZXh0ZW5kcyBNb2RhbF9BYnN0cmFjdCB7XG4gKiAgICAgc3RhdGljIGFzeW5jIHNob3coKSB7XG4gKiAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IE1vZGFsLmZvcm0oe1xuICogICAgICAgICAgICAgdGl0bGU6ICdBZGQgVXNlcicsXG4gKiAgICAgICAgICAgICBjb21wb25lbnQ6ICdBZGRfVXNlcl9Nb2RhbF9Gb3JtJyxcbiAqICAgICAgICAgICAgIG9uX3N1Ym1pdDogYXN5bmMgKGZvcm0pID0+IHtcbiAqICAgICAgICAgICAgICAgICB0cnkge1xuICogICAgICAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZXMgPSBmb3JtLnZhbHMoKTtcbiAqICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgQ29udHJvbGxlci5hZGRfdXNlcih2YWx1ZXMpO1xuICogICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0OyAvLyBDbG9zZSBtb2RhbCwgcmV0dXJuIGRhdGFcbiAqICAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICogICAgICAgICAgICAgICAgICAgICBhd2FpdCBmb3JtLnJlbmRlcl9lcnJvcihlcnJvcik7XG4gKiAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsgLy8gS2VlcCBtb2RhbCBvcGVuXG4gKiAgICAgICAgICAgICAgICAgfVxuICogICAgICAgICAgICAgfSxcbiAqICAgICAgICAgfSk7XG4gKiAgICAgICAgIHJldHVybiByZXN1bHQgfHwgZmFsc2U7XG4gKiAgICAgfVxuICogfVxuICogYGBgXG4gKlxuICogQ3VzdG9tIGNvbnRlbnQgbW9kYWw6XG4gKiBgYGBcbiAqIGNsYXNzIENvbmZpcm1fRGVsZXRlX01vZGFsIGV4dGVuZHMgTW9kYWxfQWJzdHJhY3Qge1xuICogICAgIHN0YXRpYyBhc3luYyBzaG93KHtpdGVtX25hbWV9KSB7XG4gKiAgICAgICAgIHJldHVybiBhd2FpdCBNb2RhbC5jb25maXJtKFxuICogICAgICAgICAgICAgJ0NvbmZpcm0gRGVsZXRlJyxcbiAqICAgICAgICAgICAgIGBBcmUgeW91IHN1cmUgeW91IHdhbnQgdG8gZGVsZXRlICR7aXRlbV9uYW1lfT9gXG4gKiAgICAgICAgICk7XG4gKiAgICAgfVxuICogfVxuICogYGBgXG4gKlxuICogTW9kYWwgd2l0aCBiYWNrZW5kIGNhbGw6XG4gKiBgYGBcbiAqIGNsYXNzIFNlbmRfSW52aXRlX01vZGFsIGV4dGVuZHMgTW9kYWxfQWJzdHJhY3Qge1xuICogICAgIHN0YXRpYyBhc3luYyBzaG93KHVzZXJfaWQpIHtcbiAqICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgQ29udHJvbGxlci5zZW5kX2ludml0ZSh7dXNlcl9pZH0pO1xuICogICAgICAgICBpZiAocmVzdWx0Lmludml0ZV91cmwpIHtcbiAqICAgICAgICAgICAgIGF3YWl0IE1vZGFsLmFsZXJ0KCdJbnZpdGUgU2VudCcsIHJlc3VsdC5pbnZpdGVfdXJsKTtcbiAqICAgICAgICAgfVxuICogICAgICAgICByZXR1cm4gcmVzdWx0O1xuICogICAgIH1cbiAqIH1cbiAqIGBgYFxuICpcbiAqICoqVXNhZ2UgUGF0dGVybioqOlxuICogYGBgXG4gKiAvLyBQYWdlIEpTIG9yY2hlc3RyYXRlcyBmbG93LCBtb2RhbHMgaGFuZGxlIFVJXG4gKiBjb25zdCB1c2VyID0gYXdhaXQgQWRkX1VzZXJfTW9kYWwuc2hvdygpO1xuICogaWYgKHVzZXIpIHtcbiAqICAgICAkKCcuVXNlcnNfRGF0YUdyaWQnKS5jb21wb25lbnQoKS5yZWxvYWQoKTtcbiAqICAgICBhd2FpdCBTZW5kX1VzZXJfSW52aXRlX01vZGFsLnNob3codXNlci5pZCk7XG4gKiB9XG4gKiBgYGBcbiAqXG4gKiAqKkJlc3QgUHJhY3RpY2VzKio6XG4gKiAtIEtlZXAgbW9kYWwgY2xhc3NlcyBmb2N1c2VkOiBvbmUgbW9kYWwgPSBvbmUgY2xhc3NcbiAqIC0gUGFnZSBKUyBvcmNoZXN0cmF0ZXMgc2VxdWVuY2UsIG1vZGFsIGNsYXNzZXMgaGFuZGxlIGluZGl2aWR1YWwgbW9kYWxzXG4gKiAtIE1vZGFsIGNsYXNzZXMgZG9uJ3QgY2FsbCBlYWNoIG90aGVyIGRpcmVjdGx5XG4gKiAtIE1vZGFsIGNsYXNzZXMgZG9uJ3QgdXBkYXRlIFVJIChncmlkcywgbGlzdHMpIC0gcGFnZSBKUyBkb2VzIHRoYXRcbiAqIC0gVXNlIGRlc2NyaXB0aXZlIG5hbWVzIGVuZGluZyBpbiBfTW9kYWwgKEFkZF9Vc2VyX01vZGFsLCBTZW5kX0ludml0ZV9Nb2RhbClcbiAqIC0gUGxhY2UgZmVhdHVyZS1zcGVjaWZpYyBtb2RhbHMgaW4gZmVhdHVyZSBkaXJlY3RvcnlcbiAqIC0gUGxhY2UgcmV1c2FibGUgbW9kYWxzIGluIHRoZW1lL2NvbXBvbmVudHMvbW9kYWwvXG4gKlxuICogKipXaGVuIHRvIFVzZSBNb2RhbCBDbGFzc2VzKio6XG4gKiAtIE11bHRpLXN0ZXAgZm9ybXNcbiAqIC0gRm9ybXMgd2l0aCBjb21wbGV4IHZhbGlkYXRpb25cbiAqIC0gTW9kYWxzIGNhbGxlZCBmcm9tIG11bHRpcGxlIHBsYWNlc1xuICogLSBNb2RhbHMgd2l0aCBiYWNrZW5kIGludGVyYWN0aW9uc1xuICpcbiAqICoqV2hlbiBOT1QgdG8gVXNlIE1vZGFsIENsYXNzZXMqKjpcbiAqIC0gU2ltcGxlIGFsZXJ0czogYGF3YWl0IE1vZGFsLmFsZXJ0KCdTYXZlZCEnKWBcbiAqIC0gU2ltcGxlIGNvbmZpcm1hdGlvbnM6IGBpZiAoYXdhaXQgTW9kYWwuY29uZmlybSgnRGVsZXRlPycpKSB7Li4ufWBcbiAqIC0gT25lLW9mZiBwcm9tcHRzOiBgY29uc3QgbmFtZSA9IGF3YWl0IE1vZGFsLnByb21wdCgnRW50ZXIgbmFtZTonKWBcbiAqL1xuY2xhc3MgTW9kYWxfQWJzdHJhY3Qge1xuICAgIC8vIFRoaXMgY2xhc3MgcHJvdmlkZXMgc3RydWN0dXJlIGFuZCBkb2N1bWVudGF0aW9uIGZvciBtb2RhbCBwYXR0ZXJucy5cbiAgICAvLyBDb25jcmV0ZSBtb2RhbCBjbGFzc2VzIGV4dGVuZCB0aGlzIGFuZCBpbXBsZW1lbnQgc3RhdGljIHNob3coKSBtZXRob2QuXG59XG4iXSwibWFwcGluZ3MiOiI7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNQSxjQUFjLENBQUM7RUFDakI7RUFDQTtBQUFBIiwiaWdub3JlTGlzdCI6W119