@ai-matrx/content-ir-react 0.19.1 → 0.20.1

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.d.cts CHANGED
@@ -1,9 +1,9 @@
1
- import { c as KindDefinitionSource, C as ContentIrHost } from './host-types-YP_l_Q_t.cjs';
1
+ import { c as KindDefinitionSource, C as ContentIrHost } from './host-types-BRLk_J_3.cjs';
2
2
  import { d as ComponentResolutionSource } from './component-resolution.types-DwKSF64x.cjs';
3
3
  import * as react from 'react';
4
4
  import react__default, { ReactNode } from 'react';
5
5
  import '@ai-matrx/content-ir';
6
- import './directive-host-Bw2_PrgL.cjs';
6
+ import './directive-host-CtFMuSZc.cjs';
7
7
 
8
8
  /**
9
9
  * The two registries this hook watches. Passed explicitly by a host whose
package/dist/react.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { c as KindDefinitionSource, C as ContentIrHost } from './host-types-eSjFmXyF.js';
1
+ import { c as KindDefinitionSource, C as ContentIrHost } from './host-types-BpcRcZ48.js';
2
2
  import { d as ComponentResolutionSource } from './component-resolution.types-DwKSF64x.js';
3
3
  import * as react from 'react';
4
4
  import react__default, { ReactNode } from 'react';
5
5
  import '@ai-matrx/content-ir';
6
- import './directive-host-Bw2_PrgL.js';
6
+ import './directive-host-CtFMuSZc.js';
7
7
 
8
8
  /**
9
9
  * The two registries this hook watches. Passed explicitly by a host whose
package/dist/react.js CHANGED
@@ -99,9 +99,10 @@ import { nounLabel } from "@ai-matrx/content-ir";
99
99
 
100
100
  // directives/item-changes.ts
101
101
  import { isUuidShape } from "@ai-matrx/kit/uuid";
102
+ import { humanizeIdentifier } from "@ai-matrx/kit/text-case";
102
103
  var TARGETING_CLASSES = /* @__PURE__ */ new Set(["update", "delete"]);
103
104
  var NOT_A_CHANGE = /* @__PURE__ */ new Set(["__kind", "id"]);
104
- var CHANGE_VALUE_MAX = 60;
105
+ var CHANGE_VALUE_MAX = 280;
105
106
  function itemRecordId(item) {
106
107
  const id = item.id;
107
108
  if (typeof id === "string" && id.trim()) return id.trim();
@@ -109,18 +110,24 @@ function itemRecordId(item) {
109
110
  return null;
110
111
  }
111
112
  function fieldLabel(key) {
112
- const spaced = key.replace(/_/g, " ").trim();
113
- return spaced.charAt(0).toUpperCase() + spaced.slice(1);
113
+ return humanizeIdentifier(key) || key;
114
114
  }
115
+ function directiveFieldLabel(key, titleColumn) {
116
+ return titleColumn && key === titleColumn ? "Title" : fieldLabel(key);
117
+ }
118
+ var EMPTY_VALUE_WORD = "None";
115
119
  function recordFallbackName(nounLabel3, id) {
116
120
  const short = isUuidShape(id) ? id.slice(0, 8) : id.length > 12 ? `${id.slice(0, 12)}\u2026` : id;
117
121
  return `${nounLabel3} ${short}`;
118
122
  }
119
- function describeValue(value) {
120
- if (value === null || value === void 0) return { value: "cleared", full: "cleared", clears: true };
123
+ var EMPTY = { value: EMPTY_VALUE_WORD, full: EMPTY_VALUE_WORD, clears: true };
124
+ function describeValue(value, word) {
125
+ if (value === null || value === void 0) return EMPTY;
121
126
  if (typeof value === "string") {
122
127
  const trimmed = value.trim();
123
- if (!trimmed) return { value: "cleared", full: "cleared", clears: true };
128
+ if (!trimmed) return EMPTY;
129
+ const named = word?.(trimmed) ?? null;
130
+ if (named) return { value: named, full: named, clears: false };
124
131
  const oneLine = trimmed.replace(/\s+/g, " ");
125
132
  const shown = oneLine.length > CHANGE_VALUE_MAX ? `${oneLine.slice(0, CHANGE_VALUE_MAX - 1)}\u2026` : oneLine;
126
133
  return { value: shown, full: trimmed, clears: false };
@@ -130,11 +137,11 @@ function describeValue(value) {
130
137
  }
131
138
  if (Array.isArray(value)) {
132
139
  const n2 = value.length;
133
- const text2 = n2 === 0 ? "cleared" : `${n2} ${n2 === 1 ? "entry" : "entries"}`;
140
+ const text2 = n2 === 0 ? EMPTY_VALUE_WORD : `${n2} ${n2 === 1 ? "entry" : "entries"}`;
134
141
  return { value: text2, full: safeJson(value), clears: n2 === 0 };
135
142
  }
136
143
  const n = Object.keys(value).length;
137
- const text = n === 0 ? "cleared" : `${n} ${n === 1 ? "field" : "fields"}`;
144
+ const text = n === 0 ? EMPTY_VALUE_WORD : `${n} ${n === 1 ? "field" : "fields"}`;
138
145
  return { value: text, full: safeJson(value), clears: n === 0 };
139
146
  }
140
147
  function safeJson(value) {
@@ -159,10 +166,12 @@ function itemChanges(item, current, options = {}) {
159
166
  const titleColumn = options.titleColumn ?? null;
160
167
  for (const [key, raw] of Object.entries(item)) {
161
168
  if (NOT_A_CHANGE.has(key)) continue;
162
- const label = key === titleColumn ? "Title" : fieldLabel(key);
163
- const change = { key, label, ...describeValue(raw) };
169
+ const label = directiveFieldLabel(key, titleColumn);
170
+ const valueWord = options.valueWord;
171
+ const word = key === titleColumn || !valueWord ? void 0 : (v) => valueWord(key, v);
172
+ const change = { key, label, ...describeValue(raw, word) };
164
173
  if (current && Object.prototype.hasOwnProperty.call(current, key)) {
165
- change.before = describeValue(current[key]);
174
+ change.before = describeValue(current[key], word);
166
175
  change.same = sameValue(current[key], raw);
167
176
  }
168
177
  out.push(change);
@@ -618,7 +627,7 @@ function ApplyDirectiveButton({
618
627
  type: "button",
619
628
  disabled: askingAgain,
620
629
  onClick: () => void handleApply(!bad),
621
- className: "inline-flex items-center gap-1 rounded px-1 py-0.5 text-muted-foreground hover:bg-accent hover:text-accent-foreground disabled:opacity-50",
630
+ className: "inline-flex shrink-0 items-center gap-1 whitespace-nowrap rounded px-1 py-0.5 text-muted-foreground hover:bg-accent hover:text-accent-foreground disabled:opacity-50",
622
631
  "data-apply-action": bad ? "retry" : "run-again",
623
632
  children: [
624
633
  /* @__PURE__ */ jsx4(RotateCcwIcon, { className: "h-3 w-3" }),
@@ -658,8 +667,8 @@ function ApplyDirectiveButton({
658
667
  }
659
668
  const destructive = directive.directiveClass === "delete";
660
669
  const muted = nothingToChange && view.status === "idle";
661
- return /* @__PURE__ */ jsxs2("span", { className: "inline-flex items-center gap-2", children: [
662
- muted ? /* @__PURE__ */ jsx4("span", { className: "text-xs text-muted-foreground", "data-apply-nothing": "", children: "Nothing to change" }) : null,
670
+ return /* @__PURE__ */ jsxs2("span", { className: "flex min-w-0 flex-wrap items-center justify-end gap-x-2 gap-y-1", children: [
671
+ muted ? /* @__PURE__ */ jsx4("span", { className: "min-w-0 text-xs text-muted-foreground", "data-apply-nothing": "", children: "Nothing to change" }) : null,
663
672
  /* @__PURE__ */ jsxs2(
664
673
  "button",
665
674
  {
@@ -668,7 +677,7 @@ function ApplyDirectiveButton({
668
677
  disabled: view.status === "applying" || view.status === "asking" || items.length === 0,
669
678
  "data-apply-tone": muted ? "muted" : destructive ? "destructive" : "default",
670
679
  title: muted ? "It sets no fields, so applying it changes nothing." : void 0,
671
- className: `inline-flex items-center gap-1 rounded-md border px-2 py-1 text-xs font-medium disabled:opacity-50 ${muted ? "border-border/60 bg-background text-muted-foreground hover:bg-accent" : destructive ? "border-destructive/50 bg-background text-destructive hover:bg-destructive/10" : "border-border bg-background hover:bg-accent"}`,
680
+ className: `inline-flex shrink-0 items-center gap-1 whitespace-nowrap rounded-md border px-2 py-1 text-xs font-medium disabled:opacity-50 ${muted ? "border-border/60 bg-background text-muted-foreground hover:bg-accent" : destructive ? "border-destructive/50 bg-background text-destructive hover:bg-destructive/10" : "border-border bg-background hover:bg-accent"}`,
672
681
  children: [
673
682
  view.status === "applying" ? /* @__PURE__ */ jsx4(LoaderIcon, { className: "h-3.5 w-3.5 animate-spin" }) : /* @__PURE__ */ jsx4(PlayIcon, { className: "h-3.5 w-3.5" }),
674
683
  view.status === "applying" ? `Applying${itemCount ? ` ${itemCount} ${itemCount === 1 ? "item" : "items"}` : ""}\u2026${elapsed ? ` ${elapsed}s` : ""}` : label
@@ -719,7 +728,7 @@ function FailureNotice({
719
728
  type: "button",
720
729
  onClick: () => setOpen((v) => !v),
721
730
  "aria-expanded": open,
722
- className: "ml-1 underline underline-offset-2 hover:no-underline",
731
+ className: "ml-1 whitespace-nowrap underline underline-offset-2 hover:no-underline",
723
732
  "data-apply-failure-details-toggle": true,
724
733
  children: open ? "Hide details" : "Details"
725
734
  }
@@ -828,6 +837,14 @@ import {
828
837
  nounTitleColumn
829
838
  } from "@ai-matrx/content-ir";
830
839
  import { Fragment, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
840
+ function directiveValueWord(host, noun) {
841
+ const valueLabel = host.valueLabel;
842
+ return valueLabel ? (field, value) => valueLabel({ noun, field, value }) : null;
843
+ }
844
+ function omitKey(item, key) {
845
+ const { [key]: _omitted, ...rest } = item;
846
+ return rest;
847
+ }
831
848
  var ROWS_BEFORE_FOLD = 3;
832
849
  function ItemRow({
833
850
  directive,
@@ -844,16 +861,21 @@ function ItemRow({
844
861
  const titleColumn = nounTitleColumn(directive.noun, host.nouns);
845
862
  const title = itemTitle(item, titleColumn, index, total);
846
863
  const subtitle = itemSubtitle(item);
847
- const facts = itemFacts(item);
864
+ const valueWord = directiveValueWord(host, directive.noun);
865
+ const facts = itemFacts(titleColumn ? omitKey(item, titleColumn) : item).map((fact) => ({
866
+ ...fact,
867
+ label: directiveFieldLabel(fact.key, titleColumn),
868
+ value: valueWord?.(fact.key, fact.value) ?? fact.value
869
+ }));
848
870
  const kind = host.itemKind?.(directive.slug) ?? null;
849
871
  const display = directiveDisplay3(directive.directiveClass, directive.noun, host.nouns);
850
872
  const openItem = host.openItem;
851
873
  const body = /* @__PURE__ */ jsxs5(Fragment, { children: [
852
874
  /* @__PURE__ */ jsx7("span", { className: "min-w-0 shrink-0 truncate font-medium text-foreground", children: title }),
853
- /* @__PURE__ */ jsx7("span", { className: "hidden min-w-0 flex-1 items-baseline gap-2 overflow-hidden sm:flex", children: facts.map((fact) => /* @__PURE__ */ jsxs5("span", { className: "truncate text-[11px] text-muted-foreground", children: [
854
- fact.value,
875
+ /* @__PURE__ */ jsx7("span", { className: "hidden min-w-0 flex-1 items-baseline gap-2 overflow-hidden sm:flex", children: facts.map((fact) => /* @__PURE__ */ jsxs5("span", { className: "truncate text-[11px] text-muted-foreground", "data-item-fact": fact.key, children: [
876
+ fact.label,
855
877
  " ",
856
- fact.label
878
+ /* @__PURE__ */ jsx7("span", { className: "text-foreground/80", children: fact.value })
857
879
  ] }, fact.key)) }),
858
880
  subtitle && facts.length === 0 ? /* @__PURE__ */ jsx7("span", { className: "hidden truncate text-[11px] text-muted-foreground sm:inline", children: subtitle }) : null,
859
881
  openItem ? /* @__PURE__ */ jsx7(MaximizeIcon, { className: "ml-auto h-3 w-3 shrink-0 text-muted-foreground" }) : null
@@ -888,35 +910,36 @@ function DirectiveChangeList({
888
910
  if (changes.length === 0) {
889
911
  return /* @__PURE__ */ jsx7("p", { className: `text-[11px] text-muted-foreground${className ? ` ${className}` : ""}`, children: "Sets no fields \u2014 nothing would change." });
890
912
  }
891
- return /* @__PURE__ */ jsx7("ul", { className: `space-y-0.5${className ? ` ${className}` : ""}`, "data-directive-changes": "", children: changes.map((change) => {
913
+ return /* @__PURE__ */ jsx7("ul", { className: `@container space-y-1${className ? ` ${className}` : ""}`, "data-directive-changes": "", children: changes.map((change) => {
892
914
  const before = change.before && !change.same ? change.before : null;
893
- const was = before ? before.clears ? "empty" : before.value : null;
894
915
  return /* @__PURE__ */ jsxs5(
895
916
  "li",
896
917
  {
897
- className: "flex min-w-0 items-baseline gap-1.5 text-[11px]",
898
- title: before ? `${change.label}: ${before.clears ? "empty" : before.full} \u2192 ${change.full}` : `${change.label} \u2192 ${change.full}`,
918
+ className: "flex min-w-0 flex-col text-[11px] @xs:flex-row @xs:flex-wrap @xs:items-baseline @xs:gap-x-1.5",
919
+ title: before ? `${change.label}: ${before.full} \u2192 ${change.full}` : `${change.label} \u2192 ${change.full}`,
899
920
  "data-change-key": change.key,
900
921
  children: [
901
922
  /* @__PURE__ */ jsx7("span", { className: "shrink-0 text-muted-foreground", children: change.label }),
902
- was !== null ? /* @__PURE__ */ jsx7(
923
+ before ? /* @__PURE__ */ jsx7(
903
924
  "span",
904
925
  {
905
- className: "min-w-0 max-w-[40%] shrink truncate text-muted-foreground line-through",
926
+ className: "min-w-0 text-muted-foreground line-through [overflow-wrap:anywhere]",
906
927
  "data-change-before": "",
907
- children: was
928
+ children: before.value
908
929
  }
909
930
  ) : null,
910
- /* @__PURE__ */ jsx7("span", { "aria-hidden": true, className: "shrink-0 text-muted-foreground", children: "\u2192" }),
911
- /* @__PURE__ */ jsx7(
912
- "span",
913
- {
914
- className: `min-w-0 truncate ${change.clears ? "italic text-muted-foreground" : "text-foreground"}`,
915
- "data-change-after": "",
916
- children: change.value
917
- }
918
- ),
919
- change.same ? /* @__PURE__ */ jsx7("span", { className: "shrink-0 text-muted-foreground", children: "(no change)" }) : null
931
+ /* @__PURE__ */ jsxs5("span", { className: "flex min-w-0 items-baseline gap-1.5", children: [
932
+ /* @__PURE__ */ jsx7("span", { "aria-hidden": true, className: "shrink-0 text-muted-foreground", children: "\u2192" }),
933
+ /* @__PURE__ */ jsx7(
934
+ "span",
935
+ {
936
+ className: `min-w-0 [overflow-wrap:anywhere] ${change.clears ? "italic text-muted-foreground" : "text-foreground"}`,
937
+ "data-change-after": "",
938
+ children: change.value
939
+ }
940
+ ),
941
+ change.same ? /* @__PURE__ */ jsx7("span", { className: "shrink-0 text-muted-foreground", children: "(no change)" }) : null
942
+ ] })
920
943
  ]
921
944
  },
922
945
  change.key
@@ -939,12 +962,20 @@ function TargetRow({
939
962
  readsLive ? { noun: directive.noun, id: recordId } : null
940
963
  );
941
964
  const compareTo = phase.phase === "applied" ? phase.before?.[index] ?? null : readsLive ? live.values : null;
942
- const changes = isUpdate ? itemChanges(item, compareTo, { titleColumn: nounTitleColumn(directive.noun, host.nouns) }) : [];
965
+ const changes = isUpdate ? itemChanges(item, compareTo, {
966
+ titleColumn: nounTitleColumn(directive.noun, host.nouns),
967
+ valueWord: directiveValueWord(host, directive.noun)
968
+ }) : [];
943
969
  const name = host.renderRecord ? host.renderRecord({ noun: directive.noun, id: recordId, fallback, context: "row" }) : /* @__PURE__ */ jsx7("span", { className: "truncate font-medium text-foreground", children: fallback });
944
970
  return /* @__PURE__ */ jsxs5("div", { className: "py-1 text-xs", "data-directive-target": recordId, children: [
945
971
  /* @__PURE__ */ jsxs5("div", { className: "flex min-w-0 items-center gap-2", children: [
946
972
  /* @__PURE__ */ jsx7("span", { className: "flex min-w-0 flex-1 items-center gap-1 px-1", children: name }),
947
- host.renderCopy?.({ label: fallback, value: item, size: "xs" })
973
+ host.renderCopy?.({
974
+ label: `this ${nounLabel2(directive.noun, host.nouns).toLowerCase()}`,
975
+ value: item,
976
+ size: "xs",
977
+ record: { noun: directive.noun, id: recordId }
978
+ })
948
979
  ] }),
949
980
  isUpdate ? /* @__PURE__ */ jsx7(DirectiveChangeList, { changes, className: "mt-0.5 px-1" }) : null
950
981
  ] });
@@ -972,7 +1003,7 @@ function SideEffectDirectiveCard({ directive }) {
972
1003
  " ",
973
1004
  total === 1 ? "item" : "items"
974
1005
  ] }),
975
- /* @__PURE__ */ jsxs5("div", { className: "ml-auto flex items-center gap-1", children: [
1006
+ /* @__PURE__ */ jsxs5("div", { className: "ml-auto flex min-w-0 flex-wrap items-center justify-end gap-1", children: [
976
1007
  host.renderCopy?.({ label: display.title, value: directive.shell, size: "icon" }),
977
1008
  /* @__PURE__ */ jsx7(
978
1009
  ApplyDirectiveButton,
@@ -994,7 +1025,7 @@ function SideEffectDirectiveCard({ directive }) {
994
1025
  {
995
1026
  type: "button",
996
1027
  onClick: () => setExpanded((v) => !v),
997
- className: "mt-0.5 inline-flex items-center gap-1 rounded px-1 py-0.5 text-[11px] text-muted-foreground hover:text-foreground",
1028
+ className: "mt-0.5 inline-flex items-center gap-1 whitespace-nowrap rounded px-1 py-0.5 text-[11px] text-muted-foreground hover:text-foreground",
998
1029
  children: [
999
1030
  expanded ? /* @__PURE__ */ jsx7(ChevronDownIcon, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx7(ChevronRightIcon, { className: "h-3 w-3" }),
1000
1031
  expanded ? "Show less" : `Show ${hidden} more`