react-bwin 0.3.4 → 0.3.5-dev.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 CHANGED
@@ -1,8 +1,13 @@
1
1
  ## React Binary Window
2
2
 
3
+ [![Publish to npm](https://github.com/bhjsdev/react-bwin/actions/workflows/publish.yml/badge.svg)](https://github.com/bhjsdev/react-bwin/actions/workflows/publish.yml)
4
+ [![npm version](https://img.shields.io/npm/v/react-bwin)](https://www.npmjs.com/package/react-bwin)
5
+
3
6
  A React-based tiling window manager featuring resizable panes, drag-and-drop, and more. Built on top of the [Binary Window](https://github.com/bhjsdev/bwin) library.
4
7
 
5
- [Documentation](https://bhjsdev.github.io/bwin-docs/)
8
+ [![A react-bwin tiling layout with resizable panes showing charts and a data table](docs/screenshot.png)](https://bhjsdev.github.io/bwin-docs)
9
+
10
+ [Documentation](https://bhjsdev.github.io/bwin-docs/react/get-started)
6
11
 
7
12
  ### Development
8
13
 
@@ -15,10 +20,12 @@ This starts the dev server with internal test pages at `http://localhost:5173`.
15
20
 
16
21
  ### Examples
17
22
 
18
- See the `examples/` directory for standalone apps. To run one:
23
+ See the `examples/` directory for standalone apps. They depend on the library's built
24
+ output, so build it first, then run an example (e.g. `dashboard`):
19
25
 
20
26
  ```bash
21
- cd examples/dashboard
22
27
  pnpm install
28
+ pnpm build
29
+ cd examples/dashboard
23
30
  pnpm dev
24
31
  ```
@@ -1,6 +1,8 @@
1
1
  declare module 'react-bwin' {
2
2
  export const BUILTIN_ACTIONS: Action[]
3
- export const Window: React.FC<WindowProps>
3
+ export const Window: React.ForwardRefExoticComponent<
4
+ WindowProps & React.RefAttributes<WindowHandle>
5
+ >
4
6
  }
5
7
 
6
8
  declare global {
@@ -60,6 +62,7 @@ declare global {
60
62
  width?: number
61
63
  height?: number
62
64
  fitContainer?: boolean
65
+ theme?: string
63
66
  title?: React.ReactNode
64
67
  content?: React.ReactNode
65
68
  children?: ConfigNode[]
@@ -71,17 +74,20 @@ declare global {
71
74
  windowElement: HTMLElement
72
75
  containerElement: HTMLElement
73
76
  sillElement: HTMLElement
77
+ theme: string
74
78
  mount(container: HTMLElement): void
75
79
  enableFeatures(): void
76
80
  fit(): void
77
81
  addPane(targetPaneId: string, fields: PaneFields): Sash
78
82
  removePane(targetPaneId: string): void
83
+ setTheme(theme: string): void
79
84
  }
80
85
 
81
86
  type WindowHandle = {
82
87
  addPane: (targetPaneId: string, fields: PaneFields) => void
83
88
  removePane: (targetPaneId: string) => void
84
89
  fit: () => void
90
+ setTheme: (theme: string) => void
85
91
  }
86
92
 
87
93
  type WindowProps = Omit<ConfigRoot, 'children'> & {
@@ -1021,10 +1021,12 @@ var ue = t((t, c) => {
1021
1021
  }, []), r(c, () => ({
1022
1022
  fit: h.fit.bind(h),
1023
1023
  removePane: h.removePane.bind(h),
1024
+ setTheme: h.setTheme.bind(h),
1024
1025
  addPane: b
1025
1026
  }), []);
1026
1027
  let v = /* @__PURE__ */ e.createElement("bw-window", {
1027
1028
  "root-sash-id": h.rootSash.id,
1029
+ theme: h.theme || void 0,
1028
1030
  style: {
1029
1031
  width: h.rootSash.width,
1030
1032
  height: h.rootSash.height
@@ -1046,6 +1048,6 @@ var ue = t((t, c) => {
1046
1048
  }]);
1047
1049
  }
1048
1050
  return /* @__PURE__ */ e.createElement(e.Fragment, null, y, d?.map((e) => s(e.node, e.container)));
1049
- }), de = "0.3.4";
1051
+ }), de = "0.3.5-dev.0";
1050
1052
  //#endregion
1051
1053
  export { Y as BUILTIN_ACTIONS, ue as Window, de as version };
@@ -5,4 +5,4 @@ top: ${e.style.top}
5
5
  left: ${e.style.left}
6
6
  width: ${e.style.width}
7
7
  height: ${e.style.height}
8
- `.trim(),t}var B={createWindow({theme:e}={}){let t=document.createElement(`bw-window`);return t.style.width=`${this.rootSash.width}px`,t.style.height=`${this.rootSash.height}px`,t.setAttribute(`root-sash-id`,this.rootSash.id),e&&t.setAttribute(`theme`,e),t},glaze(){this.rootSash.walk(e=>{let t=null;e.children.length>0?(t=this.createMuntin(e),this.onMuntinCreate(t,e),this.windowElement.append(t)):(t=this.createPane(e),this.onPaneCreate(t,e),this.windowElement.prepend(t)),e.domNode=t})},update(){this.windowElement.style.width=`${this.rootSash.width}px`,this.windowElement.style.height=`${this.rootSash.height}px`;let e=this.rootSash.getAllIds(),t=[];this.windowElement.querySelectorAll(`[sash-id]`).forEach(n=>{let r=n.getAttribute(`sash-id`);t.push(r),e.includes(r)||n.remove()}),this.rootSash.walk(e=>{e.children.length>0?t.includes(e.id)?(this.updateMuntin(e),this.onMuntinUpdate(e.domNode,e)):(e.domNode=this.createMuntin(e),this.windowElement.append(e.domNode)):t.includes(e.id)?(this.updatePane(e),this.onPaneUpdate(e.domNode,e)):(e.domNode||=this.createPane(e),this.windowElement.prepend(e.domNode))})}},V={muntinSize:4,createMuntin(e){let t=document.createElement(`bw-muntin`),n=e.leftChild,r=e.topChild;return n?(t.style.width=`${this.muntinSize}px`,t.style.height=`${e.height}px`,t.style.top=`${e.top}px`,t.style.left=`${e.left+n.width-this.muntinSize/2}px`,t.setAttribute(`vertical`,``)):r&&(t.style.width=`${e.width}px`,t.style.height=`${this.muntinSize}px`,t.style.top=`${e.top+r.height-this.muntinSize/2}px`,t.style.left=`${e.left}px`,t.setAttribute(`horizontal`,``)),t.setAttribute(`sash-id`,e.id),e.store.resizable===!1&&t.setAttribute(`resizable`,`false`),t},onMuntinCreate(e,t){},updateMuntin(e){let t=e.domNode,n=e.leftChild,r=e.topChild;n?(t.style.height=`${e.height}px`,t.style.top=`${e.top}px`,t.style.left=`${e.left+n.width-this.muntinSize/2}px`):r&&(t.style.width=`${e.width}px`,t.style.top=`${e.top+r.height-this.muntinSize/2}px`,t.style.left=`${e.left}px`)},onMuntinUpdate(e,t){}},H={fitContainer:!1,fit(){this.rootSash.width=this.containerElement.clientWidth,this.rootSash.height=this.containerElement.clientHeight,this.update()},enableFitContainer(){new ResizeObserver(e=>{requestAnimationFrame(()=>{for(let t of e)t.target===this.containerElement&&this.fitContainer&&this.fit()})}).observe(this.containerElement)}},U={activeMuntinSash:null,isResizeStarted:!1,isDropStarted:!1,lastX:0,lastY:0,applyResizeStyles(){this.activeMuntinSash.domNode.hasAttribute(`vertical`)?document.body.classList.add(`body--bw-resize-x`):this.activeMuntinSash.domNode.hasAttribute(`horizontal`)&&document.body.classList.add(`body--bw-resize-y`)},revertResizeStyles(){document.body.classList.remove(`body--bw-resize-x`),document.body.classList.remove(`body--bw-resize-y`)},enableResize(){document.addEventListener(`mousedown`,e=>{if(e.target.tagName!==`BW-MUNTIN`||e.target.getAttribute(`resizable`)===`false`)return;let t=e.target.getAttribute(`sash-id`);this.activeMuntinSash=this.rootSash.getById(t),this.activeMuntinSash&&(this.isResizeStarted=!0,this.lastX=e.pageX,this.lastY=e.pageY,this.applyResizeStyles())}),document.addEventListener(`mousemove`,e=>{if(!this.isResizeStarted||!this.activeMuntinSash)return;let[t,n,r,i]=this.activeMuntinSash.getChildren(),a=this.activeMuntinSash.isLeftRightSplit(),o=this.activeMuntinSash.isTopBottomSplit();if(a&&i&&n){let t=e.pageX-this.lastX,r=i.width+t,a=n.width-t;if(t>0&&a<=n.calcMinWidth()||t<0&&r<=i.calcMinWidth())return;i.width=r,n.width=a,n.left+=t,this.update(),this.lastX=e.pageX}else if(o&&t&&r){let n=e.pageY-this.lastY,i=t.height+n,a=r.height-n;if(n>0&&a<=r.calcMinHeight()||n<0&&i<=t.calcMinHeight())return;t.height=i,r.height=a,r.top+=n,this.update(),this.lastY=e.pageY}}),document.addEventListener(`mouseup`,()=>{this.isResizeStarted=!1,this.activeMuntinSash=null,this.revertResizeStyles()})}},ae={activeDropPaneEl:null,onPaneDrop(e,t){},enableDrop(){this.windowElement.addEventListener(`dragover`,e=>{e.preventDefault();let t=e.target.matches(`bw-pane`)?e.target:e.target.closest(`bw-pane`);if(!t||(t!==this.activeDropPaneEl&&(this.activeDropPaneEl&&this.activeDropPaneEl.removeAttribute(`drop-area`),this.activeDropPaneEl=t),t.getAttribute(`can-drop`)===`false`))return;let n=C(t,e);t.setAttribute(`drop-area`,n)}),this.windowElement.addEventListener(`dragleave`,e=>{e.currentTarget.contains(e.relatedTarget)&&e.currentTarget!==e.relatedTarget||(this.activeDropPaneEl&&=(this.activeDropPaneEl.removeAttribute(`drop-area`),null))}),this.windowElement.addEventListener(`drop`,e=>{if(!this.activeDropPaneEl||this.activeDropPaneEl.getAttribute(`can-drop`)===`false`)return;let t=this.activeDropPaneEl.getAttribute(`sash-id`),n=this.rootSash.getById(t);this.onPaneDrop(e,n),typeof n.store.onDrop==`function`&&n.store.onDrop(e,n),this.activeDropPaneEl.removeAttribute(`drop-area`),this.activeDropPaneEl=null})}},W=!1,G=class{windowElement=null;containerElement=null;debug=W;constructor(e){let t=null;e instanceof k?(t=e,this.rootSash=e):(t=new ie(e),this.rootSash=t.buildSashTree({resizeStrategy:t.resizeStrategy})),this.fitContainer=t.fitContainer,this.theme=t.theme}frame(e){this.containerElement=e,this.windowElement=this.createWindow({theme:this.theme}),this.glaze(),this.containerElement.append(this.windowElement)}enableFeatures(){this.enableResize(),this.enableDrop(),this.fitContainer&&this.enableFitContainer()}mount(e){this.frame(e),this.enableFeatures()}static assemble(...e){e.forEach(e=>{g(this.prototype,e)})}};G.assemble(B,V,R,H,ae,U);var K={label:``,className:`bw-glass-action--close`,onClick:(e,t)=>{let n=L(e.target);t.removePane(n)}},q={label:``,className:`bw-glass-action--minimize`,onClick:(e,t)=>{let n=t.sillElement;if(!n)throw Error(`[bwin] Sill element not found when minimizing`);let r=v(`<button class="bw-minimized-glass" />`);n.append(r);let i=e.target.closest(`bw-pane`),a=e.target.closest(`bw-glass`),o=i.getAttribute(`sash-id`),s=i.getAttribute(`position`);r.bwGlassElement=a,r.bwOriginalPosition=s,r.bwOriginalBoundingRect=y(i),r.bwOriginalSashId=o,t.removePane(o)}},J={label:``,className:`bw-glass-action--maximize`,onClick:e=>{let t=e.target.closest(`bw-pane`);t.hasAttribute(`maximized`)?(t.removeAttribute(`maximized`),t.style.left=`${t.bwOriginalBoundingRect.left}px`,t.style.top=`${t.bwOriginalBoundingRect.top}px`,t.style.width=`${t.bwOriginalBoundingRect.width}px`,t.style.height=`${t.bwOriginalBoundingRect.height}px`):(t.setAttribute(`maximized`,``),t.bwOriginalBoundingRect=y(t),t.style.left=`0`,t.style.top=`0`,t.style.width=`100%`,t.style.height=`100%`)}};function oe(e,t){let n=e.left+e.width,r=e.top+e.height,i=t.left+t.width,a=t.top+t.height;if(e.left>=i||t.left>=n||e.top>=a||t.top>=r)return null;let o=Math.max(e.left,t.left),s=Math.max(e.top,t.top),c=Math.min(n,i),l=Math.min(r,a);return{left:o,top:s,width:c-o,height:l-s}}var Y=[q,J,K],se={enableActions(){this.handleMinimizedGlassClick(),this.observeActionButtons()},restoreGlass(e){let t=e.bwOriginalBoundingRect,n=0,r=null;if(this.windowElement.querySelectorAll(`bw-pane`).forEach(e=>{let i=oe(t,y(e));if(i){let t=i.width*i.height;t>n&&(n=t,r=e)}}),r){let n=e.bwOriginalPosition,i=y(r),a=r.getAttribute(`sash-id`),o=this.rootSash.getById(a),s=0;if(n===b.Left||n===b.Right)s=i.width-t.width<o.minWidth?i.width/2:t.width;else if(n===b.Top||n===b.Bottom)s=i.height-t.height<o.minHeight?i.height/2:t.height;else throw Error(`[bwin] Invalid position when restoring glass`);let c=e.bwOriginalSashId;this.addPane(r.getAttribute(`sash-id`),{id:c,position:n,size:s}).domNode.append(e.bwGlassElement)}},handleMinimizedGlassClick(){this.sillElement.addEventListener(`click`,e=>{if(!e.target.matches(`.bw-minimized-glass`))return;let t=e.target;this.restoreGlass(t),t.remove()})},updateDisabledStateOfActionButtons(){this.updateDisabledState(`.bw-glass-action--close`),this.updateDisabledState(`.bw-glass-action--minimize`),this.updateDisabledState(`.bw-glass-action--maximize`)},updateDisabledState(e){if(this.windowElement.querySelectorAll(`bw-pane`).length===1){let t=this.windowElement.querySelector(e);t&&t.setAttribute(`disabled`,``)}else this.windowElement.querySelectorAll(e).forEach(e=>{e.removeAttribute(`disabled`)})},getMinimizedGlassElementBySashId(e){let t=this.windowElement.querySelectorAll(`.bw-minimized-glass`);return Array.from(t).find(t=>t.bwOriginalSashId===e)},observeActionButtons(){this.updateDisabledStateOfActionButtons(),new MutationObserver(e=>{e.forEach(e=>{e.type===`childList`&&this.updateDisabledStateOfActionButtons()})}).observe(this.windowElement,{childList:!0})}},X={title:null,content:null,tabs:[],actions:void 0,draggable:!0},Z=class{domNode;constructor({title:e=X.title,content:t=X.content,tabs:n=X.tabs,actions:r=X.actions,draggable:i=X.draggable,sash:a,binaryWindow:o}){this.title=e,this.content=t,this.tabs=n,this.actions=r,this.sash=a,this.draggable=i,this.binaryWindow=o,this.build()}build(){let e=document.createElement(`bw-glass-header`);if(Array.isArray(this.tabs)&&this.tabs.length>0)e.append(this.createTabs());else if(this.title){let t=document.createElement(`bw-glass-title`);t.append(v(this.title)),e.append(t)}e.setAttribute(`can-drag`,this.draggable),e.append(this.createActions());let t=document.createElement(`bw-glass-content`),n=v(this.content);n&&t.append(n),this.domNode=document.createElement(`bw-glass`),this.domNode.append(e,t)}createTabs(){let e=document.createElement(`bw-glass-tab-container`);for(let t of this.tabs){let n=v(`<button class="bw-glass-tab">${t?.label??t}</button>`);e.append(n)}return e}createActions(){let e=document.createElement(`bw-glass-action-container`),t=this.actions===void 0?Y:Array.isArray(this.actions)?this.actions:[];for(let n of t){let t=n?.label??n,r=v(`<button class="${n.className?`bw-glass-action ${n.className}`:`bw-glass-action`}">${t}</button>`);typeof n.onClick==`function`&&r.addEventListener(`click`,e=>{n.onClick(e,this.binaryWindow)}),e.append(r)}return e}get contentElement(){return this.domNode.querySelector(`bw-glass-content`)}get headerElement(){return this.domNode.querySelector(`bw-glass-header`)}},ce={activeDragGlassEl:null,activeDragGlassPaneCanDrop:!1,onPaneDrop(e,t){if(!this.activeDragGlassEl)return;let n=this.activeDropPaneEl.getAttribute(`drop-area`);if(n===`center`){let e=this.activeDragGlassEl.closest(`bw-pane`);this.swapPanes(e,this.activeDropPaneEl);return}else{let e=L(this.activeDragGlassEl);this.removePane(e),this.addPane(t.id,{position:n,id:e}).domNode.append(this.activeDragGlassEl)}},enableDrag(){document.addEventListener(`mousedown`,e=>{if(e.button!==0||!e.target.matches(`bw-glass-header`))return;if(e.target.getAttribute(`can-drag`)===`false`){e.preventDefault();return}let t=e.target.closest(`bw-glass`);t.setAttribute(`draggable`,!0),this.activeDragGlassEl=t}),document.addEventListener(`mouseup`,()=>{this.activeDragGlassEl&&=(this.activeDragGlassEl.removeAttribute(`draggable`),null)}),this.windowElement.addEventListener(`dragstart`,e=>{if(!(e.target instanceof HTMLElement)||!e.target.matches(`bw-glass`)||!this.activeDragGlassEl)return;e.dataTransfer.effectAllowed=`move`;let t=this.activeDragGlassEl.closest(`bw-pane`);this.activeDragGlassPaneCanDrop=t.getAttribute(`can-drop`)!==`false`,t.setAttribute(`can-drop`,!1)}),this.windowElement.addEventListener(`dragend`,()=>{this.activeDragGlassEl&&=(this.activeDragGlassEl.removeAttribute(`draggable`),this.activeDragGlassEl.closest(`bw-pane`).setAttribute(`can-drop`,this.activeDragGlassPaneCanDrop),null)})}},le={trimMuntin(e){e.hasAttribute(`vertical`)?(e.style.top=`${parseFloat(e.style.top)+this.muntinSize/2}px`,e.style.height=`${parseFloat(e.style.height)-this.muntinSize}px`):e.hasAttribute(`horizontal`)&&(e.style.left=`${parseFloat(e.style.left)+this.muntinSize/2}px`,e.style.width=`${parseFloat(e.style.width)-this.muntinSize}px`)},onMuntinCreate(e){this.trimMuntin(e)},onMuntinUpdate(e){this.trimMuntin(e)}},Q=class extends G{sillElement=null;frame(){super.frame(...arguments);let e=v(`<bw-sill />`);this.windowElement.append(e),this.sillElement=e}enableFeatures(){super.enableFeatures(),this.enableDrag(),this.enableActions()}onPaneCreate(e,t){let n=new Z({...t.store,sash:t,binaryWindow:this});e.innerHTML=``,e.append(n.domNode),this.debug&&n.contentElement.prepend(`${t.id}`)}onPaneUpdate(){}addPane(e,t){let{position:n,size:r,id:i,...a}=t,o=super.addPane(e,{position:n,size:r,id:i}),s=new Z({...a,sash:o,binaryWindow:this});return o.domNode.append(s.domNode),o}setTheme(e){if(!e){this.theme=``,this.windowElement.removeAttribute(`theme`);return}this.theme=e,this.windowElement.setAttribute(`theme`,e)}removePane(e){if(this.windowElement.querySelector(`[sash-id="${e}"]`)){super.removePane(e);return}let t=this.getMinimizedGlassElementBySashId(e);t&&t.remove()}};Q.assemble(ce,le,se);var $=4;function ue({sash:e}){let n=(0,t.useRef)(),r=e.leftChild,i=e.topChild,a,o,s,c,l,u;return r?(a=$,o=e.height-$,s=e.top+$/2,c=e.left+r.width-$/2,l=!0):i&&(a=e.width-$,o=$,s=e.top+i.height-$/2,c=e.left+$/2,u=!0),(0,t.useEffect)(()=>{e.domNode=n.current},[]),t.default.createElement(`bw-muntin`,{"sash-id":e.id,style:{width:a,height:o,top:s,left:c},vertical:l,horizontal:u,resizable:e.store?.resizable===!1?`false`:`true`,ref:n})}function de({sash:e,bwin:n}){let r=(0,t.useRef)(),{left:i,top:a,width:o,height:s,id:c,position:l}=e;(0,t.useEffect)(()=>{e.domNode=r.current},[]);let u=e.store?.actions===void 0?Y:Array.isArray(e.store.actions)?e.store.actions:[];return t.default.createElement(`bw-pane`,{"sash-id":c,position:l,style:{left:i,top:a,width:o,height:s},"can-drop":e.store?.droppable===!1?`false`:`true`,ref:r},t.default.createElement(`bw-glass`,null,t.default.createElement(`bw-glass-header`,{"can-drag":e.store?.draggable===!1?`false`:`true`},e.store?.title&&t.default.createElement(`bw-glass-title`,null,e.store.title),u.length>0&&t.default.createElement(`bw-glass-action-container`,null,u.map((e,r)=>{let i=e.className?`bw-glass-action ${e.className}`:`bw-glass-action`;return t.default.createElement(`button`,{className:i,key:r,onClick:t=>e.onClick(t,n)},e.label)}))),t.default.createElement(`bw-glass-content`,null,e.store?.content)))}var fe=(0,t.forwardRef)((e,r)=>{let i=(0,t.useRef)(),a=(0,t.useRef)(),[o,s]=(0,t.useState)(),{panes:c,...l}=e,u=new Q({...l,children:c}),d=[],f=[];u.rootSash.walk(e=>{e.children.length>0?d.push(e):f.push(e)}),(0,t.useEffect)(()=>{let e=i.current;e?.parentElement&&(u.windowElement=e,u.containerElement=e.parentElement,u.sillElement=a.current,u.enableFeatures())},[]),(0,t.useImperativeHandle)(r,()=>({fit:u.fit.bind(u),removePane:u.removePane.bind(u),addPane:h}),[]);let p=t.default.createElement(`bw-window`,{"root-sash-id":u.rootSash.id,style:{width:u.rootSash.width,height:u.rootSash.height},ref:i},f.map(e=>t.default.createElement(de,{key:e.id,sash:e,bwin:u})),d.map(e=>t.default.createElement(ue,{key:e.id,sash:e})),t.default.createElement(`bw-sill`,{ref:a})),m=(0,t.useMemo)(()=>p,[]);function h(e,t){let{content:n,...r}=t,i=u.addPane(e,r),a=document.querySelector(`bw-pane[sash-id="${i.id}"] bw-glass-content`);s(e=>[...e||[],{node:n,container:a}])}return t.default.createElement(t.default.Fragment,null,m,o?.map(e=>(0,n.createPortal)(e.node,e.container)))});e.BUILTIN_ACTIONS=Y,e.Window=fe,e.version=`0.3.4`});
8
+ `.trim(),t}var B={createWindow({theme:e}={}){let t=document.createElement(`bw-window`);return t.style.width=`${this.rootSash.width}px`,t.style.height=`${this.rootSash.height}px`,t.setAttribute(`root-sash-id`,this.rootSash.id),e&&t.setAttribute(`theme`,e),t},glaze(){this.rootSash.walk(e=>{let t=null;e.children.length>0?(t=this.createMuntin(e),this.onMuntinCreate(t,e),this.windowElement.append(t)):(t=this.createPane(e),this.onPaneCreate(t,e),this.windowElement.prepend(t)),e.domNode=t})},update(){this.windowElement.style.width=`${this.rootSash.width}px`,this.windowElement.style.height=`${this.rootSash.height}px`;let e=this.rootSash.getAllIds(),t=[];this.windowElement.querySelectorAll(`[sash-id]`).forEach(n=>{let r=n.getAttribute(`sash-id`);t.push(r),e.includes(r)||n.remove()}),this.rootSash.walk(e=>{e.children.length>0?t.includes(e.id)?(this.updateMuntin(e),this.onMuntinUpdate(e.domNode,e)):(e.domNode=this.createMuntin(e),this.windowElement.append(e.domNode)):t.includes(e.id)?(this.updatePane(e),this.onPaneUpdate(e.domNode,e)):(e.domNode||=this.createPane(e),this.windowElement.prepend(e.domNode))})}},V={muntinSize:4,createMuntin(e){let t=document.createElement(`bw-muntin`),n=e.leftChild,r=e.topChild;return n?(t.style.width=`${this.muntinSize}px`,t.style.height=`${e.height}px`,t.style.top=`${e.top}px`,t.style.left=`${e.left+n.width-this.muntinSize/2}px`,t.setAttribute(`vertical`,``)):r&&(t.style.width=`${e.width}px`,t.style.height=`${this.muntinSize}px`,t.style.top=`${e.top+r.height-this.muntinSize/2}px`,t.style.left=`${e.left}px`,t.setAttribute(`horizontal`,``)),t.setAttribute(`sash-id`,e.id),e.store.resizable===!1&&t.setAttribute(`resizable`,`false`),t},onMuntinCreate(e,t){},updateMuntin(e){let t=e.domNode,n=e.leftChild,r=e.topChild;n?(t.style.height=`${e.height}px`,t.style.top=`${e.top}px`,t.style.left=`${e.left+n.width-this.muntinSize/2}px`):r&&(t.style.width=`${e.width}px`,t.style.top=`${e.top+r.height-this.muntinSize/2}px`,t.style.left=`${e.left}px`)},onMuntinUpdate(e,t){}},H={fitContainer:!1,fit(){this.rootSash.width=this.containerElement.clientWidth,this.rootSash.height=this.containerElement.clientHeight,this.update()},enableFitContainer(){new ResizeObserver(e=>{requestAnimationFrame(()=>{for(let t of e)t.target===this.containerElement&&this.fitContainer&&this.fit()})}).observe(this.containerElement)}},U={activeMuntinSash:null,isResizeStarted:!1,isDropStarted:!1,lastX:0,lastY:0,applyResizeStyles(){this.activeMuntinSash.domNode.hasAttribute(`vertical`)?document.body.classList.add(`body--bw-resize-x`):this.activeMuntinSash.domNode.hasAttribute(`horizontal`)&&document.body.classList.add(`body--bw-resize-y`)},revertResizeStyles(){document.body.classList.remove(`body--bw-resize-x`),document.body.classList.remove(`body--bw-resize-y`)},enableResize(){document.addEventListener(`mousedown`,e=>{if(e.target.tagName!==`BW-MUNTIN`||e.target.getAttribute(`resizable`)===`false`)return;let t=e.target.getAttribute(`sash-id`);this.activeMuntinSash=this.rootSash.getById(t),this.activeMuntinSash&&(this.isResizeStarted=!0,this.lastX=e.pageX,this.lastY=e.pageY,this.applyResizeStyles())}),document.addEventListener(`mousemove`,e=>{if(!this.isResizeStarted||!this.activeMuntinSash)return;let[t,n,r,i]=this.activeMuntinSash.getChildren(),a=this.activeMuntinSash.isLeftRightSplit(),o=this.activeMuntinSash.isTopBottomSplit();if(a&&i&&n){let t=e.pageX-this.lastX,r=i.width+t,a=n.width-t;if(t>0&&a<=n.calcMinWidth()||t<0&&r<=i.calcMinWidth())return;i.width=r,n.width=a,n.left+=t,this.update(),this.lastX=e.pageX}else if(o&&t&&r){let n=e.pageY-this.lastY,i=t.height+n,a=r.height-n;if(n>0&&a<=r.calcMinHeight()||n<0&&i<=t.calcMinHeight())return;t.height=i,r.height=a,r.top+=n,this.update(),this.lastY=e.pageY}}),document.addEventListener(`mouseup`,()=>{this.isResizeStarted=!1,this.activeMuntinSash=null,this.revertResizeStyles()})}},ae={activeDropPaneEl:null,onPaneDrop(e,t){},enableDrop(){this.windowElement.addEventListener(`dragover`,e=>{e.preventDefault();let t=e.target.matches(`bw-pane`)?e.target:e.target.closest(`bw-pane`);if(!t||(t!==this.activeDropPaneEl&&(this.activeDropPaneEl&&this.activeDropPaneEl.removeAttribute(`drop-area`),this.activeDropPaneEl=t),t.getAttribute(`can-drop`)===`false`))return;let n=C(t,e);t.setAttribute(`drop-area`,n)}),this.windowElement.addEventListener(`dragleave`,e=>{e.currentTarget.contains(e.relatedTarget)&&e.currentTarget!==e.relatedTarget||(this.activeDropPaneEl&&=(this.activeDropPaneEl.removeAttribute(`drop-area`),null))}),this.windowElement.addEventListener(`drop`,e=>{if(!this.activeDropPaneEl||this.activeDropPaneEl.getAttribute(`can-drop`)===`false`)return;let t=this.activeDropPaneEl.getAttribute(`sash-id`),n=this.rootSash.getById(t);this.onPaneDrop(e,n),typeof n.store.onDrop==`function`&&n.store.onDrop(e,n),this.activeDropPaneEl.removeAttribute(`drop-area`),this.activeDropPaneEl=null})}},W=!1,G=class{windowElement=null;containerElement=null;debug=W;constructor(e){let t=null;e instanceof k?(t=e,this.rootSash=e):(t=new ie(e),this.rootSash=t.buildSashTree({resizeStrategy:t.resizeStrategy})),this.fitContainer=t.fitContainer,this.theme=t.theme}frame(e){this.containerElement=e,this.windowElement=this.createWindow({theme:this.theme}),this.glaze(),this.containerElement.append(this.windowElement)}enableFeatures(){this.enableResize(),this.enableDrop(),this.fitContainer&&this.enableFitContainer()}mount(e){this.frame(e),this.enableFeatures()}static assemble(...e){e.forEach(e=>{g(this.prototype,e)})}};G.assemble(B,V,R,H,ae,U);var K={label:``,className:`bw-glass-action--close`,onClick:(e,t)=>{let n=L(e.target);t.removePane(n)}},q={label:``,className:`bw-glass-action--minimize`,onClick:(e,t)=>{let n=t.sillElement;if(!n)throw Error(`[bwin] Sill element not found when minimizing`);let r=v(`<button class="bw-minimized-glass" />`);n.append(r);let i=e.target.closest(`bw-pane`),a=e.target.closest(`bw-glass`),o=i.getAttribute(`sash-id`),s=i.getAttribute(`position`);r.bwGlassElement=a,r.bwOriginalPosition=s,r.bwOriginalBoundingRect=y(i),r.bwOriginalSashId=o,t.removePane(o)}},J={label:``,className:`bw-glass-action--maximize`,onClick:e=>{let t=e.target.closest(`bw-pane`);t.hasAttribute(`maximized`)?(t.removeAttribute(`maximized`),t.style.left=`${t.bwOriginalBoundingRect.left}px`,t.style.top=`${t.bwOriginalBoundingRect.top}px`,t.style.width=`${t.bwOriginalBoundingRect.width}px`,t.style.height=`${t.bwOriginalBoundingRect.height}px`):(t.setAttribute(`maximized`,``),t.bwOriginalBoundingRect=y(t),t.style.left=`0`,t.style.top=`0`,t.style.width=`100%`,t.style.height=`100%`)}};function oe(e,t){let n=e.left+e.width,r=e.top+e.height,i=t.left+t.width,a=t.top+t.height;if(e.left>=i||t.left>=n||e.top>=a||t.top>=r)return null;let o=Math.max(e.left,t.left),s=Math.max(e.top,t.top),c=Math.min(n,i),l=Math.min(r,a);return{left:o,top:s,width:c-o,height:l-s}}var Y=[q,J,K],se={enableActions(){this.handleMinimizedGlassClick(),this.observeActionButtons()},restoreGlass(e){let t=e.bwOriginalBoundingRect,n=0,r=null;if(this.windowElement.querySelectorAll(`bw-pane`).forEach(e=>{let i=oe(t,y(e));if(i){let t=i.width*i.height;t>n&&(n=t,r=e)}}),r){let n=e.bwOriginalPosition,i=y(r),a=r.getAttribute(`sash-id`),o=this.rootSash.getById(a),s=0;if(n===b.Left||n===b.Right)s=i.width-t.width<o.minWidth?i.width/2:t.width;else if(n===b.Top||n===b.Bottom)s=i.height-t.height<o.minHeight?i.height/2:t.height;else throw Error(`[bwin] Invalid position when restoring glass`);let c=e.bwOriginalSashId;this.addPane(r.getAttribute(`sash-id`),{id:c,position:n,size:s}).domNode.append(e.bwGlassElement)}},handleMinimizedGlassClick(){this.sillElement.addEventListener(`click`,e=>{if(!e.target.matches(`.bw-minimized-glass`))return;let t=e.target;this.restoreGlass(t),t.remove()})},updateDisabledStateOfActionButtons(){this.updateDisabledState(`.bw-glass-action--close`),this.updateDisabledState(`.bw-glass-action--minimize`),this.updateDisabledState(`.bw-glass-action--maximize`)},updateDisabledState(e){if(this.windowElement.querySelectorAll(`bw-pane`).length===1){let t=this.windowElement.querySelector(e);t&&t.setAttribute(`disabled`,``)}else this.windowElement.querySelectorAll(e).forEach(e=>{e.removeAttribute(`disabled`)})},getMinimizedGlassElementBySashId(e){let t=this.windowElement.querySelectorAll(`.bw-minimized-glass`);return Array.from(t).find(t=>t.bwOriginalSashId===e)},observeActionButtons(){this.updateDisabledStateOfActionButtons(),new MutationObserver(e=>{e.forEach(e=>{e.type===`childList`&&this.updateDisabledStateOfActionButtons()})}).observe(this.windowElement,{childList:!0})}},X={title:null,content:null,tabs:[],actions:void 0,draggable:!0},Z=class{domNode;constructor({title:e=X.title,content:t=X.content,tabs:n=X.tabs,actions:r=X.actions,draggable:i=X.draggable,sash:a,binaryWindow:o}){this.title=e,this.content=t,this.tabs=n,this.actions=r,this.sash=a,this.draggable=i,this.binaryWindow=o,this.build()}build(){let e=document.createElement(`bw-glass-header`);if(Array.isArray(this.tabs)&&this.tabs.length>0)e.append(this.createTabs());else if(this.title){let t=document.createElement(`bw-glass-title`);t.append(v(this.title)),e.append(t)}e.setAttribute(`can-drag`,this.draggable),e.append(this.createActions());let t=document.createElement(`bw-glass-content`),n=v(this.content);n&&t.append(n),this.domNode=document.createElement(`bw-glass`),this.domNode.append(e,t)}createTabs(){let e=document.createElement(`bw-glass-tab-container`);for(let t of this.tabs){let n=v(`<button class="bw-glass-tab">${t?.label??t}</button>`);e.append(n)}return e}createActions(){let e=document.createElement(`bw-glass-action-container`),t=this.actions===void 0?Y:Array.isArray(this.actions)?this.actions:[];for(let n of t){let t=n?.label??n,r=v(`<button class="${n.className?`bw-glass-action ${n.className}`:`bw-glass-action`}">${t}</button>`);typeof n.onClick==`function`&&r.addEventListener(`click`,e=>{n.onClick(e,this.binaryWindow)}),e.append(r)}return e}get contentElement(){return this.domNode.querySelector(`bw-glass-content`)}get headerElement(){return this.domNode.querySelector(`bw-glass-header`)}},ce={activeDragGlassEl:null,activeDragGlassPaneCanDrop:!1,onPaneDrop(e,t){if(!this.activeDragGlassEl)return;let n=this.activeDropPaneEl.getAttribute(`drop-area`);if(n===`center`){let e=this.activeDragGlassEl.closest(`bw-pane`);this.swapPanes(e,this.activeDropPaneEl);return}else{let e=L(this.activeDragGlassEl);this.removePane(e),this.addPane(t.id,{position:n,id:e}).domNode.append(this.activeDragGlassEl)}},enableDrag(){document.addEventListener(`mousedown`,e=>{if(e.button!==0||!e.target.matches(`bw-glass-header`))return;if(e.target.getAttribute(`can-drag`)===`false`){e.preventDefault();return}let t=e.target.closest(`bw-glass`);t.setAttribute(`draggable`,!0),this.activeDragGlassEl=t}),document.addEventListener(`mouseup`,()=>{this.activeDragGlassEl&&=(this.activeDragGlassEl.removeAttribute(`draggable`),null)}),this.windowElement.addEventListener(`dragstart`,e=>{if(!(e.target instanceof HTMLElement)||!e.target.matches(`bw-glass`)||!this.activeDragGlassEl)return;e.dataTransfer.effectAllowed=`move`;let t=this.activeDragGlassEl.closest(`bw-pane`);this.activeDragGlassPaneCanDrop=t.getAttribute(`can-drop`)!==`false`,t.setAttribute(`can-drop`,!1)}),this.windowElement.addEventListener(`dragend`,()=>{this.activeDragGlassEl&&=(this.activeDragGlassEl.removeAttribute(`draggable`),this.activeDragGlassEl.closest(`bw-pane`).setAttribute(`can-drop`,this.activeDragGlassPaneCanDrop),null)})}},le={trimMuntin(e){e.hasAttribute(`vertical`)?(e.style.top=`${parseFloat(e.style.top)+this.muntinSize/2}px`,e.style.height=`${parseFloat(e.style.height)-this.muntinSize}px`):e.hasAttribute(`horizontal`)&&(e.style.left=`${parseFloat(e.style.left)+this.muntinSize/2}px`,e.style.width=`${parseFloat(e.style.width)-this.muntinSize}px`)},onMuntinCreate(e){this.trimMuntin(e)},onMuntinUpdate(e){this.trimMuntin(e)}},Q=class extends G{sillElement=null;frame(){super.frame(...arguments);let e=v(`<bw-sill />`);this.windowElement.append(e),this.sillElement=e}enableFeatures(){super.enableFeatures(),this.enableDrag(),this.enableActions()}onPaneCreate(e,t){let n=new Z({...t.store,sash:t,binaryWindow:this});e.innerHTML=``,e.append(n.domNode),this.debug&&n.contentElement.prepend(`${t.id}`)}onPaneUpdate(){}addPane(e,t){let{position:n,size:r,id:i,...a}=t,o=super.addPane(e,{position:n,size:r,id:i}),s=new Z({...a,sash:o,binaryWindow:this});return o.domNode.append(s.domNode),o}setTheme(e){if(!e){this.theme=``,this.windowElement.removeAttribute(`theme`);return}this.theme=e,this.windowElement.setAttribute(`theme`,e)}removePane(e){if(this.windowElement.querySelector(`[sash-id="${e}"]`)){super.removePane(e);return}let t=this.getMinimizedGlassElementBySashId(e);t&&t.remove()}};Q.assemble(ce,le,se);var $=4;function ue({sash:e}){let n=(0,t.useRef)(),r=e.leftChild,i=e.topChild,a,o,s,c,l,u;return r?(a=$,o=e.height-$,s=e.top+$/2,c=e.left+r.width-$/2,l=!0):i&&(a=e.width-$,o=$,s=e.top+i.height-$/2,c=e.left+$/2,u=!0),(0,t.useEffect)(()=>{e.domNode=n.current},[]),t.default.createElement(`bw-muntin`,{"sash-id":e.id,style:{width:a,height:o,top:s,left:c},vertical:l,horizontal:u,resizable:e.store?.resizable===!1?`false`:`true`,ref:n})}function de({sash:e,bwin:n}){let r=(0,t.useRef)(),{left:i,top:a,width:o,height:s,id:c,position:l}=e;(0,t.useEffect)(()=>{e.domNode=r.current},[]);let u=e.store?.actions===void 0?Y:Array.isArray(e.store.actions)?e.store.actions:[];return t.default.createElement(`bw-pane`,{"sash-id":c,position:l,style:{left:i,top:a,width:o,height:s},"can-drop":e.store?.droppable===!1?`false`:`true`,ref:r},t.default.createElement(`bw-glass`,null,t.default.createElement(`bw-glass-header`,{"can-drag":e.store?.draggable===!1?`false`:`true`},e.store?.title&&t.default.createElement(`bw-glass-title`,null,e.store.title),u.length>0&&t.default.createElement(`bw-glass-action-container`,null,u.map((e,r)=>{let i=e.className?`bw-glass-action ${e.className}`:`bw-glass-action`;return t.default.createElement(`button`,{className:i,key:r,onClick:t=>e.onClick(t,n)},e.label)}))),t.default.createElement(`bw-glass-content`,null,e.store?.content)))}var fe=(0,t.forwardRef)((e,r)=>{let i=(0,t.useRef)(),a=(0,t.useRef)(),[o,s]=(0,t.useState)(),{panes:c,...l}=e,u=new Q({...l,children:c}),d=[],f=[];u.rootSash.walk(e=>{e.children.length>0?d.push(e):f.push(e)}),(0,t.useEffect)(()=>{let e=i.current;e?.parentElement&&(u.windowElement=e,u.containerElement=e.parentElement,u.sillElement=a.current,u.enableFeatures())},[]),(0,t.useImperativeHandle)(r,()=>({fit:u.fit.bind(u),removePane:u.removePane.bind(u),setTheme:u.setTheme.bind(u),addPane:h}),[]);let p=t.default.createElement(`bw-window`,{"root-sash-id":u.rootSash.id,theme:u.theme||void 0,style:{width:u.rootSash.width,height:u.rootSash.height},ref:i},f.map(e=>t.default.createElement(de,{key:e.id,sash:e,bwin:u})),d.map(e=>t.default.createElement(ue,{key:e.id,sash:e})),t.default.createElement(`bw-sill`,{ref:a})),m=(0,t.useMemo)(()=>p,[]);function h(e,t){let{content:n,...r}=t,i=u.addPane(e,r),a=document.querySelector(`bw-pane[sash-id="${i.id}"] bw-glass-content`);s(e=>[...e||[],{node:n,container:a}])}return t.default.createElement(t.default.Fragment,null,m,o?.map(e=>(0,n.createPortal)(e.node,e.container)))});e.BUILTIN_ACTIONS=Y,e.Window=fe,e.version=`0.3.5-dev.0`});
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "react-bwin",
3
3
  "description": "A tiling window manager in React based on Binary Window library",
4
- "version": "0.3.4",
4
+ "version": "0.3.5-dev.0",
5
5
  "type": "module",
6
6
  "repository": {
7
7
  "type": "git",