Initial Commit
This commit is contained in:
@@ -0,0 +1,165 @@
|
||||
// saladui/components/dialog.js
|
||||
import Component from "../core/component";
|
||||
import SaladUI from "../index";
|
||||
import FocusTrap from "../core/focus-trap";
|
||||
import ClickOutsideMonitor from "../core/click-outside";
|
||||
|
||||
class DialogComponent extends Component {
|
||||
constructor(el, hookContext) {
|
||||
super(el, { hookContext, initialState: "closed" });
|
||||
|
||||
// Initialize properties
|
||||
this.root = this.el;
|
||||
this.content = this.getPart("content");
|
||||
this.contentPanel = this.getPart("content-panel");
|
||||
this.config.preventDefaultKeys = ["Escape"];
|
||||
|
||||
this.setupEvents();
|
||||
this.transition(this.el.dataset.open == "true" ? "open" : "close");
|
||||
}
|
||||
|
||||
getComponentConfig() {
|
||||
return {
|
||||
stateMachine: {
|
||||
closed: {
|
||||
enter: "onClosedEnter",
|
||||
exit: "onClosedExit",
|
||||
transitions: {
|
||||
open: "open",
|
||||
},
|
||||
},
|
||||
open: {
|
||||
enter: "onOpenEnter",
|
||||
transitions: {
|
||||
close: "closed",
|
||||
},
|
||||
},
|
||||
},
|
||||
events: {
|
||||
closed: {
|
||||
keyMap: {},
|
||||
},
|
||||
open: {
|
||||
keyMap: {
|
||||
Escape: "close",
|
||||
},
|
||||
},
|
||||
},
|
||||
hiddenConfig: {
|
||||
closed: {
|
||||
content: true,
|
||||
},
|
||||
open: {
|
||||
content: false,
|
||||
},
|
||||
},
|
||||
ariaConfig: {
|
||||
content: {
|
||||
all: {
|
||||
role: "dialog",
|
||||
},
|
||||
open: {
|
||||
hidden: "false",
|
||||
modal: "true",
|
||||
},
|
||||
closed: {
|
||||
hidden: "true",
|
||||
},
|
||||
},
|
||||
"content-panel": {
|
||||
open: {
|
||||
labelledby: () => this.getPartId("title"),
|
||||
describedby: () => this.getPartId("description"),
|
||||
},
|
||||
},
|
||||
"close-trigger": {
|
||||
all: {
|
||||
label: "Close dialog",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Setup component events
|
||||
setupComponentEvents() {
|
||||
super.setupComponentEvents();
|
||||
|
||||
// Only setup click handler if closeOnOutsideClick is enabled
|
||||
if (this.options.closeOnOutsideClick) {
|
||||
this.setupOutsideClickDetection();
|
||||
}
|
||||
}
|
||||
|
||||
setupOutsideClickDetection() {
|
||||
// Create click outside monitor to handle clicks on the overlay
|
||||
this.clickOutsideMonitor = new ClickOutsideMonitor(
|
||||
[this.contentPanel],
|
||||
(event) => {
|
||||
// Only close if click was directly on the content container (overlay area)
|
||||
if (
|
||||
event.target === this.content ||
|
||||
event.target.dataset.part === "overlay"
|
||||
) {
|
||||
this.transition("close");
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// State machine handlers
|
||||
onClosedEnter() {
|
||||
// Clean up focus trap
|
||||
if (this.focusTrap) {
|
||||
this.focusTrap.deactivate();
|
||||
}
|
||||
|
||||
// Clean up click outside monitor
|
||||
if (this.clickOutsideMonitor) {
|
||||
this.clickOutsideMonitor.stop();
|
||||
}
|
||||
|
||||
// Notify the server of the state change
|
||||
this.pushEvent("closed");
|
||||
}
|
||||
|
||||
onClosedExit() {
|
||||
// No special handling needed
|
||||
}
|
||||
|
||||
onOpenEnter() {
|
||||
// Initialize focus trap if not already created
|
||||
this.el.focus();
|
||||
if (!this.focusTrap) {
|
||||
this.focusTrap = new FocusTrap(this.contentPanel);
|
||||
}
|
||||
|
||||
// Activate focus trap
|
||||
this.focusTrap.activate();
|
||||
|
||||
// Activate click outside monitor if enabled
|
||||
if (this.clickOutsideMonitor) {
|
||||
this.clickOutsideMonitor.start();
|
||||
}
|
||||
|
||||
// Setup escape key handling - now handled by the component's keyMap
|
||||
|
||||
// Notify the server of the state change
|
||||
this.pushEvent("opened");
|
||||
}
|
||||
|
||||
beforeDestroy() {
|
||||
// Clean up focus trap
|
||||
this.focusTrap?.destroy();
|
||||
this.focusTrap = null;
|
||||
|
||||
// Clean up click outside monitor
|
||||
this.clickOutsideMonitor?.destroy();
|
||||
this.clickOutsideMonitor = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Register the component
|
||||
SaladUI.register("dialog", DialogComponent);
|
||||
|
||||
export default DialogComponent;
|
||||
Reference in New Issue
Block a user