@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/CHANGELOG.md +48 -0
- package/dist/{directive-host-Bw2_PrgL.d.cts → directive-host-CtFMuSZc.d.cts} +23 -1
- package/dist/{directive-host-Bw2_PrgL.d.ts → directive-host-CtFMuSZc.d.ts} +23 -1
- package/dist/directives.cjs +77 -43
- package/dist/directives.cjs.map +1 -1
- package/dist/directives.d.cts +38 -7
- package/dist/directives.d.ts +38 -7
- package/dist/directives.js +77 -43
- package/dist/directives.js.map +1 -1
- package/dist/{host-types-YP_l_Q_t.d.cts → host-types-BRLk_J_3.d.cts} +1 -1
- package/dist/{host-types-eSjFmXyF.d.ts → host-types-BpcRcZ48.d.ts} +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 +77 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +38 -7
- package/dist/index.d.ts +38 -7
- package/dist/index.js +77 -43
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +72 -41
- 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 +72 -41
- package/dist/react.js.map +1 -1
- package/dist/{route-CtYw2cTN.d.ts → route-CiCUQGAB.d.ts} +23 -1
- package/dist/{route-KoRMp3Qn.d.cts → route-DMTBn8w4.d.cts} +23 -1
- package/dist/route.d.cts +1 -1
- package/dist/route.d.ts +1 -1
- package/package.json +3 -3
package/dist/directives.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { D as
|
|
2
|
-
export {
|
|
1
|
+
import { D as DirectiveHost, a as DirectiveFailure, b as DirectiveFailureWords, c as DirectiveRecordRef } from './directive-host-CtFMuSZc.cjs';
|
|
2
|
+
export { d as DirectiveApplyResult, e as DirectiveApplyState, f as DirectiveAskRequest, g as DirectiveCopyProps, h as DirectiveHostProvider, i as DirectiveHostProviderProps, j as DirectiveOpenItemOptions, k as DirectiveRecordProps, l as DirectiveScope, m as DirectiveScopeProvider, n as DirectiveShell, o as DirectiveValueRef, u as useDirectiveHost, p as useDirectiveScope } from './directive-host-CtFMuSZc.cjs';
|
|
3
3
|
import * as react from 'react';
|
|
4
4
|
import { ComponentType } from 'react';
|
|
5
5
|
import { DecodedDirective, DirectiveClass } from '@ai-matrx/content-ir';
|
|
@@ -94,12 +94,33 @@ declare function ApplyDirectiveButton({ directive, label, itemCount, onApplied,
|
|
|
94
94
|
*/
|
|
95
95
|
/** Classes whose items point at an EXISTING record by `id`. */
|
|
96
96
|
declare const TARGETING_CLASSES: ReadonlySet<string>;
|
|
97
|
-
/**
|
|
98
|
-
|
|
97
|
+
/**
|
|
98
|
+
* How long a changed value may read before it is shortened. A value someone
|
|
99
|
+
* must judge — a title, a status, a date — is always whole (G8A review: a 60
|
|
100
|
+
* cap plus CSS truncation cut "Review4 tasks…" on a phone); only a body of
|
|
101
|
+
* prose longer than this is shortened, whole on hover and in View/Copy.
|
|
102
|
+
*/
|
|
103
|
+
declare const CHANGE_VALUE_MAX = 280;
|
|
99
104
|
/** The id of the existing record an update/delete item targets, or null. */
|
|
100
105
|
declare function itemRecordId(item: Record<string, unknown>): string | null;
|
|
101
|
-
/** "due_date" → "Due
|
|
106
|
+
/** "due_date" → "Due Date" — THE humanizer; underscores read as developer output. */
|
|
102
107
|
declare function fieldLabel(key: string): string;
|
|
108
|
+
/**
|
|
109
|
+
* THE ONE FIELD-LABEL RULE for a directive — card rows, card facts and the
|
|
110
|
+
* host's confirm: the noun's title column reads "Title" whatever it is stored
|
|
111
|
+
* as (a workbook's `workbook_name`, a note's `label`), every other field reads
|
|
112
|
+
* through THE humanizer. A new workbook card said "workbook name" while its
|
|
113
|
+
* confirm said "Title" (G8A review, 2026-10-02).
|
|
114
|
+
*/
|
|
115
|
+
declare function directiveFieldLabel(key: string, titleColumn: string | null | undefined): string;
|
|
116
|
+
/**
|
|
117
|
+
* The app's word for ONE stored value of ONE field — "incomplete" on a task
|
|
118
|
+
* reads "Inbox", "high" reads "High". The host answers it for its pick-list
|
|
119
|
+
* fields; null → the value as stored.
|
|
120
|
+
*/
|
|
121
|
+
type DirectiveValueWord = (field: string, value: string) => string | null;
|
|
122
|
+
/** How an empty value reads — before or after, on the card and in the confirm. */
|
|
123
|
+
declare const EMPTY_VALUE_WORD = "None";
|
|
103
124
|
/** A short, honest name for a record we could not look up: "Task 1a2b3c4d". */
|
|
104
125
|
declare function recordFallbackName(nounLabel: string, id: string): string;
|
|
105
126
|
/** One value as a row reads it: shortened, the whole of it, and whether it is empty. */
|
|
@@ -122,7 +143,7 @@ interface ItemChange extends ChangeValue {
|
|
|
122
143
|
same?: boolean;
|
|
123
144
|
}
|
|
124
145
|
/** One value, described for a change row (`value` shortened, `full` whole). */
|
|
125
|
-
declare function describeChangeValue(value: unknown): ChangeValue;
|
|
146
|
+
declare function describeChangeValue(value: unknown, word?: (value: string) => string | null): ChangeValue;
|
|
126
147
|
/**
|
|
127
148
|
* Every field an UPDATE item sets, in the order the item carries them — ALL of
|
|
128
149
|
* them, never a sample: a person approving an overwrite sees the whole of it.
|
|
@@ -139,17 +160,27 @@ interface ItemChangesOptions {
|
|
|
139
160
|
* (reviewer, 2026-10-02). The same rule the directive builder's form uses.
|
|
140
161
|
*/
|
|
141
162
|
titleColumn?: string | null;
|
|
163
|
+
/** The app's word for a stored value (`DirectiveHost.valueLabel`, bound to the noun). */
|
|
164
|
+
valueWord?: DirectiveValueWord | null;
|
|
142
165
|
}
|
|
143
166
|
declare function itemChanges(item: Record<string, unknown>, current?: Record<string, unknown> | null, options?: ItemChangesOptions): ItemChange[];
|
|
144
167
|
|
|
145
168
|
interface SideEffectDirectiveCardProps {
|
|
146
169
|
directive: DecodedDirective;
|
|
147
170
|
}
|
|
171
|
+
/** The host's value words for one record type, or null when it has none. */
|
|
172
|
+
declare function directiveValueWord(host: Pick<DirectiveHost, "valueLabel">, noun: string): DirectiveValueWord | null;
|
|
148
173
|
/**
|
|
149
174
|
* THE CHANGE LIST — every field an update sets, as "Label old → new" when the
|
|
150
175
|
* record's current value is known, "Label → new" when it is not. ONE component
|
|
151
176
|
* for the card row and the host's confirm dialog, so the two can never read
|
|
152
177
|
* differently (reviewer, 2026-10-02: the confirm showed only the new value).
|
|
178
|
+
*
|
|
179
|
+
* 🚨 A VALUE SOMEONE MUST JUDGE IS NEVER CUT (G8A review, 2026-10-02): on a
|
|
180
|
+
* phone the card is ~230px and the row read "Title Review… → Review4 tas…".
|
|
181
|
+
* Values wrap; below a 20rem container the label, the old value and the new
|
|
182
|
+
* value stack, one per line. Measured on the list's own width (a container
|
|
183
|
+
* query), so a narrow window panel on a desktop gets the same stacking.
|
|
153
184
|
*/
|
|
154
185
|
declare function DirectiveChangeList({ changes, className, }: {
|
|
155
186
|
changes: ItemChange[];
|
|
@@ -232,4 +263,4 @@ declare function noteRecordChanged(id: string): void;
|
|
|
232
263
|
declare function useRecordRevision(id: string): number;
|
|
233
264
|
declare function useRecordValues(read: RecordReader | undefined, ref: DirectiveRecordRef | null): RecordValues;
|
|
234
265
|
|
|
235
|
-
export { ApplyDirectiveButton, type ApplyDirectiveButtonProps, CHANGE_VALUE_MAX, type ChangeValue, type DirectiveApplyPhase, DirectiveChangeList, DirectiveFailure, DirectiveFailureWords, DirectiveFallbackCard, type DirectiveFallbackCardProps, DirectiveProvisionalCard, type DirectiveProvisionalCardProps, DirectiveRecordRef, DirectiveRender, type DirectiveRenderProps, type DirectiveRenderer, type DirectiveRendererProps, type ItemChange, type ItemChangesOptions, type RecordReader, type RecordValues, type RecordValuesStatus, SideEffectDirectiveCard, type SideEffectDirectiveCardProps, TARGETING_CLASSES, defaultFailureWords, describeChangeValue, failureWords, fieldLabel, getDirectiveRenderer, itemChanges, itemRecordId, noteRecordChanged, provisionalDirectiveSlug, readsApplyLedger, recordFallbackName, recordRevision, registerDirectiveRenderer, resetDirectiveRenderers, useRecordRevision, useRecordValues };
|
|
266
|
+
export { ApplyDirectiveButton, type ApplyDirectiveButtonProps, CHANGE_VALUE_MAX, type ChangeValue, type DirectiveApplyPhase, DirectiveChangeList, DirectiveFailure, DirectiveFailureWords, DirectiveFallbackCard, type DirectiveFallbackCardProps, DirectiveHost, DirectiveProvisionalCard, type DirectiveProvisionalCardProps, DirectiveRecordRef, DirectiveRender, type DirectiveRenderProps, type DirectiveRenderer, type DirectiveRendererProps, type DirectiveValueWord, EMPTY_VALUE_WORD, type ItemChange, type ItemChangesOptions, type RecordReader, type RecordValues, type RecordValuesStatus, SideEffectDirectiveCard, type SideEffectDirectiveCardProps, TARGETING_CLASSES, defaultFailureWords, describeChangeValue, directiveFieldLabel, directiveValueWord, failureWords, fieldLabel, getDirectiveRenderer, itemChanges, itemRecordId, noteRecordChanged, provisionalDirectiveSlug, readsApplyLedger, recordFallbackName, recordRevision, registerDirectiveRenderer, resetDirectiveRenderers, useRecordRevision, useRecordValues };
|
package/dist/directives.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { D as
|
|
2
|
-
export {
|
|
1
|
+
import { D as DirectiveHost, a as DirectiveFailure, b as DirectiveFailureWords, c as DirectiveRecordRef } from './directive-host-CtFMuSZc.js';
|
|
2
|
+
export { d as DirectiveApplyResult, e as DirectiveApplyState, f as DirectiveAskRequest, g as DirectiveCopyProps, h as DirectiveHostProvider, i as DirectiveHostProviderProps, j as DirectiveOpenItemOptions, k as DirectiveRecordProps, l as DirectiveScope, m as DirectiveScopeProvider, n as DirectiveShell, o as DirectiveValueRef, u as useDirectiveHost, p as useDirectiveScope } from './directive-host-CtFMuSZc.js';
|
|
3
3
|
import * as react from 'react';
|
|
4
4
|
import { ComponentType } from 'react';
|
|
5
5
|
import { DecodedDirective, DirectiveClass } from '@ai-matrx/content-ir';
|
|
@@ -94,12 +94,33 @@ declare function ApplyDirectiveButton({ directive, label, itemCount, onApplied,
|
|
|
94
94
|
*/
|
|
95
95
|
/** Classes whose items point at an EXISTING record by `id`. */
|
|
96
96
|
declare const TARGETING_CLASSES: ReadonlySet<string>;
|
|
97
|
-
/**
|
|
98
|
-
|
|
97
|
+
/**
|
|
98
|
+
* How long a changed value may read before it is shortened. A value someone
|
|
99
|
+
* must judge — a title, a status, a date — is always whole (G8A review: a 60
|
|
100
|
+
* cap plus CSS truncation cut "Review4 tasks…" on a phone); only a body of
|
|
101
|
+
* prose longer than this is shortened, whole on hover and in View/Copy.
|
|
102
|
+
*/
|
|
103
|
+
declare const CHANGE_VALUE_MAX = 280;
|
|
99
104
|
/** The id of the existing record an update/delete item targets, or null. */
|
|
100
105
|
declare function itemRecordId(item: Record<string, unknown>): string | null;
|
|
101
|
-
/** "due_date" → "Due
|
|
106
|
+
/** "due_date" → "Due Date" — THE humanizer; underscores read as developer output. */
|
|
102
107
|
declare function fieldLabel(key: string): string;
|
|
108
|
+
/**
|
|
109
|
+
* THE ONE FIELD-LABEL RULE for a directive — card rows, card facts and the
|
|
110
|
+
* host's confirm: the noun's title column reads "Title" whatever it is stored
|
|
111
|
+
* as (a workbook's `workbook_name`, a note's `label`), every other field reads
|
|
112
|
+
* through THE humanizer. A new workbook card said "workbook name" while its
|
|
113
|
+
* confirm said "Title" (G8A review, 2026-10-02).
|
|
114
|
+
*/
|
|
115
|
+
declare function directiveFieldLabel(key: string, titleColumn: string | null | undefined): string;
|
|
116
|
+
/**
|
|
117
|
+
* The app's word for ONE stored value of ONE field — "incomplete" on a task
|
|
118
|
+
* reads "Inbox", "high" reads "High". The host answers it for its pick-list
|
|
119
|
+
* fields; null → the value as stored.
|
|
120
|
+
*/
|
|
121
|
+
type DirectiveValueWord = (field: string, value: string) => string | null;
|
|
122
|
+
/** How an empty value reads — before or after, on the card and in the confirm. */
|
|
123
|
+
declare const EMPTY_VALUE_WORD = "None";
|
|
103
124
|
/** A short, honest name for a record we could not look up: "Task 1a2b3c4d". */
|
|
104
125
|
declare function recordFallbackName(nounLabel: string, id: string): string;
|
|
105
126
|
/** One value as a row reads it: shortened, the whole of it, and whether it is empty. */
|
|
@@ -122,7 +143,7 @@ interface ItemChange extends ChangeValue {
|
|
|
122
143
|
same?: boolean;
|
|
123
144
|
}
|
|
124
145
|
/** One value, described for a change row (`value` shortened, `full` whole). */
|
|
125
|
-
declare function describeChangeValue(value: unknown): ChangeValue;
|
|
146
|
+
declare function describeChangeValue(value: unknown, word?: (value: string) => string | null): ChangeValue;
|
|
126
147
|
/**
|
|
127
148
|
* Every field an UPDATE item sets, in the order the item carries them — ALL of
|
|
128
149
|
* them, never a sample: a person approving an overwrite sees the whole of it.
|
|
@@ -139,17 +160,27 @@ interface ItemChangesOptions {
|
|
|
139
160
|
* (reviewer, 2026-10-02). The same rule the directive builder's form uses.
|
|
140
161
|
*/
|
|
141
162
|
titleColumn?: string | null;
|
|
163
|
+
/** The app's word for a stored value (`DirectiveHost.valueLabel`, bound to the noun). */
|
|
164
|
+
valueWord?: DirectiveValueWord | null;
|
|
142
165
|
}
|
|
143
166
|
declare function itemChanges(item: Record<string, unknown>, current?: Record<string, unknown> | null, options?: ItemChangesOptions): ItemChange[];
|
|
144
167
|
|
|
145
168
|
interface SideEffectDirectiveCardProps {
|
|
146
169
|
directive: DecodedDirective;
|
|
147
170
|
}
|
|
171
|
+
/** The host's value words for one record type, or null when it has none. */
|
|
172
|
+
declare function directiveValueWord(host: Pick<DirectiveHost, "valueLabel">, noun: string): DirectiveValueWord | null;
|
|
148
173
|
/**
|
|
149
174
|
* THE CHANGE LIST — every field an update sets, as "Label old → new" when the
|
|
150
175
|
* record's current value is known, "Label → new" when it is not. ONE component
|
|
151
176
|
* for the card row and the host's confirm dialog, so the two can never read
|
|
152
177
|
* differently (reviewer, 2026-10-02: the confirm showed only the new value).
|
|
178
|
+
*
|
|
179
|
+
* 🚨 A VALUE SOMEONE MUST JUDGE IS NEVER CUT (G8A review, 2026-10-02): on a
|
|
180
|
+
* phone the card is ~230px and the row read "Title Review… → Review4 tas…".
|
|
181
|
+
* Values wrap; below a 20rem container the label, the old value and the new
|
|
182
|
+
* value stack, one per line. Measured on the list's own width (a container
|
|
183
|
+
* query), so a narrow window panel on a desktop gets the same stacking.
|
|
153
184
|
*/
|
|
154
185
|
declare function DirectiveChangeList({ changes, className, }: {
|
|
155
186
|
changes: ItemChange[];
|
|
@@ -232,4 +263,4 @@ declare function noteRecordChanged(id: string): void;
|
|
|
232
263
|
declare function useRecordRevision(id: string): number;
|
|
233
264
|
declare function useRecordValues(read: RecordReader | undefined, ref: DirectiveRecordRef | null): RecordValues;
|
|
234
265
|
|
|
235
|
-
export { ApplyDirectiveButton, type ApplyDirectiveButtonProps, CHANGE_VALUE_MAX, type ChangeValue, type DirectiveApplyPhase, DirectiveChangeList, DirectiveFailure, DirectiveFailureWords, DirectiveFallbackCard, type DirectiveFallbackCardProps, DirectiveProvisionalCard, type DirectiveProvisionalCardProps, DirectiveRecordRef, DirectiveRender, type DirectiveRenderProps, type DirectiveRenderer, type DirectiveRendererProps, type ItemChange, type ItemChangesOptions, type RecordReader, type RecordValues, type RecordValuesStatus, SideEffectDirectiveCard, type SideEffectDirectiveCardProps, TARGETING_CLASSES, defaultFailureWords, describeChangeValue, failureWords, fieldLabel, getDirectiveRenderer, itemChanges, itemRecordId, noteRecordChanged, provisionalDirectiveSlug, readsApplyLedger, recordFallbackName, recordRevision, registerDirectiveRenderer, resetDirectiveRenderers, useRecordRevision, useRecordValues };
|
|
266
|
+
export { ApplyDirectiveButton, type ApplyDirectiveButtonProps, CHANGE_VALUE_MAX, type ChangeValue, type DirectiveApplyPhase, DirectiveChangeList, DirectiveFailure, DirectiveFailureWords, DirectiveFallbackCard, type DirectiveFallbackCardProps, DirectiveHost, DirectiveProvisionalCard, type DirectiveProvisionalCardProps, DirectiveRecordRef, DirectiveRender, type DirectiveRenderProps, type DirectiveRenderer, type DirectiveRendererProps, type DirectiveValueWord, EMPTY_VALUE_WORD, type ItemChange, type ItemChangesOptions, type RecordReader, type RecordValues, type RecordValuesStatus, SideEffectDirectiveCard, type SideEffectDirectiveCardProps, TARGETING_CLASSES, defaultFailureWords, describeChangeValue, directiveFieldLabel, directiveValueWord, failureWords, fieldLabel, getDirectiveRenderer, itemChanges, itemRecordId, noteRecordChanged, provisionalDirectiveSlug, readsApplyLedger, recordFallbackName, recordRevision, registerDirectiveRenderer, resetDirectiveRenderers, useRecordRevision, useRecordValues };
|
package/dist/directives.js
CHANGED
|
@@ -49,9 +49,10 @@ import { nounLabel } from "@ai-matrx/content-ir";
|
|
|
49
49
|
|
|
50
50
|
// directives/item-changes.ts
|
|
51
51
|
import { isUuidShape } from "@ai-matrx/kit/uuid";
|
|
52
|
+
import { humanizeIdentifier } from "@ai-matrx/kit/text-case";
|
|
52
53
|
var TARGETING_CLASSES = /* @__PURE__ */ new Set(["update", "delete"]);
|
|
53
54
|
var NOT_A_CHANGE = /* @__PURE__ */ new Set(["__kind", "id"]);
|
|
54
|
-
var CHANGE_VALUE_MAX =
|
|
55
|
+
var CHANGE_VALUE_MAX = 280;
|
|
55
56
|
function itemRecordId(item) {
|
|
56
57
|
const id = item.id;
|
|
57
58
|
if (typeof id === "string" && id.trim()) return id.trim();
|
|
@@ -59,21 +60,27 @@ function itemRecordId(item) {
|
|
|
59
60
|
return null;
|
|
60
61
|
}
|
|
61
62
|
function fieldLabel(key) {
|
|
62
|
-
|
|
63
|
-
return spaced.charAt(0).toUpperCase() + spaced.slice(1);
|
|
63
|
+
return humanizeIdentifier(key) || key;
|
|
64
64
|
}
|
|
65
|
+
function directiveFieldLabel(key, titleColumn) {
|
|
66
|
+
return titleColumn && key === titleColumn ? "Title" : fieldLabel(key);
|
|
67
|
+
}
|
|
68
|
+
var EMPTY_VALUE_WORD = "None";
|
|
65
69
|
function recordFallbackName(nounLabel3, id) {
|
|
66
70
|
const short = isUuidShape(id) ? id.slice(0, 8) : id.length > 12 ? `${id.slice(0, 12)}\u2026` : id;
|
|
67
71
|
return `${nounLabel3} ${short}`;
|
|
68
72
|
}
|
|
69
|
-
function describeChangeValue(value) {
|
|
70
|
-
return describeValue(value);
|
|
73
|
+
function describeChangeValue(value, word) {
|
|
74
|
+
return describeValue(value, word);
|
|
71
75
|
}
|
|
72
|
-
|
|
73
|
-
|
|
76
|
+
var EMPTY = { value: EMPTY_VALUE_WORD, full: EMPTY_VALUE_WORD, clears: true };
|
|
77
|
+
function describeValue(value, word) {
|
|
78
|
+
if (value === null || value === void 0) return EMPTY;
|
|
74
79
|
if (typeof value === "string") {
|
|
75
80
|
const trimmed = value.trim();
|
|
76
|
-
if (!trimmed) return
|
|
81
|
+
if (!trimmed) return EMPTY;
|
|
82
|
+
const named = word?.(trimmed) ?? null;
|
|
83
|
+
if (named) return { value: named, full: named, clears: false };
|
|
77
84
|
const oneLine = trimmed.replace(/\s+/g, " ");
|
|
78
85
|
const shown = oneLine.length > CHANGE_VALUE_MAX ? `${oneLine.slice(0, CHANGE_VALUE_MAX - 1)}\u2026` : oneLine;
|
|
79
86
|
return { value: shown, full: trimmed, clears: false };
|
|
@@ -83,11 +90,11 @@ function describeValue(value) {
|
|
|
83
90
|
}
|
|
84
91
|
if (Array.isArray(value)) {
|
|
85
92
|
const n2 = value.length;
|
|
86
|
-
const text2 = n2 === 0 ?
|
|
93
|
+
const text2 = n2 === 0 ? EMPTY_VALUE_WORD : `${n2} ${n2 === 1 ? "entry" : "entries"}`;
|
|
87
94
|
return { value: text2, full: safeJson(value), clears: n2 === 0 };
|
|
88
95
|
}
|
|
89
96
|
const n = Object.keys(value).length;
|
|
90
|
-
const text = n === 0 ?
|
|
97
|
+
const text = n === 0 ? EMPTY_VALUE_WORD : `${n} ${n === 1 ? "field" : "fields"}`;
|
|
91
98
|
return { value: text, full: safeJson(value), clears: n === 0 };
|
|
92
99
|
}
|
|
93
100
|
function safeJson(value) {
|
|
@@ -112,10 +119,12 @@ function itemChanges(item, current, options = {}) {
|
|
|
112
119
|
const titleColumn = options.titleColumn ?? null;
|
|
113
120
|
for (const [key, raw] of Object.entries(item)) {
|
|
114
121
|
if (NOT_A_CHANGE.has(key)) continue;
|
|
115
|
-
const label = key
|
|
116
|
-
const
|
|
122
|
+
const label = directiveFieldLabel(key, titleColumn);
|
|
123
|
+
const valueWord = options.valueWord;
|
|
124
|
+
const word = key === titleColumn || !valueWord ? void 0 : (v) => valueWord(key, v);
|
|
125
|
+
const change = { key, label, ...describeValue(raw, word) };
|
|
117
126
|
if (current && Object.prototype.hasOwnProperty.call(current, key)) {
|
|
118
|
-
change.before = describeValue(current[key]);
|
|
127
|
+
change.before = describeValue(current[key], word);
|
|
119
128
|
change.same = sameValue(current[key], raw);
|
|
120
129
|
}
|
|
121
130
|
out.push(change);
|
|
@@ -571,7 +580,7 @@ function ApplyDirectiveButton({
|
|
|
571
580
|
type: "button",
|
|
572
581
|
disabled: askingAgain,
|
|
573
582
|
onClick: () => void handleApply(!bad),
|
|
574
|
-
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",
|
|
583
|
+
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",
|
|
575
584
|
"data-apply-action": bad ? "retry" : "run-again",
|
|
576
585
|
children: [
|
|
577
586
|
/* @__PURE__ */ jsx3(RotateCcwIcon, { className: "h-3 w-3" }),
|
|
@@ -611,8 +620,8 @@ function ApplyDirectiveButton({
|
|
|
611
620
|
}
|
|
612
621
|
const destructive = directive.directiveClass === "delete";
|
|
613
622
|
const muted = nothingToChange && view.status === "idle";
|
|
614
|
-
return /* @__PURE__ */ jsxs2("span", { className: "
|
|
615
|
-
muted ? /* @__PURE__ */ jsx3("span", { className: "text-xs text-muted-foreground", "data-apply-nothing": "", children: "Nothing to change" }) : null,
|
|
623
|
+
return /* @__PURE__ */ jsxs2("span", { className: "flex min-w-0 flex-wrap items-center justify-end gap-x-2 gap-y-1", children: [
|
|
624
|
+
muted ? /* @__PURE__ */ jsx3("span", { className: "min-w-0 text-xs text-muted-foreground", "data-apply-nothing": "", children: "Nothing to change" }) : null,
|
|
616
625
|
/* @__PURE__ */ jsxs2(
|
|
617
626
|
"button",
|
|
618
627
|
{
|
|
@@ -621,7 +630,7 @@ function ApplyDirectiveButton({
|
|
|
621
630
|
disabled: view.status === "applying" || view.status === "asking" || items.length === 0,
|
|
622
631
|
"data-apply-tone": muted ? "muted" : destructive ? "destructive" : "default",
|
|
623
632
|
title: muted ? "It sets no fields, so applying it changes nothing." : void 0,
|
|
624
|
-
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"}`,
|
|
633
|
+
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"}`,
|
|
625
634
|
children: [
|
|
626
635
|
view.status === "applying" ? /* @__PURE__ */ jsx3(LoaderIcon, { className: "h-3.5 w-3.5 animate-spin" }) : /* @__PURE__ */ jsx3(PlayIcon, { className: "h-3.5 w-3.5" }),
|
|
627
636
|
view.status === "applying" ? `Applying${itemCount ? ` ${itemCount} ${itemCount === 1 ? "item" : "items"}` : ""}\u2026${elapsed ? ` ${elapsed}s` : ""}` : label
|
|
@@ -672,7 +681,7 @@ function FailureNotice({
|
|
|
672
681
|
type: "button",
|
|
673
682
|
onClick: () => setOpen((v) => !v),
|
|
674
683
|
"aria-expanded": open,
|
|
675
|
-
className: "ml-1 underline underline-offset-2 hover:no-underline",
|
|
684
|
+
className: "ml-1 whitespace-nowrap underline underline-offset-2 hover:no-underline",
|
|
676
685
|
"data-apply-failure-details-toggle": true,
|
|
677
686
|
children: open ? "Hide details" : "Details"
|
|
678
687
|
}
|
|
@@ -701,6 +710,14 @@ import {
|
|
|
701
710
|
nounTitleColumn
|
|
702
711
|
} from "@ai-matrx/content-ir";
|
|
703
712
|
import { Fragment, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
713
|
+
function directiveValueWord(host, noun) {
|
|
714
|
+
const valueLabel = host.valueLabel;
|
|
715
|
+
return valueLabel ? (field, value) => valueLabel({ noun, field, value }) : null;
|
|
716
|
+
}
|
|
717
|
+
function omitKey(item, key) {
|
|
718
|
+
const { [key]: _omitted, ...rest } = item;
|
|
719
|
+
return rest;
|
|
720
|
+
}
|
|
704
721
|
var ROWS_BEFORE_FOLD = 3;
|
|
705
722
|
function ItemRow({
|
|
706
723
|
directive,
|
|
@@ -717,16 +734,21 @@ function ItemRow({
|
|
|
717
734
|
const titleColumn = nounTitleColumn(directive.noun, host.nouns);
|
|
718
735
|
const title = itemTitle(item, titleColumn, index, total);
|
|
719
736
|
const subtitle = itemSubtitle(item);
|
|
720
|
-
const
|
|
737
|
+
const valueWord = directiveValueWord(host, directive.noun);
|
|
738
|
+
const facts = itemFacts(titleColumn ? omitKey(item, titleColumn) : item).map((fact) => ({
|
|
739
|
+
...fact,
|
|
740
|
+
label: directiveFieldLabel(fact.key, titleColumn),
|
|
741
|
+
value: valueWord?.(fact.key, fact.value) ?? fact.value
|
|
742
|
+
}));
|
|
721
743
|
const kind = host.itemKind?.(directive.slug) ?? null;
|
|
722
744
|
const display = directiveDisplay(directive.directiveClass, directive.noun, host.nouns);
|
|
723
745
|
const openItem = host.openItem;
|
|
724
746
|
const body = /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
725
747
|
/* @__PURE__ */ jsx4("span", { className: "min-w-0 shrink-0 truncate font-medium text-foreground", children: title }),
|
|
726
|
-
/* @__PURE__ */ jsx4("span", { className: "hidden min-w-0 flex-1 items-baseline gap-2 overflow-hidden sm:flex", children: facts.map((fact) => /* @__PURE__ */ jsxs3("span", { className: "truncate text-[11px] text-muted-foreground", children: [
|
|
727
|
-
fact.
|
|
748
|
+
/* @__PURE__ */ jsx4("span", { className: "hidden min-w-0 flex-1 items-baseline gap-2 overflow-hidden sm:flex", children: facts.map((fact) => /* @__PURE__ */ jsxs3("span", { className: "truncate text-[11px] text-muted-foreground", "data-item-fact": fact.key, children: [
|
|
749
|
+
fact.label,
|
|
728
750
|
" ",
|
|
729
|
-
fact.
|
|
751
|
+
/* @__PURE__ */ jsx4("span", { className: "text-foreground/80", children: fact.value })
|
|
730
752
|
] }, fact.key)) }),
|
|
731
753
|
subtitle && facts.length === 0 ? /* @__PURE__ */ jsx4("span", { className: "hidden truncate text-[11px] text-muted-foreground sm:inline", children: subtitle }) : null,
|
|
732
754
|
openItem ? /* @__PURE__ */ jsx4(MaximizeIcon, { className: "ml-auto h-3 w-3 shrink-0 text-muted-foreground" }) : null
|
|
@@ -761,35 +783,36 @@ function DirectiveChangeList({
|
|
|
761
783
|
if (changes.length === 0) {
|
|
762
784
|
return /* @__PURE__ */ jsx4("p", { className: `text-[11px] text-muted-foreground${className ? ` ${className}` : ""}`, children: "Sets no fields \u2014 nothing would change." });
|
|
763
785
|
}
|
|
764
|
-
return /* @__PURE__ */ jsx4("ul", { className:
|
|
786
|
+
return /* @__PURE__ */ jsx4("ul", { className: `@container space-y-1${className ? ` ${className}` : ""}`, "data-directive-changes": "", children: changes.map((change) => {
|
|
765
787
|
const before = change.before && !change.same ? change.before : null;
|
|
766
|
-
const was = before ? before.clears ? "empty" : before.value : null;
|
|
767
788
|
return /* @__PURE__ */ jsxs3(
|
|
768
789
|
"li",
|
|
769
790
|
{
|
|
770
|
-
className: "flex min-w-0 items-baseline gap-1.5
|
|
771
|
-
title: before ? `${change.label}: ${before.
|
|
791
|
+
className: "flex min-w-0 flex-col text-[11px] @xs:flex-row @xs:flex-wrap @xs:items-baseline @xs:gap-x-1.5",
|
|
792
|
+
title: before ? `${change.label}: ${before.full} \u2192 ${change.full}` : `${change.label} \u2192 ${change.full}`,
|
|
772
793
|
"data-change-key": change.key,
|
|
773
794
|
children: [
|
|
774
795
|
/* @__PURE__ */ jsx4("span", { className: "shrink-0 text-muted-foreground", children: change.label }),
|
|
775
|
-
|
|
796
|
+
before ? /* @__PURE__ */ jsx4(
|
|
776
797
|
"span",
|
|
777
798
|
{
|
|
778
|
-
className: "min-w-0
|
|
799
|
+
className: "min-w-0 text-muted-foreground line-through [overflow-wrap:anywhere]",
|
|
779
800
|
"data-change-before": "",
|
|
780
|
-
children:
|
|
801
|
+
children: before.value
|
|
781
802
|
}
|
|
782
803
|
) : null,
|
|
783
|
-
/* @__PURE__ */
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
804
|
+
/* @__PURE__ */ jsxs3("span", { className: "flex min-w-0 items-baseline gap-1.5", children: [
|
|
805
|
+
/* @__PURE__ */ jsx4("span", { "aria-hidden": true, className: "shrink-0 text-muted-foreground", children: "\u2192" }),
|
|
806
|
+
/* @__PURE__ */ jsx4(
|
|
807
|
+
"span",
|
|
808
|
+
{
|
|
809
|
+
className: `min-w-0 [overflow-wrap:anywhere] ${change.clears ? "italic text-muted-foreground" : "text-foreground"}`,
|
|
810
|
+
"data-change-after": "",
|
|
811
|
+
children: change.value
|
|
812
|
+
}
|
|
813
|
+
),
|
|
814
|
+
change.same ? /* @__PURE__ */ jsx4("span", { className: "shrink-0 text-muted-foreground", children: "(no change)" }) : null
|
|
815
|
+
] })
|
|
793
816
|
]
|
|
794
817
|
},
|
|
795
818
|
change.key
|
|
@@ -812,12 +835,20 @@ function TargetRow({
|
|
|
812
835
|
readsLive ? { noun: directive.noun, id: recordId } : null
|
|
813
836
|
);
|
|
814
837
|
const compareTo = phase.phase === "applied" ? phase.before?.[index] ?? null : readsLive ? live.values : null;
|
|
815
|
-
const changes = isUpdate ? itemChanges(item, compareTo, {
|
|
838
|
+
const changes = isUpdate ? itemChanges(item, compareTo, {
|
|
839
|
+
titleColumn: nounTitleColumn(directive.noun, host.nouns),
|
|
840
|
+
valueWord: directiveValueWord(host, directive.noun)
|
|
841
|
+
}) : [];
|
|
816
842
|
const name = host.renderRecord ? host.renderRecord({ noun: directive.noun, id: recordId, fallback, context: "row" }) : /* @__PURE__ */ jsx4("span", { className: "truncate font-medium text-foreground", children: fallback });
|
|
817
843
|
return /* @__PURE__ */ jsxs3("div", { className: "py-1 text-xs", "data-directive-target": recordId, children: [
|
|
818
844
|
/* @__PURE__ */ jsxs3("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
819
845
|
/* @__PURE__ */ jsx4("span", { className: "flex min-w-0 flex-1 items-center gap-1 px-1", children: name }),
|
|
820
|
-
host.renderCopy?.({
|
|
846
|
+
host.renderCopy?.({
|
|
847
|
+
label: `this ${nounLabel2(directive.noun, host.nouns).toLowerCase()}`,
|
|
848
|
+
value: item,
|
|
849
|
+
size: "xs",
|
|
850
|
+
record: { noun: directive.noun, id: recordId }
|
|
851
|
+
})
|
|
821
852
|
] }),
|
|
822
853
|
isUpdate ? /* @__PURE__ */ jsx4(DirectiveChangeList, { changes, className: "mt-0.5 px-1" }) : null
|
|
823
854
|
] });
|
|
@@ -845,7 +876,7 @@ function SideEffectDirectiveCard({ directive }) {
|
|
|
845
876
|
" ",
|
|
846
877
|
total === 1 ? "item" : "items"
|
|
847
878
|
] }),
|
|
848
|
-
/* @__PURE__ */ jsxs3("div", { className: "ml-auto flex items-center gap-1", children: [
|
|
879
|
+
/* @__PURE__ */ jsxs3("div", { className: "ml-auto flex min-w-0 flex-wrap items-center justify-end gap-1", children: [
|
|
849
880
|
host.renderCopy?.({ label: display.title, value: directive.shell, size: "icon" }),
|
|
850
881
|
/* @__PURE__ */ jsx4(
|
|
851
882
|
ApplyDirectiveButton,
|
|
@@ -867,7 +898,7 @@ function SideEffectDirectiveCard({ directive }) {
|
|
|
867
898
|
{
|
|
868
899
|
type: "button",
|
|
869
900
|
onClick: () => setExpanded((v) => !v),
|
|
870
|
-
className: "mt-0.5 inline-flex items-center gap-1 rounded px-1 py-0.5 text-[11px] text-muted-foreground hover:text-foreground",
|
|
901
|
+
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",
|
|
871
902
|
children: [
|
|
872
903
|
expanded ? /* @__PURE__ */ jsx4(ChevronDownIcon, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx4(ChevronRightIcon, { className: "h-3 w-3" }),
|
|
873
904
|
expanded ? "Show less" : `Show ${hidden} more`
|
|
@@ -994,10 +1025,13 @@ export {
|
|
|
994
1025
|
DirectiveProvisionalCard,
|
|
995
1026
|
DirectiveRender,
|
|
996
1027
|
DirectiveScopeProvider,
|
|
1028
|
+
EMPTY_VALUE_WORD,
|
|
997
1029
|
SideEffectDirectiveCard,
|
|
998
1030
|
TARGETING_CLASSES,
|
|
999
1031
|
defaultFailureWords,
|
|
1000
1032
|
describeChangeValue,
|
|
1033
|
+
directiveFieldLabel,
|
|
1034
|
+
directiveValueWord,
|
|
1001
1035
|
failureWords,
|
|
1002
1036
|
fieldLabel,
|
|
1003
1037
|
getDirectiveRenderer,
|