@ai-matrx/rich-content 0.0.0 → 0.2.3

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.
Files changed (248) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/LICENSE +1 -1
  3. package/README.md +58 -3
  4. package/dist/display/blocks/csv/CsvBlock.d.ts +10 -0
  5. package/dist/display/blocks/csv/CsvBlock.js +245 -0
  6. package/dist/display/blocks/table/parseMarkdownTable.d.ts +20 -0
  7. package/dist/display/blocks/table/parseMarkdownTable.js +35 -0
  8. package/dist/display/chat-markdown/citations/remarkMatrxCite.d.ts +33 -0
  9. package/dist/display/chat-markdown/citations/remarkMatrxCite.js +71 -0
  10. package/dist/display/chat-markdown/matrx-variables/remarkMatrxVariable.d.ts +29 -0
  11. package/dist/display/chat-markdown/matrx-variables/remarkMatrxVariable.js +71 -0
  12. package/dist/display/chat-markdown/page-break/remarkMatrxPageBreak.d.ts +55 -0
  13. package/dist/display/chat-markdown/page-break/remarkMatrxPageBreak.js +108 -0
  14. package/dist/display/chat-markdown/rehypeSafeRawHtml.d.ts +59 -0
  15. package/dist/display/chat-markdown/rehypeSafeRawHtml.js +140 -0
  16. package/dist/display/markdown-classification/processors/bock-processors/parse-markdown-table.d.ts +14 -0
  17. package/dist/display/markdown-classification/processors/bock-processors/parse-markdown-table.js +171 -0
  18. package/dist/display/markdown-classification/processors/types.d.ts +120 -0
  19. package/dist/display/markdown-classification/processors/types.js +10 -0
  20. package/dist/display/markdown-classification/processors/utils/client-blocks.d.ts +169 -0
  21. package/dist/display/markdown-classification/processors/utils/client-blocks.js +0 -0
  22. package/dist/display/markdown-classification/processors/utils/content-splitter-core.d.ts +223 -0
  23. package/dist/display/markdown-classification/processors/utils/content-splitter-core.js +1791 -0
  24. package/dist/display/markdown-classification/processors/utils/content-splitter-v2.d.ts +15 -0
  25. package/dist/display/markdown-classification/processors/utils/content-splitter-v2.js +19 -0
  26. package/dist/display/markdown-classification/processors/utils/expand-text-blocks.d.ts +9 -0
  27. package/dist/display/markdown-classification/processors/utils/expand-text-blocks.js +36 -0
  28. package/dist/display/markdown-classification/processors/utils/gfm-table-lines.d.ts +5 -0
  29. package/dist/display/markdown-classification/processors/utils/gfm-table-lines.js +40 -0
  30. package/dist/display/markdown-classification/processors/utils/gfm-table-vector-inputs.d.ts +16 -0
  31. package/dist/display/markdown-classification/processors/utils/gfm-table-vector-inputs.js +385 -0
  32. package/dist/display/markdown-classification/processors/utils/gfm-table-vectors.d.ts +43 -0
  33. package/dist/display/markdown-classification/processors/utils/gfm-table-vectors.js +33 -0
  34. package/dist/display/markdown-classification/processors/utils/table-data-parser.d.ts +9 -0
  35. package/dist/display/markdown-classification/processors/utils/table-data-parser.js +30 -0
  36. package/dist/display/markdown-classification/processors/utils/thinking-parser.d.ts +7 -0
  37. package/dist/display/markdown-classification/processors/utils/thinking-parser.js +70 -0
  38. package/dist/display/render-block.d.ts +23 -0
  39. package/dist/display/render-block.js +0 -0
  40. package/dist/display/themes.d.ts +1023 -0
  41. package/dist/display/themes.js +1105 -0
  42. package/dist/display/types.d.ts +32 -0
  43. package/dist/display/types.js +0 -0
  44. package/dist/host/ContentIrHostBoundary.d.ts +8 -0
  45. package/dist/host/ContentIrHostBoundary.js +15 -0
  46. package/dist/host/ErrorActions.d.ts +4 -0
  47. package/dist/host/ErrorActions.js +11 -0
  48. package/dist/host/NestedContent.d.ts +3 -0
  49. package/dist/host/NestedContent.js +12 -0
  50. package/dist/host/ResourcePeek.d.ts +6 -0
  51. package/dist/host/ResourcePeek.js +14 -0
  52. package/dist/host/component-registry.d.ts +2 -0
  53. package/dist/host/component-registry.js +25 -0
  54. package/dist/host/diagnostics.d.ts +2 -0
  55. package/dist/host/diagnostics.js +15 -0
  56. package/dist/host/index.d.ts +3 -0
  57. package/dist/host/index.js +18 -0
  58. package/dist/host/kind-incident.d.ts +3 -0
  59. package/dist/host/kind-incident.js +12 -0
  60. package/dist/host/kind-registry.d.ts +2 -0
  61. package/dist/host/kind-registry.js +35 -0
  62. package/dist/host/people.d.ts +3 -0
  63. package/dist/host/people.js +12 -0
  64. package/dist/host/registry.d.ts +27 -0
  65. package/dist/host/registry.js +55 -0
  66. package/dist/host/splitter-envelopes.d.ts +2 -0
  67. package/dist/host/splitter-envelopes.js +7 -0
  68. package/dist/host/tables.d.ts +6 -0
  69. package/dist/host/tables.js +8 -0
  70. package/dist/host/toast.d.ts +2 -0
  71. package/dist/host/toast.js +57 -0
  72. package/dist/host/types.d.ts +157 -0
  73. package/dist/host/types.js +0 -0
  74. package/dist/host/wikilinks.d.ts +15 -0
  75. package/dist/host/wikilinks.js +23 -0
  76. package/dist/kinds/host/route-env.d.ts +33 -0
  77. package/dist/kinds/host/route-env.js +16 -0
  78. package/dist/kinds/react/KindEscapedNotice.d.ts +14 -0
  79. package/dist/kinds/react/KindEscapedNotice.js +72 -0
  80. package/dist/kinds/react/ProvisionalKindBoundary.d.ts +19 -0
  81. package/dist/kinds/react/ProvisionalKindBoundary.js +17 -0
  82. package/dist/kinds/react/ensure-kind-renderable.d.ts +14 -0
  83. package/dist/kinds/react/ensure-kind-renderable.js +45 -0
  84. package/dist/kinds/react/kind-problems.d.ts +62 -0
  85. package/dist/kinds/react/kind-problems.js +134 -0
  86. package/dist/kinds/react/kind-route.d.ts +23 -0
  87. package/dist/kinds/react/kind-route.js +24 -0
  88. package/dist/kinds/react/loading/infer-loading-slug.d.ts +58 -0
  89. package/dist/kinds/react/loading/infer-loading-slug.js +100 -0
  90. package/dist/kinds/react/loading/kind-loading-components.d.ts +48 -0
  91. package/dist/kinds/react/loading/kind-loading-components.js +447 -0
  92. package/dist/kinds/react/loading/kind-loading-registry.d.ts +21 -0
  93. package/dist/kinds/react/loading/kind-loading-registry.js +62 -0
  94. package/dist/kinds/react/loading/kind-loading-slugs.d.ts +18 -0
  95. package/dist/kinds/react/loading/kind-loading-slugs.js +34 -0
  96. package/dist/kinds/react/loading/kind-loading.types.d.ts +79 -0
  97. package/dist/kinds/react/loading/kind-loading.types.js +31 -0
  98. package/dist/kinds/react/loading/resolve-loading-slug.d.ts +29 -0
  99. package/dist/kinds/react/loading/resolve-loading-slug.js +51 -0
  100. package/dist/kinds/react/partial-kind-route.d.ts +32 -0
  101. package/dist/kinds/react/partial-kind-route.js +27 -0
  102. package/dist/kinds/react/registry-versioned.d.ts +54 -0
  103. package/dist/kinds/react/registry-versioned.js +18 -0
  104. package/dist/kinds/react/route-at-version.d.ts +38 -0
  105. package/dist/kinds/react/route-at-version.js +78 -0
  106. package/dist/kinds/react/slot/KindSlot.d.ts +87 -0
  107. package/dist/kinds/react/slot/KindSlot.js +65 -0
  108. package/dist/kinds/react/use-registry-repaint.d.ts +6 -0
  109. package/dist/kinds/react/use-registry-repaint.js +36 -0
  110. package/dist/kinds/react/useIrNode.d.ts +9 -0
  111. package/dist/kinds/react/useIrNode.js +46 -0
  112. package/dist/kinds/react/useLiveJsonRegion.d.ts +15 -0
  113. package/dist/kinds/react/useLiveJsonRegion.js +84 -0
  114. package/dist/kinds/redux/render-block-envelope.d.ts +14 -0
  115. package/dist/kinds/redux/render-block-envelope.js +26 -0
  116. package/dist/kinds/registry/kind-correctors.d.ts +63 -0
  117. package/dist/kinds/registry/kind-correctors.js +94 -0
  118. package/dist/kinds/registry/legacy-quiz-envelope.d.ts +1 -0
  119. package/dist/kinds/registry/legacy-quiz-envelope.js +1 -0
  120. package/dist/kinds/registry/region-envelope-memo.d.ts +45 -0
  121. package/dist/kinds/registry/region-envelope-memo.js +94 -0
  122. package/dist/kinds/registry/registry-debug.d.ts +38 -0
  123. package/dist/kinds/registry/registry-debug.js +39 -0
  124. package/dist/markdown-core/MarkdownCore.d.ts +6 -0
  125. package/dist/markdown-core/MarkdownCore.js +32 -0
  126. package/dist/markdown-core/MarkdownCoreImpl.d.ts +3 -0
  127. package/dist/markdown-core/MarkdownCoreImpl.js +27 -0
  128. package/dist/markdown-core/MarkdownCoreServer.d.ts +4 -0
  129. package/dist/markdown-core/MarkdownCoreServer.js +26 -0
  130. package/dist/markdown-core/heading-anchors-context.d.ts +2 -0
  131. package/dist/markdown-core/heading-anchors-context.js +11 -0
  132. package/dist/markdown-core/heading-anchors-props.d.ts +2 -0
  133. package/dist/markdown-core/heading-anchors-props.js +6 -0
  134. package/dist/markdown-core/markdown-core-html.d.ts +3 -0
  135. package/dist/markdown-core/markdown-core-html.js +33 -0
  136. package/dist/markdown-core/markdown-core-presets.d.ts +22 -0
  137. package/dist/markdown-core/markdown-core-presets.js +118 -0
  138. package/dist/markdown-core/markdown-core-types.d.ts +43 -0
  139. package/dist/markdown-core/markdown-core-types.js +0 -0
  140. package/dist/markdown-core/math/vendor/micromark-math-math-flow.d.ts +15 -0
  141. package/dist/markdown-core/math/vendor/micromark-math-math-flow.js +143 -0
  142. package/dist/markdown-core/math/vendor/micromark-math-math-text.d.ts +24 -0
  143. package/dist/markdown-core/math/vendor/micromark-math-math-text.js +127 -0
  144. package/dist/markdown-core/math/vendor/micromark-math-syntax.d.ts +30 -0
  145. package/dist/markdown-core/math/vendor/micromark-math-syntax.js +15 -0
  146. package/dist/markdown-core/math/vendor/rehype-katex.d.ts +15 -0
  147. package/dist/markdown-core/math/vendor/rehype-katex.js +83 -0
  148. package/dist/markdown-core/math/vendor/remark-math.d.ts +9 -0
  149. package/dist/markdown-core/math/vendor/remark-math.js +20 -0
  150. package/dist/markdown-core/math-normalizer.d.ts +57 -0
  151. package/dist/markdown-core/math-normalizer.js +315 -0
  152. package/dist/markdown-core/plain-title.d.ts +2 -0
  153. package/dist/markdown-core/plain-title.js +1 -0
  154. package/dist/markdown-core/stream-heal.d.ts +2 -0
  155. package/dist/markdown-core/stream-heal.js +184 -0
  156. package/dist/markdown-core/streaming-context.d.ts +2 -0
  157. package/dist/markdown-core/streaming-context.js +11 -0
  158. package/dist/markdown-core/syntax/callout-types.d.ts +9 -0
  159. package/dist/markdown-core/syntax/callout-types.js +101 -0
  160. package/dist/markdown-core/syntax/containers.d.ts +17 -0
  161. package/dist/markdown-core/syntax/containers.js +353 -0
  162. package/dist/markdown-core/syntax/document-numbering.d.ts +52 -0
  163. package/dist/markdown-core/syntax/document-numbering.js +184 -0
  164. package/dist/markdown-core/syntax/elements/CalloutIcon.d.ts +3 -0
  165. package/dist/markdown-core/syntax/elements/CalloutIcon.js +41 -0
  166. package/dist/markdown-core/syntax/elements/CrossRef.d.ts +12 -0
  167. package/dist/markdown-core/syntax/elements/CrossRef.js +57 -0
  168. package/dist/markdown-core/syntax/elements/CsvFence.d.ts +4 -0
  169. package/dist/markdown-core/syntax/elements/CsvFence.js +18 -0
  170. package/dist/markdown-core/syntax/elements/DetailsElements.d.ts +12 -0
  171. package/dist/markdown-core/syntax/elements/DetailsElements.js +38 -0
  172. package/dist/markdown-core/syntax/elements/DocumentNumbering.d.ts +20 -0
  173. package/dist/markdown-core/syntax/elements/DocumentNumbering.js +37 -0
  174. package/dist/markdown-core/syntax/elements/DocumentPropertiesPanel.d.ts +4 -0
  175. package/dist/markdown-core/syntax/elements/DocumentPropertiesPanel.js +46 -0
  176. package/dist/markdown-core/syntax/elements/InDocAnchor.d.ts +11 -0
  177. package/dist/markdown-core/syntax/elements/InDocAnchor.js +87 -0
  178. package/dist/markdown-core/syntax/elements/MarkdownSourceEdit.d.ts +24 -0
  179. package/dist/markdown-core/syntax/elements/MarkdownSourceEdit.js +28 -0
  180. package/dist/markdown-core/syntax/elements/MatrxTabs.d.ts +10 -0
  181. package/dist/markdown-core/syntax/elements/MatrxTabs.js +59 -0
  182. package/dist/markdown-core/syntax/elements/MentionChip.d.ts +7 -0
  183. package/dist/markdown-core/syntax/elements/MentionChip.js +69 -0
  184. package/dist/markdown-core/syntax/elements/NestedBody.d.ts +3 -0
  185. package/dist/markdown-core/syntax/elements/NestedBody.js +13 -0
  186. package/dist/markdown-core/syntax/elements/TableOfContents.d.ts +5 -0
  187. package/dist/markdown-core/syntax/elements/TableOfContents.js +44 -0
  188. package/dist/markdown-core/syntax/elements/TaskCheckbox.d.ts +7 -0
  189. package/dist/markdown-core/syntax/elements/TaskCheckbox.js +63 -0
  190. package/dist/markdown-core/syntax/elements/WikiEmbed.d.ts +7 -0
  191. package/dist/markdown-core/syntax/elements/WikiEmbed.js +68 -0
  192. package/dist/markdown-core/syntax/elements/WikiLink.d.ts +10 -0
  193. package/dist/markdown-core/syntax/elements/WikiLink.js +114 -0
  194. package/dist/markdown-core/syntax/elements/core-syntax-elements.d.ts +22 -0
  195. package/dist/markdown-core/syntax/elements/core-syntax-elements.js +70 -0
  196. package/dist/markdown-core/syntax/elements/find-in-document.d.ts +3 -0
  197. package/dist/markdown-core/syntax/elements/find-in-document.js +20 -0
  198. package/dist/markdown-core/syntax/elements/wiki-target.d.ts +5 -0
  199. package/dist/markdown-core/syntax/elements/wiki-target.js +8 -0
  200. package/dist/markdown-core/syntax/frontmatter.d.ts +26 -0
  201. package/dist/markdown-core/syntax/frontmatter.js +72 -0
  202. package/dist/markdown-core/syntax/gfm-cell-pipes.d.ts +11 -0
  203. package/dist/markdown-core/syntax/gfm-cell-pipes.js +4 -0
  204. package/dist/markdown-core/syntax/inline-syntax.d.ts +26 -0
  205. package/dist/markdown-core/syntax/inline-syntax.js +163 -0
  206. package/dist/markdown-core/syntax/linear-scan.d.ts +46 -0
  207. package/dist/markdown-core/syntax/linear-scan.js +129 -0
  208. package/dist/markdown-core/syntax/mdast-helpers.d.ts +48 -0
  209. package/dist/markdown-core/syntax/mdast-helpers.js +48 -0
  210. package/dist/markdown-core/syntax/mentions.d.ts +2 -0
  211. package/dist/markdown-core/syntax/mentions.js +42 -0
  212. package/dist/markdown-core/syntax/names.d.ts +6 -0
  213. package/dist/markdown-core/syntax/names.js +18 -0
  214. package/dist/markdown-core/syntax/prepare-syntax-source.d.ts +1 -0
  215. package/dist/markdown-core/syntax/prepare-syntax-source.js +78 -0
  216. package/dist/markdown-core/syntax/rehype-matrx-syntax.d.ts +9 -0
  217. package/dist/markdown-core/syntax/rehype-matrx-syntax.js +180 -0
  218. package/dist/markdown-core/syntax/remark-inline-only.d.ts +23 -0
  219. package/dist/markdown-core/syntax/remark-inline-only.js +25 -0
  220. package/dist/markdown-core/syntax/remark-matrx-syntax.d.ts +7 -0
  221. package/dist/markdown-core/syntax/remark-matrx-syntax.js +351 -0
  222. package/dist/markdown-core/syntax/remark-table-code-pipes.d.ts +7 -0
  223. package/dist/markdown-core/syntax/remark-table-code-pipes.js +23 -0
  224. package/dist/markdown-core/syntax/stream-heal-syntax.d.ts +2 -0
  225. package/dist/markdown-core/syntax/stream-heal-syntax.js +108 -0
  226. package/dist/markdown-core/syntax/task-source.d.ts +10 -0
  227. package/dist/markdown-core/syntax/task-source.js +34 -0
  228. package/dist/markdown-core/syntax/useDocumentProperties.d.ts +3 -0
  229. package/dist/markdown-core/syntax/useDocumentProperties.js +8 -0
  230. package/dist/math-vendor-LICENSE-NOTICE.md +18 -0
  231. package/dist/styles.css +0 -0
  232. package/dist/utils/addressWithoutNavigating.d.ts +68 -0
  233. package/dist/utils/addressWithoutNavigating.js +60 -0
  234. package/dist/utils/client-lazy.d.ts +13 -0
  235. package/dist/utils/client-lazy.js +24 -0
  236. package/dist/utils/decision-options.d.ts +21 -0
  237. package/dist/utils/decision-options.js +32 -0
  238. package/dist/utils/gfm-lexer.d.ts +5 -0
  239. package/dist/utils/gfm-lexer.js +10 -0
  240. package/dist/utils/json.d.ts +63 -0
  241. package/dist/utils/json.js +22 -0
  242. package/dist/utils/plain-title.d.ts +25 -0
  243. package/dist/utils/plain-title.js +51 -0
  244. package/dist/utils/table-source.d.ts +62 -0
  245. package/dist/utils/table-source.js +191 -0
  246. package/dist/utils/youtube.d.ts +52 -0
  247. package/dist/utils/youtube.js +137 -0
  248. package/package.json +132 -5
@@ -0,0 +1,33 @@
1
+ /**
2
+ * THE MATRIX BINDING of `@ai-matrx/content-ir-react`'s route environment.
3
+ *
4
+ * The render DECISIONS live in the package; the registries, the resolution
5
+ * platform, and the error sink are ours. This module is the one place those
6
+ * two halves meet, and it is deliberately React-free so reducers, stream
7
+ * accumulators, and tests can import it.
8
+ */
9
+ import type { KindRouteEnv } from "@ai-matrx/content-ir-react";
10
+ /**
11
+ * `web` is not a placeholder: `content_ir.kind_component.platform` already
12
+ * models react-native and friends, and a host that lies here renders the wrong
13
+ * component everywhere. This app is the web one.
14
+ */
15
+ export declare const MATRX_CONTENT_IR_PLATFORM: "web";
16
+ export declare const matrxKindRouteEnv: KindRouteEnv;
17
+ /**
18
+ * Block types THIS app owns and the route must never re-type.
19
+ *
20
+ * An `artifact` block has an identity, a version, and a Canvas to open in, and
21
+ * since 2026-08-18 it carries `metadata.__ir` so SELECTORS can read the
22
+ * envelope (`selectKindEnvelope` — the live flashcard preview and every other
23
+ * wrapped-payload surface). That envelope is DATA there, not a route: routing
24
+ * it to the bare kind component would strip the artifact chrome and lose the
25
+ * door to the Canvas.
26
+ *
27
+ * A `matrx` block is a Kind Directive — its reserved-namespace slug is BY
28
+ * DESIGN never a kind_definition row, so any resolution the route could find
29
+ * for it would be wrong, and re-typing it away from MatrxEnvelopeBlock
30
+ * re-opens the raw-JSON break the Kind Directives merge closed (adversarial
31
+ * finding A-8: today the block survives only because the lookup misses).
32
+ */
33
+ export declare const MATRX_OWNED_BLOCK_TYPES: readonly ["artifact", "matrx"];
@@ -0,0 +1,16 @@
1
+ import { captureError } from "../../host/diagnostics.js";
2
+ import { kindRegistry } from "../../host/kind-registry.js";
3
+ import { componentRegistry } from "../../host/component-registry.js";
4
+ const MATRX_CONTENT_IR_PLATFORM = "web";
5
+ const matrxKindRouteEnv = {
6
+ kinds: kindRegistry,
7
+ components: componentRegistry,
8
+ reportError: (report) => captureError(report),
9
+ platform: MATRX_CONTENT_IR_PLATFORM
10
+ };
11
+ const MATRX_OWNED_BLOCK_TYPES = ["artifact", "matrx"];
12
+ export {
13
+ MATRX_CONTENT_IR_PLATFORM,
14
+ MATRX_OWNED_BLOCK_TYPES,
15
+ matrxKindRouteEnv
16
+ };
@@ -0,0 +1,14 @@
1
+ import React from "react";
2
+ import type { FoundKindMarker } from "./kind-problems.js";
3
+ export declare function KindEscapedNotice({ markers, rendered, }: {
4
+ markers: FoundKindMarker[];
5
+ /**
6
+ * The host already drew the value as its kind (the JSON block's settled
7
+ * kind route, Arman 2026-09-30). A REGISTERED slug is still reported — it
8
+ * escaped the promotion path — but the line saying it is "not rendering as
9
+ * its component" would now be false, so nothing is shown. An UNREGISTERED
10
+ * slug keeps its line.
11
+ */
12
+ rendered?: boolean;
13
+ }): React.JSX.Element | null;
14
+ export default KindEscapedNotice;
@@ -0,0 +1,72 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { humanizeIdentifier } from "@ai-matrx/kit/text-case";
4
+ import { useEffect } from "react";
5
+ import { TriangleAlert } from "lucide-react";
6
+ import { isTableKind } from "@ai-matrx/records";
7
+ import { kindRegistry } from "../../host/kind-registry.js";
8
+ import { useEnsureKindRenderable } from "./ensure-kind-renderable.js";
9
+ import { useContentIrKindVersion } from "./use-registry-repaint.js";
10
+ import { readAtVersionForKey } from "./registry-versioned.js";
11
+ import { reportKindComponentIncident } from "../../host/kind-incident.js";
12
+ import { captureError } from "../../host/diagnostics.js";
13
+ const screamed = /* @__PURE__ */ new Set();
14
+ const registeredCache = /* @__PURE__ */ new Map();
15
+ function KindEscapedNotice({
16
+ markers,
17
+ rendered = false
18
+ }) {
19
+ const first = markers[0] ?? null;
20
+ const slug = first?.slug ?? null;
21
+ useEnsureKindRenderable(slug);
22
+ const kindVersion = useContentIrKindVersion(slug);
23
+ const registered = readAtVersionForKey(
24
+ registeredCache,
25
+ slug ?? "",
26
+ kindVersion,
27
+ () => Boolean(slug && kindRegistry.isRenderableKind(slug))
28
+ );
29
+ const tableKind = isTableKind(slug);
30
+ useEffect(() => {
31
+ if (!slug || !registered || tableKind) return;
32
+ const firstPath = first?.path;
33
+ const key = `${slug}:${firstPath === void 0 ? "" : firstPath}`;
34
+ if (screamed.has(key)) return;
35
+ screamed.add(key);
36
+ captureError({
37
+ source: "content-ir",
38
+ relation: slug,
39
+ message: `Registered kind "${slug}" rendered as a raw JSON code block \u2014 it escaped the promotion path (path: ${first?.path || "root"}).`,
40
+ hint: "The accumulator/splitter should have promoted this region (or embedded-kind recovery should have caught it). Find which arrival path delivered it.",
41
+ recoverable: true
42
+ });
43
+ reportKindComponentIncident({
44
+ kind: slug,
45
+ errorType: "kind_escaped_render",
46
+ message: `Registered kind "${slug}" rendered as a raw JSON code block (escaped the promotion path at ${first?.path || "root"}).`
47
+ });
48
+ }, [slug, registered, tableKind, first?.path]);
49
+ if (!first) return null;
50
+ if (rendered && registered) return null;
51
+ return /* @__PURE__ */ jsxs("div", { className: "mb-1 flex items-start gap-1.5 text-xs text-amber-700 dark:text-amber-400", children: [
52
+ /* @__PURE__ */ jsx(TriangleAlert, { className: "mt-0.5 h-3.5 w-3.5 shrink-0" }),
53
+ /* @__PURE__ */ jsxs("span", { children: [
54
+ registered ? /* @__PURE__ */ jsxs(Fragment, { children: [
55
+ "This JSON contains a ",
56
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: humanizeIdentifier(first.slug) }),
57
+ " ",
58
+ "Shape instance that is not rendering as its component \u2014 this is a pipeline defect and has been reported."
59
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
60
+ "This JSON declares a Shape (",
61
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: humanizeIdentifier(first.slug) }),
62
+ ") that isn't registered on this platform \u2014 check the name, or create the Shape to render it properly."
63
+ ] }),
64
+ markers.length > 1 ? ` (+${markers.length - 1} more)` : null
65
+ ] })
66
+ ] });
67
+ }
68
+ var KindEscapedNotice_default = KindEscapedNotice;
69
+ export {
70
+ KindEscapedNotice,
71
+ KindEscapedNotice_default as default
72
+ };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * The Matrix binding of the provisional-render safety net and the "still
3
+ * arriving" affordance (streaming partial kinds).
4
+ *
5
+ * Both live in `@ai-matrx/content-ir-react`: the boundary catches a component
6
+ * that throws on a provisional value, SCREAMS to the Error Inspector, drops the
7
+ * kind back to withhold for the session, and falls back to that kind's loading
8
+ * skeleton; the frame rides a `ShimmerText` chip on the block's top edge with
9
+ * no layout cost. Read the semantics there.
10
+ */
11
+ import type { ReactNode } from "react";
12
+ export declare function ProvisionalKindBoundary(props: {
13
+ kind: string;
14
+ fallback: ReactNode;
15
+ children: ReactNode;
16
+ }): import("react").JSX.Element;
17
+ export declare function ProvisionalKindFrame({ children }: {
18
+ children: ReactNode;
19
+ }): import("react").JSX.Element;
@@ -0,0 +1,17 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import {
4
+ ProvisionalKindBoundary as SharedProvisionalKindBoundary,
5
+ ProvisionalKindFrame as SharedProvisionalKindFrame
6
+ } from "@ai-matrx/content-ir-react";
7
+ import { ContentIrHostBoundary } from "../../host/ContentIrHostBoundary.js";
8
+ function ProvisionalKindBoundary(props) {
9
+ return /* @__PURE__ */ jsx(ContentIrHostBoundary, { children: /* @__PURE__ */ jsx(SharedProvisionalKindBoundary, { ...props }) });
10
+ }
11
+ function ProvisionalKindFrame({ children }) {
12
+ return /* @__PURE__ */ jsx(ContentIrHostBoundary, { children: /* @__PURE__ */ jsx(SharedProvisionalKindFrame, { children }) });
13
+ }
14
+ export {
15
+ ProvisionalKindBoundary,
16
+ ProvisionalKindFrame
17
+ };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Fire-and-forget: make sure this kind's schema and web output component are
3
+ * fetched (or known-missing). Safe to call redundantly — every layer dedupes.
4
+ *
5
+ * DD-215: the demand is UNCONDITIONAL for the component. See the comment in
6
+ * the body — a resolution that exists is not the same as a resolution that is
7
+ * settled, and the difference is which component a reader sees.
8
+ */
9
+ export declare function ensureKindRenderable(kind: string): void;
10
+ /**
11
+ * Hook form for render paths: request on mount and whenever the kind
12
+ * changes. Pass null for blocks with no envelope kind (nothing to fetch).
13
+ */
14
+ export declare function useEnsureKindRenderable(kind: string | null): void;
@@ -0,0 +1,45 @@
1
+ "use client";
2
+ import { useEffect } from "react";
3
+ import { kindRegistry } from "../../host/kind-registry.js";
4
+ import { componentRegistry } from "../../host/component-registry.js";
5
+ import { MATRX_CONTENT_IR_PLATFORM } from "../host/route-env.js";
6
+ function ensureKindRenderable(kind) {
7
+ if (!kindRegistry.getSchema(kind)) {
8
+ kindRegistry.requestSchema(kind);
9
+ }
10
+ componentRegistry.requestComponent(kind, MATRX_CONTENT_IR_PLATFORM, "output");
11
+ announceWrongComponent(kind);
12
+ }
13
+ function announceWrongComponent(kind) {
14
+ const resolution = componentRegistry.resolve(
15
+ kind,
16
+ MATRX_CONTENT_IR_PLATFORM,
17
+ "output"
18
+ );
19
+ const sourcelessDbRow = resolution?.resolvedBy === "db" && resolution.source === "db" && resolution.isActive && !resolution.hasComponentSource;
20
+ if (!sourcelessDbRow && !componentRegistry.wasRefused(kind)) return;
21
+ void (async () => {
22
+ try {
23
+ const { reportKindComponentIncident } = await import("../../host/kind-incident.js");
24
+ reportKindComponentIncident({
25
+ kind,
26
+ errorType: "component_read_refused",
27
+ platform: MATRX_CONTENT_IR_PLATFORM,
28
+ role: "output",
29
+ componentKey: resolution?.componentKey ?? null,
30
+ componentUpdatedAt: resolution?.updatedAt ?? null,
31
+ message: sourcelessDbRow ? `"${kind}" is bound to the active component "${resolution?.componentKey}" (source='db'), but the resolver holds no body for it, so the route refused it and the reader was shown the platform's bundled component instead. Nothing will fetch the body again on its own.` : `The reader was shown the platform's bundled component for "${kind}" because this organization's component row could not be READ \u2014 the request carried no session and the door refused it.`
32
+ });
33
+ } catch {
34
+ }
35
+ })();
36
+ }
37
+ function useEnsureKindRenderable(kind) {
38
+ useEffect(() => {
39
+ if (kind) ensureKindRenderable(kind);
40
+ }, [kind]);
41
+ }
42
+ export {
43
+ ensureKindRenderable,
44
+ useEnsureKindRenderable
45
+ };
@@ -0,0 +1,62 @@
1
+ /**
2
+ * The kind-problems reader — the ONE place the parser's recorded evidence of a
3
+ * broken / degraded / unroutable kind instance is flattened for human display.
4
+ *
5
+ * WHY THIS EXISTS (Arman, 2026-08-29): the parser has always recorded exactly
6
+ * what went wrong with a kind region — `residue.notices` carries `parse_error`,
7
+ * `raw_fallback` (schema violations, duplicate keys, missing `__kind`),
8
+ * `degrade_data_rescued`; `root.status`/`kindState` carry degradation; the
9
+ * route marker carries why no component rendered — and NOTHING in the UI ever
10
+ * read any of it. A shape that failed rendered as an anonymous key/value dump,
11
+ * indistinguishable from data that was never a shape at all. That silence is
12
+ * what made kind rendering feel random. This module turns that evidence into
13
+ * `KindProblem[]`, consumed by the Errors tab in `StructuredValueTabs` — so a
14
+ * broken kind is ACKNOWLEDGED as a kind, with its exact problems, everywhere
15
+ * the fallback renders.
16
+ *
17
+ * Pure over envelope data (`CanonicalBlockIR` is plain JSON from
18
+ * `@ai-matrx/content-ir`). Host diagnostics are host property (content-ir-twin
19
+ * boundary) — this makes no routing decision and renders nothing.
20
+ */
21
+ import type { CanonicalBlockIR } from "@ai-matrx/content-ir";
22
+ import type { IrRouteMarker } from "./kind-route.js";
23
+ export type KindProblemSeverity = "error" | "warning" | "info";
24
+ export interface KindProblem {
25
+ /** Stable machine code (`parse_error`, `raw_fallback`, `component_inactive`, …). */
26
+ code: string;
27
+ /** Human sentence — shown verbatim in the Errors tab. */
28
+ message: string;
29
+ /** Region-relative path of the node the problem is about ("" = root). */
30
+ path?: string;
31
+ severity: KindProblemSeverity;
32
+ }
33
+ /**
34
+ * Flatten everything the envelope + route marker recorded about why this kind
35
+ * instance is not rendering as its component. Empty array = a clean value that
36
+ * simply has no component yet (the fix-it bar's territory, not an error).
37
+ */
38
+ export declare function collectKindProblems(envelope: CanonicalBlockIR | null | undefined, marker?: IrRouteMarker | null): KindProblem[];
39
+ /** True when any collected problem is a real error (drives the tab's tint). */
40
+ export declare function hasKindErrors(problems: KindProblem[]): boolean;
41
+ export interface FoundKindMarker {
42
+ slug: string;
43
+ /** Dotted path inside the scanned value ("" = the value itself). */
44
+ path: string;
45
+ }
46
+ /**
47
+ * Deep-scan a parsed JSON value for `__kind` markers — the tripwire for a kind
48
+ * instance that escaped the promotion path and is being shown as anonymous
49
+ * JSON. Bounded (node + depth caps) so a pathological payload cannot stall a
50
+ * render; caps mean "found some", never an exhaustive census.
51
+ */
52
+ export declare function findKindMarkers(value: unknown, limit?: number): FoundKindMarker[];
53
+ /**
54
+ * Keep the raw-JSON tripwire about the boundary it can actually prove.
55
+ *
56
+ * A marker is escaped only when the canonical envelope did not already claim
57
+ * that exact path/kind. A schema-invalid kind deliberately remains on the raw
58
+ * JSON fallback, but it was still promoted; reporting it as a promotion crack
59
+ * sends repair patrols to the wrong producer and hides the real validation
60
+ * evidence carried by the envelope.
61
+ */
62
+ export declare function findEscapedKindMarkers(value: unknown, envelope: CanonicalBlockIR | null | undefined, limit?: number): FoundKindMarker[];
@@ -0,0 +1,134 @@
1
+ const ERROR_NOTICE_CODES = /* @__PURE__ */ new Set(["parse_error", "raw_fallback"]);
2
+ function noticeSeverity(code) {
3
+ if (ERROR_NOTICE_CODES.has(code)) return "error";
4
+ if (code === "partial_unvalidated") return "info";
5
+ return "warning";
6
+ }
7
+ function residueProblems(residue, path) {
8
+ if (!residue) return [];
9
+ const problems = [];
10
+ for (const notice of residue.notices ?? []) {
11
+ problems.push({
12
+ code: notice.code,
13
+ message: notice.message,
14
+ ...path ? { path } : {},
15
+ severity: noticeSeverity(notice.code)
16
+ });
17
+ }
18
+ const extraKeys = residue.extra ? Object.keys(residue.extra) : [];
19
+ if (extraKeys.length > 0) {
20
+ problems.push({
21
+ code: "unknown_keys",
22
+ message: `Keys not in this shape's schema (kept, not lost): ${extraKeys.join(", ")}`,
23
+ ...path ? { path } : {},
24
+ severity: "warning"
25
+ });
26
+ }
27
+ return problems;
28
+ }
29
+ function collectKindProblems(envelope, marker) {
30
+ const problems = [];
31
+ if (envelope) {
32
+ const root = envelope.root;
33
+ if (root.status === "error") {
34
+ problems.push({
35
+ code: "region_error",
36
+ message: "This region hit a fatal parse error \u2014 the payload below is what arrived before it broke.",
37
+ severity: "error"
38
+ });
39
+ }
40
+ if (root.kindState === "raw" && root.kind) {
41
+ problems.push({
42
+ code: "degraded_raw",
43
+ message: `This is a "${root.kind}" shape instance, but it could not be validated against the shape's schema, so it degraded to plain data.`,
44
+ severity: "error"
45
+ });
46
+ }
47
+ if (root.kindState === "pending_schema") {
48
+ problems.push({
49
+ code: "schema_unavailable",
50
+ message: `The schema for "${root.kind}" had not loaded when this region finished.`,
51
+ severity: "warning"
52
+ });
53
+ }
54
+ if (root.kindState === "unverified" && root.kind) {
55
+ problems.push({
56
+ code: "schema_unavailable",
57
+ message: `No field schema is registered for "${root.kind}", so this payload could not be checked. The data is shown as it arrived \u2014 this is a gap in the shape, not in the content.`,
58
+ severity: "warning"
59
+ });
60
+ }
61
+ problems.push(...residueProblems(root.residue, ""));
62
+ if (envelope.nodeIndex) {
63
+ for (const [pathKey, node] of Object.entries(envelope.nodeIndex)) {
64
+ if (node.kindState === "raw" && node.kind) {
65
+ problems.push({
66
+ code: "nested_degraded_raw",
67
+ message: `Nested "${node.kind}" at ${pathKey} failed validation and degraded to plain data.`,
68
+ path: pathKey,
69
+ severity: "error"
70
+ });
71
+ }
72
+ problems.push(...residueProblems(node.residue, pathKey));
73
+ }
74
+ }
75
+ }
76
+ if (marker?.reason === "inactive") {
77
+ problems.push({
78
+ code: "component_inactive",
79
+ message: "A component is registered for this shape but is held inactive \u2014 activate it to render this properly.",
80
+ severity: "warning"
81
+ });
82
+ } else if (marker?.reason === "generic-row") {
83
+ problems.push({
84
+ code: "generic_component_row",
85
+ message: "This shape's registered component IS the generic viewer \u2014 a real component still needs to be authored.",
86
+ severity: "warning"
87
+ });
88
+ }
89
+ return problems;
90
+ }
91
+ function hasKindErrors(problems) {
92
+ return problems.some((p) => p.severity === "error");
93
+ }
94
+ const KIND_KEY = "__kind";
95
+ const SCAN_NODE_CAP = 2e3;
96
+ const SCAN_DEPTH_CAP = 8;
97
+ function findKindMarkers(value, limit = 5) {
98
+ const found = [];
99
+ let visited = 0;
100
+ const walk = (node, path, depth) => {
101
+ if (found.length >= limit) return;
102
+ if (visited++ > SCAN_NODE_CAP || depth > SCAN_DEPTH_CAP) return;
103
+ if (Array.isArray(node)) {
104
+ node.forEach(
105
+ (item, i) => walk(item, path ? `${path}.${i}` : String(i), depth + 1)
106
+ );
107
+ return;
108
+ }
109
+ if (typeof node !== "object" || node === null) return;
110
+ const record = node;
111
+ const slug = record[KIND_KEY];
112
+ if (typeof slug === "string" && slug.trim()) {
113
+ found.push({ slug: slug.trim(), path });
114
+ }
115
+ for (const [key, child] of Object.entries(record)) {
116
+ if (key === KIND_KEY) continue;
117
+ walk(child, path ? `${path}.${key}` : key, depth + 1);
118
+ }
119
+ };
120
+ walk(value, "", 0);
121
+ return found;
122
+ }
123
+ function findEscapedKindMarkers(value, envelope, limit = 5) {
124
+ return findKindMarkers(value, limit).filter((marker) => {
125
+ const claimedNode = marker.path ? envelope?.nodeIndex?.[marker.path] : envelope?.root;
126
+ return claimedNode?.kind !== marker.slug;
127
+ });
128
+ }
129
+ export {
130
+ collectKindProblems,
131
+ findEscapedKindMarkers,
132
+ findKindMarkers,
133
+ hasKindErrors
134
+ };
@@ -0,0 +1,23 @@
1
+ /**
2
+ * The Matrix binding of THE KIND ROUTE.
3
+ *
4
+ * The route itself — envelope → registered kind → the right component, with the
5
+ * db-override flip, the compiled-bridge path, the resolver path, and the R6
6
+ * generic fallback — lives in `@ai-matrx/content-ir-react`
7
+ * (`route/kind-route.ts`), and since 0.8.0 the per-host partial application
8
+ * does too (`createKindRouteBinding`). Read the semantics there.
9
+ *
10
+ * This module only INJECTS our env + owned block types (host/route-env.ts) and
11
+ * keeps the historical import path stable so ~60 call sites and every doc
12
+ * pointer still read the same.
13
+ */
14
+ export { DB_KIND_COMPONENT_KEY, GENERIC_STRUCTURED_COMPONENT_KEY, IR_ROUTE_KEY, readIrRouteMarker, type GenericFallbackReason, type IrRoutableBlock, type IrRouteMarker, } from "@ai-matrx/content-ir-react";
15
+ /** Route one block through the Matrix registries. */
16
+ export declare const applyIrKindRoute: <T extends import("@ai-matrx/content-ir-react").IrRoutableBlock>(block: T) => T;
17
+ /**
18
+ * Rehydration route for STRUCTURED persisted artifacts (Track 2B): given a
19
+ * stored zero-loss value object, derive the registered kind's legacy
20
+ * `serverData` with no re-parse. Null for non-objects, unregistered kinds, or
21
+ * kinds without a legacy bridge.
22
+ */
23
+ export declare const kindServerDataFromStoredValue: (value: unknown) => Record<string, unknown> | null;
@@ -0,0 +1,24 @@
1
+ import { createKindRouteBinding } from "@ai-matrx/content-ir-react";
2
+ import {
3
+ MATRX_OWNED_BLOCK_TYPES,
4
+ matrxKindRouteEnv
5
+ } from "../host/route-env.js";
6
+ import {
7
+ DB_KIND_COMPONENT_KEY,
8
+ GENERIC_STRUCTURED_COMPONENT_KEY,
9
+ IR_ROUTE_KEY,
10
+ readIrRouteMarker
11
+ } from "@ai-matrx/content-ir-react";
12
+ const binding = createKindRouteBinding(matrxKindRouteEnv, {
13
+ ownedTypes: MATRX_OWNED_BLOCK_TYPES
14
+ });
15
+ const applyIrKindRoute = binding.applyIrKindRoute;
16
+ const kindServerDataFromStoredValue = binding.kindServerDataFromStoredValue;
17
+ export {
18
+ DB_KIND_COMPONENT_KEY,
19
+ GENERIC_STRUCTURED_COMPONENT_KEY,
20
+ IR_ROUTE_KEY,
21
+ applyIrKindRoute,
22
+ kindServerDataFromStoredValue,
23
+ readIrRouteMarker
24
+ };
@@ -0,0 +1,58 @@
1
+ /**
2
+ * DERIVED loading slugs — the smart floor under the declared one.
3
+ *
4
+ * A kind that never declared `metadata.loading_component` used to fall all
5
+ * the way through to the `generic` skeleton, which tells the reader nothing
6
+ * about what is coming. On 2026-08-25 that was 354 of the 357 renderable
7
+ * ACTIVE kinds: a backlog nobody can close one row at a time.
8
+ *
9
+ * So the fallback stops being dumb. A kind's own SCHEMA already says what
10
+ * shape it is — a long prose body is a document, a list of structured items
11
+ * is a list, image fields are media — and the loader whose silhouette
12
+ * matches the finished component is derivable from exactly that. Every kind
13
+ * therefore gets a shape-appropriate loader with zero authoring, zero DB
14
+ * writes, and zero deploys.
15
+ *
16
+ * PRECEDENCE — declaration always wins:
17
+ * metadata.loading_component → this derivation → `generic`
18
+ * so setting a slug is still the way to override. The order is executed in
19
+ * ONE place, `resolve-loading-slug.ts` — never re-inline it as a `??` chain,
20
+ * because an INVALID declaration has to fall through to this derivation
21
+ * rather than short-circuit to `generic`.
22
+ *
23
+ * The shape doctor agrees with that precedence (2026-08-25): a kind with a
24
+ * DERIVED loader reads `ok` and raises no finding, because a shape-appropriate
25
+ * loader is a real loader however it was chosen. The `no-loading-component`
26
+ * yellow now fires only when derivation finds nothing distinctive either — the
27
+ * kinds that genuinely do stream behind the generic skeleton (428 yellows
28
+ * became 19).
29
+ *
30
+ * The rules read the schema, never the instance value: derivation must be
31
+ * stable for a kind, identical on every render, and available before a
32
+ * single byte of the value has arrived.
33
+ */
34
+ import type { KindSchema } from "@ai-matrx/content-ir";
35
+ import type { KindLoadingSlug } from "./kind-loading-slugs.js";
36
+ /**
37
+ * The best-matching library slug for this schema, or null when nothing in the
38
+ * shape is distinctive enough to beat the generic skeleton.
39
+ *
40
+ * Ordered most-specific first. The order encodes a judgment made with Arman
41
+ * on 2026-08-24 while looking at real shapes: a kind with BOTH a prose body
42
+ * and structured lists (a newsjacking article: `article_body` + quotes +
43
+ * sources + faqs) reads as a DOCUMENT, because the body is what fills the
44
+ * screen — the lists are supporting material.
45
+ */
46
+ export declare function inferLoadingSlug(schema: KindSchema | undefined | null): KindLoadingSlug | null;
47
+ /**
48
+ * The SAME derivation over a raw JSON Schema.
49
+ *
50
+ * Most kinds have no parser `KindSchema` at all: Python owns them and stores
51
+ * only `emitted_json_schema` (344 of 392 undeclared renderable kinds on
52
+ * 2026-08-25, measured — `kind_definition.data` is NULL for every one). A
53
+ * derivation that reads only `KindSchema` is therefore blind to the large
54
+ * majority of the backlog it exists to serve, which is why this second door
55
+ * exists rather than a second set of rules: both doors normalize to the same
56
+ * `{name → type}` census and run the identical precedence above.
57
+ */
58
+ export declare function inferLoadingSlugFromJsonSchema(jsonSchema: unknown): KindLoadingSlug | null;
@@ -0,0 +1,100 @@
1
+ const MEDIA_NAME = /(^|_)(image|images|photo|photos|thumbnail|cover_image|video|videos|audio|media)(_|$)/i;
2
+ const GALLERY_NAME = /(^|_)(gallery|images|photos|screenshots|slides_images)(_|$)/i;
3
+ const BODY_NAME = /(^|_)(body|article_body|content|markdown|text|prose|transcript|summary_long|full_text|report|essay|description_long)(_|$)/i;
4
+ const CODE_NAME = /(^|_)(code|snippet|source|diff|patch|sql|script)(_|$)/i;
5
+ const DOC_ARRAY_NAME = /(^|_)(sections|chapters|paragraphs|pages)(_|$)/i;
6
+ const CHART_NAME = /(^|_)(series|datapoints|data_points|metrics|chart|trend|timeseries)(_|$)/i;
7
+ const TIMELINE_NAME = /(^|_)(timeline|events|milestones|history|phases|periods)(_|$)/i;
8
+ const STEP_NAME = /(^|_)(steps|stages|progress|checklist|tasks)(_|$)/i;
9
+ const STAT_NAME = /(^|_)(stats|statistics|totals|counts|kpis|summary_stats)(_|$)/i;
10
+ function isStructuredArray(field) {
11
+ return field.type === "array" || field.type === "json[]";
12
+ }
13
+ function isProseField(name, field) {
14
+ return field.type === "string" && BODY_NAME.test(name);
15
+ }
16
+ function inferLoadingSlug(schema) {
17
+ if (!schema) return null;
18
+ if (schema.root) {
19
+ if (schema.root.type === "string") return "document";
20
+ if (isStructuredArray(schema.root)) return "list";
21
+ return null;
22
+ }
23
+ const entries = Object.entries(schema.fields ?? {}).filter(
24
+ ([name]) => name !== "__kind"
25
+ );
26
+ if (entries.length === 0) return null;
27
+ let hasProse = false;
28
+ let hasDocArray = false;
29
+ let structuredArrays = 0;
30
+ let hasMedia = false;
31
+ let hasGallery = false;
32
+ let hasCode = false;
33
+ let hasChart = false;
34
+ let hasTimeline = false;
35
+ let hasSteps = false;
36
+ let hasStats = false;
37
+ for (const [name, field] of entries) {
38
+ if (!field || typeof field !== "object") continue;
39
+ if (isProseField(name, field)) hasProse = true;
40
+ if (isStructuredArray(field)) {
41
+ structuredArrays += 1;
42
+ if (DOC_ARRAY_NAME.test(name)) hasDocArray = true;
43
+ if (GALLERY_NAME.test(name)) hasGallery = true;
44
+ if (CHART_NAME.test(name)) hasChart = true;
45
+ if (TIMELINE_NAME.test(name)) hasTimeline = true;
46
+ if (STEP_NAME.test(name)) hasSteps = true;
47
+ if (STAT_NAME.test(name)) hasStats = true;
48
+ }
49
+ if (MEDIA_NAME.test(name) && !isStructuredArray(field)) hasMedia = true;
50
+ if (CODE_NAME.test(name) && field.type === "string") hasCode = true;
51
+ }
52
+ if (hasGallery) return "gallery";
53
+ if (hasMedia) return "media";
54
+ if (hasProse || hasDocArray) return "document";
55
+ if (hasCode) return "code";
56
+ if (hasTimeline) return "timeline";
57
+ if (hasChart) return "chart";
58
+ if (hasSteps) return "progress";
59
+ if (hasStats) return "stat-grid";
60
+ if (structuredArrays > 0) return "list";
61
+ if (entries.length >= 2 && entries.length <= 12) return "card";
62
+ return null;
63
+ }
64
+ function inferLoadingSlugFromJsonSchema(jsonSchema) {
65
+ if (!jsonSchema || typeof jsonSchema !== "object" || Array.isArray(jsonSchema)) {
66
+ return null;
67
+ }
68
+ const root = jsonSchema;
69
+ const rootType = root.type;
70
+ if (rootType === "string") return "document";
71
+ if (rootType === "array") return "list";
72
+ const properties = root.properties;
73
+ if (!properties || typeof properties !== "object" || Array.isArray(properties)) {
74
+ return null;
75
+ }
76
+ const fields = {};
77
+ for (const [name, raw] of Object.entries(properties)) {
78
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) continue;
79
+ const prop = raw;
80
+ const type = prop.type;
81
+ if (type === "array") {
82
+ const items = prop.items;
83
+ const itemType = items && typeof items === "object" && !Array.isArray(items) ? items.type : void 0;
84
+ const structured = itemType === "object" || itemType === void 0 || // $ref'd child kind — structured by definition
85
+ items && typeof items === "object" && "$ref" in items;
86
+ fields[name] = { type: structured ? "array" : "string[]" };
87
+ continue;
88
+ }
89
+ if (type === "string") {
90
+ fields[name] = { type: "string" };
91
+ continue;
92
+ }
93
+ fields[name] = { type: typeof type === "string" ? type : "json" };
94
+ }
95
+ return inferLoadingSlug({ kind: "", fields });
96
+ }
97
+ export {
98
+ inferLoadingSlug,
99
+ inferLoadingSlugFromJsonSchema
100
+ };