@ai-matrx/content-ir-react 0.24.4 → 0.25.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/index.cjs CHANGED
@@ -58,6 +58,7 @@ __export(index_exports, {
58
58
  SideEffectDirectiveCard: () => SideEffectDirectiveCard,
59
59
  TARGETING_CLASSES: () => TARGETING_CLASSES,
60
60
  applyIrKindRoute: () => applyIrKindRoute,
61
+ changesNothing: () => changesNothing,
61
62
  consoleErrorReporter: () => consoleErrorReporter,
62
63
  createDbKindComponentCache: () => createDbKindComponentCache,
63
64
  createKindRouteBinding: () => createKindRouteBinding,
@@ -932,6 +933,9 @@ function itemChanges(item, current, options = {}) {
932
933
  }
933
934
  return out;
934
935
  }
936
+ function changesNothing(changes) {
937
+ return changes.every((change) => change.same === true);
938
+ }
935
939
 
936
940
  // directives/record-values.ts
937
941
  var import_react4 = require("react");
@@ -1440,7 +1444,7 @@ function ApplyDirectiveButton({
1440
1444
  onFocus: warm,
1441
1445
  disabled: view.status === "applying" || view.status === "asking" || items.length === 0,
1442
1446
  "data-apply-tone": muted ? "muted" : destructive ? "destructive" : "default",
1443
- title: muted ? "It sets no fields, so applying it changes nothing." : void 0,
1447
+ title: muted ? "Applying it changes nothing." : void 0,
1444
1448
  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"}`,
1445
1449
  children: [
1446
1450
  view.status === "applying" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LoaderIcon, { className: "h-3.5 w-3.5 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PlayIcon, { className: "h-3.5 w-3.5" }),
@@ -1613,12 +1617,23 @@ function ItemRow({
1613
1617
  item,
1614
1618
  index,
1615
1619
  total,
1616
- phase
1620
+ phase,
1621
+ onNothing
1617
1622
  }) {
1618
1623
  const host = useDirectiveHost();
1619
1624
  const recordId = TARGETING_CLASSES.has(directive.directiveClass) ? itemRecordId(item) : null;
1620
1625
  if (recordId) {
1621
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TargetRow, { directive, item, recordId, index, phase });
1626
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1627
+ TargetRow,
1628
+ {
1629
+ directive,
1630
+ item,
1631
+ recordId,
1632
+ index,
1633
+ phase,
1634
+ onNothing
1635
+ }
1636
+ );
1622
1637
  }
1623
1638
  const titleColumn = (0, import_content_ir8.nounTitleColumn)(directive.noun, host.nouns);
1624
1639
  const ownName = itemOwnName(item, titleColumn);
@@ -1637,7 +1652,8 @@ function ItemRow({
1637
1652
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1638
1653
  "span",
1639
1654
  {
1640
- className: `min-w-0 shrink-0 truncate font-medium ${ownName ? "text-foreground" : "italic text-muted-foreground"}`,
1655
+ className: `min-w-0 line-clamp-2 font-medium [overflow-wrap:anywhere] sm:shrink-0 sm:truncate ${ownName ? "text-foreground" : "italic text-muted-foreground"}`,
1656
+ "data-item-name": "",
1641
1657
  "data-item-untitled": ownName ? void 0 : "",
1642
1658
  children: title
1643
1659
  }
@@ -1726,7 +1742,8 @@ function TargetRow({
1726
1742
  item,
1727
1743
  recordId,
1728
1744
  index,
1729
- phase
1745
+ phase,
1746
+ onNothing
1730
1747
  }) {
1731
1748
  const host = useDirectiveHost();
1732
1749
  const fallback = recordFallbackName((0, import_content_ir8.nounLabel)(directive.noun, host.nouns));
@@ -1741,7 +1758,11 @@ function TargetRow({
1741
1758
  titleColumn: (0, import_content_ir8.nounTitleColumn)(directive.noun, host.nouns),
1742
1759
  valueWord: directiveValueWord(host, directive.noun)
1743
1760
  }) : [];
1744
- 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 });
1761
+ const nothing = readsLive && live.values !== null && changesNothing(changes);
1762
+ (0, import_react6.useEffect)(() => {
1763
+ onNothing?.(index, nothing);
1764
+ }, [onNothing, index, nothing]);
1765
+ const name = host.renderRecord ? host.renderRecord({ noun: directive.noun, id: recordId, fallback, context: "row" }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "line-clamp-2 min-w-0 font-medium text-foreground [overflow-wrap:anywhere]", children: fallback });
1745
1766
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "py-1 text-xs", "data-directive-target": recordId, children: [
1746
1767
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex min-w-0 items-center gap-2", children: [
1747
1768
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "flex min-w-0 flex-1 items-center gap-1 px-1", children: name }),
@@ -1765,7 +1786,9 @@ function SideEffectDirectiveCard({ directive }) {
1765
1786
  const [phase, setPhase] = (0, import_react6.useState)(
1766
1787
  () => readsApplyLedger(host, directive) ? { phase: "pending" } : { phase: "open" }
1767
1788
  );
1768
- const nothingToChange = directive.directiveClass === "update" && total > 0 && items.every((item) => itemChanges(item).length === 0);
1789
+ const [nothingAt, setNothingAt] = (0, import_react6.useState)({});
1790
+ const noteNothing = (index, nothing) => setNothingAt((prev) => prev[index] === nothing ? prev : { ...prev, [index]: nothing });
1791
+ const nothingToChange = directive.directiveClass === "update" && total > 0 && items.every((item, index) => itemChanges(item).length === 0 || nothingAt[index] === true);
1769
1792
  const shown = expanded ? items : items.slice(0, ROWS_BEFORE_FOLD);
1770
1793
  const hidden = total - shown.length;
1771
1794
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "my-3 rounded-md border border-border bg-card px-2.5 py-1.5", "data-directive": directive.slug, children: [
@@ -1794,7 +1817,18 @@ function SideEffectDirectiveCard({ directive }) {
1794
1817
  total === 0 ? (
1795
1818
  // Stated, never silent: an empty batch is a real (and suspicious) state.
1796
1819
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "mt-1 text-xs text-muted-foreground", children: "No items \u2014 nothing would be written." })
1797
- ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "mt-0.5 divide-y divide-border/60", children: shown.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ItemRow, { directive, item, index: i, total, phase }, i)) }),
1820
+ ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "mt-0.5 divide-y divide-border/60", children: shown.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1821
+ ItemRow,
1822
+ {
1823
+ directive,
1824
+ item,
1825
+ index: i,
1826
+ total,
1827
+ phase,
1828
+ onNothing: noteNothing
1829
+ },
1830
+ i
1831
+ )) }),
1798
1832
  hidden > 0 || expanded ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1799
1833
  "button",
1800
1834
  {