@kubohiroya/turbowarp-plus-editor-layout 0.1.12 → 0.1.14

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.
@@ -15,7 +15,7 @@ export declare function stageDockActionLabel(locale: string, { drawer, detached,
15
15
  drawer?: boolean;
16
16
  detached: boolean;
17
17
  external?: boolean;
18
- }): "ドックに戻す" | "Dock stage" | "ステージを別ウィンドウで開く" | "別ウィンドウで開く" | "Open in a separate window" | "アンドック" | "Undock stage";
18
+ }): "ステージをエディターに戻す" | "Dock stage" | "ステージを別ウィンドウで開く" | "別ウィンドウで開く" | "Open in a separate window" | "アンドック" | "Undock stage";
19
19
  type StagePlacement = Pick<NonNullable<ReturnType<typeof useDockviewStage>>, 'surface' | 'inlineRef' | 'docked'>;
20
20
  export declare function createStageSurface(React: typeof import('react'), { context, EdgeDrawer, Panel }: {
21
21
  context: Context<{
@@ -53,7 +53,7 @@ const isJapanese = (locale) => /^ja(?:-|$)/i.test(locale);
53
53
  export function stageDockActionLabel(locale, { drawer, detached, external }) {
54
54
  const japanese = isJapanese(locale);
55
55
  if (detached)
56
- return japanese ? 'ドックに戻す' : 'Dock stage';
56
+ return japanese ? 'ステージをエディターに戻す' : 'Dock stage';
57
57
  if (external)
58
58
  return japanese ? (drawer ? 'ステージを別ウィンドウで開く' : '別ウィンドウで開く') : 'Open in a separate window';
59
59
  return japanese ? 'アンドック' : 'Undock stage';
@@ -81,7 +81,8 @@ export function createStageSurface(React, { context, EdgeDrawer, Panel }) {
81
81
  edge: 'right',
82
82
  label: japanese ? 'ステージを展開' : 'Reveal stage',
83
83
  onOpenChange: setStageDrawerOpen,
84
- portalContent: Boolean(placement)
84
+ portalContent: Boolean(placement),
85
+ holdOpenSelector: '[data-turbowarp-app-shell-source-chooser][role="dialog"][aria-modal="true"]'
85
86
  }, inline) : inline;
86
87
  return placement ? React.createElement(React.Fragment, null, dock, createPortal(panel, placement.surface)) : dock;
87
88
  };
@@ -16,12 +16,13 @@ export declare function createStandardLayout(React: any, { styles, targetStyles,
16
16
  Container: any;
17
17
  render: any;
18
18
  }) => any;
19
- EdgeDrawer: ({ edge, label, pinned, onOpenChange, portalContent, children }: {
19
+ EdgeDrawer: ({ edge, label, pinned, onOpenChange, portalContent, holdOpenSelector, children }: {
20
20
  edge: any;
21
21
  label: any;
22
22
  pinned?: boolean;
23
23
  onOpenChange: any;
24
24
  portalContent?: boolean;
25
+ holdOpenSelector?: string;
25
26
  children: any;
26
27
  }) => any;
27
28
  TargetLayout: ({ compact, render }: {
@@ -12,7 +12,7 @@ export function createStandardLayout(React, { styles, targetStyles, context, Lay
12
12
  const targetTools = React.createContext(null);
13
13
  function StandardLayout({ enabled, splitter, windowLayout, stageActionEnabled, stageDrawer = false, onPaletteModeChange, windowTools, Container, render, ...props }) {
14
14
  const [showUndock, setShowUndock] = useState(false);
15
- const [targetsPinned, setTargetsPinned] = useState(false);
15
+ const [targetsPinned, setTargetsPinned] = useState(true);
16
16
  const [showStage, setShowStage] = useState(true);
17
17
  const [stageDrawerOpen, setStageDrawerOpen] = useState(false);
18
18
  const [size, setSize] = useState(null);
@@ -136,13 +136,33 @@ export function createStandardLayout(React, { styles, targetStyles, context, Lay
136
136
  stageDrawer: plusLayout && stageDrawer, setStageDrawerOpen, locale: props.locale
137
137
  } }, Container ? element(Container, { locale: props.locale }, layout) : layout);
138
138
  }
139
- function EdgeDrawer({ edge, label, pinned = false, onOpenChange, portalContent = false, children }) {
139
+ function EdgeDrawer({ edge, label, pinned = false, onOpenChange, portalContent = false, holdOpenSelector = '', children }) {
140
140
  const [hovered, setHovered] = useState(false);
141
141
  const [engaged, setEngaged] = useState(false);
142
+ const [heldOpen, setHeldOpen] = useState(false);
142
143
  const drawer = useRef(null);
143
144
  const trigger = useRef(null);
144
145
  const panel = useRef(null);
145
- const open = pinned || hovered || engaged;
146
+ const open = pinned || hovered || engaged || heldOpen;
147
+ useLayoutEffect(() => {
148
+ if (!holdOpenSelector)
149
+ return;
150
+ const node = panel.current;
151
+ const view = node.ownerDocument.defaultView;
152
+ if (!view)
153
+ return;
154
+ const update = () => setHeldOpen(Array.from(node.querySelectorAll(holdOpenSelector)).some(element => !element.hasAttribute('hidden') && element.getAttribute('aria-hidden') !== 'true' &&
155
+ view.getComputedStyle(element).display !== 'none'));
156
+ const observer = new view.MutationObserver(records => {
157
+ if (records.some(record => record.type === 'childList' ||
158
+ record.target.matches(holdOpenSelector)))
159
+ update();
160
+ });
161
+ observer.observe(node, { subtree: true, childList: true, attributes: true,
162
+ attributeFilter: ['style', 'hidden', 'aria-hidden'] });
163
+ update();
164
+ return () => observer.disconnect();
165
+ }, [holdOpenSelector]);
146
166
  useLayoutEffect(() => { onOpenChange?.(open); }, [open, onOpenChange]);
147
167
  const enter = (event) => {
148
168
  if (event.pointerType === 'mouse')
@@ -180,7 +200,7 @@ export function createStandardLayout(React, { styles, targetStyles, context, Lay
180
200
  'data-pinned': pinned || undefined,
181
201
  ...(!portalContent && { onPointerEnter: enter, onPointerLeave: leave, onFocus: focus, onBlur: blur }),
182
202
  onKeyDown: event => {
183
- if (event.key !== 'Escape' || pinned || !open || event.defaultPrevented)
203
+ if (event.key !== 'Escape' || pinned || heldOpen || !open || event.defaultPrevented)
184
204
  return;
185
205
  setHovered(false);
186
206
  setEngaged(false);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubohiroya/turbowarp-plus-editor-layout",
3
- "version": "0.1.12",
3
+ "version": "0.1.14",
4
4
  "description": "Resizable panes and layout for TurboWarp Plus Editor",
5
5
  "type": "module",
6
6
  "license": "GPL-3.0-or-later",
@@ -71,7 +71,7 @@ export function stageDockActionLabel(locale: string, {drawer, detached, external
71
71
  external?: boolean;
72
72
  }) {
73
73
  const japanese = isJapanese(locale);
74
- if (detached) return japanese ? 'ドックに戻す' : 'Dock stage';
74
+ if (detached) return japanese ? 'ステージをエディターに戻す' : 'Dock stage';
75
75
  if (external) return japanese ? (drawer ? 'ステージを別ウィンドウで開く' : '別ウィンドウで開く') : 'Open in a separate window';
76
76
  return japanese ? 'アンドック' : 'Undock stage';
77
77
  }
@@ -107,7 +107,8 @@ export function createStageSurface(React: typeof import('react'), {
107
107
  edge: 'right',
108
108
  label: japanese ? 'ステージを展開' : 'Reveal stage',
109
109
  onOpenChange: setStageDrawerOpen,
110
- portalContent: Boolean(placement)
110
+ portalContent: Boolean(placement),
111
+ holdOpenSelector: '[data-turbowarp-app-shell-source-chooser][role="dialog"][aria-modal="true"]'
111
112
  }, inline) : inline;
112
113
  return placement ? React.createElement(React.Fragment, null, dock, createPortal(panel, placement.surface)) : dock;
113
114
  };
@@ -18,7 +18,7 @@ export function createStandardLayout(React, {styles, targetStyles, context, Layo
18
18
  onPaletteModeChange, windowTools, Container, render, ...props
19
19
  }) {
20
20
  const [showUndock, setShowUndock] = useState(false);
21
- const [targetsPinned, setTargetsPinned] = useState(false);
21
+ const [targetsPinned, setTargetsPinned] = useState(true);
22
22
  const [showStage, setShowStage] = useState(true);
23
23
  const [stageDrawerOpen, setStageDrawerOpen] = useState(false);
24
24
  const [size, setSize] = useState(null);
@@ -151,13 +151,33 @@ export function createStandardLayout(React, {styles, targetStyles, context, Layo
151
151
  Container ? element(Container, {locale: props.locale}, layout) : layout);
152
152
  }
153
153
 
154
- function EdgeDrawer({edge, label, pinned = false, onOpenChange, portalContent = false, children}) {
154
+ function EdgeDrawer({edge, label, pinned = false, onOpenChange, portalContent = false, holdOpenSelector = '', children}) {
155
155
  const [hovered, setHovered] = useState(false);
156
156
  const [engaged, setEngaged] = useState(false);
157
+ const [heldOpen, setHeldOpen] = useState(false);
157
158
  const drawer = useRef(null);
158
159
  const trigger = useRef(null);
159
160
  const panel = useRef(null);
160
- const open = pinned || hovered || engaged;
161
+ const open = pinned || hovered || engaged || heldOpen;
162
+
163
+ useLayoutEffect(() => {
164
+ if (!holdOpenSelector) return;
165
+ const node = panel.current as HTMLElement;
166
+ const view = node.ownerDocument.defaultView;
167
+ if (!view) return;
168
+ const update = () => setHeldOpen(Array.from(node.querySelectorAll(holdOpenSelector)).some(element =>
169
+ !element.hasAttribute('hidden') && element.getAttribute('aria-hidden') !== 'true' &&
170
+ view.getComputedStyle(element).display !== 'none'
171
+ ));
172
+ const observer = new view.MutationObserver(records => {
173
+ if (records.some(record => record.type === 'childList' ||
174
+ (record.target as Element).matches(holdOpenSelector))) update();
175
+ });
176
+ observer.observe(node, {subtree: true, childList: true, attributes: true,
177
+ attributeFilter: ['style', 'hidden', 'aria-hidden']});
178
+ update();
179
+ return () => observer.disconnect();
180
+ }, [holdOpenSelector]);
161
181
 
162
182
  useLayoutEffect(() => {onOpenChange?.(open);}, [open, onOpenChange]);
163
183
 
@@ -195,7 +215,7 @@ export function createStandardLayout(React, {styles, targetStyles, context, Layo
195
215
  'data-pinned': pinned || undefined,
196
216
  ...(!portalContent && {onPointerEnter: enter, onPointerLeave: leave, onFocus: focus, onBlur: blur}),
197
217
  onKeyDown: event => {
198
- if (event.key !== 'Escape' || pinned || !open || event.defaultPrevented) return;
218
+ if (event.key !== 'Escape' || pinned || heldOpen || !open || event.defaultPrevented) return;
199
219
  setHovered(false);
200
220
  setEngaged(false);
201
221
  trigger.current.focus();