@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.
@@ -1,4 +1,5 @@
1
- export { D as DirectiveApplyResult, a as DirectiveApplyState, b as DirectiveAskRequest, c as DirectiveCopyProps, d as DirectiveHost, e as DirectiveHostProvider, f as DirectiveHostProviderProps, g as DirectiveOpenItemOptions, h as DirectiveRecordProps, i as DirectiveRecordRef, j as DirectiveScope, k as DirectiveScopeProvider, l as DirectiveShell, u as useDirectiveHost, m as useDirectiveScope } from './directive-host-DJfF35FD.js';
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
- * WHAT A DIRECTIVE ITEM WILL DO TO AN EXISTING RECORD — for the card, the
99
- * confirm dialog, and anything else that must say it before the click.
100
- *
101
- * WHY (reviewer, 2026-09-30): an Update card and a Delete card showed each item
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
- * Every field an UPDATE item sets, in the order the item carries them — ALL of
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 };
@@ -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 itemChanges(item) {
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
- out.push({ key, label: fieldLabel(key), ...describeValue(raw) });
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 [state, setState] = useState(
215
- readsLedger ? { status: "checking" } : { status: "idle" }
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
- className: "inline-flex items-center gap-1 rounded-md border border-border bg-background px-2 py-1 text-xs font-medium hover:bg-accent disabled:opacity-50",
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 useState2 } from "react";
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 TargetRow({
483
- directive,
484
- item,
485
- recordId
565
+ function DirectiveChangeList({
566
+ changes,
567
+ className
486
568
  }) {
487
- const host = useDirectiveHost();
488
- const fallback = recordFallbackName(nounLabel2(directive.noun, host.nouns), recordId);
489
- const changes = directive.directiveClass === "update" ? itemChanges(item) : [];
490
- 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 });
491
- return /* @__PURE__ */ jsxs3("div", { className: "py-1 text-xs", "data-directive-target": recordId, children: [
492
- /* @__PURE__ */ jsxs3("div", { className: "flex min-w-0 items-center gap-2", children: [
493
- /* @__PURE__ */ jsx4("span", { className: "flex min-w-0 flex-1 items-center gap-1 px-1", children: name }),
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
- )) }) : null
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] = useState2(false);
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