@forgeax/app-shell 0.43.0 → 0.45.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 +40 -2
- package/dist/react.js +177 -6
- 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
|
|
|
@@ -92,6 +92,44 @@ interface AnchoredResizeHandleProps extends Omit<ResizeHandleProps, 'onDrag' | '
|
|
|
92
92
|
/** Product-neutral anchored resize session over the public pointer carrier. */
|
|
93
93
|
declare function AnchoredResizeHandle({ readSize, writeSize, direction, resizingBodyClassName, ...handleProps }: AnchoredResizeHandleProps): react.JSX.Element;
|
|
94
94
|
|
|
95
|
+
type PointerReorderFinishReason = 'pointerup' | 'pointercancel' | 'buttons-released' | 'replacement' | 'cancel' | 'dispose' | 'error';
|
|
96
|
+
interface PointerReorderSessionOptions<Item> {
|
|
97
|
+
readonly element: HTMLElement;
|
|
98
|
+
readonly target: Window;
|
|
99
|
+
readonly resolveItem: (target: EventTarget | null) => Item | null;
|
|
100
|
+
readonly canStart?: (event: globalThis.PointerEvent, item: Item) => boolean;
|
|
101
|
+
readonly reorder: (dragged: Item, over: Item, event: globalThis.PointerEvent) => void;
|
|
102
|
+
readonly onDraggingChange?: (item: Item | null, reason?: PointerReorderFinishReason) => void;
|
|
103
|
+
readonly equals?: (left: Item, right: Item) => boolean;
|
|
104
|
+
}
|
|
105
|
+
interface PointerReorderSession {
|
|
106
|
+
cancel(): void;
|
|
107
|
+
dispose(): void;
|
|
108
|
+
}
|
|
109
|
+
/** Own one delegated pointer reorder lifecycle without owning item identity or mutation policy. */
|
|
110
|
+
declare function installPointerReorderSession<Item>(options: PointerReorderSessionOptions<Item>): PointerReorderSession;
|
|
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
|
+
|
|
95
133
|
type PanelContentPadding = 'none' | 'sm' | 'md';
|
|
96
134
|
type PanelContentScroll = 'none' | 'auto';
|
|
97
135
|
type PanelContentTone = 'default' | 'surface' | 'tool';
|
|
@@ -233,4 +271,4 @@ interface ShellSlotProps extends HTMLAttributes<HTMLElement> {
|
|
|
233
271
|
/** Structural shell marker that preserves the caller's semantic element. */
|
|
234
272
|
declare function ShellSlot({ as, name, ...props }: ShellSlotProps): ReactElement;
|
|
235
273
|
|
|
236
|
-
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, 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, installThresholdPointerDragSession, isSlotDebugEnabled, useDockLayoutControlBinding, useLocalSize, usePersistentSizeStore };
|
|
274
|
+
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 TabCloseInteractions, type TabCloseInteractionsOptions, type ThresholdPointerDragFinishReason, type ThresholdPointerDragSession, type ThresholdPointerDragSessionOptions, applyAnchoredResizeDelta, beginAnchoredResize, createPersistentSizeStore, hashSlotHue, installPointerDragSession, installPointerReorderSession, installThresholdPointerDragSession, isSlotDebugEnabled, useDockLayoutControlBinding, useLocalSize, usePersistentSizeStore, useTabCloseInteractions };
|
package/dist/react.js
CHANGED
|
@@ -1067,6 +1067,175 @@ function AnchoredResizeHandle({
|
|
|
1067
1067
|
);
|
|
1068
1068
|
}
|
|
1069
1069
|
|
|
1070
|
+
// src/pointer-reorder.ts
|
|
1071
|
+
function installPointerReorderSession(options) {
|
|
1072
|
+
const equals = options.equals ?? Object.is;
|
|
1073
|
+
let disposed = false;
|
|
1074
|
+
let generation = 0;
|
|
1075
|
+
let active = null;
|
|
1076
|
+
const publishDragging = (item, reason) => {
|
|
1077
|
+
try {
|
|
1078
|
+
options.onDraggingChange?.(item, reason);
|
|
1079
|
+
} catch {
|
|
1080
|
+
}
|
|
1081
|
+
};
|
|
1082
|
+
const settle = (reason) => {
|
|
1083
|
+
const current = active;
|
|
1084
|
+
if (current === null) return;
|
|
1085
|
+
active = null;
|
|
1086
|
+
if (current.dragging) publishDragging(null, reason);
|
|
1087
|
+
};
|
|
1088
|
+
const onPointerDown = (event) => {
|
|
1089
|
+
if (disposed || event.button !== 0 || event.isPrimary === false) return;
|
|
1090
|
+
let item;
|
|
1091
|
+
try {
|
|
1092
|
+
item = options.resolveItem(event.target);
|
|
1093
|
+
if (item === null || options.canStart?.(event, item) === false) return;
|
|
1094
|
+
} catch {
|
|
1095
|
+
return;
|
|
1096
|
+
}
|
|
1097
|
+
const nextGeneration = ++generation;
|
|
1098
|
+
settle("replacement");
|
|
1099
|
+
if (disposed || generation !== nextGeneration) return;
|
|
1100
|
+
active = {
|
|
1101
|
+
generation: nextGeneration,
|
|
1102
|
+
pointerId: event.pointerId,
|
|
1103
|
+
item,
|
|
1104
|
+
dragging: false,
|
|
1105
|
+
lastOver: null
|
|
1106
|
+
};
|
|
1107
|
+
};
|
|
1108
|
+
const onPointerMove = (event) => {
|
|
1109
|
+
const current = active;
|
|
1110
|
+
if (disposed || current === null || event.pointerId !== current.pointerId) return;
|
|
1111
|
+
if ((event.buttons & 1) !== 1) {
|
|
1112
|
+
settle("buttons-released");
|
|
1113
|
+
return;
|
|
1114
|
+
}
|
|
1115
|
+
let over;
|
|
1116
|
+
try {
|
|
1117
|
+
over = options.resolveItem(event.target);
|
|
1118
|
+
} catch {
|
|
1119
|
+
settle("error");
|
|
1120
|
+
return;
|
|
1121
|
+
}
|
|
1122
|
+
if (active !== current || current.generation !== generation) return;
|
|
1123
|
+
if (over === null) return;
|
|
1124
|
+
let sameItem;
|
|
1125
|
+
try {
|
|
1126
|
+
sameItem = equals(over, current.item);
|
|
1127
|
+
} catch {
|
|
1128
|
+
if (active === current) settle("error");
|
|
1129
|
+
return;
|
|
1130
|
+
}
|
|
1131
|
+
if (active !== current || current.generation !== generation || sameItem) return;
|
|
1132
|
+
if (current.lastOver !== null) {
|
|
1133
|
+
let sameTarget;
|
|
1134
|
+
try {
|
|
1135
|
+
sameTarget = equals(over, current.lastOver);
|
|
1136
|
+
} catch {
|
|
1137
|
+
if (active === current) settle("error");
|
|
1138
|
+
return;
|
|
1139
|
+
}
|
|
1140
|
+
if (active !== current || current.generation !== generation || sameTarget) return;
|
|
1141
|
+
}
|
|
1142
|
+
current.lastOver = over;
|
|
1143
|
+
if (!current.dragging) {
|
|
1144
|
+
current.dragging = true;
|
|
1145
|
+
publishDragging(current.item);
|
|
1146
|
+
if (active !== current || current.generation !== generation) return;
|
|
1147
|
+
}
|
|
1148
|
+
try {
|
|
1149
|
+
options.reorder(current.item, over, event);
|
|
1150
|
+
} catch {
|
|
1151
|
+
settle("error");
|
|
1152
|
+
}
|
|
1153
|
+
};
|
|
1154
|
+
const onPointerFinish = (event) => {
|
|
1155
|
+
const current = active;
|
|
1156
|
+
if (disposed || current === null || event.pointerId !== current.pointerId) return;
|
|
1157
|
+
settle(event.type === "pointercancel" ? "pointercancel" : "pointerup");
|
|
1158
|
+
};
|
|
1159
|
+
options.element.addEventListener("pointerdown", onPointerDown);
|
|
1160
|
+
options.element.addEventListener("pointermove", onPointerMove);
|
|
1161
|
+
options.target.addEventListener("pointerup", onPointerFinish, true);
|
|
1162
|
+
options.target.addEventListener("pointercancel", onPointerFinish, true);
|
|
1163
|
+
return {
|
|
1164
|
+
cancel: () => settle("cancel"),
|
|
1165
|
+
dispose: () => {
|
|
1166
|
+
if (disposed) return;
|
|
1167
|
+
disposed = true;
|
|
1168
|
+
generation += 1;
|
|
1169
|
+
options.element.removeEventListener("pointerdown", onPointerDown);
|
|
1170
|
+
options.element.removeEventListener("pointermove", onPointerMove);
|
|
1171
|
+
options.target.removeEventListener("pointerup", onPointerFinish, true);
|
|
1172
|
+
options.target.removeEventListener("pointercancel", onPointerFinish, true);
|
|
1173
|
+
settle("dispose");
|
|
1174
|
+
}
|
|
1175
|
+
};
|
|
1176
|
+
}
|
|
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
|
+
|
|
1070
1239
|
// src/panel.tsx
|
|
1071
1240
|
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
1072
1241
|
function PanelEmptyState({
|
|
@@ -1209,7 +1378,7 @@ var SurfaceRegion = forwardRef(
|
|
|
1209
1378
|
);
|
|
1210
1379
|
|
|
1211
1380
|
// src/dock-layout-control.ts
|
|
1212
|
-
import { useEffect as
|
|
1381
|
+
import { useEffect as useEffect4, useMemo, useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
1213
1382
|
function useDockLayoutControlBinding({
|
|
1214
1383
|
state,
|
|
1215
1384
|
onToggle,
|
|
@@ -1222,7 +1391,7 @@ function useDockLayoutControlBinding({
|
|
|
1222
1391
|
state.getSnapshot,
|
|
1223
1392
|
state.getSnapshot
|
|
1224
1393
|
);
|
|
1225
|
-
|
|
1394
|
+
useEffect4(() => installDockLayoutControlToggle({ onToggle }, state), [onToggle, state]);
|
|
1226
1395
|
const panelControl = useMemo(() => createDockLayoutPanelControl({
|
|
1227
1396
|
isOpen: isPanelOpen,
|
|
1228
1397
|
close: closePanel,
|
|
@@ -1233,7 +1402,7 @@ function useDockLayoutControlBinding({
|
|
|
1233
1402
|
|
|
1234
1403
|
// src/floating-menu.tsx
|
|
1235
1404
|
var import_react_dom = __toESM(require_react_dom(), 1);
|
|
1236
|
-
import { useEffect as
|
|
1405
|
+
import { useEffect as useEffect5, useLayoutEffect, useRef as useRef3, useState as useState3 } from "react";
|
|
1237
1406
|
import { Fragment, jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1238
1407
|
var VIEWPORT_PADDING = 8;
|
|
1239
1408
|
function FloatingMenu({
|
|
@@ -1246,7 +1415,7 @@ function FloatingMenu({
|
|
|
1246
1415
|
className,
|
|
1247
1416
|
children
|
|
1248
1417
|
}) {
|
|
1249
|
-
const menuRef =
|
|
1418
|
+
const menuRef = useRef3(null);
|
|
1250
1419
|
const [position, setPosition] = useState3({ top: 0 });
|
|
1251
1420
|
useLayoutEffect(() => {
|
|
1252
1421
|
if (!open) return;
|
|
@@ -1283,7 +1452,7 @@ function FloatingMenu({
|
|
|
1283
1452
|
}
|
|
1284
1453
|
}
|
|
1285
1454
|
}, [align, anchor?.bottom, anchor?.left, anchor?.right, anchor?.top, offset, open, point?.x, point?.y]);
|
|
1286
|
-
|
|
1455
|
+
useEffect5(() => {
|
|
1287
1456
|
if (!open) return;
|
|
1288
1457
|
const closeOnEscape = (event) => {
|
|
1289
1458
|
if (event.key === "Escape") onClose();
|
|
@@ -1435,11 +1604,13 @@ export {
|
|
|
1435
1604
|
createPersistentSizeStore,
|
|
1436
1605
|
hashSlotHue,
|
|
1437
1606
|
installPointerDragSession,
|
|
1607
|
+
installPointerReorderSession,
|
|
1438
1608
|
installThresholdPointerDragSession,
|
|
1439
1609
|
isSlotDebugEnabled,
|
|
1440
1610
|
useDockLayoutControlBinding,
|
|
1441
1611
|
useLocalSize,
|
|
1442
|
-
usePersistentSizeStore
|
|
1612
|
+
usePersistentSizeStore,
|
|
1613
|
+
useTabCloseInteractions
|
|
1443
1614
|
};
|
|
1444
1615
|
/*! Bundled license information:
|
|
1445
1616
|
|