@forgeax/app-shell 0.46.0 → 0.47.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 CHANGED
@@ -143,6 +143,17 @@ interface LiveTabTitleSource {
143
143
  */
144
144
  declare function useLiveTabTitle(source: LiveTabTitleSource): string | undefined;
145
145
 
146
+ interface LiveTabPlacement {
147
+ readonly isEdge: boolean;
148
+ readonly groupId: string;
149
+ }
150
+ interface LiveTabPlacementSource {
151
+ getPlacement(): LiveTabPlacement;
152
+ subscribe(listener: () => void): () => void;
153
+ }
154
+ /** Observe one tab's live edge/group placement without owning host identities. */
155
+ declare function useLiveTabPlacement(source: LiveTabPlacementSource): LiveTabPlacement | undefined;
156
+
146
157
  type PanelContentPadding = 'none' | 'sm' | 'md';
147
158
  type PanelContentScroll = 'none' | 'auto';
148
159
  type PanelContentTone = 'default' | 'surface' | 'tool';
@@ -284,4 +295,4 @@ interface ShellSlotProps extends HTMLAttributes<HTMLElement> {
284
295
  /** Structural shell marker that preserves the caller's semantic element. */
285
296
  declare function ShellSlot({ as, name, ...props }: ShellSlotProps): ReactElement;
286
297
 
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 };
298
+ 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 LiveTabPlacement, type LiveTabPlacementSource, 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, useLiveTabPlacement, useLiveTabTitle, useLocalSize, usePersistentSizeStore, useTabCloseInteractions };
package/dist/react.js CHANGED
@@ -1302,6 +1302,76 @@ function useLiveTabTitle(source) {
1302
1302
  );
1303
1303
  }
1304
1304
 
1305
+ // src/tab-placement.tsx
1306
+ import { useMemo as useMemo2, useSyncExternalStore as useSyncExternalStore3 } from "react";
1307
+ function samePlacement(left, right) {
1308
+ return left?.isEdge === right?.isEdge && left?.groupId === right?.groupId;
1309
+ }
1310
+ function stabilizeLiveTabPlacementSource(source) {
1311
+ let snapshot;
1312
+ try {
1313
+ const initial = source.getPlacement();
1314
+ snapshot = Object.freeze({ isEdge: initial.isEdge, groupId: initial.groupId });
1315
+ } catch {
1316
+ snapshot = void 0;
1317
+ }
1318
+ const synchronize = () => {
1319
+ let next;
1320
+ try {
1321
+ next = source.getPlacement();
1322
+ } catch {
1323
+ return false;
1324
+ }
1325
+ if (samePlacement(snapshot, next)) return false;
1326
+ snapshot = Object.freeze({ isEdge: next.isEdge, groupId: next.groupId });
1327
+ return true;
1328
+ };
1329
+ return {
1330
+ getSnapshot: () => {
1331
+ synchronize();
1332
+ return snapshot;
1333
+ },
1334
+ subscribe: (listener) => {
1335
+ let active = true;
1336
+ const notify = () => {
1337
+ if (!active || !synchronize()) return;
1338
+ try {
1339
+ listener();
1340
+ } catch {
1341
+ }
1342
+ };
1343
+ let dispose = () => {
1344
+ };
1345
+ try {
1346
+ dispose = source.subscribe(notify);
1347
+ } catch {
1348
+ notify();
1349
+ return () => {
1350
+ if (!active) return;
1351
+ active = false;
1352
+ };
1353
+ }
1354
+ notify();
1355
+ return () => {
1356
+ if (!active) return;
1357
+ active = false;
1358
+ try {
1359
+ dispose();
1360
+ } catch {
1361
+ }
1362
+ };
1363
+ }
1364
+ };
1365
+ }
1366
+ function useLiveTabPlacement(source) {
1367
+ const stable = useMemo2(() => stabilizeLiveTabPlacementSource(source), [source]);
1368
+ return useSyncExternalStore3(
1369
+ stable.subscribe,
1370
+ stable.getSnapshot,
1371
+ stable.getSnapshot
1372
+ );
1373
+ }
1374
+
1305
1375
  // src/panel.tsx
1306
1376
  import { jsx as jsx3, jsxs } from "react/jsx-runtime";
1307
1377
  function PanelEmptyState({
@@ -1444,7 +1514,7 @@ var SurfaceRegion = forwardRef(
1444
1514
  );
1445
1515
 
1446
1516
  // src/dock-layout-control.ts
1447
- import { useEffect as useEffect4, useMemo as useMemo2, useSyncExternalStore as useSyncExternalStore3 } from "react";
1517
+ import { useEffect as useEffect4, useMemo as useMemo3, useSyncExternalStore as useSyncExternalStore4 } from "react";
1448
1518
  function useDockLayoutControlBinding({
1449
1519
  state,
1450
1520
  onToggle,
@@ -1452,18 +1522,18 @@ function useDockLayoutControlBinding({
1452
1522
  closePanel,
1453
1523
  reopenPanel
1454
1524
  }) {
1455
- const snapshot = useSyncExternalStore3(
1525
+ const snapshot = useSyncExternalStore4(
1456
1526
  state.subscribe,
1457
1527
  state.getSnapshot,
1458
1528
  state.getSnapshot
1459
1529
  );
1460
1530
  useEffect4(() => installDockLayoutControlToggle({ onToggle }, state), [onToggle, state]);
1461
- const panelControl = useMemo2(() => createDockLayoutPanelControl({
1531
+ const panelControl = useMemo3(() => createDockLayoutPanelControl({
1462
1532
  isOpen: isPanelOpen,
1463
1533
  close: closePanel,
1464
1534
  reopen: reopenPanel
1465
1535
  }), [closePanel, isPanelOpen, reopenPanel]);
1466
- return useMemo2(() => ({ snapshot, panelControl }), [panelControl, snapshot]);
1536
+ return useMemo3(() => ({ snapshot, panelControl }), [panelControl, snapshot]);
1467
1537
  }
1468
1538
 
1469
1539
  // src/floating-menu.tsx
@@ -1674,6 +1744,7 @@ export {
1674
1744
  installThresholdPointerDragSession,
1675
1745
  isSlotDebugEnabled,
1676
1746
  useDockLayoutControlBinding,
1747
+ useLiveTabPlacement,
1677
1748
  useLiveTabTitle,
1678
1749
  useLocalSize,
1679
1750
  usePersistentSizeStore,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forgeax/app-shell",
3
- "version": "0.46.0",
3
+ "version": "0.47.0",
4
4
  "description": "Generic Dock, Panel, Window, and Slot composition primitives",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",