@ai-matrx/content-ir-react 0.18.1 → 0.19.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/index.d.cts CHANGED
@@ -428,6 +428,15 @@ interface RecordValues {
428
428
  status: RecordValuesStatus;
429
429
  }
430
430
  type RecordReader = (ref: DirectiveRecordRef) => Promise<Record<string, unknown> | null>;
431
+ /** How many times this page has changed record `id` (0 = never). */
432
+ declare function recordRevision(id: string): number;
433
+ /**
434
+ * Record `id` just changed (an apply wrote it, or any other writer on the page).
435
+ * Every `useRecordValues` naming it reads it again.
436
+ */
437
+ declare function noteRecordChanged(id: string): void;
438
+ /** The live revision of record `id`, re-rendering when it changes. */
439
+ declare function useRecordRevision(id: string): number;
431
440
  declare function useRecordValues(read: RecordReader | undefined, ref: DirectiveRecordRef | null): RecordValues;
432
441
 
433
442
  /**
@@ -693,4 +702,4 @@ declare class DbKindComponentErrorBoundary extends react.Component<DbKindCompone
693
702
  render(): react.ReactNode;
694
703
  }
695
704
 
696
- export { ApplyDirectiveButton, type ApplyDirectiveButtonProps, CHANGE_VALUE_MAX, type ChangeValue, type CompiledDbKindComponent, ComponentResolution, ComponentResolutionSource, ContentIrErrorReporter, ContentIrHost, ContentIrRenderProvider, type ContentIrRenderProviderProps, type DbKindActionResult, type DbKindCompileResult, type DbKindComponentCache, type DbKindComponentCachePorts, type DbKindComponentCompiler, DbKindComponentErrorBoundary, type DbKindComponentErrorBoundaryProps, type DbKindComponentIncident, type DbKindComponentIncidentSink, type DbKindComponentIncidentType, type DbKindComponentRenderProps, DelegatedOutput, type DelegatedOutputProps, type DirectiveApplyPhase, DirectiveChangeList, DirectiveFailure, DirectiveFailureWords, DirectiveFallbackCard, type DirectiveFallbackCardProps, DirectiveProvisionalCard, type DirectiveProvisionalCardProps, DirectiveRecordRef, DirectiveRender, type DirectiveRenderProps, type DirectiveRenderer, type DirectiveRendererProps, GenericStructuredView, type GenericStructuredViewProps, type ItemChange, type ItemChangesOptions, type KindComponentUiOptions, KindDefinitionSource, KindInstanceRender, type KindInstanceRenderProps, KindRouteEnv, type KindVersionSources, NodeOutcomeView, type NodeOutcomeViewProps, ProvisionalKindBoundary, ProvisionalKindFrame, type RecordReader, type RecordValues, type RecordValuesStatus, type ResolveKindValue, type RunDbKindAction, RunResultView, type RunResultViewProps, SideEffectDirectiveCard, type SideEffectDirectiveCardProps, TARGETING_CLASSES, createDbKindComponentCache, defaultFailureWords, describeChangeValue, failureWords, fieldLabel, getDirectiveRenderer, isDbKindComponentBodyPending, isRecordValue, itemChanges, itemRecordId, kindIsRoutable, provisionalDirectiveSlug, readsApplyLedger, recordFallbackName, registerDirectiveRenderer, resetDirectiveRenderers, useContentIrHost, useContentIrHostOrNull, useContentIrKindVersion, useKindRouteEnv, useRecordValues };
705
+ export { ApplyDirectiveButton, type ApplyDirectiveButtonProps, CHANGE_VALUE_MAX, type ChangeValue, type CompiledDbKindComponent, ComponentResolution, ComponentResolutionSource, ContentIrErrorReporter, ContentIrHost, ContentIrRenderProvider, type ContentIrRenderProviderProps, type DbKindActionResult, type DbKindCompileResult, type DbKindComponentCache, type DbKindComponentCachePorts, type DbKindComponentCompiler, DbKindComponentErrorBoundary, type DbKindComponentErrorBoundaryProps, type DbKindComponentIncident, type DbKindComponentIncidentSink, type DbKindComponentIncidentType, type DbKindComponentRenderProps, DelegatedOutput, type DelegatedOutputProps, type DirectiveApplyPhase, DirectiveChangeList, DirectiveFailure, DirectiveFailureWords, DirectiveFallbackCard, type DirectiveFallbackCardProps, DirectiveProvisionalCard, type DirectiveProvisionalCardProps, DirectiveRecordRef, DirectiveRender, type DirectiveRenderProps, type DirectiveRenderer, type DirectiveRendererProps, GenericStructuredView, type GenericStructuredViewProps, type ItemChange, type ItemChangesOptions, type KindComponentUiOptions, KindDefinitionSource, KindInstanceRender, type KindInstanceRenderProps, KindRouteEnv, type KindVersionSources, NodeOutcomeView, type NodeOutcomeViewProps, ProvisionalKindBoundary, ProvisionalKindFrame, type RecordReader, type RecordValues, type RecordValuesStatus, type ResolveKindValue, type RunDbKindAction, RunResultView, type RunResultViewProps, SideEffectDirectiveCard, type SideEffectDirectiveCardProps, TARGETING_CLASSES, createDbKindComponentCache, defaultFailureWords, describeChangeValue, failureWords, fieldLabel, getDirectiveRenderer, isDbKindComponentBodyPending, isRecordValue, itemChanges, itemRecordId, kindIsRoutable, noteRecordChanged, provisionalDirectiveSlug, readsApplyLedger, recordFallbackName, recordRevision, registerDirectiveRenderer, resetDirectiveRenderers, useContentIrHost, useContentIrHostOrNull, useContentIrKindVersion, useKindRouteEnv, useRecordRevision, useRecordValues };
package/dist/index.d.ts CHANGED
@@ -428,6 +428,15 @@ interface RecordValues {
428
428
  status: RecordValuesStatus;
429
429
  }
430
430
  type RecordReader = (ref: DirectiveRecordRef) => Promise<Record<string, unknown> | null>;
431
+ /** How many times this page has changed record `id` (0 = never). */
432
+ declare function recordRevision(id: string): number;
433
+ /**
434
+ * Record `id` just changed (an apply wrote it, or any other writer on the page).
435
+ * Every `useRecordValues` naming it reads it again.
436
+ */
437
+ declare function noteRecordChanged(id: string): void;
438
+ /** The live revision of record `id`, re-rendering when it changes. */
439
+ declare function useRecordRevision(id: string): number;
431
440
  declare function useRecordValues(read: RecordReader | undefined, ref: DirectiveRecordRef | null): RecordValues;
432
441
 
433
442
  /**
@@ -693,4 +702,4 @@ declare class DbKindComponentErrorBoundary extends react.Component<DbKindCompone
693
702
  render(): react.ReactNode;
694
703
  }
695
704
 
696
- export { ApplyDirectiveButton, type ApplyDirectiveButtonProps, CHANGE_VALUE_MAX, type ChangeValue, type CompiledDbKindComponent, ComponentResolution, ComponentResolutionSource, ContentIrErrorReporter, ContentIrHost, ContentIrRenderProvider, type ContentIrRenderProviderProps, type DbKindActionResult, type DbKindCompileResult, type DbKindComponentCache, type DbKindComponentCachePorts, type DbKindComponentCompiler, DbKindComponentErrorBoundary, type DbKindComponentErrorBoundaryProps, type DbKindComponentIncident, type DbKindComponentIncidentSink, type DbKindComponentIncidentType, type DbKindComponentRenderProps, DelegatedOutput, type DelegatedOutputProps, type DirectiveApplyPhase, DirectiveChangeList, DirectiveFailure, DirectiveFailureWords, DirectiveFallbackCard, type DirectiveFallbackCardProps, DirectiveProvisionalCard, type DirectiveProvisionalCardProps, DirectiveRecordRef, DirectiveRender, type DirectiveRenderProps, type DirectiveRenderer, type DirectiveRendererProps, GenericStructuredView, type GenericStructuredViewProps, type ItemChange, type ItemChangesOptions, type KindComponentUiOptions, KindDefinitionSource, KindInstanceRender, type KindInstanceRenderProps, KindRouteEnv, type KindVersionSources, NodeOutcomeView, type NodeOutcomeViewProps, ProvisionalKindBoundary, ProvisionalKindFrame, type RecordReader, type RecordValues, type RecordValuesStatus, type ResolveKindValue, type RunDbKindAction, RunResultView, type RunResultViewProps, SideEffectDirectiveCard, type SideEffectDirectiveCardProps, TARGETING_CLASSES, createDbKindComponentCache, defaultFailureWords, describeChangeValue, failureWords, fieldLabel, getDirectiveRenderer, isDbKindComponentBodyPending, isRecordValue, itemChanges, itemRecordId, kindIsRoutable, provisionalDirectiveSlug, readsApplyLedger, recordFallbackName, registerDirectiveRenderer, resetDirectiveRenderers, useContentIrHost, useContentIrHostOrNull, useContentIrKindVersion, useKindRouteEnv, useRecordValues };
705
+ export { ApplyDirectiveButton, type ApplyDirectiveButtonProps, CHANGE_VALUE_MAX, type ChangeValue, type CompiledDbKindComponent, ComponentResolution, ComponentResolutionSource, ContentIrErrorReporter, ContentIrHost, ContentIrRenderProvider, type ContentIrRenderProviderProps, type DbKindActionResult, type DbKindCompileResult, type DbKindComponentCache, type DbKindComponentCachePorts, type DbKindComponentCompiler, DbKindComponentErrorBoundary, type DbKindComponentErrorBoundaryProps, type DbKindComponentIncident, type DbKindComponentIncidentSink, type DbKindComponentIncidentType, type DbKindComponentRenderProps, DelegatedOutput, type DelegatedOutputProps, type DirectiveApplyPhase, DirectiveChangeList, DirectiveFailure, DirectiveFailureWords, DirectiveFallbackCard, type DirectiveFallbackCardProps, DirectiveProvisionalCard, type DirectiveProvisionalCardProps, DirectiveRecordRef, DirectiveRender, type DirectiveRenderProps, type DirectiveRenderer, type DirectiveRendererProps, GenericStructuredView, type GenericStructuredViewProps, type ItemChange, type ItemChangesOptions, type KindComponentUiOptions, KindDefinitionSource, KindInstanceRender, type KindInstanceRenderProps, KindRouteEnv, type KindVersionSources, NodeOutcomeView, type NodeOutcomeViewProps, ProvisionalKindBoundary, ProvisionalKindFrame, type RecordReader, type RecordValues, type RecordValuesStatus, type ResolveKindValue, type RunDbKindAction, RunResultView, type RunResultViewProps, SideEffectDirectiveCard, type SideEffectDirectiveCardProps, TARGETING_CLASSES, createDbKindComponentCache, defaultFailureWords, describeChangeValue, failureWords, fieldLabel, getDirectiveRenderer, isDbKindComponentBodyPending, isRecordValue, itemChanges, itemRecordId, kindIsRoutable, noteRecordChanged, provisionalDirectiveSlug, readsApplyLedger, recordFallbackName, recordRevision, registerDirectiveRenderer, resetDirectiveRenderers, useContentIrHost, useContentIrHostOrNull, useContentIrKindVersion, useKindRouteEnv, useRecordRevision, useRecordValues };
package/dist/index.js CHANGED
@@ -268,8 +268,8 @@ var ComponentResolver = class {
268
268
  }
269
269
  bumpKind(kind) {
270
270
  this.kindVersions.set(kind, (this.kindVersions.get(kind) ?? 0) + 1);
271
- const listeners = this.kindListeners.get(kind);
272
- if (listeners) for (const listener of listeners) listener();
271
+ const listeners2 = this.kindListeners.get(kind);
272
+ if (listeners2) for (const listener of listeners2) listener();
273
273
  }
274
274
  notifyChanged() {
275
275
  this.version += 1;
@@ -753,7 +753,7 @@ import { looksLikeDirectiveHead, tryDecodeDirectiveContent } from "@ai-matrx/con
753
753
  import { directiveDisplay } from "@ai-matrx/content-ir";
754
754
 
755
755
  // directives/ApplyDirectiveButton.tsx
756
- import { useEffect, useRef, useState, useSyncExternalStore as useSyncExternalStore2 } from "react";
756
+ import { useEffect as useEffect2, useRef, useState as useState2, useSyncExternalStore as useSyncExternalStore3 } from "react";
757
757
  import { nounLabel } from "@ai-matrx/content-ir";
758
758
 
759
759
  // directives/item-changes.ts
@@ -832,6 +832,73 @@ function itemChanges(item, current, options = {}) {
832
832
  return out;
833
833
  }
834
834
 
835
+ // directives/record-values.ts
836
+ import { useEffect, useState, useSyncExternalStore as useSyncExternalStore2 } from "react";
837
+ var STORE_SLOT = /* @__PURE__ */ Symbol.for("@ai-matrx/content-ir-react/record-revisions");
838
+ function revisionStore() {
839
+ const slots = globalThis;
840
+ let store = slots[STORE_SLOT];
841
+ if (!store) {
842
+ store = { revisions: /* @__PURE__ */ new Map(), listeners: /* @__PURE__ */ new Set() };
843
+ slots[STORE_SLOT] = store;
844
+ }
845
+ return store;
846
+ }
847
+ var { revisions, listeners } = revisionStore();
848
+ function recordRevision(id) {
849
+ return revisions.get(id) ?? 0;
850
+ }
851
+ function noteRecordChanged(id) {
852
+ if (!id) return;
853
+ revisions.set(id, recordRevision(id) + 1);
854
+ for (const listener of listeners) listener();
855
+ }
856
+ function subscribeRevisions(listener) {
857
+ listeners.add(listener);
858
+ return () => {
859
+ listeners.delete(listener);
860
+ };
861
+ }
862
+ function useRecordRevision(id) {
863
+ return useSyncExternalStore2(
864
+ subscribeRevisions,
865
+ () => recordRevision(id),
866
+ () => 0
867
+ );
868
+ }
869
+ function useRecordValues(read, ref) {
870
+ const revision = useRecordRevision(ref?.id ?? "");
871
+ const key = ref && read ? `${ref.noun}:${ref.id}#${revision}` : "";
872
+ const [result, setResult] = useState({
873
+ key: "",
874
+ values: null,
875
+ status: "idle"
876
+ });
877
+ useEffect(() => {
878
+ if (!key || !read) return;
879
+ const split = key.indexOf(":");
880
+ const target = {
881
+ noun: key.slice(0, split),
882
+ id: key.slice(split + 1, key.lastIndexOf("#"))
883
+ };
884
+ let live = true;
885
+ setResult({ key, values: null, status: "loading" });
886
+ read(target).then((values) => {
887
+ if (!live) return;
888
+ setResult({ key, values, status: values ? "ready" : "unavailable" });
889
+ }).catch(() => {
890
+ if (!live) return;
891
+ setResult({ key, values: null, status: "unavailable" });
892
+ });
893
+ return () => {
894
+ live = false;
895
+ };
896
+ }, [key, read]);
897
+ if (!key) return { values: null, status: "idle" };
898
+ if (result.key !== key) return { values: null, status: "loading" };
899
+ return { values: result.values, status: result.status };
900
+ }
901
+
835
902
  // directives/failure-words.ts
836
903
  var PAST = {
837
904
  create: "created",
@@ -951,6 +1018,13 @@ function classIcon(directiveClass, noun) {
951
1018
 
952
1019
  // directives/ApplyDirectiveButton.tsx
953
1020
  import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
1021
+ function announceChangedRecords(directive, items) {
1022
+ if (!TARGETING_CLASSES.has(directive.directiveClass)) return;
1023
+ for (const item of items) {
1024
+ const id = itemRecordId(item);
1025
+ if (id) noteRecordChanged(id);
1026
+ }
1027
+ }
954
1028
  var applyOutcomes = /* @__PURE__ */ new WeakMap();
955
1029
  var EMPTY_AUTHORITY = {};
956
1030
  var outcomeListeners = /* @__PURE__ */ new Set();
@@ -973,7 +1047,7 @@ function subscribeOutcomes(listener) {
973
1047
  };
974
1048
  }
975
1049
  function useApplyOutcome(host, identity) {
976
- return useSyncExternalStore2(
1050
+ return useSyncExternalStore3(
977
1051
  subscribeOutcomes,
978
1052
  () => applyOutcomes.get(host)?.get(identity) ?? null,
979
1053
  () => null
@@ -998,12 +1072,12 @@ function ApplyDirectiveButton({
998
1072
  const items = directive.items;
999
1073
  const readsLedger = readsApplyLedger(host, directive);
1000
1074
  const initial = readsLedger ? { status: "checking" } : { status: "idle" };
1001
- const [state, setState] = useState(initial);
1002
- const [elapsed, setElapsed] = useState(0);
1003
- const [askingAgain, setAskingAgain] = useState(false);
1075
+ const [state, setState] = useState2(initial);
1076
+ const [elapsed, setElapsed] = useState2(0);
1077
+ const [askingAgain, setAskingAgain] = useState2(false);
1004
1078
  const startedAt = useRef(null);
1005
1079
  const identity = JSON.stringify([directive.slug, items, conversationId ?? null]);
1006
- const [stateFor, setStateFor] = useState(identity);
1080
+ const [stateFor, setStateFor] = useState2(identity);
1007
1081
  if (stateFor !== identity) {
1008
1082
  setStateFor(identity);
1009
1083
  setState(initial);
@@ -1013,14 +1087,14 @@ function ApplyDirectiveButton({
1013
1087
  const shared = useApplyOutcome(host.confirm ?? EMPTY_AUTHORITY, identity);
1014
1088
  const view = state.status === "asking" || !shared ? state : shared;
1015
1089
  const currentIdentity = useRef(identity);
1016
- useEffect(() => {
1090
+ useEffect2(() => {
1017
1091
  currentIdentity.current = identity;
1018
1092
  }, [identity]);
1019
1093
  const nounText = nounLabel(directive.noun, host.nouns);
1020
1094
  const shellKey = readsLedger ? JSON.stringify([directive.slug, items, conversationId ?? null]) : "";
1021
1095
  const read = host.applyState;
1022
1096
  const report = host.reportError;
1023
- useEffect(() => {
1097
+ useEffect2(() => {
1024
1098
  if (!shellKey || !read) return;
1025
1099
  const [slug, shellItems, inConversation] = JSON.parse(shellKey);
1026
1100
  const shell = { __kind: slug, items: shellItems };
@@ -1068,14 +1142,14 @@ function ApplyDirectiveButton({
1068
1142
  const appliedClean = view.status === "applied" && view.failed === 0 ? view : null;
1069
1143
  const appliedBefore = appliedClean ? appliedClean.before : null;
1070
1144
  const phaseKey = view.status === "checking" || view.status === "finishing" ? "pending" : appliedClean ? `applied:${JSON.stringify(appliedBefore)}` : "open";
1071
- useEffect(() => {
1145
+ useEffect2(() => {
1072
1146
  if (!onPhase) return;
1073
1147
  if (phaseKey === "pending") onPhase({ phase: "pending" });
1074
1148
  else if (phaseKey === "open") onPhase({ phase: "open" });
1075
1149
  else onPhase({ phase: "applied", before: appliedBefore });
1076
1150
  }, [phaseKey, onPhase, appliedBefore]);
1077
1151
  const applyingSince = view.status === "applying" ? view.startedAt : null;
1078
- useEffect(() => {
1152
+ useEffect2(() => {
1079
1153
  if (applyingSince === null) return;
1080
1154
  startedAt.current = applyingSince;
1081
1155
  const id = setInterval(
@@ -1127,7 +1201,13 @@ function ApplyDirectiveButton({
1127
1201
  const shell = { __kind: directive.slug, items };
1128
1202
  if (conversationId) shell.conversationId = conversationId;
1129
1203
  if (again) shell.force = true;
1130
- const result = await confirm(shell);
1204
+ let result;
1205
+ try {
1206
+ result = await confirm(shell);
1207
+ } finally {
1208
+ announceChangedRecords(directive, items);
1209
+ }
1210
+ for (const record of result.records ?? []) noteRecordChanged(record.id);
1131
1211
  publishOutcome(confirm, askedFor, {
1132
1212
  status: "applied",
1133
1213
  applied: result.applied,
@@ -1288,7 +1368,7 @@ function FailureNotice({
1288
1368
  words,
1289
1369
  raw
1290
1370
  }) {
1291
- const [open, setOpen] = useState(false);
1371
+ const [open, setOpen] = useState2(false);
1292
1372
  const detail = raw?.trim() ?? "";
1293
1373
  return /* @__PURE__ */ jsxs2("span", { className: "flex min-w-0 flex-col gap-0.5", "data-apply-failure": true, children: [
1294
1374
  /* @__PURE__ */ jsxs2("span", { className: "min-w-0", children: [
@@ -1417,39 +1497,6 @@ import {
1417
1497
  nounLabel as nounLabel2,
1418
1498
  nounTitleColumn
1419
1499
  } from "@ai-matrx/content-ir";
1420
-
1421
- // directives/record-values.ts
1422
- import { useEffect as useEffect2, useState as useState2 } from "react";
1423
- function useRecordValues(read, ref) {
1424
- const key = ref && read ? `${ref.noun}:${ref.id}` : "";
1425
- const [result, setResult] = useState2({
1426
- key: "",
1427
- values: null,
1428
- status: "idle"
1429
- });
1430
- useEffect2(() => {
1431
- if (!key || !read) return;
1432
- const split = key.indexOf(":");
1433
- const target = { noun: key.slice(0, split), id: key.slice(split + 1) };
1434
- let live = true;
1435
- setResult({ key, values: null, status: "loading" });
1436
- read(target).then((values) => {
1437
- if (!live) return;
1438
- setResult({ key, values, status: values ? "ready" : "unavailable" });
1439
- }).catch(() => {
1440
- if (!live) return;
1441
- setResult({ key, values: null, status: "unavailable" });
1442
- });
1443
- return () => {
1444
- live = false;
1445
- };
1446
- }, [key, read]);
1447
- if (!key) return { values: null, status: "idle" };
1448
- if (result.key !== key) return { values: null, status: "loading" };
1449
- return { values: result.values, status: result.status };
1450
- }
1451
-
1452
- // directives/SideEffectDirectiveCard.tsx
1453
1500
  import { Fragment, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
1454
1501
  var ROWS_BEFORE_FOLD = 3;
1455
1502
  function ItemRow({
@@ -2137,10 +2184,12 @@ export {
2137
2184
  kindIsRoutable,
2138
2185
  kindServerDataFromStoredValue,
2139
2186
  markKindPartialUnsafe,
2187
+ noteRecordChanged,
2140
2188
  provisionalDirectiveSlug,
2141
2189
  readIrRouteMarker,
2142
2190
  readsApplyLedger,
2143
2191
  recordFallbackName,
2192
+ recordRevision,
2144
2193
  registerDirectiveRenderer,
2145
2194
  resetDirectiveRenderers,
2146
2195
  resetPartialUnsafeKinds,
@@ -2155,6 +2204,7 @@ export {
2155
2204
  useDirectiveHost,
2156
2205
  useDirectiveScope,
2157
2206
  useKindRouteEnv,
2207
+ useRecordRevision,
2158
2208
  useRecordValues
2159
2209
  };
2160
2210
  //# sourceMappingURL=index.js.map