@forgeax/app-shell 0.44.0 → 0.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/react.d.ts +36 -2
- package/dist/react.js +138 -9
- package/package.json +1 -1
package/dist/react.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { ReactElement, HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
import { ReactElement, RefCallback, PointerEventHandler, HTMLAttributes, ReactNode } from 'react';
|
|
3
3
|
import { DetachedWindowCapability } from './window.js';
|
|
4
4
|
import { DockLayoutControlSnapshot, DockLayoutPanelControl, DockLayoutControlState, DockLayoutControlToggleSource } from './dock.js';
|
|
5
5
|
|
|
@@ -109,6 +109,40 @@ interface PointerReorderSession {
|
|
|
109
109
|
/** Own one delegated pointer reorder lifecycle without owning item identity or mutation policy. */
|
|
110
110
|
declare function installPointerReorderSession<Item>(options: PointerReorderSessionOptions<Item>): PointerReorderSession;
|
|
111
111
|
|
|
112
|
+
interface TabCloseInteractionsOptions<TabElement extends HTMLElement = HTMLElement> {
|
|
113
|
+
readonly close: () => void;
|
|
114
|
+
readonly disabled?: boolean;
|
|
115
|
+
readonly onPointerDown?: PointerEventHandler<TabElement>;
|
|
116
|
+
readonly onPointerUp?: PointerEventHandler<TabElement>;
|
|
117
|
+
readonly onPointerLeave?: PointerEventHandler<TabElement>;
|
|
118
|
+
}
|
|
119
|
+
interface TabCloseInteractions<TabElement extends HTMLElement = HTMLElement> {
|
|
120
|
+
readonly closeRef: RefCallback<HTMLElement>;
|
|
121
|
+
readonly onPointerDown: PointerEventHandler<TabElement>;
|
|
122
|
+
readonly onPointerUp: PointerEventHandler<TabElement>;
|
|
123
|
+
readonly onPointerLeave: PointerEventHandler<TabElement>;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Owns the browser-specific close gestures for a tab without owning tab identity,
|
|
127
|
+
* close policy, or presentation. Native pointerdown keeps an action surface from
|
|
128
|
+
* activating its parent tab; a middle-button close settles only the matching
|
|
129
|
+
* pointer that armed it.
|
|
130
|
+
*/
|
|
131
|
+
declare function useTabCloseInteractions<TabElement extends HTMLElement = HTMLElement>(options: TabCloseInteractionsOptions<TabElement>): TabCloseInteractions<TabElement>;
|
|
132
|
+
|
|
133
|
+
interface LiveTabTitleSource {
|
|
134
|
+
getTitle(): string | undefined;
|
|
135
|
+
subscribe(listener: () => void): () => void;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Observe one live tab title without owning its identity or display policy.
|
|
139
|
+
*
|
|
140
|
+
* The post-subscription read closes the gap between render and listener
|
|
141
|
+
* installation. A generation fence prevents retained listeners from a
|
|
142
|
+
* replaced source from publishing stale values.
|
|
143
|
+
*/
|
|
144
|
+
declare function useLiveTabTitle(source: LiveTabTitleSource): string | undefined;
|
|
145
|
+
|
|
112
146
|
type PanelContentPadding = 'none' | 'sm' | 'md';
|
|
113
147
|
type PanelContentScroll = 'none' | 'auto';
|
|
114
148
|
type PanelContentTone = 'default' | 'surface' | 'tool';
|
|
@@ -250,4 +284,4 @@ interface ShellSlotProps extends HTMLAttributes<HTMLElement> {
|
|
|
250
284
|
/** Structural shell marker that preserves the caller's semantic element. */
|
|
251
285
|
declare function ShellSlot({ as, name, ...props }: ShellSlotProps): ReactElement;
|
|
252
286
|
|
|
253
|
-
export { type AnchoredResizeDirection, AnchoredResizeHandle, type AnchoredResizeHandleProps, type AnchoredResizeSession, DetachedPanelBoundary, type DetachedPanelBoundaryProps, DetachedSurfaceFrame, type DetachedSurfaceFrameProps, DetachedSurfaceStatus, type DetachedSurfaceStatusProps, type DetachedSurfaceStatusTone, type DockLayoutControlBinding, type DockLayoutControlBindingOptions, DockLayoutMenu, type DockLayoutMenuPanel, type DockLayoutMenuProps, FloatingMenu, type FloatingMenuAnchor, type FloatingMenuPoint, type FloatingMenuProps, type PanelContentPadding, type PanelContentPolicy, type PanelContentScroll, type PanelContentTone, PanelEmptyState, type PanelEmptyStateProps, PanelSurface, type PanelSurfaceProps, type PersistentSizeStorage, type PersistentSizeStore, type PersistentSizeStoreOptions, type PersistentSizeUpdate, type PointerDragFinishReason, type PointerDragSessionOptions, type PointerReorderFinishReason, type PointerReorderSession, type PointerReorderSessionOptions, ResizeHandle, type ResizeHandleProps, ShellSlot, type ShellSlotElement, type ShellSlotProps, SlotDebugOverlay, SurfacePlaceholder, type SurfacePlaceholderProps, SurfaceRegion, type SurfaceRegionProps, type ThresholdPointerDragFinishReason, type ThresholdPointerDragSession, type ThresholdPointerDragSessionOptions, applyAnchoredResizeDelta, beginAnchoredResize, createPersistentSizeStore, hashSlotHue, installPointerDragSession, installPointerReorderSession, installThresholdPointerDragSession, isSlotDebugEnabled, useDockLayoutControlBinding, useLocalSize, usePersistentSizeStore };
|
|
287
|
+
export { type AnchoredResizeDirection, AnchoredResizeHandle, type AnchoredResizeHandleProps, type AnchoredResizeSession, DetachedPanelBoundary, type DetachedPanelBoundaryProps, DetachedSurfaceFrame, type DetachedSurfaceFrameProps, DetachedSurfaceStatus, type DetachedSurfaceStatusProps, type DetachedSurfaceStatusTone, type DockLayoutControlBinding, type DockLayoutControlBindingOptions, DockLayoutMenu, type DockLayoutMenuPanel, type DockLayoutMenuProps, FloatingMenu, type FloatingMenuAnchor, type FloatingMenuPoint, type FloatingMenuProps, type LiveTabTitleSource, type PanelContentPadding, type PanelContentPolicy, type PanelContentScroll, type PanelContentTone, PanelEmptyState, type PanelEmptyStateProps, PanelSurface, type PanelSurfaceProps, type PersistentSizeStorage, type PersistentSizeStore, type PersistentSizeStoreOptions, type PersistentSizeUpdate, type PointerDragFinishReason, type PointerDragSessionOptions, type PointerReorderFinishReason, type PointerReorderSession, type PointerReorderSessionOptions, ResizeHandle, type ResizeHandleProps, ShellSlot, type ShellSlotElement, type ShellSlotProps, SlotDebugOverlay, SurfacePlaceholder, type SurfacePlaceholderProps, SurfaceRegion, type SurfaceRegionProps, type TabCloseInteractions, type TabCloseInteractionsOptions, type ThresholdPointerDragFinishReason, type ThresholdPointerDragSession, type ThresholdPointerDragSessionOptions, applyAnchoredResizeDelta, beginAnchoredResize, createPersistentSizeStore, hashSlotHue, installPointerDragSession, installPointerReorderSession, installThresholdPointerDragSession, isSlotDebugEnabled, useDockLayoutControlBinding, useLiveTabTitle, useLocalSize, usePersistentSizeStore, useTabCloseInteractions };
|
package/dist/react.js
CHANGED
|
@@ -1175,6 +1175,133 @@ function installPointerReorderSession(options) {
|
|
|
1175
1175
|
};
|
|
1176
1176
|
}
|
|
1177
1177
|
|
|
1178
|
+
// src/tab-close.tsx
|
|
1179
|
+
import {
|
|
1180
|
+
useCallback,
|
|
1181
|
+
useEffect as useEffect3,
|
|
1182
|
+
useRef as useRef2
|
|
1183
|
+
} from "react";
|
|
1184
|
+
function useTabCloseInteractions(options) {
|
|
1185
|
+
const optionsRef = useRef2(options);
|
|
1186
|
+
const closeElementRef = useRef2(null);
|
|
1187
|
+
const middlePointerRef = useRef2(null);
|
|
1188
|
+
optionsRef.current = options;
|
|
1189
|
+
const closeCurrent = useCallback(() => {
|
|
1190
|
+
const current = optionsRef.current;
|
|
1191
|
+
if (current.disabled) return;
|
|
1192
|
+
try {
|
|
1193
|
+
current.close();
|
|
1194
|
+
} catch {
|
|
1195
|
+
}
|
|
1196
|
+
}, []);
|
|
1197
|
+
const onClosePointerDown = useCallback((event) => {
|
|
1198
|
+
event.preventDefault();
|
|
1199
|
+
event.stopPropagation();
|
|
1200
|
+
closeCurrent();
|
|
1201
|
+
}, [closeCurrent]);
|
|
1202
|
+
const closeRef = useCallback((element) => {
|
|
1203
|
+
const previous = closeElementRef.current;
|
|
1204
|
+
if (previous === element) return;
|
|
1205
|
+
previous?.removeEventListener("pointerdown", onClosePointerDown);
|
|
1206
|
+
closeElementRef.current = element;
|
|
1207
|
+
element?.addEventListener("pointerdown", onClosePointerDown);
|
|
1208
|
+
}, [onClosePointerDown]);
|
|
1209
|
+
const forward = useCallback((callback, event) => {
|
|
1210
|
+
try {
|
|
1211
|
+
callback?.(event);
|
|
1212
|
+
} catch {
|
|
1213
|
+
}
|
|
1214
|
+
}, []);
|
|
1215
|
+
const onPointerDown = useCallback((event) => {
|
|
1216
|
+
middlePointerRef.current = event.button === 1 ? event.pointerId : null;
|
|
1217
|
+
forward(optionsRef.current.onPointerDown, event);
|
|
1218
|
+
}, [forward]);
|
|
1219
|
+
const onPointerUp = useCallback((event) => {
|
|
1220
|
+
const matches = middlePointerRef.current === event.pointerId;
|
|
1221
|
+
const shouldClose = event.button === 1 && matches;
|
|
1222
|
+
if (matches) middlePointerRef.current = null;
|
|
1223
|
+
if (shouldClose) closeCurrent();
|
|
1224
|
+
forward(optionsRef.current.onPointerUp, event);
|
|
1225
|
+
}, [closeCurrent, forward]);
|
|
1226
|
+
const onPointerLeave = useCallback((event) => {
|
|
1227
|
+
if (middlePointerRef.current === event.pointerId) middlePointerRef.current = null;
|
|
1228
|
+
forward(optionsRef.current.onPointerLeave, event);
|
|
1229
|
+
}, [forward]);
|
|
1230
|
+
useEffect3(() => () => {
|
|
1231
|
+
middlePointerRef.current = null;
|
|
1232
|
+
const closeElement = closeElementRef.current;
|
|
1233
|
+
closeElementRef.current = null;
|
|
1234
|
+
closeElement?.removeEventListener("pointerdown", onClosePointerDown);
|
|
1235
|
+
}, [onClosePointerDown]);
|
|
1236
|
+
return { closeRef, onPointerDown, onPointerUp, onPointerLeave };
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
// src/tab-title.tsx
|
|
1240
|
+
import { useMemo, useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
1241
|
+
function stabilizeLiveTabTitleSource(source) {
|
|
1242
|
+
let snapshot;
|
|
1243
|
+
try {
|
|
1244
|
+
snapshot = source.getTitle();
|
|
1245
|
+
} catch {
|
|
1246
|
+
snapshot = void 0;
|
|
1247
|
+
}
|
|
1248
|
+
const synchronize = () => {
|
|
1249
|
+
let next;
|
|
1250
|
+
try {
|
|
1251
|
+
next = source.getTitle();
|
|
1252
|
+
} catch {
|
|
1253
|
+
return false;
|
|
1254
|
+
}
|
|
1255
|
+
if (Object.is(snapshot, next)) return false;
|
|
1256
|
+
snapshot = next;
|
|
1257
|
+
return true;
|
|
1258
|
+
};
|
|
1259
|
+
return {
|
|
1260
|
+
getSnapshot: () => {
|
|
1261
|
+
synchronize();
|
|
1262
|
+
return snapshot;
|
|
1263
|
+
},
|
|
1264
|
+
subscribe: (listener) => {
|
|
1265
|
+
let active = true;
|
|
1266
|
+
const notify = () => {
|
|
1267
|
+
if (!active || !synchronize()) return;
|
|
1268
|
+
try {
|
|
1269
|
+
listener();
|
|
1270
|
+
} catch {
|
|
1271
|
+
}
|
|
1272
|
+
};
|
|
1273
|
+
let dispose = () => {
|
|
1274
|
+
};
|
|
1275
|
+
try {
|
|
1276
|
+
dispose = source.subscribe(notify);
|
|
1277
|
+
} catch {
|
|
1278
|
+
notify();
|
|
1279
|
+
return () => {
|
|
1280
|
+
if (!active) return;
|
|
1281
|
+
active = false;
|
|
1282
|
+
};
|
|
1283
|
+
}
|
|
1284
|
+
notify();
|
|
1285
|
+
return () => {
|
|
1286
|
+
if (!active) return;
|
|
1287
|
+
active = false;
|
|
1288
|
+
try {
|
|
1289
|
+
dispose();
|
|
1290
|
+
} catch {
|
|
1291
|
+
}
|
|
1292
|
+
};
|
|
1293
|
+
}
|
|
1294
|
+
};
|
|
1295
|
+
}
|
|
1296
|
+
function useLiveTabTitle(source) {
|
|
1297
|
+
const stable = useMemo(() => stabilizeLiveTabTitleSource(source), [source]);
|
|
1298
|
+
return useSyncExternalStore2(
|
|
1299
|
+
stable.subscribe,
|
|
1300
|
+
stable.getSnapshot,
|
|
1301
|
+
stable.getSnapshot
|
|
1302
|
+
);
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1178
1305
|
// src/panel.tsx
|
|
1179
1306
|
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
1180
1307
|
function PanelEmptyState({
|
|
@@ -1317,7 +1444,7 @@ var SurfaceRegion = forwardRef(
|
|
|
1317
1444
|
);
|
|
1318
1445
|
|
|
1319
1446
|
// src/dock-layout-control.ts
|
|
1320
|
-
import { useEffect as
|
|
1447
|
+
import { useEffect as useEffect4, useMemo as useMemo2, useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
1321
1448
|
function useDockLayoutControlBinding({
|
|
1322
1449
|
state,
|
|
1323
1450
|
onToggle,
|
|
@@ -1325,23 +1452,23 @@ function useDockLayoutControlBinding({
|
|
|
1325
1452
|
closePanel,
|
|
1326
1453
|
reopenPanel
|
|
1327
1454
|
}) {
|
|
1328
|
-
const snapshot =
|
|
1455
|
+
const snapshot = useSyncExternalStore3(
|
|
1329
1456
|
state.subscribe,
|
|
1330
1457
|
state.getSnapshot,
|
|
1331
1458
|
state.getSnapshot
|
|
1332
1459
|
);
|
|
1333
|
-
|
|
1334
|
-
const panelControl =
|
|
1460
|
+
useEffect4(() => installDockLayoutControlToggle({ onToggle }, state), [onToggle, state]);
|
|
1461
|
+
const panelControl = useMemo2(() => createDockLayoutPanelControl({
|
|
1335
1462
|
isOpen: isPanelOpen,
|
|
1336
1463
|
close: closePanel,
|
|
1337
1464
|
reopen: reopenPanel
|
|
1338
1465
|
}), [closePanel, isPanelOpen, reopenPanel]);
|
|
1339
|
-
return
|
|
1466
|
+
return useMemo2(() => ({ snapshot, panelControl }), [panelControl, snapshot]);
|
|
1340
1467
|
}
|
|
1341
1468
|
|
|
1342
1469
|
// src/floating-menu.tsx
|
|
1343
1470
|
var import_react_dom = __toESM(require_react_dom(), 1);
|
|
1344
|
-
import { useEffect as
|
|
1471
|
+
import { useEffect as useEffect5, useLayoutEffect, useRef as useRef3, useState as useState3 } from "react";
|
|
1345
1472
|
import { Fragment, jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1346
1473
|
var VIEWPORT_PADDING = 8;
|
|
1347
1474
|
function FloatingMenu({
|
|
@@ -1354,7 +1481,7 @@ function FloatingMenu({
|
|
|
1354
1481
|
className,
|
|
1355
1482
|
children
|
|
1356
1483
|
}) {
|
|
1357
|
-
const menuRef =
|
|
1484
|
+
const menuRef = useRef3(null);
|
|
1358
1485
|
const [position, setPosition] = useState3({ top: 0 });
|
|
1359
1486
|
useLayoutEffect(() => {
|
|
1360
1487
|
if (!open) return;
|
|
@@ -1391,7 +1518,7 @@ function FloatingMenu({
|
|
|
1391
1518
|
}
|
|
1392
1519
|
}
|
|
1393
1520
|
}, [align, anchor?.bottom, anchor?.left, anchor?.right, anchor?.top, offset, open, point?.x, point?.y]);
|
|
1394
|
-
|
|
1521
|
+
useEffect5(() => {
|
|
1395
1522
|
if (!open) return;
|
|
1396
1523
|
const closeOnEscape = (event) => {
|
|
1397
1524
|
if (event.key === "Escape") onClose();
|
|
@@ -1547,8 +1674,10 @@ export {
|
|
|
1547
1674
|
installThresholdPointerDragSession,
|
|
1548
1675
|
isSlotDebugEnabled,
|
|
1549
1676
|
useDockLayoutControlBinding,
|
|
1677
|
+
useLiveTabTitle,
|
|
1550
1678
|
useLocalSize,
|
|
1551
|
-
usePersistentSizeStore
|
|
1679
|
+
usePersistentSizeStore,
|
|
1680
|
+
useTabCloseInteractions
|
|
1552
1681
|
};
|
|
1553
1682
|
/*! Bundled license information:
|
|
1554
1683
|
|