Compare commits

...

1486 Commits

Author SHA1 Message Date
mathuo
093a034738
Merge pull request #921 from mathuo/883-tab-overflow-dropdown-doesnt-collide-with-edge-of-screen
883 tab overflow dropdown doesnt collide with edge of screen
2025-04-30 20:43:39 +01:00
mathuo
f9ca5b99d5
Merge pull request #920 from mathuo/891-first-tab-does-not-drag-drop-when-there-is-not-enough-space-above-the-dockview-area
bug: fix ghost image rendering
2025-04-30 20:43:16 +01:00
mathuo
420466398d
bug: popout service overflow handle 2025-04-29 22:01:27 +01:00
mathuo
20b5c844f3
Merge branch 'master' of https://github.com/mathuo/dockview into 883-tab-overflow-dropdown-doesnt-collide-with-edge-of-screen 2025-04-29 22:00:44 +01:00
mathuo
6d2f2f1012
bug: fix ghost image rendering 2025-04-29 21:45:23 +01:00
mathuo
3ddea55834
chore(release): publish v4.2.4 2025-04-29 21:01:28 +01:00
mathuo
2f334c63c1
chore: v4.2.4 docs 2025-04-29 21:01:04 +01:00
mathuo
8334f9795c
Merge pull request #917 from mathuo/913-returning-group-in-popout-to-main-window-via-drag-creates-empty-space-ghost-group
bug: ghost groups appearing
2025-04-28 21:32:47 +01:00
mathuo
7ea3154946
Merge pull request #828 from dzek69/patch-1
Fix provenance npm link
2025-04-28 21:27:28 +01:00
mathuo
1ef3dc06ce
Merge pull request #827 from AlexErrant/patch-1
drop extraneous <BrowserHeader />
2025-04-28 21:25:47 +01:00
mathuo
1ff74f2e65
Merge pull request #916 from mathuo/903-popover-overflow-when-hovering-right-aligned-more-icon-in-panel-group
903 popover overflow when hovering right aligned more icon in panel group
2025-04-28 21:24:40 +01:00
mathuo
a82aac09bc
bug: ghost groups appearing 2025-04-23 20:57:35 +01:00
mathuo
d1239a5ee5
bug: popup within floating panel 2025-04-23 20:35:46 +01:00
mathuo
22deb851dc
bug: popup overflow 2025-04-15 19:24:23 +01:00
mathuo
87f257df1e
chore(release): publish v4.2.3 2025-04-08 18:23:57 +01:00
mathuo
a92a056981
chore: correct versions 2025-04-08 18:23:44 +01:00
mathuo
c3e203f420
chore: update lerna 2025-04-08 18:22:33 +01:00
mathuo
8bdd15161c
chore: v4.2.3 docs 2025-04-08 18:19:12 +01:00
mathuo
8a3a7e5063
chore(release): publish v4.2.2 2025-03-26 22:15:46 +00:00
mathuo
65d95f1271
chore: v4.2.2 docs 2025-03-26 22:15:14 +00:00
mathuo
3ec6627013
Merge pull request #892 from mathuo/889-splitviewreact-and-gridviewreact-encounter-error-invalid-operation-resource-is-already-disposed
bug: remove reference to component once disposed preventing further u…
2025-03-26 22:14:59 +00:00
mathuo
c0227d620c
bug: remove reference to component once disposed preventing further usage 2025-03-26 22:08:31 +00:00
mathuo
aad168da84
chore(release): publish v4.2.1 2025-03-18 19:52:39 +00:00
mathuo
dfee4111a2
chore: v4.2.1 docs 2025-03-18 19:46:05 +00:00
mathuo
712f3f860d
Merge pull request #888 from mathuo/886-drag-and-drop-broken-after-latest-version-420
bug: fix options init
2025-03-18 19:45:23 +00:00
mathuo
f545a0a5c7
Merge pull request #887 from mathuo/884-cant-drop-tabs-between-panels-and-some-other-issues-with-v4-1
bug: dnd issues
2025-03-18 19:40:21 +00:00
mathuo
e3d39fd2ed
bug: fix options init 2025-03-18 19:38:32 +00:00
mathuo
dca0eb0df7
bug: dnd issues 2025-03-18 19:32:54 +00:00
mathuo
8188fd9429
chore(release): publish v4.2.0 2025-03-17 19:49:00 +00:00
mathuo
54a51ed10b
Merge branch 'master' of https://github.com/mathuo/dockview 2025-03-17 19:48:49 +00:00
mathuo
1a11a4ba2c
chore: docs 2025-03-17 19:48:37 +00:00
mathuo
b6d83df1aa
chore: v4.2.0 docs 2025-03-17 19:47:34 +00:00
mathuo
6444e4cb7d
Merge pull request #885 from mathuo/884-cant-drop-tabs-between-panels-and-some-other-issues-with-v4
feat: disableCustomScrollbars option
2025-03-17 19:47:13 +00:00
mathuo
ca7bd0a86d
bug: popover z-index 2025-03-17 19:29:06 +00:00
mathuo
dc828b7658
feat: disableCustomScrollbars option 2025-03-17 19:28:36 +00:00
mathuo
6e02e59fec
chore: v4.1.0 docs 2025-03-16 21:09:38 +00:00
mathuo
f79bbe0a6a
chore(release): publish v4.1.0 2025-03-16 21:08:08 +00:00
mathuo
12448e006f
chore: v4.1.0 docs 2025-03-16 21:07:51 +00:00
mathuo
5e380affe7
Merge pull request #882 from mathuo/676-is-it-possiable-that-the-id-and-title-of-group-can-be-assigned
676 is it possiable that the id and title of group can be assigned
2025-03-16 21:01:18 +00:00
mathuo
a44fc01f34
Merge branch 'master' of https://github.com/mathuo/dockview into 676-is-it-possiable-that-the-id-and-title-of-group-can-be-assigned 2025-03-16 20:48:41 +00:00
mathuo
8e03e584a7
Merge pull request #876 from mathuo/857-ondidrepositionpopoutgroup-event
feat: popout group resize events
2025-03-16 20:45:40 +00:00
mathuo
1ddcaefe80
test: add tests 2025-03-16 20:43:04 +00:00
mathuo
d086dfd081
Merge pull request #864 from dqhieuu/master
Make `id` option in addGroup without referenceGroup/referencePanel work
2025-03-16 20:40:54 +00:00
mathuo
b231367e44
Merge pull request #791 from mathuo/774-drag-and-drop-not-working-for-iframe-panels-within-a-shadow-dom
bug: disable iframes within shadowdom during dnd
2025-03-16 20:33:07 +00:00
mathuo
bba22fedd4
feat: popout group resize events 2025-03-16 20:28:35 +00:00
mathuo
3ebcb8eaef
Merge pull request #875 from mathuo/863-headercomponents-for-paneviewreact-is-never-used-and-cannot-set-height-because-harcoded-to-22px
feat: custom paneview header height
2025-03-16 20:26:33 +00:00
mathuo
39dd5f0759
feat: more efficient search 2025-03-16 20:23:39 +00:00
mathuo
e4f07dfbda
Merge pull request #881 from mathuo/721-loading-of-splitview-state-from-json-adds-extra-div-containers-that-break-layout
bug: remove splitview dom element
2025-03-16 20:09:31 +00:00
mathuo
d30263af67
bug: remove splitview dom element 2025-03-14 22:12:22 +00:00
mathuo
54ae457ccd
chore(release): publish v4.0.1 2025-03-14 22:01:56 +00:00
mathuo
416039bc99
chore: v4.0.1 docs 2025-03-14 21:59:59 +00:00
mathuo
e8fdabba08
Merge pull request #880 from mathuo/878-fullwidth-tabs-are-not-rendered-full-width-in-40
bug: fix full-width css
2025-03-14 21:59:08 +00:00
mathuo
9373802115
Merge pull request #879 from mathuo/877-missing-tab-divider-in-40
bug: fix tab divider css
2025-03-14 21:59:03 +00:00
mathuo
759dcc7b05
bug: fix full-width css 2025-03-14 21:57:37 +00:00
mathuo
f8faca731d
bug: fix tab divider css 2025-03-14 21:55:33 +00:00
mathuo
d168356344
Merge branch 'master' of https://github.com/mathuo/dockview into 774-drag-and-drop-not-working-for-iframe-panels-within-a-shadow-dom 2025-03-12 21:23:46 +00:00
mathuo
64e11a880c
bug: disable iframes within shadowdom during dnd 2025-03-12 21:16:21 +00:00
mathuo
a306742508
feat: custom paneview header height 2025-03-12 21:03:05 +00:00
mathuo
bffd2dea89
chore(release): publish v4.0.0 2025-03-12 20:25:13 +00:00
mathuo
ac92d59d0a
chore: v4.0.0 docs 2025-03-12 20:24:59 +00:00
mathuo
21d94b654b
chore: generate docs 2025-03-12 20:18:27 +00:00
mathuo
1030bdb778
feat: rename theme property 2025-03-12 20:16:57 +00:00
mathuo
082b811d20
Merge pull request #870 from mathuo/866-splitviewreact-rendered-twice-in-react-strict-mode
bug: remove element after dispose
2025-03-12 20:06:31 +00:00
mathuo
4eff83e9a0
bug: remove element after dispose 2025-03-10 21:35:17 +00:00
mathuo
090f2d26f8
chore: docs 2025-03-10 21:28:33 +00:00
mathuo
e34fb43913
chore: theme docs 2025-03-10 21:25:11 +00:00
mathuo
c0119d65c0
chore: fixup docs 2025-03-10 21:17:33 +00:00
mathuo
d3d57b62b2
Merge pull request #822 from mathuo/610-feature-request-dropdown-menu-to-handle-overflow-tabs-4
tabs overflow menu
2025-03-03 21:52:23 +00:00
mathuo
96d6947aa6
feat: scrollbars 2025-03-03 21:45:32 +00:00
mathuo
5fb13dd8a2
chore: update sonarqube build version 2025-03-03 20:47:54 +00:00
mathuo
cfe37766a9
feat: scrollbars 2025-03-03 20:47:44 +00:00
mathuo
7a6b2cb26d
feat: tab panel overflow dropdown 2025-02-27 21:15:38 +00:00
Hieu
6511b8d936
Make addGroup wiithout reference panel/group allow id option 2025-02-24 04:54:01 +07:00
mathuo
5754ddc3f4
Merge branch 'master' of https://github.com/mathuo/dockview into 610-feature-request-dropdown-menu-to-handle-overflow-tabs-4 2025-02-23 20:19:12 +00:00
mathuo
eec57c1cde
Merge pull request #850 from mathuo/849-improved-dnd-overlay-model
feat: improved dnd model
2025-02-23 20:16:37 +00:00
mathuo
3530c9896e
Merge branch 'master' of https://github.com/mathuo/dockview into 849-improved-dnd-overlay-model 2025-02-23 20:09:03 +00:00
mathuo
d811ca6554
feat: improved dnd model 2025-02-23 19:53:43 +00:00
mathuo
ab965ca726
chore(release): publish v3.2.0 2025-02-12 21:29:30 +00:00
mathuo
b13c841416
chore: v3.2.0 docs 2025-02-12 21:29:04 +00:00
mathuo
773bf5a53c
Merge pull request #860 from mathuo/859-added-support-for-sash-delay-and-duration-customization
859 added support for sash delay and duration customization
2025-02-12 21:28:34 +00:00
mathuo
837fabac86
feat: active sash animation css properties 2025-02-12 21:22:19 +00:00
mathuo
21caabce60
Merge pull request #858 from amirmamaghani/master
Added support for sash delay and duration customization
2025-02-12 21:15:52 +00:00
mathuo
14b918b7ae
chore: enhance examples page 2025-02-12 21:01:36 +00:00
Amir
f98be640ce Added support for sash delay and duration customization 2025-02-12 14:54:41 +01:00
mathuo
cd1aa81d93
Merge pull request #856 from mathuo/833-vanilla-js-expand-header-buttons
chore: add template example
2025-02-09 22:03:05 +00:00
mathuo
490fc05baf
chore: add template example 2025-02-09 14:49:01 +00:00
mathuo
16373429a8
chore(release): publish v3.1.1 2025-02-09 14:40:58 +00:00
mathuo
59fba25ade
Merge branch 'master' of https://github.com/mathuo/dockview 2025-02-09 14:40:47 +00:00
mathuo
cdd0183fa9
chore: v3.1.1 docs 2025-02-09 14:40:29 +00:00
mathuo
98cbe377c2
Merge pull request #855 from mathuo/853-middle-button-click---closes-tabs-with-hideclose
conditional middle-btn tab close
2025-02-09 14:38:46 +00:00
mathuo
d8da2f29c3
conditional middle-btn tab close 2025-02-08 15:38:31 +00:00
mathuo
8ed0fb5586
chore : v3.1.0 docs 2025-02-02 22:31:11 +00:00
mathuo
a56f01215b
chore : v3.1.0 docs 2025-02-02 22:30:58 +00:00
mathuo
e71d8b1d09
chore(release): publish v3.1.0 2025-02-02 22:30:35 +00:00
mathuo
71b99541b3
chore: v3.0.3 docs 2025-02-02 20:57:55 +00:00
mathuo
0e3afcf83f
Merge pull request #847 from mathuo/830-cannot-close-tab-with-middle-mouse-button
feat: close tab with middle btn
2025-01-31 22:16:59 +00:00
mathuo
1a85444b81
Merge pull request #848 from mathuo/835-crash-on-navigation-with-open-popup
835 crash on navigation with open popup
2025-01-31 22:16:40 +00:00
mathuo
19a22c49c3
bug: popup disposal runs after instance dispose 2025-01-30 20:40:18 +00:00
mathuo
06f02ba411
Merge pull request #845 from chris-mrl/fix-crash-open-popout-navigation
check tabToRemove is not undefined before access
2025-01-30 20:37:09 +00:00
mathuo
0e9c648fa9
feat: close tab with middle btn 2025-01-30 20:30:22 +00:00
mathuo
bb93c9e4c8
Merge pull request #843 from mathuo/842-api-init-bug
bug: setup onDidAcitvePanelChange subscription quicker
2025-01-28 20:50:49 +00:00
mathuo
c6dcef537f
bug: setup onDidAcitvePanelChange subscription quicker 2025-01-28 20:30:38 +00:00
Chris Nolan
3e409c4265
check tabToRemove is not undefined before access 2025-01-28 08:15:19 +00:00
mathuo
ca09ae537d
Create SECURITY.md 2025-01-27 22:35:43 +00:00
mathuo
e9985df262
Merge pull request #831 from milomg/patch-1
Fix vertical sash in replit theme
2025-01-27 19:05:30 +00:00
Milo Mighdoll
dc6bfc67e3
Fix vertical sash in replit theme 2025-01-20 12:42:31 -05:00
mathuo
5ca5ffac8d
tmp 2025-01-19 20:00:26 +00:00
mathuo
723272d6de
Merge branch 'master' of https://github.com/mathuo/dockview into 610-feature-request-dropdown-menu-to-handle-overflow-tabs-4 2025-01-14 21:24:37 +00:00
mathuo
6421a72653
chore: use dockview-core package metrics in README
Some checks failed
CI / build (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
2025-01-14 18:01:59 +00:00
Jacek Nowacki
0c1b8ce4d7
Fix provenance npm link 2025-01-12 12:12:26 +01:00
Alex Errant
f40532f272
drop extraneous <BrowserHeader /> 2025-01-11 16:17:34 -06:00
mathuo
6b75b5093c
chore: fix docs 2025-01-11 21:04:44 +00:00
mathuo
c0cbe89835
chore(release): publish v3.0.2 2025-01-11 15:12:57 +00:00
mathuo
b46a473cdf
chore: v3.0.2 release notes 2025-01-11 15:00:00 +00:00
mathuo
239c99ffe5
chore: fix docs 2025-01-11 14:58:06 +00:00
mathuo
6678ae24e0
Merge pull request #825 from mathuo/818-container-with-theme-class-is-created-twice-1
bug: duplicate container HTML Element
2025-01-11 14:57:56 +00:00
mathuo
680eaca96c
Merge pull request #824 from mathuo/797-popout-group-flow-error-1
bug: fix floating->popout->floating group transition
2025-01-11 14:36:14 +00:00
mathuo
3d23a2d352
Merge branch 'master' of https://github.com/mathuo/dockview into 818-container-with-theme-class-is-created-twice-1 2025-01-11 14:34:28 +00:00
mathuo
c7c1ae9238
Merge pull request #816 from zaxer2/Making-React-Dockview-Demo-work-nice-with-Strict-Mode
Fixing duplicate state in React-Dockview-Demo caused by strict mode
2025-01-11 14:33:28 +00:00
mathuo
c122bfd310
fixup demo wrt React.StrictMode 2025-01-10 22:09:24 +00:00
mathuo
1a3c6ea7db
bug: duplicate container HTML Element 2025-01-10 22:08:37 +00:00
mathuo
c6865c691c
bug: fix floating->popout->floating group transition 2025-01-09 20:42:19 +00:00
mathuo
872ec7cba9
chore(release): publish v3.0.1 2025-01-09 20:17:19 +00:00
mathuo
2a3647db28
chore: v3.0.1 docs 2025-01-09 20:16:59 +00:00
mathuo
2f9af48146
Merge pull request #819 from mathuo/818-container-with-theme-class-is-created-twice
bug: duplicate root container
2025-01-09 20:07:39 +00:00
mathuo
04e4ea1a70
tabs overflow menu 2025-01-06 21:11:49 +00:00
mathuo
2d8d38b466
bug: duplicate root container 2025-01-06 20:14:14 +00:00
zaxer2
10fd5778dc
Copying Sandbox change to corresponding Template
see prev. commit
2025-01-03 13:24:28 -05:00
zaxer2
cd91f4a4d3
Updated react dockview-demo CodeSandbox to reset relevant state on subsequent onReady calls
Strict Mode causes the Dockview component to render twice, causing onReady to be called twice, which puts two copies of DefaultLayout in state without resetting between calls.

A most-ideal solution would probably be to expose an onUnload hook or something like that, to be called after one onReady but before the next. Then, the state resets could be called in that hook. but this fix will at least ensure the Dockview-Demo codesandbox behaves nicely for the time being.
2025-01-03 13:22:07 -05:00
mathuo
148a05a201
chore(release): publish v3.0.0 2024-12-29 14:17:33 +00:00
mathuo
8359596be0
chore: v3.0.0 docs 2024-12-29 14:17:13 +00:00
mathuo
cb45889aca
chore: sonar fixes 2024-12-29 13:55:54 +00:00
mathuo
5e116c80b4
Merge pull request #812 from mathuo/809-standardize-framework-components-1
chore: align api with existing components
2024-12-28 14:37:24 +00:00
mathuo
20eb30ed1c
chore: docs config 2024-12-28 14:30:30 +00:00
mathuo
5173922c69
chore: docs 2024-12-28 14:29:48 +00:00
mathuo
0ca56eaa8a
chore: align api with existing components 2024-12-28 14:21:23 +00:00
mathuo
c14b66e5e5
Merge pull request #811 from mathuo/784-class-dv-single-tab-not-updated-on-drag-drop-of-tabs
bug: fix classname enablement
2024-12-27 22:38:23 +00:00
mathuo
cc5037d208
bug: fix classname enablement 2024-12-27 19:52:23 +00:00
mathuo
a53665adc5
chore: autogen docs 2024-12-23 20:04:14 +00:00
mathuo
d799b5bc89
Merge pull request #810 from mathuo/809-standardize-framework-components
feat: migrate to generic construction
2024-12-23 19:58:33 +00:00
mathuo
fade057412
feat: migrate to generic construction 2024-12-23 19:51:51 +00:00
mathuo
f6e7e4e390
Merge pull request #806 from mathuo/805-rename-class-dockview-react-part-to-dv-react-part
feat: rename class
2024-12-23 15:56:06 +00:00
mathuo
d33babd522
Merge pull request #808 from mathuo/807-dockview-vue-vue-peer-dependency
chore: vue3 peerDependency
2024-12-23 15:54:06 +00:00
mathuo
7df9c510bd
chore: clean up project dependencies 2024-12-23 15:53:20 +00:00
mathuo
3479828237
chore: vue3 peerDependency 2024-12-23 15:52:53 +00:00
mathuo
b3ce3e0366
feat: rename class 2024-12-22 19:24:20 +00:00
mathuo
32fa1511d8
chore(release): publish v2.1.4 2024-12-22 19:20:36 +00:00
mathuo
e1304ce694
chore: docs 2024-12-22 19:20:24 +00:00
mathuo
bdf81fd5b5
Merge branch 'master' of https://github.com/mathuo/dockview 2024-12-22 19:20:06 +00:00
mathuo
cd7984cb2b
Merge pull request #804 from mathuo/803-popout-overlay-container-incorrect-for-floating-group-return
bug: fix overlay container for popout to floating
2024-12-22 19:20:01 +00:00
mathuo
491872ea75
chore: v2.1.4 docs 2024-12-22 19:19:38 +00:00
mathuo
296b49180e
bug: fix overlay container for popout to floating 2024-12-22 19:14:14 +00:00
mathuo
487d02bd90
Merge pull request #802 from mathuo/801-disposable-fix
chore: adjust dockview disposable
2024-12-22 18:54:07 +00:00
mathuo
4d01d4e0af
chore: adjust dockview disposable 2024-12-22 18:47:29 +00:00
mathuo
8650de90aa
chore(release): publish v2.1.3 2024-12-22 10:17:37 +00:00
mathuo
e45d9e48e8
Merge pull request #800 from mathuo/799-popout-group-new-group-rendering-bug
bug: popout group to new group rendering bug fix
2024-12-22 10:17:18 +00:00
mathuo
da750e89d7
chore: v2.1.3 docs 2024-12-22 10:13:24 +00:00
mathuo
81a904ccbc
bug: popout group to new group rendering bug fix 2024-12-22 10:10:26 +00:00
mathuo
6016362c5c
chore: docs 2024-12-22 09:41:57 +00:00
mathuo
7fe2e43d43
chore(release): publish v2.1.2 2024-12-21 19:25:31 +00:00
mathuo
56d4dc7c74
chore: v2.1.2 docs 2024-12-21 19:25:06 +00:00
mathuo
6fbe2b4233
Merge pull request #798 from mathuo/797-popout-group-flow-error
bug: fixup popout group flows
2024-12-21 19:24:50 +00:00
mathuo
f749372eb2
chore: memory leak fixes and tests 2024-12-21 14:22:53 +00:00
mathuo
c216d70354
chore: comments 2024-12-21 14:00:57 +00:00
mathuo
0d32d285d2
chore: remove testing code 2024-12-21 13:59:24 +00:00
mathuo
5d868e63ce
feat: additional event sequencing checks 2024-12-21 13:58:11 +00:00
mathuo
7515b9b05d
bug: fixup popout group flows 2024-12-21 13:33:09 +00:00
mathuo
703418e27f
chore: typo 2024-12-20 20:07:58 +00:00
mathuo
53cdf42d84
chore(release): publish v2.1.1 2024-12-20 20:07:17 +00:00
mathuo
140a61f401
chore: v2.1.1 docs 2024-12-20 20:06:49 +00:00
mathuo
ff0bf75632
Merge pull request #796 from mathuo/795-popout-groups-bug
bug: only dispose of ref group if empty
2024-12-20 20:05:02 +00:00
mathuo
dd918294d1
bug: only dispose of ref group if empty 2024-12-19 22:05:59 +00:00
mathuo
684b0593e7
chore: update auto-gen docs 2024-12-19 21:33:55 +00:00
mathuo
13c4a65e18
chore(release): publish v2.1.0 2024-12-17 22:17:55 +00:00
mathuo
755135c5ad
chore: fix demo 2024-12-17 22:10:49 +00:00
mathuo
15bf4bbd1f
chore: v2.1.0 docs 2024-12-17 21:39:01 +00:00
mathuo
429177436e
Merge pull request #789 from mathuo/788-sonar-fixes
chore: adjust sonar parameters
2024-12-10 20:20:29 +00:00
mathuo
cf6891368e
chore: adjust sonar parameters 2024-12-10 19:54:23 +00:00
mathuo
e2302372b1
chore: fix sonar issues 2024-12-10 19:30:32 +00:00
mathuo
f13f009155
chore: adjust sonar parameters 2024-12-10 19:21:16 +00:00
mathuo
c5025424c7
Merge pull request #783 from mathuo/777-keeping-header-actions-even-when-no-tabs-are-open
feat: ensure group always exists
2024-12-10 19:20:31 +00:00
mathuo
a66fdae8a3
Merge pull request #762 from mathuo/494-unable-to-persist-fullscreen-maximized-mode
feat: serialization of maximized views
2024-12-10 19:16:08 +00:00
mathuo
c777ff463d
Merge pull request #787 from mathuo/786-dockview-react-peer-dependencies
feat: specify react peerDependency
2024-12-10 19:15:03 +00:00
mathuo
04327b4613
Merge branch 'master' of https://github.com/mathuo/dockview into 777-keeping-header-actions-even-when-no-tabs-are-open 2024-12-10 19:12:59 +00:00
mathuo
a02241d1a7
feat: ensure group always exists 2024-12-10 19:11:46 +00:00
Daniel Goodwin
615886e666
Do not close group if it's the only group available 2024-12-10 19:11:17 +00:00
mathuo
1b921864fc
chore: fix sonar issue 2024-12-10 19:11:17 +00:00
mathuo
1ce96c8ab8
test: add tests 2024-12-10 19:11:16 +00:00
mathuo
d651c2213e
bug: fix setVisible on floating groups 2024-12-10 19:11:16 +00:00
Jafar Akhondali
1d61a47e7c
Block malicious looking requests to prevent path traversal attacks. 2024-12-10 19:11:16 +00:00
mathuo
aeb0e38249
feat: tab container empty space not focusable 2024-12-10 19:11:16 +00:00
mathuo
df3269d56e
chore: v2.0.0 docs 2024-12-10 19:11:16 +00:00
mathuo
0233e8fa42
chore(release): publish v2.0.0 2024-12-10 19:11:15 +00:00
mathuo
2bcd62412d
feat: specify react peerDependency 2024-12-10 19:01:18 +00:00
mathuo
32e759ef75
Merge pull request #785 from mathuo/782-dockview-fails-or-crashes-when-attempting-to-make-a-floating-group-from-a-popout-group
bug: wrong event ordering
2024-12-09 20:03:36 +00:00
mathuo
ede5a58ec9
Merge pull request #769 from mathuo/705-when-loading-stored-layout-having-popout-grooups-dockview-doesnt-respect-the-popouturl-passed-instead-it-defaults-it-to-popouthtml
feat: persist custom popout group urls
2024-12-09 19:41:44 +00:00
mathuo
56bdec846c
bug: wrong event ordering 2024-12-09 19:40:49 +00:00
mathuo
25489bf48e
Merge pull request #770 from mathuo/689-docs-demos-for-vanilla-js-support
chore: fix files
2024-11-15 21:19:03 +00:00
mathuo
9564319e43
chore: fix files 2024-11-15 21:18:09 +00:00
mathuo
461c30dc5b
feat: persist custom popout group urls 2024-11-15 21:03:38 +00:00
mathuo
be628a5683
Merge pull request #743 from mathuo/689-docs-demos-for-vanilla-js-support
chore: docs
2024-11-15 20:48:58 +00:00
mathuo
19f027a0db
chore: docs 2024-11-15 20:36:51 +00:00
mathuo
e46a586044
chore: remove old docs 2024-11-15 20:36:26 +00:00
mathuo
2f4150013b
feat: serialization of maximized views 2024-11-10 20:19:20 +00:00
mathuo
24cc974a68
Merge pull request #755 from mathuo/665-floating-group-setvisible-will-crash
bug: fix setVisible on floating groups
2024-11-10 14:29:57 +00:00
mathuo
a00875aae0
chore: fix sonar issue 2024-11-10 11:12:01 +00:00
mathuo
02d0ad8634
test: add tests 2024-11-10 10:58:21 +00:00
mathuo
93b29e77c4
Merge pull request #759 from JafarAkhondali/master
Fixing a Path Traversal Vulnerability
2024-11-10 10:42:03 +00:00
mathuo
df0d12128b
Merge pull request #761 from mathuo/760-remove-tabindex-from-empty-tab-space
feat: tab container empty space not focusable
2024-11-07 18:58:54 +00:00
mathuo
986132c602
feat: tab container empty space not focusable 2024-11-07 18:58:25 +00:00
Jafar Akhondali
fe39c475a2 Block malicious looking requests to prevent path traversal attacks. 2024-11-07 17:23:01 +01:00
mathuo
c9e90168a4
bug: fix setVisible on floating groups 2024-11-04 20:28:27 +00:00
mathuo
1a9ee8c34e
chore: v2.0.0 docs 2024-11-03 19:23:16 +00:00
mathuo
8a05aede4c
chore(release): publish v2.0.0 2024-11-03 19:21:57 +00:00
mathuo
83b01a9a66
Merge branch 'master' of https://github.com/mathuo/dockview into 689-docs-demos-for-vanilla-js-support 2024-11-03 19:19:03 +00:00
mathuo
7ebbd437a1
Merge pull request #752 from mathuo/739-sonar-code-cleanup
chore: sonar
2024-11-03 19:15:18 +00:00
mathuo
d8ae04e274
chore: sonar 2024-11-03 19:14:49 +00:00
mathuo
3f5c9743ad
Merge pull request #751 from mathuo/750-add-panel-in-a-specific-index-within-a-group-without-making-it-active
feat: addPanel positional index
2024-11-03 19:05:35 +00:00
mathuo
3d1fa25677
Merge pull request #744 from mathuo/717-setconstraints-no-longer-works
bug: fix constraints
2024-11-03 19:05:19 +00:00
mathuo
108bc49401
Merge pull request #748 from mathuo/747-fromjson-error-while-the-json-include-popoutgroups
bug: duplicate .close() call
2024-11-03 19:05:00 +00:00
mathuo
291e76afdb
feat: addPanel positional index 2024-11-03 15:12:23 +00:00
mathuo
2dc4f81b20
bug: fix constraints 2024-11-03 14:56:58 +00:00
mathuo
ca6f46ac8e
Merge pull request #749 from mathuo/716-css-variable-dv-background-color-is-always-black-which-breaks-theming-of-auxilliary-components
feat: remove --dv-background-color
2024-11-03 14:19:38 +00:00
mathuo
dad9eba474
feat: remove --dv-background-color 2024-11-02 21:11:21 +00:00
mathuo
adaeb16b98
bug: duplicate .close() call 2024-11-02 20:18:11 +00:00
mathuo
ee7cf637bb
Merge pull request #746 from mathuo/739-sonar-code-cleanup
chore: fix theme
2024-10-31 19:20:12 +00:00
mathuo
e70755e4fc
chore: update auto-gen api 2024-10-29 20:25:09 +00:00
mathuo
112dc2e2a9
Merge branch 'master' of https://github.com/mathuo/dockview into 739-sonar-code-cleanup 2024-10-29 20:24:16 +00:00
mathuo
5cf3cfb616
chore: docs 2024-10-29 20:22:40 +00:00
mathuo
f6f248c63a
chore: fix theme 2024-10-29 20:06:03 +00:00
mathuo
4bf3fc4820
Merge pull request #740 from mathuo/739-sonar-code-cleanup
chore: code cleanup
2024-10-27 20:09:46 +00:00
mathuo
40c1a26ead
chore: fix 2024-10-27 20:00:54 +00:00
mathuo
3f3ed52007
Merge pull request #742 from mathuo/741-remove-depreciated-method
chore: remove depricated method
2024-10-27 19:54:18 +00:00
mathuo
b812cf9117
chore: code cleanup 2024-10-27 19:53:29 +00:00
mathuo
210ff38cfa
chore: remove depricated method 2024-10-27 19:47:30 +00:00
mathuo
3ffb5034c6
Merge pull request #738 from mathuo/726-__dockview_internal_drag_event__-appearing-in-editor-text-after-dragdrop-of-panel
feat: use empty string to fill dataTransfer field
2024-10-27 10:37:26 +00:00
mathuo
2657c79620
feat: use empty string to fill dataTransfer field 2024-10-27 10:20:54 +00:00
mathuo
cd4cd0f0ce
Merge pull request #673 from mathuo/672-vu3-injectprovides-not-propagated-to-panels
bug: maintain inject/provide context
2024-10-27 09:48:55 +00:00
mathuo
408db93917
Merge pull request #737 from mathuo/736-bug-set-initial-size-and-use-proper-window-on-event
736 bug set initial size and use proper window on event
2024-10-27 09:40:35 +00:00
mathuo
f557e9080a
test: add tests 2024-10-26 22:05:07 +01:00
mathuo
e0744531ca
Merge pull request #688 from mathuo/687-css-class-prefixing
chore: rename classes to start with dv-
2024-10-26 21:57:54 +01:00
mathuo
3c680b251f
Merge pull request #727 from iammola/popout-group-sizing-event
🐛 fix: set initial size and use proper window on event
2024-10-26 21:52:43 +01:00
mathuo
c086cabd39
Merge branch 'master' of https://github.com/mathuo/dockview into 687-css-class-prefixing 2024-10-12 15:22:08 +01:00
mathuo
a202a49182
Merge pull request #731 from mathuo/710-reloading-of-popout-window-is-displaying-blank-page
bug: close popout window if unloaded
2024-10-12 15:20:51 +01:00
mathuo
efd77413da
chore: docs typo 2024-10-12 15:20:03 +01:00
mathuo
0097da7fde
chore(release): publish v1.17.2 2024-10-12 15:18:12 +01:00
mathuo
8c7369ccf0
chore: 1.17.2 release notes 2024-10-12 15:17:49 +01:00
mathuo
8015860bde
Merge pull request #730 from mathuo/720-allow-customization-of-the-default_overlay_z_index-value
720 allow customization of the default overlay z index value
2024-10-09 22:23:04 +01:00
mathuo
14382aa0fd
Merge pull request #715 from NotWearingPants/patch-2
docs: add the splash-screen to the dockview package
2024-10-09 22:16:57 +01:00
mathuo
7ddb63383f
bug: close popout window if unloaded 2024-10-09 22:16:27 +01:00
mathuo
ac56a1f250
feat: fixup z-index overlay override 2024-10-09 22:14:06 +01:00
mathuo
12bb6f6d20
Merge pull request #724 from amirmamaghani/master
Added support for custom overlay z-index
2024-10-09 21:53:27 +01:00
mathuo
bc455265cd
Merge pull request #714 from NotWearingPants/patch-1
docs: fix typo in core/panels/tabs
2024-10-04 20:09:27 +01:00
Ademola Adedeji
6881daa593 🐛 fix: set initial size and use proper window on event 2024-10-03 20:17:17 -03:00
Amir
3c90e9d196 Added support for custom overlay z-index 2024-10-01 08:48:32 +02:00
NotWearingPants
c55257ac56
docs: add the splash-screen to the dockview package 2024-09-18 02:10:39 +03:00
NotWearingPants
1b7f29e800
docs: fix typo in core/panels/tabs 2024-09-18 01:41:51 +03:00
mathuo
693a3cd6ef
chore: docs 2024-09-05 20:26:17 +01:00
mathuo
d1d8c8083e
chore(release): publish v1.17.1 2024-09-05 20:18:53 +01:00
mathuo
fd29ea570f
Merge branch 'master' of https://github.com/mathuo/dockview 2024-09-05 20:18:41 +01:00
mathuo
1acdd969a0
chore: v1.17.1 docs 2024-09-05 20:18:08 +01:00
mathuo
aeda5f4ca1
Merge pull request #709 from mathuo/696-touch-support-for-dragging-dockview-panels
bug: fix mouseup->pointerup
2024-09-05 20:16:36 +01:00
mathuo
5df4c5cce1
bug: fix mouseup->pointerup 2024-09-05 20:16:01 +01:00
mathuo
62fee4e7ec
chore(release): publish v1.17.0 2024-09-05 19:49:21 +01:00
mathuo
b24470fa42
chore: v1.17.0 release notes 2024-09-05 19:48:56 +01:00
mathuo
0c602afab5
Merge pull request #703 from mathuo/702-documentation
chore: docs
2024-09-05 19:33:13 +01:00
mathuo
ab5a11f13b
chore: docs 2024-09-05 19:20:37 +01:00
mathuo
fc7b9fb2e2
Merge pull request #698 from mathuo/696-touch-support-for-dragging-dockview-panels
feat: ensure use of pointerevents for touch support
2024-08-28 20:32:07 +01:00
mathuo
d519c239e3
Merge pull request #690 from mathuo/640-panel-and-group-default-sizes-and-bounding-dimensions
640 panel and group default sizes and bounding dimensions
2024-08-28 20:31:42 +01:00
mathuo
2b36844110
Merge pull request #693 from mathuo/640-panel-and-group-default-sizes-and-bounding-dimensions-1
feat: retain size when moving groups
2024-08-28 20:31:25 +01:00
mathuo
e2e91834ff
feat: retain size when moving groups 2024-08-27 21:16:14 +01:00
mathuo
72f457ab9d
feat: panel initial sizing 2024-08-27 20:59:38 +01:00
mathuo
1033b80783
feat: ensure use of pointerevents for touch support 2024-08-27 20:54:27 +01:00
mathuo
7adabec088
Merge pull request #694 from OneAndOnlyFinbar/master
Fix typo in replit theme
2024-08-24 21:40:33 +01:00
OneAndOnlyFinbar
4841d95573
Fix typo in replit theme
Remove duplicated pound sign.
2024-08-24 15:02:18 -04:00
mathuo
2dc0dafa5a
feat: addGroup initial sizes 2024-08-20 22:00:21 +01:00
mathuo
9d4f4cb534
feat: panel constraints 2024-08-20 21:52:11 +01:00
mathuo
05084030db
Merge pull request #686 from mathuo/651-offical-support-for-vanilla-typescript-1
chore: updateOptions logic
2024-08-16 19:16:42 +01:00
mathuo
4d71775804
chore: fix test 2024-08-16 18:54:33 +01:00
mathuo
77bccb3f69
chore: remove method 2024-08-15 21:39:45 +01:00
mathuo
affb8590dc
chore: rename classes to start with dv- 2024-08-15 20:52:53 +01:00
mathuo
6c39c448bb
chore: updateOptions logic 2024-08-15 20:43:00 +01:00
mathuo
a6a2d048c7
chore(release): publish v1.16.1 2024-08-13 19:45:23 +01:00
mathuo
464e255d56
chore: 1.16.1 docs 2024-08-13 19:44:51 +01:00
mathuo
0e8139217b
Merge pull request #685 from mathuo/684-multiple-classes-on-dockviewreact-element-doesnt-work-in-1160
bug: multiple classnames
2024-08-13 19:43:29 +01:00
mathuo
1876511c70
bug: multiple classnames 2024-08-13 19:37:24 +01:00
mathuo
56182aa60f
chore(release): publish v1.16.0 2024-08-11 21:48:35 +01:00
mathuo
bf35b265db
chore: 1.16.0 docs 2024-08-11 21:47:42 +01:00
mathuo
520aa39724
Merge pull request #683 from mathuo/656-renderer-always-causes-floating-group-z-index-bug
feat: correct z-index level for floating always rendered panel
2024-08-11 20:41:15 +01:00
mathuo
59acd94bc6
feat: correct z-index level for floating always rendered panel 2024-08-11 20:34:49 +01:00
mathuo
619b0b3276
Merge pull request #679 from mathuo/656-renderer-always-causes-floating-group-z-index-bug
656 renderer always causes floating group z index bug
2024-08-11 11:04:33 +01:00
mathuo
d686b2c2c7
chore: refactor and fix tests 2024-08-11 10:45:47 +01:00
mathuo
479d4bb322
Merge pull request #682 from mathuo/681-resize-handlers-position-is-wrong-for-more-than-2-panels-in-one-branch
681 resize handlers position is wrong for more than 2 panels in one branch
2024-08-11 10:33:17 +01:00
mathuo
49b1c5a174
bug: gap sizing fixes 2024-08-11 10:26:04 +01:00
mathuo
35b3ee2b0f
Merge pull request #667 from RayJason/fix/layout-view-size-calc
fix: splitview layout view size with hidden view
2024-08-10 12:37:25 +01:00
mathuo
a443bb5e41
Merge branch 'master' of https://github.com/mathuo/dockview into 656-renderer-always-causes-floating-group-z-index-bug 2024-08-06 21:43:40 +01:00
mathuo
a05d2af417
chore: fix test 2024-08-06 21:37:07 +01:00
mathuo
1efa5c0ef6
bug: always rendered floating groups z-index 2024-08-06 21:33:20 +01:00
mathuo
6bf0263797
Merge branch 'master' of https://github.com/mathuo/dockview into 656-renderer-always-causes-floating-group-z-index-bug 2024-08-05 21:35:44 +01:00
mathuo
ed3fd57d6a
Merge pull request #678 from mathuo/677-floating-panel-documentation-example-not-working
chore: fix documentation
2024-08-05 21:28:53 +01:00
mathuo
5a80b3a58d
Merge pull request #662 from mathuo/660-dragging-last-panel-from-popout-group-breaks-layout
feat: moving single panel out of popout group
2024-08-05 21:23:37 +01:00
mathuo
f022f3cb26
Merge pull request #652 from mathuo/651-offical-support-for-vanilla-typescript
feat: offical support for vanilla typescript
2024-08-05 21:23:10 +01:00
mathuo
af5ce5bbfd
chore: fix documentation 2024-08-05 21:18:57 +01:00
mathuo
ea5b94ad90
bug: maintain inject/provide context 2024-08-01 20:47:07 +01:00
mathuo
e5e9603221
chore(release): publish v1.15.3 2024-08-01 20:07:13 +01:00
mathuo
cc18f5055c
chore: v1.15.3 docs 2024-08-01 20:06:34 +01:00
mathuo
fafc18b419
Merge pull request #670 from mathuo/668-load-layout-will-not-keep-the-size-of-floating-group
bug: floating-groups deserialization
2024-08-01 20:06:19 +01:00
mathuo
bb312d871c
Merge pull request #666 from RayJason/fix/style-typo
fix: default tab ellipsis typo
2024-08-01 20:01:35 +01:00
mathuo
49561d14cc
bug: floating-groups deserialization 2024-08-01 20:00:11 +01:00
RayJason
1cd4251083 fix: mistake of sashes offset when custom gap 2024-07-30 23:10:22 +08:00
RayJason
ee74785d7e fix: calc views style 2024-07-30 21:11:36 +08:00
RayJason
eda3ea1210 fix: splitview layout view size with hidden view 2024-07-30 15:44:38 +08:00
RayJason
f689e38e59 fix: default tab ellipsis typo 2024-07-30 15:41:01 +08:00
mathuo
f765dd52fc
bug: render mode z-index fixes 2024-07-27 20:34:06 +01:00
mathuo
04d54e1dc5
feat: moving single panel out of popout group 2024-07-27 20:24:48 +01:00
mathuo
e93a008fe4
chore: docs 2024-07-23 20:42:09 +01:00
mathuo
5b9dbdf57e
chore(release): publish v1.15.2 2024-07-17 22:34:33 +01:00
mathuo
0e77bdf4d7
chore: v1.15.2 release notes 2024-07-17 22:34:13 +01:00
mathuo
0211148b66
Merge pull request #655 from mathuo/654-resize
bug: fix layout force flag
2024-07-17 22:33:50 +01:00
mathuo
973ecff0be
bug: fix layout force flag 2024-07-17 22:28:31 +01:00
mathuo
bdf286103f
bug: continue to check size change when force= 2024-07-17 19:53:55 +01:00
mathuo
e86155adf4
feat: offical support for vanilla typescript 2024-07-17 19:41:57 +01:00
mathuo
374bd2adff
chore(release): publish v1.15.1 2024-07-16 20:25:01 +01:00
mathuo
8618ed3aad
chore: v1.15.1 release notes 2024-07-16 20:23:19 +01:00
mathuo
aa39b55563
Merge pull request #648 from mathuo/647-115-removed-types-that-are-still-valid
bug: fixup types
2024-07-16 20:22:38 +01:00
mathuo
24e8c99dea
Merge pull request #645 from timadevelop/fix/popout-single-dockviewpanel
bug: fix passing through options for opening single panel in a popot window
2024-07-16 20:20:30 +01:00
mathuo
eeab0251d2
Merge pull request #649 from mathuo/613-gap-between-panels-leads-to-some-panels-size-overflow-2
bug: fix dockview  option
2024-07-16 18:59:15 +01:00
mathuo
2111e2293c
bug: fix dockview option 2024-07-15 21:24:06 +01:00
mathuo
bd28468bf5
bug: fixup types 2024-07-15 20:44:51 +01:00
Vlad Timofeev
05b1c27320 bug: fix passing through options for opening single panel in a popout window 2024-07-15 15:50:30 +03:00
mathuo
b326291f94
chore(release): publish v1.15.0 2024-07-10 21:41:09 +01:00
mathuo
8a4380ec14
Merge pull request #638 from mathuo/626-docs-1
chore: v1.15.0 docs
2024-07-10 21:09:39 +01:00
mathuo
eb3cac8b1b
chore: improve docs 2024-07-09 21:16:59 +01:00
mathuo
0db4f59990
chore: v1.15.0 docs 2024-07-06 22:09:39 +01:00
mathuo
aed7b97bac
Merge pull request #618 from mathuo/613-gap-between-panels-leads-to-some-panels-size-overflow-1
bug: panel gap styling
2024-07-06 22:07:21 +01:00
mathuo
9e4b3bbdd6
Merge pull request #616 from mathuo/582-expose-event-for-moving-tab-within-same-panel
feat: move panel events
2024-07-06 22:07:03 +01:00
mathuo
cd59248f34
Merge branch 'master' of https://github.com/mathuo/dockview into 582-expose-event-for-moving-tab-within-same-panel 2024-07-06 21:59:08 +01:00
mathuo
876b107284
feat: move panel events 2024-07-06 21:58:38 +01:00
mathuo
ea9dc13992
bug: panel gap styling 2024-07-06 21:22:34 +01:00
mathuo
f20b5285da
Merge pull request #628 from mathuo/544-floatinggroups-support-for-css-absolute-box-attributes-bottom-and-right
544 floatinggroups support for css absolute box attributes bottom and right
2024-07-03 22:18:34 +01:00
mathuo
9b46c1e7d9
chore: addFlotaingGroup method changes 2024-07-01 22:18:27 +01:00
mathuo
d7e1fd4bb2
Merge pull request #633 from mathuo/630-after-all-the-groups-in-the-branch-are-hidden-an-error-is-reported-when-calling-fromjson
feat: setVisible enhancements
2024-07-01 22:15:48 +01:00
mathuo
ae88703a8b
feat: setVisible enhancements 2024-07-01 20:29:03 +01:00
mathuo
cf8f18dbbd
test: fix tests 2024-06-19 22:17:59 +01:00
mathuo
b96ccf00ce
Merge branch 'master' of https://github.com/mathuo/dockview into 544-floatinggroups-support-for-css-absolute-box-attributes-bottom-and-right 2024-06-14 17:16:21 +01:00
mathuo
5285baebdb
Merge pull request #621 from crubier/master
Allow right and bottom anchored floating groups
2024-06-14 17:14:58 +01:00
mathuo
3652505a08
Merge pull request #627 from mathuo/626-docs
chore: docs
2024-06-08 23:51:13 +03:00
mathuo
c5f94906d4
chore: docs 2024-06-08 21:39:43 +01:00
mathuo
e3fb689d27
chore(release): publish v1.14.2 2024-06-08 20:01:33 +01:00
mathuo
93e5ecec4c
chore: 1.14.2 release notes 2024-06-08 20:00:47 +01:00
mathuo
82dbdb29c3
Merge pull request #625 from mathuo/624-dockview-vue-error-cannot-read-properties-of-null-reading-appcontext
bug: vue getInstance
2024-06-08 19:15:19 +03:00
mathuo
476b0a1d42
Merge pull request #623 from mathuo/622-settitle-issues
bug: fix setTitle issues
2024-06-08 19:15:08 +03:00
mathuo
e7622f6c2b
bug: vue getInstance 2024-06-08 16:55:15 +01:00
mathuo
cd6604d28c
bug: fix setTitle issues 2024-06-04 22:56:27 +03:00
Vincent Lecrubier
cffd742b7b Docs 2024-06-03 11:41:07 +01:00
Vincent Lecrubier
bbdb99dbb5 Support bottom and right anchor for Overlay 2024-06-03 11:25:38 +01:00
mathuo
ce381f8ce9
Merge pull request #620 from mathuo/562-dockview-framework-wrappers-vuejs-angular-javascript-etc-3
chore: vue docs
2024-05-30 21:06:37 +01:00
mathuo
1bd2bff8f8
chore: vue docs 2024-05-30 20:59:38 +01:00
mathuo
943c2dc425
Merge pull request #617 from mathuo/562-dockview-framework-wrappers-vuejs-angular-javascript-etc-3
chore: vue3 docs
2024-05-30 20:44:23 +01:00
mathuo
bc278f2beb
chore: vue3 docs 2024-05-30 20:37:57 +01:00
mathuo
b81afd45e8
chore(release): publish v1.14.1 2024-05-28 21:47:50 +01:00
mathuo
77b8023b56
Merge branch 'master' of https://github.com/mathuo/dockview 2024-05-28 21:46:51 +01:00
mathuo
963607defe
chore: 1.14.1 release notes 2024-05-28 21:46:46 +01:00
mathuo
4a0b328622
chore: update README.md files 2024-05-28 21:46:32 +01:00
mathuo
5762faac9d
Merge pull request #614 from mathuo/613-gap-between-panels-leads-to-some-panels-size-overflow
bug: --group-gap-size overflow fix
2024-05-28 21:42:20 +01:00
mathuo
7f750330b1
bug: --group-gap-size overflow fix 2024-05-24 19:50:25 +01:00
mathuo
55d9ca31d4
Merge pull request #612 from mathuo/611-sonar-suggestions
chore: sonar suggested fixes
2024-05-24 18:33:43 +01:00
mathuo
fde6764377
chore: sonar suggested fixes 2024-05-23 22:38:38 +01:00
mathuo
9c6dae30ca
chore(release): publish v1.14.0 2024-05-23 22:01:14 +01:00
mathuo
acadeedaf6
chore: v1.14.0 release notes 2024-05-23 22:00:04 +01:00
mathuo
fc84942b9b
Merge pull request #606 from mathuo/562-dockview-framework-wrappers-vuejs-angular-javascript-etc-2
562 dockview framework wrappers vuejs angular javascript etc 2
2024-05-14 21:03:21 +01:00
mathuo
e3eb851ab7
chore: configure dockview-react package 2024-05-14 20:42:33 +01:00
mathuo
84d02b9925
Merge pull request #605 from mathuo/603-sonarcloud-cleanups
chore: cleanup code
2024-05-14 20:39:57 +01:00
mathuo
3fcbf6515e
chore: configure dockview-vue package 2024-05-14 20:37:45 +01:00
mathuo
9306d9fcdc
chore: configure dockview-react package 2024-05-14 20:36:35 +01:00
mathuo
d29052e606
chore: cleanup code 2024-05-14 20:33:14 +01:00
mathuo
9ee2b821ff
Merge pull request #604 from mathuo/603-sonarcloud-cleanups
chore: sonarcloud requests
2024-05-13 21:33:27 +01:00
mathuo
c4ab6ac562
chore: sonarcloud requests 2024-05-13 20:50:05 +01:00
mathuo
35630e4f1c
Merge pull request #594 from mathuo/562-dockview-framework-wrappers-vuejs-angular-javascript-etc-1
feat: vue3
2024-05-13 19:42:45 +01:00
mathuo
07b548c6b6
Merge branch 'master' of https://github.com/mathuo/dockview into 562-dockview-framework-wrappers-vuejs-angular-javascript-etc-1 2024-05-13 19:34:34 +01:00
mathuo
7eff8a8642
Merge pull request #602 from mathuo/601-internal-clean-up-update-function
chore: cleanup internals
2024-05-13 19:34:02 +01:00
mathuo
abaad37edd
chore: cleanup internals 2024-05-13 18:11:24 +01:00
mathuo
b68d8df9ac
chore: clean code 2024-05-11 10:42:44 +01:00
mathuo
07d67b2246
chore: remove unused imports 2024-05-10 22:59:13 +01:00
mathuo
0ae16cf444
feat: vue3 fixes 2024-05-10 22:44:24 +01:00
mathuo
26cd1cc1cc
chore: configure dockview-vue package 2024-05-09 21:04:45 +01:00
mathuo
56457fe269
Merge branch 'master' of https://github.com/mathuo/dockview into 562-dockview-framework-wrappers-vuejs-angular-javascript-etc-1 2024-05-09 20:48:58 +01:00
mathuo
688abef81d
chore(release): publish v1.13.1 2024-05-05 19:59:28 +01:00
mathuo
4803109203
chore: 1.13.1 docs 2024-05-05 19:59:04 +01:00
mathuo
4d878a375c
Merge pull request #600 from mathuo/597-ondidlayoutchange-callback-catches-panels-init
597 ondidlayoutchange callback catches panels init
2024-05-05 19:50:39 +01:00
mathuo
0de2e57a1d
Merge branch 'master' of https://github.com/mathuo/dockview into 597-ondidlayoutchange-callback-catches-panels-init 2024-05-05 19:46:28 +01:00
mathuo
87d42c96e2
Merge pull request #598 from mathuo/596-moving-a-group-leaves-ghost-groups-that-cant-be-removed
bug: duplicate group added when added group with absolute position
2024-05-05 19:44:55 +01:00
mathuo
61abf780d1
feat: improve onDidLayoutChange events 2024-05-05 14:05:46 +01:00
mathuo
ffe7d59b74
bug/feat: use a better implementation of 'asap scheduled' (and buffered per event-cycle) events 2024-05-03 20:07:55 +01:00
mathuo
3dc590351c
bug: duplicate group added when added group with absolute position 2024-05-03 19:27:21 +01:00
mathuo
5d6055c4d2
feat: vue3 2024-05-01 20:35:07 +01:00
mathuo
d0eda81a9e
chore: docs 2024-04-28 14:34:21 +01:00
mathuo
db9703a150
chore: fix docs build 2024-04-27 13:48:18 +01:00
mathuo
f6e816fa10
chore: fix docs build 2024-04-27 13:37:55 +01:00
mathuo
9c091f5126
chore(release): publish v1.13.0 2024-04-27 13:19:52 +01:00
mathuo
c6403ff6e8
chore: 1.13.0 docs 2024-04-27 13:19:25 +01:00
mathuo
24817976f6
Merge pull request #588 from mathuo/562-dockview-framework-wrappers-vuejs-angular-javascript-etc
562 dockview framework wrappers vuejs angular javascript etc
2024-04-27 13:13:03 +01:00
mathuo
459963c13b
chore: fix error message 2024-04-27 13:02:35 +01:00
mathuo
eaabf7968c
Merge branch '562-dockview-framework-wrappers-vuejs-angular-javascript-etc' of https://github.com/mathuo/dockview into 562-dockview-framework-wrappers-vuejs-angular-javascript-etc 2024-04-27 13:02:07 +01:00
mathuo
521d2a0e6d
chore: docs 2024-04-26 22:13:37 +01:00
mathuo
2a3f623c30
Merge pull request #586 from mathuo/585-add-panel-event-unintentially-called-when-adding-floating-panel
bug: prevent unintential add_panel event
2024-04-25 23:12:29 +01:00
mathuo
33d8a7a026
bug: prevent unintential add_panel event 2024-04-25 23:06:56 +01:00
mathuo
dc684d05a7
Merge pull request #576 from mathuo/562-dockview-framework-wrappers-vuejs-angular-javascript-etc
feat: vue3 prep
2024-04-25 23:04:36 +01:00
mathuo
36527910f3
chore: docs 2024-04-25 22:14:39 +01:00
mathuo
4b1b4bab32
chore: fix tests 2024-04-25 21:10:07 +01:00
mathuo
2f0e34c99f
chore: fix import 2024-04-25 21:01:54 +01:00
mathuo
67fee68ebe
Merge branch 'master' of https://github.com/mathuo/dockview into 562-dockview-framework-wrappers-vuejs-angular-javascript-etc 2024-04-25 20:59:24 +01:00
mathuo
7eff1da988
feat: vue3 work 2024-04-25 20:58:51 +01:00
mathuo
ffbd7bcf04
Merge pull request #573 from mathuo/572-opening-a-new-tab-without-activating-it
572 opening a new tab without activating it
2024-04-25 20:00:31 +01:00
mathuo
dbe97b086c
Merge branch 'master' of https://github.com/mathuo/dockview into 562-dockview-framework-wrappers-vuejs-angular-javascript-etc 2024-04-23 21:45:01 +01:00
mathuo
b0ed0a99ff
feat: vue3 prep 2024-04-21 21:31:04 +01:00
mathuo
3c45c962b2
Merge pull request #578 from qcz/td/swap-width-height
Set width and height correctly when calling layout for floating panels
2024-04-19 19:28:48 +01:00
mathuo
f124414594
Merge pull request #577 from mathuo/imgbot
[ImgBot] Optimize images
2024-04-19 19:24:34 +01:00
Tar Dániel
715cd1e03d Set width and height correctly when calling layout for floating panels 2024-04-18 11:41:00 +02:00
ImgBotApp
d00c2207d9
[ImgBot] Optimize images
*Total -- 809.66kb -> 649.59kb (19.77%)

/packages/docs/static/img/Animation.gif -- 628.83kb -> 472.85kb (24.8%)
/packages/docs/static/img/react-icon.svg -- 0.36kb -> 0.33kb (9.02%)
/packages/docs/static/img/undraw_docusaurus_mountain.svg -- 30.75kb -> 29.20kb (5.04%)
/packages/docs/static/img/undraw_docusaurus_react.svg -- 35.16kb -> 33.60kb (4.43%)
/packages/docs/static/img/add_to_group.svg -- 1.99kb -> 1.91kb (3.93%)
/packages/docs/static/img/dockview_grid_4.svg -- 6.61kb -> 6.40kb (3.25%)
/packages/docs/static/img/add_to_tab.svg -- 1.60kb -> 1.56kb (2.38%)
/packages/docs/static/img/magnet_drop_positions.svg -- 5.03kb -> 4.93kb (1.98%)
/packages/docs/static/img/dockview_logo.svg -- 3.92kb -> 3.84kb (1.97%)
/packages/docs/static/img/drop_positions.svg -- 4.88kb -> 4.79kb (1.82%)
/packages/docs/static/img/undraw_docusaurus_tree.svg -- 11.61kb -> 11.42kb (1.62%)
/packages/docs/static/img/float_move.svg -- 5.47kb -> 5.42kb (0.93%)
/packages/docs/static/img/dockview_grid_3.svg -- 18.01kb -> 17.90kb (0.61%)
/packages/docs/static/img/js-icon.svg -- 0.67kb -> 0.67kb (0.44%)
/packages/docs/static/img/codesandbox_hint.svg -- 54.78kb -> 54.77kb (0.02%)

Signed-off-by: ImgBotApp <ImgBotHelp@gmail.com>
2024-04-17 20:33:48 +00:00
mathuo
6ca39ba58b
Merge pull request #541 from mathuo/538-interested-in-porting-dockview-to-vuejs
feat: Vue 3 Support
2024-04-17 20:34:20 +01:00
mathuo
4a05fd0aed
feat: provide 'inactive' property to addPanel 2024-04-17 20:29:28 +01:00
mathuo
bc8fa59557
chore: fix jest debugging experience 2024-04-17 20:26:50 +01:00
mathuo
936499aa1e
chore: fix config 2024-04-17 19:49:11 +01:00
mathuo
9642dd844d
Merge branch 'master' of https://github.com/mathuo/dockview into 538-interested-in-porting-dockview-to-vuejs 2024-04-15 21:20:46 +01:00
mathuo
40e5c8053d
Merge branch '538-interested-in-porting-dockview-to-vuejs' of https://github.com/mathuo/dockview into 538-interested-in-porting-dockview-to-vuejs 2024-04-15 21:19:37 +01:00
mathuo
b0d98102fc
feat: multiple framework support work 2024-04-15 21:18:21 +01:00
mathuo
ec5b681196
feat: multiple framework support work 2024-04-15 21:09:33 +01:00
mathuo
5a1e41775f
chore(release): publish v1.12.0 2024-04-15 21:06:18 +01:00
mathuo
95685efbbd
chore: prepare v1.12.0 2024-04-15 21:05:30 +01:00
mathuo
ce3706d1b3
Merge pull request #570 from mathuo/569-expose-panel-component-id-via-the-panelapi
feat: expose api.(tab)component
2024-04-15 21:00:24 +01:00
mathuo
bb09f2ccf0
feat: expose api.(tab)component 2024-04-15 20:55:10 +01:00
mathuo
da0270066b
Merge pull request #566 from mathuo/564-add-groupdata-fields-to-onwillshowoverlays-event
feat: enhance onWillShowOverlay event
2024-04-14 15:37:37 +01:00
mathuo
baef193d78
feat: enhance onWillShowOverlay event 2024-04-14 15:24:27 +01:00
mathuo
61f3c252d4
Merge branch 'master' of https://github.com/mathuo/dockview into 538-interested-in-porting-dockview-to-vuejs 2024-03-27 21:32:22 +00:00
mathuo
b0e4c6d926
feat: multiple framework support work 2024-03-27 21:32:05 +00:00
mathuo
eb7d6b87d6
Merge pull request #559 from mathuo/531-fixtypo-onlywhenvisibile-onlywhenvisible
531 fixtypo onlywhenvisibile onlywhenvisible
2024-03-27 21:31:35 +00:00
mathuo
78a5534bab
Merge branch 'master' of https://github.com/madcodelife/dockview into 531-fixtypo-onlywhenvisibile-onlywhenvisible 2024-03-27 21:26:37 +00:00
mathuo
f79b7296e6
Merge branch 'master' of https://github.com/mathuo/dockview into 538-interested-in-porting-dockview-to-vuejs 2024-03-17 14:25:19 +00:00
mathuo
deb59eb94a
chore(release): publish v1.11.0 2024-03-17 14:23:08 +00:00
mathuo
331be77b08
chore: release notes 1.11.0 2024-03-17 14:22:51 +00:00
mathuo
b09ab48cd8
Merge pull request #556 from mathuo/555-import-react-vs-import-as-react
chore: adjust react import
2024-03-16 21:28:36 +00:00
mathuo
61eaae30c8
chore: adjust react import 2024-03-16 21:18:12 +00:00
mathuo
362cce88eb
Merge branch 'master' of https://github.com/mathuo/dockview into 538-interested-in-porting-dockview-to-vuejs 2024-03-15 20:47:49 +00:00
mathuo
09edbddf72
Merge pull request #553 from mathuo/552-css-should-only-be-in-dockview-core-package
chore: css exported only from core package
2024-03-15 20:36:18 +00:00
mathuo
4e54915a93
chore(release): publish v1.10.2 2024-03-15 20:26:50 +00:00
mathuo
4a9a791047
chore: css exported only from core package 2024-03-13 23:13:57 +00:00
mathuo
db747f1ead
feat: framework support 2024-03-11 22:00:02 +00:00
mathuo
e147255fcd
Merge branch '538-interested-in-porting-dockview-to-vuejs' of https://github.com/mathuo/dockview into 538-interested-in-porting-dockview-to-vuejs 2024-03-11 21:56:27 +00:00
mathuo
0b459800cc
Merge branch 'master' of https://github.com/mathuo/dockview into 538-interested-in-porting-dockview-to-vuejs 2024-03-11 21:55:44 +00:00
mathuo
c5770d4381
feat: Vue 3 Support 2024-03-11 21:54:30 +00:00
mathuo
ddcb42fe53
chore: update api docs 2024-03-11 21:37:38 +00:00
mathuo
5bd1f1e1c6
Merge branch 'master' of https://github.com/mathuo/dockview 2024-03-11 21:35:58 +00:00
mathuo
ba0b5f3985
chore: v1.10.2 docs 2024-03-11 21:35:52 +00:00
mathuo
451a8579d9
Merge pull request #549 from mathuo/542-access-panel-contentcomponent-via-the-panel-api
feat: expose component string
2024-03-11 21:18:50 +00:00
mathuo
da6704b517
Merge pull request #548 from mathuo/504-bug-updating-panel-parameters-does-not-trigger-ondidlayoutchange
504 bug updating panel parameters does not trigger ondidlayoutchange
2024-03-11 21:15:53 +00:00
mathuo
68f0319e1b
feat: expose component string 2024-03-11 21:12:00 +00:00
mathuo
c55c3e4a2f
feat: title and parameter events 2024-03-11 20:49:01 +00:00
mathuo
f93e5b613e
tmp 2024-03-11 20:03:29 +00:00
mathuo
1c33ee46a2
Merge pull request #530 from MichailShcherbakov/master
fix(panels): improve the reactivity of panel parameters and titles
2024-03-11 20:02:46 +00:00
mathuo
258be8594d
Merge branch '504-bug-updating-panel-parameters-does-not-trigger-ondidlayoutchange' into master 2024-03-11 20:02:08 +00:00
mathuo
b25264e190
feat: Vue 3 Support 2024-03-08 21:41:48 +00:00
mathuo
45919ff397
chore(release): publish v1.10.1 2024-03-02 22:31:11 +00:00
mathuo
c584f24a02
chore: docs 2024-03-02 22:23:34 +00:00
mathuo
9a9dc3500e
chore: docs 2024-03-02 22:13:25 +00:00
mathuo
0634f4fe52
chore: docs (#527)
* chore: docs
2024-03-02 21:49:09 +00:00
mathuo
f00b3d88e1
Merge pull request #535 from mathuo/534-setvisible-is-missing-from-splitviewpanelapiimpl
feat: cleanup setVisible api
2024-03-02 20:49:14 +00:00
mathuo
d3b22d83cf
feat: cleanup setVisible api 2024-03-02 16:24:24 +00:00
mathuo
2ee9b46eb9
Merge pull request #533 from mathuo/imgbot
[ImgBot] Optimize images
2024-02-29 22:05:06 +00:00
ImgBotApp
2f1f35bd31
[ImgBot] Optimize images
*Total -- 857.56kb -> 678.27kb (20.91%)

/packages/docs/src/misc/math/visual_1.jpg -- 34.74kb -> 25.91kb (25.42%)
/packages/docs/src/misc/math/constraints.jpg -- 134.20kb -> 103.55kb (22.84%)
/packages/docs/static/img/splashscreen.gif -- 654.69kb -> 515.26kb (21.3%)
/packages/docs/static/img/dockview_grid.svg -- 2.75kb -> 2.68kb (2.73%)
/packages/docs/static/img/dockview_splash_2.svg -- 3.59kb -> 3.50kb (2.67%)
/packages/docs/static/img/dockview_grid_2.svg -- 3.57kb -> 3.49kb (2.46%)
/packages/docs/static/img/add_to_empty_space.svg -- 1.62kb -> 1.58kb (2.36%)
/packages/docs/static/img/float_add.svg -- 4.58kb -> 4.54kb (0.77%)
/packages/docs/static/img/float_group.svg -- 17.81kb -> 17.77kb (0.24%)

Signed-off-by: ImgBotApp <ImgBotHelp@gmail.com>
2024-02-29 20:35:03 +00:00
Sherbakov Mikhail
465141c097
fix(panels): improve the reactivity of panel parameters and titles 2024-02-27 19:57:31 +03:00
Floyd Wang
0d34d7285e fix(typo): onlyWhenVisibile -> onlyWhenVisible 2024-02-27 19:29:54 +08:00
mathuo
9ee00ab423
Merge pull request #526 from mathuo/525-onwillshowoverlay-to-handle-edge-drops
handle edge drops for onWillShowOverlay
2024-02-25 16:55:57 +00:00
mathuo
12c873c7cf
replace DockviewDropTragets with DockviewGroupDropLocation 2024-02-25 16:12:49 +00:00
mathuo
5a635336b3
handle edge drops for onWillShowOverlay 2024-02-25 16:09:48 +00:00
mathuo
60f49ce449
chore: docs 2024-02-25 16:08:26 +00:00
mathuo
50608f4520
chore: update 1.10.0 release notes date 2024-02-25 15:54:38 +00:00
mathuo
566fc0a7c8
chore(release): publish v1.10.0 2024-02-25 15:44:12 +00:00
mathuo
d2baa1371c
Merge pull request #524 from mathuo/475-improved-docs-1
chore: fix docs
2024-02-25 15:25:52 +00:00
mathuo
814a8e4dae
chore: fix docs 2024-02-25 15:25:21 +00:00
mathuo
e85863b65f
475 improved docs (#484)
* chore: docs
2024-02-25 12:32:58 +00:00
mathuo
cc50199cff
Merge pull request #522 from mathuo/395-showdndoverlay-is-not-called-always-2
feat: simplify event
2024-02-24 21:30:44 +00:00
mathuo
8533a18fea
feat: simplify event 2024-02-24 21:19:17 +00:00
mathuo
fd2460416a
Merge pull request #518 from mathuo/479-is-there-any-way-to-focus-the-panel-content
feat: events
2024-02-19 20:57:42 +00:00
mathuo
889e4d200c
feat: events 2024-02-19 20:57:15 +00:00
mathuo
14b7e8de80
Merge pull request #517 from mathuo/479-is-there-any-way-to-focus-the-panel-content
479 is there any way to focus the panel content
2024-02-19 20:55:31 +00:00
mathuo
5fddff72e7
Merge branch '479-is-there-any-way-to-focus-the-panel-content' of https://github.com/mathuo/dockview into 479-is-there-any-way-to-focus-the-panel-content 2024-02-19 20:51:57 +00:00
mathuo
775145f176
feat: events 2024-02-19 20:51:50 +00:00
mathuo
5418538874
Merge pull request #514 from mathuo/509-source-map-parsing-fails-when-used-in-create-react-app-typescript-project
chore: remove source maps
2024-02-19 20:46:20 +00:00
mathuo
05ff795188
Merge pull request #516 from mathuo/447-feature-request-adding-a-gap-around-panels
feat: correct contain size
2024-02-19 20:45:58 +00:00
mathuo
5c945e97d6
feat: correct contain size 2024-02-19 20:20:24 +00:00
mathuo
68d36612dc
chore: remove source maps 2024-02-18 09:29:25 +00:00
mathuo
70014a8c10
Merge pull request #513 from mathuo/512-expose-close-on-group-api
feat: group.api.close
2024-02-16 22:51:02 +00:00
mathuo
bb40c45a29
Merge pull request #511 from mathuo/448-drop-target-selection-transformation-scales-borders-and-outlines
feat: dnd overlay fix
2024-02-16 22:50:53 +00:00
mathuo
a84bdb9182
Merge pull request #510 from mathuo/479-is-there-any-way-to-focus-the-panel-content
feat: fix rendering
2024-02-16 22:49:01 +00:00
mathuo
d379b111ee
feat: group.api.close 2024-02-16 22:45:49 +00:00
mathuo
157ea8a3d1
feat: dnd overlay fix 2024-02-16 22:44:39 +00:00
mathuo
9523e6fb48
feat: fix rendering 2024-02-16 22:43:46 +00:00
mathuo
7b0cc492e7
Merge pull request #508 from mathuo/479-is-there-any-way-to-focus-the-panel-content
feat: fixes
2024-02-13 20:31:19 +00:00
mathuo
ed40e224e7
feat: fixes 2024-02-13 20:24:56 +00:00
mathuo
53de69a61a
Merge pull request #502 from mathuo/501-ensure-group-is-active-after-being-maximized
bug: maximized group must be active
2024-02-09 21:09:14 +00:00
mathuo
6b2ed70a7c
bug: maximized group must be active 2024-02-09 21:02:39 +00:00
mathuo
de93234632
Merge pull request #499 from mathuo/498-dockview-does-not-support-reactmemo-for-components
feat: accept a wider range of React components
2024-02-09 20:28:08 +00:00
mathuo
024c2d5349
Merge pull request #500 from mathuo/495-api-ondidmaximizedgroupchange-misspelled-as-ondidmaxmizedgroupchange
chore: fix typos
2024-02-09 20:28:00 +00:00
mathuo
e7ab35a30e
chore: fix typos 2024-02-09 20:21:45 +00:00
mathuo
874da1c7d9
feat: accept a wider range of React components 2024-02-09 20:19:55 +00:00
mathuo
30c7fa2c6a
Merge pull request #497 from mathuo/479-is-there-any-way-to-focus-the-panel-content
feat: events
2024-02-08 21:35:30 +00:00
mathuo
d2b9493fb4
feat: events 2024-02-08 21:24:13 +00:00
mathuo
8d56a2ec3a
Merge pull request #482 from mathuo/479-is-there-any-way-to-focus-the-panel-content
feat: align focus/active methods
2024-02-08 20:18:56 +00:00
mathuo
284fb1440b
feat: events cleanup 2024-02-08 19:38:52 +00:00
mathuo
807ccf80de
feat: events cleanup 2024-02-07 21:55:57 +00:00
mathuo
89fe866ac5
Merge branch 'master' of https://github.com/mathuo/dockview into 479-is-there-any-way-to-focus-the-panel-content 2024-02-03 14:02:21 +00:00
mathuo
cb69d47926
Merge pull request #490 from mathuo/469-add-window-lifecycle-callbacks-1
feat: popout persistance logic
2024-02-03 13:49:59 +00:00
mathuo
9e57a8691a
feat: popout persistance logic 2024-02-01 19:51:07 +00:00
mathuo
f7b173f7df
Merge pull request #488 from mathuo/469-add-window-lifecycle-callbacks-1
feat: fix popout group persistance
2024-01-31 21:44:54 +00:00
mathuo
c4f46a190a
feat: fix popout group persistance 2024-01-31 21:39:16 +00:00
mathuo
d488e8c3d9
Merge pull request #461 from mathuo/460-locked-mode-prevent-all-mouse-resizing
feat: locked mode
2024-01-30 19:58:31 +00:00
mathuo
c70327e268
Merge pull request #485 from mathuo/448-drop-target-selection-transformation-scales-borders-and-outlines
feat: replace transform with top,left,width,height
2024-01-30 19:58:20 +00:00
mathuo
d8cb5ac3f8
Merge branch 'master' of https://github.com/mathuo/dockview 2024-01-30 19:57:58 +00:00
mathuo
9b641f64be
chore: migrate to codeql v3 2024-01-30 19:57:46 +00:00
mathuo
aeccce639c
chore: migrate to v4 build actions 2024-01-30 19:56:40 +00:00
mathuo
1d7ab22027
Merge branch 'master' of https://github.com/mathuo/dockview into 460-locked-mode-prevent-all-mouse-resizing 2024-01-30 19:51:56 +00:00
mathuo
0b1a09d910
feat: replace transform with top,left,width,height 2024-01-30 19:50:40 +00:00
mathuo
5fc8a6a4d3
Merge pull request #487 from mathuo/469-add-window-lifecycle-callbacks-1
feat: popout group enhancements
2024-01-30 19:45:19 +00:00
mathuo
66d96cf6ae
chore: upgrade builds to node v20 2024-01-30 19:43:27 +00:00
mathuo
926b688267
chore: stop nightly docs job 2024-01-30 19:41:05 +00:00
mathuo
0bca63b550
feat: popout group enhancements 2024-01-30 17:41:04 +00:00
mathuo
c2791c6124
Merge pull request #453 from mathuo/395-showdndoverlay-is-not-called-always
work-in-progress
2024-01-29 22:42:22 +00:00
mathuo
e1849f72a5
chore: internals renaming 2024-01-29 22:40:43 +00:00
mathuo
fb6aba1d7f
Merge branch 'master' of https://github.com/mathuo/dockview into 395-showdndoverlay-is-not-called-always 2024-01-29 22:29:21 +00:00
mathuo
e28c76626f
Merge branch 'master' of https://github.com/mathuo/dockview into 460-locked-mode-prevent-all-mouse-resizing 2024-01-29 22:28:42 +00:00
mathuo
aa8e7e09e0
Merge pull request #481 from mathuo/469-add-window-lifecycle-callbacks-1
feat: provide means to obtain popoutWindow document
2024-01-29 22:27:45 +00:00
mathuo
47b691b6b4
Merge pull request #454 from mathuo/447-feature-request-adding-a-gap-around-panels
work-in-progress: group gaps
2024-01-29 22:22:28 +00:00
mathuo
20c1a66d20
feat: popout group enhancements 2024-01-29 22:21:52 +00:00
mathuo
8f9d225c61
feat: window popout enhancements 2024-01-29 20:57:37 +00:00
mathuo
0127857544
feat: group gaps 2024-01-28 13:57:13 +00:00
mathuo
6274708acb
feat: align event names 2024-01-28 13:43:09 +00:00
mathuo
a8472e8b71
Merge branch '469-add-window-lifecycle-callbacks' of https://github.com/mathuo/dockview into 469-add-window-lifecycle-callbacks-1 2024-01-28 13:38:02 +00:00
mathuo
586400019f
feat: align focus/active methods 2024-01-27 20:26:00 +00:00
mathuo
0fd3a669c7
test 2024-01-27 19:21:09 +00:00
mathuo
a24dd21ca2
feat: provide means to obtain popoutWindow document 2024-01-27 14:21:56 +00:00
mathuo
b901f4de0c
Merge pull request #477 from mathuo/madcodelife-master
chore: typos
2024-01-23 19:43:45 +00:00
mathuo
c7eb2dc105
Merge branch 'master' of https://github.com/madcodelife/dockview into madcodelife-master 2024-01-23 18:47:45 +00:00
mathuo
c11d65bef7
chore(release): publish v1.9.2 2024-01-23 17:37:01 +00:00
mathuo
f4866c9f89
chore: docs 2024-01-23 17:36:51 +00:00
mathuo
e9cf1bfd9f
chore: 1.9.2 docs 2024-01-23 17:33:53 +00:00
mathuo
e47ccdea6a
Merge pull request #474 from mathuo/472-panel-loses-content
bug: fix rendering issue
2024-01-23 17:31:26 +00:00
mathuo
a855c55132
bug: fix rendering issue 2024-01-23 17:25:06 +00:00
Floyd Wang
8f24d6b366 fix: typo 2024-01-23 19:21:17 +08:00
mathuo
75066f2420
Merge pull request #468 from mathuo/465-adding-group-doesnt-allow-for-group-creation-options
465 adding group doesnt allow for group creation options
2024-01-22 22:34:53 +00:00
mathuo
1cc340f3f1
Merge pull request #470 from sachnk/469-add-window-lifecycle-callbacks
Add window-lifecycle callbacks
2024-01-22 20:12:37 +00:00
sachnk
23b1edb003
add window-lifecycle callbacks 2024-01-22 19:02:53 +00:00
mathuo
87e52f88d0
Merge pull request #466 from NaNgets/465-add-group-with-options
Add group with options.
2024-01-22 18:48:58 +00:00
NaNgets
6499e78544
Fix dockview component interface addGroup. 2024-01-21 22:52:44 +02:00
NaNgets
02af66a10f
PR comments. 2024-01-21 22:51:19 +02:00
NaNgets
a6a6ffc058
Fix indentation. 2024-01-21 15:02:45 +02:00
NaNgets
03a39507dc
Add group with options. 2024-01-21 15:00:35 +02:00
mathuo
502a984d2b
chore(release): publish v1.9.1 2024-01-20 15:05:40 +00:00
mathuo
1762389406
Merge pull request #462 from mathuo/432-dockview-191-iteration-plan
chore: 1.9.1 docs
2024-01-20 13:54:15 +00:00
mathuo
87b999fe46
chore: 1.9.1 docs 2024-01-20 13:51:31 +00:00
mathuo
b0a5e66cff
Merge pull request #464 from mathuo/451-provide-drop-target-dropzone-quadrant-class
feat: rename class
2024-01-20 10:02:37 +00:00
mathuo
16e0971275
feat: rename class 2024-01-20 10:02:18 +00:00
mathuo
cae8f3664e
Merge pull request #463 from mathuo/451-provide-drop-target-dropzone-quadrant-class
feat: drop target classnames
2024-01-19 15:16:42 +00:00
mathuo
9ccc7add41
feat: drop target classnames 2024-01-19 15:16:14 +00:00
mathuo
22ba48e81e
feat: locked mode 2024-01-19 14:23:52 +00:00
mathuo
6a1f47d4da
feat: expose onWillDrop 2024-01-19 13:35:46 +00:00
mathuo
8da26f1484
Merge branch 'master' of https://github.com/mathuo/dockview into 395-showdndoverlay-is-not-called-always 2024-01-18 19:33:07 +00:00
mathuo
512a8d2c72
feat: dnd control changes 2024-01-18 19:32:48 +00:00
mathuo
6c670c1fbb
Merge pull request #431 from mathuo/430-support-droptarget-size-options
feat: expose dockview root droptarget overlay options (work-in-progress)
2024-01-18 19:32:27 +00:00
mathuo
cc88096413
feat: expose dockview root droptarget overlay options 2024-01-18 16:08:38 +00:00
mathuo
e5334f0fd7
Merge pull request #458 from mathuo/455-floating-groups-lose-size-if-instance-toggled-with-display-none
feat: short-circuit resize calls when display:none
2024-01-18 16:02:30 +00:00
mathuo
a6bafcc063
feat: short-circuit resize calls when display:none 2024-01-18 15:30:26 +00:00
mathuo
c61cb1a6e8
Merge pull request #449 from mathuo/446-content-container-does-not-scroll
feat: scrollbar as default
2024-01-17 22:54:51 +00:00
mathuo
c49fcd4d9d
Merge pull request #452 from mathuo/451-provide-drop-target-dropzone-quadrant-class
feat: provide classnames for droptarget overlays
2024-01-17 22:43:50 +00:00
mathuo
e3e87f4133
feat: provide classnames for droptarget overlays 2024-01-17 22:19:43 +00:00
mathuo
0df4062de4
feat: scrollbar as default 2024-01-17 19:57:24 +00:00
mathuo
8a67f60747
chore(release): publish v1.9.0 2024-01-15 20:24:39 +00:00
mathuo
90690fa8ea
Revert "chore: 1.9.0"
This reverts commit 9e245e6f5e.
2024-01-15 20:20:05 +00:00
mathuo
9e245e6f5e
chore: 1.9.0 2024-01-15 20:11:40 +00:00
mathuo
ffddc95602
chore: update docs (#429)
* chore: 1.9.0 docs
2024-01-15 20:03:20 +00:00
mathuo
5ca1cc5e62
Merge pull request #442 from mathuo/360-investigate-opening-tabs-in-new-browser-window
feat: update watermark for popout windows
2024-01-11 15:21:43 +00:00
mathuo
9c44a08a31
feat: update watermark for popout windows 2024-01-11 15:21:26 +00:00
mathuo
1d9b285bf4
Merge pull request #441 from mathuo/397-gready-rendering-mode
bug: destroy overlay render when detached
2024-01-11 11:33:30 +00:00
mathuo
31596772a7
test: render overlay container 2024-01-11 11:26:49 +00:00
mathuo
0380b4fda0
bug: destroy overlay render when detached 2024-01-11 11:03:41 +00:00
mathuo
c2ae86de3a
Merge pull request #439 from mathuo/397-gready-rendering-mode
feat: render mode
2024-01-10 23:14:13 +00:00
mathuo
718e3344ca
feat: render mode 2024-01-10 23:08:44 +00:00
mathuo
ccef43cb82
Merge branch 'master' of https://github.com/mathuo/dockview into 397-gready-rendering-mode 2024-01-10 22:34:10 +00:00
mathuo
d0d6508ae3
feat: render mode 2024-01-10 22:23:35 +00:00
mathuo
b084ac6e00
Merge pull request #438 from mathuo/360-investigate-opening-tabs-in-new-browser-window
feat: popout window unique id
2024-01-10 20:01:25 +00:00
mathuo
dbe0fe88ad
feat: popout window unique id 2024-01-10 20:00:50 +00:00
mathuo
3ec3c8358a
Merge pull request #437 from mathuo/360-investigate-opening-tabs-in-new-browser-window
feat: popout window position account for window.screen position
2024-01-10 15:42:57 +00:00
mathuo
312aeded25
feat: popout window position account for window.screen position 2024-01-10 15:42:27 +00:00
mathuo
16a0bc5b3e
Merge pull request #436 from mathuo/361-full-screen-mode-for-a-single-tab
test: maximize view cleanup
2024-01-10 13:33:03 +00:00
mathuo
c7d7749308
test: maximize view cleanup 2024-01-10 13:31:45 +00:00
mathuo
8ca80b542d
Merge pull request #435 from mathuo/397-gready-rendering-mode
chore: remove unused code
2024-01-10 13:18:39 +00:00
mathuo
e686ecb9d5
chore: remove unused code 2024-01-10 13:18:22 +00:00
mathuo
0b67d8e50b
Merge pull request #434 from mathuo/361-full-screen-mode-for-a-single-tab
feat: do not persist maximized view state
2024-01-10 13:10:13 +00:00
mathuo
da269aa71b
feat: do not persist maximized view state 2024-01-10 13:09:48 +00:00
mathuo
4c9caadcf5
Merge pull request #433 from mathuo/361-full-screen-mode-for-a-single-tab
feat: set minimum panel size > 0
2024-01-10 11:04:10 +00:00
mathuo
3df1642d91
feat: set minimum panel size > 0 2024-01-10 11:00:07 +00:00
mathuo
2c77b7e208
chore: fix demo 2024-01-10 09:49:16 +00:00
mathuo
64076b2bdd
Merge pull request #426 from mathuo/425-dockview-inside-shadowdom
bug: resizable should work within shadow dom
2024-01-09 21:49:51 +00:00
mathuo
5e45b9a469
bug: resizable should work within shadow dom 2024-01-09 21:42:04 +00:00
mathuo
b78a7a6207
Merge pull request #422 from mathuo/360-investigate-opening-tabs-in-new-browser-window
test: add tests
2024-01-08 22:03:44 +00:00
mathuo
105be3661f
feat: popout groups 2024-01-08 21:54:33 +00:00
mathuo
aa6eb27d7d
test: add tests 2024-01-07 16:18:07 +00:00
mathuo
22d5067395
chore: docs 2024-01-05 16:12:01 +00:00
mathuo
32d668f69d
chore: docs 2024-01-05 15:39:20 +00:00
mathuo
4b616c5578
Merge pull request #421 from mathuo/397-gready-rendering-mode
feat: gready rendering
2024-01-04 19:53:32 +00:00
mathuo
10256672b4
test: add tests 2024-01-03 20:29:58 +00:00
mathuo
43548618ba
Merge branch 'master' of https://github.com/mathuo/dockview into 397-gready-rendering-mode 2024-01-03 19:08:37 +00:00
mathuo
9b1c366ce5
feat: gready rendering 2024-01-03 16:25:35 +00:00
mathuo
5a2d7394be
Merge pull request #419 from mathuo/361-full-screen-mode-for-a-single-tab
test: gridview tests
2024-01-03 13:56:47 +00:00
mathuo
b222de86f7
feat: enhance maximize group api methods 2024-01-03 13:51:43 +00:00
mathuo
3e9f96bdbf
test: gridview tests 2024-01-03 13:09:55 +00:00
mathuo
4045689bd0
chore: fix sonar issues 2024-01-02 15:22:55 +00:00
mathuo
ecf12b175e
chore: allow manual docs build 2024-01-02 15:02:42 +00:00
mathuo
740ded45f4
Merge pull request #362 from mathuo/361-full-screen-mode-for-a-single-tab
wip: experiment with fullscreen tabs
2024-01-02 15:00:19 +00:00
mathuo
bb1a7934c0
Merge pull request #418 from mathuo/417-upgrade-docasaurus
chore: upgrade deps
2024-01-02 14:49:43 +00:00
mathuo
ea51b5c883
chore: upgrade deps 2024-01-02 14:43:32 +00:00
mathuo
5ec847ec77
chore: fix docs build 2024-01-02 14:28:32 +00:00
mathuo
a18b95f9ad
feat: full-screen-groups 2024-01-01 22:49:23 +00:00
mathuo
cb203bdf1e
Merge branch 'master' of https://github.com/mathuo/dockview into 361-full-screen-mode-for-a-single-tab 2024-01-01 22:47:08 +00:00
mathuo
cf6ee14f3d
Merge pull request #416 from mathuo/397-gready-rendering-mode
bug: fix title renderer
2024-01-01 22:46:56 +00:00
mathuo
6a620d4088
bug: fix title renderer 2024-01-01 22:46:15 +00:00
mathuo
bd2d8d7bf6
feat: maximized groups 2024-01-01 22:33:34 +00:00
mathuo
c195fa19bf
Merge branch 'master' of https://github.com/mathuo/dockview into 361-full-screen-mode-for-a-single-tab 2024-01-01 22:30:21 +00:00
mathuo
eb0172f06c
Merge pull request #364 from mathuo/360-investigate-opening-tabs-in-new-browser-window
work-in-progress: popout windows
2024-01-01 22:28:00 +00:00
mathuo
fa25c55655
Merge pull request #415 from mathuo/414-css-styles-for-focused-tab
feat: indicate focused tab with css style
2024-01-01 21:45:27 +00:00
mathuo
406af8a87f
feat: popout windows 2024-01-01 21:43:07 +00:00
mathuo
ff6d40a545
feat: indicate focused tab with css style 2024-01-01 21:40:53 +00:00
mathuo
ca12d7d920
Merge branch 'master' of https://github.com/mathuo/dockview into 361-full-screen-mode-for-a-single-tab 2023-12-26 21:59:12 +00:00
mathuo
73cd0dba4e
feat: fullscreen panels 2023-12-26 21:56:33 +00:00
mathuo
584795b099
Merge branch 'master' of https://github.com/mathuo/dockview into 360-investigate-opening-tabs-in-new-browser-window 2023-12-26 20:23:29 +00:00
mathuo
343d42cb86
Merge pull request #409 from mathuo/397-gready-rendering-mode
feat: rename rendering modes
2023-12-26 20:22:32 +00:00
mathuo
36dd190ddb
feat: rename rendering modes 2023-12-26 20:14:57 +00:00
mathuo
f7fc6235e5
Merge branch 'master' of https://github.com/mathuo/dockview into 360-investigate-opening-tabs-in-new-browser-window 2023-12-26 20:06:44 +00:00
mathuo
5799549901
feat: popout windows 2023-12-26 19:58:21 +00:00
mathuo
450e37f973
Merge pull request #398 from mathuo/397-gready-rendering-mode
feat: gready render mode
2023-12-26 19:57:46 +00:00
mathuo
a2a4e68166
feat: gready render mode 2023-12-25 21:39:46 +00:00
mathuo
ef70ea236d
Merge pull request #392 from cemalgnlts/patch-1
Remove the hover effect for inactive sash classes.
2023-11-23 22:27:17 +00:00
Cemal Gönültaş
de88179b26
Remove the hover effect for inactive sash classes. 2023-11-16 16:48:00 +03:00
mathuo
b17aa24637
chore: rename action 2023-10-29 13:22:11 +00:00
mathuo
a1b3a94c42
chore(release): publish v1.8.5 2023-10-29 13:09:21 +00:00
mathuo
8df1de888a
chore: v1.8.5 release notes 2023-10-29 13:05:58 +00:00
mathuo
53c0a39d7a
Merge pull request #381 from mathuo/380-complete-set-of-events
feat: events system
2023-10-29 13:02:08 +00:00
mathuo
3c747aa4a7
feat: events system 2023-10-22 20:01:55 +01:00
mathuo
8aa0d0192e
Merge pull request #379 from mathuo/373-fix-sonar-issues
chore: fix sonar issues
2023-10-22 19:59:33 +01:00
mathuo
331e190bf8
chore: fix sonar issues 2023-10-22 19:12:46 +01:00
mathuo
ed466f758f
Merge pull request #378 from mathuo/371-update-dependencies
chore: update engine to node18
2023-10-22 16:16:23 +01:00
mathuo
7ca2997970
chore: update engine to node18 2023-10-22 16:16:03 +01:00
mathuo
26805d023a
Merge pull request #377 from mathuo/376-disable-autoresizing-flag
bug: fix disableAutoResizing flag
2023-10-22 16:14:41 +01:00
mathuo
126d01ede0
bug: fix disableAutoResizing flag 2023-10-22 16:10:28 +01:00
mathuo
d953cf9e4e
Merge pull request #372 from mathuo/371-update-dependencies
chore: update dependencies
2023-10-22 15:57:44 +01:00
mathuo
9fbb1ee479
Merge pull request #374 from mathuo/373-fix-sonar-issues
chore: fix sonar issues
2023-10-22 15:50:08 +01:00
mathuo
8e6f7bf808
chore: update dependencies 2023-10-22 15:48:28 +01:00
mathuo
882c1353c7
chore: fix sonar issues 2023-10-22 15:40:11 +01:00
mathuo
318cbd6854
Merge pull request #370 from mathuo/366-move-npm-publishing-to-github-actions
366 move npm publishing to GitHub actions
2023-10-22 14:57:56 +01:00
mathuo
329ed77115
chore: configure publish action 2023-10-22 13:44:42 +01:00
mathuo
c104503d62
chore: use node 18 2023-10-22 13:35:35 +01:00
mathuo
c6753f176a
Merge pull request #369 from mathuo/366-move-npm-publishing-to-github-actions
chore: Github Publish Actions
2023-10-22 13:20:09 +01:00
mathuo
dc50d4e2ac
chore: setup npm provenance attestation 2023-10-22 12:15:07 +01:00
mathuo
0f555075ae
chore: Github Publish Actions 2023-10-22 12:01:05 +01:00
mathuo
b4ff626b74
Merge pull request #368 from mathuo/366-move-npm-publishing-to-github-actions
chore: Github Publish Actions
2023-10-22 11:35:04 +01:00
mathuo
eeddad542b
chore: Github Publish Actions 2023-10-22 11:28:42 +01:00
mathuo
b07961df3a
Merge pull request #367 from mathuo/366-move-npm-publishing-to-github-actions
chore: Github Action npm experimental publish
2023-10-22 11:21:26 +01:00
mathuo
d4d79b220f
chore: Github Action npm experimental publish 2023-10-22 11:14:30 +01:00
mathuo
e3ed4251ed
chore: revert 2023-10-09 20:48:42 +01:00
mathuo
58e9f9b355
chore: improve docs 2023-10-09 20:29:57 +01:00
mathuo
47f78ad649
chore(release): publish v1.8.4 2023-10-06 20:14:56 +01:00
mathuo
a3b20deee9
chore: v1.8.4 docs 2023-10-06 20:05:16 +01:00
mathuo
3803bfa13a
Merge pull request #353 from mathuo/352-documentation-improvements
352 documentation improvements
2023-10-06 20:02:52 +01:00
mathuo
03235172a8
chore: docs 2023-10-06 19:56:42 +01:00
mathuo
859723a890
Merge pull request #359 from mathuo/358-splitview-separator-style-on-fromjson
fix: apply splitview styles on deserialize
2023-10-04 21:08:12 +01:00
mathuo
b5c3bcc86a
fix: apply splitview styles on deserialize 2023-10-04 21:00:17 +01:00
mathuo
e726b4ab02
Merge branch 'master' of https://github.com/mathuo/dockview into 352-documentation-improvements 2023-10-04 20:11:26 +01:00
mathuo
1661ff77d2
Merge pull request #357 from mathuo/356-nested-gridview-bug
bug: fix incorrect view disposal
2023-10-03 22:09:07 +01:00
mathuo
4300b1f89c
bug: remove views from branchnode before .dispose 2023-10-03 21:47:42 +01:00
mathuo
42a4d50c47
Merge branch 'master' of https://github.com/mathuo/dockview into 352-documentation-improvements 2023-10-03 20:02:47 +01:00
mathuo
76c3fb6fa0
Merge pull request #355 from mathuo/341-dockview-stuck-in-broken-state-after-apifromjson-fails-due-to-invalid-component-name
feat: fromJSON error handling and cleanup
2023-10-03 20:02:03 +01:00
mathuo
0ee10912a2
feat: fromJSON error handling and cleanup 2023-10-03 19:50:46 +01:00
mathuo
82b83e7ed3
chore: docs 2023-10-02 19:42:46 +01:00
mathuo
46bceea217
Merge branch '352-documentation-improvements' of https://github.com/mathuo/dockview into 352-documentation-improvements 2023-10-02 19:36:26 +01:00
mathuo
5a3f0b1d4a
Merge branch 'master' of https://github.com/mathuo/dockview into 352-documentation-improvements 2023-10-01 22:26:07 +01:00
mathuo
faeb8241a5
Merge pull request #351 from mathuo/350-provide-examples-of-complex-scenarios
chore: provide additional examples
2023-10-01 22:25:06 +01:00
mathuo
e71fd7b153
chore: auto-gen type docs 2023-10-01 21:55:15 +01:00
mathuo
5af4aa2da9
chore: auto-gen type docs 2023-10-01 21:53:59 +01:00
mathuo
4ee0617014
Merge branch 'master' into 350-provide-examples-of-complex-scenarios 2023-10-01 21:50:23 +01:00
mathuo
717247bbec
Merge pull request #348 from mathuo/347-move-between-tabs
chore: navigation examples
2023-10-01 20:46:22 +01:00
mathuo
2337373a6f
Merge pull request #340 from mathuo/338-options-before-tabs-start
feat: pre-tab actions
2023-10-01 20:45:40 +01:00
mathuo
a96400d970
Merge pull request #346 from mathuo/344-floating-tab-groups-move-in-bested-dockview
bug: skip resize for unmounted elements
2023-10-01 20:45:31 +01:00
mathuo
9006fb9917
Merge pull request #342 from mathuo/341-dockview-stuck-in-broken-state-after-apifromjson-fails-due-to-invalid-component-name
bug: unable to recover from loading a corrupted layout
2023-10-01 20:45:22 +01:00
mathuo
fdb148bc85
chore: update dependencies 2023-10-01 12:07:48 +01:00
mathuo
bd1a8f1d44
feat: prefix header actions 2023-09-30 12:08:45 +01:00
mathuo
fc1c747bed
test: add tests 2023-09-30 11:47:36 +01:00
mathuo
4c142b9632
chore: update examples 2023-09-30 11:31:01 +01:00
mathuo
08ec3fd3a5
feat: ensure view priority used for viewChange events 2023-09-30 11:29:55 +01:00
mathuo
206255b411
chore: provide additional examples 2023-09-30 11:23:51 +01:00
mathuo
ffbcaa6259
Merge pull request #336 from mathuo/335-actions-in-paneview
chore: sandbox paneview examples
2023-09-30 10:27:51 +01:00
mathuo
a15e895337
chore: navigation examples 2023-09-29 21:31:48 +01:00
mathuo
19595f3b12
bug: skip resize for unmounted elements 2023-09-29 20:55:14 +01:00
mathuo
1ccd75b2b3
bug: unable to recover from loading a corrupted layout 2023-09-28 21:39:24 +01:00
mathuo
4d1952387c
chore: sandbox paneview examples 2023-09-19 21:26:46 +01:00
mathuo
4ad5b0ffe4
chore(release): publish v1.8.3 2023-09-17 14:16:37 +01:00
mathuo
739976ea28
chore: v1.8.3 docs 2023-09-16 21:13:35 +01:00
mathuo
3ea9f21e90
chore: v1.8.3 docs 2023-09-16 21:13:08 +01:00
mathuo
bac862a5fc
Merge pull request #327 from mathuo/326-possible-to-stop-floating-windows-being-dragged-outside-visible-dockview-area
feat: floating group viewport rules
2023-09-12 22:35:59 +01:00
mathuo
78e0b89a78
feat: fix sonar issues 2023-09-12 22:26:26 +01:00
mathuo
16a49c7b27
Merge branch 'master' of https://github.com/mathuo/dockview into 326-possible-to-stop-floating-windows-being-dragged-outside-visible-dockview-area 2023-09-09 22:18:24 +01:00
mathuo
292e25935f
feat: floating group overlay rules 2023-09-04 20:10:52 +01:00
mathuo
0b39e84f86
Merge pull request #322 from mathuo/299-access-to-datatransfer-object-on-drag-events
feat: expose dragstart event on custom handlers
2023-09-04 19:43:36 +01:00
mathuo
a1cd01380b
chore: tests and docs 2023-09-04 19:32:42 +01:00
mathuo
f6cfb4418c
Merge branch 'master' of https://github.com/mathuo/dockview into 326-possible-to-stop-floating-windows-being-dragged-outside-visible-dockview-area 2023-09-03 16:26:41 +01:00
mathuo
65a7da6a36
Merge pull request #334 from mathuo/321-add-hideclose-to-dockviewdefaulttab-component
feat: override close option
2023-09-03 16:25:12 +01:00
mathuo
4aa707132f
feat: override close option 2023-09-03 16:01:13 +01:00
mathuo
63ca9053a5
Merge pull request #331 from mathuo/330-preventdefault-on-dockviewdefaulttab-close-btn
bug: preventDefault on close btn mouseDown
2023-08-29 21:59:40 +01:00
mathuo
bfa4f60288
feat : drag intercept examples 2023-08-29 20:22:23 +01:00
mathuo
493f843987
Merge pull request #328 from mathuo/321-add-hideclose-to-dockviewdefaulttab-component
docs: add note
2023-08-29 20:10:01 +01:00
mathuo
e64d96cef7
bug: preventDefault on close btn mouseDown 2023-08-29 20:09:43 +01:00
mathuo
3832222fef
Merge pull request #329 from mathuo/316-locked-group-drop-targets
tests: test locked behaviours
2023-08-28 20:18:35 +01:00
mathuo
007b2a8fea
tests: test locked behaviours 2023-08-28 20:04:19 +01:00
mathuo
2ce175dbf3
docs: add note 2023-08-27 21:59:53 +01:00
mathuo
6c2d511827
Merge branch 'master' of https://github.com/mathuo/dockview into 299-access-to-datatransfer-object-on-drag-events 2023-08-27 21:51:31 +01:00
mathuo
715281b804
feat: floating group viewport rules 2023-08-27 21:50:23 +01:00
mathuo
a1b2b9b1da
Merge pull request #323 from mathuo/321-add-hideclose-to-dockviewdefaulttab-component
feat: hideClose on DockviewDefaultTab
2023-08-26 12:54:15 +01:00
mathuo
5ac2a9ffdb
feat: hideClose on DockviewDefaultTab 2023-08-22 20:32:58 +01:00
mathuo
821c2f5c44
add drag intercept events 2023-08-22 20:17:53 +01:00
mathuo
be0fea7104
Merge pull request #320 from Imbozter/master
Remove supressClosable option from docs
2023-08-19 15:29:28 +01:00
Imbozter
ffc19f891d
Merge pull request #1 from Imbozter/Remove-suppressClosable-option-from-docs
Update dockview.mdx
2023-08-16 23:54:37 +10:00
Imbozter
3ef9f4ed2d
Update dockview.mdx 2023-08-16 23:53:50 +10:00
mathuo
3fb2800db4
Merge pull request #315 from techbech/locked-groups
feat: added the option for 'no-drop-target' for locked on dockview groups
2023-07-30 16:48:37 +01:00
Peter Bech
d577f0238c
Fix wrong quotation sign in docs 2023-07-27 10:28:24 +02:00
Peter Bech
b551d93dac
added lockedgroup-dockview to the codesandbox ci configuration 2023-07-26 22:03:51 +02:00
Peter Bech
55802a7a16
patch: renamed lockedgroup-dockview sandbox package name to match directory name 2023-07-26 21:52:29 +02:00
Peter Bech
17c0f6e575
feat: added the option for 'no-drop-target' for locked on dockview groups 2023-07-26 21:40:13 +02:00
mathuo
7701625b6f
Merge pull request #283 from mathuo/281-type-hints-for-panel-parameters
281 type hints for panel parameters
2023-07-25 22:47:32 +01:00
mathuo
141b2beaf3
Merge branch 'master' of https://github.com/mathuo/dockview into 281-type-hints-for-panel-parameters 2023-07-25 22:34:40 +01:00
mathuo
bae45867fa
chore(release): publish v1.8.2 2023-07-24 21:04:39 +01:00
mathuo
8ae5a9fc94
chore: v1.8.2 docs 2023-07-24 21:01:55 +01:00
mathuo
76d1f9ab70
Merge pull request #313 from mathuo/311-dnd-v180-bug
feat: external-dnd center drop when dockview is empty
2023-07-24 20:59:45 +01:00
mathuo
3ab3467547
feat: external-dnd center drop when dockview is empty 2023-07-24 20:52:22 +01:00
mathuo
175e8caa67
chore(release): publish v1.8.1 2023-07-24 20:30:50 +01:00
mathuo
b36fd3f312
chore: v1.8.1 docs 2023-07-24 20:27:08 +01:00
mathuo
dfdda78ab4
Merge pull request #312 from mathuo/311-dnd-v180-bug
bug: external-dnd event regression
2023-07-24 20:26:11 +01:00
mathuo
a8e243b3fd
bug: external-dnd event regression
external-dnd events should not trigger the top-level center drop target
2023-07-24 20:14:02 +01:00
mathuo
2aa700bca0
work in progress 2023-07-24 19:47:04 +01:00
mathuo
8833a973b9
feat: expose dragstart event on custom handlers 2023-07-23 21:24:56 +01:00
mathuo
a7dafbf301
chore: v.1.8.0 docs 2023-07-23 20:16:51 +01:00
mathuo
4b49c66283
chore: v1.8.0 release notes 2023-07-23 14:36:13 +01:00
mathuo
2202a89c15
chore(release): publish v1.8.0 2023-07-23 14:33:45 +01:00
mathuo
430f97fd7e
Merge pull request #308 from mathuo/230-explore-floating-groups
230 explore floating groups
2023-07-20 21:34:22 +01:00
mathuo
866869710b
Merge branch 'master' of https://github.com/mathuo/dockview into 230-explore-floating-groups 2023-07-20 21:26:20 +01:00
mathuo
59f9016e8d
test: fix assertion 2023-07-20 21:19:34 +01:00
mathuo
0eec369120
feat: propagate resize and move events when in floating mode 2023-07-20 21:16:26 +01:00
mathuo
1dd8392726 feat: adjust floating group boundaries 2023-07-19 21:52:06 +01:00
mathuo
c89dd5009a
feat: adjust floating group boundaries 2023-07-19 21:30:22 +01:00
mathuo
133ecbfccc feat: overlay resizing outside of main viewport but within bounds 2023-07-18 21:02:39 +01:00
mathuo
83d0c350c1 feat: link api resize events to overlay for floating panels 2023-07-18 21:02:39 +01:00
mathuo
e089b29442
feat: overlay resizing outside of main viewport but within bounds 2023-07-18 20:53:00 +01:00
mathuo
3b27621623
feat: link api resize events to overlay for floating panels 2023-07-18 20:46:43 +01:00
mathuo
5cd51f9f67
Merge pull request #304 from mathuo/230-explore-floating-groups
fix: limit drag handle scope
2023-07-17 20:39:39 +01:00
mathuo
ce15208694
fix: limit drag handle scope 2023-07-17 20:34:23 +01:00
mathuo
8f94f0a3c2
Merge pull request #303 from mathuo/230-explore-floating-groups
fix: limit drag handle scope
2023-07-17 19:50:23 +01:00
mathuo
37a688c874
fix: limit drag handle scope 2023-07-17 19:49:37 +01:00
mathuo
7f5f34d6f2
Merge pull request #302 from mathuo/230-explore-floating-groups
230 explore floating groups
2023-07-16 19:56:10 +01:00
mathuo
e234312e03
feat: simplify logic 2023-07-16 19:41:39 +01:00
mathuo
59aa2723fc
feat: remove .stopPropagation() 2023-07-16 19:36:35 +01:00
mathuo
11269c4625
Merge pull request #301 from mathuo/295-documentation
295 documentation
2023-07-14 20:32:14 +01:00
mathuo
2323c24a6a
chore: docs 2023-07-14 17:17:13 +01:00
mathuo
6acc444c58
fix: build 2023-07-13 20:24:52 +01:00
mathuo
c4e2d1c645
chore: rename script commands 2023-07-13 20:20:37 +01:00
mathuo
a084c8b5b0
docs: sourcemaps 2023-07-13 20:20:18 +01:00
mathuo
ed265d398b
Merge pull request #296 from mathuo/295-documentation
feat: next release v1.8.0 docs
2023-07-13 20:00:37 +01:00
mathuo
559bf48372
Merge branch 'master' of https://github.com/mathuo/dockview into 295-documentation 2023-07-13 19:58:54 +01:00
mathuo
f1357edbb5
Merge pull request #300 from mathuo/230-explore-floating-groups
feat: resrict new floating groups if floating with 1 tab
2023-07-13 18:40:25 +01:00
mathuo
58840287b2
feat: resrict new floating groups if floating with 1 tab 2023-07-13 18:30:40 +01:00
mathuo
f9a6233481
feat: docs 2023-07-13 18:17:45 +01:00
mathuo
38b02a3775
feat: disableFloatingGroups 2023-07-12 22:06:30 +01:00
mathuo
07df1b48ba
feat: docs 2023-07-12 21:53:28 +01:00
mathuo
30e035b2f3
Merge pull request #294 from mathuo/293-expose-removepanel-methods-in-api
feat: expose removepanel on dockviewapi
2023-07-10 21:12:34 +01:00
mathuo
f32cb06056
feat: expose removepanel on dockviewapi 2023-07-10 21:11:48 +01:00
mathuo
2dbfda25e9
Merge pull request #262 from mathuo/230-explore-floating-groups
230 explore floating groups
2023-07-10 21:02:30 +01:00
mathuo
307780d15a
feat: add additional methods and docs for floating groups 2023-07-10 20:51:15 +01:00
mathuo
42b95e5f0a
docs: add docs 2023-07-08 10:49:52 +01:00
mathuo
319cf65ac2
feat: adjust gridview logic 2023-07-08 10:49:30 +01:00
mathuo
12b4a0d27b
feat: floating groups 2023-07-06 21:56:05 +01:00
mathuo
f364bb70a6
feat: allow center drops when no grid panels 2023-07-05 20:24:15 +01:00
mathuo
c1bf5deaf9
remove drop-target overlays when not needed 2023-07-05 20:23:30 +01:00
mathuo
47fb99a06f
fix: inserting orthogonal gridview when empty should not add new views 2023-07-05 20:22:57 +01:00
mathuo
1462b6a37a
test: floating group tests 2023-07-04 21:49:56 +01:00
mathuo
b2b58a4e57
Merge branch '230-explore-floating-groups' of https://github.com/mathuo/dockview into 230-explore-floating-groups 2023-07-02 20:35:04 +01:00
mathuo
86be252e99
feat: floating group persistance 2023-06-29 22:15:44 +01:00
mathuo
50b70a298e
feat: floating group persistance 2023-06-27 20:27:04 +01:00
mathuo
c53d2690c3
Merge branch 'master' of https://github.com/mathuo/dockview into 230-explore-floating-groups 2023-06-21 20:19:45 +01:00
mathuo
e0f167050c
Merge pull request #264 from mathuo/263-left-header-actions
feat: add left header actions
2023-06-21 20:09:51 +01:00
mathuo
359b0e81d0
Merge branch 'master' of https://github.com/mathuo/dockview into 263-left-header-actions 2023-06-21 20:01:53 +01:00
mathuo
b77df7c168
Merge pull request #285 from mathuo/284-layouting
feat: retain layout size after fromJSON
2023-06-21 20:00:57 +01:00
mathuo
5d1b6c336f
chore(release): publish v1.7.6 2023-06-21 19:57:30 +01:00
mathuo
49fed85612
Merge pull request #290 from mathuo/268-touch-support-for-resizing-panels-3
fix: pointmove sash events
2023-06-20 20:47:32 +01:00
mathuo
13516a5f37
fix: pointmove sash events 2023-06-20 20:46:51 +01:00
mathuo
33cf223334
Merge pull request #289 from mathuo/268-touch-support-for-resizing-panels-3
fix: remove .preventDefault() on touch events
2023-06-19 20:55:45 +01:00
mathuo
2c8422b85e
fix: remove .preventDefault() on touch events 2023-06-19 20:11:20 +01:00
mathuo
f87341b99c
Merge pull request #287 from mathuo/286-update-github-actions
chore: update versions on github actions
2023-06-17 15:45:56 +01:00
mathuo
5f3f44bd21
Merge branch 'master' of https://github.com/mathuo/dockview into 286-update-github-actions 2023-06-17 14:11:13 +01:00
mathuo
f483e08497
chore: update versions on github actions 2023-06-17 14:10:24 +01:00
mathuo
5058a9c978
chore: fix docs 2023-06-17 14:09:26 +01:00
mathuo
4fb8a3a098
feat: retain layout size after fromJSON 2023-06-16 21:38:54 +01:00
mathuo
59a947c4c7
chore: prepare v1.7.6 2023-06-16 20:53:32 +01:00
mathuo
6665c61a95
feat: addPanel generics 2023-06-13 20:08:51 +01:00
mathuo
bfc4faeed2
Merge pull request #282 from mpearson/mpearson/component-params-typing
feat: add  optional type parameter for addPanel() params
2023-06-13 19:56:31 +01:00
mathuo
853a5be569
Merge branch '281-type-hints-for-panel-parameters' into mpearson/component-params-typing 2023-06-13 19:53:08 +01:00
mathuo
782a468b7b
Merge pull request #280 from mathuo/268-touch-support-for-resizing-panels-3
268 touch support for resizing panels
2023-06-13 19:41:43 +01:00
mathuo
01544a9953
feat: touch support refactor and test
- add tests
- refactor methods to have a clear seperation between mouse and touch
  logic
2023-06-12 22:11:07 +01:00
mathuo
9e10814840
Patch 1 (#278)
* Touch support for split view

* Attempting to make TS happy

* Making typescript happy round two

https://stackoverflow.com/questions/54688147/react-typescript-event-type-for-both-interfaces-mouseevent-and-touchevent

* make TS Happy

* Update splitview.ts

---------

Co-authored-by: Ray Foss <ray@vblip.com>
2023-06-12 21:36:24 +01:00
mathuo
fbe6c65186
Merge pull request #275 from mathuo/274-gridview-tests
test: gridview tests
2023-06-12 21:28:15 +01:00
mathuo
e3dd45a185
test: add tests 2023-06-12 21:19:39 +01:00
mathuo
0eff522f1f
Merge branch 'master' of https://github.com/mathuo/dockview into 274-gridview-tests 2023-06-11 21:32:13 +01:00
mathuo
1e756209a0
Merge pull request #273 from mathuo/270-documentation-for-iframes
chore: docs
2023-06-11 21:17:23 +01:00
mathuo
35a97b7426
test: gridview tests 2023-06-11 21:17:04 +01:00
mathuo
477394cd1e
chore: docs 2023-06-11 20:43:13 +01:00
mathuo
54bc30c1aa
chore(release): publish v1.7.5 2023-06-11 20:25:44 +01:00
mathuo
c42d8648ea
chore: prepare v1.7.5 2023-06-11 20:25:23 +01:00
mathuo
d8e8103f80
chore: prepare v1.7.5 2023-06-11 20:21:11 +01:00
mathuo
1923ad66ca
Merge pull request #272 from mathuo/255-dispose-of-all-resources-correctly-2
fix: revert gridview disposal changes
2023-06-11 20:20:01 +01:00
mathuo
4f5b6adb5f
fix: revert gridview disposal changes 2023-06-11 20:11:08 +01:00
mathuo
6f9b540fdf
Merge pull request #271 from mathuo/270-documentation-for-iframes
chore: iFrame example
2023-06-11 15:55:50 +01:00
mathuo
ba3fe82c02
chore: iFrame example 2023-06-11 15:49:27 +01:00
mathuo
7905af2945
Merge pull request #269 from mathuo/268-touch-support-for-resizing-panels
test: add tests to existing mouse dnd functionality
2023-06-11 15:18:22 +01:00
mathuo
a39c2938f0
test: listener utilities 2023-06-11 14:32:20 +01:00
mathuo
1539321320
test: add tests to existing mouse dnd functionality 2023-06-11 13:23:12 +01:00
mathuo
2ca4c6fd65
Merge branch 'master' of https://github.com/mathuo/dockview into 263-left-header-actions 2023-06-11 11:34:16 +01:00
mathuo
7dde18c636
chore(release): publish v1.7.4 2023-06-11 09:45:28 +01:00
mathuo
d9906eb802
chore: prepare v1.7.4 2023-06-10 11:38:41 +01:00
mathuo
88565f022c
Merge pull request #265 from mathuo/258-dockviewapitojson-doesnt-include-panel-titles-2
bug: title is deleted when updateParameters() is called with no title
2023-06-06 21:37:55 +01:00
mathuo
78eac85c68
bug: title is deleted when updateParameters() is called with no title 2023-06-06 21:30:28 +01:00
mathuo
105017245b
feat: left header actions 2023-06-04 15:15:41 +01:00
mathuo
77925dc4ca
feat: floating groups 2023-06-04 14:38:48 +01:00
mathuo
bd5999b0ea
Merge branch 'master' of https://github.com/mathuo/dockview into 230-explore-floating-groups 2023-06-04 14:36:30 +01:00
mathuo
b112b2d5e4
Merge branch 'master' of https://github.com/mathuo/dockview into 263-left-header-actions 2023-06-04 14:35:07 +01:00
mathuo
936a5c6917
Merge pull request #257 from mathuo/255-dispose-of-all-responses-correctly
cleanup event listeners after use
2023-06-04 14:34:29 +01:00
mathuo
97483623d4
Merge branch 'master' of https://github.com/mathuo/dockview into 255-dispose-of-all-responses-correctly 2023-06-04 14:26:58 +01:00
mathuo
0cb621e860
cleanup event listeners after use 2023-06-04 14:15:36 +01:00
mathuo
d7baa93a9b
feat: left header actions 2023-06-04 14:13:24 +01:00
mathuo
3d47c8e2c5
chore(release): publish v1.7.3 2023-06-04 10:22:22 +01:00
mathuo
1964d6b306
chore: update sandbox metadata 2023-06-04 10:20:29 +01:00
mathuo
5b493b95e0
feat: experimental floating groups 2023-06-04 10:04:24 +01:00
mathuo
44a7019c60
Merge branch 'master' of https://github.com/mathuo/dockview into 263-left-header-actions 2023-06-03 20:33:26 +01:00
mathuo
efbe019583
Merge branch 'master' of https://github.com/mathuo/dockview 2023-06-03 20:26:53 +01:00
mathuo
b49e2e5d10
chore: generate docs for v1.7.3 2023-06-03 20:26:45 +01:00
mathuo
13d3db605b
feat: add left header actions 2023-06-03 20:21:25 +01:00
mathuo
6434e68b5b
Merge pull request #260 from mathuo/258-dockviewapitojson-doesnt-include-panel-titles
bug: fix conflicts between panel.title and panel.params.title (user p…
2023-06-03 14:57:25 +01:00
mathuo
7fdede6952
Merge branch 'master' of https://github.com/mathuo/dockview into 230-explore-floating-groups 2023-05-31 20:02:45 +01:00
mathuo
1cf23f04ba
bug: fix conflicts between panel.title and panel.params.title (user provided title) 2023-05-31 19:37:36 +01:00
mathuo
32746e248d
chore: docs (plain ts examples) 2023-05-22 21:37:50 +01:00
mathuo
107c20a81d
Merge branch 'master' of https://github.com/mathuo/dockview 2023-05-22 21:10:49 +01:00
mathuo
3c24579e90
chore: docs: plain typescript examples 2023-05-22 21:10:43 +01:00
mathuo
d083ddd129
Merge pull request #253 from mathuo/252-add-typedocs
feat: add typedocs
2023-05-16 21:34:29 +01:00
mathuo
36299d08f9
feat: add typedocs 2023-05-16 21:28:02 +01:00
Matthew Pearson
e6cae5f90d added an optional type parameter for addPanel() so the params prop can be strictly typed 2023-05-13 15:14:00 -07:00
mathuo
22018e0d28
chore: docs 2023-05-08 20:46:12 +01:00
mathuo
fda40a9fcb
chore(release): publish v1.7.2 2023-05-07 20:53:10 +01:00
mathuo
50789414ea
chore: prepare v1.7.2 2023-05-07 15:37:00 +01:00
mathuo
5de5bae766
Merge pull request #250 from mpearson/249-stuck-resizing-fix
bug: disable user-select on drag handles
2023-05-07 15:34:00 +01:00
Matthew Pearson
a147a28222 bug: disable user-select on drag handles 2023-05-06 02:19:38 -07:00
mathuo
bdecc00c81
Update issue templates 2023-04-16 22:35:00 +01:00
mathuo
be11692114
Merge pull request #248 from mathuo/247-remove-code-smells
test: remove smells and test
2023-04-16 22:12:56 +01:00
mathuo
ec341f0706
test: adjust tsconfig for tests 2023-04-16 22:06:48 +01:00
mathuo
575a1d7031
test: remove smells and test 2023-04-16 21:53:28 +01:00
mathuo
7f54cff960
docs: fix website 2023-04-11 22:34:30 +01:00
mathuo
302c269849
chore(release): publish v1.7.1 2023-04-11 21:06:54 +01:00
mathuo
99d4c1e180
docs: 1.7.1 2023-04-11 21:06:17 +01:00
mathuo
c1edea8744
docs: 1.7.1 2023-04-11 21:04:34 +01:00
mathuo
d20689170d
chore: remove source maps from rollup jobs 2023-04-11 20:43:38 +01:00
mathuo
75da885f91
Merge pull request #244 from mathuo/234-improve-tsconfig-setup
chore: remove sourcemaps from rollup jobs
2023-04-11 20:29:40 +01:00
mathuo
98c63628af
chore: remove sourcemaps from rollup jobs 2023-04-11 20:29:13 +01:00
mathuo
6b7f18a3ee
Merge pull request #243 from mathuo/242-adding-panel-through-absoulte-direction-bug
bug: flip orientation when removing intermediate node
2023-04-11 19:42:16 +01:00
mathuo
7b3adb919e
bug: flip orientation when removing intermediate node 2023-04-11 19:23:30 +01:00
mathuo
081e665e56
Merge pull request #241 from mathuo/220-improve-documentation
chore: improve docs
2023-04-06 21:07:19 +01:00
mathuo
c4f778f1cc
chore: improve docs 2023-04-06 21:06:55 +01:00
mathuo
acb500a9d8
Merge pull request #240 from mathuo/220-improve-documentation
chore: docs
2023-04-03 22:45:56 +01:00
mathuo
dd70450a8e
chore: docs 2023-04-03 22:41:19 +01:00
mathuo
21bbaa7349
Merge pull request #235 from mathuo/234-improve-tsconfig-setup
feat: tsconfig adjustments
2023-04-03 22:24:07 +01:00
mathuo
24e7b05321
Merge pull request #237 from mathuo/232-minor-typescript-types-adjustment
chore: type definition fix
2023-04-03 22:23:44 +01:00
mathuo
82df784065
chore: type definition fix 2023-04-03 22:14:52 +01:00
mathuo
9c5fd414c1
Merge pull request #236 from mathuo/233-remove-js-tabheight-setter-in-favour-of-css
feature: remove tabHeight setter
2023-04-03 22:06:47 +01:00
mathuo
e07cedf01f
feat: remove tabHeight setter 2023-04-03 22:06:24 +01:00
mathuo
36299f8c93
feat: tsconfig adjustments 2023-04-03 22:06:10 +01:00
mathuo
7343009e9b
chore: align types 2023-04-01 21:01:07 +01:00
mathuo
ffd5db273e
feature: floating groups 2023-04-01 20:57:41 +01:00
mathuo
1f384c3c65
Merge pull request #229 from mathuo/220-improve-documentation
chore: docs
2023-03-27 21:21:09 +01:00
mathuo
74f451ea16
chore: docs 2023-03-27 21:20:41 +01:00
mathuo
d5da2a443b
Merge pull request #228 from mathuo/220-improve-documentation
220 improve documentation
2023-03-27 21:19:26 +01:00
mathuo
d68a1c88d0
chore: docs 2023-03-27 21:11:05 +01:00
mathuo
857b475be7
Merge pull request #221 from mathuo/220-improve-documentation
chore: docs
2023-03-26 19:58:19 +01:00
mathuo
3cbd238c8a
Merge branch 'master' of https://github.com/mathuo/dockview into 220-improve-documentation 2023-03-26 19:52:31 +01:00
mathuo
e95777a6a2
Merge pull request #227 from mathuo/226-move-resizeobserver-logic-into-dockview-core
feat: move resizeObserver logic into dockview-core
2023-03-26 19:51:03 +01:00
mathuo
1853d45191
Merge pull request #223 from mathuo/222-include-source-maps-in-build
feat: adjust tsconfigs
2023-03-26 19:49:13 +01:00
mathuo
c3db8e303d
chore: docs 2023-03-26 19:38:37 +01:00
mathuo
551731ffd1
Merge pull request #225 from mathuo/224-bug-close-button-on-default-watermark-doesnt-work
bug: fix close button on default watermark
2023-03-26 19:34:29 +01:00
mathuo
d847f18cd0
feat: move resizeObserver logic into dockview-core 2023-03-26 19:27:44 +01:00
mathuo
360d6ef429
bug: fix close button on default watermark 2023-03-26 16:03:23 +01:00
mathuo
2b7ba6489c
feat: adjust tsconfigs 2023-03-26 15:12:35 +01:00
mathuo
a51740c123
Merge pull request #217 from mathuo/208-documentation-examples-1
chore: docs
2023-03-25 20:38:01 +00:00
mathuo
0f828a909a
Merge branch 'master' of https://github.com/mathuo/dockview into 208-documentation-examples-1 2023-03-25 20:29:29 +00:00
mathuo
42a608b93d
chore: 1.7.0 docs 2023-03-25 20:26:14 +00:00
mathuo
4a7c6b3fee
chore: docs 2023-03-25 20:16:22 +00:00
mathuo
5e15af4ad5
chore(release): publish v1.7.0 2023-03-25 15:01:20 +00:00
mathuo
17cf5a6057
Merge pull request #216 from mathuo/215-obscuring-react-dnd-droptargets-inside-of-a-dockview-in-160
bug: fix dnd events interaction with third-party libs
2023-03-23 17:45:32 +01:00
mathuo
84088505a8
bug: fix dnd events interaction with third-party libs 2023-03-22 21:32:09 +01:00
mathuo
464c4fd938
Merge pull request #212 from mathuo/210-setconstraints-on-gridview-enable-size-locking-1
fix: dockview panel group should derive constraints
2023-03-22 21:30:36 +01:00
mathuo
20f200963f
refactor: cleanup 2023-03-21 17:57:53 +01:00
mathuo
1e3462a193
chore: docs 2023-03-21 17:48:56 +01:00
mathuo
997208822b
Merge branch 'master' of https://github.com/mathuo/dockview into 210-setconstraints-on-gridview-enable-size-locking-1 2023-03-21 17:34:41 +01:00
mathuo
84e88f458f
Merge pull request #214 from mathuo/213-internal-refactoring
refactor: internal refactoring
2023-03-21 20:33:41 +04:00
mathuo
6aca089685
refactor: internal refactoring 2023-03-21 17:27:04 +01:00
mathuo
ad05a3cc25
chore: docs 2023-03-21 17:24:06 +01:00
mathuo
a74daf410e
fix: dockview panel group should derive constraints 2023-03-19 23:00:10 +04:00
mathuo
d1f67828e3
chore: docs 2023-03-19 22:59:47 +04:00
mathuo
c44ccfa52e
test: add test 2023-03-19 22:59:46 +04:00
mathuo
5b1aa4221f
Merge pull request #209 from mathuo/208-documentation-examples
chore: sandbox example
2023-03-19 21:56:54 +04:00
mathuo
6e5e8429ec
chore: sandbox examples 2023-03-19 21:43:24 +04:00
mathuo
454542b729
feat: adjust watermark component props 2023-03-15 21:26:34 +03:00
mathuo
015cef7fb0
chore: sandbox example 2023-03-15 21:24:22 +03:00
mathuo
325a203877
Merge pull request #207 from mathuo/206-internal-enhancements
refactor: remove legacy code
2023-03-14 21:11:04 +03:00
mathuo
3a458461a1
refactor: move and delete code 2023-03-14 19:47:56 +03:00
mathuo
09a6f265d5
refactor: jest setup 2023-03-14 19:19:38 +03:00
mathuo
1134f972d3
refactor: remove legacy code 2023-03-14 07:46:29 +03:00
mathuo
1b6c2ba92c
Merge pull request #205 from mathuo/198-vanillajs-rendering-and-persistance
198 vanillajs rendering and persistance
2023-03-14 01:19:53 +08:00
mathuo
6d5f3e5975
chore: fix sonar line coverage 2023-03-13 20:19:25 +03:00
mathuo
5ee487f110
test 2023-03-13 19:42:14 +03:00
mathuo
1f3bed9740
Merge pull request #201 from mathuo/198-vanillajs-rendering-and-persistance
test
2023-03-14 00:12:53 +08:00
mathuo
d60b4c6ba2
tests: add tests 2023-03-13 19:12:33 +03:00
mathuo
3e0911aa91
Merge pull request #202 from JoshuaKGoldberg/patch-1
chore: typo "Serialziable"/"Serializable"
2023-03-13 22:55:06 +08:00
Josh Goldberg
c5e6ebbe7f
typo: "Serialziable"/"Serializable" 2023-03-13 01:41:38 -04:00
mathuo
3fdb3fd3d6
Merge pull request #200 from mathuo/198-vanillajs-rendering-and-persistance
198 vanillajs rendering and persistance
2023-03-12 21:54:05 +08:00
mathuo
dd8a648a3e
chore: readme file 2023-03-12 21:45:30 +08:00
mathuo
7ac07bdf0d
chore: fix docs build 2023-03-12 21:43:28 +08:00
mathuo
e0bf694512
chore: add README 2023-03-07 22:47:21 +08:00
mathuo
db1cb49487
refactor: set deserializer by default 2023-03-07 22:33:13 +08:00
mathuo
d00da9234d
Merge pull request #199 from mathuo/198-vanillajs-rendering-and-persistance
198 vanillajs rendering and persistance
2023-03-07 22:08:55 +08:00
mathuo
8918e254ed
refactor: improve typings 2023-03-07 21:55:36 +08:00
mathuo
7d50eb5453
refactor: moving files 2023-03-07 18:38:05 +08:00
mathuo
c3e2ed1a87
refactor: renaming files 2023-03-06 23:37:50 +08:00
mathuo
8528f8d70f
Merge branch 'master' of https://github.com/mathuo/dockview into 198-vanillajs-rendering-and-persistance 2023-03-06 23:18:28 +08:00
mathuo
a43ee59bc2
Merge pull request #174 from mathuo/172-zero-dependency-vanilla-js
refactor: expose a vanillajs export
2023-03-06 23:13:48 +08:00
mathuo
52e458772e
tests: fix tests 2023-03-06 23:12:51 +08:00
mathuo
b883e2fd31
refactor: renaming 2023-03-03 15:43:31 +08:00
mathuo
f26a1cd404
feat: persistance and rendering 2023-02-28 22:43:21 +08:00
mathuo
37b0a062a4
chore: cleanup 2023-02-27 22:55:36 +08:00
mathuo
a9b44d9641
chore: build fixes 2023-02-27 22:12:03 +08:00
mathuo
e2049edab7
chore: adjust sonar projects 2023-02-27 16:59:08 +08:00
mathuo
5f72f5a36d
chore: split packages 2023-02-27 16:58:50 +08:00
mathuo
d09b2e8ff4
Merge branch 'master' of https://github.com/mathuo/dockview into 172-zero-dependency-vanilla-js 2023-02-27 16:05:54 +08:00
mathuo
722152c80c
Merge pull request #197 from mathuo/196-make-dockview-panel-title-optional
feat: dockview title to be optional
2023-02-27 16:01:06 +08:00
mathuo
4f09deeae5
Merge pull request #195 from mathuo/181-release-documentation
chore: 1.6.0 docs
2023-02-26 21:50:38 +08:00
mathuo
660d99754a
feat: dockview title to be optional 2023-02-26 21:50:15 +08:00
mathuo
0f714daaa8
chore: 1.6.0 docs 2023-02-26 20:45:49 +08:00
mathuo
c7565f7c24
chore(release): publish v1.6.0 2023-02-26 20:40:25 +08:00
mathuo
2e09a7028f
Merge pull request #188 from mathuo/181-release-documentation
chore: docs
2023-02-26 20:36:06 +08:00
mathuo
4222d32b8d
chore: docs 2023-02-26 20:31:50 +08:00
mathuo
acdad8f439
Merge branch 'master' of https://github.com/mathuo/dockview into 181-release-documentation 2023-02-25 18:37:23 +08:00
mathuo
417cdf875f
Merge pull request #194 from mathuo/191-dockview-watermark-fixes
feat: attach watermark seperately from groups
2023-02-25 18:36:55 +08:00
mathuo
14f565da4e
feat: attach watermark seperately from groups 2023-02-25 18:31:46 +08:00
mathuo
fdf7db15e3
Merge pull request #193 from mathuo/192-dockview-panel-dnd-fix
fix: dnd only for same dockview instance
2023-02-25 18:23:22 +08:00
mathuo
34ea71a09a
fix: dnd only for same dockview instance 2023-02-25 17:56:20 +08:00
mathuo
2e757e7aed
chore: docs 2023-02-22 23:26:30 +08:00
mathuo
7cfabd53d4
Merge branch 'master' of https://github.com/mathuo/dockview into 181-release-documentation 2023-02-22 11:35:47 +07:00
mathuo
e7caeb1906
Merge pull request #190 from mathuo/189-dockview-settitle-method
fix: dockview panel setTitle
2023-02-22 11:35:07 +07:00
mathuo
eb5006fc03
fix: dockview panel setTitle 2023-02-22 11:28:39 +07:00
mathuo
97c75eb7f7
chore: docs 2023-02-21 07:41:15 +07:00
mathuo
b02087d222
Merge pull request #182 from mathuo/181-release-documentation
chore: docs
2023-02-21 07:40:41 +07:00
mathuo
1eac7e83ea
Merge branch 'master' of https://github.com/mathuo/dockview into 181-release-documentation 2023-02-21 07:30:44 +07:00
mathuo
171031d940
Merge pull request #187 from mathuo/186-website-crashing
186 website crashing
2023-02-21 07:29:57 +07:00
mathuo
199e4ff77d
fix: use alternative build for docs due to breaking changing in upcoming release 2023-02-21 07:24:03 +07:00
mathuo
4ff77d4696
chore: docs 2023-02-20 20:32:25 +07:00
mathuo
fb9c056ff6
Merge branch 'master' of https://github.com/mathuo/dockview into 181-release-documentation 2023-02-20 20:30:12 +07:00
mathuo
200e1c4ccb
Merge pull request #185 from mathuo/176-dnd-to-edge-of-dockview
feat: dnd edge custom dnd handles
2023-02-20 20:29:15 +07:00
mathuo
9f504f2597
feat: dnd edge custom dnd handles 2023-02-20 20:24:00 +07:00
mathuo
d4ef82835a
Merge branch 'master' of https://github.com/mathuo/dockview into 181-release-documentation 2023-02-20 18:09:27 +07:00
mathuo
fe5a882631
Merge pull request #184 from mathuo/183-panel-apisetsize
feat: panel.api.setSize links to group setSize
2023-02-20 18:09:17 +07:00
mathuo
debdcb8d8b
feat: panel.api.setSize links to group setSize 2023-02-20 18:04:24 +07:00
mathuo
9e8b0fddd4
chore: docs for release v1.6.0 2023-02-20 17:55:49 +07:00
mathuo
4bd6eba53a
Merge pull request #180 from mathuo/179-update-dependencies
chore: update deps
2023-02-16 21:44:54 +07:00
mathuo
4e830afa3c
chore: update deps 2023-02-16 21:11:12 +07:00
mathuo
213d3ed235
Merge pull request #177 from mathuo/176-dnd-to-edge-of-dockview
176 dnd to edge of dockview
2023-02-15 22:41:31 +07:00
mathuo
6600cb88d8
refactor: rename files 2023-02-15 22:05:07 +07:00
mathuo
3052857dfc
refactor: simplify dnd control 2023-02-14 22:38:01 +07:00
mathuo
321f78ec0e
tests: add tests 2023-02-14 16:00:53 +07:00
mathuo
bf350e404b
fix: self dropping group dnd 2023-02-13 16:09:49 +07:00
mathuo
747049b8f3
refactor: code quality fixes 2023-02-13 16:03:02 +07:00
mathuo
026e6b9b91
refactor: single tab mode 2023-02-13 15:22:42 +07:00
mathuo
01816a1d8b
refactor: improve public api 2023-02-12 22:58:37 +07:00
mathuo
716424d972
refactor: remove dead code 2023-02-12 21:12:14 +07:00
mathuo
fa5cf06431
refactor: clean dnd logic 2023-02-12 21:11:51 +07:00
mathuo
c99a385a1d
Merge branch 'master' of https://github.com/mathuo/dockview into 176-dnd-to-edge-of-dockview 2023-02-12 20:57:17 +07:00
mathuo
b8a5d30f81
Merge pull request #171 from mathuo/170-allow-dnd-of-entire-dockview-groups
feat: dnd dockview groups
2023-02-12 20:54:15 +07:00
mathuo
78336d6d90
Merge branch '170-allow-dnd-of-entire-dockview-groups' of https://github.com/mathuo/dockview into 176-dnd-to-edge-of-dockview 2023-02-12 20:46:43 +07:00
mathuo
82490cba46
refactor: cleanup code 2023-02-12 20:30:51 +07:00
mathuo
a35bb26f3d
refactor: prefix classnames with dv-* to prevent collisions 2023-02-12 20:22:15 +07:00
mathuo
ff3f0b23a8
feat: generate UMD bundle without react dependency 2023-02-07 18:03:07 +07:00
mathuo
bd381640af
refactor: isolate react code 2023-02-07 17:36:41 +07:00
mathuo
b21b222ee4
Merge branch 'master' of https://github.com/mathuo/dockview into 172-zero-dependency-vanilla-js 2023-02-06 18:01:26 +07:00
mathuo
7aa19b2c89
feat: improve api 2023-02-06 18:01:01 +07:00
mathuo
c41158cea6
refactor: improve droptarget component 2023-02-02 18:08:37 +07:00
mathuo
c34e03f158
Merge branch '170-allow-dnd-of-entire-dockview-groups' of https://github.com/mathuo/dockview into 176-dnd-to-edge-of-dockview 2023-02-01 22:01:25 +07:00
mathuo
edaf3cb067
refactor: reduce code duplication 2023-02-01 22:00:34 +07:00
mathuo
563d57be59
Merge pull request #168 from mathuo/163-ability-to-drag-tabs-into-empty-panels
feat: allowing dnd actions on empty containers
2023-02-01 21:49:10 +07:00
mathuo
f5709549c6
feat: dnd to edge of dockview 2023-02-01 21:48:11 +07:00
mathuo
5e4d2cb506
feat: dnd dockview groups 2023-01-18 22:55:05 +08:00
mathuo
080db84537
refactor: expose a vanillajs export 2023-01-18 22:36:15 +08:00
mathuo
4fdd836380
feat: allowing dnd actions on empty containers 2023-01-08 22:25:29 +09:00
mathuo
5e4a9d5855
chore: remove 1.4.3 and 1.5.0 docs 2022-10-04 16:45:00 -04:00
mathuo
7168f55fab
chore: 1.5.2 docs 2022-10-04 16:44:16 -04:00
mathuo
834d763445
chore(release): publish v1.5.2 2022-10-04 16:38:28 -04:00
mathuo
33a52523fe
Merge pull request #157 from mathuo/156-add-doucmentation-for-dockview-resizing
update documentation
2022-09-26 21:21:57 +01:00
mathuo
407d9b3aad
chore: update docs 2022-09-21 21:21:36 +01:00
mathuo
19ecd531e1
feat: onDidChange allow for orthogonalSize changes 2022-09-21 21:21:16 +01:00
mathuo
d5920bd4f8
chore: update documentation 2022-09-21 21:21:00 +01:00
mathuo
8810ad1a66
Merge pull request #153 from mathuo/152-fix-build
chore: fix builds
2022-08-20 13:50:21 +01:00
mathuo
6b146cf1bf
chore: fix builds 2022-08-20 13:29:39 +01:00
mathuo
b1216dc96d
chore: fix docs build 2022-08-18 22:38:30 +01:00
mathuo
5171a4a592
chore: fix docs build 2022-08-18 21:12:02 +01:00
mathuo
562055a72f
chore: fix docs build 2022-08-17 20:55:19 +01:00
mathuo
f8fca83166
chore: remove old demo project 2022-07-23 16:31:23 +01:00
mathuo
9e6f0877f1
chore: update 1.5.1 docs 2022-07-23 16:30:49 +01:00
mathuo
bb7d8dfb52
chore: 1.5.1 release notes 2022-07-23 16:00:01 +01:00
mathuo
f8137b7eb7
chore(release): publish v1.5.1 2022-07-23 15:49:27 +01:00
mathuo
3533671406
Merge pull request #146 from mathuo/145-remove-suppressclosable
feat: remove suppress closable option
2022-07-17 15:31:37 +01:00
mathuo
9ca535efa7
feat: remove suppress closable option 2022-07-15 19:29:59 +01:00
mathuo
e2f981274c
Merge pull request #144 from mathuo/143-fix-panel-getparams
fix: change get(params)
2022-07-15 19:28:46 +01:00
mathuo
e9bf894acb
fix: change get(params) 2022-07-13 21:30:17 +01:00
mathuo
06252f1d0c
Merge pull request #141 from mathuo/140-update-docs-to-new-version
140 update docs to new version
2022-06-20 20:11:14 +01:00
mathuo
9951563ce1
Merge pull request #127 from mathuo/126-remove-dockview-ontabcontextmenu
feat: remove onTabContextMenu and add a default tab option
2022-06-19 20:39:40 +01:00
mathuo
a05f101ad4
chore: latest docs 2022-06-19 20:33:12 +01:00
mathuo
653fead20b
chore(release): publish v1.5.0 2022-06-19 20:22:05 +01:00
mathuo
9dee87dce4
chore: fix test 2022-06-19 20:20:44 +01:00
mathuo
34d8317ec5
chore: remove circular dependency 2022-06-19 20:19:37 +01:00
mathuo
42881ab3c0
Merge pull request #139 from mathuo/133-dnd-enhancements
feat: don't serialize info when using default tab
2022-06-19 20:11:35 +01:00
mathuo
4e124e6eb6
feat: don't serialize info when using default tab 2022-06-19 20:04:39 +01:00
mathuo
fbc8fce942
Merge pull request #138 from mathuo/137-group-controls-section
feat: group controls renderer
2022-06-11 23:08:30 +01:00
mathuo
a7f69fc617
feat: group controls renderer 2022-06-11 22:51:58 +01:00
mathuo
a92fb3f554
Merge pull request #136 from mathuo/133-dnd-enhancements
feat: dnd changes
2022-06-10 21:09:45 +01:00
mathuo
ea69f14f73
feat: dnd changes 2022-06-10 20:26:57 +01:00
mathuo
a2929a84ff
Merge branch 'master' of https://github.com/mathuo/dockview into 126-remove-dockview-ontabcontextmenu 2022-06-05 22:41:31 +01:00
mathuo
60333848af
Merge pull request #132 from mathuo/131-use-svg-icons
feat: use svg icons and CSS color property for icons
2022-06-05 22:40:11 +01:00
mathuo
0c28f2dabe
feat: use svg icons and CSS color property for icons 2022-06-05 22:32:04 +01:00
mathuo
cb354445ac
Merge branch 'master' of https://github.com/mathuo/dockview into 126-remove-dockview-ontabcontextmenu 2022-05-31 20:49:01 +01:00
mathuo
68e573e5f0
Merge pull request #130 from mathuo/100-docs
100 docs
2022-05-31 20:40:45 +01:00
mathuo
878452e9d3
chore: docs 2022-05-31 20:13:58 +01:00
mathuo
3faf0ae6dc
Merge branch 'master' of https://github.com/mathuo/dockview into 100-docs 2022-05-31 19:56:18 +01:00
mathuo
f82f2c8636
Merge branch 'master' of https://github.com/mathuo/dockview into master 2022-05-31 19:55:52 +01:00
mathuo
1921e170e0
feat: add abyss theme 2022-05-31 19:55:43 +01:00
mathuo
238c11f969
chore: docs 2022-05-31 19:55:19 +01:00
mathuo
025ea3279a
Merge pull request #129 from mathuo/100-docs
100 docs
2022-05-30 22:28:00 +01:00
mathuo
9ade38b0c4
chore: docs 2022-05-30 22:22:19 +01:00
mathuo
96ef9ee464
Merge branch '100-docs' of https://github.com/mathuo/dockview into 126-remove-dockview-ontabcontextmenu 2022-05-30 22:09:00 +01:00
mathuo
1865fe7ca0
chore: docs 2022-05-30 22:00:44 +01:00
mathuo
61875fff08
Merge branch 'master' of https://github.com/mathuo/dockview into 126-remove-dockview-ontabcontextmenu 2022-05-29 19:47:29 +01:00
mathuo
6c2c59f858
Merge pull request #128 from mathuo/100-docs
100 docs
2022-05-29 19:47:26 +01:00
mathuo
7882e581e5
chore: docs 2022-05-29 18:05:58 +01:00
mathuo
28f77ac3ae
Merge branch 'master' of https://github.com/mathuo/dockview into 100-docs 2022-05-29 17:50:19 +01:00
mathuo
10e12340f9
chore: add versions 2022-05-29 17:49:08 +01:00
mathuo
d1cf3818a9
feat: remove onTabContextMenu and add a default tab option 2022-05-29 17:31:29 +01:00
mathuo
f563ae4fe4
Merge pull request #125 from mathuo/100-docs
chore: improve docs!
2022-05-29 16:49:59 +01:00
mathuo
c75964632b
chore: improve docs 2022-05-29 16:33:48 +01:00
mathuo
b271565bf3
chore: improve docs 2022-05-29 16:27:52 +01:00
mathuo
101dbbdfde
Merge pull request #122 from mathuo/100-docs
publish
2022-05-26 22:42:02 +01:00
mathuo
8b736513a4
chore: fix github deploy action 2022-05-26 22:41:39 +01:00
mathuo
6218281af0
Merge branch 'master' of https://github.com/mathuo/dockview into 100-docs 2022-05-26 22:09:11 +01:00
mathuo
f697fc5da8
chore: fix github deploy action 2022-05-26 22:04:27 +01:00
mathuo
95c7b1a624
chore(release): publish v1.4.3 2022-05-26 22:01:13 +01:00
mathuo
b2c2869574
Merge pull request #121 from mathuo/100-docs
100 docs
2022-05-26 21:59:51 +01:00
mathuo
64e71f8931
Merge branch 'master' of https://github.com/mathuo/dockview into 100-docs 2022-05-26 21:56:01 +01:00
mathuo
04f42ba801
chore: move docs package 2022-05-26 21:54:35 +01:00
mathuo
eed74f5310
chore: fix lerna 2022-05-26 21:48:22 +01:00
mathuo
982bbc1ed9
feat: add docs to lerna 2022-05-26 21:45:12 +01:00
mathuo
faf4103f6e
Merge pull request #101 from mathuo/100-docs
chore: docs
2022-05-26 21:43:04 +01:00
mathuo
bfee4c6a51
chore: docs 2022-05-26 21:38:16 +01:00
mathuo
b486e3ae58
Merge branch 'master' of https://github.com/mathuo/dockview into 100-docs 2022-05-25 23:29:28 +01:00
mathuo
9dd307b5e3
Merge pull request #119 from mathuo/118-enhance-api
feat: add clear method and fix .orientation setter
2022-05-25 22:39:29 +01:00
mathuo
88c7761b4e
Merge pull request #120 from mathuo/115-adjust-default-paneview-header
feat: fix styles
2022-05-25 22:39:03 +01:00
mathuo
84463e4240
feat: add clear method and fix .orientation setter 2022-05-25 22:33:26 +01:00
mathuo
2fe3f53ac1
feat: fix styles 2022-05-25 22:32:07 +01:00
mathuo
014125d823
chore: docs 2022-05-25 22:22:11 +01:00
mathuo
659a59f16f
Merge branch 'master' of https://github.com/mathuo/dockview into 100-docs 2022-05-22 22:13:20 +01:00
mathuo
0ad2fc4b48
Merge pull request #114 from mathuo/113-improve-events
feat: improve events
2022-05-22 22:13:12 +01:00
mathuo
1f022635cf
feat: improve events 2022-05-22 21:10:54 +01:00
mathuo
93ff4045a0
Merge pull request #116 from mathuo/115-adjust-default-paneview-header
feat: adjust paneview header
2022-05-22 20:35:14 +01:00
mathuo
7544926d08
Merge pull request #117 from mathuo/111-api-improvements
Revert "feat: remove panel.api.focus() from public api"
2022-05-22 20:35:06 +01:00
mathuo
598175ea60
Revert "feat: remove panel.api.focus() from public api"
This reverts commit 03642d50a2.
2022-05-22 19:52:16 +01:00
mathuo
06f467184b
feat: adjust paneview header 2022-05-22 19:49:42 +01:00
mathuo
8a51593ac3
further docs work 2022-05-21 21:43:11 +01:00
mathuo
d306387a0a
Merge branch 'master' of https://github.com/mathuo/dockview into 100-docs 2022-05-21 21:13:16 +01:00
mathuo
2774a27eda
Merge pull request #110 from mathuo/109-external-dnd-events
feat: improve dnd events
2022-05-21 21:10:50 +01:00
mathuo
92465af989
Merge branch 'master' of https://github.com/mathuo/dockview into 100-docs 2022-05-21 20:28:58 +01:00
mathuo
87d474d11b
Merge pull request #112 from mathuo/111-api-improvements
feat: fix typo
2022-05-21 20:28:17 +01:00
mathuo
d9453329cf
chore: move project 2022-05-21 20:27:22 +01:00
mathuo
79df8020b8
remove api methods not intended to be public 2022-05-21 19:52:05 +01:00
mathuo
03642d50a2
feat: remove panel.api.focus() from public api 2022-05-21 19:08:13 +01:00
mathuo
81bd9953c5
feat: improve dnd events 2022-05-21 19:07:10 +01:00
mathuo
c0f5b1d86b
feat: fix typo 2022-05-21 18:57:42 +01:00
mathuo
0dc3098d69
feat: convert to docasaurus 2022-05-19 21:46:39 +01:00
mathuo
3cfc01bec4
Merge branch 'master' of https://github.com/mathuo/dockview into 100-docs 2022-05-16 21:33:50 +01:00
mathuo
5fba8814a8
chore(release): publish v1.4.2 2022-05-16 21:29:20 +01:00
mathuo
575dbac8ca
Merge pull request #108 from mathuo/107-deserialization-issue
feat: fix deserialization active panel issue + tests
2022-05-16 21:19:33 +01:00
mathuo
b7085493a7
feat: fix deserialization active panel issue + tests 2022-05-16 18:03:02 +01:00
mathuo
7d69014561
Merge branch '100-docs' of https://github.com/mathuo/dockview into 100-docs 2022-05-13 20:35:52 +01:00
mathuo
10317206e0
chore: docs 2022-05-11 22:19:32 +01:00
mathuo
0693c49098
Merge pull request #106 from mathuo/104-api-enhancements
feat: rename public api method to more suitable names
2022-05-11 22:00:38 +01:00
mathuo
ba2976dd74
chore(release): publish v1.4.1 2022-05-11 21:55:07 +01:00
mathuo
f24e33f224
feat: rename public api method to more suitable names 2022-05-11 21:32:02 +01:00
mathuo
f5b90725f4
Merge branch 'master' of https://github.com/mathuo/dockview into 100-docs 2022-05-10 21:59:28 +01:00
mathuo
c259b44e39
Merge pull request #105 from mathuo/104-api-enhancements
feat: api enhancements
2022-05-10 21:59:16 +01:00
mathuo
6d58e48470
chore: fix demo 2022-05-10 21:59:06 +01:00
mathuo
568731b723
chore: docs 2022-05-10 21:51:07 +01:00
mathuo
b4a1f46a49
feat: api enhancements
* rename variable
* remove interface functions not intended to be public
2022-05-10 21:49:43 +01:00
mathuo
c249d44017
Merge pull request #103 from mathuo/102-drag-event-on-tab-content-not-bubbled-to-tab
102 drag event on tab content not bubbled to tab
2022-05-10 19:11:54 +01:00
mathuo
a7b05cf1a8
feat: only update text content if required 2022-05-09 21:37:57 +01:00
mathuo
48a1cc9693
chore: fix demo
demo app to be deleted soon in favor of docs so fix is just to remove
code
2022-05-09 21:26:47 +01:00
mathuo
bb247e1303
feat: fix dnd firefox bug
+ simplify tab rendering and remove support for HOC Dockview components
  since it's not a great implementation - can find another solution if
  required
2022-05-09 21:23:32 +01:00
mathuo
88860cd4cd
chore: docs 2022-05-08 22:43:25 +01:00
mathuo
df52c808ab
Merge pull request #99 from mathuo/79-new-documentation-website
chore: yarn
2022-05-08 21:57:10 +01:00
mathuo
8a9106ab76
chore: yarn 2022-05-08 21:51:05 +01:00
mathuo
0932a83f1a
Merge pull request #98 from mathuo/79-new-documentation-website
chore: fix action runtime
2022-05-08 21:05:28 +01:00
mathuo
8bd560688a
chore: fix action runtime 2022-05-08 21:05:13 +01:00
mathuo
63a9ba81cc
chore(release): publish v1.4.0 2022-05-08 21:02:18 +01:00
mathuo
d84f48e151
chore: jest dependencies 2022-05-08 21:00:22 +01:00
mathuo
2d3b35c008
Merge pull request #97 from mathuo/79-new-documentation-website
79 new documentation website
2022-05-08 20:57:37 +01:00
mathuo
4d72d84971
chore: project changes 2022-05-08 20:55:34 +01:00
mathuo
73da6be06a
chore: fix demo 2022-05-08 20:18:48 +01:00
mathuo
0ba72eeb5e
chore: update docs 2022-05-08 19:49:32 +01:00
mathuo
1f0bc97b10
Merge branch 'master' of https://github.com/mathuo/dockview into 79-new-documentation-website 2022-05-08 19:47:23 +01:00
mathuo
3241cec703
feat: docs 2022-05-05 23:00:11 +01:00
mathuo
cec14b9d50
Merge pull request #96 from mathuo/95-api-enhancements
feat: rename classes
2022-05-05 21:59:07 +01:00
mathuo
530226dcbd
feat: rename classes 2022-05-05 21:20:03 +01:00
mathuo
d94460955d
feat: rename classes 2022-05-05 20:32:42 +01:00
mathuo
d7d6dc2635
Merge pull request #87 from mathuo/84-add-ability-to-have-fixed-panel-with-no-tab-in-dockviewreact
84 add ability to have fixed panel with no tab in dockviewreact
2022-05-04 20:43:17 +01:00
mathuo
79f4379b8c
test: add tests 2022-05-04 20:28:20 +01:00
mathuo
ce60215af5
Merge branch 'master' of https://github.com/mathuo/dockview into 84-add-ability-to-have-fixed-panel-with-no-tab-in-dockviewreact 2022-05-04 20:00:38 +01:00
mathuo
2883276888
Merge pull request #94 from mathuo/79-new-documentation-website
chore: adjust action frequency
2022-05-04 20:00:31 +01:00
mathuo
50896ff879
chore: adjust action frequency 2022-05-04 20:00:06 +01:00
mathuo
6ebd185f0a
Merge branch 'master' of https://github.com/mathuo/dockview into 84-add-ability-to-have-fixed-panel-with-no-tab-in-dockviewreact 2022-05-04 19:54:29 +01:00
mathuo
49594e5bfe
Merge pull request #80 from mathuo/79-new-documentation-website
feat: docs website
2022-05-04 19:54:07 +01:00
mathuo
0943ff8f4b
chore: deploy scripts 2022-05-04 19:48:17 +01:00
mathuo
c044af68e9
fix: packages 2022-05-02 22:40:17 +01:00
mathuo
901a4d0c7f
Merge branch 'master' of https://github.com/mathuo/dockview into 79-new-documentation-website 2022-05-02 22:33:39 +01:00
mathuo
b0124d6180
Merge pull request #93 from mathuo/90-api-enhancements
chore: fix demo
2022-05-02 22:31:05 +01:00
mathuo
2381481ec5
chore: docs 2022-05-02 22:30:36 +01:00
mathuo
a5ce4f5873
chore: fix demo 2022-05-02 22:19:06 +01:00
mathuo
a6b0250b86
feat: adjust to make group non-optional 2022-05-02 22:14:08 +01:00
mathuo
05f8ab8f8b
Merge branch 'master' of https://github.com/mathuo/dockview into 84-add-ability-to-have-fixed-panel-with-no-tab-in-dockviewreact 2022-05-02 17:20:07 +01:00
mathuo
1627dacd50
Merge pull request #92 from mathuo/90-api-enhancements
feat: api improvements
2022-05-02 17:19:39 +01:00
mathuo
4806421ba5
feat: api improvements 2022-05-02 17:14:41 +01:00
mathuo
926272067a
chore: fix 2022-05-01 21:49:44 +01:00
mathuo
77db3adbe9
Merge branch 'master' into 90-api-enhancements 2022-05-01 21:48:42 +01:00
mathuo
20b6db2202
feat: api improvements 2022-05-01 21:40:05 +01:00
mathuo
ee3a1b4d4e
Merge branch '90-api-enhancements' of https://github.com/mathuo/dockview into 79-new-documentation-website 2022-05-01 21:17:40 +01:00
mathuo
9dd77af81a
feat: api improvements 2022-05-01 21:15:26 +01:00
mathuo
7f00754571
Merge branch '79-new-documentation-website' of https://github.com/mathuo/dockview into 79-new-documentation-website 2022-05-01 21:10:53 +01:00
mathuo
d90aadb67a
chore: docs 2022-05-01 21:06:33 +01:00
mathuo
bb13a10d5c
Merge branch 'master' of https://github.com/mathuo/dockview into 79-new-documentation-website 2022-05-01 20:39:09 +01:00
mathuo
b77e7922bb
feat: api improvements 2022-05-01 20:34:41 +01:00
mathuo
432ab10e7f
chore(release): publish v1.3.1 2022-05-01 20:27:13 +01:00
mathuo
094d19cb34
feat: docs website 2022-04-28 23:23:37 +01:00
mathuo
4936f64c0b
Merge pull request #89 from mathuo/88-fix-droptarget-styles
fix: style fix
2022-04-28 23:22:38 +01:00
mathuo
30a42a6fcd
feat: docs website 2022-04-28 23:20:39 +01:00
mathuo
9a38f039f4
feat: simplify public api 2022-04-28 23:20:38 +01:00
mathuo
e8c746208c
chore(release): publish v1.3.0 2022-04-28 23:20:38 +01:00
mathuo
bc7731a39d
fix watermark 2022-04-28 23:20:38 +01:00
mathuo
03b6c62239
chore: fix sonar code smells 2022-04-28 23:20:38 +01:00
mathuo
9d253d2c70
chore: fix sonar code smells 2022-04-28 23:20:38 +01:00
mathuo
8f8083e835
fix: style fix 2022-04-28 23:15:28 +01:00
mathuo
7f0786dd7a
feat: api changes 2022-04-28 21:41:36 +01:00
mathuo
15ccdfa3c0
feat: npm experimental publish script 2022-04-27 22:50:25 +01:00
mathuo
fe3d0b23bd
feat: additional group api 2022-04-27 22:32:21 +01:00
mathuo
083ca6a8fb
Merge pull request #86 from mathuo/85-enhance-public-interfaces
feat: simplify public api
2022-04-27 18:52:37 +01:00
mathuo
0a32c2ed89
feat: simplify public api 2022-04-27 18:36:48 +01:00
mathuo
0987e92676
feat: docs website 2022-04-25 22:13:44 +01:00
mathuo
bbf59bd311
chore(release): publish v1.3.0 2022-04-24 15:11:57 +01:00
mathuo
aa579c4e32
Merge pull request #83 from mathuo/82-fix-watermark-component
fix watermark
2022-04-24 13:22:57 +01:00
mathuo
666df6b7a9
fix watermark 2022-04-24 13:12:00 +01:00
mathuo
4df08e0661
Merge pull request #81 from mathuo/77-fix-sonar-code-smells-from-new-rule
chore: fix sonar code smells
2022-04-24 11:34:18 +01:00
mathuo
5c61854ba4
chore: fix sonar code smells 2022-04-24 11:33:56 +01:00
mathuo
f852f2f97c
Merge pull request #78 from mathuo/77-fix-sonar-code-smells-from-new-rule
chore: fix sonar code smells
2022-04-24 11:28:03 +01:00
mathuo
306a54a5b4
chore: fix sonar code smells 2022-04-24 11:23:02 +01:00
mathuo
979cb9aa5c
Merge pull request #76 from mathuo/73-use-more-react-18-friendly-code
feat: react 18
2022-04-24 11:22:19 +01:00
mathuo
3ddbd1bc85
feat: react 18 2022-04-24 11:07:52 +01:00
mathuo
8cec47ef81
Merge pull request #75 from mathuo/73-use-more-react-18-friendly-code
Revert "feat: usestate over useref"
2022-04-23 23:42:14 +01:00
mathuo
944725d5e8
Revert "feat: usestate over useref"
This reverts commit 077bacbc27.
2022-04-23 23:41:44 +01:00
mathuo
1aa215676d
Merge pull request #74 from mathuo/73-use-more-react-18-friendly-code
feat: usestate over useref
2022-04-23 23:27:20 +01:00
mathuo
077bacbc27
feat: usestate over useref 2022-04-23 23:25:59 +01:00
mathuo
8b8c0fd79b
Merge pull request #72 from mathuo/71-dockview-panel-disposal
work in progress
2022-04-23 23:01:53 +01:00
mathuo
a40ce0d428
feat: dispose of view panels correctly 2022-04-23 23:01:34 +01:00
mathuo
ec7116fbf1
Merge pull request #70 from mathuo/69-dockview-error-on-duplicate-panel-id
feat: error in duplicate id
2022-04-23 22:56:16 +01:00
mathuo
2f8abd0e11
feat: error in duplicate id 2022-04-23 21:19:35 +01:00
mathuo
9c75701182
Delete packages/dockview-docs directory 2022-04-23 17:25:46 +01:00
mathuo
2dc0c4ab21
chore(release): publish v1.2.0 2022-04-23 16:44:39 +01:00
mathuo
a2c269dbd4
Merge pull request #68 from mathuo/51-expose-params-item-on-panel-interfaces
chore: fix demo
2022-04-23 16:38:58 +01:00
mathuo
3c7781d945
chore: fix demo 2022-04-23 16:37:10 +01:00
mathuo
7071cf7b72
Merge pull request #52 from mathuo/51-expose-params-item-on-panel-interfaces
feat: expose params object
2022-04-23 10:32:44 +01:00
mathuo
f24a3239a3
Merge pull request #67 from mathuo/20-enhance-public-api
chore: fix demo
2022-04-23 10:28:11 +01:00
mathuo
557621aa83
expose params object for dockview panels 2022-04-23 10:27:52 +01:00
mathuo
14b222a138
chore: fix demo 2022-04-23 09:58:23 +01:00
mathuo
2e051f6690
Merge pull request #66 from mathuo/20-enhance-public-api
chore: fix demo
2022-04-22 22:34:32 +01:00
mathuo
203c532f87
chore: fix demo 2022-04-22 22:18:38 +01:00
mathuo
5c0d4124bc
Merge pull request #65 from mathuo/64-ensure-elements-are-removed-on-dispose
feat: cleanup components on dispose
2022-04-22 22:11:55 +01:00
mathuo
cc406fce17
Merge pull request #63 from mathuo/20-enhance-public-api
chore: fix demo
2022-04-22 22:07:53 +01:00
mathuo
dc4a90a5ce
feat: cleanup components on dispose 2022-04-22 22:07:32 +01:00
mathuo
994ffcafd0
chore: fix demo 2022-04-22 21:51:20 +01:00
mathuo
b1e89e92e3
Merge pull request #59 from mathuo/58-improve-dockview-events
feat: improve remove group events
2022-04-21 21:29:06 +01:00
mathuo
c499a6b11f
Merge pull request #62 from mathuo/20-enhance-public-api
reduce public api
2022-04-21 21:27:08 +01:00
mathuo
98e0ac340f
Merge pull request #61 from mathuo/60-adjust-droptarget-css
feat: adjust css to use transform methods
2022-04-21 21:24:14 +01:00
mathuo
f6bc266e1d
feat: improve remove group events 2022-04-21 21:24:01 +01:00
mathuo
5b11d316d0
Merge pull request #57 from mathuo/56-fix-layout-issues
feat: fixes to layout w/tests
2022-04-21 21:20:54 +01:00
mathuo
d2404f679b
reduce public api 2022-04-21 21:20:36 +01:00
mathuo
dd03d44d2a
feat: adjust css to use transform methods 2022-04-21 21:17:57 +01:00
mathuo
19005f948d
feat: fixes to layout w/tests 2022-04-20 21:32:23 +01:00
mathuo
6a1d2757f0
Merge pull request #55 from mathuo/53-update-project-dependencies
chore: update dependencies
2022-04-19 23:22:25 +01:00
mathuo
168b090502
chore: update dependencies 2022-04-18 22:41:38 +01:00
mathuo
4b1e94fcdf
Merge pull request #54 from mathuo/53-update-project-dependencies
chore: update project dependencies
2022-04-15 21:54:53 +01:00
mathuo
be55cd7b0e
chore: update project dependencies 2022-04-15 21:48:42 +01:00
mathuo
58bfcef222
Merge pull request #44 from mathuo/43-remove-circular-import
fix: remove circular import
2022-03-17 22:34:14 +00:00
mathuo
0c41630b29
fix: remove circular import 2022-03-17 21:32:02 +00:00
mathuo
4fbc0fd5e7
Merge pull request #46 from mathuo/45-update-project-dependencies
chore: update project dependencies
2022-03-17 21:31:19 +00:00
mathuo
074fefc59e
chore: update project dependencies 2022-03-17 20:41:03 +00:00
mathuo
1816476fbb
chore(release): publish v1.1.0 2022-03-17 20:32:07 +00:00
mathuo
28a149b924
Merge branch 'master' of https://github.com/mathuo/dockview into master 2022-03-17 20:28:21 +00:00
mathuo
cca7b57dae
Merge pull request #42 from mathuo/40-improved-events-for-dockview
feat: add event
2022-03-17 20:26:49 +00:00
mathuo
87eb58d49f
feat: add event 2022-03-17 20:22:25 +00:00
mathuo
317957c26f
Merge branch 'master' of https://github.com/mathuo/dockview into master 2022-03-17 20:04:41 +00:00
mathuo
b14443c009
Merge pull request #39 from mathuo/38-remove-panels-cache-in-dockview
feat: remove panels caching layer
2022-03-17 19:40:03 +00:00
mathuo
3acfdc8ccc
Merge pull request #41 from mathuo/40-improved-events-for-dockview
feat: improve events
2022-03-17 19:19:53 +00:00
mathuo
6b60712943
fix: remove sonar code smell 2022-03-17 19:19:26 +00:00
mathuo
6a1b4bee8c
chore: include es2019 lib 2022-03-17 19:14:36 +00:00
mathuo
85093617d1
feat: improve events 2022-03-17 19:14:14 +00:00
mathuo
8484db6968
feat: remove panels caching layer
caching layer is not required, just read panels directly from the group
models
2022-03-17 19:05:15 +00:00
mathuo
8a9f00169e
Merge pull request #37 from mathuo/23-increase-test-coverage
chore: reduce function complexities
2022-03-14 22:29:05 +00:00
mathuo
16ea522ee9
chore: reduce function complexities 2022-03-14 22:24:41 +00:00
mathuo
39eb6a3e25
Merge pull request #36 from mathuo/35-dockview-fromjson-fix
feat: adjust fromJSON logic
2022-03-14 21:56:28 +00:00
mathuo
ae15e4e897
chore: update readme 2022-03-14 21:56:18 +00:00
mathuo
cb64522757
feat: adjust fromJSON logic 2022-03-14 21:50:10 +00:00
mathuo
99fff495f6
Merge pull request #34 from mathuo/32-add-group-events-on-grouppanelapi
test: add test
2022-03-14 20:14:08 +00:00
mathuo
e21ca56092
chore: update readme 2022-03-14 20:08:59 +00:00
mathuo
6642bcb430
chore: update demo 2022-03-14 20:05:30 +00:00
mathuo
2a58771a17
test: add test 2022-03-14 20:05:02 +00:00
mathuo
3d970f51ea
Merge branch 'master' of https://github.com/mathuo/dockview into master 2022-03-14 20:03:56 +00:00
mathuo
e487c80315
Merge pull request #33 from mathuo/32-add-group-events-on-grouppanelapi
32 add group events on grouppanelapi
2022-03-14 20:03:52 +00:00
mathuo
4f4d21d9dc
Merge branch 'master' of https://github.com/mathuo/dockview into master 2022-03-14 20:03:26 +00:00
mathuo
7b01e59622
feat: update demo 2022-03-14 20:03:21 +00:00
mathuo
88b871af25
feat: minor style and Type fixes 2022-03-14 19:57:11 +00:00
mathuo
c3f1bda881
feat: add group active events 2022-03-14 19:52:52 +00:00
mathuo
2e7711486b
Merge pull request #31 from mathuo/23-increase-test-coverage
chore: reduce sonar smells
2022-03-12 22:33:17 +00:00
mathuo
486c1546fb
chore: reduce sonar smells 2022-03-12 22:25:26 +00:00
mathuo
ce46422347
Merge pull request #30 from mathuo/23-increase-test-coverage
tests: add tests
2022-03-12 21:44:36 +00:00
mathuo
7a189091bb
chore: remove unused code 2022-03-12 21:35:35 +00:00
mathuo
9608ec957d
tests: add tests 2022-03-12 21:32:43 +00:00
mathuo
0d9abc4937
Merge pull request #29 from mathuo/23-increase-test-coverage
tests: add tests
2022-03-11 22:42:23 +00:00
mathuo
e8a7157d45
tests: add tests 2022-03-11 22:27:29 +00:00
mathuo
b43a4b9d06
Merge pull request #28 from mathuo/20-enhance-public-api
20 enhance public api
2022-03-11 21:37:08 +00:00
mathuo
f55b64a215
Merge branch 'master' of https://github.com/mathuo/dockview into 20-enhance-public-api 2022-03-11 21:30:15 +00:00
mathuo
e520a25ef0
feat: synchronous close panel functions 2022-03-11 21:20:48 +00:00
mathuo
cd33a753d6
Merge pull request #27 from mathuo/23-increase-test-coverage
feat: dispose of event listeners
2022-03-10 22:43:15 +00:00
mathuo
b42d8f9852
feat: dispose of event listeners 2022-03-10 22:37:42 +00:00
mathuo
181c5f0a2b
Merge pull request #25 from mathuo/20-enhance-public-api
feat: reintroduce panel.update(..) to public api
2022-03-10 22:15:31 +00:00
mathuo
cc60d3b129
Merge pull request #26 from mathuo/23-increase-test-coverage
chore: refactor to use existing code
2022-03-10 22:15:21 +00:00
mathuo
9ae54bd779
chore: refactor to use existing code 2022-03-10 22:09:50 +00:00
mathuo
a637ca714b
temp 2022-03-10 22:06:55 +00:00
mathuo
26f2908b39
feat: reintroduce panel.update(..) to public api 2022-03-10 22:04:15 +00:00
mathuo
ff88de0395
Merge pull request #24 from mathuo/23-increase-test-coverage
chore: increase test coverage and delete unused code
2022-03-10 21:12:04 +00:00
mathuo
943ea3b93e
chore: add tests 2022-03-10 20:59:47 +00:00
mathuo
fe8845631d
chore: increase test coverage and delete unused code 2022-03-10 20:53:49 +00:00
mathuo
aa3f8430a8
Merge pull request #22 from mathuo/20-enhance-public-api
20 enhance public api
2022-03-10 20:12:16 +00:00
mathuo
e1d42c22c1
chore: fix demo 2022-03-10 20:06:17 +00:00
mathuo
58083bb6a9
feat: remove obsolete functionality
IGroupPanel
- remove setDirty(isDirty: boolean): void

PanelApi
- remove onDidStateChange: Event<void>
- remove setState(key: string, value: StateObject): void
- remove setState(state: State): void
- remove getState(): State
- remove getStateKey: <T extends StateObject>(key:string) => T
2022-03-10 20:06:12 +00:00
mathuo
87110574b6
Merge pull request #21 from mathuo/20-enhance-public-api
feat: api enhancements
2022-03-08 22:07:32 +00:00
mathuo
4a34374fd8
feat: api enhancements
- reduce scope of public api
- expose params field on panel api
2022-03-08 22:01:42 +00:00
mathuo
494def7d3a
Merge pull request #19 from mathuo/Groupview-Custom-drop-handler-#18
feat: dockview custom dnd events
2022-03-08 21:59:02 +00:00
mathuo
e4b6c2e7cd
chore: update readme 2022-02-22 22:08:40 +00:00
mathuo
d180320b19
chore: remove comment 2022-02-22 22:04:58 +00:00
mathuo
38fa8f2f6e
chore: update readme 2022-02-22 22:03:49 +00:00
mathuo
c9eb954de8
feat: dockview custom dnd events
- remove old flag for external dnd events
- add methods onDidDrop and showDndOverlay to allow interaction with
  custom dnd events
2022-02-22 21:58:34 +00:00
mathuo
0b05115733
chore(release): publish v1.0.3 2022-02-22 21:13:05 +00:00
mathuo
67b4b2502f
feat: Improve onDidAdd/onDidRemove events for pane/splitview 2022-02-22 21:10:06 +00:00
mathuo
6ba8015502
chore(release): publish v1.0.2 2022-02-22 20:14:56 +00:00
mathuo
e0bcecfac0
fix: fix demo project after breaking change 2022-02-22 20:05:08 +00:00
mathuo
5dbbdce43c
chore: update dependencies 2022-02-22 20:04:46 +00:00
mathuo
4ef8049413
feat: expose additional events 2022-02-22 19:53:46 +00:00
mathuo
3dbe00d2a1
feat: rename event to nativeEvent to avoid event.event calls 2022-02-22 19:49:58 +00:00
mathuo
929690e730
feat: fix sonar bugs 2022-02-16 20:59:28 +00:00
mathuo
8f49d29bdb
chore(release): publish v1.0.1 2022-02-16 20:36:38 +00:00
mathuo
5264ecf506
fix: react peer dependency version 2022-02-16 20:28:31 +00:00
mathuo
8b236c9c0d
feat: update dependencies 2022-02-16 20:27:56 +00:00
mathuo
60d49fde61
feat: remove footnote 2022-02-16 20:25:24 +00:00
mathuo
647945debc
feat: components prop changes are propagated 2022-02-16 20:22:14 +00:00
mathuo
017e6856f9
feat: improve types 2022-02-16 20:21:04 +00:00
mathuo
5c2a0cf93d
chore(release): publish v1.0.0 2021-12-18 16:11:53 +00:00
mathuo
aca9ae670f
chore: update dependencies 2021-12-18 16:11:26 +00:00
mathuo
699a1fb8bb
feat: export additional types 2021-12-18 16:02:57 +00:00
mathuo
6aff4d1709
Merge branch 'master' of https://github.com/mathuo/dockview into master 2021-11-29 20:49:31 +00:00
mathuo
af8f6e2f25
chore: update README 2021-11-29 20:49:01 +00:00
mathuo
d4079cdf4c
chore(release): publish v0.0.28 2021-11-19 22:00:02 +00:00
mathuo
2faf43ef80
chore: fix sonar code smells 2021-11-16 22:11:25 +00:00
mathuo
760c28ff8c
chore: typo 2021-11-16 22:05:16 +00:00
mathuo
28ffd9f01b
chore: refactoring + removing unused code 2021-11-16 22:03:41 +00:00
mathuo
c989b80e00
chore: fix tests 2021-11-16 21:32:16 +00:00
mathuo
3b2214d6b6
feat: update component state before add/remove events 2021-11-16 21:25:57 +00:00
mathuo
367db9fa40
feat: improve types for react components registry 2021-11-14 22:17:32 +00:00
mathuo
bcb16f0fc4
chore: update README 2021-10-31 21:29:07 +00:00
mathuo
f1ec5dfe4f
chore: enhance demo 2021-10-31 21:24:30 +00:00
mathuo
17f64bcc9e
chore: update README.md 2021-10-25 22:06:11 +01:00
mathuo
a15a646e11
chore: remove code 2021-10-25 22:05:22 +01:00
mathuo
f713f6385d
chore: update README and cleanup 2021-10-25 21:56:58 +01:00
mathuo
8c6f7db665
chore: fix imports 2021-10-25 21:34:09 +01:00
mathuo
fb593231d9
chore(release): publish v0.0.27 2021-10-25 21:29:46 +01:00
mathuo
cfb1b5c38b
Merge branch 'master' of https://github.com/mathuo/dockview into master 2021-10-25 21:22:10 +01:00
mathuo
ecbf0f7fc7
feat: improve layout events 2021-10-25 21:21:48 +01:00
mathuo
0f85c093f9
feat: remove global focus tracking 2021-10-24 17:41:09 +01:00
mathuo
c087dc1418
chore(release): publish v0.0.26 2021-10-24 17:08:17 +01:00
mathuo
b37b6775d1
Merge branch 'master' of https://github.com/mathuo/dockview 2021-10-24 17:07:12 +01:00
mathuo
0da044671f
feat: reduce .onDidDrop nesting and demo work 2021-10-24 17:05:34 +01:00
mathuo
dd81a1bbad
feat: update demo app 2021-10-20 23:23:43 +01:00
mathuo
3b35997b2f
feat: general cleanup 2021-10-20 23:19:20 +01:00
mathuo
ee22a08b2e
feat: further enhance view events 2021-10-20 23:17:46 +01:00
mathuo
0ef3df76f9
feat: enhance fired events 2021-10-19 18:38:19 +01:00
mathuo
005d802a99
chore(release): publish v0.0.25 2021-10-17 21:58:39 +01:00
mathuo
7c3343a431
Merge pull request #13 from mathuo/remove-circuluar-deps
feat: remove circular dependencies
2021-10-17 21:52:56 +01:00
mathuo
333c71ad09
feat: remove circular dependencies 2021-10-17 21:46:27 +01:00
mathuo
edbeeffd60 chore: tests 2021-10-16 20:38:13 +01:00
mathuo
725f364186 feat: don't fire events during toJSON() 2021-10-16 19:41:33 +01:00
mathuo
af88a17950 chore: remove log lines 2021-10-16 19:40:51 +01:00
mathuo
80856c4364 chore(release): publish v0.0.24 2021-10-14 17:55:58 +01:00
mathuo
72470acc3d test: fix test 2021-10-13 23:10:29 +01:00
mathuo
50aa22f3ff feat: improve draggable paneviews 2021-10-13 22:38:34 +01:00
mathuo
937e851d11 chore: fix typedoc setup 2021-10-13 17:14:52 +01:00
mathuo
e41d0ea64a
Merge pull request #11 from mathuo/tests
Tests
2021-10-10 16:31:50 +01:00
mathuo
569809f072 chore: fix sonar issues 2021-10-10 16:26:13 +01:00
mathuo
8cbeb2c531 test: add test 2021-10-10 16:18:43 +01:00
mathuo
b17019af08
Merge pull request #10 from mathuo/dependencies-update
Dependencies update
2021-10-10 14:47:37 +01:00
mathuo
3919fcf6c5 chore: npm audit fix 2021-10-10 14:33:33 +01:00
mathuo
e41efe54fe chore: update dependencies 2021-10-10 14:31:22 +01:00
mathuo
5fccfb1db6 chore: jest setup 2021-10-10 14:25:37 +01:00
mathuo
596a0d8ee1 chore: updade CI node version to 16.x 2021-10-10 13:51:17 +01:00
mathuo
03c0e12181 chore: remove hoist 2021-10-10 13:34:17 +01:00
mathuo
8daaf2a248 chore: update dependencies 2021-10-10 12:43:09 +01:00
mathuo
1dc4e65073 chore: update webpack 2021-10-10 12:22:47 +01:00
mathuo
35b210cbd1 chore: audit fix 2021-10-10 12:17:59 +01:00
mathuo
5676bc4f8c chore: update dependencies 2021-10-09 11:25:44 +01:00
mathuo
52de9080e4 Revert "chore: update dependencies"
This reverts commit 2b86f16b54.
2021-10-09 10:59:30 +01:00
mathuo
26177327a5 Merge branch 'master' of https://github.com/mathuo/dockview into master 2021-10-09 10:09:46 +01:00
mathuo
2b86f16b54 chore: update dependencies 2021-10-09 10:09:42 +01:00
mathuo
b234599172 feat: unify component api methods 2021-10-07 22:09:45 +01:00
mathuo
e339a48c38 feat: expose additional methods 2021-10-07 21:51:19 +01:00
mathuo
6b52a9f24e
Merge pull request #8 from mathuo/dnd-improvements
feat: expose dnd functions
2021-10-07 21:45:49 +01:00
mathuo
29771cace1 feat: draggable panels work 2021-10-04 20:51:38 +01:00
mathuo
28685f679a chore: eslint setup 2021-10-04 20:22:05 +01:00
mathuo
b0cf543d44 Merge branch 'dnd-improvements' of https://github.com/mathuo/dockview into dnd-improvements 2021-10-02 12:19:40 +01:00
mathuo
db390583d7 test: fix tests 2021-10-02 12:14:16 +01:00
mathuo
c140b560fe feat: expose dnd functions 2021-08-23 22:05:16 +01:00
mathuo
c51597fde3 feat: expose dnd functions 2021-08-23 20:53:39 +01:00
mathuo
7ec824ea01 chore(release): publish v0.0.23 2021-07-14 20:33:37 +01:00
mathuo
bce106217a
Merge pull request #7 from mathuo/refactor-dnd
work in progress
2021-07-14 20:32:23 +01:00
mathuo
adf09a1a25 work in progress 2021-07-09 21:57:09 +01:00
mathuo
529bbed42f chore(release): publish v0.0.22 2021-07-02 21:04:19 +01:00
mathuo
c94987d88c chore: reduce codeql job frequency 2021-06-21 21:11:03 +01:00
mathuo
29f6775af6 feat: flip orientation and component options dynamically 2021-06-21 21:07:24 +01:00
mathuo
c7090b5301 chore(release): publish v0.0.21 2021-06-16 22:32:51 +01:00
mathuo
c407929a03
Merge pull request #6 from mathuo/Title-change-bug
fix: set title and suppressclosable via panel api
2021-06-16 22:30:46 +01:00
mathuo
cd21c54f0b fix: set title and suppressclosable via panel api
feature was broken in a previous change, this fixes the change and adds
tests
2021-06-16 22:23:50 +01:00
mathuo
88d6026335 refactor: cleaner code 2021-06-08 22:29:44 +01:00
mathuo
374d59f2cb chore(release): publish v0.0.20 2021-06-07 18:33:01 +01:00
mathuo
850ce4f0aa fix: tests 2021-06-07 18:32:41 +01:00
mathuo
ccd8e7fdf5 feat: refactor dockview update logic 2021-06-07 18:13:04 +01:00
mathuo
3f93b34f73 fix: build script 2021-06-06 14:51:25 +01:00
mathuo
53b9b9368b chore(release): publish v0.0.19 2021-06-06 14:42:09 +01:00
mathuo
ecf592fee0 chore: update dependencies 2021-06-06 14:41:50 +01:00
mathuo
ef8c2efaa9 feat: rename css theme properties 2021-06-05 17:17:35 +01:00
mathuo
5555005de0 fix: tests 2021-06-05 16:20:12 +01:00
mathuo
d728ee8590 fix: custom params parsed as 'param' react prop 2021-06-05 15:55:28 +01:00
mathuo
907d7d5a12 chore: update pkg lock 2021-06-05 15:53:04 +01:00
mathuo
682faea308 chore: fix custom props params in demo 2021-06-03 22:31:11 +01:00
mathuo
68572e4f24 chore(release): publish v0.0.18 2021-06-03 21:32:01 +01:00
mathuo
23f1c58742 chore: update README 2021-06-03 21:27:53 +01:00
mathuo
c01290811e chore: update demo 2021-06-03 21:27:28 +01:00
mathuo
f40f96f840 feat: active sash background color 2021-06-03 21:26:54 +01:00
mathuo
f70e26c8ad chore: update pkg locks 2021-06-03 21:26:35 +01:00
mathuo
9060ff1a55 feat: extract custom react props into seperate prop variable 2021-06-03 21:24:06 +01:00
mathuo
2c02bed5d0 chore: update storybook 2021-04-11 22:08:09 +01:00
mathuo
59e2f25802 chore(release): publish v0.0.17 2021-04-11 20:22:56 +01:00
mathuo
184dc90544 refactor: rename public panel api objects 2021-04-11 13:28:53 +01:00
mathuo
46fa98fd8c bug: remove unwanted code 2021-04-10 22:03:14 +01:00
mathuo
92ae705dfb test: fix tests 2021-04-10 21:54:17 +01:00
mathuo
4442ca0caa feat: rename public panel api 2021-04-10 17:34:48 +01:00
mathuo
d04bbe5d9a chore: update demo 2021-04-10 17:27:58 +01:00
mathuo
ce28ad271b test: add test 2021-04-10 17:27:45 +01:00
mathuo
93a09b1b4f chore: credit sources 2021-04-10 17:26:40 +01:00
mathuo
c98121edd6 feat: expose .title and .suppressClosable values/events through api 2021-04-10 16:33:32 +01:00
mathuo
24c98c5830 fix: hide footnode in test environments 2021-04-10 16:32:41 +01:00
mathuo
ca70217b62 test: fix 2021-03-30 22:48:55 +01:00
mathuo
36f34f305c refactor: general code refactoring 2021-03-29 22:02:17 +01:00
mathuo
8646ea43d8 bug: min dimensions incorrectly set in dockview 2021-03-29 21:42:25 +01:00
mathuo
cabc4e901b feat: firebox thin scrollbars in tabs container 2021-03-29 21:41:57 +01:00
mathuo
e98eb96a2d test: react component init sizing 2021-03-29 21:10:54 +01:00
mathuo
cbeb197347 chore: update demo stories 2021-03-29 20:44:40 +01:00
mathuo
0533073e1d feat: init react views with container size 2021-03-29 20:44:03 +01:00
mathuo
cea4dcffc0 refactor: reduce code smells 2021-03-29 17:53:48 +01:00
mathuo
f368b3ea8e Merge branch 'master' of https://github.com/mathuo/dockview into master 2021-03-29 17:22:04 +01:00
mathuo
c6ddeb3c58 feat: primary/left click only to switch tabs 2021-03-29 17:21:55 +01:00
mathuo
b5de6c7e43 refactor: reduce code smells 2021-03-29 17:21:08 +01:00
mathuo
b70b914009 chore: update coverage badge 2021-03-28 23:02:52 +01:00
mathuo
2faa8512e6 chore(release): publish v0.0.16 2021-03-28 22:49:29 +01:00
mathuo
b24e6b225f chore: fix sonar setup 2021-03-28 22:30:06 +01:00
mathuo
581e5be904 chore: fix sonar setup 2021-03-28 22:19:22 +01:00
mathuo
85e8a6923d chore: fix sonar setup 2021-03-28 22:11:14 +01:00
mathuo
6e1e457e60 chore: fix sonar setup 2021-03-28 22:05:15 +01:00
mathuo
bc8d6fa30d chore: fix sonar setup 2021-03-28 21:58:50 +01:00
mathuo
3b140c140c chore: fix sonar setup 2021-03-28 21:45:31 +01:00
mathuo
b3b3d6836d chore: fix sonar setup 2021-03-28 21:27:09 +01:00
mathuo
bd9fe555b6 chore: fix sonar test integration 2021-03-28 21:14:10 +01:00
mathuo
02568345b6 chore: use jest sonar reporter 2021-03-28 20:54:43 +01:00
mathuo
0c6318c655 chore: enable test coverage for sonar 2021-03-28 20:39:01 +01:00
mathuo
ad9fd519ec chore: edit sonar config file 2021-03-28 18:40:26 +01:00
mathuo
650b1e253c chore: update sonarcloud config 2021-03-28 18:33:48 +01:00
mathuo
8a953f28c5 chore: rename file 2021-03-28 18:29:11 +01:00
mathuo
b678afe668 feat: add sonarcloud build 2021-03-28 18:28:59 +01:00
mathuo
233dee5bae chore: fix README 2021-03-28 18:23:45 +01:00
mathuo
f5530d316b chore: add sonarcloud config 2021-03-28 18:23:08 +01:00
mathuo
8378c368d5 refactor: rename packages to dockview* 2021-03-25 21:59:50 +00:00
mathuo
4ac7a56379 chore: adjust lerna publish message 2021-03-25 21:43:39 +00:00
mathuo
21e531c82c refactor: use encoded svg rather than remote svg 2021-03-25 21:43:23 +00:00
mathuo
62e568265e feat: forwardRef the React views 2021-03-25 21:42:54 +00:00
mathuo
9c547f90b6 refactor: reduce code smells 2021-03-24 21:40:21 +00:00
mathuo
7aaec28ebd v0.0.15 2021-03-24 21:08:16 +00:00
mathuo
03f3617c50 chore: preversion -> prepack 2021-03-24 21:07:56 +00:00
mathuo
606241c499 chore: typo 2021-03-24 21:01:51 +00:00
mathuo
de5faec9ec v0.0.14 2021-03-24 20:30:03 +00:00
mathuo
ee3f782d91 chore: add info banner to module bundles 2021-03-24 20:27:36 +00:00
mathuo
2631765972 refactor: housekeeping 2021-03-24 17:43:22 +00:00
mathuo
09c639c28f bug: panel remove event doesn't fire gridEvent 2021-03-24 17:42:52 +00:00
mathuo
822180e533 chore: rename scripts 2021-03-24 17:42:07 +00:00
mathuo
f0526ff278 bug: focus capturing on dockview panel not working 2021-03-24 17:41:07 +00:00
mathuo
43de915410 v0.0.13 2021-03-23 21:38:17 +00:00
mathuo
5da6a5e200 feat: configure action and tab react components from the primary panel component 2021-03-23 21:35:24 +00:00
mathuo
abbc5479bc chore: update package.json files 2021-03-23 17:35:50 +00:00
mathuo
50e252e840 feat: various module outputs using rollup 2021-03-23 17:31:56 +00:00
mathuo
fa903f1793 chore: update README 2021-03-22 23:39:17 +00:00
mathuo
c9c4ec28c3 refactor: unify react export to a single export line 2021-03-22 23:17:35 +00:00
mathuo
c91ab8617c refactor: change dist/styles.css to dist/styles/dockview.css 2021-03-22 23:16:47 +00:00
mathuo
65a8095e27 chore: storybook docs 2021-03-21 21:51:31 +00:00
mathuo
b7d1dad0da v0.0.12 2021-03-18 08:12:17 +00:00
mathuo
f877de7e98 bug: fix esm output 2021-03-18 08:10:28 +00:00
mathuo
7dafd633c2 chore: update storybook and lerna versions 2021-03-15 22:14:51 +00:00
mathuo
13bcef8672 chore: fix demo + update docs 2021-03-14 20:26:03 +00:00
mathuo
f341b01fea refactor: rename panel api objects 2021-03-14 19:59:24 +00:00
mathuo
85f53ffae9
Create LICENSE 2021-03-14 16:27:18 +00:00
mathuo
05334f1b5e v0.0.11 2021-03-14 16:18:40 +00:00
mathuo
72c111795f chore: fix build issues 2021-03-14 16:17:09 +00:00
mathuo
8205806be4 chore: fix build issues 2021-03-14 15:59:14 +00:00
mathuo
951050e000 docs: add footnote to console 2021-03-11 20:24:36 +00:00
mathuo
9b002ed595 chore: fix typedocs options file 2021-03-11 20:23:27 +00:00
mathuo
076ff7e1b5 style: size content of react watermark 2021-03-11 20:17:46 +00:00
mathuo
bf5d2962b5 chore: update storybook 2021-03-08 20:54:24 +00:00
mathuo
b508da1643 refactor: replace node-sass with sass (dart) 2021-03-07 22:06:28 +00:00
mathuo
6d3ef658e1 v0.0.10 2021-03-07 21:53:57 +00:00
mathuo
eb78bf26e7 refactor: update dependencies 2021-03-07 21:49:51 +00:00
mathuo
8538266928 refactor: remove console.log line 2021-03-07 21:28:48 +00:00
mathuo
87fb3497b4 v0.0.9 2021-02-10 21:59:59 +00:00
mathuo
e2a8053e94 feat: demo 2021-02-10 21:58:00 +00:00
mathuo
9ace22003c bug: initialize isExpanded api value 2021-02-10 21:57:47 +00:00
mathuo
748f284bcc bug: paneview persistance not updated on expansion of panel 2021-02-10 21:29:31 +00:00
mathuo
03134ed774 feat: add to storybook demos 2021-02-09 17:41:09 +00:00
mathuo
549e64422e v0.0.8 2021-02-09 17:29:15 +00:00
mathuo
8d56f06b72 refactor: better disposable of resources 2021-02-09 17:27:59 +00:00
mathuo
f82039aeda feat: Paneview serialization / deserialization 2021-02-09 11:20:32 +00:00
mathuo
2bf5dd60d8 refactor: remove log lines 2021-02-09 11:16:04 +00:00
mathuo
9cb46add24 refactor: rework dockview groups 2021-01-01 10:38:05 +00:00
mathuo
8564f7a9f5 refactor: rename css properties 2020-12-22 22:50:25 +00:00
mathuo
723299aac9 refactor: enable TypeScript strict-mode 2020-12-22 15:15:46 +00:00
mathuo
a3776e9d6c refactor: delete code 2020-12-21 21:40:28 +00:00
mathuo
21c623e8e8 refactor: remove code 2020-12-21 21:35:23 +00:00
mathuo
fb2c4cbea9 v0.0.7 2020-12-20 21:10:41 +00:00
mathuo
f6c4791f0c docs: demo + storybook 2020-12-20 21:09:23 +00:00
mathuo
fc7ef9226b v0.0.6 2020-12-20 20:34:22 +00:00
mathuo
64c24dca55 feat: autoresize views 2020-12-20 20:18:48 +00:00
mathuo
7d21f9f19e bug: panel not added to internal cache 2020-12-20 19:03:12 +00:00
mathuo
27b072ec5b bug: disable pointer events on iframes when resizing/dragging panels 2020-12-19 11:46:55 +00:00
982 changed files with 134923 additions and 49526 deletions

46
.codesandbox/ci.json Normal file
View File

@ -0,0 +1,46 @@
{
"packages": [
"packages/dockview-core",
"packages/dockview-vue",
"packages/dockview-react",
"packages/dockview"
],
"sandboxes": [
"/packages/docs/sandboxes/constraints-dockview",
"/packages/docs/sandboxes/customheader-dockview",
"/packages/docs/sandboxes/demo-dockview",
"/packages/docs/sandboxes/dnd-dockview",
"/packages/docs/sandboxes/dockview-app",
"/packages/docs/sandboxes/editor-gridview",
"/packages/docs/sandboxes/events-dockview",
"/packages/docs/sandboxes/externaldnd-dockview",
"/packages/docs/sandboxes/floatinggroup-dockview",
"/packages/docs/sandboxes/fullwidthtab-dockview",
"/packages/docs/sandboxes/headeractions-dockview",
"/packages/docs/sandboxes/groupcontol-dockview",
"/packages/docs/sandboxes/iframe-dockview",
"/packages/docs/sandboxes/keyboard-dockview",
"/packages/docs/sandboxes/layout-dockview",
"/packages/docs/sandboxes/lockedgroup-dockview",
"/packages/docs/sandboxes/maximizegroup-dockview",
"/packages/docs/sandboxes/nativeapp-dockview",
"/packages/docs/sandboxes/nested-dockview",
"/packages/docs/sandboxes/popoutgroup-dockview",
"/packages/docs/sandboxes/rendering-dockview",
"/packages/docs/sandboxes/rendermode-dockview",
"/packages/docs/sandboxes/resize-dockview",
"/packages/docs/sandboxes/resizecontainer-dockview",
"/packages/docs/sandboxes/scrollbars-dockview",
"/packages/docs/sandboxes/simple-dockview",
"/packages/docs/sandboxes/simple-gridview",
"/packages/docs/sandboxes/simple-paneview",
"/packages/docs/sandboxes/tabheight-dockview",
"/packages/docs/sandboxes/updatetitle-dockview",
"/packages/docs/sandboxes/watermark-dockview",
"/packages/docs/sandboxes/javascript/fullwidthtab-dockview",
"/packages/docs/sandboxes/javascript/simple-dockview",
"/packages/docs/sandboxes/javascript/tabheight-dockview",
"/packages/docs/sandboxes/javascript/vanilla-dockview"
],
"node": "18"
}

10
.editorconfig Normal file
View File

@ -0,0 +1,10 @@
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
quote_type = single

View File

@ -1,21 +0,0 @@
{
"parser": "@typescript-eslint/parser",
"plugins": [
"@typescript-eslint"
],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended"
],
"rules": {
"no-case-declarations":"off",
"@typescript-eslint/no-namespace": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-unused-vars": "off",
"@typescript-eslint/ban-types": "off",
"@typescript-eslint/no-empty-interface": "off",
"@typescript-eslint/no-non-null-assertion":"off"
}
}

19
.eslintrc.js Normal file
View File

@ -0,0 +1,19 @@
module.exports = {
root: true,
parserOptions: {
sourceType: 'module',
project: ['./tsconfig.eslint.json', './packages/*/tsconfig.json'],
tsconfigRootDir: __dirname,
},
plugins: ['@typescript-eslint'],
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'],
rules: {
'no-case-declarations': 'off',
'@typescript-eslint/no-namespace': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-unused-vars': 'off',
'@typescript-eslint/ban-types': 'off',
'@typescript-eslint/no-non-null-assertion': 'off',
},
};

33
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,33 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
[dockview.dev](https://dockview.dev) provides a number of examples with Code Sandbox templates. Are you able to produce the bug by forking one of those templates? Sharing a link to the forked sandbox with the bug would be extremely helpful.
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

View File

@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@ -3,60 +3,60 @@
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
name: "CodeQL"
name: 'CodeQL'
on:
push:
branches: [master]
pull_request:
# The branches below must be a subset of the branches above
branches: [master]
schedule:
- cron: '0 4 * * 1'
# push:
# branches: [master]
# pull_request:
# # The branches below must be a subset of the branches above
# branches: [master]
schedule:
- cron: '0 4 * * *'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
analyze:
name: Analyze
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# Override automatic language detection by changing the below list
# Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
language: ['javascript']
# Learn more...
# https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
strategy:
fail-fast: false
matrix:
# Override automatic language detection by changing the below list
# Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
language: ['javascript']
# Learn more...
# https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
steps:
- name: Checkout repository
uses: actions/checkout@v2
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v3
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3

46
.github/workflows/deploy-docs.yml vendored Normal file
View File

@ -0,0 +1,46 @@
name: Deploy Docs
on:
workflow_dispatch:
jobs:
deploy-nightly-demo-app:
runs-on: ubuntu-latest
steps:
- name: Checkout 🛎️
uses: actions/checkout@v4
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: '20.x'
- uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-node-
- run: yarn install
- run: npm run build
working-directory: packages/dockview-core
- run: npm run build
working-directory: packages/dockview
- run: npm run build
working-directory: packages/dockview-vue
- run: npm run build
working-directory: packages/dockview-react
- run: npm run build
working-directory: packages/docs
- run: npm run docs
working-directory: .
- run: npm run package-docs
working-directory: .
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@3.7.1
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH: gh-pages # The branch the action should deploy to.
FOLDER: build # The folder the action should deploy.
TARGET_FOLDER: .
CLEAN: true # Automatically remove deleted files from the deploy branch

View File

@ -1,40 +0,0 @@
name: Deploy Nightly Demo App
on:
schedule:
- cron: '0 3 * * *' # every day at 3 am UTC
jobs:
deploy-nightly-demo-app:
runs-on: ubuntu-latest
steps:
- name: Checkout 🛎️
uses: actions/checkout@v2.3.1 # If you're using actions/checkout@v2 you must set persist-credentials to false in most cases for the deployment to work correctly.
with:
persist-credentials: false
- name: Use Node.js
uses: actions/setup-node@v1
with:
node-version: '12.x'
- uses: actions/cache@v2
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- run: npm ci
- run: npm run bootstrap-no-hoist
- run: npm run build
- run: npm run test
- run: npm run package-all
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@3.7.1
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH: gh-pages # The branch the action should deploy to.
FOLDER: output # The folder the action should deploy.
TARGET_FOLDER: output
CLEAN: true # Automatically remove deleted files from the deploy branch

View File

@ -7,25 +7,27 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
# might be required for sonar to work correctly
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Use Node.js
uses: actions/setup-node@v1
uses: actions/setup-node@v4
with:
node-version: '12.x'
node-version: '20.x'
- uses: actions/cache@v2
- uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- run: npm ci
- run: npm run bootstrap
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-node-
- run: yarn
- run: npm run build
- run: npm run test-cov
- run: npm run codecov-publish
- run: npm run test:cov
- name: SonarCloud Scan
uses: sonarsource/sonarqube-scan-action@v5
env:
CI: true
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

78
.github/workflows/publish.yml vendored Normal file
View File

@ -0,0 +1,78 @@
name: Publish to npm
env:
NPM_CONFIG_PROVENANCE: true
on:
workflow_dispatch:
release:
types: [published]
jobs:
publish:
if: github.event_name == 'release'
runs-on: ubuntu-latest
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
permissions:
id-token: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20.x'
registry-url: 'https://registry.npmjs.org'
- uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-node-
- run: yarn
- name: Publish dockview-core
run: npm publish --provenance
working-directory: packages/dockview-core
- name: Publish dockview
run: npm publish --provenance
working-directory: packages/dockview
- name: Publish dockview-vue
run: npm publish --provenance
working-directory: packages/dockview-vue
- name: Publish dockview-react
run: npm publish --provenance
working-directory: packages/dockview-react
publish-experimental:
if: github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
permissions:
id-token: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20.x'
registry-url: 'https://registry.npmjs.org'
- uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-node-
- run: yarn
- run: npm run set-experimental-versions
- name: Publish dockview-core
run: npm publish --provenance --tag experimental
working-directory: packages/dockview-core
- name: Publish dockview
run: npm publish --provenance --tag experimental
working-directory: packages/dockview
- name: Publish dockview-vue
run: npm publish --provenance --tag experimental
working-directory: packages/dockview-vue
- name: Publish dockview-react
run: npm publish --provenance --tag experimental
working-directory: packages/dockview-react

9
.gitignore vendored
View File

@ -7,4 +7,11 @@ typedocs/
.DS_Store
*-debug.log
.build
storybook-static/
storybook-static/
.rollup.cache/
test-report.xml
*.code-workspace
yarn-error.log
/build
/docs/
/generated/

View File

@ -3,7 +3,13 @@
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
// List of extensions which should be recommended for users of this workspace.
"recommendations": ["esbenp.prettier-vscode", "redhat.vscode-yaml"],
"recommendations": [
"esbenp.prettier-vscode",
"redhat.vscode-yaml",
"dbaeumer.vscode-eslint",
"editorconfig.editorconfig",
"vue.volar"
],
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
"unwantedRecommendations": []
}

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 mathuo
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

103
README.md
View File

@ -1,97 +1,38 @@
<div align="center">
<h1>dockview</h1>
<p>Zero dependency layout manager supporting tabs, grids and splitviews with ReactJS support</p>
<p>Zero dependency layout manager supporting tabs, groups, grids and splitviews. Supports React, Vue and Vanilla TypeScript</p>
</div>
---
![stability-experimental](https://img.shields.io/badge/stability-experimental-orange.svg)
[![npm version](https://badge.fury.io/js/dockview.svg)](https://www.npmjs.com/package/dockview)
[![npm version](https://badge.fury.io/js/dockview-core.svg)](https://www.npmjs.com/package/dockview-core)
[![npm](https://img.shields.io/npm/dm/dockview-core)](https://www.npmjs.com/package/dockview-core)
[![CI Build](https://github.com/mathuo/dockview/workflows/CI/badge.svg)](https://github.com/mathuo/dockview/actions?query=workflow%3ACI)
[![codecov](https://codecov.io/gh/mathuo/dockview/branch/master/graph/badge.svg?token=BF083TK64H)](https://codecov.io/gh/mathuo/dockview/branch/master)
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=mathuo_dockview&metric=coverage)](https://sonarcloud.io/summary/overall?id=mathuo_dockview)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=mathuo_dockview&metric=alert_status)](https://sonarcloud.io/summary/overall?id=mathuo_dockview)
[![Bundle Phobia](https://badgen.net/bundlephobia/minzip/dockview-core)](https://bundlephobia.com/result?p=dockview-core)
##
A zero dependency layout manager based on the layering of split-view components with ReactJS support.
- View the live demo [here](https://mathuo.github.io/dockview/).
- Storybook demo [here](https://mathuo.github.io/dockview/output/storybook-static).
- Automatically generated TypeDocs can be found [here](https://mathuo.github.io/dockview/output/docs/index.html).
![](packages/docs/static/img/splashscreen.gif)
## Installation
You can install the project from [npm](https://www.npmjs.com/package/dockview). The project comes with TypeScript typings.
Please see the website: https://dockview.dev
```bash
npm install --save dockview
```
## Features
## Configuration
- Serialization / deserialization with full layout management
- Support for split-views, grid-views and 'dockable' views
- Themeable and customizable
- Tab and Group docking / Drag n' Drop
- Popout Windows
- Floating Groups
- Extensive API
- Supports Shadow DOMs
- High test coverage
- Documentation website with live examples
- Transparent builds and Code Analysis
- Security at mind - verifed publishing and builds through GitHub Actions
You must import the core css stylesheet but you are free to supply your own theming in addition to the core stylesheet. The location to reference for the stylesheet is
```
dockview/dist/styles.css
```
By default the seperator between panels is `transparent` but this can be set through the CSS varibable `--separator-border`. Alternatively, or if you require the `DockviewReact` you should attach the classname of an included theme; either `dockview-theme-dark` or `dockview-theme-light`.
### Sandbox examples
- [Dockview](https://codesandbox.io/s/simple-dockview-t6491)
- [Gridview](https://codesandbox.io/s/simple-gridview-jrp0n)
- [Splitview](https://codesandbox.io/s/simple-splitview-l53nn)
- [Paneview](https://codesandbox.io/s/simple-paneview-v8qvb)
## React
### Splitview
```javascript
import {
ISplitviewPanelProps,
Orientation,
SplitviewReact,
SplitviewReadyEvent
} from "dockview";
const components = {
"my-component": (props: ISplitviewPanelProps) => {
return (
<div>
<span>This is a panel</span>
<span>{props.arbitraryProp}</span>
</div>
)
}
}
const Example = () => {
const onReady = (event: SplitviewReadyEvent) => {
event.addPanel({
id: "panel-1",
component: "my-component",
params: {
arbitraryProp: "Hello World"
}
});
event.addPanel({
id: "panel-2",
component: "my-component",
params: {
arbitraryProp: "World Hello"
}
});
}
return (
<SplitviewReact
components={components}
onReady={onReady}
orientation={Orientation.VERTICAL}
/>
)
}
```
## Run the demo locally
Want to verify our builds? Go [here](https://www.npmjs.com/package/dockview#user-content-provenance).

8
SECURITY.md Normal file
View File

@ -0,0 +1,8 @@
# Reporting a Vulnerability
- Dockview is an entirely open source project.
- All build and publication scripts use public Github Action files found [here](https://github.com/mathuo/dockview/tree/master/.github/workflows).
- All npm publications are verified through the use of [provenance statements](https://docs.npmjs.com/generating-provenance-statements/).
- All builds are scanned with SonarCube and outputs can be found [here](https://sonarcloud.io/summary/overall?id=mathuo_dockview).
If you believe you have found a security or vulnerability issue please send a complete example to github.mathuo@gmail.com where it will be investigated.

1
jest-setup.ts Normal file
View File

@ -0,0 +1 @@
import '@testing-library/jest-dom';

View File

@ -1,20 +0,0 @@
const {join, normalize} = require("path");
const tsconfig = normalize(join(__dirname, "tsconfig.test.json"))
module.exports = {
displayName: { name: "root" },
preset: "ts-jest",
projects: ["<rootDir>/packages/*/jest.config.js"],
transform: {
"^.+\\.tsx?$":"ts-jest"
},
moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json"],
globals: {
"ts-jest": {
tsconfig,
experimental: true,
compilerHost: true
}
}
}

View File

@ -1,16 +0,0 @@
const baseConfig = require("./jest.config.base");
module.exports = {
...baseConfig,
displayName: { name: "root", color: "blue" },
projects: ["<rootDir>/packages/*/jest.config.js"],
collectCoverage: true,
collectCoverageFrom:[
"<rootDir>/packages/*/src/**/*.{js,jsx,ts,tsx}",
],
coveragePathIgnorePatterns: [
"/node_modules/",
"<rootDir>packages/*/src/__tests__/",
],
coverageDirectory: "coverage"
};

17
jest.config.ts Normal file
View File

@ -0,0 +1,17 @@
import { JestConfigWithTsJest } from 'ts-jest';
const config: JestConfigWithTsJest = {
preset: 'ts-jest',
displayName: { name: 'root', color: 'blue' },
projects: ['<rootDir>/packages/*/jest.config.ts'],
collectCoverage: true,
collectCoverageFrom: ['<rootDir>/packages/*/src/**/*.{js,jsx,ts,tsx}'],
coveragePathIgnorePatterns: [
'/node_modules/',
'<rootDir>/packages/*/src/__tests__/',
],
coverageDirectory: 'coverage',
testResultsProcessor: 'jest-sonar-reporter',
};
export default config;

View File

@ -1,6 +1,12 @@
{
"packages": [
"packages/*"
],
"version": "0.0.5"
}
"packages": [
"packages/*"
],
"version": "4.2.4",
"npmClient": "yarn",
"command": {
"publish": {
"message": "chore(release): publish %s"
}
}
}

View File

@ -1,30 +0,0 @@
{
"compilerOptions": {
"module": "es6",
"declaration": true,
"target": "es5",
"moduleResolution": "node",
"esModuleInterop": true,
"downlevelIteration": true,
"incremental": true,
"noImplicitReturns": true,
"noImplicitAny": true,
"allowUnreachableCode": false,
"forceConsistentCasingInFileNames": true,
// "strict": true,
"strictBindCallApply": true, // pass
"alwaysStrict": true, // pass
"noImplicitThis": true, // pass
"strictFunctionTypes": true, // pass
"strictNullChecks": false,
"strictPropertyInitialization": false,
"lib": [
"ES2015",
"ES2016.Array.Include",
"ES2017.String",
"ES2018.Promise",
"DOM",
]
}
}

View File

@ -1,29 +0,0 @@
{
"compilerOptions": {
"module": "commonjs",
"declaration": true,
"target": "es5",
"esModuleInterop": true,
"downlevelIteration": true,
"incremental": true,
"sourceMap": true,
"noImplicitReturns": true,
"noImplicitAny": true,
"allowUnreachableCode": false,
"forceConsistentCasingInFileNames": true,
// "strict": true,
"strictBindCallApply": true, // pass
"alwaysStrict": true, // pass
"noImplicitThis": true, // pass
"strictFunctionTypes": true, // pass
"strictNullChecks": false,
"strictPropertyInitialization": false,
"lib": [
"ES2015",
"ES2016.Array.Include",
"ES2017.String",
"ES2018.Promise",
"DOM",
]
}
}

18027
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,61 +1,81 @@
{
"name": "splitview-root",
"private": true,
"description": "",
"main": "index.js",
"scripts": {
"test": "jest",
"lint": "eslint packages/**/src/** --ext .ts,.tsx,.js,.jsx",
"package": "node scripts/package.js",
"package-all": "npm run build-demo && npm run docs && node scripts/package.js",
"build": "lerna run build --ignore splitview-demo",
"build-demo": "lerna run build --scope splitview-demo",
"docs": "lerna run docs --scope dockview",
"clean": "lerna run clean",
"bootstrap": "lerna bootstrap --hoist",
"bootstrap-no-hoist": "lerna bootstrap",
"test-cov": "jest --coverage",
"codecov-publish": "codecov",
"version-beta-build": "lerna version prerelease --preid beta",
"publish-app": "lerna publish"
},
"repository": {
"type": "git",
"url": "git+https://github.com/mathuo/dockview.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/mathuo/dockview/issues"
},
"homepage": "https://github.com/mathuo/dockview#readme",
"devDependencies": {
"@testing-library/dom": "^7.28.1",
"@types/jest": "^26.0.15",
"@typescript-eslint/eslint-plugin": "^4.8.1",
"@typescript-eslint/parser": "^4.8.1",
"codecov": "^3.8.1",
"cross-env": "^7.0.2",
"css-loader": "^3.6.0",
"eslint": "^7.14.0",
"fs-extra": "^9.0.1",
"gulp": "^4.0.2",
"gulp-concat": "^2.6.1",
"gulp-sass": "^4.1.0",
"jest": "^26.6.3",
"jsdom": "^16.4.0",
"lerna": "^3.22.1",
"merge2": "^1.4.1",
"node-sass": "^4.14.1",
"rimraf": "^3.0.2",
"sass-loader": "^8.0.2",
"style-loader": "^1.3.0",
"ts-jest": "^26.4.4",
"ts-loader": "^7.0.5",
"typescript": "^4.1.2",
"webpack": "^5.6.0",
"webpack-cli": "^4.2.0",
"webpack-dev-server": "^3.11.0"
},
"dependencies": {}
"name": "dockview-monorepo-root",
"private": true,
"description": "Monorepo for https://github.com/mathuo/dockview",
"homepage": "https://github.com/mathuo/dockview#readme",
"bugs": {
"url": "https://github.com/mathuo/dockview/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/mathuo/dockview.git"
},
"license": "MIT",
"author": "https://github.com/mathuo",
"workspaces": [
"packages/*"
],
"scripts": {
"build": "lerna run build --scope '{dockview-core,dockview,dockview-vue,dockview-react}'",
"clean": "lerna run clean",
"docs": "typedoc",
"generate-docs": "node scripts/docs.mjs",
"lint": "eslint packages/**/src/** --ext .ts,.tsx,.js,.jsx",
"package": "node scripts/package.js",
"package-docs": "node scripts/package-docs.js",
"set-experimental-versions": "node scripts/set-experimental-versions",
"test": "jest",
"test:cov": "jest --coverage",
"version": "lerna version"
},
"resolutions": {
"@types/react": "^18.2.46",
"@types/react-dom": "^18.2.18"
},
"devDependencies": {
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-terser": "^0.4.4",
"@rollup/plugin-typescript": "^11.1.5",
"@testing-library/dom": "^9.3.3",
"@testing-library/jest-dom": "^6.1.6",
"@testing-library/react": "^14.1.2",
"@total-typescript/shoehorn": "^0.1.1",
"@types/jest": "^29.5.11",
"@types/react": "^18.2.46",
"@types/react-dom": "^18.2.18",
"@typescript-eslint/eslint-plugin": "^6.17.0",
"@typescript-eslint/parser": "^6.17.0",
"@vitejs/plugin-vue": "^5.0.4",
"@vue/tsconfig": "^0.5.1",
"concurrently": "^8.2.2",
"cross-env": "^7.0.3",
"eslint": "^8.56.0",
"fs-extra": "^11.2.0",
"gulp": "^4.0.2",
"gulp-concat": "^2.6.1",
"gulp-dart-sass": "^1.1.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"jest-sonar-reporter": "^2.0.0",
"jsdom": "^23.0.1",
"lerna": "^8.2.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"rimraf": "^5.0.5",
"rollup": "^4.9.2",
"rollup-plugin-postcss": "^4.0.2",
"ts-jest": "^29.1.1",
"ts-loader": "^9.5.1",
"ts-node": "^10.9.2",
"tslib": "^2.6.2",
"typedoc": "^0.25.6",
"typescript": "^5.3.3",
"vite": "^5.1.5",
"vue": "^3.4.21",
"vue-sfc-loader": "^0.1.0",
"vue-tsc": "^2.0.5"
},
"engines": {
"node": ">=18.0"
}
}

18
packages/README.md Normal file
View File

@ -0,0 +1,18 @@
# Project Structure
This mono-repository has a number of packages containing the code for the [dockview](https://www.npmjs.com/package/dockview) library and the documentation website [dockview.dev](dockview.dev).
## dockview-core
- Contains the core logic for the dockview library.
- Written entirely in vanilla JavaScript/TypeScript.
## dockview
- Depends on `dockview-core`.
- Exports a `React` wrapper.
- Published as [dockview](https://www.npmjs.com/package/dockview) on npm.
## docs
- Code for [dockview.dev](dockview.dev).

View File

@ -0,0 +1,56 @@
<div align="center">
<h1>dockview</h1>
<p>Zero dependency layout manager supporting tabs, groups, grids and splitviews with ReactJS support written in TypeScript</p>
</div>
---
[![npm version](https://badge.fury.io/js/dockview.svg)](https://www.npmjs.com/package/dockview)
[![npm](https://img.shields.io/npm/dm/dockview)](https://www.npmjs.com/package/dockview)
[![CI Build](https://github.com/mathuo/dockview/workflows/CI/badge.svg)](https://github.com/mathuo/dockview/actions?query=workflow%3ACI)
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=mathuo_dockview&metric=coverage)](https://sonarcloud.io/summary/overall?id=mathuo_dockview)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=mathuo_dockview&metric=alert_status)](https://sonarcloud.io/summary/overall?id=mathuo_dockview)
[![Bundle Phobia](https://badgen.net/bundlephobia/minzip/dockview)](https://bundlephobia.com/result?p=dockview)
##
Please see the website: https://dockview.dev
## Features
- Serialization / deserialization with full layout management
- Support for split-views, grid-views and 'dockable' views
- Themeable and customizable
- Tab and Group docking / Drag n' Drop
- Popout Windows
- Floating Groups
- Extensive API
- Supports Shadow DOMs
- High test coverage
- Documentation website with live examples
- Transparent builds and Code Analysis
- Security at mind - verifed publishing and builds through GitHub Actions
Want to verify our builds? Go [here](https://www.npmjs.com/package/dockview#Provenance).
## Quick start
Dockview has a peer dependency on `react >= 16.8.0` and `react-dom >= 16.8.0`. You can install dockview from [npm](https://www.npmjs.com/package/dockview).
```
npm install --save dockview
```
Within your project you must import or reference the stylesheet at `dockview/dist/styles/dockview.css` and attach a theme.
```css
@import '~dockview/dist/styles/dockview.css';
```
You should also attach a dockview theme to an element containing your components. For example:
```html
<body classname="dockview-theme-dark"></body>
```

View File

@ -0,0 +1,34 @@
import { JestConfigWithTsJest } from 'ts-jest';
const config: JestConfigWithTsJest = {
preset: 'ts-jest',
roots: ['<rootDir>/packages/dockview-angular'],
modulePaths: ['<rootDir>/packages/dockview-angular/src'],
displayName: { name: 'dockview-angular', color: 'blue' },
rootDir: '../../',
collectCoverageFrom: [
'<rootDir>/packages/dockview-angular/src/**/*.{js,jsx,ts,tsx}',
],
setupFiles: [
// '<rootDir>/packages/dockview-angular/src/__tests__/__mocks__/resizeObserver.js',
],
setupFilesAfterEnv: ['<rootDir>/jest-setup.ts'],
coveragePathIgnorePatterns: ['/node_modules/'],
modulePathIgnorePatterns: [
// '<rootDir>/packages/dockview-angular/src/__tests__/__mocks__',
// '<rootDir>/packages/dockview-angular/src/__tests__/__test_utils__',
],
coverageDirectory: '<rootDir>/packages/dockview-angular/coverage/',
testResultsProcessor: 'jest-sonar-reporter',
testEnvironment: 'jsdom',
transform: {
'^.+\\.tsx?$': [
'ts-jest',
{
tsconfig: '<rootDir>/tsconfig.test.json',
},
],
},
};
export default config;

View File

@ -0,0 +1,59 @@
{
"name": "dockview-angular",
"version": "4.2.4",
"description": "Zero dependency layout manager supporting tabs, grids and splitviews",
"keywords": [
"splitview",
"split-view",
"gridview",
"grid-view",
"dockview",
"dock-view",
"grid",
"tabs",
"layout",
"layout manager",
"dock layout",
"dock",
"docking",
"splitter",
"drag-and-drop",
"drag",
"drop",
"react",
"react-component"
],
"homepage": "https://github.com/mathuo/dockview",
"bugs": {
"url": "https://github.com/mathuo/dockview/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/mathuo/dockview.git"
},
"license": "MIT",
"author": "https://github.com/mathuo",
"main": "./dist/cjs/index.js",
"module": "./dist/esm/index.js",
"types": "./dist/cjs/index.d.ts",
"files": [
"dist",
"README.md"
],
"scripts": {
"build": "npm run build:package && npm run build:bundles",
"build:bundles": "rollup -c",
"build:cjs": "cross-env ../../node_modules/.bin/tsc --build ./tsconfig.json --verbose --extendedDiagnostics",
"build:css": "gulp sass",
"build:esm": "cross-env ../../node_modules/.bin/tsc --build ./tsconfig.esm.json --verbose --extendedDiagnostics",
"build:package": "npm run build:cjs && npm run build:esm && npm run build:css",
"clean": "rimraf dist/ .build/ .rollup.cache/",
"prepublishOnly": "npm run rebuild && npm run test",
"rebuild": "npm run clean && npm run build",
"test": "cross-env ../../node_modules/.bin/jest --selectProjects dockview",
"test:cov": "cross-env ../../node_modules/.bin/jest --selectProjects dockview --coverage"
},
"dependencies": {
"dockview-core": "^4.2.4"
}
}

View File

@ -0,0 +1,113 @@
/* eslint-disable */
const { join } = require('path');
const typescript = require('@rollup/plugin-typescript');
const terser = require('@rollup/plugin-terser');
const postcss = require('rollup-plugin-postcss');
const nodeResolve = require('@rollup/plugin-node-resolve');
const { name, version, homepage, license } = require('./package.json');
const main = join(__dirname, './scripts/rollupEntryTarget.ts');
const mainNoStyles = join(__dirname, './src/index.ts');
const outputDir = join(__dirname, 'dist');
function outputFile(format, isMinified, withStyles) {
let filename = join(outputDir, name);
if (format !== 'umd') {
filename += `.${format}`;
}
if (isMinified) {
filename += '.min';
}
if (!withStyles) {
filename += '.noStyle';
}
return `${filename}.js`;
}
function getInput(options) {
const { withStyles } = options;
if (withStyles) {
return main;
}
return mainNoStyles;
}
function createBundle(format, options) {
const { withStyles, isMinified } = options;
const input = getInput(options);
const file = outputFile(format, isMinified, withStyles);
const external = [];
const output = {
file,
format,
sourcemap: true,
globals: {},
banner: [
`/**`,
` * ${name}`,
` * @version ${version}`,
` * @link ${homepage}`,
` * @license ${license}`,
` */`,
].join('\n'),
};
const plugins = [
nodeResolve({
include: ['node_modules/dockview-core/**'],
}),
typescript({
tsconfig: 'tsconfig.esm.json',
}),
];
if (isMinified) {
plugins.push(terser());
}
if (withStyles) {
plugins.push(postcss());
}
if (format === 'umd') {
output['name'] = name;
}
external.push('react', 'react-dom');
if (format === 'umd') {
output.globals['react'] = 'React';
output.globals['react-dom'] = 'ReactDOM';
}
return {
input,
output,
plugins,
external,
};
}
module.exports = [
// amd
createBundle('amd', { withStyles: false, isMinified: false }),
createBundle('amd', { withStyles: true, isMinified: false }),
createBundle('amd', { withStyles: false, isMinified: true }),
createBundle('amd', { withStyles: true, isMinified: true }),
// umd
createBundle('umd', { withStyles: false, isMinified: false }),
createBundle('umd', { withStyles: true, isMinified: false }),
createBundle('umd', { withStyles: false, isMinified: true }),
createBundle('umd', { withStyles: true, isMinified: true }),
// cjs
createBundle('cjs', { withStyles: true, isMinified: false }),
// esm
createBundle('esm', { withStyles: true, isMinified: false }),
createBundle('esm', { withStyles: true, isMinified: true }),
];

View File

@ -0,0 +1,2 @@
import '../dist/styles/dockview.css';
export * from '../src/index';

View File

@ -0,0 +1,5 @@
describe('empty', () => {
test('that passes', () => {
expect(true).toBeTruthy();
});
});

View File

@ -0,0 +1 @@
export * from 'dockview-core';

View File

@ -0,0 +1,14 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"module": "ES2020",
"moduleResolution": "node",
"target": "es6",
"outDir": "dist/esm",
"tsBuildInfoFile": ".build/tsconfig.tsbuildinfo.esm",
"jsx": "react",
"rootDir": "src"
},
"include": ["src"],
"exclude": ["**/node_modules", "src/__tests__"]
}

View File

@ -1,5 +1,5 @@
{
"extends": "../../module-build/tsconfig.json",
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist/cjs",
"tsBuildInfoFile": ".build/tsconfig.tsbuildinfo.cjs",
@ -8,4 +8,4 @@
},
"include": ["src"],
"exclude": ["**/node_modules", "src/__tests__"]
}
}

View File

@ -0,0 +1,5 @@
{
"extends": ["../../typedoc.base.json"],
"entryPoints": ["src/index.ts"],
"exclude": ["**/dist/**"]
}

View File

@ -0,0 +1,38 @@
<div align="center">
<h1>dockview</h1>
<p>Zero dependency layout manager supporting tabs, groups, grids and splitviews. Supports React, Vue and Vanilla TypeScript</p>
</div>
---
[![npm version](https://badge.fury.io/js/dockview.svg)](https://www.npmjs.com/package/dockview)
[![npm](https://img.shields.io/npm/dm/dockview)](https://www.npmjs.com/package/dockview)
[![CI Build](https://github.com/mathuo/dockview/workflows/CI/badge.svg)](https://github.com/mathuo/dockview/actions?query=workflow%3ACI)
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=mathuo_dockview&metric=coverage)](https://sonarcloud.io/summary/overall?id=mathuo_dockview)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=mathuo_dockview&metric=alert_status)](https://sonarcloud.io/summary/overall?id=mathuo_dockview)
[![Bundle Phobia](https://badgen.net/bundlephobia/minzip/dockview)](https://bundlephobia.com/result?p=dockview)
##
![](packages/docs/static/img/splashscreen.gif)
Please see the website: https://dockview.dev
## Features
- Serialization / deserialization with full layout management
- Support for split-views, grid-views and 'dockable' views
- Themeable and customizable
- Tab and Group docking / Drag n' Drop
- Popout Windows
- Floating Groups
- Extensive API
- Supports Shadow DOMs
- High test coverage
- Documentation website with live examples
- Transparent builds and Code Analysis
- Security at mind - verifed publishing and builds through GitHub Actions
Want to verify our builds? Go [here](https://www.npmjs.com/package/dockview#Provenance).

View File

@ -0,0 +1,13 @@
const gulp = require('gulp');
const gulpSass = require('gulp-dart-sass');
const concat = require('gulp-concat');
gulp.task('sass', () => {
return gulp
.src('./src/**/*.scss')
.pipe(gulpSass().on('error', gulpSass.logError))
.pipe(concat('dockview.css'))
.pipe(gulp.dest('./dist/styles/'));
});
gulp.task('run', gulp.series(['sass']));

View File

@ -0,0 +1,34 @@
import { JestConfigWithTsJest } from 'ts-jest';
const config: JestConfigWithTsJest = {
preset: 'ts-jest',
roots: ['<rootDir>/packages/dockview-core'],
modulePaths: ['<rootDir>/packages/dockview-core/src'],
displayName: { name: 'dockview-core', color: 'blue' },
rootDir: '../../',
collectCoverageFrom: [
'<rootDir>/packages/dockview-core/src/**/*.{js,jsx,ts,tsx}',
],
setupFiles: [
'<rootDir>/packages/dockview-core/src/__tests__/__mocks__/resizeObserver.js',
],
setupFilesAfterEnv: ['<rootDir>/jest-setup.ts'],
coveragePathIgnorePatterns: ['/node_modules/'],
modulePathIgnorePatterns: [
'<rootDir>/packages/dockview-core/src/__tests__/__mocks__',
'<rootDir>/packages/dockview-core/src/__tests__/__test_utils__',
],
coverageDirectory: '<rootDir>/packages/dockview-core/coverage/',
testResultsProcessor: 'jest-sonar-reporter',
testEnvironment: 'jsdom',
transform: {
'^.+\\.tsx?$': [
'ts-jest',
{
tsconfig: '<rootDir>/tsconfig.test.json',
},
],
},
};
export default config;

View File

@ -0,0 +1,56 @@
{
"name": "dockview-core",
"version": "4.2.4",
"description": "Zero dependency layout manager supporting tabs, grids and splitviews",
"keywords": [
"splitview",
"split-view",
"gridview",
"grid-view",
"dockview",
"dock-view",
"grid",
"tabs",
"layout",
"layout manager",
"dock layout",
"dock",
"docking",
"splitter",
"drag-and-drop",
"drag",
"drop",
"react",
"react-component"
],
"homepage": "https://github.com/mathuo/dockview",
"bugs": {
"url": "https://github.com/mathuo/dockview/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/mathuo/dockview.git"
},
"license": "MIT",
"author": "https://github.com/mathuo",
"main": "./dist/cjs/index.js",
"module": "./dist/esm/index.js",
"types": "./dist/cjs/index.d.ts",
"files": [
"dist",
"README.md"
],
"scripts": {
"build": "npm run build:package && npm run build:bundles",
"build:bundles": "rollup -c",
"build:cjs": "cross-env ../../node_modules/.bin/tsc --build ./tsconfig.json --verbose --extendedDiagnostics",
"build:css": "gulp sass",
"build:esm": "cross-env ../../node_modules/.bin/tsc --build ./tsconfig.esm.json --verbose --extendedDiagnostics",
"build:package": "npm run build:cjs && npm run build:esm && npm run build:css",
"clean": "rimraf dist/ .build/ .rollup.cache/",
"prepublishOnly": "npm run rebuild && npm run test",
"rebuild": "npm run clean && npm run build",
"test": "cross-env ../../node_modules/.bin/jest --selectProjects dockview-core",
"test:cov": "cross-env ../../node_modules/.bin/jest --selectProjects dockview-core --coverage"
}
}

View File

@ -0,0 +1,102 @@
/* eslint-disable */
const { join } = require('path');
const typescript = require('@rollup/plugin-typescript');
const terser = require('@rollup/plugin-terser');
const postcss = require('rollup-plugin-postcss');
const { name, version, homepage, license } = require('./package.json');
const main = join(__dirname, './scripts/rollupEntryTarget.ts');
const mainNoStyles = join(__dirname, './src/index.ts');
const outputDir = join(__dirname, 'dist');
function outputFile(format, isMinified, withStyles) {
let filename = join(outputDir, name);
if (format !== 'umd') {
filename += `.${format}`;
}
if (isMinified) {
filename += '.min';
}
if (!withStyles) {
filename += '.noStyle';
}
return `${filename}.js`;
}
function getInput(options) {
const { withStyles } = options;
if (withStyles) {
return main;
}
return mainNoStyles;
}
function createBundle(format, options) {
const { withStyles, isMinified, isReact } = options;
const input = getInput(options);
const file = outputFile(format, isMinified, withStyles, isReact);
const external = [];
const output = {
file,
format,
sourcemap: true,
globals: {},
banner: [
`/**`,
` * ${name}`,
` * @version ${version}`,
` * @link ${homepage}`,
` * @license ${license}`,
` */`,
].join('\n'),
};
const plugins = [
typescript({
tsconfig: 'tsconfig.esm.json',
}),
];
if (isMinified) {
plugins.push(terser());
}
if (withStyles) {
plugins.push(postcss());
}
if (format === 'umd') {
output['name'] = name;
}
return {
input,
output,
plugins,
external,
};
}
module.exports = [
// amd
createBundle('amd', { withStyles: false, isMinified: false }),
createBundle('amd', { withStyles: true, isMinified: false }),
createBundle('amd', { withStyles: false, isMinified: true }),
createBundle('amd', { withStyles: true, isMinified: true }),
// umd
createBundle('umd', { withStyles: false, isMinified: false }),
createBundle('umd', { withStyles: true, isMinified: false }),
createBundle('umd', { withStyles: false, isMinified: true }),
createBundle('umd', { withStyles: true, isMinified: true }),
// cjs
createBundle('cjs', { withStyles: true, isMinified: false }),
// esm
createBundle('esm', { withStyles: true, isMinified: false }),
createBundle('esm', { withStyles: true, isMinified: true }),
];

View File

@ -0,0 +1,2 @@
import '../dist/styles/dockview.css';
export * from '../src/index';

View File

@ -0,0 +1,47 @@
import { IDockviewPanelModel } from '../../dockview/dockviewPanelModel';
import { DockviewGroupPanel } from '../../dockview/dockviewGroupPanel';
import {
TabPartInitParameters,
IContentRenderer,
ITabRenderer,
} from '../../dockview/types';
import { PanelUpdateEvent } from '../../panel/types';
import { TabLocation } from '../../dockview/framework';
export class DockviewPanelModelMock implements IDockviewPanelModel {
constructor(
readonly contentComponent: string,
readonly content: IContentRenderer,
readonly tabComponent: string,
readonly tab: ITabRenderer
) {
//
}
createTabRenderer(tabLocation: TabLocation): ITabRenderer {
return this.tab;
}
init(params: TabPartInitParameters): void {
//
}
updateParentGroup(
group: DockviewGroupPanel,
isPanelVisible: boolean
): void {
//
}
update(event: PanelUpdateEvent): void {
//
}
layout(width: number, height: number): void {
//
}
dispose(): void {
//
}
}

View File

@ -0,0 +1,45 @@
import { fromPartial } from '@total-typescript/shoehorn';
export function setupMockWindow() {
const listeners: Record<string, (() => void)[]> = {};
let width = 1000;
let height = 2000;
return fromPartial<Window>({
addEventListener: (type: string, listener: () => void) => {
if (!listeners[type]) {
listeners[type] = [];
}
listeners[type].push(listener);
if (type === 'load') {
listener();
}
},
removeEventListener: (type: string, listener: () => void) => {
if (listeners[type]) {
const index = listeners[type].indexOf(listener);
if (index > -1) {
listeners[type].splice(index, 1);
}
}
},
dispatchEvent: (event: Event) => {
const items = listeners[event.type];
if (!items) {
return;
}
items.forEach((item) => item());
},
document: document,
close: () => {
listeners['beforeunload']?.forEach((f) => f());
},
get innerWidth() {
return width++;
},
get innerHeight() {
return height++;
},
});
}

View File

@ -0,0 +1,13 @@
class ResizeObserver {
observe() {
// do nothing
}
unobserve() {
// do nothing
}
disconnect() {
// do nothing
}
}
window.ResizeObserver = ResizeObserver;

View File

@ -0,0 +1,73 @@
import React from 'react';
/**
* useful utility type to erase readonly signatures for testing purposes
*
* @see https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#readonly-mapped-type-modifiers-and-readonly-arrays
*/
export type Writable<T> = T extends object
? { -readonly [K in keyof T]: Writable<T[K]> }
: T;
export function setMockRefElement(node: Partial<HTMLElement>): void {
const mockRef = {
get current() {
return node;
},
set current(_value) {
//noop
},
};
jest.spyOn(React, 'useRef').mockReturnValueOnce(mockRef);
}
export function createOffsetDragOverEvent(params: {
clientX: number;
clientY: number;
}): Event {
const event = new Event('dragover', {
bubbles: true,
cancelable: true,
});
Object.defineProperty(event, 'clientX', { get: () => params.clientX });
Object.defineProperty(event, 'clientY', { get: () => params.clientY });
return event;
}
/**
* `jest.runAllTicks` doesn't seem to exhaust all events in the micro-task queue so
* as a **hacky** alternative we'll wait for an empty Promise to complete which runs
* on the micro-task queue so will force a run-to-completion emptying the queue
* of any pending micro-task
*/
export function exhaustMicrotaskQueue(): Promise<void> {
return new Promise<void>((resolve) => resolve());
}
export const mockGetBoundingClientRect = ({
left,
top,
height,
width,
}: {
left: number;
top: number;
height: number;
width: number;
}) => {
const result = {
left,
top,
height,
width,
right: left + width,
bottom: top + height,
x: left,
y: top,
};
return {
...result,
toJSON: () => result,
};
};

View File

@ -0,0 +1,69 @@
import { PanelApiImpl } from '../../api/panelApi';
import { IPanel } from '../../panel/types';
describe('api', () => {
let api: PanelApiImpl;
beforeEach(() => {
api = new PanelApiImpl('dummy_id', 'fake-component');
});
test('updateParameters', () => {
const panel = {
update: jest.fn(),
} as Partial<IPanel>;
api.initialize(panel as IPanel);
expect(panel.update).toHaveBeenCalledTimes(0);
api.updateParameters({ keyA: 'valueA' });
expect(panel.update).toHaveBeenCalledTimes(1);
expect(panel.update).toHaveBeenCalledWith({
params: { keyA: 'valueA' },
});
});
test('should update isFcoused getter', () => {
expect(api.isFocused).toBeFalsy();
api._onDidChangeFocus.fire({ isFocused: true });
expect(api.isFocused).toBeTruthy();
api._onDidChangeFocus.fire({ isFocused: false });
expect(api.isFocused).toBeFalsy();
});
test('should update isActive getter', () => {
expect(api.isFocused).toBeFalsy();
api._onDidActiveChange.fire({ isActive: true });
expect(api.isActive).toBeTruthy();
api._onDidActiveChange.fire({ isActive: false });
expect(api.isActive).toBeFalsy();
});
test('should update isActive getter', () => {
expect(api.isVisible).toBeTruthy();
api._onDidVisibilityChange.fire({ isVisible: false });
expect(api.isVisible).toBeFalsy();
api._onDidVisibilityChange.fire({ isVisible: true });
expect(api.isVisible).toBeTruthy();
});
test('should update width and height getter', () => {
expect(api.height).toBe(0);
expect(api.width).toBe(0);
api._onDidDimensionChange.fire({ height: 10, width: 20 });
expect(api.height).toBe(10);
expect(api.width).toBe(20);
api._onDidDimensionChange.fire({ height: 20, width: 10 });
expect(api.height).toBe(20);
expect(api.width).toBe(10);
});
});

View File

@ -0,0 +1,155 @@
import {
SplitviewApi,
PaneviewApi,
GridviewApi,
DockviewApi,
} from '../../api/component.api';
import { GridviewComponent } from '../../gridview/gridviewComponent';
import { PaneviewComponent } from '../../paneview/paneviewComponent';
import { SplitviewComponent } from '../../splitview/splitviewComponent';
import { DockviewComponent } from '../../dockview/dockviewComponent';
describe('component.api', () => {
describe('splitview', () => {
test('splitviewapi', () => {
const list: (keyof SplitviewComponent)[] = [
'minimumSize',
'maximumSize',
'height',
'width',
'length',
'orientation',
'onDidLayoutChange',
'onDidAddView',
'onDidRemoveView',
'panels',
'focus',
'toJSON',
];
for (const _ of list) {
const f = jest.fn();
const component: Partial<SplitviewComponent> = {
[_]: f(),
};
const cut = new SplitviewApi(<SplitviewComponent>component);
(cut as any)[_];
expect(f).toBeCalledTimes(1);
}
});
});
describe('paneview', () => {
test('panviewapi', () => {
const list: (keyof PaneviewComponent)[] = [
'minimumSize',
'maximumSize',
'height',
'width',
'onDidLayoutChange',
'onDidAddView',
'onDidRemoveView',
'panels',
'focus',
'toJSON',
];
for (const _ of list) {
const f = jest.fn();
const component: Partial<PaneviewComponent> = {
[_]: f(),
};
const cut = new PaneviewApi(<PaneviewComponent>component);
(cut as any)[_];
expect(f).toBeCalledTimes(1);
}
});
});
describe('gridview', () => {
test('gridviewapi', () => {
const list: (keyof GridviewComponent)[] = [
'minimumHeight',
'maximumHeight',
'minimumWidth',
'maximumWidth',
'width',
'height',
'onDidLayoutChange',
'orientation',
'focus',
'toJSON',
'onDidActiveGroupChange',
'onDidAddGroup',
'onDidRemoveGroup',
'onDidLayoutFromJSON',
];
for (const _ of list) {
const f = jest.fn();
const component: Partial<GridviewComponent> = {
[_]: f(),
};
const cut = new GridviewApi(<GridviewComponent>component);
(cut as any)[_];
expect(f).toBeCalledTimes(1);
}
});
});
describe('dockview', () => {
test('dockviewapi', () => {
const list: (keyof DockviewComponent)[] = [
'minimumHeight',
'maximumHeight',
'minimumWidth',
'maximumWidth',
'width',
'height',
'size',
'totalPanels',
'onDidLayoutChange',
'panels',
'groups',
'activeGroup',
'activePanel',
'focus',
'closeAllGroups',
'toJSON',
'onDidActiveGroupChange',
'onDidAddGroup',
'onDidRemoveGroup',
'onDidActivePanelChange',
'onDidAddPanel',
'onDidRemovePanel',
'onDidLayoutFromJSON',
];
for (const _ of list) {
const f = jest.fn();
const component: Partial<DockviewComponent> = {
[_]: f(),
};
const cut = new DockviewApi(<DockviewComponent>component);
(cut as any)[_];
expect(f).toBeCalledTimes(1);
}
});
});
});

View File

@ -0,0 +1,123 @@
import { DockviewPanelApiImpl } from '../../api/dockviewPanelApi';
import { DockviewComponent } from '../../dockview/dockviewComponent';
import { DockviewPanel } from '../../dockview/dockviewPanel';
import { DockviewGroupPanel } from '../../dockview/dockviewGroupPanel';
import { fromPartial } from '@total-typescript/shoehorn';
describe('groupPanelApi', () => {
test('title', () => {
const accessor = fromPartial<DockviewComponent>({
onDidAddPanel: jest.fn(),
onDidRemovePanel: jest.fn(),
options: {},
onDidOptionsChange: jest.fn(),
});
const panelMock = jest.fn<DockviewPanel, []>(() => {
return {
update: jest.fn(),
setTitle: jest.fn(),
} as any;
});
const panel = new panelMock();
const group = fromPartial<DockviewGroupPanel>({
api: {
onDidVisibilityChange: jest.fn(),
onDidLocationChange: jest.fn(),
onDidActiveChange: jest.fn(),
},
});
const cut = new DockviewPanelApiImpl(
panel,
group,
<DockviewComponent>accessor,
'fake-component'
);
cut.setTitle('test_title');
expect(panel.setTitle).toBeCalledTimes(1);
expect(panel.setTitle).toBeCalledWith('test_title');
});
test('updateParameters', () => {
const groupPanel: Partial<DockviewPanel> = {
id: 'test_id',
update: jest.fn(),
};
const accessor = fromPartial<DockviewComponent>({
onDidAddPanel: jest.fn(),
onDidRemovePanel: jest.fn(),
options: {},
onDidOptionsChange: jest.fn(),
});
const groupViewPanel = new DockviewGroupPanel(
<DockviewComponent>accessor,
'',
{}
);
const cut = new DockviewPanelApiImpl(
<DockviewPanel>groupPanel,
<DockviewGroupPanel>groupViewPanel,
<DockviewComponent>accessor,
'fake-component'
);
cut.updateParameters({ keyA: 'valueA' });
expect(groupPanel.update).toHaveBeenCalledWith({
params: { keyA: 'valueA' },
});
expect(groupPanel.update).toHaveBeenCalledTimes(1);
});
test('onDidGroupChange', () => {
const groupPanel: Partial<DockviewPanel> = {
id: 'test_id',
};
const accessor = fromPartial<DockviewComponent>({
onDidAddPanel: jest.fn(),
onDidRemovePanel: jest.fn(),
options: {},
onDidOptionsChange: jest.fn(),
});
const groupViewPanel = new DockviewGroupPanel(
<DockviewComponent>accessor,
'',
{}
);
const cut = new DockviewPanelApiImpl(
<DockviewPanel>groupPanel,
<DockviewGroupPanel>groupViewPanel,
<DockviewComponent>accessor,
'fake-component'
);
let events = 0;
const disposable = cut.onDidGroupChange(() => {
events++;
});
expect(events).toBe(0);
expect(cut.group).toBe(groupViewPanel);
const groupViewPanel2 = new DockviewGroupPanel(
<DockviewComponent>accessor,
'',
{}
);
cut.group = groupViewPanel2;
expect(events).toBe(1);
expect(cut.group).toBe(groupViewPanel2);
disposable.dispose();
});
});

View File

@ -3,24 +3,25 @@ import {
last,
pushToEnd,
pushToStart,
range,
remove,
sequenceEquals,
tail,
} from '../array';
describe('array', () => {
it('tail', () => {
test('tail', () => {
expect(tail([1, 2, 3, 4, 5])).toEqual([[1, 2, 3, 4], 5]);
expect(tail([1, 2])).toEqual([[1], 2]);
expect(tail([1])).toEqual([[], 1]);
expect(() => tail([])).toThrow('Invalid tail call');
});
it('last', () => {
test('last', () => {
expect(last([1, 2, 3, 4])).toBe(4);
expect(last([])).toBeUndefined();
});
it('pushToEnd', () => {
test('pushToEnd', () => {
const arr1 = [1, 2, 3, 4];
pushToEnd(arr1, 3);
expect(arr1).toEqual([1, 2, 4, 3]);
@ -28,7 +29,7 @@ describe('array', () => {
expect(arr1).toEqual([1, 2, 4, 3]);
});
it('pushToStart', () => {
test('pushToStart', () => {
const arr1 = [1, 2, 3, 4];
pushToStart(arr1, 3);
expect(arr1).toEqual([3, 1, 2, 4]);
@ -36,21 +37,33 @@ describe('array', () => {
expect(arr1).toEqual([3, 1, 2, 4]);
});
it('range', () => {
expect(range(0, 5)).toEqual([0, 1, 2, 3, 4]);
expect(range(5, 0)).toEqual([5, 4, 3, 2, 1]);
expect(range(5)).toEqual([0, 1, 2, 3, 4]);
});
it('firstIndex', () => {
test('firstIndex', () => {
expect(firstIndex([1, 2, 3, 4, 3], (item) => item === 3)).toBe(2);
expect(firstIndex([1, 2, 3, 4, 3], (item) => item === 5)).toBe(-1);
});
it('firstIndex', () => {
test('firstIndex', () => {
expect(sequenceEquals([1, 2, 3, 4], [1, 2, 3, 4])).toBeTruthy();
expect(sequenceEquals([1, 2, 3, 4], [4, 3, 2, 1])).toBeFalsy();
expect(sequenceEquals([1, 2, 3, 4], [1, 2, 3])).toBeFalsy();
expect(sequenceEquals([1, 2, 3, 4], [1, 2, 3, 4, 5])).toBeFalsy();
});
test('remove', () => {
const arr1 = [1, 2, 3, 4];
remove(arr1, 2);
expect(arr1).toEqual([1, 3, 4]);
const arr2 = [1, 2, 2, 3, 4];
remove(arr2, 2);
expect(arr2).toEqual([1, 2, 3, 4]);
const arr3 = [1];
remove(arr3, 2);
expect(arr3).toEqual([1]);
remove(arr3, 1);
expect(arr3).toEqual([]);
remove(arr3, 1);
expect(arr3).toEqual([]);
});
});

View File

@ -0,0 +1,179 @@
import { fireEvent } from '@testing-library/dom';
import { DragHandler } from '../../dnd/abstractDragHandler';
import { IDisposable } from '../../lifecycle';
describe('abstractDragHandler', () => {
test('that className dv-dragged is added to element after dragstart event', () => {
jest.useFakeTimers();
const element = document.createElement('div');
const handler = new (class TestClass extends DragHandler {
constructor(el: HTMLElement) {
super(el);
}
getData(): IDisposable {
return {
dispose: () => {
// /
},
};
}
})(element);
expect(element.classList.contains('dv-dragged')).toBeFalsy();
fireEvent.dragStart(element);
expect(element.classList.contains('dv-dragged')).toBeTruthy();
jest.runAllTimers();
expect(element.classList.contains('dv-dragged')).toBeFalsy();
handler.dispose();
});
test('that iframes and webviews have pointerEvents=none set whilst drag action is in process', () => {
jest.useFakeTimers();
const element = document.createElement('div');
const iframe = document.createElement('iframe');
const webview = document.createElement('webview');
const span = document.createElement('span');
document.body.appendChild(element);
document.body.appendChild(iframe);
document.body.appendChild(webview);
document.body.appendChild(span);
const handler = new (class TestClass extends DragHandler {
constructor(el: HTMLElement) {
super(el);
}
getData(): IDisposable {
return {
dispose: () => {
// /
},
};
}
})(element);
expect(iframe.style.pointerEvents).toBeFalsy();
expect(webview.style.pointerEvents).toBeFalsy();
expect(span.style.pointerEvents).toBeFalsy();
fireEvent.dragStart(element);
expect(iframe.style.pointerEvents).toBe('none');
expect(webview.style.pointerEvents).toBe('none');
expect(span.style.pointerEvents).toBeFalsy();
fireEvent.dragEnd(element);
expect(iframe.style.pointerEvents).toBe('');
expect(webview.style.pointerEvents).toBe('');
expect(span.style.pointerEvents).toBeFalsy();
handler.dispose();
});
test('that the disabling of pointerEvents is restored on a premature disposal of the handler', () => {
jest.useFakeTimers();
const element = document.createElement('div');
const iframe = document.createElement('iframe');
const webview = document.createElement('webview');
const span = document.createElement('span');
document.body.appendChild(element);
document.body.appendChild(iframe);
document.body.appendChild(webview);
document.body.appendChild(span);
const handler = new (class TestClass extends DragHandler {
constructor(el: HTMLElement) {
super(el);
}
getData(): IDisposable {
return {
dispose: () => {
// /
},
};
}
})(element);
expect(iframe.style.pointerEvents).toBeFalsy();
expect(webview.style.pointerEvents).toBeFalsy();
expect(span.style.pointerEvents).toBeFalsy();
fireEvent.dragStart(element);
expect(iframe.style.pointerEvents).toBe('none');
expect(webview.style.pointerEvents).toBe('none');
expect(span.style.pointerEvents).toBeFalsy();
handler.dispose();
expect(iframe.style.pointerEvents).toBe('');
expect(webview.style.pointerEvents).toBe('');
expect(span.style.pointerEvents).toBeFalsy();
});
test('that .preventDefault() is called for cancelled events', () => {
const element = document.createElement('div');
const handler = new (class TestClass extends DragHandler {
constructor(el: HTMLElement) {
super(el);
}
protected isCancelled(_event: DragEvent): boolean {
return true;
}
getData(): IDisposable {
return {
dispose: () => {
// /
},
};
}
})(element);
const event = new Event('dragstart');
const spy = jest.spyOn(event, 'preventDefault');
fireEvent(element, event);
expect(spy).toBeCalledTimes(1);
handler.dispose();
});
test('that .preventDefault() is not called for non-cancelled events', () => {
const element = document.createElement('div');
const handler = new (class TestClass extends DragHandler {
constructor(el: HTMLElement) {
super(el);
}
protected isCancelled(_event: DragEvent): boolean {
return false;
}
getData(): IDisposable {
return {
dispose: () => {
// /
},
};
}
})(element);
const event = new Event('dragstart');
const spy = jest.spyOn(event, 'preventDefault');
fireEvent(element, event);
expect(spy).toHaveBeenCalledTimes(0);
handler.dispose();
});
});

View File

@ -0,0 +1,101 @@
import {
getPaneData,
getPanelData,
LocalSelectionTransfer,
PanelTransfer,
PaneTransfer,
} from '../../dnd/dataTransfer';
describe('dataTransfer', () => {
describe('getPanelData', () => {
test('should be undefined when there is no local transfer object', () => {
expect(getPanelData()).toBeUndefined();
});
test('should be undefined when there is a local transfer object that is not a PanelTransfer', () => {
LocalSelectionTransfer.getInstance<PaneTransfer>().setData(
[new PaneTransfer('viewId', 'groupId')],
PaneTransfer.prototype
);
expect(getPanelData()).toBeUndefined();
});
test('should retrieve the PanelTransfer object when transfer is active', () => {
const transferObject = new PanelTransfer(
'viewId',
'groupId',
'panelId'
);
LocalSelectionTransfer.getInstance<PanelTransfer>().setData(
[transferObject],
PanelTransfer.prototype
);
expect(getPanelData()).toBe(transferObject);
});
test('should retrieve the PanelTransfer when a new transfer overrides an existing one', () => {
LocalSelectionTransfer.getInstance<PaneTransfer>().setData(
[new PaneTransfer('viewId', 'groupId')],
PaneTransfer.prototype
);
expect(getPanelData()).toBeUndefined();
const transferObject = new PanelTransfer(
'viewId',
'groupId',
'panelId'
);
LocalSelectionTransfer.getInstance<PanelTransfer>().setData(
[transferObject],
PanelTransfer.prototype
);
expect(getPanelData()).toBe(transferObject);
});
});
describe('getPaneData', () => {
test('should be undefined when there is no local transfer object', () => {
expect(getPaneData()).toBeUndefined();
});
test('should be undefined when there is a local transfer object that is not a PaneTransfer', () => {
LocalSelectionTransfer.getInstance<PanelTransfer>().setData(
[new PanelTransfer('viewId', 'groupId', 'panelId')],
PanelTransfer.prototype
);
expect(getPaneData()).toBeUndefined();
});
test('should retrieve the PaneTransfer object when transfer is active', () => {
const transferObject = new PaneTransfer('viewId', 'groupId');
LocalSelectionTransfer.getInstance<PaneTransfer>().setData(
[transferObject],
PaneTransfer.prototype
);
expect(getPaneData()).toBe(transferObject);
});
test('should retrieve the PanelTransfer when a new transfer overrides an existing one', () => {
LocalSelectionTransfer.getInstance<PanelTransfer>().setData(
[new PanelTransfer('viewId', 'groupId', 'panelId')],
PanelTransfer.prototype
);
expect(getPaneData()).toBeUndefined();
const transferObject = new PaneTransfer('viewId', 'groupId');
LocalSelectionTransfer.getInstance<PaneTransfer>().setData(
[transferObject],
PaneTransfer.prototype
);
expect(getPaneData()).toBe(transferObject);
});
});
});

View File

@ -0,0 +1,401 @@
import {
calculateQuadrantAsPercentage,
calculateQuadrantAsPixels,
directionToPosition,
Droptarget,
Position,
positionToDirection,
} from '../../dnd/droptarget';
import { fireEvent } from '@testing-library/dom';
import { createOffsetDragOverEvent } from '../__test_utils__/utils';
describe('droptarget', () => {
let element: HTMLElement;
let droptarget: Droptarget;
beforeEach(() => {
element = document.createElement('div');
jest.spyOn(element, 'offsetHeight', 'get').mockImplementation(
() => 100
);
jest.spyOn(element, 'offsetWidth', 'get').mockImplementation(() => 200);
});
test('that dragover events are marked', () => {
droptarget = new Droptarget(element, {
canDisplayOverlay: () => true,
acceptedTargetZones: ['center'],
});
fireEvent.dragEnter(element);
const event = new Event('dragover');
fireEvent(element, event);
expect(
(event as any)['__dockview_droptarget_event_is_used__']
).toBeTruthy();
});
test('that the drop target is removed when receiving a marked dragover event', () => {
let position: Position | undefined = undefined;
droptarget = new Droptarget(element, {
canDisplayOverlay: () => true,
acceptedTargetZones: ['center'],
});
droptarget.onDrop((event) => {
position = event.position;
});
fireEvent.dragEnter(element);
fireEvent.dragOver(element);
const target = element.querySelector(
'.dv-drop-target-dropzone'
) as HTMLElement;
fireEvent.drop(target);
expect(position).toBe('center');
const event = new Event('dragover');
(event as any)['__dockview_droptarget_event_is_used__'] = true;
fireEvent(element, event);
expect(element.querySelector('.dv-drop-target-dropzone')).toBeNull();
});
test('directionToPosition', () => {
expect(directionToPosition('above')).toBe('top');
expect(directionToPosition('below')).toBe('bottom');
expect(directionToPosition('left')).toBe('left');
expect(directionToPosition('right')).toBe('right');
expect(directionToPosition('within')).toBe('center');
expect(() => directionToPosition('bad_input' as any)).toThrow(
"invalid direction 'bad_input'"
);
});
test('positionToDirection', () => {
expect(positionToDirection('top')).toBe('above');
expect(positionToDirection('bottom')).toBe('below');
expect(positionToDirection('left')).toBe('left');
expect(positionToDirection('right')).toBe('right');
expect(positionToDirection('center')).toBe('within');
expect(() => positionToDirection('bad_input' as any)).toThrow(
"invalid position 'bad_input'"
);
});
test('non-directional', () => {
let position: Position | undefined = undefined;
droptarget = new Droptarget(element, {
canDisplayOverlay: () => true,
acceptedTargetZones: ['center'],
});
droptarget.onDrop((event) => {
position = event.position;
});
fireEvent.dragEnter(element);
fireEvent.dragOver(element);
const target = element.querySelector(
'.dv-drop-target-dropzone'
) as HTMLElement;
fireEvent.drop(target);
expect(position).toBe('center');
});
test('drop', () => {
let position: Position | undefined = undefined;
droptarget = new Droptarget(element, {
canDisplayOverlay: () => true,
acceptedTargetZones: ['top', 'left', 'right', 'bottom', 'center'],
});
droptarget.onDrop((event) => {
position = event.position;
});
fireEvent.dragEnter(element);
fireEvent.dragOver(element);
const target = element.querySelector(
'.dv-drop-target-dropzone'
) as HTMLElement;
jest.spyOn(target, 'clientHeight', 'get').mockImplementation(() => 100);
jest.spyOn(target, 'clientWidth', 'get').mockImplementation(() => 200);
fireEvent(
target,
createOffsetDragOverEvent({
clientX: 19,
clientY: 0,
})
);
expect(position).toBeUndefined();
fireEvent.drop(target);
expect(position).toBe('left');
});
test('default', () => {
droptarget = new Droptarget(element, {
canDisplayOverlay: () => true,
acceptedTargetZones: ['top', 'left', 'right', 'bottom', 'center'],
});
expect(droptarget.state).toBeUndefined();
fireEvent.dragEnter(element);
fireEvent.dragOver(element);
let viewQuery = element.querySelectorAll(
'.dv-drop-target > .dv-drop-target-dropzone > .dv-drop-target-selection'
);
expect(viewQuery.length).toBe(1);
const target = element.querySelector(
'.dv-drop-target-dropzone'
) as HTMLElement;
jest.spyOn(target, 'clientHeight', 'get').mockImplementation(() => 100);
jest.spyOn(target, 'clientWidth', 'get').mockImplementation(() => 200);
fireEvent(
target,
createOffsetDragOverEvent({ clientX: 19, clientY: 0 })
);
function check(
element: HTMLElement,
box: {
left: string;
top: string;
width: string;
height: string;
}
) {
expect(element.style.top).toBe(box.top);
expect(element.style.left).toBe(box.left);
expect(element.style.width).toBe(box.width);
expect(element.style.height).toBe(box.height);
}
viewQuery = element.querySelectorAll(
'.dv-drop-target > .dv-drop-target-dropzone > .dv-drop-target-selection'
);
expect(viewQuery.length).toBe(1);
expect(droptarget.state).toBe('left');
check(
element
.getElementsByClassName('dv-drop-target-selection')
.item(0) as HTMLDivElement,
{
top: '0px',
left: '0px',
width: '50%',
height: '100%',
}
);
fireEvent(
target,
createOffsetDragOverEvent({ clientX: 40, clientY: 19 })
);
viewQuery = element.querySelectorAll(
'.dv-drop-target > .dv-drop-target-dropzone > .dv-drop-target-selection'
);
expect(viewQuery.length).toBe(1);
expect(droptarget.state).toBe('top');
check(
element
.getElementsByClassName('dv-drop-target-selection')
.item(0) as HTMLDivElement,
{
top: '0px',
left: '0px',
width: '100%',
height: '50%',
}
);
fireEvent(
target,
createOffsetDragOverEvent({ clientX: 160, clientY: 81 })
);
viewQuery = element.querySelectorAll(
'.dv-drop-target > .dv-drop-target-dropzone > .dv-drop-target-selection'
);
expect(viewQuery.length).toBe(1);
expect(droptarget.state).toBe('bottom');
check(
element
.getElementsByClassName('dv-drop-target-selection')
.item(0) as HTMLDivElement,
{
top: '50%',
left: '0px',
width: '100%',
height: '50%',
}
);
fireEvent(
target,
createOffsetDragOverEvent({ clientX: 161, clientY: 0 })
);
viewQuery = element.querySelectorAll(
'.dv-drop-target > .dv-drop-target-dropzone > .dv-drop-target-selection'
);
expect(viewQuery.length).toBe(1);
expect(droptarget.state).toBe('right');
check(
element
.getElementsByClassName('dv-drop-target-selection')
.item(0) as HTMLDivElement,
{
top: '0px',
left: '50%',
width: '50%',
height: '100%',
}
);
fireEvent(
target,
createOffsetDragOverEvent({ clientX: 100, clientY: 50 })
);
expect(droptarget.state).toBe('center');
expect(
(
element
.getElementsByClassName('dv-drop-target-selection')
.item(0) as HTMLDivElement
).style.transform
).toBe('');
fireEvent.dragLeave(target);
expect(droptarget.state).toBe('center');
viewQuery = element.querySelectorAll('.dv-drop-target');
expect(viewQuery.length).toBe(0);
});
describe('calculateQuadrantAsPercentage', () => {
test('variety of cases', () => {
const inputs: Array<{
directions: Position[];
x: number;
y: number;
result: Position | null;
}> = [
{ directions: ['left', 'right'], x: 19, y: 50, result: 'left' },
{
directions: ['left', 'right'],
x: 81,
y: 50,
result: 'right',
},
{
directions: ['top', 'bottom'],
x: 50,
y: 19,
result: 'top',
},
{
directions: ['top', 'bottom'],
x: 50,
y: 81,
result: 'bottom',
},
{
directions: ['left', 'right', 'top', 'bottom', 'center'],
x: 50,
y: 50,
result: 'center',
},
{
directions: ['left', 'right', 'top', 'bottom'],
x: 50,
y: 50,
result: null,
},
];
for (const input of inputs) {
expect(
calculateQuadrantAsPercentage(
new Set(input.directions),
input.x,
input.y,
100,
100,
20
)
).toBe(input.result);
}
});
});
describe('calculateQuadrantAsPixels', () => {
test('variety of cases', () => {
const inputs: Array<{
directions: Position[];
x: number;
y: number;
result: Position | null;
}> = [
{ directions: ['left', 'right'], x: 19, y: 50, result: 'left' },
{
directions: ['left', 'right'],
x: 81,
y: 50,
result: 'right',
},
{
directions: ['top', 'bottom'],
x: 50,
y: 19,
result: 'top',
},
{
directions: ['top', 'bottom'],
x: 50,
y: 81,
result: 'bottom',
},
{
directions: ['left', 'right', 'top', 'bottom', 'center'],
x: 50,
y: 50,
result: 'center',
},
{
directions: ['left', 'right', 'top', 'bottom'],
x: 50,
y: 50,
result: null,
},
];
for (const input of inputs) {
expect(
calculateQuadrantAsPixels(
new Set(input.directions),
input.x,
input.y,
100,
100,
20
)
).toBe(input.result);
}
});
});
});

View File

@ -0,0 +1,31 @@
import { addGhostImage } from '../../dnd/ghost';
describe('ghost', () => {
beforeEach(() => {
jest.useFakeTimers();
jest.clearAllTimers();
});
test('that a custom class is added, the element is added to the document and all is removed afterwards', () => {
const dataTransferMock = jest.fn<Partial<DataTransfer>, []>(() => {
return {
setDragImage: jest.fn(),
};
});
const element = document.createElement('div');
const dataTransfer = <DataTransfer>new dataTransferMock();
addGhostImage(dataTransfer, element);
expect(element.className).toBe('dv-dragged');
expect(element.parentElement).toBe(document.body);
expect(dataTransfer.setDragImage).toBeCalledTimes(1);
expect(dataTransfer.setDragImage).toBeCalledWith(element, 0, 0);
jest.runAllTimers();
expect(element.className).toBe('');
expect(element.parentElement).toBe(null);
});
});

View File

@ -0,0 +1,114 @@
import { fireEvent } from '@testing-library/dom';
import { GroupDragHandler } from '../../dnd/groupDragHandler';
import { DockviewGroupPanel } from '../../dockview/dockviewGroupPanel';
import { LocalSelectionTransfer, PanelTransfer } from '../../dnd/dataTransfer';
import { DockviewComponent } from '../../dockview/dockviewComponent';
describe('groupDragHandler', () => {
test('that the dnd transfer object is setup and torndown', () => {
const element = document.createElement('div');
const groupMock = jest.fn<DockviewGroupPanel, []>(() => {
const partial: Partial<DockviewGroupPanel> = {
id: 'test_group_id',
api: { location: { type: 'grid' } } as any,
};
return partial as DockviewGroupPanel;
});
const group = new groupMock();
const cut = new GroupDragHandler(
element,
{ id: 'test_accessor_id' } as DockviewComponent,
group
);
fireEvent.dragStart(element, new Event('dragstart'));
expect(
LocalSelectionTransfer.getInstance<PanelTransfer>().hasData(
PanelTransfer.prototype
)
).toBeTruthy();
const transferObject =
LocalSelectionTransfer.getInstance<PanelTransfer>().getData(
PanelTransfer.prototype
)![0];
expect(transferObject).toBeTruthy();
expect(transferObject.viewId).toBe('test_accessor_id');
expect(transferObject.groupId).toBe('test_group_id');
expect(transferObject.panelId).toBeNull();
fireEvent.dragStart(element, new Event('dragend'));
expect(
LocalSelectionTransfer.getInstance<PanelTransfer>().hasData(
PanelTransfer.prototype
)
).toBeFalsy();
cut.dispose();
});
test('that the event is cancelled when floating and shiftKey=true', () => {
const element = document.createElement('div');
const groupMock = jest.fn<DockviewGroupPanel, []>(() => {
const partial: Partial<DockviewGroupPanel> = {
api: { location: { type: 'floating' } } as any,
};
return partial as DockviewGroupPanel;
});
const group = new groupMock();
const cut = new GroupDragHandler(
element,
{ id: 'accessor_id' } as DockviewComponent,
group
);
const event = new KeyboardEvent('dragstart', { shiftKey: false });
const spy = jest.spyOn(event, 'preventDefault');
fireEvent(element, event);
expect(spy).toBeCalledTimes(1);
const event2 = new KeyboardEvent('dragstart', { shiftKey: true });
const spy2 = jest.spyOn(event2, 'preventDefault');
fireEvent(element, event);
expect(spy2).toBeCalledTimes(0);
cut.dispose();
});
test('that the event is never cancelled when the group is not floating', () => {
const element = document.createElement('div');
const groupMock = jest.fn<DockviewGroupPanel, []>(() => {
const partial: Partial<DockviewGroupPanel> = {
api: { location: { type: 'grid' } } as any,
};
return partial as DockviewGroupPanel;
});
const group = new groupMock();
const cut = new GroupDragHandler(
element,
{ id: 'accessor_id' } as DockviewComponent,
group
);
const event = new KeyboardEvent('dragstart', { shiftKey: false });
const spy = jest.spyOn(event, 'preventDefault');
fireEvent(element, event);
expect(spy).toBeCalledTimes(0);
const event2 = new KeyboardEvent('dragstart', { shiftKey: true });
const spy2 = jest.spyOn(event2, 'preventDefault');
fireEvent(element, event);
expect(spy2).toBeCalledTimes(0);
cut.dispose();
});
});

View File

@ -0,0 +1,174 @@
import { fireEvent } from '@testing-library/dom';
import { ContentContainer } from '../../../../dockview/components/panel/content';
import {
GroupPanelPartInitParameters,
IContentRenderer,
} from '../../../../dockview/types';
import { CompositeDisposable } from '../../../../lifecycle';
import { PanelUpdateEvent } from '../../../../panel/types';
import { IDockviewPanel } from '../../../../dockview/dockviewPanel';
import { IDockviewPanelModel } from '../../../../dockview/dockviewPanelModel';
import { DockviewComponent } from '../../../../dockview/dockviewComponent';
import { fromPartial } from '@total-typescript/shoehorn';
import { DockviewGroupPanelModel } from '../../../../dockview/dockviewGroupPanelModel';
import { OverlayRenderContainer } from '../../../../overlay/overlayRenderContainer';
class TestContentRenderer
extends CompositeDisposable
implements IContentRenderer
{
readonly element: HTMLElement;
constructor(public id: string) {
super();
this.element = document.createElement('div');
this.element.id = id;
}
init(parameters: GroupPanelPartInitParameters): void {
//
}
layout(width: number, height: number): void {
//
}
update(event: PanelUpdateEvent): void {
//
}
toJSON(): object {
return {};
}
focus(): void {
//
}
}
describe('contentContainer', () => {
beforeEach(() => {
jest.useFakeTimers();
});
test('basic focus test', () => {
let focus = 0;
let blur = 0;
const disposable = new CompositeDisposable();
const overlayRenderContainer = new OverlayRenderContainer(
document.createElement('div'),
fromPartial<DockviewComponent>({})
);
const cut = new ContentContainer(
fromPartial<DockviewComponent>({
renderer: 'onlyWhenVisible',
overlayRenderContainer,
}),
fromPartial<DockviewGroupPanelModel>({
renderContainer: overlayRenderContainer,
})
);
disposable.addDisposables(
cut.onDidFocus(() => {
focus++;
}),
cut.onDidBlur(() => {
blur++;
})
);
const contentRenderer = new TestContentRenderer('id-1');
const panel = fromPartial<IDockviewPanel>({
view: {
content: contentRenderer,
},
api: { renderer: 'onlyWhenVisible' },
});
cut.openPanel(panel as IDockviewPanel);
expect(focus).toBe(0);
expect(blur).toBe(0);
// container has focus within
fireEvent.focus(contentRenderer.element);
expect(focus).toBe(1);
expect(blur).toBe(0);
// container looses focus
fireEvent.blur(contentRenderer.element);
jest.runAllTimers();
expect(focus).toBe(1);
expect(blur).toBe(1);
const contentRenderer2 = new TestContentRenderer('id-2');
const panel2 = {
view: {
content: contentRenderer2,
} as Partial<IDockviewPanelModel>,
api: { renderer: 'onlyWhenVisible' },
} as Partial<IDockviewPanel>;
cut.openPanel(panel2 as IDockviewPanel);
// expect(focus).toBe(2);
// expect(blur).toBe(1);
// new panel recieves focus
fireEvent.focus(contentRenderer2.element);
expect(focus).toBe(2);
expect(blur).toBe(1);
// new panel looses focus
fireEvent.blur(contentRenderer2.element);
jest.runAllTimers();
expect(focus).toBe(2);
expect(blur).toBe(2);
disposable.dispose();
});
test("that panels renderered as 'onlyWhenVisible' are removed when closed", () => {
const overlayRenderContainer = fromPartial<OverlayRenderContainer>({
detatch: jest.fn(),
});
const cut = new ContentContainer(
fromPartial<DockviewComponent>({
overlayRenderContainer,
}),
fromPartial<DockviewGroupPanelModel>({
renderContainer: overlayRenderContainer,
})
);
const panel1 = fromPartial<IDockviewPanel>({
api: {
renderer: 'onlyWhenVisible',
},
view: { content: new TestContentRenderer('panel_1') },
});
const panel2 = fromPartial<IDockviewPanel>({
api: {
renderer: 'onlyWhenVisible',
},
view: { content: new TestContentRenderer('panel_2') },
});
cut.openPanel(panel1);
expect(panel1.view.content.element.parentElement).toBe(cut.element);
expect(cut.element.childNodes.length).toBe(1);
cut.openPanel(panel2);
expect(panel1.view.content.element.parentElement).toBeNull();
expect(panel2.view.content.element.parentElement).toBe(cut.element);
expect(cut.element.childNodes.length).toBe(1);
});
});

View File

@ -0,0 +1,310 @@
import { fireEvent } from '@testing-library/dom';
import {
LocalSelectionTransfer,
PanelTransfer,
} from '../../../dnd/dataTransfer';
import { DockviewComponent } from '../../../dockview/dockviewComponent';
import { DockviewGroupPanel } from '../../../dockview/dockviewGroupPanel';
import { DockviewGroupPanelModel } from '../../../dockview/dockviewGroupPanelModel';
import { Tab } from '../../../dockview/components/tab/tab';
import { IDockviewPanel } from '../../../dockview/dockviewPanel';
import { fromPartial } from '@total-typescript/shoehorn';
describe('tab', () => {
test('that empty tab has inactive-tab class', () => {
const accessorMock = jest.fn();
const groupMock = jest.fn();
const cut = new Tab(
{ id: 'panelId' } as IDockviewPanel,
new accessorMock(),
new groupMock()
);
expect(cut.element.className).toBe('dv-tab dv-inactive-tab');
});
test('that active tab has active-tab class', () => {
const accessorMock = jest.fn();
const groupMock = jest.fn();
const cut = new Tab(
{ id: 'panelId' } as IDockviewPanel,
new accessorMock(),
new groupMock()
);
cut.setActive(true);
expect(cut.element.className).toBe('dv-tab dv-active-tab');
cut.setActive(false);
expect(cut.element.className).toBe('dv-tab dv-inactive-tab');
});
test('that an external event does not render a drop target and calls through to the group model', () => {
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => {
return {
id: 'testcomponentid',
};
});
const groupView = fromPartial<DockviewGroupPanelModel>({
canDisplayOverlay: jest.fn(),
});
const groupPanelMock = jest.fn<Partial<DockviewGroupPanel>, []>(() => {
return {
id: 'testgroupid',
model: groupView,
};
});
const accessor = new accessorMock() as DockviewComponent;
const groupPanel = new groupPanelMock() as DockviewGroupPanel;
const cut = new Tab(
{ id: 'panelId' } as IDockviewPanel,
accessor,
groupPanel
);
jest.spyOn(cut.element, 'offsetHeight', 'get').mockImplementation(
() => 100
);
jest.spyOn(cut.element, 'offsetWidth', 'get').mockImplementation(
() => 100
);
fireEvent.dragEnter(cut.element);
fireEvent.dragOver(cut.element);
expect(groupView.canDisplayOverlay).toHaveBeenCalled();
expect(
cut.element.getElementsByClassName('dv-drop-target-dropzone').length
).toBe(0);
});
test('that if you drag over yourself a drop target is shown', () => {
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => {
return {
id: 'testcomponentid',
};
});
const groupView = fromPartial<DockviewGroupPanelModel>({
canDisplayOverlay: jest.fn(),
});
const groupPanelMock = jest.fn<Partial<DockviewGroupPanel>, []>(() => {
return {
id: 'testgroupid',
model: groupView,
};
});
const accessor = new accessorMock() as DockviewComponent;
const groupPanel = new groupPanelMock() as DockviewGroupPanel;
const cut = new Tab(
{ id: 'panel1' } as IDockviewPanel,
accessor,
groupPanel
);
jest.spyOn(cut.element, 'offsetHeight', 'get').mockImplementation(
() => 100
);
jest.spyOn(cut.element, 'offsetWidth', 'get').mockImplementation(
() => 100
);
LocalSelectionTransfer.getInstance().setData(
[new PanelTransfer('testcomponentid', 'anothergroupid', 'panel1')],
PanelTransfer.prototype
);
fireEvent.dragEnter(cut.element);
fireEvent.dragOver(cut.element);
expect(groupView.canDisplayOverlay).toHaveBeenCalledTimes(0);
expect(
cut.element.getElementsByClassName('dv-drop-target-dropzone').length
).toBe(1);
});
test('that if you drag over another tab a drop target is shown', () => {
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => {
return {
id: 'testcomponentid',
};
});
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
() => {
return {
canDisplayOverlay: jest.fn(),
};
}
);
const groupView = new groupviewMock() as DockviewGroupPanelModel;
const groupPanelMock = jest.fn<Partial<DockviewGroupPanel>, []>(() => {
return {
id: 'testgroupid',
model: groupView,
};
});
const accessor = new accessorMock() as DockviewComponent;
const groupPanel = new groupPanelMock() as DockviewGroupPanel;
const cut = new Tab(
{ id: 'panel1' } as IDockviewPanel,
accessor,
groupPanel
);
jest.spyOn(cut.element, 'offsetHeight', 'get').mockImplementation(
() => 100
);
jest.spyOn(cut.element, 'offsetWidth', 'get').mockImplementation(
() => 100
);
LocalSelectionTransfer.getInstance().setData(
[new PanelTransfer('testcomponentid', 'anothergroupid', 'panel2')],
PanelTransfer.prototype
);
fireEvent.dragEnter(cut.element);
fireEvent.dragOver(cut.element);
expect(groupView.canDisplayOverlay).toBeCalledTimes(0);
expect(
cut.element.getElementsByClassName('dv-drop-target-dropzone').length
).toBe(1);
});
test('that dropping on a tab with the same id but from a different component should not render a drop over and call through to the group model', () => {
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => {
return {
id: 'testcomponentid',
};
});
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
() => {
return {
canDisplayOverlay: jest.fn(),
};
}
);
const groupView = new groupviewMock() as DockviewGroupPanelModel;
const groupPanelMock = jest.fn<Partial<DockviewGroupPanel>, []>(() => {
return {
id: 'testgroupid',
model: groupView,
};
});
const accessor = new accessorMock() as DockviewComponent;
const groupPanel = new groupPanelMock() as DockviewGroupPanel;
const cut = new Tab(
{ id: 'panel1' } as IDockviewPanel,
accessor,
groupPanel
);
jest.spyOn(cut.element, 'offsetHeight', 'get').mockImplementation(
() => 100
);
jest.spyOn(cut.element, 'offsetWidth', 'get').mockImplementation(
() => 100
);
LocalSelectionTransfer.getInstance().setData(
[
new PanelTransfer(
'anothercomponentid',
'anothergroupid',
'panel1'
),
],
PanelTransfer.prototype
);
fireEvent.dragEnter(cut.element);
fireEvent.dragOver(cut.element);
expect(groupView.canDisplayOverlay).toBeCalledTimes(1);
expect(
cut.element.getElementsByClassName('dv-drop-target-dropzone').length
).toBe(0);
});
test('that dropping on a tab from a different component should not render a drop over and call through to the group model', () => {
const accessorMock = jest.fn<Partial<DockviewComponent>, []>(() => {
return {
id: 'testcomponentid',
};
});
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
() => {
return {
canDisplayOverlay: jest.fn(),
};
}
);
const groupView = new groupviewMock() as DockviewGroupPanelModel;
const groupPanelMock = jest.fn<Partial<DockviewGroupPanel>, []>(() => {
return {
id: 'testgroupid',
model: groupView,
};
});
const accessor = new accessorMock() as DockviewComponent;
const groupPanel = new groupPanelMock() as DockviewGroupPanel;
const cut = new Tab(
{ id: 'panel1' } as IDockviewPanel,
accessor,
groupPanel
);
jest.spyOn(cut.element, 'offsetHeight', 'get').mockImplementation(
() => 100
);
jest.spyOn(cut.element, 'offsetWidth', 'get').mockImplementation(
() => 100
);
LocalSelectionTransfer.getInstance().setData(
[
new PanelTransfer(
'anothercomponentid',
'anothergroupid',
'panel2'
),
],
PanelTransfer.prototype
);
fireEvent.dragEnter(cut.element);
fireEvent.dragOver(cut.element);
expect(groupView.canDisplayOverlay).toBeCalledTimes(1);
expect(
cut.element.getElementsByClassName('dv-drop-target-dropzone').length
).toBe(0);
});
});

View File

@ -0,0 +1,63 @@
import { DockviewApi } from '../../../../api/component.api';
import { DockviewPanelApi, TitleEvent } from '../../../../api/dockviewPanelApi';
import { DefaultTab } from '../../../../dockview/components/tab/defaultTab';
import { fromPartial } from '@total-typescript/shoehorn';
import { Emitter } from '../../../../events';
import { fireEvent } from '@testing-library/dom';
describe('defaultTab', () => {
test('that title updates', () => {
const cut = new DefaultTab();
let el = cut.element.querySelector('.dv-default-tab-content');
expect(el).toBeTruthy();
expect(el!.textContent).toBe('');
const onDidTitleChange = new Emitter<TitleEvent>();
const api = fromPartial<DockviewPanelApi>({
onDidTitleChange: onDidTitleChange.event,
});
const containerApi = fromPartial<DockviewApi>({});
cut.init({
api,
containerApi,
params: {},
title: 'title_abc',
});
el = cut.element.querySelector('.dv-default-tab-content');
expect(el).toBeTruthy();
expect(el!.textContent).toBe('title_abc');
onDidTitleChange.fire({ title: 'title_def' });
expect(el!.textContent).toBe('title_def');
});
test('that click closes tab', () => {
const cut = new DefaultTab();
const api = fromPartial<DockviewPanelApi>({
onDidTitleChange: jest.fn(),
close: jest.fn(),
});
const containerApi = fromPartial<DockviewApi>({});
cut.init({
api,
containerApi,
params: {},
title: 'title_abc',
});
let el = cut.element.querySelector('.dv-default-tab-action');
fireEvent.pointerDown(el!);
expect(api.close).toHaveBeenCalledTimes(0);
fireEvent.click(el!);
expect(api.close).toHaveBeenCalledTimes(1);
});
});

View File

@ -0,0 +1,66 @@
import { Tabs } from '../../../../dockview/components/titlebar/tabs';
import { fromPartial } from '@total-typescript/shoehorn';
import { DockviewGroupPanel } from '../../../../dockview/dockviewGroupPanel';
import { DockviewComponent } from '../../../../dockview/dockviewComponent';
describe('tabs', () => {
describe('disableCustomScrollbars', () => {
test('enabled by default', () => {
const cut = new Tabs(
fromPartial<DockviewGroupPanel>({}),
fromPartial<DockviewComponent>({
options: {},
}),
{
showTabsOverflowControl: true,
}
);
expect(
cut.element.querySelectorAll(
'.dv-scrollable > .dv-tabs-container'
).length
).toBe(1);
});
test('enabled when disabled flag is false', () => {
const cut = new Tabs(
fromPartial<DockviewGroupPanel>({}),
fromPartial<DockviewComponent>({
options: {
scrollbars: 'custom',
},
}),
{
showTabsOverflowControl: true,
}
);
expect(
cut.element.querySelectorAll(
'.dv-scrollable > .dv-tabs-container'
).length
).toBe(1);
});
test('disabled when disabled flag is true', () => {
const cut = new Tabs(
fromPartial<DockviewGroupPanel>({}),
fromPartial<DockviewComponent>({
options: {
scrollbars: 'native',
},
}),
{
showTabsOverflowControl: true,
}
);
expect(
cut.element.querySelectorAll(
'.dv-scrollable > .dv-tabs-container'
).length
).toBe(0);
});
});
});

View File

@ -0,0 +1,867 @@
import {
LocalSelectionTransfer,
PanelTransfer,
} from '../../../../dnd/dataTransfer';
import { TabsContainer } from '../../../../dockview/components/titlebar/tabsContainer';
import { DockviewComponent } from '../../../../dockview/dockviewComponent';
import { DockviewGroupPanel } from '../../../../dockview/dockviewGroupPanel';
import { DockviewGroupPanelModel } from '../../../../dockview/dockviewGroupPanelModel';
import { fireEvent } from '@testing-library/dom';
import { TestPanel } from '../../dockviewGroupPanelModel.spec';
import { IDockviewPanel } from '../../../../dockview/dockviewPanel';
import { fromPartial } from '@total-typescript/shoehorn';
import { DockviewPanelApi } from '../../../../api/dockviewPanelApi';
describe('tabsContainer', () => {
test('that an external event does not render a drop target and calls through to the group mode', () => {
const accessor = fromPartial<DockviewComponent>({
onDidAddPanel: jest.fn(),
onDidRemovePanel: jest.fn(),
options: {},
onDidOptionsChange: jest.fn(),
});
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
() => {
return {
canDisplayOverlay: jest.fn(),
};
}
);
const groupView = new groupviewMock() as DockviewGroupPanelModel;
const groupPanelMock = jest.fn<Partial<DockviewGroupPanel>, []>(() => {
return {
model: groupView,
};
});
const groupPanel = new groupPanelMock() as DockviewGroupPanel;
const cut = new TabsContainer(accessor, groupPanel);
const emptySpace = cut.element
.getElementsByClassName('dv-void-container')
.item(0) as HTMLElement;
if (!emptySpace!) {
fail('element not found');
}
jest.spyOn(emptySpace!, 'offsetHeight', 'get').mockImplementation(
() => 100
);
jest.spyOn(emptySpace!, 'offsetWidth', 'get').mockImplementation(
() => 100
);
fireEvent.dragEnter(emptySpace!);
fireEvent.dragOver(emptySpace!);
expect(groupView.canDisplayOverlay).toHaveBeenCalled();
expect(
cut.element.getElementsByClassName('dv-drop-target-dropzone').length
).toBe(0);
});
test('that a drag over event from another tab should render a drop target', () => {
const accessor = fromPartial<DockviewComponent>({
id: 'testcomponentid',
onDidAddPanel: jest.fn(),
onDidRemovePanel: jest.fn(),
options: {},
onDidOptionsChange: jest.fn(),
});
const dropTargetContainer = document.createElement('div');
const groupView = fromPartial<DockviewGroupPanelModel>({
canDisplayOverlay: jest.fn(),
// dropTargetContainer: new DropTargetAnchorContainer(
// dropTargetContainer
// ),
});
const groupPanelMock = jest.fn<Partial<DockviewGroupPanel>, []>(() => {
return {
id: 'testgroupid',
model: groupView,
panels: [],
};
});
const groupPanel = new groupPanelMock() as DockviewGroupPanel;
const cut = new TabsContainer(accessor, groupPanel);
const emptySpace = cut.element
.getElementsByClassName('dv-void-container')
.item(0) as HTMLElement;
if (!emptySpace!) {
fail('element not found');
}
jest.spyOn(emptySpace!, 'offsetHeight', 'get').mockImplementation(
() => 100
);
jest.spyOn(emptySpace!, 'offsetWidth', 'get').mockImplementation(
() => 100
);
LocalSelectionTransfer.getInstance().setData(
[
new PanelTransfer(
'testcomponentid',
'anothergroupid',
'anotherpanelid'
),
],
PanelTransfer.prototype
);
fireEvent.dragEnter(emptySpace!);
fireEvent.dragOver(emptySpace!);
expect(groupView.canDisplayOverlay).toHaveBeenCalledTimes(0);
expect(
cut.element.getElementsByClassName('dv-drop-target-dropzone').length
).toBe(1);
// expect(
// dropTargetContainer.getElementsByClassName('dv-drop-target-anchor')
// .length
// ).toBe(1);
});
test('that dropping over the empty space should render a drop target', () => {
const accessor = fromPartial<DockviewComponent>({
id: 'testcomponentid',
onDidAddPanel: jest.fn(),
onDidRemovePanel: jest.fn(),
options: {},
onDidOptionsChange: jest.fn(),
});
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
() => {
return {
canDisplayOverlay: jest.fn(),
};
}
);
const groupView = new groupviewMock() as DockviewGroupPanelModel;
const groupPanelMock = jest.fn<Partial<DockviewGroupPanel>, []>(() => {
return {
id: 'testgroupid',
model: groupView,
panels: [],
};
});
const groupPanel = new groupPanelMock() as DockviewGroupPanel;
const cut = new TabsContainer(accessor, groupPanel);
cut.openPanel(new TestPanel('panel1', jest.fn() as any));
cut.openPanel(new TestPanel('panel2', jest.fn() as any));
const emptySpace = cut.element
.getElementsByClassName('dv-void-container')
.item(0) as HTMLElement;
if (!emptySpace!) {
fail('element not found');
}
jest.spyOn(emptySpace!, 'offsetHeight', 'get').mockImplementation(
() => 100
);
jest.spyOn(emptySpace!, 'offsetWidth', 'get').mockImplementation(
() => 100
);
LocalSelectionTransfer.getInstance().setData(
[new PanelTransfer('testcomponentid', 'anothergroupid', 'panel2')],
PanelTransfer.prototype
);
fireEvent.dragEnter(emptySpace!);
fireEvent.dragOver(emptySpace!);
expect(groupView.canDisplayOverlay).toHaveBeenCalledTimes(0);
expect(
cut.element.getElementsByClassName('dv-drop-target-dropzone').length
).toBe(1);
});
test('that dropping the first tab should render a drop target', () => {
const accessor = fromPartial<DockviewComponent>({
id: 'testcomponentid',
onDidAddPanel: jest.fn(),
onDidRemovePanel: jest.fn(),
options: {},
onDidOptionsChange: jest.fn(),
});
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
() => {
return {
canDisplayOverlay: jest.fn(),
};
}
);
const groupView = new groupviewMock() as DockviewGroupPanelModel;
const groupPanelMock = jest.fn<Partial<DockviewGroupPanel>, []>(() => {
return {
id: 'testgroupid',
model: groupView,
panels: [],
};
});
const groupPanel = new groupPanelMock() as DockviewGroupPanel;
const cut = new TabsContainer(accessor, groupPanel);
cut.openPanel(new TestPanel('panel1', jest.fn() as any));
cut.openPanel(new TestPanel('panel2', jest.fn() as any));
const emptySpace = cut.element
.getElementsByClassName('dv-void-container')
.item(0) as HTMLElement;
if (!emptySpace!) {
fail('element not found');
}
jest.spyOn(emptySpace!, 'offsetHeight', 'get').mockImplementation(
() => 100
);
jest.spyOn(emptySpace!, 'offsetWidth', 'get').mockImplementation(
() => 100
);
LocalSelectionTransfer.getInstance().setData(
[new PanelTransfer('testcomponentid', 'anothergroupid', 'panel1')],
PanelTransfer.prototype
);
fireEvent.dragEnter(emptySpace!);
fireEvent.dragOver(emptySpace!);
expect(groupView.canDisplayOverlay).toHaveBeenCalledTimes(0);
expect(
cut.element.getElementsByClassName('dv-drop-target-dropzone').length
).toBe(1);
});
test('that dropping a tab from another component should not render a drop target', () => {
const accessor = fromPartial<DockviewComponent>({
id: 'testcomponentid',
onDidAddPanel: jest.fn(),
onDidRemovePanel: jest.fn(),
options: {},
onDidOptionsChange: jest.fn(),
});
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
() => {
return {
canDisplayOverlay: jest.fn(),
};
}
);
const groupView = new groupviewMock() as DockviewGroupPanelModel;
const groupPanelMock = jest.fn<Partial<DockviewGroupPanel>, []>(() => {
return {
id: 'testgroupid',
model: groupView,
};
});
const groupPanel = new groupPanelMock() as DockviewGroupPanel;
const cut = new TabsContainer(accessor, groupPanel);
cut.openPanel(new TestPanel('panel1', jest.fn() as any));
cut.openPanel(new TestPanel('panel2', jest.fn() as any));
const emptySpace = cut.element
.getElementsByClassName('dv-void-container')
.item(0) as HTMLElement;
if (!emptySpace!) {
fail('element not found');
}
jest.spyOn(emptySpace!, 'offsetHeight', 'get').mockImplementation(
() => 100
);
jest.spyOn(emptySpace!, 'offsetWidth', 'get').mockImplementation(
() => 100
);
LocalSelectionTransfer.getInstance().setData(
[
new PanelTransfer(
'anothercomponentid',
'anothergroupid',
'panel1'
),
],
PanelTransfer.prototype
);
fireEvent.dragEnter(emptySpace!);
fireEvent.dragOver(emptySpace!);
expect(groupView.canDisplayOverlay).toHaveBeenCalledTimes(1);
expect(
cut.element.getElementsByClassName('dv-drop-target-dropzone').length
).toBe(0);
});
test('left actions', () => {
const accessor = fromPartial<DockviewComponent>({
id: 'testcomponentid',
onDidAddPanel: jest.fn(),
onDidRemovePanel: jest.fn(),
options: {},
onDidOptionsChange: jest.fn(),
});
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
return (<Partial<DockviewGroupPanel>>{}) as DockviewGroupPanel;
});
const groupPanel = new groupPanelMock();
const cut = new TabsContainer(accessor, groupPanel);
let query = cut.element.querySelectorAll(
'.dv-tabs-and-actions-container > .dv-left-actions-container'
);
expect(query.length).toBe(1);
expect(query[0].children.length).toBe(0);
// add left action
const left = document.createElement('div');
left.className = 'test-left-actions-element';
cut.setLeftActionsElement(left);
query = cut.element.querySelectorAll(
'.dv-tabs-and-actions-container > .dv-left-actions-container'
);
expect(query.length).toBe(1);
expect(query[0].children.item(0)?.className).toBe(
'test-left-actions-element'
);
expect(query[0].children.length).toBe(1);
// add left action
const left2 = document.createElement('div');
left2.className = 'test-left-actions-element-2';
cut.setLeftActionsElement(left2);
query = cut.element.querySelectorAll(
'.dv-tabs-and-actions-container > .dv-left-actions-container'
);
expect(query.length).toBe(1);
expect(query[0].children.item(0)?.className).toBe(
'test-left-actions-element-2'
);
expect(query[0].children.length).toBe(1);
// remove left action
cut.setLeftActionsElement(undefined);
query = cut.element.querySelectorAll(
'.dv-tabs-and-actions-container > .dv-left-actions-container'
);
expect(query.length).toBe(1);
expect(query[0].children.length).toBe(0);
});
test('right actions', () => {
const accessor = fromPartial<DockviewComponent>({
id: 'testcomponentid',
onDidAddPanel: jest.fn(),
onDidRemovePanel: jest.fn(),
options: {},
onDidOptionsChange: jest.fn(),
});
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
return (<Partial<DockviewGroupPanel>>{}) as DockviewGroupPanel;
});
const groupPanel = new groupPanelMock();
const cut = new TabsContainer(accessor, groupPanel);
let query = cut.element.querySelectorAll(
'.dv-tabs-and-actions-container > .dv-right-actions-container'
);
expect(query.length).toBe(1);
expect(query[0].children.length).toBe(0);
// add right action
const right = document.createElement('div');
right.className = 'test-right-actions-element';
cut.setRightActionsElement(right);
query = cut.element.querySelectorAll(
'.dv-tabs-and-actions-container > .dv-right-actions-container'
);
expect(query.length).toBe(1);
expect(query[0].children.item(0)?.className).toBe(
'test-right-actions-element'
);
expect(query[0].children.length).toBe(1);
// add right action
const right2 = document.createElement('div');
right2.className = 'test-right-actions-element-2';
cut.setRightActionsElement(right2);
query = cut.element.querySelectorAll(
'.dv-tabs-and-actions-container > .dv-right-actions-container'
);
expect(query.length).toBe(1);
expect(query[0].children.item(0)?.className).toBe(
'test-right-actions-element-2'
);
expect(query[0].children.length).toBe(1);
// remove right action
cut.setRightActionsElement(undefined);
query = cut.element.querySelectorAll(
'.dv-tabs-and-actions-container > .dv-right-actions-container'
);
expect(query.length).toBe(1);
expect(query[0].children.length).toBe(0);
});
test('that a tab will become floating when clicked if not floating and shift is selected', () => {
const accessor = fromPartial<DockviewComponent>({
options: {},
onDidAddPanel: jest.fn(),
onDidRemovePanel: jest.fn(),
element: document.createElement('div'),
addFloatingGroup: jest.fn(),
doSetGroupActive: jest.fn(),
onDidOptionsChange: jest.fn(),
});
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
return (<Partial<DockviewGroupPanel>>{
api: { location: { type: 'grid' } } as any,
}) as DockviewGroupPanel;
});
const groupPanel = new groupPanelMock();
const cut = new TabsContainer(accessor, groupPanel);
const container = cut.element.querySelector('.dv-void-container')!;
expect(container).toBeTruthy();
jest.spyOn(cut.element, 'getBoundingClientRect').mockImplementation(
() => {
return { top: 50, left: 100, width: 0, height: 0 } as any;
}
);
jest.spyOn(
accessor.element,
'getBoundingClientRect'
).mockImplementation(() => {
return { top: 10, left: 20, width: 0, height: 0 } as any;
});
const event = new KeyboardEvent('pointerdown', { shiftKey: true });
const eventPreventDefaultSpy = jest.spyOn(event, 'preventDefault');
fireEvent(container, event);
expect(accessor.doSetGroupActive).toHaveBeenCalledWith(groupPanel);
expect(accessor.addFloatingGroup).toHaveBeenCalledWith(groupPanel, {
x: 100,
y: 60,
inDragMode: true,
});
expect(accessor.addFloatingGroup).toHaveBeenCalledTimes(1);
expect(eventPreventDefaultSpy).toHaveBeenCalledTimes(1);
const event2 = new KeyboardEvent('pointerdown', { shiftKey: false });
const eventPreventDefaultSpy2 = jest.spyOn(event2, 'preventDefault');
fireEvent(container, event2);
expect(accessor.addFloatingGroup).toHaveBeenCalledTimes(1);
expect(eventPreventDefaultSpy2).toHaveBeenCalledTimes(0);
});
test('that a tab that is already floating cannot be floated again', () => {
const accessor = fromPartial<DockviewComponent>({
options: {},
onDidAddPanel: jest.fn(),
onDidRemovePanel: jest.fn(),
element: document.createElement('div'),
addFloatingGroup: jest.fn(),
doSetGroupActive: jest.fn(),
onDidOptionsChange: jest.fn(),
});
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
return (<Partial<DockviewGroupPanel>>{
api: { location: { type: 'floating' } } as any,
}) as DockviewGroupPanel;
});
const groupPanel = new groupPanelMock();
const cut = new TabsContainer(accessor, groupPanel);
const container = cut.element.querySelector('.dv-void-container')!;
expect(container).toBeTruthy();
jest.spyOn(cut.element, 'getBoundingClientRect').mockImplementation(
() => {
return { top: 50, left: 100, width: 0, height: 0 } as any;
}
);
jest.spyOn(
accessor.element,
'getBoundingClientRect'
).mockImplementation(() => {
return { top: 10, left: 20, width: 0, height: 0 } as any;
});
const event = new KeyboardEvent('pointerdown', { shiftKey: true });
const eventPreventDefaultSpy = jest.spyOn(event, 'preventDefault');
fireEvent(container, event);
expect(accessor.doSetGroupActive).toHaveBeenCalledWith(groupPanel);
expect(accessor.addFloatingGroup).toHaveBeenCalledTimes(0);
expect(eventPreventDefaultSpy).toHaveBeenCalledTimes(0);
const event2 = new KeyboardEvent('pointerdown', { shiftKey: false });
const eventPreventDefaultSpy2 = jest.spyOn(event2, 'preventDefault');
fireEvent(container, event2);
expect(accessor.addFloatingGroup).toHaveBeenCalledTimes(0);
expect(eventPreventDefaultSpy2).toHaveBeenCalledTimes(0);
});
test('that selecting a tab with shift down will move that tab into a new floating group', () => {
const accessor = fromPartial<DockviewComponent>({
options: {},
onDidAddPanel: jest.fn(),
onDidRemovePanel: jest.fn(),
element: document.createElement('div'),
addFloatingGroup: jest.fn(),
getGroupPanel: jest.fn(),
onDidOptionsChange: jest.fn(),
});
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
return (<Partial<DockviewGroupPanel>>{
api: { location: { type: 'floating' } } as any,
model: {} as any,
}) as DockviewGroupPanel;
});
const groupPanel = new groupPanelMock();
const cut = new TabsContainer(accessor, groupPanel);
const createPanel = (id: string) =>
fromPartial<IDockviewPanel>({
id,
view: {
tab: {
element: document.createElement('div'),
},
content: {
element: document.createElement('div'),
},
},
});
const panel = createPanel('test_id');
cut.openPanel(panel);
const el = cut.element.querySelector('.dv-tab')!;
expect(el).toBeTruthy();
const event = new KeyboardEvent('pointerdown', { shiftKey: true });
const preventDefaultSpy = jest.spyOn(event, 'preventDefault');
fireEvent(el, event);
// a floating group with a single tab shouldn't be eligible
expect(preventDefaultSpy).toHaveBeenCalledTimes(0);
expect(accessor.addFloatingGroup).toHaveBeenCalledTimes(0);
const panel2 = createPanel('test_id_2');
cut.openPanel(panel2);
fireEvent(el, event);
expect(preventDefaultSpy).toHaveBeenCalledTimes(1);
expect(accessor.addFloatingGroup).toHaveBeenCalledTimes(1);
});
test('pre header actions', () => {
const accessor = fromPartial<DockviewComponent>({
options: {},
onDidAddPanel: jest.fn(),
onDidRemovePanel: jest.fn(),
element: document.createElement('div'),
addFloatingGroup: jest.fn(),
getGroupPanel: jest.fn(),
onDidOptionsChange: jest.fn(),
});
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
return (<Partial<DockviewGroupPanel>>{
api: { location: { type: 'grid' } } as any,
model: {} as any,
}) as DockviewGroupPanel;
});
const groupPanel = new groupPanelMock();
const cut = new TabsContainer(accessor, groupPanel);
const panelMock = jest.fn<IDockviewPanel, [string]>((id: string) => {
const partial: Partial<IDockviewPanel> = {
id,
view: {
tab: {
element: document.createElement('div'),
} as any,
content: {
element: document.createElement('div'),
} as any,
} as any,
};
return partial as IDockviewPanel;
});
const panel = new panelMock('test_id');
cut.openPanel(panel);
let result = cut.element.querySelector('.dv-pre-actions-container');
expect(result).toBeTruthy();
expect(result!.childNodes.length).toBe(0);
const actions = document.createElement('div');
cut.setPrefixActionsElement(actions);
result = cut.element.querySelector('.dv-pre-actions-container');
expect(result).toBeTruthy();
expect(result!.childNodes.length).toBe(1);
expect(result!.childNodes.item(0)).toBe(actions);
const updatedActions = document.createElement('div');
cut.setPrefixActionsElement(updatedActions);
result = cut.element.querySelector('.dv-pre-actions-container');
expect(result).toBeTruthy();
expect(result!.childNodes.length).toBe(1);
expect(result!.childNodes.item(0)).toBe(updatedActions);
cut.setPrefixActionsElement(undefined);
result = cut.element.querySelector('.dv-pre-actions-container');
expect(result).toBeTruthy();
expect(result!.childNodes.length).toBe(0);
});
test('left header actions', () => {
const accessor = fromPartial<DockviewComponent>({
options: {},
onDidAddPanel: jest.fn(),
onDidRemovePanel: jest.fn(),
element: document.createElement('div'),
addFloatingGroup: jest.fn(),
getGroupPanel: jest.fn(),
onDidOptionsChange: jest.fn(),
});
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
return (<Partial<DockviewGroupPanel>>{
api: { location: { type: 'grid' } } as any,
model: {} as any,
}) as DockviewGroupPanel;
});
const groupPanel = new groupPanelMock();
const cut = new TabsContainer(accessor, groupPanel);
const panelMock = jest.fn<IDockviewPanel, [string]>((id: string) => {
const partial: Partial<IDockviewPanel> = {
id,
view: {
tab: {
element: document.createElement('div'),
} as any,
content: {
element: document.createElement('div'),
} as any,
} as any,
};
return partial as IDockviewPanel;
});
const panel = new panelMock('test_id');
cut.openPanel(panel);
let result = cut.element.querySelector('.dv-left-actions-container');
expect(result).toBeTruthy();
expect(result!.childNodes.length).toBe(0);
const actions = document.createElement('div');
cut.setLeftActionsElement(actions);
result = cut.element.querySelector('.dv-left-actions-container');
expect(result).toBeTruthy();
expect(result!.childNodes.length).toBe(1);
expect(result!.childNodes.item(0)).toBe(actions);
const updatedActions = document.createElement('div');
cut.setLeftActionsElement(updatedActions);
result = cut.element.querySelector('.dv-left-actions-container');
expect(result).toBeTruthy();
expect(result!.childNodes.length).toBe(1);
expect(result!.childNodes.item(0)).toBe(updatedActions);
cut.setLeftActionsElement(undefined);
result = cut.element.querySelector('.dv-left-actions-container');
expect(result).toBeTruthy();
expect(result!.childNodes.length).toBe(0);
});
test('right header actions', () => {
const accessor = fromPartial<DockviewComponent>({
options: {},
onDidAddPanel: jest.fn(),
onDidRemovePanel: jest.fn(),
element: document.createElement('div'),
addFloatingGroup: jest.fn(),
getGroupPanel: jest.fn(),
onDidOptionsChange: jest.fn(),
});
const groupPanelMock = jest.fn<DockviewGroupPanel, []>(() => {
return (<Partial<DockviewGroupPanel>>{
api: { location: { type: 'grid' } } as any,
model: {} as any,
}) as DockviewGroupPanel;
});
const groupPanel = new groupPanelMock();
const cut = new TabsContainer(accessor, groupPanel);
const panelMock = jest.fn<IDockviewPanel, [string]>((id: string) => {
const partial: Partial<IDockviewPanel> = {
id,
view: {
tab: {
element: document.createElement('div'),
} as any,
content: {
element: document.createElement('div'),
} as any,
} as any,
};
return partial as IDockviewPanel;
});
const panel = new panelMock('test_id');
cut.openPanel(panel);
let result = cut.element.querySelector('.dv-right-actions-container');
expect(result).toBeTruthy();
expect(result!.childNodes.length).toBe(0);
const actions = document.createElement('div');
cut.setRightActionsElement(actions);
result = cut.element.querySelector('.dv-right-actions-container');
expect(result).toBeTruthy();
expect(result!.childNodes.length).toBe(1);
expect(result!.childNodes.item(0)).toBe(actions);
const updatedActions = document.createElement('div');
cut.setRightActionsElement(updatedActions);
result = cut.element.querySelector('.dv-right-actions-container');
expect(result).toBeTruthy();
expect(result!.childNodes.length).toBe(1);
expect(result!.childNodes.item(0)).toBe(updatedActions);
cut.setRightActionsElement(undefined);
result = cut.element.querySelector('.dv-right-actions-container');
expect(result).toBeTruthy();
expect(result!.childNodes.length).toBe(0);
});
test('class dv-single-tab is present when only one tab exists`', () => {
const cut = new TabsContainer(
fromPartial<DockviewComponent>({
options: {},
onDidOptionsChange: jest.fn(),
}),
fromPartial<DockviewGroupPanel>({})
);
expect(cut.element.classList.contains('dv-single-tab')).toBeFalsy();
const panel1 = new TestPanel(
'panel_1',
fromPartial<DockviewPanelApi>({})
);
cut.openPanel(panel1);
expect(cut.element.classList.contains('dv-single-tab')).toBeTruthy();
const panel2 = new TestPanel(
'panel_2',
fromPartial<DockviewPanelApi>({})
);
cut.openPanel(panel2);
expect(cut.element.classList.contains('dv-single-tab')).toBeFalsy();
cut.closePanel(panel1);
expect(cut.element.classList.contains('dv-single-tab')).toBeTruthy();
cut.closePanel(panel2);
expect(cut.element.classList.contains('dv-single-tab')).toBeFalsy();
});
});

View File

@ -0,0 +1,20 @@
import { VoidContainer } from '../../../../dockview/components/titlebar/voidContainer';
import { fromPartial } from '@total-typescript/shoehorn';
import { DockviewComponent } from '../../../../dockview/dockviewComponent';
import { DockviewGroupPanel } from '../../../../dockview/dockviewGroupPanel';
import { fireEvent } from '@testing-library/dom';
describe('voidContainer', () => {
test('that `pointerDown` triggers activation', () => {
const accessor = fromPartial<DockviewComponent>({
doSetGroupActive: jest.fn(),
});
const group = fromPartial<DockviewGroupPanel>({});
const cut = new VoidContainer(accessor, group);
expect(accessor.doSetGroupActive).not.toHaveBeenCalled();
fireEvent.pointerDown(cut.element);
expect(accessor.doSetGroupActive).toHaveBeenCalledWith(group);
});
});

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,190 @@
import { DockviewComponent } from '../../dockview/dockviewComponent';
import { DockviewGroupPanel } from '../../dockview/dockviewGroupPanel';
import { fromPartial } from '@total-typescript/shoehorn';
import { GroupOptions } from '../../dockview/dockviewGroupPanelModel';
import { DockviewPanel, IDockviewPanel } from '../../dockview/dockviewPanel';
import { DockviewPanelModelMock } from '../__mocks__/mockDockviewPanelModel';
import { IContentRenderer, ITabRenderer } from '../../dockview/types';
import { OverlayRenderContainer } from '../../overlay/overlayRenderContainer';
import { IDockviewPanelModel } from '../../dockview/dockviewPanelModel';
import { ContentContainer } from '../../dockview/components/panel/content';
describe('dockviewGroupPanel', () => {
test('default minimum/maximium width/height', () => {
const accessor = fromPartial<DockviewComponent>({
onDidActivePanelChange: jest.fn(),
onDidAddPanel: jest.fn(),
onDidRemovePanel: jest.fn(),
options: {},
onDidOptionsChange: jest.fn(),
});
const options = fromPartial<GroupOptions>({});
const cut = new DockviewGroupPanel(accessor, 'test_id', options);
expect(cut.minimumWidth).toBe(100);
expect(cut.minimumHeight).toBe(100);
expect(cut.maximumHeight).toBe(Number.MAX_SAFE_INTEGER);
expect(cut.maximumWidth).toBe(Number.MAX_SAFE_INTEGER);
});
test('that onDidActivePanelChange is configured at inline', () => {
const accessor = fromPartial<DockviewComponent>({
onDidActivePanelChange: jest.fn(),
onDidAddPanel: jest.fn(),
onDidRemovePanel: jest.fn(),
options: {},
api: {},
renderer: 'always',
overlayRenderContainer: {
attach: jest.fn(),
detatch: jest.fn(),
},
doSetGroupActive: jest.fn(),
onDidOptionsChange: jest.fn(),
});
const options = fromPartial<GroupOptions>({});
const cut = new DockviewGroupPanel(accessor, 'test_id', options);
let counter = 0;
cut.api.onDidActivePanelChange((event) => {
counter++;
});
cut.model.openPanel(
fromPartial<IDockviewPanel>({
updateParentGroup: jest.fn(),
view: {
tab: { element: document.createElement('div') },
content: new ContentContainer(accessor, cut.model),
},
api: {
renderer: 'onlyWhenVisible',
onDidTitleChange: jest.fn(),
onDidParametersChange: jest.fn(),
},
layout: jest.fn(),
runEvents: jest.fn(),
})
);
expect(counter).toBe(1);
});
test('group constraints', () => {
const accessor = fromPartial<DockviewComponent>({
onDidActivePanelChange: jest.fn(),
onDidAddPanel: jest.fn(),
onDidRemovePanel: jest.fn(),
doSetGroupActive: jest.fn(),
overlayRenderContainer: fromPartial<OverlayRenderContainer>({
attach: jest.fn(),
detatch: jest.fn(),
}),
options: {},
onDidOptionsChange: jest.fn(),
});
const options = fromPartial<GroupOptions>({});
const cut = new DockviewGroupPanel(accessor, 'test_id', options);
cut.api.setConstraints({
minimumHeight: 10,
maximumHeight: 100,
minimumWidth: 20,
maximumWidth: 200,
});
// initial constraints
expect(cut.minimumWidth).toBe(20);
expect(cut.minimumHeight).toBe(10);
expect(cut.maximumHeight).toBe(100);
expect(cut.maximumWidth).toBe(200);
const panelModel = new DockviewPanelModelMock(
'content_component',
fromPartial<IContentRenderer>({
element: document.createElement('div'),
}),
'tab_component',
fromPartial<ITabRenderer>({
element: document.createElement('div'),
})
);
const panel = new DockviewPanel(
'panel_id',
'component_id',
undefined,
accessor,
accessor.api,
cut,
panelModel,
{
renderer: 'onlyWhenVisible',
minimumWidth: 21,
minimumHeight: 11,
maximumHeight: 101,
maximumWidth: 201,
}
);
cut.model.openPanel(panel);
// active panel constraints
expect(cut.minimumWidth).toBe(21);
expect(cut.minimumHeight).toBe(11);
expect(cut.maximumHeight).toBe(101);
expect(cut.maximumWidth).toBe(201);
const panel2 = new DockviewPanel(
'panel_id',
'component_id',
undefined,
accessor,
accessor.api,
cut,
panelModel,
{
renderer: 'onlyWhenVisible',
minimumWidth: 22,
minimumHeight: 12,
maximumHeight: 102,
maximumWidth: 202,
}
);
cut.model.openPanel(panel2);
// active panel constraints
expect(cut.minimumWidth).toBe(22);
expect(cut.minimumHeight).toBe(12);
expect(cut.maximumHeight).toBe(102);
expect(cut.maximumWidth).toBe(202);
const panel3 = new DockviewPanel(
'panel_id',
'component_id',
undefined,
accessor,
accessor.api,
cut,
panelModel,
{
renderer: 'onlyWhenVisible',
}
);
cut.model.openPanel(panel3);
// active panel without specified constraints so falls back to group constraints
expect(cut.minimumWidth).toBe(20);
expect(cut.minimumHeight).toBe(10);
expect(cut.maximumHeight).toBe(100);
expect(cut.maximumWidth).toBe(200);
});
});

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,287 @@
import { DockviewComponent } from '../../dockview/dockviewComponent';
import { DockviewApi } from '../../api/component.api';
import { DockviewPanel } from '../../dockview/dockviewPanel';
import { IDockviewPanelModel } from '../../dockview/dockviewPanelModel';
import { DockviewGroupPanel } from '../../dockview/dockviewGroupPanel';
import { fromPartial } from '@total-typescript/shoehorn';
describe('dockviewPanel', () => {
test('update title', () => {
const api = fromPartial<DockviewApi>({});
const accessor = fromPartial<DockviewComponent>({});
const group = fromPartial<DockviewGroupPanel>({
api: {
onDidVisibilityChange: jest.fn(),
onDidLocationChange: jest.fn(),
onDidActiveChange: jest.fn(),
},
});
const model = fromPartial<IDockviewPanelModel>({
update: jest.fn(),
init: jest.fn(),
dispose: jest.fn(),
});
const cut = new DockviewPanel(
'fake-id',
'fake-component',
undefined,
accessor,
api,
group,
model,
{
renderer: 'onlyWhenVisible',
}
);
let latestTitle: string | undefined = undefined;
const disposable = cut.api.onDidTitleChange((event) => {
latestTitle = event.title;
});
expect(cut.title).toBeUndefined();
cut.init({ title: 'new title', params: {} });
expect(latestTitle).toBe('new title');
expect(cut.title).toBe('new title');
cut.setTitle('another title');
expect(latestTitle).toBe('another title');
expect(cut.title).toBe('another title');
disposable.dispose();
});
test('that .setTitle updates the title', () => {
const api = fromPartial<DockviewApi>({});
const accessor = fromPartial<DockviewComponent>({});
const group = fromPartial<DockviewGroupPanel>({
api: {
onDidVisibilityChange: jest.fn(),
onDidLocationChange: jest.fn(),
onDidActiveChange: jest.fn(),
},
});
const model = fromPartial<IDockviewPanelModel>({
update: jest.fn(),
init: jest.fn(),
});
const cut = new DockviewPanel(
'fake-id',
'fake-component',
undefined,
accessor,
api,
group,
model,
{
renderer: 'onlyWhenVisible',
}
);
cut.init({ title: 'myTitle', params: {} });
expect(cut.title).toBe('myTitle');
cut.setTitle('newTitle');
expect(cut.title).toBe('newTitle');
cut.api.setTitle('new title 2');
expect(cut.title).toBe('new title 2');
});
test('dispose cleanup', () => {
const api = fromPartial<DockviewApi>({});
const accessor = fromPartial<DockviewComponent>({});
const group = fromPartial<DockviewGroupPanel>({
api: {
onDidVisibilityChange: jest
.fn()
.mockReturnValue({ dispose: jest.fn() }),
onDidLocationChange: jest
.fn()
.mockReturnValue({ dispose: jest.fn() }),
onDidActiveChange: jest
.fn()
.mockReturnValue({ dispose: jest.fn() }),
},
});
const model = fromPartial<IDockviewPanelModel>({
update: jest.fn(),
init: jest.fn(),
dispose: jest.fn(),
});
const cut = new DockviewPanel(
'fake-id',
'fake-component',
undefined,
accessor,
api,
group,
model,
{
renderer: 'onlyWhenVisible',
}
);
cut.init({ params: {}, title: 'title' });
cut.dispose();
expect(model.dispose).toHaveBeenCalled();
});
test('get params', () => {
const api = fromPartial<DockviewApi>({});
const accessor = fromPartial<DockviewComponent>({});
const group = fromPartial<DockviewGroupPanel>({
api: {
onDidVisibilityChange: jest.fn(),
onDidLocationChange: jest.fn(),
onDidActiveChange: jest.fn(),
},
});
const model = fromPartial<IDockviewPanelModel>({
update: jest.fn(),
init: jest.fn(),
dispose: jest.fn(),
});
const cut = new DockviewPanel(
'fake-id',
'fake-component',
undefined,
accessor,
api,
group,
model,
{
renderer: 'onlyWhenVisible',
}
);
expect(cut.params).toEqual(undefined);
cut.update({ params: { variableA: 'A', variableB: 'B' } });
expect(cut.params).toEqual({ variableA: 'A', variableB: 'B' });
});
test('setSize propagates to underlying group', () => {
const api = fromPartial<DockviewApi>({});
const accessor = fromPartial<DockviewComponent>({});
const group = fromPartial<DockviewGroupPanel>({
api: {
onDidVisibilityChange: jest.fn(),
onDidLocationChange: jest.fn(),
onDidActiveChange: jest.fn(),
setSize: jest.fn(),
},
});
const model = fromPartial<IDockviewPanelModel>({
update: jest.fn(),
init: jest.fn(),
dispose: jest.fn(),
});
const cut = new DockviewPanel(
'fake-id',
'fake-component',
undefined,
accessor,
api,
group,
model,
{
renderer: 'onlyWhenVisible',
}
);
cut.api.setSize({ height: 123, width: 456 });
expect(group.api.setSize).toHaveBeenCalledWith({
height: 123,
width: 456,
});
expect(group.api.setSize).toHaveBeenCalledTimes(1);
});
test('updateParameter', () => {
const api = fromPartial<DockviewApi>({});
const accessor = fromPartial<DockviewComponent>({});
const group = fromPartial<DockviewGroupPanel>({
api: {
onDidVisibilityChange: jest.fn(),
onDidLocationChange: jest.fn(),
onDidActiveChange: jest.fn(),
},
});
const model = fromPartial<IDockviewPanelModel>({
update: jest.fn(),
init: jest.fn(),
dispose: jest.fn(),
});
const cut = new DockviewPanel(
'fake-id',
'fake-component',
undefined,
accessor,
api,
group,
model,
{
renderer: 'onlyWhenVisible',
}
);
cut.init({ params: { a: '1', b: '2' }, title: 'A title' });
expect(cut.params).toEqual({ a: '1', b: '2' });
// update 'a' and add 'c'
cut.update({ params: { a: '-1', c: '3' } });
expect(cut.params).toEqual({ a: '-1', b: '2', c: '3' });
expect(model.update).toHaveBeenCalledWith({
params: { a: '-1', b: '2', c: '3' },
});
cut.update({ params: { d: '4', e: '5', f: '6' } });
expect(cut.params).toEqual({
a: '-1',
b: '2',
c: '3',
d: '4',
e: '5',
f: '6',
});
expect(model.update).toHaveBeenCalledWith({
params: { a: '-1', b: '2', c: '3', d: '4', e: '5', f: '6' },
});
cut.update({
params: {
d: '',
e: null,
f: undefined,
g: '',
h: null,
i: undefined,
},
});
expect(cut.params).toEqual({
a: '-1',
b: '2',
c: '3',
d: '',
e: null,
g: '',
h: null,
});
expect(model.update).toHaveBeenCalledWith({
params: { a: '-1', b: '2', c: '3', d: '', e: null, g: '', h: null },
});
});
});

View File

@ -0,0 +1,200 @@
import { DockviewComponent } from '../../dockview/dockviewComponent';
import { DockviewPanelModel } from '../../dockview/dockviewPanelModel';
import { IContentRenderer, ITabRenderer } from '../../dockview/types';
import { DefaultTab } from '../../dockview/components/tab/defaultTab';
import { fromPartial } from '@total-typescript/shoehorn';
describe('dockviewGroupPanel', () => {
let contentMock: jest.Mock<IContentRenderer>;
let tabMock: jest.Mock<ITabRenderer>;
let accessorMock: DockviewComponent;
beforeEach(() => {
contentMock = jest.fn<IContentRenderer, []>(() => {
const partial: Partial<IContentRenderer> = {
element: document.createElement('div'),
dispose: jest.fn(),
update: jest.fn(),
};
return partial as IContentRenderer;
});
tabMock = jest.fn<ITabRenderer, []>(() => {
const partial: Partial<IContentRenderer> = {
element: document.createElement('div'),
dispose: jest.fn(),
update: jest.fn(),
};
return partial as IContentRenderer;
});
accessorMock = fromPartial<DockviewComponent>({
options: {
createComponent(options) {
switch (options.name) {
case 'contentComponent':
return new contentMock(options.id, options.name);
default:
throw new Error(`unsupported`);
}
},
createTabComponent(options) {
switch (options.name) {
case 'tabComponent':
return new tabMock(options.id, options.name);
default:
throw new Error(`unsupported`);
}
},
},
});
});
test('that dispose is called on content and tab renderers when present', () => {
const cut = new DockviewPanelModel(
accessorMock,
'id',
'contentComponent',
'tabComponent'
);
cut.dispose();
expect(cut.content.dispose).toHaveBeenCalled();
expect(cut.tab.dispose).toHaveBeenCalled();
});
test('that update is called on content and tab renderers when present', () => {
const cut = new DockviewPanelModel(
accessorMock,
'id',
'contentComponent',
'tabComponent'
);
cut.update({
params: {},
});
expect(cut.content.update).toHaveBeenCalled();
expect(cut.tab.update).toHaveBeenCalled();
});
test('that the default tab is created', () => {
accessorMock = fromPartial<DockviewComponent>({
options: {
createComponent(options) {
switch (options.name) {
case 'contentComponent':
return new contentMock(options.id, options.name);
default:
throw new Error(`unsupported`);
}
},
createTabComponent(options) {
switch (options.name) {
case 'tabComponent':
return tabMock;
default:
throw new Error(`unsupported`);
}
},
},
});
const cut = new DockviewPanelModel(
accessorMock,
'id',
'contentComponent',
'tabComponent'
);
expect(cut.tab).toEqual(tabMock);
});
test('that the provided default tab is chosen when no implementation is provided', () => {
accessorMock = fromPartial<DockviewComponent>({
options: {
defaultTabComponent: 'tabComponent',
createComponent(options) {
switch (options.name) {
case 'contentComponent':
return new contentMock(options.id, options.name);
default:
throw new Error(`unsupported`);
}
},
createTabComponent(options) {
switch (options.name) {
case 'tabComponent':
return tabMock;
default:
throw new Error(`unsupported`);
}
},
},
});
const cut = new DockviewPanelModel(
accessorMock,
'id',
'contentComponent'
);
expect(cut.tab).toEqual(tabMock);
});
test('that is library default tab instance is created when no alternative exists', () => {
accessorMock = fromPartial<DockviewComponent>({
options: {
createComponent(options) {
switch (options.name) {
case 'contentComponent':
return new contentMock(options.id, options.name);
default:
throw new Error(`unsupported`);
}
},
},
});
const cut = new DockviewPanelModel(
accessorMock,
'id',
'contentComponent'
);
expect(cut.tab instanceof DefaultTab).toBeTruthy();
});
test('that the default content is created', () => {
accessorMock = fromPartial<DockviewComponent>({
options: {
createComponent(options) {
switch (options.name) {
case 'contentComponent':
return contentMock;
default:
throw new Error(`unsupported`);
}
},
createTabComponent(options) {
switch (options.name) {
case 'tabComponent':
return tabMock;
default:
throw new Error(`unsupported`);
}
},
},
});
const cut = new DockviewPanelModel(
accessorMock,
'id',
'contentComponent'
);
expect(cut.content).toEqual(contentMock);
});
});

View File

@ -0,0 +1,83 @@
import {
disableIframePointEvents,
isInDocument,
quasiDefaultPrevented,
quasiPreventDefault,
} from '../dom';
describe('dom', () => {
test('quasiPreventDefault', () => {
const event = new Event('myevent');
expect((event as any)['dv-quasiPreventDefault']).toBeUndefined();
quasiPreventDefault(event);
expect((event as any)['dv-quasiPreventDefault']).toBe(true);
});
test('quasiDefaultPrevented', () => {
const event = new Event('myevent');
expect(quasiDefaultPrevented(event)).toBeFalsy();
(event as any)['dv-quasiPreventDefault'] = false;
expect(quasiDefaultPrevented(event)).toBeFalsy();
(event as any)['dv-quasiPreventDefault'] = true;
expect(quasiDefaultPrevented(event)).toBeTruthy();
});
test('isInDocument: DOM element', () => {
const el = document.createElement('div');
expect(isInDocument(el)).toBeFalsy();
document.body.appendChild(el);
expect(isInDocument(el)).toBeTruthy();
});
test('isInDocument: Shadow DOM element', () => {
const el = document.createElement('div');
document.body.appendChild(el);
const shadow = el.attachShadow({ mode: 'open' });
const el2 = document.createElement('div');
expect(isInDocument(el2)).toBeFalsy();
shadow.appendChild(el2);
expect(isInDocument(el2)).toBeTruthy();
});
test('disableIframePointEvents', () => {
const el1 = document.createElement('iframe');
const el2 = document.createElement('iframe');
const el3 = document.createElement('webview');
const el4 = document.createElement('webview');
document.body.appendChild(el1);
document.body.appendChild(el2);
document.body.appendChild(el3);
document.body.appendChild(el4);
el1.style.pointerEvents = 'inherit';
el3.style.pointerEvents = 'inherit';
expect(el1.style.pointerEvents).toBe('inherit');
expect(el2.style.pointerEvents).toBe('');
expect(el3.style.pointerEvents).toBe('inherit');
expect(el4.style.pointerEvents).toBe('');
const f = disableIframePointEvents();
expect(el1.style.pointerEvents).toBe('none');
expect(el2.style.pointerEvents).toBe('none');
expect(el3.style.pointerEvents).toBe('none');
expect(el4.style.pointerEvents).toBe('none');
f.release();
expect(el1.style.pointerEvents).toBe('inherit');
expect(el2.style.pointerEvents).toBe('');
expect(el3.style.pointerEvents).toBe('inherit');
expect(el4.style.pointerEvents).toBe('');
});
});

View File

@ -0,0 +1,278 @@
import {
AsapEvent,
Emitter,
Event,
addDisposableListener,
} from '../events';
describe('events', () => {
describe('emitter', () => {
it('debug mode is off', () => {
expect(Emitter.ENABLE_TRACKING).toBeFalsy();
});
it('should emit values', () => {
const emitter = new Emitter<number>();
let value: number | undefined = undefined;
emitter.fire(-1);
expect(value).toBeUndefined();
const stream = emitter.event((x) => {
value = x;
});
emitter.fire(0);
expect(value).toBe(0);
emitter.fire(1);
expect(value).toBe(1);
stream.dispose();
});
it('should stop emitting after dispose', () => {
const emitter = new Emitter<number>();
let value: number | undefined = undefined;
const stream = emitter.event((x) => {
value = x;
});
emitter.fire(0);
expect(value).toBe(0);
stream.dispose();
value = undefined;
emitter.fire(1);
expect(value).toBeUndefined();
});
it('should stop emitting after dispose', () => {
const emitter = new Emitter<number>();
let value: number | undefined = undefined;
const stream = emitter.event((x) => {
value = x;
});
emitter.fire(0);
expect(value).toBe(0);
stream.dispose();
value = undefined;
emitter.fire(1);
expect(value).toBeUndefined();
});
it('should relay last value in replay mode', () => {
const emitter = new Emitter<number>({ replay: true });
let value: number | undefined = undefined;
emitter.fire(1);
const stream = emitter.event((x) => {
value = x;
});
expect(value).toBe(1);
stream.dispose();
});
});
describe('asapEvent', () => {
test('that asapEvents fire once per event-loop-cycle', () => {
jest.useFakeTimers();
const event = new AsapEvent();
let preFireCount = 0;
let postFireCount = 0;
event.onEvent(() => {
preFireCount++;
});
for (let i = 0; i < 100; i++) {
event.fire();
}
/**
* check that subscribing after the events have fired but before the event-loop cycle completes
* results in no event fires.
*/
event.onEvent((e) => {
postFireCount++;
});
expect(preFireCount).toBe(0);
expect(postFireCount).toBe(0);
jest.runAllTimers();
expect(preFireCount).toBe(1);
expect(postFireCount).toBe(0);
});
});
it('should emit a value when any event fires', () => {
const emitter1 = new Emitter<number>();
const emitter2 = new Emitter<number>();
const emitter3 = new Emitter<number>();
let value: number | undefined = 0;
const stream = Event.any(
emitter1.event,
emitter2.event,
emitter3.event
)((x) => {
value = x;
});
emitter2.fire(2);
expect(value).toBe(2);
emitter1.fire(1);
expect(value).toBe(1);
emitter3.fire(3);
expect(value).toBe(3);
});
it('addDisposableListener with capture options', () => {
const element = {
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
};
const handler = jest.fn();
const disposable = addDisposableListener(
element as any,
'pointerdown',
handler,
true
);
expect(element.addEventListener).toBeCalledTimes(1);
expect(element.addEventListener).toHaveBeenCalledWith(
'pointerdown',
handler,
true
);
expect(element.removeEventListener).toBeCalledTimes(0);
disposable.dispose();
expect(element.addEventListener).toBeCalledTimes(1);
expect(element.removeEventListener).toBeCalledTimes(1);
expect(element.removeEventListener).toBeCalledWith(
'pointerdown',
handler,
true
);
});
it('addDisposableListener without capture options', () => {
const element = {
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
};
const handler = jest.fn();
const disposable = addDisposableListener(
element as any,
'pointerdown',
handler
);
expect(element.addEventListener).toBeCalledTimes(1);
expect(element.addEventListener).toHaveBeenCalledWith(
'pointerdown',
handler,
undefined
);
expect(element.removeEventListener).toBeCalledTimes(0);
disposable.dispose();
expect(element.addEventListener).toBeCalledTimes(1);
expect(element.removeEventListener).toBeCalledTimes(1);
expect(element.removeEventListener).toBeCalledWith(
'pointerdown',
handler,
undefined
);
});
it('addDisposableListener with capture options', () => {
const element = {
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
};
const handler = jest.fn();
const disposable = addDisposableListener(
element as any,
'pointerdown',
handler,
true
);
expect(element.addEventListener).toBeCalledTimes(1);
expect(element.addEventListener).toHaveBeenCalledWith(
'pointerdown',
handler,
true
);
expect(element.removeEventListener).toBeCalledTimes(0);
disposable.dispose();
expect(element.addEventListener).toBeCalledTimes(1);
expect(element.removeEventListener).toBeCalledTimes(1);
expect(element.removeEventListener).toBeCalledWith(
'pointerdown',
handler,
true
);
});
it('addDisposableListener without capture options', () => {
const element = {
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
};
const handler = jest.fn();
const disposable = addDisposableListener(
element as any,
'pointerdown',
handler
);
expect(element.addEventListener).toBeCalledTimes(1);
expect(element.addEventListener).toHaveBeenCalledWith(
'pointerdown',
handler,
undefined
);
expect(element.removeEventListener).toBeCalledTimes(0);
disposable.dispose();
expect(element.addEventListener).toBeCalledTimes(1);
expect(element.removeEventListener).toBeCalledTimes(1);
expect(element.removeEventListener).toBeCalledWith(
'pointerdown',
handler,
undefined
);
});
});

View File

@ -0,0 +1,206 @@
import { Emitter } from '../../events';
import {
BaseGrid,
IGridPanelView,
BaseGridOptions,
} from '../../gridview/baseComponentGridview';
import { IViewSize } from '../../gridview/gridview';
import { CompositeDisposable } from '../../lifecycle';
import {
PanelInitParameters,
PanelUpdateEvent,
Parameters,
} from '../../panel/types';
import { LayoutPriority, Orientation } from '../../splitview/splitview';
class TestPanel implements IGridPanelView {
_onDidChange = new Emitter<IViewSize | undefined>();
readonly onDidChange = this._onDidChange.event;
isVisible: boolean = true;
isActive: boolean = true;
params: Parameters = {};
constructor(
public readonly id: string,
public readonly element: HTMLElement,
public readonly minimumWidth: number,
public readonly maximumWidth: number,
public readonly minimumHeight: number,
public readonly maximumHeight: number,
public priority: LayoutPriority,
public snap: boolean
) {}
init(params: PanelInitParameters): void {
//
}
setActive(isActive: boolean): void {
//
}
toJSON(): object {
return {};
}
layout(width: number, height: number): void {
//
}
update(event: PanelUpdateEvent<Parameters>): void {
//
}
focus(): void {
//
}
fromJSON(json: object): void {
//
}
dispose(): void {
//
}
}
class ClassUnderTest extends BaseGrid<TestPanel> {
readonly gridview = this.gridview;
constructor(parentElement: HTMLElement, options: BaseGridOptions) {
super(parentElement, options);
}
doRemoveGroup(
group: TestPanel,
options?: { skipActive?: boolean; skipDispose?: boolean }
): TestPanel {
return super.doRemoveGroup(group, options);
}
doAddGroup(group: TestPanel, location?: number[], size?: number): void {
this._groups.set(group.id, {
value: group,
disposable: {
dispose: () => {
//
},
},
});
super.doAddGroup(group, location, size);
}
public fromJSON(data: any): void {
//
}
public toJSON(): object {
return {};
}
public clear(): void {
//
}
}
describe('baseComponentGridview', () => {
test('that the container is not removed when grid is disposed', () => {
const root = document.createElement('div');
const container = document.createElement('div');
root.appendChild(container);
const cut = new ClassUnderTest(container, {
orientation: Orientation.HORIZONTAL,
proportionalLayout: true,
});
cut.dispose();
expect(container.parentElement).toBe(root);
});
test('that .layout(...) force flag works', () => {
const cut = new ClassUnderTest(document.createElement('div'), {
orientation: Orientation.HORIZONTAL,
proportionalLayout: true,
});
const spy = jest.spyOn(cut.gridview, 'layout');
cut.layout(100, 100);
expect(spy).toHaveBeenCalledTimes(1);
cut.layout(100, 100, false);
expect(spy).toHaveBeenCalledTimes(1);
cut.layout(100, 100, true);
expect(spy).toHaveBeenCalledTimes(2);
cut.layout(150, 150, false);
expect(spy).toHaveBeenCalledTimes(3);
cut.layout(150, 150, true);
expect(spy).toHaveBeenCalledTimes(4);
});
test('can add group', () => {
const cut = new ClassUnderTest(document.createElement('div'), {
orientation: Orientation.HORIZONTAL,
proportionalLayout: true,
});
const events: { type: string; panel: TestPanel | undefined }[] = [];
const disposable = new CompositeDisposable(
cut.onDidAdd((event) => {
events.push({ type: 'add', panel: event });
}),
cut.onDidRemove((event) => {
events.push({ type: 'remove', panel: event });
}),
cut.onDidActiveChange((event) => {
events.push({ type: 'active', panel: event });
})
);
const panel1 = new TestPanel(
'id',
document.createElement('div'),
0,
100,
0,
100,
LayoutPriority.Normal,
false
);
cut.doAddGroup(panel1);
expect(events.length).toBe(1);
expect(events[0]).toEqual({ type: 'add', panel: panel1 });
const panel2 = new TestPanel(
'id',
document.createElement('div'),
0,
100,
0,
100,
LayoutPriority.Normal,
false
);
cut.doAddGroup(panel2);
expect(events.length).toBe(2);
expect(events[1]).toEqual({ type: 'add', panel: panel2 });
cut.doRemoveGroup(panel1);
expect(events.length).toBe(3);
expect(events[2]).toEqual({ type: 'remove', panel: panel1 });
disposable.dispose();
cut.dispose();
});
});

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,25 @@
import { DockviewComponent } from '../../dockview/dockviewComponent';
import { DockviewGroupPanel } from '../../dockview/dockviewGroupPanel';
describe('gridviewPanel', () => {
test('get panel', () => {
const accessorMock = jest.fn<DockviewComponent, []>(() => {
return {
onDidAddPanel: jest.fn(),
onDidRemovePanel: jest.fn(),
options: {},
onDidOptionsChange: jest.fn(),
} as any;
});
const accessor = new accessorMock();
const cut = new DockviewGroupPanel(accessor, 'id', {});
expect(cut.params).toEqual(undefined);
cut.update({ params: { variableA: 'A', variableB: 'B' } });
expect(cut.params).toEqual({ variableA: 'A', variableB: 'B' });
});
});

View File

@ -0,0 +1,83 @@
import {
CompositeDisposable,
Disposable,
MutableDisposable,
} from '../lifecycle';
describe('lifecycle', () => {
test('mutable disposable', () => {
const mutableDisposable = new MutableDisposable();
let disposed = 0;
const disposable = () => ({
dispose: () => {
disposed++;
},
});
mutableDisposable.value = disposable();
expect(disposed).toBe(0);
mutableDisposable.value = disposable();
expect(disposed).toBe(1);
mutableDisposable.dispose();
expect(disposed).toBe(2);
mutableDisposable.dispose();
});
test('composite disposable', () => {
const d1 = {
dispose: jest.fn(),
};
const d2 = {
dispose: jest.fn(),
};
const d3 = {
dispose: jest.fn(),
};
const d4 = {
dispose: jest.fn(),
};
const cut = new CompositeDisposable(d1, d2);
cut.addDisposables(d3, d4);
cut.dispose();
expect(d1.dispose).toHaveBeenCalledTimes(1);
expect(d2.dispose).toHaveBeenCalledTimes(1);
expect(d3.dispose).toHaveBeenCalledTimes(1);
expect(d4.dispose).toHaveBeenCalledTimes(1);
});
test('that isDisposed=true once CompositeDisposable is disposed', () => {
class Test extends CompositeDisposable {
checkIsDisposed(): boolean {
return this.isDisposed;
}
}
const cut = new Test();
expect(cut.checkIsDisposed()).toBeFalsy();
cut.dispose();
expect(cut.checkIsDisposed()).toBeTruthy();
});
test('Disposable.from(...)', () => {
const func = jest.fn();
const disposable = Disposable.from(func);
expect(func).not.toHaveBeenCalled();
disposable.dispose();
expect(func).toHaveBeenCalledTimes(1);
});
});

View File

@ -0,0 +1,21 @@
import { clamp, range } from '../math';
describe('math', () => {
describe('clamp', () => {
it('should clamp between a minimum and maximum value', () => {
expect(clamp(45, 40, 50)).toBe(45);
expect(clamp(35, 40, 50)).toBe(40);
expect(clamp(55, 40, 50)).toBe(50);
});
it('if min > max return min', () => {
expect(clamp(55, 50, 40)).toBe(50);
});
});
test('range', () => {
expect(range(0, 5)).toEqual([0, 1, 2, 3, 4]);
expect(range(5, 0)).toEqual([5, 4, 3, 2, 1]);
expect(range(5)).toEqual([0, 1, 2, 3, 4]);
});
});

View File

@ -0,0 +1,418 @@
import { Overlay } from '../../overlay/overlay';
import { mockGetBoundingClientRect } from '../__test_utils__/utils';
describe('overlay', () => {
test('toJSON, top left', () => {
const container = document.createElement('div');
const content = document.createElement('div');
document.body.appendChild(container);
container.appendChild(content);
const cut = new Overlay({
height: 200,
width: 100,
left: 10,
top: 20,
minimumInViewportWidth: 0,
minimumInViewportHeight: 0,
container,
content,
});
jest.spyOn(
container.childNodes.item(0) as HTMLElement,
'getBoundingClientRect'
).mockImplementation(() => {
return mockGetBoundingClientRect({
left: 80,
top: 100,
width: 40,
height: 50,
});
});
jest.spyOn(container, 'getBoundingClientRect').mockImplementation(
() => {
return mockGetBoundingClientRect({
left: 20,
top: 30,
width: 100,
height: 100,
});
}
);
cut.setBounds();
expect(cut.toJSON()).toEqual({
top: 70,
left: 60,
width: 40,
height: 50,
});
cut.dispose();
});
test('toJSON, bottom right', () => {
const container = document.createElement('div');
const content = document.createElement('div');
document.body.appendChild(container);
container.appendChild(content);
const cut = new Overlay({
height: 200,
width: 100,
right: 10,
bottom: 20,
minimumInViewportWidth: 0,
minimumInViewportHeight: 0,
container,
content,
});
jest.spyOn(
container.childNodes.item(0) as HTMLElement,
'getBoundingClientRect'
).mockImplementation(() => {
return mockGetBoundingClientRect({
left: 80,
top: 100,
width: 40,
height: 50,
});
});
jest.spyOn(container, 'getBoundingClientRect').mockImplementation(
() => {
return mockGetBoundingClientRect({
left: 20,
top: 30,
width: 100,
height: 100,
});
}
);
cut.setBounds();
expect(cut.toJSON()).toEqual({
bottom: -20,
right: 0,
width: 40,
height: 50,
});
cut.dispose();
});
test('that out-of-bounds dimensions are fixed, top left', () => {
const container = document.createElement('div');
const content = document.createElement('div');
document.body.appendChild(container);
container.appendChild(content);
const cut = new Overlay({
height: 200,
width: 100,
left: -1000,
top: -1000,
minimumInViewportWidth: 0,
minimumInViewportHeight: 0,
container,
content,
});
jest.spyOn(
container.childNodes.item(0) as HTMLElement,
'getBoundingClientRect'
).mockImplementation(() => {
return mockGetBoundingClientRect({
left: 80,
top: 100,
width: 40,
height: 50,
});
});
jest.spyOn(container, 'getBoundingClientRect').mockImplementation(
() => {
return mockGetBoundingClientRect({
left: 20,
top: 30,
width: 100,
height: 100,
});
}
);
cut.setBounds();
expect(cut.toJSON()).toEqual({
top: 70,
left: 60,
width: 40,
height: 50,
});
cut.dispose();
});
test('that out-of-bounds dimensions are fixed, bottom right', () => {
const container = document.createElement('div');
const content = document.createElement('div');
document.body.appendChild(container);
container.appendChild(content);
const cut = new Overlay({
height: 200,
width: 100,
bottom: -1000,
right: -1000,
minimumInViewportWidth: 0,
minimumInViewportHeight: 0,
container,
content,
});
jest.spyOn(
container.childNodes.item(0) as HTMLElement,
'getBoundingClientRect'
).mockImplementation(() => {
return mockGetBoundingClientRect({
left: 80,
top: 100,
width: 40,
height: 50,
});
});
jest.spyOn(container, 'getBoundingClientRect').mockImplementation(
() => {
return mockGetBoundingClientRect({
left: 20,
top: 30,
width: 100,
height: 100,
});
}
);
cut.setBounds();
expect(cut.toJSON()).toEqual({
bottom: -20,
right: 0,
width: 40,
height: 50,
});
cut.dispose();
});
test('setBounds, top left', () => {
const container = document.createElement('div');
const content = document.createElement('div');
document.body.appendChild(container);
container.appendChild(content);
const cut = new Overlay({
height: 1000,
width: 1000,
left: 0,
top: 0,
minimumInViewportWidth: 0,
minimumInViewportHeight: 0,
container,
content,
});
const element: HTMLElement = container.querySelector(
'.dv-resize-container'
)!;
expect(element).toBeTruthy();
jest.spyOn(element, 'getBoundingClientRect').mockImplementation(() => {
return mockGetBoundingClientRect({
left: 300,
top: 400,
width: 200,
height: 100,
});
});
jest.spyOn(container, 'getBoundingClientRect').mockImplementation(
() => {
return mockGetBoundingClientRect({
left: 0,
top: 0,
width: 1000,
height: 1000,
});
}
);
cut.setBounds({ height: 100, width: 200, left: 300, top: 400 });
expect(element.style.height).toBe('100px');
expect(element.style.width).toBe('200px');
expect(element.style.left).toBe('300px');
expect(element.style.top).toBe('400px');
cut.dispose();
});
test('setBounds, bottom right', () => {
const container = document.createElement('div');
const content = document.createElement('div');
document.body.appendChild(container);
container.appendChild(content);
const cut = new Overlay({
height: 1000,
width: 1000,
right: 0,
bottom: 0,
minimumInViewportWidth: 0,
minimumInViewportHeight: 0,
container,
content,
});
const element: HTMLElement = container.querySelector(
'.dv-resize-container'
)!;
expect(element).toBeTruthy();
jest.spyOn(element, 'getBoundingClientRect').mockImplementation(() => {
return mockGetBoundingClientRect({
left: 500,
top: 500,
width: 200,
height: 100,
});
});
jest.spyOn(container, 'getBoundingClientRect').mockImplementation(
() => {
return mockGetBoundingClientRect({
left: 0,
top: 0,
width: 1000,
height: 1000,
});
}
);
cut.setBounds({ height: 100, width: 200, right: 300, bottom: 400 });
expect(element.style.height).toBe('100px');
expect(element.style.width).toBe('200px');
expect(element.style.right).toBe('300px');
expect(element.style.bottom).toBe('400px');
cut.dispose();
});
test('that the resize handles are added', () => {
const container = document.createElement('div');
const content = document.createElement('div');
const cut = new Overlay({
height: 500,
width: 500,
left: 100,
top: 200,
minimumInViewportWidth: 0,
minimumInViewportHeight: 0,
container,
content,
});
expect(container.querySelector('.dv-resize-handle-top')).toBeTruthy();
expect(
container.querySelector('.dv-resize-handle-bottom')
).toBeTruthy();
expect(container.querySelector('.dv-resize-handle-left')).toBeTruthy();
expect(container.querySelector('.dv-resize-handle-right')).toBeTruthy();
expect(
container.querySelector('.dv-resize-handle-topleft')
).toBeTruthy();
expect(
container.querySelector('.dv-resize-handle-topright')
).toBeTruthy();
expect(
container.querySelector('.dv-resize-handle-bottomleft')
).toBeTruthy();
expect(
container.querySelector('.dv-resize-handle-bottomright')
).toBeTruthy();
cut.dispose();
});
test('aria-level attributes and corresponding z-index', () => {
const container = document.createElement('div');
const content = document.createElement('div');
const createOverlay = () =>
new Overlay({
height: 500,
width: 500,
left: 100,
top: 200,
minimumInViewportWidth: 0,
minimumInViewportHeight: 0,
container,
content,
});
const overlay1 = createOverlay();
const zIndexValue = (delta: number) =>
`calc(var(--dv-overlay-z-index, 999) + ${delta})`;
expect(overlay1.element.getAttribute('aria-level')).toBe('0');
expect(overlay1.element.style.zIndex).toBe(zIndexValue(0));
const overlay2 = createOverlay();
const overlay3 = createOverlay();
expect(overlay1.element.getAttribute('aria-level')).toBe('0');
expect(overlay2.element.getAttribute('aria-level')).toBe('1');
expect(overlay3.element.getAttribute('aria-level')).toBe('2');
expect(overlay1.element.style.zIndex).toBe(zIndexValue(0));
expect(overlay2.element.style.zIndex).toBe(zIndexValue(2));
expect(overlay3.element.style.zIndex).toBe(zIndexValue(4));
overlay2.bringToFront();
expect(overlay1.element.getAttribute('aria-level')).toBe('0');
expect(overlay2.element.getAttribute('aria-level')).toBe('2');
expect(overlay3.element.getAttribute('aria-level')).toBe('1');
expect(overlay1.element.style.zIndex).toBe(zIndexValue(0));
expect(overlay2.element.style.zIndex).toBe(zIndexValue(4));
expect(overlay3.element.style.zIndex).toBe(zIndexValue(2));
overlay1.bringToFront();
expect(overlay1.element.getAttribute('aria-level')).toBe('2');
expect(overlay2.element.getAttribute('aria-level')).toBe('1');
expect(overlay3.element.getAttribute('aria-level')).toBe('0');
expect(overlay1.element.style.zIndex).toBe(zIndexValue(4));
expect(overlay2.element.style.zIndex).toBe(zIndexValue(2));
expect(overlay3.element.style.zIndex).toBe(zIndexValue(0));
overlay2.dispose();
expect(overlay1.element.getAttribute('aria-level')).toBe('1');
expect(overlay3.element.getAttribute('aria-level')).toBe('0');
expect(overlay1.element.style.zIndex).toBe(zIndexValue(2));
expect(overlay3.element.style.zIndex).toBe(zIndexValue(0));
overlay1.dispose();
expect(overlay3.element.getAttribute('aria-level')).toBe('0');
expect(overlay3.element.style.zIndex).toBe(zIndexValue(0));
});
});

View File

@ -0,0 +1,265 @@
import { Droptarget } from '../../dnd/droptarget';
import { IDockviewPanel } from '../../dockview/dockviewPanel';
import { Emitter } from '../../events';
import {
IRenderable,
OverlayRenderContainer,
} from '../../overlay/overlayRenderContainer';
import { fromPartial } from '@total-typescript/shoehorn';
import { Writable, exhaustMicrotaskQueue } from '../__test_utils__/utils';
import { DockviewComponent } from '../../dockview/dockviewComponent';
import { DockviewGroupPanel } from '../../dockview/dockviewGroupPanel';
describe('overlayRenderContainer', () => {
let referenceContainer: IRenderable;
let parentContainer: HTMLElement;
beforeEach(() => {
parentContainer = document.createElement('div');
referenceContainer = {
element: document.createElement('div'),
dropTarget: fromPartial<Droptarget>({}),
};
});
test('that attach(...) and detach(...) mutate the DOM as expected', () => {
const cut = new OverlayRenderContainer(
parentContainer,
fromPartial<DockviewComponent>({})
);
const panelContentEl = document.createElement('div');
const onDidVisibilityChange = new Emitter<any>();
const onDidDimensionsChange = new Emitter<any>();
const onDidLocationChange = new Emitter<any>();
const panel = fromPartial<IDockviewPanel>({
api: {
id: 'test_panel_id',
onDidVisibilityChange: onDidVisibilityChange.event,
onDidDimensionsChange: onDidDimensionsChange.event,
onDidLocationChange: onDidLocationChange.event,
isVisible: true,
location: { type: 'grid' },
},
view: {
content: {
element: panelContentEl,
},
},
group: {
api: {
location: { type: 'grid' },
},
},
});
cut.attach({ panel, referenceContainer });
expect(panelContentEl.parentElement?.parentElement).toBe(
parentContainer
);
cut.detatch(panel);
expect(panelContentEl.parentElement?.parentElement).toBeUndefined();
});
test('add a view that is not currently in the DOM', async () => {
const cut = new OverlayRenderContainer(
parentContainer,
fromPartial<DockviewComponent>({})
);
const panelContentEl = document.createElement('div');
const onDidVisibilityChange = new Emitter<any>();
const onDidDimensionsChange = new Emitter<any>();
const onDidLocationChange = new Emitter<any>();
const panel = fromPartial<IDockviewPanel>({
api: {
id: 'test_panel_id',
onDidVisibilityChange: onDidVisibilityChange.event,
onDidDimensionsChange: onDidDimensionsChange.event,
onDidLocationChange: onDidLocationChange.event,
isVisible: true,
location: { type: 'grid' },
},
view: {
content: {
element: panelContentEl,
},
},
group: {
api: {
location: { type: 'grid' },
},
},
});
(parentContainer as jest.Mocked<HTMLDivElement>).getBoundingClientRect =
jest
.fn<DOMRect, []>()
.mockReturnValueOnce(
fromPartial<DOMRect>({
left: 100,
top: 200,
width: 1000,
height: 500,
})
)
.mockReturnValueOnce(
fromPartial<DOMRect>({
left: 101,
top: 201,
width: 1000,
height: 500,
})
)
.mockReturnValueOnce(
fromPartial<DOMRect>({
left: 100,
top: 200,
width: 1000,
height: 500,
})
);
(
referenceContainer.element as jest.Mocked<HTMLDivElement>
).getBoundingClientRect = jest
.fn<DOMRect, []>()
.mockReturnValueOnce(
fromPartial<DOMRect>({
left: 150,
top: 300,
width: 100,
height: 200,
})
)
.mockReturnValueOnce(
fromPartial<DOMRect>({
left: 150,
top: 300,
width: 101,
height: 201,
})
)
.mockReturnValueOnce(
fromPartial<DOMRect>({
left: 150,
top: 300,
width: 100,
height: 200,
})
);
const container = cut.attach({ panel, referenceContainer });
await exhaustMicrotaskQueue();
expect(panelContentEl.parentElement).toBe(container);
expect(container.parentElement).toBe(parentContainer);
expect(container.style.display).toBe('');
expect(container.style.left).toBe('50px');
expect(container.style.top).toBe('100px');
expect(container.style.width).toBe('100px');
expect(container.style.height).toBe('200px');
expect(
referenceContainer.element.getBoundingClientRect
).toHaveBeenCalledTimes(1);
onDidDimensionsChange.fire({});
expect(container.style.display).toBe('');
expect(container.style.left).toBe('49px');
expect(container.style.top).toBe('99px');
expect(container.style.width).toBe('101px');
expect(container.style.height).toBe('201px');
expect(
referenceContainer.element.getBoundingClientRect
).toHaveBeenCalledTimes(2);
(panel as Writable<IDockviewPanel>).api.isVisible = false;
onDidVisibilityChange.fire({});
expect(container.style.display).toBe('none');
expect(
referenceContainer.element.getBoundingClientRect
).toHaveBeenCalledTimes(2);
(panel as Writable<IDockviewPanel>).api.isVisible = true;
onDidVisibilityChange.fire({});
expect(container.style.display).toBe('');
expect(container.style.left).toBe('50px');
expect(container.style.top).toBe('100px');
expect(container.style.width).toBe('100px');
expect(container.style.height).toBe('200px');
expect(
referenceContainer.element.getBoundingClientRect
).toHaveBeenCalledTimes(3);
});
test('related z-index from `aria-level` set on floating panels', async () => {
const group = fromPartial<DockviewGroupPanel>({});
const element = document.createElement('div');
element.setAttribute('aria-level', '2');
const spy = jest.spyOn(element, 'getAttribute');
const accessor = fromPartial<DockviewComponent>({
floatingGroups: [
{
group,
overlay: {
element,
},
},
],
});
const cut = new OverlayRenderContainer(parentContainer, accessor);
const panelContentEl = document.createElement('div');
const onDidVisibilityChange = new Emitter<any>();
const onDidDimensionsChange = new Emitter<any>();
const onDidLocationChange = new Emitter<any>();
const panel = fromPartial<IDockviewPanel>({
api: {
id: 'test_panel_id',
onDidVisibilityChange: onDidVisibilityChange.event,
onDidDimensionsChange: onDidDimensionsChange.event,
onDidLocationChange: onDidLocationChange.event,
isVisible: true,
group,
location: { type: 'floating' },
},
view: {
content: {
element: panelContentEl,
},
},
group: {
api: {
location: { type: 'floating' },
},
},
});
cut.attach({ panel, referenceContainer });
await exhaustMicrotaskQueue();
expect(spy).toHaveBeenCalledWith('aria-level');
expect(panelContentEl.parentElement!.style.zIndex).toBe(
'calc(var(--dv-overlay-z-index, 999) + 5)'
);
});
});

View File

@ -0,0 +1,147 @@
import { CompositeDisposable } from '../../lifecycle';
import { Paneview } from '../../paneview/paneview';
import { IPanePart, PaneviewPanel } from '../../paneview/paneviewPanel';
import { Orientation } from '../../splitview/splitview';
class TestPanel extends PaneviewPanel {
protected getBodyComponent(): IPanePart {
return {
element: document.createElement('div'),
update: () => {
//
},
dispose: () => {
//
},
init: () => {
// /
},
};
}
protected getHeaderComponent(): IPanePart {
return {
element: document.createElement('div'),
update: () => {
//
},
dispose: () => {
//
},
init: () => {
// /
},
};
}
}
describe('paneview', () => {
let container: HTMLElement;
beforeEach(() => {
container = document.createElement('div');
container.className = 'container';
});
test('onDidAddView and onDidRemoveView events', () => {
const paneview = new Paneview(container, {
orientation: Orientation.HORIZONTAL,
});
const added: PaneviewPanel[] = [];
const removed: PaneviewPanel[] = [];
const disposable = new CompositeDisposable(
paneview.onDidAddView((view) => added.push(view)),
paneview.onDidRemoveView((view) => removed.push(view))
);
const view1 = new TestPanel({
id: 'id',
component: 'component',
headerComponent: 'headerComponent',
orientation: Orientation.VERTICAL,
isExpanded: true,
isHeaderVisible: true,
headerSize: 22,
minimumBodySize: 0,
maximumBodySize: Number.MAX_SAFE_INTEGER,
});
const view2 = new TestPanel({
id: 'id2',
component: 'component',
headerComponent: 'headerComponent',
orientation: Orientation.VERTICAL,
isExpanded: true,
isHeaderVisible: true,
headerSize: 22,
minimumBodySize: 0,
maximumBodySize: Number.MAX_SAFE_INTEGER,
});
expect(added.length).toBe(0);
expect(removed.length).toBe(0);
paneview.addPane(view1);
expect(added.length).toBe(1);
expect(removed.length).toBe(0);
expect(added[0]).toBe(view1);
paneview.addPane(view2);
expect(added.length).toBe(2);
expect(removed.length).toBe(0);
expect(added[1]).toBe(view2);
paneview.removePane(0);
expect(added.length).toBe(2);
expect(removed.length).toBe(1);
expect(removed[0]).toBe(view1);
paneview.removePane(0);
expect(added.length).toBe(2);
expect(removed.length).toBe(2);
expect(removed[1]).toBe(view2);
disposable.dispose();
});
test('dispose of paneview', () => {
expect(container.childNodes.length).toBe(0);
const paneview = new Paneview(container, {
orientation: Orientation.HORIZONTAL,
});
const view1 = new TestPanel({
id: 'id',
component: 'component',
headerComponent: 'headerComponent',
orientation: Orientation.VERTICAL,
isExpanded: true,
isHeaderVisible: true,
headerSize: 22,
minimumBodySize: 0,
maximumBodySize: Number.MAX_SAFE_INTEGER,
});
const view2 = new TestPanel({
id: 'id2',
component: 'component',
headerComponent: 'headerComponent',
orientation: Orientation.VERTICAL,
isExpanded: true,
isHeaderVisible: true,
headerSize: 22,
minimumBodySize: 0,
maximumBodySize: Number.MAX_SAFE_INTEGER,
});
paneview.addPane(view1);
paneview.addPane(view2);
expect(container.childNodes.length).toBeGreaterThan(0);
paneview.dispose();
expect(container.childNodes.length).toBe(0);
});
});

View File

@ -0,0 +1,619 @@
import { PanelDimensionChangeEvent } from '../../api/panelApi';
import { CompositeDisposable } from '../../lifecycle';
import { PanelUpdateEvent } from '../../panel/types';
import { PaneviewComponent } from '../../paneview/paneviewComponent';
import {
PaneviewPanel,
IPanePart,
PanePanelComponentInitParameter,
} from '../../paneview/paneviewPanel';
import { Orientation } from '../../splitview/splitview';
class TestPanel extends PaneviewPanel {
constructor(id: string, component: string) {
super({
id,
component,
headerComponent: 'header',
orientation: Orientation.VERTICAL,
isExpanded: false,
isHeaderVisible: true,
headerSize: 22,
minimumBodySize: 0,
maximumBodySize: Number.MAX_SAFE_INTEGER,
});
}
getHeaderComponent() {
return new (class Header implements IPanePart {
private _element: HTMLElement = document.createElement('div');
get element() {
return this._element;
}
init(params: PanePanelComponentInitParameter) {
//
}
update(params: PanelUpdateEvent) {
//
}
dispose() {
//
}
})();
}
getBodyComponent() {
return new (class Header implements IPanePart {
private _element: HTMLElement = document.createElement('div');
get element() {
return this._element;
}
init(params: PanePanelComponentInitParameter) {
//
}
update(params: PanelUpdateEvent) {
//
}
dispose() {
//
}
})();
}
}
describe('paneviewComponent', () => {
let container: HTMLElement;
beforeEach(() => {
container = document.createElement('div');
container.className = 'container';
});
test('that the container is not removed when grid is disposed', () => {
const root = document.createElement('div');
const container = document.createElement('div');
root.appendChild(container);
const paneview = new PaneviewComponent(container, {
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
});
paneview.dispose();
expect(container.parentElement).toBe(root);
expect(container.children.length).toBe(0);
});
test('vertical panels', () => {
const disposables = new CompositeDisposable();
const paneview = new PaneviewComponent(container, {
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
});
paneview.layout(300, 200);
paneview.addPanel({
id: 'panel1',
component: 'default',
title: 'Panel 1',
});
paneview.addPanel({
id: 'panel2',
component: 'default',
title: 'Panel2',
});
const panel1 = paneview.getPanel('panel1') as PaneviewPanel;
const panel2 = paneview.getPanel('panel2') as PaneviewPanel;
let panel1Dimensions: PanelDimensionChangeEvent | undefined = undefined;
disposables.addDisposables(
panel1.api.onDidDimensionsChange((event) => {
panel1Dimensions = event;
})
);
let panel2Dimensions: PanelDimensionChangeEvent | undefined = undefined;
disposables.addDisposables(
panel2.api.onDidDimensionsChange((event) => {
panel2Dimensions = event;
})
);
paneview.layout(600, 400);
expect(panel1Dimensions).toEqual({ width: 600, height: 22 });
expect(panel2Dimensions).toEqual({ width: 600, height: 22 });
panel1.api.setSize({ size: 300 });
expect(panel1Dimensions).toEqual({ width: 600, height: 22 });
expect(panel2Dimensions).toEqual({ width: 600, height: 22 });
paneview.layout(200, 600);
expect(panel1Dimensions).toEqual({ width: 200, height: 22 });
expect(panel2Dimensions).toEqual({ width: 200, height: 22 });
panel1.api.setExpanded(true);
expect(panel1Dimensions).toEqual({ width: 200, height: 578 });
expect(panel2Dimensions).toEqual({ width: 200, height: 22 });
panel2.api.setExpanded(true);
panel1.api.setSize({ size: 300 });
expect(panel1Dimensions).toEqual({ width: 200, height: 300 });
expect(panel2Dimensions).toEqual({ width: 200, height: 300 });
panel1.api.setSize({ size: 200 });
expect(panel1Dimensions).toEqual({ width: 200, height: 200 });
expect(panel2Dimensions).toEqual({ width: 200, height: 400 });
disposables.dispose();
paneview.dispose();
});
test('serialization', () => {
const paneview = new PaneviewComponent(container, {
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
});
expect(container.querySelectorAll('.dv-pane-container').length).toBe(1);
paneview.fromJSON({
size: 6,
views: [
{
size: 1,
data: {
id: 'panel1',
component: 'default',
title: 'Panel 1',
},
expanded: true,
},
{
size: 2,
data: {
id: 'panel2',
component: 'default',
title: 'Panel 2',
},
expanded: false,
},
{
size: 3,
data: {
id: 'panel3',
component: 'default',
title: 'Panel 3',
},
},
],
});
expect(container.querySelectorAll('.dv-pane-container').length).toBe(1);
paneview.layout(400, 800);
const panel1 = paneview.getPanel('panel1');
expect(panel1!.api.height).toBe(756);
expect(panel1!.api.width).toBe(400);
expect(panel1!.api.id).toBe('panel1');
// expect(panel1!.api.isActive).toBeTruthy();
// expect(panel1?.api.isFocused).toBeFalsy();
expect(panel1!.api.isVisible).toBeTruthy();
expect(panel1!.api.isExpanded).toBeTruthy();
const panel2 = paneview.getPanel('panel2');
expect(panel2!.api.height).toBe(22);
expect(panel2!.api.width).toBe(400);
expect(panel2!.api.id).toBe('panel2');
// expect(panel2!.api.isActive).toBeTruthy();
// expect(panel2?.api.isFocused).toBeFalsy();
expect(panel2!.api.isVisible).toBeTruthy();
expect(panel2!.api.isExpanded).toBeFalsy();
const panel3 = paneview.getPanel('panel3');
expect(panel3!.api.height).toBe(22);
expect(panel3!.api.width).toBe(400);
expect(panel3!.api.id).toBe('panel3');
// expect(panel3!.api.isActive).toBeTruthy();
// expect(panel3?.api.isFocused).toBeFalsy();
expect(panel3!.api.isVisible).toBeTruthy();
expect(panel3!.api.isExpanded).toBeFalsy();
expect(JSON.parse(JSON.stringify(paneview.toJSON()))).toEqual({
size: 800,
views: [
{
size: 756,
data: {
id: 'panel1',
component: 'default',
title: 'Panel 1',
},
expanded: true,
headerSize: 22,
},
{
size: 22,
data: {
id: 'panel2',
component: 'default',
title: 'Panel 2',
},
expanded: false,
headerSize: 22,
},
{
size: 22,
data: {
id: 'panel3',
component: 'default',
title: 'Panel 3',
},
expanded: false,
headerSize: 22,
},
],
});
});
test('toJSON shouldnt fire any layout events', () => {
const paneview = new PaneviewComponent(container, {
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
});
paneview.layout(1000, 1000);
paneview.addPanel({
id: 'panel1',
component: 'default',
title: 'Panel 1',
});
paneview.addPanel({
id: 'panel2',
component: 'default',
title: 'Panel 2',
});
const disposable = paneview.onDidLayoutChange(() => {
fail('onDidLayoutChange shouldnt have been called');
});
const result = paneview.toJSON();
expect(result).toBeTruthy();
disposable.dispose();
});
test('panel is disposed of when component is disposed', () => {
const paneview = new PaneviewComponent(container, {
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
});
paneview.layout(1000, 1000);
paneview.addPanel({
id: 'panel1',
component: 'default',
title: 'Panel 1',
});
paneview.addPanel({
id: 'panel2',
component: 'default',
title: 'Panel 2',
});
const panel1 = paneview.getPanel('panel1')!;
const panel2 = paneview.getPanel('panel2')!;
const panel1Spy = jest.spyOn(panel1, 'dispose');
const panel2Spy = jest.spyOn(panel2, 'dispose');
paneview.dispose();
expect(panel1Spy).toHaveBeenCalledTimes(1);
expect(panel2Spy).toHaveBeenCalledTimes(1);
});
test('panel is disposed of when removed', () => {
const paneview = new PaneviewComponent(container, {
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
});
paneview.layout(1000, 1000);
paneview.addPanel({
id: 'panel1',
component: 'default',
title: 'Panel 1',
});
paneview.addPanel({
id: 'panel2',
component: 'default',
title: 'Panel 2',
});
const panel1 = paneview.getPanel('panel1')!;
const panel2 = paneview.getPanel('panel2')!;
const panel1Spy = jest.spyOn(panel1, 'dispose');
const panel2Spy = jest.spyOn(panel2, 'dispose');
paneview.removePanel(panel2);
expect(panel1Spy).not.toHaveBeenCalled();
expect(panel2Spy).toHaveBeenCalledTimes(1);
});
test('panel is disposed of when fromJSON is called', () => {
const paneview = new PaneviewComponent(container, {
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
});
paneview.layout(1000, 1000);
paneview.addPanel({
id: 'panel1',
component: 'default',
title: 'Panel 1',
});
paneview.addPanel({
id: 'panel2',
component: 'default',
title: 'Panel 2',
});
const panel1 = paneview.getPanel('panel1')!;
const panel2 = paneview.getPanel('panel2')!;
const panel1Spy = jest.spyOn(panel1, 'dispose');
const panel2Spy = jest.spyOn(panel2, 'dispose');
paneview.fromJSON({ views: [], size: 0 });
expect(panel1Spy).toHaveBeenCalledTimes(1);
expect(panel2Spy).toHaveBeenCalledTimes(1);
});
test('that fromJSON layouts are resized to the current dimensions', async () => {
const paneview = new PaneviewComponent(container, {
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
});
paneview.layout(400, 600);
paneview.fromJSON({
size: 6,
views: [
{
size: 1,
data: {
id: 'panel1',
component: 'default',
title: 'Panel 1',
},
minimumSize: 100,
expanded: true,
},
{
size: 2,
data: {
id: 'panel2',
component: 'default',
title: 'Panel 2',
},
expanded: true,
},
{
size: 3,
data: {
id: 'panel3',
component: 'default',
title: 'Panel 3',
},
expanded: true,
},
],
});
// heights slightly differ because header height isn't accounted for
expect(JSON.parse(JSON.stringify(paneview.toJSON()))).toEqual({
size: 600,
views: [
{
size: 122,
data: {
id: 'panel1',
component: 'default',
title: 'Panel 1',
},
expanded: true,
minimumSize: 100,
headerSize: 22,
},
{
size: 22,
data: {
id: 'panel2',
component: 'default',
title: 'Panel 2',
},
expanded: true,
headerSize: 22,
},
{
size: 456,
data: {
id: 'panel3',
component: 'default',
title: 'Panel 3',
},
expanded: true,
headerSize: 22,
},
],
});
});
test('that disableAutoResizing is false by default', () => {
const paneview = new PaneviewComponent(container, {
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
});
expect(paneview.disableResizing).toBeFalsy();
});
test('that disableAutoResizing can be enabled', () => {
const paneview = new PaneviewComponent(container, {
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
disableAutoResizing: true,
});
expect(paneview.disableResizing).toBeTruthy();
});
test('that setVisible toggles visiblity', () => {
const paneview = new PaneviewComponent(container, {
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
disableAutoResizing: true,
});
paneview.layout(1000, 1000);
const panel1 = paneview.addPanel({
id: 'panel1',
component: 'default',
title: 'panel1',
});
const panel2 = paneview.addPanel({
id: 'panel2',
component: 'default',
title: 'panel2',
});
expect(panel1.api.isVisible).toBeTruthy();
expect(panel2.api.isVisible).toBeTruthy();
panel1.api.setVisible(false);
expect(panel1.api.isVisible).toBeFalsy();
expect(panel2.api.isVisible).toBeTruthy();
panel1.api.setVisible(true);
expect(panel1.api.isVisible).toBeTruthy();
expect(panel2.api.isVisible).toBeTruthy();
});
test('update className', () => {
const paneview = new PaneviewComponent(container, {
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
disableAutoResizing: true,
className: 'test-a test-b',
});
expect(paneview.element.className).toBe('test-a test-b');
paneview.updateOptions({ className: 'test-b test-c' });
expect(paneview.element.className).toBe('test-b test-c');
});
});

View File

@ -0,0 +1,901 @@
import { Emitter } from '../../events';
import { CompositeDisposable } from '../../lifecycle';
import {
IView,
LayoutPriority,
Orientation,
Sizing,
Splitview,
} from '../../splitview/splitview';
import { fireEvent } from '@testing-library/dom';
class Testview implements IView {
private _element: HTMLElement = document.createElement('div');
private _size = 0;
private _orthogonalSize = 0;
private _priority: LayoutPriority | undefined;
private readonly _onDidChange = new Emitter<{
size?: number;
orthogonalSize?: number;
}>();
readonly onDidChange = this._onDidChange.event;
private readonly _onLayoutCalled = new Emitter<void>();
readonly onLayoutCalled = this._onLayoutCalled.event;
private readonly _onRendered = new Emitter<void>();
readonly onRenderered = this._onRendered.event;
get minimumSize() {
return this._minimumSize;
}
get maximumSize() {
return this._maxiumSize;
}
get element() {
this._onRendered.fire();
return this._element;
}
get size() {
return this._size;
}
get orthogonalSize() {
return this._orthogonalSize;
}
get priority() {
return this._priority;
}
constructor(
private _minimumSize: number,
private _maxiumSize: number,
priority?: LayoutPriority
) {
this._priority = priority;
}
layout(size: number, orthogonalSize: number) {
this._size = size;
this._orthogonalSize = orthogonalSize;
this._onLayoutCalled.fire();
}
fireChangeEvent(value: { size?: number; orthogonalSize?: number }) {
this._onDidChange.fire(value);
}
setVisible(isVisible: boolean) {
//
}
dispose() {
this._onDidChange.dispose();
}
}
describe('splitview', () => {
let container: HTMLElement;
beforeEach(() => {
container = document.createElement('div');
container.className = 'container';
jest.clearAllMocks();
});
test('vertical splitview', () => {
const splitview = new Splitview(container, {
orientation: Orientation.HORIZONTAL,
});
expect(splitview.orientation).toBe(Orientation.HORIZONTAL);
const viewQuery = container.querySelectorAll(
'.dv-split-view-container dv-horizontal'
);
expect(viewQuery).toBeTruthy();
splitview.dispose();
});
test('horiziontal splitview', () => {
const splitview = new Splitview(container, {
orientation: Orientation.VERTICAL,
});
expect(splitview.orientation).toBe(Orientation.VERTICAL);
const viewQuery = container.querySelectorAll(
'.dv-split-view-container dv-vertical'
);
expect(viewQuery).toBeTruthy();
splitview.dispose();
});
test('has views and sashes', () => {
const splitview = new Splitview(container, {
orientation: Orientation.HORIZONTAL,
});
splitview.addView(new Testview(50, 50));
splitview.addView(new Testview(50, 50));
splitview.addView(new Testview(50, 50));
let viewQuery = container.querySelectorAll(
'.dv-split-view-container > .dv-view-container > .dv-view'
);
expect(viewQuery.length).toBe(3);
let sashQuery = container.querySelectorAll(
'.dv-split-view-container > .dv-sash-container > .dv-sash'
);
expect(sashQuery.length).toBe(2);
splitview.removeView(2);
viewQuery = container.querySelectorAll(
'.dv-split-view-container > .dv-view-container > .dv-view'
);
expect(viewQuery.length).toBe(2);
sashQuery = container.querySelectorAll(
'.dv-split-view-container > .dv-sash-container > .dv-sash'
);
expect(sashQuery.length).toBe(1);
splitview.removeView(0);
viewQuery = container.querySelectorAll(
'.dv-split-view-container > .dv-view-container > .dv-view'
);
expect(viewQuery.length).toBe(1);
sashQuery = container.querySelectorAll(
'.dv-split-view-container > .dv-sash-container > .dv-sash'
);
expect(sashQuery.length).toBe(0);
splitview.removeView(0);
viewQuery = container.querySelectorAll(
'.dv-split-view-container > .dv-view-container > .dv-view'
);
expect(viewQuery.length).toBe(0);
sashQuery = container.querySelectorAll(
'.dv-split-view-container > .dv-sash-container > .dv-sash'
);
expect(sashQuery.length).toBe(0);
splitview.dispose();
});
test('visiblity classnames', () => {
const splitview = new Splitview(container, {
orientation: Orientation.HORIZONTAL,
});
const view1 = new Testview(50, 50);
const view2 = new Testview(50, 50);
splitview.addView(view1);
splitview.addView(view2);
let viewQuery = container.querySelectorAll(
'.dv-split-view-container > .dv-view-container > .dv-view.visible'
);
expect(viewQuery.length).toBe(2);
splitview.setViewVisible(1, false);
viewQuery = container.querySelectorAll(
'.dv-split-view-container > .dv-view-container > .dv-view.visible'
);
expect(viewQuery.length).toBe(1);
splitview.dispose();
});
test('calls lifecycle methods on view', () => {
const splitview = new Splitview(container, {
orientation: Orientation.HORIZONTAL,
});
splitview.layout(200, 500);
let rendered = false;
let layout = false;
const view = new Testview(50, Number.POSITIVE_INFINITY);
const layoutDisposable = view.onLayoutCalled(() => {
layout = true;
});
const renderDisposable = view.onRenderered(() => {
rendered = true;
});
splitview.addView(view);
splitview.layout(100, 100);
expect(rendered).toBeTruthy();
expect(layout).toBeTruthy();
layoutDisposable.dispose();
renderDisposable.dispose();
splitview.dispose();
});
test('add view at specified index', () => {
const splitview = new Splitview(container, {
orientation: Orientation.HORIZONTAL,
});
splitview.layout(200, 500);
const view1 = new Testview(50, 200);
const view2 = new Testview(50, 200);
const view3 = new Testview(50, 200);
splitview.addView(view1);
splitview.addView(view2, Sizing.Distribute, 0);
splitview.addView(view3, Sizing.Distribute, 1);
expect(splitview.getViews()).toEqual([view2, view3, view1]);
});
test('streches to viewport', () => {
const splitview = new Splitview(container, {
orientation: Orientation.HORIZONTAL,
});
splitview.layout(200, 500);
const view = new Testview(50, Number.POSITIVE_INFINITY);
splitview.addView(view);
expect(view.size).toBe(200);
splitview.layout(100, 500);
expect(view.size).toBe(100);
splitview.layout(50, 500);
expect(view.size).toBe(50);
splitview.layout(30, 500);
expect(view.size).toBe(50);
splitview.layout(100, 500);
expect(view.size).toBe(100);
splitview.dispose();
});
test('can resize views 1', () => {
const splitview = new Splitview(container, {
orientation: Orientation.HORIZONTAL,
});
splitview.layout(200, 500);
const view1 = new Testview(50, 200);
const view2 = new Testview(50, 200);
splitview.addView(view1);
splitview.addView(view2);
expect(view1.size).toBe(100);
expect(view2.size).toBe(100);
view1.fireChangeEvent({ size: 65 });
expect(view1.size).toBe(65);
expect(view2.size).toBe(135);
view2.fireChangeEvent({ size: 75 });
expect(view1.size).toBe(125);
expect(view2.size).toBe(75);
view2.fireChangeEvent({});
expect(view1.size).toBe(125);
expect(view2.size).toBe(75);
splitview.dispose();
});
test('can resize views 2', () => {
const splitview = new Splitview(container, {
orientation: Orientation.HORIZONTAL,
});
splitview.layout(200, 500);
const view1 = new Testview(50, 200);
const view2 = new Testview(50, 200);
const view3 = new Testview(50, 200);
splitview.addView(view1);
splitview.addView(view2);
splitview.addView(view3);
expect([view1.size, view2.size, view3.size]).toEqual([66, 66, 68]);
splitview.resizeView(1, 100);
expect([view1.size, view2.size, view3.size]).toEqual([50, 100, 50]);
splitview.resizeView(2, 60);
expect([view1.size, view2.size, view3.size]).toEqual([50, 90, 60]);
expect([
splitview.getViewSize(0),
splitview.getViewSize(1),
splitview.getViewSize(2),
splitview.getViewSize(3),
]).toEqual([50, 90, 60, -1]);
splitview.dispose();
});
test('move view', () => {
const splitview = new Splitview(container, {
orientation: Orientation.HORIZONTAL,
});
splitview.layout(200, 500);
const view1 = new Testview(50, 200);
const view2 = new Testview(50, 200);
const view3 = new Testview(50, 200);
splitview.addView(view1);
splitview.addView(view2);
splitview.addView(view3);
expect([view1.size, view2.size, view3.size]).toEqual([66, 66, 68]);
splitview.moveView(2, 0);
expect(splitview.getViews()).toEqual([view3, view1, view2]);
expect([view1.size, view2.size, view3.size]).toEqual([66, 66, 68]);
splitview.moveView(0, 2);
expect(splitview.getViews()).toEqual([view1, view2, view3]);
expect([view1.size, view2.size, view3.size]).toEqual([66, 66, 68]);
splitview.dispose();
});
test('layout called after views added', () => {
const splitview = new Splitview(container, {
orientation: Orientation.HORIZONTAL,
});
const view1 = new Testview(50, 200);
const view2 = new Testview(50, 200);
const view3 = new Testview(50, 200);
splitview.addView(view1);
splitview.addView(view2);
splitview.addView(view3);
splitview.layout(200, 500);
expect([view1.size, view2.size, view3.size]).toEqual([67, 67, 66]);
splitview.dispose();
});
test('proportional layout', () => {
const splitview = new Splitview(container, {
orientation: Orientation.HORIZONTAL,
});
splitview.layout(200, 500);
const view1 = new Testview(20, Number.POSITIVE_INFINITY);
const view2 = new Testview(20, Number.POSITIVE_INFINITY);
splitview.addView(view1);
splitview.addView(view2);
expect([view1.size, view2.size]).toEqual([100, 100]);
splitview.layout(100, 500);
expect([view1.size, view2.size]).toEqual([50, 50]);
splitview.dispose();
});
test('disable proportional layout', () => {
const splitview = new Splitview(container, {
orientation: Orientation.HORIZONTAL,
proportionalLayout: false,
});
splitview.layout(200, 500);
const view1 = new Testview(20, Number.POSITIVE_INFINITY);
const view2 = new Testview(20, Number.POSITIVE_INFINITY);
splitview.addView(view1);
splitview.addView(view2);
expect([view1.size, view2.size]).toEqual([100, 100]);
splitview.layout(100, 500);
expect([view1.size, view2.size]).toEqual([80, 20]);
splitview.dispose();
});
test('high priority', () => {
const splitview = new Splitview(container, {
orientation: Orientation.HORIZONTAL,
proportionalLayout: false,
});
splitview.layout(300, 500);
const view1 = new Testview(50, Number.POSITIVE_INFINITY);
const view2 = new Testview(
50,
Number.POSITIVE_INFINITY,
LayoutPriority.High
);
const view3 = new Testview(50, Number.POSITIVE_INFINITY);
splitview.addView(view1);
splitview.addView(view2);
splitview.addView(view3);
expect([view1.size, view2.size, view3.size]).toEqual([100, 100, 100]);
splitview.layout(400, 500);
expect([view1.size, view2.size, view3.size]).toEqual([100, 200, 100]);
splitview.dispose();
});
test('low priority', () => {
const splitview = new Splitview(container, {
orientation: Orientation.HORIZONTAL,
proportionalLayout: false,
});
splitview.layout(300, 500);
const view1 = new Testview(
50,
Number.POSITIVE_INFINITY,
LayoutPriority.Low
);
const view2 = new Testview(50, Number.POSITIVE_INFINITY);
const view3 = new Testview(50, Number.POSITIVE_INFINITY);
splitview.addView(view1);
splitview.addView(view2);
splitview.addView(view3);
expect([view1.size, view2.size, view3.size]).toEqual([100, 100, 100]);
splitview.layout(400, 500);
expect([view1.size, view2.size, view3.size]).toEqual([100, 100, 200]);
splitview.dispose();
});
test('from descriptor', () => {
const descriptor = {
size: 300,
views: [
{
size: 80,
view: new Testview(0, Number.POSITIVE_INFINITY),
},
{
size: 100,
view: new Testview(0, Number.POSITIVE_INFINITY),
},
{
size: 120,
view: new Testview(0, Number.POSITIVE_INFINITY),
},
],
};
const splitview = new Splitview(container, {
orientation: Orientation.HORIZONTAL,
proportionalLayout: false,
descriptor,
});
expect([
descriptor.views[0].size,
descriptor.views[1].size,
descriptor.views[2].size,
]).toEqual([80, 100, 120]);
expect(splitview.size).toBe(300);
});
test('onDidAddView and onDidRemoveView events', () => {
const splitview = new Splitview(container, {
orientation: Orientation.HORIZONTAL,
proportionalLayout: false,
});
const added: IView[] = [];
const removed: IView[] = [];
const disposable = new CompositeDisposable(
splitview.onDidAddView((view) => added.push(view)),
splitview.onDidRemoveView((view) => removed.push(view))
);
const view1 = new Testview(0, 100);
const view2 = new Testview(0, 100);
expect(added.length).toBe(0);
expect(removed.length).toBe(0);
splitview.addView(view1);
expect(added.length).toBe(1);
expect(removed.length).toBe(0);
expect(added[0]).toBe(view1);
splitview.addView(view2);
expect(added.length).toBe(2);
expect(removed.length).toBe(0);
expect(added[1]).toBe(view2);
splitview.removeView(0);
expect(added.length).toBe(2);
expect(removed.length).toBe(1);
expect(removed[0]).toBe(view1);
splitview.removeView(0);
expect(added.length).toBe(2);
expect(removed.length).toBe(2);
expect(removed[1]).toBe(view2);
disposable.dispose();
});
test('dispose of splitview', () => {
expect(container.childNodes.length).toBe(0);
const splitview = new Splitview(container, {
orientation: Orientation.HORIZONTAL,
proportionalLayout: false,
});
const view1 = new Testview(0, 100);
const view2 = new Testview(0, 100);
splitview.addView(view1);
splitview.addView(view2);
expect(container.childNodes.length).toBeGreaterThan(0);
let anyEvents = false;
const listener = splitview.onDidRemoveView((e) => {
anyEvents = true; // disposing of the splitview shouldn't fire onDidRemoveView events
});
splitview.dispose();
listener.dispose();
expect(anyEvents).toBeFalsy();
expect(container.childNodes.length).toBe(0);
});
test('dnd: pointer events to move sash', () => {
const splitview = new Splitview(container, {
orientation: Orientation.HORIZONTAL,
proportionalLayout: false,
});
splitview.layout(400, 500);
const view1 = new Testview(0, 1000);
const view2 = new Testview(0, 1000);
splitview.addView(view1);
splitview.addView(view2);
const addEventListenerSpy = jest.spyOn(document, 'addEventListener');
const removeEventListenerSpy = jest.spyOn(
document,
'removeEventListener'
);
const sashElement = container
.getElementsByClassName('dv-sash')
.item(0) as HTMLElement;
// validate the expected state before drag
expect([view1.size, view2.size]).toEqual([200, 200]);
expect(sashElement).toBeTruthy();
expect(view1.element.parentElement!.style.pointerEvents).toBe('');
expect(view2.element.parentElement!.style.pointerEvents).toBe('');
// start the drag event
fireEvent(
sashElement,
new MouseEvent('pointerdown', { clientX: 50, clientY: 100 })
);
expect(addEventListenerSpy).toBeCalledTimes(3);
// during a sash drag the views should have pointer-events disabled
expect(view1.element.parentElement!.style.pointerEvents).toBe('none');
expect(view2.element.parentElement!.style.pointerEvents).toBe('none');
// expect a delta move of 70 - 50 = 20
fireEvent(
document,
new MouseEvent('pointermove', { clientX: 70, clientY: 110 })
);
expect([view1.size, view2.size]).toEqual([220, 180]);
// expect a delta move of 75 - 70 = 5
fireEvent(
document,
new MouseEvent('pointermove', { clientX: 75, clientY: 110 })
);
expect([view1.size, view2.size]).toEqual([225, 175]);
// end the drag event
fireEvent(
document,
new MouseEvent('pointerup', { clientX: 70, clientY: 110 })
);
expect(removeEventListenerSpy).toBeCalledTimes(3);
// expect pointer-eventes on views to be restored
expect(view1.element.parentElement!.style.pointerEvents).toBe('');
expect(view2.element.parentElement!.style.pointerEvents).toBe('');
fireEvent(
document,
new MouseEvent('pointermove', { clientX: 100, clientY: 100 })
);
// expect no additional resizes
expect([view1.size, view2.size]).toEqual([225, 175]);
// expect no additional document listeners
expect(addEventListenerSpy).toBeCalledTimes(3);
expect(removeEventListenerSpy).toBeCalledTimes(3);
});
test('setViewVisible', () => {
const splitview = new Splitview(container, {
orientation: Orientation.HORIZONTAL,
proportionalLayout: false,
});
splitview.layout(900, 500);
const view1 = new Testview(0, 1000);
const view2 = new Testview(0, 1000);
const view3 = new Testview(0, 1000);
splitview.addView(view1);
splitview.addView(view2);
splitview.addView(view3);
expect([view1.size, view2.size, view3.size]).toEqual([300, 300, 300]);
splitview.setViewVisible(0, false);
expect([view1.size, view2.size, view3.size]).toEqual([0, 300, 600]);
splitview.setViewVisible(0, true);
expect([view1.size, view2.size, view3.size]).toEqual([300, 300, 300]);
});
test('setViewVisible with one view having high layout priority', () => {
const splitview = new Splitview(container, {
orientation: Orientation.HORIZONTAL,
proportionalLayout: false,
});
splitview.layout(900, 500);
const view1 = new Testview(0, 1000);
const view2 = new Testview(0, 1000, LayoutPriority.High);
const view3 = new Testview(0, 1000);
splitview.addView(view1);
splitview.addView(view2);
splitview.addView(view3);
expect([view1.size, view2.size, view3.size]).toEqual([300, 300, 300]);
splitview.setViewVisible(0, false);
expect([view1.size, view2.size, view3.size]).toEqual([0, 600, 300]);
splitview.setViewVisible(0, true);
expect([view1.size, view2.size, view3.size]).toEqual([300, 300, 300]);
});
test('set view size', () => {
const splitview = new Splitview(container, {
orientation: Orientation.HORIZONTAL,
proportionalLayout: false,
});
splitview.layout(900, 500);
const view1 = new Testview(0, 1000);
const view2 = new Testview(0, 1000);
const view3 = new Testview(0, 1000);
splitview.addView(view1);
splitview.addView(view2);
splitview.addView(view3);
expect([view1.size, view2.size, view3.size]).toEqual([300, 300, 300]);
view1.fireChangeEvent({ size: 0 });
expect([view1.size, view2.size, view3.size]).toEqual([0, 300, 600]);
view1.fireChangeEvent({ size: 300 });
expect([view1.size, view2.size, view3.size]).toEqual([300, 300, 300]);
});
test('set view size with one view having high layout priority', () => {
const splitview = new Splitview(container, {
orientation: Orientation.HORIZONTAL,
proportionalLayout: false,
});
splitview.layout(900, 500);
const view1 = new Testview(0, 1000);
const view2 = new Testview(0, 1000, LayoutPriority.High);
const view3 = new Testview(0, 1000);
splitview.addView(view1);
splitview.addView(view2);
splitview.addView(view3);
expect([view1.size, view2.size, view3.size]).toEqual([300, 300, 300]);
view1.fireChangeEvent({ size: 0 });
expect([view1.size, view2.size, view3.size]).toEqual([0, 600, 300]);
view1.fireChangeEvent({ size: 300 });
expect([view1.size, view2.size, view3.size]).toEqual([300, 300, 300]);
});
test('that margins are applied to view sizing', () => {
const splitview = new Splitview(container, {
orientation: Orientation.HORIZONTAL,
proportionalLayout: false,
margin: 24,
});
splitview.layout(924, 500);
const view1 = new Testview(0, 1000);
const view2 = new Testview(0, 1000);
const view3 = new Testview(0, 1000);
const view4 = new Testview(0, 1000);
splitview.addView(view1);
expect([view1.size]).toEqual([924]);
splitview.addView(view2);
expect([view1.size, view2.size]).toEqual([450, 450]); // 450 + 24 + 450 = 924
splitview.addView(view3);
expect([view1.size, view2.size, view3.size]).toEqual([292, 292, 292]); // 292 + 24 + 292 + 24 + 292 = 924
splitview.addView(view4);
expect([view1.size, view2.size, view3.size, view4.size]).toEqual([
213, 213, 213, 213,
]); // 213 + 24 + 213 + 24 + 213 + 24 + 213 = 924
let viewQuery = Array.from(
container
.querySelectorAll(
'.dv-split-view-container > .dv-view-container > .dv-view'
)
.entries()
)
.map(([i, e]) => e as HTMLElement)
.map((e) => ({
left: e.style.left,
top: e.style.top,
height: e.style.height,
width: e.style.width,
}));
let sashQuery = Array.from(
container
.querySelectorAll(
'.dv-split-view-container > .dv-sash-container > .dv-sash'
)
.entries()
)
.map(([i, e]) => e as HTMLElement)
.map((e) => ({
left: e.style.left,
top: e.style.top,
}));
// check HTMLElement positions since these are the ones that really matter
expect(viewQuery).toEqual([
{ left: '0px', top: '', width: '213px', height: '' },
// 213 + 24 = 237
{ left: '237px', top: '', width: '213px', height: '' },
// 237 + 213 + 24 = 474
{ left: '474px', top: '', width: '213px', height: '' },
// 474 + 213 + 24 = 474
{ left: '711px', top: '', width: '213px', height: '' },
// 711 + 213 = 924
]);
// 924 / 4 = 231 view size
// 231 - (24*3/4) = 213 margin adjusted view size
// 213 - 4/2 + 24/2 = 223
expect(sashQuery).toEqual([
// 213 - 4/2 + 24/2 = 223
{ left: '223px', top: '0px' },
// 213 + 24 + 213 = 450
// 450 - 4/2 + 24/2 = 460
{ left: '460px', top: '0px' },
// 213 + 24 + 213 + 24 + 213 = 687
// 687 - 4/2 + 24/2 = 697
{ left: '697px', top: '0px' },
]);
splitview.setViewVisible(0, false);
viewQuery = Array.from(
container
.querySelectorAll(
'.dv-split-view-container > .dv-view-container > .dv-view'
)
.entries()
)
.map(([i, e]) => e as HTMLElement)
.map((e) => ({
left: e.style.left,
top: e.style.top,
height: e.style.height,
width: e.style.width,
}));
sashQuery = Array.from(
container
.querySelectorAll(
'.dv-split-view-container > .dv-sash-container > .dv-sash'
)
.entries()
)
.map(([i, e]) => e as HTMLElement)
.map((e) => ({
left: e.style.left,
top: e.style.top,
}));
expect(viewQuery).toEqual([
{ left: '0px', top: '', width: '0px', height: '' },
{ left: '0px', top: '', width: '215px', height: '' },
{ left: '239px', top: '', width: '215px', height: '' },
{ left: '478px', top: '', width: '446px', height: '' },
]);
expect(sashQuery).toEqual([
{ left: '0px', top: '0px' },
{ left: '225px', top: '0px' },
{ left: '464px', top: '0px' },
]);
});
});

View File

@ -0,0 +1,743 @@
import { PanelDimensionChangeEvent } from '../../api/panelApi';
import { Emitter } from '../../events';
import { CompositeDisposable } from '../../lifecycle';
import { Orientation } from '../../splitview/splitview';
import { SplitviewComponent } from '../../splitview/splitviewComponent';
import { SplitviewPanel } from '../../splitview/splitviewPanel';
class TestPanel extends SplitviewPanel {
getComponent() {
return {
update: () => {
//
},
dispose: () => {
//
},
};
}
}
describe('componentSplitview', () => {
let container: HTMLElement;
beforeEach(() => {
container = document.createElement('div');
container.className = 'container';
});
test('that the container is not removed when grid is disposed', () => {
const root = document.createElement('div');
const container = document.createElement('div');
root.appendChild(container);
const splitview = new SplitviewComponent(container, {
orientation: Orientation.VERTICAL,
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
});
splitview.dispose();
expect(container.parentElement).toBe(root);
expect(container.children.length).toBe(0);
});
test('event leakage', () => {
Emitter.setLeakageMonitorEnabled(true);
const splitview = new SplitviewComponent(container, {
orientation: Orientation.VERTICAL,
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
});
splitview.layout(600, 400);
const panel1 = splitview.addPanel({
id: 'panel1',
component: 'default',
});
const panel2 = splitview.addPanel({
id: 'panel2',
component: 'default',
});
splitview.movePanel(0, 1);
splitview.removePanel(panel1);
splitview.dispose();
if (Emitter.MEMORY_LEAK_WATCHER.size > 0) {
for (const entry of Array.from(
Emitter.MEMORY_LEAK_WATCHER.events
)) {
console.log(entry[1]);
}
throw new Error('not all listeners disposed');
}
Emitter.setLeakageMonitorEnabled(false);
});
test('remove panel', () => {
const splitview = new SplitviewComponent(container, {
orientation: Orientation.VERTICAL,
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
});
splitview.layout(600, 400);
splitview.addPanel({ id: 'panel1', component: 'default' });
splitview.addPanel({ id: 'panel2', component: 'default' });
splitview.addPanel({ id: 'panel3', component: 'default' });
const panel1 = splitview.getPanel('panel1')!;
const panel2 = splitview.getPanel('panel2')!;
const panel3 = splitview.getPanel('panel3')!;
expect(panel1.api.isActive).toBeFalsy();
expect(panel2.api.isActive).toBeFalsy();
expect(panel3.api.isActive).toBeTruthy();
splitview.removePanel(panel3);
expect(panel1.api.isActive).toBeFalsy();
expect(panel2.api.isActive).toBeTruthy();
expect(splitview.length).toBe(2);
splitview.removePanel(panel1);
expect(panel2.api.isActive).toBeTruthy();
expect(splitview.length).toBe(1);
splitview.removePanel(panel2);
expect(splitview.length).toBe(0);
});
test('horizontal dimensions', () => {
const splitview = new SplitviewComponent(container, {
orientation: Orientation.HORIZONTAL,
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
});
splitview.layout(600, 400);
expect(splitview.height).toBe(400);
expect(splitview.width).toBe(600);
});
test('vertical dimensions', () => {
const splitview = new SplitviewComponent(container, {
orientation: Orientation.VERTICAL,
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
});
splitview.layout(600, 400);
expect(splitview.height).toBe(400);
expect(splitview.width).toBe(600);
});
test('api resize', () => {
const splitview = new SplitviewComponent(container, {
orientation: Orientation.VERTICAL,
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
});
splitview.layout(400, 600);
splitview.addPanel({ id: 'panel1', component: 'default' });
splitview.addPanel({ id: 'panel2', component: 'default' });
splitview.addPanel({ id: 'panel3', component: 'default' });
const panel1 = splitview.getPanel('panel1')!;
const panel2 = splitview.getPanel('panel2')!;
const panel3 = splitview.getPanel('panel3')!;
expect(panel1.width).toBe(400);
expect(panel1.height).toBe(200);
expect(panel2.width).toBe(400);
expect(panel2.height).toBe(200);
expect(panel3.width).toBe(400);
expect(panel3.height).toBe(200);
panel1.api.setSize({ size: 100 });
expect(panel1.width).toBe(400);
expect(panel1.height).toBe(100);
expect(panel2.width).toBe(400);
expect(panel2.height).toBe(200);
expect(panel3.width).toBe(400);
expect(panel3.height).toBe(300);
panel2.api.setSize({ size: 100 });
expect(panel1.width).toBe(400);
expect(panel1.height).toBe(100);
expect(panel2.width).toBe(400);
expect(panel2.height).toBe(100);
expect(panel3.width).toBe(400);
expect(panel3.height).toBe(400);
panel3.api.setSize({ size: 100 });
expect(panel1.width).toBe(400);
expect(panel1.height).toBe(100);
expect(panel2.width).toBe(400);
expect(panel2.height).toBe(400);
expect(panel3.width).toBe(400);
expect(panel3.height).toBe(100);
});
test('api', () => {
const splitview = new SplitviewComponent(container, {
orientation: Orientation.HORIZONTAL,
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
});
splitview.layout(600, 400);
splitview.addPanel({ id: 'panel1', component: 'default' });
const panel1 = splitview.getPanel('panel1');
expect(panel1!.api.height).toBe(400);
expect(panel1!.api.width).toBe(600);
expect(panel1!.api.id).toBe('panel1');
expect(panel1!.api.isActive).toBeTruthy();
// expect(panel1?.api.isFocused).toBeFalsy();
expect(panel1!.api.isVisible).toBeTruthy();
splitview.addPanel({ id: 'panel2', component: 'default' });
const panel2 = splitview.getPanel('panel2');
expect(panel1!.api.isActive).toBeFalsy();
expect(panel2!.api.height).toBe(400);
expect(panel2!.api.width).toBe(300);
expect(panel2!.api.id).toBe('panel2');
expect(panel2!.api.isActive).toBeTruthy();
// expect(panel2!.api.isFocused).toBeFalsy();
expect(panel2!.api.isVisible).toBeTruthy();
panel1?.api.setActive();
expect(panel1!.api.isActive).toBeTruthy();
expect(panel2!.api.isActive).toBeFalsy();
});
test('vertical panels', () => {
const disposables = new CompositeDisposable();
const splitview = new SplitviewComponent(container, {
orientation: Orientation.VERTICAL,
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
});
splitview.layout(300, 200);
splitview.addPanel({ id: 'panel1', component: 'default' });
splitview.addPanel({ id: 'panel2', component: 'default' });
const panel1 = splitview.getPanel('panel1') as SplitviewPanel;
const panel2 = splitview.getPanel('panel2') as SplitviewPanel;
let panel1Dimensions: PanelDimensionChangeEvent | undefined;
disposables.addDisposables(
panel1.api.onDidDimensionsChange((event) => {
panel1Dimensions = event;
})
);
let panel2Dimensions: PanelDimensionChangeEvent | undefined;
disposables.addDisposables(
panel2.api.onDidDimensionsChange((event) => {
panel2Dimensions = event;
})
);
splitview.layout(600, 400);
expect(panel1Dimensions).toEqual({ width: 600, height: 200 });
expect(panel2Dimensions).toEqual({ width: 600, height: 200 });
panel1.api.setSize({ size: 300 });
expect(panel1Dimensions).toEqual({ width: 600, height: 300 });
expect(panel2Dimensions).toEqual({ width: 600, height: 100 });
splitview.layout(200, 600);
expect(panel1Dimensions).toEqual({ width: 200, height: 450 });
expect(panel2Dimensions).toEqual({ width: 200, height: 150 });
disposables.dispose();
splitview.dispose();
});
test('horizontal panels', () => {
const disposables = new CompositeDisposable();
const splitview = new SplitviewComponent(container, {
orientation: Orientation.HORIZONTAL,
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
});
splitview.layout(300, 200);
splitview.addPanel({ id: 'panel1', component: 'default' });
splitview.addPanel({ id: 'panel2', component: 'default' });
const panel1 = splitview.getPanel('panel1') as SplitviewPanel;
const panel2 = splitview.getPanel('panel2') as SplitviewPanel;
let panel1Dimensions: PanelDimensionChangeEvent | undefined;
disposables.addDisposables(
panel1.api.onDidDimensionsChange((event) => {
panel1Dimensions = event;
})
);
let panel2Dimensions: PanelDimensionChangeEvent | undefined;
disposables.addDisposables(
panel2.api.onDidDimensionsChange((event) => {
panel2Dimensions = event;
})
);
splitview.layout(600, 400);
expect(panel1Dimensions).toEqual({ width: 300, height: 400 });
expect(panel2Dimensions).toEqual({ width: 300, height: 400 });
panel1.api.setSize({ size: 200 });
expect(panel1Dimensions).toEqual({ width: 200, height: 400 });
expect(panel2Dimensions).toEqual({ width: 400, height: 400 });
splitview.layout(200, 600);
expect(panel1Dimensions).toEqual({ width: 67, height: 600 });
expect(panel2Dimensions).toEqual({ width: 133, height: 600 });
disposables.dispose();
splitview.dispose();
});
test('serialization', () => {
const splitview = new SplitviewComponent(container, {
orientation: Orientation.VERTICAL,
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
});
splitview.layout(400, 6);
expect(
container.querySelectorAll('.dv-split-view-container').length
).toBe(1);
splitview.fromJSON({
views: [
{
size: 1,
data: { id: 'panel1', component: 'default' },
snap: false,
},
{
size: 2,
data: { id: 'panel2', component: 'default' },
snap: true,
},
{ size: 3, data: { id: 'panel3', component: 'default' } },
],
size: 6,
orientation: Orientation.VERTICAL,
activeView: 'panel1',
});
expect(
container.querySelectorAll('.dv-split-view-container').length
).toBe(1);
expect(splitview.length).toBe(3);
expect(JSON.parse(JSON.stringify(splitview.toJSON()))).toEqual({
views: [
{
size: 1,
data: { id: 'panel1', component: 'default' },
snap: false,
},
{
size: 2,
data: { id: 'panel2', component: 'default' },
snap: true,
},
{
size: 3,
data: { id: 'panel3', component: 'default' },
snap: false,
},
],
size: 6,
orientation: Orientation.VERTICAL,
activeView: 'panel1',
});
});
test('toJSON shouldnt fire any layout events', () => {
const splitview = new SplitviewComponent(container, {
orientation: Orientation.HORIZONTAL,
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
});
splitview.layout(1000, 1000);
splitview.addPanel({
id: 'panel1',
component: 'default',
});
splitview.addPanel({
id: 'panel2',
component: 'default',
});
const disposable = splitview.onDidLayoutChange(() => {
fail('onDidLayoutChange shouldnt have been called');
});
const result = splitview.toJSON();
expect(result).toBeTruthy();
disposable.dispose();
});
test('panel is disposed of when component is disposed', () => {
const splitview = new SplitviewComponent(container, {
orientation: Orientation.HORIZONTAL,
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
});
splitview.layout(1000, 1000);
splitview.addPanel({
id: 'panel1',
component: 'default',
});
splitview.addPanel({
id: 'panel2',
component: 'default',
});
const panel1 = splitview.getPanel('panel1')!;
const panel2 = splitview.getPanel('panel2')!;
const panel1Spy = jest.spyOn(panel1, 'dispose');
const panel2Spy = jest.spyOn(panel2, 'dispose');
splitview.dispose();
expect(panel1Spy).toHaveBeenCalledTimes(1);
expect(panel2Spy).toHaveBeenCalledTimes(1);
});
test('panel is disposed of when removed', () => {
const splitview = new SplitviewComponent(container, {
orientation: Orientation.HORIZONTAL,
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
});
splitview.layout(1000, 1000);
splitview.addPanel({
id: 'panel1',
component: 'default',
});
splitview.addPanel({
id: 'panel2',
component: 'default',
});
const panel1 = splitview.getPanel('panel1')!;
const panel2 = splitview.getPanel('panel2')!;
const panel1Spy = jest.spyOn(panel1, 'dispose');
const panel2Spy = jest.spyOn(panel2, 'dispose');
splitview.removePanel(panel2);
expect(panel1Spy).not.toHaveBeenCalled();
expect(panel2Spy).toHaveBeenCalledTimes(1);
});
test('panel is disposed of when fromJSON is called', () => {
const splitview = new SplitviewComponent(container, {
orientation: Orientation.HORIZONTAL,
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
});
splitview.layout(1000, 1000);
splitview.addPanel({
id: 'panel1',
component: 'default',
});
splitview.addPanel({
id: 'panel2',
component: 'default',
});
const panel1 = splitview.getPanel('panel1')!;
const panel2 = splitview.getPanel('panel2')!;
const panel1Spy = jest.spyOn(panel1, 'dispose');
const panel2Spy = jest.spyOn(panel2, 'dispose');
splitview.fromJSON({
orientation: Orientation.HORIZONTAL,
size: 0,
views: [],
});
expect(panel1Spy).toHaveBeenCalledTimes(1);
expect(panel2Spy).toHaveBeenCalledTimes(1);
});
test('that fromJSON layouts are resized to the current dimensions', async () => {
const splitview = new SplitviewComponent(container, {
orientation: Orientation.VERTICAL,
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
});
splitview.layout(400, 600);
splitview.fromJSON({
views: [
{
size: 1,
data: { id: 'panel1', component: 'default' },
snap: false,
},
{
size: 2,
data: { id: 'panel2', component: 'default' },
snap: true,
},
{ size: 3, data: { id: 'panel3', component: 'default' } },
],
size: 6,
orientation: Orientation.VERTICAL,
activeView: 'panel1',
});
expect(JSON.parse(JSON.stringify(splitview.toJSON()))).toEqual({
views: [
{
size: 100,
data: { id: 'panel1', component: 'default' },
snap: false,
},
{
size: 200,
data: { id: 'panel2', component: 'default' },
snap: true,
},
{
size: 300,
data: { id: 'panel3', component: 'default' },
snap: false,
},
],
size: 600,
orientation: Orientation.VERTICAL,
activeView: 'panel1',
});
});
test('that disableAutoResizing is false by default', () => {
const splitview = new SplitviewComponent(container, {
orientation: Orientation.VERTICAL,
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
});
expect(splitview.disableResizing).toBeFalsy();
});
test('that disableAutoResizing can be enabled', () => {
const splitview = new SplitviewComponent(container, {
orientation: Orientation.VERTICAL,
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
disableAutoResizing: true,
});
expect(splitview.disableResizing).toBeTruthy();
});
test('that setVisible toggles visiblity', () => {
const splitview = new SplitviewComponent(container, {
orientation: Orientation.HORIZONTAL,
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
});
splitview.layout(1000, 1000);
const panel1 = splitview.addPanel({
id: 'panel1',
component: 'default',
});
const panel2 = splitview.addPanel({
id: 'panel2',
component: 'default',
});
expect(panel1.api.isVisible).toBeTruthy();
expect(panel2.api.isVisible).toBeTruthy();
panel1.api.setVisible(false);
expect(panel1.api.isVisible).toBeFalsy();
expect(panel2.api.isVisible).toBeTruthy();
panel1.api.setVisible(true);
expect(panel1.api.isVisible).toBeTruthy();
expect(panel2.api.isVisible).toBeTruthy();
});
test('update className', () => {
const splitview = new SplitviewComponent(container, {
orientation: Orientation.HORIZONTAL,
createComponent: (options) => {
switch (options.name) {
case 'default':
return new TestPanel(options.id, options.name);
default:
throw new Error('unsupported');
}
},
className: 'test-a test-b',
});
expect(splitview.element.className).toBe('test-a test-b');
splitview.updateOptions({ className: 'test-b test-c' });
expect(splitview.element.className).toBe('test-b test-c');
});
});

View File

@ -0,0 +1,933 @@
import {
DockviewMaximizedGroupChanged,
FloatingGroupOptions,
IDockviewComponent,
MovePanelEvent,
PopoutGroupChangePositionEvent,
PopoutGroupChangeSizeEvent,
SerializedDockview,
} from '../dockview/dockviewComponent';
import {
AddGroupOptions,
AddPanelOptions,
DockviewComponentOptions,
DockviewDndOverlayEvent,
MovementOptions,
} from '../dockview/options';
import { Parameters } from '../panel/types';
import { Direction } from '../gridview/baseComponentGridview';
import {
AddComponentOptions,
IGridviewComponent,
SerializedGridviewComponent,
} from '../gridview/gridviewComponent';
import { IGridviewPanel } from '../gridview/gridviewPanel';
import {
AddPaneviewComponentOptions,
SerializedPaneview,
IPaneviewComponent,
} from '../paneview/paneviewComponent';
import { IPaneviewPanel } from '../paneview/paneviewPanel';
import {
AddSplitviewComponentOptions,
ISplitviewComponent,
SerializedSplitview,
} from '../splitview/splitviewComponent';
import { IView, Orientation, Sizing } from '../splitview/splitview';
import { ISplitviewPanel } from '../splitview/splitviewPanel';
import {
DockviewGroupPanel,
IDockviewGroupPanel,
} from '../dockview/dockviewGroupPanel';
import { Event } from '../events';
import { IDockviewPanel } from '../dockview/dockviewPanel';
import { PaneviewDidDropEvent } from '../paneview/draggablePaneviewPanel';
import {
GroupDragEvent,
TabDragEvent,
} from '../dockview/components/titlebar/tabsContainer';
import { Box } from '../types';
import {
DockviewDidDropEvent,
DockviewWillDropEvent,
WillShowOverlayLocationEvent,
} from '../dockview/dockviewGroupPanelModel';
import {
PaneviewComponentOptions,
PaneviewDndOverlayEvent,
} from '../paneview/options';
import { SplitviewComponentOptions } from '../splitview/options';
import { GridviewComponentOptions } from '../gridview/options';
export interface CommonApi<T = any> {
readonly height: number;
readonly width: number;
readonly onDidLayoutChange: Event<void>;
readonly onDidLayoutFromJSON: Event<void>;
focus(): void;
layout(width: number, height: number): void;
fromJSON(data: T): void;
toJSON(): T;
clear(): void;
dispose(): void;
}
export class SplitviewApi implements CommonApi<SerializedSplitview> {
/**
* The minimum size the component can reach where size is measured in the direction of orientation provided.
*/
get minimumSize(): number {
return this.component.minimumSize;
}
/**
* The maximum size the component can reach where size is measured in the direction of orientation provided.
*/
get maximumSize(): number {
return this.component.maximumSize;
}
/**
* Width of the component.
*/
get width(): number {
return this.component.width;
}
/**
* Height of the component.
*/
get height(): number {
return this.component.height;
}
/**
* The current number of panels.
*/
get length(): number {
return this.component.length;
}
/**
* The current orientation of the component.
*/
get orientation(): Orientation {
return this.component.orientation;
}
/**
* The list of current panels.
*/
get panels(): ISplitviewPanel[] {
return this.component.panels;
}
/**
* Invoked after a layout is loaded through the `fromJSON` method.
*/
get onDidLayoutFromJSON(): Event<void> {
return this.component.onDidLayoutFromJSON;
}
/**
* Invoked whenever any aspect of the layout changes.
* If listening to this event it may be worth debouncing ouputs.
*/
get onDidLayoutChange(): Event<void> {
return this.component.onDidLayoutChange;
}
/**
* Invoked when a view is added.
*/
get onDidAddView(): Event<IView> {
return this.component.onDidAddView;
}
/**
* Invoked when a view is removed.
*/
get onDidRemoveView(): Event<IView> {
return this.component.onDidRemoveView;
}
constructor(private readonly component: ISplitviewComponent) {}
/**
* Removes an existing panel and optionally provide a `Sizing` method
* for the subsequent resize.
*/
removePanel(panel: ISplitviewPanel, sizing?: Sizing): void {
this.component.removePanel(panel, sizing);
}
/**
* Focus the component.
*/
focus(): void {
this.component.focus();
}
/**
* Get the reference to a panel given it's `string` id.
*/
getPanel(id: string): ISplitviewPanel | undefined {
return this.component.getPanel(id);
}
/**
* Layout the panel with a width and height.
*/
layout(width: number, height: number): void {
return this.component.layout(width, height);
}
/**
* Add a new panel and return the created instance.
*/
addPanel<T extends object = Parameters>(
options: AddSplitviewComponentOptions<T>
): ISplitviewPanel {
return this.component.addPanel(options);
}
/**
* Move a panel given it's current and desired index.
*/
movePanel(from: number, to: number): void {
this.component.movePanel(from, to);
}
/**
* Deserialize a layout to built a splitivew.
*/
fromJSON(data: SerializedSplitview): void {
this.component.fromJSON(data);
}
/** Serialize a layout */
toJSON(): SerializedSplitview {
return this.component.toJSON();
}
/**
* Remove all panels and clear the component.
*/
clear(): void {
this.component.clear();
}
/**
* Update configuratable options.
*/
updateOptions(options: Partial<SplitviewComponentOptions>): void {
this.component.updateOptions(options);
}
/**
* Release resources and teardown component. Do not call when using framework versions of dockview.
*/
dispose(): void {
this.component.dispose();
}
}
export class PaneviewApi implements CommonApi<SerializedPaneview> {
/**
* The minimum size the component can reach where size is measured in the direction of orientation provided.
*/
get minimumSize(): number {
return this.component.minimumSize;
}
/**
* The maximum size the component can reach where size is measured in the direction of orientation provided.
*/
get maximumSize(): number {
return this.component.maximumSize;
}
/**
* Width of the component.
*/
get width(): number {
return this.component.width;
}
/**
* Height of the component.
*/
get height(): number {
return this.component.height;
}
/**
* All panel objects.
*/
get panels(): IPaneviewPanel[] {
return this.component.panels;
}
/**
* Invoked when any layout change occures, an aggregation of many events.
*/
get onDidLayoutChange(): Event<void> {
return this.component.onDidLayoutChange;
}
/**
* Invoked after a layout is deserialzied using the `fromJSON` method.
*/
get onDidLayoutFromJSON(): Event<void> {
return this.component.onDidLayoutFromJSON;
}
/**
* Invoked when a panel is added. May be called multiple times when moving panels.
*/
get onDidAddView(): Event<IPaneviewPanel> {
return this.component.onDidAddView;
}
/**
* Invoked when a panel is removed. May be called multiple times when moving panels.
*/
get onDidRemoveView(): Event<IPaneviewPanel> {
return this.component.onDidRemoveView;
}
/**
* Invoked when a Drag'n'Drop event occurs that the component was unable to handle. Exposed for custom Drag'n'Drop functionality.
*/
get onDidDrop(): Event<PaneviewDidDropEvent> {
return this.component.onDidDrop;
}
get onUnhandledDragOverEvent(): Event<PaneviewDndOverlayEvent> {
return this.component.onUnhandledDragOverEvent;
}
constructor(private readonly component: IPaneviewComponent) {}
/**
* Remove a panel given the panel object.
*/
removePanel(panel: IPaneviewPanel): void {
this.component.removePanel(panel);
}
/**
* Get a panel object given a `string` id. May return `undefined`.
*/
getPanel(id: string): IPaneviewPanel | undefined {
return this.component.getPanel(id);
}
/**
* Move a panel given it's current and desired index.
*/
movePanel(from: number, to: number): void {
this.component.movePanel(from, to);
}
/**
* Focus the component. Will try to focus an active panel if one exists.
*/
focus(): void {
this.component.focus();
}
/**
* Force resize the component to an exact width and height. Read about auto-resizing before using.
*/
layout(width: number, height: number): void {
this.component.layout(width, height);
}
/**
* Add a panel and return the created object.
*/
addPanel<T extends object = Parameters>(
options: AddPaneviewComponentOptions<T>
): IPaneviewPanel {
return this.component.addPanel(options);
}
/**
* Create a component from a serialized object.
*/
fromJSON(data: SerializedPaneview): void {
this.component.fromJSON(data);
}
/**
* Create a serialized object of the current component.
*/
toJSON(): SerializedPaneview {
return this.component.toJSON();
}
/**
* Reset the component back to an empty and default state.
*/
clear(): void {
this.component.clear();
}
/**
* Update configuratable options.
*/
updateOptions(options: Partial<PaneviewComponentOptions>): void {
this.component.updateOptions(options);
}
/**
* Release resources and teardown component. Do not call when using framework versions of dockview.
*/
dispose(): void {
this.component.dispose();
}
}
export class GridviewApi implements CommonApi<SerializedGridviewComponent> {
/**
* Width of the component.
*/
get width(): number {
return this.component.width;
}
/**
* Height of the component.
*/
get height(): number {
return this.component.height;
}
/**
* Minimum height of the component.
*/
get minimumHeight(): number {
return this.component.minimumHeight;
}
/**
* Maximum height of the component.
*/
get maximumHeight(): number {
return this.component.maximumHeight;
}
/**
* Minimum width of the component.
*/
get minimumWidth(): number {
return this.component.minimumWidth;
}
/**
* Maximum width of the component.
*/
get maximumWidth(): number {
return this.component.maximumWidth;
}
/**
* Invoked when any layout change occures, an aggregation of many events.
*/
get onDidLayoutChange(): Event<void> {
return this.component.onDidLayoutChange;
}
/**
* Invoked when a panel is added. May be called multiple times when moving panels.
*/
get onDidAddPanel(): Event<IGridviewPanel> {
return this.component.onDidAddGroup;
}
/**
* Invoked when a panel is removed. May be called multiple times when moving panels.
*/
get onDidRemovePanel(): Event<IGridviewPanel> {
return this.component.onDidRemoveGroup;
}
/**
* Invoked when the active panel changes. May be undefined if no panel is active.
*/
get onDidActivePanelChange(): Event<IGridviewPanel | undefined> {
return this.component.onDidActiveGroupChange;
}
/**
* Invoked after a layout is deserialzied using the `fromJSON` method.
*/
get onDidLayoutFromJSON(): Event<void> {
return this.component.onDidLayoutFromJSON;
}
/**
* All panel objects.
*/
get panels(): IGridviewPanel[] {
return this.component.groups;
}
/**
* Current orientation. Can be changed after initialization.
*/
get orientation(): Orientation {
return this.component.orientation;
}
set orientation(value: Orientation) {
this.component.updateOptions({ orientation: value });
}
constructor(private readonly component: IGridviewComponent) {}
/**
* Focus the component. Will try to focus an active panel if one exists.
*/
focus(): void {
this.component.focus();
}
/**
* Force resize the component to an exact width and height. Read about auto-resizing before using.
*/
layout(width: number, height: number, force = false): void {
this.component.layout(width, height, force);
}
/**
* Add a panel and return the created object.
*/
addPanel<T extends object = Parameters>(
options: AddComponentOptions<T>
): IGridviewPanel {
return this.component.addPanel(options);
}
/**
* Remove a panel given the panel object.
*/
removePanel(panel: IGridviewPanel, sizing?: Sizing): void {
this.component.removePanel(panel, sizing);
}
/**
* Move a panel in a particular direction relative to another panel.
*/
movePanel(
panel: IGridviewPanel,
options: { direction: Direction; reference: string; size?: number }
): void {
this.component.movePanel(panel, options);
}
/**
* Get a panel object given a `string` id. May return `undefined`.
*/
getPanel(id: string): IGridviewPanel | undefined {
return this.component.getPanel(id);
}
/**
* Create a component from a serialized object.
*/
fromJSON(data: SerializedGridviewComponent): void {
return this.component.fromJSON(data);
}
/**
* Create a serialized object of the current component.
*/
toJSON(): SerializedGridviewComponent {
return this.component.toJSON();
}
/**
* Reset the component back to an empty and default state.
*/
clear(): void {
this.component.clear();
}
updateOptions(options: Partial<GridviewComponentOptions>) {
this.component.updateOptions(options);
}
/**
* Release resources and teardown component. Do not call when using framework versions of dockview.
*/
dispose(): void {
this.component.dispose();
}
}
export class DockviewApi implements CommonApi<SerializedDockview> {
/**
* The unique identifier for this instance. Used to manage scope of Drag'n'Drop events.
*/
get id(): string {
return this.component.id;
}
/**
* Width of the component.
*/
get width(): number {
return this.component.width;
}
/**
* Height of the component.
*/
get height(): number {
return this.component.height;
}
/**
* Minimum height of the component.
*/
get minimumHeight(): number {
return this.component.minimumHeight;
}
/**
* Maximum height of the component.
*/
get maximumHeight(): number {
return this.component.maximumHeight;
}
/**
* Minimum width of the component.
*/
get minimumWidth(): number {
return this.component.minimumWidth;
}
/**
* Maximum width of the component.
*/
get maximumWidth(): number {
return this.component.maximumWidth;
}
/**
* Total number of groups.
*/
get size(): number {
return this.component.size;
}
/**
* Total number of panels.
*/
get totalPanels(): number {
return this.component.totalPanels;
}
/**
* Invoked when the active group changes. May be undefined if no group is active.
*/
get onDidActiveGroupChange(): Event<DockviewGroupPanel | undefined> {
return this.component.onDidActiveGroupChange;
}
/**
* Invoked when a group is added. May be called multiple times when moving groups.
*/
get onDidAddGroup(): Event<DockviewGroupPanel> {
return this.component.onDidAddGroup;
}
/**
* Invoked when a group is removed. May be called multiple times when moving groups.
*/
get onDidRemoveGroup(): Event<DockviewGroupPanel> {
return this.component.onDidRemoveGroup;
}
/**
* Invoked when the active panel changes. May be undefined if no panel is active.
*/
get onDidActivePanelChange(): Event<IDockviewPanel | undefined> {
return this.component.onDidActivePanelChange;
}
/**
* Invoked when a panel is added. May be called multiple times when moving panels.
*/
get onDidAddPanel(): Event<IDockviewPanel> {
return this.component.onDidAddPanel;
}
/**
* Invoked when a panel is removed. May be called multiple times when moving panels.
*/
get onDidRemovePanel(): Event<IDockviewPanel> {
return this.component.onDidRemovePanel;
}
get onDidMovePanel(): Event<MovePanelEvent> {
return this.component.onDidMovePanel;
}
/**
* Invoked after a layout is deserialzied using the `fromJSON` method.
*/
get onDidLayoutFromJSON(): Event<void> {
return this.component.onDidLayoutFromJSON;
}
/**
* Invoked when any layout change occures, an aggregation of many events.
*/
get onDidLayoutChange(): Event<void> {
return this.component.onDidLayoutChange;
}
/**
* Invoked when a Drag'n'Drop event occurs that the component was unable to handle. Exposed for custom Drag'n'Drop functionality.
*/
get onDidDrop(): Event<DockviewDidDropEvent> {
return this.component.onDidDrop;
}
/**
* Invoked when a Drag'n'Drop event occurs but before dockview handles it giving the user an opportunity to intecept and
* prevent the event from occuring using the standard `preventDefault()` syntax.
*
* Preventing certain events may causes unexpected behaviours, use carefully.
*/
get onWillDrop(): Event<DockviewWillDropEvent> {
return this.component.onWillDrop;
}
/**
* Invoked before an overlay is shown indicating a drop target.
*
* Calling `event.preventDefault()` will prevent the overlay being shown and prevent
* the any subsequent drop event.
*/
get onWillShowOverlay(): Event<WillShowOverlayLocationEvent> {
return this.component.onWillShowOverlay;
}
/**
* Invoked before a group is dragged.
*
* Calling `event.nativeEvent.preventDefault()` will prevent the group drag starting.
*
*/
get onWillDragGroup(): Event<GroupDragEvent> {
return this.component.onWillDragGroup;
}
/**
* Invoked before a panel is dragged.
*
* Calling `event.nativeEvent.preventDefault()` will prevent the panel drag starting.
*/
get onWillDragPanel(): Event<TabDragEvent> {
return this.component.onWillDragPanel;
}
get onUnhandledDragOverEvent(): Event<DockviewDndOverlayEvent> {
return this.component.onUnhandledDragOverEvent;
}
get onDidPopoutGroupSizeChange(): Event<PopoutGroupChangeSizeEvent> {
return this.component.onDidPopoutGroupSizeChange;
}
get onDidPopoutGroupPositionChange(): Event<PopoutGroupChangePositionEvent> {
return this.component.onDidPopoutGroupPositionChange;
}
/**
* All panel objects.
*/
get panels(): IDockviewPanel[] {
return this.component.panels;
}
/**
* All group objects.
*/
get groups(): DockviewGroupPanel[] {
return this.component.groups;
}
/**
* Active panel object.
*/
get activePanel(): IDockviewPanel | undefined {
return this.component.activePanel;
}
/**
* Active group object.
*/
get activeGroup(): DockviewGroupPanel | undefined {
return this.component.activeGroup;
}
constructor(private readonly component: IDockviewComponent) {}
/**
* Focus the component. Will try to focus an active panel if one exists.
*/
focus(): void {
this.component.focus();
}
/**
* Get a panel object given a `string` id. May return `undefined`.
*/
getPanel(id: string): IDockviewPanel | undefined {
return this.component.getGroupPanel(id);
}
/**
* Force resize the component to an exact width and height. Read about auto-resizing before using.
*/
layout(width: number, height: number, force = false): void {
this.component.layout(width, height, force);
}
/**
* Add a panel and return the created object.
*/
addPanel<T extends object = Parameters>(
options: AddPanelOptions<T>
): IDockviewPanel {
return this.component.addPanel(options);
}
/**
* Remove a panel given the panel object.
*/
removePanel(panel: IDockviewPanel): void {
this.component.removePanel(panel);
}
/**
* Add a group and return the created object.
*/
addGroup(options?: AddGroupOptions): DockviewGroupPanel {
return this.component.addGroup(options);
}
/**
* Close all groups and panels.
*/
closeAllGroups(): void {
return this.component.closeAllGroups();
}
/**
* Remove a group and any panels within the group.
*/
removeGroup(group: IDockviewGroupPanel): void {
this.component.removeGroup(<DockviewGroupPanel>group);
}
/**
* Get a group object given a `string` id. May return undefined.
*/
getGroup(id: string): DockviewGroupPanel | undefined {
return this.component.getPanel(id);
}
/**
* Add a floating group
*/
addFloatingGroup(
item: IDockviewPanel | DockviewGroupPanel,
options?: FloatingGroupOptions
): void {
return this.component.addFloatingGroup(item, options);
}
/**
* Create a component from a serialized object.
*/
fromJSON(data: SerializedDockview): void {
this.component.fromJSON(data);
}
/**
* Create a serialized object of the current component.
*/
toJSON(): SerializedDockview {
return this.component.toJSON();
}
/**
* Reset the component back to an empty and default state.
*/
clear(): void {
this.component.clear();
}
/**
* Move the focus progmatically to the next panel or group.
*/
moveToNext(options?: MovementOptions): void {
this.component.moveToNext(options);
}
/**
* Move the focus progmatically to the previous panel or group.
*/
moveToPrevious(options?: MovementOptions): void {
this.component.moveToPrevious(options);
}
maximizeGroup(panel: IDockviewPanel): void {
this.component.maximizeGroup(panel.group);
}
hasMaximizedGroup(): boolean {
return this.component.hasMaximizedGroup();
}
exitMaximizedGroup(): void {
this.component.exitMaximizedGroup();
}
get onDidMaximizedGroupChange(): Event<DockviewMaximizedGroupChanged> {
return this.component.onDidMaximizedGroupChange;
}
/**
* Add a popout group in a new Window
*/
addPopoutGroup(
item: IDockviewPanel | DockviewGroupPanel,
options?: {
position?: Box;
popoutUrl?: string;
onDidOpen?: (event: { id: string; window: Window }) => void;
onWillClose?: (event: { id: string; window: Window }) => void;
}
): Promise<boolean> {
return this.component.addPopoutGroup(item, options);
}
updateOptions(options: Partial<DockviewComponentOptions>) {
this.component.updateOptions(options);
}
/**
* Release resources and teardown component. Do not call when using framework versions of dockview.
*/
dispose(): void {
this.component.dispose();
}
}

View File

@ -0,0 +1,140 @@
import { Position, positionToDirection } from '../dnd/droptarget';
import { DockviewComponent } from '../dockview/dockviewComponent';
import { DockviewGroupPanel } from '../dockview/dockviewGroupPanel';
import {
DockviewGroupChangeEvent,
DockviewGroupLocation,
} from '../dockview/dockviewGroupPanelModel';
import { Emitter, Event } from '../events';
import { GridviewPanelApi, GridviewPanelApiImpl } from './gridviewPanelApi';
export interface DockviewGroupMoveParams {
group?: DockviewGroupPanel;
position?: Position;
/**
* The index to place the panel within a group, only applicable if the placement is within an existing group
*/
index?: number;
}
export interface DockviewGroupPanelApi extends GridviewPanelApi {
readonly onDidLocationChange: Event<DockviewGroupPanelFloatingChangeEvent>;
readonly onDidActivePanelChange: Event<DockviewGroupChangeEvent>;
readonly location: DockviewGroupLocation;
/**
* If you require the Window object
*/
getWindow(): Window;
moveTo(options: DockviewGroupMoveParams): void;
maximize(): void;
isMaximized(): boolean;
exitMaximized(): void;
close(): void;
}
export interface DockviewGroupPanelFloatingChangeEvent {
readonly location: DockviewGroupLocation;
}
const NOT_INITIALIZED_MESSAGE =
'dockview: DockviewGroupPanelApiImpl not initialized';
export class DockviewGroupPanelApiImpl extends GridviewPanelApiImpl {
private _group: DockviewGroupPanel | undefined;
readonly _onDidLocationChange =
new Emitter<DockviewGroupPanelFloatingChangeEvent>();
readonly onDidLocationChange: Event<DockviewGroupPanelFloatingChangeEvent> =
this._onDidLocationChange.event;
readonly _onDidActivePanelChange = new Emitter<DockviewGroupChangeEvent>();
readonly onDidActivePanelChange = this._onDidActivePanelChange.event;
get location(): DockviewGroupLocation {
if (!this._group) {
throw new Error(NOT_INITIALIZED_MESSAGE);
}
return this._group.model.location;
}
constructor(id: string, private readonly accessor: DockviewComponent) {
super(id, '__dockviewgroup__');
this.addDisposables(
this._onDidLocationChange,
this._onDidActivePanelChange
);
}
close(): void {
if (!this._group) {
return;
}
return this.accessor.removeGroup(this._group);
}
getWindow(): Window {
return this.location.type === 'popout'
? this.location.getWindow()
: window;
}
moveTo(options: DockviewGroupMoveParams): void {
if (!this._group) {
throw new Error(NOT_INITIALIZED_MESSAGE);
}
const group =
options.group ??
this.accessor.addGroup({
direction: positionToDirection(options.position ?? 'right'),
skipSetActive: true,
});
this.accessor.moveGroupOrPanel({
from: { groupId: this._group.id },
to: {
group,
position: options.group
? options.position ?? 'center'
: 'center',
index: options.index,
},
});
}
maximize(): void {
if (!this._group) {
throw new Error(NOT_INITIALIZED_MESSAGE);
}
if (this.location.type !== 'grid') {
// only grid groups can be maximized
return;
}
this.accessor.maximizeGroup(this._group);
}
isMaximized(): boolean {
if (!this._group) {
throw new Error(NOT_INITIALIZED_MESSAGE);
}
return this.accessor.isMaximizedGroup(this._group);
}
exitMaximized(): void {
if (!this._group) {
throw new Error(NOT_INITIALIZED_MESSAGE);
}
if (this.isMaximized()) {
this.accessor.exitMaximizedGroup();
}
}
initialize(group: DockviewGroupPanel): void {
this._group = group;
}
}

View File

@ -0,0 +1,236 @@
import { Emitter, Event } from '../events';
import { GridviewPanelApiImpl, GridviewPanelApi } from './gridviewPanelApi';
import { DockviewGroupPanel } from '../dockview/dockviewGroupPanel';
import { CompositeDisposable, MutableDisposable } from '../lifecycle';
import { DockviewPanel } from '../dockview/dockviewPanel';
import { DockviewComponent } from '../dockview/dockviewComponent';
import { DockviewPanelRenderer } from '../overlay/overlayRenderContainer';
import {
DockviewGroupMoveParams,
DockviewGroupPanelFloatingChangeEvent,
} from './dockviewGroupPanelApi';
import { DockviewGroupLocation } from '../dockview/dockviewGroupPanelModel';
export interface TitleEvent {
readonly title: string;
}
export interface RendererChangedEvent {
readonly renderer: DockviewPanelRenderer;
}
export interface ActiveGroupEvent {
readonly isActive: boolean;
}
export interface GroupChangedEvent {
// empty
}
export type DockviewPanelMoveParams = DockviewGroupMoveParams;
export interface DockviewPanelApi
extends Omit<
GridviewPanelApi,
// omit properties that do not make sense here
'setVisible' | 'onDidConstraintsChange' | 'setConstraints'
> {
/**
* The id of the tab component renderer
*
* Undefined if no custom tab renderer is provided
*/
readonly tabComponent: string | undefined;
readonly group: DockviewGroupPanel;
readonly isGroupActive: boolean;
readonly renderer: DockviewPanelRenderer;
readonly title: string | undefined;
readonly onDidActiveGroupChange: Event<ActiveGroupEvent>;
readonly onDidGroupChange: Event<GroupChangedEvent>;
readonly onDidTitleChange: Event<TitleEvent>;
readonly onDidRendererChange: Event<RendererChangedEvent>;
readonly location: DockviewGroupLocation;
readonly onDidLocationChange: Event<DockviewGroupPanelFloatingChangeEvent>;
close(): void;
setTitle(title: string): void;
setRenderer(renderer: DockviewPanelRenderer): void;
moveTo(options: DockviewPanelMoveParams): void;
maximize(): void;
isMaximized(): boolean;
exitMaximized(): void;
/**
* If you require the Window object
*/
getWindow(): Window;
}
export class DockviewPanelApiImpl
extends GridviewPanelApiImpl
implements DockviewPanelApi
{
private _group: DockviewGroupPanel;
private readonly _tabComponent: string | undefined;
readonly _onDidTitleChange = new Emitter<TitleEvent>();
readonly onDidTitleChange = this._onDidTitleChange.event;
private readonly _onDidActiveGroupChange = new Emitter<ActiveGroupEvent>();
readonly onDidActiveGroupChange = this._onDidActiveGroupChange.event;
private readonly _onDidGroupChange = new Emitter<GroupChangedEvent>();
readonly onDidGroupChange = this._onDidGroupChange.event;
readonly _onDidRendererChange = new Emitter<RendererChangedEvent>();
readonly onDidRendererChange = this._onDidRendererChange.event;
private readonly _onDidLocationChange =
new Emitter<DockviewGroupPanelFloatingChangeEvent>();
readonly onDidLocationChange: Event<DockviewGroupPanelFloatingChangeEvent> =
this._onDidLocationChange.event;
private readonly groupEventsDisposable = new MutableDisposable();
get location(): DockviewGroupLocation {
return this.group.api.location;
}
get title(): string | undefined {
return this.panel.title;
}
get isGroupActive(): boolean {
return this.group.isActive;
}
get renderer(): DockviewPanelRenderer {
return this.panel.renderer;
}
set group(value: DockviewGroupPanel) {
const oldGroup = this._group;
if (this._group !== value) {
this._group = value;
this._onDidGroupChange.fire({});
this.setupGroupEventListeners(oldGroup);
this._onDidLocationChange.fire({
location: this.group.api.location,
});
}
}
get group(): DockviewGroupPanel {
return this._group;
}
get tabComponent(): string | undefined {
return this._tabComponent;
}
constructor(
private readonly panel: DockviewPanel,
group: DockviewGroupPanel,
private readonly accessor: DockviewComponent,
component: string,
tabComponent?: string
) {
super(panel.id, component);
this._tabComponent = tabComponent;
this.initialize(panel);
this._group = group;
this.setupGroupEventListeners();
this.addDisposables(
this.groupEventsDisposable,
this._onDidRendererChange,
this._onDidTitleChange,
this._onDidGroupChange,
this._onDidActiveGroupChange,
this._onDidLocationChange
);
}
getWindow(): Window {
return this.group.api.getWindow();
}
moveTo(options: DockviewPanelMoveParams): void {
this.accessor.moveGroupOrPanel({
from: { groupId: this._group.id, panelId: this.panel.id },
to: {
group: options.group ?? this._group,
position: options.group
? options.position ?? 'center'
: 'center',
index: options.index,
},
});
}
setTitle(title: string): void {
this.panel.setTitle(title);
}
setRenderer(renderer: DockviewPanelRenderer): void {
this.panel.setRenderer(renderer);
}
close(): void {
this.group.model.closePanel(this.panel);
}
maximize(): void {
this.group.api.maximize();
}
isMaximized(): boolean {
return this.group.api.isMaximized();
}
exitMaximized(): void {
this.group.api.exitMaximized();
}
private setupGroupEventListeners(previousGroup?: DockviewGroupPanel) {
let _trackGroupActive = previousGroup?.isActive ?? false; // prevent duplicate events with same state
this.groupEventsDisposable.value = new CompositeDisposable(
this.group.api.onDidVisibilityChange((event) => {
const hasBecomeHidden = !event.isVisible && this.isVisible;
const hasBecomeVisible = event.isVisible && !this.isVisible;
const isActivePanel = this.group.model.isPanelActive(
this.panel
);
if (hasBecomeHidden || (hasBecomeVisible && isActivePanel)) {
this._onDidVisibilityChange.fire(event);
}
}),
this.group.api.onDidLocationChange((event) => {
if (this.group !== this.panel.group) {
return;
}
this._onDidLocationChange.fire(event);
}),
this.group.api.onDidActiveChange(() => {
if (this.group !== this.panel.group) {
return;
}
if (_trackGroupActive !== this.isGroupActive) {
_trackGroupActive = this.isGroupActive;
this._onDidActiveGroupChange.fire({
isActive: this.isGroupActive,
});
}
})
);
}
}

View File

@ -0,0 +1,46 @@
import {
DockviewApi,
GridviewApi,
PaneviewApi,
SplitviewApi,
} from '../api/component.api';
import { DockviewComponent } from '../dockview/dockviewComponent';
import { DockviewComponentOptions } from '../dockview/options';
import { GridviewComponent } from '../gridview/gridviewComponent';
import { GridviewComponentOptions } from '../gridview/options';
import { PaneviewComponentOptions } from '../paneview/options';
import { PaneviewComponent } from '../paneview/paneviewComponent';
import { SplitviewComponentOptions } from '../splitview/options';
import { SplitviewComponent } from '../splitview/splitviewComponent';
export function createDockview(
element: HTMLElement,
options: DockviewComponentOptions
): DockviewApi {
const component = new DockviewComponent(element, options);
return component.api;
}
export function createSplitview(
element: HTMLElement,
options: SplitviewComponentOptions
): SplitviewApi {
const component = new SplitviewComponent(element, options);
return new SplitviewApi(component);
}
export function createGridview(
element: HTMLElement,
options: GridviewComponentOptions
): GridviewApi {
const component = new GridviewComponent(element, options);
return new GridviewApi(component);
}
export function createPaneview(
element: HTMLElement,
options: PaneviewComponentOptions
): PaneviewApi {
const component = new PaneviewComponent(element, options);
return new PaneviewApi(component);
}

View File

@ -0,0 +1,68 @@
import { Emitter, Event } from '../events';
import { IPanel } from '../panel/types';
import { FunctionOrValue } from '../types';
import { PanelApiImpl, PanelApi } from './panelApi';
export interface GridConstraintChangeEvent {
readonly minimumWidth?: number;
readonly minimumHeight?: number;
readonly maximumWidth?: number;
readonly maximumHeight?: number;
}
interface GridConstraintChangeEvent2 {
readonly minimumWidth?: FunctionOrValue<number>;
readonly minimumHeight?: FunctionOrValue<number>;
readonly maximumWidth?: FunctionOrValue<number>;
readonly maximumHeight?: FunctionOrValue<number>;
}
export interface SizeEvent {
readonly width?: number;
readonly height?: number;
}
export interface GridviewPanelApi extends PanelApi {
readonly onDidConstraintsChange: Event<GridConstraintChangeEvent>;
setConstraints(value: GridConstraintChangeEvent2): void;
setSize(event: SizeEvent): void;
}
export class GridviewPanelApiImpl
extends PanelApiImpl
implements GridviewPanelApi
{
private readonly _onDidConstraintsChangeInternal =
new Emitter<GridConstraintChangeEvent2>();
readonly onDidConstraintsChangeInternal: Event<GridConstraintChangeEvent2> =
this._onDidConstraintsChangeInternal.event;
readonly _onDidConstraintsChange = new Emitter<GridConstraintChangeEvent>();
readonly onDidConstraintsChange: Event<GridConstraintChangeEvent> =
this._onDidConstraintsChange.event;
private readonly _onDidSizeChange = new Emitter<SizeEvent>();
readonly onDidSizeChange: Event<SizeEvent> = this._onDidSizeChange.event;
constructor(id: string, component: string, panel?: IPanel) {
super(id, component);
this.addDisposables(
this._onDidConstraintsChangeInternal,
this._onDidConstraintsChange,
this._onDidSizeChange
);
if (panel) {
this.initialize(panel);
}
}
public setConstraints(value: GridConstraintChangeEvent): void {
this._onDidConstraintsChangeInternal.fire(value);
}
public setSize(event: SizeEvent): void {
this._onDidSizeChange.fire(event);
}
}

View File

@ -0,0 +1,188 @@
import { DockviewEvent, Emitter, Event } from '../events';
import { CompositeDisposable, MutableDisposable } from '../lifecycle';
import { IPanel, Parameters } from '../panel/types';
export interface FocusEvent {
readonly isFocused: boolean;
}
export interface PanelDimensionChangeEvent {
readonly width: number;
readonly height: number;
}
export interface VisibilityEvent {
readonly isVisible: boolean;
}
export interface ActiveEvent {
readonly isActive: boolean;
}
export interface PanelApi {
// events
readonly onDidDimensionsChange: Event<PanelDimensionChangeEvent>;
readonly onDidFocusChange: Event<FocusEvent>;
readonly onDidVisibilityChange: Event<VisibilityEvent>;
readonly onDidActiveChange: Event<ActiveEvent>;
readonly onDidParametersChange: Event<Parameters>;
setActive(): void;
setVisible(isVisible: boolean): void;
updateParameters(parameters: Parameters): void;
/**
* The id of the component renderer
*/
readonly component: string;
/**
* The id of the panel that would have been assigned when the panel was created
*/
readonly id: string;
/**
* Whether the panel holds the current focus
*/
readonly isFocused: boolean;
/**
* Whether the panel is the actively selected panel
*/
readonly isActive: boolean;
/**
* Whether the panel is visible
*/
readonly isVisible: boolean;
/**
* The panel width in pixels
*/
readonly width: number;
/**
* The panel height in pixels
*/
readonly height: number;
readonly onWillFocus: Event<WillFocusEvent>;
getParameters<T extends Parameters = Parameters>(): T;
}
export class WillFocusEvent extends DockviewEvent {
constructor() {
super();
}
}
/**
* A core api implementation that should be used across all panel-like objects
*/
export class PanelApiImpl extends CompositeDisposable implements PanelApi {
private _isFocused = false;
private _isActive = false;
private _isVisible = true;
private _width = 0;
private _height = 0;
private _parameters: Parameters = {};
private readonly panelUpdatesDisposable = new MutableDisposable();
readonly _onDidDimensionChange = new Emitter<PanelDimensionChangeEvent>();
readonly onDidDimensionsChange = this._onDidDimensionChange.event;
readonly _onDidChangeFocus = new Emitter<FocusEvent>();
readonly onDidFocusChange: Event<FocusEvent> = this._onDidChangeFocus.event;
//
readonly _onWillFocus = new Emitter<WillFocusEvent>();
readonly onWillFocus: Event<WillFocusEvent> = this._onWillFocus.event;
//
readonly _onDidVisibilityChange = new Emitter<VisibilityEvent>();
readonly onDidVisibilityChange: Event<VisibilityEvent> =
this._onDidVisibilityChange.event;
readonly _onWillVisibilityChange = new Emitter<VisibilityEvent>();
readonly onWillVisibilityChange: Event<VisibilityEvent> =
this._onWillVisibilityChange.event;
readonly _onDidActiveChange = new Emitter<ActiveEvent>();
readonly onDidActiveChange: Event<ActiveEvent> =
this._onDidActiveChange.event;
readonly _onActiveChange = new Emitter<void>();
readonly onActiveChange: Event<void> = this._onActiveChange.event;
readonly _onDidParametersChange = new Emitter<Parameters>();
readonly onDidParametersChange: Event<Parameters> =
this._onDidParametersChange.event;
get isFocused(): boolean {
return this._isFocused;
}
get isActive(): boolean {
return this._isActive;
}
get isVisible(): boolean {
return this._isVisible;
}
get width(): number {
return this._width;
}
get height(): number {
return this._height;
}
constructor(readonly id: string, readonly component: string) {
super();
this.addDisposables(
this.onDidFocusChange((event) => {
this._isFocused = event.isFocused;
}),
this.onDidActiveChange((event) => {
this._isActive = event.isActive;
}),
this.onDidVisibilityChange((event) => {
this._isVisible = event.isVisible;
}),
this.onDidDimensionsChange((event) => {
this._width = event.width;
this._height = event.height;
}),
this.panelUpdatesDisposable,
this._onDidDimensionChange,
this._onDidChangeFocus,
this._onDidVisibilityChange,
this._onDidActiveChange,
this._onWillFocus,
this._onActiveChange,
this._onWillFocus,
this._onWillVisibilityChange,
this._onDidParametersChange
);
}
getParameters<T extends Parameters = Parameters>(): T {
return this._parameters as T;
}
public initialize(panel: IPanel): void {
this.panelUpdatesDisposable.value = this._onDidParametersChange.event(
(parameters) => {
this._parameters = parameters;
panel.update({
params: parameters,
});
}
);
}
setVisible(isVisible: boolean): void {
this._onWillVisibilityChange.fire({ isVisible });
}
setActive(): void {
this._onActiveChange.fire();
}
updateParameters(parameters: Parameters): void {
this._onDidParametersChange.fire(parameters);
}
}

View File

@ -0,0 +1,55 @@
import { Emitter, Event } from '../events';
import { PaneviewPanel } from '../paneview/paneviewPanel';
import { SplitviewPanelApi, SplitviewPanelApiImpl } from './splitviewPanelApi';
export interface ExpansionEvent {
readonly isExpanded: boolean;
}
export interface PaneviewPanelApi extends SplitviewPanelApi {
readonly isExpanded: boolean;
readonly onDidExpansionChange: Event<ExpansionEvent>;
readonly onMouseEnter: Event<MouseEvent>;
readonly onMouseLeave: Event<MouseEvent>;
setExpanded(isExpanded: boolean): void;
}
export class PaneviewPanelApiImpl
extends SplitviewPanelApiImpl
implements PaneviewPanelApi
{
readonly _onDidExpansionChange = new Emitter<ExpansionEvent>({
replay: true,
});
readonly onDidExpansionChange: Event<ExpansionEvent> =
this._onDidExpansionChange.event;
readonly _onMouseEnter = new Emitter<MouseEvent>({});
readonly onMouseEnter: Event<MouseEvent> = this._onMouseEnter.event;
readonly _onMouseLeave = new Emitter<MouseEvent>({});
readonly onMouseLeave: Event<MouseEvent> = this._onMouseLeave.event;
private _pane: PaneviewPanel | undefined;
set pane(pane: PaneviewPanel) {
this._pane = pane;
}
constructor(id: string, component: string) {
super(id, component);
this.addDisposables(
this._onDidExpansionChange,
this._onMouseEnter,
this._onMouseLeave
);
}
setExpanded(isExpanded: boolean): void {
this._pane?.setExpanded(isExpanded);
}
get isExpanded(): boolean {
return !!this._pane?.isExpanded();
}
}

View File

@ -0,0 +1,65 @@
import { Emitter, Event } from '../events';
import { IDisposable } from '../lifecycle';
import { FunctionOrValue } from '../types';
import { PanelApiImpl, PanelApi } from './panelApi';
interface PanelConstraintChangeEvent2 {
readonly minimumSize?: FunctionOrValue<number>;
readonly maximumSize?: FunctionOrValue<number>;
}
export interface PanelConstraintChangeEvent {
readonly minimumSize?: number;
readonly maximumSize?: number;
}
export interface PanelSizeEvent {
readonly size: number;
}
export interface SplitviewPanelApi extends PanelApi {
readonly onDidConstraintsChange: Event<PanelConstraintChangeEvent>;
setConstraints(value: PanelConstraintChangeEvent2): void;
setSize(event: PanelSizeEvent): void;
}
export class SplitviewPanelApiImpl
extends PanelApiImpl
implements SplitviewPanelApi, IDisposable
{
readonly _onDidConstraintsChangeInternal =
new Emitter<PanelConstraintChangeEvent2>();
readonly onDidConstraintsChangeInternal: Event<PanelConstraintChangeEvent2> =
this._onDidConstraintsChangeInternal.event;
//
readonly _onDidConstraintsChange = new Emitter<PanelConstraintChangeEvent>({
replay: true,
});
readonly onDidConstraintsChange: Event<PanelConstraintChangeEvent> =
this._onDidConstraintsChange.event;
//
readonly _onDidSizeChange = new Emitter<PanelSizeEvent>();
readonly onDidSizeChange: Event<PanelSizeEvent> =
this._onDidSizeChange.event;
//
constructor(id: string, component: string) {
super(id, component);
this.addDisposables(
this._onDidConstraintsChangeInternal,
this._onDidConstraintsChange,
this._onDidSizeChange
);
}
setConstraints(value: PanelConstraintChangeEvent2) {
this._onDidConstraintsChangeInternal.fire(value);
}
setSize(event: PanelSizeEvent) {
this._onDidSizeChange.fire(event);
}
}

View File

@ -47,27 +47,6 @@ export function pushToEnd<T>(arr: T[], value: T): void {
}
}
export const range = (from: number, to?: number): number[] => {
const result: number[] = [];
if (typeof to !== 'number') {
to = from;
from = 0;
}
if (from <= to) {
for (let i = from; i < to; i++) {
result.push(i);
}
} else {
for (let i = from; i > to; i--) {
result.push(i);
}
}
return result;
};
export function firstIndex<T>(
array: T[] | ReadonlyArray<T>,
fn: (item: T) => boolean
@ -82,3 +61,13 @@ export function firstIndex<T>(
return -1;
}
export function remove<T>(array: T[], value: T): boolean {
const index = array.findIndex((t) => t === value);
if (index > -1) {
array.splice(index, 1);
return true;
}
return false;
}

View File

@ -0,0 +1,3 @@
export const DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE = 100;
export const DEFAULT_FLOATING_GROUP_POSITION = { left: 100, top: 100, width: 300, height: 300 };

View File

@ -0,0 +1,84 @@
import { disableIframePointEvents } from '../dom';
import { addDisposableListener, Emitter } from '../events';
import {
CompositeDisposable,
IDisposable,
MutableDisposable,
} from '../lifecycle';
export abstract class DragHandler extends CompositeDisposable {
private readonly dataDisposable = new MutableDisposable();
private readonly pointerEventsDisposable = new MutableDisposable();
private readonly _onDragStart = new Emitter<DragEvent>();
readonly onDragStart = this._onDragStart.event;
constructor(protected readonly el: HTMLElement) {
super();
this.addDisposables(
this._onDragStart,
this.dataDisposable,
this.pointerEventsDisposable
);
this.configure();
}
abstract getData(event: DragEvent): IDisposable;
protected isCancelled(_event: DragEvent): boolean {
return false;
}
private configure(): void {
this.addDisposables(
this._onDragStart,
addDisposableListener(this.el, 'dragstart', (event) => {
if (event.defaultPrevented || this.isCancelled(event)) {
event.preventDefault();
return;
}
const iframes = disableIframePointEvents();
this.pointerEventsDisposable.value = {
dispose: () => {
iframes.release();
},
};
this.el.classList.add('dv-dragged');
setTimeout(() => this.el.classList.remove('dv-dragged'), 0);
this.dataDisposable.value = this.getData(event);
this._onDragStart.fire(event);
if (event.dataTransfer) {
event.dataTransfer.effectAllowed = 'move';
const hasData = event.dataTransfer.items.length > 0;
if (!hasData) {
/**
* Although this is not used by dockview many third party dnd libraries will check
* dataTransfer.types to determine valid drag events.
*
* For example: in react-dnd if dataTransfer.types is not set then the dragStart event will be cancelled
* through .preventDefault(). Since this is applied globally to all drag events this would break dockviews
* dnd logic. You can see the code at
P * https://github.com/react-dnd/react-dnd/blob/main/packages/backend-html5/src/HTML5BackendImpl.ts#L542
*/
event.dataTransfer.setData('text/plain', '');
}
}
}),
addDisposableListener(this.el, 'dragend', () => {
this.pointerEventsDisposable.dispose();
setTimeout(() => {
this.dataDisposable.dispose(); // allow the data to be read by other handlers before disposing
}, 0);
})
);
}
}

View File

@ -0,0 +1,88 @@
class TransferObject {
// intentionally empty class
}
export class PanelTransfer extends TransferObject {
constructor(
public readonly viewId: string,
public readonly groupId: string,
public readonly panelId: string | null
) {
super();
}
}
export class PaneTransfer extends TransferObject {
constructor(
public readonly viewId: string,
public readonly paneId: string
) {
super();
}
}
/**
* A singleton to store transfer data during drag & drop operations that are only valid within the application.
*/
export class LocalSelectionTransfer<T> {
private static readonly INSTANCE = new LocalSelectionTransfer();
private data?: T[];
private proto?: T;
private constructor() {
// protect against external instantiation
}
static getInstance<T>(): LocalSelectionTransfer<T> {
return LocalSelectionTransfer.INSTANCE as LocalSelectionTransfer<T>;
}
hasData(proto: T): boolean {
return proto && proto === this.proto;
}
clearData(proto: T): void {
if (this.hasData(proto)) {
this.proto = undefined;
this.data = undefined;
}
}
getData(proto: T): T[] | undefined {
if (this.hasData(proto)) {
return this.data;
}
return undefined;
}
setData(data: T[], proto: T): void {
if (proto) {
this.data = data;
this.proto = proto;
}
}
}
export function getPanelData(): PanelTransfer | undefined {
const panelTransfer = LocalSelectionTransfer.getInstance<PanelTransfer>();
const isPanelEvent = panelTransfer.hasData(PanelTransfer.prototype);
if (!isPanelEvent) {
return undefined;
}
return panelTransfer.getData(PanelTransfer.prototype)![0];
}
export function getPaneData(): PaneTransfer | undefined {
const paneTransfer = LocalSelectionTransfer.getInstance<PaneTransfer>();
const isPanelEvent = paneTransfer.hasData(PaneTransfer.prototype);
if (!isPanelEvent) {
return undefined;
}
return paneTransfer.getData(PaneTransfer.prototype)![0];
}

View File

@ -0,0 +1,109 @@
import { addDisposableListener } from '../events';
import { CompositeDisposable } from '../lifecycle';
export interface IDragAndDropObserverCallbacks {
onDragEnter: (e: DragEvent) => void;
onDragLeave: (e: DragEvent) => void;
onDrop: (e: DragEvent) => void;
onDragEnd: (e: DragEvent) => void;
onDragOver?: (e: DragEvent) => void;
}
export class DragAndDropObserver extends CompositeDisposable {
private target: EventTarget | null = null;
constructor(
private readonly element: HTMLElement,
private readonly callbacks: IDragAndDropObserverCallbacks
) {
super();
this.registerListeners();
}
onDragEnter(e: DragEvent): void {
this.target = e.target;
this.callbacks.onDragEnter(e);
}
onDragOver(e: DragEvent): void {
e.preventDefault(); // needed so that the drop event fires (https://stackoverflow.com/questions/21339924/drop-event-not-firing-in-chrome)
if (this.callbacks.onDragOver) {
this.callbacks.onDragOver(e);
}
}
onDragLeave(e: DragEvent): void {
if (this.target === e.target) {
this.target = null;
this.callbacks.onDragLeave(e);
}
}
onDragEnd(e: DragEvent): void {
this.target = null;
this.callbacks.onDragEnd(e);
}
onDrop(e: DragEvent): void {
this.callbacks.onDrop(e);
}
private registerListeners(): void {
this.addDisposables(
addDisposableListener(
this.element,
'dragenter',
(e: DragEvent) => {
this.onDragEnter(e);
},
true
)
);
this.addDisposables(
addDisposableListener(
this.element,
'dragover',
(e: DragEvent) => {
this.onDragOver(e);
},
true
)
);
this.addDisposables(
addDisposableListener(this.element, 'dragleave', (e: DragEvent) => {
this.onDragLeave(e);
})
);
this.addDisposables(
addDisposableListener(this.element, 'dragend', (e: DragEvent) => {
this.onDragEnd(e);
})
);
this.addDisposables(
addDisposableListener(this.element, 'drop', (e: DragEvent) => {
this.onDrop(e);
})
);
}
}
export interface IDraggedCompositeData {
eventData: DragEvent;
dragAndDropData: any;
}
export interface ICompositeDragAndDropObserverCallbacks {
onDragEnter?: (e: IDraggedCompositeData) => void;
onDragLeave?: (e: IDraggedCompositeData) => void;
onDrop?: (e: IDraggedCompositeData) => void;
onDragOver?: (e: IDraggedCompositeData) => void;
onDragStart?: (e: IDraggedCompositeData) => void;
onDragEnd?: (e: IDraggedCompositeData) => void;
}

View File

@ -0,0 +1,23 @@
.dv-drop-target-container {
position: absolute;
z-index: 9999;
top: 0px;
left: 0px;
height: 100%;
width: 100%;
pointer-events: none;
overflow: hidden;
--dv-transition-duration: 300ms;
.dv-drop-target-anchor {
position: relative;
border: var(--dv-drag-over-border);
transition: opacity var(--dv-transition-duration) ease-in,
top var(--dv-transition-duration) ease-out,
left var(--dv-transition-duration) ease-out,
width var(--dv-transition-duration) ease-out,
height var(--dv-transition-duration) ease-out;
background-color: var(--dv-drag-over-background-color);
opacity: 1;
}
}

View File

@ -0,0 +1,102 @@
import { CompositeDisposable, Disposable } from '../lifecycle';
import { DropTargetTargetModel } from './droptarget';
export class DropTargetAnchorContainer extends CompositeDisposable {
private _model:
| { root: HTMLElement; overlay: HTMLElement; changed: boolean }
| undefined;
private _outline: HTMLElement | undefined;
private _disabled = false;
get disabled(): boolean {
return this._disabled;
}
set disabled(value: boolean) {
if (this.disabled === value) {
return;
}
this._disabled = value;
if (value) {
this.model?.clear();
}
}
get model(): DropTargetTargetModel | undefined {
if (this.disabled) {
return undefined;
}
return {
clear: () => {
if (this._model) {
this._model.root.parentElement?.removeChild(
this._model.root
);
}
this._model = undefined;
},
exists: () => {
return !!this._model;
},
getElements: (event?: DragEvent, outline?: HTMLElement) => {
const changed = this._outline !== outline;
this._outline = outline;
if (this._model) {
this._model.changed = changed;
return this._model;
}
const container = this.createContainer();
const anchor = this.createAnchor();
this._model = { root: container, overlay: anchor, changed };
container.appendChild(anchor);
this.element.appendChild(container);
if (event?.target instanceof HTMLElement) {
const targetBox = event.target.getBoundingClientRect();
const box = this.element.getBoundingClientRect();
anchor.style.left = `${targetBox.left - box.left}px`;
anchor.style.top = `${targetBox.top - box.top}px`;
}
return this._model;
},
};
}
constructor(readonly element: HTMLElement, options: { disabled: boolean }) {
super();
this._disabled = options.disabled;
this.addDisposables(
Disposable.from(() => {
this.model?.clear();
})
);
}
private createContainer(): HTMLElement {
const el = document.createElement('div');
el.className = 'dv-drop-target-container';
return el;
}
private createAnchor(): HTMLElement {
const el = document.createElement('div');
el.className = 'dv-drop-target-anchor';
el.style.visibility = 'hidden';
return el;
}
}

View File

@ -0,0 +1,54 @@
.dv-drop-target {
position: relative;
--dv-transition-duration: 70ms;
> .dv-drop-target-dropzone {
position: absolute;
left: 0px;
top: 0px;
height: 100%;
width: 100%;
z-index: 1000;
pointer-events: none;
> .dv-drop-target-selection {
position: relative;
box-sizing: border-box;
height: 100%;
width: 100%;
border: var(--dv-drag-over-border);
background-color: var(--dv-drag-over-background-color);
transition: top var(--dv-transition-duration) ease-out,
left var(--dv-transition-duration) ease-out,
width var(--dv-transition-duration) ease-out,
height var(--dv-transition-duration) ease-out,
opacity var(--dv-transition-duration) ease-out;
will-change: transform;
pointer-events: none;
&.dv-drop-target-top {
&.dv-drop-target-small-vertical {
border-top: 1px solid var(--dv-drag-over-border-color);
}
}
&.dv-drop-target-bottom {
&.dv-drop-target-small-vertical {
border-bottom: 1px solid var(--dv-drag-over-border-color);
}
}
&.dv-drop-target-left {
&.dv-drop-target-small-horizontal {
border-left: 1px solid var(--dv-drag-over-border-color);
}
}
&.dv-drop-target-right {
&.dv-drop-target-small-horizontal {
border-right: 1px solid var(--dv-drag-over-border-color);
}
}
}
}
}

View File

@ -0,0 +1,644 @@
import { toggleClass } from '../dom';
import { DockviewEvent, Emitter, Event } from '../events';
import { CompositeDisposable } from '../lifecycle';
import { DragAndDropObserver } from './dnd';
import { clamp } from '../math';
import { Direction } from '../gridview/baseComponentGridview';
export interface DroptargetEvent {
readonly position: Position;
readonly nativeEvent: DragEvent;
}
export class WillShowOverlayEvent
extends DockviewEvent
implements DroptargetEvent
{
get nativeEvent(): DragEvent {
return this.options.nativeEvent;
}
get position(): Position {
return this.options.position;
}
constructor(
private readonly options: {
nativeEvent: DragEvent;
position: Position;
}
) {
super();
}
}
export function directionToPosition(direction: Direction): Position {
switch (direction) {
case 'above':
return 'top';
case 'below':
return 'bottom';
case 'left':
return 'left';
case 'right':
return 'right';
case 'within':
return 'center';
default:
throw new Error(`invalid direction '${direction}'`);
}
}
export function positionToDirection(position: Position): Direction {
switch (position) {
case 'top':
return 'above';
case 'bottom':
return 'below';
case 'left':
return 'left';
case 'right':
return 'right';
case 'center':
return 'within';
default:
throw new Error(`invalid position '${position}'`);
}
}
export type Position = 'top' | 'bottom' | 'left' | 'right' | 'center';
export type CanDisplayOverlay = (
dragEvent: DragEvent,
state: Position
) => boolean;
export type MeasuredValue = { value: number; type: 'pixels' | 'percentage' };
export type DroptargetOverlayModel = {
size?: MeasuredValue;
activationSize?: MeasuredValue;
};
const DEFAULT_ACTIVATION_SIZE: MeasuredValue = {
value: 20,
type: 'percentage',
};
const DEFAULT_SIZE: MeasuredValue = {
value: 50,
type: 'percentage',
};
const SMALL_WIDTH_BOUNDARY = 100;
const SMALL_HEIGHT_BOUNDARY = 100;
export interface DropTargetTargetModel {
getElements(
event?: DragEvent,
outline?: HTMLElement
): {
root: HTMLElement;
overlay: HTMLElement;
changed: boolean;
};
exists(): boolean;
clear(): void;
}
export interface DroptargetOptions {
canDisplayOverlay: CanDisplayOverlay;
acceptedTargetZones: Position[];
overlayModel?: DroptargetOverlayModel;
getOverrideTarget?: () => DropTargetTargetModel | undefined;
className?: string;
getOverlayOutline?: () => HTMLElement | null;
}
export class Droptarget extends CompositeDisposable {
private targetElement: HTMLElement | undefined;
private overlayElement: HTMLElement | undefined;
private _state: Position | undefined;
private _acceptedTargetZonesSet: Set<Position>;
private readonly _onDrop = new Emitter<DroptargetEvent>();
readonly onDrop: Event<DroptargetEvent> = this._onDrop.event;
private readonly _onWillShowOverlay = new Emitter<WillShowOverlayEvent>();
readonly onWillShowOverlay: Event<WillShowOverlayEvent> =
this._onWillShowOverlay.event;
readonly dnd: DragAndDropObserver;
private static USED_EVENT_ID = '__dockview_droptarget_event_is_used__';
private static ACTUAL_TARGET: Droptarget | undefined;
private _disabled: boolean;
get disabled(): boolean {
return this._disabled;
}
set disabled(value: boolean) {
this._disabled = value;
}
get state(): Position | undefined {
return this._state;
}
constructor(
private readonly element: HTMLElement,
private readonly options: DroptargetOptions
) {
super();
this._disabled = false;
// use a set to take advantage of #<set>.has
this._acceptedTargetZonesSet = new Set(
this.options.acceptedTargetZones
);
this.dnd = new DragAndDropObserver(this.element, {
onDragEnter: () => {
this.options.getOverrideTarget?.()?.getElements();
},
onDragOver: (e) => {
Droptarget.ACTUAL_TARGET = this;
const overrideTraget = this.options.getOverrideTarget?.();
if (this._acceptedTargetZonesSet.size === 0) {
if (overrideTraget) {
return;
}
this.removeDropTarget();
return;
}
const target =
this.options.getOverlayOutline?.() ?? this.element;
const width = target.offsetWidth;
const height = target.offsetHeight;
if (width === 0 || height === 0) {
return; // avoid div!0
}
const rect = (
e.currentTarget as HTMLElement
).getBoundingClientRect();
const x = (e.clientX ?? 0) - rect.left;
const y = (e.clientY ?? 0) - rect.top;
const quadrant = this.calculateQuadrant(
this._acceptedTargetZonesSet,
x,
y,
width,
height
);
/**
* If the event has already been used by another DropTarget instance
* then don't show a second drop target, only one target should be
* active at any one time
*/
if (this.isAlreadyUsed(e) || quadrant === null) {
// no drop target should be displayed
this.removeDropTarget();
return;
}
if (!this.options.canDisplayOverlay(e, quadrant)) {
if (overrideTraget) {
return;
}
this.removeDropTarget();
return;
}
const willShowOverlayEvent = new WillShowOverlayEvent({
nativeEvent: e,
position: quadrant,
});
/**
* Provide an opportunity to prevent the overlay appearing and in turn
* any dnd behaviours
*/
this._onWillShowOverlay.fire(willShowOverlayEvent);
if (willShowOverlayEvent.defaultPrevented) {
this.removeDropTarget();
return;
}
this.markAsUsed(e);
if (overrideTraget) {
//
} else if (!this.targetElement) {
this.targetElement = document.createElement('div');
this.targetElement.className = 'dv-drop-target-dropzone';
this.overlayElement = document.createElement('div');
this.overlayElement.className = 'dv-drop-target-selection';
this._state = 'center';
this.targetElement.appendChild(this.overlayElement);
target.classList.add('dv-drop-target');
target.append(this.targetElement);
// this.overlayElement.style.opacity = '0';
// requestAnimationFrame(() => {
// if (this.overlayElement) {
// this.overlayElement.style.opacity = '';
// }
// });
}
this.toggleClasses(quadrant, width, height);
this._state = quadrant;
},
onDragLeave: () => {
const target = this.options.getOverrideTarget?.();
if (target) {
return;
}
this.removeDropTarget();
},
onDragEnd: (e) => {
const target = this.options.getOverrideTarget?.();
if (target && Droptarget.ACTUAL_TARGET === this) {
if (this._state) {
// only stop the propagation of the event if we are dealing with it
// which is only when the target has state
e.stopPropagation();
this._onDrop.fire({
position: this._state,
nativeEvent: e,
});
}
}
this.removeDropTarget();
target?.clear();
},
onDrop: (e) => {
e.preventDefault();
const state = this._state;
this.removeDropTarget();
this.options.getOverrideTarget?.()?.clear();
if (state) {
// only stop the propagation of the event if we are dealing with it
// which is only when the target has state
e.stopPropagation();
this._onDrop.fire({ position: state, nativeEvent: e });
}
},
});
this.addDisposables(this._onDrop, this._onWillShowOverlay, this.dnd);
}
setTargetZones(acceptedTargetZones: Position[]): void {
this._acceptedTargetZonesSet = new Set(acceptedTargetZones);
}
setOverlayModel(model: DroptargetOverlayModel): void {
this.options.overlayModel = model;
}
dispose(): void {
this.removeDropTarget();
super.dispose();
}
/**
* Add a property to the event object for other potential listeners to check
*/
private markAsUsed(event: DragEvent): void {
(event as any)[Droptarget.USED_EVENT_ID] = true;
}
/**
* Check is the event has already been used by another instance of DropTarget
*/
private isAlreadyUsed(event: DragEvent): boolean {
const value = (event as any)[Droptarget.USED_EVENT_ID];
return typeof value === 'boolean' && value;
}
private toggleClasses(
quadrant: Position,
width: number,
height: number
): void {
const target = this.options.getOverrideTarget?.();
if (!target && !this.overlayElement) {
return;
}
const isSmallX = width < SMALL_WIDTH_BOUNDARY;
const isSmallY = height < SMALL_HEIGHT_BOUNDARY;
const isLeft = quadrant === 'left';
const isRight = quadrant === 'right';
const isTop = quadrant === 'top';
const isBottom = quadrant === 'bottom';
const rightClass = !isSmallX && isRight;
const leftClass = !isSmallX && isLeft;
const topClass = !isSmallY && isTop;
const bottomClass = !isSmallY && isBottom;
let size = 1;
const sizeOptions = this.options.overlayModel?.size ?? DEFAULT_SIZE;
if (sizeOptions.type === 'percentage') {
size = clamp(sizeOptions.value, 0, 100) / 100;
} else {
if (rightClass || leftClass) {
size = clamp(0, sizeOptions.value, width) / width;
}
if (topClass || bottomClass) {
size = clamp(0, sizeOptions.value, height) / height;
}
}
if (target) {
const outlineEl =
this.options.getOverlayOutline?.() ?? this.element;
const elBox = outlineEl.getBoundingClientRect();
const ta = target.getElements(undefined, outlineEl);
const el = ta.root;
const overlay = ta.overlay;
const bigbox = el.getBoundingClientRect();
const rootTop = elBox.top - bigbox.top;
const rootLeft = elBox.left - bigbox.left;
const box = {
top: rootTop,
left: rootLeft,
width: width,
height: height,
};
if (rightClass) {
box.left = rootLeft + width * (1 - size);
box.width = width * size;
} else if (leftClass) {
box.width = width * size;
} else if (topClass) {
box.height = height * size;
} else if (bottomClass) {
box.top = rootTop + height * (1 - size);
box.height = height * size;
}
if (isSmallX && isLeft) {
box.width = 4;
}
if (isSmallX && isRight) {
box.left = rootLeft + width - 4;
box.width = 4;
}
const topPx = `${Math.round(box.top)}px`;
const leftPx = `${Math.round(box.left)}px`;
const widthPx = `${Math.round(box.width)}px`;
const heightPx = `${Math.round(box.height)}px`;
if (
overlay.style.top === topPx &&
overlay.style.left === leftPx &&
overlay.style.width === widthPx &&
overlay.style.height === heightPx
) {
return;
}
overlay.style.top = topPx;
overlay.style.left = leftPx;
overlay.style.width = widthPx;
overlay.style.height = heightPx;
overlay.style.visibility = 'visible';
overlay.className = `dv-drop-target-anchor${
this.options.className ? ` ${this.options.className}` : ''
}`;
toggleClass(overlay, 'dv-drop-target-left', isLeft);
toggleClass(overlay, 'dv-drop-target-right', isRight);
toggleClass(overlay, 'dv-drop-target-top', isTop);
toggleClass(overlay, 'dv-drop-target-bottom', isBottom);
toggleClass(
overlay,
'dv-drop-target-center',
quadrant === 'center'
);
if (ta.changed) {
toggleClass(
overlay,
'dv-drop-target-anchor-container-changed',
true
);
setTimeout(() => {
toggleClass(
overlay,
'dv-drop-target-anchor-container-changed',
false
);
}, 10);
}
return;
}
if (!this.overlayElement) {
return;
}
const box = { top: '0px', left: '0px', width: '100%', height: '100%' };
/**
* You can also achieve the overlay placement using the transform CSS property
* to translate and scale the element however this has the undesired effect of
* 'skewing' the element. Comment left here for anybody that ever revisits this.
*
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/transform
*
* right
* translateX(${100 * (1 - size) / 2}%) scaleX(${scale})
*
* left
* translateX(-${100 * (1 - size) / 2}%) scaleX(${scale})
*
* top
* translateY(-${100 * (1 - size) / 2}%) scaleY(${scale})
*
* bottom
* translateY(${100 * (1 - size) / 2}%) scaleY(${scale})
*/
if (rightClass) {
box.left = `${100 * (1 - size)}%`;
box.width = `${100 * size}%`;
} else if (leftClass) {
box.width = `${100 * size}%`;
} else if (topClass) {
box.height = `${100 * size}%`;
} else if (bottomClass) {
box.top = `${100 * (1 - size)}%`;
box.height = `${100 * size}%`;
}
this.overlayElement.style.top = box.top;
this.overlayElement.style.left = box.left;
this.overlayElement.style.width = box.width;
this.overlayElement.style.height = box.height;
toggleClass(
this.overlayElement,
'dv-drop-target-small-vertical',
isSmallY
);
toggleClass(
this.overlayElement,
'dv-drop-target-small-horizontal',
isSmallX
);
toggleClass(this.overlayElement, 'dv-drop-target-left', isLeft);
toggleClass(this.overlayElement, 'dv-drop-target-right', isRight);
toggleClass(this.overlayElement, 'dv-drop-target-top', isTop);
toggleClass(this.overlayElement, 'dv-drop-target-bottom', isBottom);
toggleClass(
this.overlayElement,
'dv-drop-target-center',
quadrant === 'center'
);
}
private calculateQuadrant(
overlayType: Set<Position>,
x: number,
y: number,
width: number,
height: number
): Position | null {
const activationSizeOptions =
this.options.overlayModel?.activationSize ??
DEFAULT_ACTIVATION_SIZE;
const isPercentage = activationSizeOptions.type === 'percentage';
if (isPercentage) {
return calculateQuadrantAsPercentage(
overlayType,
x,
y,
width,
height,
activationSizeOptions.value
);
}
return calculateQuadrantAsPixels(
overlayType,
x,
y,
width,
height,
activationSizeOptions.value
);
}
private removeDropTarget(): void {
if (this.targetElement) {
this._state = undefined;
this.targetElement.parentElement?.classList.remove(
'dv-drop-target'
);
this.targetElement.remove();
this.targetElement = undefined;
this.overlayElement = undefined;
}
}
}
export function calculateQuadrantAsPercentage(
overlayType: Set<Position>,
x: number,
y: number,
width: number,
height: number,
threshold: number
): Position | null {
const xp = (100 * x) / width;
const yp = (100 * y) / height;
if (overlayType.has('left') && xp < threshold) {
return 'left';
}
if (overlayType.has('right') && xp > 100 - threshold) {
return 'right';
}
if (overlayType.has('top') && yp < threshold) {
return 'top';
}
if (overlayType.has('bottom') && yp > 100 - threshold) {
return 'bottom';
}
if (!overlayType.has('center')) {
return null;
}
return 'center';
}
export function calculateQuadrantAsPixels(
overlayType: Set<Position>,
x: number,
y: number,
width: number,
height: number,
threshold: number
): Position | null {
if (overlayType.has('left') && x < threshold) {
return 'left';
}
if (overlayType.has('right') && x > width - threshold) {
return 'right';
}
if (overlayType.has('top') && y < threshold) {
return 'top';
}
if (overlayType.has('bottom') && y > height - threshold) {
return 'bottom';
}
if (!overlayType.has('center')) {
return null;
}
return 'center';
}

View File

@ -0,0 +1,21 @@
import { addClasses, removeClasses } from '../dom';
export function addGhostImage(
dataTransfer: DataTransfer,
ghostElement: HTMLElement,
options?: { x?: number; y?: number }
): void {
// class dockview provides to force ghost image to be drawn on a different layer and prevent weird rendering issues
addClasses(ghostElement, 'dv-dragged');
// move the element off-screen initially otherwise it may in some cases be rendered at (0,0) momentarily
ghostElement.style.top = '-9999px';
document.body.appendChild(ghostElement);
dataTransfer.setDragImage(ghostElement, options?.x ?? 0, options?.y ?? 0);
setTimeout(() => {
removeClasses(ghostElement, 'dv-dragged');
ghostElement.remove();
}, 0);
}

View File

@ -0,0 +1,88 @@
import { DockviewComponent } from '../dockview/dockviewComponent';
import { DockviewGroupPanel } from '../dockview/dockviewGroupPanel';
import { quasiPreventDefault } from '../dom';
import { addDisposableListener } from '../events';
import { IDisposable } from '../lifecycle';
import { DragHandler } from './abstractDragHandler';
import { LocalSelectionTransfer, PanelTransfer } from './dataTransfer';
import { addGhostImage } from './ghost';
export class GroupDragHandler extends DragHandler {
private readonly panelTransfer =
LocalSelectionTransfer.getInstance<PanelTransfer>();
constructor(
element: HTMLElement,
private readonly accessor: DockviewComponent,
private readonly group: DockviewGroupPanel
) {
super(element);
this.addDisposables(
addDisposableListener(
element,
'pointerdown',
(e) => {
if (e.shiftKey) {
/**
* You cannot call e.preventDefault() because that will prevent drag events from firing
* but we also need to stop any group overlay drag events from occuring
* Use a custom event marker that can be checked by the overlay drag events
*/
quasiPreventDefault(e);
}
},
true
)
);
}
override isCancelled(_event: DragEvent): boolean {
if (this.group.api.location.type === 'floating' && !_event.shiftKey) {
return true;
}
return false;
}
getData(dragEvent: DragEvent): IDisposable {
const dataTransfer = dragEvent.dataTransfer;
this.panelTransfer.setData(
[new PanelTransfer(this.accessor.id, this.group.id, null)],
PanelTransfer.prototype
);
const style = window.getComputedStyle(this.el);
const bgColor = style.getPropertyValue(
'--dv-activegroup-visiblepanel-tab-background-color'
);
const color = style.getPropertyValue(
'--dv-activegroup-visiblepanel-tab-color'
);
if (dataTransfer) {
const ghostElement = document.createElement('div');
ghostElement.style.backgroundColor = bgColor;
ghostElement.style.color = color;
ghostElement.style.padding = '2px 8px';
ghostElement.style.height = '24px';
ghostElement.style.fontSize = '11px';
ghostElement.style.lineHeight = '20px';
ghostElement.style.borderRadius = '12px';
ghostElement.style.position = 'absolute';
ghostElement.style.pointerEvents = 'none';
ghostElement.style.top = '-9999px';
ghostElement.textContent = `Multiple Panels (${this.group.size})`;
addGhostImage(dataTransfer, ghostElement, { y: -10, x: 30 });
}
return {
dispose: () => {
this.panelTransfer.clearData(PanelTransfer.prototype);
},
};
}
}

Some files were not shown because too many files have changed in this diff Show More