@ai-matrx/summon 0.1.4 → 0.1.6

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/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.6
4
+
5
+ UNVERIFIED: this release has no Unreleased entry and the source comparison could not be made (the caller supplied no source comparison). Whether source changed is unknown; consumer action is unknown.
6
+ Check the package's gitHead on npm against this version's gitHead: `git diff <previous gitHead> <this gitHead> -- apps/shared/summon/src`.
7
+
8
+ ## 0.1.5
9
+ ### Unreleased
10
+
11
+ - **Light imports for the boot graph.** `usePopout`, `PopoutContext`, `usePopoutContainer` and `useOverlaySurfaceRenderAck` are now on `./window-host` (the popout context lives there, one identity; `./window` re-exports them), and `useOverlayLink` is on `./react` (`./url` re-exports it). Why: a section ships as one module, so an app that imported one of these hooks from `./window` or `./url` at boot carried the whole window section (WindowPanel, popout, mobile, tray: ~100 KB minified) or the link manager in every route's first load (AI Matrx: `/pricing`, `/notes`, `/dashboard`). Consumer action: none required; import these hooks from `./window-host` / `./react` to drop the heavy sections from a static graph.
12
+ - **New: `./dock`, the one primitive for floating chrome-less cards, pills and docks** (design R5 wave 2). `<Dock>` / `<DockHandle>` / `useDock()` / `useDockContext()` / `<DockProvider>`: pointer drag that never re-renders while moving (CSS `translate` in one animation frame, one commit on release), corner-relative positions clamped to the viewport with an optional nearest-corner snap and fixed-control avoidance, the position remembered per dock id (own store, `DockProvider`, else localStorage) or reported to a controlled host, the window manager's z-order lane on press, the design-system drag cursor hold, a click-vs-drag threshold that swallows the trailing click. Replaces the copies in AI Matrx (`useDraggableFloat`, the assists `useDockDrag`) and in `@ai-matrx/chat` (`useDraggablePanel`, the agent widget drags). Guard: `src/dock/__tests__/dock.test.tsx`. Consumer action: none.
13
+ - **Idle cost: the root-mounted pieces do nothing until used.** `WindowTraySync` no longer dispatches two actions on mount and on every resize of a page with no windows: it attaches its resize listener only while a window is registered or waiting to restore (one boolean selector), and `recomputeTrayPositions` writes nothing when the tray is empty (a resize with no tray hands subscribers the same state). Persistence boot is one read: a port may implement `loadAll()` (key → stored value), and when it does the controller restores the workspace and every saved component state from that single call instead of `load` + `list` + one `load` per state key; the `./persistence/data` adapter implements it (one `users.user_surface_state` select). Guards: `src/window/__tests__/windowTraySyncIdle.test.tsx`, `controller.test.ts` (boot = exactly `["loadAll"]`), `src/importCost.test.ts` (the root-mounted entries `.`, `./react`, `./window-host`, `./next` never reach WindowPanel, links, persistence, dialog/sheet/lite or testing). Consumer action: none.
14
+ - **New: the render map can live on the host.** `render` is now optional on `defineOverlay`, and `<SummonHost renders={…}>` takes an id → `() => import("./<id>.render")` map (`OverlayRenderMap`, data type erased, no `any`) for definitions declared without one. A definition's own `render` still wins. Why: every file that imports a definition to open it also inherited an `import()` edge to that overlay's window subtree; with ~220 overlays and ~450 opener files in AI Matrx that multiplied the build graph (a sub-app build went from ~10 s to an out-of-memory kill). An opened overlay with no render source shows its error card (`OverlayRenderMissingError`, `MISSING_RENDER_ERROR`) and logs in development. Guard: `src/react/__tests__/hostRenders.test.tsx`. Consumer action: none for existing users.
15
+
3
16
  ## 0.1.4
4
17
  ### Unreleased
5
18
 
package/README.md CHANGED
@@ -25,7 +25,7 @@ pnpm add @ai-matrx/summon react react-dom react-redux @reduxjs/toolkit
25
25
  | `html-to-image` (optional) | tray thumbnails of minimized windows (without it the tile shows no preview) |
26
26
  | `@supabase/supabase-js` | only `./persistence/data`, through `@ai-matrx/data` |
27
27
 
28
- Entries: `.` (core, no React), `./handles` (no React, no Redux), `./react`, `./window`, `./window-host` (the root-mountable half of the window section: `WindowsProvider`, `WindowTraySync`, `registerTrayPreview` — never loads WindowPanel), `./dialog`, `./sheet`, `./lite`, `./dock`, `./url`, `./persistence`, `./persistence/data`, `./next`, `./testing`, `./styles.css`.
28
+ Entries: `.` (core, no React), `./handles` (no React, no Redux), `./react`, `./window`, `./window-host` (the root-mountable half of the window section: `WindowsProvider`, `WindowTraySync`, `registerTrayPreview`, and the in-window hooks `usePopout`, `usePopoutContainer`, `useOverlaySurfaceRenderAck` — never loads WindowPanel), `./dialog`, `./sheet`, `./lite`, `./dock`, `./url`, `./persistence`, `./persistence/data`, `./next`, `./testing`, `./styles.css`.
29
29
 
30
30
  ## Quick start
31
31
 
@@ -239,7 +239,7 @@ defineOverlay<NotesWindowData>()({
239
239
  ```
240
240
 
241
241
  - Opening `/page?panels=notes:42` runs `hydrate({ id: "42", args, open, dispatch })`. `hydrate` may be async (load a record, then `open`).
242
- - A mounted overlay publishes its own address with `useOverlayLink("notes", noteId, { tab: "history" })`. `WindowPanel` does it for you from its `urlSyncKey`, `urlSyncId` and `urlSyncArgs` props.
242
+ - A mounted overlay publishes its own address with `useOverlayLink("notes", noteId, { tab: "history" })` (also exported from `./react`, so a render module can publish without loading the link section). `WindowPanel` does it for you from its `urlSyncKey`, `urlSyncId` and `urlSyncArgs` props.
243
243
  - Unknown keys are announced at once; tokens whose overlay never registers are announced at a deadline and kept verbatim.
244
244
  - **Grammar v2**: `panels = token ("," token)*`, `token = key[:id[:k-v(_k-v)*]]`. Ids are percent-encoded for `% , :`, arg keys and values for `% , : _ -`, so any value survives; v1 links still parse. Helpers: `parseLinkToken`, `parseLinkParam`, `formatLinkToken`, `readPanelsParam`, `withPanelsParam`.
245
245
  - **One door**: `openFromLink(searchOrUrl, { dispatch, requireAll?, onError? })` returns `{ opened, refused, unknown, failed }` and serves the address bar, notifications and any bridge. `requireAll: true` opens nothing if any key is unknown. `openPanelRequest(payload, { dispatch })` validates and opens a `{ panelId, instanceId?, data? }` request from a bridge (returns `{ ok: true, … }` or `{ ok: false, error: "invalid_payload" | "unknown_panel" }`).
@@ -382,9 +382,10 @@ import { Dock, DockHandle, DockProvider, useDock, useDockContext } from "@ai-mat
382
382
  …
383
383
  </Dock>
384
384
 
385
- // Your own markup: spread the bindings.
386
- const dock = useDock({ id: "assists", corner: "bottom-right", position, onPositionChange: save, touch: false, clamp: { margin: 0, minVisible: { width: 120, height: 32 } } });
387
- <div ref={dock.ref} style={dock.style}><button {...dock.handleProps}>pill</button></div>
385
+ // Your own markup: spread the bindings. Destructure them: the React compiler treats an object
386
+ // carrying a `ref` as a ref, so reading `dock.style` during render counts as a ref access.
387
+ const { ref, style, handleProps } = useDock({ id: "assists", corner: "bottom-right", position, onPositionChange: save, touch: false, clamp: { margin: 0, minVisible: { width: 120, height: 32 } } });
388
+ <div ref={ref} style={style}><button {...handleProps}>pill</button></div>
388
389
 
389
390
  // Hand every dock the host's storage (declared keys, per-user sync).
390
391
  <DockProvider store={{ read: (id) => …, write: (id, position) => … }}>…</DockProvider>
package/dist/index.cjs CHANGED
@@ -1319,11 +1319,14 @@ var windowManagerSlice = (0, import_toolkit2.createSlice)({
1319
1319
  if (!Number.isFinite(viewportWidth) || !Number.isFinite(viewportHeight) || viewportWidth <= 0 || viewportHeight <= 0) {
1320
1320
  return;
1321
1321
  }
1322
- state2.trayViewport = { width: viewportWidth, height: viewportHeight };
1323
1322
  const minimized = Object.values(state2.windows).filter(
1324
1323
  (w) => w.state === "minimized" && w.traySlot !== null
1325
1324
  );
1326
1325
  if (minimized.length === 0) return;
1326
+ const tv = state2.trayViewport;
1327
+ if (!tv || tv.width !== viewportWidth || tv.height !== viewportHeight) {
1328
+ state2.trayViewport = { width: viewportWidth, height: viewportHeight };
1329
+ }
1327
1330
  recomputeAllTrayRects(state2);
1328
1331
  },
1329
1332
  /**