@ai-matrx/content-ir-react 0.19.1 → 0.20.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,5 +1,5 @@
1
- import { D as DirectiveFailure, a as DirectiveFailureWords, b as DirectiveRecordRef } from './directive-host-Bw2_PrgL.cjs';
2
- export { c as DirectiveApplyResult, d as DirectiveApplyState, e as DirectiveAskRequest, f as DirectiveCopyProps, g as DirectiveHost, h as DirectiveHostProvider, i as DirectiveHostProviderProps, j as DirectiveOpenItemOptions, k as DirectiveRecordProps, l as DirectiveScope, m as DirectiveScopeProvider, n as DirectiveShell, u as useDirectiveHost, o as useDirectiveScope } from './directive-host-Bw2_PrgL.cjs';
1
+ import { D as DirectiveHost, a as DirectiveFailure, b as DirectiveFailureWords, c as DirectiveRecordRef } from './directive-host-B1hcjJxS.cjs';
2
+ export { d as DirectiveApplyResult, e as DirectiveApplyState, f as DirectiveAskRequest, g as DirectiveCopyProps, h as DirectiveHostProvider, i as DirectiveHostProviderProps, j as DirectiveOpenItemOptions, k as DirectiveRecordProps, l as DirectiveScope, m as DirectiveScopeProvider, n as DirectiveShell, o as DirectiveValueRef, u as useDirectiveHost, p as useDirectiveScope } from './directive-host-B1hcjJxS.cjs';
3
3
  import * as react from 'react';
4
4
  import { ComponentType } from 'react';
5
5
  import { DecodedDirective, DirectiveClass } from '@ai-matrx/content-ir';
@@ -94,12 +94,33 @@ declare function ApplyDirectiveButton({ directive, label, itemCount, onApplied,
94
94
  */
95
95
  /** Classes whose items point at an EXISTING record by `id`. */
96
96
  declare const TARGETING_CLASSES: ReadonlySet<string>;
97
- /** How long a changed value may read before it is shortened (full value on hover). */
98
- declare const CHANGE_VALUE_MAX = 60;
97
+ /**
98
+ * How long a changed value may read before it is shortened. A value someone
99
+ * must judge — a title, a status, a date — is always whole (G8A review: a 60
100
+ * cap plus CSS truncation cut "Review4 tasks…" on a phone); only a body of
101
+ * prose longer than this is shortened, whole on hover and in View/Copy.
102
+ */
103
+ declare const CHANGE_VALUE_MAX = 280;
99
104
  /** The id of the existing record an update/delete item targets, or null. */
100
105
  declare function itemRecordId(item: Record<string, unknown>): string | null;
101
- /** "due_date" → "Due date". Underscores read as developer output. */
106
+ /** "due_date" → "Due Date" — THE humanizer; underscores read as developer output. */
102
107
  declare function fieldLabel(key: string): string;
108
+ /**
109
+ * THE ONE FIELD-LABEL RULE for a directive — card rows, card facts and the
110
+ * host's confirm: the noun's title column reads "Title" whatever it is stored
111
+ * as (a workbook's `workbook_name`, a note's `label`), every other field reads
112
+ * through THE humanizer. A new workbook card said "workbook name" while its
113
+ * confirm said "Title" (G8A review, 2026-10-02).
114
+ */
115
+ declare function directiveFieldLabel(key: string, titleColumn: string | null | undefined): string;
116
+ /**
117
+ * The app's word for ONE stored value of ONE field — "incomplete" on a task
118
+ * reads "Inbox", "high" reads "High". The host answers it for its pick-list
119
+ * fields; null → the value as stored.
120
+ */
121
+ type DirectiveValueWord = (field: string, value: string) => string | null;
122
+ /** How an empty value reads — before or after, on the card and in the confirm. */
123
+ declare const EMPTY_VALUE_WORD = "None";
103
124
  /** A short, honest name for a record we could not look up: "Task 1a2b3c4d". */
104
125
  declare function recordFallbackName(nounLabel: string, id: string): string;
105
126
  /** One value as a row reads it: shortened, the whole of it, and whether it is empty. */
@@ -122,7 +143,7 @@ interface ItemChange extends ChangeValue {
122
143
  same?: boolean;
123
144
  }
124
145
  /** One value, described for a change row (`value` shortened, `full` whole). */
125
- declare function describeChangeValue(value: unknown): ChangeValue;
146
+ declare function describeChangeValue(value: unknown, word?: (value: string) => string | null): ChangeValue;
126
147
  /**
127
148
  * Every field an UPDATE item sets, in the order the item carries them — ALL of
128
149
  * them, never a sample: a person approving an overwrite sees the whole of it.
@@ -139,17 +160,27 @@ interface ItemChangesOptions {
139
160
  * (reviewer, 2026-10-02). The same rule the directive builder's form uses.
140
161
  */
141
162
  titleColumn?: string | null;
163
+ /** The app's word for a stored value (`DirectiveHost.valueLabel`, bound to the noun). */
164
+ valueWord?: DirectiveValueWord | null;
142
165
  }
143
166
  declare function itemChanges(item: Record<string, unknown>, current?: Record<string, unknown> | null, options?: ItemChangesOptions): ItemChange[];
144
167
 
145
168
  interface SideEffectDirectiveCardProps {
146
169
  directive: DecodedDirective;
147
170
  }
171
+ /** The host's value words for one record type, or null when it has none. */
172
+ declare function directiveValueWord(host: Pick<DirectiveHost, "valueLabel">, noun: string): DirectiveValueWord | null;
148
173
  /**
149
174
  * THE CHANGE LIST — every field an update sets, as "Label old → new" when the
150
175
  * record's current value is known, "Label → new" when it is not. ONE component
151
176
  * for the card row and the host's confirm dialog, so the two can never read
152
177
  * differently (reviewer, 2026-10-02: the confirm showed only the new value).
178
+ *
179
+ * 🚨 A VALUE SOMEONE MUST JUDGE IS NEVER CUT (G8A review, 2026-10-02): on a
180
+ * phone the card is ~230px and the row read "Title Review… → Review4 tas…".
181
+ * Values wrap; below a 20rem container the label, the old value and the new
182
+ * value stack, one per line. Measured on the list's own width (a container
183
+ * query), so a narrow window panel on a desktop gets the same stacking.
153
184
  */
154
185
  declare function DirectiveChangeList({ changes, className, }: {
155
186
  changes: ItemChange[];
@@ -232,4 +263,4 @@ declare function noteRecordChanged(id: string): void;
232
263
  declare function useRecordRevision(id: string): number;
233
264
  declare function useRecordValues(read: RecordReader | undefined, ref: DirectiveRecordRef | null): RecordValues;
234
265
 
235
- export { ApplyDirectiveButton, type ApplyDirectiveButtonProps, CHANGE_VALUE_MAX, type ChangeValue, type DirectiveApplyPhase, DirectiveChangeList, DirectiveFailure, DirectiveFailureWords, DirectiveFallbackCard, type DirectiveFallbackCardProps, DirectiveProvisionalCard, type DirectiveProvisionalCardProps, DirectiveRecordRef, DirectiveRender, type DirectiveRenderProps, type DirectiveRenderer, type DirectiveRendererProps, type ItemChange, type ItemChangesOptions, type RecordReader, type RecordValues, type RecordValuesStatus, SideEffectDirectiveCard, type SideEffectDirectiveCardProps, TARGETING_CLASSES, defaultFailureWords, describeChangeValue, failureWords, fieldLabel, getDirectiveRenderer, itemChanges, itemRecordId, noteRecordChanged, provisionalDirectiveSlug, readsApplyLedger, recordFallbackName, recordRevision, registerDirectiveRenderer, resetDirectiveRenderers, useRecordRevision, useRecordValues };
266
+ export { ApplyDirectiveButton, type ApplyDirectiveButtonProps, CHANGE_VALUE_MAX, type ChangeValue, type DirectiveApplyPhase, DirectiveChangeList, DirectiveFailure, DirectiveFailureWords, DirectiveFallbackCard, type DirectiveFallbackCardProps, DirectiveHost, DirectiveProvisionalCard, type DirectiveProvisionalCardProps, DirectiveRecordRef, DirectiveRender, type DirectiveRenderProps, type DirectiveRenderer, type DirectiveRendererProps, type DirectiveValueWord, EMPTY_VALUE_WORD, type ItemChange, type ItemChangesOptions, type RecordReader, type RecordValues, type RecordValuesStatus, SideEffectDirectiveCard, type SideEffectDirectiveCardProps, TARGETING_CLASSES, defaultFailureWords, describeChangeValue, directiveFieldLabel, directiveValueWord, failureWords, fieldLabel, getDirectiveRenderer, itemChanges, itemRecordId, noteRecordChanged, provisionalDirectiveSlug, readsApplyLedger, recordFallbackName, recordRevision, registerDirectiveRenderer, resetDirectiveRenderers, useRecordRevision, useRecordValues };
@@ -1,5 +1,5 @@
1
- import { D as DirectiveFailure, a as DirectiveFailureWords, b as DirectiveRecordRef } from './directive-host-Bw2_PrgL.js';
2
- export { c as DirectiveApplyResult, d as DirectiveApplyState, e as DirectiveAskRequest, f as DirectiveCopyProps, g as DirectiveHost, h as DirectiveHostProvider, i as DirectiveHostProviderProps, j as DirectiveOpenItemOptions, k as DirectiveRecordProps, l as DirectiveScope, m as DirectiveScopeProvider, n as DirectiveShell, u as useDirectiveHost, o as useDirectiveScope } from './directive-host-Bw2_PrgL.js';
1
+ import { D as DirectiveHost, a as DirectiveFailure, b as DirectiveFailureWords, c as DirectiveRecordRef } from './directive-host-B1hcjJxS.js';
2
+ export { d as DirectiveApplyResult, e as DirectiveApplyState, f as DirectiveAskRequest, g as DirectiveCopyProps, h as DirectiveHostProvider, i as DirectiveHostProviderProps, j as DirectiveOpenItemOptions, k as DirectiveRecordProps, l as DirectiveScope, m as DirectiveScopeProvider, n as DirectiveShell, o as DirectiveValueRef, u as useDirectiveHost, p as useDirectiveScope } from './directive-host-B1hcjJxS.js';
3
3
  import * as react from 'react';
4
4
  import { ComponentType } from 'react';
5
5
  import { DecodedDirective, DirectiveClass } from '@ai-matrx/content-ir';
@@ -94,12 +94,33 @@ declare function ApplyDirectiveButton({ directive, label, itemCount, onApplied,
94
94
  */
95
95
  /** Classes whose items point at an EXISTING record by `id`. */
96
96
  declare const TARGETING_CLASSES: ReadonlySet<string>;
97
- /** How long a changed value may read before it is shortened (full value on hover). */
98
- declare const CHANGE_VALUE_MAX = 60;
97
+ /**
98
+ * How long a changed value may read before it is shortened. A value someone
99
+ * must judge — a title, a status, a date — is always whole (G8A review: a 60
100
+ * cap plus CSS truncation cut "Review4 tasks…" on a phone); only a body of
101
+ * prose longer than this is shortened, whole on hover and in View/Copy.
102
+ */
103
+ declare const CHANGE_VALUE_MAX = 280;
99
104
  /** The id of the existing record an update/delete item targets, or null. */
100
105
  declare function itemRecordId(item: Record<string, unknown>): string | null;
101
- /** "due_date" → "Due date". Underscores read as developer output. */
106
+ /** "due_date" → "Due Date" — THE humanizer; underscores read as developer output. */
102
107
  declare function fieldLabel(key: string): string;
108
+ /**
109
+ * THE ONE FIELD-LABEL RULE for a directive — card rows, card facts and the
110
+ * host's confirm: the noun's title column reads "Title" whatever it is stored
111
+ * as (a workbook's `workbook_name`, a note's `label`), every other field reads
112
+ * through THE humanizer. A new workbook card said "workbook name" while its
113
+ * confirm said "Title" (G8A review, 2026-10-02).
114
+ */
115
+ declare function directiveFieldLabel(key: string, titleColumn: string | null | undefined): string;
116
+ /**
117
+ * The app's word for ONE stored value of ONE field — "incomplete" on a task
118
+ * reads "Inbox", "high" reads "High". The host answers it for its pick-list
119
+ * fields; null → the value as stored.
120
+ */
121
+ type DirectiveValueWord = (field: string, value: string) => string | null;
122
+ /** How an empty value reads — before or after, on the card and in the confirm. */
123
+ declare const EMPTY_VALUE_WORD = "None";
103
124
  /** A short, honest name for a record we could not look up: "Task 1a2b3c4d". */
104
125
  declare function recordFallbackName(nounLabel: string, id: string): string;
105
126
  /** One value as a row reads it: shortened, the whole of it, and whether it is empty. */
@@ -122,7 +143,7 @@ interface ItemChange extends ChangeValue {
122
143
  same?: boolean;
123
144
  }
124
145
  /** One value, described for a change row (`value` shortened, `full` whole). */
125
- declare function describeChangeValue(value: unknown): ChangeValue;
146
+ declare function describeChangeValue(value: unknown, word?: (value: string) => string | null): ChangeValue;
126
147
  /**
127
148
  * Every field an UPDATE item sets, in the order the item carries them — ALL of
128
149
  * them, never a sample: a person approving an overwrite sees the whole of it.
@@ -139,17 +160,27 @@ interface ItemChangesOptions {
139
160
  * (reviewer, 2026-10-02). The same rule the directive builder's form uses.
140
161
  */
141
162
  titleColumn?: string | null;
163
+ /** The app's word for a stored value (`DirectiveHost.valueLabel`, bound to the noun). */
164
+ valueWord?: DirectiveValueWord | null;
142
165
  }
143
166
  declare function itemChanges(item: Record<string, unknown>, current?: Record<string, unknown> | null, options?: ItemChangesOptions): ItemChange[];
144
167
 
145
168
  interface SideEffectDirectiveCardProps {
146
169
  directive: DecodedDirective;
147
170
  }
171
+ /** The host's value words for one record type, or null when it has none. */
172
+ declare function directiveValueWord(host: Pick<DirectiveHost, "valueLabel">, noun: string): DirectiveValueWord | null;
148
173
  /**
149
174
  * THE CHANGE LIST — every field an update sets, as "Label old → new" when the
150
175
  * record's current value is known, "Label → new" when it is not. ONE component
151
176
  * for the card row and the host's confirm dialog, so the two can never read
152
177
  * differently (reviewer, 2026-10-02: the confirm showed only the new value).
178
+ *
179
+ * 🚨 A VALUE SOMEONE MUST JUDGE IS NEVER CUT (G8A review, 2026-10-02): on a
180
+ * phone the card is ~230px and the row read "Title Review… → Review4 tas…".
181
+ * Values wrap; below a 20rem container the label, the old value and the new
182
+ * value stack, one per line. Measured on the list's own width (a container
183
+ * query), so a narrow window panel on a desktop gets the same stacking.
153
184
  */
154
185
  declare function DirectiveChangeList({ changes, className, }: {
155
186
  changes: ItemChange[];
@@ -232,4 +263,4 @@ declare function noteRecordChanged(id: string): void;
232
263
  declare function useRecordRevision(id: string): number;
233
264
  declare function useRecordValues(read: RecordReader | undefined, ref: DirectiveRecordRef | null): RecordValues;
234
265
 
235
- export { ApplyDirectiveButton, type ApplyDirectiveButtonProps, CHANGE_VALUE_MAX, type ChangeValue, type DirectiveApplyPhase, DirectiveChangeList, DirectiveFailure, DirectiveFailureWords, DirectiveFallbackCard, type DirectiveFallbackCardProps, DirectiveProvisionalCard, type DirectiveProvisionalCardProps, DirectiveRecordRef, DirectiveRender, type DirectiveRenderProps, type DirectiveRenderer, type DirectiveRendererProps, type ItemChange, type ItemChangesOptions, type RecordReader, type RecordValues, type RecordValuesStatus, SideEffectDirectiveCard, type SideEffectDirectiveCardProps, TARGETING_CLASSES, defaultFailureWords, describeChangeValue, failureWords, fieldLabel, getDirectiveRenderer, itemChanges, itemRecordId, noteRecordChanged, provisionalDirectiveSlug, readsApplyLedger, recordFallbackName, recordRevision, registerDirectiveRenderer, resetDirectiveRenderers, useRecordRevision, useRecordValues };
266
+ export { ApplyDirectiveButton, type ApplyDirectiveButtonProps, CHANGE_VALUE_MAX, type ChangeValue, type DirectiveApplyPhase, DirectiveChangeList, DirectiveFailure, DirectiveFailureWords, DirectiveFallbackCard, type DirectiveFallbackCardProps, DirectiveHost, DirectiveProvisionalCard, type DirectiveProvisionalCardProps, DirectiveRecordRef, DirectiveRender, type DirectiveRenderProps, type DirectiveRenderer, type DirectiveRendererProps, type DirectiveValueWord, EMPTY_VALUE_WORD, type ItemChange, type ItemChangesOptions, type RecordReader, type RecordValues, type RecordValuesStatus, SideEffectDirectiveCard, type SideEffectDirectiveCardProps, TARGETING_CLASSES, defaultFailureWords, describeChangeValue, directiveFieldLabel, directiveValueWord, failureWords, fieldLabel, getDirectiveRenderer, itemChanges, itemRecordId, noteRecordChanged, provisionalDirectiveSlug, readsApplyLedger, recordFallbackName, recordRevision, registerDirectiveRenderer, resetDirectiveRenderers, useRecordRevision, useRecordValues };
@@ -49,9 +49,10 @@ import { nounLabel } from "@ai-matrx/content-ir";
49
49
 
50
50
  // directives/item-changes.ts
51
51
  import { isUuidShape } from "@ai-matrx/kit/uuid";
52
+ import { humanizeIdentifier } from "@ai-matrx/kit/text-case";
52
53
  var TARGETING_CLASSES = /* @__PURE__ */ new Set(["update", "delete"]);
53
54
  var NOT_A_CHANGE = /* @__PURE__ */ new Set(["__kind", "id"]);
54
- var CHANGE_VALUE_MAX = 60;
55
+ var CHANGE_VALUE_MAX = 280;
55
56
  function itemRecordId(item) {
56
57
  const id = item.id;
57
58
  if (typeof id === "string" && id.trim()) return id.trim();
@@ -59,21 +60,27 @@ function itemRecordId(item) {
59
60
  return null;
60
61
  }
61
62
  function fieldLabel(key) {
62
- const spaced = key.replace(/_/g, " ").trim();
63
- return spaced.charAt(0).toUpperCase() + spaced.slice(1);
63
+ return humanizeIdentifier(key) || key;
64
64
  }
65
+ function directiveFieldLabel(key, titleColumn) {
66
+ return titleColumn && key === titleColumn ? "Title" : fieldLabel(key);
67
+ }
68
+ var EMPTY_VALUE_WORD = "None";
65
69
  function recordFallbackName(nounLabel3, id) {
66
70
  const short = isUuidShape(id) ? id.slice(0, 8) : id.length > 12 ? `${id.slice(0, 12)}\u2026` : id;
67
71
  return `${nounLabel3} ${short}`;
68
72
  }
69
- function describeChangeValue(value) {
70
- return describeValue(value);
73
+ function describeChangeValue(value, word) {
74
+ return describeValue(value, word);
71
75
  }
72
- function describeValue(value) {
73
- if (value === null || value === void 0) return { value: "cleared", full: "cleared", clears: true };
76
+ var EMPTY = { value: EMPTY_VALUE_WORD, full: EMPTY_VALUE_WORD, clears: true };
77
+ function describeValue(value, word) {
78
+ if (value === null || value === void 0) return EMPTY;
74
79
  if (typeof value === "string") {
75
80
  const trimmed = value.trim();
76
- if (!trimmed) return { value: "cleared", full: "cleared", clears: true };
81
+ if (!trimmed) return EMPTY;
82
+ const named = word?.(trimmed) ?? null;
83
+ if (named) return { value: named, full: named, clears: false };
77
84
  const oneLine = trimmed.replace(/\s+/g, " ");
78
85
  const shown = oneLine.length > CHANGE_VALUE_MAX ? `${oneLine.slice(0, CHANGE_VALUE_MAX - 1)}\u2026` : oneLine;
79
86
  return { value: shown, full: trimmed, clears: false };
@@ -83,11 +90,11 @@ function describeValue(value) {
83
90
  }
84
91
  if (Array.isArray(value)) {
85
92
  const n2 = value.length;
86
- const text2 = n2 === 0 ? "cleared" : `${n2} ${n2 === 1 ? "entry" : "entries"}`;
93
+ const text2 = n2 === 0 ? EMPTY_VALUE_WORD : `${n2} ${n2 === 1 ? "entry" : "entries"}`;
87
94
  return { value: text2, full: safeJson(value), clears: n2 === 0 };
88
95
  }
89
96
  const n = Object.keys(value).length;
90
- const text = n === 0 ? "cleared" : `${n} ${n === 1 ? "field" : "fields"}`;
97
+ const text = n === 0 ? EMPTY_VALUE_WORD : `${n} ${n === 1 ? "field" : "fields"}`;
91
98
  return { value: text, full: safeJson(value), clears: n === 0 };
92
99
  }
93
100
  function safeJson(value) {
@@ -112,10 +119,12 @@ function itemChanges(item, current, options = {}) {
112
119
  const titleColumn = options.titleColumn ?? null;
113
120
  for (const [key, raw] of Object.entries(item)) {
114
121
  if (NOT_A_CHANGE.has(key)) continue;
115
- const label = key === titleColumn ? "Title" : fieldLabel(key);
116
- const change = { key, label, ...describeValue(raw) };
122
+ const label = directiveFieldLabel(key, titleColumn);
123
+ const valueWord = options.valueWord;
124
+ const word = key === titleColumn || !valueWord ? void 0 : (v) => valueWord(key, v);
125
+ const change = { key, label, ...describeValue(raw, word) };
117
126
  if (current && Object.prototype.hasOwnProperty.call(current, key)) {
118
- change.before = describeValue(current[key]);
127
+ change.before = describeValue(current[key], word);
119
128
  change.same = sameValue(current[key], raw);
120
129
  }
121
130
  out.push(change);
@@ -701,6 +710,14 @@ import {
701
710
  nounTitleColumn
702
711
  } from "@ai-matrx/content-ir";
703
712
  import { Fragment, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
713
+ function directiveValueWord(host, noun) {
714
+ const valueLabel = host.valueLabel;
715
+ return valueLabel ? (field, value) => valueLabel({ noun, field, value }) : null;
716
+ }
717
+ function omitKey(item, key) {
718
+ const { [key]: _omitted, ...rest } = item;
719
+ return rest;
720
+ }
704
721
  var ROWS_BEFORE_FOLD = 3;
705
722
  function ItemRow({
706
723
  directive,
@@ -717,16 +734,21 @@ function ItemRow({
717
734
  const titleColumn = nounTitleColumn(directive.noun, host.nouns);
718
735
  const title = itemTitle(item, titleColumn, index, total);
719
736
  const subtitle = itemSubtitle(item);
720
- const facts = itemFacts(item);
737
+ const valueWord = directiveValueWord(host, directive.noun);
738
+ const facts = itemFacts(titleColumn ? omitKey(item, titleColumn) : item).map((fact) => ({
739
+ ...fact,
740
+ label: directiveFieldLabel(fact.key, titleColumn),
741
+ value: valueWord?.(fact.key, fact.value) ?? fact.value
742
+ }));
721
743
  const kind = host.itemKind?.(directive.slug) ?? null;
722
744
  const display = directiveDisplay(directive.directiveClass, directive.noun, host.nouns);
723
745
  const openItem = host.openItem;
724
746
  const body = /* @__PURE__ */ jsxs3(Fragment, { children: [
725
747
  /* @__PURE__ */ jsx4("span", { className: "min-w-0 shrink-0 truncate font-medium text-foreground", children: title }),
726
- /* @__PURE__ */ jsx4("span", { className: "hidden min-w-0 flex-1 items-baseline gap-2 overflow-hidden sm:flex", children: facts.map((fact) => /* @__PURE__ */ jsxs3("span", { className: "truncate text-[11px] text-muted-foreground", children: [
727
- fact.value,
748
+ /* @__PURE__ */ jsx4("span", { className: "hidden min-w-0 flex-1 items-baseline gap-2 overflow-hidden sm:flex", children: facts.map((fact) => /* @__PURE__ */ jsxs3("span", { className: "truncate text-[11px] text-muted-foreground", "data-item-fact": fact.key, children: [
749
+ fact.label,
728
750
  " ",
729
- fact.label
751
+ /* @__PURE__ */ jsx4("span", { className: "text-foreground/80", children: fact.value })
730
752
  ] }, fact.key)) }),
731
753
  subtitle && facts.length === 0 ? /* @__PURE__ */ jsx4("span", { className: "hidden truncate text-[11px] text-muted-foreground sm:inline", children: subtitle }) : null,
732
754
  openItem ? /* @__PURE__ */ jsx4(MaximizeIcon, { className: "ml-auto h-3 w-3 shrink-0 text-muted-foreground" }) : null
@@ -761,35 +783,36 @@ function DirectiveChangeList({
761
783
  if (changes.length === 0) {
762
784
  return /* @__PURE__ */ jsx4("p", { className: `text-[11px] text-muted-foreground${className ? ` ${className}` : ""}`, children: "Sets no fields \u2014 nothing would change." });
763
785
  }
764
- return /* @__PURE__ */ jsx4("ul", { className: `space-y-0.5${className ? ` ${className}` : ""}`, "data-directive-changes": "", children: changes.map((change) => {
786
+ return /* @__PURE__ */ jsx4("ul", { className: `@container space-y-1${className ? ` ${className}` : ""}`, "data-directive-changes": "", children: changes.map((change) => {
765
787
  const before = change.before && !change.same ? change.before : null;
766
- const was = before ? before.clears ? "empty" : before.value : null;
767
788
  return /* @__PURE__ */ jsxs3(
768
789
  "li",
769
790
  {
770
- className: "flex min-w-0 items-baseline gap-1.5 text-[11px]",
771
- title: before ? `${change.label}: ${before.clears ? "empty" : before.full} \u2192 ${change.full}` : `${change.label} \u2192 ${change.full}`,
791
+ className: "flex min-w-0 flex-col text-[11px] @xs:flex-row @xs:flex-wrap @xs:items-baseline @xs:gap-x-1.5",
792
+ title: before ? `${change.label}: ${before.full} \u2192 ${change.full}` : `${change.label} \u2192 ${change.full}`,
772
793
  "data-change-key": change.key,
773
794
  children: [
774
795
  /* @__PURE__ */ jsx4("span", { className: "shrink-0 text-muted-foreground", children: change.label }),
775
- was !== null ? /* @__PURE__ */ jsx4(
796
+ before ? /* @__PURE__ */ jsx4(
776
797
  "span",
777
798
  {
778
- className: "min-w-0 max-w-[40%] shrink truncate text-muted-foreground line-through",
799
+ className: "min-w-0 text-muted-foreground line-through [overflow-wrap:anywhere]",
779
800
  "data-change-before": "",
780
- children: was
801
+ children: before.value
781
802
  }
782
803
  ) : null,
783
- /* @__PURE__ */ jsx4("span", { "aria-hidden": true, className: "shrink-0 text-muted-foreground", children: "\u2192" }),
784
- /* @__PURE__ */ jsx4(
785
- "span",
786
- {
787
- className: `min-w-0 truncate ${change.clears ? "italic text-muted-foreground" : "text-foreground"}`,
788
- "data-change-after": "",
789
- children: change.value
790
- }
791
- ),
792
- change.same ? /* @__PURE__ */ jsx4("span", { className: "shrink-0 text-muted-foreground", children: "(no change)" }) : null
804
+ /* @__PURE__ */ jsxs3("span", { className: "flex min-w-0 items-baseline gap-1.5", children: [
805
+ /* @__PURE__ */ jsx4("span", { "aria-hidden": true, className: "shrink-0 text-muted-foreground", children: "\u2192" }),
806
+ /* @__PURE__ */ jsx4(
807
+ "span",
808
+ {
809
+ className: `min-w-0 [overflow-wrap:anywhere] ${change.clears ? "italic text-muted-foreground" : "text-foreground"}`,
810
+ "data-change-after": "",
811
+ children: change.value
812
+ }
813
+ ),
814
+ change.same ? /* @__PURE__ */ jsx4("span", { className: "shrink-0 text-muted-foreground", children: "(no change)" }) : null
815
+ ] })
793
816
  ]
794
817
  },
795
818
  change.key
@@ -812,7 +835,10 @@ function TargetRow({
812
835
  readsLive ? { noun: directive.noun, id: recordId } : null
813
836
  );
814
837
  const compareTo = phase.phase === "applied" ? phase.before?.[index] ?? null : readsLive ? live.values : null;
815
- const changes = isUpdate ? itemChanges(item, compareTo, { titleColumn: nounTitleColumn(directive.noun, host.nouns) }) : [];
838
+ const changes = isUpdate ? itemChanges(item, compareTo, {
839
+ titleColumn: nounTitleColumn(directive.noun, host.nouns),
840
+ valueWord: directiveValueWord(host, directive.noun)
841
+ }) : [];
816
842
  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 });
817
843
  return /* @__PURE__ */ jsxs3("div", { className: "py-1 text-xs", "data-directive-target": recordId, children: [
818
844
  /* @__PURE__ */ jsxs3("div", { className: "flex min-w-0 items-center gap-2", children: [
@@ -994,10 +1020,13 @@ export {
994
1020
  DirectiveProvisionalCard,
995
1021
  DirectiveRender,
996
1022
  DirectiveScopeProvider,
1023
+ EMPTY_VALUE_WORD,
997
1024
  SideEffectDirectiveCard,
998
1025
  TARGETING_CLASSES,
999
1026
  defaultFailureWords,
1000
1027
  describeChangeValue,
1028
+ directiveFieldLabel,
1029
+ directiveValueWord,
1001
1030
  failureWords,
1002
1031
  fieldLabel,
1003
1032
  getDirectiveRenderer,