@ai-matrx/detail 0.1.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.
@@ -0,0 +1,191 @@
1
+ import { D as DetailRef, a as DetailInstanceData, b as DetailPresentation, c as DetailRecordType, d as DetailStatus, e as DetailRow, f as DetailField, g as DetailSourceHealth, h as DetailFrameContext, i as DetailListContext, j as DetailLoadState, k as DetailOpenRequest } from './host-eKqulRpB.cjs';
2
+ export { l as DetailDockedShellProps, m as DetailEffectivePresentation, n as DetailHostPorts, o as DetailHostProvider, p as DetailPageShellProps, q as DetailPresentationSetting, r as DetailShellSlots, s as DetailShells, t as DetailWindowShellProps, u as requireResolveType, v as requireShell, w as useDetailHost } from './host-eKqulRpB.cjs';
3
+ import * as react from 'react';
4
+ import { KeyboardEvent } from 'react';
5
+
6
+ interface DetailKeyboardHandlers {
7
+ onClose?: (() => void) | null;
8
+ onPrev?: (() => void) | null;
9
+ onNext?: (() => void) | null;
10
+ /**
11
+ * 🚨 NEW-22 (VERIFY-U-P1-R4) — CMD+ENTER NEVER VANISHES. The chord is one of
12
+ * the three bindings the primitive promises, and nothing is registered to save
13
+ * unless a section with an editor is open, so the keystroke was swallowed in
14
+ * silence on every read-only record. A deliberate keystroke gets an answer.
15
+ */
16
+ onSaveUnavailable?: (() => void) | null;
17
+ }
18
+ interface DetailKeyboard {
19
+ /** Spread onto the presentation root. */
20
+ rootProps: {
21
+ tabIndex: -1;
22
+ onKeyDownCapture: (event: KeyboardEvent<HTMLElement>) => void;
23
+ };
24
+ /** A section with an editor registers its save; returns the unregister. */
25
+ registerSave: (save: () => void | Promise<void>) => () => void;
26
+ /** Whether anything is registered — the switcher shows the hint only then. */
27
+ hasSave: () => boolean;
28
+ }
29
+ declare function useDetailKeyboard(handlers: DetailKeyboardHandlers): DetailKeyboard;
30
+
31
+ interface DetailCore {
32
+ ref: DetailRef;
33
+ data: DetailInstanceData;
34
+ presentation: DetailPresentation;
35
+ /** `null` when the host has no registration for this type — the body says so. */
36
+ recordType: DetailRecordType | null;
37
+ status: DetailStatus;
38
+ /** Set when `status === "error"`. */
39
+ errorMessage: string | null;
40
+ row: DetailRow | null;
41
+ title: string;
42
+ /** The title is a stand-in (loading / not found / failed), not a record's name. */
43
+ titleIsStandIn: boolean;
44
+ /**
45
+ * 🚨 NEW-9 — WHETHER THE RECORD'S OWN DOORS MAY SHOW. A question about the
46
+ * RECORD, not about its name: a record that exists but stores nothing more
47
+ * here still opens in its home, and a title that could not be loaded has no
48
+ * record behind it to open. The header hung the doors off `titleIsStandIn`,
49
+ * which is why a type with no source became a named dead end.
50
+ */
51
+ doorsAvailable: boolean;
52
+ /**
53
+ * 🚨 NEW-17 — WHETHER A CONTROL THAT OPENS THIS RECORD SOMEWHERE ELSE IS
54
+ * ACTUALLY ON THE SCREEN (the token resolves to a route or a peek). The body's
55
+ * absent-state sentence is derived from this; it used to promise a door for
56
+ * every type, including the ones whose header shows none.
57
+ */
58
+ canOpenElsewhere: boolean;
59
+ /**
60
+ * Human label for the record TYPE ("File") — for a statement about the type,
61
+ * such as the presentation setting's "Every file record now opens as a window".
62
+ */
63
+ typeLabel: string;
64
+ /**
65
+ * What THIS ROW is ("Company" for a `crm.party` row whose `party_kind` is
66
+ * `organization`, where `typeLabel` says "Person"). The header's type chip and
67
+ * the stand-in titles use this; `typeLabel` when the registration cannot tell
68
+ * the difference. See `DetailRecordType.labelForRow`.
69
+ */
70
+ recordLabel: string;
71
+ about: string | null;
72
+ fields: DetailField[];
73
+ /**
74
+ * The source health strip's content — `null` for a record the platform owns
75
+ * outright, or while a producer that reads it from the host is still
76
+ * answering. See `useDetailHealth`.
77
+ */
78
+ health: DetailSourceHealth | null;
79
+ /** The entity token doors / associations / history key off; null = none. */
80
+ entityToken: string | null;
81
+ frameCtx: DetailFrameContext | null;
82
+ keyboard: DetailKeyboard;
83
+ list: {
84
+ context: DetailListContext | null;
85
+ hasPrev: boolean;
86
+ hasNext: boolean;
87
+ prev: () => void;
88
+ next: () => void;
89
+ };
90
+ /** Re-open this record in another presentation and leave the current one. */
91
+ switchTo: (presentation: DetailPresentation) => void;
92
+ /**
93
+ * 🚨 D1 — THE ONE EXIT FROM THE PAGE PRESENTATION. Back chevron, Escape and
94
+ * a switch that leaves the route all come here; no host, route or shell may
95
+ * call `back()` itself.
96
+ */
97
+ leave: () => void;
98
+ close: () => void;
99
+ }
100
+ declare function useDetailCore(data: DetailInstanceData, presentation: DetailPresentation,
101
+ /**
102
+ * `onClose` is how an IN-PLACE presentation is dismissed (the overlay's
103
+ * close). The page presentation needs none: it is left through `leave`,
104
+ * which is the guarded exit — see `close` below.
105
+ */
106
+ options: {
107
+ onClose?: () => void;
108
+ }): DetailCore;
109
+
110
+ declare function useDetailRecord(recordType: DetailRecordType | null, id: string | null): DetailLoadState<DetailRow>;
111
+
112
+ interface UseDetailHealthArgs {
113
+ recordType: DetailRecordType | null;
114
+ /** The loaded row — health is only ever produced for a record that loaded. */
115
+ row: DetailRow | null;
116
+ ref: DetailRef;
117
+ /** The host's reconnect action for this record's source, when it has one. */
118
+ reconnect: ((ref: DetailRef, source: string) => void) | null;
119
+ }
120
+ /**
121
+ * The strip's Reconnect for a producer's answer: the producer's own action, its
122
+ * explicit refusal (`null`), or — only when it said nothing — the host's.
123
+ *
124
+ * 🚨 AND `grant: "blocked"` NEVER GETS ONE (chair, 2026-09-18). The word means
125
+ * the source refuses and nothing the person can click repairs it, so the refusal
126
+ * is structural here rather than a promise each producer must remember to keep:
127
+ * a host that binds `reconnectSource` cannot put the button back, and neither
128
+ * can a producer that supplies an action by mistake.
129
+ */
130
+ declare function reconnectFor(value: DetailSourceHealth, hostReconnect: ((source: string) => void) | null): (() => void) | null;
131
+ declare function useDetailHealth({ recordType, row, ref, reconnect, }: UseDetailHealthArgs): DetailSourceHealth | null;
132
+
133
+ type OpenDetail = (request: DetailOpenRequest) => Promise<DetailPresentation>;
134
+ /**
135
+ * @param warmType a record type this surface will open — its setting is
136
+ * resolved on mount so the click is synchronous.
137
+ */
138
+ declare function useOpenDetail(warmType?: string | null): OpenDetail;
139
+
140
+ declare function DetailTitle({ core }: {
141
+ core: DetailCore;
142
+ }): react.JSX.Element;
143
+ /**
144
+ * The type, the id and the record's doors, in the BODY — where the header
145
+ * hands them off below `sm`, and where the id lives at every width now that
146
+ * the header cluster is icons only.
147
+ */
148
+ declare function DetailRecordMeta({ core }: {
149
+ core: DetailCore;
150
+ }): react.JSX.Element;
151
+ declare function DetailActions({ core }: {
152
+ core: DetailCore;
153
+ }): react.JSX.Element;
154
+
155
+ declare function DetailBody({ core }: {
156
+ core: DetailCore;
157
+ }): react.JSX.Element;
158
+
159
+ declare function DetailPresentationPane({ core }: {
160
+ core: DetailCore;
161
+ }): react.JSX.Element | null;
162
+
163
+ interface DetailPresentationProps {
164
+ data: DetailInstanceData;
165
+ onClose: () => void;
166
+ }
167
+ declare function DetailWindowPresentation({ data, onClose }: DetailPresentationProps): react.JSX.Element;
168
+ declare function DetailDockedPresentation({ data, onClose }: DetailPresentationProps): react.JSX.Element;
169
+ /**
170
+ * 🚨 D1 — THE PAGE OWNS ITS OWN EXIT. It accepts no `onBack` FROM ITS CALLER: the
171
+ * route passes none, and this component is what fills the shell's `onBack` slot,
172
+ * with `core.leave` — so the back chevron, Escape and a presentation switch all
173
+ * leave through the one guarded exit (`canGoBack` → `back()`, otherwise the
174
+ * record's own home). A route that passed its own `router.back()` in here is
175
+ * exactly how a pasted or bookmarked detail link still landed the tab on
176
+ * `about:blank` after round 1's fix (VERIFY-U-P1-R2, D1). N9 (VERIFY-U-P1-R5):
177
+ * this sentence used to read "It takes no `onBack`" directly above the line that
178
+ * passes one, which is the sentence a future agent trusts.
179
+ */
180
+ declare function DetailPagePresentation({ data }: {
181
+ data: DetailInstanceData;
182
+ }): react.JSX.Element;
183
+
184
+ /** The container the detail header's breakpoint reads — declared by the window chrome. */
185
+ declare const DETAIL_HEADER_CONTAINER = "@container/window-header";
186
+ /** Below this container width the optional actions move into the overflow menu. */
187
+ declare const DETAIL_HEADER_COMPACT_BELOW = "@max-[26rem]/window-header";
188
+ /** The floor under the record's name: ~96px, enough for a readable fragment. */
189
+ declare const DETAIL_TITLE_MIN_WIDTH_CLASS = "min-w-[6rem]";
190
+
191
+ export { DETAIL_HEADER_COMPACT_BELOW, DETAIL_HEADER_CONTAINER, DETAIL_TITLE_MIN_WIDTH_CLASS, DetailActions, DetailBody, type DetailCore, DetailDockedPresentation, type DetailKeyboard, type DetailKeyboardHandlers, DetailPagePresentation, DetailPresentationPane, type DetailPresentationProps, DetailRecordMeta, DetailTitle, DetailWindowPresentation, type OpenDetail, type UseDetailHealthArgs, reconnectFor, useDetailCore, useDetailHealth, useDetailKeyboard, useDetailRecord, useOpenDetail };
@@ -0,0 +1,191 @@
1
+ import { D as DetailRef, a as DetailInstanceData, b as DetailPresentation, c as DetailRecordType, d as DetailStatus, e as DetailRow, f as DetailField, g as DetailSourceHealth, h as DetailFrameContext, i as DetailListContext, j as DetailLoadState, k as DetailOpenRequest } from './host-eKqulRpB.js';
2
+ export { l as DetailDockedShellProps, m as DetailEffectivePresentation, n as DetailHostPorts, o as DetailHostProvider, p as DetailPageShellProps, q as DetailPresentationSetting, r as DetailShellSlots, s as DetailShells, t as DetailWindowShellProps, u as requireResolveType, v as requireShell, w as useDetailHost } from './host-eKqulRpB.js';
3
+ import * as react from 'react';
4
+ import { KeyboardEvent } from 'react';
5
+
6
+ interface DetailKeyboardHandlers {
7
+ onClose?: (() => void) | null;
8
+ onPrev?: (() => void) | null;
9
+ onNext?: (() => void) | null;
10
+ /**
11
+ * 🚨 NEW-22 (VERIFY-U-P1-R4) — CMD+ENTER NEVER VANISHES. The chord is one of
12
+ * the three bindings the primitive promises, and nothing is registered to save
13
+ * unless a section with an editor is open, so the keystroke was swallowed in
14
+ * silence on every read-only record. A deliberate keystroke gets an answer.
15
+ */
16
+ onSaveUnavailable?: (() => void) | null;
17
+ }
18
+ interface DetailKeyboard {
19
+ /** Spread onto the presentation root. */
20
+ rootProps: {
21
+ tabIndex: -1;
22
+ onKeyDownCapture: (event: KeyboardEvent<HTMLElement>) => void;
23
+ };
24
+ /** A section with an editor registers its save; returns the unregister. */
25
+ registerSave: (save: () => void | Promise<void>) => () => void;
26
+ /** Whether anything is registered — the switcher shows the hint only then. */
27
+ hasSave: () => boolean;
28
+ }
29
+ declare function useDetailKeyboard(handlers: DetailKeyboardHandlers): DetailKeyboard;
30
+
31
+ interface DetailCore {
32
+ ref: DetailRef;
33
+ data: DetailInstanceData;
34
+ presentation: DetailPresentation;
35
+ /** `null` when the host has no registration for this type — the body says so. */
36
+ recordType: DetailRecordType | null;
37
+ status: DetailStatus;
38
+ /** Set when `status === "error"`. */
39
+ errorMessage: string | null;
40
+ row: DetailRow | null;
41
+ title: string;
42
+ /** The title is a stand-in (loading / not found / failed), not a record's name. */
43
+ titleIsStandIn: boolean;
44
+ /**
45
+ * 🚨 NEW-9 — WHETHER THE RECORD'S OWN DOORS MAY SHOW. A question about the
46
+ * RECORD, not about its name: a record that exists but stores nothing more
47
+ * here still opens in its home, and a title that could not be loaded has no
48
+ * record behind it to open. The header hung the doors off `titleIsStandIn`,
49
+ * which is why a type with no source became a named dead end.
50
+ */
51
+ doorsAvailable: boolean;
52
+ /**
53
+ * 🚨 NEW-17 — WHETHER A CONTROL THAT OPENS THIS RECORD SOMEWHERE ELSE IS
54
+ * ACTUALLY ON THE SCREEN (the token resolves to a route or a peek). The body's
55
+ * absent-state sentence is derived from this; it used to promise a door for
56
+ * every type, including the ones whose header shows none.
57
+ */
58
+ canOpenElsewhere: boolean;
59
+ /**
60
+ * Human label for the record TYPE ("File") — for a statement about the type,
61
+ * such as the presentation setting's "Every file record now opens as a window".
62
+ */
63
+ typeLabel: string;
64
+ /**
65
+ * What THIS ROW is ("Company" for a `crm.party` row whose `party_kind` is
66
+ * `organization`, where `typeLabel` says "Person"). The header's type chip and
67
+ * the stand-in titles use this; `typeLabel` when the registration cannot tell
68
+ * the difference. See `DetailRecordType.labelForRow`.
69
+ */
70
+ recordLabel: string;
71
+ about: string | null;
72
+ fields: DetailField[];
73
+ /**
74
+ * The source health strip's content — `null` for a record the platform owns
75
+ * outright, or while a producer that reads it from the host is still
76
+ * answering. See `useDetailHealth`.
77
+ */
78
+ health: DetailSourceHealth | null;
79
+ /** The entity token doors / associations / history key off; null = none. */
80
+ entityToken: string | null;
81
+ frameCtx: DetailFrameContext | null;
82
+ keyboard: DetailKeyboard;
83
+ list: {
84
+ context: DetailListContext | null;
85
+ hasPrev: boolean;
86
+ hasNext: boolean;
87
+ prev: () => void;
88
+ next: () => void;
89
+ };
90
+ /** Re-open this record in another presentation and leave the current one. */
91
+ switchTo: (presentation: DetailPresentation) => void;
92
+ /**
93
+ * 🚨 D1 — THE ONE EXIT FROM THE PAGE PRESENTATION. Back chevron, Escape and
94
+ * a switch that leaves the route all come here; no host, route or shell may
95
+ * call `back()` itself.
96
+ */
97
+ leave: () => void;
98
+ close: () => void;
99
+ }
100
+ declare function useDetailCore(data: DetailInstanceData, presentation: DetailPresentation,
101
+ /**
102
+ * `onClose` is how an IN-PLACE presentation is dismissed (the overlay's
103
+ * close). The page presentation needs none: it is left through `leave`,
104
+ * which is the guarded exit — see `close` below.
105
+ */
106
+ options: {
107
+ onClose?: () => void;
108
+ }): DetailCore;
109
+
110
+ declare function useDetailRecord(recordType: DetailRecordType | null, id: string | null): DetailLoadState<DetailRow>;
111
+
112
+ interface UseDetailHealthArgs {
113
+ recordType: DetailRecordType | null;
114
+ /** The loaded row — health is only ever produced for a record that loaded. */
115
+ row: DetailRow | null;
116
+ ref: DetailRef;
117
+ /** The host's reconnect action for this record's source, when it has one. */
118
+ reconnect: ((ref: DetailRef, source: string) => void) | null;
119
+ }
120
+ /**
121
+ * The strip's Reconnect for a producer's answer: the producer's own action, its
122
+ * explicit refusal (`null`), or — only when it said nothing — the host's.
123
+ *
124
+ * 🚨 AND `grant: "blocked"` NEVER GETS ONE (chair, 2026-09-18). The word means
125
+ * the source refuses and nothing the person can click repairs it, so the refusal
126
+ * is structural here rather than a promise each producer must remember to keep:
127
+ * a host that binds `reconnectSource` cannot put the button back, and neither
128
+ * can a producer that supplies an action by mistake.
129
+ */
130
+ declare function reconnectFor(value: DetailSourceHealth, hostReconnect: ((source: string) => void) | null): (() => void) | null;
131
+ declare function useDetailHealth({ recordType, row, ref, reconnect, }: UseDetailHealthArgs): DetailSourceHealth | null;
132
+
133
+ type OpenDetail = (request: DetailOpenRequest) => Promise<DetailPresentation>;
134
+ /**
135
+ * @param warmType a record type this surface will open — its setting is
136
+ * resolved on mount so the click is synchronous.
137
+ */
138
+ declare function useOpenDetail(warmType?: string | null): OpenDetail;
139
+
140
+ declare function DetailTitle({ core }: {
141
+ core: DetailCore;
142
+ }): react.JSX.Element;
143
+ /**
144
+ * The type, the id and the record's doors, in the BODY — where the header
145
+ * hands them off below `sm`, and where the id lives at every width now that
146
+ * the header cluster is icons only.
147
+ */
148
+ declare function DetailRecordMeta({ core }: {
149
+ core: DetailCore;
150
+ }): react.JSX.Element;
151
+ declare function DetailActions({ core }: {
152
+ core: DetailCore;
153
+ }): react.JSX.Element;
154
+
155
+ declare function DetailBody({ core }: {
156
+ core: DetailCore;
157
+ }): react.JSX.Element;
158
+
159
+ declare function DetailPresentationPane({ core }: {
160
+ core: DetailCore;
161
+ }): react.JSX.Element | null;
162
+
163
+ interface DetailPresentationProps {
164
+ data: DetailInstanceData;
165
+ onClose: () => void;
166
+ }
167
+ declare function DetailWindowPresentation({ data, onClose }: DetailPresentationProps): react.JSX.Element;
168
+ declare function DetailDockedPresentation({ data, onClose }: DetailPresentationProps): react.JSX.Element;
169
+ /**
170
+ * 🚨 D1 — THE PAGE OWNS ITS OWN EXIT. It accepts no `onBack` FROM ITS CALLER: the
171
+ * route passes none, and this component is what fills the shell's `onBack` slot,
172
+ * with `core.leave` — so the back chevron, Escape and a presentation switch all
173
+ * leave through the one guarded exit (`canGoBack` → `back()`, otherwise the
174
+ * record's own home). A route that passed its own `router.back()` in here is
175
+ * exactly how a pasted or bookmarked detail link still landed the tab on
176
+ * `about:blank` after round 1's fix (VERIFY-U-P1-R2, D1). N9 (VERIFY-U-P1-R5):
177
+ * this sentence used to read "It takes no `onBack`" directly above the line that
178
+ * passes one, which is the sentence a future agent trusts.
179
+ */
180
+ declare function DetailPagePresentation({ data }: {
181
+ data: DetailInstanceData;
182
+ }): react.JSX.Element;
183
+
184
+ /** The container the detail header's breakpoint reads — declared by the window chrome. */
185
+ declare const DETAIL_HEADER_CONTAINER = "@container/window-header";
186
+ /** Below this container width the optional actions move into the overflow menu. */
187
+ declare const DETAIL_HEADER_COMPACT_BELOW = "@max-[26rem]/window-header";
188
+ /** The floor under the record's name: ~96px, enough for a readable fragment. */
189
+ declare const DETAIL_TITLE_MIN_WIDTH_CLASS = "min-w-[6rem]";
190
+
191
+ export { DETAIL_HEADER_COMPACT_BELOW, DETAIL_HEADER_CONTAINER, DETAIL_TITLE_MIN_WIDTH_CLASS, DetailActions, DetailBody, type DetailCore, DetailDockedPresentation, type DetailKeyboard, type DetailKeyboardHandlers, DetailPagePresentation, DetailPresentationPane, type DetailPresentationProps, DetailRecordMeta, DetailTitle, DetailWindowPresentation, type OpenDetail, type UseDetailHealthArgs, reconnectFor, useDetailCore, useDetailHealth, useDetailKeyboard, useDetailRecord, useOpenDetail };