consolidate modal handling into a new core file
This commit is contained in:
parent
41edcd408b
commit
79f7a33823
3 changed files with 127 additions and 64 deletions
|
|
@ -6,6 +6,7 @@ import { base } from '../../geo/base.js';
|
|||
import { local as sdb } from '../../data/local.js';
|
||||
import { slider } from './slider.js';
|
||||
import { keyboard } from './keyboard.js';
|
||||
import { modal } from './modal.js';
|
||||
import { space } from '../../moto/space.js';
|
||||
import { LOCAL, SETUP } from './main.js';
|
||||
import { VIEWS, MODES, SEED } from './consts.js';
|
||||
|
|
@ -848,6 +849,23 @@ function init_one() {
|
|||
settingsSave(undefined, ui.settingsName.value);
|
||||
};
|
||||
|
||||
// initialize modal controller
|
||||
modal.init({
|
||||
ui: {
|
||||
modal: ui.modal,
|
||||
modals: ui.modals
|
||||
},
|
||||
onShow: (which) => {
|
||||
api.event.emit('modal.show', which);
|
||||
},
|
||||
onHide: () => {
|
||||
api.event.emit('modal.hide');
|
||||
}
|
||||
});
|
||||
|
||||
// expose modal to API
|
||||
api.modal = modal;
|
||||
|
||||
// slider setup
|
||||
slider.init({
|
||||
ui: {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import './frame.js';
|
|||
import '../../ext/base64.js';
|
||||
|
||||
import STACKS from './stacks.js';
|
||||
import { modal } from './modal.js';
|
||||
|
||||
import { $ } from '../../moto/webui.js';
|
||||
import { api } from './api.js';
|
||||
|
|
@ -49,8 +50,8 @@ stats.set('kiri', version);
|
|||
self.kiri_catalog = FILES;
|
||||
|
||||
export const dialog = {
|
||||
show: showModal,
|
||||
hide: hideModal,
|
||||
show: (which) => modal.show(which),
|
||||
hide: () => modal.hide(),
|
||||
update_process_list: updateProcessList
|
||||
};
|
||||
|
||||
|
|
@ -84,11 +85,8 @@ export const image = {
|
|||
convert: loadImageConvert
|
||||
};
|
||||
|
||||
export const modal = {
|
||||
show: showModal,
|
||||
hide: hideModal,
|
||||
visible: modalShowing
|
||||
};
|
||||
// Re-export modal singleton methods
|
||||
export { modal };
|
||||
|
||||
export const mode = {
|
||||
get_id() { return MODE },
|
||||
|
|
@ -172,7 +170,7 @@ export const view = {
|
|||
};
|
||||
|
||||
// add show() to catalog for API
|
||||
FILES.show = showCatalog;
|
||||
FILES.show = () => modal.show('files');
|
||||
|
||||
// patch broker for api backward compatibility
|
||||
EVENT.on = (topic, listener) => {
|
||||
|
|
@ -604,59 +602,6 @@ function clearWorkspace() {
|
|||
platform.delete(selection.meshes());
|
||||
}
|
||||
|
||||
function modalShowing() {
|
||||
return api.ui.modal.style.display === 'flex';
|
||||
}
|
||||
|
||||
function showModal(which) {
|
||||
let mod = api.ui.modal,
|
||||
style = mod.style,
|
||||
visible = modalShowing(),
|
||||
info = { pct: 0 };
|
||||
|
||||
// hide all modals befroe showing another
|
||||
Object.keys(api.ui.modals).forEach(name => {
|
||||
api.ui.modals[name].style.display = name === which ? 'flex' : '';
|
||||
});
|
||||
|
||||
function ondone() {
|
||||
api.event.emit('modal.show', which);
|
||||
}
|
||||
|
||||
if (visible) {
|
||||
return ondone();
|
||||
}
|
||||
|
||||
style.height = '0';
|
||||
style.display = 'flex';
|
||||
|
||||
new TWEEN.Tween(info).
|
||||
easing(TWEEN.Easing.Quadratic.InOut).
|
||||
to({ pct: 100 }, 100).
|
||||
onUpdate(() => { style.height = `${info.pct}%` }).
|
||||
onComplete(ondone).
|
||||
start();
|
||||
}
|
||||
|
||||
function hideModal() {
|
||||
if (!modalShowing()) {
|
||||
return;
|
||||
}
|
||||
let mod = api.ui.modal, style = mod.style, info={pct:100};
|
||||
new TWEEN.Tween(info).
|
||||
easing(TWEEN.Easing.Quadratic.InOut).
|
||||
to({pct:0}, 100).
|
||||
onUpdate(() => { style.height = `${info.pct}%` }).
|
||||
onComplete(() => {
|
||||
style.display = '';
|
||||
api.event.emit('modal.hide');
|
||||
}).
|
||||
start();
|
||||
}
|
||||
|
||||
function showCatalog() {
|
||||
showModal("files");
|
||||
}
|
||||
|
||||
function editSettings(e) {
|
||||
let current = settings.get(),
|
||||
|
|
@ -729,7 +674,7 @@ function updateProcessList() {
|
|||
load.onclick = (ev) => {
|
||||
api.conf.load(undefined, sk);
|
||||
updateProcessList();
|
||||
hideModal();
|
||||
modal.hide();
|
||||
}
|
||||
load.appendChild(DOC.createTextNode(sk));
|
||||
if (sk == settings.proc().processName) {
|
||||
|
|
@ -772,7 +717,7 @@ function showHelpFile(local,then) {
|
|||
}
|
||||
const LANG = api.language.current;
|
||||
$('kiri-version').innerHTML = `${LANG.version} ${version}`;
|
||||
showModal('help');
|
||||
modal.show('help');
|
||||
api.event.emit('help.show', local);
|
||||
}
|
||||
|
||||
|
|
@ -881,7 +826,7 @@ function setMode(mode, lock, then) {
|
|||
selection.update_bounds(api.widgets.all());
|
||||
api.conf.update_fields();
|
||||
// because device dialog, if showing, needs to be updated
|
||||
if (modalShowing()) {
|
||||
if (modal.visible()) {
|
||||
api.show.devices();
|
||||
}
|
||||
api.space.restore(null, true);
|
||||
|
|
|
|||
100
src/kiri/core/modal.js
Normal file
100
src/kiri/core/modal.js
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||
|
||||
/**
|
||||
* Modal Manager (Singleton)
|
||||
* Manages modal dialog display and animations
|
||||
*/
|
||||
|
||||
class ModalControl {
|
||||
#ui;
|
||||
#onShow;
|
||||
#onHide;
|
||||
#initialized = false;
|
||||
|
||||
/**
|
||||
* Initialize the modal controller with dependencies
|
||||
* @param {Object} config
|
||||
* @param {Object} config.ui - UI element references
|
||||
* @param {HTMLElement} config.ui.modal - Modal container element
|
||||
* @param {Object} config.ui.modals - Object containing all modal elements by name
|
||||
* @param {Function} config.onShow - Optional callback when modal is shown
|
||||
* @param {Function} config.onHide - Optional callback when modal is hidden
|
||||
*/
|
||||
init({ ui, onShow, onHide }) {
|
||||
if (this.#initialized) {
|
||||
throw new Error('Modal already initialized');
|
||||
}
|
||||
|
||||
this.#ui = ui;
|
||||
this.#onShow = onShow;
|
||||
this.#onHide = onHide;
|
||||
this.#initialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if modal is currently visible
|
||||
* @returns {boolean}
|
||||
*/
|
||||
visible() {
|
||||
return this.#ui.modal.style.display === 'flex';
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a specific modal with animation
|
||||
* @param {string} which - Name of the modal to show
|
||||
*/
|
||||
show(which) {
|
||||
let mod = this.#ui.modal,
|
||||
style = mod.style,
|
||||
visible = this.visible(),
|
||||
info = { pct: 0 };
|
||||
|
||||
// hide all modals before showing another
|
||||
Object.keys(this.#ui.modals).forEach(name => {
|
||||
this.#ui.modals[name].style.display = name === which ? 'flex' : '';
|
||||
});
|
||||
|
||||
const ondone = () => {
|
||||
this.#onShow?.(which);
|
||||
};
|
||||
|
||||
if (visible) {
|
||||
return ondone();
|
||||
}
|
||||
|
||||
style.height = '0';
|
||||
style.display = 'flex';
|
||||
|
||||
new TWEEN.Tween(info).
|
||||
easing(TWEEN.Easing.Quadratic.InOut).
|
||||
to({ pct: 100 }, 100).
|
||||
onUpdate(() => { style.height = `${info.pct}%` }).
|
||||
onComplete(ondone).
|
||||
start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide the modal with animation
|
||||
*/
|
||||
hide() {
|
||||
if (!this.visible()) {
|
||||
return;
|
||||
}
|
||||
let mod = this.#ui.modal,
|
||||
style = mod.style,
|
||||
info = { pct: 100 };
|
||||
|
||||
new TWEEN.Tween(info).
|
||||
easing(TWEEN.Easing.Quadratic.InOut).
|
||||
to({ pct: 0 }, 100).
|
||||
onUpdate(() => { style.height = `${info.pct}%` }).
|
||||
onComplete(() => {
|
||||
style.display = '';
|
||||
this.#onHide?.();
|
||||
}).
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
// Export singleton instance
|
||||
export const modal = new ModalControl();
|
||||
Loading…
Reference in a new issue