@kubohiroya/turbowarp-plus-editor-layout 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ja.md +2 -0
- package/README.md +2 -0
- package/dist/sprite-asset-pane.d.ts +37 -0
- package/dist/sprite-asset-pane.js +109 -0
- package/dist/sprite-editor-toolbar.d.ts +25 -0
- package/dist/sprite-editor-toolbar.js +72 -0
- package/dist/sprite-layout-menu.d.ts +11 -0
- package/dist/sprite-layout-menu.js +114 -0
- package/dist/sprite-tabs.d.ts +113 -20
- package/dist/sprite-tabs.js +496 -76
- package/dist/stage-surface.d.ts +31 -0
- package/dist/stage-surface.js +81 -0
- package/dist/standard-layout.d.ts +2 -1
- package/dist/standard-layout.js +9 -6
- package/package.json +16 -1
- package/src/editor.css +97 -5
- package/src/sprite-asset-pane.css +169 -0
- package/src/sprite-asset-pane.tsx +168 -0
- package/src/sprite-editor-toolbar.css +108 -0
- package/src/sprite-editor-toolbar.tsx +124 -0
- package/src/sprite-layout-menu.css +54 -0
- package/src/sprite-layout-menu.ts +119 -0
- package/src/sprite-tabs.ts +593 -95
- package/src/stage-surface.ts +104 -0
- package/src/standard-layout.ts +10 -6
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type {Context, ElementType} from 'react';
|
|
2
|
+
import {createDockview, themeLight} from 'dockview';
|
|
3
|
+
|
|
4
|
+
interface StageWindowConnection<Target> {
|
|
5
|
+
ready: Promise<Target>;
|
|
6
|
+
disconnected: AbortSignal;
|
|
7
|
+
close(): void;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface StageWindowHost<Request, Target> {
|
|
11
|
+
open(request: Request): StageWindowConnection<Target> | null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function createStagePopoutHost<Request, Target extends {mount: HTMLElement}>(
|
|
15
|
+
host: StageWindowHost<Request, Target>, title: string
|
|
16
|
+
): StageWindowHost<Request, Target> {
|
|
17
|
+
return {
|
|
18
|
+
open(request) {
|
|
19
|
+
const connection = host.open(request);
|
|
20
|
+
if (!connection) return null;
|
|
21
|
+
|
|
22
|
+
const disconnected = new AbortController();
|
|
23
|
+
const disconnect = () => disconnected.abort();
|
|
24
|
+
connection.disconnected.addEventListener('abort', disconnect, {once: true});
|
|
25
|
+
if (connection.disconnected.aborted) disconnect();
|
|
26
|
+
|
|
27
|
+
let dockview: ReturnType<typeof createDockview> | undefined;
|
|
28
|
+
let removed: {dispose(): void} | undefined;
|
|
29
|
+
let closed = false;
|
|
30
|
+
const ready = connection.ready.then(target => {
|
|
31
|
+
if (closed || disconnected.signal.aborted) throw new Error('Stage window closed');
|
|
32
|
+
const content = target.mount.ownerDocument.createElement('div');
|
|
33
|
+
Object.assign(content.style, {width: '100%', height: '100%'});
|
|
34
|
+
dockview = createDockview(target.mount, {
|
|
35
|
+
createComponent: () => ({element: content, init() {}}),
|
|
36
|
+
theme: themeLight,
|
|
37
|
+
disableDnd: true,
|
|
38
|
+
disableFloatingGroups: true
|
|
39
|
+
});
|
|
40
|
+
dockview.addPanel({id: 'stage', component: 'stage', title});
|
|
41
|
+
removed = dockview.onDidRemovePanel(disconnect);
|
|
42
|
+
return {...target, mount: content};
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
ready,
|
|
47
|
+
disconnected: disconnected.signal,
|
|
48
|
+
close() {
|
|
49
|
+
if (closed) return;
|
|
50
|
+
closed = true;
|
|
51
|
+
connection.disconnected.removeEventListener('abort', disconnect);
|
|
52
|
+
try {
|
|
53
|
+
removed?.dispose();
|
|
54
|
+
dockview?.dispose();
|
|
55
|
+
} finally {
|
|
56
|
+
connection.close();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const isJapanese = (locale: string) => /^ja(?:-|$)/i.test(locale);
|
|
65
|
+
|
|
66
|
+
export function stageDockActionLabel(locale: string, {drawer, detached, external}: {
|
|
67
|
+
drawer?: boolean;
|
|
68
|
+
detached: boolean;
|
|
69
|
+
external?: boolean;
|
|
70
|
+
}) {
|
|
71
|
+
const japanese = isJapanese(locale);
|
|
72
|
+
if (detached) return japanese ? 'ドックに戻す' : 'Dock stage';
|
|
73
|
+
if (external) return japanese ? (drawer ? '別窓で開く' : '別ウィンドウで開く') : 'Open in a separate window';
|
|
74
|
+
return japanese ? 'アンドック' : 'Undock stage';
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function createStageSurface(React: typeof import('react'), {
|
|
78
|
+
context, EdgeDrawer, Panel
|
|
79
|
+
}: {
|
|
80
|
+
context: Context<{locale: string; stageDrawer?: boolean; setStageDrawerOpen?: (open: boolean) => void}>;
|
|
81
|
+
EdgeDrawer: ElementType;
|
|
82
|
+
Panel: ElementType;
|
|
83
|
+
}) {
|
|
84
|
+
return function StageSurface({externalHost, onDockActionChange, ...props}) {
|
|
85
|
+
const {locale, stageDrawer, setStageDrawerOpen} = React.useContext(context);
|
|
86
|
+
const japanese = isJapanese(locale);
|
|
87
|
+
const title = japanese ? 'ステージ' : 'Stage';
|
|
88
|
+
const host = React.useMemo(() => stageDrawer && externalHost ?
|
|
89
|
+
createStagePopoutHost(externalHost, title) : externalHost, [stageDrawer, externalHost, title]);
|
|
90
|
+
const panel = React.createElement(Panel, {
|
|
91
|
+
...props,
|
|
92
|
+
id: 'stage',
|
|
93
|
+
title,
|
|
94
|
+
externalHost: host,
|
|
95
|
+
externalOnly: stageDrawer,
|
|
96
|
+
onDockActionChange: stageDrawer && !host ? undefined : onDockActionChange
|
|
97
|
+
});
|
|
98
|
+
return stageDrawer ? React.createElement(EdgeDrawer, {
|
|
99
|
+
edge: 'right',
|
|
100
|
+
label: japanese ? 'ステージを展開' : 'Reveal stage',
|
|
101
|
+
onOpenChange: setStageDrawerOpen
|
|
102
|
+
}, panel) : panel;
|
|
103
|
+
};
|
|
104
|
+
}
|
package/src/standard-layout.ts
CHANGED
|
@@ -14,11 +14,13 @@ export function createStandardLayout(React, {styles, targetStyles, context, Layo
|
|
|
14
14
|
const targetTools = React.createContext(null);
|
|
15
15
|
|
|
16
16
|
function StandardLayout({
|
|
17
|
-
enabled, splitter, windowLayout, stageActionEnabled,
|
|
17
|
+
enabled, splitter, windowLayout, stageActionEnabled, stageDrawer = false,
|
|
18
|
+
onPaletteModeChange, windowTools, Container, render, ...props
|
|
18
19
|
}) {
|
|
19
20
|
const [showUndock, setShowUndock] = useState(false);
|
|
20
21
|
const [targetsPinned, setTargetsPinned] = useState(false);
|
|
21
22
|
const [showStage, setShowStage] = useState(true);
|
|
23
|
+
const [stageDrawerOpen, setStageDrawerOpen] = useState(false);
|
|
22
24
|
const [size, setSize] = useState(null);
|
|
23
25
|
const [targetRatio, setTargetRatio] = useState(null);
|
|
24
26
|
const [preferredStageWidth, setPreferredStageWidth] = useState(null);
|
|
@@ -94,10 +96,11 @@ export function createStandardLayout(React, {styles, targetStyles, context, Layo
|
|
|
94
96
|
};
|
|
95
97
|
if (!plusLayout) return shared;
|
|
96
98
|
const stageOverlap = `${stageWidth + 20}px`;
|
|
99
|
+
const stageOverlaps = showStage && (!stageDrawer || stageDrawerOpen);
|
|
97
100
|
const bodyStyle = {
|
|
98
101
|
display: 'grid',
|
|
99
|
-
'--plus-stage-overlap':
|
|
100
|
-
'--plus-stage-tab-inset':
|
|
102
|
+
'--plus-stage-overlap': stageOverlaps ? stageOverlap : '0px',
|
|
103
|
+
'--plus-stage-tab-inset': stageOverlaps ? stageOverlap : '3rem'
|
|
101
104
|
};
|
|
102
105
|
if (resizable) {
|
|
103
106
|
bodyStyle['--plus-target-width'] = `${targetSplit.first}px`;
|
|
@@ -117,7 +120,7 @@ export function createStandardLayout(React, {styles, targetStyles, context, Layo
|
|
|
117
120
|
columnSplitter,
|
|
118
121
|
editorStyle: {gridArea: 'editor', minWidth: 0, minHeight: 0},
|
|
119
122
|
stageColumnStyle: {display: 'contents'},
|
|
120
|
-
stageClassName: `${styles.stagePanel} ${styles.floatingStage}${stageHidden ? ` ${styles.stageHidden}` : ''}`,
|
|
123
|
+
stageClassName: `${styles.stagePanel} ${styles.floatingStage}${stageDrawer ? ` ${styles.stageDrawer}` : ''}${stageHidden ? ` ${styles.stageHidden}` : ''}`,
|
|
121
124
|
targetClassName: targetsPinned ? styles.standardTargets :
|
|
122
125
|
`${styles.standardTargets} ${styles.retractedTargets}`,
|
|
123
126
|
stageDisplayWidth: stageWidth,
|
|
@@ -142,7 +145,8 @@ export function createStandardLayout(React, {styles, targetStyles, context, Layo
|
|
|
142
145
|
render: slots => render(applyStandardLayout(slots), showUndock)
|
|
143
146
|
});
|
|
144
147
|
return element(context.Provider, {value: {
|
|
145
|
-
showUndock, plusLayout, targetsPinned, setTargetsPinned, stageHidden, setStageVisible: setShowStage, stageResize, stageActionMount,
|
|
148
|
+
showUndock, plusLayout, targetsPinned, setTargetsPinned, stageHidden, setStageVisible: setShowStage, stageResize, stageActionMount,
|
|
149
|
+
stageDrawer: plusLayout && stageDrawer, setStageDrawerOpen, locale: props.locale
|
|
146
150
|
}},
|
|
147
151
|
Container ? element(Container, {locale: props.locale}, layout) : layout);
|
|
148
152
|
}
|
|
@@ -192,7 +196,7 @@ export function createStandardLayout(React, {styles, targetStyles, context, Layo
|
|
|
192
196
|
if (panel.current && !panel.current.hidden) panel.current.focus({preventScroll: true});
|
|
193
197
|
});
|
|
194
198
|
}
|
|
195
|
-
},
|
|
199
|
+
}, {left: '›', right: '‹', bottom: '⌃'}[edge]),
|
|
196
200
|
element('div', {className: styles.edgePanel, ref: panel, tabIndex: -1, hidden: !open}, children));
|
|
197
201
|
}
|
|
198
202
|
|