@forgeax/app-shell 0.45.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 CHANGED
@@ -130,6 +130,19 @@ interface TabCloseInteractions<TabElement extends HTMLElement = HTMLElement> {
130
130
  */
131
131
  declare function useTabCloseInteractions<TabElement extends HTMLElement = HTMLElement>(options: TabCloseInteractionsOptions<TabElement>): TabCloseInteractions<TabElement>;
132
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
+
133
146
  type PanelContentPadding = 'none' | 'sm' | 'md';
134
147
  type PanelContentScroll = 'none' | 'auto';
135
148
  type PanelContentTone = 'default' | 'surface' | 'tool';
@@ -271,4 +284,4 @@ interface ShellSlotProps extends HTMLAttributes<HTMLElement> {
271
284
  /** Structural shell marker that preserves the caller's semantic element. */
272
285
  declare function ShellSlot({ as, name, ...props }: ShellSlotProps): ReactElement;
273
286
 
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 };
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
@@ -1236,6 +1236,72 @@ function useTabCloseInteractions(options) {
1236
1236
  return { closeRef, onPointerDown, onPointerUp, onPointerLeave };
1237
1237
  }
1238
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
+
1239
1305
  // src/panel.tsx
1240
1306
  import { jsx as jsx3, jsxs } from "react/jsx-runtime";
1241
1307
  function PanelEmptyState({
@@ -1378,7 +1444,7 @@ var SurfaceRegion = forwardRef(
1378
1444
  );
1379
1445
 
1380
1446
  // src/dock-layout-control.ts
1381
- import { useEffect as useEffect4, useMemo, useSyncExternalStore as useSyncExternalStore2 } from "react";
1447
+ import { useEffect as useEffect4, useMemo as useMemo2, useSyncExternalStore as useSyncExternalStore3 } from "react";
1382
1448
  function useDockLayoutControlBinding({
1383
1449
  state,
1384
1450
  onToggle,
@@ -1386,18 +1452,18 @@ function useDockLayoutControlBinding({
1386
1452
  closePanel,
1387
1453
  reopenPanel
1388
1454
  }) {
1389
- const snapshot = useSyncExternalStore2(
1455
+ const snapshot = useSyncExternalStore3(
1390
1456
  state.subscribe,
1391
1457
  state.getSnapshot,
1392
1458
  state.getSnapshot
1393
1459
  );
1394
1460
  useEffect4(() => installDockLayoutControlToggle({ onToggle }, state), [onToggle, state]);
1395
- const panelControl = useMemo(() => createDockLayoutPanelControl({
1461
+ const panelControl = useMemo2(() => createDockLayoutPanelControl({
1396
1462
  isOpen: isPanelOpen,
1397
1463
  close: closePanel,
1398
1464
  reopen: reopenPanel
1399
1465
  }), [closePanel, isPanelOpen, reopenPanel]);
1400
- return useMemo(() => ({ snapshot, panelControl }), [panelControl, snapshot]);
1466
+ return useMemo2(() => ({ snapshot, panelControl }), [panelControl, snapshot]);
1401
1467
  }
1402
1468
 
1403
1469
  // src/floating-menu.tsx
@@ -1608,6 +1674,7 @@ export {
1608
1674
  installThresholdPointerDragSession,
1609
1675
  isSlotDebugEnabled,
1610
1676
  useDockLayoutControlBinding,
1677
+ useLiveTabTitle,
1611
1678
  useLocalSize,
1612
1679
  usePersistentSizeStore,
1613
1680
  useTabCloseInteractions
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forgeax/app-shell",
3
- "version": "0.45.0",
3
+ "version": "0.46.0",
4
4
  "description": "Generic Dock, Panel, Window, and Slot composition primitives",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",