@ai-matrx/content-ir-react 0.19.0 → 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);
@@ -125,8 +134,17 @@ function itemChanges(item, current, options = {}) {
125
134
 
126
135
  // directives/record-values.ts
127
136
  import { useEffect, useState, useSyncExternalStore } from "react";
128
- var revisions = /* @__PURE__ */ new Map();
129
- var listeners = /* @__PURE__ */ new Set();
137
+ var STORE_SLOT = /* @__PURE__ */ Symbol.for("@ai-matrx/content-ir-react/record-revisions");
138
+ function revisionStore() {
139
+ const slots = globalThis;
140
+ let store = slots[STORE_SLOT];
141
+ if (!store) {
142
+ store = { revisions: /* @__PURE__ */ new Map(), listeners: /* @__PURE__ */ new Set() };
143
+ slots[STORE_SLOT] = store;
144
+ }
145
+ return store;
146
+ }
147
+ var { revisions, listeners } = revisionStore();
130
148
  function recordRevision(id) {
131
149
  return revisions.get(id) ?? 0;
132
150
  }
@@ -692,6 +710,14 @@ import {
692
710
  nounTitleColumn
693
711
  } from "@ai-matrx/content-ir";
694
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
+ }
695
721
  var ROWS_BEFORE_FOLD = 3;
696
722
  function ItemRow({
697
723
  directive,
@@ -708,16 +734,21 @@ function ItemRow({
708
734
  const titleColumn = nounTitleColumn(directive.noun, host.nouns);
709
735
  const title = itemTitle(item, titleColumn, index, total);
710
736
  const subtitle = itemSubtitle(item);
711
- 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
+ }));
712
743
  const kind = host.itemKind?.(directive.slug) ?? null;
713
744
  const display = directiveDisplay(directive.directiveClass, directive.noun, host.nouns);
714
745
  const openItem = host.openItem;
715
746
  const body = /* @__PURE__ */ jsxs3(Fragment, { children: [
716
747
  /* @__PURE__ */ jsx4("span", { className: "min-w-0 shrink-0 truncate font-medium text-foreground", children: title }),
717
- /* @__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: [
718
- 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,
719
750
  " ",
720
- fact.label
751
+ /* @__PURE__ */ jsx4("span", { className: "text-foreground/80", children: fact.value })
721
752
  ] }, fact.key)) }),
722
753
  subtitle && facts.length === 0 ? /* @__PURE__ */ jsx4("span", { className: "hidden truncate text-[11px] text-muted-foreground sm:inline", children: subtitle }) : null,
723
754
  openItem ? /* @__PURE__ */ jsx4(MaximizeIcon, { className: "ml-auto h-3 w-3 shrink-0 text-muted-foreground" }) : null
@@ -752,35 +783,36 @@ function DirectiveChangeList({
752
783
  if (changes.length === 0) {
753
784
  return /* @__PURE__ */ jsx4("p", { className: `text-[11px] text-muted-foreground${className ? ` ${className}` : ""}`, children: "Sets no fields \u2014 nothing would change." });
754
785
  }
755
- 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) => {
756
787
  const before = change.before && !change.same ? change.before : null;
757
- const was = before ? before.clears ? "empty" : before.value : null;
758
788
  return /* @__PURE__ */ jsxs3(
759
789
  "li",
760
790
  {
761
- className: "flex min-w-0 items-baseline gap-1.5 text-[11px]",
762
- 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}`,
763
793
  "data-change-key": change.key,
764
794
  children: [
765
795
  /* @__PURE__ */ jsx4("span", { className: "shrink-0 text-muted-foreground", children: change.label }),
766
- was !== null ? /* @__PURE__ */ jsx4(
796
+ before ? /* @__PURE__ */ jsx4(
767
797
  "span",
768
798
  {
769
- 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]",
770
800
  "data-change-before": "",
771
- children: was
801
+ children: before.value
772
802
  }
773
803
  ) : null,
774
- /* @__PURE__ */ jsx4("span", { "aria-hidden": true, className: "shrink-0 text-muted-foreground", children: "\u2192" }),
775
- /* @__PURE__ */ jsx4(
776
- "span",
777
- {
778
- className: `min-w-0 truncate ${change.clears ? "italic text-muted-foreground" : "text-foreground"}`,
779
- "data-change-after": "",
780
- children: change.value
781
- }
782
- ),
783
- 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
+ ] })
784
816
  ]
785
817
  },
786
818
  change.key
@@ -803,7 +835,10 @@ function TargetRow({
803
835
  readsLive ? { noun: directive.noun, id: recordId } : null
804
836
  );
805
837
  const compareTo = phase.phase === "applied" ? phase.before?.[index] ?? null : readsLive ? live.values : null;
806
- 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
+ }) : [];
807
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 });
808
843
  return /* @__PURE__ */ jsxs3("div", { className: "py-1 text-xs", "data-directive-target": recordId, children: [
809
844
  /* @__PURE__ */ jsxs3("div", { className: "flex min-w-0 items-center gap-2", children: [
@@ -985,10 +1020,13 @@ export {
985
1020
  DirectiveProvisionalCard,
986
1021
  DirectiveRender,
987
1022
  DirectiveScopeProvider,
1023
+ EMPTY_VALUE_WORD,
988
1024
  SideEffectDirectiveCard,
989
1025
  TARGETING_CLASSES,
990
1026
  defaultFailureWords,
991
1027
  describeChangeValue,
1028
+ directiveFieldLabel,
1029
+ directiveValueWord,
992
1030
  failureWords,
993
1031
  fieldLabel,
994
1032
  getDirectiveRenderer,