@ai-matrx/content-ir-react 0.15.2 → 0.16.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 +25 -0
- package/dist/{directive-host-DJfF35FD.d.cts → directive-host-C4TcPpxX.d.cts} +19 -2
- package/dist/{directive-host-DJfF35FD.d.ts → directive-host-C4TcPpxX.d.ts} +19 -2
- package/dist/directives.cjs +143 -28
- package/dist/directives.cjs.map +1 -1
- package/dist/directives.d.cts +76 -41
- package/dist/directives.d.ts +76 -41
- package/dist/directives.js +143 -28
- package/dist/directives.js.map +1 -1
- package/dist/{host-types-9NfBeqrG.d.ts → host-types-CEc86R-v.d.ts} +1 -1
- package/dist/{host-types-DVIaaGR_.d.cts → host-types-a0XEr5b3.d.cts} +1 -1
- package/dist/host.cjs.map +1 -1
- package/dist/host.d.cts +3 -3
- package/dist/host.d.ts +3 -3
- package/dist/host.js.map +1 -1
- package/dist/index.cjs +149 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +76 -42
- package/dist/index.d.ts +76 -42
- package/dist/index.js +146 -31
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +142 -33
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +2 -2
- package/dist/react.d.ts +2 -2
- package/dist/react.js +139 -30
- package/dist/react.js.map +1 -1
- package/dist/{route-DDbgc-ID.d.ts → route-De9c5YgW.d.ts} +19 -2
- package/dist/{route-BCtPhF7W.d.cts → route-YcoyR3Fj.d.cts} +19 -2
- package/dist/route.d.cts +1 -1
- package/dist/route.d.ts +1 -1
- package/package.json +1 -1
package/dist/directives.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import { D as DirectiveRecordRef } from './directive-host-C4TcPpxX.js';
|
|
2
|
+
export { a as DirectiveApplyResult, b as DirectiveApplyState, c as DirectiveAskRequest, d as DirectiveCopyProps, e as DirectiveHost, f as DirectiveHostProvider, g as DirectiveHostProviderProps, h as DirectiveOpenItemOptions, i as DirectiveRecordProps, j as DirectiveScope, k as DirectiveScopeProvider, l as DirectiveShell, u as useDirectiveHost, m as useDirectiveScope } from './directive-host-C4TcPpxX.js';
|
|
2
3
|
import * as react from 'react';
|
|
3
4
|
import { ComponentType } from 'react';
|
|
4
5
|
import { DecodedDirective, DirectiveClass } from '@ai-matrx/content-ir';
|
|
@@ -48,9 +49,75 @@ interface ApplyDirectiveButtonProps {
|
|
|
48
49
|
}
|
|
49
50
|
declare function ApplyDirectiveButton({ directive, label, itemCount, onApplied, }: ApplyDirectiveButtonProps): react.JSX.Element | null;
|
|
50
51
|
|
|
52
|
+
/**
|
|
53
|
+
* WHAT A DIRECTIVE ITEM WILL DO TO AN EXISTING RECORD — for the card, the
|
|
54
|
+
* confirm dialog, and anything else that must say it before the click.
|
|
55
|
+
*
|
|
56
|
+
* WHY (reviewer, 2026-09-30): an Update card and a Delete card showed each item
|
|
57
|
+
* as "Item" — they never named the record they would change, and an Update card
|
|
58
|
+
* never said what it would change. The item-summary helpers name a thing to be
|
|
59
|
+
* CREATED from its own fields; an update or delete item carries the TARGET's id
|
|
60
|
+
* and, for an update, the NEW values — so its "title" field is the new title,
|
|
61
|
+
* not the name of the record being changed. Naming the target is the host's
|
|
62
|
+
* live lookup (`DirectiveHost.renderRecord`); what changes is right here.
|
|
63
|
+
*
|
|
64
|
+
* Law: common-docs/policies/destructive-and-expensive-actions.md — the sentence
|
|
65
|
+
* names what changes.
|
|
66
|
+
*/
|
|
67
|
+
/** Classes whose items point at an EXISTING record by `id`. */
|
|
68
|
+
declare const TARGETING_CLASSES: ReadonlySet<string>;
|
|
69
|
+
/** How long a changed value may read before it is shortened (full value on hover). */
|
|
70
|
+
declare const CHANGE_VALUE_MAX = 60;
|
|
71
|
+
/** The id of the existing record an update/delete item targets, or null. */
|
|
72
|
+
declare function itemRecordId(item: Record<string, unknown>): string | null;
|
|
73
|
+
/** "due_date" → "Due date". Underscores read as developer output. */
|
|
74
|
+
declare function fieldLabel(key: string): string;
|
|
75
|
+
/** A short, honest name for a record we could not look up: "Task 1a2b3c4d". */
|
|
76
|
+
declare function recordFallbackName(nounLabel: string, id: string): string;
|
|
77
|
+
/** One value as a row reads it: shortened, the whole of it, and whether it is empty. */
|
|
78
|
+
interface ChangeValue {
|
|
79
|
+
value: string;
|
|
80
|
+
full: string;
|
|
81
|
+
clears: boolean;
|
|
82
|
+
}
|
|
83
|
+
interface ItemChange extends ChangeValue {
|
|
84
|
+
key: string;
|
|
85
|
+
/** "Due date". */
|
|
86
|
+
label: string;
|
|
87
|
+
/**
|
|
88
|
+
* What the field holds NOW, when the host could read the record — so an
|
|
89
|
+
* update reads "old → new", never just the new value (reviewer, 2026-10-02).
|
|
90
|
+
* Absent when the current record is unknown.
|
|
91
|
+
*/
|
|
92
|
+
before?: ChangeValue;
|
|
93
|
+
/** True when the record already holds exactly this value — nothing changes. */
|
|
94
|
+
same?: boolean;
|
|
95
|
+
}
|
|
96
|
+
/** One value, described for a change row (`value` shortened, `full` whole). */
|
|
97
|
+
declare function describeChangeValue(value: unknown): ChangeValue;
|
|
98
|
+
/**
|
|
99
|
+
* Every field an UPDATE item sets, in the order the item carries them — ALL of
|
|
100
|
+
* them, never a sample: a person approving an overwrite sees the whole of it.
|
|
101
|
+
*
|
|
102
|
+
* Pass `current` — the record as it is now (`DirectiveHost.readRecord`) — and
|
|
103
|
+
* each change also carries what it REPLACES (`before`) and whether it changes
|
|
104
|
+
* anything at all (`same`). A field the record does not carry gets no `before`.
|
|
105
|
+
*/
|
|
106
|
+
declare function itemChanges(item: Record<string, unknown>, current?: Record<string, unknown> | null): ItemChange[];
|
|
107
|
+
|
|
51
108
|
interface SideEffectDirectiveCardProps {
|
|
52
109
|
directive: DecodedDirective;
|
|
53
110
|
}
|
|
111
|
+
/**
|
|
112
|
+
* THE CHANGE LIST — every field an update sets, as "Label old → new" when the
|
|
113
|
+
* record's current value is known, "Label → new" when it is not. ONE component
|
|
114
|
+
* for the card row and the host's confirm dialog, so the two can never read
|
|
115
|
+
* differently (reviewer, 2026-10-02: the confirm showed only the new value).
|
|
116
|
+
*/
|
|
117
|
+
declare function DirectiveChangeList({ changes, className, }: {
|
|
118
|
+
changes: ItemChange[];
|
|
119
|
+
className?: string;
|
|
120
|
+
}): react.JSX.Element;
|
|
54
121
|
declare function SideEffectDirectiveCard({ directive }: SideEffectDirectiveCardProps): react.JSX.Element;
|
|
55
122
|
|
|
56
123
|
interface DirectiveFallbackCardProps {
|
|
@@ -94,45 +161,13 @@ interface DirectiveRenderProps {
|
|
|
94
161
|
}
|
|
95
162
|
declare function DirectiveRender({ conversationId, ...props }: DirectiveRenderProps): react.JSX.Element;
|
|
96
163
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
* as "Item" — they never named the record they would change, and an Update card
|
|
103
|
-
* never said what it would change. The item-summary helpers name a thing to be
|
|
104
|
-
* CREATED from its own fields; an update or delete item carries the TARGET's id
|
|
105
|
-
* and, for an update, the NEW values — so its "title" field is the new title,
|
|
106
|
-
* not the name of the record being changed. Naming the target is the host's
|
|
107
|
-
* live lookup (`DirectiveHost.renderRecord`); what changes is right here.
|
|
108
|
-
*
|
|
109
|
-
* Law: common-docs/policies/destructive-and-expensive-actions.md — the sentence
|
|
110
|
-
* names what changes.
|
|
111
|
-
*/
|
|
112
|
-
/** Classes whose items point at an EXISTING record by `id`. */
|
|
113
|
-
declare const TARGETING_CLASSES: ReadonlySet<string>;
|
|
114
|
-
/** How long a changed value may read before it is shortened (full value on hover). */
|
|
115
|
-
declare const CHANGE_VALUE_MAX = 60;
|
|
116
|
-
/** The id of the existing record an update/delete item targets, or null. */
|
|
117
|
-
declare function itemRecordId(item: Record<string, unknown>): string | null;
|
|
118
|
-
/** "due_date" → "Due date". Underscores read as developer output. */
|
|
119
|
-
declare function fieldLabel(key: string): string;
|
|
120
|
-
/** A short, honest name for a record we could not look up: "Task 1a2b3c4d". */
|
|
121
|
-
declare function recordFallbackName(nounLabel: string, id: string): string;
|
|
122
|
-
interface ItemChange {
|
|
123
|
-
key: string;
|
|
124
|
-
/** "Due date". */
|
|
125
|
-
label: string;
|
|
126
|
-
/** What it becomes, shortened for a row; `full` carries the whole value. */
|
|
127
|
-
value: string;
|
|
128
|
-
full: string;
|
|
129
|
-
/** True when the new value empties the field. */
|
|
130
|
-
clears: boolean;
|
|
164
|
+
type RecordValuesStatus = "idle" | "loading" | "ready" | "unavailable";
|
|
165
|
+
interface RecordValues {
|
|
166
|
+
/** The record's fields now, or null until (or unless) they are read. */
|
|
167
|
+
values: Record<string, unknown> | null;
|
|
168
|
+
status: RecordValuesStatus;
|
|
131
169
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
* them, never a sample: a person approving an overwrite sees the whole of it.
|
|
135
|
-
*/
|
|
136
|
-
declare function itemChanges(item: Record<string, unknown>): ItemChange[];
|
|
170
|
+
type RecordReader = (ref: DirectiveRecordRef) => Promise<Record<string, unknown> | null>;
|
|
171
|
+
declare function useRecordValues(read: RecordReader | undefined, ref: DirectiveRecordRef | null): RecordValues;
|
|
137
172
|
|
|
138
|
-
export { ApplyDirectiveButton, type ApplyDirectiveButtonProps, CHANGE_VALUE_MAX, DirectiveFallbackCard, type DirectiveFallbackCardProps, DirectiveProvisionalCard, type DirectiveProvisionalCardProps, DirectiveRender, type DirectiveRenderProps, type DirectiveRenderer, type DirectiveRendererProps, type ItemChange, SideEffectDirectiveCard, type SideEffectDirectiveCardProps, TARGETING_CLASSES, fieldLabel, getDirectiveRenderer, itemChanges, itemRecordId, provisionalDirectiveSlug, recordFallbackName, registerDirectiveRenderer, resetDirectiveRenderers };
|
|
173
|
+
export { ApplyDirectiveButton, type ApplyDirectiveButtonProps, CHANGE_VALUE_MAX, type ChangeValue, DirectiveChangeList, DirectiveFallbackCard, type DirectiveFallbackCardProps, DirectiveProvisionalCard, type DirectiveProvisionalCardProps, DirectiveRecordRef, DirectiveRender, type DirectiveRenderProps, type DirectiveRenderer, type DirectiveRendererProps, type ItemChange, type RecordReader, type RecordValues, type RecordValuesStatus, SideEffectDirectiveCard, type SideEffectDirectiveCardProps, TARGETING_CLASSES, describeChangeValue, fieldLabel, getDirectiveRenderer, itemChanges, itemRecordId, provisionalDirectiveSlug, recordFallbackName, registerDirectiveRenderer, resetDirectiveRenderers, useRecordValues };
|
package/dist/directives.js
CHANGED
|
@@ -66,6 +66,9 @@ function recordFallbackName(nounLabel3, id) {
|
|
|
66
66
|
const short = isUuidShape(id) ? id.slice(0, 8) : id.length > 12 ? `${id.slice(0, 12)}\u2026` : id;
|
|
67
67
|
return `${nounLabel3} ${short}`;
|
|
68
68
|
}
|
|
69
|
+
function describeChangeValue(value) {
|
|
70
|
+
return describeValue(value);
|
|
71
|
+
}
|
|
69
72
|
function describeValue(value) {
|
|
70
73
|
if (value === null || value === void 0) return { value: "cleared", full: "cleared", clears: true };
|
|
71
74
|
if (typeof value === "string") {
|
|
@@ -94,11 +97,26 @@ function safeJson(value) {
|
|
|
94
97
|
return String(value);
|
|
95
98
|
}
|
|
96
99
|
}
|
|
97
|
-
function
|
|
100
|
+
function sameValue(a, b) {
|
|
101
|
+
if (a === b) return true;
|
|
102
|
+
if (a === null || a === void 0 || b === null || b === void 0) {
|
|
103
|
+
const emptyA = a === null || a === void 0 || a === "";
|
|
104
|
+
const emptyB = b === null || b === void 0 || b === "";
|
|
105
|
+
return emptyA && emptyB;
|
|
106
|
+
}
|
|
107
|
+
if (typeof a === "object" || typeof b === "object") return safeJson(a) === safeJson(b);
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
function itemChanges(item, current) {
|
|
98
111
|
const out = [];
|
|
99
112
|
for (const [key, raw] of Object.entries(item)) {
|
|
100
113
|
if (NOT_A_CHANGE.has(key)) continue;
|
|
101
|
-
|
|
114
|
+
const change = { key, label: fieldLabel(key), ...describeValue(raw) };
|
|
115
|
+
if (current && Object.prototype.hasOwnProperty.call(current, key)) {
|
|
116
|
+
change.before = describeValue(current[key]);
|
|
117
|
+
change.same = sameValue(current[key], raw);
|
|
118
|
+
}
|
|
119
|
+
out.push(change);
|
|
102
120
|
}
|
|
103
121
|
return out;
|
|
104
122
|
}
|
|
@@ -211,12 +229,23 @@ function ApplyDirectiveButton({
|
|
|
211
229
|
const conversationId = scope.conversationId || void 0;
|
|
212
230
|
const items = directive.items;
|
|
213
231
|
const readsLedger = !!host.applyState && !!host.confirm && directive.parsed.executes && items.length > 0;
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
);
|
|
232
|
+
const initial = readsLedger ? { status: "checking" } : { status: "idle" };
|
|
233
|
+
const [state, setState] = useState(initial);
|
|
217
234
|
const [elapsed, setElapsed] = useState(0);
|
|
218
235
|
const [askingAgain, setAskingAgain] = useState(false);
|
|
219
236
|
const startedAt = useRef(null);
|
|
237
|
+
const identity = JSON.stringify([directive.slug, items, conversationId ?? null]);
|
|
238
|
+
const [stateFor, setStateFor] = useState(identity);
|
|
239
|
+
if (stateFor !== identity) {
|
|
240
|
+
setStateFor(identity);
|
|
241
|
+
setState(initial);
|
|
242
|
+
setAskingAgain(false);
|
|
243
|
+
setElapsed(0);
|
|
244
|
+
}
|
|
245
|
+
const currentIdentity = useRef(identity);
|
|
246
|
+
useEffect(() => {
|
|
247
|
+
currentIdentity.current = identity;
|
|
248
|
+
}, [identity]);
|
|
220
249
|
const nounText = nounLabel(directive.noun, host.nouns);
|
|
221
250
|
const shellKey = readsLedger ? JSON.stringify([directive.slug, items, conversationId ?? null]) : "";
|
|
222
251
|
const read = host.applyState;
|
|
@@ -239,7 +268,8 @@ function ApplyDirectiveButton({
|
|
|
239
268
|
applied: shellItems.length,
|
|
240
269
|
failed: 0,
|
|
241
270
|
message: answer.message?.trim() ? answer.message.trim() : null,
|
|
242
|
-
records: answer.records ?? []
|
|
271
|
+
records: answer.records ?? [],
|
|
272
|
+
copies: Math.max(1, answer.copies ?? 1)
|
|
243
273
|
} : prev
|
|
244
274
|
);
|
|
245
275
|
} else if (answer.state === "in_flight" && polls < FINISH_POLLS_MAX) {
|
|
@@ -279,6 +309,9 @@ function ApplyDirectiveButton({
|
|
|
279
309
|
async function handleApply(again = false) {
|
|
280
310
|
if (!confirm) return;
|
|
281
311
|
const before = state;
|
|
312
|
+
const askedFor = identity;
|
|
313
|
+
const stillHere = () => currentIdentity.current === askedFor;
|
|
314
|
+
const priorCopies = state.status === "applied" ? state.copies : 0;
|
|
282
315
|
if (host.ask) {
|
|
283
316
|
if (again) setAskingAgain(true);
|
|
284
317
|
else setState({ status: "asking" });
|
|
@@ -291,6 +324,7 @@ function ApplyDirectiveButton({
|
|
|
291
324
|
...again ? { again: true } : {}
|
|
292
325
|
});
|
|
293
326
|
} catch (error) {
|
|
327
|
+
if (!stillHere()) return;
|
|
294
328
|
setAskingAgain(false);
|
|
295
329
|
setState({
|
|
296
330
|
status: "error",
|
|
@@ -298,6 +332,7 @@ function ApplyDirectiveButton({
|
|
|
298
332
|
});
|
|
299
333
|
return;
|
|
300
334
|
}
|
|
335
|
+
if (!stillHere()) return;
|
|
301
336
|
setAskingAgain(false);
|
|
302
337
|
if (!ok) {
|
|
303
338
|
setState(again ? before : { status: "idle" });
|
|
@@ -311,15 +346,19 @@ function ApplyDirectiveButton({
|
|
|
311
346
|
if (conversationId) shell.conversationId = conversationId;
|
|
312
347
|
if (again) shell.force = true;
|
|
313
348
|
const result = await confirm(shell);
|
|
349
|
+
if (!stillHere()) return;
|
|
314
350
|
setState({
|
|
315
351
|
status: "applied",
|
|
316
352
|
applied: result.applied,
|
|
317
353
|
failed: result.failed,
|
|
318
354
|
message: result.message?.trim() ? result.message.trim() : null,
|
|
319
|
-
records: result.records ?? []
|
|
355
|
+
records: result.records ?? [],
|
|
356
|
+
// "Run again" made one more; a first apply (or a replay of one) is one.
|
|
357
|
+
copies: again ? Math.max(1, priorCopies) + 1 : Math.max(1, priorCopies)
|
|
320
358
|
});
|
|
321
359
|
onApplied?.();
|
|
322
360
|
} catch (error) {
|
|
361
|
+
if (!stillHere()) return;
|
|
323
362
|
setState({
|
|
324
363
|
status: "error",
|
|
325
364
|
message: error instanceof Error && error.message ? error.message : "That couldn't be applied just now. Please try again."
|
|
@@ -344,6 +383,15 @@ function ApplyDirectiveButton({
|
|
|
344
383
|
bad && !state.message ? ` \xB7 ${state.failed} failed` : ""
|
|
345
384
|
] })
|
|
346
385
|
] }),
|
|
386
|
+
state.copies > 1 ? /* @__PURE__ */ jsx3(
|
|
387
|
+
"span",
|
|
388
|
+
{
|
|
389
|
+
className: "shrink-0 text-muted-foreground",
|
|
390
|
+
"data-apply-copies": state.copies,
|
|
391
|
+
title: records.length > 0 ? directive.directiveClass === "create" ? "Links to the latest copy." : "Links to the latest run." : void 0,
|
|
392
|
+
children: directive.directiveClass === "create" ? `${state.copies} copies` : `Ran ${state.copies} times`
|
|
393
|
+
}
|
|
394
|
+
) : null,
|
|
347
395
|
records.map((record) => /* @__PURE__ */ jsx3("span", { className: "inline-flex min-w-0 items-center", children: host.renderRecord?.({
|
|
348
396
|
...record,
|
|
349
397
|
fallback: recordFallbackName(label2, record.id),
|
|
@@ -394,6 +442,7 @@ function ApplyDirectiveButton({
|
|
|
394
442
|
}
|
|
395
443
|
);
|
|
396
444
|
}
|
|
445
|
+
const destructive = directive.directiveClass === "delete";
|
|
397
446
|
return /* @__PURE__ */ jsxs2("span", { className: "inline-flex items-center gap-2", children: [
|
|
398
447
|
/* @__PURE__ */ jsxs2(
|
|
399
448
|
"button",
|
|
@@ -401,7 +450,8 @@ function ApplyDirectiveButton({
|
|
|
401
450
|
type: "button",
|
|
402
451
|
onClick: () => void handleApply(),
|
|
403
452
|
disabled: state.status === "applying" || state.status === "asking" || items.length === 0,
|
|
404
|
-
|
|
453
|
+
"data-apply-tone": destructive ? "destructive" : "default",
|
|
454
|
+
className: `inline-flex items-center gap-1 rounded-md border px-2 py-1 text-xs font-medium disabled:opacity-50 ${destructive ? "border-destructive/50 bg-background text-destructive hover:bg-destructive/10" : "border-border bg-background hover:bg-accent"}`,
|
|
405
455
|
children: [
|
|
406
456
|
state.status === "applying" ? /* @__PURE__ */ jsx3(LoaderIcon, { className: "h-3.5 w-3.5 animate-spin" }) : /* @__PURE__ */ jsx3(PlayIcon, { className: "h-3.5 w-3.5" }),
|
|
407
457
|
state.status === "applying" ? `Applying${itemCount ? ` ${itemCount} ${itemCount === 1 ? "item" : "items"}` : ""}\u2026${elapsed ? ` ${elapsed}s` : ""}` : label
|
|
@@ -416,7 +466,7 @@ function ApplyDirectiveButton({
|
|
|
416
466
|
}
|
|
417
467
|
|
|
418
468
|
// directives/SideEffectDirectiveCard.tsx
|
|
419
|
-
import { useState as
|
|
469
|
+
import { useState as useState3 } from "react";
|
|
420
470
|
import {
|
|
421
471
|
asKindInstance,
|
|
422
472
|
directiveDisplay,
|
|
@@ -426,6 +476,39 @@ import {
|
|
|
426
476
|
nounLabel as nounLabel2,
|
|
427
477
|
nounTitleColumn
|
|
428
478
|
} from "@ai-matrx/content-ir";
|
|
479
|
+
|
|
480
|
+
// directives/record-values.ts
|
|
481
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
482
|
+
function useRecordValues(read, ref) {
|
|
483
|
+
const key = ref && read ? `${ref.noun}:${ref.id}` : "";
|
|
484
|
+
const [result, setResult] = useState2({
|
|
485
|
+
key: "",
|
|
486
|
+
values: null,
|
|
487
|
+
status: "idle"
|
|
488
|
+
});
|
|
489
|
+
useEffect2(() => {
|
|
490
|
+
if (!key || !read) return;
|
|
491
|
+
const split = key.indexOf(":");
|
|
492
|
+
const target = { noun: key.slice(0, split), id: key.slice(split + 1) };
|
|
493
|
+
let live = true;
|
|
494
|
+
setResult({ key, values: null, status: "loading" });
|
|
495
|
+
read(target).then((values) => {
|
|
496
|
+
if (!live) return;
|
|
497
|
+
setResult({ key, values, status: values ? "ready" : "unavailable" });
|
|
498
|
+
}).catch(() => {
|
|
499
|
+
if (!live) return;
|
|
500
|
+
setResult({ key, values: null, status: "unavailable" });
|
|
501
|
+
});
|
|
502
|
+
return () => {
|
|
503
|
+
live = false;
|
|
504
|
+
};
|
|
505
|
+
}, [key, read]);
|
|
506
|
+
if (!key) return { values: null, status: "idle" };
|
|
507
|
+
if (result.key !== key) return { values: null, status: "loading" };
|
|
508
|
+
return { values: result.values, status: result.status };
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
// directives/SideEffectDirectiveCard.tsx
|
|
429
512
|
import { Fragment, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
430
513
|
var ROWS_BEFORE_FOLD = 3;
|
|
431
514
|
function ItemRow({
|
|
@@ -479,44 +562,73 @@ function ItemRow({
|
|
|
479
562
|
host.renderCopy?.({ label: title, value: item, kind, size: "xs" })
|
|
480
563
|
] });
|
|
481
564
|
}
|
|
482
|
-
function
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
recordId
|
|
565
|
+
function DirectiveChangeList({
|
|
566
|
+
changes,
|
|
567
|
+
className
|
|
486
568
|
}) {
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
host.renderCopy?.({ label: fallback, value: item, size: "xs" })
|
|
495
|
-
] }),
|
|
496
|
-
directive.directiveClass === "update" ? changes.length === 0 ? /* @__PURE__ */ jsx4("p", { className: "px-1 text-[11px] text-muted-foreground", children: "Sets no fields \u2014 nothing would change." }) : /* @__PURE__ */ jsx4("ul", { className: "mt-0.5 space-y-0.5 px-1", children: changes.map((change) => /* @__PURE__ */ jsxs3(
|
|
569
|
+
if (changes.length === 0) {
|
|
570
|
+
return /* @__PURE__ */ jsx4("p", { className: `text-[11px] text-muted-foreground${className ? ` ${className}` : ""}`, children: "Sets no fields \u2014 nothing would change." });
|
|
571
|
+
}
|
|
572
|
+
return /* @__PURE__ */ jsx4("ul", { className: `space-y-0.5${className ? ` ${className}` : ""}`, "data-directive-changes": "", children: changes.map((change) => {
|
|
573
|
+
const before = change.before && !change.same ? change.before : null;
|
|
574
|
+
const was = before ? before.clears ? "empty" : before.value : null;
|
|
575
|
+
return /* @__PURE__ */ jsxs3(
|
|
497
576
|
"li",
|
|
498
577
|
{
|
|
499
578
|
className: "flex min-w-0 items-baseline gap-1.5 text-[11px]",
|
|
500
|
-
title: `${change.label} \u2192 ${change.full}`,
|
|
579
|
+
title: before ? `${change.label}: ${before.clears ? "empty" : before.full} \u2192 ${change.full}` : `${change.label} \u2192 ${change.full}`,
|
|
580
|
+
"data-change-key": change.key,
|
|
501
581
|
children: [
|
|
502
582
|
/* @__PURE__ */ jsx4("span", { className: "shrink-0 text-muted-foreground", children: change.label }),
|
|
583
|
+
was !== null ? /* @__PURE__ */ jsx4(
|
|
584
|
+
"span",
|
|
585
|
+
{
|
|
586
|
+
className: "min-w-0 max-w-[40%] shrink truncate text-muted-foreground line-through",
|
|
587
|
+
"data-change-before": "",
|
|
588
|
+
children: was
|
|
589
|
+
}
|
|
590
|
+
) : null,
|
|
503
591
|
/* @__PURE__ */ jsx4("span", { "aria-hidden": true, className: "shrink-0 text-muted-foreground", children: "\u2192" }),
|
|
504
592
|
/* @__PURE__ */ jsx4(
|
|
505
593
|
"span",
|
|
506
594
|
{
|
|
507
595
|
className: `min-w-0 truncate ${change.clears ? "italic text-muted-foreground" : "text-foreground"}`,
|
|
596
|
+
"data-change-after": "",
|
|
508
597
|
children: change.value
|
|
509
598
|
}
|
|
510
|
-
)
|
|
599
|
+
),
|
|
600
|
+
change.same ? /* @__PURE__ */ jsx4("span", { className: "shrink-0 text-muted-foreground", children: "(no change)" }) : null
|
|
511
601
|
]
|
|
512
602
|
},
|
|
513
603
|
change.key
|
|
514
|
-
)
|
|
604
|
+
);
|
|
605
|
+
}) });
|
|
606
|
+
}
|
|
607
|
+
function TargetRow({
|
|
608
|
+
directive,
|
|
609
|
+
item,
|
|
610
|
+
recordId
|
|
611
|
+
}) {
|
|
612
|
+
const host = useDirectiveHost();
|
|
613
|
+
const fallback = recordFallbackName(nounLabel2(directive.noun, host.nouns), recordId);
|
|
614
|
+
const isUpdate = directive.directiveClass === "update";
|
|
615
|
+
const current = useRecordValues(
|
|
616
|
+
isUpdate ? host.readRecord : void 0,
|
|
617
|
+
isUpdate ? { noun: directive.noun, id: recordId } : null
|
|
618
|
+
);
|
|
619
|
+
const changes = isUpdate ? itemChanges(item, current.values) : [];
|
|
620
|
+
const name = host.renderRecord ? host.renderRecord({ noun: directive.noun, id: recordId, fallback, context: "row" }) : /* @__PURE__ */ jsx4("span", { className: "truncate font-medium text-foreground", children: fallback });
|
|
621
|
+
return /* @__PURE__ */ jsxs3("div", { className: "py-1 text-xs", "data-directive-target": recordId, children: [
|
|
622
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
623
|
+
/* @__PURE__ */ jsx4("span", { className: "flex min-w-0 flex-1 items-center gap-1 px-1", children: name }),
|
|
624
|
+
host.renderCopy?.({ label: fallback, value: item, size: "xs" })
|
|
625
|
+
] }),
|
|
626
|
+
isUpdate ? /* @__PURE__ */ jsx4(DirectiveChangeList, { changes, className: "mt-0.5 px-1" }) : null
|
|
515
627
|
] });
|
|
516
628
|
}
|
|
517
629
|
function SideEffectDirectiveCard({ directive }) {
|
|
518
630
|
const host = useDirectiveHost();
|
|
519
|
-
const [expanded, setExpanded] =
|
|
631
|
+
const [expanded, setExpanded] = useState3(false);
|
|
520
632
|
const items = directive.items;
|
|
521
633
|
const total = items.length;
|
|
522
634
|
const display = directiveDisplay(directive.directiveClass, directive.noun, host.nouns);
|
|
@@ -668,6 +780,7 @@ function DirectiveRenderInner({ content, className, streaming }) {
|
|
|
668
780
|
export {
|
|
669
781
|
ApplyDirectiveButton,
|
|
670
782
|
CHANGE_VALUE_MAX,
|
|
783
|
+
DirectiveChangeList,
|
|
671
784
|
DirectiveFallbackCard,
|
|
672
785
|
DirectiveHostProvider,
|
|
673
786
|
DirectiveProvisionalCard,
|
|
@@ -675,6 +788,7 @@ export {
|
|
|
675
788
|
DirectiveScopeProvider,
|
|
676
789
|
SideEffectDirectiveCard,
|
|
677
790
|
TARGETING_CLASSES,
|
|
791
|
+
describeChangeValue,
|
|
678
792
|
fieldLabel,
|
|
679
793
|
getDirectiveRenderer,
|
|
680
794
|
itemChanges,
|
|
@@ -684,6 +798,7 @@ export {
|
|
|
684
798
|
registerDirectiveRenderer,
|
|
685
799
|
resetDirectiveRenderers,
|
|
686
800
|
useDirectiveHost,
|
|
687
|
-
useDirectiveScope
|
|
801
|
+
useDirectiveScope,
|
|
802
|
+
useRecordValues
|
|
688
803
|
};
|
|
689
804
|
//# sourceMappingURL=directives.js.map
|