@perspective-dev/workspace 4.0.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/LICENSE.md +193 -0
- package/dist/cdn/perspective-workspace.js +45 -0
- package/dist/cdn/perspective-workspace.js.map +7 -0
- package/dist/css/pro-dark.css +1 -0
- package/dist/css/pro.css +1 -0
- package/dist/esm/perspective-workspace.d.ts +181 -0
- package/dist/esm/perspective-workspace.js +14 -0
- package/dist/esm/perspective-workspace.js.map +7 -0
- package/dist/esm/utils/custom_elements.d.ts +14 -0
- package/dist/esm/utils/observable_map.d.ts +9 -0
- package/dist/esm/workspace/commands.d.ts +3 -0
- package/dist/esm/workspace/dockpanel.d.ts +13 -0
- package/dist/esm/workspace/index.d.ts +1 -0
- package/dist/esm/workspace/menu.d.ts +11 -0
- package/dist/esm/workspace/tabbar.d.ts +25 -0
- package/dist/esm/workspace/tabbarrenderer.d.ts +19 -0
- package/dist/esm/workspace/widget.d.ts +27 -0
- package/dist/esm/workspace/workspace.d.ts +123 -0
- package/package.json +55 -0
- package/src/html/workspace.html +11 -0
- package/src/less/dockpanel.less +95 -0
- package/src/less/injected.less +14 -0
- package/src/less/menu.less +128 -0
- package/src/less/tabbar.less +366 -0
- package/src/less/viewer.less +86 -0
- package/src/less/widget.less +40 -0
- package/src/less/workspace.less +70 -0
- package/src/svg/bookmark-icon.svg +4 -0
- package/src/svg/drag-handle.svg +10 -0
- package/src/themes/pro-dark.less +139 -0
- package/src/themes/pro.less +93 -0
- package/src/ts/external.d.ts +21 -0
- package/src/ts/external.js +11 -0
- package/src/ts/perspective-workspace.ts +306 -0
- package/src/ts/utils/custom_elements.ts +95 -0
- package/src/ts/utils/observable_map.ts +39 -0
- package/src/ts/workspace/commands.ts +269 -0
- package/src/ts/workspace/dockpanel.ts +145 -0
- package/src/ts/workspace/index.ts +13 -0
- package/src/ts/workspace/menu.ts +213 -0
- package/src/ts/workspace/tabbar.ts +237 -0
- package/src/ts/workspace/tabbarrenderer.ts +91 -0
- package/src/ts/workspace/widget.ts +101 -0
- package/src/ts/workspace/workspace.ts +1056 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
2
|
+
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
|
3
|
+
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
|
4
|
+
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
|
5
|
+
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
|
6
|
+
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
|
7
|
+
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
|
8
|
+
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
|
9
|
+
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
|
10
|
+
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
|
+
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
|
+
|
|
13
|
+
@grey60: #c5c9d0;
|
|
14
|
+
@grey500: #3b3f46;
|
|
15
|
+
@grey600: #2f3136;
|
|
16
|
+
@grey700: #2a2c2f;
|
|
17
|
+
@grey800: #242526;
|
|
18
|
+
|
|
19
|
+
perspective-workspace,
|
|
20
|
+
perspective-workspace[theme="Pro Dark"],
|
|
21
|
+
perspective-indicator[theme="Pro Dark"] {
|
|
22
|
+
--theme-name: "Pro Dark";
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
perspective-workspace perspective-viewer {
|
|
26
|
+
--status-bar--height: 39px;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
perspective-workspace perspective-viewer[settings] {
|
|
30
|
+
--modal-panel--margin: -4px 0 -4px 0;
|
|
31
|
+
--status-bar--border-radius: 6px 0 0 0;
|
|
32
|
+
--main-column--margin: 3px 0 3px 3px;
|
|
33
|
+
--main-column--border: 1px solid var(--inactive--color);
|
|
34
|
+
--main-column--border-width: 1px 0px 1px 1px;
|
|
35
|
+
--main-column--border-radius: 6px 0 0 6px;
|
|
36
|
+
--settings-button--margin: 10px 0 0 0;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
perspective-workspace {
|
|
40
|
+
@include perspective-workspace-pro-base;
|
|
41
|
+
@include perspective-viewer-pro-dark--colors;
|
|
42
|
+
|
|
43
|
+
background-color: #000202;
|
|
44
|
+
color: white;
|
|
45
|
+
// --workspace-master--background-color: @grey800;
|
|
46
|
+
--workspace-tabbar--background-color: @grey800;
|
|
47
|
+
// --workspace-tabbar--border: 1px solid @grey500;
|
|
48
|
+
// --workspace-tabbar--border-color: @grey500;
|
|
49
|
+
--workspace-secondary--color: @grey60;
|
|
50
|
+
--workspace-tabbar--border: 1px solid var(--inactive--color);
|
|
51
|
+
--workspace-tabbar--border-width: 0px 1px 1px 1px;
|
|
52
|
+
--workspace-tabbar--border-radius: 6px;
|
|
53
|
+
--workspace-tabbar--border-color: var(--inactive--color);
|
|
54
|
+
--workspace-tabbar-tab--border-width: 1px 1px 0 1px;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
perspective-viewer[theme="Pro Dark"].workspace-master-widget {
|
|
58
|
+
--plugin--background: @grey800;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
perspective-workspace-menu {
|
|
62
|
+
font-family:
|
|
63
|
+
"ui-monospace", "SFMono-Regular", "SF Mono", "Menlo", "Consolas",
|
|
64
|
+
"Liberation Mono", monospace;
|
|
65
|
+
font-weight: 300;
|
|
66
|
+
background: @grey700 !important;
|
|
67
|
+
color: white !important;
|
|
68
|
+
border: 1px solid @grey500 !important;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
@mixin perspective-workspace-pro-base {
|
|
72
|
+
font-family:
|
|
73
|
+
"ui-monospace", "SFMono-Regular", "SF Mono", "Menlo", "Consolas",
|
|
74
|
+
"Liberation Mono", monospace;
|
|
75
|
+
--open-settings-button--content: "expand_more";
|
|
76
|
+
--close-settings-button--content: "expand_less";
|
|
77
|
+
--close-button--content: "\2715";
|
|
78
|
+
--master-divider--background-color: #243136;
|
|
79
|
+
--menu-maximize--content: "fullscreen";
|
|
80
|
+
--menu-minimize--content: "fullscreen_exit";
|
|
81
|
+
--menu-duplicate--content: "call_split";
|
|
82
|
+
--menu-master--content: "cast";
|
|
83
|
+
--menu-detail--content: "notes";
|
|
84
|
+
--menu-export--content: "file_download";
|
|
85
|
+
--menu-copy--content: "file_copy";
|
|
86
|
+
--menu-reset--content: "autorenew";
|
|
87
|
+
--menu-link--content: "link";
|
|
88
|
+
--menu-unlink--content: "link_off";
|
|
89
|
+
--menu-newmenu--content: "add";
|
|
90
|
+
--menu-close--content: "close";
|
|
91
|
+
--menu-new--content: "description";
|
|
92
|
+
--menu-newview--content: "file_copy";
|
|
93
|
+
|
|
94
|
+
--workspace-tabbar--border: 1px solid var(--inactive--color);
|
|
95
|
+
--workspace-tabbar--border-width: 0px 1px 1px 1px;
|
|
96
|
+
--workspace-tabbar--border-radius: 6px;
|
|
97
|
+
--workspace-tabbar--border-color: var(--inactive--color);
|
|
98
|
+
--workspace-tabbar-tab--border-width: 1px 1px 0px 1px;
|
|
99
|
+
|
|
100
|
+
// Workspace
|
|
101
|
+
--column-drag-handle--mask-image: url("../svg/drag-handle.svg");
|
|
102
|
+
--bookmarks--mask-image: url("../svg/bookmark-icon.svg");
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
@mixin perspective-viewer-pro-dark--colors {
|
|
106
|
+
background-color: #242526;
|
|
107
|
+
--workspace-split-panel-handle--background-color: @grey800;
|
|
108
|
+
color: white;
|
|
109
|
+
--icon--color: white;
|
|
110
|
+
--active--color: #2770a9;
|
|
111
|
+
--error--color: #ff9485;
|
|
112
|
+
--inactive--color: #61656e;
|
|
113
|
+
--inactive--border-color: #4c505b;
|
|
114
|
+
--plugin--background: #242526;
|
|
115
|
+
--modal-target--background: rgba(255, 255, 255, 0.05);
|
|
116
|
+
--active--background: rgba(39, 113, 170, 0.5);
|
|
117
|
+
--expression--operator-color: #c5c9d0;
|
|
118
|
+
--expression--function-color: #22a0ce;
|
|
119
|
+
--expression--error-color: rgb(255, 136, 136);
|
|
120
|
+
--calendar--filter: invert(1);
|
|
121
|
+
--warning--color: #242526;
|
|
122
|
+
--warning--background: var(--icon--color);
|
|
123
|
+
|
|
124
|
+
--select-arrow--background-image: var(
|
|
125
|
+
--select-arrow-light--background-image
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
--select-arrow--hover--background-image: var(
|
|
129
|
+
--select-arrow-dark--background-image
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
// Syntax
|
|
133
|
+
--code-editor-symbol--color: white;
|
|
134
|
+
--code-editor-literal--color: #7dc3f0;
|
|
135
|
+
--code-editor-operator--color: rgb(23, 166, 123);
|
|
136
|
+
--code-editor-comment--color: rgb(204, 120, 48);
|
|
137
|
+
--code-editor-column--color: #e18ee1;
|
|
138
|
+
// --code-editor-unknown--color: rgb(204, 120, 48);
|
|
139
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
2
|
+
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
|
3
|
+
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
|
4
|
+
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
|
5
|
+
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
|
6
|
+
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
|
7
|
+
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
|
8
|
+
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
|
9
|
+
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
|
10
|
+
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
|
+
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
|
+
|
|
13
|
+
@import url("ref://pro.less");
|
|
14
|
+
|
|
15
|
+
perspective-workspace,
|
|
16
|
+
perspective-workspace[theme="Pro Light"],
|
|
17
|
+
perspective-indicator[theme="Pro Light"] {
|
|
18
|
+
--theme-name: "Pro Light";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
perspective-workspace {
|
|
22
|
+
@include perspective-workspace-pro-base;
|
|
23
|
+
@include perspective-viewer-pro--colors;
|
|
24
|
+
background-color: #dadada;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
perspective-workspace perspective-viewer[settings] {
|
|
28
|
+
--modal-panel--margin: -4px 0 -4px 0;
|
|
29
|
+
--status-bar--border-radius: 6px 0 0 0;
|
|
30
|
+
--main-column--margin: 3px 0 3px 3px;
|
|
31
|
+
--main-column--border: 1px solid var(--inactive--color);
|
|
32
|
+
--main-column--border-width: 1px 0px 1px 1px;
|
|
33
|
+
--main-column--border-radius: 6px 0 0 6px;
|
|
34
|
+
--settings-button--margin: 10px 0 0 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
perspective-workspace perspective-viewer {
|
|
38
|
+
--status-bar--height: 39px;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
perspective-viewer[theme="Pro Light"].workspace-master-widget {
|
|
42
|
+
background-color: #f2f4f6;
|
|
43
|
+
--plugin--background: #f2f4f6;
|
|
44
|
+
regular-table {
|
|
45
|
+
td,
|
|
46
|
+
th {
|
|
47
|
+
border-color: #e0e4e9;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@mixin perspective-workspace-pro-base {
|
|
53
|
+
font-family:
|
|
54
|
+
"ui-monospace", "SFMono-Regular", "SF Mono", "Menlo", "Consolas",
|
|
55
|
+
"Liberation Mono", monospace;
|
|
56
|
+
--open-settings-button--content: "expand_more";
|
|
57
|
+
--close-settings-button--content: "expand_less";
|
|
58
|
+
--close-button--content: "\2715";
|
|
59
|
+
--master-divider--background-color: #243136;
|
|
60
|
+
--menu-maximize--content: "fullscreen";
|
|
61
|
+
--menu-minimize--content: "fullscreen_exit";
|
|
62
|
+
--menu-duplicate--content: "call_split";
|
|
63
|
+
--menu-master--content: "cast";
|
|
64
|
+
--menu-detail--content: "notes";
|
|
65
|
+
--menu-export--content: "file_download";
|
|
66
|
+
--menu-copy--content: "file_copy";
|
|
67
|
+
--menu-reset--content: "autorenew";
|
|
68
|
+
--menu-link--content: "link";
|
|
69
|
+
--menu-unlink--content: "link_off";
|
|
70
|
+
--menu-newmenu--content: "add";
|
|
71
|
+
--menu-close--content: "close";
|
|
72
|
+
--menu-new--content: "description";
|
|
73
|
+
--menu-newview--content: "file_copy";
|
|
74
|
+
--workspace-split-panel-handle--background-color: #f2f4f6;
|
|
75
|
+
|
|
76
|
+
--workspace-tabbar--border: 1px solid var(--inactive--color);
|
|
77
|
+
--workspace-tabbar--border-width: 0px 1px 1px 1px;
|
|
78
|
+
--workspace-tabbar--border-radius: 6px;
|
|
79
|
+
--workspace-tabbar--border-color: var(--inactive--color);
|
|
80
|
+
--workspace-tabbar-tab--border-width: 1px 1px 0px 1px;
|
|
81
|
+
|
|
82
|
+
// Workspace
|
|
83
|
+
--column-drag-handle--mask-image: url("../svg/drag-handle.svg");
|
|
84
|
+
--bookmarks--mask-image: url("../svg/bookmark-icon.svg");
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
perspective-workspace-menu {
|
|
88
|
+
font-family:
|
|
89
|
+
"ui-monospace", "SFMono-Regular", "SF Mono", "Menlo", "Consolas",
|
|
90
|
+
"Liberation Mono", monospace;
|
|
91
|
+
font-weight: 300;
|
|
92
|
+
color: #161616;
|
|
93
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
2
|
+
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
|
3
|
+
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
|
4
|
+
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
|
5
|
+
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
|
6
|
+
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
|
7
|
+
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
|
8
|
+
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
|
9
|
+
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
|
10
|
+
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
|
+
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
|
+
|
|
13
|
+
declare module "*.css" {
|
|
14
|
+
const content: string;
|
|
15
|
+
export default content;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
declare module "*.html" {
|
|
19
|
+
const content: string;
|
|
20
|
+
export default content;
|
|
21
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
2
|
+
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
|
3
|
+
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
|
4
|
+
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
|
5
|
+
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
|
6
|
+
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
|
7
|
+
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
|
8
|
+
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
|
9
|
+
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
|
10
|
+
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
|
+
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
2
|
+
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
|
3
|
+
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
|
4
|
+
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
|
5
|
+
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
|
6
|
+
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
|
7
|
+
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
|
8
|
+
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
|
9
|
+
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
|
10
|
+
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
|
+
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
|
+
|
|
13
|
+
import { MessageLoop } from "@lumino/messaging";
|
|
14
|
+
import { Widget } from "@lumino/widgets";
|
|
15
|
+
import { HTMLPerspectiveViewerElement } from "@perspective-dev/viewer";
|
|
16
|
+
import type * as psp from "@perspective-dev/client";
|
|
17
|
+
|
|
18
|
+
export { PerspectiveWorkspace } from "./workspace";
|
|
19
|
+
export { PerspectiveViewerWidget } from "./workspace/widget";
|
|
20
|
+
|
|
21
|
+
import "./external";
|
|
22
|
+
import {
|
|
23
|
+
PerspectiveWorkspace,
|
|
24
|
+
PerspectiveWorkspaceConfig,
|
|
25
|
+
ViewerConfigUpdateExt,
|
|
26
|
+
} from "./workspace";
|
|
27
|
+
import { bindTemplate, CustomElementProto } from "./utils/custom_elements";
|
|
28
|
+
import style from "../../build/css/workspace.css";
|
|
29
|
+
import template from "../html/workspace.html";
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* A Custom Element for coordinating a set of `<perspective-viewer>` light DOM
|
|
33
|
+
* children. `<perspective-workspace>` is built on Lumino.js to allow a more
|
|
34
|
+
* app-like experience than `<perspective-viewer>`, providing
|
|
35
|
+
* these features additionally:
|
|
36
|
+
*
|
|
37
|
+
* - Docking, arranging, tabbing and max/min-ing of `<perspective-viewer>`s.
|
|
38
|
+
* - Trivial `<perspective-viewer>` duplication.
|
|
39
|
+
* - Global Filter sidebar, for using selection state of a pivot table to filter
|
|
40
|
+
* siblings.
|
|
41
|
+
* - Total persistence/serializable state and child state.
|
|
42
|
+
* - Easy sharing/ownership of `Table()` among different `<perspective-viewer>`.
|
|
43
|
+
* - A cool DOM-reactive API.
|
|
44
|
+
*
|
|
45
|
+
* There are a few ways to use this Custom Element. In plain HTML, you can
|
|
46
|
+
* express your initial view simply:
|
|
47
|
+
*
|
|
48
|
+
* ```html
|
|
49
|
+
* <perspective-workspace>
|
|
50
|
+
* <perspective-viewer
|
|
51
|
+
* name="View One"
|
|
52
|
+
* table="superstore">
|
|
53
|
+
* </perspective-viewer>
|
|
54
|
+
* <perspective-viewer
|
|
55
|
+
* name="View Two"
|
|
56
|
+
* table="superstore">
|
|
57
|
+
* </perspective-viewer>
|
|
58
|
+
* </perspective-workspace>
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* You can also use the DOM API in Javascript:
|
|
62
|
+
*
|
|
63
|
+
* ```javascript
|
|
64
|
+
* const workspace = document.createElement("perspective-workspace");
|
|
65
|
+
* const viewer = document.createElement("perspective-viewer");
|
|
66
|
+
* workspace.appendChild(viewer);
|
|
67
|
+
* document.body.appendChild(workspace);
|
|
68
|
+
* ```
|
|
69
|
+
*
|
|
70
|
+
* This will yield a `<perspective-workspace> with the default layout. To load
|
|
71
|
+
* a `Table()`, add it to `tables` via the `Map()` API where it will be
|
|
72
|
+
* auto-wired into all matching `<perspective-viewer>`s immediately:
|
|
73
|
+
*
|
|
74
|
+
* ```javascript
|
|
75
|
+
* workspace.tables.set("superstore", await worker.table(my_data));
|
|
76
|
+
* ```
|
|
77
|
+
*
|
|
78
|
+
*
|
|
79
|
+
*/
|
|
80
|
+
export class HTMLPerspectiveWorkspaceElement extends HTMLElement {
|
|
81
|
+
private workspace?: PerspectiveWorkspace;
|
|
82
|
+
private _resize_observer?: ResizeObserver;
|
|
83
|
+
|
|
84
|
+
constructor() {
|
|
85
|
+
super();
|
|
86
|
+
this.setAutoSize(true);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/***************************************************************************
|
|
90
|
+
*
|
|
91
|
+
* Public
|
|
92
|
+
*
|
|
93
|
+
*/
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Persists this `<perspective-workspace>` to a token `Object`. This object
|
|
97
|
+
* is JSON serializable and describes the state of the Workspace and it's
|
|
98
|
+
* child `<perspective-viewer>` elements. Some important keys:
|
|
99
|
+
*
|
|
100
|
+
* - `viewers`: The serialized state of `<perspective-viewer>` children,
|
|
101
|
+
* named by `slot`.
|
|
102
|
+
* - `detail`: The main layout.
|
|
103
|
+
* - `master`: The contents of the Global Filter sidebar.
|
|
104
|
+
*
|
|
105
|
+
* While the `table` attribute is persisted for each `perspective-viewer`,
|
|
106
|
+
* `Table`s themselves must be added to the `tables` property `Map()`
|
|
107
|
+
* separately.
|
|
108
|
+
*
|
|
109
|
+
* @return {Object} A configuration token, compatible with
|
|
110
|
+
* `restore(config)`.
|
|
111
|
+
* @example
|
|
112
|
+
* // Save this layout to local storage
|
|
113
|
+
* const workspace = document.querySelector("perspective-workspace");
|
|
114
|
+
* localStorage.set("CONFIG", JSON.stringify(workspace.save()));
|
|
115
|
+
*/
|
|
116
|
+
save() {
|
|
117
|
+
return this.workspace!.save();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Restore this `<perspective-workspace>` to a previous state captured by
|
|
122
|
+
* `save()`. Calling this method will completely rewrite this element's
|
|
123
|
+
* `innerHTML`, but may reuse `<perspective-viewer>` children depending
|
|
124
|
+
* on the `slot` attribute names. However, it should always be possible
|
|
125
|
+
* to recreate any given state from within the UI itself, as the attributes
|
|
126
|
+
* on `<perspective-viewer>` itself create immutable views.
|
|
127
|
+
*
|
|
128
|
+
* While the `table` attribute is set for each `perspective-viewer`,
|
|
129
|
+
* `Table`s themselves must be added to the `tables` property `Map()`
|
|
130
|
+
* separately.
|
|
131
|
+
* @param {Object} config A configuration token, as returned by `save()`.
|
|
132
|
+
* @example
|
|
133
|
+
* // Restore this layout from local storage
|
|
134
|
+
* const workspace = document.querySelector("perspective-workspace");
|
|
135
|
+
* workspace.restore(JSON.parse(localStorage.get("CONFIG"));
|
|
136
|
+
*
|
|
137
|
+
* // Add `Table` separately.
|
|
138
|
+
* workspace.tables.set("superstore", await worker.table(data));
|
|
139
|
+
*/
|
|
140
|
+
async restore(layout: PerspectiveWorkspaceConfig<string>) {
|
|
141
|
+
await this.workspace!.restore(layout);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async clear() {
|
|
145
|
+
await this.restore({
|
|
146
|
+
sizes: [],
|
|
147
|
+
master: { sizes: [] },
|
|
148
|
+
detail: { sizes: [] },
|
|
149
|
+
viewers: {},
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Await all asynchronous tasks for all viewers in this workspace. This is
|
|
155
|
+
* useful to make sure asynchonous side effects of synchronous methods calls
|
|
156
|
+
* are applied.
|
|
157
|
+
*/
|
|
158
|
+
async flush() {
|
|
159
|
+
await Promise.all(
|
|
160
|
+
Array.from(this.querySelectorAll("perspective-viewer")).map((x) => {
|
|
161
|
+
const psp_widget = x as HTMLPerspectiveViewerElement;
|
|
162
|
+
return psp_widget.flush();
|
|
163
|
+
}),
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Add a new viewer to the workspace for a given `ViewerConfigUpdateExt`.
|
|
169
|
+
* @param config
|
|
170
|
+
*/
|
|
171
|
+
async addViewer(config: ViewerConfigUpdateExt) {
|
|
172
|
+
this.workspace!.addViewer(config);
|
|
173
|
+
await this.flush();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Add a new `Table` to the workspace, so that it can be bound by viewers.
|
|
178
|
+
* Each `Table` is identified by a unique `name`.
|
|
179
|
+
*/
|
|
180
|
+
async addTable(name: string, table: Promise<psp.Table>) {
|
|
181
|
+
this.workspace!.addTable(name, table);
|
|
182
|
+
await this.flush();
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Deleta a table by name from this workspace
|
|
187
|
+
* @param name
|
|
188
|
+
* @returns
|
|
189
|
+
*/
|
|
190
|
+
getTable(name: string) {
|
|
191
|
+
return this.workspace!.getTable(name);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Replace a `Table` by name. As `Table` doe snot guarantee the same
|
|
196
|
+
* structure, this will wipe the viewer's state.
|
|
197
|
+
* @param name
|
|
198
|
+
* @param table
|
|
199
|
+
*/
|
|
200
|
+
async replaceTable(name: string, table: Promise<psp.Table>) {
|
|
201
|
+
this.workspace!.replaceTable(name, table);
|
|
202
|
+
await this.flush();
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Remove a `Table` by name.
|
|
207
|
+
* @param name
|
|
208
|
+
* @returns
|
|
209
|
+
*/
|
|
210
|
+
removeTable(name: string) {
|
|
211
|
+
return this.workspace!.removeTable(name);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* A `Map()` of `perspective.Table()` by name. The names set here will auto
|
|
216
|
+
* wire any child `perspective-viewer` elements in this Workspace's subtree,
|
|
217
|
+
* by looking up their respective `table` attribute.
|
|
218
|
+
*
|
|
219
|
+
* Calling methods on this `Map()` may have side-effects, as
|
|
220
|
+
* `PerspectiveViewerHTMLElement.load()` is called when a new `Table()` is
|
|
221
|
+
* set with a name matching an existing child `perspective-viewer`.
|
|
222
|
+
*
|
|
223
|
+
* @readonly
|
|
224
|
+
* @memberof HTMLPerspectiveWorkspaceElement
|
|
225
|
+
*/
|
|
226
|
+
get tables() {
|
|
227
|
+
return this.workspace!.tables;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Invalidate this component's dimensions and recalculate.
|
|
232
|
+
*/
|
|
233
|
+
async resize() {
|
|
234
|
+
this.workspace!.update();
|
|
235
|
+
await this.flush();
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Set whether this workspace element should auto-size itself via a
|
|
240
|
+
* `ResizeObserver`.
|
|
241
|
+
*/
|
|
242
|
+
setAutoSize(is_auto_size: boolean) {
|
|
243
|
+
this._resize_observer?.unobserve(this);
|
|
244
|
+
this._resize_observer = undefined;
|
|
245
|
+
if (is_auto_size) {
|
|
246
|
+
this._resize_observer = new ResizeObserver((...args) =>
|
|
247
|
+
this.workspace?.update(),
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
this._resize_observer.observe(this);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
connectedCallback() {
|
|
255
|
+
if (!this.workspace) {
|
|
256
|
+
const container = this.shadowRoot!.querySelector("#container")!;
|
|
257
|
+
this.workspace = new PerspectiveWorkspace(this);
|
|
258
|
+
this._register_light_dom_listener();
|
|
259
|
+
MessageLoop.sendMessage(this.workspace, Widget.Msg.BeforeAttach);
|
|
260
|
+
container.insertBefore(this.workspace.node, null);
|
|
261
|
+
MessageLoop.sendMessage(this.workspace, Widget.Msg.AfterAttach);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/***************************************************************************
|
|
266
|
+
*
|
|
267
|
+
* Private
|
|
268
|
+
*
|
|
269
|
+
*/
|
|
270
|
+
|
|
271
|
+
private _light_dom_changed() {
|
|
272
|
+
const viewers = Array.from(
|
|
273
|
+
this.childNodes,
|
|
274
|
+
) as HTMLPerspectiveViewerElement[];
|
|
275
|
+
|
|
276
|
+
for (const viewer of viewers) {
|
|
277
|
+
if (viewer.nodeType !== Node.ELEMENT_NODE) {
|
|
278
|
+
continue;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if (viewer.tagName !== "PERSPECTIVE-VIEWER") {
|
|
282
|
+
console.warn("Not a <perspective-viewer>");
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
this.workspace!.update_widget_for_viewer(
|
|
287
|
+
viewer as HTMLPerspectiveViewerElement,
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
this.workspace!.remove_unslotted_widgets(viewers);
|
|
292
|
+
this.workspace!.update_details_panel(viewers);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
private _register_light_dom_listener() {
|
|
296
|
+
let observer = new MutationObserver(this._light_dom_changed.bind(this));
|
|
297
|
+
let config = { attributes: false, childList: true, subtree: false };
|
|
298
|
+
observer.observe(this, config);
|
|
299
|
+
this._light_dom_changed();
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
bindTemplate(
|
|
304
|
+
template,
|
|
305
|
+
style,
|
|
306
|
+
)(HTMLPerspectiveWorkspaceElement as unknown as CustomElementProto);
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
2
|
+
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
|
3
|
+
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
|
4
|
+
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
|
5
|
+
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
|
6
|
+
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
|
7
|
+
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
|
8
|
+
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
|
9
|
+
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
|
10
|
+
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
|
+
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Instantiate a Template DOM object from an HTML text string.
|
|
15
|
+
*
|
|
16
|
+
* Params
|
|
17
|
+
* ------
|
|
18
|
+
* template : An HTML string representing a template.
|
|
19
|
+
*
|
|
20
|
+
* Returns
|
|
21
|
+
* -------
|
|
22
|
+
* A Template DOM object.
|
|
23
|
+
*/
|
|
24
|
+
function importTemplate(template: string): HTMLTemplateElement {
|
|
25
|
+
const div = document.createElement("div");
|
|
26
|
+
div.innerHTML = template;
|
|
27
|
+
return Array.prototype.slice.call(div.children)[0];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface CustomElementProto extends CustomElementConstructor {
|
|
31
|
+
connectedCallback(): void;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* A simple tool for creating Web Components v0.
|
|
36
|
+
*
|
|
37
|
+
* Params
|
|
38
|
+
* ------
|
|
39
|
+
* template : An HTML string representing a template. Should have an 'id'
|
|
40
|
+
* attribute which will become the new Web Component's tag name.
|
|
41
|
+
* proto : The new Web Component's prototype object, as per spec.
|
|
42
|
+
*/
|
|
43
|
+
export function registerElement(
|
|
44
|
+
templateString: string,
|
|
45
|
+
styleString: string,
|
|
46
|
+
proto: CustomElementProto,
|
|
47
|
+
) {
|
|
48
|
+
const template = importTemplate(templateString);
|
|
49
|
+
if (styleString) {
|
|
50
|
+
template.innerHTML =
|
|
51
|
+
`<style>${styleString.toString()}</style>` + template.innerHTML;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const _perspective_element = class extends proto {
|
|
55
|
+
private _initialized: boolean;
|
|
56
|
+
private _initializing: boolean;
|
|
57
|
+
|
|
58
|
+
constructor() {
|
|
59
|
+
super();
|
|
60
|
+
this._initialized = false;
|
|
61
|
+
this._initializing = false;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
connectedCallback() {
|
|
65
|
+
if (this._initialized) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
this._initializing = true;
|
|
70
|
+
const node = document.importNode(template.content, true);
|
|
71
|
+
const root = this.attachShadow({ mode: "open" });
|
|
72
|
+
root.appendChild(node);
|
|
73
|
+
if (proto.prototype.connectedCallback) {
|
|
74
|
+
proto.prototype.connectedCallback.call(this);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
this._initializing = false;
|
|
78
|
+
this._initialized = true;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
static get observedAttributes() {
|
|
82
|
+
return Object.getOwnPropertyNames(proto.prototype);
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
let name = template.getAttribute("id")!;
|
|
87
|
+
window.customElements.define(name, _perspective_element);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function bindTemplate(template: string, ...styleStrings: string[]) {
|
|
91
|
+
const style = styleStrings.map((x) => x.toString()).join("\n");
|
|
92
|
+
return function (cls: CustomElementProto) {
|
|
93
|
+
return registerElement(template, style, cls);
|
|
94
|
+
};
|
|
95
|
+
}
|