@ai-matrx/rich-content 0.2.45 → 0.2.47

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 CHANGED
@@ -1,5 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.47
4
+
5
+ - The JSON value types and guards (`isJsonObject`, `isJsonArray`, `isJsonPrimitive`, `Json*`)
6
+ in `./utils/json` are re-exported from their one home, `@ai-matrx/kit/json-format`; only
7
+ `toJsonRecord` stays rich-content's own (architecture step 3).
8
+
9
+ Consumer action: none — `@ai-matrx/rich-content/utils/json` keeps every name.
10
+
11
+ ## 0.2.46
12
+
13
+ - **A text field's "…" menu reads its text aloud.** `RegistryActionList` has no bar above it,
14
+ so it now lists the bar's primary rows too (new `barlessMenuActions`): plain "Read aloud"
15
+ (`tts-play`) leads ProTextarea's menu instead of being filtered out, leaving only the AI
16
+ summaries. Guard: `variants/shared/__tests__/barless-menu-reads-aloud.test.ts`.
17
+
18
+ Consumer action: none.
19
+
3
20
  ## 0.2.45
4
21
 
5
22
  - The delimiter guard and the thinking-tag helpers are read from their one home,
@@ -111,7 +111,7 @@ declare const JSON_BLOCK_PATTERNS: {
111
111
  };
112
112
  readonly decision_tree: {
113
113
  readonly rootKey: "decision_tree";
114
- readonly validate: (parsed: unknown) => import("../../../../utils/json.js").JsonValue | undefined;
114
+ readonly validate: (parsed: unknown) => import("@ai-matrx/kit/json-format").JsonValue | undefined;
115
115
  };
116
116
  readonly comparison_table: {
117
117
  readonly rootKey: "comparison";
@@ -6,11 +6,11 @@ import { cn } from "@ai-matrx/design-system";
6
6
  import { useActionSurfaceProvider } from "../runtime/useActionSurfaceProvider.js";
7
7
  import {
8
8
  AI_SUBMENU_LABEL,
9
+ barlessMenuActions,
9
10
  buildMenuTree,
10
11
  withAiSlot
11
12
  } from "./shared/menuStructure.js";
12
13
  import { resolveActionDisplay, runAction } from "./shared/runAction.js";
13
- import { menuActions } from "./RegistryActionMenu.js";
14
14
  const ROW = "flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-left text-sm text-foreground transition-colors hover:bg-accent hover:text-accent-foreground disabled:opacity-50";
15
15
  function RegistryActionList(props) {
16
16
  const { content, source, actions, onClose, className, aiSlot } = props;
@@ -25,7 +25,9 @@ function RegistryActionList(props) {
25
25
  ...getCtx(),
26
26
  onClose
27
27
  });
28
- const tree = buildMenuTree(menuActions(resolvedActions), { aiSlot: Boolean(aiSlot) });
28
+ const tree = buildMenuTree(barlessMenuActions(resolvedActions), {
29
+ aiSlot: Boolean(aiSlot)
30
+ });
29
31
  const submenus = withAiSlot(tree.submenus, Boolean(aiSlot));
30
32
  if (!aiSlot && tree.topLevel.length === 0 && tree.submenus.length === 0 && tree.extras.length === 0) {
31
33
  return null;
@@ -68,6 +68,14 @@ export declare function buildMenuTree(input: RichDocumentAction[], options?: {
68
68
  * keeps every host's tree identical (guard: __tests__/oneMenuTree.test.ts).
69
69
  */
70
70
  export declare function registryMenuActions(actions: RichDocumentAction[]): RichDocumentAction[];
71
+ /**
72
+ * The rows of a menu that has NO bar above it (ProTextarea / ProInput's "…"
73
+ * menu). A bar's primary buttons — Read aloud above all — have nowhere else to
74
+ * appear there, so they are listed too, in MENU_STRUCTURE's promoted section
75
+ * (which names them first for exactly these hosts). Dropping them is how a
76
+ * text field's menu lost plain read-aloud and offered only AI summaries.
77
+ */
78
+ export declare function barlessMenuActions(actions: RichDocumentAction[]): RichDocumentAction[];
71
79
  /**
72
80
  * The AI submenu, guaranteed present when a host has its own AI rows to fold
73
81
  * in (a ProTextarea's bound agents, the v3 agent-shortcut libraries), at the
@@ -222,6 +222,9 @@ function buildMenuTree(input, options = {}) {
222
222
  function registryMenuActions(actions) {
223
223
  return actions.filter((a) => (a.renderSlot ?? "overflow") !== "primary");
224
224
  }
225
+ function barlessMenuActions(actions) {
226
+ return actions;
227
+ }
225
228
  function withAiSlot(submenus, hasSlot) {
226
229
  if (!hasSlot || submenus.some((s) => s.label === AI_SUBMENU_LABEL)) return submenus;
227
230
  const ai = {
@@ -262,6 +265,7 @@ export {
262
265
  AI_SUBMENU_LABEL,
263
266
  CONVERSATION_SUBMENU_LABEL,
264
267
  MENU_STRUCTURE,
268
+ barlessMenuActions,
265
269
  buildMenuTree,
266
270
  extendMenuSection,
267
271
  flattenMenuTreeIds,
@@ -35,21 +35,9 @@
35
35
  * open / loosely-shaped JSON the standards doc calls "just an object" — they
36
36
  * give it an honest name so nobody reaches for `any` or a whole-row cast.
37
37
  */
38
- export type JsonPrimitive = string | number | boolean | null;
39
- /**
40
- * A JSON object. Values are `JsonValue | undefined` so optional keys read
41
- * cleanly (mirrors Supabase's original generated `Json` object member).
42
- */
43
- export interface JsonObject {
44
- [key: string]: JsonValue | undefined;
45
- }
46
- export type JsonArray = JsonValue[];
47
- export type JsonValue = JsonPrimitive | JsonObject | JsonArray;
48
- /**
49
- * Narrow an `unknown` (e.g. a bare JSONB column) to a `JsonObject`.
50
- * Plain object only — arrays and `null` return false.
51
- */
52
- export declare function isJsonObject(value: unknown): value is JsonObject;
38
+ import type { JsonObject, JsonValue } from "@ai-matrx/kit/json-format";
39
+ export { isJsonArray, isJsonObject, isJsonPrimitive } from "@ai-matrx/kit/json-format";
40
+ export type { JsonArray, JsonObject, JsonPrimitive, JsonValue } from "@ai-matrx/kit/json-format";
53
41
  /**
54
42
  * Convert a `JsonObject` (values `JsonValue | undefined`) into the strict
55
43
  * `Record<string, JsonValue>` shape generated API request bodies demand,
@@ -57,7 +45,3 @@ export declare function isJsonObject(value: unknown): value is JsonObject;
57
45
  * only appears via optional-key reads). Cast-free by construction.
58
46
  */
59
47
  export declare function toJsonRecord(obj: JsonObject): Record<string, JsonValue>;
60
- /** Narrow an `unknown` to a `JsonArray`. */
61
- export declare function isJsonArray(value: unknown): value is JsonArray;
62
- /** Narrow an `unknown` to a JSON primitive (string | number | boolean | null). */
63
- export declare function isJsonPrimitive(value: unknown): value is JsonPrimitive;
@@ -1,6 +1,4 @@
1
- function isJsonObject(value) {
2
- return typeof value === "object" && value !== null && !Array.isArray(value);
3
- }
1
+ import { isJsonArray, isJsonObject, isJsonPrimitive } from "@ai-matrx/kit/json-format";
4
2
  function toJsonRecord(obj) {
5
3
  const out = {};
6
4
  for (const [key, value] of Object.entries(obj)) {
@@ -8,12 +6,6 @@ function toJsonRecord(obj) {
8
6
  }
9
7
  return out;
10
8
  }
11
- function isJsonArray(value) {
12
- return Array.isArray(value);
13
- }
14
- function isJsonPrimitive(value) {
15
- return value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
16
- }
17
9
  export {
18
10
  isJsonArray,
19
11
  isJsonObject,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-matrx/rich-content",
3
- "version": "0.2.45",
3
+ "version": "0.2.47",
4
4
  "description": "The AI Matrx formatted-text engine: the one markdown renderer, streaming markdown, the block splitter and renderer, the generic blocks, <RichContent> levels, the rich-document action registry and menus, copy, and the selection toolbar — as portable React.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -130,17 +130,17 @@
130
130
  "unist-util-visit": "^5.1.0",
131
131
  "unist-util-visit-parents": "^6.0.2",
132
132
  "yaml": "^2.9.1",
133
- "@ai-matrx/alchemy": "latest",
134
133
  "@ai-matrx/canvas": "latest",
135
134
  "@ai-matrx/content-ir": "latest",
136
135
  "@ai-matrx/content-ir-react": "latest",
137
136
  "@ai-matrx/data": "latest",
137
+ "@ai-matrx/alchemy": "latest",
138
138
  "@ai-matrx/design-system": "latest",
139
+ "@ai-matrx/diff": "latest",
139
140
  "@ai-matrx/icons": "latest",
140
141
  "@ai-matrx/kit": "latest",
141
- "@ai-matrx/print": "latest",
142
142
  "@ai-matrx/media": "latest",
143
- "@ai-matrx/diff": "latest",
143
+ "@ai-matrx/print": "latest",
144
144
  "@ai-matrx/records": "latest",
145
145
  "@ai-matrx/records-ui": "latest",
146
146
  "@ai-matrx/tap-target": "latest",