diff --git a/examples/flexlayout-react-demo/.gitignore b/examples/flexlayout-react-demo/.gitignore new file mode 100644 index 00000000..a547bf36 --- /dev/null +++ b/examples/flexlayout-react-demo/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/examples/flexlayout-react-demo/.prettierrc b/examples/flexlayout-react-demo/.prettierrc new file mode 100644 index 00000000..870577d5 --- /dev/null +++ b/examples/flexlayout-react-demo/.prettierrc @@ -0,0 +1,5 @@ +{ + "printWidth": 200, + "semi": false, + "tabWidth": 2 +} diff --git a/examples/flexlayout-react-demo/index.html b/examples/flexlayout-react-demo/index.html new file mode 100644 index 00000000..c29908b5 --- /dev/null +++ b/examples/flexlayout-react-demo/index.html @@ -0,0 +1,16 @@ + + + + + + FlexLayour React Demo + + + + + + +
+ + + diff --git a/examples/flexlayout-react-demo/package.json b/examples/flexlayout-react-demo/package.json new file mode 100644 index 00000000..e6cf013d --- /dev/null +++ b/examples/flexlayout-react-demo/package.json @@ -0,0 +1,31 @@ +{ + "name": "flexlayout-react-demo", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "preview": "vite preview", + "format": "prettier . --write", + "lint": "eslint --ext .ts,.tsx,.js --ignore-path .gitignore --fix src" + }, + "dependencies": { + "flexlayout-react": "^0.7.4", + "nanoid": "^4.0.0", + "prismjs": "^1.28.0", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/prismjs": "^1.26.0", + "@types/react": "^18.0.15", + "@types/react-dom": "^18.0.6", + "@vitejs/plugin-react": "^2.0.0", + "eslint": "^8.21.0", + "eslint-config-prettier": "^8.5.0", + "prettier": "^2.7.1", + "typescript": "^4.6.4", + "vite": "^3.0.0" + } +} diff --git a/examples/flexlayout-react-demo/popout.html b/examples/flexlayout-react-demo/popout.html new file mode 100755 index 00000000..641a439e --- /dev/null +++ b/examples/flexlayout-react-demo/popout.html @@ -0,0 +1,13 @@ + + + + + + FlexLayout Popout + + + diff --git a/examples/flexlayout-react-demo/public/images/add.svg b/examples/flexlayout-react-demo/public/images/add.svg new file mode 100644 index 00000000..1ba7140f --- /dev/null +++ b/examples/flexlayout-react-demo/public/images/add.svg @@ -0,0 +1,4 @@ + + + + diff --git a/examples/flexlayout-react-demo/public/images/article.svg b/examples/flexlayout-react-demo/public/images/article.svg new file mode 100644 index 00000000..2d93bc2a --- /dev/null +++ b/examples/flexlayout-react-demo/public/images/article.svg @@ -0,0 +1 @@ + diff --git a/examples/flexlayout-react-demo/public/images/bar_chart.svg b/examples/flexlayout-react-demo/public/images/bar_chart.svg new file mode 100644 index 00000000..2cd5b3be --- /dev/null +++ b/examples/flexlayout-react-demo/public/images/bar_chart.svg @@ -0,0 +1 @@ + diff --git a/examples/flexlayout-react-demo/public/images/folder.svg b/examples/flexlayout-react-demo/public/images/folder.svg new file mode 100644 index 00000000..2481e4c8 --- /dev/null +++ b/examples/flexlayout-react-demo/public/images/folder.svg @@ -0,0 +1 @@ + diff --git a/examples/flexlayout-react-demo/public/images/settings.svg b/examples/flexlayout-react-demo/public/images/settings.svg new file mode 100644 index 00000000..9363671b --- /dev/null +++ b/examples/flexlayout-react-demo/public/images/settings.svg @@ -0,0 +1 @@ + diff --git a/examples/flexlayout-react-demo/public/images/terminal.svg b/examples/flexlayout-react-demo/public/images/terminal.svg new file mode 100644 index 00000000..02b7b846 --- /dev/null +++ b/examples/flexlayout-react-demo/public/images/terminal.svg @@ -0,0 +1 @@ + diff --git a/examples/flexlayout-react-demo/public/layouts/complex.layout b/examples/flexlayout-react-demo/public/layouts/complex.layout new file mode 100755 index 00000000..67b63de3 --- /dev/null +++ b/examples/flexlayout-react-demo/public/layouts/complex.layout @@ -0,0 +1,610 @@ +{ + "global": { + "tabEnableFloat": true + }, + "layout": { + "type": "row", + "id": "#5", + "children": [ + { + "type": "tabset", + "id": "#6", + "weight": 12.5, + "selected": 9, + "children": [ + { + "type": "tab", + "id": "#7", + "name": "FX", + "component": "grid" + }, + { + "type": "tab", + "id": "#8", + "name": "Global", + "component": "grid" + }, + { + "type": "tab", + "id": "#37", + "name": "grid 26", + "component": "grid" + }, + { + "type": "tab", + "id": "#38", + "name": "grid 27", + "component": "grid" + }, + { + "type": "tab", + "id": "#39", + "name": "grid 28", + "component": "grid" + }, + { + "type": "tab", + "id": "#40", + "name": "grid 29", + "component": "grid" + }, + { + "type": "tab", + "id": "#41", + "name": "grid 30", + "component": "grid" + }, + { + "type": "tab", + "id": "#42", + "name": "grid 31", + "component": "grid" + }, + { + "type": "tab", + "id": "#49", + "name": "grid 38", + "component": "grid" + }, + { + "type": "tab", + "id": "#50", + "name": "grid 39", + "component": "grid" + } + ] + }, + { + "type": "row", + "id": "#52", + "weight": 25, + "children": [ + { + "type": "row", + "id": "#88", + "weight": 50, + "children": [ + { + "type": "tabset", + "id": "#9", + "weight": 50, + "selected": 23, + "children": [ + { + "type": "tab", + "id": "#10", + "name": "FI", + "component": "grid" + }, + { + "type": "tab", + "id": "#12", + "name": "grid 1", + "component": "grid" + }, + { + "type": "tab", + "id": "#13", + "name": "grid 2", + "component": "grid" + }, + { + "type": "tab", + "id": "#14", + "name": "grid 3", + "component": "grid" + }, + { + "type": "tab", + "id": "#15", + "name": "grid 4", + "component": "grid" + }, + { + "type": "tab", + "id": "#16", + "name": "grid 5", + "component": "grid" + }, + { + "type": "tab", + "id": "#17", + "name": "grid 6", + "component": "grid" + }, + { + "type": "tab", + "id": "#18", + "name": "grid 7", + "component": "grid" + }, + { + "type": "tab", + "id": "#19", + "name": "grid 8", + "component": "grid" + }, + { + "type": "tab", + "id": "#20", + "name": "grid 9", + "component": "grid" + }, + { + "type": "tab", + "id": "#21", + "name": "grid 10", + "component": "grid" + }, + { + "type": "tab", + "id": "#22", + "name": "grid 11", + "component": "grid" + }, + { + "type": "tab", + "id": "#23", + "name": "grid 12", + "component": "grid" + }, + { + "type": "tab", + "id": "#24", + "name": "grid 13", + "component": "grid" + }, + { + "type": "tab", + "id": "#25", + "name": "grid 14", + "component": "grid" + }, + { + "type": "tab", + "id": "#26", + "name": "grid 15", + "component": "grid" + }, + { + "type": "tab", + "id": "#27", + "name": "grid 16", + "component": "grid" + }, + { + "type": "tab", + "id": "#28", + "name": "grid 17", + "component": "grid" + }, + { + "type": "tab", + "id": "#29", + "name": "grid 18", + "component": "grid" + }, + { + "type": "tab", + "id": "#30", + "name": "grid 19", + "component": "grid" + }, + { + "type": "tab", + "id": "#31", + "name": "grid 20", + "component": "grid" + }, + { + "type": "tab", + "id": "#32", + "name": "grid 21", + "component": "grid" + }, + { + "type": "tab", + "id": "#33", + "name": "grid 22", + "component": "grid" + }, + { + "type": "tab", + "id": "#34", + "name": "grid 23", + "component": "grid" + } + ] + }, + { + "type": "tabset", + "id": "#87", + "weight": 50, + "selected": 7, + "children": [ + { + "type": "tab", + "id": "#36", + "name": "grid 25", + "component": "grid" + }, + { + "type": "tab", + "id": "#91", + "name": "grid 71", + "component": "grid" + }, + { + "type": "tab", + "id": "#92", + "name": "grid 72", + "component": "grid" + }, + { + "type": "tab", + "id": "#93", + "name": "grid 73", + "component": "grid" + }, + { + "type": "tab", + "id": "#94", + "name": "grid 74", + "component": "grid" + }, + { + "type": "tab", + "id": "#95", + "name": "grid 75", + "component": "grid" + }, + { + "type": "tab", + "id": "#96", + "name": "grid 76", + "component": "grid" + }, + { + "type": "tab", + "id": "#97", + "name": "grid 77", + "component": "grid" + } + ] + } + ] + }, + { + "type": "tabset", + "id": "#51", + "weight": 50, + "selected": 12, + "children": [ + { + "type": "tab", + "id": "#35", + "name": "grid 24", + "component": "grid" + }, + { + "type": "tab", + "id": "#55", + "name": "grid 40", + "component": "grid" + }, + { + "type": "tab", + "id": "#56", + "name": "grid 41", + "component": "grid" + }, + { + "type": "tab", + "id": "#57", + "name": "grid 42", + "component": "grid" + }, + { + "type": "tab", + "id": "#58", + "name": "grid 43", + "component": "grid" + }, + { + "type": "tab", + "id": "#59", + "name": "grid 44", + "component": "grid" + }, + { + "type": "tab", + "id": "#63", + "name": "grid 48", + "component": "grid" + }, + { + "type": "tab", + "id": "#64", + "name": "grid 49", + "component": "grid" + }, + { + "type": "tab", + "id": "#66", + "name": "grid 51", + "component": "grid" + }, + { + "type": "tab", + "id": "#67", + "name": "grid 52", + "component": "grid" + }, + { + "type": "tab", + "id": "#86", + "name": "grid 1", + "component": "grid" + }, + { + "type": "tab", + "id": "#89", + "name": "grid 2", + "component": "grid" + }, + { + "type": "tab", + "id": "#90", + "name": "grid 3", + "component": "grid" + } + ], + "active": true + } + ] + } + ] + }, + "borders": [ + { + "type": "border", + "selected": 13, + "size": 132, + "location": "bottom", + "children": [ + { + "type": "tab", + "id": "#1", + "name": "Activity Blotter", + "component": "grid", + "enableClose": false + }, + { + "type": "tab", + "id": "#2", + "name": "Execution Blotter", + "component": "grid", + "enableClose": false + }, + { + "type": "tab", + "id": "#75", + "name": "grid 60", + "component": "grid" + }, + { + "type": "tab", + "id": "#76", + "name": "grid 61", + "component": "grid" + }, + { + "type": "tab", + "id": "#77", + "name": "grid 62", + "component": "grid" + }, + { + "type": "tab", + "id": "#78", + "name": "grid 63", + "component": "grid" + }, + { + "type": "tab", + "id": "#79", + "name": "grid 64", + "component": "grid" + }, + { + "type": "tab", + "id": "#60", + "name": "grid 45", + "component": "grid" + }, + { + "type": "tab", + "id": "#61", + "name": "grid 46", + "component": "grid" + }, + { + "type": "tab", + "id": "#80", + "name": "grid 65", + "component": "grid" + }, + { + "type": "tab", + "id": "#81", + "name": "grid 66", + "component": "grid" + }, + { + "type": "tab", + "id": "#62", + "name": "grid 47", + "component": "grid" + }, + { + "type": "tab", + "id": "#82", + "name": "grid 67", + "component": "grid" + }, + { + "type": "tab", + "id": "#65", + "name": "grid 50", + "component": "grid" + }, + { + "type": "tab", + "id": "#83", + "name": "grid 68", + "component": "grid" + }, + { + "type": "tab", + "id": "#84", + "name": "grid 69", + "component": "grid" + } + ] + }, + { + "type": "border", + "selected": 4, + "size": 188, + "location": "left", + "children": [ + { + "type": "tab", + "id": "#3", + "name": "Navigation", + "component": "grid", + "enableClose": false + }, + { + "type": "tab", + "id": "#43", + "name": "grid 32", + "component": "grid" + }, + { + "type": "tab", + "id": "#85", + "name": "grid 70", + "component": "grid" + }, + { + "type": "tab", + "id": "#44", + "name": "grid 33", + "component": "grid" + }, + { + "type": "tab", + "id": "#45", + "name": "grid 34", + "component": "grid" + }, + { + "type": "tab", + "id": "#46", + "name": "grid 35", + "component": "grid" + }, + { + "type": "tab", + "id": "#48", + "name": "grid 37", + "component": "grid" + }, + { + "type": "tab", + "id": "#47", + "name": "grid 36", + "component": "grid" + } + ] + }, + { + "type": "border", + "selected": 5, + "size": 196, + "location": "right", + "children": [ + { + "type": "tab", + "id": "#69", + "name": "grid 54", + "component": "grid" + }, + { + "type": "tab", + "id": "#74", + "name": "grid 59", + "component": "grid" + }, + { + "type": "tab", + "id": "#73", + "name": "grid 58", + "component": "grid" + }, + { + "type": "tab", + "id": "#4", + "name": "Options", + "component": "grid", + "enableClose": false + }, + { + "type": "tab", + "id": "#72", + "name": "grid 57", + "component": "grid" + }, + { + "type": "tab", + "id": "#71", + "name": "grid 56", + "component": "grid" + }, + { + "type": "tab", + "id": "#70", + "name": "grid 55", + "component": "grid" + }, + { + "type": "tab", + "id": "#68", + "name": "grid 53", + "component": "grid" + } + ] + } + ] +} \ No newline at end of file diff --git a/examples/flexlayout-react-demo/public/layouts/default.layout b/examples/flexlayout-react-demo/public/layouts/default.layout new file mode 100755 index 00000000..06590a31 --- /dev/null +++ b/examples/flexlayout-react-demo/public/layouts/default.layout @@ -0,0 +1,104 @@ +{ + "global": { + "tabEnableFloat": true, + "tabSetMinHeight":100, + "tabSetMinWidth":100, + "borderMinSize":100 + }, + "layout": { + "type": "row", + "children": [ + { + "type": "tabset", + "weight": 12.5, + "active": true, + "children": [ + { + "type": "tab", + "name": "One", + "component": "grid" + }, + { + "type": "tab", + "name": "Two", + "component": "grid" + } + ] + }, + { + "type": "tabset", + "weight": 25, + "children": [ + { + "type": "tab", + "name": "Three", + "component": "grid" + }, + { + "type": "tab", + "name": "Wikipedia", + "component": "multitype", + "config": { + "type":"url", + "data": "https://en.wikipedia.org/wiki/Main_Page" + } + } + ] + } + ] + }, + "borders": [ + { + "type": "border", + "location": "bottom", + "children": [ + { + "type": "tab", + "enableClose":false, + "name": "Output", + "component": "grid", + "icon":"images/bar_chart.svg" + }, + { + "type": "tab", + "enableClose":false, + "name": "Terminal", + "component": "grid", + "icon":"images/terminal.svg" + }, + { + "type": "tab", + "name": "Layout JSON", + "component": "json" + } + ] + }, + { + "type": "border", + "location": "left", + "children": [ + { + "type": "tab", + "enableClose":false, + "name": "Navigation", + "altName": "The Navigation Tab", + "component": "grid", + "icon":"images/folder.svg" + } + ] + }, + { + "type": "border", + "location": "right", + "children": [ + { + "type": "tab", + "enableClose":false, + "name": "Options", + "component": "grid", + "icon":"images/settings.svg" + } + ] + } + ] +} diff --git a/examples/flexlayout-react-demo/public/layouts/headers.layout b/examples/flexlayout-react-demo/public/layouts/headers.layout new file mode 100755 index 00000000..d4e736b6 --- /dev/null +++ b/examples/flexlayout-react-demo/public/layouts/headers.layout @@ -0,0 +1,54 @@ +{ +"global": { +"tabEnableRename":false +}, +"layout": + { + "type": "row", + "weight": 100, + "children": [ + { + "type": "tabset", + "weight": 50, + "name":"Header 1", + "selected": 0, + "children": [ + { + "type": "tab", + "name": "One", + "component":"grid" + } + ] + }, + { + "type": "tabset", + "weight": 50, + "color": "#ffcccc", + "selected": 0, + "children": [ + { + "type": "tab", + "name": "Two", + "component":"grid", + "config": { + "id": "2" + } + } + ] + }, + { + "type": "tabset", + "weight": 50, + "name":"Header 2", + "selected": 0, + "children": [ + { + "type": "tab", + "name": "Three", + "component":"grid" + } + ] + } + ] + } +} diff --git a/examples/flexlayout-react-demo/public/layouts/newfeatures.layout b/examples/flexlayout-react-demo/public/layouts/newfeatures.layout new file mode 100755 index 00000000..82faa908 --- /dev/null +++ b/examples/flexlayout-react-demo/public/layouts/newfeatures.layout @@ -0,0 +1,104 @@ +{ + "global": { + "tabEnableFloat": true, + "tabSetMinHeight":100, + "tabSetMinWidth":100, + "borderMinSize":100, + "borderEnableAutoHide": true, + "tabSetEnableClose":true, + "splitterSize":1, + "splitterExtra":4 + }, + "layout": { + "type": "row", + "children": [ + { + "type": "tabset", + "weight": 12.5, + "active": true, + "children": [ + { + "type": "tab", + "name": "New", + "helpText": "this tab has helpText defined", + "component": "newfeatures" + }, + { + "type": "tab", + "name": "Two", + "component": "grid" + } + ] + }, + { + "type": "tabset", + "weight": 25, + "children": [ + { + "type": "tab", + "borderWidth":500, + "name": "Tab Storage", + "component": "tabstorage" + } + ] + } + ] + }, + "borders": [ + { + "type": "border", + "location": "bottom", + "children": [ + { + "type": "tab", + "enableClose":false, + "name": "Output", + "component": "grid" + }, + { + "type": "tab", + "enableClose":false, + "name": "Terminal", + "component": "grid" + }, + { + "type": "tab", + "name": "Layout JSON", + "component": "json" + } + ] + }, + { + "type": "border", + "location": "left", + "children": [ + { + "type": "tab", + "enableClose":false, + "name": "Navigation", + "component": "grid" + }, + { + "type": "tab", + "enableClose":false, + "borderWidth":500, + "borderHeight":500, + "name": "With border sizes", + "component": "grid" + } + ] + }, + { + "type": "border", + "location": "right", + "children": [ + { + "type": "tab", + "enableClose":false, + "name": "Options", + "component": "grid" + } + ] + } + ] +} diff --git a/examples/flexlayout-react-demo/public/layouts/simple.layout b/examples/flexlayout-react-demo/public/layouts/simple.layout new file mode 100644 index 00000000..be4f384b --- /dev/null +++ b/examples/flexlayout-react-demo/public/layouts/simple.layout @@ -0,0 +1,38 @@ +{ + "global": {}, + "borders": [], + "layout": { + "type": "row", + "id": "1", + "children": [ + { + "type": "tabset", + "id": "2", + "weight": 50, + "children": [ + { + "type": "tab", + "id": "3", + "name": "Layout JSON", + "component": "json" + } + ], + "active": true + }, + { + "type": "tabset", + "id": "4", + "weight": 50, + "children": [ + { + "type": "tab", + "id": "5", + "name": "Grid 1", + "component": "grid", + "icon": "images/article.svg" + } + ] + } + ] + } +} diff --git a/examples/flexlayout-react-demo/public/layouts/sub.layout b/examples/flexlayout-react-demo/public/layouts/sub.layout new file mode 100755 index 00000000..df8b8f45 --- /dev/null +++ b/examples/flexlayout-react-demo/public/layouts/sub.layout @@ -0,0 +1,112 @@ +{ + "global": { + "tabEnableFloat": true + }, + "borders": [], + "layout": { + "type": "row", + "children": [ + { + "type": "tabset", + "weight": 23.6, + "children": [ + { + "type": "tab", + "name": "Tabbed Pane", + "component": "sub", + "config": { + "model": { + "global": { + "tabSetTabLocation": "bottom" + }, + "borders": [], + "layout": { + "type": "row", + "children": [ + { + "type": "tabset", + "weight": 50, + "selected": 1, + "children": [ + { + "type": "tab", + "name": "AAAA", + "component": "grid", + "config": { + "id": "1" + } + }, + { + "type": "tab", + "name": "BBBB", + "component": "grid", + "config": { + "id": "2" + } + } + ], + "active": true + } + ] + } + } + } + } + ] + }, + { + "type": "tabset", + "weight": 26.4, + "children": [ + { + "type": "tab", + "name": "Split Pane", + "component": "sub", + "config": { + "model": { + "global": { + "tabSetEnableTabStrip": false + }, + "borders": [], + "layout": { + "type": "row", + "children": [ + { + "type": "tabset", + "weight": 50, + "children": [ + { + "type": "tab", + "name": "1111", + "component": "grid", + "config": { + "id": "1" + } + } + ] + }, + { + "type": "tabset", + "weight": 50, + "children": [ + { + "type": "tab", + "name": "2222", + "component": "grid", + "config": { + "id": "2" + } + } + ] + } + ] + } + } + } + } + ], + "active": true + } + ] + } +} diff --git a/examples/flexlayout-react-demo/public/styles/base.css b/examples/flexlayout-react-demo/public/styles/base.css new file mode 100644 index 00000000..5d247f42 --- /dev/null +++ b/examples/flexlayout-react-demo/public/styles/base.css @@ -0,0 +1,544 @@ +.flexlayout__layout { + --color-text: black; + --color-background: white; + --color-base: white; + --color-1: #f7f7f7; + --color-2: #f0f0f0; + --color-3: #e9e9e9; + --color-4: #e2e2e2; + --color-5: #dbdbdb; + --color-6: #d4d4d4; + --color-drag1: rgb(95, 134, 196); + --color-drag2: rgb(119, 166, 119); + --color-drag1-background: rgba(95, 134, 196, 0.1); + --color-drag2-background: rgba(119, 166, 119, 0.075); + --font-size: medium; + --font-family: Roboto, Arial, sans-serif; + --color-overflow: gray; + --color-icon: gray; + --color-tabset-background: var(--color-background); + --color-tabset-background-selected: var(--color-1); + --color-tabset-background-maximized: var(--color-6); + --color-tabset-divider-line: var(--color-4); + --color-tabset-header-background: var(--color-background); + --color-tabset-header: var(--color-text); + --color-border-background: var(--color-background); + --color-border-divider-line: var(--color-4); + --color-tab-selected: var(--color-text); + --color-tab-selected-background: var(--color-4); + --color-tab-unselected: gray; + --color-tab-unselected-background: transparent; + --color-tab-textbox: var(--color-text); + --color-tab-textbox-background: var(--color-3); + --color-border-tab-selected: var(--color-text); + --color-border-tab-selected-background: var(--color-4); + --color-border-tab-unselected: gray; + --color-border-tab-unselected-background: var(--color-2); + --color-splitter: var(--color-1); + --color-splitter-hover: var(--color-4); + --color-splitter-drag: var(--color-4); + --color-drag-rect-border: var(--color-6); + --color-drag-rect-background: var(--color-4); + --color-drag-rect: var(--color-text); + --color-popup-border: var(--color-6); + --color-popup-unselected: var(--color-text); + --color-popup-unselected-background: white; + --color-popup-selected: var(--color-text); + --color-popup-selected-background: var(--color-3); + --color-edge-marker: gray; +} + +.flexlayout__layout { + left: 0; + top: 0; + right: 0; + bottom: 0; + position: absolute; + overflow: hidden; +} +.flexlayout__splitter { + background-color: var(--color-splitter); +} +@media (hover: hover) { + .flexlayout__splitter:hover { + background-color: var(--color-splitter-hover); + transition: background-color ease-in 0.1s; + transition-delay: 0.05s; + } +} +.flexlayout__splitter_border { + z-index: 10; +} +.flexlayout__splitter_drag { + z-index: 1000; + background-color: var(--color-splitter-drag); +} +.flexlayout__splitter_extra { + background-color: transparent; +} +.flexlayout__outline_rect { + position: absolute; + pointer-events: none; + box-sizing: border-box; + border: 2px solid var(--color-drag1); + background: var(--color-drag1-background); + border-radius: 5px; + z-index: 1000; +} +.flexlayout__outline_rect_edge { + pointer-events: none; + border: 2px solid var(--color-drag2); + background: var(--color-drag2-background); + border-radius: 5px; + z-index: 1000; + box-sizing: border-box; +} +.flexlayout__edge_rect { + position: absolute; + z-index: 1000; + box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2); + background-color: var(--color-edge-marker); + pointer-events: none; +} +.flexlayout__drag_rect { + position: absolute; + cursor: move; + color: var(--color-drag-rect); + background-color: var(--color-drag-rect-background); + border: 2px solid var(--color-drag-rect-border); + border-radius: 5px; + z-index: 1000; + box-sizing: border-box; + opacity: 0.9; + text-align: center; + display: flex; + justify-content: center; + flex-direction: column; + overflow: hidden; + padding: 0.3em 1em; + word-wrap: break-word; + font-size: var(--font-size); + font-family: var(--font-family); +} +.flexlayout__tabset { + display: flex; + flex-direction: column; + overflow: hidden; + background-color: var(--color-tabset-background); + box-sizing: border-box; + font-size: var(--font-size); + font-family: var(--font-family); +} +.flexlayout__tabset_tab_divider { + width: 4px; +} +.flexlayout__tabset_content { + display: flex; + flex-grow: 1; + align-items: center; + justify-content: center; +} +.flexlayout__tabset_header { + display: flex; + align-items: center; + padding: 3px 3px 3px 5px; + box-sizing: border-box; + border-bottom: 1px solid var(--color-tabset-divider-line); + color: var(--color-tabset-header); + background-color: var(--color-tabset-header-background); +} +.flexlayout__tabset_header_content { + flex-grow: 1; +} +.flexlayout__tabset_tabbar_outer { + box-sizing: border-box; + background-color: var(--color-tabset-background); + overflow: hidden; + display: flex; +} +.flexlayout__tabset_tabbar_outer_top { + border-bottom: 1px solid var(--color-tabset-divider-line); +} +.flexlayout__tabset_tabbar_outer_bottom { + border-top: 1px solid var(--color-tabset-divider-line); +} +.flexlayout__tabset_tabbar_inner { + position: relative; + box-sizing: border-box; + display: flex; + flex-grow: 1; + overflow: hidden; +} +.flexlayout__tabset_tabbar_inner_tab_container { + display: flex; + padding-left: 4px; + padding-right: 4px; + box-sizing: border-box; + position: absolute; + top: 0; + bottom: 0; + width: 10000px; +} +.flexlayout__tabset_tabbar_inner_tab_container_top { + border-top: 2px solid transparent; +} +.flexlayout__tabset_tabbar_inner_tab_container_bottom { + border-bottom: 2px solid transparent; +} +.flexlayout__tabset-selected { + background-color: var(--color-tabset-background-selected); +} +.flexlayout__tabset-maximized { + background-color: var(--color-tabset-background-maximized); +} +.flexlayout__tab_button_stamp { + display: inline-flex; + align-items: center; + gap: 0.3em; + white-space: nowrap; + box-sizing: border-box; +} +.flexlayout__tab { + overflow: auto; + position: absolute; + box-sizing: border-box; + background-color: var(--color-background); + color: var(--color-text); +} +.flexlayout__tab_button { + display: flex; + gap: 0.3em; + align-items: center; + box-sizing: border-box; + padding: 3px 0.5em; + cursor: pointer; +} +.flexlayout__tab_button--selected { + background-color: var(--color-tab-selected-background); + color: var(--color-tab-selected); +} +@media (hover: hover) { + .flexlayout__tab_button:hover { + background-color: var(--color-tab-selected-background); + color: var(--color-tab-selected); + } +} +.flexlayout__tab_button--unselected { + background-color: var(--color-tab-unselected-background); + color: var(--color-tab-unselected); + color: gray; +} +.flexlayout__tab_button_leading { + display: flex; +} +.flexlayout__tab_button_content { + display: flex; +} +.flexlayout__tab_button_textbox { + border: none; + font-family: var(--font-family); + font-size: var(--font-size); + color: var(--color-tab-textbox); + background-color: var(--color-tab-textbox-background); + border: 1px inset var(--color-1); + border-radius: 3px; + width: 10em; +} +.flexlayout__tab_button_textbox:focus { + outline: none; +} +.flexlayout__tab_button_trailing { + display: flex; + visibility: hidden; + border-radius: 4px; +} +.flexlayout__tab_button_trailing:hover { + background-color: var(--color-3); +} +@media (hover: hover) { + .flexlayout__tab_button:hover .flexlayout__tab_button_trailing { + visibility: visible; + } +} +.flexlayout__tab_button--selected .flexlayout__tab_button_trailing { + visibility: visible; +} +.flexlayout__tab_button_overflow { + display: flex; + align-items: center; + border: none; + color: var(--color-overflow); + font-size: inherit; + background-color: transparent; +} +.flexlayout__tab_toolbar { + display: flex; + align-items: center; + gap: 0.3em; + padding-left: 0.5em; + padding-right: 0.3em; +} +.flexlayout__tab_toolbar_button { + border: none; + outline: none; + font-size: inherit; + margin: 0px; + background-color: transparent; + border-radius: 4px; + padding: 1px; +} +@media (hover: hover) { + .flexlayout__tab_toolbar_button:hover { + background-color: var(--color-2); + } +} +.flexlayout__tab_toolbar_sticky_buttons_container { + display: flex; + gap: 0.3em; + padding-left: 5px; + align-items: center; +} +.flexlayout__tab_floating { + overflow: auto; + position: absolute; + box-sizing: border-box; + color: var(--color-text); + background-color: var(--color-background); + display: flex; + justify-content: center; + align-items: center; +} +.flexlayout__tab_floating_inner { + overflow: auto; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} +.flexlayout__tab_floating_inner div { + margin-bottom: 5px; + text-align: center; +} +.flexlayout__tab_floating_inner div a { + color: royalblue; +} +.flexlayout__border { + box-sizing: border-box; + overflow: hidden; + display: flex; + font-size: var(--font-size); + font-family: var(--font-family); + color: var(--color-border); + background-color: var(--color-border-background); +} +.flexlayout__border_top { + border-bottom: 1px solid var(--color-border-divider-line); + align-items: center; +} +.flexlayout__border_bottom { + border-top: 1px solid var(--color-border-divider-line); + align-items: center; +} +.flexlayout__border_left { + border-right: 1px solid var(--color-border-divider-line); + align-content: center; + flex-direction: column; +} +.flexlayout__border_right { + border-left: 1px solid var(--color-border-divider-line); + align-content: center; + flex-direction: column; +} +.flexlayout__border_inner { + position: relative; + box-sizing: border-box; + display: flex; + overflow: hidden; + flex-grow: 1; +} +.flexlayout__border_inner_tab_container { + white-space: nowrap; + display: flex; + padding-left: 2px; + padding-right: 2px; + box-sizing: border-box; + position: absolute; + top: 0; + bottom: 0; + width: 10000px; +} +.flexlayout__border_inner_tab_container_right { + transform-origin: top left; + transform: rotate(90deg); +} +.flexlayout__border_inner_tab_container_left { + flex-direction: row-reverse; + transform-origin: top right; + transform: rotate(-90deg); +} +.flexlayout__border_tab_divider { + width: 4px; +} +.flexlayout__border_button { + display: flex; + gap: 0.3em; + align-items: center; + cursor: pointer; + padding: 3px 0.5em; + margin: 2px 0px; + box-sizing: border-box; + white-space: nowrap; +} +.flexlayout__border_button--selected { + background-color: var(--color-border-tab-selected-background); + color: var(--color-border-tab-selected); +} +@media (hover: hover) { + .flexlayout__border_button:hover { + background-color: var(--color-border-tab-selected-background); + color: var(--color-border-tab-selected); + } +} +.flexlayout__border_button--unselected { + background-color: var(--color-border-tab-unselected-background); + color: var(--color-border-tab-unselected); +} +.flexlayout__border_button_leading { + display: flex; +} +.flexlayout__border_button_content { + display: flex; +} +.flexlayout__border_button_trailing { + display: flex; + border-radius: 4px; + visibility: hidden; +} +.flexlayout__border_button_trailing:hover { + background-color: var(--color-3); +} +@media (hover: hover) { + .flexlayout__border_button:hover .flexlayout__border_button_trailing { + visibility: visible; + } +} +.flexlayout__border_button--selected .flexlayout__border_button_trailing { + visibility: visible; +} +.flexlayout__border_toolbar { + display: flex; + gap: 0.3em; + align-items: center; +} +.flexlayout__border_toolbar_left, .flexlayout__border_toolbar_right { + flex-direction: column; + padding-top: 0.5em; + padding-bottom: 0.3em; +} +.flexlayout__border_toolbar_top, .flexlayout__border_toolbar_bottom { + padding-left: 0.5em; + padding-right: 0.3em; +} +.flexlayout__border_toolbar_button { + border: none; + outline: none; + font-size: inherit; + background-color: transparent; + border-radius: 4px; + padding: 1px; +} +@media (hover: hover) { + .flexlayout__border_toolbar_button:hover { + background-color: var(--color-2); + } +} +.flexlayout__border_toolbar_button_overflow { + display: flex; + align-items: center; + border: none; + color: var(--color-overflow); + font-size: inherit; + background-color: transparent; +} +.flexlayout__popup_menu { + font-size: var(--font-size); + font-family: var(--font-family); +} +.flexlayout__popup_menu_item { + padding: 2px 0.5em; + white-space: nowrap; + cursor: pointer; + border-radius: 2px; +} +@media (hover: hover) { + .flexlayout__popup_menu_item:hover { + background-color: var(--color-6); + } +} +.flexlayout__popup_menu_container { + box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.15); + border: 1px solid var(--color-popup-border); + color: var(--color-popup-unselected); + background: var(--color-popup-unselected-background); + border-radius: 3px; + position: absolute; + z-index: 1000; + max-height: 50%; + min-width: 100px; + overflow: auto; + padding: 2px; +} +.flexlayout__floating_window _body { + height: 100%; +} +.flexlayout__floating_window_content { + left: 0; + top: 0; + right: 0; + bottom: 0; + position: absolute; +} +.flexlayout__floating_window_tab { + overflow: auto; + left: 0; + top: 0; + right: 0; + bottom: 0; + position: absolute; + box-sizing: border-box; + background-color: var(--color-background); + color: var(--color-text); +} +.flexlayout__error_boundary_container { + left: 0; + top: 0; + right: 0; + bottom: 0; + position: absolute; + display: flex; + justify-content: center; +} +.flexlayout__error_boundary_content { + display: flex; + align-items: center; +} +.flexlayout__tabset_sizer { + padding-top: 5px; + padding-bottom: 3px; + font-size: var(--font-size); + font-family: var(--font-family); +} +.flexlayout__tabset_header_sizer { + padding-top: 3px; + padding-bottom: 3px; + font-size: var(--font-size); + font-family: var(--font-family); +} +.flexlayout__border_sizer { + padding-top: 6px; + padding-bottom: 5px; + font-size: var(--font-size); + font-family: var(--font-family); +} + +/*# sourceMappingURL=light.css.map */ diff --git a/examples/flexlayout-react-demo/public/styles/dark.css b/examples/flexlayout-react-demo/public/styles/dark.css new file mode 100644 index 00000000..711a0a66 --- /dev/null +++ b/examples/flexlayout-react-demo/public/styles/dark.css @@ -0,0 +1,144 @@ +html, +body { + height: 100%; + margin: 0; + padding: 0; + overflow: hidden; + font-size: medium; + font-family: Roboto, Arial, sans-serif; + background-color: black; +} + +.toolbar_control { + color: lightgray; + background-color: black; + border-radius: 3px; + border: 1px solid #444; +} + +.drag-from { + background-color: #666; + color: white; +} + +#container { + left: 10px; + top: 10px; + right: 10px; + bottom: 10px; + position: absolute; + display: flex; + overflow: hidden; + background-color: black; +} +::-webkit-scrollbar { + width: 8px; + height: 8px; +} +::-webkit-scrollbar-button { + background-color: #222; +} +::-webkit-scrollbar-track { + background-color: #444; +} +::-webkit-scrollbar-track-piece { + background-color: #333; +} +::-webkit-scrollbar-thumb { + height: 50px; + background-color: #666; + border-radius: 3px; +} +::-webkit-scrollbar-corner { + background-color: #333; +} +::-webkit-resizer { + background-color: #666; +} + +.app { + display: flex; + flex-direction: column; + flex-grow: 1; +} + +.toolbar { + margin: 2px; + display: flex; + align-items: center; +} + +.contents { + flex-grow: 1; + left: 0; + top: 0; + right: 0; + bottom: 0; + position: relative; + border: 1px solid gray; +} + +/* simple_bundled table styling*/ +.simple_table { + background-color: #222; + color: gray; + border-collapse: collapse; +} +.simple_table th { + color: #ddd; + background-color: #282828; + border-right: 1px solid #333; + padding: 4px; + border-bottom-color: transparent; + text-align: left; + width: 100px; + min-width: 100px; +} + +.simple_table td { + border-right: 1px solid #333; + border-bottom: 1px solid #333; + padding: 4px; +} +.simple_table tr:nth-child(even) { + background: #242424; +} +.simple_table tr:nth-child(odd) { + background: #222; +} + +.tab-storage { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + padding-left: 1em; + padding-right: 1em; + padding-bottom: 1em; + overflow: auto; +} + +.tab-storage > .tab-storage-tabs > .tab-storage-entry { + padding: 1em; + background-color: #222; + border-radius: 0.5em; + margin-bottom: 1em; +} + +.tab-storage > .tab-storage-tabs > .tab-storage-entry:last-child { + margin-bottom: 0; +} + +small { + color: lightgray; +} + +li { + color: white; + margin-bottom: 1em; +} + +ul { + margin-right: 1em; +} diff --git a/examples/flexlayout-react-demo/public/styles/gray.css b/examples/flexlayout-react-demo/public/styles/gray.css new file mode 100644 index 00000000..0955872e --- /dev/null +++ b/examples/flexlayout-react-demo/public/styles/gray.css @@ -0,0 +1,142 @@ +html, +body { + height: 100%; + margin: 0; + padding: 0; + overflow: hidden; + font-size: medium; + font-family: Roboto, Arial, sans-serif; +} + +.toolbar_control { + border-radius: 3px; + border: 1px solid lightgray; +} + +.drag-from { + background-color: lightgray; + color: black; +} + +#container { + left: 10px; + top: 10px; + right: 10px; + bottom: 10px; + position: absolute; + display: flex; + overflow: hidden; + background-color: white; +} + +::-webkit-scrollbar { + width: 8px; + height: 8px; +} +::-webkit-scrollbar-button { + background-color: #ddd; +} +::-webkit-scrollbar-track { + background-color: #efefef; +} +::-webkit-scrollbar-track-piece { + background-color: #eee; +} +::-webkit-scrollbar-thumb { + height: 50px; + background-color: #ccc; + border-radius: 3px; +} +::-webkit-scrollbar-corner { + background-color: #fff; +} +::-webkit-resizer { + background-color: #999; +} + +.app { + display: flex; + flex-direction: column; + flex-grow: 1; +} + +.toolbar { + margin: 2px; + display: flex; + align-items: center; +} + +.contents { + flex-grow: 1; + left: 0; + top: 0; + right: 0; + bottom: 0; + position: relative; + border: 1px solid #ddd; +} + +/* simple_bundled table styling*/ +.simple_table { + background-color: white; + color: #333; + border-collapse: collapse; +} + +.simple_table th { + background-color: #e0e0e0; + border-right: 1px solid #ddd; + padding: 4px; + border-bottom-color: transparent; + text-align: left; + width: 100px; + min-width: 100px; +} + +.simple_table td { + border-right: 1px solid #ddd; + border-bottom-color: transparent; + padding: 4px; +} +.simple_table tr:nth-child(even) { + background: #f0f0f0; +} +.simple_table tr:nth-child(odd) { + background: white; +} + +.tab-storage { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + padding-left: 1em; + padding-right: 1em; + padding-bottom: 1em; + overflow: auto; +} + +.tab-storage > .tab-storage-tabs > .tab-storage-entry { + padding: 1em; + background-color: #ddd; + border-radius: 0.5em; + margin-bottom: 1em; +} + +.tab-storage > .tab-storage-tabs > .tab-storage-entry:last-child { + margin-bottom: 0; +} + +small { + color: gray; +} + +li { + color: #444; + margin-bottom: 1em; +} + +ul { + margin-right: 1em; +} diff --git a/examples/flexlayout-react-demo/public/styles/light.css b/examples/flexlayout-react-demo/public/styles/light.css new file mode 100644 index 00000000..b62081f7 --- /dev/null +++ b/examples/flexlayout-react-demo/public/styles/light.css @@ -0,0 +1,142 @@ +html, +body { + height: 100%; + margin: 0; + padding: 0; + overflow: hidden; + font-size: medium; + font-family: Roboto, Arial, sans-serif; +} + +.toolbar_control { + border-radius: 3px; + border: 1px solid lightgray; +} + +.drag-from { + background-color: lightgray; + color: black; +} + +#container { + left: 10px; + top: 10px; + right: 10px; + bottom: 10px; + position: absolute; + display: flex; + overflow: hidden; + background-color: white; +} + +::-webkit-scrollbar { + width: 8px; + height: 8px; +} +::-webkit-scrollbar-button { + background-color: #ddd; +} +::-webkit-scrollbar-track { + background-color: #efefef; +} +::-webkit-scrollbar-track-piece { + background-color: #eee; +} +::-webkit-scrollbar-thumb { + height: 50px; + background-color: #ccc; + border-radius: 3px; +} +::-webkit-scrollbar-corner { + background-color: #fff; +} +::-webkit-resizer { + background-color: #999; +} + +.app { + display: flex; + flex-direction: column; + flex-grow: 1; +} + +.toolbar { + margin: 2px; + display: flex; + align-items: center; +} + +.contents { + flex-grow: 1; + left: 0; + top: 0; + right: 0; + bottom: 0; + position: relative; + border: 1px solid #ddd; +} + +/* simple_bundled table styling*/ +.simple_table { + background-color: white; + color: #333; + border-collapse: collapse; +} + +.simple_table th { + background-color: #e0e0e0; + border-right: 1px solid #ddd; + padding: 4px; + border-bottom-color: transparent; + text-align: left; + width: 100px; + min-width: 100px; +} + +.simple_table td { + border-right: 1px solid #ddd; + border-bottom-color: transparent; + padding: 4px; +} +.simple_table tr:nth-child(even) { + background: #f0f0f0; +} +.simple_table tr:nth-child(odd) { + background: white; +} + +.tab-storage { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + padding-left: 1em; + padding-right: 1em; + padding-bottom: 1em; + overflow: auto; +} + +.tab-storage > .tab-storage-tabs > .tab-storage-entry { + padding: 1em; + background-color: #f0f0f0; + border-radius: 0.5em; + margin-bottom: 1em; +} + +.tab-storage > .tab-storage-tabs > .tab-storage-entry:last-child { + margin-bottom: 0; +} + +small { + color: gray; +} + +li { + color: #444; + margin-bottom: 1em; +} + +ul { + margin-right: 1em; +} diff --git a/examples/flexlayout-react-demo/public/styles/popupmenu.css b/examples/flexlayout-react-demo/public/styles/popupmenu.css new file mode 100644 index 00000000..9deb89af --- /dev/null +++ b/examples/flexlayout-react-demo/public/styles/popupmenu.css @@ -0,0 +1,37 @@ +.popup_menu { + font-size: var(--font-size); + font-family: var(--font-family); +} +.popup_menu_title { + margin: 2px; + padding: 2px 10px 2px 10px; + white-space: nowrap; + color: var(--color-text); + background-color: var(--color-5); + border-bottom: 1px solid var(--color-6); + cursor: default; +} +.popup_menu_item { + margin: 2px; + padding: 2px 10px 2px 10px; + white-space: nowrap; + cursor: pointer; + border-radius: 2px; +} +@media (hover: hover) { + .popup_menu_item:hover { + background-color: var(--color-6); + } +} +.popup_menu_container { + box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.15); + border: 1px solid var(--color-6); + color: var(--color-text); + background: var(--color-background); + border-radius: 3px; + position: absolute; + z-index: 1000; + max-height: 50%; + min-width: 100px; + overflow: auto; +} diff --git a/examples/flexlayout-react-demo/public/styles/underline.css b/examples/flexlayout-react-demo/public/styles/underline.css new file mode 100644 index 00000000..b62081f7 --- /dev/null +++ b/examples/flexlayout-react-demo/public/styles/underline.css @@ -0,0 +1,142 @@ +html, +body { + height: 100%; + margin: 0; + padding: 0; + overflow: hidden; + font-size: medium; + font-family: Roboto, Arial, sans-serif; +} + +.toolbar_control { + border-radius: 3px; + border: 1px solid lightgray; +} + +.drag-from { + background-color: lightgray; + color: black; +} + +#container { + left: 10px; + top: 10px; + right: 10px; + bottom: 10px; + position: absolute; + display: flex; + overflow: hidden; + background-color: white; +} + +::-webkit-scrollbar { + width: 8px; + height: 8px; +} +::-webkit-scrollbar-button { + background-color: #ddd; +} +::-webkit-scrollbar-track { + background-color: #efefef; +} +::-webkit-scrollbar-track-piece { + background-color: #eee; +} +::-webkit-scrollbar-thumb { + height: 50px; + background-color: #ccc; + border-radius: 3px; +} +::-webkit-scrollbar-corner { + background-color: #fff; +} +::-webkit-resizer { + background-color: #999; +} + +.app { + display: flex; + flex-direction: column; + flex-grow: 1; +} + +.toolbar { + margin: 2px; + display: flex; + align-items: center; +} + +.contents { + flex-grow: 1; + left: 0; + top: 0; + right: 0; + bottom: 0; + position: relative; + border: 1px solid #ddd; +} + +/* simple_bundled table styling*/ +.simple_table { + background-color: white; + color: #333; + border-collapse: collapse; +} + +.simple_table th { + background-color: #e0e0e0; + border-right: 1px solid #ddd; + padding: 4px; + border-bottom-color: transparent; + text-align: left; + width: 100px; + min-width: 100px; +} + +.simple_table td { + border-right: 1px solid #ddd; + border-bottom-color: transparent; + padding: 4px; +} +.simple_table tr:nth-child(even) { + background: #f0f0f0; +} +.simple_table tr:nth-child(odd) { + background: white; +} + +.tab-storage { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + padding-left: 1em; + padding-right: 1em; + padding-bottom: 1em; + overflow: auto; +} + +.tab-storage > .tab-storage-tabs > .tab-storage-entry { + padding: 1em; + background-color: #f0f0f0; + border-radius: 0.5em; + margin-bottom: 1em; +} + +.tab-storage > .tab-storage-tabs > .tab-storage-entry:last-child { + margin-bottom: 0; +} + +small { + color: gray; +} + +li { + color: #444; + margin-bottom: 1em; +} + +ul { + margin-right: 1em; +} diff --git a/examples/flexlayout-react-demo/src/App.tsx b/examples/flexlayout-react-demo/src/App.tsx new file mode 100755 index 00000000..04ddd725 --- /dev/null +++ b/examples/flexlayout-react-demo/src/App.tsx @@ -0,0 +1,373 @@ +// Libs +import React, { useState, useEffect } from "react" +import { Actions, BorderNode, CLASSES, DragDrop, DropInfo, ILayoutProps, Layout, Model, Node, TabNode, TabSetNode } from "flexlayout-react" + +// Project imports +import { useAppContext } from "./Context" +import NewFeatures from "./components/NewFeatures" +import Table from "./components/Table" +import TabStorage from "./components/TabStorage" +import Toolbar from "./components/Toolbar" +import { downloadFile, makeFakeData, showPopup } from "./utils" + +var fields = ["Name", "Field1", "Field2", "Field3", "Field4", "Field5"] + +interface ComponentProps {} + +const App: React.FC = () => { + const ctx = useAppContext() + const layoutRef = React.createRef() + const [loadingLayoutName, setLoadingLayoutName] = useState() + + useEffect(() => { + loadLayout("default", false) + document.body.addEventListener("touchmove", preventIOSScrollingWhenDragging, { passive: false }) + + // use to generate json typescript interfaces + // Model.toTypescriptInterfaces(); + + return () => { + save() + } + }, []) + + const save = () => { + // var jsonStr = JSON.stringify(ctx.model!.toJson(), null, "\t") + // localStorage.setItem(ctx.layoutFile!, jsonStr) + } + + const loadLayout = (layoutName: string, reload?: boolean) => { + if (ctx.layoutFile !== null) { + save() + } + + setLoadingLayoutName(layoutName) + let loaded = false + if (!reload) { + var json = localStorage.getItem(layoutName) + if (json != null) { + load(json) + loaded = true + } + } + + if (!loaded) { + downloadFile("layouts/" + layoutName + ".layout", load, error) + } + } + + const load = (jsonText: string) => { + let json = JSON.parse(jsonText) + let model = Model.fromJson(json) + ctx.setModel(model) + + // model.setOnCreateTabSet((tabNode?: TabNode) => { + // console.log("onCreateTabSet " + tabNode); + // // return { type: "tabset", name: "Header Text" }; + // return { type: "tabset" }; + // }); + + // you can control where nodes can be dropped + //model.setOnAllowDrop(this.allowDrop); + + ctx.setLayoutFile(loadingLayoutName!) + } + + const error = (reason: string) => { + alert("Error loading json config file: " + loadingLayoutName + "\n" + reason) + } + + const preventIOSScrollingWhenDragging = (e: Event) => { + if (DragDrop.instance.isActive()) { + e.preventDefault() + } + } + + const allowDrop = (dragNode: TabNode | TabSetNode, dropInfo: DropInfo) => { + let dropNode = dropInfo.node + + // prevent non-border tabs dropping into borders + if (dropNode.getType() === "border" && (dragNode.getParent() == null || dragNode.getParent()!.getType() != "border")) return false + + // prevent border tabs dropping into main layout + if (dropNode.getType() !== "border" && dragNode.getParent() != null && dragNode.getParent()!.getType() == "border") return false + + return true + } + + const onSelectLayout = (event: React.FormEvent) => { + var target = event.target as HTMLSelectElement + loadLayout(target.value) + } + + const onAddFromTabSetButton = (node: TabSetNode | BorderNode) => { + ctx.incNextGridIndex() + layoutRef!.current!.addTabToTabSet(node.getId(), { + component: "grid", + name: "Grid " + ctx.nextGridIndex, + }) + } + + const props: ILayoutProps = { + model: ctx.model!, + factory(node) { + // log lifecycle events + //node.setEventListener("resize", function(p){console.log("resize", node);}); + //node.setEventListener("visibility", function(p){console.log("visibility", node);}); + //node.setEventListener("close", function(p){console.log("close", node);}); + + var component = node.getComponent() + + if (component === "json") { + return
+      } else if (component === "grid") {
+        if (node.getExtraData().data == null) {
+          // create data in node extra data first time accessed
+          node.getExtraData().data = makeFakeData(fields)
+        }
+
+        return  {}} data={node.getExtraData().data} />
+        //   return 
+ } else if (component === "sub") { + var model = node.getExtraData().model + if (model == null) { + node.getExtraData().model = Model.fromJson(node.getConfig().model) + model = node.getExtraData().model + // save submodel on save event + node.setEventListener("save", (p: any) => { + ctx.model!.doAction(Actions.updateNodeAttributes(node.getId(), { config: { model: node.getExtraData().model.toJson() } })) + // node.getConfig().model = node.getExtraData().model.toJson(); + }) + } + + return + } else if (component === "text") { + try { + return
+ } catch (e) { + console.log(e) + } + } else if (component === "newfeatures") { + return + } else if (component === "multitype") { + try { + const config = node.getConfig() + if (config.type === "url") { + return