@api-client/ui 0.0.10 → 0.0.12

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.
Files changed (176) hide show
  1. package/.eslintrc +16 -1
  2. package/demo/elements/index.html +3 -0
  3. package/demo/elements/store/file-picker.html +15 -0
  4. package/demo/elements/store/file-picker.ts +134 -0
  5. package/demo/elements/store/index.html +19 -0
  6. package/demo/index.html +3 -0
  7. package/demo/layout/index.html +91 -0
  8. package/demo/layout/index.ts +182 -0
  9. package/demo/store/StorePlugin.js +1 -0
  10. package/dist/bindings/base/StoreBindings.d.ts +5 -0
  11. package/dist/bindings/base/StoreBindings.d.ts.map +1 -1
  12. package/dist/bindings/base/StoreBindings.js +15 -1
  13. package/dist/bindings/base/StoreBindings.js.map +1 -1
  14. package/dist/define/store/file-picker.d.ts +9 -0
  15. package/dist/define/store/file-picker.d.ts.map +1 -0
  16. package/dist/define/store/file-picker.js +10 -0
  17. package/dist/define/store/file-picker.js.map +1 -0
  18. package/dist/define/{files → store}/share-file.d.ts +1 -1
  19. package/dist/define/store/share-file.d.ts.map +1 -0
  20. package/dist/define/{files → store}/share-file.js +2 -2
  21. package/dist/define/store/share-file.js.map +1 -0
  22. package/dist/elements/layout/SplitItem.d.ts +1 -9
  23. package/dist/elements/layout/SplitItem.d.ts.map +1 -1
  24. package/dist/elements/layout/SplitItem.js +27 -20
  25. package/dist/elements/layout/SplitItem.js.map +1 -1
  26. package/dist/elements/layout/SplitLayout.d.ts +16 -14
  27. package/dist/elements/layout/SplitLayout.d.ts.map +1 -1
  28. package/dist/elements/layout/SplitLayout.js +47 -42
  29. package/dist/elements/layout/SplitLayout.js.map +1 -1
  30. package/dist/elements/layout/SplitPanel.d.ts +7 -2
  31. package/dist/elements/layout/SplitPanel.d.ts.map +1 -1
  32. package/dist/elements/layout/SplitPanel.js +130 -52
  33. package/dist/elements/layout/SplitPanel.js.map +1 -1
  34. package/dist/elements/layout/SplitView.d.ts.map +1 -1
  35. package/dist/elements/layout/SplitView.js +18 -14
  36. package/dist/elements/layout/SplitView.js.map +1 -1
  37. package/dist/elements/layout/type.d.ts +3 -3
  38. package/dist/elements/layout/type.d.ts.map +1 -1
  39. package/dist/elements/layout/type.js.map +1 -1
  40. package/dist/elements/store/FilePicker.element.d.ts +87 -0
  41. package/dist/elements/store/FilePicker.element.d.ts.map +1 -0
  42. package/dist/elements/store/FilePicker.element.js +263 -0
  43. package/dist/elements/store/FilePicker.element.js.map +1 -0
  44. package/dist/elements/store/FilePicker.styles.d.ts +3 -0
  45. package/dist/elements/store/FilePicker.styles.d.ts.map +1 -0
  46. package/dist/elements/store/FilePicker.styles.js +72 -0
  47. package/dist/elements/store/FilePicker.styles.js.map +1 -0
  48. package/dist/elements/store/FilesLib.d.ts +10 -0
  49. package/dist/elements/store/FilesLib.d.ts.map +1 -0
  50. package/dist/elements/store/FilesLib.js +38 -0
  51. package/dist/elements/store/FilesLib.js.map +1 -0
  52. package/dist/elements/{files/ShareFile.d.ts → store/ShareFile.element.d.ts} +1 -1
  53. package/dist/elements/store/ShareFile.element.d.ts.map +1 -0
  54. package/dist/elements/{files/ShareFile.js → store/ShareFile.element.js} +1 -1
  55. package/dist/elements/store/ShareFile.element.js.map +1 -0
  56. package/dist/elements/store/ShareFile.styles.d.ts.map +1 -0
  57. package/dist/elements/{files → store}/ShareFile.styles.js.map +1 -1
  58. package/dist/events/EventTypes.d.ts +1 -0
  59. package/dist/events/EventTypes.d.ts.map +1 -1
  60. package/dist/events/EventTypes.js +1 -0
  61. package/dist/events/EventTypes.js.map +1 -1
  62. package/dist/events/Events.d.ts +1 -0
  63. package/dist/events/Events.d.ts.map +1 -1
  64. package/dist/events/StoreEvents.d.ts +8 -1
  65. package/dist/events/StoreEvents.d.ts.map +1 -1
  66. package/dist/events/StoreEvents.js +19 -0
  67. package/dist/events/StoreEvents.js.map +1 -1
  68. package/dist/pages/ApplicationScreen.d.ts +1 -1
  69. package/dist/pages/ApplicationScreen.d.ts.map +1 -1
  70. package/dist/pages/ApplicationScreen.js +4 -2
  71. package/dist/pages/ApplicationScreen.js.map +1 -1
  72. package/dist/pages/api-client/ApiClient.screen.d.ts +0 -6
  73. package/dist/pages/api-client/ApiClient.screen.d.ts.map +1 -1
  74. package/dist/pages/api-client/ApiClient.screen.js +16 -29
  75. package/dist/pages/api-client/ApiClient.screen.js.map +1 -1
  76. package/dist/pages/api-client/Authenticate.screen.d.ts +1 -1
  77. package/dist/pages/api-client/Authenticate.screen.d.ts.map +1 -1
  78. package/dist/pages/api-client/Authenticate.screen.js +2 -2
  79. package/dist/pages/api-client/Authenticate.screen.js.map +1 -1
  80. package/dist/pages/api-client/pages/Files.page.d.ts +6 -35
  81. package/dist/pages/api-client/pages/Files.page.d.ts.map +1 -1
  82. package/dist/pages/api-client/pages/Files.page.js +32 -141
  83. package/dist/pages/api-client/pages/Files.page.js.map +1 -1
  84. package/dist/pages/api-client/pages/Shared.page.d.ts +1 -5
  85. package/dist/pages/api-client/pages/Shared.page.d.ts.map +1 -1
  86. package/dist/pages/api-client/pages/Shared.page.js +1 -40
  87. package/dist/pages/api-client/pages/Shared.page.js.map +1 -1
  88. package/dist/pages/demo/DemoPage.d.ts +7 -0
  89. package/dist/pages/demo/DemoPage.d.ts.map +1 -1
  90. package/dist/pages/demo/DemoPage.js +14 -0
  91. package/dist/pages/demo/DemoPage.js.map +1 -1
  92. package/dist/pages/http-project/HttpClientCommands.d.ts.map +1 -1
  93. package/dist/pages/http-project/HttpClientCommands.js +28 -12
  94. package/dist/pages/http-project/HttpClientCommands.js.map +1 -1
  95. package/dist/store/FileSystem.d.ts +90 -0
  96. package/dist/store/FileSystem.d.ts.map +1 -0
  97. package/dist/store/FileSystem.js +260 -0
  98. package/dist/store/FileSystem.js.map +1 -0
  99. package/dist/styles/global-styles.d.ts.map +1 -1
  100. package/dist/styles/global-styles.js +7 -0
  101. package/dist/styles/global-styles.js.map +1 -1
  102. package/dist/ui/icons/Icons.d.ts +2 -1
  103. package/dist/ui/icons/Icons.d.ts.map +1 -1
  104. package/dist/ui/icons/Icons.js +1 -0
  105. package/dist/ui/icons/Icons.js.map +1 -1
  106. package/dist/ui/list/UiDropdownList.d.ts +9 -1
  107. package/dist/ui/list/UiDropdownList.d.ts.map +1 -1
  108. package/dist/ui/list/UiDropdownList.js +39 -17
  109. package/dist/ui/list/UiDropdownList.js.map +1 -1
  110. package/dist/ui/list/UiList.d.ts +6 -1
  111. package/dist/ui/list/UiList.d.ts.map +1 -1
  112. package/dist/ui/list/UiList.js +24 -9
  113. package/dist/ui/list/UiList.js.map +1 -1
  114. package/dist/ui/table/DataTable.d.ts +4 -0
  115. package/dist/ui/table/DataTable.d.ts.map +1 -1
  116. package/dist/ui/table/DataTable.js +23 -1
  117. package/dist/ui/table/DataTable.js.map +1 -1
  118. package/package.json +2 -1
  119. package/src/bindings/base/StoreBindings.ts +16 -1
  120. package/src/define/store/file-picker.ts +12 -0
  121. package/src/define/{files → store}/share-file.ts +2 -2
  122. package/src/elements/layout/SplitItem.ts +29 -21
  123. package/src/elements/layout/SplitLayout.ts +53 -43
  124. package/src/elements/layout/SplitPanel.ts +140 -57
  125. package/src/elements/layout/SplitView.ts +18 -15
  126. package/src/elements/layout/type.ts +3 -4
  127. package/src/elements/store/FilePicker.element.ts +297 -0
  128. package/src/elements/store/FilePicker.styles.ts +72 -0
  129. package/src/elements/store/FilesLib.ts +32 -0
  130. package/src/events/EventTypes.ts +1 -0
  131. package/src/events/StoreEvents.ts +21 -1
  132. package/src/pages/ApplicationScreen.ts +5 -3
  133. package/src/pages/api-client/ApiClient.screen.ts +16 -31
  134. package/src/pages/api-client/Authenticate.screen.ts +2 -2
  135. package/src/pages/api-client/pages/Files.page.ts +37 -164
  136. package/src/pages/api-client/pages/Shared.page.ts +2 -40
  137. package/src/pages/demo/DemoPage.ts +17 -0
  138. package/src/pages/http-project/HttpClientCommands.ts +28 -12
  139. package/src/store/FileSystem.ts +325 -0
  140. package/src/styles/global-styles.ts +7 -0
  141. package/src/ui/icons/Icons.ts +2 -1
  142. package/src/ui/list/UiDropdownList.ts +44 -17
  143. package/src/ui/list/UiList.ts +26 -10
  144. package/src/ui/table/DataTable.ts +29 -3
  145. package/test/elements/layout/SplitItem.test.ts +76 -75
  146. package/test/elements/layout/SplitLayoutManager.test.ts +70 -69
  147. package/test/elements/layout/SplitPanel.test.ts +10 -7
  148. package/test/elements/store/FilePicker.test.ts +241 -0
  149. package/test/env.js +3 -0
  150. package/test/helpers/StoreHelper.ts +390 -0
  151. package/tsconfig.eslint.json +10 -0
  152. package/web-test-runner.config.mjs +51 -2
  153. package/dist/define/files/share-file.d.ts.map +0 -1
  154. package/dist/define/files/share-file.js.map +0 -1
  155. package/dist/define/layout/layout-panel.d.ts +0 -7
  156. package/dist/define/layout/layout-panel.d.ts.map +0 -1
  157. package/dist/define/layout/layout-panel.js +0 -3
  158. package/dist/define/layout/layout-panel.js.map +0 -1
  159. package/dist/elements/files/ShareFile.d.ts.map +0 -1
  160. package/dist/elements/files/ShareFile.js.map +0 -1
  161. package/dist/elements/files/ShareFile.styles.d.ts.map +0 -1
  162. package/dist/elements/layout/LayoutManager.d.ts +0 -327
  163. package/dist/elements/layout/LayoutManager.d.ts.map +0 -1
  164. package/dist/elements/layout/LayoutManager.js +0 -747
  165. package/dist/elements/layout/LayoutManager.js.map +0 -1
  166. package/dist/elements/layout/LayoutPanelElement.d.ts +0 -62
  167. package/dist/elements/layout/LayoutPanelElement.d.ts.map +0 -1
  168. package/dist/elements/layout/LayoutPanelElement.js +0 -628
  169. package/dist/elements/layout/LayoutPanelElement.js.map +0 -1
  170. package/src/define/layout/layout-panel.ts +0 -9
  171. package/src/elements/layout/LayoutManager.ts +0 -930
  172. package/src/elements/layout/LayoutPanelElement.ts +0 -651
  173. /package/dist/elements/{files → store}/ShareFile.styles.d.ts +0 -0
  174. /package/dist/elements/{files → store}/ShareFile.styles.js +0 -0
  175. /package/src/elements/{files/ShareFile.ts → store/ShareFile.element.ts} +0 -0
  176. /package/src/elements/{files → store}/ShareFile.styles.ts +0 -0
@@ -1,651 +0,0 @@
1
- /* eslint-disable class-methods-use-this */
2
- import { LitElement, html, TemplateResult, CSSResult, css } from 'lit';
3
- import { property, state, eventOptions } from 'lit/decorators.js';
4
- import { ifDefined } from 'lit/directives/if-defined.js';
5
- import { classMap } from 'lit/directives/class-map.js';
6
- // eslint-disable-next-line import/no-cycle
7
- import { LayoutPanel, DropRegion, ILayoutItem } from './LayoutManager.js';
8
- import surfaceStyles from '../../styles/m3/surface.module.js';
9
- import '../../define/ui/ui-icon.js';
10
-
11
- export default class LayoutPanelElement extends LitElement {
12
- static override get styles(): CSSResult[] {
13
- return [surfaceStyles, css`
14
- :host {
15
- display: flex;
16
- position: relative;
17
- flex-direction: column;
18
- /* border: 1px red solid; */
19
- }
20
-
21
- .content {
22
- display: flex;
23
- flex: 1;
24
- }
25
-
26
- :host([constrain]) .content {
27
- overflow: hidden;
28
- }
29
-
30
- :host([layout=horizontal]) .content {
31
- flex-direction: row;
32
- }
33
-
34
- :host([layout=vertical]) .content {
35
- flex-direction: column;
36
- }
37
-
38
- :host ::slotted(*) {
39
- flex: 1;
40
- /* width: 100%;
41
- height: 100%; */
42
- }
43
-
44
- .drag-region {
45
- position: absolute;
46
- background-color: rgba(0,0,0,0.12);
47
- }
48
-
49
- .drag-region.center {
50
- top: 0;
51
- bottom: 0;
52
- left: 0;
53
- right:0;
54
- }
55
-
56
- .drag-region.west {
57
- top: 0;
58
- bottom: 0;
59
- left: 0;
60
- right: 50%;
61
- }
62
-
63
- .drag-region.east {
64
- top: 0;
65
- bottom: 0;
66
- left: 50%;
67
- right: 0;
68
- }
69
-
70
- .drag-region.north {
71
- top: 0;
72
- left: 0;
73
- right: 0;
74
- bottom: 50%;
75
- }
76
-
77
- .drag-region.south {
78
- top: 50%;
79
- left: 0;
80
- right: 0;
81
- bottom: 0;
82
- }
83
-
84
- .layout-tabs {
85
- display: flex;
86
- align-items: center;
87
- background: var(--layout-tabs-background, var(--secondary-background-color));
88
- }
89
-
90
- .layout-tab {
91
- position: relative;
92
- display: inline-flex;
93
- align-items: center;
94
- flex: 1 1 200px;
95
- max-width: 200px;
96
- min-width: 40px;
97
- width: 200px;
98
- height: 100%;
99
- font-size: 0.94rem;
100
- padding: 0px 12px;
101
- border-radius: var(--md-sys-shape-corner-small-top);
102
- height: 40px;
103
- outline: none;
104
- justify-content: flex-start;
105
- text-transform: none;
106
- color: var(--md-sys-color-on-surface);
107
-
108
- font-family: var(--md-sys-typescale-body-medium-font-family-name);
109
- font-style: var(--md-sys-typescale-body-medium-font-family-style);
110
- font-weight: var(--md-sys-typescale-body-medium-font-weight);
111
- font-size: var(--md-sys-typescale-body-medium-font-size);
112
- letter-spacing: var(--md-sys-typescale-body-medium-tracking);
113
- line-height: var(--md-sys-typescale-body-medium-height);
114
- text-transform: var(--md-sys-typescale-body-medium-text-transform);
115
- text-decoration: var(--md-sys-typescale-body-medium-text-decoration);
116
- }
117
-
118
- .tab-label {
119
- overflow: hidden;
120
- white-space: nowrap;
121
- text-overflow: ellipsis;
122
- }
123
-
124
- .is-dirty .tab-label {
125
- font-style: italic;
126
- }
127
-
128
- .is-dirty .tab-label::after {
129
- content: '*';
130
- user-select: none;
131
- }
132
-
133
- .layout-tab.selected {
134
- /* z-index: 2; */
135
- background: var(--layout-tab-select-background, var(--primary-background-color));
136
- }
137
-
138
- .layout-tab:not(.selected):hover::before {
139
- background-color: var(--md-sys-color-primary);
140
- opacity: var(--md-sys-state-hover-state-layer-opacity);
141
- position: absolute;
142
- inset: 0;
143
- content: '';
144
- border-radius: inherit;
145
- }
146
-
147
- .layout-tab:not(.selected):focus::before {
148
- background-color: var(--md-sys-color-primary);
149
- opacity: var(--md-sys-state-focus-state-layer-opacity);
150
- position: absolute;
151
- inset: 0;
152
- content: '';
153
- border-radius: inherit;
154
- }
155
-
156
- /* .layout-tab:focus {
157
- border-top-color: var(--primary-color);
158
- } */
159
-
160
- .tab-favicon {
161
- width: 16px;
162
- height: 16px;
163
- margin-right: 8px;
164
- }
165
-
166
- .close-icon {
167
- width: 16px;
168
- height: 16px;
169
- margin-left: auto;
170
- }
171
-
172
- .tab-divider {
173
- width: 1px;
174
- min-width: 1px;
175
- height: 20px;
176
- background-color: var(--md-sys-color-outline-variant);
177
- }
178
-
179
- .tab-divider.hidden {
180
- background-color: transparent;
181
- }
182
- `];
183
- }
184
-
185
- /**
186
- * @attribute
187
- */
188
- @property({ type: String, reflect: true }) layout: 'horizontal' | 'vertical' = 'horizontal';
189
-
190
- /**
191
- * @attribute
192
- */
193
- @property({ type: Number, reflect: true }) layoutId?: number;
194
-
195
- @property({ type: Array }) dragTypes?: string[];
196
-
197
- /**
198
- * Whether dragging is occurring over the element
199
- */
200
- @state() protected inDrag = false;
201
-
202
- /**
203
- * The region the drag is leaning to.
204
- */
205
- @state() protected dragRegion?: DropRegion = 'center';
206
-
207
- @property({ type: Object }) panel?: LayoutPanel;
208
-
209
- /**
210
- * When set it adds the `overflow` hidden on the container that holds the tab contents.
211
- * @attribute
212
- */
213
- @property({ type: Boolean, reflect: true }) constrain = false;
214
-
215
- constructor() {
216
- super();
217
- this._dragEnterHandler = this._dragEnterHandler.bind(this);
218
- this._dragOverHandler = this._dragOverHandler.bind(this);
219
- this._dropHandler = this._dropHandler.bind(this);
220
- this._dragleaveHandler = this._dragleaveHandler.bind(this);
221
- this._dragendHandler = this._dragendHandler.bind(this);
222
- }
223
-
224
- override connectedCallback(): void {
225
- super.connectedCallback();
226
- this.addEventListener('dragenter', this._dragEnterHandler);
227
- this.addEventListener('dragover', this._dragOverHandler);
228
- this.addEventListener('drop', this._dropHandler);
229
- document.body.addEventListener('dragleave', this._dragleaveHandler);
230
- document.body.addEventListener('dragend', this._dragendHandler);
231
- }
232
-
233
- override disconnectedCallback(): void {
234
- super.disconnectedCallback();
235
- this.removeEventListener('dragenter', this._dragEnterHandler);
236
- this.removeEventListener('dragover', this._dragOverHandler);
237
- this.removeEventListener('drop', this._dropHandler);
238
- document.body.removeEventListener('dragleave', this._dragleaveHandler);
239
- document.body.removeEventListener('dragend', this._dragendHandler);
240
- }
241
-
242
- protected hasDropTypes(dt: DataTransfer): boolean {
243
- const { dragTypes } = this;
244
- if (!Array.isArray(dragTypes)) {
245
- return true;
246
- }
247
- const eventTypes = [...dt.types];
248
- const allowedTypes = dragTypes.map(i => i.toLowerCase());
249
- return !allowedTypes.some(type => !eventTypes.includes(type));
250
- }
251
-
252
- protected panelCanDrop(e: DragEvent): boolean {
253
- if (e.defaultPrevented) {
254
- return false;
255
- }
256
- if (e.dataTransfer && !this.hasDropTypes(e.dataTransfer)) {
257
- return false;
258
- }
259
- const { panel } = this;
260
- if (!panel) {
261
- return true;
262
- }
263
- return panel.canDrop();
264
- }
265
-
266
- protected _dragEnterHandler(e: DragEvent): void {
267
- const { dataTransfer } = e;
268
- if (!dataTransfer || !this.panelCanDrop(e)) {
269
- return;
270
- }
271
- e.preventDefault();
272
- e.stopPropagation();
273
- dataTransfer.dropEffect = 'copy';
274
- }
275
-
276
- protected _dragOverHandler(e: DragEvent): void {
277
- const { dataTransfer } = e;
278
- if (!dataTransfer || !this.panelCanDrop(e)) {
279
- return;
280
- }
281
- e.preventDefault();
282
- e.stopPropagation();
283
- const region = this.getDropRegionFromEvent(e);
284
- if (!region) {
285
- this.inDrag = false;
286
- return;
287
- }
288
- dataTransfer.dropEffect = 'copy';
289
- this.inDrag = true;
290
- this.dragRegion = region;
291
- }
292
-
293
- protected _dropHandler(e: DragEvent): void {
294
- const { dataTransfer } = e;
295
- if (!dataTransfer || !this.panelCanDrop(e)) {
296
- return;
297
- }
298
- e.preventDefault();
299
- e.stopPropagation();
300
- const kind = dataTransfer.getData('text/kind');
301
- const key = dataTransfer.getData('text/key');
302
- if (!kind || !key) {
303
- return;
304
- }
305
- this.inDrag = false;
306
- const { panel } = this;
307
- let dispatch = true;
308
- if (panel) {
309
- dispatch = panel.addItem({ key, kind, label: 'New tab' }, { region: this.dragRegion });
310
- }
311
- if (dispatch) {
312
- this.dispatchEvent(new CustomEvent('datadrop', {
313
- detail: { kind, key, region: this.dragRegion },
314
- composed: true,
315
- bubbles: true,
316
- cancelable: true,
317
- }));
318
- }
319
- this.requestUpdate();
320
- }
321
-
322
- protected _dragleaveHandler(e: DragEvent): void {
323
- const elm = this.findLayout(e);
324
- if (!elm || elm !== this) {
325
- this.inDrag = false;
326
- this.dragRegion = 'center';
327
- }
328
- }
329
-
330
- protected _dragendHandler(): void {
331
- this.inDrag = false;
332
- this.dragRegion = 'center';
333
- }
334
-
335
- protected getDropRegionFromEvent(e: DragEvent): DropRegion | undefined {
336
- const layout = this.findLayout(e);
337
- if (!layout) {
338
- return undefined;
339
- }
340
- return this.getDropRegion(layout, e);
341
- }
342
-
343
- getDropRegion(element: HTMLElement, e: DragEvent): DropRegion | undefined {
344
- const { pageX, pageY } = e;
345
- const rect = element.getBoundingClientRect();
346
- const quarterWidth = rect.width / 4;
347
- const quarterHeight = rect.height / 4;
348
- if (pageX < rect.left + quarterWidth) {
349
- return 'west';
350
- }
351
- if (pageX > rect.right - quarterWidth) {
352
- return 'east';
353
- }
354
- if (pageY < rect.top + quarterHeight) {
355
- return 'north';
356
- }
357
- if (pageY > rect.bottom - quarterHeight) {
358
- return 'south';
359
- }
360
- const withingCenterX = (pageX >= rect.left + quarterWidth) && (pageX <= rect.right - quarterWidth);
361
- const withingCenterY = (pageY >= rect.top + quarterHeight) && (pageY <= rect.bottom - quarterHeight);
362
- if (withingCenterX && withingCenterY) {
363
- return 'center';
364
- }
365
- return undefined;
366
- }
367
-
368
- protected findLayout(e: Event): LayoutPanelElement | undefined {
369
- const path = e.composedPath();
370
- while (path.length) {
371
- const node = path.shift() as Element;
372
- if (node.nodeType !== Node.ELEMENT_NODE) {
373
- continue;
374
- }
375
- if (node.localName === this.localName) {
376
- return node as LayoutPanelElement;
377
- }
378
- }
379
- return undefined;
380
- }
381
-
382
- protected async _tabSelectHandler(e: Event): Promise<void> {
383
- if (!this.panel) {
384
- return;
385
- }
386
- const key = (e.currentTarget as HTMLElement).dataset.key as string;
387
- if (!key) {
388
- return;
389
- }
390
- if (this.panel.selected === key) {
391
- return;
392
- }
393
- this.panel.selected = key;
394
- this.panel.manager.changed();
395
- this.requestUpdate();
396
- await this.updateComplete;
397
- const child = this.querySelector(`[data-key="${key}"]`);
398
- if (child) {
399
- child.dispatchEvent(new Event('resize'));
400
- }
401
- }
402
-
403
- /**
404
- * Closes a panel with right pointer configuration
405
- */
406
- protected _tabPointerDownHandler(e: PointerEvent): void {
407
- // the configuration of a middle button click which is
408
- // equal to 3 fingers click on a track pad.
409
- if (e.button === 1 && e.buttons === 4) {
410
- e.preventDefault();
411
- e.stopPropagation();
412
- const key = (e.target as HTMLElement).dataset.key as string;
413
- this.closeTab(key);
414
- }
415
- }
416
-
417
- protected _tabCloseHandler(e: Event): void {
418
- const icon = e.target as HTMLElement;
419
- const button = icon.parentElement as HTMLElement;
420
- const key = button.dataset.key as string;
421
- if (key) {
422
- e.preventDefault();
423
- e.stopPropagation();
424
- this.closeTab(key);
425
- }
426
- }
427
-
428
- @eventOptions({ passive: true })
429
- protected _tabTouchStartHandler(e: TouchEvent): void {
430
- if (e.targetTouches.length === 3) {
431
- e.preventDefault();
432
- e.stopPropagation();
433
- const key = (e.target as HTMLElement).dataset.key as string;
434
- this.closeTab(key);
435
- }
436
- }
437
-
438
- protected closeTab(key: string): void {
439
- const { panel } = this;
440
- if (!panel) {
441
- return;
442
- }
443
- const item = panel.items.find(i => i.key === key);
444
- if (!item) {
445
- return;
446
- }
447
- if (item.persistent && item.pinned) {
448
- return;
449
- }
450
- panel.removeItem(key);
451
- this.requestUpdate();
452
- this.dispatchEvent(new CustomEvent('closetab', {
453
- bubbles: true,
454
- cancelable: true,
455
- composed: true,
456
- detail: key,
457
- }));
458
- }
459
-
460
- protected _tabKeydownHandler(e: KeyboardEvent): void {
461
- if (e.key === 'Enter') {
462
- this._tabSelectHandler(e);
463
- }
464
- }
465
-
466
- protected _tabDragStart(e: DragEvent): void {
467
- const dt = e.dataTransfer;
468
- if (!dt || this.layoutId === undefined) {
469
- return;
470
- }
471
-
472
- dt.effectAllowed = 'copyMove';
473
- dt.dropEffect = 'move';
474
- const node = e.target as HTMLElement;
475
- dt.setData('text/kind', node.dataset.kind as string);
476
- dt.setData('text/key', node.dataset.key as string);
477
- dt.setData('text/source', this.localName);
478
- dt.setData('layout/id', String(this.layoutId));
479
- }
480
-
481
- protected _tabsDragEnterHandler(e: DragEvent): void {
482
- const dt = e.dataTransfer;
483
- if (!dt || !this.panelCanDrop(e)) {
484
- return;
485
- }
486
- e.stopPropagation();
487
- e.preventDefault();
488
- dt.effectAllowed = 'move';
489
- dt.dropEffect = 'move';
490
- }
491
-
492
- protected _tabsDragoverHandler(e: DragEvent): void {
493
- const dt = e.dataTransfer;
494
- if (!dt || !this.panelCanDrop(e)) {
495
- return;
496
- }
497
- e.stopPropagation();
498
- e.preventDefault();
499
- dt.effectAllowed = 'move';
500
- dt.dropEffect = 'move';
501
- }
502
-
503
- protected _tabsDrop(e: DragEvent): void {
504
- const dt = e.dataTransfer;
505
- if (!dt || !this.panelCanDrop(e) || this.layoutId === undefined) {
506
- return;
507
- }
508
- e.stopPropagation();
509
- e.preventDefault();
510
- const src = dt.getData('text/source');
511
- const key = dt.getData('text/key');
512
- const kind = dt.getData('text/kind');
513
- const lid = dt.getData('layout/id');
514
- const movingTab = src === this.localName;
515
-
516
- const overTab = this.findTab(e);
517
- const toIndex = overTab ? Number(overTab.dataset.index) : undefined;
518
-
519
- if (movingTab) {
520
- if (!lid) {
521
- return;
522
- }
523
- const srcPanel = Number(lid);
524
- if (Number.isNaN(srcPanel)) {
525
- return;
526
- }
527
- this.moveTab(srcPanel, this.layoutId, key, toIndex);
528
- } else {
529
- let dispatch = true;
530
- if (this.panel) {
531
- dispatch = this.panel.addItem({ key, kind, label: 'New tab' }, { index: toIndex });
532
- }
533
- if (dispatch) {
534
- this.dispatchEvent(new CustomEvent('datadrop', {
535
- detail: { kind, key, index: toIndex },
536
- composed: true,
537
- bubbles: true,
538
- cancelable: true,
539
- }));
540
- }
541
- this.requestUpdate();
542
- }
543
- }
544
-
545
- protected moveTab(fromLayout: number, toLayout: number, key: string, toIndex?: number): void {
546
- const { panel } = this;
547
- if (panel) {
548
- panel.manager.moveTab(fromLayout, toLayout, key, toIndex);
549
- }
550
- }
551
-
552
- protected findTab(e: Event): HTMLElement | undefined {
553
- const path = e.composedPath();
554
- while (path.length) {
555
- const node = path.shift() as Element;
556
- if (node.nodeType !== Node.ELEMENT_NODE) {
557
- continue;
558
- }
559
- if (node.classList.contains('layout-tab')) {
560
- return node as HTMLElement;
561
- }
562
- }
563
- return undefined;
564
- }
565
-
566
- override render(): TemplateResult {
567
- return html`
568
- ${this.dragRegionTemplate()}
569
- ${this.tabsTemplate()}
570
- <div class="content">
571
- <slot></slot>
572
- </div>
573
- `;
574
- }
575
-
576
- protected dragRegionTemplate(): TemplateResult | string {
577
- const { inDrag, dragRegion } = this;
578
- if (!inDrag) {
579
- return '';
580
- }
581
- return html`
582
- <div class="drag-region ${dragRegion}"></div>
583
- `;
584
- }
585
-
586
- protected tabsTemplate(): TemplateResult | string {
587
- const { panel } = this;
588
- if (!panel) {
589
- return '';
590
- }
591
- const items = panel.sortedItems();
592
- if (!items) {
593
- return '';
594
- }
595
- const size = items.length;
596
- return html`
597
- <div
598
- class="layout-tabs"
599
- role="tablist"
600
- @dragenter="${this._tabsDragEnterHandler}"
601
- @dragover="${this._tabsDragoverHandler}"
602
- @drop="${this._tabsDrop}"
603
- >
604
- ${items.map((tab, i) => this.tabTemplate(tab, i + 1 === size, items[i + 1]?.key))}
605
- </div>
606
- `;
607
- }
608
-
609
- protected tabTemplate(item: ILayoutItem, last: boolean, nextKey?: string): TemplateResult {
610
- const { key, kind, label = '', index=0, icon, isDirty = false, parent } = item;
611
- const { panel } = this;
612
- const selected = !!panel && panel.selected === key;
613
- const nextSelected = !!nextKey && !!panel && panel.selected === nextKey;
614
- const closable = !item.persistent && !item.pinned;
615
- const classes = {
616
- 'layout-tab': true,
617
- 'is-dirty': isDirty,
618
- selected,
619
- surface1: selected,
620
- };
621
- let title = label;
622
- if (isDirty) {
623
- title = 'Unsaved changes';
624
- }
625
-
626
- const dividerHidden = last || selected || nextSelected;
627
- return html`
628
- <div
629
- data-key="${key}"
630
- data-kind="${kind}"
631
- data-index="${index}"
632
- data-parent="${ifDefined(parent)}"
633
- data-dirty="${isDirty}"
634
- role="tab"
635
- class="${classMap(classes)}"
636
- draggable="true"
637
- @dragstart="${this._tabDragStart}"
638
- @click="${this._tabSelectHandler}"
639
- @pointerdown="${this._tabPointerDownHandler}"
640
- @touchstart="${this._tabTouchStartHandler}"
641
- @keydown="${this._tabKeydownHandler}"
642
- tabindex="0"
643
- >
644
- ${icon ? html`<ui-icon icon="${icon}" class="tab-favicon"></ui-icon>` : ''}
645
- <span class="tab-label" title="${title}">${label}</span>
646
- ${closable ? html`<ui-icon icon="close" class="close-icon" @click="${this._tabCloseHandler}"></ui-icon>` : ''}
647
- </div>
648
- <div class="tab-divider ${dividerHidden ? 'hidden' : ''}"></div>
649
- `;
650
- }
651
- }