@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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.16.0 — 2026-10-02
|
|
4
|
+
|
|
5
|
+
The G3 review of the action cards (nightly clone). Guard: `__tests__/directive-card-g3.test.tsx`
|
|
6
|
+
(7 cases, every one red on 0.15.2).
|
|
7
|
+
|
|
8
|
+
- **An update says old → new.** New host seam `DirectiveHost.readRecord({noun, id})` →
|
|
9
|
+
the record's current fields (or null). `itemChanges(item, current)` now carries `before`
|
|
10
|
+
and `same`; the new `DirectiveChangeList` draws "Label old → new" (old struck through,
|
|
11
|
+
"empty" for a blank field, "(no change)" when it already holds the value). ONE component
|
|
12
|
+
for the card row and a host's confirm dialog. `useRecordValues(read, ref)` reads it.
|
|
13
|
+
- **A Delete card's Apply looks destructive** (`data-apply-tone="destructive"`), not the
|
|
14
|
+
neutral grey of a create's.
|
|
15
|
+
- **Run again shows the copies.** `DirectiveApplyState.copies` (1 + every Run again) and
|
|
16
|
+
`records` = the LATEST copy's. The tally says "2 copies" (create) / "Ran 2 times" and
|
|
17
|
+
links the newest copy; a yes to Run again counts one more.
|
|
18
|
+
- **The card's state belongs to the block, not its slot.** A host that keys blocks by
|
|
19
|
+
position handed one card instance a different directive when a block was inserted
|
|
20
|
+
above it; an applied Update card flipped back to "Apply" until a reload. The Apply
|
|
21
|
+
control now resets and re-reads the ledger whenever the block it draws changes, and an
|
|
22
|
+
apply that finishes after its block moved away never lands on the new one.
|
|
23
|
+
|
|
24
|
+
Consumer action: pass `readRecord` on the directive host for old → new; a host's own
|
|
25
|
+
confirm dialog draws changes through `DirectiveChangeList`; an `applyState` answer passes
|
|
26
|
+
`copies` when its ledger knows it.
|
|
27
|
+
|
|
3
28
|
## 0.15.2 — 2026-10-02
|
|
4
29
|
|
|
5
30
|
- While "Run again" asks, the tally stays on screen (only its own button goes
|
|
@@ -32,8 +32,17 @@ interface DirectiveApplyState {
|
|
|
32
32
|
state: "not_applied" | "in_flight" | "applied";
|
|
33
33
|
/** The ledger row's sentence ("Created task."), never composed client-side. */
|
|
34
34
|
message?: string | null;
|
|
35
|
-
/**
|
|
35
|
+
/**
|
|
36
|
+
* The records the LATEST apply wrote — the tally's doors. After "Run again"
|
|
37
|
+
* that is the newest copy, never the first.
|
|
38
|
+
*/
|
|
36
39
|
records?: DirectiveRecordRef[];
|
|
40
|
+
/**
|
|
41
|
+
* How many times the ledger holds this block as applied: 1 for the original,
|
|
42
|
+
* one more for every "Run again". Absent → 1. A create that ran twice made
|
|
43
|
+
* two records, and the card says so (reviewer, 2026-10-02).
|
|
44
|
+
*/
|
|
45
|
+
copies?: number;
|
|
37
46
|
}
|
|
38
47
|
/** One record a directive names: the noun it is, and its id. */
|
|
39
48
|
interface DirectiveRecordRef {
|
|
@@ -132,6 +141,14 @@ interface DirectiveHost {
|
|
|
132
141
|
* is idempotent. Absent → the card starts at Apply, as before.
|
|
133
142
|
*/
|
|
134
143
|
applyState?: (shell: DirectiveShell) => Promise<DirectiveApplyState>;
|
|
144
|
+
/**
|
|
145
|
+
* Read the CURRENT values of ONE existing record, so an update says what it
|
|
146
|
+
* replaces — "Status open → done", never just "→ done" (reviewer,
|
|
147
|
+
* 2026-10-02). Resolve `null` when the record cannot be read (no access, no
|
|
148
|
+
* such record, a noun the host cannot read); reject only for a real failure.
|
|
149
|
+
* Absent → an update row shows the new values alone, as before.
|
|
150
|
+
*/
|
|
151
|
+
readRecord?: (ref: DirectiveRecordRef) => Promise<Record<string, unknown> | null>;
|
|
135
152
|
/**
|
|
136
153
|
* Draw ONE existing record by its live name, as a way to open it. Used on
|
|
137
154
|
* update/delete rows (the record that will change), in the host's own ask
|
|
@@ -176,4 +193,4 @@ declare function DirectiveHostProvider({ host, children }: DirectiveHostProvider
|
|
|
176
193
|
*/
|
|
177
194
|
declare function useDirectiveHost(): DirectiveHost;
|
|
178
195
|
|
|
179
|
-
export { type
|
|
196
|
+
export { type DirectiveRecordRef as D, type DirectiveApplyResult as a, type DirectiveApplyState as b, type DirectiveAskRequest as c, type DirectiveCopyProps as d, type DirectiveHost as e, DirectiveHostProvider as f, type DirectiveHostProviderProps as g, type DirectiveOpenItemOptions as h, type DirectiveRecordProps as i, type DirectiveScope as j, DirectiveScopeProvider as k, type DirectiveShell as l, useDirectiveScope as m, useDirectiveHost as u };
|
|
@@ -32,8 +32,17 @@ interface DirectiveApplyState {
|
|
|
32
32
|
state: "not_applied" | "in_flight" | "applied";
|
|
33
33
|
/** The ledger row's sentence ("Created task."), never composed client-side. */
|
|
34
34
|
message?: string | null;
|
|
35
|
-
/**
|
|
35
|
+
/**
|
|
36
|
+
* The records the LATEST apply wrote — the tally's doors. After "Run again"
|
|
37
|
+
* that is the newest copy, never the first.
|
|
38
|
+
*/
|
|
36
39
|
records?: DirectiveRecordRef[];
|
|
40
|
+
/**
|
|
41
|
+
* How many times the ledger holds this block as applied: 1 for the original,
|
|
42
|
+
* one more for every "Run again". Absent → 1. A create that ran twice made
|
|
43
|
+
* two records, and the card says so (reviewer, 2026-10-02).
|
|
44
|
+
*/
|
|
45
|
+
copies?: number;
|
|
37
46
|
}
|
|
38
47
|
/** One record a directive names: the noun it is, and its id. */
|
|
39
48
|
interface DirectiveRecordRef {
|
|
@@ -132,6 +141,14 @@ interface DirectiveHost {
|
|
|
132
141
|
* is idempotent. Absent → the card starts at Apply, as before.
|
|
133
142
|
*/
|
|
134
143
|
applyState?: (shell: DirectiveShell) => Promise<DirectiveApplyState>;
|
|
144
|
+
/**
|
|
145
|
+
* Read the CURRENT values of ONE existing record, so an update says what it
|
|
146
|
+
* replaces — "Status open → done", never just "→ done" (reviewer,
|
|
147
|
+
* 2026-10-02). Resolve `null` when the record cannot be read (no access, no
|
|
148
|
+
* such record, a noun the host cannot read); reject only for a real failure.
|
|
149
|
+
* Absent → an update row shows the new values alone, as before.
|
|
150
|
+
*/
|
|
151
|
+
readRecord?: (ref: DirectiveRecordRef) => Promise<Record<string, unknown> | null>;
|
|
135
152
|
/**
|
|
136
153
|
* Draw ONE existing record by its live name, as a way to open it. Used on
|
|
137
154
|
* update/delete rows (the record that will change), in the host's own ask
|
|
@@ -176,4 +193,4 @@ declare function DirectiveHostProvider({ host, children }: DirectiveHostProvider
|
|
|
176
193
|
*/
|
|
177
194
|
declare function useDirectiveHost(): DirectiveHost;
|
|
178
195
|
|
|
179
|
-
export { type
|
|
196
|
+
export { type DirectiveRecordRef as D, type DirectiveApplyResult as a, type DirectiveApplyState as b, type DirectiveAskRequest as c, type DirectiveCopyProps as d, type DirectiveHost as e, DirectiveHostProvider as f, type DirectiveHostProviderProps as g, type DirectiveOpenItemOptions as h, type DirectiveRecordProps as i, type DirectiveScope as j, DirectiveScopeProvider as k, type DirectiveShell as l, useDirectiveScope as m, useDirectiveHost as u };
|
package/dist/directives.cjs
CHANGED
|
@@ -23,6 +23,7 @@ var directives_exports = {};
|
|
|
23
23
|
__export(directives_exports, {
|
|
24
24
|
ApplyDirectiveButton: () => ApplyDirectiveButton,
|
|
25
25
|
CHANGE_VALUE_MAX: () => CHANGE_VALUE_MAX,
|
|
26
|
+
DirectiveChangeList: () => DirectiveChangeList,
|
|
26
27
|
DirectiveFallbackCard: () => DirectiveFallbackCard,
|
|
27
28
|
DirectiveHostProvider: () => DirectiveHostProvider,
|
|
28
29
|
DirectiveProvisionalCard: () => DirectiveProvisionalCard,
|
|
@@ -30,6 +31,7 @@ __export(directives_exports, {
|
|
|
30
31
|
DirectiveScopeProvider: () => DirectiveScopeProvider,
|
|
31
32
|
SideEffectDirectiveCard: () => SideEffectDirectiveCard,
|
|
32
33
|
TARGETING_CLASSES: () => TARGETING_CLASSES,
|
|
34
|
+
describeChangeValue: () => describeChangeValue,
|
|
33
35
|
fieldLabel: () => fieldLabel,
|
|
34
36
|
getDirectiveRenderer: () => getDirectiveRenderer,
|
|
35
37
|
itemChanges: () => itemChanges,
|
|
@@ -39,7 +41,8 @@ __export(directives_exports, {
|
|
|
39
41
|
registerDirectiveRenderer: () => registerDirectiveRenderer,
|
|
40
42
|
resetDirectiveRenderers: () => resetDirectiveRenderers,
|
|
41
43
|
useDirectiveHost: () => useDirectiveHost,
|
|
42
|
-
useDirectiveScope: () => useDirectiveScope
|
|
44
|
+
useDirectiveScope: () => useDirectiveScope,
|
|
45
|
+
useRecordValues: () => useRecordValues
|
|
43
46
|
});
|
|
44
47
|
module.exports = __toCommonJS(directives_exports);
|
|
45
48
|
|
|
@@ -107,6 +110,9 @@ function recordFallbackName(nounLabel3, id) {
|
|
|
107
110
|
const short = (0, import_uuid.isUuidShape)(id) ? id.slice(0, 8) : id.length > 12 ? `${id.slice(0, 12)}\u2026` : id;
|
|
108
111
|
return `${nounLabel3} ${short}`;
|
|
109
112
|
}
|
|
113
|
+
function describeChangeValue(value) {
|
|
114
|
+
return describeValue(value);
|
|
115
|
+
}
|
|
110
116
|
function describeValue(value) {
|
|
111
117
|
if (value === null || value === void 0) return { value: "cleared", full: "cleared", clears: true };
|
|
112
118
|
if (typeof value === "string") {
|
|
@@ -135,11 +141,26 @@ function safeJson(value) {
|
|
|
135
141
|
return String(value);
|
|
136
142
|
}
|
|
137
143
|
}
|
|
138
|
-
function
|
|
144
|
+
function sameValue(a, b) {
|
|
145
|
+
if (a === b) return true;
|
|
146
|
+
if (a === null || a === void 0 || b === null || b === void 0) {
|
|
147
|
+
const emptyA = a === null || a === void 0 || a === "";
|
|
148
|
+
const emptyB = b === null || b === void 0 || b === "";
|
|
149
|
+
return emptyA && emptyB;
|
|
150
|
+
}
|
|
151
|
+
if (typeof a === "object" || typeof b === "object") return safeJson(a) === safeJson(b);
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
function itemChanges(item, current) {
|
|
139
155
|
const out = [];
|
|
140
156
|
for (const [key, raw] of Object.entries(item)) {
|
|
141
157
|
if (NOT_A_CHANGE.has(key)) continue;
|
|
142
|
-
|
|
158
|
+
const change = { key, label: fieldLabel(key), ...describeValue(raw) };
|
|
159
|
+
if (current && Object.prototype.hasOwnProperty.call(current, key)) {
|
|
160
|
+
change.before = describeValue(current[key]);
|
|
161
|
+
change.same = sameValue(current[key], raw);
|
|
162
|
+
}
|
|
163
|
+
out.push(change);
|
|
143
164
|
}
|
|
144
165
|
return out;
|
|
145
166
|
}
|
|
@@ -252,12 +273,23 @@ function ApplyDirectiveButton({
|
|
|
252
273
|
const conversationId = scope.conversationId || void 0;
|
|
253
274
|
const items = directive.items;
|
|
254
275
|
const readsLedger = !!host.applyState && !!host.confirm && directive.parsed.executes && items.length > 0;
|
|
255
|
-
const
|
|
256
|
-
|
|
257
|
-
);
|
|
276
|
+
const initial = readsLedger ? { status: "checking" } : { status: "idle" };
|
|
277
|
+
const [state, setState] = (0, import_react2.useState)(initial);
|
|
258
278
|
const [elapsed, setElapsed] = (0, import_react2.useState)(0);
|
|
259
279
|
const [askingAgain, setAskingAgain] = (0, import_react2.useState)(false);
|
|
260
280
|
const startedAt = (0, import_react2.useRef)(null);
|
|
281
|
+
const identity = JSON.stringify([directive.slug, items, conversationId ?? null]);
|
|
282
|
+
const [stateFor, setStateFor] = (0, import_react2.useState)(identity);
|
|
283
|
+
if (stateFor !== identity) {
|
|
284
|
+
setStateFor(identity);
|
|
285
|
+
setState(initial);
|
|
286
|
+
setAskingAgain(false);
|
|
287
|
+
setElapsed(0);
|
|
288
|
+
}
|
|
289
|
+
const currentIdentity = (0, import_react2.useRef)(identity);
|
|
290
|
+
(0, import_react2.useEffect)(() => {
|
|
291
|
+
currentIdentity.current = identity;
|
|
292
|
+
}, [identity]);
|
|
261
293
|
const nounText = (0, import_content_ir2.nounLabel)(directive.noun, host.nouns);
|
|
262
294
|
const shellKey = readsLedger ? JSON.stringify([directive.slug, items, conversationId ?? null]) : "";
|
|
263
295
|
const read = host.applyState;
|
|
@@ -280,7 +312,8 @@ function ApplyDirectiveButton({
|
|
|
280
312
|
applied: shellItems.length,
|
|
281
313
|
failed: 0,
|
|
282
314
|
message: answer.message?.trim() ? answer.message.trim() : null,
|
|
283
|
-
records: answer.records ?? []
|
|
315
|
+
records: answer.records ?? [],
|
|
316
|
+
copies: Math.max(1, answer.copies ?? 1)
|
|
284
317
|
} : prev
|
|
285
318
|
);
|
|
286
319
|
} else if (answer.state === "in_flight" && polls < FINISH_POLLS_MAX) {
|
|
@@ -320,6 +353,9 @@ function ApplyDirectiveButton({
|
|
|
320
353
|
async function handleApply(again = false) {
|
|
321
354
|
if (!confirm) return;
|
|
322
355
|
const before = state;
|
|
356
|
+
const askedFor = identity;
|
|
357
|
+
const stillHere = () => currentIdentity.current === askedFor;
|
|
358
|
+
const priorCopies = state.status === "applied" ? state.copies : 0;
|
|
323
359
|
if (host.ask) {
|
|
324
360
|
if (again) setAskingAgain(true);
|
|
325
361
|
else setState({ status: "asking" });
|
|
@@ -332,6 +368,7 @@ function ApplyDirectiveButton({
|
|
|
332
368
|
...again ? { again: true } : {}
|
|
333
369
|
});
|
|
334
370
|
} catch (error) {
|
|
371
|
+
if (!stillHere()) return;
|
|
335
372
|
setAskingAgain(false);
|
|
336
373
|
setState({
|
|
337
374
|
status: "error",
|
|
@@ -339,6 +376,7 @@ function ApplyDirectiveButton({
|
|
|
339
376
|
});
|
|
340
377
|
return;
|
|
341
378
|
}
|
|
379
|
+
if (!stillHere()) return;
|
|
342
380
|
setAskingAgain(false);
|
|
343
381
|
if (!ok) {
|
|
344
382
|
setState(again ? before : { status: "idle" });
|
|
@@ -352,15 +390,19 @@ function ApplyDirectiveButton({
|
|
|
352
390
|
if (conversationId) shell.conversationId = conversationId;
|
|
353
391
|
if (again) shell.force = true;
|
|
354
392
|
const result = await confirm(shell);
|
|
393
|
+
if (!stillHere()) return;
|
|
355
394
|
setState({
|
|
356
395
|
status: "applied",
|
|
357
396
|
applied: result.applied,
|
|
358
397
|
failed: result.failed,
|
|
359
398
|
message: result.message?.trim() ? result.message.trim() : null,
|
|
360
|
-
records: result.records ?? []
|
|
399
|
+
records: result.records ?? [],
|
|
400
|
+
// "Run again" made one more; a first apply (or a replay of one) is one.
|
|
401
|
+
copies: again ? Math.max(1, priorCopies) + 1 : Math.max(1, priorCopies)
|
|
361
402
|
});
|
|
362
403
|
onApplied?.();
|
|
363
404
|
} catch (error) {
|
|
405
|
+
if (!stillHere()) return;
|
|
364
406
|
setState({
|
|
365
407
|
status: "error",
|
|
366
408
|
message: error instanceof Error && error.message ? error.message : "That couldn't be applied just now. Please try again."
|
|
@@ -385,6 +427,15 @@ function ApplyDirectiveButton({
|
|
|
385
427
|
bad && !state.message ? ` \xB7 ${state.failed} failed` : ""
|
|
386
428
|
] })
|
|
387
429
|
] }),
|
|
430
|
+
state.copies > 1 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
431
|
+
"span",
|
|
432
|
+
{
|
|
433
|
+
className: "shrink-0 text-muted-foreground",
|
|
434
|
+
"data-apply-copies": state.copies,
|
|
435
|
+
title: records.length > 0 ? directive.directiveClass === "create" ? "Links to the latest copy." : "Links to the latest run." : void 0,
|
|
436
|
+
children: directive.directiveClass === "create" ? `${state.copies} copies` : `Ran ${state.copies} times`
|
|
437
|
+
}
|
|
438
|
+
) : null,
|
|
388
439
|
records.map((record) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "inline-flex min-w-0 items-center", children: host.renderRecord?.({
|
|
389
440
|
...record,
|
|
390
441
|
fallback: recordFallbackName(label2, record.id),
|
|
@@ -435,6 +486,7 @@ function ApplyDirectiveButton({
|
|
|
435
486
|
}
|
|
436
487
|
);
|
|
437
488
|
}
|
|
489
|
+
const destructive = directive.directiveClass === "delete";
|
|
438
490
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "inline-flex items-center gap-2", children: [
|
|
439
491
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
440
492
|
"button",
|
|
@@ -442,7 +494,8 @@ function ApplyDirectiveButton({
|
|
|
442
494
|
type: "button",
|
|
443
495
|
onClick: () => void handleApply(),
|
|
444
496
|
disabled: state.status === "applying" || state.status === "asking" || items.length === 0,
|
|
445
|
-
|
|
497
|
+
"data-apply-tone": destructive ? "destructive" : "default",
|
|
498
|
+
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"}`,
|
|
446
499
|
children: [
|
|
447
500
|
state.status === "applying" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(LoaderIcon, { className: "h-3.5 w-3.5 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PlayIcon, { className: "h-3.5 w-3.5" }),
|
|
448
501
|
state.status === "applying" ? `Applying${itemCount ? ` ${itemCount} ${itemCount === 1 ? "item" : "items"}` : ""}\u2026${elapsed ? ` ${elapsed}s` : ""}` : label
|
|
@@ -457,8 +510,41 @@ function ApplyDirectiveButton({
|
|
|
457
510
|
}
|
|
458
511
|
|
|
459
512
|
// directives/SideEffectDirectiveCard.tsx
|
|
460
|
-
var
|
|
513
|
+
var import_react4 = require("react");
|
|
461
514
|
var import_content_ir3 = require("@ai-matrx/content-ir");
|
|
515
|
+
|
|
516
|
+
// directives/record-values.ts
|
|
517
|
+
var import_react3 = require("react");
|
|
518
|
+
function useRecordValues(read, ref) {
|
|
519
|
+
const key = ref && read ? `${ref.noun}:${ref.id}` : "";
|
|
520
|
+
const [result, setResult] = (0, import_react3.useState)({
|
|
521
|
+
key: "",
|
|
522
|
+
values: null,
|
|
523
|
+
status: "idle"
|
|
524
|
+
});
|
|
525
|
+
(0, import_react3.useEffect)(() => {
|
|
526
|
+
if (!key || !read) return;
|
|
527
|
+
const split = key.indexOf(":");
|
|
528
|
+
const target = { noun: key.slice(0, split), id: key.slice(split + 1) };
|
|
529
|
+
let live = true;
|
|
530
|
+
setResult({ key, values: null, status: "loading" });
|
|
531
|
+
read(target).then((values) => {
|
|
532
|
+
if (!live) return;
|
|
533
|
+
setResult({ key, values, status: values ? "ready" : "unavailable" });
|
|
534
|
+
}).catch(() => {
|
|
535
|
+
if (!live) return;
|
|
536
|
+
setResult({ key, values: null, status: "unavailable" });
|
|
537
|
+
});
|
|
538
|
+
return () => {
|
|
539
|
+
live = false;
|
|
540
|
+
};
|
|
541
|
+
}, [key, read]);
|
|
542
|
+
if (!key) return { values: null, status: "idle" };
|
|
543
|
+
if (result.key !== key) return { values: null, status: "loading" };
|
|
544
|
+
return { values: result.values, status: result.status };
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// directives/SideEffectDirectiveCard.tsx
|
|
462
548
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
463
549
|
var ROWS_BEFORE_FOLD = 3;
|
|
464
550
|
function ItemRow({
|
|
@@ -512,44 +598,73 @@ function ItemRow({
|
|
|
512
598
|
host.renderCopy?.({ label: title, value: item, kind, size: "xs" })
|
|
513
599
|
] });
|
|
514
600
|
}
|
|
515
|
-
function
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
recordId
|
|
601
|
+
function DirectiveChangeList({
|
|
602
|
+
changes,
|
|
603
|
+
className
|
|
519
604
|
}) {
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
host.renderCopy?.({ label: fallback, value: item, size: "xs" })
|
|
528
|
-
] }),
|
|
529
|
-
directive.directiveClass === "update" ? changes.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "px-1 text-[11px] text-muted-foreground", children: "Sets no fields \u2014 nothing would change." }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ul", { className: "mt-0.5 space-y-0.5 px-1", children: changes.map((change) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
605
|
+
if (changes.length === 0) {
|
|
606
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: `text-[11px] text-muted-foreground${className ? ` ${className}` : ""}`, children: "Sets no fields \u2014 nothing would change." });
|
|
607
|
+
}
|
|
608
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ul", { className: `space-y-0.5${className ? ` ${className}` : ""}`, "data-directive-changes": "", children: changes.map((change) => {
|
|
609
|
+
const before = change.before && !change.same ? change.before : null;
|
|
610
|
+
const was = before ? before.clears ? "empty" : before.value : null;
|
|
611
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
530
612
|
"li",
|
|
531
613
|
{
|
|
532
614
|
className: "flex min-w-0 items-baseline gap-1.5 text-[11px]",
|
|
533
|
-
title: `${change.label} \u2192 ${change.full}`,
|
|
615
|
+
title: before ? `${change.label}: ${before.clears ? "empty" : before.full} \u2192 ${change.full}` : `${change.label} \u2192 ${change.full}`,
|
|
616
|
+
"data-change-key": change.key,
|
|
534
617
|
children: [
|
|
535
618
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "shrink-0 text-muted-foreground", children: change.label }),
|
|
619
|
+
was !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
620
|
+
"span",
|
|
621
|
+
{
|
|
622
|
+
className: "min-w-0 max-w-[40%] shrink truncate text-muted-foreground line-through",
|
|
623
|
+
"data-change-before": "",
|
|
624
|
+
children: was
|
|
625
|
+
}
|
|
626
|
+
) : null,
|
|
536
627
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { "aria-hidden": true, className: "shrink-0 text-muted-foreground", children: "\u2192" }),
|
|
537
628
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
538
629
|
"span",
|
|
539
630
|
{
|
|
540
631
|
className: `min-w-0 truncate ${change.clears ? "italic text-muted-foreground" : "text-foreground"}`,
|
|
632
|
+
"data-change-after": "",
|
|
541
633
|
children: change.value
|
|
542
634
|
}
|
|
543
|
-
)
|
|
635
|
+
),
|
|
636
|
+
change.same ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "shrink-0 text-muted-foreground", children: "(no change)" }) : null
|
|
544
637
|
]
|
|
545
638
|
},
|
|
546
639
|
change.key
|
|
547
|
-
)
|
|
640
|
+
);
|
|
641
|
+
}) });
|
|
642
|
+
}
|
|
643
|
+
function TargetRow({
|
|
644
|
+
directive,
|
|
645
|
+
item,
|
|
646
|
+
recordId
|
|
647
|
+
}) {
|
|
648
|
+
const host = useDirectiveHost();
|
|
649
|
+
const fallback = recordFallbackName((0, import_content_ir3.nounLabel)(directive.noun, host.nouns), recordId);
|
|
650
|
+
const isUpdate = directive.directiveClass === "update";
|
|
651
|
+
const current = useRecordValues(
|
|
652
|
+
isUpdate ? host.readRecord : void 0,
|
|
653
|
+
isUpdate ? { noun: directive.noun, id: recordId } : null
|
|
654
|
+
);
|
|
655
|
+
const changes = isUpdate ? itemChanges(item, current.values) : [];
|
|
656
|
+
const name = host.renderRecord ? host.renderRecord({ noun: directive.noun, id: recordId, fallback, context: "row" }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "truncate font-medium text-foreground", children: fallback });
|
|
657
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "py-1 text-xs", "data-directive-target": recordId, children: [
|
|
658
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
659
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "flex min-w-0 flex-1 items-center gap-1 px-1", children: name }),
|
|
660
|
+
host.renderCopy?.({ label: fallback, value: item, size: "xs" })
|
|
661
|
+
] }),
|
|
662
|
+
isUpdate ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DirectiveChangeList, { changes, className: "mt-0.5 px-1" }) : null
|
|
548
663
|
] });
|
|
549
664
|
}
|
|
550
665
|
function SideEffectDirectiveCard({ directive }) {
|
|
551
666
|
const host = useDirectiveHost();
|
|
552
|
-
const [expanded, setExpanded] = (0,
|
|
667
|
+
const [expanded, setExpanded] = (0, import_react4.useState)(false);
|
|
553
668
|
const items = directive.items;
|
|
554
669
|
const total = items.length;
|
|
555
670
|
const display = (0, import_content_ir3.directiveDisplay)(directive.directiveClass, directive.noun, host.nouns);
|