@wuisdk/shell 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -0
- package/dist/base.shell-BD3tzDD9.d.ts +50 -0
- package/dist/desktop/index.css +1 -0
- package/dist/desktop/index.d.ts +16 -0
- package/dist/desktop/index.js +2 -0
- package/dist/index.css +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +2 -0
- package/dist/mobile/index.css +1 -0
- package/dist/mobile/index.d.ts +14 -0
- package/dist/mobile/index.js +2 -0
- package/dist/types-ayz5MABs.d.ts +41 -0
- package/dist/viewport-BEoQW1zd.js +17 -0
- package/package.json +34 -0
package/README.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
## @wuisdk/shell
|
|
2
|
+
- @wuisdk/shell/desktop
|
|
3
|
+
- @wuisdk/shell/mobile
|
|
4
|
+
|
|
5
|
+
### App Shell
|
|
6
|
+
```html
|
|
7
|
+
<div class="wui">
|
|
8
|
+
<aside class="wui-sidebar"></aside>
|
|
9
|
+
<div class="wui-shell">
|
|
10
|
+
<main class="wui-content"></main>
|
|
11
|
+
<div class="wui-loader"></div>
|
|
12
|
+
</div>
|
|
13
|
+
<nav class="wui-tabbar"></nav>
|
|
14
|
+
</div>
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### Overlay Root
|
|
18
|
+
```html
|
|
19
|
+
<div class="overlay-root">
|
|
20
|
+
<div class="overlay-backdrop"></div>
|
|
21
|
+
<div class="overlay-layer" data-type="drawer"></div>
|
|
22
|
+
<div class="overlay-layer" data-type="modal"></div>
|
|
23
|
+
<div class="overlay-layer" data-type="dialog"></div>
|
|
24
|
+
<div class="overlay-layer" data-type="popover"></div>
|
|
25
|
+
<div class="overlay-layer" data-type="toast"></div>
|
|
26
|
+
</div>
|
|
27
|
+
```
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { a as ViewportSize, i as ThemeMode, r as SidebarState } from "./types-ayz5MABs.js";
|
|
2
|
+
import { BaseComponent, IAppShell, ShellType, StoreListener, StoreSelector, SubscribeOptions } from "@wuisdk/core";
|
|
3
|
+
//#region src/store.d.ts
|
|
4
|
+
declare module '@wuisdk/core' {
|
|
5
|
+
interface WuiStoreMap {
|
|
6
|
+
layout: ShellLayoutStore;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
interface LayoutState {
|
|
10
|
+
theme: ThemeMode;
|
|
11
|
+
shell: ShellType;
|
|
12
|
+
viewport: ViewportSize;
|
|
13
|
+
sidebar: SidebarState;
|
|
14
|
+
sidebarPref?: SidebarState;
|
|
15
|
+
}
|
|
16
|
+
declare class ShellLayoutStore {
|
|
17
|
+
private store;
|
|
18
|
+
get state(): Readonly<LayoutState>;
|
|
19
|
+
subscribe<R>(selector: StoreSelector<LayoutState, R>, handler: StoreListener<R>, options?: SubscribeOptions<R>): () => void;
|
|
20
|
+
updateLayout(updates: Partial<LayoutState>): void;
|
|
21
|
+
toggleSidebar(): void;
|
|
22
|
+
private calcSidebarState;
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/regions/wui-shell.d.ts
|
|
26
|
+
declare class WuiShell extends BaseComponent {
|
|
27
|
+
private content;
|
|
28
|
+
private loader;
|
|
29
|
+
constructor();
|
|
30
|
+
protected render(): void;
|
|
31
|
+
protected onDestroy(): void;
|
|
32
|
+
get wuiContent(): HTMLElement;
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
//#region src/shell/base.shell.d.ts
|
|
36
|
+
declare abstract class BaseShell extends BaseComponent implements IAppShell {
|
|
37
|
+
protected wuiShell: WuiShell;
|
|
38
|
+
constructor();
|
|
39
|
+
protected onMount(): void;
|
|
40
|
+
protected onDestroy(): void;
|
|
41
|
+
get wuiRoot(): HTMLElement;
|
|
42
|
+
get wuiContent(): HTMLElement;
|
|
43
|
+
protected abstract readonly layoutStore: ShellLayoutStore;
|
|
44
|
+
protected abstract onShellMount(): void;
|
|
45
|
+
protected abstract onShellDestroy(): void;
|
|
46
|
+
private setupLayoutStateListener;
|
|
47
|
+
private setupSystemStateListener;
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
50
|
+
export { ShellLayoutStore as n, BaseShell as t };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer shell{.wui ::-webkit-scrollbar{width:var(--spacing-sm);height:var(--spacing-sm)}.wui ::-webkit-scrollbar-track{background:0 0}.wui ::-webkit-scrollbar-thumb{border-radius:var(--radius-full);background:#0000001a}}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { n as RegionsConfig } from "../types-ayz5MABs.js";
|
|
2
|
+
import { n as ShellLayoutStore, t as BaseShell } from "../base.shell-BD3tzDD9.js";
|
|
3
|
+
//#region src/shell/desktop.d.ts
|
|
4
|
+
declare class DesktopShell extends BaseShell {
|
|
5
|
+
private sidebar;
|
|
6
|
+
private viewport;
|
|
7
|
+
private indicator;
|
|
8
|
+
protected readonly layoutStore: ShellLayoutStore;
|
|
9
|
+
constructor(config?: RegionsConfig);
|
|
10
|
+
protected render(): void;
|
|
11
|
+
protected onShellMount(): void;
|
|
12
|
+
protected onShellDestroy(): void;
|
|
13
|
+
private setupPrefState;
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
export { DesktopShell };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import './index.css';
|
|
2
|
+
import{i as e,n as t,o as n,r,t as i}from"../viewport-BEoQW1zd.js";var a=class extends e{sidebar;viewport;indicator=new i;layoutStore=new r;constructor(e={}){super(),this.sidebar=new n(e.sidebar),this.viewport=new t(this.layoutStore)}render(){}onShellMount(){this.sidebar.injectContext(this.ctx).mount(this.element),this.wuiShell.injectContext(this.ctx).mount(this.element),this.indicator.injectContext(this.ctx).mount(this.element),this.setupPrefState(),this.viewport.observe()}onShellDestroy(){this.sidebar.destroy(),this.viewport.disconnect()}setupPrefState(){let{storage:e}=this.ctx.config,t=localStorage.getItem(e.SIDEBAR_STATE);t&&[`expanded`,`collapsed`].includes(t)&&this.layoutStore.updateLayout({sidebarPref:t}),this.layoutStore.subscribe(e=>e.sidebarPref,t=>{t&&[`expanded`,`collapsed`].includes(t)&&localStorage.setItem(e.SIDEBAR_STATE,t)},{signal:this.signal})}};export{a as DesktopShell};
|
package/dist/index.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer layout{.wui{grid-template-columns:1fr;width:100%;height:100dvh;display:grid;overflow:hidden}.wui-shell{flex-direction:column;min-width:0;height:100%;min-height:0;display:flex;position:relative;overflow:hidden}.wui-content{flex:1;min-width:0;min-height:0;overflow:auto}.wui-viewport{left:var(--spacing-sm);color:var(--color-text-muted);z-index:var(--z-overlay-root);font-size:10px;line-height:1;position:fixed}.wui[data-shell=dashboard]:not([data-sidebar=overlay],[data-sidebar=hidden]){grid-template-columns:auto 1fr}.wui[data-shell=dashboard]:not([data-sidebar=overlay],[data-sidebar=hidden]) .wui-content{margin:var(--spacing-md);border:1px solid var(--color-border-soft);border-radius:var(--radius-xl);background-color:var(--color-surface);margin-left:0;overflow:hidden}.wui[data-shell=dashboard]:is([data-sidebar=overlay],[data-sidebar=hidden]) .wui-content{background-color:var(--color-surface);overflow:hidden}.wui[data-shell=auth] .wui-content{background:linear-gradient(135deg,#f8fafd 0%,#eef2f8 45%,#e2e8f3 100%)}.wui[data-shell=auth] .wui-page,.wui[data-shell=auth] .wui-loader{justify-content:center;align-items:center}.wui-loader{padding:5.5rem var(--spacing-lg);transition:var(--fade-transition);z-index:var(--z-above);opacity:0;visibility:hidden;justify-content:center;display:flex;position:absolute;inset:0}.wui[data-loading=true] .wui-loader{opacity:1;visibility:visible}.wui-spinner{width:48px;height:48px;display:block;position:relative}.wui-spinner div{transform-origin:24px 24px;animation:1.2s linear infinite fade-out}.wui-spinner div:after{content:"";background-color:var(--color-primary);border-radius:2px;width:4px;height:11px;display:block;position:absolute;top:3px;left:22px}.wui-spinner div:first-child{animation-delay:-1.1s;transform:rotate(0)}.wui-spinner div:nth-child(2){animation-delay:-1s;transform:rotate(30deg)}.wui-spinner div:nth-child(3){animation-delay:-.9s;transform:rotate(60deg)}.wui-spinner div:nth-child(4){animation-delay:-.8s;transform:rotate(90deg)}.wui-spinner div:nth-child(5){animation-delay:-.7s;transform:rotate(120deg)}.wui-spinner div:nth-child(6){animation-delay:-.6s;transform:rotate(150deg)}.wui-spinner div:nth-child(7){animation-delay:-.5s;transform:rotate(180deg)}.wui-spinner div:nth-child(8){animation-delay:-.4s;transform:rotate(210deg)}.wui-spinner div:nth-child(9){animation-delay:-.3s;transform:rotate(240deg)}.wui-spinner div:nth-child(10){animation-delay:-.2s;transform:rotate(270deg)}.wui-spinner div:nth-child(11){animation-delay:-.1s;transform:rotate(300deg)}.wui-spinner div:nth-child(12){animation-delay:0s;transform:rotate(330deg)}:root{--sidebar-expanded-width:224px;--sidebar-collapsed-width:64px;--sidebar-bg:var(--color-bg)}.wui-sidebar{width:0;padding:var(--spacing-sm);background-color:var(--sidebar-bg);z-index:var(--z-sidebar);transition:width var(--transition-base), transform var(--transition-base);flex-direction:column;display:flex;position:fixed;inset:0 auto 0 0;overflow:hidden;transform:translate(-100%)}.sidebar__header{height:3rem;padding:0 var(--spacing-md);flex-shrink:0;justify-content:space-between;align-items:center;display:flex}.sidebar__logo{padding-left:var(--spacing-lg);font-family:var(--font-heading);font-size:var(--font-size-heading);color:var(--color-primary-text);white-space:nowrap;font-weight:600;overflow:hidden}.sidebar__toggle{border-radius:var(--radius-full);width:32px;height:32px;font-size:var(--font-xl);color:var(--color-primary-text);background-color:#0000;flex-shrink:0;padding:0}.sidebar__footer{height:3.5rem;padding:var(--spacing-sm);flex-shrink:0}.profile{justify-content:flex-start;gap:var(--spacing-md);width:100%;height:100%;padding:0 var(--spacing-md);background-color:#0000}.profile__avatar{width:2.25rem;height:2.25rem;padding:var(--spacing-xs);border-radius:var(--radius-full);background:#0000001a;flex-shrink:0;overflow:hidden}.profile__avatar img{border-radius:var(--radius-full);width:100%;height:100%;display:block}.profile__info{min-width:0;font-family:var(--font-body);text-align:left;white-space:nowrap;overflow:hidden}.profile__info :first-child{line-height:1.5;font-size:var(--font-sm);font-weight:500}.profile__info :last-child{line-height:1.25;font-size:var(--font-xs);color:var(--color-text-muted)}.wui[data-shell=dashboard][data-sidebar=collapsed] .wui-sidebar{width:var(--sidebar-collapsed-width);position:relative;transform:translate(0)}.wui[data-shell=dashboard][data-sidebar=expanded] .wui-sidebar{width:var(--sidebar-expanded-width);position:relative;transform:translate(0)}.wui[data-shell=dashboard][data-sidebar=overlay] .wui-sidebar{width:var(--sidebar-expanded-width);box-shadow:var(--shadow-lg);transform:translate(0)}.wui[data-sidebar=collapsed] .sidebar__logo,.wui[data-sidebar=collapsed] .profile__info{display:none}.wui[data-sidebar=collapsed] .sidebar__header,.wui[data-sidebar=collapsed] .profile{justify-content:center;padding:0}@media (hover:hover) and (pointer:fine){.sidebar__toggle:hover{background-color:var(--nav-item-bg-hover)}.profile:hover{color:var(--nav-item-text-hover);background-color:var(--nav-item-bg-hover)}}:root{--nav-item-text:var(--color-slate-500);--nav-item-text-hover:var(--color-slate-600);--nav-item-text-active:var(--color-primary-text);--nav-item-bg-hover:#0000000a;--nav-item-bg-active:var(--color-primary-100);--nav-item-border-active:rgb(from var(--color-primary-200) r g b / 25%)}.sidebar__nav{padding:var(--spacing-md);white-space:nowrap;scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;flex:1;overflow:hidden auto}.nav-item,.nav-subitem{justify-content:flex-start;align-items:center;gap:var(--spacing-md);padding:0 var(--spacing-lg);border-radius:var(--radius-md);margin-bottom:var(--spacing-sm);user-select:none;color:var(--nav-item-text);font-size:var(--font-size-label);background-color:#0000;border:1px solid #0000;width:100%;min-width:0;height:2.5rem;font-weight:500;text-decoration:none;display:flex}.nav-item[data-active],.nav-subitem[data-active]{color:var(--nav-item-text-active);background:var(--nav-item-bg-active);border-color:var(--nav-item-border-active)}.nav-item[data-active] .nav-icon,.nav-subitem[data-active] .nav-icon{font-weight:900}.nav-icon,.nav-caret{text-align:left;min-width:22px;line-height:1;font-family:var(--font-icon);font-size:var(--font-md);flex-shrink:0}.nav-label{text-align:left;font-family:var(--font-heading);white-space:nowrap;flex:1}.nav-group{flex-direction:column;display:flex}.nav-group[data-open=true]{margin-bottom:var(--spacing-sm)}.nav-caret{min-width:auto;transition:transform var(--transition-fast)}.nav-group[data-open=true] .nav-caret{transform:rotate(90deg)}.nav-children{visibility:hidden;opacity:0;grid-template-rows:0fr;transition:opacity .2s ease-out,grid-template-rows .2s ease-out;display:grid}.nav-group[data-open=true] .nav-children{visibility:visible;opacity:1;grid-template-rows:1fr}.nav-children>*{min-height:0}.nav-children__wrapper{border-left:2px solid #0000000a;padding:0 3px;overflow:hidden}.nav-subitem{height:32px;font-size:var(--font-sm);padding:0 6px}.nav-subitem:last-child{margin-bottom:0}.nav-subitem .nav-icon{text-align:right}.wui[data-sidebar=collapsed] .nav-item,.wui[data-sidebar=collapsed] .nav-subitem{justify-content:center}.wui[data-sidebar=collapsed] .nav-label,.wui[data-sidebar=collapsed] .nav-caret{display:none}.wui[data-sidebar=collapsed] .nav-icon{min-width:auto;font-size:var(--font-lg)}@media (hover:hover) and (pointer:fine){.nav-item:hover:not([data-active]),.nav-subitem:hover:not([data-active]){color:var(--nav-item-text-hover);background-color:var(--nav-item-bg-hover)}}:root{--tabbar-height:56px}.wui-tabbar{padding:var(--spacing-lg);padding-bottom:calc(var(--spacing-md) + env(safe-area-inset-bottom));z-index:var(--z-tabbar);pointer-events:none;justify-content:center;align-items:center;display:flex;position:fixed;bottom:0;left:0;right:0}.tabbar__list{width:100%;max-width:400px;height:var(--tabbar-height);padding:0 var(--spacing-md);border-radius:var(--radius-full);-webkit-backdrop-filter:blur(16px);pointer-events:auto;background-color:#ffffffd1;border:1px solid #fff9;justify-content:space-between;align-items:center;display:flex;box-shadow:0 1px 2px #0000000d,0 8px 16px #0000000f,0 16px 32px #1018280a,0 0 0 1px #00000005}.tabbar__item{justify-content:center;align-items:center;gap:var(--spacing-sm);color:inherit;flex-direction:column;flex:1;height:100%;text-decoration:none;display:flex}.tabbar__icon{line-height:1;font-family:var(--font-icon);font-size:var(--font-xl);transition:font-weight .2s,transform .3s cubic-bezier(.34,1.56,.64,1)}.tabbar__label{line-height:1;font-family:var(--font-heading);font-size:11px}.tabbar__item[data-active]{color:var(--color-primary)}.tabbar__item[data-active] .tabbar__icon{font-weight:900;transform:translateY(-2px)scale(1.1)}@media (hover:hover) and (pointer:fine){.tabbar__item:not([data-active]):hover{color:var(--color-slate-600)}}.wui-page{min-width:0;height:100%;min-height:0;transition:var(--fade-transition);opacity:0;visibility:hidden;flex-direction:column;display:flex;overflow:hidden}.wui[data-ready=true] .wui-page{opacity:1;visibility:visible}.page-header,.page-footer{justify-content:space-between;align-items:center;gap:var(--spacing-md);padding:0 var(--spacing-xl);z-index:var(--z-above);height:3rem;transition:box-shadow var(--transition-fast), background-color var(--transition-fast);display:flex}.page-body{min-width:0;min-height:0;padding:var(--spacing-xl);flex:1;overflow:auto}.page-header.has-shadow{background-color:var(--color-surface);box-shadow:0 4px 12px #0000000f,0 1px 2px #0000000a}.page-header__main,.page-header__actions{align-items:center;gap:var(--spacing-md);display:flex}.page-header__main{flex:1;min-width:0}.page-header__actions{flex-shrink:0}.page-title{padding:0 var(--spacing-sm);font-family:var(--font-heading);font-size:var(--font-size-title);white-space:nowrap;text-overflow:ellipsis;margin:0;font-weight:600;overflow:hidden}.page-header__actions .btn--circle{font-size:var(--font-lg)!important}.page-scroll-sentinel{visibility:hidden;pointer-events:none;height:1px;margin-top:-1px}}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer shell{.wui{grid-template-columns:1fr}.wui .wui-content{background-color:#0000;border-color:#0000;border-radius:0;margin:0}}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { n as RegionsConfig } from "../types-ayz5MABs.js";
|
|
2
|
+
import { n as ShellLayoutStore, t as BaseShell } from "../base.shell-BD3tzDD9.js";
|
|
3
|
+
//#region src/shell/mobile.d.ts
|
|
4
|
+
declare class MobileShell extends BaseShell {
|
|
5
|
+
private tabbar;
|
|
6
|
+
private viewport;
|
|
7
|
+
protected readonly layoutStore: ShellLayoutStore;
|
|
8
|
+
constructor(config?: RegionsConfig);
|
|
9
|
+
protected render(): void;
|
|
10
|
+
protected onShellMount(): void;
|
|
11
|
+
protected onShellDestroy(): void;
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
export { MobileShell };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import './index.css';
|
|
2
|
+
import{a as e,i as t,n,r}from"../viewport-BEoQW1zd.js";var i=class extends t{tabbar;viewport;layoutStore=new r;constructor(t={}){super(),this.tabbar=new e(t.tabbar),this.viewport=new n(this.layoutStore)}render(){}onShellMount(){this.wuiShell.injectContext(this.ctx).mount(this.element),this.tabbar.injectContext(this.ctx).mount(this.element),this.viewport.observe()}onShellDestroy(){this.tabbar.destroy(),this.viewport.disconnect()}};export{i as MobileShell};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
//#region src/types.d.ts
|
|
2
|
+
type ThemeMode = 'light' | 'dark' | 'system';
|
|
3
|
+
type ViewportSize = 'sm' | 'md' | 'lg';
|
|
4
|
+
type SidebarState = 'expanded' | 'collapsed' | 'overlay' | 'hidden';
|
|
5
|
+
interface RegionBaseConfig {
|
|
6
|
+
readonly enabled?: boolean;
|
|
7
|
+
}
|
|
8
|
+
interface SidebarConfig extends RegionBaseConfig {
|
|
9
|
+
readonly menu?: NavItem[];
|
|
10
|
+
}
|
|
11
|
+
interface TabbarConfig extends RegionBaseConfig {
|
|
12
|
+
readonly menu?: NavItem[];
|
|
13
|
+
}
|
|
14
|
+
interface RegionsConfig {
|
|
15
|
+
readonly sidebar?: SidebarConfig;
|
|
16
|
+
readonly tabbar?: TabbarConfig;
|
|
17
|
+
}
|
|
18
|
+
interface BaseNavItem {
|
|
19
|
+
label: string;
|
|
20
|
+
icon?: string;
|
|
21
|
+
hidden?: boolean;
|
|
22
|
+
disabled?: boolean;
|
|
23
|
+
badge?: string | number;
|
|
24
|
+
}
|
|
25
|
+
interface NavLink extends BaseNavItem {
|
|
26
|
+
type: 'item';
|
|
27
|
+
path: string;
|
|
28
|
+
exact?: boolean;
|
|
29
|
+
}
|
|
30
|
+
interface NavGroup extends BaseNavItem {
|
|
31
|
+
type: 'group';
|
|
32
|
+
children: NavItem[];
|
|
33
|
+
defaultOpen?: boolean;
|
|
34
|
+
}
|
|
35
|
+
type Role = 'admin' | 'user' | 'guest';
|
|
36
|
+
interface WithPermission {
|
|
37
|
+
roles?: Role[];
|
|
38
|
+
}
|
|
39
|
+
type NavItem = (NavLink & WithPermission) | (NavGroup & WithPermission);
|
|
40
|
+
//#endregion
|
|
41
|
+
export { ViewportSize as a, ThemeMode as i, RegionsConfig as n, SidebarState as r, NavItem as t };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import{BaseComponent as e,Store as t}from"@wuisdk/core";import{dom as n}from"@wuisdk/utils";import{WuiActionMenu as r}from"@wuisdk/comps/dropdown";var i=class extends e{content=n.createElement(`main`,{className:`wui-content`});loader=n.createElement(`div`,{className:`wui-loader`});constructor(){super(`div`,{className:`wui-shell`})}render(){let e=n.createElement(`div`,{className:`wui-spinner`}),t=Array.from({length:12},()=>n.createElement(`div`));e.append(...t),this.loader.replaceChildren(e),this.element.append(this.content,this.loader)}onDestroy(){this.content.remove(),this.loader.remove()}get wuiContent(){return this.content}};const a=(e,t)=>{if(!e||!t)return;let n=`admin`,r=document.createDocumentFragment();t.forEach(e=>{e.roles&&!e.roles.includes(n)||e.hidden||(e.type===`item`&&r.append(o(e)),e.type===`group`&&r.append(s(e,n)))}),e.replaceChildren(r)},o=(e,t=!1)=>{let r=n.createElement(`a`,{className:t?`nav-subitem`:`nav-item`,attributes:{href:e.path??`#`},dataset:{wuiLink:``}}),i=n.createElement(`span`,{className:`nav-icon`},e.icon??``),a=n.createElement(`span`,{className:`nav-label`},e.label??``);return r.append(i,a),e.disabled&&r.classList.add(`is-disabled`),r},s=(e,t)=>{let r=n.createElement(`div`,{className:`nav-group`,dataset:{open:String(e.defaultOpen||!1)}}),i=n.createElement(`button`,{className:[`nav-item`,`has-children`]}),a=n.createElement(`span`,{className:`nav-icon`},e.icon??``),c=n.createElement(`span`,{className:`nav-label`},e.label??``),l=n.createElement(`span`,{className:`nav-caret`},``);i.append(a,c,l);let u=n.createElement(`div`,{className:`nav-children`}),d=n.createElement(`div`,{className:`nav-children__wrapper`});return e.children.forEach(e=>{e.roles&&!e.roles.includes(t)||(e.type===`item`?d.append(o(e,!0)):d.append(s(e,t)))}),u.appendChild(d),r.append(i,u),r};var c=`<div class="sidebar__header">
|
|
2
|
+
<div class="sidebar__logo">
|
|
3
|
+
<i class="fa-regular fa-fire"></i>
|
|
4
|
+
<span class="app-name">App Name</span>
|
|
5
|
+
</div>
|
|
6
|
+
<button class="sidebar__toggle">☰</button>
|
|
7
|
+
</div>
|
|
8
|
+
<nav class="sidebar__nav"></nav>
|
|
9
|
+
<div class="sidebar__footer">
|
|
10
|
+
<button class="profile">
|
|
11
|
+
<div class="profile__avatar"></div>
|
|
12
|
+
<div class="profile__info">
|
|
13
|
+
<div class="name">Display Name</div>
|
|
14
|
+
<div class="unit">Department Name</div>
|
|
15
|
+
</div>
|
|
16
|
+
</button>
|
|
17
|
+
</div>`,l=class extends e{config;navLink=[];profileAction=null;constructor(e={}){super(`aside`,{className:`wui-sidebar`}),this.config=e}render(){let e=n.renderTemplate(c);this.element.replaceChildren(e)}onMount(){this.setupNavMenu(),this.setProfileAction(),this.element.addEventListener(`click`,this.handleClick,{signal:this.signal}),this.ctx.events.on(`sys:route-changed`,e=>{this.setNavActive(e.path)},this.signal);let e=this.element.querySelector(`.app-name`);e&&(e.textContent=this.ctx.config.appName),this.ctx.stores.auth?.subscribe(e=>e.user,e=>this.setProfile(e),{signal:this.signal}),this.ctx.stores.fiber.subscribe(e=>e.user,e=>this.setAccess(e),{signal:this.signal})}onUnmount(){this.profileAction?.destroy(),this.profileAction=null}setNavActive(e){this.navLink.forEach(t=>{let n=t.getAttribute(`href`),r=n===e||n===`/${e}`;t.toggleAttribute(`data-active`,r)})}setupNavMenu(){let e=this.element.querySelector(`nav`);e&&this.config.menu&&(a(e,this.config.menu),this.navLink=Array.from(e.querySelectorAll(`[data-wui-link]`)))}handleClick=e=>{let t=e.target;if(t.closest(`.sidebar__toggle`)){this.ctx.stores.layout.toggleSidebar();return}let n=t.closest(`.nav-item.has-children`);if(n){e.preventDefault();let t=n.closest(`.nav-group`);if(t){let e=t.dataset.open===`true`;t.dataset.open=String(!e)}}};setProfile(e){if(!e)return;let t=this.element.querySelector(`.profile__avatar`);if(t&&e.picture){let r=n.createElement(`img`,{attributes:{src:e.picture}});t.replaceChildren(r)}let r=this.element.querySelector(`.profile__info .name`),i=this.element.querySelector(`.profile__info .unit`);r&&(r.textContent=e.name),i&&(i.textContent=e.unit)}setAccess(e){if(!e)return;let t=this.element.querySelector(`.profile__avatar`);if(t){let e=n.createElement(`img`,{attributes:{src:`https://cdn.jsdelivr.net/gh/wkrdev/assets/img/icon/icon-03.png`}});t.replaceChildren(e)}let r=this.element.querySelector(`.profile__info .name`),i=this.element.querySelector(`.profile__info .unit`);r&&(r.textContent=e.full_name),i&&(i.textContent=e.sect?e.sect_name:e.dvsn_name)}setProfileAction(){let e=[{id:`profile`,label:`โปรไฟล์`,icon:``},{id:`setting`,label:`การตั้งค่า`,icon:``},{id:`manual`,label:`ช่วยเหลือ`,icon:``},{id:`hwlink`,label:`HwLink`,icon:``},{divider:!0},{id:`logout`,label:`ลงชื่อออก`,icon:``,onClick:this.handleLogout}],t=this.element.querySelector(`.profile`);t&&(this.profileAction=new r({trigger:t,items:e,placement:`top-start`,signal:this.signal}).injectContext(this.ctx))}handleLogout=async()=>{await this.ctx.ui.dialog.confirm(`ยืนยัน.! การออกจากระบบ`)&&(this.ctx.plugins.auth&&this.ctx.plugins.auth.logout(),this.ctx.plugins.fiber&&this.ctx.plugins.fiber.logout())}},u=`<div class="tabbar__list"></div>`,d=class extends e{config;navLink=[];constructor(e={}){super(`nav`,{className:`wui-tabbar`}),this.config=e}render(){let e=n.renderTemplate(u);this.element.replaceChildren(e)}onMount(){this.setupTabMenu(),this.ctx.events.on(`sys:route-changed`,e=>{this.setNavActive(e.path)},this.signal)}setNavActive(e){this.navLink.forEach(t=>{let n=t.getAttribute(`href`),r=n===e||n===`/${e}`;t.toggleAttribute(`data-active`,r)})}setupTabMenu(){let e=this.element.querySelector(`.tabbar__list`);if(e&&this.config.menu){let t=document.createDocumentFragment();this.config.menu.forEach(e=>{if(e.type!==`item`)return;let r=n.createElement(`a`,{className:`tabbar__item`,attributes:{href:e.path,"data-wui-link":``}},n.createElement(`span`,{className:`tabbar__icon`},e.icon),n.createElement(`span`,{className:`tabbar__label`},e.label));t.appendChild(r)}),e.replaceChildren(t),this.navLink=Array.from(e.querySelectorAll(`[data-wui-link]`))}}},f=class extends e{wuiShell;constructor(){super(`div`,{className:`wui`}),this.wuiShell=new i}onMount(){this.ctx.registerStore(`layout`,this.layoutStore),this.setupLayoutStateListener(),this.setupSystemStateListener(),this.ctx.events.on(`sys:page-mounted`,e=>{this.layoutStore.updateLayout({shell:e.shell})}),this.onShellMount()}onDestroy(){this.wuiShell.destroy(),this.onShellDestroy()}get wuiRoot(){return this.element}get wuiContent(){return this.wuiShell.wuiContent}setupLayoutStateListener(){let e=this.layoutStore.state;Object.entries(e).forEach(([e,t])=>{e!==`sidebarPref`&&(this.element.dataset[e]=String(t))}),this.layoutStore.subscribe(e=>e,(e,t)=>{Object.entries(e).forEach(([e,n])=>{e!==`sidebarPref`&&(!t||t[e]!==n)&&(this.element.dataset[e]=String(n))})},{isEqual:(e,t)=>e===t?!0:!e||!t?!1:Object.keys(e).every(n=>e[n]===t[n]),signal:this.signal})}setupSystemStateListener(){let e=this.ctx.stores.sys,t=e.state;this.element.dataset.loading=String(t.loading),this.element.dataset.ready=String(t.ready),e.subscribe(e=>({loading:e.loading,ready:e.ready}),(e,t)=>{t.loading!==e.loading&&(this.element.dataset.loading=String(e.loading)),t.ready!==e.ready&&(this.element.dataset.ready=String(e.ready))},{isEqual:(e,t)=>e.loading===t.loading&&e.ready===t.ready,signal:this.signal})}},p=class{store=new t({theme:`system`,shell:`blank`,viewport:`sm`,sidebar:`hidden`});get state(){return this.store.getState()}subscribe(e,t,n){return this.store.subscribe(e,t,n)}updateLayout(e){this.store.setState(t=>{let n={...t,...e};return(e.shell!==void 0||e.viewport!==void 0)&&(n.sidebar=this.calcSidebarState(n.shell,n.viewport,n.sidebarPref)),n})}toggleSidebar(){this.store.setState(e=>{let{viewport:t,sidebar:n,shell:r,sidebarPref:i}=e;if(r!==`dashboard`)return{};let a,o=i;return t===`sm`?a=n===`hidden`?`overlay`:`hidden`:(a=n===`expanded`?`collapsed`:`expanded`,o=a),{sidebar:a,sidebarPref:o}})}calcSidebarState(e,t,n){return e!==`dashboard`||t===`sm`?`hidden`:n&&[`expanded`,`collapsed`].includes(n)?n:t===`md`?`collapsed`:`expanded`}},m=class{store;abortController=null;mediaQueries;constructor(e,t={md:`(min-width: 600px)`,lg:`(min-width: 800px)`}){this.store=e,this.mediaQueries={md:window.matchMedia(t.md),lg:window.matchMedia(t.lg)}}observe(){if(this.abortController)return;this.abortController=new AbortController;let{signal:e}=this.abortController,t=()=>{let e=`sm`;this.mediaQueries.lg.matches?e=`lg`:this.mediaQueries.md.matches&&(e=`md`),this.store.state.viewport!==e&&this.store.updateLayout({viewport:e})};Object.values(this.mediaQueries).forEach(n=>{n.addEventListener(`change`,t,{signal:e})}),t()}disconnect(){this.abortController&&=(this.abortController.abort(),null)}},h=class extends e{isTicking=!1;constructor(){super(`div`,{className:`wui-viewport`})}render(){this.updateDimensions()}onMount(){window.addEventListener(`resize`,this.handleResize,{signal:this.signal})}handleResize=()=>{this.isTicking||=(window.requestAnimationFrame(()=>{this.updateDimensions(),this.isTicking=!1}),!0)};updateDimensions(){let e=window.innerWidth,t=window.innerHeight;this.element.textContent=`${e}x${t}`}};export{d as a,f as i,m as n,l as o,p as r,h as t};
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wuisdk/shell",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": {
|
|
7
|
+
"import": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts"
|
|
9
|
+
},
|
|
10
|
+
"./*": {
|
|
11
|
+
"import": "./dist/*/index.js",
|
|
12
|
+
"types": "./dist/*/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"access": "public"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsdown --minify",
|
|
23
|
+
"dev": "tsdown --no-clean --watch"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@wuisdk/comps": "*",
|
|
27
|
+
"@wuisdk/core": "*",
|
|
28
|
+
"@wuisdk/utils": "*",
|
|
29
|
+
"@wuisdk/plugin-auth": "*",
|
|
30
|
+
"@wuisdk/plugin-fiber": "*"
|
|
31
|
+
},
|
|
32
|
+
"author": "hs3lcs@gmail.com",
|
|
33
|
+
"license": "MIT"
|
|
34
|
+
}
|