Get menu alignment to somewhat work
This commit is contained in:
parent
af08c5094d
commit
14b3571af3
@ -5,19 +5,20 @@ export interface MenuItemConfig {
|
|||||||
customHTML?: HTMLElement;
|
customHTML?: HTMLElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type MenuAnchor =
|
export enum MenuPosition {
|
||||||
| "LeftCenter"
|
TopLeft = 'top-left',
|
||||||
| "RightCenter"
|
Left = 'left',
|
||||||
| "TopCenter"
|
BottomLeft = 'bottom-left',
|
||||||
| "BottomCenter"
|
Top = 'top',
|
||||||
| "TopLeft"
|
Bottom = 'bottom',
|
||||||
| "TopRight"
|
TopRight = 'top-right',
|
||||||
| "BottomLeft"
|
Right = 'right',
|
||||||
| "BottomRight";
|
BottomRight = 'bottom-right',
|
||||||
|
}
|
||||||
|
|
||||||
export interface MenuConfig {
|
export interface MenuConfig {
|
||||||
isGlobal?: boolean;
|
isGlobal?: boolean;
|
||||||
anchor: MenuAnchor;
|
menuPosition: MenuPosition;
|
||||||
activationRadius: number;
|
activationRadius?: number;
|
||||||
items: MenuItemConfig[];
|
items: MenuItemConfig[];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { MenuConfig, MenuItemConfig } from '@src/common/interfaces/ClientUiMenu.interface';
|
import { MenuPosition, MenuConfig, MenuItemConfig } from '@src/common/interfaces/ClientUiMenu.interface';
|
||||||
import extensionCss from '@src/main.css?inline';
|
import extensionCss from '@src/main.css?inline';
|
||||||
|
|
||||||
export class ClientMenu {
|
export class ClientMenu {
|
||||||
@ -8,9 +8,12 @@ export class ClientMenu {
|
|||||||
private root!: HTMLDivElement;
|
private root!: HTMLDivElement;
|
||||||
private visible = false;
|
private visible = false;
|
||||||
|
|
||||||
|
private menuPositionClasses: string[] = [];
|
||||||
|
|
||||||
constructor(private config: MenuConfig) {}
|
constructor(private config: MenuConfig) {}
|
||||||
|
|
||||||
mount(anchorElement: HTMLElement) {
|
mount(anchorElement: HTMLElement) {
|
||||||
|
this.buildMenuPositionClassList();
|
||||||
this.createHost();
|
this.createHost();
|
||||||
this.createShadow();
|
this.createShadow();
|
||||||
this.createMenu();
|
this.createMenu();
|
||||||
@ -76,7 +79,6 @@ export class ClientMenu {
|
|||||||
this.shadow.appendChild(style);
|
this.shadow.appendChild(style);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private createHost() {
|
private createHost() {
|
||||||
this.host = document.createElement("div");
|
this.host = document.createElement("div");
|
||||||
this.host.classList.add('uw-ultrawidify-container-root');
|
this.host.classList.add('uw-ultrawidify-container-root');
|
||||||
@ -90,7 +92,6 @@ export class ClientMenu {
|
|||||||
height: "100%",
|
height: "100%",
|
||||||
zIndex: this.config.isGlobal ? "2147483647" : "2147483640",
|
zIndex: this.config.isGlobal ? "2147483647" : "2147483640",
|
||||||
// pointerEvents: "none",
|
// pointerEvents: "none",
|
||||||
backgroundColor: "#00000099",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('UI host created:', this.host);
|
console.log('UI host created:', this.host);
|
||||||
@ -101,30 +102,74 @@ export class ClientMenu {
|
|||||||
this.injectStyles();
|
this.injectStyles();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
private buildMenuPositionClassList() {
|
||||||
|
let classList;
|
||||||
|
switch (this.config.menuPosition) {
|
||||||
|
case MenuPosition.TopLeft:
|
||||||
|
classList = ['uw-menu-left','uw-menu-top'];
|
||||||
|
break;
|
||||||
|
case MenuPosition.Left:
|
||||||
|
classList = ['uw-menu-left','uw-menu-ycenter'];
|
||||||
|
break;
|
||||||
|
case MenuPosition.BottomLeft:
|
||||||
|
classList = ['uw-menu-left','uw-menu-bottom'];
|
||||||
|
break;
|
||||||
|
case MenuPosition.Top:
|
||||||
|
classList = ['uw-menu-center','uw-menu-top'];
|
||||||
|
break;
|
||||||
|
case MenuPosition.Bottom:
|
||||||
|
classList = ['uw-menu-center', 'uw-menu-bottom'];
|
||||||
|
break;
|
||||||
|
case MenuPosition.TopRight:
|
||||||
|
classList = ['uw-menu-right', 'uw-menu-top'];
|
||||||
|
break;
|
||||||
|
case MenuPosition.Right:
|
||||||
|
classList = ['uw-menu-right', 'uw-menu-ycenter'];
|
||||||
|
break;
|
||||||
|
case MenuPosition.BottomRight:
|
||||||
|
classList = ['uw-menu-right', 'uw-menu-bottom'];
|
||||||
|
break;
|
||||||
|
default: // left-center is our default position
|
||||||
|
classList = ['uw-menu-left', 'uw-menu-ycenter'];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.menuPositionClasses = classList;
|
||||||
|
}
|
||||||
|
|
||||||
private createMenu() {
|
private createMenu() {
|
||||||
this.root = document.createElement("div");
|
this.root = document.createElement("div");
|
||||||
this.root.className = "uw-menu-root font-mono";
|
this.root.className = "uw-menu-root font-mono";
|
||||||
|
|
||||||
const trigger = document.createElement("div");
|
const trigger = document.createElement("div");
|
||||||
trigger.className = "uw-menu-trigger";
|
trigger.classList = "uw-menu-trigger uw-trigger";
|
||||||
trigger.textContent = "☰";
|
trigger.textContent = "Ultrawidify";
|
||||||
|
|
||||||
const submenu = this.buildSubmenu(this.config.items);
|
const submenu = this.buildSubmenu(this.config.items);
|
||||||
|
|
||||||
trigger.addEventListener("mouseenter", () => this.show());
|
trigger.addEventListener("mouseenter", () => this.show());
|
||||||
this.root.addEventListener("mouseleave", () => this.hide());
|
this.root.addEventListener("mouseleave", () => this.hide());
|
||||||
|
|
||||||
this.root.append(trigger, submenu);
|
console.log('menu position classes:', this.menuPositionClasses)
|
||||||
|
this.root.classList.add(...this.menuPositionClasses);
|
||||||
|
|
||||||
|
trigger.appendChild(submenu);
|
||||||
|
this.root.append(trigger);
|
||||||
this.shadow.appendChild(this.root);
|
this.shadow.appendChild(this.root);
|
||||||
}
|
}
|
||||||
|
|
||||||
private buildSubmenu(items: MenuItemConfig[]): HTMLDivElement {
|
private buildSubmenu(items: MenuItemConfig[]): HTMLDivElement {
|
||||||
const menu = document.createElement("div");
|
const menu = document.createElement("div");
|
||||||
menu.className = "uw-submenu";
|
menu.classList = "uw-submenu";
|
||||||
|
menu.classList.add(...this.menuPositionClasses);
|
||||||
|
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
const el = document.createElement("div");
|
const el = document.createElement("div");
|
||||||
el.className = "uw-menu-item";
|
el.className = `uw-menu-item uw-trigger`;
|
||||||
|
|
||||||
if (item.customHTML) {
|
if (item.customHTML) {
|
||||||
el.appendChild(item.customHTML);
|
el.appendChild(item.customHTML);
|
||||||
@ -151,8 +196,11 @@ export class ClientMenu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private position(anchorEl: HTMLElement) {
|
private position(anchorEl: HTMLElement) {
|
||||||
const rect = anchorEl.getBoundingClientRect();
|
let appendClassList: string[] = [];
|
||||||
const r = this.root.style;
|
|
||||||
|
|
||||||
|
|
||||||
|
anchorEl.classList.add(...appendClassList);
|
||||||
|
|
||||||
// switch (this.config.anchor) {
|
// switch (this.config.anchor) {
|
||||||
// case "LeftCenter":
|
// case "LeftCenter":
|
||||||
@ -188,14 +236,15 @@ export class ClientMenu {
|
|||||||
private show() {
|
private show() {
|
||||||
if (!this.visible) {
|
if (!this.visible) {
|
||||||
this.visible = true;
|
this.visible = true;
|
||||||
this.root.classList.add("visible");
|
this.root.classList.add("uw-visible");
|
||||||
|
this.root.classList.remove("uw-hidden");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private hide() {
|
private hide() {
|
||||||
if (this.visible) {
|
if (this.visible) {
|
||||||
this.visible = false;
|
this.visible = false;
|
||||||
this.root.classList.remove("visible");
|
this.root.classList.remove("uw-visible");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import { ClientMenu } from './ClientMenu';
|
|||||||
import EventBus from '../EventBus';
|
import EventBus from '../EventBus';
|
||||||
import PlayerData from '../video-data/PlayerData';
|
import PlayerData from '../video-data/PlayerData';
|
||||||
import { SiteSettings } from '../settings/SiteSettings';
|
import { SiteSettings } from '../settings/SiteSettings';
|
||||||
|
import { MenuPosition as MenuPosition } from '../../../common/interfaces/ClientUiMenu.interface';
|
||||||
|
|
||||||
if (process.env.CHANNEL !== 'stable'){
|
if (process.env.CHANNEL !== 'stable'){
|
||||||
console.info("Loading: UI");
|
console.info("Loading: UI");
|
||||||
@ -118,7 +119,14 @@ class UI {
|
|||||||
const uwid = `uw-ultrawidify-${this.interfaceId}-root-${random}`
|
const uwid = `uw-ultrawidify-${this.interfaceId}-root-${random}`
|
||||||
|
|
||||||
if (this.uiConfig.parentElement) {
|
if (this.uiConfig.parentElement) {
|
||||||
const uwMenu = new ClientMenu({isGlobal: this.isGlobal, anchor: "LeftCenter", items: [{label: 'test'}]});
|
const uwMenu = new ClientMenu({
|
||||||
|
isGlobal: this.isGlobal,
|
||||||
|
menuPosition: MenuPosition.Left,
|
||||||
|
items: [
|
||||||
|
{label: 'test'},
|
||||||
|
{label: 'test nested', subitems: [{label: 'sub test'}, {label: 'sub test 2'}]}
|
||||||
|
]
|
||||||
|
});
|
||||||
uwMenu.mount(this.uiConfig.parentElement);
|
uwMenu.mount(this.uiConfig.parentElement);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -2,9 +2,92 @@
|
|||||||
@import "tailwindcss/utilities";
|
@import "tailwindcss/utilities";
|
||||||
|
|
||||||
.uw-menu-root {
|
.uw-menu-root {
|
||||||
@apply h-full w-full font-mono text-stone-200 text-[16px];
|
@apply h-full w-full font-mono text-stone-200 text-[16px] flex flex-row;
|
||||||
|
|
||||||
|
&.uw-menu-left {
|
||||||
|
@apply justify-start;
|
||||||
|
}
|
||||||
|
&.uw-menu-right {
|
||||||
|
@apply justify-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.uw-menu-left, &.uw-menu-right {
|
||||||
|
&.uw-menu-top {
|
||||||
|
@apply items-start;
|
||||||
|
}
|
||||||
|
&.uw-menu-ycenter {
|
||||||
|
@apply items-center;
|
||||||
|
}
|
||||||
|
&.uw-menu-bottom {
|
||||||
|
@apply items-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.uw-menu-center {
|
||||||
|
@apply flex-col items-center;
|
||||||
|
|
||||||
|
&.uw-menu-top {
|
||||||
|
@apply justify-start;
|
||||||
|
}
|
||||||
|
&.uw-menu-bottom {
|
||||||
|
@apply justify-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
@apply font-mono text-stone-200 text-[1em];
|
@apply font-mono text-stone-200 text-[1em];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.uw-menu-trigger {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.uw-submenu {
|
||||||
|
@apply absolute flex flex-col gap-0;
|
||||||
|
|
||||||
|
&.uw-menu-left {
|
||||||
|
@apply left-full;
|
||||||
|
}
|
||||||
|
&.uw-menu-right {
|
||||||
|
@apply right-full;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.uw-menu-left, &.uw-menu-right {
|
||||||
|
&.uw-menu-top {
|
||||||
|
@apply top-1/2 -translate-y-1/2;
|
||||||
|
}
|
||||||
|
&.uw-menu-ycenter {
|
||||||
|
@apply top-0;
|
||||||
|
}
|
||||||
|
&.uw-menu-bottom {
|
||||||
|
@apply bottom-0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.uw-menu-center {
|
||||||
|
@apply left-1/2 -translate-x-1/2 flex-row;
|
||||||
|
|
||||||
|
&.uw-menu-top {
|
||||||
|
@apply bottom-0;
|
||||||
|
}
|
||||||
|
&.uw-menu-bottom {
|
||||||
|
@apply top-0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
@apply font-mono text-stone-200 text-[1em];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.uw-trigger {
|
||||||
|
@apply p-4 relative block
|
||||||
|
bg-stone-950/75 backdrop-blur-[1em] backdrop-brightness-75 backdrop-saturate-50
|
||||||
|
text-nowrap
|
||||||
|
;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
@apply text-primary-200 bg-stone-800/75;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user