@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.
package/dist/react.cjs CHANGED
@@ -139,9 +139,10 @@ var import_content_ir = require("@ai-matrx/content-ir");
139
139
 
140
140
  // directives/item-changes.ts
141
141
  var import_uuid = require("@ai-matrx/kit/uuid");
142
+ var import_text_case = require("@ai-matrx/kit/text-case");
142
143
  var TARGETING_CLASSES = /* @__PURE__ */ new Set(["update", "delete"]);
143
144
  var NOT_A_CHANGE = /* @__PURE__ */ new Set(["__kind", "id"]);
144
- var CHANGE_VALUE_MAX = 60;
145
+ var CHANGE_VALUE_MAX = 280;
145
146
  function itemRecordId(item) {
146
147
  const id = item.id;
147
148
  if (typeof id === "string" && id.trim()) return id.trim();
@@ -149,18 +150,24 @@ function itemRecordId(item) {
149
150
  return null;
150
151
  }
151
152
  function fieldLabel(key) {
152
- const spaced = key.replace(/_/g, " ").trim();
153
- return spaced.charAt(0).toUpperCase() + spaced.slice(1);
153
+ return (0, import_text_case.humanizeIdentifier)(key) || key;
154
154
  }
155
+ function directiveFieldLabel(key, titleColumn) {
156
+ return titleColumn && key === titleColumn ? "Title" : fieldLabel(key);
157
+ }
158
+ var EMPTY_VALUE_WORD = "None";
155
159
  function recordFallbackName(nounLabel3, id) {
156
160
  const short = (0, import_uuid.isUuidShape)(id) ? id.slice(0, 8) : id.length > 12 ? `${id.slice(0, 12)}\u2026` : id;
157
161
  return `${nounLabel3} ${short}`;
158
162
  }
159
- function describeValue(value) {
160
- if (value === null || value === void 0) return { value: "cleared", full: "cleared", clears: true };
163
+ var EMPTY = { value: EMPTY_VALUE_WORD, full: EMPTY_VALUE_WORD, clears: true };
164
+ function describeValue(value, word) {
165
+ if (value === null || value === void 0) return EMPTY;
161
166
  if (typeof value === "string") {
162
167
  const trimmed = value.trim();
163
- if (!trimmed) return { value: "cleared", full: "cleared", clears: true };
168
+ if (!trimmed) return EMPTY;
169
+ const named = word?.(trimmed) ?? null;
170
+ if (named) return { value: named, full: named, clears: false };
164
171
  const oneLine = trimmed.replace(/\s+/g, " ");
165
172
  const shown = oneLine.length > CHANGE_VALUE_MAX ? `${oneLine.slice(0, CHANGE_VALUE_MAX - 1)}\u2026` : oneLine;
166
173
  return { value: shown, full: trimmed, clears: false };
@@ -170,11 +177,11 @@ function describeValue(value) {
170
177
  }
171
178
  if (Array.isArray(value)) {
172
179
  const n2 = value.length;
173
- const text2 = n2 === 0 ? "cleared" : `${n2} ${n2 === 1 ? "entry" : "entries"}`;
180
+ const text2 = n2 === 0 ? EMPTY_VALUE_WORD : `${n2} ${n2 === 1 ? "entry" : "entries"}`;
174
181
  return { value: text2, full: safeJson(value), clears: n2 === 0 };
175
182
  }
176
183
  const n = Object.keys(value).length;
177
- const text = n === 0 ? "cleared" : `${n} ${n === 1 ? "field" : "fields"}`;
184
+ const text = n === 0 ? EMPTY_VALUE_WORD : `${n} ${n === 1 ? "field" : "fields"}`;
178
185
  return { value: text, full: safeJson(value), clears: n === 0 };
179
186
  }
180
187
  function safeJson(value) {
@@ -199,10 +206,12 @@ function itemChanges(item, current, options = {}) {
199
206
  const titleColumn = options.titleColumn ?? null;
200
207
  for (const [key, raw] of Object.entries(item)) {
201
208
  if (NOT_A_CHANGE.has(key)) continue;
202
- const label = key === titleColumn ? "Title" : fieldLabel(key);
203
- const change = { key, label, ...describeValue(raw) };
209
+ const label = directiveFieldLabel(key, titleColumn);
210
+ const valueWord = options.valueWord;
211
+ const word = key === titleColumn || !valueWord ? void 0 : (v) => valueWord(key, v);
212
+ const change = { key, label, ...describeValue(raw, word) };
204
213
  if (current && Object.prototype.hasOwnProperty.call(current, key)) {
205
- change.before = describeValue(current[key]);
214
+ change.before = describeValue(current[key], word);
206
215
  change.same = sameValue(current[key], raw);
207
216
  }
208
217
  out.push(change);
@@ -212,8 +221,17 @@ function itemChanges(item, current, options = {}) {
212
221
 
213
222
  // directives/record-values.ts
214
223
  var import_react4 = require("react");
215
- var revisions = /* @__PURE__ */ new Map();
216
- var listeners = /* @__PURE__ */ new Set();
224
+ var STORE_SLOT = /* @__PURE__ */ Symbol.for("@ai-matrx/content-ir-react/record-revisions");
225
+ function revisionStore() {
226
+ const slots = globalThis;
227
+ let store = slots[STORE_SLOT];
228
+ if (!store) {
229
+ store = { revisions: /* @__PURE__ */ new Map(), listeners: /* @__PURE__ */ new Set() };
230
+ slots[STORE_SLOT] = store;
231
+ }
232
+ return store;
233
+ }
234
+ var { revisions, listeners } = revisionStore();
217
235
  function recordRevision(id) {
218
236
  return revisions.get(id) ?? 0;
219
237
  }
@@ -849,6 +867,14 @@ function getDirectiveRenderer(directive) {
849
867
  var import_react6 = require("react");
850
868
  var import_content_ir5 = require("@ai-matrx/content-ir");
851
869
  var import_jsx_runtime7 = require("react/jsx-runtime");
870
+ function directiveValueWord(host, noun) {
871
+ const valueLabel = host.valueLabel;
872
+ return valueLabel ? (field, value) => valueLabel({ noun, field, value }) : null;
873
+ }
874
+ function omitKey(item, key) {
875
+ const { [key]: _omitted, ...rest } = item;
876
+ return rest;
877
+ }
852
878
  var ROWS_BEFORE_FOLD = 3;
853
879
  function ItemRow({
854
880
  directive,
@@ -865,16 +891,21 @@ function ItemRow({
865
891
  const titleColumn = (0, import_content_ir5.nounTitleColumn)(directive.noun, host.nouns);
866
892
  const title = (0, import_content_ir5.itemTitle)(item, titleColumn, index, total);
867
893
  const subtitle = (0, import_content_ir5.itemSubtitle)(item);
868
- const facts = (0, import_content_ir5.itemFacts)(item);
894
+ const valueWord = directiveValueWord(host, directive.noun);
895
+ const facts = (0, import_content_ir5.itemFacts)(titleColumn ? omitKey(item, titleColumn) : item).map((fact) => ({
896
+ ...fact,
897
+ label: directiveFieldLabel(fact.key, titleColumn),
898
+ value: valueWord?.(fact.key, fact.value) ?? fact.value
899
+ }));
869
900
  const kind = host.itemKind?.(directive.slug) ?? null;
870
901
  const display = (0, import_content_ir5.directiveDisplay)(directive.directiveClass, directive.noun, host.nouns);
871
902
  const openItem = host.openItem;
872
903
  const body = /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
873
904
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "min-w-0 shrink-0 truncate font-medium text-foreground", children: title }),
874
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "hidden min-w-0 flex-1 items-baseline gap-2 overflow-hidden sm:flex", children: facts.map((fact) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "truncate text-[11px] text-muted-foreground", children: [
875
- fact.value,
905
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "hidden min-w-0 flex-1 items-baseline gap-2 overflow-hidden sm:flex", children: facts.map((fact) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "truncate text-[11px] text-muted-foreground", "data-item-fact": fact.key, children: [
906
+ fact.label,
876
907
  " ",
877
- fact.label
908
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-foreground/80", children: fact.value })
878
909
  ] }, fact.key)) }),
879
910
  subtitle && facts.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "hidden truncate text-[11px] text-muted-foreground sm:inline", children: subtitle }) : null,
880
911
  openItem ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MaximizeIcon, { className: "ml-auto h-3 w-3 shrink-0 text-muted-foreground" }) : null
@@ -909,35 +940,36 @@ function DirectiveChangeList({
909
940
  if (changes.length === 0) {
910
941
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: `text-[11px] text-muted-foreground${className ? ` ${className}` : ""}`, children: "Sets no fields \u2014 nothing would change." });
911
942
  }
912
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("ul", { className: `space-y-0.5${className ? ` ${className}` : ""}`, "data-directive-changes": "", children: changes.map((change) => {
943
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("ul", { className: `@container space-y-1${className ? ` ${className}` : ""}`, "data-directive-changes": "", children: changes.map((change) => {
913
944
  const before = change.before && !change.same ? change.before : null;
914
- const was = before ? before.clears ? "empty" : before.value : null;
915
945
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
916
946
  "li",
917
947
  {
918
- className: "flex min-w-0 items-baseline gap-1.5 text-[11px]",
919
- title: before ? `${change.label}: ${before.clears ? "empty" : before.full} \u2192 ${change.full}` : `${change.label} \u2192 ${change.full}`,
948
+ className: "flex min-w-0 flex-col text-[11px] @xs:flex-row @xs:flex-wrap @xs:items-baseline @xs:gap-x-1.5",
949
+ title: before ? `${change.label}: ${before.full} \u2192 ${change.full}` : `${change.label} \u2192 ${change.full}`,
920
950
  "data-change-key": change.key,
921
951
  children: [
922
952
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "shrink-0 text-muted-foreground", children: change.label }),
923
- was !== null ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
953
+ before ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
924
954
  "span",
925
955
  {
926
- className: "min-w-0 max-w-[40%] shrink truncate text-muted-foreground line-through",
956
+ className: "min-w-0 text-muted-foreground line-through [overflow-wrap:anywhere]",
927
957
  "data-change-before": "",
928
- children: was
958
+ children: before.value
929
959
  }
930
960
  ) : null,
931
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { "aria-hidden": true, className: "shrink-0 text-muted-foreground", children: "\u2192" }),
932
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
933
- "span",
934
- {
935
- className: `min-w-0 truncate ${change.clears ? "italic text-muted-foreground" : "text-foreground"}`,
936
- "data-change-after": "",
937
- children: change.value
938
- }
939
- ),
940
- change.same ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "shrink-0 text-muted-foreground", children: "(no change)" }) : null
961
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "flex min-w-0 items-baseline gap-1.5", children: [
962
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { "aria-hidden": true, className: "shrink-0 text-muted-foreground", children: "\u2192" }),
963
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
964
+ "span",
965
+ {
966
+ className: `min-w-0 [overflow-wrap:anywhere] ${change.clears ? "italic text-muted-foreground" : "text-foreground"}`,
967
+ "data-change-after": "",
968
+ children: change.value
969
+ }
970
+ ),
971
+ change.same ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "shrink-0 text-muted-foreground", children: "(no change)" }) : null
972
+ ] })
941
973
  ]
942
974
  },
943
975
  change.key
@@ -960,7 +992,10 @@ function TargetRow({
960
992
  readsLive ? { noun: directive.noun, id: recordId } : null
961
993
  );
962
994
  const compareTo = phase.phase === "applied" ? phase.before?.[index] ?? null : readsLive ? live.values : null;
963
- const changes = isUpdate ? itemChanges(item, compareTo, { titleColumn: (0, import_content_ir5.nounTitleColumn)(directive.noun, host.nouns) }) : [];
995
+ const changes = isUpdate ? itemChanges(item, compareTo, {
996
+ titleColumn: (0, import_content_ir5.nounTitleColumn)(directive.noun, host.nouns),
997
+ valueWord: directiveValueWord(host, directive.noun)
998
+ }) : [];
964
999
  const name = host.renderRecord ? host.renderRecord({ noun: directive.noun, id: recordId, fallback, context: "row" }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "truncate font-medium text-foreground", children: fallback });
965
1000
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "py-1 text-xs", "data-directive-target": recordId, children: [
966
1001
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex min-w-0 items-center gap-2", children: [