@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.
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);
@@ -858,6 +867,14 @@ function getDirectiveRenderer(directive) {
858
867
  var import_react6 = require("react");
859
868
  var import_content_ir5 = require("@ai-matrx/content-ir");
860
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
+ }
861
878
  var ROWS_BEFORE_FOLD = 3;
862
879
  function ItemRow({
863
880
  directive,
@@ -874,16 +891,21 @@ function ItemRow({
874
891
  const titleColumn = (0, import_content_ir5.nounTitleColumn)(directive.noun, host.nouns);
875
892
  const title = (0, import_content_ir5.itemTitle)(item, titleColumn, index, total);
876
893
  const subtitle = (0, import_content_ir5.itemSubtitle)(item);
877
- 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
+ }));
878
900
  const kind = host.itemKind?.(directive.slug) ?? null;
879
901
  const display = (0, import_content_ir5.directiveDisplay)(directive.directiveClass, directive.noun, host.nouns);
880
902
  const openItem = host.openItem;
881
903
  const body = /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
882
904
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "min-w-0 shrink-0 truncate font-medium text-foreground", children: title }),
883
- /* @__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: [
884
- 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,
885
907
  " ",
886
- fact.label
908
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-foreground/80", children: fact.value })
887
909
  ] }, fact.key)) }),
888
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,
889
911
  openItem ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MaximizeIcon, { className: "ml-auto h-3 w-3 shrink-0 text-muted-foreground" }) : null
@@ -918,35 +940,36 @@ function DirectiveChangeList({
918
940
  if (changes.length === 0) {
919
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." });
920
942
  }
921
- 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) => {
922
944
  const before = change.before && !change.same ? change.before : null;
923
- const was = before ? before.clears ? "empty" : before.value : null;
924
945
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
925
946
  "li",
926
947
  {
927
- className: "flex min-w-0 items-baseline gap-1.5 text-[11px]",
928
- 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}`,
929
950
  "data-change-key": change.key,
930
951
  children: [
931
952
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "shrink-0 text-muted-foreground", children: change.label }),
932
- was !== null ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
953
+ before ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
933
954
  "span",
934
955
  {
935
- 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]",
936
957
  "data-change-before": "",
937
- children: was
958
+ children: before.value
938
959
  }
939
960
  ) : null,
940
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { "aria-hidden": true, className: "shrink-0 text-muted-foreground", children: "\u2192" }),
941
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
942
- "span",
943
- {
944
- className: `min-w-0 truncate ${change.clears ? "italic text-muted-foreground" : "text-foreground"}`,
945
- "data-change-after": "",
946
- children: change.value
947
- }
948
- ),
949
- 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
+ ] })
950
973
  ]
951
974
  },
952
975
  change.key
@@ -969,7 +992,10 @@ function TargetRow({
969
992
  readsLive ? { noun: directive.noun, id: recordId } : null
970
993
  );
971
994
  const compareTo = phase.phase === "applied" ? phase.before?.[index] ?? null : readsLive ? live.values : null;
972
- 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
+ }) : [];
973
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 });
974
1000
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "py-1 text-xs", "data-directive-target": recordId, children: [
975
1001
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex min-w-0 items-center gap-2", children: [