@ai-matrx/associations 0.2.0 → 0.3.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/CHANGELOG.md +95 -0
- package/README.md +35 -5
- package/dist/core/index.cjs +3 -1
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +13 -0
- package/dist/core/index.d.ts +13 -0
- package/dist/core/index.js +3 -1
- package/dist/core/index.js.map +1 -1
- package/dist/react/index.cjs +3158 -0
- package/dist/react/index.cjs.map +1 -0
- package/dist/react/index.d.cts +1758 -0
- package/dist/react/index.d.ts +1758 -0
- package/dist/react/index.js +3142 -0
- package/dist/react/index.js.map +1 -0
- package/package.json +24 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,100 @@
|
|
|
1
1
|
# Changelog — @ai-matrx/associations
|
|
2
2
|
|
|
3
|
+
## 0.3.0 — 2026-08-29 (unreleased; W3 + W4 of the extraction)
|
|
4
|
+
|
|
5
|
+
Waves 3 and 4: the `/react` subpath — the seven hooks riding the /core store
|
|
6
|
+
via `useSyncExternalStore`, and the faces/pickers/capture toolbar. Behavior
|
|
7
|
+
ported VERBATIM from the matrx-frontend originals (re-read in full
|
|
8
|
+
2026-08-29); only the measured seams inverted onto the W1 ports. `/react` is
|
|
9
|
+
the package's ONE banner group: its dist chunks carry `"use client"` (tsup
|
|
10
|
+
banner + `scripts/stamp-client-boundary.mjs` belt); the root and `/core`
|
|
11
|
+
stay pure, and `verify-tarball` now proves both directions.
|
|
12
|
+
|
|
13
|
+
- **`AssociationsProvider` (`src/react/context.tsx`)** — the one React
|
|
14
|
+
binding point: the host constructs the /core store in its binding module
|
|
15
|
+
and mounts the provider with the five UI ports (notifier / windowShell /
|
|
16
|
+
capture / pickerOverrides / entityDoors). Every hook/face reaches the
|
|
17
|
+
store via `useAssociationsStore()`, which THROWS with a precise message
|
|
18
|
+
when no provider is mounted. `useNotifier()` implements the notifier
|
|
19
|
+
degradation: absent → warn ONCE via errorSink, every user-facing failure
|
|
20
|
+
still screams to the sink.
|
|
21
|
+
- **W3 hooks, signatures byte-compatible with the originals** (the W5 swap
|
|
22
|
+
is a re-export flip + Redux-fragment deletion, call sites unchanged):
|
|
23
|
+
`useAssociations` (+ `useEntityRelationships` alias + re-exported
|
|
24
|
+
`AssociationWriteResult`), `useContainerLinks` (incl. the viewer-aware
|
|
25
|
+
`conversation_files` branch, generation/stale guards verbatim),
|
|
26
|
+
`useEntityTitles` (labels never exempt the liveness read; one settled
|
|
27
|
+
round proves absence), `useCategories`, `useUniversalEntitySearch`
|
|
28
|
+
(debounce + recents via `ues_list`), `useAssociationCandidates`,
|
|
29
|
+
`useAssociationEntitySelectAdapter` (+ the
|
|
30
|
+
`AssociationEntitySelectAdapter` contract, which now lives with the
|
|
31
|
+
hook). Redux selectors/thunks → `useSyncExternalStore` over the store;
|
|
32
|
+
`@/lib/toast` → notifier; `console.error` → errorSink; the host `Json`
|
|
33
|
+
type → `unknown` (`ContainerLink.metadata`, `attach` metadata).
|
|
34
|
+
`useAssociationCandidates`' Redux `selectUserId` read became a LENIENT
|
|
35
|
+
identity-port read (null when unauthenticated): `ownerId` is a
|
|
36
|
+
candidate-read filter, not an auth gate — write paths keep the loud
|
|
37
|
+
`requireUserId` contract.
|
|
38
|
+
- **W4 faces**: `AssociationCard`, `AssociationCardGrid`, `AssociationList`
|
|
39
|
+
(+ `ContainerResourcesAdapter` + `useContainerLinksAdapter`),
|
|
40
|
+
`AssociationPicker` (+ `AssociationCandidateBody` + the
|
|
41
|
+
create-then-associate footer), `UniversalAssociationPicker`,
|
|
42
|
+
`AttachedItemsSheet`, `AssociationCaptureToolbar`, `AssociationWindow`,
|
|
43
|
+
`PrimaryEntityProvider`/`usePrimaryEntity`, plus the content-role chrome
|
|
44
|
+
(`CONTENT_ROLES`/`getContentRoleMeta` — display metadata is /react's;
|
|
45
|
+
the classification stays /core's) and the door-seam helpers
|
|
46
|
+
(`DoorRef`/`UnresolvedRef`).
|
|
47
|
+
- **Seam inversions (deliberate, per the design's Decision 2 table)**:
|
|
48
|
+
- the hardcoded `token === "file"` → FilePickerWindow branch became the
|
|
49
|
+
`pickerOverrides` port: `AssociationPicker` routes a registered token to
|
|
50
|
+
its override component (same `AssociationPickerProps` contract);
|
|
51
|
+
`UniversalAssociationPicker`'s browse mode opens the override too, so
|
|
52
|
+
"file enumeration only happens through the canonical picker" survives
|
|
53
|
+
the inversion; with no override the generic candidate list serves every
|
|
54
|
+
token (the documented degradation);
|
|
55
|
+
- `WindowPanel` → the `windowShell` port; absent → a package-internal
|
|
56
|
+
fixed centered overlay (non-draggable, same anatomy, page behind stays
|
|
57
|
+
interactive);
|
|
58
|
+
- `EntityRef`/`EntityDoorControls`/access-gate `UnresolvedEntityRef` →
|
|
59
|
+
the `entityDoors` port; absent → title text with the overlay `hrefFor`
|
|
60
|
+
anchor when present, plain text otherwise, and the package's plain
|
|
61
|
+
"Unavailable" chip for unreadable targets;
|
|
62
|
+
- the capture toolbar's `features/files` + `features/data-tables` imports
|
|
63
|
+
→ the `capture` port, PER-HANDLER optional: chips render only when
|
|
64
|
+
their handler exists, zero handlers → no toolbar and no drop zone
|
|
65
|
+
(never dead buttons, never a drop that swallows files). The original's
|
|
66
|
+
"Add document" picker (a host command palette over
|
|
67
|
+
`listAccessibleDocuments`) has no capture handler by design — hosts
|
|
68
|
+
append it via `extraActions`. "New document" collects its name with an
|
|
69
|
+
inline input row (the original's `TextInputDialog` is host chrome) and
|
|
70
|
+
opens the created document through the registry's `hrefFor` overlay
|
|
71
|
+
instead of a hardcoded `/documents/…` route;
|
|
72
|
+
- lucide icons → the package's own inlined SVGs (C19); host shadcn
|
|
73
|
+
`Input`/`Skeleton`/`Button`/`cn` → `@ai-matrx/design-system` (new
|
|
74
|
+
OPTIONAL peer at the `>=0.2.0` floor, per C18 — never vendored twins).
|
|
75
|
+
- **Store additions (additive, /core)**: `AssociationsStore` now exposes
|
|
76
|
+
the bound `errorSink` and `identity` so /react surfaces scream and read
|
|
77
|
+
identity without a second binding.
|
|
78
|
+
- **W4 gaps (deliberately NOT built — design-system 0.2.0 lacks the
|
|
79
|
+
primitives; vendoring twins is banned)**: `AssociationEntitySelect`,
|
|
80
|
+
`CategorySelect`, `CategoryTagPicker`. They need a Command/combobox
|
|
81
|
+
family (cmdk-style CommandInput/List/Item/Group/Empty + CommandDialog),
|
|
82
|
+
a Select, and the CreatablePicker composite. The
|
|
83
|
+
`AssociationEntitySelectAdapter` contract + default adapter hook (the
|
|
84
|
+
Redux-free seam) shipped anyway, so those faces are a pure-chrome build
|
|
85
|
+
once design-system grows.
|
|
86
|
+
- Tests: 131 (from 97) — jsdom behavioral suites per hook (subscription
|
|
87
|
+
updates, in-flight dedup across two consumers, error surfaces,
|
|
88
|
+
create-then-attach retry + loud outcome) and per face (render +
|
|
89
|
+
interaction against fake ports, every degradation branch: no windowShell,
|
|
90
|
+
no entityDoors, picker override routing, zero capture handlers,
|
|
91
|
+
created-but-unlinked screams).
|
|
92
|
+
- Gate: `pnpm typecheck && pnpm test && pnpm check:package` green; the
|
|
93
|
+
tarball canary installs react + react-dom + `@ai-matrx/design-system`
|
|
94
|
+
(npm, 0.2.0) into the empty project and imports AND requires `/react`,
|
|
95
|
+
proves the `"use client"` banner on both /react chunks and its absence
|
|
96
|
+
on all four pure chunks.
|
|
97
|
+
|
|
3
98
|
## 0.2.0 — 2026-08-29 (unreleased; W2 of the extraction)
|
|
4
99
|
|
|
5
100
|
Wave 2: the headless owns-persistence `/core` subpath — the service
|
package/README.md
CHANGED
|
@@ -4,11 +4,12 @@ THE one way to relate two entities on the AI Matrx platform: association edges,
|
|
|
4
4
|
categories, favorites/recents, and the generated entity-type vocabulary — shipped
|
|
5
5
|
as one package a Matrx client or enterprise app installs.
|
|
6
6
|
|
|
7
|
-
**v0.
|
|
8
|
-
chokepoint, guards, the never-throw result funnel,
|
|
9
|
-
|
|
10
|
-
list, pickers,
|
|
11
|
-
about the schema is binding — it is the package's
|
|
7
|
+
**v0.3 ships the types root, the headless `/core`, and the React binding
|
|
8
|
+
`/react`** — the service chokepoint, guards, the never-throw result funnel,
|
|
9
|
+
the registry merge engine, the subscribable cache store, the seven hooks, and
|
|
10
|
+
the association faces (cards, list, pickers, attached-items sheet, capture
|
|
11
|
+
toolbar). Everything below about the schema is binding — it is the package's
|
|
12
|
+
product.
|
|
12
13
|
|
|
13
14
|
```ts
|
|
14
15
|
import {
|
|
@@ -46,6 +47,35 @@ await store.favorites.setFavorite("note", noteId, true);
|
|
|
46
47
|
await assertDemandedSchema(supabase, { selfTest: true });
|
|
47
48
|
```
|
|
48
49
|
|
|
50
|
+
```tsx
|
|
51
|
+
// /react — the banner'd React binding (peer: react >=18 and
|
|
52
|
+
// @ai-matrx/design-system >=0.2.0 for the faces' chrome). Bind ONCE:
|
|
53
|
+
import {
|
|
54
|
+
AssociationsProvider,
|
|
55
|
+
useAssociations, // the seven hooks keep the app originals' exact signatures
|
|
56
|
+
AssociationCardGrid, // + AssociationCard / AssociationList / pickers / capture toolbar
|
|
57
|
+
PrimaryEntityProvider,
|
|
58
|
+
} from "@ai-matrx/associations/react";
|
|
59
|
+
|
|
60
|
+
<AssociationsProvider
|
|
61
|
+
store={store} // the /core store from createAssociationsStore
|
|
62
|
+
notifier={toastAdapter} // optional — absent warns once, failures still hit errorSink
|
|
63
|
+
windowShell={windowAdapter} // optional — absent falls back to a fixed overlay
|
|
64
|
+
capture={captureHandlers} // optional, per-handler — chips render only when bound
|
|
65
|
+
pickerOverrides={{ file: FilePickerWindowAdapter }} // optional per-token pickers
|
|
66
|
+
entityDoors={{ EntityRef, DoorControls, UnresolvedRef }} // optional doors
|
|
67
|
+
>
|
|
68
|
+
<PrimaryEntityProvider value={{ type: "organization", id, orgId, label }}>
|
|
69
|
+
<AssociationCardGrid />
|
|
70
|
+
</PrimaryEntityProvider>
|
|
71
|
+
</AssociationsProvider>;
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The faces style with Tailwind semantic tokens (`bg-card`,
|
|
75
|
+
`text-muted-foreground`, …): register this package as a Tailwind v4 source in
|
|
76
|
+
the consuming app (`@source "../node_modules/@ai-matrx/associations/dist"`)
|
|
77
|
+
the same way `@ai-matrx/design-system` documents.
|
|
78
|
+
|
|
49
79
|
## The demanded schema — read this first
|
|
50
80
|
|
|
51
81
|
This package is **opinionated like the Python `matrx-*` packages**: it does not
|
package/dist/core/index.cjs
CHANGED
|
@@ -3019,7 +3019,9 @@ function createAssociationsStore(config) {
|
|
|
3019
3019
|
helpers,
|
|
3020
3020
|
registry,
|
|
3021
3021
|
services: { associations, categories },
|
|
3022
|
-
registerEntityOverlay: registry.registerEntityOverlay
|
|
3022
|
+
registerEntityOverlay: registry.registerEntityOverlay,
|
|
3023
|
+
errorSink,
|
|
3024
|
+
identity: config.identity
|
|
3023
3025
|
};
|
|
3024
3026
|
}
|
|
3025
3027
|
|