├── .eslintignore
├── .eslintrc
├── .github
└── dependabot.yml
├── .gitignore
├── .npmignore
├── CHANGELOG.md
├── README.md
├── demo
├── app.vue
├── demo-stack.vue
├── dist
│ ├── app.js
│ ├── favicon.ico
│ └── index.html
├── favicon.ico
├── index.ejs
├── index.ts
├── layout-route.vue
├── p-head.vue
├── router.ts
├── tree.vue
├── tsconfig.json
└── webpack.config.js
├── dts-bundle-plugin.js
├── jsconfig.json
├── package-lock.json
├── package.json
├── src
├── @types
│ └── vue-resize-directive.d.ts
├── colors.ts
├── gl-component.vue
├── gl-dstack.ts
├── gl-group.vue
├── gl-groups.ts
├── golden.vue
├── index.ts
├── roles
│ ├── child.ts
│ ├── container.ts
│ ├── index.ts
│ ├── item.ts
│ └── link.ts
├── router
│ ├── gl-component-route.ts
│ ├── gl-container-route.vue
│ ├── gl-route-base.ts
│ ├── gl-route.vue
│ ├── gl-router.vue
│ └── utils.ts
├── tsconfig.json
└── utils.ts
└── webpack.config.js
/.eslintignore:
--------------------------------------------------------------------------------
1 | **/*.js
2 | *.json
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "es6": true
5 | },
6 | "extends": [
7 | "eslint:recommended",
8 | "plugin:vue/essential"
9 | ],
10 | "globals": {
11 | "Atomics": "readonly",
12 | "SharedArrayBuffer": "readonly"
13 | },
14 | "parserOptions": {
15 | "parser": "@typescript-eslint/parser",
16 | "ecmaVersion": 2018,
17 | "sourceType": "module",
18 | "ecmaFeatures": {
19 | "legacyDecorators": true
20 | }
21 | },
22 | "plugins": [
23 | "vue",
24 | "@typescript-eslint"
25 | ],
26 | "rules": {
27 | "no-console": "off",
28 | "no-unused-vars": "warn"
29 | }
30 | }
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: npm
4 | directory: "/"
5 | schedule:
6 | interval: daily
7 | open-pull-requests-limit: 10
8 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
3 | /dist
4 | .vscode
5 | coverage
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
3 | demo
4 | test
5 | .*
6 | yalc.lock
7 | package-lock.*
8 | *.lock
9 | webpack.*
10 | coverage
11 | doc
12 | .eslint*
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 |
8 | ## [2.0.10] - 2020-07-18
9 |
10 | ### Fixed
11 |
12 | - adding return value for the goldenContainer data mixin
13 |
14 | ## [2.0.9] - 2020-06-23
15 |
16 | ### Fixed
17 |
18 | - issue#59
19 |
20 | ## [2.0.8] - 2020-06-15
21 |
22 | ### Changed
23 |
24 | - Component' model becomes a generic `state.sync` that can be used on any GL object
25 |
26 | ## [2.0.7] - 2020-06-14
27 |
28 | ### Added
29 |
30 | - Component' model
31 |
32 | ## [2.0.5] - 2020-02-28
33 |
34 | ### Changed
35 |
36 | - Used packages upgrade
37 |
38 | ## [2.0.4] - 2020-02-28
39 |
40 | ### Fixed
41 |
42 | - issue #57
43 |
44 | ## [2.0.3] - 2020-02-18
45 |
46 | ### Fixed
47 |
48 | - issue #55
49 |
50 | ## [2.0.2] - 2019-11-08
51 |
52 | ### Fixed
53 |
54 | - Obsolete code removal
55 | - issue-51
56 | - `forwardEvent` calls
57 |
58 | ## [2.0.1] - 2019-10.xx
59 |
60 | ### Added
61 |
62 | - `vueComponent.focus()`
63 |
64 | ### Changed
65 |
66 | - Lots of code clean-up
67 | - Fix moving random tab in `gl-router`
68 | - Documentation rewriting
69 | - Selecting a tab in a `d-stack` now `focus()` it even if it is not in the d-stack anymore
70 |
71 | ## [2.0.0] - 2019-10.xx
72 |
73 | ### Added
74 |
75 | - Cross-windows synchronisation: one `vue` tree controls all the windows
76 | - Custom containers: allows to define custom controls who contain a part of the layout
77 | - Custom containers as route components
78 | - Branch coloring to retrieve which master goes with which slave easily
79 |
80 | ### Changed
81 |
82 | - Named template are obsolete, components are to be defined inline
83 |
84 | ## [1.5.14] - 2019-02-15
85 |
86 | ### Added
87 |
88 | - `inter-window` property
89 |
90 | ### Fixed
91 |
92 | - Templates now can access to the `VueComponent`' data
93 | - `golden-layout` and `gl-items` are not observed anymore
94 | - Security vulnerability fix
95 |
96 | ## [1.5.13] - 2019-01-15
97 |
98 | ### Fixed
99 |
100 | - Routes and custom components have a `glComponent` class
101 |
102 | ## [1.5.12] - 2019-01-09
103 |
104 | ### Fixed
105 |
106 | - Security vulnerability fix
107 |
108 | ## [1.5.10] - 2018-11-28
109 |
110 | ### Fixed
111 |
112 | - The `state` as a `Promise` is indeed a pretty neat solution. Tested and a bit corrected
113 | - Weird bug corrected with the saved state of popups (arraay-like objects not array ... ?!?)
114 |
115 | ## [1.5.9] - 2018-11-24
116 |
117 | The branch `feature/dstack` has been merged with the `gl-dstack` functionality (implemented by the `gl-router`)
118 |
119 | ### Added
120 |
121 | - The control `gl-dstack` that behaves like a `gl-stack` but remains opened in the main window when poped-out
122 | - The control `gl-route` allows the user to use the routing hacks implemented here
123 | - The golden-layout `state` can be given as a Promise
124 | - The property `reorder-enabled` that can avoid a tab to be dragged
125 |
126 | ## [1.5.8] - 2018-10-30
127 |
128 | The library has become stable enough for us to take care to keep a stable master branch. Let's get this libray from "hobby" level to "serious" one.
129 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # vue-golden-layout
3 |
4 | [](https://www.npmjs.com/package/vue-golden-layout)
5 | [](https://gist.github.com/cheerfulstoic/d107229326a01ff0f333a1d3476e068d)
6 |
7 | _DEPRECATED_: The project is not maintained anymore. A new version for Vue3 has been begun here : https://github.com/emedware/v3-gl-ext
8 |
9 |
10 | Integration of the golden-layout to Vue
11 |
12 | ## Installation
13 |
14 | ```sh
15 | npm i -S vue-golden-layout
16 | ```
17 |
18 | ### Fast example
19 |
20 | ```html
21 |
22 |
23 |
24 |
Component 1
25 |
26 |
27 |
28 |
Component 2
29 |
30 |
31 |
Component 3
32 |
33 |
34 |
35 |
36 | ```
37 |
38 | Note: each component who is not rendered in a stack will indeed be rendered in a golden-layout singleton stack.
39 |
40 | ### Bigger example
41 |
42 | > Demo available [here](https://rawcdn.githack.com/emedware/vue-golden-layout/master/demo/dist/index.html)
43 |
44 | A more complex exemple is in the project when git-cloned.
45 | In order to test, the static sample application can be compiled like this:
46 |
47 | ```sh
48 | npm install
49 | npm run demo
50 | ```
51 |
52 | You can now browse `http://localhost:9000`
53 |
54 | The example can be found in the sources under the '/demo' folder
55 |
56 | ## Usage
57 |
58 | ```javascript
59 | import vgl from 'vue-golden-layout'
60 | Vue.use(vgl);
61 | ```
62 |
63 | In case of incompatibility with bundlers, `vue-golden-layout` can be bundeled by the sources.
64 | The sources entry point is in `vue-golden-layout/src/index.ts`
65 |
66 | ```javascript
67 | import vgl from 'vue-golden-layout/src'
68 | Vue.use(vgl);
69 | ```
70 |
71 | ### Don't forget in order to make it work
72 |
73 | - Include a golden-layout theme CSS.
74 |
75 | ```typescript
76 | import 'golden-layout/src/css/goldenlayout-light-theme.css'
77 | ```
78 |
79 | Available themes are `light`, `dark`, `soda`, `translucent`.
80 |
81 | `goldenlayout-base.css` is already integrated to the library.
82 |
83 | ## Structure
84 |
85 | Elements like ``, `` and `` can be represented in a tree - they respectively stand for a golden-layout row, column and stack.
86 |
87 | ### Components
88 |
89 | Component are described *by extension* - namely, by giving their content using the data from the defining component.
90 |
91 | ```html
92 |
93 |
Heydoo
94 | Price: {{priceLess}}
95 |
96 | ```
97 |
98 | ## Saving/restoring states
99 |
100 | > TL;DR: The state is the model of the golden-layout object
101 |
102 | The `golden-layout` has a *property* and an *event* named `state`.
103 |
104 | - The event is triggered when the state has changed (even deeply, like a deep watch).
105 | - The property is used [**at mount**](https://github.com/emedware/vue-golden-layout/issues/20#issuecomment-433828678) to initialise the configuration. After that, any change will have no effect.
106 | - The `state` property can be a `Promise`, then the golden-layout will be rendered only when the `Promise` has been resolved.
107 |
108 | Notes:
109 |
110 | - The property `state` can be given minified or not
111 | - The event `state` gives indeed the minified version of the config, and the expanded version as a second argument.
112 | - It is also the `v-model` of the `golden-layout`
113 | - In order to reload a state, the Vue object structure must corresp to the state it be applied to
114 | - If there is a miss-match between the Vue object structure and the state, the `golden-layout` object `creation-error` event will be raised
115 |
116 | ### Sub-object states
117 |
118 | Every `` can have a `:state.sync` property (`Dictionary`) that will be saved along his other properties in the golden-layout state.
119 | This is a good place for example for custom containers to store locally what is needed to be persisted.
120 |
121 | ## Components events and properties
122 |
123 | ### Events
124 |
125 | #### Layout' events
126 |
127 | Straight forwards from golden-layout, refer to their doc
128 |
129 | ```javascript
130 | itemCreated
131 | stackCreated
132 | rowCreated
133 | tabCreated
134 | columnCreated
135 | componentCreated
136 | selectionChanged
137 | windowOpened
138 | windowClosed
139 | itemDestroyed
140 | initialised
141 | activeContentItemChanged
142 | ```
143 |
144 | #### Contained objects' events
145 |
146 | Straight forwards from golden-layout, refer to their doc
147 |
148 | ```javascript
149 | stateChanged
150 | titleChanged
151 | activeContentItemChanged
152 | beforeItemDestroyed
153 | itemDestroyed
154 | itemCreated
155 | ```
156 |
157 | #### Components' events
158 |
159 | Straight forwards from golden-layout, refer to their doc
160 |
161 | ```javascript
162 | open
163 | destroy
164 | close
165 | tab
166 | hide
167 | show
168 | resize
169 | ```
170 |
171 | ### Properties
172 |
173 | #### Layout' properties
174 |
175 | ```typescript
176 | @Prop({default: true}) hasHeaders: boolean
177 | @Prop({default: true}) reorderEnabled: boolean
178 | @Prop({default: false}) selectionEnabled: boolean
179 | @Prop({default: true}) popoutWholeStack: boolean
180 | @Prop({default: true}) closePopoutsOnUnload: boolean
181 | @Prop({default: true}) showPopoutIcon: boolean
182 | @Prop({default: true}) showMaximiseIcon: boolean
183 | @Prop({default: true}) showCloseIcon: boolean
184 | @Prop({default: 5}) borderWidth: number
185 | @Prop({default: 10}) minItemHeight: number
186 | @Prop({default: 10}) minItemWidth: number
187 | @Prop({default: 20}) headerHeight: number
188 | @Prop({default: 300}) dragProxyWidth: number
189 | @Prop({default: 200}) dragProxyHeight: number
190 | ```
191 |
192 | ##### `popup-timeout`
193 |
194 | (default: 5 = 5 seconds)
195 |
196 | When the state change, an event is fired and provides the new state. Unfortunately, when something is poped-out, querying the state will raise an exception if the pop-out' golden-layout is not loaded. Hence, the first call to `GoldenLayout.toConfig()` will for sure raise an exception.
197 |
198 | The policy chosen here is to then wait a bit and try again. In order to avoid infinite exception+try-again, a time-out is still specified.
199 |
200 | Therefore:
201 |
202 | - Changing this value to higher will not postpone the event fireing, it will just allow more time for the pop-out to load before raising an exception
203 | - This can be useful to increase in applications where the main page has some long loading process before displaying the golden-layout
204 |
205 | #### Contained objects' properties
206 |
207 | - `title: string`: Used for tab title
208 | - `tabId: string`: Used as the `v-model` of a `gl-stack` or `gl-dstack` to determine/set the active tab
209 | - `width: number`
210 | - `height: number`
211 | - `closable: boolean`
212 | - `reorderEnabled: boolean`
213 | - `hidden: boolean`
214 |
215 | #### Contained objects' methods
216 |
217 | - `show()` and `hide()` respectively show and hide the element
218 | - `focus()` brings the element in front recursively, making sure all tabs are right for them to be visible (also brings the window in front if needed)
219 | - `delete()` delete the vue-object and the gl-object
220 | - `nodePath` is the unique path to this node from the golden-layout root (can change).
221 | The golden-layout object has a method `getSubChild(path: string)` that returns this vue-object (useful between page reload)
222 |
223 | #### Containers
224 |
225 | Containers have an additional `color-group: boolean` property defaulted to `false`.
226 | A container for which this property is set to `true` will see all his descendants have a color assigned to their tabs.
227 |
228 | This is meant to be used when the same component can be used twice on different objects, to follow in the pop-outs which is the descendant of which.
229 |
230 | Note: by default, routes that are `glCustomContainer` have a `color-group` set to `true`
231 |
232 | ## Specific components
233 |
234 | Some components have been programmed as an extension, even if they are not part of golden-layout *proprio sensu*.
235 |
236 | ### gl-dstack
237 |
238 | *Duplicatable stacks* are stacks that should always remain in the main window as their content is modified programatically. These stacks, when poped-out, *remain* in the main screen while their content is poped-out.
239 | Components defined in it that are not `closable` nor `reorder-enabled` will *stay* in the stack in the main window.
240 |
241 | ### gl-router
242 |
243 | The router is a `glContainer` that aims to sublimate the ``
244 | It lets users manage their routes in tabs, open them in a split screen or even popped-out in another browser window on another physical display.
245 |
246 | The main usage is ``. Any options of `router-view` still has to be implemented.
247 |
248 | Note: `gl-router` is a `gl-dstack`.
249 |
250 | #### gl-router' slots
251 |
252 | A default content to render all routes can be provided as the `route` slot template - with or without scope : if a scope is queried, it will be the route object.
253 | If this content is provided, it should contain a `` tag that will be filled with the loaded route component.
254 |
255 | Note: the provided template will be ignored when maximised/popped-out.
256 |
257 | All the components in the default slot will be added as tabs in the router.
258 |
259 | #### gl-router' properties
260 |
261 | ##### `titler`
262 |
263 | Allows to specify a function that takes a route object in parameter and gives the string that will be used as tab title.
264 | If none is specified, the default is to take `$route.meta.title` - this means that routes have to be defined with a title in their meta-data.
265 |
266 | ##### `empty-route`
267 |
268 | Specify the URL to use when the user closes all the tabs (`"/"` by default)
269 |
270 | ### gl-route
271 |
272 | `gl-route`s are components displaying a route. They are meant to be used in a gl-router but only have to be used in a golden-layout container.
273 |
274 | They can take a `name` and/or a `path`, and their `closable` and `reorder-enabled` properties are false by default. They can be forced a `title` but their container' `titler` will be used if not.
275 |
276 | Note: all the elements inside them will have a `this.$route` pointing to the given route, not the actual URL.
277 |
278 | ## glCustomContainers
279 |
280 | Users can define components who describe a part of the layout. In order to do this, instead of extending `Vue`, the component has to extend `glCustomContainer`.
281 |
282 | ```js
283 | var comp = Vue.extend({...});
284 | // becomes
285 | var vgl = require('vue-golden-layout')
286 | var comp = vgl.glCustomContainer.extend({...});
287 | ```
288 |
289 | ```ts
290 | @Component
291 | export class MyComp extends Vue {
292 | ...
293 | }
294 | // becomes
295 | import { glCustomContainer } from 'vue-golden-layout'
296 |
297 | @Component
298 | export class MyComp extends glCustomContainer {
299 | ...
300 | }
301 | ```
302 |
303 | The template' root must therefore be a proper golden-layout child (row, col, stack, ...)
304 |
305 | These components can be used as route components.
306 |
307 | ## Low-level functionalities
308 |
309 | ### Global components
310 |
311 | Some golden-layout global component can be given before any instanciation (while declaring classes) by calling this function:
312 |
313 | ```typescript
314 | import { registerGlobalComponent } from 'vue-golden-layout'
315 | // registerGlobalComponent(name: string, comp: (gl: goldenLayout, container: any, state: any)=> void)
316 | ```
317 |
318 | `(container: any, state: any)=> void` is the signature of a gloden-layout component and they are created per golden-layout instances
319 |
320 | ### `isSubWindow`
321 |
322 | ```typescript
323 | import { isSubWindow } from 'vue-golden-layout'
324 | ```
325 |
326 | The main application component will be created in any pop-out that is opened. The `` node will generate an empty HTML content, so nothing in it will be rendered. Though, if needed, this value is `true` when the component is generated in a pop-out which indicate that the component won't even be rendered and should take no action.
327 |
328 | ### CSS
329 |
330 | The elements with the `glComponent` CSS class are the ones directly included in the `
` controlled and sized by golden-layout and answers to this class to fit in the layout child container, that can be overridden
331 |
332 | ```css
333 | .glComponent {
334 | width: 100%;
335 | height: 100%;
336 | overflow: auto;
337 | }
338 | ```
339 |
340 | ### Objects linking
341 |
342 | Golden-layout and Vue both have objects representing their internal state. A `glRow` is associated with a `ContentItem`.
343 |
344 | Each vue object has a `glObject` property and, vice versa, each golden-layout object has a `vueObject` property linking to each another.
345 |
346 | #### Virtual vs actual tree
347 |
348 | Vue objects (rows, components, stacks, ...) all have a `$parent` that retrieve their Vue' parent. Also their children might be retrieved with `$children`.
349 |
350 | Though, the user might change the order of things and who contain what. To retrieve the golden-layout-wise hierarchy, we can use `glParent` as well as `glChildren` on the vue objects to retrieve vue objects.
351 |
--------------------------------------------------------------------------------
/demo/app.vue:
--------------------------------------------------------------------------------
1 |
2 |