@ai-matrx/content-ir-react 0.24.5 → 0.25.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/CHANGELOG.md +16 -0
- package/dist/{directive-host-QjoZEeik.d.cts → directive-host-BF9Zzfbr.d.cts} +6 -0
- package/dist/{directive-host-QjoZEeik.d.ts → directive-host-BF9Zzfbr.d.ts} +6 -0
- package/dist/directives.cjs +43 -9
- package/dist/directives.cjs.map +1 -1
- package/dist/directives.d.cts +12 -3
- package/dist/directives.d.ts +12 -3
- package/dist/directives.js +44 -10
- package/dist/directives.js.map +1 -1
- package/dist/{host-types-DvZukz6J.d.ts → host-types-CBZTM8am.d.ts} +1 -1
- package/dist/{host-types-B2Q8fiU8.d.cts → host-types-CuCbs6Bc.d.cts} +1 -1
- package/dist/host.cjs.map +1 -1
- package/dist/host.d.cts +3 -3
- package/dist/host.d.ts +3 -3
- package/dist/host.js.map +1 -1
- package/dist/index.cjs +43 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -3
- package/dist/index.d.ts +12 -3
- package/dist/index.js +46 -12
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +42 -9
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +2 -2
- package/dist/react.d.ts +2 -2
- package/dist/react.js +45 -12
- package/dist/react.js.map +1 -1
- package/dist/{route-Bq6db_zH.d.cts → route-B9dsQHWZ.d.cts} +6 -0
- package/dist/{route-DStinBoZ.d.ts → route-CO_7dx0A.d.ts} +6 -0
- package/dist/route.d.cts +1 -1
- package/dist/route.d.ts +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.25.1
|
|
4
|
+
### A host can word a failure's Details (G15, 2026-10-07)
|
|
5
|
+
|
|
6
|
+
- `DirectiveFailureWords.details` (optional): when the host's `explainFailure` returns it, the card shows it behind "Details" instead of the raw server text — so a field reads as the form names it ("Title is required", never "name is required"). Absent → the raw text, as before.
|
|
7
|
+
|
|
8
|
+
Consumer action: none required; matrx-frontend `explainDirectiveFailure` returns `details`.
|
|
9
|
+
|
|
10
|
+
## 0.25.0
|
|
11
|
+
### An update that changes nothing says so (G11B, 2026-10-07)
|
|
12
|
+
|
|
13
|
+
- `changesNothing(changes)` (new export, `directives/item-changes`): true when an update sets no field, or every field already holds its value. Unknown current values count as a change.
|
|
14
|
+
- `SideEffectDirectiveCard`: once a row reads its record, an update whose every field already holds its value shows "Nothing to change" and a muted Apply — it used to be full-weight while the confirm listed "(no change)".
|
|
15
|
+
- A row's name wraps to two lines on a phone instead of being cut to one.
|
|
16
|
+
|
|
17
|
+
Consumer action: a host confirm for an update can call `changesNothing(itemChanges(item, values))` to say "Nothing to change" (matrx-frontend `DirectiveConsequence` does).
|
|
18
|
+
|
|
3
19
|
## 0.24.4
|
|
4
20
|
|
|
5
21
|
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
@@ -228,6 +228,12 @@ interface DirectiveFailure {
|
|
|
228
228
|
interface DirectiveFailureWords {
|
|
229
229
|
what: string;
|
|
230
230
|
next: string;
|
|
231
|
+
/**
|
|
232
|
+
* The text behind "Details", when the host words it (e.g. the server's field
|
|
233
|
+
* names read as the form labels them — "Title is required", never
|
|
234
|
+
* "name is required"). Absent → the raw text.
|
|
235
|
+
*/
|
|
236
|
+
details?: string;
|
|
231
237
|
}
|
|
232
238
|
/** Where a directive renders — today, the conversation it sits in (if any). */
|
|
233
239
|
interface DirectiveScope {
|
|
@@ -228,6 +228,12 @@ interface DirectiveFailure {
|
|
|
228
228
|
interface DirectiveFailureWords {
|
|
229
229
|
what: string;
|
|
230
230
|
next: string;
|
|
231
|
+
/**
|
|
232
|
+
* The text behind "Details", when the host words it (e.g. the server's field
|
|
233
|
+
* names read as the form labels them — "Title is required", never
|
|
234
|
+
* "name is required"). Absent → the raw text.
|
|
235
|
+
*/
|
|
236
|
+
details?: string;
|
|
231
237
|
}
|
|
232
238
|
/** Where a directive renders — today, the conversation it sits in (if any). */
|
|
233
239
|
interface DirectiveScope {
|
package/dist/directives.cjs
CHANGED
|
@@ -33,6 +33,7 @@ __export(directives_exports, {
|
|
|
33
33
|
NO_TITLE_WORD: () => NO_TITLE_WORD,
|
|
34
34
|
SideEffectDirectiveCard: () => SideEffectDirectiveCard,
|
|
35
35
|
TARGETING_CLASSES: () => TARGETING_CLASSES,
|
|
36
|
+
changesNothing: () => changesNothing,
|
|
36
37
|
defaultFailureWords: () => defaultFailureWords,
|
|
37
38
|
describeChangeValue: () => describeChangeValue,
|
|
38
39
|
directiveFieldLabel: () => directiveFieldLabel,
|
|
@@ -190,6 +191,9 @@ function itemChanges(item, current, options = {}) {
|
|
|
190
191
|
}
|
|
191
192
|
return out;
|
|
192
193
|
}
|
|
194
|
+
function changesNothing(changes) {
|
|
195
|
+
return changes.every((change) => change.same === true);
|
|
196
|
+
}
|
|
193
197
|
|
|
194
198
|
// directives/record-values.ts
|
|
195
199
|
var import_react2 = require("react");
|
|
@@ -698,7 +702,7 @@ function ApplyDirectiveButton({
|
|
|
698
702
|
onFocus: warm,
|
|
699
703
|
disabled: view.status === "applying" || view.status === "asking" || items.length === 0,
|
|
700
704
|
"data-apply-tone": muted ? "muted" : destructive ? "destructive" : "default",
|
|
701
|
-
title: muted ? "
|
|
705
|
+
title: muted ? "Applying it changes nothing." : void 0,
|
|
702
706
|
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"}`,
|
|
703
707
|
children: [
|
|
704
708
|
view.status === "applying" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(LoaderIcon, { className: "h-3.5 w-3.5 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PlayIcon, { className: "h-3.5 w-3.5" }),
|
|
@@ -738,7 +742,7 @@ function FailureNotice({
|
|
|
738
742
|
raw
|
|
739
743
|
}) {
|
|
740
744
|
const [open, setOpen] = (0, import_react3.useState)(false);
|
|
741
|
-
const detail = raw?.trim()
|
|
745
|
+
const detail = raw?.trim() ? words.details?.trim() || raw.trim() : "";
|
|
742
746
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "flex min-w-0 flex-col gap-0.5", "data-apply-failure": true, children: [
|
|
743
747
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "min-w-0", children: [
|
|
744
748
|
words.what,
|
|
@@ -785,12 +789,23 @@ function ItemRow({
|
|
|
785
789
|
item,
|
|
786
790
|
index,
|
|
787
791
|
total,
|
|
788
|
-
phase
|
|
792
|
+
phase,
|
|
793
|
+
onNothing
|
|
789
794
|
}) {
|
|
790
795
|
const host = useDirectiveHost();
|
|
791
796
|
const recordId = TARGETING_CLASSES.has(directive.directiveClass) ? itemRecordId(item) : null;
|
|
792
797
|
if (recordId) {
|
|
793
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
798
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
799
|
+
TargetRow,
|
|
800
|
+
{
|
|
801
|
+
directive,
|
|
802
|
+
item,
|
|
803
|
+
recordId,
|
|
804
|
+
index,
|
|
805
|
+
phase,
|
|
806
|
+
onNothing
|
|
807
|
+
}
|
|
808
|
+
);
|
|
794
809
|
}
|
|
795
810
|
const titleColumn = (0, import_content_ir4.nounTitleColumn)(directive.noun, host.nouns);
|
|
796
811
|
const ownName = itemOwnName(item, titleColumn);
|
|
@@ -809,7 +824,8 @@ function ItemRow({
|
|
|
809
824
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
810
825
|
"span",
|
|
811
826
|
{
|
|
812
|
-
className: `min-w-0 shrink-0 truncate
|
|
827
|
+
className: `min-w-0 line-clamp-2 font-medium [overflow-wrap:anywhere] sm:shrink-0 sm:truncate ${ownName ? "text-foreground" : "italic text-muted-foreground"}`,
|
|
828
|
+
"data-item-name": "",
|
|
813
829
|
"data-item-untitled": ownName ? void 0 : "",
|
|
814
830
|
children: title
|
|
815
831
|
}
|
|
@@ -898,7 +914,8 @@ function TargetRow({
|
|
|
898
914
|
item,
|
|
899
915
|
recordId,
|
|
900
916
|
index,
|
|
901
|
-
phase
|
|
917
|
+
phase,
|
|
918
|
+
onNothing
|
|
902
919
|
}) {
|
|
903
920
|
const host = useDirectiveHost();
|
|
904
921
|
const fallback = recordFallbackName((0, import_content_ir4.nounLabel)(directive.noun, host.nouns));
|
|
@@ -913,7 +930,11 @@ function TargetRow({
|
|
|
913
930
|
titleColumn: (0, import_content_ir4.nounTitleColumn)(directive.noun, host.nouns),
|
|
914
931
|
valueWord: directiveValueWord(host, directive.noun)
|
|
915
932
|
}) : [];
|
|
916
|
-
const
|
|
933
|
+
const nothing = readsLive && live.values !== null && changesNothing(changes);
|
|
934
|
+
(0, import_react4.useEffect)(() => {
|
|
935
|
+
onNothing?.(index, nothing);
|
|
936
|
+
}, [onNothing, index, nothing]);
|
|
937
|
+
const name = host.renderRecord ? host.renderRecord({ noun: directive.noun, id: recordId, fallback, context: "row" }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "line-clamp-2 min-w-0 font-medium text-foreground [overflow-wrap:anywhere]", children: fallback });
|
|
917
938
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "py-1 text-xs", "data-directive-target": recordId, children: [
|
|
918
939
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
919
940
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "flex min-w-0 flex-1 items-center gap-1 px-1", children: name }),
|
|
@@ -937,7 +958,9 @@ function SideEffectDirectiveCard({ directive }) {
|
|
|
937
958
|
const [phase, setPhase] = (0, import_react4.useState)(
|
|
938
959
|
() => readsApplyLedger(host, directive) ? { phase: "pending" } : { phase: "open" }
|
|
939
960
|
);
|
|
940
|
-
const
|
|
961
|
+
const [nothingAt, setNothingAt] = (0, import_react4.useState)({});
|
|
962
|
+
const noteNothing = (index, nothing) => setNothingAt((prev) => prev[index] === nothing ? prev : { ...prev, [index]: nothing });
|
|
963
|
+
const nothingToChange = directive.directiveClass === "update" && total > 0 && items.every((item, index) => itemChanges(item).length === 0 || nothingAt[index] === true);
|
|
941
964
|
const shown = expanded ? items : items.slice(0, ROWS_BEFORE_FOLD);
|
|
942
965
|
const hidden = total - shown.length;
|
|
943
966
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "my-3 rounded-md border border-border bg-card px-2.5 py-1.5", "data-directive": directive.slug, children: [
|
|
@@ -966,7 +989,18 @@ function SideEffectDirectiveCard({ directive }) {
|
|
|
966
989
|
total === 0 ? (
|
|
967
990
|
// Stated, never silent: an empty batch is a real (and suspicious) state.
|
|
968
991
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mt-1 text-xs text-muted-foreground", children: "No items \u2014 nothing would be written." })
|
|
969
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mt-0.5 divide-y divide-border/60", children: shown.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
992
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mt-0.5 divide-y divide-border/60", children: shown.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
993
|
+
ItemRow,
|
|
994
|
+
{
|
|
995
|
+
directive,
|
|
996
|
+
item,
|
|
997
|
+
index: i,
|
|
998
|
+
total,
|
|
999
|
+
phase,
|
|
1000
|
+
onNothing: noteNothing
|
|
1001
|
+
},
|
|
1002
|
+
i
|
|
1003
|
+
)) }),
|
|
970
1004
|
hidden > 0 || expanded ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
971
1005
|
"button",
|
|
972
1006
|
{
|