Merge branch 'dev'
This commit is contained in:
commit
ecbbd2d5ff
|
|
@ -27,6 +27,10 @@ export class RStackSpaceSwitcher extends HTMLElement {
|
||||||
#shadow: ShadowRoot;
|
#shadow: ShadowRoot;
|
||||||
#spaces: SpaceInfo[] = [];
|
#spaces: SpaceInfo[] = [];
|
||||||
#loaded = false;
|
#loaded = false;
|
||||||
|
// Preserved create-form state across open/close
|
||||||
|
#createFormOpen = false;
|
||||||
|
#createName = '';
|
||||||
|
#createVisibility = 'public';
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
@ -107,11 +111,27 @@ export class RStackSpaceSwitcher extends HTMLElement {
|
||||||
if (!this.#loaded) {
|
if (!this.#loaded) {
|
||||||
await this.#loadSpaces();
|
await this.#loadSpaces();
|
||||||
this.#renderMenu(menu, current);
|
this.#renderMenu(menu, current);
|
||||||
|
} else {
|
||||||
|
// Restore create form state if it was open
|
||||||
|
this.#restoreCreateFormState(menu);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Preserve create form state before closing
|
||||||
|
this.#saveCreateFormState(menu);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener("click", () => menu.classList.remove("open"));
|
// Close menu only when clicking outside both trigger and menu
|
||||||
|
document.addEventListener("click", (e) => {
|
||||||
|
if (!menu.classList.contains("open")) return;
|
||||||
|
const path = e.composedPath();
|
||||||
|
if (path.includes(menu) || path.includes(trigger)) return;
|
||||||
|
this.#saveCreateFormState(menu);
|
||||||
|
menu.classList.remove("open");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Prevent clicks inside menu from closing it
|
||||||
|
menu.addEventListener("click", (e) => e.stopPropagation());
|
||||||
}
|
}
|
||||||
|
|
||||||
#visibilityInfo(s: SpaceInfo): { cls: string; label: string } {
|
#visibilityInfo(s: SpaceInfo): { cls: string; label: string } {
|
||||||
|
|
@ -397,10 +417,11 @@ export class RStackSpaceSwitcher extends HTMLElement {
|
||||||
name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 40);
|
name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 40);
|
||||||
|
|
||||||
toggle.addEventListener("click", (e) => {
|
toggle.addEventListener("click", (e) => {
|
||||||
e.stopPropagation();
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const showing = popout.classList.toggle("hidden");
|
const wasHidden = popout.classList.contains("hidden");
|
||||||
if (!showing) nameInput.focus();
|
popout.classList.toggle("hidden");
|
||||||
|
this.#createFormOpen = wasHidden;
|
||||||
|
if (wasHidden) nameInput.focus();
|
||||||
});
|
});
|
||||||
|
|
||||||
nameInput.addEventListener("input", () => {
|
nameInput.addEventListener("input", () => {
|
||||||
|
|
@ -408,18 +429,17 @@ export class RStackSpaceSwitcher extends HTMLElement {
|
||||||
slugPreview.textContent = slug ? `slug: ${slug}` : "";
|
slugPreview.textContent = slug ? `slug: ${slug}` : "";
|
||||||
});
|
});
|
||||||
|
|
||||||
nameInput.addEventListener("click", (e) => e.stopPropagation());
|
cancelBtn.addEventListener("click", () => {
|
||||||
|
|
||||||
cancelBtn.addEventListener("click", (e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
popout.classList.add("hidden");
|
popout.classList.add("hidden");
|
||||||
nameInput.value = "";
|
nameInput.value = "";
|
||||||
slugPreview.textContent = "";
|
slugPreview.textContent = "";
|
||||||
status.textContent = "";
|
status.textContent = "";
|
||||||
|
this.#createFormOpen = false;
|
||||||
|
this.#createName = '';
|
||||||
|
this.#createVisibility = 'public';
|
||||||
});
|
});
|
||||||
|
|
||||||
submitBtn.addEventListener("click", async (e) => {
|
submitBtn.addEventListener("click", async () => {
|
||||||
e.stopPropagation();
|
|
||||||
const name = nameInput.value.trim();
|
const name = nameInput.value.trim();
|
||||||
if (!name) { status.textContent = "Name required"; return; }
|
if (!name) { status.textContent = "Name required"; return; }
|
||||||
|
|
||||||
|
|
@ -479,6 +499,43 @@ export class RStackSpaceSwitcher extends HTMLElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#saveCreateFormState(menu: HTMLElement) {
|
||||||
|
const popout = menu.querySelector("#create-popout") as HTMLElement;
|
||||||
|
if (!popout) return;
|
||||||
|
this.#createFormOpen = !popout.classList.contains("hidden");
|
||||||
|
const nameInput = menu.querySelector("#create-name") as HTMLInputElement;
|
||||||
|
if (nameInput) this.#createName = nameInput.value;
|
||||||
|
const checkedRadio = menu.querySelector('input[name="create-vis"]:checked') as HTMLInputElement;
|
||||||
|
if (checkedRadio) this.#createVisibility = checkedRadio.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#restoreCreateFormState(menu: HTMLElement) {
|
||||||
|
const popout = menu.querySelector("#create-popout") as HTMLElement;
|
||||||
|
const nameInput = menu.querySelector("#create-name") as HTMLInputElement;
|
||||||
|
const slugPreview = menu.querySelector("#create-slug") as HTMLElement;
|
||||||
|
if (!popout || !nameInput) return;
|
||||||
|
|
||||||
|
if (this.#createFormOpen) {
|
||||||
|
popout.classList.remove("hidden");
|
||||||
|
}
|
||||||
|
if (this.#createName) {
|
||||||
|
nameInput.value = this.#createName;
|
||||||
|
const toSlug = (name: string) =>
|
||||||
|
name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 40);
|
||||||
|
if (slugPreview) {
|
||||||
|
const slug = toSlug(this.#createName);
|
||||||
|
slugPreview.textContent = slug ? `slug: ${slug}` : "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.#createVisibility !== 'public') {
|
||||||
|
const radio = menu.querySelector(`input[name="create-vis"][value="${this.#createVisibility}"]`) as HTMLInputElement;
|
||||||
|
if (radio) radio.checked = true;
|
||||||
|
}
|
||||||
|
if (this.#createFormOpen) {
|
||||||
|
requestAnimationFrame(() => nameInput.focus());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#showRequestAccessModal(slug: string, spaceName: string) {
|
#showRequestAccessModal(slug: string, spaceName: string) {
|
||||||
if (document.querySelector(".rstack-auth-overlay")) return;
|
if (document.querySelector(".rstack-auth-overlay")) return;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue